[
  {
    "path": ".gitignore",
    "content": "*.o\nMakefile\nMakefile.in\naclocal.m4\nautom4te.cache\nbuild-aux\nconfig.h\nconfig.h.in\nconfig.log\nconfig.status\nconfigure\n.deps\nMakefile.in\ncompress_gtf\ncuffcompare\ncuffdiff\ncufflinks\ncuffnorm\ncuffquant\ngffread\ngtf_to_sam\n*.a\nstamp-h1\n"
  },
  {
    "path": "AUTHORS",
    "content": "Cufflinks authors\nPrimary contact <cole@cs.umd.edu>\n\nCole Trapnell designed and wrote Cufflinks and Cuffdiff, with substantial technical input \nfrom Geo Pertea, Brian Williams, Ali Mortazavi, Jeltje van Baren, Steven Salzberg, Barbara Wold, \nand Lior Pachter. Geo Pertea wrote Cuffcompare.  Adam Roberts made substantial improvements to\nthe abundance estimation model used by Cufflinks and Cuffdiff.\n\n\"Tuxedo\" Websites:\n Cufflinks:\t\t\t http://cole-trapnell-lab.github.io/cufflinks/\n TopHat:\t\t\t http://tophat.cbcb.umd.edu\n Bowtie:             http://bowtie-bio.sf.net\n\nAs of version 1.0, Cufflinks depends on and includes LOCFIT, a regression package originally written \nby Catherine Loader and Jiayang Sun. Some modifications were made to LOCFIT.  Modified source\nfor LOCFIT lives in src/locfit.\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (C) 2003-2009 Cole Trapnell et al\n\n===========================================================================\nBoost Software License, Version 1.0\n===========================================================================\n\nPermission is hereby granted, free of charge, to any person or organization\nobtaining a copy of the software and accompanying documentation covered by\nthis license (the \"Software\") to use, reproduce, display, distribute,\nexecute, and transmit the Software, and to prepare derivative works of the\nSoftware, and to permit third-parties to whom the Software is furnished to\ndo so, all subject to the following:\n\nThe copyright notices in the Software and this entire statement, including\nthe above license grant, this restriction and the following disclaimer,\nmust be included in all copies of the Software, in whole or in part, and\nall derivative works of the Software, unless such copies or derivative\nworks are solely in the form of machine-executable object code generated by\na source language processor.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\nSHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\nFOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n\n\n"
  },
  {
    "path": "Makefile.am",
    "content": "\nALWAYS_BUILT = src\nSUBDIRS = $(ALWAYS_BUILT)\nDIST_SUBDIRS = $(ALWAYS_BUILT) \n\nEXTRA_DIST = LICENSE\n\n.PHONY: FORCE\n"
  },
  {
    "path": "README.md",
    "content": "\n# Cufflinks\n\nThe main *website* for cufflinks is [here](http://cole-trapnell-lab.github.io/cufflinks/)\n\n*NOTE*: If you're looking for old releases of Cufflinks, including source, you can find them [here](http://cole-trapnell-lab.github.io/cufflinks/install/).\n\nCufflinks assembles transcripts, estimates their abundances, and tests for differential expression and regulation in RNA-Seq samples. It accepts aligned RNA-Seq reads and assembles the alignments into a parsimonious set of transcripts. Cufflinks then estimates the relative abundances of these transcripts based on how many reads support each one, taking into account biases in library preparation protocols. \n\nCufflinks was originally developed as part of a collaborative effort between the [Laboratory for Mathematical and Computational Biology](http://bio.math.berkeley.edu/), led by Lior Pachter at UC Berkeley, Steven Salzberg's [computational genomics group](http://ccb.jhu.edu/people/salzberg/) at the Institute of Genetic Medicine at Johns Hopkins University, and [Barbara Wold's lab](http://woldlab.caltech.edu/) at Caltech. The project is now maintained by [Cole Trapnell's](http://cole-trapnell-lab.github.io/) lab at the University of Washington.\n\nCufflinks is provided under the OSI-approved [Boost License](http://en.wikipedia.org/wiki/Boost_Software_License)\n\n# News\n\n*To get the latest updates on the Cufflinks project and the rest of the \"Tuxedo tools\", please subscribe to our [**mailing list**](https://lists.sourceforge.net/lists/listinfo/bowtie-bio-announce)* \n\n# Install quick-start\n\n## Installing a pre-compiled binary release\n\nIn order to make it easy to install Cufflinks, we provide a few binary packages [here](http://cole-trapnell-lab.github.io/cufflinks/install/) to save users from the occasionally frustrating process of building Cufflinks, which requires that you install the Boost libraries. To use the binary packages, simply download the appropriate one for your machine, untar it, and make sure the cufflinks,cuffdiff and cuffcompare binaries are in a directory in your PATH environment variable.\n\n# Building Cufflinks from source\n\nIn order to build Cufflinks, you must have the [Boost C++ libraries](http://www.boost.org/) (version 1.47 or higher) installed on your system. See below for instructions on installing Boost.\n\n## Installing Boost\n\n1. Download Boost and the bjam build engine. **WARNING:** Due to a serious issue with Boost Serlialization library introduced in version 1.56, Cufflinks currently can only be built with Boost version 1.55 or lower.  The issue is expected to be fixed in the upcoming Boost v1.59.\n2. Unpack bjam and add it to your PATH.\n3. Unpack the Boost tarball and cd to the Boost source directory. This directory is called the BOOST_ROOT in some Boost installation instructions.\n4. Build Boost. Note that you can specify where to put Boost with the --prefix option. The default Boost installation directory is /usr/local. Take note of the boost installation directory, because you will need to tell the Cufflinks installer where to find Boost later on.\n\n- If you are on Mac OS X, type (all on one line): \n```bash\nbjam --prefix=<YOUR_BOOST_INSTALL_DIRECTORY> --toolset=darwin architecture=x86 address_model=32_64 link=static runtime-link=static --layout=versioned stage install\n```\n\n- If you are on a 32-bit Linux system, type (all on one line): \n```bash\nbjam --prefix=<YOUR_BOOST_INSTALL_DIRECTORY> --toolset=gcc architecture=x86 address_model=32 link=static runtime-link=static stage install\n```\n\n- If you are on a 64-bit Linux system, type (all on one line): \n```bash\nbjam --prefix=<YOUR_BOOST_INSTALL_DIRECTORY> --toolset=gcc architecture=x86 address_model=64 link=static runtime-link=static stage install\n```\n\n## Installing the SAM tools\n\n1. [Download the SAM tools](http://samtools.sourceforge.net/)\n2. Unpack the SAM tools tarball and cd to the SAM tools source directory.\n3. Build the SAM tools by typing make at the command line.\n4. Choose a directory into which you wish to copy the SAM tools binary, the included library <tt>libbam.a</tt>, and the library headers. A common choice is <tt>/usr/local/</tt>.\n5. Copy libbam.a to the lib/ directory in the folder you've chosen above (e.g. <tt>/usr/local/lib/</tt>)\n6. Create a directory called \"bam\" in the <tt>include/</tt> directory (e.g. <tt>/usr/local/include/bam</tt>)\n7. Copy the headers (files ending in <tt>.h</tt>) to the include/bam directory you've created above (e.g. <tt>/usr/local/include/</tt>bam)\n8. Copy the samtools binary to some directory in your <tt>PATH</tt>.\n\n## Installing the Eigen libraries\n\n1. [Download Eigen](http://eigen.tuxfamily.org/)\n2. Unpack the Eigen tarball and cd to the Eigen source directory.\n3. Copy the Eigen/ subdirectory someplace on your system where you keep header files (e.g. /usr/local/include)\n\n## Building Cufflinks\n\n### If you are starting from a source tarball downloaded from [here](http://cole-trapnell-lab.github.io/cufflinks/install/):\n\nUnpack the Cufflinks source tarball (in this example for version 2.2.1):\n```bash\ntar zxvf cufflinks-2.2.1.tar.gz\n```\nChange to the Cufflinks directory:\n```bash\ncd cufflinks-2.2.1\n```\n\n### If you want to clone the Cufflinks github repo:\n```bash\ngit clone https://github.com/cole-trapnell-lab/cufflinks.git\ncd cufflinks\nautoreconf --install\n```\nThe above will generate the configure script.\n\n### To configure Cufflinks prior to the build\n\nIf Boost is installed somewhere other than /usr/local, you will need to tell the installer where to find it using the --with-boost option. Specify where to install Cufflinks using the --prefix option.\n```bash\n./configure --prefix=/path/to/cufflinks/install --with-boost=/path/to/boost --with-eigen=/path/to/eigen\n```\n\nIf you see any errors during configuration, verify that you are using Boost version 1.47 or higher, and that the directory you specified via --with-boost contains the boost header files and libraries. See the Boost Getting started page for more details. If you copied the SAM tools binaries to someplace other than /usr/local/, you may need to supply the --with-bam configuration option.\nFinally, make and install Cufflinks.\n```bash\nmake\nmake install\n```\n\n## Testing the installation\n\n1. [Download](http://cufflinks.cbcb.umd.edu/downloads/test_data.sam) the test data\n2. In the directory where you placed the test file, type:\n\n```bash\ncufflinks ./test_data.sam\n```\n\nYou should see the following output:\n\n<pre>\n[bam_header_read] EOF marker is absent. The input is probably truncated.\n[bam_header_read] invalid BAM binary header (this is not a BAM file).\nFile ./test_data.sam doesn't appear to be a valid BAM file, trying SAM...\n[13:23:15] Inspecting reads and determining fragment length distribution.\n> Processed 1 loci.                            [*************************] 100%\nWarning: Using default Gaussian distribution due to insufficient paired-end reads in open ranges.  \nIt is recommended that correct paramaters (--frag-len-mean and --frag-len-std-dev) be provided.\n> Map Properties:\n>       Total Map Mass: 102.50\n>       Read Type: 75bp x 75bp\n>       Fragment Length Distribution: Truncated Gaussian (default)\n>                     Estimated Mean: 200\n>                  Estimated Std Dev: 80\n[13:23:15] Assembling transcripts and estimating abundances.\n> Processed 1 loci.                            [*************************] 100%\n</pre>\n\nVerify that the file transcripts.gtf is in the current directory and looks like this (your file will have GTF attributes, omitted here for clarity)\n\n<pre>\ntest_chromosome Cufflinks       exon    53      250     1000    +       . \ntest_chromosome Cufflinks       exon    351     400     1000    +       . \ntest_chromosome Cufflinks       exon    501     550     1000    +       .\n</pre>\t\n\n# Common uses of the Cufflinks package\n\nCufflinks includes a number of tools for analyzing RNA-Seq experiments. Some of these tools can be run on their own, while others are pieces of a larger workflow. The complexity of your workflow depends on what you want to achieve with your analysis. For a complete discussion of how Cufflinks can help you with your analysis, please [see our protocol paper](http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html). The paper includes a diagram (Figure 2) describing how the various parts of the Cufflinks package (and its companion tool TopHat) fit together. As of version 2.2.0, you can also run Cuffquant and Cuffnorm to make large scale analyses easier to handle. The figure below is an updated version of Figure 2 showing how the two utilities released after the protocol paper appeared fit into the workflow: \n\n<div style=\"text-align:center\">\n![Workflow]({{ site.url }}/images/tuxedo_workflow.png)\n</div>\n\nYou can use Cuffquant to pre-compute gene expression levels for each of your samples, which can save time if you have to re-run part of your analysis. Using Cuffquant also makes it easier to spread the load of computation for lots of samples across multiple computers. If you don't want to perform differential expression analysis, you can run Cuffnorm instead of Cuffdiff. Cuffnorm produces simple tables of expression values that you can look at in R (for example) to cluster samples and perform other follow up analysis.\t\n\n# Using pre-built annotation packages\n\nA number of steps in the Tuxedo package work better if you have pre-existing gene annotations. How you can use these annotations is detailed in our [protocol paper](http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html). Illumina has kindly provided a large number of annotation packages for commonly used model organisms and humans. You can find these packages [here]({{ site.url }}/igenome_table/index.html).\t\n\n# References\n\nCufflinks is an ongoing research project as well as a suite of tools. Here are the papers that describe the science behind the programs. If you use Cufflinks, please cite these papers in your work!\n\n**Transcript assembly and quantification by RNA-Seq reveals unannotated transcripts and isoform switching during cell differentiation**\nCole Trapnell, Brian Williams, Geo Pertea, Ali Mortazavi, Gordon Kwan, Jeltje van Baren, Steven Salzberg, Barbara Wold, Lior Pachter.\n*Nature Biotechnology*, 2010, doi:10.1038/nbt.1621\n*Note: This is the original Cufflinks paper. Please cite this paper if you use Cufflinks in your work.*\n\n**Improving RNA-Seq expression estimates by correcting for fragment bias**\nAdam Roberts, Cole Trapnell, Julie Donaghey, John L. Rinn, Lior Pachter.\n*Genome Biology*, 2011, doi:10.1186/gb-2011-12-3-r22\n*Note: This paper describes improvements made to Cufflinks to handle bias in RNA-Seq read coverage. Please cite this paper if you use Cufflinks with the <tt>-b</tt> option in your work.*\n\n**Identification of novel transcripts in annotated genomes using RNA-Seq**\nAdam Roberts, Harold Pimentel, Cole Trapnell, Lior Pachter.\n*Bioinformatics*, 2011, doi:10.1093/bioinformatics/btr355\n*Note: This paper describes the RABT assembly algorithm. Please cite this paper if you use Cufflinks in RABT mode in your work.*\n\n**Differential analysis of gene regulation at transcript resolution with RNA-seq**\nCole Trapnell, David Hendrickson, Martin Sauvageau, Loyal Goff, John L. Rinn, Lior Pachter\n*Nature Biotechnology*, 2012, doi:10.1038/nbt.2450\n*Note: This paper describes Cuffdiff 2. Please cite this paper if you use Cuffdiff in your work.*\n\nCufflinks builds on many ideas, including some\nproposed in the following papers:\n\n1. Ali Mortazavi, Brian A Williams, Kenneth McCue, Lorian Schaeffer and Barbara \nWold, \"Mapping and quantifying mammalian transcriptomes by RNA-Seq\",Nature \nMethods, volume 5, 621 - 628 (2008)\n2. Hui Jiang and Wing Hung Wong, \"Statistical Inferences for isoform expression\", \nBioinformatics, 2009 25(8):1026-1032=\n3.Nicholas Eriksson, Lior Pachter, Yumi Mitsuya, Soo-Yon Rhee, Chunlin Wang, \nBaback Gharizadeh, Mostafa Ronaghi, Robert W. Shafer, Niko Beerenwinkel, \"Viral \npopulation estimation using pyrosequencing\", PLoS Computational Biology, \n4(5):e1000074\n"
  },
  {
    "path": "autogen.sh",
    "content": "#!/bin/sh\n\nsubmodule_init ( ) {\n    local SUBMODULES=$(git submodule | awk '{print $2}')\n    for submodule in $SUBMODULES; do\n\techo \"Initializing submodule $submodule\"\n\tgit submodule init $submodule\n\tgit submodule update $submodule\n\tcd $submodule\n\tif test -f version.sh\n\tthen\n\t    ./version.sh\n\tfi\n\tsubmodule_init\n\tcd ..\n    done\n}\n\n./version.sh\nsubmodule_init\nautoreconf --install\n"
  },
  {
    "path": "ax_bam.m4",
    "content": "# SYNOPSIS\n#\n#   AX_BAM\n#\n# DESCRIPTION\n#\n#   Test for the BAM libraries (htslib or bamlib)\n#\n#   If no path to the installed bam library is given the macro searchs\n#   under /usr, /usr/local, /opt and /opt/local and evaluates the\n#   $BAM_ROOT environment variable.\n#\tAdapted from AX_BOOST_BASE\n#\n#   This macro calls:\n#\n#     AC_SUBST(BAM_CPPFLAGS) / AC_SUBST(BAM_LDFLAGS)\n#\n#   And sets:\n#\n#     HAVE_BAM, HAVE_HTSLIB\n#\n# LICENSE\n#\n#   Copyright (c) 2010 Cole Trapnell <cole@cs.umd.edu>\n#\n#   Copying and distribution of this file, with or without modification, are\n#   permitted in any medium without royalty provided the copyright notice\n#   and this notice are preserved.\n\nAC_DEFUN([AX_BAM],\n[\nAC_ARG_WITH([bam],\n\tAS_HELP_STRING([--with-bam@<:@=DIR@:>@], [use BAM libraries (default is yes) - it is possible to specify the root directory for BAM (optional)]),\n\t[\n    if test \"$withval\" = \"no\"; then\n\t\twant_bam=\"no\"\n    elif test \"$withval\" = \"yes\"; then\n        want_bam=\"yes\"\n        ac_bam_path=\"\"\n    else\n\t    want_bam=\"yes\"\n        ac_bam_path=\"$withval\"\n\tfi\n    ],\n    [want_bam=\"yes\"])\n\n\nAC_ARG_WITH([bam-libdir],\n        AS_HELP_STRING([--with-bam-libdir=LIB_DIR],\n        [Force given directory for bam libraries. Note that this will overwrite library path detection, so use this parameter only if default library detection fails and you know exactly where your bam libraries are located.]),\n        [\n        if test -d $withval\n        then\n                ac_bam_lib_path=\"$withval\"\n        else\n                AC_MSG_ERROR(--with-bam-libdir expected directory name)\n        fi\n        ],\n        [ac_bam_lib_path=\"\"]\n)\n\nif test \"x$want_bam\" = \"xyes\"; then\n#\tbam_lib_version_req=ifelse([$1], ,1.20.0,$1)\n#\tbam_lib_version_req_shorten=`expr $bam_lib_version_req : '\\([[0-9]]*\\.[[0-9]]*\\)'`\n#\tbam_lib_version_req_major=`expr $bam_lib_version_req : '\\([[0-9]]*\\)'`\n#\tbam_lib_version_req_minor=`expr $bam_lib_version_req : '[[0-9]]*\\.\\([[0-9]]*\\)'`\n#\tbam_lib_version_req_sub_minor=`expr $bam_lib_version_req : '[[0-9]]*\\.[[0-9]]*\\.\\([[0-9]]*\\)'`\n#\tif test \"x$bam_lib_version_req_sub_minor\" = \"x\" ; then\n#\t\tbam_lib_version_req_sub_minor=\"0\"\n#    \tfi\n#\tWANT_BAM_VERSION=`expr $bam_lib_version_req_major \\* 100000 \\+  $bam_lib_version_req_minor \\* 100 \\+ $bam_lib_version_req_sub_minor`\n\tAC_MSG_CHECKING(for htslib or bamlib)\n\tsucceeded=no\n\n\tUSE_HTSLIB=0\n\n\tdnl first we check the system location for bam libraries\n\tSEARCH_DIRS=\"/usr /usr/local /opt /opt/local\"\n\tif test \"$ac_bam_path\" != \"\"; then\n\t    SEARCH_DIRS=$ac_bam_path\n\tfi\n\tfor ac_bam_path_tmp in $SEARCH_DIRS ; do\n\t\tif test -d \"$ac_bam_path_tmp/include/htslib\" && test -r \"$ac_bam_path_tmp/include/htslib\"; then\n\t\t\tBAM_LDFLAGS=\"-L$ac_bam_path_tmp/lib\"\n\t\t\tBAM_CPPFLAGS=\"-I$ac_bam_path_tmp/include\"\n\t\t\tBAM_LIB_PARAM=\"-lhts\"\n\t\t\tUSE_HTSLIB=1\n\t\t\tAC_DEFINE(HAVE_HTSLIB,,[define if the BAM library is htslib])\n\t\t\tbreak;\n\t\tfi\n\t\tif test -d \"$ac_bam_path_tmp/include/bam\" && test -r \"$ac_bam_path_tmp/include/bam\"; then\n\t\t\tBAM_LDFLAGS=\"-L$ac_bam_path_tmp/lib\"\n\t\t\tBAM_CPPFLAGS=\"-I$ac_bam_path_tmp/include\"\n\t\t\tBAM_LIB_PARAM=\"-lbam\"\n\t\t\tbreak;\n\t\tfi\n\tdone\n\n    dnl overwrite ld flags if we have required special directory with\n    dnl --with-bam-libdir parameter\n    if test \"$ac_bam_lib_path\" != \"\"; then\n       BAM_LDFLAGS=\"-L$ac_bam_lib_path\"\n    fi\n\n\tCPPFLAGS_SAVED=\"$CPPFLAGS\"\n\tCPPFLAGS=\"$CPPFLAGS $BAM_CPPFLAGS\"\n\texport CPPFLAGS\n\n\tLDFLAGS_SAVED=\"$LDFLAGS\"\n\tLDFLAGS=\"$LDFLAGS $BAM_LDFLAGS\"\n\texport LDFLAGS\n\n\tif test \"$USE_HTSLIB\" == \"0\"; then\n\n\t   AC_LANG_PUSH(C++)\n\t        \tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t\t\t\t\t@%:@include <bam/bam.h>\n\t\t\t\t\t]], [[]])],[\n       AC_MSG_RESULT(yes)\n\t   succeeded=yes\n\t   found_system=yes\n       \t],[\n       \t])\n\t   AC_LANG_POP([C++])\n\n\telse\n\n\t   AC_LANG_PUSH(C++)\n\t        \tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t\t\t\t\t@%:@include <htslib/hts.h>\n\t\t\t\t\t]], [[]])],[\n       AC_MSG_RESULT(yes)\n\t   succeeded=yes\n\t   found_system=yes\n       \t],[\n       \t])\n\t   AC_LANG_POP([C++])\n\n    fi\n\n\tif test \"$succeeded\" != \"yes\" ; then\n\t\tAC_MSG_ERROR([[We could not detect the bam libraries. Try installing htslib or libbam, or specifying a path to one with --with-bam=/some/path]])\n\telse\n\t\tBAM_LIB=\"$BAM_LIB_PARAM\"\n\t\tAC_SUBST(BAM_CPPFLAGS)\n\t\tAC_SUBST(BAM_LDFLAGS)\n\t\tAC_SUBST(BAM_LIB)\n\t\tAC_DEFINE(HAVE_BAM,,[define if the BAM library is available])\n\tfi\n\n        CPPFLAGS=\"$CPPFLAGS_SAVED\"\n       \tLDFLAGS=\"$LDFLAGS_SAVED\"\nfi\n\n])\n"
  },
  {
    "path": "ax_boost_base.m4",
    "content": "# ===========================================================================\n#      https://www.gnu.org/software/autoconf-archive/ax_boost_base.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])\n#\n# DESCRIPTION\n#\n#   Test for the Boost C++ libraries of a particular version (or newer)\n#\n#   If no path to the installed boost library is given the macro searchs\n#   under /usr, /usr/local, /opt and /opt/local and evaluates the\n#   $BOOST_ROOT environment variable. Further documentation is available at\n#   <http://randspringer.de/boost/index.html>.\n#\n#   This macro calls:\n#\n#     AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)\n#\n#   And sets:\n#\n#     HAVE_BOOST\n#\n# LICENSE\n#\n#   Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>\n#   Copyright (c) 2009 Peter Adolphs\n#\n#   Copying and distribution of this file, with or without modification, are\n#   permitted in any medium without royalty provided the copyright notice\n#   and this notice are preserved. This file is offered as-is, without any\n#   warranty.\n\n#serial 45\n\n# example boost program (need to pass version)\nm4_define([_AX_BOOST_BASE_PROGRAM],\n          [AC_LANG_PROGRAM([[\n#include <boost/version.hpp>\n]],[[\n(void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < ($1))]));\n]])])\n\nAC_DEFUN([AX_BOOST_BASE],\n[\nAC_ARG_WITH([boost],\n  [AS_HELP_STRING([--with-boost@<:@=ARG@:>@],\n    [use Boost library from a standard location (ARG=yes),\n     from the specified location (ARG=<path>),\n     or disable it (ARG=no)\n     @<:@ARG=yes@:>@ ])],\n    [\n     AS_CASE([$withval],\n       [no],[want_boost=\"no\";_AX_BOOST_BASE_boost_path=\"\"],\n       [yes],[want_boost=\"yes\";_AX_BOOST_BASE_boost_path=\"\"],\n       [want_boost=\"yes\";_AX_BOOST_BASE_boost_path=\"$withval\"])\n    ],\n    [want_boost=\"yes\"])\n\n\nAC_ARG_WITH([boost-libdir],\n  [AS_HELP_STRING([--with-boost-libdir=LIB_DIR],\n    [Force given directory for boost libraries.\n     Note that this will override library path detection,\n     so use this parameter only if default library detection fails\n     and you know exactly where your boost libraries are located.])],\n  [\n   AS_IF([test -d \"$withval\"],\n         [_AX_BOOST_BASE_boost_lib_path=\"$withval\"],\n    [AC_MSG_ERROR([--with-boost-libdir expected directory name])])\n  ],\n  [_AX_BOOST_BASE_boost_lib_path=\"\"])\n\nBOOST_LDFLAGS=\"\"\nBOOST_CPPFLAGS=\"\"\nAS_IF([test \"x$want_boost\" = \"xyes\"],\n      [_AX_BOOST_BASE_RUNDETECT([$1],[$2],[$3])])\nAC_SUBST(BOOST_CPPFLAGS)\nAC_SUBST(BOOST_LDFLAGS)\n])\n\n\n# convert a version string in $2 to numeric and affect to polymorphic var $1\nAC_DEFUN([_AX_BOOST_BASE_TONUMERICVERSION],[\n  AS_IF([test \"x$2\" = \"x\"],[_AX_BOOST_BASE_TONUMERICVERSION_req=\"1.20.0\"],[_AX_BOOST_BASE_TONUMERICVERSION_req=\"$2\"])\n  _AX_BOOST_BASE_TONUMERICVERSION_req_shorten=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\\([[0-9]]*\\.[[0-9]]*\\)'`\n  _AX_BOOST_BASE_TONUMERICVERSION_req_major=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\\([[0-9]]*\\)'`\n  AS_IF([test \"x$_AX_BOOST_BASE_TONUMERICVERSION_req_major\" = \"x\"],\n        [AC_MSG_ERROR([You should at least specify libboost major version])])\n  _AX_BOOST_BASE_TONUMERICVERSION_req_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\\.\\([[0-9]]*\\)'`\n  AS_IF([test \"x$_AX_BOOST_BASE_TONUMERICVERSION_req_minor\" = \"x\"],\n        [_AX_BOOST_BASE_TONUMERICVERSION_req_minor=\"0\"])\n  _AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\\.[[0-9]]*\\.\\([[0-9]]*\\)'`\n  AS_IF([test \"X$_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor\" = \"X\"],\n        [_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor=\"0\"])\n  _AX_BOOST_BASE_TONUMERICVERSION_RET=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req_major \\* 100000 \\+  $_AX_BOOST_BASE_TONUMERICVERSION_req_minor \\* 100 \\+ $_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor`\n  AS_VAR_SET($1,$_AX_BOOST_BASE_TONUMERICVERSION_RET)\n])\n\ndnl Run the detection of boost should be run only if $want_boost\nAC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[\n    _AX_BOOST_BASE_TONUMERICVERSION(WANT_BOOST_VERSION,[$1])\n    succeeded=no\n\n\n    AC_REQUIRE([AC_CANONICAL_HOST])\n    dnl On 64-bit systems check for system libraries in both lib64 and lib.\n    dnl The former is specified by FHS, but e.g. Debian does not adhere to\n    dnl this (as it rises problems for generic multi-arch support).\n    dnl The last entry in the list is chosen by default when no libraries\n    dnl are found, e.g. when only header-only libraries are installed!\n    AS_CASE([${host_cpu}],\n      [x86_64],[libsubdirs=\"lib64 libx32 lib lib64\"],\n      [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64],[libsubdirs=\"lib64 lib lib64\"],\n      [libsubdirs=\"lib\"]\n    )\n\n    dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give\n    dnl them priority over the other paths since, if libs are found there, they\n    dnl are almost assuredly the ones desired.\n    AS_CASE([${host_cpu}],\n      [i?86],[multiarch_libsubdir=\"lib/i386-${host_os}\"],\n      [multiarch_libsubdir=\"lib/${host_cpu}-${host_os}\"]\n    )\n\n    dnl first we check the system location for boost libraries\n    dnl this location ist chosen if boost libraries are installed with the --layout=system option\n    dnl or if you install boost with RPM\n    AS_IF([test \"x$_AX_BOOST_BASE_boost_path\" != \"x\"],[\n        AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) includes in \"$_AX_BOOST_BASE_boost_path/include\"])\n         AS_IF([test -d \"$_AX_BOOST_BASE_boost_path/include\" && test -r \"$_AX_BOOST_BASE_boost_path/include\"],[\n           AC_MSG_RESULT([yes])\n           BOOST_CPPFLAGS=\"-I$_AX_BOOST_BASE_boost_path/include\"\n           for _AX_BOOST_BASE_boost_path_tmp in $multiarch_libsubdir $libsubdirs; do\n                AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) lib path in \"$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp\"])\n                AS_IF([test -d \"$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp\" && test -r \"$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp\" ],[\n                        AC_MSG_RESULT([yes])\n                        BOOST_LDFLAGS=\"-L$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp\";\n                        break;\n                ],\n      [AC_MSG_RESULT([no])])\n           done],[\n      AC_MSG_RESULT([no])])\n    ],[\n        if test X\"$cross_compiling\" = Xyes; then\n            search_libsubdirs=$multiarch_libsubdir\n        else\n            search_libsubdirs=\"$multiarch_libsubdir $libsubdirs\"\n        fi\n        for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do\n            if test -d \"$_AX_BOOST_BASE_boost_path_tmp/include/boost\" && test -r \"$_AX_BOOST_BASE_boost_path_tmp/include/boost\" ; then\n                for libsubdir in $search_libsubdirs ; do\n                    if ls \"$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_\"* >/dev/null 2>&1 ; then break; fi\n                done\n                BOOST_LDFLAGS=\"-L$_AX_BOOST_BASE_boost_path_tmp/$libsubdir\"\n                BOOST_CPPFLAGS=\"-I$_AX_BOOST_BASE_boost_path_tmp/include\"\n                break;\n            fi\n        done\n    ])\n\n    dnl overwrite ld flags if we have required special directory with\n    dnl --with-boost-libdir parameter\n    AS_IF([test \"x$_AX_BOOST_BASE_boost_lib_path\" != \"x\"],\n          [BOOST_LDFLAGS=\"-L$_AX_BOOST_BASE_boost_lib_path\"])\n\n    AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION)])\n    CPPFLAGS_SAVED=\"$CPPFLAGS\"\n    CPPFLAGS=\"$CPPFLAGS $BOOST_CPPFLAGS\"\n    export CPPFLAGS\n\n    LDFLAGS_SAVED=\"$LDFLAGS\"\n    LDFLAGS=\"$LDFLAGS $BOOST_LDFLAGS\"\n    export LDFLAGS\n\n    AC_REQUIRE([AC_PROG_CXX])\n    AC_LANG_PUSH(C++)\n        AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[\n        AC_MSG_RESULT(yes)\n    succeeded=yes\n    found_system=yes\n        ],[\n        ])\n    AC_LANG_POP([C++])\n\n\n\n    dnl if we found no boost with system layout we search for boost libraries\n    dnl built and installed without the --layout=system option or for a staged(not installed) version\n    if test \"x$succeeded\" != \"xyes\" ; then\n        CPPFLAGS=\"$CPPFLAGS_SAVED\"\n        LDFLAGS=\"$LDFLAGS_SAVED\"\n        BOOST_CPPFLAGS=\n        if test -z \"$_AX_BOOST_BASE_boost_lib_path\" ; then\n            BOOST_LDFLAGS=\n        fi\n        _version=0\n        if test -n \"$_AX_BOOST_BASE_boost_path\" ; then\n            if test -d \"$_AX_BOOST_BASE_boost_path\" && test -r \"$_AX_BOOST_BASE_boost_path\"; then\n                for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do\n                    _version_tmp=`echo $i | sed \"s#$_AX_BOOST_BASE_boost_path##\" | sed 's/\\/include\\/boost-//' | sed 's/_/./'`\n                    V_CHECK=`expr $_version_tmp \\> $_version`\n                    if test \"x$V_CHECK\" = \"x1\" ; then\n                        _version=$_version_tmp\n                    fi\n                    VERSION_UNDERSCORE=`echo $_version | sed 's/\\./_/'`\n                    BOOST_CPPFLAGS=\"-I$_AX_BOOST_BASE_boost_path/include/boost-$VERSION_UNDERSCORE\"\n                done\n                dnl if nothing found search for layout used in Windows distributions\n                if test -z \"$BOOST_CPPFLAGS\"; then\n                    if test -d \"$_AX_BOOST_BASE_boost_path/boost\" && test -r \"$_AX_BOOST_BASE_boost_path/boost\"; then\n                        BOOST_CPPFLAGS=\"-I$_AX_BOOST_BASE_boost_path\"\n                    fi\n                fi\n                dnl if we found something and BOOST_LDFLAGS was unset before\n                dnl (because \"$_AX_BOOST_BASE_boost_lib_path\" = \"\"), set it here.\n                if test -n \"$BOOST_CPPFLAGS\" && test -z \"$BOOST_LDFLAGS\"; then\n                    for libsubdir in $libsubdirs ; do\n                        if ls \"$_AX_BOOST_BASE_boost_path/$libsubdir/libboost_\"* >/dev/null 2>&1 ; then break; fi\n                    done\n                    BOOST_LDFLAGS=\"-L$_AX_BOOST_BASE_boost_path/$libsubdir\"\n                fi\n            fi\n        else\n            if test \"x$cross_compiling\" != \"xyes\" ; then\n                for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do\n                    if test -d \"$_AX_BOOST_BASE_boost_path\" && test -r \"$_AX_BOOST_BASE_boost_path\" ; then\n                        for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do\n                            _version_tmp=`echo $i | sed \"s#$_AX_BOOST_BASE_boost_path##\" | sed 's/\\/include\\/boost-//' | sed 's/_/./'`\n                            V_CHECK=`expr $_version_tmp \\> $_version`\n                            if test \"x$V_CHECK\" = \"x1\" ; then\n                                _version=$_version_tmp\n                                best_path=$_AX_BOOST_BASE_boost_path\n                            fi\n                        done\n                    fi\n                done\n\n                VERSION_UNDERSCORE=`echo $_version | sed 's/\\./_/'`\n                BOOST_CPPFLAGS=\"-I$best_path/include/boost-$VERSION_UNDERSCORE\"\n                if test -z \"$_AX_BOOST_BASE_boost_lib_path\" ; then\n                    for libsubdir in $libsubdirs ; do\n                        if ls \"$best_path/$libsubdir/libboost_\"* >/dev/null 2>&1 ; then break; fi\n                    done\n                    BOOST_LDFLAGS=\"-L$best_path/$libsubdir\"\n                fi\n            fi\n\n            if test -n \"$BOOST_ROOT\" ; then\n                for libsubdir in $libsubdirs ; do\n                    if ls \"$BOOST_ROOT/stage/$libsubdir/libboost_\"* >/dev/null 2>&1 ; then break; fi\n                done\n                if test -d \"$BOOST_ROOT\" && test -r \"$BOOST_ROOT\" && test -d \"$BOOST_ROOT/stage/$libsubdir\" && test -r \"$BOOST_ROOT/stage/$libsubdir\"; then\n                    version_dir=`expr //$BOOST_ROOT : '.*/\\(.*\\)'`\n                    stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'`\n                        stage_version_shorten=`expr $stage_version : '\\([[0-9]]*\\.[[0-9]]*\\)'`\n                    V_CHECK=`expr $stage_version_shorten \\>\\= $_version`\n                    if test \"x$V_CHECK\" = \"x1\" && test -z \"$_AX_BOOST_BASE_boost_lib_path\" ; then\n                        AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)\n                        BOOST_CPPFLAGS=\"-I$BOOST_ROOT\"\n                        BOOST_LDFLAGS=\"-L$BOOST_ROOT/stage/$libsubdir\"\n                    fi\n                fi\n            fi\n        fi\n\n        CPPFLAGS=\"$CPPFLAGS $BOOST_CPPFLAGS\"\n        export CPPFLAGS\n        LDFLAGS=\"$LDFLAGS $BOOST_LDFLAGS\"\n        export LDFLAGS\n\n        AC_LANG_PUSH(C++)\n            AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[\n            AC_MSG_RESULT(yes)\n        succeeded=yes\n        found_system=yes\n            ],[\n            ])\n        AC_LANG_POP([C++])\n    fi\n\n    if test \"x$succeeded\" != \"xyes\" ; then\n        if test \"x$_version\" = \"x0\" ; then\n            AC_MSG_NOTICE([[We could not detect the boost libraries (version $1 or higher). If you have a staged boost library (still not installed) please specify \\$BOOST_ROOT in your environment and do not give a PATH to --with-boost option.  If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])\n        else\n            AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).])\n        fi\n        # execute ACTION-IF-NOT-FOUND (if present):\n        ifelse([$3], , :, [$3])\n    else\n        AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])\n        # execute ACTION-IF-FOUND (if present):\n        ifelse([$2], , :, [$2])\n    fi\n\n    CPPFLAGS=\"$CPPFLAGS_SAVED\"\n    LDFLAGS=\"$LDFLAGS_SAVED\"\n\n])\n"
  },
  {
    "path": "ax_boost_filesystem.m4",
    "content": "# ===========================================================================\n#   https://www.gnu.org/software/autoconf-archive/ax_boost_filesystem.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_BOOST_FILESYSTEM\n#\n# DESCRIPTION\n#\n#   Test for Filesystem library from the Boost C++ libraries. The macro\n#   requires a preceding call to AX_BOOST_BASE. Further documentation is\n#   available at <http://randspringer.de/boost/index.html>.\n#\n#   This macro calls:\n#\n#     AC_SUBST(BOOST_FILESYSTEM_LIB)\n#\n#   And sets:\n#\n#     HAVE_BOOST_FILESYSTEM\n#\n# LICENSE\n#\n#   Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>\n#   Copyright (c) 2009 Michael Tindal\n#   Copyright (c) 2009 Roman Rybalko <libtorrent@romanr.info>\n#\n#   Copying and distribution of this file, with or without modification, are\n#   permitted in any medium without royalty provided the copyright notice\n#   and this notice are preserved. This file is offered as-is, without any\n#   warranty.\n\n#serial 27\n\nAC_DEFUN([AX_BOOST_FILESYSTEM],\n[\n\tAC_ARG_WITH([boost-filesystem],\n\tAS_HELP_STRING([--with-boost-filesystem@<:@=special-lib@:>@],\n                   [use the Filesystem library from boost - it is possible to specify a certain library for the linker\n                        e.g. --with-boost-filesystem=boost_filesystem-gcc-mt ]),\n        [\n        if test \"$withval\" = \"no\"; then\n\t\t\twant_boost=\"no\"\n        elif test \"$withval\" = \"yes\"; then\n            want_boost=\"yes\"\n            ax_boost_user_filesystem_lib=\"\"\n        else\n\t\t    want_boost=\"yes\"\n\t\tax_boost_user_filesystem_lib=\"$withval\"\n\t\tfi\n        ],\n        [want_boost=\"yes\"]\n\t)\n\n\tif test \"x$want_boost\" = \"xyes\"; then\n        AC_REQUIRE([AC_PROG_CC])\n\t\tCPPFLAGS_SAVED=\"$CPPFLAGS\"\n\t\tCPPFLAGS=\"$CPPFLAGS $BOOST_CPPFLAGS\"\n\t\texport CPPFLAGS\n\n\t\tLDFLAGS_SAVED=\"$LDFLAGS\"\n\t\tLDFLAGS=\"$LDFLAGS $BOOST_LDFLAGS\"\n\t\texport LDFLAGS\n\n\t\tLIBS_SAVED=$LIBS\n\t\tLIBS=\"$LIBS $BOOST_SYSTEM_LIB\"\n\t\texport LIBS\n\n        AC_CACHE_CHECK(whether the Boost::Filesystem library is available,\n\t\t\t\t\t   ax_cv_boost_filesystem,\n        [AC_LANG_PUSH([C++])\n         AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/filesystem/path.hpp>]],\n                                   [[using namespace boost::filesystem;\n                                   path my_path( \"foo/bar/data.txt\" );\n                                   return 0;]])],\n\t\t\t\t\t       ax_cv_boost_filesystem=yes, ax_cv_boost_filesystem=no)\n         AC_LANG_POP([C++])\n\t\t])\n\t\tif test \"x$ax_cv_boost_filesystem\" = \"xyes\"; then\n\t\t\tAC_DEFINE(HAVE_BOOST_FILESYSTEM,,[define if the Boost::Filesystem library is available])\n            BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\\/@:>@*//'`\n            if test \"x$ax_boost_user_filesystem_lib\" = \"x\"; then\n                for libextension in `ls -r $BOOSTLIBDIR/libboost_filesystem* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\\..*,,'` ; do\n                     ax_lib=${libextension}\n\t\t\t\t    AC_CHECK_LIB($ax_lib, main,\n                                 [BOOST_FILESYSTEM_LIB=\"-l$ax_lib\"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem=\"yes\"; break],\n                                 [link_filesystem=\"no\"])\n\t\t\t\tdone\n                if test \"x$link_filesystem\" != \"xyes\"; then\n                for libextension in `ls -r $BOOSTLIBDIR/boost_filesystem* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\\..*,,'` ; do\n                     ax_lib=${libextension}\n\t\t\t\t    AC_CHECK_LIB($ax_lib, main,\n                                 [BOOST_FILESYSTEM_LIB=\"-l$ax_lib\"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem=\"yes\"; break],\n                                 [link_filesystem=\"no\"])\n\t\t\t\tdone\n\t\t    fi\n            else\n               for ax_lib in $ax_boost_user_filesystem_lib boost_filesystem-$ax_boost_user_filesystem_lib; do\n\t\t\t\t      AC_CHECK_LIB($ax_lib, main,\n                                   [BOOST_FILESYSTEM_LIB=\"-l$ax_lib\"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem=\"yes\"; break],\n                                   [link_filesystem=\"no\"])\n                  done\n\n            fi\n            if test \"x$ax_lib\" = \"x\"; then\n                AC_MSG_ERROR(Could not find a version of the library!)\n            fi\n\t\t\tif test \"x$link_filesystem\" != \"xyes\"; then\n\t\t\t\tAC_MSG_ERROR(Could not link against $ax_lib !)\n\t\t\tfi\n\t\tfi\n\n\t\tCPPFLAGS=\"$CPPFLAGS_SAVED\"\n\t\tLDFLAGS=\"$LDFLAGS_SAVED\"\n\t\tLIBS=\"$LIBS_SAVED\"\n\tfi\n])\n"
  },
  {
    "path": "ax_boost_serialization.m4",
    "content": "# ===========================================================================\n#  https://www.gnu.org/software/autoconf-archive/ax_boost_serialization.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_BOOST_SERIALIZATION\n#\n# DESCRIPTION\n#\n#   Test for Serialization library from the Boost C++ libraries. The macro\n#   requires a preceding call to AX_BOOST_BASE. Further documentation is\n#   available at <http://randspringer.de/boost/index.html>.\n#\n#   This macro calls:\n#\n#     AC_SUBST(BOOST_SERIALIZATION_LIB)\n#\n#   And sets:\n#\n#     HAVE_BOOST_SERIALIZATION\n#\n# LICENSE\n#\n#   Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>\n#\n#   Copying and distribution of this file, with or without modification, are\n#   permitted in any medium without royalty provided the copyright notice\n#   and this notice are preserved. This file is offered as-is, without any\n#   warranty.\n\n#serial 22\n\nAC_DEFUN([AX_BOOST_SERIALIZATION],\n[\n\tAC_ARG_WITH([boost-serialization],\n\tAS_HELP_STRING([--with-boost-serialization@<:@=special-lib@:>@],\n                   [use the Serialization library from boost - it is possible to specify a certain library for the linker\n                        e.g. --with-boost-serialization=boost_serialization-gcc-mt-d-1_33_1 ]),\n        [\n        if test \"$withval\" = \"no\"; then\n\t\t\twant_boost=\"no\"\n        elif test \"$withval\" = \"yes\"; then\n            want_boost=\"yes\"\n            ax_boost_user_serialization_lib=\"\"\n        else\n\t\t    want_boost=\"yes\"\n\t\tax_boost_user_serialization_lib=\"$withval\"\n\t\tfi\n        ],\n        [want_boost=\"yes\"]\n\t)\n\n\tif test \"x$want_boost\" = \"xyes\"; then\n        AC_REQUIRE([AC_PROG_CC])\n\t\tCPPFLAGS_SAVED=\"$CPPFLAGS\"\n\t\tCPPFLAGS=\"$CPPFLAGS $BOOST_CPPFLAGS\"\n\t    AC_MSG_WARN(BOOST_CPPFLAGS $BOOST_CPPFLAGS)\n\t\texport CPPFLAGS\n\n\t\tLDFLAGS_SAVED=\"$LDFLAGS\"\n\t\tLDFLAGS=\"$LDFLAGS $BOOST_LDFLAGS\"\n\t\texport LDFLAGS\n\n        AC_CACHE_CHECK(whether the Boost::Serialization library is available,\n\t\t\t\t\t   ax_cv_boost_serialization,\n        [AC_LANG_PUSH([C++])\n\t\t\t AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <fstream>\n\t\t\t\t\t\t\t\t\t\t\t\t @%:@include <boost/archive/text_oarchive.hpp>\n                                                 @%:@include <boost/archive/text_iarchive.hpp>\n\t\t\t\t\t\t\t\t\t\t\t\t]],\n                                   [[std::ofstream ofs(\"filename\");\n\t\t\t\t\t\t\t\t\tboost::archive::text_oarchive oa(ofs);\n\t\t\t\t\t\t\t\t\t return 0;\n                                   ]])],\n                   ax_cv_boost_serialization=yes, ax_cv_boost_serialization=no)\n         AC_LANG_POP([C++])\n\t\t])\n\t\tif test \"x$ax_cv_boost_serialization\" = \"xyes\"; then\n\t\t\tAC_DEFINE(HAVE_BOOST_SERIALIZATION,,[define if the Boost::Serialization library is available])\n            BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\\/@:>@*//'`\n            if test \"x$ax_boost_user_serialization_lib\" = \"x\"; then\n                for libextension in `ls $BOOSTLIBDIR/libboost_serialization*.so* $BOOSTLIBDIR/libboost_serialization*.dylib* $BOOSTLIBDIR/libboost_serialization*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\\(boost_serialization.*\\)\\.so.*$;\\1;' -e 's;^lib\\(boost_serialization.*\\)\\.dylib.*$;\\1;' -e 's;^lib\\(boost_serialization.*\\)\\.a*$;\\1;'` ; do\n                     ax_lib=${libextension}\n\t\t\t\t    AC_CHECK_LIB($ax_lib, main,\n                                 [BOOST_SERIALIZATION_LIB=\"-l$ax_lib\"; AC_SUBST(BOOST_SERIALIZATION_LIB) link_serialization=\"yes\"; break],\n                                 [link_serialization=\"no\"])\n\t\t\t\tdone\n                if test \"x$link_serialization\" != \"xyes\"; then\n                for libextension in `ls $BOOSTLIBDIR/boost_serialization*.dll* $BOOSTLIBDIR/boost_serialization*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\\(boost_serialization.*\\)\\.dll.*$;\\1;' -e 's;^\\(boost_serialization.*\\)\\.a.*$;\\1;'` ; do\n                     ax_lib=${libextension}\n\t\t\t\t    AC_CHECK_LIB($ax_lib, main,\n                                 [BOOST_SERIALIZATION_LIB=\"-l$ax_lib\"; AC_SUBST(BOOST_SERIALIZATION_LIB) link_serialization=\"yes\"; break],\n                                 [link_serialization=\"no\"])\n\t\t\t\tdone\n                fi\n\n            else\n               for ax_lib in $ax_boost_user_serialization_lib boost_serialization-$ax_boost_user_serialization_lib; do\n\t\t\t\t      AC_CHECK_LIB($ax_lib, main,\n                                   [BOOST_SERIALIZATION_LIB=\"-l$ax_lib\"; AC_SUBST(BOOST_SERIALIZATION_LIB) link_serialization=\"yes\"; break],\n                                   [link_serialization=\"no\"])\n                  done\n\n            fi\n            if test \"x$ax_lib\" = \"x\"; then\n                AC_MSG_ERROR(Could not find a version of the library!)\n            fi\n\t\t\tif test \"x$link_serialization\" != \"xyes\"; then\n\t\t\t\tAC_MSG_ERROR(Could not link against $ax_lib !)\n\t\t\tfi\n\t\tfi\n\n\t\tCPPFLAGS=\"$CPPFLAGS_SAVED\"\n\tLDFLAGS=\"$LDFLAGS_SAVED\"\n\tfi\n])\n"
  },
  {
    "path": "ax_boost_system.m4",
    "content": "# ===========================================================================\n#     https://www.gnu.org/software/autoconf-archive/ax_boost_system.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_BOOST_SYSTEM\n#\n# DESCRIPTION\n#\n#   Test for System library from the Boost C++ libraries. The macro requires\n#   a preceding call to AX_BOOST_BASE. Further documentation is available at\n#   <http://randspringer.de/boost/index.html>.\n#\n#   This macro calls:\n#\n#     AC_SUBST(BOOST_SYSTEM_LIB)\n#\n#   And sets:\n#\n#     HAVE_BOOST_SYSTEM\n#\n# LICENSE\n#\n#   Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>\n#   Copyright (c) 2008 Michael Tindal\n#   Copyright (c) 2008 Daniel Casimiro <dan.casimiro@gmail.com>\n#\n#   Copying and distribution of this file, with or without modification, are\n#   permitted in any medium without royalty provided the copyright notice\n#   and this notice are preserved. This file is offered as-is, without any\n#   warranty.\n\n#serial 19\n\nAC_DEFUN([AX_BOOST_SYSTEM],\n[\n\tAC_ARG_WITH([boost-system],\n\tAS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@],\n                   [use the System library from boost - it is possible to specify a certain library for the linker\n                        e.g. --with-boost-system=boost_system-gcc-mt ]),\n        [\n        if test \"$withval\" = \"no\"; then\n\t\t\twant_boost=\"no\"\n        elif test \"$withval\" = \"yes\"; then\n            want_boost=\"yes\"\n            ax_boost_user_system_lib=\"\"\n        else\n\t\t    want_boost=\"yes\"\n\t\tax_boost_user_system_lib=\"$withval\"\n\t\tfi\n        ],\n        [want_boost=\"yes\"]\n\t)\n\n\tif test \"x$want_boost\" = \"xyes\"; then\n        AC_REQUIRE([AC_PROG_CC])\n        AC_REQUIRE([AC_CANONICAL_BUILD])\n\t\tCPPFLAGS_SAVED=\"$CPPFLAGS\"\n\t\tCPPFLAGS=\"$CPPFLAGS $BOOST_CPPFLAGS\"\n\t\texport CPPFLAGS\n\n\t\tLDFLAGS_SAVED=\"$LDFLAGS\"\n\t\tLDFLAGS=\"$LDFLAGS $BOOST_LDFLAGS\"\n\t\texport LDFLAGS\n\n        AC_CACHE_CHECK(whether the Boost::System library is available,\n\t\t\t\t\t   ax_cv_boost_system,\n        [AC_LANG_PUSH([C++])\n\t\t\t CXXFLAGS_SAVE=$CXXFLAGS\n\t\t\t CXXFLAGS=\n\n\t\t\t AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/system/error_code.hpp>]],\n\t\t\t\t    [[boost::system::error_category *a = 0;]])],\n                   ax_cv_boost_system=yes, ax_cv_boost_system=no)\n\t\t\t CXXFLAGS=$CXXFLAGS_SAVE\n             AC_LANG_POP([C++])\n\t\t])\n\t\tif test \"x$ax_cv_boost_system\" = \"xyes\"; then\n\t\t\tAC_SUBST(BOOST_CPPFLAGS)\n\n\t\t\tAC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available])\n            BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\\/@:>@*//'`\n\n\t\t\tLDFLAGS_SAVE=$LDFLAGS\n            if test \"x$ax_boost_user_system_lib\" = \"x\"; then\n                for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\\..*,,'` ; do\n                     ax_lib=${libextension}\n\t\t\t\t    AC_CHECK_LIB($ax_lib, main,\n                                 [BOOST_SYSTEM_LIB=\"-l$ax_lib\"; AC_SUBST(BOOST_SYSTEM_LIB) link_system=\"yes\"; break],\n                                 [link_system=\"no\"])\n\t\t\t\tdone\n                if test \"x$link_system\" != \"xyes\"; then\n                for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\\..*,,'` ; do\n                     ax_lib=${libextension}\n\t\t\t\t    AC_CHECK_LIB($ax_lib, main,\n                                 [BOOST_SYSTEM_LIB=\"-l$ax_lib\"; AC_SUBST(BOOST_SYSTEM_LIB) link_system=\"yes\"; break],\n                                 [link_system=\"no\"])\n\t\t\t\tdone\n                fi\n\n            else\n               for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do\n\t\t\t\t      AC_CHECK_LIB($ax_lib, main,\n                                   [BOOST_SYSTEM_LIB=\"-l$ax_lib\"; AC_SUBST(BOOST_SYSTEM_LIB) link_system=\"yes\"; break],\n                                   [link_system=\"no\"])\n                  done\n\n            fi\n            if test \"x$ax_lib\" = \"x\"; then\n                AC_MSG_ERROR(Could not find a version of the library!)\n            fi\n\t\t\tif test \"x$link_system\" = \"xno\"; then\n\t\t\t\tAC_MSG_ERROR(Could not link against $ax_lib !)\n\t\t\tfi\n\t\tfi\n\n\t\tCPPFLAGS=\"$CPPFLAGS_SAVED\"\n\tLDFLAGS=\"$LDFLAGS_SAVED\"\n\tfi\n])\n"
  },
  {
    "path": "ax_boost_thread.m4",
    "content": "# ===========================================================================\n#     https://www.gnu.org/software/autoconf-archive/ax_boost_thread.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_BOOST_THREAD\n#\n# DESCRIPTION\n#\n#   Test for Thread library from the Boost C++ libraries. The macro requires\n#   a preceding call to AX_BOOST_BASE. Further documentation is available at\n#   <http://randspringer.de/boost/index.html>.\n#\n#   This macro calls:\n#\n#     AC_SUBST(BOOST_THREAD_LIB)\n#\n#   And sets:\n#\n#     HAVE_BOOST_THREAD\n#\n# LICENSE\n#\n#   Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>\n#   Copyright (c) 2009 Michael Tindal\n#\n#   Copying and distribution of this file, with or without modification, are\n#   permitted in any medium without royalty provided the copyright notice\n#   and this notice are preserved. This file is offered as-is, without any\n#   warranty.\n\n#serial 31\n\nAC_DEFUN([AX_BOOST_THREAD],\n[\n    AC_ARG_WITH([boost-thread],\n    AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@],\n                   [use the Thread library from boost -\n                    it is possible to specify a certain library for the linker\n                    e.g. --with-boost-thread=boost_thread-gcc-mt ]),\n        [\n        if test \"$withval\" = \"yes\"; then\n            want_boost=\"yes\"\n            ax_boost_user_thread_lib=\"\"\n        else\n            want_boost=\"yes\"\n            ax_boost_user_thread_lib=\"$withval\"\n        fi\n        ],\n        [want_boost=\"yes\"]\n    )\n\n    if test \"x$want_boost\" = \"xyes\"; then\n        AC_REQUIRE([AC_PROG_CC])\n        AC_REQUIRE([AC_CANONICAL_BUILD])\n        CPPFLAGS_SAVED=\"$CPPFLAGS\"\n        CPPFLAGS=\"$CPPFLAGS $BOOST_CPPFLAGS\"\n        export CPPFLAGS\n\n        LDFLAGS_SAVED=\"$LDFLAGS\"\n        LDFLAGS=\"$LDFLAGS $BOOST_LDFLAGS\"\n        export LDFLAGS\n\n        AC_CACHE_CHECK(whether the Boost::Thread library is available,\n                       ax_cv_boost_thread,\n        [AC_LANG_PUSH([C++])\n             CXXFLAGS_SAVE=$CXXFLAGS\n\n             if test \"x$host_os\" = \"xsolaris\" ; then\n                 CXXFLAGS=\"-pthreads $CXXFLAGS\"\n             elif test \"x$host_os\" = \"xmingw32\" ; then\n                 CXXFLAGS=\"-mthreads $CXXFLAGS\"\n             else\n                CXXFLAGS=\"-pthread $CXXFLAGS\"\n             fi\n             AC_COMPILE_IFELSE([\n                 AC_LANG_PROGRAM(\n                     [[@%:@include <boost/thread/thread.hpp>]],\n                     [[boost::thread_group thrds;\n                       return 0;]])],\n                 ax_cv_boost_thread=yes, ax_cv_boost_thread=no)\n             CXXFLAGS=$CXXFLAGS_SAVE\n             AC_LANG_POP([C++])\n        ])\n        if test \"x$ax_cv_boost_thread\" = \"xyes\"; then\n           if test \"x$host_os\" = \"xsolaris\" ; then\n              BOOST_CPPFLAGS=\"-pthreads $BOOST_CPPFLAGS\"\n           elif test \"x$host_os\" = \"xmingw32\" ; then\n              BOOST_CPPFLAGS=\"-mthreads $BOOST_CPPFLAGS\"\n           else\n              BOOST_CPPFLAGS=\"-pthread $BOOST_CPPFLAGS\"\n           fi\n\n            AC_SUBST(BOOST_CPPFLAGS)\n\n            AC_DEFINE(HAVE_BOOST_THREAD,,\n                      [define if the Boost::Thread library is available])\n            BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\\/@:>@*//'`\n\n            LDFLAGS_SAVE=$LDFLAGS\n                        case \"x$host_os\" in\n                          *bsd* )\n                               LDFLAGS=\"-pthread $LDFLAGS\"\n                          break;\n                          ;;\n                        esac\n            if test \"x$ax_boost_user_thread_lib\" = \"x\"; then\n                for libextension in `ls -r $BOOSTLIBDIR/libboost_thread* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\\..*,,'`; do\n                     ax_lib=${libextension}\n                    AC_CHECK_LIB($ax_lib, main,\n                                 [link_thread=\"yes\"; break],\n                                 [link_thread=\"no\"])\n                done\n                if test \"x$link_thread\" != \"xyes\"; then\n                for libextension in `ls -r $BOOSTLIBDIR/boost_thread* 2>/dev/null | sed 's,.*/,,' | sed 's,\\..*,,'`; do\n                     ax_lib=${libextension}\n                    AC_CHECK_LIB($ax_lib, main,\n                                 [link_thread=\"yes\"; break],\n                                 [link_thread=\"no\"])\n                done\n                fi\n\n            else\n               for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do\n                      AC_CHECK_LIB($ax_lib, main,\n                                   [link_thread=\"yes\"; break],\n                                   [link_thread=\"no\"])\n                  done\n\n            fi\n            if test \"x$ax_lib\" = \"x\"; then\n                AC_MSG_ERROR(Could not find a version of the library!)\n            fi\n            if test \"x$link_thread\" = \"xno\"; then\n                AC_MSG_ERROR(Could not link against $ax_lib !)\n            else\n                BOOST_THREAD_LIB=\"-l$ax_lib\"\n                case \"x$host_os\" in\n                    *bsd* )\n                        BOOST_LDFLAGS=\"-pthread $BOOST_LDFLAGS\"\n                        break;\n                        ;;\n                    xsolaris )\n                        BOOST_THREAD_LIB=\"$BOOST_THREAD_LIB -lpthread\"\n                        break;\n                        ;;\n                    xmingw32 )\n                        break;\n                        ;;\n                    * )\n                        BOOST_THREAD_LIB=\"$BOOST_THREAD_LIB -lpthread\"\n                        break;\n                        ;;\n                esac\n                AC_SUBST(BOOST_THREAD_LIB)\n            fi\n        fi\n\n        CPPFLAGS=\"$CPPFLAGS_SAVED\"\n        LDFLAGS=\"$LDFLAGS_SAVED\"\n    fi\n])\n"
  },
  {
    "path": "ax_check_eigen.m4",
    "content": "# SYNOPSIS\n#\n#   AX_EIGEN\n#\n# DESCRIPTION\n#\n#   Test for the EIGEN libraries of a particular version (or newer)\n#\n#   If no path to the installed eigen library is given the macro searchs\n#   under /usr, /usr/local, /opt and /opt/local and evaluates the\n#   $EIGEN_ROOT environment variable. \n#\tAdapted from AX_BOOST_BASE\n#\n#   This macro calls:\n#\n#     AC_SUBST(EIGEN_CPPFLAGS) / AC_SUBST(EIGEN_LDFLAGS)\n#\n#   And sets:\n#\n#     HAVE_EIGEN\n#\n# LICENSE\n#\n#   Copyright (c) 2010 Cole Trapnell <cole@cs.umd.edu>\n#\n#   Copying and distribution of this file, with or without modification, are\n#   permitted in any medium without royalty provided the copyright notice\n#   and this notice are preserved.\n\nAC_DEFUN([AX_EIGEN],\n[\nAC_ARG_WITH([eigen],\nAS_HELP_STRING([--with-eigen@<:@=DIR@:>@], [use EIGEN libraries (default is yes) - it is possible to specify the root directory for EIGEN (optional)]),\n[\nif test \"$withval\" = \"no\"; then\nwant_eigen=\"no\"\nelif test \"$withval\" = \"yes\"; then\nwant_eigen=\"yes\"\nac_eigen_path=\"\"\nelse\nwant_eigen=\"yes\"\nac_eigen_path=\"$withval\"\nfi\n],\n[want_eigen=\"yes\"])\n\nif test \"x$want_eigen\" = \"xyes\"; then\nAC_MSG_CHECKING(for eigenlib)\nsucceeded=no\n\ndnl first we check the system location for eigen libraries\nif test \"$ac_eigen_path\" != \"\"; then\nEIGEN_CPPFLAGS=\"-I$ac_eigen_path/include\"\nelse\nfor ac_eigen_path_tmp in /usr /usr/local /opt /opt/local ; do\n  for ac_eigen_subdir in eigen eigen3 ; do\n    ac_candidate_path=\"$ac_eigen_path_tmp/include/$ac_eigen_subdir\"\n    if test -d \"$ac_candidate_path\" && test -r \"$ac_candidate_path\"; then\n      EIGEN_CPPFLAGS=\"-I$ac_candidate_path\"\n      break;\n    fi\n  done\ndone\nfi\n\nCPPFLAGS_SAVED=\"$CPPFLAGS\"\nCPPFLAGS=\"$CPPFLAGS $EIGEN_CPPFLAGS\"\nexport EIGEN_CPPFLAGS\n\nAC_LANG_PUSH(C++)\nAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n@%:@include <Eigen/Dense>\n]], [[\n]])],[\nAC_MSG_RESULT(yes)\nsucceeded=yes\nfound_system=yes\n],[\nAC_MSG_ERROR([[We could not detect the Eigen3 library. Try installing libeigen3, or specifying a path with --with-eigen=/some/path]])\n])\nAC_LANG_POP([C++])\n\nCPPFLAGS=\"$CPPFLAGS $EIGEN_CPPFLAGS\"\nexport CPPFLAGS\nLDFLAGS=\"$LDFLAGS $EIGEN_LDFLAGS\"\nexport LDFLAGS\nexport EIGEN_CPPFLAGS\n\nif test \"$succeeded\" == \"yes\" ; then\nAC_SUBST(EIGEN_CPPFLAGS)\nAC_DEFINE(HAVE_EIGEN,,[define if the EIGEN library is available])\nfi\n\nCPPFLAGS=\"$CPPFLAGS_SAVED\"\nLDFLAGS=\"$LDFLAGS_SAVED\"\nfi\n\n])\n"
  },
  {
    "path": "ax_check_zlib.m4",
    "content": "# ===========================================================================\n#       http://www.gnu.org/software/autoconf-archive/ax_check_zlib.html\n# ===========================================================================\n#\n# SYNOPSIS\n#\n#   AX_CHECK_ZLIB()\n#\n# DESCRIPTION\n#\n#   This macro searches for an installed zlib library. If nothing was\n#   specified when calling configure, it searches first in /usr/local and\n#   then in /usr. If the --with-zlib=DIR is specified, it will try to find\n#   it in DIR/include/zlib.h and DIR/lib/libz.a. If --without-zlib is\n#   specified, the library is not searched at all.\n#\n#   If either the header file (zlib.h) or the library (libz) is not found,\n#   the configuration exits on error, asking for a valid zlib installation\n#   directory or --without-zlib.\n#\n#   The macro defines the symbol HAVE_LIBZ if the library is found. You\n#   should use autoheader to include a definition for this symbol in a\n#   config.h file. Sample usage in a C/C++ source is as follows:\n#\n#     #ifdef HAVE_LIBZ\n#     #include <zlib.h>\n#     #endif /* HAVE_LIBZ */\n#\n# LICENSE\n#\n#   Copyright (c) 2008 Loic Dachary <loic@senga.org>\n#\n#   This program is free software; you can redistribute it and/or modify it\n#   under the terms of the GNU General Public License as published by the\n#   Free Software Foundation; either version 2 of the License, or (at your\n#   option) any later version.\n#\n#   This program is distributed in the hope that it will be useful, but\n#   WITHOUT ANY WARRANTY; without even the implied warranty of\n#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n#   Public License for more details.\n#\n#   You should have received a copy of the GNU General Public License along\n#   with this program. If not, see <http://www.gnu.org/licenses/>.\n#\n#   As a special exception, the respective Autoconf Macro's copyright owner\n#   gives unlimited permission to copy, distribute and modify the configure\n#   scripts that are the output of Autoconf when processing the Macro. You\n#   need not follow the terms of the GNU General Public License when using\n#   or distributing such scripts, even though portions of the text of the\n#   Macro appear in them. The GNU General Public License (GPL) does govern\n#   all other use of the material that constitutes the Autoconf Macro.\n#\n#   This special exception to the GPL applies to versions of the Autoconf\n#   Macro released by the Autoconf Archive. When you make and distribute a\n#   modified version of the Autoconf Macro, you may extend this special\n#   exception to the GPL to apply to your modified version as well.\n\n#serial 7\n\nAU_ALIAS([CHECK_ZLIB], [AX_CHECK_ZLIB])\nAC_DEFUN([AX_CHECK_ZLIB],\n#\n# Handle user hints\n#\n[AC_MSG_CHECKING(if zlib is wanted)\nAC_ARG_WITH(zlib,\n[  --with-zlib=DIR root directory path of zlib installation [defaults to\n                    /usr/local or /usr if not found in /usr/local]\n  --without-zlib to disable zlib usage completely],\n[if test \"$withval\" != no ; then\n  AC_MSG_RESULT(yes)\n  if test -d \"$withval\"\n  then\n    ZLIB_HOME=\"$withval\"\n  else\n    AC_MSG_WARN([Sorry, $withval does not exist, checking usual places])\n  fi\nelse\n  AC_MSG_RESULT(no)\nfi],\n[AC_MSG_RESULT(yes)])\n\nZLIB_HOME=/usr/local\nif test ! -f \"${ZLIB_HOME}/include/zlib.h\"\nthen\n        ZLIB_HOME=/usr\nfi\n\n#\n# Locate zlib, if wanted\n#\nif test -n \"${ZLIB_HOME}\"\nthen\n        ZLIB_OLD_LDFLAGS=$LDFLAGS\n        ZLIB_OLD_CPPFLAGS=$LDFLAGS\n        LDFLAGS=\"$LDFLAGS -L${ZLIB_HOME}/lib\"\n        CPPFLAGS=\"$CPPFLAGS -I${ZLIB_HOME}/include\"\n        AC_LANG_SAVE\n        AC_LANG_C\n        AC_CHECK_LIB(z, inflateEnd, [zlib_cv_libz=yes], [zlib_cv_libz=no])\n        AC_CHECK_HEADER(zlib.h, [zlib_cv_zlib_h=yes], [zlib_cv_zlib_h=no])\n        AC_LANG_RESTORE\n        if test \"$zlib_cv_libz\" = \"yes\" -a \"$zlib_cv_zlib_h\" = \"yes\"\n        then\n                #\n                # If both library and header were found, use them\n                #\n                AC_CHECK_LIB(z, inflateEnd)\n                AC_MSG_CHECKING(zlib in ${ZLIB_HOME})\n                AC_MSG_RESULT(ok)\n\t\t\t\tZLIB=\"-lz\"\n\t\t\t\tAC_SUBST(ZLIB)\n        else\n                #\n                # If either header or library was not found, revert and bomb\n                #\n                AC_MSG_CHECKING(zlib in ${ZLIB_HOME})\n                LDFLAGS=\"$ZLIB_OLD_LDFLAGS\"\n                CPPFLAGS=\"$ZLIB_OLD_CPPFLAGS\"\n                AC_MSG_RESULT(failed)\n                AC_MSG_ERROR(either specify a valid zlib installation with --with-zlib=DIR or disable zlib usage with --without-zlib)\n        fi\nfi\n\n])\n"
  },
  {
    "path": "ax_openmp.m4",
    "content": " # AC_C_OPENMP\n # -----------\n # Check which options need to be passed to the C compiler to support OpenMP.\n # Set the OPENMP_CFLAGS variable to these options.\n # The options are necessary at compile time (so the #pragmas are understood)\n # and at link time (so the appropriate library is linked with).\n # This macro takes care to not produce redundant options if $CC $CFLAGS \nalready\n # supports OpenMP. It also is careful to not pass options to compilers that\n # misinterpret them; for example, most compilers accept \"-openmp\" and create\n # an output file called 'penmp' rather than activating OpenMP support.\n AC_DEFUN([AC_C_OPENMP],\n [\n   AC_MSG_CHECKING([whether to use OpenMP])\n   AC_ARG_ENABLE(openmp,\n     [AS_HELP_STRING([--disable-openmp], [do not use OpenMP])],\n     [],\n     [enable_openmp=yes])\n   AC_MSG_RESULT([$enable_openmp])\n   OPENMP_CFLAGS=\n   if test \"$enable_openmp\" = yes; then\n     AC_MSG_CHECKING([for $CC option to support OpenMP])\n     AC_CACHE_VAL([ac_cv_prog_cc_openmp], [\n       ac_cv_prog_cc_openmp=unsupported\n       AC_LINK_IFELSE([\n #ifndef _OPENMP\n  choke me\n #endif\n #include <omp.h>\n int main () { return omp_get_num_threads (); }\n         ], [ac_cv_prog_cc_openmp=\"none needed\"])\n       if test \"$ac_cv_prog_cc_openmp\" = unsupported; then\n         dnl Try these flags:\n         dnl   GCC >= 4.2           -fopenmp\n         dnl   SunPRO C             -xopenmp\n         dnl   Intel C              -openmp\n         dnl   SGI C, PGI C         -mp\n         dnl   Tru64 Compaq C       -omp\n         dnl   IBM C (AIX, Linux)   -qsmp=omp\n         for brand in GCC SunPRO Intel SGI/PGI Compaq IBM; do\n           case $brand in\n             GCC)\n               ac_conditional='defined __GNUC__'\n               ac_option='-fopenmp' ;;\n             SunPRO)\n               ac_conditional='defined __SUNPRO_C || defined __SUNPRO_CC'\n               ac_option='-xopenmp' ;;\n             Intel)\n               ac_conditional='defined __INTEL_COMPILER'\n               ac_option='-openmp' ;;\n             SGI/PGI)\n               ac_conditional='defined __sgi || defined __PGI || defined \n__PGIC__'\n               ac_option='-mp' ;;\n             Compaq)\n               ac_conditional='defined __DECC || defined __DECCXX'\n               ac_option='-omp' ;;\n             IBM)\n               ac_conditional='defined __xlc__ || defined __xlC__'\n               ac_option='-qsmp=omp' ;;\n           esac\n           if test $brand = GCC; then\n             if test \"$GCC\" = yes; then\n               ac_openmp_result=yes\n             else\n               ac_openmp_result=no\n             fi\n           else\n             AC_EGREP_CPP([Brand], [\n               #if $ac_conditional\n                Brand\n               #endif\n               ], [ac_openmp_result=yes], [ac_openmp_result=no])\n           fi\n           if test $ac_openmp_result = yes; then\n             ac_save_CFLAGS=$CFLAGS\n             CFLAGS=\"$CFLAGS $ac_option\"\n             AC_LINK_IFELSE([\n #ifndef _OPENMP\n  choke me\n #endif\n #include <omp.h>\n int main () { return omp_get_num_threads (); }\n               ], [ac_cv_prog_cc_openmp=$ac_option])\n             CFLAGS=$ac_save_CFLAGS\n             break\n           fi\n         done\n       fi\n       ])\n     AC_MSG_RESULT([$ac_cv_prog_cc_openmp])\n     case $ac_cv_prog_cc_openmp in\n       \"none needed\" | unsupported)\n         OPENMP_CFLAGS= ;;\n       *)\n         OPENMP_CFLAGS=$ac_cv_prog_cc_openmp ;;\n     esac\n   fi\n   AC_SUBST([OPENMP_CFLAGS])\n ])\n\n"
  },
  {
    "path": "boost.m4",
    "content": "dnl AC_PATH_BOOST([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])\ndnl Test for the Boost C++ libraries of a particular version (or newer)\ndnl Defines:\ndnl   BOOST_CXXFLAGS to the set of flags required to compiled Boost\nAC_DEFUN([AC_PATH_BOOST], \n[\n  BOOST_CXXFLAGS=\"\"\n  path_given=\"no\"\n\ndnl Extract the path name from a --with-boost=PATH argument\n  AC_ARG_WITH(boost,\n    [  --with-boost=PATH absolute path name where the Boost C++ libraries\n    reside. Alternatively, the BOOST_ROOT environment variable will be used],\n    if test \"$withval\" = no ; then\n\tpath_given=\"no\"\n\tBOOST_CXXFLAGS=\"\"\n    else\n      if test \"$withval\" != yes ; then\n        path_given=\"yes\"\n        BOOST_CXXFLAGS=\"-I$withval\"\n        BOOST_ROOT=\"$withval\"\n      fi\n    fi    \n  )\n\ndnl If no path with given and there is a BOOST_ROOT environment variable,\ndnl use it\n  if test \"$path_given\" = \"no\"; then\n    if test \"x$BOOST_ROOT\" = \"x\"; then\n      BOOST_CXXFLAGS=\"\"\n    else\n      BOOST_CXXFLAGS=\"-I$BOOST_ROOT\"\n    fi\n  fi\n\n  boost_min_version=ifelse([$1], ,1.20.0,$1)\n\n  AC_LANG_SAVE\n  AC_LANG_CPLUSPLUS\n  OLD_CXX_FLAGS=$CXXFLAGS\n  CXXFLAGS=\"$CXXFLAGS $BOOST_CXXFLAGS\"\n  AC_MSG_CHECKING([for the Boost C++ libraries, version $boost_min_version or newer])\n  AC_TRY_COMPILE(\n    [\n#include <boost/version.hpp>\n],\n    [],\n    [\n      have_boost=\"yes\"\n    ],\n    [\n      AC_MSG_RESULT(no)\n      have_boost=\"no\"\n      ifelse([$3], , :, [$3])\n    ])\n\n  if test \"$have_boost\" = \"yes\"; then\n    WANT_BOOST_MAJOR=`expr $boost_min_version : '\\([[0-9]]\\+\\)'`\n    WANT_BOOST_MINOR=`expr $boost_min_version : '[[0-9]]\\+\\.\\([[0-9]]\\+\\)'`\n    WANT_BOOST_SUB_MINOR=`expr $boost_min_version : '[[0-9]]\\+\\.[[0-9]]\\+\\.\\([[0-9]]\\+\\)'`\n    WANT_BOOST_VERSION=`expr $WANT_BOOST_MAJOR \\* 100000 \\+ $WANT_BOOST_MINOR \\* 100 \\+ $WANT_BOOST_SUB_MINOR`\n\n    AC_TRY_COMPILE(\n      [\n#include <boost/version.hpp>\n],\n      [\n#if BOOST_VERSION >= $WANT_BOOST_VERSION\n// Everything is okay\n#else\n#  error Boost version is too old\n#endif\n\n],\n      [\n        AC_MSG_RESULT(yes)\n        ifelse([$2], , :, [$2])\n      ],\n      [\n        AC_MSG_RESULT([no, version of installed Boost libraries is too old])\n        ifelse([$3], , :, [$3])\n      ])\n  fi\n  CXXFLAGS=$OLD_CXXFLAGS\n  AC_LANG_RESTORE\n])\n\n"
  },
  {
    "path": "configure.ac",
    "content": "m4_include([ax_boost_base.m4])\nm4_include([ax_boost_thread.m4])\nm4_include([ax_boost_system.m4])\nm4_include([ax_boost_serialization.m4])\nm4_include([ax_boost_filesystem.m4])\nm4_include([ax_bam.m4])\nm4_include([ax_check_eigen.m4])\nm4_include([ax_check_zlib.m4])\n\ndefine([svnversion], esyscmd([sh -c \"svnversion|tr -d '\\n'\"]))dnl\nAC_INIT([cufflinks], [2.2.2], [cole@cs.umd.edu])\nAC_DEFINE(SVN_REVISION, \"svnversion\", [SVN Revision])\n\nAC_CONFIG_SRCDIR([config.h.in])\nAC_CONFIG_HEADERS([config.h])\nAC_CONFIG_AUX_DIR([build-aux])\nAM_INIT_AUTOMAKE\n\n#AM_PATH_CPPUNIT(1.10.2)\n\nAC_ARG_VAR(PYTHON, [python program])\n\n # Make sure CXXFLAGS is defined so that AC_PROG_CXX doesn't set it.\nCXXFLAGS=\"$CXXFLAGS\"\nCFLAGS=\"$CFLAGS\"\n\nAC_LANG(C)\n\n# Checks for programs.\nAC_PROG_AWK\nAC_PROG_CXX\nAC_PROG_CC\nAC_PROG_MAKE_SET\nAC_PROG_RANLIB\nAC_PROG_INSTALL\nm4_ifdef([AM_PROG_AR], [AM_PROG_AR])\nAM_PATH_PYTHON([2.4])\nAX_BOOST_BASE([1.47.0])\nAX_BAM\nAX_BOOST_SYSTEM\nAX_BOOST_SERIALIZATION\nAX_BOOST_FILESYSTEM\nAX_BOOST_THREAD\nAX_CHECK_ZLIB()\n\n#PKG_CHECK_MODULES([EIGEN3], [eigen3])\nAX_EIGEN\n\n# Checks for header files.\nAC_CHECK_HEADERS([stdlib.h string.h unistd.h])\n\n# Checks for typedefs, structures, and compiler characteristics.\nAC_HEADER_STDBOOL\nAC_C_INLINE\nAC_TYPE_PID_T\nAC_TYPE_SIZE_T\nAC_CHECK_TYPES([ptrdiff_t])\n\n\n# Checks for library functions.\n#AC_FUNC_FORK\n#AC_CHECK_FUNCS([floor memmove pow regcomp sqrt strchr strcspn strspn strstr])\n\n# check the platform\nAC_CANONICAL_HOST\n\n# set CFLAGS and CXXFLAGS\nuser_CFLAGS=${CFLAGS}\ngeneric_CFLAGS=\"-Wall -Wno-strict-aliasing -g -gdwarf-2 -Wunused -Wuninitialized -ftemplate-depth-1024\"\next_CFLAGS=\"\"\ndebug_CFLAGS=\"\"\n#echo \"${host_cpu}-${host_os}\"\ncase \"${host_cpu}-${host_os}\" in\n  i*86-*linux*)\n\t    ext_CFLAGS=\"-march=i686\";;\n  i*86-darwin*)\n\tCFLAGS=\"-m64\"\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM], [ext_CFLAGS=\"-arch x86_64\"], []);;\n  *)\n    AC_MSG_CHECKING([if gcc accepts -m64])\n    CFLAGS=\"-m64\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [ext_CFLAGS=\"-m64\"; AC_MSG_RESULT([yes])],\n\t\t\t\t\t  [ext_CFLAGS=\"-D_FILE_OFFSET_BITS=64\"; AC_MSG_RESULT([no])]);;\nesac\n\nAC_ARG_ENABLE(vectorize,    [  --enable-vectorize        Enable GCC auto-vectorization],\n\t\t\t  [ext_CFLAGS=\"${ext_CFLAGS} -ftree-vectorize -msse3 -ffast-math -ftree-vectorizer-verbose=99\"], [])\n\nAC_ARG_ENABLE(intel64,      [  --enable-intel64        optimize for Intel64 CPU such as Xeon and Core2],\n\t\t\t  [ext_CFLAGS=\"${ext_CFLAGS} -march=nocona\"], [])\n\nAC_ARG_ENABLE([debug],\n              [AS_HELP_STRING([--enable-debug],\n\t                      [enable debugging info (default is no)])],\n              [], [enable_debug=no])\n\n\t\t\t  \nAC_ARG_ENABLE([optim],\n              [AS_HELP_STRING([--enable-optim@<:@=0|1|2|3@:>@],\n\t                      [set optimization level (default is 3)])],\n              [if test \"x$enable_optim\" = xyes; then enable_optim=3; fi],\n              [enable_optim=3])\n\nAS_IF([test \"x$enable_optim\" != xno], [ext_CFLAGS=\"$ext_CFLAGS -O$enable_optim\"])\t\n\nAS_IF([test \"x$enable_debug\" = xyes],\n      [debug_CFLAGS=\"-DDEBUG\"],\n      [debug_CFLAGS=\"-DNDEBUG\"])\n\t  \nAC_ARG_ENABLE(profiling,      [  --enable-profiling        enable profiling with google-perftools],\n\t  [ext_LDFLAGS=\"-lprofiler -ltcmalloc\"], [])\n\t  \nCFLAGS=\"${generic_CFLAGS} ${ext_CFLAGS} ${user_CFLAGS} ${debug_CFLAGS} ${OPENMP_CFLAGS}\"\nCXXFLAGS=\"$CFLAGS -std=c++03\"\nCXXFLAGS=\"${CXXFLAGS} ${BOOST_CPPFLAGS} ${BAM_CPPFLAGS} ${EIGEN_CPPFLAGS}\"\nuser_LDFLAGS=\"$LDFLAGS\"\nLDFLAGS=\"${ext_LDFLAGS} ${user_LDFLAGS}\"\n\n# Checks for structures/functions that can be used to determine system memory\nAC_CHECK_MEMBERS([struct sysinfo.totalram], [], [], [#include <sys/sysinfo.h>])\nAC_CHECK_DECLS([sysctl, CTL_HW, HW_PHYSMEM], [], [], [#include <sys/sysctl.h>])\n\nAM_INIT_AUTOMAKE([-Wall tar-pax foreign])\n\nAC_CONFIG_FILES([Makefile\t\t\t\t \n\t\t\t\t src/Makefile])\n\nAC_OUTPUT\n# dump some configuration confirmations\necho \\\n\"\n-- ${PACKAGE_STRING} Configuration Results --\n  C++ compiler:        ${CXX} ${CXXFLAGS} ${LDFLAGS}\"\n\nif test x\"${GCC}\" = x\"yes\" ; then\n   gcc_version=`${CC} --version | head -n 1`\n   echo \"  GCC version:         ${gcc_version}\"\nelse\n   gcc_version=''\nfi\n\necho \\\n\"  Host System type:    ${host}\n  Install prefix:      ${prefix}\n  Install eprefix:     ${exec_prefix}\n\n  See config.h for further configuration information.\n  Email <${PACKAGE_BUGREPORT}> with questions and bug reports.\n\"\n\nif test x\"${PYTHON}\" = x\":\"  ||  ! test -x \"${PYTHON}\"; then\n    echo \"WARNING! python was not found and is required to run some utility scripts\"\n    echo \"  We recommend installing python and pointing configure to the installed location\"\nfi\n\n"
  },
  {
    "path": "cufflinks.xcodeproj/cole.pbxuser",
    "content": "// !$*UTF8*$!\n{\n\t08FB7793FE84155DC02AAC07 /* Project object */ = {\n\t\tactiveArchitecturePreference = x86_64;\n\t\tactiveBuildConfigurationName = Debug;\n\t\tactiveExecutable = EDD0CD9D10C72AC200AF308F /* cufflinks */;\n\t\tactiveTarget = 8DD76F620486A84900D96B5E /* cufflinks */;\n\t\taddToTargets = (\n\t\t\tEDFE39B0122BE65600F24CD3 /* cuffcluster */,\n\t\t);\n\t\tbreakpoints = (\n\t\t\tED0E3F3F12CBA86F00074D2E /* sorting_hat.cpp:725 */,\n\t\t\tED0E3F4312CBA89F00074D2E /* sorting_hat.cpp:735 */,\n\t\t\tEDC57AC912F7D53300493081 /* cufflinks.cpp:483 */,\n\t\t\tEDC57ACD12F7D56A00493081 /* scaffolds.cpp:539 */,\n\t\t\tEDC57AE812F8578000493081 /* cufflinks.cpp:543 */,\n\t\t\tEDC57AEE12F857FF00493081 /* filters.cpp:506 */,\n\t\t\tEDDC69AA1304DCE000637B75 /* cuffdiff.cpp:435 */,\n\t\t\tEDDC69BF1304DEF800637B75 /* cuffdiff.cpp:458 */,\n\t\t\tEDDC69C51304DF9000637B75 /* cuffdiff.cpp:452 */,\n\t\t\tEDDC69D41304E09600637B75 /* differential.cpp:28 */,\n\t\t\tEDDC69EC1304E2C600637B75 /* differential.cpp:35 */,\n\t\t\tEDC583B21308455A0013090E /* cufflinks.cpp:646 */,\n\t\t\tEDC583C0130847140013090E /* filters.cpp:867 */,\n\t\t\tEDC583CA130853530013090E /* filters.cpp:897 */,\n\t\t\tEDC583F41308558F0013090E /* filters.cpp:936 */,\n\t\t\tEDC583FF130855D10013090E /* filters.cpp:927 */,\n\t\t\tEDC58405130856060013090E /* filters.cpp:916 */,\n\t\t\tEDC5840D130856B00013090E /* filters.cpp:931 */,\n\t\t\tEDC5843C130859F80013090E /* filters.cpp:894 */,\n\t\t\tEDC5844A13085AD90013090E /* filters.cpp:930 */,\n\t\t\tEDC5845C13085BDA0013090E /* filters.cpp:912 */,\n\t\t\tEDC584A8130863A20013090E /* filters.cpp:985 */,\n\t\t\tEDC584AC130863FE0013090E /* filters.cpp:992 */,\n\t\t);\n\t\tcodeSenseManager = EDA5150110C72929000A4F41 /* Code sense */;\n\t\texecutables = (\n\t\t\tEDD0CD9D10C72AC200AF308F /* cufflinks */,\n\t\t\tEDD0CE2310C72F7D00AF308F /* cuffdiff */,\n\t\t\tEDD6A9D611598ABA00D3F668 /* cuffcompare */,\n\t\t\tEDD6AA241159BA2E00D3F668 /* Unit Tests */,\n\t\t\tEDD94CD31208E48B00AA1086 /* gtf_to_sam */,\n\t\t\tEDFE39CF122BE65600F24CD3 /* cuffcluster */,\n\t\t\tED41B839127602C60000B5A2 /* gtf_reads */,\n\t\t);\n\t\tperUserDictionary = {\n\t\t\t\"PBXConfiguration.PBXBreakpointsDataSource.v1:1CA23EDF0692099D00951B8B\" = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t20,\n\t\t\t\t\t20,\n\t\t\t\t\t165,\n\t\t\t\t\t20,\n\t\t\t\t\t165,\n\t\t\t\t\t165,\n\t\t\t\t\t165,\n\t\t\t\t\t20,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXBreakpointsDataSource_ActionID,\n\t\t\t\t\tPBXBreakpointsDataSource_TypeID,\n\t\t\t\t\tPBXBreakpointsDataSource_BreakpointID,\n\t\t\t\t\tPBXBreakpointsDataSource_UseID,\n\t\t\t\t\tPBXBreakpointsDataSource_LocationID,\n\t\t\t\t\tPBXBreakpointsDataSource_ConditionID,\n\t\t\t\t\tPBXBreakpointsDataSource_IgnoreCountID,\n\t\t\t\t\tPBXBreakpointsDataSource_ContinueID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t22,\n\t\t\t\t\t300,\n\t\t\t\t\t372,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXExecutablesDataSource_ActiveFlagID,\n\t\t\t\t\tPBXExecutablesDataSource_NameID,\n\t\t\t\t\tPBXExecutablesDataSource_CommentsID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t20,\n\t\t\t\t\t484,\n\t\t\t\t\t20,\n\t\t\t\t\t48,\n\t\t\t\t\t43,\n\t\t\t\t\t43,\n\t\t\t\t\t20,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXFileDataSource_FiletypeID,\n\t\t\t\t\tPBXFileDataSource_Filename_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Built_ColumnID,\n\t\t\t\t\tPBXFileDataSource_ObjectSize_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Errors_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Warnings_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Target_ColumnID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t200,\n\t\t\t\t\t750.20849609375,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXFindDataSource_MessageID,\n\t\t\t\t\tPBXFindDataSource_LocationID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.PBXSymbolsDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXSymbolsDataSource_SymbolNameID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t16,\n\t\t\t\t\t200,\n\t\t\t\t\t50,\n\t\t\t\t\t513,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXSymbolsDataSource_SymbolTypeIconID,\n\t\t\t\t\tPBXSymbolsDataSource_SymbolNameID,\n\t\t\t\t\tPBXSymbolsDataSource_SymbolTypeID,\n\t\t\t\t\tPBXSymbolsDataSource_ReferenceNameID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.XCSCMDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t20,\n\t\t\t\t\t20,\n\t\t\t\t\t815,\n\t\t\t\t\t20,\n\t\t\t\t\t48.16259765625,\n\t\t\t\t\t43,\n\t\t\t\t\t43,\n\t\t\t\t\t20,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXFileDataSource_SCM_ColumnID,\n\t\t\t\t\tPBXFileDataSource_FiletypeID,\n\t\t\t\t\tPBXFileDataSource_Filename_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Built_ColumnID,\n\t\t\t\t\tPBXFileDataSource_ObjectSize_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Errors_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Warnings_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Target_ColumnID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t20,\n\t\t\t\t\t510,\n\t\t\t\t\t60,\n\t\t\t\t\t20,\n\t\t\t\t\t48,\n\t\t\t\t\t43,\n\t\t\t\t\t43,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXFileDataSource_FiletypeID,\n\t\t\t\t\tPBXFileDataSource_Filename_ColumnID,\n\t\t\t\t\tPBXTargetDataSource_PrimaryAttribute,\n\t\t\t\t\tPBXFileDataSource_Built_ColumnID,\n\t\t\t\t\tPBXFileDataSource_ObjectSize_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Errors_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Warnings_ColumnID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXPerProjectTemplateStateSaveDate = 319308049;\n\t\t\tPBXWorkspaceStateSaveDate = 319308049;\n\t\t};\n\t\tperUserProjectItems = {\n\t\t\tED0E3EF212CB949000074D2E /* PBXTextBookmark */ = ED0E3EF212CB949000074D2E /* PBXTextBookmark */;\n\t\t\tED0E3F0712CB97B000074D2E /* PBXTextBookmark */ = ED0E3F0712CB97B000074D2E /* PBXTextBookmark */;\n\t\t\tED291363122D32B500C3703E /* PBXTextBookmark */ = ED291363122D32B500C3703E /* PBXTextBookmark */;\n\t\t\tED48339D12400ED100642337 /* PBXTextBookmark */ = ED48339D12400ED100642337 /* PBXTextBookmark */;\n\t\t\tED48351812415CA300642337 /* PBXTextBookmark */ = ED48351812415CA300642337 /* PBXTextBookmark */;\n\t\t\tED4835AE12481D1900642337 /* PBXTextBookmark */ = ED4835AE12481D1900642337 /* PBXTextBookmark */;\n\t\t\tED70726B11F79D170028F305 /* PBXTextBookmark */ = ED70726B11F79D170028F305 /* PBXTextBookmark */;\n\t\t\tED78C54112F52C6E00111993 /* PBXTextBookmark */ = ED78C54112F52C6E00111993 /* PBXTextBookmark */;\n\t\t\tED79DB8512A49C3400ABC8B3 /* PBXTextBookmark */ = ED79DB8512A49C3400ABC8B3 /* PBXTextBookmark */;\n\t\t\tED79DC1E12AC5D4E00ABC8B3 /* PBXTextBookmark */ = ED79DC1E12AC5D4E00ABC8B3 /* PBXTextBookmark */;\n\t\t\tED79DC9912AC5F1A00ABC8B3 /* PBXTextBookmark */ = ED79DC9912AC5F1A00ABC8B3 /* PBXTextBookmark */;\n\t\t\tED79DC9B12AC5F1A00ABC8B3 /* PBXTextBookmark */ = ED79DC9B12AC5F1A00ABC8B3 /* PBXTextBookmark */;\n\t\t\tED79DCB212AC629D00ABC8B3 /* PBXTextBookmark */ = ED79DCB212AC629D00ABC8B3 /* PBXTextBookmark */;\n\t\t\tED7CFAE71294286100DB052B /* PBXTextBookmark */ = ED7CFAE71294286100DB052B /* PBXTextBookmark */;\n\t\t\tED7CFAEA1294286100DB052B /* PBXTextBookmark */ = ED7CFAEA1294286100DB052B /* PBXTextBookmark */;\n\t\t\tEDA5B99312F6599F005AEC09 /* PBXTextBookmark */ = EDA5B99312F6599F005AEC09 /* PBXTextBookmark */;\n\t\t\tEDAE42851298369000F35B48 /* PBXTextBookmark */ = EDAE42851298369000F35B48 /* PBXTextBookmark */;\n\t\t\tEDBBA10211DA433F0015175B /* PBXTextBookmark */ = EDBBA10211DA433F0015175B /* PBXTextBookmark */;\n\t\t\tEDBBA3FA11DD8E140015175B /* PBXTextBookmark */ = EDBBA3FA11DD8E140015175B /* PBXTextBookmark */;\n\t\t\tEDBCDD4B1235E4090050A8E4 /* PBXTextBookmark */ = EDBCDD4B1235E4090050A8E4 /* PBXTextBookmark */;\n\t\t\tEDBCDD4D1235E4090050A8E4 /* PBXTextBookmark */ = EDBCDD4D1235E4090050A8E4 /* PBXTextBookmark */;\n\t\t\tEDBCDDFB1235EEB60050A8E4 /* PBXTextBookmark */ = EDBCDDFB1235EEB60050A8E4 /* PBXTextBookmark */;\n\t\t\tEDBCDDFC1235EEB60050A8E4 /* PBXTextBookmark */ = EDBCDDFC1235EEB60050A8E4 /* PBXTextBookmark */;\n\t\t\tEDBCDF80123721790050A8E4 /* PBXTextBookmark */ = EDBCDF80123721790050A8E4 /* PBXTextBookmark */;\n\t\t\tEDC57A9512F7CC9F00493081 /* PBXTextBookmark */ = EDC57A9512F7CC9F00493081 /* PBXTextBookmark */;\n\t\t\tEDC57AE012F7D66C00493081 /* PBXTextBookmark */ = EDC57AE012F7D66C00493081 /* PBXTextBookmark */;\n\t\t\tEDC57AF312F8580200493081 /* PBXTextBookmark */ = EDC57AF312F8580200493081 /* PBXTextBookmark */;\n\t\t\tEDC57AF612F8580200493081 /* PBXTextBookmark */ = EDC57AF612F8580200493081 /* PBXTextBookmark */;\n\t\t\tEDC57B0C12F859B500493081 /* PBXTextBookmark */ = EDC57B0C12F859B500493081 /* PBXTextBookmark */;\n\t\t\tEDC57B1212F85B6E00493081 /* PBXTextBookmark */ = EDC57B1212F85B6E00493081 /* PBXTextBookmark */;\n\t\t\tEDC58391130833E90013090E /* PBXTextBookmark */ = EDC58391130833E90013090E /* PBXTextBookmark */;\n\t\t\tEDC58392130833E90013090E /* PBXTextBookmark */ = EDC58392130833E90013090E /* PBXTextBookmark */;\n\t\t\tEDC58393130833E90013090E /* PBXTextBookmark */ = EDC58393130833E90013090E /* PBXTextBookmark */;\n\t\t\tEDC58394130833E90013090E /* PBXTextBookmark */ = EDC58394130833E90013090E /* PBXTextBookmark */;\n\t\t\tEDC583B6130845640013090E /* PBXTextBookmark */ = EDC583B6130845640013090E /* PBXTextBookmark */;\n\t\t\tEDC583B7130845640013090E /* PBXTextBookmark */ = EDC583B7130845640013090E /* PBXTextBookmark */;\n\t\t\tEDC583F0130855740013090E /* PBXTextBookmark */ = EDC583F0130855740013090E /* PBXTextBookmark */;\n\t\t\tEDC584BD130865E80013090E /* PBXTextBookmark */ = EDC584BD130865E80013090E /* PBXTextBookmark */;\n\t\t\tEDC584C5130866820013090E /* PBXTextBookmark */ = EDC584C5130866820013090E /* PBXTextBookmark */;\n\t\t\tEDC584C6130866820013090E /* PBXTextBookmark */ = EDC584C6130866820013090E /* PBXTextBookmark */;\n\t\t\tEDC584C7130866820013090E /* XCBuildMessageTextBookmark */ = EDC584C7130866820013090E /* XCBuildMessageTextBookmark */;\n\t\t\tEDC584C913087F870013090E /* PBXTextBookmark */ = EDC584C913087F870013090E /* PBXTextBookmark */;\n\t\t\tEDDBF71412D2BD4400130D8A /* PBXTextBookmark */ = EDDBF71412D2BD4400130D8A /* PBXTextBookmark */;\n\t\t\tEDDBF71512D2BD4400130D8A /* PBXTextBookmark */ = EDDBF71512D2BD4400130D8A /* PBXTextBookmark */;\n\t\t\tEDDC69911304DBC100637B75 /* PBXTextBookmark */ = EDDC69911304DBC100637B75 /* PBXTextBookmark */;\n\t\t\tEDDC69F01304E2FC00637B75 /* PBXTextBookmark */ = EDDC69F01304E2FC00637B75 /* PBXTextBookmark */;\n\t\t\tEDFDE77312BEA9100044EDD0 /* PBXTextBookmark */ = EDFDE77312BEA9100044EDD0 /* PBXTextBookmark */;\n\t\t\tEDFDE78F12BEACA20044EDD0 /* PBXTextBookmark */ = EDFDE78F12BEACA20044EDD0 /* PBXTextBookmark */;\n\t\t\tEDFE393512299AE500F24CD3 /* PBXTextBookmark */ = EDFE393512299AE500F24CD3 /* PBXTextBookmark */;\n\t\t\tEDFE3A0C122BE93000F24CD3 /* PBXTextBookmark */ = EDFE3A0C122BE93000F24CD3 /* PBXTextBookmark */;\n\t\t\tEDFE3A0D122BE93000F24CD3 /* PBXTextBookmark */ = EDFE3A0D122BE93000F24CD3 /* PBXTextBookmark */;\n\t\t\tEDFE3A5B122C04D700F24CD3 /* PBXTextBookmark */ = EDFE3A5B122C04D700F24CD3 /* PBXTextBookmark */;\n\t\t};\n\t\tsourceControlManager = EDA5150010C72929000A4F41 /* Source Control */;\n\t\tuserBuildSettings = {\n\t\t};\n\t};\n\t0A5D9A35123B5BE0002BEFD5 /* GFastaIndex.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1084, 2197}}\";\n\t\t\tsepNavSelRange = \"{1068, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1544}\";\n\t\t};\n\t};\n\t0A5D9A3F123B5BFE002BEFD5 /* GFastaIndex.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1084, 1196}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 824}\";\n\t\t};\n\t};\n\t0ACD78C612E6647B00310E07 /* update_check.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1475, 1248}}\";\n\t\t\tsepNavSelRange = \"{2052, 32}\";\n\t\t\tsepNavVisRange = \"{1052, 1451}\";\n\t\t};\n\t};\n\t8DD76F620486A84900D96B5E /* cufflinks */ = {\n\t\tactiveExec = 0;\n\t\texecutables = (\n\t\t\tEDD0CD9D10C72AC200AF308F /* cufflinks */,\n\t\t);\n\t};\n\tED0E3ED812CB937D00074D2E /* stl_iterator_base_types.h */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.h;\n\t\tname = stl_iterator_base_types.h;\n\t\tpath = \"/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_iterator_base_types.h\";\n\t\tsourceTree = \"<absolute>\";\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1002, 2210}}\";\n\t\t\tsepNavSelRange = \"{4481, 0}\";\n\t\t\tsepNavVisRange = \"{4047, 936}\";\n\t\t};\n\t};\n\tED0E3EF212CB949000074D2E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED0E3ED812CB937D00074D2E /* stl_iterator_base_types.h */;\n\t\tname = \"stl_iterator_base_types.h: 84\";\n\t\trLen = 0;\n\t\trLoc = 3524;\n\t\trType = 0;\n\t\tvrLen = 1922;\n\t\tvrLoc = 2559;\n\t};\n\tED0E3F0712CB97B000074D2E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5151E10C72963000A4F41 /* abundances.cpp */;\n\t\tname = \"abundances.cpp: 363\";\n\t\trLen = 45;\n\t\trLoc = 7849;\n\t\trType = 0;\n\t\tvrLen = 1563;\n\t\tvrLoc = 7505;\n\t};\n\tED0E3F3F12CBA86F00074D2E /* sorting_hat.cpp:725 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDFE39AF122BE4F400F24CD3 /* sorting_hat.cpp */;\n\t\tfunctionName = \"driver(FILE* fpkm_file, FILE* spec_out, FILE* row_matrix_out, FILE* row_density_out)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 725;\n\t\tlocation = cufflinks_xcode;\n\t\tmodificationTime = 319317165.204594;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tED0E3F4312CBA89F00074D2E /* sorting_hat.cpp:735 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDFE39AF122BE4F400F24CD3 /* sorting_hat.cpp */;\n\t\tfunctionName = \"driver(FILE* fpkm_file, FILE* spec_out, FILE* row_matrix_out, FILE* row_density_out)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 735;\n\t\tlocation = cufflinks_xcode;\n\t\tmodificationTime = 319317165.205203;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tED1C0C7111D7D9E500CFD663 /* ax_boost_base.m4 */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {3064, 2860}}\";\n\t\t\tsepNavSelRange = \"{3845, 13}\";\n\t\t\tsepNavVisRange = \"{2759, 1708}\";\n\t\t};\n\t};\n\tED1C0C7211D7D9E500CFD663 /* ax_boost_thread.m4 */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1860, 1872}}\";\n\t\t\tsepNavSelRange = \"{4519, 26}\";\n\t\t\tsepNavVisRange = \"{0, 1482}\";\n\t\t};\n\t};\n\tED1C0C7411D7DA3200CFD663 /* ax_bam.m4 */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {2952, 2704}}\";\n\t\t\tsepNavSelRange = \"{6426, 4}\";\n\t\t\tsepNavVisRange = \"{5471, 1174}\";\n\t\t};\n\t};\n\tED1C0CAA11D7E52400CFD663 /* ax_check_zlib.m4 */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {943, 1651}}\";\n\t\t\tsepNavSelRange = \"{4111, 0}\";\n\t\t\tsepNavVisRange = \"{2926, 1646}\";\n\t\t};\n\t};\n\tED291363122D32B500C3703E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED291364122D32B500C3703E /* bind.hpp */;\n\t\tname = \"bind.hpp: 306\";\n\t\trLen = 0;\n\t\trLoc = 7929;\n\t\trType = 0;\n\t\tvrLen = 1655;\n\t\tvrLoc = 7187;\n\t};\n\tED291364122D32B500C3703E /* bind.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = bind.hpp;\n\t\tpath = \"/usr/local/include/boost-1_41/boost/bind/bind.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED41B816127602C60000B5A2 /* gtf_reads */ = {\n\t\tactiveExec = 0;\n\t\texecutables = (\n\t\t\tED41B839127602C60000B5A2 /* gtf_reads */,\n\t\t);\n\t};\n\tED41B839127602C60000B5A2 /* gtf_reads */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t);\n\t\targumentStrings = (\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 0;\n\t\tconfigStateDict = {\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlibgmallocEnabled = 0;\n\t\tname = gtf_reads;\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t};\n\tED48339D12400ED100642337 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5150C10C72963000A4F41 /* codons.h */;\n\t\tname = \"codons.h: 1\";\n\t\trLen = 0;\n\t\trLoc = 0;\n\t\trType = 0;\n\t\tvrLen = 795;\n\t\tvrLoc = 0;\n\t};\n\tED48351812415CA300642337 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5152F10C72963000A4F41 /* gtf_tracking.cpp */;\n\t\tname = \"gtf_tracking.cpp: 458\";\n\t\trLen = 0;\n\t\trLoc = 15301;\n\t\trType = 0;\n\t\tvrLen = 1332;\n\t\tvrLoc = 14452;\n\t};\n\tED4835AE12481D1900642337 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDE78A2C11B5F4F0000F8846 /* graph_optimize.cpp */;\n\t\tname = \"graph_optimize.cpp: 691\";\n\t\trLen = 0;\n\t\trLoc = 18780;\n\t\trType = 0;\n\t\tvrLen = 1336;\n\t\tvrLoc = 2617;\n\t};\n\tED4835D81249057500642337 /* progressbar.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {728, 1131}}\";\n\t\t\tsepNavSelRange = \"{709, 8}\";\n\t\t\tsepNavVisRange = \"{395, 757}\";\n\t\t};\n\t};\n\tED70726B11F79D170028F305 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED70726C11F79D170028F305 /* vector_map.h */;\n\t\tname = \"vector_map.h: 152\";\n\t\trLen = 0;\n\t\trLoc = 4673;\n\t\trType = 0;\n\t\tvrLen = 921;\n\t\tvrLoc = 4204;\n\t};\n\tED70726C11F79D170028F305 /* vector_map.h */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.h;\n\t\tname = vector_map.h;\n\t\tpath = /Users/cole/develop/cufflinks/src/lemon/bits/vector_map.h;\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED78C54112F52C6E00111993 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDDBF70912D29DF000130D8A /* cuffcluster.cpp */;\n\t\tname = \"cuffcluster.cpp: 793\";\n\t\trLen = 0;\n\t\trLoc = 24115;\n\t\trType = 0;\n\t\tvrLen = 1037;\n\t\tvrLoc = 23577;\n\t};\n\tED79DB8512A49C3400ABC8B3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED4835D81249057500642337 /* progressbar.h */;\n\t\tname = \"progressbar.h: 39\";\n\t\trLen = 8;\n\t\trLoc = 709;\n\t\trType = 0;\n\t\tvrLen = 757;\n\t\tvrLoc = 395;\n\t};\n\tED79DC1E12AC5D4E00ABC8B3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5153010C72963000A4F41 /* hits.cpp */;\n\t\tname = \"hits.cpp: 552\";\n\t\trLen = 0;\n\t\trLoc = 13884;\n\t\trType = 0;\n\t\tvrLen = 779;\n\t\tvrLoc = 7836;\n\t};\n\tED79DC9712AC5F0900ABC8B3 /* sp_counted_base_gcc_x86.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = sp_counted_base_gcc_x86.hpp;\n\t\tpath = /Users/cole/boost_install/boost_1_41_0/./boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp;\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED79DC9912AC5F1A00ABC8B3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED79DC9A12AC5F1A00ABC8B3 /* thread.cpp */;\n\t\tname = \"thread.cpp: 184\";\n\t\trLen = 0;\n\t\trLoc = 6214;\n\t\trType = 0;\n\t\tvrLen = 704;\n\t\tvrLoc = 5786;\n\t};\n\tED79DC9A12AC5F1A00ABC8B3 /* thread.cpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.cpp;\n\t\tname = thread.cpp;\n\t\tpath = /Users/cole/boost_install/boost_1_41_0/libs/thread/src/pthread/thread.cpp;\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED79DC9B12AC5F1A00ABC8B3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED79DC9C12AC5F1A00ABC8B3 /* thread.hpp */;\n\t\tname = \"thread.hpp: 184\";\n\t\trLen = 0;\n\t\trLoc = 4934;\n\t\trType = 0;\n\t\tvrLen = 569;\n\t\tvrLoc = 4657;\n\t};\n\tED79DC9C12AC5F1A00ABC8B3 /* thread.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = thread.hpp;\n\t\tpath = /usr/local/include/boost/thread/detail/thread.hpp;\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED79DCB212AC629D00ABC8B3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED79DC9712AC5F0900ABC8B3 /* sp_counted_base_gcc_x86.hpp */;\n\t\tname = \"sp_counted_base_gcc_x86.hpp: 132\";\n\t\trLen = 0;\n\t\trLoc = 2701;\n\t\trType = 0;\n\t\tvrLen = 643;\n\t\tvrLoc = 2613;\n\t};\n\tED79DCDB12AC63F200ABC8B3 /* stl_vector.h */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.h;\n\t\tname = stl_vector.h;\n\t\tpath = \"/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_vector.h\";\n\t\tsourceTree = \"<absolute>\";\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1002, 12766}}\";\n\t\t\tsepNavSelRange = \"{16871, 0}\";\n\t\t\tsepNavVisRange = \"{16542, 887}\";\n\t\t};\n\t};\n\tED7CFAE71294286100DB052B /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7CFAE81294286100DB052B /* exceptions.hpp */;\n\t\tname = \"exceptions.hpp: 87\";\n\t\trLen = 53;\n\t\trLoc = 2928;\n\t\trType = 0;\n\t\tvrLen = 1216;\n\t\tvrLoc = 2223;\n\t};\n\tED7CFAE81294286100DB052B /* exceptions.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = exceptions.hpp;\n\t\tpath = \"/usr/local/include/boost-1_41/boost/format/exceptions.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED7CFAEA1294286100DB052B /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDBAC4C011FF5AD3002B7162 /* biascorrection.h */;\n\t\tname = \"biascorrection.h: 71\";\n\t\trLen = 0;\n\t\trLoc = 2034;\n\t\trType = 0;\n\t\tvrLen = 1171;\n\t\tvrLoc = 1468;\n\t};\n\tEDA5150010C72929000A4F41 /* Source Control */ = {\n\t\tisa = PBXSourceControlManager;\n\t\tfallbackIsa = XCSourceControlManager;\n\t\tisSCMEnabled = 0;\n\t\tscmConfiguration = {\n\t\t\trepositoryNamesForRoots = {\n\t\t\t\t\"\" = \"SR Trac\";\n\t\t\t};\n\t\t};\n\t};\n\tEDA5150110C72929000A4F41 /* Code sense */ = {\n\t\tisa = PBXCodeSenseManager;\n\t\tindexTemplatePath = \"\";\n\t};\n\tEDA5150910C72963000A4F41 /* abundances.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1118, 6045}}\";\n\t\t\tsepNavSelRange = \"{4600, 9}\";\n\t\t\tsepNavVisRange = \"{3906, 1089}\";\n\t\t};\n\t};\n\tEDA5150A10C72963000A4F41 /* assemble.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {654, 650}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 844}\";\n\t\t};\n\t};\n\tEDA5150B10C72963000A4F41 /* bundles.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1020, 8632}}\";\n\t\t\tsepNavSelRange = \"{2226, 0}\";\n\t\t\tsepNavVisRange = \"{1684, 1237}\";\n\t\t};\n\t};\n\tEDA5150C10C72963000A4F41 /* codons.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1084, 663}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 795}\";\n\t\t};\n\t};\n\tEDA5150D10C72963000A4F41 /* common.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {852, 3640}}\";\n\t\t\tsepNavSelRange = \"{7402, 0}\";\n\t\t\tsepNavVisRange = \"{5413, 1998}\";\n\t\t};\n\t};\n\tEDA5150E10C72963000A4F41 /* filters.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {662, 585}}\";\n\t\t\tsepNavSelRange = \"{928, 5}\";\n\t\t\tsepNavVisRange = \"{0, 968}\";\n\t\t};\n\t};\n\tEDA5151010C72963000A4F41 /* GBase.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1132, 5473}}\";\n\t\t\tsepNavSelRange = \"{7541, 0}\";\n\t\t\tsepNavVisRange = \"{7070, 1033}\";\n\t\t};\n\t};\n\tEDA5151210C72963000A4F41 /* genes.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1132, 2028}}\";\n\t\t\tsepNavSelRange = \"{800, 15}\";\n\t\t\tsepNavVisRange = \"{245, 1229}\";\n\t\t};\n\t};\n\tEDA5151310C72963000A4F41 /* GFaSeqGet.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {861, 1391}}\";\n\t\t\tsepNavSelRange = \"{1468, 12}\";\n\t\t\tsepNavVisRange = \"{1179, 919}\";\n\t\t};\n\t};\n\tEDA5151510C72963000A4F41 /* gff.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {747, 11011}}\";\n\t\t\tsepNavSelRange = \"{8355, 6}\";\n\t\t\tsepNavVisRange = \"{7906, 1526}\";\n\t\t};\n\t};\n\tEDA5151710C72963000A4F41 /* gtf_tracking.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {705, 15639}}\";\n\t\t\tsepNavSelRange = \"{23139, 3}\";\n\t\t\tsepNavVisRange = \"{85, 950}\";\n\t\t};\n\t};\n\tEDA5151810C72963000A4F41 /* hits.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {845, 12480}}\";\n\t\t\tsepNavSelRange = \"{3093, 8}\";\n\t\t\tsepNavVisRange = \"{2587, 821}\";\n\t\t\tsepNavWindowFrame = \"{{15, 615}, {750, 558}}\";\n\t\t};\n\t};\n\tEDA5151910C72963000A4F41 /* scaffolds.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {662, 8749}}\";\n\t\t\tsepNavSelRange = \"{4712, 6}\";\n\t\t\tsepNavVisRange = \"{4559, 841}\";\n\t\t};\n\t};\n\tEDA5151A10C72963000A4F41 /* tokenize.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {845, 719}}\";\n\t\t\tsepNavSelRange = \"{380, 0}\";\n\t\t\tsepNavVisRange = \"{0, 417}\";\n\t\t};\n\t};\n\tEDA5151B10C72963000A4F41 /* transitive_closure.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {845, 5096}}\";\n\t\t\tsepNavSelRange = \"{4199, 5}\";\n\t\t\tsepNavVisRange = \"{3205, 1910}\";\n\t\t};\n\t};\n\tEDA5151C10C72963000A4F41 /* GHash.hh */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {662, 6565}}\";\n\t\t\tsepNavSelRange = \"{4533, 5}\";\n\t\t\tsepNavVisRange = \"{3766, 1765}\";\n\t\t};\n\t};\n\tEDA5151D10C72963000A4F41 /* GList.hh */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1132, 14742}}\";\n\t\t\tsepNavSelRange = \"{20676, 0}\";\n\t\t\tsepNavVisRange = \"{20108, 862}\";\n\t\t};\n\t};\n\tEDA5151E10C72963000A4F41 /* abundances.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {880, 25415}}\";\n\t\t\tsepNavSelRange = \"{7849, 45}\";\n\t\t\tsepNavVisRange = \"{7505, 1563}\";\n\t\t};\n\t};\n\tEDA5151F10C72963000A4F41 /* assemble.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {951, 7644}}\";\n\t\t\tsepNavSelRange = \"{4744, 36}\";\n\t\t\tsepNavVisRange = \"{5633, 728}\";\n\t\t\tsepNavWindowFrame = \"{{56, 0}, {1224, 778}}\";\n\t\t};\n\t};\n\tEDA5152010C72963000A4F41 /* bundles.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1017, 20930}}\";\n\t\t\tsepNavSelRange = \"{4607, 0}\";\n\t\t\tsepNavVisRange = \"{4608, 683}\";\n\t\t};\n\t};\n\tEDA5152110C72963000A4F41 /* codons.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {845, 962}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 3657}\";\n\t\t};\n\t};\n\tEDA5152210C72963000A4F41 /* common.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {866, 4576}}\";\n\t\t\tsepNavSelRange = \"{798, 0}\";\n\t\t\tsepNavVisRange = \"{410, 1245}\";\n\t\t};\n\t};\n\tEDA5152310C72963000A4F41 /* cuffcompare.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1167, 32825}}\";\n\t\t\tsepNavSelRange = \"{11662, 0}\";\n\t\t\tsepNavVisRange = \"{10667, 2154}\";\n\t\t};\n\t};\n\tEDA5152410C72963000A4F41 /* cuffdiff.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1216, 16562}}\";\n\t\t\tsepNavSelRange = \"{13672, 19}\";\n\t\t\tsepNavVisRange = \"{13345, 770}\";\n\t\t};\n\t};\n\tEDA5152510C72963000A4F41 /* cufflinks.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1002, 17082}}\";\n\t\t\tsepNavSelRange = \"{20436, 0}\";\n\t\t\tsepNavVisRange = \"{0, 638}\";\n\t\t};\n\t};\n\tEDA5152610C72963000A4F41 /* filters.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {880, 13338}}\";\n\t\t\tsepNavSelRange = \"{28447, 0}\";\n\t\t\tsepNavVisRange = \"{27593, 1534}\";\n\t\t};\n\t};\n\tEDA5152710C72963000A4F41 /* GArgs.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {939, 3367}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{115, 1213}\";\n\t\t};\n\t};\n\tEDA5152810C72963000A4F41 /* GBase.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {846, 8008}}\";\n\t\t\tsepNavSelRange = \"{449, 37}\";\n\t\t\tsepNavVisRange = \"{353, 1048}\";\n\t\t};\n\t};\n\tEDA5152A10C72963000A4F41 /* genes.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1419, 1495}}\";\n\t\t\tsepNavSelRange = \"{2215, 9}\";\n\t\t\tsepNavVisRange = \"{408, 1088}\";\n\t\t};\n\t};\n\tEDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {939, 3848}}\";\n\t\t\tsepNavSelRange = \"{948, 12}\";\n\t\t\tsepNavVisRange = \"{1858, 1226}\";\n\t\t};\n\t};\n\tEDA5152C10C72963000A4F41 /* gff.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {943, 17147}}\";\n\t\t\tsepNavSelRange = \"{20913, 0}\";\n\t\t\tsepNavVisRange = \"{20451, 902}\";\n\t\t};\n\t};\n\tEDA5152D10C72963000A4F41 /* GStr.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {859, 16757}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 818}\";\n\t\t};\n\t};\n\tEDA5152E10C72963000A4F41 /* gtf_reads.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {670, 2353}}\";\n\t\t\tsepNavSelRange = \"{2396, 0}\";\n\t\t\tsepNavVisRange = \"{1704, 1284}\";\n\t\t};\n\t};\n\tEDA5152F10C72963000A4F41 /* gtf_tracking.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1084, 7748}}\";\n\t\t\tsepNavSelRange = \"{15301, 0}\";\n\t\t\tsepNavVisRange = \"{14452, 1332}\";\n\t\t};\n\t};\n\tEDA5153010C72963000A4F41 /* hits.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {859, 11713}}\";\n\t\t\tsepNavSelRange = \"{13884, 0}\";\n\t\t\tsepNavVisRange = \"{7836, 779}\";\n\t\t};\n\t};\n\tEDA5153110C72963000A4F41 /* scaffolds.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {951, 19591}}\";\n\t\t\tsepNavSelRange = \"{37749, 0}\";\n\t\t\tsepNavVisRange = \"{35854, 962}\";\n\t\t};\n\t};\n\tEDA5153210C72963000A4F41 /* tokenize.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {802, 764}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1223}\";\n\t\t};\n\t};\n\tEDA5B99312F6599F005AEC09 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDE78BC411B716C3000F8846 /* matching_merge.cpp */;\n\t\tname = \"matching_merge.cpp: 1\";\n\t\trLen = 0;\n\t\trLoc = 0;\n\t\trType = 0;\n\t\tvrLen = 773;\n\t\tvrLoc = 0;\n\t};\n\tEDACE430114EFF5C009024DB /* differential.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {951, 3874}}\";\n\t\t\tsepNavSelRange = \"{858, 24}\";\n\t\t\tsepNavVisRange = \"{906, 696}\";\n\t\t};\n\t};\n\tEDACE431114EFF5C009024DB /* differential.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {782, 10322}}\";\n\t\t\tsepNavSelRange = \"{771, 6}\";\n\t\t\tsepNavVisRange = \"{478, 1424}\";\n\t\t};\n\t};\n\tEDACE438114F031B009024DB /* clustering.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1084, 1885}}\";\n\t\t\tsepNavSelRange = \"{685, 0}\";\n\t\t\tsepNavVisRange = \"{2026, 1419}\";\n\t\t};\n\t};\n\tEDACE439114F031B009024DB /* clustering.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {911, 1833}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{464, 988}\";\n\t\t};\n\t};\n\tEDAE42851298369000F35B48 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */;\n\t\tname = \"biascorrection.cpp: 669\";\n\t\trLen = 0;\n\t\trLoc = 18761;\n\t\trType = 0;\n\t\tvrLen = 1361;\n\t\tvrLoc = 17949;\n\t};\n\tEDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {728, 10140}}\";\n\t\t\tsepNavSelRange = \"{18761, 0}\";\n\t\t\tsepNavVisRange = \"{17949, 1361}\";\n\t\t};\n\t};\n\tEDBAC4C011FF5AD3002B7162 /* biascorrection.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {845, 1287}}\";\n\t\t\tsepNavSelRange = \"{2034, 0}\";\n\t\t\tsepNavVisRange = \"{1468, 1171}\";\n\t\t};\n\t};\n\tEDBBA10211DA433F0015175B /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5151210C72963000A4F41 /* genes.h */;\n\t\tname = \"genes.h: 121\";\n\t\trLen = 5;\n\t\trLoc = 2683;\n\t\trType = 0;\n\t\tvrLen = 1027;\n\t\tvrLoc = 2186;\n\t};\n\tEDBBA3FA11DD8E140015175B /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5153210C72963000A4F41 /* tokenize.cpp */;\n\t\tname = \"tokenize.cpp: 1\";\n\t\trLen = 0;\n\t\trLoc = 0;\n\t\trType = 0;\n\t\tvrLen = 1223;\n\t\tvrLoc = 0;\n\t};\n\tEDBBE9C811AA3F5E006AC14A /* transitive_reduction.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {751, 1690}}\";\n\t\t\tsepNavSelRange = \"{4405, 0}\";\n\t\t\tsepNavVisRange = \"{876, 2560}\";\n\t\t};\n\t};\n\tEDBCDD4B1235E4090050A8E4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDBCDD4C1235E4090050A8E4 /* checked_delete.hpp */;\n\t\tname = \"checked_delete.hpp: 34\";\n\t\trLen = 0;\n\t\trLoc = 895;\n\t\trType = 0;\n\t\tvrLen = 614;\n\t\tvrLoc = 618;\n\t};\n\tEDBCDD4C1235E4090050A8E4 /* checked_delete.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = checked_delete.hpp;\n\t\tpath = \"/usr/local/include/boost-1_41/boost/checked_delete.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDBCDD4D1235E4090050A8E4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDBCDD4E1235E4090050A8E4 /* sp_counted_impl.hpp */;\n\t\tname = \"sp_counted_impl.hpp: 78\";\n\t\trLen = 0;\n\t\trLoc = 1917;\n\t\trType = 0;\n\t\tvrLen = 555;\n\t\tvrLoc = 1679;\n\t};\n\tEDBCDD4E1235E4090050A8E4 /* sp_counted_impl.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = sp_counted_impl.hpp;\n\t\tpath = \"/usr/local/include/boost-1_41/boost/smart_ptr/detail/sp_counted_impl.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDBCDDFB1235EEB60050A8E4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDFE38AC12298E3400F24CD3 /* sp_counted_base_gcc_x86.hpp */;\n\t\tname = \"sp_counted_base_gcc_x86.hpp: 133\";\n\t\trLen = 0;\n\t\trLoc = 2707;\n\t\trType = 0;\n\t\tvrLen = 807;\n\t\tvrLoc = 2328;\n\t};\n\tEDBCDDFC1235EEB60050A8E4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDBEA60411EA75CD00C661A7 /* shared_count.hpp */;\n\t\tname = \"shared_count.hpp: 223\";\n\t\trLen = 0;\n\t\trLoc = 4802;\n\t\trType = 0;\n\t\tvrLen = 675;\n\t\tvrLoc = 4534;\n\t};\n\tEDBCDF80123721790050A8E4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5152810C72963000A4F41 /* GBase.cpp */;\n\t\tname = \"GBase.cpp: 15\";\n\t\trLen = 37;\n\t\trLoc = 449;\n\t\trType = 0;\n\t\tvrLen = 1048;\n\t\tvrLoc = 353;\n\t};\n\tEDBEA60411EA75CD00C661A7 /* shared_count.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = shared_count.hpp;\n\t\tpath = \"/usr/local/include/boost-1_41/boost/smart_ptr/detail/shared_count.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDBEA60611EA75CD00C661A7 /* stl_iterator.h */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.h;\n\t\tname = stl_iterator.h;\n\t\tpath = \"/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_iterator.h\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDC57A9512F7CC9F00493081 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5151F10C72963000A4F41 /* assemble.cpp */;\n\t\tname = \"assemble.cpp: 201\";\n\t\trLen = 36;\n\t\trLoc = 4744;\n\t\trType = 0;\n\t\tvrLen = 1463;\n\t\tvrLoc = 4729;\n\t};\n\tEDC57AC912F7D53300493081 /* cufflinks.cpp:483 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152510C72963000A4F41 /* cufflinks.cpp */;\n\t\tfunctionName = \"pseudohits_from_ref(vector<shared_ptr<Scaffold> >& ref_scaffs, vector<Scaffold>& pseudohits, int hit_len)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 483;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.205485;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC57ACD12F7D56A00493081 /* scaffolds.cpp:539 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5153110C72963000A4F41 /* scaffolds.cpp */;\n\t\tfunctionName = \"Scaffold::sub_scaffold(Scaffold& sub_scaff, int g_left, int match_length)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 539;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.205942;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC57AE012F7D66C00493081 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDC57AE112F7D66C00493081 /* shared_ptr.hpp */;\n\t\tname = \"shared_ptr.hpp: 418\";\n\t\trLen = 0;\n\t\trLoc = 10346;\n\t\trType = 0;\n\t\tvrLen = 750;\n\t\tvrLoc = 9887;\n\t};\n\tEDC57AE112F7D66C00493081 /* shared_ptr.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = shared_ptr.hpp;\n\t\tpath = /usr/local/include/boost/smart_ptr/shared_ptr.hpp;\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDC57AE812F8578000493081 /* cufflinks.cpp:543 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152510C72963000A4F41 /* cufflinks.cpp */;\n\t\tfunctionName = \"scaffolds_for_bundle(const HitBundle& bundle, vector<shared_ptr<Scaffold> >& scaffolds, vector<shared_ptr<Scaffold> >* ref_scaffs = NULL, BundleStats* stats = NULL)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 543;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.206342;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC57AEE12F857FF00493081 /* filters.cpp:506 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"filter_hits(int bundle_length, int bundle_left, vector<Scaffold>& hits)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 506;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.206833;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC57AF312F8580200493081 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDBEA60611EA75CD00C661A7 /* stl_iterator.h */;\n\t\tname = \"stl_iterator.h: 653\";\n\t\trLen = 0;\n\t\trLoc = 20926;\n\t\trType = 0;\n\t\tvrLen = 1260;\n\t\tvrLoc = 20301;\n\t};\n\tEDC57AF612F8580200493081 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5150B10C72963000A4F41 /* bundles.h */;\n\t\tname = \"bundles.h: 82\";\n\t\trLen = 0;\n\t\trLoc = 2226;\n\t\trType = 0;\n\t\tvrLen = 1237;\n\t\tvrLoc = 1684;\n\t};\n\tEDC57B0C12F859B500493081 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5151910C72963000A4F41 /* scaffolds.h */;\n\t\tname = \"scaffolds.h: 204\";\n\t\trLen = 6;\n\t\trLoc = 4712;\n\t\trType = 0;\n\t\tvrLen = 841;\n\t\tvrLoc = 4559;\n\t};\n\tEDC57B1212F85B6E00493081 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5153110C72963000A4F41 /* scaffolds.cpp */;\n\t\tname = \"scaffolds.cpp: 1417\";\n\t\trLen = 0;\n\t\trLoc = 36434;\n\t\trType = 0;\n\t\tvrLen = 1537;\n\t\tvrLoc = 36099;\n\t};\n\tEDC58391130833E90013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDACE431114EFF5C009024DB /* differential.cpp */;\n\t\tname = \"differential.cpp: 35\";\n\t\trLen = 6;\n\t\trLoc = 771;\n\t\trType = 0;\n\t\tvrLen = 1424;\n\t\tvrLoc = 478;\n\t};\n\tEDC58392130833E90013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = 0ACD78C612E6647B00310E07 /* update_check.h */;\n\t\tname = \"update_check.h: 86\";\n\t\trLen = 32;\n\t\trLoc = 2052;\n\t\trType = 0;\n\t\tvrLen = 1451;\n\t\tvrLoc = 1052;\n\t};\n\tEDC58393130833E90013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5151510C72963000A4F41 /* gff.h */;\n\t\tname = \"gff.h: 328\";\n\t\trLen = 6;\n\t\trLoc = 8355;\n\t\trType = 0;\n\t\tvrLen = 1526;\n\t\tvrLoc = 7906;\n\t};\n\tEDC58394130833E90013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5152310C72963000A4F41 /* cuffcompare.cpp */;\n\t\trLen = 11;\n\t\trLoc = 11530;\n\t\trType = 0;\n\t};\n\tEDC583B21308455A0013090E /* cufflinks.cpp:646 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152510C72963000A4F41 /* cufflinks.cpp */;\n\t\tfunctionName = \"scaffolds_for_bundle(const HitBundle& bundle, vector<shared_ptr<Scaffold> >& scaffolds, vector<shared_ptr<Scaffold> >* ref_scaffs = NULL, BundleStats* stats = NULL)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 646;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.208697;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC583B6130845640013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5150E10C72963000A4F41 /* filters.h */;\n\t\tname = \"filters.h: 39\";\n\t\trLen = 5;\n\t\trLoc = 928;\n\t\trType = 0;\n\t\tvrLen = 968;\n\t\tvrLoc = 0;\n\t};\n\tEDC583B7130845640013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5151C10C72963000A4F41 /* GHash.hh */;\n\t\tname = \"GHash.hh: 108\";\n\t\trLen = 5;\n\t\trLoc = 4533;\n\t\trType = 0;\n\t\tvrLen = 1765;\n\t\tvrLoc = 3766;\n\t};\n\tEDC583C0130847140013090E /* filters.cpp:867 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 867;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.209119;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC583CA130853530013090E /* filters.cpp:897 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 897;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.209418;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC583F0130855740013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED79DCDB12AC63F200ABC8B3 /* stl_vector.h */;\n\t\tname = \"stl_vector.h: 478\";\n\t\trLen = 0;\n\t\trLoc = 16903;\n\t\trType = 0;\n\t\tvrLen = 1624;\n\t\tvrLoc = 16136;\n\t};\n\tEDC583F41308558F0013090E /* filters.cpp:936 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 936;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.209702;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC583FF130855D10013090E /* filters.cpp:927 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 927;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.210135;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC58405130856060013090E /* filters.cpp:916 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 916;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.210451;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC5840D130856B00013090E /* filters.cpp:931 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 931;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.210683;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC5843C130859F80013090E /* filters.cpp:894 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 894;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.210957;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC5844A13085AD90013090E /* filters.cpp:930 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 930;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.211209;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC5845C13085BDA0013090E /* filters.cpp:912 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 912;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.21152;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC584A8130863A20013090E /* filters.cpp:985 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 985;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.211774;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC584AC130863FE0013090E /* filters.cpp:992 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tfunctionName = \"clip_by_3_prime_dropoff(Scaffold& scaff)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 992;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 319317165.212033;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDC584BD130865E80013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5152610C72963000A4F41 /* filters.cpp */;\n\t\tname = \"filters.cpp: 965\";\n\t\trLen = 0;\n\t\trLoc = 28447;\n\t\trType = 0;\n\t\tvrLen = 1534;\n\t\tvrLoc = 27593;\n\t};\n\tEDC584C5130866820013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5152210C72963000A4F41 /* common.cpp */;\n\t\tname = \"common.cpp: 46\";\n\t\trLen = 0;\n\t\trLoc = 798;\n\t\trType = 0;\n\t\tvrLen = 1245;\n\t\tvrLoc = 410;\n\t};\n\tEDC584C6130866820013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5150D10C72963000A4F41 /* common.h */;\n\t\tname = \"common.h: 311\";\n\t\trLen = 0;\n\t\trLoc = 7402;\n\t\trType = 0;\n\t\tvrLen = 1998;\n\t\tvrLoc = 5413;\n\t};\n\tEDC584C7130866820013090E /* XCBuildMessageTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tcomments = \"'OPT_3_PRIME_DROPOFF_FRAC' was not declared in this scope\";\n\t\tfRef = EDA5152510C72963000A4F41 /* cufflinks.cpp */;\n\t\tfallbackIsa = XCBuildMessageTextBookmark;\n\t\trLen = 0;\n\t\trLoc = 293;\n\t\trType = 1;\n\t};\n\tEDC584C913087F870013090E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5152510C72963000A4F41 /* cufflinks.cpp */;\n\t\tname = \"cufflinks.cpp: 294\";\n\t\trLen = 0;\n\t\trLoc = 11409;\n\t\trType = 0;\n\t\tvrLen = 1066;\n\t\tvrLoc = 10672;\n\t};\n\tEDD0CD9D10C72AC200AF308F /* cufflinks */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tYES,\n\t\t\tYES,\n\t\t);\n\t\targumentStrings = (\n\t\t\t\"--max-mle-iterations 4\",\n\t\t\t\"--num-importance-samples 100\",\n\t\t\t\"-G MB8_plus_exons.cannonical_chr_names.gtf\",\n\t\t\ttsr.sam,\n\t\t\t\"-F 0.0\",\n\t\t\t\"-j 0.25\",\n\t\t\t\"-m 194\",\n\t\t\tY3_FYB.sam,\n\t\t\t\"--output-dir test_dir\",\n\t\t\t\"--collapse-thresh 30\",\n\t\t\tshort.sam,\n\t\t\t\"-m 100\",\n\t\t\t\"-j 0.05\",\n\t\t\t\"-F 0.05\",\n\t\t\tnanog.sam,\n\t\t\tY4_IL7R.sam,\n\t\t\tlong.sam,\n\t\t\tTpm3.sam,\n\t\t\tsegfault.sam,\n\t\t\tTh17_2_C6orf125.sam,\n\t\t\t\"-o perfect_abund -G mm9_chr123.gtf sim.sam\",\n\t\t\t\"-s 40\",\n\t\t\t\"-m 50\",\n\t\t\tlarge.sam,\n\t\t\t\"-G dmel-all-no-analysis-r5.12.no_ops_strand_exons.gtf\",\n\t\t\ttophat_out_090428_Graveley_lane2_accepted_hits.sam,\n\t\t\tfixed.sam,\n\t\t\tFubp1.sam,\n\t\t\tmega_bundle_2.sam,\n\t\t\tFhl3.sam,\n\t\t\tFn1.sam,\n\t\t\tmega_bundle_1.sam,\n\t\t\tNek2.sam,\n\t\t\tLypla1.sam,\n\t\t\tadipose_snippet.sam,\n\t\t\tyyy.sam,\n\t\t\t\"-s 30\",\n\t\t\tadh_cluster.sam,\n\t\t\tPfkfb2.sam,\n\t\t\tLgtn.sam,\n\t\t\t\"-G gtf4.gtf\",\n\t\t\tdelme7.sam,\n\t\t\ttophat_out/accepted_hits.bam,\n\t\t\taccepted_hits.bam,\n\t\t\tchr1_307200_308260.no_splicing.sam,\n\t\t\tchr1_307200_308260.sam,\n\t\t\tPEchr1MinQV15_15e6.sam,\n\t\t\tPEchr1MinQV15_15e6.bam,\n\t\t\t\"-o perfect_abund -G mm9_chr123.gtf -p 6 fixed.sam\",\n\t\t\t\"-G sample.gtf\",\n\t\t\t\"-s 4000\",\n\t\t\t\"-i 10\",\n\t\t\t\"-m 169\",\n\t\t\t\"-m 165\",\n\t\t\t\"-G SMTN_asm.gtf\",\n\t\t\tSMTN.bam,\n\t\t\t\"-M mask.gtf\",\n\t\t\txxx.bam,\n\t\t\t\"--library-type solid-fragment\",\n\t\t\t/Volumes/Abel/wt.sr.bam,\n\t\t\t\"-j 0.05\",\n\t\t\t\"-F 0.0\",\n\t\t\t\"-F 0.0\",\n\t\t\t\"Xist-breast.bam\",\n\t\t\t\"Xist-ovary.bam\",\n\t\t\t\"-o xxx\",\n\t\t\t\"-G Homo_sapiens.GRCh37.58.name=id.gtf chr19.sam\",\n\t\t\tIgH.bam,\n\t\t\t\"-o perfect_abund -G mm9_chr123.gtf -p 1 sim.sam\",\n\t\t\tsim.sam,\n\t\t\t\"-G hg18-refGene.gtf\",\n\t\t\tassembly.sorted.bam,\n\t\t\t\"--overhang-tolerance 150\",\n\t\t\txxx.sam,\n\t\t\tSAMD11_NOC2L.bam,\n\t\t\t\"-F 0.0\",\n\t\t\t\"-G mm9_chr123.gtf\",\n\t\t\t\"-G small.gtf\",\n\t\t\tsmall.sam,\n\t\t\t\"-G ref_genes.gtf\",\n\t\t\tsim.bam,\n\t\t\tsim.sam,\n\t\t\tadh_cluster.sam,\n\t\t\t\"-j 0.0\",\n\t\t\tTMEM161B.bam,\n\t\t\tAHNAK.sam,\n\t\t\tORM1_ORM2.bam,\n\t\t\ttiny.sam,\n\t\t\t\"--min-frags-per-transfrag 15\",\n\t\t\tsmall_solid.bam,\n\t\t\tNOC2L_solid.bam,\n\t\t\tmega_bundle.bam,\n\t\t\txxx.sam,\n\t\t\tchr1.top100k.blat.sam,\n\t\t\tO16_18.trim.bam,\n\t\t\t\"--verbose\",\n\t\t\t\"-G ginormous.100806.gtf header\",\n\t\t\t\"--min-frags-per-transfrag 0\",\n\t\t\t\"--min-intron-length 20\",\n\t\t\tatpase.sam,\n\t\t\talignments.sam,\n\t\t\tdeletions.sam,\n\t\t\tDUF221_family_protein,\n\t\t\t\"--min-frags-per-transfrag 0\",\n\t\t\t\"--library-type=fr-firststrand\",\n\t\t\t\"CTCF-locus-H1-hESC-WC-PolyA-005WC+.sam\",\n\t\t\tyyy.sam,\n\t\t\t\"-A 0.0 -j 0.0 -F 0.0 --library-type=transfrags xxx.sam\",\n\t\t\t\"-A 0.0 -j 0.0 -F 0.0 --library-type=transfrags allGTFsam_chr14.sam\",\n\t\t\t\"-G chr19_metaAsm.gtf colon_chr19.2.bam\\t\",\n\t\t\t\"-G htt.gtf htt.sam\",\n\t\t\t\"--GTF-guide 174mb.gtf 174mb.sam\",\n\t\t\t\"--trim-3-avgcov-thresh 10000.0\",\n\t\t\tGNA12.bam,\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 1;\n\t\tconfigStateDict = {\n\t\t\t\"PBXLSLaunchAction-0\" = {\n\t\t\t\tPBXLSLaunchAction = 0;\n\t\t\t\tPBXLSLaunchStartAction = 1;\n\t\t\t\tPBXLSLaunchStdioStyle = 2;\n\t\t\t\tPBXLSLaunchStyle = 0;\n\t\t\t\tclass = PBXLSRunLaunchConfig;\n\t\t\t\tcommandLineArgs = (\n\t\t\t\t);\n\t\t\t\tdisplayName = \"Executable Runner\";\n\t\t\t\tenvironment = {\n\t\t\t\t};\n\t\t\t\tidentifier = com.apple.Xcode.launch.runConfig;\n\t\t\t\tremoteHostInfo = \"\";\n\t\t\t\tstartActionInfo = \"\";\n\t\t\t};\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlibgmallocEnabled = 0;\n\t\tname = cufflinks;\n\t\tsavedGlobals = {\n\t\t};\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t\tstartupPath = /Users/cole/develop/cufflinks/tests/3prime_testing/hit_driven_0.5/GNA12;\n\t\tvariableFormatDictionary = {\n\t\t};\n\t};\n\tEDD0CE0810C72F7D00AF308F /* cuffdiff */ = {\n\t\tactiveExec = 0;\n\t\texecutables = (\n\t\t\tEDD0CE2310C72F7D00AF308F /* cuffdiff */,\n\t\t);\n\t};\n\tEDD0CE2310C72F7D00AF308F /* cuffdiff */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tYES,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t);\n\t\targumentStrings = (\n\t\t\t\"-c 10\",\n\t\t\t\"--num-importance-samples 10000\",\n\t\t\t\"--max-mle-iterations 4\",\n\t\t\t\"-c 5000 ref_genes.gtf sim.sam sim.sam\",\n\t\t\tsample1/tophat_out/accepted_hits.sam,\n\t\t\tsample2/tophat_out/accepted_hits.sam,\n\t\t\tconsensus.gtf,\n\t\t\tNeu.gtf,\n\t\t\texp.sam,\n\t\t\t60hr.sam,\n\t\t\t5day.sam,\n\t\t\t7day.sam,\n\t\t\t\"-o xxx_out\",\n\t\t\tSAA2.exon.gtf,\n\t\t\tcontrol1.sam,\n\t\t\tcontrol1.shadow.sam,\n\t\t\ttranscripts.gtf,\n\t\t\t\"SMTN.bam,SMTN.bam\",\n\t\t\t\"SMTN.bam,SMTN.bam\",\n\t\t\t\"mm9_chr123.gtf sim.sam,tmp/sim_replicate_1.sam tmp/sim_replicate_3.sam,tmp/sim_replicate_3.sam\",\n\t\t\t\" -o YYY mm9_chr123.gtf xxx.sam xxx.sam\",\n\t\t\t\"-p 1 mm9_chr123.gtf sim.sam tmp/sim_replicate_1.sam\",\n\t\t\t\"-L rep1,rep2 -o replicate_diff -p 2 ref_genes.gtf sim.sam sim.sam\",\n\t\t\t\"-c 0 --FDR 1.0 mm9_chr123.gtf xxx.sam xxx.sam\",\n\t\t\t\"mm9_chr123.gtf sim.bam sim.bam\",\n\t\t\t\"-p 2 -o replicate_diff mm9_chr123.gtf sim.sam tmp/sim_replicate_1.sam\",\n\t\t\t\"tested_transcriptome.gtf sim.sam sim.sam\",\n\t\t\t\"Ensembl.gtf adipose.bam.mitch.bam kidney.bam.mitch.bam\",\n\t\t\t\"Ensembl.gtf adipose.bam.mitch.bam kidney.bam.mitch.bam skeletal-muscle.bam.mitch.bam adrenal.bam.mitch.bam liver.bam.mitch.bam testes.bam.mitch.bam brain.bam.mitch.bam lung.bam.mitch.bam thyroid.bam.mitch.bam breast.bam.mitch.bam lymph-node.bam.mitch.bam white-blood-cells.bam.mitch.bam colon.bam.mitch.bam ovary.bam.mitch.bam heart.bam.mitch.bam prostate.bam.mitch.bam\",\n\t\t\t\"--min-alignment-count 100 Vkorc1.gtf BAT_D0_Vkorc1.bam BAT_D8_Vkorc1.bam\",\n\t\t\t\"-c 100 AK079912.1.gtf AK079912_Sub_D0.bam  AK079912_Sub_D8.bam\",\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 1;\n\t\tconfigStateDict = {\n\t\t\t\"PBXLSLaunchAction-0\" = {\n\t\t\t\tPBXLSLaunchAction = 0;\n\t\t\t\tPBXLSLaunchStartAction = 1;\n\t\t\t\tPBXLSLaunchStdioStyle = 2;\n\t\t\t\tPBXLSLaunchStyle = 0;\n\t\t\t\tclass = PBXLSRunLaunchConfig;\n\t\t\t\tcommandLineArgs = (\n\t\t\t\t);\n\t\t\t\tdisplayName = \"Executable Runner\";\n\t\t\t\tenvironment = {\n\t\t\t\t};\n\t\t\t\tidentifier = com.apple.Xcode.launch.runConfig;\n\t\t\t\tremoteHostInfo = \"\";\n\t\t\t\tstartActionInfo = \"\";\n\t\t\t};\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlibgmallocEnabled = 0;\n\t\tname = cuffdiff;\n\t\tsavedGlobals = {\n\t\t};\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t\tstartupPath = \"/Users/cole/develop/simulations/RNA-Seq/mm9_small\";\n\t\tvariableFormatDictionary = {\n\t\t};\n\t};\n\tEDD6A7A0115562EE00D3F668 /* Makefile.am */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {662, 1820}}\";\n\t\t\tsepNavSelRange = \"{2798, 0}\";\n\t\t\tsepNavVisRange = \"{1957, 1171}\";\n\t\t};\n\t};\n\tEDD6A9BA11598AB900D3F668 /* cuffcompare */ = {\n\t\tactiveExec = 0;\n\t\texecutables = (\n\t\t\tEDD6A9D611598ABA00D3F668 /* cuffcompare */,\n\t\t);\n\t};\n\tEDD6A9D611598ABA00D3F668 /* cuffcompare */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tYES,\n\t\t);\n\t\targumentStrings = (\n\t\t\t\"-r NCBI36.48.short.gtf\",\n\t\t\tNCBI36.48.short.gtf,\n\t\t\ty1_short.gtf,\n\t\t\ty2_short.gtf,\n\t\t\t\"-r  MB8_plus_exons.cannonical_chr_names.gtf\",\n\t\t\ttranscripts.gtf,\n\t\t\t\"-r gencode_v4.annotation.GRCh37.gtf -s ./  -o pooled -d 600 lymph-node.gtf\",\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 1;\n\t\tconfigStateDict = {\n\t\t\t\"PBXLSLaunchAction-0\" = {\n\t\t\t\tPBXLSLaunchAction = 0;\n\t\t\t\tPBXLSLaunchStartAction = 1;\n\t\t\t\tPBXLSLaunchStdioStyle = 2;\n\t\t\t\tPBXLSLaunchStyle = 0;\n\t\t\t\tclass = PBXLSRunLaunchConfig;\n\t\t\t\tcommandLineArgs = (\n\t\t\t\t);\n\t\t\t\tdisplayName = \"Executable Runner\";\n\t\t\t\tenvironment = {\n\t\t\t\t};\n\t\t\t\tidentifier = com.apple.Xcode.launch.runConfig;\n\t\t\t\tremoteHostInfo = \"\";\n\t\t\t\tstartActionInfo = \"\";\n\t\t\t};\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlibgmallocEnabled = 0;\n\t\tname = cuffcompare;\n\t\tsavedGlobals = {\n\t\t};\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t\tstartupPath = /Users/cole/tmp;\n\t\tvariableFormatDictionary = {\n\t\t};\n\t};\n\tEDD6AA221159BA2E00D3F668 /* Unit Tests */ = {\n\t\tactiveExec = 0;\n\t\texecutables = (\n\t\t\tEDD6AA241159BA2E00D3F668 /* Unit Tests */,\n\t\t);\n\t};\n\tEDD6AA241159BA2E00D3F668 /* Unit Tests */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t);\n\t\targumentStrings = (\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 1;\n\t\tconfigStateDict = {\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlibgmallocEnabled = 0;\n\t\tname = \"Unit Tests\";\n\t\tsavedGlobals = {\n\t\t};\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t};\n\tEDD6AA461159BE6500D3F668 /* test_abundances.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {859, 358}}\";\n\t\t\tsepNavSelRange = \"{147, 0}\";\n\t\t\tsepNavVisRange = \"{0, 150}\";\n\t\t};\n\t};\n\tEDD6AA471159BE6500D3F668 /* test_main.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {914, 4615}}\";\n\t\t\tsepNavSelRange = \"{1018, 0}\";\n\t\t\tsepNavVisRange = \"{352, 1162}\";\n\t\t};\n\t};\n\tEDD94B461205C9E800AA1086 /* gtf_to_sam */ = {\n\t\tactiveExec = 0;\n\t\texecutables = (\n\t\t\tEDD94CD31208E48B00AA1086 /* gtf_to_sam */,\n\t\t);\n\t};\n\tEDD94B711205CAF400AA1086 /* gtf_to_sam.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1069, 3146}}\";\n\t\t\tsepNavSelRange = \"{3814, 12}\";\n\t\t\tsepNavVisRange = \"{3290, 801}\";\n\t\t};\n\t};\n\tEDD94CD31208E48B00AA1086 /* gtf_to_sam */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t);\n\t\targumentStrings = (\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 1;\n\t\tconfigStateDict = {\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlibgmallocEnabled = 0;\n\t\tname = gtf_to_sam;\n\t\tsavedGlobals = {\n\t\t};\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t};\n\tEDDBF70912D29DF000130D8A /* cuffcluster.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1090, 12142}}\";\n\t\t\tsepNavSelRange = \"{24115, 0}\";\n\t\t\tsepNavVisRange = \"{23577, 1037}\";\n\t\t};\n\t};\n\tEDDBF71412D2BD4400130D8A /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDFE39FA122BE7B700F24CD3 /* jensen_shannon.cpp */;\n\t\tname = \"jensen_shannon.cpp: 92\";\n\t\trLen = 0;\n\t\trLoc = 2132;\n\t\trType = 0;\n\t\tvrLen = 955;\n\t\tvrLoc = 1806;\n\t};\n\tEDDBF71512D2BD4400130D8A /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDEBCDF8112DFD7600E2479E /* configure.ac */;\n\t\tname = \"configure.ac: 7\";\n\t\trLen = 0;\n\t\trLoc = 213;\n\t\trType = 0;\n\t\tvrLen = 857;\n\t\tvrLoc = 0;\n\t};\n\tEDDC69911304DBC100637B75 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDD6A7A0115562EE00D3F668 /* Makefile.am */;\n\t\tname = \"Makefile.am: 133\";\n\t\trLen = 0;\n\t\trLoc = 2798;\n\t\trType = 0;\n\t\tvrLen = 1171;\n\t\tvrLoc = 1957;\n\t};\n\tEDDC69AA1304DCE000637B75 /* cuffdiff.cpp:435 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152410C72963000A4F41 /* cuffdiff.cpp */;\n\t\tfunctionName = \"fdr_significance(double fdr, vector<SampleDifference*>& tests)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 435;\n\t\tlocation = cuffdiff;\n\t\tmodificationTime = 319317165.207273;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDDC69BF1304DEF800637B75 /* cuffdiff.cpp:458 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152410C72963000A4F41 /* cuffdiff.cpp */;\n\t\tfunctionName = \"fdr_significance(double fdr, vector<SampleDifference*>& tests)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 458;\n\t\tmodificationTime = 319317165.207641;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 0;\n\t};\n\tEDDC69C51304DF9000637B75 /* cuffdiff.cpp:452 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDA5152410C72963000A4F41 /* cuffdiff.cpp */;\n\t\tfunctionName = \"fdr_significance(double fdr, vector<SampleDifference*>& tests)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 452;\n\t\tmodificationTime = 319317165.207932;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 0;\n\t};\n\tEDDC69D41304E09600637B75 /* differential.cpp:28 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDACE431114EFF5C009024DB /* differential.cpp */;\n\t\tfunctionName = \"test_diffexp(const FPKMContext& curr, const FPKMContext& prev, SampleDifference& test)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 28;\n\t\tlocation = cuffdiff;\n\t\tmodificationTime = 319317165.208195;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDDC69EC1304E2C600637B75 /* differential.cpp:35 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDACE431114EFF5C009024DB /* differential.cpp */;\n\t\tfunctionName = \"test_diffexp(const FPKMContext& curr, const FPKMContext& prev, SampleDifference& test)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 35;\n\t\tlocation = cuffdiff;\n\t\tmodificationTime = 319317165.208446;\n\t\toriginalNumberOfMultipleMatches = 1;\n\t\tstate = 2;\n\t};\n\tEDDC69F01304E2FC00637B75 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5152410C72963000A4F41 /* cuffdiff.cpp */;\n\t\tname = \"cuffdiff.cpp: 452\";\n\t\trLen = 19;\n\t\trLoc = 13672;\n\t\trType = 0;\n\t\tvrLen = 870;\n\t\tvrLoc = 13185;\n\t};\n\tEDE78A2B11B5F4F0000F8846 /* graph_optimize.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {976, 1235}}\";\n\t\t\tsepNavSelRange = \"{2174, 30}\";\n\t\t\tsepNavVisRange = \"{1179, 1378}\";\n\t\t};\n\t};\n\tEDE78A2C11B5F4F0000F8846 /* graph_optimize.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1373, 9555}}\";\n\t\t\tsepNavSelRange = \"{18780, 0}\";\n\t\t\tsepNavVisRange = \"{2854, 910}\";\n\t\t\tsepNavWindowFrame = \"{{58, 0}, {1222, 778}}\";\n\t\t};\n\t};\n\tEDE78A7811B6E912000F8846 /* scaffold_graph.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {996, 697}}\";\n\t\t\tsepNavSelRange = \"{372, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1012}\";\n\t\t};\n\t};\n\tEDE78A7911B6E912000F8846 /* scaffold_graph.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1132, 4095}}\";\n\t\t\tsepNavSelRange = \"{3213, 5}\";\n\t\t\tsepNavVisRange = \"{2490, 1557}\";\n\t\t};\n\t};\n\tEDE78BC411B716C3000F8846 /* matching_merge.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {662, 1352}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 773}\";\n\t\t};\n\t};\n\tEDE78BC511B716C3000F8846 /* matching_merge.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {654, 1482}}\";\n\t\t\tsepNavSelRange = \"{2680, 14}\";\n\t\t\tsepNavVisRange = \"{1739, 1080}\";\n\t\t};\n\t};\n\tEDEBCDF8112DFD7600E2479E /* configure.ac */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {728, 1937}}\";\n\t\t\tsepNavSelRange = \"{213, 0}\";\n\t\t\tsepNavVisRange = \"{0, 857}\";\n\t\t};\n\t};\n\tEDFDE77312BEA9100044EDD0 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDACE430114EFF5C009024DB /* differential.h */;\n\t\tname = \"differential.h: 130\";\n\t\trLen = 8;\n\t\trLoc = 2989;\n\t\trType = 0;\n\t\tvrLen = 1063;\n\t\tvrLoc = 2462;\n\t};\n\tEDFDE78F12BEACA20044EDD0 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5152010C72963000A4F41 /* bundles.cpp */;\n\t\tname = \"bundles.cpp: 189\";\n\t\trLen = 0;\n\t\trLoc = 4607;\n\t\trType = 0;\n\t\tvrLen = 872;\n\t\tvrLoc = 5236;\n\t};\n\tEDFE38AC12298E3400F24CD3 /* sp_counted_base_gcc_x86.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = sp_counted_base_gcc_x86.hpp;\n\t\tpath = \"/usr/local/include/boost-1_41/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDFE393512299AE500F24CD3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5151B10C72963000A4F41 /* transitive_closure.h */;\n\t\tname = \"transitive_closure.h: 136\";\n\t\trLen = 5;\n\t\trLoc = 4199;\n\t\trType = 0;\n\t\tvrLen = 1910;\n\t\tvrLoc = 3205;\n\t};\n\tEDFE39AF122BE4F400F24CD3 /* sorting_hat.cpp */ = {\n\t\tisa = PBXFileReference;\n\t\tfileEncoding = 4;\n\t\tlastKnownFileType = sourcecode.cpp.cpp;\n\t\tname = sorting_hat.cpp;\n\t\tpath = /Users/cole/develop/cufflinks/src/sorting_hat.cpp;\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDFE39B0122BE65600F24CD3 /* cuffcluster */ = {\n\t\tactiveExec = 0;\n\t\texecutables = (\n\t\t\tEDFE39CF122BE65600F24CD3 /* cuffcluster */,\n\t\t);\n\t};\n\tEDFE39CF122BE65600F24CD3 /* cuffcluster */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t\tNO,\n\t\t\tYES,\n\t\t\tYES,\n\t\t\tYES,\n\t\t\tYES,\n\t\t\tYES,\n\t\t\tNO,\n\t\t\tNO,\n\t\t);\n\t\targumentStrings = (\n\t\t\t\"--log-fpkm\",\n\t\t\t\"--max-iterations 150\",\n\t\t\t\"-k 3\",\n\t\t\t\"--row-densities 2cond.densities\",\n\t\t\t2cond.fpkm_tracking,\n\t\t\t2cond.sorting_hat_out,\n\t\t\txxx.fpkm_tracking,\n\t\t\txxx.sorting_hat_out,\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 1;\n\t\tconfigStateDict = {\n\t\t\t\"PBXLSLaunchAction-0\" = {\n\t\t\t\tPBXLSLaunchAction = 0;\n\t\t\t\tPBXLSLaunchStartAction = 1;\n\t\t\t\tPBXLSLaunchStdioStyle = 2;\n\t\t\t\tPBXLSLaunchStyle = 0;\n\t\t\t\tclass = PBXLSRunLaunchConfig;\n\t\t\t\tcommandLineArgs = (\n\t\t\t\t);\n\t\t\t\tdisplayName = \"Executable Runner\";\n\t\t\t\tenvironment = {\n\t\t\t\t};\n\t\t\t\tidentifier = com.apple.Xcode.launch.runConfig;\n\t\t\t\tremoteHostInfo = \"\";\n\t\t\t\tstartActionInfo = \"\";\n\t\t\t};\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlibgmallocEnabled = 0;\n\t\tname = cuffcluster;\n\t\tsavedGlobals = {\n\t\t};\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t\tstartupPath = \"/Users/cole/projects/Clone Wars/linc_db2_expression\";\n\t\tvariableFormatDictionary = {\n\t\t};\n\t};\n\tEDFE39FA122BE7B700F24CD3 /* jensen_shannon.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {728, 2288}}\";\n\t\t\tsepNavSelRange = \"{2132, 0}\";\n\t\t\tsepNavVisRange = \"{1806, 955}\";\n\t\t};\n\t};\n\tEDFE39FD122BE7CB00F24CD3 /* jensen_shannon.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {845, 606}}\";\n\t\t\tsepNavSelRange = \"{383, 0}\";\n\t\t\tsepNavVisRange = \"{0, 832}\";\n\t\t};\n\t};\n\tEDFE3A0C122BE93000F24CD3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5152110C72963000A4F41 /* codons.cpp */;\n\t\tname = \"codons.cpp: 1\";\n\t\trLen = 0;\n\t\trLoc = 0;\n\t\trType = 0;\n\t\tvrLen = 3657;\n\t\tvrLoc = 0;\n\t};\n\tEDFE3A0D122BE93000F24CD3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA5151A10C72963000A4F41 /* tokenize.h */;\n\t\tname = \"tokenize.h: 17\";\n\t\trLen = 0;\n\t\trLoc = 380;\n\t\trType = 0;\n\t\tvrLen = 417;\n\t\tvrLoc = 0;\n\t};\n\tEDFE3A5B122C04D700F24CD3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDFE39FD122BE7CB00F24CD3 /* jensen_shannon.h */;\n\t\tname = \"jensen_shannon.h: 18\";\n\t\trLen = 0;\n\t\trLoc = 383;\n\t\trType = 0;\n\t\tvrLen = 832;\n\t\tvrLoc = 0;\n\t};\n}\n"
  },
  {
    "path": "cufflinks.xcodeproj/cole.perspectivev3",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>ActivePerspectiveName</key>\n\t<string>Project</string>\n\t<key>AllowedModules</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXSmartGroupTreeModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Groups and Files Outline View</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Editor</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>XCTaskListModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Task List</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>XCDetailModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>File and Smart Group Detail Viewer</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>1</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXBuildResultsModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Detailed Build Results Viewer</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>1</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXProjectFindModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Project Batch Find Tool</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>XCProjectFormatConflictsModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Project Format Conflicts List</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXBookmarksModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Bookmarks Tool</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXClassBrowserModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Class Browser</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXCVSModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Source Code Control Tool</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXDebugBreakpointsModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debug Breakpoints Tool</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>XCDockableInspector</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Inspector</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXOpenQuicklyModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Open Quickly Tool</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>1</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debugger</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>1</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXDebugCLIModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debug Console</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>XCSnapshotModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Snapshots Tool</string>\n\t\t</dict>\n\t</array>\n\t<key>BundlePath</key>\n\t<string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string>\n\t<key>Description</key>\n\t<string>AIODescriptionKey</string>\n\t<key>DockingSystemVisible</key>\n\t<false/>\n\t<key>Extension</key>\n\t<string>perspectivev3</string>\n\t<key>FavBarConfig</key>\n\t<dict>\n\t\t<key>PBXProjectModuleGUID</key>\n\t\t<string>EDA514FF10C72929000A4F41</string>\n\t\t<key>XCBarModuleItemNames</key>\n\t\t<dict/>\n\t\t<key>XCBarModuleItems</key>\n\t\t<array/>\n\t</dict>\n\t<key>FirstTimeWindowDisplayed</key>\n\t<false/>\n\t<key>Identifier</key>\n\t<string>com.apple.perspectives.project.defaultV3</string>\n\t<key>MajorVersion</key>\n\t<integer>34</integer>\n\t<key>MinorVersion</key>\n\t<integer>0</integer>\n\t<key>Name</key>\n\t<string>All-In-One</string>\n\t<key>Notifications</key>\n\t<array/>\n\t<key>OpenEditors</key>\n\t<array/>\n\t<key>PerspectiveWidths</key>\n\t<array>\n\t\t<integer>1063</integer>\n\t\t<integer>1063</integer>\n\t</array>\n\t<key>Perspectives</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>ChosenToolbarItems</key>\n\t\t\t<array>\n\t\t\t\t<string>XCToolbarPerspectiveControl</string>\n\t\t\t\t<string>NSToolbarSeparatorItem</string>\n\t\t\t\t<string>active-combo-popup</string>\n\t\t\t\t<string>action</string>\n\t\t\t\t<string>active-architecture-popup</string>\n\t\t\t\t<string>active-executable-popup</string>\n\t\t\t\t<string>NSToolbarFlexibleSpaceItem</string>\n\t\t\t\t<string>debugger-enable-breakpoints</string>\n\t\t\t\t<string>build-and-go</string>\n\t\t\t\t<string>com.apple.ide.PBXToolbarStopButton</string>\n\t\t\t\t<string>get-info</string>\n\t\t\t\t<string>NSToolbarFlexibleSpaceItem</string>\n\t\t\t\t<string>com.apple.pbx.toolbar.searchfield</string>\n\t\t\t</array>\n\t\t\t<key>ControllerClassBaseName</key>\n\t\t\t<string></string>\n\t\t\t<key>IconName</key>\n\t\t\t<string>WindowOfProject</string>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>perspective.project</string>\n\t\t\t<key>IsVertical</key>\n\t\t\t<false/>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>PBXBottomSmartGroupGIDs</key>\n\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t<string>1C37FBAC04509CD000000102</string>\n\t\t\t\t\t\t\t<string>1C37FAAC04509CD000000102</string>\n\t\t\t\t\t\t\t<string>1C37FABC05509CD000000102</string>\n\t\t\t\t\t\t\t<string>1C37FABC05539CD112110102</string>\n\t\t\t\t\t\t\t<string>E2644B35053B69B200211256</string>\n\t\t\t\t\t\t\t<string>1C37FABC04509CD000100104</string>\n\t\t\t\t\t\t\t<string>1CC0EA4004350EF90044410B</string>\n\t\t\t\t\t\t\t<string>1CC0EA4004350EF90041110B</string>\n\t\t\t\t\t\t\t<string>1C77FABC04509CD000000102</string>\n\t\t\t\t\t\t</array>\n\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t<string>1CA23ED40692098700951B8B</string>\n\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t<string>Files</string>\n\t\t\t\t\t\t<key>PBXProjectStructureProvided</key>\n\t\t\t\t\t\t<string>yes</string>\n\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnData</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<real>267</real>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<string>MainColumn</string>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<string>08FB7794FE84155DC02AAC07</string>\n\t\t\t\t\t\t\t\t<string>0A25E74A1242E9270080BEA9</string>\n\t\t\t\t\t\t\t\t<string>ED1C0C6D11D7D9C000CFD663</string>\n\t\t\t\t\t\t\t\t<string>C6859E8C029090F304C91782</string>\n\t\t\t\t\t\t\t\t<string>1C37FBAC04509CD000000102</string>\n\t\t\t\t\t\t\t\t<string>1C37FAAC04509CD000000102</string>\n\t\t\t\t\t\t\t\t<string>1C77FABC04509CD000000102</string>\n\t\t\t\t\t\t\t\t<string>1C3E0DCA080725EA00A55177</string>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<integer>23</integer>\n\t\t\t\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>\n\t\t\t\t\t\t\t<string>{{0, 300}, {267, 914}}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>PBXTopSmartGroupGIDs</key>\n\t\t\t\t\t\t<array/>\n\t\t\t\t\t\t<key>XCIncludePerspectivesSwitch</key>\n\t\t\t\t\t\t<false/>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t<string>{{0, 0}, {284, 932}}</string>\n\t\t\t\t\t\t<key>GroupTreeTableConfiguration</key>\n\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t<string>MainColumn</string>\n\t\t\t\t\t\t\t<real>267</real>\n\t\t\t\t\t\t</array>\n\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t<string>469 55 1063 973 0 0 1680 1028 </string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t<string>PBXSmartGroupTreeModule</string>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>284pt</string>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<true/>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>EDA514FA10C72929000A4F41</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>cufflinks.cpp</string>\n\t\t\t\t\t\t\t\t<key>PBXSplitModuleInNavigatorKey</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>Split0</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>EDA514FB10C72929000A4F41</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>cufflinks.cpp</string>\n\t\t\t\t\t\t\t\t\t\t<key>_historyCapacity</key>\n\t\t\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t\t\t<key>bookmark</key>\n\t\t\t\t\t\t\t\t\t\t<string>EDC584C913087F870013090E</string>\n\t\t\t\t\t\t\t\t\t\t<key>history</key>\n\t\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDBBA10211DA433F0015175B</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDBBA3FA11DD8E140015175B</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED70726B11F79D170028F305</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDFE393512299AE500F24CD3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDFE3A0C122BE93000F24CD3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDFE3A0D122BE93000F24CD3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDFE3A5B122C04D700F24CD3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED291363122D32B500C3703E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDBCDD4B1235E4090050A8E4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDBCDD4D1235E4090050A8E4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDBCDDFB1235EEB60050A8E4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDBCDDFC1235EEB60050A8E4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDBCDF80123721790050A8E4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED48339D12400ED100642337</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED48351812415CA300642337</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED4835AE12481D1900642337</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED7CFAE71294286100DB052B</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED7CFAEA1294286100DB052B</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDAE42851298369000F35B48</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED79DB8512A49C3400ABC8B3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED79DC1E12AC5D4E00ABC8B3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED79DC9912AC5F1A00ABC8B3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED79DC9B12AC5F1A00ABC8B3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED79DCB212AC629D00ABC8B3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDFDE77312BEA9100044EDD0</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDFDE78F12BEACA20044EDD0</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0E3EF212CB949000074D2E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0E3F0712CB97B000074D2E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDDBF71412D2BD4400130D8A</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDDBF71512D2BD4400130D8A</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDA5B99312F6599F005AEC09</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED78C54112F52C6E00111993</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC57A9512F7CC9F00493081</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC57AE012F7D66C00493081</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC57AF312F8580200493081</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC57AF612F8580200493081</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC57B0C12F859B500493081</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC57B1212F85B6E00493081</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDDC69911304DBC100637B75</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDDC69F01304E2FC00637B75</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC58391130833E90013090E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC58392130833E90013090E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC58393130833E90013090E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC58394130833E90013090E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC583B6130845640013090E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC583B7130845640013090E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC583F0130855740013090E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC584BD130865E80013090E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC584C5130866820013090E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC584C6130866820013090E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDC584C7130866820013090E</string>\n\t\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>SplitCount</key>\n\t\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>StatusBarVisibility</key>\n\t\t\t\t\t\t\t\t<true/>\n\t\t\t\t\t\t\t\t<key>XCSharingToken</key>\n\t\t\t\t\t\t\t\t<string>com.apple.Xcode.CommonNavigatorGroupSharingToken</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {774, 691}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>469 55 1063 973 0 0 1680 1028 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>691pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>236pt</string>\n\t\t\t\t\t\t\t<key>Tabs</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1CA23EDF0692099D00951B8B</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>Detail</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t\t\t<string>{{10, 27}, {723, 209}}</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t\t\t<string>XCDetailModule</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1CA23EE00692099D00951B8B</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>Project Find</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t\t\t<string>{{10, 27}, {774, 209}}</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t\t\t<string>PBXProjectFindModule</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXCVSModuleFilterTypeKey</key>\n\t\t\t\t\t\t\t\t\t\t<integer>1032</integer>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1CA23EE10692099D00951B8B</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>SCM Results</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t\t\t<string>{{10, 27}, {1002, 287}}</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t\t\t<string>PBXCVSModule</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>XCMainBuildResultsModuleGUID</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>Build Results</string>\n\t\t\t\t\t\t\t\t\t\t<key>XCBuildResultsTrigger_Collapse</key>\n\t\t\t\t\t\t\t\t\t\t<integer>1021</integer>\n\t\t\t\t\t\t\t\t\t\t<key>XCBuildResultsTrigger_Open</key>\n\t\t\t\t\t\t\t\t\t\t<integer>1011</integer>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t\t\t<string>{{10, 27}, {774, 209}}</string>\n\t\t\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t\t\t<string>469 55 1063 973 0 0 1680 1028 </string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t\t\t<string>PBXBuildResultsModule</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>774pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Project</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>XCModuleDock</string>\n\t\t\t\t<string>PBXSmartGroupTreeModule</string>\n\t\t\t\t<string>XCModuleDock</string>\n\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t<string>XCDockableTabModule</string>\n\t\t\t\t<string>XCDetailModule</string>\n\t\t\t\t<string>PBXProjectFindModule</string>\n\t\t\t\t<string>PBXCVSModule</string>\n\t\t\t\t<string>PBXBuildResultsModule</string>\n\t\t\t</array>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>EDC583AB1308445A0013090E</string>\n\t\t\t\t<string>1CA23ED40692098700951B8B</string>\n\t\t\t\t<string>EDC583AC1308445A0013090E</string>\n\t\t\t\t<string>EDA514FA10C72929000A4F41</string>\n\t\t\t\t<string>EDC583AD1308445A0013090E</string>\n\t\t\t\t<string>1CA23EDF0692099D00951B8B</string>\n\t\t\t\t<string>1CA23EE00692099D00951B8B</string>\n\t\t\t\t<string>1CA23EE10692099D00951B8B</string>\n\t\t\t\t<string>XCMainBuildResultsModuleGUID</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfigUserDefaultsMinorVersion</key>\n\t\t\t<string>2</string>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.defaultV3</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>ChosenToolbarItems</key>\n\t\t\t<array>\n\t\t\t\t<string>XCToolbarPerspectiveControl</string>\n\t\t\t\t<string>NSToolbarSeparatorItem</string>\n\t\t\t\t<string>active-combo-popup</string>\n\t\t\t\t<string>NSToolbarFlexibleSpaceItem</string>\n\t\t\t\t<string>debugger-enable-breakpoints</string>\n\t\t\t\t<string>build-and-go</string>\n\t\t\t\t<string>com.apple.ide.PBXToolbarStopButton</string>\n\t\t\t\t<string>debugger-restart-executable</string>\n\t\t\t\t<string>debugger-pause</string>\n\t\t\t\t<string>debugger-step-over</string>\n\t\t\t\t<string>debugger-step-into</string>\n\t\t\t\t<string>debugger-step-out</string>\n\t\t\t\t<string>NSToolbarFlexibleSpaceItem</string>\n\t\t\t\t<string>servicesModulebreakpoints</string>\n\t\t\t\t<string>debugger-show-console-window</string>\n\t\t\t</array>\n\t\t\t<key>ControllerClassBaseName</key>\n\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t<key>IconName</key>\n\t\t\t<string>DebugTabIcon</string>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>perspective.debug</string>\n\t\t\t<key>IsVertical</key>\n\t\t\t<true/>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t<string>1CCC7628064C1048000F2A68</string>\n\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t<string>Debugger Console</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t<string>{{0, 0}, {1063, 267}}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t<string>PBXDebugCLIModule</string>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>267pt</string>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Debugger</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HorizontalSplitView</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>_collapsingFrameDimension</key>\n\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t<key>_indexOfCollapsedView</key>\n\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t<key>_percentageOfCollapsedView</key>\n\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t<key>isCollapsed</key>\n\t\t\t\t\t\t\t\t<string>yes</string>\n\t\t\t\t\t\t\t\t<key>sizes</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {498, 411}}</string>\n\t\t\t\t\t\t\t\t\t<string>{{498, 0}, {565, 411}}</string>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>VerticalSplitView</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>_collapsingFrameDimension</key>\n\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t<key>_indexOfCollapsedView</key>\n\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t<key>_percentageOfCollapsedView</key>\n\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t<key>isCollapsed</key>\n\t\t\t\t\t\t\t\t<string>yes</string>\n\t\t\t\t\t\t\t\t<key>sizes</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {1063, 411}}</string>\n\t\t\t\t\t\t\t\t\t<string>{{0, 411}, {1063, 310}}</string>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>LauncherConfigVersion</key>\n\t\t\t\t\t\t<string>8</string>\n\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t<string>1CCC7629064C1048000F2A68</string>\n\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t<string>Debug</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>DebugConsoleVisible</key>\n\t\t\t\t\t\t<string>None</string>\n\t\t\t\t\t\t<key>DebugConsoleWindowFrame</key>\n\t\t\t\t\t\t<string>{{200, 200}, {500, 300}}</string>\n\t\t\t\t\t\t<key>DebugSTDIOWindowFrame</key>\n\t\t\t\t\t\t<string>{{200, 200}, {500, 300}}</string>\n\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t<string>{{0, 272}, {1063, 721}}</string>\n\t\t\t\t\t\t<key>PBXDebugSessionStackFrameViewKey</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>DebugVariablesTableConfiguration</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<string>Name</string>\n\t\t\t\t\t\t\t\t<real>235</real>\n\t\t\t\t\t\t\t\t<string>Value</string>\n\t\t\t\t\t\t\t\t<real>85</real>\n\t\t\t\t\t\t\t\t<string>Summary</string>\n\t\t\t\t\t\t\t\t<real>220</real>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t<string>{{498, 0}, {565, 411}}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>721pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debug</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>XCModuleDock</string>\n\t\t\t\t<string>PBXDebugCLIModule</string>\n\t\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t\t<string>PBXDebugProcessAndThreadModule</string>\n\t\t\t\t<string>PBXDebugProcessViewModule</string>\n\t\t\t\t<string>PBXDebugThreadViewModule</string>\n\t\t\t\t<string>PBXDebugStackFrameViewModule</string>\n\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t</array>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>EDC583F7130855A90013090E</string>\n\t\t\t\t<string>1CCC7628064C1048000F2A68</string>\n\t\t\t\t<string>1CCC7629064C1048000F2A68</string>\n\t\t\t\t<string>EDC583F8130855A90013090E</string>\n\t\t\t\t<string>EDC583F9130855A90013090E</string>\n\t\t\t\t<string>EDC583FA130855A90013090E</string>\n\t\t\t\t<string>EDC583FB130855A90013090E</string>\n\t\t\t\t<string>EDA514FA10C72929000A4F41</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfigUserDefaultsMinorVersion</key>\n\t\t\t<string>2</string>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.debugV3</string>\n\t\t</dict>\n\t</array>\n\t<key>PerspectivesBarVisible</key>\n\t<true/>\n\t<key>ShelfIsVisible</key>\n\t<false/>\n\t<key>SourceDescription</key>\n\t<string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecification.xcperspec'</string>\n\t<key>StatusbarIsVisible</key>\n\t<true/>\n\t<key>TimeStamp</key>\n\t<real>0.0</real>\n\t<key>ToolbarConfigUserDefaultsMinorVersion</key>\n\t<string>2</string>\n\t<key>ToolbarDisplayMode</key>\n\t<integer>1</integer>\n\t<key>ToolbarIsVisible</key>\n\t<true/>\n\t<key>ToolbarSizeMode</key>\n\t<integer>1</integer>\n\t<key>Type</key>\n\t<string>Perspectives</string>\n\t<key>UpdateMessage</key>\n\t<string></string>\n\t<key>WindowJustification</key>\n\t<integer>5</integer>\n\t<key>WindowOrderList</key>\n\t<array>\n\t\t<string>EDC583FD130855A90013090E</string>\n\t\t<string>EDC583FE130855A90013090E</string>\n\t\t<string>/Users/cole/develop/cufflinks/cufflinks.xcodeproj</string>\n\t</array>\n\t<key>WindowString</key>\n\t<string>469 55 1063 973 0 0 1680 1028 </string>\n\t<key>WindowToolsV3</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.debugger</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Debugger</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>HorizontalSplitView</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>_collapsingFrameDimension</key>\n\t\t\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t\t\t<key>_indexOfCollapsedView</key>\n\t\t\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t\t\t<key>_percentageOfCollapsedView</key>\n\t\t\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t\t\t<key>isCollapsed</key>\n\t\t\t\t\t\t\t\t\t\t<string>yes</string>\n\t\t\t\t\t\t\t\t\t\t<key>sizes</key>\n\t\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {317, 164}}</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>{{317, 0}, {377, 164}}</string>\n\t\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>VerticalSplitView</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>_collapsingFrameDimension</key>\n\t\t\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t\t\t<key>_indexOfCollapsedView</key>\n\t\t\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t\t\t<key>_percentageOfCollapsedView</key>\n\t\t\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t\t\t<key>isCollapsed</key>\n\t\t\t\t\t\t\t\t\t\t<string>yes</string>\n\t\t\t\t\t\t\t\t\t\t<key>sizes</key>\n\t\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {694, 164}}</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>{{0, 164}, {694, 216}}</string>\n\t\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>LauncherConfigVersion</key>\n\t\t\t\t\t\t\t\t<string>8</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1C162984064C10D400B95A72</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Debug - GLUTExamples (Underwater)</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>DebugConsoleDrawerSize</key>\n\t\t\t\t\t\t\t\t<string>{100, 120}</string>\n\t\t\t\t\t\t\t\t<key>DebugConsoleVisible</key>\n\t\t\t\t\t\t\t\t<string>None</string>\n\t\t\t\t\t\t\t\t<key>DebugConsoleWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>{{200, 200}, {500, 300}}</string>\n\t\t\t\t\t\t\t\t<key>DebugSTDIOWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>{{200, 200}, {500, 300}}</string>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {694, 380}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>321 238 694 422 0 0 1440 878 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>100%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>100%</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debugger</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1CD10A99069EF8BA00B06720</string>\n\t\t\t\t<string>1C0AD2AB069F1E9B00FABCE6</string>\n\t\t\t\t<string>1C162984064C10D400B95A72</string>\n\t\t\t\t<string>1C0AD2AC069F1E9B00FABCE6</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.debugV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>321 238 694 422 0 0 1440 878 </string>\n\t\t\t<key>WindowToolGUID</key>\n\t\t\t<string>1CD10A99069EF8BA00B06720</string>\n\t\t\t<key>WindowToolIsVisible</key>\n\t\t\t<integer>0</integer>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.build</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CD0528F0623707200166675</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>&lt;No Editor&gt;</string>\n\t\t\t\t\t\t\t\t<key>PBXSplitModuleInNavigatorKey</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>Split0</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1CD052900623707200166675</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>SplitCount</key>\n\t\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>StatusBarVisibility</key>\n\t\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {500, 215}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>192 257 500 500 0 0 1280 1002 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>218pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>XCMainBuildResultsModuleGUID</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Build Results</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 222}, {500, 236}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>192 257 500 500 0 0 1280 1002 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXBuildResultsModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>236pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>458pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Build Results</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXBuildResultsModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1C78EAA5065D492600B07095</string>\n\t\t\t\t<string>1C78EAA6065D492600B07095</string>\n\t\t\t\t<string>1CD0528F0623707200166675</string>\n\t\t\t\t<string>XCMainBuildResultsModuleGUID</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.buildV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>192 257 500 500 0 0 1280 1002 </string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.find</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1CDD528C0622207200134675</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>&lt;No Editor&gt;</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXSplitModuleInNavigatorKey</key>\n\t\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t\t<key>Split0</key>\n\t\t\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t\t\t<string>1CD0528D0623707200166675</string>\n\t\t\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t\t\t<key>SplitCount</key>\n\t\t\t\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t\t<key>StatusBarVisibility</key>\n\t\t\t\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {781, 167}}</string>\n\t\t\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t\t\t<string>62 385 781 470 0 0 1440 878 </string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t\t\t<string>781pt</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>50%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CD0528E0623707200166675</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Project Find</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{8, 0}, {773, 254}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>62 385 781 470 0 0 1440 878 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXProjectFindModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>50%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>428pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Project Find</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXProjectFindModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1C530D57069F1CE1000CFCEE</string>\n\t\t\t\t<string>1C530D58069F1CE1000CFCEE</string>\n\t\t\t\t<string>1C530D59069F1CE1000CFCEE</string>\n\t\t\t\t<string>1CDD528C0622207200134675</string>\n\t\t\t\t<string>1C530D5A069F1CE1000CFCEE</string>\n\t\t\t\t<string>1CE0B1FE06471DED0097A5F4</string>\n\t\t\t\t<string>1CD0528E0623707200166675</string>\n\t\t\t</array>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>62 385 781 470 0 0 1440 878 </string>\n\t\t\t<key>WindowToolGUID</key>\n\t\t\t<string>1C530D57069F1CE1000CFCEE</string>\n\t\t\t<key>WindowToolIsVisible</key>\n\t\t\t<integer>0</integer>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.snapshots</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>XCSnapshotModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>100%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>100%</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Snapshots</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>XCSnapshotModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<string>Yes</string>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.snapshots</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>315 824 300 550 0 0 1440 878 </string>\n\t\t\t<key>WindowToolIsVisible</key>\n\t\t\t<string>Yes</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>FirstTimeWindowDisplayed</key>\n\t\t\t<false/>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.debuggerConsole</string>\n\t\t\t<key>IsVertical</key>\n\t\t\t<true/>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1C78EAAC065D492600B07095</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Debugger Console</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {440, 359}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>267 368 440 400 0 0 1280 778 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXDebugCLIModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>359pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>359pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debugger Console</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXDebugCLIModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<true/>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1C530D5B069F1CE1000CFCEE</string>\n\t\t\t\t<string>EDA1843F119F1BE300E815BB</string>\n\t\t\t\t<string>1C78EAAC065D492600B07095</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.consoleV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>267 368 440 400 0 0 1280 778 </string>\n\t\t\t<key>WindowToolGUID</key>\n\t\t\t<string>1C530D5B069F1CE1000CFCEE</string>\n\t\t\t<key>WindowToolIsVisible</key>\n\t\t\t<false/>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.scm</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1C78EAB2065D492600B07095</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>&lt;No Editor&gt;</string>\n\t\t\t\t\t\t\t\t<key>PBXSplitModuleInNavigatorKey</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>Split0</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1C78EAB3065D492600B07095</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>SplitCount</key>\n\t\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>StatusBarVisibility</key>\n\t\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {452, 0}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>743 379 452 308 0 0 1280 1002 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>0pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CD052920623707200166675</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>SCM</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>ConsoleFrame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 259}, {452, 0}}</string>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 7}, {452, 259}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>743 379 452 308 0 0 1280 1002 </string>\n\t\t\t\t\t\t\t\t<key>TableConfiguration</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>Status</string>\n\t\t\t\t\t\t\t\t\t<real>30</real>\n\t\t\t\t\t\t\t\t\t<string>FileName</string>\n\t\t\t\t\t\t\t\t\t<real>199</real>\n\t\t\t\t\t\t\t\t\t<string>Path</string>\n\t\t\t\t\t\t\t\t\t<real>197.09500122070312</real>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<key>TableFrame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {452, 250}}</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXCVSModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>262pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>266pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>SCM</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXCVSModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1C78EAB4065D492600B07095</string>\n\t\t\t\t<string>1C78EAB5065D492600B07095</string>\n\t\t\t\t<string>1C78EAB2065D492600B07095</string>\n\t\t\t\t<string>1CD052920623707200166675</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.scmV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>743 379 452 308 0 0 1280 1002 </string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.breakpoints</string>\n\t\t\t<key>IsVertical</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXBottomSmartGroupGIDs</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>1C77FABC04509CD000000102</string>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CE0B1FE06471DED0097A5F4</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Files</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectStructureProvided</key>\n\t\t\t\t\t\t\t\t<string>no</string>\n\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnData</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>\n\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t<real>168</real>\n\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>\n\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t<string>MainColumn</string>\n\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>\n\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t<string>1C77FABC04509CD000000102</string>\n\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>\n\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>\n\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {168, 350}}</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>PBXTopSmartGroupGIDs</key>\n\t\t\t\t\t\t\t\t<array/>\n\t\t\t\t\t\t\t\t<key>XCIncludePerspectivesSwitch</key>\n\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {185, 368}}</string>\n\t\t\t\t\t\t\t\t<key>GroupTreeTableConfiguration</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>MainColumn</string>\n\t\t\t\t\t\t\t\t\t<real>168</real>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>315 424 744 409 0 0 1440 878 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXSmartGroupTreeModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>185pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CA1AED706398EBD00589147</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Detail</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{190, 0}, {554, 368}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>315 424 744 409 0 0 1440 878 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>XCDetailModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>554pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>368pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>MajorVersion</key>\n\t\t\t<integer>3</integer>\n\t\t\t<key>MinorVersion</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>Name</key>\n\t\t\t<string>Breakpoints</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXSmartGroupTreeModule</string>\n\t\t\t\t<string>XCDetailModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1CDDB66807F98D9800BB5817</string>\n\t\t\t\t<string>1CDDB66907F98D9800BB5817</string>\n\t\t\t\t<string>1CE0B1FE06471DED0097A5F4</string>\n\t\t\t\t<string>1CA1AED706398EBD00589147</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.breakpointsV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>315 424 744 409 0 0 1440 878 </string>\n\t\t\t<key>WindowToolGUID</key>\n\t\t\t<string>1CDDB66807F98D9800BB5817</string>\n\t\t\t<key>WindowToolIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.debugAnimator</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>100%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>100%</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debug Visualizer</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.debugAnimatorV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>100 100 700 500 0 0 1280 1002 </string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.bookmarks</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXBookmarksModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>166pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>166pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Bookmarks</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXBookmarksModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>538 42 401 187 0 0 1280 1002 </string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.projectFormatConflicts</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>XCProjectFormatConflictsModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>100%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>100%</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Project Format Conflicts</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>XCProjectFormatConflictsModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>WindowContentMinSize</key>\n\t\t\t<string>450 300</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>50 850 472 307 0 0 1440 877</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.classBrowser</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>OptionsSetName</key>\n\t\t\t\t\t\t\t\t<string>Hierarchy, all classes</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CA6456E063B45B4001379D8</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Class Browser - NSObject</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>ClassesFrame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {369, 96}}</string>\n\t\t\t\t\t\t\t\t<key>ClassesTreeTableConfiguration</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>PBXClassNameColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>208</real>\n\t\t\t\t\t\t\t\t\t<string>PBXClassBookColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>22</real>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {616, 353}}</string>\n\t\t\t\t\t\t\t\t<key>MembersFrame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 105}, {369, 395}}</string>\n\t\t\t\t\t\t\t\t<key>MembersTreeTableConfiguration</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>PBXMemberTypeIconColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>22</real>\n\t\t\t\t\t\t\t\t\t<string>PBXMemberNameColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>216</real>\n\t\t\t\t\t\t\t\t\t<string>PBXMemberTypeColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>94</real>\n\t\t\t\t\t\t\t\t\t<string>PBXMemberBookColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>22</real>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<key>PBXModuleWindowStatusBarHidden2</key>\n\t\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>597 125 616 374 0 0 1280 1002 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXClassBrowserModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>354pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>354pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Class Browser</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXClassBrowserModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1C78EABA065D492600B07095</string>\n\t\t\t\t<string>1C78EABB065D492600B07095</string>\n\t\t\t\t<string>1CA6456E063B45B4001379D8</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.classbrowser</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>597 125 616 374 0 0 1280 1002 </string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.refactoring</string>\n\t\t\t<key>IncludeInToolsMenu</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{0, 0}, {500, 335}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>{0, 0}, {500, 335}</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>XCRefactoringModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>100%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>100%</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Refactoring</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>XCRefactoringModule</string>\n\t\t\t</array>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>200 200 500 356 0 0 1920 1200 </string>\n\t\t</dict>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "cufflinks.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t0A6183721324308800EFF9AF /* multireads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A6183711324308800EFF9AF /* multireads.cpp */; };\n\t\t0A6183731324308800EFF9AF /* multireads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A6183711324308800EFF9AF /* multireads.cpp */; };\n\t\t0A69414F132AEDAB00558D76 /* dens_haz.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3613213B19008DDA0B /* dens_haz.c */; };\n\t\t0A694150132AEDAB00558D76 /* dens_int.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3713213B19008DDA0B /* dens_int.c */; };\n\t\t0A694151132AEDAB00558D76 /* dens_odi.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3813213B19008DDA0B /* dens_odi.c */; };\n\t\t0A694152132AEDAB00558D76 /* vari.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3313213903008DDA0B /* vari.cpp */; };\n\t\t0A694153132AEDAB00558D76 /* density.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F30132137F4008DDA0B /* density.c */; };\n\t\t0A694154132AEDAB00558D76 /* minmax.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5D13204FE30031949A /* minmax.c */; };\n\t\t0A694155132AEDAB00558D76 /* locfit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5E13204FE30031949A /* locfit.c */; };\n\t\t0A694156132AEDAB00558D76 /* ev_interp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5F13204FE30031949A /* ev_interp.c */; };\n\t\t0A694157132AEDAB00558D76 /* ev_atree.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6013204FE30031949A /* ev_atree.c */; };\n\t\t0A694158132AEDAB00558D76 /* weight.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6113204FE30031949A /* weight.c */; };\n\t\t0A694159132AEDAB00558D76 /* wdiag.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6213204FE40031949A /* wdiag.c */; };\n\t\t0A69415A132AEDAB00558D76 /* adap.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4013213C15008DDA0B /* adap.c */; };\n\t\t0A69415B132AEDAB00558D76 /* strings.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6313204FE40031949A /* strings.c */; };\n\t\t0A69415C132AEDAB00558D76 /* pout.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4F132150D9008DDA0B /* pout.c */; };\n\t\t0A69415D132AEDAB00558D76 /* dist.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4313213C49008DDA0B /* dist.c */; };\n\t\t0A69415E132AEDAB00558D76 /* startlf.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6413204FE40031949A /* startlf.c */; };\n\t\t0A69415F132AEDAB00558D76 /* band.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4C13213D03008DDA0B /* band.c */; };\n\t\t0A694160132AEDAB00558D76 /* lfd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4913213CDE008DDA0B /* lfd.c */; };\n\t\t0A694161132AEDAB00558D76 /* readfile.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5B132158CA008DDA0B /* readfile.c */; };\n\t\t0A694162132AEDAB00558D76 /* makecmd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F521321520A008DDA0B /* makecmd.c */; };\n\t\t0A694163132AEDAB00558D76 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4613213CAE008DDA0B /* random.c */; };\n\t\t0A694164132AEDAB00558D76 /* help.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5513215828008DDA0B /* help.c */; };\n\t\t0A694165132AEDAB00558D76 /* c_plot.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F581321587C008DDA0B /* c_plot.c */; };\n\t\t0A694166132AEDAB00558D76 /* solve.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6513204FE40031949A /* solve.c */; };\n\t\t0A694167132AEDAB00558D76 /* simul.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6613204FE40031949A /* simul.c */; };\n\t\t0A694168132AEDAB00558D76 /* preplot.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6713204FE40031949A /* preplot.c */; };\n\t\t0A694169132AEDAB00558D76 /* pcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6813204FE40031949A /* pcomp.c */; };\n\t\t0A69416A132AEDAC00558D76 /* nbhd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6913204FE40031949A /* nbhd.c */; };\n\t\t0A69416B132AEDAC00558D76 /* math.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6A13204FE40031949A /* math.c */; };\n\t\t0A69416C132AEDAC00558D76 /* m_max.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6B13204FE40031949A /* m_max.c */; };\n\t\t0A69416D132AEDAC00558D76 /* m_eigen.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6C13204FE40031949A /* m_eigen.c */; };\n\t\t0A69416E132AEDAC00558D76 /* linalg.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6D13204FE40031949A /* linalg.c */; };\n\t\t0A69416F132AEDAC00558D76 /* lfstr.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6E13204FE40031949A /* lfstr.c */; };\n\t\t0A694170132AEDAC00558D76 /* lf_vari.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6F13204FE40031949A /* lf_vari.c */; };\n\t\t0A694171132AEDAC00558D76 /* lf_fitfun.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7013204FE50031949A /* lf_fitfun.c */; };\n\t\t0A694172132AEDAC00558D76 /* lf_dercor.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7113204FE50031949A /* lf_dercor.c */; };\n\t\t0A694173132AEDAC00558D76 /* frend.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7213204FE50031949A /* frend.c */; };\n\t\t0A694174132AEDAC00558D76 /* fitted.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7313204FE50031949A /* fitted.c */; };\n\t\t0A694175132AEDAC00558D76 /* family.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7413204FE50031949A /* family.c */; };\n\t\t0A694176132AEDAC00558D76 /* ev_trian.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7513204FE50031949A /* ev_trian.c */; };\n\t\t0A694177132AEDAC00558D76 /* ev_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7613204FE50031949A /* ev_main.c */; };\n\t\t0A694178132AEDAC00558D76 /* ev_kdtre.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7713204FE50031949A /* ev_kdtre.c */; };\n\t\t0A694179132AEDAC00558D76 /* scb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7813204FE60031949A /* scb.c */; };\n\t\t0A69417A132AEDAC00558D76 /* scb_cons.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7A13204FE60031949A /* scb_cons.c */; };\n\t\t0A69417C132AEDAC00558D76 /* m_jacob.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7D13204FE60031949A /* m_jacob.c */; };\n\t\t0A694181132AEDAC00558D76 /* lf_robust.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8313204FE80031949A /* lf_robust.c */; };\n\t\t0A694182132AEDAC00558D76 /* m_chol.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8413204FE80031949A /* m_chol.c */; };\n\t\t0A694184132AEDAC00558D76 /* arith.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8913204FE90031949A /* arith.c */; };\n\t\t0A694185132AEDAC00558D76 /* c_args.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8A13204FE90031949A /* c_args.c */; };\n\t\t0A694186132AEDAC00558D76 /* ar_funs.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8B13204FE90031949A /* ar_funs.c */; };\n\t\t0A694189132AEDAC00558D76 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5913204F180031949A /* cmd.c */; };\n\t\t0A87350314118DD700E28429 /* libboost_thread-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A87350214118DD700E28429 /* libboost_thread-mt.a */; };\n\t\t0A9291D5132AD37100E7B024 /* replicates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED677C0D132A3D83000CFDC8 /* replicates.cpp */; };\n\t\t9C31043215250D8600F56669 /* jensen_shannon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDFE39FA122BE7B700F24CD3 /* jensen_shannon.cpp */; };\n\t\t9CBCD9B41333EB5B0059FE74 /* multireads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A6183711324308800EFF9AF /* multireads.cpp */; };\n\t\t9CBCD9B51333ECCE0059FE74 /* replicates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED677C0D132A3D83000CFDC8 /* replicates.cpp */; };\n\t\t9CBCD9B61333ECF50059FE74 /* dens_haz.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3613213B19008DDA0B /* dens_haz.c */; };\n\t\t9CBCD9B71333ECF50059FE74 /* dens_int.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3713213B19008DDA0B /* dens_int.c */; };\n\t\t9CBCD9B81333ECF50059FE74 /* dens_odi.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3813213B19008DDA0B /* dens_odi.c */; };\n\t\t9CBCD9B91333ECF50059FE74 /* vari.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3313213903008DDA0B /* vari.cpp */; };\n\t\t9CBCD9BA1333ECF50059FE74 /* density.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F30132137F4008DDA0B /* density.c */; };\n\t\t9CBCD9BB1333ECF50059FE74 /* minmax.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5D13204FE30031949A /* minmax.c */; };\n\t\t9CBCD9BC1333ECF50059FE74 /* locfit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5E13204FE30031949A /* locfit.c */; };\n\t\t9CBCD9BD1333ECF50059FE74 /* ev_interp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5F13204FE30031949A /* ev_interp.c */; };\n\t\t9CBCD9BE1333ECF50059FE74 /* ev_atree.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6013204FE30031949A /* ev_atree.c */; };\n\t\t9CBCD9BF1333ECF50059FE74 /* weight.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6113204FE30031949A /* weight.c */; };\n\t\t9CBCD9C01333ECF50059FE74 /* wdiag.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6213204FE40031949A /* wdiag.c */; };\n\t\t9CBCD9C11333ECF50059FE74 /* adap.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4013213C15008DDA0B /* adap.c */; };\n\t\t9CBCD9C21333ECF50059FE74 /* strings.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6313204FE40031949A /* strings.c */; };\n\t\t9CBCD9C31333ECF50059FE74 /* pout.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4F132150D9008DDA0B /* pout.c */; };\n\t\t9CBCD9C41333ECF50059FE74 /* dist.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4313213C49008DDA0B /* dist.c */; };\n\t\t9CBCD9C51333ECF50059FE74 /* startlf.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6413204FE40031949A /* startlf.c */; };\n\t\t9CBCD9C61333ECF50059FE74 /* band.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4C13213D03008DDA0B /* band.c */; };\n\t\t9CBCD9C71333ECF50059FE74 /* lfd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4913213CDE008DDA0B /* lfd.c */; };\n\t\t9CBCD9C81333ECF50059FE74 /* readfile.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5B132158CA008DDA0B /* readfile.c */; };\n\t\t9CBCD9C91333ECF50059FE74 /* makecmd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F521321520A008DDA0B /* makecmd.c */; };\n\t\t9CBCD9CA1333ECF50059FE74 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4613213CAE008DDA0B /* random.c */; };\n\t\t9CBCD9CB1333ECF50059FE74 /* help.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5513215828008DDA0B /* help.c */; };\n\t\t9CBCD9CC1333ECF50059FE74 /* c_plot.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F581321587C008DDA0B /* c_plot.c */; };\n\t\t9CBCD9CD1333ECF50059FE74 /* solve.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6513204FE40031949A /* solve.c */; };\n\t\t9CBCD9CE1333ECF50059FE74 /* simul.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6613204FE40031949A /* simul.c */; };\n\t\t9CBCD9CF1333ECF50059FE74 /* preplot.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6713204FE40031949A /* preplot.c */; };\n\t\t9CBCD9D01333ECF50059FE74 /* pcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6813204FE40031949A /* pcomp.c */; };\n\t\t9CBCD9D11333ECF50059FE74 /* nbhd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6913204FE40031949A /* nbhd.c */; };\n\t\t9CBCD9D21333ECF50059FE74 /* math.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6A13204FE40031949A /* math.c */; };\n\t\t9CBCD9D31333ECF50059FE74 /* m_max.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6B13204FE40031949A /* m_max.c */; };\n\t\t9CBCD9D41333ECF50059FE74 /* m_eigen.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6C13204FE40031949A /* m_eigen.c */; };\n\t\t9CBCD9D51333ECF50059FE74 /* linalg.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6D13204FE40031949A /* linalg.c */; };\n\t\t9CBCD9D61333ECF50059FE74 /* lfstr.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6E13204FE40031949A /* lfstr.c */; };\n\t\t9CBCD9D71333ECF50059FE74 /* lf_vari.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6F13204FE40031949A /* lf_vari.c */; };\n\t\t9CBCD9D81333ECF50059FE74 /* lf_fitfun.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7013204FE50031949A /* lf_fitfun.c */; };\n\t\t9CBCD9D91333ECF50059FE74 /* lf_dercor.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7113204FE50031949A /* lf_dercor.c */; };\n\t\t9CBCD9DA1333ECF50059FE74 /* frend.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7213204FE50031949A /* frend.c */; };\n\t\t9CBCD9DB1333ECF50059FE74 /* fitted.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7313204FE50031949A /* fitted.c */; };\n\t\t9CBCD9DC1333ECF50059FE74 /* family.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7413204FE50031949A /* family.c */; };\n\t\t9CBCD9DD1333ECF50059FE74 /* ev_trian.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7513204FE50031949A /* ev_trian.c */; };\n\t\t9CBCD9DE1333ECF50059FE74 /* ev_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7613204FE50031949A /* ev_main.c */; };\n\t\t9CBCD9DF1333ECF50059FE74 /* ev_kdtre.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7713204FE50031949A /* ev_kdtre.c */; };\n\t\t9CBCD9E01333ECF50059FE74 /* scb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7813204FE60031949A /* scb.c */; };\n\t\t9CBCD9E11333ECF50059FE74 /* scb_cons.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7A13204FE60031949A /* scb_cons.c */; };\n\t\t9CBCD9E21333ECFD0059FE74 /* m_jacob.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7D13204FE60031949A /* m_jacob.c */; };\n\t\t9CBCD9E31333ECFD0059FE74 /* lf_robust.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8313204FE80031949A /* lf_robust.c */; };\n\t\t9CBCD9E41333ECFD0059FE74 /* m_chol.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8413204FE80031949A /* m_chol.c */; };\n\t\t9CBCD9E51333ECFD0059FE74 /* arith.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8913204FE90031949A /* arith.c */; };\n\t\t9CBCD9E61333ECFD0059FE74 /* c_args.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8A13204FE90031949A /* c_args.c */; };\n\t\t9CBCD9E71333ECFD0059FE74 /* ar_funs.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8B13204FE90031949A /* ar_funs.c */; };\n\t\t9CBCD9E81333ECFD0059FE74 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5913204F180031949A /* cmd.c */; };\n\t\t9CCF1F3C135E29D600D7D6BD /* minmax.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5D13204FE30031949A /* minmax.c */; };\n\t\t9CCF1F3D135E29D600D7D6BD /* locfit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5E13204FE30031949A /* locfit.c */; };\n\t\t9CCF1F3E135E29D600D7D6BD /* ev_interp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5F13204FE30031949A /* ev_interp.c */; };\n\t\t9CCF1F3F135E29D600D7D6BD /* ev_atree.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6013204FE30031949A /* ev_atree.c */; };\n\t\t9CCF1F40135E29D600D7D6BD /* weight.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6113204FE30031949A /* weight.c */; };\n\t\t9CCF1F41135E29D600D7D6BD /* wdiag.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6213204FE40031949A /* wdiag.c */; };\n\t\t9CCF1F42135E29D600D7D6BD /* strings.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6313204FE40031949A /* strings.c */; };\n\t\t9CCF1F43135E29D600D7D6BD /* startlf.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6413204FE40031949A /* startlf.c */; };\n\t\t9CCF1F44135E29D600D7D6BD /* solve.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6513204FE40031949A /* solve.c */; };\n\t\t9CCF1F45135E29D600D7D6BD /* simul.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6613204FE40031949A /* simul.c */; };\n\t\t9CCF1F46135E29D700D7D6BD /* preplot.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6713204FE40031949A /* preplot.c */; };\n\t\t9CCF1F47135E29D700D7D6BD /* pcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6813204FE40031949A /* pcomp.c */; };\n\t\t9CCF1F48135E29D700D7D6BD /* nbhd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6913204FE40031949A /* nbhd.c */; };\n\t\t9CCF1F49135E29D700D7D6BD /* math.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6A13204FE40031949A /* math.c */; };\n\t\t9CCF1F4A135E29D700D7D6BD /* m_max.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6B13204FE40031949A /* m_max.c */; };\n\t\t9CCF1F4B135E29D700D7D6BD /* m_eigen.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6C13204FE40031949A /* m_eigen.c */; };\n\t\t9CCF1F4C135E29D700D7D6BD /* linalg.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6D13204FE40031949A /* linalg.c */; };\n\t\t9CCF1F4D135E29D700D7D6BD /* lfstr.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6E13204FE40031949A /* lfstr.c */; };\n\t\t9CCF1F4E135E29D700D7D6BD /* lf_vari.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6F13204FE40031949A /* lf_vari.c */; };\n\t\t9CCF1F4F135E29D700D7D6BD /* lf_fitfun.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7013204FE50031949A /* lf_fitfun.c */; };\n\t\t9CCF1F50135E29D700D7D6BD /* lf_dercor.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7113204FE50031949A /* lf_dercor.c */; };\n\t\t9CCF1F51135E29D700D7D6BD /* frend.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7213204FE50031949A /* frend.c */; };\n\t\t9CCF1F52135E29D700D7D6BD /* fitted.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7313204FE50031949A /* fitted.c */; };\n\t\t9CCF1F53135E29D700D7D6BD /* family.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7413204FE50031949A /* family.c */; };\n\t\t9CCF1F54135E29D700D7D6BD /* ev_trian.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7513204FE50031949A /* ev_trian.c */; };\n\t\t9CCF1F55135E29D700D7D6BD /* ev_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7613204FE50031949A /* ev_main.c */; };\n\t\t9CCF1F56135E29D700D7D6BD /* ev_kdtre.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7713204FE50031949A /* ev_kdtre.c */; };\n\t\t9CCF1F57135E29D700D7D6BD /* scb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7813204FE60031949A /* scb.c */; };\n\t\t9CCF1F58135E29D700D7D6BD /* scb_cons.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7A13204FE60031949A /* scb_cons.c */; };\n\t\t9CCF1F59135E29E400D7D6BD /* m_jacob.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7D13204FE60031949A /* m_jacob.c */; };\n\t\t9CCF1F5A135E29E400D7D6BD /* lf_robust.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8313204FE80031949A /* lf_robust.c */; };\n\t\t9CCF1F5B135E29E400D7D6BD /* m_chol.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8413204FE80031949A /* m_chol.c */; };\n\t\t9CCF1F5C135E29E400D7D6BD /* arith.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8913204FE90031949A /* arith.c */; };\n\t\t9CCF1F5D135E29E400D7D6BD /* c_args.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8A13204FE90031949A /* c_args.c */; };\n\t\t9CCF1F5E135E29E400D7D6BD /* ar_funs.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8B13204FE90031949A /* ar_funs.c */; };\n\t\t9CCF1F5F135E29E400D7D6BD /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5913204F180031949A /* cmd.c */; };\n\t\t9CD6E8EA13379B7E00CCE1DE /* GFastaIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D9A35123B5BE0002BEFD5 /* GFastaIndex.cpp */; };\n\t\t9CD6E8EB13379B7E00CCE1DE /* abundances.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151E10C72963000A4F41 /* abundances.cpp */; };\n\t\t9CD6E8EC13379B7E00CCE1DE /* assemble.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151F10C72963000A4F41 /* assemble.cpp */; };\n\t\t9CD6E8ED13379B7E00CCE1DE /* bundles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152010C72963000A4F41 /* bundles.cpp */; };\n\t\t9CD6E8EE13379B7E00CCE1DE /* codons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152110C72963000A4F41 /* codons.cpp */; };\n\t\t9CD6E8EF13379B7E00CCE1DE /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152210C72963000A4F41 /* common.cpp */; };\n\t\t9CD6E8F013379B7E00CCE1DE /* filters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152610C72963000A4F41 /* filters.cpp */; };\n\t\t9CD6E8F113379B7E00CCE1DE /* GArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152710C72963000A4F41 /* GArgs.cpp */; };\n\t\t9CD6E8F213379B7E00CCE1DE /* GBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152810C72963000A4F41 /* GBase.cpp */; };\n\t\t9CD6E8F313379B7E00CCE1DE /* gdna.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152910C72963000A4F41 /* gdna.cpp */; };\n\t\t9CD6E8F413379B7E00CCE1DE /* genes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152A10C72963000A4F41 /* genes.cpp */; };\n\t\t9CD6E8F513379B7E00CCE1DE /* GFaSeqGet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */; };\n\t\t9CD6E8F613379B7E00CCE1DE /* gff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152C10C72963000A4F41 /* gff.cpp */; };\n\t\t9CD6E8F713379B7E00CCE1DE /* GStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152D10C72963000A4F41 /* GStr.cpp */; };\n\t\t9CD6E8F813379B7E00CCE1DE /* gtf_tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152F10C72963000A4F41 /* gtf_tracking.cpp */; };\n\t\t9CD6E8FA13379B7E00CCE1DE /* hits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153010C72963000A4F41 /* hits.cpp */; };\n\t\t9CD6E8FB13379B7E00CCE1DE /* scaffolds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153110C72963000A4F41 /* scaffolds.cpp */; };\n\t\t9CD6E8FC13379B7E00CCE1DE /* tokenize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153210C72963000A4F41 /* tokenize.cpp */; };\n\t\t9CD6E8FD13379B7E00CCE1DE /* clustering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDACE439114F031B009024DB /* clustering.cpp */; };\n\t\t9CD6E8FE13379B7E00CCE1DE /* graph_optimize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78A2C11B5F4F0000F8846 /* graph_optimize.cpp */; };\n\t\t9CD6E8FF13379B7E00CCE1DE /* scaffold_graph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78A7911B6E912000F8846 /* scaffold_graph.cpp */; };\n\t\t9CD6E90013379B7E00CCE1DE /* matching_merge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78BC411B716C3000F8846 /* matching_merge.cpp */; };\n\t\t9CD6E90113379B7E00CCE1DE /* biascorrection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */; };\n\t\t9CD6E90213379B7E00CCE1DE /* multireads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A6183711324308800EFF9AF /* multireads.cpp */; };\n\t\t9CD6E90313379B7E00CCE1DE /* replicates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED677C0D132A3D83000CFDC8 /* replicates.cpp */; };\n\t\t9CD6E90413379B7E00CCE1DE /* dens_haz.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3613213B19008DDA0B /* dens_haz.c */; };\n\t\t9CD6E90513379B7E00CCE1DE /* dens_int.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3713213B19008DDA0B /* dens_int.c */; };\n\t\t9CD6E90613379B7E00CCE1DE /* dens_odi.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3813213B19008DDA0B /* dens_odi.c */; };\n\t\t9CD6E90713379B7E00CCE1DE /* vari.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3313213903008DDA0B /* vari.cpp */; };\n\t\t9CD6E90813379B7E00CCE1DE /* density.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F30132137F4008DDA0B /* density.c */; };\n\t\t9CD6E90913379B7E00CCE1DE /* minmax.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5D13204FE30031949A /* minmax.c */; };\n\t\t9CD6E90A13379B7E00CCE1DE /* locfit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5E13204FE30031949A /* locfit.c */; };\n\t\t9CD6E90B13379B7E00CCE1DE /* ev_interp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5F13204FE30031949A /* ev_interp.c */; };\n\t\t9CD6E90C13379B7E00CCE1DE /* ev_atree.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6013204FE30031949A /* ev_atree.c */; };\n\t\t9CD6E90D13379B7E00CCE1DE /* weight.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6113204FE30031949A /* weight.c */; };\n\t\t9CD6E90E13379B7E00CCE1DE /* wdiag.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6213204FE40031949A /* wdiag.c */; };\n\t\t9CD6E90F13379B7E00CCE1DE /* adap.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4013213C15008DDA0B /* adap.c */; };\n\t\t9CD6E91013379B7E00CCE1DE /* strings.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6313204FE40031949A /* strings.c */; };\n\t\t9CD6E91113379B7E00CCE1DE /* pout.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4F132150D9008DDA0B /* pout.c */; };\n\t\t9CD6E91213379B7E00CCE1DE /* dist.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4313213C49008DDA0B /* dist.c */; };\n\t\t9CD6E91313379B7E00CCE1DE /* startlf.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6413204FE40031949A /* startlf.c */; };\n\t\t9CD6E91413379B7E00CCE1DE /* band.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4C13213D03008DDA0B /* band.c */; };\n\t\t9CD6E91513379B7E00CCE1DE /* lfd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4913213CDE008DDA0B /* lfd.c */; };\n\t\t9CD6E91613379B7E00CCE1DE /* readfile.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5B132158CA008DDA0B /* readfile.c */; };\n\t\t9CD6E91713379B7E00CCE1DE /* makecmd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F521321520A008DDA0B /* makecmd.c */; };\n\t\t9CD6E91813379B7E00CCE1DE /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4613213CAE008DDA0B /* random.c */; };\n\t\t9CD6E91913379B7E00CCE1DE /* help.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5513215828008DDA0B /* help.c */; };\n\t\t9CD6E91A13379B7E00CCE1DE /* c_plot.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F581321587C008DDA0B /* c_plot.c */; };\n\t\t9CD6E91B13379B7E00CCE1DE /* solve.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6513204FE40031949A /* solve.c */; };\n\t\t9CD6E91C13379B7E00CCE1DE /* simul.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6613204FE40031949A /* simul.c */; };\n\t\t9CD6E91D13379B7E00CCE1DE /* preplot.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6713204FE40031949A /* preplot.c */; };\n\t\t9CD6E91E13379B7E00CCE1DE /* pcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6813204FE40031949A /* pcomp.c */; };\n\t\t9CD6E91F13379B7E00CCE1DE /* nbhd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6913204FE40031949A /* nbhd.c */; };\n\t\t9CD6E92013379B7E00CCE1DE /* math.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6A13204FE40031949A /* math.c */; };\n\t\t9CD6E92113379B7E00CCE1DE /* m_max.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6B13204FE40031949A /* m_max.c */; };\n\t\t9CD6E92213379B7E00CCE1DE /* m_eigen.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6C13204FE40031949A /* m_eigen.c */; };\n\t\t9CD6E92313379B7E00CCE1DE /* linalg.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6D13204FE40031949A /* linalg.c */; };\n\t\t9CD6E92413379B7E00CCE1DE /* lfstr.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6E13204FE40031949A /* lfstr.c */; };\n\t\t9CD6E92513379B7E00CCE1DE /* lf_vari.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6F13204FE40031949A /* lf_vari.c */; };\n\t\t9CD6E92613379B7E00CCE1DE /* lf_fitfun.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7013204FE50031949A /* lf_fitfun.c */; };\n\t\t9CD6E92713379B7E00CCE1DE /* lf_dercor.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7113204FE50031949A /* lf_dercor.c */; };\n\t\t9CD6E92813379B7E00CCE1DE /* frend.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7213204FE50031949A /* frend.c */; };\n\t\t9CD6E92913379B7E00CCE1DE /* fitted.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7313204FE50031949A /* fitted.c */; };\n\t\t9CD6E92A13379B7E00CCE1DE /* family.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7413204FE50031949A /* family.c */; };\n\t\t9CD6E92B13379B7E00CCE1DE /* ev_trian.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7513204FE50031949A /* ev_trian.c */; };\n\t\t9CD6E92C13379B7E00CCE1DE /* ev_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7613204FE50031949A /* ev_main.c */; };\n\t\t9CD6E92D13379B7E00CCE1DE /* ev_kdtre.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7713204FE50031949A /* ev_kdtre.c */; };\n\t\t9CD6E92E13379B7E00CCE1DE /* scb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7813204FE60031949A /* scb.c */; };\n\t\t9CD6E92F13379B7E00CCE1DE /* scb_cons.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7A13204FE60031949A /* scb_cons.c */; };\n\t\t9CD6E93013379B7E00CCE1DE /* m_jacob.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7D13204FE60031949A /* m_jacob.c */; };\n\t\t9CD6E93113379B7E00CCE1DE /* lf_robust.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8313204FE80031949A /* lf_robust.c */; };\n\t\t9CD6E93213379B7E00CCE1DE /* m_chol.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8413204FE80031949A /* m_chol.c */; };\n\t\t9CD6E93313379B7E00CCE1DE /* arith.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8913204FE90031949A /* arith.c */; };\n\t\t9CD6E93413379B7E00CCE1DE /* c_args.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8A13204FE90031949A /* c_args.c */; };\n\t\t9CD6E93513379B7E00CCE1DE /* ar_funs.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8B13204FE90031949A /* ar_funs.c */; };\n\t\t9CD6E93613379B7E00CCE1DE /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5913204F180031949A /* cmd.c */; };\n\t\t9CD6E93A13379B7E00CCE1DE /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = ED1C0D7911D7F94900CFD663 /* libz.dylib */; };\n\t\t9CD6E94113379B9D00CCE1DE /* compress_gtf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CD6E8D913379B0900CCE1DE /* compress_gtf.cpp */; };\n\t\t9CE680F9149FBEBD00855EDB /* sampling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CE680F8149FBEBD00855EDB /* sampling.cpp */; };\n\t\t9CE680FB149FBF3000855EDB /* sampling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CE680F8149FBEBD00855EDB /* sampling.cpp */; };\n\t\tA2047A18191141C7007193FC /* libbam.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A2047A17191141C7007193FC /* libbam.a */; };\n\t\tA2047A19191141C7007193FC /* libbam.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A2047A17191141C7007193FC /* libbam.a */; };\n\t\tA2047A1A191141C8007193FC /* libbam.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A2047A17191141C7007193FC /* libbam.a */; };\n\t\tA2047A1B191141C8007193FC /* libbam.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A2047A17191141C7007193FC /* libbam.a */; };\n\t\tED1C0D7A11D7F94900CFD663 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = ED1C0D7911D7F94900CFD663 /* libz.dylib */; };\n\t\tED41B818127602C60000B5A2 /* GFastaIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D9A35123B5BE0002BEFD5 /* GFastaIndex.cpp */; };\n\t\tED41B819127602C60000B5A2 /* abundances.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151E10C72963000A4F41 /* abundances.cpp */; };\n\t\tED41B81A127602C60000B5A2 /* assemble.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151F10C72963000A4F41 /* assemble.cpp */; };\n\t\tED41B81B127602C60000B5A2 /* bundles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152010C72963000A4F41 /* bundles.cpp */; };\n\t\tED41B81C127602C60000B5A2 /* codons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152110C72963000A4F41 /* codons.cpp */; };\n\t\tED41B81D127602C60000B5A2 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152210C72963000A4F41 /* common.cpp */; };\n\t\tED41B81E127602C60000B5A2 /* filters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152610C72963000A4F41 /* filters.cpp */; };\n\t\tED41B81F127602C60000B5A2 /* GArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152710C72963000A4F41 /* GArgs.cpp */; };\n\t\tED41B820127602C60000B5A2 /* GBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152810C72963000A4F41 /* GBase.cpp */; };\n\t\tED41B821127602C60000B5A2 /* gdna.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152910C72963000A4F41 /* gdna.cpp */; };\n\t\tED41B822127602C60000B5A2 /* genes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152A10C72963000A4F41 /* genes.cpp */; };\n\t\tED41B823127602C60000B5A2 /* GFaSeqGet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */; };\n\t\tED41B824127602C60000B5A2 /* gff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152C10C72963000A4F41 /* gff.cpp */; };\n\t\tED41B825127602C60000B5A2 /* GStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152D10C72963000A4F41 /* GStr.cpp */; };\n\t\tED41B826127602C60000B5A2 /* gtf_tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152F10C72963000A4F41 /* gtf_tracking.cpp */; };\n\t\tED41B828127602C60000B5A2 /* hits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153010C72963000A4F41 /* hits.cpp */; };\n\t\tED41B829127602C60000B5A2 /* scaffolds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153110C72963000A4F41 /* scaffolds.cpp */; };\n\t\tED41B82A127602C60000B5A2 /* tokenize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153210C72963000A4F41 /* tokenize.cpp */; };\n\t\tED41B82B127602C60000B5A2 /* clustering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDACE439114F031B009024DB /* clustering.cpp */; };\n\t\tED41B82C127602C60000B5A2 /* graph_optimize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78A2C11B5F4F0000F8846 /* graph_optimize.cpp */; };\n\t\tED41B82D127602C60000B5A2 /* scaffold_graph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78A7911B6E912000F8846 /* scaffold_graph.cpp */; };\n\t\tED41B82E127602C60000B5A2 /* matching_merge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78BC411B716C3000F8846 /* matching_merge.cpp */; };\n\t\tED41B82F127602C60000B5A2 /* biascorrection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */; };\n\t\tED41B833127602C60000B5A2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = ED1C0D7911D7F94900CFD663 /* libz.dylib */; };\n\t\tED41B83E127603A20000B5A2 /* gtf_reads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152E10C72963000A4F41 /* gtf_reads.cpp */; };\n\t\tED48324B123E83D100642337 /* GFastaIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D9A35123B5BE0002BEFD5 /* GFastaIndex.cpp */; };\n\t\tED677C0F132A3D83000CFDC8 /* replicates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED677C0D132A3D83000CFDC8 /* replicates.cpp */; };\n\t\tED677C10132A3D83000CFDC8 /* replicates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED677C0D132A3D83000CFDC8 /* replicates.cpp */; };\n\t\tED877B73123BCA3F0025A050 /* GFastaIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED877B72123BCA3F0025A050 /* GFastaIndex.cpp */; };\n\t\tED877B74123BCA3F0025A050 /* GFastaIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED877B72123BCA3F0025A050 /* GFastaIndex.cpp */; };\n\t\tED877B75123BCA3F0025A050 /* GFastaIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED877B72123BCA3F0025A050 /* GFastaIndex.cpp */; };\n\t\tED920F0C132136BE008DDA0B /* minmax.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5D13204FE30031949A /* minmax.c */; };\n\t\tED920F0D132136BE008DDA0B /* locfit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5E13204FE30031949A /* locfit.c */; };\n\t\tED920F0E132136BE008DDA0B /* ev_interp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5F13204FE30031949A /* ev_interp.c */; };\n\t\tED920F0F132136BE008DDA0B /* ev_atree.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6013204FE30031949A /* ev_atree.c */; };\n\t\tED920F10132136BE008DDA0B /* weight.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6113204FE30031949A /* weight.c */; };\n\t\tED920F11132136BE008DDA0B /* wdiag.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6213204FE40031949A /* wdiag.c */; };\n\t\tED920F12132136BE008DDA0B /* strings.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6313204FE40031949A /* strings.c */; };\n\t\tED920F14132136BE008DDA0B /* solve.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6513204FE40031949A /* solve.c */; };\n\t\tED920F15132136BE008DDA0B /* simul.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6613204FE40031949A /* simul.c */; };\n\t\tED920F16132136BE008DDA0B /* preplot.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6713204FE40031949A /* preplot.c */; };\n\t\tED920F17132136BE008DDA0B /* pcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6813204FE40031949A /* pcomp.c */; };\n\t\tED920F18132136BE008DDA0B /* nbhd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6913204FE40031949A /* nbhd.c */; };\n\t\tED920F19132136BE008DDA0B /* math.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6A13204FE40031949A /* math.c */; };\n\t\tED920F1A132136BE008DDA0B /* m_max.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6B13204FE40031949A /* m_max.c */; };\n\t\tED920F1B132136BE008DDA0B /* m_eigen.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6C13204FE40031949A /* m_eigen.c */; };\n\t\tED920F1C132136BE008DDA0B /* linalg.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6D13204FE40031949A /* linalg.c */; };\n\t\tED920F1D132136BE008DDA0B /* lfstr.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6E13204FE40031949A /* lfstr.c */; };\n\t\tED920F1E132136BE008DDA0B /* lf_vari.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6F13204FE40031949A /* lf_vari.c */; };\n\t\tED920F1F132136BE008DDA0B /* lf_fitfun.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7013204FE50031949A /* lf_fitfun.c */; };\n\t\tED920F20132136BE008DDA0B /* lf_dercor.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7113204FE50031949A /* lf_dercor.c */; };\n\t\tED920F21132136BE008DDA0B /* frend.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7213204FE50031949A /* frend.c */; };\n\t\tED920F22132136BE008DDA0B /* fitted.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7313204FE50031949A /* fitted.c */; };\n\t\tED920F23132136BE008DDA0B /* family.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7413204FE50031949A /* family.c */; };\n\t\tED920F24132136BE008DDA0B /* ev_trian.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7513204FE50031949A /* ev_trian.c */; };\n\t\tED920F25132136BE008DDA0B /* ev_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7613204FE50031949A /* ev_main.c */; };\n\t\tED920F26132136BE008DDA0B /* ev_kdtre.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7713204FE50031949A /* ev_kdtre.c */; };\n\t\tED920F27132136BE008DDA0B /* scb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7813204FE60031949A /* scb.c */; };\n\t\tED920F28132136BE008DDA0B /* scb_cons.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7A13204FE60031949A /* scb_cons.c */; };\n\t\tED920F29132136CE008DDA0B /* m_jacob.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7D13204FE60031949A /* m_jacob.c */; };\n\t\tED920F2A132136CE008DDA0B /* lf_robust.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8313204FE80031949A /* lf_robust.c */; };\n\t\tED920F2B132136CE008DDA0B /* m_chol.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8413204FE80031949A /* m_chol.c */; };\n\t\tED920F2C132136CE008DDA0B /* arith.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8913204FE90031949A /* arith.c */; };\n\t\tED920F2D132136CE008DDA0B /* c_args.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8A13204FE90031949A /* c_args.c */; };\n\t\tED920F2E132136CE008DDA0B /* ar_funs.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8B13204FE90031949A /* ar_funs.c */; };\n\t\tED920F2F132136CE008DDA0B /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5913204F180031949A /* cmd.c */; };\n\t\tED920F31132137F4008DDA0B /* density.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F30132137F4008DDA0B /* density.c */; };\n\t\tED920F32132137F4008DDA0B /* density.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F30132137F4008DDA0B /* density.c */; };\n\t\tED920F3413213903008DDA0B /* vari.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3313213903008DDA0B /* vari.cpp */; };\n\t\tED920F3513213903008DDA0B /* vari.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3313213903008DDA0B /* vari.cpp */; };\n\t\tED920F3913213B19008DDA0B /* dens_haz.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3613213B19008DDA0B /* dens_haz.c */; };\n\t\tED920F3A13213B19008DDA0B /* dens_haz.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3613213B19008DDA0B /* dens_haz.c */; };\n\t\tED920F3B13213B19008DDA0B /* dens_int.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3713213B19008DDA0B /* dens_int.c */; };\n\t\tED920F3C13213B19008DDA0B /* dens_int.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3713213B19008DDA0B /* dens_int.c */; };\n\t\tED920F3D13213B19008DDA0B /* dens_odi.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3813213B19008DDA0B /* dens_odi.c */; };\n\t\tED920F3E13213B19008DDA0B /* dens_odi.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3813213B19008DDA0B /* dens_odi.c */; };\n\t\tED920F3F13213BAC008DDA0B /* startlf.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6413204FE40031949A /* startlf.c */; };\n\t\tED920F4113213C15008DDA0B /* adap.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4013213C15008DDA0B /* adap.c */; };\n\t\tED920F4213213C15008DDA0B /* adap.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4013213C15008DDA0B /* adap.c */; };\n\t\tED920F4413213C49008DDA0B /* dist.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4313213C49008DDA0B /* dist.c */; };\n\t\tED920F4513213C49008DDA0B /* dist.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4313213C49008DDA0B /* dist.c */; };\n\t\tED920F4713213CAF008DDA0B /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4613213CAE008DDA0B /* random.c */; };\n\t\tED920F4813213CAF008DDA0B /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4613213CAE008DDA0B /* random.c */; };\n\t\tED920F4A13213CDF008DDA0B /* lfd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4913213CDE008DDA0B /* lfd.c */; };\n\t\tED920F4B13213CDF008DDA0B /* lfd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4913213CDE008DDA0B /* lfd.c */; };\n\t\tED920F4D13213D03008DDA0B /* band.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4C13213D03008DDA0B /* band.c */; };\n\t\tED920F4E13213D03008DDA0B /* band.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4C13213D03008DDA0B /* band.c */; };\n\t\tED920F50132150D9008DDA0B /* pout.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4F132150D9008DDA0B /* pout.c */; };\n\t\tED920F51132150D9008DDA0B /* pout.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4F132150D9008DDA0B /* pout.c */; };\n\t\tED920F531321520A008DDA0B /* makecmd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F521321520A008DDA0B /* makecmd.c */; };\n\t\tED920F541321520A008DDA0B /* makecmd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F521321520A008DDA0B /* makecmd.c */; };\n\t\tED920F5613215828008DDA0B /* help.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5513215828008DDA0B /* help.c */; };\n\t\tED920F5713215828008DDA0B /* help.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5513215828008DDA0B /* help.c */; };\n\t\tED920F591321587C008DDA0B /* c_plot.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F581321587C008DDA0B /* c_plot.c */; };\n\t\tED920F5A1321587C008DDA0B /* c_plot.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F581321587C008DDA0B /* c_plot.c */; };\n\t\tED920F5C132158CA008DDA0B /* readfile.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5B132158CA008DDA0B /* readfile.c */; };\n\t\tED920F5D132158CA008DDA0B /* readfile.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5B132158CA008DDA0B /* readfile.c */; };\n\t\tEDA5155210C729A9000A4F41 /* abundances.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151E10C72963000A4F41 /* abundances.cpp */; };\n\t\tEDA5155310C729A9000A4F41 /* assemble.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151F10C72963000A4F41 /* assemble.cpp */; };\n\t\tEDA5155410C729A9000A4F41 /* bundles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152010C72963000A4F41 /* bundles.cpp */; };\n\t\tEDA5155510C729A9000A4F41 /* codons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152110C72963000A4F41 /* codons.cpp */; };\n\t\tEDA5155610C729A9000A4F41 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152210C72963000A4F41 /* common.cpp */; };\n\t\tEDA5155910C729A9000A4F41 /* cufflinks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152510C72963000A4F41 /* cufflinks.cpp */; };\n\t\tEDA5155A10C729A9000A4F41 /* filters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152610C72963000A4F41 /* filters.cpp */; };\n\t\tEDA5155B10C729A9000A4F41 /* GArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152710C72963000A4F41 /* GArgs.cpp */; };\n\t\tEDA5155C10C729A9000A4F41 /* GBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152810C72963000A4F41 /* GBase.cpp */; };\n\t\tEDA5155D10C729A9000A4F41 /* gdna.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152910C72963000A4F41 /* gdna.cpp */; };\n\t\tEDA5155E10C729A9000A4F41 /* genes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152A10C72963000A4F41 /* genes.cpp */; };\n\t\tEDA5155F10C729A9000A4F41 /* GFaSeqGet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */; };\n\t\tEDA5156010C729A9000A4F41 /* gff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152C10C72963000A4F41 /* gff.cpp */; };\n\t\tEDA5156110C729A9000A4F41 /* GStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152D10C72963000A4F41 /* GStr.cpp */; };\n\t\tEDA5156310C729A9000A4F41 /* gtf_tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152F10C72963000A4F41 /* gtf_tracking.cpp */; };\n\t\tEDA5156410C729A9000A4F41 /* hits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153010C72963000A4F41 /* hits.cpp */; };\n\t\tEDA5156510C729A9000A4F41 /* scaffolds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153110C72963000A4F41 /* scaffolds.cpp */; };\n\t\tEDA5156610C729A9000A4F41 /* tokenize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153210C72963000A4F41 /* tokenize.cpp */; };\n\t\tEDACE432114EFF5C009024DB /* differential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDACE431114EFF5C009024DB /* differential.cpp */; };\n\t\tEDACE43A114F031B009024DB /* clustering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDACE439114F031B009024DB /* clustering.cpp */; };\n\t\tEDACE43B114F031B009024DB /* clustering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDACE439114F031B009024DB /* clustering.cpp */; };\n\t\tEDBAC4C111FF5AD3002B7162 /* biascorrection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */; };\n\t\tEDBAC4C211FF5AD3002B7162 /* biascorrection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */; };\n\t\tEDD0CE0A10C72F7D00AF308F /* abundances.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151E10C72963000A4F41 /* abundances.cpp */; };\n\t\tEDD0CE0C10C72F7D00AF308F /* bundles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152010C72963000A4F41 /* bundles.cpp */; };\n\t\tEDD0CE0D10C72F7D00AF308F /* codons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152110C72963000A4F41 /* codons.cpp */; };\n\t\tEDD0CE0E10C72F7D00AF308F /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152210C72963000A4F41 /* common.cpp */; };\n\t\tEDD0CE1010C72F7D00AF308F /* filters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152610C72963000A4F41 /* filters.cpp */; };\n\t\tEDD0CE1110C72F7D00AF308F /* GArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152710C72963000A4F41 /* GArgs.cpp */; };\n\t\tEDD0CE1210C72F7D00AF308F /* GBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152810C72963000A4F41 /* GBase.cpp */; };\n\t\tEDD0CE1310C72F7D00AF308F /* gdna.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152910C72963000A4F41 /* gdna.cpp */; };\n\t\tEDD0CE1410C72F7D00AF308F /* genes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152A10C72963000A4F41 /* genes.cpp */; };\n\t\tEDD0CE1510C72F7D00AF308F /* GFaSeqGet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */; };\n\t\tEDD0CE1610C72F7D00AF308F /* gff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152C10C72963000A4F41 /* gff.cpp */; };\n\t\tEDD0CE1710C72F7D00AF308F /* GStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152D10C72963000A4F41 /* GStr.cpp */; };\n\t\tEDD0CE1810C72F7D00AF308F /* gtf_tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152F10C72963000A4F41 /* gtf_tracking.cpp */; };\n\t\tEDD0CE1910C72F7D00AF308F /* hits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153010C72963000A4F41 /* hits.cpp */; };\n\t\tEDD0CE1A10C72F7D00AF308F /* scaffolds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153110C72963000A4F41 /* scaffolds.cpp */; };\n\t\tEDD0CE1B10C72F7D00AF308F /* tokenize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153210C72963000A4F41 /* tokenize.cpp */; };\n\t\tEDD0CE2410C72F9300AF308F /* cuffdiff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152410C72963000A4F41 /* cuffdiff.cpp */; };\n\t\tEDD6A9BF11598AB900D3F668 /* codons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152110C72963000A4F41 /* codons.cpp */; };\n\t\tEDD6A9C311598AB900D3F668 /* GArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152710C72963000A4F41 /* GArgs.cpp */; };\n\t\tEDD6A9C411598AB900D3F668 /* GBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152810C72963000A4F41 /* GBase.cpp */; };\n\t\tEDD6A9C511598AB900D3F668 /* gdna.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152910C72963000A4F41 /* gdna.cpp */; };\n\t\tEDD6A9C711598AB900D3F668 /* GFaSeqGet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */; };\n\t\tEDD6A9C811598AB900D3F668 /* gff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152C10C72963000A4F41 /* gff.cpp */; };\n\t\tEDD6A9C911598AB900D3F668 /* GStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152D10C72963000A4F41 /* GStr.cpp */; };\n\t\tEDD6A9CA11598AB900D3F668 /* gtf_tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152F10C72963000A4F41 /* gtf_tracking.cpp */; };\n\t\tEDD6A9DE11598CFC00D3F668 /* cuffcompare.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152310C72963000A4F41 /* cuffcompare.cpp */; };\n\t\tEDD94B481205C9E800AA1086 /* abundances.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151E10C72963000A4F41 /* abundances.cpp */; };\n\t\tEDD94B491205C9E800AA1086 /* assemble.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151F10C72963000A4F41 /* assemble.cpp */; };\n\t\tEDD94B4A1205C9E800AA1086 /* bundles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152010C72963000A4F41 /* bundles.cpp */; };\n\t\tEDD94B4B1205C9E800AA1086 /* codons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152110C72963000A4F41 /* codons.cpp */; };\n\t\tEDD94B4C1205C9E800AA1086 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152210C72963000A4F41 /* common.cpp */; };\n\t\tEDD94B4E1205C9E800AA1086 /* filters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152610C72963000A4F41 /* filters.cpp */; };\n\t\tEDD94B4F1205C9E800AA1086 /* GArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152710C72963000A4F41 /* GArgs.cpp */; };\n\t\tEDD94B501205C9E800AA1086 /* GBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152810C72963000A4F41 /* GBase.cpp */; };\n\t\tEDD94B511205C9E800AA1086 /* gdna.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152910C72963000A4F41 /* gdna.cpp */; };\n\t\tEDD94B521205C9E800AA1086 /* genes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152A10C72963000A4F41 /* genes.cpp */; };\n\t\tEDD94B531205C9E800AA1086 /* GFaSeqGet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */; };\n\t\tEDD94B541205C9E800AA1086 /* gff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152C10C72963000A4F41 /* gff.cpp */; };\n\t\tEDD94B551205C9E800AA1086 /* GStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152D10C72963000A4F41 /* GStr.cpp */; };\n\t\tEDD94B561205C9E800AA1086 /* gtf_tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152F10C72963000A4F41 /* gtf_tracking.cpp */; };\n\t\tEDD94B571205C9E800AA1086 /* hits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153010C72963000A4F41 /* hits.cpp */; };\n\t\tEDD94B581205C9E800AA1086 /* scaffolds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153110C72963000A4F41 /* scaffolds.cpp */; };\n\t\tEDD94B591205C9E800AA1086 /* tokenize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153210C72963000A4F41 /* tokenize.cpp */; };\n\t\tEDD94B5A1205C9E800AA1086 /* clustering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDACE439114F031B009024DB /* clustering.cpp */; };\n\t\tEDD94B5B1205C9E800AA1086 /* graph_optimize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78A2C11B5F4F0000F8846 /* graph_optimize.cpp */; };\n\t\tEDD94B5C1205C9E800AA1086 /* scaffold_graph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78A7911B6E912000F8846 /* scaffold_graph.cpp */; };\n\t\tEDD94B5D1205C9E800AA1086 /* matching_merge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78BC411B716C3000F8846 /* matching_merge.cpp */; };\n\t\tEDD94B5E1205C9E800AA1086 /* biascorrection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */; };\n\t\tEDD94B621205C9E800AA1086 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = ED1C0D7911D7F94900CFD663 /* libz.dylib */; };\n\t\tEDD94B741205CB1700AA1086 /* gtf_to_sam.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDD94B711205CAF400AA1086 /* gtf_to_sam.cpp */; };\n\t\tEDDBF70A12D29DF000130D8A /* cuffcluster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDDBF70912D29DF000130D8A /* cuffcluster.cpp */; };\n\t\tEDE107E911E37CE7005F1F4B /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = ED1C0D7911D7F94900CFD663 /* libz.dylib */; };\n\t\tEDE78A2D11B5F4F0000F8846 /* graph_optimize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78A2C11B5F4F0000F8846 /* graph_optimize.cpp */; };\n\t\tEDE78A7A11B6E912000F8846 /* scaffold_graph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78A7911B6E912000F8846 /* scaffold_graph.cpp */; };\n\t\tEDE78BC611B716C3000F8846 /* matching_merge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE78BC411B716C3000F8846 /* matching_merge.cpp */; };\n\t\tEDFE39B6122BE65600F24CD3 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152210C72963000A4F41 /* common.cpp */; };\n\t\tEDFE39C2122BE65600F24CD3 /* tokenize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153210C72963000A4F41 /* tokenize.cpp */; };\n\t\tEDFE39C9122BE65600F24CD3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = ED1C0D7911D7F94900CFD663 /* libz.dylib */; };\n\t\tEDFE39FB122BE7B700F24CD3 /* jensen_shannon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDFE39FA122BE7B700F24CD3 /* jensen_shannon.cpp */; };\n\t\tEDFE39FC122BE7B700F24CD3 /* jensen_shannon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDFE39FA122BE7B700F24CD3 /* jensen_shannon.cpp */; };\n\t\tF4A9F3711742865A000087E1 /* abundances.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151E10C72963000A4F41 /* abundances.cpp */; };\n\t\tF4A9F3721742865A000087E1 /* bundles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152010C72963000A4F41 /* bundles.cpp */; };\n\t\tF4A9F3731742865A000087E1 /* codons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152110C72963000A4F41 /* codons.cpp */; };\n\t\tF4A9F3741742865A000087E1 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152210C72963000A4F41 /* common.cpp */; };\n\t\tF4A9F3751742865A000087E1 /* filters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152610C72963000A4F41 /* filters.cpp */; };\n\t\tF4A9F3761742865A000087E1 /* GArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152710C72963000A4F41 /* GArgs.cpp */; };\n\t\tF4A9F3771742865A000087E1 /* GBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152810C72963000A4F41 /* GBase.cpp */; };\n\t\tF4A9F3781742865A000087E1 /* gdna.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152910C72963000A4F41 /* gdna.cpp */; };\n\t\tF4A9F3791742865A000087E1 /* genes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152A10C72963000A4F41 /* genes.cpp */; };\n\t\tF4A9F37A1742865A000087E1 /* GFaSeqGet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */; };\n\t\tF4A9F37B1742865A000087E1 /* gff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152C10C72963000A4F41 /* gff.cpp */; };\n\t\tF4A9F37C1742865A000087E1 /* GStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152D10C72963000A4F41 /* GStr.cpp */; };\n\t\tF4A9F37D1742865A000087E1 /* gtf_tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152F10C72963000A4F41 /* gtf_tracking.cpp */; };\n\t\tF4A9F37E1742865A000087E1 /* hits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153010C72963000A4F41 /* hits.cpp */; };\n\t\tF4A9F37F1742865A000087E1 /* scaffolds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153110C72963000A4F41 /* scaffolds.cpp */; };\n\t\tF4A9F3801742865A000087E1 /* tokenize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153210C72963000A4F41 /* tokenize.cpp */; };\n\t\tF4A9F3821742865A000087E1 /* clustering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDACE439114F031B009024DB /* clustering.cpp */; };\n\t\tF4A9F3831742865A000087E1 /* biascorrection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */; };\n\t\tF4A9F3841742865A000087E1 /* jensen_shannon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDFE39FA122BE7B700F24CD3 /* jensen_shannon.cpp */; };\n\t\tF4A9F3851742865A000087E1 /* GFastaIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED877B72123BCA3F0025A050 /* GFastaIndex.cpp */; };\n\t\tF4A9F3861742865A000087E1 /* minmax.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5D13204FE30031949A /* minmax.c */; };\n\t\tF4A9F3871742865A000087E1 /* locfit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5E13204FE30031949A /* locfit.c */; };\n\t\tF4A9F3881742865A000087E1 /* ev_interp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5F13204FE30031949A /* ev_interp.c */; };\n\t\tF4A9F3891742865A000087E1 /* ev_atree.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6013204FE30031949A /* ev_atree.c */; };\n\t\tF4A9F38A1742865A000087E1 /* weight.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6113204FE30031949A /* weight.c */; };\n\t\tF4A9F38B1742865A000087E1 /* wdiag.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6213204FE40031949A /* wdiag.c */; };\n\t\tF4A9F38C1742865A000087E1 /* strings.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6313204FE40031949A /* strings.c */; };\n\t\tF4A9F38D1742865A000087E1 /* solve.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6513204FE40031949A /* solve.c */; };\n\t\tF4A9F38E1742865A000087E1 /* simul.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6613204FE40031949A /* simul.c */; };\n\t\tF4A9F38F1742865A000087E1 /* preplot.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6713204FE40031949A /* preplot.c */; };\n\t\tF4A9F3901742865A000087E1 /* pcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6813204FE40031949A /* pcomp.c */; };\n\t\tF4A9F3911742865A000087E1 /* nbhd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6913204FE40031949A /* nbhd.c */; };\n\t\tF4A9F3921742865A000087E1 /* math.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6A13204FE40031949A /* math.c */; };\n\t\tF4A9F3931742865A000087E1 /* m_max.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6B13204FE40031949A /* m_max.c */; };\n\t\tF4A9F3941742865A000087E1 /* m_eigen.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6C13204FE40031949A /* m_eigen.c */; };\n\t\tF4A9F3951742865A000087E1 /* linalg.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6D13204FE40031949A /* linalg.c */; };\n\t\tF4A9F3961742865A000087E1 /* lfstr.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6E13204FE40031949A /* lfstr.c */; };\n\t\tF4A9F3971742865A000087E1 /* lf_vari.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6F13204FE40031949A /* lf_vari.c */; };\n\t\tF4A9F3981742865A000087E1 /* lf_fitfun.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7013204FE50031949A /* lf_fitfun.c */; };\n\t\tF4A9F3991742865A000087E1 /* lf_dercor.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7113204FE50031949A /* lf_dercor.c */; };\n\t\tF4A9F39A1742865A000087E1 /* frend.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7213204FE50031949A /* frend.c */; };\n\t\tF4A9F39B1742865A000087E1 /* fitted.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7313204FE50031949A /* fitted.c */; };\n\t\tF4A9F39C1742865A000087E1 /* family.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7413204FE50031949A /* family.c */; };\n\t\tF4A9F39D1742865A000087E1 /* ev_trian.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7513204FE50031949A /* ev_trian.c */; };\n\t\tF4A9F39E1742865A000087E1 /* ev_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7613204FE50031949A /* ev_main.c */; };\n\t\tF4A9F39F1742865A000087E1 /* ev_kdtre.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7713204FE50031949A /* ev_kdtre.c */; };\n\t\tF4A9F3A01742865A000087E1 /* scb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7813204FE60031949A /* scb.c */; };\n\t\tF4A9F3A11742865A000087E1 /* scb_cons.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7A13204FE60031949A /* scb_cons.c */; };\n\t\tF4A9F3A21742865A000087E1 /* m_jacob.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7D13204FE60031949A /* m_jacob.c */; };\n\t\tF4A9F3A31742865A000087E1 /* lf_robust.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8313204FE80031949A /* lf_robust.c */; };\n\t\tF4A9F3A41742865A000087E1 /* m_chol.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8413204FE80031949A /* m_chol.c */; };\n\t\tF4A9F3A51742865A000087E1 /* arith.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8913204FE90031949A /* arith.c */; };\n\t\tF4A9F3A61742865A000087E1 /* c_args.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8A13204FE90031949A /* c_args.c */; };\n\t\tF4A9F3A71742865A000087E1 /* ar_funs.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8B13204FE90031949A /* ar_funs.c */; };\n\t\tF4A9F3A81742865A000087E1 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5913204F180031949A /* cmd.c */; };\n\t\tF4A9F3A91742865A000087E1 /* density.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F30132137F4008DDA0B /* density.c */; };\n\t\tF4A9F3AA1742865A000087E1 /* vari.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3313213903008DDA0B /* vari.cpp */; };\n\t\tF4A9F3AB1742865A000087E1 /* dens_haz.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3613213B19008DDA0B /* dens_haz.c */; };\n\t\tF4A9F3AC1742865A000087E1 /* dens_int.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3713213B19008DDA0B /* dens_int.c */; };\n\t\tF4A9F3AD1742865A000087E1 /* dens_odi.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3813213B19008DDA0B /* dens_odi.c */; };\n\t\tF4A9F3AE1742865A000087E1 /* startlf.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6413204FE40031949A /* startlf.c */; };\n\t\tF4A9F3AF1742865A000087E1 /* adap.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4013213C15008DDA0B /* adap.c */; };\n\t\tF4A9F3B01742865A000087E1 /* dist.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4313213C49008DDA0B /* dist.c */; };\n\t\tF4A9F3B11742865A000087E1 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4613213CAE008DDA0B /* random.c */; };\n\t\tF4A9F3B21742865A000087E1 /* lfd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4913213CDE008DDA0B /* lfd.c */; };\n\t\tF4A9F3B31742865A000087E1 /* band.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4C13213D03008DDA0B /* band.c */; };\n\t\tF4A9F3B41742865A000087E1 /* pout.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4F132150D9008DDA0B /* pout.c */; };\n\t\tF4A9F3B51742865A000087E1 /* makecmd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F521321520A008DDA0B /* makecmd.c */; };\n\t\tF4A9F3B61742865A000087E1 /* help.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5513215828008DDA0B /* help.c */; };\n\t\tF4A9F3B71742865A000087E1 /* c_plot.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F581321587C008DDA0B /* c_plot.c */; };\n\t\tF4A9F3B81742865A000087E1 /* readfile.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5B132158CA008DDA0B /* readfile.c */; };\n\t\tF4A9F3B91742865A000087E1 /* multireads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A6183711324308800EFF9AF /* multireads.cpp */; };\n\t\tF4A9F3BA1742865A000087E1 /* replicates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED677C0D132A3D83000CFDC8 /* replicates.cpp */; };\n\t\tF4A9F3BB1742865A000087E1 /* sampling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CE680F8149FBEBD00855EDB /* sampling.cpp */; };\n\t\tF4A9F3C01742865A000087E1 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = ED1C0D7911D7F94900CFD663 /* libz.dylib */; };\n\t\tF4A9F3C617428670000087E1 /* cuffquant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4A9F36D17428648000087E1 /* cuffquant.cpp */; };\n\t\tF4A9F3C91742C26D000087E1 /* tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4A9F3C81742C26D000087E1 /* tracking.cpp */; };\n\t\tF4A9F3CA1742C26D000087E1 /* tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4A9F3C81742C26D000087E1 /* tracking.cpp */; };\n\t\tF4D2AB1518D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */; };\n\t\tF4D2AB1618D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */; };\n\t\tF4D2AB1718D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */; };\n\t\tF4D2AB1818D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */; };\n\t\tF4D2AB1918D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */; };\n\t\tF4D2AB1A18D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */; };\n\t\tF4D2AB1B18D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */; };\n\t\tF4D2AB1C18D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */; };\n\t\tF4D2AB1E18D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */; };\n\t\tF4D2AB1F18D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */; };\n\t\tF4D2AB2018D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */; };\n\t\tF4D2AB2118D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */; };\n\t\tF4D2AB2218D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */; };\n\t\tF4D2AB2318D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */; };\n\t\tF4D2AB2418D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */; };\n\t\tF4D2AB2518D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */; };\n\t\tF4D2AB2818D108EC00BB1CF0 /* libboost_thread-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1418D108EC00BB1CF0 /* libboost_thread-mt.a */; };\n\t\tF4D2AB2918D108EC00BB1CF0 /* libboost_thread-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1418D108EC00BB1CF0 /* libboost_thread-mt.a */; };\n\t\tF4D2AB2A18D108EC00BB1CF0 /* libboost_thread-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1418D108EC00BB1CF0 /* libboost_thread-mt.a */; };\n\t\tF4D2AB2B18D108EC00BB1CF0 /* libboost_thread-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1418D108EC00BB1CF0 /* libboost_thread-mt.a */; };\n\t\tF4D2AB2C18D108ED00BB1CF0 /* libboost_thread-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1418D108EC00BB1CF0 /* libboost_thread-mt.a */; };\n\t\tF4D2AB2D18D108ED00BB1CF0 /* libboost_thread-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1418D108EC00BB1CF0 /* libboost_thread-mt.a */; };\n\t\tF4D2AB2E18D108ED00BB1CF0 /* libboost_thread-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1418D108EC00BB1CF0 /* libboost_thread-mt.a */; };\n\t\tF4D2AB3418D1124600BB1CF0 /* abundances.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5151E10C72963000A4F41 /* abundances.cpp */; };\n\t\tF4D2AB3518D1124600BB1CF0 /* bundles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152010C72963000A4F41 /* bundles.cpp */; };\n\t\tF4D2AB3618D1124600BB1CF0 /* codons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152110C72963000A4F41 /* codons.cpp */; };\n\t\tF4D2AB3718D1124600BB1CF0 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152210C72963000A4F41 /* common.cpp */; };\n\t\tF4D2AB3818D1124600BB1CF0 /* filters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152610C72963000A4F41 /* filters.cpp */; };\n\t\tF4D2AB3918D1124600BB1CF0 /* GArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152710C72963000A4F41 /* GArgs.cpp */; };\n\t\tF4D2AB3A18D1124600BB1CF0 /* GBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152810C72963000A4F41 /* GBase.cpp */; };\n\t\tF4D2AB3B18D1124600BB1CF0 /* gdna.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152910C72963000A4F41 /* gdna.cpp */; };\n\t\tF4D2AB3C18D1124600BB1CF0 /* genes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152A10C72963000A4F41 /* genes.cpp */; };\n\t\tF4D2AB3D18D1124600BB1CF0 /* GFaSeqGet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */; };\n\t\tF4D2AB3E18D1124600BB1CF0 /* gff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152C10C72963000A4F41 /* gff.cpp */; };\n\t\tF4D2AB3F18D1124600BB1CF0 /* GStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152D10C72963000A4F41 /* GStr.cpp */; };\n\t\tF4D2AB4018D1124600BB1CF0 /* gtf_tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5152F10C72963000A4F41 /* gtf_tracking.cpp */; };\n\t\tF4D2AB4118D1124600BB1CF0 /* hits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153010C72963000A4F41 /* hits.cpp */; };\n\t\tF4D2AB4218D1124600BB1CF0 /* scaffolds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153110C72963000A4F41 /* scaffolds.cpp */; };\n\t\tF4D2AB4318D1124600BB1CF0 /* tokenize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDA5153210C72963000A4F41 /* tokenize.cpp */; };\n\t\tF4D2AB4418D1124600BB1CF0 /* differential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDACE431114EFF5C009024DB /* differential.cpp */; };\n\t\tF4D2AB4518D1124600BB1CF0 /* clustering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDACE439114F031B009024DB /* clustering.cpp */; };\n\t\tF4D2AB4618D1124600BB1CF0 /* biascorrection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */; };\n\t\tF4D2AB4718D1124600BB1CF0 /* jensen_shannon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDFE39FA122BE7B700F24CD3 /* jensen_shannon.cpp */; };\n\t\tF4D2AB4818D1124600BB1CF0 /* GFastaIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED877B72123BCA3F0025A050 /* GFastaIndex.cpp */; };\n\t\tF4D2AB4918D1124600BB1CF0 /* minmax.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5D13204FE30031949A /* minmax.c */; };\n\t\tF4D2AB4A18D1124600BB1CF0 /* locfit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5E13204FE30031949A /* locfit.c */; };\n\t\tF4D2AB4B18D1124600BB1CF0 /* ev_interp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5F13204FE30031949A /* ev_interp.c */; };\n\t\tF4D2AB4C18D1124600BB1CF0 /* ev_atree.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6013204FE30031949A /* ev_atree.c */; };\n\t\tF4D2AB4D18D1124600BB1CF0 /* weight.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6113204FE30031949A /* weight.c */; };\n\t\tF4D2AB4E18D1124600BB1CF0 /* wdiag.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6213204FE40031949A /* wdiag.c */; };\n\t\tF4D2AB4F18D1124600BB1CF0 /* strings.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6313204FE40031949A /* strings.c */; };\n\t\tF4D2AB5018D1124600BB1CF0 /* solve.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6513204FE40031949A /* solve.c */; };\n\t\tF4D2AB5118D1124600BB1CF0 /* simul.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6613204FE40031949A /* simul.c */; };\n\t\tF4D2AB5218D1124600BB1CF0 /* preplot.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6713204FE40031949A /* preplot.c */; };\n\t\tF4D2AB5318D1124600BB1CF0 /* pcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6813204FE40031949A /* pcomp.c */; };\n\t\tF4D2AB5418D1124600BB1CF0 /* nbhd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6913204FE40031949A /* nbhd.c */; };\n\t\tF4D2AB5518D1124600BB1CF0 /* math.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6A13204FE40031949A /* math.c */; };\n\t\tF4D2AB5618D1124600BB1CF0 /* m_max.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6B13204FE40031949A /* m_max.c */; };\n\t\tF4D2AB5718D1124600BB1CF0 /* m_eigen.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6C13204FE40031949A /* m_eigen.c */; };\n\t\tF4D2AB5818D1124600BB1CF0 /* linalg.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6D13204FE40031949A /* linalg.c */; };\n\t\tF4D2AB5918D1124600BB1CF0 /* lfstr.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6E13204FE40031949A /* lfstr.c */; };\n\t\tF4D2AB5A18D1124600BB1CF0 /* lf_vari.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6F13204FE40031949A /* lf_vari.c */; };\n\t\tF4D2AB5B18D1124600BB1CF0 /* lf_fitfun.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7013204FE50031949A /* lf_fitfun.c */; };\n\t\tF4D2AB5C18D1124600BB1CF0 /* lf_dercor.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7113204FE50031949A /* lf_dercor.c */; };\n\t\tF4D2AB5D18D1124600BB1CF0 /* frend.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7213204FE50031949A /* frend.c */; };\n\t\tF4D2AB5E18D1124600BB1CF0 /* fitted.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7313204FE50031949A /* fitted.c */; };\n\t\tF4D2AB5F18D1124600BB1CF0 /* family.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7413204FE50031949A /* family.c */; };\n\t\tF4D2AB6018D1124600BB1CF0 /* ev_trian.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7513204FE50031949A /* ev_trian.c */; };\n\t\tF4D2AB6118D1124600BB1CF0 /* ev_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7613204FE50031949A /* ev_main.c */; };\n\t\tF4D2AB6218D1124600BB1CF0 /* ev_kdtre.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7713204FE50031949A /* ev_kdtre.c */; };\n\t\tF4D2AB6318D1124600BB1CF0 /* scb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7813204FE60031949A /* scb.c */; };\n\t\tF4D2AB6418D1124600BB1CF0 /* scb_cons.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7A13204FE60031949A /* scb_cons.c */; };\n\t\tF4D2AB6518D1124600BB1CF0 /* m_jacob.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B7D13204FE60031949A /* m_jacob.c */; };\n\t\tF4D2AB6618D1124600BB1CF0 /* lf_robust.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8313204FE80031949A /* lf_robust.c */; };\n\t\tF4D2AB6718D1124600BB1CF0 /* m_chol.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8413204FE80031949A /* m_chol.c */; };\n\t\tF4D2AB6818D1124600BB1CF0 /* arith.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8913204FE90031949A /* arith.c */; };\n\t\tF4D2AB6918D1124600BB1CF0 /* c_args.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8A13204FE90031949A /* c_args.c */; };\n\t\tF4D2AB6A18D1124600BB1CF0 /* ar_funs.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B8B13204FE90031949A /* ar_funs.c */; };\n\t\tF4D2AB6B18D1124600BB1CF0 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B5913204F180031949A /* cmd.c */; };\n\t\tF4D2AB6C18D1124600BB1CF0 /* density.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F30132137F4008DDA0B /* density.c */; };\n\t\tF4D2AB6D18D1124600BB1CF0 /* vari.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3313213903008DDA0B /* vari.cpp */; };\n\t\tF4D2AB6E18D1124600BB1CF0 /* dens_haz.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3613213B19008DDA0B /* dens_haz.c */; };\n\t\tF4D2AB6F18D1124600BB1CF0 /* dens_int.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3713213B19008DDA0B /* dens_int.c */; };\n\t\tF4D2AB7018D1124600BB1CF0 /* dens_odi.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F3813213B19008DDA0B /* dens_odi.c */; };\n\t\tF4D2AB7118D1124600BB1CF0 /* startlf.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC50B6413204FE40031949A /* startlf.c */; };\n\t\tF4D2AB7218D1124600BB1CF0 /* adap.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4013213C15008DDA0B /* adap.c */; };\n\t\tF4D2AB7318D1124600BB1CF0 /* dist.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4313213C49008DDA0B /* dist.c */; };\n\t\tF4D2AB7418D1124600BB1CF0 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4613213CAE008DDA0B /* random.c */; };\n\t\tF4D2AB7518D1124600BB1CF0 /* lfd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4913213CDE008DDA0B /* lfd.c */; };\n\t\tF4D2AB7618D1124600BB1CF0 /* band.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4C13213D03008DDA0B /* band.c */; };\n\t\tF4D2AB7718D1124600BB1CF0 /* pout.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F4F132150D9008DDA0B /* pout.c */; };\n\t\tF4D2AB7818D1124600BB1CF0 /* makecmd.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F521321520A008DDA0B /* makecmd.c */; };\n\t\tF4D2AB7918D1124600BB1CF0 /* help.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5513215828008DDA0B /* help.c */; };\n\t\tF4D2AB7A18D1124600BB1CF0 /* c_plot.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F581321587C008DDA0B /* c_plot.c */; };\n\t\tF4D2AB7B18D1124600BB1CF0 /* readfile.c in Sources */ = {isa = PBXBuildFile; fileRef = ED920F5B132158CA008DDA0B /* readfile.c */; };\n\t\tF4D2AB7C18D1124600BB1CF0 /* multireads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A6183711324308800EFF9AF /* multireads.cpp */; };\n\t\tF4D2AB7D18D1124600BB1CF0 /* replicates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED677C0D132A3D83000CFDC8 /* replicates.cpp */; };\n\t\tF4D2AB7E18D1124600BB1CF0 /* sampling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9CE680F8149FBEBD00855EDB /* sampling.cpp */; };\n\t\tF4D2AB7F18D1124600BB1CF0 /* tracking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4A9F3C81742C26D000087E1 /* tracking.cpp */; };\n\t\tF4D2AB8118D1124600BB1CF0 /* libboost_serialization-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */; };\n\t\tF4D2AB8318D1124600BB1CF0 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = ED1C0D7911D7F94900CFD663 /* libz.dylib */; };\n\t\tF4D2AB8418D1124600BB1CF0 /* libboost_thread-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1418D108EC00BB1CF0 /* libboost_thread-mt.a */; };\n\t\tF4D2AB8518D1124600BB1CF0 /* libboost_system-mt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */; };\n\t\tF4D2AB8B18D1125D00BB1CF0 /* cuffnorm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4D43F2118D0BA3600AEB7BA /* cuffnorm.cpp */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t8DD76F690486A84900D96B5E /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 8;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n\t\t9CD6E93B13379B7E00CCE1DE /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 8;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n\t\tED41B834127602C60000B5A2 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 8;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n\t\tEDD0CE1E10C72F7D00AF308F /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 8;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n\t\tEDD6A9D111598AB900D3F668 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 8;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n\t\tEDD94B631205C9E800AA1086 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 8;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n\t\tEDFE39CA122BE65600F24CD3 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 8;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n\t\tF4A9F3C11742865A000087E1 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 8;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n\t\tF4D2AB8618D1124600BB1CF0 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 8;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t0A25E74B1242E95A0080BEA9 /* progressbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = progressbar.h; path = src/progressbar.h; sourceTree = \"<group>\"; };\n\t\t0A4C0AD412F734DE0055A9D8 /* multireads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = multireads.h; path = src/multireads.h; sourceTree = \"<group>\"; };\n\t\t0A5D9A35123B5BE0002BEFD5 /* GFastaIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GFastaIndex.cpp; path = src/GFastaIndex.cpp; sourceTree = \"<group>\"; };\n\t\t0A5D9A3F123B5BFE002BEFD5 /* GFastaIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GFastaIndex.h; path = src/GFastaIndex.h; sourceTree = \"<group>\"; };\n\t\t0A6183711324308800EFF9AF /* multireads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = multireads.cpp; path = src/multireads.cpp; sourceTree = \"<group>\"; };\n\t\t0A87350214118DD700E28429 /* libboost_thread-mt.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = \"libboost_thread-mt.a\"; path = \"/opt/local/lib/libboost_thread-mt.a\"; sourceTree = \"<absolute>\"; };\n\t\t0ACD78C612E6647B00310E07 /* update_check.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = update_check.h; path = src/update_check.h; sourceTree = \"<group>\"; };\n\t\t9C198ABD12F231CD00919C3B /* test_scaffolds.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_scaffolds.cpp; sourceTree = \"<group>\"; };\n\t\t9C29C3E31339285000EC6E65 /* vari.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = vari.hpp; sourceTree = \"<group>\"; };\n\t\t9C40F31B13C78FEF00515339 /* cuffmerge */ = {isa = PBXFileReference; explicitFileType = text.script.python; name = cuffmerge; path = src/cuffmerge; sourceTree = \"<group>\"; };\n\t\t9CC50B5913204F180031949A /* cmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = cmd.c; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.c; };\n\t\t9CC50B5D13204FE30031949A /* minmax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = minmax.c; sourceTree = \"<group>\"; };\n\t\t9CC50B5E13204FE30031949A /* locfit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = locfit.c; sourceTree = \"<group>\"; };\n\t\t9CC50B5F13204FE30031949A /* ev_interp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ev_interp.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6013204FE30031949A /* ev_atree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ev_atree.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6113204FE30031949A /* weight.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = weight.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6213204FE40031949A /* wdiag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wdiag.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6313204FE40031949A /* strings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = strings.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6413204FE40031949A /* startlf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = startlf.c; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.c; };\n\t\t9CC50B6513204FE40031949A /* solve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = solve.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6613204FE40031949A /* simul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simul.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6713204FE40031949A /* preplot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = preplot.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6813204FE40031949A /* pcomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pcomp.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6913204FE40031949A /* nbhd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nbhd.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6A13204FE40031949A /* math.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = math.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6B13204FE40031949A /* m_max.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_max.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6C13204FE40031949A /* m_eigen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_eigen.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6D13204FE40031949A /* linalg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = linalg.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6E13204FE40031949A /* lfstr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lfstr.c; sourceTree = \"<group>\"; };\n\t\t9CC50B6F13204FE40031949A /* lf_vari.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lf_vari.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7013204FE50031949A /* lf_fitfun.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lf_fitfun.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7113204FE50031949A /* lf_dercor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lf_dercor.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7213204FE50031949A /* frend.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = frend.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7313204FE50031949A /* fitted.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fitted.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7413204FE50031949A /* family.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = family.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7513204FE50031949A /* ev_trian.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ev_trian.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7613204FE50031949A /* ev_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ev_main.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7713204FE50031949A /* ev_kdtre.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ev_kdtre.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7813204FE60031949A /* scb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scb.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7A13204FE60031949A /* scb_cons.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scb_cons.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7B13204FE60031949A /* local.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; lineEnding = 0; path = local.h; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };\n\t\t9CC50B7D13204FE60031949A /* m_jacob.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_jacob.c; sourceTree = \"<group>\"; };\n\t\t9CC50B7F13204FE70031949A /* design.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = design.h; sourceTree = \"<group>\"; };\n\t\t9CC50B8013204FE70031949A /* lffuns.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lffuns.h; sourceTree = \"<group>\"; };\n\t\t9CC50B8113204FE70031949A /* lfstruc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lfstruc.h; sourceTree = \"<group>\"; };\n\t\t9CC50B8213204FE70031949A /* mutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mutil.h; sourceTree = \"<group>\"; };\n\t\t9CC50B8313204FE80031949A /* lf_robust.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lf_robust.c; sourceTree = \"<group>\"; };\n\t\t9CC50B8413204FE80031949A /* m_chol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_chol.c; sourceTree = \"<group>\"; };\n\t\t9CC50B8513204FE80031949A /* lfcons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lfcons.h; sourceTree = \"<group>\"; };\n\t\t9CC50B8913204FE90031949A /* arith.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arith.c; sourceTree = \"<group>\"; };\n\t\t9CC50B8A13204FE90031949A /* c_args.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = c_args.c; sourceTree = \"<group>\"; };\n\t\t9CC50B8B13204FE90031949A /* ar_funs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ar_funs.c; sourceTree = \"<group>\"; };\n\t\t9CC50B8E13204FEA0031949A /* lfwin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lfwin.h; sourceTree = \"<group>\"; };\n\t\t9CC50B8F13204FEA0031949A /* imatlb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imatlb.h; sourceTree = \"<group>\"; };\n\t\t9CD6E8D913379B0900CCE1DE /* compress_gtf.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = compress_gtf.cpp; path = src/compress_gtf.cpp; sourceTree = \"<group>\"; };\n\t\t9CD6E93F13379B7E00CCE1DE /* compress_gtf */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = compress_gtf; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t9CE680F6149697B500855EDB /* cuffmerge */ = {isa = PBXFileReference; explicitFileType = text.script.python; name = cuffmerge; path = src/cuffmerge; sourceTree = \"<group>\"; };\n\t\t9CE680F7149FBE2F00855EDB /* sampling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sampling.h; path = src/sampling.h; sourceTree = \"<group>\"; };\n\t\t9CE680F8149FBEBD00855EDB /* sampling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sampling.cpp; path = src/sampling.cpp; sourceTree = \"<group>\"; };\n\t\tA2047A17191141C7007193FC /* libbam.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbam.a; path = ../../../../opt/local/libIntel64/libbam.a; sourceTree = \"<group>\"; };\n\t\tED1C0C7111D7D9E500CFD663 /* ax_boost_base.m4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ax_boost_base.m4; sourceTree = \"<group>\"; };\n\t\tED1C0C7211D7D9E500CFD663 /* ax_boost_thread.m4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ax_boost_thread.m4; sourceTree = \"<group>\"; };\n\t\tED1C0C7411D7DA3200CFD663 /* ax_bam.m4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ax_bam.m4; sourceTree = \"<group>\"; };\n\t\tED1C0CAA11D7E52400CFD663 /* ax_check_zlib.m4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ax_check_zlib.m4; sourceTree = \"<group>\"; };\n\t\tED1C0D7911D7F94900CFD663 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };\n\t\tED41B838127602C60000B5A2 /* cufflinks_xcode */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = cufflinks_xcode; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tED4835D81249057500642337 /* progressbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = progressbar.h; path = src/progressbar.h; sourceTree = \"<group>\"; };\n\t\tED677C0D132A3D83000CFDC8 /* replicates.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = replicates.cpp; path = src/replicates.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tED677C0E132A3D83000CFDC8 /* replicates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = replicates.h; path = src/replicates.h; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };\n\t\tED877B72123BCA3F0025A050 /* GFastaIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GFastaIndex.cpp; path = src/GFastaIndex.cpp; sourceTree = \"<group>\"; };\n\t\tED920F30132137F4008DDA0B /* density.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = density.c; sourceTree = \"<group>\"; };\n\t\tED920F3313213903008DDA0B /* vari.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = vari.cpp; sourceTree = \"<group>\"; };\n\t\tED920F3613213B19008DDA0B /* dens_haz.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dens_haz.c; sourceTree = \"<group>\"; };\n\t\tED920F3713213B19008DDA0B /* dens_int.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dens_int.c; sourceTree = \"<group>\"; };\n\t\tED920F3813213B19008DDA0B /* dens_odi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dens_odi.c; sourceTree = \"<group>\"; };\n\t\tED920F4013213C15008DDA0B /* adap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adap.c; sourceTree = \"<group>\"; };\n\t\tED920F4313213C49008DDA0B /* dist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dist.c; sourceTree = \"<group>\"; };\n\t\tED920F4613213CAE008DDA0B /* random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = random.c; sourceTree = \"<group>\"; };\n\t\tED920F4913213CDE008DDA0B /* lfd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lfd.c; sourceTree = \"<group>\"; };\n\t\tED920F4C13213D03008DDA0B /* band.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = band.c; sourceTree = \"<group>\"; };\n\t\tED920F4F132150D9008DDA0B /* pout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pout.c; sourceTree = \"<group>\"; };\n\t\tED920F521321520A008DDA0B /* makecmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = makecmd.c; sourceTree = \"<group>\"; };\n\t\tED920F5513215828008DDA0B /* help.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = help.c; sourceTree = \"<group>\"; };\n\t\tED920F581321587C008DDA0B /* c_plot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = c_plot.c; sourceTree = \"<group>\"; };\n\t\tED920F5B132158CA008DDA0B /* readfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readfile.c; sourceTree = \"<group>\"; };\n\t\tEDA5150910C72963000A4F41 /* abundances.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = abundances.h; path = src/abundances.h; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };\n\t\tEDA5150A10C72963000A4F41 /* assemble.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = assemble.h; path = src/assemble.h; sourceTree = \"<group>\"; };\n\t\tEDA5150B10C72963000A4F41 /* bundles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = bundles.h; path = src/bundles.h; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };\n\t\tEDA5150C10C72963000A4F41 /* codons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = codons.h; path = src/codons.h; sourceTree = \"<group>\"; };\n\t\tEDA5150D10C72963000A4F41 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = common.h; path = src/common.h; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };\n\t\tEDA5150E10C72963000A4F41 /* filters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = filters.h; path = src/filters.h; sourceTree = \"<group>\"; };\n\t\tEDA5150F10C72963000A4F41 /* GArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GArgs.h; path = src/GArgs.h; sourceTree = \"<group>\"; };\n\t\tEDA5151010C72963000A4F41 /* GBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GBase.h; path = src/GBase.h; sourceTree = \"<group>\"; };\n\t\tEDA5151110C72963000A4F41 /* gdna.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gdna.h; path = src/gdna.h; sourceTree = \"<group>\"; };\n\t\tEDA5151210C72963000A4F41 /* genes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = genes.h; path = src/genes.h; sourceTree = \"<group>\"; };\n\t\tEDA5151310C72963000A4F41 /* GFaSeqGet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GFaSeqGet.h; path = src/GFaSeqGet.h; sourceTree = \"<group>\"; };\n\t\tEDA5151510C72963000A4F41 /* gff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gff.h; path = src/gff.h; sourceTree = \"<group>\"; };\n\t\tEDA5151610C72963000A4F41 /* GStr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GStr.h; path = src/GStr.h; sourceTree = \"<group>\"; };\n\t\tEDA5151710C72963000A4F41 /* gtf_tracking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gtf_tracking.h; path = src/gtf_tracking.h; sourceTree = \"<group>\"; };\n\t\tEDA5151810C72963000A4F41 /* hits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = hits.h; path = src/hits.h; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };\n\t\tEDA5151910C72963000A4F41 /* scaffolds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scaffolds.h; path = src/scaffolds.h; sourceTree = \"<group>\"; };\n\t\tEDA5151A10C72963000A4F41 /* tokenize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tokenize.h; path = src/tokenize.h; sourceTree = \"<group>\"; };\n\t\tEDA5151B10C72963000A4F41 /* transitive_closure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = transitive_closure.h; path = src/transitive_closure.h; sourceTree = \"<group>\"; };\n\t\tEDA5151C10C72963000A4F41 /* GHash.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = GHash.hh; path = src/GHash.hh; sourceTree = \"<group>\"; };\n\t\tEDA5151D10C72963000A4F41 /* GList.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = GList.hh; path = src/GList.hh; sourceTree = \"<group>\"; };\n\t\tEDA5151E10C72963000A4F41 /* abundances.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = abundances.cpp; path = src/abundances.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDA5151F10C72963000A4F41 /* assemble.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = assemble.cpp; path = src/assemble.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDA5152010C72963000A4F41 /* bundles.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = bundles.cpp; path = src/bundles.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDA5152110C72963000A4F41 /* codons.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = codons.cpp; path = src/codons.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5152210C72963000A4F41 /* common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = common.cpp; path = src/common.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDA5152310C72963000A4F41 /* cuffcompare.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = cuffcompare.cpp; path = src/cuffcompare.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDA5152410C72963000A4F41 /* cuffdiff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = cuffdiff.cpp; path = src/cuffdiff.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDA5152510C72963000A4F41 /* cufflinks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = cufflinks.cpp; path = src/cufflinks.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDA5152610C72963000A4F41 /* filters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = filters.cpp; path = src/filters.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDA5152710C72963000A4F41 /* GArgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GArgs.cpp; path = src/GArgs.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5152810C72963000A4F41 /* GBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GBase.cpp; path = src/GBase.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5152910C72963000A4F41 /* gdna.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gdna.cpp; path = src/gdna.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5152A10C72963000A4F41 /* genes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = genes.cpp; path = src/genes.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GFaSeqGet.cpp; path = src/GFaSeqGet.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5152C10C72963000A4F41 /* gff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gff.cpp; path = src/gff.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5152D10C72963000A4F41 /* GStr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GStr.cpp; path = src/GStr.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5152E10C72963000A4F41 /* gtf_reads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gtf_reads.cpp; path = src/gtf_reads.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5152F10C72963000A4F41 /* gtf_tracking.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gtf_tracking.cpp; path = src/gtf_tracking.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5153010C72963000A4F41 /* hits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = hits.cpp; path = src/hits.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDA5153110C72963000A4F41 /* scaffolds.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = scaffolds.cpp; path = src/scaffolds.cpp; sourceTree = \"<group>\"; };\n\t\tEDA5153210C72963000A4F41 /* tokenize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tokenize.cpp; path = src/tokenize.cpp; sourceTree = \"<group>\"; };\n\t\tEDACE430114EFF5C009024DB /* differential.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; lineEnding = 0; name = differential.h; path = src/differential.h; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDACE431114EFF5C009024DB /* differential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = differential.cpp; path = src/differential.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDACE438114F031B009024DB /* clustering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = clustering.h; path = src/clustering.h; sourceTree = \"<group>\"; };\n\t\tEDACE439114F031B009024DB /* clustering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = clustering.cpp; path = src/clustering.cpp; sourceTree = \"<group>\"; };\n\t\tEDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = biascorrection.cpp; path = src/biascorrection.cpp; sourceTree = \"<group>\"; };\n\t\tEDBAC4C011FF5AD3002B7162 /* biascorrection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = biascorrection.h; path = src/biascorrection.h; sourceTree = \"<group>\"; };\n\t\tEDBBE9C811AA3F5E006AC14A /* transitive_reduction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = transitive_reduction.h; path = src/transitive_reduction.h; sourceTree = \"<group>\"; };\n\t\tEDD0CD9C10C72AC200AF308F /* cufflinks */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = cufflinks; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tEDD0CE2210C72F7D00AF308F /* cuffdiff */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = cuffdiff; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tEDD6A7A0115562EE00D3F668 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Makefile.am; path = src/Makefile.am; sourceTree = \"<group>\"; };\n\t\tEDD6A9D511598ABA00D3F668 /* cufflinks_xcode */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = cufflinks_xcode; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tEDD6AA461159BE6500D3F668 /* test_abundances.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_abundances.cpp; sourceTree = \"<group>\"; };\n\t\tEDD6AA471159BE6500D3F668 /* test_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_main.cpp; sourceTree = \"<group>\"; };\n\t\tEDD94B671205C9E800AA1086 /* cufflinks_xcode */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = cufflinks_xcode; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tEDD94B711205CAF400AA1086 /* gtf_to_sam.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gtf_to_sam.cpp; path = src/gtf_to_sam.cpp; sourceTree = \"<group>\"; };\n\t\tEDDBF70912D29DF000130D8A /* cuffcluster.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cuffcluster.cpp; path = src/cuffcluster.cpp; sourceTree = \"<group>\"; };\n\t\tEDDC08C015064AA600CFC7EF /* ax_check_eigen.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ax_check_eigen.m4; sourceTree = \"<group>\"; };\n\t\tEDE26F1E15115CCB00A5199D /* rounding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rounding.h; path = src/rounding.h; sourceTree = \"<group>\"; };\n\t\tEDE78A2B11B5F4F0000F8846 /* graph_optimize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = graph_optimize.h; path = src/graph_optimize.h; sourceTree = \"<group>\"; };\n\t\tEDE78A2C11B5F4F0000F8846 /* graph_optimize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = graph_optimize.cpp; path = src/graph_optimize.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDE78A7811B6E912000F8846 /* scaffold_graph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scaffold_graph.h; path = src/scaffold_graph.h; sourceTree = \"<group>\"; };\n\t\tEDE78A7911B6E912000F8846 /* scaffold_graph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = scaffold_graph.cpp; path = src/scaffold_graph.cpp; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };\n\t\tEDE78BC411B716C3000F8846 /* matching_merge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = matching_merge.cpp; path = src/matching_merge.cpp; sourceTree = \"<group>\"; };\n\t\tEDE78BC511B716C3000F8846 /* matching_merge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = matching_merge.h; path = src/matching_merge.h; sourceTree = \"<group>\"; };\n\t\tEDEBCDF8112DFD7600E2479E /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = configure.ac; sourceTree = \"<group>\"; };\n\t\tEDEBCEBB112E316400E2479E /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };\n\t\tEDFE39CE122BE65600F24CD3 /* cuffcluster */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = cuffcluster; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tEDFE39FA122BE7B700F24CD3 /* jensen_shannon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = jensen_shannon.cpp; path = src/jensen_shannon.cpp; sourceTree = \"<group>\"; };\n\t\tEDFE39FD122BE7CB00F24CD3 /* jensen_shannon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jensen_shannon.h; path = src/jensen_shannon.h; sourceTree = \"<group>\"; };\n\t\tF4A9F36D17428648000087E1 /* cuffquant.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = cuffquant.cpp; path = src/cuffquant.cpp; sourceTree = \"<group>\"; };\n\t\tF4A9F3C51742865A000087E1 /* cuffquant */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = cuffquant; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tF4A9F3C71742B994000087E1 /* tracking.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tracking.h; path = src/tracking.h; sourceTree = \"<group>\"; };\n\t\tF4A9F3C81742C26D000087E1 /* tracking.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tracking.cpp; path = src/tracking.cpp; sourceTree = \"<group>\"; };\n\t\tF4A9F3CB1742D011000087E1 /* ax_boost_serialization.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ax_boost_serialization.m4; sourceTree = \"<group>\"; };\n\t\tF4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = \"libboost_serialization-mt.a\"; path = \"../../../../opt/local/lib/libboost_serialization-mt.a\"; sourceTree = \"<group>\"; };\n\t\tF4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = \"libboost_system-mt.a\"; path = \"../../../../opt/local/lib/libboost_system-mt.a\"; sourceTree = \"<group>\"; };\n\t\tF4D2AB1418D108EC00BB1CF0 /* libboost_thread-mt.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = \"libboost_thread-mt.a\"; path = \"../../../../opt/local/lib/libboost_thread-mt.a\"; sourceTree = \"<group>\"; };\n\t\tF4D2AB8A18D1124600BB1CF0 /* cuffdiff copy */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = \"cuffdiff copy\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tF4D43F2118D0BA3600AEB7BA /* cuffnorm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = cuffnorm.cpp; path = src/cuffnorm.cpp; sourceTree = \"<group>\"; };\n\t\tF4D43F2818D0BA9900AEB7BA /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = \"<group>\"; };\n\t\tF4D43F2A18D0BA9900AEB7BA /* cuffnorm.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = cuffnorm.1; sourceTree = \"<group>\"; };\n\t\tF4DD461F1625F564008994EC /* negative_binomial_distribution.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = negative_binomial_distribution.h; path = src/negative_binomial_distribution.h; sourceTree = \"<group>\"; };\n\t\tF4E2296816CD261C00D355C5 /* ax_boost_system.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ax_boost_system.m4; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t8DD76F660486A84900D96B5E /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tA2047A18191141C7007193FC /* libbam.a in Frameworks */,\n\t\t\t\tED1C0D7A11D7F94900CFD663 /* libz.dylib in Frameworks */,\n\t\t\t\t0A87350314118DD700E28429 /* libboost_thread-mt.a in Frameworks */,\n\t\t\t\tF4D2AB1518D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */,\n\t\t\t\tF4D2AB1E18D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t9CD6E93713379B7E00CCE1DE /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF4D2AB1918D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */,\n\t\t\t\t9CD6E93A13379B7E00CCE1DE /* libz.dylib in Frameworks */,\n\t\t\t\tF4D2AB2B18D108EC00BB1CF0 /* libboost_thread-mt.a in Frameworks */,\n\t\t\t\tF4D2AB2218D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tED41B830127602C60000B5A2 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF4D2AB1B18D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */,\n\t\t\t\tED41B833127602C60000B5A2 /* libz.dylib in Frameworks */,\n\t\t\t\tF4D2AB2D18D108ED00BB1CF0 /* libboost_thread-mt.a in Frameworks */,\n\t\t\t\tF4D2AB2418D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tEDD0CE1C10C72F7D00AF308F /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tA2047A19191141C7007193FC /* libbam.a in Frameworks */,\n\t\t\t\tF4D2AB1618D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */,\n\t\t\t\tEDE107E911E37CE7005F1F4B /* libz.dylib in Frameworks */,\n\t\t\t\tF4D2AB2818D108EC00BB1CF0 /* libboost_thread-mt.a in Frameworks */,\n\t\t\t\tF4D2AB1F18D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tEDD6A9CF11598AB900D3F668 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF4D2AB1718D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */,\n\t\t\t\tF4D2AB2918D108EC00BB1CF0 /* libboost_thread-mt.a in Frameworks */,\n\t\t\t\tF4D2AB2018D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tEDD94B5F1205C9E800AA1086 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF4D2AB1818D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */,\n\t\t\t\tEDD94B621205C9E800AA1086 /* libz.dylib in Frameworks */,\n\t\t\t\tF4D2AB2A18D108EC00BB1CF0 /* libboost_thread-mt.a in Frameworks */,\n\t\t\t\tF4D2AB2118D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tEDFE39C6122BE65600F24CD3 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF4D2AB1A18D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */,\n\t\t\t\tEDFE39C9122BE65600F24CD3 /* libz.dylib in Frameworks */,\n\t\t\t\tF4D2AB2C18D108ED00BB1CF0 /* libboost_thread-mt.a in Frameworks */,\n\t\t\t\tF4D2AB2318D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF4A9F3BC1742865A000087E1 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tA2047A1A191141C8007193FC /* libbam.a in Frameworks */,\n\t\t\t\tF4D2AB1C18D108EC00BB1CF0 /* libboost_serialization-mt.a in Frameworks */,\n\t\t\t\tF4A9F3C01742865A000087E1 /* libz.dylib in Frameworks */,\n\t\t\t\tF4D2AB2E18D108ED00BB1CF0 /* libboost_thread-mt.a in Frameworks */,\n\t\t\t\tF4D2AB2518D108EC00BB1CF0 /* libboost_system-mt.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF4D2AB8018D1124600BB1CF0 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tA2047A1B191141C8007193FC /* libbam.a in Frameworks */,\n\t\t\t\tF4D2AB8118D1124600BB1CF0 /* libboost_serialization-mt.a in Frameworks */,\n\t\t\t\tF4D2AB8318D1124600BB1CF0 /* libz.dylib in Frameworks */,\n\t\t\t\tF4D2AB8418D1124600BB1CF0 /* libboost_thread-mt.a in Frameworks */,\n\t\t\t\tF4D2AB8518D1124600BB1CF0 /* libboost_system-mt.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t08FB7794FE84155DC02AAC07 /* cufflinks_xcode */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tA2047A17191141C7007193FC /* libbam.a */,\n\t\t\t\tF4D2AB1218D108EC00BB1CF0 /* libboost_serialization-mt.a */,\n\t\t\t\tF4D2AB1318D108EC00BB1CF0 /* libboost_system-mt.a */,\n\t\t\t\tF4D2AB1418D108EC00BB1CF0 /* libboost_thread-mt.a */,\n\t\t\t\tEDD6AA441159BE6500D3F668 /* tests */,\n\t\t\t\t0A25E74A1242E9270080BEA9 /* src */,\n\t\t\t\tC6859E8C029090F304C91782 /* Documentation */,\n\t\t\t\tF4D43F2718D0BA9900AEB7BA /* cuffnorm */,\n\t\t\t\t1AB674ADFE9D54B511CA2CBB /* Products */,\n\t\t\t\tEDEBCEBB112E316400E2479E /* Accelerate.framework */,\n\t\t\t\tED1C0D7911D7F94900CFD663 /* libz.dylib */,\n\t\t\t);\n\t\t\tname = cufflinks_xcode;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0A25E74A1242E9270080BEA9 /* src */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tEDA5151E10C72963000A4F41 /* abundances.cpp */,\n\t\t\t\tEDA5150910C72963000A4F41 /* abundances.h */,\n\t\t\t\tEDA5151F10C72963000A4F41 /* assemble.cpp */,\n\t\t\t\tEDA5150A10C72963000A4F41 /* assemble.h */,\n\t\t\t\tED1C0C6D11D7D9C000CFD663 /* Autotools */,\n\t\t\t\tEDBAC4BF11FF5AD3002B7162 /* biascorrection.cpp */,\n\t\t\t\tEDBAC4C011FF5AD3002B7162 /* biascorrection.h */,\n\t\t\t\tEDA5152010C72963000A4F41 /* bundles.cpp */,\n\t\t\t\tEDA5150B10C72963000A4F41 /* bundles.h */,\n\t\t\t\tEDACE439114F031B009024DB /* clustering.cpp */,\n\t\t\t\tEDACE438114F031B009024DB /* clustering.h */,\n\t\t\t\tEDA5152110C72963000A4F41 /* codons.cpp */,\n\t\t\t\tEDA5150C10C72963000A4F41 /* codons.h */,\n\t\t\t\tEDA5152210C72963000A4F41 /* common.cpp */,\n\t\t\t\tEDA5150D10C72963000A4F41 /* common.h */,\n\t\t\t\t9CD6E8D913379B0900CCE1DE /* compress_gtf.cpp */,\n\t\t\t\tEDDBF70912D29DF000130D8A /* cuffcluster.cpp */,\n\t\t\t\tEDA5152310C72963000A4F41 /* cuffcompare.cpp */,\n\t\t\t\tEDA5152410C72963000A4F41 /* cuffdiff.cpp */,\n\t\t\t\tEDA5152510C72963000A4F41 /* cufflinks.cpp */,\n\t\t\t\tF4D43F2118D0BA3600AEB7BA /* cuffnorm.cpp */,\n\t\t\t\t9CE680F6149697B500855EDB /* cuffmerge */,\n\t\t\t\tF4A9F36D17428648000087E1 /* cuffquant.cpp */,\n\t\t\t\tEDACE431114EFF5C009024DB /* differential.cpp */,\n\t\t\t\tEDACE430114EFF5C009024DB /* differential.h */,\n\t\t\t\tEDA5152610C72963000A4F41 /* filters.cpp */,\n\t\t\t\tEDA5150E10C72963000A4F41 /* filters.h */,\n\t\t\t\tEDA5152710C72963000A4F41 /* GArgs.cpp */,\n\t\t\t\tEDA5150F10C72963000A4F41 /* GArgs.h */,\n\t\t\t\tEDA5152810C72963000A4F41 /* GBase.cpp */,\n\t\t\t\tEDA5151010C72963000A4F41 /* GBase.h */,\n\t\t\t\tEDA5152910C72963000A4F41 /* gdna.cpp */,\n\t\t\t\tEDA5151110C72963000A4F41 /* gdna.h */,\n\t\t\t\tEDA5152A10C72963000A4F41 /* genes.cpp */,\n\t\t\t\tEDA5151210C72963000A4F41 /* genes.h */,\n\t\t\t\tEDA5152B10C72963000A4F41 /* GFaSeqGet.cpp */,\n\t\t\t\tEDA5151310C72963000A4F41 /* GFaSeqGet.h */,\n\t\t\t\tED877B72123BCA3F0025A050 /* GFastaIndex.cpp */,\n\t\t\t\t0A5D9A3F123B5BFE002BEFD5 /* GFastaIndex.h */,\n\t\t\t\tEDA5152C10C72963000A4F41 /* gff.cpp */,\n\t\t\t\tEDA5151510C72963000A4F41 /* gff.h */,\n\t\t\t\tEDA5151C10C72963000A4F41 /* GHash.hh */,\n\t\t\t\tEDA5151D10C72963000A4F41 /* GList.hh */,\n\t\t\t\tEDE78A2C11B5F4F0000F8846 /* graph_optimize.cpp */,\n\t\t\t\tEDE78A2B11B5F4F0000F8846 /* graph_optimize.h */,\n\t\t\t\tEDA5152D10C72963000A4F41 /* GStr.cpp */,\n\t\t\t\tEDA5151610C72963000A4F41 /* GStr.h */,\n\t\t\t\tEDA5152E10C72963000A4F41 /* gtf_reads.cpp */,\n\t\t\t\tEDD94B711205CAF400AA1086 /* gtf_to_sam.cpp */,\n\t\t\t\tEDA5152F10C72963000A4F41 /* gtf_tracking.cpp */,\n\t\t\t\tEDA5151710C72963000A4F41 /* gtf_tracking.h */,\n\t\t\t\tEDA5153010C72963000A4F41 /* hits.cpp */,\n\t\t\t\tEDA5151810C72963000A4F41 /* hits.h */,\n\t\t\t\tEDFE39FA122BE7B700F24CD3 /* jensen_shannon.cpp */,\n\t\t\t\tEDFE39FD122BE7CB00F24CD3 /* jensen_shannon.h */,\n\t\t\t\t9CC50B5813204F180031949A /* locfit */,\n\t\t\t\tEDE78BC411B716C3000F8846 /* matching_merge.cpp */,\n\t\t\t\tEDE78BC511B716C3000F8846 /* matching_merge.h */,\n\t\t\t\t0A6183711324308800EFF9AF /* multireads.cpp */,\n\t\t\t\t0A4C0AD412F734DE0055A9D8 /* multireads.h */,\n\t\t\t\tF4DD461F1625F564008994EC /* negative_binomial_distribution.h */,\n\t\t\t\t0A25E74B1242E95A0080BEA9 /* progressbar.h */,\n\t\t\t\t0A5D9A35123B5BE0002BEFD5 /* GFastaIndex.cpp */,\n\t\t\t\tED677C0D132A3D83000CFDC8 /* replicates.cpp */,\n\t\t\t\tED677C0E132A3D83000CFDC8 /* replicates.h */,\n\t\t\t\tEDE26F1E15115CCB00A5199D /* rounding.h */,\n\t\t\t\t9CE680F8149FBEBD00855EDB /* sampling.cpp */,\n\t\t\t\t9CE680F7149FBE2F00855EDB /* sampling.h */,\n\t\t\t\tEDE78A7911B6E912000F8846 /* scaffold_graph.cpp */,\n\t\t\t\tEDE78A7811B6E912000F8846 /* scaffold_graph.h */,\n\t\t\t\tEDA5153110C72963000A4F41 /* scaffolds.cpp */,\n\t\t\t\tEDA5151910C72963000A4F41 /* scaffolds.h */,\n\t\t\t\tEDA5153210C72963000A4F41 /* tokenize.cpp */,\n\t\t\t\tEDA5151A10C72963000A4F41 /* tokenize.h */,\n\t\t\t\tF4A9F3C81742C26D000087E1 /* tracking.cpp */,\n\t\t\t\tF4A9F3C71742B994000087E1 /* tracking.h */,\n\t\t\t\tEDA5151B10C72963000A4F41 /* transitive_closure.h */,\n\t\t\t\tEDBBE9C811AA3F5E006AC14A /* transitive_reduction.h */,\n\t\t\t\t0ACD78C612E6647B00310E07 /* update_check.h */,\n\t\t\t\tED4835D81249057500642337 /* progressbar.h */,\n\t\t\t\t0A5D9A3F123B5BFE002BEFD5 /* GFastaIndex.h */,\n\t\t\t\t9C40F31B13C78FEF00515339 /* cuffmerge */,\n\t\t\t);\n\t\t\tname = src;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1AB674ADFE9D54B511CA2CBB /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tEDD0CD9C10C72AC200AF308F /* cufflinks */,\n\t\t\t\tEDD0CE2210C72F7D00AF308F /* cuffdiff */,\n\t\t\t\tEDD6A9D511598ABA00D3F668 /* cufflinks_xcode */,\n\t\t\t\tEDD94B671205C9E800AA1086 /* cufflinks_xcode */,\n\t\t\t\tEDFE39CE122BE65600F24CD3 /* cuffcluster */,\n\t\t\t\tED41B838127602C60000B5A2 /* cufflinks_xcode */,\n\t\t\t\t9CD6E93F13379B7E00CCE1DE /* compress_gtf */,\n\t\t\t\tF4A9F3C51742865A000087E1 /* cuffquant */,\n\t\t\t\tF4D2AB8A18D1124600BB1CF0 /* cuffdiff copy */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9CC50B5813204F180031949A /* locfit */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tED920F3613213B19008DDA0B /* dens_haz.c */,\n\t\t\t\tED920F3713213B19008DDA0B /* dens_int.c */,\n\t\t\t\tED920F3813213B19008DDA0B /* dens_odi.c */,\n\t\t\t\tED920F3313213903008DDA0B /* vari.cpp */,\n\t\t\t\tED920F30132137F4008DDA0B /* density.c */,\n\t\t\t\t9CC50B5D13204FE30031949A /* minmax.c */,\n\t\t\t\t9CC50B5E13204FE30031949A /* locfit.c */,\n\t\t\t\t9CC50B5F13204FE30031949A /* ev_interp.c */,\n\t\t\t\t9CC50B6013204FE30031949A /* ev_atree.c */,\n\t\t\t\t9CC50B6113204FE30031949A /* weight.c */,\n\t\t\t\t9CC50B6213204FE40031949A /* wdiag.c */,\n\t\t\t\tED920F4013213C15008DDA0B /* adap.c */,\n\t\t\t\t9CC50B6313204FE40031949A /* strings.c */,\n\t\t\t\tED920F4F132150D9008DDA0B /* pout.c */,\n\t\t\t\tED920F4313213C49008DDA0B /* dist.c */,\n\t\t\t\t9CC50B6413204FE40031949A /* startlf.c */,\n\t\t\t\tED920F4C13213D03008DDA0B /* band.c */,\n\t\t\t\tED920F4913213CDE008DDA0B /* lfd.c */,\n\t\t\t\tED920F5B132158CA008DDA0B /* readfile.c */,\n\t\t\t\tED920F521321520A008DDA0B /* makecmd.c */,\n\t\t\t\tED920F4613213CAE008DDA0B /* random.c */,\n\t\t\t\tED920F5513215828008DDA0B /* help.c */,\n\t\t\t\tED920F581321587C008DDA0B /* c_plot.c */,\n\t\t\t\t9CC50B6513204FE40031949A /* solve.c */,\n\t\t\t\t9CC50B6613204FE40031949A /* simul.c */,\n\t\t\t\t9CC50B6713204FE40031949A /* preplot.c */,\n\t\t\t\t9CC50B6813204FE40031949A /* pcomp.c */,\n\t\t\t\t9CC50B6913204FE40031949A /* nbhd.c */,\n\t\t\t\t9CC50B6A13204FE40031949A /* math.c */,\n\t\t\t\t9CC50B6B13204FE40031949A /* m_max.c */,\n\t\t\t\t9CC50B6C13204FE40031949A /* m_eigen.c */,\n\t\t\t\t9CC50B6D13204FE40031949A /* linalg.c */,\n\t\t\t\t9CC50B6E13204FE40031949A /* lfstr.c */,\n\t\t\t\t9CC50B6F13204FE40031949A /* lf_vari.c */,\n\t\t\t\t9CC50B7013204FE50031949A /* lf_fitfun.c */,\n\t\t\t\t9CC50B7113204FE50031949A /* lf_dercor.c */,\n\t\t\t\t9CC50B7213204FE50031949A /* frend.c */,\n\t\t\t\t9CC50B7313204FE50031949A /* fitted.c */,\n\t\t\t\t9CC50B7413204FE50031949A /* family.c */,\n\t\t\t\t9CC50B7513204FE50031949A /* ev_trian.c */,\n\t\t\t\t9CC50B7613204FE50031949A /* ev_main.c */,\n\t\t\t\t9CC50B7713204FE50031949A /* ev_kdtre.c */,\n\t\t\t\t9CC50B7813204FE60031949A /* scb.c */,\n\t\t\t\t9CC50B7A13204FE60031949A /* scb_cons.c */,\n\t\t\t\t9CC50B7B13204FE60031949A /* local.h */,\n\t\t\t\t9CC50B7D13204FE60031949A /* m_jacob.c */,\n\t\t\t\t9CC50B7F13204FE70031949A /* design.h */,\n\t\t\t\t9CC50B8013204FE70031949A /* lffuns.h */,\n\t\t\t\t9CC50B8113204FE70031949A /* lfstruc.h */,\n\t\t\t\t9CC50B8213204FE70031949A /* mutil.h */,\n\t\t\t\t9CC50B8313204FE80031949A /* lf_robust.c */,\n\t\t\t\t9CC50B8413204FE80031949A /* m_chol.c */,\n\t\t\t\t9CC50B8513204FE80031949A /* lfcons.h */,\n\t\t\t\t9CC50B8913204FE90031949A /* arith.c */,\n\t\t\t\t9CC50B8A13204FE90031949A /* c_args.c */,\n\t\t\t\t9CC50B8B13204FE90031949A /* ar_funs.c */,\n\t\t\t\t9CC50B8E13204FEA0031949A /* lfwin.h */,\n\t\t\t\t9CC50B8F13204FEA0031949A /* imatlb.h */,\n\t\t\t\t9CC50B5913204F180031949A /* cmd.c */,\n\t\t\t\t9C29C3E31339285000EC6E65 /* vari.hpp */,\n\t\t\t);\n\t\t\tname = locfit;\n\t\t\tpath = src/locfit;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tC6859E8C029090F304C91782 /* Documentation */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tname = Documentation;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tED1C0C6D11D7D9C000CFD663 /* Autotools */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tEDDC08C015064AA600CFC7EF /* ax_check_eigen.m4 */,\n\t\t\t\tED1C0CAA11D7E52400CFD663 /* ax_check_zlib.m4 */,\n\t\t\t\tED1C0C7111D7D9E500CFD663 /* ax_boost_base.m4 */,\n\t\t\t\tED1C0C7211D7D9E500CFD663 /* ax_boost_thread.m4 */,\n\t\t\t\tF4A9F3CB1742D011000087E1 /* ax_boost_serialization.m4 */,\n\t\t\t\tF4E2296816CD261C00D355C5 /* ax_boost_system.m4 */,\n\t\t\t\tEDEBCDF8112DFD7600E2479E /* configure.ac */,\n\t\t\t\tEDD6A7A0115562EE00D3F668 /* Makefile.am */,\n\t\t\t\tED1C0C7411D7DA3200CFD663 /* ax_bam.m4 */,\n\t\t\t);\n\t\t\tname = Autotools;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tEDD6AA441159BE6500D3F668 /* tests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tEDD6AA451159BE6500D3F668 /* unit_tests */,\n\t\t\t);\n\t\t\tpath = tests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tEDD6AA451159BE6500D3F668 /* unit_tests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tEDD6AA461159BE6500D3F668 /* test_abundances.cpp */,\n\t\t\t\tEDD6AA471159BE6500D3F668 /* test_main.cpp */,\n\t\t\t\t9C198ABD12F231CD00919C3B /* test_scaffolds.cpp */,\n\t\t\t);\n\t\t\tpath = unit_tests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF4D43F2718D0BA9900AEB7BA /* cuffnorm */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF4D43F2818D0BA9900AEB7BA /* main.cpp */,\n\t\t\t\tF4D43F2A18D0BA9900AEB7BA /* cuffnorm.1 */,\n\t\t\t);\n\t\t\tpath = cuffnorm;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t8DD76F620486A84900D96B5E /* cufflinks */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget \"cufflinks\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t8DD76F640486A84900D96B5E /* Sources */,\n\t\t\t\t8DD76F660486A84900D96B5E /* Frameworks */,\n\t\t\t\t8DD76F690486A84900D96B5E /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = cufflinks;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = cufflinks_xcode;\n\t\t\tproductReference = EDD0CD9C10C72AC200AF308F /* cufflinks */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n\t\t9CD6E8E813379B7E00CCE1DE /* compress_gtf */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 9CD6E93C13379B7E00CCE1DE /* Build configuration list for PBXNativeTarget \"compress_gtf\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t9CD6E8E913379B7E00CCE1DE /* Sources */,\n\t\t\t\t9CD6E93713379B7E00CCE1DE /* Frameworks */,\n\t\t\t\t9CD6E93B13379B7E00CCE1DE /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = compress_gtf;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = cufflinks_xcode;\n\t\t\tproductReference = 9CD6E93F13379B7E00CCE1DE /* compress_gtf */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n\t\tED41B816127602C60000B5A2 /* gtf_reads */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = ED41B835127602C60000B5A2 /* Build configuration list for PBXNativeTarget \"gtf_reads\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tED41B817127602C60000B5A2 /* Sources */,\n\t\t\t\tED41B830127602C60000B5A2 /* Frameworks */,\n\t\t\t\tED41B834127602C60000B5A2 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = gtf_reads;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = cufflinks_xcode;\n\t\t\tproductReference = ED41B838127602C60000B5A2 /* cufflinks_xcode */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n\t\tEDD0CE0810C72F7D00AF308F /* cuffdiff */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = EDD0CE1F10C72F7D00AF308F /* Build configuration list for PBXNativeTarget \"cuffdiff\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tEDD0CE0910C72F7D00AF308F /* Sources */,\n\t\t\t\tEDD0CE1C10C72F7D00AF308F /* Frameworks */,\n\t\t\t\tEDD0CE1E10C72F7D00AF308F /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = cuffdiff;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = cufflinks_xcode;\n\t\t\tproductReference = EDD0CE2210C72F7D00AF308F /* cuffdiff */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n\t\tEDD6A9BA11598AB900D3F668 /* cuffcompare */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = EDD6A9D211598AB900D3F668 /* Build configuration list for PBXNativeTarget \"cuffcompare\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tEDD6A9BB11598AB900D3F668 /* Sources */,\n\t\t\t\tEDD6A9CF11598AB900D3F668 /* Frameworks */,\n\t\t\t\tEDD6A9D111598AB900D3F668 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = cuffcompare;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = cufflinks_xcode;\n\t\t\tproductReference = EDD6A9D511598ABA00D3F668 /* cufflinks_xcode */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n\t\tEDD94B461205C9E800AA1086 /* gtf_to_sam */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = EDD94B641205C9E800AA1086 /* Build configuration list for PBXNativeTarget \"gtf_to_sam\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tEDD94B471205C9E800AA1086 /* Sources */,\n\t\t\t\tEDD94B5F1205C9E800AA1086 /* Frameworks */,\n\t\t\t\tEDD94B631205C9E800AA1086 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = gtf_to_sam;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = cufflinks_xcode;\n\t\t\tproductReference = EDD94B671205C9E800AA1086 /* cufflinks_xcode */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n\t\tEDFE39B0122BE65600F24CD3 /* cuffcluster */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = EDFE39CB122BE65600F24CD3 /* Build configuration list for PBXNativeTarget \"cuffcluster\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tEDFE39B1122BE65600F24CD3 /* Sources */,\n\t\t\t\tEDFE39C6122BE65600F24CD3 /* Frameworks */,\n\t\t\t\tEDFE39CA122BE65600F24CD3 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = cuffcluster;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = cufflinks_xcode;\n\t\t\tproductReference = EDFE39CE122BE65600F24CD3 /* cuffcluster */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n\t\tF4A9F36E1742865A000087E1 /* cuffquant */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = F4A9F3C21742865A000087E1 /* Build configuration list for PBXNativeTarget \"cuffquant\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tF4A9F36F1742865A000087E1 /* Sources */,\n\t\t\t\tF4A9F3BC1742865A000087E1 /* Frameworks */,\n\t\t\t\tF4A9F3C11742865A000087E1 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = cuffquant;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = cufflinks_xcode;\n\t\t\tproductReference = F4A9F3C51742865A000087E1 /* cuffquant */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n\t\tF4D2AB3118D1124600BB1CF0 /* cuffnorm */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = F4D2AB8718D1124600BB1CF0 /* Build configuration list for PBXNativeTarget \"cuffnorm\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tF4D2AB3218D1124600BB1CF0 /* Sources */,\n\t\t\t\tF4D2AB8018D1124600BB1CF0 /* Frameworks */,\n\t\t\t\tF4D2AB8618D1124600BB1CF0 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = cuffnorm;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = cufflinks_xcode;\n\t\t\tproductReference = F4D2AB8A18D1124600BB1CF0 /* cuffdiff copy */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t08FB7793FE84155DC02AAC07 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tBuildIndependentTargetsInParallel = YES;\n\t\t\t\tLastUpgradeCheck = 0510;\n\t\t\t};\n\t\t\tbuildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject \"cufflinks\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 1;\n\t\t\tknownRegions = (\n\t\t\t\tEnglish,\n\t\t\t\tJapanese,\n\t\t\t\tFrench,\n\t\t\t\tGerman,\n\t\t\t);\n\t\t\tmainGroup = 08FB7794FE84155DC02AAC07 /* cufflinks_xcode */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t8DD76F620486A84900D96B5E /* cufflinks */,\n\t\t\t\tEDD0CE0810C72F7D00AF308F /* cuffdiff */,\n\t\t\t\tEDD6A9BA11598AB900D3F668 /* cuffcompare */,\n\t\t\t\tEDD94B461205C9E800AA1086 /* gtf_to_sam */,\n\t\t\t\t9CD6E8E813379B7E00CCE1DE /* compress_gtf */,\n\t\t\t\tEDFE39B0122BE65600F24CD3 /* cuffcluster */,\n\t\t\t\tED41B816127602C60000B5A2 /* gtf_reads */,\n\t\t\t\tF4A9F36E1742865A000087E1 /* cuffquant */,\n\t\t\t\tF4D2AB3118D1124600BB1CF0 /* cuffnorm */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t8DD76F640486A84900D96B5E /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t0A69414F132AEDAB00558D76 /* dens_haz.c in Sources */,\n\t\t\t\t0A694150132AEDAB00558D76 /* dens_int.c in Sources */,\n\t\t\t\t0A694151132AEDAB00558D76 /* dens_odi.c in Sources */,\n\t\t\t\t0A694152132AEDAB00558D76 /* vari.cpp in Sources */,\n\t\t\t\t0A694153132AEDAB00558D76 /* density.c in Sources */,\n\t\t\t\t0A694154132AEDAB00558D76 /* minmax.c in Sources */,\n\t\t\t\t0A694155132AEDAB00558D76 /* locfit.c in Sources */,\n\t\t\t\t0A694156132AEDAB00558D76 /* ev_interp.c in Sources */,\n\t\t\t\t0A694157132AEDAB00558D76 /* ev_atree.c in Sources */,\n\t\t\t\t0A694158132AEDAB00558D76 /* weight.c in Sources */,\n\t\t\t\t0A694159132AEDAB00558D76 /* wdiag.c in Sources */,\n\t\t\t\t0A69415A132AEDAB00558D76 /* adap.c in Sources */,\n\t\t\t\t0A69415B132AEDAB00558D76 /* strings.c in Sources */,\n\t\t\t\t0A69415C132AEDAB00558D76 /* pout.c in Sources */,\n\t\t\t\t0A69415D132AEDAB00558D76 /* dist.c in Sources */,\n\t\t\t\t0A69415E132AEDAB00558D76 /* startlf.c in Sources */,\n\t\t\t\t0A69415F132AEDAB00558D76 /* band.c in Sources */,\n\t\t\t\t0A694160132AEDAB00558D76 /* lfd.c in Sources */,\n\t\t\t\t0A694161132AEDAB00558D76 /* readfile.c in Sources */,\n\t\t\t\t0A694162132AEDAB00558D76 /* makecmd.c in Sources */,\n\t\t\t\t0A694163132AEDAB00558D76 /* random.c in Sources */,\n\t\t\t\t0A694164132AEDAB00558D76 /* help.c in Sources */,\n\t\t\t\t0A694165132AEDAB00558D76 /* c_plot.c in Sources */,\n\t\t\t\t0A694166132AEDAB00558D76 /* solve.c in Sources */,\n\t\t\t\t0A694167132AEDAB00558D76 /* simul.c in Sources */,\n\t\t\t\t0A694168132AEDAB00558D76 /* preplot.c in Sources */,\n\t\t\t\t0A694169132AEDAB00558D76 /* pcomp.c in Sources */,\n\t\t\t\t0A69416A132AEDAC00558D76 /* nbhd.c in Sources */,\n\t\t\t\t0A69416B132AEDAC00558D76 /* math.c in Sources */,\n\t\t\t\t0A69416C132AEDAC00558D76 /* m_max.c in Sources */,\n\t\t\t\t0A69416D132AEDAC00558D76 /* m_eigen.c in Sources */,\n\t\t\t\t0A69416E132AEDAC00558D76 /* linalg.c in Sources */,\n\t\t\t\t0A69416F132AEDAC00558D76 /* lfstr.c in Sources */,\n\t\t\t\t0A694170132AEDAC00558D76 /* lf_vari.c in Sources */,\n\t\t\t\t0A694171132AEDAC00558D76 /* lf_fitfun.c in Sources */,\n\t\t\t\t0A694172132AEDAC00558D76 /* lf_dercor.c in Sources */,\n\t\t\t\t0A694173132AEDAC00558D76 /* frend.c in Sources */,\n\t\t\t\t0A694174132AEDAC00558D76 /* fitted.c in Sources */,\n\t\t\t\t0A694175132AEDAC00558D76 /* family.c in Sources */,\n\t\t\t\t0A694176132AEDAC00558D76 /* ev_trian.c in Sources */,\n\t\t\t\t0A694177132AEDAC00558D76 /* ev_main.c in Sources */,\n\t\t\t\t0A694178132AEDAC00558D76 /* ev_kdtre.c in Sources */,\n\t\t\t\t0A694179132AEDAC00558D76 /* scb.c in Sources */,\n\t\t\t\t0A69417A132AEDAC00558D76 /* scb_cons.c in Sources */,\n\t\t\t\t0A69417C132AEDAC00558D76 /* m_jacob.c in Sources */,\n\t\t\t\t0A694181132AEDAC00558D76 /* lf_robust.c in Sources */,\n\t\t\t\t0A694182132AEDAC00558D76 /* m_chol.c in Sources */,\n\t\t\t\t0A694184132AEDAC00558D76 /* arith.c in Sources */,\n\t\t\t\t0A694185132AEDAC00558D76 /* c_args.c in Sources */,\n\t\t\t\t0A694186132AEDAC00558D76 /* ar_funs.c in Sources */,\n\t\t\t\t0A694189132AEDAC00558D76 /* cmd.c in Sources */,\n\t\t\t\t0A9291D5132AD37100E7B024 /* replicates.cpp in Sources */,\n\t\t\t\tEDA5155210C729A9000A4F41 /* abundances.cpp in Sources */,\n\t\t\t\tEDA5155310C729A9000A4F41 /* assemble.cpp in Sources */,\n\t\t\t\tEDA5155410C729A9000A4F41 /* bundles.cpp in Sources */,\n\t\t\t\tEDA5155510C729A9000A4F41 /* codons.cpp in Sources */,\n\t\t\t\tEDA5155610C729A9000A4F41 /* common.cpp in Sources */,\n\t\t\t\tEDA5155910C729A9000A4F41 /* cufflinks.cpp in Sources */,\n\t\t\t\tEDA5155A10C729A9000A4F41 /* filters.cpp in Sources */,\n\t\t\t\tEDA5155B10C729A9000A4F41 /* GArgs.cpp in Sources */,\n\t\t\t\tEDA5155C10C729A9000A4F41 /* GBase.cpp in Sources */,\n\t\t\t\tEDA5155D10C729A9000A4F41 /* gdna.cpp in Sources */,\n\t\t\t\tEDA5155E10C729A9000A4F41 /* genes.cpp in Sources */,\n\t\t\t\tEDA5155F10C729A9000A4F41 /* GFaSeqGet.cpp in Sources */,\n\t\t\t\tEDA5156010C729A9000A4F41 /* gff.cpp in Sources */,\n\t\t\t\tEDA5156110C729A9000A4F41 /* GStr.cpp in Sources */,\n\t\t\t\tEDA5156310C729A9000A4F41 /* gtf_tracking.cpp in Sources */,\n\t\t\t\tEDA5156410C729A9000A4F41 /* hits.cpp in Sources */,\n\t\t\t\tEDA5156510C729A9000A4F41 /* scaffolds.cpp in Sources */,\n\t\t\t\tEDA5156610C729A9000A4F41 /* tokenize.cpp in Sources */,\n\t\t\t\tEDACE43B114F031B009024DB /* clustering.cpp in Sources */,\n\t\t\t\tEDE78A2D11B5F4F0000F8846 /* graph_optimize.cpp in Sources */,\n\t\t\t\tEDE78A7A11B6E912000F8846 /* scaffold_graph.cpp in Sources */,\n\t\t\t\tEDE78BC611B716C3000F8846 /* matching_merge.cpp in Sources */,\n\t\t\t\tEDBAC4C111FF5AD3002B7162 /* biascorrection.cpp in Sources */,\n\t\t\t\tED877B74123BCA3F0025A050 /* GFastaIndex.cpp in Sources */,\n\t\t\t\t0A6183721324308800EFF9AF /* multireads.cpp in Sources */,\n\t\t\t\t9C31043215250D8600F56669 /* jensen_shannon.cpp in Sources */,\n\t\t\t\t9CE680F9149FBEBD00855EDB /* sampling.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t9CD6E8E913379B7E00CCE1DE /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t9CD6E94113379B9D00CCE1DE /* compress_gtf.cpp in Sources */,\n\t\t\t\t9CD6E8EA13379B7E00CCE1DE /* GFastaIndex.cpp in Sources */,\n\t\t\t\t9CD6E8EB13379B7E00CCE1DE /* abundances.cpp in Sources */,\n\t\t\t\t9CD6E8EC13379B7E00CCE1DE /* assemble.cpp in Sources */,\n\t\t\t\t9CD6E8ED13379B7E00CCE1DE /* bundles.cpp in Sources */,\n\t\t\t\t9CD6E8EE13379B7E00CCE1DE /* codons.cpp in Sources */,\n\t\t\t\t9CD6E8EF13379B7E00CCE1DE /* common.cpp in Sources */,\n\t\t\t\t9CD6E8F013379B7E00CCE1DE /* filters.cpp in Sources */,\n\t\t\t\t9CD6E8F113379B7E00CCE1DE /* GArgs.cpp in Sources */,\n\t\t\t\t9CD6E8F213379B7E00CCE1DE /* GBase.cpp in Sources */,\n\t\t\t\t9CD6E8F313379B7E00CCE1DE /* gdna.cpp in Sources */,\n\t\t\t\t9CD6E8F413379B7E00CCE1DE /* genes.cpp in Sources */,\n\t\t\t\t9CD6E8F513379B7E00CCE1DE /* GFaSeqGet.cpp in Sources */,\n\t\t\t\t9CD6E8F613379B7E00CCE1DE /* gff.cpp in Sources */,\n\t\t\t\t9CD6E8F713379B7E00CCE1DE /* GStr.cpp in Sources */,\n\t\t\t\t9CD6E8F813379B7E00CCE1DE /* gtf_tracking.cpp in Sources */,\n\t\t\t\t9CD6E8FA13379B7E00CCE1DE /* hits.cpp in Sources */,\n\t\t\t\t9CD6E8FB13379B7E00CCE1DE /* scaffolds.cpp in Sources */,\n\t\t\t\t9CD6E8FC13379B7E00CCE1DE /* tokenize.cpp in Sources */,\n\t\t\t\t9CD6E8FD13379B7E00CCE1DE /* clustering.cpp in Sources */,\n\t\t\t\t9CD6E8FE13379B7E00CCE1DE /* graph_optimize.cpp in Sources */,\n\t\t\t\t9CD6E8FF13379B7E00CCE1DE /* scaffold_graph.cpp in Sources */,\n\t\t\t\t9CD6E90013379B7E00CCE1DE /* matching_merge.cpp in Sources */,\n\t\t\t\t9CD6E90113379B7E00CCE1DE /* biascorrection.cpp in Sources */,\n\t\t\t\t9CD6E90213379B7E00CCE1DE /* multireads.cpp in Sources */,\n\t\t\t\t9CD6E90313379B7E00CCE1DE /* replicates.cpp in Sources */,\n\t\t\t\t9CD6E90413379B7E00CCE1DE /* dens_haz.c in Sources */,\n\t\t\t\t9CD6E90513379B7E00CCE1DE /* dens_int.c in Sources */,\n\t\t\t\t9CD6E90613379B7E00CCE1DE /* dens_odi.c in Sources */,\n\t\t\t\t9CD6E90713379B7E00CCE1DE /* vari.cpp in Sources */,\n\t\t\t\t9CD6E90813379B7E00CCE1DE /* density.c in Sources */,\n\t\t\t\t9CD6E90913379B7E00CCE1DE /* minmax.c in Sources */,\n\t\t\t\t9CD6E90A13379B7E00CCE1DE /* locfit.c in Sources */,\n\t\t\t\t9CD6E90B13379B7E00CCE1DE /* ev_interp.c in Sources */,\n\t\t\t\t9CD6E90C13379B7E00CCE1DE /* ev_atree.c in Sources */,\n\t\t\t\t9CD6E90D13379B7E00CCE1DE /* weight.c in Sources */,\n\t\t\t\t9CD6E90E13379B7E00CCE1DE /* wdiag.c in Sources */,\n\t\t\t\t9CD6E90F13379B7E00CCE1DE /* adap.c in Sources */,\n\t\t\t\t9CD6E91013379B7E00CCE1DE /* strings.c in Sources */,\n\t\t\t\t9CD6E91113379B7E00CCE1DE /* pout.c in Sources */,\n\t\t\t\t9CD6E91213379B7E00CCE1DE /* dist.c in Sources */,\n\t\t\t\t9CD6E91313379B7E00CCE1DE /* startlf.c in Sources */,\n\t\t\t\t9CD6E91413379B7E00CCE1DE /* band.c in Sources */,\n\t\t\t\t9CD6E91513379B7E00CCE1DE /* lfd.c in Sources */,\n\t\t\t\t9CD6E91613379B7E00CCE1DE /* readfile.c in Sources */,\n\t\t\t\t9CD6E91713379B7E00CCE1DE /* makecmd.c in Sources */,\n\t\t\t\t9CD6E91813379B7E00CCE1DE /* random.c in Sources */,\n\t\t\t\t9CD6E91913379B7E00CCE1DE /* help.c in Sources */,\n\t\t\t\t9CD6E91A13379B7E00CCE1DE /* c_plot.c in Sources */,\n\t\t\t\t9CD6E91B13379B7E00CCE1DE /* solve.c in Sources */,\n\t\t\t\t9CD6E91C13379B7E00CCE1DE /* simul.c in Sources */,\n\t\t\t\t9CD6E91D13379B7E00CCE1DE /* preplot.c in Sources */,\n\t\t\t\t9CD6E91E13379B7E00CCE1DE /* pcomp.c in Sources */,\n\t\t\t\t9CD6E91F13379B7E00CCE1DE /* nbhd.c in Sources */,\n\t\t\t\t9CD6E92013379B7E00CCE1DE /* math.c in Sources */,\n\t\t\t\t9CD6E92113379B7E00CCE1DE /* m_max.c in Sources */,\n\t\t\t\t9CD6E92213379B7E00CCE1DE /* m_eigen.c in Sources */,\n\t\t\t\t9CD6E92313379B7E00CCE1DE /* linalg.c in Sources */,\n\t\t\t\t9CD6E92413379B7E00CCE1DE /* lfstr.c in Sources */,\n\t\t\t\t9CD6E92513379B7E00CCE1DE /* lf_vari.c in Sources */,\n\t\t\t\t9CD6E92613379B7E00CCE1DE /* lf_fitfun.c in Sources */,\n\t\t\t\t9CD6E92713379B7E00CCE1DE /* lf_dercor.c in Sources */,\n\t\t\t\t9CD6E92813379B7E00CCE1DE /* frend.c in Sources */,\n\t\t\t\t9CD6E92913379B7E00CCE1DE /* fitted.c in Sources */,\n\t\t\t\t9CD6E92A13379B7E00CCE1DE /* family.c in Sources */,\n\t\t\t\t9CD6E92B13379B7E00CCE1DE /* ev_trian.c in Sources */,\n\t\t\t\t9CD6E92C13379B7E00CCE1DE /* ev_main.c in Sources */,\n\t\t\t\t9CD6E92D13379B7E00CCE1DE /* ev_kdtre.c in Sources */,\n\t\t\t\t9CD6E92E13379B7E00CCE1DE /* scb.c in Sources */,\n\t\t\t\t9CD6E92F13379B7E00CCE1DE /* scb_cons.c in Sources */,\n\t\t\t\t9CD6E93013379B7E00CCE1DE /* m_jacob.c in Sources */,\n\t\t\t\t9CD6E93113379B7E00CCE1DE /* lf_robust.c in Sources */,\n\t\t\t\t9CD6E93213379B7E00CCE1DE /* m_chol.c in Sources */,\n\t\t\t\t9CD6E93313379B7E00CCE1DE /* arith.c in Sources */,\n\t\t\t\t9CD6E93413379B7E00CCE1DE /* c_args.c in Sources */,\n\t\t\t\t9CD6E93513379B7E00CCE1DE /* ar_funs.c in Sources */,\n\t\t\t\t9CD6E93613379B7E00CCE1DE /* cmd.c in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tED41B817127602C60000B5A2 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tED41B83E127603A20000B5A2 /* gtf_reads.cpp in Sources */,\n\t\t\t\tED41B818127602C60000B5A2 /* GFastaIndex.cpp in Sources */,\n\t\t\t\tED41B819127602C60000B5A2 /* abundances.cpp in Sources */,\n\t\t\t\tED41B81A127602C60000B5A2 /* assemble.cpp in Sources */,\n\t\t\t\tED41B81B127602C60000B5A2 /* bundles.cpp in Sources */,\n\t\t\t\tED41B81C127602C60000B5A2 /* codons.cpp in Sources */,\n\t\t\t\tED41B81D127602C60000B5A2 /* common.cpp in Sources */,\n\t\t\t\tED41B81E127602C60000B5A2 /* filters.cpp in Sources */,\n\t\t\t\tED41B81F127602C60000B5A2 /* GArgs.cpp in Sources */,\n\t\t\t\tED41B820127602C60000B5A2 /* GBase.cpp in Sources */,\n\t\t\t\tED41B821127602C60000B5A2 /* gdna.cpp in Sources */,\n\t\t\t\tED41B822127602C60000B5A2 /* genes.cpp in Sources */,\n\t\t\t\tED41B823127602C60000B5A2 /* GFaSeqGet.cpp in Sources */,\n\t\t\t\tED41B824127602C60000B5A2 /* gff.cpp in Sources */,\n\t\t\t\tED41B825127602C60000B5A2 /* GStr.cpp in Sources */,\n\t\t\t\tED41B826127602C60000B5A2 /* gtf_tracking.cpp in Sources */,\n\t\t\t\tED41B828127602C60000B5A2 /* hits.cpp in Sources */,\n\t\t\t\tED41B829127602C60000B5A2 /* scaffolds.cpp in Sources */,\n\t\t\t\tED41B82A127602C60000B5A2 /* tokenize.cpp in Sources */,\n\t\t\t\tED41B82B127602C60000B5A2 /* clustering.cpp in Sources */,\n\t\t\t\tED41B82C127602C60000B5A2 /* graph_optimize.cpp in Sources */,\n\t\t\t\tED41B82D127602C60000B5A2 /* scaffold_graph.cpp in Sources */,\n\t\t\t\tED41B82E127602C60000B5A2 /* matching_merge.cpp in Sources */,\n\t\t\t\tED41B82F127602C60000B5A2 /* biascorrection.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tEDD0CE0910C72F7D00AF308F /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tEDD0CE2410C72F9300AF308F /* cuffdiff.cpp in Sources */,\n\t\t\t\tEDD0CE0A10C72F7D00AF308F /* abundances.cpp in Sources */,\n\t\t\t\tEDD0CE0C10C72F7D00AF308F /* bundles.cpp in Sources */,\n\t\t\t\tEDD0CE0D10C72F7D00AF308F /* codons.cpp in Sources */,\n\t\t\t\tEDD0CE0E10C72F7D00AF308F /* common.cpp in Sources */,\n\t\t\t\tEDD0CE1010C72F7D00AF308F /* filters.cpp in Sources */,\n\t\t\t\tEDD0CE1110C72F7D00AF308F /* GArgs.cpp in Sources */,\n\t\t\t\tEDD0CE1210C72F7D00AF308F /* GBase.cpp in Sources */,\n\t\t\t\tEDD0CE1310C72F7D00AF308F /* gdna.cpp in Sources */,\n\t\t\t\tEDD0CE1410C72F7D00AF308F /* genes.cpp in Sources */,\n\t\t\t\tEDD0CE1510C72F7D00AF308F /* GFaSeqGet.cpp in Sources */,\n\t\t\t\tEDD0CE1610C72F7D00AF308F /* gff.cpp in Sources */,\n\t\t\t\tEDD0CE1710C72F7D00AF308F /* GStr.cpp in Sources */,\n\t\t\t\tEDD0CE1810C72F7D00AF308F /* gtf_tracking.cpp in Sources */,\n\t\t\t\tEDD0CE1910C72F7D00AF308F /* hits.cpp in Sources */,\n\t\t\t\tEDD0CE1A10C72F7D00AF308F /* scaffolds.cpp in Sources */,\n\t\t\t\tEDD0CE1B10C72F7D00AF308F /* tokenize.cpp in Sources */,\n\t\t\t\tEDACE432114EFF5C009024DB /* differential.cpp in Sources */,\n\t\t\t\tEDACE43A114F031B009024DB /* clustering.cpp in Sources */,\n\t\t\t\tEDBAC4C211FF5AD3002B7162 /* biascorrection.cpp in Sources */,\n\t\t\t\tEDFE39FC122BE7B700F24CD3 /* jensen_shannon.cpp in Sources */,\n\t\t\t\tED877B73123BCA3F0025A050 /* GFastaIndex.cpp in Sources */,\n\t\t\t\tED920F0C132136BE008DDA0B /* minmax.c in Sources */,\n\t\t\t\tED920F0D132136BE008DDA0B /* locfit.c in Sources */,\n\t\t\t\tED920F0E132136BE008DDA0B /* ev_interp.c in Sources */,\n\t\t\t\tED920F0F132136BE008DDA0B /* ev_atree.c in Sources */,\n\t\t\t\tED920F10132136BE008DDA0B /* weight.c in Sources */,\n\t\t\t\tED920F11132136BE008DDA0B /* wdiag.c in Sources */,\n\t\t\t\tED920F12132136BE008DDA0B /* strings.c in Sources */,\n\t\t\t\tED920F14132136BE008DDA0B /* solve.c in Sources */,\n\t\t\t\tED920F15132136BE008DDA0B /* simul.c in Sources */,\n\t\t\t\tED920F16132136BE008DDA0B /* preplot.c in Sources */,\n\t\t\t\tED920F17132136BE008DDA0B /* pcomp.c in Sources */,\n\t\t\t\tED920F18132136BE008DDA0B /* nbhd.c in Sources */,\n\t\t\t\tED920F19132136BE008DDA0B /* math.c in Sources */,\n\t\t\t\tED920F1A132136BE008DDA0B /* m_max.c in Sources */,\n\t\t\t\tED920F1B132136BE008DDA0B /* m_eigen.c in Sources */,\n\t\t\t\tED920F1C132136BE008DDA0B /* linalg.c in Sources */,\n\t\t\t\tED920F1D132136BE008DDA0B /* lfstr.c in Sources */,\n\t\t\t\tED920F1E132136BE008DDA0B /* lf_vari.c in Sources */,\n\t\t\t\tED920F1F132136BE008DDA0B /* lf_fitfun.c in Sources */,\n\t\t\t\tED920F20132136BE008DDA0B /* lf_dercor.c in Sources */,\n\t\t\t\tED920F21132136BE008DDA0B /* frend.c in Sources */,\n\t\t\t\tED920F22132136BE008DDA0B /* fitted.c in Sources */,\n\t\t\t\tED920F23132136BE008DDA0B /* family.c in Sources */,\n\t\t\t\tED920F24132136BE008DDA0B /* ev_trian.c in Sources */,\n\t\t\t\tED920F25132136BE008DDA0B /* ev_main.c in Sources */,\n\t\t\t\tED920F26132136BE008DDA0B /* ev_kdtre.c in Sources */,\n\t\t\t\tED920F27132136BE008DDA0B /* scb.c in Sources */,\n\t\t\t\tED920F28132136BE008DDA0B /* scb_cons.c in Sources */,\n\t\t\t\tED920F29132136CE008DDA0B /* m_jacob.c in Sources */,\n\t\t\t\tED920F2A132136CE008DDA0B /* lf_robust.c in Sources */,\n\t\t\t\tED920F2B132136CE008DDA0B /* m_chol.c in Sources */,\n\t\t\t\tED920F2C132136CE008DDA0B /* arith.c in Sources */,\n\t\t\t\tED920F2D132136CE008DDA0B /* c_args.c in Sources */,\n\t\t\t\tED920F2E132136CE008DDA0B /* ar_funs.c in Sources */,\n\t\t\t\tED920F2F132136CE008DDA0B /* cmd.c in Sources */,\n\t\t\t\tED920F31132137F4008DDA0B /* density.c in Sources */,\n\t\t\t\tED920F3413213903008DDA0B /* vari.cpp in Sources */,\n\t\t\t\tED920F3913213B19008DDA0B /* dens_haz.c in Sources */,\n\t\t\t\tED920F3B13213B19008DDA0B /* dens_int.c in Sources */,\n\t\t\t\tED920F3D13213B19008DDA0B /* dens_odi.c in Sources */,\n\t\t\t\tED920F3F13213BAC008DDA0B /* startlf.c in Sources */,\n\t\t\t\tED920F4113213C15008DDA0B /* adap.c in Sources */,\n\t\t\t\tED920F4413213C49008DDA0B /* dist.c in Sources */,\n\t\t\t\tED920F4713213CAF008DDA0B /* random.c in Sources */,\n\t\t\t\tED920F4A13213CDF008DDA0B /* lfd.c in Sources */,\n\t\t\t\tED920F4D13213D03008DDA0B /* band.c in Sources */,\n\t\t\t\tED920F50132150D9008DDA0B /* pout.c in Sources */,\n\t\t\t\tED920F531321520A008DDA0B /* makecmd.c in Sources */,\n\t\t\t\tED920F5613215828008DDA0B /* help.c in Sources */,\n\t\t\t\tED920F591321587C008DDA0B /* c_plot.c in Sources */,\n\t\t\t\tED920F5C132158CA008DDA0B /* readfile.c in Sources */,\n\t\t\t\t0A6183731324308800EFF9AF /* multireads.cpp in Sources */,\n\t\t\t\tED677C0F132A3D83000CFDC8 /* replicates.cpp in Sources */,\n\t\t\t\t9CE680FB149FBF3000855EDB /* sampling.cpp in Sources */,\n\t\t\t\tF4A9F3C91742C26D000087E1 /* tracking.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tEDD6A9BB11598AB900D3F668 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tEDD6A9DE11598CFC00D3F668 /* cuffcompare.cpp in Sources */,\n\t\t\t\tEDD6A9BF11598AB900D3F668 /* codons.cpp in Sources */,\n\t\t\t\tEDD6A9C311598AB900D3F668 /* GArgs.cpp in Sources */,\n\t\t\t\tEDD6A9C411598AB900D3F668 /* GBase.cpp in Sources */,\n\t\t\t\tEDD6A9C511598AB900D3F668 /* gdna.cpp in Sources */,\n\t\t\t\tEDD6A9C711598AB900D3F668 /* GFaSeqGet.cpp in Sources */,\n\t\t\t\tEDD6A9C811598AB900D3F668 /* gff.cpp in Sources */,\n\t\t\t\tEDD6A9C911598AB900D3F668 /* GStr.cpp in Sources */,\n\t\t\t\tEDD6A9CA11598AB900D3F668 /* gtf_tracking.cpp in Sources */,\n\t\t\t\tED877B75123BCA3F0025A050 /* GFastaIndex.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tEDD94B471205C9E800AA1086 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tED48324B123E83D100642337 /* GFastaIndex.cpp in Sources */,\n\t\t\t\tEDD94B481205C9E800AA1086 /* abundances.cpp in Sources */,\n\t\t\t\tEDD94B491205C9E800AA1086 /* assemble.cpp in Sources */,\n\t\t\t\tEDD94B4A1205C9E800AA1086 /* bundles.cpp in Sources */,\n\t\t\t\tEDD94B4B1205C9E800AA1086 /* codons.cpp in Sources */,\n\t\t\t\tEDD94B4C1205C9E800AA1086 /* common.cpp in Sources */,\n\t\t\t\tEDD94B4E1205C9E800AA1086 /* filters.cpp in Sources */,\n\t\t\t\tEDD94B4F1205C9E800AA1086 /* GArgs.cpp in Sources */,\n\t\t\t\tEDD94B501205C9E800AA1086 /* GBase.cpp in Sources */,\n\t\t\t\tEDD94B511205C9E800AA1086 /* gdna.cpp in Sources */,\n\t\t\t\tEDD94B521205C9E800AA1086 /* genes.cpp in Sources */,\n\t\t\t\tEDD94B531205C9E800AA1086 /* GFaSeqGet.cpp in Sources */,\n\t\t\t\tEDD94B541205C9E800AA1086 /* gff.cpp in Sources */,\n\t\t\t\tEDD94B551205C9E800AA1086 /* GStr.cpp in Sources */,\n\t\t\t\tEDD94B561205C9E800AA1086 /* gtf_tracking.cpp in Sources */,\n\t\t\t\tEDD94B741205CB1700AA1086 /* gtf_to_sam.cpp in Sources */,\n\t\t\t\tEDD94B571205C9E800AA1086 /* hits.cpp in Sources */,\n\t\t\t\tEDD94B581205C9E800AA1086 /* scaffolds.cpp in Sources */,\n\t\t\t\tEDD94B591205C9E800AA1086 /* tokenize.cpp in Sources */,\n\t\t\t\tEDD94B5A1205C9E800AA1086 /* clustering.cpp in Sources */,\n\t\t\t\tEDD94B5B1205C9E800AA1086 /* graph_optimize.cpp in Sources */,\n\t\t\t\tEDD94B5C1205C9E800AA1086 /* scaffold_graph.cpp in Sources */,\n\t\t\t\tEDD94B5D1205C9E800AA1086 /* matching_merge.cpp in Sources */,\n\t\t\t\tEDD94B5E1205C9E800AA1086 /* biascorrection.cpp in Sources */,\n\t\t\t\t9CBCD9B41333EB5B0059FE74 /* multireads.cpp in Sources */,\n\t\t\t\t9CBCD9B51333ECCE0059FE74 /* replicates.cpp in Sources */,\n\t\t\t\t9CBCD9B61333ECF50059FE74 /* dens_haz.c in Sources */,\n\t\t\t\t9CBCD9B71333ECF50059FE74 /* dens_int.c in Sources */,\n\t\t\t\t9CBCD9B81333ECF50059FE74 /* dens_odi.c in Sources */,\n\t\t\t\t9CBCD9B91333ECF50059FE74 /* vari.cpp in Sources */,\n\t\t\t\t9CBCD9BA1333ECF50059FE74 /* density.c in Sources */,\n\t\t\t\t9CBCD9BB1333ECF50059FE74 /* minmax.c in Sources */,\n\t\t\t\t9CBCD9BC1333ECF50059FE74 /* locfit.c in Sources */,\n\t\t\t\t9CBCD9BD1333ECF50059FE74 /* ev_interp.c in Sources */,\n\t\t\t\t9CBCD9BE1333ECF50059FE74 /* ev_atree.c in Sources */,\n\t\t\t\t9CBCD9BF1333ECF50059FE74 /* weight.c in Sources */,\n\t\t\t\t9CBCD9C01333ECF50059FE74 /* wdiag.c in Sources */,\n\t\t\t\t9CBCD9C11333ECF50059FE74 /* adap.c in Sources */,\n\t\t\t\t9CBCD9C21333ECF50059FE74 /* strings.c in Sources */,\n\t\t\t\t9CBCD9C31333ECF50059FE74 /* pout.c in Sources */,\n\t\t\t\t9CBCD9C41333ECF50059FE74 /* dist.c in Sources */,\n\t\t\t\t9CBCD9C51333ECF50059FE74 /* startlf.c in Sources */,\n\t\t\t\t9CBCD9C61333ECF50059FE74 /* band.c in Sources */,\n\t\t\t\t9CBCD9C71333ECF50059FE74 /* lfd.c in Sources */,\n\t\t\t\t9CBCD9C81333ECF50059FE74 /* readfile.c in Sources */,\n\t\t\t\t9CBCD9C91333ECF50059FE74 /* makecmd.c in Sources */,\n\t\t\t\t9CBCD9CA1333ECF50059FE74 /* random.c in Sources */,\n\t\t\t\t9CBCD9CB1333ECF50059FE74 /* help.c in Sources */,\n\t\t\t\t9CBCD9CC1333ECF50059FE74 /* c_plot.c in Sources */,\n\t\t\t\t9CBCD9CD1333ECF50059FE74 /* solve.c in Sources */,\n\t\t\t\t9CBCD9CE1333ECF50059FE74 /* simul.c in Sources */,\n\t\t\t\t9CBCD9CF1333ECF50059FE74 /* preplot.c in Sources */,\n\t\t\t\t9CBCD9D01333ECF50059FE74 /* pcomp.c in Sources */,\n\t\t\t\t9CBCD9D11333ECF50059FE74 /* nbhd.c in Sources */,\n\t\t\t\t9CBCD9D21333ECF50059FE74 /* math.c in Sources */,\n\t\t\t\t9CBCD9D31333ECF50059FE74 /* m_max.c in Sources */,\n\t\t\t\t9CBCD9D41333ECF50059FE74 /* m_eigen.c in Sources */,\n\t\t\t\t9CBCD9D51333ECF50059FE74 /* linalg.c in Sources */,\n\t\t\t\t9CBCD9D61333ECF50059FE74 /* lfstr.c in Sources */,\n\t\t\t\t9CBCD9D71333ECF50059FE74 /* lf_vari.c in Sources */,\n\t\t\t\t9CBCD9D81333ECF50059FE74 /* lf_fitfun.c in Sources */,\n\t\t\t\t9CBCD9D91333ECF50059FE74 /* lf_dercor.c in Sources */,\n\t\t\t\t9CBCD9DA1333ECF50059FE74 /* frend.c in Sources */,\n\t\t\t\t9CBCD9DB1333ECF50059FE74 /* fitted.c in Sources */,\n\t\t\t\t9CBCD9DC1333ECF50059FE74 /* family.c in Sources */,\n\t\t\t\t9CBCD9DD1333ECF50059FE74 /* ev_trian.c in Sources */,\n\t\t\t\t9CBCD9DE1333ECF50059FE74 /* ev_main.c in Sources */,\n\t\t\t\t9CBCD9DF1333ECF50059FE74 /* ev_kdtre.c in Sources */,\n\t\t\t\t9CBCD9E01333ECF50059FE74 /* scb.c in Sources */,\n\t\t\t\t9CBCD9E11333ECF50059FE74 /* scb_cons.c in Sources */,\n\t\t\t\t9CBCD9E21333ECFD0059FE74 /* m_jacob.c in Sources */,\n\t\t\t\t9CBCD9E31333ECFD0059FE74 /* lf_robust.c in Sources */,\n\t\t\t\t9CBCD9E41333ECFD0059FE74 /* m_chol.c in Sources */,\n\t\t\t\t9CBCD9E51333ECFD0059FE74 /* arith.c in Sources */,\n\t\t\t\t9CBCD9E61333ECFD0059FE74 /* c_args.c in Sources */,\n\t\t\t\t9CBCD9E71333ECFD0059FE74 /* ar_funs.c in Sources */,\n\t\t\t\t9CBCD9E81333ECFD0059FE74 /* cmd.c in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tEDFE39B1122BE65600F24CD3 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t9CCF1F59135E29E400D7D6BD /* m_jacob.c in Sources */,\n\t\t\t\t9CCF1F5A135E29E400D7D6BD /* lf_robust.c in Sources */,\n\t\t\t\t9CCF1F5B135E29E400D7D6BD /* m_chol.c in Sources */,\n\t\t\t\t9CCF1F5C135E29E400D7D6BD /* arith.c in Sources */,\n\t\t\t\t9CCF1F5D135E29E400D7D6BD /* c_args.c in Sources */,\n\t\t\t\t9CCF1F5E135E29E400D7D6BD /* ar_funs.c in Sources */,\n\t\t\t\t9CCF1F5F135E29E400D7D6BD /* cmd.c in Sources */,\n\t\t\t\t9CCF1F3C135E29D600D7D6BD /* minmax.c in Sources */,\n\t\t\t\t9CCF1F3D135E29D600D7D6BD /* locfit.c in Sources */,\n\t\t\t\t9CCF1F3E135E29D600D7D6BD /* ev_interp.c in Sources */,\n\t\t\t\t9CCF1F3F135E29D600D7D6BD /* ev_atree.c in Sources */,\n\t\t\t\t9CCF1F40135E29D600D7D6BD /* weight.c in Sources */,\n\t\t\t\t9CCF1F41135E29D600D7D6BD /* wdiag.c in Sources */,\n\t\t\t\t9CCF1F42135E29D600D7D6BD /* strings.c in Sources */,\n\t\t\t\t9CCF1F43135E29D600D7D6BD /* startlf.c in Sources */,\n\t\t\t\t9CCF1F44135E29D600D7D6BD /* solve.c in Sources */,\n\t\t\t\t9CCF1F45135E29D600D7D6BD /* simul.c in Sources */,\n\t\t\t\t9CCF1F46135E29D700D7D6BD /* preplot.c in Sources */,\n\t\t\t\t9CCF1F47135E29D700D7D6BD /* pcomp.c in Sources */,\n\t\t\t\t9CCF1F48135E29D700D7D6BD /* nbhd.c in Sources */,\n\t\t\t\t9CCF1F49135E29D700D7D6BD /* math.c in Sources */,\n\t\t\t\t9CCF1F4A135E29D700D7D6BD /* m_max.c in Sources */,\n\t\t\t\t9CCF1F4B135E29D700D7D6BD /* m_eigen.c in Sources */,\n\t\t\t\t9CCF1F4C135E29D700D7D6BD /* linalg.c in Sources */,\n\t\t\t\t9CCF1F4D135E29D700D7D6BD /* lfstr.c in Sources */,\n\t\t\t\t9CCF1F4E135E29D700D7D6BD /* lf_vari.c in Sources */,\n\t\t\t\t9CCF1F4F135E29D700D7D6BD /* lf_fitfun.c in Sources */,\n\t\t\t\t9CCF1F50135E29D700D7D6BD /* lf_dercor.c in Sources */,\n\t\t\t\t9CCF1F51135E29D700D7D6BD /* frend.c in Sources */,\n\t\t\t\t9CCF1F52135E29D700D7D6BD /* fitted.c in Sources */,\n\t\t\t\t9CCF1F53135E29D700D7D6BD /* family.c in Sources */,\n\t\t\t\t9CCF1F54135E29D700D7D6BD /* ev_trian.c in Sources */,\n\t\t\t\t9CCF1F55135E29D700D7D6BD /* ev_main.c in Sources */,\n\t\t\t\t9CCF1F56135E29D700D7D6BD /* ev_kdtre.c in Sources */,\n\t\t\t\t9CCF1F57135E29D700D7D6BD /* scb.c in Sources */,\n\t\t\t\t9CCF1F58135E29D700D7D6BD /* scb_cons.c in Sources */,\n\t\t\t\tEDFE39B6122BE65600F24CD3 /* common.cpp in Sources */,\n\t\t\t\tEDFE39C2122BE65600F24CD3 /* tokenize.cpp in Sources */,\n\t\t\t\tEDFE39FB122BE7B700F24CD3 /* jensen_shannon.cpp in Sources */,\n\t\t\t\tEDDBF70A12D29DF000130D8A /* cuffcluster.cpp in Sources */,\n\t\t\t\tED920F32132137F4008DDA0B /* density.c in Sources */,\n\t\t\t\tED920F3513213903008DDA0B /* vari.cpp in Sources */,\n\t\t\t\tED920F3A13213B19008DDA0B /* dens_haz.c in Sources */,\n\t\t\t\tED920F3C13213B19008DDA0B /* dens_int.c in Sources */,\n\t\t\t\tED920F3E13213B19008DDA0B /* dens_odi.c in Sources */,\n\t\t\t\tED920F4213213C15008DDA0B /* adap.c in Sources */,\n\t\t\t\tED920F4513213C49008DDA0B /* dist.c in Sources */,\n\t\t\t\tED920F4813213CAF008DDA0B /* random.c in Sources */,\n\t\t\t\tED920F4B13213CDF008DDA0B /* lfd.c in Sources */,\n\t\t\t\tED920F4E13213D03008DDA0B /* band.c in Sources */,\n\t\t\t\tED920F51132150D9008DDA0B /* pout.c in Sources */,\n\t\t\t\tED920F541321520A008DDA0B /* makecmd.c in Sources */,\n\t\t\t\tED920F5713215828008DDA0B /* help.c in Sources */,\n\t\t\t\tED920F5A1321587C008DDA0B /* c_plot.c in Sources */,\n\t\t\t\tED920F5D132158CA008DDA0B /* readfile.c in Sources */,\n\t\t\t\tED677C10132A3D83000CFDC8 /* replicates.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF4A9F36F1742865A000087E1 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF4A9F3C617428670000087E1 /* cuffquant.cpp in Sources */,\n\t\t\t\tF4A9F3711742865A000087E1 /* abundances.cpp in Sources */,\n\t\t\t\tF4A9F3721742865A000087E1 /* bundles.cpp in Sources */,\n\t\t\t\tF4A9F3731742865A000087E1 /* codons.cpp in Sources */,\n\t\t\t\tF4A9F3741742865A000087E1 /* common.cpp in Sources */,\n\t\t\t\tF4A9F3751742865A000087E1 /* filters.cpp in Sources */,\n\t\t\t\tF4A9F3761742865A000087E1 /* GArgs.cpp in Sources */,\n\t\t\t\tF4A9F3771742865A000087E1 /* GBase.cpp in Sources */,\n\t\t\t\tF4A9F3781742865A000087E1 /* gdna.cpp in Sources */,\n\t\t\t\tF4A9F3791742865A000087E1 /* genes.cpp in Sources */,\n\t\t\t\tF4A9F37A1742865A000087E1 /* GFaSeqGet.cpp in Sources */,\n\t\t\t\tF4A9F37B1742865A000087E1 /* gff.cpp in Sources */,\n\t\t\t\tF4A9F37C1742865A000087E1 /* GStr.cpp in Sources */,\n\t\t\t\tF4A9F37D1742865A000087E1 /* gtf_tracking.cpp in Sources */,\n\t\t\t\tF4A9F37E1742865A000087E1 /* hits.cpp in Sources */,\n\t\t\t\tF4A9F37F1742865A000087E1 /* scaffolds.cpp in Sources */,\n\t\t\t\tF4A9F3801742865A000087E1 /* tokenize.cpp in Sources */,\n\t\t\t\tF4A9F3821742865A000087E1 /* clustering.cpp in Sources */,\n\t\t\t\tF4A9F3831742865A000087E1 /* biascorrection.cpp in Sources */,\n\t\t\t\tF4A9F3841742865A000087E1 /* jensen_shannon.cpp in Sources */,\n\t\t\t\tF4A9F3851742865A000087E1 /* GFastaIndex.cpp in Sources */,\n\t\t\t\tF4A9F3861742865A000087E1 /* minmax.c in Sources */,\n\t\t\t\tF4A9F3871742865A000087E1 /* locfit.c in Sources */,\n\t\t\t\tF4A9F3881742865A000087E1 /* ev_interp.c in Sources */,\n\t\t\t\tF4A9F3891742865A000087E1 /* ev_atree.c in Sources */,\n\t\t\t\tF4A9F38A1742865A000087E1 /* weight.c in Sources */,\n\t\t\t\tF4A9F38B1742865A000087E1 /* wdiag.c in Sources */,\n\t\t\t\tF4A9F38C1742865A000087E1 /* strings.c in Sources */,\n\t\t\t\tF4A9F38D1742865A000087E1 /* solve.c in Sources */,\n\t\t\t\tF4A9F38E1742865A000087E1 /* simul.c in Sources */,\n\t\t\t\tF4A9F38F1742865A000087E1 /* preplot.c in Sources */,\n\t\t\t\tF4A9F3901742865A000087E1 /* pcomp.c in Sources */,\n\t\t\t\tF4A9F3911742865A000087E1 /* nbhd.c in Sources */,\n\t\t\t\tF4A9F3921742865A000087E1 /* math.c in Sources */,\n\t\t\t\tF4A9F3931742865A000087E1 /* m_max.c in Sources */,\n\t\t\t\tF4A9F3941742865A000087E1 /* m_eigen.c in Sources */,\n\t\t\t\tF4A9F3951742865A000087E1 /* linalg.c in Sources */,\n\t\t\t\tF4A9F3961742865A000087E1 /* lfstr.c in Sources */,\n\t\t\t\tF4A9F3971742865A000087E1 /* lf_vari.c in Sources */,\n\t\t\t\tF4A9F3981742865A000087E1 /* lf_fitfun.c in Sources */,\n\t\t\t\tF4A9F3991742865A000087E1 /* lf_dercor.c in Sources */,\n\t\t\t\tF4A9F39A1742865A000087E1 /* frend.c in Sources */,\n\t\t\t\tF4A9F39B1742865A000087E1 /* fitted.c in Sources */,\n\t\t\t\tF4A9F39C1742865A000087E1 /* family.c in Sources */,\n\t\t\t\tF4A9F39D1742865A000087E1 /* ev_trian.c in Sources */,\n\t\t\t\tF4A9F39E1742865A000087E1 /* ev_main.c in Sources */,\n\t\t\t\tF4A9F39F1742865A000087E1 /* ev_kdtre.c in Sources */,\n\t\t\t\tF4A9F3A01742865A000087E1 /* scb.c in Sources */,\n\t\t\t\tF4A9F3A11742865A000087E1 /* scb_cons.c in Sources */,\n\t\t\t\tF4A9F3A21742865A000087E1 /* m_jacob.c in Sources */,\n\t\t\t\tF4A9F3A31742865A000087E1 /* lf_robust.c in Sources */,\n\t\t\t\tF4A9F3A41742865A000087E1 /* m_chol.c in Sources */,\n\t\t\t\tF4A9F3A51742865A000087E1 /* arith.c in Sources */,\n\t\t\t\tF4A9F3A61742865A000087E1 /* c_args.c in Sources */,\n\t\t\t\tF4A9F3A71742865A000087E1 /* ar_funs.c in Sources */,\n\t\t\t\tF4A9F3A81742865A000087E1 /* cmd.c in Sources */,\n\t\t\t\tF4A9F3A91742865A000087E1 /* density.c in Sources */,\n\t\t\t\tF4A9F3AA1742865A000087E1 /* vari.cpp in Sources */,\n\t\t\t\tF4A9F3AB1742865A000087E1 /* dens_haz.c in Sources */,\n\t\t\t\tF4A9F3AC1742865A000087E1 /* dens_int.c in Sources */,\n\t\t\t\tF4A9F3AD1742865A000087E1 /* dens_odi.c in Sources */,\n\t\t\t\tF4A9F3AE1742865A000087E1 /* startlf.c in Sources */,\n\t\t\t\tF4A9F3AF1742865A000087E1 /* adap.c in Sources */,\n\t\t\t\tF4A9F3B01742865A000087E1 /* dist.c in Sources */,\n\t\t\t\tF4A9F3B11742865A000087E1 /* random.c in Sources */,\n\t\t\t\tF4A9F3B21742865A000087E1 /* lfd.c in Sources */,\n\t\t\t\tF4A9F3B31742865A000087E1 /* band.c in Sources */,\n\t\t\t\tF4A9F3B41742865A000087E1 /* pout.c in Sources */,\n\t\t\t\tF4A9F3B51742865A000087E1 /* makecmd.c in Sources */,\n\t\t\t\tF4A9F3B61742865A000087E1 /* help.c in Sources */,\n\t\t\t\tF4A9F3B71742865A000087E1 /* c_plot.c in Sources */,\n\t\t\t\tF4A9F3B81742865A000087E1 /* readfile.c in Sources */,\n\t\t\t\tF4A9F3B91742865A000087E1 /* multireads.cpp in Sources */,\n\t\t\t\tF4A9F3BA1742865A000087E1 /* replicates.cpp in Sources */,\n\t\t\t\tF4A9F3BB1742865A000087E1 /* sampling.cpp in Sources */,\n\t\t\t\tF4A9F3CA1742C26D000087E1 /* tracking.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tF4D2AB3218D1124600BB1CF0 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF4D2AB8B18D1125D00BB1CF0 /* cuffnorm.cpp in Sources */,\n\t\t\t\tF4D2AB3418D1124600BB1CF0 /* abundances.cpp in Sources */,\n\t\t\t\tF4D2AB3518D1124600BB1CF0 /* bundles.cpp in Sources */,\n\t\t\t\tF4D2AB3618D1124600BB1CF0 /* codons.cpp in Sources */,\n\t\t\t\tF4D2AB3718D1124600BB1CF0 /* common.cpp in Sources */,\n\t\t\t\tF4D2AB3818D1124600BB1CF0 /* filters.cpp in Sources */,\n\t\t\t\tF4D2AB3918D1124600BB1CF0 /* GArgs.cpp in Sources */,\n\t\t\t\tF4D2AB3A18D1124600BB1CF0 /* GBase.cpp in Sources */,\n\t\t\t\tF4D2AB3B18D1124600BB1CF0 /* gdna.cpp in Sources */,\n\t\t\t\tF4D2AB3C18D1124600BB1CF0 /* genes.cpp in Sources */,\n\t\t\t\tF4D2AB3D18D1124600BB1CF0 /* GFaSeqGet.cpp in Sources */,\n\t\t\t\tF4D2AB3E18D1124600BB1CF0 /* gff.cpp in Sources */,\n\t\t\t\tF4D2AB3F18D1124600BB1CF0 /* GStr.cpp in Sources */,\n\t\t\t\tF4D2AB4018D1124600BB1CF0 /* gtf_tracking.cpp in Sources */,\n\t\t\t\tF4D2AB4118D1124600BB1CF0 /* hits.cpp in Sources */,\n\t\t\t\tF4D2AB4218D1124600BB1CF0 /* scaffolds.cpp in Sources */,\n\t\t\t\tF4D2AB4318D1124600BB1CF0 /* tokenize.cpp in Sources */,\n\t\t\t\tF4D2AB4418D1124600BB1CF0 /* differential.cpp in Sources */,\n\t\t\t\tF4D2AB4518D1124600BB1CF0 /* clustering.cpp in Sources */,\n\t\t\t\tF4D2AB4618D1124600BB1CF0 /* biascorrection.cpp in Sources */,\n\t\t\t\tF4D2AB4718D1124600BB1CF0 /* jensen_shannon.cpp in Sources */,\n\t\t\t\tF4D2AB4818D1124600BB1CF0 /* GFastaIndex.cpp in Sources */,\n\t\t\t\tF4D2AB4918D1124600BB1CF0 /* minmax.c in Sources */,\n\t\t\t\tF4D2AB4A18D1124600BB1CF0 /* locfit.c in Sources */,\n\t\t\t\tF4D2AB4B18D1124600BB1CF0 /* ev_interp.c in Sources */,\n\t\t\t\tF4D2AB4C18D1124600BB1CF0 /* ev_atree.c in Sources */,\n\t\t\t\tF4D2AB4D18D1124600BB1CF0 /* weight.c in Sources */,\n\t\t\t\tF4D2AB4E18D1124600BB1CF0 /* wdiag.c in Sources */,\n\t\t\t\tF4D2AB4F18D1124600BB1CF0 /* strings.c in Sources */,\n\t\t\t\tF4D2AB5018D1124600BB1CF0 /* solve.c in Sources */,\n\t\t\t\tF4D2AB5118D1124600BB1CF0 /* simul.c in Sources */,\n\t\t\t\tF4D2AB5218D1124600BB1CF0 /* preplot.c in Sources */,\n\t\t\t\tF4D2AB5318D1124600BB1CF0 /* pcomp.c in Sources */,\n\t\t\t\tF4D2AB5418D1124600BB1CF0 /* nbhd.c in Sources */,\n\t\t\t\tF4D2AB5518D1124600BB1CF0 /* math.c in Sources */,\n\t\t\t\tF4D2AB5618D1124600BB1CF0 /* m_max.c in Sources */,\n\t\t\t\tF4D2AB5718D1124600BB1CF0 /* m_eigen.c in Sources */,\n\t\t\t\tF4D2AB5818D1124600BB1CF0 /* linalg.c in Sources */,\n\t\t\t\tF4D2AB5918D1124600BB1CF0 /* lfstr.c in Sources */,\n\t\t\t\tF4D2AB5A18D1124600BB1CF0 /* lf_vari.c in Sources */,\n\t\t\t\tF4D2AB5B18D1124600BB1CF0 /* lf_fitfun.c in Sources */,\n\t\t\t\tF4D2AB5C18D1124600BB1CF0 /* lf_dercor.c in Sources */,\n\t\t\t\tF4D2AB5D18D1124600BB1CF0 /* frend.c in Sources */,\n\t\t\t\tF4D2AB5E18D1124600BB1CF0 /* fitted.c in Sources */,\n\t\t\t\tF4D2AB5F18D1124600BB1CF0 /* family.c in Sources */,\n\t\t\t\tF4D2AB6018D1124600BB1CF0 /* ev_trian.c in Sources */,\n\t\t\t\tF4D2AB6118D1124600BB1CF0 /* ev_main.c in Sources */,\n\t\t\t\tF4D2AB6218D1124600BB1CF0 /* ev_kdtre.c in Sources */,\n\t\t\t\tF4D2AB6318D1124600BB1CF0 /* scb.c in Sources */,\n\t\t\t\tF4D2AB6418D1124600BB1CF0 /* scb_cons.c in Sources */,\n\t\t\t\tF4D2AB6518D1124600BB1CF0 /* m_jacob.c in Sources */,\n\t\t\t\tF4D2AB6618D1124600BB1CF0 /* lf_robust.c in Sources */,\n\t\t\t\tF4D2AB6718D1124600BB1CF0 /* m_chol.c in Sources */,\n\t\t\t\tF4D2AB6818D1124600BB1CF0 /* arith.c in Sources */,\n\t\t\t\tF4D2AB6918D1124600BB1CF0 /* c_args.c in Sources */,\n\t\t\t\tF4D2AB6A18D1124600BB1CF0 /* ar_funs.c in Sources */,\n\t\t\t\tF4D2AB6B18D1124600BB1CF0 /* cmd.c in Sources */,\n\t\t\t\tF4D2AB6C18D1124600BB1CF0 /* density.c in Sources */,\n\t\t\t\tF4D2AB6D18D1124600BB1CF0 /* vari.cpp in Sources */,\n\t\t\t\tF4D2AB6E18D1124600BB1CF0 /* dens_haz.c in Sources */,\n\t\t\t\tF4D2AB6F18D1124600BB1CF0 /* dens_int.c in Sources */,\n\t\t\t\tF4D2AB7018D1124600BB1CF0 /* dens_odi.c in Sources */,\n\t\t\t\tF4D2AB7118D1124600BB1CF0 /* startlf.c in Sources */,\n\t\t\t\tF4D2AB7218D1124600BB1CF0 /* adap.c in Sources */,\n\t\t\t\tF4D2AB7318D1124600BB1CF0 /* dist.c in Sources */,\n\t\t\t\tF4D2AB7418D1124600BB1CF0 /* random.c in Sources */,\n\t\t\t\tF4D2AB7518D1124600BB1CF0 /* lfd.c in Sources */,\n\t\t\t\tF4D2AB7618D1124600BB1CF0 /* band.c in Sources */,\n\t\t\t\tF4D2AB7718D1124600BB1CF0 /* pout.c in Sources */,\n\t\t\t\tF4D2AB7818D1124600BB1CF0 /* makecmd.c in Sources */,\n\t\t\t\tF4D2AB7918D1124600BB1CF0 /* help.c in Sources */,\n\t\t\t\tF4D2AB7A18D1124600BB1CF0 /* c_plot.c in Sources */,\n\t\t\t\tF4D2AB7B18D1124600BB1CF0 /* readfile.c in Sources */,\n\t\t\t\tF4D2AB7C18D1124600BB1CF0 /* multireads.cpp in Sources */,\n\t\t\t\tF4D2AB7D18D1124600BB1CF0 /* replicates.cpp in Sources */,\n\t\t\t\tF4D2AB7E18D1124600BB1CF0 /* sampling.cpp in Sources */,\n\t\t\t\tF4D2AB7F18D1124600BB1CF0 /* tracking.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t1DEB923208733DC60010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_AUTO_VECTORIZATION = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = NO;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = NO;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\tHAVE_BAM,\n\t\t\t\t\tDEBUG,\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = \"\";\n\t\t\t\tGCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = NO;\n\t\t\t\tGCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;\n\t\t\t\tGCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;\n\t\t\t\tGCC_WARN_SHADOW = NO;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = NO;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = NO;\n\t\t\t\tGCC_WARN_UNUSED_PARAMETER = NO;\n\t\t\t\tGCC_WARN_UNUSED_VALUE = YES;\n\t\t\t\tGENERATE_PROFILING_CODE = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/opt/local/include,\n\t\t\t\t\t/usr/include,\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(SRCROOT)\",\n\t\t\t\t\t/opt/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = cufflinks;\n\t\t\t\tSTANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB923308733DC60010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_AUTO_VECTORIZATION = NO;\n\t\t\t\tGCC_DEBUGGING_SYMBOLS = used;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES;\n\t\t\t\tGCC_ENABLE_TRIGRAPHS = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 3;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = HAVE_BAM;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_UNROLL_LOOPS = YES;\n\t\t\t\tGCC_VERSION = \"\";\n\t\t\t\tGCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/opt/local/include,\n\t\t\t\t\t/usr/include,\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(SRCROOT)\",\n\t\t\t\t\t/opt/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPRODUCT_NAME = cufflinks;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t1DEB923608733DC60010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvmgcc42;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/opt/local/include,\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tLINK_WITH_STANDARD_LIBRARIES = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.7;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t\t\"-ftemplate-depth=1024\",\n\t\t\t\t);\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tUSER_HEADER_SEARCH_PATHS = \"/usr/include /opt/local/include /usr/local/include\";\n\t\t\t\tVALID_ARCHS = x86_64;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB923708733DC60010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvmgcc42;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/opt/local/include,\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tLINK_WITH_STANDARD_LIBRARIES = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.7;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t\t\"-ftemplate-depth=1024\",\n\t\t\t\t);\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tUSER_HEADER_SEARCH_PATHS = \"/usr/include /opt/local/include /usr/local/include\";\n\t\t\t\tVALID_ARCHS = x86_64;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t9CD6E93D13379B7E00CCE1DE /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_AUTO_VECTORIZATION = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = NO;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = NO;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\tHAVE_BAM,\n\t\t\t\t\tDEBUG,\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;\n\t\t\t\tGCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;\n\t\t\t\tGCC_WARN_SHADOW = NO;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = NO;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = NO;\n\t\t\t\tGCC_WARN_UNUSED_PARAMETER = NO;\n\t\t\t\tGCC_WARN_UNUSED_VALUE = YES;\n\t\t\t\tGENERATE_PROFILING_CODE = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t\t\"/usr/local/include/boost-1_41\",\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"\\\\\\\\\\\\\\\"$(SRCROOT)\\\\\\\\\\\\\\\"\",\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = compress_gtf;\n\t\t\t\tSTANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t9CD6E93E13379B7E00CCE1DE /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_DEBUGGING_SYMBOLS = used;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES;\n\t\t\t\tGCC_ENABLE_TRIGRAPHS = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 3;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_UNROLL_LOOPS = YES;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t./src,\n\t\t\t\t\t\"/usr/local/include/boost-1_41\",\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"\\\\\\\\\\\\\\\"$(SRCROOT)\\\\\\\\\\\\\\\"\",\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPRODUCT_NAME = compress_gtf;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tED41B836127602C60000B5A2 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_AUTO_VECTORIZATION = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = NO;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = NO;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\tHAVE_BAM,\n\t\t\t\t\tDEBUG,\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;\n\t\t\t\tGCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;\n\t\t\t\tGCC_WARN_SHADOW = NO;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = NO;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = NO;\n\t\t\t\tGCC_WARN_UNUSED_PARAMETER = NO;\n\t\t\t\tGCC_WARN_UNUSED_VALUE = YES;\n\t\t\t\tGENERATE_PROFILING_CODE = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t\t\"/usr/local/include/boost-1_41\",\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"\\\\\\\\\\\\\\\"$(SRCROOT)\\\\\\\\\\\\\\\"\",\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = cufflinks_xcode;\n\t\t\t\tSTANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tED41B837127602C60000B5A2 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_DEBUGGING_SYMBOLS = used;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES;\n\t\t\t\tGCC_ENABLE_TRIGRAPHS = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 3;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_UNROLL_LOOPS = YES;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t./src,\n\t\t\t\t\t\"/usr/local/include/boost-1_41\",\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"\\\\\\\\\\\\\\\"$(SRCROOT)\\\\\\\\\\\\\\\"\",\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPRODUCT_NAME = cufflinks;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tEDD0CE2010C72F7D00AF308F /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\tHAVE_BAM,\n\t\t\t\t\tDEBUG,\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = \"\";\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/opt/local/include,\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"$(SRCROOT)\",\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/libIntel64,\n\t\t\t\t);\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t\t\"-ftemplate-depth=1024\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = cuffdiff;\n\t\t\t\tRUN_CLANG_STATIC_ANALYZER = NO;\n\t\t\t\tSTANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;\n\t\t\t\tUSER_HEADER_SEARCH_PATHS = \"\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tEDD0CE2110C72F7D00AF308F /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_AUTO_VECTORIZATION = YES;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 3;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = HAVE_VECLIB;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_UNROLL_LOOPS = YES;\n\t\t\t\tGCC_VERSION = \"\";\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGENERATE_PROFILING_CODE = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/opt/local/include,\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"$(SRCROOT)\",\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/libIntel64,\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t\t\"-ftemplate-depth=1024\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = cuffdiff;\n\t\t\t\tRUN_CLANG_STATIC_ANALYZER = NO;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tEDD6A9D311598AB900D3F668 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_AUTO_VECTORIZATION = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = NO;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = NO;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = DEBUG;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;\n\t\t\t\tGCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;\n\t\t\t\tGCC_WARN_SHADOW = NO;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = NO;\n\t\t\t\tGCC_WARN_UNUSED_PARAMETER = NO;\n\t\t\t\tGCC_WARN_UNUSED_VALUE = YES;\n\t\t\t\tGENERATE_PROFILING_CODE = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t\t\"/usr/local/include/boost-1_41\",\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"\\\\\\\\\\\\\\\"$(SRCROOT)\\\\\\\\\\\\\\\"\",\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = cufflinks_xcode;\n\t\t\t\tSTANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tEDD6A9D411598AB900D3F668 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_DEBUGGING_SYMBOLS = used;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES;\n\t\t\t\tGCC_ENABLE_TRIGRAPHS = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 3;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_UNROLL_LOOPS = YES;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t./src,\n\t\t\t\t\t\"/usr/local/include/boost-1_41\",\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"\\\\\\\\\\\\\\\"$(SRCROOT)\\\\\\\\\\\\\\\"\",\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPRODUCT_NAME = cufflinks;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tEDD94B651205C9E800AA1086 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_AUTO_VECTORIZATION = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = NO;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = NO;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\tHAVE_BAM,\n\t\t\t\t\tDEBUG,\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;\n\t\t\t\tGCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;\n\t\t\t\tGCC_WARN_SHADOW = NO;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = NO;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = NO;\n\t\t\t\tGCC_WARN_UNUSED_PARAMETER = NO;\n\t\t\t\tGCC_WARN_UNUSED_VALUE = YES;\n\t\t\t\tGENERATE_PROFILING_CODE = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t\t\"/usr/local/include/boost-1_41\",\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"\\\\\\\"$(SRCROOT)\\\\\\\"\",\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = cufflinks_xcode;\n\t\t\t\tSTANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tEDD94B661205C9E800AA1086 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_DEBUGGING_SYMBOLS = used;\n\t\t\t\tGCC_ENABLE_SSE3_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE41_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SSE42_EXTENSIONS = YES;\n\t\t\t\tGCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES;\n\t\t\t\tGCC_ENABLE_TRIGRAPHS = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 3;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_UNROLL_LOOPS = YES;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t./src,\n\t\t\t\t\t\"/usr/local/include/boost-1_41\",\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"\\\\\\\"$(SRCROOT)\\\\\\\"\",\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPRODUCT_NAME = cufflinks;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tEDFE39CC122BE65600F24CD3 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\tHAVE_BAM,\n\t\t\t\t\tDEBUG,\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/usr/local/include/,\n\t\t\t\t\t./src,\n\t\t\t\t\t\"/usr/local/include/boost-1_41\",\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"\\\\\\\"$(SRCROOT)\\\\\\\"\",\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = cuffcluster;\n\t\t\t\tSTANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tEDFE39CD122BE65600F24CD3 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_AUTO_VECTORIZATION = YES;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 3;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = HAVE_VECLIB;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_UNROLL_LOOPS = YES;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t./src,\n\t\t\t\t\t\"/usr/local/include/boost-1_41\",\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"\\\\\\\"$(SRCROOT)\\\\\\\"\",\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPRODUCT_NAME = sorting_hat;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tF4A9F3C31742865A000087E1 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\tHAVE_BAM,\n\t\t\t\t\tDEBUG,\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = \"\";\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/opt/local/include,\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"$(SRCROOT)\",\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/libIntel64,\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.7;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t\t\"-ftemplate-depth=1024\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = cuffquant;\n\t\t\t\tRUN_CLANG_STATIC_ANALYZER = NO;\n\t\t\t\tSTANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;\n\t\t\t\tUSER_HEADER_SEARCH_PATHS = \"\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tF4A9F3C41742865A000087E1 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_AUTO_VECTORIZATION = YES;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 3;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = HAVE_VECLIB;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_UNROLL_LOOPS = YES;\n\t\t\t\tGCC_VERSION = \"\";\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGENERATE_PROFILING_CODE = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/opt/local/include,\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"$(SRCROOT)\",\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t\t/usr/local/libIntel64,\n\t\t\t\t\t/opt/local/libIntel64,\n\t\t\t\t);\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.7;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t\t\"-ftemplate-depth=1024\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = cuffquant;\n\t\t\t\tRUN_CLANG_STATIC_ANALYZER = NO;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tF4D2AB8818D1124600BB1CF0 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\tHAVE_BAM,\n\t\t\t\t\tDEBUG,\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = \"\";\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/opt/local/include,\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"$(SRCROOT)\",\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t\t/opt/local/libIntel64,\n\t\t\t\t);\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t\t\"-ftemplate-depth=1024\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = \"cuffdiff copy\";\n\t\t\t\tRUN_CLANG_STATIC_ANALYZER = NO;\n\t\t\t\tSTANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;\n\t\t\t\tUSER_HEADER_SEARCH_PATHS = \"\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tF4D2AB8918D1124600BB1CF0 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_AUTO_VECTORIZATION = YES;\n\t\t\t\tGCC_INLINES_ARE_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 3;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = HAVE_VECLIB;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_UNROLL_LOOPS = YES;\n\t\t\t\tGCC_VERSION = \"\";\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGENERATE_PROFILING_CODE = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t/opt/local/include,\n\t\t\t\t\t/usr/local/include,\n\t\t\t\t\t./src,\n\t\t\t\t);\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/lib,\n\t\t\t\t\t\"$(SRCROOT)\",\n\t\t\t\t\t/opt/local/lib,\n\t\t\t\t\t/opt/local/libIntel64,\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t\t\"-ftemplate-depth=1024\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = \"cuffdiff copy\";\n\t\t\t\tRUN_CLANG_STATIC_ANALYZER = NO;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget \"cufflinks\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB923208733DC60010E9CD /* Debug */,\n\t\t\t\t1DEB923308733DC60010E9CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t1DEB923508733DC60010E9CD /* Build configuration list for PBXProject \"cufflinks\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB923608733DC60010E9CD /* Debug */,\n\t\t\t\t1DEB923708733DC60010E9CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t9CD6E93C13379B7E00CCE1DE /* Build configuration list for PBXNativeTarget \"compress_gtf\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t9CD6E93D13379B7E00CCE1DE /* Debug */,\n\t\t\t\t9CD6E93E13379B7E00CCE1DE /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tED41B835127602C60000B5A2 /* Build configuration list for PBXNativeTarget \"gtf_reads\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tED41B836127602C60000B5A2 /* Debug */,\n\t\t\t\tED41B837127602C60000B5A2 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tEDD0CE1F10C72F7D00AF308F /* Build configuration list for PBXNativeTarget \"cuffdiff\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tEDD0CE2010C72F7D00AF308F /* Debug */,\n\t\t\t\tEDD0CE2110C72F7D00AF308F /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tEDD6A9D211598AB900D3F668 /* Build configuration list for PBXNativeTarget \"cuffcompare\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tEDD6A9D311598AB900D3F668 /* Debug */,\n\t\t\t\tEDD6A9D411598AB900D3F668 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tEDD94B641205C9E800AA1086 /* Build configuration list for PBXNativeTarget \"gtf_to_sam\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tEDD94B651205C9E800AA1086 /* Debug */,\n\t\t\t\tEDD94B661205C9E800AA1086 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tEDFE39CB122BE65600F24CD3 /* Build configuration list for PBXNativeTarget \"cuffcluster\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tEDFE39CC122BE65600F24CD3 /* Debug */,\n\t\t\t\tEDFE39CD122BE65600F24CD3 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tF4A9F3C21742865A000087E1 /* Build configuration list for PBXNativeTarget \"cuffquant\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tF4A9F3C31742865A000087E1 /* Debug */,\n\t\t\t\tF4A9F3C41742865A000087E1 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tF4D2AB8718D1124600BB1CF0 /* Build configuration list for PBXNativeTarget \"cuffnorm\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tF4D2AB8818D1124600BB1CF0 /* Debug */,\n\t\t\t\tF4D2AB8918D1124600BB1CF0 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 08FB7793FE84155DC02AAC07 /* Project object */;\n}\n"
  },
  {
    "path": "doc/CL_supplement.tex",
    "content": "\\documentclass[12pt]{amsart}\r\n\r\n\\usepackage{graphicx}\r\n\\usepackage{amsmath}\r\n\\usepackage[pdftex]{hyperref}\r\n\r\n\\setlength{\\textwidth}{6.2in}\r\n\\setlength{\\textheight}{8.4in}\r\n\\setlength{\\topmargin}{0.2in}\r\n\\setlength{\\oddsidemargin}{0in}\r\n\\setlength{\\evensidemargin}{0in}\r\n\\setlength{\\headsep}{.3in}\r\n\\footskip 0.3in\r\n\\newtheorem{thm}{Theorem}\r\n\\newtheorem{lemma}[thm]{Lemma}\r\n\\newtheorem{prop}[thm]{Proposition}\r\n\\newtheorem{cor}[thm]{Corollary}\r\n\\theoremstyle{definition}\r\n\\newtheorem{defn}[thm]{Definition}\r\n\\newtheorem{example}[thm]{Example}\r\n\\newtheorem{remark}[thm]{Remark}\r\n\\newtheorem{conj}[thm]{Conjecture}\r\n\r\n\\newcommand{\\cherry}[1]{\\ensuremath{\\langle #1 \\rangle}}\r\n\\newcommand{\\ignore}[1]{}\r\n\\newcommand{\\half}{\\frac{1}{2}}\r\n\\newcommand{\\eopf}{\\framebox[6.5pt]{} \\vspace{0.2in}}\r\n\r\n%------------------document begins-----------------------\r\n\r\n\\begin{document}\r\n\r\n\\title{Supplementary methods for the paper\\\\\r\nTranscript assembly and quantification by RNA-Seq \r\nreveals unannotated transcripts and isoform switching \r\nduring cell differentiation}\r\n\\author{Cole Trapnell \\and Brian A Williams \\and Geo Pertea \\and Ali Mortazavi \\and Gordon Kwan \\and Marijke J van Baren \\and Steven L Salzberg\r\n\\and Barbara J Wold \\and Lior Pachter}\r\n%\\address{}\r\n%\\email{\\{whoweare\\}@math.berkeley.edu}\r\n%\\dedicatory{\\today}\r\n\r\n%\\thanks{Supported in part by ....}\r\n%\\subjclass{Primary 55M20; Secondary 47H10}\r\n\r\n\\maketitle\r\n\\markboth{C Trapnell et al.}{Transcript assembly and abundance estimation from RNA-Seq}\r\n\r\nThis document is a companion to the paper ``Transcript assembly and abundance estimation from RNA-Seq reveals thousands of new transcripts and switching among isoforms''. It describes the experiment\r\nperformed, the details of the {\\tt Cufflinks} assembler and abundance\r\nestimation methods, and provides\r\nsupplementary tables, figures and supporting evidence for claims in\r\nthe paper.\r\n%\\pagestyle{plain}\r\n\\pagenumbering{roman} \\tableofcontents \\listoffigures \\listoftables \\newpage \\pagenumbering{arabic}\r\n\r\n\\section{Sequencing experiment}\r\n\r\nThe data analyzed in the paper consisted of 430,467,018 paired 75bp reads\r\nsequenced from the transcriptome of mouse skeletal muscle C2C12 cells induced\r\nto undergo myogenic differentiation. Total RNA was extracted from these cells,\r\nand subsequently mRNA was isolated at four different time points (-24 hours,\r\n60 hours, 120 hours, 168 hours). cDNA was prepared following a similar\r\nprocedure to the one described in \\cite{Mortazavi2008}. Fragmentation of the\r\nmRNA followed by size selection resulted in fragment lengths\r\napproximately 200nt long for\r\nall of the time-points. The distribution of fragment lengths is shown in\r\nSupplementary Figure \\ref{fragment_lengths} (in Section \\ref{sec:abundances}\r\nthis distribution of fragment lengths is referred to as $F$). These estimates\r\nare based on alignments of the spiked-in sequences using {\\tt Bowtie} 0.12\r\n\\cite{Langmead2009}.\r\n\r\n\\begin{figure}[h] \r\n    \\includegraphics{pdfs/library_frags.pdf}\r\n    \\caption[Fragment length distributions of C2C12 time-course libraries]{Fragment length distributions of C2C12 time-course libraries. \\label{fragment_lengths}}\r\n\\end{figure}\r\n\r\n\\section{Mapping fragments to the genome}\r\n\r\nIn principle, an algorithm that infers individual transcript abundances by\r\nmeasuring the fraction of fragments originating from each of a set of known\r\ntranscripts would begin by computing alignments between fragments and the set\r\nof known transcripts that may be contained in the sample. However, because the\r\ntranscriptome for mouse is incompletely annotated, such an analysis requires\r\nmapping of fragments to the genome as a proxy for mapping directly to\r\ntranscripts. This means that alignments of short sequencing reads must be\r\nallowed to span exon-exon splice junctions in genomic coordinate space. We\r\npreviously developed a program called {\\tt TopHat} to map RNA-Seq reads to the\r\ngenome. {\\tt TopHat} does not require a reference transcriptome and can\r\ntherefore be used to discover novel splice junctions. \\cite{Trapnell2009}\r\n\r\nFragments were mapped to build 37.1 of the mouse genome with {\\tt TopHat} version\r\n1.0.13. We extended our previous algorithms described in\r\n\\cite{Trapnell2009} to exploit the longer\r\npaired reads used in the study. The original {\\tt TopHat} program used a\r\nseed-and-extend alignment strategy to find spliced alignments of unpaired\r\nRNA-Seq experiments. However, due to computational limitations, our original\r\nmethod reported only alignments across GT-AG introns shorter than 20Kb by\r\ndefault. This strategy also could not align reads that spanned multiple splice\r\njunctions. However, as sequencing technology has improved and longer (paired end) reads have \r\nbecome available, we have\r\nmodified the software to employ new strategies to align reads across splice\r\njunctions. {\\tt TopHat} version 1.0.7 and later splits a read 75bp or longer in\r\nthree or more segments of approximately equal size (25bp), and maps them\r\nindependently. Reads with segments that can be mapped to the genome only\r\nnon-contiguously are marked as possible intron-spanning reads. These\r\n``contiguously unmappable'' reads are used to build a set of possible introns\r\nin the transcriptome.\r\n\r\n\\subsection{Discovering splice junctions} Suppose $S$ is a read of length\r\n$l$ that crosses a splice junction. {\\tt TopHat} splits $S$ into $n=\\lfloor\r\nl/k \\rfloor$ segments where $k=25$bp ($k$ is a parameter that can be\r\nadjusted by the user in {\\tt TopHat}). At most\r\none of these segments must cross the splice junction, and junctions\r\ncan be discovered if they lie in any of the segments. {\\tt TopHat} maps the\r\nsegments $s_1,...,s_n$ with {\\tt Bowtie} to the genome, and checks for\r\ninternal segments $s_2,...,s_{n-1}$ that do not map anywhere to the genome, as\r\nwell as for pairs of successive segments $s_i,s_{i+1}$ that both align to the\r\ngenome, but not adjacently. When a segment $s_i$ fails to align because it\r\ncrosses a splice junction, but $s_{i-1}$ and $s_{i+1}$ are aligned (say at\r\nstarting at positions $x$ and $y$, respectively), {\\tt TopHat} looks for the\r\ndonor and acceptor sites for the junction near $x$ and $y$. Assuming\r\n(without loss of generality)  that the\r\ntranscript is on Crick strand of the genome the\r\ndonor must fall within $k$ bases upstream of position $x+k$, and the acceptor\r\nmust be within $k$ bases downstream of $y$, a total of $k$ possible exon-exon\r\nsplice junctions. Similarly, when successive segments $s_i$ and $s_{i+1}$\r\nalign to the genome non-adjacently at positions $x$ and $y$, the junction\r\nspanned by the read must be from positions $x+k$ to $y$ in the genome.\r\n\r\n{\\tt TopHat} accumulates an index of potential splice junctions by examining\r\nsegment mapping for all contiguously unmappable reads. For each junction the\r\nprogram then concatenates $k$bp upstream of the donor to $k$bp downstream of\r\nthe acceptor to form a synthetic spliced sequence around the junction. The\r\nsegments of the contiguously unmappable reads are then aligned against these\r\nsynthetic sequences with {\\tt Bowtie}. The resulting contiguous and spliced\r\nsegment alignments for these reads are merged to form complete alignments to\r\nthe genome, each spanning one or more splice junctions.\r\n\r\n\\subsection{Resolving multiple alignments for fragments}\r\n\r\nThe alignments for both reads from a mate pair are examined together to\r\nproduce a set of alignments for the corresponding library fragment as a whole,\r\nreported in SAM format \\cite{Li2009a}. These fragment alignments are\r\nranked according to the procedure described below, and only highest ranking alignments are reported. The ranks are\r\ndesigned to incorporate very loose assumptions on intron and gene length,\r\nnamely that introns longer than 20kb are rare. Let $x$ and $y$ be fragment\r\nalignments. Then $x < y$ if {\\em any} of the following (applied in order) are\r\ntrue:\r\n\r\n\\begin {enumerate}\r\n    \\item $x$ is a singleton, and $y$ has both ends mapped,\r\n    \\item $x$ crosses more splice junctions than $y$,\r\n    \\item the reads from $x$ map significantly farther apart in the genome than expected according to the library's fragment length distribution ($\\geq$ 3 s.d.), and the reads from $y$ do not,\r\n    \\item the reads from $x$ are significantly closer together than expected according to the library's fragment length distribution, and the reads from $y$ are not,\r\n    \\item The reads from $x$ map more than 100bp farther apart than the reads from $y$,\r\n    \\item $x$ and $y$ both span an intron, and $x$ spans a longer one,\r\n    \\item $x$ has more mismatches than $y$ to the genome.\r\n\\end {enumerate}\r\n\r\nFragments that have multiple equally good alignments according to the above\r\nrules are all reported. If there are $n$ alignments for a fragment,\r\neach is assigned a probability\r\nof only $1/n$ of being correct. The SAM format encodes this probability in the\r\nmapping quality field, which is later used by {\\tt Cufflinks} to reduce the\r\ncontribution of multiply mapping fragments (to $1/n$ of a uniquely\r\nmappable read) in FPKM calculations (FPKM is a measurement of\r\nexpression, and is formally defined in Section\r\n\\ref{sec:abundances}). The recent work of Li et al. \\cite{Li2009b}\r\naddresses the problem of probabilistically assigning multi-reads, and\r\nit should be possible to incorporate the ideas of that paper into\r\nfuture versions of {\\tt Tophat} and {\\tt Cufflinks}. \r\n\r\n\\begin{table}[h]{\r\n    \\Small\r\n    \\label{table:reads}\r\n    \\begin{tabular}{l|c|c|c|c|c|c} \r\n        \\hline\r\n        \\textbf{Sample} & \\textbf{Sequenced} & \\textbf{Aligned} & \\textbf{Singleton} & \\textbf{Spliced} & \\textbf{Multi-mapping} & \\textbf{Total} \\\\\r\n        & \\textbf{fragments} & \\textbf{fragments} & \\textbf{fragments} & \\textbf{fragments} & \\textbf{fragments} & \\textbf{alignments} \\\\\r\n        \\hline\r\n\r\n        -24 hours & 42,184,539 & 35,852,366 & 11,031,886 & 8,824,825 & 1,768,041 & 41,663,170 \\\\\r\n        60 hours & 70,192,031 & 57,071,494 & 18,104,211 & 15,778,114 & \t2,265,378 & 64,637,511 \\\\\r\n        120 hours & 41,069,106 & 27,914,989 & 14,431,734 & 7,711,026 & 1,881,772 & 33,929,133 \\\\\r\n        168 hours & 61,787,833 & 50,705,080 & 20,396,250 & 14,585,287 & \t2,458,292 &\t58,797,912 \\\\\r\n        Total & 215,233,509 & 171,543,929 & 63,964,081 & 46,899,252 & 8,373,483 & 199,027,726 \\\\\r\n\r\n        \\hline\r\n        \r\n    \\end{tabular}\r\n    }\r\n\\vskip 0.2in\r\n\\caption[Number of fragments sequenced, aligned and mapped with {\\tt TopHat}]{Number of fragments sequenced, aligned and mapped with {\\tt\r\n    TopHat}. Singleton fragments are fragments for which only one end\r\n  could be mapped. Spliced fragments include at least one end that\r\n  maps across a junction. The numbers in the total alignment column\r\n  may not be the sum of the entries in each row, because some fragments\r\n  fall into multiple classes.}\r\n\\end{table}\r\n\r\n\\newpage\r\n\\section{Transcript abundance estimation \\label{abundances}}\r\n\\label{sec:abundances}\r\n\r\n\\subsection{Definitions}\r\n\r\nA {\\em transcript} is an RNA molecule that has been transcribed from DNA. A\r\n{\\em primary transcript} is an RNA molecule that has yet to undergo\r\nmodification. The {\\em genomic location} of a primary transcript consists of a\r\npair of coordinates in the genome representing the $5'$ transcription start\r\nsite and the $3'$ polyadenylation cleavage site. We denote the set of all\r\ntranscripts in a transcriptome by $T$. We partition transcripts into {\\em\r\ntranscription loci} (for simplicity we refer to these as loci) so that every\r\nlocus contains a set of transcripts all of whose genomic locations do not\r\noverlap the genomic location of any transcript in any other locus. Formally,\r\nwe consider a maximal partition of transcripts into loci, a partition denoted\r\nby $G$, where the genomic location of a transcript $t \\in g \\in G$ does not\r\noverlap the genomic location of any transcript $u $ where $u \\in h \\in G$ and\r\n$h \\neq g$. We emphasize that the definition of a transcription locus is not\r\nbiological; transcripts in the same locus may be regulated via different\r\npromoters, and may differ completely in sequence (for example if one\r\ntranscript is in the intron of another) or have different functions. The\r\nreason for defining loci is that we will see that they are computationally\r\nconvenient.\r\n\r\n\r\nWe assume that at the time of an experiment, a transcriptome consists of an\r\nensemble of transcripts $T$ where the proportion of transcript $t \\in T$ is\r\n$\\rho_t$, so that $\\sum_{t \\in T} \\rho_t = 1$ and $0 \\leq \\rho_t \\leq 1$ for\r\nall $t \\in T$. Formally, a {\\em transcriptome} is a set of transcripts $T$\r\ntogether with the abundances $\\rho=\\{ \\rho_t\\}_{t \\in T}$. For convenience we also introduce\r\nnotation for the proportion of transcripts in each locus. We let $\\sigma_g =\r\n\\sum_{t \\in g} \\rho_t$. Similarly, within a locus $g$, we denote the\r\nproportion of each transcript $t \\in g$ by $\\tau_t = \\frac{\\rho_t}{\\sigma_g}$.\r\nWe refer to $\\rho,\\sigma$ and $\\tau$ as {\\em transcript abundances}.\r\n\r\n\r\nTranscripts have lengths, which we denote by $l(t)$. For a collection of transcripts $S \\subset T$ in a transcriptome, we define the length of $S$ using the weighted mean:\r\n\\begin{equation}\r\n\\label{eq:effective_length}\r\nl(S) =\\frac{\\sum_{t \\in S} \\rho_tl(t)}{\\sum_{t \\in S}\\rho_t}.\r\n\\end{equation}\r\nIt is important to note that the length of a set of transcripts depends on their relative abundances; the reason for this will be clear later. \r\n\r\nOne grouping of transcripts that we will focus on is the set of transcripts\r\nwithin a locus that share the same transcription start site (TSS). Unlike the\r\nconcept of a locus, grouping by TSS has a biological basis. Transcripts\r\nwithin such a group are by definition alternatively spliced, and if they have\r\ndifferent expression levels, this is most likely due to the spliceosome and\r\nnot due to differences in transcriptional regulation.\r\n\r\n\\subsection{A statistical model for RNA-Seq}\r\n\r\nIn order to analyze expression levels of transcripts with RNA-Seq data, it is\r\nnecessary to have a model for the (stochastic) process of sequencing. A {\\em\r\nsequencing experiment} consists of selecting a total of $M$ fragments of\r\ntranscripts uniformly at random from the transcriptome. Each fragment is\r\nidentified by sequencing from its ends, resulting in two reads called {\\em\r\nmate pairs}. The length of a fragment is a random variable, with a\r\ndistribution we will denote by $F$. That is, the probability that a fragment\r\nhas length $i$ is $F(i)$ and $\\sum_{i=1}^{\\infty} F(i) = 1$. In this paper we\r\nassume that $F$ is normal, however in principle $F$ can be estimated using\r\ndata from the experiment (e.g. spike-in sequences). We decided to use\r\nthe normal approximation to $F$ (allowing for user specified\r\nparameters of the normal distribution) in order to simplify the\r\nrequirements for running {\\tt Cufflinks} at this time. \r\n\r\nThe assumption of random\r\nfragment selection is known to oversimplify the complexities of a sequencing\r\nexperiment, however without rigorous ways to normalize we decided to work with\r\nthe uniform at random assumption. It is easy to adapt the model to include\r\nmore complex models that address sequencing bias as RNA-Seq experiments mature\r\nand the technologies are better understood.\r\n\r\nThe transcript abundance estimation problem in paired-end RNA-Seq is to\r\nestimate $\\rho$ given a set of transcripts $T$ and a set of reads sequenced\r\nfrom the ends of fragments. In {\\tt Cufflinks}, the transcripts $T$ can be\r\nspecified by the user, or alternatively $T$ can be estimated directly from the\r\nreads. The latter problem is the transcript assembly problem which we discuss\r\nin Section \\ref{sec:assembly}. We ran {\\tt Cufflinks} in the latter\r\n``discovery'' mode where we assembled the transcripts without using the\r\nreference annotation.\r\n\r\nThe fact that fragments have different lengths has bearing on the calculation\r\nof the probability of selecting a fragment from a transcript. Consider a\r\ntranscript $t$ with length $l(t)$. The probability of selecting a fragment of\r\nlength $k$ from $t$ at one of the positions in $t$ assuming that it is\r\nselected uniformly at random, is $\\frac{1}{l(t)-k}$. For this reason, we will\r\ndefine an adjusted length for transcripts as\r\n\r\n\\begin{equation}\r\n\\tilde{l}(t) = \\sum_{i=1}^{l(t)} F(i)(l(t)-i+1).\r\n\\end{equation}\r\nWe also revisit the definition of length for a group of transcripts, and define \r\n\\begin{equation}\r\n\\tilde{l}(S) =\\frac{\\sum_{t \\in S} \\rho_t\\tilde{l}(t)}{\\sum_{t \\in S}\\rho_t}.\r\n\\end{equation} \r\n\r\nIt is important to note that given a read it may not be obvious from which\r\ntranscript the fragment it was sequenced from originated. The consistency of\r\nfragments with transcripts is important and we define the {\\em\r\nfragment-transcript matrix} $A_{R,T}$ to be the $M \\times |T|$ matrix with\r\n$A(r,t)=1$ if the fragment alignment $r$ is completely contained in the\r\ngenomic interval spanned by $t$, and all the implied introns in $r$ match\r\nintrons in $t$ (in order), and with $A(r,t)=0$ otherwise. Note that the reads\r\nin Figure 1c in the main text are colored according to the matrix $A_{R,T}$,\r\nwith each column of the matrix corresponding to one of the three colors\r\n(yellow, blue, red) and reads colored according to the mixture of colors\r\ncorresponding to the transcripts their fragments are contained in.\r\n\r\nEven given the read\r\nalignment to a reference genome, it may not be obvious what the length of the\r\nfragment was. Formally, in the case that $A_{R,T}(r,t)=1$ we denote by $I_t(r)$ the fragment length from within\r\na transcript $t$ implied by the (presumably unique) sequences corresponding to\r\nthe mate pairs of a fragment $r$. If $A_{R,T}(r,t)=0$ then $I_t(r)$ is set to be\r\ninfinite and $F(I_t(r)) = 0$. \r\n\r\nGiven a set of reads, we assume that we can identify for each of them the set\r\nof transcripts with which the fragments the reads belonged to are consistent. The\r\nrationale for this assumption is the following: we map the reads to a\r\nreference genome, and we assume that the read lengths are sufficiently long so\r\nthat every mate-pair can be uniquely mapped to the genome. We refer to this\r\nmapping as the {\\em fragment alignment}. We also assume that we know all the\r\npossible transcripts and their alignments to the genome. Therefore, we can\r\nidentify for each read the possible transcripts from which the fragment it\r\nbelonged to originated.\r\n\r\n\\begin{figure}[!ht] \r\n    \\includegraphics[scale=0.8]{pdfs/implied_length}\r\n    \\caption[Implied length of a fragment alignment]{Alignments of reads to the genome (rectangles) may be consistent with multiple transcripts (in this case both $t_1$ and $t_2$). The transcripts $t_1$ and $t_2$ differ by an internal exon; introns are indicated by long dashed lines. If we denote the fragment alignment by $r$, this means that $A_{R,T}(r,t_1)=1$ and $A_{R,T}(r,t_2)=1$. It is apparent that the implied length $I_{t_1}(r) > I_{t_2}(r)$ due to the presence of the extra internal exon in $t_1$. }\r\n\\end{figure}\r\n\r\nWe are now ready to write down the likelihood equation for the model. We will\r\nwrite $L(\\rho|R)$ for the likelihood of a set of fragment alignments $R$\r\nconstructed from $M$ reads. The notation $Pr(trans. = t)$ means ``the\r\nprobability that a fragment selected at random originates from transcript $t$''.\r\n\r\n\\begin{eqnarray}\r\n& & L(\\rho|R) = \\prod_{r \\in R} Pr(rd.\\ aln. =r)\\\\\r\n&  = & \\prod_{r \\in R} \\sum_{t \\in T} Pr(rd.\\ aln. =r|trans. =t)Pr(trans. =t)\\\\\r\n& = & \\prod_{r \\in R} \\sum_{t \\in T} \\frac{\\rho_t\\tilde{l}(t)}{\\sum_{u \\in T}\\rho_u\\tilde{l}(u)} Pr(rd.\\ aln. = r|trans. =t)\\\\ \r\n& = & \\prod_{r \\in R} \\sum_{t \\in T}\\frac{\\rho_t\\tilde{l}(t)}{\\sum_{u \\in T}\\rho_u\\tilde{l}(u)} \\left(\\frac{F(I_t(r))}{l(t)-I_t(r)+1}\\right) \\\\ \\label{eq:likerho}\r\n& = &  \\prod_{r \\in R} \\sum_{t \\in T} \\alpha_t\\left(\\frac{F(I_t(r))}{l(t)-I_t(r)+1}\\right),\r\n\\end{eqnarray}\r\nwhere \r\n\\begin{equation}\r\n\\alpha_t = \\frac{\\rho_t\\tilde{l}(t)}{\\sum_{u \\in T}\\rho_u\\tilde{l}(u)}.\r\n\\end{equation}\r\n\r\nObserve that $\\alpha_t$ is exactly the probability that a fragment selected at\r\nrandom comes from transcript $t$, and we have that $\\sum_{t \\in T}\\alpha_t =\r\n1$. In light of the probabilistic meaning of the $\\alpha=\\{\\alpha_t\\}_{t \\in T}$, we refer to them as\r\n{\\em fragment abundances}.\r\n\r\nIt is evident that the likelihood function is that of a linear model\r\nand  that the likelihood function is\r\nconcave (Proposition \\ref{prop:linearmodel}) so a numerical method can be used\r\nto find the $\\alpha$. It is then possible, in principle, to recover the $\\rho$\r\nusing Lemma \\ref{lemma:readstoprobs}. However the number of parameters is in the tens of\r\nthousands, and in practice this form of the likelihood function is unwieldy.\r\nInstead, we re-write the likelihood utilizing the fact that transcripts in\r\ndistinct loci do not overlap in genomic location.\r\n\r\nWe first calculate the  probability that a fragment originates from a transcript within a given locus $g$:\r\n\\begin{eqnarray}\r\n\\beta_g & := &  \\sum_{t \\in g} \\alpha_t\\\\\r\n& = & \\frac{\\sum_{t \\in g} \\rho_t \\tilde{l}(t)}{\\sum_{u \\in T} \\rho_u \\tilde{l}(u)}\\\\\r\n& = & \\frac{\\sum_{t \\in g} \\sigma_g\\tau_t \\tilde{l}(t)}{\\sum_{h \\in G} \\sum_{u \\in h} \\sigma_h\\tau_u \\tilde{l}(u)}\\\\\r\n& = & \\frac{\\sigma_g\\sum_{t \\in g} \\tau_t \\tilde{l}(t)}{\\sum_{h \\in G} \\sigma_h \\sum_{u \\in h} \\tau_u \\tilde{l}(u)}\\\\\r\n & = &  \\frac{\\sigma_g \\tilde{l}(g)}{\\sum_{h \\in G} \\sigma_h \\tilde{l}(h)}. \r\n\\end{eqnarray}\r\nRecall that $\\sigma_g = \\sum_{t \\in g} \\rho_t$ and that $\\tau_t = \\frac{\\rho_t}{\\sigma_g}$ for a locus $g$. \r\n\r\nSimilarly, the probability of selecting a fragment from a single transcript $t$ conditioned on selecting a transcript from the locus $g$ in which $t$ is contained is\r\n\\begin{equation}\r\n\\label{eq:gammatau}\r\n\\gamma_t = \\frac{\\tau_t \\tilde{l}(t)}{\\sum_{u \\in g} \\tau_u \\tilde{l}(u)}. \r\n\\end{equation}\r\nThe parameters $\\gamma=\\{\\gamma_t\\}_{t \\in g}$ are conditional fragment abundances, and they are the parameters we estimate from the data in the next Section. Note that for a transcript $t \\in g$, $\\alpha_t = \\beta_g \\cdot \\gamma_t$ and it is easy to convert between fragment abundances and transcript abundances using Lemma \\ref{lemma:readstoprobs}.\r\n\r\nWe denote the fragment counts by $X$; specifically, we denote the number of\r\nalignments in locus $g$ by $X_g$. Note that $\\sum_{g \\in G} X_g = M$. We also\r\nuse the notation $g_r$ to denote the (unique) locus from which a read\r\nalignment $r$ can be obtained.\r\n\r\nThe likelihood function is given by\r\n\\begin{eqnarray}\r\n& & L(\\rho|R) = \\prod_{r \\in R} Pr(rd.\\ aln. =r)\\\\\r\n&  = & \\prod_{r \\in R} \\sum_{g \\in G} Pr(rd.\\ aln. =r|locus=g)Pr(locus=g)\\\\\r\n& = & \\prod_{r \\in R} \\frac{\\sigma_{g_{r}}\\tilde{l}(g_{r})}{\\sum_{g \\in G} \\sigma_g\\tilde{l}(g)} Pr(rd.\\ aln. =r|locus=g_r)\\\\\r\n& = & \\prod_{r \\in R}  \\beta_{g_r}\r\n\\sum_{t \\in g_r}Pr(rd.\\ aln. =r|locus=g_{r},trans. = t)Pr(trans. =t|locus=g_r)\\\\\r\n& = & \\prod_{r \\in R} \\beta_{g_r}\r\n\\sum_{t \\in g_r} \\frac{\\tau_t\\tilde{l}(t)}{\\sum_{u \\in g_r}\\tau_u \\tilde{l}(u)} Pr(rd.\\ aln. =r|locus=g_{r},trans. = t)\\\\ \r\n& = & \\left( \\prod_{r \\in R} \\beta_{g_r} \\right) \\left( \\prod_{r \\in R} \\sum_{t \\in g} \\gamma_t \\cdot\r\nPr(rd.\\ aln. =r|locus=g_r,trans. =t) \\right)\\\\\r\n& = & \\left( \\prod_{r \\in R}  \\beta_{g_r} \\right) \\left( \\prod_{r \\in R} \\sum_{t \\in g}  \\gamma_t\\cdot  \\frac{F(I_t(r))}{l(t)-I_t(r)+1}\\right)\\\\\r\n& = & \\left( \\prod_{g \\in G}  \\beta_g^{X_{g}} \\right) \\left( \\prod_{g \\in G} \\left( \\prod_{r \\in R:r \\in g} \\sum_{t \\in g}  \\gamma_t \\cdot\r\n\\frac{F(I_t(r))}{l(t)-I_t(r)+1}\\right) \\right). \\label{eq:likebest}\r\n\\end{eqnarray}\r\n\r\nExplicitly, in terms of the parameters $\\rho$, Equation (\\ref{eq:likebest})\r\nsimplifies to Equation (\\ref{eq:likerho}) but we will see in the next section\r\nhow the maximum likelihood estimates $\\hat{\\rho}$ are most conveniently\r\nobtained by first finding $\\hat{\\beta}$ and $\\hat{\\gamma}$ using Equation\r\n(\\ref{eq:likebest}).\r\n\r\nWe note that it is biologically meaningful to include prior distributions on\r\n$\\sigma$ and $\\tau$ that reflect the inherent stochasticity and resulting\r\nvariability of transcription in a cell. This will be an interesting direction\r\nfor further research as more RNA-Seq data (with replicates) becomes available\r\nallowing for the determination of biologically meaningful priors. In\r\nparticular, it seems plausible that specific isoform abundances may vary\r\nconsiderably and randomly within cells from a single tissue and that this may\r\nbe important in studying differential splicing. We mention to this to clarify\r\nthat in this paper, the confidence intervals we report represent the\r\nvariability in the maximum likelihood estimates $\\hat{\\sigma}_j$ and\r\n$\\hat{\\tau}^k_j$, and are not the variances of prior distributions.\r\n\r\n\r\n\\subsection{Estimation of parameters}\r\n\r\nWe begin with a discussion of identifiability of our\r\nmodel. Identifiability refers to the injectivity of the model, i.e.,\r\n\\begin{equation}\r\n\\mbox{if } Pr_{\\rho_1}(r) = Pr_{\\rho_2}(r) \\  \\forall r \\in R, \\ \\mbox{ then } \\rho_1 = \\rho_2.\r\n\\end{equation}\r\n\r\n\r\nThe identifiability of RNA-Seq models was discussed in\r\n\\cite{Hiller2009}, where a standard analysis for linear models is\r\napplied to RNA-Seq (for another related biological example, see \\cite{Pe'er2004} which discusses\r\nidentifiability of haplotypes in mixed populations from genotype data).\r\nThe results in these papers apply to our model. For completeness we review the conditions for\r\nidentifiability. Recall that $A_{R,T}$ is the fragment-transcript matrix that specifies which transcripts each fragment is compatible with. The following theorem provides a simple characterization of identifiability:\r\n\r\n\\begin{thm}\r\nThe RNA-Seq model is identifiable iff $A_{R,T}$ is full rank.\r\n\\end{thm}\r\n\r\nTherefore, for a given set of transcripts and a read set $R$, we can\r\ntest whether the model is identifiable using elementary linear\r\nalgebra. For the results in this paper, when estimating expression\r\nwith given annotations, when the model was not identifiable we picked {\\em a} maximum likelihood solution,\r\nalthough in principle it is possible to bound the total expression of\r\nthe locus and/or report identifiability problems to the user. \r\n\r\nReturning to the likelihood function\r\n\\begin{equation}\r\n\\left( \\prod_{g \\in G}  \\beta_g^{X_{g}} \\right) \\left( \\prod_{g \\in G} \\left( \\prod_{r \\in R:r \\in g} \\sum_{t \\in g}  \\gamma_t \\cdot\r\n\\frac{F(I_t(r))}{l(t)-I_t(r)+1}\\right) \\right),\r\n\\end{equation}\r\nwe note that both the $\\beta$ and $\\gamma$ parameters depend on the $\\rho$ parameters. However, we will see that if we maximize the $\\beta$ separately from the $\\gamma$, and also each of the sets $\\{\\gamma_t:t \\in g\\}$ separately, then it is always possible to find $\\rho$ that match both the maximal $\\beta$ and $\\gamma$. In other words, \r\nthe problem of finding $\\hat{\\rho}$ is equivalent\r\nto finding $\\hat{\\beta}$ that maximizes \r\n$ \\prod_{g \\in G} \\beta_g^{X_g}$\r\nand separately, for each locus $g$, the $\\hat{\\gamma}_t$ that maximize\r\n\\begin{equation}\r\n\\prod_{r \\in R:r \\in g} \\sum_{t \\in g}  \\gamma_t\r\n\\frac{F(I_t(r))}{l(t)-I_t(r)+1}.\r\n\\end{equation}\r\n\r\nWe begin by solving for the $\\hat{\\beta}$ and $\\hat{\\gamma}$ and the variances\r\nof the maximum likelihood estimates, and then explain how these are used to\r\nreport expression levels.\r\n\r\nWe can solve for the $\\hat{\\gamma}$ using the fact that the model is linear.\r\nThat is, the probability of each individual read is linear in the read\r\nabundances $\\gamma_t$. It is a standard result in statistics (see, e.g.,\r\nProposition 1.4 in \\cite{ASCB2005}) that the log likelihood function of a\r\nlinear model is concave. Thus, a hill climbing method can be used to find the\r\n$\\hat{\\gamma}$. We used the EM algorithm for this purpose.\r\n\r\nRather than using the direct ML estimates, we obtained a regularized\r\nestimate by importance sampling from the posterior distribution with a\r\nproposal distribution we explain below. The samples were also used to estimate\r\nvariances for our estimates. \r\n\r\nIt follows from standard MLE asymptotic\r\ntheory that the $\\hat{\\gamma}$ are asymptotically multivariate normal with\r\nvariance-covariance matrix given by the inverse of the observed Fisher\r\ninformation matrix. This matrix is defined as follows:\r\n\r\n\\begin{defn}[Observed Fisher information matrix]\r\nThe observed Fisher information matrix is the negative of the Hessian of the log likelihood function evaluated at the maximum likelihood estimate. That is, for parameters $\\Theta=(\\theta_1,\\ldots,\\theta_n)$, the $n \\times n$ matrix is\r\n\\begin{eqnarray}\r\n\\mathcal{F}_{k,l}(\\hat{\\Theta}) & = & - \\frac{\\partial^2 log(\\mathcal{L}(\\Theta|R))}{\\partial \\theta_k \\theta_l} |_{\\theta=\\hat{\\theta}}.\r\n\\end{eqnarray}\r\n\\end{defn}\r\nIn our case, considering a single locus $g$, the parameters are $\\Theta = (\\gamma_{t_1},\\ldots,\\gamma_{t_{|g|}})$, and as expected from Proposition \\ref{prop:linearmodel}:\r\n\\begin{eqnarray}\r\n\\label{eq:Fisher}\r\n\\mathcal{F}_{t_k,t_l}(\\hat{\\Theta}) & = & \\sum_{r \\in R:r \\in g}\r\n\\left[ \\frac{1}{\\left( \\sum_{h \\in g}  \\hat{\\gamma}_h \\frac{F(I_h(r))}{l(h) - I_h(r)+1} \\right)^2} \\frac{F(I_{t_k}(r)) F(I_{t_l}(r)) }{(l(t_k)-I_{t_k}+1)(l(t_l)-I_{t_l}+1)} \\right].\r\n\\end{eqnarray}\r\n\r\n\r\nBecause some of the transcript abundances may be close to zero, we\r\nadopted the\r\nBayesian approach of \\cite{Jiang2009} and instead sampled from the\r\njoint posterior distribution of $\\Theta$ using the proposal\r\ndistribution consisting of the multivariate normal with mean\r\ngiven by the MLE, and variance-covariance matrix given by the inverse of\r\n(\\ref{eq:Fisher}). If the Observed Fisher Information Matrix is\r\nsingular then the user is warned and the confidence intervals of all\r\ntranscripts are set to $[0,1]$ (meaning that there is no information\r\nabout relative abundances).\r\n\r\nThe method used for sampling was importance sampling. The samples were used to obtain a maximum-a-posterior estimate for\r\n$\\hat{\\gamma}_t$ for each $t$ and for the variance-covariance matrix which we\r\ndenote by $\\Psi^g$ (where $g \\in G$ denotes the locus). Note that $\\Psi^g$ is\r\na $|g| \\times |g|$ matrix. The covariance between $\\hat{\\gamma}_{t_k}$ and\r\n$\\hat{\\gamma}_{t_l}$ for $t_k,t_l \\in g$ is given by $\\Psi^g_{t_k,t_l}$.\r\n\r\nTurning to the maximum likelihood estimates $\\hat{\\beta}$, we use the fact that the model is the log-linear. Therefore, \r\n\\begin{equation}\r\n\\label{eq:sigmahat}\r\n\\hat{\\beta_g} = \\frac{X_{g}}{M}.\r\n\\end{equation}\r\n\r\nViewed as a random variable, the counts $X_{g}$ are approximately Poisson and therefore the variance of the MLE $\\hat{\\beta}_g$ is approximately $X_{g}$. We note that for the tests in this paper we directly used the total counts $M$ and the proportional counts $X_g$, however it is easy to incorporate recent suggestions for total count normalization, such as \\cite{Bullard2010} into {\\tt Cufflinks}.\r\n\r\nThe favored units for reporting expression in RNA-Seq studies to date is not\r\nusing the transcript abundances directly, but rather using a measure\r\nabbreviated as FPKM, which means ``expected number of fragments per kilobase\r\nof transcript sequence per millions base pairs sequenced''. These units are\r\nequivalent to measuring transcript abundances (multiplied by a scalar). The\r\ncomputational advantage of FPKM, is that the normalization constants\r\nconveniently simplify some of the formulas for the variances of transcript\r\nabundance estimates.\r\n\r\nFor example, the abundance of a transcript $t \\in g$ in FPKM units is\r\n\\begin{equation}\r\n\\label{eq:FPKM1}\r\n \\frac{10^6 \\cdot 10^3 \\cdot \\alpha_t}{\\tilde{l}(t)} =  \\frac{10^6 \\cdot 10^3 \\cdot \\beta_g \\cdot \\gamma_t}{\\tilde{l}(t)}.\r\n\\end{equation}\r\n\r\nEquation (\\ref{eq:FPKM1}) makes it clear that although the abundance of each\r\ntranscript $t \\in g$ in FPKM units is proportional to the transcript abundance\r\n$\\rho_t$ it is given in terms of the read abundances $\\beta_g$ and $\\gamma_t$\r\nwhich are the parameters estimated from the likelihood function.\r\n\r\nThe maximum likelihood estimates of $\\beta_g$ and $\\gamma_t$ are random\r\nvariables, and we denote their scaled product (in FPKM units) by $A_t$. That\r\nis $Pr(A_t = a)$ is the probability that for a random set of fragment alignments\r\nfrom a sequencing experiment, the maximum likelihood estimate of the\r\ntranscript abundance for $t$ in FPKM units is $a$.\r\n\r\nUsing the fact that the expectation of a product of independent random\r\nvariables is the product of the expectations, for a transcript $t \\in g$ we\r\nhave\r\n\\begin{equation}\r\nE[A_t] = \\frac{10^9X_{g}\\hat{\\gamma}_t}{\\tilde{l}(t)M}.\r\n\\end{equation}\r\n\r\nGiven the variance estimates for the $\\hat{\\gamma}_t$ we turn to the problem of estimating $Var[A_t]$ for a transcript $t \\in g$. We use Lemma \\ref{lemma:varproduct} to obtain\r\n\\begin{eqnarray}\r\nVar[A_t]& =  & \\left(\\frac{10^9}{\\tilde{l}(t)M}\\right)^2 \\left( \\Psi^g_{t,t}X_{g} + \\Psi^g_{t,t}X^2_{g} + (\\hat{\\gamma}_t)^2 X_{g} \\right)\\\\\r\n& = & X_{g}\\left(\\frac{10^9}{\\tilde{l}(t)M)}\\right)^2  \\left( \\Psi^g_{t,t}(1+X_{g}) + (\\hat{\\gamma}_t)^2\\right).\r\n\\end{eqnarray}\r\n\r\nThis variance calculation can be used to estimate a confidence interval by\r\nutilizing the fact \\cite{Aroian1978} that when the expectation divided by the\r\nstandard deviation of at least one of two random variables is large, their\r\nproduct is approximately normal.\r\n\r\nNext we turn to the problem of estimating expression levels (and variances of\r\nthese estimates) for groups of transcripts. Let $S \\subset T$ be a group of\r\ntranscripts located in a single locus $g$, e.g. a collection of transcripts\r\nsharing a common TSS.\r\n\r\nThe analogy of Equation (\\ref{eq:FPKM1}) for the FPKM of the group is\r\n\\begin{eqnarray}\r\n\\label{eq:grouphard}\r\n& & \\frac{10^6 \\cdot 10^3 \\cdot \\beta_g \\cdot \\left( \\sum_{t \\in S} \\gamma_t\\right)}{\\tilde{l}(S)}\\\\ \r\n& = & 10^6 \\cdot 10^3 \\cdot \\beta_g \\cdot \\sum_{t \\in S} \\frac{\\gamma_t}{\\tilde{l}(t)}. \\label{eq:groupeasy}\r\n\\end{eqnarray}\r\n\r\nAs before, we denote by $B_S$ the random variables for which $Pr(B_S = b)$ is\r\nthe probability that for a random set of fragment alignments from a sequencing\r\nexperiment, the maximum likelihood estimate of the transcript abundance for\r\nall the transcripts in $S$ in FPKM units is $b$. We note that the $B_S$ are\r\nproducts and sums of random variables (Equation (\\ref{eq:groupeasy})). This\r\nmakes Equation (\\ref{eq:groupeasy})  more useful than the\r\nequivalent unsimplified Equation (\\ref{eq:grouphard}), especially because\r\n$\\tilde{l}(S)$ is, in general, a ratio of two random variables.\r\n\r\nWe again use the fact that the expectation of independent random variables is\r\nthe product of the expectation, in addition to the fact that expectation is a\r\nlinear operator to conclude that for a group of transcripts $S$,\r\n\r\n\\begin{equation}\r\n\\label{eq:expectTSS}\r\nE[B_S] = \\frac{10^9 \\cdot X_g \\cdot \\sum_{t \\in S} \\frac{\\hat{\\gamma}_t}{\\tilde{l}(t)}}{M}.\r\n\\end{equation}\r\nIn order to compute the variance of $B_S$, we first note that \r\n\\begin{equation}\r\nVar\\left[\\sum_{t \\in S} \\frac{\\hat{\\gamma}_t}{\\tilde{l}(t)}\\right] = \\sum_{t \\in S}\\frac{1}{\\tilde{l}(t)^2}\\Psi^g_{t,t} + \\sum_{t,u \\in S} \\frac{1}{\\tilde{l}(t)\\tilde{l}(u)} \\Psi^g_{t,u}.\r\n\\end{equation}\r\nTherefore,\r\n\\begin{eqnarray}\r\n& & \\quad Var[B_S] \\quad = \\quad \\nonumber \\\\ \r\n& &  X_g\\left(\\frac{10^9}{M}\\right)^2\\left( \\left(1+X_g\\right) \\left(\\sum_{t \\in S}\\frac{1}{\\tilde{l}(t)^2}\\Psi^g_{t,t} + \\sum_{t,u \\in S} \\frac{1}{\\tilde{l}(t)\\tilde{l}(u)} \\Psi^g_{t,u}\\right) + \\left( \\sum_{t \\in S} \\frac{\\hat{\\gamma}_t}{\\tilde{l}(t)} \\right)^2 \\right). \\label{eq:varTSS}\r\n\\end{eqnarray}\r\n\r\nWe can again estimate a confidence interval by utilizing the fact that $B_S$\r\nis approximately normal \\cite{Aroian1978}.\r\n\r\n\\subsection{Assessment of abundance estimation}\r\n\r\nWe evaluated the accuracy of {\\tt Cufflinks}' transcript abundance estimates by first comparing the estimated FPKM values for the spiked-in sequences in each sample against their intended concentrations.  Spike FPKMs were highly correlated across a 5-log dynamic range in all four samples (Supplementary Figure \\ref{spikes}).  However, because sequenced spike fragments were unambiguously mappable, we performed additional simulation to measure the accuracy of the software in alternatively spliced loci. \r\n\r\n\\begin{figure}[h] \r\n    \\includegraphics{pdfs/spikes.pdf}\r\n    \\caption[{\\tt Cufflinks}' abundance estimates of spiked-in sequences]{{\\tt Cufflinks}' abundance estimates of spiked-in sequences.\\label{spikes}}\r\n\\end{figure}\r\n\r\n\\begin{figure}[h] \r\n    \\includegraphics[scale=0.5]{pdfs/sim_small.pdf}\r\n    \\caption[Accuracy of {\\tt Cufflinks} abundance estimates]{\\emph{In silico} assessment of the accuracy of {\\tt Cufflinks}’  abundance estimation when provided with a perfect assembly (a) and after {\\it de novo} comparative assembly (b). Red points indicate in silico transcripts that were only partially recovered, where black points were fully reconstructed by {\\tt Cufflinks}. Simulated reads were aligned with {\\tt TopHat} and the alignments were provided to {\\tt Cufflinks} along with the structures of the transcripts in the simulated sample. \\label{sim}}\r\n\\end{figure}\r\n\r\nTo assess the accuracy of {\\tt Cufflinks}' estimates,\r\nwe simulated an RNA-Seq experiment using the FluxSimulator, a freely available\r\nsoftware package that models whole-transcriptome sequencing experiments with\r\nthe Illumina Genome Analyzer. \\cite{Sammeth} The software works by first\r\nrandomly assigning expression values to the transcripts provided by the user,\r\nconstructing an amplified, size-selected library, and sequencing\r\nit. Mouse UCSC transcripts were supplied to the software, along with build\r\n37.1 of the genome. FluxSimulator then randomly assigned expression ranks to\r\n18,935 transcripts, with the expression value $y$ computed from the rank $x$\r\naccording to the formula \r\n\r\n\\begin{equation}\r\n    y =\\left( \\frac{x}{5.0 \\times 10^7}\\right)^{-0.6}e^{-\\left(\\frac{x}{9.5\\times{10^3}}\\right) - \\left(\\frac{x}{9.5\\times{10^3}}\\right)^2}. \r\n\\end{equation}\r\n\r\nFrom these relative expression levels, the software constructed an \\emph{in\r\nsilico} RNA sample, with each transcript assigned a number of molecules\r\naccording to its abundances. The software modeled the polyadenylation of each\r\ntranscript by adding a poly-A tail (of mean length 125nt) after the terminal\r\nexon. FluxSimulator then simulated reverse transcription of \\emph{in silico}\r\nmRNAs by random hexamer priming, followed by size selection of RT products to\r\nbetween 175 and 225 nt. The resulting ``library'' of 6,601,805 cDNA fragments\r\nwas then sampled uniformly at random for simulated sequencing, where the\r\ninitial and terminal 75bp of each selected fragment were reported as reads.\r\nFluxSimulator does not allow precise control over the number of reads\r\ngenerated (Michael Sammeth, personal communication), but nevertheless\r\ngenerated 13,203,516 75nt paired-end RNA-Seq reads. These reads included\r\nsequencing errors; FluxSimulator includes a position-specific sequencing\r\nerror model.\r\n\r\nFragments were mapped with {\\tt TopHat} to the mouse genome using identical\r\nparameters to those used to map the C2C12 reads, mapping a total of 6,176,961\r\n(93\\% of the library). These alignments were supplied along with the exact set\r\nof expressed transcripts to {\\tt Cufflinks}, to measure {\\tt Cufflinks}' abundance\r\nestimation accuracy when working with a ``perfect'' assembly (Supplementary\r\nFigure \\ref{sim}). Estimated FPKM was very close to true \\emph{in silico} FPKM\r\nacross a dynamic range of expression of nearly six orders of magnitude\r\n($R^2=0.95$).\r\n\r\n\\begin{figure}[!ht] \r\n    \\includegraphics[scale=0.30]{pdfs/vs_no_discovery_small.pdf}\r\n    \\caption[Improved abundance accuracy with novel\r\n    transcripts]{Excluding novel C2C12 transcripts from abundance\r\n      estimation results in inaccurate estimates for known transcripts. \\label{vs_no_discovery}}\r\n\\end{figure}\r\n\r\nEstimation of transcript abundances by assigning fragments to them may be inaccurate if\r\none is working with an incomplete set of transcripts for a particular sample.\r\nTo evaluate the impact of missing transcripts, we removed the newly discovered\r\ntranscripts from our high-confidence set and re-estimated the abundances of\r\nknown transcripts, and then compared them to those obtained when working with\r\nthe complete high-confidence set. While estimates of known transcripts were\r\noverall similar or identical when working with both sets, reflecting\r\nsingle-isoform or fully annotated genes, isoforms of some alternatively\r\nspliced genes differed greatly. (Supplementary Figure \\ref{vs_no_discovery})\r\n\r\nAs a final note, we point out that a na\\\"{i}ve, yet popular, current\r\napproach to expression estimation is to sum the reads mapping to a\r\ngene (where the sum is taken across all exons appearing in all\r\npossible isoforms), and then to normalize the count by either the\r\ntotal number of exonic bases, or by the average length of the\r\ntranscripts. We call the former method the ``projective normalization''\r\nmethod, and the latter the ``average length'' method.\r\n\r\n\\begin{prop}\r\nThe totally projective normalization method is correct only for single isoform\r\ngenes. If a gene has two or more isoforms the expression is underestimated.\r\n\\end{prop}\r\n{\\bf Proof}: The effective length of the gene is overestimated, hence\r\nthe expression level is underestimated. To see this, first note that\r\nthe length of some transcript in a gene is less than the total number\r\nof exonic bases among all transcripts. Then,  if $a_1,\\ldots,a_n$ are\r\nreal numbers all greater than zero and $b_1,\\ldots,b_n$ are not all equal, we have\r\n\\begin{equation}\r\n\\frac{\\sum_{i=1}^na_ib_i}{\\sum_{i=1}^n a_i} < max_{i}(b_i),\r\n\\end{equation}\r\nso that the effective length in equation (\\ref{eq:effective_length}) is always less than the total\r\nnumber of exonic bases among all transcripts.\r\n\r\nStated differently, the projective normalization method has the problem that\r\nit produces numbers that are not proportional to the $\\rho$, so that\r\nit is not additive. The average length method is flawed for the same reason. The\r\ntranscript abundances are not taken into account in computing the\r\neffective lengths. In some cases the method might produce the correct\r\nanswer (for the wrong reasons), but it is bound to be incorrect on most examples,\r\nespecially in genes with transcripts of variable lengths and\r\nnon-uniform abundances.\r\n\r\n\\section{Transcript assembly}\r\n\\label{sec:assembly}\r\n\\subsection{Overview}\r\n\r\n{\\tt Cufflinks} takes as input alignments of RNA-Seq fragments to a reference\r\ngenome and, in the absence of an (optional) user provided annotation, initially assembles transcripts from the alignments. Transcripts in\r\neach of the loci are assembled independently. The assembly algorithm\r\nis designed to aim for the following:\r\n\\begin{enumerate}\r\n\\item Every fragment is consistent with at least one assembled\r\n  transcript.\r\n\\item Every transcript is tiled by reads.\r\n\\item The number of transcripts is the smallest required to satisfy requirement (1).\r\n\\item The resulting RNA-Seq models (in the sense of Section \\ref{sec:abundances}) are identifiable.\r\n\\end{enumerate}\r\nIn other words, we seek an assembly that parsimoniously “explains” the fragments from the RNA-Seq experiment; every\r\nfragment in the experiment (except those filtered out during a preliminary\r\nerror-control step) should have come from a {\\tt Cufflinks} transcript, and\r\n{\\tt Cufflinks} should produce as few transcripts as possible with that property.\r\nThus, {\\tt Cufflinks} seeks to optimize the criterion suggested in \\cite{Xing2004},\r\nhowever, unlike the method in that paper, {\\tt Cufflinks} leverages Dilworth's\r\nTheorem \\cite{Dilworth1950} to solve the problem by reducing it\r\nto a matching problem via the equivalence of Dilworth's and K\\\"{o}nig's theorems (Theorem \\ref{thm:dilko} in Appendix A). Our approach to isoform reconstruction is inspired by a similar approach used for haplotype reconstruction from HIV quasi-species \\cite{Eriksson2008}.\r\n\r\n\\subsection{A partial order on fragment alignments}\r\n\r\nThe {\\tt Cufflinks} program loads a set of alignments in SAM format sorted by reference\r\nposition and assembles non-overlapping sets of alignments independently. After\r\nfiltering out any erroneous spliced alignments or reads from incompletely\r\nspliced RNAs, {\\tt Cufflinks} constructs a partial order (Definition \\ref{def:po}), or equivalently a directed acyclic graph (DAG), with\r\none node for each fragment that in turn consists of an aligned pair of mated reads. First, we note that fragment alignments are of two types: those where reads align in their entirety to the genome, and reads which have a split alignment (due to an implied intron). \r\n\r\nIn the case of single reads, the partial order can be simply\r\nconstructed by checking the reads for {\\em compatibility}. Two reads\r\nare {\\em compatible} if their overlap contains the exact same implied\r\nintrons (or none). If two reads are not compatible they are {\\em\r\n  incompatible}. The reads can be partially ordered by defining, for\r\ntwo reads $x,y$, that $x\\leq y$ if the starting coordinate of $x$ is\r\nat or before the starting coordinate of $y$, and if they are\r\ncompatible.\r\n\r\nIn the case of paired-end RNA-Seq the situation is more complicated\r\nbecause the unknown sequence between mate pairs. To understand this,\r\nwe first note that pairs of fragments can still be determined to be\r\nincompatible if they cannot have originated from the same\r\ntranscript. As with single reads, this happens when there is\r\ndisagreement on implied introns in the overlap. However compatibility\r\nis more subtle. We would like to define a pair of fragments $x,y$ to\r\nbe compatible if they do not overlap, or if every implied intron in one fragment overlaps an identical implied intron in the other fragment. \r\n\r\nHowever it is important to note that it may be impossible to determine\r\nthe compatibility (as defined above) or incompatibility of a pair of fragments. For example, an unknown region internal to a fragment may overlap two different introns (that are incompatible with each other). The fragment may be compatible with one of the introns (and the fragment from which it originates) in which case it is incompatible with the other. Since the opposite situation is also feasible, compatibility (or incompatibility) cannot be assigned. Fragments for which the compatibility/incompatibility cannot be determined with respect to every other fragment are called {\\em uncertain}. Finally, two fragments are called {\\em nested} if one is contained within the other.\r\n\r\n\r\n\\begin{figure}[h] \r\n    \\includegraphics[scale=0.5]{pdfs/compatibility.pdf}\r\n    \\caption[Compatibility and incompatibility of\r\n    fragments]{Compatibility and incompatibility of\r\n      fragments. End-reads are solid lines, unknown sequences within\r\n      fragments are shown by dotted lines and implied introns are\r\n      dashed lines. The reads in (a) are compatible, whereas the\r\n      fragments in (b) are incompatible. The fragments in (c) are\r\n      nested. Fragment $x_4$ in (d) is uncertain, because $y_4$ and\r\n      $y_5$ are incompatible with each other.}\r\n\\end{figure}\r\n\r\nBefore constructing a partial order, fragments are extended to include\r\ntheir nested fragments and uncertain fragments are discarded. These discarded fragments\r\nare used in the abundance estimation. In theory, this may result in\r\nsuboptimal (i.e. non-minimal assemblies) but we determined empirically\r\nthat after assembly uncertain fragments are almost always consistent\r\nwith one of the transcripts. When they are not, there was no\r\ncompletely tiled transcript that contained them. Thus, we employ a\r\nheuristic that substantially speeds up the program, and that works\r\nin practice.\r\n\r\nA partial order $P$ is then constructed from the remaining fragments\r\nby declaring that $x \\leq y$ whenever the fragment corresponding to\r\n$x$ begins at, or before, the location of the fragment corresponding\r\nto $y$ and $x$ and $y$ are compatible. In what follows we identify $P$\r\nwith its Hasse diagram (or covering relation), equivalently a directed\r\nacyclic graph (DAG) that is the transitive reduction. \r\n\r\n\\begin{prop}\r\n$P$ is a partial order.\r\n\\end{prop}\r\n{\\bf Proof}: The fragments can be totally ordered according to the locations where they begin. It therefore suffices to check that if $x,y,z$ are fragments with $x$ compatible with $y$ and $y$ compatible with $z$ then $x$ is compatible with $z$. Since $x$ is not uncertain, it must be either compatible or incompatible with $z$. The latter case can occur only if $x$ and/or $z$ contain implied introns that overlap and are not identical. Since $y$ is not nested within $z$ and $x$ is not nested within $y$, it must be that $y$ contains an implied intron that is not identical with an implied intron in either $x$ or $z$. Therefore $y$ cannot be compatible with both $x$ and $z$. \\qed\r\n\r\n\\subsection{Assembling a parsimonious set of transcripts}\r\n\r\nIn order to assemble a set of transcripts, {\\tt Cufflinks} finds a\r\n(minimum) partition of $P$ into chains (see Definition\r\n\\ref{def:po}). A partition of $P$ into chains yields an assembly\r\nbecause every chain is a totally ordered set of compatible fragments\r\n$x_1,\\ldots,x_l$ and therefore there is a set of overlapping fragments\r\nthat connects them. By Dilworth's theorem (Theorem \\ref{thm:Dilworth}), the problem of finding a minimum partition $P$ into chains is equivalent to finding a maximum antichain in $P$ (an antichain is a set of mutually incompatible fragments). Subsequently, by Theorem \\ref{thm:dilko}, the problem of finding a maximum antichain in $P$ can be reduced to finding a maximum matching in a certain bipartite graph that emerges naturally in deducing Dilworth's theorem from K\\\"{o}nig's theorem \\ref{thm:konig}. \r\nWe call the key bipartite graph the ``reachability'' graph. It is the transitive closure of the DAG, i.e. it is the graph \r\nwhere each fragment $x$ has nodes $L_x$ and $R_x$ in the left and\r\nright partitions of the reachability graph respectively, and where there is an edge between $L_x$ and $R_y$ when $x \\leq y$ in $P$. The maximum matching problem is a classic problem that admits a polynomial time algorithm. The Hopcroft-Karp algorithm \\cite{Hopcroft1973} has a run time of $O(\\sqrt{V}E)$ where in our case $V$ is the number of fragments and $E$ depends on the extent of overlap, but is bounded by a constant times the coverage depth. We note that our parsimony approach to assembly therefore has a better complexity than the $O(V^3)$ PASA algorithm \\cite{Haas2003}. \r\n\r\nThe minimum cardinality chain decomposition computed using the approach above may not be unique.\r\nFor example, a locus may contain two putative distinct initial exons (defined by overlapping incompatible fragments), and one\r\nof two distinct terminal and a constitutive exon in between that is longer than any\r\nread or insert in the RNA-Seq experiment. In such a case, the parsimonious assembly will consist of two transcripts, but there are four possible solutions that are all minimal. In order to ``phase'' distant exons, we leverage the fact that abundance inhomogeneities can link distant exons via their coverage. We therefore weight the edges of the bipartite reachability graph based on the percent-spliced-in metric introduced by\r\nWang \\emph{et al.} in \\cite{Wang2008}. In our setting, the percent-spliced-in\r\n$\\psi_x$ for an alignment $x$ is computed by counting the alignments\r\noverlapping $x$ in the genome that are compatible with $x$ and dividing by the\r\ntotal number of alignments that overlap $x$, and normalizing for the length of\r\nthe $x$. The cost $C(y,z)$ assigned to an edge between alignments $y$ and $z$ reflects\r\nthe belief that they originate from different transcripts:\r\n\r\n\r\n\\begin{equation}\r\n    C(y,z) = -\\log(1 - |\\psi_y - \\psi_z|).\r\n    \\label{eq:match_cost} \r\n\\end{equation}\r\n\r\nRather than using the Hopcroft-Karp algorithm,  a modified version of the {\\tt\r\nLEMON} \\cite{LEMON} and {\\tt Boost} \\cite{Boost} graph libraries are used to\r\ncompute a {\\em min-cost} maximum cardinality matching on the bipartite compatibility\r\ngraph. Even with the presence of weighted edges, our algorithm is\r\nvery fast. The best known algorithm for weighted matching is $O(V^2logV+VE)$.\r\n\r\nBecause we isolated total RNA, we\r\nexpected that a small fraction of our reads would come from the intronic\r\nregions of incompletely processed primary transcripts. Moreover, transcribed\r\nrepetitive elements and low-complexity sequence result in ``shadow''\r\ntransfrags that we wished to discard as artifacts. Thus, {\\tt Cufflinks}\r\nheuristically identifies artifact transfrags and suppresses them in its\r\noutput. We also filter extremely low-abundance minor isoforms of alternatively\r\nspliced genes, using the model described in Section \\ref {abundances} as a\r\nmeans of reducing the variance of estimates for more abundant transcripts. A\r\ntranscript $x$ meeting any of the following criteria is suppressed:\r\n\r\n\\begin{enumerate}\r\n    \\item $x$ aligns to the genome entirely within an intronic region of the alignment for a transcript $y$, and the abundance of $x$ is less than 15\\% of $y$'s abundance.\r\n    \\item $x$ is supported by only a single fragment alignment to the genome.\r\n    \\item More than 75\\% of the fragment alignments supporting $x$, are mappable to multiple genomic loci.\r\n    \\item $x$ is an isoform of an alternatively spliced gene, and has an estimated abundance less than 5\\% of the major isoform of the gene. \r\n\\end{enumerate}\r\n\r\nPrior to transcript assembly, {\\tt Cufflinks} also filters out some of the alignments\r\nfor fragments that are likely to originate from incompletely spliced nuclear\r\nRNA, as these can reduce the accuracy abundance estimates for fully spliced\r\nmRNAs. These filters and the output filters above are detailed in the source\r\nfile \\verb!filters.cpp! of the source code for {\\tt Cufflinks}.\r\n\r\nIn the overview of this Section, we mentioned that our assembly algorithm has the property that the resulting models are identifiable. This is a convenient property that emerges naturally from the parsimony criterion for a ``minimal explanation'' of the fragment alignments. Formally, it is a corollary of Dilworth's theorem:\r\n\r\n\\begin{prop}\r\nThe assembly produced by the {\\tt Cufflinks} algorithm always results in an\r\nidentifiable RNA-Seq model.\r\n\\end{prop}\r\n{\\bf Proof}:  By Dilworth's theorem, the minimum chain decomposition (assembly)\r\nwe obtain has the same size as the maximum antichain in the partially\r\nordered set  we\r\nconstruct from the reads. An antichain consists of reads that are\r\npairwise incompatible, and therefore those reads must form a\r\npermutation sub-matrix in the fragment-transcript matrix $A_{R,T}$ with columns corresponding to the transcripts in a locus, and with rows corresponding to the fragments in the antichain. The matrix $A_{R,T}$ therefore contains permutation sub-matrices that together span all the columns, and the matrix is full-rank.\r\n\r\n\\subsection{Assessment of assembly quality}\r\n\r\nTo compare {\\tt Cufflinks} transfrags against annotated transcriptomes, and\r\nalso to find transfrags common to multiple assemblies, we developed a tool\r\ncalled {\\tt Cuffcompare} that builds structural equivalence classes of\r\ntranscripts. We ran {\\tt Cuffcompare} on each the assembly from each time point against the\r\ncombined annotated transcriptomes of the {UCSC known genes}, {\\tt Ensembl},\r\nand {\\tt Vega}. Because of the stochastic nature of sequencing, \\emph{ab\r\ninitio} assembly of the same transcript in two different samples may result in\r\ntransfrags of slightly different lengths. A {\\tt Cufflinks} transfrag was\r\nconsidered a complete match when there was a transcript with an identical\r\nchain of introns in the combined annotation.\r\n\r\nWhen no complete match is found between a {\\tt Cufflinks} transfrag and the\r\ntranscripts in the combined annotation, {\\tt Cuffcompare} determines and reports if\r\nanother substantial relationship exists with any of the annotation\r\ntranscripts that can be found in or around the same genomic locus. For\r\nexample, when all the introns of a transfrag match perfectly a part of the\r\nintron chain (sub-chain) of an annotation transcript, a ``containment''\r\nrelationship is reported. For single-exon transfrags, containment is also\r\nreported when the exon appears fully overlapped by any of the exons of an\r\nannotation transcript. If there is no perfect match for the intron chain of a\r\ntransfrag but only some exons overlap and there is at least one intron-exon\r\njunction match, {\\tt Cuffcompare} classifies the transfrag as a putative ``novel''\r\nisoform of an annotated gene. When a transfrag is unspliced (single-exon) and\r\nit overlaps the intronic genomic space of a reference annotation transcript,\r\nthe transfrag is classified as potential pre-mRNA fragment. Finally, when no\r\nother relationship is found between a {\\tt Cufflinks} transfrag and an\r\nannotation transcript, {\\tt Cuffcompare} can check the repeat content of the\r\ntransfrag's genomic region (assuming the soft-masked genomic sequence was also\r\nprovided) and it would classify the transfrag as ``repeat'' if most of its\r\nbases are found to be repeat-masked.\r\n\r\nWhen provided multiple time point assemblies, {\\tt Cuffcompare} matches transcripts\r\nbetween samples that have an identical intron structure, placing all mutually\r\nmatching transcripts in the same equivalence class. The program reports a\r\nnon-redundant set of transcript structures, choosing the longest transcript\r\nfrom each equivalence class as the representative transcript. {\\tt Cuffcompare} also\r\nreports the relationships found between each equivalence class (transcripts\r\nthat have a complete match across time points) and reference transcripts from\r\nthe combined annotation set, where applicable.\r\n\r\n\\begin{figure}[h] \r\n    \\includegraphics{pdfs/categories.pdf}\r\n    \\caption[Categorization of {\\tt Cufflinks} transcripts by estimated depth of read coverage]{Categorization of {\\tt Cufflinks} transcripts by estimated depth of read coverage. \\label{categories}}\r\n\\end{figure}\r\n\r\nTable \\ref{category_table} includes the classifications of the transfrags\r\nreported by {\\tt Cufflinks} after assembling the C2C12 reads. While only\r\n13.5\\% of assembled transfrags represent known transcripts, {\\tt Cufflinks}\r\nassigns more than 76\\% of reads to these, reflecting the fact that moderate\r\nand highly-abundant transfrags generate most of the library fragments in the\r\nexperiment. Less abundant transcripts receive less complete sequencing\r\ncoverage, resulting in numerous transfrags that partially but compatibly match\r\nknown transcripts. Supplementary Figure \\ref{categories} shows the categories\r\nof {\\tt Cufflinks} transfrags as estimated depth of sequencing coverage\r\nincreasing.\r\n\r\n\\begin{table}[h]{\r\n    \\Small\r\n    \\begin{tabular}{l|c|c|c} \r\n        \\hline\r\n        \\textbf{Category} & \\textbf{Transfrags} & \\textbf{\\% of total transfrags} & \\textbf{Assembled reads} (\\%) \\\\\r\n        \\hline\r\n        Match to known isoform & 39,857 & 13.5 &\t76.7 \\\\\r\n        Novel isoform of known gene & 18,565 & 6.3 & 11.3 \\\\\r\n        Contained in known isoform & 71,029 & 24.1 & 4.6 \\\\\r\n        Repeat & 41,906 & 14.2 & 0.6 \\\\\r\n        Intronic & 32,658 & 11.1 & 0.6 \\\\\r\n        Polymerase run-on & 18,522 & 6.3 & 0.5 \\\\\r\n        Intergenic & 48,604 & 16.5 & 1.2 \\\\\r\n        Other artifacts & 22,483 & 7.7 & 4.5 \\\\\r\n        \\hline\r\n        Total transfrags & 293,624 & 100.0 & 100.0 \\\\\r\n        \\hline\r\n        \r\n    \\end{tabular}\r\n    }\r\n\\caption[Types of assembled transfrags]{Classification of all transfrags produced at any time point with respect to annotated gene models and masked repeats in the mouse genome.  Transfrags that are present in multiple time point assemblies are multiply counted to preserve the relative distribution of transfrags among the categories across the full experiment. \\label{category_table}}\r\n\\end{table}\r\n\r\nWe selected the {\\tt Cufflinks} transfrags that did not have a complete match\r\nor ``containment'' relationship with a known annotation transcript, but were\r\nclassified by {\\tt Cuffcompare} as putative ``novel isoforms'' of known genes. We\r\nexplored the sequence similarity between these transfrags and two sets of mRNA\r\nsequences: one set representing the mouse transcriptome and consisting of all\r\nmouse ESTs in dbEST plus all reviewed or validated RefSeq mouse mRNAs, and the\r\nother consisting of all reviewed or validated RefSeq mRNAs from other\r\nmammalian species.\r\n\r\nWe used megablast to map all mouse ESTs onto this set of {\\tt Cufflinks}\r\ntransfrags, only keeping EST alignments where at least 80\\% of the EST length\r\nwas aligned with at least 95\\% identity. We calculated transfrag coverage by\r\ntiling overlapping EST mappings on each transfrag and counted only those\r\ntransfrags that are covered by ESTs for at least 80\\% of the transfrag length\r\nwithout any coverage gaps, and with coverage discontinuities only allowed at\r\nno more than 10\\% distance from either end. For the mouse mRNAs alignments we\r\nalso used megablast with the same basic coverage cutoffs (minimum 80\\% covered\r\nwith no more than 10\\% unaligned on either side of the overlap) but applied to\r\neach pairwise alignment independently (i.e. as opposed to EST alignments, no\r\ncoverage tiling was considered for mRNA alignments). For alignments with the\r\nnon-mouse mRNAs we used discontiguous megablast with a dual (combined)\r\ndiscontiguous word template (option -N 2), with the same coverage assessment\r\nprotocol as in the case of mouse mRNA alignments but with the percent identity\r\ncutoff lowered to 80\\%.\r\n\r\n\\begin{figure}[h] \r\n    \\includegraphics{pdfs/FHL3_RT-PCR.pdf}\r\n    \\caption[New isoform of Fhl3]{New and known isoforms of Fhl3 recovered by {\\tt Cufflinks} at each time point (a) were confirmed by form-specific RT-PCR (b). \\label{FHL3_RT-PCR}}\r\n\\end{figure}\r\n\r\n\\begin{figure}[h] \r\n    \\includegraphics{pdfs/Additional_RT-PCR.pdf}\r\n    \\caption[RT-PCR validation of selected genes]{RT-PCR of selected genes.  For Schip1, {\\tt Cufflinks} assembled a known and a novel isoform (with a new TSS), both of which are detected by RT-PCR.  Prkar1a is annotated with two alternate first exons and start sites in {\\tt UCSC known genes}, both of which were detected. {\\tt Cufflinks} assembles the known isoform of the splicing factor Sfpq, along with a novel variant that contains most of RIKEN clone. Tpm1, a gene known to have muscle- and non-muscle-specific isoforms displays previously observed alternative first and last exons.   \\label{RT-PCR}}\r\n\\end{figure}\r\n\r\n\\begin{table}[h]{\r\n    \\Small\r\n    \\begin{tabular}{r|l|c|c}\r\n         \r\n        \\hline\r\n        \\textbf{Primer name}\t& \\textbf{sequence}\t& \\textbf{product length} & \\textbf{endpoint gel score} \\\\\r\n        \\hline\r\n        \r\n        \\textbf{FHL3 Ex1Ex3}\t& & & \\\\\t\t\r\n        Left &\tCTCGCCGCTGCTCTCTCG & 221 & +++ \\\\\r\n        Right &\tGTGTTGTCATAGCACGGAACG & &\t\\\\\t\r\n        \\textbf{FHL3 Ex2Ex3}\t & & & \\\\\t\t\r\n        Left &\tAGGAAGGGCTCACAAGTGG\t& 407 & +++ \\\\\r\n        Right &\tATAGCACGGAACGCAGTAGG & & \\\\\t\t\r\n        \\textbf{Sfpq Ex9Ex10} & & & \\\\\t\t\r\n        Left & GTGGTGGCATAGGTTATGAAGC & 936 & +++ \\\\\r\n        Right & CCATTTTCAAAAGCTTTCAAGG & & \\\\\t\t\r\n        \\textbf{Sfpq Ex9Ex11} & & & \\\\\t\t\r\n        Left & GTGGTGGCATAGGTTATGAAGC & 172 & +++ \\\\\r\n        Right & CTCAAGTAAATAAGACTCCAAAATCAGC & & \\\\\t\t\r\n        \\textbf{Prkar1aEx1Ex3} & & & \\\\\t\t\r\n        Left & ACAGCAGGGATCTCCTTGTCC & 418 & +++ \\\\\r\n        Right & CCTCTCAAAGTATTCCCGAAGG & & \\\\\t\t\r\n        \\textbf{Prkar1aEx2Ex3} & & & \\\\\t\t\t\r\n        Left & GCTATCGCAGAGTGGTAGTGAGG & 279 & +++ \\\\\r\n        Right & CCTCTCAAAGTATTCCCGAAGG & & \\\\\t\t\t\r\n        \\textbf{Schip1Ex1Ex3} & & & \\\\\t\t\r\n        Left & GGCTATGAGGGTGAAAAGTGC & 1050\t& +++ \\\\\r\n        Right & GTATAGATTCCTGGGCCATCG & & \\\\\t\t\r\n        \\textbf{Schip1Ex2Ex3} & & & \\\\\t\t\r\n        Left & CAGCATGAGTGGTAACCAAGG & 269 & +++ \\\\\r\n        Right & GTATAGATTCCTGGGCCATCG & & \\\\\t\t\r\n        \\textbf{Tpm1Ex1Ex3} & & & \\\\\t\t\r\n        Left & TGAACAAAAGACCCCAGAGG & 565 & +++ \\\\\r\n        Right & CTGAAGTACAAGGCCATCAGC & & \\\\\t\t\r\n        \\textbf{Tpm1Ex2Ex3} & & & \\\\\t\t\t\r\n        Left & AGTTTTATTGAGCGTTGAGACG &\t318 & +++ \\\\\r\n        Right & CTGAAGTACAAGGCCATCAGC & & \\\\\r\n        \\hline\r\n        \r\n    \\end{tabular}\r\n    }\r\n\\caption[Form-specific RT-PCR primers for selected genes]{Form-specific RT-PCR primers for selected genes, designed with Primer3 \\cite{Rozen2000}. \\label{RT-PCR_primers}}\r\n\\end{table}\r\n\r\n\r\nTo assess the dependence of assembly quality on the depth of sequencing, we\r\nmapped and assembled subsets of our reads at the 60 hour time point. We\r\npartitioned the three Illumina lanes' worth of data (a total of ~140 million\r\nreads) into 64 subsets. We then processed a single subset with {\\tt TopHat}\r\nand {\\tt Cufflinks}, as above, and compared the resulting transfrags to the\r\noutput of {\\tt Cufflinks} on all three lanes using {\\tt Cuffcompare}. We\r\nrepeated the mapping and assembly with two subsets, four subsets, eight, and\r\nso on. Figure 4 in the main text shows the fraction of reference transcripts\r\ncaptured by {\\tt Cufflinks} using all three lanes that are still captured when\r\nless data is available. For transcripts with low abundance ($<$15\r\nFPKM), increased sequencing yields more full-length transcripts. However, for\r\neven moderately abundant transcripts ($\\geq$15 FPKM), 75\\% or more of\r\nthe transcripts are recovered with only ~40 million reads, or a lane's worth\r\nof Illumina GA II sequencing.\r\n\r\n\\section{Analysis of gene expression dynamics}\r\n\r\nExpression dynamics of genes are composed of absolute changes in\r\noverall transcript abundances, as well as relative changes in\r\ntranscript abundances over time. Moreover, select groups of\r\ntranscripts, for example transcripts grouped by TSS, may exhibit\r\nspecific dynamics due to the underlying biological mechanisms that\r\ndrive expression.\r\n\r\nIn this section we describe statistical tests we developed in the\r\nmultiple hypothesis testing framework for examining absolute and\r\nrelative changes in arbitrary groups of transcripts.\r\n\r\n\\subsection{Selection of high-confidence transcripts for expression tracking}\r\n\r\nWe first restricted our analysis of expression dynamics over the time-course\r\nto a set of transcripts we believed were fully sequenced and correctly\r\nassembled, and we focused only on known and reliable novel isoforms of\r\nannotated genes. This set consisted of transcripts that either were present in\r\nthe {\\tt UCSC genome browser}, {\\tt Ensembl}, or {\\tt Vega} annotated\r\ntranscriptomes, or were found in multiple C2C12 time point assemblies. We\r\nignored transfrags classified as intronic pre-mRNA or polymerase run-on, as\r\nwell as intergenic repeats to focus on coding genes and long non-coding RNAs.\r\nThis high-confidence set contained a total of 17,416 transcripts, 13,692 of\r\nwhich were in {\\tt UCSC known genes}, {\\tt Ensembl} or {\\tt VEGA} annotation\r\nand 3,724 of which are novel. Running {\\tt Cufflinks}' abundance estimation\r\nalgorithm on this high-confidence set of transcripts at each time point\r\nallowed us to scan for differentially expressed transcripts, differentially\r\nspliced pre-mRNAs, and genes with shifts in promoter preference.\r\n\r\n\\subsection{Testing for changes in absolute expression} \r\n\r\nBetween any two consecutive time points, we tested whether a transcript was\r\nsignificantly (after FDR control \\cite{Benjamini1995}) up or down regulated with respect to the\r\nnull hypothesis of no change, with variability in expression due solely to the\r\nuncertainties resulting from our abundance estimation procedure. This was done\r\nusing the following testing procedure for absolute differential expression:\r\n\r\nWe employed the standard method used in microarray-based expression analysis\r\nand proposed for RNA-Seq in \\cite{Bullard2010}, which is to compute the\r\nlogarithm of the ratio of intensities (in our case FPKM), and to then use the\r\ndelta method to estimate the variance of the log odds. We describe this for\r\ntesting differential expression of individual transcripts and also groups of\r\ntranscripts (e.g. grouped by TSS).\r\n\r\nWe recall that the MLE FPKM for a transcript $t$ in a locus $g$ is given by \r\n\\begin{equation}\r\n\\frac{10^9X_g\\hat{\\gamma}_t}{\\tilde{l}(t)M}.\r\n\\end{equation}\r\nGiven two different experiments resulting in $X^a_g,M^a$ and $X^b_g,M^b$ respectively, as well as $\\hat{\\gamma}^a_t$ and $\\hat{\\gamma}^b_t$, we would like to test the significance of departures from unity of the ratio of MLE FPKMS, i.e. \r\n\\begin{eqnarray}\r\n& & \\left(\\frac{10^9X^a_g\\hat{\\gamma}^a_t}{\\tilde{l}(t)M^a}\\right) / \\left(\\frac{10^9X^b_g\\hat{\\gamma}^b_t}{\\tilde{l}(t)M^b}\\right)\\\\\r\n& = & \\frac{X_g^a\\hat{\\gamma}^a_tM^b}{X_g^b \\hat{\\gamma}^b_tM^a}.\r\n\\end{eqnarray}\r\n\r\nThis can be turned into a test statistic that is approximately normal by\r\ntaking the logarithm, and normalizing by the variance. We recall that using\r\nthe delta method, if $X$ is a random variable then $Var[log(X)] \\approx\r\n\\frac{Var[X]}{E[X]^2}$.\r\n\r\nTherefore, our test statistic is \r\n\\begin{equation}\r\n\\frac{log(X^a_g)+log(\\hat{\\gamma}^a_t)+log(M^b)-log(X^b_g)-log(\\hat{\\gamma}^b_t)-log(M^a)}\r\n{ \\sqrt{\\frac{\\left( \\Psi^{g,a}_{t,t}(1+X^a_{g}) + (\\hat{\\gamma}^a_t)^2\\right)}{X^a_g \\left(\\hat{\\gamma}^a_t \\right)^2}+\r\n\\frac{\\left( \\Psi^{g,b}_{t,t}(1+X^b_{g}) + (\\hat{\\gamma}^b_t)^2\\right)}{X^b_{g}\\left(  \\hat{\\gamma}^b_t\\right)^2}    }  }.\r\n\\end{equation}\r\n\r\nIn order to test for differential expression of a group of transcripts, we\r\nreplace the numerator and denominator above by those from Equations\r\n(\\ref{eq:expectTSS}) and (\\ref{eq:varTSS}).\r\n\r\nIt is has been noted that the power of differential expression tests in RNA-Seq depend on the length of the transcripts being tested, because longer transcripts accumulate more reads \\cite{Oshlack2009}. This means that the results we report are biased towards discovering longer differentially expressed transcripts and genes.\r\n\r\n\\subsection{Quantifying transcriptional and post-transcriptional overloading}\r\n\r\nIn order to infer the extent of differential promoter usage, we\r\ndecided to measure changes in relative abundances of primary\r\ntranscripts of single genes. Similarly, we investigated changes in\r\nrelative abundances of transcripts grouped by TSS in order to infer\r\ndifferential splicing.  These inferences required two ingredients: \r\n\\begin{enumerate}\r\n\\item A metric on probability distributions (derived from relative\r\n  abundances).\r\n\\item A test statistic for assessing significant changes in\r\n  differential promoter usage and splicing as measured using the\r\n  metric referred to above. \r\n\\end{enumerate}\r\n\r\nIn order to address the first requirement, namely a metric on\r\nprobability distributions, we turned to an entropy-based metric. This\r\nwas motivated by the methods in \\cite{Ritchie2008} where tests for\r\ndifferences in relative isoform abundances were performed to\r\ndistinguish cancer cells from normal cells. We extend\r\nthis approach to be able to test for relative isoform abundance changes among multiple\r\nexperiments in RNA-Seq.\r\n\r\n\\begin{defn}[Entropy]\r\nThe entropy of a discrete probability distribution\r\n$p=(p_1,\\ldots,p_n)$ ($0 \\leq p_i \\leq 1$ and $\\sum_{i=1}^n p_i = 1$) is \r\n\\begin{equation}\r\nH(p) = -\\sum_{i=1}^n p_i log p_i.\r\n\\end{equation}\r\nIf $p_i=0$ for some $i$ the value of $p_i log p_i$ is taken to be $0$.\r\n\\end{defn}\r\n\\begin{defn}[The Jensen-Shannon divergence]\r\nThe Jensen-Shannon divergence of $m$ discrete probability distributions $p^1,\\ldots,p^m$ is defined to be:\r\n\\begin{equation}\r\nJS(p^1,\\ldots,p^m) = H\\left(\\frac{p^1 + \\cdots + p^m}{m}\\right) - \\frac{\\sum_{j=1}^m H(p^j)}{m}.\r\n\\end{equation}\r\n\r\nIn other words, the Jensen-Shannon divergence of a set of probability\r\ndistributions is the entropy of their average minus the average of their\r\nentropies. \\end{defn}\r\n\r\nIn the case where $m=2$, we remark that the Jensen-Shannon divergence can also\r\nbe described in terms of the Kullback-Leibler divergence of two discrete\r\nprobability distributions. If we denote Kullback-Leibler divergence by\r\n\r\n\\begin{equation}\r\nD(p^1\\|p^2) = \\sum_i p^1_i log \\frac{p^1_i}{p^2_i},\r\n\\end{equation}\r\nthen\r\n\\begin{equation}\r\nJS(p^1,p^2) = \\frac{1}{2}D(p^1\\|m)+\\frac{1}{2}D(p^2\\|m)\r\n\\end{equation}\r\nwhere $m=\\frac{1}{2}(p^1+p^2)$. In other words the Jensen-Shannon\r\ndivergence is a symmetrized variant of the Kullback-Leibler divergence.\r\n\r\nThe Jensen-Shannon divergence has a number of useful properties: for\r\nexample it is symmetric and non-negative. However it is {\\em not} a\r\nmetric. The following theorem shows how to construct a metric\r\nfrom the Jensen-Shannon divergence:\r\n\r\n\\begin{thm}[Fuglede and Tops{\\o}e 2004 \\cite{Fuglede2004}]\r\nThe square root of the Jensen-Shannon divergence is a metric.\r\n\\end{thm}\r\n\r\nThe proof of this result is based on a harmonic analysis argument that is the basis for\r\nthe remark in the main paper that ``transcript abundances move in time along a\r\nlogarithmic spiral in Hilbert space''.  We therefore call the square root of the Jensen-Shannon divergence the {\\em Jensen-Shannon metric}. We employed this metric in\r\norder to quantify relative changes in expression in (groups of) transcripts.\r\n\r\nIn order to test for significance, we introduce a bit of notation.\r\nSuppose that $S$ is a collection of transcripts (for example, they may\r\n share a common TSS). We define\r\n\\begin{equation}\r\n\\kappa_t = \\frac{ \\frac{\\gamma_t}{\\tilde{l}(t)}}{\\sum_{u \\in S} \\frac{\\gamma_u}{\\tilde{l}(u)}}\r\n\\end{equation}\r\nto be the proportion of transcript $t$ among all the transcripts in a\r\ngroup $S$. We let \r\n$Z=\\sum_{u \\in S} \\hat{\\gamma}_u / \\tilde{l}(u)$ so that $\\hat{\\kappa}_t = \\frac{\\gamma_t}{\\tilde{l}(t)Z}$. We therefore have that\r\n\\begin{eqnarray}\r\n\\label{eq:variancekappa1}\r\nVar[\\hat{\\kappa}_t] & =  &\\frac{Var[\\hat{\\gamma}_t]}{\\tilde{l}(t)^2Z^2}, \\\\\r\nCov[\\hat{\\kappa}_t,\\hat{\\kappa}_u] & =  & \\frac{Cov[\\hat{\\gamma}_t,\\hat{\\gamma}_u]}{\\tilde{l}(t)\\tilde{l}(u)Z^2}.\\label{eq:variancekappa2}\r\n\\end{eqnarray}\r\n\r\nOur test statistic for divergent relative expression was the\r\nJensen-Shannon metric. The test could be applied to multiple time\r\npoints simultaneously, but we focused on pairwise tests (involving\r\nconsecutive time points). Under the null hypothesis of no change in\r\nrelative expression, the Jensen-Shannon metric should be\r\nzero. We tested for this using a one-sided $t$-test, based on an\r\nasymptotic derivation of the distribution of the Jensen-Shannon metric\r\nunder the null hypothesis. This asymptotic distribution is normal by applying the delta method approximation,\r\nwhich involves computing the linear component of the Taylor expansion of the\r\nvariance of $\\sqrt{JS}$.\r\n\r\nIn order to simplify notation, we let $f(p^1,\\ldots,p^m)$ be the\r\nJensen-Shannon metric for $m$ probability distributions $p^1,\\ldots,p^m$.\r\n\r\n\\begin{lemma}\r\nThe partial derivatives of the Jensen-Shannon metric are give by\r\n\\begin{equation}\r\n\\frac{\\partial f}{\\partial p^k_l} = \\frac{1}{2m\\sqrt{f(p^1,\\ldots,p^m)}} log \\left( \\frac{p^k_l}{\\frac{1}{m} \\sum_{j=1}^m p_l^j} \\right).\r\n\\end{equation}\r\n\\end{lemma}\r\n\r\nLet $\\hat{\\kappa}^1,\\ldots,\\hat{\\kappa}^m$ denote $m$ probability\r\ndistributions on the set of transcripts $S$, for example the MLE for the transcript abundances in a time course. Then from the delta method we\r\nhave that $\\sqrt{JS(\\hat{\\kappa}^1,\\ldots,\\hat{\\kappa}^m)}$ is approximately normally\r\ndistributed with variance given by\r\n\r\n\\begin{equation}\r\nVar[\\sqrt{JS(\\hat{\\kappa}^1,\\ldots,\\hat{\\kappa}^m)}] \\approx (\\bigtriangledown f)^T \\Sigma (\\bigtriangledown f),\r\n\\end{equation}\r\n\r\nwhere $\\Sigma$ is the variance-covariance matrix for the\r\n$\\kappa^1,\\ldots,\\kappa^m$, i.e., it is a block diagonal matrix where the\r\n$i$th block is the variance-covariance matrix for the $\\kappa^i_t$ given by\r\nEquations (\\ref{eq:variancekappa1},\\ref{eq:variancekappa2}).\r\n\r\n\r\nThere are two biologically meaningful groupings of transcripts whose\r\nrelative abundances are interesting to track in a\r\ntime course. Transcripts that share a TSS are likely to be regulated by\r\nthe same promoter, and therefore tracking the change in relative\r\nabundances of groups of transcripts sharing a TSS may reveal how\r\ntranscriptional regulation is affecting expression over\r\ntime. Similarly, transcripts that share a TSS and exhibit changes in\r\nexpression relative to each other are likely to be affected by\r\nsplicing or other post-transcriptional regulation. We therefore\r\ngrouped transcripts by TSS and compared relative abundance changes\r\nwithin and between groups. \r\n\r\nWe define ``overloading'' to be a significant change in relative\r\nabundances for a set of transcripts (as determined by the Jensen-Shannon metric, see below). The term is intended to generalize the simple notion of\r\n``isoform switching'' that is well-defined in the case of two\r\ntranscripts, to multiple transcripts. It is complementary to absolute\r\ndifferential changes in expression: the overall expression of a gene\r\nmay remain constant while individual transcripts change drastically in\r\nrelative abundances resulting in overloading. The term is borrowed from\r\ncomputer science, where in some statically-typed programming\r\nlanguages, a function may be used in multiple, specialized instances\r\nvia ``method overloading''. \r\n\r\nWe tested for overloaded genes by performing a one-sided $t$-test based on the asymptotics of the Jensen-Shannon metric under the null hypothesis of no change in relative abundnaces of isoforms (either grouped by shared TSS for for post-transcriptional overloading, or by comparison of groups of isoforms with shared TSS for transcriptional overloading). Type I errors were controlled with the Benjamini-Hochberg \\cite{Benjamini1995} correction for multiple testing. \r\n A selection of overloaded genes are displayed in Supplemental Figs. \\ref{splice_overloaded} and \\ref{promoter_overloaded}.\r\n\r\n\\newpage\r\n\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/splice_overloaded}\r\n    \\caption[Selected genes with post-transcriptional\r\n    overloading]{Selected genes with post-transcriptional\r\n      overloading. Trajectories indicate the expression of individual\r\n      isoforms in FPKM ($y$ axis) over time in hours ($x$\r\n      axis). Dashed isoforms have not been previously\r\n      annotated. Isoform trajectories are colored by TSS, so isoforms\r\n      with the same color presumably share a common promoter and are\r\n      processed from the same primary transcript. It is evident that\r\n      total gene expression may remain constant during isoforms\r\n      switching (Eya3) while in other cases changes in relative\r\n      abundance are accompanied by changes in absolute expression. \r\nThe Jensen-Shannon metric generalizes the notion of ``isoform\r\nswitching'' and is useful in cases with multiple isoforms\r\n(e.g. Ddx17).    \r\n  \\label{splice_overloaded}}\r\n\\end{figure}\r\n\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/promoter_overloaded}\r\n    \\caption[Selected genes with transcriptional overloading]{Selected\r\n      genes with transcriptional overloading. Trajectories indicate\r\n      the expression of individual isoforms in FPKM (y axis) over time\r\n      in hours (x axis). Dashed isoforms have not been previously\r\n      annotated. Isoform trajectories are colored by TSS, so that\r\n      isoforms with different colors presumably vary in their promoter\r\n      and are processed from different primary transcripts.  \\label{promoter_overloaded}}\r\n\\end{figure}\r\n\r\nWe can visualize overloading and expression dynamics with a plot that\r\nsuperimposes transcriptional and post-transcriptional overloading and\r\ngene-level expression over the time course. We refer to these as\r\n``Minard plots'', after Charles Joseph Minard's famous depiction\r\nof the advance and retreat of\r\nNapoleon's armies in the campaign against Russia in 1812\r\n\\cite{Tufte2001}. Minard made use of multiple visual cues to display\r\nnumerous varying quantities in one diagram. An example of a Minard\r\nplot for the gene\r\nMyc is shown in Figure 3c, and others are given in Appendix B. The dotted line indicates gene-level FPKM, with measured\r\nFPKM indicated by black circles. Grey circles indicate the arithmetic mean of\r\ngene-level FPKM between consecutive measured time points, interpolating FPKM\r\nat intermediate time points. The total gene expression overloading is\r\nvisualized as a swatch centered around the interpolated expression curve.\r\nThe width of the swatch encodes the amount of expression overloading between\r\nsuccessive time points. The color of the swatch indicates the relative\r\ncontributions of transcriptional and post-transcriptional expression\r\noverloading.\r\n\r\nSome genes, such as tropomyosin I and II, feature a single primary\r\ntranscript, and so all overloading is by definition post-transcriptional.\r\nOthers, like Fhl3, have two primary transcripts, but only a single isoform\r\narises from each, so all overloading is transcriptional. Genes with multiple\r\nprimary transcripts, one or more of which are alternatively spliced, such as\r\nMyc or RTN4, display both forms.\r\n\r\n\r\n\\section{The {\\tt Cufflinks} software}\r\n\r\nThe transcript assembly and abundance estimation algorithms are implemented in\r\nfreely available open source software called {\\tt Cufflinks} that is available\r\nfrom \\newline {\\tt http://cufflinks.cbcb.umd.edu/} \\newline Furthermore\r\nmethods for comparing annotations across time points, and for performing the\r\ndifferential expression, promoter usage and splicing tests are implemented in\r\nthe companion programs {\\tt Cuffdiff} and {\\tt Cuffcompare}. Instructions on\r\nhow to install and run the software are provided on the website.\r\n\r\nThe input to {\\tt Cufflinks} consists of fragment alignments in the SAM format\r\n\\cite{Li2009a}. These may consist of either single fragment alignments, or alignments of mate-pairs (paired-end reads produce better assemblies and more accurate abundance estimates than single reads). {\\tt Cufflinks} will assemble the transcripts using the\r\nalgorithm in Section \\ref{sec:assembly}, and transcript abundances will be\r\nestimated using the model in Section \\ref{sec:abundances}. Transcript\r\ncoordinates and abundances are reported in the Gene Transfer Format (GTF).\r\nUser supplied annotations may be provided to {\\tt Cufflinks} (optional input) in\r\nwhich case they form the basis for the transcript abundance estimation.\r\n\r\nSome of the algorithms here rely on sufficient depth of sequencing in order to\r\nproduce reliable output. {\\tt Cufflinks} determines that depth is sufficient where\r\npossible to check that required assumptions hold. For example, in loci where one\r\nor more isoforms have extremely low relative expression, the observed Fisher\r\nInformation Matrix may not be positive definite after rounding errors. In this\r\ncase, it is not possible to produce a reliable variance-covariance matrix for\r\nisoform fragment abundances. {\\tt Cufflinks} will report a numerical\r\nexception in this and similar cases. When an exception is reported, the\r\nconfidence intervals for the isoforms' abundances will be set from 0\r\nFPKM to the FPKM for the whole gene. If such an exception is generated during\r\na {\\tt Cuffdiff} run, no differential analysis involving the problematic\r\nsample will be performed on that locus. \r\n\\newpage \r\n\\section{Appendix A: Lemmas and Theorems}\r\n\r\nThe following elementary/classical results are required for our methods and we include them so that the supplement is self-contained.\r\n\r\n\\begin{lemma}\r\n\\label{lemma:varsum}\r\nLet $X_1,\\ldots,X_n$ be random variables and $a_1,\\ldots,a_n$ real numbers with $Y=\\sum_{i=1}^na_iX_i$. Then\r\n\\begin{equation}\r\nVar[Y] = \\sum_{i=1}^n a_i^2Var[X_i]+2\\sum_{i<j} a_ia_j Cov[X_i,X_j].\r\n\\end{equation}\r\n\\end{lemma}\r\n\\begin{lemma}[Taylor Series]\r\nIf $X$ and $Y$ are random variables then\r\n\\begin{eqnarray}\r\n  Var[f(X,Y)] & \\approx & \\left(\\frac{\\partial f}{\\partial X}(E[X],E[Y])\\right)^2Var[X] \\nonumber \\\\ & &+2\\frac{\\partial f}{\\partial X}(E[X],E[Y])\\frac{\\partial f}{\\partial Y}(E[X],E[Y])Cov[X,Y] \\nonumber \\\\ & & +\\left( \\frac{\\partial f}{\\partial Y}(E[X],E[Y])\\right)^2 Var[Y].\r\n\\end{eqnarray}\r\n\\end{lemma}\r\n\\begin{cor}\r\nIf $X$ and $Y$ are independent then\r\n\\begin{eqnarray}\r\n  Var\\left[log\\left(\\frac{X}{Y}\\right)\\right] & \\approx & \\frac{V[X]}{E[X]^2} + \\frac{V[Y]}{E[Y]^2}.\r\n\\end{eqnarray}\r\n\\end{cor}\r\n\\begin{cor}\r\n\\label{lemma:varproduct}\r\nIf $X$ and $Y$ are independent random variables then\r\n\\begin{equation}\r\nVar[XY] = Var[X]Var[Y]+E[X]^2Var[Y]+E[Y]^2Var[X].\r\n\\end{equation}\r\n\\end{cor}\r\n\r\nThe above result is exact using the 2nd order Taylor expansion (higher\r\nderivatives vanish).\r\n\r\n\\begin{lemma}[\\cite{Li2009b}]\r\n\\label{lemma:readstoprobs}\r\nLet $a_1,\\ldots,a_n,w_1,\\ldots,w_n$ be real numbers satisfying: $w_i \\neq 0$ and $0 \\leq a_i \\leq 1$ for all $i$, $\\sum_{i=1}^n a_i = 1$ and $\\sum_{i=1}^na_iw_i \\neq 0$.  Let \r\n$ b_j = \\frac{a_jw_j}{\\sum_{i=1}^n a_iw_i}$. Then $a_j = \\frac{b_j\\frac{1}{w_j}}{\\sum_{i=1}^n b_i\\frac{1}{w_i}}$.\r\n\\end{lemma}\r\n{\\bf Proof}: \\begin{eqnarray}\r\nb_j & =  & \\frac{a_jw_j}{\\sum_{i=1}^n a_iw_i} \\\\\r\n\\Rightarrow \\,  \\sum_{k=1}^n \\frac{b_k}{w_k} & = &   \\sum_{k=1}^n \\frac{a_k}{\\sum_{i=1}^na_iw_i}\\\\\r\n&  = &  \\frac{1}{\\sum_{i=1}^n a_iw_i}\\\\\r\n& = & \\frac{b_j}{a_jw_j}\\\\\r\n \\Rightarrow \\,  a_j  & =  & \\frac{b_j\\frac{1}{w_j}}{\\sum_{i=1}^n b_i \\frac{1}{w_i}}.\r\n\\end{eqnarray} \\qed\r\n\\begin{prop}[\\cite{ASCB2005}]\r\n\\label{prop:linearmodel}\r\nLet $f_i(\\theta) = \\sum_{j=1}^d a_{ij}\\theta_j + b_i$ ($1 \\leq i \\leq\r\nm$) describe a linear statistical model with $a_{ij} \\geq$ for all\r\n$i,j$.  That is, $\\sum_{i=1}^m f_i(\\theta) = 1$. If $u_i \\geq 0$ for\r\nall $i$ then the log likelihood function\r\n\\begin{equation}\r\nl(\\theta) = \\sum_{i=1}^m u_i log(f_i(\\theta))\r\n\\end{equation}\r\nis concave.\r\n\\end{prop}\r\n{\\bf Proof}: It is easy to see that \r\n\\begin{equation}\r\n\\left( \\frac{\\partial^2 l}{\\partial \\theta_j \\partial \\theta_k}  \\right)  = -A^Tdiag\\left( \\frac{u_1}{f_1(\\theta)^2},\\ldots,\\frac{u_m}{f_m(\\theta)^2}\\right) A,\r\n\\end{equation}\r\nwhere $A$ is the $m \\times d$ matrix whose entry in row $i$ and column\r\n$j$ equals $a_{ij}$. Therefore the Hessian is a symmetric matrix with\r\nnon-positive eigenvalues, and is therefore negative semi-definite.\r\n\\qed\r\n\r\n\\begin{defn}\r\n\\label{def:po}\r\nA partially ordered set is a set $S$ with a binary relation $\\leq$\r\nsatisfying:\r\n\\begin{enumerate}\r\n\\item $x \\leq x$ for all $x \\in S$,\r\n\\item If $x \\leq y$ and $y \\leq z$ then $x \\leq z$,\r\n\\item If $x \\leq y$ and $y \\leq x$ then $x=y$.\r\n\\end{enumerate}\r\nA {\\em chain} is a set of elements in $C \\subseteq S$ such that for every\r\n$x,y \\in C$ either $x \\leq y$ or $y \\leq x$. An {\\em antichain} is a set of\r\nelements that are pairwise incompatible.\r\n\\end{defn}\r\nPartially ordered sets are equivalent to directed acyclic graphs (DAGs). The following min-max theorems relate chain partitions to antichains and are special cases of linear-programming duality. More details and complete proofs can be found in \\cite{Lovasz2009}.\r\n\r\n\\begin{thm}[Dilworth's theorem]\r\n\\label{thm:Dilworth}\r\nLet $P$ be a finite partially ordered set. The maximum number of elements in any antichain of $P$ equals the minimum number of chains in any partition of $P$ into chains.\r\n\\end{thm}\r\n\\begin{thm}[K\\\"{o}nig's theorem]\r\n\\label{thm:konig}\r\nIn a bipartite graph, the number of edges in a maximum matching equals\r\nthe number of vertices in a minimum vertex cover.\r\n\\end{thm}\r\n\\begin{thm}\r\n\\label{thm:dilko}\r\nDilworth's theorem is equivalent to K\\\"{o}nig's theorem.\r\n\\end{thm}\r\n{\\bf Proof}: We first show that Dilworth's theorem follows from\r\nK\\\"{o}nig's theorem. Let $P$ be a partially ordered set with $n$\r\nelements. We define a bipartite graph $G=(U,V,E)$ where\r\n$U=V=P$, i.e. each partition in the bipartite graph is equally to\r\n$P$. Two nodes $u,v$ form an edge $(u,v) \\in E$ in the graph $G$ iff\r\n$u<v$ in $P$. By K\\\"{o}nig's theorem there exist both a matching $M$ and a\r\na vertex cover $C$ in $G$ of the same cardinality. Let $T \\subset\r\nS$ be the set of elements not contained in $C$. Note that $T$ is an\r\nantichain in $P$. We now form a partition $W$ of $P$ into chains by declaring $u$ and\r\n$v$ to be in the same chain whenever there is an edge $(u,v) \\in\r\nM$. Since $C$ and $M$ have the same size, it follows that $T$ and $W$\r\nhave the same size.\r\n\r\nTo deduce K\\\"{o}nig's theorem from Dilworth's theorem, we begin with a\r\nbipartite graph $G=(U,V,E)$ and form a partial order $P$ on the\r\nvertices of $G$ by defining $u<v$ when $u \\in U, v \\in V$ and $(u,v)\r\n\\in E$. By Dilworth's theorem, there exists an antichain of $P$ and a\r\npartition into chains of the same size. The non-trivial chains in $P$\r\nform a matching in the graph. Similarly, the complement of the\r\nvertices corresponding to the anti-chain in $P$ is a vertex cover of\r\n$G$ with the same cardinality as the matching.  \\qed\r\n\r\n\\begin{figure}[!ht] \r\n    \\includegraphics[scale=0.8]{pdfs/Dilworth_Konig}\r\n\r\n%\\caption[Equivalence of Dilworth's and K\\\"{o}nig's theorems]{\r\n\\end{figure}\r\nThe equivalence of Dilworth's and K\\\"{o}nig's theorems is depicted above. The\r\n      partially ordered set with 8 elements on the left is partitioned into 3\r\n      chains. This is the size of a minimum partition into chains, and\r\n    is equal to the maximum size of an antichain (Dilworth's\r\n    theorem). The antichain is shown with double circles. On the\r\n    right, the reachability graph constructed from the partially\r\n    ordered set on the left is shown. The maximum matching\r\n    corresponding to the chain partition consists of 5 edges and is equal in size to the\r\n    number of vertices in a minimum vertex cover (K\\\"{o}nig's\r\n    theorem). The vertex cover is shown with double circles. Note that\r\n    8=3+5.\r\n\r\n\r\n\\newpage\r\n\r\n\\section{Appendix B: selected Minard plots}\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/Tpm1_Tpm2.pdf}\r\n\\end{figure}\r\n%\\newpage\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/Fhl3_RTN4.pdf}\r\n\\end{figure}\r\n\\newpage\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/Myf6_Myf5.pdf}\r\n\\end{figure}\r\n%\\newpage\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/MyoD_Myog.pdf}\r\n\\end{figure}\r\n\\newpage\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/Actn.pdf}\r\n\\end{figure}\r\n%\\newpage\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/Ddx.pdf}\r\n\\end{figure}\r\n\\newpage\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/Myl1.pdf}\r\n\\end{figure}\r\n%\\newpage\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/Mef2.pdf}\r\n\\end{figure}\r\n\r\n\\newpage\r\n\\bibliographystyle{amsplain}\r\n\\bibliography{cufflinks}\r\n\\end{document}\r\n\r\n% long read length is required for uniquely determining genomic origin of fragments, but its fragment length that is critical for assignment of fragments to transcripts.\r\n% The length of a set of transcripts depends on their abundances\r\n% single read sequencing prevents the correct normalization for fragment sizes in the length.\r\n"
  },
  {
    "path": "doc/CL_versions.tex",
    "content": "\\documentclass[12pt]{amsart}\r\n\r\n\\usepackage{graphicx}\r\n\\usepackage{amsmath}\r\n\\usepackage[pdftex]{hyperref}\r\n\r\n\\setlength{\\textwidth}{6.2in}\r\n\\setlength{\\textheight}{8.4in}\r\n\\setlength{\\topmargin}{0.2in}\r\n\\setlength{\\oddsidemargin}{0in}\r\n\\setlength{\\evensidemargin}{0in}\r\n\\setlength{\\headsep}{.3in}\r\n\\footskip 0.3in\r\n\\newtheorem{thm}{Theorem}\r\n\\newtheorem{lemma}[thm]{Lemma}\r\n\\newtheorem{prop}[thm]{Proposition}\r\n\\newtheorem{cor}[thm]{Corollary}\r\n\\theoremstyle{definition}\r\n\\newtheorem{defn}[thm]{Definition}\r\n\\newtheorem{example}[thm]{Example}\r\n\\newtheorem{remark}[thm]{Remark}\r\n\\newtheorem{conj}[thm]{Conjecture}\r\n\r\n\\newcommand{\\cherry}[1]{\\ensuremath{\\langle #1 \\rangle}}\r\n\\newcommand{\\ignore}[1]{}\r\n\\newcommand{\\half}{\\frac{1}{2}}\r\n\\newcommand{\\eopf}{\\framebox[6.5pt]{} \\vspace{0.2in}}\r\n\r\n%------------------document begins-----------------------\r\n\r\n\\begin{document}\r\n\r\n\\title{Methods of Cufflinks}\r\n\\author{Cole Trapnell \\and Lior Pachter}\r\n%\\address{}\r\n%\\email{\\{whoweare\\}@math.berkeley.edu}\r\n%\\dedicatory{\\today}\r\n\r\n%\\thanks{Supported in part by ....}\r\n%\\subjclass{Primary 55M20; Secondary 47H10}\r\n\r\n\\maketitle\r\n\\markboth{C Trapnell and L Pachter}{Methods of Cufflinks}\r\n\r\nThis document describes the methods used in the Cufflinks RNA-Seq analysis program.\r\n%\\pagestyle{plain}\r\n\\pagenumbering{roman} \\tableofcontents \\listoffigures \\listoftables \\newpage \\pagenumbering{arabic}\r\n\r\n\\section{Version 0.8.3}\r\n\r\n\\subsection{Transcript abundance estimation \\label{abundances}}\r\n\\label{sec:abundances}\r\n\r\n\\subsubsection{Definitions}\r\n\r\nA {\\em transcript} is an RNA molecule that has been transcribed from DNA. A\r\n{\\em primary transcript} is an RNA molecule that has yet to undergo\r\nmodification. The {\\em genomic location} of a primary transcript consists of a\r\npair of coordinates in the genome representing the $5'$ transcription start\r\nsite and the $3'$ polyadenylation cleavage site. We denote the set of all\r\ntranscripts in a transcriptome by $T$. We partition transcripts into {\\em\r\ntranscription loci} (for simplicity we refer to these as loci) so that every\r\nlocus contains a set of transcripts all of whose genomic locations do not\r\noverlap the genomic location of any transcript in any other locus. Formally,\r\nwe consider a maximal partition of transcripts into loci, a partition denoted\r\nby $G$, where the genomic location of a transcript $t \\in g \\in G$ does not\r\noverlap the genomic location of any transcript $u $ where $u \\in h \\in G$ and\r\n$h \\neq g$. We emphasize that the definition of a transcription locus is not\r\nbiological; transcripts in the same locus may be regulated via different\r\npromoters, and may differ completely in sequence (for example if one\r\ntranscript is in the intron of another) or have different functions. The\r\nreason for defining loci is that we will see that they are computationally\r\nconvenient.\r\n\r\n\r\nWe assume that at the time of an experiment, a transcriptome consists of an\r\nensemble of transcripts $T$ where the proportion of transcript $t \\in T$ is\r\n$\\rho_t$, so that $\\sum_{t \\in T} \\rho_t = 1$ and $0 \\leq \\rho_t \\leq 1$ for\r\nall $t \\in T$. Formally, a {\\em transcriptome} is a set of transcripts $T$\r\ntogether with the abundances $\\rho=\\{ \\rho_t\\}_{t \\in T}$. For convenience we also introduce\r\nnotation for the proportion of transcripts in each locus. We let $\\sigma_g =\r\n\\sum_{t \\in g} \\rho_t$. Similarly, within a locus $g$, we denote the\r\nproportion of each transcript $t \\in g$ by $\\tau_t = \\frac{\\rho_t}{\\sigma_g}$.\r\nWe refer to $\\rho,\\sigma$ and $\\tau$ as {\\em transcript abundances}.\r\n\r\n\r\nTranscripts have lengths, which we denote by $l(t)$. For a collection of transcripts $S \\subset T$ in a transcriptome, we define the length of $S$ using the weighted mean:\r\n\\begin{equation}\r\n\\label{eq:effective_length}\r\nl(S) =\\frac{\\sum_{t \\in S} \\rho_tl(t)}{\\sum_{t \\in S}\\rho_t}.\r\n\\end{equation}\r\nIt is important to note that the length of a set of transcripts depends on their relative abundances; the reason for this will be clear later. \r\n\r\nOne grouping of transcripts that we will focus on is the set of transcripts\r\nwithin a locus that share the same transcription start site (TSS). Unlike the\r\nconcept of a locus, grouping by TSS has a biological basis. Transcripts\r\nwithin such a group are by definition alternatively spliced, and if they have\r\ndifferent expression levels, this is most likely due to the spliceosome and\r\nnot due to differences in transcriptional regulation.\r\n\r\n\\subsubsection{A statistical model for RNA-Seq}\r\n\r\nIn order to analyze expression levels of transcripts with RNA-Seq data, it is\r\nnecessary to have a model for the (stochastic) process of sequencing. A {\\em\r\nsequencing experiment} consists of selecting a total of $M$ fragments of\r\ntranscripts uniformly at random from the transcriptome. Each fragment is\r\nidentified by sequencing from its ends, resulting in two reads called {\\em\r\nmate pairs}. The length of a fragment is a random variable, with a\r\ndistribution we will denote by $F$. That is, the probability that a fragment\r\nhas length $i$ is $F(i)$ and $\\sum_{i=1}^{\\infty} F(i) = 1$. In this paper we\r\nassume that $F$ is normal, however in principle $F$ can be estimated using\r\ndata from the experiment (e.g. spike-in sequences). We decided to use\r\nthe normal approximation to $F$ (allowing for user specified\r\nparameters of the normal distribution) in order to simplify the\r\nrequirements for running {\\tt Cufflinks} at this time. \r\n\r\nThe assumption of random\r\nfragment selection is known to oversimplify the complexities of a sequencing\r\nexperiment, however without rigorous ways to normalize we decided to work with\r\nthe uniform at random assumption. It is easy to adapt the model to include\r\nmore complex models that address sequencing bias as RNA-Seq experiments mature\r\nand the technologies are better understood.\r\n\r\nThe transcript abundance estimation problem in paired-end RNA-Seq is to\r\nestimate $\\rho$ given a set of transcripts $T$ and a set of reads sequenced\r\nfrom the ends of fragments. In {\\tt Cufflinks}, the transcripts $T$ can be\r\nspecified by the user, or alternatively $T$ can be estimated directly from the\r\nreads. The latter problem is the transcript assembly problem which we discuss\r\nin Section \\ref{sec:assembly}. We ran {\\tt Cufflinks} in the latter\r\n``discovery'' mode where we assembled the transcripts without using the\r\nreference annotation.\r\n\r\nThe fact that fragments have different lengths has bearing on the calculation\r\nof the probability of selecting a fragment from a transcript. Consider a\r\ntranscript $t$ with length $l(t)$. The probability of selecting a fragment of\r\nlength $k$ from $t$ at one of the positions in $t$ assuming that it is\r\nselected uniformly at random, is $\\frac{1}{l(t)-k}$. For this reason, we will\r\ndefine an adjusted length for transcripts as\r\n\r\n\\begin{equation}\r\n\\tilde{l}(t) = \\sum_{i=1}^{l(t)} F(i)(l(t)-i+1).\r\n\\end{equation}\r\nWe also revisit the definition of length for a group of transcripts, and define \r\n\\begin{equation}\r\n\\tilde{l}(S) =\\frac{\\sum_{t \\in S} \\rho_t\\tilde{l}(t)}{\\sum_{t \\in S}\\rho_t}.\r\n\\end{equation} \r\n\r\nIt is important to note that given a read it may not be obvious from which\r\ntranscript the fragment it was sequenced from originated. The consistency of\r\nfragments with transcripts is important and we define the {\\em\r\nfragment-transcript matrix} $A_{R,T}$ to be the $M \\times |T|$ matrix with\r\n$A(r,t)=1$ if the fragment alignment $r$ is completely contained in the\r\ngenomic interval spanned by $t$, and all the implied introns in $r$ match\r\nintrons in $t$ (in order), and with $A(r,t)=0$ otherwise. Note that the reads\r\nin Figure 1c in the main text are colored according to the matrix $A_{R,T}$,\r\nwith each column of the matrix corresponding to one of the three colors\r\n(yellow, blue, red) and reads colored according to the mixture of colors\r\ncorresponding to the transcripts their fragments are contained in.\r\n\r\nEven given the read\r\nalignment to a reference genome, it may not be obvious what the length of the\r\nfragment was. Formally, in the case that $A_{R,T}(r,t)=1$ we denote by $I_t(r)$ the fragment length from within\r\na transcript $t$ implied by the (presumably unique) sequences corresponding to\r\nthe mate pairs of a fragment $r$. If $A_{R,T}(r,t)=0$ then $I_t(r)$ is set to be\r\ninfinite and $F(I_t(r)) = 0$. \r\n\r\nGiven a set of reads, we assume that we can identify for each of them the set\r\nof transcripts with which the fragments the reads belonged to are consistent. The\r\nrationale for this assumption is the following: we map the reads to a\r\nreference genome, and we assume that the read lengths are sufficiently long so\r\nthat every mate-pair can be uniquely mapped to the genome. We refer to this\r\nmapping as the {\\em fragment alignment}. We also assume that we know all the\r\npossible transcripts and their alignments to the genome. Therefore, we can\r\nidentify for each read the possible transcripts from which the fragment it\r\nbelonged to originated.\r\n\r\n\\begin{figure}[!ht] \r\n    \\includegraphics[scale=0.8]{pdfs/implied_length}\r\n    \\caption[Implied length of a fragment alignment]{Alignments of reads to the genome (rectangles) may be consistent with multiple transcripts (in this case both $t_1$ and $t_2$). The transcripts $t_1$ and $t_2$ differ by an internal exon; introns are indicated by long dashed lines. If we denote the fragment alignment by $r$, this means that $A_{R,T}(r,t_1)=1$ and $A_{R,T}(r,t_2)=1$. It is apparent that the implied length $I_{t_1}(r) > I_{t_2}(r)$ due to the presence of the extra internal exon in $t_1$. }\r\n\\end{figure}\r\n\r\nWe are now ready to write down the likelihood equation for the model. We will\r\nwrite $L(\\rho|R)$ for the likelihood of a set of fragment alignments $R$\r\nconstructed from $M$ reads. The notation $Pr(trans. = t)$ means ``the\r\nprobability that a fragment selected at random originates from transcript $t$''.\r\n\r\n\\begin{eqnarray}\r\n& & L(\\rho|R) = \\prod_{r \\in R} Pr(rd.\\ aln. =r)\\\\\r\n&  = & \\prod_{r \\in R} \\sum_{t \\in T} Pr(rd.\\ aln. =r|trans. =t)Pr(trans. =t)\\\\\r\n& = & \\prod_{r \\in R} \\sum_{t \\in T} \\frac{\\rho_t\\tilde{l}(t)}{\\sum_{u \\in T}\\rho_u\\tilde{l}(u)} Pr(rd.\\ aln. = r|trans. =t)\\\\ \r\n& = & \\prod_{r \\in R} \\sum_{t \\in T}\\frac{\\rho_t\\tilde{l}(t)}{\\sum_{u \\in T}\\rho_u\\tilde{l}(u)} \\left(\\frac{F(I_t(r))}{l(t)-I_t(r)+1}\\right) \\\\ \\label{eq:likerho}\r\n& = &  \\prod_{r \\in R} \\sum_{t \\in T} \\alpha_t\\left(\\frac{F(I_t(r))}{l(t)-I_t(r)+1}\\right),\r\n\\end{eqnarray}\r\nwhere \r\n\\begin{equation}\r\n\\alpha_t = \\frac{\\rho_t\\tilde{l}(t)}{\\sum_{u \\in T}\\rho_u\\tilde{l}(u)}.\r\n\\end{equation}\r\n\r\nObserve that $\\alpha_t$ is exactly the probability that a fragment selected at\r\nrandom comes from transcript $t$, and we have that $\\sum_{t \\in T}\\alpha_t =\r\n1$. In light of the probabilistic meaning of the $\\alpha=\\{\\alpha_t\\}_{t \\in T}$, we refer to them as\r\n{\\em fragment abundances}.\r\n\r\nIt is evident that the likelihood function is that of a linear model\r\nand  that the likelihood function is\r\nconcave (Proposition \\ref{prop:linearmodel}) so a numerical method can be used\r\nto find the $\\alpha$. It is then possible, in principle, to recover the $\\rho$\r\nusing Lemma \\ref{lemma:readstoprobs}. However the number of parameters is in the tens of\r\nthousands, and in practice this form of the likelihood function is unwieldy.\r\nInstead, we re-write the likelihood utilizing the fact that transcripts in\r\ndistinct loci do not overlap in genomic location.\r\n\r\nWe first calculate the  probability that a fragment originates from a transcript within a given locus $g$:\r\n\\begin{eqnarray}\r\n\\beta_g & := &  \\sum_{t \\in g} \\alpha_t\\\\\r\n& = & \\frac{\\sum_{t \\in g} \\rho_t \\tilde{l}(t)}{\\sum_{u \\in T} \\rho_u \\tilde{l}(u)}\\\\\r\n& = & \\frac{\\sum_{t \\in g} \\sigma_g\\tau_t \\tilde{l}(t)}{\\sum_{h \\in G} \\sum_{u \\in h} \\sigma_h\\tau_u \\tilde{l}(u)}\\\\\r\n& = & \\frac{\\sigma_g\\sum_{t \\in g} \\tau_t \\tilde{l}(t)}{\\sum_{h \\in G} \\sigma_h \\sum_{u \\in h} \\tau_u \\tilde{l}(u)}\\\\\r\n & = &  \\frac{\\sigma_g \\tilde{l}(g)}{\\sum_{h \\in G} \\sigma_h \\tilde{l}(h)}. \r\n\\end{eqnarray}\r\nRecall that $\\sigma_g = \\sum_{t \\in g} \\rho_t$ and that $\\tau_t = \\frac{\\rho_t}{\\sigma_g}$ for a locus $g$. \r\n\r\nSimilarly, the probability of selecting a fragment from a single transcript $t$ conditioned on selecting a transcript from the locus $g$ in which $t$ is contained is\r\n\\begin{equation}\r\n\\label{eq:gammatau}\r\n\\gamma_t = \\frac{\\tau_t \\tilde{l}(t)}{\\sum_{u \\in g} \\tau_u \\tilde{l}(u)}. \r\n\\end{equation}\r\nThe parameters $\\gamma=\\{\\gamma_t\\}_{t \\in g}$ are conditional fragment abundances, and they are the parameters we estimate from the data in the next Section. Note that for a transcript $t \\in g$, $\\alpha_t = \\beta_g \\cdot \\gamma_t$ and it is easy to convert between fragment abundances and transcript abundances using Lemma \\ref{lemma:readstoprobs}.\r\n\r\nWe denote the fragment counts by $X$; specifically, we denote the number of\r\nalignments in locus $g$ by $X_g$. Note that $\\sum_{g \\in G} X_g = M$. We also\r\nuse the notation $g_r$ to denote the (unique) locus from which a read\r\nalignment $r$ can be obtained.\r\n\r\nThe likelihood function is given by\r\n\\begin{eqnarray}\r\n& & L(\\rho|R) = \\prod_{r \\in R} Pr(rd.\\ aln. =r)\\\\\r\n&  = & \\prod_{r \\in R} \\sum_{g \\in G} Pr(rd.\\ aln. =r|locus=g)Pr(locus=g)\\\\\r\n& = & \\prod_{r \\in R} \\frac{\\sigma_{g_{r}}\\tilde{l}(g_{r})}{\\sum_{g \\in G} \\sigma_g\\tilde{l}(g)} Pr(rd.\\ aln. =r|locus=g_r)\\\\\r\n& = & \\prod_{r \\in R}  \\beta_{g_r}\r\n\\sum_{t \\in g_r}Pr(rd.\\ aln. =r|locus=g_{r},trans. = t)Pr(trans. =t|locus=g_r)\\\\\r\n& = & \\prod_{r \\in R} \\beta_{g_r}\r\n\\sum_{t \\in g_r} \\frac{\\tau_t\\tilde{l}(t)}{\\sum_{u \\in g_r}\\tau_u \\tilde{l}(u)} Pr(rd.\\ aln. =r|locus=g_{r},trans. = t)\\\\ \r\n& = & \\left( \\prod_{r \\in R} \\beta_{g_r} \\right) \\left( \\prod_{r \\in R} \\sum_{t \\in g} \\gamma_t \\cdot\r\nPr(rd.\\ aln. =r|locus=g_r,trans. =t) \\right)\\\\\r\n& = & \\left( \\prod_{r \\in R}  \\beta_{g_r} \\right) \\left( \\prod_{r \\in R} \\sum_{t \\in g}  \\gamma_t\\cdot  \\frac{F(I_t(r))}{l(t)-I_t(r)+1}\\right)\\\\\r\n& = & \\left( \\prod_{g \\in G}  \\beta_g^{X_{g}} \\right) \\left( \\prod_{g \\in G} \\left( \\prod_{r \\in R:r \\in g} \\sum_{t \\in g}  \\gamma_t \\cdot\r\n\\frac{F(I_t(r))}{l(t)-I_t(r)+1}\\right) \\right). \\label{eq:likebest}\r\n\\end{eqnarray}\r\n\r\nExplicitly, in terms of the parameters $\\rho$, Equation (\\ref{eq:likebest})\r\nsimplifies to Equation (\\ref{eq:likerho}) but we will see in the next section\r\nhow the maximum likelihood estimates $\\hat{\\rho}$ are most conveniently\r\nobtained by first finding $\\hat{\\beta}$ and $\\hat{\\gamma}$ using Equation\r\n(\\ref{eq:likebest}).\r\n\r\nWe note that it is biologically meaningful to include prior distributions on\r\n$\\sigma$ and $\\tau$ that reflect the inherent stochasticity and resulting\r\nvariability of transcription in a cell. This will be an interesting direction\r\nfor further research as more RNA-Seq data (with replicates) becomes available\r\nallowing for the determination of biologically meaningful priors. In\r\nparticular, it seems plausible that specific isoform abundances may vary\r\nconsiderably and randomly within cells from a single tissue and that this may\r\nbe important in studying differential splicing. We mention to this to clarify\r\nthat in this paper, the confidence intervals we report represent the\r\nvariability in the maximum likelihood estimates $\\hat{\\sigma}_j$ and\r\n$\\hat{\\tau}^k_j$, and are not the variances of prior distributions.\r\n\r\n\r\n\\subsubsection{Estimation of parameters}\r\n\r\nWe begin with a discussion of identifiability of our\r\nmodel. Identifiability refers to the injectivity of the model, i.e.,\r\n\\begin{equation}\r\n\\mbox{if } Pr_{\\rho_1}(r) = Pr_{\\rho_2}(r) \\  \\forall r \\in R, \\ \\mbox{ then } \\rho_1 = \\rho_2.\r\n\\end{equation}\r\n\r\n\r\nThe identifiability of RNA-Seq models was discussed in\r\n\\cite{Hiller2009}, where a standard analysis for linear models is\r\napplied to RNA-Seq (for another related biological example, see \\cite{Pe'er2004} which discusses\r\nidentifiability of haplotypes in mixed populations from genotype data).\r\nThe results in these papers apply to our model. For completeness we review the conditions for\r\nidentifiability. Recall that $A_{R,T}$ is the fragment-transcript matrix that specifies which transcripts each fragment is compatible with. The following theorem provides a simple characterization of identifiability:\r\n\r\n\\begin{thm}\r\nThe RNA-Seq model is identifiable iff $A_{R,T}$ is full rank.\r\n\\end{thm}\r\n\r\nTherefore, for a given set of transcripts and a read set $R$, we can\r\ntest whether the model is identifiable using elementary linear\r\nalgebra. For the results in this paper, when estimating expression\r\nwith given annotations, when the model was not identifiable we picked {\\em a} maximum likelihood solution,\r\nalthough in principle it is possible to bound the total expression of\r\nthe locus and/or report identifiability problems to the user. \r\n\r\nReturning to the likelihood function\r\n\\begin{equation}\r\n\\left( \\prod_{g \\in G}  \\beta_g^{X_{g}} \\right) \\left( \\prod_{g \\in G} \\left( \\prod_{r \\in R:r \\in g} \\sum_{t \\in g}  \\gamma_t \\cdot\r\n\\frac{F(I_t(r))}{l(t)-I_t(r)+1}\\right) \\right),\r\n\\end{equation}\r\nwe note that both the $\\beta$ and $\\gamma$ parameters depend on the $\\rho$ parameters. However, we will see that if we maximize the $\\beta$ separately from the $\\gamma$, and also each of the sets $\\{\\gamma_t:t \\in g\\}$ separately, then it is always possible to find $\\rho$ that match both the maximal $\\beta$ and $\\gamma$. In other words, \r\nthe problem of finding $\\hat{\\rho}$ is equivalent\r\nto finding $\\hat{\\beta}$ that maximizes \r\n$ \\prod_{g \\in G} \\beta_g^{X_g}$\r\nand separately, for each locus $g$, the $\\hat{\\gamma}_t$ that maximize\r\n\\begin{equation}\r\n\\prod_{r \\in R:r \\in g} \\sum_{t \\in g}  \\gamma_t\r\n\\frac{F(I_t(r))}{l(t)-I_t(r)+1}.\r\n\\end{equation}\r\n\r\nWe begin by solving for the $\\hat{\\beta}$ and $\\hat{\\gamma}$ and the variances\r\nof the maximum likelihood estimates, and then explain how these are used to\r\nreport expression levels.\r\n\r\nWe can solve for the $\\hat{\\gamma}$ using the fact that the model is linear.\r\nThat is, the probability of each individual read is linear in the read\r\nabundances $\\gamma_t$. It is a standard result in statistics (see, e.g.,\r\nProposition 1.4 in \\cite{ASCB2005}) that the log likelihood function of a\r\nlinear model is concave. Thus, a hill climbing method can be used to find the\r\n$\\hat{\\gamma}$. We used the EM algorithm for this purpose.\r\n\r\nRather than using the direct ML estimates, we obtained a regularized\r\nestimate by importance sampling from the posterior distribution with a\r\nproposal distribution we explain below. The samples were also used to estimate\r\nvariances for our estimates. \r\n\r\nIt follows from standard MLE asymptotic\r\ntheory that the $\\hat{\\gamma}$ are asymptotically multivariate normal with\r\nvariance-covariance matrix given by the inverse of the observed Fisher\r\ninformation matrix. This matrix is defined as follows:\r\n\r\n\\begin{defn}[Observed Fisher information matrix]\r\nThe observed Fisher information matrix is the negative of the Hessian of the log likelihood function evaluated at the maximum likelihood estimate. That is, for parameters $\\Theta=(\\theta_1,\\ldots,\\theta_n)$, the $n \\times n$ matrix is\r\n\\begin{eqnarray}\r\n\\mathcal{F}_{k,l}(\\hat{\\Theta}) & = & - \\frac{\\partial^2 log(\\mathcal{L}(\\Theta|R))}{\\partial \\theta_k \\theta_l} |_{\\theta=\\hat{\\theta}}.\r\n\\end{eqnarray}\r\n\\end{defn}\r\nIn our case, considering a single locus $g$, the parameters are $\\Theta = (\\gamma_{t_1},\\ldots,\\gamma_{t_{|g|}})$, and as expected from Proposition \\ref{prop:linearmodel}:\r\n\\begin{eqnarray}\r\n\\label{eq:Fisher}\r\n\\mathcal{F}_{t_k,t_l}(\\hat{\\Theta}) & = & \\sum_{r \\in R:r \\in g}\r\n\\left[ \\frac{1}{\\left( \\sum_{h \\in g}  \\hat{\\gamma}_h \\frac{F(I_h(r))}{l(h) - I_h(r)+1} \\right)^2} \\frac{F(I_{t_k}(r)) F(I_{t_l}(r)) }{(l(t_k)-I_{t_k}+1)(l(t_l)-I_{t_l}+1)} \\right].\r\n\\end{eqnarray}\r\n\r\n\r\nBecause some of the transcript abundances may be close to zero, we\r\nadopted the\r\nBayesian approach of \\cite{Jiang2009} and instead sampled from the\r\njoint posterior distribution of $\\Theta$ using the proposal\r\ndistribution consisting of the multivariate normal with mean\r\ngiven by the MLE, and variance-covariance matrix given by the inverse of\r\n(\\ref{eq:Fisher}). If the Observed Fisher Information Matrix is\r\nsingular then the user is warned and the confidence intervals of all\r\ntranscripts are set to $[0,1]$ (meaning that there is no information\r\nabout relative abundances).\r\n\r\nThe method used for sampling was importance sampling. The samples were used to obtain a maximum-a-posterior estimate for\r\n$\\hat{\\gamma}_t$ for each $t$ and for the variance-covariance matrix which we\r\ndenote by $\\Psi^g$ (where $g \\in G$ denotes the locus). Note that $\\Psi^g$ is\r\na $|g| \\times |g|$ matrix. The covariance between $\\hat{\\gamma}_{t_k}$ and\r\n$\\hat{\\gamma}_{t_l}$ for $t_k,t_l \\in g$ is given by $\\Psi^g_{t_k,t_l}$.\r\n\r\nTurning to the maximum likelihood estimates $\\hat{\\beta}$, we use the fact that the model is the log-linear. Therefore, \r\n\\begin{equation}\r\n\\label{eq:sigmahat}\r\n\\hat{\\beta_g} = \\frac{X_{g}}{M}.\r\n\\end{equation}\r\n\r\nViewed as a random variable, the counts $X_{g}$ are approximately Poisson and therefore the variance of the MLE $\\hat{\\beta}_g$ is approximately $X_{g}$. We note that for the tests in this paper we directly used the total counts $M$ and the proportional counts $X_g$, however it is easy to incorporate recent suggestions for total count normalization, such as \\cite{Bullard2010} into {\\tt Cufflinks}.\r\n\r\nThe favored units for reporting expression in RNA-Seq studies to date is not\r\nusing the transcript abundances directly, but rather using a measure\r\nabbreviated as FPKM, which means ``expected number of fragments per kilobase\r\nof transcript sequence per millions base pairs sequenced''. These units are\r\nequivalent to measuring transcript abundances (multiplied by a scalar). The\r\ncomputational advantage of FPKM, is that the normalization constants\r\nconveniently simplify some of the formulas for the variances of transcript\r\nabundance estimates.\r\n\r\nFor example, the abundance of a transcript $t \\in g$ in FPKM units is\r\n\\begin{equation}\r\n\\label{eq:FPKM1}\r\n \\frac{10^6 \\cdot 10^3 \\cdot \\alpha_t}{\\tilde{l}(t)} =  \\frac{10^6 \\cdot 10^3 \\cdot \\beta_g \\cdot \\gamma_t}{\\tilde{l}(t)}.\r\n\\end{equation}\r\n\r\nEquation (\\ref{eq:FPKM1}) makes it clear that although the abundance of each\r\ntranscript $t \\in g$ in FPKM units is proportional to the transcript abundance\r\n$\\rho_t$ it is given in terms of the read abundances $\\beta_g$ and $\\gamma_t$\r\nwhich are the parameters estimated from the likelihood function.\r\n\r\nThe maximum likelihood estimates of $\\beta_g$ and $\\gamma_t$ are random\r\nvariables, and we denote their scaled product (in FPKM units) by $A_t$. That\r\nis $Pr(A_t = a)$ is the probability that for a random set of fragment alignments\r\nfrom a sequencing experiment, the maximum likelihood estimate of the\r\ntranscript abundance for $t$ in FPKM units is $a$.\r\n\r\nUsing the fact that the expectation of a product of independent random\r\nvariables is the product of the expectations, for a transcript $t \\in g$ we\r\nhave\r\n\\begin{equation}\r\nE[A_t] = \\frac{10^9X_{g}\\hat{\\gamma}_t}{\\tilde{l}(t)M}.\r\n\\end{equation}\r\n\r\nGiven the variance estimates for the $\\hat{\\gamma}_t$ we turn to the problem of estimating $Var[A_t]$ for a transcript $t \\in g$. We use Lemma \\ref{lemma:varproduct} to obtain\r\n\\begin{eqnarray}\r\nVar[A_t]& =  & \\left(\\frac{10^9}{\\tilde{l}(t)M}\\right)^2 \\left( \\Psi^g_{t,t}X_{g} + \\Psi^g_{t,t}X^2_{g} + (\\hat{\\gamma}_t)^2 X_{g} \\right)\\\\\r\n& = & X_{g}\\left(\\frac{10^9}{\\tilde{l}(t)M)}\\right)^2  \\left( \\Psi^g_{t,t}(1+X_{g}) + (\\hat{\\gamma}_t)^2\\right).\r\n\\end{eqnarray}\r\n\r\nThis variance calculation can be used to estimate a confidence interval by\r\nutilizing the fact \\cite{Aroian1978} that when the expectation divided by the\r\nstandard deviation of at least one of two random variables is large, their\r\nproduct is approximately normal.\r\n\r\nNext we turn to the problem of estimating expression levels (and variances of\r\nthese estimates) for groups of transcripts. Let $S \\subset T$ be a group of\r\ntranscripts located in a single locus $g$, e.g. a collection of transcripts\r\nsharing a common TSS.\r\n\r\nThe analogy of Equation (\\ref{eq:FPKM1}) for the FPKM of the group is\r\n\\begin{eqnarray}\r\n\\label{eq:grouphard}\r\n& & \\frac{10^6 \\cdot 10^3 \\cdot \\beta_g \\cdot \\left( \\sum_{t \\in S} \\gamma_t\\right)}{\\tilde{l}(S)}\\\\ \r\n& = & 10^6 \\cdot 10^3 \\cdot \\beta_g \\cdot \\sum_{t \\in S} \\frac{\\gamma_t}{\\tilde{l}(t)}. \\label{eq:groupeasy}\r\n\\end{eqnarray}\r\n\r\nAs before, we denote by $B_S$ the random variables for which $Pr(B_S = b)$ is\r\nthe probability that for a random set of fragment alignments from a sequencing\r\nexperiment, the maximum likelihood estimate of the transcript abundance for\r\nall the transcripts in $S$ in FPKM units is $b$. We note that the $B_S$ are\r\nproducts and sums of random variables (Equation (\\ref{eq:groupeasy})). This\r\nmakes Equation (\\ref{eq:groupeasy})  more useful than the\r\nequivalent unsimplified Equation (\\ref{eq:grouphard}), especially because\r\n$\\tilde{l}(S)$ is, in general, a ratio of two random variables.\r\n\r\nWe again use the fact that the expectation of independent random variables is\r\nthe product of the expectation, in addition to the fact that expectation is a\r\nlinear operator to conclude that for a group of transcripts $S$,\r\n\r\n\\begin{equation}\r\n\\label{eq:expectTSS}\r\nE[B_S] = \\frac{10^9 \\cdot X_g \\cdot \\sum_{t \\in S} \\frac{\\hat{\\gamma}_t}{\\tilde{l}(t)}}{M}.\r\n\\end{equation}\r\nIn order to compute the variance of $B_S$, we first note that \r\n\\begin{equation}\r\nVar\\left[\\sum_{t \\in S} \\frac{\\hat{\\gamma}_t}{\\tilde{l}(t)}\\right] = \\sum_{t \\in S}\\frac{1}{\\tilde{l}(t)^2}\\Psi^g_{t,t} + \\sum_{t,u \\in S} \\frac{1}{\\tilde{l}(t)\\tilde{l}(u)} \\Psi^g_{t,u}.\r\n\\end{equation}\r\nTherefore,\r\n\\begin{eqnarray}\r\n& & \\quad Var[B_S] \\quad = \\quad \\nonumber \\\\ \r\n& &  X_g\\left(\\frac{10^9}{M}\\right)^2\\left( \\left(1+X_g\\right) \\left(\\sum_{t \\in S}\\frac{1}{\\tilde{l}(t)^2}\\Psi^g_{t,t} + \\sum_{t,u \\in S} \\frac{1}{\\tilde{l}(t)\\tilde{l}(u)} \\Psi^g_{t,u}\\right) + \\left( \\sum_{t \\in S} \\frac{\\hat{\\gamma}_t}{\\tilde{l}(t)} \\right)^2 \\right). \\label{eq:varTSS}\r\n\\end{eqnarray}\r\n\r\nWe can again estimate a confidence interval by utilizing the fact that $B_S$\r\nis approximately normal \\cite{Aroian1978}.\r\n\r\n\\subsection{Transcript assembly}\r\n\\label{sec:assembly}\r\n\\subsubsection{Overview}\r\n\r\n{\\tt Cufflinks} takes as input alignments of RNA-Seq fragments to a reference\r\ngenome and, in the absence of an (optional) user provided annotation, initially assembles transcripts from the alignments. Transcripts in\r\neach of the loci are assembled independently. The assembly algorithm\r\nis designed to aim for the following:\r\n\\begin{enumerate}\r\n\\item Every fragment is consistent with at least one assembled\r\n  transcript.\r\n\\item Every transcript is tiled by reads.\r\n\\item The number of transcripts is the smallest required to satisfy requirement (1).\r\n\\item The resulting RNA-Seq models (in the sense of Section \\ref{sec:abundances}) are identifiable.\r\n\\end{enumerate}\r\nIn other words, we seek an assembly that parsimoniously “explains” the fragments from the RNA-Seq experiment; every\r\nfragment in the experiment (except those filtered out during a preliminary\r\nerror-control step) should have come from a {\\tt Cufflinks} transcript, and\r\n{\\tt Cufflinks} should produce as few transcripts as possible with that property.\r\nThus, {\\tt Cufflinks} seeks to optimize the criterion suggested in \\cite{Xing2004},\r\nhowever, unlike the method in that paper, {\\tt Cufflinks} leverages Dilworth's\r\nTheorem \\cite{Dilworth1950} to solve the problem by reducing it\r\nto a matching problem via the equivalence of Dilworth's and K\\\"{o}nig's theorems (Theorem \\ref{thm:dilko} in Appendix A). Our approach to isoform reconstruction is inspired by a similar approach used for haplotype reconstruction from HIV quasi-species \\cite{Eriksson2008}.\r\n\r\n\\subsection{A partial order on fragment alignments}\r\n\r\nThe {\\tt Cufflinks} program loads a set of alignments in SAM format sorted by reference\r\nposition and assembles non-overlapping sets of alignments independently. After\r\nfiltering out any erroneous spliced alignments or reads from incompletely\r\nspliced RNAs, {\\tt Cufflinks} constructs a partial order (Definition \\ref{def:po}), or equivalently a directed acyclic graph (DAG), with\r\none node for each fragment that in turn consists of an aligned pair of mated reads. First, we note that fragment alignments are of two types: those where reads align in their entirety to the genome, and reads which have a split alignment (due to an implied intron). \r\n\r\nIn the case of single reads, the partial order can be simply\r\nconstructed by checking the reads for {\\em compatibility}. Two reads\r\nare {\\em compatible} if their overlap contains the exact same implied\r\nintrons (or none). If two reads are not compatible they are {\\em\r\n  incompatible}. The reads can be partially ordered by defining, for\r\ntwo reads $x,y$, that $x\\leq y$ if the starting coordinate of $x$ is\r\nat or before the starting coordinate of $y$, and if they are\r\ncompatible.\r\n\r\nIn the case of paired-end RNA-Seq the situation is more complicated\r\nbecause the unknown sequence between mate pairs. To understand this,\r\nwe first note that pairs of fragments can still be determined to be\r\nincompatible if they cannot have originated from the same\r\ntranscript. As with single reads, this happens when there is\r\ndisagreement on implied introns in the overlap. However compatibility\r\nis more subtle. We would like to define a pair of fragments $x,y$ to\r\nbe compatible if they do not overlap, or if every implied intron in one fragment overlaps an identical implied intron in the other fragment. \r\n\r\nHowever it is important to note that it may be impossible to determine\r\nthe compatibility (as defined above) or incompatibility of a pair of fragments. For example, an unknown region internal to a fragment may overlap two different introns (that are incompatible with each other). The fragment may be compatible with one of the introns (and the fragment from which it originates) in which case it is incompatible with the other. Since the opposite situation is also feasible, compatibility (or incompatibility) cannot be assigned. Fragments for which the compatibility/incompatibility cannot be determined with respect to every other fragment are called {\\em uncertain}. Finally, two fragments are called {\\em nested} if one is contained within the other.\r\n\r\n\r\n\\begin{figure}[h] \r\n    \\includegraphics[scale=0.5]{pdfs/compatibility.pdf}\r\n    \\caption[Compatibility and incompatibility of\r\n    fragments]{Compatibility and incompatibility of\r\n      fragments. End-reads are solid lines, unknown sequences within\r\n      fragments are shown by dotted lines and implied introns are\r\n      dashed lines. The reads in (a) are compatible, whereas the\r\n      fragments in (b) are incompatible. The fragments in (c) are\r\n      nested. Fragment $x_4$ in (d) is uncertain, because $y_4$ and\r\n      $y_5$ are incompatible with each other.}\r\n\\end{figure}\r\n\r\nBefore constructing a partial order, fragments are extended to include\r\ntheir nested fragments and uncertain fragments are discarded. These discarded fragments\r\nare used in the abundance estimation. In theory, this may result in\r\nsuboptimal (i.e. non-minimal assemblies) but we determined empirically\r\nthat after assembly uncertain fragments are almost always consistent\r\nwith one of the transcripts. When they are not, there was no\r\ncompletely tiled transcript that contained them. Thus, we employ a\r\nheuristic that substantially speeds up the program, and that works\r\nin practice.\r\n\r\nA partial order $P$ is then constructed from the remaining fragments\r\nby declaring that $x \\leq y$ whenever the fragment corresponding to\r\n$x$ begins at, or before, the location of the fragment corresponding\r\nto $y$ and $x$ and $y$ are compatible. In what follows we identify $P$\r\nwith its Hasse diagram (or covering relation), equivalently a directed\r\nacyclic graph (DAG) that is the transitive reduction. \r\n\r\n\\begin{prop}\r\n$P$ is a partial order.\r\n\\end{prop}\r\n{\\bf Proof}: The fragments can be totally ordered according to the locations where they begin. It therefore suffices to check that if $x,y,z$ are fragments with $x$ compatible with $y$ and $y$ compatible with $z$ then $x$ is compatible with $z$. Since $x$ is not uncertain, it must be either compatible or incompatible with $z$. The latter case can occur only if $x$ and/or $z$ contain implied introns that overlap and are not identical. Since $y$ is not nested within $z$ and $x$ is not nested within $y$, it must be that $y$ contains an implied intron that is not identical with an implied intron in either $x$ or $z$. Therefore $y$ cannot be compatible with both $x$ and $z$. \\qed\r\n\r\n\\subsection{Assembling a parsimonious set of transcripts}\r\n\r\nIn order to assemble a set of transcripts, {\\tt Cufflinks} finds a\r\n(minimum) partition of $P$ into chains (see Definition\r\n\\ref{def:po}). A partition of $P$ into chains yields an assembly\r\nbecause every chain is a totally ordered set of compatible fragments\r\n$x_1,\\ldots,x_l$ and therefore there is a set of overlapping fragments\r\nthat connects them. By Dilworth's theorem (Theorem \\ref{thm:Dilworth}), the problem of finding a minimum partition $P$ into chains is equivalent to finding a maximum antichain in $P$ (an antichain is a set of mutually incompatible fragments). Subsequently, by Theorem \\ref{thm:dilko}, the problem of finding a maximum antichain in $P$ can be reduced to finding a maximum matching in a certain bipartite graph that emerges naturally in deducing Dilworth's theorem from K\\\"{o}nig's theorem \\ref{thm:konig}. \r\nWe call the key bipartite graph the ``reachability'' graph. It is the transitive closure of the DAG, i.e. it is the graph \r\nwhere each fragment $x$ has nodes $L_x$ and $R_x$ in the left and\r\nright partitions of the reachability graph respectively, and where there is an edge between $L_x$ and $R_y$ when $x \\leq y$ in $P$. The maximum matching problem is a classic problem that admits a polynomial time algorithm. The Hopcroft-Karp algorithm \\cite{Hopcroft1973} has a run time of $O(\\sqrt{V}E)$ where in our case $V$ is the number of fragments and $E$ depends on the extent of overlap, but is bounded by a constant times the coverage depth. We note that our parsimony approach to assembly therefore has a better complexity than the $O(V^3)$ PASA algorithm \\cite{Haas2003}. \r\n\r\nThe minimum cardinality chain decomposition computed using the approach above may not be unique.\r\nFor example, a locus may contain two putative distinct initial exons (defined by overlapping incompatible fragments), and one\r\nof two distinct terminal and a constitutive exon in between that is longer than any\r\nread or insert in the RNA-Seq experiment. In such a case, the parsimonious assembly will consist of two transcripts, but there are four possible solutions that are all minimal. In order to ``phase'' distant exons, we leverage the fact that abundance inhomogeneities can link distant exons via their coverage. We therefore weight the edges of the bipartite reachability graph based on the percent-spliced-in metric introduced by\r\nWang \\emph{et al.} in \\cite{Wang2008}. In our setting, the percent-spliced-in\r\n$\\psi_x$ for an alignment $x$ is computed by counting the alignments\r\noverlapping $x$ in the genome that are compatible with $x$ and dividing by the\r\ntotal number of alignments that overlap $x$, and normalizing for the length of\r\nthe $x$. The cost $C(y,z)$ assigned to an edge between alignments $y$ and $z$ reflects\r\nthe belief that they originate from different transcripts:\r\n\r\n\r\n\\begin{equation}\r\n    C(y,z) = -\\log(1 - |\\psi_y - \\psi_z|).\r\n    \\label{eq:match_cost} \r\n\\end{equation}\r\n\r\nRather than using the Hopcroft-Karp algorithm,  a modified version of the {\\tt\r\nLEMON} \\cite{LEMON} and {\\tt Boost} \\cite{Boost} graph libraries are used to\r\ncompute a {\\em min-cost} maximum cardinality matching on the bipartite compatibility\r\ngraph. Even with the presence of weighted edges, our algorithm is\r\nvery fast. The best known algorithm for weighted matching is $O(V^2logV+VE)$.\r\n\r\nBecause we isolated total RNA, we\r\nexpected that a small fraction of our reads would come from the intronic\r\nregions of incompletely processed primary transcripts. Moreover, transcribed\r\nrepetitive elements and low-complexity sequence result in ``shadow''\r\ntransfrags that we wished to discard as artifacts. Thus, {\\tt Cufflinks}\r\nheuristically identifies artifact transfrags and suppresses them in its\r\noutput. We also filter extremely low-abundance minor isoforms of alternatively\r\nspliced genes, using the model described in Section \\ref {abundances} as a\r\nmeans of reducing the variance of estimates for more abundant transcripts. A\r\ntranscript $x$ meeting any of the following criteria is suppressed:\r\n\r\n\\begin{enumerate}\r\n    \\item $x$ aligns to the genome entirely within an intronic region of the alignment for a transcript $y$, and the abundance of $x$ is less than 15\\% of $y$'s abundance.\r\n    \\item $x$ is supported by only a single fragment alignment to the genome.\r\n    \\item More than 75\\% of the fragment alignments supporting $x$, are mappable to multiple genomic loci.\r\n    \\item $x$ is an isoform of an alternatively spliced gene, and has an estimated abundance less than 5\\% of the major isoform of the gene. \r\n\\end{enumerate}\r\n\r\nPrior to transcript assembly, {\\tt Cufflinks} also filters out some of the alignments\r\nfor fragments that are likely to originate from incompletely spliced nuclear\r\nRNA, as these can reduce the accuracy abundance estimates for fully spliced\r\nmRNAs. These filters and the output filters above are detailed in the source\r\nfile \\verb!filters.cpp! of the source code for {\\tt Cufflinks}.\r\n\r\nIn the overview of this Section, we mentioned that our assembly algorithm has the property that the resulting models are identifiable. This is a convenient property that emerges naturally from the parsimony criterion for a ``minimal explanation'' of the fragment alignments. Formally, it is a corollary of Dilworth's theorem:\r\n\r\n\\begin{prop}\r\nThe assembly produced by the {\\tt Cufflinks} algorithm always results in an\r\nidentifiable RNA-Seq model.\r\n\\end{prop}\r\n{\\bf Proof}:  By Dilworth's theorem, the minimum chain decomposition (assembly)\r\nwe obtain has the same size as the maximum antichain in the partially\r\nordered set  we\r\nconstruct from the reads. An antichain consists of reads that are\r\npairwise incompatible, and therefore those reads must form a\r\npermutation sub-matrix in the fragment-transcript matrix $A_{R,T}$ with columns corresponding to the transcripts in a locus, and with rows corresponding to the fragments in the antichain. The matrix $A_{R,T}$ therefore contains permutation sub-matrices that together span all the columns, and the matrix is full-rank.\r\n\r\n\\subsection{Assessment of assembly quality}\r\n\r\nTo compare {\\tt Cufflinks} transfrags against annotated transcriptomes, and\r\nalso to find transfrags common to multiple assemblies, we developed a tool\r\ncalled {\\tt Cuffcompare} that builds structural equivalence classes of\r\ntranscripts. We ran {\\tt Cuffcompare} on each the assembly from each time point against the\r\ncombined annotated transcriptomes of the {UCSC known genes}, {\\tt Ensembl},\r\nand {\\tt Vega}. Because of the stochastic nature of sequencing, \\emph{ab\r\ninitio} assembly of the same transcript in two different samples may result in\r\ntransfrags of slightly different lengths. A {\\tt Cufflinks} transfrag was\r\nconsidered a complete match when there was a transcript with an identical\r\nchain of introns in the combined annotation.\r\n\r\nWhen no complete match is found between a {\\tt Cufflinks} transfrag and the\r\ntranscripts in the combined annotation, {\\tt Cuffcompare} determines and reports if\r\nanother substantial relationship exists with any of the annotation\r\ntranscripts that can be found in or around the same genomic locus. For\r\nexample, when all the introns of a transfrag match perfectly a part of the\r\nintron chain (sub-chain) of an annotation transcript, a ``containment''\r\nrelationship is reported. For single-exon transfrags, containment is also\r\nreported when the exon appears fully overlapped by any of the exons of an\r\nannotation transcript. If there is no perfect match for the intron chain of a\r\ntransfrag but only some exons overlap and there is at least one intron-exon\r\njunction match, {\\tt Cuffcompare} classifies the transfrag as a putative ``novel''\r\nisoform of an annotated gene. When a transfrag is unspliced (single-exon) and\r\nit overlaps the intronic genomic space of a reference annotation transcript,\r\nthe transfrag is classified as potential pre-mRNA fragment. Finally, when no\r\nother relationship is found between a {\\tt Cufflinks} transfrag and an\r\nannotation transcript, {\\tt Cuffcompare} can check the repeat content of the\r\ntransfrag's genomic region (assuming the soft-masked genomic sequence was also\r\nprovided) and it would classify the transfrag as ``repeat'' if most of its\r\nbases are found to be repeat-masked.\r\n\r\nWhen provided multiple time point assemblies, {\\tt Cuffcompare} matches transcripts\r\n\r\n\\subsubsection{Testing for changes in absolute expression} \r\n\r\nBetween any two consecutive time points, we tested whether a transcript was\r\nsignificantly (after FDR control \\cite{Benjamini1995}) up or down regulated with respect to the\r\nnull hypothesis of no change, with variability in expression due solely to the\r\nuncertainties resulting from our abundance estimation procedure. This was done\r\nusing the following testing procedure for absolute differential expression:\r\n\r\nWe employed the standard method used in microarray-based expression analysis\r\nand proposed for RNA-Seq in \\cite{Bullard2010}, which is to compute the\r\nlogarithm of the ratio of intensities (in our case FPKM), and to then use the\r\ndelta method to estimate the variance of the log odds. We describe this for\r\ntesting differential expression of individual transcripts and also groups of\r\ntranscripts (e.g. grouped by TSS).\r\n\r\nWe recall that the MLE FPKM for a transcript $t$ in a locus $g$ is given by \r\n\\begin{equation}\r\n\\frac{10^9X_g\\hat{\\gamma}_t}{\\tilde{l}(t)M}.\r\n\\end{equation}\r\nGiven two different experiments resulting in $X^a_g,M^a$ and $X^b_g,M^b$ respectively, as well as $\\hat{\\gamma}^a_t$ and $\\hat{\\gamma}^b_t$, we would like to test the significance of departures from unity of the ratio of MLE FPKMS, i.e. \r\n\\begin{eqnarray}\r\n& & \\left(\\frac{10^9X^a_g\\hat{\\gamma}^a_t}{\\tilde{l}(t)M^a}\\right) / \\left(\\frac{10^9X^b_g\\hat{\\gamma}^b_t}{\\tilde{l}(t)M^b}\\right)\\\\\r\n& = & \\frac{X_g^a\\hat{\\gamma}^a_tM^b}{X_g^b \\hat{\\gamma}^b_tM^a}.\r\n\\end{eqnarray}\r\n\r\nThis can be turned into a test statistic that is approximately normal by\r\ntaking the logarithm, and normalizing by the variance. We recall that using\r\nthe delta method, if $X$ is a random variable then $Var[log(X)] \\approx\r\n\\frac{Var[X]}{E[X]^2}$.\r\n\r\nTherefore, our test statistic is \r\n\\begin{equation}\r\n\\frac{log(X^a_g)+log(\\hat{\\gamma}^a_t)+log(M^b)-log(X^b_g)-log(\\hat{\\gamma}^b_t)-log(M^a)}\r\n{ \\sqrt{\\frac{\\left( \\Psi^{g,a}_{t,t}(1+X^a_{g}) + (\\hat{\\gamma}^a_t)^2\\right)}{X^a_g \\left(\\hat{\\gamma}^a_t \\right)^2}+\r\n\\frac{\\left( \\Psi^{g,b}_{t,t}(1+X^b_{g}) + (\\hat{\\gamma}^b_t)^2\\right)}{X^b_{g}\\left(  \\hat{\\gamma}^b_t\\right)^2}    }  }.\r\n\\end{equation}\r\n\r\nIn order to test for differential expression of a group of transcripts, we\r\nreplace the numerator and denominator above by those from Equations\r\n(\\ref{eq:expectTSS}) and (\\ref{eq:varTSS}).\r\n\r\nIt is has been noted that the power of differential expression tests in RNA-Seq depend on the length of the transcripts being tested, because longer transcripts accumulate more reads \\cite{Oshlack2009}. This means that the results we report are biased towards discovering longer differentially expressed transcripts and genes.\r\n\r\n\\subsection{Quantifying transcriptional and post-transcriptional overloading}\r\n\r\nIn order to infer the extent of differential promoter usage, we\r\ndecided to measure changes in relative abundances of primary\r\ntranscripts of single genes. Similarly, we investigated changes in\r\nrelative abundances of transcripts grouped by TSS in order to infer\r\ndifferential splicing.  These inferences required two ingredients: \r\n\\begin{enumerate}\r\n\\item A metric on probability distributions (derived from relative\r\n  abundances).\r\n\\item A test statistic for assessing significant changes in\r\n  differential promoter usage and splicing as measured using the\r\n  metric referred to above. \r\n\\end{enumerate}\r\n\r\nIn order to address the first requirement, namely a metric on\r\nprobability distributions, we turned to an entropy-based metric. This\r\nwas motivated by the methods in \\cite{Ritchie2008} where tests for\r\ndifferences in relative isoform abundances were performed to\r\ndistinguish cancer cells from normal cells. We extend\r\nthis approach to be able to test for relative isoform abundance changes among multiple\r\nexperiments in RNA-Seq.\r\n\r\n\\begin{defn}[Entropy]\r\nThe entropy of a discrete probability distribution\r\n$p=(p_1,\\ldots,p_n)$ ($0 \\leq p_i \\leq 1$ and $\\sum_{i=1}^n p_i = 1$) is \r\n\\begin{equation}\r\nH(p) = -\\sum_{i=1}^n p_i log p_i.\r\n\\end{equation}\r\nIf $p_i=0$ for some $i$ the value of $p_i log p_i$ is taken to be $0$.\r\n\\end{defn}\r\n\\begin{defn}[The Jensen-Shannon divergence]\r\nThe Jensen-Shannon divergence of $m$ discrete probability distributions $p^1,\\ldots,p^m$ is defined to be:\r\n\\begin{equation}\r\nJS(p^1,\\ldots,p^m) = H\\left(\\frac{p^1 + \\cdots + p^m}{m}\\right) - \\frac{\\sum_{j=1}^m H(p^j)}{m}.\r\n\\end{equation}\r\n\r\nIn other words, the Jensen-Shannon divergence of a set of probability\r\ndistributions is the entropy of their average minus the average of their\r\nentropies. \\end{defn}\r\n\r\nIn the case where $m=2$, we remark that the Jensen-Shannon divergence can also\r\nbe described in terms of the Kullback-Leibler divergence of two discrete\r\nprobability distributions. If we denote Kullback-Leibler divergence by\r\n\r\n\\begin{equation}\r\nD(p^1\\|p^2) = \\sum_i p^1_i log \\frac{p^1_i}{p^2_i},\r\n\\end{equation}\r\nthen\r\n\\begin{equation}\r\nJS(p^1,p^2) = \\frac{1}{2}D(p^1\\|m)+\\frac{1}{2}D(p^2\\|m)\r\n\\end{equation}\r\nwhere $m=\\frac{1}{2}(p^1+p^2)$. In other words the Jensen-Shannon\r\ndivergence is a symmetrized variant of the Kullback-Leibler divergence.\r\n\r\nThe Jensen-Shannon divergence has a number of useful properties: for\r\nexample it is symmetric and non-negative. However it is {\\em not} a\r\nmetric. The following theorem shows how to construct a metric\r\nfrom the Jensen-Shannon divergence:\r\n\r\n\\begin{thm}[Fuglede and Tops{\\o}e 2004 \\cite{Fuglede2004}]\r\nThe square root of the Jensen-Shannon divergence is a metric.\r\n\\end{thm}\r\n\r\nThe proof of this result is based on a harmonic analysis argument that is the basis for\r\nthe remark in the main paper that ``transcript abundances move in time along a\r\nlogarithmic spiral in Hilbert space''.  We therefore call the square root of the Jensen-Shannon divergence the {\\em Jensen-Shannon metric}. We employed this metric in\r\norder to quantify relative changes in expression in (groups of) transcripts.\r\n\r\nIn order to test for significance, we introduce a bit of notation.\r\nSuppose that $S$ is a collection of transcripts (for example, they may\r\n share a common TSS). We define\r\n\\begin{equation}\r\n\\kappa_t = \\frac{ \\frac{\\gamma_t}{\\tilde{l}(t)}}{\\sum_{u \\in S} \\frac{\\gamma_u}{\\tilde{l}(u)}}\r\n\\end{equation}\r\nto be the proportion of transcript $t$ among all the transcripts in a\r\ngroup $S$. We let \r\n$Z=\\sum_{u \\in S} \\hat{\\gamma}_u / \\tilde{l}(u)$ so that $\\hat{\\kappa}_t = \\frac{\\gamma_t}{\\tilde{l}(t)Z}$. We therefore have that\r\n\\begin{eqnarray}\r\n\\label{eq:variancekappa1}\r\nVar[\\hat{\\kappa}_t] & =  &\\frac{Var[\\hat{\\gamma}_t]}{\\tilde{l}(t)^2Z^2}, \\\\\r\nCov[\\hat{\\kappa}_t,\\hat{\\kappa}_u] & =  & \\frac{Cov[\\hat{\\gamma}_t,\\hat{\\gamma}_u]}{\\tilde{l}(t)\\tilde{l}(u)Z^2}.\\label{eq:variancekappa2}\r\n\\end{eqnarray}\r\n\r\nOur test statistic for divergent relative expression was the\r\nJensen-Shannon metric. The test could be applied to multiple time\r\npoints simultaneously, but we focused on pairwise tests (involving\r\nconsecutive time points). Under the null hypothesis of no change in\r\nrelative expression, the Jensen-Shannon metric should be\r\nzero. We tested for this using a one-sided $t$-test, based on an\r\nasymptotic derivation of the distribution of the Jensen-Shannon metric\r\nunder the null hypothesis. This asymptotic distribution is normal by applying the delta method approximation,\r\nwhich involves computing the linear component of the Taylor expansion of the\r\nvariance of $\\sqrt{JS}$.\r\n\r\nIn order to simplify notation, we let $f(p^1,\\ldots,p^m)$ be the\r\nJensen-Shannon metric for $m$ probability distributions $p^1,\\ldots,p^m$.\r\n\r\n\\begin{lemma}\r\nThe partial derivatives of the Jensen-Shannon metric are give by\r\n\\begin{equation}\r\n\\frac{\\partial f}{\\partial p^k_l} = \\frac{1}{2m\\sqrt{f(p^1,\\ldots,p^m)}} log \\left( \\frac{p^k_l}{\\frac{1}{m} \\sum_{j=1}^m p_l^j} \\right).\r\n\\end{equation}\r\n\\end{lemma}\r\n\r\nLet $\\hat{\\kappa}^1,\\ldots,\\hat{\\kappa}^m$ denote $m$ probability\r\ndistributions on the set of transcripts $S$, for example the MLE for the transcript abundances in a time course. Then from the delta method we\r\nhave that $\\sqrt{JS(\\hat{\\kappa}^1,\\ldots,\\hat{\\kappa}^m)}$ is approximately normally\r\ndistributed with variance given by\r\n\r\n\\begin{equation}\r\nVar[\\sqrt{JS(\\hat{\\kappa}^1,\\ldots,\\hat{\\kappa}^m)}] \\approx (\\bigtriangledown f)^T \\Sigma (\\bigtriangledown f),\r\n\\end{equation}\r\n\r\nwhere $\\Sigma$ is the variance-covariance matrix for the\r\n$\\kappa^1,\\ldots,\\kappa^m$, i.e., it is a block diagonal matrix where the\r\n$i$th block is the variance-covariance matrix for the $\\kappa^i_t$ given by\r\nEquations (\\ref{eq:variancekappa1},\\ref{eq:variancekappa2}).\r\n\r\n\r\nThere are two biologically meaningful groupings of transcripts whose\r\nrelative abundances are interesting to track in a\r\ntime course. Transcripts that share a TSS are likely to be regulated by\r\nthe same promoter, and therefore tracking the change in relative\r\nabundances of groups of transcripts sharing a TSS may reveal how\r\ntranscriptional regulation is affecting expression over\r\ntime. Similarly, transcripts that share a TSS and exhibit changes in\r\nexpression relative to each other are likely to be affected by\r\nsplicing or other post-transcriptional regulation. We therefore\r\ngrouped transcripts by TSS and compared relative abundance changes\r\nwithin and between groups. \r\n\r\nWe define ``overloading'' to be a significant change in relative\r\nabundances for a set of transcripts (as determined by the Jensen-Shannon metric, see below). The term is intended to generalize the simple notion of\r\n``isoform switching'' that is well-defined in the case of two\r\ntranscripts, to multiple transcripts. It is complementary to absolute\r\ndifferential changes in expression: the overall expression of a gene\r\nmay remain constant while individual transcripts change drastically in\r\nrelative abundances resulting in overloading. The term is borrowed from\r\ncomputer science, where in some statically-typed programming\r\nlanguages, a function may be used in multiple, specialized instances\r\nvia ``method overloading''. \r\n\r\nWe tested for overloaded genes by performing a one-sided $t$-test based on the asymptotics of the Jensen-Shannon metric under the null hypothesis of no change in relative abundnaces of isoforms (either grouped by shared TSS for for post-transcriptional overloading, or by comparison of groups of isoforms with shared TSS for transcriptional overloading). Type I errors were controlled with the Benjamini-Hochberg \\cite{Benjamini1995} correction for multiple testing. \r\n A selection of overloaded genes are displayed in Supplemental Figs. \\ref{splice_overloaded} and \\ref{promoter_overloaded}.\r\n\r\n\\newpage\r\n\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/splice_overloaded}\r\n    \\caption[Selected genes with post-transcriptional\r\n    overloading]{Selected genes with post-transcriptional\r\n      overloading. Trajectories indicate the expression of individual\r\n      isoforms in FPKM ($y$ axis) over time in hours ($x$\r\n      axis). Dashed isoforms have not been previously\r\n      annotated. Isoform trajectories are colored by TSS, so isoforms\r\n      with the same color presumably share a common promoter and are\r\n      processed from the same primary transcript. It is evident that\r\n      total gene expression may remain constant during isoforms\r\n      switching (Eya3) while in other cases changes in relative\r\n      abundance are accompanied by changes in absolute expression. \r\nThe Jensen-Shannon metric generalizes the notion of ``isoform\r\nswitching'' and is useful in cases with multiple isoforms\r\n(e.g. Ddx17).    \r\n  \\label{splice_overloaded}}\r\n\\end{figure}\r\n\r\n\\begin{figure}[!ht] \r\n    \\includegraphics{pdfs/promoter_overloaded}\r\n    \\caption[Selected genes with transcriptional overloading]{Selected\r\n      genes with transcriptional overloading. Trajectories indicate\r\n      the expression of individual isoforms in FPKM (y axis) over time\r\n      in hours (x axis). Dashed isoforms have not been previously\r\n      annotated. Isoform trajectories are colored by TSS, so that\r\n      isoforms with different colors presumably vary in their promoter\r\n      and are processed from different primary transcripts.  \\label{promoter_overloaded}}\r\n\\end{figure}\r\n\r\nWe can visualize overloading and expression dynamics with a plot that\r\nsuperimposes transcriptional and post-transcriptional overloading and\r\ngene-level expression over the time course. We refer to these as\r\n``Minard plots'', after Charles Joseph Minard's famous depiction\r\nof the advance and retreat of\r\nNapoleon's armies in the campaign against Russia in 1812\r\n\\cite{Tufte2001}. Minard made use of multiple visual cues to display\r\nnumerous varying quantities in one diagram. An example of a Minard\r\nplot for the gene\r\nMyc is shown in Figure 3c, and others are given in Appendix B. The dotted line indicates gene-level FPKM, with measured\r\nFPKM indicated by black circles. Grey circles indicate the arithmetic mean of\r\ngene-level FPKM between consecutive measured time points, interpolating FPKM\r\nat intermediate time points. The total gene expression overloading is\r\nvisualized as a swatch centered around the interpolated expression curve.\r\nThe width of the swatch encodes the amount of expression overloading between\r\nsuccessive time points. The color of the swatch indicates the relative\r\ncontributions of transcriptional and post-transcriptional expression\r\noverloading.\r\n\r\nSome genes, such as tropomyosin I and II, feature a single primary\r\ntranscript, and so all overloading is by definition post-transcriptional.\r\nOthers, like Fhl3, have two primary transcripts, but only a single isoform\r\narises from each, so all overloading is transcriptional. Genes with multiple\r\nprimary transcripts, one or more of which are alternatively spliced, such as\r\nMyc or RTN4, display both forms.\r\n\r\n\r\n\\subsection{The {\\tt Cufflinks} software}\r\n\r\nThe transcript assembly and abundance estimation algorithms are implemented in\r\nfreely available open source software called {\\tt Cufflinks} that is available\r\nfrom \\newline {\\tt http://cufflinks.cbcb.umd.edu/} \\newline Furthermore\r\nmethods for comparing annotations across time points, and for performing the\r\ndifferential expression, promoter usage and splicing tests are implemented in\r\nthe companion programs {\\tt Cuffdiff} and {\\tt Cuffcompare}. Instructions on\r\nhow to install and run the software are provided on the website.\r\n\r\nThe input to {\\tt Cufflinks} consists of fragment alignments in the SAM format\r\n\\cite{Li2009a}. These may consist of either single fragment alignments, or alignments of mate-pairs (paired-end reads produce better assemblies and more accurate abundance estimates than single reads). {\\tt Cufflinks} will assemble the transcripts using the\r\nalgorithm in Section \\ref{sec:assembly}, and transcript abundances will be\r\nestimated using the model in Section \\ref{sec:abundances}. Transcript\r\ncoordinates and abundances are reported in the Gene Transfer Format (GTF).\r\nUser supplied annotations may be provided to {\\tt Cufflinks} (optional input) in\r\nwhich case they form the basis for the transcript abundance estimation.\r\n\r\nSome of the algorithms here rely on sufficient depth of sequencing in order to\r\nproduce reliable output. {\\tt Cufflinks} determines that depth is sufficient where\r\npossible to check that required assumptions hold. For example, in loci where one\r\nor more isoforms have extremely low relative expression, the observed Fisher\r\nInformation Matrix may not be positive definite after rounding errors. In this\r\ncase, it is not possible to produce a reliable variance-covariance matrix for\r\nisoform fragment abundances. {\\tt Cufflinks} will report a numerical\r\nexception in this and similar cases. When an exception is reported, the\r\nconfidence intervals for the isoforms' abundances will be set from 0\r\nFPKM to the FPKM for the whole gene. If such an exception is generated during\r\na {\\tt Cuffdiff} run, no differential analysis involving the problematic\r\nsample will be performed on that locus. \r\n\\newpage \r\n\\section{Appendix A: Lemmas and Theorems}\r\n\r\nThe following elementary/classical results are required for our methods and we include them so that the supplement is self-contained.\r\n\r\n\\begin{lemma}\r\n\\label{lemma:varsum}\r\nLet $X_1,\\ldots,X_n$ be random variables and $a_1,\\ldots,a_n$ real numbers with $Y=\\sum_{i=1}^na_iX_i$. Then\r\n\\begin{equation}\r\nVar[Y] = \\sum_{i=1}^n a_i^2Var[X_i]+2\\sum_{i<j} a_ia_j Cov[X_i,X_j].\r\n\\end{equation}\r\n\\end{lemma}\r\n\\begin{lemma}[Taylor Series]\r\nIf $X$ and $Y$ are random variables then\r\n\\begin{eqnarray}\r\n  Var[f(X,Y)] & \\approx & \\left(\\frac{\\partial f}{\\partial X}(E[X],E[Y])\\right)^2Var[X] \\nonumber \\\\ & &+2\\frac{\\partial f}{\\partial X}(E[X],E[Y])\\frac{\\partial f}{\\partial Y}(E[X],E[Y])Cov[X,Y] \\nonumber \\\\ & & +\\left( \\frac{\\partial f}{\\partial Y}(E[X],E[Y])\\right)^2 Var[Y].\r\n\\end{eqnarray}\r\n\\end{lemma}\r\n\\begin{cor}\r\nIf $X$ and $Y$ are independent then\r\n\\begin{eqnarray}\r\n  Var\\left[log\\left(\\frac{X}{Y}\\right)\\right] & \\approx & \\frac{V[X]}{E[X]^2} + \\frac{V[Y]}{E[Y]^2}.\r\n\\end{eqnarray}\r\n\\end{cor}\r\n\\begin{cor}\r\n\\label{lemma:varproduct}\r\nIf $X$ and $Y$ are independent random variables then\r\n\\begin{equation}\r\nVar[XY] = Var[X]Var[Y]+E[X]^2Var[Y]+E[Y]^2Var[X].\r\n\\end{equation}\r\n\\end{cor}\r\n\r\nThe above result is exact using the 2nd order Taylor expansion (higher\r\nderivatives vanish).\r\n\r\n\\begin{lemma}[\\cite{Li2009b}]\r\n\\label{lemma:readstoprobs}\r\nLet $a_1,\\ldots,a_n,w_1,\\ldots,w_n$ be real numbers satisfying: $w_i \\neq 0$ and $0 \\leq a_i \\leq 1$ for all $i$, $\\sum_{i=1}^n a_i = 1$ and $\\sum_{i=1}^na_iw_i \\neq 0$.  Let \r\n$ b_j = \\frac{a_jw_j}{\\sum_{i=1}^n a_iw_i}$. Then $a_j = \\frac{b_j\\frac{1}{w_j}}{\\sum_{i=1}^n b_i\\frac{1}{w_i}}$.\r\n\\end{lemma}\r\n{\\bf Proof}: \\begin{eqnarray}\r\nb_j & =  & \\frac{a_jw_j}{\\sum_{i=1}^n a_iw_i} \\\\\r\n\\Rightarrow \\,  \\sum_{k=1}^n \\frac{b_k}{w_k} & = &   \\sum_{k=1}^n \\frac{a_k}{\\sum_{i=1}^na_iw_i}\\\\\r\n&  = &  \\frac{1}{\\sum_{i=1}^n a_iw_i}\\\\\r\n& = & \\frac{b_j}{a_jw_j}\\\\\r\n \\Rightarrow \\,  a_j  & =  & \\frac{b_j\\frac{1}{w_j}}{\\sum_{i=1}^n b_i \\frac{1}{w_i}}.\r\n\\end{eqnarray} \\qed\r\n\\begin{prop}[\\cite{ASCB2005}]\r\n\\label{prop:linearmodel}\r\nLet $f_i(\\theta) = \\sum_{j=1}^d a_{ij}\\theta_j + b_i$ ($1 \\leq i \\leq\r\nm$) describe a linear statistical model with $a_{ij} \\geq$ for all\r\n$i,j$.  That is, $\\sum_{i=1}^m f_i(\\theta) = 1$. If $u_i \\geq 0$ for\r\nall $i$ then the log likelihood function\r\n\\begin{equation}\r\nl(\\theta) = \\sum_{i=1}^m u_i log(f_i(\\theta))\r\n\\end{equation}\r\nis concave.\r\n\\end{prop}\r\n{\\bf Proof}: It is easy to see that \r\n\\begin{equation}\r\n\\left( \\frac{\\partial^2 l}{\\partial \\theta_j \\partial \\theta_k}  \\right)  = -A^Tdiag\\left( \\frac{u_1}{f_1(\\theta)^2},\\ldots,\\frac{u_m}{f_m(\\theta)^2}\\right) A,\r\n\\end{equation}\r\nwhere $A$ is the $m \\times d$ matrix whose entry in row $i$ and column\r\n$j$ equals $a_{ij}$. Therefore the Hessian is a symmetric matrix with\r\nnon-positive eigenvalues, and is therefore negative semi-definite.\r\n\\qed\r\n\r\n\\begin{defn}\r\n\\label{def:po}\r\nA partially ordered set is a set $S$ with a binary relation $\\leq$\r\nsatisfying:\r\n\\begin{enumerate}\r\n\\item $x \\leq x$ for all $x \\in S$,\r\n\\item If $x \\leq y$ and $y \\leq z$ then $x \\leq z$,\r\n\\item If $x \\leq y$ and $y \\leq x$ then $x=y$.\r\n\\end{enumerate}\r\nA {\\em chain} is a set of elements in $C \\subseteq S$ such that for every\r\n$x,y \\in C$ either $x \\leq y$ or $y \\leq x$. An {\\em antichain} is a set of\r\nelements that are pairwise incompatible.\r\n\\end{defn}\r\nPartially ordered sets are equivalent to directed acyclic graphs (DAGs). The following min-max theorems relate chain partitions to antichains and are special cases of linear-programming duality. More details and complete proofs can be found in \\cite{Lovasz2009}.\r\n\r\n\\begin{thm}[Dilworth's theorem]\r\n\\label{thm:Dilworth}\r\nLet $P$ be a finite partially ordered set. The maximum number of elements in any antichain of $P$ equals the minimum number of chains in any partition of $P$ into chains.\r\n\\end{thm}\r\n\\begin{thm}[K\\\"{o}nig's theorem]\r\n\\label{thm:konig}\r\nIn a bipartite graph, the number of edges in a maximum matching equals\r\nthe number of vertices in a minimum vertex cover.\r\n\\end{thm}\r\n\\begin{thm}\r\n\\label{thm:dilko}\r\nDilworth's theorem is equivalent to K\\\"{o}nig's theorem.\r\n\\end{thm}\r\n{\\bf Proof}: We first show that Dilworth's theorem follows from\r\nK\\\"{o}nig's theorem. Let $P$ be a partially ordered set with $n$\r\nelements. We define a bipartite graph $G=(U,V,E)$ where\r\n$U=V=P$, i.e. each partition in the bipartite graph is equally to\r\n$P$. Two nodes $u,v$ form an edge $(u,v) \\in E$ in the graph $G$ iff\r\n$u<v$ in $P$. By K\\\"{o}nig's theorem there exist both a matching $M$ and a\r\na vertex cover $C$ in $G$ of the same cardinality. Let $T \\subset\r\nS$ be the set of elements not contained in $C$. Note that $T$ is an\r\nantichain in $P$. We now form a partition $W$ of $P$ into chains by declaring $u$ and\r\n$v$ to be in the same chain whenever there is an edge $(u,v) \\in\r\nM$. Since $C$ and $M$ have the same size, it follows that $T$ and $W$\r\nhave the same size.\r\n\r\nTo deduce K\\\"{o}nig's theorem from Dilworth's theorem, we begin with a\r\nbipartite graph $G=(U,V,E)$ and form a partial order $P$ on the\r\nvertices of $G$ by defining $u<v$ when $u \\in U, v \\in V$ and $(u,v)\r\n\\in E$. By Dilworth's theorem, there exists an antichain of $P$ and a\r\npartition into chains of the same size. The non-trivial chains in $P$\r\nform a matching in the graph. Similarly, the complement of the\r\nvertices corresponding to the anti-chain in $P$ is a vertex cover of\r\n$G$ with the same cardinality as the matching.  \\qed\r\n\r\n\\begin{figure}[!ht] \r\n    \\includegraphics[scale=0.8]{pdfs/Dilworth_Konig}\r\n\r\n%\\caption[Equivalence of Dilworth's and K\\\"{o}nig's theorems]{\r\n\\end{figure}\r\nThe equivalence of Dilworth's and K\\\"{o}nig's theorems is depicted above. The\r\n      partially ordered set with 8 elements on the left is partitioned into 3\r\n      chains. This is the size of a minimum partition into chains, and\r\n    is equal to the maximum size of an antichain (Dilworth's\r\n    theorem). The antichain is shown with double circles. On the\r\n    right, the reachability graph constructed from the partially\r\n    ordered set on the left is shown. The maximum matching\r\n    corresponding to the chain partition consists of 5 edges and is equal in size to the\r\n    number of vertices in a minimum vertex cover (K\\\"{o}nig's\r\n    theorem). The vertex cover is shown with double circles. Note that\r\n    8=3+5.\r\n\r\n\r\n\\newpage\r\n\\bibliographystyle{amsplain}\r\n\\bibliography{cufflinks}\r\n\\end{document}\r\n\r\n% long read length is required for uniquely determining genomic origin of fragments, but its fragment length that is critical for assignment of fragments to transcripts.\r\n% The length of a set of transcripts depends on their abundances\r\n% single read sequencing prevents the correct normalization for fragment sizes in the length.\r\n"
  },
  {
    "path": "doc/algorithm/algorithm.bib",
    "content": "%% This BibTeX bibliography file in UTF-8 format was created using Papers.\n%% http://mekentosj.com/papers/\n\n@article{Eriksson:2008p1143,\nauthor = {Nicholas Eriksson and Lior Pachter and Yumi Mitsuya and Soo-Yon Rhee and Chunlin Wang and Baback Gharizadeh and Mostafa Ronaghi and Robert W Shafer and Niko Beerenwinkel and Glenn Tesler}, \njournal = {PLoS Computational Biology},\ntitle = {Viral Population Estimation Using Pyrosequencing},\nnumber = {5},\nvolume = {4},\nyear = {2008},\nmonth = {May},\ndate-added = {2009-03-08 12:34:19 -0700},\ndate-modified = {2009-03-08 12:34:20 -0700},\n}\n\n@article{Haas:2003p810,\nauthor = {B. J Haas}, \njournal = {Nucleic Acids Research},\ntitle = {Improving the Arabidopsis genome annotation using maximal transcript alignment assemblies},\nnumber = {19},\npages = {5654--5666},\nvolume = {31},\nyear = {2003},\nmonth = {Oct},\ndate-added = {2008-08-15 11:17:58 -0700},\ndate-modified = {2008-08-15 11:17:59 -0700},\ndoi = {10.1093/nar/gkg770},\nlocal-url = {file://localhost/Users/cole/Data/Documents/Papers/2003/Haas/Nucleic%20Acids%20Research%202003%20Haas.pdf},\nuri = {papers://1C45D7C8-DE5F-4BCB-8C6D-9D101AFF5EFF/Paper/p810},\nread = {Yes},\nrating = {0}\n}\n\n"
  },
  {
    "path": "doc/algorithm/algorithm.tex",
    "content": "%\n%  Cufflinks algorithm\n%\n%  Created by Cole Trapnell on 2009-03-11.\n%  Copyright (c) 2009 Cole Trapnell. All rights reserved.\n%\n\\documentclass[twocolumn]{homework}\n\n% Use utf-8 encoding for foreign characters\n%\\usepackage[utf8]{inputenc}\n\n% Setup for fullpage use\n\\usepackage{fullpage}\n\n% Uncomment some of the following if you use the features\n%\n% Running Headers and footers\n%\\usepackage{fancyhdr}\n\n% Multipart figures\n%\\usepackage{subfigure}\n\n% More symbols\n%\\usepackage{amsmath}\n%\\usepackage{amssymb}\n%\\usepackage{latexsym}\n\n% Package for including code in the document\n\\usepackage{listings}\n\n% This is now the recommended way for checking for PDFLaTeX:\n\\usepackage{ifpdf}\n\n\\usepackage{amsmath}\n\\usepackage{amsthm}\n\n%\\newif\\ifpdf\n%\\ifx\\pdfoutput\\undefined\n%\\pdffalse % we are not running PDFLaTeX\n%\\else\n%\\pdfoutput=1 % we are running PDFLaTeX\n%\\pdftrue\n%\\fi\n\n\\theoremstyle{definition}\n\\newtheorem{defn}{Definition}\n\n\\ifpdf\n\\usepackage[pdftex]{graphicx}\n\\else\n\\usepackage{graphicx}\n\\fi\n\\title{The Cufflinks transcript assembly algorithm}\n\\author{ Cole Trapnell, Ali Mortazavi, and Lior Pachter }\n\n\\begin{document}\n\n\\ifpdf\n\\DeclareGraphicsExtensions{.pdf, .jpg, .tif}\n\\else\n\\DeclareGraphicsExtensions{.eps, .jpg}\n\\fi\n\n\\maketitle\n\n\n\\section{Introduction}\n\nThe Cufflinks algorithm takes as input a reference genome and a set of single or paired end alignments of RNA-Seq reads and reports as output a set of messenger RNA (transcript) sequences along with estimates of their relative abundances in the input sample.  The algorithm is a direct extension of an algorithm that performs haplotype frequency estimation in viral populations \\cite{Eriksson:2008p1143}.  Much of what appears here is copied verbatim from that paper to make the presentation of the extensions more clear.  Both algorithms report a parsimonious set of assembled sequences that are consistent with the alignments, and assign reads to the assembled sequences using a maximum likelihood step.  When the algorithm terminates, a maximal number of reads are assigned to assembled sequences, and every assigned read is consistent with the sequence to which it is assigned.\n\nThe Cufflinks algorithm extends the ShoRHA algorithm in  \\cite{Eriksson:2008p1143} in several ways.  First, ShoRAH assumes that the reads are unpaired, and align to the reference without gaps.  Cufflinks handles reads that aligned over splice junctions, and reads that are paired.  Second, ShoRHA assumes that the haplotypes are the same length and are syntenic.  Cufflinks assembles a diverse set of sequences, corresponding to transcripts that are generally not the same length. Third, Cufflinks can integrate annotations seamlessly to produce its assemblies, increasing its effectiveness in regions of relatively low read coverage.\n\n\\section{Algorithm}\n\nWe describe the algorithm to comparatively assemble paired-end read alignments into transcripts in this section.  Discussion of how to assemble single-end alignments, or mixtures of single- and paired-ends is omitted, but is believed to be straightforward with minor extensions to this algorithm.  The first step in the algorithm computes a minimal set of transcript sequences needed to explain the reads.  The second step estimates the relative abundances of those transcripts in the input via a maximum-likelihood calculation.\n\nLet $M$ be the paired-end reads alignments or \\emph{mate alignments} provided as input to the algorithm.  Each mate alignment consists of two \\emph{read alignments}, which each consist of an offset into the reference and a sequence of CIGAR operations.  We restrict ourselves to the `match' and `skip' operations.  Match operations simply denote a contiguous interval in the alignment (i.e. a region of alignments that contains exact base matches and substitutions, but no gaps).  Skip operations denote a (often intron-sized) gap in the alignment.  For a mate alignment $m$, we denote the read alignment with the lower offset into the reference as the ``left'' read alignment, $m_L$, and the larger offset alignment the ``right'' read alignment, $m_R$.  Also, we write the lowest-offset base in the reference covered by $m$ as $m_l$, and the highest-offset base as $m_r$.  \n\n\\begin{defn}\nTwo mate alignments $x$ and $y$ are said to overlap if the intervals $[x_l,x_r]$ and $[y_l,y_r]$ intersect.    \n\\end{defn}\n\nAn overlapping pair of mate alignments is \\emph{consistent} if they do not \n``disagree'' about the locations and lengths of their implied introns (if any) and could have come from the same transcript. A pair of overlapping \\emph{read} alignments ``intron-agree'' on introns only if the computed offsets of the CIGAR skip operations are identical for both alignments. A pair of read alignments that do \\emph{not} overlap are said to vacuously agree.  \n\nThe RNA-Seq protocol usually specifies randomly fragmenting cDNA and then\nsize-selecting fragments. Each fragment or \\emph{insert} is sequenced for a\nfixed number of cycles from both ends, resulting in a pair of reads separated\nin the transcriptome coordinate space by a length following a generally well\nbehaved (and presumed to be normal) distribution. Consider a pair of mates $x$\nand $y$ that overlap such that part of a read alignment from $y$ falls within\nthe genomic interval in between the read alignments of $x$. Call this part of\n$y$'s read alignment $y*$, and denote its length $l_{y*}$. If $x$ and $y$ are\nfrom the same transcript, then the (unknown) part of the transcript between\n$x$'s read alignments must contain $y*$ as a substring. Thus the distance\nbetween $x$'s read alignments in the transcriptome coordinate space must be at\nleast $l_{y*}$. If the cumulative distribution function of the insert length\ndistribution is $F(d)$, then the probability that the transcriptomic inner\ndistance $x$ is at least $l_{y*}$ is $1 - F(l_{y*})$.  For some probability threshold $t$, we say $x$ ``distance-agrees'' with $y$ if:\n\\begin{equation*}\n    1 - F(l_{y*}) \\geq t\n\\end{equation*}\n\nNote that the binary relation of distance-agreement is not generally symmetric\n\n\\begin{defn}\n    A pair of overlapping mate alignments $x$ and $y$ are consistent only if the following are both true:\n    \\begin{enumerate}\n        \\item $x_L$ intron-agrees with $y_L$ and $x_R$ \n            intron-agrees with $y_R$.\n        \\item $x$ distance-agrees with $y$ and $y$ distance-agrees with $x$ with some probability threshold $t$.\n    \\end{enumerate}\n\\end{defn}\n\nA given transcript is called \\emph{completely consistent} with the input set of mate alignments $M$ if its sequence can be constructed from a subset of $M$, where any mates in the subset that overlap are consistent.  Let $C_M$ be the set of all transcripts constructible from subsequences (by concatenation) of the reference and that are completely consistent with $M$.  What follows are methods for constructing and sampling $C_M$ necessary for computing a minimal set of transcripts necessary to explain the mates in $M$.\n\n\\begin{defn}\n    The \\emph{mate graph} $G_M$ associated with $M$ is a directed, acyclic graph with vertices $\\{M_{irr}, s, t\\}$ consisting of a source $s$, a sink $t$, and a vertex for each irredundant mate alignment.  A mate alignment is $x$ redudant if it is overlapped by another mate alignment $y$, $x_L$ intron-agrees with and is contained by $y_L$ and $x_R$ intron-agrees with and is contained by $y_R$. The edges of $G_M$ are defined by including an edge from $x$ to $y$ when \n    \\begin{enumerate}\n        \\item $x_l < y_l$\n        \\item $x$ and $y$ overlap consistently\n        \\item there would not be a path from $x$ to $y$ in $G_M$ without this edge.\n    \\end{enumerate}\n    Finally, edges are added from the source vertex $s$ to any vertex in $M_{irr}$ that lacks a ``left overlap'', i.e. a vertex for mate $x$ where there is no overlapping, consistent mate $y$ with $y_l < x_l$.  Edges are similarly added from mates without right overlaps to the sink vertex $t$.\n\\end{defn}\n\nA path through the mate graph corresponds to a transcript that is completely consistent with $M$ and whose sequence can be constructed from overlaps implied by the edges on the path.  We say that a set of transcript sequences $T$ is an explaining set for $M$ if every mate alignment $m \\in M$, can be obtained as a pair of substrings from a transcript in $T$ separated by a distance $d$ that is less than two standard deviations from the mean of the inner distance length distribution. \n\nWe want to compute a minimal explaining set of transcripts that is completely consistent with our mate alignments.  The proposition on page four of \\cite{Eriksson:2008p1143} implies that an explaining set of completely consistent transcripts is precisely a set of paths from the source to the sink, such that each vertex of the mate graph is covered by at least one path.  This amounts to ``explaining'' each read by including it in a larger assembly.  Such a set of paths is called a \\emph{cover}, and can be computed efficiently by the following theorem:\n\n\\theoremstyle{theorem}\n\\newtheorem*{DL}{Dilworth's Theorem}\n\\begin{DL}\n    Given a mate graph: \n    \\begin{enumerate}\n        \\item Every minimal cover of the mate graph has the same cardinality, namely the size of the largest set $Q$ of vertices such that there are no paths between elements of $Q$.\n      \n        \\item A minimal cover of the mate graph can be computed by solving a maximum matching problem in an associated bipartite graph.  This maching problem can be solved in time at worst cubic in the number of irredundant reads.\n    \\end{enumerate}\n\\end{DL}\n\nA minimal cover obtained from the maximum matching algorithm is in general not unique.  It provides a minimal \\emph{chain decomposition} of the graph.  A \\emph{chain} in a DAG is a set of vertices that all lie on at least one common path from the source to the sink, and can generally be extended to a number of different paths. Put another way, a chain is a set of reads that are all comparable to each other according to the partial ordering implied by the mate graph. While this chain decomposition is also in general not unique, the cardinality of the minimal cover is well-defined, and is an important invariant of the set of alignments.  The cardinality of the minimal cover is a lower bound on the number of transcripts needed to explain the mate alignments.\n\n\\subsection{Computing the minimal set of explaining transcripts}\nThe algorithm to compute a minimal set of explaining transcripts has four steps:\n\n\\begin{enumerate}\n    \\item Construct the mate graph $G_M$ associate with $M$\n    \\item Compute a minimal chain decomposition of $G_M$.\n    \\item Extend chains in the decomposition to paths from the source to the sink in $G_M$.\n    \\item Output the transcript sequences corresponding to the paths.\n\\end{enumerate}\n\nStep one is straightforward, and consists of sorting the mate alignments by\nreference position, checking for overlaps, and then checking for consistency\nbetween any overlapping pairs. It has worst case complexity $O(|M|^2)$, but is\nlikely to be fast for typical inputs.\n\nStep two begins by taking $G_M$ and building the associated bipartite graph\nwith a vertex for each mate alignment, and an edge between mates $x$ and $y$\nif there is a path from $x$ to $y$ in $G_M$. This amounts to a transitive\nclosure calculation on $G_M$, which has time complexity $O(|V'||E'|)$, where\nhere $|V'| = 2|M|$ and $|E'| = |M|^2$. Thus this step is worst-case cubic.\n\nAfter building the bipartite graph from the transitive closure of $G_M$, the\nalgorithm computes a minimal chain decomposition on $G_M$. Dilworth's Theorem\n(http://en.wikipedia.org/wiki/Dilworth's\\_theorem) states that we can\nconstruct a minimal chain decomposition from a maximum cardinality matching\n$H$ on the bipartite graph. A constructive proof, which follows from K\\\"onig's\nTheorem, works by building an \\emph{antichain} on $G_M$. An antichain here is\na set of mate alignments from $G_M$ where there is no path between any two\nelements. After building the bipartite graph as above, K\\\"onig's Theorem says\nthat there is a matching $H$ and a set of vertices $C$ in the bipartite graph,\nsuch that each edge in the graph contains at least one vertex in $C$ and such\nthat $H$ and $C$ have the same cardinality $m$. Let $A$ be the set of mate\nalignments that do not correspond to any vertex in $C$; then $A$ has at least\n$|M| - |H|$ elements. Now let $P$ be a family of chains formed by including\nthe mate alignment for $x$ and the mate alignment for $y$ in the same chain\nwhenever there is an edge from a vertex representing $x$ to a vertex\nrepresenting $y$ in the matching. $P$ has $|H|-|H|$ chains. Therefore, we have\nconstructed an antichain and a partition into chains with the same\ncardinality.\n\nIn step three, the algorithm extends the chains in the graph to paths from the\nsource to the sink. Note that while there is not necessarily a unique\nextension from a given chain to such a path, any set of extensions of the\nchains to paths will yield a minimal explaining set of transcripts for the\nreads. As described in below, a path through $G_M$ corresponds to a sequence\nof (possibly overlapping) read alignments of the mate alignments intermixed\nwith regions where the transcript sequence is unknown, but where the length of\nthe unknown sequence in the transcriptome coordinate space can be estimated.\nSince any set of path extensions will produce a minimal explaining set, the\nalgorithm choosing the one which minimizes the amount unknown sequence in each\npath. Since the paths form a cover of the mate alignments, rather than a\npartition, this is essentially a trivial optimization problem which can be\nsolved optimally with greedy, local choices during the path extension step.\n\nStep four takes paths generated by step three and outputs the sequences for\nthe transcripts constructible from them. Each path corresponds to a set of\nconsistent mate alignments, and each mate alignment consists of a pair of read\nalignments, each of which has a CIGAR string. The algorithm produces a single\nCIGAR string for the entire path, along with a sequence for the path on which\n(along with the reference) the CIGAR string operates.\n\n\\subsection{Transcript abundance estimation} We view an input mRNA sample as a\nprobability distribution on a set of transcripts. We want to estimate this\ndistribution from a set of observed paired-end reads. Let $\\mathbf{T}$ be the\nset of candidate transcripts. Ideally, we would take $\\mathbf{T}$ as the set\nof all possible transcripts, but we must limit ourselves to a small explaining\nset of transcripts. Using the set of transcripts produced by the algorithm\nabove will make the abundance estimate feasible to calculate. Let $\\mathbf{M}$\nbe the set of possible mate alignments that are compatible with transcripts in\n$\\mathbf{T}$. Then we can write the mate alignment observation data as a\nvector $u$, where $u_m$ is the number of times we observed mate alignment $m$.\n\nThe inference process is based on a statistical model for the generation of\npaired-end reads from an mRNA sample. We assume that read pairs are generated\nas follows. First, a transcript $t$ is drawn at random from the unknown\nprobability distribution $p=(p_t)_{t \\in \\mathbf{T}}$. Next, a new mate $m$ is\ngenerated from $t$ by first picking a left read alignment starting at $m_l$ at\nrandom from all positions in $t$. Then, a the end of the right read alignment\n$m_r$ is generated by picking a length from the distribution of insert lengths\nand adding that length to $m_l$. If the length would exceed the end of the\ntranscript, then a new length is picked from the mate pair length distribution\nuntil a valid mate pair is obtained. Estimating the structure of the\npopulation is the problem of estimating $p$ from $u$ under this generative\nmodel.\n\nLet $T$ be the hidden random variable with values in $\\mathbf{T}$ that\ndescribes the transcript and $M$ the observed random variable over\n$\\mathbf{M}$ for the mate pair. Then the probability of observing mate pair\n$m$ under this model is\n\n\\begin{equation*} \n    Pr(M=m) = \\sum_{t \\in \\mathbf{T}} p_t Pr(M=m|T=t)\n\\end{equation*}\n\nWhere the conditional probability is taken as zero if $m$ is not consistent\nwith $t$, and otherwise defined as $Pr(M=m||T=t) = (1/K)p_l(m_r - m_l)$, where\n$K$ is the length of $t$ and $p_l$ is the mate pair length distribution, which\nwe assume to normal and with a given mean and variance.\n\nThe algorithm then estimates $p$ by iteratively estimating the missing data\n$u_{mt}$, the number of times mate alignment $m$ originated from transcript\n$t$, by maximizing the log-likelihood function of the hidden model\n\n\\begin{equation*}\n    \\mathcal{L}_{hid}(p_1,...,p_{|T|}) = \\sum_{m \\in \\mathbf{M}} \\sum_{t \\in \\mathbf{T}} u_{mt} log( Pr(M=m|T=t) )\n\\end{equation*}\n\nIn the E step, the expected values of the missing data is computed as \n\n\\begin{equation*}\n    u_{mt} = u_m \\frac{p_t Pr(M=m|T=t)}{P(M=m)}\n\\end{equation*}\n\nIn the M step, maximization of $\\mathcal{L}_{hid}$ yields \n\n\\begin{equation*}\n    \\hat{p}_t = \\frac{\\sum_{m \\in \\mathbf{M}} u_{mt} }{\\sum_{m \\in \\mathbf{M}} u_m}\n\\end{equation*}\n\n\\bibliographystyle{plain} \\bibliography{algorithm} \\end{document}\n"
  },
  {
    "path": "doc/algorithm/homework.cls",
    "content": "% homework.sty \n% For formatting homework  \n% --- Class structure: identification part \n% --- \n\\ProvidesClass{homework}[9/17/2006 version 1.00 Homework] \n\\NeedsTeXFormat{LaTeX2e} \n\n% --- Class structure: declaration of options part \n% --- \n% This class extends the article class \n% Read all the documentclass options; pass them to article, \n% unless the file \"<currentoption>.min\" exists, then it is loaded \n\\DeclareOption*{\\InputIfFileExists{\\CurrentOption.hwk}{}{% \n\\PassOptionsToClass{\\CurrentOption}{article}}} \n\n\n% --- Class structure: execution of options part \n% --- \n\\ProcessOptions \\relax \n% --- Class structure: declaration of options part \n% --- \n\\LoadClass{article} \n\n% Page layout \n\\RequirePackage[left=1in,right=1in,top=1in,bottom=1in]{geometry} \n\n\n\\usepackage{fancyhdr}           % For LaTeX2.09 you should specify {fancyhdr} \n                                % in the \\documentstyle instead of the \n                                % \\usepackage command\n\\usepackage{ifthen}\n\n% headers for all pages\n\\pagestyle{fancy}\n\\fancyhf{}                      % clear all header and footer fields\n\\renewcommand{\\headrulewidth}{1pt}   \n\\renewcommand{\\footrulewidth}{1pt}   \n\n% if short title (#1) does not exits, use long title (#2) for header, else use #1\n\\newcommand\\settitle[2][]{%\n \\title{#2}\n \\ifthenelse{\\equal{#1}{}}%\n  {\n  \t\\fancyhead[C]{#2}\n  \t\\fancyhead[R]{\\thepage}\n  }%\n  {\n  \t\\fancyhead[C]{#1}\n  \t\\fancyhead[R]{\\thepage}\n  }%\n}\n\n% use short author list (#1) for header\n\\newcommand\\setauthors[2]{%\n \\author{#2}\n  {\\fancyhead[L]{#1}}%\n}\n\n% header for first page\n\\fancypagestyle{plain}{%\n\\fancyhf{}  \n% URL suffix will be filled in by Dagstuhl             \n%\\fancyfoot[L]{\\scriptsize Dagstuhl Seminar Proceedings <seminar-number>\\\\ http://drops.dagstuhl.de/opus/volltexte/2005/}\n\\renewcommand{\\headrulewidth}{0pt}\n\\renewcommand{\\footrulewidth}{0pt}}"
  },
  {
    "path": "doc/cufflinks.bib",
    "content": "%% This BibTeX bibliography file was created using BibDesk.\r\n%% http://bibdesk.sourceforge.net/\r\n\r\n\r\n%% Created for Colin Dewey at 2005-10-16 22:47:51 -0700\r\n\r\n\r\n%% Saved with string encoding ASCII (TeX)\r\n\r\n\r\n%PASA, alt. splicing graphs, Burge, Sorek, Roderic...\r\n\r\n\r\n\r\n@book{ASCB2005,\r\n    Editor = {L Pachter and B Sturmfels},\r\n    Publisher = {Cambridge University Press},\r\n    Title = {{Algebraic Statistics for Computational Biology}},\r\n    Year = {2005}}\r\n\r\n@Article{Rozen2000,\r\n  author = \t {S Rozen and H J Skaletsky},\r\n  title = \t {{Primer3 on the WWW for general users and for biolgist programmers}},\r\n  journal = \t {Methods and Protocols: Methods in Molecular Biology},\r\n  year = \t {2000},\r\n  OPTkey = \t {},\r\n  volume = \t {4},\r\n  OPTnumber = \t {},\r\n  pages = \t {365-386},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Oshlack2009,\r\n  author = \t {A Oshlack and MJ Wakefield},\r\n  title = \t {Transcript length bias in {RNA-Seq} data confounds systems biology},\r\n  journal = \t {Biology Direct},\r\n  year = \t {2009},\r\n  OPTkey = \t {},\r\n  volume = \t {4},\r\n  OPTnumber = \t {},\r\n  pages = \t {14},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@book{Agresti1990,\r\n    Address = {New York},\r\n    Author = {A Agresti},\r\n    Isbn = {0-471-85301-1},\r\n    Mrclass = {62H17},\r\n    Mrnumber = {MR1044993 (91k:62055)},\r\n    Mrreviewer = {I. J. Good},\r\n    Note = {A Wiley-Interscience Publication},\r\n    Pages = {xvi+558},\r\n    Publisher = {John Wiley \\& Sons Inc.},\r\n    Series = {Wiley Series in Probability and Mathematical Statistics: Applied Probability and Statistics},\r\n    Title = {Categorical Data Analysis},\r\n    Year = {1990}}\r\n\r\n\r\n@Article{Aroian1978,\r\n  author = \t {LA Aroian and VS Taneja and LW Cornwell},\r\n  title = \t {Mathematical forms of the distribution of the product of two normal variables},\r\n  journal = \t {Communications in Statistics: Theory and Methods},\r\n  year = \t {1978},\r\n  OPTkey = \t {},\r\n  volume = \t {A7},\r\n  OPTnumber = \t {},\r\n  pages = \t {165--172},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Bandelt1992,\r\n    Author = {HJ Bandelt and A Dress},\r\n    Date-Modified = {2005-03-01 19:33:42 -0500},\r\n    Journal = {Advances in Mathematics},\r\n    Pages = {47--105},\r\n    Title = {A canonical decomposition theory for metrics on a finite set},\r\n    Volume = {92},\r\n    Year = {1992}}\r\n\r\n@article{Bandelt1995,\r\n    Author = {HJ Bandelt and P Forster and BC Sykes and MB Richards},\r\n    Date-Modified = {2005-03-01 19:34:19 -0500},\r\n    Journal = {Genetics},\r\n    Pages = {743--753},\r\n    Title = {Mitochondrial portraits of human population using median networks},\r\n    Volume = {141},\r\n    Year = {1995}}\r\n\r\n@inCollection{Barad2003,\r\n  author =       {G Barad},\r\n  title = \t {Genome rearrangements and algebraic geometry},\r\n  year = \t {2003},\r\n  OPTkey = \t {},\r\n  booktitle =    {Knots in Washington XV},\r\n  editor = \t {K Kobayashi and K Przytycki and Y Rong and S Suzuki and K Taniyama and T Tsukamoto and A Yasuhara},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTaddress = \t {},\r\n  OPTmonth = \t {},\r\n  OPTorganization = {},\r\n  OPTpublisher = {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Book{Barthelemy1991,\r\n  author = \t {J-P Barth'{e}l\\'{e}my and A Gu\\'{e}noche},\r\n  ALTeditor = \t {},\r\n  title = \t {Trees and Proximity Representations},\r\n  publisher = \t {John Wiley \\& Sons},\r\n  year = \t {1991},\r\n  OPTkey = \t {},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Barthelemy2008,\r\n  author = \t {J-P Barth'{e}lemy and F Brucker},\r\n  title = \t {Binary clustering},\r\n  journal = \t {Discrete Applied Mathematics},\r\n  year = \t {2008},\r\n  OPTkey = \t {},\r\n  volume = \t {156},\r\n  OPTnumber = \t {8},\r\n  pages = \t {1237--1250},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n\r\n@Article{Benjamini1995,\r\n  author = \t {Y Benjamini and Y Hochberg},\r\n  title = \t {Controlling the False Discovery Rate: a Practical and Powerful Approach to Multiple Testing},\r\n  journal = \t {Journal of the Royal Statistical Society, Series B (Methodological)},\r\n  year = \t {1995},\r\n  OPTkey = \t {},\r\n  volume = \t {57},\r\n  OPTnumber = \t {},\r\n  pages = \t {289--300},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Bertrand2002,\r\n  author = \t {P Bertrand and MF Janowitz},\r\n  title = \t {Pyramids and weak hierarchies in the ordinal model for clustering},\r\n  journal = \t {Discrete Applied Mathematics},\r\n  year = \t {2002},\r\n  OPTkey = \t {},\r\n  volume = \t {122},\r\n  OPTnumber = \t {},\r\n  pages = \t {55--81},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n\r\n@book{Bertsekas1999,\r\n    Address = {MA Belmont},\r\n    Author = {D Bertsekas},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Athena Scientific},\r\n    Title = {Nonlinear Programming},\r\n    Year = {1999}}\r\n\r\n@book{Bertsimas1997,\r\n    Author = {D Bertsimas and J Tsitsiklis},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Athena Scientific},\r\n    Title = {Introduction to Linear Programming},\r\n    Year = {1997}}\r\n\r\n@incollection{Berz1991,\r\n    Address = {Philadelphia, PA},\r\n    Author = {M Berz},\r\n    Booktitle = {Automatic differentiation of algorithms: theory, implementation and applications},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Editor = {A Griewank and G Corliss},\r\n    Pages = {147--156},\r\n    Publisher = {SIAM},\r\n    Title = {Forward algorithms for high orders and many variables with application to beam physics},\r\n    Year = {1991}}\r\n\r\n@article{Besag1974,\r\n    Author = {Besag, J.},\r\n    Journal = {Journal of the Royal Statistical Society},\r\n    Pages = {192--236},\r\n    Title = {Spatial interaction and the statistical analysis of lattice systems},\r\n    Volume = {B,36},\r\n    Year = {1974}}\r\n\r\n\r\n@article{Besag1986,\r\n    Author = {J Besag},\r\n    Journal = {Journal of the Royal Statistical Society},\r\n    Pages = {259--302},\r\n    Title = {On the statistical analysis of dirty pictures},\r\n    Volume = {B 48 No. 3},\r\n    Year = {1986}}\r\n\r\n@book{Bickel2000,\r\n    Author = {PJ Bickel and KA Doksum},\r\n    Publisher = {Prentice Hall},\r\n    Title = {Mathematical statistics: Basic Ideas and Selected Topics, Vol I (2nd Edition)},\r\n    Year = {2000}}\r\n\r\n\r\n@article{Billera2001,\r\n    Author = {LJ Billera and SP Holmes and K Vogtmann},\r\n    Date-Modified = {2005-02-05 13:05:35 -0800},\r\n    Fjournal = {Advances in Applied Mathematics},\r\n    Issn = {0196-8858},\r\n    Journal = {Advances in Applied Mathematics},\r\n    OPTMrclass = {05C90 (92B10)},\r\n    OPTMrnumber = {MR1867931 (2002k:05229)},\r\n    Mrreviewer = {Charles A. Semple},\r\n    OPTNumber = {4},\r\n    Pages = {733--767},\r\n    Title = {Geometry of the space of phylogenetic trees},\r\n    Volume = {27},\r\n    Year = {2001}}\r\n\r\n@incollection{Blanchette2000,\r\n    Address = {Providence, RI},\r\n    Author = {D Sankoff and M Blanchette},\r\n    Booktitle = {Stochastic models (Ottawa, ON, 1998)},\r\n    Mrclass = {92D15 (60J27)},\r\n    Mrnumber = {MR1765022 (2002f:92014)},\r\n    Mrreviewer = {Ming-Ying Leung},\r\n    Pages = {399--418},\r\n    Publisher = {American Mathematical Society},\r\n    Series = {Proceedings of the International Conference on Stochstic Models},\r\n    Title = {Comparative genomics via phylogenetic invariants for {J}ukes-{C}antor semigroups},\r\n    Volume = {26},\r\n    Year = {2000}}\r\n\r\n\r\n\r\n@article{Blanchette2004,\r\n    Author = {M Blanchette and WJ Kent and C Riemer and L Elnitski and AFA Smit and KM Roskin and R Baertsch and K Rosenbloom and H Clawson and ED Green and others},\r\n    Journal = {Genome Research},\r\n    Pages = {708--715},\r\n    Title = {Aligning multiple genomic sequences with the threaded blockset aligner},\r\n    Volume = {14},\r\n    Year = {2004}}\r\n\r\n@article{Boffelli2003,\r\n    Abstract = {Nonhuman primates represent the most relevant model organisms to understand the biology of Homo sapiens. The recent divergence and associated overall sequence conservation between individual members of this taxon have nonetheless largely precluded the use of primates in comparative sequence studies. We used sequence comparisons of an extensive set of Old World and New World monkeys and hominoids to identify functional regions in the human genome. Analysis of these data enabled the discovery of primate-specific gene regulatory elements and the demarcation of the exons of multiple genes. Much of the information content of the comprehensive primate sequence comparisons could be captured with a small subset of phylogenetically close primates. These results demonstrate the utility of intraprimate sequence comparisons to discover common mammalian as well as primate-specific functional elements in the human genome, which are unattainable through the evaluation of more evolutionarily distant species.},\r\n    Affiliation = {U.S. Department of Energy Joint Genome Institute, Walnut Creek, CA 94598, USA.},\r\n    Aid = {299/5611/1391 {$[$}pii{$]$}},\r\n    Au = {Rubin EM},\r\n    Author = {D Boffelli and J McAuliffe and D Ovcharenko and KD Lewis and I Ovcharenko and L Pachter and EM Rubin},\r\n    Cin = {Science. 2003 Feb 28;299(5611):1331-3. PMID: 12610290},\r\n    Da = {20030228},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20030314},\r\n    Edat = {2003/03/01 04:00},\r\n    Gr = {R01-HG02362-01/HG/NHGRI},\r\n    Jid = {0404511},\r\n    Journal = {Science},\r\n    Keywords = {Animals and Apolipoproteins A/genetics and Cebidae/genetics and Cercopithecidae/genetics and Computational Biology and Conserved Sequence and DNA-Binding Proteins/metabolism and Electrophoretic Mobility Shift Assay and Evolution and Exons and Gene Expression Regulation and *Genome and *Genome, Human and Hominidae/genetics and Humans and Hylobates/genetics and Likelihood Functions and *Phylogeny and Primates/*genetics and Regulatory Sequences, Nucleic Acid and Research Support, U.S. Gov't, Non-P.H.S. and Research Support, U.S. Gov't, P.H.S. and *Sequence Analysis, DNA and Species Specificity and Tumor Cells, Cultured},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2003/03/15 04:00},\r\n    Number = {5611},\r\n    Own = {NLM},\r\n    Pages = {1391--4},\r\n    Pl = {United States},\r\n    Pmid = {12610304},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (DNA-Binding Proteins)},\r\n    Sb = {IM},\r\n    So = {Genome Res 2003 Mar;13(3):496-502.},\r\n    Stat = {MEDLINE},\r\n    Title = {Phylogenetic shadowing of primate sequences to find functional regions of the human genome.},\r\n    Volume = {299},\r\n    Year = {2003}}\r\n\r\n\r\n\r\n\r\n@article{Boffelli2004,\r\n    Author = {D Boffelli and MA Nobrega and EM Rubin},\r\n    Journal = {Nature Reviews Genetics},\r\n    Pages = {456--465},\r\n    Title = {Comparative Genomics at the Vertebrate Extremes},\r\n    Volume = {5},\r\n    Year = {2004}}\r\n\r\n\r\n\r\n@article{Boffelli2004a,\r\n    Author = {D Boffelli and CV Weer and L Weng and KD Lewis and MI Shoukry and L Pachter and DN Keys and EM Rubin},\r\n    Journal = {Genome Research},\r\n    Pages = {2406--2411},\r\n    Title = {Intraspecies sequence comparisons for annotating genomes},\r\n    Volume = {14},\r\n    Year = {2004}}\r\n\r\n@Misc{Boost,\r\n  key = \t {Boost library},\r\n  author = \t {Boost C++ libraries},\r\n  title = \t {{\\tt http://www.boost.org/}},\r\n  OPThowpublished = {},\r\n  OPTmonth = \t {},\r\n  OPTyear = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n\r\n@article{Bosma1997,\r\n    Author = {W Bosma and J Cannon and C Playoust},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Doi = {http://dx.doi.org/10.1006/jsco.1996.0125},\r\n    Issn = {0747-7171},\r\n    Journal = {Journal of Symbolic Computation},\r\n    Number = {3-4},\r\n    Pages = {235--265},\r\n    Publisher = {Academic Press, Inc.},\r\n    Title = {{The MAGMA algebra system I: the user language}},\r\n    Volume = {24},\r\n    Year = {1997}}\r\n\r\n@article{Bourque2004,\r\n    Abstract = {Recent analysis of genome rearrangements in human and mouse genomes revealed evidence for more rearrangements than thought previously and shed light on previously unknown features of mammalian evolution, like breakpoint reuse and numerous microrearrangements. However, two-way analysis cannot reveal the genomic architecture of ancestral mammals or assign rearrangement events to different lineages. Thus, the \"original synteny\" problem introduced by Nadeau and Sankoff previously, remains unsolved, as at least three mammalian genomes are required to derive the ancestral mammalian karyotype. We show that availability of the rat genome allows one to reconstruct a putative genomic architecture of the ancestral murid rodent genome. This reconstruction suggests that this ancestral genome retained many previously postulated chromosome associations in the placental ancestor and reveals others that were beyond the resolution of cytogenetic, radiation hybrid mapping, and chromosome painting techniques. Three-way analysis of rearrangements leads to a reliable reconstruction of the genomic architecture of specific regions in the murid ancestor, including the X chromosome, and for the first time allows one to assign major rearrangement events to one of human, mouse, and rat lineages. Our analysis implies that the rate of rearrangements is much higher in murid rodents than in the human lineage and confirms the existence of rearrangement hot-spots in all three lineages.},\r\n    Affiliation = {Centre de Recherches Mathematiques, Universite de Montreal, Canada H3C 3J7.},\r\n    Aid = {14/4/507 {$[$}pii{$]$}},\r\n    Au = {Tesler G},\r\n    Author = {G Bourque and PA Pevzner and G Tesler},\r\n    Da = {20040402},\r\n    Dcom = {20040505},\r\n    Edat = {2004/04/03 05:00},\r\n    Jid = {9518021},\r\n    Journal = {Genome Research},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2004/05/07 05:00},\r\n    Number = {4},\r\n    Own = {NLM},\r\n    Pages = {507--16},\r\n    Pl = {United States},\r\n    Pmid = {15059991},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Sb = {IM},\r\n    Stat = {MEDLINE},\r\n    Title = {Reconstructing the genomic architecture of ancestral mammals: lessons from human, mouse, and rat genomes.},\r\n    Volume = {14},\r\n    Year = {2004}}\r\n\r\n@article{Boykov1999,\r\n    Author = {Y Boykov and O Veksler and R Zabih},\r\n    Journal = {Intl. Conf. on Computer Vision},\r\n    Title = {Fast approximate energy minimization via graph cuts},\r\n    Year = {1999}}\r\n\r\n@article{Bray2003,\r\n    Abstract = {MAVID is a multiple alignment program suitable for many large genomic regions. The MAVID web server allows biomedical researchers to quickly obtain multiple alignments for genomic sequences and to subsequently analyse the alignments for conserved regions. MAVID has been successfully used for the alignment of closely related species such as primates and also for the alignment of more distant organisms such as human and fugu. The server is fast, capable of aligning hundreds of kilobases in less than a minute. The multiple alignment is used to build a phylogenetic tree for the sequences, which is subsequently used as a basis for identifying conserved regions in the alignment. The server can be accessed at http://baboon.math.berkeley.edu/mavid/.},\r\n    Affiliation = {Department of Mathematics, 970 Evans Hall, UC Berkeley, Berkeley, CA 94720, USA.},\r\n    Au = {Pachter L},\r\n    Author = {N Bray and L Pachter},\r\n    Da = {20030625},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20030818},\r\n    Edat = {2003/06/26 05:00},\r\n    Jid = {0411011},\r\n    Journal = {Nucleic Acids Research},\r\n    Keywords = {Animals and Base Sequence and Conserved Sequence and Genomics/*methods and Humans and Internet and Mice and Molecular Sequence Data and Phylogeny and Rats and Sequence Alignment/*methods and Sequence Analysis, DNA/*methods and *Software and Takifugu/genetics},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2003/08/19 05:00},\r\n    Number = {13},\r\n    Own = {NLM},\r\n    Pages = {3525--6},\r\n    Pl = {England},\r\n    Pmid = {12824358},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Sb = {IM},\r\n    So = {J Comput Biol 2003;10(3-4):509-20.},\r\n    Stat = {MEDLINE},\r\n    Title = {{MAVID} multiple alignment server.},\r\n    Volume = {31},\r\n    Year = {2003}}\r\n\r\n\r\n\r\n@article{Bray2003a,\r\n    Abstract = {In this paper we describe a new global alignment method called AVID. The method is designed to be fast, memory efficient, and practical for sequence alignments of large genomic regions up to megabases long. We present numerous applications of the method, ranging from the comparison of assemblies to alignment of large syntenic genomic regions and whole genome human/mouse alignments. We have also performed a quantitative comparison of AVID with other popular alignment tools. To this end, we have established a format for the representation of alignments and methods for their comparison. These formats and methods should be useful for future studies. The tools we have developed for the alignment comparisons, as well as the AVID program, are publicly available. See Web Site References section for AVID Web address and Web addresses for other programs discussed in this paper.},\r\n    Affiliation = {Lawrence Berkeley National Laboratory, Berkeley, California 94720, USA.},\r\n    Aid = {10.1101/gr.789803 {$[$}doi{$]$}},\r\n    Au = {Pachter L},\r\n    Author = {N Bray and I Dubchak and L Pachter},\r\n    Da = {20030116},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20030317},\r\n    Edat = {2003/01/17 04:00},\r\n    Gr = {RO1-HG02362-01/HG/NHGRI},\r\n    Jid = {9518021},\r\n    Journal = {Genome Research},\r\n    Keywords = {Algorithms and Animals and Cats and Cattle and Chickens and Comparative Study and Dogs and Evolution, Molecular and Exons/genetics and Humans and Pan troglodytes and Rats and Repetitive Sequences, Nucleic Acid/genetics and Reproducibility of Results and Research Support, U.S. Gov't, P.H.S. and Sensitivity and Specificity and Sequence Alignment/*methods and *Software and Swine and Time Factors and Untranslated Regions/genetics},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2003/03/18 04:00},\r\n    Number = {1},\r\n    Own = {NLM},\r\n    Pages = {97--102},\r\n    Pl = {United States},\r\n    Pmid = {12529311},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (Untranslated Regions)},\r\n    Sb = {IM},\r\n    So = {Science 2003 Feb 28;299(5611):1391-4.},\r\n    Stat = {MEDLINE},\r\n    Title = {{AVID}: A global alignment program.},\r\n    Volume = {13},\r\n    Year = {2003}}\r\n\r\n@article{Bray2004,\r\n    Abstract = {We describe a new global multiple-alignment program capable of aligning a large number of genomic regions. Our progressive-alignment approach incorporates the following ideas: maximum-likelihood inference of ancestral sequences, automatic guide-tree construction, protein-based anchoring of ab-initio gene predictions, and constraints derived from a global homology map of the sequences. We have implemented these ideas in the MAVID program, which is able to accurately align multiple genomic regions up to megabases long. MAVID is able to effectively align divergent sequences, as well as incomplete unfinished sequences. We demonstrate the capabilities of the program on the benchmark CFTR region, which consists of 1.8 Mb of human sequence and 20 orthologous regions in marsupials, birds, fish, and mammals. Finally, we describe two large MAVID alignments, an alignment of all the available HIV genomes and a multiple alignment of the entire human, mouse, and rat genomes.},\r\n    Affiliation = {Department of Mathematics, University of California at Berkeley, Berkeley, California 94720, USA.},\r\n    Aid = {14/4/693 {$[$}pii{$]$}},\r\n    Au = {Pachter L},\r\n    Author = {N Bray and L Pachter},\r\n    Da = {20040402},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20040505},\r\n    Edat = {2004/04/03 05:00},\r\n    Gr = {R01-HG02362-01/HG/NHGRI},\r\n    Jid = {9518021},\r\n    Journal = {Genome Research},\r\n    Keywords = {Animals and Cats and Cattle and Comparative Study and Computational Biology/methods and Cystic Fibrosis Transmembrane Conductance Regulator/genetics and Dogs and *Evolution, Molecular and Fishes/genetics and Genome and Genome, Human and Genome, Viral and HIV-1/genetics and Humans and Mice and Rabbits and Rats and Research Support, U.S. Gov't, P.H.S. and SIV/genetics and Sequence Alignment/*methods/statistics \\& numerical data and Software/statistics \\& numerical data/*trends and Swine/genetics},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2004/05/07 05:00},\r\n    Number = {4},\r\n    Own = {NLM},\r\n    Pages = {693--9},\r\n    Pl = {United States},\r\n    Pmid = {15060012},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {126880-72-6 (Cystic Fibrosis Transmembrane Conductance Regulator)},\r\n    Sb = {IM},\r\n    So = {Genome Res 2004 Apr;14(4):716-20.},\r\n    Stat = {MEDLINE},\r\n    Title = {{MAVID}: constrained ancestral alignment of multiple sequences.},\r\n    Volume = {14},\r\n    Year = {2004}}\r\n\r\n@article{Brown1982,\r\n    Author = {WM Brown and EM Prager and A Wang and AC Wilson},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Molecular Evolution},\r\n    Pages = {225--239},\r\n    Title = {Mitochondrial {DNA} sequences of primates, tempo and mode of evolution},\r\n    Volume = {18},\r\n    Year = {1982}}\r\n\r\n@book{Brown2002,\r\n    Author = {TA Brown},\r\n    Publisher = {John Wiley \\& Son, Inc.},\r\n    Title = {Genomes 2},\r\n    Year = {2002}}\r\n\r\n@article{Brudno2003,\r\n    Author = {M Brudno and S Malde and A Poliakov and C Do and O Couronne and I Dubchak and S Batzoglou},\r\n    Journal = {Special issue on the Proceedings of the ISMB 2003, Bioinformatics},\r\n    Pages = {54i--64i},\r\n    Title = {Glocal alignment: finding rearrangements during alignment},\r\n    Volume = {19},\r\n    Year = {2003}}\r\n\r\n@article{Brudno2003a,\r\n    Author = {M Brudno and C Do and G Cooper and MF Kim and E Davydov and ED Green and A Sidow and S Batzoglou},\r\n    Journal = {Genome Research},\r\n    Pages = {721--731},\r\n    Title = {{LAGAN and Multi-LAGAN: efficient tools for large-scale multiple alignment of genomic DNA}},\r\n    Volume = {13},\r\n    Year = {2003}}\r\n\r\n@Article{Bruno2000,\r\n  author = {WJ Bruno and ND Socci and AL Halpern},\r\n  title = {Weighted neighbor-joining: a likelihood-based approach to\r\n                  distance-based phylogeny reconstruction},\r\n  journal = {Molecular Biology and Evolution},\r\n  year = {2000},\r\n  OPTkey = {},\r\n  volume = {17},\r\n  number = {1},\r\n  pages = {189--197},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@TechReport{Bryant2003,\r\n  author = \t {D Bryant and V Moulton},\r\n  title = \t {Consistency of the {N}eighbor{N}et algorithm for constructing phylogenetic networks},\r\n  institution =  {McGill University},\r\n  year = \t {2003},\r\n  OPTkey = \t {},\r\n  OPTtype = \t {},\r\n  OPTnumber = \t {},\r\n  OPTaddress = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Bryant2004,\r\n    Author = {D Bryant and V Moulton},\r\n    Date-Modified = {2005-03-01 19:59:37 -0500},\r\n    Journal = {Molecular Biology And Evolution},\r\n    Pages = {255--265},\r\n    Title = {{NeighborNet}: An agglomerative method for the construction of planar phylogenetic networks},\r\n    Volume = {21},\r\n    Year = {2004}}\r\n\r\n@Article{Bryant2005,\r\n  author = {D Bryant},\r\n  title = {On the uniqueness of the selection criterion in\r\n                  neighbor-joining},\r\n  journal = {Journal of Classification},\r\n  year = {2005},\r\n  OPTkey = {},\r\n  volume = {22},\r\n  number = {1},\r\n  pages = {3--15},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@InCollection{Bryant2005b,\r\n  author = \t {D Bryant and F Filimon and R Gray},\r\n  title = \t {Untangling our past: languages, trees, splits and networks},\r\n  booktitle = \t {The evolution of cultural diversity: phylogenetic approaches},\r\n  OPTcrossref =  {},\r\n  OPTkey = \t {},\r\n  pages = \t {69-85},\r\n  publisher = {UCL Press},\r\n  year = \t {2005},\r\n  editor = \t {R Mace and C Holden and S Shennan},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTtype = \t {},\r\n  OPTchapter = \t {},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n\r\n@InCollection{Bryant2005c,\r\n  author = \t {D Bryant},\r\n  title = \t {Extending tree models to split networks},\r\n  booktitle = \t {Algebraic Statistics for Computational Biology},\r\n  OPTcrossref =  {},\r\n  OPTkey = \t {},\r\n  pages = \t {322--334},\r\n  publisher = {Cambridge University Press},\r\n  year = \t {2005},\r\n  editor = \t {L Pachter and B Sturmfels},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTtype = \t {},\r\n  OPTchapter = \t {},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@phdthesis{Buchberger1965,\r\n    Author = {B Buchberger},\r\n    School = {Univ. Innsbruck, Dept. of Math., Innsbruck, Austria},\r\n    Title = {An algorithm for finding a basis for the residue class ring of a zero-dimensional polynomial ideal (in German).},\r\n    Year = {1965}}\r\n\r\n@inproceedings{Bucher1996,\r\n    Author = {P Bucher and K Hofmann},\r\n    Booktitle = {Proceedings Intelligent Systems in Molecular Biology},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Key = {Bucher},\r\n    Title = {A sequence similarity search algorithm based on a probabilistic interpretation of an alignment scoring system},\r\n    Year = {1996}}\r\n\r\n@TechReport{Bullard2009,\r\n  author = \t {JH Bullard and EA Purdom and KD Hansen and S Durinck and S Dudoit},\r\n  title = \t {Statistical inference in {mRNA-Seq}: exploratory data analysis and differential expression},\r\n  institution =  {UC Berkeley},\r\n  year = \t {2009},\r\n  OPTkey = \t {},\r\n  OPTtype = \t {},\r\n  OPTnumber = \t {},\r\n  OPTaddress = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Bullard2010,\r\n  author = \t {JH Bullard and E Purdom and KD Hansen and S Dudoit},\r\n  title = \t {Evaluation of statistical methods for normalization and differential expression in {mRNA-Seq} experiments},\r\n  journal = \t {BMC Bioinformatics},\r\n  year = \t {2010},\r\n  OPTkey = \t {},\r\n  volume = \t {11},\r\n  OPTnumber = \t {},\r\n  pages = \t {94},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Bulmer1991,\r\n    Author = {D Bulmer},\r\n    Date-Modified = {2005-03-01 20:05:24 -0500},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Number = {6},\r\n    Pages = {868--883},\r\n    Title = {Use of the Method of Generalized Least Squares in Reconstructing Phylogenies from Sequence Data},\r\n    Volume = {8},\r\n    Year = {1991}}\r\n\r\n@InCollection{Buneman1971,\r\n  author = \t {P Buneman},\r\n  title = \t {The recovery of trees from measures of dissimilarity},\r\n  booktitle = \t {Mathematics in the Archaeological and Historical Sciences},\r\n  OPTcrossref =  {},\r\n  OPTkey = \t {},\r\n  pages = \t {387--395},\r\n  publisher = {Edinburgh University Press},\r\n  year = \t {1971},\r\n  editor = \t {FR Hodson and DG Kendall and P Tautu},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTtype = \t {},\r\n  OPTchapter = \t {},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Burge1997,\r\n    Author = {C Burge and S Karlin},\r\n    Journal = {Journal of Molecular Biology},\r\n    Number = {1},\r\n    Pages = {78--94},\r\n    Title = {{Prediction of complete gene structures in human genomic DNA}},\r\n    Volume = {268},\r\n    Year = {1997}}\r\n\r\n@article{Campbell1999,\r\n    Author = {A Campbell and J Mrazek and S Karlin},\r\n    Journal = {Proceedings of the National Academy of Sciences USA},\r\n    Number = {16},\r\n    Pages = {9184--9189},\r\n    Title = {Genome signature comparisons among prokaryote, plasmid and mitochondrial {DNA}},\r\n    Volume = {96},\r\n    Year = {1999}}\r\n\r\n@Article{Carr2006,\r\n  author = \t {M Carr and S Devadoss},\r\n  title = \t {Coxeter complexes and graph associahedra},\r\n  journal = \t {Topology and its applications},\r\n  year = \t {2006},\r\n  OPTkey = \t {},\r\n  volume = \t {153},\r\n  OPTnumber = \t {},\r\n  pages = \t {2155--2168},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@misc{Casanellas2004,\r\n    Author = {M Casanellas and LD Garcia and S Sullivant},\r\n    Howpublished = {\\url{http://www.math.tamu.edu/~lgp/small-trees/}},\r\n    Title = {Small Phylogenetic trees},\r\n    Year = {2004}}\r\n\r\n@article{Catalisano2002,\r\n    Author = {MV Catalisano and AV Geramita and A Gimigliano},\r\n    Fjournal = {Linear Algebra and its Applications},\r\n    Journal = {Linear Algebra Appl.},\r\n    Pages = {263--285},\r\n    Title = {Ranks of tensors, secant varieties of {S}egre varieties and fat points},\r\n    Volume = {355},\r\n    Year = {2002}}\r\n\r\n@article{Catanese2005,\r\n    Author = {F Catanese and S Ho{\\c{s}}ten and A Khetan and B Sturmfels},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {American Journal of Mathematics},\r\n    Note = {To appear},\r\n    Title = {The maximum likelihood degree},\r\n    Year = {2005}}\r\n\r\n\r\n\r\n@article{Cavalli-Sforza1967,\r\n    Author = {L Cavalli-Sforza and A Edwards},\r\n    Date-Modified = {2005-03-01 20:03:56 -0500},\r\n    Journal = {Evolution},\r\n    Pages = {550--570},\r\n    Title = {Phylogenetic analysis models and estimation procedures},\r\n    Volume = {32},\r\n    Year = {1967}}\r\n\r\n@article{Cavender87,\r\n    Author = {J Cavender and J Felsenstein},\r\n    Journal = {Journal of Classification},\r\n    Pages = {57--71},\r\n    Title = {Invariants of phylogenies in a simple case with discrete states},\r\n    Volume = {4},\r\n    Year = {1987}}\r\n\r\n@article{Cawley2003,\r\n    Abstract = {SLAM is a program that simultaneously aligns and annotates pairs of homologous sequences. The SLAM web server integrates SLAM with repeat masking tools and the AVID alignment program to allow for rapid alignment and gene prediction in user submitted sequences. Along with annotations and alignments for the submitted sequences, users obtain a list of predicted conserved non-coding sequences (and their associated alignments). The web site also links to whole genome annotations of the human, mouse and rat genomes produced with the SLAM program. The server can be accessed at http://bio.math.berkeley.edu/slam.},\r\n    Affiliation = {Affymetrix Inc., 6550 Vallejo St, Suite 100, Emeryville, CA 94608, USA. simon_cawley@affymetrix.com},\r\n    Au = {Alexandersson M},\r\n    Author = {S Cawley and L Pachter and M Alexandersson},\r\n    Da = {20030625},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Dcom = {20030818},\r\n    Edat = {2003/06/26 05:00},\r\n    Gr = {R01-HG02362-01/HG/NHGRI},\r\n    Jid = {0411011},\r\n    Journal = {Nucleic Acids Research},\r\n    Keywords = {Algorithms and Amino Acid Sequence and Animals and Base Sequence and Conserved Sequence and Gene Components and Genomics/*methods and Humans and Internet and Markov Chains and Mice and Peptides/chemistry and RNA, Messenger/chemistry and RNA, Untranslated/chemistry and Rats and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, P.H.S. and Sequence Alignment/*methods and Sequence Analysis, DNA/*methods and *Software},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2003/08/19 05:00},\r\n    Number = {13},\r\n    Own = {NLM},\r\n    Pages = {3507--9},\r\n    Pl = {England},\r\n    Pmid = {12824355},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (RNA, Untranslated)},\r\n    Sb = {IM},\r\n    So = {Nucleic Acids Res 2003 Jul 1;31(13):3525-6.},\r\n    Stat = {MEDLINE},\r\n    Title = {{SLAM} web server for comparative gene finding and alignment.},\r\n    Volume = {31},\r\n    Year = {2003}}\r\n\r\n@article{Cawley2003a,\r\n    Abstract = {The standard method of applying hidden Markov models to biological problems is to find a Viterbi (maximal weight) path through the HMM graph. The Viterbi algorithm reduces the problem of finding the most likely hidden state sequence that explains given observations, to a dynamic programming problem for corresponding directed acyclic graphs. For example, in the gene finding application, the HMM is used to find the most likely underlying gene structure given a DNA sequence. In this note we discuss the applications of sampling methods for HMMs. The standard sampling algorithm for HMMs is a variant of the common forward-backward and backtrack algorithms, and has already been applied in the context of Gibbs sampling methods. Nevetheless, the practice of sampling state paths from HMMs does not seem to have been widely adopted, and important applications have been overlooked. We show how sampling can be used for finding alternative splicings for genes, including alternative splicings that are conserved between genes from related organisms. We also show how sampling from the posterior distribution is a natural way to compute probabilities for predicted exons and gene structures being correct under the assumed model. Finally, we describe a new memory efficient sampling algorithm for certain classes of HMMs which provides a practical sampling alternative to the Hirschberg algorithm for optimal alignment. The ideas presented have applications not only to gene finding and HMMs but more generally to stochastic context free grammars and RNA structure prediction. Key words: suboptimal parses, sampling, hidden Markov model, conserved alternative splicing Contact: lpachter@math.berkeley.edu},\r\n    Affiliation = {Affymetrix, 6550 Vallejo St Suite 100, Emeryville, CA 94608, USA Department of Mathematics, U.C. Berkeley, CA 94720, USA.},\r\n    Au = {Pachter L},\r\n    Author = {S Cawley and L Pachter},\r\n    Da = {20031009},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Edat = {2003/10/10 05:00},\r\n    Jid = {9808944},\r\n    Journal = {Bioinformatics},\r\n    Language = {eng},\r\n    Mhda = {2003/10/10 05:00},\r\n    Number = {1367-4803},\r\n    Own = {NLM},\r\n    Pages = {II36--II41},\r\n    Pl = {England},\r\n    Pmid = {14534169},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Sb = {IM},\r\n    So = {Bioinformatics 2004 Aug 12;20(12):1850-60. Epub 2004 Feb 26.},\r\n    Stat = {In-Data-Review},\r\n    Title = {{HMM} sampling and applications to gene finding and alternative splicing.},\r\n    Volume = {19 Suppl 2},\r\n    Year = {2003}}\r\n\r\n@article{Chakrabarti2004,\r\n    Abstract = {We introduce a novel genome browser application, the K-BROWSER, that allows intuitive visualization of biological information across an arbitrary number of multiply aligned genomes. In particular, the K-BROWSER simultaneously displays an arbitrary number of genomes both through overlaid annotations and predictions that describe their respective characteristics, and through the multiple alignment that describes their global relationship to one another. The browsing environment has been designed to allow users seamless access to information available in every genome and, furthermore, to allow easy navigation within and between genomes. As of the date of publication, the K-BROWSER has been set up on the human, mouse, and rat genomes.},\r\n    Affiliation = {Department of Computer Science, University of California, Berkeley, Berkeley, California 94720, USA.},\r\n    Aid = {14/4/716 {$[$}pii{$]$}},\r\n    Au = {Pachter L},\r\n    Author = {K Chakrabarti and L Pachter},\r\n    Da = {20040402},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Dcom = {20040505},\r\n    Edat = {2004/04/03 05:00},\r\n    Gr = {R02-HG02362-01/HG/NHGRI},\r\n    Jid = {9518021},\r\n    Journal = {Genome Research},\r\n    Keywords = {Animals and Computational Biology/methods/trends and Computer Graphics/*trends and Conserved Sequence/genetics and *Genome and Genome, Human and Humans and Mice and Rats and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, P.H.S. and Sequence Alignment/*methods/trends and Sequence Homology, Nucleic Acid and Software/*trends},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2004/05/07 05:00},\r\n    Number = {4},\r\n    Own = {NLM},\r\n    Pages = {716--20},\r\n    Pl = {United States},\r\n    Pmid = {15060015},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Sb = {IM},\r\n    So = {Nucleic Acids Res 2004 Jul 1;32(Web Server issue):W273-9.},\r\n    Stat = {MEDLINE},\r\n    Title = {Visualization of multiple genome annotations and alignments with the {K-BROWSER}.},\r\n    Volume = {14},\r\n    Year = {2004}}\r\n\r\n@article{Chargaff1950,\r\n    Author = {E Chargaff},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Experientia},\r\n    Pages = {201--209},\r\n    Title = {Chemical specificity of nucleic acids and mechanism for the enzymatic degradation},\r\n    Volume = {6},\r\n    Year = {1950}}\r\n\r\n@inproceedings{Chazelle1991,\r\n    Author = {B Chazelle},\r\n    Booktitle = {Proceedings of the 32nd IEEE Symposium on Foundations of Computer Science},\r\n    Pages = {29--38},\r\n    Title = {An Optimal Convex Hull Algorithm and New Results on Cuttings},\r\n    Year = {1991}}\r\n\r\n@article{Chazelle1993,\r\n    Author = {B Chazelle},\r\n    Journal = {Discrete Computational Geometry},\r\n    Pages = {377--409},\r\n    Title = {An optimal convex hull algorithm in any fixed dimension},\r\n    Volume = {10},\r\n    Year = {1993}}\r\n\r\n@Article{Chepoi1997,\r\n  author = \t {V Chepoi and B Fichet},\r\n  title = \t {Recognition of Robinsonian dissimilarities},\r\n  journal = \t {Journal of Classification},\r\n  year = \t {1997},\r\n  OPTkey = \t {},\r\n  volume = \t {14},\r\n  OPTnumber = \t {2},\r\n  pages = \t {1432--1343},\r\n  OPTmonth = \t {January},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Chepoi1998,\r\n  author = \t {V Chepoi and B Fichet},\r\n  title = \t {A note on circular decomposable metrics},\r\n  journal = \t {Geometrica Dedicata},\r\n  year = \t {1998},\r\n  OPTkey = \t {},\r\n  volume = \t {69},\r\n  OPTnumber = \t {},\r\n  pages = \t {237--240},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@InProceedings{Chiaromonte2002,\r\n  author =   {F Chiaromonte and VB Yap and W Miller},\r\n  title =    {Scoring pairwise genomic sequence alignments},\r\n  OPTcrossref =  {},\r\n  OPTkey =   {},\r\n  booktitle = {Proceedings of the Pacific Symposium on Biocomputing},\r\n  pages =    {115--126},\r\n  year =     {2002},\r\n  OPTeditor =    {},\r\n  OPTvolume =    {},\r\n  OPTnumber =    {},\r\n  OPTseries =    {},\r\n  OPTaddress =   {},\r\n  OPTmonth =     {},\r\n  OPTorganization = {},\r\n  OPTpublisher = {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n@incollection{Chickering1996,\r\n    Author = {DM Chickering},\r\n    Booktitle = {Learning from Data: Artificial Intelligence and Statistics V},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Editor = {D Fisher and H-J Lenz},\r\n    Publisher = {Springer Verlag},\r\n    Title = {Learning {B}ayesian Networks is {NP}-complete},\r\n    Year = {1996}}\r\n\r\n@article{Chor2000,\r\n    Author = {B Chor and MD Hendy and BR Holland and D Penny},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {1529--1541},\r\n    Title = {Multiple maxima of likelihood in phylogenetic trees: an analytic approach},\r\n    Volume = {17},\r\n    Year = {2000}}\r\n\r\n@InProceedings{Christopher1996,\r\n  author = \t {G Christopher and M Farach and M Trick},\r\n  title = \t {The structure of circular decomposable metrics},\r\n  OPTcrossref =  {},\r\n  OPTkey = \t {},\r\n  booktitle = {Lecture Notes in Computer Science},\r\n  pages = \t {406--418},\r\n  year = \t {1996},\r\n  OPTeditor = \t {},\r\n  volume = \t {1136},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTaddress = \t {},\r\n  OPTmonth = \t {},\r\n  OPTorganization = {},\r\n  publisher = {Springer, New York},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@PhdThesis{Christopher1997,\r\n  author = \t {G Christopher},\r\n  title = \t {Structure and applications of totally decomposable metrics},\r\n  school = \t {Carnegie Mellon University},\r\n  year = \t {1997},\r\n  OPTkey = \t {},\r\n  OPTtype = \t {},\r\n  OPTaddress = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Cohen1993,\r\n    Author = {JE Cohen and UG Rothblum},\r\n    Coden = {LAAPAW},\r\n    Fjournal = {Linear Algebra and its Applications},\r\n    Issn = {0024-3795},\r\n    Journal = {Linear Algebra Appl.},\r\n    Mrclass = {15A48 (15A23)},\r\n    Mrnumber = {MR1230356 (94i:15015)},\r\n    Mrreviewer = {Thomas L. Markham},\r\n    Pages = {149--168},\r\n    Title = {Nonnegative ranks, decompositions, and factorizations of nonnegative matrices},\r\n    Volume = {190},\r\n    Year = {1993}}\r\n\r\n@article{Cohen2004,\r\n    Affiliation = {Laboratory of Populations, Rockefeller and Columbia Universities, New York, New York, USA. cohen@rockefeller.edu},\r\n    Aid = {10.1371/journal.pbio.0020439 {$[$}doi{$]$}},\r\n    Au = {Cohen JE},\r\n    Author = {JE Cohen},\r\n    Da = {20041214},\r\n    Edat = {2004/12/15 09:00},\r\n    Jid = {101183755},\r\n    Journal = {PLoS Biol},\r\n    Language = {eng},\r\n    Mhda = {2004/12/15 09:00},\r\n    Number = {12},\r\n    Own = {NLM},\r\n    Pages = {e439},\r\n    Pl = {United States},\r\n    Pmid = {15597117},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Sb = {IM},\r\n    Stat = {In-Process},\r\n    Title = {Mathematics is biology's next microscope, only better; biology is mathematics' next physics, only better.},\r\n    Volume = {2},\r\n    Year = {2004}}\r\n\r\n@Misc{Concorde,\r\n  key = \t {Concorde},\r\n  author = \t {D Applegate and R Bixby and V Chvatal and W Cook},\r\n  title = \t {{The Concorde TSP solver}},\r\n howpublished = {{\\tt http://www.tsp.gatech.edu/concorde.html/}},\r\n  OPTmonth = \t {},\r\n  OPTyear = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@InCollection{Contois2005,\r\n  author = \t {M Contois and D Levy},\r\n  title = \t {Small trees and generalized neighbor-joining},\r\n  booktitle = \t {Algebraic Statistics for Computational Biology},\r\n  OPTcrossref =  {},\r\n  OPTkey = \t {},\r\n  pages = \t {333--344},\r\n  publisher = {Cambridge University Press},\r\n  year = \t {2005},\r\n  editor = \t {L Pachter and B Sturmfels},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTtype = \t {},\r\n  chapter = \t {18},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Couronne2003,\r\n    Abstract = {The availability of the assembled mouse genome makes possible, for the first time, an alignment and comparison of two large vertebrate genomes. We investigated different strategies of alignment for the subsequent analysis of conservation of genomes that are effective for assemblies of different quality. These strategies were applied to the comparison of the working draft of the human genome with the Mouse Genome Sequencing Consortium assembly, as well as other intermediate mouse assemblies. Our methods are fast and the resulting alignments exhibit a high degree of sensitivity, covering more than 90% of known coding exons in the human genome. We obtained such coverage while preserving specificity. With a view towards the end user, we developed a suite of tools and Web sites for automatically aligning and subsequently browsing and working with whole-genome comparisons. We describe the use of these tools to identify conserved non-coding regions between the human and mouse genomes, some of which have not been identified by other methods.},\r\n    Affiliation = {Lawrence Berkeley National Laboratory, Berkeley, California 94720, USA.},\r\n    Aid = {10.1101/gr.762503 {$[$}doi{$]$}},\r\n    Au = {Pachter L},\r\n    Author = {O Couronne and A Poliakov and N Bray and T Ishkhanov and D Ryaboy and E Rubin and L Pachter and I Dubchak},\r\n    Da = {20030116},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Dcom = {20030317},\r\n    Edat = {2003/01/17 04:00},\r\n    Jid = {9518021},\r\n    Journal = {Genome Research},\r\n    Keywords = {Algorithms and Animals and Chromosomes/genetics and Chromosomes, Human/genetics and Comparative Study and Computer Communication Networks/instrumentation and Databases, Genetic and *Genome and *Genome, Human and Humans and Internet/instrumentation and Mice and *Research Design and Research Support, U.S. Gov't, Non-P.H.S. and Research Support, U.S. Gov't, P.H.S. and Sequence Alignment/*instrumentation/*methods and Software},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2003/03/18 04:00},\r\n    Number = {1},\r\n    Own = {NLM},\r\n    Pages = {73--80},\r\n    Pl = {United States},\r\n    Pmid = {12529308},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Sb = {IM},\r\n    So = {Genome Res 2003 Jan;13(1):97-102.},\r\n    Stat = {MEDLINE},\r\n    Title = {Strategies and tools for whole-genome alignments.},\r\n    Volume = {13},\r\n    Year = {2003}}\r\n\r\n@book{Cover1991,\r\n    Author = {TM Cover and JA Thomas},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Wiley},\r\n    Title = {Elements of Information Theory},\r\n    Year = {1991}}\r\n\r\n@book{Cowell1999,\r\n    Address = {New York},\r\n    Author = {RG Cowell and AP Dawid and SL Lauritzen and DJ Spiegelhalter},\r\n    Publisher = {Springer-Verlag},\r\n    Series = {Statistics for Engineering and Information Sciences},\r\n    Title = {Probabilistic Networks and Expert Systems},\r\n    Year = {1999}}\r\n\r\n@book{Cox1997,\r\n    Address = {New York},\r\n    Author = {D Cox and J Little and D O'Shea},\r\n    Date-Modified = {2005-02-05 13:01:41 -0800},\r\n    Edition = {Second},\r\n    Isbn = {0-387-94680-2},\r\n    Mrclass = {13P10 (13-01 14-01 14Qxx 68Q40)},\r\n    Mrnumber = {MR1417938 (97h:13024)},\r\n    Note = {An introduction to computational algebraic geometry and commutative algebra},\r\n    Pages = {xiv+536},\r\n    Publisher = {Springer-Verlag},\r\n    Series = {Undergraduate Texts in Mathematics},\r\n    Title = {Ideals, Varieties, and Algorithms},\r\n    Year = {1997}}\r\n\r\n@article{Craciun2005,\r\n    Author = {G Craciun and M Feinberg},\r\n    Journal = {SIAM Journal of Applied Mathematics},\r\n    Note = {To appear},\r\n    Title = {Multiple Equilibria in Complex Chemical Reaction Networks: I. The Injectivity Property},\r\n    Year = {2005}}\r\n\r\n@article{Cuyt2001,\r\n    Author = {A Cuyt and B Verdonk and S Becuwe and P Kuterna},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Computing},\r\n    Pages = {309--320},\r\n    Title = {A remarkable example of catastrophic cancellation unraveled},\r\n    Volume = {66},\r\n    Year = {2001}}\r\n\r\n@article{Darling2004,\r\n    Author = {ACE Darling and B Mau and FR Blattner and NT Perna},\r\n    Journal = {Genome Research},\r\n    Pages = {1394--1403},\r\n    Title = {{Mauve: multiple alignment of conserved genomic sequence with rearrangements}},\r\n    Volume = {14},\r\n    Year = {2004}}\r\n\r\n\r\n\r\n@book{Darwin1859,\r\n    Author = {C Darwin},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {John Murray, London},\r\n    Title = {On the Origin of Species by Means of Natural Selection, or the Preservation of Favoured Races in the Struggle for Life},\r\n    Year = {1859}}\r\n\r\n@book{Davey2002,\r\n    Address = {New York},\r\n    Author = {BA Davey and HA Priestley},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Edition = {Second},\r\n    Publisher = {Cambridge University Press},\r\n    Title = {Introduction to Lattices and Order},\r\n    Year = {2002}}\r\n\r\n@book{DeConcini1982,\r\n    Address = {Paris},\r\n    Author = {C DeConcini and D Eisenbud and C Procesi},\r\n    Mrclass = {13B99 (13-04 13D10 14M15)},\r\n    Mrnumber = {MR680936 (85d:13009)},\r\n    Mrreviewer = {Melvin Hochster},\r\n    Note = {With a French summary},\r\n    Pages = {87},\r\n    Publisher = {Soci\\'et\\'e Math\\'ematique de France},\r\n    Series = {Ast\\'erisque},\r\n    Title = {Hodge algebras},\r\n    Volume = {91},\r\n    Year = {1982}}\r\n\r\n@book{DeGroot1970,\r\n    Address = {New York},\r\n    Author = {MH DeGroot},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {McGraw-Hill},\r\n    Title = {Optimal Statistical Decisions},\r\n    Year = {1970}}\r\n\r\n@Article{Deineko1998,\r\n  author = \t {VG Deineko and R Rudolf and GJ Woeginger},\r\n  title = \t {Sometimes traveling is easy: the master tour problem},\r\n  journal = \t {SIAM Journal of Discrete Mathematics},\r\n  year = \t {1998},\r\n  OPTkey = \t {},\r\n  volume = \t {11},\r\n  OPTnumber = \t {1},\r\n  pages = \t {81--93},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Delcher1999,\r\n    Author = {AL Delcher and S Kasif and RD Fleischmann and J Peterson and O White and AL Salzberg},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Nucleic Acids Research},\r\n    Pages = {2369--2376},\r\n    Title = {Alignment of whole genomes},\r\n    Volume = {27},\r\n    Year = {1999}}\r\n\r\n@book{Demmel1997,\r\n    Address = {Philadelphia, PA},\r\n    Author = {JW Demmel},\r\n    Isbn = {0-89871-389-7},\r\n    Mrclass = {65-01 (65Fxx)},\r\n    Mrnumber = {MR1463942 (98m:65001)},\r\n    Mrreviewer = {William W. Hager},\r\n    Pages = {xii+419},\r\n    Publisher = {Society for Industrial and Applied Mathematics (SIAM)},\r\n    Title = {Applied Numerical Linear Algebra},\r\n    Year = {1997}}\r\n\r\n@article{Dempster1977,\r\n    Author = {AP Dempster and NM Laird and DB Rubin},\r\n    Journal = {Journal of the Royal Statistical Society},\r\n    Pages = {1--38},\r\n    Title = {Maximum Likelihood from Incomplete Data via the {EM} Algorithm},\r\n    Volume = {39},\r\n    Year = {1977}}\r\n\r\n@article{Dermitzakis2003,\r\n    Author = {ET Dermitzakis and A Reymond and N Scamuffa and C Ucla and E Kirkness and C Rossier and SE Antonarakis},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Science},\r\n    Pages = {1033--1035},\r\n    Title = {Evolutionary Discrimination of Mammalian Conserved Non-Genic Sequences ({CNG}s)},\r\n    Volume = {302},\r\n    Year = {2003}}\r\n\r\n@article{Desper1999,\r\n    Author = {R Desper and F Jiang and O-P Kallioniemi and H Moch and CH Papadimitriou and AA Sch{\\\"a}ffer},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Computational Biology},\r\n    Number = {1},\r\n    Pages = {37--51},\r\n    Title = {Inferring tree models for oncogenesis from comparative genome hybridization data},\r\n    Volume = {6},\r\n    Year = {1999}}\r\n\r\n@Article{Desper2002,\r\n  author = \t {R Desper and O Gascuel},\r\n  title = \t {Fast and accurate phylogeny reconstruction algorithms based on the minimum-evolution principle},\r\n  journal = \t {Journal of Computational Biology},\r\n  year = \t {2002},\r\n  OPTkey = \t {},\r\n  volume = \t {19},\r\n  number = \t {5},\r\n  pages = \t {687--705},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Desper2004,\r\n  author = \t {R Desper and O Gascuel},\r\n  title = \t {Theoretical foundation of the balanced minimum evolution method of phylogenetic inference and its relationship to weighted least-squares tree fitting},\r\n  journal = \t {Molecular Biology and Evolution},\r\n  year = \t {2004},\r\n  OPTkey = \t {},\r\n  volume = \t {21},\r\n  OPTnumber = \t {},\r\n  pages = \t {587--598},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@InCollection{Desper2005,\r\n  author =   {R Desper and O Gascuel},\r\n  title =    {The minimum evolution distance-based approach to phylogenetic inference},\r\n  booktitle =    {Mathematics of Evolution and Phylogeny},\r\n  OPTcrossref =  {},\r\n  OPTkey =   {},\r\n  OPTpages =     {},\r\n  publisher = {Oxford University Press},\r\n  year =      {2005},\r\n  editor =   {O Gascuel},\r\n  OPTvolume =    {},\r\n  OPTnumber =    {},\r\n  OPTseries =    {},\r\n  OPTtype =      {},\r\n  OPTchapter =   {},\r\n  OPTaddress =   {},\r\n  OPTedition =   {},\r\n  OPTmonth =     {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n@Article{Devadoss1999,\r\n  author = \t {S Devadoss},\r\n  title = \t {Tessellations of moduli spaces and the mosaic operad},\r\n  journal = \t {Contemporary mathematics},\r\n  year = \t {1999},\r\n  OPTkey = \t {},\r\n  volume = \t {239},\r\n  OPTnumber = \t {},\r\n  pages = \t {91--114},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Devadoss2004,\r\n  author = \t {S Devadoss},\r\n  title = \t {Combinatorial equivalence of real moduli spaces},\r\n  journal = \t {Notices of the American Mathematical Society},\r\n  year = \t {2004},\r\n  OPTkey = \t {},\r\n  volume = \t {51},\r\n  OPTnumber = \t {},\r\n  pages = \t {620--628},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Develin2003,\r\n    Author = {M Develin and F Santos and B Sturmfels},\r\n    Journal = {MSRI Proceedings},\r\n    Note = {To appear},\r\n    Title = {On the tropical rank of a matrix},\r\n    Year = {2003}}\r\n\r\n@article{Develin2004,\r\n    Author = {M Develin and B Sturmfels},\r\n    Date-Modified = {2005-02-05 12:58:09 -0800},\r\n    Fjournal = {Documenta Mathematica},\r\n    Issn = {1431-0643},\r\n    Journal = {Documenta Mathematica},\r\n    Mrclass = {52A30 (52B10)},\r\n    Mrnumber = {MR2054977},\r\n    Pages = {1--27 (electronic)},\r\n    Title = {Tropical convexity},\r\n    Volume = {9},\r\n    Year = {2004}}\r\n\r\n@article{Dewey2004,\r\n    Abstract = {We describe a new method for simultaneously identifying novel homologous genes with identical structure in the human, mouse, and rat genomes by combining pairwise predictions made with the SLAM gene-finding program. Using this method, we found 3698 gene triples in the human, mouse, and rat genomes which are predicted with exactly the same gene structure. We show, both computationally and experimentally, that the introns of these triples are predicted accurately as compared with the introns of other ab initio gene prediction sets. Computationally, we compared the introns of these gene triples, as well as those from other ab initio gene finders, with known intron annotations. We show that a unique property of SLAM, namely that it predicts gene structures simultaneously in two organisms, is key to producing sets of predictions that are highly accurate in intron structure when combined with other programs. Experimentally, we performed reverse transcription-polymerase chain reaction (RT-PCR) in both the human and rat to test the exon pairs flanking introns from a subset of the gene triples for which the human gene had not been previously identified. By performing RT-PCR on orthologous introns in both the human and rat genomes, we additionally explore the validity of using RT-PCR as a method for confirming gene predictions.},\r\n    Affiliation = {Department of Electrical Engineering, University of California-Berkeley, Berkeley, California 94720, USA.},\r\n    Aid = {14/4/661 {$[$}pii{$]$}},\r\n    Au = {Pachter L},\r\n    Author = {C Dewey and JQ Wu and S Cawley and M Alexandersson and R Gibbs and L Pachter},\r\n    Da = {20040402},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20040505},\r\n    Edat = {2004/04/03 05:00},\r\n    Gr = {R01 HG2362-2/HG/NHGRI},\r\n    Jid = {9518021},\r\n    Journal = {Genome Research},\r\n    Keywords = {Animals and Chromosome Mapping/methods and Comparative Study and Computational Biology/methods and Databases, Genetic and Exons/genetics and Genes, Structural/*genetics and Genome and Genome, Human and Humans and Introns/genetics and Mice and Predictive Value of Tests and Rats and Research Support, U.S. Gov't, P.H.S. and Sequence Homology, Nucleic Acid and Software},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2004/05/07 05:00},\r\n    Number = {4},\r\n    Own = {NLM},\r\n    Pages = {661--4},\r\n    Pl = {United States},\r\n    Pmid = {15060007},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Sb = {IM},\r\n    So = {Genome Res 2004 Apr;14(4):693--9.},\r\n    Stat = {MEDLINE},\r\n    Title = {Accurate identification of novel human genes through simultaneous gene prediction in human, mouse, and rat.},\r\n    Volume = {14},\r\n    Year = {2004}}\r\n\r\n@misc{Dewey2005,\r\n    Author = {C Dewey},\r\n    Howpublished = {Software available at \\url{http://hanuman.math.berkeley.edu/~cdewey/mercator/}},\r\n    Title = {{MERCATOR}: multiple whole-genome orthology map construction},\r\n    Year = {2005}}\r\n\r\n@book{Deza1997,\r\n    Address = {Berlin},\r\n    Author = {MM Deza and M Laurent},\r\n    Isbn = {3-540-61611-X},\r\n    Mrclass = {52-02 (05B30 05C12 51K05 52B12 52C07 68R05 90C28)},\r\n    Mrnumber = {MR1460488 (98g:52001)},\r\n    Mrreviewer = {Alexander I. Barvinok},\r\n    Pages = {xii+587},\r\n    Publisher = {Springer-Verlag},\r\n    Series = {Algorithms and Combinatorics},\r\n    Title = {Geometry of Cuts and Metrics},\r\n    Volume = {15},\r\n    Year = {1997}}\r\n\r\n@Book{Deza2006,\r\n  author = \t {E Deza and MM Deza},\r\n  ALTeditor = \t {},\r\n  title = \t {Dictionary of Distances},\r\n  publisher = \t {Elsevier},\r\n  year = \t {2006},\r\n  OPTkey = \t {},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@InBook{Diday1986,\r\n  author = \t {E Diday},\r\n  editor = \t {J De Leeuw et al.},\r\n  title = \t {Multidimensional data analysis},\r\n  chapter = \t {Orders and overlapping clusters by pyramids},\r\n  publisher = \t {DWO Press, Leiden},\r\n  year = \t {1986},\r\n  OPTkey = \t {},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTtype = \t {},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  pages = \t {201--234},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Dilworth1950,\r\n  author = \t {RP Dilworth},\r\n  title = \t {A decomposition theorem for partially ordered sets},\r\n  journal = \t {The Annals of Mathematics},\r\n  year = \t {1950},\r\n  OPTkey = \t {},\r\n  volume = \t {51},\r\n  OPTnumber = \t {},\r\n  pages = \t {161--166},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Douzery2003,\r\n    Author = {EJP Douzery and F Delsuc and MJ Stanhope and D Huchon},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {201-213},\r\n    Title = {Local molecular clocks in three nuclear genes: divergence ages of rodents and other mammals, and incompatibility between fossil calibrations},\r\n    Volume = {57},\r\n    Year = {2003}}\r\n\r\n@Article{Dress1996,\r\n  author = \t {A Dress and V Moulton and W Terhalle},\r\n  title = \t {T-theory: an overview},\r\n  journal = \t {European Journal Combinatorics},\r\n  year = \t {1996},\r\n  OPTkey = \t {},\r\n  volume = \t {17},\r\n  OPTnumber = \t {},\r\n  pages = \t {161--175},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@InCollection{Dress1997,\r\n  author = \t {A Dress},\r\n  title = \t {Towards a theory of holistic clustering},\r\n  booktitle = \t {Mathematical Hierarchies and Biology},\r\n  OPTcrossref =  {},\r\n  OPTkey = \t {},\r\n  OPTpages = \t {},\r\n  publisher = {DIMACS},\r\n  year = \t {1997},\r\n  OPTeditor = \t {},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTtype = \t {},\r\n  OPTchapter = \t {},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@inproceedings{Dress1998,\r\n    Author = {A Dress and W Terhalle},\r\n    Booktitle = {Proceedings of the International Congress of Mathematicians},\r\n    Fjournal = {Documenta Mathematica},\r\n    Issn = {1431-0643},\r\n    Journal = {Documenta Mathematica},\r\n    Mrclass = {05B35 (05C05 92B10 92D15)},\r\n    Mrnumber = {MR1648188 (99k:05051)},\r\n    Mrreviewer = {Charles A. Semple},\r\n    Number = {Extra Vol. III},\r\n    Pages = {565--574 (electronic)},\r\n    Series = {Vol. III (Berlin, 1998)},\r\n    Title = {The tree of life and other affine buildings},\r\n    Year = {1998}}\r\n\r\n@article{Dress2002,\r\n    Author = {A Dress and JH Koolen and V Moulton},\r\n    Fjournal = {European Journal of Combinatorics},\r\n    Issn = {0195-6698},\r\n    Journal = {European Journal of Combinatorics},\r\n    Mrclass = {52C30 (51M10)},\r\n    Mrnumber = {MR1931939 (2003h:52024)},\r\n    Number = {5},\r\n    Pages = {549--557},\r\n    Title = {On line arrangements in the hyperbolic plane},\r\n    Volume = {23},\r\n    Year = {2002}}\r\n\r\n@Article{Dress2004,\r\n  author = \t {A Dress and DH Huson},\r\n    Journal = {IEEE/ACM Transactions in Computational Biology and Bioinformatics},\r\n  title = \t {Constructing splits graphs},\r\n  year = \t {2004},\r\n  OPTkey = \t {},\r\n  volume = \t {1},\r\n  OPTnumber = \t {3},\r\n  pages = \t {109--115},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Dress2007,\r\n  author = \t {A Dress and KT Huber and V Moulton},\r\n  title = \t {Some uses of the Farris transform in mathematics and phylogenetics-- a review},\r\n  journal = \t {Annals of Combinatorics},\r\n  year = \t {2007},\r\n  OPTkey = \t {},\r\n  volume = \t {11},\r\n  OPTnumber = \t {},\r\n  pages = \t {1--37},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Drysdale2005,\r\n  author =   {RA Drysdale and MA Crosby and {The Flybase Consortium}},\r\n  title =    {{Flybase: Genes and gene models}},\r\n  journal =      {Nucleic Acids Research},\r\n  year =     {2005},\r\n  OPTkey =   {},\r\n  volume =   {33},\r\n  OPTnumber =    {},\r\n  pages =    {D390--D395},\r\n  OPTmonth =     {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n@article{Dubchak2000,\r\n    Abstract = {Human and mouse genomic sequence comparisons are being increasingly used to search for evolutionarily conserved gene regulatory elements. Large-scale human-mouse DNA comparison studies have discovered numerous conserved noncoding sequences of which only a fraction has been functionally investigated A question therefore remains as to whether most of these noncoding sequences are conserved because of functional constraints or are the result of a lack of divergence time.},\r\n    Affiliation = {Center for Bioinformatics and Computational Genomics, Lawrence Berkeley National Laboratory, Berkeley, California 94720, USA.},\r\n    Au = {Frazer KA},\r\n    Author = {I Dubchak and M Brudno and GG Loots and L Pachter and C Mayor and EM Rubin and KA Frazer},\r\n    Da = {20001017},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20001017},\r\n    Edat = {2000/09/14 11:00},\r\n    Gr = {GM-5748202/GM/NIGMS},\r\n    Jid = {9518021},\r\n    Journal = {Genome Research},\r\n    Keywords = {Animals and Comparative Study and Conserved Sequence/*genetics and Dogs and Humans and Mice and Molecular Sequence Data and Research Support, U.S. Gov't, Non-P.H.S. and Research Support, U.S. Gov't, P.H.S. and *Sequence Alignment and Species Specificity and Untranslated Regions/*genetics/isolation \\& purification},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2000/10/21 11:01},\r\n    Number = {9},\r\n    Own = {NLM},\r\n    Pages = {1304--6},\r\n    Pl = {UNITED STATES},\r\n    Pmid = {10984448},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (Untranslated Regions)},\r\n    Sb = {IM},\r\n    Si = {GENBANK/AF276990},\r\n    So = {Bioinformatics 2000 Nov;16(11):1046-7.},\r\n    Stat = {MEDLINE},\r\n    Title = {Active conservation of noncoding sequences revealed by three-way species comparisons.},\r\n    Volume = {10},\r\n    Year = {2000}}\r\n\r\n@article{Dubchak2002,\r\n    Abstract = {The explosion in genomic sequence available in public databases has resulted in an unprecedented opportunity for computational whole genome analyses. A number of promising comparative-based approaches have been developed for gene finding, regulatory element discovery and other purposes, and it is clear that these tools will play a fundamental role in analysing the enormous amount of new data that is currently being generated. The synthesis of computationally intensive comparative computational approaches with the requirement for whole genome analysis represents both an unprecedented challenge and opportunity for computational scientists. We focus on a few of these challenges, using by way of example the problems of alignment, gene finding and regulatory element discovery, and discuss the issues that have arisen in attempts to solve these problems in the context of whole genome analysis pipelines.},\r\n    Affiliation = {Lawrence Berkeley National Laboratory, National Energy Resesarch Scientific Computing Center, CA 94720, USA. ildubchak@lbl.gov},\r\n    Au = {Pachter L},\r\n    Author = {I Dubchak and L Pachter},\r\n    Da = {20020510},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Dcom = {20021024},\r\n    Edat = {2002/05/11 10:00},\r\n    Jid = {100912837},\r\n    Journal = {Brief Bioinform},\r\n    Keywords = {Comparative Study and *Computational Biology and *Genome and Regulatory Sequences, Nucleic Acid and Research Support, U.S. Gov't, P.H.S.},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2002/10/31 04:00},\r\n    Number = {1},\r\n    Own = {NLM},\r\n    Pages = {18--22},\r\n    Pl = {England},\r\n    Pmid = {12002220},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Sb = {IM},\r\n    So = {J Comput Biol 2002;9(2):389-99.},\r\n    Stat = {MEDLINE},\r\n    Title = {The computational challenges of applying comparative-based computational methods to whole genomes.},\r\n    Volume = {3},\r\n    Year = {2002}}\r\n\r\n@Article{Dunn2005,\r\n  author = \t {M Dunn and A Terrill and G Reesnik and RA Foley and SC Levinson},\r\n  title = \t {Structural phylogenetics and reconstruction of ancient language history},\r\n  journal = \t {Science},\r\n  year = \t {2005},\r\n  OPTkey = \t {},\r\n  OPTvolume = \t {309},\r\n  OPTnumber = \t {},\r\n  pages = \t {2072--2075},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n\r\n@book{Durbin1998,\r\n    Author = {R Durbin and S Eddy and A Korgh and G Mitchison},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Cambridge University Press},\r\n    Title = {{Biological Sequence Analysis: Probabilistic Models of Proteins and Nucleic Acids}},\r\n    Year = {1998}}\r\n\r\n@inproceedings{Eddy1995,\r\n    Author = {SR Eddy},\r\n    Booktitle = {Proceedings Intelligent Systems in Molecular Biology},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Title = {Multiple alignment using hidden {M}arkov models},\r\n    Year = {1995}}\r\n\r\n@book {Edelsbrunner1987,\r\n    AUTHOR = {H Edelsbrunner},\r\n     TITLE = {Algorithms in combinatorial geometry},\r\n    SERIES = {EATCS Monographs on Theoretical Computer Science},\r\n    VOLUME = {10},\r\n PUBLISHER = {Springer-Verlag},\r\n   ADDRESS = {Berlin},\r\n      YEAR = {1987},\r\n     PAGES = {xvi+423},\r\n      ISBN = {3-540-13722-X},\r\n   MRCLASS = {68U05 (52-04 68Q25)},\r\n  MRNUMBER = {MR904271 (89a:68205)},\r\nMRREVIEWER = {D. T. Lee}}\r\n\r\n@article{Eichler2003,\r\n    Author = {EE Eichler and D Sankoff},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Science},\r\n    Pages = {793--797},\r\n    Title = {Structural dynamics of eukaryotic chromosome evolution},\r\n    Volume = {301},\r\n    Year = {2003}}\r\n\r\n@book{Eisenbud2002,\r\n    Address = {Berlin},\r\n    Date-Modified = {2005-02-05 12:58:09 -0800},\r\n    Editor = {D Eisenbud and DR Grayson and M Stillman},\r\n    Isbn = {3-540-42230-7},\r\n    Mrclass = {14-04 (13-04 13P10 14Q99 68W30)},\r\n    Mrnumber = {MR1949544 (2004b:14002)},\r\n    Mrreviewer = {Luis Miguel Pardo},\r\n    Pages = {xvi+329},\r\n    Publisher = {Springer-Verlag},\r\n    Series = {Algorithms and Computation in Mathematics},\r\n    Title = {Computations in algebraic geometry with {M}acaulay 2},\r\n    Volume = {8},\r\n    Year = {2002}}\r\n\r\n@InProceedings{Elias2005,\r\n  author =   {I Elias and J Lagergren},\r\n  title =    {Fast neighbor joining},\r\n  OPTcrossref =  {},\r\n  OPTkey =   {},\r\n  booktitle = {Proceedings of the International Colloquium on\r\n                  Automata, Languages and Programming (ICALP '05)},\r\n  OPTpages =     {},\r\n  year =     {2005},\r\n  OPTeditor =    {},\r\n  OPTvolume =    {},\r\n  OPTnumber =    {},\r\n  OPTseries =    {},\r\n  OPTaddress =   {},\r\n  OPTmonth =     {},\r\n  OPTorganization = {},\r\n  OPTpublisher = {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n@article{Encode2004,\r\n    Abstract = {The ENCyclopedia Of DNA Elements (ENCODE) Project aims to identify all functional elements in the human genome sequence. The pilot phase of the Project is focused on a specified 30 megabases (approximately 1%) of the human genome sequence and is organized as an international consortium of computational and laboratory-based scientists working to develop and apply high-throughput approaches for detecting all sequence elements that confer biological function. The results of this pilot phase will guide future efforts to analyze the entire human genome.},\r\n    Aid = {10.1126/science.1105136 {$[$}doi{$]$}},\r\n    Author = {{ENCODE} Project Consortium},\r\n    Cn = {ENCODE Project Consortium.},\r\n    Da = {20041022},\r\n    Date-Modified = {2005-02-05 12:50:27 -0800},\r\n    Dcom = {20041122},\r\n    Edat = {2004/10/23 09:00},\r\n    Jid = {0404511},\r\n    Journal = {Science},\r\n    Key = {ENCODE},\r\n    Keywords = {Access to Information and Animals and *Computational Biology and Conserved Sequence and Databases, Nucleic Acid and Evolution, Molecular and *Genome, Human and *Genomics and Humans and Information Dissemination and Internet and National Institutes of Health (U.S.) and Pilot Projects and Proteins/genetics and Publishing and Regulatory Sequences, Nucleic Acid and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, P.H.S. and Sequence Analysis, DNA and United States},\r\n    Language = {eng},\r\n    Mhda = {2004/12/16 09:00},\r\n    Number = {5696},\r\n    Own = {NLM},\r\n    Pages = {636--40},\r\n    Pl = {United States},\r\n    Pmid = {15499007},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (Proteins)},\r\n    Sb = {IM},\r\n    So = {Nature 2003 Aug 14;424(6950):788-93.},\r\n    Stat = {MEDLINE},\r\n    Title = {{The ENCODE (ENCyclopedia Of DNA Elements) Project}},\r\n    Volume = {306},\r\n    Year = {2004}}\r\n\r\n@Article{Erdos1999,\r\n  author = {PL Erd\\\"{o}s and MA Steel and LA Sz\\'{e}kely and TJ\r\n                  Warnow},\r\n  title = {A few logs suffice to build (almost) all trees. {I}},\r\n  journal = {Random Structures and Algorithms},\r\n  year = {1999},\r\n  OPTkey = {},\r\n  volume = {14},\r\n  number = {2},\r\n  pages = {153--184},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@Article{Eriksson2008,\r\n  author = \t {N Eriksson and L Pachter and Y Mitsuya and S-Y Rhee and C Wang and B Gharizadeh and M Ronaghi and RW Shafer and N Beerenwinkel},\r\n  title = \t {Viral population estimation using pyrosequencing},\r\n  journal = \t {PLoS Computational Biology},\r\n  year = \t {2008},\r\n  OPTkey = \t {},\r\n  volume = \t {4},\r\n  OPTnumber = \t {5},\r\n  pages = \t {e1000074},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Evans1993,\r\n    Author = {S Evans and T Speed},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {The Annals of Statistics},\r\n    Pages = {355--377},\r\n    Title = {Invariants of some probability models used in phylogenetic inference},\r\n    Volume = {21},\r\n    Year = {1993}}\r\n\r\n@book{Ewens2005,\r\n    Address = {New York},\r\n    Author = {WJ Ewens and GR Grant},\r\n    Edition = {Second},\r\n    Isbn = {0-387-40082-6},\r\n    Mrclass = {92B15 (60J10 62-01 62F10 62F15 62P10)},\r\n    Mrnumber = {MR2107608},\r\n    Pages = {xx+597},\r\n    Publisher = {Springer-Verlag},\r\n    Series = {Statistics for Biology and Health},\r\n    Title = {Statistical Methods in Bioinformatics: An Introduction},\r\n    Year = {2005}}\r\n\r\n@article{Faith1992,\r\n    Author = {DP Faith},\r\n    Journal = {Biological Conservation},\r\n    Pages = {1--10},\r\n    Title = {Conservation evaluation and phylogenetic diversity},\r\n    Volume = {61},\r\n    Year = {1992}}\r\n\r\n@article{Farris1972,\r\n    Author = {JS Farris},\r\n    Date-Modified = {2005-03-01 20:04:38 -0500},\r\n    Journal = {American Naturalist},\r\n    Pages = {645--668},\r\n    Title = {Estimating phylogenetic trees from distance matrices},\r\n    Volume = {106},\r\n    Year = {1972}}\r\n\r\n\r\n\r\n@InCollection{Farris1977,\r\n  author = \t {JS Farris},\r\n  title = \t {On the phenetic approach to vertebrate classification},\r\n  booktitle = \t {Major patterns in vertebrate evolution},\r\n  OPTcrossref =  {},\r\n  OPTkey = \t {},\r\n  pages = \t {823--950},\r\n  publisher = {Plenum, New York},\r\n  year = \t {1977},\r\n  OPTeditor = \t {},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTtype = \t {},\r\n  OPTchapter = \t {},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Farris1996,\r\n  author = {JS Farris and VA Albert and M K\\\"{a}llersj\\\"{o} and D\r\n                  Lipscomb and AG Kluge},\r\n  title = {Parsimony jackknifing outperforms neighbor-joining},\r\n  journal = {Cladistics},\r\n  year = {1996},\r\n  OPTkey = {},\r\n  volume = {12},\r\n  OPTnumber = {},\r\n  pages = {99--124},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@article{Felsenstein1978,\r\n    Author = {J. Felsenstein},\r\n    Journal = {Syst. Zool.},\r\n    Pages = {240-249},\r\n    Title = {Cases in which parsimony or compatibility methods will be positively misleading},\r\n    Volume = {22},\r\n    Year = {1978}}\r\n\r\n@article{Felsenstein1981,\r\n    Author = {J Felsenstein},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Molecular Evolution},\r\n    Pages = {368--376},\r\n    Title = {Evolutionary trees from {DNA} sequences: a maximum likelihood approach},\r\n    Volume = {17},\r\n    Year = {1981}}\r\n\r\n@article{Felsenstein1989,\r\n    Author = {J Felsenstein},\r\n    Journal = {Cladistics},\r\n    Pages = {164--166},\r\n    Title = {{PHYLIP -- Phylogeny Inference Package (Version 3.2)}},\r\n    Volume = {5},\r\n    Year = {1989}}\r\n\r\n@book{Felsenstein2003,\r\n    Author = {J Felsenstein},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Sinauer Associates, Inc.},\r\n    Title = {Inferring Phylogenies},\r\n    Year = {2003}}\r\n\r\n@misc{Felsenstein2004,\r\n    Author = {J Felsenstein},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Howpublished = {Distributed by the author, Department of Genome Sciences, University of Washington, Seattle},\r\n    Title = {{PHYLIP (Phylogeny Inference Package) version 3.6}},\r\n    Year = {2004}}\r\n\r\n@article{Fernandez-Baca2000,\r\n    Author = {D Fern\\'andez-Baca and T Sepp\\\"al\\\"ainen and G Slutzki},\r\n    Date-Modified = {2005-02-25 12:49:26 -0800},\r\n    Journal = {Journal of Discrete Algorithms},\r\n    Number = {2},\r\n    Pages = {271--287},\r\n    Title = {Parametric multiple sequence alignment and phylogeny construction},\r\n    Volume = {2},\r\n    Year = {2004}}\r\n\r\n@article{Fernandez-Baca2002,\r\n    Author = {D Fern\\'andez-Baca and T Sepp\\\"al\\\"ainen and G Slutzki},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Discrete Applied Mathematics},\r\n    Pages = {181--198},\r\n    Title = {Bounds for parametric sequence comparison},\r\n    Volume = {118},\r\n    Year = {2002}}\r\n\r\n@article{Fernandez-Baca2004,\r\n    Author = {D Fern\\'andez-Baca and T Sepp\\\"al\\\"ainen and G Slutzki},\r\n    Date-Modified = {2005-10-16 22:07:46 -0700},\r\n    Journal = {Journal of Discrete Algorithms},\r\n    Number = {2},\r\n    Pages = {271--287},\r\n    Title = {Parametric multiple sequence alignment and phylogeny construction},\r\n    Volume = {2},\r\n    Year = {2004}}\r\n\r\n@incollection{Fernandez-Baca2005,\r\n    Author = {D Fern\\'andez-Baca and B Venkatachalam},\r\n    Booktitle = {To appear in Handbook of Computational Molecular Biology},\r\n    Date-Added = {2005-10-16 22:08:25 -0700},\r\n    Date-Modified = {2005-10-16 22:10:40 -0700},\r\n    Editor = {S Aluru},\r\n    Pages = {271--287},\r\n    Publisher = {Chapman and Hall/CRC Press Computer and Information Science Series},\r\n    Title = {Parametric sequence alignment},\r\n    Volume = {2},\r\n    Year = {2005, in press}}\r\n\r\n@article{Ferrari1995,\r\n    Author = {P Ferrari and A Frigessi and P de Sa},\r\n    Journal = {Journal of the Royal Statistical Society},\r\n    Title = {Fast approximate maximum a posteriori restoration of multi-color images},\r\n    Volume = {B,57},\r\n    Year = {1995}}\r\n\r\n@article{Fitch1983,\r\n    Abstract = {Current theory is adequate to the task of finding an optimal alignment between two character strings such as nucleic acids. Most algorithms currently in use must fail to find the homologous alignment between a set of codons for the chicken [alpha] - and {beta} -hemoglobin sequence when it is in fact discoverable by a more general treatment of gaps. Fundamental reasons for this are discussed.\r\n},\r\n    Author = {WM Fitch and TF Smith},\r\n    Journal = {PNAS},\r\n    Number = {5},\r\n    Pages = {1382--1386},\r\n    Title = {{Optimal sequence alignments}},\r\n    Url = {http://www.pnas.org/cgi/content/abstract/80/5/1382},\r\n    Volume = {80},\r\n    Year = {1983}}\r\n\r\n@article{Fleischmann1995,\r\n    Author = {RD Fleischmann and MD Adams and O White and RA Clayton and EF Kirkness and AR Kerlavage and CJ Bult and JF Tomb and BA Dougherty and JM Merrick et al.},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Science},\r\n    Number = {5223},\r\n    Pages = {496--512},\r\n    Title = {{Whole-genome random sequencing and assembly of {\\it Haemophilus influenza} Rd}},\r\n    Volume = {269},\r\n    Year = {1995}}\r\n\r\n\r\n@article{Floyd1962,\r\n    Author = {RW Floyd},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Communications of ACM},\r\n    Number = {6},\r\n    Pages = {345},\r\n    Title = {Algorithm 97: shortest path},\r\n    Volume = {5},\r\n    Year = {1962}}\r\n\r\n\r\n@article{Forney1973,\r\n    Author = {GD Forney},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Procedings of the IEEE},\r\n    Number = {3},\r\n    Pages = {268-278},\r\n    Title = {The {V}iterbi Algorithm},\r\n    Volume = {61},\r\n    Year = {1973}}\r\n\r\n@article{Frazer2004,\r\n    Abstract = {Comparison of DNA sequences from different species is a fundamental method for identifying functional elements in genomes. Here, we describe the VISTA family of tools created to assist biologists in carrying out this task. Our first VISTA server at http://www-gsd.lbl.gov/vista/ was launched in the summer of 2000 and was designed to align long genomic sequences and visualize these alignments with associated functional annotations. Currently the VISTA site includes multiple comparative genomics tools and provides users with rich capabilities to browse pre-computed whole-genome alignments of large vertebrate genomes and other groups of organisms with VISTA Browser, to submit their own sequences of interest to several VISTA servers for various types of comparative analysis and to obtain detailed comparative analysis results for a set of cardiovascular genes. We illustrate capabilities of the VISTA site by the analysis of a 180 kb interval on human chromosome 5 that encodes for the kinesin family member 3A (KIF3A) protein.},\r\n    Affiliation = {Perlegen Sciences, Inc., 2021 Stierlin Court, Mountain View, CA 94043, USA.},\r\n    Aid = {32/suppl{\\_}2/W273 {$[$}pii{$]$}},\r\n    Au = {Dubchak I},\r\n    Author = {KA Frazer and L Pachter and A Poliakov and EM Rubin and I Dubchak},\r\n    Da = {20040624},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Dcom = {20040820},\r\n    Edat = {2004/06/25 05:00},\r\n    Jid = {0411011},\r\n    Journal = {Nucleic Acids Research},\r\n    Keywords = {Binding Sites and Chromosomes, Human, Pair 5 and *Computational Biology and Genome, Human and *Genomics and Humans and Internet and Kinesin/genetics and Phylogeny and Regulatory Sequences, Nucleic Acid and Sequence Alignment and Sequence Analysis, DNA and *Software and Transcription Factors/metabolism},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2004/08/21 05:00},\r\n    Number = {Web Server issue},\r\n    Own = {NLM},\r\n    Pages = {W273--9},\r\n    Pl = {England},\r\n    Pmid = {15215394},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {EC 3.6.1.- (Kinesin)},\r\n    Sb = {IM},\r\n    So = {Proc Natl Acad Sci U S A 2004 Nov 16;101(46):16138-43. Epub 2004 Nov 08.},\r\n    Stat = {MEDLINE},\r\n    Title = {VISTA: computational tools for comparative genomics.},\r\n    Volume = {32},\r\n    Year = {2004}}\r\n\r\n\r\n@inproceedings{Friedman1997,\r\n    Author = {N Friedman},\r\n    Booktitle = {Proceedings of the International Conference on Machine Learning},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Title = {Learning belief networks in the presence of missing values and hidden variables},\r\n    Year = {1997}}\r\n\r\n@article{Friedman1997a,\r\n    Author = {N Friedman and D Geiger and M Goldszmit},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Machine Learning},\r\n    Pages = {131--163},\r\n    Title = {{Bayesian} Network Classifiers},\r\n    Volume = {29},\r\n    Year = {1997}}\r\n\r\n@unpublished{Friedman1999,\r\n    Author = {N Friedman and I Nachman and D Pe{\\'e}r},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Note = {Submitted},\r\n    Title = {Learning of {Bayesian} Network Structure from Massive Datasets: {The} ``Sparse Candidate'' Algorithm},\r\n    Year = {1999}}\r\n\r\n@article{Friedman2004,\r\n    Author = {N Friedman},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Science},\r\n    Pages = {799--805},\r\n    Title = {Inferring Cellular Networks Using Probabilistic Graphical Models},\r\n    Volume = {303},\r\n    Year = {2004}}\r\n\r\n@inproceedings{Frieze1998,\r\n    Author = {A Frieze and R Kannan and S Vempala},\r\n    Booktitle = {39th Symposium on Foundations of Computing},\r\n    Pages = {370--378},\r\n    Title = {Fast {M}onte {C}arlo algorithms for low rank approximation},\r\n    Year = {1998}}\r\n\r\n@InProceedings{Fuglede2004,\r\n  author = \t {B Fuglede and F Tops{\\o}e},\r\n  title = \t {{Jensen-Shannon divergence and Hilbert space embedding}},\r\n  OPTcrossref =  {},\r\n  OPTkey = \t {},\r\n  booktitle = {{Proceedings of the IEEE International Symposium on Information Theory}},\r\n  pages = \t {31},\r\n  year = \t {2004},\r\n  OPTeditor = \t {},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTaddress = \t {},\r\n  OPTmonth = \t {},\r\n  OPTorganization = {},\r\n  OPTpublisher = {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Fukuda2004,\r\n    Author = {K Fukuda},\r\n    Fjournal = {Journal of Symbolic Computation},\r\n    Issn = {0747-7171},\r\n    Journal = {Journal of Symbolic Computation},\r\n    Mrclass = {52A39 (52B55 68U05)},\r\n    Mrnumber = {MR2094220},\r\n    Number = {4},\r\n    Pages = {1261--1272},\r\n    Title = {From the zonotope construction to the {M}inkowski addition of convex polytopes},\r\n    Volume = {38},\r\n    Year = {2004}}\r\n\r\n@misc{GMP,\r\n    Howpublished = {Available at \\url{http://www.swox.com/gmp/}},\r\n    Key = {GMP},\r\n    Title = {{GNU} {M}ultiple {P}recision Arithmetic Library},\r\n    Year = {2004}}\r\n\r\n@article{Galtier1998,\r\n    Author = {N Galtier and M Gouy},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Number = {4},\r\n    Pages = {871--879},\r\n    Title = {Inferring pattern and process: maximum likelihood implementation of a non-homogeneous model of {DNA} sequence evolution for phylogenetic analysis.},\r\n    Volume = {154},\r\n    Year = {1998}}\r\n\r\n@incollection{Garcia2004,\r\n    Address = {Arlington, VA},\r\n    Author = {LD Garcia},\r\n    Booktitle = {Proceedings of the $20^{th}$ Conference on Uncertainty in Artificial Intelligence},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Editor = {M Chickering and J Halpern},\r\n    Pages = {177--184},\r\n    Publisher = {AUAI Press},\r\n    Title = {Algebraic Statistics in Model Selection},\r\n    Year = {2004}}\r\n\r\n@article{Garcia2004a,\r\n    Author = {Garcia, L. D. and Stillman, M. and Sturmfels, B.},\r\n    Editor = {AM Cohen, G-M Greuel, M-F Roy},\r\n    Fjournal = {Journal of Symbolic Computation, Special issue on the occasion of MEGA 2003},\r\n    Journal = {Journal of Symbolic Computation},\r\n    Note = {Special issue on the occasion of MEGA 2003},\r\n    Pages = {331--355},\r\n    Title = {Algebraic geometry of {B}ayesian networks},\r\n    Volume = {39/3-4},\r\n    Year = {2004}}\r\n\r\n@Article{Gascuel1994,\r\n  author =   {O Gascuel},\r\n  title =    {{A note on Sattath and Tversky's, Saitou and Nei's, and Studier and Keppler's Algorithms for Inferring Phylogenies from Evolutionary Distances}},\r\n  journal =      {Molecular Biology and Evolution},\r\n  year =     {1994},\r\n  OPTkey =   {},\r\n  volume =   {11},\r\n  OPTnumber =   {6},\r\n  pages =    {961--963},\r\n  OPTmonth =     {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n@Article{Gascuel1997,\r\n  author = {O Gascuel},\r\n  title = {{BIONJ: an improved version of the NJ algorithm based on a\r\n                  simple model of sequence data}},\r\n  journal = {Molecular Biology and Evolution},\r\n  year = {1997},\r\n  OPTkey = {},\r\n  volume = {14},\r\n  OPTnumber = {7},\r\n  pages = {685--695},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@Article{Gascuel2004,\r\n  author =   {O Gascuel and A McKenzie},\r\n  title =    {Performance analysis of hierarchical clustering algorithms},\r\n  journal =      {Journal of Classification},\r\n  year =     {2004},\r\n  OPTkey =   {},\r\n  volume =   {21},\r\n  OPTnumber =    {},\r\n  pages =    {3--18},\r\n  OPTmonth =     {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n\r\n@Article{Gascuel2006,\r\n  author =   {O Gascuel and M Steel},\r\n  title =    {{Neighbor-joining revealed}},\r\n  journal =      {Molecular Biology and Evolution},\r\n  year =     {2006},\r\n  OPTkey =   {},\r\n  volume =    {23},\r\n  OPTnumber =    {11},\r\n  pages =     {1997--2000},\r\n  OPTmonth =     {},\r\n  note =     {},\r\n  OPTannote =    {}\r\n}\r\n\r\n\r\n\r\n\r\n@article{Gatermann2005,\r\n    Author = {K Gatermann and M Wolfrum},\r\n    Journal = {Advances in Applied Mathematics},\r\n    Number = {2},\r\n    Pages = {252--294},\r\n    Title = {Bernstein's second theorem and {V}iro's method for sparse polynomial systems in chemistry},\r\n    Volume = {34},\r\n    Year = {2005}}\r\n\r\n@incollection{Gaut1998,\r\n    Address = {New York, NY},\r\n    Author = {BS Gaut},\r\n    Booktitle = {Evolutionary Biology, Vol 30},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Editor = {MK Hecht RJ Macintyre and MT Clegg},\r\n    Pages = {93--120},\r\n    Publisher = {Plenum Press Div Plenum Publishing Corp},\r\n    Title = {Molecular clocks and nucleotide substitution rates in higher plants},\r\n    Year = {1998}}\r\n\r\n@incollection{Gawrilow2000,\r\n    Author = {E Gawrilow and M Joswig},\r\n    Booktitle = {Polytopes --- Combinatorics and Computation},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Editor = {G Kalai and GM Ziegler},\r\n    Pages = {43--74},\r\n    Publisher = {Birkh\\\"auser},\r\n    Title = {Polymake: a Framework for Analyzing Convex Polytopes},\r\n    Year = {2000}}\r\n\r\n@inproceedings{Gawrilow2001,\r\n    Author = {E Gawrilow and M Joswig},\r\n    Booktitle = {Proceedings of the 17th Annual Symposium on Computational Geometry},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Note = {June 3-5, 2001, Medford, MA},\r\n    Organization = {ACM},\r\n    Pages = {222--231},\r\n    Title = {Polymake: an Approach to Modular Software Design in Computational Geometry},\r\n    Year = {2001}}\r\n\r\n@article{Geiger2001,\r\n    Author = {D Geiger and D Heckerman and H King and C Meek},\r\n    Fjournal = {The Annals of Statistics},\r\n    Journal = {The Annals of Statist.},\r\n    Number = {2},\r\n    Pages = {505--529},\r\n    Title = {Stratified exponential families: graphical models and model selection},\r\n    Volume = {29},\r\n    Year = {2001}}\r\n\r\n@article{Geiger2005,\r\n    Author = {D Geiger and C Meek and B Sturmfels},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Institution = {Microsoft Research},\r\n    Journal = {The Annals of Statistics},\r\n    Note = {To appear},\r\n    Title = {On the toric algebra of graphical models},\r\n    Year = {2005}}\r\n\r\n@article{Geman1984,\r\n    Author = {S Geman and D Geman},\r\n    Journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence, PAMI-6},\r\n    Pages = {721--741},\r\n    Title = {Stochastic relaxation, Gibbs distributions and the {Bayesian} restoration of images},\r\n    Year = {1984}}\r\n\r\n@article{Gentleman2004,\r\n    Author = {RC Gentleman and VJ Carey and DM Bates and B Bolstad and M Dettling and S Dudoit and B Ellis and L Gautier and Y Ge and J Gentry and others},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Genome Biology},\r\n    Pages = {R80},\r\n    Title = {Bioconductor: Open software development for computational biology and bioinformatics},\r\n    Url = {http://genomebiology.com/2004/5/10/R80},\r\n    Volume = {5},\r\n    Year = {2004}}\r\n\r\n@article{Gentles2001,\r\n    Author = {AJ Gentles and S Karlin},\r\n    Journal = {Genome Research},\r\n    Pages = {540--546},\r\n    Title = {Genome-scale compositional comparisons in eukaryotes},\r\n    Volume = {4},\r\n    Year = {2001}}\r\n\r\n@article{Gibbs2004,\r\n    Abstract = {The laboratory rat (Rattus norvegicus) is an indispensable tool in experimental medicine and drug development, having made inestimable contributions to human health. We report here the genome sequence of the Brown Norway (BN) rat strain. The sequence represents a high-quality 'draft' covering over 90% of the genome. The BN rat sequence is the third complete mammalian genome to be deciphered, and three-way comparisons with the human and mouse genomes resolve details of mammalian evolution. This first comprehensive analysis includes genes and proteins and their relation to human disease, repeated sequences, comparative genome-wide studies of mammalian orthologous chromosomal regions and rearrangement breakpoints, reconstruction of ancestral karyotypes and the events leading to existing species, rates of variation, and lineage-specific and lineage-independent evolutionary events such as expansion of gene families, orthology relations and protein evolution.},\r\n    Affiliation = {Human Genome Sequencing Center, Department of Molecular and Human Genetics, Baylor College of Medicine, MS BCM226, One Baylor Plaza, Houston, Texas 77030, USA <http://www.hgsc.bcm.tmc.edu>.},\r\n    Aid = {nature02426 {$[$}pii{$]$}},\r\n    Au = {Collins F},\r\n    Author = {RA Gibbs and GM Weinstock and ML Metzker and DM Muzny and EJ Sodergren and S Scherer and G Scott and D Steffen and KC Worley and PE Burch and others},\r\n    Cin = {Nature. 2004 Apr 1;428(6982):475-6. PMID: 15057812},\r\n    Cn = {Rat Genome Sequencing Project Consortium.},\r\n    Da = {20040401},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20040414},\r\n    Edat = {2004/04/02 05:00},\r\n    Jid = {0410462},\r\n    Journal = {Nature},\r\n    Keywords = {Animals and Base Composition and Centromere/genetics and Chromosomes, Mammalian/genetics and CpG Islands/genetics and DNA Transposable Elements/genetics and DNA, Mitochondrial/genetics and *Evolution, Molecular and Gene Duplication and *Genome and *Genomics and Humans and Introns/genetics and Male and Mice and Models, Molecular and Mutagenesis and Polymorphism, Single Nucleotide/genetics and RNA Splice Sites/genetics and RNA, Untranslated/genetics and Rats and Rats, Inbred BN/*genetics and Regulatory Sequences, Nucleic Acid/genetics and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, P.H.S. and Retroelements/genetics and Sequence Analysis, DNA and Telomere/genetics},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2004/04/15 05:00},\r\n    Number = {6982},\r\n    Own = {NLM},\r\n    Pages = {493--521},\r\n    Phst = {2004/02/20 {$[$}accepted{$]$}},\r\n    Pl = {England},\r\n    Pmid = {15057822},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (Retroelements)},\r\n    Sb = {IM},\r\n    So = {Genome Res 2004 Apr;14(4):574-9.},\r\n    Stat = {MEDLINE},\r\n    Title = {Genome sequence of the Brown Norway rat yields insights into mammalian evolution.},\r\n    Volume = {428},\r\n    Year = {2004}}\r\n\r\n@book{Golub1989,\r\n    Author = {GH Golub and CF Van Loan},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Edition = {second},\r\n    Publisher = {The Johns Hopkins University Press},\r\n    Title = {Matrix Computations},\r\n    Year = {1989}}\r\n\r\n@article{Gorban2004,\r\n    Author = {AN Gorban and AY Zinovyev},\r\n    Journal = {arXiv.org:q-bio.GN/0412015},\r\n    Title = {The mystery of two straight lines in bacterial genome statistics},\r\n    Year = {2004}}\r\n\r\n@misc{Grayson2002,\r\n    Author = {DR Grayson and ME Stillman},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Howpublished = {Available at \\url{http://www.math.uiuc.edu/Macaulay2/}},\r\n    Title = {Macaulay 2, a software system for research in algebraic geometry},\r\n    Year = {2002}}\r\n\r\n@article{Greig1989,\r\n    Author = {DM Greig and BT Porteous and AH Seheult},\r\n    Journal = {Journal of the Royal Statistical Society},\r\n    Pages = {271--279},\r\n    Title = {Exact maximum a posteriori estimation for binary images},\r\n    Volume = {Series B, 51},\r\n    Year = {1989}}\r\n\r\n@book{Greuel2002,\r\n    Address = {Berlin and Heidelberg},\r\n    Author = {GM Greuel and G Pfister},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Springer-Verlag},\r\n    Title = {A Singular Introduction to Commutative Algebra},\r\n    Year = {2002}}\r\n\r\n@misc{Greuel2003,\r\n    Author = {GM Greuel and G. Pfister and H. Schoenemann},\r\n    Date-Modified = {2005-02-28 12:49:26 -0800},\r\n    Howpublished = {Available at \\url{http://www.singular.uni-kl.de/}},\r\n    Title = {SINGULAR: A Computer Algebra System for Polynomial Computations},\r\n    Year = {2003}}\r\n\r\n\r\n@article{Griffiths1996,\r\n    Author = {RC Griffiths and P Marjoram},\r\n    Bibsource = {DBLP, http://dblp.uni-trier.de},\r\n    Date-Modified = {2005-03-01 19:23:49 -0500},\r\n    Journal = {Journal of Computational Biology},\r\n    Number = {4},\r\n    Pages = {479--502},\r\n    Title = {Ancestral Inference from Samples of DNA Sequences with Recombination.},\r\n    Volume = {3},\r\n    Year = {1996}}\r\n\r\n@article{Gritzmann1993,\r\n    Author = {P Gritzmann and B Sturmfels},\r\n    Journal = {SIAM Journal of Discrete Mathematics},\r\n    Pages = {246--269},\r\n    Title = {{M}inkowski addition of polytopes: {C}omputational complexity and applications to {G}r\\\"obner bases},\r\n    Volume = {6},\r\n    Year = {1993}}\r\n\r\n@book{Grotschel1988,\r\n    Address = {Berlin},\r\n    Author = {M Gr{\\\"o}tschel and L Lov{\\'a}sz and A Schrijver},\r\n    Isbn = {3-540-13624-X},\r\n    Mrclass = {90C27 (05-02 52-02 68Q25)},\r\n    Mrnumber = {MR936633 (89m:90135)},\r\n    Mrreviewer = {J{\\\"u}rgen K{\\\"o}hler},\r\n    Pages = {xii+362},\r\n    Publisher = {Springer-Verlag},\r\n    Series = {Algorithms and Combinatorics: Study and Research Texts},\r\n    Title = {Geometric algorithms and combinatorial optimization},\r\n    Volume = {2},\r\n    Year = {1988}}\r\n\r\n\r\n\r\n@book{Grotschel1993,\r\n    Author = {M Gr{\\\"o}tschel and L Lov{\\'a}sz and A Schrijver},\r\n    Isbn = {0-387-56740-2},\r\n    Publisher = {Springer-Verlag},\r\n    Series = {{\\rm Algorithms and Combinatorics}},\r\n    Title = {Geometric Algorithms and Combinatorial Optimization},\r\n    Volume = {2},\r\n    Year = {1993}}\r\n\r\n@book{Grunbaum2003,\r\n    Address = {New York},\r\n    Author = {B Gr{\\\"u}nbaum},\r\n    Edition = {Second},\r\n    Isbn = {0-387-00424-6; 0-387-40409-0},\r\n    Mrclass = {52-01 (52Bxx)},\r\n    Mrnumber = {MR1976856 (2004b:52001)},\r\n    Mrreviewer = {Alexander Zvonkin},\r\n    Note = {Prepared and with a preface by Volker Kaibel, Victor Klee and G\\\"unter M.\\ Ziegler},\r\n    Pages = {xvi+468},\r\n    Publisher = {Springer-Verlag},\r\n    Series = {{\\rm Graduate Texts in Mathematics}},\r\n    Title = {Convex Polytopes},\r\n    Volume = {221},\r\n    Year = {2003}}\r\n\r\n@article{Guigo2004,\r\n    Author = {R Guig\\'{o} and E Birbey and M Brent and E Dermitzakis and L Pachter and H Roest Crollius and V Solovyev and MQ Zhang},\r\n    Journal = {arXiv.org:q-bio.GN/0410008},\r\n    Title = {Needed for completion of the human genome: hypothesis driven experiments and biologically realistic mathematical models},\r\n    Year = {2004}}\r\n\r\n@article{Gusfield1994,\r\n    Author = {D Gusfield and K Balasubramanian and D Naor},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Algorithmica},\r\n    Pages = {312--326},\r\n    Title = {Parametric optimization of sequence alignment},\r\n    Volume = {12},\r\n    Year = {1994}}\r\n\r\n@article{Gusfield1996,\r\n    Author = {D Gusfield and P Stelling},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Methods Enzymology},\r\n    Pages = {481--494},\r\n    Title = {Parametric and inverse-parametric sequence alignment with XPARAL},\r\n    Volume = {266},\r\n    Year = {1996}}\r\n\r\n@book{Gusfield1997,\r\n    Author = {D Gusfield},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Cambridge University Press},\r\n    Title = {Algorithms on Strings, Trees, and Sequences},\r\n    Year = {1997}}\r\n\r\n@Article{Haas2003,\r\n  author = \t {BJ Haas and AL Delcher and SM Mount and JR Wortman and RK Smith and LI Hannick and R Maiti and CM Ronning and DB Rusch and CD Town and SL Salzberg and O White},\r\n  title = \t {Improving the {{\\it Arabidopsis}} genome annotation using maximal transcript alignment assemblies},\r\n  journal = \t {Nucleic Acids Research},\r\n  year = \t {2003},\r\n  OPTkey = \t {},\r\n  volume = \t {31},\r\n  OPTnumber = \t {19},\r\n  pages = \t {5654--5666},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Hacijan1979,\r\n    Author = {LG Ha{\\v{c}}ijan},\r\n    Fjournal = {Doklady Akademii Nauk SSSR},\r\n    Issn = {0002-3264},\r\n    Journal = {Dokl. Akad. Nauk SSSR},\r\n    Mrclass = {90C05},\r\n    Mrnumber = {MR522052 (80g:90071)},\r\n    Mrreviewer = {M. Stef{\\u{a}}nescu},\r\n    Number = {5},\r\n    Pages = {1093--1096},\r\n    Title = {A polynomial algorithm in linear programming},\r\n    Volume = {244},\r\n    Year = {1979}}\r\n\r\n@Article{Hall2005,\r\n  author = {BG Hall},\r\n  title = {Comparison of the accuracies of several phylogenetic\r\n                  methods using protein and {DNA} sequences},\r\n  journal = {Molecular Biology and Evolution},\r\n  year = {2005},\r\n  OPTkey = {},\r\n  volume = {22},\r\n  number = {3},\r\n  pages = {792--802},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@article{Hallgrimsdottir2005,\r\n    Author = {I Hallgr\\'{\\i}msd\\'{o}ttir and B Sturmfels},\r\n    Journal = {Journal of Symbolic Computation},\r\n    Note = {To appear},\r\n    Title = {Resultants in Genetic Linkage Analysis},\r\n    Year = {2005}}\r\n\r\n@book{Hammer1995,\r\n    Address = {Berlin},\r\n    Author = {R Hammer and M Hocks and U Kulisch and D Ratz},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Springer-Verlag},\r\n    Title = {C++ Toolbox for Verified Computing: Basic Numerical Problems},\r\n    Year = {1995}}\r\n\r\n@article{Hannenhalli1999,\r\n    Author = {S Hannenhalli and PA Pevzner},\r\n    Journal = {Journal of the ACM},\r\n    Number = {1},\r\n    Pages = {1--27},\r\n    Title = {{Transforming cabbage into turnip: polynomial algorithm for sorting signed permutations by reversals}},\r\n    Volume = {46},\r\n    Year = {1999}}\r\n\r\n@article{Hansen1980,\r\n    Author = {E Hansen},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Numerische Mathematik},\r\n    Pages = {247--270},\r\n    Title = {Global optimization using interval analysis -- the multi-dimensional case},\r\n    Volume = {34},\r\n    Year = {1980}}\r\n\r\n@article{Hansen1981,\r\n    Author = {E Hansen and S Sengupta},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {BIT},\r\n    Pages = {203--211},\r\n    Title = {Bounding solutions of systems of equations using interval analysis},\r\n    Volume = {21},\r\n    Year = {1981}}\r\n\r\n@book{Hansen1992,\r\n    Address = {New York},\r\n    Author = {E Hansen},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Marcel Dekker},\r\n    Title = {Global Optimization using Interval Analysis},\r\n    Year = {1992}}\r\n\r\n@book{Hartwell2003,\r\n    Author = {L Hartwell and L Hood and ML Goldberg and LM Silver and RC Veres and A Reynolds},\r\n    Edition = {second},\r\n    Publisher = {McGraw-Hill Science/Engineering/Math},\r\n    Title = {{Genetics: From Genes to Genomes}},\r\n    Year = {2003}}\r\n\r\n@article{Hasegawa1985,\r\n    Author = {M Hasegawa and H Kishino and T Yano},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Molecular Evolution},\r\n    Pages = {160--174},\r\n    Title = {Dating of the human-ape splitting by a molecular clock of mitochondrial {DNA}},\r\n    Volume = {22},\r\n    Year = {1985}}\r\n\r\n@article{Heckerman1995,\r\n    Author = {D Heckerman and D Geiger and DM Chickering},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Machine Learning},\r\n    Pages = {197--243},\r\n    Title = {Learning {B}ayesian Networks: {T}he combination of knowledge and statistical data},\r\n    Volume = {20},\r\n    Year = {1995}}\r\n\r\n@techreport{Heckerman1995a,\r\n    Author = {D Heckerman},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Institution = {Microsoft Research},\r\n    Number = {MSR-TR-95-06},\r\n    Title = {A tutorial on learning with {B}ayesian networks},\r\n    Year = {1995}}\r\n\r\n@incollection{Heckerman1998,\r\n    Address = {Cambridge, Massachusetts},\r\n    Author = {D Heckerman},\r\n    Booktitle = {Learning in Graphical Models},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Editor = {MI Jordan},\r\n    Publisher = {MIT Press},\r\n    Title = {A tutorial on learning with {B}ayesian networks},\r\n    Year = {1998}}\r\n\r\n@article{Hendy1989,\r\n    Author = {M Hendy and D Penny},\r\n    Date-Added = {2005-03-01 20:20:00 -0500},\r\n    Date-Modified = {2005-03-01 20:20:51 -0500},\r\n    Journal = {Systematic Zoology},\r\n    Number = {4},\r\n    Title = {A framework for the quantitative study of evolutionary trees},\r\n    Volume = {38},\r\n    Year = {1989}}\r\n\r\n@article{Hendy1993,\r\n    Author = {MD Hendy and D Penny},\r\n    Journal = {Journal of Classification},\r\n    Pages = {5--24},\r\n    Title = {Spectral analysis of phylogenetic data},\r\n    Volume = {10},\r\n    Year = {1993}}\r\n\r\n@article{Heydebreck2004,\r\n    Author = {A von Heydebreck and B Gunawan and L F{\\\"u}zesi},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Biostatistics},\r\n    Number = {4},\r\n    Pages = {545--556},\r\n    Title = {Maximum likelihood estimation of oncogenetic tree models},\r\n    Url = {http://biostatistics.oupjournals.org/cgi/content/abstract/5/4/545?etoc},\r\n    Volume = {5},\r\n    Year = {2004}}\r\n\r\n@article{Hibi1987,\r\n    Author = {T Hibi},\r\n    Journal = {Advanced Studies in Pure Mathematics},\r\n    Pages = {93--109},\r\n    Title = {Distributive Lattices, Affine Semigroup Rings and Algebras with Straightening Laws},\r\n    Volume = {11},\r\n    Year = {1987}}\r\n\r\n@Article{Hiller2009,\r\n  author = \t {D Hiller and H Jiang and W Xu and WH Wong},\r\n  title = \t {Identifiability of isoform deconvolution from junction arrays and {RNA-Seq}},\r\n  journal = \t {Bioinformatics},\r\n  year = \t {2009},\r\n  OPTkey = \t {},\r\n  volume = \t {25},\r\n  OPTnumber = \t {23},\r\n  pages = \t {3056--3059},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Hillier2004,\r\n    Abstract = {We present here a draft genome sequence of the red jungle fowl, Gallus gallus. Because the chicken is a modern descendant of the dinosaurs and the first non-mammalian amniote to have its genome sequenced, the draft sequence of its genome--composed of approximately one billion base pairs of sequence and an estimated 20,000-23,000 genes--provides a new perspective on vertebrate genome evolution, while also improving the annotation of mammalian genomes. For example, the evolutionary distance between chicken and human provides high specificity in detecting functional elements, both non-coding and coding. Notably, many conserved non-coding sequences are far from genes and cannot be assigned to defined functional classes. In coding regions the evolutionary dynamics of protein domains and orthologous groups illustrate processes that distinguish the lineages leading to birds and mammals. The distinctive properties of avian microchromosomes, together with the inferred patterns of conserved synteny, provide additional insights into vertebrate chromosome architecture.},\r\n    Affiliation = {Genome Sequencing Center, Washington University School of Medicine, Campus Box 8501, 4444 Forest Park Avenue, St Louis, Missouri 63108, USA.},\r\n    Aid = {10.1038/nature03154 {$[$}doi{$]$}},\r\n    Au = {Wilson RK},\r\n    Author = {LW Hillier and W Miller and E Birney and W Warren and RC Hardison and CP Ponting and P Bork and DW Burt and MAM Groenen and ME Delany and others},\r\n    Cin = {Nature. 2004 Dec 9;432(7018):679-80. PMID: 15592391},\r\n    Cn = {International Chicken Genome Sequencing Consortium.},\r\n    Da = {20041216},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Dcom = {20050105},\r\n    Edat = {2004/12/14 09:00},\r\n    Jid = {0410462},\r\n    Journal = {Nature},\r\n    Keywords = {Animals and Avian Proteins/genetics and Chickens/*genetics and Comparative Study and Conserved Sequence/genetics and DNA Transposable Elements/genetics and *Evolution, Molecular and Gene Duplication and Genes/genetics and *Genome and *Genomics and Humans and Long Interspersed Nucleotide Elements/genetics and Multigene Family/genetics and Mutagenesis/genetics and Physical Chromosome Mapping and Pseudogenes/genetics and RNA, Untranslated/genetics and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, Non-P.H.S. and Research Support, U.S. Gov't, P.H.S. and Retroviridae/genetics and Sequence Analysis, DNA and Short Interspersed Nucleotide Elements/genetics and Synteny and Vertebrates/genetics},\r\n    Language = {eng},\r\n    Mhda = {2005/01/06 09:00},\r\n    Number = {7018},\r\n    Own = {NLM},\r\n    Pages = {695-716},\r\n    Phst = {2004/11/01 {$[$}accepted{$]$}},\r\n    Pl = {England},\r\n    Pmid = {15592404},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (RNA, Untranslated)},\r\n    Sb = {IM},\r\n    So = {Science 2001 Feb 16;291(5507):1304-51.},\r\n    Stat = {MEDLINE},\r\n    Title = {Sequence and comparative analysis of the chicken genome provide unique perspectives on vertebrate evolution.},\r\n    Volume = {432},\r\n    Year = {2004}}\r\n\r\n@article{Hirschberg1975,\r\n    Author = {DS Hirschberg},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {CACM},\r\n    Number = {6},\r\n    Pages = {341--343},\r\n    Title = {A Linear Space Algorithm for Computing Maximal Common Subsequences},\r\n    Volume = {18},\r\n    Year = {1975}}\r\n\r\n@article{Holland2004,\r\n    Author = {B Holland and KT Huber and V Moulton and P Lockhart},\r\n    Date-Added = {2005-03-01 19:42:44 -0500},\r\n    Date-Modified = {2005-03-01 19:44:00 -0500},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Number = {7},\r\n    Pages = {1459--1461},\r\n    Title = {Using Consensus Networks to Visualize Contradictory Evidence for Species Phylogeny},\r\n    Volume = {21},\r\n    Year = {2004}}\r\n\r\n@article{Holmes2001,\r\n    Author = {I Holmes and WJ Bruno},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Bioinformatics},\r\n    Number = {9},\r\n    Pages = {803--820},\r\n    Title = {{Evolutionary HMMs: a Bayesian approach to multiple alignment}},\r\n    Volume = {17},\r\n    Year = {2001}}\r\n\r\n@Article{Hopcroft1973,\r\n  author = \t {JE Hopcroft and RM Karp},\r\n  title = \t {An $n^{5/2}$ algorithm for maximum matchings in bipartite graphs},\r\n  journal = \t {SIAM Journal on Computing},\r\n  year = \t {1973},\r\n  OPTkey = \t {},\r\n  volume = \t {2},\r\n  OPTnumber = \t {4},\r\n  pages = \t {225--231},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Hosten2005,\r\n    Author = {S Ho{\\c{s}}ten and A Khetan and B Sturmfels},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Foundations of Computational Mathematics},\r\n    Note = {To appear},\r\n    Title = {Solving the likelihood equations},\r\n    Year = {2005}}\r\n\r\n@article{Huber2002,\r\n    Author = {KT Huber and M Langton and D Penny and V Moulton and M Hendy},\r\n    Date-Added = {2005-03-01 19:35:57 -0500},\r\n    Date-Modified = {2005-03-01 19:39:03 -0500},\r\n    Journal = {Applied Bioinformatics},\r\n    Number = {3},\r\n    Pages = {2041--2059},\r\n    Title = {Spectronet: A package for computing spectra and median networks},\r\n    Volume = {1},\r\n    Year = {2002}}\r\n\r\n@Article{Huelsenbeck1993,\r\n  author =   {J Huelsenbeck and D Hillis},\r\n  title =    {Success of phylogenetic methods in the four-taxon case},\r\n  journal =      {Systematic Biology},\r\n  year =     {1993},\r\n  OPTkey =   {},\r\n  volume =   {42},\r\n  number =   {3},\r\n  pages =    {247--264},\r\n  OPTmonth =     {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n@article{Huelsenbeck2000,\r\n    Author = {JP Huelsenbeck and B Larget and DL Swofford},\r\n    Journal = {Genetics},\r\n    Number = {4},\r\n    Pages = {1879--1892},\r\n    Title = {A compound Poisson process for relaxing the molecular clock},\r\n    Volume = {154},\r\n    Year = {2000}}\r\n\r\n@article{Hughey1996,\r\n    Author = {R Hughey and A Krogh},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {CABIOS},\r\n    Pages = {95--107},\r\n    Title = {Hidden {Markov} models for sequence analysis: {E}xtension and analysis of the basic method},\r\n    Volume = {12},\r\n    Year = {1996}}\r\n\r\n@article{Human2004,\r\n    Annote = {10.1038/nature03001},\r\n    Author = {Human Genome Sequencing Consortium, International},\r\n    Date-Modified = {2005-02-12 12:17:12 -0800},\r\n    Ep = {945},\r\n    Journal = {Nature},\r\n    L3 = {http://www.nature.com/nature/journal/v431/n7011/suppinfo/nature03001.html},\r\n    M3 = {10.1038/nature03001},\r\n    Number = {7011},\r\n    Pages = {931--945},\r\n    Sn = {0028-0836},\r\n    Sp = {931},\r\n    Title = {Finishing the euchromatic sequence of the human genome},\r\n    Ty = {JOUR},\r\n    Url = {http://dx.doi.org/10.1038/nature03001},\r\n    Volume = {431},\r\n    Year = {2004}}\r\n\r\n@article{Huson1998,\r\n    Author = {D Huson},\r\n    Date-Modified = {2005-03-01 20:26:50 -0500},\r\n    Journal = {Bioinformatics},\r\n    Number = {1},\r\n    Pages = {68--73},\r\n    Title = {SplitsTree - a program for analyzing and visualizing evolutionary data},\r\n    Volume = {14},\r\n    Year = {1998}}\r\n\r\n@article{Huson2004,\r\n    Author = {D Huson and T Dezulian and T Kloepper and M Steel},\r\n    Date-Added = {2005-03-01 19:49:09 -0500},\r\n    Date-Modified = {2005-03-01 19:50:40 -0500},\r\n    Journal = {IEEE Transactions on Computational Biology and Bioinformatics},\r\n    Number = {4},\r\n    Pages = {151--158},\r\n    Title = {Phylogenetic super-networks from partial trees},\r\n    Volume = {1},\r\n    Year = {2004}}\r\n\r\n@unpublished{Huson2005,\r\n    Author = {D Huson and D Bryant},\r\n    Date-Added = {2005-03-01 19:52:22 -0500},\r\n    Date-Modified = {2005-03-01 19:54:56 -0500},\r\n    Note = {in preparation},\r\n    Title = {{Estimating phylogenetic trees and networks using SplitsTree4}},\r\n    Year = {2005}}\r\n\r\n@Article{Huson2005b,\r\n  author = \t {D Huson and D Bryant},\r\n  title = \t {Application of phylogenetic networks in evolutionary studies},\r\n  journal = \t {Molecular Biology and Evolution},\r\n  year = \t {2005},\r\n  OPTkey = \t {},\r\n  volume = \t {23},\r\n  OPTnumber = \t {},\r\n  pages = \t {254--267},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@manual{IEEE:p754,\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Key = {IEEE Task P754},\r\n    Note = {A preliminary draft was published in the January 1980 issue of IEEE Computer, together with several companion articles. Available from the IEEE Service Center, Piscataway, NJ, USA.},\r\n    Organization = {IEEE, New York},\r\n    Title = {{ANSI}\\slash {IEEE} 754-1985, Standard for Binary Floating-Point Arithmetic},\r\n    Year = {1985}}\r\n\r\n@article{Ihaka1996,\r\n    Author = {I Ross and R Gentleman},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Computational and Graphical Statistics},\r\n    Number = {3},\r\n    Pages = {299--314},\r\n    Title = {R: A Language for Data Analysis and Graphics},\r\n    Url = {http://www.amstat.org/publications/jcgs/},\r\n    Volume = {5},\r\n    Year = {1996}}\r\n\r\n@book{Imrich2000,\r\n    Author = {W Imrich and S Klav{\\v{z}}ar},\r\n    Date-Modified = {2005-03-01 20:31:05 -0500},\r\n    Isbn = {0-471-37039-8},\r\n    Mrclass = {05-01 (05C75 05C85 05C90 68R10)},\r\n    Mrnumber = {MR1788124 (2001k:05001)},\r\n    Mrreviewer = {Pranava K. Jha},\r\n    Note = {Structure and recognition, With a foreword by Peter Winkler},\r\n    Pages = {xvi+358},\r\n    Publisher = {Wiley--Interscience, New York},\r\n    Series = {Wiley--Interscience Series in Discrete Mathematics and Optimization},\r\n    Title = {Product Graphs},\r\n    Year = {2000}}\r\n\r\n@article{International-Human-Genome-Sequencing-Consortium2001,\r\n    Author = {{Human Genome Sequencing Consortium}},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Nature},\r\n    Month = {February},\r\n    Number = {6822},\r\n    Pages = {860--921},\r\n    Title = {{Initial sequencing and analysis of the human genome}},\r\n    Volume = {409},\r\n    Year = {2001}}\r\n\r\n@article{Jensen2001,\r\n    Author = {R Jensen},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Genome Biology},\r\n    Number = {8},\r\n    Pages = {1002--1005},\r\n    Title = {Orthologs and Paralogs -- we need to get it right},\r\n    Volume = {2},\r\n    Year = {2001}}\r\n\r\n@Article{Jiang2009,\r\n  author = \t {H Jiang and WH Wong},\r\n  title = \t {Statistical inferences for isoform expression in {RNA-Seq}},\r\n  journal = \t {Bioinformatics},\r\n  year = \t {2009},\r\n  OPTkey = \t {},\r\n  volume = \t {25},\r\n  OPTnumber = \t {},\r\n  pages = \t {1026--1032},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Johnson2006,\r\n  author = \t {O Johnson and J Liu},\r\n  title = \t {A traveling salesman approach for predicting protein functions},\r\n  journal = \t {Source Code for Biology and Medicine},\r\n  year = \t {2006},\r\n  OPTkey = \t {},\r\n  volume = \t {1},\r\n  OPTnumber = \t {3},\r\n  OPTpages = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@book{Jordan2005,\r\n    Author = {MI Jordan},\r\n    Publisher = {In preparation},\r\n    Title = {An Introduction to Probabilistic Graphical Models},\r\n    Year = {2005}}\r\n\r\n@incollection{Jukes1969,\r\n    Author = {TH Jukes and C Cantor},\r\n    Booktitle = {Mammalian Protein Metabolism},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Editor = {HN Munro},\r\n    Pages = {21--32},\r\n    Publisher = {New York, Academic Press},\r\n    Title = {Evolution of protein molecules},\r\n    Year = {1969}}\r\n\r\n@Article{Kalmanson1975,\r\n  author = \t {K Kalmanson},\r\n  title = \t {Edgeconvex circuits and the traveling salesman problem},\r\n  journal = \t {Canadian Journal of Mathematics},\r\n  year = \t {1974},\r\n  OPTkey = \t {},\r\n  volume = \t {27},\r\n  OPTnumber = \t {},\r\n  pages = \t {1000--1010},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Karlin1990,\r\n    Author = {S Karlin and SF Altschul},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Proceedings of the National Academy of Sciences, USA},\r\n    Pages = {2264--2268},\r\n    Title = {Methods for assessing the statistical significance of molecular sequence features by using general scoring schemes},\r\n    Volume = {87},\r\n    Year = {1990}}\r\n\r\n\r\n@article{Karloff1993,\r\n    Author = {H Karloff},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Information Processing Letters},\r\n    Pages = {53--60},\r\n    Title = {Fast algorithms for approximately counting mismatches},\r\n    Volume = {48},\r\n    Year = {1993}}\r\n\r\n@article{Karplus1998,\r\n    Author = {K Karplus and C Barrett and R Hughey},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Bioinformatics},\r\n    Pages = {846--856},\r\n    Title = {Hidden Markov models for detecting remote protein homologies},\r\n    Volume = {14},\r\n    Year = {1998}}\r\n\r\n@article{Kellis2004,\r\n    Author = {M Kellis and B Birren and E Lander},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Nature},\r\n    Pages = {617--624},\r\n    Title = {Proof and evolutionary analysis of ancient genome duplication in the yeast Saccharomyces cerevisae},\r\n    Volume = {8},\r\n    Year = {2004}}\r\n\r\n@article{Kent2002,\r\n    Author = {WJ Kent},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Genome Biology},\r\n    Number = {4},\r\n    Pages = {656--664},\r\n    Title = {{BLAT- The BLAST like Alignment Tool}},\r\n    Volume = {12},\r\n    Year = {2002}}\r\n\r\n@article{Kent2002a,\r\n    Author = {WJ Kent and CW Sugnet and TS Furey and KM Roskin and TH Pringle and AM Zhaler and D Haussler},\r\n    Journal = {Genome Research},\r\n    Number = {6},\r\n    Pages = {996--1006},\r\n    Title = {The human genome browser at {UCSC}},\r\n    Volume = {12},\r\n    Year = {2002}}\r\n\r\n@article{Khalil:2009p1195,\r\n\tauthor = {Ahmad M Khalil and Mitchell Guttman and Maite Huarte and Manuel Garber and Arjun Raj and Dianali Rivea Morales and Kelly Thomas and Aviva Presser and Bradley E Bernstein and Alexander van Oudenaarden and Aviv Regev and Eric S Lander and John L Rinn}, \r\n\tjournal = {Proc Natl Acad Sci USA},\r\n\ttitle = {Many human large intergenic noncoding RNAs associate with chromatin-modifying complexes and affect gene expression},\r\n\tabstract = {We recently showed that the mammalian genome encodes >1,000 large intergenic noncoding (linc)RNAs that are clearly conserved across mammals and, thus, functional. Gene expression patterns have implicated these lincRNAs in diverse biological processes, including cell-cycle regulation, immune surveillance, and embryonic stem cell pluripotency. However, the mechanism by which these lincRNAs function is unknown. Here, we expand the catalog of human lincRNAs to approximately 3,300 by analyzing chromatin-state maps of various human cell types. Inspired by the observation that the well-characterized lincRNA HOTAIR binds the polycomb repressive complex (PRC)2, we tested whether many lincRNAs are physically associated with PRC2. Remarkably, we observe that approximately 20% of lincRNAs expressed in various cell types are bound by PRC2, and that additional lincRNAs are bound by other chromatin-modifying complexes. Also, we show that siRNA-mediated depletion of certain lincRNAs associated with PRC2 leads to changes in gene expression, and that the up-regulated genes are enriched for those normally silenced by PRC2. We propose a model in which some lincRNAs guide chromatin-modifying complexes to specific genomic loci to regulate gene expression.},\r\n\taffiliation = {The Broad Institute of Harvard and Massachusetts Institute of Technology, Cambridge, MA 02142, USA.},\r\n\tnumber = {28},\r\n\tpages = {11667--72},\r\n\tvolume = {106},\r\n\tyear = {2009},\r\n\tmonth = {Jul},\r\n\tlanguage = {eng},\r\n\tkeywords = {Repressor Proteins, RNA: Untranslated, Gene Expression Profiling, Models: Genetic, Humans, Gene Expression Regulation, Oligonucleotide Array Sequence Analysis, Chromatin, Epigenesis: Genetic}, \r\n\tdate-added = {2009-09-06 15:49:47 -0700},\r\n\tdate-modified = {2010-02-23 17:02:00 -0800},\r\n\tdoi = {10.1073/pnas.0904715106},\r\n\tpii = {0904715106},\r\n\tpmid = {19571010},\r\n\tlocal-url = {file://localhost/Users/cole/Data/Documents/Papers/2009/Khalil/Proc%20Natl%20Acad%20Sci%20USA%202009%20Khalil.pdf},\r\n\turi = {papers://1C45D7C8-DE5F-4BCB-8C6D-9D101AFF5EFF/Paper/p1195},\r\n\tread = {Yes},\r\n\trating = {0}\r\n}\r\n\r\n\r\n@article{Khachiyan1980,\r\n    Author = {LG Khachiyan},\r\n    Journal = {USSR Computational Mathematics and Mathematical Physics},\r\n    Pages = {53--72},\r\n    Title = {Polynomial Algorithms in Linear Programming},\r\n    Volume = {20},\r\n    Year = {1980}}\r\n\r\n@article{Kimura1980,\r\n    Author = {M Kimura},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Molecular Evolution},\r\n    Pages = {111--120},\r\n    Title = {A simple method for estimating evolutionary rates of base substitution through comparative studies of nucleotide sequences},\r\n    Volume = {16},\r\n    Year = {1980}}\r\n\r\n@article{Kimura1981,\r\n    Author = {M Kimura},\r\n    Date-Added = {2005-03-01 20:17:11 -0500},\r\n    Date-Modified = {2005-03-01 20:18:29 -0500},\r\n    Journal = {Proceedings of the National Academy of Sciences, USA},\r\n    Pages = {454--458},\r\n    Title = {Estimation of evolutionary sequences between homologous nucleotide sequences},\r\n    Volume = {78},\r\n    Year = {1981}}\r\n\r\n@article{Kolmogorov2003,\r\n    Author = {V Kolmogorov and R Zabih},\r\n    Journal = {European Conference on Computer Vision (ECCV)},\r\n    Title = {Multi-camera Scene Reconstruction via Graph Cuts},\r\n    Year = {2003}}\r\n\r\n@article{Korf2001,\r\n    Author = {I Korf and P Flicek and D Duan and MR Brent},\r\n    Journal = {Bioinformatics},\r\n    Pages = {S140--8},\r\n    Title = {{Integrating genomic homology into gene structure prediction}},\r\n    Volume = {17 Suppl 1},\r\n    Year = {2001}}\r\n\r\n@book{Korf2003,\r\n    Address = {Sebastopol, CA},\r\n    Author = {I Korf and M Yandell and J Bedell},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {O'Reilly \\& Associates},\r\n    Title = {BLAST},\r\n    Year = {2003}}\r\n\r\n@book{Korner1989,\r\n    Address = {Cambridge},\r\n    Author = {TW K{\\\"o}rner},\r\n    Date-Modified = {2005-03-01 20:14:52 -0500},\r\n    Edition = {Second},\r\n    Isbn = {0-521-38991-7},\r\n    Mrclass = {42-01},\r\n    Mrnumber = {MR1035216 (90j:42001)},\r\n    Pages = {xii+591},\r\n    Publisher = {Cambridge University Press},\r\n    Title = {Fourier Analysis},\r\n    Year = {1989}}\r\n\r\n\r\n@Article{Korostensky2000,\r\n  author = \t {C Korostensky and G Gonnet},\r\n  title = \t {Using traveling salesman problem algorithms for evolutionary tree construction},\r\n  journal = \t {Bioinformatics},\r\n  year = \t {2000},\r\n  OPTkey = \t {},\r\n  volume = \t {16},\r\n  OPTnumber = \t {},\r\n  pages = \t {619--627},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Krogh1994,\r\n    Author = {A Krogh and M Brown and IS Mian and K Sjolander and DJ Haussler},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Molecular Biology},\r\n    Pages = {1501--31},\r\n    Title = {Hidden Markov models in computational biology. Applications to protein modeling},\r\n    Volume = {235},\r\n    Year = {1994}}\r\n\r\n@article{Kschischang2001,\r\n    Author = {F Kschischang and H Loeliger and B Frey},\r\n    Journal = {IEEE Transactions on Information Theory},\r\n    Month = feb,\r\n    Number = {2},\r\n    Title = {Factor Graphs and the Sum-Product Algorithm},\r\n    Url = {http://citeseer.ist.psu.edu/631022.html},\r\n    Volume = {47},\r\n    Year = {2001}}\r\n\r\n@article{Kuhn1955,\r\n    Author = {HW Kuhn},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Naval Research Logistics Quarterly},\r\n    Pages = {83--97},\r\n    Title = {The {H}ungarian method for the assignment problem},\r\n    Volume = {2},\r\n    Year = {1955}}\r\n\r\n@Article{Kuhner1994,\r\n  author = {MK Kuhner and J Felsenstein},\r\n  title = {A simulation comparison of phylogeny algorithms under equal\r\n                  and unequal evolutionary rates},\r\n  journal = {Molecular Biology and Evolution},\r\n  year = {1994},\r\n  OPTkey = {},\r\n  volume = {11},\r\n  pages = {459--468},\r\n  OPTpages = {},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@book{Kulisch2001,\r\n    Address = {New York},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Editor = {U Kulisch and R Lohner and A Facius},\r\n    Publisher = {Springer-Verlag},\r\n    Title = {Perspectives on Enclosure Methods},\r\n    Year = {2001}}\r\n\r\n@incollection{Kulisch2001a,\r\n    Address = {New York},\r\n    Author = {U Kulisch},\r\n    Booktitle = {Perspectives on encolsure methods},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Editor = {U Kulisch and R Lohner and A Facius},\r\n    Pages = {50--70},\r\n    Publisher = {Springer-Verlag},\r\n    Title = {Advanced arithmetic for the digital computer, interval arithmetic revisited},\r\n    Year = {2001}}\r\n\r\n@inproceedings{Kulp1996,\r\n    Author = {D Kulp and D Haussler and MG Reese and FH Eeckman},\r\n    Booktitle = {Proceedings of the Fourth International Conference on Intelligent Systems for Molecular Biology},\r\n    Isbn = {1-57735-002-2},\r\n    Pages = {134--142},\r\n    Publisher = {AAAI Press},\r\n    Title = {A Generalized Hidden {M}arkov Model for the Recognition of Human Genes in {DNA}},\r\n    Year = {1996}}\r\n\r\n@Article{Kumar2000,\r\n  author = {S Kumar and SR Gadagker},\r\n  title = {Efficiency of the neighbor-joining method in reconstructing\r\n                  evolutionary relationships in large phylogenies},\r\n  journal = {Journal of Molecular Evolution},\r\n  year = {2000},\r\n  OPTkey = {},\r\n  volume = {51},\r\n  OPTnumber = {},\r\n  pages = {544--553},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@article{Kuo2005,\r\n    Author = {E Kuo},\r\n    Journal = {Journal of Symbolic Computation},\r\n    Note = {To appear},\r\n    Title = {Viterbi Sequences and Polytopes},\r\n    Year = {2005}}\r\n\r\n@Misc{LEMON,\r\n  key = \t {Lemon graph library},\r\n  author = \t {Lemon graph library},\r\n  title = \t {{\\tt http://lemon.cs.elte.hu/trac/lemon}},\r\n  OPThowpublished = {},\r\n  OPTmonth = \t {},\r\n  OPTyear = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Lake1987,\r\n    Author = {JA Lake},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {167--191},\r\n    Title = {A rate-independent technique for analysis of nucleaic acid sequences: evolutionary parsimony},\r\n    Volume = {4},\r\n    Year = {1987}}\r\n\r\n@article{Lam1994,\r\n    Author = {W Lam and F Bacchus},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Pages = {269--293},\r\n    Title = {Learning {B}ayesian Belief Networks: {A}n approach based on the {MDL} principle},\r\n    Volume = {10},\r\n    Year = {1994}}\r\n\r\n@article{Lam2003,\r\n    Abstract = {The application of Needleman--Wunsch alignment techniques to biological sequences is complicated by two serious problems when the sequences are long: the running time, which scales as the product of the lengths of sequences, and the difficulty in obtaining suitable parameters that produce meaningful alignments. The running time problem is often corrected by reducing the search space, using techniques such as banding, or chaining of high-scoring pairs. The parameter problem is more difficult to fix, partly because the probabilistic model, which Needleman--Wunsch is equivalent to, does not capture a key feature of biological sequence alignments, namely the alternation of conserved blocks and seemingly unrelated nonconserved segments. We present a solution to the problem of designing efficient search spaces for pair hidden Markov models that align biological sequences by taking advantage of their associated features. Our approach leads to an optimization problem, for which we obtain a 2-approximation algorithm, and that is based on the construction of Manhattan networks, which are close relatives of Steiner trees. We describe the underlying theory and show how our methods can be applied to alignment of DNA sequences in practice, successfully reducing the Viterbi algorithm search space of alignment PHMMs by three orders of magnitude.},\r\n    Affiliation = {Department of Mathematics, Massachusetts Institute of Technology, Cambridge, MA 02139, USA.},\r\n    Aid = {10.1089/10665270360688156 {$[$}doi{$]$}},\r\n    Au = {Pachter L},\r\n    Author = {F Lam and M Alexandersson and L Pachter},\r\n    Da = {20030825},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20040330},\r\n    Edat = {2003/08/26 05:00},\r\n    Jid = {9433358},\r\n    Journal = {J Comput Biol},\r\n    Keywords = {Algorithms and Animals and Antigens, CD4/genetics and Computational Biology/*methods and *Data Interpretation, Statistical and Humans and Markov Chains and Mice and Research Support, Non-U.S. Gov't and Sequence Alignment/*methods},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2004/03/31 05:00},\r\n    Number = {3-4},\r\n    Own = {NLM},\r\n    Pages = {509--20},\r\n    Pl = {United States},\r\n    Pmid = {12935341},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (Antigens, CD4)},\r\n    Sb = {IM},\r\n    So = {Bioinformatics 2003 Oct;19 Suppl 2:II36-II41.},\r\n    Stat = {MEDLINE},\r\n    Title = {Picking alignments from (Steiner) trees.},\r\n    Volume = {10},\r\n    Year = {2003}}\r\n\r\n@article{Lanave1984,\r\n    Author = {CG Lanave and G Preparata and C Saccone and G Serio},\r\n    Journal = {Journal of Molecular Evolution},\r\n    Pages = {86--93},\r\n    Title = {A new method for calculating evolutionary substitution rates},\r\n    Volume = {20},\r\n    Year = {1984}}\r\n\r\n@article{Lander1988,\r\n    Author = {ES Lander and MS Waterman},\r\n    Journal = {Genomics},\r\n    Pages = {231--239},\r\n    Title = {Genomic mapping by fingerprinting random clones: a mathematical analysis},\r\n    Volume = {2},\r\n    Year = {1988}}\r\n\r\n@article{Landsberg2004,\r\n    Author = {JM Landsberg and L Manivel},\r\n    Journal = {Foundations of Computational Mathematics},\r\n    Number = {4},\r\n    Pages = {397--422},\r\n    Title = {On the Ideals of Secant Varieties of {Segre} Varieties},\r\n    Volume = {4},\r\n    Year = {2004}}\r\n\r\n@Article{Langmead2009,\r\n  author = \t {B Langmead and C Trapnell and M Pop and SL Salzberg},\r\n  title = \t {Ultrafast and memory-efficient alignment of short {DNA} sequences to the human genome},\r\n  journal = \t {Genome Biology},\r\n  year = \t {2009},\r\n  OPTkey = \t {},\r\n  volume = \t {10},\r\n  OPTnumber = \t {},\r\n  pages = \t {R25},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@inproceedings{Laubenbacher2003,\r\n    Author = {R Laubenbacher},\r\n    Booktitle = {Proceedings of the 2003 International Symposium on Symbolic and Algebraic Computation},\r\n    Optorganization = {Association for Computing Machinery},\r\n    Title = {A computer algebra approach to biological systems},\r\n    Year = {2003}}\r\n\r\n@article{Laubenbacher2004,\r\n    Author = {R Laubenbacher and B Stigler},\r\n    Journal = {Journal of Theoretical Biology},\r\n    Pages = {523--537},\r\n    Title = {A Computational Algebra Approach to the Reverse Engineering of Gene Regulatory Networks},\r\n    Volume = {229},\r\n    Year = {2004}}\r\n\r\n@article{Lauritzen1995,\r\n    Author = {SL Lauritzen},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Computational Statistics and Data Analysis},\r\n    Pages = {191--201},\r\n    Title = {The {EM} Algorithm for Graphical Association Models with Missing Data},\r\n    Volume = {19},\r\n    Year = {1995}}\r\n\r\n@book{Lauritzen1996,\r\n    Address = {New York},\r\n    Author = {SL Lauritzen},\r\n    Isbn = {0-19-852219-3},\r\n    Mrclass = {62-01 (05C90 60J99 62H05 62H10 62H17 68T30)},\r\n    Mrnumber = {MR1419991 (98g:62001)},\r\n    Mrreviewer = {M. Studen{\\'y}},\r\n    Note = {Oxford Science Publications},\r\n    Pages = {x+298},\r\n    Publisher = {The Clarendon Press Oxford University Press},\r\n    Series = {{\\rm Oxford Statistical Science Series}},\r\n    Title = {Graphical models},\r\n    Volume = {17},\r\n    Year = {1996}}\r\n\r\n@article{Lenstra1983,\r\n    Author = {HW Lenstra},\r\n    Fjournal = {Mathematics of Operations Research},\r\n    Issn = {0364-765X},\r\n    Journal = {Mathematics of Operations Research},\r\n    Mrclass = {90C10},\r\n    Mrnumber = {MR727410 (86f:90106)},\r\n    Number = {4},\r\n    Pages = {538--548},\r\n    Title = {Integer programming with a fixed number of variables},\r\n    Volume = {8},\r\n    Year = {1983}}\r\n\r\n@article{Levinson1987,\r\n    Author = {G Levinson and GA Gutman},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {203--221},\r\n    Title = {Slipped-strand mispairing: a major mechanism for {DNA} sequence evolution},\r\n    Volume = {4},\r\n    Year = {1987}}\r\n\r\n@Article{Levy2006,\r\n  Author = {D Levy and R Yoshida and L Pachter},\r\n  title =    {Beyond pairwise distances: neighbor joining with\r\n                  phylogenetic diversity estimates},\r\n  journal =      {Molecular Biology and Evolution},\r\n  year =     {2006},\r\n  OPTkey =   {},\r\n  volume =   {23},\r\n  OPTnumber =    {},\r\n  pages =    {491--498},\r\n  OPTmonth =     {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n@Article{Li2009a,\r\n  author = \t {H Li and B Handsaker and A Wysoker and T Fennell and J Ruan and N Homer and G Marth and G Abecasis and R Durbin and 1000 Genome Project Data Processing Subgroup},\r\n  title = \t {The sequence alignment/map format and {SAM}tools},\r\n  journal = \t {Bioinformatics},\r\n  year = \t {2009},\r\n  OPTkey = \t {},\r\n  volume = \t {25},\r\n  OPTnumber = \t {16},\r\n  pages = \t {2078--2079},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Li2009b,\r\n  author = \t {B Li and V Ruotti and RM Stewart and JA Thomson and CN Dewey},\r\n  title = \t {{RNA-Seq} gene expression estimation with read mapping uncertainty},\r\n  journal = \t {Bioinformatics},\r\n  year = \t {2009},\r\n  OPTkey = \t {},\r\n  volume = \t {26},\r\n  OPTnumber = \t {},\r\n  pages = \t {493--500},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Lin2002,\r\n    Author = {YH Lin and PA McLenachan and AR Gore and MJ Phillips and R Ota and MD Hendy and D Penny},\r\n    Journal = {Molecular Phylogenetics and Evolution},\r\n    Pages = {2060-2070},\r\n    Title = {Four new mitochondrial genomes and the increased stability of evolutionary trees of mammals from improved taxon sampling.},\r\n    Volume = {19},\r\n    Year = {2002}}\r\n\r\n@article{Litvinov2005,\r\n    Author = {G Litvinov},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {arXiv.org:math/0501038},\r\n    Title = {{The Maslov dequantization, idempotent and tropical mathematics: a very brief introduction}},\r\n    Year = {2005}}\r\n\r\n@article{Liu1995,\r\n    Author = {JS Liu and CE Lawrence and A Neuwald},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Journal of the American Statistical Association},\r\n    Pages = {1156--70},\r\n    Title = {{Bayesian models for multiple local sequence alignment and its Gibbs sampling strategies}},\r\n    Volume = {90},\r\n    Year = {1995}}\r\n\r\n@article{Loh2002,\r\n    Author = {E Loh and GW Walster},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Reliable Computing},\r\n    Pages = {245--248},\r\n    Title = {Rump's example revisited},\r\n    Volume = {8},\r\n    Year = {2002}}\r\n\r\n@misc{Loots2002,\r\n    Abstract = {Identifying transcriptional regulatory elements represents a significant challenge in annotating the genomes of higher vertebrates. We have developed a computational tool, rVista, for high-throughput discovery of cis-regulatory elements that combines clustering of predicted transcription factor binding sites (TFBSs) and the analysis of interspecies sequence conservation to maximize the identification of functional sites. To assess the ability of rVista to discover true positive TFBSs while minimizing the prediction of false positives, we analyzed the distribution of several TFBSs across 1 Mb of the well-annotated cytokine gene cluster (Hs5q31; Mm11). Because a large number of AP-1, NFAT, and GATA-3 sites have been experimentally identified in this interval, we focused our analysis on the distribution of all binding sites specific for these transcription factors. The exploitation of the orthologous human-mouse dataset resulted in the elimination of > 95% of the approximately 58,000 binding sites predicted on analysis of the human sequence alone, whereas it identified 88% of the experimentally verified binding sites in this region.},\r\n    Affiliation = {Genome Sciences Department, Lawrence Berkeley National Laboratory, Berkeley, California 94720, USA. ggloots@lbl.gov},\r\n    Aid = {10.1101/gr.225502. Article published online before print in April 2002 [doi]},\r\n    Au = {Rubin EM},\r\n    Author = {GG Loots and I Ovcharenko and L Pachter and I Dubchak and EM Rubin},\r\n    Da = {20020508},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Dcom = {20020605},\r\n    Edat = {2002/05/09 10:00},\r\n    Jid = {9518021},\r\n    Journal = {Genome Research},\r\n    Keywords = {Animals and Base Sequence/genetics and Binding Sites/genetics and Comparative Study and Computational Biology/methods and Cytokines/chemistry/genetics and Humans and Mice and Multigene Family/genetics and Promoter Regions (Genetics)/genetics and Research Support, U.S. Gov't, Non-P.H.S. and Research Support, U.S. Gov't, P.H.S. and *Software and Transcription Factors/*chemistry/*genetics},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2002/06/06 10:01},\r\n    Number = {5},\r\n    Own = {NLM},\r\n    Pages = {832--9},\r\n    Pl = {United States},\r\n    Pmid = {11997350},\r\n    Pst = {ppublish},\r\n    Pt = {Validation Studies},\r\n    Pubm = {Print},\r\n    Rn = {0 (Transcription Factors)},\r\n    Sb = {IM},\r\n    So = {Brief Bioinform 2002 Mar;3(1):18-22.},\r\n    Stat = {MEDLINE},\r\n    Title = {rVista for comparative sequence-based discovery of functional transcription factor binding sites.},\r\n    Volume = {12},\r\n    Year = {2002}}\r\n\r\n@Book{Lovasz2009,\r\n  author = \t {L L\\'{o}vasz and MD Plummer},\r\n  ALTeditor = \t {},\r\n  title = \t {{Matching Theory}},\r\n  publisher = \t {American Mathematical Society Press},\r\n  year = \t {2009},\r\n  OPTkey = \t {},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{MAVID,\r\n    Author = {MAVID},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Note = {http://baboon.math.berkeley.edu/mavid},\r\n    Title = {http://baboon.math.berkeley.edu/mavid}}\r\n\r\n@unpublished{MLAGAN,\r\n    Author = {MLAGAN},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Note = {http://lagan.stanford.edu/},\r\n    Title = {http://lagan.stanford.edu/}}\r\n\r\n@article{Madsen2001,\r\n    Author = {O Madsen and M Scally and CJ Douady and DJ Kao and RW Debry and R Adkins and HM Ambrine and MJ Stanhope and WW DeJong and MS Springer},\r\n    Journal = {Nature},\r\n    Pages = {610-614},\r\n    Title = {{Parallel adaptive radiations in two major clades of placental mammals.}},\r\n    Volume = {409},\r\n    Year = {2001}}\r\n\r\n@article{Marcotte1999,\r\n    Author = {EM Marcotte and M Pellegrini and MJ Thompson and T Yeates and D Eisenberg},\r\n    Journal = {Nature},\r\n    Pages = {83--86},\r\n    Title = {A Combined Algorithm for Genome-Wide Prediction of Protein Function},\r\n    Volume = {402},\r\n    Year = {1999}}\r\n\r\n@article{Mayor2000,\r\n    Abstract = {Summary: VISTA is a program for visualizing global DNA sequence alignments of arbitrary length. It has a clean output, allowing for easy identification of similarity, and is easily configurable, enabling the visualization of alignments of various lengths at different levels of resolution. It is currently available on the web, thus allowing for easy access by all researchers. Availability: VISTA server is available on the web at http://www-gsd.lbl.gov/vista. The source code is available upon request. Contact: vista@lbl.gov},\r\n    Affiliation = {National Energy Research Scientific Computing Center Genome Sciences Department, Berkeley, CA 94720, USA. vista@lbl.gov},\r\n    Au = {Dubchak I},\r\n    Author = {Mayor, C and Brudno, M and Schwartz, J R and Poliakov, A and Rubin, E M and Frazer, K A and Pachter, L S and Dubchak, I},\r\n    Da = {20010222},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Dcom = {20010419},\r\n    Edat = {2001/02/13 11:00},\r\n    Gr = {GM-5748202/GM/NIGMS},\r\n    Jid = {9808944},\r\n    Journal = {Bioinformatics},\r\n    Keywords = {Animals and Computational Biology and DNA/*genetics and Humans and Internet and Mice and Rabbits and Research Support, U.S. Gov't, Non-P.H.S. and Research Support, U.S. Gov't, P.H.S. and Sequence Alignment/*statistics \\& numerical data and *Software},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2001/04/21 10:01},\r\n    Number = {11},\r\n    Own = {NLM},\r\n    Pages = {1046--7},\r\n    Pl = {England},\r\n    Pmid = {11159318},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {9007-49-2 (DNA)},\r\n    Sb = {IM},\r\n    So = {Genome Res 2001 May;11(5):710-30.},\r\n    Stat = {MEDLINE},\r\n    Title = {VISTA : visualizing global DNA sequence alignments of arbitrary length.},\r\n    Volume = {16},\r\n    Year = {2000}}\r\n\r\n\r\n@article{McAuliffe2004,\r\n    Abstract = {MOTIVATION: Phylogenetic shadowing is a comparative genomics principle that allows for the discovery of conserved regions in sequences from multiple closely related organisms. We develop a formal probabilistic framework for combining phylogenetic shadowing with feature-based functional annotation methods. The resulting model, a generalized hidden {Markov} phylogeny (GHMP), applies to a variety of situations where functional regions are to be inferred from evolutionary constraints. RESULTS: We show how GHMPs can be used to predict complete shared gene structures in multiple primate sequences. We also describe shadower, our implementation of such a prediction system. We find that shadower outperforms previously reported ab initio gene finders, including comparative human-mouse approaches, on a small sample of diverse exonic regions. Finally, we report on an empirical analysis of shadower's performance which reveals that as few as five well-chosen species may suffice to attain maximal sensitivity and specificity in exon demarcation. AVAILABILITY: A Web server is available at http://bonaire.lbl.gov/shadower},\r\n    Affiliation = {Department of Statistics, University of California, 367 Evans Hall, Berkeley, CA 94720, USA.},\r\n    Aid = {bth153 {$[$}pii{$]$}},\r\n    Au = {Jordan MI},\r\n    Author = {JD McAuliffe and L Pachter and MI Jordan},\r\n    Da = {20040812},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dep = {20040226},\r\n    Edat = {2004/02/28 05:00},\r\n    Gr = {R01-HG02362-02/HG/NHGRI},\r\n    Jid = {9808944},\r\n    Journal = {Bioinformatics},\r\n    Language = {eng},\r\n    Mhda = {2004/02/28 05:00},\r\n    Number = {12},\r\n    Own = {NLM},\r\n    Pages = {1850-60},\r\n    Phst = {2004/02/26 {$[$}aheadofprint{$]$}},\r\n    Pl = {England},\r\n    Pmid = {14988105},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print-Electronic},\r\n    Sb = {IM},\r\n    So = {Nature 2004 Apr 1;428(6982):493-521.},\r\n    Stat = {In-Process},\r\n    Title = {Multiple-sequence functional annotation and the generalized hidden {M}arkov phylogeny.},\r\n    Volume = {20},\r\n    Year = {2004}}\r\n\r\n\r\n@article{McMullen1971,\r\n    Author = {P McMullen},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Journal of Combinatorial Theory, Series B},\r\n    Pages = {179--184},\r\n    Title = {The maximum numbers of faces of a convex polytope},\r\n    Volume = {10},\r\n    Year = {1971}}\r\n\r\n@article{Megiddo1984,\r\n    Author = {N Megiddo},\r\n    Coden = {JACOAH},\r\n    Fjournal = {Journal of the Association for Computing Machinery},\r\n    Issn = {0004-5411},\r\n    Journal = {Journal of the Association for Computing Machinery},\r\n    Mrclass = {90C05},\r\n    Mrnumber = {MR821388 (87b:90082)},\r\n    Number = {1},\r\n    Pages = {114--127},\r\n    Title = {Linear programming in linear time when the dimension is fixed},\r\n    Volume = {31},\r\n    Year = {1984}}\r\n\r\n@unpublished{Mihaescu2005,\r\n    Author = {R Mihaescu},\r\n    Date-Modified = {2005-02-28 12:49:27 -0800},\r\n    Note = {In preparation},\r\n    Title = {The Toric Ideal of the Unhidden {M}arkov Model.},\r\n    Year = {2005}}\r\n\r\n@Unpublished{Mihaescu2006,\r\n  author = \t {R Mihaescu and D Levy and L Pachter},\r\n  title = \t {Why neighbor joining works},\r\n  note = \t {arXiv cs.DS/0602041},\r\n  OPTkey = \t {},\r\n  OPTmonth = \t {},\r\n  year = \t {2006},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Miller2001,\r\n    Author = {W Miller},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Bioinformatics},\r\n    Pages = {391--397},\r\n    Title = {Comparison of genomic DNA sequences: solved and unsolved problems},\r\n    Volume = {17},\r\n    Year = {2001}}\r\n\r\n@article{Mindell1990,\r\n    Author = {DP Mindell and RL Honeycutt},\r\n    Journal = {Annual Review of Ecology and Systematics},\r\n    Pages = {541--566},\r\n    Title = {Ribosomal {RNA} in vertebrates: evolution and phylogenetic applications.},\r\n    Volume = {21},\r\n    Year = {1990}}\r\n\r\n@article{Mitchison1999,\r\n    Author = {GJ Mitchison},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Molecular Evolution},\r\n    Number = {1},\r\n    Pages = {11--22},\r\n    Title = {A Probabilistic Treatment of Phylogeny and Sequence Alignment},\r\n    Volume = {49},\r\n    Year = {1999}}\r\n\r\n\r\n\r\n@article{Mond2003,\r\n    Author = {DMQ Mond and JQ Smith and D Van Straten},\r\n    Journal = {Proceedings of the Royal Society of London, Series A},\r\n    Pages = {2821--2845},\r\n    Title = {Stochastic factorisations, sandwiched simplices and the topology of the space of explanations},\r\n    Volume = {459},\r\n    Year = {2003}}\r\n\r\n@book{Moore1967,\r\n    Address = {Englewood Cliffs, New Jersey},\r\n    Author = {RE Moore},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Prentice-Hall},\r\n    Title = {Interval Analysis},\r\n    Year = {1967}}\r\n\r\n@book{Moore1979,\r\n    Address = {Philadelphia, Pennsylvania},\r\n    Author = {RE Moore},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {SIAM},\r\n    Title = {Methods and Applications of Interval analysis},\r\n    Year = {1979}}\r\n\r\n@Article{Moret2004,\r\n  author = \t {BE Moret and L Nakhleh and T Warnow and CR Linder and A Tholse and A Padolina and J Sun and R Timme},\r\n  title = \t {Phylogenetic networks: modeling reconstructibility and accuracy},\r\n  journal = \t {IEEE/ACM Transactions on Computational Biology and Bioinformatics},\r\n  year = \t {2004},\r\n  OPTkey = \t {},\r\n  volume = \t {1},\r\n  OPTnumber = \t {1},\r\n  pages = \t {13--23},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Morgenstern1996,\r\n    Author = {B Morgenstern and A Dress and T Werner},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Proceedings of the National Academy of Sciences, USA},\r\n    Pages = {12098--12103},\r\n    Title = {Multiple DNA and protein sequence alignment based on segment-to-segment comparison},\r\n    Volume = {93},\r\n    Year = {1996}}\r\n\r\n\r\n\r\n@article{Morgenstern1999,\r\n    Author = {B Morgenstern},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Bioinformatics},\r\n    Pages = {211--218},\r\n    Title = {DIALIGN 2: Improvement of the segment-to-segment approach to multiple sequence alignment},\r\n    Volume = {15},\r\n    Year = {1999}}\r\n\r\n\r\n\r\n\r\n@article{Morgenstern2000,\r\n    Author = {B Morgenstern},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Bioinformatics},\r\n    Pages = {948--949},\r\n    Title = {A space-efficient algorithm for aligning large genomic sequences},\r\n    Volume = {16},\r\n    Year = {2000}}\r\n\r\n@Article{Mortazavi2008,\r\n  author = \t {A Mortazavi and BA Williams and K McCue and L Schaeffer and B Wold},\r\n  title = \t {Mapping and quantifying mammalian transcriptomes by {RNA-Seq}},\r\n  journal = \t {Nature Methods},\r\n  year = \t {2008},\r\n  OPTkey = \t {},\r\n  volume = \t {5},\r\n  OPTnumber = \t {7},\r\n  pages = \t {585--587},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Mount1982,\r\n    Author = {SM Mount},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Nucleic Acids Research},\r\n    Number = {2},\r\n    Pages = {459--472},\r\n    Title = {A catalogue of splice junction sequence},\r\n    Volume = {10},\r\n    Year = {1982}}\r\n\r\n@inproceedings{Murphy1999,\r\n    Author = {KP Murphy and Y Weiss and MI Jordan},\r\n    Booktitle = {Proceedings of the Uncertainty in Artificial Intelligence Conference},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Pages = {467--475},\r\n    Title = {Loopy belief propagation for approximate inference: an empirical study},\r\n    Year = {1999}}\r\n\r\n@article{Murphy2001,\r\n    Author = {WJ Murphy and E Eizirik and WE Johnson and YP Zhang and OA Ryder and SJ O'Brien.},\r\n    Journal = {Nature},\r\n    Pages = {614--618},\r\n    Title = {Molecular phylogenetics and the origins of placental mammals.},\r\n    Volume = {409},\r\n    Year = {2001}}\r\n\r\n@article{Myers1999,\r\n    Author = {E Myers},\r\n    Journal = {IEEE Computational Engineering and Science},\r\n    Number = {1},\r\n    Pages = {33--43},\r\n    Title = {Whole-Genome {DNA} Sequencing},\r\n    Volume = {3},\r\n    Year = {1999}}\r\n\r\n@book{Na1990,\r\n    Author = {A Neumaier},\r\n    Optaddress = {Cambridge},\r\n    Publisher = {Cambridge university press},\r\n    Title = {Interval Methods for Systems of Equations},\r\n    Year = {1990}}\r\n\r\n@article{Nakhleh2003,\r\n    Author = {L Nakhleh and J Sun and T Warnow and CR Linder and BME Moret and A Tholse},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Proceedings of the Eighth Pacific Symposium on Biocomputing (PSB 03)},\r\n    Title = {Towards the Development of Computational Tools for Evaluating Phylogenetic Network Reconstruction Methods},\r\n    Year = {2003}}\r\n\r\n@article{Nasrallah2002,\r\n    Author = {JB Nasrallah},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Science},\r\n    Pages = {305--308},\r\n    Title = {Recognition and rejection of self in plant reproduction},\r\n    Volume = {296},\r\n    Year = {2002}}\r\n\r\n@article{Needleman1970,\r\n    Author = {SB Needleman and CD Wunsch},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Molecular Biology},\r\n    Pages = {443--445},\r\n    Title = {A general method applicable to the search for similarities in the amino acid sequence of two proteins},\r\n    Volume = {48},\r\n    Year = {1970}}\r\n\r\n@book{Neumaier1990,\r\n    Address = {Cambridge},\r\n    Author = {A Neumaier},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Cambridge university press},\r\n    Title = {Interval methods for systems of equations},\r\n    Year = {1990}}\r\n\r\n@Article{Newberg1996,\r\n  author = \t {LA Newberg},\r\n  title = \t {The number of clone orderings},\r\n  journal = \t {Discrete Applied Mathematics},\r\n  year = \t {1996},\r\n  OPTkey = \t {},\r\n  volume = \t {69},\r\n  OPTnumber = \t {},\r\n  pages = \t {233--245},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@incollection{Neyman1971,\r\n    Address = {New York},\r\n    Author = {J Neyman},\r\n    Booktitle = {Statistical Decision Theory and Related Topics},\r\n    Editor = {S Gupta and Y Jackel},\r\n    Pages = {1--27},\r\n    Publisher = {Academic Press},\r\n    Title = {Molecular studies of evolution: {A} source of novel statistical problems},\r\n    Year = {1971}}\r\n\r\n@article{Ng1985,\r\n    Author = {SY Ng and P Gunning and R Eddy and P Ponte and J Leavitt and T Shows and L Kedes},\r\n    Journal = {Molecular and Cellular Biology},\r\n    Pages = {2720--2732},\r\n    Title = {Evolution of the functional human beta-actin gene and its multi-pseudogene family: conservation of noncoding regions and chromosomal dispersion of pseudogenes},\r\n    Volume = {5},\r\n    Year = {1985}}\r\n\r\n@article{Nobrega2003,\r\n    Author = {MA Nobrega and I Ovcharenko and V Afzal and EM Rubin},\r\n    Eprint = {http://www.sciencemag.org/cgi/reprint/302/5644/413.pdf},\r\n    Journal = {Science},\r\n    Number = {5644},\r\n    Pages = {413-},\r\n    Title = {Scanning Human Gene Deserts for Long-Range Enhancers},\r\n    Url = {\\url{http://www.sciencemag.org}},\r\n    Volume = {302},\r\n    Year = {2003}}\r\n\r\n@article{Notredame2000,\r\n    Author = {C Notredame and D Higgins and J Heringa},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Journal of Molecular Biology},\r\n    Pages = {205--217},\r\n    Title = {T-Coffee: A novel method for multiple sequence alignments},\r\n    Volume = {302},\r\n    Year = {2000}}\r\n\r\n\r\n@Article{Olsen1994,\r\n  author = {GJ Olsen and H Matsuda and R Hagstrom and R Overbeek},\r\n  title = {{fastDNAml: A tool for construction of phylogenetic trees\r\n                  of DNA sequences using maximum likelihood}},\r\n  journal = {Computational Applied Biosciences},\r\n  year = {1994},\r\n  OPTkey = {},\r\n  volume = {10},\r\n  OPTnumber = {},\r\n  pages = {41--48},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@article{Ota2000,\r\n    Author = {S Ota and WH Li},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Number = {9},\r\n    Pages = {1401--1409},\r\n    Title = {{NJML}: A Hybrid Algorithm for the Neighbor-Joining and Maximum Likelihood Methods},\r\n    Volume = {17},\r\n    Year = {2000}}\r\n\r\n@article{Pachter1999,\r\n    Abstract = {This paper describes a fast and fully automated dictionary-based approach to gene annotation and exon prediction. Two dictionaries are constructed, one from the nonredundant protein OWL database and the other from the dbEST database. These dictionaries are used to obtain O (1) time lookups of tuples in the dictionaries (4 tuples for the OWL database and 11 tuples for the dbEST database). These tuples can be used to rapidly find the longest matches at every position in an input sequence to the database sequences. Such matches provide very useful information pertaining to locating common segments between exons, alternative splice sites, and frequency data of long tuples for statistical purposes. These dictionaries also provide the basis for both homology determination, and statistical approaches to exon prediction.},\r\n    Affiliation = {Department of Mathematics, Massachusetts Institute of Technology, Cambridge 02139, USA.},\r\n    Aid = {10.1089/106652799318364 {$[$}doi{$]$}},\r\n    Au = {Berger B},\r\n    Author = {L Pachter and S Batzoglou and VI Spitkovsky and E Banks and ES Lander and DJ Kleitman and B Berger},\r\n    Da = {19991230},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {19991230},\r\n    Edat = {1999/12/03},\r\n    Jid = {9433358},\r\n    Journal = {J Comput Biol},\r\n    Keywords = {Alternative Splicing and Animals and *Databases, Factual and *Dictionaries and Exons and Expressed Sequence Tags and *Genes and Genetic Techniques and Humans and Proteins/genetics and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, P.H.S. and Sequence Alignment/statistics \\& numerical data and Software},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {1999/12/03 00:01},\r\n    Number = {3-4},\r\n    Own = {NLM},\r\n    Pages = {419--30},\r\n    Pl = {UNITED STATES},\r\n    Pmid = {10582576},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (Proteins)},\r\n    Sb = {IM},\r\n    So = {Genome Res 2000 Jul;10(7):950-8.},\r\n    Stat = {MEDLINE},\r\n    Title = {A dictionary-based approach for gene annotation.},\r\n    Volume = {6},\r\n    Year = {1999}}\r\n\r\n@article{Pachter2002,\r\n    Abstract = {Hidden Markov models (HMMs) have been successfully applied to a variety of problems in molecular biology, ranging from alignment problems to gene finding and annotation. Alignment problems can be solved with pair HMMs, while gene finding programs rely on generalized HMMs in order to model exon lengths. In this paper, we introduce the generalized pair HMM (GPHMM), which is an extension of both pair and generalized HMMs. We show how GPHMMs, in conjunction with approximate alignments, can be used for cross-species gene finding and describe applications to DNA-cDNA and DNA-protein alignment. GPHMMs provide a unifying and probabilistically sound theory for modeling these problems.},\r\n    Affiliation = {Department of Mathematics, University of California Berkeley, Berkeley, CA 94720, USA. lpachter@math.berkeley.edu},\r\n    Aid = {10.1089/10665270252935520 {$[$}doi{$]$}},\r\n    Au = {Cawley S},\r\n    Author = {L Pachter and M Alexandersson and S Cawley},\r\n    Da = {20020517},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20021004},\r\n    Edat = {2002/05/23 10:00},\r\n    Jid = {9433358},\r\n    Journal = {J Comput Biol},\r\n    Keywords = {Algorithms and Computational Biology and DNA/genetics and *Markov Chains and Models, Statistical and Proteins/genetics and Research Support, Non-U.S. Gov't and Sequence Alignment/*statistics \\& numerical data},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2002/10/09 04:00},\r\n    Number = {2},\r\n    Own = {NLM},\r\n    Pages = {389--99},\r\n    Pl = {United States},\r\n    Pmid = {12015888},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {9007-49-2 (DNA)},\r\n    Sb = {IM},\r\n    So = {Nature 2002 Dec 5;420(6915):520-62.},\r\n    Stat = {MEDLINE},\r\n    Title = {{Applications of generalized pair hidden Markov models to alignment and gene finding problems}},\r\n    Volume = {9},\r\n    Year = {2002}}\r\n\r\n@article{Pachter2004,\r\n    Author = {L Pachter and D Speyer},\r\n    Coden = {AMLEEL},\r\n    Date-Modified = {2005-02-05 13:00:15 -0800},\r\n    Fjournal = {Applied Mathematics Letters. An International Journal of Rapid Publication},\r\n    Issn = {0893-9659},\r\n    Journal = {Applied Mathematics Letters},\r\n    Mrclass = {05C05 (05C85 92D15)},\r\n    Mrnumber = {MR2064171 (2005b:05066)},\r\n    Number = {6},\r\n    Pages = {615--621},\r\n    Title = {Reconstructing trees from subtree weights},\r\n    Volume = {17},\r\n    Year = {2004}}\r\n\r\n@article{Pachter2004b,\r\n    Abstract = {One of the major successes in computational biology has been the unification, by using the graphical model formalism, of a multitude of algorithms for annotating and comparing biological sequences. Graphical models that have been applied to these problems include hidden Markov models for annotation, tree models for phylogenetics, and pair hidden Markov models for alignment. A single algorithm, the sum-product algorithm, solves many of the inference problems that are associated with different statistical models. This article introduces the polytope propagation algorithm for computing the Newton polytope of an observation from a graphical model. This algorithm is a geometric version of the sum-product algorithm and is used to analyze the parametric behavior of maximum a posteriori inference calculations for graphical models.},\r\n    Affiliation = {Department of Mathematics, University of California, Berkeley, CA 94720, USA. lpachter@math.berkeley.edu},\r\n    Aid = {10.1073/pnas.0406011101 {$[$}doi{$]$}},\r\n    Au = {Sturmfels B},\r\n    Author = {L Pachter and B Sturmfels},\r\n    Da = {20041119},\r\n    Date-Modified = {2005-02-05 13:00:15 -0800},\r\n    Dcom = {20041227},\r\n    Dep = {20041108},\r\n    Edat = {2004/11/10 09:00},\r\n    Gr = {R01-HG02362-02/HG/NHGRI},\r\n    Jid = {7505876},\r\n    Journal = {Proc Natl Acad Sci U S A},\r\n    Keywords = {Algorithms and Markov Chains and Models, Statistical and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, Non-P.H.S. and Research Support, U.S. Gov't, P.H.S. and Sequence Alignment/statistics \\& numerical data and Sequence Analysis/*statistics \\& numerical data and Sequence Analysis, DNA/statistics \\& numerical data},\r\n    Language = {eng},\r\n    Lr = {20050121},\r\n    Mhda = {2004/12/28 09:00},\r\n    Number = {46},\r\n    Own = {NLM},\r\n    Pages = {16138--43},\r\n    Phst = {2004/11/08 {$[$}aheadofprint{$]$}},\r\n    Pl = {United States},\r\n    Pmid = {15534223},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print-Electronic},\r\n    Sb = {IM},\r\n    So = {Proc Natl Acad Sci U S A 2004 Nov 16;101(46):16132-7. Epub 2004 Nov 08.},\r\n    Stat = {MEDLINE},\r\n    Title = {Parametric inference for biological sequence analysis.},\r\n    Volume = {101},\r\n    Year = {2004}}\r\n\r\n@article{Pachter2004c,\r\n    Abstract = {This article presents a unified mathematical framework for inference in graphical models, building on the observation that graphical models are algebraic varieties. From this geometric viewpoint, observations generated from a model are coordinates of a point in the variety, and the sum-product algorithm is an efficient tool for evaluating specific coordinates. Here, we address the question of how the solutions to various inference problems depend on the model parameters. The proposed answer is expressed in terms of tropical algebraic geometry. The Newton polytope of a statistical model plays a key role. Our results are applied to the hidden Markov model and the general Markov model on a binary tree.},\r\n    Affiliation = {Department of Mathematics, University of California, Berkeley, CA 94720, USA.},\r\n    Aid = {10.1073/pnas.0406010101 {$[$}doi{$]$}},\r\n    Au = {Sturmfels B},\r\n    Author = {L Pachter and B Sturmfels},\r\n    Da = {20041119},\r\n    Date-Modified = {2005-02-05 13:00:15 -0800},\r\n    Dcom = {20041227},\r\n    Dep = {20041108},\r\n    Edat = {2004/11/10 09:00},\r\n    Gr = {R01-HG02362-02/HG/NHGRI},\r\n    Jid = {7505876},\r\n    Journal = {Proceedings of the National Academy of Sciences, USA},\r\n    Keywords = {Algorithms and Markov Chains and Mathematics and *Models, Statistical and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, Non-P.H.S. and Research Support, U.S. Gov't, P.H.S.},\r\n    Language = {eng},\r\n    Lr = {20050121},\r\n    Mhda = {2004/12/28 09:00},\r\n    Number = {46},\r\n    Own = {NLM},\r\n    Pages = {16132-7},\r\n    Phst = {2004/11/08 {$[$}aheadofprint{$]$}},\r\n    Pl = {United States},\r\n    Pmid = {15534224},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print-Electronic},\r\n    Sb = {IM},\r\n    So = {Nature 2004 Dec 9;432(7018):695-716.},\r\n    Stat = {MEDLINE},\r\n    Title = {Tropical geometry of statistical models.},\r\n    Volume = {101},\r\n    Year = {2004}}\r\n\r\n@article{Pachter2005,\r\n    Author = {L Pachter and B Sturmfels},\r\n    Date-Modified = {2005-02-05 13:00:15 -0800},\r\n    Journal = {SIAM Review, in press},\r\n    Title = {The Mathematics of Phylogenomics},\r\n    Year = {2005}}\r\n\r\n@article{Park1998,\r\n    Author = {J Park and K Karplus and C Barrett and R Hughey and D Haussler and T Hubbard and C Chothia},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Journal of Molecular Biology},\r\n    Pages = {1201--1210},\r\n    Title = {Sequence Comparisons Using Multiple Sequences Detect Three Times as Many Remote Homolgues as Pairwise Methods},\r\n    Volume = {284},\r\n    Year = {1998}}\r\n\r\n@article{Parra2000,\r\n    Author = {G Parra and E Blanco and R Guig\\'{o}},\r\n    Journal = {Genome Research},\r\n    Number = {4},\r\n    Pages = {511--515},\r\n    Title = {{GENEID} in Drosophila},\r\n    Volume = {10},\r\n    Year = {2000}}\r\n\r\n@Article{Pauplin2000,\r\n  author =   {Y Pauplin},\r\n  title =    {Direct calculation of tree length using a distance matrix},\r\n  journal =      {Journal of Molecular Evolution},\r\n  year =     {2000},\r\n  OPTkey =   {},\r\n  volume =   {51},\r\n  OPTnumber =    {},\r\n  pages =    {41--47},\r\n  OPTmonth =     {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n@Article{Pe'er2004,\r\n  author = \t {I Pe'er and JS Beckmann},\r\n  title = \t {Recovering Frequencies of Known Haplotype Blocks From Single-Nucleotide Polymorphism Allele Frequencies},\r\n  journal = \t {Genetics},\r\n  year = \t {2004},\r\n  OPTkey = \t {},\r\n  volume = \t {166},\r\n  OPTnumber = \t {},\r\n  pages = \t {2001--2006},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@book{Pearl1988,\r\n    Address = {San Francisco},\r\n    Author = {J Pearl},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Morgan Kaufmann},\r\n    Title = {Probabilistic Reasoning in Intelligent Systems},\r\n    Year = {1988}}\r\n\r\n@article{Pennacchio2001,\r\n    Author = {LA Pennacchio and EM Rubin},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Nature Review Genetics},\r\n    Pages = {100--109},\r\n    Title = {Genomic strategies to identify mammalian regulatory sequences},\r\n    Volume = {2},\r\n    Year = {2001}}\r\n\r\n@article{Peter2002,\r\n    Abstract = {The Drosophila melanogaster genome consists of four chromosomes that contain 165 Mb of DNA, 120 Mb of which are euchromatic. The two Drosophila Genome Projects, in collaboration with Celera Genomics Systems, have sequenced the genome, complementing the previously established physical and genetic maps. In addition, the Berkeley Drosophila Genome Project has undertaken large-scale functional analysis based on mutagenesis by transposable P element insertions into autosomes. Here, we present a large-scale P element insertion screen for vital gene functions and a BAC tiling map for the X chromosome. A collection of 501 X-chromosomal P element insertion lines was used to map essential genes cytogenetically and to establish short sequence tags (STSs) linking the insertion sites to the genome. The distribution of the P element integration sites, the identified genes and transcription units as well as the expression patterns of the P-element-tagged enhancers is described and discussed.},\r\n    Affiliation = {Max-Planck-Institut fur Biophysikalische Chemie, Abt. Molekulare Entwicklungsbiologie, Am Fassberg, 37077 Gottingen, Germany.},\r\n    Aid = {kvf012 {$[$}pii{$]$}},\r\n    Au = {Schafer U},\r\n    Author = {A Peter and P Schottler and M Werner and N Beinert and G Dowe and P Burkert and F Mourkioti and L Dentzer and Y He and P Deak and others},\r\n    Da = {20020118},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20020923},\r\n    Dep = {20011219},\r\n    Edat = {2001/12/26 10:00},\r\n    Jid = {100963049},\r\n    Journal = {EMBO Rep},\r\n    Keywords = {Animals and *Chromosome Mapping and Chromosomes, Artificial, Bacterial and Contig Mapping and DNA Probes and DNA Transposable Elements and Drosophila melanogaster/*genetics and Female and Genes, Essential and Genes, Insect and Male and Mutagenesis and Research Support, Non-U.S. Gov't and *X Chromosome},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2002/09/30 10:00},\r\n    Number = {1},\r\n    Own = {NLM},\r\n    Pages = {34--8},\r\n    Phst = {2001/12/19 {$[$}aheadofprint{$]$}},\r\n    Pl = {England},\r\n    Pmid = {11751581},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print-Electronic},\r\n    Rn = {0 (DNA Transposable Elements)},\r\n    Sb = {IM},\r\n    So = {Genome Res 2002 May;12(5):832--9.},\r\n    Stat = {MEDLINE},\r\n    Title = {Mapping and identification of essential gene functions on the X chromosome of Drosophila.},\r\n    Volume = {3},\r\n    Year = {2002}}\r\n\r\n@article{Peters2000,\r\n    Author = {T Peters and R Dildrop and K Ausmeier and U Ruther},\r\n    Journal = {Genome Research},\r\n    Pages = {1453--1462},\r\n    Title = {Organization of Mouse Iroquois Homeobox Genes in Two Clusters Suggests a Conserved Regulation and Function in Vertebrate Development},\r\n    Volume = {10},\r\n    Year = {2000}}\r\n\r\n@article{Pevzner2003,\r\n    Author = {P Pevzner and G Tesler},\r\n    Journal = {Genome Research},\r\n    Pages = {37--45},\r\n    Title = {Genome rearrangements in mammalian evolution: lessons from human and mouse genomes},\r\n    Volume = {13(1)},\r\n    Year = {2003}}\r\n\r\n@article{Phillips2003,\r\n    Author = {MJ Phillips and D Penny},\r\n    Journal = {Molecular Phylogenetics and Evolution},\r\n    Pages = {171-185},\r\n    Title = {The root of the mammalian tree inferred from whole mitochondrial genomes.},\r\n    Volume = {28},\r\n    Year = {2003}}\r\n\r\n@incollection{Pin1998,\r\n    Address = {Cambridge},\r\n    Author = {Pin, Jean-Eric},\r\n    Booktitle = {Idempotency (Bristol, 1994)},\r\n    Mrclass = {16Y60 (68Q45 68Q70)},\r\n    Mrnumber = {MR1608374 (99a:16045)},\r\n    Mrreviewer = {C. J. Maxson},\r\n    Pages = {50--69},\r\n    Publisher = {Cambridge Univ. Press},\r\n    Series = {Publ. Newton Inst.},\r\n    Title = {Tropical semirings},\r\n    Volume = {11},\r\n    Year = {1998}}\r\n\r\n@book{Pistone2000,\r\n    Author = {G Pistone and E Riccomagno and HP Wynn},\r\n    Month = {December},\r\n    Publisher = {Chapman \\& Hall/CRC},\r\n    Title = {Algebraic Statistics: Computational Commutative Algebra in Statistics},\r\n    Year = {2000}}\r\n\r\n@incollection{Pistone2001,\r\n    Address = {Providence, RI},\r\n    Author = {Pistone, Giovanni and Riccomagno, Eva and Wynn, Henry P.},\r\n    Booktitle = {Algebraic methods in statistics and probability (Notre Dame, IN, 2000)},\r\n    Mrclass = {62B15 (13P99 62H17 62J05 62J12 68W30)},\r\n    Mrnumber = {MR1873681 (2002m:62017)},\r\n    Pages = {267--282},\r\n    Publisher = {American Mathematical Society},\r\n    Series = {Contemporary Mathematics},\r\n    Title = {Computational commutative algebra in discrete statistics},\r\n    Volume = {287},\r\n    Year = {2001}}\r\n\r\n@article{Pollard2001,\r\n    Author = {TD Pollard},\r\n    Journal = {Nature},\r\n    Pages = {842--843},\r\n    Title = {Genomics, the cytoskeleton and motility},\r\n    Volume = {409},\r\n    Year = {2001}}\r\n\r\n\r\n\r\n@book{Preparata1985,\r\n    Address = {New York},\r\n    Author = {F Preparata and MI Shamos},\r\n    Isbn = {0-387-96131-3},\r\n    Publisher = {Springer},\r\n    Series = {Texts and Monographs in Computer Science},\r\n    Title = {Computational Geometry: An Introduction},\r\n    Year = {1985}}\r\n\r\n@book{Press2002,\r\n    Address = {Cambridge},\r\n    Author = {WH Press and SA Teukolsky and WT Vetterling and BP Flannery},\r\n    Date-Modified = {2005-02-05 13:12:03 -0800},\r\n    Isbn = {0-521-75033-4},\r\n    Mrclass = {65-04},\r\n    Mrnumber = {MR1880993 (2003a:65005)},\r\n    Note = {The art of scientific computing, Second edition, updated for C++},\r\n    Pages = {xxviii+1002},\r\n    Publisher = {Cambridge University Press},\r\n    Title = {Numerical recipes in {C}{\\bf++}},\r\n    Year = {2002}}\r\n\r\n@manual{R2004,\r\n    Address = {Vienna, Austria},\r\n    Author = {{R Development Core Team}},\r\n    Note = {3-900051-07-0},\r\n    Organization = {R Foundation for Statistical Computing},\r\n    Title = {R: A language and environment for statistical computing},\r\n    Url = {http://www.R-project.org},\r\n    Year = 2004}\r\n\r\n@article{Radmacher2001,\r\n    Author = {MD Radmacher and R Simon and R Desper and R Taetle and AA Sch{\\\"a}ffer and MA Nelson},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Theoretical Biology},\r\n    Pages = {535--548},\r\n    Title = {Graph models of oncogenesis with an application to melanoma},\r\n    Volume = {212},\r\n    Year = {2001}}\r\n\r\n@article{Rahnenfuehrer2005,\r\n    Author = {J Rahnenf{\\\"u}hrer and N Beerenwinkel and WA Schulz and C Hartmann and A von Deimling and B Wullich and T Lengauer},\r\n    Journal = {Bioinformatics},\r\n    Note = {To appear},\r\n    Title = {Estimating cancer survival and clinical outcome based on genetic tumor progression scores},\r\n    Year = {2005}}\r\n\r\n@article{Rahnenfuhrer,\r\n    Author = {J Rahnenf{\\\"u}hrer and N Beerenwinkel and WA Schulz and C Hartmann and A von Deimling and B Wullich and T Lengauer},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Bioinformatics},\r\n    Note = {Submitted},\r\n    Title = {Estimating cancer survival and clinical outcome based on genetic tumor progression scores}}\r\n\r\n@book{Rall1981,\r\n    Address = {New York},\r\n    Author = {LB Rall},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {Springer-Verlag},\r\n    Series = {{\\rm Springer Lecture Notes in Computer Science}},\r\n    Title = {Automatic Differentiation, Techniques and Applications},\r\n    Volume = {120},\r\n    Year = {1981}}\r\n\r\n@article{Rambaut1997,\r\n    Author = {A Rambaut and NC Grassly},\r\n    Journal = {Comput. Appl. Biosci.},\r\n    Pages = {235--238},\r\n    Title = {{Seq-Gen}: An application for the {M}onte {C}arlo simulation of {DNA} sequence evolution along phylogenetic trees},\r\n    Volume = {13},\r\n    Year = {1997}}\r\n\r\n@Article{Ranwez2002,\r\n  author = {V Ranwez and O Gascuel},\r\n  title = {Improvement of distance-based phylogenetic methods by a\r\n                  local maximum likelihood approach using triplets},\r\n  journal = {Molecular Biology and Evolution},\r\n  year = {2002},\r\n  OPTkey = {},\r\n  volume = {19},\r\n  number = {11},\r\n  pages = {1952--1963},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@article{Raphael2004,\r\n    Author = {B Raphael and P Pevzner},\r\n    Journal = {Bioinformatics},\r\n    Pages = {I265--I273},\r\n    Title = {Reconstructing Tumor Amplisomes},\r\n    Volume = {20 Suppl 1, Special ISMB/ECCB 2004 issue},\r\n    Year = {2004}}\r\n\r\n@phdthesis{Ratz1992,\r\n    Address = {Karlsruhe, Germany},\r\n    Author = {D Ratz},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    School = {Universit\\\"{a}t Karlsruhe},\r\n    Title = {Automatische {Ergebnisverifikation} bei globalen {Optimierungsproblemen}},\r\n    Type = {{Ph.D.} Dissertation},\r\n    Year = {1992}}\r\n\r\n@article{Richards2005,\r\n    Abstract = {We have sequenced the genome of a second Drosophila species, Drosophila pseudoobscura, and compared this to the genome sequence of Drosophila melanogaster, a primary model organism. Throughout evolution the vast majority of Drosophila genes have remained on the same chromosome arm, but within each arm gene order has been extensively reshuffled, leading to a minimum of 921 syntenic blocks shared between the species. A repetitive sequence is found in the D. pseudoobscura genome at many junctions between adjacent syntenic blocks. Analysis of this novel repetitive element family suggests that recombination between offset elements may have given rise to many paracentric inversions, thereby contributing to the shuffling of gene order in the D. pseudoobscura lineage. Based on sequence similarity and synteny, 10,516 putative orthologs have been identified as a core gene set conserved over 25-55 million years (Myr) since the pseudoobscura/melanogaster divergence. Genes expressed in the testes had higher amino acid sequence divergence than the genome-wide average, consistent with the rapid evolution of sex-specific proteins. Cis-regulatory sequences are more conserved than random and nearby sequences between the species--but the difference is slight, suggesting that the evolution of cis-regulatory elements is flexible. Overall, a pattern of repeat-mediated chromosomal rearrangement, and high coadaptation of both male genes and cis-regulatory sequences emerges as important themes of genome divergence between these species of Drosophila.},\r\n    Affiliation = {Human Genome Sequencing Center and Department of Molecular and Human Genetics, Baylor College of Medicine, Houston Texas 77030, USA. stephenr@bcm.tmc.edu},\r\n    Aid = {10.1101/gr.3059305 {$[$}doi{$]$}},\r\n    Au = {Richards S and Liu Y and Bettencourt BR and Hradecky P and Letovsky S and Nielsen R and Thornton K and Hubisz MJ and Chen R and Meisel RP and others},\r\n    Author = {S Richards and Y Liu and BR Bettencourt and P Hradecky and S Letovsky and R Nielsen and K Thornton and MJ Hubisz and R Chen and RP Meisel and others},\r\n    Da = {20050105},\r\n    Date-Added = {2005-10-16 22:47:25 -0700},\r\n    Date-Modified = {2005-10-16 22:47:25 -0700},\r\n    Dcom = {20050414},\r\n    Edat = {2005/01/06 09:00},\r\n    Gr = {LM007276/LM/NLM},\r\n    Ip = {1},\r\n    Jid = {9518021},\r\n    Journal = {Genome Res},\r\n    Keywords = {Animals, Chromosome Breakage/genetics, Chromosome Mapping/methods, Chromosomes/*genetics, Comparative Study, Conserved Sequence/genetics, Drosophila/*genetics, Drosophila melanogaster/genetics, Enhancer Elements (Genetics), *Evolution, Molecular, Gene Rearrangement/genetics, Genes, Structural, Insect/*genetics, *Genome, Inversion, Chromosome/genetics, Molecular Sequence Data, Predictive Value of Tests, Repetitive Sequences, Nucleic Acid/genetics, Research Support, Non-U.S. Gov't, Research Support, U.S. Gov't, P.H.S., Sequence Analysis, DNA/*methods, Variation (Genetics)/genetics},\r\n    Language = {eng},\r\n    Mhda = {2005/04/15 09:00},\r\n    Own = {NLM},\r\n    Pages = {1-18},\r\n    Pl = {United States},\r\n    Pmid = {15632085},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Sb = {IM},\r\n    Si = {GENBANK/AY693425},\r\n    So = {Genome Res 2005 Jan;15(1):1-18.},\r\n    Stat = {MEDLINE},\r\n    Title = {Comparative genome sequencing of {Drosophila} pseudoobscura: chromosomal, gene, and cis-element evolution.},\r\n    Volume = {15},\r\n    Year = {2005}}\r\n\r\n@inproceedings{Richter-Gebert2003,\r\n    Author = {J Richter-Gebert and B Sturmfels and T Theobald},\r\n    Booktitle = {Proceedings of the Conference on Idempotent Mathematics and Mathematical Physics},\r\n    Editor = {GL Litvinov and VP Maslov},\r\n    Title = {First steps in tropical geometry},\r\n    Year = {2003}}\r\n\r\n@Article{Ritchie2008,\r\n  author = \t {W Ritchie and S Granjeaud and D Puthier and D Gautheret},\r\n  title = \t {Entropy measures quantify global splicing disorders in cancer},\r\n  journal = \t {PLoS Computational Biology},\r\n  year = \t {2008},\r\n  OPTkey = \t {},\r\n  volume = \t {4},\r\n  OPTnumber = \t {3},\r\n  pages = \t {e1000011},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{STjohn2003,\r\n    Author = {K St. John and T Warnow and B Moret and L Vawter},\r\n    Journal = {Journal of Algorithms},\r\n    Pages = {174--193},\r\n    Title = {Performance study of phylogenetic methods: (unweighted) quartet methods and neighbor joining},\r\n    Volume = {48},\r\n    Year = {2003}}\r\n\r\n@techreport{Sainudiin2004,\r\n    Author = {R Sainudiin},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Institution = {Department of Biol.~Stats.~and Comp.~Bio., Cornell University},\r\n    Number = {BU1653-M},\r\n    Title = {Enclosing the maximum likelihood of the simplest {DNA} model evolving on fixed topologies: towards a rigorous framework for phylogenetic inference},\r\n    Year = {2004}}\r\n\r\n@article{Sainudiin2005,\r\n    Author = {R Sainudiin and SW Wong and K Yogeeswaran and J Nasrallah and Z Yang and R Nielsen},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Molecular Evolution},\r\n    Title = {Detecting site-specific physicochemical selective pressures: applications to the class-{I} {HLA} of the human major histocompatibility complex and the {SRK} of the plant sporophytic self-incompatibility system},\r\n    Volume = {in press},\r\n    Year = {2005}}\r\n\r\n@article{Saitou1987,\r\n    Author = {N Saitou and M Nei},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Molecular Biology and Evolution},\r\n    OPTNumber = {4},\r\n    Pages = {406--425},\r\n    Title = {The neighbor joining method: a new method for reconstructing phylogenetic trees},\r\n    Volume = {4},\r\n    Year = {1987}}\r\n\r\n@inproceedings{Salakhutdinov2003,\r\n    Author = {R Salakhutdinov and S Roweis and Z Ghahramani},\r\n    Booktitle = {Proceedings of the Twentieth International Conference on Machine Learning (ICML-2003)},\r\n    Title = {Optimization with EM and Expectation-Conjugate-Gradient},\r\n    Year = {2003}}\r\n\r\n@article{Salakhutdinov2004,\r\n    Author = {R Salakhutdinov and S Roweis and Z Ghahramani},\r\n    Journal = {in preparation},\r\n    Title = {{Relationship between gradient and EM steps in latent variable models}},\r\n    Year = {2004}}\r\n\r\n@Misc{Sammeth,\r\n  key = \t {Flux Capacitor Simulator},\r\n  author = \t {M Sammeth and V Lacroix and  P Ribeca and R Guig\\'{o}},\r\n  title = \t {Flux Capacitor Simulator: {\\tt http://flux.sammeth.net/}},\r\n  OPThowpublished = {},\r\n  OPTmonth = \t {},\r\n  year = \t {2009},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Sandelin2004,\r\n    Author = {A Sandelin and P Bailey and S Bruce and PG Engstr\\\"{o}m and JM Klos and WW Wasserman and J Ericson and B Lenhard},\r\n    Journal = {BMC Genomics},\r\n    Pages = {99},\r\n    Title = {Arrays of Ultraconserved Non-Coding Regions Span the Loci of Key Developmental Genes in Vertebrate Genomes},\r\n    Volume = {5},\r\n    Year = {2004}}\r\n\r\n@article{Sankoff2003,\r\n    Author = {D Sankoff and JH Nadeau},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Proceedings of the National Academy of Sciences, USA},\r\n    Pages = {11188--11189},\r\n    Title = {Chromosome rearrangements in evolution: from gene order to genome sequence and back},\r\n    Volume = {100},\r\n    Year = {2003}}\r\n\r\n@Article{Sattath1977,\r\n  author =   {S Sattath and A Tversky},\r\n  title =    {Additive similarity trees},\r\n  journal =      {Psychometrika},\r\n  year =     {1977},\r\n  OPTkey =   {},\r\n  volume =   {42},\r\n  number =   {6},\r\n  pages =    {319--345},\r\n  OPTmonth =     {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n@book{Schenck2003,\r\n    Author = {H Schenck},\r\n    Publisher = {Cambridge University Press},\r\n    Series = {London Mathematical Society Student Texts},\r\n    Title = {Computational Algebraic Geometry},\r\n    Year = {2003}}\r\n\r\n@article{Schmitz2003,\r\n    Author = {J Schmitz and H Zischler},\r\n    Journal = {Molecular Phylogenetics and Evolution},\r\n    Pages = {341--349},\r\n    Title = {A novel family of tRNA-derived SINEs in the colugo and two new retrotransposable markers separating dermopterans from primates.},\r\n    Volume = {28},\r\n    Year = {2003}}\r\n\r\n@book{Schrijver1986,\r\n    Address = {Chichester},\r\n    Author = {A Schrijver},\r\n    Isbn = {0-471-90854-1},\r\n    Mrclass = {90C05 (90C10)},\r\n    Mrnumber = {MR874114 (88m:90090)},\r\n    Mrreviewer = {J{\\\"u}rgen K{\\\"o}hler},\r\n    Note = {A Wiley--Interscience Publication},\r\n    Pages = {xii+471},\r\n    Publisher = {John Wiley \\& Sons Ltd.},\r\n    Series = {Wiley-Interscience Series in Discrete Mathematics},\r\n    Title = {Theory of Linear and Integer Programming},\r\n    Year = {1986}}\r\n\r\n@article{Schwartz2000,\r\n    Author = {A Schwartz and Z Zhang and KA Frazer and A Smit and C Riemer and J Bouck and R Gibbs and R Hardison and W Miller},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Genome Research},\r\n    Pages = {577--586},\r\n    Title = {PipMaker- A web server for aligning two genomic DNA sequences},\r\n    Volume = {10},\r\n    Year = {2000}}\r\n\r\n@article{Schwartz2003,\r\n    Author = {S Schwartz and WJ Kent and A Smit and Z Zhang and R Baertsch and RC Hardison and D Haussler and W Miller},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Genome Research},\r\n    Pages = {103--107},\r\n    Title = {Human--Mouse Alignments with {BLASTZ}},\r\n    Volume = {13},\r\n    Year = {2003}}\r\n\r\n@article{Schwarz,\r\n    Author = {G Schwarz},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {The Annals of Statistics},\r\n    Pages = {461--464},\r\n    Title = {Estimating the dimension of a model},\r\n    Volume = {6}}\r\n\r\n@incollection{Seidel2004,\r\n    Author = {R Seidel},\r\n    Booktitle = {Handbook of Discrete and Computational Geometry},\r\n    Chapter = {22},\r\n    Edition = {Second},\r\n    Editor = {Goodman, Jacob E. and O'Rourke, Joseph},\r\n    Mrclass = {52-00 (00A20 05B25 65D18 68U05)},\r\n    Mrnumber = {MR2082993},\r\n    Publisher = {Chapman \\& Hall/CRC, Boca Raton, FL},\r\n    Series = {Discrete Mathematics and its Applications (Boca Raton)},\r\n    Title = {Convex hull computations},\r\n    Year = {2004}}\r\n\r\n@book{Semple2003,\r\n    Address = {Oxford},\r\n    Author = {C Semple and M Steel},\r\n    Isbn = {0-19-850942-1},\r\n    OPTMrclass = {92D15 (05C05 05C90 92D40)},\r\n    OPTMrnumber = {MR2060009},\r\n    Pages = {xiv+239},\r\n    Publisher = {Oxford University Press},\r\n    Series = {{\\rm Oxford Lecture Series in Mathematics and its Applications}},\r\n    Title = {Phylogenetics},\r\n    Volume = {24},\r\n    Year = {2003}}\r\n\r\n@Article{Semple2004,\r\n  author = \t {C Semple and M Steel},\r\n  title = \t {Cyclic permutations and evolutionary trees},\r\n  journal = \t {Advances in Applied Mathematics},\r\n  year = \t {2004},\r\n  OPTkey = \t {},\r\n  volume = \t {32},\r\n  OPTnumber = \t {},\r\n  pages = \t {669--680},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@misc{Shoup2004,\r\n    Author = {V Shoup},\r\n    Date-Modified = {2005-02-28 12:49:26 -0800},\r\n    Howpublished = {Available at http://shoup.net/ntl/},\r\n    Title = {{NTL, A Library for doing Number Theory}},\r\n    Year = {2004}}\r\n\r\n@article{Siepel2004,\r\n    Author = {A Siepel and D Haussler},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Computational Biology},\r\n    Pages = {413--428},\r\n    Title = {Combining phylogenetic and hidden Markov models in biosequence analysis},\r\n    Volume = {11},\r\n    Year = {2004}}\r\n\r\n@misc{Siepel2005,\r\n    Author = {A Siepel},\r\n    Title = {personal communication},\r\n    Year = {2005}}\r\n\r\n@article{Simon2000,\r\n    Author = {R Simon and R Desper and CH Papadimitriou and A Peng and DS Alberts and R Taetle and JM Trent and AA Sch{\\\"a}ffer},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Genes, Chromosomes \\& Cancer},\r\n    Pages = {106--120},\r\n    Title = {Chromosome Abnormalities in Ovarian Adenocarcinoma: {III}. {U}sing Breakpoint Data to Infer and Test Mathematical Models for Oncogenesis},\r\n    Volume = {28},\r\n    Year = {2000}}\r\n\r\n@article{Smith1981,\r\n    Author = {TF Smith and MS Waterman},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Molecular Biology},\r\n    Pages = {195--197},\r\n    Title = {Identification of common molecular sequences},\r\n    Volume = {147},\r\n    Year = {1981}}\r\n\r\n\r\n@book{Smith1998,\r\n    Author = {JM Smith},\r\n    Edition = {Second},\r\n    Month = {March},\r\n    Publisher = {Oxford University Press},\r\n    Title = {Evolutionary Genetics},\r\n    Year = {1998}}\r\n\r\n@book{Sneath1973,\r\n    Address = {San Francisco},\r\n    Author = {PHA Sneath and RR Sokal},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Publisher = {W.H. Freeman},\r\n    Title = {Numerical Taxonomy: the Principles and Practice of Numerical Classification},\r\n    Year = {1973}}\r\n\r\n@article{Speyer2004,\r\n    Author = {D Speyer and B Sturmfels},\r\n    Coden = {AGDEA3},\r\n    Date-Modified = {2005-02-05 12:58:09 -0800},\r\n    Fjournal = {Advances in Geometry},\r\n    Issn = {1615-715X},\r\n    Journal = {Adv. Geom.},\r\n    Mrclass = {14P99 (13J30 14M25)},\r\n    Mrnumber = {MR2071813},\r\n    Mrreviewer = {Meirav Amram-Blei},\r\n    Number = {3},\r\n    Pages = {389--411},\r\n    Title = {The tropical {G}rassmannian},\r\n    Volume = {4},\r\n    Year = {2004}}\r\n\r\n@article{Speyer2004a,\r\n    Author = {D Speyer},\r\n    Journal = {Submitted},\r\n    Title = {Tropical Linear Spaces},\r\n    Year = {2004}}\r\n\r\n@article{Speyer2004b,\r\n    Author = {D Speyer and L Williams},\r\n    Journal = {Journal of Algebraic Combinatorics, in press},\r\n    Title = {The tropical totally positive {Grassmanian}},\r\n    Year = {2004}}\r\n\r\n@book{Stanley1997,\r\n    Address = {Cambridge},\r\n    Author = {RP Stanley},\r\n    Isbn = {0-521-55309-1; 0-521-66351-2},\r\n    OPTMrclass = {05-02 (05A15 06-02 11-02)},\r\n    OPTMrnumber = {MR1442260 (98a:05001)},\r\n    Mrreviewer = {Wayne M. Dymacek},\r\n    OPTNote = {With a foreword by Gian-Carlo Rota, Corrected reprint of the 1986 original},\r\n    Pages = {xii+325},\r\n    Publisher = {Cambridge University Press},\r\n    Series = {{\\rm Cambridge Studies in Advanced Mathematics}},\r\n    Title = {Enumerative Combinatorics. {V}ol. 1},\r\n    Volume = {49},\r\n    Year = {1997}}\r\n\r\n@book{Stanley1999,\r\n    Address = {Cambridge},\r\n    Author = {RP Stanley},\r\n    Isbn = {0-521-56069-1; 0-521-78987-7},\r\n    OPTMrclass = {05A15 (05-02 05E05 05E10 68R05)},\r\n    OPTMrnumber = {MR1676282 (2000k:05026)},\r\n    OPTMrreviewer = {Ira Gessel},\r\n    OPTNote = {With a foreword by Gian-Carlo Rota and appendix 1 by Sergey Fomin},\r\n    Pages = {xii+581},\r\n    Publisher = {Cambridge University Press},\r\n    Series = {Cambridge Studies in Advanced Mathematics},\r\n    Title = {Enumerative combinatorics. {V}ol. 2},\r\n    Volume = {62},\r\n    Year = {1999}}\r\n\r\n@article{Steel1992,\r\n    Author = {MA Steel and MD Hendy and LA Sz{\\'e}kely and PL Erd{\\H{o}}s},\r\n    Coden = {AMLEEL},\r\n    Date-Modified = {2005-03-01 20:22:22 -0500},\r\n    Fjournal = {Applied Mathematics Letters. An International Journal of Rapid Publication},\r\n    Issn = {0893-9659},\r\n    Journal = {Applied Mathematics Letters},\r\n    Mrclass = {92D15},\r\n    Mrnumber = {MR1345926},\r\n    Number = {6},\r\n    Pages = {63--67},\r\n    Title = {Spectral analysis and a closest tree method for genetic sequences},\r\n    Volume = {5},\r\n    Year = {1992}}\r\n\r\n@book{Strachan2004,\r\n    Author = {T Strachan and AP Read},\r\n    Edition = {third},\r\n    Month = {June},\r\n    Publisher = {Garland Press},\r\n    Title = {{Human Molecular Genetics}},\r\n    Year = {2004}}\r\n\r\n@article{Strassen1983,\r\n    Author = {V Strassen},\r\n    Coden = {LAAPAW},\r\n    Fjournal = {Linear Algebra and its Applications},\r\n    Issn = {0024-3795},\r\n    Journal = {Linear Algebra Appl.},\r\n    Mrclass = {15A72 (14N99)},\r\n    Mrnumber = {MR709378 (85b:15039)},\r\n    Mrreviewer = {Allen Tannenbaum},\r\n    Pages = {645--685},\r\n    Title = {Rank and optimal computation of generic tensors},\r\n    Volume = {52/53},\r\n    Year = {1983}}\r\n\r\n@article{Strimmer1996,\r\n    Author = {K Strimmer and A von Haeseler},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {964--969},\r\n    Title = {Quartet puzzling: A quartet maximum likelihood method for reconstructing tree topologies},\r\n    Volume = {13},\r\n    Year = {1996}}\r\n\r\n@article{Strimmer2000,\r\n    Author = {K Strimmer and V Moulton},\r\n    Date-Added = {2005-03-01 20:10:40 -0500},\r\n    Date-Modified = {2005-03-01 20:11:43 -0500},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {875-881},\r\n    Title = {Likelihood Analysis of Phylogenetic Networks using directed graphical models},\r\n    Volume = {17},\r\n    Year = {2000}}\r\n\r\n@article{Strimmer2001,\r\n    Author = {K Strimmer and C Wiuf and V Moulton},\r\n    Date-Modified = {2005-03-01 20:09:47 -0500},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {97--99},\r\n    Title = {Recombination analysis using directed graphical models},\r\n    Volume = {18},\r\n    Year = {2001}}\r\n\r\n@article{Studier1988,\r\n    Author = {JA Studier and KJ Keppler},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {729--731},\r\n    Title = {A note on the neighbor-joining method of Saitou and Nei},\r\n    Volume = {5},\r\n    Year = {1988}}\r\n\r\n@article{Sturmfels1990,\r\n    Author = {B Sturmfels},\r\n    Coden = {MAZEAX},\r\n    Fjournal = {Mathematische Zeitschrift},\r\n    Issn = {0025-5874},\r\n    Journal = {Mathematische Zeitschrift},\r\n    Mrclass = {14M12 (13P10 68Q40)},\r\n    Mrnumber = {MR1069489 (91m:14076)},\r\n    Mrreviewer = {Piotr Pragacz},\r\n    Number = {1},\r\n    Pages = {137--144},\r\n    Title = {Gr\\\"obner bases and {S}tanley decompositions of determinantal rings},\r\n    Volume = {205},\r\n    Year = {1990}}\r\n\r\n@book{Sturmfels1993,\r\n    Address = {Vienna},\r\n    Author = {B Sturmfels},\r\n    Isbn = {3-211-82445-6},\r\n    Mrclass = {13A50 (13P10 20-01 20-04 20G05)},\r\n    Mrnumber = {MR1255980 (94m:13004)},\r\n    Mrreviewer = {Frank D. Grosshans},\r\n    Pages = {vi+197},\r\n    Publisher = {Springer-Verlag},\r\n    Series = {Texts and Monographs in Symbolic Computation},\r\n    Title = {Algorithms in Invariant Theory},\r\n    Year = {1993}}\r\n\r\n@book{Sturmfels2002,\r\n    Author = {B Sturmfels},\r\n    Date-Modified = {2005-02-05 12:58:09 -0800},\r\n    Isbn = {0-8218-3251-4},\r\n    Mrclass = {13P10 (14P99 14Q15 62-09 65H10)},\r\n    Mrnumber = {MR1925796 (2003i:13037)},\r\n    Mrreviewer = {Joseph Gubeladze},\r\n    Pages = {viii+152},\r\n    Publisher = {Published for the Conference Board of the Mathematical Sciences, Washington, DC},\r\n    Series = {CBMS Regional Conference Series in Mathematics},\r\n    Title = {Solving Systems of Polynomial Equations},\r\n    Volume = {97},\r\n    Year = {2002}}\r\n\r\n@incollection{Sturmfels2002a,\r\n    Address = {Berlin},\r\n    Author = {B Sturmfels},\r\n    Booktitle = {Computations in algebraic geometry with Macaulay 2},\r\n    Date-Modified = {2005-02-05 12:58:09 -0800},\r\n    Mrclass = {13-04 (14-04)},\r\n    Mrnumber = {MR1949545},\r\n    Pages = {3--15},\r\n    Publisher = {Springer},\r\n    Series = {Algorithms and Computations in Mathematics},\r\n    Title = {Ideals, varieties and {M}acaulay 2},\r\n    Volume = {8},\r\n    Year = {2002}}\r\n\r\n@article{Sturmfels2004,\r\n    Author = {B Sturmfels and J Yu},\r\n    Date-Modified = {2005-02-05 12:58:09 -0800},\r\n    Fjournal = {Electronic Journal of Combinatorics},\r\n    Issn = {1077-8926},\r\n    Journal = {Electronic Journal of Combinatorics},\r\n    Mrclass = {51K05 (05C12)},\r\n    Mrnumber = {MR2097310},\r\n    Pages = {Research Paper 44, 16 pp. (electronic)},\r\n    Title = {Classification of six-point metrics},\r\n    Volume = {11},\r\n    Year = {2004}}\r\n\r\n@article{Sturmfels2005,\r\n    Author = {B Sturmfels and S Sullivant},\r\n    Journal = {Journal of Computational Biology},\r\n    Pages = {204--228},\r\n    Title = {Toric ideals of phylogenetic invariants},\r\n    Volume = {12},\r\n    Year = {2005}}\r\n\r\n@unpublished{Sturmfels2007,\r\n  author = \t {B Sturmfels and S Sullivant},\r\n  title = \t {Toric geometry of cuts and splits},\r\n  note  = \t {arXiv math.AC/0606683},\r\n  year = \t {2007},\r\n  OPTkey = \t {},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTpages = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Sun2002,\r\n    Author = {F Sun and D Fern\\'andez-Baca and W Yu},\r\n    Date-Modified = {2005-02-23 12:49:26 -0800},\r\n    Journal = {International Computing and Combinatorics Conference (COCOON)},\r\n    Title = {Inverse parametric sequence alignment},\r\n    Year = {2002}}\r\n\r\n@article{Susko2003,\r\n    Author = {E Susko},\r\n    Date-Added = {2005-03-01 20:06:38 -0500},\r\n    Date-Modified = {2005-03-01 20:07:08 -0500},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Title = {Confidence Regions and Hypothesis Tests for Topologies Using Generalized Least Squares},\r\n    Year = {2003}}\r\n\r\n@manual{Swofford1998,\r\n    Address = {Sunderland Mass.},\r\n    Author = {DL Swofford},\r\n    Publisher = {Sinauer Associates},\r\n    Title = {PAUP*. Phylogenetic Analysis using Parsimony (* and other Methods)},\r\n    Year = {1998}}\r\n\r\n@misc{Swox2004,\r\n    Author = {AB Swox},\r\n    Date-Modified = {2005-02-28 12:49:26 -0800},\r\n    Howpublished = {Available at \\url{http://swox.com/gmp/}},\r\n    Title = {{GMP, the GNU Multiple Precision Arithmetic Library}},\r\n    Year = {2004}}\r\n\r\n@article{Szabo2002,\r\n    Author = {A Szabo and K Boucher},\r\n    Journal = {Mathematical Biosciences},\r\n    Pages = {219--240},\r\n    Title = {Estimating an oncogenetic tree when false negatives and positives are present},\r\n    Volume = {176},\r\n    Year = {2002}}\r\n\r\n\r\n@article{Szekely1993,\r\n    Author = {LA Sz{\\'e}kely and MA Steel and PL Erd{\\H{o}}s},\r\n    Date-Modified = {2005-03-01 19:31:08 -0500},\r\n    Fjournal = {Advances in Applied Mathematics},\r\n    Issn = {0196-8858},\r\n    Journal = {Advances in Applied Mathematics},\r\n    Mrclass = {92D15 (42A38)},\r\n    Mrnumber = {MR1218244 (94i:92009)},\r\n    Mrreviewer = {J. Albrycht},\r\n    Number = {2},\r\n    Pages = {200--210},\r\n    Title = {Fourier calculus on evolutionary trees},\r\n    Volume = {14},\r\n    Year = {1993}}\r\n\r\n@article{Tamura1993,\r\n    Author = {K Tamura and M Nei},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {512--526},\r\n    Title = {Estimation of the number of nucleotide substitutions in the control region of mitochondrial {DNA} in humans and chimpanzees},\r\n    Volume = {10},\r\n    Year = {1993}}\r\n\r\n@Article{Tamura2004,\r\n  author = {K Tamura and M Nei and S Kumar},\r\n  title = {Prospects for inferring very large phylogenies by using the\r\n                  neighbor-joining method},\r\n  journal = {Proceedings of the National Academy of Sciences},\r\n  year = {2004},\r\n  OPTkey = {},\r\n  volume = {101},\r\n  OPTnumber = {},\r\n  pages = {11030--11035},\r\n  OPTmonth = {},\r\n  OPTnote = {},\r\n  OPTannote = {}\r\n}\r\n\r\n@article{Tavare1986,\r\n    Author = {S Tavar\\'{e}},\r\n    Journal = {Lectures on the Mathematics in the Life Sciences},\r\n    Pages = {57--86},\r\n    Title = {Some probabilistic and statistical problems in the analysis of {DNA} sequences},\r\n    Volume = {17},\r\n    Year = {1986}}\r\n\r\n@article{Terao2002,\r\n    Author = {H Terao},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of Algebra},\r\n    Number = {2},\r\n    Pages = {549--558},\r\n    Title = {Algebras generated by reciprocals of linear forms},\r\n    Volume = {250},\r\n    Year = {2002}}\r\n\r\n@article{Tesler2002,\r\n    Author = {G Tesler},\r\n    Journal = {Journal of Computer and System Sciences},\r\n    Number = {3},\r\n    Pages = {587--609},\r\n    Title = {Efficient algorithms for multichromosomal genome rearrangements},\r\n    Volume = {65},\r\n    Year = {2002}}\r\n\r\n@article{Thomas2003,\r\n    Abstract = {The systematic comparison of genomic sequences from different organisms represents a central focus of contemporary genome analysis. Comparative analyses of vertebrate sequences can identify coding and conserved non-coding regions, including regulatory elements, and provide insight into the forces that have rendered modern-day genomes. As a complement to whole-genome sequencing efforts, we are sequencing and comparing targeted genomic regions in multiple, evolutionarily diverse vertebrates. Here we report the generation and analysis of over 12 megabases (Mb) of sequence from 12 species, all derived from the genomic region orthologous to a segment of about 1.8 Mb on human chromosome 7 containing ten genes, including the gene mutated in cystic fibrosis. These sequences show conservation reflecting both functional constraints and the neutral mutational events that shaped this genomic region. In particular, we identify substantial numbers of conserved non-coding segments beyond those previously identified experimentally, most of which are not detectable by pair-wise sequence comparisons alone. Analysis of transposable element insertions highlights the variation in genome dynamics among these species and confirms the placement of rodents as a sister group to the primates.},\r\n    Affiliation = {Genome Technology Branch, National Human Genome Research Institute, National Institutes of Health, Bethesda, Maryland 20892,USA.},\r\n    Aid = {nature01858 {$[$}pii{$]$}},\r\n    Au = {Green ED},\r\n    Author = {JW Thomas and JW Touchman and RW Blakesley and GG Bouffard and SM Beckstrom-Sternberg and EH Margulies and M Blanchette and AC Siepel and PJ Thomas and JC McDowell and others},\r\n    Da = {20030814},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20030821},\r\n    Edat = {2003/08/15 05:00},\r\n    Jid = {0410462},\r\n    Journal = {Nature},\r\n    Keywords = {Animals and Chromosomes, Human, Pair 7/genetics and Comparative Study and Conserved Sequence/*genetics and Cystic Fibrosis Transmembrane Conductance Regulator/genetics and DNA Transposable Elements/genetics and *Evolution, Molecular and Genome and *Genomics and Humans and Mammals/genetics and Mutagenesis/genetics and Phylogeny and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, P.H.S. and Sequence Alignment and Sequence Homology, Nucleic Acid and Species Specificity and Vertebrates/*genetics},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2003/08/22 05:00},\r\n    Number = {6950},\r\n    Own = {NLM},\r\n    Pages = {788--93},\r\n    Phst = {2003/06/16 {$[$}accepted{$]$}},\r\n    Pl = {England},\r\n    Pmid = {12917688},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {126880-72-6 (Cystic Fibrosis Transmembrane Conductance Regulator)},\r\n    Sb = {IM},\r\n    So = {Journal of Computational Biology 1999 Fall-Winter;6(3-4):419-30.},\r\n    Stat = {MEDLINE},\r\n    Title = {Comparative analyses of multi-species sequences from targeted genomic regions.},\r\n    Volume = {424},\r\n    Year = {2003}}\r\n\r\n@article{Thompson1994,\r\n    Author = {JD Thompson and DG Higgins and TJ Gibseon},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Nucleic Acids Research},\r\n    Pages = {4673--4680},\r\n    Title = {CLUSTALW: improving the sensitivity of progressive multiple sequence alignment through sequence weighting, position-specific gap penalties and weight matrix choice},\r\n    Volume = {22},\r\n    Year = {1994}}\r\n\r\n@article{Tompa2005,\r\n    Annote = {10.1038/nbt1053},\r\n    Author = {M Tompa and N Li and TL Bailey and GM Church and B De Moor and E Eskin and AV Favorov and MC Frith and Y Fu and WJ Kent and others},\r\n    Ep = {144},\r\n    Journal = {Nature Biotechnology},\r\n    L3 = {http://www.nature.com/nbt/journal/v23/n1/suppinfo/nbt1053{\\_}S1.html},\r\n    M3 = {10.1038/nbt1053},\r\n    Number = {1},\r\n    Pages = {137--144},\r\n    Sn = {1087-0156},\r\n    Sp = {137},\r\n    Title = {Assessing computational tools for the discovery of transcription factor binding sites},\r\n    Ty = {JOUR},\r\n    Url = {http://dx.doi.org/10.1038/nbt1053},\r\n    Volume = {23},\r\n    Year = {2005}}\r\n\r\n@Article{Trapnell2009,\r\n  author = \t {C Trapnell and L Pachter and S Salzberg},\r\n  title = \t {{TopHat: discovering splice junctions with RNA-Seq}},\r\n  journal = \t {Bioinformatics},\r\n  year = \t {2009},\r\n  OPTkey = \t {},\r\n  volume = \t {25},\r\n  OPTnumber = \t {9},\r\n  pages = \t {1105--1111},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Book{Tufte2001,\r\n  author = \t {Edward R. Tufte},\r\n  ALTeditor = \t {},\r\n  title = \t {The Visual Display of Quantitative Information},\r\n  publisher = \t {Graphics Press},\r\n  year = \t {2001},\r\n  OPTkey = \t {},\r\n  OPTvolume = \t {},\r\n  OPTnumber = \t {},\r\n  OPTseries = \t {},\r\n  OPTaddress = \t {},\r\n  OPTedition = \t {},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Ureta-Vidal2003,\r\n    Author = {A Ureta-Vidal and L Ettwiller and E Birney},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Nature Review Genetics},\r\n    Pages = {251--262},\r\n    Title = {Comparative Genomics: Genome-wide analysis in metazoan eukaryotes},\r\n    Volume = {4},\r\n    Year = {2003}}\r\n\r\n@article{Valiant1979,\r\n    Author = {L Valiant},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Journal = {Theoretical Computer Science},\r\n    Pages = {189--201},\r\n    Title = {The complexity of computing the permanent},\r\n    Volume = {8},\r\n    Year = {1979}}\r\n\r\n@book{Vapnik1995,\r\n    Address = {New York, New York},\r\n    Author = {VN Vapnik},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Publisher = {Springer-Verlag},\r\n    Title = {The Nature of Statistical Learning Theory},\r\n    Year = {1995}}\r\n\r\n@article{Varchenko1995,\r\n    Author = {A Varchenko},\r\n    Coden = {CMPMAF},\r\n    Fjournal = {Compositio Mathematica},\r\n    Issn = {0010-437X},\r\n    Journal = {Compositio Mathematica},\r\n    Mrclass = {32S50 (17B10 32G34 32S40)},\r\n    Mrnumber = {MR1353281 (96j:32053)},\r\n    Mrreviewer = {V. Leksin},\r\n    Number = {3},\r\n    Pages = {385--401},\r\n    Title = {Critical points of the product of powers of linear functions and families of bases of singular vectors},\r\n    Volume = {97},\r\n    Year = {1995}}\r\n\r\n@article{Venter2001,\r\n    Abstract = {A 2.91-billion base pair (bp) consensus sequence of the euchromatic portion of the human genome was generated by the whole-genome shotgun sequencing method. The 14.8-billion bp DNA sequence was generated over 9 months from 27,271,853 high-quality sequence reads (5.11-fold coverage of the genome) from both ends of plasmid clones made from the DNA of five individuals. Two assembly strategies-a whole-genome assembly and a regional chromosome assembly-were used, each combining sequence data from Celera and the publicly funded genome effort. The public data were shredded into 550-bp segments to create a 2.9-fold coverage of those genome regions that had been sequenced, without including biases inherent in the cloning and assembly procedure used by the publicly funded group. This brought the effective coverage in the assemblies to eightfold, reducing the number and size of gaps in the final assembly over what would be obtained with 5.11-fold coverage. The two assembly strategies yielded very similar results that largely agree with independent mapping data. The assemblies effectively cover the euchromatic regions of the human chromosomes. More than 90% of the genome is in scaffold assemblies of 100,000 bp or more, and 25% of the genome is in scaffolds of 10 million bp or larger. Analysis of the genome sequence revealed 26,588 protein-encoding transcripts for which there was strong corroborating evidence and an additional approximately 12,000 computationally derived genes with mouse matches or other weak supporting evidence. Although gene-dense clusters are obvious, almost half the genes are dispersed in low G+C sequence separated by large tracts of apparently noncoding sequence. Only 1.1% of the genome is spanned by exons, whereas 24% is in introns, with 75% of the genome being intergenic DNA. Duplications of segmental blocks, ranging in size up to chromosomal lengths, are abundant throughout the genome and reveal a complex evolutionary history. Comparative genomic analysis indicates vertebrate expansions of genes associated with neuronal function, with tissue-specific developmental regulation, and with the hemostasis and immune systems. DNA sequence comparisons between the consensus sequence and publicly funded genome data provided locations of 2.1 million single-nucleotide polymorphisms (SNPs). A random pair of human haploid genomes differed at a rate of 1 bp per 1250 on average, but there was marked heterogeneity in the level of polymorphism across the genome. Less than 1% of all SNPs resulted in variation in proteins, but the task of determining which SNPs have functional consequences remains an open challenge.},\r\n    Affiliation = {Celera Genomics, 45 West Gude Drive, Rockville, MD 20850, USA. humangenome@celera.com},\r\n    Aid = {291/5507/1304 {$[$}pii{$]$}},\r\n    Au = {Zhu X},\r\n    Author = {JC Venter and MD Adams and EW Myers and PW Li and RJ Mural and GG Sutton and HO Smith and M Yandell and CA Evans and RA Holt and others},\r\n    Cin = {Proc Natl Acad Sci U S A. 2003 Mar 18;100(6):3022-4; author reply 3025-6. PMID: 12631699},\r\n    Da = {20010222},\r\n    Date-Modified = {2005-02-05 12:49:27 -0800},\r\n    Dcom = {20010315},\r\n    Edat = {2001/02/22 11:00},\r\n    Ein = {Science 2001 Jun 5;292(5523):1838},\r\n    Jid = {0404511},\r\n    Journal = {Science},\r\n    Keywords = {Algorithms and Animals and Chromosome Banding and Chromosome Mapping and Chromosomes, Artificial, Bacterial and Computational Biology and Consensus Sequence and CpG Islands and DNA, Intergenic and Databases, Factual and Evolution, Molecular and Exons and Female and Gene Duplication and Genes and *Genome, Human and *Human Genome Project and Humans and Introns and Male and Phenotype and Physical Chromosome Mapping and Polymorphism, Single Nucleotide and Proteins/genetics/physiology and Pseudogenes and Repetitive Sequences, Nucleic Acid and Research Support, Non-U.S. Gov't and Retroelements and *Sequence Analysis, DNA/methods and Species Specificity and Variation (Genetics)},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2001/03/17 10:01},\r\n    Number = {5507},\r\n    Own = {NLM},\r\n    Pages = {1304--51},\r\n    Pl = {United States},\r\n    Pmid = {11181995},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (Retroelements)},\r\n    Sb = {IM},\r\n    Stat = {MEDLINE},\r\n    Title = {The sequence of the human genome.},\r\n    Volume = {291},\r\n    Year = {2001}}\r\n\r\n@article{Viterbi1967,\r\n    Author = {AJ Viterbi},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {IEEE Transactions on Information Theory},\r\n    Pages = {260-269},\r\n    Title = {Error Bounds for Convolutional Codes and an Asymptotically Optimum Decoding Algorithm},\r\n    Volume = {13},\r\n    Year = {1967}}\r\n\r\n@article{Vogelstein1988,\r\n    Author = {B Vogelstein and E Fearon and S Hamilton},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {New England Journal of Medicine},\r\n    Pages = {525--532},\r\n    Title = {Genetic alterations during colorectal-tumor development},\r\n    Volume = {319},\r\n    Year = {1988}}\r\n\r\n@article{Vonheydebreck2004,\r\n    Author = {A von Heydebreck and B Gunawan and L F{\\\"u}zesi},\r\n    Journal = {Biostatistics},\r\n    Number = {4},\r\n    Pages = {545--556},\r\n    Title = {Maximum likelihood estimation of oncogenetic tree models},\r\n    Url = {http://biostatistics.oupjournals.org/cgi/content/abstract/5/4/545?etoc},\r\n    Volume = {5},\r\n    Year = {2004}}\r\n\r\n@Article{Wang2008,\r\n  author = \t {ET Wang and R Sandberg S Luo and I Khrebtukova and L Zhang and C Mayr and SF Kingsmore and GP Schroth and CB Burge},\r\n  title = \t {Alternative isoform regulation in human tissue transcriptomes},\r\n  journal = \t {Nature},\r\n  year = \t {2008},\r\n  OPTkey = \t {},\r\n  volume = \t {456},\r\n  OPTnumber = \t {},\r\n  pages = \t {470--476},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@article{Warshall1962,\r\n    Author = {S Warshall},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Journal of the ACM},\r\n    Number = {1},\r\n    Pages = {18},\r\n    Title = {A theorem on Boolean matrices},\r\n    Volume = {9},\r\n    Year = {1962}}\r\n\r\n@article{Waterman1992,\r\n    Author = {MS Waterman and M Eggert and ES Lander},\r\n    Journal = {Proceedings of the National Academy of Sciences, USA},\r\n    Pages = {6090--6093},\r\n    Title = {Parametric sequence comparisons},\r\n    Volume = {89},\r\n    Year = {1992}}\r\n\r\n@book{Waterman1995,\r\n    Author = {MS Waterman},\r\n    Month = {June},\r\n    Publisher = {Chapman \\& Hall/CRC},\r\n    Title = {Introduction to Computational Biology: Maps, Sequences and Genomes},\r\n    Year = {1995}}\r\n\r\n@article{Waterston2002,\r\n    Abstract = {The sequence of the mouse genome is a key informational tool for understanding the contents of the human genome and a key experimental tool for biomedical research. Here, we report the results of an international collaboration to produce a high-quality draft sequence of the mouse genome. We also present an initial comparative analysis of the mouse and human genomes, describing some of the insights that can be gleaned from the two sequences. We discuss topics including the analysis of the evolutionary forces shaping the size, structure and sequence of the genomes; the conservation of large-scale synteny across most of the genomes; the much lower extent of sequence orthology covering less than half of the genomes; the proportions of the genomes under selection; the number of protein-coding genes; the expansion of gene families related to reproduction and immunity; the evolution of proteins; and the identification of intraspecies polymorphism.},\r\n    Affiliation = {Genome Sequencing Center, Washington University School of Medicine, Campus Box 8501, 4444 Forest Park Avenue, St Louis, Missouri 63108, USA. waterston@gs.washington.edu},\r\n    Aid = {nature01262 {$[$}pii{$]$}},\r\n    Au = {Lander ES},\r\n    Author = {RH Waterston and K Lindblad-Toh and E Birney and J Rogers and JF Abril and P Agarwal and R Agarwala and R Ainscough and M Alexandersson and P An and others},\r\n    Cin = {Nature. 2002 Dec 5;420(6915):515-6. PMID: 12466847},\r\n    Cn = {Mouse Genome Sequencing Consortium.},\r\n    Da = {20021205},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20021227},\r\n    Edat = {2002/12/06 04:00},\r\n    Jid = {0410462},\r\n    Journal = {Nature},\r\n    Keywords = {Animals and Base Composition and Chromosomes, Mammalian/*genetics and Comparative Study and Conserved Sequence/genetics and CpG Islands/genetics and *Evolution, Molecular and Gene Expression Regulation and Genes/genetics and *Genome and Genome, Human and Genomics and Humans and Mice/classification/*genetics and Mice, Knockout and Mice, Transgenic and Models, Animal and Multigene Family/genetics and Mutagenesis and Neoplasms/genetics and *Physical Chromosome Mapping and Proteome/genetics and Pseudogenes/genetics and Quantitative Trait Loci/genetics and RNA, Untranslated/genetics and Repetitive Sequences, Nucleic Acid/genetics and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, Non-P.H.S. and Research Support, U.S. Gov't, P.H.S. and Selection (Genetics) and Sequence Analysis, DNA and Sex Chromosomes/genetics and Species Specificity and Synteny and Variation (Genetics)/genetics},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2002/12/28 04:00},\r\n    Own = {NLM},\r\n    Pages = {520-62},\r\n    Phst = {2002/10/31 {$[$}accepted{$]$}},\r\n    Pl = {England},\r\n    Pmid = {12466850},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (RNA, Untranslated)},\r\n    Sb = {IM},\r\n    So = {Genome Res 2003 Jan;13(1):73-80.},\r\n    Stat = {MEDLINE},\r\n    Title = {Initial sequencing and comparative analysis of the mouse genome.},\r\n    Volume = {420},\r\n    Year = {2002}}\r\n\r\n@article{Watson1953,\r\n    Author = {J Watson and F Crick},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Journal = {Nature},\r\n    Pages = {964--967},\r\n    Title = {A structure for deoxyribose nucleic acid},\r\n    Volume = {171},\r\n    Year = {1953}}\r\n\r\n@mastersthesis{Wetzel1995,\r\n    Author = {R Wetzel},\r\n    Date-Modified = {2005-03-01 19:55:48 -0500},\r\n    School = {Fakult\\\"{a}t Mathematik, Universit\\\"{a}t Bielefeld},\r\n    Title = {Zur {V}isualisierung abstrakter \\\"{A}hnlichkeitsbeziehungen},\r\n    Year = {1995}}\r\n\r\n@article{Winkler1984,\r\n    Author = {P Winkler},\r\n    Date-Added = {2005-03-01 20:01:12 -0500},\r\n    Date-Modified = {2005-03-01 20:02:00 -0500},\r\n    Journal = {Discrete Applied Mathematics},\r\n    Pages = {221--225},\r\n    Title = {Isometric embeddings in products of complete graphs},\r\n    Volume = {7},\r\n    Year = {1984}}\r\n\r\n@article{Wolf2000,\r\n    Author = {MJ Wolf and S Easteal and M Kahn and BD McKay and LS Jermiin},\r\n    Journal = {Bioinformatics},\r\n    Pages = {383--394},\r\n    Title = {TrExML: A maximum likelihood program for extensive tree-space exploration},\r\n    Volume = {16},\r\n    Year = {2000}}\r\n\r\n@article{Woolfe2005,\r\n    Author = {A Woolfe and M Goodson and DK Goode and P Snell and GK McEwen and T Vavouri and SF Smith and P North and H Callaway and K Kelly and others},\r\n    Journal = {PLoS Biology},\r\n    Pages = {7},\r\n    Title = {Highly Conserved Non-Coding Sequences Are Associated with Vertebrate Development},\r\n    Volume = {3},\r\n    Year = {2005}}\r\n\r\n@article{Wu1983,\r\n    Author = {JCF Wu},\r\n    Coden = {ASTSC7},\r\n    Fjournal = {The Annals of Statistics},\r\n    Issn = {0090-5364},\r\n    Journal = {The Annals of Statistics},\r\n    Mrclass = {62F10},\r\n    Mrnumber = {MR684867 (85e:62049)},\r\n    Mrreviewer = {Huynh Huynh},\r\n    Number = {1},\r\n    Pages = {95--103},\r\n    Title = {On the convergence properties of the {EM} algorithm},\r\n    Volume = {11},\r\n    Year = {1983}}\r\n\r\n@article{Wu1985,\r\n    Abstract = {When the coding regions of 11 genes from rodents (mouse or rat) and man are compared with those from another mammalian species (usually bovine), it is found that rodents evolve significantly faster than man. The ratio of the number of nucleotide substitutions in the rodent lineage to that in the human lineage since their divergence is 2.0 for synonymous substitutions and 1.3 for nonsynonymous substitutions. Rodents also evolve faster in the 5' and 3' untranslated regions of five different mRNAs; the ratios are 2.6 and 3.1, respectively. The numbers of nucleotide substitutions between members of the {beta} -globin gene family that were duplicated before the man-mouse split are also higher in mouse than in man. The difference is, again, greater for synonymous substitutions than for nonsynonymous substitutions. This tendency is more consistent with the neutralist view of molecular evolution than with the selectionist view. A simple explanation for the higher rates in rodents is that rodents have shorter generation times and, thus, higher mutation rates. The implication of our findings for the study of molecular phylogeny is discussed.\r\n},\r\n    Author = {CI Wu and WH Li},\r\n    Journal = {PNAS},\r\n    Number = {6},\r\n    Pages = {1741-1745},\r\n    Title = {Evidence for Higher Rates of Nucleotide Substitution in Rodents Than in Man},\r\n    Url = {http://www.pnas.org/cgi/content/abstract/82/6/1741},\r\n    Volume = {82},\r\n    Year = {1985}}\r\n\r\n@Article{Xing2004,\r\n  author = \t {Y Xing and A Resch and C Lee},\r\n  title = \t {The multiassembly problem: reconstructing multiple transcript isoforms from {EST} fragment mixtures},\r\n  journal = \t {Genome Research},\r\n  year = \t {2004},\r\n  OPTkey = \t {},\r\n  volume = \t {14},\r\n  OPTTnumber = \t {},\r\n  pages = \t {426--441},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@Article{Xu2005,\r\n  author =   {Y Xu and W Dai and B Zhu},\r\n  title =    {A lower bound on the edge $l_{\\infty}$ radius of {S}aitou and {N}ei's method for phylogenetic reconstruction},\r\n  journal =      {Information Processing Letters},\r\n  year =     {2005},\r\n  OPTkey =   {},\r\n  volume =   {94},\r\n  OPTnumber =    {},\r\n  pages =    {225--230},\r\n  OPTmonth =     {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n\r\n@article{Yang1995,\r\n    Author = {Z Yang and D Roberts},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {451--458},\r\n    Title = {On the use of nucleic acid sequences to infer early branchings in the tree of life},\r\n    Volume = {12},\r\n    Year = {1995}}\r\n\r\n@article{Yang1997,\r\n    Author = {Z Yang},\r\n    Howpublished = {Available at \\url{http://abacus.gene.ucl.ac.uk/software/paml.html}},\r\n    Journal = {CABIOS},\r\n    Pages = {555--556},\r\n    Title = {{PAML}: A program package for phylogenetic analysis by maximum likelihood},\r\n    Volume = {15},\r\n    Year = {1997}}\r\n\r\n@article{Yap2004,\r\n    Abstract = {We describe a whole-genome comparative analysis of the human, mouse, and rat genomes to describe the average substitution patterns of four genomic regions: ancient repeats, rodent-specific DNA, exons, and conserved (coding and noncoding) regions, and to identify rodent evolutionary hotspots. In all types of regions, except the rodent-specific DNA, the rat branch is slightly longer than the mouse branch. Moreover, the mouse-rat distance is longer in the rodent-specific DNA than in the ancient repeats. Analysis of individual conserved regions with different substitution models yielded the conclusion that the Jukes--Cantor model is inadequate, and the Hasegawa-Kishino-Yano model is almost as good as the REV model. Using human as an outgroup, we identified 5055 evolutionary hotspots, which are highly conserved subalignment blocks (each consisting of at least 100 aligned sites and a small fraction of gaps) with a large and statistically significant difference in the branch lengths of the rodent species. The cutoffs used to identify the hotspots are partially based on estimates of the average rates of substitution. The fractions of hotspots overlapping with the rodent RefSeq genes, RefSeq exons, and ESTs are all higher than expected. Still, more than half of the hotspots lie in noncoding regions of the mouse genome. We believe that the hotspots represent biologically interesting regions in the rodent genomes.},\r\n    Affiliation = {Department of Mathematics, University of California, Berkeley, California 94720-3840, USA. vonbing@math.berkeley.edu},\r\n    Aid = {14/4/574 {$[$}pii{$]$}},\r\n    Au = {Pachter L},\r\n    Author = {VB Yap and L Pachter},\r\n    Da = {20040402},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Dcom = {20040505},\r\n    Edat = {2004/04/03 05:00},\r\n    Gr = {HG02362-01/HG/NHGRI},\r\n    Jid = {9518021},\r\n    Journal = {Genome Research},\r\n    Keywords = {Animals and Comparative Study and Conserved Sequence/genetics and DNA/genetics and *Evolution, Molecular and *Genome and Genome, Human and Humans and Mice and Models, Genetic and Mutation/genetics and Rats and Repetitive Sequences, Nucleic Acid/genetics and Research Support, U.S. Gov't, P.H.S. and Sensitivity and Specificity and Sequence Alignment/methods/statistics \\& numerical data and Species Specificity},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2004/05/07 05:00},\r\n    Number = {4},\r\n    Own = {NLM},\r\n    Pages = {574--9},\r\n    Pl = {United States},\r\n    Pmid = {15059998},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {9007-49-2 (DNA)},\r\n    Sb = {IM},\r\n    So = {Genome Res 2004 Apr;14(4):661-4.},\r\n    Stat = {MEDLINE},\r\n    Title = {Identification of evolutionary hotspots in the rodent genomes.},\r\n    Volume = {14},\r\n    Year = {2004}}\r\n\r\n@inproceedings{Yedidia2000,\r\n    Author = {J Yedidia and W Freeman and Y Weiss},\r\n    Booktitle = {{NIPS}},\r\n    Date-Modified = {2005-02-05 12:49:26 -0800},\r\n    Title = {Generalized Belief Propagation},\r\n    Year = {2000}}\r\n\r\n@article{Yoder2000,\r\n    Author = {AD Yoder and Z Yang},\r\n    Journal = {Molecular Biology and Evolution},\r\n    Pages = {1081-1090},\r\n    Title = {Estimation of primate speciation dates using local molecular clocks},\r\n    Volume = {17},\r\n    Year = {2000}}\r\n\r\n@article{Yu2002,\r\n    Abstract = {We have produced a draft sequence of the rice genome for the most widely cultivated subspecies in China, {Oryza sativa} {L. ssp. indica}, by whole-genome shotgun sequencing. The genome was 466 megabases in size, with an estimated 46,022 to 55,615 genes. Functional coverage in the assembled sequences was 92.0%. About 42.2% of the genome was in exact 20-nucleotide oligomer repeats, and most of the transposons were in the intergenic regions between genes. Although 80.6% of predicted Arabidopsis thaliana genes had a homolog in rice, only 49.4% of predicted rice genes had a homolog in A. thaliana. The large proportion of rice genes with no recognizable homologs is due to a gradient in the GC content of rice coding sequences.},\r\n    Affiliation = {Beijing Genomics Institute/Center of Genomics and Bioinformatics, Chinese Academy of Sciences, Beijing 101300, China.},\r\n    Aid = {296/5565/79 {$[$}pii{$]$}},\r\n    Au = {Yang H},\r\n    Author = {J Yu and S Hu and J Wang and GKS Wong and S Li and B Liu and Y Deng and L Dai and Y Zhou and X Zhang and others},\r\n    Cin = {Science. 2002 Apr 5;296(5565):92-100. PMID: 11935018},\r\n    Da = {20020405},\r\n    Date-Modified = {2005-02-19 20:05:00 -0800},\r\n    Dcom = {20020423},\r\n    Edat = {2002/04/06 10:00},\r\n    Gr = {1 RO1 ES09909/ES/NIEHS},\r\n    Jid = {0404511},\r\n    Journal = {Science},\r\n    Keywords = {Arabidopsis/genetics and Base Composition and Computational Biology and Contig Mapping and DNA Transposable Elements and DNA, Intergenic and DNA, Plant/chemistry/genetics and Databases, Nucleic Acid and Exons and Gene Duplication and Genes, Plant and *Genome, Plant and Genomics and Introns and Molecular Sequence Data and Oryza sativa/*genetics and Plant Proteins/chemistry/genetics and Polymorphism, Genetic and Repetitive Sequences, Nucleic Acid and Research Support, Non-U.S. Gov't and Research Support, U.S. Gov't, Non-P.H.S. and Research Support, U.S. Gov't, P.H.S. and *Sequence Analysis, DNA and Sequence Homology, Nucleic Acid and Software and Species Specificity and Synteny},\r\n    Language = {eng},\r\n    Lr = {20041117},\r\n    Mhda = {2002/04/24 10:01},\r\n    Number = {5565},\r\n    Own = {NLM},\r\n    Pages = {79--92},\r\n    Pl = {United States},\r\n    Pmid = {11935017},\r\n    Pst = {ppublish},\r\n    Pt = {Journal Article},\r\n    Pubm = {Print},\r\n    Rn = {0 (Plant Proteins)},\r\n    Sb = {IM},\r\n    So = {PLoS Biol 2005 Feb;3(2):e38. Epub 2005 Feb 1.},\r\n    Stat = {MEDLINE},\r\n    Title = {{A draft sequence of the rice genome (Oryza sativa L. ssp. indica)}},\r\n    Volume = {296},\r\n    Year = {2002}}\r\n\r\n@Article{bangjensen2004,\r\n  author = \t {J Bang-Jensen and G Gutin and A Yeo},\r\n  title = \t {When the greedy algorithm fails},\r\n  journal = \t {Discrete Optimization},\r\n  year = \t {2004},\r\n  OPTkey = \t {},\r\n  volume = \t {1},\r\n  OPTnumber = \t {},\r\n  pages = \t {121--127},\r\n  OPTmonth = \t {},\r\n  OPTnote = \t {},\r\n  OPTannote = \t {}\r\n}\r\n\r\n@TECHREPORT{phylip,\r\n  AUTHOR =       {J Felsenstein},\r\n  TITLE =        {{PHYLIP (phylogeny inference package) version 3.5c.}},\r\n  INSTITUTION =  {Department of Genetics, University of Washington, Seattle},\r\n  YEAR =         {1993},\r\n}\r\n\r\n@Article{seq_gen,\r\n  author =   {A Rambaut and N C Grassly},\r\n  title =    {{Seq-Gen: an application for the Monte Carlo simulation of DNA sequences evolution along phylogenetic trees}},\r\n  journal =  {Computational Applied Bioscience},\r\n  year =     {1997},\r\n  OPTkey =   {},\r\n  volume =   {13},\r\n  OPTnumber =    {},\r\n  pages =    {235--238},\r\n  OPTmonth =     {},\r\n  OPTnote =      {},\r\n  OPTannote =    {}\r\n}\r\n"
  },
  {
    "path": "doc/html/css/style.css",
    "content": "/* \nStylesheet for the free sNews15_1 template\nfrom http://www.free-css-templates.com\n*/\n\n/* Reset all margins and paddings for browsers */\n* { \n\tpadding: 0;\n\tmargin: 0;\n}\n\nbody { \n\tfont: .8em Verdana, Arial, Sans-Serif; \n\tline-height: 1.6em; \n\tmargin: 0;\n\t/* background-image: url(../images/bg.jpg); */\n\t/* background-repeat: repeat */\n}\n\n#wrap {\tmargin: 0 auto;\twidth: 95% }\n\n/* TOP HEADER -------- */\n#top {\n\tmargin: 0 auto;\n\tpadding: 0;\n\tcolor: #666;\n\tbackground: #FFF url(../images/cbcbstrip.jpg) repeat-x top;\n\theight: 81px;\n}\n#top h1 { padding: 10px 0 0 25px; color: #FFF; font-size: 240%; background: transparent;}\n#top h2 { padding: 0px 0 0 25px; color: #bbb; font-size: 100%; background: transparent;}\n#top .padding { padding-top: 5px; }\n/*\n#top .lefts { \n\tbackground: transparent url(../images/topl.jpg) no-repeat left; \n\theight: 81px; \n}\n#top .rights {\n\tbackground: transparent url(../images/topr.jpg) no-repeat right;\n\tfloat: right;\n\theight: 81px;\n\twidth: 18px;\n}\n*/\n/* SEARCH BOX AND BUTTON ----------*/\n#search { float: right;  padding: 10px 25px 0 0;  }\n\n#search input.text { \n\tborder: 1px solid #eee;\n\tdisplay: inline;\n\tmargin-top: 5px;\n\twidth: 120px;\n\theight: 12px;\n\tfont-size: 10px;\n }\n #search input.searchbutton {\n\tborder: 0;\n\tbackground: transparent;\n\tcolor: #FFF;\n\tcursor: pointer;\n\tfont: bold 0.8em Arial, Arial, Sans-Serif\n }\n\n#subheader { \n\tclear: both; \n\tborder-top: 1px dotted #888;\t\n\tborder-bottom: 1px dotted #888;\n\tbackground: #eaeaea;\n\tcolor: #505050;\n\tpadding: 1em;\n\tmargin: 15px 0px 10px 0px;\n\t\n}\n#subheader a { text-decoration: none; /* border-bottom: 1px dashed #0066B3; */ } \n \n \n/* TOP MENU ---------- */\n#topmenu {  \tmargin: 0px 8px 0 8px; \n\t\t\tpadding: 0;\n\t\t\tbackground: url(../images/menu.jpg) repeat-x top;\n\t\t\theight: 30px;\n\t\t\t\n}\n#topmenu .lefts { \n\tbackground: url(../images/menul.jpg) no-repeat left; \n\theight: 30px; \n\tpadding-left: 0px;\n}\n#topmenu .rights {\n\tbackground: url(../images/menur.jpg) no-repeat right;\n\tfloat: right;\n\theight: 30px;\n\twidth: 8px;\n}\n#topmenu li a { \n\tcolor: #FFF;\n\ttext-align: left;\n\tpadding-left: 10px;\n\tpadding-right: 15px;\n\ttext-decoration: none;\n\tbackground: transparent;\n\tfont-weight: bold\n} \n#topmenu li { padding: 0px;\n\tfloat: left;\n\tmargin: 0;\n\tfont-size: 11px;\n\tline-height: 30px;\n\twhite-space: nowrap;\n\t/* list-style-type: none; */\n\twidth: auto;\n\tbackground: url(../images/sep.gif) no-repeat top right\n\t\n}\n\n#main { background: #FFF; margin: 25px 0 15px 0; color: #666; }\n\n#main #rightside {\n\twidth: 300px;\n\tfloat: right;\n\tbackground: #FFF;\n\tmargin-right: 0px;\n\tcolor: #555;\n\t\n} \n\n#main #rightside .box {\n\tbackground: #efefef;\n\tmargin-bottom: 10px;\n\tpadding: 5px;\n\tcolor: #555;\n}\n\n#main #rightside h2 {\n\tfont: bold 1.0em Arial, Arial, Sans-Serif; \n    background: #CDCDCD url(../images/greyc.gif) no-repeat top right;\n\theight: 18px;\n\tpadding: 3px;\n\tcolor: #666;\n}\n\n/* LEFT SIDE - ARTICLES AREA -------- */\n#leftside {\n\tpadding-left: 8px;\n\tcolor: #555;\n\tbackground: #FFF;\n\tmargin-right: 255px;\n\tmargin-left: 0px;\n\t\n}\n#leftside h2 { color: #555; text-indent: 17px; background: #FFF url(../images/head.gif) no-repeat left; }\n#leftside h3 { font-size: 100%; margin-left: 15px; text-indent: 17px; background: #FFF url(../images/head.gif) no-repeat left; }\n#leftside ul { margin-left: 24px; padding-left 24px; list-style-type: circle }\n#leftside li { }\n\n#footer {\n\tclear: both;\n\tbackground: #FFF url(../images/footer.jpg) repeat-x;\n\theight: 46px;\n\tmargin-left: 0px;\n\tmargin-right: 0px;\n\tfont-size: 75%;\n\tcolor: #666;\n}\n#footer p  { padding: 5px }\n#footer .rside { float: right; display: inline; padding: 5px; text-align: right}\n\n#toc ol { list-style: roman }\n\na { color: #0066B3; background: inherit; text-decoration: none }\nh1 { font: bold 1.9em Arial, Arial, Sans-Serif }\nh2 { font: bold 1.2em Arial, Arial, Sans-Serif; padding: 0; margin: 0 }\nul { padding: 0; margin: 0; list-style-type: none }\nli {  }\nol { margin-left: 24px;\n     padding-left 24px;\n     list-style: decimal }\nblockquote { margin-left: 35px; font-family: \"Courier New\", Courier, monospace; }\ntt { font-family: \"Courier New\", Courier, monospace; }\n.date { border-top: 1px solid #e5e5e5; text-align: right; margin-bottom: 25px; margin-top: 5px;}\n#main #leftside .date a, #main #rightside a { border: 0; text-decoration: none; }\n \n.comment .date { text-align: left; border: 0;}\t\n\n\n#breadcrumbs { \n\tfloat: left;\n\tpadding-left: 8px;\n\tpadding-top: 0px;\n\tfont: bold .8em Arial, Arial, Sans-Serif; \n\tcolor: #666;\n\twidth: 100%;\n\theight: 25px;\n\tmargin-top: 10px;\n\tmargin-bottom: 10px;\n\tclear: both;\n}\n\n\n\n#leftside #txt {width: 100%; height: 10em; padding: 3px 3px 3px 6px; margin-left:0em;}\n#leftside textarea { border: 1px solid #bbb; width: 100%;  }\n\n\n/* SNEWS */\n#main #leftside fieldset { float: left; width: 100%; border: 1px solid #ccc; padding: 10px 8px; margin: 0 10px 8px 0; background: #FFF; color: #000; }\n#main #leftside fieldset p { width: 100%; }\n#main input { padding: 3px; margin: 0; border: 1px solid #bbb }\np { margin-top: 5px; }\n/*input.search { border: 1px solid #ccc; padding: 4px; width: 160px; }*/\n.comment { background: #FFF; color: #808080; padding: 10px; margin: 0 0 10px 0; border-top: 1px solid #ccc; }\n.commentsbox { background: #FFF; color: #808080; padding: 10px; margin: 0 0 10px 0; border-top: 1px solid #ccc; }\n\n\n#box-table-a\n{\n\tfont-family: .8em Verdana, Arial, Sans-Serif; \n\t/*font-size: 12px;*/\n\tmargin: 45px;\n\twidth: 600px;\n\ttext-align: left;\n\tborder-collapse: collapse;\n}\n#box-table-a th\n{\n\tfont-size: 13px;\n\tfont-weight: normal;\n\tpadding: 8px;\n\tbackground: #b9c9fe;\n\tborder-top: 4px solid #aabcfe;\n\tborder-bottom: 1px solid #fff;\n\tcolor: #039;\n}\n#box-table-a td\n{\n\tpadding: 8px;\n\tbackground: #e8edff; \n\tborder-bottom: 2px solid #fff;\n\tcolor: #669;\n\tborder-top: 2px solid transparent;\n}\n#box-table-a tr:hover td\n{\n\tbackground: #d0dafd;\n\tcolor: #339;\n}\n\n\n#box-table-b\n{\n\tfont-family: .8em Verdana, Arial, Sans-Serif; \n\t/*font-size: 12px;*/\n\tmargin: 45px;\n\twidth: 480px;\n\ttext-align: center;\n\tborder-collapse: collapse;\n\tborder-top: 7px solid #9baff1;\n\tborder-bottom: 7px solid #9baff1;\n}\n#box-table-b th\n{\n\tfont-size: 13px;\n\tfont-weight: normal;\n\tpadding: 8px;\n\tbackground: #e8edff;\n\tborder-right: 1px solid #9baff1;\n\tborder-left: 1px solid #9baff1;\n\tcolor: #039;\n}\n#box-table-b td\n{\n\tpadding: 8px;\n\tbackground: #e8edff; \n\tborder-right: 1px solid #aabcfe;\n\tborder-left: 1px solid #aabcfe;\n\tcolor: #669;\n}"
  },
  {
    "path": "doc/html/downloads/test_data.sam",
    "content": "test_mRNA_3_187_51\t99\ttest_chromosome\t53\t255\t75M\t=\t163\t0\tTACTATTTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTCGGACTACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_4_191_5d\t163\ttest_chromosome\t54\t255\t75M\t=\t167\t0\tACTATCTGACGAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTACCATTACGCGGATGACGACTAGGACTACGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\ntest_mRNA_5_197_46\t97\ttest_chromosome\t55\t255\t75M\t=\t173\t0\tCTATCTGACTAGACTCGAGGCGCTTGCGTCTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_6_182_59\t99\ttest_chromosome\t56\t255\t75M\t=\t158\t0\tTATCTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCAGTACGGGGATGACGACTAGGACTACGGAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_8_155_9\t163\ttest_chromosome\t58\t255\t75M\t=\t131\t0\tTGTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_8_197_1\t99\ttest_chromosome\t58\t255\t75M\t=\t173\t0\tTCTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGACACTACGGGGATGGCGACTAGGACTACGGACGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_9_179_52\t163\ttest_chromosome\t59\t255\t75M\t=\t155\t0\tCTGACTAGACTGGAGGCGCTCGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_11_190_1a\t99\ttest_chromosome\t61\t255\t75M\t=\t166\t0\tGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_16_194_10\t163\ttest_chromosome\t66\t255\t75M\t=\t170\t0\tGACTGGATGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTCGGACTACGGACGGACTTAAAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_21_208_24\t163\ttest_chromosome\t71\t255\t75M\t=\t184\t0\tGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_22_173_62\t99\ttest_chromosome\t72\t255\t75M\t=\t149\t0\tAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_23_186_42\t163\ttest_chromosome\t73\t255\t75M\t=\t162\t0\tGGCGCTTGTGACTGAGCTAGGACGTGCCACTACGGGGATGAAGACTAGGACTACGGACGGACTTAGAGCGTCAGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_26_189_30\t163\ttest_chromosome\t76\t255\t75M\t=\t165\t0\tGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_28_188_11\t99\ttest_chromosome\t78\t255\t75M\t=\t164\t0\tTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGAACGGACTTAGAGCGTCAGATGCAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_28_206_1f\t73\ttest_chromosome\t78\t255\t75M\t*\t0\t0\tTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGACGCAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_30_231_3c\t161\ttest_chromosome\t80\t255\t75M\t=\t207\t0\tGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_33_223_4e\t73\ttest_chromosome\t83\t255\t75M\t*\t0\t0\tACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_36_146_27\t163\ttest_chromosome\t86\t255\t75M\t=\t122\t0\tGCGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACAGACGGACTTAGAGCGTCAGATGCAGCGACTGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_36_218_12\t99\ttest_chromosome\t86\t255\t75M\t=\t194\t0\tGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGCCTTAGAGCGTCAGATGCAGCGACTGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_38_199_29\t99\ttest_chromosome\t88\t255\t75M\t=\t175\t0\tGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_39_219_5c\t99\ttest_chromosome\t89\t255\t75M\t=\t195\t0\tCTAGGACGTCCCACTATGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGGCTGGACTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_41_236_55\t97\ttest_chromosome\t91\t255\t75M\t=\t212\t0\tAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGAATATT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_42_209_25\t99\ttest_chromosome\t92\t255\t75M\t=\t185\t0\tGGACGTGCCACTACGTGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_44_193_3f\t99\ttest_chromosome\t94\t255\t75M\t=\t169\t0\tACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGTCTATTTAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_44_197_35\t99\ttest_chromosome\t94\t255\t75M\t=\t173\t0\tACGTGCAACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_44_225_1e\t163\ttest_chromosome\t94\t255\t75M\t=\t201\t0\tACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCGGGTGCAGCGACTGGACTATTTAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_46_195_17\t137\ttest_chromosome\t96\t255\t75M\t*\t0\t0\tGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_46_232_2f\t99\ttest_chromosome\t96\t255\t75M\t=\t208\t0\tGTGCCACTACGGGGATGACGACTAGGACTACGGCCGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_48_207_39\t73\ttest_chromosome\t98\t255\t75M\t*\t0\t0\tGCCCCTACGGGGATGACGACTAGGACTACGGACGGATTTAGACCGTCAGATGCAGCGACTGGACTATTTAGGACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_48_249_20\t161\ttest_chromosome\t98\t255\t75M\t=\t225\t0\tGCCACTACGGGGATGACGACTAGGACGACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_50_224_2d\t163\ttest_chromosome\t100\t255\t75M\t=\t200\t0\tCACTACGAGGATGACGTCTAGGACTACGGACGGACTTAGAGCGTCAGACGCAGCGACTGGACTATTTAGGACGAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_51_194_47\t163\ttest_chromosome\t101\t255\t75M\t=\t170\t0\tACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_51_194_49\t99\ttest_chromosome\t101\t255\t75M\t=\t170\t0\tACTACGGGGATGACGACTAGGCCTACGGATGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_51_237_a\t99\ttest_chromosome\t101\t255\t75M\t=\t213\t0\tACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_51_248_14\t97\ttest_chromosome\t101\t255\t75M\t=\t224\t0\tACTACGGGGATGACGACGAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGAACTTTTTAGGACGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_52_261_1b\t97\ttest_chromosome\t102\t255\t75M\t=\t237\t0\tCTACGGGAATGACGACTAGGGCTACGGAGGGACTTACAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\ntest_mRNA_53_212_19\t99\ttest_chromosome\t103\t255\t75M\t=\t188\t0\tTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGAATATTTAGGACGATCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_53_272_5a\t161\ttest_chromosome\t103\t255\t75M\t=\t248\t0\tTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_56_183_56\t99\ttest_chromosome\t106\t255\t75M\t=\t159\t0\tGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTGGGACGATCGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_57_231_8\t99\ttest_chromosome\t107\t255\t75M\t=\t207\t0\tGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCACCGACTGGACTATTTAGGACGATCGGACTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_58_218_16\t163\ttest_chromosome\t108\t255\t75M\t=\t194\t0\tGGATGACGACTAGGACTACGGACGGACTTAGAACGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_58_220_3d\t163\ttest_chromosome\t108\t255\t75M\t=\t196\t0\tGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_58_234_7\t163\ttest_chromosome\t108\t255\t75M\t=\t210\t0\tGGATGACGCCTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_63_229_4c\t163\ttest_chromosome\t113\t255\t75M\t=\t205\t0\tACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGGGACTGGACTATTTAGGACGATCGGACTGAGGAGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_65_238_2e\t99\ttest_chromosome\t115\t255\t75M\t=\t214\t0\tGACTAGGACTACGGACGGACTTAGAGCGTCAGAAGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_69_229_23\t163\ttest_chromosome\t119\t255\t75M\t=\t205\t0\tAGGACTACGGACGGACTTATAGGGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_36_146_27\t83\ttest_chromosome\t122\t255\t75M\t=\t86\t0\tACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGTGCAGTAGGT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_72_258_4\t163\ttest_chromosome\t122\t255\t75M\t=\t234\t0\tACTACGGACGGACTTAGAGCGTCAGATGCAGCAACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_73_240_34\t99\ttest_chromosome\t123\t255\t75M\t=\t216\t0\tCTACGGACGGACTTAGAGCGTCAGATGCAGCGAATGGACTATTTAGGACGCTCGGACTGAGGAGGGCAGTAGGAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_73_259_5e\t99\ttest_chromosome\t123\t255\t75M\t=\t235\t0\tCTACGGACGGACTTAGAGCGTCAGATGCTGCGACTGGACTATTTGGGACGATCGGACTGAGGAGGGCAGTAGGAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_75_204_54\t73\ttest_chromosome\t125\t255\t75M\t*\t0\t0\tACGGACGGACTTCGAGCCTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_75_235_21\t73\ttest_chromosome\t125\t255\t75M\t*\t0\t0\tACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGCACGATCGGACTGAGGAGGGCAGTAGAACGT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_75_277_3b\t97\ttest_chromosome\t125\t255\t75M\t=\t353\t0\tACGGACGGACTTAAAGCTTCAGATGCAGCGACAGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_77_256_2c\t73\ttest_chromosome\t127\t255\t75M\t*\t0\t0\tGGACGGACTTAGAGCATCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_78_276_4b\t97\ttest_chromosome\t128\t255\t75M\t=\t352\t0\tGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGGCGCTAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_79_256_31\t137\ttest_chromosome\t129\t255\t75M\t*\t0\t0\tACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_81_228_3a\t163\ttest_chromosome\t131\t255\t75M\t=\t204\t0\tGGACTGAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGTAGTAGGACGCTACGTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_81_245_4d\t163\ttest_chromosome\t131\t255\t75M\t=\t221\t0\tGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGATGAGGGCAGTAGGACGCTACGTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_8_155_9\t83\ttest_chromosome\t131\t255\t75M\t=\t58\t0\tGGACTTCGAGCGTCAGATGCAGCGACTGTACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_82_255_2\t137\ttest_chromosome\t132\t255\t75M\t*\t0\t0\tGACTTAGAGCGTCAGATGCAGCGACTGGACTTTTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_82_271_58\t99\ttest_chromosome\t132\t255\t75M\t=\t247\t0\tGACTTAGAGCGTCAGTTGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_85_268_53\t99\ttest_chromosome\t135\t255\t75M\t=\t244\t0\tTTAGTGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_87_250_57\t163\ttest_chromosome\t137\t255\t75M\t=\t226\t0\tAGAGCGTCAGATGCAGAGACTGGACTATTTAGGACGATCGGACTGAGGAGTGCAGTAGGACGCTACGTATTTGGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_87_279_5f\t161\ttest_chromosome\t137\t255\t75M\t=\t355\t0\tAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACCGAGGAGGGCAGTAGGACGCTACGTATTTGGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_88_257_50\t137\ttest_chromosome\t138\t255\t75M\t*\t0\t0\tGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_89_230_b\t163\ttest_chromosome\t139\t255\t75M\t=\t206\t0\tAGCGTCAGGTGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_89_245_15\t99\ttest_chromosome\t139\t255\t75M\t=\t221\t0\tAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_89_267_32\t163\ttest_chromosome\t139\t255\t75M\t=\t243\t0\tAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGAGTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_91_256_41\t73\ttest_chromosome\t141\t255\t75M\t*\t0\t0\tCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_92_250_44\t99\ttest_chromosome\t142\t255\t75M\t=\t226\t0\tGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\ntest_mRNA_92_266_43\t99\ttest_chromosome\t142\t255\t75M\t=\t242\t0\tGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTCAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_96_238_3\t163\ttest_chromosome\t146\t255\t75M\t=\t214\t0\tGATGCAGCGACTGGACTATTTAGGACGATCGGACGGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGACC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_97_275_26\t97\ttest_chromosome\t147\t255\t75M\t=\t351\t0\tATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_22_173_62\t147\ttest_chromosome\t149\t255\t75M\t=\t72\t0\tGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_103_284_2a\t161\ttest_chromosome\t153\t255\t75M\t=\t360\t0\tCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_104_278_3e\t161\ttest_chromosome\t154\t255\t75M\t=\t354\t0\tGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTTTTTGGCGCGCGGCCCTACGGCTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_105_266_13\t163\ttest_chromosome\t155\t255\t75M\t=\t242\t0\tACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_105_276_c\t161\ttest_chromosome\t155\t255\t75M\t=\t352\t0\tACTGGACTATTTAGGACGATCGGACTGAGGAAGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_9_179_52\t83\ttest_chromosome\t155\t255\t75M\t=\t59\t0\tACTGGACCATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_106_253_45\t137\ttest_chromosome\t156\t255\t75M\t*\t0\t0\tCTGGACTATTTAGGTCGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_107_286_5\t161\ttest_chromosome\t157\t255\t75M\t=\t362\t0\tTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGCATTTGGCGCGCGGCCCTACGGCTGAGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_6_182_59\t147\ttest_chromosome\t158\t255\t75M\t=\t56\t0\tGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_56_183_56\t147\ttest_chromosome\t159\t255\t75M\t=\t106\t0\tGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_110_267_22\t163\ttest_chromosome\t160\t255\t75M\t=\t243\t0\tACTAGTTAGGGCGATCGGACTGAGGAGGGCAGTAGGACGCTACGTAGTTGGCGCGCGGCCCTACGACTGAGCGTC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:5\ntest_mRNA_110_271_28\t99\ttest_chromosome\t160\t255\t75M\t=\t247\t0\tACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_111_297_61\t161\ttest_chromosome\t161\t255\t75M\t=\t373\t0\tCTATTTAGGACGATCGGACTGGGGAGGGCAGTAGGACGCTACGGATTTGGCGCGCGGCCCTACGGCTGAGCGTCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_23_186_42\t83\ttest_chromosome\t162\t255\t75M\t=\t73\t0\tTATTTAGGACGATCGGACGGAGGAGGGCAGAAGGACGCTACGTATTTGGCGCGCGGCCCTACGACTGAGCGTCGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\ntest_mRNA_3_187_51\t147\ttest_chromosome\t163\t255\t75M\t=\t53\t0\tATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_114_277_5b\t161\ttest_chromosome\t164\t255\t75M\t=\t353\t0\tTTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGCCTGAGCGTCGAGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_28_188_11\t147\ttest_chromosome\t164\t255\t75M\t=\t78\t0\tTTTAGGACGATCGGACTGAGGAAGGCAGTAGGACGCTTCGTATTTGGCGCGAGGCCCTACGGCTGAGCGTCGAGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\ntest_mRNA_26_189_30\t83\ttest_chromosome\t165\t255\t75M\t=\t76\t0\tTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGGTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_33_189_4a\t89\ttest_chromosome\t165\t255\t75M\t*\t0\t0\tTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACCTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGGGCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_116_271_2b\t163\ttest_chromosome\t166\t255\t75M\t=\t247\t0\tTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_116_295_63\t161\ttest_chromosome\t166\t255\t75M\t=\t371\t0\tTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_11_190_1a\t147\ttest_chromosome\t166\t255\t75M\t=\t61\t0\tTAGGTCGATGGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGTGGCCCTACGGCTGAGCGTCGAGCTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\ntest_mRNA_4_191_5d\t83\ttest_chromosome\t167\t255\t75M\t=\t54\t0\tAGGACGATCGGACTGAGTAGGGCAGTAGGACACTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_118_297_f\t161\ttest_chromosome\t168\t255\t75M\t=\t373\t0\tGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_44_193_3f\t147\ttest_chromosome\t169\t255\t75M\t=\t94\t0\tGACGATCGGACTGGGGAGAGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_16_194_10\t83\ttest_chromosome\t170\t255\t75M\t=\t66\t0\tACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_51_194_47\t83\ttest_chromosome\t170\t255\t75M\t=\t101\t0\tACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_51_194_49\t147\ttest_chromosome\t170\t255\t75M\t=\t101\t0\tACGTTCGGACTGAGGAGGGCAGTAGGACGCCACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\ntest_mRNA_122_299_6\t161\ttest_chromosome\t172\t255\t75M\t=\t375\t0\tGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_44_197_35\t147\ttest_chromosome\t173\t255\t75M\t=\t94\t0\tATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGATCGTCGAGCTTGCGATAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\ntest_mRNA_5_197_46\t145\ttest_chromosome\t173\t255\t75M\t=\t55\t0\tATCGGACGGAGGAGGGCAGTAGGACGCTACGTATTTGGCGGGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_8_197_1\t147\ttest_chromosome\t173\t255\t75M\t=\t58\t0\tATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_125_280_48\t97\ttest_chromosome\t175\t255\t75M\t=\t356\t0\tCGGACTGAGGAGGGCAGTAGGACGCTATGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGAAACGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\ntest_mRNA_125_293_60\t161\ttest_chromosome\t175\t255\t75M\t=\t369\t0\tCGGACTGAGGAGGGCAGTAGGACGCTATGTATTTGGCGCGCGGCCCTACGGCTGAGCTTCGAGGTTGCGATACGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\ntest_mRNA_38_199_29\t147\ttest_chromosome\t175\t255\t75M\t=\t88\t0\tCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_126_282_18\t161\ttest_chromosome\t176\t255\t75M\t=\t358\t0\tGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\ntest_mRNA_131_260_33\t99\ttest_chromosome\t181\t255\t70M100N5M\t=\t236\t0\tGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_21_208_24\t83\ttest_chromosome\t184\t255\t67M100N8M\t=\t71\t0\tGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGCCTGAGCGTCGAGCTTGCGATACGCCACTATTAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_42_209_25\t147\ttest_chromosome\t185\t255\t66M100N9M\t=\t92\t0\tAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_53_212_19\t147\ttest_chromosome\t188\t255\t63M100N12M\t=\t103\t0\tGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTTCTTTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:1\ntest_mRNA_36_218_12\t147\ttest_chromosome\t194\t255\t57M100N18M\t=\t86\t0\tGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_58_218_16\t83\ttest_chromosome\t194\t255\t57M100N18M\t=\t108\t0\tGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_145_300_37\t163\ttest_chromosome\t195\t255\t56M100N19M\t=\t376\t0\tGACGCTACGTATTTGGCGCGGGGCCCTATGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTAGTATATT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:5\tXS:A:+\tNS:i:2\ntest_mRNA_39_219_5c\t147\ttest_chromosome\t195\t255\t56M100N19M\t=\t89\t0\tGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCCAGCTTGCGATACGCCACTATTACTTTATTATCTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_58_220_3d\t83\ttest_chromosome\t196\t255\t55M100N20M\t=\t108\t0\tACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGGTTGCGATACGCCACTATTACTTTATTATCTTC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:1\ntest_mRNA_50_224_2d\t83\ttest_chromosome\t200\t255\t51M100N24M\t=\t100\t0\tTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_44_225_1e\t83\ttest_chromosome\t201\t255\t50M100N25M\t=\t94\t0\tACGTATATGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_81_228_3a\t83\ttest_chromosome\t204\t255\t47M100N28M\t=\t131\t0\tTATTTGGCGCGCGGCCCTATGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGTAGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\tXS:A:+\tNS:i:0\ntest_mRNA_63_229_4c\t83\ttest_chromosome\t205\t255\t46M100N29M\t=\t113\t0\tATTTGGCGCGCGGCCCTACGGCTGAGTGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:1\ntest_mRNA_69_229_23\t83\ttest_chromosome\t205\t255\t46M100N29M\t=\t119\t0\tCTTTGGCGCGCGGCCCTACGGCTGAGCGTCTAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:1\ntest_mRNA_89_230_b\t83\ttest_chromosome\t206\t255\t45M100N30M\t=\t139\t0\tTCTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTAACTCACTCGGACGTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\tXS:A:+\tNS:i:0\ntest_mRNA_30_231_3c\t81\ttest_chromosome\t207\t255\t44M100N31M\t=\t80\t0\tTTGGCGCGCGGCCCTACGGCTAAGCGTCGAGCTTGCGATACGCCACTATTACTTTAATATCTTACTCGCACGTAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\tXS:A:+\tNS:i:0\ntest_mRNA_57_231_8\t147\ttest_chromosome\t207\t255\t44M100N31M\t=\t107\t0\tTTGGCGCGCGGCCCTAGGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_46_232_2f\t147\ttest_chromosome\t208\t255\t43M100N32M\t=\t96\t0\tTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_58_234_7\t83\ttest_chromosome\t210\t255\t41M100N34M\t=\t108\t0\tGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTAGTTTATTATCTGACTCGGACGTAGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\tXS:A:+\tNS:i:1\ntest_mRNA_41_236_55\t145\ttest_chromosome\t212\t255\t39M100N36M\t=\t91\t0\tGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_51_237_a\t147\ttest_chromosome\t213\t255\t38M100N37M\t=\t101\t0\tCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_65_238_2e\t147\ttest_chromosome\t214\t255\t37M100N38M\t=\t115\t0\tGCGGCCCTACGGCTGCGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_96_238_3\t83\ttest_chromosome\t214\t255\t37M100N38M\t=\t146\t0\tGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCTACTAGTACTTTATTATCTTACGCGGACGTAGACGGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\tXS:A:+\tNS:i:2\ntest_mRNA_73_240_34\t147\ttest_chromosome\t216\t255\t35M100N40M\t=\t123\t0\tGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTTCTCGGACGTAGACGGATCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_81_245_4d\t83\ttest_chromosome\t221\t255\t30M100N45M\t=\t131\t0\tTACGGCTGAGCGTCGAGGTTGCGATACGCCACTATTACTTTATAATCTTACTCGGACGTAGACGGATCGGCAACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:1\ntest_mRNA_89_245_15\t147\ttest_chromosome\t221\t255\t30M100N45M\t=\t139\t0\tTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTTCTCTATTATCTTACTCGGACGTAGACGGATCGGCAACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:2\ntest_mRNA_172_294_4f\t99\ttest_chromosome\t222\t255\t29M100N46M\t=\t370\t0\tACGGATGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTCCTCGGACGTAGACGGATCGCCAACGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:1\ntest_mRNA_51_248_14\t145\ttest_chromosome\t224\t255\t27M100N48M\t=\t101\t0\tGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGAACGGCAACGGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:0\ntest_mRNA_48_249_20\t81\ttest_chromosome\t225\t255\t26M100N49M\t=\t98\t0\tGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTACTATCTTACTCGGACGGAGACGGATCGGCAACGGGAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:0\ntest_mRNA_87_250_57\t83\ttest_chromosome\t226\t255\t25M100N50M\t=\t137\t0\tATGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_92_250_44\t147\ttest_chromosome\t226\t255\t25M100N50M\t=\t142\t0\tCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGGTACGGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_128_252_36\t153\ttest_chromosome\t228\t255\t23M100N52M\t*\t0\t0\tGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGGAACGGGACTTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\tXS:A:+\tNS:i:0\ntest_mRNA_72_258_4\t83\ttest_chromosome\t234\t255\t17M100N50M100N8M\t=\t122\t0\tCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATGGGCAACGGGACTTTTTCTAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:1\ntest_mRNA_73_259_5e\t147\ttest_chromosome\t235\t255\t16M100N50M100N9M\t=\t123\t0\tGAGCTTGCGATACGCCACTATTACTGTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_131_260_33\t147\ttest_chromosome\t236\t255\t15M100N50M100N10M\t=\t181\t0\tAGCTTGTGATACGCCACTATTACTTTATTATCTTACTCGGACGTAAACGGATCGGCCACGGGACTTTTTTTACTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\tXS:A:+\tNS:i:3\ntest_mRNA_52_261_1b\t145\ttest_chromosome\t237\t255\t14M100N50M100N11M\t=\t102\t0\tGCTTGCGATACGCCACTATTACTTAATTATCTTACTCGGACGTAGAAGGATCGGCAACGGGACTTTTTCTACTTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:1\ntest_mRNA_105_266_13\t83\ttest_chromosome\t242\t255\t9M100N50M100N16M\t=\t155\t0\tCGATCCGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:1\ntest_mRNA_92_266_43\t147\ttest_chromosome\t242\t255\t9M100N50M100N16M\t=\t142\t0\tCGATACGCCACTATTACTTTCTTATCTTACTCGGACGTAGACGGAGCGGCAACGGGACTTTTTCTACTTGAGACC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:2\ntest_mRNA_110_267_22\t83\ttest_chromosome\t243\t255\t8M100N50M100N17M\t=\t160\t0\tGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\tXS:A:+\tNS:i:0\ntest_mRNA_89_267_32\t83\ttest_chromosome\t243\t255\t8M100N50M100N17M\t=\t139\t0\tGATACGGCACTATTACTTTATTATCTTTCTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:1\ntest_mRNA_111_268_d\t89\ttest_chromosome\t244\t255\t7M100N50M100N18M\t*\t0\t0\tATACGCCACTATTATTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:1\ntest_mRNA_85_268_53\t147\ttest_chromosome\t244\t255\t7M100N50M100N18M\t=\t135\t0\tATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGTCAACGGGACTTTTTCTACTTGAGACTGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_110_271_28\t147\ttest_chromosome\t247\t255\t4M100N50M100N21M\t=\t160\t0\tCGCCACTATTACTTTATTATCTTACTCGGACGAAGACGGATCGGCAACGGGGCTTTTTCTACTTGAGACTGGGAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:1\ntest_mRNA_116_271_2b\t83\ttest_chromosome\t247\t255\t4M100N50M100N21M\t=\t166\t0\tCGCCACTATTACTTTATTATCTTACTCGGACGTAGACAGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_82_271_58\t147\ttest_chromosome\t247\t255\t4M100N50M100N21M\t=\t132\t0\tCGCCACTATTACTTTATTATCTTACTCGGACGTAGACGCATCGGCAACGGGACTTTTTCTACTTGAGACTGGGAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_53_272_5a\t81\ttest_chromosome\t248\t255\t3M100N50M100N22M\t=\t103\t0\tGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGACACTGGGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:1\ntest_mRNA_104_274_1c\t89\ttest_chromosome\t350\t255\t51M100N24M\t*\t0\t0\tCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_85_275_38\t153\ttest_chromosome\t351\t255\t50M100N25M\t*\t0\t0\tACTCTTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTACTACTTGAGACTGGGATCGAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_97_275_26\t145\ttest_chromosome\t351\t255\t50M100N25M\t=\t147\t0\tACTATTACTTTATTATCTTAGTCGGACGTAGACGGATCGGAAACGGGACTCTTTCTACTTGAGACTGGGATCGAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:0\ntest_mRNA_105_276_c\t81\ttest_chromosome\t352\t255\t49M100N26M\t=\t155\t0\tCTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGGCTTTTTCTACTTGAGACTGGGATCGAGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_78_276_4b\t145\ttest_chromosome\t352\t255\t49M100N26M\t=\t128\t0\tCTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTAGGATCGAGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_114_277_5b\t81\ttest_chromosome\t353\t255\t48M100N27M\t=\t164\t0\tTATTACTTTATTATCTTACTCGGAGGTAGACGGAACGGCAACGGGACTTTTTCTGCTTGAGACTGGGATCGAGGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:4\tXS:A:+\tNS:i:0\ntest_mRNA_75_277_3b\t145\ttest_chromosome\t353\t255\t48M100N27M\t=\t125\t0\tTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACCTGAGACTGGGATCGAGGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_104_278_3e\t17\ttest_chromosome\t354\t255\t47M100N28M\t=\t154\t0\tATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGAATCGAGGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:0\ntest_mRNA_104_278_3e\t81\ttest_chromosome\t354\t255\t47M100N28M\t=\t154\t0\tATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGAATCGAGGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_87_279_5f\t81\ttest_chromosome\t355\t255\t46M100N29M\t=\t137\t0\tTTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\tXS:A:+\tNS:i:0\ntest_mRNA_125_280_48\t145\ttest_chromosome\t356\t255\t45M100N30M\t=\t175\t0\tTACTTTATTATCTTACTCTGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGAGCGAGGCGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_126_282_18\t81\ttest_chromosome\t358\t255\t43M100N32M\t=\t176\t0\tCTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\tXS:A:+\tNS:i:0\ntest_mRNA_103_284_2a\t81\ttest_chromosome\t360\t255\t41M100N34M\t=\t153\t0\tTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\tXS:A:+\tNS:i:0\ntest_mRNA_107_286_5\t81\ttest_chromosome\t362\t255\t39M100N36M\t=\t157\t0\tATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\tXS:A:+\tNS:i:0\ntest_mRNA_151_286_e\t153\ttest_chromosome\t362\t255\t39M100N36M\t*\t0\t0\tATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTATCTACTTGAGACTGGGATCGAGGCGGACTTTTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:1\ntest_mRNA_150_290_0\t89\ttest_chromosome\t366\t255\t35M100N40M\t*\t0\t0\tTCTTACTCGGACGTAGACGGATCGCCAACGGGACTTTTTCTACTTGAGACTGAGACCGAGGCGGACTTTTTAGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:0\ntest_mRNA_94_291_40\t153\ttest_chromosome\t367\t255\t34M100N41M\t*\t0\t0\tCTTCCTGGGACGTAGACGGATCGGCAACGCGACATTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTGGGAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:5\tXS:A:+\tNS:i:2\ntest_mRNA_125_293_60\t81\ttest_chromosome\t369\t255\t32M100N43M\t=\t175\t0\tTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\tXS:A:+\tNS:i:0\ntest_mRNA_172_294_4f\t147\ttest_chromosome\t370\t255\t31M100N44M\t=\t222\t0\tACTCGGACGTAGACGGGTCGGCAGCGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACGTTTTAGGACGGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:0\ntest_mRNA_116_295_63\t81\ttest_chromosome\t371\t255\t30M100N45M\t=\t166\t0\tCTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\tXS:A:+\tNS:i:0\ntest_mRNA_111_297_61\t17\ttest_chromosome\t373\t255\t28M100N47M\t=\t161\t0\tCGGACGTAGACGGATCCGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:0\ntest_mRNA_111_297_61\t81\ttest_chromosome\t373\t255\t28M100N47M\t=\t161\t0\tCGGACGTAGACGGATCCGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_118_297_f\t17\ttest_chromosome\t373\t255\t28M100N47M\t=\t168\t0\tCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_118_297_f\t81\ttest_chromosome\t373\t255\t28M100N47M\t=\t168\t0\tCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:0\tXS:A:+\tNS:i:0\ntest_mRNA_151_297_1d\t153\ttest_chromosome\t373\t255\t28M100N47M\t*\t0\t0\tCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACATTTTAGGACGGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\ntest_mRNA_151_297_1d\t25\ttest_chromosome\t373\t255\t28M100N47M\t*\t0\t0\tCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACATTTTAGGACGGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:3\tXS:A:+\tNS:i:0\ntest_mRNA_122_299_6\t81\ttest_chromosome\t375\t255\t26M100N49M\t=\t172\t0\tGACGTAGACGGAGCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACTTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:2\tXS:A:+\tNS:i:0\ntest_mRNA_145_300_37\t83\ttest_chromosome\t376\t255\t25M100N50M\t=\t195\t0\tACGTAGACGGATCGGAAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACTTGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tNM:i:1\tXS:A:+\tNS:i:0\n"
  },
  {
    "path": "doc/html/faq.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<title>Cufflinks RNA-Seq analysis tools - Frequently Asked Questions</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n<meta name=\"description\" content=\"Common issues and questions when using Cufflinks to discover new genes or find differentially expressed ones with RNA-Seq\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\" media=\"screen\" />\n</head>\n<body>\n<div id=\"wrap\">\n  <div id=\"top\">\n    <div class=\"lefts\">\n    <table width=\"100%\" cellpadding=\"2\">\n      <tr><td>\n        <a href=\"./index.html\"><h1>Cufflinks</h1></a>\n        <h2>Transcript assembly, differential expression, and differential regulation for RNA-Seq</h2>\n      </td><td align=\"right\" valign=\"middle\">\n        <a href=\"http://www.mcb.berkeley.edu/\">\n          <img style=\"vertical-align:middle;padding-top:4px\" \n            border=0 src=\"images/UCBerkeley-seal.scaled.gif\">\n        </a>&nbsp;\n        <a href=\"http://genomics.jhu.edu/\">\n          <img style=\"vertical-align:middle;padding-top:4px\"\n           src=\"images/JHU-seal.gif\" border=\"0\">\n        </a>&nbsp;\n\n        <a href=\"http://www.cbcb.umd.edu/\"><img style=\"vertical-align:middle;padding-top:4px\" border=0 src=\"images/cbcb_logo.gif\"></a>&nbsp;&nbsp;\n      </td></tr>\n    </table>\n    </div>\n  </div>\n  <div id=\"subheader\">\n  <table width=\"100%\"><tr>\n  <td>\n  \t\t<strong>Please Note</strong> If you have questions \n\t\t  about how to use Cufflinks or would like more information about \n\t\t  the software, please email <a href=\"mailto:tophat.cufflinks@gmail.com\">the Cufflinks team</a>, \n\t\t  though we ask you to have a look at the <a href=\"http://dx.doi.org/10.1038/nbt.1621\">paper</a> \n\t\t  and the  <a href=\"http://www.nature.com/nbt/journal/v28/n5/extref/nbt.1621-S1.pdf\">\n\t\t  supplemental methods</a> first, as your question may be answered there.\n\t</td><td align=right valign=middle>\n  </td></tr>\n  </table>\n  </div>\n  <div id=\"main\">\n    <div id=\"rightside\">\n\t\t<h2>Site Map</h2>\n        <div class=\"box\">\n          <ul>\n            <li><a href=\"index.html\">Home</a></li>\n            <li><a href=\"tutorial.html\">Getting started</a></li>\n            <li><a href=\"manual.html\">Manual</a></li>\n            <li><a href=\"howitworks.html\">How Cufflinks works</a></li>\n\t\t\t  <li><a href=\"igenomes.html\">Index and annotation downloads</a></li>\n            <li><a href=\"faq.html\">FAQ</a></li>\n\t\t\t  <li><a href=\"http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html\">Protocol</a></li>\n\t\t\t  <li><a href=\"report.html\">Benchmarking</a></li>\n          </ul>\n        </div>\n\t\t\n        <h2><u>News and updates</u></h2>\n        <div class=\"box\">\n          <ul>\n            <table width=\"100%\">\n              <tbody>\n                <tr>\n                  <td>New releases and related tools will be announced\n                    through the <a\n                      href=\"https://lists.sourceforge.net/lists/listinfo/bowtie-bio-announce\"><b>mailing\n                        list</b></a></td>\n                </tr>\n              </tbody>\n            </table>\n          </ul>\n        </div>\n        <h2><u>Getting Help</u></h2>\n        <div class=\"box\">\n          <ul>\n            <table width=\"100%\">\n              <tbody>\n                <tr>\n                  <td>Questions about Cufflinks and Cuffdiff should be posted on our <a href=\"https://groups.google.com/forum/#!forum/tuxedo-tools-users\"><b>Google Group</b></a>. Please use <a\n                      href=\"mailto:tophat.cufflinks@gmail.com\">tophat.cufflinks@gmail.com</a> for private communications only.\n                    Please do not email technical questions to\n                    Cufflinks contributors directly.</td>\n                </tr>\n              </tbody>\n            </table>\n          </ul>\n        </div>\n\t\t  \n\t\t\n          <a href=\"./downloads\">\n            <h2><u>Releases</u></h2>\n          </a>\n          <div class=\"box\">\n            <ul>\n              <table width=\"100%\">\n                <tbody>\n                  <tr>\n                    <td>version 2.2.0</td>\n                    <td align=\"right\">5/25/2014</td>\n                  </tr>\n                  <tr>\n                    <td><a href=\"./downloads/cufflinks-2.2.0.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks_source');\n                        \">&nbsp;&nbsp;&nbsp;Source code</a></td>\n                  </tr>\n                  <tr>\n                    <td><a\n                        href=\"./downloads/cufflinks-2.2.0.Linux_x86_64.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks');\n                        \">&nbsp;&nbsp;&nbsp;Linux x86_64 binary</a></td>\n                  </tr>\n                  <tr>\n                    <td><a\n                        href=\"./downloads/cufflinks-2.2.0.OSX_x86_64.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks');\n                        \">&nbsp;&nbsp;&nbsp;Mac OS X x86_64 binary</a></td>\n                  </tr>\n                </tbody>\n              </table>\n            </ul>\n          </div>          \n\t\t\n\t\t  <h2>Related Tools</h2>\n          <div class=\"box\">\n            <ul>\n                <li><a href=\"http://monocle-bio.sourceforge.net\">Monocle</a>:\n                  Single-cell RNA-Seq analysis</li>\n\t\t\t\t<li><a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a>:\n\t                Visualization of RNA-Seq differential analysis</li>\n              <li><a href=\"http://tophat.cbcb.umd.edu/\">TopHat</a>:\n                Alignment of short RNA-Seq reads</li>\n              <li><a href=\"http://bowtie.cbcb.umd.edu\">Bowtie</a>:\n                Ultrafast short read alignment</li>\n            </ul>\n          </div>\n\n\t\t  <h2>Publications</h2>\n          <div class=\"box\">\n            <ul>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Trapnell C, Williams BA, Pertea G, Mortazavi AM, Kwan\n                  G, van Baren MJ, Salzberg SL, Wold B, Pachter L.<b> <a\n                      href=\"http://dx.doi.org/10.1038/nbt.1621\">Transcript\n                      assembly and quantification by RNA-Seq reveals\n                      unannotated transcripts and isoform switching\n                      during cell differentiation</a></b> <br>\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\n                      Biotechnology</a></i> doi:10.1038/nbt.1621</p>\n                <br>\n              </li>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Roberts A, Trapnell C, Donaghey J, Rinn JL, Pachter\n                  L.<b> <a\n                      href=\"http://genomebiology.com/2011/12/3/R22/abstract\">Improving\n                      RNA-Seq expression estimates by correcting for\n                      fragment bias</a></b> <br>\n                  <i><a href=\"http://www.genomebiology.com\">Genome\n                      Biology</a></i> doi:10.1186/gb-2011-12-3-r22</p>\n                <br>\n              </li>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Roberts A, Pimentel H, Trapnell C, Pachter\n                  L.<b> <a\n                      href=\"http://bioinformatics.oxfordjournals.org/content/early/2011/06/21/bioinformatics.btr355.abstract\">\n                      Identification of novel transcripts in annotated genomes using RNA-Seq</a></b> <br>\n                  <i><a href=\"http://bioinformatics.oxfordjournals.org/\">Bioinformatics</a></i> doi:10.1093/bioinformatics/btr355</p>\n                <br>\n              </li>\n\t\t\t  <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Trapnell C, Hendrickson D,Sauvageau S, Goff L, Rinn JL, Pachter L<b> <a\n                      href=\"http://dx.doi.org/10.1038/nbt.2450\">Differential \n\t\t\t\t\t analysis of gene regulation at transcript resolution with RNA-seq\n\t\t\t\t\t</a></b> <br>\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\n                      Biotechnology</a></i> doi:10.1038/nbt.2450</p>\n                <br>\n              </li>\n            </ul>\n          </div>\n          <h2>Contributors</h2>\n          <div class=\"box\">\n            <ul>\n              <li><a href=\"http://www.cs.umd.edu/%7Ecole/\">Cole Trapnell</a></li>\n              <li><a href=\"http://www.cs.berkeley.edu/%7Eadarob/\">Adam\n                  Roberts</a></li>\n              <li>Geo Pertea</li>\n\t\t\t  <li>David Hendrickson<li>\n\t\t\t  <li>Loyal Goff</li>\n\t\t\t  <li>Martin Sauvageau</li>\n              <li>Brian Williams</li>\n              <li><a href=\"http://wormlab.caltech.edu/members/\">Ali\n                  Mortazavi</a></li>\n              <li>Gordon Kwan</li>\n              <li>Jeltje van Baren</li>\n\t\t\t  <li><a href=\"http://www.rinnlab.com\">John Rinn</a></li>\n              <li><a href=\"http://www.cbcb.umd.edu/%7Esalzberg/\">Steven\n                  Salzberg</a></li>\n              <li><a href=\"http://biology.caltech.edu/Members/Wold\">Barbara\n                  Wold</a></li>\n              <li><a href=\"http://www.math.berkeley.edu/%7Elpachter/\">Lior\n                  Pachter</a></li>\n            </ul>\n          </div>\n\t\t  <h2>Links</h2>\n\t\t  <div class=\"box\">\n\t\t    <ul>\n\t\t      <li><a href=\"http://bio.math.berkeley.edu/\">Berkeley LMCB</a></li>\n\t\t      <li><a href=\"http://www.cbcb.umd.edu/\">UMD CBCB</a></li>\n\t\t\t  <li><a href=\"http://woldlab.caltech.edu/\">Wold Lab</a></li>\n\t\t    </ul>\n\t\t  </div>          \n          \n    </div> <!-- End of \"rightside\" -->\n    <div id=\"leftside\">\n  \t  <table><tr><td cellpadding=7>\n  \t  <h1>Frequently Asked Questions</h1><br/>\n      <div id=\"toc\">\n  \t    <ul>\n \t    <li><a href=\"#fpkm\">What's the difference between FPKM and RPKM?</a></li>\n \t    <li><a href=\"#hssd\">Can Cufflinks handle strand-specific RNA-Seq data?</li>\n \t  \t<li><a href=\"#bact\">Can I use Cufflinks with RNA-Seq data from Bacteria?</a></li>\n \t  \t<li><a href=\"#count\">I want to find differentially expressed genes.  Can I use Cufflinks in conjunction with count-based differential expression packages?</a></li>\n\t\t<li><a href=\"#numfrags\">How can I find out how many fragments come from each transcript?</a></li>\n\t\t<li><a href=\"#cuffdiff\">How is Cuffdiff different from other differential expression tools?</a></li>\n \t  \t<li><a href=\"#snps\">Can I use Cufflinks to find SNPs or RNA editing sites?</a></li>\n  \t  \t<li><a href=\"#fusi\">Does Cufflinks discover gene fusions or trans-spliced transcripts?</a></li>\n \t  \t<li><a href=\"#hbam\">Do Cufflinks and Cuffdiff support both BAM and SAM?</a></li>\n\t   \t<li><a href=\"#notest\">What does \"NOTEST\" mean in Cuffdiff's output?</a></li>\n\t    <li><a href=\"#lowdata\">What does \"LOWDATA\" mean in Cuffdiff's output?</a></li>\n\t    <li><a href=\"#fail\">What does \"FAIL\" mean in Cuffdiff's output?</a></li>\n     \t<li><a href=\"#exon\">Can Cufflinks/Cuffdiff give me FPKM for each exon or splicing event?</a></li>\n\t \t<!-- <li><a href=\"#reps\">How many replicates do I need?  Do I need technical replicates as well as biological ones?</a></li> -->\n\t\t<li><a href=\"#gene\">How do I find differentially expressed genes with Cuffdiff?</a></li>\n\t\t<li><a href=\"#pval\">How does Cufflinks calculate its p-values?</a></li>\n\t\t<li><a href=\"#gtfs\">I'm looking for a GTF file with annotated transcripts.  Do you provide annotation files?</a></li>\n\t\t<li><a href=\"#time\">Can I use Cuffdiff on time-series data?</a></li>\n\t\t<li><a href=\"#visi\">How can I visualize by Cufflinks and Cuffdiff results?</a></li>\n \t    <li><a href=\"#inst\">I'm having trouble installing Cufflinks on my system.  Can you help me?</a></li>\n\n  \t    </ul><br/>\n  \t  </div>\n  \t  <h2 id=\"fpkm\">What's the difference between FPKM and RPKM?</h2><br/><p> \n\t  They're almost the same thing.  RPKM stands for Reads Per Kilobase of transcript per Million mapped reads.  FPKM stands for Fragments Per Kilobase of transcript per Million mapped reads.  In RNA-Seq, the relative expression of a transcript is proportional to the number of cDNA fragments that originate from it. Paired-end RNA-Seq experiments produce two reads per fragment, but that doesn't necessarily mean that both reads will be mappable.  For example, the second read is of poor quality. If we were to count reads rather than fragments, we might double-count some fragments but not others, leading to a skewed expression value. Thus, FPKM is calculated by counting fragments, not reads.   \n  \t  </p><br/>\n\n\t  <h2 id=\"hssd\">Can Cufflinks handle strand-specific RNA-Seq data?</h2><br/><p> \n\t  Yes.  If you mapped your reads with TopHat using the strand-specific mode or manually added\n  \t  XS tags, Cufflinks will automatically treat your data as strand-specific.  If this is not the case,\n  \t  you should use the <tt>--library-type</tt> option along with the type of strand-specific protocol that\n  \t  was used to generate your data.  More information can be found <a href=manual.html#library>here</a>.\n  \t  </p><br/>\n\n\t  <h2 id=\"bact\">Can I use Cufflinks with RNA-Seq data from Bacteria?</h2><br/><p> \n\t  Sure, with one or two caveats.  We don't recommend assembling bacterial transcripts using Cufflinks at first. If you're working on a new bacterial genome, consider using a computational gene finding application such as <a href=\"http://www.cbcb.umd.edu/software/glimmer/\">Glimmer</a>.  These tools are very mature and work well.  With an annotation, you can use Cufflinks and Cuffdiff to profile expression and look for differences.  Also, note that Cufflinks doesn't handle circular genomes in any special way, so make sure your genome and annotation are suitably linearized.</p><br/>\n\n\t  <h2 id=\"count\">I want to find differentially expressed genes.  Can I use Cufflinks in conjunction with count-based differential expression packages?</h2><br/><p>\n\t  It's possible, but we strongly advise against this.  Current count-based differential expression tools are poorly suited to differential expression analysis in genomes with alternatively spliced genes.  The main reason for this is that when a gene has multiple isoforms, a change in the total number of reads or fragments from that gene doesn't always correspond to a change in expression for that gene. Conversely, a gene's expression may change, but the total number of fragments generated by its isoforms may be very similar. In order to detect changes accurately, it's necessary to estimate how many fragments came from each individual splice variant in each sample.  Current count-based tools don't do this (to our knowledge - please send us email if you know of one!).  Even if they did, fragments that come from parts of genes that are shared by more than one splice variant can't generally assigned to a single isoform, so the fragment counts for each isoform are only estimates, and there is some uncertainty in the counts.  Isoforms that are very similar will have a great deal of uncertainty surrounding their fragment counts.  This uncertainty needs to be accounted for when testing for differential expression. So while you could use Cufflinks to estimate isoform-level counts, you'd be throwing away Cufflinks' uncertainty, and thus have more confidence in the differences you see than you really should.  This will probably lead to many false positives in your analysis.  Furthermore, we do not normalize simply by the length to calculate FPKM but an effective length, as explained in our publications.  Calculting counts from FPKM by multiplying by the length will give incorrect results.  We strongly encourage you to consider using Cuffdiff to find differentially expressed genes and transcripts.\n\n\t  </p><br/>\n\t\n\t  <h2 id=\"numfrags\">How can I find out how many fragments come from each transcript?</h2><br/><p>\n\t  In response to user-demand and support the development of analysis methods downstream of abundance estimation, we have added this functionality in Cuffdiff 2.0.  See the <a href=\"manual.html#count_tracking_format\">count tracking</a> table description in the manual page.  Support for count tracking will be coming to Cufflinks soon. However, people who have asked for this almost always want to use Cufflinks in conjunction with count-based differential expression packages, which is not a good idea.  \n\t  </p><br/>\n\t\n\t  <h2 id=\"cuffdiff\">How is Cuffdiff different from other differential expression tools?</h2><br/><p>\n\t  To our knowledge, most other differential expression packages work by counting up the number of fragments that originate from each gene in each sample, looking for differences in the count for each gene across conditions, and testing the observed differences for statistical significance. This approach works well when genes have a single isoform and occur only once in the genome (i.e. aren't members of \"gene families\").  However, when dealing with genes with more than one isoform, it's generally not possible to tell with certainty which isoform generated each fragment.  This greatly complicates the problem of looking for differentially expressed genes.  \n\t  </p>\n\t\t<p>\n\t\tMost differential expression packages count reads at a gene level and look for differences in these counts directly.  However, this approach can be very inaccurate for genes that have multiple isoforms, because a change in relative abundance of the isoforms can change overall gene abundance <emph>without generating a large change in the number of reads from that gene</emph>.  Conversely, a change in overall gene counts does not necessarily imply a similar fold-change in gene expression.  For example, suppose a gene has two isoforms, one which is twice as long as the other.  At equal abundance, the longer one will produce twice as many reads.  Consider two RNA-Seq samples, where only the shorter isoform is present in the first sample, and only the longer isoform is present in the second sample.  If the abundance of each isoform is the same in the two conditions, the second sample will have twice as many reads from the gene!  Thus, simply looking for differences in the overall number of reads from a gene may lead to the incorrect conclusion that it is differentially expessed.\n\t\t<p>\n\t\tCuffdiff looks for differentially expressed genes by estimating how many fragments came from each isoform and then converting the counts into isoform expression levels.  To find differentially expressed genes, Cuffdiff calculates expression levels in each condition for each gene by adding up the expression levels for each gene's splice isoforms.  Cuffdiff tests for differences in each gene's expression level across conditions.  See <a href=\"howitworks.html#hdif\">here</a> for more details about how this works.\n\t\t</p>\n\t  <br/>\n\t\n\t  <h2 id=\"snps\">Can I use Cufflinks to find SNPs or RNA editing sites?</h2><br/><p>\n\t  Not at the moment, because Cufflinks doesn't do any base calling of its own.  We recommend that you check out the <a href=\"http://samtools.sourceforge.net\">samtools</a> for this purpose.\n\t  </p><br/>\n\t\n\t  <h2 id=\"fusi\">Does Cufflinks discover or quantify gene fusions or trans-spliced transcripts?</h2><br/><p>\n\t  Not yet, but we will likely support this in a future release (we have no idea how far away that release will be).\n\t  </p><br/>\n\t\n\t  <h2 id=\"hbam\">Do Cufflinks and Cuffdiff support both BAM and SAM?</h2><br/><p> \n\t  Yes. If a SAM is supplied, a message will be output that the file is not a valid BAM file.\n\t  However, Cufflinks will recognize this and treat the file as a SAM.  When using a SAM file, you should\n\t  include a proper header or ensure that the reads are lexicographically by chromosome and then numerically\n\t  by left position.  You can accomplish this sorting with the command <tt>sort -k3,3 -k4,4n in.sam > out.sam</tt>.\n\t  </p><br/>\n\t\t  \n\t  <h2 id=\"cdif\">How is Cuffdiff different from other differential expression tools?</h2><br/><p> \t\n\t  Cuffdiff is able to estimate p-values for differential expression of\n\t  individual transcripts. Like other tools, it uses a negative binomial\n\t  model estimated from data to obtain variance estimates from which\n\t  p-values are computed. More details will be available in a forthcoming\n\t  publication.\n\t  </p><br/>\n\t\t\n\t  <h2 id=\"notest\">What does \"NOTEST\" mean in Cuffdiff's output?</h2><br/><p>\n\t  This status code is used by Cuffdiff to indicate that neither of the conditions contained enough reads in a locus to support a reliable calculation of expression level.  Basically, Cuffdiff wasn't confident that it had enough data in that gene.  You can control Cuffdiff's behavior in this regard by lowering or raising the <tt>-c</tt> option. \n\t  </p><br/>\n\t\n\t  <h2 id=\"lowdata\">What does \"LOWDATA\" mean in Cuffdiff's output?</h2><br/><p>\n\t  This status code is used by Cuffdiff to indicate that in both conditions, the gene being tested was either too complex or too shallowly sequenced to support a reliable calculation of abundance.  Cuffdiff can often (though not always) tell via some simple linear algebra that it doesn't have enough reads to pick apart expression levels for all of a gene's isoforms, and without these, it can't calculate expression for the gene.  When this happens in both conditions, Cuffdiff marks any observed difference in expression as not statistically signficant and sets the status code as <tt>LOWDATA</tt>.  You should treat any such observed changes as highly unreliable.    \n\t  </p><br/>\n\t\n\t  <h2 id=\"fail\">What does \"FAIL\" mean in Cuffdiff's output?</h2><br/><p>\n\t  This status code is used by Cuffdiff to indicate that in one or both conditions, Cuffdiff encountered a numerical exception while calculating expression levels in the locus.  This can happen because of rounding errors and other \"facts of life\" when doing math on computers.  Typically, this occurs in very complex genes with relatively low expression levels. When this happens in one or both conditions being tested, Cuffdiff marks any observed difference in expression as not statistically signficant and sets the status code as <tt>FAIL</tt>.  You should treat any such observed changes as highly unreliable.    \n\t  </p><br/>\n\t\n\t <h2 id=\"exon\">Can Cufflinks/Cuffdiff give me FPKM for each exon or splicing event?</h2><br/><p>\n\t For the foreseeable future, no.    \n\t  </p><br/>\n\t\n\t  <!-- <h2 id=\"hssd\">How many replicates do I need?  Do I need technical replicates as well as biological ones?</h2><br/><p>\n\t  Good question.  The short answer is: don't bother with technical replicates (e.g. multiples libraries made from the same RNA), but get as many biological replicates as you can afford.  Early papers on the technical reproducibility of RNA-Seq have suggested that lane effects are minimal and that relative expression levels between technical replicates are extremely consistent over a very large dynamic range.  However, RNA-Seq won't do anything to remove biological variability, and the degree of variability varies (no pun intended) widely and depends on the experiment.  Just how many replicates are needed is an almost entirely open question at this point.  A related question is: considering that power to detect differences between conditions depends both on number of replicates and overall sequencing depth in each replicate, should we prefer a lot of replicates sequenced at low depth or fewer replicates sequenced very deeply?  We don't have a good answer for this yet either.    \n\t  </p><br/> -->\n\t\n\t  <h2 id=\"gene\">How does cufflinks calculate its p values?</h2><br/><p>\n\t  <p>Run Cuffdiff (see <a href=\"tutorial.html#differential\">here</a> for an example) and look at the <tt>gene_exp.diff</tt> output file.</a>\n\t  </p><br/>\n\t\n\t  <h2 id=\"pval\">How do I find differentially expressed genes with Cuffdiff?</h2><br/><p>\n\t  <p>See <a href=\"howitworks.html#hdif\">here</a>\n\t  </p><br/>\n\t  \n\t\n\t  <h2 id=\"gtfs\">I'm looking for a GTF file with annotated transcripts.  Do you provide annotation files?</h2><br/><p>\n\t  <p>No.  Curating these annotation files would be way too much work for us, and organizations like Ensembl and UCSC already do a great job.  We suggest you check out either of these for a high quality annotation GTF for your organism.\n\t  </p><br/>\n\t\n\t  <h2 id=\"h99p\">I'm trying to assemble a sample.  Cufflinks is almost done, but it seems to be hanging at \"99% complete\".  What's going on?</h2><br/><p> \n\t  Cufflinks spawns threads for each locus to assemble and quantitate the \"bundle\" of reads in that locus.  Some loci may have more reads and more complicated alternative\n\t  splicing than others, which requires more CPU cycles.  These bundles can continue processing long after all others have completed, leading\n\t  to this behavior.  You may be able to decrease the number of such bundles by masking out ribosomal and mitochondrial RNA using the <tt>-M/--mask-file</tt> option\n\t  described in the <a href=\"manual.html\">Manual</a>.\n\t  </p><br/>\n\t  \t\n\t  <h2 id=\"time\">Can I use Cuffdiff on time-series data?</h2><br/><p>\n\t  <p>Yes.  Check out the <tt>-T</tt> option in Cuffdiff.\n\t  </p><br/>\n\t\n      <h2 id=\"visi\">How can I visualize by Cufflinks and Cuffdiff results?</h2><br/><p>\n\t  <p>We've built <a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a> for this purpose, which is based on the elegant, powerful <a href=\"http://had.co.nz/ggplot2/\">ggplot2</a> library for this.  It's written by Hadley Wickham in R and makes plotting very simple.\n\t  </p><br/>\n\t\n\t  <h2 id=\"inst\">I'm having trouble installing Cufflinks on my system.  Can you help me?</h2><br/><p>\n\t  <p>  While binaries are provided for easy installation on Mac and Linux, Cufflinks can also be installed \n\t  from source on numerous systems. If you are using a\n\t  Mac we recommend <a href=http://www.macports.org/>MacPorts</a>. For other systems, we encourage you to\n\t  visit <a href=http://www.seqanswers.org>SeqAnswers</a> for discussions about installation issues on\n\t  various platforms.\n\t  You can try sending email to our <a href=\"tophat.cufflinks@gmail.com\">support address</a>, but please be aware that we get a great deal of email, and requests for installation help are generally the lowest priority for us.\n\t  </p><br/>\n\n\t\n\t</div>\n  </div>\n  <div id=\"footer\">\n  \t<table width=\"100%\" cellspacing=15><tr><td>\n    This research was supported in part by NIH grants R01-LM06845 and R01-GM083873, NSF grant CCF-0347992 and the Miller Institute for Basic\n\t\tResearch in Science at UC Berkeley.\n    </td><td align=right>\n    Administrator: <a href=\"mailto:cole@cs.umd.edu\">Cole Trapnell</a>. Design by <a href=\"http://www.free-css-templates.com\" title=\"Design by David Herreman\">David Herreman</a>\n    </td></tr></table>\n  </div>\n</div>\n\n<!-- Google analytics code -->\n<script type=\"text/javascript\">\nvar gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\ndocument.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n</script>\n<script type=\"text/javascript\">\ntry {\nvar pageTracker = _gat._getTracker(\"UA-6101038-2\");\npageTracker._trackPageview();\n} catch(err) {}</script>\n<!-- End Google analytics code -->\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/gff.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>\n    \n<title>Cufflinks RNA-Seq analysis tools - GFF/GTF Format Guide</title>  \n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<meta name=\"description\" content=\"Overview of the GTF and GFF formats needed by Cufflinks\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\" media=\"screen\">\n  </head>\n  <body>\n    \n<div id=\"wrap\">\n      <div id=\"top\">\n        <div class=\"lefts\">\n          <table width=\"100%\" cellpadding=\"2\">\n            <tbody>\n              <tr>\n                <td> <a href=\"./index.html\">\n                    <h1>Cufflinks</h1>\n                  </a>\n                  <h2>Transcript assembly, differential expression, and\n                    differential regulation for RNA-Seq</h2>\n                </td>\n                <td align=\"right\" valign=\"middle\"> \n                  <a href=\"http://bio.math.berkeley.edu/\">\n                  <img style=\"vertical-align:middle;padding-top:4px\" \n                    src=\"images/UCBerkeley-seal.scaled.gif\" border=\"0\">\n                  </a>&nbsp;\n                  <a href=\"http://genomics.jhu.edu/\">\n                  <img style=\"vertical-align:middle;padding-top:4px\"\n                      src=\"images/JHU-seal.gif\" border=\"0\">\n                  </a>&nbsp;\n                  \n                  <a href=\"http://www.cbcb.umd.edu/\"><img style=\"vertical-align:middle;padding-top:4px\" src=\"images/cbcb_logo.gif\" border=\"0\"></a>&nbsp;&nbsp;\n                </td>\n              </tr>\n            </tbody>\n          </table>\n        </div>\n      </div>\n      <div id=\"main\">\n        <div id=\"rightside\">\n          <h2>Site Map</h2>\n          <div class=\"box\">\n            <ul>\n              <li><a href=\"index.html\">Home</a></li>\n              <li><a href=\"tutorial.html\">Getting started</a></li>\n              <li><a href=\"manual.html\">Manual</a></li>\n              <li><a href=\"howitworks.html\">How Cufflinks works</a></li>\n\t\t\t  <li><a href=\"igenomes.html\">Index and annotation downloads</a></li>\n              <li><a href=\"faq.html\">FAQ</a></li>\n\t\t\t  <li><a href=\"http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html\">Protocol</a></li>\n\t\t\t  <li><a href=\"report.html\">Benchmarking</a></li>\n            </ul>\n          </div>\n          <h2><u>News and updates</u></h2>\n          <div class=\"box\">\n            <ul>\n              <table width=\"100%\">\n                <tbody>\n                  <tr>\n                    <td>New releases and related tools will be announced\n                      through the <a\n                        href=\"https://lists.sourceforge.net/lists/listinfo/bowtie-bio-announce\"><b>mailing\n                          list</b></a></td>\n                  </tr>\n                </tbody>\n              </table>\n            </ul>\n          </div>\n          <h2><u>Getting Help</u></h2>\n          <div class=\"box\">\n            <ul>\n              <table width=\"100%\">\n                <tbody>\n                  <tr>\n                    <td>Questions about Cufflinks and Cuffdiff should be posted on our <a href=\"https://groups.google.com/forum/#!forum/tuxedo-tools-users\"><b>Google Group</b></a>. Please use <a\n                        href=\"mailto:tophat.cufflinks@gmail.com\">tophat.cufflinks@gmail.com</a> for private communications only.\n                      Please do not email technical questions to\n                      Cufflinks contributors directly.</td>\n                  </tr>\n                </tbody>\n              </table>\n            </ul>\n          </div>\n          \n\n\n          <a href=\"./downloads\">\n            <h2><u>Releases</u></h2>\n          </a>\n          <div class=\"box\">\n            <ul>\n              <table width=\"100%\">\n                <tbody>\n                  <tr>\n                    <td>version 2.2.0</td>\n                    <td align=\"right\">5/25/2014</td>\n                  </tr>\n                  <tr>\n                    <td><a href=\"./downloads/cufflinks-2.2.0.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks_source');\n                        \">&nbsp;&nbsp;&nbsp;Source code</a></td>\n                  </tr>\n                  <tr>\n                    <td><a\n                        href=\"./downloads/cufflinks-2.2.0.Linux_x86_64.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks');\n                        \">&nbsp;&nbsp;&nbsp;Linux x86_64 binary</a></td>\n                  </tr>\n                  <tr>\n                    <td><a\n                        href=\"./downloads/cufflinks-2.2.0.OSX_x86_64.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks');\n                        \">&nbsp;&nbsp;&nbsp;Mac OS X x86_64 binary</a></td>\n                  </tr>\n                </tbody>\n              </table>\n            </ul>\n          </div>          \n\n\t\t  <h2>Related Tools</h2>\n          <div class=\"box\">\n            <ul>\n                <li><a href=\"http://monocle-bio.sourceforge.net\">Monocle</a>:\n                  Single-cell RNA-Seq analysis</li>\n\t\t\t\t<li><a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a>:\n\t                Visualization of RNA-Seq differential analysis</li>\n              <li><a href=\"http://tophat.cbcb.umd.edu/\">TopHat</a>:\n                Alignment of short RNA-Seq reads</li>\n              <li><a href=\"http://bowtie.cbcb.umd.edu\">Bowtie</a>:\n                Ultrafast short read alignment</li>\n            </ul>\n          </div>\n\n\n\n\t\t<h2>Publications</h2>\n          <div class=\"box\">\n            <ul>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Trapnell C, Williams BA, Pertea G, Mortazavi AM, Kwan\n                  G, van Baren MJ, Salzberg SL, Wold B, Pachter L.<b> <a\n                      href=\"http://dx.doi.org/10.1038/nbt.1621\">Transcript\n                      assembly and quantification by RNA-Seq reveals\n                      unannotated transcripts and isoform switching\n                      during cell differentiation</a></b> <br>\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\n                      Biotechnology</a></i> doi:10.1038/nbt.1621</p>\n                <br>\n              </li>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Roberts A, Trapnell C, Donaghey J, Rinn JL, Pachter\n                  L.<b> <a\n                      href=\"http://genomebiology.com/2011/12/3/R22/abstract\">Improving\n                      RNA-Seq expression estimates by correcting for\n                      fragment bias</a></b> <br>\n                  <i><a href=\"http://www.genomebiology.com\">Genome\n                      Biology</a></i> doi:10.1186/gb-2011-12-3-r22</p>\n                <br>\n              </li>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Roberts A, Pimentel H, Trapnell C, Pachter\n                  L.<b> <a\n                      href=\"http://bioinformatics.oxfordjournals.org/content/early/2011/06/21/bioinformatics.btr355.abstract\">\n                      Identification of novel transcripts in annotated genomes using RNA-Seq</a></b> <br>\n                  <i><a href=\"http://bioinformatics.oxfordjournals.org/\">Bioinformatics</a></i> doi:10.1093/bioinformatics/btr355</p>\n                <br>\n              </li>\n\t\t\t  <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Trapnell C, Hendrickson D,Sauvageau S, Goff L, Rinn JL, Pachter L<b> <a\n                      href=\"http://dx.doi.org/10.1038/nbt.2450\">Differential \n\t\t\t\t\t analysis of gene regulation at transcript resolution with RNA-seq\n\t\t\t\t\t</a></b> <br>\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\n                      Biotechnology</a></i> doi:10.1038/nbt.2450</p>\n                <br>\n              </li>\n            </ul>\n          </div>\n          <h2>Contributors</h2>\n          <div class=\"box\">\n            <ul>\n              <li><a href=\"http://www.cs.umd.edu/%7Ecole/\">Cole Trapnell</a></li>\n              <li><a href=\"http://www.cs.berkeley.edu/%7Eadarob/\">Adam\n                  Roberts</a></li>\n              <li>Geo Pertea</li>\n\t\t\t  <li>David Hendrickson<li>\n\t\t\t  <li>Loyal Goff</li>\n\t\t\t  <li>Martin Sauvageau</li>\n              <li>Brian Williams</li>\n              <li><a href=\"http://wormlab.caltech.edu/members/\">Ali\n                  Mortazavi</a></li>\n              <li>Gordon Kwan</li>\n              <li>Jeltje van Baren</li>\n\t\t\t  <li><a href=\"http://www.rinnlab.com\">John Rinn</a></li>\n              <li><a href=\"http://www.cbcb.umd.edu/%7Esalzberg/\">Steven\n                  Salzberg</a></li>\n              <li><a href=\"http://biology.caltech.edu/Members/Wold\">Barbara\n                  Wold</a></li>\n              <li><a href=\"http://www.math.berkeley.edu/%7Elpachter/\">Lior\n                  Pachter</a></li>\n            </ul>\n          </div>\n\t\t  <h2>Links</h2>\n\t\t  <div class=\"box\">\n\t\t    <ul>\n\t\t      <li><a href=\"http://bio.math.berkeley.edu/\">Berkeley LMCB</a></li>\n\t\t      <li><a href=\"http://www.cbcb.umd.edu/\">UMD CBCB</a></li>\n\t\t\t  <li><a href=\"http://woldlab.caltech.edu/\">Wold Lab</a></li>\n\t\t    </ul>\n\t\t  </div>\n\t\t</div>\n        <!-- End of \"rightside\" -->\n        <div id=\"leftside\">\n          <table>\n            <tbody>\n              <tr>\n                <td cellpadding=\"7\">\n                  <h1>GFF files</h1>\n                  <br>\n                  Some of the Cufflinks modules take as input a file (or\n                  more) containing known gene annotations or other\n                  transcript data in GFF format (General Feature\n                  Format). GFF has many versions, but the two most\n                  popular that are supported by Cufflinks (and other\n                  programs in the Tuxedo suite, like Tophat) are GTF2\n                  (Gene Transfer Format, described <a href=\"http://mblab.wustl.edu/GTF2.html\">here</a>)\n                  and GFF3 (defined <a href=\"http://www.sequenceontology.org/gff3.shtml\">here</a>).\n\n                  Here are a few notes about the way these formats are\n                  interpreted by the Cufflinks programs.<br>\n                  <br>\n                  <h2 id=\"inst\">GTF2</h2>\n                  \n                  <p>As seen in the <a href=\"http://mblab.wustl.edu/GTF2.html\">GTF2\n                    specification</a>, the <b>transcript_id</b> attribute is also required by\n                  our GFF parser, and a <b>gene_id</b> attribute, though not strictly\n                  required in our programs, is very useful for grouping alternative transcripts under a gene/locus identifier.\n                  An optional <b>gene_name</b>\n                  attribute, if found, will be taken and shown as&nbsp;\n                  a symbolic gene name or short-form abbreviation (e.g.\n                  gene symbols from HGNC or Entrez Gene). Some annotation\n                  sources (e.g. Ensembl) place a \"human readable\" gene\n                  name/symbol in the <b>gene_name</b>\n                  attribute, like a HUGO symbol (while <b>gene_id</b> might be\n                  just an automatically generated numeric identifier for the\n                  gene). <br>\n                  <br>\n                  TopHat and Cufflinks generally expect <i>exon</i> features to\n                  define a transcript structure, with optional <i>CDS</i> features to\n                  specify the coding segments. Our GFF reader will\n                  ignore redundant features like start_codon, stop_codon\n                  when whole <i>CDS</i> features were provided, or <i>*UTR</i> features when whole <i>exon</i> features\n                  were also given. However, it is still possible to\n                  provide only <i>CDS</i> and <i>*UTR</i>\n                  features and our GFF parser will reassemble the exonic\n                  structure accordingly.<br>\n                  </p><p>Example of a GTF2 transcript record with minimal attributes:</p>\n                  <div style=\"margin:2px;\">\n                    <textarea rows=\"8\" cols=\"138\" readonly=\"readonly\" wrap=\"off\" class=\"tcode\">20\tprotein_coding\texon\t9873504\t9874841\t.\t+\t.\tgene_id \"ENSBTAG00000020601\"; transcript_id \"ENSBTAT00000027448\"; gene_name \"ZNF366\";\n20\tprotein_coding\tCDS\t9873504\t9874841\t.\t+\t0\tgene_id \"ENSBTAG00000020601\"; transcript_id \"ENSBTAT00000027448\"; gene_name \"ZNF366\";\n20\tprotein_coding\texon\t9877488\t9877679\t.\t+\t.\tgene_id \"ENSBTAG00000020601\"; transcript_id \"ENSBTAT00000027448\"; gene_name \"ZNF366\";\n20\tprotein_coding\tCDS\t9877488\t9877679\t.\t+\t0\tgene_id \"ENSBTAG00000020601\"; transcript_id \"ENSBTAT00000027448\"; gene_name \"ZNF366\";\n20\tprotein_coding\texon\t9888412\t9888586\t.\t+\t.\tgene_id \"ENSBTAG00000020601\"; transcript_id \"ENSBTAT00000027448\"; gene_name \"ZNF366\";\n20\tprotein_coding\tCDS\t9888412\t9888586\t.\t+\t0\tgene_id \"ENSBTAG00000020601\"; transcript_id \"ENSBTAT00000027448\"; gene_name \"ZNF366\";\n20\tprotein_coding\texon\t9891475\t9891998\t.\t+\t.\tgene_id \"ENSBTAG00000020601\"; transcript_id \"ENSBTAT00000027448\"; gene_name \"ZNF366\";\n20\tprotein_coding\tCDS\t9891475\t9891995\t.\t+\t2\tgene_id \"ENSBTAG00000020601\"; transcript_id \"ENSBTAT00000027448\"; gene_name \"ZNF366\";</textarea>\n                    \n                  </div>\n                  <br>\n                  <h2 id=\"inst\">GFF3</h2>\n                  As defined by the <a href=\"http://www.sequenceontology.org/gff3.shtml\">GFF3 specification</a>, \n                  the parent features (usually transcripts, i.e. \"mRNA\" features) are required to\n                  have an <b>ID</b> attribute, but here again an optional <b>gene_name</b>\n                  attribute can be used to specify a common gene name abbreviation. If gene_name is not given, it can be\n                  also inferred from the Name or ID attributes of the parent <i>gene</i> feature of the current parent mRNA feature (if\n                  given in the input file). Exon or CDS features arerequired to have a <b>Parent</b>\n                  attribute whose value must match the value of the <b>ID</b> attribute of a parent transcript feature (usually a \"mRNA\" feature).<br>\n                  <br>\n                  <h2 id=\"inst\">Feature restrictions</h2>\n                  For various reasons we currently assume the following limits (maximum\n                  values) for the genomic length (span) of gene and transcript features:<br>\n                  <ul>\n                    <li>genes and transcripts cannot span more than 7 Megabases on the genomic sequence</li>\n                    <li>exons cannot be longer than 30 Kilobases</li>\n                    <li>introns cannot be larger than 6 Megabases<br>\n                    </li>\n                  </ul>\n                  Also, transcript IDs are expected to be unique per GFF input file (though we relaxed this\n                  restriction by limiting it to a chromosome/contig scope).<br>\n                  <br>\n                  Due to these requirements, Cufflinks programs may fail to load the user provided GFF file, and an error\n                  message should specify the offending GFF record. The user is expected to remove or correct such GFF records\n                  in order to continue the analysis.\n                  <p>Example of a GFF3 transcript record with minimal attributes:</p>\n                  <div style=\"margin:2px;\">\n                    <textarea rows=\"9\" cols=\"79\" readonly=\"readonly\" wrap=\"off\" class=\"tcode\">ctg123\texample\tmRNA\t1300\t9950\t.\t+\t.\tID=t_012143;gene_name=EDEN\nctg123\texample\texon\t1300\t1500\t.\t+\t.\tParent=t_012143\nctg123\texample\texon\t3000\t3902\t.\t+\t.\tParent=t_012143\nctg123\texample\texon\t5000\t5500\t.\t+\t.\tParent=t_012143\nctg123\texample\texon\t7000\t9000\t.\t+\t.\tParent=t_012143\nctg123\texample\texon\t9400\t9950\t.\t+\t.\tParent=t_012143\nctg123\texample\tCDS\t3301\t3902\t.\t+\t0\tParent=t_012143\nctg123\texample\tCDS\t5000\t5500\t.\t+\t1\tParent=t_012143\nctg123\texample\tCDS\t7000\t7600\t.\t+\t1\tParent=t_012143</textarea>\n                  </div>\n                  <br>\n\n                  <h2 id=\"inst\">The gffread utility</h2>\n                  \n                  A program called <b>gffread</b>\n                  is included with the Cufflinks package and it can be used to verify or perform various operations on GFF\n                  files (use <span class=\"tcode\">gffread -h</span> to see the various usage options). Because the program \n                  shares the same  GFF parser code with Cufflinks and other programs in the Tuxedo suite, it could be used to verify that a GFF file \n                  from a certain annotation source is correctly \"understood\" by these programs. Thus the gffread utility can be used \n                  to simply read the transcripts from the file and print these transcripts back, in either GFF3 (default) or GTF2 format \n                  (-T option), discarding any extra attributes and keeping only the essential ones, so the user can quickly verify if \n                  the transcripts in that file are properly parsed by \nthe GFF reader code.  The command line for such a quick cleanup and \n                  visual inspection of a given GFF file could be:<br>\n                  <br>\n                  <pre><big>gffread -E annotation.gff -o- | more</big></pre>\n                  <br>\n                  This will show the minimalist GFF3 re-formatting of \nthe transcript records given in the input file (annotation.gff in this \nexample).\n                  The -E option directs gffread to \"expose\" (display \nwarnings about) any potential issues encountered while parsing the given\n GFF file.<br>\n                                    \n                  In order to see the GTF2 version of the same \ntranscripts the -T option should be added:<br>\n                  <br>\n                  <pre><big>gffread -E annotation.gff -T -o- | more</big></pre>\n                  <br>\n                  \n                  From these examples it can be seen that gffread can also be used to convert a file between GTF2 and GFF3 formats.\n<br>\n                  \n                  <strong><br>\nExtracting transcript sequences</strong><br>\n                  \n                  The gffread utility can be used to generate a FASTA \nfile with the DNA sequences for all transcripts in a GFF file. \n                  For this operation a fasta file with the genomic \nsequences have to be provided as well.\n                  For example, one might want to extract the sequence of\n all transfrags assembled from a Cufflinks assembly session.\n                  This can be accomplished with a command line like \nthis:<br>\n                  <br>\n                  <pre><big>gffread -w transcripts.fa -g /path/to/genome.fa transcripts.gtf</big></pre>\n                  <br>\n                  The file genome.fa in this example would be a multi \nfasta file with the genomic sequences of the \n                  target genome.  This also requires that every contig \nor chromosome name found in the 1st column of the input GFF file \n                  (transcript.gtf in this example) must have a \ncorresponding sequence entry in chromosomes.fa. This should be the case \nin our\n                  example if genome.fa is the file corresponding to the \nsame genome (index) that was used for mapping the reads with Tophat.\n                  \n                  Note that the retrieval of the transcript sequences \nthis way is going to be quicker if a fasta index file \n                  (genome.fa.fai in this example) is found in the same \ndirectory with the genomic fasta file. Such an index file can be created\n \n                  with samtools prior to running gffread, like this:\n                  <br><br>\n                  <pre><big>samtools faidx genome.fa</big></pre>\n                  <br>\n                  Then in subsequent runs using the -g option gffread \nwill find the fasta index and use it to speed up the extraction of the \ntranscript sequences.\n\n                  <br>\n<br>\n                  <div id=\"footer\">\n                    <table width=\"100%\" cellspacing=\"15\">\n                      <tbody>\n                        <tr>\n                          <td> This research was supported in part by\n                            NIH grants R01-LM06845 and R01-GM083873, NSF\n                            grant CCF-0347992 and the Miller Institute\n                            for Basic Research in Science at UC\n                            Berkeley. </td>\n                          <td align=\"right\"> Administrator: <a href=\"mailto:cole@cs.umd.edu\">Cole\n                              Trapnell</a>. Design by <a href=\"http://www.free-css-templates.com\" title=\"Design by David Herreman\">David\n                              Herreman</a> </td>\n                        </tr>\n                      </tbody>\n                    </table>\n                  </div>\n                  <!-- Google analytics code -->\n                  <script type=\"text/javascript\">\nvar gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\ndocument.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n</script>\n                  <script type=\"text/javascript\">\ntry {\nvar pageTracker = _gat._getTracker(\"UA-6101038-2\");\npageTracker._trackPageview();\n} catch(err) {}</script>\n                  <!-- End google analytics code --> </td>\n              </tr>\n            </tbody>\n          </table>\n        </div>\n      </div>\n    </div>\n\n\n</body></html>\n"
  },
  {
    "path": "doc/html/howitworks.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<title>Cufflinks RNA-Seq analysis tools - Background</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n<link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\" media=\"screen\" />\n</head>\n<body>\n<div id=\"wrap\">\n  <div id=\"top\">\n    <div class=\"lefts\">\n    <table width=\"100%\" cellpadding=\"2\">\n      <tr><td>\n        <a href=\"./index.html\"><h1>Cufflinks</h1></a>\n        <h2>Transcript assembly, differential expression, and differential regulation for RNA-Seq</h2>\n      </td><td align=\"right\" valign=\"middle\">\n        <a href=\"http://bio.math.berkeley.edu/\">\n        <img style=\"vertical-align:middle;padding-top:4px\" \n          border=0 src=\"images/UCBerkeley-seal.scaled.gif\">\n        </a>&nbsp;\n        <a href=\"http://genomics.jhu.edu/\">\n        <img style=\"vertical-align:middle;padding-top:4px\"\n          src=\"images/JHU-seal.gif\" border=\"0\">\n        </a>&nbsp;\n        <a href=\"http://www.cbcb.umd.edu/\"><img style=\"vertical-align:middle;padding-top:4px\" border=0 src=\"images/cbcb_logo.gif\"></a>&nbsp;&nbsp;\n      </td></tr>\n    </table>\n    </div>\n  </div>\n  <div id=\"subheader\">\n  <table width=\"100%\"><tr>\n  <td>\n  \t\t<strong>Please Note</strong> If you have questions \n\t\t  about how to use Cufflinks or would like more information about \n\t\t  the software, please email <a href=\"mailto:tophat.cufflinks@gmail.com\"><b>tophat.cufflinks@gmail.com</b></a>, \n\t\t  though we ask you to have a look at the <a href=\"http://dx.doi.org/10.1038/nbt.1621\">paper</a> \n\t\t  and the  <a href=\"http://www.nature.com/nbt/journal/v28/n5/extref/nbt.1621-S1.pdf\">\n\t\t  supplemental methods</a> first, as your question may be answered there.\n\t</td><td align=right valign=middle>\n  </td></tr>\n  </table>\n  </div>\n  <div id=\"main\">\n    <div id=\"rightside\">\n\t\t<h2>Site Map</h2>\n        <div class=\"box\">\n          <ul>\n            <li><a href=\"index.html\">Home</a></li>\n            <li><a href=\"tutorial.html\">Getting started</a></li>\n            <li><a href=\"manual.html\">Manual</a></li>\n            <li><a href=\"howitworks.html\">How Cufflinks works</a></li>\n\t\t\t  <li><a href=\"igenomes.html\">Index and annotation downloads</a></li>\n            <li><a href=\"faq.html\">FAQ</a></li>\n\t\t\t  <li><a href=\"http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html\">Protocol</a></li>\n\t\t\t  <li><a href=\"report.html\">Benchmarking</a></li>\n          </ul>\n        </div>\n\t\t\n        <h2><u>News and updates</u></h2>\n        <div class=\"box\">\n          <ul>\n            <table width=\"100%\">\n              <tbody>\n                <tr>\n                  <td>New releases and related tools will be announced\n                    through the <a\n                      href=\"https://lists.sourceforge.net/lists/listinfo/bowtie-bio-announce\"><b>mailing\n                        list</b></a></td>\n                </tr>\n              </tbody>\n            </table>\n          </ul>\n        </div>\n        <h2><u>Getting Help</u></h2>\n        <div class=\"box\">\n          <ul>\n            <table width=\"100%\">\n              <tbody>\n                <tr>\n                  <td>Questions about Cufflinks and Cuffdiff should be posted on our <a href=\"https://groups.google.com/forum/#!forum/tuxedo-tools-users\"><b>Google Group</b></a>. Please use <a\n                      href=\"mailto:tophat.cufflinks@gmail.com\">tophat.cufflinks@gmail.com</a> for private communications only.\n                    Please do not email technical questions to\n                    Cufflinks contributors directly.</td>\n                </tr>\n              </tbody>\n            </table>\n          </ul>\n        </div>\n\t\t  \n\t\t\n          <a href=\"./downloads\">\n            <h2><u>Releases</u></h2>\n          </a>\n          <div class=\"box\">\n            <ul>\n              <table width=\"100%\">\n                <tbody>\n                  <tr>\n                    <td>version 2.2.0</td>\n                    <td align=\"right\">5/25/2014</td>\n                  </tr>\n                  <tr>\n                    <td><a href=\"./downloads/cufflinks-2.2.0.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks_source');\n                        \">&nbsp;&nbsp;&nbsp;Source code</a></td>\n                  </tr>\n                  <tr>\n                    <td><a\n                        href=\"./downloads/cufflinks-2.2.0.Linux_x86_64.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks');\n                        \">&nbsp;&nbsp;&nbsp;Linux x86_64 binary</a></td>\n                  </tr>\n                  <tr>\n                    <td><a\n                        href=\"./downloads/cufflinks-2.2.0.OSX_x86_64.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks');\n                        \">&nbsp;&nbsp;&nbsp;Mac OS X x86_64 binary</a></td>\n                  </tr>\n                </tbody>\n              </table>\n            </ul>\n          </div>\t\t\n\t\t  <h2>Related Tools</h2>\n          <div class=\"box\">\n            <ul>\n                <li><a href=\"http://monocle-bio.sourceforge.net\">Monocle</a>:\n                  Single-cell RNA-Seq analysis</li>\n\t\t\t\t<li><a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a>:\n\t                Visualization of RNA-Seq differential analysis</li>\n              <li><a href=\"http://tophat.cbcb.umd.edu/\">TopHat</a>:\n                Alignment of short RNA-Seq reads</li>\n              <li><a href=\"http://bowtie.cbcb.umd.edu\">Bowtie</a>:\n                Ultrafast short read alignment</li>\n            </ul>\n          </div>\n\n\n\n\t\t  <h2>Publications</h2>\n          <div class=\"box\">\n            <ul>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Trapnell C, Williams BA, Pertea G, Mortazavi AM, Kwan\n                  G, van Baren MJ, Salzberg SL, Wold B, Pachter L.<b> <a\n                      href=\"http://dx.doi.org/10.1038/nbt.1621\">Transcript\n                      assembly and quantification by RNA-Seq reveals\n                      unannotated transcripts and isoform switching\n                      during cell differentiation</a></b> <br>\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\n                      Biotechnology</a></i> doi:10.1038/nbt.1621</p>\n                <br>\n              </li>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Roberts A, Trapnell C, Donaghey J, Rinn JL, Pachter\n                  L.<b> <a\n                      href=\"http://genomebiology.com/2011/12/3/R22/abstract\">Improving\n                      RNA-Seq expression estimates by correcting for\n                      fragment bias</a></b> <br>\n                  <i><a href=\"http://www.genomebiology.com\">Genome\n                      Biology</a></i> doi:10.1186/gb-2011-12-3-r22</p>\n                <br>\n              </li>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Roberts A, Pimentel H, Trapnell C, Pachter\n                  L.<b> <a\n                      href=\"http://bioinformatics.oxfordjournals.org/content/early/2011/06/21/bioinformatics.btr355.abstract\">\n                      Identification of novel transcripts in annotated genomes using RNA-Seq</a></b> <br>\n                  <i><a href=\"http://bioinformatics.oxfordjournals.org/\">Bioinformatics</a></i> doi:10.1093/bioinformatics/btr355</p>\n                <br>\n              </li>\n\t\t\t  <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Trapnell C, Hendrickson D,Sauvageau S, Goff L, Rinn JL, Pachter L<b> <a\n                      href=\"http://dx.doi.org/10.1038/nbt.2450\">Differential \n\t\t\t\t\t analysis of gene regulation at transcript resolution with RNA-seq\n\t\t\t\t\t</a></b> <br>\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\n                      Biotechnology</a></i> doi:10.1038/nbt.2450</p>\n                <br>\n              </li>\n            </ul>\n          </div>\n          <h2>Contributors</h2>\n          <div class=\"box\">\n            <ul>\n              <li><a href=\"http://www.cs.umd.edu/%7Ecole/\">Cole Trapnell</a></li>\n              <li><a href=\"http://www.cs.berkeley.edu/%7Eadarob/\">Adam\n                  Roberts</a></li>\n              <li>Geo Pertea</li>\n\t\t\t  <li>David Hendrickson<li>\n\t\t\t  <li>Loyal Goff</li>\n\t\t\t  <li>Martin Sauvageau</li>\n              <li>Brian Williams</li>\n              <li><a href=\"http://wormlab.caltech.edu/members/\">Ali\n                  Mortazavi</a></li>\n              <li>Gordon Kwan</li>\n              <li>Jeltje van Baren</li>\n\t\t\t  <li><a href=\"http://www.rinnlab.com\">John Rinn</a></li>\n              <li><a href=\"http://www.cbcb.umd.edu/%7Esalzberg/\">Steven\n                  Salzberg</a></li>\n              <li><a href=\"http://biology.caltech.edu/Members/Wold\">Barbara\n                  Wold</a></li>\n              <li><a href=\"http://www.math.berkeley.edu/%7Elpachter/\">Lior\n                  Pachter</a></li>\n            </ul>\n          </div>\n\n\t\t  <h2>Links</h2>\n\t\t  <div class=\"box\">\n\t\t    <ul>\n\t\t      <li><a href=\"http://bio.math.berkeley.edu/\">Berkeley LMCB</a></li>\n\t\t      <li><a href=\"http://www.cbcb.umd.edu/\">UMD CBCB</a></li>\n\t\t\t  <li><a href=\"http://woldlab.caltech.edu/\">Wold Lab</a></li>\n\t\t    </ul>\n\t\t  </div>          \n          \n    </div> <!-- End of \"rightside\" -->\n    <div id=\"leftside\">\n  \t  <table><tr><td cellpadding=7>\n  \t  <h1>How Cufflinks works</h1><br/>\n      <div id=\"toc\">\n  \t    \n\t\t<ul>\n  \t    \t<li><a href=\"#whis\">What is Cufflinks?</a></li>\n  \t    \t<ul>\n  \t      <li><a href=\"#hass\">How does Cufflinks assemble transcripts?</a></li>\n  \t  \t  <li><a href=\"#hqua\">How does Cufflinks calculate transcript abundances?</a></li>\n  \t  \t  <li><a href=\"#hdis\">How does Cufflinks estimate the fragment length distribution?</a></li>\n  \t  \t  <li><a href=\"#hsbi\">How does Cufflinks identify and correct for sequence bias?</a></li>\n  \t  \t  <li><a href=\"#hmul\">How does Cufflinks handle multi-mapped reads?</a></li>\n   \t  \t  <li><a href=\"#hrga\">How does Reference Annotation Based Transcript (RABT) assembly work?</a></li>\n\t\t  <!-- <li><a href=\"#mrge\">How does Cuffmerge work?</a></li> -->\n  \t  </ul>\n\t  </ul>\n\t   <ul> \n\t  \t  <li><a href=\"#diff\">What is Cuffdiff?</a></li>\n\t\t  <ul>\n\t\t  <li><a href=\"#difftest\">How does Cuffdiff test for differentially expressed and regulated genes?</a></li>\n\t\t  <li><a href=\"#diffdiff\">What's changed since the paper was published?</a></li>\n\t  \t  </ul>\n \t   </ul>\n\n  \t    <br/>\n  \t  </div>\n  \t  <h2 id=\"whis\">What is Cufflinks?</h2><br/>\n  \t  <p> Cufflinks is a program that assembles aligned RNA-Seq reads into \n\t\ttranscripts, estimates their abundances, and tests for \n\t\tdifferential expression and regulation transcriptome-wide.\n\t  \tCufflinks runs on <strong>Linux</strong> and <strong>OS X</strong>.\n\t <p>\n        Cufflinks is described in our recent <b><a href=\"http://dx.doi.org/10.1038/nbt.1621\">paper</a></b>, \n        and much of the algorithmic and mathematical material is presented in the \t\n        <a href=\"http://www.nature.com/nbt/journal/v28/n5/extref/nbt.1621-S1.pdf\">\n\t\tsupplemental methods</a>\n\t  </p> \n  \t  <br/>\n\t  <h2 id=\"hass\">How does Cufflinks assemble transcripts?</h2><br/>\n\t  <p>Cufflinks constructs a parsimonious set of transcripts that \"explain\" the \n\t  reads observed in an RNA-Seq experiment.  It does so by reducing the \n\t  comparative assembly problem to a problem in maximum matching in bipartite\n\t  graphs.  In essence, Cufflinks implements a constructive proof of \n\t  <a href=\"http://en.wikipedia.org/wiki/Dilworth%27s_theorem\">Dilworth's Theorem</a> \n\t  by constructing a covering relation on the read alignments, and finding a \n\t  minimum path cover on the directed acyclic graph for the relation.</p>\n\t\n\t  <p>While Cufflinks works well with unpaired RNA-Seq reads, it is designed \n\t\twith paired reads in mind. The assembly algorithm explicitly handles paired end reads by treating\n\t\tthe alignment for a given pair as a single object in the covering relation. \n\t\tThe proof of Dilworth's theorem finds a maximum cardinality matching on the \n\t\tbipartite graph of the transitive closure of the DAG.  However, there is not \n\t\tnecessarily a unique maximum cardinality matching, reflecting the fact \n\t\tthat due to the limited size of RNA-Seq cDNA fragments, we may not know\n\t\twith certainty which outcomes of alternative splicing events go together\n\t\tin the same transcripts.  Cufflinks tries to find the correct parsimonious\n\t\tset of transcripts by performing a <strong>minimum cost</strong> maximum \n\t\tmatching. The cost of associating splicing events is based on the \"percent-spliced-in\" \n\t\tscore introduced in\n\t\t<p>\n\t\t<ul>\n\t\t<li>Eric T. Wang, Rickard Sandberg, Shujun Luo, Irina Khrebtukova, Lu Zhang, Christine Mayr, Stephen F. Kingsmore, Gary P. Schroth, and Christopher B. Burge,\n\t\t\t<a href=\"http://www.nature.com/nature/journal/v456/n7221/abs/nature07509.html\">Alternative isoform regulation in human tissue transcriptomes</a>\n\t\t\tNature, Volume 456, 470 - 476 (2008)\n\t   </ul>\n\t\t\n\t\t<p>\n\t    This matching is then extended to a minimum cost path cover of the DAG,\n\t    with each path representing a different transcript.</p> <br/>\n\t\t\n\t\tThe algorithm builds on ideas behind the  \n\t\t<a href=\"http://www.bsse.ethz.ch/cbg/software/shorah\">ShoRAH</a> algorithm \n\t\tfor haplotype abundance estimation in viral populations, described in:\n\t\t<p>\n\t\t<ul>\n\t\t\t<li>Nicholas Eriksson, Lior Pachter, Yumi Mitsuya, Soo-Yon Rhee, Chunlin Wang, Baback Gharizadeh, Mostafa Ronaghi, Robert W. Shafer, Niko Beerenwinkel\n\t\t<a href=\"http://www.ploscompbiol.org/doi/pcbi.1000074\">Viral population estimation using pyrosequencing</a>,\n\t\tPLoS Computational Biology, 4(5):e1000074\n\t\t</ul>\n\t\tThe assembler also borrows some ideas introduced with the <a href=\"http://pasa.sourceforge.net/\">PASA</a> algorithm for annotating genomes from EST and full length mRNA evidence, described in:\n\t\t<ul>\n\t\t\t<li>Haas, B.J., Delcher, A.L., Mount, S.M., Wortman, J.R., Smith Jr, R.K., Jr., Hannick, L.I., Maiti, R., Ronning, C.M., Rusch, D.B., Town, C.D. et al. (2003) Improving the Arabidopsis genome annotation using maximal transcript alignment assemblies. <a href=\"http://nar.oxfordjournals.org/cgi/content/full/31/19/5654\">Nucleic Acids Res, 31, 5654-5666</a>. \n\t\t</ul>\n\t\t<br/>\n\t\tCufflinks is implemented in C++ and makes substantial use of the \n\t\t<a href=\"http://www.boost.org\">Boost Libraries</a> as well as the <a href=\"https://lemon.cs.elte.hu/trac/lemon\">LEMON</a>\n\t\tGraph Library, which was launched by the Egerváry Research Group on Combinatorial Optimization (EGRES).\n\t\t\n\t  <br/>\n\t  <br/>\n  \t  <h2 id=\"hqua\">How does Cufflinks calculate transcript abundances?</h2><br/>\n\t  <p>\n\t  In RNA-Seq experiments, cDNA fragments are sequenced and mapped back to \n\t  genes and ideally, individual transcripts. Properly normalized, the RNA-Seq fragment counts\n\t  can be used as a measure of relative abundance of transcripts, \n\t  and Cufflinks measures transcript abundances in <b>F</b>ragments <b>P</b>er \n\t  <b>K</b>ilobase of exon per <b>M</b>illion fragments mapped (<b>FPKM</b>), which is \n\t  analagous to single-read \"RPKM\", originally proposed in:\n\t  </p>\n\t\t<br/>\n\t \n\t  <ul>\n\t\t<li>Ali Mortazavi, Brian A Williams, Kenneth McCue, Lorian Schaeffer and Barbara Wold\n\t\t\t<a href=\"http://www.nature.com/nmeth/journal/v5/n7/abs/nmeth.1226.html\">Mapping and quantifying mammalian transcriptomes by RNA-Seq</a>\n\t\t\tNature Methods, Volume 5, 621 - 628 (2008)\n\t  </ul>\n\t  <br/>\n\t  \n\t  <p>\n\t  \tIn paired-end RNA-Seq experiments, fragments are sequenced from both ends, \n\t\tproviding two reads for each fragment.  To estimate isoform-level abundances, \n\t\tone must assign fragments to individual transcripts, which may be \n\t\tdifficult because a read may align to multiple\n\t  \tisoforms of the same gene.  Cufflinks uses a statistical model of \n\t  \tpaired-end sequencing experiments to derive a likelihood for the abundances of a set of\n\t\ttranscripts given a set of fragments. This likelihood function can be\n\t\tshown to have a unique maximum, which Cufflinks finds using a\n\t\tnumerical optimization algorithm.  The program then multiplies these probabilities \n\t  \tto compute the overall likelihood that one would observe the fragments in the experiment, \n\t  \tgiven the proposed abundances on the transcripts.  Because Cufflinks' statistical\n\t  \tmodel is linear, the likelihood function has a unique maximum value, and\n\t  \tCufflinks finds it with a numerical optimization algorithm.</p>\n  \n\t  <p>Using this statistical method, Cufflinks can estimate the abundances of the isoforms present in the sample,\n\t  either using a known \"reference\" annotation, \tor after an ab-initio \n\t\tassembly of the transcripts using only the reference genome.\n      </p>\n\t  <br/>\n\t\n\t  <h2 id=\"hdis\">How does Cufflinks estimate the fragment length distribution?</h2><br/>\n\t  <p>\n\t  The probability distribution on the length of fragments plays an important role in assembly, abundance\n\t  estimation, and bias correction.  The accuracy of this distribution will have a great impact on the \n\t  accuracy of our results.  Because of this, we now attempt to \"learn\" this distribution from the input\n\t  data instead of relying on an approximate Gaussian distribution, whenever possible.\n\t  </p>\n\t  <ul><li>\n\t  \tIf only single-end reads are provided, there is no way to estimate the empirical distribution,\n\t  \tso Cufflinks must use an approximate Gaussian distribution with either default or user-provided\n\t  \tparameters (see the manual for more details).  \n\t  </li></ul>\n  \n\t  <ul><li>If the alignment file contains paired-end reads and an asssembly is provided, Cufflinks is able to learn the distribution\n\t  from reads that map to single-isoform genes. Because the assembly provides the splicing structure, introns can be removed from\n\t  between the paired reads, providing the most accurate estimation.</ul></li>\n\t  \n\t  \n\t  <ul><li>If given paired end reads and no assembly, Cufflinks will search for large \"open ranges\" where the alignments contain no splices within\n\t  the reads. Within these ranges, Cufflinks uses the genomic length of the paired-end reads to estimate the distribution. If not enough reads can \n\t  be found within these ranges, Cufflinks will default to the Gaussian approximation as in the single-end case. To ensure an empirical distribution\n\t  will be used, one can first assemble with the Gaussian and then supply the output GTF assembly in a second run of Cufflinks.</li></ul>\n\t  <br/>\n\t  \n\t<h2 id=\"hsbi\">How does Cufflinks identify and correct for sequence bias?</h2><br/>\n\t  <p>\n\t  Often in RNA-Seq experiments, a sequence-specific bias is introduced during the \n\t  library preparation that challenges the assumption of uniform coverage. For example, \n\t  a sequence-specific bias caused by the use of random hexamers was identified in\n\t  </p>\n\t\t<br/>\n\t \n\t  <ul>\n\t\t<li>Kasper D. Hansen, Steven E. Brenner, Sandrine Dudoit,\n\t\t\t<a href=\"http://nar.oxfordjournals.org/cgi/content/abstract/38/12/e131\">Biases in Illumina transcriptome sequencing caused by random hexamer priming</a>\n\t\t\tNucleic Acids Research, Volume 38, Issue 12 (2010)\n\t  </ul>\n\t  <br/>\n\t  \n\t  <p>\n\t  \tBecause this bias is usually caused by primers used either in PCR or reverse transcription, it appears near \n\t  \tthe ends of the sequenced fragments.  We have developed a method to correct this bias by “learning” what sequences \n\t  \tare being selected for (or ignored) in a given experiment, and including these measurements in the abundance \n\t  \testimation.  \n\t  </p>\n  \n\t  <p>The first step in the process is to generate an initial abundance estimation without using bias correction.  \n\t  Since different transcripts will have different sequences appear in them, we use this approximate abundance to \n\t  weight reads by the expression level of the transcript from which they arise.  This helps us avoid over-counting \n\t  sequences that may be common in the mapping data due to high expression rather than bias.</p>\n\t  \n\t  <p>We next revisit each fragment in the alignment file and apply the abundance weighting as we “learn” features of the \n\t  sequence in a window surrounding the 5’ and 3’ end of the transcript using a graphical model of the statistical dependencies \n\t  between bases in the window.  We keep a separate model for each end of the read since the biases in the first \n\t  and second strand synthesis of the fragment are not always the same.</p>\n\t  \n\t  <p>Finally, we re-estimate the abundances using a new likelihood function that has been adjusted to take the sequence \n\t  bias into account, based on the parameters of the graphical model we computed in the previous step.  The result is a \n\t  new set of FPKMs that are less affected by sequence-specific bias.</p>\n\t  \n\t  <p> Note that since it must know which ends of reads are fragment ends, Cufflinks will not bias correct reads mapping to transcripts\n\t  with unknown strandedness.\n\t  </p>\n\t  <p>The full details of our method can be found in</p>\n\t  \t\t\n\t  <br/><ul>\n\t\t<li>Adam Roberts, Cole Trapnell, Julie Donaghey, John L. Rinn and Lior Pachter,\n\t\t\t<a href=\"http://genomebiology.com/2011/12/3/R22/abstract\">Improving RNA-Seq expression estimates by correcting for fragment bias</a>\n\t\t\tGenome Biology, Volume 12, R22 (2011)\n\t  </ul><br/>\n\t  \n\t  \n\t  <h2 id=\"hmul\">How does Cufflinks handle multi-mapped reads?</h2><br/>\n\t  <p> Individual reads will sometimes be mapped to multiple positions in the genome due to sequence repeats and homology. \n\t  By default, Cufflinks will uniformly divide each multi-mapped read to all of the positions it maps to.  In other words,\n\t  a read mapping to 10 positions will count as 10% of a read at each position.</p>\n\t  <p>If multi-mapped read correction is enabled (-u/--multi-read-correct), Cufflinks will improve its estimation in a manner\n\t  inspired by (but using more information than) the 'rescue' method described in</p>\t\n\t  <br/><ul>\n\t\t<li>Ali Mortazavi, Brian A Williams, Kenneth McCue, Lorian Schaeffer and Barbara Wold\n\t\t\t<a href=\"http://www.nature.com/nmeth/journal/v5/n7/abs/nmeth.1226.html\">Mapping and quantifying mammalian transcriptomes by RNA-Seq</a>\n\t\t\tNature Methods, Volume 5, 621 - 628 (2008)\n\t  </ul><br/>\n\t  <p>Cufflinks will first calculate initial abundance estimates for all transcripts using the uniform dividing scheme.  Cufflinks will\n\t  then re-estimate the abundances dividing each multi-mapped read probabalistically based on the initial abundance estimation of the genes\n\t  it maps to, the inferred fragment length, and fragment bias (if bias correction is enabled).</p>\n\t  <br/>\n\t  \n\t  <h2 id=\"hrga\">How does Reference Annotation Based Transcript (RABT) assembly work?</h2><br/>\n\t  <p>Reference annotation based assembly seeks to build upon available information about the transcriptome of\n\t  an organism to find novel genes and isoforms.  When a reference GTF is provided with the -g/--GTF-guide option,\n\t  the reference transcripts are tiled with faux-reads that will aid in the assembly of novel isoforms. These\n\t  faux reads are combined with the sequencing reads and are input into the regular Cufflinks assembler.  The assembled\n\t  transfrags are then compared to the reference transcripts to determine if they are sufficiently different to be \n\t  considered novel.  Those that are labeled novel by our criteria (see Cufflinks options to adjust the parameters)\n\t  are output along with the transcripts from the annotation.\n\t  <p>The use of faux-reads was inspired by the methods of</p>\n\t<br/><ul>\n\t\t<li>J Venter, M Adams, E Myers, P Li, R Mural, G Sutton, H Smith, M Yandell, C Evans, R Holt, et al.\n\t\t\t<a href=\"http://www.sciencemag.org/content/291/5507/1304.full\">The sequence of the human genome</a>\n\t\t\tScience, Volume 291, 1304 - 1351 (2001)\n\t  </ul><br/>\n\t\n\t<!-- <h2 id=\"mrge\">How does Cuffmerge work?</h2><br/> -->\n\t\n\t<h2 id=\"diff\">What is Cuffdiff?</h2><br/>\n  \t<p> Cuffdiff is a program that uses the Cufflinks transcript quantification\n\tengine to calculate gene and transcript expression levels in more than one condition and \n\ttest them for signficant differences.  You can use it to find differentially expressed genes \n\tand transcripts, as well as genes that are being differentially <em>regulated</em> at the \n\ttranscriptional and post-transcriptional level.\n\t</p>\n\t\n\t<p>Cuffdiff is described in detail in the manuscript below:\n\t\t<ul>\n\t\t\t<li>Trapnell C, Hendrickson D,Sauvageau S, Goff L, Rinn JL, Pachter L, <a\n\t\t                      href=\"http://dx.doi.org/10.1038/nbt.2450\">Differential \n\t\t\t\t\t\t\t analysis of gene regulation at transcript resolution with RNA-seq\n\t\t\t\t\t\t\t</a> <br>\n\t\t                  <i><a href=\"http://www.nature.com/nbt\">Nature\n\t\t                      Biotechnology</a></i> doi:10.1038/nbt.2450\n\t\t\n\t\t\n\t\t\t </li>\n\t\t </ul>\n\t </p>\n\t <br/>\n\t <h2 id=\"difftest\">How does Cuffdiff 2 test for differentially expressed and regulated genes?</h2><br/>\n\t <p>\n\t\t To identify a gene or transcript as DE, Cuffdiff 2 tests the observed log-fold-change in its expression against the null hypothesis of no change (i.e. the true log-fold-change is zero).  Because measurement error, technical variability, and cross-replicate biological variability might result in an observed log-fold-change that is nonzero, Cuffdiff assesses significance using a model of variability in the log-fold-change under the null hypothesis. This model is described in detail in detail in Trapnell and Hendrickson et al. Briefly, Cuffdiff two constructs, for each condition, a table that predicts how much variance there is in the number of reads originating from a gene or transcript.  The table is keyed by the average reads across replicates, so to look up the variance for a transcript using the table, Cuffdiff estimates how many reads originated from that transcript, and then queries the table to retrieve the variance for that number of reads.  Cuffdiff 2 then accounts for read mapping and assignment uncertainty by simulating probabilistic assignment of the reads mapping to a locus to the splice isoforms for that locus. At the end of the estimation procedure, Cuffdiff 2 obtains an estimate of the number of reads that originated from each gene and transcript, along with variances in those estimates.  The read counts are reported along with FPKM values and their variances.  Change in expression is reported as the log fold change in FPKM, and the FPKM variances allow the program to estimate the variance in the log-fold-change itself.  Naturally, a gene that has highly variable expression will have a highly variable log-fold-change between two conditions. \n\t </p>\n\t <br/>\n\t <h2 id=\"diffdiff\">What's changed since the paper?</h2><br/>\n\t <p>Numerous small changes, bugfixes, and minor features have appeared since version 2.0.2 of Cuffdiff (which was used for Trapnell and Hendrickson et al).  There are also two more substantial changes:\n\t\t <p> The first change is that Cuffdiff now reports the FPKM for each condition as the average FPKM calculated for each individual replicate.  Previous versions pooled the reads from all replicates of a condition together and computed FPKM for each gene and transcript from the pool.  The two approaches yield extremely similar values, but the new method is faster and simpler, and will make implementing several planned features much easier. \n\t <p>\n\t\t The second change is that Cuffdiff 2.1 introduced a new testing method that substantially improves performance over previous releases, including the one used for the paper. The modifications made in Cuffdiff 2.1 improve sensitivity in calling differentially expressed (DE) genes and transcripts while maintaining a low false positive rate.  They stem from the method used to calculate the variability in the log fold change in expression.  In Trapnell et al, Cuffdiff 2 used the “delta method” to estimate the variance of the log fold change estimate for a gene or transcript. This method yields a simple equation that takes as input the mean and variance of the transcript’s expression in two conditions and produces a variance for the log fold change.  However, the equation contains no explicit accounting for the number of replicates used to produce those estimates – they are assumed to be perfectly accurate. The equation also assumes that the distribution of log fold changes (after a particular transformation) is approximately normal.  For most genes and transcripts, this approximation is a good one.  However, for the remaining genes and transcripts, Cuffdiff 2 sometimes failed to detect a signficant change in expression.\n\t <p>\n\t\t The improved version of Cuffdiff 2 more accurately estimates the variance in the log-fold-change using simulated draws from the model of variance in expression for each of the two conditions.  Imagine an experiment that has <em>n</em> replicates in condition <em>A</em> and <em>m</em> replicates in condition <em>B</em>. To estimate the distribution of the log-fold-change in expression for a gene <em>G</em> under the null hypothesis, Cuffdiff first draws <em>n</em> times from the distribution of expression of <em>G</em> according to the algorithm’s model of expression.  Cuffdiff then takes the average of the <em>n</em> draws to obtain an expression “measurement”. Then, Cuffdiff draws <em>m</em> from the same distribution and again takes their average.    Cuffdiff then takes the log ratio of these averages, places this value in a list, and then repeats the procedure until there are thousands of such log-fold-change samples in the list.  The software then makes a similar list, this time using the expression model for condition <em>B</em> – the null hypothesis assumes both sets of replicates originate from the same condition, but we do not know whether <em>A</em> or <em>B</em> is the better representative of that condition, so we must draw samples from both and combine them.   To calculate a <em>p</em>-value of observing the real log-fold-change under this null model, we simply sort all the samples and count how many of them are more extreme than the log fold change we actually saw in the real data.  This number divided by the total number of draws is our estimate for the <em>p</em>-value.\n\t<p>\t \n\t\t Cuffdiff 2 reports not only genes and transcripts that are significantly DE between conditions, but also groups of transcripts (i.e. the isoforms of a gene) that show significant changes in expression relative to one another.  The test for this is similar to what is described in Trapnell et al, but comparably modified along the lines described above for single genes or transcripts.  Draws of expression are made for each transcript in a group according to the number of replicates in the experiment.  These are averaged, and the shift in relative transcript abundance for the draw is made using the Jensen-Shannon metric.  These draws are added to a list and used to calculate <em>p</em>-values for significance of observed shifts in relative abundance under the null hypothesis.\n\t\t \n\t <br/>\n  </div>\n  <div id=\"footer\">\n  \t<table width=\"100%\" cellspacing=15><tr><td>\n    This research was supported in part by NIH grants R01-LM06845 and R01-GM083873, NSF grant CCF-0347992 and the Miller Institute for Basic\n\t\tResearch in Science at UC Berkeley.\n    </td><td align=right>\n    Administrator: <a href=\"mailto:cole@cs.umd.edu\">Cole Trapnell</a>. Design by <a href=\"http://www.free-css-templates.com\" title=\"Design by David Herreman\">David Herreman</a>\n    </td></tr></table>\n  </div>\n</div>\n\n<!-- Google analytics code -->\n<script type=\"text/javascript\">\nvar gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\ndocument.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n</script>\n<script type=\"text/javascript\">\ntry {\nvar pageTracker = _gat._getTracker(\"UA-6101038-2\");\npageTracker._trackPageview();\n} catch(err) {}</script>\n<!-- End Google analytics code -->\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/igenome/igenome_table.py",
    "content": "#!/usr/bin/env python\n\nimport sys, os\nimport string\nfrom ftplib import FTP\n\nuse_message = '''\n'''\n\nftp_address = 'ftp.illumina.com'\nuser_id = 'igenome'\npassword = 'G3nom3s4u'\n\nvisible_organisms = \\\n    ['Homo_sapiens',\n     'Mus_musculus',\n     'Rattus_norvegicus',\n     'Bos_taurus',\n     'Canis_familiaris',\n     'Gallus_gallus',\n     'Drosophila_melanogaster',\n     'Arabidopsis_thaliana',\n     'Caenorhabditis_elegans',\n     'Saccharomyces_cerevisiae']\n\ndef generate_table():\n    ftp = FTP(ftp_address)\n\n    print >> sys.stderr, \"Logging into %s\" % ftp_address\n    print >> sys.stderr, ftp.login(user_id, password)\n\n    organisms = {}\n    organisms_index = {}\n\n    def get_list(size_and_date = False):\n        result = []\n        lines = []\n        def get_string(str):\n            if len(str) > 0:\n                lines.append(str)\n                \n        ftp.retrlines('LIST', get_string)\n        \n        for line in lines:\n            elements = line.split()\n            flag, organism, size, date = elements[0], elements[-1], elements[4], ' '.join(elements[-4:-1])\n            result.append([flag, organism])\n\n            if size_and_date:\n                result[-1] += [size, date]\n\n        return result\n\n    files = get_list()\n    for file in files:\n        flag, name = file\n        if flag[0] == 'd':\n            organisms[name] = []\n            organisms_index[name] = []\n\n    for name in visible_organisms:\n        print >> sys.stderr, name\n\n        count = 0\n        ftp.cwd(\"/%s\" % name)\n        sources = get_list()\n        for flag, source in sources:\n            if flag[0] != 'd':\n                pass\n            ftp.cwd(\"/%s/%s\" % (name, source))\n            versions = get_list()\n            for flag, version in versions:\n                if flag[0] != 'd':\n                    next\n\n                ftp.cwd(\"/%s/%s/%s\" % (name, source, version))\n                size_and_date = True\n                files = get_list(True)\n                file_name = \"\"\n                for flag, file, size, date in files:\n                    if string.find(file, 'tar.gz') != -1:\n                        file_name = file\n                        break\n\n                size = int(size) / (1024 * 1024)\n                size = \"%d MB\" % size\n                    \n                address = r\"ftp://%s:%s@%s/%s/%s/%s/%s\" % \\\n                    (user_id, password, ftp_address, name, source, version, file_name)\n                organisms[name].append([source, version, address, size, date])\n                count += 1\n            organisms_index[name].append(count)\n            \n    ftp.close()\n\n    html_file = open('igenome_table.html', 'w')\n    print >> html_file, r'<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">'\n    print >> html_file, r'<html xmlns=\"http://www.w3.org/1999/xhtml\">'\n    print >> html_file, r'<head>'\n    print >> html_file, r'<title>TopHat :: Center for Bioinformatics and Computational Biology</title>'\n    print >> html_file, r'<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />'\n    print >> html_file, r'<link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\" media=\"screen\" />'\n    print >> html_file, r'</head>'\n    print >> html_file, r'<body>'\n    print >> html_file, r'<div id=\"leftside\">'\n    print >> html_file, r'<TABLE CELLPADDING=3 BORDER=\"1\">'\n    print >> html_file, r'<TR>'\n    print >> html_file, r'<TH ALIGN=\"LEFT\">Organism</TH>'\n    print >> html_file, r'<TH ALIGN=\"LEFT\">Data source</TH>'\n    print >> html_file, r'<TH ALIGN=\"LEFT\">Version</TH>'\n    print >> html_file, r'<TH ALIGN=\"LEFT\">Size</TH>'\n    print >> html_file, r'<TH ALIGN=\"LEFT\">Last Modified</TH>'\n    print >> html_file, r'</TR>'\n\n    for name in visible_organisms:\n        organism = organisms[name]\n        organism_index = organisms_index[name]\n\n        prev_i = 0\n        for i in organism_index:\n            for j in range(prev_i, i):\n                version = organism[j]\n                print >> html_file, r'<TR>'\n\n                if j == 0:\n                    print >> html_file, r'<TD ALIGN=\"LEFT\" rowspan=%d>%s</TD>' % \\\n                        (organism_index[-1], string.replace(name, '_', ' '))\n\n                if j == prev_i:\n                    print >> html_file, r'<TD ALIGN=\"LEFT\" rowspan=%d>%s</TD>' % (i - prev_i, version[0])\n\n                print >> html_file, r'<TD ALIGN=\"LEFT\"><A HREF=\"%s\">%s</A></TD>' % (version[2], version[1])\n                print >> html_file, r'<TD ALIGN=\"RIGHT\">%s</TD>' % version[3]\n                print >> html_file, r'<TD ALIGN=\"LEFT\">%s</TD>' % version[4]\n                print >> html_file, r'</TR>'\n            \n            prev_i = i\n    \n    print >> html_file, r'</TABLE>'\n    print >> html_file, r'</div>'\n    print >> html_file, r'</body>'\n    print >> html_file, r'</html>'\n\n    html_file.close()\n\nif __name__ == \"__main__\":\n    sys.exit(generate_table())\n"
  },
  {
    "path": "doc/html/igenomes.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n  <head>\n<title>Cufflinks - Transcript assembly, differential expression, and\n          differential regulation for RNA-Seq</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n<link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\" media=\"screen\" />\n</head>\n<body>\n<div id=\"wrap\">\n  <div id=\"top\">\n    <div class=\"lefts\">\n    <table width=\"100%\" cellpadding=\"2\">\n      <tr><td>\n           <a href=\"./index.html\"><h1>Illumina iGenomes</h1></a>\n      </td><td align=\"right\" valign=\"middle\">\n        <a href=\"http://www.mcb.berkeley.edu/\">\n          <img style=\"vertical-align:middle;padding-top:4px\" \n            border=0 src=\"images/UCBerkeley-seal.scaled.gif\">\n        </a>&nbsp;\n        <a href=\"http://genomics.jhu.edu/\">\n           <img style=\"vertical-align:middle;padding-top:4px\"\n                src=\"images/JHU-seal.gif\" border=\"0\">\n           </a>&nbsp;\n        <a href=\"http://www.cbcb.umd.edu/\"><img style=\"vertical-align:middle;padding-top:4px\" border=0 src=\"images/cbcb_logo.gif\"></a>&nbsp;&nbsp;\n      </td></tr>\n      </td></tr>\n    </table>\n    </div>\n  </div>\n\n  <div id=\"main\">\n\t\n      <div id=\"rightside\">\n          <h2>Site Map</h2>\n          <div class=\"box\">\n            <ul>\n              <li><a href=\"index.html\">Home</a></li>\n              <li><a href=\"tutorial.html\">Getting started</a></li>\n              <li><a href=\"manual.html\">Manual</a></li>\n              <li><a href=\"howitworks.html\">How Cufflinks works</a></li>\n\t\t\t  <li><a href=\"igenomes.html\">Index and annotation downloads</a></li>\n              <li><a href=\"faq.html\">FAQ</a></li>\n\t\t\t  <li><a href=\"http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html\">Protocol</a></li>\n\t\t\t  <li><a href=\"report.html\">Benchmarking</a></li>\n            </ul>\n          </div>\n          <h2><u>News and updates</u></h2>\n          <div class=\"box\">\n            <ul>\n              <table width=\"100%\">\n                <tbody>\n                  <tr>\n                    <td>New releases and related tools will be announced\n                      through the <a\n                        href=\"https://lists.sourceforge.net/lists/listinfo/bowtie-bio-announce\"><b>mailing\n                          list</b></a></td>\n                  </tr>\n                </tbody>\n              </table>\n            </ul>\n          </div>\n          <h2><u>Getting Help</u></h2>\n          <div class=\"box\">\n            <ul>\n              <table width=\"100%\">\n                <tbody>\n                  <tr>\n                    <td>Questions about Cufflinks and Cuffdiff should be posted on our <a href=\"https://groups.google.com/forum/#!forum/tuxedo-tools-users\"><b>Google Group</b></a>. Please use <a\n                        href=\"mailto:tophat.cufflinks@gmail.com\">tophat.cufflinks@gmail.com</a> for private communications only.\n                      Please do not email technical questions to\n                      Cufflinks contributors directly.</td>\n                  </tr>\n                </tbody>\n              </table>\n            </ul>\n          </div>\n         \n      \n          <a href=\"./downloads\">\n            <h2><u>Releases</u></h2>\n          </a>\n          <div class=\"box\">\n            <ul>\n              <table width=\"100%\">\n                <tbody>\n                  <tr>\n                    <td>version 2.2.0</td>\n                    <td align=\"right\">5/25/2014</td>\n                  </tr>\n                  <tr>\n                    <td><a href=\"./downloads/cufflinks-2.2.0.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks_source');\n                        \">&nbsp;&nbsp;&nbsp;Source code</a></td>\n                  </tr>\n                  <tr>\n                    <td><a\n                        href=\"./downloads/cufflinks-2.2.0.Linux_x86_64.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks');\n                        \">&nbsp;&nbsp;&nbsp;Linux x86_64 binary</a></td>\n                  </tr>\n                  <tr>\n                    <td><a\n                        href=\"./downloads/cufflinks-2.2.0.OSX_x86_64.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks');\n                        \">&nbsp;&nbsp;&nbsp;Mac OS X x86_64 binary</a></td>\n                  </tr>\n                </tbody>\n              </table>\n            </ul>\n          </div>         \n\n\t\t  <h2>Related Tools</h2>\n          <div class=\"box\">\n            <ul>\n                <li><a href=\"http://monocle-bio.sourceforge.net\">Monocle</a>:\n                  Single-cell RNA-Seq analysis</li>\n\t\t\t\t<li><a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a>:\n\t                Visualization of RNA-Seq differential analysis</li>\n              <li><a href=\"http://tophat.cbcb.umd.edu/\">TopHat</a>:\n                Alignment of short RNA-Seq reads</li>\n              <li><a href=\"http://bowtie.cbcb.umd.edu\">Bowtie</a>:\n                Ultrafast short read alignment</li>\n            </ul>\n          </div>\n\n\n\n         <h2>Publications</h2>\n          <div class=\"box\">\n            <ul>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Trapnell C, Williams BA, Pertea G, Mortazavi AM, Kwan\n                  G, van Baren MJ, Salzberg SL, Wold B, Pachter L.<b> <a\n                      href=\"http://dx.doi.org/10.1038/nbt.1621\">Transcript\n                      assembly and quantification by RNA-Seq reveals\n                      unannotated transcripts and isoform switching\n                      during cell differentiation</a></b> <br>\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\n                      Biotechnology</a></i> doi:10.1038/nbt.1621</p>\n                <br>\n              </li>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Roberts A, Trapnell C, Donaghey J, Rinn JL, Pachter\n                  L.<b> <a\n                      href=\"http://genomebiology.com/2011/12/3/R22/abstract\">Improving\n                      RNA-Seq expression estimates by correcting for\n                      fragment bias</a></b> <br>\n                  <i><a href=\"http://www.genomebiology.com\">Genome\n                      Biology</a></i> doi:10.1186/gb-2011-12-3-r22</p>\n                <br>\n              </li>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Roberts A, Pimentel H, Trapnell C, Pachter\n                  L.<b> <a\n                      href=\"http://bioinformatics.oxfordjournals.org/content/early/2011/06/21/bioinformatics.btr355.abstract\">\n                      Identification of novel transcripts in annotated genomes using RNA-Seq</a></b> <br>\n                  <i><a href=\"http://bioinformatics.oxfordjournals.org/\">Bioinformatics</a></i> doi:10.1093/bioinformatics/btr355</p>\n                <br>\n              </li>\n\t\t\t  <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Trapnell C, Hendrickson D,Sauvageau S, Goff L, Rinn JL, Pachter L<b> <a\n                      href=\"http://dx.doi.org/10.1038/nbt.2450\">Differential \n\t\t\t\t\t analysis of gene regulation at transcript resolution with RNA-seq\n\t\t\t\t\t</a></b> <br>\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\n                      Biotechnology</a></i> doi:10.1038/nbt.2450</p>\n                <br>\n              </li>\n            </ul>\n          </div>\n          <h2>Contributors</h2>\n          <div class=\"box\">\n            <ul>\n              <li><a href=\"http://www.cs.umd.edu/%7Ecole/\">Cole Trapnell</a></li>\n              <li><a href=\"http://www.cs.berkeley.edu/%7Eadarob/\">Adam\n                  Roberts</a></li>\n              <li>Geo Pertea</li>\n\t\t\t  <li>David Hendrickson<li>\n\t\t\t  <li>Loyal Goff</li>\n\t\t\t  <li>Martin Sauvageau</li>\n              <li>Brian Williams</li>\n              <li><a href=\"http://wormlab.caltech.edu/members/\">Ali\n                  Mortazavi</a></li>\n              <li>Gordon Kwan</li>\n              <li>Jeltje van Baren</li>\n\t\t\t  <li><a href=\"http://www.rinnlab.com\">John Rinn</a></li>\n              <li><a href=\"http://www.cbcb.umd.edu/%7Esalzberg/\">Steven\n                  Salzberg</a></li>\n              <li><a href=\"http://biology.caltech.edu/Members/Wold\">Barbara\n                  Wold</a></li>\n              <li><a href=\"http://www.math.berkeley.edu/%7Elpachter/\">Lior\n                  Pachter</a></li>\n            </ul>\n          </div>\n         <h2>Links</h2>\n         <div class=\"box\">\n           <ul>\n             <li><a href=\"http://bio.math.berkeley.edu/\">Berkeley LMCB</a></li>\n             <li><a href=\"http://www.cbcb.umd.edu/\">UMD CBCB</a></li>\n             <li><a href=\"http://woldlab.caltech.edu/\">Wold Lab</a></li>\n           </ul>\n         </div>\n       </div>\n      \n    </div> <!-- End of \"rightside\" -->\n    <div id=\"leftside\">\n    Illumina has provided the RNA-Seq user community with a set of genome sequence indexes (including Bowtie indexes) as well as GTF transcript annotation files.  These files can be used with TopHat and Cufflinks to quickly perform expression analysis and gene discovery.  The annotation files are augmented with the <tt>tss_id</tt> and <tt>p_id</tt> GTF attributes that Cufflinks needs to perform differential splicing, CDS output, and promoter user analysis. We recommend that you download your Bowtie indexes and annotation files from this page. More information about Illumina's iGenomes project can be found <A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/README.txt\">here</A>.\n    <br/>\n    <br/>\n    <TABLE id=\"box-table-a\" CELLPADDING=3>\n      \n      <TR>\n<TH ALIGN=\"LEFT\">Organism</TH>\n<TH ALIGN=\"LEFT\">Data source</TH>\n<TH ALIGN=\"LEFT\">Version</TH>\n<TH ALIGN=\"LEFT\">Size</TH>\n<TH ALIGN=\"LEFT\">Last Modified</TH>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=6>Homo sapiens</TD>\n<TD ALIGN=\"LEFT\" rowspan=1>Ensembl</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Homo_sapiens/Ensembl/GRCh37/Homo_sapiens_Ensembl_GRCh37.tar.gz\">GRCh37</A></TD>\n<TD ALIGN=\"RIGHT\">17297 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 17:23</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=3>NCBI</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Homo_sapiens/NCBI/build36.3/Homo_sapiens_NCBI_build36.3.tar.gz\">build36.3</A></TD>\n<TD ALIGN=\"RIGHT\">15814 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 19:36</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Homo_sapiens/NCBI/build37.1/Homo_sapiens_NCBI_build37.1.tar.gz\">build37.1</A></TD>\n<TD ALIGN=\"RIGHT\">15850 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 19:04</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Homo_sapiens/NCBI/build37.2/Homo_sapiens_NCBI_build37.2.tar.gz\">build37.2</A></TD>\n<TD ALIGN=\"RIGHT\">21450 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 17:54</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=2>UCSC</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Homo_sapiens/UCSC/hg18/Homo_sapiens_UCSC_hg18.tar.gz\">hg18</A></TD>\n<TD ALIGN=\"RIGHT\">17349 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 15:31</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Homo_sapiens/UCSC/hg19/Homo_sapiens_UCSC_hg19.tar.gz\">hg19</A></TD>\n<TD ALIGN=\"RIGHT\">21058 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 15:36</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=5>Mus musculus</TD>\n<TD ALIGN=\"LEFT\" rowspan=1>Ensembl</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Mus_musculus/Ensembl/NCBIM37/Mus_musculus_Ensembl_NCBIM37.tar.gz\">NCBIM37</A></TD>\n<TD ALIGN=\"RIGHT\">14428 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 22:13</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=2>NCBI</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Mus_musculus/NCBI/build37.1/Mus_musculus_NCBI_build37.1.tar.gz\">build37.1</A></TD>\n<TD ALIGN=\"RIGHT\">15260 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 17:53</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Mus_musculus/NCBI/build37.2/Mus_musculus_NCBI_build37.2.tar.gz\">build37.2</A></TD>\n<TD ALIGN=\"RIGHT\">15725 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 22:52</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=2>UCSC</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Mus_musculus/UCSC/mm9/Mus_musculus_UCSC_mm9.tar.gz\">mm9</A></TD>\n<TD ALIGN=\"RIGHT\">14537 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 21:12</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Mus_musculus/UCSC/mm10/Mus_musculus_UCSC_mm10.tar.gz\">mm10</A></TD>\n<TD ALIGN=\"RIGHT\">14193 MB</TD>\n<TD ALIGN=\"LEFT\">Jun 14 11:29</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=3>Rattus norvegicus</TD>\n<TD ALIGN=\"LEFT\" rowspan=1>Ensembl</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Rattus_norvegicus/Ensembl/RGSC3.4/Rattus_norvegicus_Ensembl_RGSC3.4.tar.gz\">RGSC3.4</A></TD>\n<TD ALIGN=\"RIGHT\">13725 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 22:33</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=1>NCBI</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Rattus_norvegicus/NCBI/RGSC_v3.4/Rattus_norvegicus_NCBI_RGSC_v3.4.tar.gz\">RGSC_v3.4</A></TD>\n<TD ALIGN=\"RIGHT\">14234 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 23:58</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=1>UCSC</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Rattus_norvegicus/UCSC/rn4/Rattus_norvegicus_UCSC_rn4.tar.gz\">rn4</A></TD>\n<TD ALIGN=\"RIGHT\">13710 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 22:32</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=6>Bos taurus</TD>\n<TD ALIGN=\"LEFT\" rowspan=2>Ensembl</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Bos_taurus/Ensembl/Btau_4.0/Bos_taurus_Ensembl_Btau_4.0.tar.gz\">Btau_4.0</A></TD>\n<TD ALIGN=\"RIGHT\">13315 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 14:18</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Bos_taurus/Ensembl/UMD3.1/Bos_taurus_Ensembl_UMD3.1.tar.gz\">UMD3.1</A></TD>\n<TD ALIGN=\"RIGHT\">14042 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 12:41</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=3>NCBI</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Bos_taurus/NCBI/Btau_4.2/Bos_taurus_NCBI_Btau_4.2.tar.gz\">Btau_4.2</A></TD>\n<TD ALIGN=\"RIGHT\">13357 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 14:11</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Bos_taurus/NCBI/Btau_4.6.1/Bos_taurus_NCBI_Btau_4.6.1.tar.gz\">Btau_4.6.1</A></TD>\n<TD ALIGN=\"RIGHT\">13448 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 16:09</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Bos_taurus/NCBI/UMD_3.1/Bos_taurus_NCBI_UMD_3.1.tar.gz\">UMD_3.1</A></TD>\n<TD ALIGN=\"RIGHT\">13990 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 16:08</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=1>UCSC</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Bos_taurus/UCSC/bosTau4/Bos_taurus_UCSC_bosTau4.tar.gz\">bosTau4</A></TD>\n<TD ALIGN=\"RIGHT\">13386 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 12:36</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=4>Canis familiaris</TD>\n<TD ALIGN=\"LEFT\" rowspan=1>Ensembl</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Canis_familiaris/Ensembl/BROADD2/Canis_familiaris_Ensembl_BROADD2.tar.gz\">BROADD2</A></TD>\n<TD ALIGN=\"RIGHT\">13087 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 18:00</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=2>NCBI</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Canis_familiaris/NCBI/build2.1/Canis_familiaris_NCBI_build2.1.tar.gz\">build2.1</A></TD>\n<TD ALIGN=\"RIGHT\">12847 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 19:22</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Canis_familiaris/NCBI/build3.1/Canis_familiaris_NCBI_build3.1.tar.gz\">build3.1</A></TD>\n<TD ALIGN=\"RIGHT\">12528 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 19:30</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=1>UCSC</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Canis_familiaris/UCSC/canFam2/Canis_familiaris_UCSC_canFam2.tar.gz\">canFam2</A></TD>\n<TD ALIGN=\"RIGHT\">13138 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 17:50</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=4>Gallus gallus</TD>\n<TD ALIGN=\"LEFT\" rowspan=1>Ensembl</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Gallus_gallus/Ensembl/WASHUC2/Gallus_gallus_Ensembl_WASHUC2.tar.gz\">WASHUC2</A></TD>\n<TD ALIGN=\"RIGHT\">5547 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 12:30</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=2>NCBI</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Gallus_gallus/NCBI/build2.1/Gallus_gallus_NCBI_build2.1.tar.gz\">build2.1</A></TD>\n<TD ALIGN=\"RIGHT\">5592 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 13:08</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Gallus_gallus/NCBI/build3.1/Gallus_gallus_NCBI_build3.1.tar.gz\">build3.1</A></TD>\n<TD ALIGN=\"RIGHT\">5469 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 13:18</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=1>UCSC</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Gallus_gallus/UCSC/galGal3/Gallus_gallus_UCSC_galGal3.tar.gz\">galGal3</A></TD>\n<TD ALIGN=\"RIGHT\">5546 MB</TD>\n<TD ALIGN=\"LEFT\">May 14 11:52</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=6>Drosophila melanogaster</TD>\n<TD ALIGN=\"LEFT\" rowspan=2>Ensembl</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Drosophila_melanogaster/Ensembl/BDGP5/Drosophila_melanogaster_Ensembl_BDGP5.tar.gz\">BDGP5</A></TD>\n<TD ALIGN=\"RIGHT\">669 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 19:35</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Drosophila_melanogaster/Ensembl/BDGP5.25/Drosophila_melanogaster_Ensembl_BDGP5.25.tar.gz\">BDGP5.25</A></TD>\n<TD ALIGN=\"RIGHT\">692 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 19:32</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=3>NCBI</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Drosophila_melanogaster/NCBI/build4.1/Drosophila_melanogaster_NCBI_build4.1.tar.gz\">build4.1</A></TD>\n<TD ALIGN=\"RIGHT\">701 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 19:38</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Drosophila_melanogaster/NCBI/build5/Drosophila_melanogaster_NCBI_build5.tar.gz\">build5</A></TD>\n<TD ALIGN=\"RIGHT\">701 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 19:41</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Drosophila_melanogaster/NCBI/build5.3/Drosophila_melanogaster_NCBI_build5.3.tar.gz\">build5.3</A></TD>\n<TD ALIGN=\"RIGHT\">674 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 19:40</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=1>UCSC</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Drosophila_melanogaster/UCSC/dm3/Drosophila_melanogaster_UCSC_dm3.tar.gz\">dm3</A></TD>\n<TD ALIGN=\"RIGHT\">763 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 19:28</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=4>Arabidopsis thaliana</TD>\n<TD ALIGN=\"LEFT\" rowspan=2>Ensembl</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Arabidopsis_thaliana/Ensembl/TAIR9/Arabidopsis_thaliana_Ensembl_TAIR9.tar.gz\">TAIR9</A></TD>\n<TD ALIGN=\"RIGHT\">710 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 10:47</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Arabidopsis_thaliana/Ensembl/TAIR10/Arabidopsis_thaliana_Ensembl_TAIR10.tar.gz\">TAIR10</A></TD>\n<TD ALIGN=\"RIGHT\">679 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 10:46</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=2>NCBI</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Arabidopsis_thaliana/NCBI/build9.1/Arabidopsis_thaliana_NCBI_build9.1.tar.gz\">build9.1</A></TD>\n<TD ALIGN=\"RIGHT\">721 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 10:51</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Arabidopsis_thaliana/NCBI/TAIR10/Arabidopsis_thaliana_NCBI_TAIR10.tar.gz\">TAIR10</A></TD>\n<TD ALIGN=\"RIGHT\">658 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 10:51</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=6>Caenorhabditis elegans</TD>\n<TD ALIGN=\"LEFT\" rowspan=2>Ensembl</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Caenorhabditis_elegans/Ensembl/WS210/Caenorhabditis_elegans_Ensembl_WS210.tar.gz\">WS210</A></TD>\n<TD ALIGN=\"RIGHT\">597 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 16:16</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Caenorhabditis_elegans/Ensembl/WS220/Caenorhabditis_elegans_Ensembl_WS220.tar.gz\">WS220</A></TD>\n<TD ALIGN=\"RIGHT\">560 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 16:17</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=2>NCBI</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Caenorhabditis_elegans/NCBI/WS190/Caenorhabditis_elegans_NCBI_WS190.tar.gz\">WS190</A></TD>\n<TD ALIGN=\"RIGHT\">566 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 16:21</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Caenorhabditis_elegans/NCBI/WS195/Caenorhabditis_elegans_NCBI_WS195.tar.gz\">WS195</A></TD>\n<TD ALIGN=\"RIGHT\">554 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 16:21</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=2>UCSC</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Caenorhabditis_elegans/UCSC/ce6/Caenorhabditis_elegans_UCSC_ce6.tar.gz\">ce6</A></TD>\n<TD ALIGN=\"RIGHT\">617 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 16:13</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Caenorhabditis_elegans/UCSC/ce10/Caenorhabditis_elegans_UCSC_ce10.tar.gz\">ce10</A></TD>\n<TD ALIGN=\"RIGHT\">552 MB</TD>\n<TD ALIGN=\"LEFT\">May 11 16:12</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=7>Saccharomyces cerevisiae</TD>\n<TD ALIGN=\"LEFT\" rowspan=3>Ensembl</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Saccharomyces_cerevisiae/Ensembl/EF2/Saccharomyces_cerevisiae_Ensembl_EF2.tar.gz\">EF2</A></TD>\n<TD ALIGN=\"RIGHT\">74 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 22:35</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Saccharomyces_cerevisiae/Ensembl/EF3/Saccharomyces_cerevisiae_Ensembl_EF3.tar.gz\">EF3</A></TD>\n<TD ALIGN=\"RIGHT\">72 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 22:35</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Saccharomyces_cerevisiae/Ensembl/EF4/Saccharomyces_cerevisiae_Ensembl_EF4.tar.gz\">EF4</A></TD>\n<TD ALIGN=\"RIGHT\">71 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 22:34</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=2>NCBI</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Saccharomyces_cerevisiae/NCBI/build2.1/Saccharomyces_cerevisiae_NCBI_build2.1.tar.gz\">build2.1</A></TD>\n<TD ALIGN=\"RIGHT\">70 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 22:36</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Saccharomyces_cerevisiae/NCBI/build3.1/Saccharomyces_cerevisiae_NCBI_build3.1.tar.gz\">build3.1</A></TD>\n<TD ALIGN=\"RIGHT\">70 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 22:36</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\" rowspan=2>UCSC</TD>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Saccharomyces_cerevisiae/UCSC/sacCer2/Saccharomyces_cerevisiae_UCSC_sacCer2.tar.gz\">sacCer2</A></TD>\n<TD ALIGN=\"RIGHT\">70 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 22:34</TD>\n</TR>\n<TR>\n<TD ALIGN=\"LEFT\"><A HREF=\"ftp://igenome:G3nom3s4u@ussd-ftp.illumina.com/Saccharomyces_cerevisiae/UCSC/sacCer3/Saccharomyces_cerevisiae_UCSC_sacCer3.tar.gz\">sacCer3</A></TD>\n<TD ALIGN=\"RIGHT\">70 MB</TD>\n<TD ALIGN=\"LEFT\">May 15 22:33</TD>\n</TR>\n</TABLE>\n  </div>\n    <br/>\n    <br/>\n\n  <div id=\"footer\">\n    <table width=\"100%\" cellspacing=15><tr><td>\n    This research was supported in part by NIH grants R01-LM06845 and R01-GM083873 and NSF grant CCF-0347992.\n    </td><td align=right>\n    Administrator: <a href=\"mailto:cole@cs.umd.edu\">Cole Trapnell</a>. Design by <a href=\"http://www.free-css-templates.com\" title=\"Design by David Herreman\">David Herreman</a>\n    </td></tr></table>\n  </div>\n</div>\n\n<!-- Google analytics code -->\n<script type=\"text/javascript\">\nvar gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\ndocument.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n</script>\n<script type=\"text/javascript\">\nvar pageTracker = _gat._getTracker(\"UA-6101038-1\");\npageTracker._trackPageview();\n</script>\n\n<!-- End google analytics code -->\n\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/index.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n  <head>\r\n    <title>Cufflinks - Transcript assembly, differential expression, and\r\n          differential regulation for RNA-Seq</title>\r\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\r\n\t<meta name=\"description\" content=\"Open source tools for transcript assembly, differential expression, and\r\n        differential regulation for RNA-Seq\">\r\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\"\r\n      media=\"screen\">\r\n  </head>\r\n  <body>\r\n    <div id=\"wrap\">\r\n      <div id=\"top\">\r\n        <div class=\"lefts\">\r\n          <table cellpadding=\"2\" width=\"100%\">\r\n            <tbody>\r\n              <tr>\r\n                <td> <a href=\"./index.html\">\r\n                    <h1>Cufflinks</h1>\r\n                  </a>\r\n                  <h2>Transcript assembly, differential expression, and\r\n                    differential regulation for RNA-Seq</h2>\r\n                </td>\r\n                <td align=\"right\" valign=\"middle\"> \r\n                    <a href=\"http://bio.math.berkeley.edu/\">\r\n                    <img style=\"vertical-align:middle;padding-top:4px\"\r\n                      src=\"images/UCBerkeley-seal.scaled.gif\" border=\"0\">\r\n                    </a>&nbsp;\r\n                    <a href=\"http://genomics.jhu.edu/\">\r\n                    <img style=\"vertical-align:middle;padding-top:4px\"\r\n                      src=\"images/JHU-seal.gif\" border=\"0\">\r\n                    </a>&nbsp;\r\n\r\n                  <a href=\"http://www.cbcb.umd.edu/\"><img\r\n                      style=\"vertical-align:middle;padding-top:4px\"\r\n                      src=\"images/cbcb_logo.gif\" border=\"0\"></a>&nbsp;&nbsp;\r\n\r\n                </td>\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n        </div>\r\n      </div>\r\n      <div id=\"subheader\">\r\n        <table width=\"100%\">\r\n          <tbody>\r\n            <tr>\r\n              <td> <strong>Cufflinks</strong> assembles transcripts,\r\n                estimates their abundances, and tests for <b>differential\r\n                  expression</b> and <b>regulation</b> in RNA-Seq\r\n                samples. It accepts aligned RNA-Seq reads and assembles\r\n                the alignments into a parsimonious set of transcripts.\r\n                Cufflinks then estimates the relative abundances of\r\n                these transcripts based on how many reads support each\r\n                one, taking into account biases in library preparation\r\n                protocols. <br>\r\n                <br>\r\n                Cufflinks is a collaborative effort between the <a\r\n                  href=\"http://bio.math.berkeley.edu/\">Laboratory for\r\n                  Mathematical and Computational Biology</a>, led by\r\n                Lior Pachter at UC Berkeley, Steven Salzberg's \r\n                <a href=\"http://genomics.jhu.edu\">computational genomics group</a>\r\n                 at the Institute of Genetic Medicine at Johns Hopkins University, and\r\n                <a href=\"http://woldlab.caltech.edu/\">Barbara Wold's lab</a>\r\n                at Caltech. <br>\r\n                <br>\r\n                Cufflinks is provided under the OSI-approved <a\r\n                  href=\"http://en.wikipedia.org/wiki/Boost_Software_License\">Boost\r\n                  License</a> </td>\r\n              <td align=\"right\" valign=\"middle\"> <a\r\n                  href=\"http://opensource.org\"><img alt=\"Open Source\r\n                    Software\" src=\"images/osi-certified.gif\" border=\"0\"></a>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n      <div id=\"main\">\r\n        <div id=\"rightside\">\r\n\t\r\n          <h2>Site Map</h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <li><a href=\"index.html\">Home</a></li>\r\n              <li><a href=\"tutorial.html\">Getting started</a></li>\r\n              <li><a href=\"manual.html\">Manual</a></li>\r\n              <li><a href=\"howitworks.html\">How Cufflinks works</a></li>\r\n\t\t\t  <li><a href=\"igenomes.html\">Index and annotation downloads</a></li>\r\n              <li><a href=\"faq.html\">FAQ</a></li>\r\n\t\t\t  <li><a href=\"http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html\">Protocol</a></li>\r\n\t\t\t  <li><a href=\"report.html\">Benchmarking</a></li>\r\n            </ul>\r\n          </div>\r\n\r\n          <h2><u>News and updates</u></h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <table width=\"100%\">\r\n                <tbody>\r\n                  <tr>\r\n                    <td>New releases and related tools will be announced\r\n                      through the <a\r\n                        href=\"https://lists.sourceforge.net/lists/listinfo/bowtie-bio-announce\"><b>mailing\r\n                          list</b></a></td>\r\n                  </tr>\r\n                </tbody>\r\n              </table>\r\n            </ul>\r\n          </div>\r\n          <h2><u>Getting Help</u></h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <table width=\"100%\">\r\n                <tbody>\r\n                  <tr>\r\n                    <td>Questions about Cufflinks and Cuffdiff should be posted on our <a href=\"https://groups.google.com/forum/#!forum/tuxedo-tools-users\"><b>Google Group</b></a>. Please use <a\r\n                        href=\"mailto:tophat.cufflinks@gmail.com\">tophat.cufflinks@gmail.com</a> for private communications only.\r\n                      Please do not email technical questions to\r\n                      Cufflinks contributors directly.</td>\r\n                  </tr>\r\n                </tbody>\r\n              </table>\r\n            </ul>\r\n          </div>\r\n       \r\n          <a href=\"./downloads\">\r\n            <h2><u>Releases</u></h2>\r\n          </a>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <table width=\"100%\">\r\n                <tbody>\r\n                  <tr>\r\n                    <td>version 2.2.0</td>\r\n                    <td align=\"right\">5/25/2014</td>\r\n                  </tr>\r\n                  <tr>\r\n                    <td><a href=\"./downloads/cufflinks-2.2.0.tar.gz\"\r\n                        onclick=\"javascript:\r\n                        pageTracker._trackPageview('/downloads/cufflinks_source');\r\n                        \">&nbsp;&nbsp;&nbsp;Source code</a></td>\r\n                  </tr>\r\n                  <tr>\r\n                    <td><a\r\n                        href=\"./downloads/cufflinks-2.2.0.Linux_x86_64.tar.gz\"\r\n                        onclick=\"javascript:\r\n                        pageTracker._trackPageview('/downloads/cufflinks');\r\n                        \">&nbsp;&nbsp;&nbsp;Linux x86_64 binary</a></td>\r\n                  </tr>\r\n                  <tr>\r\n                    <td><a\r\n                        href=\"./downloads/cufflinks-2.2.0.OSX_x86_64.tar.gz\"\r\n                        onclick=\"javascript:\r\n                        pageTracker._trackPageview('/downloads/cufflinks');\r\n                        \">&nbsp;&nbsp;&nbsp;Mac OS X x86_64 binary</a></td>\r\n                  </tr>\r\n                </tbody>\r\n              </table>\r\n            </ul>\r\n          </div>\r\n          \r\n\r\n\r\n\t\t  <h2>Related Tools</h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n                <li><a href=\"http://monocle-bio.sourceforge.net\">Monocle</a>:\r\n                  Single-cell RNA-Seq analysis</li>\r\n\t\t\t\t<li><a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a>:\r\n\t                Visualization of RNA-Seq differential analysis</li>\r\n              <li><a href=\"http://tophat.cbcb.umd.edu/\">TopHat</a>:\r\n                Alignment of short RNA-Seq reads</li>\r\n              <li><a href=\"http://bowtie.cbcb.umd.edu\">Bowtie</a>:\r\n                Ultrafast short read alignment</li>\r\n            </ul>\r\n          </div>\r\n\r\n\r\n          <h2>Publications</h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <li style=\"font-size: x-small; line-height: 130%\">\r\n                <p>Trapnell C, Williams BA, Pertea G, Mortazavi AM, Kwan\r\n                  G, van Baren MJ, Salzberg SL, Wold B, Pachter L.<b> <a\r\n                      href=\"http://dx.doi.org/10.1038/nbt.1621\">Transcript\r\n                      assembly and quantification by RNA-Seq reveals\r\n                      unannotated transcripts and isoform switching\r\n                      during cell differentiation</a></b> <br>\r\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\r\n                      Biotechnology</a></i> doi:10.1038/nbt.1621</p>\r\n                <br>\r\n              </li>\r\n              <li style=\"font-size: x-small; line-height: 130%\">\r\n                <p>Roberts A, Trapnell C, Donaghey J, Rinn JL, Pachter\r\n                  L.<b> <a\r\n                      href=\"http://genomebiology.com/2011/12/3/R22/abstract\">Improving\r\n                      RNA-Seq expression estimates by correcting for\r\n                      fragment bias</a></b> <br>\r\n                  <i><a href=\"http://www.genomebiology.com\">Genome\r\n                      Biology</a></i> doi:10.1186/gb-2011-12-3-r22</p>\r\n                <br>\r\n              </li>\r\n              <li style=\"font-size: x-small; line-height: 130%\">\r\n                <p>Roberts A, Pimentel H, Trapnell C, Pachter\r\n                  L.<b> <a\r\n                      href=\"http://bioinformatics.oxfordjournals.org/content/early/2011/06/21/bioinformatics.btr355.abstract\">\r\n                      Identification of novel transcripts in annotated genomes using RNA-Seq</a></b> <br>\r\n                  <i><a href=\"http://bioinformatics.oxfordjournals.org/\">Bioinformatics</a></i> doi:10.1093/bioinformatics/btr355</p>\r\n                <br>\r\n              </li>\r\n\t\t\t  <li style=\"font-size: x-small; line-height: 130%\">\r\n                <p>Trapnell C, Hendrickson D,Sauvageau S, Goff L, Rinn JL, Pachter L<b> <a\r\n                      href=\"http://dx.doi.org/10.1038/nbt.2450\">Differential \r\n\t\t\t\t\t analysis of gene regulation at transcript resolution with RNA-seq\r\n\t\t\t\t\t</a></b> <br>\r\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\r\n                      Biotechnology</a></i> doi:10.1038/nbt.2450</p>\r\n                <br>\r\n              </li>\r\n            </ul>\r\n          </div>\r\n          <h2>Contributors</h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <li><a href=\"http://www.cs.umd.edu/%7Ecole/\">Cole Trapnell</a></li>\r\n              <li><a href=\"http://www.cs.berkeley.edu/%7Eadarob/\">Adam\r\n                  Roberts</a></li>\r\n              <li>Geo Pertea</li>\r\n\t\t\t  <li>David Hendrickson<li>\r\n\t\t\t  <li>Loyal Goff</li>\r\n\t\t\t  <li>Martin Sauvageau</li>\r\n              <li>Brian Williams</li>\r\n              <li><a href=\"http://wormlab.caltech.edu/members/\">Ali\r\n                  Mortazavi</a></li>\r\n              <li>Gordon Kwan</li>\r\n              <li>Jeltje van Baren</li>\r\n\t\t\t  <li><a href=\"http://www.rinnlab.com\">John Rinn</a></li>\r\n              <li><a href=\"http://www.cbcb.umd.edu/%7Esalzberg/\">Steven\r\n                  Salzberg</a></li>\r\n              <li><a href=\"http://biology.caltech.edu/Members/Wold\">Barbara\r\n                  Wold</a></li>\r\n              <li><a href=\"http://www.math.berkeley.edu/%7Elpachter/\">Lior\r\n                  Pachter</a></li>\r\n            </ul>\r\n          </div>\r\n          <h2>Links</h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <li><a href=\"http://bio.math.berkeley.edu/\">Berkeley LMCB</a></li>\r\n              <li><a href=\"http://www.cbcb.umd.edu/\">UMD CBCB</a></li>\r\n              <li><a href=\"http://woldlab.caltech.edu/\">Wold Lab</a></li>\r\n            </ul>\r\n          </div>\r\n        </div>\r\n        <!-- End of \"rightside\" -->\r\n        <div id=\"leftside\">\r\n\t\t\t<h2>2.2.0 release - 3/25/2014</h2>\r\n\t\t\t<p>This release introduces some new features designed to simplify and speed up Cufflinks workflows. Release version 2.2.0 includes two new programs, <a href=\"manual.html#cuffquant\"><tt>cuffquant</tt></a> and <a href=\"manual.html#cuffnorm\"><tt>cuffnorm</tt></a> that make it easier to quantify gene expression in experiments with many samples. These are particularly helpful for single cell RNA-Seq experiments, where the reads for each cell are provided as a separate FASTQ file or pair of files.\r\n\t\t\t<p>Release 2.2.0 also introduces <a href=\"manual.html#sample_sheets\"><strong>sample sheets</strong></a> and <a href=\"manual.html#contrast_files\"><strong>contrast files</strong></a>. These facilities make it easier to work with large analyses involving many samples.\r\n\t\t\t<p>Cuffquant quantifies gene and transcript expression levels for a single BAM file.  These levels are stored in a new binary file type, the CXB file.  You can then provide CXB files for your samples directly to Cuffdiff instead of BAMs.  Mixing BAM and CXB files is not yet supported.  Because expression levels for each sample are quantified by Cuffquant, Cuffdiff doesn't have to perform this step, which speeds up Cuffdiff runs substantially and lowers their memory footprints. We recommend that most users switch to this new Cuffdiff workflow for all experiments that involve more than a few samples.  However, note that running Cuffquant prior to running Cuffdiff is <strong>optional</strong> - you can still directly supply BAM files to Cuffdiff.\r\n\t\t\t\t</p>\r\n\t\t\t<p>Cuffquant files can also be passed to Cuffnorm, which simply computes a normalized table of expression values for genes and transcripts.  Unlike Cuffdiff, Cuffnorm performs no differential expression testing.  Cuffnorm also does not calculate confidence intervals on expression values.  Cuffnorm is meant to be used when all you want is a set of comparable expression values for genes, transcripts, CDS groups, and TSS groups, such as when you simply want to make heatmaps or dendrograms or plot values for individual genes.  Cuffnorm can output values in one of two formats: Cuffdiff tracking tables (which can be used with <a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a>), or in simple, tab-delimited tables.  The latter is the recommended output format for use with <a href=\"http://monocle-bio.sourceforge.net/\">Monocle</a> in single cell RNA-Seq experiments.\r\n\t\t\t</p>\r\n\t\t\t<p> Here's an overview of the new (optional) workflow, compared to the old workflow described in our Nature Protocols paper:<img style=\"vertical-align:middle;padding-top:4px; display: block; margin-left: auto; margin-right: auto;\"\r\n          border=0 src=\"images/tuxedo_workflow.png\">\r\n\t\t\t\t\r\n\t\t\t<br/>\r\n\t\t\t<br/>\r\n\t\t\t<h2>2.1.1 release - 4/11/2013</h2>\r\n\t\t\t<p>This release fixes a bug introduced with version 2.1.0, which for some users caused Cufflinks to output empty transcript GTF files.\r\n\t\t\t\t</p>\r\n\t\t\t<br/>\r\n\t\t\t<h2>2.1.0 release - 4/10/2013</h2>\r\n\t\t\t\t<p>\r\n\t\t\t\t\tThis release substantially improves the accuracy, speed, and memory footprint of Cufflinks and Cuffdiff.  It is recommended for all users. Those who wish to see the impact of the accuracy improvements should look at the new <a href=\"report.html\">benchmarking</a> section.  In addition to numerous bugfixes, the main changes are as follows:\r\n\t\t\t\t<ul>\r\n\t\t\t\t\t<li>Cuffdiff now includes a new statistical test.  Prior versions used a delta method-based test, which lacked power for designs with more than a few replicates.  The new test directly samples from the beta negative binomial model for each transcript in each condition in order to estimate the null distribution of its log fold change under the null hypothesis.  This test is substantially more powerful, resulting in improved accuracy over all experimental designs, particularly those with more than three replicates. A similarly improved test is now used for isoform-switching. The <a href=\"report.html\">benchmarking</a> page shows the improvements in detail. \r\n\t\t\t\t\t\t<li>Prior versions of Cuffdiff reported the FPKM for each gene and transcript that maximizes the joint likelihood of the reads from all replicates pooled together.  In version 2.1, Cuffdiff instead reports the mean of the maximum likelihood estimates from each replicate processed independently.  As shown in the benchmarking section, these two methods report nearly identical values.  However, the new method is faster and simpler to compute, and will enable new features for future releases.\r\n\t\t\t\t\t<li>The high and low confidence intervals reported by Cufflinks and Cuffdiff are now constructed from the samples generated from the beta negative binomial model, rather than estimated as twice the standard deviation.  This better reflects the underlying distribution of the FPKM.\r\n\t\t\t\t\t<li>The library normalization system in Cuffdiff 2 has been overhauled, and several new normalization-related options have been added:\r\n\t\t\t\t\t\t<ul>\r\n\t\t\t\t\t\t\t<li>The new <tt>--library-norm-method</tt> option now sets which method should be used to compute scaling factors for the library sizes.  The default method <tt>geometric</tt> is the same as prior releases of Cuffdiff (and the same as DESeq). The optional modes <tt>quartile</tt> and <tt>classic-fpkm</tt> are also supported.\r\n\t\t\t\t\t\t\t<li>The new <tt>--dispersion-method</tt> option controls how the variance model should be computed for each condition.  The default mode <tt>pooled</tt> computes a mean-variance model for each condition that has multiple replicates, averages these models to generate a \"pooled\" average, and uses it for all conditions.  This policy is borrowed from DESeq. Alternative models <tt>blind</tt> and <tt>per-condition</tt> are also supported. Prior versions of Cuffdiff used the method <tt>per-condition</tt>.\r\n\t\t\t\t\t\t\t<li>Several bugs for quartile normalization have been fixed.\r\n\t\t\t\t\t\t\t<li>Quartile normalization is no longer supported in Cufflinks, just in Cuffdiff.  Cufflinks only supports the <tt>classic-fpkm</tt> mode. \r\n\t\t\t\t\t\t\t<li>All library size normalization is now conducted through the internal scaling factor. The external scaling factor should always be set to 1.0.\r\n\t\t\t\t\t\t\t<li>Library sizes and dispersions are now computed only on fragment counts from compatible fragments.  Prior versions counted intronic and other structurally incompatible fragments in some sections of the code.\r\n\t\t\t\t\t\t</ul>\r\n\t\t\t\t\t</li>\r\n\t\t\t\t\t<li>An optimized sampling procedure drastically improves running time for Cuffdiff.  Cufflinks also benefits from this change.  The improvements are particularly noticeable on deeply sequenced libraries.\r\n\t\t\t\t\t<li>The range of p-values that users should expect from Cuffdiff has changed.  Because the test is now based on explicit sampling from the beta negative binomial, users will not see values less than 10^-5 by default. The <tt>test_stat</tt> field of Cuffdiff's output still contains the  delta method's test statistic, but this test statistic is not used to compute p-values.  It is preserved for backward compatibility with some functions in <a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a>.\r\n\t\t\t\t\t<li>Some extraneous temporary output files have been removed after Cuffmerge runs.\r\n\t\t\t\t</ul>\t\r\n\t\t\t\t</p>\r\n\t\t\t\t<br/>\r\n\t\t\t\t\r\n\t\t\t<h2>New google group for TopHat, Cufflinks, and CummeRbund users - 4/11/2013</h2>\r\n\t\t\t<p>To better handle the many questions we receive from users, we have launched a new google group for discussion and questions about our tools. We are simply unable to handle the email we receive, and our hope is that the users of of the group will help each other.  While we will continue to answer email sent to <a href=\"mailto:tophat.cufflinks@gmail.com\">tophat.cufflinks@gmail.com</a> as we have time, we will also answer questions posted to the group, and the latter questions will be prioritized.  Please post questions or comments to the group (if your question hasn't already been asked and answered) before emailing <a href=\"mailto:tophat.cufflinks@gmail.com\">tophat.cufflinks@gmail.com</a>.  \r\n\t\t\t</p>\r\n\t\t\t<br/>\r\n\t\t\t\r\n\t\t\t<h2>TransDecoder: calling novel ORFs in RNA-Seq assemblies- 4/11/2013</h2>\r\n\t\t\t<p>Our friend <a href=\"http://www.broadinstitute.org/~bhaas/\">Brian Haas</a> (of <a href=\"http://trinityrnaseq.sourceforge.net/\">Trinity</a> fame) has written a tool that might be helpful to Cufflinks users wishing to discover new coding genes and splice variants.  TransDecoder takes as input an assembly of RNA-Seq reads from Trinity, Cufflinks, and other tools and produces predictions about likely open reading frames as output.  http://transdecoder.sourceforge.net/\r\n\t\t\t</p>\r\n\t\t\t<br/>\r\n\t\t\t<h2>Cuffdiff 2 manuscript published at <em>Nature Biotechnology</em> - 12/11/2012</h2>\r\n\t\t\t\t<p>\r\n\t\t\t\tWe are happy to announce a <a href=\"http://dx.doi.org/10.1038/nbt.2450\">new manuscript</a> describing Cuffdiff 2 \r\n\t\t\t\thas appeared in print at <em>Nature Biotechnology</em>. The manuscript\r\n\t\t\t\tcontains performance assessments of Cuffdiff 2 and a detailed \r\n\t\t\t\tcomparison of our methods against other tools for differential\r\n\t\t\t\tanalysis.\r\n\t\t\t\t</p>\r\n\t\t\t\t<br/>\r\n\t\r\n\t\t\t<h2>2.0.2 release - 7/8/2012</h2>\r\n\t\t\t\t<p>This release fixes several bugs:\r\n\t\t\t\t<ul>\r\n\t\t\t\t\t<li>Some users were experiencing a crash on exit in Cufflinks when run with bias correction. The source of the crash has been fixed.\r\n\t\t\t\t\t<li>A few minor fixes in the estimation routines for cross-replicate variability.\r\n\t\t\t\t\t<li>Providing the same BAM file multiple times was producing inconsistent expression values.  This has been corrected.\r\n\t\t\t\t</ul>\r\n\t\t\t\t</p>\r\n\t\t\t\t<br/>\r\n\t\r\n\t\t\t<h2>2.0.1 release - 6/15/2012</h2>\r\n\t\t\t\t<p>This release addresses several bugs, most of which were introduced as \r\n\t\t\t\tpart of the 2.0.0 release:\r\n\t\t\t\t<ul>\r\n\t\t\t\t\t<li>Some users were experiencing a problem with the Linux \r\n\t\t\t\t\t\tpre-compiled binary packages where Cuffdiff was reporting\r\n\t\t\t\t\t\tmany genes and transcripts as having expression levels of\r\n\t\t\t\t\t\tzero or \"nan\" or \"inf\".  This was determined to be caused \r\n\t\t\t\t\t\tby a recent change in the binary packaging process we use \r\n\t\t\t\t\t\tto distribute pre-compiled binaries.  \r\n\t\t\t\t\t<li>Multi-read correction in Cuffdiff 2.0 was not always being\r\n\t\t\t\t\t\tapplied when the user specified <tt>-u/--multi-read-correct</tt>.\r\n\t\t\t\t\t<li>Some rarely encountered GTF parsing issues have been corrected.\r\n\t\t\t\t\t<li>Effective length correction can be disabled in Cufflinks \r\n\t\t\t\t\t\tand Cuffdiff with the new <tt>--no-effective-length-correction</tt> option.\r\n\t\t\t\t</ul>\r\n\t\t\t\t</p>\r\n\t\t\t\t<br/>\r\n\t\t\t\r\n\t\t\t<h2> Illumina iGenomes now include both Bowtie1 and Bowtie2 indexes - 5/23/2012</h2>\r\n\t\t\t\t  <br/>\r\n\t\t\t\t\r\n\t\t\t<h2>2.0.0 release - 5/4/2012</h2>\r\n\t\t\t  <p>This release substantially improves the accuracy and robustness of \r\n\t\t\t\tdifferential analysis with Cuffdiff. The update also  \r\n\t\t\t\tresolves several user-reported issues and bugs, and several requested features.  \r\n\t\t\t\tDue to the large number of enchancements and fixes, users are \r\n\t\t\t\tencouraged to treat this as a beta release.  A manuscript \r\n\t\t\t\tdescribing the algorithmic improvements to the software is in preparation. Changes include:\r\n\t\t\t\t<ul>\r\n\t\t\t\t\t<li>Cuffdiff now reports estimated counts assigned to each gene and transcript, \r\n\t\t\t\t\t\talong with count variances due to uncertainty and cross-replicate variability. \r\n\t\t\t\t\t\tSee the <a href=\"manual.html#count_tracking_format\">manual</a> for \r\n\t\t\t\t\t\tmore details on the new count tracking file format. \r\n\t\t\t\t\t\tCount tracking is not yet available in Cufflinks (e.g. with the -G option), \r\n\t\t\t\t\t\tbut this functionality will be ported over in a future release.\r\n\t\t\t\t    <li>Cuffdiff now tracks and records per-replicate FPKMs and counts. See the manual for\r\n\t\t\t\t\t\tmore details on the new replicate tracking files. A version of \r\n\t\t\t\t\t\t<a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a> \r\n\t\t\t\t\t\tthat exposes this information in many plot types will be forthcoming.\r\n\t\t\t\t\t<li>Cuffdiff reports replicate and run metadata as part of each run.\r\n\t\t\t\t\t<li>Some users were reporting a high FAIL rate on gene and\r\n\t\t\t\t\t\ttranscripts quantification.  This has been resolved \r\n\t\t\t\t\t\taccording to a battery of tests using real and simulated data.  \r\n\t\t\t\t\t\tThe root cause was that in conditions with substantial\r\n\t\t\t\t\t\toverdispersion across replicates, the FPKM variance-covariance \r\n\t\t\t\t\t\tmatrices  produced by the Cuffdiff model were not always \r\n\t\t\t\t\t\tpositive-definite.  Cuffdiff was detecting this, \r\n\t\t\t\t\t\tand marking those genes as having unreliable confidence intervals. \r\n\t\t\t\t\t\tPrior to 2.0.0, the model contained a heuristic approximation of the \r\n\t\t\t\t\t\tcovariances between assigned fragment counts (which are necessary \r\n\t\t\t\t\t\tfor calculating the variance on each gene's expression level),\r\n\t\t\t\t\t\tand this approximation was producing poorly conditioned matrices. \r\n\t\t\t\t\t\tWe have replaced the heuristic approximation with a direct sampling \r\n\t\t\t\t\t\tapproach, in effect \"simulating\" the assignment of fragments \r\n\t\t\t\t\t\tto each isoform many times for each gene.  \r\n\t\t\t\t\t\tBy simulating fragment generation and assignment to each transcript, \r\n\t\t\t\t\t\twe are reconstructing variance-covariance matrices for assigned fragment \r\n\t\t\t\t\t\tcounts that are always properly condition.  This sampling \r\n\t\t\t\t\t\tapproach produces more accurate estimates of variance and covariance as well, \r\n\t\t\t\t\t\timproving accuracy of transcript and gene level differential analysis. \r\n\t\t\t\t\t\tUsers should expect more accurate quantification and shorter, \r\n\t\t\t\t\t\tmore conservative lists of differentially expressed genes and trasncripts. \r\n\t\t\t\t\t<li>After substantial performance testing, we have determined that\r\n\t\t\t\t\t\tthe false discovery rate of Jensen-Shannon-based tests \r\n\t\t\t\t\t\t(differential splicing, CDS switching, and promoter switching) can be \r\n\t\t\t\t\t\tunnacceptably high when used with fewer than three replicates in the\r\n\t\t\t\t\t\tconditions being compared.  Cuffdiff now refrains from \r\n\t\t\t\t\t\tperforming significance tests when one of the conditions involved has \r\n\t\t\t\t\t\tfewer than three replicates.  You can change this behavior with the new\r\n\t\t\t\t\t\t<tt>--min-reps-for-js-test</tt> option.  Cuffdiff still produces\r\n\t\t\t\t\t\t<tt>splicing.diff</tt>, <tt>cds.diff</tt>, and <tt>promoters.diff</tt> \r\n\t\t\t\t\t\tregardless of how many replicates you have.  These files will include\r\n\t\t\t\t\t\tthe JS distance scores, but none of the genes will be marked significant if you\r\n\t\t\t\t\t\thave fewer than the required number of replicates.\r\n\t\t\t\t\t<li>Cufflinks and Cuffdiff can now be told to ignore fragments that map \r\n\t\t\t\t\t\tto the genome more than a specified number of times using the \r\n\t\t\t\t\t\t<tt>--max-frag-multihits</tt> option.  By default, Cufflinks \r\n\t\t\t\t\t\tand Cuffdiff still consider all fragments in the alignment file.\r\n\t\t\t\t\t<li>Cufflinks by default doesn't report assembled transfrags that \r\n\t\t\t\t\t\tare built mostly from multiply mapping reads.  \r\n\t\t\t\t\t\tThis behavior can now be controlled or disabled with the \r\n\t\t\t\t\t\tnew <tt>--max-multiread-fraction</tt> option.\r\n\t\t\t\t\t<li>Cufflinks by default fills small gaps in coverage when assembling transcripts.  \r\n\t\t\t\t\t\tGaps smaller than 50bp are filled and the transfrags joined.  \r\n\t\t\t\t\t\tThis behavior can be controlled or disabled with the new \r\n\t\t\t\t\t\t<tt>--overlap-radius</tt> option.\r\n\t\t\t\t\t<li>Before testing for differential expression or regulation of genes and transcripts,\r\n\t\t\t\t\t\tCuffdiff now checks that the variance model for the gene or transcript in question is a good fit.  \r\n\t\t\t\t\t\tThis behavior can be controlled or disabled with the <tt>--min-outlier-p</tt> option.\r\n\t\t\t\t\t\tSee the relevant section in the \"How Cufflinks works\" page for more on this.\r\n\t\t\t\t\t<li>A few bugs in the bias correction code and isoform deconvolution routines have been fixed, improving transcript-level expression accuracy.</li>\r\n\t\t\t\t\t<li>Positional bias correction was reducing accuracy on \r\n\t\t\t\t\t\tcertain datasets in some genes, so we have changed the\r\n\t\t\t\t\t\t default bias correction algorithm to model sequence-specific \r\n\t\t\t\t\t\tbias only.  Bias correction is still disabled by default, \r\n\t\t\t\t\t\tand positional bias correction is still available as an \r\n\t\t\t\t\t\toptional mode.</li>\r\n\t\t\t\t\t<li>Several minor issues related to library size normalization have been fixed.\r\n\t\t\t\t\t<li>A new library size normalization mode based on the \r\n\t\t\t\t\t\tgeometric mean has been added, and is now the default \r\n\t\t\t\t\t\tfor Cuffdiff. This method was introduced by Anders and\r\n\t\t\t\t\t\t Huber (Genome Biology, 2010).\r\n\t\t\t\t\t<li>Cuffdiff now uses the <a href=\"http://eigen.tuxfamily.org\">Eigen</a> \r\n\t\t\t\t\t\tlinear algebra libraries.  Eigen is a fast package for \r\n\t\t\t\t\t\tmatrix operations and makes good use of vector registers \r\n\t\t\t\t\t\tin modern processors, speeding up some of the numerical routines used during abundance estimation.\r\n\t\t\t\t\t<li>Cuffdiff now requires Boost version 1.47 or later.\r\n\t\t\t\t</ul>\r\n\t\t\t  <br/>\r\n\t\r\n\t\t\t<h2>TopHat and Cufflinks protocol published at Nature Protocols - 3/12/2012</h2>\r\n\t\t\t  <p>A complete <a href=\"http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html\">bioinformatic protocol</a> for analysis of RNA-Seq data using our tools \r\n\t\t\t\thas been published at <em>Nature Protocols</em>.  The protocol covers read alignment with TopHat, \r\n\t\t\t\tgene and transcript discovery with Cufflinks, annotation analysis with Cuffmerge and Cuffcompare, \r\n\t\t\t\tdifferential expression analysis with Cuffdiff, and visualization with CummeRbund.  \r\n\t\t\t\tSeveral variants of the protocol are included for those who wish to forgo certain analysis steps, such as gene discovery.\r\n\t\t\t  </p>\r\n\t\t\t  <br/>\r\n\t\t\t<h2>1.3.0 release - 1/2/2012</h2>\r\n\t\t\t  <p>This release improves the accuracy of Cuffdiff's isoform switching tests and fixes several bugs.\r\n\t\t\t\t<ul>\r\n\t\t\t\t\t<li>Cuffdiff find genes that are differentially spliced or switch promoters between conditions using the Jensen-Shannon distance metric. Previous versions of Cuffdiff tested for the signficance of observed shifts in relative isoform abundance using an analytic approximation of the variance of this metric for each gene.  However, when few replicates are available or sequencing is shallow, this approximation can be poor.  This release improves Cuffdiff's accuracy with a computational-derived estimate of the variance of the Jensen-Shannon metric by sampling in each gene.  This improvement substantially reduces the false positive rate of Cuffdiff's tests in <tt>splicing.diff</tt>, <tt>promoters.diff</tt>, and <tt>cds.diff</tt>.  Tests for changes in global expression are not affected.\r\n\t\t\t\t\t<li>A bug in Cuffmerge that caused a crash with a warning about improper sorting of SAM files has been corrected.\r\n\t\t\t\t\t<li>A bug that caused Cuffmerge to drop some reference transcripts from the output has been fixed.\r\n\t\t\t\t\t<li>A few minor issues with Cufflinks' pre-assembly alignment filters have been fixed.\r\n\t\t\t\t</ul>\r\n\t\t\t  <br/>\r\n\t\t\t<h2>1.2.0 release - 11/23/2011</h2>\r\n\t\t\t  <p>This release fixes a number of bugs and includes some signficant accuracy and performance improvements:\r\n\t\t\t\t  <ul>\r\n\t\t\t\t<li>Some users were experiencing a large number of genes or transcripts marked FAIL during Cuffdiff runs or Cufflinks quantification runs.  These were caused by one of several issues.  Most of these genes were due to numerical exceptions generated during importance sampling, a procedure originally intended to improve accuracy of abundance estimates in genes with one or more very low abundance isoforms.  After detailed simulation experiments, we have concluded that the gains in accuracy are minor and do not justify the number of genes that FAIL when this procudure can't be executed.  We have dropped both this routine and the bootstrap check, which can similarly generate FAIL genes under similar conditions. \r\n\t\t\t\t<li>Improvements to FPKM variance estimates for genes and transcripts, resulting in better differential expression accuracy in Cuffdiff.\r\n\t\t\t\t<li>A bug that reduced accuracy in certain abundant genes has been corrected.\r\n\t\t\t\t<li>The <tt>--max-bundle-frags</tt> option, which skips extremely deeply sequenced loci that might otherwise crash the program, has been improved so that those loci are never allowed to fully load into memory.  This improves overall memory footprint and should prevent memory-related crashes.\r\n\t\t\t\t<li>A bug in bias correction that results in \"Inf\" and \"NaN\" values has been fixed.\r\n\t\t\t\t<li>An improved pre-quantification fragment collapse optimization has substantially lowered memory footprint and improved running time for Cuffdiff and Cufflinks abundance estimation.\r\n\t\t\t\t<li>A bug that halts runs on hash-collisions for read names has been fixed.\r\n\t\t\t\t<li>A buffer overflow in the SAM parser has been fixed.\r\n\t\t\t\t<li>Other minor bugfixes and accuracy improvements for quantification.\r\n\t\t\t\t</ul>\r\n\t\t\t  </ul>\r\n\t\t\t  </p>\r\n\t\t\t  <br/>\r\n\t\r\n\t\t\t<h2>CummeRbund released - 11/21/2011</h2>\r\n\t\t\t<p>\r\n\t\t\tExtracting biological insight from transcript-level RNA-Seq analysis can be very challenging. Due to the volume and complexity of output from RNA-Seq analysis pipelines, many users may choose to focus only on gene-level results, and thus miss crucial biological insights that a transcript-level analysis can provide. We are happy to present CummeRbund, an R/Bioconductor package that simplifies the organization, access, exploration, and visualization of the various output files of a Cuffdiff differential expression analysis. CummeRbund begins by re-organizing the Cuffdiff output files, and storing these data in a local SQLite database. During this process, CummeRbund indexes the data to speed up access to specific feature data (genes, isoforms, TSS, CDS, etc.), and preserves the various relationships between these features. Access to data elements is done through R via the RSQLite package and data are presented in appropriately structured R classes with various convenience functions designed to streamline your workflow. \r\n\t\t\t<p>\r\n\t\t\t\tCummeRbund simplifies the way in which you access and analyze your RNA-Seq data. Features include:\r\n\t\t\t\t<ul>\r\n\t\t\t\t<li>Numerous plotting methods to allow for rapid visualization of RNA-Seq data quality and global statistics such as FPKM distribution, as well as simple routines for plotting expression levels for one or more genes, their isoforms, TSS groups, or CDS groups. \r\n\t\t\t\t<ul>\r\n\t\t\t      <li>Plots are generally publication-ready.  However, because they are built with <a href=\"http://had.co.nz/ggplot2/\">ggplot2</a>, plot objects returned by the plotting routines are easy to manipulate in a live R session so you can tweak them to your specification.\r\n\t\t\t\t</ul>\r\n\t\t\t  <li>Persistent storage and indexing of cuffdiff data in a relational database.\r\n\t\t\t\t<ul>\r\n\t\t\t     <li>Quicker searching for feature-specific information\r\n\t\t\t     <li>Seamless aggregation of all related data points.\r\n\t\t\t     <li>Direct SQL/RSQLite querying of cuffdiff data for access to complex datasets using specialized queries.\r\n\t\t\t\t</ul>\r\n\t\t\t\t<li>Formalized R classes for data access and manipulation.\r\n\t\t\t\t\t<ul>\r\n\t\t\t      <li>'Pointer' classes call data directly from SQL tables.\r\n\t\t\t      <li>'Data' classes contain queried results and can be manipulated directly in R.\r\n\t\t\t      <li>Methods for direct access to FPKM values, differential expression data, and additional annotation of all gene-, isoform-, TSS-, and CDS-level features.\r\n\t\t\t      <li>Output formats allow for standard browsing/analysis in R (data.frame, list, etc).\r\n\t\t\t\t</ul>\r\n\t\t\t  <li>Geneset-level data access:\r\n\t\t\t\t<ul>\r\n\t\t\t      <li>Relevant data for meaningful subsets of genes (e.g. 'significantly regulated') can be quickly aggregated and stored in a geneset object.\r\n\t\t\t      <li>plot wrappers for heatmaps, expression profiles, barplots, volcano plots, scatterplots, etc.\r\n\t\t\t \t</ul>\r\n\t\t\t<li>Gene-centric data access:\r\n\t\t\t\t<ul>\r\n\t\t\t     <li>All interconnected data for a single gene are aggregated into a single data object.\r\n\t\t\t     <li>Access to all relevant FPKM, differential expression, and annotation data for all features of a single gene.\r\n\t\t\t     <li>Gene-specific plots (expression profiles)\r\n\t\t\t\t</ul>\r\n\t\t\t <li>Individual Feature-level data access as well:\r\n\t\t\t\t<ul>\r\n\t\t\t      <li>Individual Isoforms, TSS, CDS, etc. are also available.\r\n\t\t\t      <li>Direct access to distribution test results for alternative splicing, TSS groups, and CDS usage.\r\n\t\t\t\t</ul>\r\n\t\t\t</ul>\r\n\r\n\t\t\tCummeRbund is being made freely available under the OSI approved Artistic License 2.0 and can be downloaded from <a href=\"http://compbio.mit.edu/cummeRbund/\">http://compbio.mit.edu/cummeRbund/</a>. CummeRbund has also been included as part of the new R/<a href=\"http://www.bioconductor.org\">Bioconductor</a> v2.9 release and can be installed in a similar manner to standard Bioconductor packages.\r\n\t</p>\r\n\t<br/>\r\n\t\t\t<h2>1.1.0 release - 9/8/2011</h2>\r\n\t\t\t  <p>This is a fix release to address several issues reported by our users:\r\n\t\t\t\t  <ul>\r\n\t\t\t\t<li>Cuffdiff now includes a more sophisticated check for sufficient sequencing depth prior to testing for differences, which substantially improves the accuracy of differential expression analysis in loci with low to medium depth. \r\n\t\t\t\t<li>A bug in the calculation of the parameters for the beta negative binomial distribution used during variance estimation has been fixed.\r\n\t\t\t\t<li>Some users have reported that Cufflinks or Cuffdiff crashes due to running out of memory when processing highly expressed loci. Both programs now have a maximum number of fragments that can fall within a locus.  If a locus has more than this maximum, it is skipped.  The threshold is configurable via the <tt>--max-bundle-frags</tt> option.\r\n\t\t\t\t<li>Gffread now keeps the longest CDS when collapsing transcripts.\r\n\t\t\t\t</ul>\r\n\t\t\t\t<p><b>FILE FORMAT CHANGES:</b>\r\n\t\t\t\t<ul>\r\n\t\t\t\t<li>By popular request, fold changes are now reported log2, rather than natural log\r\n\t\t\t\t<li>The status column in fpkm tracking files has been replaced by a per-condition quantification status column\r\n\t\t\t\t<li>The header size limit in Cufflinks' BAM parser used to have a 4 megabyte limit.  This has been removed to allow Cufflinks to be used on assemblies with many contigs.\r\n\t\t\t  </ul>\r\n\t\t\t  </p>\r\n\t\t\t  <br/>\r\n\t\t\t\r\n\t\t\t<h2>iGenomes index and annotation packages available for download - 7/31/2011</h2>\r\n\t\t\t  <p> Illumina has generously provided a set of freely downloadable packages that contain everything you need to get started working with TopHat and Cufflinks.  These packages contain Bowtie indexes for the human, mouse, and fly genomes as well as many others.  The packages also contain annotation files (in GTF format) from UCSC, Ensembl, NCBI, and other sources.  These files are augmented with the special attributes Cufflinks needs to perform differential splicing and promoter analysis.  We strongly encourage users to download and try these packages!\r\n\t\t\t  <p></p>\r\n\t\t\t  <br>\r\n\r\n\t\t\t<h2>Cufflinks RABT assembly paper published - 6/26/2011</h2>\r\n\t\t\t  <p> Our new <a href=\"http://bioinformatics.oxfordjournals.org/content/early/2011/06/21/bioinformatics.btr355.abstract\">paper</a>\r\n\t\t\t\ton the Cufflinks reference annotation based transcript (RABT) assembly method introduced in v1.0.0\r\n\t\t\t\thas appeared in <i><a href=\"http://bioinformatics.oxfordjournals.org/\">Bioinformatics</a></i>. \r\n\t\t\t\tThe paper describes how the RABT assembler builds upon a known reference annotation to better identify novel transcripts.\r\n\t\t\t\tYou can try the RABT assembler in Cufflinks by using the <tt>-g</tt> option as explained in the manual.</p>\r\n\t\t\t  <p>Please cite this paper as well as the original Cufflinks paper if using the RABT assembler in your work.</p>\r\n\t\t\t  <p></p>\r\n\t\t\t  <br>\r\n        \r\n\t\t\t<h2>1.0.3 release - 6/1/2011</h2>\r\n\t\t\t  <p>This is a fix release to address several issues reported by our users:\r\n\t\t\t\t  <ul>\r\n\t\t\t\t<li>Several Cuffmerge bugs have been fixed.  One of these caused Cuffmerge to fail with a message about chromosome sort ordering.\r\n\t\t\t\t<li>A comment parsing issue in Cuffmerge has been fixed.\r\n\t\t\t\t<li>GTF files emitted by Cuffcompare are now lexicographically sorted by chromosome.\r\n\t\t\t\t<li>Gffread now has some transcript clustering and redundancy reduction features, similar to those found in Cuffcompare\r\n\t\t\t\t<li>The header size limit in Cufflinks' BAM parser used to have a 4 megabyte limit.  This has been removed to allow Cufflinks to be used on assemblies with many contigs.\r\n\t\t\t  </ul>\r\n\t\t\t  </p>\r\n\t\t\t  <br/>\r\n\t\t  <h2>1.0.2 release - 5/22/2011</h2>\r\n\t\t  <p>This release fixes several bugs and adds a few enhancements:\r\n\t  \t  <ul>\r\n\t\t\t<li>The differential splicing and promoter and cds use testing in 1.0.0 and later was broken, resulting in very few (often zero) differentially regulated genes. This has been fixed.\r\n\t\t\t<li>Many users were confused about the magnitude of quartile-normalized FPKM values in Cuffdiff.  Now, quartile normalized FPKM values are scaled by a constant such that they are numerically in roughly the same range as non-quartile normalized FPKMs.  Thanks to Ariel Schwartz for suggesting this change.\r\n\t\t\t<li>A performance issue when processing BAMs with many unmapped reads has been fixed.\r\n\t\t\t<li>Cuffcompare now creates <tt>.tmap</tt> and <tt>.refmap</tt> in the directory of the input file(s)\r\n\t\t\t\twith the same prefix as given by -o\r\n\t\t\t<li>An issue that caused cuffmerge to fail with a message about improperly sorted SAM files has been corrected.\r\n\t\t\t<li>Improved cuffcompare GFF support.\r\n\t\t\t<li>Cuffdiff and Cufflinks now accept new options controlling whether all hits are counted towards the FPKM denominator, or only those compatible with some transcript in the reference annotation.  Counting only compatible hits avoids certain types of bias that arise when one sample contains far more hits that aren't compatible with any transcript than the other sample does.  For example, if one sample contains vastly more mapped ribosomal RNA hits, FPKM values will appear lower in that sample, potentially leading to false positive differential expression calls.  Cuffdiff by default now uses only compatible hits.  Cufflinks still uses total hits by default, as using compatible hit accounting requires a reference GTF. \r\n\t\t  </ul>\r\n\t\t  </p>\r\n\t\t  <br/>\r\n\t\t  <h2>1.0.1 release - 5/6/2011</h2>\r\n\t\t  <p>This fix release corrects several issues introduced with 1.0.0:\r\n\t  \t  <ul>\r\n\t\t\t<li>The binary packages for 1.0.0 failed to include gtf_to_sam and gffread, causing cuffmerge to fail.\r\n\t\t\t<li>Cuffdiff's <tt>splicing.diff</tt> was missing the <tt>q_value</tt> column header\r\n\t\t\t<li>Several portability issues have been fixed (thanks to Nathan Weeks for the patches)\r\n\t\t\t<li>Cuffmerge's help message incorrectly listed several options.\r\n\t\t  </ul>\r\n\t\t  </p>\r\n\t\t  <br/>\r\n          <h2>1.0.0 release - 5/5/2011</h2>\r\n          <p>This release represents a huge leap for Cufflinks in terms\r\n            of performance and features. It is highly recommended that\r\n            all users upgrade to this version of Cufflinks. Updates and\r\n            improvements include: </p>\r\n          <ul>\r\n            <li>A new Reference Annotation Based Transcript (RABT)\r\n              assembly mode has been added. More details can be found in\r\n              the <a href=\"howitworks.html#hmul\">How Cufflinks Works</a>\r\n              section. </li>\r\n            <li>Major improvements to Cuffdiff. Handling of replicates in Cuffdiff have been\r\n              dramatically overhauled. Cuffdiff now models fragment\r\n              count overdispersion with a beta negative binomial distribution in each condition prior to testing.\r\n              See the substantially updated page on <a\r\n                href=\"howitworks.html#hdif\">How Cufflinks works</a> for\r\n              more details.</li>\r\n            <li>Bias correction described <a\r\n                href=\"http://genomebiology.com/2011/12/3/R22/\">here</a>\r\n              is now enabled with the <tt>-b/--frag-bias-correct</tt>\r\n              option (<tt>-r/--reference-seq</tt> is no longer in use).\r\n              A path to the reference multi-fasta used in mapping must\r\n              be supplied following the option. </li>\r\n            <li>Added support for improved handling multi-mapping reads.\r\n              Enable with the <tt>-u/--multi-read-correct</tt> option.\r\n              See <a href=\"howitworks.html#hmul\">How Cufflinks Works</a>\r\n              for more details. </li>\r\n            <li>Trimming has been instituted to more accurately locate\r\n              the 3' ends of transcripts during assembly based on\r\n              coverage.</li>\r\n            <li>Cufflinks now includes a new tool called Cuffmerge to help merge\r\n              assemblies from multiple samples into a single GTF for use\r\n              with Cuffdiff. The tool also helps integrate a reference\r\n              annotation file. See the <a href=\"tutorial.html\">Getting\r\n                Started</a> page for more details. </li>\r\n            <li>Output file formats have been made consistent between\r\n              Cufflinks and Cuffdiff. See the <a href=\"manual.html\">Manual</a>\r\n              for more details on the new formats.</li>\r\n            <li>Both GFF3 and GTF2.2 annotations are now fully supported\r\n              as input to all programs (see <a href=\"gff.html\">here</a>).</li>\r\n            <li>Improved reporting of map properties.</li>\r\n            <li>The programs now check for available updates automatically on launch.</li>\r\n            <li>Upper-quartile normalizaion has been fixed to be consistent with published literature (enable with <tt>-N/--upper-quartile-norm</tt>).</li>\r\n            <li>Fixed a bug where some splice-junction reads were lost\r\n              in quantitation.</li>\r\n            <li>Fixed a bug where reads landing in introns were\r\n              over-filtered in assembly.</li>\r\n            <li>Numerous improvements in speed for both assembly and\r\n              quantitation.</li>\r\n\t\t\t<li>Cuffdiff now uses dramatically less memory.  Cufflinks' memory footprint has also shrunk.</li>\r\n            <li>Numerous minor bug fixes.</li>\r\n          </ul>\r\n          <p></p>\r\n          <p><br>\r\n          </p>\r\n          <h2>Cufflinks Bias Correction paper published - 3/16/2011</h2>\r\n          <p> Our new <a href=\"http://genomebiology.com/2011/12/3/R22/\">paper</a>\r\n            on the Cufflinks bias correction method introduced in v0.9.0\r\n            has appeared in <i><a href=\"http://www.genomebiology.com/\">Genome\r\n                Biology</a></i>. The paper describes the details of the\r\n            method and provides validations for the improvements in\r\n            expression estimates it produces. As a reminder, bias\r\n            correction is only activated when a reference sequence\r\n            (fasta) is supplied with the -r option. </p>\r\n          <p>Please cite this paper if using Cufflinks bias correction\r\n            in your work.</p>\r\n          <p></p>\r\n          <br>\r\n          <h2>New \"Getting Help\" email address for TopHat and Cufflinks</h2>\r\n          <p>In order to more effectively answer user help requests and\r\n            improve usability and documentation, we have created an\r\n            email address to which users can send messages for technical\r\n            support. If you have questions about Cufflinks or TopHat,\r\n            please send them to <a\r\n              href=\"mailto:tophat.cufflinks@gmail.com\">tophat.cufflinks@gmail.com</a>.\r\n            We will do our best to answer your question in a timely\r\n            fashion, although <b>please read the manual carefully</b>\r\n            before sending your email. We have very limited time to\r\n            answer questions, and most questions require careful,\r\n            technical answers. </p>\r\n          <p>If you believe you have found a bug in the software, please\r\n            <b>include a small package of test data</b> with your email\r\n            so that we can reproduce your problem locally. A test\r\n            example makes it much easier to correct the issue. </p>\r\n          <br>\r\n          <h2>TopHat and Cufflinks now supported through Galaxy</h2>\r\n          <p>We are very pleased to announce that you can now run TopHat\r\n            and Cufflinks through <a href=\"http://usegalaxy.org\">Galaxy</a>.\r\n            The Galaxy project aims to make informatics tools accessible\r\n            through the web, and allows you to experiment with parameter\r\n            settings and create sophisticated analysis workflows easily.\r\n            Galaxy is developed by researchers at Emory University and\r\n            Penn State in the <a href=\"http://bx.mathcs.emory.edu/\">Taylor</a>\r\n            and <a href=\"http://www.bx.psu.edu/%7Eanton/\">Nekrutenko</a>\r\n            labs, respectively. We are extremely grateful for the Galaxy\r\n            team's work, and proud to have TopHat and Cufflinks offered\r\n            through their platform. </p>\r\n          <br>\r\n          <h2>0.9.3 release - 11/30/2010</h2>\r\n          <p>This release fixes several issues that affect abundance\r\n            estimation and differential expression accuracy, and is\r\n            strongly recommended for all users. Additionally, there are\r\n            some speed and threading improvements during bias modeling\r\n            and correction. Finally, a bug which causes Cufflinks to\r\n            crash on some BAM files has been fixed. </p>\r\n          <p> <br>\r\n          </p>\r\n          <h2>0.9.2 release - 10/26/2010</h2>\r\n          <p>This release modifies the way library types are handled to\r\n            add support for more strand-specific protocols as well as\r\n            adaptability to future protocols that may be introduced.\r\n            Note that the way library-types are specified in the input\r\n            has changed as a result. See the <a\r\n              href=\"manual.html#library\">Manual</a> for more details.</p>\r\n          <p>Some portability issues, which resulted in segfaults on\r\n            some systems, have been fixed in the precompiled binaries.</p>\r\n          <br>\r\n          <h2>0.9.1 release - 10/3/2010</h2>\r\n          <p>This release includes two bug fixes and some enhancements\r\n            for strand-specific RNA-Seq libraries: </p>\r\n          <ul>\r\n            <li>SAM files without headers, such as those produced by\r\n              TopHat 1.0.14 and earlier, were being erroneously reported\r\n              as unsorted during GTF-based quantification, causing\r\n              Cufflinks and Cuffdiff to exit. This has been fixed, so\r\n              that SAM files are now correctly handled, restoring\r\n              compatibility with output from TopHat 1.0.14 and earlier.</li>\r\n            <li>Cufflinks and Cuffdiff were sometimes producing\r\n              different FPKM values for minor isoforms when run on the\r\n              same sample. They are now consistent, and should agree on\r\n              isoform abundance calls. </li>\r\n            <li>Strand-specific, single end libraries are now supported.\r\n              Some library type names have changed to reflect the\r\n              expanded list of supported protocols.</li>\r\n          </ul>\r\n          <p></p>\r\n          <br>\r\n          <h2>Update - fix for 0.9.0</h2>\r\n          <p>The binaries and source have been updated to address a\r\n            floating point exception when using a SAM file with no\r\n            header and without a GTF</p>\r\n          <br>\r\n          <h2>New developer - Adam Roberts</h2>\r\n          <p>The Cufflinks team has been joined by Adam Roberts, a Ph.D.\r\n            student from the UC Berkeley Department of Computer Science.\r\n            Adam has made many improvements to Cufflinks (see the\r\n            announcement below), and we are very fortunate to benefit\r\n            from his talents and expertise.</p>\r\n          <br>\r\n          <h2>0.9.0 release - 9/27/2010</h2>\r\n          <p>This release includes significant bug fixes as well as some\r\n            major new features. Enhancements include: </p>\r\n          <ul>\r\n            <li>Thanks to the work of Adam Roberts, Cufflinks now\r\n              automatically learns certain properties of each RNA-Seq\r\n              library you analyze with it, including sequence specific\r\n              biases. Transcript and gene abundance estimates are\r\n              significantly more accurate when run with our (optional)\r\n              new bias correction technology. A manuscript describing\r\n              these changes is in preparation. </li>\r\n            <li>Due to Adam's changes, we do <b>not</b> recommend that\r\n              you supply the mean and standard deviations of the\r\n              fragment length distribution for your library. Cufflinks\r\n              now learns these automatically. </li>\r\n            <li>Cuffdiff now allows you to supply reads from multiple\r\n              technical or biological <b>replicates</b>, and adjusts\r\n              transcript and gene abundance estimates and their\r\n              confidence intervals accordingly.</li>\r\n            <li>Cuffdiff will by default report testing results between\r\n              all pairs of samples, rather than treating samples as a\r\n              time series. Time series analysis is still supported via\r\n              the <tt>--time-series</tt> option.</li>\r\n            <li>Cufflinks and Cuffdiff now offer improved compatibility\r\n              with reads aligned with Life Technology's BioScope\r\n              aligner. Strand specific SOLiD RNA-Seq runs are fully\r\n              supported.</li>\r\n            <li>Cufflinks and Cuffdiff support quantile normalization of\r\n              FPKM.</li>\r\n            <li>Cufflinks and Cuffdiff now support both BAM and SAM\r\n              files. Both file types require that the chromosome names\r\n              in header <tt>@SQ</tt> records, if present, <b>must</b>\r\n              be sorted in the same order as the reads.</li>\r\n            <li>Cufflinks and Cuffdiff are much less verbose in their\r\n              output by default, but each supports a \"verbose\" mode with\r\n              a text progress bar for users that want to keep an eye on\r\n              their runs</li>\r\n            <li>In response to user requests, FPKM values are now\r\n              provided by Cufflinks and Cuffdiff, even if their\r\n              expression levels are zero, in an effort to make\r\n              downstream analysis of Cuffdiff easier.</li>\r\n            <li>The new \"mask\" GTF option allows you to supply Cufflinks\r\n              with regions of the genome that it should ignore during\r\n              assembly and quantification. Cuffdiff also supports mask\r\n              GTF files for convenience.</li>\r\n            <li>Significant assembler fixes and improvements.</li>\r\n            <li>Some of the output files produced by Cuffdiff have\r\n              updated and simplified formats.</li>\r\n            <li>There are a number of new command line options that\r\n              users may wish to set under certain circumstances.</li>\r\n          </ul>\r\n          <p>Note that building Cufflinks from source now requires the <a\r\n              href=\"http://samtools.sourceforge.net\">SAM tools</a>. See\r\n            the installation instructions for more details. </p>\r\n          <br>\r\n          <h2>0.8.3 build update - 7/2/2010</h2>\r\n          <p> The 0.8.3 release on 6/30 included a broken version of\r\n            Cuffdiff. This and a few other minor issues have been\r\n            resolved and the builds and source have been updated. </p>\r\n          <br>\r\n          <h2>0.8.3 release - 6/30/2010</h2>\r\n          <p> Fixes and accuracy improvements to the Cufflinks\r\n            assembler. This update is strongly recommended for users\r\n            interested in identifying novel transcripts. Other changes:\r\n          </p>\r\n          <ul>\r\n            <li>Additional expression reporting fixes</li>\r\n            <li>Output from Cufflinks and Cuffdiff can now be directed\r\n              to a separate directory.</li>\r\n          </ul>\r\n          <p></p>\r\n          <br>\r\n          <h2>Cufflinks paper published - 5/2/2010</h2>\r\n          <p> Our <a href=\"http://dx.doi.org/10.1038/nbt.1621\">paper</a>\r\n            on Cufflinks has appeared at <i><a\r\n                href=\"http://www.nature.com/nbt\">Nature Biotechnology</a></i>.\r\n            In a study of developing mouse muscle cells, we identified\r\n            thousands of new transcripts and detected differential\r\n            splicing and promoter use in hundreds of genes by examining\r\n            changes in isoform abundance levels. The paper is aimed at a\r\n            general audience, so much of the algorithmic and\r\n            mathematical detail can be found in the <a\r\nhref=\"http://www.nature.com/nbt/journal/vaop/ncurrent/extref/nbt.1621-S1.pdf\">supplemental\r\n              methods</a> (WARNING: 2 MB PDF). </p>\r\n          <br>\r\n          <h2>0.8.2 release - 3/26/2010</h2>\r\n          <p> Numerous bug fixes and significant performance\r\n            improvements in Cufflinks and Cuffdiff. Note that some the <strong>formats</strong>\r\n            of some files <strong>have changed</strong>. Other changes:\r\n          </p>\r\n          <ul>\r\n            <li>Expression values were not being reported for a small\r\n              number of genes when using certain annotation files.</li>\r\n            <li>Fixed a divide-by-zero error in Cuffdiff</li>\r\n            <li>Various GTF parser fixes.</li>\r\n            <li><tt>.expr</tt> files produced by Cufflinks now contain\r\n              FPKM confidence interval columns</li>\r\n            <li>Isoform filtering was being innappropriately applied\r\n              when working with annotation in Cufflinks (via <tt>--GTF</tt>)</li>\r\n            <li>The <tt>.tmap</tt> files reported by Cuffdiff contained\r\n              zero in FPKM field.</li>\r\n            <li>New command line options <tt>--num-importance-samples</tt>\r\n              and <tt>--max-mle-iterations</tt> allow advanced users to\r\n              influence of the transcript abundance estimation. </li>\r\n          </ul>\r\n          <p></p>\r\n          <br>\r\n          <h2>0.8.1 release - 2/13/2010</h2>\r\n          <p> This is a minor fix release. Cufflinks 0.8.0 had some\r\n            lingering references to \"RPKM\", which have been replaced\r\n            with \"FPKM\". Reported expression values have always been in\r\n            FPKM, this is simply a nomenclature change to better reflect\r\n            what RNA-Seq actually measures. See the section on FPKM in\r\n            the description of how Cufflinks <a href=\"howitworks.html\">works</a>\r\n          </p>\r\n          <br>\r\n          <h2>0.8.0 release - 2/5/2010</h2>\r\n          <p> We are happy to announce a major update to Cufflinks that\r\n            introduces some powerful new features and includes a number\r\n            of performance improvement and bug fixes. Highlights\r\n            include: </p>\r\n          <p> </p>\r\n          <ul>\r\n            <li>Cufflinks now includes a new tool, \"Cuffdiff\", which\r\n              performs testing for differential expression, splicing,\r\n              promoter use, and coding sequence output on two or more\r\n              RNA-Seq samples. See the greatly expanded <a\r\n                href=\"manual.html\">manual</a> for details.</li>\r\n            <li>Cuffcompare now reports a file containing the \"union\" of\r\n              all transfrags in the files you give it as input, greatly\r\n              simplifying downstream validatation of novel transcripts.</li>\r\n            <li>Cufflinks' assembler has been overhauled and optimized,\r\n              resulting in a speedup of 4-5 times over version 0.7.0,\r\n              and a <b>greatly</b> reduced memory footprint. Phasing of\r\n              splicing events has also been improved.</li>\r\n            <li>Many bugfixes.</li>\r\n          </ul>\r\n          <br>\r\n          <h2>0.7.0 release - 9/26/2009</h2>\r\n          <p> The first public release of Cufflinks is now available for\r\n            download. Cufflinks is a program for the comparative\r\n            assembly of transcripts and the estimation of their\r\n            abundances in an RNA-Seq experiment. It runs on Linux and OS\r\n            X. It also comes with a tool to track transcripts across\r\n            multiple samples, for example in a time course of RNA-Seq. </p>\r\n          <p>Cufflinks takes as input a file of alignments in <a\r\n              href=\"http://samtools.sourceforge.net\">SAM</a> format, and\r\n            reports transfrags in <a\r\n              href=\"http://mblab.wustl.edu/GTF22.html\">GTF</a> format.\r\n            You can use <a href=\"http://tophat.cbcb.umd.edu\">TopHat</a>\r\n            to align your reads, as TopHat reports its alignments in SAM\r\n            format. </p>\r\n          <p>This software is a work in progress - it is a beta release,\r\n            and new features will continue to be added over the next\r\n            couple of weeks. To suggest a feature or report a bug,\r\n            please email <a href=\"mailto:cole@cs.umd.edu\">Cole Trapnell</a>\r\n          </p>\r\n        </div>\r\n      </div>\r\n      <div id=\"footer\">\r\n        <table cellspacing=\"15\" width=\"100%\">\r\n          <tbody>\r\n            <tr>\r\n              <td> This research was supported in part by NIH grants\r\n                R01-LM06845 and R01-GM083873, NSF grant CCF-0347992 and\r\n                the Miller Institute for Basic Research in Science at UC\r\n                Berkeley. </td>\r\n              <td align=\"right\"> Administrator: <a\r\n                  href=\"mailto:cole@cs.umd.edu\">Cole Trapnell</a>.\r\n                Design by <a href=\"http://www.free-css-templates.com\"\r\n                  title=\"Design by David Herreman\">David Herreman</a> </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </div>\r\n    <!-- Google analytics code -->\r\n    <script type=\"text/javascript\">\r\nvar gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\r\ndocument.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\r\n</script>\r\n    <script type=\"text/javascript\">\r\ntry {\r\nvar pageTracker = _gat._getTracker(\"UA-6101038-2\");\r\npageTracker._trackPageview();\r\n} catch(err) {}</script>\r\n    <!-- End google analytics code -->\r\n  </body>\r\n</html>\r\n"
  },
  {
    "path": "doc/html/manual.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<title>Cufflinks RNA-Seq analysis tools - User's Manual</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n<meta name=\"description\" content=\"A detailed guide to options and features in Cufflinks, Cuffdiff and other included tools\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\" media=\"screen\" />\n</head>\n<body>\n<div id=\"wrap\">\n  <div id=\"top\">\n    <div class=\"lefts\">\n    <table width=\"100%\" cellpadding=\"2\">\n      <tr><td>\n        <a href=\"./index.html\"><h1>Cufflinks</h1></a>\n        <h2>Transcript assembly, differential expression, and differential regulation for RNA-Seq</h2>\n      </td><td align=\"right\" valign=\"middle\">\n        <a href=\"http://bio.math.berkeley.edu/\">\n        <img style=\"vertical-align:middle;padding-top:4px\" \n          border=0 src=\"images/UCBerkeley-seal.scaled.gif\">\n        </img></a>&nbsp;\n        <a href=\"http://genomics.jhu.edu/\">\n          <img style=\"vertical-align:middle;padding-top:4px\"\n           src=\"images/JHU-seal.gif\" border=\"0\">\n        </a>&nbsp;\n     <a href=\"http://www.cbcb.umd.edu/\"><img style=\"vertical-align:middle;padding-top:4px\" border=0 src=\"images/cbcb_logo.gif\"></a>&nbsp;&nbsp;\n      </td></tr>\n    </table>\n    </div>\n  </div>\n  <div id=\"subheader\">\n  <table width=\"100%\"><tr>\n  <td>\n  \t\t<strong>Please Note</strong> If you have questions \n\t\t  about how to use Cufflinks or would like more information about \n\t\t  the software, please email <a href=\"mailto:tophat.cufflinks@gmail.com\"><b>tophat.cufflinks@gmail.com</b></a>, \n\t\t  though we ask you to have a look at the <a href=\"http://dx.doi.org/10.1038/nbt.1621\">paper</a> \n\t\t  and the  <a href=\"http://www.nature.com/nbt/journal/v28/n5/extref/nbt.1621-S1.pdf\">\n\t\t  supplemental methods</a> first, as your question be answered there.\n\t</td><td align=right valign=middle>\n  </td></tr>\n  </table>\n  </div>\n  <div id=\"main\">\n    <div id=\"rightside\">\n\t\t<h2>Site Map</h2>\n        <div class=\"box\">\n          <ul>\n            <li><a href=\"index.html\">Home</a></li>\n            <li><a href=\"tutorial.html\">Getting started</a></li>\n            <li><a href=\"manual.html\">Manual</a></li>\n            <li><a href=\"howitworks.html\">How Cufflinks works</a></li>\n\t\t\t  <li><a href=\"igenomes.html\">Index and annotation downloads</a></li>\n            <li><a href=\"faq.html\">FAQ</a></li>\n\t\t\t  <li><a href=\"http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html\">Protocol</a></li>\n\t\t\t  <li><a href=\"report.html\">Benchmarking</a></li>\n          </ul>\n        </div>\n\t\t\n        <h2><u>News and updates</u></h2>\n        <div class=\"box\">\n          <ul>\n            <table width=\"100%\">\n              <tbody>\n                <tr>\n                  <td>New releases and related tools will be announced\n                    through the <a\n                      href=\"https://lists.sourceforge.net/lists/listinfo/bowtie-bio-announce\"><b>mailing\n                        list</b></a></td>\n                </tr>\n              </tbody>\n            </table>\n          </ul>\n        </div>\n        <h2><u>Getting Help</u></h2>\n        <div class=\"box\">\n          <ul>\n            <table width=\"100%\">\n              <tbody>\n                <tr>\n                  <td>Questions about Cufflinks and Cuffdiff should be posted on our <a href=\"https://groups.google.com/forum/#!forum/tuxedo-tools-users\"><b>Google Group</b></a>. Please use <a\n                      href=\"mailto:tophat.cufflinks@gmail.com\">tophat.cufflinks@gmail.com</a> for private communications only.\n                    Please do not email technical questions to\n                    Cufflinks contributors directly.</td>\n                </tr>\n              </tbody>\n            </table>\n          </ul>\n        </div>\n\t\t  \n\t\t\n          <a href=\"./downloads\">\n            <h2><u>Releases</u></h2>\n          </a>\n          <div class=\"box\">\n            <ul>\n              <table width=\"100%\">\n                <tbody>\n                  <tr>\n                    <td>version 2.2.0</td>\n                    <td align=\"right\">5/25/2014</td>\n                  </tr>\n                  <tr>\n                    <td><a href=\"./downloads/cufflinks-2.2.0.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks_source');\n                        \">&nbsp;&nbsp;&nbsp;Source code</a></td>\n                  </tr>\n                  <tr>\n                    <td><a\n                        href=\"./downloads/cufflinks-2.2.0.Linux_x86_64.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks');\n                        \">&nbsp;&nbsp;&nbsp;Linux x86_64 binary</a></td>\n                  </tr>\n                  <tr>\n                    <td><a\n                        href=\"./downloads/cufflinks-2.2.0.OSX_x86_64.tar.gz\"\n                        onclick=\"javascript:\n                        pageTracker._trackPageview('/downloads/cufflinks');\n                        \">&nbsp;&nbsp;&nbsp;Mac OS X x86_64 binary</a></td>\n                  </tr>\n                </tbody>\n              </table>\n            </ul>\n          </div>          \n\t\t\n\t\t  <h2>Related Tools</h2>\n          <div class=\"box\">\n            <ul>\n                <li><a href=\"http://monocle-bio.sourceforge.net\">Monocle</a>:\n                  Single-cell RNA-Seq analysis</li>\n\t\t\t\t<li><a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a>:\n\t                Visualization of RNA-Seq differential analysis</li>\n              <li><a href=\"http://tophat.cbcb.umd.edu/\">TopHat</a>:\n                Alignment of short RNA-Seq reads</li>\n              <li><a href=\"http://bowtie.cbcb.umd.edu\">Bowtie</a>:\n                Ultrafast short read alignment</li>\n            </ul>\n          </div>\n\n\n\n\t\t  <h2>Publications</h2>\n          <div class=\"box\">\n            <ul>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Trapnell C, Williams BA, Pertea G, Mortazavi AM, Kwan\n                  G, van Baren MJ, Salzberg SL, Wold B, Pachter L.<b> <a\n                      href=\"http://dx.doi.org/10.1038/nbt.1621\">Transcript\n                      assembly and quantification by RNA-Seq reveals\n                      unannotated transcripts and isoform switching\n                      during cell differentiation</a></b> <br>\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\n                      Biotechnology</a></i> doi:10.1038/nbt.1621</p>\n                <br>\n              </li>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Roberts A, Trapnell C, Donaghey J, Rinn JL, Pachter\n                  L.<b> <a\n                      href=\"http://genomebiology.com/2011/12/3/R22/abstract\">Improving\n                      RNA-Seq expression estimates by correcting for\n                      fragment bias</a></b> <br>\n                  <i><a href=\"http://www.genomebiology.com\">Genome\n                      Biology</a></i> doi:10.1186/gb-2011-12-3-r22</p>\n                <br>\n              </li>\n              <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Roberts A, Pimentel H, Trapnell C, Pachter\n                  L.<b> <a\n                      href=\"http://bioinformatics.oxfordjournals.org/content/early/2011/06/21/bioinformatics.btr355.abstract\">\n                      Identification of novel transcripts in annotated genomes using RNA-Seq</a></b> <br>\n                  <i><a href=\"http://bioinformatics.oxfordjournals.org/\">Bioinformatics</a></i> doi:10.1093/bioinformatics/btr355</p>\n                <br>\n              </li>\n\t\t\t  <li style=\"font-size: x-small; line-height: 130%\">\n                <p>Trapnell C, Hendrickson D,Sauvageau S, Goff L, Rinn JL, Pachter L<b> <a\n                      href=\"http://dx.doi.org/10.1038/nbt.2450\">Differential \n\t\t\t\t\t analysis of gene regulation at transcript resolution with RNA-seq\n\t\t\t\t\t</a></b> <br>\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\n                      Biotechnology</a></i> doi:10.1038/nbt.2450</p>\n                <br>\n              </li>\n            </ul>\n          </div>\n          <h2>Contributors</h2>\n          <div class=\"box\">\n            <ul>\n              <li><a href=\"http://www.cs.umd.edu/%7Ecole/\">Cole Trapnell</a></li>\n              <li><a href=\"http://www.cs.berkeley.edu/%7Eadarob/\">Adam\n                  Roberts</a></li>\n              <li>Geo Pertea</li>\n\t\t\t  <li>David Hendrickson<li>\n\t\t\t  <li>Loyal Goff</li>\n\t\t\t  <li>Martin Sauvageau</li>\n              <li>Brian Williams</li>\n              <li><a href=\"http://wormlab.caltech.edu/members/\">Ali\n                  Mortazavi</a></li>\n              <li>Gordon Kwan</li>\n              <li>Jeltje van Baren</li>\n\t\t\t  <li><a href=\"http://www.rinnlab.com\">John Rinn</a></li>\n              <li><a href=\"http://www.cbcb.umd.edu/%7Esalzberg/\">Steven\n                  Salzberg</a></li>\n              <li><a href=\"http://biology.caltech.edu/Members/Wold\">Barbara\n                  Wold</a></li>\n              <li><a href=\"http://www.math.berkeley.edu/%7Elpachter/\">Lior\n                  Pachter</a></li>\n            </ul>\n          </div>\n\n\t\t  <h2>Links</h2>\n\t\t  <div class=\"box\">\n\t\t    <ul>\n\t\t      <li><a href=\"http://bio.math.berkeley.edu/\">Berkeley LMCB</a></li>\n\t\t      <li><a href=\"http://www.cbcb.umd.edu/\">UMD CBCB</a></li>\n\t\t\t  <li><a href=\"http://woldlab.caltech.edu/\">Wold Lab</a></li>\n\t\t    </ul>\n\t\t  </div>          \n          \n    </div> <!-- End of \"rightside\" -->\n    <div id=\"leftside\">\n  \t  <table><tr><td cellpadding=7>\n  \t  <h1>Manual</h1><br/>\n      <div id=\"toc\">\n  \t    <ul>\n  \t    <li><a href=\"#prer\">Prerequisites</a></li>\n  \t    <li><a href=\"#cufflinks\">Running Cufflinks</a></li>\n\t\t<ul>\n  \t      <li><a href=\"#cufflinks_input\">Input Files</a></li>\n  \t  \t  <li><a href=\"#cufflinks_output\">Output Files</a></li>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"#gtfout\">Transfrags in GTF</a></li>\n\t\t\t\t<li><a href=\"#transexpr\">Transcript-level expression</a></li>\n\t\t\t\t<li><a href=\"#geneexpr\">Gene-level expression</a></li>\n\t\t\t</ul>\n \t    </ul>\n  \t    <li><a href=\"#cuffcompare\">Running Cuffcompare</a></li>\n\t\t<ul>\n  \t      <li><a href=\"#cuffcomp_input\">Input Files</a></li>\n  \t  \t  <li><a href=\"#cuffcomp_output\">Output Files</a></li>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"#refmap\">Transfrags for each reference transcript</a></li>\n\t\t\t\t<li><a href=\"#tmap\">Classification for transfrag</a></li>\n\t\t\t\t<li><a href=\"#ichain\">Tracking transfrags through multiple samples</a></li>\n\t\t\t</ul>\n\t\t\t<li><a href=\"#class_codes\">Transfrag class codes</a></li>\n \t    </ul>\n\t\t<li><a href=\"#cuffmerge\">Merging assemblies with cuffmerge</a></li>\n\t\t<ul>\n  \t      <li><a href=\"#merger_input\">Input Files</a></li>\n  \t  \t  <li><a href=\"#merger_output\">Output Files</a></li>\n \t    </ul>\n\t\t<li><a href=\"#cuffquant\">Running Cuffquant</a></li>\n  \t    <li><a href=\"#cuffdiff\">Running Cuffdiff</a></li>\n\t\t<ul>\n  \t      <li><a href=\"#cuffdiff_input\">Input Files</a></li>\n  \t  \t  <li><a href=\"#cuffdiff_output\">Output Files</a></li>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"#fpkm_track\">FPKM tracking</a></li>\n\t\t\t\t<li><a href=\"#count_track\">Count tracking</a></li>\n\t\t\t\t<li><a href=\"#count_track\">Read group tracking</a></li>\n\t\t\t\t<li><a href=\"#gene_exp_diff\">Differential expression</a></li>\n\t\t\t\t<li><a href=\"#splicing_diff\">Differential splicing</a></li>\n\t\t\t\t<li><a href=\"#cds_diff\">Differential coding sequence output</a></li>\n\t\t\t\t<li><a href=\"#promoter_diff\">Differential promoter use</a></li>\n\t\t\t\t<li><a href=\"#read_group_info\">Read group info</a></li>\n\t\t\t\t<li><a href=\"#run_info\">Run info</a></li>\n\t\t\t</ul>\n \t    </ul>\n\t\t<li><a href=\"#cuffnorm\">Running Cuffnorm</a></li>  \n\t\t  <ul>\n\t\t\t  <li><a href=\"#cuffnorm_input\">Input Files</a></li>\n  \t  \t  \t  <li><a href=\"#cuffnorm_output\">Output Files</a></li>\n\t\t  </ul>\n\t\t\n\t\t<li><a href=\"#sample_sheets\">Sample sheets for Cuffdiff and Cuffnorm</a></li>\n\t\t<li><a href=\"#contrast_files\">Contrast files for Cuffdiff</a></li>\n\t\t<li><a href=\"#output_formats\">Output formats</a>\n\t\t\t<ul>\n\t\t \t    <li><a href=\"#fpkm_tracking_format\">FPKM Tracking format</a></li>\n\t\t\t\t<li><a href=\"#count_tracking_format\">Count Tracking format</a></li>\n\t\t\t\t<li><a href=\"#read_group_tracking_format\">Read Group Tracking format</a></li>\n\t\t\t\t<li><a href=\"#simple_table_expression_format\">Simple-table expression format</a></li>\n\t\t\t\t<li><a href=\"#simple_table_gene_attr_format\">Simple-table gene attributes format</a></li>\n\t\t\t\t<li><a href=\"#simple_table_sample_attr_format\">Simple-table sample attributes format</a></li>\n\t\t\t</ul>\n\t\t<li><a href=\"#library\">Library Types</a></li>\n\t\t<li><a href=\"#library_norm_meth\">Library Normalization Methods</a></li>\n\t\t<li><a href=\"#dispersion_meth\">Cross-replicate dispersion estimation methods</a></li>\n\n  \t    </ul><br/>\n  \t  </div>\n  \t  \n\t  <h2 id=\"prer\">Prerequisites</h2><br/>\n\t  <p>\n\t  Cufflinks runs on intel-based computers running Linux or Mac OS X and \n\t  that have GCC 4.0 or greater installed.  You can install pre-compiled \n\t  binaries or build Cufflinks from the source code.\n\t  If you wish to build Cufflinks yourself, you will need to install the\n\t  <a href=\"http://www.boost.org\">Boost C++ libraries</a>.  See <a href=\"tutorial.html#boost\">\n\t  Installing Boost</a>, on the getting started page. You will also need to build and install the\n\t  <a href=\"http://samtools.sourceforge.net\">SAM tools</a>, but you should take a look at the getting \n\t  started page for detailed instructions, because the headers and <tt>libbam</tt> must be accessible \n\t  to the Cufflinks build scripts.\n  \t  </p>\n \t  <br/>\n  \t  <h2 id=\"cufflinks\">Running Cufflinks</h2><br/>\n\t\tRun <tt>cufflinks</tt> from the command line as follows:\n\t  <blockquote>\n \t   Usage: cufflinks [options]* &lt;aligned_reads.(sam/bam)&gt;\n\t  </blockquote>\n\t  <p>\n\t  The following is a detailed description of the options used to control\n\t  Cufflinks:\n\t  </p><br/>\n\n\t  <table CELLSPACING=15>\n\t  <tr><td VALIGN=top>\n\t  <b>Arguments:</b>\n\t  </td><td VALIGN=top>\n\t  </td></tr>\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>&lt;aligned_reads.(sam/bam)&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  A file of RNA-Seq read alignments in the <a href=\"http://samtools.sourceforge.net\">\n\t  SAM format</a>.  SAM is a standard short read alignment, that allows aligners to \n\t  attach custom tags to individual alignments, and Cufflinks requires that\n\t  the alignments you supply have some of these tags.  Please see <a href=\"#input\">\n\t  Input formats</a> for more details.\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top>\n\t  <b>General Options:</b>\n\t  </td><td VALIGN=top>\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-h/--help</tt>\n\t  </td><td VALIGN=top>\n\t  Prints the help message and exits   \n\t  </td></tr> \n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-o/--output-dir &lt;string&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Sets the name of the directory in which Cufflinks will write all of its \n\t  output.  The default is \"./\".\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-p/--num-threads &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Use this many threads to align reads. The default is 1.\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-G/--GTF &lt;reference_annotation.(gtf/gff)&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Tells Cufflinks to use the supplied reference annotation (<a href=\"gff.html\">a GFF file</a>)\n\t  to estimate isoform expression. It will not assemble novel transcripts, and the program\n\t  will ignore alignments not structurally compatible with any reference transcript.\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-g/--GTF-guide &lt;reference_annotation.(gtf/gff)&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Tells Cufflinks to use the supplied reference annotation (<a href=\"gff.html\">GFF</a>) to guide <a href=howitworks#hrga>RABT assembly</a>.\n\t  Reference transcripts will be tiled with faux-reads to provide additional information\n\t  in assembly. Output will include all reference transcripts as well as any novel\n\t  genes and isoforms that are assembled.\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-M/--mask-file &lt;mask.(gtf/gff)&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Tells Cufflinks to ignore all reads that could have come from transcripts in this GTF \n\t  file. We recommend including any annotated rRNA, mitochondrial transcripts other abundant\n\t  transcripts you wish to ignore in your analysis in this file.  Due to variable efficiency\n\t  of mRNA enrichment methods and rRNA depletion kits, masking these transcripts often \n\t  improves the overall robustness of transcript abundance estimates. \n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-b/--frag-bias-correct &lt;genome.fa&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Providing Cufflinks with a multifasta file via this option instructs it to run our new \n\t  bias detection and correction algorithm which can significantly improve accuracy of \n\t  transcript abundance estimates.  See <a href=howitworks.html#hsbi>How Cufflinks Works</a> for more details.\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-u/--multi-read-correct</tt>\n\t  </td><td VALIGN=top>\n\t  Tells Cufflinks to do an initial estimation procedure to more accurately weight reads\n\t  mapping to multiple locations in the genome.  See <a href=howitworks.html#hmul>How Cufflinks Works</a> for more details.\n\t  </td></tr>\n\t  <tr><td VALIGN=top>\n\t  \n\t  <tt>--library-type</tt>\n\t  </td><td VALIGN=top>\n\t  See <a href=\"#library\">Library Types</a>\n\t  </td></tr>\n\t  <tr>\t\n\t\t  \n\t  <tr><td VALIGN=top nowrap>\t\n\t  <tt>--library-norm-method</tt>\n\t  </td><td VALIGN=top>\n\t  See <a href=\"#library_norm_meth\">Library Normalization Methods</a>\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top>\n\t  <b>Advanced Abundance Estimation Options:</b>\n\t  </td><td VALIGN=top>\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\t\n\t  <tt>-m/--frag-len-mean &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  This is the expected (mean) fragment length. The default is 200bp. <br/><b>Note: \n\t  Cufflinks now learns the fragment length mean for each SAM file, so using this option is\n\t  no longer recommended with paired-end reads.</b>\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-s/--frag-len-std-dev &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  The standard deviation for the distribution on fragment lengths.  The default is 80bp. <br/><b>Note: \n\t  Cufflinks now learns the fragment length standard deviation for each SAM file, so using this option is\n\t  no longer recommended with paired-end reads.</b>\n\t  </td></tr>\n\t  \n  \t  <tr><td VALIGN=top nowrap>\n\t  <tt>-N/--upper-quartile-norm</tt>\n\t  </td><td VALIGN=top>\n\t  With this option, Cufflinks normalizes by the upper quartile of the number of fragments mapping\n\t  to individual loci instead of the total number of sequenced fragments.  This can improve robustness \n\t  of differential expression calls for less abundant genes and transcripts.\n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--total-hits-norm</tt>\n\t  </td><td VALIGN=top>\n\t  With this option, Cufflinks counts all fragments, including those not compatible with any reference transcript, towards the number of mapped hits used in the FPKM denominator.  This option can be combined with <tt>-N/--upper-quartile-norm</tt>.  It is active by default.\n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--compatible-hits-norm</tt>\n\t  </td><td VALIGN=top>\n\t  With this option, Cufflinks counts only those fragments compatible with some reference transcript towards the number of mapped hits used in the FPKM denominator.  This option can be combined with <tt>-N/--upper-quartile-norm</tt>.  It is inactive by default, and can only be used in combination with <tt>--GTF</tt>.  Use with either RABT or ab initio assembly is not supported\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--max-mle-iterations &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Sets the number of iterations allowed during maximum likelihood estimation of abundances. Default: 5000  \n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--max-bundle-frags &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Sets the maximum number of fragments a locus may have before being skipped. Skipped loci are listed in <tt>skipped.gtf</tt>. Default: 1000000  \n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--no-effective-length-correction</tt>\n\t  </td><td VALIGN=top>\n\t  Cufflinks will not employ its \"effective\" length normalization to transcript FPKM. \n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--no-length-correction</tt>\n\t  </td><td VALIGN=top>\n\t  Cufflinks will not normalize fragment counts by transcript length at all.  Use this option when fragment count is independent of the size of the features being quantified (e.g. for small RNA libraries, where no fragmentation takes place, or 3 prime end sequencing, where sampled RNA fragments are all essentially the same length).  Experimental option, use with caution. \n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top>\n\t  <b>Advanced Assembly Options:</b>\n\t  </td><td VALIGN=top>\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-L/--label</tt>\n\t  </td><td VALIGN=top>\n\t  Cufflinks will report transfrags in GTF format, with a prefix given by \n\t  this option.  The default prefix is \"CUFF\".\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-F/--min-isoform-fraction &lt;0.0-1.0&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  After calculating isoform abundance for a gene, Cufflinks filters out \n\t  transcripts that it believes are very low abundance, because isoforms \n\t  expressed at extremely low levels often cannot reliably be assembled, \n\t  and may even be artifacts of incompletely spliced precursors of processed\n\t  transcripts. This parameter is also used to filter out introns\n\t  that have far fewer spliced alignments supporting them. The default is \n\t  0.1, or 10% of the most abundant isoform (the major isoform) of the gene.  \n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-j/--pre-mrna-fraction &lt;0.0-1.0&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Some RNA-Seq protocols produce a significant amount of reads that originate\n\t  from incompletely spliced transcripts, and these reads can confound the \n\t  assembly of fully spliced mRNAs.  Cufflinks uses this parameter to filter \n\t  out alignments that lie within the intronic intervals implied by the \n\t  spliced alignments.  The minimum depth of coverage in the intronic region covered \n\t  by the alignment is divided by the number of spliced reads, and if the \n\t  result is lower than this parameter value, the intronic alignments are \n\t  ignored. The default is 15%.\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-I/--max-intron-length &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  The maximum intron length.  Cufflinks will not report transcripts with \n\t  introns longer than this, and will ignore SAM alignments with REF_SKIP \n\t  CIGAR operations longer than this.  The default is 300,000.\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-a/--junc-alpha &lt;0.0-1.0&gt; </tt>\n\t  </td><td VALIGN=top>\n\t  The alpha value for the binomial test used during false positive spliced alignment \n\t  filtration. Default: 0.001\n\t  </td></tr>\n\t \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-A/--small-anchor-fraction &lt;0.0-1.0&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Spliced reads with less than this percent of their length on each side of the junction\n\t  are considered suspicious and are candidates for filtering prior to assembly.  Default: 0.09.  \n\t  </td></tr>\n\t \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--min-frags-per-transfrag &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Assembled transfrags supported by fewer than this many aligned RNA-Seq fragments are \n\t  not reported.  Default: 10.\n\t  </t></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--overhang-tolerance &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  The number of bp allowed to enter the intron of a transcript when determining if a read or \n\t  another transcript is mappable to/compatible with it.  The default is 8 bp based on the default\n\t  bowtie/TopHat parameters.\n\t  </t></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--max-bundle-length &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Maximum genomic length allowed for a given bundle.  The default is 3,500,000 bp.\n\t  </t></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--min-intron-length &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Minimum intron size allowed in genome. The default is 50 bp.\n\t  </t></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--trim-3-avgcov-thresh &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Minimum average coverage required to attempt 3' trimming.  The default is 10.\n\t  </t></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--trim-3-dropoff-frac &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  The fraction of average coverage below which to trim the 3' end of an assembled\n\t  transcript.  The default is 0.1.\n\t  </t></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--max-multiread-fraction &lt;0.0-1.0&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  The fraction a transfrag's supporting reads that may be multiply mapped to the genome. A transcript composed of more than this fraction will not be reported by the assembler.  Default: 0.75 (75% multireads or more is suppressed). \n\t  </t></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--overlap-radius &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Transfrags that are separated by less than this distance get merged together, and the gap is filled.  Default: 50 (in bp).\n\t  </t></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <b>Advanced Reference Annotation Based Transcript (RABT) Assembly Options:</b>\n\t  </td><td VALIGN=top>\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <i>These options have an affect only when used in conjuction with <tt>-g/--GTF-guide</tt>.</i>\n\t  </td><td VALIGN=top>\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--3-overhang-tolerance &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  The number of bp allowed to overhang the 3' end of a reference transcript when determining \n\t  if an assembled transcript should be merged with it (ie, the assembled transcript is not novel).  \n\t  The default is 600 bp.\n\t  </t></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--intron-overhang-tolerance &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  The number of bp allowed to enter the intron of a reference transcript when determining if an \n\t  assembled transcript should be merged with it (ie, the assembled transcript is not novel).  \n\t  The default is 50 bp.\n\t  </t></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--no-faux-reads</tt>\n\t  </td><td VALIGN=top>\n\t  This option disables tiling of the reference transcripts with faux reads.  Use this if you only\n\t  want to use sequencing reads in assembly but do not want to output assembled transcripts that lay\n\t  within reference transcripts.  All reference transcripts in the input annotation will also \n\t  be included in the output.\n\t  </t></tr>\n\n\t  <tr><td VALIGN=top>\n\t  <b>Advanced Program Behavior Options:</b>\n\t  </td><td VALIGN=top>\n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-v/--verbose</tt>\n\t  </td><td VALIGN=top>\n\t  Print lots of status updates and other diagnostic information.\n\t  </td></tr>\n\t  \n\t   <tr><td VALIGN=top nowrap>\n\t  <tt>-q/--quiet</tt>\n\t  </td><td VALIGN=top>\n\t  Suppress messages other than serious warnings and errors.\n\t  </td></tr>\n\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--no-update-check</tt>\n\t  </td><td VALIGN=top>\n\t  Turns off the automatic routine that contacts the Cufflinks server to check for a more \n\t  recent version.\n\t  </td></tr>\n\t  \n\t  </table><br/>\n\t\n\t  <h2 id=\"cufflinks_input\">Cufflinks Input</h2><br/>\n\t  <p>\n\t  \tCufflinks takes a text file of SAM alignments, or a binary SAM (BAM) file as input.  For more details\n\t  \ton the SAM format, see the <a href=\"http://samtools.sourceforge.net/SAM1.pdf\">\n\t  \tspecification</a>.  The RNA-Seq read mapper <a href=\"http://tophat.cbcb.umd.edu\">TopHat</a>\n\t  \tproduces output in this format, and is\n\t\trecommended for use with Cufflinks. However Cufflinks will accept SAM\n\t\talignments generated by any read mapper.  Here's an example of an alignment Cufflinks will accept:\n  \t  </p>\n\t  <br/>\n\t<pre>\ns6.25mer.txt-913508\t16\tchr1 4482736 255 14M431N11M * 0 0 \\\n   CAAGATGCTAGGCAAGTCTTGGAAG IIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:-\n\t</pre>\n\t\n\t  Note the use of the custom tag <tt>XS</tt>.  This attribute, which must \n\t  have a value of \"+\" or \"-\", indicates which strand the RNA that produced\n\t  this read came from.  While this tag can be applied to any alignment, \n\t  including unspliced ones, it <strong>must</strong> be present for all\n\t  spliced alignment records (those with a 'N' operation in the CIGAR string).\n\t  </p>\n\t  <p>\n\t  The SAM file supplied to Cufflinks <strong>must</strong> be sorted by \n\t  reference position.  If you aligned your reads with TopHat, your \n\t  alignments will be properly sorted already.  If you used another tool, you may\n\t  want to make sure they are properly sorted as follows:\n\t  </p>\n\t<br/>\n\t<blockquote>sort -k 3,3 -k 4,4n hits.sam > hits.sam.sorted</blockquote>\n\n      <br/>\n  <h2 id=\"cufflinks_output\">Cufflinks Output</h2><br/>\n\t<p>\n      Cufflinks produces three output files:\n\t</p>\n\t<br/>\n\t<ol>\n\t<h2 id=\"gtfout\">1) transcripts.gtf</h2>\n\t<p>\n\tThis <a href=\"http://mblab.wustl.edu/GTF22.html\">GTF</a> file contains Cufflinks'\n\tassembled isoforms.  The first 7 columns are standard GTF, and the last column\n\tcontains attributes, some of which are also standardized (\"gene_id\", and \"transcript_id\").\n\tThere one GTF record per row, and each record represents either a transcript\n\tor an exon within a transcript.  The columns are defined as follows:\n\t<table CELLSPACING=15>\n\t  <tr>\n\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>1</td><td VALIGN=top>seqname</td><td VALIGN=top><tt>chrX</tt></td><td VALIGN=top>Chromosome or contig name</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>2</td><td VALIGN=top>source</td><td VALIGN=top><tt>Cufflinks</tt></td><td VALIGN=top>The name of the program that generated this file (always 'Cufflinks')</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>3</td><td VALIGN=top>feature</td><td VALIGN=top><tt>exon</tt></td><td VALIGN=top>The type of record (always either \"transcript\" or \"exon\".</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>4</td><td VALIGN=top>start</td><td VALIGN=top><tt>77696957</tt></td><td VALIGN=top>The leftmost coordinate of this record (where 1 is the leftmost possible coordinate)</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>5</td><td VALIGN=top>end</td><td VALIGN=top><tt>77712009</tt></td><td VALIGN=top>The rightmost coordinate of this record, inclusive.</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>6</td><td VALIGN=top>score</td><td VALIGN=top><tt>77712009</tt></td><td VALIGN=top>The most abundant isoform for each gene is assigned a score of 1000.  Minor isoforms are scored by the ratio (minor FPKM/major FPKM)</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>7</td><td VALIGN=top>strand</td><td VALIGN=top><tt>+</tt></td><td VALIGN=top>Cufflinks' guess for which strand the isoform came from.  Always one of \"+\", \"-\", \".\"</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>7</td><td VALIGN=top>frame</td><td VALIGN=top><tt>.</tt></td><td VALIGN=top>Cufflinks does not predict where the start and stop codons (if any) are located within each transcript, so this field is not used.</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>8</td><td VALIGN=top>attributes</td><td VALIGN=top><tt>...</tt></td><td VALIGN=top>See below.</td>\n\t  </tr>\n\t  </table>\n\t\n\tEach GTF record is decorated with the following attributes:\n\t<table CELLSPACING=15>\n\t  <tr>\n\t\t<td VALIGN=top><strong>Attribute</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>gene_id</td><td VALIGN=top><tt>CUFF.1</tt></td><td VALIGN=top>Cufflinks gene id</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>transcript_id</td><td VALIGN=top><tt>CUFF.1.1</tt></td><td VALIGN=top>Cufflinks transcript id</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>FPKM</td><td VALIGN=top><tt>101.267</tt></td><td VALIGN=top>Isoform-level relative abundance in <strong>F</strong>ragments <strong>P</strong>er <strong>K</strong>ilobase of exon model per <strong>M</strong>illion mapped fragments</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>frac</td><td VALIGN=top><tt>0.7647</tt></td><td VALIGN=top>Reserved. Please ignore, as this attribute may be deprecated in the future</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>conf_lo</td><td VALIGN=top><tt>0.07</tt></td><td VALIGN=top>Lower bound of the 95% confidence interval of the abundance of this isoform, as a fraction of the isoform abundance.  That is, lower bound = FPKM * (1.0 - conf_lo)</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>conf_hi</td><td VALIGN=top><tt>0.1102</tt></td><td VALIGN=top>Upper bound of the 95% confidence interval of the abundance of this isoform, as a fraction of the isoform abundance. That is, upper bound = FPKM * (1.0 + conf_lo)</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>cov</td><td VALIGN=top><tt>100.765</tt></td><td VALIGN=top>Estimate for the absolute depth of read coverage across the whole transcript</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>full_read_support</td><td VALIGN=top><tt>yes</tt></td><td VALIGN=top>When RABT assembly is used, this attribute reports whether or not all introns and internal exons were fully covered by reads from the data.</td>\n\t  </tr>\n\t  </table>\n\t  <br/>\n\t<h2 id=\"transexpr\">2) isoforms.fpkm_tracking</h2>\n\t<p>\n\tThis file contains the estimated isoform-level expression values in the generic <a href=\"#tracking_format\">FPKM Tracking Format</a>.  Note, however that as there is only one sample, the \"q\" format is not used.\n\t</p>\n\t<br/>\n\t<h2 id=\"geneexpr\">3) genes.fpkm_tracking</h2>\n\t<p>\n\tThis file contains the estimated gene-level expression values in the generic <a href=\"#tracking_format\">FPKM Tracking Format</a>.  Note, however that as there is only one sample, the \"q\" format is not used.\n\t</p>\n\t<br/>\n\t</ol>\n\t<h2 id=\"cuffcompare\">Running Cuffcompare</h2><br/>\n\t<p>\n\tCufflinks includes a program that you can use to help analyze the transfrags\n\tyou assemble.  The program <tt>cuffcompare</tt> helps you:\n\t<ul>\n\t\t<li>Compare your assembled transcripts to a reference annotation</li>\n\t\t<li>Track Cufflinks transcripts across multiple experiments (e.g. across a time course)</li>\n\t</ul>\n\tFrom the command line, run <tt>cuffcompare</tt> as follows:\n\t<p>\n\t  <blockquote>\n\t   cuffcompare [options]* &lt;cuff1.gtf&gt; [cuff2.gtf] ... [cuffN.gtf]\n\t  </blockquote>\n\t\n\t<br/>\n\t<h2 id=\"cuffcomp_input\">Cuffcompare Input</h2><br/>\n\tCuffcompare takes Cufflinks' GTF output as input, and optionally can take \n\ta \"reference\" annotation (such as from <a href=\"ftp://ftp.ensembl.org/pub/current_gtf/\">Ensembl</a>)\n\t<br/>\n\t\n\t  <table CELLSPACING=15>\n\t  <tr><td VALIGN=top>\n\t  <b>Arguments:</b>\n\t  </td><td VALIGN=top>\n\t  </td></tr>\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>&lt;cuff1.gtf&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  A GTF file produced by cufflinks.\n\t  </td></tr>\n\t  <tr><td VALIGN=top>\n\t  <b>Options:</b>\n\t  </td><td VALIGN=top>\n\t  </td></tr>\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-h</tt>\n\t  </td><td VALIGN=top>\n\t  Prints the help message and exits   \n\t  </td></tr> \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-o &lt;outprefix&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  All output files created by Cuffcompare will have this prefix (e.g. &lt;outprefix&gt;.loci, &lt;outprefix&gt;.tracking, etc.).\n\t  If this option is not provided the default output prefix being used is: \"cuffcmp\"\n\t  </td></tr>\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-r</tt>\n\t  </td><td VALIGN=top>\n\t  An optional \"reference\" annotation <a href=\"gff.html\">GFF file</a>. Each sample is matched against\n\t  this file, and sample isoforms are tagged as overlapping, matching, or \n\t  novel where appropriate.  See the <a href=\"#refmap\">refmap</a> and \n\t  <a href=\"#tmap\">tmap</a> output file descriptions below.\n\t  </td></tr>\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-R</tt>\n\t  </td><td VALIGN=top>\n\t  If <tt>-r</tt> was specified, this option causes <tt>cuffcompare</tt> to \n\t  ignore reference transcripts that are not overlapped by any transcript in\n\t  one of <tt>cuff1.gtf</tt>,...,<tt>cuffN.gtf</tt>.  Useful for ignoring\n\t  annotated transcripts that are not present in your RNA-Seq samples and thus\n\t  adjusting the \"sensitivity\" calculation in the accuracy report\n\t  written in the &lt;outprefix&gt; file\n\t  </td></tr>\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-s &lt;seq_dir&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Causes <tt>cuffcompare</tt> to look into <seq_dir> for fasta files with the \n\t  underlying genomic sequences (one file per contig) against which your \n\t  reads were aligned for some optional classification functions.  For example,\n\t  Cufflinks transcripts consisting mostly of lower-case bases are classified\n\t  as repeats.  Note that &lt;seq_dir&gt; <strong>must</strong> contain one\n\t  fasta file per reference chromosome, and each file must be named after\n\t  the chromosome, and have a <tt>.fa</tt> or <tt>.fasta</tt> extension.\n\t  </td></tr>\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-C</tt>\n\t  </td><td VALIGN=top>\n\t   Enables the \"contained\" transcripts to be also written in the <i>&lt;outprefix&gt;.combined.gtf</i>file, with the attribute \"contained_in\" \n\t   showing the first container transfrag found. By default, without this option, <tt>cuffcompare</tt> does not write in that file isoforms that were found to be \n\t   fully contained/covered (with the same compatible intron structure) by other transfrags in the same locus. \n\t  </td></tr>\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-V</tt>\n\t  </td><td VALIGN=top>\n\t   Cuffcompare is a little more verbose about what it's doing, printing messages to stderr, and it will also show warning messages about any inconsistencies or potential issues \n\t   found while reading the given GFF file(s).\n\t  </td></tr>\n\t  </table><br/>\n  <h2 id=\"cuffcomp_output\">Cuffcompare Output</h2><br/>\n\t<p>\n      Cuffcompare produces the following output files:\n\t</p>\n\t<br/>\n\t<ol>\n\t<h2 id=\"stats\">1) &lt;outprefix&gt;.stats</h2>\n\t<p>\n\tCuffcompare reports various statistics related to the \"accuracy\" of the transcripts \n\tin each sample when compared to the reference annotation data. The typical gene finding measures of \"sensitivity\"\n\tand \"specificity\" (as defined in Burset, M., Guig&oacute;, R. : <b>Evaluation of gene structure prediction programs</b> (1996) <i>Genomics</i>, 34 (3), pp. 353-367. \n        <a href=\"http://dx.doi.org/10.1006/geno.1996.0298\">doi: 10.1006/geno.1996.0298</a>) \n        are calculated at various levels (nucleotide, exon, intron, transcript, gene) for each input file and reported in this file.\n        The <b>Sn</b> and <b>Sp</b> columns show specificity and sensitivity values at each level, while the <i>fSn</i> and <i>fSp</i> columns \n        are \"fuzzy\" variants of these same accuracy calculations, allowing for a very small variation in exon boundaries to still be counted as a \"match\".\n        (If the -o option was not given the default prefix \"cuffcmp\" is used and these stats will be printed into a file named <i>cuffcmp.stats</i> in the current directory)\n\t<br/>\n\t<br/>\n\t<h2 id=\"combin\">2) &lt;outprefix&gt;.combined.gtf</h2>\n\t<p>\n\tCuffcompare reports a GTF file containing the \"union\" of all transfrags in \n\teach sample.  If a transfrag is present in both samples, it is thus reported \n\tonce in the combined gtf.\n        <br/>\n\t<br/>\n\t<h2 id=\"track\">3) &lt;outprefix&gt;.tracking</h2>\n\t\t<p>\n\t\tThis file matches transcripts up between samples.  Each row contains \n\t\ta transcript structure that is present in one or more input GTF files. \n\t\tBecause the transcripts will generally have different IDs (unless you \n\t\tassembled your RNA-Seq reads against a reference transcriptome), \n\t\t<tt>cuffcompare</tt> examines the structure of each the transcripts, \n\t\tmatching transcripts that agree on the coordinates and order of all of\n\t\ttheir introns, as well as strand.  Matching transcripts are allowed to \n\t\tdiffer on the length of the first and last exons, since these lengths\n\t\twill naturally vary from sample to sample due to the random nature of \n\t\tsequencing. \n\t\t</p>\n\t\t\n\t\t<p>\n\t\tIf you ran <tt>cuffcompare</tt> with the -r option, the first and second\n\t\tcolumns contain the closest matching reference transcript to the one\n\t\tdescribed by each row.  \n\t\t</p>\n\t\t<br/>\n\t\tHere's an example of a line from the tracking file:<br/><br/>\n\t\t<pre>\nTCONS_00000045 XLOC_000023 Tcea|uc007afj.1\tj\t\\\n     q1:exp.115|exp.115.0|100|3.061355|0.350242|0.350207 \\\n     q2:60hr.292|60hr.292.0|100|4.094084|0.000000|0.000000\n\t\t</pre>\n\t\t\n\t\tIn this example, a transcript present in the two input files, called \n\t\t<tt>exp.115.0</tt> in the first and <tt>60hr.292.0</tt> in the second, \n\t\tdoesn't match any reference transcript exactly, but shares exons with\n\t\t<tt>uc007afj.1</tt>, an isoform of the gene Tcea, as indicated by the \n\t\t<a href=\"#class_codes\">class code</a> <tt>j</tt>.\n\t\t\n\t\tThe first three columns are as follows:<br/>\n\t\t\n\t\t<table CELLSPACING=15>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><strong>Column number</strong></td>\n\t\t\t<td VALIGN=top><strong>Column name</strong></td>\n\t\t\t<td VALIGN=top><strong>Example</strong></td>\n\t\t\t<td VALIGN=top><strong>Description</strong></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>1</td>\n\t\t\t<td VALIGN=top>Cufflinks transfrag id</td>\n\t\t\t<td VALIGN=top><tt>TCONS_00000045</tt></td>\n\t\t\t<td VALIGN=top>A unique internal id for the transfrag</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>2</td>\n\t\t\t<td VALIGN=top>Cufflinks locus id</td>\n\t\t\t<td VALIGN=top><tt>XLOC_000023</tt></td>\n\t\t\t<td VALIGN=top>A unique internal id for the locus</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3</td>\n\t\t\t<td VALIGN=top>Reference gene id</td>\n\t\t\t<td VALIGN=top><tt>Tcea</tt></td>\n\t\t\t<td VALIGN=top>The gene_name attribute of the reference GTF record \n\t\t\t\tfor this transcript, or '-' if no reference transcript overlaps \n\t\t\t\tthis Cufflinks transcript</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>4</td>\n\t\t\t<td VALIGN=top>Reference transcript id</td>\n\t\t\t<td VALIGN=top><tt>uc007afj.1</tt></td>\n\t\t\t<td VALIGN=top>The transcript_id attribute of the reference GTF \n\t\t\t\trecord for this transcript, or '-' if no reference transcript \n\t\t\t\toverlaps this Cufflinks transcript</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>5</td>\n\t\t\t<td VALIGN=top>Class code</td>\n\t\t\t<td VALIGN=top><tt>c</tt></td>\n\t\t\t<td VALIGN=top>The type of match between the Cufflinks transcripts\n\t\t\t\t in column  6 and the reference transcript. See <a href=\"#class_codes\">class codes</a></td>\n\t\t  </tr>\n\t\t  </table>\n\t\t\n\t\tEach of the columns after the fifth have the following format:\n\t\t\n\t\t<blockquote>qJ:&lt;gene_id&gt;|&lt;transcript_id&gt;|&lt;FMI&gt;|&lt;FPKM&gt;|&lt;conf_lo&gt;|&lt;conf_hi&gt;|&lt;cov&gt;|&lt;len&gt;</blockquote><br/>\n\t\t\n\t\tA transcript need not be present in all samples to be reported in the tracking \n\t\tfile. A sample not containing a transcript will have a \"-\" in its entry\n\t\tin the row for that transcript.\n\t<br/>\n\t<br/>(The following output files are created for each of the &lt;cuff_in&gt; file given, in the same directories where the &lt;cuff_in&gt; files reside)\n\t<br/>\n\t<br/>\n\t<h2 id=\"refmap\">4) &lt;cuff_in&gt;.refmap</h2>\n\t<p>\n\tThis tab delimited file lists, for each reference transcript, which cufflinks\n\ttranscripts either fully or partially match it.  There is one row per\n\treference transcript, and the columns are as follows:\n\t<table CELLSPACING=15>\n\t  <tr>\n\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>1</td><td VALIGN=top>Reference gene name</td><td VALIGN=top><tt>Myog</tt></td><td VALIGN=top>The gene_name attribute of the reference GTF record for this transcript, if present. Otherwise gene_id is used.</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>2</td><td VALIGN=top>Reference transcript id</td><td VALIGN=top><tt>uc007crl.1</tt></td><td VALIGN=top>The transcript_id attribute of the reference GTF record for this transcript</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>3</td><td VALIGN=top>Class code</td><td VALIGN=top><tt>c</tt></td><td VALIGN=top>The type of match between the Cufflinks transcripts in column  4 and the reference transcript.  One of either 'c' for partial match, or '=' for full match.</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>4</td><td VALIGN=top>Cufflinks matches</td><td VALIGN=top><tt>CUFF.23567.0,CUFF.24689.0</tt></td><td VALIGN=top>A comma separated list of Cufflinks transcript ids matching the reference transcript</td>\n\t  </tr>\n\t  </table>\n\t<h2 id=\"tmap\">5) &lt;cuff_in&gt;.tmap</h2>\n\t<p>\n\tThis tab delimited file lists the most closely matching reference \n\ttranscript for each Cufflinks transcript.  There is one row per Cufflinks transcript, \n\tand the columns are as follows:\n\t<table CELLSPACING=15>\n\t  <tr>\n\t\t<td VALIGN=top><strong>Column number</strong></td>\n\t\t<td VALIGN=top><strong>Column name</strong></td>\n\t\t<td VALIGN=top><strong>Example</strong></td>\n\t\t<td VALIGN=top><strong>Description</strong></td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>1</td>\n\t\t<td VALIGN=top>Reference gene name</td>\n\t\t<td VALIGN=top><tt>Myog</tt></td>\n\t\t<td VALIGN=top>The gene_name attribute of the reference GTF record for this transcript, if present. Otherwise gene_id is used.</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>2</td>\n\t\t<td VALIGN=top>Reference transcript id</td>\n\t\t<td VALIGN=top><tt>uc007crl.1</tt></td>\n\t\t<td VALIGN=top>The transcript_id attribute of the reference GTF record for this transcript</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>3</td>\n\t\t<td VALIGN=top>Class code</td>\n\t\t<td VALIGN=top><tt>c</tt></td>\n\t\t<td VALIGN=top>The type of relationship between the Cufflinks transcripts in column  4 and the reference transcript (as described in the <b>Class Codes</b> section below)</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>4</td>\n\t\t<td VALIGN=top>Cufflinks gene id</td>\n\t\t<td VALIGN=top><tt>CUFF.23567</tt></td>\n\t\t<td VALIGN=top>The Cufflinks internal gene id</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>5</td>\n\t\t<td VALIGN=top>Cufflinks transcript id</td>\n\t\t<td VALIGN=top><tt>CUFF.23567.0</tt></td>\n\t\t<td VALIGN=top>The Cufflinks internal transcript id</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>6</td>\n\t\t<td VALIGN=top>Fraction of major isoform (FMI)</td>\n\t\t<td VALIGN=top><tt>100</tt></td>\n\t\t<td VALIGN=top>The expression of this transcript expressed as a fraction of the major isoform for the gene.  Ranges from 1 to 100.</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>7</td>\n\t\t<td VALIGN=top>FPKM</td>\n\t\t<td VALIGN=top><tt>1.4567</tt></td>\n\t\t<td VALIGN=top>The expression of this transcript expressed in FPKM</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>8</td>\n\t\t<td VALIGN=top>FPKM_conf_lo</td>\n\t\t<td VALIGN=top><tt>0.7778</tt></td>\n\t\t<td VALIGN=top>The lower limit of the 95% FPKM confidence interval</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>9</td>\n\t\t<td VALIGN=top>FPKM_conf_hi</td>\n\t\t<td VALIGN=top><tt>1.9776</tt></td>\n\t\t<td VALIGN=top>The upper limit of the 95% FPKM confidence interval</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>10</td>\n\t\t<td VALIGN=top>Coverage</td>\n\t\t<td VALIGN=top><tt>3.2687</tt></td>\n\t\t<td VALIGN=top>The estimated average depth of read coverage across the transcript.</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>11</td>\n\t\t<td VALIGN=top>Length</td>\n\t\t<td VALIGN=top><tt>1426</tt></td>\n\t\t<td VALIGN=top>The length of the transcript</td>\n\t  </tr>\n\t  <tr>\n\t\t<td VALIGN=top>12</td>\n\t\t<td VALIGN=top>Major isoform ID</td>\n\t\t<td VALIGN=top><tt>CUFF.23567.0</tt></td>\n\t\t<td VALIGN=top>The Cufflinks ID of the gene's major isoform</td>\n\t  </tr>\n\t  </table>\n\t\t\n\t\t<br/><br/><strong id=\"class_codes\">Class Codes</strong><br/><br/>\n\t\tIf you ran <tt>cuffcompare</tt> with the <tt>-r</tt> option, tracking rows will\n\t\tcontain the following values.  If you did not use <tt>-r</tt>, the rows will\n\t\tall contain \"-\" in their class code column.\n\t\t<table CELLSPACING=15>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><strong>Priority</strong></td>\n\t\t\t<td VALIGN=top><strong>Code</strong></td>\n\t\t\t<td VALIGN=top><strong>Description</strong></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>1</td>\n\t\t\t<td VALIGN=top><tt>=</tt></td>\n\t\t\t<td VALIGN=top>Complete match of intron chain</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>2</td>\n\t\t\t<td VALIGN=top><tt>c</tt></td>\n\t\t\t<td VALIGN=top>Contained</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3</td>\n\t\t\t<td VALIGN=top><tt>j</tt></td>\n\t\t\t<td VALIGN=top>Potentially novel isoform (fragment): at least one splice junction is shared with a reference transcript</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>4</td>\n\t\t\t<td VALIGN=top><tt>e</tt></td>\n\t\t\t<td VALIGN=top>Single exon transfrag overlapping a reference \n\t\t\t\texon and at least 10 bp of a reference intron, indicating a \n\t\t\t\tpossible pre-mRNA fragment.</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>5</td>\n\t\t\t<td VALIGN=top><tt>i</tt></td>\n\t\t\t<td VALIGN=top>A transfrag falling entirely within a \n\t\t\t\treference intron</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>6</td>\n\t\t\t<td VALIGN=top><tt>o</tt></td>\n\t\t\t<td VALIGN=top>Generic exonic overlap with a reference transcript</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>7</td>\n\t\t\t<td VALIGN=top><tt>p</tt></td>\n\t\t\t<td VALIGN=top>Possible polymerase run-on fragment (within 2Kbases of a reference transcript)</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>8</td>\n\t\t\t<td VALIGN=top><tt>r</tt></td>\n\t\t\t<td VALIGN=top>Repeat. Currently determined by looking at the soft-masked reference\n\t\t\t\tsequence and applied to transcripts where at least 50% of the \n\t\t\t\tbases are lower case</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>9</td>\n\t\t\t<td VALIGN=top><tt>u</tt></td>\n\t\t\t<td VALIGN=top>Unknown, intergenic transcript</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>10</td>\n\t\t\t<td VALIGN=top><tt>x</tt></td>\n\t\t\t<td VALIGN=top>Exonic overlap with reference on the opposite strand</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>11</td>\n\t\t\t<td VALIGN=top><tt>s</tt></td>\n\t\t\t<td VALIGN=top>An intron of the transfrag overlaps a reference intron on the opposite strand (likely due to read mapping errors)</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>12</td>\n\t\t\t<td VALIGN=top><tt>.</tt></td>\n\t\t\t<td VALIGN=top>(.tracking file only, indicates multiple classifications)</td>\n\t\t\t<td VALIGN=top></td>\n\t\t  </tr>\n\t\t  </table>\n\t\t\n\t\t<br/>\n\t\t</ol>\n\t\t<h2 id=\"cuffmerge\">Merging assemblies with cuffmerge</h2><br/>\n\t\t<p>\n\t\tCufflinks includes a script called cuffmerge that you can use to merge \n\t\ttogether several Cufflinks assemblies.  It handles also handles running\n\t\t Cuffcompare for you, and automatically filters a number of transfrags \n\t\tthat are probably artfifacts.  If you have a reference GTF file available,\n\t\t you can provide it to the script in order to gracefully merge novel \n\t\tisoforms and known isoforms and maximize overall assembly quality.  \n\t\tThe main purpose of this script is to make it easier to make an assembly \n\t\tGTF file suitable for use with Cuffdiff.   \n\t\t\n\t\tFrom the command line, run <tt>cuffmerge</tt> as follows:\n\t\t<p>\n\t\t  <blockquote>\n\t\t   cuffmerge [options]* &lt;assembly_GTF_list.txt&gt;\n\t\t  </blockquote>\n\n\t\t<br/>\n\t\t<h2 id=\"merger_input\">cuffmerge Input</h2><br/>\n\t    cuffmerge takes several assembly GTF files from Cufflinks' as input.  Input GTF files must be specified in a \"manifest\" file listing full paths to the files. \n\t\t<br/>\n\n\t\t  <table CELLSPACING=15>\n\t\t  <tr><td VALIGN=top>\n\t\t  <b>Arguments:</b>\n\t\t  </td><td VALIGN=top>\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>&lt;assembly_list.txt&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Text file \"manifest\" with a list (one per line) of GTF files that you'd like to merge together into a single GTF file.\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top>\n\t\t  <b>Options:</b>\n\t\t  </td><td VALIGN=top>\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-h/--help</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Prints the help message and exits   \n\t\t  </td></tr> \n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-o &lt;outprefix&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Write the summary stats into the text output file &lt;outprefix&gt;(instead of stdout)\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-g/--ref-gtf</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  An optional \"reference\" annotation GTF.  The input assemblies are merged together with \n\t\t  the reference GTF and included in the final output.\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-p/--num-threads &lt;int&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Use this many threads to align reads. The default is 1.\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-s/--ref-sequence &lt;seq_dir&gt;/&lt;seq_fasta&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  This argument should point to the genomic DNA sequences for the reference. \n\t\t  If a directory, it should contain one fasta file per contig. If a \n\t\t  multifasta file, all contigs should be present.  The merge script will \n\t\t  pass this option to <tt>cuffcompare</tt>, which will use the sequences\n\t\t  to assist in classifying transfrags and excluding artifacts (e.g. repeats). For example,\n\t\t  Cufflinks transcripts consisting mostly of lower-case bases are classified\n\t\t  as repeats.  Note that &lt;seq_dir&gt; <strong>must</strong> contain one\n\t\t  fasta file per reference chromosome, and each file must be named after\n\t\t  the chromosome, and have a <tt>.fa</tt> or <tt>.fasta</tt> extension.\n\t\t  </td></tr>\n\t\t  </table><br/>\n\t  <h2 id=\"merger_output\">cuffmerge Output</h2><br/>\n\t\t<p>\n\t      cuffmerge produces a GTF file that contains an assembly that merges together the input assemblies.\n\t\t</p>\n\t\t<br/>\n\t\t<ol>\n\t\t\t<b>&lt;outprefix&gt;/merged.gtf</b>\n\t\t\t<p>\n\t\t</ol>\n\t\t\t<br/>\n\t\t\t<br/>\n\t\t\t</ol>\n\t\t<h2 id=\"cuffquant\">Running Cuffquant</h2><br/>\n\t\t\t\tRun <tt>cuffquant</tt> from the command line as follows:\n\t\t\t  <blockquote>\n\t\t \t   Usage: cuffquant [options]* &lt;annotation.(gtf/gff)&gt; &lt;aligned_reads.(sam/bam)&gt;\n\t\t\t  </blockquote>\n\t\t\t  <p>\n\t\t\t  The following is a detailed description of the options used to control\n\t\t\t  Cuffquant:\n\t\t\t  </p><br/>\n\n\t\t\t  <table CELLSPACING=15>\n\t\t\t  <tr><td VALIGN=top>\n\t\t\t  <b>Arguments:</b>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  </td></tr>\n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>&lt;annotation.(gtf/gff)&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Tells Cuffquant to use the supplied reference annotation (<a href=\"gff.html\">a GFF file</a>)\n\t\t\t  to estimate isoform expression. The program\n\t\t\t  will ignore alignments not structurally compatible with any reference transcript.\n\t\t\t  </td></tr>\n\t\t\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>&lt;aligned_reads.(sam/bam)&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  A file of RNA-Seq read alignments in the <a href=\"http://samtools.sourceforge.net\">\n\t\t\t  SAM format</a>.  SAM is a standard short read alignment, that allows aligners to \n\t\t\t  attach custom tags to individual alignments, and Cuffquant requires that\n\t\t\t  the alignments you supply have some of these tags.  Please see <a href=\"#input\">\n\t\t\t  Input formats</a> for more details.\n\t\t\t  </td></tr>\n\t  \n\t\t\t  <tr><td VALIGN=top>\n\t\t\t  <b>General Options:</b>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  </td></tr>\n\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-h/--help</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Prints the help message and exits   \n\t\t\t  </td></tr> \n\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-o/--output-dir &lt;string&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Sets the name of the directory in which Cuffquant will write all of its \n\t\t\t  output.  The default is \"./\".\n\t\t\t  </td></tr>\n\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-p/--num-threads &lt;int&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Use this many threads to align reads. The default is 1.\n\t\t\t  </td></tr>\n\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-M/--mask-file &lt;mask.(gtf/gff)&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Tells Cuffquant to ignore all reads that could have come from transcripts in this GTF \n\t\t\t  file. We recommend including any annotated rRNA, mitochondrial transcripts other abundant\n\t\t\t  transcripts you wish to ignore in your analysis in this file.  Due to variable efficiency\n\t\t\t  of mRNA enrichment methods and rRNA depletion kits, masking these transcripts often \n\t\t\t  improves the overall robustness of transcript abundance estimates. \n\t\t\t  </td></tr>\n\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-b/--frag-bias-correct &lt;genome.fa&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Providing Cuffquant with a multifasta file via this option instructs it to run  \n\t\t\t  bias detection and correction algorithm which can significantly improve accuracy of \n\t\t\t  transcript abundance estimates.  See <a href=howitworks.html#hsbi>How Cufflinks Works</a> for more details.\n\t\t\t  </td></tr>\n\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-u/--multi-read-correct</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Tells Cuffquant to do an initial estimation procedure to more accurately weight reads\n\t\t\t  mapping to multiple locations in the genome.  See <a href=howitworks.html#hmul>How Cufflinks Works</a> for more details.\n\t\t\t  </td></tr>\n\t\t\t  <tr><td VALIGN=top>\n\t  \n\t\t\t  <tt>--library-type</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  See <a href=\"#library\">Library Types</a>\n\t\t\t  </td></tr>\n\t\t\t  <tr>\t\n\t  \n\t\t\t  <tr><td VALIGN=top>\n\t\t\t  <b>Advanced Abundance Estimation Options:</b>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  </td></tr>\n\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\t\n\t\t\t  <tt>-m/--frag-len-mean &lt;int&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  This is the expected (mean) fragment length. The default is 200bp. <br/><b>Note: \n\t\t\t  Cuffquant learns the fragment length mean for each SAM file, so using this option is\n\t\t\t  no longer recommended with paired-end reads.</b>\n\t\t\t  </td></tr>\n\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-s/--frag-len-std-dev &lt;int&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  The standard deviation for the distribution on fragment lengths.  The default is 80bp. <br/><b>Note: \n\t\t\t  Cuffquant learns the fragment length standard deviation for each SAM file, so using this option is\n\t\t\t  no longer recommended with paired-end reads.</b>\n\t\t\t  </td></tr>\n\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>--max-mle-iterations &lt;int&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Sets the number of iterations allowed during maximum likelihood estimation of abundances. Default: 5000  \n\t\t\t  </td></tr>\n\t\n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>--max-bundle-frags &lt;int&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Sets the maximum number of fragments a locus may have before being skipped. Default: 1000000  \n\t\t\t  </td></tr>\n\t\n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>--no-effective-length-correction</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Cuffquant will not employ its \"effective\" length normalization to transcript FPKM. \n\t\t\t  </td></tr>\n\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>--no-length-correction</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Cuffquant will not normalize fragment counts by transcript length at all.  Use this option when fragment count is independent of the size of the features being quantified (e.g. for small RNA libraries, where no fragmentation takes place, or 3 prime end sequencing, where sampled RNA fragments are all essentially the same length).  Experimental option, use with caution. \n\t\t\t  </td></tr>\n\t\n\t\t\t  <tr><td VALIGN=top>\n\t\t\t  <b>Advanced Program Behavior Options:</b>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  </td></tr>\n\t\n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-v/--verbose</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Print lots of status updates and other diagnostic information.\n\t\t\t  </td></tr>\n\t  \n\t\t\t   <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-q/--quiet</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Suppress messages other than serious warnings and errors.\n\t\t\t  </td></tr>\n\n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>--no-update-check</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Turns off the automatic routine that contacts the Cufflinks server to check for a more \n\t\t\t  recent version.\n\t\t\t  </td></tr>\n\t  \n\t\t\t  </table><br/>\n\t\n\t\t  <h2 id=\"cufflinks_output\">Cuffquant Output</h2><br/>\n\t\t\t<p>\n\t\t      Cuffquant produces writes a single output file, <tt>abundances.cxb</tt>, into the output directory. CXB files are binary files, and can be passed to Cuffnorm or Cuffdiff for further processing.\n\t\t\t</p>\n\t\t\t<br/>\t\t\n\t\t\n\t\t<h2 id=\"cuffdiff\">Running Cuffdiff</h2><br/>\n\t\t<p>\n\t\tCufflinks includes a program, \"Cuffdiff\", that you can use to find significant changes \n\t\tin transcript expression, splicing, and promoter use.  From the command line, run <tt>cuffdiff</tt> as follows:\n\t\t<p>\n\t\t<blockquote>\n\t\tcuffdiff [options]* &lt;transcripts.gtf&gt; &lt;sample1_replicate1.sam[,...,sample1_replicateM.sam]&gt; &lt;sample2_replicate1.sam[,...,sample2_replicateM.sam]&gt;... [sampleN.sam_replicate1.sam[,...,sample2_replicateM.sam]]\n\t\t</blockquote>\n\t\t\n\t\t<br/>\n\t\t<h2 id=\"cuffdiff_input\">Cuffdiff Input</h2><br/>\n\t\tCuffdiff takes a GTF2/GFF3 file of transcripts as input, along with two or more \n\t\tSAM files containing the fragment alignments for two or more samples. \n\t\tIt produces a number of output files that contain test results for \n\t\tchanges in expression at the level of transcripts, primary transcripts, \n\t\tand genes. It also tracks changes in the relative abundance of transcripts sharing a common\n\t\ttranscription start site, and in the relative abundances of the primary \n\t\ttranscripts of each gene.  Tracking the former allows one to see changes in \n\t\tsplicing, and the latter lets one see changes in relative promoter use \n\t\twithin a gene.\n\t\t<p>\n\t\tIf you have more than one <b>replicate</b> for a sample, supply the SAM files for \n\t\tthe sample as a single <b>comma-separated</b> list.  It is not necessary to \n\t\thave the same number of replicates for each sample.\n\t\t<p>\n\t\tNote that Cuffdiff can also accepted BAM files (which are binary, compressed SAM files).  It can also accept CXB files produced by Cuffquant.  Note that mixing SAM and BAM files is supported, but you cannot currently mix CXB and SAM/BAM.  If one of the samples is supplied as a CXB file, all of the samples must be supplied as CXB files.\n\t\t<p>\n\t\tCuffdiff requires that transcripts in the input GTF be annotated with \n\t\tcertain attributes in order to look for changes in primary transcript\n\t\texpression, splicing, coding output, and promoter use.  These attributes \n\t\tare:\n\t\t\n\t\t<table CELLSPACING=15>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><strong>Attribute</strong></td>\n\t\t\t<td VALIGN=top><strong>Description</strong></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>tss_id</td>\n\t\t\t<td VALIGN=top>The ID of this transcript's inferred start site.  \n\t\t\t\tDetermines which primary transcript this processed transcript \n\t\t\t\tis believed to come from. Cuffcompare appends this attribute to\n\t\t\t\tevery transcript reported in the <i>.combined.gtf</i> file.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>p_id</td>\n\t\t\t<td VALIGN=top>The ID of the coding sequence this transcript contains. This\n\t\t\t\tattribute is attached by Cuffcompare to the <i>.combined.gtf</i> records\n\t\t\t\tonly  when it is run with a reference annotation that include CDS \n\t\t\t\trecords.  Further, differential CDS analysis is <b>only</b> \n\t\t\t\tperformed when all isoforms of a gene have <tt>p_id</tt> \n\t\t\t\tattributes, because neither Cufflinks nor Cuffcompare attempt to\n\t\t\t\tassign an open reading frame to transcripts.</td>\n\t\t  </tr>\n\t\t  </table>\n\t\t<p>\n        <p>\n        <ul><b>Note: </b>\n        If an arbitrary GTF/GFF3 file is used as input (instead of the <i>.combined.gtf</i> file produced by \n        Cuffcompare), these attributes will not be present, but Cuffcompare can still be used to obtain these\n        attributes with a command like this:\n        <br/><br/>\n        <ul>\n        <tt>        \n        cuffcompare -s /path/to/genome_seqs.fa -CG -r annotation.gtf annotation.gtf\n        </tt>\n        </ul>\n        <br>\n        \n        The resulting <tt>cuffcmp.combined.gtf</tt> file created by this command will have the <tt>tss_id</tt> and \n        <tt>p_id</tt> attributes added to each record and this file can be used as input for <tt>cuffdiff</tt>.\n        </ul>\n        <p>\n\t\t\t\n\t\t  <table CELLSPACING=15>\n\t\t  <tr><td VALIGN=top>\n\t\t  <b>Arguments:</b>\n\t\t  </td><td VALIGN=top>\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>&lt;transcripts.(gtf/gff)&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  A transcript annotation file produced by cufflinks, cuffcompare, or other source.\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>&lt;sample1.(sam/bam/cxb)&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  A SAM file of aligned RNA-Seq reads. If more than two are provided,\n\t\t  Cuffdiff tests for differential expression and regulation between all pairs of \n\t\t  samples. \n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top>\n\t\t  <b>Options:</b>\n\t\t  </td><td VALIGN=top>\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-h/--help</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Prints the help message and exits   \n\t\t  </td></tr> \n\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-o/--output-dir &lt;string&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Sets the name of the directory in which Cuffdiff will write all of its \n\t\t  output.  The default is \"./\".\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-L/--labels &lt;label1,label2,...,labelN&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Specify a label for each sample, which will be included in various output files \n\t\t  produced by Cuffdiff.\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-p/--num-threads &lt;int&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Use this many threads to align reads. The default is 1.\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-T/--time-series</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Instructs Cuffdiff to analyze the provided samples as a time series, rather than \n\t\t  testing for differences between all pairs of samples.  Samples should be provided in\n\t\t  increasing time order at the command line (e.g first time point SAM, second timepoint SAM, etc.) \n\t\t  </td></tr>\n\t\t\t\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>--total-hits-norm</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  With this option, Cufflinks counts all fragments, including those not compatible with any reference transcript, towards the number of mapped fragments used in the FPKM denominator.  This option can be combined with <tt>-N/--upper-quartile-norm</tt>.  It is inactive by default.\n\t\t  </td></tr>\n\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>--compatible-hits-norm</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  With this option, Cufflinks counts only those fragments compatible with some reference transcript towards the number of mapped fragments used in the FPKM denominator.  This option can be combined with <tt>-N/--upper-quartile-norm</tt>. Using this mode is generally recommended in Cuffdiff to reduce certain types of bias caused by differential amounts of ribosomal reads which can create the impression of falsely differentially expressed genes. It is active by default.  \n\t\t  </td></tr>\n\t\t\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-b/--frag-bias-correct &lt;genome.fa&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Providing Cufflinks with the multifasta file your reads were mapped to via this option instructs it to run our \n\t\t  bias detection and correction algorithm which can significantly improve accuracy of \n\t\t  transcript abundance estimates.  See <a href=howitworks.html#hsbi>How Cufflinks Works</a> for more details.\n\t\t  </td></tr>\n\t\t  \n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-u/--multi-read-correct</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Tells Cufflinks to do an initial estimation procedure to more accurately weight reads\n\t\t  mapping to multiple locations in the genome.  See <a href=howitworks.html#hmul>How Cufflinks Works</a> for more details.\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top>\n\t\t   \n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-c/--min-alignment-count &lt;int&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  The minimum number of alignments in a locus for needed to conduct\n\t\t  significance testing on changes in that locus observed between samples.  \n\t\t  If no testing is performed, changes in the locus are deemed not signficant, \n\t\t  and the locus' observed changes don't contribute to correction for \n\t\t  multiple testing. The default is 10 fragment alignments. \n\t\t  </td></tr>\n\t\t  \n\t\t   <tr><td VALIGN=top nowrap>\n\t  <tt>-M/--mask-file &lt;mask.(gtf/gff)&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Tells Cuffdiff to ignore all reads that could have come from transcripts in this GTF \n\t  file. We recommend including any annotated rRNA, mitochondrial transcripts other abundant\n\t  transcripts you wish to ignore in your analysis in this file.  Due to variable efficiency\n\t  of mRNA enrichment methods and rRNA depletion kits, masking these transcripts often \n\t  improves the overall robustness of transcript abundance estimates. \n\t  </td></tr>\n\t\t  \n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>--FDR &lt;float&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  The allowed false discovery rate.  The default is 0.05. \n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\t\n\t\t  <tt>--library-type</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  See <a href=\"#library\">Library Types</a>\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\t\n\t\t  <tt>--library-norm-method</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  See <a href=\"#library_norm_meth\">Library Normalization Methods</a>\n\t\t  </td></tr>\n\t\t  <tr><td VALIGN=top nowrap>\t\n\t\t  <tt>--dispersion-method</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  See <a href=\"#dispersion_meth\">Cross-replicate dispersion estimation methods</a>\n\t\t  </td></tr>\n\t\t  \n\t  <tr><td VALIGN=top>\n\t  <b>Advanced Options:</b>\n\t  </td><td VALIGN=top>\n\t  </td></tr>\n\t  \n\t   <tr><td VALIGN=top nowrap>\t\n\t  <tt>-m/--frag-len-mean &lt;int&gt;</tt>\n\t</td><td VALIGN=top>\n\t  This is the expected (mean) fragment length. The default is 200bp. <br/><b>Note: \n\t  Cufflinks now learns the fragment length mean for each SAM file, so using this option is\n\t  no longer recommended with paired-end reads.</b>\n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-s/--frag-len-std-dev &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  The standard deviation for the distribution on fragment lengths.  The default is 80bp. <br/><b>Note: \n\t  Cufflinks now learns the fragment length standard deviation for each SAM file, so using this option is\n\t  no longer recommended with paired-end reads.</b>\n\t  </td></tr>\n\t  \n\t <tr><td VALIGN=top nowrap>\n\t\t  <tt>--num-importance-samples &lt;int&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Deprecated\n\t\t  </td></tr> \n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>--max-mle-iterations &lt;int&gt;</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Sets the number of iterations allowed during maximum likelihood estimation of abundances. Default: 5000  \n\t\t  </td></tr>\n\t\t  \n\t\t  \t  <tr><td VALIGN=top nowrap>\n\t  <tt>-v/--verbose</tt>\n\t  </td><td VALIGN=top>\n\t  Print lots of status updates and other diagnostic information.\n\t  </td></tr>\n\t  \n\t   <tr><td VALIGN=top nowrap>\n\t  <tt>-q/--quiet</tt>\n\t  </td><td VALIGN=top>\n\t  Suppress messages other than serious warnings and errors.\n\t  </td></tr>\n\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--no-update-check</tt>\n\t  </td><td VALIGN=top>\n\t  Turns off the automatic routine that contacts the Cufflinks server to check for a more \n\t  recent version.\n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--poisson-dispersion</tt>\n\t  </td><td VALIGN=top>\n\t  Use the Poisson fragment dispersion model instead of learning one \n\t  in each condition.\n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--emit-count-tables</tt>\n\t  </td><td VALIGN=top>\n\t  Cuffdiff will output a file for each condition (called &lt;sample&gt;_counts.txt)\n\t  containing the fragment counts, fragment count variances, and fitted\n\t  variance model.  For internal debugging only. This option will be removed\n\t  in a future version of Cuffdiff.\n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>-F/--min-isoform-fraction &lt;0.0-1.0&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Cuffdiff will round down to zero the abundance of alternative isoforms quantified at below \n\t  the specified fraction of the major isoforms. This is done after MLE estimation\n      but before MAP estimation to improve robustness of confidence interval\n      generation and differential expression analysis.  The default is 1e-5, and \n      we recommend you not alter this parameter. \n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--max-bundle-frags &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Sets the maximum number of fragments a locus may have before being skipped. Skipped loci are marked with status HIDATA. Default: 1000000  \n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--max-frag-count-draws &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Cuffdiff will make this many draws from each transcript's predicted negative binomial \n\t  random numbder generator.  Each draw is a number of fragments that will be \n\t  probabilistically assigned to the transcripts in the transcriptome.  Used to estimate\n\t  the variance-covariance matrix on assigned fragment counts.  Default: 100. \n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--max-frag-assign-draws &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  For each fragment drawn from a transcript, Cuffdiff will assign it this \n\t  many times (probabilistically), thus estimating the assignment uncertainty \n\t  for each transcript. Used to estimate\n\t  the variance-covariance matrix on assigned fragment counts.  Default: 50. \n\t  </td></tr>\n\t\n   \t  <tr><td VALIGN=top nowrap>\n\t  <tt>-F/--min-outlier-p &lt;0.0-1.0&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  DEPRECATED\n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--min-reps-for-js-test &lt;int&gt;</tt>\n\t  </td><td VALIGN=top>\n\t  Cuffdiff won't test genes for differential regulation unless the conditions in question have at least this many replicates.  Default: 3. \n\t  </td></tr>\n\t\n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--no-effective-length-correction</tt>\n\t  </td><td VALIGN=top>\n\t  Cuffdiff will not employ its \"effective\" length normalization to transcript FPKM. \n\t  </td></tr>\n\t  \n\t  <tr><td VALIGN=top nowrap>\n\t  <tt>--no-length-correction</tt>\n\t  </td><td VALIGN=top>\n\t  Cuffdiff will not normalize fragment counts by transcript length at all.  Use this option when fragment count is independent of the size of the features being quantified (e.g. for small RNA libraries, where no fragmentation takes place, or 3 prime end sequencing, where sampled RNA fragments are all essentially the same length).  Experimental option, use with caution. \n\t  </td></tr>\n\t  \n\t  </table><br/>\n\t  <h2 id=\"cuffdiff_output\">Cuffdiff Output</h2><br/>\n\t\t<br/>\n\t\t<ol>\n\t\t<h2 id=\"fpkm_track\">1) FPKM tracking files</h2>\n\t\t<p>\n\t\tCuffdiff calculates the FPKM of each transcript, primary transcript, \n\t\tand gene in each sample.  Primary transcript and gene FPKMs are computed\n\t\tby summing the FPKMs of transcripts in each primary transcript group \n\t\tor gene group.  The results are output in FPKM tracking files in the format\n\t\tdescribed <a href=\"#fpkm_tracking_format\">here</a>.\n\t\t\n\t\tThere are <strong>four</strong> FPKM tracking files:\n\t\t\n\t\t<table CELLSPACING=15>\n\t\t  \n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>isoforms.fpkm_tracking</tt></td><td VALIGN=top>Transcript FPKMs</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>genes.fpkm_tracking</tt></td><td VALIGN=top>Gene FPKMs.  Tracks the summed FPKM of transcripts sharing each <tt>gene_id</tt></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>cds.fpkm_tracking</tt></td><td VALIGN=top>Coding sequence FPKMs. Tracks the summed FPKM of transcripts sharing each <tt>p_id</tt>, independent of <tt>tss_id</tt></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>tss_groups.fpkm_tracking</tt></td><td VALIGN=top>Primary transcript FPKMs. Tracks the summed FPKM of transcripts sharing each <tt>tss_id</tt></td>\n\t\t  </tr>\n\t\t  </table>\n\t\t\n\t\t<h2 id=\"fpkm_track\">2) Count tracking files</h2>\n\t\t<p>\n\t\tCuffdiff estimates the number of fragments that originated from each transcript, primary transcript, \n\t\tand gene in each sample.  Primary transcript and gene counts are computed\n\t\tby summing the counts of transcripts in each primary transcript group \n\t\tor gene group.  The results are output in count tracking files in the format\n\t\tdescribed <a href=\"#count_tracking_format\">here</a>.\n\n\t\tThere are <strong>four</strong> Count tracking files:\n\n\t\t<table CELLSPACING=15>\n\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>isoforms.count_tracking</tt></td><td VALIGN=top>Transcript counts</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>genes.count_tracking</tt></td><td VALIGN=top>Gene counts.  Tracks the summed counts of transcripts sharing each <tt>gene_id</tt></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>cds.count_tracking</tt></td><td VALIGN=top>Coding sequence counts. Tracks the summed counts of transcripts sharing each <tt>p_id</tt>, independent of <tt>tss_id</tt></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>tss_groups.count_tracking</tt></td><td VALIGN=top>Primary transcript counts. Tracks the summed counts of transcripts sharing each <tt>tss_id</tt></td>\n\t\t  </tr>\n\t\t  </table>\n\t\t\n\t\t<br/>\n\t\t\n\t\t<h2 id=\"read_group_track\">3) Read group tracking files</h2>\n\t\t<p>\n\t\tCuffdiff calculates the expression and fragment count for each transcript, primary transcript, \n\t\tand gene in each replicate. The results are output in per-replicate tracking files in the format\n\t\tdescribed <a href=\"#read_group_tracking_format\">here</a>.\n\t\t\n\t\tThere are <strong>four</strong> read group tracking files:\n\t\t\n\t\t<table CELLSPACING=15>\n\t\t  \n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>isoforms.read_group_tracking</tt></td><td VALIGN=top>Transcript read group tracking</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>genes.read_group_tracking</tt></td><td VALIGN=top>Gene read group tracking.  Tracks the summed expression and counts of transcripts sharing each <tt>gene_id</tt> in each replicate</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>cds.read_group_tracking</tt></td><td VALIGN=top>Coding sequence FPKMs. Tracks the summed expression and counts of transcripts sharing each <tt>p_id</tt>, independent of <tt>tss_id</tt> in each replicate</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>tss_groups.read_group_tracking</tt></td><td VALIGN=top>Primary transcript FPKMs. Tracks the summed expression and counts of transcripts sharing each <tt>tss_id</tt> in each replicate</td>\n\t\t  </tr>\n\t\t  </table>\n\t\t\n\t\t<br/>\n\t\t<h2 id=\"gene_exp_diff\">4) Differential expression tests</h2>\n\t\t<p>\n\t\tThis tab delimited file lists the results of differential\n\t\texpression testing between samples for spliced transcripts, \n\t\tprimary transcripts, genes, and coding sequences.\n\t\t\n\t\tFor each pair of samples <em>x</em> and <em>y</em>, four files are created\n\t\t<table>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>isoform_exp.diff</tt></td><td VALIGN=top>Transcript differential FPKM. </td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>gene_exp.diff</tt></td><td VALIGN=top>Gene differential FPKM.  Tests difference sin the summed FPKM of transcripts sharing each <tt>gene_id</tt></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>tss_group_exp.diff</tt></td><td VALIGN=top>Primary transcript differential FPKM.  Tests differences in the summed FPKM of transcripts sharing each <tt>tss_id</tt></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><tt>cds_exp.diff</tt></td><td VALIGN=top>Coding sequence differential FPKM. Tests differences in the summed FPKM of transcripts sharing each <tt>p_id</tt> independent of <tt>tss_id</tt></td>\n\t\t  </tr>\n\t\t</table>\n\t\t\n\t\tEach of the above files has the following format:\n\t\t<!-- test_id\tgene\tlocus\tsample_1\tsample_2 status\tvalue_1\ttvalue_2\tlog(fold_change)\ttest_stat\tp_value\tsignificant\ttested\tprotein_ids -->\n\t\t<table CELLSPACING=15>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>1</td><td VALIGN=top>Tested id</td><td VALIGN=top><tt>XLOC_000001</tt></td><td VALIGN=top>A unique identifier describing the transcipt, gene, primary transcript, or CDS being tested</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>2</td><td VALIGN=top>gene</td><td VALIGN=top><tt>Lypla1</tt></td><td VALIGN=top>The <tt>gene_name</tt>(s) or <tt>gene_id</tt>(s) being tested</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3</td><td VALIGN=top>locus</td><td VALIGN=top><tt>chr1:4797771-4835363</tt></td><td VALIGN=top>Genomic coordinates for easy browsing to the genes or transcripts being tested.</td>\n\t\t  </tr>\n\t      <tr>\n\t\t\t<td VALIGN=top>4</td><td VALIGN=top>sample 1</td><td VALIGN=top><tt>Liver</tt></td><td VALIGN=top>Label (or number if no labels provided) of the first sample being tested</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>5</td><td VALIGN=top>sample 2</td><td VALIGN=top><tt>Brain</tt></td><td VALIGN=top>Label (or number if no labels provided) of the second sample being tested</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>6</td><td VALIGN=top>Test status</td><td VALIGN=top><tt>NOTEST</tt></td><td VALIGN=top>Can be one of OK (test successful), NOTEST (not enough alignments for testing), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents testing.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>7</td><td VALIGN=top>FPKM<sub><em>x</em></sub></td><td VALIGN=top><tt>8.01089</tt></td><td VALIGN=top>FPKM of the gene in sample <em>x</em></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>8</td><td VALIGN=top>FPKM<sub><em>y</em></sub></td><td VALIGN=top><tt>8.551545</tt></td><td VALIGN=top>FPKM of the gene in sample <em>y</em></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>9</td><td VALIGN=top>log2(FPKM<sub><em>y</em></sub>/FPKM<sub><em>x</em></sub>)</td><td VALIGN=top><tt>0.06531</tt></td><td VALIGN=top>The (base 2) log of the fold change <em>y</em>/<em>x</em><td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>10</td><td VALIGN=top>test stat</td><td VALIGN=top><tt>0.860902</tt></td><td VALIGN=top>The value of the test statistic used to compute significance of the observed change in FPKM</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>11</td><td VALIGN=top>p value</td><td VALIGN=top><tt>0.389292</tt></td><td VALIGN=top>The <b>uncorrected</b> <em>p</em>-value of the test statistic</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>12</td><td VALIGN=top>q value</td><td VALIGN=top><tt>0.985216</tt></td><td VALIGN=top>The <b>FDR-adjusted</b> <em>p</em>-value of the test statistic</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>13</td><td VALIGN=top>significant</td><td VALIGN=top><tt>no</tt></td><td VALIGN=top>Can be either \"yes\" or \"no\", depending on whether <em>p</em> is greater then the FDR <b>after</b> Benjamini-Hochberg correction for multiple-testing</td>\n\t\t  </tr>\n\t\t  </table>\n\t\t\n\t\t<h2 id=\"splicing_diff\">5) Differential splicing tests - splicing.diff</h2>\n\t\t<p>\n\t\tThis tab delimited file lists, for each primary transcript, the amount of overloading\n\t\tdetected among its isoforms, i.e. how much differential splicing exists between\n\t\tisoforms processed from a single primary transcript.  Only primary \n\t\ttranscripts from which two or more isoforms are spliced are listed in this file.\n\t\t<!-- test_id\tgene\tlocus\tsample_1 sample_2 status\tvalue_1\ttvalue_2\tlog(fold_change)\ttest_stat\tp_value\tsignificant\ttested\tprotein_ids -->\n\t\t<table CELLSPACING=15>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>1</td><td VALIGN=top>Tested id</td><td VALIGN=top><tt>TSS10015</tt></td><td VALIGN=top>A unique identifier describing the primary transcript being tested.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>2</td><td VALIGN=top>gene name</td><td VALIGN=top><tt>Rtkn</tt></td><td VALIGN=top>The <tt>gene_name</tt> or <tt>gene_id</tt> that the primary transcript being tested belongs to</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3</td><td VALIGN=top>locus</td><td VALIGN=top><tt>chr6:83087311-83102572</tt></td><td VALIGN=top>Genomic coordinates for easy browsing to the genes or transcripts being tested.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>4</td><td VALIGN=top>sample 1</td><td VALIGN=top><tt>Liver</tt></td><td VALIGN=top>Label (or number if no labels provided) of the first sample being tested</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>5</td><td VALIGN=top>sample 2</td><td VALIGN=top><tt>Brain</tt></td><td VALIGN=top>Label (or number if no labels provided) of the second sample being tested</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>6</td><td VALIGN=top>Test status</td><td VALIGN=top><tt>OK</tt></td><td VALIGN=top>Can be one of OK (test successful), NOTEST (not enough alignments for testing), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents testing.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>7</td><td VALIGN=top>Reserved</td><td VALIGN=top><tt>0</tt></td><td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>8</td><td VALIGN=top>Reserved</td><td VALIGN=top><tt>0</tt></td><td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>9</td><td VALIGN=top>&radic;JS(x,y)</td><td VALIGN=top><tt>0.22115</tt></td><td VALIGN=top>The splice overloading of the primary transcript, as measured by the square root of the Jensen-Shannon divergence computed on the relative abundances of the splice variants<td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>10</td><td VALIGN=top>test stat</td><td VALIGN=top><tt>0.22115</tt></td><td VALIGN=top>The value of the test statistic used to compute significance of the observed overloading, equal to &radic;JS(x,y)</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>11</td><td VALIGN=top>p value</td><td VALIGN=top><tt>0.000174982</tt></td><td VALIGN=top>The <b>uncorrected</b> <em>p</em>-value of the test statistic.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>12</td><td VALIGN=top>q value</td><td VALIGN=top><tt>0.985216</tt></td><td VALIGN=top>The <b>FDR-adjusted</b> <em>p</em>-value of the test statistic</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>13</td><td VALIGN=top>significant</td><td VALIGN=top><tt>yes</tt></td><td VALIGN=top>Can be either \"yes\" or \"no\", depending on whether <em>p</em> is greater then the FDR <b>after</b> Benjamini-Hochberg correction for multiple-testing</td>\n\t\t  </tr>\n\t\t  </table>\n\t\t\n\t\t<h2 id=\"cds_diff\">6) Differential coding output - cds.diff</h2>\n\t\t<p>\n\t\tThis tab delimited file lists, for each gene, the amount of overloading\n\t\tdetected among its coding sequences, i.e. how much differential \n\t\tCDS output exists between samples.  Only genes producing two or more\n\t\tdistinct CDS (i.e. multi-protein genes) are listed here.</p>\n\t\t\n\t\t<!-- test_id\tgene\tlocus\tsample_1 sample_2 status\tvalue_1\ttvalue_2\tlog(fold_change)\ttest_stat\tp_value\tsignificant\ttested\tprotein_ids -->\n\t\t<table CELLSPACING=15>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>1</td><td VALIGN=top>Tested id</td><td VALIGN=top><tt>XLOC_000002-[chr1:5073200-5152501]</tt></td><td VALIGN=top>A unique identifier describing the gene being tested.  </td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>2</td><td VALIGN=top>gene name</td><td VALIGN=top><tt>Atp6v1h</tt></td><td VALIGN=top>The <tt>gene_name</tt> or <tt>gene_id</tt></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3</td><td VALIGN=top>locus</td><td VALIGN=top><tt>chr1:5073200-5152501</tt></td><td VALIGN=top>Genomic coordinates for easy browsing to the genes or transcripts being tested.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>4</td><td VALIGN=top>sample 1</td><td VALIGN=top><tt>Liver</tt></td><td VALIGN=top>Label (or number if no labels provided) of the first sample being tested</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>5</td><td VALIGN=top>sample 2</td><td VALIGN=top><tt>Brain</tt></td><td VALIGN=top>Label (or number if no labels provided) of the second sample being tested</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>6</td><td VALIGN=top>Test status</td><td VALIGN=top><tt>OK</tt></td><td VALIGN=top>Can be one of OK (test successful), NOTEST (not enough alignments for testing), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents testing.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>7</td><td VALIGN=top>Reserved</td><td VALIGN=top><tt>0</tt></td><td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>8</td><td VALIGN=top>Reserved</td><td VALIGN=top><tt>0</tt></td><td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>9</td><td VALIGN=top>&radic;JS(x,y)</td><td VALIGN=top><tt>0.0686517</tt></td><td VALIGN=top>The CDS overloading of the gene, as measured by the square root of the Jensen-Shannon divergence computed on the relative abundances of the coding sequences<td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>10</td><td VALIGN=top>test stat</td><td VALIGN=top><tt>0.0686517</tt></td><td VALIGN=top>The value of the test statistic used to compute significance of the observed overloading, equal to &radic;JS(x,y)</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>11</td><td VALIGN=top>p value</td><td VALIGN=top><tt>0.00546783</tt></td><td VALIGN=top>The <b>uncorrected</b> <em>p</em>-value of the test statistic</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>12</td><td VALIGN=top>q value</td><td VALIGN=top><tt>0.985216</tt></td><td VALIGN=top>The <b>FDR-adjusted</b> <em>p</em>-value of the test statistic</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>13</td><td VALIGN=top>significant</td><td VALIGN=top><tt>yes</tt></td><td VALIGN=top>Can be either \"yes\" or \"no\", depending on whether <em>p</em> is greater then the FDR <b>after</b> Benjamini-Hochberg correction for multiple-testing</td>\n\t\t  </tr>\n\t\t  </table>\n\t\t\n\t\t<h2 id=\"promoter_diff\">7) Differential promoter use - promoters.diff</h2>\n\t\t<p>\n\t\tThis tab delimited file lists, for each gene, the amount of overloading\n\t\tdetected among its primary transcripts, i.e. how much differential \n\t\tpromoter use exists between samples.  Only genes producing two or more\n\t\tdistinct primary transcripts (i.e. multi-promoter genes) are listed here.</p>\n\t\t\n\n\t\t<!-- test_id\tgene\tlocus\tstatus\tvalue_1\ttvalue_2\tlog(fold_change)\ttest_stat\tp_value\tsignificant\ttested\tprotein_ids -->\n\t\t<table CELLSPACING=15>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>1</td><td VALIGN=top>Tested id</td><td VALIGN=top><tt>XLOC_000019</tt></td><td VALIGN=top>A unique identifier describing the gene being tested.  </td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>2</td><td VALIGN=top>gene name</td><td VALIGN=top><tt>Tmem70</tt></td><td VALIGN=top>The <tt>gene_name</tt> or <tt>gene_id</tt></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3</td><td VALIGN=top>locus</td><td VALIGN=top><tt>chr1:16651657-16668357</tt></td><td VALIGN=top>Genomic coordinates for easy browsing to the genes or transcripts being tested.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>4</td><td VALIGN=top>sample 1</td><td VALIGN=top><tt>Liver</tt></td><td VALIGN=top>Label (or number if no labels provided) of the first sample being tested</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>5</td><td VALIGN=top>sample 2</td><td VALIGN=top><tt>Brain</tt></td><td VALIGN=top>Label (or number if no labels provided) of the second sample being tested</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>6</td><td VALIGN=top>Test status</td><td VALIGN=top><tt>OK</tt></td><td VALIGN=top>Can be one of OK (test successful), NOTEST (not enough alignments for testing), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents testing.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>7</td><td VALIGN=top>Reserved</td><td VALIGN=top><tt>0</tt></td><td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>8</td><td VALIGN=top>Reserved</td><td VALIGN=top><tt>0</tt></td><td VALIGN=top></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>9</td><td VALIGN=top>&radic;JS(x,y)</td><td VALIGN=top><tt>0.0124768</tt></td><td VALIGN=top>The promoter overloading of the gene, as measured by the square root of the Jensen-Shannon divergence computed on the relative abundances of the primary transcripts<td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>10</td><td VALIGN=top>test stat</td><td VALIGN=top><tt>0.0124768</tt></td><td VALIGN=top>The value of the test statistic used to compute significance of the observed overloading, equal to &radic;JS(x,y)</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>11</td><td VALIGN=top>p value</td><td VALIGN=top><tt>0.394327</tt></td><td VALIGN=top>The <b>uncorrected</b> <em>p</em>-value of the test statistic</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>12</td><td VALIGN=top>q value</td><td VALIGN=top><tt>0.985216</tt></td><td VALIGN=top>The <b>FDR-adjusted</b> <em>p</em>-value of the test statistic</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>13</td><td VALIGN=top>significant</td><td VALIGN=top><tt>no</tt></td><td VALIGN=top>Can be either \"yes\" or \"no\", depending on whether <em>p</em> is greater then the FDR <b>after</b> Benjamini-Hochberg correction for multiple-testing</td>\n\t\t  </tr>\n\t\t  </table>\n\t\t\n\t\t<br/>\n\t\t<h2 id=\"read_group_info\">8) Read group info - read_groups.info</h2>\n\t\t<p>\n\t\tThis tab delimited file lists, for each replicate, key properties used by Cuffdiff during quantification, such as library normalization factors.\n\t\tThe read_groups.info file has the following format:\n\t\t<!-- test_id\tgene\tlocus\tstatus\tvalue_1\ttvalue_2\tlog(fold_change)\ttest_stat\tp_value\tsignificant\ttested\tprotein_ids -->\n\t\t<table CELLSPACING=15>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>1</td><td VALIGN=top>file</td><td VALIGN=top><tt>mCherry_rep_A/accepted_hits.bam</tt></td><td VALIGN=top>BAM or SAM file containing the data for the read group</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>2</td><td VALIGN=top>condition</td><td VALIGN=top><tt>mCherry</tt></td><td VALIGN=top>Condition to which the read group belongs</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3</td><td VALIGN=top>replicate_num</td><td VALIGN=top><tt>0</tt></td><td VALIGN=top>Replicate number of the read group</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>4</td><td VALIGN=top>total_mass</td><td VALIGN=top><tt>4.72517e+06</tt></td><td VALIGN=top>Total number of fragments for the read group</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>5</td><td VALIGN=top>norm_mass</td><td VALIGN=top><tt>4.72517e+06</tt></td><td VALIGN=top>Fragment normalization constant used during calculation of FPKMs.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>6</td><td VALIGN=top>internal_scale</td><td VALIGN=top><tt>1.23916</tt></td><td VALIGN=top>Internal scaling factor, used to transform replicates of a single condition onto the \"internal\" common count scale.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>7</td><td VALIGN=top>external_scale</td><td VALIGN=top><tt>0.96</tt></td><td VALIGN=top>External scaling factor, used to transform counts from different conditions onto an internal common count scale.</td>\n\t\t  </tr>\n\t\t  </table>\n\t\t</p>\n\t\t\n\t\t<br/>\n\t\t<h2 id=\"run_info\">8) Run info - run.info</h2>\n\t\t<p>\n\t\tThis tab delimited file lists various bits of information about a Cuffdiff run to help track what options were provided. For example:\n\t\t</p>\n\t\t<pre>\nparam   value\ncmd_line        cuffdiff  base_ref.gtf mCherry/accepted_hits.bam R49/accepted_hits.bam \nversion 2.0.0\nSVN_revision    3258\nboost_version   104700\n\t\t</pre>\n\t</div>\n  </div>\n  </ol>\n    <h2 id=\"cuffnorm\">Running Cuffnorm</h2><br/>\n\t\t\tCufflinks includes a program, \"Cuffnorm\", that you can use to generate tables of expression values that are properly normalized for library size.  From the command line, run <tt>cuffnorm</tt> as follows:\n\t\t\t<p>\n\t\t\t<blockquote>\n\t\t\tcuffnorm [options]* &lt;transcripts.gtf&gt; &lt;sample1_replicate1.sam[,...,sample1_replicateM.sam]&gt; &lt;sample2_replicate1.sam[,...,sample2_replicateM.sam]&gt;... [sampleN.sam_replicate1.sam[,...,sample2_replicateM.sam]]\n\t\t\t</blockquote>\n\t\t\n\t\t\t<br/>\n\t\t\t<h2 id=\"cuffnorm_input\">Cuffnorm Input</h2><br/>\n\t\t\tRunning Cuffnorm is very similar to <a href=\"#cuffdiff_input\">running Cuffdiff</a>. Cuffnorm takes a GTF2/GFF3 file of transcripts as input, along with two or more \n\t\t\tSAM, BAM, or CXB files for two or more samples. \n\t\t\tIt produces a number of output files that contain expression levels and normalized fragment counts at the level of transcripts, primary transcripts, \n\t\t\tand genes. It also tracks changes in the relative abundance of transcripts sharing a common\n\t\t\ttranscription start site, and in the relative abundances of the primary \n\t\t\ttranscripts of each gene.  Tracking the former allows one to see changes in \n\t\t\tsplicing, and the latter lets one see changes in relative promoter use \n\t\t\twithin a gene.\n\t\t\t<p>\n\t\t\tIf you have more than one <b>replicate</b> for a sample, supply the SAM files for \n\t\t\tthe sample as a single <b>comma-separated</b> list.  It is not necessary to \n\t\t\thave the same number of replicates for each sample.\n\t\t\t<p>\n\t\t\tNote that Cuffnorm can also accepted BAM files (which are binary, compressed SAM files).  It can also accept CXB files produced by Cuffquant.  Note that mixing SAM and BAM files is supported, but you cannot currently mix CXB and SAM/BAM.  If one of the samples is supplied as a CXB file, all of the samples must be supplied as CXB files.\n\t\t\t<p>\n\t\t\tCuffnorm also requires a GFF/GTF file, conforming to the same specifications as needed for Cuffdiff.\n\t\t\n\t        <p>\n\t\t\t\n\t\t\t  <table CELLSPACING=15>\n\t\t\t  <tr><td VALIGN=top>\n\t\t\t  <b>Arguments:</b>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  </td></tr>\n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>&lt;transcripts.(gtf/gff)&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  A transcript annotation file produced by cufflinks, cuffcompare, or other source.\n\t\t\t  </td></tr>\n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>&lt;sample1.(sam/bam/cxb)&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  A SAM file of aligned RNA-Seq reads. If more than two are provided,\n\t\t\t  Cuffdiff tests for differential expression and regulation between all pairs of \n\t\t\t  samples. \n\t\t\t  </td></tr>\n\t\t\t  \n\t\t\t  <tr><td VALIGN=top>\n\t\t\t  <b>Options:</b>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  </td></tr>\n\t\t\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-h/--help</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Prints the help message and exits   \n\t\t\t  </td></tr> \n\n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-o/--output-dir &lt;string&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Sets the name of the directory in which Cuffdiff will write all of its \n\t\t\t  output.  The default is \"./\".\n\t\t\t  </td></tr>\n\t\t\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-L/--labels &lt;label1,label2,...,labelN&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Specify a label for each sample, which will be included in various output files \n\t\t\t  produced by Cuffdiff.\n\t\t\t  </td></tr>\n\t\t\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>-p/--num-threads &lt;int&gt;</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  Use this many threads to align reads. The default is 1.\n\t\t\t  </td></tr>\n\t\t\t\n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>--total-hits-norm</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  With this option, Cuffquant counts all fragments, including those not compatible with any reference transcript, towards the number of mapped fragments used in the FPKM denominator.  It is inactive by default.\n\t\t\t  </td></tr>\n\n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>--compatible-hits-norm</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  With this option, Cuffnorm counts only those fragments compatible with some reference transcript towards the number of mapped fragments used in the FPKM denominator.  It is active by default.  \n\t\t\t  </td></tr>\n\t\t    \n\t\t\t  <tr><td VALIGN=top nowrap>\t\n\t\t\t  <tt>--library-type</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  See <a href=\"#library\">Library Types</a>\n\t\t\t  </td></tr>\n\t\t\t  <tr><td VALIGN=top nowrap>\t\n\t\t\t  <tt>--library-norm-method</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  See <a href=\"#library_norm_meth\">Library Normalization Methods</a>\n\t\t\t  </td></tr>\n\t\t\t  \n\t\t\t  <tr><td VALIGN=top nowrap>\n\t\t\t  <tt>--output-format</tt>\n\t\t\t  </td><td VALIGN=top>\n\t\t\t  See <a href=\"#output_options\">Output format options</a>\n\t\t\t  </td></tr>\n\t\t  \n\t\t  <tr><td VALIGN=top>\n\t\t  <b>Advanced Options:</b>\n\t\t  </td><td VALIGN=top>\n\t\t  </td></tr>\n\t\t  \n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-v/--verbose</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Print lots of status updates and other diagnostic information.\n\t\t  </td></tr>\n\t  \n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>-q/--quiet</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Suppress messages other than serious warnings and errors.\n\t\t  </td></tr>\n\n\t\t  <tr><td VALIGN=top nowrap>\n\t\t  <tt>--no-update-check</tt>\n\t\t  </td><td VALIGN=top>\n\t\t  Turns off the automatic routine that contacts the Cufflinks server to check for a more \n\t\t  recent version.\n\t\t  </td></tr>\n\t\n\t\t  </table><br/>\n\t\t  <h2 id=\"cuffnorm_output\">Cuffnorm Output</h2><br/>\n\t\t  <p>Cuffnorm outputs a set of files containing normalized expression levels for each gene, transcript, TSS group, and CDS group in the experiment.  It does not perform differential expression analysis.  To assess the significance of changes in expression for genes and transcripts between conditions, use Cuffdiff. Cuffnorm's output files are useful when you have many samples and you simply want to cluster them or plot expression levels of genes important in your study.\n\t\t  <p>By default, Cuffnorm reports expression levels in the \"simple-table\" tab-delimted text files.  The program also reports information about your samples and about the genes, transcripts, TSS groups, and CDS groups as tab delimited text files. Note that these files have a different format than the files used by Cuffdiff.  However, you can direct Cuffnorm to report its output in the same format as used by Cuffdiff if you wish.  Simply supply the option <tt>--output-format cuffdiff</tt> at the command line.\n\t\t  <p>Cuffnorm will report both FPKM values and <strong>normalized</strong>, estimates for the number of fragments that originate from each gene, transcript, TSS group, and CDS group.  Note that because these counts are already normalized to account for differences in library size, they should not be used with downstream differential expression tools that require <strong>raw</strong> counts as input.  \n\t\t  <p>To see the details of the simple table format used by Cuffnorm, refer to the simple table expression format, simple table sample attribute format, and simple table feature (e.g. gene) attribute format sections below.\n\t\t</div>\n\t  </div>\n\t  </ol>\n\t  <br/>\n\t  <br/>\n    <h2 id=\"sample_sheets\">Sample sheets for Cuffdiff and Cuffnorm</h2><br/>\n\t<p>Both Cuffdiff and Cuffnorm can be run by specifying a list of SAM, BAM, or CXB files at the command line.  For analysis with many such files, specifying them in this way can be cumbersome and error-prone.  Both programs also allow you to specify these inputs in a simple, tab-delimited table.  Create a file called <tt>sample_sheet.txt</tt> or another name of your choice, and specify samples as follows, one per line:\n\t\t \n \t\t<table CELLSPACING=15>\n \t\t  <tr>\n \t\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n \t\t  </tr>\n \t\t  <tr>\n \t\t\t<td VALIGN=top>1</td><td VALIGN=top>sample_id</td><td VALIGN=top><tt>C1_R1.sam</tt></td><td VALIGN=top>the path to the SAM/BAM/CXB file for this sample</td>\n \t\t  </tr>\n \t\t  <tr>\n \t\t\t<td VALIGN=top>2</td><td VALIGN=top>group_label</td><td VALIGN=top><tt>C1</tt></td><td VALIGN=top>The condition label for this sample.  Replicates of a condition should share the same label</td>\n \t\t  </tr>\n \t\t  </table>\n \t\t <br/> \n\t\t \n\t\t <p>To run Cuffdiff or Cuffnorm with a sample sheet, create one and then at the command line, provide the <tt>--use-sample-sheet</tt> option and replace the list of SAM/BAM/CXB files with the name of your sample sheet file, as follows:\n\t\t\t </p>\n\t\t\t <br/>\n\t \t\t<blockquote>\n\t \t\tcuffdiff --use-sample-sheet &lt;transcripts.gtf&gt; &lt;sample_sheet.txt&gt;\n\t \t\t</blockquote>\n\t\t\t <br/>\n\t\t\t  \n\t\t \n\t\t An example sample sheet might look like this:\n\t\t \n\t\t <pre>\nsample_id\tgroup_label\nC1_R1.sam\tC1\nC1_R2.sam\tC1\nC2_R1.sam\tC2\nC2_R2.sam\tC2\t\n\t\t </pre>\n\t\t<br/> \n\t\t \n\t<h2 id=\"contrast_files\">Contrast files for Cuffdiff</h2><br/>\n\t<p>Cuffdiff, by default, compares each pair of conditions in your experiment.  If you have many conditions, this can create a lot of additional work for the program.  These extra conditions can cause Cuffdiff's output files to be very large, which can slow down <a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a> and other downstream analysis software. Often, you are not interested in all pairwise contrasts. Rather, you'd like to compare all conditions to a common control, or only look at matched pairs of samples.  You can specify the contrasts Cuffdiff should perform using a contrast file.  \n\t\n\t<p>Contrast files are simple, tab delimited text files.  They should have a single header line as the first line in the file, followed by one line for each contrast you'd like to perform.  The files should have two columns, as specified below:\n\t \t\t<table CELLSPACING=15>\n\t \t\t  <tr>\n\t \t\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t \t\t  </tr>\n\t \t\t  <tr>\n\t \t\t\t<td VALIGN=top>1</td><td VALIGN=top>condition_A</td><td VALIGN=top><tt>Ctrl</tt></td><td VALIGN=top>A condition label.  Must match one of the labels specified through -L or in the sample sheet.</td>\n\t \t\t  </tr>\n\t \t\t  <tr>\n\t \t\t\t<td VALIGN=top>1</td><td VALIGN=top>condition_B</td><td VALIGN=top><tt>Ctrl</tt></td><td VALIGN=top>A condition label.  Must match one of the labels specified through -L or in the sample sheet.</td>\n\t \t\t  </tr>\n\t \t\t  </table>\n\t \t\t <br/> \n\t\t\t <p>\n\t\t \t To run Cuffdiff with a contrast file, simply provide the <tt>-C  &lt;contrasts.txt&gt;</tt> option at the command line.\n\t\t\t<br/>\n\t\t\t An example table might look like this:\n\t\t \n\t\t <pre>\ncondition_A\tcondition_B\nCtrl\tMutant_X\nCtrl\tMutant_Y\nCtrl\tMutant_Z\t\t\n\t\t </pre>\n\t\t<br/> \n\t\n\t\n\t<h2 id=\"output_formats\">Output formats</h2><br/>\n\t<p>Cufflinks, Cuffdiff, and Cuffnorm all output numerous types of files.  They fall into one of the formats described below:\n\t\t</p>\n\t\t<br/>\n\t\t<br/>\n    <h2 id=\"fpkm_tracking_format\">FPKM Tracking Files</h2><br/>\n\n  FPKM tracking files use a generic format to output estimated expression values.  Each FPKM tracking file has the following format:\n\t\t\n\t\t<!-- ref_trans_id\tclass_code\tgene_short_name\ttss_id\tlocus\tq0_FPKM\tq0_conf_lo\tq0_conf_hi\tq1_FPKM\tq1_conf_lo\tq1_conf_hi\tq2_FPKM\tq2_conf_loq2_conf_hi\tq3_FPKM\tq3_conf_lo\tq3_conf_hi -->\n\t\t\n\t\t<table CELLSPACING=15>\n\t\t  <tr>\n\t\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>1</td><td VALIGN=top>tracking_id</td><td VALIGN=top><tt>TCONS_00000001</tt></td><td VALIGN=top>A unique identifier describing the object (gene, transcript, CDS, primary transcript)</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>2</td><td VALIGN=top>class_code</td><td VALIGN=top><tt>=</tt></td><td VALIGN=top>The <tt>class_code</tt> attribute for the object, or \"-\" if not a transcript, or if <tt>class_code</tt> isn't present</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3</td><td VALIGN=top>nearest_ref_id</td><td VALIGN=top><tt>NM_008866.1</tt></td><td VALIGN=top>The reference transcript to which the class code refers, if any</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>4</td><td VALIGN=top>gene_id</td><td VALIGN=top><tt>NM_008866</tt></td><td VALIGN=top>The <tt>gene_id</tt>(s) associated with the object</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>5</td><td VALIGN=top>gene_short_name</td><td VALIGN=top><tt>Lypla1</tt></td><td VALIGN=top>The <tt>gene_short_name</tt>(s) associated with the object</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>6</td><td VALIGN=top>tss_id</td><td VALIGN=top><tt>TSS1</tt></td><td VALIGN=top>The <tt>tss_id</tt> associated with the object, or \"-\" if not a transcript/primary transcript, or if <tt>tss_id</tt> isn't present</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>7</td><td VALIGN=top>locus</td><td VALIGN=top><tt>chr1:4797771-4835363</tt></td><td VALIGN=top>Genomic coordinates for easy browsing to the object</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>8</td><td VALIGN=top>length</td><td VALIGN=top><tt>2447</tt></td><td VALIGN=top>The number of base pairs in the transcript, or '-' if not a transcript/primary transcript</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>9</td><td VALIGN=top>coverage</td><td VALIGN=top><tt>43.4279</tt></td><td VALIGN=top>Estimate for the absolute depth of read coverage across the object</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>10</td><td VALIGN=top>q0_FPKM</td><td VALIGN=top><tt>8.01089</tt></td><td VALIGN=top>FPKM of the object in sample 0</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>11</td><td VALIGN=top>q0_FPKM_lo</td><td VALIGN=top><tt>7.03583</tt></td><td VALIGN=top>the lower bound of the 95% confidence interval on the FPKM of the object in sample 0</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>12</td><td VALIGN=top>q0_FPKM_hi</td><td VALIGN=top><tt>8.98595</tt></td><td VALIGN=top>the upper bound of the 95% confidence interval on the FPKM of the object in sample 0</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>13</td><td VALIGN=top>q0_status</td><td VALIGN=top><tt>OK</tt></td><td VALIGN=top>Quantification status for the object in sample 0. Can be one of OK (deconvolution successful), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents deconvolution.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>14</td><td VALIGN=top>q1_FPKM</td><td VALIGN=top><tt>8.55155</tt></td><td VALIGN=top>FPKM of the object in sample 1</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>15</td><td VALIGN=top>q1_FPKM_lo</td><td VALIGN=top><tt>7.77692</tt></td><td VALIGN=top>the lower bound of the 95% confidence interval on the FPKM of the object in sample 0</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>16<td VALIGN=top>q1_FPKM_hi</td><td VALIGN=top><tt>9.32617</tt></td><td VALIGN=top>the upper bound of the 95% confidence interval on the FPKM of the object in sample 1</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>17<td VALIGN=top>q1_status</td><td VALIGN=top><tt>9.32617</tt></td><td VALIGN=top>the upper bound of the 95% confidence interval on the FPKM of the object in sample 1. Can be one of OK (deconvolution successful), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents deconvolution.</td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3<em>N</em> + 12</td><td VALIGN=top>q<em>N</em>_FPKM</td><td VALIGN=top><tt>7.34115</tt></td><td VALIGN=top>FPKM of the object in sample <em>N</em></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3<em>N</em> + 13</td><td VALIGN=top>q<em>N</em>_FPKM_lo</td><td VALIGN=top><tt>6.33394</tt></td><td VALIGN=top>the lower bound of the 95% confidence interval on the FPKM of the object in sample <em>N</em></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3<em>N</em> + 14</td><td VALIGN=top>q<em>N</em>_FPKM_hi</td><td VALIGN=top><tt>8.34836</tt></td><td VALIGN=top>the upper bound of the 95% confidence interval on the FPKM of the object in sample <em>N</em></td>\n\t\t  </tr>\n\t\t  <tr>\n\t\t\t<td VALIGN=top>3<em>N</em> + 15</td><td VALIGN=top>q<em>N</em>_status</td><td VALIGN=top><tt>OK</tt></td><td VALIGN=top>Quantification status for the object in sample <em>N</em>. Can be one of OK (deconvolution successful), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents deconvolution.</td>\n\t\t  </tr>\n\t\t  </table>\n\t\t <br/> \n\t\t\n\t\t<h2 id=\"count_tracking_format\">Count Tracking Files</h2><br/>\n\n\t  Count tracking files use a generic format to output estimated fragment count values.  Each Count tracking file has the following format:\n\n\t\t\t<!-- ref_trans_id\tclass_code\tgene_short_name\ttss_id\tlocus\tq0_FPKM\tq0_conf_lo\tq0_conf_hi\tq1_FPKM\tq1_conf_lo\tq1_conf_hi\tq2_FPKM\tq2_conf_loq2_conf_hi\tq3_FPKM\tq3_conf_lo\tq3_conf_hi -->\n\n\t\t\t<table CELLSPACING=15>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>1</td><td VALIGN=top>tracking_id</td><td VALIGN=top><tt>TCONS_00000001</tt></td><td VALIGN=top>A unique identifier describing the object (gene, transcript, CDS, primary transcript)</td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>2</td><td VALIGN=top>q0_count</td><td VALIGN=top><tt>201.334</tt></td><td VALIGN=top>Estimated (externally scaled) number of fragments generated by the object in sample 0</td>\n\t\t\t  </tr>\n\t\t  \t <tr>\n\t\t\t\t<td VALIGN=top>3</td><td VALIGN=top>q0_count_variance</td><td VALIGN=top><tt>5988.24</tt></td><td VALIGN=top>Estimated variance in the number of fragments generated by the object in sample 0</td>\n\t\t\t  </tr>\n\t\t   \t  <tr>\n\t\t\t\t<td VALIGN=top>4</td><td VALIGN=top>q0_count_uncertainty_var</td><td VALIGN=top><tt>170.21</tt></td><td VALIGN=top>Estimated variance in the number of fragments generated by the object in sample 0 due to fragment assignment uncertainty.</td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>5</td><td VALIGN=top>q0_count_dispersion_var</td><td VALIGN=top><tt>4905.63</tt></td><td VALIGN=top>Estimated variance in the number of fragments generated by the object in sample 0 due to cross-replicate variability.</td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>6</td><td VALIGN=top>q0_status</td><td VALIGN=top><tt>OK</tt></td><td VALIGN=top>Quantification status for the object in sample 0. Can be one of OK (deconvolution successful), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents deconvolution.</td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>7</td><td VALIGN=top>q1_count</td><td VALIGN=top><tt>201.334</tt></td><td VALIGN=top>Estimated (externally scaled) number of fragments generated by the object in sample 1</td>\n\t\t\t  </tr>\n\t\t  \t <tr>\n\t\t\t\t<td VALIGN=top>8</td><td VALIGN=top>q1_count_variance</td><td VALIGN=top><tt>5988.24</tt></td><td VALIGN=top>Estimated variance in the number of fragments generated by the object in sample 1</td>\n\t\t\t  </tr>\n\t\t   \t  <tr>\n\t\t\t\t<td VALIGN=top>9</td><td VALIGN=top>q1_count_uncertainty_var</td><td VALIGN=top><tt>170.21</tt></td><td VALIGN=top>Estimated variance in the number of fragments generated by the object in sample 1 due to fragment assignment uncertainty.</td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>10</td><td VALIGN=top>q1_count_dispersion_var</td><td VALIGN=top><tt>4905.63</tt></td><td VALIGN=top>Estimated variance in the number of fragments generated by the object in sample 1 due to cross-replicate variability.</td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>11</td><td VALIGN=top>q1_status</td><td VALIGN=top><tt>OK</tt></td><td VALIGN=top>Quantification status for the object in sample 1. Can be one of OK (deconvolution successful), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents deconvolution.</td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>7</td><td VALIGN=top>q<em>N</em>_count</td><td VALIGN=top><tt>201.334</tt></td><td VALIGN=top>Estimated (externally scaled) number of fragments generated by the object in sample <em>N</em></td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>4<em>N</em> + 6</td><td VALIGN=top>q<em>N</em>_count_variance</td><td VALIGN=top><tt>7.34115</tt></td><td VALIGN=top>Estimated variance in the number of fragments generated by the object in sample <em>N</em></td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>4<em>N</em> + 7</td><td VALIGN=top>q<em>N</em>_count_uncertainty_var</td><td VALIGN=top><tt>6.33394</tt></td><td VALIGN=top>Estimated variance in the number of fragments generated by the object in sample <em>N</em> due to fragment assignment uncertainty.</td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>4<em>N</em> + 8</td><td VALIGN=top>q<em>N</em>_count_dispersion_var</td><td VALIGN=top><tt>8.34836</tt></td><td VALIGN=top>Estimated variance in the number of fragments generated by the object in sample <em>N</em> due to cross-replicate variability.</td>\n\t\t\t  </tr>\n\t\t\t  <tr>\n\t\t\t\t<td VALIGN=top>4<em>N</em> + 9</td><td VALIGN=top>q<em>N</em>_status</td><td VALIGN=top><tt>OK</tt></td><td VALIGN=top>Quantification status for the object in sample <em>N</em>. Can be one of OK (deconvolution successful), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents deconvolution.</td>\n\t\t\t  </tr>\n\t\t\t  </table>\n\t\t\t <br/>\n\t\t\t\n\t\t\t<h2 id=\"read_group_tracking_format\">Read Group Tracking Files</h2><br/>\n\n\t\t  \tRead group tracking files record per-replicate expression and count data.  Each Count tracking file has the following format:\n\n\t\t\t\t<!-- ref_trans_id\tclass_code\tgene_short_name\ttss_id\tlocus\tq0_FPKM\tq0_conf_lo\tq0_conf_hi\tq1_FPKM\tq1_conf_lo\tq1_conf_hi\tq2_FPKM\tq2_conf_loq2_conf_hi\tq3_FPKM\tq3_conf_lo\tq3_conf_hi -->\n\n\t\t\t\t<table CELLSPACING=15>\n\t\t\t\t  <tr>\n\t\t\t\t\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t\t\t\t  </tr>\n\t\t\t\t  <tr>\n\t\t\t\t\t<td VALIGN=top>1</td><td VALIGN=top>tracking_id</td><td VALIGN=top><tt>TCONS_00000001</tt></td><td VALIGN=top>A unique identifier describing the object (gene, transcript, CDS, primary transcript)</td>\n\t\t\t\t  </tr>\n\t\t\t\t  <tr>\n\t\t\t\t\t<td VALIGN=top>2</td><td VALIGN=top>condition</td><td VALIGN=top><tt>Fibroblasts</tt></td><td VALIGN=top>Name of the condition</td>\n\t\t\t\t  </tr>\n\t\t\t  \t <tr>\n\t\t\t\t\t<td VALIGN=top>3</td><td VALIGN=top>replicate</td><td VALIGN=top><tt>1</tt></td><td VALIGN=top>Name of the replicate of the condition</td>\n\t\t\t\t  </tr>\n\t\t\t   \t  <tr>\n\t\t\t\t\t<td VALIGN=top>4</td><td VALIGN=top>raw_frags</td><td VALIGN=top><tt>170.21</tt></td><td VALIGN=top>The estimate number of (unscaled) fragments originating from the object in this replicate</td>\n\t\t\t\t  </tr>\n\t\t\t\t  <tr>\n\t\t\t\t\t<td VALIGN=top>5</td><td VALIGN=top>internal_scaled_frags</td><td VALIGN=top><tt>4905.63</tt></td><td VALIGN=top>Estimated number of fragments originating from the object, after transforming to the internal common count scale (for comparison between replicates of this condition.)</td>\n\t\t\t\t  </tr>\n\t\t\t\t  <tr>\n\t\t\t\t\t<td VALIGN=top>6</td><td VALIGN=top>external_scaled_frags</td><td VALIGN=top><tt>99.21</tt></td><td VALIGN=top>Estimated number of fragments originating from the object, after transforming to the external common count scale (for comparison between conditions)</td>\n\t\t\t\t  </tr>\n\t\t\t\t  <tr>\n\t\t\t\t\t<td VALIGN=top>7</td><td VALIGN=top>FPKM</td><td VALIGN=top><tt>201.334</tt></td><td VALIGN=top>FPKM of this object in this replicate</td>\n\t\t\t\t  </tr>\n\t\t\t  \t <tr>\n\t\t\t\t\t<td VALIGN=top>8</td><td VALIGN=top>effective_length</td><td VALIGN=top><tt>5988.24</tt></td><td VALIGN=top>The effective length of the object in this replicate.  Currently a reserved, unreported field.</td>\n\t\t\t\t  </tr>\n\t\t\t   \t  <tr>\n\t\t\t\t\t<td VALIGN=top>9</td><td VALIGN=top>status</td><td VALIGN=top><tt>OK</tt></td><td VALIGN=top>Quantification status for the object. Can be one of OK (deconvolution successful), LOWDATA (too complex or shallowly sequenced), HIDATA (too many fragments in locus), or FAIL, when an ill-conditioned covariance matrix or other numerical exception prevents deconvolution.</td>\n\t\t\t\t  </tr>\n\t\t\t\t  </table>\n\t\t\t\t <br/>\n  <h2 id=\"simple_table_expression_format\">Simple-table expression format</h2><br/>\n  Cuffnorm reports two different types of files with this format: *.fpkm_table files and *.count_table files for each group of features: genes, transcripts, TSS groups, and CDS groups.  The files start with a column indicating the feature ID for each row. There is one subsequent column for each sample in the analysis:\n  <table CELLSPACING=15>\n  <tr>\n\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>1</td><td VALIGN=top>tracking_id</td><td VALIGN=top><tt>TCONS_00000001</tt></td><td VALIGN=top>A unique identifier describing the object (gene, transcript, CDS, primary transcript)</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>2</td><td VALIGN=top>conditionX_N</td><td VALIGN=top><tt>=</tt></td><td VALIGN=top>The FPKM value (for *.fpkm_table files) or normalized fragment count (for *.count_table files) for this feature in replicate N of conditionX</td>\n  </tr>\n   </table>\n  <br/>\n  \n  <h2 id=\"simple_table_gene_attr_format\">Simple-table gene attributes format</h2><br/>\n  Cuffdiff reports metadata for each gene, transcript, TSS group, and CDS group in the following tab delimited format:\n  <table CELLSPACING=15>\n  <tr>\n\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>1</td><td VALIGN=top>tracking_id</td><td VALIGN=top><tt>TCONS_00000001</tt></td><td VALIGN=top>A unique identifier describing the object (gene, transcript, CDS, primary transcript)</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>2</td><td VALIGN=top>class_code</td><td VALIGN=top><tt>=</tt></td><td VALIGN=top>The <tt>class_code</tt> attribute for the object, or \"-\" if not a transcript, or if <tt>class_code</tt> isn't present</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>3</td><td VALIGN=top>nearest_ref_id</td><td VALIGN=top><tt>NM_008866.1</tt></td><td VALIGN=top>The reference transcript to which the class code refers, if any</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>4</td><td VALIGN=top>gene_id</td><td VALIGN=top><tt>NM_008866</tt></td><td VALIGN=top>The <tt>gene_id</tt>(s) associated with the object</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>5</td><td VALIGN=top>gene_short_name</td><td VALIGN=top><tt>Lypla1</tt></td><td VALIGN=top>The <tt>gene_short_name</tt>(s) associated with the object</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>6</td><td VALIGN=top>tss_id</td><td VALIGN=top><tt>TSS1</tt></td><td VALIGN=top>The <tt>tss_id</tt> associated with the object, or \"-\" if not a transcript/primary transcript, or if <tt>tss_id</tt> isn't present</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>7</td><td VALIGN=top>locus</td><td VALIGN=top><tt>chr1:4797771-4835363</tt></td><td VALIGN=top>Genomic coordinates for easy browsing to the object</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>8</td><td VALIGN=top>length</td><td VALIGN=top><tt>2447</tt></td><td VALIGN=top>The number of base pairs in the transcript, or '-' if not a transcript/primary transcript</td>\n  </tr>\n  </table>\n <br/> \n  \n  <h2 id=\"simple_table_sample_attr_format\">Simple-table sample attributes format</h2><br/>\n  Cuffnorm reports some information about each sample (i.e. each SAM, BAM, or CXB file) in the analysis in the following format:\n  <table CELLSPACING=15>\n  <tr>\n\t<td VALIGN=top><strong>Column number</strong></td><td VALIGN=top><strong>Column name</strong></td><td VALIGN=top><strong>Example</strong></td><td VALIGN=top><strong>Description</strong></td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>1</td><td VALIGN=top>sample_id</td><td VALIGN=top><tt>q1_0</tt></td><td VALIGN=top>A unique identifier describing the sample. Has the format conditionX_N, meaning replicate N of conditionX.</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>2</td><td VALIGN=top>file</td><td VALIGN=top><tt>C1_R1.sam</tt></td><td VALIGN=top>The path to the file (SAM/BAM/CXB) attribute for the sample</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>3</td><td VALIGN=top>total_mass</td><td VALIGN=top><tt>94610</tt></td><td VALIGN=top>The total (un-normalized) number of fragment alignments for this sample</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>4</td><td VALIGN=top>internal_scale</td><td VALIGN=top><tt>1.0571</tt></td><td VALIGN=top>The scaling factor used to normalize this sample library size.</td>\n  </tr>\n  <tr>\n\t<td VALIGN=top>5</td><td VALIGN=top>external_scale</td><td VALIGN=top><tt>1</tt></td><td VALIGN=top>Reserved</td>\n  </tr>\n  </table>\n <br/> \n  \n  <h2 id=\"library\">Library Types</h2><br/>\n  <p>\n  In cases where Cufflinks cannot determine the platform and protocol used to generate \n  input reads, you can supply this information manually, which will allow Cufflinks to \n  infer source strand information with certain protocols. The available options are listed below.\n  For paired-end data, we currently only support protocols where reads are point towards each other.\n  </p>\n\t\t<table CELLSPACING=15>\n\t\t  <tr>\n\t\t\t<td VALIGN=top nowrap><strong>Library Type</strong></td><td VALIGN=top nowrap><strong>Examples</strong></td><td VALIGN=top><strong>Description</strong></td>\n\t\t  </tr>\n\t\t  <tr><td VALIGN=top nowrap>fr-unstranded (default)</td><td VALIGN=top nowrap><tt>Standard Illumina</tt></td><td VALIGN=top>Reads from the left-most end of the fragment (in transcript coordinates) map to the transcript strand, and the right-most end maps to the opposite strand.</td></tr>\n\t\t  <tr><td VALIGN=top nowrap>fr-firststrand</td><td VALIGN=top nowrap><tt>dUTP, NSR, NNSR</tt></td><td VALIGN=top>Same as above except we enforce the rule that the right-most end of the fragment (in transcript coordinates) is the first sequenced (or only sequenced for single-end reads).  Equivalently, it is assumed that only the strand generated during first strand synthesis is sequenced.</td></tr>\n\t\t  <tr><td VALIGN=top nowrap>fr-secondstrand</td><td VALIGN=top nowrap><tt>Directional Illumina (Ligation), Standard SOLiD</tt></td><td VALIGN=top>Same as above except we enforce the rule that the left-most end of the fragment (in transcript coordinates) is the first sequenced (or only sequenced for single-end reads).  Equivalently, it is assumed that only the strand generated during second strand synthesis is sequenced.</td></tr>\n\t\t  </table>\n  <p>\n  Please contact <a href=\"mailto:tophat.cufflinks@gmail.com\"><b>tophat.cufflinks@gmail.com</b></a> to request support for a new protocol.\n  </p>\n  <br/>\n  <h2 id=\"library_norm_meth\">Library Normalization Methods</h2><br/>\n  <p>\n  You can control how library sizes (i.e. sequencing depths) are normalized in Cufflinks and Cuffdiff.  Cuffdiff has several methods that require multiple libraries in order to work.  Library normalization methods supported by Cufflinks work on one library at a time.\n  </p>\n<table CELLSPACING=15>\n\t\t  <tr><td VALIGN=top nowrap><strong>Normalization Method</strong></td><td VALIGN=top nowrap><strong>Supported by Cufflinks</strong></td><td VALIGN=top nowrap><strong>Supported by Cuffdiff</strong></td><td VALIGN=top><strong>Description</strong></td></tr>\n\t\t  <tr><td VALIGN=top nowrap>classic-fpkm</td><td VALIGN=top>Yes</td><td VALIGN=top>Yes</td><td VALIGN=top>Library size factor is set to 1 - no scaling applied to FPKM values or fragment counts.  (default for Cufflinks)</td></tr>\n\t\t  <tr><td VALIGN=top nowrap>geometric</td><td VALIGN=top nowrap>No</td><td VALIGN=top>Yes</td><td>FPKMs and fragment counts are scaled via the median of the geometric means of fragment counts across all libraries, as described in Anders and Huber (Genome Biology, 2010). This policy identical to the one used by DESeq.  (default for Cuffdiff)</td></tr>\n\t\t  <tr><td VALIGN=top nowrap>quartile</td><td VALIGN=top>No</td><td VALIGN=top>Yes</td><td>FPKMs and fragment counts are scaled via the ratio of the 75 quartile fragment counts to the average 75 quartile value across all libraries.</td></tr>\n</table>\n  \n  <br/>\n  \n  <h2 id=\"dispersion_meth\">Cross-replicate dispersion estimation methods</h2><br/>\n  <p>\n  Cuffdiff works by modeling the variance in fragment counts across replicates as a function of the mean fragment count across replicates.  Strictly speaking, models a quantitity called dispersion - the variance present in a group of samples beyond what is expected from a simple Poisson model of RNA_Seq. You can control how Cuffdiff constructs its model of dispersion in locus fragment counts.  Each condition that has replicates can receive its own model, or Cuffdiff can use a global model for all conditions.  All of these policies are identical to those used by DESeq (Anders and Huber, Genome Biology, 2010)\n  </p>\n<table CELLSPACING=15>\n\t\t  <tr><td VALIGN=top nowrap><strong>Dispersion Method</strong></td><td VALIGN=top><strong>Description</strong></td></tr>\n\t\t  <tr><td VALIGN=top nowrap>pooled</td><td VALIGN=top>Each replicated condition is used to build a model, then these models are averaged to provide a single global model for all conditions in the experiment. (Default)</td></tr>\n\t\t  <tr><td VALIGN=top nowrap>per-condition</td><td>Each replicated condition receives its own model.  Only available when all conditions have replicates.</td></tr>\n\t\t  <tr><td VALIGN=top nowrap>blind</td><td>All samples are treated as replicates of a single global \"condition\" and used to build one model. (Default when no conditions are replicated)</td></tr>\n\t\t  <tr><td VALIGN=top nowrap>poisson</td><td>The Poisson model is used, where the variance in fragment count is predicted to equal the mean across replicates.  Not recommended.</td></tr>\n</table>\n\n<p>\nWhich method you choose largely depends on whether you expect variability in each group of samples to be similar. For example, if you are comparing two groups, A and B, where A has low cross-replicate variability and B has high variability, it may be best to choose <tt>per-condition</tt>. However, if the conditions have similar levels of variability, you might stick with the default, which sometimes provides a more robust model, especially in cases where each group has few replicates.  Finally, if you only have a single replicate in each condition, you must use <tt>blind</tt>, which treats all samples in the experiment as replicates of a single condition. This method works well when you expect the samples to have very few differentially expressed genes.  If there are many differentially expressed genes, Cuffdiff will construct an overly conservative model and you may not get any significant calls.  In this case, you will need more replicates in your experiment.\n</p>\n  <br/>\n  \n  <div id=\"footer\">\n  \t<table width=\"100%\" cellspacing=15><tr><td>\n    This research was supported in part by NIH grants R01-LM06845 and R01-GM083873, NSF grant CCF-0347992 and the Miller Institute for Basic\n\t\tResearch in Science at UC Berkeley.\n    </td><td align=right>\n    Administrator: <a href=\"mailto:cole@cs.umd.edu\">Cole Trapnell</a>. Design by <a href=\"http://www.free-css-templates.com\" title=\"Design by David Herreman\">David Herreman</a>\n    </td></tr></table>\n  </div>\n</div>\n\n<!-- Google analytics code -->\n<script type=\"text/javascript\">\nvar gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\ndocument.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n</script>\n<script type=\"text/javascript\">\ntry {\nvar pageTracker = _gat._getTracker(\"UA-6101038-2\");\npageTracker._trackPageview();\n} catch(err) {}</script>\n<!-- End Google analytics code -->\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/site.tmproj",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>currentDocument</key>\n\t<string>index.html</string>\n\t<key>documents</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>filename</key>\n\t\t\t<string>index.html</string>\n\t\t\t<key>lastUsed</key>\n\t\t\t<date>2012-01-03T13:36:19Z</date>\n\t\t\t<key>selected</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>filename</key>\n\t\t\t<string>howitworks.html</string>\n\t\t\t<key>lastUsed</key>\n\t\t\t<date>2012-01-02T14:02:11Z</date>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>filename</key>\n\t\t\t<string>manual.html</string>\n\t\t\t<key>lastUsed</key>\n\t\t\t<date>2012-01-02T14:02:00Z</date>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>filename</key>\n\t\t\t<string>faq.html</string>\n\t\t\t<key>lastUsed</key>\n\t\t\t<date>2012-01-02T14:01:46Z</date>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>filename</key>\n\t\t\t<string>tutorial.html</string>\n\t\t\t<key>lastUsed</key>\n\t\t\t<date>2012-01-02T14:01:38Z</date>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>filename</key>\n\t\t\t<string>gff.html</string>\n\t\t\t<key>lastUsed</key>\n\t\t\t<date>2012-01-02T14:02:27Z</date>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>filename</key>\n\t\t\t<string>igenomes.html</string>\n\t\t\t<key>lastUsed</key>\n\t\t\t<date>2012-01-02T14:02:17Z</date>\n\t\t</dict>\n\t</array>\n\t<key>fileHierarchyDrawerWidth</key>\n\t<integer>205</integer>\n\t<key>metaData</key>\n\t<dict>\n\t\t<key>faq.html</key>\n\t\t<dict>\n\t\t\t<key>caret</key>\n\t\t\t<dict>\n\t\t\t\t<key>column</key>\n\t\t\t\t<integer>16</integer>\n\t\t\t\t<key>line</key>\n\t\t\t\t<integer>110</integer>\n\t\t\t</dict>\n\t\t\t<key>firstVisibleColumn</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>firstVisibleLine</key>\n\t\t\t<integer>70</integer>\n\t\t</dict>\n\t\t<key>gff.html</key>\n\t\t<dict>\n\t\t\t<key>caret</key>\n\t\t\t<dict>\n\t\t\t\t<key>column</key>\n\t\t\t\t<integer>14</integer>\n\t\t\t\t<key>line</key>\n\t\t\t\t<integer>83</integer>\n\t\t\t</dict>\n\t\t\t<key>firstVisibleColumn</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>firstVisibleLine</key>\n\t\t\t<integer>79</integer>\n\t\t</dict>\n\t\t<key>howitworks.html</key>\n\t\t<dict>\n\t\t\t<key>caret</key>\n\t\t\t<dict>\n\t\t\t\t<key>column</key>\n\t\t\t\t<integer>16</integer>\n\t\t\t\t<key>line</key>\n\t\t\t\t<integer>108</integer>\n\t\t\t</dict>\n\t\t\t<key>firstVisibleColumn</key>\n\t\t\t<integer>206</integer>\n\t\t\t<key>firstVisibleLine</key>\n\t\t\t<integer>69</integer>\n\t\t</dict>\n\t\t<key>igenomes.html</key>\n\t\t<dict>\n\t\t\t<key>caret</key>\n\t\t\t<dict>\n\t\t\t\t<key>column</key>\n\t\t\t\t<integer>15</integer>\n\t\t\t\t<key>line</key>\n\t\t\t\t<integer>109</integer>\n\t\t\t</dict>\n\t\t\t<key>firstVisibleColumn</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>firstVisibleLine</key>\n\t\t\t<integer>72</integer>\n\t\t</dict>\n\t\t<key>index.html</key>\n\t\t<dict>\n\t\t\t<key>caret</key>\n\t\t\t<dict>\n\t\t\t\t<key>column</key>\n\t\t\t\t<integer>16</integer>\n\t\t\t\t<key>line</key>\n\t\t\t\t<integer>126</integer>\n\t\t\t</dict>\n\t\t\t<key>firstVisibleColumn</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>firstVisibleLine</key>\n\t\t\t<integer>117</integer>\n\t\t</dict>\n\t\t<key>manual.html</key>\n\t\t<dict>\n\t\t\t<key>caret</key>\n\t\t\t<dict>\n\t\t\t\t<key>column</key>\n\t\t\t\t<integer>16</integer>\n\t\t\t\t<key>line</key>\n\t\t\t\t<integer>109</integer>\n\t\t\t</dict>\n\t\t\t<key>firstVisibleColumn</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>firstVisibleLine</key>\n\t\t\t<integer>71</integer>\n\t\t</dict>\n\t\t<key>tutorial.html</key>\n\t\t<dict>\n\t\t\t<key>caret</key>\n\t\t\t<dict>\n\t\t\t\t<key>column</key>\n\t\t\t\t<integer>16</integer>\n\t\t\t\t<key>line</key>\n\t\t\t\t<integer>122</integer>\n\t\t\t</dict>\n\t\t\t<key>firstVisibleColumn</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>firstVisibleLine</key>\n\t\t\t<integer>85</integer>\n\t\t</dict>\n\t</dict>\n\t<key>openDocuments</key>\n\t<array>\n\t\t<string>tutorial.html</string>\n\t\t<string>faq.html</string>\n\t\t<string>index.html</string>\n\t\t<string>manual.html</string>\n\t\t<string>howitworks.html</string>\n\t\t<string>igenomes.html</string>\n\t\t<string>gff.html</string>\n\t</array>\n\t<key>showFileHierarchyDrawer</key>\n\t<true/>\n\t<key>windowFrame</key>\n\t<string>{{407, 273}, {1060, 694}}</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "doc/html/tutorial.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n  <head>\r\n    <title>Cufflinks RNA-Seq analysis tools - Getting Started</title>\r\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"></meta>\r\n\t<meta name=\"description\" content=\"A brief guide to using Cufflinks for gene discovery or differential analysis with RNA-Seq\"></meta>\r\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\"\r\n      media=\"screen\"></link>\r\n  </head>\r\n  <body>\r\n    <div id=\"wrap\">\r\n      <div id=\"top\">\r\n        <div class=\"lefts\">\r\n          <table cellpadding=\"2\" width=\"100%\">\r\n            <tbody>\r\n              <tr>\r\n                <td> <a href=\"./index.html\">\r\n                    <h1>Cufflinks</h1>\r\n                  </a>\r\n                  <h2>Transcript assembly, differential expression, and\r\n                    differential regulation for RNA-Seq</h2>\r\n                </td>\r\n                <td align=\"right\" valign=\"middle\"> \r\n                    <a href=\"http://www.mcb.berkeley.edu/\">\r\n                      <img style=\"vertical-align:middle;padding-top:4px\" \r\n                        border=0 src=\"images/UCBerkeley-seal.scaled.gif\">\r\n                    </a>&nbsp;\r\n                    <a href=\"http://genomics.jhu.edu/\">\r\n                    <img style=\"vertical-align:middle;padding-top:4px\"\r\n                      src=\"images/JHU-seal.gif\" border=\"0\">\r\n                    </a>&nbsp;\r\n                  <a href=\"http://www.cbcb.umd.edu/\"><img\r\n                      style=\"vertical-align:middle;padding-top:4px\"\r\n                      src=\"images/cbcb_logo.gif\" alt=\"\"></a>&nbsp;&nbsp;\r\n\r\n                </td>\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n        </div>\r\n      </div>\r\n\r\n      <div id=\"main\">\r\n        <div id=\"rightside\">\r\n          <h2>Site Map</h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <li><a href=\"index.html\">Home</a></li>\r\n              <li><a href=\"tutorial.html\">Getting started</a></li>\r\n              <li><a href=\"manual.html\">Manual</a></li>\r\n              <li><a href=\"howitworks.html\">How Cufflinks works</a></li>\r\n\t\t\t  <li><a href=\"igenomes.html\">Index and annotation downloads</a></li>\r\n              <li><a href=\"faq.html\">FAQ</a></li>\r\n\t\t\t  <li><a href=\"http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html\">Protocol</a></li>\r\n\t\t\t  <li><a href=\"report.html\">Benchmarking</a></li>\r\n            </ul>\r\n          </div>\r\n          <h2><u>News and updates</u></h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <table width=\"100%\">\r\n                <tbody>\r\n                  <tr>\r\n                    <td>New releases and related tools will be announced\r\n                      through the <a\r\n                        href=\"https://lists.sourceforge.net/lists/listinfo/bowtie-bio-announce\"><b>mailing\r\n                          list</b></a></td>\r\n                  </tr>\r\n                </tbody>\r\n              </table>\r\n            </ul>\r\n          </div>\r\n          <h2><u>Getting Help</u></h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <table width=\"100%\">\r\n                <tbody>\r\n                  <tr>\r\n                    <td>Questions about Cufflinks and Cuffdiff should be posted on our <a href=\"https://groups.google.com/forum/#!forum/tuxedo-tools-users\"><b>Google Group</b></a>. Please use <a\r\n                        href=\"mailto:tophat.cufflinks@gmail.com\">tophat.cufflinks@gmail.com</a> for private communications only.\r\n                      Please do not email technical questions to\r\n                      Cufflinks contributors directly.</td>\r\n                  </tr>\r\n                </tbody>\r\n              </table>\r\n            </ul>\r\n          </div>\r\n         \r\n       \r\n          <a href=\"./downloads\">\r\n            <h2><u>Releases</u></h2>\r\n          </a>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <table width=\"100%\">\r\n                <tbody>\r\n                  <tr>\r\n                    <td>version 2.2.0</td>\r\n                    <td align=\"right\">5/25/2014</td>\r\n                  </tr>\r\n                  <tr>\r\n                    <td><a href=\"./downloads/cufflinks-2.2.0.tar.gz\"\r\n                        onclick=\"javascript:\r\n                        pageTracker._trackPageview('/downloads/cufflinks_source');\r\n                        \">&nbsp;&nbsp;&nbsp;Source code</a></td>\r\n                  </tr>\r\n                  <tr>\r\n                    <td><a\r\n                        href=\"./downloads/cufflinks-2.2.0.Linux_x86_64.tar.gz\"\r\n                        onclick=\"javascript:\r\n                        pageTracker._trackPageview('/downloads/cufflinks');\r\n                        \">&nbsp;&nbsp;&nbsp;Linux x86_64 binary</a></td>\r\n                  </tr>\r\n                  <tr>\r\n                    <td><a\r\n                        href=\"./downloads/cufflinks-2.2.0.OSX_x86_64.tar.gz\"\r\n                        onclick=\"javascript:\r\n                        pageTracker._trackPageview('/downloads/cufflinks');\r\n                        \">&nbsp;&nbsp;&nbsp;Mac OS X x86_64 binary</a></td>\r\n                  </tr>\r\n                </tbody>\r\n              </table>\r\n            </ul>\r\n          </div>     \r\n\r\n\t\t  <h2>Related Tools</h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n                <li><a href=\"http://monocle-bio.sourceforge.net\">Monocle</a>:\r\n                  Single-cell RNA-Seq analysis</li>\r\n\t\t\t\t<li><a href=\"http://compbio.mit.edu/cummeRbund/\">CummeRbund</a>:\r\n\t                Visualization of RNA-Seq differential analysis</li>\r\n              <li><a href=\"http://tophat.cbcb.umd.edu/\">TopHat</a>:\r\n                Alignment of short RNA-Seq reads</li>\r\n              <li><a href=\"http://bowtie.cbcb.umd.edu\">Bowtie</a>:\r\n                Ultrafast short read alignment</li>\r\n            </ul>\r\n          </div>\r\n\r\n\r\n          <h2>Publications</h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <li style=\"font-size: x-small; line-height: 130%\">\r\n                <p>Trapnell C, Williams BA, Pertea G, Mortazavi AM, Kwan\r\n                  G, van Baren MJ, Salzberg SL, Wold B, Pachter L.<b> <a\r\n                      href=\"http://dx.doi.org/10.1038/nbt.1621\">Transcript\r\n                      assembly and quantification by RNA-Seq reveals\r\n                      unannotated transcripts and isoform switching\r\n                      during cell differentiation</a></b> <br>\r\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\r\n                      Biotechnology</a></i> doi:10.1038/nbt.1621</p>\r\n                <br>\r\n              </li>\r\n              <li style=\"font-size: x-small; line-height: 130%\">\r\n                <p>Roberts A, Trapnell C, Donaghey J, Rinn JL, Pachter\r\n                  L.<b> <a\r\n                      href=\"http://genomebiology.com/2011/12/3/R22/abstract\">Improving\r\n                      RNA-Seq expression estimates by correcting for\r\n                      fragment bias</a></b> <br>\r\n                  <i><a href=\"http://www.genomebiology.com\">Genome\r\n                      Biology</a></i> doi:10.1186/gb-2011-12-3-r22</p>\r\n                <br>\r\n              </li>\r\n              <li style=\"font-size: x-small; line-height: 130%\">\r\n                <p>Roberts A, Pimentel H, Trapnell C, Pachter\r\n                  L.<b> <a\r\n                      href=\"http://bioinformatics.oxfordjournals.org/content/early/2011/06/21/bioinformatics.btr355.abstract\">\r\n                      Identification of novel transcripts in annotated genomes using RNA-Seq</a></b> <br>\r\n                  <i><a href=\"http://bioinformatics.oxfordjournals.org/\">Bioinformatics</a></i> doi:10.1093/bioinformatics/btr355</p>\r\n                <br>\r\n              </li>\r\n\t\t\t  <li style=\"font-size: x-small; line-height: 130%\">\r\n                <p>Trapnell C, Hendrickson D,Sauvageau S, Goff L, Rinn JL, Pachter L<b> <a\r\n                      href=\"http://dx.doi.org/10.1038/nbt.2450\">Differential \r\n\t\t\t\t\t analysis of gene regulation at transcript resolution with RNA-seq\r\n\t\t\t\t\t</a></b> <br>\r\n                  <i><a href=\"http://www.nature.com/nbt\">Nature\r\n                      Biotechnology</a></i> doi:10.1038/nbt.2450</p>\r\n                <br>\r\n              </li>\r\n            </ul>\r\n          </div>\r\n          <h2>Contributors</h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <li><a href=\"http://www.cs.umd.edu/%7Ecole/\">Cole Trapnell</a></li>\r\n              <li><a href=\"http://www.cs.berkeley.edu/%7Eadarob/\">Adam\r\n                  Roberts</a></li>\r\n              <li>Geo Pertea</li>\r\n\t\t\t  <li>David Hendrickson<li>\r\n\t\t\t  <li>Loyal Goff</li>\r\n\t\t\t  <li>Martin Sauvageau</li>\r\n              <li>Brian Williams</li>\r\n              <li><a href=\"http://wormlab.caltech.edu/members/\">Ali\r\n                  Mortazavi</a></li>\r\n              <li>Gordon Kwan</li>\r\n              <li>Jeltje van Baren</li>\r\n\t\t\t  <li><a href=\"http://www.rinnlab.com\">John Rinn</a></li>\r\n              <li><a href=\"http://www.cbcb.umd.edu/%7Esalzberg/\">Steven\r\n                  Salzberg</a></li>\r\n              <li><a href=\"http://biology.caltech.edu/Members/Wold\">Barbara\r\n                  Wold</a></li>\r\n              <li><a href=\"http://www.math.berkeley.edu/%7Elpachter/\">Lior\r\n                  Pachter</a></li>\r\n            </ul>\r\n          </div>\r\n          <h2>Links</h2>\r\n          <div class=\"box\">\r\n            <ul>\r\n              <li><a href=\"http://bio.math.berkeley.edu/\">Berkeley LMCB</a></li>\r\n              <li><a href=\"http://www.cbcb.umd.edu/\">UMD CBCB</a></li>\r\n              <li><a href=\"http://woldlab.caltech.edu/\">Wold Lab</a></li>\r\n            </ul>\r\n          </div>\r\n        </div>\r\n        <!-- End of \"rightside\" -->\r\n        <div id=\"leftside\">\r\n          <table>\r\n            <tbody>\r\n              <tr>\r\n                <td>\r\n                  <h1> Getting started</h1>\r\n                  <br/>\r\n                  <div id=\"toc\">\r\n                    <ul>\r\n                      <li>Setting up Cufflinks</li>\r\n                      <ul>\r\n                        <li><a href=\"#inst\">Install quick-start</a></li>\r\n                        <li><a href=\"#ref\">Test the installation</a></li>\r\n                      </ul>\r\n                      <li>Common uses of the Cufflinks package</li>\r\n                      <ul>\r\n                        <li><a href=\"#discovery\">Discovering novel genes\r\n                            and transcripts</a></li>\r\n                        <li><a href=\"#differential\">Identifying\r\n                            differentially expressed and regulated genes</a></li>\r\n                      </ul>\r\n                    </ul>\r\n                    <br/>\r\n                  </div>\r\n                  <br/>\r\n                  <h2 id=\"inst\">Install quick-start</h2>\r\n                  <br/>\r\n                  <strong>Installing a pre-compiled binary release</strong><br/>\r\n                  <p>In order to make it easy to install Cufflinks, we\r\n                    provide a few binary packages to save users from\r\n                    occasionally frustrating process of building\r\n                    Cufflinks, which requires that you install the Boost\r\n                    libraries. To use the binary packages, simply\r\n                    download the appropriate one for your machine, untar\r\n                    it, and make sure the <tt>cufflinks</tt>,<tt>cuffdiff</tt>\r\n                    and <tt>cuffcompare</tt> binaries are in a\r\n                    directory in your PATH environment variable.</p>\r\n                  <br/>\r\n                  <strong>Building Cufflinks from source</strong><br/>\r\n                  <p> In order to build Cufflinks, you must have the <a\r\n                      href=\"http://www.boost.org\">Boost C++ libraries</a>\r\n                    (version 1.47 or higher) installed on your system.\r\n                    See below for instructions on installing Boost. </p>\r\n                  <br/>\r\n                  <h3 id=\"boost\">Installing Boost</h3>\r\n                  <br/>\r\n                  <ol>\r\n                    <li><a href=\"http://www.boost.org/users/download/\">Download</a>\r\n                      Boost and the <tt>bjam</tt> build engine.</li>\r\n                    <li>Unpack bjam and add it to your PATH.</li>\r\n                    <li>Unpack the Boost tarball and <tt>cd</tt> to the\r\n                      Boost source directory. This directory is called\r\n                      the BOOST_ROOT in some Boost installation\r\n                      instructions.</li>\r\n                    <li>Build Boost. Note that you can specify where to\r\n                      put Boost with the --prefix option. The default\r\n                      Boost installation directory is <tt>/usr/local</tt>.\r\n                      Take note of the boost installation directory,\r\n                      because you will need to tell the Cufflinks\r\n                      installer where to find Boost later on.\r\n                      <p>If you are on Mac OS X, type (all on one line):\r\n                        <br/>\r\n                      </p>\r\n                      <blockquote>bjam\r\n                        --prefix=&lt;YOUR_BOOST_INSTALL_DIRECTORY&gt;\r\n                        --toolset=darwin architecture=x86\r\n                        address_model=32_64 link=static\r\n                        runtime-link=static --layout=versioned stage\r\n                        install</blockquote>\r\n                    </li>\r\n                    <p>If you are on a 32-bit Linux system, type (all on\r\n                      one line): <br/>\r\n                    </p>\r\n                    <blockquote>bjam\r\n                      --prefix=&lt;YOUR_BOOST_INSTALL_DIRECTORY&gt;\r\n                      --toolset=gcc architecture=x86 address_model=32\r\n                      link=static runtime-link=static stage install</blockquote>\r\n                    <p>If you are on a 64-bit Linux system, type (all on\r\n                      one line): <br/>\r\n                    </p>\r\n                    <blockquote>bjam\r\n                      --prefix=&lt;YOUR_BOOST_INSTALL_DIRECTORY&gt;\r\n                      --toolset=gcc architecture=x86 address_model=64\r\n                      link=static runtime-link=static stage install</blockquote>\r\n                  </ol>\r\n                  <br/>\r\n                  <h3 id=\"samtools\">Installing the SAM tools</h3>\r\n                  <br/>\r\n                  <ol>\r\n                    <li><a href=\"http://samtools.sourceforge.net/\">Download</a>\r\n                      the SAM tools</li>\r\n                    <li>Unpack the SAM tools tarball and <tt>cd</tt> to\r\n                      the SAM tools source directory.</li>\r\n                    <li>Build the SAM tools by typing <tt>make</tt> at\r\n                      the command line.</li>\r\n                    <li>Choose a directory into which you wish to copy\r\n                      the SAM tools binary, the included library <tt>libbam.a</tt>,\r\n                      and the library headers. A common choice is <tt>/usr/local/</tt>.\r\n                    </li>\r\n                    <li>Copy libbam.a to the <tt>lib/</tt> directory in\r\n                      the folder you've chosen above (e.g. <tt>/usr/local/lib/</tt>)</li>\r\n                    <li>Create a directory called \"<tt>bam</tt>\" in the\r\n                      <tt>include/</tt> directory (e.g.\r\n                      /usr/local/include/bam) </li>\r\n                    <li>Copy the headers (files ending in .h) to the <tt>include/bam</tt>\r\n                      directory you've created above (e.g. <tt>/usr/local/include/bam</tt>)\r\n                    </li>\r\n                    <li>Copy the samtools binary to some directory in\r\n                      your PATH.</li>\r\n\t\t\t\t\t</ol>\r\n\t\t\t\t\t<h3 id=\"samtools\">Installing the Eigen libraries</h3>\r\n\t                  <br/>\r\n\t                  <ol>\r\n\t\t\t\t\t\t<li>Download <a href=\"http://eigen.tuxfamily.org/\">Eigen</a></li>\r\n\t\t\t\t\t\t<li>Unpack the Eigen tarball and <tt>cd</tt> to\r\n\t                      the Eigen source directory.</li>\r\n\t\t\t\t\t\t<li>Copy the <tt>Eigen/</tt> subdirectory someplace on your system where you keep header files (e.g. <tt>/usr/local/include</tt>)\r\n                  \t  </ol>\r\n                  <br/>\r\n                  <h3 id=\"boost\">Building Cufflinks</h3>\r\n                  <br/>\r\n                  <ol>\r\n                    <li>Unpack the Cufflinks source tarball:\r\n                      <blockquote>tar zxvf cufflinks-0.7.0.tar.gz</blockquote>\r\n                    </li>\r\n                    <li>Change to the Cufflinks directory:\r\n                      <blockquote>cd cufflinks-0.7.0</blockquote>\r\n                    </li>\r\n                    <li>Configure Cufflinks. If Boost is installed\r\n                      somewhere other than <tt>/usr/local</tt>, you\r\n                      will need to tell the installer where to find it\r\n                      using the <tt>--with-boost</tt> option. Specify\r\n                      where to install Cufflinks using the <tt>--prefix</tt>\r\n                      option.\r\n                      <blockquote>./configure\r\n                        --prefix=/path/to/cufflinks/install\r\n                        --with-boost=/path/to/boost --with-eigen=/path/to/eigen</blockquote>\r\n                      If you see any errors during configuration, verify\r\n                      that you are using Boost version 1.47 or higher,\r\n                      and that the directory you specified via <tt>--with-boost</tt>\r\n                      contains the boost header files and libraries. See\r\n                      the Boost <a href=\"\">Getting started</a> page for\r\n                      more details. If you copied the SAM tools binaries\r\n                      to someplace other than <tt>/usr/local/</tt>, you\r\n                      may need to supply the <tt>--with-bam</tt>\r\n                      configuration option. </li>\r\n                    <li>Finally, make and install Cufflinks.\r\n                      <blockquote>make</blockquote>\r\n                      <blockquote>make install</blockquote>\r\n                    </li>\r\n                  </ol>\r\n                  <h2 id=\"test\">Testing the installation</h2>\r\n                  <br/>\r\n                  <ol>\r\n                    <li>Download the <a href=\"downloads/test_data.sam\">test\r\n                        data</a> </li>\r\n                    <li>In the directory where you placed the test file,\r\n                      type:<br/>\r\n                      <blockquote>cufflinks ./test_data.sam</blockquote>\r\n                      <br/>\r\n                      You should see the following output:\r\n                      <pre>[bam_header_read] EOF marker is absent. The input is probably truncated.\r\n[bam_header_read] invalid BAM binary header (this is not a BAM file).\r\nFile ./test_data.sam doesn't appear to be a valid BAM file, trying SAM...\r\n[13:23:15] Inspecting reads and determining fragment length distribution.\r\n&gt; Processed 1 loci.                            [*************************] 100%\r\nWarning: Using default Gaussian distribution due to insufficient paired-end reads in open ranges.  \r\nIt is recommended that correct paramaters (--frag-len-mean and --frag-len-std-dev) be provided.\r\n&gt; Map Properties:\r\n&gt;       Total Map Mass: 102.50\r\n&gt;       Read Type: 75bp x 75bp\r\n&gt;       Fragment Length Distribution: Truncated Gaussian (default)\r\n&gt;                     Estimated Mean: 200\r\n&gt;                  Estimated Std Dev: 80\r\n[13:23:15] Assembling transcripts and estimating abundances.\r\n&gt; Processed 1 loci.                            [*************************] 100%\r\n</pre>\r\n                    </li>\r\n                    <li>Verify that the file <tt>transcripts.gtf</tt>\r\n                      is in the current directory and looks like this\r\n                      (your file will have GTF attributes, omitted here\r\n                      for clarity)\r\n                      <pre>test_chromosome Cufflinks       exon    53      250     1000    +       . \r\ntest_chromosome Cufflinks       exon    351     400     1000    +       . \r\ntest_chromosome Cufflinks       exon    501     550     1000    +       .\r\n\t\t\t\t\t\r\n\t\t\t\t</pre>\r\n                    </li>\r\n                  </ol>\r\n                  <br/>\r\n                  <h2>Common uses of the Cufflinks package</h2>\r\n                  <br/>\r\n\t\t\t\t  <p>Cufflinks includes a number of tools for analyzing RNA-Seq experiments. Some of these tools can be run on their own, while others are pieces of a larger workflow. The complexity of your workflow depends on what you want to achieve with your analysis.  For a complete discussion of how Cufflinks can help you with your analysis, please see our protocol paper.  The paper includes a diagram (Figure 2) describing how the various parts of the Cufflinks package (and its companion tool TopHat) fit together.  As of version 2.2.0, you can also run Cuffquant and Cuffnorm to make large scale analyses easier to handle.  The figure below is an updated version of Figure 2 showing how the two utilities released after the protocol paper appeared fit into the workflow:\r\n\t\t\t\t  <img style=\"vertical-align:middle;padding-top:4px; display: block; margin-left: auto; margin-right: auto;\"\r\n\t\t\t\t            border=0 src=\"images/tuxedo_workflow.png\">\r\n\t\t\t\t <p> You can use Cuffquant to pre-compute gene expression levels for each of your samples, which can save time if you have to re-run part of your analysis.  Using Cuffquant also makes it easier to spread the load of computation for lots of samples across multiple computers.  If you don't want to perform differential expression analysis, you can run Cuffnorm instead of Cuffdiff.  Cuffnorm produces simple tables of expression values that you can look at in R (for example) to cluster samples and perform other follow up analysis.</p>\r\n\t\t\t\t <br/>\r\n                  <h2 id=\"discovery\">Discovering novel genes and\r\n                    transcripts</h2>\r\n                  <br/>\r\n                  <p> RNA-Seq is a powerful technology for gene and\r\n                    splice variant discovery. You can use Cufflinks to\r\n                    help annotate a new genome or find new genes and\r\n                    splice isoforms of known genes in even\r\n                    well-annotated genomes. Annotating genomes is a\r\n                    complex and difficult process, but we outline a\r\n                    basic workflow that should get you started here. The\r\n                    workflow also excludes examples of the commands\r\n                    you'd run to implement each step in the workflow.\r\n                    Suppose we have RNA-Seq reads from human liver,\r\n                    brain, and heart. </p>\r\n                  <p> <br/>\r\n                  </p>\r\n                  <ol>\r\n                    <li><strong>Map the reads for each tissue to the\r\n                        reference genome</strong></li>\r\n                    <p> We recommend that you use TopHat to map your\r\n                      reads to the reference genome. For this example,\r\n                      we'll assume you have paired-end RNA-Seq data. You\r\n                      can map reads as follows: </p>\r\n                    <p> </p>\r\n                    <blockquote> tophat -r 50 -o tophat_brain\r\n                      /seqdata/indexes/hg19 brain_1.fq brain_2.fq \r\n                      tophat -r 50 -o tophat_liver /seqdata/indexes/hg19\r\n                      liver_1.fq liver_2.fq \r\n                      tophat -r 50 -o tophat_heart /seqdata/indexes/hg19\r\n                      heart_1.fq heart_2.fq \r\n                    </blockquote>\r\n                    <p> The commands above are just examples of how to\r\n                      map reads with TopHat. Please see the <a\r\n                        href=\"http://tophat.cbcb.umd.edu/manual.html\">TopHat\r\n\r\n\r\n                        manual</a> for more details on RNA-Seq read\r\n                      mapping. </p>\r\n                    <br/>\r\n                    <li><strong>Run Cufflinks on each mapping file</strong></li>\r\n                    <p> The next step is to assemble each tissue sample\r\n                      independently using Cufflinks. Assemble each\r\n                      tissue like so: </p>\r\n                    <blockquote> cufflinks -o cufflinks_brain\r\n                      tophat_brain/accepted_hits.bam<br/>\r\n                      cufflinks -o cufflinks_liver\r\n                      tophat_liver/accepted_hits.bam<br/>\r\n                      cufflinks -o cufflinks_heart\r\n                      tophat_liver/accepted_hits.bam<br/>\r\n                    </blockquote>\r\n                    <li><strong>Merge the resulting assemblies</strong></li>\r\n                    <tt><b>assemblies.txt:</b></tt>\r\n                    <blockquote> cufflinks_brain/transcripts.gtf<br/>\r\n                      cufflinks_liver/transcripts.gtf<br/>\r\n                      cufflinks_heart/transcripts.gtf<br/>\r\n                    </blockquote>\r\n                    Now run the merge script:\r\n                    <blockquote> cuffmerge -s\r\n                      /seqdata/fastafiles/hg19/hg19.fa assemblies.txt<br/>\r\n                    </blockquote>\r\n                    <p>The final, merged annotation will be in the file\r\n                      <tt>merged_asm/merged.gtf</tt>. At this point, you\r\n                      can use your favorite browser to explore the\r\n                      structure of your genes, or feed this file into\r\n                      downstream informatic analyses, such as a search\r\n                      for orthologs in other organisms. You can also\r\n                      explore your samples with Cuffdiff and identify\r\n                      genes that are significantly differentially\r\n                      expressed between the three conditions. See the\r\n                      workflows below for more details on how to do\r\n                      this. </p>\r\n                    <li><strong>(optional) Compare the merged assembly\r\n                        with known or annotated genes</strong></li>\r\n                    If you want to discover new genes in a genome that\r\n                    has been annotated, you can use <tt>cuffcompare</tt>\r\n                    to sort out what is new in your assembly from what\r\n                    is already known. Run cuffcompare like this:\r\n                    <blockquote> cuffcompare -s\r\n                      /seqdata/fastafiles/hg19/hg19.fa -r\r\n                      known_annotation.gtf merged_asm/merged.gtf<br>\r\n                    </blockquote>\r\n                    Cuffcompare will produce a number of output files\r\n                    that you can parse to select novel genes and\r\n                    isoforms.\r\n                  </ol>\r\n                  <br/>\r\n                  <h2 id=\"differential\">Identifying differentially\r\n                    expressed and regulated genes</h2>\r\n                  <br/>\r\n                  <p> There are two workflows you can choose from when\r\n                    looking for differentially expressed and regulated\r\n                    genes using the Cufflinks package. The first\r\n                    workflow is simpler and is a good choice when you\r\n                    aren't looking for novel genes and transcripts. This\r\n                    workflow requires that you not only have a reference\r\n                    genome, but also a reference gene annotation in GFF\r\n                    format (GFF3 or GTF2 formats are accepted, see\r\n                    details <a href=\"gff.html\">here</a>). The second\r\n                    workflow, which includes steps to discover new genes\r\n                    and new splice variants of known genes, is more\r\n                    complex and requires more computing power. The\r\n                    second workflow can use and augment a reference gene\r\n                    annotation GFF if one is available. </p>\r\n                  <br/>\r\n                  <b>Differential analysis without gene and transcript\r\n                    discovery</b>\r\n                  <p> </p>\r\n                  <ol>\r\n                    <li><strong>Map the reads for each condition to the\r\n                        reference genome</strong></li>\r\n                    <p> We recommend that you use TopHat to map your\r\n                      reads to the reference genome. For this example,\r\n                      we'll assume you have paired-end RNA-Seq data.\r\n                      Suppose you have RNA-Seq from a knockdown\r\n                      experiment where you have two biological\r\n                      replicates of a mock condition as a control and\r\n                      two replicates of your knockdown. </p>\r\n                    <p> <b>Note:</b> Cuffdiff will work much better if\r\n                      you map your replicates independently, rather than\r\n                      pooling the replicates from one condition into a\r\n                      single set of reads. </p>\r\n                    <p> </p>\r\n                    <p> <b>Note:</b> While an GTF of known transcripts\r\n                      is not strictly required at this stage, providing\r\n                      one will improve alignment sensitivity, and\r\n                      ultimately, the accuracy of Cuffdiff's analysis. </p>\r\n                    <p> You can map reads as follows: </p>\r\n                    <blockquote> tophat -r 50 -G annotation.gtf -o\r\n                      tophat_mock_rep1 /seqdata/indexes/hg19 \\<br/>\r\n                      &nbsp;&nbsp;mock_rep1_1.fq mock_rep1_2.fq <br/>\r\n                      tophat -r 50 -G annotation.gtf -o tophat_mock_rep2\r\n                      /seqdata/indexes/hg19 \\<br/>\r\n                      &nbsp;&nbsp;mock_rep2_1.fq mock_rep2_2.fq <br/>\r\n                      tophat -r 50 -G annotation.gtf -o\r\n                      tophat_knockdown_rep1 /seqdata/indexes/hg19 \\<br/>\r\n                      &nbsp;&nbsp;knockdown_rep1_1.fq\r\n                      knockdown_rep1_2.fq <br/>\r\n                      tophat -r 50 -G annotation.gtf -o\r\n                      tophat_knockdown_rep2 /seqdata/indexes/hg19 \\<br>\r\n                      &nbsp;&nbsp;knockdown_rep2_1.fq\r\n                      knockdown_rep2_2.fq <br/>\r\n                    </blockquote>\r\n                    <li><strong>Run Cuffdiff</strong></li>\r\n                    Take the annotated transcripts for your genome (as <a\r\n                      href=\"gff.html\">GFF or GTF</a>) and provide them\r\n                    to <tt>cuffdiff</tt> along with the BAM files from\r\n                    TopHat for each replicate:\r\n                    <blockquote> cuffdiff annotation.gtf\r\n                      mock_rep1.bam,mock_rep2.bam \\<br>\r\n                      &nbsp;&nbsp; knockdown_rep1.bam,knockdown_rep2.bam<br>\r\n                    </blockquote>\r\n                  </ol>\r\n                  <br/>\r\n                  <b>Differential analysis with gene and transcript\r\n                    discovery</b>\r\n                  <p> </p>\r\n                  <ol>\r\n                    <li><strong>Complete steps 1-3 in \"Discovering novel\r\n                        genes and transcripts\", above</strong></li>\r\n                    <p>Follow the protocol for gene and transcript\r\n                      discovery listed above. Be sure to provide TopHat\r\n                      and the assembly merging script with an reference\r\n                      annotation if one is available for your organism,\r\n                      to ensure the highest possible quality of\r\n                      differential expression analysis. </p>\r\n                    <li><strong>Run Cuffdiff</strong></li>\r\n                    Take the merged assembly from produced in step 3 of\r\n                    the discovery protocol and provide it to <tt>cuffdiff</tt>\r\n                    along with the BAM files from TopHat:\r\n                    <blockquote> cuffdiff merged_asm/merged.gtf\r\n                      liver1.bam,liver2.bam brain1.bam,brain2.bam<br/>\r\n                    </blockquote>\r\n                    As shown above, replicate BAM files for each\r\n                    conditions <strong>must</strong> be given as a\r\n                    comma separated list. If you put spaces between\r\n                    replicate files instead of commas, cuffdiff will\r\n                    treat them as independent conditions.\r\n                  </ol>\r\n                  <div id=\"footer\">\r\n                    <table cellspacing=\"15\" width=\"100%\">\r\n                      <tbody>\r\n                        <tr>\r\n                          <td> This research was supported in part by\r\n                            NIH grants R01-LM06845 and R01-GM083873, NSF\r\n                            grant CCF-0347992 and the Miller Institute\r\n                            for Basic Research in Science at UC\r\n                            Berkeley. </td>\r\n                          <td align=\"right\"> Administrator: <a\r\n                              href=\"mailto:cole@cs.umd.edu\">Cole\r\n                              Trapnell</a>. Design by <a\r\n                              href=\"http://www.free-css-templates.com\"\r\n                              title=\"Design by David Herreman\">David\r\n                              Herreman</a> </td>\r\n                        </tr>\r\n                      </tbody>\r\n                    </table>\r\n                  </div>\r\n\r\n                  <!-- Google analytics code -->\r\n                  <script type=\"text/javascript\">\r\nvar gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\r\ndocument.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\r\n</script>\r\n                  <script type=\"text/javascript\">\r\ntry {\r\nvar pageTracker = _gat._getTracker(\"UA-6101038-2\");\r\npageTracker._trackPageview();\r\n} catch(err) {}</script>\r\n                  <!-- End google analytics code --> </td>\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </body>\r\n</html>\r\n"
  },
  {
    "path": "doc/illustrator/Fig 2 - Tuxedo Workflow.ai",
    "content": "%PDF-1.5\r%\r\n1 0 obj\r<</Metadata 2 0 R/OCProperties<</D<</ON[7 0 R]/Order 8 0 R/RBGroups[]>>/OCGs[7 0 R]>>/Pages 3 0 R/Type/Catalog>>\rendobj\r2 0 obj\r<</Length 68822/Subtype/XML/Type/Metadata>>stream\r\n<?xpacket begin=\"﻿\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"Adobe XMP Core 4.2.2-c063 53.352624, 2008/07/30-18:05:41        \">\n   <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n      <rdf:Description rdf:about=\"\"\n            xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n         <dc:format>application/pdf</dc:format>\n         <dc:title>\n            <rdf:Alt>\n               <rdf:li xml:lang=\"x-default\">Fig 2 - Tuxedo Workflow</rdf:li>\n            </rdf:Alt>\n         </dc:title>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\"\n            xmlns:xmpGImg=\"http://ns.adobe.com/xap/1.0/g/img/\">\n         <xmp:MetadataDate>2014-03-25T09:14:22-04:00</xmp:MetadataDate>\n         <xmp:ModifyDate>2014-03-25T09:14:22-04:00</xmp:ModifyDate>\n         <xmp:CreateDate>2014-03-25T09:14:22-04:00</xmp:CreateDate>\n         <xmp:CreatorTool>Adobe Illustrator CS4</xmp:CreatorTool>\n         <xmp:Thumbnails>\n            <rdf:Alt>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <xmpGImg:width>116</xmpGImg:width>\n                  <xmpGImg:height>256</xmpGImg:height>\n                  <xmpGImg:format>JPEG</xmpGImg:format>\n                  <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAB0AwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXnWv6J50tdQ1XU&#xA;7XUY7OKV6xXst/IgaJ2hWOD0ZopbaDhxcBwpLE+LNhVinmKz/NG90qa0g876ZJPMVlWVLuK0VJku&#xA;fU/3XE8noGFFUR8q1PxMwqCqirOD8xIHeH/GlgLd7zkJzewyyi24xK5b1IDyduDFAKBO/KtMVZVZ&#xA;aZ56vNS8t6umsWlzY6bAsOoxQuzpeyTForpy0fCMGHgjJ8Bq3IfB+0FZ5irsVdirsVYn5zPnEX+n&#xA;nQ1na34vyW3Nuqm59SP0/rZnDOLf0/U5ekOX08cVYW/n380o7mRZYdKSGKSCGVDJAJ1DLObyQIbu&#xA;nK2kiSOOMn95yBJXfiVS3QPO/wCbEdsJNUntJJPqoohewPCX6yyk8VuhzZoVDceYC12riqdT+ZPz&#xA;I1PQrqCKS1TWjcQyQxaRLBJItuZZUmRfUkk9QIqRtz4qTy6Dpihn3q+ZP8Ger6I/xL+juf1fklPr&#xA;3oV4cqen/fbVpx+jAlOsVdiqXa//ALwxf8xll/1GRYqkXma3/M8auLjy1dac2nFI42sb5XFG51kl&#xA;EkalieOwWtPpxVd5XT8zBfxv5lfTms2gcTx2fMFZwY/TaPkK8WHqcwxO9KbdVUbpH6b+rz/Vvq3o&#xA;/XL3h6nqcv8AeuWteO3XCqMNz5iiBL2Vvcou59GdkkYeCxyRhK/OUYFVrDV7W8lktwHgvIhWW0nX&#xA;hKo6cgN1da7c0JWvfFUTcXNvbQSXFxIsMESlpJZCFVVHUknYDFUvXV7+5odP06R4j9m4u2+qxsO9&#xA;FKyT/fEAfHFV3q+ZTQ/VbJKdU+sSvy/2XoJx/wCBOKpO8Hme58qzR6Hcw6frDXt0RNIPWjSl7KXU&#xA;clHKvSpUYVSbj+ezpMJH0KJgjNb+l67fvVL8FfmN42HDlQBh2PXFWYXnL9L6VzoHpPyA3FfTFaYF&#xA;TPFXYq7FVK5tbW6gaC6hSeB6FopVDoeJDCqsCNiK4qg/8NeXP+rVZ/8ASPF/zTirv8NeXP8Aq1Wf&#xA;/SPF/wA04qjLa1tbWBYLWFIIEqViiUIg5EsaKoA3JriqrirGfzFv7jSPLNxr9pZteXejUu0SNuMg&#xA;jQj1qbHkpjrzXaq9PiAxVJPK/m/VPNHms6bqWiS2MelWdtqEhaQPB614qyQVNAXkjHJQKUDKx6hc&#xA;KvQcCuxVL5PL2gSSPJJplo8kjF5HaCMszMasxJXckmpxVr/DXlz/AKtVn/0jxf8ANOKqtro2j2k3&#xA;rWtjb281CvqRRIjUPUVUA4qjMVeVW/5w+bYUZ9T8j36xKATPCJAi1MnLkJY0IVAg5N94U/DhVl2g&#xA;+bdU1afR2bRprOy1S0uriSWYtyhe3mjjjRhwA4zJJzjJIJHbArJ8VdirsVQd5rOk2cohuryGGZhV&#xA;YWdRIwP8qV5H6Bir54/5yD/MXXtP87+XLDS9TvrDSb1CtwlsPq8rMzhVdfXjbYF6147j8FIYq/8A&#xA;ytW9E9xYeb9TFioQpbtD9ankSQlf3JjWJbjgUPrcQPSqFNeuK0iFsPzQkuZ7a08+zz3sZ0lZY7cL&#xA;K6i/0ua/kLArErBWhpFxc1Xc77YqkN152/NHy5588vaTc+aLy8F3Lbi7EiemnJrlreVE5KOagoaN&#xA;ir7APmPSk3maa3j7y3FtcQRj/WkljRF+k4oR9vcW9xCk9vKk0LiqSxsGVh4hhUHFVTFXYq7FXYq7&#xA;FVK6u7S0ga4u5o7eBSoaWVgiAswVQWYgbsQB74qg/wDEvlz/AKutn/0kRf8ANWKsI0bzDr2q6/qw&#xA;12+stO8r+ux0uOHUIUu5I1VY1EnpFyqOUMvwyow5UNRthVnejxaKlmH0dbcWjs1HteBRmUlWPJNm&#xA;YMCD74FYB+a35E+X/wAxr+zvr+/ubG4s42iVrcKaqSD+3UDFWF2//OH/AJdtllW380apEsyGKUKI&#xA;RVGZXK/Z6FkB+jFbUV/5wz8pqar5j1IHxCwjoKfy+G2Ko3SP+cRfKenaxZam2uahdPZTJMkcojoT&#xA;G/MbgA/a3xV7zirEvMEukrFd3Ggapp9h5iVmAke4SKJ5Ubiy3aKH9SlCDyXkOxU4VW+R/MUsXlex&#xA;t/NOqWB1y2T0LyeK6hkSYxniswYFf7xQGNVG9dsCsjtda0a7mEFrf2885BYRRSo7EDqeKknbFUZi&#xA;rsVdiqXa/wD7wxf8xll/1GRYq818xecPP2jeZrywbXNEjUzRS2lleckkWxlmlXmZCII/UAeMU5k0&#xA;Uni3cqjdC83+d9d1m2t7LUtDks3MFzJHbyNJctarODc8CPUhb906LVWNCwrxOKsu0jVfRt54vqd1&#xA;JxvL3444+Sn/AEuU7GuKo0+ZNMj3ufXtFH25Lm3miiX/AFpnQRD/AILAqYxSxTRJLE6yROAySIQy&#xA;sDuCCNiMVXYqgLnXdJt7g2z3Ae7UVa1hDTzAdamKIO9PoxVZ/iCw/wB9Xn/SDef9UsVYX5m1rzDp&#xA;ehWer6XqNppmlpqF3+lZL+OSvpyahVAqLFJIGKh0NQKct+mxVjsH5mefaSLPqvldDAkXqyC4eRdp&#xA;WWeUiJmZEMcfMclAX4gW+ycVeiaWuuq2i/p54ZNULXrTNbf3XFmYxBagfZiKj+vXArJMVdirsVQW&#xA;s2t1c2IjtQjTpNbzKsrFEPozpKQWVXIqE/lxVJ9V8vjVnV9U8u6TfOrKytcTNIQyGqmrWp3GKtaZ&#xA;5cXSpkm03y9pVnLGrRxvDOyFVkKlwCLXYMUUnxxVOdGtbq2sTHdBFnea4mZYmLoPWneUAMyoTQP/&#xA;AC4qjcVYv5mvtK8owDX3mWw08zompxEEQOJm4+qaDjHIpNeX7f2TUlaKoay86aB5t1RdH0fUyY1t&#xA;xd36xepFcmNyBHHuFkhDA8mb4WoV49ahVldpZ2lnAtvaQpBAteMcahVFdyaDxxVWxVIBpuqfVprK&#xA;fT7G9tWuLiZPWncVE07yrVDbuAQHp1OKpZH5D0eNXWPyjokaurI4V+IKyVLqaWnRuRqMKp5FbatL&#xA;qFpNcW9tb29qsgAhmeUkuoUAKYYgAPngVNsVSWw87eT78E2etWctAGIE8YPE8qNQkGh4Eg9xv0xV&#xA;GR69osl3b2cV9BJc3cbTWsSSKxkjQ0Zkodx/Q+BxVHYq7FXYqsuJhDBJMRURqzkDqQorir5pg/5y&#xA;x81X+t3emaV5Ys5ltmkLXFzeraRrFG/D1JpZisMQqQKs9KkDvimkFqH/ADkV5080rqHlG68hRXLX&#xA;ME8d5aG5dD6caOzkOyhaj02KEHdh8NTTFaUx+efm7yxrurXyfl7bw6jdtFBqUsFyZlVbOJY4hyhV&#xA;1EYRhxatG7E02VpXvP8AnLrztZLK915LjhjglMEsrSzCNZVJUpz9PjWqnv2xWntv5QfmLJ5/8nRa&#xA;/LaLZTPLJFJAjF1HBqbE74oZtirsVdirsVYJP+SP5bSqa6Wyy9Vm9eZnUgsVILu3QuTv1O7VxVOd&#xA;H8g+WtIuNPuLKGRZdMgkt7QtNIyhZ3aWVihbgXkd2LNT8AMVZFirsVSu/wBUuTdnTdLjWW+Ch55p&#xA;QfQt0b7LScaF2NPhjUgnuVG+KqcvlxLiGT67dz3lxIhWskjJCCRtS3iKREA9OSs3iTir5dtP+ca/&#xA;zX07V9XlgtdLv9M1VZLe5tbq5kjEsDTpcJX0eLoyywxuOL9V3qKjFNp7bflL+etraww2umaDbSW4&#xA;eOGW3uJ4uEDPdyLAqIQgVX1GUg05fZqdt1bdP+VX/OQE2mz2DW2jCO4nFzLJ9Zm5sy2ElhQnuCkx&#xA;c1/apitqXmr8nvz38zaZeWV/ZaKr31wtzPcx3MobkoVQEQ1jQcIo1PFRXjvU4rb1L8lvyquvKnka&#xA;DSteCjVUlldprSV0ZVdywUTRFGpv0xQzV7nUtFBkvpzfaStTLeOqrPbr15TcAqPEO7KoKjdqirBV&#xA;OwQRUbg4q7FXYq7FXYqgrrWLK2uTbSes8wRZGSGCeaiuWVSTEjgVKN18MVSzXtZ9fQ9Rh0+O8F/L&#xA;azJaH6ndrSZo2Efxelt8VN8VS7yM1zonl6G01q7vNT1aRmnvrwafdIGlkoWApCCwHQFt/kKKFWSW&#xA;usWVzci2j9ZJijSKk0E8NVQqrEGVEBoXXp44qjcVdirsVdiqjeXlvZ25uLgkRAqvwqzsWdgigKgZ&#xA;iSzAbDFUFJrti8bIEvULAgOLG6JFR1HKEj7xirFPy6g1Ly5Z6pY6xeXmqJJfGbTbo2N0hW09CKKO&#xA;IxLAqR+n6R2Qce4A6YqyqXzJpkUbyyrdRxRgs7tZ3YVVAqSSYtgMVTTFXYq7FWPawkzz66kN5+j5&#xA;G0yAC+4ljAOd1WUAFd0G4364qwCO91ZZGtB+bFj6qPDDweC29VCRwVW5Scubl1+11PbrhVz3Op2j&#xA;NdS/mlbqkZR5ZJYI/T9ORY0oQX9MN8Ib25EkAE1VZvZpqlpJoSRzJrFwunXPq3ckpj9YF7Y81PGX&#xA;kW7VI+eKpofMEVv/AMdK1n05P9/zBHgHiWlhaRIx7yccCporKyhlIKkVBG4IOKt4qhb7VbCxKLcy&#xA;0llr6MCK0kr068IowztSu9BtiqUatqV7cW1uv6MuIIWvLItNO0KgD65FSiLI7/QVGFWKebZ9StPN&#xA;E0y/mDb6DbyyRJ+i7mGNgPTjV1SMyvTlJyYvxG/w9xiqWFtXmhR5PzSt5kLFT9XgiAJ4ywniYn5f&#xA;CwZm8CtdqAhVOdDe8uND8xzT+bYfMxgsprWVLdEjWGVFkJ5KjMOTDv3HtTFXo2BXYq7FUrvtKu5r&#xA;ueeCeBY7qBLa4guIGnVljaQ/syxdfWIINcVSc+QbFpDI1no7SM8cjO2mkkvDT02JNx1WnXCrU/kC&#xA;znRUnttKliSMQpE9hIyBFbmPgNyVry70rjapzYaTdQXUE000BitLd7a2gtoGgVUcxnvLLsohAAFM&#xA;CpoQCKHcHFUkMS6Fcw/Vxx0e6kEUluPs200ppG8Y/ZjkchGQbBiCKDliqN1i/mtbdEtVWS+unEFn&#xA;G9eBkILFnpvwRFZ270FBvTFXaZpNvYh5ORnvZ6G6vZN5ZCPE/sqK/Ci/CvYYqqanZPeWnoxyCKQS&#xA;RSxyMvNQ0MqyrVQUqCUodxiqS33lE39x9Yvo9LuZw6yCWXT3duaDirVNz1A2xVDr5CtUt5LeK30q&#xA;GGUcXSKwkiqPUMtKpcqd3Yk+OFVa38nNa2l9a2P6OsYtSVlvDa2DRM/MFSai4pUcjSo2wKybFXYq&#xA;7FXYq7FXYq7FXYqk3nODV7jyrqkOjpHJqT27i2ilrxdqV4gqQQzDZW7NQ4qxDyZq/wCYmqebLM6/&#xA;p1vb2a6Ql+86LIvpvfkf6JxJI9SNoDVidlFKfFXFXpGKuxV2KuxV2KuxV5Vb/nD5thRn1PyPfrEo&#xA;BM8IkCLUycuQljQhUCDk33hT8OFU1tfzN1m90nUbuHyze2k1rbR3NqLiKd0uPUk4cY/SiLEkDkvt&#xA;u3EVoqyLSfMOq32tyWM+jXFjZx2qzC8npxeYyFWiTjUUC0YE0Y/yjAqfYq7FVC/d47G4kQ8XSJ2U&#xA;+BCkjFXxCkPmjV4JLwarrfr393cD9JwXZj06yKXIhENxGQvxNzVvhlUgMtEeuKU0sfJfmOLyw13r&#xA;fmfWrPWJmmW3hFxOiRrF9RIaWNxzaq3zGgZegpiqDs/I3nq+gv7iz87XTQ2MXqEyTXEbM3GWSnH1&#xA;TtwgpUV+JgKU+LFaRmlflj+YWph2tvO116MZjAuXlukhkMzcR6LPIpkEbf31B8FD1NAVae6/84v6&#xA;pqmofljE+o3T3c8V1PGJpGLsQrkfaO56YoeuYq7FXYq7FXYq7FXYq7FXYq06I6MjjkjAqynoQdiM&#xA;VeQX/wDziz+V15dXFw0V0n1mQyyRpO6pzJqTxUhepPbFVFv+cUfywYlm+usx6k3MhO/+y9sVQmmf&#xA;84t/ljdW8krJdoRNcQELcy7rDO8Yr8Xf0wcVTm5/5xs8h3On22nTTXrWVoSYIROygErxqxWhY8fh&#xA;HImg2GK2zryV5K0LyboUeiaLG0dlEzOA7cmLNu25364qn2KuxV2KuxV2KuxV2KuxV2KuxV2KrZRI&#xA;YnETBZCp4MwqA1NiRUVxVif5Y3vmq90G4n8x2cWn3f168SO1h5EUW4fm5LEmjS8+P+TTrWuKsuxV&#xA;2KuxV2KuxV2KuxV2KuxV2KuxVKvM0EM+lpDPGssT3dkHjcBlI+uRbEHY4q6bQfK0Kh5tOsYkJChn&#xA;hhUcmNAKkdScVSrzD5csrmwRNCi0y0u/VRnmkt4HBiG5QAowq5KrWm1a4VSjRNH1FvMEa6pB5fl0&#xA;YwSAfVY4xO1wshBBVkPIKrKCQVoR0PLZQy2PQPK8n93p1i+wPwwwnY9Oi+2BKhFpmm2XmS0NnaQ2&#xA;xezuw5hjSPlSW2pXiBXFU7xV2KuxV2KuxV2KuxV2KuxVLtf/AN4Yv+Yyy/6jIsVa8weXdH8waeNP&#xA;1aD6xaCaK49PkyfvIHEiElCp+0vTFXkN3+XkNjq0unad+XTXGmQB7aDUF1P0hJbvJBJXhy5ci4av&#xA;gAPoKoWz8g6ipMzeQfqcT+rO0Tai8xDzAPJGFhaqgnn0DGp26cSoep+SPJuhaFare6fpraXdX1tA&#xA;t3aGaSUR8OUgj+MkVVpWBIGBKbT/APKR2P8AzB3f/J22xVMcVdirsVdirsVdiqhe3tvZW5uLgsIg&#xA;yJ8CPIxaRwiAIgZjVmA2GKoX9P2P++rz/pCvP+qWKu/T9j/vq8/6Qrz/AKpYqqo2mazYfHEtzZyM&#xA;VaK4iIHOGShDRyqCCkidx1GKqX+GvLn/AFarP/pHi/5pxV3+GvLn/Vqs/wDpHi/5pxVL/L3l7QJd&#xA;A0ySTTLV5HtYGd2gjLFjGpJJK7k4qmH+GvLn/Vqs/wDpHi/5pxVWtNH0izlM1pY29tMVKGSKJEbi&#xA;SCVqoBpUDFVD/EOnFnVVuZPTd4maO0unXnGxRwGWMqaMpGxxVv8AT9j/AL6vP+kK8/6pYqvt9asZ&#xA;7lLZROk0gYoJreeEMF60aVEX8cVR2KuxV2Kpdr/+8MX/ADGWX/UZFirzXzENY07zNeW4/MZNNuZ5&#xA;oruLTbqMLHHZPNKGjEsvqISfWAFAGoi/ZG4Ko3QpNd1nWbZbfz9b3sQMF42nWkSMJIIZxJKEuFKF&#xA;0ZZERqD4eVD2GKsu0q61aG2nMVilzbC8vaGOcCc/6XLX93IiR9f+LcCpha65ZzXC2kyyWd61eNtc&#xA;rwZyBU+mwJjloNz6bNTviqYYql3lr/lHNK/5g7f/AJNLiqIv9TsNPjWS8mWISNwiU1LyORUJGgqz&#xA;safZUE4qhRrF3Jvb6TdyI393K/owqd6VKSSLMo+cdfbFWGeZlvI9Cs9Xk8xv5YsrLULs6jwRpxKJ&#xA;NQ5LEeDD9qPjWh2Y9sKsdg1bzFGJFufzT00pAkQaSGGGVgscrepLIn7AeOP4nrxVlJ6Nir0TS9P1&#xA;LT20W11K/Op3qtevLesvHmJWaRRxqaBFYKPYYFZJirsVdiqD1aymvbP0YJVglWWCZJHQyKDBMktC&#xA;gaMmvCn2sVSbVfKA1Z1fVIdJvnVlZWuNOaQhkNVNWuDuMVa0zyaulTJNpsOlWcsatHG8OnshVZCp&#xA;cAi42DFFJ8cVTrSbKays/RnlWeVpZ5nkRDGpM8zy0CFpCKc6faxVVvbG0vrZ7a7iEsL0qpqCCDVW&#xA;UihVlO6sDUHcYqwq08669b+aNS8qPo9xNNYWE9/pd5dMsY1BIWiVI0kT1V5VkKsx+LoSo3xVLNP/&#xA;ADTk078ufLetS6NOX1WaPTdPsEJkuGpDII5WRFJozQVKitFNdzthVnmjaWIY0vrstPqs8YNxcyqF&#xA;deQB9JEBYRRqf2FPuSzVYhUzxVIm0DUWt5rSS4sp7SSeadYrizeSnrTPLQn6woJXnStBiqVR/lpo&#xA;8ausem6JGrqyOF0viCslS6mlx0bkajCqfQ6ZqZvra4urq3eK1VxHDBbvF9tQv2mmlFAB0pgVNMVe&#xA;VW/5w+bYUZ9T8j36xKATPCJAi1MnLkJY0IVAg5N94U/DhVkei+d9a1TU9EjGhXFpp+qW009xNMj1&#xA;haNnVKtxVAriMEV+I81+HrQKzLFXYq7FVG9keKyuJENHSN2U+4UkYq+BU89+d9Y88Jp9x5jmsob/&#xA;AFJbaS6dhwhSWcRmRq/soDU1OKWVnTfzE1GcyWF/rGi20EUst9barxmnhjt4LqZpS0McNFk+pMih&#xA;41+MhasPiKrI5vKWrXOsQ2+keaNWmtROlqfUAoJX1CG2o9wsASH91doF/dvyZWbpRMUsH/MPzBqu&#xA;gQ6X+hvMupXU1yJPrjTuvEGOOEDgoijpWRpG6n4eI6qWZV9I/wDOMvmDV9b/ACxt7nVblrq4S4mj&#xA;ErmrcVchR9AGLF6zirsVdirsVdirsVdirsVdiq2SNJI2jcVRwVYeIIocVeE6n/ziD5GvdQuLtdRu&#xA;4BcSNJ6ShSFLGppU4qon/nD3ygSxOt35LgBz8O4AoAd8U2hdN/5xJ8oXtilx+mL+P1SSUqp3RiAe&#xA;o8MUWrt/zhx5Lb7WsXp+YX+uKvXfy+8h6R5H8tw6FpbO9vGzO0kn2mZzUn78VZJirsVdirsVdirs&#xA;VdirsVdiqjeXlvZ25uLgkRAqvwqzsWdgigKgZiSzAbDFUJ+n7H/fV5/0hXn/AFSxVRvdbhls54rY&#xA;3lvcyRusNx9Qum9NypCvxaEqeJ3oRirHvy41TXbbypbp5qS4/TLvI8sENhdCKFS5CIhWI8thyJJJ&#xA;qfDbCrJ/0/Y/76vP+kK8/wCqWBVW11eyurj6vH6yTFDIEmgmgqqkBivqolaFxWnjiqMxV2KuxV2K&#xA;uxV2KuxV2KuxVLtf/wB4Yv8AmMsv+oyLFUc9xAjFXkRWAqQWAIHjvirze+86fmpbSmWLy9Z3FjC5&#xA;+subiOF+ANGA5TsFK8h8R2I3oK7FVaXzx+ZoQuvk+FVjmhWWuoQMDFJx9R1Pw04fF17jpirKfLWu&#xA;313o9nL5ggh0nWrn1i+metG5URSMKKwY86R8WJ99wvQBUXP/AMpHY/8AMHd/8nbbFUxxV2KuxV2K&#xA;uxV2KuxV2KuxVK/MkscWmLLK4jijurNndiAqqLuIkknoBirFde8p/lZrmryaxfXkB1GURB50vgop&#xA;B9mic+G6/Cfh6e9DhVCz/l7+S88kryG0rM5kcC+KjkzQuxAEopye1Rj4mp74qr/4M/KFrCayE1r6&#xA;FwCJCL4hj+6eEEMJa7JIwH39cVQkv5b/AJKyzGV3tyxaZxTUHADXLc5SAJf2mp92Ksyi1HT77zFa&#xA;GyuoboR2l0JDDIsnHlLb8eXEmleJpgVOsVdirsVdirsVdirsVdirsVdirsVUbyd7e0nuEhe4eGN5&#xA;Ft4qGSQqpIRKkDk1KCpxVjv5a+Y7TzF5SttTs4ZorN3lSB514NIquQXC1O3Kq7+GKsoxV2KuxV2K&#xA;uxV2KsIs/wA6Py4uW4NqwtZdiI7mOWJjVmUdV61Q7dR0O+2Koqf81fIcVhc3y6rHNFa+n6yxhiw9&#xA;VyiijBd+QIPhTfGlV7/8yPJ9jqUenT33+kyyQRR8EZkLXLyxpRwOJAeB1ah+Eih3xVk2KrZXKRO4&#xA;FSqlqfIVxV8kN/zkL+Y9zr2u+vqkem6PpUzRcoLIXcxJm9GJVjMtupqftHkKDoCdipRln+ZH/ORd&#xA;5qlzp1ve6eJLZoU5zRNBzNzNDBbjhIFkRpJLqNeLqpUn4qUOK0pT/ml/zkBDD6rarpJ5RR3ECAHl&#xA;LFNAtxC6bdJI5F48qGp3pvRWk1h8zfnno2nGG91TTtMkRZ2trKKCH0+NurvMSWmhIo8bj4EetKj4&#xA;SCVaSy7/ADQ/5yBi1hdNtdS029Ess0UFzEgCMYHkSSoYhl4tA4Ip22qKHFaQ9x+cX5322k6rqU2t&#xA;6WY9Mt0uljijZ3nje4trclAQtFVrxalqdNh3xWnvP5Ged9Y86fl5Z67q/D67JLNE5jHFT6Tca09/&#xA;8/HFDP8AFXYq7FUhk8g+SHiMR0KxCH+SCNCKBgCCoBBUOeNOnbFV0fkbyZHbPbLoll6EkaQyoYIz&#xA;zSM8kD1HxUbep774qibryx5cu7iK5utLtZriD0/RleFGZPRZnj4kjbi0jEfM4qmeKtSIHRkPRgQa&#xA;e+2Kvm26/wCcU/NVv5jvtY8v+b/0W93JK5ZElEnGV+ZUmNk25dt+3fFKyL/nGD8z4oIYIvzCdIbc&#xA;q0CKLkBGWVJ1K0k6iWFHHuqnsMVtDN/zif5/YIG88hhFHHDGDHOeMcSCONB+82VEUKo7AYrayP8A&#xA;5xi/MLVora+l8+NK0YkFu0yTs6BwYpKH1WpyWoPjitpi3/ONX5rvNNM35jStNcBRO5+skvwLMvI+&#xA;pv8AE7H5muK2gz/zil+YLaZLpTeeuWlz8fXsuE/pPxZWHJfUKmjRqdx1A8MVt7f+VXkFfInk218u&#xA;rc/WjC8kry0p8Up5NTptXpihl2KuxV2KuxV2KuxV2KuxVSuru0tIGuLuaO3gUqGllYIgLMFUFmIG&#xA;7EAe+KoP/Evlz/q62f8A0kRf81YqpXXmHQ5LaaODWrOCd0ZYpvWhbg5FFbiWoaHehxVjX5aeYblP&#xA;KsX+KdT0+LVWmmrbwyxokcauUQCrknnx9SpP7WFWVf4l8uf9XWz/AOkiL/mrAqtaaxpF5KYbS+t7&#xA;mYKXMcUqO3EEAtRSTSpGKovFXYq7FXYq7FXYq7FXYq7FUu1//eGL/mMsv+oyLFUdNIY4ZJAhkKKW&#xA;CL1YgVoPc4q8/s/zdmldIJ/KurrdtEkzRwQ+qlHYAhXb0uXCo57bHDSqmn/my981vw8q63CkwUu9&#xA;xatGFDTejTetWrRqGlV3xVmWjak2p6bDetazWTS8g1rcrwlQo5Q8gCevGoPcb4FU5/8AlI7H/mDu&#xA;/wDk7bYqmOKuxV2KuxV2KuxV2KuxV2KpV5mnhg0tJp5FiiS7si8jkKoH1yLck7DFVT/Evlz/AKut&#xA;n/0kRf8ANWKpF5xTy55m0n9Ft5lTToHcm4ls7qJJXjaJ4ygblQbuG3B3HTFUJ5f0vy1o2q/pFfNk&#xA;l4xSaN4Lm9ieNvWaNuTCu7J6VFPap8cKso/xL5c/6utn/wBJEX/NWBULFqem3vmS0Fndw3JSzuy4&#xA;hkSTjWW2pXiTTFU7xV2KuxV2Kv8A/9k=</xmpGImg:image>\n               </rdf:li>\n            </rdf:Alt>\n         </xmp:Thumbnails>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:xmpMM=\"http://ns.adobe.com/xap/1.0/mm/\"\n            xmlns:stRef=\"http://ns.adobe.com/xap/1.0/sType/ResourceRef#\"\n            xmlns:stEvt=\"http://ns.adobe.com/xap/1.0/sType/ResourceEvent#\">\n         <xmpMM:InstanceID>uuid:155fe8cb-f01e-d24b-b813-ae3e52f9e449</xmpMM:InstanceID>\n         <xmpMM:DocumentID>xmp.did:F77F117407206811B6D0A1EA3A02BFDA</xmpMM:DocumentID>\n         <xmpMM:OriginalDocumentID>uuid:5D20892493BFDB11914A8590D31508C8</xmpMM:OriginalDocumentID>\n         <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>\n         <xmpMM:DerivedFrom rdf:parseType=\"Resource\">\n            <stRef:instanceID>uuid:6e782097-6684-c248-a076-86f4978afbf2</stRef:instanceID>\n            <stRef:documentID>xmp.did:01801174072068118DA082E1D2F4BBD4</stRef:documentID>\n            <stRef:originalDocumentID>uuid:5D20892493BFDB11914A8590D31508C8</stRef:originalDocumentID>\n            <stRef:renditionClass>proof:pdf</stRef:renditionClass>\n         </xmpMM:DerivedFrom>\n         <xmpMM:History>\n            <rdf:Seq>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>converted</stEvt:action>\n                  <stEvt:params>from application/pdf to &lt;unknown&gt;</stEvt:params>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:D27F11740720681191099C3B601C4548</stEvt:instanceID>\n                  <stEvt:when>2008-04-17T14:19:15+05:30</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>converted</stEvt:action>\n                  <stEvt:params>from application/pdf to &lt;unknown&gt;</stEvt:params>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>converted</stEvt:action>\n                  <stEvt:params>from application/pdf to &lt;unknown&gt;</stEvt:params>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F97F1174072068118D4ED246B3ADB1C6</stEvt:instanceID>\n                  <stEvt:when>2008-05-15T16:23:06-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FA7F1174072068118D4ED246B3ADB1C6</stEvt:instanceID>\n                  <stEvt:when>2008-05-15T17:10:45-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:EF7F117407206811A46CA4519D24356B</stEvt:instanceID>\n                  <stEvt:when>2008-05-15T22:53:33-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F07F117407206811A46CA4519D24356B</stEvt:instanceID>\n                  <stEvt:when>2008-05-15T23:07:07-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F77F117407206811BDDDFD38D0CF24DD</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T10:35:43-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>converted</stEvt:action>\n                  <stEvt:params>from application/pdf to &lt;unknown&gt;</stEvt:params>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F97F117407206811BDDDFD38D0CF24DD</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T10:40:59-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>converted</stEvt:action>\n                  <stEvt:params>from application/vnd.adobe.illustrator to &lt;unknown&gt;</stEvt:params>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FA7F117407206811BDDDFD38D0CF24DD</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T11:26:55-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FB7F117407206811BDDDFD38D0CF24DD</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T11:29:01-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FC7F117407206811BDDDFD38D0CF24DD</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T11:29:20-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FD7F117407206811BDDDFD38D0CF24DD</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T11:30:54-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FE7F117407206811BDDDFD38D0CF24DD</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T11:31:22-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:B233668C16206811BDDDFD38D0CF24DD</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T12:23:46-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:B333668C16206811BDDDFD38D0CF24DD</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T13:27:54-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:B433668C16206811BDDDFD38D0CF24DD</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T13:46:13-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F77F11740720681197C1BF14D1759E83</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T15:47:57-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F87F11740720681197C1BF14D1759E83</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T15:51:06-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F97F11740720681197C1BF14D1759E83</stEvt:instanceID>\n                  <stEvt:when>2008-05-16T15:52:22-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>converted</stEvt:action>\n                  <stEvt:params>from application/vnd.adobe.illustrator to application/vnd.adobe.illustrator</stEvt:params>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FA7F117407206811B628E3BF27C8C41B</stEvt:instanceID>\n                  <stEvt:when>2008-05-22T13:28:01-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>converted</stEvt:action>\n                  <stEvt:params>from application/vnd.adobe.illustrator to application/vnd.adobe.illustrator</stEvt:params>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FF7F117407206811B628E3BF27C8C41B</stEvt:instanceID>\n                  <stEvt:when>2008-05-22T16:23:53-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>converted</stEvt:action>\n                  <stEvt:params>from application/vnd.adobe.illustrator to application/vnd.adobe.illustrator</stEvt:params>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:07C3BD25102DDD1181B594070CEB88D9</stEvt:instanceID>\n                  <stEvt:when>2008-05-28T16:45:26-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>converted</stEvt:action>\n                  <stEvt:params>from application/vnd.adobe.illustrator to application/vnd.adobe.illustrator</stEvt:params>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F87F1174072068119098B097FDA39BEF</stEvt:instanceID>\n                  <stEvt:when>2008-06-02T13:25:25-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F77F117407206811BB1DBF8F242B6F84</stEvt:instanceID>\n                  <stEvt:when>2008-06-09T14:58:36-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F97F117407206811ACAFB8DA80854E76</stEvt:instanceID>\n                  <stEvt:when>2008-06-11T14:31:27-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:0180117407206811834383CD3A8D2303</stEvt:instanceID>\n                  <stEvt:when>2008-06-11T22:37:35-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F77F117407206811818C85DF6A1A75C3</stEvt:instanceID>\n                  <stEvt:when>2008-06-27T14:40:42-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>\n                     <rdf:Bag>\n                        <rdf:li>/</rdf:li>\n                     </rdf:Bag>\n                  </stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:01801174072068118DA082E1D2F4BBD4</stEvt:instanceID>\n                  <stEvt:when>2011-08-03T11:43:02-04:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F77F117407206811B6D0A1EA3A02BFDA</stEvt:instanceID>\n                  <stEvt:when>2014-03-25T09:14:18-04:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS4</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n            </rdf:Seq>\n         </xmpMM:History>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:illustrator=\"http://ns.adobe.com/illustrator/1.0/\">\n         <illustrator:Type>Document</illustrator:Type>\n         <illustrator:StartupProfile>Print</illustrator:StartupProfile>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:xmpTPg=\"http://ns.adobe.com/xap/1.0/t/pg/\"\n            xmlns:stDim=\"http://ns.adobe.com/xap/1.0/sType/Dimensions#\"\n            xmlns:stFnt=\"http://ns.adobe.com/xap/1.0/sType/Font#\"\n            xmlns:xmpG=\"http://ns.adobe.com/xap/1.0/g/\">\n         <xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint>\n         <xmpTPg:HasVisibleTransparency>False</xmpTPg:HasVisibleTransparency>\n         <xmpTPg:NPages>1</xmpTPg:NPages>\n         <xmpTPg:MaxPageSize rdf:parseType=\"Resource\">\n            <stDim:w>3.495361</stDim:w>\n            <stDim:h>8.004625</stDim:h>\n            <stDim:unit>Inches</stDim:unit>\n         </xmpTPg:MaxPageSize>\n         <xmpTPg:Fonts>\n            <rdf:Bag>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stFnt:fontName>HelveticaNeue-Bold</stFnt:fontName>\n                  <stFnt:fontFamily>Helvetica Neue</stFnt:fontFamily>\n                  <stFnt:fontFace>Bold</stFnt:fontFace>\n                  <stFnt:fontType>TrueType</stFnt:fontType>\n                  <stFnt:versionString>9.0d57e1</stFnt:versionString>\n                  <stFnt:composite>False</stFnt:composite>\n                  <stFnt:fontFileName>HelveticaNeue.dfont</stFnt:fontFileName>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stFnt:fontName>HelveticaNeue</stFnt:fontName>\n                  <stFnt:fontFamily>Helvetica Neue</stFnt:fontFamily>\n                  <stFnt:fontFace>Regular</stFnt:fontFace>\n                  <stFnt:fontType>TrueType</stFnt:fontType>\n                  <stFnt:versionString>9.0d57e1</stFnt:versionString>\n                  <stFnt:composite>False</stFnt:composite>\n                  <stFnt:fontFileName>HelveticaNeue.dfont</stFnt:fontFileName>\n               </rdf:li>\n            </rdf:Bag>\n         </xmpTPg:Fonts>\n         <xmpTPg:PlateNames>\n            <rdf:Seq>\n               <rdf:li>Cyan</rdf:li>\n               <rdf:li>Magenta</rdf:li>\n               <rdf:li>Yellow</rdf:li>\n               <rdf:li>Black</rdf:li>\n            </rdf:Seq>\n         </xmpTPg:PlateNames>\n         <xmpTPg:SwatchGroups>\n            <rdf:Seq>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <xmpG:groupName>Default Swatch Group</xmpG:groupName>\n                  <xmpG:groupType>0</xmpG:groupType>\n                  <xmpG:Colorants>\n                     <rdf:Seq>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>White</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>Black</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>100.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>CMYK Red</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>100.000000</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>CMYK Yellow</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>CMYK Green</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>100.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>CMYK Cyan</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>100.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>CMYK Blue</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>100.000000</xmpG:cyan>\n                           <xmpG:magenta>100.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>CMYK Magenta</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>100.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=15 M=100 Y=90 K=10</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>14.999998</xmpG:cyan>\n                           <xmpG:magenta>100.000000</xmpG:magenta>\n                           <xmpG:yellow>90.000000</xmpG:yellow>\n                           <xmpG:black>10.000002</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=90 Y=85 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>90.000000</xmpG:magenta>\n                           <xmpG:yellow>85.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=80 Y=95 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>80.000000</xmpG:magenta>\n                           <xmpG:yellow>95.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=50 Y=100 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>50.000000</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=35 Y=85 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>35.000004</xmpG:magenta>\n                           <xmpG:yellow>85.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=5 M=0 Y=90 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>5.000001</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>90.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=20 M=0 Y=100 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>19.999998</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=50 M=0 Y=100 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>50.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=75 M=0 Y=100 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>75.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=85 M=10 Y=100 K=10</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>85.000000</xmpG:cyan>\n                           <xmpG:magenta>10.000002</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>10.000002</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=90 M=30 Y=95 K=30</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>90.000000</xmpG:cyan>\n                           <xmpG:magenta>30.000002</xmpG:magenta>\n                           <xmpG:yellow>95.000000</xmpG:yellow>\n                           <xmpG:black>30.000002</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=75 M=0 Y=75 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>75.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>75.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=80 M=10 Y=45 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>80.000000</xmpG:cyan>\n                           <xmpG:magenta>10.000002</xmpG:magenta>\n                           <xmpG:yellow>45.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=70 M=15 Y=0 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>70.000000</xmpG:cyan>\n                           <xmpG:magenta>14.999998</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=85 M=50 Y=0 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>85.000000</xmpG:cyan>\n                           <xmpG:magenta>50.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=100 M=95 Y=5 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>100.000000</xmpG:cyan>\n                           <xmpG:magenta>95.000000</xmpG:magenta>\n                           <xmpG:yellow>5.000001</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=100 M=100 Y=25 K=25</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>100.000000</xmpG:cyan>\n                           <xmpG:magenta>100.000000</xmpG:magenta>\n                           <xmpG:yellow>25.000000</xmpG:yellow>\n                           <xmpG:black>25.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=75 M=100 Y=0 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>75.000000</xmpG:cyan>\n                           <xmpG:magenta>100.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=50 M=100 Y=0 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>50.000000</xmpG:cyan>\n                           <xmpG:magenta>100.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=35 M=100 Y=35 K=10</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>35.000004</xmpG:cyan>\n                           <xmpG:magenta>100.000000</xmpG:magenta>\n                           <xmpG:yellow>35.000004</xmpG:yellow>\n                           <xmpG:black>10.000002</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=10 M=100 Y=50 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>10.000002</xmpG:cyan>\n                           <xmpG:magenta>100.000000</xmpG:magenta>\n                           <xmpG:yellow>50.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=95 Y=20 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>95.000000</xmpG:magenta>\n                           <xmpG:yellow>19.999998</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=25 M=25 Y=40 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>25.000000</xmpG:cyan>\n                           <xmpG:magenta>25.000000</xmpG:magenta>\n                           <xmpG:yellow>39.999996</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=40 M=45 Y=50 K=5</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>39.999996</xmpG:cyan>\n                           <xmpG:magenta>45.000000</xmpG:magenta>\n                           <xmpG:yellow>50.000000</xmpG:yellow>\n                           <xmpG:black>5.000001</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=50 M=50 Y=60 K=25</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>50.000000</xmpG:cyan>\n                           <xmpG:magenta>50.000000</xmpG:magenta>\n                           <xmpG:yellow>60.000004</xmpG:yellow>\n                           <xmpG:black>25.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=55 M=60 Y=65 K=40</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>55.000000</xmpG:cyan>\n                           <xmpG:magenta>60.000004</xmpG:magenta>\n                           <xmpG:yellow>65.000000</xmpG:yellow>\n                           <xmpG:black>39.999996</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=25 M=40 Y=65 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>25.000000</xmpG:cyan>\n                           <xmpG:magenta>39.999996</xmpG:magenta>\n                           <xmpG:yellow>65.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=30 M=50 Y=75 K=10</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>30.000002</xmpG:cyan>\n                           <xmpG:magenta>50.000000</xmpG:magenta>\n                           <xmpG:yellow>75.000000</xmpG:yellow>\n                           <xmpG:black>10.000002</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=35 M=60 Y=80 K=25</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>35.000004</xmpG:cyan>\n                           <xmpG:magenta>60.000004</xmpG:magenta>\n                           <xmpG:yellow>80.000000</xmpG:yellow>\n                           <xmpG:black>25.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=40 M=65 Y=90 K=35</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>39.999996</xmpG:cyan>\n                           <xmpG:magenta>65.000000</xmpG:magenta>\n                           <xmpG:yellow>90.000000</xmpG:yellow>\n                           <xmpG:black>35.000004</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=40 M=70 Y=100 K=50</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>39.999996</xmpG:cyan>\n                           <xmpG:magenta>70.000000</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>50.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=50 M=70 Y=80 K=70</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>50.000000</xmpG:cyan>\n                           <xmpG:magenta>70.000000</xmpG:magenta>\n                           <xmpG:yellow>80.000000</xmpG:yellow>\n                           <xmpG:black>70.000000</xmpG:black>\n                        </rdf:li>\n                     </rdf:Seq>\n                  </xmpG:Colorants>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <xmpG:groupName>Grays</xmpG:groupName>\n                  <xmpG:groupType>1</xmpG:groupType>\n                  <xmpG:Colorants>\n                     <rdf:Seq>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=100</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>100.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=90</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>89.999405</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=80</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>79.998795</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=70</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>69.999702</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=60</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>59.999104</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=50</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>50.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=40</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>39.999401</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=30</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>29.998802</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=20</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>19.999701</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=10</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>9.999103</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=0 Y=0 K=5</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>0.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>4.998803</xmpG:black>\n                        </rdf:li>\n                     </rdf:Seq>\n                  </xmpG:Colorants>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <xmpG:groupName>Brights</xmpG:groupName>\n                  <xmpG:groupType>1</xmpG:groupType>\n                  <xmpG:Colorants>\n                     <rdf:Seq>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=100 Y=100 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>100.000000</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=75 Y=100 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>75.000000</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=0 M=10 Y=95 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>0.000000</xmpG:cyan>\n                           <xmpG:magenta>10.000002</xmpG:magenta>\n                           <xmpG:yellow>95.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=85 M=10 Y=100 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>85.000000</xmpG:cyan>\n                           <xmpG:magenta>10.000002</xmpG:magenta>\n                           <xmpG:yellow>100.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=100 M=90 Y=0 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>100.000000</xmpG:cyan>\n                           <xmpG:magenta>90.000000</xmpG:magenta>\n                           <xmpG:yellow>0.000000</xmpG:yellow>\n                           <xmpG:black>0.000000</xmpG:black>\n                        </rdf:li>\n                        <rdf:li rdf:parseType=\"Resource\">\n                           <xmpG:swatchName>C=60 M=90 Y=0 K=0</xmpG:swatchName>\n                           <xmpG:mode>CMYK</xmpG:mode>\n                           <xmpG:type>PROCESS</xmpG:type>\n                           <xmpG:cyan>60.000004</xmpG:cyan>\n                           <xmpG:magenta>90.000000</xmpG:magenta>\n                           <xmpG:yellow>0.003099</xmpG:yellow>\n                           <xmpG:black>0.003099</xmpG:black>\n                        </rdf:li>\n                     </rdf:Seq>\n                  </xmpG:Colorants>\n               </rdf:li>\n            </rdf:Seq>\n         </xmpTPg:SwatchGroups>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n         <pdf:Producer>Adobe PDF library 9.00</pdf:Producer>\n      </rdf:Description>\n   </rdf:RDF>\n</x:xmpmeta>\n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                           \n<?xpacket end=\"w\"?>\rendstream\rendobj\r3 0 obj\r<</Count 1/Kids[9 0 R]/Type/Pages>>\rendobj\r9 0 obj\r<</ArtBox[3.01709 17.9717 248.42 573.686]/BleedBox[0.0 0.0 251.666 576.333]/Contents 10 0 R/LastModified(D:20140325091420-04'00')/MediaBox[0.0 0.0 251.666 576.333]/Parent 3 0 R/PieceInfo<</Illustrator 11 0 R>>/Resources<</ColorSpace<</CS0 12 0 R>>/ExtGState<</GS0 13 0 R>>/Font<</TT0 5 0 R/TT1 6 0 R>>/ProcSet[/PDF/Text]/Properties<</MC0 7 0 R>>/XObject<</Fm0 14 0 R/Fm1 15 0 R/Fm2 16 0 R/Fm3 17 0 R/Fm4 18 0 R>>>>/Thumb 19 0 R/TrimBox[0.0 0.0 251.666 576.333]/Type/Page>>\rendobj\r10 0 obj\r<</Filter/FlateDecode/Length 1660>>stream\r\nHWMo\u001b7\u00109,7\u0004(\u0016\u0005\u0010rBͿ\u001br?#n\u000e5\fK.98pxL\u001c̔8:pvTGB~8Oxe]\u001dY+M\"\fVi\u0005֔\u0013\\{̈́\u0015$\u0014z+[dbKJ\u0004b¯\u0002.֔ՂtV&V(W\u0003\u0010\u0000\\z\u0001\u0000vKcЎ^e\u0018<)9.\u0001H4bR\u001e\u0000\t8\tIh@\u0018\u0007t\u001b્D\u001cm魟_\n2(5z\u0003Z\u0006[m)pNK\u0002\u0001\\\u0000ީ>6\u0006^B\u0000I\u0007[&mV\u0000\u0004?R.M؂\u0019\u0006:,BɈ<\u0001(\u0016\u0013 \u001bL\f\u0018I)}\u0006/\u000b\u0001Oy\u0003\t!Mhdn\u0014\u0006\nT#p#l߄\u001a@K\u0010\u0019E5{b\u0007q\u001e#VND\u000biDe~-\u0011 MQ*\r V!-T\u001a\"\u0002\u0000AlPGD}\u0001eHLB\"A\u001a+0[@\u0005y1\u0011\rcH=8\u001f2^ÄG,J\u001bW\u0004w$\u0015(.\u0016fjH^L)\u0017\u001al\u0018\u000buS\u0011\fK`#\\$e]\u0006x{\u001f\u0003cԱCA\u0019to֦ep%z!҅+E\u0004\u0003\u000e--W\r'=L\u0017*\u0000%\u0014M\nP6t\"\nHc; &h\u0003Qm=\u0006U\b\u000b\u0003C\u0017ga9^WXfX/\u0011ga1\n\u000b2\u0006\u0014\u001fNsD<7{*ԣ֡P\\\u0012G#\u0001bр?\u001dI8Seь6ު\u001d\u0013R^NVE\b\n\u0010+\u0002U̷E\b<6\u000f\u001a\u000fv,vXVݸlLrфƠ8@CP\u0013r\u0007-h\u0012޾SuZۍJKע!\r^\rplƣJjO\u0004\u0016-V\u001dAiMPe+v'bAqPFP((f$7\tMVM\u0018\u001c)\u001e\u001aAI{\u0004E^P4V?\t]49QM|rm%_\u0012\u001bx\u001f\u0011\u0018\u0004\\\u0013\u00032\u001cѼ:y\b\u0011\u0006KN>uuln\u0007o\u0016Ʊ\u001d\u001cf{^\nR﫯M\u0019q\u0013\u001b%\u0014onA$ޜ_=\\ވ<|\u0016:H:Ìq󩍓(͓N\u0003!\n\fz\u0016vZ7=*>ޅlұny\u000b㾰FH\t\u001bE'\u000b\u0015ߊj\u0017?\u0019cxR\fov\\\u0010O>|_(mq)9<\u001fm(_ȧ]rD\u0013ڀ̎!e\u0004]\u0002hDuy=Hh쑎\u001a}AqKѸ\u0007W\u0017(\u001e\\,kypm\u0003~\t.?\u001f,+skB\u0015\bfF)КWy>mg2{\u001d_(\u0001\u0016wֽ\u0005\t\u0016\u0011\t\u001b3dˇq\u000edt}-[WvJ\u0018p *ITQgS\u0005'q\u0010tn2=h(\u0017\u001aC--s-=琣-Öfq.\u0017SL\u0018ô\u0018f6c{Eƿi\u0001<\n}p4oѥ8\u0004Qqڨ>)Qݿ\u0011ല.Kh 5&ПOfN\u001e\u0010]H\u0002\u0013\t]?Vle*~lǗxۦmjrB\t\u0001\u0014N\u0001cO\u001fwE\rb~<C\u001em󜐓@ws\u0002_Sld&\u0005\u0018\u0000!\rendstream\rendobj\r19 0 obj\r<</BitsPerComponent 8/ColorSpace 20 0 R/Filter[/ASCII85Decode/FlateDecode]/Height 72/Length 390/Width 31>>stream\r\n8;XuY_%FU.#c*jcW02VX&+,mE#V)35*f&e?M.C#qR@aXK7WsAcp:+5_\\.<<ts)b.C\njlRl?G]@*V=m3oR:%.$be0Qi^qlLmH@63]XA+dq7+<8X0G9W^j`#<]$ord/NL^eK=\nbo#l1HPTihZ-]TtdK0Hb<G+R$5pH9q]s?)!,]^7dqLI\\di^9gkqh=F\\kg-@d2>5;+\ncYKh08D(I[]i!9h-%>$I8Jh\\g99n#]6sTuE6>*\\iB_*:FP/d`>j,=nUiN1o-r<>>R\n2%/277Y_n^hci;HatI`1Y1X`-0N!O\\PYBph@s,i9Wo[K$(.GD)=tLAfEKHrEanLEF\n)LCQ'f=5OX?0s*RG1MMj6QWY>k#uBV_*a!4F>s\"sLZY.Nma,&+)ZV9h'Uf~>\rendstream\rendobj\r20 0 obj\r[/Indexed/DeviceRGB 255 21 0 R]\rendobj\r21 0 obj\r<</Filter[/ASCII85Decode/FlateDecode]/Length 428>>stream\r\n8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@\"pJ+EP(%0\nb]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\\Ulg9dhD*\"iC[;*=3`oP1[!S^)?1)IZ4dup`\nE1r!/,*0[*9.aFIR2&b-C#s<Xl5FH@[<=!#6V)uDBXnIr.F>oRZ7Dl%MLY\\.?d>Mn\n6%Q2oYfNRF$$+ON<+]RUJmC0I<jlL.oXisZ;SYU[/7#<&37rclQKqeJe#,UF7Rgb1\nVNWFKf>nDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j<etJICj7e7nPMb=O6S7UOH<\nPO7r\\I.Hu&e0d&E<.')fERr/l+*W,)q^D*ai5<uuLX.7g/>$XKrcYp0n+Xl_nU*O(\nl[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\\~>\rendstream\rendobj\r14 0 obj\r<</BBox[120.977 515.788 165.831 500.794]/Group 22 0 R/Length 72/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 13 0 R>>/XObject<</Fm0 23 0 R>>>>/Subtype/Form>>stream\r\nq\n2 w 4 M 0 j 0 J []0 d \n/GS0 gs\n0 Tc 0 Tw 0  Ts 100  Tz 0 Tr /Fm0 Do\nQ\n\rendstream\rendobj\r15 0 obj\r<</BBox[118.178 439.934 172.373 424.939]/Group 24 0 R/Length 72/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 13 0 R>>/XObject<</Fm0 25 0 R>>>>/Subtype/Form>>stream\r\nq\n2 w 4 M 0 j 0 J []0 d \n/GS0 gs\n0 Tc 0 Tw 0  Ts 100  Tz 0 Tr /Fm0 Do\nQ\n\rendstream\rendobj\r16 0 obj\r<</BBox[112.179 343.154 177.391 328.16]/Group 26 0 R/Length 72/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 13 0 R>>/XObject<</Fm0 27 0 R>>>>/Subtype/Form>>stream\r\nq\n2 w 4 M 0 j 0 J []0 d \n/GS0 gs\n0 Tc 0 Tw 0  Ts 100  Tz 0 Tr /Fm0 Do\nQ\n\rendstream\rendobj\r17 0 obj\r<</BBox[122.199 203.172 167.587 188.178]/Group 28 0 R/Length 72/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 13 0 R>>/XObject<</Fm0 29 0 R>>>>/Subtype/Form>>stream\r\nq\n2 w 4 M 0 j 0 J []0 d \n/GS0 gs\n0 Tc 0 Tw 0  Ts 100  Tz 0 Tr /Fm0 Do\nQ\n\rendstream\rendobj\r18 0 obj\r<</BBox[99.3652 96.2881 190.421 81.2939]/Group 30 0 R/Length 72/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 13 0 R>>/XObject<</Fm0 31 0 R>>>>/Subtype/Form>>stream\r\nq\n2 w 4 M 0 j 0 J []0 d \n/GS0 gs\n0 Tc 0 Tw 0  Ts 100  Tz 0 Tr /Fm0 Do\nQ\n\rendstream\rendobj\r30 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r31 0 obj\r<</BBox[99.3652 96.2881 190.421 81.2939]/Group 32 0 R/Length 116/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 12 0 R>>/ExtGState<</GS0 13 0 R>>/Font<</TT0 5 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n/CS0 cs 0 0 0 0  scn\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0  Ts 100  Tz 0 Tr 14 0 0 14 99.3652 84.29 Tm\n(CummeRbund)Tj\nET\n\rendstream\rendobj\r32 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r5 0 obj\r<</BaseFont/WPNYIA+HelveticaNeue/Encoding/WinAnsiEncoding/FirstChar 32/FontDescriptor 33 0 R/LastChar 121/Subtype/TrueType/Type/Font/Widths[278 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 648 685 722 704 611 574 0 722 0 0 0 0 871 0 0 0 0 685 0 574 0 0 0 0 0 0 0 0 0 0 0 0 537 593 537 593 537 296 574 0 222 0 519 222 853 556 574 593 0 333 500 315 556 0 0 518 500]>>\rendobj\r33 0 obj\r<</Ascent 1077/CapHeight 714/Descent -481/Flags 32/FontBBox[-951 -481 1446 1077]/FontFamily(Helvetica Neue)/FontFile2 34 0 R/FontName/WPNYIA+HelveticaNeue/FontStretch/Normal/FontWeight 400/ItalicAngle 0/StemV 84/Type/FontDescriptor/XHeight 517>>\rendobj\r34 0 obj\r<</Filter/FlateDecode/Length 12271/Length1 30359>>stream\r\nH\tPTG\u001aǿ\u001dr(\"Ffcq7D\u0015d]\u0015\u0003\bF$z-\u001eQjb\u001cewx+x[お0\r-HRڞw^w\u0000\u000b}\u001d\\\u0013OLIH[{\u0006o\u0000<JH7\u0003\u000f\u001f6,E\t\u000f\u0000Ra#\u000eM\u000f\u0000\u0004%\u0003%\rI\u0018Zq\u0011@\u00181c\bmtH\u0012`HJIό12{\t\u00169\"51\u0001o\u0003))\ti\rgKN\"`LH\u0019b\u0000i=81>\u001bh/w\u000b\bB}B\u0000m\u001cT\u0002\u0010\ft\u001b\u0007^\u0015^\u0010sEc\"ቂN\u0003~B2\u001d]M<'\u000fH>=qpT}ۆ&FMɘ3p6.e\u0002ō\u0019wn\u0011sP\u0018\u0019Ԟ:ӛԏ\u0012SJ\fBi\u000e-E\u0015-\u001c<Sy\fO9͋y\t\rw~>%\u0006J)XiXZ%}'\u001dJ+Rr_Ҁ*\r\u0006\u0016Eh6@\u001b%i#\u0018mv@;ndnںZb\u001bG_\u001fOз{<~^\u001fgz^cXD#\u0018e7\u0018\u001bMFT\u0006\u0019l\u0011li1c8|m3\u0007i6 [c[jkc{\u0016o\u001bTv\u0003!p{S,qΑ]##S\"SG\u000f\u001e\u0011\u0011\u0013\u00169T#\u00110=Uggx?\tkp\\\\q\u0015M+<e\u0004\u0014NԉPw\bIY4\u0005%^i=mDNq<MП/\n9\u000fp1?@\u001a$IBiFʑ\bg|F\u000e\u0010x[\u0004@-TӴO\u0004-Y\u001b奿O˳uuuuL\u0007=\\7w>u\u0007\u000fa~Q\u0017\u000fbTaH6ҌtciB\u001dPif~\u0017k\u000e0,A_\u000bM\u000f\u0007A\u001el\u000fMâ@L3\u00078,\u000e_G\u00108\u0000\nss\u0007+q1~\u0001 G@}[srB1d9^\u0012@.\u0011\u00103VykF5=\r<J*|qʋھ'Տ\u001fTŜrY\n+fŗ}\u0005p縗z-{\u0006p/cn\t9]\\s]]3]]\\Y)I\u0000LBBɮ\u00007ӷ~+rm}Δۃ>x\u0017l!Ƶ\u0015j\u0017`yU2\u000b\u0014$\u0016/p7לmmQΖN{\u0012gvaeaEᑢE|[~\u0016OԝKbYb-1q/b˖c7]\u001f\ncx^(B.M|\u00055I\n% o~HX7[-_\u0015yP ﭏ\u001ekWchoݺo\u000e/E|;7ұNwK)WjTE\u001c\u0001j\u001azZ!jJ\u00153_\u0014g)<C\u001f\u001dgl\u00031́E\u0000¿a\u0003\u0015C\u0001̄e\u001cJ\u000bX\u0001p\u0004\u0000Mp\u001f\u001bf8\t?\u0016\u0018ji\u0003K \tNpNy8\u0003g\u001c<d\u0004\u0017D6\nC\u00122\\\u0011P\u000e`\u001e\u0014HQ\u0006:\u0018\rc \u001d2s\u0018\u000b0\u000e\u000e%\"7M\t0\t\u0007,\n`:T3؋g!FxPd<<\u0017\u000f/R\u0000Lx\u00022\u0005a>Uj(\u0014\u000f\u0011Bx°\u00065B\"jNjȊIǛ\u001d2\u0005WO6%\u001bޣ\u0002d\u0007\u0012S$>Vp\u0017Q<5>(jCI4\fP4>XL1\rr\u0019b)s\u001d\u001eǟ=\u001e˩\u0003A%VQ':c\ru\u0011\u0019߰DDe&rxwP\u000f؇'$P\u0001Ք\\'ʓ)7C?<\u0019rdT&K5\u0017\u0018ưV֕-l6\f R܂#\u001ff[y\u001bv\u001a\u000eɻD?^5ZmD>\u0007Gl<>\u0007ϓ/P;װ^WV*o(TF+6%W\u0014(9v{eST\u001bJR8:qOd?9bR\rR2ˁr6Kr\u001c,`\u001f9K\u00192RT**Oe\u001f<\u0015n E\u000esb}4c\\\u0000\u000e \t\u0007s\b7V)\u001c*U*\u000fν\u0003\b\u000e(\f#(02\b8\u0004\t(0().D1K,VW5jL\u001a[\u001a\u001bmIø\u0014רM?6$jpR\r\u0003_>7s~.b\u001f\\+Ѥ\u00121\u001a\u0007YEɧ0\n\u001dq(\u0003ۘi\u0019\u0000\u000e\u001f\u0015-\u00188\u001c8\u00023p$՜gq c, \u001c\t\u0018/w]6|\u00040\u0013G\u0014;ΰX9h\"yI^W5yY^\u0017p\b&kX8FE{d'ȳ^\u0001y1\u001fks8Ɂ\u000b\u001c\n\u00058\u0007\u0017\u0014|\u0001p\u0016%,\u0014Oa\u0005\u0016S\u0016/\n\u0012\n:\u001bx\u0010Re/&܂p\u0007\rw\u001b\u000f|\u0005_y<XTDZ$\u0016ڴ3Yh\u0007`),\u0013s\u0005Oh5\u0000'+\b\tbx\u001a8,rQbU\rTq*\u00165D\b(Wb<!%?UT1e--`=\u00018\bf1\bN\u0005|\\,gsyMr\\*|\t_ʗ-W\u0005\"_ȟTuT;m\u001bk57/r|U&oA\u0006\u000eƷ?\u0006\u0013.wS\u001e@\u000e\f`E\u001e~T{^Ffܪ}}vKe\\}jڭê^-\u0006\u0005\u0006Y ![\bA}Z2CE̕y2_\u0016h׵K\rv^]ΉqX\u0014B\u000fX+\u001c\"`;a\u001e㙗bG~aM:Æ$&\b\u001b{W\f\u0013ÅS\u0010\u0019=5\u001d\u0013\"^P E\u0003rv\u000bD\u00192\u001aJ\tQʚq6\u001fi;rH\u0012\u0013D9Nǰ\u0006q&\u0019<!yX~(ȃ#D\u0017NX\u0005U*Rej\fCWj*Qj|S\u001385V\u0015buP\u0015\u0018JP.sB\u0000\u001ae=\u0007r\u001e.l5;})Dav\u0013\u0017A\u0015T4Nǰ\u001e\u0017_mmeMv\u0013P\u000eCP\bcɊX%u#X\b F'p\u000fc\"\u000f\u000b*\u0013\\\u001e'obALTO\u001baf6t\u0001\u001bu$X%l<+̍FsyΌ\u001a\u0016҃.+jBŝ2u5g\\#Gy4?O\u0018\u001e\u000f0<g 6z\tmEf+(p7Y9.bu7TsL\u0016ޒ]>\u0001\u0015,\u0013a`)'\u000ep56\u0006 nnl45R$\u001eY\"\u0011\u001eUe\u000ej!?\\9\u001dd+*%O,'')˹GҐ{%F%\r}H=\u001fHR%\r'=/\u0007\u0004Ⱥ\r\u001d\n7GQ\u000f+^#^~{?$<Q\u000fp+l\"\nR8f*=AC=Su젍#8\u0004Sl& \u000fHs8D/klZo\u0005zs+hMzgp+Ёz\u00072M\u0003:\u000e\u0007hIvPn\tD[F߸\rmNAjZ\u0004\u000baL\u0019ɠݫ\u001f\u0018H\u0012\u0017\bL\u001ej\b\u001d\u000e~t\tԿ4'\u0015.A|}O>!N:Pbov00\u001b.'C:)'Ҩ(h*^Q\u0018T6\u0018T\u0004'\"\u0012\u0010V\u00126\u0012\u0012\bG\tU^Q䦇\u0019\u0019OPHp\u0011j\tK\b+\t\u001b\t[\tM*-^\u0016I^rR\fe\u0007]ZhaAP@!\u0014\u000e1Yԋ6\u0017H^=[R2!uXܠL_xz}>VJ-MH\u001fj5\u000e\u0019''ohU}lqN'wYc\u0006eO\rδ1-\u001bbJ!O8Kl\u0001O)u^\u0016\u001dAdt\u001bI#\u0011\b\b\b\b\t\to\u0011v\u0010\u000e\u0013BH܏q\u0000ULO1J/1vD.4\u001c\u0014VL\u0018\u0014\rtk\u0018&Qؙt\u001b\t9Նa5˞h/{|妰j\u0011ZhϚѯ_Ɣ:~9yDtƬ+jj\u001b> n9cS'4ȋhQ=0\u0010B{X\u0019eLϭ+\u00039NѦw/L\njkݾ%\u0019eJHMK6q0a{+YU\u0003#\u0010TRmϕ\u001eO&\u0013\u001c^(\n8t\u001f|0\u0006zj篘=cmi%wKZKa%\u001bAR\u0001\u001blq}4;3\u001a\u0011\bX(\u0005>\u000f_S|%t`]A\u0006\\F^/RnO_]>^Z-:\u0005w#X,.kcCa10K\u001fw\u0015)i!Ch\u001aNK:a=ޡ>Ku=;[V\u001f2_nmde\u001c\u0019q2c{|8-3c֤qC/[46lZ\u0005\u0017Z!-*\u0001J<O\bv@  \u0016\u0002pY*\u001e@ K+\u0001P\u0010\u0012HΙqܖ'\u0003/s?2)S\n{}d6i}-aKI}\u0007\u0002P황v\u0005\u0016\u001a~(@PR\rjT\u0003\u001a(@\u0006J5PR\rjT\u0003\u001aqxTveZŐ\u0006r0\u000e,\u0016%եBB Z8g\u0018\u001es\u000bG;!\bXkݹYz5`}1eՈjFnob2.\u000f.\u0018ɚfEƠQ\u001f\u000f߸\u001f\u0001z`ϳ/pl^\u0014>u<u_\u0013DA\u0016uge-\u001f;fM΂YP;\u000bjgA,\u0005v\u0016΂YP;\u000bjgA,G,-9$<ݢ%\u0019?f`eg`4O.QI1iNMVr\u0002^\r4[\u001dWӹtB\u0017|z*\u001dޖ\u00163r4\u0018,{\tw*I76Y+#\\۵`!%++jjŜ3:jU\fd礸<!y^\\h$Da}Y\u0018Ht\u0019VWb1ˇ.\u000bjx\u001fgq/`\u001f#\\{\r]\u0011\u0017w3bs\u001e셎|\u000b\u0010\u0014y\u001f\u0005Q(Gv\u0013E\\F|\u0014</#!W\bұɓU<Y57i7C.i\u001e`R̻RJ{T?@j\u0013f\u000b\u0011h]n[ڞ,-_U.w4J\u0016 o\u0013b^?)k%~jm7ҩک\\fN6)`'XU\u000f9\nS\u0001\nT@\u0002:\u0015ЩN\u0005t*S\u0001\nT@\u0002:\u0015N\u0005t*\u0017\u0014\u001a\"\u000eE5O}\u001fWwݹ֙r|}u쥉S+v*oGhF\r,\b\u001f1퓱42\u0015t4>]99#\u0010O#n\">x\u0011E7\u0011o\"B+r\f}\u000f\"*\u001a,\u0010켈Y 2=!zfAl.]ۭ*N:\rsC꣥|\u00194\n\u0003\u0012eF\u000f23x?{=\bL(1˹ְv.!\u001aW\u000e \tH\ra\r\b\u0001u\u0007\u0010#\f\u0011#}D\u0004\u0018\u0010e\u000f\b\u0003TLDu;!U-|fys\\Y\u0011\u0012+ݻj>\u001cjW\u00146n6\u0007֍.F\u0006\u00057ܨγ\u000eL\u0006\u001dAN$=dVK@\u0001pU2*_ݸNLŦ\u0013[K`?NG\\cV:\u001b\u0000uCr鶑ia\u0004D\u00036E\u0010\u0006+? W^ W\u0007:A\u000eru\\\u001d W\u0007C\u000eruQR\u0018[Md!c\u000eO&Sb2rՑh^\u0000YIUQ*mb56h#~p\u000f_07iDO//]\u000e\tRn(\u001c\u0013\u000bw/6ҳRvo>\ttT9^?U\\XL+`2\\\\}Imnٓ'\u0012z:TIL\u001ex'\u00049?msU{=֭G\u001f\bnxq\u001czWp>N\u001cqz⪫\u001eiw{\u001f\u0013\u000fz|1y&ٌ\u001e~o3?o'^*/8IIޠ\tęt>J}$I'y&O\fԐQe ``d.C'\u0016s!\u0011\b<`y>O\u000e#$\r3\u001c\tb\u001ex64^Ih^taEb\u0005}\u0001](Kbt\u001anm\u0013\bO\u0019I/.w?4\u0019\u00105\u000bsY/\u0012gg\tu^itюV\u0010\u001aNN8kjf'\u0015OVT\f3j\u001ci,\u000e_,n.).8\u001b|\u0002\u0007z!T\u0010~E<\\dG\u0011\u001d#ˈK\u0011G\u0011|D8\u001f\u0011G\u0011|D8\u001f\u0011G\u0011ԋ9}L%uyiT&\u001c3+܋[T\u001cu^ڝNj\u0017R,5\u0019]y-\u0014\u0007nؽn{\u0016\u0005ycB<\u0005\u000bq\r\u0012\u001f5[\u001b\u0011\u0002ށcg9OڄOڞ̦#\u0013l^235eOVng'3XsH\u0007s\u000e!$M$|\u0013y*izD\u0005MDMDMDMDMDMۤ{y\u0011rEXv#5\fdY߱3%y\u0002\u001eo\u0002.NǆúnOXgKڹ\u0015-nb\"\u0002r!\u001d'<]NoեݝH\u001cZ\u001b\u001b\u000571K3\u0013Qd0\u00155V^ImhK$So\\\fk($j\u0017\u0017\u0006d\u0007#\u001e\u0001;g{Ǐ\u0019m-ȩ\u001cO\u0018Y7F\u0015\t\u0007W)t7{q#\u0005\u0004+\fgʑ\u001dk;b\u001f=F\u0005sƾ`>9_v%AaNyDS'pN&@\\\nV\u001cQU\u001a\u000bᨪ6/\u0001A*m]\u00056?R#o\nb\u0019̤\f\u0006I;C=\\ziM}Ͻ_~g^o\u0005\u0007PGiaKrZ jy\u0014|@[D2\u001e̍\reDd8Gl>\u00165K3M6cd\nƄ11'\u0002\u0013P\u00109_nojo}\u001b{aGv`o^Tor\u0012kJL@-%ԹU\u0001\u000eІf\u0011zWu\u000fyj\u0007\u0016(_ݳݳtXY^ؚ\nG_d\u0018w+/{\u001b\u0012\">޴F0{o\u0019\u001a^|Us|\"]4A*R\u0007X=fVy'tki>@zF?-rf}\u001dk :魑21\u001bm\u0016,\u0005e\u0012T*P\u00038\u0003\u0018MKC0#J'?\u001a\u000e\u001aI~Vx\u001f ~'sii\r>/0M)d\f|r\u0004eR}h)\\<Cыm\\\u0005hRo\u001cg\u001b\u0019$\u000eҵ\u001d\u001c\u001d\u0007eۺ\"sHR5E2?G\u0019y~q\u0005cr+Tv?I/$z\u0003\u0007odxE}\u0006=2\u0015v׫>c2AAZ\u0019Ode;#v/1G&\u0019-nrv)_\u0006G}m-\u0001jt\u000b쒙\u0006ӌOX/59c\u000e|wT\u00169\u001fS~-Z݃x\u001e\\M\u0006\u001aTRgȮo-\u0012n7\u00188\fNn\u0011\bJ\u001c\u001d\u0005\u0001gn\u00164/BuBMƜ\u0004\u00024\u000bTV!&tr>Ǟ\"\u0010'|M$*\u0002t==\u0010x\u001bbN2\"kF|F\u0017Gї\u0019?l\t`\nx\u000f2V!\u001ds_%\u0012`_߯E\u000b\u0016c4N5Wh\u000b \\k{<vw:nj}\f\u0005e}빧{\u001cvF\u000bV\b'5>z\u000b}\u000fc\u000514n.G\u0015u\u000b~\\P\u0006|XQ\u0004.\u0002Qh\u001a\u0015g&Fi\u0017V(\u0002f0:}a\u000eG\u00070.24Dr;(`\u0003rW>CG<{?2̉m2\u001d՛^NK;t>5Buk)\t;d\u001e\u001d@\u001f\f\u001d\u000be\u0006{W$:D\u0016ӵ%1eU[\u001d!^hyzCp7]\u001d1\u001cby@H5G\u00069\tK.u\u00047r\u000e\u001bԐDmͻԇC\u0013J>J\u0000\u001f\u0004Zw[{AkW6ϒK7>r\u001c/NVm\u0005+\tg0&A\u001cc2/\u001bYy)\u001bZ\u0017aCUS6uF⒏?\u001fUc.y\u001f!c`P߷z2ӛdt&=(%9woE&jt9ndRk\u0011-,XԸ=\u0013=\u0001un_\f:K\u0007NX\u0017ͣ\\G\u0004\u0004ۛ.xj:{JƟ$V{#\u0003;\u001dAm\t`\u0007iAj\u0000kݙKݙOs\u001e#)e*+\u0014^s\u000bcR\u0018\\/wb\u001a\u0005k\u000fG-N/eb4ǩ8Jzi\\^o\u001fl1g=KJ+ȕo\u0010\u0013خX.9ro\"6^\u001eD˽ն\u000f3N\u001d8A/3=9\u00191z,=~R]\u0011\u001d;:n\\\u000f=8淂F0\u001f}\u0004^\u0004ݞo;'ݙ;ݞe\u000e\u001d}9cţp{\u0017o\u0006Yo7Lh\u001c|C|\u0007QB\tIa+\u00026\u0003͗nD\u00158\u001f\u000eX\u001dZ\f&>\nU\u0004\u0013=.P{\u0002ڟ*CS)\u000f0\"T\u001b=@ld_\u0015*\bfO\u0019m#6+\u001fzDAV\\ݳl'wP?]~%~\t^'L5tJ1X\u001d*cCz~%7m\u0016\r0\rl\u0007\u000egǅY|5䰍o\u0000\u001f\u0006\u001fm\u0016<ƸoǤ<|VS\u0007lsCC\u001bj6C#\u000b8=\fIr\fgT»mk[<%$B\u0006{\u000fLn\tr\u0012i\u0019o\"&50[\u00143^cq/u\u0013M{5w\b\u0003ܛPeÿ\u001d}\t;oQ4z?vA=C1e/sމ%>vZ\\\u0014pgMٹi}(v4[`KG4GƳR|[YF,}AotEΞ#K\u001fo hԍW/շrivg@\u0016;\u001ch\u00033y?.M^4z\u0013-\u001c%JXOT\u000e-a>lBY)Q}>Fo~'l9uuxTߛ\u000769\\\u001b$?}.=Otg\u0016FyK\u001fYȯe!󌽕2Ȼ\u0016vP7G!6z{b\u001a\bd\u0001:KF#Fd'o%\u001db\n$\u000f\u0007|8xNJ\u0014\"]?\u0015\u001e0T\u001f;)M.#\\L/4NV\u0010\u000b\u0017ij5Е4ߛ+e:\u001f[do*e]R\u0016laO`/j&@$OџoO[J?\u0006dCtw>\u0018-]'!k\u001a0֫Qbz].\u001d;\u0018\u0004R079\u0002/j\n\u001cbt\u001fpun}\bz\u001aELVY\u0010.vj[`=v/F)\u0006|?\"ÂwEjy'Z\u00149]<E2\u001b_n|0[̘>{\u0015\u0019;3aWGA\u001cBPy\u0004Y\",D\u0016 J\u0015(;wwʽw3swM\u0018`6h,T\u001b[1-ZmӠmMCEQ\nbi\n9w\u001bhky|wNmllӨ}1/ˀ{!\u001c$\u001cW'.Q\u000ebN90\u001e\u0010{f`~~Z}Zp#TdB\u0018/ʾb5/ᫀNZ\u001e\rU\u0019\u001c\u000bA\u001e6ܥr1\u001aTf2\u0019⠋`r\u0016(,Ş\u000e\u0007\u0016{_ѧ.c=@\f/aG\u0014/iQ:\u0002)-FwQh\"\u0000\u0007:\u001eYԺ-l\u0018 <\u000e.CɐC\u0003=\u0018\u000f\u0010w\u0000o\t\u0007VQee%Jg\u001c\u001b5w6|scL\u001cĶ7T\u000fx#P{/S40]\u0019m9(/o,`?*p޿U/eS4i1Sͳ3ސ\u0015Qaש{X\u000eQ\u001a6=`\u001cL~Fǂt,~\u0007om}B֛\rouZjC;\u001c16ٚ:(]_b?FU4X\rr%嗩XƸZũɒY\u001c|>\u0013\u001f'0GnbZL&n\"~B\u0017Ӵn2Nj0M\u0019S7w8\u0005g䘩#\u001f\n\t|GMZTN?\u0017\u0015jdB\u0011ϳTۆ8x\u001d\u000eISJ䭡Wzl=ZMX2\u001dXO~\u00073.SI\u0013o1\u0007R]27\u00101a\u000bY]>js+:ʱ\u00132C>\u0003\u0007?^\\q28cd*M9f+^\u0004ujHfXߐfH\u001etnbPc\u0003x\u0019Uk\u0010(ΠǈEgޒs߬*TS\u0011U\u0001\u0016Uc[\u0019\u0019W\u0006\r##wvvn\fsُN*gޏ\\20\u001eߍUJ{*m9~t\u001a[HBl\r_f8\nydW\u0012RWņ٩\u0006|\u000b|\u0001\u00144\u0016iC\u001fBP\u000b95װC*n80&}\u0001b\u000emg-\u001bHR\u000fSc蹇z\u0018G'\u0002\u0002ݦQ\u001ey)uۣi$^\u0017d\u0018t\tzJ=M#C6\u0013S4\u0012clo:Ҷt\u0011އ?%'X\u001c\u000b\u00189;\u0019\u0007jo%\u0006챕;d\u001c]r2TŞ췙_ħƤn< ky\u001auhI64FHSG.~Tc8%C\u0019ckن\u0019b-\u001f\rq\u0006E=Uo4\u001e!\u001e3~El\u001e=oz>=mN'\u0016k\u001eG\u0017\u0007PwX\u0007\"W(+:r72w S7䧌y\u0004=\u000fG\u001dbcRg.B>_f泴M|\u0011\u0019P+b2e4Oͽ:.s,u\u0017*YE'.\u001bk}o\u0019 #C#c)yl<n;{>[m\u0018\nwRX;Y|H9z;fH\u001d#\u0016ٍ}NS.X;,l9>K):نFGk^l\u001668G^itz/~\t7x>1Avp\u0006D봏&$YCs\nKc#\fw_\f4\b'?MݨM=^\u0015\u0019GpBbQ\u0017\u0019}ȘSUƮ\t^+Ҁ|E\u001a\u000fL`\tg\r˄SR\"ön\u0019.W&$YQ+#.h৚6e<j\"=3N\u000f%}Mc:Z4j6\u0017̪9N\u001b2ng6);N[\u000f顤/U\u00023gef[O\u0005wmbD\u000bٵ^я*%D{\u0004\u0015{U\u0003ۋB弼Dn673~\u0014=7g/'\u000b\rݠ\u001b1bckg\u000e/r\u00163~A\nN+4tN{޵C?\u0017u;k瘱\u0014r+v\u001172Yɸ2n1{\u0015l{]u# ~nsow\u000e7W\u0006\u0013UzjM L뢂SanWRU%pi\u001c߬\u0017NE%\u000b~yqa&+y9\nbsl\u0017uH\u000b(\u000e(B\u0000]N҂Op2[Uw<#M0r\u000b\u001a\u0006%?PVZƪ5nY\u001bm^|\u000er#/sZԗuV)Qκ\u0005'~N/өu!RW3rY/\u0013y~\u0011;2ru9\frG)Ww\u0017i\u001dC/K+\\V/%H tHDb,lEK/\u0018^8 Bʑd㒖v-\u0016!bqI;9P!J\nHF\u0012r{\u00072W}xs&O]\u0002J\u000ePQ<__sۥG'#H1*I\u001c[2!\u001bKR.C{%\u001bP㰚.\ticnVUXWTf\u0004տ({c\u001e*\u001dd\u0004a<{D>c(VJ/\u0003FRҫ\u001a<֘בGVUۡmYɯi^]8`}EU\u0003\\@BmZ+5N%MyV{\u0006@I*K6r&Dsz2)\u0003Ue2Pe><| \\\u0002Ng }X\u0004-\u0007>\u0003\u001cz%H!P\u0001v\u0017(ԋ*K!\b\f2\u0011G8\u0017Zs%\u0001\u0012\u0018lN\nP?$l\u0014]\u000b'4\u0016\u0001\u0007G\t4#F\u0010J\b\u001b\f\u0001\f~\f@\u001c\u00199\u000e$W\u0002D\\*З`@V\u000e8\u0013!s\u0015\u0016ADq\u0017\u001d#͸\u001f܎\u001ch<0PVFa?P\u000bUh\u0017 Q6Se\u0007\u0003\u0017à\r\u0010`\u0000\u0002D7\rendstream\rendobj\r13 0 obj\r<</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask/None/Type/ExtGState/ca 1.0/op false>>\rendobj\r12 0 obj\r[/ICCBased 35 0 R]\rendobj\r35 0 obj\r<</Filter/FlateDecode/Length 389757/N 4>>stream\r\nHuTK\u001btKKJI,t(݋\b\u00024\u0002K%ҹH4J#Ғ\u0012(H\n\bwqyy~3̙g<3\u0000\u0001\bY\u00059El\n\u0000@ ]!O-@\u0004\u0000\u0001\u0000\u0001\\+BVKK\r:\u0016\u000f\u001dO\u0001X~W\u0011Ca\u0018iHKL\u0012\u00000\u0007\u0012qY\u0018\u0005\t`5\u0000\u0014c\u0018\u000f\u0016\u0004k\u0003\n\u0000X]\u0000x=\u0005\u0001\u001c\f\u00068\u0011\t\u0010X\u0000Ŀ׽\u0016>.\u001f\u0010f\u0001#aP\u0010\u0016\u0017\u001dn\t\tD^{y8\u0006\t\u0002\u000b\b\bdp\u000b\u0018H\u0015\tst\u0005:Y\u0001\u0011\u0018׬\u0006c\u0000xc\r\u0000I\u0002V?S!\u0002:_\u0018\u0018\u001b\u001d9\u0002[YbQP~+rA\nShHht^\f\r'\u00180߅kYXY9\u0014Yqqpl'W\u0011\u0015\u0004z\u0017EE$%\u001d\u001fD>,^|t*K)%/`\u0014\\ҫ\u001a:&D\u000b\u001d[7dplD\u0006a5|mb4,yy{e\u00155\r3\u001b\u0011\u001c⚅,t+whl\u001e\u0019\u001d\u001b\u001fA\r\u0007\f\u0006\u0007\r\t\fm\u000bk\nx\u0015Y\u0016U\u0014\u0013\u001e\u0018\u0017\u0016H&\u0019%Ȥ\nqO'Mz3KT@v[NUnn^\\o]ab\u0010\u001aTrtlmE]e~U+jא\u001aZ:z\u0006aqi5};CS[\\_ۆw\u0003\u000eCa\u0011Q1;>L$Lz}4:%8M7\u0003l̎Χ/}XT^]X>\\Ym[n!ycskkƶʷ;v{p\u0017Is0Xݯ3s󝋒&$WWW*)\u000f!$$%!e$cHNOAKIMEq\u001a\u0001\u0006\f\b\u0014\u0015ƕ;KLw@\u001fYX;ؚ8^+Ds\u0015pfKO\u0014TCPp\bJ\u0014%\u0012\u000f\bD=++O\u0006%\u001b$\u0017*\u001f\u00108I\u001aZ\\Z^UK_wL\"dx]}\u0017\u0000\u0014\u0007\u0005>9=;s\u0005_G8/̹N!Gz[<=2\u0013|B}PQzlH0W\bc(Een|Pds\u0014::5&89yFT\"od䳔i/ZK^&g\u0004d:f\u0019gQ\u001f\u0015l\u0014\u0014\r\u0015kJХe\u0015J*+篍kj5U\u001b\u001a\u0015\u0014\u0015[ZU\u001eh0|em\u00176]B@`PpH\u000f\u0013\u001f?QM1Msψ*iϛ.Z\f[JYZ)X-]R޸Ѻپw?@?\u000f\u000f5 ǖ'vNg\u000e\u000b\nW3g\u0010\bLC\u0002#u!MMMEv\u0013Ams˔FVNA\u0014̝GLwA̬,llؿsݛ\u001cnͽ\u0017+\u0010!B²\"<b4\u0012$݇kRғedk\u0015*\u0015JY*/TS\u001e'<SV҈ԌЊЎԉЍЋЏ042\u001a?M4I~f\u0017s-,󡅰\"+uMm]}CcS\u0005\u0002Q\\RZsv\u0015\u001d\u0013\u000fG\u0006\u0007\u001a\u0007i\u0007H3GFFaGDƬč&$V'\u0015'g$F\u0005LG˰4͂djik\u0016h\u0015\u0014\u0017Cf%VNeA\u0015qYU\u0015ڪG^/\u001c\u0011Ճ\u001a\u001b\u001c[Z{Vڱ:;`=c}nK\f\u000e\u0006\rFv(ރ> 'R&k?3?4+:6o\u001cT\\ұڿ6VʝoF?L\u001bT;:>::>:;eqvx^sawݥʕ\u0016'\u0016\b_\u0000EFO\\DKL\u0016t\u0003AnFF)F|\u001eԭ6\\`@z?\u0006m+F;LwiA\u0000hy\u0015͖\u0001)Mgw~\u001f_\r@\u0017ZH_XA\u0004,\"F)%/*9a\u0014Z:Q,\\B^_AU񡒀2\n*'[j\u000b\u001ao5[uR1uh`fm$\u000f\u00111xJgBdrltlyyEe$\u0013feg-g#`dGbwj0T\u000eOC\u00049;\u0018 ܨݿxz6zx8\u001aIP\u0001=A!.a\u000fA\u0011x\u0011ۑ\u0000\u0003\bϊ}bG-\u0012ޒēx`G/\u0018\u0001Ԝq_O?0\"\u0015\b۬խЮ˯ǰı²µŶȷ͸ӹۺ\u0004\u0011 0@RfzƏǦȾ\f*GcЀџҿ\u0003'Lsٛ\u001aFs\u0002M6+1M\u0004Z:{\u0000\u0000\u0000T?~ò~i~L}~cbA~Da\u0005\u001fd\u001c~ty\u000f~W~O\u0014>~\\/~|~`\u000fC\u0000x\u001d}%\bH}\u001c1X}%z}K\u001e}\r{N}׋<_~7A~-\u001c\u0004ψ\u0011|\u0017|\u0017ǲ|+\u0014E|[s|z\u000e}\f^}wO@}-\u001a~ċ\t{Gu{Dz\u001b{]Ĭ{f\u0010{Zx|[]|ϕM?}R\u0019<}Ǝz]YzHħz|z={LNw{\\|=>|v\u0018\u0017|ېI8z/r\rz\u001b;bz'sMzd6zɬqv{D\u0010[{0>\f|;\u000f\u0017\u001c|\u0007\u001dyyaIy?yazYv\u0006zݮ[\u0006{^=c{Ф\u0016I{R\u0011*y߄yfUy`Vy\u0013yuKz\u0007Zi{\f<{z%\u0015zȎ\u0013~+~\u0000}͇\u0005}W0}3\u001a}HtЄ}Zk}=~\u0018z\u0001ɇ\b\u0000}!~\u0003Єd*s}Y\u000f\u0007<9\u0016w\u0003pSwu\u0010\u0019\u0014\u0013uVrU\u0017W؈|;,뇔\u0015{RsѲ;\u000e:8q)PCV\u001b\u001c:4.\u00148Ȅ\u00182\u0006񡂡?U\u0012p\u000bV\u0002u9S\f\u0013\u0015c\fbփ\u001d\u0003R\u0005.ՁNn\tU\u001f388\u0012\u001fA/ͬδz6߆өn1T\\e7݀tX\u0011T\u0003)$̯̕6;eC\u0003ʷˆ\timw3Sƀ\bV7M\n\\\u0010lGNػځNā\u0013a5t\u0014N\u0012zlߴS<H6\u0010\u0010*<a|kz|CV|\u0010Ǎ\u001a|\u0011|Ik|Ru}26'~\u0001\u00112F-\u0005B*ojQ^@5zI`\u0010\u0004ٳ\u0000$ĝ\"cߘ&Uij|PJˇv4vy\u0005\u000eVG\b.2{\u001e\u0013\u0017萾hS掼O[\u00133\u001d\u000e\u0014(J\u0015ьx&$Ԟs҉h\n~2gK>-N}o2ن\u001c\rN%է\u0000>w֣A}⇤\\fXMݘ2,\fKԐ3g\u0005°[}\n0\be6M\f_1\u000b?\f\u001e1ӣǾ\u0003I\u0016^\u0014I|B̯\u0004dܪwL\u0005e1$:\u000b\u0004rW]\r1S{z|diL\rg0\\\u000bU{[G{!{\tޔ`{&y\u0015E{xbie{Jr|/c5}~\n~\u001f:f#\u0001MKx+Ca|uI~.yW\tώ\bәߎ\u001c%¡唘[w!^T`^H*-\t5GȨ瘎=Π4rv\u0003_ҍRGf,ދ̋\b\u001f|,ƕ{\u000bҘtٕ^1Fő,;'\b<!_Yl~JJt\u0001S#]'FA4+;\u0007ۊLPf&ɔޝ\b\u000eըs@夏]\u00130\u0013E+:\u0012\u0014ևSS\t\u0002\u0006𧠨\u0007jVPp,\u0010<\u0014X\u0015Q)XV\u0005l(Js&\u0002J\u0002!\u0004K{@BE.\u000be\u0017WqQ䆓\u0003~37FHI^\\ӡ\u0018+j&Yb\u0016dML\u001e\u0018{#)FA;q\u0019T0_\r^\u00079IݤxֺƢYFh9ՅhX\u0016;Jln+jġ(m,ּJ(VaV\u0007/\u0016\u0017aؑ@Q~.8_]7]\u001dg|F)\u0002\f-/MH|P\u00138%\u0005oF\u0013xC<Rl\u000bA^\u001aQl\u001czrJAU\u0004U\u001b\u001f\u001ad*\u001dN$i܏\r#v\rb7\u0011F*4ނ\n\r\u000f\u0006pvix֖IoJ۱#\nW\u0016hԉl\"kx\u000bwVj\u0016GDz*ߜxW:ƩdP$\u0014\u0013\u0016j4WM[,]ʫ$W\u0010$I&N}7¨\rs1@9TɎ.Ez\u001fNDf\u001b\u0014*uwr \t\u000b*#\u0013\u0013,h؅\"8=N\r\u0019%=(p\u0002Qu9sLӓ\u0013(&wھ?ER\u0017\fAHi.R~\tԄ6:*tД3*۱x#m?r\u001b~3\u00192+wp6y\u0001\u0007X\u001eaTO#\nU¼<_)\u001eI(}W2SX\u0013 \u0011U\u0014\u0001w\rMf_T)\u0007?kYYF\u0014K8\u000eu;J$þ*1T\u0002\u0000>\u0013\u0004,#h%T,Qۥ{[s:9󅼓&^!Փa@!\"\u000by\u001f\u0000\n\u0011.Jl6mHju,b\u0011U6+s\u000bhܸd\u0016\u0016\u0016-ʥ}\u0006wi\u0000-\u0003\u0001su\u0010n\u0012=0Ľi-_*)U_ˈ\u001db$\u0011\u001cna+;ϧT\u001d;\u0003ppA7\u0013\u001a\u001b\u0016\u0005\u0019C\u00074\u001f.\u000f*Iߥa8M\u0012m\u0013.ACi7\u001f\\j|fi\b\u0006ԫ)]ޭj\u0007ʄU]3\u0010(í\u0016\fw\u0003hJ\u0018ch-\u00114x7h\u0016׿*\u001eP\u001c0H됎\u0019L랇ڡuÂ\u0004\u001f\u0002\u001a,{Bz}8v\u0014\u0015gg\u001cҲd[!XTZ\u001bZ.vlA\u0018\bg\u0001\n{;\u0011S\u001cm`vؿ`~?ga.\n3Ì{L^W\u0001\u0006\u0001Ye4]L<pq޴\u001ak!G\u001e]\u000bl\u0007\u0000v\u0001\b:D\u0019eH\u001a\u001fXqEK4kHoS|XֽO7\u0014o**+\u0000\u00102h`?k6ݤg,M{ST3`b\u00195\u0010XE#*\u0012\u0004і}\u001cz#C//\u000b7}V;9\u0013T\u0015\u0016\u001c)?ވ2[\u0001ُ]n$~\u001d\u0005\u0017\u0003fЌ,dp,\u0016BA\u001fdrH]`\u0019\u0011u\u0016\u0004\u0003PV\u0010kaEVvYNU5/yfD.ݡ\\ 1\u001fQa#KE:|N[k\u001f=&[],\u00061$ξB\u00070Y\u0019(ߊq\u001d\u0004$]\u0013!{Ik5\u001f\u0016U3j=Or)<V\rA\u001c8H\u0019:YjD!L_|OlxE{EY[9#Ev\u0003x2E\u0004as=[R\u0011\u0007Qi*i66`ώ,+#,i\u00061A2\u0000@\u0005\u0001ƪW\u0017\u0017mHXJNP+)\u0011̧+\u0003\u0019\u000e\u0012=l\u0004$z\u0010Ukb]i[:<\u0007旰A\u0010\u0001r)<\u0000\u0003+e.\n\u0019\u0017%ӂBsW\u0011ď[~}F.+\u0007}Wt= \nK\u0011e&\u0018,^\u0018-va(0\u0007\u0015\u000b\f\u0005\u000et\u0016\u0012tzSw0D6jtl.\\lVդ)\u0016-\u001cg\t[ѭ'\u0002x||DDߵvwi8ư=݋bY\nTC7jKIX7\u0000о\u0000s{W|}&饷MR\u001aQrs%5\u001cԯ1G\u001e*=V\u0001DM\u0000鶢l`JYKe\\\u001d+kl=ּ\u0000sr͌\n\u0014_L\u0002\u0000\\E܋ʮܤH)B\"\u0016nĕ)Jۙ3gYi&M{&MʹI\u0016B+!%,O=Y>7o\u001fk!wI~\u0000I\u0002ra^\u001c=C\u0002#\u0006Z\u001fh\u001b`Wu}p)\"z7ff&3\u0001\u0005$\u0002\u001dF\u0016J8Ҷ5\u0004m\n\u001cuR_,^VS&aR~Pf\u0007LL_Dw*`\\\u0015-9]q\u0011\u000b\u001c\f\u0017TI6)>u6\tD`e͢/x\u001fqY%\u000f9ʜ;åO\u001c\u001dd\\˾P&\u0015eRz;\u0002].R<\u0002oΡ]P\u0006{?:\fr̨\\ʻb\tҤ\u00113|m s؟W9oZt]Rn\u001cÅ\\cW#+n\u0005I\u0001&g\u0005\u0016yA\u000fjsN06\u0006HiD'@J+\u001da5V~\u001fcRI̫\u0002vwtUc[3+?F|l(iU\b\u0011^+O?Rs\u00001Hqil$Wþh=(RE\n\u00111Bvџ\u000en\u0003\u0005F/\rBsGMY9\b>ܖ3ȗqI\u0016\rڣ5V\u0015\u0014_\u00041ȣβiJiX0W\u0012V\u0013\u0015H[8g\u0000_/\nn3\f`\t38A.|f|ј\u000f\u00150I6\u0007bv\u001a%& ;Y㿜҄#\u0000dD.).p\u0005'\u00193J12K\u0012[Du\u0005ɥ$s8I<RimJ8}f \u001bDJ\u0016ƀ຃ws!ʫr\u0012\u001fRX\u001c-\\y^*̏Ld'雲9?)\r\u000b\"q^5/\u001b<\u0007\u00044i\n\u0018Q<\n;/ԱJB\"\u00147\u000ft͚,mXdھ^;촞&s`Y\"\u0015Y\u001d{\u001a>Ɗ.z^48e!R6}vc\u001aMioz\u0016\u0006o0\u001b'=~i,3:?-?o\u0015S,9w\u0006#ROa\u001e;\t\u000e?\u001dpB\n֞I\u0015O\u000bݟ\u0004e#}ԯN$\\\u001dl?\u001c],\u000b\u0011y,\u0001>&Р\u0010q]\u0018\u0017yh0A\u0007q\u001fK\u0012)ĝB\u000fFҍcH:-h-ǟc\u001af)K9T127]\u0018qEjL<>h\u0015;|U\n\u0016\u0001\u001f\u0005dpG\nƫ`&!\u00078a\u001el`83>\u0016.qɂn\u0016A9\n;\f`HByg\u000bKB*k㰗2f\u000e\u0017F=#OM\u001d eT?\nmTm\u0016\u001c_\u0017OBۊV\u001f\u0000<ɆF('n3\u0002u\bG~Ȯ#7Њ9\u001f[١`Ns.P..\u000f콤\f\u0019\u0005'K\u001fnp\u0014F\u001c\\?\rB>-`\u0012\u0003N\u0004WO\u0004OWB\u000elfxW^<x==Z/~4/.*gPʲ<\u0005*V-}&ٟw\u0004zWq=g?\u0010:;[\u001f-(\u0007Z6*<\u001bȈ\u0017`p\u0005?\u0017\u00192eQyў>b-_\u001c\u001dx&*\u0017/(\u0011j\u0002_\u0007=߆󑊢zF`\u0019LdE:\u0012SN\u001f\u0016ʔ@S 03|TOKokto\u0012}bF\b\u0013z$\u00114\u0011\u0004-,.\u0018m'j*J\u0006|)J\u001e6\bBP\f\u0006^3ewܫpX.*,07xPڳ:2X\u001eOT21|\"7=<J}|wl\\}\u0016vGic\u0019QS\u0017]<Cjȹ\u0015*\t@8-f\u0013݂={ñ(\r]\bxѨ\u0019n?ϑ]qOˏExyU\u0006\u0018\u0019c0tM]u3\u0014\u000b\u0019j o)(Co~2sЃ\blx\u0007֙\u001d\u001f\r{L\u00037\u0015z<\"\b!s[\u0001Ha\u0019*{1l\u00161,V&I*[v$#1/\u00005Z\u0010p(3\u0014]8\u0004i2\u0001|(2\u001d| zD\u00005 Ns֬\u0016\u0013\u0011viV`D0Û]\u0002\u0017R\u0016)L!\u0019'n\" <v~\u0010x)~if\nwnKܑQVB\"\u001fԽ\u0006p *+ت\u0016ED* \u0017(\u0016\u0005\u0019o\t\u0010B'{pwH؆ʴ*JѪmA-nWj\u0015GE\u0003ޯy~~?rI^\u001cWO\u001d@l)ƶWgiX\u001c\"C#k\u0014nA\f˻r)b!UڲIb=>0ߴy}ĸB)\u001bH\u000f[\u0011F\u0002s\u0006\f\u0014V+\u0019̯+Y(I(x&9JAI'tXmy\u001bG=X[8TK)2\u001d<\u001cTSR\u0019vx\u000flȓGO|g/{>\u000e\u0001\u001c4/gRFȶ&A52\fuЯ*B<i\u0016\u00000gr+O\u0017A,0-bug[\u0019\\~-\u00194:I>幃\u0016AuFǞѧuD)B,\u001e*\u0014?n`\u001e\t'qQIzK֗\b4{\u001cB_g68#ʉ2.A$\u001669!̒\u0019ub1&D3Qx\"\u000b>ɏn\u0011νxVG&TۨÓ)sxd-5KxߣD&1±\u001d\u001ejd\u001a\u0003GjJ\u0015|J\u0003\u001b{Z\u000b޲f6/vTp̄ub\u001e\rPmBU#gBg˷)\u0015-*\u0012\u0016E\n\u0002ar\u001b>>Ƶrn[ɭF\u0000-IByѸP=ĶKUC\rw\u0003\u0007G\u000bD}\u000f\"vN.p]\b]Q8u\u0019Y{#qC\u0006v}sa\u001fx_\u0015oyiNr\u0003\u0015(\rd8a\u0013w2CQ}V8UWO\u0013\\g\u0017\u000b\\\u0011\u0001yk@\u0015\u0018d\u0005cZt9$\u0006u\np\u0002-1\u001dz(=f)\n\u001av\u001e\u0019ě\u00169\u00042\u001d w\u001a\tu煼\u000fת#\u0001\u0010{P6+\u000fDq3HIi\u001a%B\u001fC\u001cb!kc\b5&U\t\u0004):X$܎\u0019[\u0002b2\u001d*@PkcӘdoT\u001aB_L1Uwi\"\u001f\u000e\u0005)\u0013=2#pI\u00179,RO>T@>\b;bn\u0004\u001aD\u001dPuC\u0005\u0003\u001cfk\u0005\b^^\u0013\u0003\u0017\\\u0012G~\r o\u0019LRcHqܮ=-8^5Ońy*9:-\\\u0017g8:T<\u0013?*\u0002C;[y\u001bX\u0017+\u0014I;lRL߭$\b\u001fDv\bYTQ6DyVmfy%\u0006/sIsmXP1Lռȭvo\u0016w)Q\u0005Bb_\u0003\u0000L\u0002VwupeėO*\u0014\u0016|+](uHװ4WU\u000f\u0015.{ \u0007\u00044\u000e\\m.Qw\u001dR~MAiRz+%BKz?\u0005'{\u0000\u0000\u0001\u0013\u000bk҉\u001daa\u0001{\u000fH]\u0012sX}da~3\u0006_au\u0013\u0019Q\u0007z\t\u001eVM\u0013\\ĵv5I0LM)Ǆp\u00071:5\u001d,\b&4\f%!$\u0017\u001d}ocޤA]R^xT◬M&/B:Dw\u0005A\u001824?cd&g]5b4a?i\u0016ǐ  Ĉ\u0004.OA\r6v\u0013f\u0016v\u001esd(\u000e5yT\u0013\u0004H\u001b/P=(a;zUs\u000bbWxDa)Eʼ\u0013\t\u001f$\u0017s\u0004gPJ\u001freY3\u0000w`cFo0|U[j5k\u0005.5J&\u0007eTor\t\u0014È´}I\tlpjC\u00058c5J=g%Uo|L58\u0004E\"\nِ\u001d[A\u001ek]J͆VBM\"{Nr\u0001Q\u0003\u0005ih\u001b\u0000Ц@Y?6^߫ZWٯ]ذc؋hKSǈ\u0017:>O\rɲ.ݰ\u0012\u0004Q\u000e{5mm<ٷ\u0010?^v\"\u0011}ъw9O&vX7\u0016km[\t\u0005,7\b0n\u000fΒ\u001f7\u0016|\u0017eP\\I;\u000f<u^\u0010\u001b\u001f`u\u0015!$PB\nET9\u0003\u000fٲFWc\u000f\u0019m$=\"G\n}Ke6~֔G_MDԿ\u0011s` \u001fg]\u0001\u0017\u001cvp-9\\\u001aNd{::gvH_3fC;}Ɠ\f\u0003\u0000P\u0000N\u0002pH\u001edU9u;9\u001b$8\u0010w\u000b3r#\u001fA\u0018FiD1n\u001b\u0016\u001e-}\u000ft\u000fe\u0000\u0000\u0010DH!5$\u001e,IQ:ȖR13<\u00187\u0019\u0018\fj1[ЊT\u000emWwzUx|\u000fվ+ք{W>p:ʤJRqY^`ǯ<~j!mr.B+'OyY+fN*żt\rW$W\\2\u0000M_c[gjj%WuU{{,_pWn%}PI^W|\u0003n;c!p\u0015u\u0017cʨN!k#)ksd5n6Q{\u0010H10U\r\n\u001c\u001e-\"{⠇TZG R,ɇ\u001ajࣶ\u0001Zw8j\tICF:b\f[\t\u001e\u0017\\+?\noA\rn'a\n\n\u0003\u0016Oj\u00030\u0016`%\u0005|^/si_XǣLqiw]IέD\"J\u001b!y!Զn0R\u0015\tzW\u0011CcchūK_R\r[*)!\rOSou\u0013Oշ܌\u0004WzeWC\u0005aϝ\u000eL/QBo_k/cg&\u0019MV?֫5z !g\u0007\u0014\"?w\u0005P͚IQ\"\u0005PA\u0001d\u0017tE)q4jGsn{\"\u000b}eUMrkzvi89C}\u001dXLB1\u0016W\".ꕝ^M\ft?WKLwDP]tU\u001e\u0014揊1rJոK\u001bVGM;phշm v>\u001a-w\u0001gFN\u0019\f\u0001cI\u0010P#\u0019qWI\u000b\u0017;\u0016NٶA)\b\u0010H~\u0002\u00067i \u000fth\u0004l~\u0004~ǳY\rCx2>*c\u0019&mb{9f\u00051\u000fX*L\u0005\t#>\u001c\u000e\n\r\b\u0007V\u000e@g\u0017蒼]7n249=MK%\r;\u0007,F\\j\u000b1k\u0011l\u0014Zi\u000e؊\u0012ΐ.|Q9а$_.!\u001c\u0017\u000e;\u0001̿lE,ɥDi\u0006\u0015}D\u001e3^a\u001c`Y\u00145\u001dg{J=\u000emɳy3C\u0005M\u0004'jM\u001f-iЦm\u000b\u0019n5?\t\u0019SJE\u0006+U~ \u0004;q.tXd~\u0010~p*QeS%.Ћ\u001a\u0004\"ưB\u0005sZ6-\u00166[\\d;^z4`;64藸\u0015ͱw\u001d;\u0010|+&AfLU3\u0005XTm)l\u0005F'l\rV\u0003ɺgcGObbɜ9;v\u000b\\C\u000fL,\u000b>B?KGC\u0011\u0011e\"z\f-@E\u0017\u000eH</s=/\u0003ᑍY{P\u0001w\\L1A\f|U{\u0010\u000f_\u0000\u0013\"҉w+Gm\r$#no\u0007x\u0002N\u0002+\u0006}M\u00199MbΥ_@Tܲ'1 ,q\u0014$;!헁h\u00061k\u0016b\u0014\u001dBo\n\\wJ\u001c\u0011uY/\u000e|ϕd<wΤc~\u0004\u0010ώ\u000e\u001dx¡#dg3~g \u001fxT2ȵ\u00116s3i75ƻZE\u0013\\1\u0003\\ɺ\u0004WA' ײ\u001d M\t}?\u0001;ʂ8|R0S#❣\u0000Cۿ\u0001Ub\u00050L\u00037ֽ\u0002\u0005`\u0015\u0001hcEk\u0014T\\\u0016m\u001e+\t6&\u001f=\u0002\u000f\u0007B9)\u0000곌\u0011\u001f\r\\@^\u000bjkaƚPh<=T6K^MK͋=݊$\u0006Q\u000e-U\u0014&>ILp<5\u0011'҉\u0010$>8#gL2m\t\u001ec\b\u00181\rc\u000b\u000fFw)P\u0001+rkC\rqp/u8#!*\u001cg\u001d°Pa`vu@oH`\"Ž\u0005:z\u001d_Q<,D>'Ӆ\u0006\bWP .`x\u0016W\u00013\u0016|!6\t\n5\u000f\u000bEl\u0001[\",0\te[Oz0\u0003~lU\u0017O\u001a+\u0004&xk\u0013P\u0014c|u$k.?\u000e{Qp\"\"\u0014kr6isV\u001aa=~@W\b_\n.<7\n\u00122#h?c~m'rE_xs6\u0014\u001aaG+\u001bK\u000b14\u0011\u0019L^kUp\u0003^^_\u0000\u0005mS^dШ'>\u0010}5\u000f$:τ!\u001eE\u0013\u0018[bJx&n t(\bm;ZsF5uq\u0000X.ՂBq\u0007K\u0015P\u0004 *\b\u0003l%{ٓ{'f';,\u001aTT,bh\u001dUq\u00192Z\u001d3;}\u001fT9vwRR;G\u001eD\n\fK*/@hUv\u0006$j!\u001c@\rvyבm,W|-͢\t^\r~D_􆭍\"ĉ\u000e\u0006#c禘*X/Ϝe>|XH;:)d9gƖ\u00134aB\u0002\u001cQ4\u0000\u001cE\u0000w,C\nۯB\u0017U#>SV$L-\u0012\u00125g\u000fV\tϯ*\u0013B#}\u000bnpþtd\u0007U$Db&$^\\^&Z\"/˺+-}%Z\u001d\u0016:}\u00169AYu\trTlP0\"~!\t͚*@5K?߫Z-P\u0019=\u001a\u001cj>܈[\u0003O?)a5\u0017\n\u0018?WUsy5^(ge\u001a${Cm>\t\"\u0014Gգ+$踿ϫ\u001b&\rXw\u0012\u001c8?\u0006g,'ō=\u0003\"/xNM)'\u0019EFqrf\u001b\rCįQ9ZY$r!6m<YZС.<V^z\u0012{US=\u001cP\nkX\u001b%3xfjn%\u0015\u0010^\u001ei𴵻\bs\u0019\u001530qh$\u0013`kܯ\u001c\u000e\u0001\u0019D&\u0000!M1\u0010W}훌1r=2NSdkb\f\\ŀpd\u0016W}^'S^\u0014}+P0iC\f\u00111R 0hDz[P\u0000\u0002&!\u001av@B]P]V< SܒGLO\u001eNgK]\u0010+&\f-A\n2\u0010#\u0001s\u0019L4j\b&D\u000eib&,AMS\u000fUD9y\u001f\n\u0015v\u001598jc\u00067MI~(sL#}3\u0018(\u0015M^\u0000Ni\u0003\u0007EKE\u0004\u00038\u001bmi\tuzI$Nr|}*+'4\u0006w{y%F $\u00118\u001c\u0013@Nz^G.g-1Vfk)\u0011G]u6K\"\u0003K1\u0007pΛ\u0007P8r>)4\rV\u00069kJ$#\u000b\u0003FьX٥C\u0013p[\bģ)CS;rFP#ImKG<h/\u0003U-,C\u001cO\u000bkOKYY;\u0013MH-t%^NξB7\"\nO\u0003ajX_\u000184V(N-{D)F0$\u0013!o\u0005Jdv/_\u001d(ǀUH8B\u0000c1fb5u&*ҽn2\bsG4\f0:\\=Y2߯\t$bi\u00038亵M$ҙ:utN\u0017)EhDhd\u0019j21|*TV˰\u0019T5Ȯ\u0010M7-^\u0004S8\u00044Te\u0001hRҨj\u0004[UG\u0004U1\u000e\u0001K{Nh6vg֨+\u000fG\u0010?`\rlݔ$Rq-.ަ\u00182Se8\u001cp\u000fSՖ\u0002k!XC\\z00\tnlhj<~I\u0011\u0015\u0014,KrL)\bIM\u000e9M\f_c+\"vҜݤL\u0004$>ɺ\u0012zj>>X9,ZL-jIbkȉ8˚?vt\u001fx\u0013PIO}_ay@\u001d:\u0007\u0007|Ve6\u0001ub\u0007d/e3<֭z\u0002t\u001b\u001aea'c\u0004LaM\nlz&,f^_!?l2x\u001f2Xy\u001c\u0002ń3D\u0016\u0013\u001d)\\\u001a\u0000\u0007\u001a\u001b?ye\f\u0019~4O+\u00009\u001b$\r\u0012\nEVD<O0Vbj&mLB2Z܈b9U;n6L0\t\u0014+oˇCr\u0004E.~>T\u001eSؓ7X\u0019?MM!ԼuOt\u000e\u0017P\u001f\u000e\u000bCbt;i\u0014\u0017ްa@gW\u0013#@\u00024c9.\u000eD\u0005o\u000bz2>M\u00175i\u001b~\u0015u0\fq\u001bs\u001dwQ9ǸLt삟Mz)>\u0019\u000fkɝI;\u000fio\"\u000e\u000eU\u0000)]$Y\u0018L\r>\u001e$$T:gUo$UK,C`sCMAJMÄKC(g]\u0014ٮ9sU\u000fG0?L5\u001dQM%0O\u000fl\u00115&\u0012`Ƒ\u001d1,\u0017x'{k+mY}\u0018-Js#\\d:i/N\u000fK\u0000\u0000\\8HstQ#-ND).s*Zymnf\u0019\\1l{(E=VGW9s:?wǟQZsC6A1ƃ6K\u0011@8OU\u0005Y^`7\u0015j6@9?,y\u001ct4&}\"T-\n\\Y&kVx녣391ٵqQ=beMq\\\u001e\b\u0012\u0004`/nņ|2͌JkzDmͫIR4\\~5NlօKɁZ]TC3l̅D3jSS)tWw$IX[\u0010wV\nWT\u0003U\u0015w^PeUhWE^ؓ~\u000fWchs\u000b\u0002s\u0005I\u0006g`wgs\u000e\u000e\r(5\u0006\u0000\u0019m\u0003r\u001d\u0018]\f\u000bB`7JfA\u001e\u001e\u0001aA3Ɠ\u0019G?{O[\u000b?xj/Z*7ex\u0010X\u000ez\rΆ\u0019})C?`KcM\u0010Ռ\u0014&)\u0002Y5\u001f\u0019\u0005J]q':]$؞]Yv\fx(ıH1eU>_0b?*񸨎\u001fb\u001d¤،\u001dD;Wxm]|N7U13*;\u0006.=>SÜj\u001c)CM>.eI1/QvН6T\u001ckk\u001e+Ɯn\\\\F\u001bFV#Xd\u001de&~WE\u0005\u00197\"bj\u001d\u0011u\u0018^I@j@bQ\fW\u0016\u001bk8w_D\u000b^z\rxZKA\f_`\bT}\u0014]\nx}ЁM0S\u0007,rV+\tKO&ƈ`;\u0018E{irf0\u001f\u0000F] w86f\u001e\f\u001bfm_8c\u000f3V<\u0005)\u0016r1p +hs|\u0001p\u0016\u001e\u0000\u001f!QP'Ղ\u001e\u000eʛ\b2r\u0015Ӥej4Y\rr\u001b\u0014,\rr?\u00044\u001e\u0006! U\u001fq]f(*&umM\u000f+\u001c;1\n-\u0012c8C\u001ajL\u0019=L1T\u0003DJ\u00037>)BH*cHY}~\u0012xI,{\u0005\u00177WjW\u0006ާʇhg_YovMKiN\u0011>\u001a\fQ\u0013Rǧ}\u0015AQj^\u0005G\u000bsyJ\u001aG\"?txt,L>֍p_>P\u0004o$^<%}KD\u000f\u0006S4\n\u0014*S<ܖyd;éIJ~JMn>ȸc\u0019I6uɖژ䩊i77_5W2'\t9\u001ct^}/8%wd\u00000k)ͦF9\u001e\u0007k\u0016ih3Sh\u001dPBULz\u0005s\u0011\u000e'0$Y/L\u00183o\u0015\b\u001c\u001bl|f\u000b\u0018ɪ\\AW#si\bS-O^I\u0011+3\u0002\u001f6xas \u001b@M\u000e\n\u0012A\u0015\fhm\u001345\u0000V-\u0013'\u0018\fѵ1\u0000S+\f\f~*\u000f\u001c%\u0014~k\u0000\u0005˝ʉl\r*\nlك=3_2~OgPs\nCcd[aے{\u0012<Х\u0016\u0005jA\t{! ߲ۓ\u001e;O'9+\u0019wEH\u001fE&\u0019JV?fiӺ j\u000205\u001d瀶bhW\u001aZxo=ƺ\f0z\u000fhK5m\u0013o\u000e\u0014v\u001a\u000b(YOut;e=\u0016R*\u0017\u0006\u001d\u0012yMVn,$v:QڳE.\u0017yVl;\u0005\bsvn\u0005,\u0005Wi\u0005.[\u000e@\u000f\u001434SD_!MF>J柣ND @$Y\u0007\u000f~-\u0003C\u0003Mu\u000b\u0011\u0019(+lBpБ\u0003^\u0012#$~\u00172\u0012è\r/@\u0018̣6 3\u0007\u0007\u0005nh\n;۪.\u00153Fq3\u000f\\َvZnZ\"/vNFNJ2V{#ΚVse\u000e_쑮Ta8C¢!Η>FL\\\u001eM{\u0006\u00075\u0018eH~7;F\t\tA\u0002\u001fB?VY=۩Q i9J.sӿc%FVb\u0017\u0017d\u0011եiL`a)kD\u0015=W\u000e\u0017\u001d\u001d \\ne>NX7Ƒ2I\u000eY\u0002\u001e\u001af-to7/~Uas\u0004[`W*\u001ev3_`~:k\u0000\u001ejR(\"\u0002\u0002E\n*\n\u0002\u0005\u0005e\u0011)DDI\u0012\u0012\u0002ss,f_n6\b\u0001\":hmh+]AqñQqSa9{~8|\u000f~bh6G\u0018\u001bZĠםN\\h+(E3\u00070~k\u001eTMGβ1:zka'LG\u00152>\u0016,\u0000gt\f\u0010X&@?e\u001f%\n\u0012=@Ihs\u001c)\u0014H\u0011\u0006\u001dUOeX^m7R7~,,\u000b\\j\u0014\u0014\u0006JԌf\u0012ͬ\u001c\u00168!*]JR:WR]Mɚ\fPZ\u000e;J\u0018N\u0011.8ɦ\u0010,[r*\u0013Α]\u0015MM\"waX)L\u0014bjd\u0002`>:?|:?u\u001f\u0007>^G\u0001$\u0002fa.\n\u001eʥ\u0010_\u0004S%\u0013ED8\fJ=\u0002ĕK\u0003{\u0012\u001c\u00146r\fz\u0007\u0003GG \u000bUi<\u0016Kg\u0006\u001c\"^ q\n\u001a\u0017I6\u0013vPWy^,\u001a\u0001\u0006uc/\u00005\u0001\u0019@:ǹ+\u001d[N+li{\u001fP#^\u001dy\u0002v\u0002,ñ\u0007-N\u001fѳH\u0004⺣\u0005\u0005<֡gxV\u0002<\u001c/\u001enb\u001d6󴳜Ρ\u000b +nhB˾PoT\u000e(W##ĉTwZU\u001d}\u000b w-vT\u0019\u001a-9O᭺HIz) z9R'dI5aZG\u0004S˟a\u0003gW=.P\u00161ٜ y?\u00022\u001eX)r4Va\u0014GX\u0017\u0001\u0018Be`9Q1͚@85\u001e\u001f$W?D\u0006}z2*\u0004\n\u0018\u001ept\f+;Br\\ܕ'>\u000b-v\u001c\u0011CNeʔ\u0019L-ʌqKHr\u000b7\u0015I\u0015\rd<\u0012\u0014B\u001dgNelB^փR\bγF2Aq\u0002CR&t7߄{\"\u000bD9\u0015u)\u0010C\u0003w1t}\u0010?\"'\u0013\u0012[7o\u0012̩~\u00171{\u0015>Ru*\fʖ\bdClutqf2[\u0005l~{S4>J$.\u0013nQnlP#\u0000x])By`r+wLH?VD:|iUG~ժ+\u0015&+R\u000fb gP>}W\u0013Թ\u001bkQǖ]WSk\u0018\u001eqwZ\n\u0012D\u001fQ\u0019dVd2\u00124KGMvU\u001e35KJ~4\u0000&\u0000jwJ*y;X߉˔O\u0015@5\u001ahw)񘴕o-9E:\u0017_\u001d̂o&\u00156\u0011#V(ѽS-te\u0007$\u000bפp}4%4mr\u0013nzhe4KX*KÃ\u001329ʩ~'Ǥl|O\u00045\u0012ÍB\n;^j㛑Q`exH;\u0001J\\*`l\u0013˴Khk\n&tF|(8\u0012V\u0006ǡܷ\u001dR\u0004\u0019\u0012:ϳoG*UjSKk\u0001nR\u001dgl\fޅ-\u001d6\u0007&Nŗ7O\u0010\u001e\u00174\u0006rGmO[du_TvY\u0010{\u000b̏Iy\\aRKy&P7ݪJ)l\"W5{K \u0012S_\u0014j\u0000\u00160WSW;\u0015wixF1^\u0012lО伴^'\u001c1b%OA\u0001\u0002Xhq)L7j}=9PX=n`ɗKX#CùA\r\u0006*7\u0017{ jWܴTBy\u0010\u0002\u001f\u0017ufכd=Af]\u0016F=_u*`q+\u0016_i݋\\^`BaE|S&%\u001d\u000fZ\u000b\u0015a\u00078\u001b+QgQ[IK-jIKr\u00182Tcju=A\u000b\u0001ʧQ\u0017\"7{ٮ\u0017ם*X|,\u0015Y\u0019\u0015\u001dz\u001dѽ\u001a}ƈf:\u0015jCo[>]x^h\u0001lhNrϳED\u000fkc\u0005\u001aCǪ\rת9c\tH\u001c\u0001\u000ft<)}z\u0012!hE~DBӳ2S͆i\u0012{;ouIp\u0018??砃46ٺ^\"\u001b1R<-65sj\u0012pCSjqi6ǳھİ紈\b\u000b41.\u0002$5E\u001dG9:\u001c=ob쾄\u000bv#\u0015[xﯦ\u000e\u0005\u0000AF\u0002+T\u000e\b\u001e\u0007\u0013(C@RQF77\u00062I\u0002$^a$\u0010Eq>\u001e.AE\u0004\u0015b\u001ciO0\u0013]ТK5ΫPÛG\f\rZd\u001fJ\u0014*$d\u000b^}E\u001f*֤>?\u0007\u0019\u001fƄ$dO\t_tl%$^7[KSECqz\"$\u001c]*\u001bB]}W\rzT[R\u0010k\u0019\"\u0015n\u0001]E\u001bUY\u0016\u001dvFUW\\B6-RB^Me2B4<ZRV\u001ajVy~O\nW>/wͺh4E\u0011k5˖<1U[t\u001bD>Q\u0012\u0019!.kR涧7u\u0000Jc>c\u0014\nl/i^3;iڐ\u001d0sĀ\u0007ZnS\u0014\nqW7Np:([568V\u001ciA\bFޜ\u0005\u0019~h\u00069Pldüj\u0005\u00102dO\n\u0016+\u000561--\u000e1Ewv\t=\u0014JCHW34܏&x\u0014\u001b8,&#Rc\u001b3Dvz6\u0001RSyu_N/nm\u000fكvT֥Y˼?R\u0005FװKzn9Q4gC^5l`\u001bP\u001c\\ܲG&\u0011ޫ`\r9PҞٲXr\u00146\u0018\nV4\u001f,{a؄\\tcY`]lǿԾ\u0015ar\u0006鴯؏=b!&Yb\r\r^[\\aYt$w\t\n[R)i\b[{$7f\"o\u000bX\u0019p\n\u0016zBz\u0001'h\u001eO|Ō4ǐ\u0001|-j\u0002\n:}̴a\u0012\u0003\u0000%T\u0017v\u00125Y\u000f9QK \u0016d0\u000b?$ćH|#uD3\f\u0011phr\u0017d@,@\u0017Xm\u0007\u0004VK\u001cY\u0010@o\u0014u(\u0013[8#!OM~.7SoJn%<IdZ=1D3!P#4(|:]S\u0010Yd_kGRh+OtB%/e䱖&]h\u0012\u001fr5\u0011slorQ\u0003\u001f\u001e\"F,bՓ*2~:ʼi\u0005[\bt˦\u001a~M\nU6DUe\u0012\"udPO:]x+\u0019\u0017GB]q:ʥ':\u0017-ML3\\F$7K\u001f3\u001e\u0000C*s\u00172zFs'Ô\u000b\f̼Ks\u0019ӚwER\t!`%aT\u000fH\u0002vRW\u0007SPƅT\u0013}FVArB\u0015[SS &}p\u001c\u0013`\t~_1{,yo\u0015\u001e{30[\u0016b\u0003\f\u0013\u001b\u0002K\u0010:w\u00043\u0010\u0007\u0007Mne6s\u001cz/0<x\u0000&3n\u0001j@\u000f_d\rKBٓ\u0017! t\u0007r\u000f!6<\u001drƕK\u001fjT;ҽ\u0017\u0012.Z\u0001\u000f.,68M\u0013Ul{D\u001e6v\f@\u0019)tmpy_.>OG\"\nÜ3N|\u001e/'O-R_1Vh&׺\u000bNPz8de\r勊ZTH;X\u0011Q6}+'h\u0002_\u0012\u0000|ȋCc\u0006uHjBA,NOS{3\tL\u0000`]\u000e1\u0005\u0005> A\u0013\r\u0000rxӴ*E^.\u0015\u000eؐ`Q5\fv{`=\u0013W6뼟\\9a\u0006vG\u0013OXc&\rv1w~\u00000W:ʎ~\u0006\u001ff\u0018:\r0/˵\u001a%m\fKRKA\u001a\u0004cR%\t\u0005P#CS\u0011\u0001ߥfmD5\u0003\u0016oEx17B0<&\u0006Yd\u00178\"\u00021\u001dw\bܡ5\u0010 TaaJ3p5\u001c7A>+yI\u0007\u001dMcu\rZd\u0001?B\u001ck1x-\brsV9s\u001c\bH6p]DGgO|\u000by5S$aE`$Ls\n[\u0017Y\u000fm\r~\u0002u8p`6*I\u000bߕ`S8\u000f\u00068sn9O3nXOE\u000b/7\u001df\u0011^lbN\b[PB\u0010FO.\u00169\u0013Z\u0005_\u001e.5>F\t\fS̉R'}ΪѬ`_dX|\u0006{d\u0003HXԾ3\u0007QlZ\u0004\u0002e7PRq\bش\u0014\u0004O5OkZrx5u`a\u0000ǂ:\b*`T),\u0001\u0001\n\u0001DPQʮ\u0006dߓJ\u0006Rk\u0005=H+\n*#u)h) )B6\u0001s9߹瞏\u001b\u0011HZGzGT\"93hDͺ\fsr|b4y\t$T\u0011K\t\u0004\"$I~\u001e$v(B#].qi\u001d\u001c\u001a?CN\f\u001a\b~\u0016ޱ|\u000fܷLcO\u0002\u000fn\u0015T~v\u0013x\u0019\u0007j̦5<.f\\K<2p:\u000fCp\u0012S\u0007y,\u0012\u001c6\u00026>|\u0007zC\n\u001f\u0000\u0011E\nT\u0000)f/:X1}J+\u0007>_~\u0000\bQ\u001f\u0014;^ㆪvs&۸>.k7yZS:˩㜍r\u001cݖۜaKa\u0017!l.g57Kv0!;\u0010ڗf\u0012e\u000b%]\"XT\fJ3\baժlwVj=v姠αe=bI/gH&\u000b:g,(y\t\u001327>a\u0016ba88fVV\u001c\u0013qɌT0\u0015N\u0012ɉB`(\f\u0015_\"fo!\ft}W\u0010\u0003g_0}HX\f9,Qx=~Jٹx>\u0011ӱe9M2mFS)Vk\u0019-eZF\u000fF٥btg0\u0015O?Dǐ%\u001f7eyښ6WS\u001eCy\u0012eUS}\u001dl`a8\u0014\u0016i\tg\"\u00161лJ\"|PKڝc,$+&\u000f\u0017PvꖴGBoj_t\u000e4I\u000bv\u0015qf熚(e\u0002C\u000e!\bb׼^S\u000ebYi1¨;\u00022W\u001f`/7\u000euh?4\n\u0017\u001e\b!z@#\b(T\u000b6\u001f\f^\u0004!R\u0015\tS\u0003#>E/Sq9z\u001b_ \u000b/\b\u0001G%ӈ\u00190C\u00129[\u0014ۼ@(٩P\u000b,\u001a}\u0002XT\u0002Okp\u0019\u0004QȫUG6\u0001\u000b\rx2e\u0015,>\u0000\r-?ϭQެYz\u0001/T\u000f5FL\u0003\u0006^`tީ\u0014\u00033\\#\u001a̬D:\u001e,\u0006v\u0000w[mD\u001bW\u0016)TBZ`0Ֆ`3tBQ˟kk\u001as41y\t`\\\u001a޸cV#\u0017\u0012z`XHhwA0چFTyqӵܫ*F˪\u0001%\u000f\u000f*\u0011\u0018/>9\u000b\ng\u0013\u001eS'\"b'zL=N)c\u000e\u0003s*bR)W<\u0015#\u0014S\t癛)K\r\n&\u001fL\\9\bWtW!\u0016Y1\u0007\u00157i*%\b\u0005wJ_\f閥nWJ\u000f!p\u0012\u000f-0T`:K6B+S\bzlL,~J\u001a#ZLHBEe߈\u0007E\u0018q1\nڸTD}\u0006bB;*OT\u0015CnՍl$OYQ0mz\u00157o\u00029NŻ|hDV[Ve֩b7YZÖ\u0004Hl\u0013~I)ܻJ5oOݑ\u000f\u0017%(,hZGҼmRd!/NEWutV57z;jjs\u0014\u0004^^l\u000eDǾ0-a\u0003_a\u0011L؁\u000fw44\u0003簍b^\u001cppi\u0015\u0015&nX\tuƻ-݂\r-cY4\u0003_\u0013\u001eg\t?\u001cjGI\u0019fH\u0019\u000b%\u0004J҂[\u0006%ϩC6Oz\u0000vW\u0015zoZtA$?z\u0011;\u001e\u0001ؼ\u000eFT\u000f2/+\u001a0\u0011@@S<@>0b\u0006Suqw;j4S'/4s\u0014Eթ(P[\u0019V\u0018^5ƊH\u0007kg\u0011/ۄw\u000b0*֭ ajyB\b5TC\u0015\fJ(_\u0017F4!m,\fRN\r?\u0006S9\r:״\u0004OfOV\"\u0002յڇ1\u0005\u0018,V)S@\u000f._\n\u0019#\u0012Q`K|ͨ%cj/&\\:\r[Ft^Z\u0000\"q٤Jm뙊jMarח`VCg\n\bw\"~><\u0007\r8i}XT8ǳ\u0001Q\u001aV\u001eY<<J=E\u0013ۏ7\u001e\u000eG8v6Z:\u001b%hBò9\u00034^ԥm!\u001c1OD>p%HG\u000f\u0018/Û`rq;Nm~Ms\\\u000f/Zh\u0007:(MXа^F.꜋.Ys}5`a\u0000((X0\u0012T+JS\u0003\f4&~|i\u0010B\u0002!\u0001\u0002!\r!\u0004\u0002)$\u0018\u0001)\u0002ʰ\fWFY\u0017]E븎3x,˽}\u001b|\u0000\u001ddc\n|i-0Ws\nQ_GpRjy0׿t\u0005jT̎ԍ\u001a\u001cD1\u0001څ\u000f\u0010ڍN:ka?\f7e\u0014k\u0015_\u000f%]a;ז\u000f\u0006\u0014\u000eF\u0004=\u000f9-b=\f&Mm0-vD\u001b\u0010'^j+/5(er^+EL\rF1$1KWE|fO\u0012FMKm::1`ڥfXЩM*i9\nl?+Lw?\u0017-Nx͈wɳ\\C0瑃f\ts\u001cM;iđ`$\u0017O0z\b*Rٹ\u0018\u0014B9@\"\u001fk5\u0001\u001dv~.lB?u\u0000g\u0013]\u0014ed\u0005\u001c8JAj\u0017͹u\u0011m.DO^^\u0017v:y;s\u0015ke\u001f+,L¶v\u0000ŝҼخ\u000ed\u0015_\u00145Z;\u001cq#k\u000e> MU\\J{l*͟ґ3Doy\"UDcu\u0005#H)BPit\u0014\u001a/\tv`\u0015_\u0015S\u001fʝ{\u0015e\u00115mpPpy=-2[m+v6\u001c*.WۿSǔ]\u001d\n^DMk\u0015,2.\u0013#\u001aɲ\\!{\u001e^\u0002I4Ԉ\u0017.~çlDcBU\u0018\\b\u0016\"c\rjvJG|H`_2r\u001d\u0019Hѥ\u001e\rt\u0002HH\u0001Ba\u0014G\t:Bf{'9\n[\u0006jaЧ\u0011\u001ae\u001c\n\u0007&h\u0016\u0013z\u00126Fdy?>gۑ\u0019x&l$^:^nx-'-\u0010]O 5\u0014@S\u001c \u001b\u0015Uڏy]Tu \u000b_,z\u001dWPT\u0005|BJ,ɕ\u001f}`\u00028ߴy?p7gˢu\\JO(_v\u0011OUue4\b\b+Qbi?A.jCxyR\u0019J\u0016駥Pt㸲r\u0004\u0015T\u0014f\u001add$ֺFR\b>P\u0015aL\u0001'\u0019\u001ev2M\u0013\u001b*׵\u0003\u0005\u0019T]`W*cD*\u000fhAe#\u001a\"ɆKO\u00169JKL2J(\fKgK\u00023\u001fjԉfZ\u0016nL5oM(_>FOӹGi}<\u001b@w#Nd\u0019\u0013h\u001doo4Y\u0003\u000b̾Fٸ2\u0003YAz$W֜5Copli\u001e\\\f\u001032l\u0015;a<;S?\u0000\u001fB><Aa\u0018rL>z\u0016p\u001erj\u0013sm1tZc̥\u001c{\u0010s/J{c*#3ހf\u0004ϡneh->Bc9S\u001bJ\"չO8'8\u0001\u000fހ `yHϤu-*`\t\u0017\u0004\u0012x[c')Oy\\x!Q\u001cS9q<oc\u001bWSR^\u000e\u0010\b\u0003[H{eU\u0006\u0001!.$,\u001a](\u001a1\u0017\noe*\np}%\nK\"\u0012G*\ryE%\u0004S\\#V9\u000bۦ24=ZH\u001c\u001dW}dUU$U\u0004>*\u0010;$;d\u001e'=NY\u000b,|ܶ\u001e34qT=ka%\u0019h\u0002\u0016s䬺\u0013\u0004UX7Fl[\u0011\u000bo1apuxf9QGk4\u0013;e\n˸7荇\u0013\u000f5xB:y\bZdͫ,`2\u001f?_a[0\u0003~9iY\fFs3g\tË9u<,yx87\u0018\u0001 1Ja\u0013\u0005,O@/g\u0001O㔛\u001e94 |.\u0016\u001a]16'^\u0018\u0000@1'p:XtwL,j\u001fVQv@wl\u0011{έ̱\\?R^UV\\G\u0004I\u0010+9D0\u00063o\u0007yd[R<\u000e\u0000\u0011\"\"\"\n.2}\u001b\"!<4tH~(-r2\u00055DH@l\u0018\"K濣,\u0005/S}\u0012\"+\u0001~w\u0017F}V\rdRz,\u0004:w&?C~FqJ}Jݢ\u0005Ji\u0017rjzEgU#p]ZF\u001d%\u0017+[Pj\u0000ewVjlW7wR\u0015/*C%%jGx\u000b@EF\u0019H)&0_\u001b\u0017\u0015Օ\u0001|Xu\nDRNX\u001dA\u0001\\\u00140JS\u0001H307͛73\fC\u0012Wc\u0003+U#r\u0012\u0011\u0015#\u0004\u000baQOL4\u0004E\u0010љ?s~{sI\u0005\u0011y?y>ҒLָKd-ޣJ\u00111v\u0000\u0017*fH\r6\u0002h\u0001z+~BO\u0019:\u0005IQqZUՍ\u001dP\u0014[\u0004UD#BM\t>$\t\u0018z|?^\u0013\u001f!J0W8\u0001\u0001N\t\u000eW\u0003zXfщ\u001b@\u0006'h\u0015\u001c<\n%sdR۔e\u0011[$z\u001f,Z2H5\u0004[&H\u0007t\tL\rU\u0012O\u0002\u000b췯<uɎrE\u0014\u0007ᾀ{\bi,8+ןwM2\u0017O\\7I8\u001eil2ewkv\"\u00079kr6±U\u0005\\R\u0013\u0015*qoGC\u0007xxy;:jYE)\u001da\u0007ΰ!\u0013Xidj\rq(8S=l(P9\u0018Iue\u0014&\u0016\u0006k)W1=kZb;8zBC4\u0015ڕav?suUuP\u001f\\Vf>+52\u001f\u001bj&P\u00116uRɮ!\na+rk!o\u00054\t\u001a`\u001aܗP\u0002)f\u0005%\u001bVQTF\u0011(Z]s,TR|O)O?ho# ]6\u0016yл\u000e)OU,F٠E})g\u0014sٴGyҘ\u0007p/k\u0016w\u0002~˖I'Y;Td\u001egYU'\u0010I8@\u001aF*\t8\u000b$\u0010I+A2((+y8OϋWȗE\r{բbW\"@\u0012}@\u0004C׌teY\u000fgvֈ\u0019H\u0003\u0010ofE`ea<oV\tF\u000bCk2*\u0014 ]v%녦Ly|\u0011KJ3PnW(\u0014<\u0000yiBVOh\u0017P|q'9[\"\u0007<c-\u0007\u0014p!pw5\fϔr\u0013)\u001c\u0013􁢮^.\u000b,8L\u0000o\u0006қr\u001f7\u001d\u0001ȶǫ\u0000.@\u0017\u0015Pp\u0000\u0004\"\u0002XSI3IkTGm\u0012WVbu6G\u0005ބ\u0000\u0003`]OZ\u001bQ&'lTR&\"N!v\u0006G{%^}T1v:Ȉ\\\u0007(IWf\u0012*ڮʃu*\u0016lgw\b\\Wd?'~|S6|ɖ)ݹ\u0013\u0015E< K7b\u0007%\u0016\u0017J\\*\\D)\u000be\n2G\u0013\u00122ћBjx$Z-\u001aa\u0005V#\u001b\u0010\u001es/\u0014h\"K6WZ,\u000fɳL9\u00190~G\"\u0001~4\u001d\u00125\"[\u0011K4hq\u0014ɕFa1U_KĪ)P\u000b\r?Q΢9ޒ\"zܮi$\u00045I0]xo\u001fܬUJ&\u0010]:QS{\u001a%Kz\u0005<\u000b~m댋/7ƣ\u001ai_y\n\u000bI<\u0010Gd\u001ek~xkے1e'w7۲\u001c\u0002Uyʪ\\PxVnL\"\u000bN6tĦ>\u0004\u0012gbN_4!/e%\u001eO;mhtWv6\u0002[iyFy4ʔat\fV]\rau\u0015\r#\u0014QY\u0011m3\u0014r\u000e\u0004M/q\u0017{\u0019~\u001ctjD\r7\u0003f\u0017i\u001e\bɷ\r\u0015\u001f .\f\u0004=[n`4\u001bqShBrx_5wԐ\f%n\u001dQ\u0016~x'G[\t`\u001e+qb]Q\u000f2Ըi=UGn~\u0013ڋJ(Aݪd\u0015\u000b\u0016\u001f\u001d\u0013E7Kz\r+M]\u001b!}\u000bjnh-Cզ_魺\u000ea٭D\u000ffrj6$-\u00044nUZ\u0006F)Zp\u001eux'\u001c@]U/ٳۿ3Ug`iU}ڰ\u0017U\u0004LWu+SU[\u0015;uXJ\u001bP\u0017vOŀ{$KF,q\u001eQruH.}imfZh~atM\u0016\u0017Bb0*iW\u0015\u001dC\u0005䶧jZmn\u001a\u000e[nKfi\u0003\fc+.&oV.\u0006\u0000&\u001cʭ{5_s9dm\u001b\u0017IA\u0001. \u001a*\bs5:\t1\u0018Ů\rm!|fl'6#N\nZ>\\oMk\u0018C\u0005Z8)*\u0011\u0007\u0002\u0001b\u0000EE@\u0018(27{I\"\t$!0\u0002a=+v\u0000UZŁ`-xEJU\u001cǺ\n\u0016\u000f\u001f~~7<NzQT!w\u0001\u001bB,C)kE+\u001f\f+#\u00046\u0005-)\u001dp*㪝A \u0007A\u0016occ~\\_xb5Ӽ\u0003zgQu\u001a}޵zGeX~\t>TS\u001dsV6\u0015i1\u0012=\u00182J眆J\u001fh@ U\u0007u;\u001d\u001f7!0\n߽\u0006\u0011\\醮\u000f\u0013%-;=.\u001d\u0004e/T7D$v{\u001a.ʫ\u001f\b\u0007\u0010|Z\u0013ѮmcDֲ+-Cu_{>1H1]\"D^nR\rٺ:E3\u001d[h9\f7TJOW+3\fv\u0003Limc\r@6'[c\u0007`Ǧ8v!b\u001aR{1_\u000fӵuoPE\u00032\\@\u0007;4\"\u0004mO\u000b\u0016\b\u0006m{\u000b\u0016ߺE\u0012\u00131dA}\u0010C=W\u0003B\u0002}[3']\\PJG5VmnY\u0002G\fXyahd'J\u001a[\u0007U~\tvWۅWo]WnGnR\u001f9H7\u001fѨ\u0011Au\u000b1\bvZ\u0017m]lUr\u001d\u0005TVA\nsj6lhm\u0018,M\u0006y4A*0vJ\u001d\u0004R? Ĵ>\u0002\u00172C\b!\u0010\u001d*#q0MJ\u001d!:ŏCR|dFa?2\u001c݂\u0018c\u001ah3d\u001c\u0017B\u001e\u0002zS\u0006It?\u0007%\u0019\u0010\u0011LmF[AxYGҏ0m;\u0010GY1űh%[s\u0015\u0007ጒ\u0019@\u00179\rq_8G>\u001cr\f\b\u001cW\u0013n\u0011)jodEzC.q\u001aJv\u0005i\u0015N&I\u001c\u0007f8bg\n\rv\u0013|\u001csd%:uTf&L0~p\u000e\u0007.(RU\n\u0017;\u000b_)w%$\b/\u000bt#\n~\u0012#u\u0014`\u0014u[w.qs\u0002\u001bY\u0018_-*'̳ɩk/)\u0005\u00172*\ri9$7fUzflc9}]\u0000,툏WYC\u001eIk\u001dS-\u0002ty7>\u0014T!\u0017<v`tFW\u0011V\u000e\")'U\u0019\u0012\u001a!<\u0017\u001a^DV\"_W퇖6!\u000f{9\u000b\u0004JJji_U(홽c4*j>\u0001\u000b26\u001aKݲ\u001e\tm\u0006&\u0019c<kQ\u0000\u001a\u0002Jl\u0006n\u001d'IyT>\u0005ӣh'\f..+upC\u0006\u00136&@j5t\u0013\u0017dP\u001b0=I˂Ė\n</B\u000fིY%\u0017\u0002V(\u0002q\u0002\u001b/ܦ,Ǘ\t9(B0jtI4\tS:qԙ1\u0014K\u0014h^ChhC\u0014\u0012\u0003\u001aF( \u0005||\u001ay0%o:TA\u001a\u000bBQ\u000fyPI\\;hVʓ2J\nĥ[Qr\u0003_k`9h\u0019 \"?7<18\u001a~Щ\rt]Z*7֡^%Aǌ#7L{Lu7\u00057]ČY\tL\u0005\u000f\u0011\u0014L\u0017\u0003;\n\u0011i\\WkI\u000eSy!KC:3\u00181hZPf:߄\u001f0C>C{\u0018޶$\u0004tR:(ϭuO\u001eR4$=jluq\u00191?פ9Si|c\u0017qF!_z^S\u001dK}`d%D\u0013T\t\u0018w\u001dV>;\u0000<'V\u0006=\u0015(5H%j\u0006WM\u0005V#9YD2֓\u001bp~~J\u001f\f}D]gNSsjJ\u0003mn\u001f->,v\u001fg&SL\bl#\u0017>^i8\u0010ʞ%4'\u0017RJ\u0014Dh\u000f\u0004RN0hBA0(r0K+a\u0005\u0003MY|\"EGE\u0013_R^v4/\u000e?m[˨yN`K\u001f/5[\u001871[\u001aG\u0001ؒ\u000f' '铯R\u001eGhqꭁ\u001a]\u0010>iI\u0019X\n5'\\G\u0013B\tćd^\u0012u\u0002x+\u0002[^%e\t֪p\u001axE\n\u001e 6%!Itި@Ҿ\u0000#%\u0007\f\u0016\u001b\u0006\u0002:*\u0000h$r7שׁ55׈Ց'I+\u0013\u00036*ЮwȰ%U#zD+Jt Ba\u0017Uؕ\t6}\u0016\u001c\u0011uO\u0019r7dP\fCu}FEua\u00007R\u0004\u0019V\u0002\"KST\u0019\b20\fE\u0018N{^\u0019\u0006\u0010\u001alk\u0003ƕ$vW(,F7b\fˢÞ\u0013Oy<\"_).kh[n 9W?gڈ7y\u001bș*ӼuA@ OpIR\u0011rP($e[i<H/\\t/G\u0005inQa@q\u0012Ia{\u0002Yʒ\u0012\u0006]e?D\u001a98ߙyd\u0002x\u0000,8?Pe1NWwAi\u001a\u0000N,\u000f\fB=%PK\u001d~\u0006҈G!OʽR=e\"!]::BI\\MJ1jGK)\u000f\u0013b\f'xL\"W?D\\GԝC{AA\r?u#U\u0015\u001bUJ\u001cǹ\tH{\u000eF\u0004[5h[\u0018N6){((\b\u0011%\u001c>VYR\n\u0007n#\u0012(a\u000e\u0013Fq\u000e\u0015&mq3%\\g?\u0010%ӆM5XD3b$ʁ\u001d\u0014W \u0006ƿ5\u0005&͔D4®K\u001ec\u001dᏊ\u000b.\n\u001f1Z\u0004\u0017\u001ao\n^`~¿`6z\tq\u0013\u000baXǰ)Ӽ܄'84\fn\"Db.\u000e\u0000\u001eyC<\u0014K\fd\u000f},{\u0017*h\u001d\u001d\nڸh\u0017>wMv^\u000bc8Iƻ(~\bj?\neoy\u001cl/Dl5Żרpy\u00151\u001fܣܵ^004{\u0016\f\u0001.\u0005\u001a%C\u0018\u0016A22dWuQ>ok\u000eL<\u001c\u001e\u00115.ſȠiffh7S-|^T\u0013jX[wCY*\u0007sG^1V\u0002e֗+\u0007˃\u0006\u0001\u0019L3\r/2y{\u0007\u001e+.;CtJ }\r-\u0002\u001d>٫\u0019y6q<\u000b\u0016\u0003\u001f<bs\nb\u0016k\u0006*ĉ\u001f_\u001cV\u001dTm\f}D\u0006\b51oU\u0000Qu\f*nҹ\u001cD\u0019U4|>WxA\b_\u0010PZ?\tQ\u0012\ty\u00141>y\u0006\bK\\\u0014.!O\u001fqM\u001e\n\u00140Cl\u0015\u0012];Sk)=R\u000fZ@[ɷ5\u0012\u001dJBeǐ$\u0006\u0005Ni\"0\f-úR4H~9.\u000e☫|Dϸa\u0005h\u0000-)r~\"eo\u0014M\u001cK%4\t_7\"\u0014e\nQD~0T.\u0018\u0017>\"x*\u001cO\u0010\u0011>酧.Ey+HVy55\bRW\u0005s\u0005Ek*\u001dPxEGB;(J\u0011\u0004\u000bX(8hiqmh^\u000b0`}_APW\u001f\u0003DLZ\u0014\u001b\u0007]<\u0001\u00154zG֦\u001b`oy\u001fZR\u001c|u^\u0014gCF#\u0004n\u0015r)Va\u001c5ƪw\u00039\bnjyIt\nxI1bIy>}-Aگ\u0005\u0013\bOShKF\u0004x\u00126xqqQ\u000b\n3SU\\ka\u0011椚̩Di~\f?{>J3\u0013mtߐZt\u0002]YNju]ɒQY\u0018lZZs\u001e\u0012NѴѷW>S\u0014ݥ0Bj\u0014\u000e+7q҄fU7m\t:8^;#eտ+\u0019*,_CY3\u0012\u001d\u0007M\u0003SU*LX.jQȖg\u0014_IW\u000fJ5a\"9R'C\u001b\\y׳qH)VU\u001d-Z\b.\\+Ѥ/a\u0007\u0012en/|F[?SPk\u0000r\"\n\u0016^\u0017Y>VH\u0001\u00139\f&yaIxQ<zU1\\\nٽl\u0007*7}\u0007hu;Twfa^cnYS\rq;)oZuG\u0007!uTUOrlk;HF-x/,u\tsm>fd}+]\nU.o.\u0019=q\u001a-y][\u001av\u001eiR\u0012gk*`/pLBu\u001a\u0018+A\u0006@\u001e[)\u0002&PY\u000eQ?im/K,Y\u0000*gu(i\u00022\u0006`؀V\"fJS\u0014s=\u0013RU@\u0000\u00127+>dْ\u0010smY\u0000)w=U?ο3D\u0012\fqjv8<!z\u001e\u0019g)\u0012\u0010b\u0015^[$zRYjT)Ԭ1c?\u0012M\u00062q=@?\u0007\u001bܣ5ew?SIfqD7\fk\\\u0000\u001eL24\u0015\u0010A<\u0015D\u00101`\u0015\u0007 (T@@\b+7{\u0004\u0002dI؁\b\t3*8\u0012:@-\u0007\u0007\u0011mq*8r\u000e\u0007><uݹ\\idXmmJJ\u0005\"U\u001ej\u0016b'm_\u0013z$b\"uO\u001cbM\u0014q_'\u0011\u0002isͼ\u0007?M#mp_=~m=İ+ȡ:L;\u000548l\u0003m\u0001\u0004b\u0003\u001e3埒-m\u001e$Y|Hn]ckk{>3׽}\u0001\u000b\u00051r@vy:{Eͩԡ.\u0017޸\u000e,珈~CH{k\u0012\u001fsv_\u0003\u001bl毁@\"lOR\u001d.\"0\u000e\u0013Fl]\u0000]C\u0014˧\u000e\u0004Mfi nq\u0015˶Q{56e\u000ff\re\u000bl[IuY_(i&;to\r\u001e\u001d\u00105kZ/\rjj\u001ap~Ch⨿䦿\u0007iRs!G-\u0017֠5\u0015\f\n&\u001fwa7\u001bWAƫXU\b\u0011r8+}E)oVӃIÌ}qZl\u0004\u0003h<\u0019gw\nA\u001f?=$6-ޡ|,)!<\u000f*\u0016ǘ*z!8߀\u001fϸuPp\u000f\u0000D|Ŝ\u0016e=sm4'Ңؽ\u0014Y\u0003aPOZ(vj?\u0004VGgxI=V\u001e\u001d-\u001e̹uMCJH_-C\u0014]\u0007B~2A\\8*E8PTΔTo\r9/whaߣ\u0005by\\'F,Ռo%wU\u0013/\u0003ժnM*T Ƌ{5\u0019ǊԢT9L;y\f_fX\u0011D\\uַA:x\"\u0001)V%V/*]1#\u000b)ԋ@X\"\u001b\u001fSVӅ4u.f?Uչk%Nj;c~?\u0011]Pۺ˄WҌ=V듍1\nE\t\u001dֻqd{q׉;\n\u0011N\u001eYHdfttc\u0018\f#&v\u001aPtQ\u0012jd\u00011o\r­\u0001R)ʽ@}\u0006<7\t&\u00108wyybH\u001c04͂\u001d@>\u0000o`\r~M<a9\u0010(n\u0017\u001c\u0011c9̼4<\u0002o/E1\u0012\u001b\u0010:\u001aɕ\u00197e\u000b.{ՇPi\tWEYxޝr\u0006\n\u0002EJ7\u001cT|4\u001f'r41 ns#?Cśhk6\u001c/ϻ\u001e7\u001e\u0005n\r\fHITc6߱=\u0001z\u001dz!?z_)c\u001b)ueT}nS3&iq4rEUYX\\K\u000e\u000288IX`}7yIi\u0007\nSi\u0011Gr3\u00048Eiօ$f\rl+n.*d}0Qe:FSS퍆֯SȺ8\u0002~%;\u0000[ژ\u0014\u001b\u001fl0~{^\u000bKbV+T\rs\u0000Ix)oeqra5),kx\u0015U\u0001Q\u0018\"YNפܾWu\u00198GQd!\u000fH92\u0006'\u0002\u000431cC\\!Q-;U9\u0014\rdZo8CNT1+hڟl-?63\u0012z,=\u0016]\bA\u000fw7!\u0011z6*\u0007H\u0005H*[|C_\u0012@m\u0007\u0006s2Ur\u000e]^\b\u00079\u0015n\u00040\"PuTt$#:H@бjyb~=噛*kuUQm9]'pu\u000b\u001ddSۖ\u0016Hgi\u0019۬6r-\u0002\u0006>`Oi#T2\"-!NSn\u0013\\ z$\u0005\u0017S\u0019C%Q%;\u0007\u0016OzcT)!M.w\u0003f.Po1\u0011U=Bl1F#F0HD\u0015\u001a\\u̞rڜ*ujQO5u8\u0005E$\u00117:\"І(UuANgulWYE*Z\u000f\"cT\\\u0019kTxlx)$<hT'\u0002,ʷ\ry={V?$N)DPVl\u0018]:|d̏\u001f\"w1*=3*gB'\u0012\u0019|\u0007'\u001b#sBFS^PR8?\u001d\n$\tm:\u0007\u0017@\u0013l\u0016(蕉9\u000bEa,\b_܎iǀ/\u0013O\t\u000eI4a\u0019S8!%UJ8C(&2J:;{\u000fMጫ~JdmrFW\t\u0011j\u000f\u0017gY?;s\u00038Ҁ\u001aZ6\\F\u0014qD\u001c,H\b\tY'{\u001e$a\u0013@Qk^жr\u001dh\"j}+mj\u001fysәMD]_CJQw\u0006)/ʹ5״2s7\u001dv}7\rTV\u0018S\u00146~GoLF\u001d\u001b\fYHKmkv\u0003\u0016~U.+j\u001a\u001b\u001epo8Ɖ$5)\\R(\u0006g\u0013Hm}w5jN)\n+pvO[nHj͌%=h\f4\u0005^\"\u0011\u001a\u0018lq:i%S,P=Ƌ\u0007G\u0015T\u001b\tBULR8LW\u001b$GxL\u000ecL\u0012S},?E;8QE$?\\.e\u0003!&\u0017\u0015K\u0015K\u0007J\u0014\u0013G7|_\u000b\u0010Ҟl8!>8(YBIY`[}\u0013.Bb\f\u0004T$=U8Oŧ\u000f\u000b\u0013yP\u0010-x$\u0018]0_\n\u001aj\u001e(\u0015sOH|/=wKR\u0001`\u0018\u000bptl\b>f\u0004*\u0001\u000eӡuU<=Ts(&zpKA?sLo`N0Mq+~*m-~F7^5惬H]\u0018${|\u0002-Ҷ\u00079Y&=X'Vu+^\u0013ϖEm\nY/0X c\u0016AdP\u001cc_X\u0007\rVRx6\u001ab|C6^FeC]o-F?f7Q3V>͝\u0012yFs\u0019\by]\u0015ݯMF͊\u0003k\u0003^\u001bNնI\u000f#FZ.7ƆQfeϫC\u0011Jn;Aj\u0016B\fJFw\nmԗ6t\u0010(I5be\u0012ElX\u0013Q\u0001\u0004͌\u000f\u001c\u000bi,)6QS 1zJezVBf\r۹ʹ\u0012/\tHQ89\u001fSnE%o-4Ǌ``,\u0018)~ut\u0016yQ\u0017\u0004\u001fN]vح\u0000p+\u0002e\"xN6y*\u0014,7\u0007$'x\\CQL\u0017[8.d@}\bCɏE)\u00101\b\u0001\u0007D?@晹\u0012b$?7\n\tYM\u001a\f\bN\u0019\u0011|\u0005\u0013\r_Td'wa\u0001}\u00170Z<9|3\u0002\u000f\u0005閗3\u0015~o=Y>l0Wb=P1jmE \u0003XR\u001f[louv:.C=;.a.BřS[nWJ\u001b3ǟN1='\\Xr8۲:KXj\u001b6e\t\u0015\u0004g΀a\u0011p\u001a\u0000%z\u0019\"K\b1.c1ɇz\u0001ɭGTRiVBe\u0018\u0000-)K@iͬ!u\u0011@_\u000e`&2q\u000bup%\u0005P\u0000\u001a\nSЧ|NWP !\u0004\u0002o-t_\u000bnyV|ؤ賐e`HʏE=>\\\u0000\u001c\u000eTǀ|cҎkIST!\u0006\u000e%Gu,%[IR'+#T}m3\u0015\\/\u0012df)`n2#\\M\u0007(CQd6fl\u0016qGv첵).Z&\u0004\u0013wI\u0019Te{\u0006JQܕQE\\m`\u0016\u0006p`Ҵ\\z[v7OVo9ݜQ}$SSFMW\u0004d\u0017\u0006nyuя:\u0015\t*o[3 \u0003\u001cO\t\u0015\u001dFRJ0\u0018ոl\u0003+L+\u000f&\u001coE+d-\n@?\u001c^fE\u0016koo\\fyJ8zΰXmi\f\u001b\u000b-\u000eNw}OYp\u001ez&@>gݪHc.\f\b]7M\u0011z#f\u0006e\"g\u0001\u0005\\a@\\qyºJc\\3ܔ\f\u0007r'WQVE\rD|P\u0002L\u001f\u0006\u0010s\\h_h\u001e\u000e#9Z-\u001c\u0012T\u0005\u0013dL>˼!WS/bniA3\u0014\u0004\u001f.1Fx\u000e@Ǡ3UNN^\u0001nPOZd\u000et<jGLys=>v\u0005WO&-8ךshveSȉ\u0015`wPU_cař=շ}m\u0017`<<$+\u0015UV66d\u0004o88{η\u0011zkG}ڻ\u0010<<7\\\u0003jvg\u001a!5M!\u000e\u0018w&GmpfSgO3\u001fx?\u0017\nwZsLRq/~lK]QV\u0010:om<\u001fQ'\u001e\u001e\u000bR]AMXy\u001cu\u0003\f\b\u001c^ȩ\f$}! \u00079LHaH8\u0004\u0004hʡrTtD-*\u0015fY]]wuu[bgg޼ߛ\"ȹ \u0019I\u00057HR\u00167HB\u0006\u001aHudt\u0018\u001a\r\u000f*Ჲ=eJtj|\u0006\t#TI/\u0013W?{\u0005ΝO\u0011^'`v'$^\u001fE=7ITF2˵7-^'Z\"[x\u000b;\u0004[U7,Q\u001dyWr\u001br9E\u001b\u00116c\u0012\u0012y'I \u0017\u0019g\u0019\u0001IR\u0016m2\u0000ZQ\u0016\n{0\b\u0019K\u0018,^H/>>G@l`T\u001f=FZnZH\tѳ$\u0013m¯\u0018鵩KA3D;w\u001a\u00127\u0010\u0014\u0011ŏw^J<`i$M_x8wU-,\u0013/h\u0013!\u0012p\u0003bP1|\u0003\u000e*k\f_U;\u0000\u0004\u0002N45j<?>\bX_:]\u001f$\r%\u001dͫX+\u0004é\u000bMiw\u0000zz{\u00137`\u0013fO\u001bE5F\u0012ohX}\u0006fL}k\u0004%J\u001aq_b_\u0000A54WK\u000e'\u0017h?\u0003\u0014:lTHmm.\tm&\"X7rV7\u0014\u0007l̨b]r+\u000bOpK[{0Euwrfӵ\u0012FajCC\u0013Pk\u0003tMݻVw[FR\u000e(Y-VE\u0018\u00118\tP?)p>\u0007͛5\t#TtF%\u001e3\tqh\u0013k\u000e\r;`LVOp\u0017Zۓ.\r\u0015j\u001b&\\\u001eC<G\u0001\u000fPJqz\u0002Kmd\nA\u0016>\u0018ʡ\t<*\u0019g\u001b!r)J\u0015;ȁ\u0012&xK0N\\\u0016B&\u0016Գ\u000f$bԍ\u00177\bfpt\u001e\u0005(0H\u001c23\u0005ӲG1d?ź\u0003\nbVֆ\u0015|\u001a\u0016\\[w+t\u001ajj?b7h\u000fwJC\u001amm#b.\u001b^V\u0016\u0018B\u0001\u0003DR\u0001b8\b\u0016\u000eE]4J\r7LGc.\u001dX\u001ed\u000e/a&ڎ\f@顢\u001cz\u0004\u0016Qu\u0003ֈ4Tqi˽èb˕ 43~,y\u0007moθ[0 \nl}\t\u0004TCuLBt\f2Z\u000eW>\u0007Eh@+[Řy0\u0007=\nsU\"r];û](̏{\u0018e E=m\u0010a^2'\bF\u0010Kv~.Оm\u00130Oj(e\u0016sߺ\r\u0014Pk\b*!3\u001cIBЦ\u001c\u0019s4{^\u0014|{6k\\\u0005*\r}XY\u0014ǠD=A\f%$hǹWǂORV\rUBꯪr\u0018\u0015+C\u001aa6\u0010 \u0004K\u0019ԣe :Zڿu6&?W&\u0016k)\u0011.\u0015]%],lb\u00107MX][H\"}WL)RIrfr\u0003?AƁY&I\u0011~_\u0017IB${Xl\u0016ZX\u0007E&|w#؆`_v\u0010ߢf\u0013\u0011u3fm\u001389?9\n̟N\u0016Վ`jz1*.@\u0005爎܋`oْJ_+-\u00004α6@\u0003\u001a/\u0011DWE\u0010jE}HR\u0002\u001aDl;Y+\u000bz/\u0006\u00011Dѓ(z)\u000eoι&;.4\u0016aZ\u0015#g\u001csbZ+X\u0018Wi;<~n\"(\t\u0007M'b6!G\flP<^\\nM8-\u001a-\u000eaG+dyXP^s:\u00050q\r\\p3b\u000f\u0011W\u0015u.,R&rm\u0014\u000f#<Heĸ\u0010vQl.ˍJ\u0001>\u0014қs)lej\u0001(^ ,=/\u0014\u0018FV6fj\u0001;e\u001a\u0002x%Dk%!FW@a\u0001o2QTvs\u000f\r5h\u000e0B{UHiGCO\u0011zL'pbIq\u0004+'_1\u0015\u0018Lv\nQA%\u001d$\u0011[H\u001f~}{\u000f1fKٲ:H\u000fmWS\nëd}2w\u001b7\u0006\u0019\fj\b\u0012< \u0005O7i2G\u0003;\u0014S\u0016Wݒ!\u000f@Y\u0003sZ~\u0003\u0006*\u0007PƐ6x\u0002Q\u001aܡ\u0005/9i7cGHVf3R\u0001>\u0010K2\u0001jZxH\"Z\")\u001evHD}\r@\u0013}\u000f\tYJ6\b4T(P_(*C]miSJqOZg\u000fA(\u000fny8}wν37;?߇*x\"D\u00116H\u0013aeZ\n5K\te\ntE=H\u0003\u0015\u0003\u001f\\ƒ\u0011W8\u0001\r72\u0013ym\u0003]L\u0005y\u0018\t\u00031N<8͍@\u0001:>\u000b>6pӹ<AМ*쵮5M\n\u0012N5g\u0014ܿ\u001a]7cD!\\\u0019\u0017\u000fO6N(bH\u0017\u0012ֲ\u0019rt1guN'wߢ\u000eeG\u0018\u0003r\u0006ubJ1a#gi|\u0007Gc\"\u001e\r\u001a'x\u001e&YH;\u00044\u001f\u001c\u0011T\u00031}Ϯ;cV*ܲw\u0013f\u0018\u001a|H2\u0006;Rl\u0018{K*GZPg׸z\u000b*ۿ\u001e?ʗ\nד:N9\u001b\u0007uL7o|jBjE\u001bV\u0001QR!Ū;~;ZZxٲ\n(񆜦q\u0003E蠟V\u00067\u0011\u0017:bg3h\\yg\u0003.:O\u0015\u001007Ң\u001c\u001ab4=NHdto{<WZgH\u001cNR\u001eRZ\\sW*Zx ƻQͮl<ITs|X)c?p\\B \u001bKue\u0012|0|/a\u001bhB\u0003|樕sEGMsMd\u0016?*G,\u0019HR\u001fg[)|\u001f3\u001cCQ{0bIט\u0004%9*XR\u001eMU)+^\fP,\u001bp\u0019y*~uR\u0016Hw,r~L;_v\u001eN\"\u0013\u0005ۿ]/\u0013/S{̑\u0018Ͷ^\u00070X\r74㊈#ޒ{Y\u0006\u0003<\u0015mg\u0018$\u00195`Vs-\u000e*lۻg\u0003ri˕[\fLX#DEhgq\u001e!N-_\u0017c\tYPa\r\u0011!w|Em\"\u0007PD\u0018OU\u0011HSr5a+[\u0012\rm\nW\u0014h*¥{I/1\bYwûJy\u0005׸jk@p[z\u00023\u001a*Re\u0001RXwq\u000230u%B\u0012AŒ%\u0013\\NC)W'5꡵\n&\u001aF+U\u001e,\u0010\u0014d5gR\r\"J\u0010rVD\u000fBSDO]V[EסdyVӃ1,+Iev\"`\u000fWrwKa\u001dG|`\u0016%+TVRC\u001cF{Ys*Z5\u0000߬\u0004Re\u001as Q3\nj\u001fQA4Ӌ<>$.7$C$p\u0018\u0002\u001d\u0014\u001dA)hJewT\u0016*FmK\u0011g-lm*{{v\\ܲsJa>3_*ݑ\bہ>V5|WG_\u001d>RR_YL\u0004!RFjz\tS\u00045fځO\u000e2\u0011< \u001a`}I\\:XiZkR\u0005\u0016\u001dH*\u001f\u00074[(x\u001a\u0010\u0011X$u|I9̺\u000fTk\u001fVz\u0006l_\u001b׼gC%*\u001ew\u0005XR\u000bnY)\u0000N.9+wZ[E9\u0013ľW\u0010J%w\u001a\u0012p`Nj\u0015[\u0018.\u0011b|JOsdW,R~#*\tĽyFdwCp\u0000\u000f*L(8Oe\u0010\u0004lL\u0000˞)A\fvf\u0012Fʹ.\u001bKnd~A򥾺]Di\u000e\u001e(i]YʯJߟ?>w\u0018[侾\u001d7KK6w\"!eD\u0010p\u00005V*\r3V\u0002Ea{:KoEDcɾJ#oOU4\u001e4\u0010\b\u0005lTjFk,>{S?ýSk>Su=\u0007|j}\u0014\u0018\u0001T\nSU.nk.m\u0014cŮ)R\u0018xb\u0000T<\u0001TV*yÙ<\u0010+`RC;\u000eS^0\u000e-itp<\u0003ȗ\u00182\u001aIZ_0ȡVVKHWol9=f\u001ed\f\u001ejb%}D\u0018C\u0005y{sI*{ZL\b1\u001d\u0011r`n}+D\u000e_*\u0012\u0003Uz3}\u0002i7\u000779_kjxL+u\t\u001c;FxL.mmQ`sKz\u0014\bK\u0013#>&\u0006ޗ\u0006xi\u0004BV^\\s\u000e\u00053_XX_رC\u0017+ҭj|S\tkϽ|j|[\u000eX\f\n\bΆBL.?\\\u0013\u0015\u0012\u001fDCqߢ7nO(M&J\u0019O\u0019iݖw0\u0000\u0014\bIJL\u0012M,NCOYPoQRSTUVX\rY#Z:[Q\\f]x^_`abcdf\u0002g\u0012h#i3jBkRl^mgnqozpqrstuvwxyz{|}~ˀɁǂŃ{pdXL@3&\u0019\f֜ȝ|jWE3 \u000eתū}kYG6$\u0012\u0000ڷȸ~kYG5\"\u0010ŵƣǑ~lYD.\u0018\u0001оѧҐyaI1\u0018\u0000ڲۘ}bG,\u0010{W3\u000eqH\u001dvU3\u000fsI\u001ea)\\\u000bZ\u0000\u0000\u0001\u0003\u0005,\u0006\u0007\b\n\u0004\u000b\u0016\f\u001c\r\u001e\u000e\u001c\u000f\u0019\u0010\u0017\u0011\u0014\u0012\u0010\u0013\u000b\u0014\u0004\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-./0123456789:;~<|=|>|?}@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ac\u0000d\u0003e\u0001efghijklmnopqrstuvwxyz{|z}o~dXMA5)\u001c\u0010ۈʉq`N=,\u001b\nٖɗmZH6%\u0014\u0004ؤʥwog`ZTOLIFEDEFHJNRW]cjr{ĄŊƐǖȝɥʭ˶̿\u0006\u0012\u001e*7DQ^kyކߔ\u0004\u0012 ,8CNYcjnoldVD/\u0017\u0000\u0000\u0002\u0005\u0003\u0005h\u0006\b\u0006\t2\nR\u000be\fr\rx\u000ez\u000fz\u0010z\u0011y\u0012u\u0013p\u0014h\u0015^\u0016R\u0017E\u00187\u0019)\u001a4\u001b=\u001c@\u001d?\u001e:\u001f4 ,!#\"\u0019#\u000f$\u0004$%&'()*+,-./|0p1d2Y3M4A566+7!8\u00169\u000b:\u0000:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{||}v~oiaZQH>5+!\u0017\f\u0002؎͏Ðxpjc^YURPOOPRUY_fnx̰߱\t 8Ql»\u0001!Ceª\u00159^ɂʦ\u00102TtҔӲ\u0006\u001e6Lat݇ޘߧoX\\[VL=*\u0012b/f\u0011Mq\u0000\u0000\u0001\u0003\u0005\t\u0006T\u0007\b\t\n\u000b\f\r\u000ep\u000f_\u0010L\u00117\u0012!\u0013\t\u0013\u0014\u0015\u0016\u0017\u0018\u0019}\u001at\u001bf\u001cU\u001dA\u001e,\u001f\u0017 \u0000 !\"#$%z&d'N(9)%*\u0010*+,-./01y2g3U4D526\"7\u00118\u000189:;<=>?@}AoBbCUDIE<F0G#H\u0017I\u000bIJKLMNOPQRSTzUmV_WQXCY5Z&[\u0018\\\t\\]^_`abcdxeffTgBh0i\u001ej\u000bjklmnopqlrVs@t)u\u0012uvwxyz{n|V}>~%\rہrW; \u0005ϊ}bG-\u0012ޒēx`G/\u0018\u0001Ԝq_O?0\"\u0015\b۬խЮ˯ǰı²µŶȷ͸ӹۺ\u0004\u0011 0@RfzƏǦȾ\f*GcЀџҿ\u0003'Lsٛ\u001aFs\u0002M6+1M\u0004Z:{\u0000\u0000\u0000OX͙~ʹ~y\u0014~eL~j~Qc=9\u0000\u0012\u000f~|4~cl@~]̳~nf~C\u0018~لOiZ/gP8\u0014v}6q}0}>ϲ:}i^},~\u0007\f׉_L\u0003\u0000p\u0014K-~~,*~&E()D\u00079vyowy=TS3wI!\u001dD)J%OBvw\u0005\u001fN<i\u0006_ΝDgA\u001b]3w^|\u001e<~]\nbʀ}S\u0019\u000eW?CN\u0004<\u0016\u0019\b-Y4\u0007\u0010 BYpzS\u0001)j\"{%>64;\u001d>FVWm\nS^Di\u001a*b\u0004Pkp\u0005ة?\u0004%\"1#!ϼK`\u0015L<\u001bn-e2*+)\tX䥂C@v2l\u0010\fQ?(=0q\rMzǃIz7M\u0013EY;\u000bY\u001b@K (-\u0000\\U\u000f\u0003&>rI^2IM\u0017e;Ya\u0017\u0004\"VN\u0014,S;o\b_\u001d%\u001fs\u001eD;f\u0006Ǝ.R?l\u000b;\u001e0Dq>\u001d8zDKG)3o+&<4@n͗0\u0004\u001b\u000fE\u001b\u0016O94\u001f#Ґ\u0014nW9\fb\u000f\u0016_\u0016\u001f\u001d\u0012\u000f7}B2yːv/ąJH삻Ȧp$ȫ\u001bވy;Æǘfo虔F\u0016¨Ls\u0017I\u0012,KhW2!\u000f\u000eAjHE^τ\u0004\u0017 _w\u0019dlX\u000egg\u0007Ωr!\u000fjU)[\u000f%\u001aB\\D\u0015Cfp\r\u0005\u000e<_\\?k,.wȲi\u0000rJRݐ=>0+cvZ{\u0013\u0003Hll\u001cLVAc۠\f^{6\u0015oCҏ\u001dS\u001d\u001d\u0015\u000fمbȏ\u000f:sz\f\r7jP@Q\u0017\u001c;[\u0010wg\u0015|z30Uq`!P\u0007-~|\u0001X3+z\u000e2lIђ:\u0013_<aXS5\\}E^\u0011G\n\u0018XJ4\u0003^Ƭ\u0006w/I!5\nbn#FO\u0000`.ܙ-J\\!gZ0\n)\u000eݥq\u0012\u0004 A\u0004ßOkV\u001e\u001a^Bf8KĈ\u0015z\u0017a>\u0013p-FOJ*\u0013Yr(\".\u0004\u001d\u0013O\u0006'\u0018\u0006q\u0018ä\u0007frCRJ'\u001fdc~h!?`}WzBd;hѲGϲm\u0004T\u000bSAij\u00119< \nߨ%@`\u000f8xLT\u0004qė=\u0012\u001e,Mk\r\u0016$\u0014hJdx\u0013_r̰gʱhtG,K\u0007\u000f\u0013\u001e\u0003ytomVK0X?R<J%mq<UG]IX't9E\n$Vt\u0000\u0016ܛ8i(GT+\bt\u0005ԃ\u0005]\u001e6k\u0013N*\u0016d$m[\u001fw_L-h\u001e\u000ek,Ȭ\u001c&º\u0006\u0014^>=\u0010Џ\f]ٛ\ba`sʠ7\u001cg&\u0007\u0002Gr\u0015ŀ?>\u0004r&z`b>\u0013\u000f&z\u001e%sx\u001eb\u000fw&{~\u001dڅ]\"W\u0003R\u0007%c\"z\u0000D\u000e\u000bzA \u0013\u0018rs!֝=jcf]r\u001fmANJl$\u0000ے#ؑ\u000b>wT\u000ef\u001eGFF699<׵.'\u0015SZ\u0011*˺#-Jl.\u000e\u0010ZZx%m*|\u0004\u0003\r\u0018o\t2ӝ_T\u0011W\u001bK4\u001eeRsu33'jRF\u0002B\u0011\u0001Wl|\u0006\nF\u0011gml0\u0007L1\u001c,\fy+Hu2f;[T0BE{:qn\u0017t\u0010oT]ok\u001fI,\n\fLgV_R:Kϋ0dP?=\tvE̷փ(M4m\\\u000fTk׉o,H=\u0012Z\u0010w\u0017/EI-LQ[\f8F/g֖'$\u0002\u0005?[u\u0015~fghXjݚ-\tVIm\u001cKՀ,%ib\u001aQ\u0002*e97W\u001cK\u0007MYiHtX\u001b\u0018TBUD\u0002w-49#i\u0007ԗ/\u0012r]hGވ/\n\nlD2\u000bh%TTT*Fdw\">GY?\"[f\b\rr5\u0012\u0011ʊ4\u001b`\u0013TAo4H5rW\u0001S8X\u0013y;$Yr'q vUP\u001fV&\u0004\u001a4m/5LJE:\u0003S\u000e7\u0015Hvy.. \u0000kP\u0000\u0000XAl`\u0014\u0001\u0005\n\u0010,e:\u0002\u0014\fE$@BKr.!{A\u0006$A\u0014\u0005,CY[EA;|\u000bTJkU>41\u001baƜdcT\u0005.\u0003Us\fR&Bch\u0004R)\n Pd;ʟHbl\u0005?1;\u0003_:i\u0007^mMh9Ӝ+,x+(j3=P6u>a}&b\f(\u0003\u001f0=.\u0017À<\u001f2&m%u\u00069_~zL\u000f!\u001b\u0006S`(6͟>թV\u001d\u0006lW䨸m5ypg!2\u001e<\tPR%wC>\u0015u\u000f\u001c\u0002bv\u001fbF.0UK$K;؂P,!\u001frA5%\\v\"\u000e\n[2gwdxJ:_'Eښ_+^Cژ\u0016 I!\tv,V72UJLNITU\u0012KɎ\u0001Iy/\u001b\u000eR+=\u0005+(֨v\u001b6\u0015!M\u0011\u0012\t@PB%R-\u0013-3\u0006|4-\u0004\u0003\u0013)#ͯ\u000bw\u0012.ܘ<;\u001eb#;*>$eG\n>3\u001d\"\u001eو~AZ$xO\u0005Ux\f\u0002\u001e\u0015f𜓜x;٥Q\fh\u000bX(\u0007Zx=`d\r8bi\u0013d, ϐ!enZ\u0014\nb\u0001\f/޲І2P0~\u000b+1ba\u001d\u0011k\u0012\u0005\u0012tT\u0000\u0014\t?g)˧9\u0011\u000bС`\u0005.ޓ\u0019\u000f`>\u0017'4\\DRdPaxԗ\u0012\u001c?i|9\u001b\u0016,t\u000bĴq]\u0017\"\u0012m-9OD'E\u001e\u0012x>#B\u000ez6\u0005N\u001ek%tm\u0012\u00066BDzV\u0018Q\u0019G\u001cq,2\u001fO:\u000by{iH\u0000cy\u000f[]va\u0003ZT5 ȨR\u000b345N\u0010@qG!\u001bfYXr{3^\u001d\u0005M\u00167HX1e\u000e\u0016y87ҙ;NP\u00079tn/D=\u0002}*I:2s̋%\u0013\u000f\u001f\u001bG{<IedX\u000fw395Iot=ޓ*\u001d\u001f̸'\u001c(#^s\u0018\u0003{\\\u0015dYdSj\tV΢\u0017T>7\u0019\u001a\u0013a\u0018b\u0011\u0004\u0019\u0000TBm6\u000f\u000eۺ4JZmI\u001e׶Fהz\\FD*rEy\u0011\u001bք\f̣V-8ˉi#7Xm\u0014ZLW:2\n$Iⷱ\u000ed`U+\u0002z3\u0003\u000b8\"}Y\\E^\u0007\\Q\u001fܵ)<&uZ!\u001cFM)V\u0014\u0001\"ڟ}&à/\u0001\rď\u0017\u000f\u0013\u000b5\u000b\u001bO546\u0011PW눤0\u000bfGlEbd\u0017c\r'ƪr\u0004\u0002Ӭ[\u0007{K(\"M/y\u000e%\u00050=\u001bzFBx}\u0010{w6{Y50\u0003%\u0006,40R}ԓvT\u0004p>K@fR$7HU(\t\u0017/10f<,1BS>٨RI3#&&pa5j\u000519#yTH9cI[էj\u0003\u0013U̟~\u001f?\u0004\u000b+\u00147NzM`k|-k\u0001qJ\u0003}(Ҙ2\u0015SaӼGi ; b:`uǤayU}T\t2Ftm̔\u001e%Op\u000fuD\u000fU0m~\u0019L\u0013-_:qWg\u00180~huw-]\fN\u0019VrP\r=<]\u001bx;Y1iw@8,n\u0018\\(z\u0013qb\u000b!$zB&5dn6\u001d1Q\u000e&\f &\r\u0016\u0011CuЎ\u000ey\u001d#c%$7]w'z\\\u0018\u0013\u00120Lk{8<Oz\to%4P\u0002˗\n9hz͊$LmxEFGO$Dcn:0td#*\u0001vT2\u0017.q0\u00186\u0014\u0012vgAԡn3\u0017l'H:<@I˞8!\u0013mRS\u0012s^\u001b\u0018Ug\u0011f\u0000B\u000b\u0002u\u00112L> \u0010;\u001afGS\u000bFx¬P\u000e~Km%t3M\u0019\u0000\u0010ccM(bCB$\u001b\r_ J,@՜ \u0000\u0000\u001f%ӸZ\u001d;.6B)PT~~:_tHNIT\u000eScΤ5\u0011_3bO6-[o\u000b7$cn\b:zNq\u0013\u0018nE2\u0007~7\\NT\u0014\u001a'\f\"[fTT^2F\u001d\u0017&+\u0013\u001bc5\u001fr\u0002~ԕ(j\u0017\u0015l\u000b48mWDC]X#<\u0016n\u0001_\tT\u0003 45\tC0\rV\u0010~\u000bm\u0001\u000e&AGA\u0005\u00047\u0013w\u0005@w;\u0003Q8\u001a\u0000\u0006Q\r?d9#1yʕ\u0013q_eS]y|d\u0010*&6Q\u001430J(WG>\u0005H\u0014\b\u0006N \u001dv\u0011Ag+[o:\u0016y1ډGm\u0005U\u0006V'p\u0013J{\"\u0016M@3X\u0005|\u0015*oƙޞ%sfJ<ߔ[-0R'G\u0018\u000bi+\u0001+qNPF\\&XT~ykPx>\u001f\u0005\u0017\u0001~u2LX'P\rMOW\trة\r\u001bZ?qU\u0014\\+w>-q}y/sRQQ\u0013J\u0007@7\u001337K\u001aa[t̷E8X,Tp\u0005!PV\u0000K$`Κ׵bu~*LlBz-<R&,\u001f+?AP]o\u0003LKِ\f'y\rY?\n~t-\u0016\"Xnv\b&\u0010?\u0018\u0001VAG\u001c+\u001d\u001a7W\u0005hK\u0002DYZ%4\u0005YF\u001dg[\u001d C_M6ЅLJ\u0012!)\u00179\u001c\u0012!6\u0014-l?@\bW\u000b\u0012?t`k;p}\n\u0018P>f\u0005{\u0012i8Db\u0017\b\u0013Mp/ŲF\u001c_<`w[Uq.\u000b\u001aY\u0003!'i7\bL' R\u0013\u0006z$\u0010v\u0011]c-ީ%HY~\u0005ٕ\u0004\u000b鞀ws{)Wa˹ԑ`\u0017{[z\fϡ\u0017Z&\u0004\fz\n\u001e-\f\u0005U@uBP.8jz\fB{G\u000ftϤ1ޕq#\r\u001a\u0006^o2\u0002N\u0013*`D\u0002Z\u0007m\u0007錞c@QY@Oy`ŕ^ )\u0003H??\u0002s\t%J@f-H%\u001a{#}řPK\u0000n@u5w:=Y\u0001X9(5#p\f\u001b9#\u0010\u0012Av(~-\"]Qb'䠡y\u000f\u0005a\n'\u0010£\t+v\u001eO@\u001b%\u00137_*Z-r*~z Ց4\u001c!w\u0007B\u0015pG-q.a+c\"wmqk=WfB\r+\u001ek^0>np\u0010u5\u0000㞃= m]0o\u0010\u0012-1:ǒ~%u\u001di\b;pVO/a3\u001b;0\u001fo\u000eKܼ\u001dL6\u0004Ed@ZU%\u0011{\r^\u000bͰyOVNHLm\u0017u?\u000eu\u001eMBEQ\u001f1\\IُO\u001f\u0002ui@L\u00117Nk\\\u0002d\u0019d[i|lRܰ3\"r\u0015\u001eW^ \u0019\n19~(V\u000eZQjs\u0016\u0019f\u000fb\u000e5~N\u001el,\f$L\u001aAE \\\u0018Yv\u0016\u00193k\"*\u0011Ie.gj\u00074uDk\"*T~~g^\f~\u0018\u0014\u0012<|1\u0006cPx7\u001dkF84K(/A\u001aI\\\u0000%H\u001eG;'\u001f6\u000e\u001f`kK\n\u0019ZJ\b\u0015AFqKq$5GT#.a<C]\u0016szO9\u001a\u0015@yQђ-\u0019DRP\u0015\u0016\u001bGD{\bn\u000fo\u0005^\u001b7PvU\u0014\u0019\u0019vT_F\"Te\r^\u00069^9(Zi\u0011\u0011\u0016*J|1\"].g:ETIFzN%T|k&JlI3ʌ+\u0015r^qfS\u0014NM\u001aXe\u000b$v{\u0017ꢫ?IB--Oi0iXo\r葚T\\.%kR\u0018&-?(\u0013m=?~3Jncu\f\u001b/mS<Ð,LeH:\u001ei_+MSVa\fk@\u0000\u0000\\Ѓ*+w\u0003\bqDS\u0001!he\u001c\n4\u00049\"(h\b\u0019d}+ɗ7\u0019\u0012\u0011\u0010)T\tbǪԪhm`Yջ\u000bs\u001d<\u0004-,@͋\u0005SC\u0011gZwN\tC\u001fU\u0016c\u0019W-JGm\\QA]Q\u0019]h&D0\u0013Zvnw%0z\u0015\u001d\b\u0016MTXI\u0015:l\u0012<\u001a7\u001c\u0004a`\t5P`ݰDhk?\u0013\u001a(b\t\u001c?`Fg\u0016ű\u0016y\u0014=4EJ0\tGvQO4W\u001fd SA\u0012\u0003nMC\u0015\u000e\u0017\nұ|`\u00077ø_vYIo\u0015\u000fRyYqE,D;&Q\\B\u0002xWr\u0013v\u000b\u0016t\f\u001e\u001d[\\\"]\u001aUˋ\r\u0003w\u000f髐\u001a<\u000b|\u0001Mc+\rZ9(W\u001cZʳͰft~X)Ui?m<P\t;G-_k&ڞI&ML<\u0011::͹7\u0002\u0018K\u0001ƒKX\u0015ѪW[5P7Wtt\u001cbE6ռz\u000b~0iWűہi4\r[$\u0004ki\u0017l$\u0004VRc4ӫ\u001fGk~ʿYQ:ٮHbFG\u0013X\f\u000e~Nu.\u0016kf\u001cc`m\rf4걳qVP~:U\u001c#/bE7K*W0]q\u0017=$ܭ \u000eXQM52ymBS<l\u0005U\nZҸLeD׊=\f\f\u0005B\u0004kLBR\u001f\u0013Y^\u001e#zA\u000f%ڥ`r^\u0005\u0004'UIo\bFg>;1\fp't.t-SSUn;QY(sў*\u0015M8=\nBHZ#\rGcD\u0014S\u0004{\u001cd',U\u0005tl=\u0017,}*\u0012vcr\u0015+]\u0013(_\u0014\u00111r\u001bØ@?A[KDlv'o>=ԏ\u001b\u0007[\u0015\u0012?Q\u000b\u0014\u001eô\u0000n!ܘ\u0019eoiB]u3PzP'ߧ%\u001e44Qw \tL7@\u0002\u0012?;gS\u0015\u001dVjg\u001fohop7s\u000fy\u0002\u001eR\\7V%xL|\r3\u0000\u0003n|2Q|\b-\u0012Go\u0018t\u0016\u0017uV֘\u001bGk\u001f}fd'̐yQ/;^+b#&~ي2(\u001a<c 3;n`92\u0012[\u001c\u001eLqzt.\u0014)<lJan\u000b\u001fX>ɚp\u0003Tֆ\u0011)$Dru\u001b:5zj,|~0T\\~>\u0002*,6\u0013\u0005Y\n]7E9!\b\u000f7;au*\u00178Y?Ң#\u0000W\u0013\u001dfi\u001fA\u000f~\\\u000f\u0006mB\\$O\u0006wD\u0019\u0000hE16:_J\u0005qBR\u001b%\u0013*X3\u0012\u000b\u0018\u001c\u000f!\u001aO\u0012:\u0012`I\u001aok\u00142+}\u000eY\u0010'1\u0015%Y\rGPMJ{rK\fw\u001d\u001d\u0018_\f\u0017L&N\u000bNy\u0004\u001fA\u0000'\u0017ճmﺾ\u0002o4gz\"v;L\tje\u0006\f%Ɯ{\u0010NS6U'*\u0006@d\u0001jNc\u0014vo^\u0001=Bi\u000b795l\u001d\u001eAⶫ627ICky\u001cV_}B.I=\u0012YR2U^c\u0014\u0012<z\u0011+\u0003w@\u0013b\n\"\u00168ۺ?pGZ:\u0005Oȿ7\u0018ÝTԐI\rJ\u0005Ax߹rxn?(؁\u0000wh?F\u0011OG\u0010j{D\u001c\"LaWe\u0017}j w\u0006*62y3r3O(1;LSP\u0005\u0002pa\u0001?\u001cU}cqT/+~3Mҫy$=IQRS$@դ@&\\l+\u0010\u001ff\u001fEI\u00161kڸvx}_nϐ\u001aMfB\u0013y\"m\u0006\r\u001b9nQpϼ\u000bϺe\\I2\u0017\u001bGt3y\u0005)w%\u0002u$\u0018w[\u001a\u0005\u001a6\u0007o\u0015\u001e@&zܞY^Zw;<\\bm\"\u0011{3\u0004\u0017\u001e\u0002=\u0013s\fSNӐov(D\u000f\"idM\u0007֬Lใj9Z\u0019K7_<ېø974P6\u000b\u00050,R?\u001fD\u0001\u0000m6.Dt\u000ehe3\n>~o\\Ƙa\u00183\u0018Ƹ2@eU*Tlmcӱ\u0013\u0000~ x\u0018\u0005nNU\u0014)\u0019o`Iχa]P\u001bFŚVTC&ϣ࿋Y=d]/\u0016\u0019\u001c..FBXs+$=}b\u0016uM>\u0011RWm\u00116Ŗ6ᢐFX 5\u0012x{v*\u0003j;zv<_~\u0000AVUJϐ^IjQxｼuQo\u0015\u0006=lK_ՑEkZ\\4sqU7vOa J?\u0011Q)4C\u0014^\u0019\u001a\\\bk[{3y~\u001aM|J'g\u00034Ay,$0( \u0005jHl:Q\"V҉1X&e\rs)M\u0005Z(W\b\f\u0014|Ϲ\u001a\\88&tcpҔ\u0014a\u001c͔\fCC\fGU$^fb|8u̸\u001d&A֍\u001f9ke\u00177;\u000e㥦koAv\u0003Տ0o5\u0011y'\u0001\u001b<!HP\u0012\u001f4\u001d|\u001ayC{_2elTr\u0002s*\u000fIdg_\b'\u001d\u0003V\nFv\u0006z|\"\u0006ƞ\u000eҩn\u00042=3[\"st\t}N8`\u001e\u001f1`Xi\u001f]x(\u0001U2\\o[v1\u001bd%J\u0016OO&rؗ0\u0015ܵ9\u000fYx\u0016ݨ\u0001 \\\u001eD\u001fm]=Hjovfd):t\u0019bdH9\\\u001dϛY\u0012\u0015?8\r<%}dVەhnuӻkV3+(+$\u001e-#Ջ\u0002QҰ\u0017ЖX@h-Nd$\u0015a>M3\u0016q\u0018\"\u0013y\u0002$[Y@SgÓ=ݎ\u0014P1)L<d\"dr\u001bՕsW\t\u0001DJ\nt\u0011b\u0011\fcj\u0016*!Aq\nhG|3j zO\u0000\u0013\u0001\b\b|\u001cN\n\u0019\u0002*π\b%2#\u001eǓH\u00167!\u0006\r;v\u0000';\u001dO~hĥ%,v6BբTxDv\"L\u0013t\u001fï\u0005K\"N#\u0006.\u0017ec}f˺\u0010\u0001d&\u001bT\u0013R\u0014AS;Yq\u0010!\u0004E,\u0014AAm?~\u0010[7\u0010\u001f[\u0000\u0013>\r\\!B\u0005;U!)/\bC$N$A³ueuU},3Y'/Jc\t.8_[\u001cO\u0002\u001f\u0015N-<\"NawG\u0013\u000fm_+yj~P\u000e]ſ^\\y\u000b\u0010\u0015X\u000f\u0018\u0003,r-\u0014|\u001f\u000f㒒ܳ\u0019<\u001aL^T},^eDR,nkqց%|\u0017r,!gJx=~p{\"\\ee\u0012EN;Þ\u0000=${q\u0015@Q_\\?/иLe>u\u0005#Mp'Yn_e<\u0016q\u0013㼅Ra8p\u000f\u0014LB=(YK\u0018\u0001[l`B\u000eK\u0006B#4;c;HS\u0019^OA\u001a<J\u0011~I4,$\",B\\HV'\b&\u0004fಀ/pO_*\u0006__#&l\bWcK\tBZ(\u0014|Zb+|KpT\u0016\nAr3v\u0004*>\u0011>Ʉ\u0013x\\+0lkOԼ`\u0000Fcfup.wl\u0018\u0016CnKJIi\u0018]\u0007&\u001af\u000f\u0018\u0003XPA\u0005\u0001n1\u0019کFTKBo\u0012\u001bI!\u0017ӮZ f\u001d)~X\u0011hy\u00179\fݨOC\u00035\u0015&|T2\u0018Ӳ\u0012nSLB\u00155eD0:\u001eyP;\u001a(w\u001a9mΪnWhKu\u0003{`\u0001\u000ew\u0019k\nkH>*\u0002ڲ\u001e1\u000bwp5Q݌$\u001e;\u0005LvvJ\u00021f3n*\u0007Tg@oO#9\u0011|}?V0M5\u0010.\u000eۀz{\"\u001a\fNK?C_$\rP&B̆e>(\u001cq\u0001Iu`|\u0018o\u0015\u0012b|\u0017_0l2WꂝsC\u001bܴLT\u001dI\u0010a?f(/+\u0003PIwB\u0004\u000bWhgH\f\u0000\u001eEiŮ(G6\u001c\n\b\u001c\u001c\u0002\" \u0012\n\"(\u0010\u0004H2̙dfr\t$\b\u0007xZE\u0014\u000fP>ţ\u001eC\u001f~\u0019\u001bE\u0017F\u0011:}\u0015<\r\\{\n%\frH\u00136N$(߫Nᷘ_%1]2:$\u0002o\u0017-8ȥ \u001fI-\u0014qt;'kTjJW^}k\u0010fQU\u0011r\\u\u001a\u001elN\u001dk\u0017Hn᫂H*\u0006W\u0007\u0007d6\u001cM2\t*{\u0010`\u000eV%VR\u001foJJ`+\"yO|s86Vy\u00128\f:+\u0015;9\u0002ɨ=.qq\u0002ѝ=ɥ\u001f^\u001bӏw\u0002ldG\u0019;<bSh\u001c\t\u001e\u0000\u0007(%]\rN}uAܹ\f`MV\u0012?g\u0012=&o\u001a:R(tWS-{66CS\u0007UfoEIhzE\u0013\u0017'ܜ&\u0005Q8,g\u0001]-2t%F@}S|QJĜh&S콧b\u0003or\r2wq|o/$\r\u0001Ĭ7Aң\u0006\u0002I\u0015MXIc>f\u0011H^\u00072\u0010`zBȳ\f\tŞ\u0003O*{M2MoR0\u0005i:T\u0006~%$9ED\u001e~cj<\u0017}\u001d\u0005${.-+P]c=Vzpwz\\S;!?\u001dC:GFIױ\u0013qY\u0018\u0016Ş\u000b݇>;\u0001\u0003\u0016]mS)yr\u001fEz_n˕\u0015aI\"l|s\bG\u000e\u0001\u000fvmߵ\u0017\u001d_7\be]֭>Г\u0018U)i\u0005:D΂G}V W5*{\u0018f?\u0014\n($p\\)9D$ZYr|(4D܁OH\u0015ʳ\f;ܫv۱jxLr_r\r;Wi\rnV|\u001b\u0013Rudܦ\u0000;@\u0012YN<qIȗscE^M|Kƿ6\u000f#Q쀫Hl6\\\u0006\u0006r\u000b\u0005\u0001\u0006EjJ\u0011K\u001d-β+\u0000x=j1\u0003(\u0003~ǒ)C[\u000fvQn1\u0013\u0018򑾪\u001b\u0014xV\fa\u0012u\u0000I[\u001d8\u0016m\u0005YGe\u000fLV(X/%W}%\u001c\u0013\nM]4\u001fǽAߗnװ\u0002Q\u000fԈXtGdƇD\\wQyR>l-QnJȲc/14\u001eC:'K&̕BOJ\u0003{ߴzfsW\u0012|F-q\u00022\u000b?}Y[pXdY<\\v+\u001eM{i\u001fr8~LJޯ\u0011\u0017\rvlL:\t?@\u001b\u0003\u0007o\u0013\u0006[g`}>?Ur\u0017ǛI2L\u0017k.}Gp\u0019I8QRV%܂L0/\u000fPU\u0013E\r?ɹT\u0016cۼf\u000eHs\u001a^QMC!)\u000f$\f;\fej\ruIy\tW\u001c\u00186#LMi9Ħͱ\u0016P*\u0017HʘF\u0013g]m\u0010ߝn+|X$Z6K\u001b'\u001eOQ\u0013Jq \u0001\u0004\u0007m(B~ljSuZ\u000bť\u0003bhWP\"z@U\u001eV\u0018\u0011J΂\\,<\u0002\\HA\u000b5\u0016\u0000Oaf\b\u001f΍C\u001875O\r<x5\u000bM\u0012KQ\u0006e%Tfʤ6\rS\u000bsFtTOUt(\u0005\u001c2\u0006\u0010[\nES!.?Ӕ#C:[6$ߴR2G[DUcbDx(M<\u0016}|y%\u000f\u0014}ђ\u0018HmzyEy)9Didh(C\bpKo\u0005Y9_\\niQsƚӮkX36R7U&\"cT4Eʈ0X,t\t\u0003:T/>\u0002Uݮx\u00127F>Q\u0017L~:ʥ#][eTS2%\u0018c\rÆ\u0006~EW\u0019\u001bg9\u001b\u001ai%3W4ފ:}޼0_\u0012X|\u0017-ƣµVu\u001a\u00058H{Y\u0016F\"qĔ-F95\u000fE\u0001!\u0019L/\u0005\u000e3zL\u0007w@\u001d\"\u0013FRm\u0010O\u001bQ&[#\u0017\u001dZO/x\u0012ˤr~9T00bܬ\f4P\u0007ߋb>_nMFY%<ip\n;Rx@\u0017|q\u0001j\u001f#lj?Ap\u0002\u000fe\u0000\u0000[ۊx{\nsHt\u0018-bM#t8f5}sc0f0\f\rCcBKRmcEkץJH[ۢŚ<!)NoO\u0013CI}52\r09\u0018tMب\u00167B\u00150؋\u001d0zD\u000bK\u001eYeRUJ\u0012\u0016ѐ:N:\u0015:,#\u0012D\u000e~6ž\u00104o1l`q5XU5G\"Z4tX\u0011 \u0014\u0011\u0013\u000bc\u0004Vu\u0012{\u0003_<9\u0015\u0007SN\u0004}h%{nԾ\"V}V\"Cw}t\u0012)b3zFjoK\u0012\u0007\u001b\bj2'Q9\n]\u000f\\Bȫ\u0015r1\u001b\u0007.8C|\b.x8~pGm\u000e<ϰ\"iS\u0005˨\u0015\u001dڠ\fu\u0017[)Ek+WE8x5\rqg<k~[0\u0002n&\rˊڮcAa\u000bJúg\u0010\":\"].f\u0016f5\r\tRuBTu6\u0012u|;\u00134R\r'hN\u001fp\\@I\u0002!Bq\":*pX'%O$K#(\u001c\u0005}\u0015\bvW&$nx\u0016TeحkU^Ik\u0012Kl\u001c\u001cY+H;\"\u0001^\\#G_KmR2\u001ayfbI\u0014-ب:ݐ$;8$N(Ӊx\u0001a\n \u00041\"*.d8\u001b>MOaN$ʡ˖~\f&($~\u001a>\u0010tBM%^i\u000f\u00153ϐE\u000ef8UB\t\u0000\u0004\u001d'\u0011`-\u0017icIaͨ+\t\u0010دR=ZȾ\u0018Ł\u001b=5\u0006U#5H\u0017\u001bR\u0003>njk\u0002y/\u0012s6\bH؃E\foLy\u0007\u0015CG/?QE%FvMMz)=ZB.\u0015ϡƋ/3O\u00048\u00035\u0017&Y\u0017\u0016\u0011Kլ(\u0017ST\u0002 eҝZV\u001dx'\u0003xaV4Ë\u001c*H]z~h~\ri0d\u0018,K\u00128CZy{jC\u0016F')\u0012b\u001d\u0012|x\u0015NJ>V{0e#|SE1b狛*_\u0017R\"\u001e\u000f37\u000fBoξ(p3\u001b_\u0014<ݥ%\u0013\u0003-tɫ\u0010\u0004\u001bBetƓ\u0018px H\u0017\u000fuRuɵ\u0007)H?m\u001cf\u001b@Iz͂qrgM_\bD|\u0006Ce\u000e\nӯ_\u0015wCՄYK/Ԩ\t佨/Y0y̸\u001d7.\u0001]*ѳa !d\u0001[m9\u000e\u0001#{-;W\u0001[\u0010\t\u001c\u0019U$mb?ci\u00063ؘsq6\u0001ĂT\u0003\rt\u0006\u0000֠}\fdl\u0015v\u0007{\u000eF\u0003yt/ټt̰K\u0012Q8\u000f\u000bN\"4ʻc\u0000'׸Ns6I\u000b<fWϚvЕ*҇T \u000b\u00139\rI#{\tmVx@.\u000b\\EyT}W*fҿSѵ:'hPofħ/\u00057n\fu3֭Fcȶ\u0007T5\u0013yŴѪ\u0001\u000eLiӔ%v\u001cI\u001fG\t\u0014\u0003ɒ3m?PH-k\u000b;\u001a?vbkk\u0005Չy^4o B\u0013\u0011[\u0002*Bo\u000eR\u000b9^FtbIydW\u0002$ګږ\u001cNT3VYzl\f((\u000fm\"Ua.\\vzC5H8H$?sZ\u0007\u00196=:\u0001hhB\u000e!É8\n`,\fg\u00146$cN!Lp<\u001db<\u0014\u0012Nz;\u00050\u001fy%\r)\u0007\u001c\"\rDB@\u0007\u000b;\u0017.a$G=W+vF\u001bv-|d%ݿǁgOŨ\u001e;$\u0011KFlbu#^$(b\t,jdM[skxv͆c?sBflSkMe͈Ly\u0003i\u00143TZugv#\u000eV'{\u000fF,8+5\u0006%\\Y`kY o\u0004C,VQ\u000f\"Bk5Wjؚ\u0011\u001d\r\u001eaxhk\"\t\u000eAƛ/d\u0017X!\u000fxJ\u001d\u0018\u0002(}~&\u0014|\u001d\th?\u000e.\u0013\u0004\u0007XS\u0007\u0002\u0000qX}|\u0013\u0010#Cic\bhK\u0007\bVF @ dw^NH L\u0011\u0007\u0015\njkujVJE)\u0016swm^\u000bVQe^*\u00177cSu\u00135.:5!{3A/u@\u0005v?aDUNCkH2)\f1z%9U鱛\u0001v򹰗!k0>]\u001b[#?wsb\u0006,4U\u0012\u001f\u0015_\tf)\u0010Eď*\tuä6\u001fG\u001ao7\u001b6ɵ\u001d{\u001f'\u001cC\u0013Ga+RUA=@5\u000e_rgs1OUG*\u0016\u0010ʚ\u0003O\u001e&Q͡\u00104%\u0001\u001cnlc=%Z\u0011 v\u0005Y\rZeਝ\b4\u0006?\feC\u0003`\u001c\u000b\u001c_wv\u001fĦ10\u001bKB\u0005\u0003/*\u000fBrv\b4\u0007όw\u0007M\t0\u0001\u0018\u001cr \u000e`$\u001d\u0001CܝGa6;g-\u0018N_\u001b\u0004&ɰ.`\u0018\u0013\t\u000e\u0001\u0016`0M\u0002/s\\\u0014PMf`p3\u0002\u0000\u0019\f\u001c$\u0002\u000eA7\ti\t\u0003c(y\r<N\u000e6\u0000e/\u0002\fcPOjm+YЪ\u001eCz\u001fXa-\u001cT`aot\u0010t._\r,q\u0014gOI]@\u001af\"\u0005\u0016\t\u0013?4|T]T7[\u0018r5+\u001bD4UffN]Ϭ'MddY%A'\u0015-:x>\u001bjӍ\u000b\u001b5!UiMSD-rBFL&\u0002\u0014^\u0004:O\u0014\u0002F\u0017-T\u00174w\rT3c\u000bq]2\u000fR\u0003\u0019d\u0016/3U\\;\u0006?Up=@b\u000f\nTYRJ3O)*\u0012+\u0000\u0003\u0002sWu.\u0007[\u0017L6ǼA. 귒\u0013h\u0010oN_=C|HW\u000f\u0012\tGz}\u000e\u0005w\\2h{\u0019?U\u0016r_ס\u0007,[<\u00174\u000eDmD\u0007〷\u0001\u0014\u0012C/\u001c\u0002Fl\rMr\u0001_򑹾g\"P\\TMIiDw\u0016$=`\fIӐ\u000b}\u001f6.j\u0007Yx^h}]\u001b\"\u0007]l\n\u0019\u000e8\u0001\"ӽ΃ǐ\u001dL\"Hڝk:^֖T\bm\u0017\u000e\u0000.\u0002\u001b^@1\u001b~qxTlU\u000f#U75:LE|4&W25exz*̖̆;M0do^lpmaIS7kD\u000f\u0013#'͊$\"lL\u0015?b\u0003AD\u000eINmEh\u000b8Ԍ*\"vұE\u0011\u001c\u0007݌5\u0004Z5\u001d\u0002\r`z\u0013~\bx[M\u0000N&a\u0000|b\b(\u001fǁ$ch\u0006\u0010\u000b|c\u000fq)M_Ɔw>bSО$\u000b\u001a\tDp\u0017\u001ez!G@\u0019o3\u001e\u000f\u001ca]\u000e\u001bPnN2);K4 U\"p+q\r7b\u0018\u001a\u0014L\u0012ay$\u001f04iCc9(6>E3a{ R䏡0`?s07y9'`Lq\u0002\u001f`Sc\u0007L\u000fr\u0000&MP.ڽ\u0002,_ru\u001e\u0010\u001b/F\u001b=܏=1ltŜ\r9>1lם\nKX_\u0012t+\t\u000b=\u0004#ثL\n\u0014uuW\u0017K̹\u000bu)F@\u001bjR_$\u0013YuBśGbQl+$\u0014,o8ql\u0016g\u001c!\b\u0017)\u000b\u0014n2\u0002Qή\u0005\u0015U>Ytw(^\u001d'\u0019Y\u0015\u0015\u001d! %GU9\u0000, &\u0004>YcwU\u0014\fMj\"\u001cZ\u001bo6VWF9\u0017=al\fm\u001fy\u0012nqA/\u00162AI̐i\u0007\nqAN?!9\u000eNxlbO{eiYQ̶>SZ\t.&s\u0005bj?1\u0019\u0004_\u0010ǡPkٟ\u0017\u001e\u001ax`дY!n6fVJ\u0005?ffon0\u001b6l)7\u0004BuyMAѢ&m>>Nj#4J%&|\u0010\u0014\u001eE]ۊ:i2g0io*6zX\u0013h\u000b+҂\u001f3;1\"2ҍ+O?Kja\u0019\u0000\u0005\bY|nMH\u0004pA/LsI5cu*ΐDx!W\f{|m\u0003pq%qehrYbBt\u000bM7uA-\nw%5,x+\u000b\u001fz!Ί\u0001}\u001f|%wpȩx\u0005e\u001fXx|Y\u001ay$M\u0002}yA\u0012z5\u000f{+=\u001a}5\"6\u0019~{άq~p^Q~Md\u0019~*X~,LU~S@~5\r~+f2T\"P{pUIp\u0000<dG\bX]'LzJ@ς\u001f5)+gI\"ۇ{\u0019~\u0006oec,dX\u0016؈\tL;o@}5^E+\u0011#\u001a\u0016zЩגoycơzWܝ\u001fL\u0004@E5+\u001d#NzOoK/cW\fK՘$B@W|5%+׊\u0005#xAqzt&oMɜ9clW\u0017K×@V\u001f\u00005+@)#\u0000qhf\u0004j[Ű1lmPʪnpEХip;\rs\u000b0Xu'xz\u001fr{qDof\u0012p[ԯ\u0002qP䩪sNE\bt;=%v15\u0006x(\nz WW}\rq(vsfv[wLP̨Ox\u0013E뢳y\n;Nz11c{v(_| ׊b~mq\u0007C|fLo|[y[|P\u0003|Eҡt}\u001f;O}1~/(~!Ep޵\u0014\u0014f&Bp[Q/PtہgES\u0018;P1ƀ(Ā!ހp,Rf\u0013O6[B5\u0011PcE`;U\u00051*)\u0017\b^!Hpy`f\u000b[>f\tP[\u0010AE;Z1ٓ0U)Fj\"0΂op~7f\r![BPY_EE;T\\1撠C)k\u0012\"dj\u0015pmf\u0017r=[M,1P\\ǑES;`Ћ1')}\u0017\"\u001cΡm\u0018fni=pkqr^mt\u0012olVur\u0017X wtD\u001dyw'0|Yz>̾jqźjlr`nt\u0006pu0rnvgkbtgwWIv~y\u0012Ctxz0b{x|bh|~j|l|^n|~pp|j\\s\u0017}AVtu[}Bw}0\u0007z~l;fׇ\ri\u001b\n9kD\u0016mh5})oviNqꂿUtX\u0003BEv=/yVǧeP{qgi卞|l\u001e{nohLp(TsuSAv@Z/ryX\u001b_d\u001cִ2f}\u0003}hƖ\u001aMk\u0010/zmtLgdojT3rxAKuI/8xσ[c&\u00125e[}gܞrQj.xylfoDSr\fd@u\u0012/\bx\\\u001dębp vdܫg%iwy3kyenbS\u001fq\u0013@to.wU\u001aad`R\u0019fWh-xkk\u0007emn)Rq\u0015\\@?t@.wZtf4uhvjxx\u0001m0xy\u000eosekz.qR|{itP?|w\u0014-~zK'rp{sqԜu#s\u001evFtgwwtudxw*Qz%x?E{zb-}|Xpzr'zssj{@(t{vxv\u0005|\u0003cwy|Q\u0007y\n}\u0004>z}-R|~H(o\u0017Ypq݃^s=uPt;bvSPPx\u000b<>Ay-\u001d|0\u0018m{o\u001b\u0004pzr\u0000t?s^auQOw+T=y>,{¹luSm\u0000oou{psGrla\u0001tqO\u0010vk?=txj,{\r@k\u000bm\u0016ܖnlp\u001frxqؔM`WsNuȌ=&x\u0015,zj׫4lgm\u001comqq0_s*9N uI_<w6,z@ja観k)m\\|2nq)p _<r`Mtړl<wJ),zy}!eu}Dh,9}j\u001c}lpp~.o\u001f^~qL!t\";w\u0001+\bzU{\foKj{ipϒ\u001b{r>\u0013|2so|u\u001d]}@vLO}xT;\"~z-*|Ly(x*yyr\rz$y\fgWT\u0007\u0002a\u0015ˢĮkTd@D\\dPPp-HG&]30;s\u000fCg(\u0002 1DE*n\u0004\u000f6ܵaz\u000e*&\u0007<//6\u0005\u0004\u0010\r\f\u0006\u0017O\u0003?Q}0$\t8\u000b_{\u000e[w\u0012 \u001a/!f\u0018Umx\u0017rI\u001dWB\u0003\u000e5(\u001f\u0010)\u00032\u0006.$\u001e5Uo\u001b\u0015}Z!OO\u0006qm\f\u0003>\u0004>P\u00013ĸg\u0015|\f\u0017\u001d,X񦁓`S$>BG\fDǕ\u001fu#i#\u0002܌-`\u001dxJ!w\u0002\u001eم:(\u0007`[HWeQ2UFD`|\u001c:Cd\u0005\u0007\u00052\u001a~Tv\u0013\u0014kdEeUb2<o]\u0018^j\u0012\u0005j'{\u0016@sJɻu\u0006iWŷ\u0000oW\u0015s%PFUV\u001d6\u0013[f\u0001\u000b\u0019ru\u001bOCU(5?\"//b;\u0014H-O\n\u0010o_%\u0005{\"b\u0004Hk&9q\\W:r\u001c&\u0019G%2.i6D1%~F+~ZC?\u001d8V\n2#⮪\u000bui^#v\nNL\u000e\u000e\u0005؏SEZLnÖ`\u0015=l\u0015\u001dva\u000e;(>̽\u0002p ʠ\b~[\b@Qd\u001bF!7H\b\u0005$\t\u001b\u0002#dLt\u0013\u0011!BOK*G-iCrB\u001e.Ul\u0011mO\u0002>\r,B2W<\u0010+36\u00137ߛ@\u0013\u000b\u001d)۠&KO\r\u001a0ޏ\u0000O\u000e\r\u0016igm82\u000f=D 4FB\u001b[!AIb\u00014~\u0005Z\u0000\t*\u0010fz\u0017\\\u0004Ot\u0003F&\u0002ӝN&3xF\u0000[Hjz&3n14\u0010\u0002bM\u0007 zB!\r\u0006\u0017|+\u0018\u001e\u000b\n/\u0006hw\u0016{V\\lsTjg?қ\u0012۟u 깮D}û.5ʺ(wM\u0012\tұ=Lj\u0007eo(u\\\u000by\u001fPXƢ8\u0001p2\u0015232\"uh0\r\u0000;(3-y\u0006bݷ3\u001aWd\u0019sF@w\t,8#\u0019!H*\u00159)iF^\n\u0010P7D\u0004g\u000e3I33D_\u0005)\u0013J\u000eQNdOm2ta':=J.۱\n\u0011s`d+\u0014u\u0013u- ǵiȵ\\L\n\u0001kw/i\u0004&G1|91:H^\u001cgW@-\u0000Eif?QF?/Kv\u0005řMkz݈uN0:ӎ3BJ]PU@׊V\u0012V\u001bz\u0002\u001fDPC9>RTl{=\u0016EY^Sc\u0001yjN\u0013\u001896b~mwj\u001c\u001e[\u0013\rZ\u0016l'd}\u0004[YގM:t\u001eU\u000e9\u0015\u0015WI-#d=sѣS\rIKu\u000fƷ6i/JO{s{\u0017c@6o\u0007PU,'9cV~M6I\u0016Q\u001f1WwoT+mlF0\\Od?o\u001ai4M4MC%HfM[r0p[\u001cp\u001a|R\u0004/L\u0010d/_c8\b]\u001e׍\u0012\u000bYpFKM(\u001fE\u0010wo\u001e@\u0004jj\u000eI0/kad[H\u000f>|/ѓL\r\b|00SVRׂV2\u0017Cæ\u0010av\u000e4\u001ax,'L82\u0003'7\u0006&n&\u001d\u0004CĿ\u0016\u0018f]\u000f9-f]i<?h_]ǿ\"a5!\t+CQ\u0005O}D\u0003{p\u0016\u0001՛\u000fx\u001f\u001bէɰiX\u001b\u00061kt́K\u0016Mw:\u0019h\u0004_Id)[`\bm:'1\u0013f%s7^V6,0\u0004|\u001b33~+\u0016䔓*\u001bo؜wPPK\u0014\rW\r{W\u00170.\u001b\f^\u000eMq\u0006'\u0006r>{T\u001aa4EeNٟή\"V_ǔ3\u0004\u0012tf6\u00135\bҷ, jP\u001e6E\u0015x)ͻ\u0019USu@6M6d\u0017F\u0007V\u0016SˬGŦwƠuy@>\u000e.TȆVOdj\u0002?#驺sycA)w,zl<\u0000\u0001\bـB*7\u001aij,\\P#\u0012;}}~r4\u0012fxO\"Zh\u001fNM\u001eBe@(7\u00078,iA#FaN}\u0012qǖ*lf\u000bZ\u0000ۋ\fM2HB-7\u0002߅,yY#p9|\u001dqeےNYƐ*M}\"A튘6؈U\u0015,ۅ#||(qW,esY!MAǊje6Ç\u0017,}#5tPcjOf=_`rhT\u001fk\u001eHm=op2s(Hv \"zbtu5k#j\u0010l_-$nnSjpDHrB=tytn2ݑOv)\u0007\u000eyL |\u0003t\u0015r\u0014iIs\r^ٟt\u001cSuSHt#v=_.x02\u001ay)B{!\n}~s<xi'y?^WLySVzOH-{\u0005=:{2\u0004|)p}!g\u000b~s@|hg]\u0016ORr:GA=\u0014^2\u000e)$!Ur\u001ehn]\u001dRy\u000eGZ<23 )h!\u0004r7h/ۋu]jR\u001cRhGv:<ِA2v)҈ƃ*\"-=rYg<\"]2$R1\u0002GDT<2䆡)?\"Yׂr+0gȖ]/&\u0004R\u001c`G;\f<\u000342^u*\u0004څ\"|/j\tcj_eU᪹h\rK$jA+mX7pM.=tsk%v\u001e\\z`ij@_׭kU֩imKoxAq7ts.\u000fvp&(y(\u001f60{i[p_`qUrK5t7A<u7˙\u0015wz.yQ&c{V\u001f+}di$w\b_OwU_vx\u001aKkxAvy7͗z.ݒ|\u000e&̍\\}[ 'K~hꭢ}9_\u001c}AU-)}TK4}wAd}7Ζ~..~'\u000bv6 hc_\u0000zU\u0017\u0015{K\u001eoAO7ԕL/\u0019\u0013'A ӆhʉ[^񧞈~U\u000e0jK\u0012EACą17ה1/7D'r\tb!\u0014khn/\u001b^U\u000fu\u001bK\rʊEA8\b7͔9/AO7'!H\u0001AhZ^bU\u0017ؐK\u000f'A<g7ۓ$/L͆'\u0014!rh\u000e`JjNcQlyfniMypl\u0013fs\bnSurq@x u</\b{,y\u0002eEkgmE\u0006j*o\u0007lpxnreqdtRt\nv|@Uvx.z={9)bv\u0004\"evh\u0018wlEjx6wm0y\u0010doyR\u0011rz?u|\u0011.ye}Si`Yjc\u000ef6̈hvRkycngQNqY?KtS.JxL^يaɉYqd%vgfu/jObmfPp>t(o.\u001aw\u001c]^`cCcHlVf+;t)i0\u000faldOȯ>tsw[-wnw\\-_AMb0ke#SsShA!a7kO|o\u0014>#r\u000b-v0[Dn^aaShdL%rg{`j哟O\u0007n-=rfv-vm3Zp]­\u000b`܄\u0012cr\rf؝C` jRNn\u0002b=q-vBw~o`^q&cc\u0016rfBt\u0018i\u000bquk_wInN1y\u0011q<{\u0016u8,-}py\u0017\u0018m\u0013jynlp\u0019ptnRr\u0018p/q\u001fsr\u0015_;ut\u0014Mwv2<Tyx,\u0004|~{6jtnlufntvTpEwFor+xF^Jt8yZLvkz;x{+{}6\fh~4lj~F(l~LFn~Qnp~e]er~L:uM~;sw~+z\u0014f\ri\f\u001ak\u0019<~m*Rmo_n\\qǃKtU;\u0017w&+z@ɮoe~giю\u0018}k:lnH[[pʈ~K\u0019s:vw+yQdX\u0001fh}\u001fj\fՇ_S\u0007\u0002\u0000VNu\u00151X\u0004DY\u0000d0\u0005@\u0002/y{e\u0001`\u0019@=P8\n\nx+OpOT+g\u0011xjZ@c}9`k`cTnw?+^5j䤢\u001eT&o\n\u000blE\u0002x\u000f9\u000b{XfPg@C_[G=/5\u0016g4\u0005\u001f\u0014ʥ^E*\u000fz\t5#\u0013p\u001d&\u0003X\u0011sY>>@?n\u0017\u0004C)HKс#Eu$%\u0011\u0002`^>[\n(?`~^x\u00000\u0000_+OËv&\"YD>\u0003s5x']\u0019~-\u0007if~>NF\u0018\"\rP\u0003\u0006\u0000^\u0005OG#\fǖ\u000e0<7ӆ7\r:\u001cs\u0001XL!\u0007kݱ\u0005r\u001dx{\u00166\u0017Rt\"+@q*\u001b7k1U誘Y\u001a}(~\u001e\\H\u0013`\u0017J䞂\\\n52[{F;On\u0012ݦ\u0005\r\u001c*\u0016C\u001a{\u001c2H\u001e<N-S2UruU\u001fKm5\u001dų\u0012Bu\n}3!JH$\u0011\u001c#\u001fh^Qv0q\u001bUY:ʫaZ=V.}V\u0012Zfsy\f\u0010\u0007֧MP\u00168:x\u0016-kն(+\u001brީGSIЭO\u000bw\u001diι9јy\b&z8,k.$x=rm\u0011\u0015RM\u0012R\u0003u\u0005\u0012Mb;dw0y\u000b2֤T\u001b{\u001dWƊ6m|+\u000e8E\u0012C`\u000bGd]\u001bMm\"W\u0002rS禜D\u0001~A\u001aS\u0005\t+\u0012G6\bW\u0010#jnA>p\u0000uw0\u001bD(\u0017MHOB$\u0000v\u0007KѻX\u0000{\u0013'V'\f5c\u000b\n\nsh\u0019\u001d]T4\u0017I\fDGãTD(2BNlz9eB_\u001c ݫ.#JUbG\u0018\u0018\u0017ɰ\u001f\tP\u0010c36߅!3\u0004\u0004?o\u0000/˼\t4Ta1l-vK\u001f\u0003WZ\u001bApɾ\u0005<\u0011>\\Щ\u001bހka8\u0001Z5$G\u0018dW#\u0012{{\u001bߢ!\te8l&V\u001dlu4ʚ\u0001@ԸQ\u0007WJ\"\u0005\u001e쎛\u0017)9\u0016(6g\u001ef\fy'1?J\u000fL)b\u0011쭢l]4L\u0001kۘPpuﲹ)nCA Ŷ+2dEH'Hm&Y3u\u000e\u0019\u0010ѷkѽ\u0005ӭ1n]_Z<ڮRvӛpj\u0000m9G݂#\u0002\u0007j\u0010}d\u001bA\u0015-u\u0000ڠ\u0007\n\u00190\\C\u000e\"\u001f\u001edhK>م\u001a\u0001\u0011\bٸ:IF\u0014q\\BVhF'$[I&3\u0013\u0015BtK\\ D'`;I\f[\"%#N\\\u001eI\n|?a\u001b8+\u001fş3\"-\u0011A\b\u0010ש\u0016\u0002_ZZKO%\u0002u\u00056`X{\u0012\u001fcͯw1\u000b$+O\u0001\u0002\u0003\u0011M{'E],jz6+\u000f~\fQk\t\u0016a=_/E\tqbVk&\u0016S7<R5|m[N\u0016S<\u000bT[＇\u0014\u0017c֝\"16`\b\u0006fi+mԂ\u0012\u001cEh6=2%w\t\\Ww3/VWx\u001bGk\t(\u001e+K6\\Gk6\u0007ygfp86,W\tC\t~8\fyq'\rSk3vI\u0017ժ*/kffԛ]_M5Ɵ$Ϲv3\\2\u001de*^\\?\u0017|_\u0002\u0013cj1\u0012xڶ+\u0005em[8\u001d@Ńr\u001a\u0017\u00011\f346=\u0018\u001f\u001ev׶\u001c+f5R\u0006jW\u0013\u0010uM!\\7c\u0000{1\u001c'a`&y[8#H\b\u00183Ci\\OR<y0mOy\u001b3lN2\u0003'\\N\u000b`́QSL'\u0005}\u0018)R찧R3Iw('gV!pGJeضR.u.jO[GCd5aL!_s\u000ed\u000b݂\u0013F\\nMͳ&ֹj~*A\u0010%y\u0000\u0000\u00002[\\f\u0016-:HLeyby \n }s\b-j5+ڲkEZ5׺ֵޛc[GSJo\u001cŤ\u001a\u0000+\u0003unR\u001aƉoQ'j\n9y<i;MB]\nY5SA\u001e*bPW#\u0013X~$u2ξ\u001a/1a+` cv&L/0̰;t)H\u0011܄|E\u000791ݎjɆ'u/qvC|\\lWja\u0014\u0014\u0014C\u0018m^~nc\u0004==7Em+O\u0014^\u0014\t|\u0004vd,<8\u000eLO\u0016j%=\fY0o}ďvCBW[K\u000e\u0015&I>fg\\\"&]KOÑ:\f\u0005%ijeB>\u0001\u0007%\u0006j:l=T1e~/\u001aߪ\u0016g\rI\u001e0^Y\bV)\u0003<^ϑ%\n\u0001զՏQS-W\u0001\u0015\u0002Gpa\u0001θD8\u0003ߠ9D֑ՃXM'\n\u0005UJ]I\"mteuuE)-\b3`Ҍ SoO\u001e\u00006\u0002Ju@$ZZǚ\u001a;o\u001bam>݄92)@\u001bm{\u0002\u001d>-V\u000f|WU>r$\u0013Ӳ]\u001e\u000eqّ¸\u001fzEYuɔ\u001a>\u000fGT@\u001f蚩\u001e\\\u0001'}њG9\u000emp.d.@L4\u001cc&,r;b\rӂdlt3ݦ]Q<\u001eb-w\r\u001c\u001aN\u001dk\tk\u000b\u0005\u0007b\bK%\u0012\u0003H@\fj\"W4\u0007sf|Aa{8c%J@\u0018bW\u0012\\E':Ehsř=}9fǹTW\f!3ߔ% \fפԘ\u0011]YzĀ&X\u001eI\u001dk\u0019Wd\u0011Pي\u001db]9gbI\u0006i\f$ O\u00141wu_)xS$P\u0019)m/U\u0013I\u000b.m\u001cpsf5Uwl}oy\b\u0010h\u001c 4;=DU\u001bIKSD\u0003S\u0010j\u001bj:?\u001a2*\u001aw0P4\u0004o\u0012+G\u00184O\u00126jeu\u000e\u0010\u000b\u0001HW)ϛ=ݮȆs\u000e51\rok\u0019\ba\u000fIӽ֒Wo0%\u0010>\u0010#\u000e}?V5N_r\u0004}%7\u0014\u001a\nԼ\u001e{!`D}K_4\u0014\n!Q\\HҽzȔ\u0004HN>\u0014uA-\u0011^Ჰbg\u001a%+k58W\t#wi+q0khcuTT[\u0019`5Z[`J\t&\u0011\u001f-\u0010v**\u001ccs0\u0010\u0000:-7\u001fo3\u001cG(\u0018Z!\u0015\u001dd\f\u0014\u001e\u000bz\tQ}vx'E\b\b}aQ#*'vi\u0016Ʒ|'in˵Y;eR{E1vikY\u0018\u0015T2\u0006\u00174o/\u0006;K\u001e\u000b|O\u000f\t\u0010c\n\u0001Rr_T'\u001bU\u0018tKy\u000fγ\u0019zaL\u001e=\fzs#\u0016k)|O\u001eĀ܇:axim&&\u001e^c\u0019o\u0001Iѓ`\n\u001bW82K/ױϬ˽^i\u000f\u0001\u0001pu\u0016\u0019O:\u0001JD:W\u0015t\u0014G<Z2]uyy+0H5W\u0007?16א\t~u[\u00184')BrjX\u0005\u0007G\u0015>\u0019<8YJ]\n\fՄyiZP-|xm\u001c4\u0012rQe`d\u001cZH\f;4SX1̚`\u0011wpu>7<dE,]5J\u0002!\u001dT%\u000e\"\u0014\u001e\u00037%:\t-+\u00126\\wO1=zs\u0006[ITNX\u0019\u0017)bOIUq~JY\u0014鮦t ͆/?\u001aw\u0012U[j\u001b+ϖ\u0015QzUR\u001e'd(_\u000eXqBy\u0014g5mV\u0019e\u000eq}\u0019Jsg[\\[>\tH2\u0000\u001d<?\\`\u0002L\u00138\u0019n/j?*BgKߩd}d\"KK{\tLTka\u0007(\u001d·t=no\u0006\u001f4iH\u0003A-:s0J\u0019\u000bַYa<Sebv]\u0014\n\u001b%;8;2\u0006\u0017/+BMqvs$`ىY4/\\ssi iUcd\u0018U\u0005a\u000ffh6uaP\u0007&>%Cd>zES?+&e\u0006{\\\u0015Q>\u0007+)\u0011\r^T9ZPF\u0001\u0003\u0001\u0000V+@\u0016l@\f\u0005A\tB\u0004\nr3\u001cL2$\u001c$\u0001\u0015\bx *,^-\u0001ڷ[]<**R\u001fI\u001b<E|N\u0000B\u0007j*K=׌A\u001d\u0004\u001fua2%V\u0005/.RC\f\u0007v(ݴܥKp\\\u0003\tt!w-<\u000bar[fA72:%E;),\u0011Aj&%\u000ey\u001aޑ\u0013\u0005$\u0010xPME@\u0013AfW\u001fxxM%|zW6J\u000bi,oV^>npdk\u0015\fŻΫ\u000b\r\u0011:\u0015\u001fC\u0001>\u001dKXi<_TTՖqcs.JmZ\u0010E\u0005\u000f:\u0013^΄hsVIbm8tSX&^ a*Ɋn^\u0002\u0015m=A2\u0015s^\u001emICca|k`K\u0002{\"Y١:nf,ڱW\tx_n~\t\n\u0012!f睥#\r\u0005Aɧ\u0018o\u001e(u\u0006\ngįVg攷E)?n\u0002/ؠbdS\u0011u3Q\u000eQIB`\\\u0010C!\u001bd\b\nP,\u0003\u00192QC[P\u0012һn`\u001eRXYU^',|Y5\u001cG\u00174-\u0011}<kCf\u0014ގo\u0015\u0003ۆ3\u00007%\u0006R/4\u0018!=\u0011\u0014\b\u001ba'm\u0006fUgL\u000f(CfU]@::&\nwo\u001f߿D[D$<H׽k\u0011\u0019U\u0016*I#;He\u00036i*80C\u001d\u0000TN/h\u0005%\fuhv\u0014\u0011L5'ƭs*=%s+:V9˲O%(\u0007LWӖswn0~\u001e~\u000bI`F\u0005\b嵃v&K^U*^6U>,V{:T5zGFd\u0011\u0014x|\u00054Zٲ u'ʦ\"Ww[f^'0X\u0015c\u0011x\u0006\u00162rKJJD\u0005JmB|CÁ=55oc/\u0002h\u001aNL9'0\u0001jI\u0015.\u0000\u0005\u0011 =$!_3s^>\u0002pX0]S\u001fcԹ`gi9\u0005\u0011Q?+,O|ekk\u0015C)6bf!),M\u0001\b\u0018jQ\u001bZ\u0018F_\u0000Y\b[-ۈfiv&\u0006m\u0016H!`5\u0001oIxu\u0016d\u001eP#F\n\u0010P&h_2nnmM\u0010sC\u0011?w\u0000O\u0015t[Pk+jnA\t\u0005ǐ\u0000H\u001aځY\u0001\u0018*zל`\u0000\u001aL﵋T\u001fL0\b\u00191|w:44o\u0012\u000f(%\u000f\u0019j\u0010̨\u00025YJ_|\u001cf\u0018\u001cyl00DO+/.5T\"$8[g\u0017)T`MH?Ɠ\\<f\u001f\\o\u0013-1\u0013\u001cby^QEE\u0005*׺\u0002e\u0014U._3P}7&\u000f^l\u0015XxVM\u0004CG\u0016|\u00000A~\u0013\f\u000b%_\u001ao\u001eÀc`4]~rf\u001c5o{/DRe\u0005)\u0010R'2:(FQKLUDu\u001949%O\u001c'\u0007EG\u0014\u0007tsӺ|U[n\u0004lMӴ\n/8*;,a8sk\r~!!@)\u001c\u0019֧&Ñs<-\u001asZ\u001b2Eb\u0019Tb~AA\u0016}Dʺ0S{{Ga\u001co\u0019qB\u0017͝$F8z\u0016*d\u0001\u001d:ٟЕLza\u000f:Jea\u001eq\u0011\rT*1\"}!\u0016@k\u0005\u001a˳߬B/lEy~eK\u000e\\\u00125$\u0010O=hZ\u0002\u000e͓ނ\u00179\u001a\u000b`_ݎ[9Ĥu2B\\s\r\u0014u5=@Όp@\u001dz\u001b\tt\u001c;*+.Z\ba]1l\u0017RS\u001bo\nКrHY\u0011Kg<\u0013`7/|+4A*K֨81%\f-1w\u0017?Ɩ)r~K0;h\u0003+f\u000f\u0019g:\"\u001b\u0010&6)rp\u0003cyB6 b\u0019#&l:w>fިÕyL/\\Zj@\u0000\u0000Ν(Wڢu\u0015\u0010\u0014\u0010d>\u0005P\u0002\"Y\u0004\bd'$$ʗ\u001eV\u0014J+W>p\u0014G[^\u000eG\u0011ڻ2|M\u000b5\u001bkci{\u001eZJ\u0007bILF<fB>\u0013PC\bR7<]'wKÍQXb\u0015\u0012*\n\u0019$f»\u0004\u001c~\t^̈́:)]\u0003\u0007}\u0014pA(\u001f+RX\u0000zE;b1t\u0017!\u001c9ݠBj`\u000bd>\u000b\u0018!\u0007L7g\u0001h\u001d%\u000f<d:@dAC\u001d<@\u001b\u0005߈\u0003\u000e\u0012@.\u0000\u001eZj\u0003\u0003@p\u0011\u0016C䂻Q\u0007a\u0006b!\u000bMbqq\u0015zbە3\u000e;@A\u000f\u0014\u0013K$˰E\u001cN\u0015T\u001dۢH=jo\u0003n_a|1r(\u0018'mrQ˰lp;Ա{qe\u0000\u0003\u0002\u0013\u001c=\u0019^ՐYcI\u0002$ۖ(o%\u000b\u0000\\-\u000f\u001cKч޻\u0014Α\u0006vKW0dng\u0006XgIF~\u0019XQHl8'KrgJ\u001f\n*XcZ3}EٓDsjd9FK䛉\u0006J \rI1{V!xnK-e>7n\u0004ׅ\u000b_Qg1R2Ǽĸ:\u0012@\u0001n\\\u0013\u0002KX\u0003\u0002\u0011)'W\u001bIC0hݤ!XL}\u0001\u001c4\u0018l5 Vh\u001a2\u0006\u001d,\u0018\u0003?bLb#(sÀytk]\u0003:ibP\u000f_\"2S&F\f ߆*\u0011:/~5\u000el6\u0018fݻ\t\u0014Ӡv\u0013<NE\"AMB\u0007I܆=ӰD!5\u0017oG\u001d]Ml[\u001bUZ~$g\"HU(>(l1u;8q\u0016i7m\u0017L[@\u0014Wxl<Rs\\]1^>\u001fg\tY<#nM\u0015D\u0015yY\u001bZOEX;/C<\u0011_\u001a\u0013IfGu\u0005R\u0013O\u0003M++c7S\n4ƊaZ\u000fԃ\u001du\u0017\tMߊ]>]o\u000f/m^&=Nh̕\u0017\u0014.g*>d_$\u000e\n]koj-]\u0015wz`g`@XR\u0013\u001dSZ^6uV\u001a^\u001fog\u0018\u0011~XQ\u0011\t濮a%{s\rT\u001ap4{HLydW\u0018)YU&R?\u0000FD/'g\u0004H7yO\u0013G\u001e\nS0᪄g\r:po\u000e\u0016\u0006)-.XF:\u001de\u0011\u0000*di\u000fG{.㯙nw\u0011n.tY<\"`7d\u001esSC\b\u0005!\u0015x$g:SX\u00009\u001eY\u0015\u0014%r\u000e_']4K\b\f.\fq cYv.\u000e㏢\u001dM\u001crm*ADbW냊M1Dqby\u001e9mT'buq\u00157Or\f}yXK8`微\u0011.;\u0014~1K}wҭrB;\u0003\u0013ҏޒ\f&6\tRr*?j䆑l\u001fugIC\u0017k\u0016M|\u000evhZYHn8Vz\u0004Q3N??֫zGP\u001c5|No(RGJ[5&Hs)qq}^&2n:zǰ\u0013kFmP\u0013\u0016\u000403;7Ns\u0006i+Z\u0012iӍ\t^\u0012zs7Tm ,\r\u0001\u000fzb@\u0014\u000e\u0002p22{9\u00106ʄ/=\f4)c\b\tx\nt&8\u0002\u001d\u00173\u000eB\u0005-(;^SedSy\u00157\u0019yG^H@Es\b7<\u0007A\u0005Q\u0001|h[\u0015\\je\bZҎy1|i-<C^ow5p\u0001\u0016c\u000bP_\u000f<.&n;ˌpa[\u0016\u0001y\u0015y$۫j!\u000bѫ$E42˚v\u0018?ݴ^\u0007wnYg?G9cK+\u0005%<qWŔz^}NV]QvS{q8ڷu)?\f\u0014WV\u00141l\u001f%\u0005Wyjp0#>M']|k!3h{\u0016&m\u00055&[\u0004KiK%}UEk̀u\u000bhT[\u0012*\u0019Fk\u0000kOZ e\u0001 e\u0010v]\u001cG\b\fؼ;G\u0006\u0013LW\u0002\u0013[\u0014\u0006d;oo\u001d3x\b\u000f\u000e\u0004\u0000Y\u0001{\u0015\u0011OEk[@|l\u00012섐^򒼗F6\u0001\u0002a\t\u00029uUQ[Em'*uW\u0011A\u000ew:^\u0018WfA\u0017w:\u0004Rc$Ǳ9-N7~c\u001b\n\n?\u0005;A34VfO\f\t5*DvUe_Rqr_pM\u0006v]\u0015{қ[;f4(\u000bc5ڑGdxEjO\u0013-n\n|\fg8\rKٶŲ]{r3J\u0010(?ұqlu;S7\u0001qWA}ǰ=o\n\u001bn\u0014xg|GC\u0002TpTaH\u0017͗O0U`ll\u0018ڤC\u0012lt0jh~pڱY_,x',IUjn\\[M\u000bz\u001eDBb<Ô]T7S0Co}2%sF͘MQ\u000f\u0005\u0003\fś\u0003!7f\u0017\u0001Sѕ&.!mFk(+O\fOȏ@\u000bW\u00021fG\f0JZ\u0017-#=qb>@\u0006@\u001egIxFz|\u0003޴\\E=Yg6at\u0012Һ*SY5T9vh\u000b\t%2{}n}I90v zR\u001ff8kOʼ\u001ejVo:*xH3_\t\u000b6WWx4\u0001\\;5juK:\u0007:i\u00077rʶY\u0005\u001dAd\u0013~X:J\u00101<;e\n(;Msr\u0014l\u001fڪU[y5\u0002vw\u0001\u001c(\u0019k\n-\u0016\u0016Ol\u0005\u001cHWeG㐣\u0016݆L9sFp6i&xИp\u0011\u001f0C2}\bTxmCH#ѽZyڇm{\u0002+EAa\u001dWd\u0002\u001dVSy%ې8bש\"SLL\u000314$B\u0000s&\u0014\u0017\u0015Bj&d@Y\u000e?O+\u001082\u0018}\u0013-D^\u0010ݒD\b(PR{\u000f\u0007Ѭ.\u0000s!$4\u0010P\u0017ڣo\u001d\\i(#u\"D8\n\u0000:]C>6ڒ׶\b*\u001dm@1GQm\u000bl\u0005ìO\u0013rusg# tk\u0015-ۤ<v+l\u0004U\u0002w\n]\u0015@V99'3\u0003ի\t\u000bP?#0eDaS#[%\u001f\u0017\u0005LYƉ\u0004\u0004U\u0019U\u0005_n\u0017F\u0017η4\u0005F/V[&+;\u0012k+4\u0019e[D7\u001b\\~YCm[D\u0006\u0011\u0019\u00064M\u001cn/\u000290\u0010:/[o\u0011\u0006\u0017`K\u000f(\u0002\u0004\u0002\nTor\u000bM8FECwLhTl\u0011\u0001\r;=\u0018\u0002\u0007Lt^r%\u0012|TXNd\u0004R3O>\u001d\u000e\u0012^\u001eG)\ry\u001dۂ2b+PgDWB\u0019;T\u0014\u001c\u0003+4Qv{\u00149輵;!f6~/ė|@r~EM$,\u0004<`\u00132+\u0010\u000eoMҿ$ȵk뤆)<$\\nnu|LX\u0000\u0018+z-]\u0002:r\"Xꗺ.KW;\u001a\u0013YFC\t:A\u0017ǔ+IU\u000bu+U>.+͋\u0004;SN@]\rL\u0000U\u0017XKx6\f͑8=*\u0007U4^qݗۥ>S韒\u001d+Ż\feLsf\b\tv?m!'粈\u0006Yv0zْ2G\u001bwT1\u0018e{BH\u0012M,\r&fr(y\u001b)%\rP\u0007\fEhl%\n$\u0018EVD\u001f\u0015Ķ\u0001t\u000bo\u001f\u000b\u0013\\\u0002~6-\u0012s//E\f2\u0011<\u0014뤪t\f\u000f:mbpV\u001an\u001a\u000f(Q7:\u001eziZ\u0005Nl*\u0007\u000f3miИ`\u0010\u001d\u0004\rsnX\nU\\Пbi0^\u0019Kc\u0017=\u0018!!{pwpy\u001cKH&Ș/UD\u0005\u001c\u001dg#\u0007M@\u001f\u001d1\u0006&yf_sI\u0007r\u0017Ŕ\\\u0012\fBc\u001b7He\u000exXltbu!\u0010hI\n&) ֩rbps\u0016;Cu\fGFq\u0003~~c6RbO'l\u0019\"<͖\u0019z\r[T\u00020}5y \u0000\u0000V|\u0014EWrф\u0000\\2a\u0010\u0002A\bA\u00100\u0002\t/ɷW&a\u0013A\n\u0011AK]מ\u000bq\\kPU\"Jѻ?W{j#'rG^$U)~VHD\u0001Tup\u00047\u0006\u0001\u0007eÊ⚊R\"I^w0^+mOX\biMi-T5ȝ'N]~{e\u0000\u000br5Ճ-wA\u0011\u0015-\u0015VYF~\u0007UgBOJt8y0.{\u0012KO\u0019(vlJ\tuS\u00190փyk^?\u000e6Wc+\n\u001fCl]\u001eEko%ݼ脦\u0000g}<p\u0007?j~t7Q|/y\tu\"-Q߽\u001b\u0019{\u001fޥw\u001e\u0001iN1j2Fc߀9uTE\u0004\u001aڵ粎\u0019\u000bt\r;HC;o\u0010\u0004\u0017sTH#d\u001c}[aT*Ч\u0000\u0004ހGX;Ppi\u0014t$V\u0006.xP\nC_\">h0[[tVۃw\u0014,U^|}X?4:a\u0013<\u0013X\rs%\u0019هU)<@ZQ/[6\f.\t\u001d0A=fx\u0012Iҗ\u0007\u0013Ql3\\PB\u001aoJ]Դ\\>[3\u0010?\u0006,\u001cЛMOyIOi>\r'|\u001b2\u0019kxo6\u0015<Jc^|5ܲZz;*,1M;\u0015]\u0007U\u0001\u0005 \u0016DQ$6\u001f*ړ\u001cXz#UfZ,ku)jF\u0012R6:\u0006\u0012\u001a*hyY\u000e\u000epI~KSpMnQjm-+\u0005yɽM4q,\u0004t0L$\u000fth!f\u000b_yb\rqX𖠕@Fb/rhf\u0013Z`;k4<a% KEb}9v_Փ\rUkw3H/usk`Ǚ;3\u0010\u0002$B4\\+;\u0014jKD\u0015 Z\rFFv\u001dEu{\u0018\u001fqcʰST\u0007K\u0011k\nrS4,FS\u0015\u000fQ?D\u0006 \"u%Zi^,\b[U6\u000f\u0005Pw\u000b԰\u001e\u0002S7$\u0018\f!E.\u0012\u0005H\u001c7\u0019^ü\u001eu\u0014\u0006m[E^)@YMSP)'b\u0016^Eq\u0003c?'Fxm\u0016uym\u0019.͇$\u0015|OKb\u001d1cwWln~B\u000bXfOyǲ\u00022MӅ\u001dBQWci2 [\u001eb},1Ew^kb)k,]wHߦ4UmϪKc`C!Zʎ5ICW  fQ9Q|Uά2=-Id\t2_M4 /ڨ\u001fB>o\u0007y\u0000*Zo9XYi\u0016fNP?1k𾠣 *_B\u0002\u0011upֲB[\r\u0011\u001d4\u0006X\u0012\u001d\u0003φ}\u0007P\u000573\b\u000fd\"d\u0006\u001dٮ&\u0006\u0016<ăT\u0017>\u0016\u0006x4\u001eY\u0016\u0010\"G\u001fXF%Ngt2\u0014S\u000b8.hpq܏\u000e#~\u001e2Hl<h\u0013ކ\naG\u0018-?J1pm\u0011\u0018\u0001\"\u001a2\u0014Vz|R\u0018\u0004aw~\u0005l\u00048\r4\u001f\u0005\u001b\u0019\u001dEZKݸUG|B\u00011&T6\u0016\u0004\u0014;wWٝ]8\u0019X\u0012yWG-%r9PvX7ix*L(\u001bu==ϲ͓m\u000b\u0015qq\u001bZ\u0006e&\u001f߰n=jcio@\u001cx/{Y/rpՓ\u0019-kb\u000e(n\u001cJ;7N]Ğ\u001c\t|ט\u0006\f9^R\u0011,qi\u0019-j5I\u000f~Wfǒ;*~xFMuò~7\u0004S.0.rm\u0011\u00044PMX\u0015\n\u001bd6͵\u001aN\u0007|b*\u00014u\u001cvv#3֬ަqV`i\u001c2d%\u001d\u001e50\u0015\b\u00107Ӝ\f\u0006jx\u00049x\u0011!KhF\u0005\t\u000e\u0007bLb4Ezc\u0016lX\u001f\u0016>\u001beҢ(j\f=\u0013~n$\rY\u001f9PKC/q䢘\u0007\u001a&lrS\u00001|\u0017\u001b8+\u0007ۺ\u0010p5q \u0000\u0000Z(\u001eQ\u0010ӸAX\u0006!\\\u0001\u0012$$$CsrL2$L\u0010%,*OQuOł\u0007BuUX뵊]xV~\u001fn,\u0011[\u0001|nC\n-bY@\u0010\u0006X?(e92\"կ)fm\u001f6@>\u0015_|Xȼ\r\u0010L\u000bN\u0019+VJ2v\u0011&ǂga:y*=\u001b>\u001fC,꽅zqw\u0019Σa\u0015VbP$Ԇ3\u0017H*\n|t\u0011c^\u001f7Cv\u001afC\u001aUʆN\u0019\u0018\\A\u000bX)MȊ\u001aQrK{\u0003Fۏe\"\u001fj\u0005\u0002%hC\u0011i24.$Ҳɹ\u0018DӮ?2\u001c\u0003\u0019]HMt\u0011a\u0018PZ+C9J*_r%QNH4r{W)\t|em}^\u0010\u001c\be\u000bٻ\n\u0007.v_\u0013.e'T)V4(F\u000eoUgzf0=rƣ[(h\u000fGjK\u0003Ңy}%]\u0002ʟ%(y\u0002쭬0L\u001d1sR1w^NJO7\u000bنyoxõO`i0)¿6T\u0012@J\u0016\b\u0019JL#״C\u0000[\u0015!)9!\bw+@,&T\u0010Q0GU5a\n5\\1(<U~\u0000ڌxݷ:vRȆq\u0005Vt.\u001a\td7J<L\u000e\u0013US0ݠLwk^Ip\u00182Z\u0003\u000b#*͚i\u000b1.~\u0001xE \\M;.7vD5枤\bBl\u000e4 &\u0013ɷ͉Qsrkd\u0016\n\u0014B2i\u0017N\u001bğ':da9<o\u000e=:\u0015O8\u000e\u0000Zq]\\\u000e(p\u0012/@\u0011ΓH+nind`gAد0iJ\u001a*\u0015eW}o\u001c߶x\"omzrQu\u001c_p==n_%!w~~S]Jѯ5VQz<\u0017\u0015L/8#\f+>-9]\u001bs41y\u001e3yʍ/\tG䇫~IĴ41_35g%@\u0005.1N§\fN̡\u0004Pi'74\u001e\u0012@rz8Z?\r i;f\ncENOri@D\u001du{A6\u0004.ѱ\u0013>1\u0013_:, J\u0014f?/LCNN*E\u0019]٭!mq=p\u0019)\u0018\u001c\u0006ݍ\nc\u0017FMH\u0018?\u001d\u0013b;t%\r7r~\u0010L&3>\u000eﰞ\u001c~6s\u0015lD'9\u0004?\u00016\u001eT­ϙ^\u000b5;\nk[\u001a}\u0010gX0^hq$WKJm3qV/f̔&|}31sO[9\"6ε6\u000b9K+|dj8a&k\u001bɐ=9wUͩ?\u0013\u0006\u0010|\u001d\u00160,lugz\u0000eU\u001d,}*\u000b\u0018e-^uGSo\u0016y7\u00057bC#Q\u0010şn[,(\u000bl^\t6!\u0000\u0011ʌ>\":j<rBa̪ NfE\u001ekI8<*͒\"e[,A\u0015v\u001d:\u0012ksCl.\\șc+5*W\u000b\u0003&ŀ~\\K4\u0005sR^?ӕ\u0012\u001cx0v>biq\u00102$V1\\$\u0003ǕwkGԣ\u0014Q\u0001\u0000%[`ѐJ\u0010\f\u001aΉ\t`]\u0019+Y)\u0007u!*5(HIdaoE\u0012lw1\u00167\u001f\u0012hYxЈrMyA39Sc\u0019LYgBل*d\u0012\u0003lQ\rP/\u0011ǅml)IR`i?ĞA\u0011\u0013Y訌:\u0018et/\rysn\u0005琸M\u000f>dSG&HP\u0002e*p\u001d:v\u000eFӫ\u0012}\u00059|%*Cd\u001dڌ\u0006Tm ؍θSVkq~VQ<\u000bf\nCB'\u0018L\u0005\u0004H\u0002\u001d? 6ǍZWzjxA|+c\u0019shi#a43\fKZr?'\u001bH:m2\u0005AĽ\feЭd\u000fcM^k^Cj#,@DL2\u0000I~tHGǫ\u0014J̀e\f\tW\u0013\u0007\u0002\u0000`_qZb\n\u0004\"\u0001p\u001bp߄CH\u0004\u0010\u0002 \tI&d2L\u0012)xʪ*jXEt\u0017JJ]EZ\u0010_=@X\u0015Y#>\u001a(UT#tgE\tUO4E\u001a]cDix\u0016`Ff\u0003w0b\u0014(U\n\u001eY]sAvjfhw@A,bx#i\u0002\u0005\u0010u+E\u0006_Xx\u0002\u0018˼U-E\u0005W'\u001a_@\u0000ce2b1(\u000bh^EN\u001c\n\u0017`V[@\u0005-kbn_Pe:\u000160\u0016\u0017lu\u0001-'\\\u0005j|Dme;tHGD˪&աD!ߪ@M?\u0003\u000eB\u001c=\u001erΕ\u001dt<GH8J\u0013d\tlM\u001e\u0006ilv>Sw\u000eo2\u0003Y!;DLž]򮆁˶R\u0016f;˷-r\u001e0ۏ\u0006첸R}\"?5#mk+3\u0011(\u001a(.R\u001dxP\u0005{K\b\u0011$\u001f\r\u0011~?\u001eu\bX m\u001e(\u0012U$C[K\u0014Il9vL\"\u0015\u001fF\u0016]C2q.OI61Q\u0003x\t1iQZx\u0005le_)O&uZCj\u001d7$\u0004\u001d6} A~\u00068zXmb|n^i>]fQBchJDj^\fk\u000f\u0012]rou#Ih\n8\bЂTc1)üW+-*kxue\u0006I~PE:LR]\r&t\u0007-¬^*$M4-b\u0001B\u000b\u0012c鎳A9Z\u0014u\u0013KDۄT}\u0002pp\u0001;ǳx0w\n\u000b7\r? r\u001elJU/3B\u0006K3\u001fhf\u0013@jm1RזD*p\u001c֓2O(\u001dVv\nndmMA\u0002O\u001b;1S`M\u001d-a6)N˛,_\nl[c.\u000eHі%Ŗش\u0015+#]lcٶ\u0015$ s~\u0015\u001c&\u0011b\u0017~In^\u001aY6-쪸ʟ/FRa`\tEi|o\u0003$Գh\u0005:)=kZv6g|\u0012\u001fV'E\u0011;R\u0003\u0005^t\u0006\\\"\u0011ZW\nYnN'⢒Li\u0016K[\b!6b\u001djnf$=+\f\u000f*\u0003.Ӄ\u001a\u001cKvIchP*%z\u000fډ,1-pGsD8DC\b7x&X8e!j5kL4Y\r\u0004\u0007&Xq\u0013\u0000Y\bLA)$]s_\u0019g^\u001c.\u0003[fx́{sHq\f\u0014\t\u001f\u0004\u0011\u0007o\u0015݌\u0004 K\u000fFaa)1$P\u0018o\u0013גיDO̐Ń\u0012w\u0019q?0\u0011\u001e$װޮx\u0007YZN8$\u000f8\u0004\f_ُ$`lcZ6ݐ?\u001cȇY+0H5zቔkQ}Ö<i|>!~QQ2&\u001eP{BcH|7gz9^s\u0011\u0010yl\u0003\u0016\u0002u^A\u000b;Rck\u001eU\u0004>)vQ\u001d\f8:oVcsK68#7>^nNk_<\u001fw\u000e*>mڹ3\"Ψ\u0010Ţl`\u000f\u000bD#\u001c\u0017ޣ7W-#h\u0007\u0000\u001d\b<Lqf66@0}\u0011\u0019\u0012\u0011كih\u000f \fӛR$0aps\u0017T9˟\ts\u0017JЫlO\u001eI\u0012w7±A8j^\u001bՏ\u0003orkl\u0004\u00151\u00027x&eoU\u000fd!S\u0012Q\u00042b+(\u0004km\\5\u001e/\u0017>D\u0017:G\"DxA\u00024\u0016\u000b>X(\u0011\u000b \u0013\u0018\u001d\u00156b-X>\u000e*\u001f\u001d'qkxOOX\u0000+{5|\ffP\u0003|\u0000~N\u0015Ez\u0012Ey?|S-2<3}=\u0004`[\u0016~#l\u0014tGP\u000f\u0018j_\u0003\r_߷,\u0017cn$\u001ak\u0002aM\u0007=UlMQ\"gɆ\u000b5iЉ5M%7R\u001b\u0002%\u001eq\u0015vLSG[]]M\tvKsw>q|\b\n\u00067pL=#.[CjϨ^wUOlTvCe\u0015]j20\u0019uuFfձʪ:AƆ\"E*\u0015\u0011S\u0004\u0004'_\n\u0004\u0001\u0000\u0002!\u001e\u0012Z\b\u0010:Qpt\u000547rv윽Ys9{<\u0005Fr\u000e׃d\u0010+G1\t\u001eF~ /bm1&&\u0000x\u0010\u0000,\u000b^\fLtZnD<t\"74\u0010\"\bף.9\u0003\u0003m-6Iq5\u00045.\u00051g)\u000fj\u001a\u0019\u0005!0O\u000eD<%\u000en{\u0019?ns\f\u0017\u001e\u001a8\u0016Y\u0015F<p\u0016\t\u001fr\u0012wPqD!\\ F\u0013\u0004\u0015KA^\u0016Z\u0001Ũˍ\rR\u0018\u0004휃EᏥ\u001cla?aZ\b뵘ltU\u001e\u0010tWz\u0005\bs1\u0016͘iea1M1g͞vw\u000b\u0017xeWmOVum6lǦmavovumw8m^w\u000fO/o}\u000f\u001e?tc\u0003N\u0004\f:\u0015|s/\\\f\t\r\u000b\u0014\u0011\u0019u9:&J\\|B\"\u001cD1X\u001c\u001e \u0010IdJԴk\u0019Yy\u0005Bz\u0011bs<D(\u0012K2T*+RWkjj봺z}CcSsKk[{[}w\u000f>\u001c\u001cz4g?\u001f\u0019\u001d\u001bx7o߽0\u00116m\u00193fB\u001b|=ks\u001dΛ\r4|K5~X\u0000p\u0011%&(*,.0<6\u001a64^\u001e?|X@`Ps\u0017B#b$ PX<1A͹O3l.O \u0014Ir\u0005\u0014OS#?UBP'\u0014\nBP\u0010T;\u0018}\f*~>22\nEOL_~[\u000f\u001f g\u000b\f,v,\u000e\u001acy]\u001ez\u0001Fl\u0003(}FVύPq㫪J6A$*H\u0012\u001a$Ρ\u000e`v0;\u001d\u000ef\u0007×9zL2ٞQC|\u000fQM5\u000fxzAR+Ԕ k*\u0005xGjsH%Ť^Vaݼ\u0002r~Lȡ3h\u001e5$؋#\u00142'$\r\n,FP].\u0005V!f\u0012oDc&2`* _\u000e\u001e'ǹ{#\u001f\tݰw%{2>\u0016aQ*X\fSV*5r1V/\u001c\\\u00052\bdL9x~dE\f]0\n\u001e^z[\u0001AKm<L!\u0015\r|\u0001\u0007t䳁,&p#Ae* aʁ'pBr\t}1zwAj\u0002$\n,\u000f9K\bͅ|-7\\c\u0003L\rS\u0001y\u0003\u000br\u0005\u0010\u000eRꈼ_bl؞ҰU\u000eKTU|YB\u001d[3@S\u0000JӸ!C2)\u0007gO|dgس\u000fu\u000e\u001ezw2PW^Rd\u0012\\=M\u00044\n\f\u0001zOh'\u001d\u00027@nOP\u0014J-yV;Lg]fΓ'\bRj\u001c^[(Ā\nyC\u001e\u0012B\u000bI@l3\u0015o? qMzۨ{6Tև*?]FW^V\u0014|\u0019.G\u00022 T\u0011!YHl\"\tIͦ\u0002\n~]tˑն:6^m5\u000b+)U\n&G͒\u0011ҥ\u0004U\t>IL\u0013Ť\u0006S\u0001K``;\u001d\u001cm\\ojc{.]w{]}A]\u0016[UT5䄚T9\"#֑$-QJ֙\n(R;7n\u001c^\u0019\u0018\u0006\u0018\u0006윆\u0010a:VVTST@e&\u0012\n\u0006PkL\u0005l\u0015v\u000ew6ԷU8{`\u0003>5#8-E\u001fʦhc\u00055\b\u0011I\u0002j\fɱUx\u0005\u0012(EU\u0012\u0002\u001au=XU=\u0010ux}{tjG\n\u0004\u0016\u000f4\u0014a\u001b(=Gr(n\u000eËqZTivU肝\u0015\u000bF7\r:&\u0010\u0007|ؾ\u0014ĮȬ8CLNlG\\nt{Bvx~T\u001b2?\u0015]\u0010ъ?:B':\u000bnA\u0004S+\u0017w.\"nG%PBRBz\u0013^MLp\u0013z&*T@ m\u0017Hh\u0011؇Dc΢&ZT_\u0000Wj\u000b\u00155yI\u001a5LOї5\u0019m\n  һE/`v0;\u001d\u000efˡp;ϙ\u0011־A\u0001}U\u001clK8\u0010SQC#kדt\u0015YFUVErAF̾!\u0017b\u00197\u000eE\u001c|\u0015{\u0019e\f\u0001wY쓌\u0016E8T@V\u0014\u00114U4<7IIi\u0004A(R@:\rj:8vug*t\u0001\b\u0001E@EQ\u001c*r\u0018 럄\u001c\u0004\b\u0004B\u0012; !\u0010r\u0011\u0002I\bC@V@\u0013]_ӇQ\u001f5<n.>UW\u001c/)\u0018aY/-Ry%F2\"\r\u000f\tInK/i\"tY\u0015{\u0011p8d|\u0001Q\\Đx\u0000i'6ĩ\u0005/UUi5gԧy\u0001ebLY(k\u000ee&\\\u00161q(h\u000e-Ev;wΛ6 !5kC(xH@\u001dm՝N&\u001bוy\rUF\u0001e\u0019af5n\\+#$\u0002,۾.w\u0016Aڐ&T%_}ؗY6\"s\f9G\u001c\u0014&j\r\u0001\u0003ơR9aWLt~-\u001a\u0010m\rANv$&!\t2p0t{z$?5Z \u001euTj\u0001]Ġ\u0010`9\u0014\u0010t\u0001&\tf,\u0004h\u0003؈!\u0000\u0010%gS$&T<6\u001dncK /\u0010\u001d\u0013'z&bp`F\u000e*\u00188b(@\u0014H3x!}\u000e': yo8\bIP&\\P\u0013{C@Rt(ɓ\u0019ʌ*\u0013rH\u00121𵐗&dx\u0003'McČ`$f>m|S~䃱\u0003ؕ$x0mq]Pe&\ti#\u0006\u0016\u001aeF6AWB~8QChiT\u0001ɞ\u0018 <|\u0010\u000e\u001f\u0007\u0007]z[u*nz!bg9Ԓr3lq\rX\u0007\u000fr3\"\t>4SP\u0002h\u0005=\u0018m@A8\u000e\f{Ͼ\u0019+\\Ǖ--F\u001b3a@\u001f4M6\u0001;ҩ'Z\b\u001e8JԐpj\u000fj\u00196 \u001d\u0003D\u0011zQ0'չ=\u0005;Qv(X\rN#0\u0010\u001c-z#}\u001e2Ң\u000e\u001c\u0003>\u0016ƾ#Ah\u001bw8Vw5C\u001d/[r\u0016:mU\u0006\u00055fY\u0004\u001bH7\u001bH\u000e)N6S\fP\u0015X'>}<5ӽe~y'N\u0010NdtOݗdjM\rZ̓x3\u0002Y\u0003AdECM&-ڀjG\fož>ْm\\\u0010-u ZT\u0015\u0001S#%\u001axG\u001a;Ѣ8]0^`#\u0018Hƺ\u0003b~\u0018ںn\u001cA-9*ViTR8\u0003\n`'yM>aATm\u0014#GђZ\u000fVZ˪ݐETD\u001b_l\t}mϒdo8zP\u000fc\u0016)VdjGT\r*:YϪ\fz*M\u0000S\u0016qKP}W7K۫Ov*om;C\u0018zzqt}J\u0001eV\u0005l|ery\u001eItV2j)k\u0017b腳h\u000b?\u0006|\u0017lIl\u0003N\u0010^\u001fmzQr}\\E+\u000f\u0015ݫl([Xp1\u0015ٔZ[m@_Xi䮠\u0006\u001ep\u0000v\u0006\u0002fy?q)?GZ\u00163=@W\t\u0019=\u001dT2lv\u0012sd\u0018rڰ\u001cP\u0013챢ށz\u0014E\u001f\r\u001f\r\u001f\r\u001f\r\u001f\r\u0011q5YTp\nyOCŻ\u0019\u0001\u0016Reb\r\u001e&l[Ghm\u001d\u000e\u001bb9M\u0005%\u0019\u001a>]\u0014\u00018!\u0016p\u0011~{gklB42?ȩV\u001anI6\ne%2G-8o\u0000\rQ\u001aP6n\u0019\u0012c\u0001\u0018\u0002N/J/FQ&=\t}-9>#,\r+>nƙ,Π\fz,\u001d>3'Џ\u0011ԍI\u0016\u0010\u0006\u00046\u001eM\u0001o$GWdosfܐT:\u000ejGyhKڻ)\u000ek[Leٓ\u0006\u0014#\u0001ceA>V\u0016l\r\u0002oiE\u0015Ǫ\u001f2p˪lMe.{J~IT\"\u0005Cvnc53}-\"\bÐh\u0003I'ِ,kHM\u0001\"D[YjsUZCM:fD˂\u001c+)\u0012\u0004U\nNa\u0007\u0002a␽Zfk@\f\t0,\"IBLtr\u0001AlĐ\u0010\u000b\u0014 N9Vr:#Q1ha\u0018\u000bx!coDjԀE\u001d\u0011\u001e_dLq\u0018i&]8NLS\u0001NI\u0006S\u001b/)W\u001f\u001b\u001aKlƜ5==\\\u0006[jTv]٨@(WKsm!fwO)iiLڤ?\u0006鑓\u001b#\u0005tɕOL\b=?ٯ\u00049,o9̳t2UA\u0014\u0005\u0011\u0010P\u0004@C6-!d!@ \u0001BB6BĂ\u0005QDk\u0016op94\u0007\u000fMre\u00179*\u000eӍ\u0018RMd0W:\u0016r\u0019B5*G1GRB\u0005d;\r\u0006ib\"P'dh8^`B5\u0011yϕJ\\\u000bL\u0017΄*\u0005nW2\u0002\u001f\u000eb\u0003߭L)3t\u0019*E&'\tsdr\u0016* i\u0001\u0013@s?/=\u001f:Vh,\u0001~ߗ;{u15\u0014k}6EnA;xo\u001cbhS$u,N%ɕ8j\u0006\r'\u0003q\u0005/qO=`S)г\u000b,Tר\bs\u0010=@\u001co5\u0003-z$^˚Fk3(l\u001aUA\u0006?5(\u0013!4\u001cv\u001c(\u0014_uw1ff:w-}hXKv\u001azqAOQ NϜ@:&z$B/\f\u001a\u0001$Gc*8?z0;ߗ]/ZZV#sY\u001c]X&q\u001azl\bKNCd\fP<d\u0013Ջc1ƶ\u0000ؽ\u000f\u0019P\u0000Ҹ\u0018=\u0014\u000fӶ1S\u0007o<X\u00188\u0002/%3Y<IXs\u0019:Hs\u0015oe\u000evn$\u000f\u0001\u001eGH\u0013\u00177\u000fG\u00038`ݗ$\u0010\u00141\u0011]\\?2^OdJt\u0007J\u0014\u001dz}\u0003eb\u00168B\u001a!\u0012v@YN݅4wB\u0006T_D\u0000Ձ}`0KwͮGf\u001eGU\u001dl,&3=m2)\u000b(\u0003ŉ'\u0007qv\u0019c\fF\b+c\u0004>¶GF\u0002\u0011\u0010\u0017ޜ\u001d=;\u001cèj!,z\u001a5ϥ+D`C^\u0016n\u0001\"\u0019NJf9\u00030\u0007\u000b2\u0018?\u001f}ɉ=y\u001aΝ\u0018i*mJn\u0014L6M$_e\rA\u001c\u0016 ($eEU\fȀӏ^9\u0014\u0007,>IoGs\u001e}YEHB\u0010W\u0011h֯յ\u001b\u0010YTwL3r\u0006S1MO\u0004eS-)*d`[\u0007hh\u0018%؝j\u0005ӣ͓\\$|\b[XRK@-_J\u0010oЌ+כŋ8V\"\u0002]?\u001f/&\u0006\u0003{\u000fd\u0011_$]B?,kʯ2xF5x\u001eun#\u000e\u001cs\u000e\u001a\n[\u0016o\u0013yDs?{\u001fhow1,8\tfL?CVAyE%\nK.?)-amU\u000b[5[ڜ\u0007\u0007ȺMtM\u001b0o\u0000?s}*\u000eϜ|-.̩\u0012\u0014 {JZVu\u001d\u000b(l\u001bI\u0011neC6%FQ\u000fnj̍;\\M\u000e{\u0019w\r\u001a564\u001c\u0004\u0019q@p$\u0010{{bKX\u0017\u0014QVx\u001d\u000b&\\\u0007^\u0011fA\u0016{O\u001c򒻭\u0004m\u001c.B\u0018\u00010b\u0010\r@\u000eħ/d?4m/o\n\u0017y0\u001c\u0007\bwA6kl\u001f\u001eoz=v\u0017Vtbd.\u0007R\u001eC{,\bǄ4\u0000]@Г\u001e\u000bzӁ4#L#y\u0016,xK|}]XÿC\u001c>A\u001b𵲇i6\u0017pD1|܎,HψP\u001e(@c\u0016\u000bii@Rq2[e\u000eaU^FR\u00176Jz!\u000e`\r{v'\u001a\u000bf\u0004\u000f\u001aQ\u001am)0}^(6\bRc$5\r(r~P,y9wM\u0016:(^։gDHD\u000fϡ\u000fyl\"0A\u00114t!5F\u00175\u001bbl\u0017\r#@\n)ۚ+Ou`;\\\rmqׂZ4++'8bqu2ǬN Gt$\u0014\u0014\r\u0001\u0001\u0002F\u00027\rG,)\u0015O\r'6bgSo\u0015/\u001a+Wu\u0012Q.mlc`r\u0003j($oQM\n0\u000frIF?\u0014i\u0004#@\u0002I_S>\u00188Z7gW-\u0017[ܫ\u0003\u0001\rJ?&[1C\u0017k\\\u0015\u0004\u0013B\"mф;[\u0016\u001f\n 7qD\n$fØt;Sj͖%\u0003qzfg,;-^\u001e\u001bQ`-}\"ҘGH\u0003v\u0004-\r35Sl.J7\u0004oÉ@\f\u001e\u00055\u001fp\u001cNgmwٱٙmu*ꊸ\u0012\u0004\u0004/#7H NH \u001c\t\u0010@\u000eHB\\$77!\u0010\u0011P\u0017x\u0000E.ov[\u001fO\u00178b\bD>\u0016Π\u0006\u0002)Q6AY-aWjLGU-oF<B84\u00154N\u0016_ \rT%wO_@9{\u0002q/ߔ`PɥXh\b{j\u001b*\u0006hZ;0T\u0012\u000f\u0017J\u001c5R+\u0000\r4x\u0007|_O 9\u000fg.mΦ\t^p܀bFl\u0015Y\\u\u0007\\,RՍRJ\tK\u00055d\u001eA䉆Hl^js\u0005l\u0010x\u00029\u0015\u0002:c6:-\r\u0006?\u0015y{\"\u000138\\n,9\"A\u0007RU\u001b+\u0005\u0012J_ʆ\u0017\u0018Q\u0003$\u001be6W}\u0012HN\u0005SA[\u00112\u0006:7\u0013<v7\u001e=DU٭٭\u001c\u000bڀSt$K\u001b\u0014\u0001\\`˓lV+\u0000\u001bh\u000fO{\u0000/y@6N.\rDO\u0007FN\u0005eئ#2z\rFifD_h$iK8uy\u0017ZEA(9pekoR\u0012 8\u0000\u0010y\u0000\u0013gLWm\u001e\u000f|!S~q\u0007\u0017``l*7aڲ+QR%_E6\u0016\u0012\u0003̌VY:+B+5-\u0000M\u0006@1uqgq\u0007;s'/9\u0016\u0005?l\u0006Rěa$si\u001dhIQ\u0017AAt>7\u0015k1Fj\u0007@3\\=ۉ\u0012 <\u0006'\u0003#Gޙ?<tczЏCC-K\u0005\u001f4\u001ev\"b$Sj\u0011ѭ^\u0004M;ڑR%R1Wi\fu\u0013%\u001b\u0010\u0001\u0003\u0007|ϻ{<k}\u001e)_=\u0005MV\u0015\u0017\f6\u0010(\u0001ƆkF\u0013[\nŹm\u001ezw,Fp\th9\u0006voZͯwxp\u0015o\u000e=3b\n$ʨ!Gl03DhvYv s)F\u0015h)\u0003-\u0000܀nWK\u000e/o>uߎo\rqxeP\u001e\u0007 IÉ\u0019h1nzY\u0014=Wu\u000bM\u0018զg\u0015ԥ\u0015'(e]\u001b-gCGi.\u0001];^ɹ>~o[?)\u0000 oOP^M!=\u000fa\u001eǠ\u000ftRl69m\u0006^r\u000fU4\\\tO%%-,O]T\u0011B*s;?Mw+Pm\u0004v{ւC\u0017)#H\u0001ܥ\u0019O)ih\\LC\u0004.!\u001a\u001f\u0000K'\u0010b1\u000bHQs.w{ϟ\u0014/2\u001eTp\u001c\t\u0006c6#s6\"bI)i+\u0019˰exV\u0012z\u0012:;9\u0016\u0016\u001c\u000f\u000bsYAnSKG?vOW{$\u0006a R*\b\u000f\u0015\u0013\u001eը1o7l\u0012\t˯WC^k\u0004h\u001a+\u0000\u0017qf7\t:\u0006B|\u0001J\u0016+*u}B2#\u0005PCѦˋS%e*\u0018:g\rc\u001bCh܁li)\u0007\n`Fm5{kï\r\r5\u0005!>s^sUXt\u00059UJ厓7YΆ\u0006\u0003-P7 $*gz0W]yl`\\:\u0006XA>s9\u001d7<5'&c\u0005E=ff\u0014\u0011\u0015ӕDdyix\tM8ZH\u0017\u000f\u0013\u000e<Wa\bT6Tچh\u0007\u0001AgE\u001at\u0006\u0017\rL1\u000e\u0001\rA\u001aCc\u001b#VEvr}fNt\r1I#7ܤ\tGۆ\nr;a\u0001t\u001f)ChH^0\u0007\ruΆc\u0013p\u0006.]\u0002\r~x\u000b^Lޓ\u0006(qUv&ro(\u0011JeP\f\u0012\u0001<_ׇ\u0011{Q\nc7Rg4tF\u0015ZgaCCQx\u0006!)(04e)\nT12Υf8E6G\tV\u0011^؃R(E֘\u0018Yՙ\u000b>6.\u001c\u0005\u0017\"\u00044\u0007Fm\tIz\u00129\u0016)d1\u000e\u000bź \tF+)m\u000eju@a7gDf\u0013FiUcԝRڊXxi>6|\u0003XG\u0001\u001b\b/@@+$ka\u0005Qbќ0\u0013/nMҋ\u0003\u0015\u0015]%:c!ר\u0017ZTxY\fjq\u0012\u00104Fּ]\u001f\u001aX\u0006yw?\u0005\u000e=5a'\u0000\u001cv:u]㌵u=,\"\u0019@n9\u0015 $$!+E\u0002@AH\bGBBp\u0004\u0010EA.\"(hA\u000bP뷙ӗ}\u001fЇw\no\bPEi\u000eԑ9\u000fq\u0005ͩ[\r\u0019q)Q<\\Uh.gY\u0015\u0006}WS(35Q\u001b\u0014EJYj)zS\rh/Pk\u0018<\u0003^~'?aS\u001b| A\u000b:8}F/R+|cha\n\r4Y^HjZU7\u000b\n[C1 ?w\u001a<}Aw{_Kyē]Pm\u0003p\\+ؐ-\rTź\u0016\u001eˠRVYĐ[t\u0000X;-i(i\u00067[9GPq\u001a4z\u0000g6@0=\u00134kֈ\\c-M\u0004ANTij\u000b*A+7V\t|ZQ4f\u000e\u0019mld/ 5\u001a\u001e@\nݽ#]w̋Us\u0018ri0\u000e7mN\fwˌ\u001a|!WQRQIc\t\u0004f\u000eWlerU\u0003\u0001:Gg&{ q?\nn.\u000b\u0007|f0\u0014rg$\u0001u͚B869A$Vˊ:bVoi\rL\u0013,EUJ@!Og)Л\u000f@v\u00144>\u00054=A[+g $fy4\"nv,\u000e9r1gJc:5J-AYL\u001a\n:J匞\u0012Y*ϗȭy\u00125Zg!W\u00026\u001c\u0001@\u0001@6,\u001e\u000fGDOMBӆF`\u0006+٘^-+*uj/iuU\u001ccnC9K)7hsz 5]\u0002Nٰ;T\u0000d~><lt&\u0006a\u001eK]\u0014VTUu_;#;stxm-&ls{\u001f^i\r\u0000\ng\u00079y\u0002\u0018NnZϮ^sws\u001b9\u0018\u001cqq.\u001a5\u001d4̨&\u0018J\u0016ld\u001b2zY\u001d.d\u001bؓj0t=\u0002#ۀ{:y\b\u001d?ڈ-w~B=wB(z\u0002?\u00011GE\u0005AR#Rƙ6TPfkG\u00185^C s\u0003\u001d\u000f#?\u000f\u001e9z\t%g\u0015^\u0010t!̛a2Rxc,ip\u0002?T\fЛVN\u000bW#E~\u0006j7 s\u0006\u0006Zo\u000e_\u0019;wf\t.U\u0014/`\nc\u0016(\u000e N`+GD+\u0012:%Z}E2u\u0001>TJ\u001e4&\r*\u0006\u000eo\u0003w}\ru?zXcΑggS+~P2u.3MV&\u0004*\u0018\u00061Z,_e%I#\\iPpYRg/Pp\u001bhms\u001f\u001dY}~'kGs4Tj`\u0006ޅ\u0005X\u0001~>\u00043en\u0010؈24\"y\u000b\u0013'ʸq~\u0015tZh/5kofصOa\u00048s߸F_$\u001f@3q˰<R\u001a\td\u0016%\u0014'\u0012nQq\u00184fM\u0016+Ҩ\u001b|׆n\u0019|qj\u0004\u001cpCh#/\u0003ⳟ_cbQG0l\n\u0002\u000f%=+>>'n9;7^^^=\u00121.5?j\u0014D'_X,D,Qn?t/J\\p\u0014\r&\u0003w!ב\u001b0؋gTStZ\u0013\u001c*j|\u001e\tD=bC\u001f\u0016B\u001e3WYx{\u000eot}\u001f5[,\u0005w\u0007$\t\u0002\u0010\u001f4\b\u000eL\u0001\u0017B\u0013A#oaQQ\\xąʈ\u000f}IH\bN\bK\fȇߠ\u0002\u000b\u0002Ke's}*\u0005_}\u0003;v$p\b\u0001;$p\\,\b\u00021~\u0011 ?\u0014$\u0007\u0006\u0003 \n\n\u0004\u0000\u000b\u0007!\u0010\u0015\n\u00019~\u001f|?}S\u0006\u0007R\u001dw\bp\u0003^@\u0010\u001d\u0010YH{\u0011V\u0019DrqQ\"Ş'VpoTU$VdDױJtzt\n*BM\"{i1a=~o\u001aضR[\u0003 \b\u0004Q!\u0005q/eUV.yVH[(`Iʪ\u001bY\u0019L<SJ0MuV\u0004~\u0002٫@\u000e(\u0014C\u0001\u001c[\u0003=\u0004\u0004着0\u0013\b#?\b/\u00050S.2sC -3)b\u001ag$395\u0004t2C!6+ӵkhC5Iu\u0005?F;;\u0001\u0000?z{w]-ＳUԧU \"\"{*(CF\nDF\u0002\u0004\b$\u0010L\u0002@\u0006\t;/\u0004d:\u0010!\u000e\u0014Z\u001cu]{w\u0019T\f\u000f*\b\u0000ʇ\u000fF\u0000\u00009\u0016\u000exɉY9E\u001bG4\u0004v؊?Ƹ@ֱBJ|\u0002\u0019/7)˜\u0001\u0010b@Ջ<*@\u001c\u0003;\u001f\u0012 \u0018\u0010fe\u0015>\u0014 \u001f1KWiE2c9rg0]\u0002Dg\u001cQ])ܚ\u0011d]ѯWiMU}:o\u0000@\u001c:v\u0000N?\u0010ć\u0002ѱ@Fq\u0019?\u0017.[cT(y\u00121oM70œh~8J\u001ch.#lQDҭWF[\u00033j;E\u0007#@\u0000O\u0015<\u0017~\u0016.;YKhk&qtd=rT}J\u001b\u001a+zPUX}Ψ9gTz\u0005<\u0007\u0015\u001d#8:\u0004<1)y/%O$y\u000fevUm:>Cn^!R$,@P18Q\u0006\u0013r\r.eFҺs&o|<#\u0003A\u001fD\u001e\u00061@q47剜_Ǌ5y\u0011vAT<Phx0,w*\u001d\\^j45\u0016]ͪD;:UqZ\u0004\u0018W\u0000s~\b\u0005,0PD\u0000ugڴlĲ\u0010}8\u001fM\u0019a\u0016)BU,QdRb\u0015n&8\u0002mpZ9.7>\u001e8a@\u0014\u000fÂ*2\nhc^\u00133~1\u00163J\u0016Ei\u0015颸r!:Aj$U\u0016^NMr\u0000s\u001b!&x\u0003t~8\u0003ۀ>\u0013\u001a\u00044@\u001fsWѴm)9PV-kQŸiP8\u001cSYFR4c4Kl]\u0004\rIC4<\u0004Q\t\u000e\u001bzás\u001d\u0006!{2 ЅfNxfKH~JμΟuF^4܊\u000e\u0018p\u001brfJ@г:6BRBd\nAm-\u000e[[ꍏ\u0007m@\u0016\u0007\u000e\u0007\u0002Ch[kd+>~r`vS!\u0019CkBD+Y]d=a&\u0016J\u000fD\u001c\u000e;Dlw؛\u000e7\u0000c_\u0000s\u0010\u0004o\u0005\u001f\u0001`\n\ty툈z\u00176tk4\u000b6֗\u00177Z\f*\u0015-Kآ&%ת#qfB\u0017׆cʡ\u0006\u001e2 \bGMT\u001b\u001f\u000fC?.\u001fX\u000f\u0007\r\u000f[\u001fZH5:Wt\u00156譥dUEF\u0005IҬŋ(\u0006\u0001ZǗkxZ\u0007,z\u00030=\u0007 >=P\u001e\u0005~\u001c\u0002\u000e\u0006?\u0018\u000fY9\u0011=1y~4\u001at\u0004V$a\u0011ix%A!\u001bjLsLdEԶrV!tZQ<\u001bs`\u0005\u0000i\u0016\t,\u0001{߸\u0003?xQ\u0012#/Ne`%zyx+UnGz)xVY'iNCV`k\"|FyT&\u000e`y\u000e\u0003\u0002'_\u0000z>\u0014#n/F\\L\u0018z2\u0005\u0019Cs/\u0014\u0011)Tb%\u001bӋ\u0016\\8yU\tB+\u0014|Ȫ/:\u0000 \u0004\u0014{7\u0003Ӟ\u001f޸ho;A[\u0007,8\u0016N(\u0014V'O7*\u0018\u000b\u0011xUzjޝ;Wd\u000f(aCV%l`P\u001aPy\u0003p<\u0007\u0001}捑\u001d^gՕ\u000fB\u001dkQG5wa\u0013g\u00197pkŭY\u0004l\u0001hd˿L\u0015^b/IİK\u001a\u000f(\u001b9w}\r\fۿy7S[Z\u001eh=(L0~l.}-ZYn@.\"@P\ng\u001a\u0005SDFd{W\u00045d˸\u0019:n8\u0015 \u001c\u0000\\o3K>\u001f^\u0002=ݻ_\u0011\u0018%%4$&8\u0004 j%|\tA\u0012\noմĶ^Ƿî:fԌ\u0019&\f6-Lz\u0005H|\f\fb?ӑu[}U\u0004\n^\u0006^\u0012_b6QYU82\u0012Tݘi-434\u0013o'iͩZRn\nZoH\u0000͟sӹ?\u0019}W>ߪm7\nb#1e\u0015n\u000b\u001f\u0017?#s\u001e\"*aQ{u5k\rixtJK}\n\u0019L\u001ejH\n0}0:[gAM v\u001ctv3tљvZuծ]uC;rCDD @\u0002\t!`\u0012BBHHB\u001c\u0004r;\u001c\u0005\\B\u0010\u0015Z\u0011PXnŋu\f؇}f~/76ذQ\u000b@\u0010\u001bBbh\u0010\\\u001eYuun^R!\u000blQw\u0004Ls\u00126\u0019\u0005H-M{#\u0011RpR\bʒ\u001fKʓ\u0016\u0014\u000f7k׌MrM'?gİk\u0017\u001b\u000eS!\"\u0004\tq8@& \u000bxw3Ksޖ\u001fG!禼:􊑟 %\u0000X\u0012\u0017~H<\u001f齾vmW\u001fkaİu\u0003\u001b~AD\n(\u0006Dh>F,AC~\u0002\u0012I)o|J\"&\u0000\u0019xŭԤǮ03bgF}P\u001fM}3-z\b[6|ǓoK\u0019\u0004@C' 룐\u0014\u000eA\u001d\u0004\tP\u0010\u0000tD\u001c`#c{xʢ\u0014\u001d\u0005H\u0000jl80bÀ\u0015!\u0001s'<\u000ejc\u0002/q/\bӃ@\u001d\u000b|\n8-\fQMxFeU>iHR|\u0000/1{\u0018.K<['-<+AIgPW7\u000bK\fg\u0006\n N\u000b\u0002\u0018\u0010H]iD/X\u0014\"IYEM\u0007\u0004\u001do(\ng]Ytd_6]8|pR~\r=)L}\u0005Uz\u0002{@\f\u0004yf4HsRA:VPRX[CYq\u000fDu\u000f*\u0014ܹr. Y%3Xl\u001asZ~\u0007=*\u001aUN\u0015^i\\U^,t\u000e{gP5y\r- A\u0001Er\u0000(ӣA\u0002eQq\u0012>IY`<<)`?\u00115Y^2]b+0gnϪn\u0017]T_\\Vc/=˚%\u0013>\u0003\u001ax\u0011[@\u0016\u001b\u0012A#I=,-B-\tg\r\u0005Vm<Ǿ_%߭PfZewJ-۸\u000e?{5#\u001b\t%Sry\u001fUC \fݠ>\u000f\bФ'XʂRlF\u0012yCrsT\u0011I<MlQ[Tpo|\u0013s^7\u001b׍\f/\u0010.v\u000e?A\u0018\u0019bw& 4'\u000e\u0000Y4yhs\t1b\b\u0004U\n\u0014II0k&K;tWp}\u0013Qh\u0005 켡E\u001dp\u0006 \u000e\f\u001c\u00070'#@%'\u0016U\u0011\u001f<Ft]\u0003\u0006]\"JQIeV\u000fƟ5\r\u0010L:cmvҘRU\u0003o=HB?\u0003M\u000eh>\u0000\u00100%ŭҐǞ݌!Wi\rKF\u0018MvWZfC?]>jqF-VTyl\u000e?\u001ad^6b\u0007#\u0002Sl0\u0013bYKO̹\u00054KftDuE5spx!DGSvW\u001bLv|j'mm\u001ecUZգ\u0016_\u001a\u001a\u0006E&Ѕm\u0007c~0\u0004\r\u0011֑ܙy<wΆ4\u0010*&ԔZ?ȯ\u000b5LA׵YNZSv}ՐCW=bPG*Ǧy\u001f\rM\u0012\u00055*`\u0019\u001f#\u0019T\u0006r+'{\u001d]x\\Z1\u001dRR=bz\u0013Scna\u0018mZˡ;tS^v\u0018#6)U\u0003kP\u0005o࿂9KpD\u0011\u001b+1v'=~oPK6\u001cm 24Ny&j<dnLCqN!hdؽ|\u0005<5\u000fm\u0004ám`\t\u0003p官z\u0012\"\u001f\r\u001dAN)@2FW\u000bgWeF\u0019[\u00155\u0002YҠ5rN\u001e\f{s;n;~U\r\u0000Ơ\u0016\u001b:\u000e9\u0013\u001d8p8tޝ\u001e55:ї_\u0010{m\u001aL5X\u001a\u0017If;Kc%t6u1\u0005N\u0016mgF|\u0006|A54\u0007n\u0000S_\u0011\u0013B{<\b|p!-'+EKV+P-U\u0018j$nl52*mwVK\u0007\\'%n'M4b\u000bGl\u0002 :\u000et\u0006Vh\u000fÙC{3\u0014\u0018݉${/$8p4R$b\u0013]ՠg0u&Vi[\u0015*sTnG|NylZ5HZ\u0007~\u0002f<m?p3OخW\u0010;oO&\u0006g$\r\u001a*nB,k8N9Ei՞VO\u0004:c\b\u0002w+MX\t$\f\ba\u0005E\u0003\u000e\u0010\u0010О  *EY\u0010dHeJ\u0000q .{1\u0007wRX%*UXʄ3\u0017W7j5W3K]L8\u001b(L6@շPv\u0010j\u000f{\u001c5m;n2I\u001fXKg(Q{8$NQ\u0013#S~-I!\u0014-P%_e^*(֔Tj5\rUږJrJjnm(\u0006\u0017vOnصЮ\u001e\u0007QWGC6{}:#/aǲ\u0015j vB\u0016&ɸR\u00151\f<\fs\u001cx\f{a9nm(1\u0006̷C;\u0007vNwo\u001f\u001c=ce߽1_ơ \bdi7NHQ\u001eƋ化|r\b+FUhueI\u0004\\\u0012yQiGgt\u0002mù[6_My>W\u0013k:nv}þv\fsv$4y4A֏K磻2nuJ\u0015\u000eUaDG222qwQ؃\u0013RpaWPgM/\fuLnmXivu:3_0\u001e\u0018%y\u0019N䍡\u0018I/ɴQ:8ǌ\t%bP,|Tv@<x֍6yPNPl\u0001jLdas\u000b&ۯ-Z^.wv+\u000e\u0005F4\u0011DM\f2g\u0012fhɘ\t\u001e7(-bL\u000f}Q(\b\u0019UFE#\u0001#׵\u0004v\u001b@W\u000f6{ꅿol`btq|ɒMx'\u0014L\\@SߡE\"\u00053OGkYNb )tZ\nR\u0004M\u0016\u0006Lp'ʸ~<xNPm\rzc\u001b\\c\u0015]O\u0016fylş]]H\u0010G$\u0012;\u001a\u0010zO'DM\r{B\u000eYL\u0004\u0016\u0002\u0016y\f\\QFє{V%ܰIe'_eP\u0001[OÏs,\u0013\u001cr1\u001e\u0010\u001e\u0014\bF\u0000\u0019\u0018\u0019\u001d\\!}!C\n\u000f+&w\u000eoF|,earq^T\u0004wgt\\w@~`\u0017\u0017`S6\u0005%#䀣\u0015\u0013mI눁`(@z\u0003;\u0004\b@\u0007F\u0000\u0002\u0012\u0002}\u001d\r`Ox|\fu,\u000bs\bs\fwY9\u0019k:蕏\u0019\u00179\"0.\u00152\u0000\u0011\\-Ps$\u0002\u0002mC >\u0000\u0001\u0007^@q\u0004;$\u0001\u00158\u001eΐ\u0004BOGhO\u0001tP___r:!\u0018͆\u0003i`=\u000eli_(x\u000f\u0000\b\b1\u0006\u0007\u001cr\u0003a\u0017 \u001eq\u0006#Ь\u0003\u0003$\u0003\u000e \r$v@\u0001\u000em\u0006\u0011dx8\u0012$\u0011 F{\u0014\b8\n;\u0015(\"a)\u0013^STS\b\u001c\r7\nӘ>ɟAdL\u001e\u000bb\u0004c!3쨠\u0017bUom`k\u001bRS2\u0005i\u0005@\u0000\u00111\u0000\u0019ȏlr>>^@=͚#K\u0010+ڴW+\u0019lc4`\u001a}_8\u00141C\u0011Q\u0017~u6h\u001bxF 0l?\u000b\t\u0003y;H\u0001 !?)|$Y\"3?iV徊H!fLSI̝Itx\u0012#\u001e\u000e{vM\u0007H!!M@0c\u001b\u0006r?H\u0011+\u0019e.%fNMcH͐/dL\u0013k\t\r\u0004V-\u001d<Iϥ\u001dA\u0003=\u0006j\u00192\u001c\f!\u0004}\u0005APt<\u001fdFd20)䷩B$9KTr_KӔrdlM\u0004N2Y\u0012ے\u0012۝=\u001f$\u000ed>I9wȫ_\u0003G 7\u0004^P\u001c\u0013\u00016P\u0014\u0002\b%Ȩea\u0012-\\`X\u0002L)jY\u0004FX\u001b|\fך3\"紒\u0014jro/&ꀣmj\u001bv;!\u0018NzA1\u001a\u0004\u0007\n1+d\u0007)VasYV.o*X0N?'\u0019Tg<'T\u0013Zs\u0010{ZI=yw)=?S\u00164О\u0016\\\u000e\u0006\u0016\u001d\tp\u0000|*\u0011N{\u0014?(ы\n\u0006Q#eMe\bXqiJѳRSFz9XFR\u0017wOMnUzwOqKqOV\u0005<mC!v\u0007\u00149\u0001~(>\u0004g\u001dKx}E5q\u001cc\u001bu\u0015(:ʢ2\b\u0003 R^P\u0003)\u0004R @\u0012JH\u000e\u0004\u0002\bC\"B\u0010E0\tA\\\u0019\u001f\u000b\u0018g\u0015nև}\u000f99? \r^\u0010\u0005!HyYz@-F*#1K\u0015cH9}\u0004b_Rh2/s/gf\u0011\u0013\u000b97y7\rHP\u0013\u0001a \u0007\u00000WRX3a\u001aA\r*v\u0015\u001e=A)%(j*5ybf?7\u0002\u000b+@\\\u0015\u0018\u0004MH@2\b\u0014\t\u000b\u0000P7\u0003\b]\u0002APe\u0007\u0016\u001aB<*#\u0013\u001eq\nr\u0013|h%x\\N/bz|V\u0007Viè-\u000e\n5(n@\n^$\u001b\u0017\u0006\u0010k\u0010\u0003\n\u0002$ub\u0007\u0010\u0001\nwk<sS߉MAn#6\u0005kHfǸ\u0018\u0010HTAtVU\u0015հ\tb@)ŶeK\u0012\tD\u000bb.n\\\u000bPbju\u0002n\u0007@if\u001f?Z\u0003_\u0002x\u001ew))J_zUB]\u0011;ŔF2]K\u0012DHHhR\u000e~DVMIDIԋq9@>\u0011\u001c\u000ed߁zf0]1>F)\u0003\\d7\u001fKhe\u0017R\u001aUr:[Dx%2Q5I%e\u0016uaY\u0015I+tJ^%\u001b(G-\u0000il\t\u001a\\~\u0000\u0017N\u001dSyU0.FyaM𔋵\bd\u0018CPq\td\u0005&؜\u001a\u001eL,Q\u001adJ)\u0014BJ)dB֋\u0001$SC\u0011\u000bw\u0006\u0014Nyߧ6\u0003Ʈ6/>\u001e\nq\u001aJ\u0018hMIlm\"\u001cY+q\f&WQ%\u0014+ŕm\u001b\nTbs@\u0002\b\u001d\u0013@ӞE\u000foܭ\u000f\u001e-~b0䤶\u001c2\u0017'rą\f>UepKyBBc^3XVVIqUz1\u000b>7\u0001\u0000O;A\u0016\u001et\u001dz\u000eB;\u0013\u0013~ICț\u0011\u0005\u0012F-LZ,\u00168\u0004\u0001GK(^4#J\u001c\u0004]\u0017cz9@Y\u000fA\u000e}O_\\;nzGPLh%\u0018\u001b%lƲ.I*\\Y(ؼ\u001cX%m\u0014K$ik\f^-\u0018\u0017!Bs@i\u000e\u0007\n?lu\u001a?ov9цwD\u0005%HS2{31\u0015|\nn)c!5*!/Q)Hj\u0010&I\r\u0006A \r|s\u0000Psp\u001d3F>M/Gl|tĺκ>mw3ȭU\u0017\u0019\u001e\u001f\u001dN\u0006ӑ98żbt\u000f,Bw2I\u001dj\u0013Vs:L&9Z&9&\u0000^\u000b\u001aMaݕɤv\u000fO\u001ceq'Ey+_hbh'G\u0011D\u001ez\u0018CȺB(kAzE\u0000*f\u00115Ό\u001c0\"4ӌ)ft\u0014\u001cPnj\u001c\u001a\u001cXo\u0017]+o?سB쨅手e36M\u000f\u0002$Po\u0018(u\nv02`R\u0004y=0^G/\u0011z*TN\rk㷩a#3\ns\u0000r%ۿ\nVe\r˴\u001e?si1\u0013ߓAԇ\u0011a\u0007qIw3S\u0011Y\u0002*v\u00175(\bY51讆\u0018to\u001040xQ9rl|Wӆu\u0010s\u0006^Y~m\u0001Kw\u0007|NQ^\u0004#Bqsғ\u0013i1s̈9Zn\u001c\u0017\u00190/GϷ`{|{\bc\u000en[\u0006:6-\u00062vk-oV\u001bZ\u001bm-FC\fq\u0014\u00184F\u0004\u0019c\u0013qƴ(c\u000e\fj&\u0018R\u0002ߕ}L{#}9,Wϼ\u001e3\u000b, S!VCﬁ}ؼþM\u000fGNK?z8O.\u0005{`b\u0002c?\u000f\u0004\u000f\u000f[BD\u0006/b\u0003>\u0010bS\u001aPo93){J<#}Yw:W@F4 \u0017WAZY\u0000۾[hΪ\u00048\u001f,\u0000v\b\n\u0002]\u0013\u0000#\u001axA\u00017\u0004\u0007̀\u0000\u0019\u0007}@a\u0017 z\u0002Z\u0007`C?\tO-\"ܖ\u001a#>65ڷ\u0002;\u00022\u0012\"{+\u000evM%\\\f-y\u0016pI\u0006^vq2_gQMg\u00009=ǥ=Gg>(*(Ȏ;\u0014H\u0002d%|\t\u000b,심\b@EERV\u0018OU\u00020l*wo{_\u000f;Ci z\u0004Cg н\u0007|_\u001fH\u0002)O\u0000m;\u0002ݠ0\u0015ʃ]ʬ_Y4(\u001f\"\u000f65\u0019p`\u001063q'\tܭc\u001d\u0001~3!>\u0000\bG \u000fP\u001c~\u0013؎\u001ewr\u0003+ ..:\u0011rN@\u0003\u0014uᎅEc\u000b\u000b*lظ\nz\u001a\u001cH\u0004MQ\fx\b\u0006\u0010\u0017zAԾ\u000eDkW \u001fpN8t\u00028\u001c@`s\u001c$@fk\u000fa;P\u001f\u0003Yl\u001an\t\"\u001d\u0016b\rHQƺ\u0007<v\bR# 9\u0013\u001f;PN@<G{\u001fw>\u001doc.᮳\u0017cً9\u000bܹ11\u0017\u0019?\u001a`\rv뀍5}w\u0000\u0012\u001f\u0011G\u0001!Bj/YD\u0002\u0003}鈿S\n+5wq\u0016\u0012Y.棇xcy/q14o(v7\u0014\u0001\u0003kH\u001ax \u000e\u0019AA\u0011n\u000f\u00198x|A\u001c\n<A$5\u001fy\u001f\u0012Ki\u0012\u0019Fb\\\u000bg]nyyʟM\b\tSḗi9\u001a\u0018X\u0003\u0012d^\u0001\r\u0007gA\u0019\u0002\u0019F\u000b\u0001\u0001/\u0012\b\u0013SB3QSJ*bB\u0003gx7\u001fۖ)\u0015\u001e\n_ឋ&\b\u0013\u0011QKQO\u001c`}\u001avAl\t\u0019!\u001fOہ*\u00052| \u001a\u0002\u0012v$S\tؙd}һ\"Rb%{Tϛȟk\u0017\u0014\u0007%S1(q7a2\u000e\u001c`c\r,A\r(=\u000f\u000b=\u0002H'P\u0013AI\u000e\u0006\u0019#\u0002DB§\f\u00076i^\\suYbMׄ^\faT8.}\"4!OnQe]f|i`\u001fY\u000fi'lm\u0017`\fw\u0004=\u0013\tADx\"S޲L7R+jp$yt23mx\u000f\u0019#>e=1ı.${5p\u0006נq\n&\u001f+\u000f0\u0007ȋ9\t\u001555l\teԄJtJ\u000e{U\u001fK\u0010?Mj>\"k>G>EOsE7\u0019ڙ\u0014+2<b\r)׃א\u001d{\u000fA\u00071(r\u001fhH<=fDϠ\u0017H:X\u001eN\u0015KS\u001f2jdК2SBQw)봑6HV+c$i\u001e\u0006:F-P\u001b\u0002,SYr\tg\u00142mGkq#(BC8\u000fzB]NEz7\u001eܒIN\u000f/3au#kX]y2\u0007xV:ȶ\byΛk\u0017\u0007?T9>k\u00191`0)쉑KxP{\u0014\n]D#؄t\nJ2:xՙ&\u0015V\"_8Cj71\u0007R\u0006uӲ\u0001\n6Y\u001dPsMҹ\u001f>\u0017jY,BOz;[Rd:\u0010MRh\u0015g75V]={__\u001bЗ\u0007s\u0004b\u001cc\r\u0003kAENB\u0005v?k|?0\u0010j7\u00188H89PE\n-aoPoꤜYB#k\r5*a\\pP&k,\u0011\u001b\nE\u0003|>O<3K\u0003b\u0016XC㟡m+y~oߛ`\u0017b<\u001e&Uȥ\\59颦lYVɋTg*uũ\r\u00056cdJ3\u0019Ft@6c\u000e\bv\u0006`^GKq\u0002\u001e;}^]\nh;c;\u001aH\fN]/eS\u000b\u0017\fVUfRe $7eMZYWF0W-3\u0006|@oΗ\fl1a\r\u0015؜um%]V;B\u000f=\u0012vB\\pW-%\\gKE\u0006\u0005RSy*ʐU(\u0019\u0016\u0012E_0}&\u00147\u00019 \u001a\u001f@͟\nS߮\\tncuO:\u000e>hp{+!Z#9RM2Ǫ*\u0016\u000bKH)\u001b\u001bT*mN6M2յ4\\DgB\u00019_\u001a2\u0002?B\rp%Mumw\u0003\u0016u\u0005\u001fL@#pBA^\tST::8iQi\u0012mlY\"Y\u001cY9}^Pd9(R6 D)LI3\t%8)|\u0019'r2$\u0005E9)y\u0012W\u000bro\u001d\u001e?(}S\u0010ӑ)\r֩ CO\u0003ǥ]%c7M\u000e5Y,iY!iFy-_RM-ϻR?{9,Rl|RRF$5t\u0013YqE\u00117\u000b\u000b\u001f)ɏ<ޑ\u0017)\r\u0015\rY\u001b4PS\u0015F5;\u0017\u0018/\u001cxWg-\u0006^f72.ԊU!AyW2*\u0012\u0012R/}8Bfzc\u0011%9gʥAgjĥ\u000f\u0014:NwJCrg\u0004ECzu6\u0007Wzsmsw~a\u001e5\u0003e\u001cJmN qȈԪkRb\u001cWH\u0006:&*_V/+w_rDgf\u0006IkU[4Pe1vGO}MO@ٛK_omϕ\u0016\u000fY'\tYw\u0003FHN\bM?\u0014x=G_s\bb\u0006:Uݔɬyɮ|ɭ\u001d\u000eRAb/+զtU|J\nWmR}mNW\u0017)6'|\u001e\u0005\u001ecǄ6%ň\u001b\u0005w\u001a\u000e3\\Heܩ\u001b\u001a%w_J{\u00181\fGV(d2*uTnVyxիE5.vmyN5ҏ.b<\u000b>\u0016\u0007\u0018oDrZc}[-\u0017\u0012U$rD$j {\u0012.TB2\u0011/^#\u001e\u000f.Sj\u0018ПS3gi{\u001bݒ>'\u001eO\u001dqb_B\u0001]\\~gݑ&ft\u0004{w\ft\\\fꨎltz\u00159\u0014)z68D\tW\u0010o\u001b\u0012Z\u0010?u#ꇗT\r\u001b,iCzҏNF\u001f<,\u0006iQ\u0003L\u0001?Л\u001fO`S,W}ueyUL+vS;3$~S' j\u0010#*eߩ]o^T,7Y+O;\u0019'=#e4@\u0019ӑ/rdbO,B\u001d&\u000fxȏY\u0012huX#wvݗ\nC3깢L<F{FxA\\\u0019T:\u001a۴|O\u0018'\u0018w7\u0015Sx\f[\u0004ׁ>!rL:{NFN&&%\u0007S\u0014T˴}P<4Mt\n/fVwWkS%*4ҩǡ;\u0018\fRa:\u000e6\u001bp`\bF~ 0cF\u0005\u0013n\buF#\u000e#\u0016G\u001c!\nE$Ks@9]0\u0007D\u000b\u0015T\u001ae\u00198\u0010v,`X\u0013`\u001e\u000b\u0005N70I>\u0000~\u0004 r>ę[\"\u001cfȱ2E>\u0013ރ\u001fwf6uw\t r3W)\u001d˕\u0013\u001e\u000b0b\n\u0006WS\u0006\r$x9[\u000eL\u0003kpXB\u0002A\u0010\u0014{c7$;\u0015C#\u001b@!MO/\tX/AbAh)\u0007c\u000052\nE0\"Z\u001e\u000e+l\u0015<Wz/\u0018kL^\u001bu\u0010\u0018!Xw\u0007\"u\r\u0011~\u001bR6lE8\u0000\u0005z\u0001o*XF[h\"n9\"\\t\u0010Eق\b.\b- \u000e0\t#nyYL\u0005<\u001d>\u0015\fx\u0004\u0005j=\u001bir$5w«\u0013\u000b/\bU\u001dr\u0007c3\\\u0013\u0011嬃h\u0016D1w!\u0002av\u0010%8\u000e?)\u0019b\u001a|\u0017J\u0016ؠs~S6$\ro=OQ\b3M\u001b\u0019\u0011\u0006Adp\u001bm:f2\u0011ɷ@H\u001dq$KˡS\rY\u0006\u0018eLT~Sz\u00147I}\u001ft\t\u0007\u0004_(Âh#\u000ft!\u0017\u0018\t\u0004\u0006NuM5\u0011exuH،x1b\u0016\b\u000fCp\f\t\u0001= Ȣ{\u000ev)\u0013Ki5)Zޤw=@0A}N7PF,\u001c\b`Ȅݾr\u001b<`&\u0010O\u0010lX+m$9C\u0001iFg#Zd\b\u0012\u0002= ̠W\u00005o*oQ+\u001f~(F{.\u00130F\u00180L\u001cw$\u001dsD%\u000blgg\u0004E\u0003w:v/@2\u001cڿ\u0016.b\u0014ϰ=l.R-:{R\u0015Up#V$\u0010BB\tY$9Y\u0004\b$0Baod(PW+^!,E^y>9/yw}\u000fq\u0007\u0001z\u001cP!\b\u0003qO(\u000bCT\u0019=\u0016gd\u000bW\to#\u0006o\u0012_F M\"#Q/IѯȷP(7b\u00035.\u0000\r0w~\u0006\u0012B~`9PX\u0007T?\u00029; \u001c\u0000<q\n'jp\u00191Ƙ0oEר*F\u001c< ~L!f(#QQP/i1sk99= \u001enmq\u0003\u0001b\u00145\u001c_\u000b4!ۀ?P(\u001f}cyJ\fMKB$gsf\u00162dL\u001de\u001cNEF\u001f\u0007c~cDϲ1\u000e\u000bvK}\u0000\u000f7\u00106\u0001'P^\u00044cA-Bǔ}7bj\u001c\u001f6Ö#qr&)D\u001c\u0015Q\u001eacn .{\u0000=p3VsnCsn\u001d>@X\u0002\u001b\\\bV\u0002?,\u0005 \u001f\u0011!tǻ4\u001a̡Y%Դ\u001bj\u0013H#\u001cu\u0003z:~CCoX}:No\\{5MU\b\u0003\u0018?ͯO+r3nw\u0005fB`\r9HY}LpuD\u001c\u0012(09ZMF\u0006\u001a5M.t\u0012+y&A\u000b\t?,'L2򤨈2%\u001f\u000b`u\u0005M\u001e\u0002\u0015%;Ěsy~QC|\u0003\r\u001d%\u000f'bz\u0004jb\u001772zjRXMI\\I-)'K\u0013b\u000bmB\\@ḨO\u0005H8\u0003\u001aW\u0001w~\u000er\u0002Csk\r3s63Q64r\u00146[!¶K\u0014&~˙\u0012F\"D\u0001]?L\f49.5%Y\t=7pH\u000f`1\u001f]\u0004,\u0014\u001eY1W|rTMOw\u000f\u000fe\u0012C/0\u0011m|L\u0002\"H\nQ\u001ao\u0014\\JhKٍ\u001cU}_\u0019\u00196HϵIӹ\u0012{\u0000\u0019n\r \u000bO\u001eO?|{e/ʏU\u0006{P\u001c\u0019u''L\u0016٠KT2^\bfq Oh\u0012gK\f^\\R\u0006\u0015Q?&\nl\u0010Lj\u000fw\u0006\u0002xѬw\u0007݂\u000f{\u0017\"YMв֞\\;T\u001ew\u001a}˄\u000bnʦD֤ctB5YN7)S92 C'N\u0013E\u001aEC,\u001aP\u0013G\u0015I1YR\r\u0007P\u0006J\u0017[\u0006r\u0007Y¹}'\u001b\u000e}K5\u0003Uv \u000fY/Ηg1c|I'\u001bS\u001cCR(NYd*R!Z2_\u0005ɞ*!hT\u000eAc2\u0006\u0003px3H]\u0006}=@]_Y0\u001a^}gwt#\u0002\u001b\u000bcOU\t\u0011EttAV\u0002\u0017JN\u0013SrY&U+\u0012UJJ\u0014E1Ha\u0001U@5i\u001ekwxN|ҹk5zC'K\u0017Ԙ<\u000e^-j3$/K5\u0013u&-Qp5\rJ暒\u001dQr4rn,Am\u0001@\u00067dK[>Tluٰ}së\u000botxՕ`ߦ\u0011*P'B2p\u00155\t(\\\u0005\u0019<af(+et}VR\f\u000f\u0015Q9#uL {\u0000\u000b>\u0007R'\rG&w5\u001b\\gZ׻^<|}\u0007WwV\u001c\u0016Pr9꘩\u001a{.\u0014+a%\u0015R!(Pq9\u0017<c952|N<>g\u00198\u0006\u00113mRa.\t$\u0004rt\r>SWV:rk>W\u001fX}rKEG\u001eK\u000b2؀9ZG@$Ub\u0015\\TDc\u0017+شB-h\u0012.Y\u0018K\u0014}\u00036(E[%XӸ$.wBl\u000f\u0010y;\u0002\nOU+ڼ\u001dG\u001cr꽳ݳҚ\u001b7\u0016\u0015y(\u001d\u001dn\u001a)(A=\u001bǮ\u001352:ZVf$+̂J\u0011]#\u0012E\u0015OP)=@\u0013/q\u0004֯\u001c/qxpoӡrΟ}=\u0007\u0003K\u0007+\u000f3F\u0004NȺ\t:\bV\u0007\u0013Mi\u0010\tӒLC5\u001b\u0002vDS\u00057\u001b<\u0000]~\u0010Qm\u001fP.r\u0004F/\u0007Pm`C߽y\u000eݏ:6Žў%GVg\r\u0007\u001b\u0016 \u001duDЏ\rfB)7\u0018^^Lu)6Z2>\u0017u\u0016䝆\u0001c\tЪh](VED$\u000e\n*d/F\u0002I\b\u0004\u0004\n\u0015\u000bb#ngT\u001c-.u\u0001Gܷ\u00020n\nB\u000039+r?\u0017%RC]9˻RzU.y;w;\u0016l`\u0007Wq\u0017y\u0017-g?cS_\u001diy\u0012=*\u001f|\u001f\tBKZ\u0005JO6>b)MSXT*4V\u0004Uj^cu:\u001fZvctWn`>ӳ~˴\u0005[\u0011\u000f9\u0012\u000fN;\u0011W/9\u0011\u0010'%j:f8\u001b#m\u0004ϲL\u0017viTv:^֚ۖǔ.[W\u0005d\u00161uV#eߴj%?\u001dPbv$k\u001d4\u001amv!\u000e&2yҶ]7tG۝8\u000b\u0012/t)\u0015]8IWN0׵^bvWrRsLyc?\u001a=\u000e*˷\u0007\t/\u000e\u0006\u0007m\u001a\u000b$\u0003\u0015\u0003KQ\tTL\r\u0002eP`F80+c_Ĵ\u0014ŦXJ\u0017\u000fU$&\fU%\rJ\u0019>\u0012=r25j\"#C##Kn\u0012D]=q=ɑgDGw>ѝW!p|!ݲ\u00117=\u0003^Jp|\u0010Rq^>(\u00059!Q\u0010\u001a(\u000bH\u0010\u0015aY\u00141!\u0018\u0013;B\u0010G.\u0010;\u0004QȞX?2n\r\u0017)\u000f~c3\u0011:Q/H&\u0000Ã\u000br\u0016\u0013\"d(|\u0012!/1B\b?\u0004\u001b\u0003\u0002\u0002T\u0007`\u001f\u0007GMG\tb\r ֶ\u0011j+}\u0016<\u001cAw#`\u0010\u000b'p\u00113nI`ǃ\u001a\u0003Ѵ(ȦG@=#\f:\u0010d\fR\u0000\u0014\u001ay=\u0017[9\u0007}Ʀ߷ V|a\u0012S\u001dt\u0000D}\u001eHp\rGP'\u0004\u0002'C>i>ԓ}<\u00179S|P6\u001b%_z\u0013\u001b=P5u\u0006v\u00041\u0011 \u001aġP/r.\rܙIH\b@Z^(%Q|\u0017\u000bDJ\u0006/\u0015\u001a&8X`a\u0001:\u0017\u0007$\u0018I!a\rxa;{K\u0019!Ȉra\u001b93a\u0010ӡ\u0004@\u0013\neq\u0014q\u0010u1\u0004S\u0000y\u0005n-\u0007\\\u001bHnlf裆XT?go\"a\u0006H\u000e\u0002i\u00079C\u0017\nc\u001brY3a\u0014aH\u000b@FV\u0018ҖECm<$ 1\u0015n&x\u0007 k&i}\u000fV3\u0005\u000b\u0004#~\u0000{P\u0007i\u0011\r\tکaa\u001b5,\u001a\r>\u000e\u0010.A\u0015\fC+Ĺ!<\u000e2\u00000\u0017DC:\u001e\u0010oe@X\u0006u\u000bQ\u001eS|pS\\\u0017(n\u0013D\u0016{;rPo\u0011,'!6@f A\u0013\fc8\u0014Lש\u001e( _\u000f6\fhLj]\n䛙āh\u001f\u000f'#NwY<L\u0015[ȧ\u0001򍤏염̒v\"k\u0016[6A>\u00063a)X<\u0003\u001c,a&\u0014Fc42\u0012Q)m\u0013kD\u001c,\u0003Bg_ \u0013ܒZTO.\u001cP&6+\u001b%_e\u0016-\u001b \u0000/\r\u0006_'\u0014\u0006E}4\u001dpR4\u001fBo`,L\u0018\\jV[x\u001e~IvX%=!+9x-\u00147+__)[T-\u0001=YsSn\\V/*G\u00075f.\r9sPl8P\u0015Y^X#*EP.r`i^|onI)k-筮\u001fE\u001dҗvElSec\u0003M셦Y֓~G>A^W֯;\u001e\u001d\u000e8\"߇U\u0001cP\u001e\u0005wG\u0005\u0013s-\u0005}5bc)pڳS2$kw[4U\u000fՇ5\u0019wtO7T]Kzuᔦp<p,ctPY3dz;/J?G\t\u0014ʔ\u0019C9}~kUa\u0015\u0005O^i[+h2VJ\u0019n57^KYEspI}%낺)3=\u0019=ƣ\u001ec'ݨ6\u0001^(aS+6LX4}\u00157oFyP:}oKV\u0014q.[#B~5wsڥ\u001d\u0019\r{\u0013S]_QMi\u0000P\u0014\u0004\u001d\u001bXP2*:\n қR\u0003\tɗ\u0002 Ih\u0001\u0000%t!Q\u0014\"ʂh\u0018x\u0001w\u0004#IY\u000b\u001dfo:^O\u0010ERS\"\u0011HN\n8\u001aLAȲ5,2_*\\7{|Ž%a?<ˏ=? \r\u001dJI\rEޢ\u0015Ĩȥ\u001e\u0014ۅow:\u001bf0E4\u0016(7*\u001bH\u0012w #jc\u0002\u001e\\\t[YX-Tylf\"n(<=\u001eŷ?\u001d|#jd7+'\u001aTJ5k\u0016r\u001dZCK&<K:Z%IO\u0015\u00167\u0014\u0004\u00108\u0016+69(8\u0002.?b\\̺:M/꼷,\rՔ]r\u0018\u0012`\\sH3\u0019A]iȶ+&vAB\u0003,IF\"Irj%^N\u0019(P)5TLх4=M@[\u0016~\u0005\u001c̦#\u0018\u00163+\u000f}\u001dXlp\\J~Z#ʈ\u0013꒸sB<+\u001eԚ\u0012)\u001eSMJ)WŤ2f=\u0018\u0004P\u001f\u0000zgd1P.SGai\b!p\u00022\u001eo;:\u001fڭX?fk:a1vz͓f7~\u0007V\u001d+9,\u0016P\u0002\u001bsX\u00112^Z$=+A\u0015S+ȅ)V(b#,^\u000b&/YLAzX\u001eHf}g\u0004!mG͞whs:6^IK([^L\n\u00150\"Ĺ1eY\u0004af\u0001>?VM63rz\\?Y\u001c\fBr\u0010s9z!p\u00122;\u0005i\u001ck#|r\u0001[a[!g=,Ʈlׂw1XWef\tƫVD\b\u0014\u0004)tL^Nn\u0012?Γ8rFJF7qxg3Pr|UO3\u0004& S5`їƽ}/\u001f0~_5t<᳷9h[C䙆xO$_TN\r\u0013r0<AvRZt%OLc4@Pv'fQr\u001e9Z\u0006-K\u000b::\fI=mB(j;jykNm\u001bx\u0011gSzl\u000f8h8]\u0010Q.\tȡbrN<K..$2ʩTA\u001dT\u00173\u0004\u0010Z\u0006@\u00074Ra0\u00159\f+\u0014\\!ۊznzyc\u0013Y\rɪVua\u000byL\u0019\u0014ɭ\u0012˖d$+22^$% LY\u001f\u0014/\u001aC'i\"=\u0015+4\f\u0001\u00056?\u001b^\u001er\u0012߳F\rݵ[٧>󖻍\\g'\u000e9Y\u0019ߎAZ\u001c\u0005-՘\u001cM\u001aOd%\u0004LM59\u001aU}v!\u00155J@XĖ1\bfGyPd\u001dв\u0006<S\u0002\u0013V#AӞ!u̓ne\u0005K8/NWE5J\b\u0015Ih$dc⚋QMR|\u0018PBF\u0011/EbD-Bf\u0018Yk'j0u\u001ca3pG\u00114L\u001f\u001c~źrg`0h:{;<\u000fCIǫ\u0018!\t91=K¸nIBR\u0018\u0006tGa\u0002Z\r3\u0000Xd\tf\u0014+`%P\u0004ɵcrqQKE\u001a=\u000f\u000fs`\rG\f%'#`B\u0017\u0007S\"BՂ <o7W=F\u000f1ap\u00056\u0006m`De\n\u0007M@Ϙ\u0019hZ\r\u001ai$:d^ic\u0013\u001di\u000e&C)\u0013Q'q㘳?\u0011ܢ~\"ƮC4<\u0000 O#\u000e(B|4c#^c!^\u000f߆y\u00119\u001ca\u0012\u0013\bv۷r\u00144Oڹ@<gc\\4{<{q=5W=\u0005b_<Cp\f\r\u001a0;aZ\u0016{{M+|<gz\u001eχEO/ݦ:lЌ\u0014\u0000M\u00115\u0002J1P<4\u0005UÓH\u0011Uބ=ju\biݬ\tZ]Qv1\u001f\u0003)\u000e~lG|i\u001eZ9]~\u001cYy!\u0000;Q@ه\u0002a# 4\u0005Es@޻wM[R;nHz%K\u001f.\u000e\u0010/C߇\u0004;\u0012\u0012dﾔzuę?O9~R:<t˄g-Am\u0000t\u0002 \u001f\u0004@A)\u0013c\r,[\u001b1\u0012<*OQu\ncK_ࠝ>p.O80v9\u0019f\u001e<\rsmOv\u000ecb8fZp(%-$T,,5K34HDu\u0013QP\"K\u0007ٗdZN<9\\vupdi}{>Q\u001f\u0010\u001c\f`\u0005\u0007>7ZNHM\u0017$RC\u0012Æ\u0002Gda\u0019\u0004+\u00112ZB'pĂp2\u001dS\u0014\u0019Hr]\nj \u001d\u001ayhC\u001c_K^hyb5b=\u0012\u0019lО#\fpQ,\u001c[\u00018X\u0010\bG*c\u0014\u000eE\u0010_\u0000O\u0010\u0004D\u0018NC\u000fVN)i8\u001dGU;ۈ&_HfPHZ!I\b!q\u0016\u001c\"Em\u0018B\u0016\"~>\"\u0003p\u0007g\u001f\u0004#!\u001e\u0005(Oh\u001dg3a\u0019NQ4\u0015N\u000eB8k\u0010C\u0006{-!v,t\u00045\u0019J\u000bd\t\u001e@T\u0010\u0000~|p7c1?#H\u0004\u0018KAo\u0004*V\u0014\"t@'\f@\fP{}dY\u00077\u0019`\nb \u000bu:\tZ34b\u0017(\u001e@,\u0000i!\u001b\u0001֡%`D(0~N\u0003\u0001\u0005\u001d\b}\f\u0005G6\u00189?CL \u0005 [(B\u001c[\u0004=\u0019\tq.Ш=4B\u0017\bqq\b\u0015\u0016\u000e%\u001e\u0004x\u0014g`]y\u000e=\u0006;\b{5\u0004\u0013x\u00055\u000f,k  2\b)B\u0013lp'0\\Wx@c2;\u0010U\u000b ._\fQM\u0004\u0004;#\u0017\u0005\u0011\u001atp[\u0019\\\u00066scc~\u0007\u0018p\u0007\u001a\b\u0011G\u0016\u0000{ÜʘT\fe\u001e0}\b \u00145alZ(~\b\u0018\u0005'gYb.\u0007cny8=לOO\u000f11v\n{*D̿D[\u0003\u0011!އ\u0002-L쑾h\fh\u0013śH 1%\b:K谺8|H!rP6 \u0013c\u001da=,(\u0016^%\u0012~w\b\b\u001eBx/\u000e[b\u0010E܋\u0002=!\u000e9a\u0000\u000bg\u001arܑ\u001eN6\u0006\u000eC=ڵQTUnE\u001d/\u001e?%'bW\u0004/w\u0005\u000es\u0007ᓸ\u0007ے\u001f\u001bRȬC\u001cAIɃL\u001f;8bXɜ\u0002!|n>sZz\u0007s~Ē7\t\u0015ѯ4[؝\u000e>sQSYr_\u001e?\u0013ߓ\u0017ߑǷKWҋayu\u0010!CNF\n;ڢ0x\u0014ǡ<T\u0014[({\u001c*#7UMkO\fUG:\u0003n=uS]\t-yM5YGqI98\u001aR6k'4C\nk %\u0019D+\u000et@1\u0013rwƺwVt\u0016\u0018\f{z?u7iC̯\u001a?\f\tWmӊK˪\u000b[V\u001f곚fnPs8aPݤ\u000er\fLd\u0010So\r_+XɜzkglA\u000f\nRڳVR6^J\u001awc\\~\u0019qusBd\r'#C\u0001ݾ\u0001^n\u001af {\u0016\u0017&c𦐑=N\u0013_lN{Z!F\u0013x\u001cv f)`_)\u0011\\\u001fגYz*eyExŰxh21\u0019v&\tuA3\u0006lQfJo`MEo\"=ƚ*zU5ŗҩ+,e\u0004'sG*e\u000735h\u001bS\u000f$N>ؐ|Ѹ#i{KcmJqkjobMZ:Oo\rtg\u0010w%;\u0012y}w,p\u0015>zݭB\u001b\u0017/M6\u0017小\\!8D߲^7ZՐUPq̸%5:=iszGRUg\u001ecefobEf\u001a\nb,g\u001b\":z\u0011\u000e_Jמ 獡#\u001fNvF:unrsԱLvSQpxWZy}&6K&w*簩2yCgu9Ir\u0018r{\u0013A\"\u001frYLtފ\u0019#oser\u001fɁ`{&^ɛu6LfJSdSy:qM\u001eP\\Tee`KBE~Cb2isjrqؤϷ&,\u0000%!\u0004T ; (]@{\u0012:!\u0004PRB(\u000bR'DD H*\b\" \rqw\u0019Pag\u001c\u000fȇ99ߒs9\u001bI$(BV\u0002K\tS%> ~\"^=7y^as`&ETSYAʨcGq'\u0013y3좂s\u0014nÔ\u0002/\u001c.w-XO\u0016lDde1%PD _*s:bh\u0007qИvN~Vqt`~xv>ǵ6Ç_\u001bTSq4Һ\"މDnW49z)p}8EGדrlD\u0014@`VFExߡ\b³JdT=bH2`#7>\"\b\u001ea\u001ak{?~л>;0y&6)!3)l09l:`\u001d9e̒\r(FP\u0005y\u0016yX햅#`\\\u0005\u0016/X˜\u001fpQ\u001b\u0012<\u001dcr9Ut(P\u0010Z=/2*PmC|zu;+lrJ\u0014'&I̩ZgTn$VlDt_$\u000bX'\u000b\u001fڤE\u0014mۓJper7ujRzdYgg穾P3Qֵ]\u0015S<xm~y-E\u0011YM\u0015Q\u0007\u001aqmID$;DXb?Q\u0014̒%T\u0006\u0016x)\t+pwB\u0012nL+\u000ee|j\tm\u001d缴Z\u0007\"-+\u0019d7 '3'0дHv[}tָ֞,fuDfĨ\u0013b\u001aE\u001ci-k\u000b\u001d#tX99\u0012\u001bd*%a(Nyh'\u0002EFcmCl\u0003\u001e\u0019g\u000fqzKFFwDEvwǆ\u000b\u0004WB\u0019\u0017*x\u001b\u0017!6]4n5\u0014\u0015\u0018\rfp4\f_$z\u0016l\u0015ϻWLp\u000eO\u0018S]8Y\u0002ђ@HuHHsxȰ`9f\u0015H5'f`hȓ\u001a\bxE!q<\u00057AϭDM\u0003Z㲵LJu_-\u0010\u000bL\u0013R\u0013.e:Gf\u0002\u0002|GC|\u0017Bgx_\\\r\u00185-LOb\u0015V/\u0005Q`bkT\u0010ܣC\u0003%hxZ\u0005w4\u000e\t9p;Ґ}+4&2j96b)\u0011T\u001cX8}qG_k'+>NA\u0002&&\u0018t.C#I.\u000f^hz-\u001f\u0001;XO#v>c>N6\u000en\u0016k\u0011Rlrk}xg\u000e.+98=7\u0017Q\u001e;\u000bpa\u0014``\u001a\u00184ݣARP.F\u001c}CycJO\u0017$\u000b]\u0015ㅾjQPpav\u001b:MaC/\u0011\u0013\u000fao,lfʹ%?wHo,\u0019\r\u000bןDY\u0012\u0000\\\u001c\u0002\u0018$\u0001\u001ao4(^U5\"kUfJglYsVXV\u000e^\u000bR\rx_md-\u0019;]:fֳ{l`^`h>jd~r\u0001gc\u001b\"\u0003\f\u0001t^\u0002hX\u0002x@@!\u001c\u001c`CӘ\u0016J*䣃t'w9O~[=>*~fnsK;jZ|[\u001e=8\u0004\u0017t\u0007\u001d#\u001442B/kd\u001e@su:pP\u000eQD-J\bSь6t7t䌞[\u001c_\u000eCe!S\n\u0015\"g\u0019f(`\u0011*\u001b`\u001eTݍ=.ne\u0004\u001f4.\u0000O\u0001\u000e\u0006H\"\u0001Q(\u0003D'P\\ЈhCFG\t\u000bt\u000f}\u000f\u0006J\u001aa\u0001FK!k.<y'lba&6j`\u0017鬜:<GW\u0000\r\u0010\n\u0010\u00143\u0010)fhH1E3\u0011ZQN|\u0017:렻6о@&1FB\r$T0tE,+`\u0002HcHdHA'S*z|,hgK\u0000wi\f\bRDXUNہ\u001eyZNzx\u0000\u0019]F7FQ\u0013\u0007Lvt\fm^~1G\rgsEo/vh\u0007\u0003.\u0002:\u001bPń^$?s\u001a\u0006c4\u0006\u0005*b`*hw6zvk>:7\u001bict5A=Ș0EƬ_lWXi\u0016\u0006?M12q\u0001\u0005\u0014\u0010\u0010J\b$ވ\u0016:&\b\u0001$\u0012\u0006\u0018*e\u0011\u0011QyPE\u001dY+:긺\f(#\f\u0010~|\u000b\u0001G E\u0015\t\b3N:\u00028ͺ;8Oz\u0000\u0002\u001b@5\u0000!\u00048\u0018\u0001\u0018&c\u0001G\u0011\u0002́\u0000\n|5;Gk\u000b:{nq\u0000#x9\u0015g\f8\u0011fӸ/\u001e<.ou[@1\u0000?\u0007s!p@3\u0006\tif o\u0004^9-j\ry;Rf\u000f5\u000e@nr\u0004v' t\u0006R/2}e_^S\\?zqfLxÞ7$\u0017\u0000>h\u0007\u0001p\fA\bNAF\\\u00012\u001ar6h\u001fjіI,[\u0017t;RZq3~.Ӿg\\^3E\u001e&$ߑN_%\u0019\b|\u000f\n\u0010,\u0000\u0006\f@`i\u0000RkC\bٽ\u0018V@8y5\u0006l 9H:ff\u0017\n(wĬMқ\\?\u0013'?z\ru:L\u0018\u001fw\u001b~v\u001f{\fS?xJ\u0003;o\u0001e;\u0001\u00125C\u001bB\"/\u0018oS\u000f\u0017lK\u0016lY\u001ak3)N\u0010d;\u00159u\u0005\u0005t\u00123{ܟ1N|ʸI/W\u001e\u0018\u001eIs\t>\u0003\u0001@e\u0001@\u0007>A\u0006\u0010n\u0011gk\u0004JXO]%i2Bӟ֯e\u0007Ǥ鎣\u00022Մ!n\u0013\t1!\u0001kt\u000ek\u0016k:K7\u0002J?\u0007(}\\[\u00000G}\bEb=\u0012l\fAd<L0R׼?8\u001e/\":<n($_A{\u001e\u0006\u0016\u0012\u001ew^f-q\r^5^?e{z;B#\u0000Z\u0010h]\u000b\u0000>HQ@\u0014[!\u0019Mڮ{W{zn4yX)(6~\u0001;aj<ⵠ\u0012*+6EI>9?\u0018ǌ3qf\u000bK\u0004\u000e10$H 0\u0006<_^\fꝉh4\u000b\u0003]\\ܒ\\w,_!5{omwr\u001bqq\u0003Q{/3=.iH}!徽\u001ajϾ&)i\u0007d`Oˬc6'v\u0014MU\u001f\u0004\u0005\u0000\u000fE]sz=H٤\u0007[\r<E!~鰆d[6AZr\u0018܅\u0003ngc<{r}Ŕ\u0013a\u0015:߂XnN\u0002Iv {ƫ\u000b=\u0012V\u0000*\u00148\u001aP~\u001e$=\u001bQ4XhpybUw\nh\u001be-/#{\u000e(ܺ\u0015ɞq\u0018\r5~4&A~]\u001bɭ\t;˯\n&\f\u001b\u0012h'ey^|[\u0012-ӃH7P\\lқ(ݢJ]wr>ע/Kj{F\u001dܕ\u0012XRgkܴ?Z\u001fWLdUE7pQ=_DőEQoQ3C:~AW\u0010=\r1%ޙ\u0016h\u0003FIiV\u0019\rV\\-[SOxgWVS{zTg*|$1ZpqXqU\u001a_-k\u0013hbOc/sc\u001fs^r⦅sx\u001d!\u0010!n\u0015꽫QZM}y\u001d6T\u0003vnj\nҀ'\u000b;\u001c#\u0019=T>\u0015)2U>(I*\u0005ي.Q$]qWV\u0014S4\u0010)u߀`_vP@cMjM給`:IkOk\u0019[\nlZ\nϗΉ#j3\u0013I%iCibVvr\u0015/]$8)NI</Q%\u000eJTIc\u0012H4+T%\t\u0010 \u0014CJ\f2D\t6Ҹ\u0002{в\u0016lep\u0011imZuCԡ(U!%49,zfF!+M]MNk\u0010$\u001e\u0010'(Ro\"\u0012\"Y2uN\u0010\u001b$~A\tt\u00056td)y\u0019v\f\u001bhfpyFOcVsTHvUDk\n\u00159d\fZj& )07!N\u0010.Dg\\Dg YaL v\u0001\u0010\u0012G\u0013\fcZcq\u0012^\u0012f)vBqɉ\u0016&ʏuum5\"*\u0019Np.J/MM)V'\u00161\u0015RNl\u0011~T~PwF\u001c7\f#EyByΜ\u0000\rb˱CK߫\u0016a\u001b\u0013+'t0n?F0ml?u\u0016\u0006pJP\u0016aTd\u0011@B\u0016 \u0006\u0012\u0013BB\u0012\"$@Xª(.\nUQ\u001cPȠ(\nn \rP\r#Z*KM\u0010yONz;պTxl6yo\u0013qBi~W5+y;)-4,^\u001ch[E|fI)xҜ9?[bؔQ4u,̱\u0002,%4xPɄ۵LRτ6p\u001b\u000f{zS\u0011\u0003{\u0004aam_{swfUn\\茝S\u001b\u0013/Tޓݧұ0\u00126Q\u0019\rAޞ\f8H&+hhq\u001ch\u00162N\u00058r(jr+lקV\u001f\u0017Pt\u001c5\u0005\u0011smLa0UW&m0=\u001fg{6\u001a\f\u001av1nX\t϶\u0002ܫ{@4h:AV\u0016\u001cl\u0002{x(&njM]\u0014ds}\u001e[$^ؘ-װ24h*~6Lg\u001b\u0015sPfu\u001aG\fQ\u0007\fQР?8P\u0001m\u0000(p\u0010\u0015\u001bI\u0005\u0012\u001d.O\u001ev?֦K2\u0017+GOi3q㵠u3\u0002SO\b17i.U#굺ڈ\u000emDSV{?B{\u0002u\u0000\u001d\u0000Wj\u0000N\u00034$6\nT^e@\tPtˍRxˇzō΋%LC\u001a7j R˹~\u0002\r훂#۷KuU2M{\\\u001a\u001a~x%W]W(/`<*\u0012U\u0000\u0000\u001a\u0001Ԟ\u0006DL(?\u001e\n\u001e8\u0007|Z ֲa\u000bϞqڙ29\u001dבōXΏKQ(vl\r\u000b\bh\rTt\rPt\n\b\u0017$3\u001a,cܮ\u00008_\u000bp(&'ϒ4i\u0001k~\u001e\u000fy)mP\u0017\u0018̲qifm9zb\u0010c7/r$Mk^V7x(\\'7\u001f˞gr?s\u0002a#_j\u0007p\b\u0013FW\u00016ܥª\u0016\u0016^9SRӻ|\u0019.\t+Keex\u001di\u001bh\u001f:e<\u0007U\u0012GEw{Tifא27qO7\b|s\u001d\u0005ۿ\u0018\u001cF]gH2\u0000\u0002YϘ\u000e?Pz9Ը^\u0011'f\u000bei5Tz+@| V:0.dp_\u0006&\u0006\fOa)>C5Cǝ/:\t;\u0005/1\u001en&K\u000b`ŏ\u0000\u0000\u001fX4j\u0007FtM@\u0001-\u001c\n\faPBzV\u0000YaL\u0018Yㅘk|kOb\u001eX3\u001dٱ~\u0006&\u00146r\u00066\u0000ȻOO\u0000\u0003\u0018G\u00106ɠDW\u001c9\u0010\u0006\u001f\u000fi\"ӽQE\u0017h\u0006\u0017\u0013Ɯ\u000b,0b*e9,'aՖS\u00013c3\u001a{\u0018DQ\u00014H0\u0002)ځ\u0018Pq\u001aE\u001e\u0014!\n<\u0014Q=0\u0010\u001bi`\u0004\u0011\r4\u0007LOt=.a.\u0016ʰ\"aD\u0018\u0018CE4TQ\u0015DU8\u000bcPf([\r.\u0018R\u0015n(A\u0018S\u0018x\u0003\u0003X9\u0018xG\fr0\u00109\u000e\u0005ACڗZ1\u0013J\u0016j\r֨IGբ\u00188h\u001aJ*\u0004\u0018\\'8(>M\\\u0006'\u0013o<G\u0003Q`\u000eG\u0004\u0019\u0014B't>t\fb`8dL\u0007T;YR6*q~\u000fuF.J=Qr\u001fNި\u0017?(KGyR\u0004$%zQQţGC1\f0Vg\u0018်Qf\u001a\u0017@e;b/\u0017C\u000fxbQި$D*,,\u0018\u0011\f\u001f\u000b]彂w\u0011\u001b9zЧ[0OE-z\u000e\rc\u001c\t\fLZ`\nc16\u0001\\0j\u001b\n#ڭaMz\u0017o0|?@uDЧj\u0014*[>*/x}P~|ݣ|ݥBY0<\f}c%\t\\*fS1wM\\\u001aH\u000bt\u0015dr\u0018t\u0019q\u001bƽ7j\u0013Cd\tn]\u001e7\u0011\u0007{G}^kNtiD/5D/4\u000fDj\u0013=|f\u001a\u0003~Rc\u00035\u0006\u001fu\u001aԙqI\u0010\u0014D\u0005Q⊈\bȾCHrs\u0013\u0016\u0001\u0003\u0004H \u0004\u0002\u0010\u0010\u0012\b\u0000};\n\n\b#x\u000eZʴiZ\u0019ԱuZ>s\u0016x9||񐊵n.<o\u0000{\u001c`Z$\bkT\":-~\u0019*?\"Xu9\"Z{JSķ\u0005䱓\u000f3\u000e_:'/:._;}N<G0d6,\u0007I{0t'\u001eFY!\u0013\"\tG2v\u0014w\u000f\ro\u0012iv`w/FFJ\u000f?\tW<\f\u001c*^\u000bZ\u0002\u001dty\u001e2~z\u000b}zm\u001a1Bk(BQrbm\u0003\u0007c1I\u001eؿ]7<_ӗMNm\"s7bDG\u0016r~~.Bx+lXˍ.A!c!z]\u000bk<H;!g(\u0014\\\f-\u0007i8Hǚ3a\u001b֝;ڇSxK3\u0001a#^=.c\u001dvҁ9\u0016lnp\u001e]rj^:qjdhDaIK\u0006ß\u000f\u001bO\u0004+q0\u0006=V\u001c<m!ڍ{}\u0000Jfk(s^(\u0017BgV\u0003ӜTI8+q4^r9V~)B|T_\u001f}0~5MB\u0007\t3%\u000fBS\u0014$a`\nil8;2-\u0000̶Ľ8r՗roو\rQ\u0014?z<cs˷\u001fH\u0006y\t*\u001eλ+ί=5Ghb\\!cfH\r1\u000fHujc'BbU\u001c\f`9\u000eK\u0004\u001c|\u0006^\u0015\u0004\u0017=(5/XO9qˤ4t(zXh3KK\u0013Ns-lϹj\u00069B\u001dXͼDB\u0017\u0010\u001d\u0005eF.cA&\u0001\u0012+8z\u0011`\u0013x\u0005(\u0000Ֆ`AmcpSfr]I|U\u001el9$\u001f\u00103dg8$n<zʷ&<\u0010c4A4qJGѢwHQ\u0012$\u0017r YɁ`4v\u0007\u000eּ;rB3\b\u001e,m\u0011xB鲒ɀ<r_,h[\u0016D \u0010s*yڴ\u0000ujmJ.L\u0014$[Լg</\u000b\u0011\fy%5/\u0017kNz1o\u001dQ\u000e<ԙJsp ~JfT񂊲W\u0019=q\\N]]vcX\u0013J=5|_U:l\u00151ׄ{ќ\u00114m\u001dM{JxQ$<`K8lu\u0000JLO\u0005kC1Wa\u0002k6\u001akx!YC\u0015I\u0019}N:^⨕]J<|\u000bD\u0000(\u0013\u0011IF7*ʸL\u0013f|J\u0013d<e\n^S3\u0005R2\u0005\u0010Y\tdb\u001b`\u0004<)2\u0002kjcp~#߇\u001b7\u001a]N֢\t]_B?TU\u0014o-8(x.r\"''GZ\u0014-\u0011EY\r@܉C4h.\u001a35]\u0007.\u0014\u0018\"K\u0004l\f\u0013:\b|2\u0004\u000b\\\u001a07\u0003=F;:m\u0004\nڮȃZu\u0012\u0015(9O!͗d)\u00032eA:r\u001d.RS4>\u00155Y\u0011MAJ\u0014\"KA\t5\u0002\u000f\r*#p\bL6\u0007#-p\u0003Ͷz7Ӧ\u0000\u001aJW\u0015n]R\u001ec&S٥\u0019\";H+,%p\u000bjHVJb\u0000e)Qa^b\u001f(,\u0005D\u0012 y)\u0006|Z\u0005\u001e)qn\u00153\u0004כ\fX)a\tzmVoRG,K)kȫvٕɎ|3LV\u0005&V\u0012%XU?@Uw\u0018(1ſ!1Ő(Z\u000e\u0019\u001fe\u0000W\u00010Wi\u0000\u001b\rx\u0001\u00186\u0006}=A{a.'\u000eM6\u000eeKȞ&!>6!$.ݙ[+tOfU\u0015U\u0007FW#ȑWy\u000f\b{R\u0016\"\u0014wy\u0000\u0000p\u0016\u000fь\u0007Ý\u0000\u001b\u0001s\u001f8>Zﵡ7\"f\u0019i-hg\u001cMoKKiIuHl\u00167I\u0019z7Q\u0017\u0018\u0010C\bi\u0018\r\nn\u000b\n\u001e\u0014\\+\u0006\u0012k{'\u0006B\u0000>\u0000\u001e\u0007\u0003p\u00176?\u001b7{qevC\u0017\u0003d]@?\u0018\bߓv> eЛb\u0017w8Gv廝x\u0006w{S;|)\u001dW[E?r/~V迒g9\u0006j\u0000fj\u0001\u0018k\u0001`\u001bs\u0004@=aSN\u001c3\u0019w1\u0016_3\"\u0016ܑН]QM^i\u001c\u0010@A\u0004H ,!!\t\t\u0004\u0012\t\u0010 aȢ\u0014\u000bѶNjkkGfܵ\"hE\r.\bq\u0012j3/s\u000f{{\u0013s\u0003fW/\b=4rl4:&e\u001fUԉU'b\u0012\u001a\u000er(PV\u0013_\u0001}P#>\u0003N\u000eW8,9u\f>K~i]ԅ\u0017܋/a坟ÝyDUD^Rj<h\u0018h.2A>\fNOD{Z\u0019\\\u0011\b\u001d\u0019oO#\"V7Њ\u0016w\u001aX\u0012N)iQOͿjr˹jʺZ\\25/$7'6}&o 7}\u001f\u0018״Gm:\u001ei=\u0016i\u001a\u0007c\u001b l\u0010:;\u0019wP^\u001a\u0001Ս\u0014\u0006\rͿ㌊|QMD\u0014\u001c[}fpN\u001aۊ<\u0012\u0016zǷ1tmk|cm_blԶݜǸv\r?6Ov\u0006wP;\u0011;y\u0005e\u0014\u001d\u001a*pA\u001dLd\u0010\u0012\u0019Rԩ3vΰOJuvuO*vt/v^^\u0019ٳK޳[s.=͐^cHz\u0018ak=U\u001d>GhùwK[\u0011w@9\u000f(+JcԾ\u0000\"_L+)q\u0003Z;@\u0002U=h\u001a̦E\u000e;ȇ\u001d#J$ëp\u000e\u001dKi\nנZV7n7ˁp;\u001b8]~Q\u001bB\bi8\fc>H7'\"\"zBJ*'T\"}kC]\u0018dR!\u001a\u0004EBXd/4\u00078pܑ\u0003\u0015~p֑\r͎,x\u001f\u001dx\u00165quoC(\u001b'u\"4c\u000b)d  $\u0010L\u0010.9\u001dt?$\\0Q \u0002\u000f̷C\u0017|n\t\u001e\u0013\u001d\u000ePݠ\u001a}f\u0006>g#Ѕf\u0000!\u0015\u00108w\n\n\u0007W\u0014\u0002(\b\u0011\u0000|\u0007!\u0010g\u0005\u0005\u00005\u0005q\u0007\r̤+$a.9\u0015\u0016N\t\b)\u000eBr=\u000fH$$(H\u0012\u0010-@\u000eTPiw\u0002\u0002gp\u0005Zwl!_t\u0010\u000e1 \u000fb\r\u0010v\u0003{\rcb\u0019\u0013h\u001801d\u0010U!$Ą\tVa\u00078*Ĥ@=\t>r\u0001e\u001b(>\u0000\u0006/}K\u001d\f\u0003\u0003\u0011_2AR]\u001e`O\u0013!tZ\nWR`HR\u0002~\u001cE$bP\nev0CK\u0005\u0006q\u0016'\u0016@\u00127'\r-\f\u0003r\\>&\u000f@~\fa\u0002\u001eأ\u001e+\u0000{X>\u001e߀\u001c8rɀ7\u0019(qVH\u001e \u0012p\u001fIj*$&9\u0005f̙\u0006!v\u0017h7z+\u0013bMDbG\u001dd*FU'9oTת+\u0011-Πӧ<\u001a\u0002S\u0015@\u0007?IH䓐0)IO\u0014\u00140M\u0012\u000f_=_3[|\u001d5\u0012略3\u001d\u001c\u000eh5gx/4x57xk}\u000e\u001b10=\u0006\u000fc \u0007֟\u0004.\u0001)~\u0004\u000bH\u000eEn\u0007Z{4:ML\u001b5\u0015y$҇V'c0l{\u0016ǌ\u001d]^An}SwQDMЮ$M|\u001d[:\u0010A8\bn@,\u0002Ҙ\u0004\u0011\u0017HB>#/~|qĒ2U<}\u0001̷;u\r3+\u0013\u0016ޣ\u001f&\u0014O\u001bp/Bh3\bP\u001bx\u0014tp_t=ᙨ*рK\u0006\u0010_걺I& (NBQ(e(:\\\u0018 Ź77ǽ#g\u001e={\tU\u001c[Zm\u00057S\u0011H!zʿE-\u0007!ƚ+ƛ\u001e9j\u0004i&\u0019\"N}\u0000\u0018}\t{o7\u0001sY\u000b\u0005Rʳj)s\\ΞMoBVkN\u0019ŲZД!cR֐\u001da\u0017̻̇$Vq\u0019SmD\u0017cYi@~<4\bV\u0001J' \u001bs<\u00110\u0010,b\u0013K\u0005%!dW\"fŹbR~]ʀs>\u000b*\u001fSINf패';Q̨<Ѡ<qOy0jjo&`@9\u0019=\ty\b>s,Ae\u001cԽ\"xBBZuh)MְBXRȶ[ȯ)\\.<9q]QMi\u0018$\u0006((H*\"@V,f\u00025@\u0002\t!\u0010L\bK\u0002@\u0002(h5x92\u001c\u001dNGǶs\u000fȇ߹~z}<gS*}.1UGf5\u0005L%w\u0006]H҇%M\u0010F\u0012Æ\u0012o\u0013\u0010\u0013_\u0010{\u0010{\u0010bw2\u0012Nf\u0019t\u0006)hcQh\u0007o;;\u0013<57h~8fq|^BÓ\u0019Rq$M\u001d4\u001a2Kcw3.Gt2\";\u0018\u000fImoI-\u001f#uL$9\u0005@\u0011@\u0012\u0000a}/\u001f}\u000e\r(\u0000r\u000e9#'v<lY\u001ces$aL\tNXk];]\u0019ЛY\u0017ܕ\u0014ڑ\u0015\u001aХM\u0016ɍi)\rJ\u0003\u0007r=\u000b!է#w\"6Cl\u0001\u0003R7%xxQ\n<<rU\u001e`E)zLi\u000b,a>c)̓\u0006*u9\u001a6\u001aϜ e^*3WuZM?YP\u00112\u0015r\u000e}mob\u000bZf\u0001kVPa\u000f\u0006~RM|%\u0019Qz|Ǹ$~(ŵO%\u001en\u0017\n%\u0001ZnUSOP\u0010j8=G`ߡ_ҥhܟ)<\u001bf\b\u0013A%\u0016z)U#%ܫe\u001bfeE䶉ò3\u0019.\fҼMBZ \u000eP+ڰ¦\b9$P%+2-\u0016%&D\u0015q\u0011\u0000lZ`\u000eߗ+\t\u0018ks9\u0018\u001al\u00053k2\"Z*?﯊\"you@+a{6\u000b}jKKKb\u0005A*h\u0014uE!j\t\u0012iT\u0011o5\u001d&#\u0014\u0014YP>e~\u0013L`C\u0004&ZSXQr5\\k\u0003޸qM>ʮSkM\u001emeCJ)׻_V&\t*\u0017W\u0013\"5QXN\u0012<\f@\u0014\u0015>Bsoh\\!B-\u0010\"\u0014\u0014y3$\u00140T\u0002`½z\u00135\u001b:<̶ɖøPFm[ÉZUGJ>EMʪ|oHY8T*\u000f\u0015W\u0011y-$W6Ec-s\u001eF\u0015F\u0011*\"od\u0000R\u0007J,\u001848X`\u0012f:` -ؼbt̡Bpק{\u0012+y~@~,6<_\u001cɮdUL2d\u000btt[Z?t\u0019Bɐ!䭐\\oJ\u0000ީr\u0013\u0016\u00161p\f{\u001c@\u000e0u\u001dָ]r]Ky\u0013뀨1ǳX]k\u0010sTu\nBV&*)LU*CqP|Ce¬Aȿ!mp\u0000\u0000\u0001L\u0003p\u0003~Wy\u001f\u000bz{ô\u000e\u001c1\u0013){˻O9w&)HWԖu㕧\u00134K\u00023!i03\"Y3JJTϑ+\rr|\u000f\u0012ȭ^\u0001:Ou\u0000W)\r{\u0003h\u001dshF}p\u0011|f+\u0019<X?pe\u001c`\u001d{~䎆v+\u0011m\u00063bl뿈-\u0010b}Fqջ\u0019,v\u0000\\DG\u0000<e\rݠVL\u0005MR\u00131\u0017N;';g\\G\u0007R\u000b\u000f\u001b*J\u001c=;շ\u0006\u000f\u001c\u001f\u001czlNhИ\u001c\u001aӋ\u0010\f>i\u0001\u0001\u0018\u001f\u0004\u001b\u0007\u0000Z@՜#H1\u0000\u0013\\%wc\u001b홗\u0013.:3.f$p\b㦥NNz\u001dj\u001d\u001f5y˟>?}?O\u0001q$6\u0004nfDgpG\u000bp\r=I=\u0018@+B;\u0006\u0016D7x\u0015xK>ؼ04+\u00136\u001bg\u0016\u0019\u0019\u001f|`r\u0005Łf\u000fڵCk3eO\u001f=IW_zFοC#fw\u001ev~Qir\u0003\nos\u0017\u000f+ k \u0012cLV-&۞˲?f`;D\u001bx;\fejgA'зhv\t7|\u001afkg/]\t\u0016z\u000bٿկ{x\u0017`\u0014)\u0000,@\r[\u0000ߙ@C\u000b8\u001e`6\u00124\u0013f1Ƴ\u0016Gm4c5ȵ4\u0011W+jv8\u0006N\fZ]\u0019 _;\u0005<Bvm5ߍ\u0000=\u0000Z4h=/p\u0010f\u0001'ZñN\u0010\u000eG1gD,Y\u0014I\u0004fl|ˠrZ6k?:jJ\u00038I%@Xe\u000b\t\t\u0010\bA\u0018\nAvd\u0005qڣcRBQ,r \u0003V+]Zƥ֭\u000e+&g.gA8;~p+Y',YUGG\u0007;}-mhCc3X\r$\u0006r+ϓ~\u000b\u0000CA!\u0015\u001b^\t`Z\u000b;e0RuM]Z;.N{`x֓\u0013\u0017l1\u0010\u0018V3]ޞf:me:{tc:?p\u0002`#q\u0013`=\u0000m\u001b@`\u001e\u0004\f\u0012@1(\u0002\u0017ȆdXM?\u0004Sn\u001fi#q4Tڤ?̣~\\C\u0019\u0010~ǰC\fKld\u001ax:NqM\u0000\u0005\u0003}\u0000\u0010\u000e0) \u001d\u0004dh\u000e\u0012\u0006\u0011:\u0010\u0019=`\u0012*\u001e)[\f\u0004\u0018BYb\u0014e\u0014\u0017(\u000ḛBf\u0007i&xh\".S\u0000ߢM\u000f\u0001>{\fz\u0006\u000b\u000bLpA\u00168\"4\u0005```\"p\u001bP\u0005,\f\u0004\u0013RF\u0018C\u0019`\nl¥\u0014zb'&jA'^R\n4TxPQ\fHG<\u0003\u0014/ch\u0011m6F&Vjr\u0007\u0016\n\u0010l\u0014&\u0016\u001ee\n#n\u001e\u001e#D\ne\u0010SNC\u0007CC@:*\"\u0018=S\u001f\u001a,\u0010kP\u0004%;LQRBlt$j\u0019\u001bs\u001c\u0014_%nsF\u001d\u0011\u001eΐـ\u0004޻9sG^x<RH?1YL)ބ/A\u001f}u\u0006\u0010WW赍Elk\u0003\u001cU\u0011GɷԛΘ]2\u001f\u000ek/69h72!K\u0013XߙB51UHC'O\u0010\u0006cqJ:\u0013\u0017\u00182STeoG?}?(s\u0015!E\roPq7hW4\u0014^#^5π\u000b\u0005Z>WSo\u0014<Uux\u001aOP@a\bY\b%3H}$31pŬf\u0003S6pO//\u000eXQUU]SN9+U\u000b!ÿXoզB~h\u000f\u0011wS8eoK\u0014Fuhr\u001fQ\u0001\f\f\u000f0=92~\u0017\tZҬvN+\fa|j12\u000eu\u0013a:vYA]+vգ\u000e\u00018\u0000tl\u001b\u00188ַ$}\"֎x\u0017\n\u0013l\u0007g\u0004齍bvE\u001a\ff?$t5=+~[V?>-\u001fTj}'润\rMuyVMg\u000e\u001c/hF5DӠD\u0018dEa\u0018\u00170\u0007$\u0000L!g*\u0006Si=j0DG3t\u00079G.ߌzF\u0012Zd-t\u0015m%mӅZ!?9\u001crNGؠ\u001dq;EQ=QGNZ\u000b(M4\u0007L\u0003fΙIJz{zX[3ح\tټkqyVcW\\Yg\u001cCS\u000eǟ\"8(s9\u001d~P\u0010~Tx>좸6xx!IM8J\u000eEo`\u0018iǒ7g\u0019`\u0016Yûl;x\nʩg\u0007[\u0017at5#}!UgєPp6i\u000e\r6\u0012-\u0011\u001d)\u0017\u001f>$VG7yTE_UF?UcP=Lx\u0018I\t\u0019d\u001fs0<\u0003\u0017Z@{-ΑR.¸\u001dj8\u0019]ECF.-D\nǣ_:\u001fN N&!Ƚ2~\"RV\u001ews܏^ZqO%(ߓo\u0013k\"!dc@13E4\u0005wкXD]c[\u0014lظ ]lq|,úՙ\u00073\n\\+ֹ\u0016M.}7מEIRN+g^3?*I1ބS8Ä́!9\u0003&1<&_b\u00047r2Wi\u000f1_ì͍d\u001dIU\u0014Tfg\u001fT6k^\u001aQI\u0006ɷ\u0019<^3{{j϶:-畅w_u+7nJG騘\b=C<\u0006R}\u0010ZVry\u0013^).jpdI\u0018*/Wy`vs-q-[ 5gdBV.YMY\u001b2O(g6yK.om\u0007Z\u001d\u0012>\u0013a\"\u0003\u0003^.\u0004#NzK\u0001\\\rg8@\u0017\u0005\u0001\u0006U+\u0015beV%y:E\u001dwn_Bu.Ϩ<\u000ePD H\u0007)#\u0003L\u0001QA\u0005\u000e,\"tІ\u0001FpF  RD *1\u0016X\u0018Qp]f%'nf=G}\u0006s=WR*\u0012x-^nAIܐ84wQSQQ;aQ\u0002\u0011P_B61x\u000eCT\u0011\u0007T0^,p̕_-]Q\u0018ך\u0017nܔ\u001bm^`UfWH+v)OmR\u0004\u0005I\u0003ޒ)ܤ޹oEDB\u0004\u0014LH$\u000bo\u0012A\u0002\u0006\u001326.98]\u0013\u0015\u0018pfn\u0017t.*[;hQ]&8+e6lǲB\u0017Y[Q+Hou\bSEg|2R>H{-H#BK&E20\u0003\\\u0002ߖpQ\u001c\f)qXt)*+4W֕\u0019V\"\u0014ҭ\u000b\u0017&ۖg:J\u000b$\\IN^vNWFv -h[i\tQ^R\"\u0012\u0012\u0003<L\u0005ny\u00043:dpR\r\u0006讶gګ<9;ΩWҩ.\u000f1P7b,e%6E\u000eyRsN-PVP_wH \u0019\\DM\u0014/!BKH,S\u0006C!pY\u000eW\u0002#4{\rԲѻK\u001f\u001duL.wvCzMu2X_`,۱٢\"Z=>K0T꺭bQ#U+\u000e,\u001d-}).$)\"\u0002\n&\u0013{d1pq\u00075\u001fk7٨&+46r5\rj\u0015:^q:(X̝),dEK\u000e9wkE5/snAph\u000e}O\u0018QQ\u0010QF_,\u0003Õ2ڃJ\u0014wf\u0016m4Յl\u0011ț5{V5\u001ad7DbRd+>6)uSu墈&ކ.uCq~hН)\nSxgz7.^܃Z\u0018\u0005Zi\u0006>\u00175Pt:2e\u001d^\u001ciRuI*K\u0017n\u001am\u00167rKs=M2\rJ\u0006nHC{p OpCpC\u001e\u000f\u001e:\u0013=z\u000fW?\n\u0018-4\u0001\r]@e*{磤ϖ)sg.VY97[pp֮(\u0003f):v!;\u001c\u0017ikw۪\u0002n\u0005{\u0016\u001bB.^R\u001e=\u001fl\u0007RM\u001fPzA]H\u0006-u̕I\u001d\u0014r\u0012\u0007b\u0007Vύ>\u001a\u0013u4Bc\u0016uGLBd\u0007\u001d.XPWv\u0005\u001cﰢqy7N}7\u001c{;s&\u000b\u000e\u001a9:\u0013t}\u0007C@\u0000\u0012H\u001fĶQc$:2%@`u#\u001bBF6\u0006_s*ppqp5\u0016~'[-<l{\f底V\u0019\"6>ǈL.\u0004\u001c7\u001c\u0006\u0014h\u001b\u00062h\u000e1=D[!b܍Y?.b/\u0004Q\u0015\u001e\b\u001cߪr<E,g޲\u0012}߱*\u0003>#icؤ\u0013#7&s,17\u0006\u0007\u0001]Կ+_6\u0002d\u0005ǁ\u001c\\DU#c$\u000f&\u00173\u0001+Y+&lU}'\u0013|2爦4\u0004SJM&-\u001em)\u001d\u0013:S\u0017]{ýq\u001ewx+}\u0000\u0010P2\nd\u0007\u0012.\u0001W)6\u0002ncmm,m\n\u001d<x\u0018\u0000F0\u001dYwbX;)l\u0012\u000e\\nNՅT_xj\u000e\u001d~4g&}t\u0007˨?\u0002-_\u0003\ngZ\u0015Z|h\bC+?r\u0006'\u001eJ8?\u00113NO3O\u0019g,g\u0012rF\u0017l\u0017LP\u001e͞d={?6u@\u0018GS&\u001b\u0010\u0003\u0016=`\u0016\\^Ws8j\u0007\\`\u0003֯?,^ٛPb&2\u0006r\u0019Mއ\u001eּ\u000f#,߯PSb PNP\u0012}$}-o\u001a\b\f8\u0004>ib\u0001191\t\u0011q\u0001BG|KV@E1a\u000eɂ:3jQ!\u0007\u0019\u000e9N,vP>'Sߨ־\u0000X\b\u0005\b\u0012\u0015ԤN]O}&gI}D]\\wa%\u0000\tR)i\u0014\u0019~\u0000\b=>B\u0007O͂82ٙ!.\u0014g.C\u001cX~\u0019خe\u0013\b6J\u0010l\u000eQ*\\iTS\u0016\u0007@H.!\u0018y\u000e`b\r\u0011F\u0005dA@A\r4\faJ\"c\u001aD\u0010'(\n( P\u0013ϱ+\u0015\u0003\u0000߱}`:{u\u0012I\u000b,\u000ec`#ց]\u000f{I\u001f|OdE\u0015?X\u0002c\u0012{<\n8b¯3\u001e7*5\u0017\u000135.C\u0013lU4-\u0001B\u000b8۰::paQ\u0006pڱX'v1e|\f2F9\u0018#\u0013a[ lA{\u0003̷S\u0000ɥ,s0\\;\n\"_\r\u0010h@\t|9\rfрW\u00052:pb5\fa|'&Gq\tb{̽D|^'F\u000fa\u00007BMh\u0002\u0005\u0017X\u0000\u0017t'\u0003\u0011=\u001bo) <<yb* \rph¬$\u001a8*\b\u000bu&#@\u001e\u0015~'8=\"he\u000e\u000bN2\u0004\u001d7n{\u0017ssr79zJ´'$\u001fc}$M\u00066\u00023\noqy-\u000bp1qևo3g\u0017\u0013o7jq|\\|T©Ig΀S\u001b93~\u001eV3^i\u000f;N0\t\f~.\b܍\u0010,+w{>u[c}[k\u0014\u000b\u0002k*tΫf=\u0016b\u001bt\u0012\u001fS|lùdߟ{#׻-\u001e~C<fx]\fFb0Y\f&]Sc:\u0002\u001f\u0004\u0012\u001bO\u001c82x!o#\u0017%0<ӵ{=t\u001ef_aon=nֿ4\u0011\u001b.\u0006]:\f\\7ٵר%O\u001d`v\u0015ag\u0006\b\b\u0002\u0010\u0004z9\u001a\u000bCC˅yK}4z\u0003~a%3*uo׽K\u0017m44èӳ\u0001\u001e\u0017<Nǯ<\u0007\u001cl\u00041u\n½X.P\\G\u0018H\u000b4\u00101\u0003=\u000ew\u0011N\u001bvcY$\u001d\u0014ϺD\u0012_mر_\u0019|kO6X\u001cli:suO!\u0011N/pm\u0013>\u0002\u001f;\u0010P\u001d\u0004,IF/\rP\u0002ݓ\b-\u000b;j13\"\u0010\u0016:\u0017wjY<㶠UǗ3k]Ra\u0012Xmu8`~\u0001Vg\u001a\u001b\u0002\u001e\txk;`bƮ@j\u0014\u0018\u000eƹ7G\u0013hPXCt3bR/I\u0017F\u0007\u0011?mo\r\u001b)M\u000e̚C-oڷfopm}P]]\u0019;Nrk~\b-\u0015*x5\u0018x[\u0001w\u0014\u0010@;\u0012M4V\u0003;A\u000bݓ\u0011L\u001fu%١\u000bI2\u000fZ{| *\r=\u001c~stQt\u001c\bU]xΰmwUo\u000bͭ\nim\tio\u000e)\u0017C\u0007\u001dC?1\ffN\u0005Kh\u000e(h\u0010?/2*I[tԝF\u0017\u00156\\DiKulI#eY\u0012=FuRimbGtUd5g\rv*gTD#\u001b\u001b\"\tG'F\"K#k\"?\bJA0\u0015M@i\u001cBSpUht\u001adXLҒ>_Yؗ\u001aڝ\u001cW(5ܞdZ\u0015nQ\u0019cU!-[j!.z5{\u001d%-dp_jI:P\u001d\u0003w1 d_h\u001ewWеL*D:臕fJ>Y)hץ\u0007(Sc\f+e&\u0015Ir2j}S\u001a_l_\u0012W-\u0017\u000bTC|)<i(WD\u001b;\u001b\u000bdn\u001c\bP\u0006\b=wp3\u0003+)#N\u0010X1:ǣ4؝NߡgVe70(WęfZ\u0015'qՉ\u0005[y:AvBPpR%Lx$ʔ\r;fʾ\b3e@b \u001cgx\u000eqR\"t\u0019g3\u0005\u0014V@GU;{TriU17e\u0007O+SFN_%5.H4+JOT\u0014(vZ2#ecZrH9K,y[<eB(O\u0001R\u0002ɾD!DsgW\u000e|*7\b\u001dUk\u0003h*[sZvmRho,X6/\\8'ƨ0;L[e)m3UvY\u0019k\u0019\u0015|Ez 519(Qqy,\u0001F6.LL\u0003aR\u001aûW2C\u0016BW\u001d߮\u00138{\u001d\\MA\rl\u001am+\u0011R7\u0017ϧ\u0015-\"\u0016\u0006VC*Q~AiN^27:#'V]M]Y>3I]':&ͺ(f^zL\u0018\u0005d\u0014/.<s?=\u001e|\u0003\fƸĽ3bf0F\u0015QPI.\u001c]))B[(%]ەnvDmv\u001dT[UJ:꼴5|{y\u0000L\u000e2,9l#(J@r=,u!\u0006\u0019SMӣW\u0011/I[`\u001fI\u000bR\u001dbW8[]9'yjsɭIO\\g&\rD'\u0011g\u001a|\u001dI\u000e\u0003PQ\u0001\u0014\r<'*;o$.gn A҆0efYsDYg.en\r7'];<zm\"*L5=9\"Kx55[TL%ʡ:\u00173a9E<\u0003'q9&5x\u0016>\u0014XBVJ/)\u0005y+\u0004nd)˼h\u0017Yh=w2٬\r)vQ,yvi%)YaYYWCoadbτd\u0007`\u0001Π\u00006Af\u0010Ҋ`u\u000b؋M,\u001ah\u0004SbE\tnU\u0018/*H,X%%.ls>\u0017abAǐSN7=p\fw\n%!9kųx\u0001)-vb\u0007E8{\u001c\u0004`u\u0011,=\n*̃/Ŗ\u0006Ŕ\tfL7=[\u0018+\"|WhW+BwK'\u0014\u0004\u0015\u0017\u000b,:\u0005\u0014}mD\u001ess\u0003\u0012^R\u001d(shR\u0005\u0003\u0002X\\)\u000e\u0010wPCTffU\u0006*'E\u001e\b\u0017L;\u0010m\u0018V1$bل-\u0003m\u001aWC_^!\u001dS~\\[~\tuI}\u0011\u001bq-v\u000bP߻\u0013`G)@N9@\u001aΡK\u0000հ\u0010Sk\nkm N\u00053<:fjm0orm\u0019ڹ55K֤Uk|YxW\u001bWENѨQ?\u000e<D:{P__a~~C8\u001c8,\u0018~\u0000֋ ^\u000e\rn0\nn\b7Ld\u0002\u001bc\u001bu\u001abu}\u001b\u0012\r\u0002\u0006\u0005F#\u00185v`o7֜~av\t\"Df\u001c/\u00008`~\u0001vkO\u0005Xt\u0002`n=\u0003\b:σF\u0013\u0018h\r\u0017\u001d;i\u0001@ʻ)j=0\u001eMeyyKs;tGOLOt#'G0\u000fo|m\u0015@\n=\u0014@\ffG|\u000f\u0010r\u0011G\u0016<a5Spo\u0011ܮk@}\u001b\\[\u0003u\u0012\"A\u0016C9XD9XE9EC/gP\u001bm{1mi%P_9z\f \u0001`w!?\u0000\u0019:\u0005.]\u0001ۅK_\u000e`\n\u001d\u001fd\u0013@pt\u0005`u/\u0005r)Qw\tey2;e2\u001aN4_r\u0006`y̿\u0004\u0010|\u0019\u0005`\r\u0000\u00004\u001e\tX`X\rzE\u000b?\u0000g`l<<\u0002Bbb\u0011\u0018L\u0001W@W\u0006}u݈~\u0005c~q\u0007\u00026\u0002D\r`t\u001b6\u0004\u0018\u0010\u000e\u000f\u0018\u0010Lދ\u0014\f?p`A\u0001\u001f@x\u000e\u0019\u000b\f\u0004@\u000f!Y\u0010\u0016N\u0013d\u0001209aӱV\u0000[\u0000jvlI7\u001f\u0000\u0000Ƅ\u0002C\u0007\u00011<\u00133<1\fqHܑ\u000f\nB\u0011\b_\f\b\u0014\r\b\u001f|\u0004ozr3^A\u0011\u0011kDC\u0011+_C(b9&41[B\u0013a\nBh;ڍJTFѷ\u0007t \u0007~\u0000gFWf\u001c4^M\u0011xpXD&drQ!ډ~t\u0018բ\u0013G9惨\u0019\u00102{+Sx~*&LzĄ7\u0014q(9w\u0013.\u0014q\u001cE\u0011\u0000&&vhb\u0013O\u0013r\u0010\u0016mf>Jw0%wrf@Rɼ\u001ce%ǘג3Ly)<v2O\u001fC\u0019ݗ\u0011?\u000eET6@\\$\u001a+^ZFRُ\"ʉ4qA\u0007Df@ye2\\+d^r\u000b}grG^NG\u0015\u0001v{\u000e[v9MN\t_\u0010Wֈ(Y\u0002kt@\u001f#q?4wit\u001cBj\u0005ӫLc(#e>P@w_wOqץu*N:ڕyw[\u001e6\u001b~_U\u0012\u0015%1/;{\bxb ؅\u0012>\u0018K=\f\u001fc\u0013.Ul&׮VsǭX[-uMu^uY~%U4u\u0007yq\u0000x\"\u0017*ʡvlC\u000e5ިx\u0000\u001e\b\u0007x\u0012Ń\u0018J\u0012s`Vm\\\u001dclTf3iwNl׶ݴMnc3w<>\u001b]لmq\u0002\u0001\u0007N\n`TRiyFxs\u0007\u0004.q|\u0001\u001dr۵yyo띭}w8>9|nr\u0010olʖ\u0005ҵ-ˤe=UΧ䋜o)\u001c\u0005`\u0004\"&#3<#\u0002QZ2\\b$D+\tmk\tݾKvx\u0007r~Kq\u0013f(\u0017/]\u000e\u0015p6Q\u00184\u001b\u0005\u00173`\t(;\u000be\u0000\u000b/r\u001c*<Eyûq[Ljf\u0001a9\nW})j&-Z)=gG\u0002N%\u001d\f<4IK:\u001e4t!x&i5XÐ䧡G\bH\\ȑ5)XKX7`\\wr\u0019\u0013>\u0015x\u0013>\t\u0007]\u0006.\u0004K<\u000b^9e>gx:,fٌ\f\u001bM`\u0014\u0019tWDL+\u001cp\u0012`\u0003_+ǐ5\u0019|\u001e\u000e\u0016U\"wxP\rw\u0002`EĄ+͸EQ\"\\!dAל8#P\f܆V\u001ck=!㼽ay4gTh֩ȑtG]\u0010\u0013 ;z6&\n,\u001d}sQD%I\u0003V%~pYJ\u0005Fii\u001c~Nu?V,\u0014\u0010'\u0005ZBsS`\t\u0019\u00159}\u0011\u0003y\u0013t{\\T_b޼1zDw5Q]_Z|#\u0004x~sK\u0001n)$U9\t\u001648U\u001a*婄\\C\"⁒RX?\"\u0007\u000e\u0007ZB\u000b=\u0011\u0011zOᨮ\u0019FgyfG*˒\u0017V{3f{OBlMz\u0018\u000f\u000b4\u000feεFO\u000b>pZ\u001d\u0002\u0015\u001b`J\u0006UD\u0018/y:\u0015Ľr\ty̿_\r#\rC{-4k-C<LƣD\u0016YV\u001a,m\u0012\u0003e*Ƙ\bcA\f@\u0001p\u0013/Uޫ\u00058[\tZ*LnƍW&\u0010*2<\u001djπJL+Sz\u0015\u0015rCpgiC&l\u000eD\u0019IV4N\u0014c\u001fS+}U+Ř`\u0004\u0003\u0015*ʿG\u0000p\u0000\u0000p\u0019\u00180n\u001dnLmXaz4E\n\u0019S\ntA*chsY3ͤlPأ1F( ?\u0019_ߏɿRR`,?\u0001>F\u000e(\u0006^Խfjpp\u0002\u0007Q0f|\u001d7\\^a3d{wUҕi\u0001M\u001a\rդ\t0ь]}Q\u0011NbWT.ŪUV^+1\u0016\\\"\u000fh\u001d:еg\u0012=\u000fՓ\u0010\u0001p\u0006\u000e>j\n-b oЫ*CH׵Gh(M<Rifc\n;JͿJ\rZS/}\u0003tZE3rϠ7.g&)\f7x9nz67\u0011ME:\nԅijZ#ʫe!BU\u0017c%g{\ncɪ0zO\u00002F\u000fZ\u0000\u0000\u000e\b`mg}\u0013-ԚВcl. \u0019$\u0014,Ҥ\rV7ֆ54뭑hI\u0001f\u0018[d\\)2D>Acj1\u0016\u0014\b:\u000e\u0000Q\u0000Lt\u0000\u0002wxBOg tZ\u0019f݈kVߙ^\u0012\u0012b]jP\u0015!\u0016SXIsGN/l7O3y|-0?a\tLYB\u0013\u00146b>@p\u001a-3(.\u0001\u0006\u001e7RF\u0007vsնD7ó\u0016\u00142?YWyĪ\u000f\u0012w6\u0016vXh\b]ٖ\feɳ<fdnâ_'t\u001e\fΣϡ6\u0000g\u001f]H\u001d<@A\u001a\fm8`[`r K_#闐2J\u001em.\u001aƳDdڎFrmo#=_ӻwar\u001b\u0012ZV4h\u0006\u0000Ã\u0000!ƽ{n,\b4N&;7mx3P2!\u001a\u0013x\u0015}r߼\u0011_Hf*\u001dp\fO\u0012hh\u0003?'c6:\u000bhP\u0000\u000eQ\u0000qC\u0004P\u001e@H~\u0003Ů7pEr]AQg\u001cw/v]]@VPX\u0010Y\u0010a\u00019\u0017[\u0014\u001111dZjh5DQ\u001bpX\u0010a=c\u0004*\u0016Q^[Q1z\u0000ib|fvyz\u0016M\u0014MΖ̓'|LY^i\u0017~b6]TVCdaǈZr1\")b\u000b|DxƯ\u001cP\u000b3i(,`e.(\u000fGmo\nm1h\u0004fZ<f\t4K8jeɖ)Be82W\u0012kIN*Zd\u0013]\\\u0011YN\u0019^E\u0015ZzBAjr.x\u0003}5A~J\u0003\u0007(?w\u0017\u0005j6\u0000󁥅\u0007ԋ)\u0006RJ%\\Ab+\u0012ʽ\u0011W\u001eX\u0019,ښYBu(̺@\u001cb]&\t\u0006Z7\u0002w[l[~s6~eqCq%\\{WGh(?#\u0013ƾ\u0003#@j%\u0010W\u0005+\u0010^CXh`Bm\u0010k\bM@`4\u0004au_\"[\u0007S~hl>јJg\u0019g]ȳfPQ%L^`\u0003}a`a\u0019Q \u0018P\u0003D\u001d0\u0010÷Q\t)\u001dFal7L\u0018s:\u0002q&\u00053sޜ\u000e0e\r\\[%\u0007%I8ù\ts>p\u0017ٴ\u001bi\u0011\u0001\u001a\n]ʞQK\r@\t?\u0005\u0018\u0019IoU\u0006Wp\u0001㠻6DC{=\u00197ff:47BsP\tu~ڪ`v\u0001? lo>m\u0017n\u0001V\u0000GA\t'&\u0005:\u000fn\u00051ߒBӡC\u000bU\u001e\u0006(|\u000e\fYO\"$=3!\u000fQ2\r@ׄBz=\u0017H\u0017f\u0014X\u001d0\u000eI\u001dF)_u@w\u001bP\u0003l\u001f\bP\f( \u001bPC2h\u0019\u001fM?\t\u0003\u0006tB\u001f\u0005\u0003\"\u001a\u0000\u001dA\n\u001bk\u001fSRsӚEs@a=2`\u00018\u0001\u0001Ȩl3q\u0011}\b\u0010\u0015JC\u001cHb >$L$)^>8\u0007qZt^\u001aw\u001dK-u\u0006\u0007D'3Ÿ2q\u0012'vA\u0019BpaRNH\u0003^ɛB~\u000bC\u001e\u0007XHPCnn\u0006DOZu\tT\f52^HF\"$\u0014W\u0003셺=W\u001f3u\u001dЯGn<PWY\u001dgk\u0018\u0006JH܉\u000f\u0004\u0018g\u001as\u0019wq2m`/t_glHj؀6k\u0013m1{`\u000f5F\nu\u001fu݁\u000e\\?mp/\u0017#8{Q\u001dciMƘ&3Փ\f>j6{ΆF.f#W'~#{;\u0003\u001e֫e=\u0002֥?:CןdNvå_VW.D.ra\u000fh+i\t8\u001f\u0018Jc=a}\u001e\u000bXa\u00192b\u001da\u0013k7lcwݿfwܳm<vn\u0018J5Cpj(\u0010Z<N{r)O.iQ\u001dICفм\u0004yɄGQ\u000e9o:kYn,g׌keBKqp޸[Oc謱@l<,:m\u00105\u0019čfI\u0006߇:W\u001a_nsg|\u0017DAJP\u0015x8\u0011ሡ\u000b1#8\u0004mAq\u001ewع\u0005BipƴRdZ+j\fL|2`DN\u0001{$\r\u0001{\u0001EڀRiM1FYjz(3qeώ\fÃm)_\n\u001e%#m\u001aE9=\r#Bd\u0014Z\"S\u0011ىBCBQ}ĵaT\u001e\u000b(.tې]6!Y|yy!EiH$AY\u001crIy0۶(0NP\u0018W{\u0003\u000f\u0005\u0018\u0011\u001eI\u0015'Ij\\脳1h\r\t66M8\u0016I\u001f+'.G^V\u001a'MCmʃ\f[9WUh.R\u0015Dk-v{?j7$\r<Q>ЗH=_2p5YIr4'jqb\u0007j\u0003Q<UL*%\u0016\u0017''9@fȦ0n n2?\u0013ۼ/T{cvdjb3c{b\u00191t\u0019aG,wlx\u00140\u0000O~\u001eg\u00044JC\u001dSG(\u001e\u000e&\tii)sS߷;e<'y2kJUfZCu\u00075}qKo\u0002\\\u001eZ\u0016\u0010H\u0002!\u0010 @+\u0010\u00039T]\u0015īu{t\u000f\u001dm׵ٱ?>3o7>xDx\u000fG\u0006#G퍼\u0013y\u001d13K~{Է\u0004ofÆ_\u0017$T\u0001T.nTwR7\\v43\u0012g7p$I42w\u001b7y\fY<=\u001dAߎ~m1[b~(h-hHh\\\u0010`\u000f%l\u0004i<\u0011?\"ﻝAt\u0006Wΰ)8\u00163Aq^a\u0001QYpZӀ4ۥWsN)LjK$4%Y\u0013\u0013g\u0004u\t煵Dğ\u0013\t\u0017\b\b|\u0013\u00051\u0019S\u0005Pk_y\u0003d`Z\u001aT[0\u0019\u0019VFr\u00072\u0012\u001czeN\nK<׭EhJ3y5Yx\u0007S\u001b}k]|tDP%\u0012VHEfuIcQؘo1}\u0010\u0018\u0007c%殺9Us0c\u0015\u0018lƐf\u0007ӧ\u000eveٷ͙\u0019.J[}FG]z%WPt!A|BT*\u0015\u0017˗$\u0006\u0000S^X`Eаt\u000f\u0003\u001fP7)r>0O\u0003c\u0012\fm@o6S\u001bm9`ߨIvV8ת\\+U\u0006rg̬-l/V\u000e\bʣBYN\u0018xBKdń\u00103_\fܣگ逋\"`~Ǹ\u001dC\u0005B\u0016GGA\u0010ӢñG%8XrӜ+\u001cwcNg3d\u0016e7\u000b}|aQ$G}%@~HJQbB'R\u0007y\"es8Ba+z|t\u0018ٰ֠i\u0016EU\u00159\u0017H\u0005\u0019.%:!_YW˫mks{\u0004\u001aH=%Qi/\u0005dj\u0013 )Բb\u0015-i\u000en\u0015\u0000({HWFG\u0012'5ԗ\u000525e;8a\\sI}iqp)2t|b\n\u0006~VA `T;!V.J亻\u0001r'?$\n\u001dK߱!u=\"!<J\fйd&7\u000e|#*ʷ1Pn9^oJt,0ɜ*WmYGv+S\u001cK/i\u0017\u001f\u0012\u0015O\u000b\u0014ER=\u0002K>{KsH_[\u0005p\u001a\u0018\"$bP[*\u0018(\tb\fݜB~x\u0007muSv%2MYY^aS̃$0(8\u001bqKQ[Q\u0015&'\u001a]%3\u000e\u0018\u0005ZZ:W\u001ctCY?\u001b֠ȺYwrpnvC}V}^8v\u001dw֕z&V\u0012k}j15\u0013\u0007,(-aW¨/\u0004U\tV\u0010]\u0011uTz>+C4\u0010\u0005-(lA~*h7#};j\u000fdEq\u0015mim2Gi9%5\u001e\\y\u001d볿_x,?:_/aa\rճ\u000e`>GSʹ\u000b-]=m]]@^7\u0017^/dٿ\u001eA0\u0011Xnb>/!W\u0014[\u0012cv\u000b幷%ޮB:B:㦉fz~t.t\u0002V.\u0005\u0007=\u000f\u0001Q7!\u001d[@$oGx(\u00133\u001e͉\u001eOF\"Ʋ\u001d9\u001eu5ctmim#\u001e#?r\u000f>\u0017o<\u0007Y,\fQ}\u000fh\u001ePv\te\u0003c@¤\u0003b\u0010=%F:ފ]\b\tgBgb=3)\fΙ\u001c\u0006mU?nqxkzq\t7/\u0013ޜS\u0003'Xc@\nv\u001e>ʵ\u0016\u000f\u0003\t s\u001aH:\u0005D&u9_[s\u001bc>\boχ`|\u0004mq\b2oT\u0016\u0013h3q6٬܍~\u001bIvl?ᮝn9~Wc\u0003\b\u00112\t\u0018N\u0000g9\u0000ឋ@e.,x p\u000biq\u00036.\u0006a]xj\u0004_Ǻ%\u0019,e%\u0003V/YUKʥ#LyFr6#Y,\u0011/<爯1E#T{'trcIIC\u0017m׀759`\u001dw\u0004\nﮃ\u0016\b^\u0018ł_\u00069}P\u0006\u0007V\u001e\f)x=\u0006χ\u001f_u\u00191>FH}oM\u0007\u0017+@\u0012\u0006\u000blz\u001fx> \u001f\u0001\u0014չ\u0001\u0016l\u0001\u0017e\u0011\u000bD\u0001\u0002((`\u0016W%\t1`A,H@Dņ(<\tC-O1\u0016D!ODQDĂg\u001b0;=;{9F\f\u00059PY0s C \u001f\u000eY\u0011ҿ#DHNb:D\u0017 X\nAC\u0015Fr<(g3J,Z=X=OZ\u00158\u0017\f`]\u000bh\u0001%\u000e+\"\u001b\u0015\u00106!j\u0005\u001a&;@:5ͣ1\u0000n@hm\u0007\n}k7\u0005jGK(]48Zw }\u00040\u0014`W\u0003.\u0000\u0017\u0001e@~\u0015\u00105Gn+jM\u000b\t\u0005:\u0002k\u001fRs\u000eG?\u0002:=@ON}DoG\u0000=b{\u0000}\u001d\u0012`\b]\u0007$7\u0001b\u0007u\b)bѽ5t?+\u0019\u0003\u0000f\r5\u0007(\u000fF?\u0000C?b>`hU\u0013ŗ`RwŮ`\u0002\u001f0o4H\u0016%$\"H>)k\u0014\u000b\u0012\u0015xCxjt\u000eh\u0003(m0k\u001b0\u0007QLɼL\u0002DcOW\u0012I%KrW߀|\u0001ExN\u001cyn@\u001b߅BV\u0011\u0011\u0013\u001d5ջ<RM)\u001fOHDɿ#3Z>\u000b]x)[,<\u0013:t6ᑬ\u0010\u001dt7J+&B\u001cZ7pC\u0010]h2ehTsE\u000f\u00129塡|(T\u001b7\u0010Tj\n:U3P\u0007Ÿ@7QMVe\u0001n)wr\u0017{q]y\u0004M\u001aWՌ\u0006Ckp^øZsƝ{=fKm`\u0005\u0001f\u00079\b/\u000fc\u0000<Bw\u0016m\"nh6\rMehԮ\u0015Z\\n%6\\Ԗ^\u0007\u0017,\u000f4jp\u0001WE\u0017w\u000b\u001fϰ~f`}`v`*j\r|\u0015vC\u000fu!^+\u001e9[Z\u0012貸iz;U۔qmٜz_\u000e۶\u0007l_\b*m`_\u001f&ۇ\t+>)\bQ\u0002Dy\fP+Kz?'\\z?#qn\u0002U듸c\u0014>;\u000fsC\r\u0001V\u000f}ҮBܾUXfLXD%\u000eL3l\u0000w`\u001eφ1H6G\u0015\u001a[\u000eg\\q\u0007ǜqy,wy\"y\u0006_sW8-\u0016q\u0010;-\u0017v\\#,s\u0017:\u0016Jvv:\u001d\u0014\u0015;\u0011\u00179\u0010\u0017:wlqfLm|N:h{u\u0007\f\u0015A!8bn\u0003qm\u0004*\n\b[u\u0012_epKؐ**2,\u0015m7\u0010\u0017\u001a֛l1l5)0.7TJ6\u0019\u001b\fW\\:dk\\^V2Yg`(v\bF\u0002#9\u001e.\t\u000f%\u000e\r}#c\bwJF\u0004sc\u0013\u0004S[ŋ6\u000f-X f%YZ=_ڽX\u001eU9\u001e\r\r\u001a֥\u001ct'+m\u0014Z#PM88\u0014\u0015>(c\u0001EV\u0000~O8qT oDѺk6+Y\"ʐ-ʑg{fzmS,maeye\u001d//L:}\u0007\u001d?>4s\u0006Ь\u0013D}>͟Po\r;\u0002`k@\u0007xry`A1Zѓ٣L2\u0012e\u0019it,E\u001aT-\u0014RB\u0003\u0005g}[~=\u0007\u000f\u0006h(1:ӑ \u0011(\b\u0001X\u001b2\r\u001e\u0004\u0011d\u0007\u000b3\u0003ǉ2|/N\u000f&I\u000bI?Wbиlqr1_5׸S3Xe<e<&\u0013\u0002R}p˴S\u0014h`o\f[t\u0011ơ \\\u001eX\u001da\u0015\u0011\u0006d{q¿\r\u000b\u0011F\u0016\u0017/\n$Y\u0010\u001c'M\u000eN'\u0005-P\tJ7\u0015J\bܠ\u0019<>jf<.iSGC\bp\"\n80\u000e(ٯ[u^\u0002ȉ̘AȈҢ}Q\u0011XqR9Ӥ'S\fE\u0019\u001f\u000b]\u001e|j\u001e)ǻM\u000ek\"-&1sT?pjPEq\u001a췍\u001bҼ3NZ,\u000fҿqBj;(v\u0014<.@0wlpvL8!f)xy\\\u001c\u0014ԨLȵ\u001f\"\u000buyGEuqwg\u0006fd`\u0016.誈\u0005\u001b\u001a\u0005i*e60\fU\u0006\u0002RUZb\u00012XYK(nQ@M\\\u001b)GO-hknQ\u001c999s{}\u0018b<31=\u0013uO\\\u0012u]D1D[~\b\u0001:\u0018s[<ס='ˍy\u001ekP0\u0010e\tP0I(H\u0001Ҝy2s&3.N\u001e#56CiuX\u0014ShvNޠGG\u001fp>36o\u0011_kE\rQ\u001aY|7jdYc\u001d?4b\u0019IQ4\u0012I\u0013\\tl-4\r\u00116)1D\")!ΐc/T+b۵\u000b\\z/NFŋ\u001a~\u0015>\\\u00033T`'ٔ\u0002uy\u0004%&G,5E^\u001brR!+ea򗤚a6IѶE\t\n\u0014$}LR¤r'V\u001daܦ\t7w\t3\u001ewY`%R\u001bf\u00105\u0006Q|\u000e'\u0013&`_\u0006ԥ<JҀt\u0007f9c(23=9Y0eJ2J\r\u0019e(۸xyLZri\u000e+\u001c\u0017ubQӆ|\rNN\u001bl\r1ԄDuh;Zle\u0007鵚\u0017.fI?9YJ,6k=\bQX%\u0018rf\bْ\u0010itvMTvm٨\b7ʵ\u000f*U\u0005/^\u0014x=̣9ߐ{_\u0001\u0019: ]t~Y]\u001f%9@!yF\u001c%H\u0002w\u000b#v\u0010]/\u0015\u0004I#\nda6\u0013KR\u0015AKr\u0015P5+w/on\u0007w/~9;N1\u0007\u0019\\,k\u0000+x\\BҖ\u0002I\u0012U+ҡ*@dd!G_\u0016 \t-'\r.\u0002Km\u0002Jmgd)\u0016W)/0hʻ09.^\\Tfzor\r63eB\u0005RL/c߱\u0012P\"R\u0005U\u00031j$B' [\b)\u0004T\u0007IfWKfVH2L\u0019i)&WTzU\u001c\"g^?)VZ!{-\u0011w\u0007}u\u000b<\u0016,3[_\rD=\n]c\u001a'\u0004ŜaU灙uW\u00039uu:ɴ\u0004ɔT\\6kkl=k4=j\"\u001ek)<V\nUxAJ\nGRR\u001cНLwL\r{MV{ت\u0001V\u0016OLL$\u001f,h\t\u0013[b\u0004O\"b\u0014IFYVIGZ,\u0011&̭mS6nطӻmX\u0005k2\u0007\u001b-\\>;I\r2ۭ^\u00188\bc\u001aGbt8Nş\u0018i\r\bk\u0004ܭz\fa5_\u0018b\u0014\u0006[7\u000b\u0003W\u0018`=.Z\n\u0004׆\u0012]4T\u0001[]Mo:`+@.\nL\u000b\u0004p? f'\fiA̓0\b\f8\t׃S\u001f\u001d\n{t{Ȁ>-fn)Eϖ:4@r\u0004o9t\u001f\u0017\u001c\u0010Xr\u001d0\u0015y\tT\u001c\u001bO&`\u001aR\u00163`Q19*hZ]nusp2\u0006Nm\u000bU{0C{2OAy\nvP7A%PJ^uqW}@w&cN\u000f7\u0003s\u000e\u0003G80\u001du\np>-\u0002*ka{\u001fl\u000f(H/xAr\u001fA\u0016$\u001d\bupup}DwPA;6yDt\u00173=S\u0003-iw8O\u0003.ձ\u0003\u0016]#Zr_`H\u0016D\u0013)PY\u001c^K:_K\b\u001fF\u0006\u0003n )kp\u001f9}5O\u0002\u001e\u000e=\u000bG;\u0012 \u0002\u0016\u0014\u0007pKŦ@\r؋+p\rBy:xy<K\u001bId;B$gcM|\u000b\u0000W\r\"sO^\u001b-/r#mPAaN\u001ekɳ!1\u000b\u0016/Y$\u0005^b]LzWs7\u0000\u00100\u0010\"DKBI\fI&Y\u000bUx5xx-\u0005\u001c\r\u0019{?|3<E\u001b<\u001e\u001a:q\u001f\u000f\u0007>\u0007DM?} :\u0010[KWO2\u0004\u0012\u001d1\fF.~E\u0011G+#<C-]\u001bc젫Ojǘ370uw\u0013͑n\u0001ѥ7硅m\u001e\u0010\u0015!ʦ0/\u00053n\u00134YJdLZGf\u000evѵf}\u00147\u0015\"\u001dٹ(.KD|\u0006;\u001a\tLyTSg\u001aƟ{$$7n#V\u0011j\u0005FzXl$&\u0000\t@\u0012v(nR\u0005(.ԵxlqL;\u0019TtZy\u0013Ow{?=#\u0013\u0013\u0015r\nO4~%<JLRj|%cI=\u001er\r\u0017ׂ\u0007&|\u0017\\\u0007\u001d]8p%\u001b'.\u0001W\u0015\u0002.+\u0005\\E\u00180TI\u0000\bC\u0017Qm@0\u001f\u0017x|ͧ\tG|>ɗK\u0012\u000bq_po-~#n\u001dT]:˪^nb\u001d\u0012\u0006\n8K!N\u000f\u0014\b\u0001>\u0010\u0012C\b\u0011\u0018\u0019<\u0016O}'iǠd\u001d[\u001c[k;\u000f\u0016ϯ\u000eEf\\\u0018\twN\u001dr\u0018gũ!p/3\u001194L`\u001c\"\"}*/\u0018\u0016@%S\u001epk6\\KÍ8\u0011N\u001fQ\u0001p:\n\u0002jp2`9N\u0004ű\t\u001c\u0019\u001c\u001ey\u001ey9\u0010t\u0005>`:G}vm(/\bcH?5'\u0004Ip?P;2z4.c:\t'i8ڍ\u0019VW0\u0007.bfz\u0005Wt[\u000e\u000e=h/\u0016\n\fn{h˸_E\t\u000fzyɓTb5\fO7?O\u0018EOH\u0018\u000ehq`t\u000bDg\b)`Cʘ!]Zv{*vkphs\u0016Ѧ\u000fŭ!\u001bCΉׇ\u00147OZ4gI{Y\u0006\u0004*w}?\fA/zP\u0016g&2\u0014S\u0017:\u0005\u001dQh\u000bMP3}:5<@SnT6h\u0016Z4uu\u0006qUҠ%YVkNq+5WSHOQZ\u0017*HyYITꩤމ&8biޡ'H\u001c}\u00111\n\"'b{d86Gj\u001ai`6D3-\u0011vv]m\f/\u0011\r%^\u001d^%^\u0019DR\u001f[\u001e-\u000b&\r+[\u0012v\\^\u0013'_\u0014H {BWG\b7&3ҿ\u0016\u000f|\b )\u0017-F{\u0000l\u0019M16\u0014ͱhIbƤ2l}C<@,L\\\u001b5G$j\u0001W3NpZzfyմ\u000eyQG}*.*D=P̎NQ\u0011-x\u0019yO\u000b|JOi\u0003:D'mx\u0015Z\u0013ѬSQ7\u0019uOg\u0012\fx\u000b$>[Tu\u0017jZ*\u001bW+\u0013F^\u0011kS\u001dRΌUighUjP\u000by\u0013j9n/L\u0007\u0002]ns!I!X2\u001a)!K\tCmJ,S,HNe'e%9ĕ\u0005ىeܬJiybLR^[(T\u0016\u000eĻ\u0017|~$A&\u000f\f\\9 4{IF ǪXn\u001cZ㻨1b12\u0006h![\\npI%\\BZ_ +/7+)ەN}\u0017?&\u0013zAI(^s?\u0001d\u0004N~7_mS\u0004J<\u0000ñ \u001dTMAeZ$Sa2\u001es\n[jfKS\\q7K]*Ӵ'Ԥ1n},)F??2\tJ/W<hH]S۳5i禋P\u001f\u00191\u00163߃'#\fe\u00191LIF\"[nd\u000b3D\u001cӒ/ɵIs,sevKOAaMgu-\u001fK\\'Q\u000bn\u00114A۴\u000f\u001e\u0001؁&W\u001f)6\u001es`Vۘ\u0015ҬP\u0014eE1Y\tf`l\u0016Ö-\\l[)gΑeZ\u0017[(Ҭxs\u001eUddʔ3)Bu\u0001̙K\u001eP\\K|gv\u00129~(uDc<\nr5pF2y\u000e-pvY尉9ybΒS!3,\u0014F{`ۏR엉*'^-(_ar<?E>袙h!kS.s(N9]\u0003Q\u001a\u000e;\byIq#\u001dIlĦ3Ein8U(1<RZ\\ܠHt)uΣ|\u0012\u0015Q\u0013\\A\u00138/H4\u0010Kis>}\n$p\u0015Gn?cU\u0012\u0002k(b,%\tJ,v-I..\u0012\tEu\u0016݊#ʘOʘ\u0002A\u0011'\u001f\u0007GHo\u000f\u0001t\u0017E,9g0\u001c@X<ah`D2\u0006O\n1I\u001eHqK%q\\LRi.(+\u000eلaf\u0007\u0004\u0005\u0006\u0001aQA\u0010\u001e׺<T\u001b5ڨ\u0018\u0005\u0001E\u0001\u0002A\tEEqA\u0005&.TD0j]S4VmXZc4DM'>\u001f3}9ݓT84ɬOOZqIP/y_,*\u0017ʷ8\u001co{\u0012PzN\u0016\u000f-gߑ\u0015n\u0013\u00161\u0018>\u001cc\tӧ\b#\u0012%\tiJ-,KRĦwIp^4;D\u0010!:gk\u001a{Re܋$$ӻ0\u0019\nLg6)C8cl7Fg\u0005aTV?\u001ex\f\u001e\u0013B\\,Il|ଥҨղY\u001beY\u0011&rM\u0011\"<'\"*WB\u001d[+XI\u000eYIoR\u001a\u0007\u0013٢M^s=\\wD\\\u001eC5\u000e`0D\u001b\"8\u0019\u00033\u0001ƹBq\u0010fL7J\u0019HCvKCviH#iȆ\u001fe!Ԧ.e.\u0002I\n^\ț{\u0006~F`8[֘B9\u0006\u00159c@\u0017\"u(\u000eAxI$\f%_2\u001cJF_Tf!ش\u0000zS۴Ne*\u0011\u0002Kv\n\u0012\u0010PrQ\u0015?\u0014\u0002\n_H\u0002\n\\\rla\u000b\u0005d5i\u001d!݉tOR r+\u0010ZJWޕe\u000eE9\u0012X\t\b0e\u0006,sò\u0004b 3КB[\u0001m(xuQ!b\u000e#IY}X\u0000La[8\f\u0000\u0006l\u0007\u0000\u001e5N\r/\u000e\u0010xF6\u0006#n\b7LŖ\u0002-lڶ\u0007*\tjoAe}\u0002u͏Dt##s*g\b16\u0005\u0018Jҿ\u000f\u0003<\u000e\tpnPB\u0002U\u0016NP6\u0018\u0006\u0018t>\u00192 \u000fkgBCfQttR@Z\u0013|\u000b01O'06 z? \r'Q@\u000486!=Õx\u0001-~\u000f\t\u00030\u0006h兠\u000fV>xڸ\u0018\\[\r9/G0+\"<5`#\u000fHa 8\u0002\u0000iAu#y㼖\u0017➼\fŜ\u0006\u0003G;/\"WX_B_-'{9\u0017\u0017ȍN2I{\u000eF(;޾^S\u0019@y\u000e\\|N u'^5Mw6'݁t$jV; .\u000b=\u001e{\\\\\f\u0011r\u000fy\f=f\n\u00040^-\u001az~I8m|E&\u0010\u0013w\u0004͜<P\u0001\u000f]Gc;==\u000e\u0007>\u0018\u0018>ɤDtح;D\u0007M\"P2$yd\u0011IOK\u000b\u0007\u0003\u001eexJ<E\u0015\u0015ߢ\u000e'xxx7w3\u0011\u000fQ\rQ\tQ;@b C\u00182ӹtqL<z<\u0002LtmB.z8Sv'n79\u001cF\u0017Btqvp(\\GBH\u0014I{\u0012-cG\">Vғ;؀DW!-tUU񭸆\u00032Gq\u0005\u0019?\u0012\"G@ο\\!/\"o89iͦ=zГQ3p\u001dkMrp\u0015\u001fq\u0016UFjF\u000fg\u001eъSm\u001c$3O\b\"%Cpb.\u0014đh8\u001f\u000f\u0014!x \u0004ܒNuY\"o$[\u000bTY:Sf*/G|\u0007\u00156Eр&E\u000b:=؝~@JD\u0010d\u0007 j|<\\5x]\u000e7\u0006\\u\u001aK18\rΨ)<Gz\u0019i8^&͇8و#\"\u001cَ֔F\u00158|\u0002\u0007\\ڱ\u0001ln/`u\u0013Q.b\u001b>ؐ\u0007<޷=\u0014||E>86\u0010pc<yLaٰ{\u0011\rP\f\u0007=q@\rا\b{&ؼ*`n:T{7aET܁ŧ\u0003PEy\u0017\"r\u0007]\u001bYt\u0002.:ଗ+Z|\u0002pG{(M^Dޅ=/F2v\u000elTb{@\u0001,\u0001e\fBy\u001eaP;+\u0006~#\tAPD\n@\fd!\u001bXjY?e=)P \u001f\u000eƞ>\u0003Qg\u0018vǡJ?\u0015\n\u0002`>\u0005e\fTNXI(ћ`P\u0018l\u00156\u00077HCNI6ܒ\u0018CHrCEIίx\u001a̲\u0017\u0001\\fimc?p}\u001da2lEa$&4l\u0006LY(6COBao/\u001a\u0014}\\\u0012)A\u001a5\u00185J\u0014\u000b\u0002.{]8\u0001\u000e..]n\u000br[ۊ(\u001a%*XԱ\u0019mSӦi3δv!mӴt2M3Mil/2f9ߞ>f&mJ`OfO-'_Ʌɍˍ\r\"ܱj}6p/\u001f{V\u001ep\\qz܊\u00175)hF\u001a+\"\u001a\tӚjLjIM\u0003s\"\u0019fÙ!v43\u000egNsCܠ\"\u001f\\\u00074w\u0015YSe}~@DPC\u001c\u0000ܦ\u001a+;t\u0004/\u0005m\"h\u0011Uc*7\u0017'sM\u0018\u0015\u0011έdFNfXa젶\ri{~0ק=hgnK.UEg\u000f_\t\u001f\ty\u0015yB\u0019\u0016r\u0001p\u0005\u001deC\u0010mn\u0007NS\u0011gcDǐނA}\u0019\u0013ۘ~#\u0000ۥ悺\\noӝQ\t~+BY_٤+Ш>B\u001fIN1@QD,60aL@ش\ræ\u00184g\"dGٌ\u001et*t<lm5vr~c?l\u001cS4\u0019#BEk7~A|3GYg*=1a\u000fV4\u0007(Pg|(1Z\u0018c\u0018$ך#V-V\u0003:V\"1\u0001i&K\u0003hi|^pD)\u0012ܖ\u0005rYUcE\u001dE*ߘ7tY.\u001e\u0015,B~&\u001fE\f\u0016ǡO܄nq':Td! \"\u0016I,a\u001aJ+:z\u0013[kc\nxJpsjqYe\u0013oğT\u0013sTM\nܧ9:ި@WYL1Q[\u0016`\u0006K\u0011R,eQʃO2^*br%ZuJ͜C\nQE4!ҬB*\u0017#Io\u0011\"IQeyCUQj\u0004y9FzK\"\u0006\thQ~\u000e^Y\r|\u0010n0je\u000b\u0018lce\u0017k\u001b9Y+\u0001E<.g\u0005( ތ)\u0018#ʟʨrʨϨH\u0013Xt<S\u000fO?\bM@Su<՛˞\u001aG6\u001c\u000e\u001d\u001d\u00059J\u0018!3\u001acm\\\u0017aE`د\n?&#>U\u0015VG5U~B$Zʜ5!M^Z{&\u000eMpݵ\u000f6W&dw\u001e*&\u0019]\u001dg]\u0001\u000b]\n+\"\\F5uWep2CiJi\n\u0011zE{R\u001dpqbS#uEuSnCw\u000f}j\u000ew\u0018ςb_\u0019c٘B5Y3xwZ.\t\nוyw\b\u0013\u000ey_sjJ\u0011`&F\u001eOy\u0001\u0007]\u00187Gif-PO՟\u0005\u0010\n\u0002f\u0003\"\u00011\u0004j\u0019=d\\?_T䴼n\"[\u001an~i~-J#0GLQ\u001a;\u0006;Z\u0000P\u00110wn)\u0017\u0001\u001c\u000ej2@eE~W9\u001ctY\u0001V\u00132s܁wyu6\u001e5\u001bWGyu\u001a7H\u0003\u0011JxZ)st~\u0017P@1л\u000e\u0004oA^nh\u0007Rqp@P>CfdJ\tU!#:¤zq65<o`M\u0019>qMMKr)=kJu.ӞF D5-\u0002\u0001ʞ\u0014[\nd!st#2ƶ\u001ec8\u0007ia=R\u0016|+,a_؉p\u0003H\u000e0ç]\u000bM&)|I\u001aI\u001a74\u001ceָLZqh\u001ecq\u0014=\u000edL\u0000O ej=N'$$O`\u001af\u000eb\u0001I\"\u001eqH+FB\u00123sH\\3o\u0011FH28O1p#Mύ!Z\u0007-v87\tdRLL=\u0003e\\,'`f<\u000b)H\\8\u0017شh\u0012lX\u0006|s\b/#~qx\u0005qo n=<9)\u001e Ch_$\u0001u\u0018\u0003h\nП\u0006fI\u0001H^\u0002\u00076]p)\u0016\tD\"\\ށ\u001aX\"vŌu+\u0012XEJ\u0000ʕA\b\u0006|\u0011-p~I|\u0000gė\u000fPG@\u0017p\u0012S%gi\u000e\u00039i%ҿL/\u0003\u0002וP\u00011M}SQQB_CRJSN\u001ahHER\r!|dB29>\u001aeȲZfǚ550żmw\\]繟њ@ҚC\u000eeSeS\u001bE؈xx\u0000u`\u001dE\fD99\u00054|Cݬ`\u0019@\u001cc\\\t0^_\u0005o\r!(`\u0005$\u0001'\f\u0005NRp>ٜ69mV\u001e<\u0004Z[9ɭ\fu;\u001dyr)\u0019ɘ+\u001aƫf0jRӢ\tP6\u0003\u0019\u000776\n\u001c}@\u0015R;Nl\u0014_lL:X\u0004;:8\u001d\fu\u001c'F7yۀ܋\u000f\u0018o\u0000uQ\u0004`\u0002=\rPSy\n*\u0002_\u00026\u0006\u0002XAEl<\u0005sDw'\fL7\u0019;\u00000\u0010x\u00190ZSלV/\u0002R\u0007\"ȭ\u001eN'w97?=\u0013G3\u0001s\u0017ǼB\u001fOٌ<\u0005\u0017݋*%_꺑aу\u0015\u0019BFqd\u0002$$\u0015o+\u0014%9V\u0019)6\t*\u00185\u0019\u0010\tGp\u001f-'.\u001eo\b\u001c\rY\u000f]>\u000b\u0019C+\"/\u0005NyYG(2ꬢ:lΧq\u000e&9[<`\u001a_\u001aGz\u000f)s\t1'\u0003#`\u0014u\u001b\bQ/Z)ʤN\u000e`\u0011uSJY\u001b1ks4r\u0012.\u0005f\u001e\u0018~/Ȣ!ӝ7\b:WGP3ٌV\"u\u0018C\u0016\u0005\u0002.b,\u001alN%3\u0017_\u000egp\u000eqoZ躙Y<8I\u0013 + \u0006᧾\u0011d\u001e\u001bJQϟ0ԊhI>\u0019K\\\u0014P\u0004\u0002\\\u001b͜E\u0013140\u0013M\\\u0019ts\u000b:\u0011k42\u000eJC斒e.F\u0012\u0018\u0018`\u001b\rJ.$A\"\bg\u0015\u0013ѦV84%^:e^.\u001a\u0016R\u001c/N\u0002Z*\u001c4؉zzu\fuawc3v\u0019E= 2\u001b\u0007,wwȍ>\u00126^X\u0006㴱;MI(\u001aM\"pX\u0019\u00052\u0001\rʏqPze6>WN\u0004bOr\u0005۱t?63/Qmv\u0013U揱-xN,+?\rbIaJ.l?=*q|\u0010\u001d\u000e]?o\u001c\u0018\u0016\u001a쵘ݖѨ)n\u001ayf\u0010Q%*W`U56Y\u0001Q1\r\u0007^GXm\u0016nzxj\u00123%Gyg{G\u0001Fh\u0018h:!m3\u0012;m}Pc\u001bjQe\u001bvlMv`7\u0007\u0015v9Xg\u0018ka}9VoE{X^\u0003\u000fnA+'C\u000b%\u000eb\u0007Y(z\u0007Կ=}\u001cbi}\u000ez5\f5\u000e6t38zc?*\u001cð1\u0002ӱ#9JYXR<,u*BSP<ldXP8^(\u0018$,\u001a'!JuYЅ,t`\u0002\u0002GH7PK/W\u0012\\~\u0003]ݱ\u0007+\\P\u001aQ!-\u0019n(p/,t+\u0010J\\uBja:1{\u0017\\\u000bb{B!\u001fx_P\u0003\u000e\u001c>ۓ\r\u000fC\u0015\u0005%(Cg(\n<'bg$<c뙈\u001cTaW'dy\b^k\fJq\u001eq\u0011):2\u0019wNo\f\u0004\u0006\u0000/y̔3'+G\u001b`\u00183\u0014NX4\u0003y*\u001f,P\u0005bJl$UE!S\u0015\fUJ\u0017fr4\u00121EU&&6KI>LCR\u0019imE/R\u001f.\u0002\u000ba\u000e\u0019\u0010ǜ|+W㬰@=\u0004ծ\u001eL?2ԡHWO,TcN\u0014iB:[H+\u0010\u0013~\u001bvHZE\u001bN\u0011һ\\b͡\\l{\u0005Jza|7\u0018[ +\u001e\u0019\u0001Θ\u001d\u0000_\u0004\u0006!90\u001cI\u0001\u0018\u0010\u0019B|B\\`\u0018\u001b/\u0004.>\f\\/E\u0005(\u0007\u001dTL\u000b:\f<&JAig\u000eV29Rz)d>rIv!\u0004cv\rRC\u001c⎙!c1#\u001f\t!a\u000bؐHĄ\nѡIBTh0=4W\f-mSL\n'-kz\u0011aR\u0017YA#[]dK\u00113\u001f\u0011f\tH0\u0010\u001a\u0007$h\\\u0011FFhM04ᘮiBdx0%|09<G\b/>\b_#M273(Bj+7&\n\"\u00000#2\u001eL*\u00078\u0018y2T2E$\\Ct2_ۮfFmo^R=\u0007|yߔ-}\u0013ԋRR-)>Ϝ\"\u0007\u00073\u001d\u0019\u0001*\u0017{$\u001eefE\u0005im4%\u0011wW^z\u001cQM\u001f\t\tʶ&fPndX\u0018VL#1Z[W,2Z2\u0005cI\b>&6j!<@\u0019<MsL).gf2˞U9Y\u0011\u001a,[2m#e%)ݖ\u001cd;ӍbSRה<&{ytv%!\u000e>ۖ\u0004\u0003h!Y>q4M\u0016`\u0005,e,x\u0012\u0000\t9*#f\u001fT{RclO8MI<ceq1\u0012\u001cQJ\b\u0006sc9q\u00128o20~(\u001aP8P\n0=\u0007}\u000e6Oּ@uRʤJΏԸ(%\u000fXg85ڙQNF:\u0019YFsi\u0014\\oq2\u000fu\u001e1G;ϙ4\u000f<t\u001cH|\u0010\u001dyZƀ2X\u0000`*˝D&<5@Sk촮\u001a]S\nkdAFF(ޕ8Wr\u0014뚬\u0018W\u0011o\fq\u0019]U(N !8c\u001aTp4hw3EM}~Z-謄%P\u00023 2OEQ)aF\fR\\a\u0017)b4=L\u0004\rqn\u0006'i{\u0006K~5F_v\u0011~ψ,nD\u0016g\u0017j\u0019\t7U\u000eOl\u00173C\u001aW(%\rLmxI\u0007\r.骨y=5p^\r7D=IT_OxLSo\u001cExY\u001ej#ܳ\u001fN\u001b\u0019%\rFx\b\t\u0004@!'=o4hk\u0006)z/Žs@\u001b\u001eQ\n&+kSwo\u001e\u0016ے겤Rz_PwB'BJ+tO\n}g4\tg\u0014怋p\"\u0019h'2\u00163\u000eYR)̬g\u0002XyKy\u001eTh TĪshuL#XRyj_Y\nܣ7\u0014X񱂞\u000f\u0014i̧\u001ci>E,\u001e%e\u0000\bF+amڭku!\u0010u\nj[5Vm8\u0002պʭVU_Z-mߺC[[\u000f7䷦A-V\bsy\u0018\\۾HJ1eRl4\u0010^kЯBnfs\u000bnԢ:D~aj^\u001d)K`eổf+\u0005]M\"ˁ\u0007샓4(-wZ^\u0004;ir)\t㞓nwF[\u001dZi&sMk.:\u0006\u001a⽏B8jijpkxj\u0014u-HN~s\u0004\u0017p\u0017Rb]05g\u00059#\u0006э܆AV\nxE{M\\0p\u000f\u0010v\u001cƎ4Gh\u0018\r1.:\u000e:6z\u001dIù:bQG,\u0005\u001f\rr/ֱ\u0017>\u0006[#>AVG%h8ٜ\u0006\u0015h[mӝihml҉GccPϡ_ONIt=.\u001d\u00059\u0013_\u000e9%\u0001t\u0007\u001cz\u0010uR \u0011\u0003gl\u0013f1\u0010\u00183] &\u0017;J\u001fw>%}\u001diBP\u001bWf2PWIU\u0012̫8rf`Db405n\u000ft;\u001bxZj~yl\t\u0002ҧp\u0005>HK\u0019\u001co\u0012[ȝ\bkrf>\u00177\u001cvߐ\u0006@a5쇃L \u000e\rB,$B&'f\u0007ѿHi5\\Buz}M=żtC:~5V)\u0010@\u0000\u0004C(M44sћ\f\u001c4棱XׯuS\u0015Dg-:\u001bXsE]>\u000f\u0013c}X\u0011+]`F>/\u001ej\u0004h\u000b\u001d\r\u0003\u001d \u000b<t\n\bb4\u0016o񉖑\nR\n*ߨ\u000f9z\u001d˓\u0010x6*&|\u001aޚX\u0007o\u0017C1\u001a\u0012Hw*>M@'\u001f_\\h(Ac\u0001{)ezO<z߬M7tT~\fka\u0000G)3͉s\u0000v0X\\ \u0016穋cgh<\u001b\u0012\u0002<Sot8DN\u000e\u0012\u0003*\u000e\u0015~D\u0006F4cQl/\u001b[~\u001bn(10\u0002dtŁSXy:\u001an]W\u0010%,W-5ZCNv\u0013]zI;b\u0007fV\rU[\u001af\u000f\u0004>=\u0017lK\u001c59cnE鄩zj>\u0000^\u0016\u0004TPn\u0001\u0003\u0001B\u0004Hȅ\u0004\u0012@B.@\u0002!\u0001B-\t\u0017!\b\"BAQDT\u0014Ruκεgzvvnݥ]9o|=y\u00132|k\u00161\u001a;nmm\u0013W׆p%f\u0007.Ōb^\u0017pe^w\u0019qbpGX}qQ,<s<N\u0000>MB!R}[\u0017;q+6\u001b7D\u0016ĕ8\u001d.n0\u0006\u0007np̆vr|\u0018'p\"~\u0017b!\u001cMX8p\u0013\u0012\u000f1Sl\u0012ӛ+,\u0005e\u0016\u001c\u001djwѽW6\u0004\\ڔs\u0005xi\u0004XJ$+\u0016\u001a܂d\u001f\u000e'wc.\u000f\u0007#2-޺[b_77\rI}O0\u0005vG1\u001eQݟP{WH{1jm\b<OYΤd\u0016\u001cKBF\u00113\u0000׈\u0019n\u001dNLq=$\u0017{2\u000719ؕ5Ѭel{\u0019mc}\f~a ;_Q\u000fDHB`,uml.^\u0011`*\u0014*08ߎ1~\u0013F\u0018w\"\u001bPn\u0004;r`  \u0010λPm\u0016\n~\u0005(zBEtI2St,RCہ\u00035ΏǤ \u0005\u0013\u00059UPQ\f#J\f\u000bCh\u0001B7> }\u0010=]8c,Pxu\u0014b\u0007'\u0019k\u0017&j~GIF\u001c(}Ls\u00141.è(\t\u0011Q\u0016v\u000b0 .E\u001c!q\u0015b\u0013z]Bg\u0017Nt\u0014W2)ZXKM於C~ʚ%X$|@5敏)\u0015pS=e\u0018勔Ǡd#$\bJr#\u0015K*C@Z\u0001\u0000Ԃv\u0003enx:)\u000b-f$sS\u0012k48\u0014?&\"f\u000eE9OO5_{Hcq2Kc^2F9)_<\u0006Ay\u0002)\b(ѡ\u0010]QVE9*(Mp+Фtl\u001b\r;|Us^l\u001c\u001ecQQfU=\u001e|ƌsdL3NY)G\u001fQF@\u0015\u0007:\u0019,xphRRW\n\u000b\u001c\u0015WzPW\t[\u0000jƙEsjN1\u001aǨ}|H@1jO'\u001ePݛz49D&N7@9z_ЦG\tt|4j\u000bJQU\u0016*;,:7:?L>fԏ\u001a\f/1*Go6Gg!=G\u0007rO4\\Q|̒մoѽ =\u000f?eiѬ_\u000f>\u0011\rT\u001bx\u0019\n`5\\@m\u0006j#5uiBu\u000f\u0006c\b:NVefZq1^T\u001ar*L\u000f#NK\u001eT֬`o\u001a+&\u0018&uh<͔\u0018zS<l-0`͇VZ\u0019\f\n\u0006VTYZڠ\u0012aj~,r%(? (-I)QVNZ/#dDHSfZ\u0011\u001ase58\u0018mQmˀƇ\u0010:\t4u*TPQ_\u000bu\u0003*\u0007.(C'̾\u0017~IO\u0017LZ\u001feҺ(+#h!sd7\u0019$]CA\u0003]m4\f\u0006\u000bjH!\u0015<\u001b\u000br\u0016ܩҩiU\u000f\r\u000fk\u0000\tVgb9&rJG~Dο33čOݰ\u0003'ɋdI\u0007irP}\u001aɍN@ݳ9\u0006*w<d[2!kE\bR\u0014\u0012\u001a\u001e\u0003JV.>\u0014y(CC\f\u0013xIe_3L\u001fV\u0012e\u0005(\b\u001c%dtSV@uʹ[hUIѶ\nX6#\r\u000e\u001eD\u001d\u0005(\u0017Яv\u0016B\t\u0003\u0001/\u0002\r\u0004?02\u0003\u0017xm\u001cY/\u001csd\u0013?q\u001d\u00005iݧg\u001d\u0010&#?E^`!!\trB*d\fl\u0016nFf\u0013\u00102SH\u000f/!-|\u001dH\t}\u0015z+NRi2Bz\u0011'6\u0000@m\u000f \u0003\u0006W7\u0014Dd\u000e;<GDHȐ\u001aDJĄ\u0006$#i\u001fGb\"6F\\yT\u0015d\u001a\"\\\u000b\\\u0004\u0005\u0004\u0012T\u0010.j:ZS:*\b\u0006\u000b +\\\u0010\u0004\u0005\\R\u0012EG'rIsL:Fs\u001bq<\u0016z:\u0000p{-{\\-2=3\u0000L\u0004VáhG5֢]2PŀYO~+y\u00168u<\ne*\f{a\n#Z\u0013~/c`\u0014˹hfɱL\u000e52\u0014}'2\u0014|#ÜL\u000eyV-J\u0016!\rwdbR,)r\u0014'\u0005\u0016?WX\u000eXb''\u001c-&%P\u0006KG[̲ZZF%Y6\f5'Rv\u0006\u0002v̒+4Ļ\u001fxB\u0001MJ\u001d̐&\u0007l.@\u001f藢\u0004cl+\u001deS0\u001dw/\u0004q\u0018ƪxhU4j:qj\u0019\u0004\u0018>灼\u0005\u0011i06@0{]1\u0013K%\u00155edX+a\u0011Xo/m` ƣP\u0011;612@\u0012:\u0002X\u0006vp\r{KO\"ޣbrϯ.˥*4q~d%d\u0007Գ\u001cճ\u0018|$$\u001e;G\u000f\u0003\u0019؍\u001d=g\u000f\u0017~\u000fIރs{Ec\u001dp\u0003nk*>'͓\u0003|]%5!qw4V\r\u0001BB%}\b\u0007lN:PBp$\u001daI\u0018v\u001cg\b9s~DD$<Ɂ'\u000f\u0019\u0014\u000b=\u0011\u0006Q\u0003%_BfjDd{\u0000=Yp\u0012N')|FLN3,19%]`a\u001d\u0018B.(}INPWʤ8x\u0015\u001ed8Du:1>J;돟\u001eЧ[\u001co\f\u0017pp\tp\u0006&t\u0017;1({@}>\u001fn\u0000p/\u001b\u0011p\u0003_\b\u0007b?'v\u001f5Q5M+[4[R\u001ejcr}Ǯ{Gﱷ\u0016EsS{^\r\u000f=9\u0005כ\t\f`\u000f.\u0005AF\u001bh\u000eC+\u001eqrCH_i!\u001aeWk\u00152[EB ;ɳtUv\u001cZ+~\u001f~v\u0003uGM\u0006\u001bD]쟀F\u001a\u001a3A#\u000fbÎZ̙\u0015m\re\u0014|\u0018??[\u001f\u0011#(\u001cFXI\u000b\u00155\u0012h\u0006\u0013HKS?(4\u0012H\u001cИ9h\u0011b4\u0016qR<_\u0003Zق\u0005\u00115b.@d\u001bP+^?jF\u001cؤsbguC\r\u001d\u0000|\u0019h4)ڏ\u001d$/{\u0011;vk.rrk\u0013mOqR-Yۤk#ވ\u000b?;@_e.hza}\u0010D\u0013\fBc>\u001dرlÎر\u0019;ꔏ<-zU\u0012\u001a\u0013v5\u0011ZVJ*\u0012T\u0013\u001d\u0007)W\fx+>hv@Iy\u000b_b\u0018h4\u0005\u0013ICgV)\u0017B^fUll\u0012F-n~TTj{OĎ\u0007\\봷\u001eh\u001ah{NC-U'5vk}?U\u000fV\b0īܐe\u0014-5LbC\u001cfaJ\u001ch*w\\*v:\"*p~9.ϔbU\u0017nܜoGEچ\u0004{\u001b[EhsVDh\u0018_wTb\u001c\u0004-pM<I*v\"\u001c\u0015\u0016j[VjFtoPG6]T}e~\u0006֟\u0001h<w{a\u000bm~\u001d-\u001a*eAKM&Y<u6kg/\u0015{U\u0000\u001c<X\u001a^땪l\feSF\u0005Jo[mk4ջ^S|\u000e)\u000bv?U8\u001fB\f=@e\u0007v\r)\r`|o|jo|5]7{MR@e\rU_%j_OS&*%`\u0007q\u001f*9\u0006݆J\n4c\bi3T\u0012Bl)Ɩ\u0002\u0000'\u0006z(+_\u0019AJ\u000fҴ\u0012Gi498F\u0013G(%8^\u0013B5.$U!Jz@\u000e\u0010E\u0014\u001fvZþU\\؏`}ɩHL\u001c\u0016E1cll\u000e\u0006wpӔPo\u0006kRXgu\u001a\u0017Wc\u0006(\u0010%v\u001c1\u001d\u0013iFwJW\\<\\*\bE܄\u001fc\u0018I`\r,b%\u000bұeJ&w6jBƅ؈0%FDjLD\u000f%D\u0011o+.\"F\fWl\u0004\u001cS5,jF-;\n\r6oRQ1ѧ\r\u001a\u001ekP\u0017V\u001db\nUP\u0002s Qlz4>D(9IQ&1S9DqpŚjdt/\ra\u000344ztc\u0015-Mh`y\u001aн\\g̣:0+*\"\u0012EP\u0014E\u0014\u0006a\u0019\u0006eX\u0006\u0005T\u00167(\n.\u0015ǚ\u001c\u0015b\u0014&Zq_\u0012c\u00185֥1xXҨZMD?\t\\{0t^>|\u0006߂\u0017\u000e\u0018\u00183s\u00181T\u0010G9y\u0002%41W1~\u001a\u001f\u0013PŌV1V$ٍ6e\u0019s\u0019[2͔-WJ3-WAMJ`?fr\u000f1\r6\u000b\u0018k`\u0019T\u001c78bEq\u001e\u001agO9+\u0014h`U9Kq&(%a,pFIJHc0'\u001d+\r\r\t?:cx#%S\u0007\u000f3=|\u0014\u0013K!1'tTN쉽/[P%5)J)Iq$[d\u0012-`.s\\ŧ<+SJM2Z\u0018\u001c\u0019bS\u001e\u0016I\u0018\tQ\b\u000eg[)#Si)Zd\u000eQ5DJH5ʜ4LiK+Rm9-QtzƦoԘТK\u001cj\u00010;1Ue\f\n\u0001v~ۘ7m]Č~2g\fV|F2\u0014\u0019-cY1YVEg56@c\u0015ehKoPxve\u001f\u000b\nG\u0007\nr+\u0002^eti)̇\u0019\u001c\u000b߶L<G\u00163L^魘\u001cE\u0006ilnr4:/Ny\u0016Ee*ܑ0GF9HGB\u001d+\u0014FoC\u001aN#\u001cw4\"'\u0015V3\u001au\u0004JE\u0004\u000eHg$Oɕإv\u001a;SQ}\u00159\"\n\u0002\u0014V0\\\n50F4NHaF\u0014jxD\u0005\u0017kX\u0002\r-QP\u000b\n,ڬ!E\u0007,V`\n,`rȡ\u000e0\u000b&2F75C\u00101A\n\u001e\n)%\n.\tҰP\r-RPi\u0002KS4ԮB\r.AeUzl~ej@~~\u000175\u0007\r,v)̃r4!\u001fRr\u0011\u000b:\u0018W^A<5d\u0002Ӡz<Xa\u001ad3A~N;\u001d,U_g8^|[~]=^ܭԡ\u0018K8\u001b\"E;\rms\u0014=&(\u0002UtV9^7TwezU\boE>UvyWMP*սj\u00154ʳrU\u001eS99~\u0015nբ\u0000f@\tp<dvt)\u0012\u001a2K\n.ϕ.|\\`\u0002\nQ7We+_]5W\u001d\\\f0\u000eP}Anw)\u0017a\u001a\b9S\u0003sl)\n}tF?\u0007\\I]j<ձGk]\f5|krRKS?`L5`?u]\t\u001f<τ2\u0018G3ND;z4j4t1].<Jɣ3\u0000{AO\u000e<j\u00065\fDk6o@5<l\u001e}\u001fr\u001dNUY\u0004M-\\n\\34l\u0019+>WKXN/`\u0000^\r\f\u001b\u0018@\u001c\u001b8)a3/f\u0019f\u0016l^˹-\u000e~\u0004**\u0001uv4\u0017\u0001{Wnuٕ-thFt2K\u0019\u0013\u0003\u0018`\u000bP\u0001y;N\u0000n\u001e\u0014{7M.v77\\ĵ7TN(WRjgp\u0007G˽_&\u0019h'\u0006?mM^!A918P~!0q\u0000G\u0007B\u001fA\blp\u0002.|\u0011\u001a7\u0000ݾ\\\u0003G\u0000\u001c\u0016x\u0017`K:9:A$'1\n\u001f\u0012G\ff\u001f\u0001:GMhI\rކ* \u0019]{\u001c\u000f.CvyH8\u0002ZZg8\u000bU\u0013\u0007|J}'|/F\u0006\u001fk~\u0006Eo#v{\u001fn;tk\u001b`\u0018\u00063\u000e?MNñ=]\u001d|m--M<\rW8/t?\u001búB9sI\u0013m|y=C\u001b魇\nЏ\u001a\u001dF\u0017{\u0017o\u0015k:KkOB\u001c<\u001au:=K\u0003[Dp\\\u0014џD\u0013lAOЕp@\u0017F\u0013\u0019=\u001b+1\u0001ɤI\t*!q|@\u001c#q8մǋB)\u0016\u001dod\u0000JOX\u0001WGta\u001f\u0015(\u0013V2:h䳣:F\u001cG\bqK]\u000ek!*W\u0003m\u0001Wxvj\u000fgv\u001dBm1<{/H.ΐ\u0018}\"1\u000f++Y\u001cO䱜LYv\u0013NA\u001cTúuLM&آMG2ӤO<\u0010\u0012JpW0`\u00036``\u00036`\u0010\u0004\n$&!Is\u001cM4I&kf]zd=Uuӎv6դQҺN:mkUv޷dz{\u001e>I}\u0003R/xW%^սŋ\u00177Zʥc:\u0006\u0003\\G\u0011&\u001fdQ\u001aqX<pz}^\u0005ݐs:D\u0014v)^VY\r=HӨ5KH:\u0015ҩ\t.f\u001fƨ4&$\u001f\u0017^\u0005KcEi;\u001d:p\\'zL}L5i\u001f\u0015Tx{Y<򔞯+=\u0012\u0015'$eKDY5\u001eί g\u00068\u001350wk\u00178v\u000fǢ\u000f\u0012}'GuW9IX\u0002c~ξ[c_,oS)z(]Qx!˷\u0018'&sy\u0015[Ʃ\r՜-\u001c\u001e\rp8nCqS\u00117ρE\u0019l8\u001eyn7<R\u0013_ga4~\u000ec+Th)\u001b_4\u001d3\t17r|S\u0006+\"\u000e\u001b-\u001c4:8bB\u001b\t~&;a\u0013YLfWN\u0016\u0012#(ۓ2tיItLǶOJ|k\u0005z\u0014JA.=\u0013yJ-爼\u001cJ6p 9\\vXJb1RYH#-\u0010si#̦M2>t\u0012S\u0007\tgb\"\u0012㙏5;e2|+\nO\u0017\t=\u001f.V%?{ewV,Y\t,de#l33a*pN79\u0003nek4y\u000bg(\u0004\u0017\u0019(Fs\u0015P;.\"7)R\u0019.JŎ].%Y\u001d\u0005ˏg m\u0005\u000bK(dXѢV\f\u00152X4Lq턶GIP\u0002ݦ2=Ke6ҿ7Q\u0001׾H\u001c\u0017\u0007_Ny5K\u0018/Ib$\u0011S\u0011Cr\u0006M6MNJ)&X:@w8]eo\b\u001ds[<\u00077C_\u0011kҝ6\u0003\u001bG\u001eYyҾLh_Fͱ\f\f3k6\u0011Tmqeioi⧣\"D{(\u0019Uh:D,\u001e\u0003xlO}fۯ_\\DVyFWf\u0016\u0007\u0012/\u0013k\\2,\u0006\u0013'XL5\u001b\u000ev\rIM\u0016[\u000faS4,d\u0003\f+48\u0014/QxKEDd'{VwQi> f<aQS@M\u001c5\u0019x\u0005K+q\u001d4;\\49pvX;HC$u;p:S<Emq\u001c^?pF\u0015LWu\u000eJ\u001a뗏\u001b_\u0006ڜF<T49P_C}}\u0003Ά\u0016\u001a6h\u001cǮ\u0002ƵL$M5}\u000bkwůğĿ\"\\F\u001fŢKy\u0018\u0017z\u000eKq䊧ѕL}S\u0016ΦBjp4[7Q݁݋=FgJ\u001e*ZciO<\u0005[~\u0003/,*\u000fJR\u0003:\u0007M%Ҩ>ѩ6n5zq\u0018mIޚNuk>V\u0013ֶJ\u001cTzx#f(-Q[仗G~C\u0016\u001f(\u00137_eJ\u0014\"(YRZ\rX;TvPљN3eՔ1[(\u0007\u0012\u001880EQ`\u0017#\u0014\u0004.x\u000bO~S\nU..HgI*1'k*j;\u0016\u0018ʃ\u0006(`KO>=&z(쭥\u000ez\rM\u0013Iv Y\f=DFۤ~&~OF'dD\u0012wK렴\u0016ĔDPKINA?\u0014\f\u001a\u001bL!w(\"d\rU9@p\u001bA҆GI\u001d#yd\u001fGΈ$\r?KŻ$\r}*wJkYE\bHM%Zc\u000fUV\u000e\u001aQ[cȘ06HD:)y$OyZ\u0012'$b\u0010cxMćOb\b_\u0011O\u00137x\u001bG\u0018?#~<\u0016i1\"\u001eѡ5UIJQ٘U!}z\rI$m8Ms\u0017`/\u00156\u001b8e|/\u0013Hu^d\u001bD~@cL<0\"\"\u00032\b\n*\f\u001c5\b\"(Ȧ\b((\t(8*\n+˩₩\u001e1n&DQc%i[5ǦMjԨI44>99=Ǚg}T:++\u001cHϖ\u0012s<r0K5\u0017}ŀyoԣM\u001e\u0016Yj%H.rDCf\u0010\\\u000b\u000b2`]x\u0000\u0018\u001ck\u0018ت頫g\u0010\u0012ȇ,\u001eIF;\u000e\u00119X2n@5\u0016kE\u001erA1x-Xޟfʋ\u0001gȭ\u0004Ԋ!+\u000fZ\u001bp^9\u0014\n\"\u000e\u0005҄9a\t9\u0006\u0017H\u0003x<\u0016:W0\\\u001aht6|6҈)m4\u001c\u001byx8l\u00140fa[\u0013o\u0016=oUf\u0001d\u0011I;}Ț\u0019M\rQ'f\u0010Rg\u000exmvh\u001d\u0013?vpM᳇BC,1̬nsZsItJk\u00079r9k_/\u00197K\u00064v\u001b\b'\r>''\u001e-\f\u0005\u0007<h\u0006i\u000fHi\u0015?:^m䤍\u0002k#\u0016m\u0000#HG\u0005&4xO!މK\u0007yp\u0014z\u00035$/\u0012\u001d#\u0006\u00020\\!K:NL^'&'I;M4oi\u001a3tΰϒ賋X%\u0016g۹O]\u001cJ6e%9X'nL\f%x\r^\u0007B@\u000eH+\u0018\u0018P༫t\\\"7eP\u0010?.Ӕ}ċ\nyd_\u0002Az\u0014Nye\u0004r\u0002r\u0006^_j`}\u000es\u000eà\u0018_2|\u0004W\u001a܀N'\u001dr1|\u0016 G\u0005|`\u000f\u0000y\u0004;\u001bx\u001f\u0004`\u0018<g̘)WߨٴD_3=a{Ĝ%s\u0003&Ltt\u0019S]???'ܽou\u0013wp\u001d.]N ǧ\u0001|\u001ai\u0018q衦2)s˻̗V>ŏ;q\u001b?>Əq)\u001aS\u0015&\u000fժ\u000ft\u0002\u000f\"_u\u001e\u000e~\u0003uyzYW\bz+T\u0013XG\u001aO~>/~\u0019\u0010طb-v7R\u001e(=zB>C,N)V|\u0012^\u001d)<R\u0017\"f v'\fBk(:hL~Q6OI\u0016aToS~-]vف>P+[]G\b9DF\u000fx!\u000f\u001d\u000fNgu%y\u0016ab\rQh@#\u001e`52yi>ZU\u001a\u001dƏq@Vf*%cD\u001cuX;\u0003;\u0001\u001d\u000fM,$\u0016ǩW\u00155Ġ1\n㱟LV<Hf؅\u001f;I+\u0005o[m${\u001d\n_v'\u000e\u000blS#8\u001eia\u0000t\u0018\u0018Nr\n3l4\u0019?6ᇍl>\u001aUG$oV*V[rcգ_Ks4g\u000b[{/^g\u0002\tA'\nhEc\u0002\u001a)hd\u001bc)E\nZV,\"\u001f\u0016\"[.v._iswr#\fk\u001bG>>wpel\u0006wUSVw\tJhYG%Vu.ZꚢZL-q\"|Y܊TVj\u001aZ֤y-*s?RwTcx<Q9;đz㽅WM\u0013ظn\u0015\nVziew/wRZ1H\u0016C\u0016\u001aF\u0010\u0005$LU\u0014Uxjg<KT5_^K5ǫAE^Tc\n_,w5\u001f}y\u0005J'm|^-,]dtBo\u0016x\u0007ۤy\b\u001b8Z%x\u0015\u001b'jO|T蓧\u0002\"PbJ{nUNSMe\n~\u0004{''y\u001c0\n@C\bm\r\u0016\u0005S/]TK%~4ׯ*\u001b5XNPg(?G\u0005\u0016P\u001aMcUfM%\u0016ئJ\rA\u0007smױ\u0004Ā6lE\u0018泊r)Ɨ92;C(?f\u0004\u001b\u0018\u0018e\u0007TV8M\rJԔTeRz<+e@\u0007lФJ2\u001dJ4]Qbȗ\u001c\\Ն.ڍ\bi\u0019TC\u0019s_/2#r{hZ\u0006Sfp2LQJ7\rSi&+4I!\u0019\u00188R\u0013BjQ杊\u000b;\u00024.\rz\bn]Ff\u0018*`n\u0014ˣ5!.Yf\u0017ez*=W>J1l\u000eD\u0010%G(1,V\ta\u001a\u001fAي\u000b/иrF,؈\u0006lC\u001a\u0015uR#~\u0007=;iAo\u000bm\n1\u0000\nǽl09C\"J\t\u0011\u0010\u0011(E\u000eӸъ\u001cQ)\u001a\u00135U\u0007kTtFF[4b\u001a0dǼa1\u001a\u001a\u0001|`!v\u001dS\u001b\\7y\u000fa&po\nK#.\u0014M\ṭ>0\u001adQv\u0019MvD}\u0006\u0018\u001c}GEepcĠ`Ԉ\u0010\u001b\\\u0000Ƹ5qiFkUظ/MjzbNs\u001a5MSTk7\u0001IOsf`f{{K9\u0006Y\u0013eIPfRIIHJWzrҒR%SJMJM]\u0014j%\u001b7)\u0012MG`\u0000A,W\u000e\u0013}́z@\u0005\u0014y>9JTq\u0000\u001bd2јTI)&\n`ҧ)1ݮEX\u0019\u001b\u0015gޭX\u001b`>\u0007x7e8\u0006نV7m\\30\u0015*\u0004ǔ.SR3(<NI(%'*!3U񙙚IePX\u001cM,TS+:k\u000e+2,=E[\u001cl\"*3\u0001k\u000465C!X!Y\u001d\u00167%ey)jP5PqpZ'hBvb5>;[9%ʩVdLE(<wrWhpH!yBsC8\u001ehEc\u000eh\u001aTB\t*\u0016'cW\u0012\u0015|_/WTA\"\u000b\u0015Q\u0010B\n-\n-,THQ\u00155(YAE\u001d\n,zN\u0001;u\u0017E_\u0002\nQ`CE\u001dĪB9\u0014\u0015<\\*1\u0014U2R\n+3(,H\"\u0014\\\u0016d\u0005\u0015P'\n1\u0015M\u001a]&C3xQ*IV|QwW@2z\u0012hKUP\u0002y0\t\"_:FbUB*]\u00144Sվ\u001a[=VcC4:Zx1ȣj)Z4ʻvjY\u0015~ \u0013<kC,d\u000e\n(bjP*%;&KQS\u001a)N2L\u001f!z/ @޶0yqyڒ!S\u001e\u0002۪46Cn\u0016:b땳m\\%ܕ\u0007jGqـ^5B\u001ekvj%\u0013{\u0014]+a\u0019\u0003m\u0019l\u0017y=4\u0011r\u0007\u001e)gD\rdj v~d\u0007VjĨ6b\u001a3|9w\u001fZV#5\u0006Yo\u0011X\u0007h'\u0018QX\u0003э7I]N\u000b\u0001\u000fP\u0006\u0003J[)^lX\f=m|!3]\frȣzf`\u0014>\u0007}t\r\u0001jK4l)\u001ew)\u001eW\u001be\f7\u000fv\u001e2\u001cl\f{\u0007Emg\u0011\u00136k|m~s\u0015n\u00130\u0005(z8\u0014E\rBװH~Rr_&,K8p\u0001.+*.]tq\u0002\u0003íAaa=\u0014\rG\u001ew1]_5\u000bͩPFs([\\!k\\>\u0006Z\u001diJɩ\u001bm*\u0017si-\u0017䱎<S\r\u0003\u0017Q\rzt!aGO\u0018>jb`;\u001f6\u0001{[\rVf\u00016SD\u001cE\u001aVFr{\u000e\t6x\u0001h$2\u0012\u0017.c\u000f}c\u001fc}\u001d\u0017\u000fǹ}\u00007TGKH1Ia1y\u001c5빑o\u0019z\tv^x\u0015\b2\n\u0000 3#jrK\u0000\f\u0003y3\u001b\u001c6\fY+0\u0004;g6~K8N[\fu?E\\v\u000ei\u000eh\u001d\u00182@o!ނ18\u0001I\u001e59͌#\u000b\u000b<\u0004/W/RK\fե\re\u0002_&*F;\u0013Dj\u001dǒ7\u001f\u000epjY`\u0002\\\rU\n\\eN>aFї2gl\u001b\fMV\u0016żu\u0018ؠu\t<\u000f\u0004=\u0011w'-]U'm\u001fu}r\u000bu\u0003\u0017v\u001d\u0007xa}k}Ӹ_C<ω\u0010\u0017\f<\u001674}t\u001fWE/JD3\u0013|t*Ш-6\u0010\u0013KANw}e\u001cE|y\\Y\u001d\"qyW(\u001f\u001e29?9<{\u001a\u001a=;\u0019B\u001bǲQDJ^G\u001bt<ΐ))y|<NBi~\u0006NCُ<8$\f\u0003S%^\n^\u00128=\u0004t2a$J\u0018*\"\byI_\u000ek\u001e[X\u0001\u0003k\u0018\rz\r*CoBݺ](Dux8}hșy\u000e\u0003k\b\u001b!~2f\u0005]ʶ$v\u001dmĞ=j\"\u0002.f\u000bkVj;\u0007ًd\u001b*[j3\u00117ѥ^}'\u0019:\u0006\b<\u001eZG\u0006H|?É\u001fG|#-t9إĮV棏9ݬYĞK\u0005]B'bBY\fzZ7DfV-7м8\u000f\u000e\u001d=vj=E\u001fE\u0004⛈ja_BJRz\"~\u00131[R:ҩr|.t\u0010}\u0019lc+78\u0006vce+ڼ\u001cQ蹡MEǠ\u0011F\f\u0013JB!_I4&QK\u0007ј<v\u0013TC\t\"R\u0016iOǛf\u00078͑vu\u0017>X5<\\i0w|G'\u001cX4HG#\u000b|4J\u001f=ͫ\fO\u0013[;i$Nb'\u0013'sqbױsqiRM6Z\u0017:umU\u001d]K+T(L\\Mh\u0013\t\u0010B6&\u0010B\fĆ\u0010\fm0ډ\u00013??~:w}~{\u0007c\u001fc/\u001eV0]b\r-|Q_75O op}\u001a\u0002$1s4WG\n\f:kѡ\\i5ϫ~\u000fj%?L\u000bFX0i*\\ъv\u0016if/hGɋ*ɒ5Q&>d\u001f\neE\u001ci׸?-Ye,\u0002-5jԪJ-ЬyC\f=ij\u0010׌!\u001dƔiM\u001a5a<\u001bNjĮ1]ר鞒ה0\u0011F,Yڬ^FzЧ}c~,lZ\u0005sLf1;5mnДE\u000eami21˘F-Jn\\U\rc>nzRqU\rZju~?\u0003>./8\u0003l\u0011>Xz\u001e{f,3qږ)Q)&\u001c\u001aiU֦-\u0006,x\u0006wnm~LъksxUa\u000f\u000f\nWާyEit-<3M2\u0014s36{\u0015f\r5dw*nנݧ\u0001G\u001d=9bV\u000er\\Ym(TO5wU:k\u000foÇg\u001f\u0012ZI\u001b\u0003\"r=I8c\u0019e^F\u0018ːH\u001b_mUPY^g8[\u0015R&Au׎*X;Eu\u001dT\u0002o͉[=\u001f?kh=\u0011R\u001ei\u0018oޡy\u0019d,}<E]\u0006E\\\u0016]VU.W:p^ߧ@}BI5RgZ\u001aOxQ͍o;|BVW9\u001a\u00164c\u000f@\nF\u001fjg{\u0014xr)QcRǦvC\u0001O<jmlS7\u0016oT!57<'o\u001a}']P[\"ww\\\u0000i4\u000f`?\u0017[0\u0006\u000f\u001fe,a\bBGs\u0002F6W!ϩ&_->TckDָ\u001aTߖۿG.Ljj\u00037T\u00132|[/iW?ճ@su~NB\u0012\u0010/\f]\u000em|\u00065j\f\u0013RC%w{\u0013\u0004j\u000fc@\u001d霑sE՝GT*^eٻހ_p7ά濏\u0004\u001eY\u000ejN\u0018~#\u0010\u0004?\u001cyJ\u000e\nZU\u001bVnT\u001dTeOL\u0011CS\b-isCO,|\r$[[&[=>Vy\u000f\u001354ИVA\b:R#Շ}rn1*bQe\\HnUCe\u0011٢CFS\u0014]C\u0018;'Ḵ{Mb?9WY73hzϣ3N\u0002\u0006 \u0002Aۄ%n໣RU_*KT>`RـUA6\rj`#e\u0019\f\u001c\u001f)>\u0006s2\u0019\u0019/]_SIǴ0\u0000:\u001etf|0^\fB\u0001-'F)ՃR\u0005uPAED6$dLeHKɘJ\t\u0015'w([*H^T^r*7C%~\u000f\u001f(c\u001dFg\u0018J D H~h\u000fObl3ɘ*QIʤ&\u0015*Lժ ըT@\u0013aتu\u0013\u0013L.\u0004\u0004EL%*Pl܎3%\fC\u001fe{ˇvLJm\u0012<I\r6b\u001a3KO$\u0001f\u00134/\txi4ETi\u00168+\u0012{@+\u000eA\u001c\u0010$Vb\u0010s8cF\u001a,ڵ^ԖK\u0018%\f2~Ppg3,l?\nEm$Pf>ϳ\u0014?ݿ}\"\t\u0012\u0003\u0010JH\u0001%:bv̠RѰ$\u0015H@p\u001ch\u001cĈ\u001c`ּ>5&ym\fxyX{g(b\u000f\u000f\u0005\u000f5\u0018\f\u0013s/w)\u00001WΣ0JWA\u000fJ\u000ec6\u001fԔG1\u0018\t#uơK?C\"<˚eße.o\u001f-q3<{>Mzmx_ShB?ʹ\u0003\u000b|\u00195[B\by=\u0005g®r'oϳ.0gK2{9\u000e\t2{2r{\u0006\t8|oa\u0003<!j\r]q8zlk\f=?4\u0018\u001f\u0002WӘ녘r\f\r\u001bD\u001d\u001d\u000e6B\u000f4-qEUswJ21s\u000fg\u0011\u001ct@5yq_\u0011\u0011!1\u0001\u0002&@\u0004\b\u0000p\u000b7\u0005\"  \u0016\u0015V}ZV[;SnUu^ZYٺ^9gtksZ5a\u001d\u000fw/>ׄnZr1\u0003x\u001cv\u0013\u0010\u0000fK04&{CYi\u001f>>椏 \b~q\u0000>\u000eJ%?A۹B>z\u0007Ƹ%9\u0007j]\b\u001ccF\u00042ur9ACa?/~곟B;i\u0006\u001a8\u0007'U9@m\u0000cAg|FW(ćW$\f^~Ea{3ظ!'}q\u001a=/\u000fX\u001fRl\u001f\u000b$\u0002Ip.G\u0011\u000e&&\rҝjKt>oKOlH1\u0005\u000fӝS{7$\u001d\u001dۘ~S\u0015\b \u0015M̫2ґZv>\u001eϪ@V\u001fOS;tF=ğI\u0016\r|ݞpOѩy\u001ee\u001d\t\\0]׹\u000b\u0018<w2\\R@w^62\u001cR[(ד\u0016b\f=z\t\u001f/\u0005|\u001cQ|\u001ca\u0011x\u000ei\u000eRr_GKVL\u001e\u0004v,t\u0007r\bSk\u0017\u0016Ɛ\u00182\u0018C\u001eK@\u0016b\u0000~M!t(ޣl\"?ZI;ηq2n\u0010?Wѽ\bg@Yk\u0010@ǌ\u0015\u000ec\u0019i\u0017}ɼl>i\"'\u0013k\u001eL>\u001eR\u0007X\u001b\u0016f)'Z:%t\u001d,e\u001fv+-H\u0018|'\u0012;!.'v5LqTa'&3iB/\u0015mt9.h\u0015XI\u0015dn9L?Ev(\f,\u0011r5^qOCr\u00111/$v9u\u0015&\u0011\u0002q'\u001c-[|c!.\u0017yds.3:\nO\u001a\u0004n1\u000f.̓ي\u000e\nU2\u0011E|\u001b\u001d$E/\"|,||\\q7˺LOgT\u0018T2CeO\u001f8[S\u001c\u00056[\u0007.R^\u0001/\u0016i8:\u00164\u0012D#\u000b<4(GJ31yJ}P\\M曓Tp$:\u000e`v [6\rjV\u0012\u001c^?!=8\u0002-\u0013:qHCh(fSwԫ\u0016M\u0018ԡAS4>.\u000bY2a\rݩЃj\n=!\u0018v\u0019A@{ql5[=0\u0017fO53\\6;ܠICtgUaɚ\u0010R{X\u000fi\u0012\rTkh79|uq\f5D,P}JEn\u001d<jI\u001d\\\u0010\u0013hn\u00188z`\u001cfB7]<K\u0007^:Cn0j!Fx58lP!G\u00021X:cj\u001amUeTiڨ\n\u000e\u000fI߇4k#[c#\u0007\u001c;zy\\s,k\u00164G\u001cFI\r8ՙ5j9Kf\u001a\u0015UQU\u0011լ\u000eE\u001f3G%1Tl,T\u0010{\u0000^/=\r\bh\u0013ZWL\u001dZ1yހ:ƆbT%Z#-6UZUaq̒X*Rq\u0018\u0015ƍSYg+JUmr);%8\u000b:\u00040Z+МQt*Nh1\u0005my\u0015>GBTaT,5VŶD\u0015ٜ*e/Hy&)7U9]N%}Ik2*#\\gsó֣\u0014T=\fW|$^h)Ub{\nFʳ'+מle'I.;FY)LTc\u001d|Pr:#\u0005x\u0007>3\u001a\u0003z\bhL\u000e9eHc_\u0003#yV\u0012R\b!:\fqq)ˑLS\u0019,yJO-QZZR\u001aL#}R\\\u000bz@IGe\u0003Ǖ6|W<\u000fh5\u000bћ<XuPu9~\u0000/^N\u000f\u0015\fI.W\\6Rpɑ\"%gV*)AJt(=OUy/G\u001a\t\u0005}U6w@+јfyP\u0007P\u0003ϼLC\u0018D)3BI\u001eiJ(!ۧrrjemӈ)˝X}x\u001fQw7\u001cU\r\u0006ؽhN%i\u0000UP\u0006E<\u0003\u000fr{ \u001bH%\u0014o-?A|Fg*ΗX_\u0016_b\n*KQ\u00052\u0017.T\u000b\u001a^pQC@KПDڑP\u000bP\u0002>ȅL|}^d+\nW\\QhŔX\u0015]tȑ_$\u00144(c,\u0019J*t=TO\\K%7ME\u001dF4\f gR]AQg\u0018\u0017]wEЪ(*\u0002\n-,\u000b \nB\u0004\u0010\u0002\u001em\u0013ăD\u00133iFUi;1&ͤN\u001dk\u001eNc̴L56i֣c,d?Y罾}FL+\u001f`WJQ\u0016\u0005dv|\u0003dȕQ\fJv\\*C\t~;+ιOcqX\u0014\u000e^8V±\u0007`>(\u0001 \u001c\u0001*i\u001dd_\u0010+;IFYIJdT'[\u0002y*\u0014u)ڋ\u0004'/\u0002ыp|\u001f \u0010<<_h&\u0004q\u0003;(\u0007@\u001e1τ;\u001a~$J\u000b~d\u0017ŉJ\u0014\u001b**@\u000f0\u0003\u001c\u0000\u001b \u0000:3\b\"$\b *\b \u0002!y\u0005URx\u0016\u001aP\tJ\u0000lL_qÿ\u0010~Llu1JXbPt\u0003\u0017|\u0003\u0017R.F\u0006z#ìCH\u001b\t\u000bNjų#\u0000aKgpK-\u0001/p\nPH9ĜE̓}O?/Q_µEg\u0005KO\u000bF+k+:w%K\u001bF.(\\\u001b/Qu`;ϰ-D\u0002MT\u0013\\~\u0002vPBsy&1O\t_\u000f?f4`\u00149\u0016\u0019\u001aVAZM.\u001b?P\u0007\u0017pxs{E\u000fz\u00013\u001c\u0002r\r[d\u0011\u001f!m\\@̳p}jΫ)$C\u0014\u00057X\u0018laX\u001f\u001f?\u0006X6N`\u0011LM6s6U|RMySpw+\b\u0017TQ\"\u001e͡|ի\u0014^3uK\ta·A?\f\u000bXWY<e0\":\u001f\u000e1%7\u001f\tp\u0018;q|'q\u0011L~xԹ|Ӊ9c5=\u0012mp>\nq/O=\u0019r,\u000bw}qK\u0000C\u0000M~'q~\u001fg<>,\u000fO\u000bڙzb/ku\u0014?#|ag\u0000D:a\u0007\u001c\u0000/Caq0&Xk\u000f\u0018u\u00197F\u00194(8\u001e!8G\u000f䠿&M\u0007\u0014\u0013\u0013\fs\u0018\u0011A\u0001\f\"\u0010;`4\"hu\u0004&x`x\u0017?NsfO\u001b\u00198)w\t\u0014/:r΄;M6\bHhD\b9p\u001d\u001a\u0016ɈH#\u00198\u00038r\u0010pu\\,b%\u000e%\n~O\ny.\b!\u000eMwAQj@|ν:\b+OQ8|\u0002H❧I~E\u0002?\"s\u0004p\u0016h\u001aBp;C->Un3o>$}|Q\u0015X5=:7\u0011j\u000b\u001f~\u0017{\u001e=Hj=k?\nUx3z]W]R\u001at+pk>\u0013\\\u0003P\u0002\\fFi3\u0013\u001c[\u0004GP'^uz|:z\u0003\u0015:~\u0018C\u0018E\u001e0-\u0017{\b/J'i\u000b:\f\bA \u0007ƸE+Zd$\u0014,%ض㷋\\D\u0015Kè\u0011!\u0006A6\u001c]Ty\u0014xscu\u000e9\u0019/p\u0003ޏ#N[f|a\nGb\u0016]m;V]a;\u0006l/nvS<\u0010\u001b7v\u001f#dr\u000b\u001dEA+|2\u0016\u001b\u0019;17bۊtf.v\u0019#ʎ\u0005^\u0000D\u0005Z\u000e=B]\u0001F yB\u001bz\u001d}d%\b,ã%2vb\\lQ*'a{:s\u0018υ.#U\u001a{~=7QBy\u001e5df'ީ\u0018~\u0012.=\u0014\u0019$\u0017\u001b8#`;\rۓ=\u0003b\u0010eد~\u000b?:CZEK\u001bo\u0016\n\u0006rzSL9q,\u0018Ǭ\u0003`#v\u001dpFHo~:b&'2\u000fB\".\n\u001a8p\u0004@wtұk\u0019uԣj\u0007 .3HxU3\u0000\u001e2_\tVq\rG-*\u0011\u001e3VÑ\u0001G&\u001cȃc\u001eeT\u0000\u001e\u001f<xk1Q舅Kyt7͉w3\t\u001b\u001fùs\u001cW;#k#\u0012w3p\u00135&Ū1>Y\r1\u0016GT\u00175Ii\nDe\u001f=G(\\jycm+U5qr\r\u0011?'\u0013L8\u00074^z\u0012JKX\u0011k'/\u0001SIF-6X3k,!K.l-HWMbHQuOzU&.U\u0018Uf\u001cRqJL/tBE\u000f\u0015p\u000b|'6\\\u000fp-\u0003^~w[6\u001b2UcJӔjTM3Te|S**7WUV㖫hjͳUk}Eso*!\u0006=pm`c\u001dmzk\u0000\u0001.|q⛃SbUeMRŢ\nMI*NS5[ֹ*\u0016Z\u0014S\u0002;IyW)7urR٩O+fL9p\u0015{HC\nU\u000b|w*\u0002_ԖTRST:A\u0005575Kslʳ\u0015*V\u001cDEʞT5#}2.\u00195-cD\u001955,\u0013\u0002!\r¿\u00164`\u0003$\u001c|\u001fe\u0003}oJx\u000b\u0010 \u0004b\u0002\tI\u00125AI*\u0006\u0014;VYKfnVbUQyUۺuն]ﶹ]n9\td\u001d'y^z|*|̍W%Yety-Y*R OGrjU(E\u000ek\n&-V_v\u0016l4~PVg\u0004~<mYm\u0002j8\u0017!\u000b:h\u001d0\rL\u0001ܫJ)JA (ͤB[\u001c6\u001bpUJ\u0006kRAsR~Y;|Vf)e;\u0006ו%?\u0004\nzX]\u001cp\r\u001aU[\u0019(\u001f\u000fp9&HQ#]vGlNN\u0007(V^OSkr\\m2{^,&ezvyF\u0019=V2h\u0003o\u0016h*ցS\u000eJ\u0003|wIcTnI\"re.r+\\Yŵ,\tTҪ)ݻQio\u001d\u0006'}\u0013\u0012ܔ\u000bR\u0016S\u0007p\u000f \u0006@)>\u0015\u0001߬8Ki̥*PfYI(/Tz\u0017T)\rjhQjE'Uo@ɾA%;Ċs2T\\*>W?\u0017a;R\u0011ԃ|ǤJ\u000b\u0014pϊ|THپx&')ʨL\u0019iԪ\u0002P*JnRbuDŚXFwlU|^U\tկ+|DU\u0002ݬmo\u0002\r\u0006W\n<w\u000fLFjV\u0014\u0019Je۔wiL\u001a\u0010@\u0005أ\u0003+\u0001,X#\u0010,~\u0016o?c-bf\u00116WBQ9(\u0001.ÝW\r-RZ N)S\f24`⢇X$H\u0006)Z\u0007Bh\u0010B6\u000b)B\u0000&Ȗ\u0014D$4\u0003>\u0006\b\bTP\u000b*1Q\n<|.\u0006HF3\u0012ńٴF4P(Ni\u0006O\u0005;\u0017J\u0017N3X3\u001c\u001d.\u0002kᡖ&lAĵ)\u001f\u0005\b0(4\u000f1\u0000{\u0005$f[3\u0015\u0010\u000fK\u00147E\u0017,^mfv\u000e\b\u001e)\u001e\u000f\u001d##ψv\u0004l/\f\u001bdx:\u00054z0\u0019^o\u001a\u0010\u001d\u0013\u0016Q&R1&J\tȵ\t\u000e\u0016Ny\u0017=/亭M\u000fԃ\u001e>!\u0014\u0010g}6bl\u0002S\u0005|\u0010s>imd7y\u000e\u001ap.]6\u0002\u0016E,`c\t5Y\u001f\u0005Q>\u0006\u00059f\u0003q/r9br9c/[\u000fyf\u0010g\b\u00060% <RIFxK\u0000-Ƃ\u0001\u001f+j'\u001fkcmt\u0019eg\u0017\u0003\u00043~i 'җ_c6QaR\u0015k\f̫WFx\rK(\u000b&ρu`= ,k\t,\u0016AR0/A\u000eAn>.mm,\u0017\u000eo:HCYk7f-\u0018Pl\u0001\u001f\u001c\u0013\u0001,`\u0007\u0019'&'ߡOQ!zt\u0003~\u001e\"'(~\u0002\u0006sbϫ\u00155*]M\u000f\u0012sv\u001f,!{_3hl<&Bh-TlǄ0 ň2\u0010=r\u0004?F\u0011\u000e\u0011\u0006(8\na\u001e:t\u0012PuV\u0006r\u00184%-\u001b|\u0001\b\u00034.F\u0000\u0015&1BJg蓳q\\\u0002E?OAr3!pFpv\u0003R#<+;\u001c<\u0014au:\u0011\u0015Q\u001ax\u001d\\\u0000(.\u0001A]6\u0007}f\u001aJ#+\u0010{^8i\u001c=s\u001byS~}=*:\u0003+G\f/\u0018\u000fP]Wiԟ%.~J~B.i\\:\u0014ops0\u000e^\u0001/c_>Q\u001a\\f\n\u001b4G5t̻jL\u0018?~ʹy\u000b-\u0006J<Cs\u000e?DP@LÜ:\u0005\tt\fk#Dw\u0014Q}\u0005\u000e;1?\u001aR1\u0011\u0015\u001e\u0017<eد%Su\u0006e2~ƏS(\u001cX'P84F\b~\u001f6f\u0017\u001e\u001cs0>Cx\u0007ЙOE\u0015\u000f\u0018\u0016\u0015\u0019h47jvP}\u001fhũ߄3,ji0)\u0014('\n\u0003L5{ #u̼M`pEWhT՟W<~`;\u0003۹v0Ŵi%\u0016mx\u001c}\u000b%\u0018rǘ\u000b\u0016as9jj=7{L\u000f`e\u000b\u0019R\u001f5:%.Z;}Q`O#6\u0015Zm/\u0019u؞{݌VlEݥ\fTe\u0013 е/iVқbX\u00181\\G.t욱k\u0003.l{]Z\u0006쇰\u001fV+#\u001c]Lb\n\u0019Y<H0\u001dg\u0004?>:1~6\u001c\u0013\u001fkt\u0017v\r5bׄE\u000bg\u0002\u0017?RX \u001ca2)snM?ӳٮ\u000e:e\u000e05\u0011&9(Fd\u0003\u0007}\u000e{\\,XH.&=F\u000fڍ\u001fc\u001e~t\u0006\u0000\u001c!셱ۦv\u0011,n/f\u0016:z43Ua\u0011\u0016K\u001aH}$A+o\u0015X\u0006\u0016&fp:9/:\u001cj\u0012Q6LC\u0001\u001c\u001e8JdRruaĉc;ǗN8NvlǱs:M$m״\tK֭bBJAV\u0004S\u001dV1D\u0019m0؀A\th*h6&.ZQPG\u0007'e=:3Hì1V*f\u0006젗\fc%X\u001fz\u000f>A4lsG\u0006X\r㰔gKH\t\u0016\u0014\u001d;;Ѩ$\u0000:u4\u00072to>.&\tzg=;6%ʯc³x/U\u0007|8fw\u001e\u0018cn\u001c\b\u0017\u0010\u0010\u0015iL\"\u0006.|5ը\\nsL]:Yu\u0014v0\u0011\u0016-WxZ(m٣fA,ǔVr\t\u001a\u0001vM{Ra\u0018\u0000G^\u001f{\u001c\u0005\u0017jSW\u0012KVZliDҸZJJ[;lWʺPɲ1%(n۬mj\u001fS\"\nۧ\u001a\u0014:\\G\u001a8N\n6\nCC7]'\u0013caVDY]-vJ~%uJأj\u0014w)UԱ@\r1E(llVG!~\u001a*h<\u001aG\n\u0018W^k\u000f[K\u0017B\u000ezN<Y޵\u0010K3J\u001aV%\fK1çF#\u0006#Ѥ3zgC\n(Z\u001a\u0014pV>Uy9-粼u7\u000b;\\MZL3\u0014v@gi%r1O\u001a\u00165m\n\rջ+\u0014rW]'\u001aO\u0002\u0015\u001dWT]HU+ީJ.Uq}\\Kryr{oj'\u001a荓@.\u0018pm4$x\u0017#FE[תסץjWU DJ[զ~UT㟐ۿA\f|EF\u001bpJ偋r\u0004POt\u0017\u001ak\u001b#Z\b!k\u0006R\u0013]\u0003'D\u001a~\u0002vy\u0003*\u0003\u0015\b婩&.W0#gGڅ2j<4)Gh/òRY\u001c\u0001cm݆]\u001d\u001eh44\u0011O#\u0010\"\u001aYePP\\u\u000e9rWɨUy}\u001c4t\u001e'[d\"kdlUidJ%#DN\u000b*\\\u000fd\tԿ\u0002EسA,$!=\u000eP\r<wGr6.G){RhʢaY\tT\u0012\u001b%Hű*oRa^d?\u0019**vt#\t\u000eihY#ԣY\u000b~}<`1%%m&\r$=$USQ2&sET\nR\u0014^\u0019Ҽ{\u00127;IƔ|\u000ffR(\u0000\u0018\"P\u00075Pų\nl3A4lQiM\u0019\u0019\n\u000b\u0012h6\u0005xVLk+yt+^\u0015oJf%b\u00022\u0000cfF{1u簆\u0002\tGc\u0003\br_ͳʤ¶c\u0013\u0019m\u0016\u0015fF\u0002c\u001boՍƸv\u0001\fD\u0001=\u0002d\f/û,\u0019Ӯa6h&5@{?M\u0003\u0019\u0007 &\u0015\u0014\u0003\u0003|nc\u0017 }1Gxa\u000e)r\u0018\u001cem\u00003\u000eh)m\u001bx7d!\u0018s_C}Y5:%\u001bUIE4O8؇9\\\u0017\u00100}1B_2yGQ>\u001c\u0007ˀ91B4B6Lֺ\"og4\u0000t@\u000bmM@\u0003m\u0001ݍ>T𚱮\u001cib\u00108d6\u0018cL\u001el\u0013l&\u0013\u0004qc|-0'3/\u001d<~w4\\|tzFaɪ{Y\u0003נ\u00196t-#Hb\u00033ı8V\u0012jXC\u001cc1dO\u0017T\n3\u001e\u0002\u001eoce}~z.hE75L\u0001\\=5-Ch,I5$s\u0001o%{sI\u001dF\u0012Mı817v0&;X\u0019TV\u0016f\u000fH3׆A\u0000!s\u0013++z\f))\"ö[/:@\u0017ndwt/\u000bıv?~\u0016ޗ}\u0015S)\nkyR{꣯s\"!\u0006Rt{^sk^n\u0007h\nƂz8K\u000e\u001b!Lt?I!\u0012q8\u001ef\u001ce\u001dep\u001f#Tx\u0018pl\u0001CN.a\u001d0UXR|\u001ce>oH\u001e\u0002])a0K$\u0019SgX'0ٟq%=y2ղ1@ۏk#VR+{ @^y3xޔ\u001a\u0003T'Y{.o\u001a\u000f?$\u000b%\u000eKE&\u0005<{ŋsgW\u001c \u001eml}y`}\u0014ò\u0012{ސ͚:Lm`VKs%O,\u0004~\u0006cc\u0003l:W \u0016{ś4썓dŧp\u0013\u0004O/yC\b/s\f/d\"o\u0017GG\u0016,~~ͤyIK\u001cLWW\u0018\u001f^/\u0004}\u0010_%Կ,jg\u0014'ހ\fUfy\u0007w\u0015?6\u001esZ)\n:\u000e2qӺ\u0003{Es\u000e\u0017x\u0002q~\u001d&̳gcۼ8m~v|\u0011;\u001d׉8i\u0012M鑶뵵)F\u0006=Cݠ$@c\u001a\u0010\u0006\u0012L\f\tILHC\u0002C􏩈C$PP}~{<$\u0004%<t~n+k\u0015|\u0011>\u001d\rݜ73\r0(_f\u0013\u0015ѯ=\u0018MgP^ <?QR$gHGHX\u0017x<\tr\u0003/0{\r>\u0007O߰y\u000bކ!\u000f\u0010$=~7V!Rd\fc\u0017se\te:#h$>+xyK+Dgt*sB?Lm*\fу_u]S\u001e25t,\u0013v#Wȑq\u0011?>\u00152S{R\u0017\u0018#a\u0012CdC\u0004/6k*<\t3\u0017\u0017ϋJ\\;-[Cw6Н@w\u001aY4\u0017:\u000f0\u000bGt7\u000f)T\u001f 2\u0013\u0013d\t\u0003V9\u000e\u001c-hm[=c0\u0017g\u0019!\u0003\u0005X=G\u001fG\fxl\u001c'[p<Sx<\u0019\u0012:Gϟ#~)|{6\u0004o\u001c\r'h\u0019Vt\u0013aE\u0016.U\u0007\u001fF\f&1KT0\u0019{l9O.:\u001eH\u0006\u0006:7Ŏv9V \u0005]7\u0006&Dn,\u0005n_G\u0018qɐ9ߏG5,N\u0012\t2ix\u001111v1vq|Xc\u001c3g9򎳥-s]yl.G;\bQgY\u0019\u0005lQ\u0000z\rt']Có\u0007YI\u0017Ƞ\u0017o\u001bp\u000bͳU=\u001cs\u000fp\u001fQZyֲQM:,6rc\u001c\u001de4ԁ\u00026ب76f~fHՈjx2{\u0005?]>3=Ѳ\u0004ЄqQϰǦ![[\u0006-&v؉c'\u001cvة`\u001f;\u0016fL$G\u0015S\\VY<:\u0010ށ(Na <e4\b[)3,y\u001d[Tu\u001au\u0004Uj--n[^%{\u001c*8ةsI91uVu]Ru]i׋RηR\u000fu\u001e\u001b'kc\u0012\u001a0}\u001f{/eMeånW%_EOP\u0005wTr.ux*ʶԕi\u0019U;w}GwIquUE}o{z?\n6`oRc\u0007%\u0018\fA\u001f=R]\t_L:M~O9_@Y_X\u0019_\\i#WQVWZ1c\u0004)l^Q|NA\u001b#__\u0014\fKq\b{sQrr\u0001\u0003P後/EuK\u000e!ARGdT(n&\u00153;\u00145K\u0004kj\r(\u001cl*\u0014ZT0tDfhEfgᦌk2Bo\u0017z?u\n\u001b\u00077K3A)<\u0004}Pᾄ/\fZ\u0016+\u0011r*\u0016*\u00125\u0014R8\u001cW(Q0ܥ`k֭\nD\u001f=$#zZcƮ%Uyߓ;&ܒ'rW\u0017{;i\u0015`Rʵ\f\u0005|.\u0003Z\u0014\u0014\u0015z\u0014\u001a2cA\u0005bQc2e\u0012u&o\u001b;K~yNʕ g\u00199_;\\ğdO1\u0017פ5j@\u001d*P<dy6-ĭ\n%2.>\u0019|ay\u0013jiȓ*ʝʕ\u001e3ݔ=$[愬ep\u001af(H\u0014i\u001f\u000ecc\u000e{SP2\u0014(:x$!(*n?/UK/w6$gGL\u001d*)r\fF%O9s*\fr\u0000g}-ckl<K\u001c\u0017JY\u0016_Ro(\u000ffg2r.tz,\u0018\u0017LYH.\u0006E\u001d_\u0006\"SDsVY( \u00149/wo\u0000K}\u000e>\u001b@%!4\u0012\nA\u0005hߌM-]N9K-uma\u0003*$M\u0005G+],lj\u001ej@iCePPo)C\u0016Н$\u000ePnN\u0007S\b!\u00076J@e\u0015\u001c4U6\u001a\u001b]?\u001bMS'hu>[w4qu:@zJʱ\u000f{-\u0010\u0007\u0007hAz<2Lrr\u001f®Y~\u0005ΚE~\u000e\u0001\u000eA\u000e!\u000eah66\u0006@A<\u001a0\u000fǀfq&m&А\f\u0003ឦ\t]\u0003`\u000bta/)q\fĮQ<Hr\u001c2ā?B;ꐶq3\u0017\u0013dh\u0017M5I<4ɉ\u001b\u001aI\tw&\u0018VB\u0019{\u0005ƛ!\u0007\b]\u0003a6)h\u000e8w7\u000e\u00056\u0005b,\fxe\u0001\u0013sn\u001aYݙw]w4Ս\u0014*a75I{\u001aS\u001au5@Q4\u0003L\u0016)t\u0010e?~,abr\u001f\u001ba0sq\b\u000fq8S\u001d$'\u0003}jN\u001c\u0018k\u0005\u0005)\u001ceA>aE{HYaNaV\u00036\u000b3]Qg\u00186{9d7l\u001b\u0010\u0012[\rPb\u000b\u0014F\n*\u0005e(P*SS\u0007\n\u0003\u0002J\u0006/Pʥj-2 ʴ:ڱj\u0001\u000b3Hm-ɞt;oel\u0014?V\u0018~YpYKbr5\u0018\u001a\u000bc̉ջc,N\b\u000fY{&Μ&38]p~ᣴX,k:g\u0019HL6}\u0003?ѯ\u000f'\u000f\tv\f?mI[-~x;g\u0003r!\u0016q68wsΕΒm\u0007\u001c\u0003QQ]·˨#\b\u001ers[  7c?}&{vdVĻH\"8sIKi\u001b&x\u0011A;.G\u0014d#\u000e#h^e~WN0?H\u001dH3\u0004(q\u0014e3~VpN\u001dEj'[ٜ;nG<\u0018$\u0001H9X<\rWU~H<^W^ef\\\u0001.\u0012\u000b\u0004e\u000euqDI\u0015N\u001dۿ\u000e^p᳹\u001fϏU\u00156K<`\u0011,D$+\u000e5>\u0001>\u0003\u001aɿJKb&\u0016>f-\u000b|\n\u0001\u001fOl\u0013.>IQAaM2z\u0013\u000b\u0002\u0006\u0001\u0019\u001a2z\u000eQ{\u0001u΢k~8\u0005\tp\u000b޿\u001b\u0002z\u000f]u\u0005\u001dq\u0005-\u000el$.%~\u0001u9Ge\u0011m\u0002~<GHOQ0'Hq\u0006oqt\u0011x\u000f=;xyWV\u0017w3v/!^D-<8~89:ΰzA4\n)w&>~|\u000f?D~bz\":'~BiUh\n^VXe]SNڟ&\u0016hq48Z\u0007j%v؝ǉ~>\u0006^\u0006\u001en.\u0006NC)u}v\u0001!~D_v\u0015<\u0015m\u0004v\\pǝ;v\u001ed`\u0004IЈ\"v;;\u0005eZu&v;\u0017#bl/\"Vc(p<\r4z\"%kЙcp\u0002_\u0005/;muiG:ў؊\u0000\u000b@\u001eENA{;\u0015ӱ;ar\u0001\u0011XeQÛ\u0013 r\u0004\u0015W+b f8\u001c\u0018S\u001e\fa\u000e@\u001a䩾\";=\u0019}\u001ell\u000e>B~\t*YoaT1v\u0010|\u0006*\u00138=ط\u0002{Lcz\\c\u0000Q\u0010\u0007\u0019lz+۱ݍ>l\u000f`o6\u001e\f\u0013;s:>GNU\rQuCt\u001c\b~\u001b1lEоkپ\u0016\u0010\u000bT\u0002\bc\u0004\t~\u001eo~\u0017;@V\u0006d\u001e\u0015jY\u0019dg:Y\u001cG-e:5c_\t;~\u0017σaWuMC,\u0006lr2ژ\u001fT\u000f2c\u0015^y;u£\u0011\u0012)TE\u000f\fG7Y.\u0016w\u0015mkUh9WJ4\u0004f<iS&\u0016Tr2ژJG\u001ah\u0015vMnYm' dv\u0012QnKt\\iUd\u0014~E&q\t\u001f6qݏr-e/`5\u001d\u00023\fznzWn\u000fAA\u0014\u0018\u001cI8p4Q^'t\u0002UR \u001fTx\u0013'y&@#5ThG<\u0005BVa֟Y\f\u0005:l\u0012\u0005<*jUTtGꊂ\n]9x\nLf\u001a]e\\suu2U`Ү\u001dt\u0011<x\u0003\u0011}Fu\u0005\u001ca\u0018\u001fVB\u0017/\u0016|)\u0018n5|j\n\u0004\u001bjE5&(̓N}J\u001a|T\t7+T,\u0019Y˲<e{X\u0002|xgqɠ\u0003xW\u0000M|(\u001b*\u0013+\u0013\n*\u001d\f+\u0015*\u0019T\u001fH*\u0011*\u001e((\u001elW,8EVp<%\u001aL\u0018c\"ƣ¡3UZE\r5\u0017\u0006xn}\u001ed#\u0013QΣ_H@pH1#,ˈL##3ܤ(B\u000e1\u0012T82\u001f,Q7P&\u0005뾭@ݓj#U#7\u0002/7\u00044I\u000fh\u0007E̻\u001ce@ҬQ*\u0016ˊ\u0006d\u0005\u0015\u0018pE\u0014\u0014@h\u0011t)d\u00154oW\\Zn\rYߒ:(uRn\u0015pE5\r-\b|9H.\u0006\n<7\u0001%a\u0015Lf@ufPa3$Ê(d\nZ\t\u0005b\rX>y$;B5ur%X|\u0013\f\tEΊ}ṗs&o/\u0004E̻,HK}ܥx#+iժ\u000eDb\u0001\u0019񠂉jO˓˝lSMG\u0014;l\u001aqf܆i\t\u000fI|HbxSGdQ\u000fh\u0007- ϻ\u0006|Iy\"QX+3S\u0014D\u0012~\u0019\n&\ry2\u00114Xr5\r9gϢ)\u001cK{\u000ecaq+X³Yφ$/\"\\Cedj\u0017(fs\u0006I>'ݲ=&=\u0000#U0?\u001b;ӼMv\u0003ū_nF5#\\\u0011O\u0005&~\u001bmXfl\u0003ؒ!\r|\u0005|e6\u000f;A+h9/)>O\u0014\u0003&d\\25\nr73D\u000b\fV:HJ\u0014W\txmǶAlcoC\u001c%K\"K+>|pN+=`\u0012hi\u0016y׀\u001f)\u0004\u0011ޅ~F5}faX5\tZZ\"\nnUƱ3h:\u0001Z+neJ;=HYB6B\bIH@P\u0013 !\u0001\u0001Ѻ/NT;նK2x:ɇ0p=!?}\u001af^LRpφ`\u0011@\u000eVr\u0002@G\u0010 A\u0018\u0002w\"0<\u0004A!\u0000\\Ŝ\u0007ԪX\u0007<7\u00101\u000b1\r'#\u0004hGw_C0\"\f\u000b5\u0000\u0017m ṫ`\u001c\u000b\"\u0004,B\"\u0014,BPGb\u0004P\f!\u0018BpS/ \u0010\u0002t\u000f\u00153\u0016Ϟߧ\"$\u001c\u0018/0\u0018`\r\u0017%\b\u0018:BrX\u0001\u0016a`\u0011F6;XAp\u0002\u0004ٕ\u0018Vb\\r\u0012>\u0001i\u0019:_PK\f\u0002-:\u0006G/Ґ9\u0017c+.q|\u000f\u0001h\"|X\u000b~5.5uб\u0011\u0007Fl\r0a\u001e\u001a\u0012|x=u\u0018\u001e04.zE4)\u0010x\tC$Hl-\u001c\u0014\ry\u0013ױ;'jn\u0017\r\u0015i\\\rW8tl\u0006-б\u001dk\u0003\u0007\u000e؎n\u000fA\u000bpNlEMlaY\u00136{ר`\nY;\u0005y\u001480\u001d\u0012_w97\u001b=Ecg\u001b@Ҁ\u0002=\u0011\t\u001dб\u0017\u0017\u0005\u0015\u0007\u0001\u0003QR$Ή\b\f{P\u00131j`\t<z\t\u0000aXB5n&s;\u001fJ\u001cM\u0001BD\u001bq\u001c~A\u0003v\u0014{%\u0016\u0011|\u0017{\u001c,wQ\u0011G\f\\:hEx5\u001e\u0003~<t;Vw]|()\f\u001241#<=J DQgP\u001c\u00106X\u0013\u001e@s\u0000\u0005#LtЧG?\u0012zj\u000ee*\u001a{\u0010\u0011;\r~\u001fv؝;O{(8C#\u001c\u0018\\\n\u0019\u0018\u0012Fس٨\r)S\u0002\"\u0018̌t\bNTf`#H\u0011800\u0011;Iw>\u000eB΃Vݕ\fYk`Õ(,7U\n\u001eU+\u0015'F\u0014|\u0019`\u001e\t\n ^EMB@n/+iQ'\u0019B/ paT/D;\u001aC\u0014!XB\"0cr>Q\u001b8\u001c8/l0݊\u0002M?xy\u000f~n0\u001a7|cǎ0q)SMs\u0006\u0004\u0006\u000f^(d^^2l/WYn_zWl۾ܵ{\"ވ־o\u001f|#G\u001b?\u0007>3L6\u0013ğ=w>1)B\u0019Y\"D-U5ڂ¢\u0012CiTSźƦffpvv]|nܼu}ŗ_o\u001f~O\u0006\u001aD\u001c\u000f%}y\u00041<\\'_ gK<b}\u0001\u0012ˉ_+\u0006\u0000\b'\u0004\u0012\u0004\u0001\tHBM`8@8\u0010\u0010A\u0004Aq\u0012,>\"0X\u0006\u001f8\u0012\bd\u0002$\rD\u00040Q\u0000P\u0001p)#`@L\u00136-F8\bn#mO\u0003@zH(=&c̾\u0005dݽ\u0007z\u0018~x\fF\u0013Eyy\r\u001a=\u0018\f\f%\u0014\u000b\u0012G\u0018\t\u0018\u0000X\u0000'\u0002$`\u0002(\u0002,K?\u0018W-=C\u001f\fo\"[\t;=\u0011Qo;p0ȱ\u00134Ï?!\u0014Idr\u0005\u000b-bXwAWM\u0017\u00051\t\t0\nz\u000e޻\u000f}\u000e_>x\u0015\u000fo\u001f=z;xɓO\u0018kMuDT__ba~Cٖ\u0012sJ:C\u001eR\u000bZ\tG#e&\\WfHKi\fh\u00180a@À\u0001\r\u0003\u001a\u00064\u0003\rw|kfdKeUh_ݯAųs\u000294HASe\t*g)AxӀ\tn_ToO*HSoTb.W]ޠZA\u0007\rР\u0006%4(ײ3\u0013n膆>nE$YL!`*_mԝ/QsР\u0006\r4y\u0015\"\u0015ySIfuaƹ\u001b\u0006gc,i0,5\u0001pCu~S9Ѡriȇ\u0006۝+]xWY\"Z:ӸdM3^Dv\u0011\r9\u00187V\u0015\u001f0N6\u0014CC\u00014N۝#>1tdBG*@C'ie$5hͥ\u0015o\u0018t\u001aРUrS!\\ʖrz$\u0012N\u0010:Ҡ#\u0005{脆\u000eƒn\u0007#Hi\tКʷ\u0019\u0007kJ\u001a\nA˱)sNy6K\"cwgI=q\u0001:\u0012E+6\u000b\u001a\bZg\nUo-/\u001f4\u0017C\u000e\u001aTРa;rV(Օ\u0001\u001dБu9'_4\u001cq\u000eb\u0011f՚\u000b*ʶ\u001b̅ڸ|5ǢT۳\u0015,8Ȅ#Eƾt^鎗{<6X\u0011jwУ-VZzQQYkF}QLV\u001bנ<VDɲ\t\u0015̎\u001c#Er&ٝg9]|\u0019ak۝%m\u000e[\r-\fjtgpZ\u0017נ԰e*5+ٖd2\nVG\u0010p\u001c\\9iϷ9[\u001c\u00032CeXְRUt6 Ne54̖t5Ӓb&I.ps6v.iXmq-NzX\u001eS^\u0019\u0018JYV\u0018wQcgh\u0017Y͉\u001aVKm\u0011 x*2\u001eG6A?^TRaX*+\u0014\u0017\u001f5j\u0005$\u001d!An\u0014h9|N\u0013'h\u0004\u001eG]ǰ.چr'=Uti.4'$\u0011l'Nb;ni\bP\u0000\rq[\f\u0003RN\f\u0004RJK9\u0000IӬ\u0010\"Oli{%Z6[mْ\u0017yKҙqL\u00128=\\8F\\\u0019\u001fwߐLTe$\u001e(!aS\u000bIc.4\f3l'u߻x=ن7ӚVTRLz\"\b_E>\bϋI\u000fh4X\u0012$&}49߻w\u0013?cW{YE˫}\u001f?\u001dQ\r\n˱lp\b\u0007WDL|rV\\`Ɖ\u001cм\u001dVmӰi4l\u001a6\r\u000fm\u001b{Pǆg0|ǐ0aV]\u0004ց灡F!ʺ[Kn۹l\u001b{\u0014\u0018`\u0015?\u0002)`\u000fo\u0018h@\u0016\u0012lǧ\"sf\u001d\\޼\u0010-RtɌ)\u0016Nm-në=\n5e'#1=0htH\u0015h#EAg\u001d\"F\tVhIbm\u00180;;6\f\u0002\u000f7`2>A\r:S\u001cvI\u0019\u0004Q\u0003ĢU]1W\fB%\rOXoL[n`\t`\u0003\u0006Q/c\u0002\u0006×\u0001\u0004hޫF'Jcs\u0014_\u000e+!\u0015DtU3(\u0010˗\u0016vjYy\u0001`x\u0017\u0018N\u0000\u0003+\u001e1\u001e-x[V\u001dJf\u0003\fAƻ\u001eC)\u001b,ȗfjkۭTkë\u001fK\u001d/ck$f\u0018L\u0016<zҢ3\u001aAAh%{E\"\u0013_(v}ÐnѡՑǀE{vX|!\u001e3\u00013Z\u0018Ѳ]X4A-jؒB/KC,_\u0012)%o2-o1\u000f\u0001ã\u0005{z\u001b\u0018c\u0011[O\u000fvˈNـ\b6VԔ*tAD@])Kz3c7\u001f\u001eZf\u0015\u001c۳{\u0019p~.\u001eqte<`7\"e\u001eUi9\u0006\r\u0005!8\u0013\\$Uijݱf\u0007V\u0013X\u0005ׯY!\u000fC}\u0014Oł\u001b)\t)\u001b\fZ\u000fU:hF\u001ax\u000fT\u00135Lͭ\\϶|Up?G\\\u0007=)\u0007D93}\u0005[WaP\u001fX\u0004:xEfq-6jɺ[5|=홯G޺ng\u0015T~N\u0004\u0003ɤѝڐ\u001el]=!5\u0003F\u0010Xx\u0006B\nǪhC˵};޼ka\u0015\u0003OF#\u0011\u0017}\u0001\u001a\u001bTYإA\u000b{\\\u0004,|\u001341e\u001c\u0013\u0014W؈XÎRϾ*m;BRq\u000b\u0013}Z鳌ٝ9bIl\u0006\u0015\u0004VȵB%\u00020\u000b2qȌO[uaDӵ7&(-k~\u0011\u0003iRNPF\n\u001cvhT@Ac<\nʓ6;B?\u0003[\"ۊTa[ddcW(i\t\u001d\fi}\u001fEUq%ݝ p\bPs\u001dvd\u0014c\bA\u0014>G\u0011z(6lj;^i<)7m}\u0016Uɰw>&t%4\u0014aS\u001c\u0017&H\u0006s\u0019ĉe!\u0007e;l[԰0ݸ/Wi<kQ\r%ߤ\u0006C\u001f\u0007\u0007X\u0017\u000b<pC#IF\u0019̍2\u001bc`7bTL8uxp{lh=W-\rrɓ\u0014w\u0002͉\u0010;\u00040\u0014@\"l?:ǢH\u0018./\u0003#3\u000f>oƮOW}/\u001d\u0011>{cI_ᜲks,p!m,g9@O\u0019v.Rg\u0018u6A$Ⱥ[\u000f5\u001eX=ښWǖͯs\u000flw\u0013rl$&\u0013\u0001\"\u0015\u0011\u0010;\u001a$\u0000&,aq\u001eJ'=ʲ[_vw\u0019MæaӰi7X?ښc˖\u00059_\f0tJddD'%x:,&rA>'>\\0EE\u001eh`NӽGWpkz^`x \u0006\u0005+\u0012W\u0002c\"R,\u0013\u001a\u0002Bq&<$Lci7_uA\u0019\u0017[=kV};\u0006Ǘ/\t\u0019\u0003b$fǢ*\t˱\\PW@i.wE\bfx΁Hmj\bi\u0006HW#-]\u001d\u000e`\u00050(̩\f\f\u0002IHL\u0017\u001f`\u0002\u001d\rHw\u0010EĴϙqrxsvB@E\u0013\u0010͌\u0006:yn8~\u000b^\u0003I3\u0010mfځ6M\u0002mҔK\u0019\fI\u0019J\fqCwI֣yGﻭѾobKl˖%[^ p(t4uU}\\?ɩ\u0007\u000ek3\u001a\u000eXb?<1{B1\r)\u001e\u0012ʠ)\u0018u\ne;\u0017\u00185+jK״4Œ^S5x{\u001cz\u001e~q_=a8\u0019\f\u001fie/\u000eŴxX\u0007j(Q@Ө\u0014ʨV\u0018f\u000e\u000b=[rSPԤtuEhx{\u001c~\f{\u000f/ͩ0/\u001e!=k[\u00058P&\u0017\u0012ڪY V\t$7\u001cyMRULM\u0019og\bn\u0018\u000e`##4n%ubD@tPf\u001d*haTIȚ^ʸ,oe>OUq\u000bx\f-\"8g\u0013\u001a3h.Pԗ\b\bMЬ]\u000bU,*WPW2M~K(\u0012d+\\\u0011+x{\u0018\u0010ڍ\u0019^o_\u001e=\u0019Ni\u0005o\u0011Yz\u0012!pg'ئb\u0006\nZ(e\u0002^\u0015ik\u001c\u0019{dEDUۆa}B{_k_ӜB3sޔJ(6y<d#d؞\u0019I\u000b.h5`U\u0002JUPW\n\n]_ft\u0007--\u000f}\u0014\f\u001fl?mhtƛ]\bk1m(@SV#8SZʂDC\"\u000b\tBj]*QTv?r?mc\u001f\u001coG#'=c3#\rF-DQ\u001bL\u000f\u000bu@Y\u0018\u001aBPQ\u00054\n\u0015-^uֽ/\u001f[\u000f|<\u001f7Ƒsp%\u0003'\u0003\u001eZf#,՚D\u0011\u0019ɳ\\S\u0010\u001d8\u000f2C:vDo\u0012s/{롽Kmx8dGR\u0016\u001b!k\u0018LBE\t\u001b)3T}@\u0002\u0006Zd`\u0006\u0016&7+ܞ}\u0013}}}TUK8=\u001b1%\rvBFc\u0003rQpX\u0002\u0002L\"\u0016\u0014l\u0006\u0019*\"D&\u0018[K76ٲm~~y5L\u001eu\u0004?\u0019=Z\t8\u0003\u0019\r0\u000bk\u0014\u0018cwy\bbd+@\"\u0005LCӝ]\u001bg^)5Ah\u0010]@\u0014Q28\u0014\u0001\u001d4N`\u0016Y\u0006e)68GQs$\u001b#⯜mh\\ltrB3lHaO\u0005$+aFT&\u0004.JRL,\tN(\u0005;1\tQ\u001c1\u001ev iҷ4ްin|b-dY\u0012~FN좃\u001da\u0007\u001c/\u0010a\u0018\u0005i.(\u0001\u0004I\nJM\u0002(-9\"I\u0012JO\u0011E|3٦J/\u001ci=#\u0018)}ȧ\u0016l\u000e\u001e1S\u0012\u0003#8N\b\u0019\u001d\u00000\u000fC\u0010\rQ=A\u0004DR.Z;[Oj;r\r`aR4B\u0019\u0014NuK\u000b}Ae\u0004A9N\\ˑ(,$\u000bfh\u0019\u0004w&}\u0007G\u001d'\u0018\u000f\u0006E\u0013_yعr\u0015Xꂯ,@.W\u0018\u0017\u0017\u0017Da\u0001ι99*l\t-qWG_hw퇎-?k׽ҏD.gF0\u001d\u0013Q\u0002I\u0011\u0012\u0018Y0\u000eL,\u0006I\\(\u001b\u000f\f)'ڼ[pjxڅ\u0019\u000ebmwu\u001fVe9A\u0017\u0011{@RB\u000b\u0005H,ʡ'LX\u0004!n.\u0000\b&⼏(+Aݤ{4\u00180\u0017Twm\u0018^Qw\u001c8RvW~_UvJ\u0015v\u001eoJB\n&dp$&#|$\u0015b32A:39\u0013>\n%<$iCPMAcqd<k[cݍ\u0019G\fۤYѧۗ\u0011\t9\u0014J6\u0016\"Y?1ᣱ&=\u0010\u00063.tET\u0004]J0L\u001b\t)<\u001bup}\u000b\u001b\u0006'/%\u001f\f\u0015hT\u000e'bj&HCg\u00160g\u0016\bdsX]sFaFG2MP`\u0006\u00143\u001enc8޿ ?)J._J\u001fȱ\u0012Np/\\ڔIAi9\u0007_S\u0011b$kdlSݳax\u00193`<_V夗]i5_Jov+À\r5\u001c\u0014R\b!ڃBҦn\u0012\u0002u\\\u0018#.@\u00103\u0010\u00133lp1%YKִ_[\u0016l6$4\u000b_1}Eo}O(E\u0014\b\u001a\"9_72NƘɞx%+,C\u001aT\u0015堶 \u0005#y{hX`{a4'ĝ7PeK(\"*$\u0015}\u001ex-B\nN\u001ehJ\u0016&.F%9*J`mA\fG*Z\u0006]\u0006i;8EU͡\u0014\u000fkt@\t{dKم)\u000b9k~aə\u001e(k\u000bB~gxl؂kN(?d'ii/i\nŴxX\u000bjxW\u0001:epC1u3D\u001br~ϜK6-(',e\u001eS$̻챡lo~lP\u0019u\u0017՝\u000fxXOu`\u001a.8YNJ\u0018db\u0017=\u00125P:)'4c\u001c]\u001e\u0019|kˆ\u001f\u001b\bE+؋\u001a1SK<l}FdХ\u000b\u00165<S 3r\u0019rETvp%9T:VL\u00051\u0016O;ZI5x\u0006Ǜ;ƭ=iNse<T0nkĴ\f\u000ftPJ%4%V@3\\\u0019\nKƾw0)Fz.\u0016*\t-ה\r\u001bk0&\u001dĢ]i\u0003g|78O섌\u0004\u000fШF\u000bK@\u0005Nq\u00144]\u0015iD%D\u0014qX-Tc굘wC\u0006w\t\u000eIq#\u0004\u000exqA\u0001+@[\u000bq5@&\u0011\u0015}\u0012T'j\u0004U\u0003jM05o}\rz\rw\u001bҤ\u0001\u000e[\u001d{4p vKX\u0002\u000eL@\u000bQ\u000eLBc\u0006\u0019j\u0014M8Y+\u001e#UJ\u0002Vak0\u001a\u001awVC*yCMhmgpjL\u001a줌\n,\u0001:5\u0002#,\u0003\u0019QPv\u0019?v\u0012\r=JKЊ5X5Uܟzx?\u00137c\u001eM\tRځJ[~\u0019\u0018`A\u0004\r&dH\u001f&\u001bY#$c0$\u0007U\u000f\"W;[e7u\u0017\u0016C+fspO뭍(\u0017rW;*q\u0000)\u001dtـ,\u0006V\u000f\u0005\u0007\u0016\u0000\u0019 X\u0015\u001fދ-]u?z˃z͑eu}4[u*/ օ%1=\u0002<'r\u001c`4;p\u0006#Y\u0018v\u001b;GuV\\bKV\u001d}~\u0019]t;\u0004QoV9EAb!@\r&X.(I/`\u0014r\"(डT'=Eq2Rd\u0007+Erp*Vͻ[}n*L/|'t{q\u000b\u001d݅-*\u000eZkb>\"mnf\u0005:p\u0000\b~0HA\u000e\u001f\\^0K\u000b\bÌ\u0010<h%\u0018\\|l|5Zس5\u00102\u0013\u001f\u0013\u0001CRj=wIM̶i\u00195M6(Ƌ(Ԍ\u0002\u000bIҔ-&h8VIlG\u0017,M\u0016%;%_<3m\u0017ɟ!\u001c\u0005J-\u0006΅&nc~\u0014/l\u0013E#\u0014aj!Prj\b\rd\f0+joU7\u0016*Öo6\u001c|$?6:x\u0016_\u0019󔺫K`L\u001b|b\u001c>*QJ \u001482Eg\u001e`*)=P\u00033\u0015؏6r[h/w`}o羣=\\[\u001fu᣻\u001anj:|Ͷ\u0007oZp7ȗ\u000e|ImK\u0010u\u0004:m\u0017lB%a50\u0015as5ޱ\u000fwDGI\u0006^{Ivx\\/\u000e$ٝ\u0004\u001bh\f\u0010c\u001dD,IFIdB#mZ47\"TՁ>m\u00193\u0019V?1Yi\u001e\u001aޯ-:B\u0016}Ky/e\u0005\u001cN(\u0011^,\u0006\nюd,A#$9Z6mt\u0018oJZmio=a\u0015qS5ݾ|OӂSa\u0005cO\u0005\u000f\u00150.v8hx\u0014'#TQ*LIHLʆt ޜY\u0017ޖ~0˪a\nаm=ć!A)# xB\u001f\u00151B\t\u001e3\u0012QFg2\u0002R!@\tR`,\u0017 \u0002\u0004}\u0017owYr6[iì+auc71'R\t9#lD\u0014\u0016\u000f\u001e}qNܱqZӝNUzuuk@zWEAAP I\\\u0005Bx $F$@Bȅp\u0011AEV\u0016Ժ9;m-ʶ?\u001e\u0001*\b9M\u000e8bɢv:jh\"(V\u001bV@ߠTe\bi4\u0012EJt\u0001Lp\u0007avwk}n\u000e䅜4~\u0014\u00111+=n*(N\u001dU\n<\u001aL\u0006;s\u0006YIN\u0010iBx\u00026\u0015\n_sZfFG\u0006ܰ\u001dZ)HB\u0014':\b!\u0014\u0018TU\u0003r_JD\u0006o\u0019t\u001f$\r\u0019\u0007H\u0013\\$\\\u0006V\u0015Q\"F\u001ba]|VaG\f^\u0003j\u001c2#(Q6\"*\u0012r*&!i\"$]0\fk\fA]0ݺ4!>DZр/rz[IV-9\u0005~\u001b\u0015`qL45\u0003z]ECmdULDD\u0014](Հ\u0005OICVt^DA$\"C\u0003\u000bV[+{$SL\u000f:Q\u000b1hG\t5M|CF^kʇZx3U\u0013AP\u0001\u001bi/\r\r\u0019n҄d\u001f\u0012i=\u0006ۊ~i+zd%C6\u0011\u001c@\u0006>k\\OX[\"d>Еq\u0001]\u0013iB6gx;iذ\u0001%\r\ngd9\t\u001e$*M\u001eM//ux\u0015U\u001ea\u0004kf\u0002R2ȕ\\o`*\u0007X(\u000b\u001a0,O\u0003ƤAq\u0013\u0019.<1*;\u000bO[T\u000e{j8lQ\f.\u00173&B\u0002a:A8/\u001b\u0014\t\u000eW=hS\r\u0018g\u00004IC΢\u0019\u0017\u001b/\u0004\u0003}ڐ:\u000f=k\u0019J]*\u001d\r*8l]\u0013Kh\u0013-nH6j\u001a\t&_\u0015ciS\r\u00183Ҁir`xaؚDy]\u000eMݧ\r1M&o\nZr-s.j)kjTA\u001c\u001aAd\u0018G\u0002O۸7`p\u001cHG\u0016\u0010ܤ\u0002M$Հ!\u0003\u0018o\u0000?f*w\u0014m2~\\?h2b۩\u000fz2l\u0005nʯK @1'\u001d\u001eTY\u0018Y0FG)2\u0010U\u0019h\u0001Ӳ4`^\u00012nK֬f{}Vm&pҁ-Zw\u0001Zܥ5UUz(ԦMjJ\u0012\f\u0005m\u00183Gr\bA\f\u0013\u0004A\u0013%h\u00014\f`Z\tЭ\u000fl\u001fVy1>g<X.t+L52\u0003\u0014hA)\u0006-\u0014h\u0001\u0016\u0018D\u0015{\u0010\u000fb8V#aUh%i2\u0003\u00044!_]+.\u0018\u001exkqn-1c|Fȏ\u0018`\u001d\nju~X\u000bG(ZF\u001dix\u0003X Z\u0015Eu\u0003i2`y/\u0013\u00187eZ{~dUbk\"UWYse]-\u001d\u001e\u00195 ?H\r0\r M\u000f((#DDYa<\tc0\u0006EP\u0001ۯ\u0003ez`]Q`%y$4)l\t\u000eVnb\u0004\u001d:36z\u0019&O3\u0014#dd\u0011\f\u0000\u000b`\f\r\u001acs_\u0001Ǣ|)p^g՟oM,w9ԛ$Ib\u0000\ti{e:'ɳ\u001c+e;`/L\u001f\u0011l\u001fŚ{1f/\u001ew.{ɒ}x}c뻬2\ndw\u001a6M\u0012f_=8=M4<d3\rYpn\u0015\tj\\\f[ebۯ8\n'?nulֻh?Do.̴.V{\u0019df]%{j\u001b\t\u001eâ'\u000f^@\b-Uquj\u0018'\f\u0011/\u0007\u0000\u0014).ѕ}LU:S7}k#pr\u0012djz^.\"*\b`Nn\u0015R+n0.J*\u0017UqG1\u0011|]\b0?Lm8;\u00047I0\u0005y\tNc\rϋEƫ+\u0017}\fV~\u0001\u001bR}sߟXr+\u0005ߖVS9+;S_c\t''\"OQȹic\f$jѾWCj-\u0004Kr[\u001dx#\u001a=Pác\u001c?8lޣ\u000fK±\u0007%G\u001fT]<=CH\u0007A\u0007eVT+^\u0013˹`;Tv=\u001el\\\u0005>~\t|y\u0011؟\u0007~uG<w\u000f\u001dxzيSgM\u0007\u0000'9tL&)A@\nmBS )`B\u0002\u0001mh!1\u0016RcӒeYu߷dIֹz%!v]iu \u0019\u0003pd0!L̐$̯ۚ>? \u000fӷm\u001cH\u001cozޯ\u0005'|%:WS\r8#^\u001887Ѐ\u001b`SӏT\u0018\u000f]\u0003\u0015=\u001br{L&\u0012u\u0014\u0012~C*gN{i\u0018%8\fdp?3 \u0014\u000fx\u0006\u000f\u001f\f\u0019\\ah\u0015e\u001deh\f\u0007jOy`~RM\u0015\u0002OU!KrUh\u0005>\u0017Du38ǉ,\u000fJ\u00190\u0011pz\u0004T\u001b~\u0018ޡ\u0001{&`jm\u001dյk˦t˸(\u0007\"R(HɼX&\u0004QoAq\u001dq\u001c˓2\u0003,\u001dah6EeX=\u00017eN\u0019ަ\f;6\u00013e0uOɧ4]jn\u0016H\"QRĀv\u0014\u0017\u001a\u001cߌ帶la,/1 \u001cG\u0014#\u0019\u001ca\u0004\u0019ܔ>ehi3~1k<ʞ1tȧiPQ\u001f'5D^L\u0013RM\u0006\u0017l)l8q\u0012(˛G\u0019|\f0#x\u0015\u0013eX\u0000+)z\u001a\u0018\f9Ys\u001b{xJ1?o\u0018\u001f'ud^H2\u0015\u0013k<k>q\u00162,\u001f9ʄq00|\u0015\u0003hah\u001de>o\u001c옵\u001efϘ+&\u001f;jpQǋ\u0017$\n%\u001dh>鵐if\u0005qfb5\\\u0011É\u0006ߊys&``1k\u0003{ڦ4vTᢁ\u001d/\u0018AɩYL\"2B\u001d5=+\tv:̂*\u0010;\\q`r\u0007!=\\=\u0001\r\u0017\u0001ycʚq\u001cOZO:ᢉ\u0011/),du\u001cP\u0014bM97Fz\\W\u0011j\u0013z{Be7\u0017&\u0007H΋\t(\run̬uyP>8Z?\u000e\u0017]'[E(fjY1)QU\u0002\u0018oh\"^\u001b\u0005jN^l^$oGs4o-\u0002Ҁ28>u9Ƚyhlu^sKO\u0005\u00073;\u0004(j\u0015zIyD.\u001f\b\rAs\\\u00035K\u001fT1E\u0000\u001b\u0004\u00117\u0000\u0006w>u>\u00013\u001emu\f*].NQ!i\u0011WcZDX\u0014\r޲\b=7B^\bUtpQ+\u001a.hD\u00112\u0004-\u0002hM\u0019;[l'Apd:d;\u001c,{OH\u0004gpj]<5jT:hC\u0013jJ\n]QI%d@\r[\u001a[ߎA;.}\u000e\u0010߆w[|p\u001bRB\\G;\u0018\u0007A-٤\u0016\u001d}SKUT\u0011*K0)!D=\u0000e\bR\u0006oh`2xo.cxk{wt\u0013#;]ds=\u0002c?b\u0011v>\b\tk6`B\u0014\u0012:E\u000eM{M\u000fDZ\"VE\nӼgw\u001bo2oM{\rireӇ\u001fŢ#3PS\u0018\n\t\u0018}\u0012fj;8wym>3tE`\buÅz\u0002A\u0000Q\u001a\u001aln\u0000wG6\u001e{x\u0017ϫkE7]HH ~\u0001\u001b\u00045_8ɯs뜀g\u0013q\u0007+<kkz\u0002\u0012ʰ2I\u0003ކ\u0006\u0010ڰ\u0017\rꚮO'6ǈ!D\u0015D\u001dQ.aB\u00042, Q\u00171&d1B*\u000fUPz\u0002\u0016/\u0016i\u0001D~?>>~?>].Lm\u0006`=a\u001dcܜ>\"ˑ~R\bJai\u0013VUXaS\u0001\u000f/%(\\bxa@\u000b@Յ e n\u0003H\\tzK?Y)ƶX\u0007\u000b\u0007f#fHvuq\u001eҨ\u0010Fą^DJ\f+a]XH:$\u0010?y\u0011\u001e.\u0013\bd\u0001_Y\b«\u001bѶ</\u001f\"|gvtȣLeU'\u0004\u0010돉sF\u0015\u0004;3\u0006\u0011\u0012\u000b\u0018\u0013\u0004\u0002@^~\u0011\f\\\u0006R|Q{i\u0007K|\r;ywpQ~\u0017zD74 (/\u001f\tvj HRtwB;ڕ0^LG;t=\u0017@\u0017A\u0013rɊəūK\u001a~\u00065\u0001\u001c\u001d\u001dl;ζЙtwfevuV@\u0005D@\u000e\u00019\\\"\u0004\u0002\bIH\"$!\t\"\tI\b\u0010\u0012r\u001b\b\u001b\u0004Tģ]ԭ.㮀:}\u001b^E_|^<<~$go\u001aX7XMsSR8JI\u001aj\b\u0001\u0016'C=\u0003\f\u0003r[k1^\t\u0017}bcO7_my~{`aaGO?d8V9Г×;-%Pȷr\u0018\u001b\u001c|%jMk\fV\"H+&Im\u0013Tyxd,\u001ec\u0017T\n1*S\u0017]\u001bS\u0002wB?6o?\u0006>Oo~~ZJ^]r\u0011\u0019rj[E\u001cۛ\u0004\u0016b.A\\Ԓwͽ\u000bxYbN\u001d8ww`{-\u000fCp\b\u001cl\u0006InF'LǬ/F>-/\u0001,zTB^\u001a\u001d\u001aO\u001c>{.\u0001V~\u00131\u001evtnYHI׽{B\u0002c{C:\f\u0002\u0007>gώP:\u0010}\u0006$%_z^US~nˢ\u0017e\u0015\u0019Ϫq%kҔ\u001fIe?R˒6^L|,Oxri'\f\tޥ^y/\u0014\u0002\t>9\u0000\u000e}\u0003Ǿ\u0002+\u0005\b\u0012\u000322AnB:@$dP\u0006\u001aɈğ?Ǐ۠d~u9;\u00153'ܝd\u001b}/Ds;d\u0017\u0004~\u0001>O\u0006\u0007\u000f`?T.\u0006\u0011\u0017@WY4v,\u0019dG$xPt2\u000e\\\u000511\u0000\u0015\u001b\rЧO\u0002|\t@<\u0013\u0005(1>\u00020\u0013\u0003nN\u0002\\x?\b?\u0007G\u0000\u0017\u0011\t\u0011)e\u0005\u0018UMuƥ\u0006\u00066\u0003-\u0010\u0004k8b\u000e#S͢\u0015\u001av\u001a횮馐J~Ү*\u0007\u0001`wo\u001f2`\u0003i(`!\u0002\u001b8\u0005)\u001b\u0012:\u0011\u0013W@K\u0016\u001bD|Ъj){g\u00023W\u001bzǫqdq\f1>\u0018,\rA\u0004\u001b\u0011\u0005y\u001b-\"8\u000fYhf\u0012NS\u0006%o_%B)X7o\u0019Ƕ;L\u001ay\u0004eT;-\u001a\u0003\r\u001e\u0010\u0005DA\f\u001b \r\r\u001ep[ZT\tͷ4z\u0013S>KkL7\bt\u0013Da 3fY`l^{j\u001f{~8\u000b&x@\b\u001b\f\u0000?=\n\bR7\u0004\u0017\nEUne2\u0007^dQDLr9I[M#D%@P؆~?VN\u001d\u000e8\u000bo\u0007\r@A\u0002\u001b$o\r@\u001a\u0005\r(pM@/6,qkً\u001cxդfu㍼\u0011*d\t%vk\\Cn\u0010\\\u0018ӂ9X\u0007g\u000f\u0016h\r?\u0002)l\u0010ń\u0003(9\nR7Dk\u0017PPq\u0012Kf9T$Y?\u0005.\u000b\u0014c(w\r5A3x\u001c\u0018ی{6\u001egsv` ;\u001fl\u0014lH\u0011klԪa\t*,ђY.I38aO\u0015\u0006r\u0000791f\u0019k\u001ap\u0016\u000eoui6\b\u0016\u0010\u0006ٶ0 \u000e\u0007( KJlK-Xo;_*%/K8\u000bP*cK3\\iaY<\u0010\rr\u000f|^|ǐ\u001bk\u001c2L=>_\u0017U\u0004SI;\u0005İ\r6m\u001bN\u0003H OHT$\u0015+U=Td\u0010웒rl+Z3! \u001b\u00186?9(zI!73`\u0019\u0002zѯ\u001bP\u0013^e-'ڜ2\u0011\u0006a@\u0002\u001bd#LҖ*1:\u0019HFמӼ(/\u0012J\t\u0011pEHy,\u001bpWt:;7\r\u0011^)\u0016m.\u0011\b\u00163ȷ\r'\u0004\b=Zs&6qg\n6q[\u000fͷOG$$_py\u001c\"!hgT6! !\u0006E\rf_+\u0011Rl.\u0001\b[bu\u0018\u0006ũ@\u001336.\u0007}\"~'>]W6\u001cSL\n\r1\u0003f񌒢\u0013Su\u0013\u0010<*\u0002qOh\u0016\u000ffuqi6gAm8%h?w=\u0000Oe4Ĕ=1a$P[k\u0012匭sH_g7)hv!oFVϷ0&9\u00116g\u0006tdul`5(\r_\u0001YT8PG\u001e\u0003]\u0010s߉5{4;~elH&{aL0Ejm\u0016<,P2|s\u001fszl e1-\u001e\u0006\n\u0016?N٭\u0013<T3TTNؔfWZi[y噡rx ((\bxJ !x$)ef55M>s\u0003׏oP\u0018ʝ~\u0006\u0011w8\tJ\u0007W\u001d14Gu'C0\u0010VЮ#ԫ\u0013%JFWV]\u0000R-fE`%la\u0017*2\n\u001d&\r7Ym((C\fU5XB~dg\u0007r[7h~\u000b}\u0014hč87w*A?\u000e:Lڞ\u001264\u0006^or]҆\u001eXѝ&jL/RiYvCA\u001f\u0006)T\u0004u6Ae}\n{4\u00188=?pk\u0012bPVg(3\u0002]BGiK{hnzicgXeT\u001aCP\tT!\u0006١} փN\u001ft[\u001a>59w#;vމ)/\u001d\b)+F\f\u0005$ev+Ӥ(󻒔.R\u0015PtSj\u0015]Τ\neGrJc(D\f5f&P}\u0014j-~&sw\u001dl\u001d&n.Yh)\u001cYQtв\u001eE~\u0007Nkbr[iWr\u0016a;=VCjRic.TڄjP E\f&P)4\u00036_.K{OkV\u000eW<>D:Ewa>r\u0015:lHd(\u0013qm6\u0015r[uKT[\u0015|ks+AutpP\u0018.0\u0001Vhaf'\r,լR:\u0010!]: sep1\"@L)FK%t\u0015ەY\u001fݑ@\u0010\t29\u001c!kZ\u001b\u0006\u0003\u0019b\u0018.zۖ7\u000f.nޭY[\"B>ߝ1cEGC\t\u0001z)?\"\u0006WWc{\u00055\u0011:\fDUՄ/\u001a\njDA?iW7l\u001cZ7ʷ\u0014;[\u0010%NJ\u000fd&Dr'IY\\hR\u000160r-ʺ\u00106W\u001c\u0017C`}UI$P,1\u0014oDAÖ/V:\u001b\u000feņ-`,\u0003oY/ݱ)|!\t1\u000fiTܽشD\u0014ιt^\u001473h\u001d0!-\u001b/\u001d]6\u0018(֣5~c#턉ӗR05\u0017nl:C\u0011Ly!\fa1Q_sOq!)%\u001a5\u0011#03g!0̃T2^6\u001b:ע4C_\u0018XW\tL\u001f:\rip=\u000e<U_\u000fA\u0001ޝ\u000f\u000e\u001d\u001b\u001a[TX+jJrK&\u0016x?<pjxrY\u001c\nF֠uF51xn]!L03cy\u00128Z\u0011,v\u000e\u0003cAp\u001fB\u0003\u001e^Gu\u001abϜ\u0004>\u0018'>\u001fsCa@Ci4kP\rz#T=\u0000\u001bsaTؽ\u0002;`\u0007\u0003f\u0007\u001eVg\u0006\r\u0001 ;`\u001c\u0000x\u001cN@vvG!\tR\\\u001d!\u0003p\u0003\u001d\u0014\u0019JCPy8Otغ.\u0006̾߄?m?\u0003.N8Bp\u0013D\u001ct\u0000=~8+[Z\u001f\u0006!\u001bH\u0006\u0015\u000f\u0002\u0002[C\u0001k#`X\u000b\u0019\u0005\u00190- -\t\"<A\n|GF1<SJ^R0!Y@*'Ve\u0013.a\u0015\u0005\u0011\nf»\u00043a\u0005C\u001f\u00066b@\f\u001cF\fL\u000erp\u000f`E\u0005eR+)1h\u001c\"0Alq<T;K?C\u0017L\u0014ES\u0016TZ8\u0015q]4\u00151(\u001a\u0012\rn\too>\u0017dl2\u0002.b\"\f>c\t@gaЫ\\BXK&=ה%\u001a?}*_Ŗ͐iŢIbh\u0012X<\" JFA0(&~> \u0006C\f\u001ce\t\u0001\u000fCfpc/شLVbJ\u0016\u0001-?k.A7\u0013_\"\u0014NDˊǣ%cƒ1;;AͲ^bYgT\u00182\u0011C\u0016b!,OK=\fyЫ7D\u0013vZC&3O&\u0015\u0015L%H\u0013q\u00151\u000e|4JYqZy-\u0013>i':OJ|C>\u000b1d#LĐ\u00043\bѫorٔT\u0002ÛcM'\u0017\u0016M$cؚ\u0011r]0IU=\u001cuf# ȮZT!΢<0ZOsjӞqkuQ\u000fj-\"e\u0011\u0001A`\b\t\u0004@XB\u0002$d%!@V\bI %$lj@AA\u0006\u000bV\u001dG;ߙuzݼ</W-D\r4P\u000b\u0006Ƒ-\u000b\u0013a\u001fXkSҞdh\u0015[djZ\r\"Ox \u001aɤ+\u00073\r-\u0003:\u0014\u0015]VlW1UV[\u0005TP\u001aQ\u0003-h%B\u00007<\u0000xG?p_1g0\u000f;U$x\u00059ZB_/4\r\t9ҖXJQr]N\u0005l8xZw\u0014N\u001ă\u001aP\u001d\u0012!?\u0007\u0004\u0011G@\u0010\u0013ﺄԧ)f\u0016\u000e=:N+eyʫ\u0004?X|AUDُSVM'Ρ8ZC\"84\u000e<&n\u001a@G\r}+/ԇ솆Ph:F\u0018L-ʡI,\u000f~!\u001d(k˓_i\u0010\u0005o3hrm\u0006e\u001ebh&\"zi]'wh.t{\u000bP\u0003\u001d50P\u0003s\n\u0010\u0004o\u0014\u001a\u0002𘷢ϛNb\u001f\n\u000beRYD^Z?D^).u\u0017Z\u0013B5y\u0016h5K/X\u000b6Cc\u0001\u0017\u0016u\u000ewC-j`]\u000eA@\u0014=H\u000e\u001d\u0002w\bKYL#IbdSjOl?9\u001a-\u0010\u0019;r6M֜o\u000b,Bf\u0017!:\u0012:o\u000bX\u000e\r{7$p\u0017ȃ\u000fpZ\u0012QOZ\b\u000f\u0014Iwd\u00194Oc\u001e\n,մ\u0002s{.`p4\u0016\u0010\u0001b+6#\u00041K\u0010=Į\u0016ԠZD\r=ˠi\u0006\u0005\u0004E~P\u001f\b\u001e\u001a?\rOyN\u001a\u00129Wz\u0019\u0014\u0016JLJ{+m\u0011:%:'lJVf\\[j32Jm\u0006F)\f`\u0006\u0016j\u0010/\u0005zhٽ\u0003\u0001\r:p(XҔxD\u0007\u0006;lN/UgRX'72\u0019\u0016vusUU\u001a\u001cU&[\u0015bXMU\u00156cU\u0005b@{ų\u001a\u0001w@\u000f4\u00034r +,vRLS}b>٦$DbR\u001bfw9\u001aWiQ^cUT-\u0015U\u00163f5URmJ*\u00160P\u0003\u000b5ṗƝK@\u001fޱ\u0015\fC\u0002?\n\u000e\u000b;61|3$-!x\u0002\u0015UF1\u0015x&(\u0018bJfX,tf(FނOg\u0000\u001b5p}o1(\u0006f<?\u0004znFE_\u001eO1ʮ\u001a!\u0015\u0018ѿLWV\u0004+GOd#͖\u0002\\Ȳ\u0019j\u0011=ay\u000b\u001axAu\u0011|Wqˆm[w\u0013wvHDdk46U;t*_ܗBcd˜\u0004Y.Bn;ge\u0019R\nsjlV\u0013^h3\u0011\u0003ks\u001cZo\u0001\u000b5p\u0017\u0002\u0017 wl\\\u001eٰ٥\\빽{Ǖ;\u001anEGu?&S\u0019>|Sv/%V})$;͚F.MeםuE\u000emvC\u0006'h\u0016QCݢYаsh]\u0015\u0018,^trx77n97Lw@,Dd\u0001u,B\u001d \b%\u0017k{\u0015=\u000eeե:uS.uܥʐt*\u0005\u001c\u0014\u0006ڿB۷/\u00057&V,tOmx}\b \fo*<^DAxbyލ\u001a0>P,8OkĸDT6.HO:{\u001e9F#OV{\u000fxA\u001aW~\u0002%=3ϭ/?ulmWۂ%/=\u000fJ=:U|?HdeP2<EL\u0010pY\u0017?\u001dh\u0015\u0018\u000f\u00051\u0017\u001d}\r־Fo/>дp\u0016\u0017y7g3w{j<Umv?6\u001dTX\u0006q*6\u0007;ϸAJS\u0019+$<\u001bu\u0011\t#j6r\u001c\u0019`D\u000e\f3,op\u000fH\u0017\u0004\u001eOm\\ekİ~'\u0007\u000e  \u0017gg=`O?H'\u0011O޽P\u0010{\\\u00143A+E%,a\\^~l\\f/\u000f\u001bZvllk \u0007\u0018sip9*XU\u0013,_Æ۩#\u0018\u0010߇EcDǧM'%HNIx\u0016+\\̣$l/\u0015ptl%\u001c17~K^}\r1dN<<yk g:ӧwG3/?\b_͂UVV\u0012Y\u0010\u0016\nQ:j8\u001e@ϙΔZtV[p\n\nJ\u001a,ʒ,$@\u0016D\u0010L\u0002\u0001\u0002$\u0010 QU\"{A(\" \"Z3ynt;b7i\\B+11쥂txNE%\u001a!fZs\u001b=ycȑv\u001bi@~Zj^\b\u000e֬̆M\u001b$k\u000b\u0017ە\u0002A>d8⇃ȀX\r\u0006<&\u0002(G\u0014dl1?\u001a\u0002Ƞ\u000fʨ1\u0007\u00173\u001c?\u001c\u00163vjjqBn8J:j`G'`21|\r;7`&\u0002oPh\b\u001d\u00011G a\u001f\u0006\u0012}C \t\u001d\b)ȁe\u001d\u0007\u001fd\u001cD#O/6\u0007\u0014\rP{]䈪F\f(\u001a䠀Kc\u0006.#K<x\u0006\u0010z\b0\u001bC |s\u0000l~wG\u0003y~4\u0007;@k\u0017dy\u0004n\u000f#\u0019֊B\u0015B匣P2\u0003\u000b>qgKhpu\u001e?ŀ׊@ؿ\u0000\u001ctAC}\u0010\u001b\"c_zAW;\u0013(\u001bv@ہ;\\B\u0016Pn\f\f:\u0001w#-\u0001y\u0005a~\u0003\t\u0005C\u001a'\u0002\u0018\u0005z6\rUC\u0014_\n\u000bB\r9t\f;{p?\u001d*\u0011N\u0016N\u0013&\tn\u001e\nn\u0012lw\u0006\u000bp\u0001?\u0003\u00048_QC<\nLq;FVk)+>eRƜ%Y8ωgz4Q0k\u0012Ma\u0012?M47q1콌!}\rXu;\u0001\u000f1p\u0010C:b`\u0002!7\u0010Ey\u0018\u0006!%\u0014x\u001fL\u0005i\u0017RK3\u00143oT-\"֋\u0012\u001a2$+Ill2_\u0000;$'I\u0018$ʻ\u0007厐\u0018\u0018\u00187Fz,\u001e\r\u0012\u0012\u0006\u000f\\\u001e\rGN-M\"Eǚ\u001bT`R%~BL&6\u001e\u0013.dN(&p\u001dG\u0001\b~H988l'\r+\u0004\u000e]\u0004mE\fP7Ȍ\u0004E\u001c\u001a2\u0018&G\u0017rpI/9i\u001aγ\"Szx2*}L|DjP'^81Nh~ʾ}8K\u001a ii\u0013\b\u0011\u0003\u001f1\b\u0010\u0003U \u000fvp\u000f9l\u0002\u0006\u0014\u0005\t\u0013Z$N0gy4x2L6AT'f=$7< \u001aKl\u001d#&\u000e\u0007s)'\r/S\u0007՗\u0004\u001c@\tA\nN\u0004*\u00031hb \u0012d|\u000bQ&\u0019O%xΗL(Ɠ+\u001fjU)\rQS4w75}\u0001M{Ҁ6D\u001f6%\u000fh'\u000fh\u0016\u000bĈA\u0018DA\u0015\fp\u0005\u001d\u0005m|(\"F-lT\u0016e\u000b'Z88kaVmF\u001awI\u0005I7\ni~~~}\u0003FY;A2\u0007\u0010\tΠq@P\u0018\u001fB \u001f\u0017^Wf\u0002ΔT!\u0010\u0015\u000f\u000bsF\u0014.\u0007\u001dJsѯ\u000ezJr\u0002Иk8W\\+e^_4 \u00061b ,o\u0017\u001d\u001aB!\u0007\fAP\u0014w}A\"NUqSJxBrR9\u001da\u001bC۴s%Ime]+nnYfSV))\u001a\u0016\u000b!c\u0013H\u0011ɽ_o\u0003\u0004C\u0019\u001b\u0001P\u0016\u0013\u000e%\u000bI/\f֔J zP*5aniԚ>Z*|a98fkz.7q{ʹ=\u0005O\u001d@\u0018dA\u000b(F\u0007\u00160\u0007\u0001aD\u001eY0\u001eH \u0014R'u\u001cJP\n\u000b;-ִ\u0015WSXmzNf+\u001d2~D]n\u0010t\u001b\u0017\u000f\u00141\u0011k%~\u0005fo2\u000b0~P\u0015y]\u0015\u0013܊?K\n\u001eՉLMeQkj\\rU[k\u0005תKmVHaыLzqWb\u001c1\u0010CO@s0\n&\u0010߷uasQO\u001eԑLe-Zy\u001cUqR+\nYg\u0012ԕ[j2ZkkU6NQt.bA&b#\u0006Vg\u001cL{BP\u0003\u0004z7\u001cCF\u000e7}V3GvHwVeU+mŲ.5[4my6kR-4UN\u0019<We\u001aqhw\u0007wϝ\u000f}򯈀+\u001fN\u0000LRbЦ\u001c)skк8r͘a\u00183$gR\"\fFB0MUD)M*W˦ҡ\u0003=?0\u001f^??ߞ\t8&6\u001c\u0012U}|kY\u001c jNve~fI-[4\r\u000b}u\u001a^6$䥉+P\u0002I UA\nR\u0006\u00019(1\u0006BN7׆\u0016K/vou\u001bQ{87\u001a#\u0012Ng&\u0016\u0015eTd\u0015֦T7&t6%e6$gեdפf\fRyC4\u0002%\u0004ІT!KO\u000eJѿ\u00175h:.qƳ#^؉a`o \u0015t=\\Eˢ\u0005\u000bIW㊅\r1ŷ\u001ac\u000b&W\u001eJ\u000fU\u0014\u000b\u001fHG\u001bІ7X\u0011jMv@o\u001f\\ԙ\u001fsy(`;0Q\u0013\\~S\\~r]Ji(*J(\r\u0013V\u0017!諍.9U0 \u001b\u00124\\\u0019Q,x\\\u00126\\MPi\u0015\u001a\rPSϯF,~î)\u0017Ӂ\to[#d^ΙK\u0011ii7Oĵ%\u0015Gd\u000b˪m\"Vàp*lH\u0018U2\\\u0019](\u0016+;_\"n\u0002.P-\u000b\u0003ТKWX_iz\u0012hV_F\u001cZ\u001e\u0012+ǨbV\fo ,)7&D.~\tҲ唎{kb\u0001F,\bW\u001eZv,Ո\u0012ɀ6d\rW6@ݾMЮ)a`cmYms͸;<'z<\u0004'\u0018IǌL\u000bE\u0017s\u0003ĥ\u0005~$Bђ\u0012fX\tG8V̩\u0018+\u00042HA:\u0010hk{dv̍+I?U\u001d\\4P|eۺ`o.z+'?C'~\u0016|*l*\u001cc215`#Me\u0011f\u0013&>#rH\u0013|jx>A2\r91PRo<݂\u0019x.NW\u0012@Ʋ5΅ʃ\u000fvz!0$l\u0015Ŝ\rKHH\"N\u0017_Ԥy=Hzg\u001a\u001404Ay,Ey\u0004٬,G\u0016\u0019} \"}bg}OXe\u001beK'!vD\t_0Yǩo\"ȋąs^kJ86׍z99`t2~@2ȓCB\u001eyvK\u0006߿\u0001靐E?)ԯ&X׺5\\L^sv:\u0019F\"\u0007\u0006e\u0007d\u0011?\tƿK\t\\⇻)t{]ue5yn4nq2ueI\u000b1@&d\ttGeɍRR؞\u0007\u0006Z\u0019`n\u0004vb\u0017\u000e, S!\u0010O\"\nHu\rrK}*e:.װ~vxcOѥ\u0005$Z\u0012\"o\u0018\u001dieL\u001a\u0011Mo\u0002ʲ@[\u000bF{\u0012^\fؙ\u0002Μ\u0001\u0014\u0005\u0013\u001e.\u0010z\u0018D{@\u0013\u0010\u001c,D۵rZ\r?\u001e8rD\u0013\b݁A\rb\u0018fL6lL\u0003\u001d\u00040V;\u0001f`Kdp3%\u0000\u001e\td\u000b7\fl+G\bq@#[8ko\rG-x\u0004\n,\u001c=j]\u000b\u0016bO\u001b\br\u000eT!H4dT2\u0005-pSbj\u0000'tC\u0017\u0007>\u0007\u001c\u001d\u0004\u0019Z\u0003\u0012MISs?Ç \u000bk\nL\u0018D\u0016Fr\b$j@\u000f#H$C\u0004!\u0012\u0014ױAU&\u001046\u0011Aw'(vGU\u0003Nkp+o\u000f\u0016\u00025\u000e\u0001S\u0014B!J\u0010b\u001eD\u001d}ӃP\u001f*CD}q\u0004IE3 aQ\u0006\u0018\u0012\u0001*qG\u001et7Z#`&g\u0006V[\u000eV\u0013pV0\u0002wE\u0003\u000fJz@٦\u000b\f}\u0010}/DІ\u001d.ݐ\u001br%`U\f0j(\u00036\npU\u0003\u000ea/\u0004S\f1\u0007f-u\u0007%o/&\u0002\u000f|E@j R|iA\u0001\n~9_y\u0007\"\r-c>Czϐ\u0004BT0B\u001bh\u00062@E\u001bjp\u001c\u0017B\u0003 e\u0001(;`u\u0006z\u0007P/\u0012R\u000be@SWI-A+vw>\u0003o\u0007/\u0017e<{g@|˚]b={ǖ\u0004\rlMi\b2\u00004k\u0005\bp/\u001d70\u0005D\u0003'\u0015^\u0010'\u0002\fRʚBka~mg}#|%\u000e\u0006#3a&ϰ&5\u0007==-:+ZQԣuTD+ʅuBf\b!\fH\u0002\u0019,'$!\bҠ(\"e\u0005(U\u001c(\u0012Lx@e(λO}\u0017\u0017s7i /l\u0015>BG<sg\u0003\u00115Ġ\u0006f\u000fm\u0004>/`X/Ш[\rD\u0001Մ\u0002.3#6'=0]\t3ĉjқ:kc\u000fi!i\u000f{J\u0018F\u000eӚ0#N\u0003I@Z\n݀\u0001\u0005xr 9{\"=\u0004qH{\\v[l\u0001a\u0002SBz\u001dYF\u0019\u000f\nH\u0015z1\u0016|\u0016\u001c\b\u001b`D>e1̦X\u0001\r5Q\u0003\u00015P7y\u00007\u0013@\u0014\u0016\u0018?H\u000b@O<\f\u000fqzܻ,\u001b\\>5F})b_d\b\u001e\r<\ty\u0019`ۣpnapE?\u0007tݦ,p8\u0001\u00029 ٹ\u0004\u000e\u0005i\u001f$\u0001\u0016\u0004,~'<=E3ch/qǘcӬ*h䥄g\u0011x\u0011=?1x~M\\!_;_[\u001a\r8>\u001e y\u000eȷ/\u00015\f\u0005Yt Ac|bIo\u0014#e\\\u000e\u0005=;0\u0016\fcÑ͢GV\\_͘>؇:Cɹ>q%y\u0010?\u0005h]\u001a \u0016\u0002\u0017zjP\u0005o4L \tA f~\t'J8=le\u0015C5Q\rQI^M|or=\u0002񁬊@vܛ|ܛ,`\u0006:jp\u001f!ul\u0006,\u0002Ap#\u0003@\u0015\u0007\u0014䐏bv\u0004/f<#|`l\t\\\u0000QރR܎V^N9OJtQ'i=\n\u001bG,`Ow\u0001& iנ8\u000b\u0010`ڹ\u0012} 3\u001f\fѻkJ&DD\u001c0\u001f\rG\u001c\u0003MIT:\rwc;\u001drjޑnct\u00153:S\u000b])lG\ren G\f`2\u001fw, o\u0006o~g1Ag[$\u0019K\u0016i\u0013PyRT'5kk\u000e\u0019CWl\u0016ǷiY<V*ݙ,m\n\t^S uẀ- wR۽C\u0001Wa#A\u0003&RXo\u0006\u0007H0\u0004\u0004HeNNZ-D[CW\u001aӌ\u0016xPnr\u001cln6ۮ$t\u0005i.B\rS@޽ w'\u0014\u0004,_V)޷aB<V33N\"\u0017&iB<0]nMfS.kA,|w6-\"hW;\u000b\u0012P\u0003{+$w\nh\tVo \u001f7\u0017m؉=\u0006O\u001e;\u0019~1#+\t4R)i$D},1pTPj:«dZLf\u0013\"gԋ\fQ^'r财\u001ag}6pP\u0004q2\u000br=Y`<MVggv8<\t܁?\nȸZ+Q'5\nEaNsDfEL\u0016ƪ4eiwjisZڂvJХK4\u0002\u001ez[pQC\u0002\u000b8\u001dme\u001d.[Zuxˍ2ߏ\u00132Y|A!,֪5H\u0019(,_\u0015[VEh6)-FnPZ3mZg\u0001o+ȿ\fS{ڻ3\u001bgV4wnKW޹p\u0015}J\tزc4Zq\u001em\u0015ːTJoD|D]n\u0015i[Ū;\u0016IzIbLJ\u001b\u0019Ɋ6@\u001a\u0012PCɐ\u0006ūSk<+\u000fnװuaǊƋ\u0007[q\u0016R(X<c(YuDY2\f\\3x:ej w-f@ӂ\bv(ݑ֦ug\u0003\u000f5\u001dY2\u0005l+T/.zએ{O;ۗ_߷.lwi\r.\",d>jl|(9Uѱrfr%\u000b503\u0016o'\u001c:M,\u0010\u0005\u0004s&[W8nR)\u0013UK\u000e]^6a\u001a֖\r\u001b\u00026\u0006X~%dgEl|\u001cAWIg)\u0013\u0012E\n\tb\tK1F|q\u000bB̳\u001b(V=1mxCY\u001a0\u0015;̂c&εk\\\u0007,č\r`rlLj\u001dxcWʴ\u0014|Y\u001du6N\u0017QaK\u001c:|a6.ݮX:ҝ\u0005b\u000f\u0017M\u0004f*7CIC<\\:W{}w/<ص\u0000SS~Ս\u0018\u001a\u0017u\u001aq\u0006\u0004\u0014\u0001uDPQ\u0004T(\u0002\u0001\u0010bIl$$,\u0006D\u0002*0:Z;NZ:nǵZP*2)\bUd\u0011\u0010K9}m^|^K.\u0017\u00177VzaZjBK5}F_\\c<\\mzGiafӛ\u00040ܻ=|j|\u001e4쳨Ǟ$MW\u001b?l{\u0017I]voqf\"k[եm+\u000eUnzZh|:^Eh[m[?\u0010<Y<\u001e\fidkMnsΠ1G_F}\r7^gĪ'\u0014AQЖn-h-ϥ\u001fU+\u001em+\u001e*\u0016/\u0013?)\u0016(^{\\|g`\u001dsv\u0014}Ε\\J\u001e\u0013}\u0013\u000f\u0006y*!dCOZDU[MtY]\u0016Ug(֙][\u0017ujxi\u0015ڝ'S ](U\bN:HӉQ\u000b9{Õ|F\u000e\f\u001a\f`䔿ڸ!m28nM0˦M7\"-_&R*:6վK^<`L\u001aj7x^\u001b[^g\u000fX\u001c\u0019F\btƙit&Gﺐ\u001d\u001d\u001f\\\u001cUɫ\u0014T4N>Q\u0016\u0017IT\"b\u0010ŋx\u0010FR.\u0013p\\\u0019T\u0013*m?;1te\u001f!W\u0013rΉ\u001cDy\u0014jx,k#]!Գ\u001cQ>ň\u000fX&gk *Y>cȎcd%rQ\u001c)#5\u0016\u0007Ңq\u0017+QhG\u001f3bwF-!?&H#!\u0012EjZ\u0005Q\bq_qY\u0007_iR\b\u0004H\u0003\u001d\f#ܰ8\u0014΋Ŋh\u0017M\\\u001c\r\u0005sp1n\u000e\u001eq\u001d9f\u0006G\u0013\u0006!~%d͠3Y\t/RLtFk\u0006ӡ\\O\u0019b\u000bICo2\u0013 \u000f: \u001aƩ:\u000fKay\u0010\u0007U4c&ϜBp,4\u0018?\u000e\r#G2_%d\u0003BR\u0010+>a\u0019\u0014\u0001.|\u0004\fs\u0012\u0011\u001e\u0004\u0018xF=\u0017qs@\r݄Y0)\u0004։AX\u0013ISQ\u001b-~bOqp?;\"s;T\u0011R4HH6\b%\u0007t0\u001d\t\b\u0018\u0015`Hp\\\"b4\u0007G\u0002\u001d\u0014v\u0010n\u0010M-\u00001\u001c3\u0019Vw_,\u0007\u001e\u0013Q1\u0001_@?\t`g]!gC\u0005\u0017zz\u001atPh\ná.r=3'CM*${y\u0010\u001fC\u0000B\bEXtY\fm\tRw2\u00066MV/z/钼vH?\u0006i3\r\u0005lhS`\u0014¨\u000eDFf(\u0005\u0011Ь\\\u0000_\u0012ܜ\u0002v\u001eCrH\u00001\u0011D%\u00103O\f;r,jߥh@a\u0017\u0014Evy7;S0\t\u001aA1\u0015l\u0018\u0016z,\n8\u001bHA6\tMPnK|\u0000bH-\fz9DW\u0014\u0010UB𘂠z'\u001c~\u0017٨\u001e]BfoU\u0014\u001f\fA\u001b\f%@ǰl\u001fr\u00142p`^\u001c\u0005cI<\u0017B\u0007W\u0002(w8 V\u000e)%$u\u0014WT\u00105!zJ\u000f\u000b_6\u0000+\u001d_(ltrH\u000be<p\u0000Fc\u001aG<\u001fear\u0015\rKQ\u0002)\"z\u0014~\u0005\u0014G)O!@zU\u000b}ݰ.y\r:ڨAT6\u001dzp\u0001\u0006tg\\`\ng#/\u000bH\u001cB5\u0007]eE*L\u0004o@C\u0001^\u0015Ti<N?\"1,Va\u001c\u001a;V>&f|U7h\u00002}`\bt06\ncP2A J\u001c\u0014\u001b$7\u0011?OCj!L\u001b0lSAG\u0003~DuAYg\u001aV\\7?QtR6?I:?K\u000b\u0019\u00039\u000e4d0\r\u0019\\`Q\u0012r$TOCl6Vh%\u0011\u0005\u0005<XȪV´a=}NUm3|ۣm׾mY\u0019~2h;ٗw\u0001X&94\u0019\u0010\u0017,5\u001a+bu\u000f֦MZI(VQ0qQj塰D>o\reLpq__ӫڣI7?k\u0000~\u0002\"-ցjWu\u0005\u0011D\u0004d \u0004\b!\u0004I\f2\b\th\b\u001b\u0004\u0003\bQ\u0017P\u0001(Th\u0018I \fǭ\u0003{{̋yy~y$A\u0014'b*3\u0015\u00157EmJO%\\OŚx4C\u0014<H2\u001f\n\u0001ezvA;\u0004{ೀMyK\u0007Pa,\u0004`\u001fBхߠ>\u000b\u001f\rb'iݑ/\u0017f\u000bF}KF-%:v22vf\u000eAi\u001c:Oǡs=\u0007_H`\u00150Z:\u0019*\u0003J?,m:\t20%\tqqChmݨ6foT?'j݆4\u00129u\tNU\u0004<*А^\u0005\t_b`40\u000f6YAP2\u001a\u001e4]f2e\\\u001ew|D\fx\b\u0007~j&TxXp%=6s@4j\rr\u0011ѐǓ\n)\u000b\u0014\u0013[`b\u0003c1\u0010`\ti,p\u0015<\u0006f;/_\n|\u001cA;sT\u0004!\u00055஘I\t7X\u0012\u0012-\teI$->CX\u0017?\\I\u001e\u0015j(c\u0002O3 4#76N0\u000b\u0012\u0012Zd{\u0001߽\b\u0016\u001f\\ml׷\u0012m#šC\u0019.9\u000b!\u0016ƶ\u0014˜LV\u001d\b]\u0014Q[\u001aj6,K\u001c\u0011eǄ\f=<Àd0\fx9h@\u0002Z\u0003jK\u0012f{p?pjw˓S?+<ڕ\u001dߡcSX8Z-PKj~!Bl0{R2Y:=,VGr\u0004\u001c=/mDP\\s`\u001cz[k\tsBf\u001ajv,t^<{\tj]7\u000f\u0003wZu@E\rמVET$\u0016\bxb%Rν)S \u0011$\u0015\u0019\u0011\"B\u0019˸\u0006D5ŕh\u0006\u0012ڷxHGz\u0015,߾ோ;^5YovYcS%]7+Îj~jrXU\u0016P\u0014P\u0014l,S.)Du2qrgH\\&\u0012餢aH8,\u0012\tD\u0002\u0003O7\"@\u0012@\u0002*,XSiy}\u0007-\u001bz.h\rum\u0014ǟѨ1yHJ%e+f%\u000bb~jږʑ!K餈tXHFy1\u0001_d\r9\u0002\u0003i9%FWa`F\u001cN֏oU\u001f6>\\w1ҧ\"6TU\u0005\u001c\"O\u0012e!<\u001132%Q*f<%I\u0019i#b|TȖ\t8)\u0006\u001eGjD́dtm\u0005-\u001c,_tmkŃ]_t_w]|`e\u0003DAmLpf\u0015\u0005V\"tnK\u0011R%q)yI㲇%dՈznLHK\n\u0003B\u001b@\n6\u001bX\u0000֬6c7WG0}wv]:֋5-a9AZRNV\n\u0019T#$Jđ%\"\\hrLǟ7J#rn<\u001c[%\u0000\u0016/\u0001sڥY-xg\u000b~5=?\u001dXt,S~gZx\u0006B/sI$4\u0011IŎ gj/C5z\u001e*4 F.!gCȚ0\u000b\u0017-Em-xl\u0003\u0006ۀl@З}pƁ}U7\u0017ܭ>\"\u0015Ϳ\u001e{IŒ81k\u0012\u00125\u0016R\bji`\u0005\u0002MK\u0013\tvX\u0015QdbF\u00160\u000b\fv\u0006<\u0006[_o\u00077\u0007l@陣U\u0013eEmz]~?hn\u0007/$\u000e%8vC2]$\u0006ow/4WԀWKկh!\u0015Ab;,\u0000å\u0016`\ntY\u001ek2\u00104c\u001cGf\u000fMcݬ?\u000eQ\u001e\f}#\u0006ف!\u0019'\u001f\u0016Gz\u000f6⼆p\u0007q^o\t7\u0010}:Y0y!\u0003`\u001a\u0003XNKg\rj,\u0004eU\u0016\u0017L9or^!p]/\u0018?4$\u0019BQ.X=㴞\u00150&+\u0003A\u0006m;2]>0\u000fGzb\u001eL\u0003\u0006;Z\fhk\u0000\r,A}kPd\u0003k-[me{Vg]1f=Ϝt\u0004\u000e{jx&{9:jo|\u000e}{\u0007\u001f׉ϾGt~;߁\u0002p\u001aF\u0000\u001a:0\u0002\u001fY\u001f\u0017c>:̓|ޖy9ӡ7Fy\u0017:\u0017-p.\u0007]gQMy\u0018?\t\tq\u0005\n.,*  l\u0001\u0002!!\u001b!{\u0002\tI\b\t\u0010\b\u0004\u00047k\u001dKG\u0019wKU#-X+:\u000euA\u001c=zL[8\b\nB|潚|w]=hil*5{.]0wp3G\u001fN\u000bRqU\"֘[>\u0000as\u0007bOn\u001e\")\u0007{>G6bڸ\b-Gx\u0017\u0012}HY\b|HC4ЄaX(AQ\u0010<f`u|\u001a$$c_R\"mJ\u001cnƢ/-\u0006H'\u0012<<IQϒ(jO\u0017Em־V\u000eUM+E(݂\t\u0006|LC4S\u0002,\u0001rpa\n@qH*tA<ֆE<\"\u0012\\q+:\f}ѡ@9FQ_^$W)jmHQ`Re\u001dg\f|2\u000b\r2\u0005$\u000eS cA3-\u0001qΈ&\"Q\u001f5\u0001\u000buv\b\u0004en .\u0004EW\\\u0004AG\u001d%wA}\u001c(\u001bh\u0011\u0013i0u\u0014^B\u0004Ӹ\bf#B\u0012#\u0001lX fF@>>\fa\u0010\u0002@TNq\f\bGq2͓\u001d$ߡ(\u00132)*\u000f\u0014%\u0003\u0012`8\u000ez\u001e\td\u001e\bE!;\fqL\u000f\u0006\u001e\b.}6D\u0000\u00183e|\u00044|E\u001ds262'a\u0007qh\b\u0010/Ȣh\u0010f3 2*\u001f (\\GAi,;\u0012 <\u0004As\nRu\rt:3ALd>\u0004\r1\u0005y\u0003\u000f\u0005\f\nJ\f' JCʀÄF\u000b\u001f\u001aK\u0010T\u0015aP-!\u000eDX\u0010\u001eK/ldAV'ɺ\u0005.\u000fg Ivg|\u000f[\u0011xbd=x\u0006M\u00174d'ѡ`1IgB'^\u001d\u00009\u0018pGCI<ے!ٟ\ntNf@x&\u0013v.\u0004Ywg!>\u001fY\u0002\b\u0000\u0019\u0016/y\u000eB\tt&xCȀ.\t\u000f&E\u0000\u0010\u000b[\u001b\u0003D(@/8nBܖ\u0005\u0005>B\bE\u0010<\u0010\u0013C\u0016!ρ\fُQx /(#hPy#o1\u0003&\u0016\u0013\u0016\u001f\u0001BPP\u0014\u0001CU\u001cꓠ4\rʝ\u001c\u000f =GBH\u0015#3\u001b\u0012\u001e\rKGR<U@@\tUx@/\u0017Ҡ1\u000ek\u0002\u0013\f?8\u0003`׆\u001c0`A!\u001d\\\u0004P4 o@z>\u00079 &'}HNJ1&\u0019Q\u000e\u0014On=[}KAݝ\u000b<Ϡ#\u001d4>\u001b(:qLT}\u0012å\nA1\u0002(Iy\r\u0007-|v{8\u0007\u0016\u0019Tg\u0014P^R\u0015W\u0015hʟk\u0006\u00144Owy\u001bw:?.\u001b<C>)4½a#*}P2\u00053L\u001e\u001a}\u0004*\u0016Q\u000f\u0006hAd$?\u001aҵj}jzo\u0018W\f˦QӅQ9g0\"7\u0006\u0002\u001a\u0016x&XśU@|\u001be渱jGʰs)wtuV+neEc88ᑾx_~aKyrpf\u0019.l=tГ|\u001b{]Ċ\b:&N'ؐ=\u0007ա#1+mWU]GF&\u001dK_\nn\u0017[nZ\u001e\u0014d\u001a(0\u000f[\u0006mmECSC-_z\u0002l/\u0018yA\u001ao\"ؔ-Y#\u0014\u0006\u001azY[|%+p2\\+9TcqK?gK:-;,J/Y_8Z4h\r8N\u0007J\u001f)\u001d,9\u0018y\u0002L~#d\u001e+ȷ.ͱLlK2ȟ9(\rv\u0005mpo\u0011]_JSMk{As_%Q\u0005{k7%γfGpYeM\u0001>\u001b'( dȾWOz4̣a[4\u0003;Y\u0013p؛=n[m\r.ѕ+\u001d+ۗn)ztAGd9׉+eU|Yy+׾ʾݮ~.\u001d\u0001'0\u001dFfQC5&2\u001d%?1A\u0007\u0007d袻[~\u0014mC?h9|{ɉǪ]]mK\u000e:j\\]Etm_Wly8y\u001bƟ8H%CESf_˖\u001c889v!5d\u0017l!\u0015Ҵ\u0010eFiK4L^\u0017XYA@\u001f\u0003\u00113AZ6]MDj+.;\u001f\u0014\u001cfw9&G7%ƞgTF\u0015.8\u0017M<m^\u000e\u0005?7Ogg99v:>$\u0010,\n%tI\u0018Il\u0014b樒I^֥N\u0017{:+vxo\u0014\u0004f:4\u000bkRe\ti\"anH^lYXVt\u0003/#\\Ԉ 5=/%z*\"9z&,9j649j>$)j%=֓0{\"_B4{YS.uEp@\n\u000fk%\u001aY5_qOf\u0016Kf|\u001dP\u0012\u0012w .\u0013\u000eF\n&B\u0014WLxYN\\\u001c;.v%\n#<{+\u0002\u0016\u001aUͤHߴzrLN\u0006M\u0015~jK\nO\u0014Ddg%222YI)x䇑\t~d\u00147*a:<:~\u0013\u00137ǎ\u0011.DD\u000faD\u0006rxY\u0011~nSћjᮽ\u0012\u0003&ʷmZ\u001b_s2P\"wZ~ܙ\u0002 \u001b*d\f\b8ᇧOq#Rgy)\u001c~\u001c[\u0012\u0005&<pH,\u000b'\u000b+2Ui\u0018!\r{Tanޮ#;ڭ5\u001b]\u001a\u0002T8<\u0013.)Je\nsC9\u0015ᬼ&\u001e3\u001f#/8g:\"$s&,4c66\u000eK]`\u0002\u0003\u0010)K\u0005\u0019\u001a\u0018W[\n(ݾ\u001b=\u0015oZmbܦӖ\r\tu\u0011151$\u0006<,+)\u0012W\u0017[.ܿx&, ̙c\u0007e͇/\u0004\u0002\u001eb\u00013]\u0019\u0015^6H\u0004<}_v.WgA7;=4i\u001bq^b7&\u0007g2J\u001a؞uC=ٞ5sSe!~\u000b\u0005\u0001LQ !^\u0012\u00160ZE&\u001a<A\u0018t\u000fA6J#\u0003ʯM7\u0016޳ɼ?)[\fK\r\u0003\u0011~Zmm=Lko\u0002]'./1=^ˁJ\u0019\b\u0019T*-\u0006xVG\u0007mTEbT\u001a\u001am&W=Փ*\u001a6V\u001aL~^t{!V~\u001dg_[oSoCo}\u001b\u001f۞~\u000e\u001dM'.!0\r\u001c\u00152v\fMiPR\n*GUIEWSc~\u001bGm3\u000ftp\u0013\u0013PPPPqW'æOO?\u001cZ?\u0004\u0013\u0000\u000b\u0001\u0002~WQz\u0006ck ww\u0007ec7S澵\u001c2~R'\u001eA\u0006\u001ecCc_\u001a;eڎ\u0015[\u001c\u001fk|}ś7V}6}Chq\u001fzE\u0014e\u0002<'2\b\u000e\u000bP\u0002/h5%\u000b&5hQtٰcJ\t\u001bu\t\u0017M\t'&\u0018&8zv\u00131\u0006\u0013tCf5FGw\u001aL\r\u001b\u001bO\u001b\u001f\rM&ߢgh)Q\"\u0007u\u0000]-M\u0001\u00112 qI\u0001b4ܥ%Ce\u0013\u0005e+\u0015eGue-\u001fY`X~0]ehTh`2\u001fAÃ\"]\u0014U\u00007\u0012w\u0012w\u0000r\u0007\u0001R^\u0001N\u0003/\u0005\u0012:Y߇e\\L\fUł8a1j\u001cƨ-\u00070YS\u001fa^lٍw\u000e]hz\u001a\u0000ڈ{\u0000r\u001e\u0002$\u0000\u001eI\u0012\u0002Q䋪dwԤ\u001d\u001fG#)346A;Y#t\u0001\u0006ۇJ{0ZY\u0017S7lBUmU.m8I\u0013g7m\u001a[\u0011E\fPIt{\u001f \u0019\u0000\u001c =\u001f\u0003e\u0019דlQl_P.\u0011\u001aшzh-\u001b$w\u000eIi!KZ\u0013\u00052_\u001d\u000bnZ9U߀\n*2~Z'Dw\t\u0011\u0000k\u0000/\u0000\u001e+@h\u0006׀9ʑQt\u00107Q\u0017u)t\u0016\u001amEs1\r\u0011SCg*zҔ1@|\u001d+PB\u000e%b,Hb\f\u0014I~\u001f\u0010ݦ\u0001l\u0011\bm#H\u0003(\rz\u000f]T\"\u001ai\u001bn%oFm\u001a7\u001eE\t\r)hDGSZʠ3u\rzQ%I!_Ibq(Fخ<\n V\u0005渶(.\u0010@\b\u0010 \u0004B\u0000\tdO\b\t D\b\u0002\u0001%\u0014A\u0005FT8\u0015+xvpk:V;zU{J\u001dF`YM&<|GtN\n\bQb؁ʹ\u0003'\u001e\u001c\u00038\t3VCX|\u0016#⌀\u001d.`]\u0001OW+N~n5|\u0011w<\u0013>\u0013\u000b`\u001d\u0013A\r\u0005O\u0004_\u001dB\b'=q\u0000/n&yd,@؆%`mY`Yn`\u001cu\u0007\u0003g=w\u00064{@\u001f7|I\u0003:H\u0017\u00025\u001a\f?BHI t`{R\"n\u0007>\u001e|\u0003bf/s\u0004/m!?\u0002삐OV\"x\u001b\u000eF`'!,ɹ\r\u001d\u001f0z}OX\t҂A\u0004g,\u00047{Ɇ_\u001fg\"D.\u0005ǃ\n\u0017\u0015QvGl\u0003YMtBt\"s+]*W5Fh+\r!:\u0003i_\u0004_#;?\u0004=G+b\u001f `>7\u0011\u001aҁO\b=3\u0005@\u0007$fA\u0004b\b\"h%[WWG\u0003\u001bmtp:f}6\u0000aי\b\u000bD @+\u001b5\bz\u0003q$X?\u0011r'j\"Du\"֕\n\u001dS g8@\u0015>\u000bJ\u0013dHJ[\u0006Q+<\u0011\u001b\u0006:\fD3\u0011q,\u0010]b\u0003k,d;\u00102{!\u000f\u0003\u00018?Ds3\u0016듀\u0016UHXAPAK\n},\u0004N&-*\u0005unH2 \u0011_x+l\u000eƴ\u0005Ew\bÆ\u0005؃Q7Q9/\u00059}\u0002pŀw3\u000e\u0011W\u0011q>\u0001\u0011&\u0018!?{ԯZ\u001f{d>@V#֊\u0016ArArUU=,7\u000fJ\u0005\u000e$6^Z^%s^\u001f[\u0017%*7!q+C;\u000eQ\u0012 8/D\bN&A-\bd_Ɠ|Ň\u0011-֑{\u0005@\u001ew.\flٲt[R[\"WQ\u0017T;KRg\u0003IO{[\u00177c\u0013! \u0014qe\u0010\u001e#C1\u0011$WLh\u0016b-\n#G4\u0014g\u0016\t\u000f\u0018\u0013_\u00184egy?YH_κs[+▲%\u001bkҞ+o\u0013.J{\u0013IEe\u0010\u001fW@ܩ\u001aj$\u0011>đ|)֑\u0016\u00056UTN\u001d-g7G8/yZ\\ИNn}%7,ܫQ=\u001fV!Jy2\u0017\u00177ңv[\u0001V-\u0012@g\u0012_B\u0006idg'=6M%sz_e_-\u000b~6K]nt^7\nr\r9戞;O?O9$\u001ew&8|[ٮ]ٖ2h[ͩ㲦ԷƴwI\rdgQ@zlZh\u0003RjwZOkCf>VEuv$ٳ!}*$\\KlWv#Ir8}`Zj\u0019Mk귚}#ꆵ\u0019VE}Ƹ|{[)!y\u001fDmH@6o<\u001bl&}\fԭmݣF\u001fyN$,P}U.\u001c+*w\u0014W\u000fdS6g\u001d4e6d\\Kٙ٫\u001aN\u001eQdsqYUDH$[G\rdΥ2VrG6O]m5\u001dn6;^\u0017.{vW\u00026g?h䷙6\n[\n+\u0012eyU;\fjks?լ}0Ri\u0018N0-1VU0.{\u001f$mJ l޲\u0014T͡\fp<߽Vԫ{58xth\u0003\u000eWf\u000flYWf\u00126nIY\\#-lTW\u0017O0vZn|Z^03\u0017\fi\u0011MqTU?(˷\u0007\u0019y{)L|28k\u001c݃(7\u000ex_h\r{YGՌ\u001fF6Z\nĚ*yeNfSkʦԒ4Sb\u001f:ST41\u0015L\u001b\u0014\r\t a&.&\u0001\u0019{S͠|>rǔmݭ%\"J};\u0011uʍbBf\\.1M),,ոLZ^ُĀ>ӐX:)(\u0019U\u0015Ɣ\u001bLV&B\u000eٜ3(CU沧iFuh:\u000e'ʿ۝j\u000f[W[Ģx=rzSS\nnW&./fkIiViqUX٬5X9SY׺-Cu\u001ayTe4\\Ѫ\u001fu\u001a\u0001MBX\u0004E\u0010A\b\u0000aIX\u0012\u0004E@0\u0010\u0004\u0004\u0005qW\u001czZ\u0015D\nR\u0014E\u0001APAܵEܗ#n=3v\ncNUԞ\u001e,gg|~zy}?ѐf͂1=ŧo\u000f\bA4\u001aӵV+ok\u000e2?\u0010mW{$QRYk+;.b}˶S\"{qIyy%w,>{I@m\u0019˶\u000e\\6E~\u001bу*!ݮ3Ftm\u0002uM原Tյh'\u001fly}OqOj#\u000bǬ;&a\u0017)*>K_X?+w᜜}md}=@V^`O2w\f\u0019\r\u000bY\u001f٧DN6\b\t\u0001u1ֳ.3&\u0011sՒ\"/jT\u00166慮;TnuÛf=,=sӪo2/\fU\u0019\u0019YeCsw\u000f\u000e\u001bFRևD\"_IUǧ\u000bM\u001c%S,\\R\u0018U\\\b,=\u0017㰽CQ>wݩy\u0005'\u0016G,iY5-yc\\vSѬc{S\u001bkR\u001bN\u0018\u001ao\u0018\r/\fÆ/?\u0018R>\u0019*FGRGCo#zTFtb=tG_]\u0015ҡkT%\u0013^\r1MmDd+/d/>08g6;>'^:1U\u001f>>\u0014f6#9(TѰ臝Dw\u000e\u0010]\u0018۽j/qTyÈM{\\]ۑ\u0013ފ_q3m,k\u000b|V\u0004\u001aS\\\u001a1s6zڌ1י\u0017ӣ vyŴ#>\u00053D\u000f\u0012]!h`?\u0011Utr뮈ӖO}[8:>\u001c\u001e˼&<ت};hVFB\u001dyCx]DFvA\u001bu\u0019:yDgD7\u001c#jnfʯ\u0010Ӗ\"kNkzżr =Z\u0004kCO]JOxV\u0012cz>Fȵ=U\u0011͊t2T8\u0017w(C@u75\u00102ω.\u00124\u0012\u001d>/\u0012N\u0003͈V/\u001dy/eTFW\u0011fɯfOxd\u0015חa3/N׷!oc.܂M\r|{FD7\u0015$/!\u00195Z!Dul\u000e+X\u000fvv\u0011\u0015'_\u0016=7-)_3{p~j\u0019\u0003Zx\u0016Y\u00134C\u0013\nUClw~d5\u001cĲAl\u0010bY?\u001c\u0018h\u0007GX\u000f\u000eaD\u0012\u0015|K#Q;#J\u0004Î\u0017\u000f7n:Z(\u0005\b\u00153\nBH\u0014c?d`\u001c\u0005l.AT\u001cVK\u0017\\_0l\b_ǈ*P5˿C)<?gD\b(\u0016\u00165E@SÝ\u000b\u0017\u0000\u0002j\u001cQ\u0002)f\b1K\n\u0019X.\"[\u0014\u001b$X\nϘ\fLGb3Prh-\u0015Orz\u0013ż#\u0002Q(L(?&|X\u001d2$B9A9@A˷A,\nI|Kdc\u001ck\u0004f.0E\u0004Bc\u0017<\u001b\u0002M|=HU\u0002\u001c`J\u0012'W\u001e\u0002'\r\nR\u0004x,\u0010\u001b\u0010\u0014Q\b\u001c[\u001a9B6'2qc\f=/JGp \u0011 P'D@\b~&P,6:KȋYf\u0003σ\u001ee\n\u001d\u0000[\u00131<~b8c!e\u001bNÊf5(8\u0004auhB\u0004PG\t\u0011\u0014/*\u0014\u0001\u0016h\"\u0014['{dxW=\u001c ocg_t\u0013N:C3pf\u0004/F\u0001a?\u0007\u0005/\u0007C8#\"P0!BgI5CHx\u0004\u0015XAU8\u0019\u0001v/_\u0018\r=\u0004߳P|\u0002]6\"3/ܠxǌ0|r\u001b\n;\u0015\u0006A2\u001aBY\r!\u001c\"8\u0017@\u0017\"n\bd3DL@IlEv{\u0004uDP3\u0002\\jv\rKS\u000e\u0013\u0004_!\tX\n@H\u000b+5<B6\u001a9XC'\u001f\u0002\u0005\n\u0011\u0017+a\u001cb2,1m\rk r\u0018Ờ\u0011VКKi\u0014N'Խ#מC\u0001~\r<WCV\u00037\u0002>EpVCԿ.4\u0010YEjE\u0003( \u0002\b\"A\b%\u0001\u0003\u0004\u0012\t\u0010#@\u0012#r\r\u0002\u0011A(\"H\u0015M׫XVG+VWZ]gߝ/g|g]ך\u0001$i\tVc\u0002\u0019j\u000fD\u00030!D\nhzG\b[\u0007Cq\u0003\u0004\fn@=_\u0017\\r}As}F}\nns[\u0000x\n\u0004ϫAy9\u0001*Φ9|f\u00109DY@\u0015D\u0004B(\u001eK\u001cD*׌F!.mz\u001e<vli'k\u001f?\b~1KwZ\blD\u0007i&xb6S \u0002\u0014a\u000b[n\u0006b<\u001c$^@\u0012`\u00031\u001f\tx!JsC)W<GnznO\u00011y5euz믬+[o\u001ez|}\t>?2a4\u0001;Na1\u0012vk\nZC\u0001\u0002狰oR \u001e#\u001c\u001e ~H{\u0011/px*ٽ_\nǇjٰb׻ͷ\u0005=o:~y_#!|\\qw|\u001c\t$\u0004|ÃQ>P\u0005@\u001d\u0014)\u0010w\u0011usW`Qn2#5h\u0003yR/ף5n3Q-߇\u001b/5\u0017uM\u000b\u0007\n\u0003N\t:!\u0011x\\$hB6&\u0004P(\u0004APo8\u0004.S3\u0005)\u0010mOE\u0014Hd`\\iXf6iK\u0019'E\u000fd\u000bRtv阽';'\u0002\r:\u001a>\u0012|$l*\u001f\u0018\u0011@\u0004zg\u0014!U\f4S\f\u0000V,\f=vS^jR\n\\g\u000b[\u0004ͨ\u0005.Ǭ=\"w99)xOHKU\u0007|%i\rt\fD\u000f0\u0013^y(ewE&:bh\rF\t0\u001a$@@)=Į%Ωs?A\u000b\u001cşS~+[ovlLq\u0017ɥgr\"\u001d2.GR<G>IZ\u0001YEࡄ\u0010c|;+\u0010#vl6Kns\u001bc$\u001bS\u001b\u000fA\nj)0@7\u0005\u000eb-ǮȳCc\u0003SSfz3%쥓\u0005a㹱.#-\u0003\u0019\u0019>J\r;,3*o&\u001ae=d}06\u0004ߐp]PW%\u0003n\f8r r`d0\u0005\u0003q\u0006\u0016-\b=-@Ѝ}M\u0016>*g.\u0019/\u0015\u0019.q<Jά\u001cjkF\u0011QQI>L\u001a\u0014'\u001d\u0017꒮\b\u0014O\u0005+I\u0006X\u0001\"\u0005\u0010\u0018) ]E7!\u001a=*nFgf\u001a\u001c\u001bONT\u001dF*=ERώ\u0014\\\u0015>fP陕\u0019\u001c}z;D/*'D\u0005ˡ9a~\u001a5i(akRe\n-D\u0010}/\n=˷Duz|o.5-Bg7\u001f߿f6x@\rwqo\u000e]GSI:mu~\u001e<YSѪ[x\u001aU0'k,Tu!THR}\u0010\u0004R\u0001lu:\u0010@\u0004B\u0015L\u000btOKA7*,Еy8>nG߶a6޲z1hQo\u001dge!̩R^[.*Kח\u0004\u0015k\u0019\u0005\u0005U\u001cM\u0013/+(L\u001d\rU~\u0017P^\u0005^Z6j`0\u0005p\u0017XWwT\rhu\u001e:y\u000eMt5\u001b2-&bEKh}]m[UM6]e_Q*P+K+\u0006njQ@\u001d\u0011ɵgCe\"y;B\u0003\u0000;9\u0017\bS \u0006w!\u001e!tC}fh\u0002@ǌ\u000bՔ\u0001UO\u000eguUMbW]CVm7ϐ\u0019\u000fNԱ\u0014\u0015u/\u000f\tD{X[~|\u0019p\u0013L\u0002[V\b)\u0010DB\bwNc=fh\u0006\r\u001erͲ]5\bgm[Gn˞YʆܠRzBN\u0018\u0006Q\u0013H\u001d~T\u001b\nȘ\nHt@Ė\u0002\u0014ZY\bpـp\u0007{\u001eC\b\r|i\u000e\u000e/C\u001dC.\u0016_\u001c-+aNn݉[S\u000e;mŴݭՌV\"0G<E\nosM8\u000e\u0005\"\u0006XQ4\u0005\b=Ej9Ba7j\u0003O3>)j\u001cs23\u001c^;B|3$t\u0018\u0014oL>,u'{\u001dRFj\u0011\u0007+\u0003E\u0010^O?dr7\u0019\fN\u001707\u0001]X\u000f!@*Bw\b]Ad\u000bBc\b\r_ݤ\u001dt{+<sA\u0004!(sX亄#qΒѤQaN:8?&l\nC \u0004\b\u0004D\u0016\u0002aI)TeZ=zSm:g\\j\u001cj=\u001d.\u000eZ7\u0016w:V2ֱ. VD\u000bױ ·߹?>k/7ZT_ks7\u00146m\u0005\u000fDna-r[;~\u0016\u0011cx|\u0003D_|J\u0016>KˎEћԂEG->\u001c\u001cv8T)\u0017\u000eNв@]n|;)T{s%35q0Ͷ\u000f\u0019m@yW\u0012\u001e\u00105;dd&GyS\u0017-<\u001dD6z<m\u001d5򩊐ꈲW\u0014ζ7V%}0֨jf\u001ce|\u0003Cq\u0018\u000f\bH߱\u001e\u001cH'D\u000ejdV\u001c&ZrR@𢙝~4\u001dEj~\"tK\\\u0017/v.dwf7DǤkr{\u001d<sHL\u000eISPԺh\u001f`S={l\u0006V\u001c\"ZvЗ;x~&u+*\u0012.;ˣ]>vc_֍Yco,\b\u0015dY\u0013b\u0014jm\bt\"\\\u00178\\ۅHM\u0017k\u001eD\f\u000f\u0013Ds;^ ,4\u001c㹼~\u001doc\u0011d\u0011\r8=\rTxV{\u001b\r.\u001c\u0019\\;vhH5mL¯.Cw\u0003\u0010C\u001c׏\u0012ma3>\u0007^gsX~G[B\u001b\u0016Q(e>*\f\u0003\u0002\u000bMCra\u0002xa\u001cyFc\f\u001fxGaw$\u000exKp'\u0002\u0019\u001f\fl`3vog&_$*BM#\u000b|Ʉ@CBZ((\t*.\u0001\\,\\\fx\u0019H\u0014\u0012` \u0010\u0005\u0001X&\u0014c\u001f\tࠇ\bW!\u0006fpU3+l?\u0007D\u001e\"\u0000\\\"\rH\u0005\u0011ų:\u0014 \u0019Ix\nC\u0012\u0017\f=\u0017q?\b\u0005/8\u001fT\u000b籎簝'c\b\b??g5\u0007|M\u0013˾Erb(xS\u0004(\u0004b\nD\bZDhĒ\u000fT\t\u001d/j!8K\"f5SdZ\u0003m\u0012$=\u000fm2\u000f]\n{\n-H\bE\u0007bfy\"z\u0017} ];\u001aҏ|!\u0007i\bү 9ꏨ\u000fbD2wa1xd]\u0000 \u0010\u0011Ԡky\u0018X\u001dz\u0000LVG\u0007\u0012'zB9\u000bq\u000b\u0011h(\u000bF\u0011\u001f|?b2\u0007\u0003 ?ɜgfn3\u000f~_r\nB,\u001f#dX,T\u001c<Ii\u000bb\u0011@o\u0013i^\u0018;o\u0014To\"q\b\tP#F¶\u0000(w\u0006B+\b&x0\u001dU&s/\u0018\t]\b\b\u001dNDP\u0012}\u0016\u001390\t<T<5<,\u00176\u000f]0Nah$.n?\r h>\u000ezG\bP\u000fA}1a4\b{W#\u001c\"f2ς友\u0011\u001a#; @v\u0007\u001cȨAKH?\u0006\u00010\u000eq}\b5H\u0016p\u0018vE,UO\u0003\rɯ)\u0003\u0001cI\nn\u001b e@t\t1W͈<Y0*Y-C\u001eSph\u0005(\b\t{\u000fr!{\u0018Y<q\u0011\u000f6GOg\u000eYI\u0007-Gd\u0003n[/<a˂;\u001dg3\u0010&YHeϖrȗpp2.VO)R\u0010lO\u0014shpVWC\u0006K\u0007rޑGbf蟳b_{\u0007=S\u001f\u0015Wd\u001dVH<\u0005U\u00156@ud\u0004\feD\u0019*%d\u0001*='\u0014\fU\u0018xx^h_\u0012IcpM+c/]khoR'\u0012/%vR?T١iC{$\u000f\u0002h\u0016Bg\u0004X8\u0014$\u0007\u0011^LUp60,\u001cyߜ멚\u0012xmF^,]\u001a}*\\{ʳ?J<S%鴳Nح98mu\u001ds\u000e:\u001d04:a]\u0004Cx\u0018v\u0016C_7\u0002rX\u000f\u0002\t\u0015lי\u0012@x10S=J\u0016>1Ҵʀ﫧4OmbEۄ?+[+M:VHiPv}>dj3q]3r57`\u0017g0o/iK9<r]QMgy\u0018%D\n*2\u00032XP\u0004HT\u0002A\u0011\u0011\u001b\u0002D\u0012 @(\u0012J\u0002ޔ\u0000A\u0001B\u00196\u0012=\u000esfκ޽\u001c\u001f\u001f{\u0011b\u000bO\u0016MbCx-'I?&s>\u0012\u0005\u0017XߎM9\u001b#sdkQ\u00115\u0013nBN\fy\\8\u001a\t\f<;\u000b?\u0014QB\u0011+\fy#p!\u0004\u000fu\u0012N\u0002\u000e\u0006x\u0019ʶ\f[]\f\u0016X&wg\u0012<%ݫ:0/<8\u001aS6|n:\u001b9@틼H뉸Axh|KD~F!ZS4\u0011.\u001ay}\n\n\u001f|\u0006&\u0012t3I\tl\u0005}#fr+Ȧ0k4f,9nD$s&\f\bJ{j<b1=V\b7j=`~fYGj>Uw\u0005\u001fQ1\u001ek\t\u0010n\b$o\u001d<.\u0005\u0019\u0005x:rVȖQ\u0019F\"\u001bvIv$\u00165\nJs\u0016t0k울\tNe\u001dNEO\u001cU{JX\u0002(\u0011 Z\u00000\u0002D]\t\n\u0000(\b\u0000ަ\u0010i\u00010E&p\u0002JהF\u0002ߍyǷ\fʣl2\u0004v2&%ݵI ť3ɵD\rK%\u001a)\u0015^U\n\n/\nEs\n\u0012\u0011\u001b\u0017!Bh\u0018`\u0005\u0001/\t\f{o.\u0011\u0016\n\u0012c2{\bWT\u0017K\u001bEV}\u001d9{[I\u000e\r\u0019\u001crU:]M/6\u000b%}\u001c_\u00167[͖7[|\u0012Ē\u0011C_dD[\t:\u0007U\u00027\bJHu!ܪ\b5*5\u0015L\u0000Ne莖=jС&K<\\YH)ʨ+d\rnQnz\r\u001f1!\u001fY*bR\u0010Sv\u001a10x\u0000\u0011{J\u0002.7[$5;\tלvU\u001d<\u000buS\u0007Tbt<\u0005%7GEϒ׳dYa$8\u0007̯~Lđd\"4\u001d12D\u0014\u0014\u0000\nX\u0001p\u0014;O\u0015\u0011눠kX\u000fMaщԭq-5ǷUWFRW%\u001dT\u0014\u001dVze\u0014RkY\u0012E;')O'̝{/!\u000f\bs\u0011[Y)(\u0004J\"\u0015j\u0001&\u001a\tp\u0004\u001ak\u001c0hkZ1i8f\u000b\f.ZU*+{H˔Ԥj\u001d<\u001b\u0017|/_|b\u000b\u0011+.\u001f1\u0010]\u001a\u0014\u0003$[=gp\u0006{W#vV\u000e\u0012vYB{>bc'ٸQ9jU\u0012#'!@jYR.:S%񫚙'+\u0007|*'8\u0011\u000f8\u0011\u0015|\"*\u0010;R%S\"\u001ah5[K\u001a\u0019L\u0001q\u0003\u001bf`34\u000e&w3T1Lz\u000e\u0015-#6-.Y(l5+ȼ&WdC#-\u0011\fn\nVa\u0006#Fp\u001dV#ZX\u0005+*_ͿE\u001f{W\u0002p\f\u0019`\u0018\u0002`\u001b\u0000#6ფ!ly +@\u0017N{S\u001ds\\»JC:՞A=q;\u0001\u001d\u0001m\u001aAԣ͈zL(Auy{\u001eoq\u0012`\u0012w0\u0007\u001c@-vвu\u0015\u0014q\u000f1Q\u000b-q/x\u0013l#GN\r\u001d\u001f\u001f*v:s9>Վiq\u001d\\r@\f o/\"s;\u0011ٿ}52\u0000G\u0000p\u0007\u001as\u0000\u001dg\u0001\u0003N k\u0002dӻ\tiWR\u0014X0o\u00163\u00199jUmW;\u0003'2w\u001d(\u000et\u0017\u001dێLݒ\u0003c\u0013}\f9. \u0017\u0010ra\u000e\u000f\f\u0000\u0000\fu\u0001t\r\u00004\u0000|$@M\u0003H3\u0003v\u0010;\u0010b=IQ>as7\u001e[\u001cMΦ[sf\nfjvg:`Kږ:du\u001eȎ\u00151{\\E+WwA'@?@\u0013ίXΟ\u0002H\t m\u0000\u000f!f\b[\u0005\u0017B\u0002ਞ_\u001fl쫏^'1)\u001bi\u0014}g6Ky+wVn\u000f\u0001|\u001f8x\u000f8]M\u0006\u001dh\u0019\u0006\u001a\u0007_ο\u000e-\u00113\u0002'\u0015p\u0005C\u0004\"HvY(9yѡY&/J9hZru3W/\u001c~\u0011,=A}ny\u0003\u000e;P\u000bg\u0000\u0012\u0002D.\u0000\u0004~\u000fg\u0012ЗL{\u0012(m# a\u0011\u001e!:\u000b5px7?\u0019\u0015ՙ\u0001Sa20\u0000\f\ff\u0018`F\u001aP\u0005\"JQ,X\"q%Uc\tjt\u001eE=.Y{u\u0012ƵG\u0017\"\u0018%(\n!\u001c;O}}'~$~0Ofh\u0007#v^R+uBW\u000be{;\fF;\u0019m_ \u001ax(6Q}اD\u001c֍\"j)]\u00105GPps`|(\u0004|H\u0013?\u0013-\u0005\"\")bϏ߈5X/v~\u001bnH>6J-\u0010߳*\f.C4'DD\u001e\u00108?(\f\n\n\fА\u001e:H>0\u0013\u000fZA\u0017rCO\u0015Y\ny\u0013J\u0004\u0007L\u0012X R`\u001e\u0007Ev%,M4/q-T{cDAD\u0001 3\u001d8Ӆ<Ajt\"\u0017\u0013\u0011@4э$H%Ί\u0005B\u0019+gl\u001fjٛ\u000e?-\u000eQ\n=\u00199ߧȓkpg.\\3D\\\f$71#\u000bg1,e|/Ab|}~\u0000\u0016\u0001\u0006\u0016̂\"\u0005\u0004FM\u0004414b\u000f\u0017C=A\u0002\u0019l\u0001[*pªdpϾg?Ƞ\"\u0001cM\fmdpk7\u001da߁!\\@Y@][E\bL\u0010A,o1:\rT\u00024V.f)ACS\u000eAs\u000e\u0017=5V;xOL\u0001O(?o\n\u0011\u0010\u001e,\u0012*l\u0011!$F\u001eb\u0004f/o\u0014Il\fErhWvngG\u0015Оc73\u0002\u0016G\u001d\u0014:([tphW\u001d!s-F\u0001Q\u0002\u0006^wM\u0004'b3\b͓ x\u0014\t2\u0018ao\u00072_\u0002MJ\u0018v(\u0011X#\u000e0bW\u001caxbhpl6wh2w#\u001b\rP1F\f\bo\u000b\u0013\u0010/ ^\"u\u0014Ce#|=s\u00140/ri#LlSʹts_&}\u001b\rw/p3\u0004\f\u001d!*s}\u0005t$\u001bKzxg[w1˗!v]ktC\u000e:szk[mmk\u000eWj\u0006kzV]gIV\r[\u0015M\u001bt\b:\\\u000fBO\u0015\u0016$ 5JbL+oJ,ICC)/VvY\"ay:g\t[ܟv\u001cai\u0007\t?zMx\u0019}-\u001e>㡽.Cw&\u0001]m\u000fqm{w'♯E^d֬\u0018QSz\u000fɫly]jyh'P=9]}GK4wV{Ju#qg|&\u001exBSFӉПHD1\u000fv(\t\u0001C\u001ejxm<oe\u0015RkQx\u0013)*~/] {n0\u0019k'{\\NbNSKНI:J\u0006\u001esW\bǪ\u001em\nS;B\u001b!󳔄\u001c^|\u000fj,Qm~xpd鏟W^)T?L\t^\u001c3Gw4s&seJA}\"Cv󓛁\u0019\bݐL\u001e^; Бn\u0007=*őI\u0016e)O\u001c\u001b4\\S3p\\C\u0013us\u001b[\u001cН7mϮ2oScec/\u0011a}a^\u000f\u0015\u0010\u001eY)},QCPӑNtċ.2\u000bgKJO譬\u0019z`HpOU_w\u000e\u001a-oV߄m]aސSiY#b\u0001\u0001g\u0006<-i.A\\D.EĢ\\/\u0014+\u001e\bTϳƃ\u00121\u0019#[c\u0015ty;-\r\u0011\u001c\u001e;K|\u001dGn)\u001e4K!k\u000b6_lY9hM-%y;\u00190^̂7\u00076o0\u0011`D\u001d\fK{\u0007~y1ϝw\ntTJѹ\tt(\u001c.\u001dS˶yF\u000f,\u0019_3bBЪaSC\u0017\u000e_2da䢢\u0005\u001b\u000bw-8\u001a7fܬW_\u0015!zf\u0011l:\bӋ\u0010\u001e2\u0003QPux9/\u0013/etrL\u000e]\u0013췖e6լ--]Y~σ\u0016\u0014deyQs/<kXeoZ\\\u0013?j\u0010ˢ\fEM)Fd{#@p>#TFtfNLPɮ+\u000e( \u0003\u0004\u0010}߆}f\u0018\u0010\u0012\u0017DTD\u0014DYa\u001f\u0004\u0006\u0018Ve\u0013P\u0016YM*X\u0002&FM0.59Ѵ1ihKs\u0003\u001f\u001f޼[ą3r\u000b\u0018{\u0017\u0005\rʏ2hnڒ۪1Sb_ǯ*Ҫ=RDna_Y9sMF\u0014\"\",MB0R߯\u001a\u000fi\u0002PQ\u0011t\t\u000b&VX)\fwj+\\ټwIl徼Tʜl~Yv<sQq;Gr/+}_~?#_\u0017\f\t\u0012\u0014IQ(MC0\n`~'4\u001bT?PL)<\u0000j0Rm\u0004\u0003|Vwﲶ\u0010nsz5;-\u000bmK\n2d\u0005<gnn(3[=蛚u?%k?9_r>)(NBQj&\nS(Xla\u0016ᮔ^\u0012;4>#80Pk\u0000=uL{Ӽ/xE}ZhB\u0011g./c$18%#p0U$MK]O=O>d(NGQb.\nw`1JD}\u0006P\u0003:}\u0000'i\u001bh`A\u0001=hcZ\u000e\bU\u001b4u\u0014\fkbMeՉV9iҊ\u001c~-FX\u0015_r'N>\u001b+\u0017+D\u001f\u00178\u0018E;\nQ\u0000\u0005B`\u000f4\u0007ԃs5ԃz{\u000e\u0002vH\u0007[C\u001e\u0001je-ZEM+\u001bc\u001b-$u))Y\u0015$TzU7\tUxm\u001c\u0013];xs\u00056pk\u0019\nbJs\u0000S\u001f\u000b5\u001aPH3@/*Ʌ.3rev.+\bk_ٶ0\u000eӤ{,wdh9\u001e(w辩K\u0010pB\u0003r_\u0007:\u0014lE\u001aX\u000bz.,^.\u001a\u0007\u0018Vô\u00036\u0000T\u0007~GK5=\u0011Z)Gv\u0013Mw[n̳>\\\u0018Q缮kD{x\u0005v\u000f;a\u0007=\u0019\"\u001azNϤB\u000b4\u0013M\u0000C\tr\u0004f\u0000h\ra]\u001d\u0001';m$gxF\u0006[b\u001bF\u000fl\u001c6_7 o\u0017\u00107䴺\u001f)\u0015\u0011AU輺\u0003ɡQA5h\u00008Az\u0014v\u0010V,\u0003Ns!e\u0014L83\t\u0013Gx*Ng\u001eLбB㐱\u001aUm\u0016\u001e\n\u001c\u000e\u0018k\u0015poo\u0018ȱ>^\u0003A\u0001wP~1?O\u0000\u0002H\u00041Łi=3\u001eLL\u0000{\u001aյ3\u001bOǨޥzZtnT!\u0003ACӷyFsh\"D3\\p\u0006-\u0016Ds8I?D\u0004M\u0000\u0003y\u0001`%6U\u0013\" l\u0001BgE\u0010\fb eJ2L^U\u0017+\u0015+fMOe?Y-k7g]ew+\u001fb\u001b\u0007\u001d\u0000G)F\u0001)O+a5\u0016\u0004X\u0006s\\3\u0006\u000e )\u0002ς@x+\u0011܊f<nǳnK.wTwU\u001eQu\u0004\r\u001cPv\u000e5l>\u0015֟btRk(j/˔?\u000b\u0010'O\u0000DT\u000bup~\u000b\t\u001c\u001e`$\u001clF\u0004򙔱xV2e\u0018\u0005ы,?xO{*PuAo_t?_\u0001#?\u0003\u0004\u0007%7j`\u000eX~\u0003|0^\b@0\u000f\u0005W\u001bANx絔Ahieޞ`og?\u0018hΓ|9g|Ht7\u0000B\u0000|\u0002\u0007{\b`\u0002'\u000e\u000b\u0006\u000bzh\u0004%h\u0003p\u001d4\u000740\u0018p\u001dpX\u0005%B\u00050H1Bo\tF\u0012ʗRQ>=\u000e\u000b\u0003X=\u0005Q[LɅ\u0015Cy+)\u0004hEˉ\bH\u0000\t#[\b\u0014!\u0000`\u001b|E~\\BAYpS\u001f\u00008RB7\u0006(\u0017\u0000ˉ\nro\t\u0010}bL\tx`B/\u0006H\u000fb\u0007\u0000͇C<\u0012hƠ3̕A#\u0001z\fjAM,H`Z&)&5t>2L$U)}~D^\fK\u0003K0hȠ\r]̝ACo\u001e\fl`\u000e\u0016rI\u0001$\u001c!\t2A%r|IN\u0010\u0016eJ\u0005\u0013vv\f:2hOZ\u0018\u00071[XB\\RJj٨B:\tBw,\\'u}GEugq\u0000S\u001dF\u0010A\u0010\"3\u0000\u0001u\f\nD\u0006PA\u0005d230\f \"\u0006,\u0004B\u0014K\u00045Z\u0012WcM\u0011=hbY-b\u000e'su߻}9(zy'V&q_ Nq\u0019\u001b\u001a%]ev^Hi\u001ehde\u0012\u001b-r8hQA:'hE\u0000\u0019\"[|}mqBLb?\u0011ǖ( zŨ\u0018-\u0001,\u0012\u001brw\u0016(\u000be}\u001c\u0007\u0019\u001cow\u0015?$kxo%\u001d7W\u001d\u0017C\u0013gҋ_w?=߷{'+E\u001d;\u001c\u000eoKQܒ(['e\u00068s21\u0001E3fNPxpz\u0010\u001b]8oW.Z\u000b?Y̬\u001b\u000bY\u0011\t\u001e0\u0007\u0005/2]\u00057\\\ng\u0005'\\e\n\u0013/p\u0014@w\u0011$@/#@oZP/^z~>+]}A&\u0002ݙ\u0015;\u0006U'Eb\u0019;w>3\u000e_q\u0005\u0013)0JƧ\u0015(:@38]z\u0014~@Iw\u0001}҆\u0001<\u00014\u0000{~ެ\u0007>;ܛs\u0015\\Z&Uٳg7\u001e\u001b'dY>=\u0006x5qχ&G<ޚ~f<p \u0019\u0003h\f=#)ͥ\u0019D\u0013l\u0002/|'3ϝ\u0000K\u0001\u0019~?&3:z\u000f\u000e3ȔA\u0007}\u0014E>\u0017#z}b\u0018!\u001b\u0003\\ \u0000\f\u0019\u000fC\ra\tZd\u0003C\u0010_E\u000by\u0016\u001d\u000fN68\u001a=qh~y\u0015&\u0003s\u001bL\u000f\u0006?ݢ?`xOn>A]gw\u0004d-Mw\u0000N\u00126]\u0014V\u001b@\u001fA\u0000`Wal-\u0000\u0006pM9\u0005G2p:ҋ},b>H\u0014\u000e.p ,ݨ?$Ev/6߹r{Z6A[K:K7\u0005]\u0010`'Q\u0016k\u0016ԱO/&\u000ef~e%<\u0012\u0007疈J\u0006GT؃q\u0001=ѱ{#4=\u0002]7n\bmtۯ\u000f6lM%YK#٪w\u000e͡hOP\u0018\u0015c8\u0003\u0000O\u00007c\u0001q>\u0003_'d$8,d\u0005_۝P=>Ұ;.AԵ$lSlEGtmMֈ6\u0016eY˩1sC9z\u0003:N\u0011(#\u000e5\u0011hW\u001dұ0\u0003\b\u001ee7\u0000gRYp\"\u000bS'g\u001967c\u001a{g7'upKJFu=1Ŭ-![ܪYĕ6/Yn\"UV\u001fѩ6̥2+yy]7Li\f:Ƣ8н}I\fڍ\u001a0۔)oS1ņ,\u0003؛m\t;s䬞l/^g\\Pu1$U)&uMCR.־:acE|sejkQ)Wjvţ3q$2\n\u001aÍxA\u001ae\r\r\u0000\u0003\u0000Z!3|gVglnG^[΢\tDY\tf\r\u0019itMuZ<ʾ$ɱHѩII'ܴI7r/Z52ĉȴI0\u0016.\u0000x82\u0007LcT\u0010e}\u0005\u0000\nAO)t\u0015X\u001d6ei<q}nYuN\"[c])\u0014g\u0017d48楯erҺ䚴O2Ӿ[F\u000byF\u001a2)3\r\u001d3SQF\u001cFa\b텑\np:z@\u000f\u0016\u0001QV́\u0012\u0011tڱJ\u0015\u0012q\r\n\u0017\u001bUbM˖&Y\u0014gZmڜzGMv+,OvK\u001c|<wUk%YY蘒m\u0005:ȣ\u001ePR\u001d9HG$hi9eJK'\u0017-K0_Zn-̝\u0015e\u0014R87\u0013vgrU\u001e2\\tE\u0004-\u0012rtd/$Q\u00068\u001eP>ʟPj=\u001aVٵuZaIBC]U(ReS*,˶I+-K\u001c\u00125;\u0015w01E]#.BdS\u000e\u001dc\nPF\u001cF\u0012\r9P\u000fg?\u0003\\N\u001b\u0000\u001aay\u00054;ʛfq\u001b\u0004\u0005+\r\rFuj,ĚqҘFYdNʊmLXŠKh\u0005LX9:RXU\u0000[<^H}\u0000ݍ\u0000\u0000\u0003kW\u000b\u0014J8\n(8g\u001a6NZ`jNmzN\u0000?f`af\u0000\u001dn\u0002M\u0018P\u0011\bEESkٺn]6eyZ(*X\n\u001a)JYY\u0012\u0018ػ\u000fہΞ;0\u001c\u000e}'MZB׋ǽ2-c$)nJ\u0018jG%W?ō'=v\u000f\u0017\u000ep\u0006UB`\u0001\u001fJ56<ցYk\u0007i3d\u001e^S`gꪉ~E+߷bz\t+\u001e\u000b\u001e|NX\u0011c.\u001atsȥձ\u0005K\u0016,i)X,1\u0005$f\u001b\u0012=baoy-~\u001eKU^\u0012\u001e\u0005\u001f)5cFi(\u001eޔmJצJG\u001bxiqoM\u0015nx$p̆;\u000b.X$lhIix^IUDnIcDܵ\u0012Z\"sVIdގ\u00075^u+7r\u0006~v\u0013'\u000fl3`Jy\u0000*qEX[Qsl$S}Fna\u001e)kֹ\u00019[\u0017V̭\u001f3ʮ؇-%$}0=5P-gť\u0001ʁi\\&T\u0001wWQX\u001d\u0018J(W\u001a\u001a\rwݣw\u0015y\u001e2df\u00193]/\u0016ӪKR\\;-]\flI6h\u0004\f)\u0003wH\u000ep\u00068_\u0005\\ɞ\u001e:\u0012\u000fP;`\u001eyVCNd\u001bQ7F׍j)3u\u0007\u0017{&կro7$\u001c<dH\u0015_{ؿF|o>1T\b(c1f`6ɝ.`2Wû\u000e\u0000ùf6h\u0018\u0001\u0003Xt$\fG<\u0006gS\u001e\u0012Fc\u0013\u0011wA\u001eUQ˴2-Z-\u0016~ˣQ;\"ĳro`R?\u001ePTY\u0007@Ƈ& c\u001dO\u0019\u0011\u0005!g\u0011|&\u0016_$#%\u001b;`?;\u0001}MCO\"\bh-ݰ}\f`;+BgDi#3~\u0005n`\u0006k/b݅\rF I\u001f\u0003'3@9=\u0002.a\u0012\u0000k[\u0018,m03\bLv^\u0018NOй\u0000^6Am?t\u0017uނvU*\u00173N5?\u0004ev\u001eSO\u0000\tHf\u0007\u0007l\u0017\u0001o\u0015|o\u001aa1\u0014:w4;\u0011pP\u0007A\u0016\u001c7 -`s̟ɹ\u00172;ك?e[V\u0015`'`\u0004\f\u0000x@7\u001fBd\u0014NqL9ć\u0002ᇡ\u001c7\\.,P.W/{rg̎\u0000\u0004\rX\u0000>\u001d̽\u0006o,v$'ehB| \u0010C\u000fG\u0012{\"$(C\u0002\u0010 i\u0012J0~O\u001cz\u0016Jclr}jO\u0012][B\u001f\u0016\u000b\t9 <9Sb(T/yf(ў:-TDA\u000e@'/R'\u001ayN[ߛ3?;nD$_\u0014}\u000e<Z$%?(1΢i>-&¸P9U^x<~4^\u000f.0#;ߟi%\u000eG\u0011\\\u0007\f)P\u0012\u001baI\u00176Re١\u0016Ԫ֏\rk괶\u000eMM6ѮAbN} :F\u0014\u00119U\u0012rꧠǕiE`_PKuf\u0019T\r:kA+i_\u0007\u000b!7!q6Tt-? \tA$b@k\"q\u0000$>\u0019ǫ\u001eP\u001cZ%vٱDX}ب]ti\u0017\u001c;֨ڹ\u000fS+\u001eD7ǈ\u0018:\u001a##ݢ{\u0001\u0001-T3$88t%|t$\u0015ˉWӵ\u000bki-Η=>wqڹ\\wYss\u001fsy6%6{6&]jH`\u0018T$>5\u0012@\u000f| q4Ay@+#\u001cWӝt[\u0006ZF⋴d\u0003ډ\u001eS5?gcb)+\r\r)\u001b\u000fy\u001fLeKgMi4\u001dHm5M'UvSUX*i\u0017IX\u0010gk<OH\t]~h/\u001dd|Ɯ\u001e\r??xc^u\u0018j_2z׬%>{YjveVc<dݕu{U۶,/˒wm\u000b\u0010#v\u000f(\u0000\u001e\u000b_\u000eaAh*HQZ͈\t}\u0005S=\u001d>5\tSհ|w\rc\u0002e\u0012my\u0004U\u0006Wo5+\ro\u0012\"\u000e\u0002\tJ\u0012bZE(\u0012 K\u0010\u0002!@k\u0013\u0000@\u0000E(\u0010޸junkn۱vvt;ad?=s9s\u001e߰NJbMH\tk\u0017\u000e)\t^\u000bك{\u0006x\u001e\u000b\f\u001fs%'\t\u001e0!\bn%\u0004&,%\u001f^JR/5|ϹR\u001a3\u0001qS\u0011։ةPG2{4!xW!s΀e$\u0014\t\u0002k\u0015\u0017g\u0010\u0013\u0002|¾Ct\u001a\u0000+J\u0011\\V卵WI*9}V8=0MT\u0004L$[ƒۘI=!CC\u0013Y=2/.H\u001f]r³\tזDظT\u001euY\u001ac繥ΕAt_\u0007f\u001bMM\u0014tf<TDz#DmZLU\u001d<lb\u000fuRܞT\u0007K1#T\u001d֡)*\b[S\bkI%\u0002p\u0011\u000e^u\u001d^oOq\u001f\u001d<╻l/Xвn38uԓ\u0007\u000ec8;{0Ko\u0014\u0005e=\u0019\u0010[s8\bϚ6,hUO\tD\rz\u00164\u0012\b\u0010\u001eE8\u0010ᷘ?d`A{.\u0015>v<\u0006gTF0즎\u0016Ї\u0018yj^]w!S[lϩ\tmn6gu\u001b4Ca\u0016ͤ&s>*\u001dIe#YBCDHYC\b\u000fB\u0000>9Ήװ{^.\u0002p!g\u000b0e\fb\t\u0014GP\u0007\u001d5&0z\nޝ,\u0002}`k~\tI_\u0015Zȭusf털\\;')Yh?P[xJ$\f\u0011 |s×jߢ7\rA\tR7\u0012\n\u0002`L\u0004RʢܺKeM\n\f\"]`Ȭ3VV\u0017s͆v~YQaIH?+)/n(|+)\u00131\"4\u0000#Uc\u0016p\u000e\u000fу.\f{F\u001f\u0006\u0004[UQyнŜX[W]_]j\b6BJj9%m|cqP4*\u001bHt+\u001brޠ5~#\u001a\u0016\u001a0\bt`\u0016\u0001\u0007aB\u000f\t8Y\u00030O0{\u000f\u001cͲny\\\u0017VQS\n(\u000f2UXEj/\u000e-\u001b\u0016唞\u000eה^dޗd\u00053MD1\u0011AJ^W%fA\u0011=X\u001c\u00014\u0007\u0002\u0005By#45Zѫ\u001b\u0019\u0015\rޥ~E@C]\u0011S_k\u000eͭif\u0004!azSz;\\Yu\u0017:\\YHUITf\"P\t_]Ax<K\u0007\u0010\r\u0012\tsЊ3hA}\u000e`o\u000fڎ\u001d(2k{5ų-'U\u001bk)\fi.gi,\u000eq@0)Li8/Jn-J&JGl!:O%<9<338߈g\n0\u0001ЏX\u000fF\u0000\t򞭔7\u0018z~Rzز|5\u0001靦 ZVjn&Ƿ\u0004q֛a2\u0002Yۿq\u001fBẍ́XEna\u0003̣\rs\rЃ4\u001d\u00010\u0003E\u0003l(\u001cx\u0019(\u0003Ѵ8zf֟ᥴ|\u0015GV\u0005&0z{C\u000ecz9{H{đ<H\bGj#6\u000f_]@v\u0007\u0001v`-\u001d}4o\u0001ZG\u0010d;Ġ\u0019\u0006c\u0014\u0001!P\u001d\u001e\u0006oh\u0000HO`#8jxg:\u0019y_A\u001c@\"f`\u001e\u000f=\u0018@\u000f\u0007]\u0000П\u0000H?\u0005p\u000bN\u000eLo\bHKQe\nځ\f<h#it|^w\u000e\u001f|\u00171Γd\td\u0004:f\u0002}\u0006ǆ,\u0000\u0003TD\u000f\u0006H&{\u0001\u0007C̼\u0000\u000banvI!ʕ@RRpevn\\\u001du]C[]3W\\\u001e[\\_0s\u001c4K7%>k\u0019C?4\n`Cz'f,@\u001c\u0005\u0010w\u0001 \n;kW j0\\\u0014-nؾ$mˉuY\r[uMeW/ة)Z\u0015x\u0011M*\u000bu]x\u0005pN\u001fA{&q\u000638\u0003;\u0007\bp\u0005;\u0012@57h\u0010~\u001bD@t[\u0000ۛ N\u0004\bD\u0003n\u0002\u0001^>pW\u0003\rBCȃz\u001b`\u0007uP\ty2cc\u0000}8\u0016ܻy\u00013itu\u001f`\u001d\u0000\u0003\u000f cO\bx\u0014\u0000\u0004>\u000e\u0015\u0012\u0007>\b\u0000ޏ\u0011;x}~\u0006<?\u0001\u001e_|\u0005\u0006\u0011^\u001fPQ]i\u001co\u0019\u0007\u0006\u001e\f0P,$\u00145\u000e1q\u0015T\b\n\"* \u0005D\u0006\u001b\u0012(\u0016Į\u000bŵ`Y#Q\u0012\tQcC\u001d\r֛\"9sp~;̼~߽\u00023Hu\u00161~\u001e}\u0002|8s\u001fȼ{\u0006¾g\u000f\u0002\u001c\u0001\u0003O\u0000Ӏ\u001c`}^\u0005oZ/頺\u0002P\\t-\u0017@n*\u0019\u000bw\u0003j\u001d\u0017g&p!pS|ƟT\u0002d'3! \u00071$v\u0016p\u0000䋀\u0015@q\u001d-5ِ\u000emf\u001d\r\u001e\bGܔ<f;p{\u001d\u0014xv\n\twN\u0001֟5\u001f\u0007'sv/3k\u0006cߦT\"-mK@MC\u001cn*)\u0010\\DZD\u001c؂I{OY2pmfl_\u0000wtW\u0001q3!!DX\u001d&Z\u00127\"^;\u000b\u0016\\0O[\u0007/\b\u001d|\u0014Dݨ\u000f\rMi6-%Q)2:N.sbl'q\u001dݙ'\u0015ۄ\u0014Hԛ\u0006R\u0006)4\"ZNŴ^QF\u0005^\u0016^\u0019oI}\u0011.҈%lz*\u0007\u0010\u0016!F4%Q:eEb\u0015+\u0005vw\u001c9'c\u000eGCzPzD#n\ff0\u0018kۡc-d\u0013a\u0015B\u00136\u0011k7\\R\u000bu!jL]jF<VoCU\u0019;J>lFຕ@\u001dCq\u001d  \\\u0016\u0017֥)\u0005\u0013bJr:ɣP-g<\r\u000f<ܗ\\;Jܖᦼ\u0005Up8^E'\t霽:\b'\u00078\u0001^v\u0010Mm <erf-\u001a7g{ܹ\u0003\u0010\u00142d0\u001ajˆ|\\2,E27¸\u0019{pGr\"\u001dw}\"\t\u0011:&,\u000e\u000f\u00197B4SCxހ\u001fy\u000fwͨj\u0012Mb[$Ꞇs#8\u0014L\\GTJ:Aqsa\u0015[z%TiP#|\nOhk+-^#o#n4¥fK`[7CwPOOg~<}>-,U)Q٬jifM~/\u001b\u0013-߿\u0012-4˩S\u001d۟*p\u0006-lQ犓|P:\u0000Ma(UOUϰfRn1MPm6MWf7\n\u001bl0Ԭ7m\\keYb\u001f׭Vh\u000b%? Z+js\u000el\u0012gXgz\u001cj\u0011\u0005~:J[EJ\u0003,6\u0005\u000ePn\bLW\r\u0018.\t\u0018)\u000elڜk\\]n^bԼfy\\d\\h,7W\u0016\u0004\b9\u0000aSs\u001f\u0004\\\f\u0001Nq+H\neu\u0015-\u001d??;w\nWtX1QcJe\u001djtȴ*\n\u0016\u0006OY\u00104K\u0017Th;7h.?~vP}^P}n#\u0019~zБ]N-:3.mK\u0019v\u0005ʺ\u0000{:+=TFiXC\u000fEqYZ\u0019\u0011X\u001a\u001e,\nS\u0017v\u001ffU\u00106z\u0017Y_L.4W\u001b:~Frǜ\r!{v\u0014ziBЏ\u000f\u0015dO\u0019%\u0002\u001f⹷\u0007\u001a7ubM7gjHwP,,ΏL떢u͌lsdvq\u0014\u0010);|a\\N\u0013\u0011wY\u0011o\f_G\b=9\u0003\u0011\u001c\u00037Y#Y.{{3~,K\u001b`E\u000f=\u0016^&W{^V\u001b\u0013ocvJ4yRp\t}ب<Bcfdm.#\"]EtɈzë\u0012\u0006ғHP)`e8p\u001f\u0003v$p\u0016(x\u000fJ\u0013O2'>R=9$A_ٍCf\t=s\rc;\u0015eH~kZL\u0015tN\u0011\u0006r\"}zpp\u001bpc-<w\u000fL\u0002x\u000ehI1\u001fkI91:oO˱\tڬd9ϗv#tȈF?4n!=yp\nAnɱ\u0006^\u0017.\u0003c\fɱBOu\u001e\u001d;yfd8\u0005X2y?܁nI6`q\u0003Y\u00035\u0006kG/gK\u001b4!=i>4CJbe\u00126%%\u001cppj\\&\b#\u0019\u0012\u0013}\u001bYI\u000b%\u0019)֘ꌉ!;_\u001a3\u0016T#R4\u0019b\fJIO\u0019d\u0007e\u001e7\t1P,,.V:,U\u0001\u0015\bH\u0005A@\u0017*`-k1X\u0005b]QQD\b#UѱrԊ:k+ڙs@wŤ,F/(GFWύ8;jSxT\u0007QWc(a\u001f>_#\u000b\u001d}xk+$|dm\u00028\u0002IZ%\u000fBN(If4-yYrR\"!1ba\\eLBUt|M,9\"\u0016V\u00186:p\fkv\n<r\b\u0015X\u000f\u0011\u0018\u001a`\u001bA\u0013'uH\u0003^4?Ut[df8#=U1Fc(}Z`\bh՜\u0004눔ŚBmHIF\u0019I\u001c\u0002\u001c']p> A\u0018>0^舶K\u001eg\u000fų\u000ef]\u001c\f޹>-\u001a)9;\u001cr=$eѹ~Ȝ\u00199a\u0016\u0011ّʰ4<M\u0015\u0017W3\u001a2\u000eO//M触\tTO\u0015v=~le\u000es۲\u0016s\u000er\u0012)y@|\nq\u0005XP8\u0018QE$󊼤&\u000bg\u0015(\u000bX\u0004(\u0003Srmj&/Y]RYrH{:\\\u0011v>$Khz:\rw=}lIV\u0003|\u0017(fYb\u001a.sFx\u000b<%!e\u00133˦\u0002˂K\u0015Q\u0016~\u0013-'-Vy\u0014[M(Yc^IW\u0001ؒSڎ]*lH!)\u00106=\u001cg\u000e\u000e\u0006;ؖm^\u0006!I.I}*$\bBP#\u0002 `hKWjlҪP3yU\u000b\u0015UeXxU\u0016YRzVnQyTWW+>\u0016j\na^c\u0003{s\u00132|\u0005s@鎭\u0000W\u0003U[`\u0006\r|7q8P3\u001ekH̐\tY I\u0019{6+1n2w55w1lmxk:VXX\\s;\u0002}FZ:K+* <\u001am\u0002o\u0001ԪYG]׏[\u0007\\?\u0001Mx\u0014,\u0019i+q1K6HVȆjdCL\u0006N\u00062\u001bT+䃶^\u00037τ={\u001dtW\u0005\nM\u0000Do\u0004fm\u0006\u0002\u0013\u0002\u0001]2\fkPO\r\u0006\f3\u0000C\u001e\u0018w\u0002\u0006ǀPosc\u001a6.C}$NK\u001cE%q\\[H\u001dv\tl#z\u001d\u0002,z\u0017\u001ba\u0002\u0002\r˞u?0 \u001c&5M:0h`<\u001ec=\u0016F`Ӓ\u0003rXBz\\U3X\u001d\u0015>\"$d382;s\u000b`. \u001100(л\u0005в]:!e\n\u0016mv0o\rE\u00102\nN?!k\u0000vN}'5\u0001) i{M'܋\u000eH\u0001DrA..\u000e\u0004i\u0003T\u001d\u0005\u000f\u001a5/\u001eZ\\\u001f\u0010\u0002/\u0017_\\Jy\u0019C2h/`\u0004pB/뭐yO33OW:\u0003\u0018赦;X_\u0012*8kx!v\u0004\u0006\u00027\\[cی@77,]N)\u0015KOgͣ\u000fp\u000f4\u0003\u0006x0mځ=jz\u0015/ȏ\u0006I~\"r\u0004~T\u000f<\u0007<\u0019\u000e<EW\u001ey \u000b~\u0001\nn:-ZU\u0015\u001bC@(4nOyi<s\tP+p%\u0003<!_\u0015\u001cOEl\ts\"\u00126,q\u0017q \u0010U/`ŷ\u0010Vo!,!d|\r\u0018EƑi\u0003\u0012CRɇ5H6\u0013\u0013I#89C\u0003\"?\u001faC5{\\Uo\bE_f\u0000\u0019AƐ)$'$\u00142RI֓s\u0005k8\u0015Ё,\u0013&1x\u0006n\u0003g.\bz̅;&d6#i99J`5=l\u001e3\u001d|n\u00166?yy\r\b\u0003:-а&Ē(X\u0013ȗ'H\u0014eU@rzYK-li`\u0005\u000eq\u0015q\nG\u0006#\u000e֌C\u0002cŚ(CXxB3\f<=i,)A\b?p]Vk*\u0014Wpl'.}VwL.t??\u0012h\u00148|kD_X2\u000e\u0005=\u0006\u001b\u000e/#q_=\u000eݪ\f\u000feU\u0006.\u0018T+qV\u001aUFtz;:qR݂6NlE#Ь\u0011%\u0012\fZ8\u0019\u0013;\t?i\u0007;z&\u0000gѩ]\u000e]\u0012N2>\u001f/qC.נ(++7&F\u0005\b,(,ȲܖEv\u0005vrY˂+\u000b\u0002\u000b\"\b.\u0004\u0014!xC\u0011Eh&Fmc6If:i:MSM[\u001bvڴ}z\u001c<_9y\u001f>|e\f>X6\u0005e\u00177\u0007pmŕOK\b\\@\u001f$\u000bd\u001dXqu,xF\bVe\u0015\n*\u0015U-]\u000f)[kkݵMp=\u0003\u0004{aj1d\u0014r\u0018r\u0010r_w~ko7CfC\t$r\"CkK\u0002Gm\u0014o\u001cWk\u0005qKp/4\fn\u001b\u001bRZ\u001e.GRZpP\u00159E;}VC)g\u0014~֬(b}Bq}Lq==\u0015WΑHH둄CH\u0004\u0010W\fׇG1\u00007r}\u0014G͛`!:\u0011)3aNi(-)>)wf\u001di^Q\u0010g2z{88w<z7\u001fU~\u001fQ~?\u0018_\u0018\u001f\\_\u00026\u001a\u0002|f~FdܳpύJ\f\u0003\u000bV\b8\ti0`\u0013dB\u0005pB\r{\\\u0019Srn!7\u001c\u000fO\u0007\f\t\u0006\n}\u001f\tT{TDгD\u0000\u000eق@\u001czN\r?\u001d\u0016\u0006\u00171D\u0001Nz\u0019N$\u001b\u001a%L$S\u0013)YXJ>}Hca\rkl!M\u001dw07ߟWЧ>(U\u001f\tQϊ귙.=C\u0015ӞOQ[2\t$\u0013\b<%b޿{?@ωls\u000ec9ʅ49Lf\u0004øv33\u0013\f@f\u000ekזs5ތF~OF-L/jO\u0010J[>})iNؕN\u0018D\u0004\"BW\u0012O_z\u0005p\u0013}b\u001e0L\n&tR\u0018ݱ\u001ap@\u001fGt>ի/`wg[]6^\u000eg@ێ֬@wV?Ӓ\u0017t3Fݼ^wKZVw#\u0011ơ#\"$9\u0013p\u001c7\u0000\\G߷`=\u0000`\nci`@J\u00180C1\u0016\u0018)Q0󊸞<+ߝ[\u001bВ\u0012rE\r9{NÈa\u0018ޒW\u0019ޕ\rm'2H\u00101D\u0004>\u001bO1\u0007w\u0000W9K\u0000(D}7\u001f\b\nA)\fiN3X&\u0003{m.,5\u0016V\u0005\u00174\b\nZE5=!8)\u001aAe_\u0006\u001a\u001aH\bSGD\u0003瘃[xqz\u0013\u0014~\\\u0007\u0007__\u0000z_Β\u0010hlViI]lvcI>Yb9Jl\u00015N-,+̃RaYLPZIXn6\u0011iH\u0010;\u0003\r\\>b\u000e<aN<]&\u0007O\u001ap[#ٺjjhgTW\u0014րrETZ)..\u001d-Bˬ<r%h\u0018h!\u0012\"Ab\u0014\u0014\u00133:_Cy\u001b~\u000bρJXڬ,pۤl\u00114V:rT'UZ*mrV-(5\u0005+w3\u0005$F,zRn.֟\"+\u0014\u0018\t=g|}w\u0007뿈swj\u0000 m\u0018O\u000b\f8\u001d+n=T;L4.m+\u00149,<\u001ePP ̫rjk2]%'ȟd*\"ɬ\"L;atv\"ٖx}w\u0013W΋u\u001eDQ9@ZzW\u0010\b\nrW\u0014\u00126tBW\u001e;d\u0019\u0002\u001bB]\u001eaX0#ImX4ܗj(Iq\u0012qJ\u001daR(\u0007w1\u0007}\u001c\t\u0011\u001dio{\u000b\u001e7\u000f,dP*=P艁|v*ϓAx,}k!;Z\u0012+Ը\u0002if<$\u001f1-\u0011%6\u0013Q\u0004nF\u0012w1\u0007\u0006s?FߋV\u001bq#\u0001:(0v2۵\u001crn\u001dխ2utHyK\u001a6qwuU]\u0003&\u0005ۺ\tc\bc;\u00160\bcۈ`\u00057\u0016γ\u001eqGv#M\u0000\u000e\u00060\u0002\u0004/\bWC/\u001cR|J\u0012A=N%\rDV*Xq>';(}-ügyQۼxQ}z\t?j\u000fXxc^.=.vv)j\u0003d\u000e\u0002\u000fҐ0@+\u0010w(\u0018\u001dRV, Ư\\2ZBm\u001a6\u0015^V\u001e{\u000e\u0012N\u0010r\u0005\u00171糨{\u000f{\u0011i'҈ߕ>\u0001j@k\u0019\u0005\u0000<Ƀȣ\u0012P\u001c]\u000e\u0011S!\u0010>\u0015\t\u001bkjX?7vy@E}eaO\u001f\u0006p}P\u0004,\u0004\t\n(q]ՠƂ\u0006\bADET,\u0018NPX\u001d\u0018h\u0004\u001d{,G$1qu]\u0013{X\u0012ۏ{\u001d@x\u0004gygΑڛ%_>`Q2l]f(\u00102C\u001b/)멷4y赌A.| b38\u0003\u0016\u0003~Z9P\trx\u0007ë;<+\"Q1\u0004\u0015\u001fír\u0012\\\\\u0015p4é\u0006Up,\u00022!9V3y\u001fLYǻH?\u0001\u0004RO\t\u0010VF*\u0003gS݀c\u001aju#\u001d`W\u001bDak2\u001461ZCcIڲ\u0001*K%\\@]+!\u0002=\u0014b\u001e\u0019ԝC݉\u001dEݸr6ԯ\u0005\u0002\u000e_\u0003ȠAV\u0000\u0003h\u0003\u000e\u0007\u00116#G\u001c\u0003deYPV:\rS^\r\u000b\u0005\u0002jO-\u0005Pw\u0018m\u0018.\u0001߃k=?\u0002\u001c\u0003CIl3\u000eYw\u00018ߕ\u0010\u001bF6e\u0017ل\\dikbR5љ\u001d&+\"CV!V`z\u0005\u0001m\u0002DQ7\u001b\u0000\u001f+|\u001c;\rR\u0002@.\u001cWtll]>\r\u000e\b7 Lb\u0011\u0002|II}g'&w!h!y6\u001e\u0007\u0018N(\u001bF{;Q׋\u0000]# D\u001fuOrLh\u0016v/C?[7\u0019lO\u000b1yI#_ҐW\u0016\u001fh\u0000\u001cv\u0012\b<\u0003xռmּE\u0011\u0017xD3\u001a\u001a=\u0005桍i\u0017<,\b`\u0005!\u0018Pq\u0005k\u000f6@k\u0004\u0010\u0012A\u0006?\t$#d\u0019YM6\u0002RDJvRK!u/+~xI!쨭Pp\u0005W;\u0019H32$t䐍d\u0013ur\n.\u000f\u00182i.\u001e'WG\u0007\u000bƙ5\u000fH?2|B>N\"u9Rk\u0006C:k%2SVo\u0003>~\u0013C\u0005G7A8RWm\u0007!\nGz\u0018jXjMf\u001a|tX@Tjd\u000es\"@\u0019#\u000b~I\rp'\u00164q7F\u001f \\hK_h\u0019\u0013ZG9&ۇGx}Lԙ0&\u0018H\u0015e%rM8O_\u0005S\t8tZ%#R\u00069\u0005SThgG8\u0017\u000fA'5qU\u001a˲h%|:b\u0011N+qJ\u0002'98̃UYê\n4jpHՀ&|W2c\u0004jAxQeN\u0011W^/'\u0015\u00157~}\u001f6}pV7\u0018lGX\u001c3`?\u000f\u0017`8n\u0015sW\u0019u2:AC=84a\u0003T9F@Y\u001bBz7ˈn.yJ\\C;N;tQw\u001e\u0003ð\u0013ԹG\u0014T{$a\u0002L\u000e敃*|Tx\u0015{\u0007J\u000f\u001c\u0018HfKi\nIA3\u0006!!Z=k,\u0017\t`;孁\u0011\u0007Pg} l\u001bʎcPR(bdl\tH\u0002VJ\r\u0000T\u0018X)\u0007Iy'e~LY֐՝F\u0004\u0002R\u0006K0\u00043O\u0017\u0019v@ol\u001c=P\u00124\u0000[\u001bGas8\u0014\u0006OgHy!s!)\r!!9!\u00055!U!쐣eO\u0015KC\"#TțY?]\u00038iG,=c~3XP7l\u0016\ba(\b<`\u001aG`q8AZc\"[eLe\u001b\u0017ʳƕLFEq2ݸS^\u001a~E\u0012X(\\(I\u000e\u0017\u0016<\t\u0013ԝn_>|r8n\u0007\u0002U\t=+\u0014L\u0011XcFie\u001a%-7e&2Lt\\E)EjZL1S-0\u0017FlSϏ8gj1=6\t,P\u0011e\u000b\u0011<W{\u0007>s :W|j\n{Kھ>X\u0015\u0019\u001eX?\n\u0019#e&\u00125E\u001c\\\u0010\u0017\u0013F3+Pydvf>6#\u001fhE\t(\u001a)Tm(O\u001f|ǧJx\u0014\r\u0006bca@OdFwƒ0XiQGdcNR̎L\u0019NNγ\u0012]\u001cmMV71.!Fh\u0013*a`+\"\u0018\u0007}cc\u001cbuX2\u0015qH\u0019\r&̏\u001f(͍͎\u001f)K\u001f#\u0019\"q4!SR4Vh\u0013uGEyafav\r.D&葨(((\"\u00030\f̌\r(\b\u0013\bqh]\u0010\\\u0012Q0.\u0011\u001d\u0013c\u0012Mh\u00184rZ=&Ic\\kmm&A;8}}yIirj\u001dIjI4j{'JxU?3\u0007~F\u0007[6a\u0012>\u0019(Ѡ\u001f\u0010Ԧ\u0010*CPnH\u0012\u0016\u0019\ft$=WV^\u001cPVOW5\u001d\u0016Mߡ\u001fYgMYHc֋*^TZRES.q\u001fa\u000eQ\u0005ؑ\u0005lZVu\u001bd\bD9TfCi*L\u0005iPlJ\u0014N]Y(_Yeƕjq&˸KΘqZqC&#CT\u0019\rҏ}mf`69x%RuԘ\u0004TfbK0ʬcQbBA<!?;Ek͔:92)϶\u0005-5Jeh^1۵ifNoPjM5g*ԛDeITr\u0014,ځV\u001bq#SüTpM9:\u0014ۆ\u001e\nc\u0012\u001cӱ1W;$9\u000eJ͎\\y\u0015aV\u001aUz:uUM66vUP-\u0012Ee\t^z\u0019o!c.*ZzR,U#/o\u0010\u0016\u001c4X\u0005s`rI,鐥9\u0001\rʄ<j~vu|\u0001M\\IrY\u0013@\u001dPT\u0011<xʟ1.'\u0003`\u0019!<NQ\u0018@X#$\f&\u0014\u0018]0\tid!e$r\u0002قry|I\"d2xjv\u0013Yߨf\u0015S*\u00141\u0005\t>>dbJx\u001ey\u0016h\u0007I%){\u000ers\u0000~0\u000fAZy(R+R\u00119HL\u0010\u0016T\u000b\u0016I\\E4L6-U\u0014\u0010]ު^W\u0019Y>J\u0011\"r,\u0013\u0003J\u0013B2`y)PK8]LWA߳\u0004H^FB@̯}\u001ea瞂hĺ0ǝ\"ĸ3ndX\u0012宖Ns/nO}M><<<ZG,!U|w\u0003K\u0006RECZ ާA!n\u001c\u0019&` ҳ\u0000Sy_X)\u001e\u0010\u0010&z\u001a%\u0013<=\u001d\u0017<H<a?H\u001aDiˤWdT<p/.$H.L6\u0003XEŹh\u000eƤјf\"Dbw\u000e{\u0013׈0\u0003c\u0018\u0013B^a]\u0018}K\bY#^\u0018Zh\"DI*ލ/\u0003\u0017\u0014=5X\u000e7\u0001k\u00017҃h\u0011y Fm\u001ec\u0010:\u0011#Z#|[,kK639-\u0018\tCló[|\u0018\u0013\u0004FP(\u0004m\"\u001bɆ>P{\n\t~\u0019\u0001u\u001d@\u00177\u0003\u0013hYGo\u0007\u000b\bڥŠ\u0001$\u0018\u0003;Fc@G8\u0002;#\\<өG\u001c]\n\u0006\t<\u0005M\rhw=n\b];G;65\u0003+\u0014P\u0007`\u00130^\u0001ہN`\u001e`~\fj\u0016C\u0003\u0010p(\u0018C!EAe\u0003aqC1}\u0002\u0013C\"?\f6je6ր\u0004v\u0003\u00131.Ao\u00028]@8B{|\u0010a#hB>n~psyn\u0016u\u0011\u0017󘈿+2\u00077ԝXg\u001c\u0002&Qs459=@{\u0002\u0004?0#\tpZM3lF{p3,?gyٟ!a{(pm>/\u001cд.d/`=\u001a\u001c\u0001fC70\u0004ԧ\u0001'\u0013J\u000e\"\u0010H5K\\\u0015~¿ƍ\tb^?EnD|B]\u0007k4\u001c\u0006R\u001dCI\u001dX=\n(z%-B\u001bR&kOm\u001a\u0001?r\u001dw\u0018޸\u0012p0\u000f>&\u0007?<a\u0001\u000f\b;\u0006QWw\u000e}I~%\u0004(\b\u0002Ӌ\\C\r9\u0011Y\u001bMFM\u0013^\"\u000fċ\fXdO\u0010eD\u001d$H$'\u0019NJH\u0015#I3YOZ+'qp\u000ewS\u001e\u001f!\u0010\u001c\r\"A$!%$X,\"KI\u0003YIp\r\u0019mw\u0007\u001e`7\u000bp\u0014wp:=L\r\u0013\u001fQC@\u0013E8&\tx\u001c:\u0015pS8Vg'y},q\u0003gp\u001d*q3|˙z:t̅o\fd,J͹\"Z\u0016Q\u001aUx\u0011.\u0016ik9W\u000bvn\u000e|\u0003S8<F8Yv\u0007Eyq^\u000b] [Q@PN\u0017Ac9V؅\u0005v9vZe9\u0017 'x\u0013bzV\u0019,xhĚX4Sg:i$f:}Emdg}?<=?5T-u'@DOk%k)\"d>62\u001aj4\u0017hG\u000f\u0019\u0007LAIþx\u001bq\u00071GxP\u0014R*Ǎ+GsMԝ\u001aPS20l<@\u0011\u001c?F-5Aո\u001e\u001e޸5Zx\u001dWXwq+0\"<⢤MT8UK\u0003<yX>Ʊs\u000e\u000bqW\\\f%u\u0012W\u00157hZpYӉQ\u001e\\ňv\f\u000e¸C8?\f΍3\u001cn&<ĉId\u0015GoN~\u0000:G\u001f\u0001\tӊx0n\u0002\u000611\u001aW&%atr\u0016F&0-\u0005\u000b\u001e_\u0017NI~\u001c\u0015G\u000fH)\u001c\n\u0001\u000e\u0006\u0010\u0007^\u001d\u0002?`ST!\b|:l\u0016G\u001c<vq2k\u0018\r\u0017p>0\u000e\u001c\u001cV#ӝ84\u0006ߛш\u00033۱j웹\tCv`p\u0010>ݳ10\u0016v%%U'8V?\t_LHjȹ\u001c{<\u001e3&̬)8>'\b$r&cp\u0003{\u0016T`:\f\u00045cgP'v\u0004ö~ak\u001e?\u0017|^\r.l\n>/څCք|/\u001f@\u0007܎\u0003FcyG9\u0016\u0000\u00162\u0017\u001d\u0016]ұcq6-.Rl\u000ew/#\t\u001bû\r\u0011º]bO~qui;\u0015\u0019X\\\u0019/=R}F4\u0010XLk6c9\u0018\u0003\u001d\u0018\fb r&G/Ė\u0018\u001d$W|ٱVW.jձ*]إ[/vI\u001d!-\u001a;*ޕb$7SjU\u0010=c\u0019;\u00063Ҙ?\u0007o\u0003v$/޸\u0005ذ,\n\u0012Xn}\u000e+Ra%=W.H\tƄ'N\u0018Q?RjjWr^\\\tE\u001c\u0011kp4ri\u000eӊ\r2)I~<'yN\u000eGWJ\u001cV\u001aRn0͐/\u001a\u001cBBl4ԉ\u001eC6\frUe8T\u001a.j*\fw4eߓ(N*;ST<Uڍfրg_&k\r\u001at3m6:2BСŘ&r4\u0018s\u0005Hp\u001bbF66IUN¸Q.3TJ3\u000ejJ2q\u0018o؍\u000f5vߕ\fU~J*ٟD2j^\u0000'\b91M52XEk\f4g\u0005\u0014\rY\u000f9\u001dll\u0013+\nsXnHNs\\bZ8Lەb~MO馏[\u001fKդ*,U&5Sl#\u00165/\u0003Gi763+w.֧<\t\r9SG%\u0002չMEe^P/8bInuKŹmranbݪX-4y3>\u0016u\u001c˯\u0017\u001c\u0018lU\u001a'\rj^,^\u000fh71nF\u001bȘy\u0013P\"\\ֹ-B-\u0016΂d\u0014,Ǌ\u0002`/(\u0012\nbAAdHyղ֯dۆ4fi,5L}2dZU%3_S11׫=W̽H;\u0010Xx:\u0019O#c㳪\u0017Ep\u0016FIB81(rБ-\u001c6!Q\"ګ\u001c{dwY>ey&&\rMCMZ\u0013MZ\u0015r\u0018\u00054;ej\\\u0001\u0015A+XEq\f\u0014\u0006挄\u00192\u0003r˲S/d\u0005SYlN)ݹINuVR55I\u000f4)I%)RCm|Gi\u0007J%\u0001i\"ߋ\u0000k$UNj\u001er\u0016!ۥɕ,\u0011]\u0016\u0018]EBLHu\u0014W ]\u0003򲪣r|ը\u0012纯UUT\nU+Wg`/\u0017*\u001f!mMVXE]\rk#\u001fݳ\u000eFz}\u0014IEǄd\u0015\u0012A\u0011yZ8Z1~\u0014SIOrYSZU!ϸ\\R㻤Ž@H5\u001d5\u0006 IFJd$LEb<[ðu\t⽉f`ׂX.\u0012o\u0010m\u0012Bw{P\f\u000e޻bh'bh*6FU\f{\b\u001f'\u000eZa\u0007'|/^@\u0001,\u001c%#k&\u0016 jU8\"W-EĪdĢn+ºKuG|qX\bYĖ,$&niTUk_p\n\u0013\"\u0012$\u0012\u0012\u0015D\u0012ԒPJ2\u0019UcLUjj:Jϕ:Gr#y<꒕Ȭ\fg\u0015\u001a*]FhI#tM#44B3`i\tM7-a\u000b*tfp\u0016Y\rSa*gC~mw\u0014@^dQbOE*<7Ps#)7Fay\n믐\n\u001f\n̟\u000ej_v;\u0014\\\u0001y)`jc\u001am\u0017Av\u00033y\u001ff.\u0012f\u0002\u0013N\u00065`={e!/b򥈥Rpq\u0013/R\u0012?-\tT@iڔʿ4A~\u0003kS>jmVҾU^#_WOjY\u0016Q\u0004\u001ax?Vv&g\u0011\u0010R\\)\u0000\"K/\u0002ʥk%O<\u001c\u001d\bXp1P\u001com$5qQ cXFTޕe)\nSM4PIYhx>\u000f]B\rI\u0012ϕR\u001a)51JjIb۶\u001621\foc\u0000\u000e\u0002R\r\u000fP\r\rRCk(b\rWo\u0007vm7)\u001c\u0006\n\tĚ\u0006zrjE\u0003\roTK;$]++>v\u0003\u000f\u001e\u001a۽\fc\u001f~ǏZZ\u001a}-ͥbb\u0000j\u000fW#0G\u001ci%oFɺUh$/5?(\u0019G\t~\u001cŏc0\b$~b\u00009EQ:\u0004\b\u000e_|F^\u0005}\u0019I;l\u000b5wKa\u000bMchJV\u00160\u0000\u0019E:\\:Ǣt%B{\u000b\u0006KuL/\u0000gd\u0012s2y\u001e4\b]!\u0011T=AOI.\u001b?\u0000\u0013\u0012H+XMXPܥ\u0016\u001dq>gA*K\u0004\u0004c\u001bzM#c/v?>>~\u0016_zNo:pt\u001b\u000fp\u000f0\u001fJSjc \f&C0&51II1/\u0012\u001bg\u001dה_\u0010\u0001q0\u0000ބ10\u0005f\u001cX\bP\u0004+`\r-\u0013\u00176ПPOls\u001e&\\wV6\u0010\u0006=\u001f\f\u00110\u0011a&~j\t[Z=\u0006W^u_:Rt\u0005zm\u0016e\u000f.\u00054+k4xƠF\n)O</~\u0001vV\u0012W%qmwڡkڧ\u0018:G6|\"gֿl\"\\N\u001f:u[זjD+D1x4bj6\u0002plVcw\u001dvR\u000f\u0019+4gSX>\tίu/`@hȉ+\u0018f7r\u0016\u0000}!>\u0012w7%,gҹYn!Kkt\u001cv>\u001d\t<Z\u001fäŘ\r><r\rjrsqQA</::o1\fOE%\u000f=\u001ahG#\u0017{P-^9\u0011ح=څ'\u001fpS\u001a[m/`zu܂Ϋߔ\\\"\u000eD\u0011UG*:8o1\u0016h$M\tXN>KP_\r٤4*3ZzC\u000eǪljjm3S\u0015/`R\u001e\r_Z\u001f-\nN\u0013\u000e\u001a!\u0012Mho\u001bn6\\[\u0016b6R\\wϑc*=Vc=?jCZyF+n{>@\u0011<iGK\r\u0015i\u0007O)rN϶\nזѻZ.GZzִrZ3]+}fk\u0002}Ϯb?jԿV\u0005r\u0003(E\th!¤ϣxz\u001dήA{ցgկ6h*\u0002kux/{*0L\u001dFkYǉZ1I\u0005Z\u0012\u001c\u0006\u0015+'B[0x\u0007Լk\f}P\u001c\u000f~+OQ\u000f\u0000f×u6PyV\u0004WIHRaZi:\u000fZ\u0014>NZ\u0010\u00115/bF\u0016*#r#7\u0019i{YQǍԨ+ƌG(HyNd\u00037x\u001cg{=Ê6Wvg\"7\u0011\u001e*l.a\u001an\tZЭ\u000f跔\u0019=Js'jvLbR53f\u001ag̈YaT\u00192c?5b/\u0019Sc\u001f\u001aSbM#I̯\\%gˌ\\}2|))enE1>\u001f\u001b=*U)@=Da\u001d)fn$[\u0018I\u001ccuhuX&L;by7q\u000f3qFzWhD{o͌\u001d\tqڽ]iVK\u001d4+>B\t=5#>\u00034`%ۆ)6ZSmD{d[1ѶИ`+UXj,m\\Fλݳ\r1g$\u0005b>\u001e\u0001ã0{\u0011\tKH\u0010e\u0005\fK\"\b\u0004\u0002I&L2IfLB&$$C\b!\u0006\u0012\b\"ITBR,\u0014\t@\u0014!(\u0015}cV\u0016Vc]\nB_H\u001fg3s9|/>X$E\rҐ\u0010cU8E5IsT@U\u000e-wdґ\nG@2#Xa:\u0018Ŏ;BGYn;[ycq9.YK\u001c$\u001f_mq\u000eg\u0005.j]L,kc\racSUU\r\nTE<',ݩӣ\u0012gFsQ3Lw[,q+'+yN+fNj?g8IK+Mu\u001bJ,Ty]\u0013\u0014̈Qif3\u0017ȝ;K\u0005nEFk\\mǽvo\u000f[Vr_\\GF\u00069Ʊ\u001c\u0002lMԀxꉧ,'r`fE8;J9SU3GK=\u000bqɔϛ\\o@^o1Mfg<`9={4cVy+󱕒c}fCV?8+\u0016/\u0013n-xBRgT7\\c_\u0012-or}'w*Q?_n0\u0006#b&w[I^+Z\\xm&\u000e\u0013}$=\u0015o%PF</ot\u000b]\u0010̂\u0004e\u0004R\nd)=WZX)#H\n\u0003̈́.sA\u0019\u001fx\u000e>0\u000b7f|>\u0002x\u000f\u0016\u0016\u001fhA\u001d,B\u001deVVQ2#*RzTVj|&)ԥ`\u0012\u0001-\nV(!x l\u000fc\r4o\u000e\u001e2cؒbی-͸\"ۈ+c/bO~o&j`\u0019<HiX\u00161JEӕP\u0019\tZ\u0010JU|([C\u001b\nJņn3ڍ١\u0007Y\u0019\u0019\u001a3\u0001l1tzJٓЂ\u001aR}eeWJ>C5o(]\u0019k(FӜUʥ\u001bWj֪\"ͬFnԴnM=ɵ(zۚ\\16&gJm<\u000eh|Pu\u0000<ش\u0015\u000eZՃ4>\\3\u001a\ti\u001f7ѴxMmthJc\u001buC2Mjӄ6ii|qkzC\u001bz[Qk`mD#hl#Y\u0002y&\u0016-\u0016)\u001etS4\u001d\u0012<D\u0013[\"4eo\u0018oIZ\u0017jlkƴzu]kmu\u001aնYm{\u0014FWDlIIO\u000fݷ\nߋ^\u001dTB:^ZVŲNoA\u0014\u0011\u000f\u001eȎ\b\u0018Ή\u0010XX\u0011.\rӰ\n\rlPX&]ݹC;誎3\u001a~AWo5nlol$ϵYPFu+kYkf`Wѿ\u0017\u000fX\u001a5L\"5k̮I288\u0000ywYh$M][\u0001S\r\r\u001b\u0001\u0007λ\u0019zs)9[\rMLtH㱉T\n\u0014K2v\u000fW\u0019\u0019C3\u0006d//`N'\u000b@~:s\u001d5PBwK)\u0006w\u0016\u001fDҨ\u001ei\u0018\u0003pЂ\u001cvq8\u001e\u001d'\u001d&#aˁeaR#$p\u0010Kȵ\u0001*\b5o3s@\u0016;\\'E\u001fQ?*\rE7p\f~ۇ)=I=ӈ?5Jzz,0቙ٳ\u001c\u0016K'\u001d'x5Wh+-\"lMg\u0012x4#JÞ̧<\u0001'9=?Wь\r1\u001f9 e2q8ρ\n\u001bU&. רk\u0017[mH}+iޯ\u0018p#\f;9<\u0011K2\u0002M\u0007f]j>s!&\u0002E\u001c:TKXܗ\u001e.S\fp8.jkaR\u00023н\u0014AWe\u0017\u00064ހRbc/\bL>e~>g|A\u000e`\u0002\u0014\u0003fNm\u0017\u001dh\u00185@8\nq\fP\u0000`%:X\u000f\u0019\u000e>qBx_]}%~1%\u0000ޅ&V\u0000#\u0007\u00047B\u0002\u0007%\u0010B\u001870v\u0007ޯեh>g^}~$%zE\u001fs\u0011`@}x\u0013ËWb\u0018\u0001Ca\bA\u0004DA\f\u0003\u0007z,EL\nF\u0005e;\u0018{\u0003v0-[nrt#Lq\u001bjh\u00058\u0003Чm\u0006>Gu\u0017lꖀiEP0'oeX׈<qL\u001c/\u0013YY=-s\\yL\u0019ǿoΆ\u0006\u0002$@Ä!\\0`\r\u0006cm\f6\u0018laCH %\u00079HPҜm\u0012%Ҵ94R4G\u001b֩iVȦ-4e/\tҚ')'tpgS\u000fxx\fƬZ\u001aQN\u0015\u001d0]s?\u001bu\u001d]\fW4#={ԌOJ5*:t0#4qVN|H\u001f\u001f5*}\\.I\\\\\u0019΋xN.y^s\\٧'y\u0005\u00003\u0005\u001e1n\u001eS4[BxS+k)\u001aj9\u00186.jRc\u001a\u001bsNui$\u001ec\\Q4W9sf92\u0013^o\u001f:\u0011\t|\u0014skL*\u000en45\u001a9\n+9qJxpBq|N\u001f^3sqL͛yphyLο\u0003\u000b`\u000b_ao'L\u00171u\u00184trX>?L\u00170?\u0016g\u0016pj\u0002JU^lb\u001b\u000ePx;\u000ew@x\b#F7b;&\"awQ\\r\u000e㑗#\u000eG~-QXM7gQ;O-SQp2\"\u0012G#\u0013q$*\u0003q`i9-2\u000bv/kΘV#\u0017cak\u00186X\u0011.\u001d#/a8\u00166\u001c\u0012`\u0019\u0012Cj~c>11\u0004\u0014_Cqy,$Ȱ31\u0007;V\u0014cJlYi$+6%90H\u001fAO\u0019PK\u0018L=PI\u0004SA&ze?Z#tI\b %UoW9R2\u0006y\u001bWP~Xa\u000fJy\u0001;RU496*pz9֧1ڌv\fd\u0011?\u0017}ѓ\u0015ݙ\u0011\u001fCM7!\u001cY'KG=2%|'>KL!rl/碗͙s1\u0011\r\u0004\fec [\u0012Do\u0001=9\rV8\u0010PxWtS9\u000e\u0018ڕ{QNUy^\u001f\u001f\tg#?¡\u00143m>\u0017K\u0013,;&Y\u0002\u0017gɸl`\\\u0006\u0015\b*cїy\b\u0017_΂j\n([\nOa\u0017Z\u000bp6¥\u0005jJ4\tꚰ>\u0013ªzB$a-@\u0012Sf\u00054(cCO#\t1.aV-EWQ\u0012|řh/΃D*\u001a.m\u0005\u0003^4aS$E\b0 \u0016u3J$a\"?JE>Nśi^\u0019t!:Q%,\u001dr\u0005\\\u0015pVhЬE\u001ev\u00036\u0017VZk`n\u0017&AaԾ&\fE\u0013QH\u00195咸Oͫz4KI='=\u0005駛q\u0011f\u001eܚ%piQ)CSU6UhԕêӣAgF\u000e\u0015&}\u0000F \fF@N\u0013Z\u0003OIB[%\u0019*%qX\u0002\u001f'{j\u0001\u001f\u001f}񻋿UZLXj`-P:\u0011FC#j\r-1tBo\fAg\u001c\u0013}Bc<!ʍ2\u001d6F\r\u0010ZIk$Q6C$nQm\u0006C2J_K}vo0R\u0017\rS\n\u0018M0\u00145\u0017Ƭ\\\u000b\u001eU\u0016'*-\u001dXQn\u0019EeBZb;PY~%T\u0013IL({:\u0002ۢ&`\u0007aۊ^q\u00075,\u000bQ[\u001fx2TYQX\u0000mc\u00194zL(5Amփb0T](\u001d\u0015D#R(\u001b\u001f\u000bU\u0012\rKz\u00052IA\u0012 mFV\u001clt69\u0006IP;2PPQb\u0016EN\u0003TF\u00148w\u0005Z\u000fk\u001c9Wz\u0003Y~\u0001o;$d5K\"%qeI2AFO|\u001b쀡}\u0017K\u0016\u001d\u0006Uk\u0014\n[\u0013P&C~[6\nA#c\u001a\u0013^\u001f\u0001dza0Vy#{\u00032 \u00056\ti-aU-8YO\u0012\u000fiɞm@o>r:#\u0019w#K\f\u0011V5H\u001bA\u0016 5Їf$\u0005&\"p\u0016\u000f|\u0004wHdꓰb\u000e\t|\f.&\u001c7P[\u000e\u0014M`븪o\u0011R#\u001f\u0014$\u000532\u0015R$\u0006uH\bY\u0010\u001fjA\\\u001b\u0011,\u000biD\"*cD\u0005AtH8M\u001eEN\u001cLm]'{\u0000\u0016LwX\u0015ǿ *\u0010\u0001\u0015\u0010p\u0000ʐ%Dq\u0004E\u0014\u0017\bׁ\u0010\u0014\u0011\f/B\u001cE\u001c\u001byj\u001cMl`֓&8֪16Mn?\u0017H}~~=~\u0005_Y⦎%(\t)Dn(/WS:`ʖ@Φ%r2mKʡ\u001c|\u00142Lh\u0015L\u0002cx, W<$Rk\u00113`\\r2#\u0007s͡jgQ[ ٙek,\u001b3ƛ\u0006vs\u0018Z+\u0019*P\u0010b[嵅O<i\u0010>Ηg\u0019\nS\u00153`Vj\u001deSˌ[ۑC\u0005h(u\u0014:.:\u0012.\u001bXn\u00190g<̙+\u001e\u0002[F\u0018_sa\nSyH1g`\u0014^.@Us\u0005$z\u001a\r4\u001bfp'Eg\u000b\r\u0016\nm=E'{x\u001f\u0016K4\u0004bX94s\u0006퉮j#MCd;srÎ]ر\u0007;\u0012ر\u001f;\u001ah\u001a(|\u0007F\u0001ul]pwr߇\r{)5\u0017\u0017՜ ݌>\u00064A\u0001p&B\u0007\u001d\u00064hΏ{Hc_N`G#I#ůK\u0014uX4`;1\u001f'-cٮqu\u0005\u0007x-tɞ%CR[1Y\u001b~ւ}8\u000369\u00064\u0017\u0019\u0012.H\u001fbU(M\u001c\u0002\u001am&>v\u000b~\u0004fت\u0003\u001bn\u001fc8!;ݪu\u0016.4\u000f@\u000fW\t9|\u0017\u0007\u0006\r-M\u001d\u000eywt\u000f{\u0004\u0015>S\u001f\bӆ\u0010#I\u0007?\r\u001f{YrU\u000b\nn\u0000GL_M%݁{ց\r\u001e0=&&O\u0019VۃA\u001ccYp\u000b\u001c\u0007\u001cdr\u000eXw@0\u001cC\u0006̄9P\feP\u0005`~aY̍;\u001f\u001fټ'\tK=\u0003=⭇܁\u0017uޔ\u0001\u000e_\b8\u0018\f \rl4r9\tscx\u001dƎi\r)>s]\u0012\u001au ~˯|\r|\r\u001a\\K68\u001dش\r+/cHgi?\u000b؂\u0012.c*Zkl7\u000eң49Y}]ZZ9\u000ff\u001blA\u001cM\u000fOŢ\u0012:#WϚdD</W2v\\\u000bZs.$\bB|D\u0004*VޅpنgOS-37\u0015V8~$`P]dO)㘁\u000fF֞\\.f2\u001d\u0012VGr!e\u0007~d\u001fJV9\u001b\u001e]|\u001c\u001d_|#\u0018ht\u0006Y\"\u001efQ\u0007\u0001;c^أj\"G&A,\u0017[Y\u001e6\u0013MY\u001c߶i9l\u000e숗Xu\u0000N\u001c\u000fnNaF\u001d[ȏ2\rd2\"\u001b62\u0000\u0016P\u001dY]n@yr,9lk\u001dtŧdX\u000f\"Ih$1\u00164429\u0011J\u0015Bb*_T\u0013*c1\nۧ*oC{\u0003S1\u0001ڝ<A\t\u0019<8~Zg\u0013նZfV\rղZnjMRuj?Sf9/Qb9j&-p-Q\u0015;]T-\u0015\u0004Ԉɏ>eo{g)Q~\u001ahAN^Z\u001c\u001a0UiEU\u0018\u0012Un\u0018E\u001d&h\u0014\u001aerU|w+Wr\u0015m\u001c]w?<\u001c5\u0005\u0016nk0I\u001b!vßWÕ_n/*}cJ;U\u000b*4X;<1*J\u001c,{T\\,POfӌov?)E]\u0019C)!\u0018*\u0018mU\u00062a.mTAE5k)7Vy~\u00037L9ɚ?^3kz7\u001dP\u00002\u0003VkJ6\u0007\u001eҤ3J\u000b&\u0006=UjE7%g\u0017az<+Ŗ7fn^\t \u001e\u0019jz\u0004M9X=G(\u0018eJSF,B\u0005W(5x&k\\A\ryOcB+%FXZ\b(\u0005.E\u000fQ6X\u0005U\u001e<+Ė|l%69\u000e\u0011i!]552{+w\f>4)l&MPjX&и\u0002\r/SJ\nج\u0006%E҈\u0007\r\u0012CE#\\\f06\u000fC9\u0014,\u001f{rh\u0018a\u001dVᮚ\u0012ɑJ쭉}5\u000b\u001a\u001f5D㢒46jR'ktQ\u001a\u0019@#bjxF\u001cOCcNjH\b,\u001a\u0012\rQ-נ\u0006\u0016\\Z\u001cZ\u000f#mP\u0016GjRRc<5>_b5&.R)q\u001ao%jd\u0014%ŧix|\u00124,ޤ5\u001a^Jأ\u0017\u0013Nh`'\u001aP\u0003-\u001a?<*?we1 $\u0000n \"\"\f\f2\u0002,0Q\u0010NHAA(\u0015MqZ5q4զM6mzĸ&ƚX\u000fa\u000f9\u0001}\u001b\"Ρ\u0002l\bX?m\r_fK1S\u0013U@Y(/ir'+; ,E&C2\f\u00152UZJRSdHPR>%RBǊO\r\u000e%$Hr\u0014T#,g=\r3\b\nb\u0018\u0014oe\u0006Ȝ6RpeE+#=Itsj\u0014L\u0019J26(\\MG\u0019'\u0015qA;Nw(4bS\u001d:F\r@Q\u000fU<Cq\u001a\u0006l6\u000e)c22PzfLJ5M\u0014T%eU\u0004\fř4lWy\u001b4ɼK\u0013`\u0010nkBC&0#Oa\u00154A\u001d̂`\u001c0eIFs\u001ff{Ȑ㣤@%VBnrc59/Yyɛ\u0012MDK&XZ\u0015aYp\u000eY)\r_+4ϡ\\qh\\C\u0007R\u0007,\u0006r()J\u001c<zn\u0014?e&{)_\u0005*\fӤIXtEXs4:M\nY\u0014jm\u00185ں]#\n~B:\u0002wh\u0014^\u000f0\u001fJ\u0001VE7Q)ٓ1jZM(TD\u00035dJ\"\u0014Z\u0012%\u0006)\u0002,-SHiJTj\u0005\u0011\u0015P\u001e\u0012F\u0014CC\u001cڞ\u0000\u000b\u000elP\ffю\u001b2\u0014_\"gT\u0019;sF{idB*\u0014\\\u0011H=Y\u0011@[F4V\"[l\rz&_V\u000ev\u0016njXCt8-sE4V@\u0003TC\u0019L\\F4#lyE_.at\fs<_-\u0000=Q\u001dǫɷ&J>5I\u001aVcwU^56=VS5Y!r>\u0003><\u001ce\u0003kz\u0005P\u0000\u0000\n)\u0011il\u0015\u0001uO\u0000y-P0yڇ>\u0012\u001e+7{\u00064>]\u00035o_pS$l7SO7=ϡ~z&\u0001j\u0002\"9F\u000ef3A(h\u001e\u000b\u0019ܚ4K}i~i<[dZ8ZL-\u0014P\u000bky\u0016gຈm\u001dlyh*^/|3Xs\"kĚC 7IÚ%%\u0012m\u0018,1ϵxXE#\u000bC\rN01Ҿ\u0014C\u0000P\"p8iFjz͚\r 5Jc{J\u001aj}?@\u0011?6f\b\tp뤰;YT':p\u0003p\u001czy\u0006\u0016bFc\u0017I7xZZ+ow\u0015^\u0006BmxB<v.c/\u0017>\u0013P\\wFzw>{pbGs֏\u000b\u000bŜC9VM(g\u0007U8\u0000@xu\u0017\bq\u001c?Nx;AEqu\u0011\u0017O/\u001cNj[9\u0017W\u0003<F^W]ZGMg\u0000_p\u001a\bb x%7ҠÏ\u0011\f,\\~gw-/\u0001MCOH9\u0018;b?%=].;\u0012\u0018\u0015zÇp9AeW\u0006Kä/\nM\f\u001ay\"\u001eujM穀5Z\u0012\u0012za\u001bqiȥg7`x\u0019a\rn\u0001a\u001d\u0006w4'?P\u000f\b_\u001c\\c\u001a\nz \u001c \u0003a:̂`&h65z=\u0013}oÔx$}L_\u001e6op\u0015\u0002\u00179o@\u000f\u000b\u0002`\fDA\ndca~P\u0019\u001a:۱߄V_\u0015?\u00064z\"J\"<}t\tK=|\u0002\u001fYxC?K\u001fWL|Y[0\u001aϚ2cA\u0018دj\u0019~|ʴ\tS\u001fټ\u0017T?QJ\fz9\">uq\u001aN\t\u000f?%\u0016wŗ̺75f/NLN>V\t1,v\u0015b{\u0001%Ө;[|;xR>\u0016<Z7tH\u001eCu8\n#>pr\u0012WJU}s_\u0011DщTMNΨ@Ə7𣋼:~\u001cŏZu\u001c\u001f[8}D|\u000fE\fBm'|.\u001f85go\u0015\u0006-/\u0011(t\"шZ:s_\u0012l\u0013خ|l6bsll29=ق\u001dlds\u0013\u001b\u001f\u001eۮ\u0018\"\u0016G'\u0007#$:D\fb]Pr\\l.`w,$\nϓTVWUD̮\u0011r]9\u0011 ];A1\u0014B9\u0006\r\u0003\u001a(\u0013hr4*Ѩf\u0003\u001e,R\u0004\u0016y\u000b\u0019ZDd\u0017+\u001aG#r\"p\u0010vrԾѿ+`ܵ^\rGk4:ıT-TiL\\\u0019\u001fYn\u00180˰/\u0003\u00002,\u00003,3\u00181\u0007\f\u0018$\u0013vcxKʭk7V괪*RRU~V.Q*Jc;R\u001f{;G:\u0001\trq+YȦcn:J\u0015\u000eFd)\u0001ﱰ\u0017G}VuWj폴~UeZr6f_T=/F|T\u001cg\"S8%S[K8\u0011]ͱ\u0006lsrx[\u0017}嘽,Lr fÄce.v\u001bLg2=&> \u00141,wvi9Tk%?k5t2Y$Dq\"n\u0007G9\u0014or\u0012j8`!E8\\\u0000IL&1B(iK{\u0004S\u001e\u0012H9#\u001f3j\u0014JCq'_vDSyʝi%S\u001eK,'r %pj6iLU1݌2ьQfL\u00114-\u00110`tݙ2y\u0017_\fd2LG_\u000fd}>'.zi{Xd\u000fU˜jɌf*3Y&w/\u001a4\u0011i'p y-0ws_c\u0002=om)]Ɲo6\u001bt=&ez\u000fX✖.kߜ,ȔjٯZ͛ٗ\u0017\u001es\u001a\u001c\u000bJ\u0018*fwa=V|En\u0006+\u001ax\fO\u001c=ūt\u0015?*\u001d%o^\u000eΒ\u001fVGa<Ywe\u0012\nŪI\u001fW=\u001af8%K\u0018(-޲Z\u000e<.z*<tU\f\u0018b\u0006e\u0005e6\u0015Z,l:M\u001f\u000f񔊧#\u001b|\n\u0017ğ\u0012bFk\u001eգ(ǠYgI[LwU\u0019]V\rtTvn\u0006iNb[a[ѶA6vר \f꬟RmvBCYcbAL7c~اz<(m;pפQ\u0018gm%muvZZhG}F~'&=US]g<][Q49ܠy ; ߫ZUS=8\u001aRhmȢ\u0000Gc\u0005M5465䥮iZ86<ՎT9.`qܠ\u0016eG:~GYӿAyAE]i,{Iߡ\u0016bH.\u001dwiۦ\u001cCSs\"\r-\u0019Էao-zlmmXۺnS69G(\u0017(q^B\u000f(pRjP7tՋd\u000f\" |#\\UK\u001eMm\u000el4l:\n`騥N:)C{B*su\u001c\r9  enpS?\u001fuBX!'Dk;4(>ֺ\"tQޓDY\u001e3%R=V\n=\u0014xz1{GN]a92\u0012k=c`~53t\u001e\u0017\u001eRLrH[\u001e(m\u0014\f$`\u001eH#Ϸ\\_!9\n}ue1\u0007ӿH4)$(~I$\r=5XE_Z#_t\t^\u0015}Wt,RT\u001d$k$\u0016S @:;\u0003\u0005I\rT\u0012h$9\")Obp/\tyv\u0004O\u0011\u001fL\\Mb&&+#rrC\u0006\u0017|ǥ\u0013\u0016Ġp!\u001cҮZ\u000fj\u0005BV\u0012Cq$Y\u0011\u0017!6BLaCSl\r\u001daTd\u0016\u0011o\u00101\u0013'\"\u0019l\u0011gqHL\u0018\u0010ݢէ9(Ji\u0017+\"J_1uB\u0019p:ع\u0018\tDS\u0012bsMa}aܰn\u0012\u001e\u0013Bywx\u000bfkf?T#VJ٭aH=Aa+\\89\u0007JI_4\u0005)ҟMD\u001dZYXI׃(O\u001dRS_US[Ƕ\\[U\\=%=@vP5,\u001bO8\"Y=\u0018%]6mzI0H_)K\u00100l>.wR\f)ZL\u0016\u001d-vj5\u0016!/Cp'V54Xք,(z۩g\u001c\fC|D' z\r\"9&5x\u0019\u001dZpT%\u0016\r-v\u001bz'57`\u001b\u000bBcㆎS}&T\u0005yi0(:5\r: \u0014HtR\u0010w\u0016Kc\u0006)j<)^xrS긭\u001dMz\u001a[\u001c9\u001b5Yi\u0006Gcݲ9S\u000bOkI7e.5\u0013ӍB\u000b2\u001f\u001a{2ce\u0012\u000fe\u001e\u0014y\u0007\u001e(\u0014Kk]XX\u0017Xv]`\u00179\u0014\u0011\u0011DP\u0011EEE-}3Ѫ68ƨ\u001aǚ\u0018\u0003&\u00135UcըʹMG\u001a϶&iLL9l?\bqg~e}yG㣍\u000bY\u001b&FaV\u0006\u000f[O?r&\u000e4\u0011ݑ\u000bCƹ\u001aߢ\u0018ԩ~?\u0004p\u0004\u0000Ҫ\u0018\r'Ki.g\u0004\u0005]\u000el\u0000穋\u000bL\u0016hݷS\rc\u001e)\u0019+\u001bC7`?vj\t$\u0011ur\u0001.{gx\u001f\u0006hV.37k\u001cznP7I7M;*D\u001d2f;y6U+\u001f6S|\u0007}\u0003.\u0003U\u000eXzM|;]j\u001esrE5zH]< t9}\u0017\u000f\"\fv@\tZ\u00023a\u000e,\u000ftS|\u001e=\u0013\u0017t}M\u0007>|\u0001\\sOzO\u000e \u0000B\bVȆB}24FQG@\u0006\u001fǗ\u00059\u000b3ЕbA\\\u0019Ru!u>}\u0004p\u0012?^0z\u0006ݣ׽C.RC('~n\u001a>_~fb/%||\u0011\u0016%\nx\u001c6\u001dOt\u0016k?\u0018Sn)q\u0018\u0019G>H^WBԟq\u001e\u001fsϨسu\u00048Mhl6uF\u0016\u000f*\u001eާ<k1N161\u001e){\u0003:&2\u0015l\u000fQ|#&x\u001d!MgM:\u0003c\u0011\u000bw/w\u0012Ec\u0007j/v\u0006wzYΗ:Irq\\\u001c.\u000e+\u0016\r\u000b\u001av*\naڃI$bNg\u001bkb\u0016\u0016\u0012w%[z\\h3n6\u0011i#7PP]I\u00034ou.w:h?K.vi\u0000\u0013nEA\\\u0017\u0012\u0018G\u0012{4XKIěN\u0006Rj5\u001b*\" /rfu)f)OUp-q\u0017l'\u0017eZ!#1ѰɌi\r>Vc%>V2e\te摍\u0015ϯ\u0011i\u000e\u0019lJfSQM49αͷ\u001ehf\rx%{Z\u00051p\"ơ4-6\u0016o,P\u0011\u001a\n4jИTm\u0006n\u001aq<Me>\u001a\u0015_x\f\u001f\u0018\u001cy-5\u001c+\u00028{wn}\u0018W0zh%KdhVWfvWc!޽LӺR8MI~Tc&X[Us<1=/gj\u0013jb(G\u0018ˋl\u001ba5øp\u001dh\u0000?\u001dYC\u001fif5iJ_&U}\u0002M\f(Q]H\u000fѸ\u001a\u001b8C5\u000bT\u001dFU[U\u0019W\u0015o<=\b\u0002\u0007ߏ2pFq\u0015Z\u0012#-93#gj\b\u0004Ҕ\u0005>(B\u0013\u001a\u001flQmp֘~\u001e+~e_UC,dlְ\u001a\u001aڪ!\u0017T\u001c~\u0000\u001f\u001d\u001c\u001aq\u0002\f>O\r\rИ\u0010UEktI\"\u00062¡\u00119*\u001fP\u0011\u0003J4<BcUshl\u0015\u001b+\u0015\u0018v*pX^9yn)/1ON\"C\u0007m\t\\e83\u0003\u0004\rOoSxʨ~*Ԉx\r4&]b44֣!q*\u001b¸j\u0015+8K^\u0012\u0019+ǸC.!eǟQV\u0011p\u0012\u0019;86\\E\u0017@#$\u0012#R\u0016SA*\u000fЄX\u0015\u000f4hM\u0005\u0003\u001d\u001alQP^SU5mn˼HYL.G\"\\i'ބ}O0t\u0000\\{\u0001L\u001a8g5G~\u0005/K)^&vWQb\nB48)J^K<\u0014YMv)'9_\u0012eT(3VΔiHgf&SJ^@\u0014\u0006%w\u000fM.rǆP2(b\f\u0006\u00194@nQ.[lL͔3#Gj2R˕Nc [\\Y(9yY\u000e(1iW\u0012S}Jjnts\\N-ک\u0003r>@\u0011);҃i\u000f\u001e\f\u0019Vgd(͑TG\u00069du(9Y\u0016g\u0012drF\twAF2:)SB\u0006}ځγ$\u001d:P\u0015\u0012^\f,\u000eg\u000f3\u0003_Y\u0006ٲ5(ۢt%ggWk̮*\\Jp5fuoQeEຬ(]Eg\u0010S\u000bWg\u001fђL1P\u000e%P\u0000R]e`Yr#\u0017+sY<\u00069Sg<\u0015);S\u00062Ez7+;y*sIa\u0014SDn\u0007[X,4&rP\f^pV,o4 P\u0005!2\u0016\u0018\u0014Wd\u0014\u0015U薡PE#\u0014Q4NE\n-ZE'̃>8\u0015\u0004dY]p9dj\fF\u0017\u0016EvǮ\"\u0016!fRzD1j56$\u001aHӚ1Z\u001bsL5Gڴ4uS\u0013v~\u0016LǇ=}}}J,}Zҗe-=/kMي\\!iZP[\u0018Ohg\u001dJ(<E{,#K!ʨ4+iS3EL8\u001c#+W\u0003]EJrdsZ\u0004W,͊wXfQ\\g\u0015.s%k=~FG!\":P\reP\biǳ\u001eUF\u001538dw\f\u0012$ٌ4Y!J0FbW1U5劫Ƨؚv\u0018\u0014e<HyE\u0018g\u0014\n_+\u001dTtuPX\\~ ZpA\txA{\f]36:<RJ\r3HY\u001aLZe5Pw\u000f*ʛHoy\t\u0018$\fR^\u0006Ɔp`\u0001}t\nV@\u0011L8GTKC\u0019\u001c3N1ϊPX1}\\~\u000eu?\u0007Mg\u00183g!0C1\u0018Ü`\u001fv\u001e.tޗTgY\u0003b\u000f3\u0006g\u0018\u0006`6Ffc!\u0017\"\u0000]7f\u000b\u0001\u0002\b́v`\r0D.b8]`.\r\u001fZЙM\"ׅ\u0010ziXdt\u000b$s\u0014\u001d\u001eGJ˘+;hv:i4\btsp]f.\u0007\fu3gv\u001eyg/p9\u0001|\fG R^'ĜCxZHeR&4u\\!c5~!\u001fc=~lu\u0013\u001bk\u0013؈qC}ڠ|S:N^u<jU\\>\u0016~\u001aԏ0h.CM&\r\u001fl\u0005X\boӈ`]~\u001f񣇋5顸{\b\t\u0002ٽ\t]k4N>brK\t$B\u001f]\u001a)f\u0003:[`\u001bki8`o\u0001g\u0019\u0002g~rr9H}\u001c\u0019;¥{\bEv\u0004$\u001e9P\u0013\u0007,z)YJ\\BcU?t-\u0019=7\u001f\u000e\u0007\u0005\u0019\u0018\u001eL0cQq-)8ť|<B$\u0013$!`=޺!\\D|f)xROhXux3<\u0010\u0004Ҫ_;\u001e\r\rL\f\u0006Yc'E\u000eK\u0014e\n2A]ؕKpS9\u000b(b ǉP!ݟ+a\u0013p:+5\u000b\u000f\u001fp\u0019H>\u0003?ct$`]9sMxB\u0003@\u0010w~Ǆ\u0011\r\u0010\u0005q`\u0014\u0018\na2B5\u001cX\u0000\u0001XQfe\u0007zE|^&WT\u0013_?\u0005x\u0017N\u001bDH\fx\u0000&@\u0001Q\u0005GՠoLNי1]e\n\u0002?>Ǐ?Y>c2\u0002D|oI9d\r\u00038\u0003\u00158>//w@<)3\u0014̤\u0013\bN\u001bL\r\u0004?>ď0՝\u0000?{wgROyN9%x%cd5\u0014^\u0017 \u000f\\\u001f{%\u0011e3\u000e)/&.l\u001bخlln\u001b应wEVوvϓ:^<@G!\u000f\u0013\u001b\u0011.b(\u0004?\u0005hDc\u0002y\u00122Ķ\u0007uDڄ]?Sm+_qх*?J&v%} \u001d(n\u000fC\nD:\\fkm\bt*\u0011t\u000f3z\u0010s<l`ۉm\u000fgbI\nR\rK9Һ`6\u0001o֓ul\u0003\u001atj\u000b\u001d3\u001eI{nYа1\u0018f\u0012;L5bJqaxE:d'ӁⲾ\u001du\u000e#zoБFBWA\u0004\u0016t\u001b\u001ah\f!#\u0018Z\u001fх\u001f\u000fG'~,#\u001fO&\u0002Z\u0002D\u0010X\u0016\\@m.6n\u000es\u001c;w\u0016ޯ\u000f]\b{d\u0005XN}v&\u001d\u000fQhdk&Q,E*xШ\u001ch!##|B,֣\u0013r/!\u001a4G\u0011\u001eZ-\n\u0011uT&bV&ֳ\u0019ndt\n)C\nZ2ш%TJ TO\re?<\u001dq[Ƞ}ǸXƑ\u0006`\t\u0005\"\u001cmּ6͍LC4+\u00015F7:G1SU\u0017S11\u00012b}r.RulLTi*M0\u001dWn\u001c/G$3\u0012\u001d[kK\n-\u001fƟ&\u001bXdWy\u000e͈\u001fQ2c$@Ֆ2UYԩ2a*\u0012\u0016,aJ\u001b4Kګ\u0002\u001bʷ~|!{N`8NZu\\\u0019\u000f>7]\u001d/Rk3ɰZ嶥jm\\L\u001cʤ\"iʒUTZM\u001b8K\u0003[T`T}wj9M\u001cE$QnrvJ\u001eˤ\u0006\u0003\u00043i\rƗR\u001c-gE\u0015)v8T:Lũ#5-u&0Pi\u001bєA^M\u001eԬI_\tەO_\u000b\u001akx\nG҂Ҋ.\r\u000b`+ܔ9\"T0k#Q\u0019i*\u00187e\u0002\u0014yG(\u001c\u0001AuY`w]`e]]\u00156xM0xD⠉h\u0018hԦ:M4=$\u001a\u001bΤvI\u001c۴\u001d;\u0001^3\u001d7{y{wiJ>SMM,)O\"\u0017t]-)\u000fn~]6p\u0007\u0017Do}=׿%؃\nM|!.oNP9M1#U3&_\u0016,\u000eU\u0016VSSE\u0004\u0015嶶i] u.XwzH\u001fb=\u000fx\u001fpgي\u001alA\u001d\u001b\u0004S!|(^UEUY\\QYM29m^a,-\u0012<\u0015ٗоY\u0016.\u0007e|9)-\u00020pvӍ*\u0007-\u000eM0\t&]\u001d*pĪ̑,Wi*-5,TRŮ:\u0015&5U\u0016W27j{/h\u001f*u]9rFc3e.\u0001K\u0010F\bB|P\te;GYli*.RQy\u0015\u0016\u0015Ve(S^&OF{f)ӡQ\u001b]FV>L+\u001ay\u001f>FG\u001b\u001c\u0003\u0015\u0000\u0016\u001c\u001c\u001e*^\u00143T͑[|oF׸[SQ5SӨ|3kWo2|ەۯ4\t\r\u0005\\UZ\rFoTQ=Fh.&\f\u001fB\u001a\n}/\u000fP06Fk[\u001cyoHCY\u00012\u0003u\bLRz`\u0002\u000b\u001aXmJ\u000e<q%\u0006(YI{J*6-h\u0011\u0006\u0000P\u0005e`GZ>-o\u001ccB2)\bf(=\r&\u001arkxȧPPɡf%*!BCC݊\u000fS\\bo+6\u0007zn\u0013ڌ5]\u001c0\u0011\u0002P\u0003\u001ep]\u0019W>mĤX6&*%p¹J\b[4,p\u0012\u000e(.ܨ0\u001e/\u00046\u0001&|f,4b\u0002\u001a96D\u0007x5ƌ\u0000@=\u001a|mA{D'\u001fRb45AC[R\u0014\u001b@pDT#EM\u001daP\u0011<\u0004\u0018\b0iB\u000eS\u0003Bc\u0004\u0005a<}P{{\u001e$7eh\u0003\u00126ugrј?\u0003v6\u0007ʜM\u0006ncښ\r0mx\u00069\u0007c8\u0002G\u0007Xf\u0014H\u0001⽓1[\u0019s\u0014)\u0005V)m\u001c)n\u001e\u0017\u0005ql(\t\".\u001bɣ=åM$w\u0010c:<\b_O\u0003&\u001c\u0003(\u0002ӧ &⩒i\u001aX\ftSK(k\u0003\u0013Rˆpp\t[eg%yt2'9drcN/8&s-[\u0010ֳ\u0019\u0001ji'7U\u0001j\u0006Cm^0\u001b}ƛnr\u0014\f]\"W4\u000ey\u0000\u000f&걙ztG7B\u001e=V6,Ԣ\u0002\\\u00121ovaM\u000e]QD:Ro\fig3tt:~͍\u0005[`+<\u0006\u0005(f\"$<G/\u0007r/\u001b~/\u000b\u0001~\u001d\b[׸q}\u000fpԹ\u0001Zj^L\u000fR\u001cZ(\u001dDTL棆\u0016ˋkś?x\u00110\u001eAjrf-8F\u001ecNGgZ.\u0004x;\\ qSY\u001bS;Z{\u0003\\ٯ_\u0003X\u0018\u001fb\u0002S@H\fؠAx\u0015^\u0006q\u00034\u001b[4ُ\u0010zq\n\u0017q]\u0013C&\u001f9\u0018x\u001d1~cI\b27e\u001d8c\u0018~!|D^ KK\u001cX}4Y\u001f+]$>#I̯e'{\u00005N1bh\u0001o\u001bf=Cc@\u0007~\t\u0017Wad\u000b\u001c0\u001f*r޸ΞqM&:$fϼɀ\u001d$\u000e\u0012`8dA>ؠ\u0012A\u0003\u0018d\u0001,-=qB\u0015\u0001~#M][}wu\u0005\u0019O|ʯ~\u0003g\f\tr\u0017yA\u000eX\u000fzEa \u0005N\nn2.S\u0016Y4yy]C4\u0003b9eh'{̻Ja,#tZ\\S\tZ\u0015!}5}L\u001e\u001f>U3\txG;h^\u0010ms\u0002{V3]8\nJe|I\u001aN\u001aS\u00184\u001chT\u0012O[}?#ĞIybZg)W*7eƻ\u0012\u001e\bjArz}\u000e}F\u000ew\u0007ㄧ\rSh\u0011GV4\\ԭ~b\u001d&Tb n\u001b_}ث\fѫm\u0003M-v,ϵ\u0013'`\u0007|\r\u001e/\u0016>g,ƒ8B-^T*G\u0005_L|7{٢\u000e\u0012mӉ9:\u0012w\r[i\u0017ɨ\r\u0011Fܤ\u001a\u001d`\u0013<\fW;k,Ex\u000eNT2yg\u0010?fۈ_FtA7\u0010\nZ9\u001c#9NZ֓I:Y'\n\\9y\u000f\u0017v\u00182\u0019\u001aÈ?#\u000e\u0013K\u000fB\u001bh&t0U\u0000jg\u0018BF5\u0011׏p\u000f6Xf\u001eƱZtR'e\u001e]o\u001d;v.p8qNlp9\u001c&MNv-mvJWrT+[v\rh5[@QZXA\\1&\n\f\r\t\u0012\u0013\n\u0012\b!:'}<_+Qˌ7ъF\b\b\u001aQ4$M\u0012,c]Ox\u0013aYE\u001bVW\u001f^e\u001aN{{J;Q>!ctM\u0003\u001d\u0017:^FݏN\u0018\u001et\u0019f6R;Ih\u001ea\u001e:fmMEQ\bڣ\u0019^C\")RQX\u001cs<\nuM!}*F\u0014jT\ftj\"W\u00065=dƲ7k\r\u0007\u00157,jpV\u00037P\u0003E,+s_ܴb%4J{JCvJ.Ym\\)Weʘ\u0002&+W*ߩd~\nZ4Z\u0010HAD\u001a*@\u0011#S4hтk\"6P\u001d:M\u001fAZ]ƴwRIJ\u0015\u001ffa\tX<\u001a1ٔ09\u001474dnҀ9~sb}\u0016kIieF\u0011˜,\u000b\u001cWrFAeY*]\u0006\u0000Yz\u0014\u0014J9ZM\u000b\u001b`\u001d\u000e<\u0017ĉeȖ\"\rX-V\u0006(b\u000b֣.:c\n7(hߡ}\n\u001eSkj.7-}G\\ܓ\u0015<:B %CYX\u000fc)O\u0007/;Qb-SOYrʫYVI6\u0005+^\u0019UrD~ǤZ\u001c[ث&xF\u001eǋr;^\u001c\u001fɊp\u000ehƒ8$:j\u001c0.kQmRD5\u0015jq*P mZjj\u00199Ffy|Bu|A5WU|\u000b\u0000\u001fqOPٍQ4`\u000bz=^0>Eü^P.Z\\jvW]/ۧv5GT_?(g\\.&9=\u000f<OsQ*|_\u000fWy=\u0015\u0002<Mۅ%\u000e\u0000\u0018\u0013\u0014\u0016<y\u001bjhTNnWꚺT\u0014SMӘ|\u001bUW|'e]P+'k߲5euv\u000f7\u001d؈MK6B\u0017x\u001efhӼF\u0016ZrFխ\u001eU[USXe)\u0003;U\u0012xTe\t</s2\rJ\u0004\u0003n\u000e@?@\u0007ڠ\u0005\u001aw\u0007{\u0005r\u0004ͪ\fT\u001et,R)CzT\u0012\u001a^/Kx\u0014%\u0015_Q~6\u0002`ZEpb\u000f\u0004ǡ]\u0010\u0004?3DOiZޙ#{Q%VYˠFGőV#2Ee(Y\u0005=ʋ<\u0019\u0019\"/)\u0016L+\u001c8Bh\u0006+A\u000ehy\u000b4]vU\u0017XYlY\ndeT\u0014TaԥOѠrcʉ\u0010VV\f\u0003\u00130ˀ\u0001o\nU\u000eNڟ`\u001e \u0006\u0010\u0019+/hנ]VG%KL*ʐ(SvM`&\u0018\u0004\u001f$\u0006\u0001\u0003&0\t\u0004F)~\u00030\u0005C0^e\u001fo\u0006C#\u000eY;]#U\rb\u0019\fg)4O$I-Y@Oqئ)\u0016X`]\u0012x)k\nӘ\u0001$y\u000fҫo3h$a\u0000z\u000fʵ5ЏK\u0004fmٓ)Ý7́>A6Á2\u0002\u00033|43\r\u0001#796\u001f4U_.\u000e4&a\u0018b1۸zs\u001dVW6t-ribAL\"c+\u0005ǶDObIcN9TYPs46Ǉs;0c`w^@\u0018nwUf\t5V1!a5&9f6Ԍn&<V\u001c<\u0004cw.,㱗8\u0011\u0001\u0012\u0002\u0002\u0002\u0013@c\u000b<?\u0000xWx[Ǩ\u0012\u001e)`v3֭㬁\t\u00065O7XޔF|\u000b4G!ZIO0/G(Ǝ2/ǈc\u0004wdsMX,ґ\u0000s\t*cأ`wiGoX7n\fڂ>لnތc+Z$\u001c_-xIL\u0001|1yyuz8c}:`?Ggis\u0014yǼO& \u001dٷ=0ۃ>9g4OdNi8)<|\u001e.\u0002[O\u0018+q8O^aX\\\u0004ūÚ\u0002RZ#u\u000f}g\u0017\\\"ӿ\u00193\u00120+FH\u0017a\u001eW\r\u001aMqM\u00167-:u\u0013\u0017q\u0016\u000eSu_qp?a`\u0014ә>^h^\u0018\u0000;\f\u0003s͌I.1\u001d\u001d_^\t}\u0001\u0011\u0003C\u0002~\u000fw=ue|\u0018>r\u000e,!݆!ytVL\u001dX1K\u001f/W[\u0010\u0019e\u00122c̦Z^ً@'~y\u001f\u0005y_=ͫ\fO8\u0017v?;N\u001cǱ%n\u0012;7zImvݺ6[E֪]\u000bB\u0007ҁ(\tʠ*\u0010\u0014kT.T`\u000f@\u001b\u001d`m2\u0012sQS>w{y\u001f+8\u0003!hn\u0018\tX\u0003\u001e_8wp@7)\u001b82}]c^e\u0000?̫\n<\u000e߅o79|\u001eNFb-COoc\\#Wp9/|^u¹\u0003|<~K\u001ehM^#80lO1|e.c\u001d\u0002_\u001cރw&2؉_3/^P'\u0019=C%i/pZO~\u001b\u001b|1!}\n\"zARB\u001bLy\u0010,|\u000e>\u0003O\u001bsyx\u00164c$csyy0;G{\u0014\tW=hϳ<*wnY6\u001fe6NY\u0005]adZy\u001aN8K΋eT/·df\u0019\u000b}?\u0019edNa\u001aA{\u001c)tg\"֣=Sqy9\tܯ3\u0018\n\u0018OTna\u000f\u0012wj~\tm+'\u0014`6@;v\u0006ahO0y\u001c$\u0003>f{;{n2ŵSϰހ\u0002a\u001b<_֜B~c7E\u001fE]\u001c\u001e\u001e\u001eT\u0003K\u001e2/{]\u001aB?J5hgI\u00168Zrs̜y)u&x\"\u0005<\u000e参\u000bǃ-hQt\u000f\u00101\u0013\"Eo2KnB>@6X=GRf\u0019f}6C<o'G\u0002q։J\u0001ekC\u0002}7Ƕ\ba\u00181\u001411-4+f\u001d:Ol#\u0003\u0007\u000b<+x\u001br\u000b\u0002d8rD.\u0004w\u0014-\n2\u0016k\u00199s9Y޵XENf';VR\u001f+\t8WY\\Nc\bo5\u000eR\u0003T\u0000#߯ \"g\u0000~m0\u000fa{i\tgXV\u001dq\u0011;\u0004HV\"\u0013\u0019\u0019/4\u0019gt6覲4+dgdG$~\n>Kc@\fZ\u001abKI\u0018~hyYE6\u0014VhF~\r,\t)Y}E\t\u0016SQiT]ILkiS;,>Dj+>V%%9ib\u001d\"6N\u001f&!\u0011\u0007\u0005\u000fˀX\u0003f2ez˪cU99Ty:;QޣeJZV2V˼\u001dj\u001cQAE-\u0014\\RrU!u9E\u0004q\u0012s\u000bm\u001cohn0*]7t\u000bԵTiU)C\u001djꔴX\u001aSҤZnicƄYEy\u001dj0*h|JTgX>E:'?\u001c'n݅=XK۳|\u0003ý49u_;-s\u0014)(WaQV+\u001aTѦhEJ\u0011gά\u001ak\u0014pnr*\u000f[yZsrW^Ru\u000bpSngN5p\u001fw\u0010oc-u@[>\u000eC\u000b)\u0013VB.1WljtU(r+RW:긂\n\u0010ܫuonk\u000eUsJ5_#9ϫ}*s:Ļv|OA?t\u001d\u0012bqo&FxL\ny,j+P[ZޠMyu\u001b7)6U>(g\u00019|'e=\"\u0003|Ru\u0019ޜp\u0000-ĺV|e:^$Z\"s\u0001~|KwF@܁\u0003r\u0005Ҫ\f\u000e\u0019d%\u0007\u001e\"#O\tY_%xQgT\u001exS\u0000J}N\u001fBw3h&h\u0007\u001bڡ{\u0010\u0006Pa\\a.UF|rFBt\u001e\u0011\u001d-:'kt,=2GWY!D.\u00145Wi8{\t5سly\u0014\tCc~\u0017\u0002;7zUSr\fcN\u00191\u000f\u0004d5\u0016O\u001aQy|Lj78SEc*hct\tU\n9?ހ\u0014ڣس^V>7CPǵIrag+Z\neʖʚpȒp1xiE%ɔL%I\u0015$1\u000eILY(\tIpB'P\u0006\u0012o\u001d+h{\u0007$qh~\b\\r߅uc\tH\u0016^\"sʢ!Sʩ%)\nS\fj\u001fV\f`\u001cV4NaRRRl֝I\u0007ّ]hϠņd6h3\u0006\u0010\u0000/\u0013/\u000e<P@\u0012\u0015MM,\"ϰ2E\f*\u0000&&C79ų\u0018>LH/S/9t\u00075Hu\u000b\u001ai࿏{vw\u0012\u000b\u000f#\u0001\u000eA<\u0010\u00070\u001bsqs\u001bc,\u00181\u001d\u001b\u0004|\u0018\u0006rl7mF1f#+>i\u001d\u0013<>\b]s\r4y%\u0001lH*\u001aP_rsN0\u0016+8t&ܧH()^b\u0017)<v;[i[A:A\u0007=A\u000e8\u0016m9d E\u0004\u0011Aĵ\u0010$+\u0015\"o<8ߐ;ݼldw쒓\u0010\u0002!\u0001\u0002\u0004\u0012 SAn\n G\u0004@e\"\u0001\nJGC))\u0003RZСP\u0004flikRATe\u0005j~Nξ>\u001ce`.ɐц\u001f\u001d?:񣛜\u001b\u000eM'\u0000х.;\u0011q\u001d\b+\\̎\u0007\r\r'\u0015)'/a\u0006S}\t0Pc\u000e7!g \u0006\u001ey\u0000?\u0016Q\u001bK9d%\u0014\u0012\f.\u00005u!\u000f}0\u0014klV\u0013\bO)^\u0003ތ6)\u0003\u001e\u000f`\u0001\u000f{`5=0XI}ƏuaK}u\u0018\\kWr@n\u001bzcyGY<\u0016D^%-ći 5M7a&\u0017X90\u0007Os\u00006&j\u0005\u0006>괟\u0001d+\u0007V곟Xl!y}K\u0018؟6S\u0013ϟ!\u0016\u001fs=U|R<\u001e/hr\u0005뭁\u001b\u0013H(!0\u000bX\u0016\u0012BqaC*5\u000f?\u000e+\u00078p\u000elI>|\tL}_cuM;9`ͅ9x7Z}\u0016\u0000\u0006k\r\u0007\u0001-Ǹ(dD\\,\u001cFN\u001c?#'')\u00133\u0010q˥|x\u0002Cul\u0001b3׻Z>W]y\u0012D&Qp\u001c$\rU\\0\u0005!Vs%\u0012q@ϓs ,QTg~)!Ļ\u0018<jg\t۬13 BM\u0000[\fI\u0003\u0002\u0005>\u0000\u001feW9IнFsƺFA}\u0006\u0015\u0016pC&k\u001f@&0@>\br0\u001c\u0006\u000f\u0001u-y\u000f\u001ds\u0007%\rkTm\u0005r\u0000 YWI\u0015e\u000e{1܏-S׀\u001fCX5ȵG6(пјwU\u0005H}r\u001b:~\\e\u0013\u0011M!\rs\u0011?Σij\u0017OZ{$U1\u0017#1J\t]\u0001v[>\u0003_mp\u0003mu\r})\u0013'hЗ\u0017Q*\f8fy\n>=\u0014w$)\rt9\u0002Ïa|$\u001eљY;6\u000f\u0005f_)\u0003\u000fb\f5خǶ&b{\u001agbx\b\u000bO)5d\u0019t;mG/Q'*;\u0003)p\u000bXUf{\u001d&\u0016w\u0007Ѻ\u0007ИP\u001bn\u0003\u0014.\u0014N\u000e\u000eVjd\u000b~\u0011E=\u000fKx:\\?דDt\u0003O`\u0015X\t>-`\u0012U\u00062K@\t+\\gQ\u001bQ\u001bH/5\u000e?z\fORz^Nl߰Ǩ\u0018c~\u0001g;h$\u0007\u001ci=\rlYnl\u0017\tWP:l7`{\u001c'!n\u001c-n\u001e_%\u0012sŃtA\u000fzDwm\u0002_P|\u001c\u0018ت\u0013]\u0007>`\u0003\u0002td\u0004\u0015\u001fJ\u0015a\u00017#u:IDQR-\u001b4,MGZYm\u0000\u0005bÛV͵ǐy,G\u00051C,E'9 '\u001dF;5:KQL\u001f䥅L>f2H\u00046l\u001b\u0015q\u001f~+93\u0007=\\s\u001csAOǾ\u001dٚ5E^8BpDJ8j\u0018nV\u0013_D*P#\u001cĸc7|8V3pw1w\u001aG6Q)pd\u0005G\u000e\u001cn\u0018Rx੅\u001eM؟Ld4HR1è\u001a:g(UW^1D\u0006wAýx\u0011\u0010K#>\u001e6s13:m\u001aԐ`ˀ)\u0017\u0002\u0002𔰓U\rW\u001d\\ᚈ\u0019xC\tv~nw]\u0002Al\u0000}`hi\u0001`,\rY̹ß\u0011I\u001a)\u000e&;U^U'4$yRTR\u0006LPij݊.V8uS_T(u\u0002)G9\u0015%RQ}\u0015_\u0002ι_m>@\u0013\u0018\u0005xV˻\u001aJP=Eՙ\u001aa2åL2TYrEm5\u0015WEA{\u0002kߢ\u0002^y䶝Ur\u001dF8Xʸ\f\u001aHjFJޗO4:\u001aVđ,Y**U\u0018\u0000\" 3X|WF\\~96>\u0000>`b:\u0019ɧ2\u000e0ہZyV\u0001J)7\u0011WJI*vf*RRY N@9U*\u0019!k]S˵HNZe^+쮳\u001c9ALk=\u001fYHI;c\u0000Q5WR>\fB\u0013K?/M<\n*ϗ'';<wrݵr\u001bLRg\f\u00029<el2<?Q\u001a|\flυk\u00061\u0001\f\u0007C@\u0019\"S\f|\u0007^PP,wMy^C\\*7To\u001cf3eUYɾ7;\u0005*{Gޘ\u001e W!A\r\u0004y\u0016\u0006A\u0017-\u001a@A\u0013\b\u0016\u0011\u001e-TPC-J\rӆ)1\u0012B\b&aa0L\u001d\u0003bZN0\u0005uȣj~@$_@\u0011u\u001eϝŃdSd\u0018ʌ*#Uz$HRÔ\u0014mTbt\u0012\b(\"I\u0014݉À)a%ى>\u0018\u0016A\u0015׃AA?L\u000bp\u0015ew^g;n\u0012\t,$$\\ T \n\u0014D8V\u0002\u0002^\u0010Bq\u001c\u0014\u00182ZN6#2Ң\u001d\f>q;9o\u0016yn'[鐫%g+{ ]Il%\u0004\ne\u000bVP!\u001ad\u000e\"Z \"8\u001b<<]\u000fLpUq-@ԉ\u0004h\u0006\u0011\u0010\u0000ܛ\u0006_!\nc>\r)\r$Uc֥\u0010\r&\u0006\u000fSa\n(H\u0010w#\b\b)<\u001fa\u000es29C\u0001>\u0006q-JFP\u000b.~1͵\u001a~L{\tMH\u0012i\r4\u0019\r-JG\tl\u000f\u0011l+@5c`\u0010*o\r>40E70c\u001bۭ\u001e \u000f+W/\u0005p\u0016dK\u001c,1!\u0001a7\u0003fF3bl\u0018l\fm\u0015\u000b\u0018B&xjG\u000f؄\u0012\u0000;@\u0013 |\u0015Ro.\u0019\u000f<\u0003)>\u000b?:c\u000em\u00179&'4^6O/\u001e3\bJκ\u0011sܺbCg\\o\u00073@\bji\u001ay\\g6\u000f\u0007^g8\u000b\u000e9@/\u001f}o\u001e1DN\u0016\u0016QCb\u0005w\u0003D\u0002&A\u001fzkN#\u0000\r\u0016-:Ncnx\u001d_`=\b\u0001\u0016'd\u001862\u0018\u0000\u0018!'#\u0014\bFW?r&eR\u001cR;㚅ͬU[uv\f~&v6IZ\u0019F\u001ePI\u001c`%XEnE㮥>y\bl>7\r,f=F\u00185\\3\u000eKTh\\5\u0011!%>擤!s`\u001a1k\u001aD\u001f-\f^[c\u0003\u0011sX|\u00070>\u001eCMlFY}\u000b\u001fs\u001d$A\fnZ5d||X`5?b\rߝ\u0010%b&&ϰo_`aM<\u0001~\u0016H{xy71RX\u0007\u0007:8{\u0018\u0013WYI\u0018ň%\u001e@#_&A%WL\u001f$u8x\u0015WXQ>8B>\u000e0uUJ\u000b&^p\u0006Kd|\u0014<a\r&\u0017iD\nɷe\nׁ)Vޒ)V\u0014p˻K4w(_\u000bBS\b\u00104n;6Yas_\"\u001cx\u001bPz\u0007\u0010^dt\u0005\nu\u001d|L/ANAù#$^{Yz<SU)\u001b \u001f[\u0013x30I\u000f\u0007PJ_e:\u001fF=3S?)\u001b(\u0014G,\u001a\u000bJ.y\u0002_\u0000?\u0002\u0007`\u000f0\u0014!ݴo4-2yV0~o4\u000f}6{4?~\f\u001b\"~\u0002:8\u000b\u0019ܛ$\u0014_,`\u0007x\fpz&Ck*2hK\u000bqxiFA8E8A8{\u0015?'i\u000e~yX\u001cԟtN-\u00148x\u0018l\u0001wR:3vN\u0012k8Z\u0018\b~\u001c\u001f^i\u001f@\u0001Gu>G|FwUV3]\u00146KD\u000e_PLpo\u0006Fp*%U~/N\r)ڇGNvS\u001bO\u00138\u0018jQv85mjd+~<L<P6A<AT\u000eNyes\f|\u001d\u0002+EďX`\u00068MPei ZN˨n\u001dv6vh=5\u001aY\u001fk^t7VVRy0Bږ;\f\u0002K[Znv\u0016X0\u0011cK{N\u00079.v9+\rb;B+mv\u000bvgS\u0011ݴ~߁\u0015TZڄWߣzO弩\u0005\u0002x\u0007@j\u000fXlfa3\u0019.|6@\u0006brl\u00075]\u0019m*fcJ\u001dxKH\u0010n2;6\u0000s\u0002\u0007tr1#<*\u0007]'`;\rdb?J,~9\u000fc\u0011{_\u0007Og\u0018hgUmDBg&O\u0005o<\u001a\u0017O2\u0000:\u001a\u0019wE' '\u001d,8(\u0002 \u001c\u0011lFv5Uh7\u00062W\n\b\bt0\u0011P\u0007\u0018q5;\u0019\u0006@\u000fH\u00071q\u0004(\u0011N{\u0001\u001fQ@\u0016S\ttOx\u0012ZV1j\u001aTWSUE_m\u0010^\\[\u0019Ɯ$\u001c-\u000b\u0019zlu\u0013\f5O}\u001d\u00148!\rd\u000bW!\\T\u0013FlU\u000f\u0011\u001a\"[y\u000eO\u0011d\u0018\bn8\u0004(G\u0012F>Ɵ9\u0015D\u0003!Mǧ);\u0015Lr+jOU,U*.V\u0003_ZUbRmP*Q!y7^\u0018\u0003'q~&\u001c>\u0006@\u001d^gUcS;Y\u0015))*wzT0TjĞb{\u001c*t\u0004T(Ѭ<grq\u000e+˹Z\u0007xJ~!ȗ|\r\u0002qm2\u0006\u0019˻\u0018[\f\u0010\u0002\u0001U2O\u0003%$\u0015{\u001c*vTS+Ky<Mu(]\u001cwX&ez:WgX>j\u0019-JsH\u001eOU/\u0010Zl\u000f(\f\"\u0006Tr\fO\u0011\u0014%*HV^SSS\u001aI++5W0*7B\u0019MJ3:e\u0018\u0003\u001aK1VmlxRS4Na\\\u0001ɑJb1\u0006ǐ' \u0004A9J@!%7=A9$e(ϗ\u0002P&#}cr?\u00068ʫ\no6$,fwI6l~vIHBH&@\u0002J\u0002$\u0010\n$AkJJJ\bRZjŢX\u000eZdZQt:0\u0002V\u001d\u001dvږa\u000fV;0/۽=s}o\n|ӷCy\u0007d}Ke+\u001c{y3\u0006݌slP\u000f⼫\u0002\u0011`M2|e\u000ey*\u0017\u0013\u001d(\u0003!\u0015\u0007U\u0014h+ت`>9ò\u00077\u0016RN\u0010-\u001bF\f \u0002\u0017\u00186`\u0015|KZi\n\u0016\u0018|\u0017\u0002A|\u0007l\u0005r\r:)w\u001dr(4KP\nQ~RpBpN\b\u001d/B׏܆hDѲ!|\bPN\u0015\u0019c%|a#hp\u000eJF0ߕK<Gr\u0015rG*TPV\u001e+*X\u001c瓀-\b c\f\n-[ 1!ʜ\u0015\u001fޅJ\u0000x]\u0014%oʀgO&w]E<\u0015T\u0017\u0011/Ɠ-ZMT\u0001D+`J00%F\u0000Q(b\u001e\u001b'h\r|},늑\u0007\u0004]/\u0011\u000f?<w}QܦZ\u001cu4z\u001aX;{S$6ł\u0014:>żbxLq㤸\u0001Sn~ǐ Ѐ\u000f\r(%\u0019\u001c]%\\a8\u0003g\u000f|JHlHOq4\u0015di\u000b\rX\u00116\u00165\u0002|ՆoexhE0W!\u0017Д\u0000./n{\u001dy೎Y\u000e|<\r\u000b\u0014s\u0018cZlŏv0\u000b:r\u0000EE\u00160&u٦0k@3\u0018\u0005n\u0005Ik%\u0010e\ro!ya|\u000eHsvB!'KA#\u0016KYd>`]*Y \u0000Ճr\\tu\u0005L-1Glk\u0000Kx_\fo\u0001\u000e8I/\u00179kA\u000f!h.\\c\u0006 \u0005<FVx%XPb14\"sq}F\u000b(vxg\u0003Um\u001f\u0002xm7%g\u001b#rVZ\b5d\u001dc\u0004?%DN)q63c=\nq\u0004Ŵ\u000eyּ#\r3\u00116\\/5\u0011Q\u001c%,iD e\t$~l6[)\u0010l&`,4o!$>\u00062ꄯ\u0019MS\u0003~w9Xeqrđ\u0005&f\u0012Njn\fq/X6\u001a\u0006,ao=\u0007puV?&kyGC&g\u0005\u001d\u00103d\u0019L(9\u0006!Qj\u0000g\u001b\u0001k\u0004y?\u001bۇG>-})wk)\n!#6ko,c\\Ɋ\u0018A(\u0003\u0012f\u0019\u0002C\b~\u001c\u001eyCv\u001e&\bړ{OK߹F*Jy\u0015W=\u0016烀%\f\u0003qe#3p\u0019H\u0002\u0001\\΀\u0015j<9y{@&/|N:\u0013gT\r\u001f\"bc|'k\u0006u4\u000f\u001dJg-_\u0017-__߃?[m\u0015rrz{\u0013ҿr\u001dGQ\n-@t%\"}v̨N|S\u001dtLF8$\u001fP3\\PEM\u0000/3y^b\u001a}\"3ɹ#LV92l+C\n3l3ԑ)eX%x\u0007?<>j*\n\n-tL4\u0005&qXsh^x_xOǋqJtR{\u001cL(P\u0019&˽\u0017\u0003v+p^\u0004Z!3\bNe8\u001cqY\f\u0014Squ\f\bsa\u000f(C2M~]\u001f\u0017\u0007\n{mf{L\u0001m5\u0003:'`6?)\u001c=|w|_APŎL籟.Li$_y=Bz\u0018?\u001e\"\u001ekz\u000fǱ}p_!B\u0019<DKM`\u00022:\u0001~b9^_#nrGL_Y^.=4.r\u001aى\u001f;v\u001eo'3xll\u001fy\u0005\u001f\u0005`\u0014<gu\u0014͑\u0005v\u0012\u001d*499T\r?n#/[ne\u000bt\u001aLh\u0019l\n\u001dFn$'Dh\fR-며\u000eU`\b\u001c\u0003V\u001bf&&L{s\u0001\u000f(\u0003!lǰ]\u0014v[a`^LS\u001d7\n\u0004U;Mܧ\u0015,\u0006~x?\f,<fﲸU`\u0005s%vX\fSjjcX~l?\u0004mn\u0007Q\u0012\u000ep\u0006JU=ŵ[}mtڿ\n6Z0\u0015jTqlA!vݠg?\u0015\u0010#\u0004o^\u0007v\u0017P}Tʠ\u0013NAVQQf^\\N\\Z]g\u0015uJ\u0002Ëꘑ*F:t\u0006J3Қ\u0005p\u0004\bc?\u0004RlBM\u0010fbfs\u0012R0$<7Af\u0006\u00185\u0004\u0019e%\"H'#ݸ\u0000\u0005\u0018\u000e\u000f('\bO\u0004jlcIxӀD&l-Y8\u0017K5t8\u0001&\u0006\\+7cHTûH\u0014>%}']\rJ)\u001c(<5kn\u000b\u0013t\u0015b#BŅ9\u001f!:N\u001aw\u000fp\b\u0010CȎn\u000e$|_)nSV\"xf\u000fO\b*x\u0012lyxH%k7\u001dx\u0010xSsp\u0019d;I쯇o9r8+[@\nԁ8cҕhC|E\\\n;\u0015{\u0014Tn\u000f\u00026ٻ4wX܍*ɝyyr\u001egEo/(3?do%3$$`BH@\u0001\fU\u0016\u0018d(\u0015Q\"\u0014EED\n\u0018TPM(Ȗ-Z\"\b\"K\u0005w;=\u001e4s\u000f3_sg\u0004}\u0015ߖ6\u0015(\u0005M@\u0001rA\u0016k&Ь\u0012%vJ\u0001^\t;\u0003\fK\u0019\u0013gM@\túZ|\u001eu\u000e\u00169I<9v,\u0015}l\u001f+팸\t\u0019\u0002O8:C_\u000bmk<\u0005b\u0013$J.!)A-A&\u0001.~OHtO\u0006\u0011HZsѴѪŭ$NV\u001c\u0004i%M[\"V\u0006x\u000esRܢ\u0001x:{u>\u00034\u0001 gq\u0010\u0005YBz\u0004t}N}.ѽ\u001ez\u0005DEģg\u0002q%+ġ\u0013~\u0003Ţ\u0013N\u0018y}d8/aKbrg\u001d*bNE}\u0000\nA\u001e3A\u0006\u000b\"\u0001M~K[4[<~M\u0001\u0002\f\u0011\u0013[\u0005[%VA[\u001a\u0004\br\u0013\u0005N\u0001j\u001f\u0002?]༆ey\u0000\u0005|\u00011G@(h`*]S@\u0003K!M>b\rG\u0012\u0011s\u0016)\u00034\u000b\u0011N\b_\u001b(|\u000f \u0000SC\u0007,u%7\u001c\u001d$ђ4\u0001ų\f\u0010`\b\u000f6уv\u0001-d\u0017wCaآ\u001eļb1a1\u0006\u00051NS\u001aaȤϋ\u00008!5F\u0000 -ES\u001bw':{U\u0006!<\\>y\u00160\u001e?*>⎤3&C̙\u001c\",\\&57\u001aK?GӚ\n\u00074JC\u000196g! -dSC\u0016I23!\u0019rm3A\u0001{Z\"\u0011%\u0000I\fcfqdZ$-*\u001c\u000e<\u000e|6xc\u0016w!^\u0014\"0Å(\"\u0017q\u0014k\u0016\u0002NƤ5!96\"M%3\rCs\u0007o\u0004#:2\u0013\u001a4s4/\u001c%R\u001aL\u0019Z\u000fJ\u0001k\u001b\u0019M[f\u0006\nESjhrٓ\u0014\u0014\\gRG\u0014\u0010B\u000b%xPEWjI],-VI\u0005^T0\u0015\fG\u0015\u0015FZќ^IRkA#VN,c.'Zϕ\u0018\u0014\u0003W:g/\\hL1$\u0017iRUkkuRG[bNڱE\u0015\u0003A\u0015\u0013Κh˺نTIn}\u000e\u0003\u0012Rɻ@S3$\u0007(\u0004\u000b4[f\\\"\th\u001f\t/\\4D\u001dSGwΆ\u0017݊+yލCF3\u0013gDv6\u0003gTT \u0015a[>u\r\u0005\b4UFhF\u00114B@?hI\u0016|\rbaX_\u0006MbHДt%\u001b0>B\bS\r.\u0011z$f*|ը\u0010\u0004j@8:FF0'YPyH\u0004`pΪ4M\rLH9:KFf T\u001a{\u0019|jH\u0005h#\u0010O\u0000S4p\u0017udd\u0011q'q\u0007m*i~RRB7\r೛%lj\u0004ۛ\rZo\u0016Iq@>CRM}jP~D&%x8\u0013(\u0004\u000f\u001fD笚|9*Ŭvh֘Ws/wQqN2\u0014,\u0003AI5F(SB)R\u0007V$M׍lux\u0006Uyd./(ǘ\u0017n+\bД<np5\u0014\u0017K:ٔ\u0000+sj\u0012UdӨݒjb\u000f\u000f+1'\u0007Xo#M\u0014c[:>ЬB݆\u0005j>\u001a\u0014\u0017׍l\u0006[\f{\u001b\u001cT3\u00158\u000e؂r99<\u001fcBv\u0018OUd\u001cN[`(\u001cY9y\n\u001a\u00176izEqe-Z^Yqխ暶U_WݱSv7٫w\u000f\u00188vC\r\u001f1r1\u00197~¤Snco5{gκos~?\u000f.x?.|EO<䩥˖xz3ϮZ\u000bk^Z~Ɨ7ymn߱s[{o\u000f{>Og𑯎~}\u001fϜ=ϟ.\\J\u001aJ]IYWQdg+\b/RKrR+kA\u0001ݔ\u00037)\u000bnƃ\u001ae-ʅpa2b\"NLUV܉\u0017w+3~ܘ\u001dP~<\fy\fG\u0016+K<Ô+/b:&e+8fMy[sP>|\f\u001cT\u0016}<:I?().^J\u001d>\\ͻ%\u0019~\u0018__b2\u0016\u0015\u000flv\u0007ǣaO\u0011\fG8#\u00191<\u0014\\\u0016|\u0018LҚ7?3'\rt뮶\u0012;f[\u000emq\u0013&O6}ƽfϝ7\u000b\u001f[xe+.j[ȤƟILiLT*N\u0014h\bj~o\u0013'G\u001f~83gϞ;w\u001e?]p\u0006ƶehbm֮-\u0012;zW_5a\u000f\u001c3Жj꩛sӲZdOG.\u0017\r54PCC\r\r54PCC\rw\r+\u001au\u001d\u001a%^]/\u000f9\t_ԏ-~kwe\u000bܝVOѢ'~HPG\rVF\u0012ծ=Ͽ1}C&|ww>/n{y\r/Mٵz\u001do.Ѳ{_d'װ\u001a6Rk]/޳̾\u0017{t\u001at\u0000p|gvzffgi;fiNд2/\u0014\u0011\u0011\u0004A\u0010\u0000oF)TLP.\u0015\u0003\u0000\u0010\fE[\"-)'-߶g/yޘᎀN\u0003\"_\n)Uk\u0015a\"a>W\u0010~\u0013ՓĢ\r?\u001aJ!&vezzc-̣>$Ck\u0010SFkCe\\\t)j3J-)|ʉ鱶\u000f\u0006\u001ed(;\u000enZs>w'C71}fDm\u001b<W\u0018,\u0010QduY\u0018կ\u0012b\u000bOi6 \f| :\u000en\\h[S\u0006<Fǯ\u001f%\u001bwE:\u0004!D|\u0016%K\u0015\u0015Xu#\t\u0006\u0004?װ\n\u001f\u0016}~ϴv|ʵM4Yg`&_`3Ȓ;\nTEr-ZFbJ\u0012_\u001e6P@\u0000\u0019\u000e]Tnm=1l3<qZ'J7V\u001d`\u001btH.]*GS¤j|\rVJ[\u001b(\f{V\u00015o'92zᴫ{˔\u0007z؇\"\u000b\u0019\u0019ȂD\u001d\u001bA\u0017زz|9ZN6P\n\u0019J!Cճ'׏:ڴ^tSM_CƼ\u001eDz1$\u001a$7\bM0-\u0017,6P\u0006\u0019XP\u001djw摳Z_8l|rE:\u000eNxc\u0003\u000f\u0011~T*\u0007 v2pFB6\u001b\u001aŴ6 ޲\fveF`5mgw8ȀŒ9[yވX\u0018D\u0019BGG<\u0006\b\u00183))\u0014若[\u001bزl^ў=ǏSϞ)\u0001v\u0004{7w\u001bo\u001982\nbpO8\u0013\">\bX4\t>J6 3O;F.\u001c^h\u0007\u001e\u0003\u0017\u0006W\u0017}F\u0007]υ\n{E\u0012\"\u0003f(/c`4Ѭ7h^!}w\u0007>85\u0007K\u0007\u000ehʙH\u0003AΡ 5\u0018.\u0007-F\\\r|\u001f\u0006{Gq{\u0017\u0010im=/ZtU\u0002p\u001cpdK*8+\u001a#KD0\n\u00043\u0000{\u0017\u00007\u000217\u0001@Ao\u0006Pa\u0013.\u001d\u000557\u0017d0\u0017\u0012\u0014~DK2qH9y\u0014\u000eBCOmHLU1tՔl2\"8dX2,\u0019\fK%e(\f%6\u001b@\u0015du=\nםj^A\u0004\\ˎ*\u0019$,!2.K\u001cG\u0015v[\u0007=ZP\n\u0019$A\u000e\u0019=]\u001b+#\u0018zw\u0019^\u000bXaF*b\u001b\u0013Z*SRD\t&^\\\u001d4h`C\u0006͏@v~'x\u0014<\\վAGi]\u00158^@(WI<}I\u0016XA-edYÍDVa(\fe\u000e\f\u001a\u000fZ\u001fg:8QCHz,I\u0014^P\u0014Q%xI-02\u0003\u0016,탡\u00002\u0014A\u0006\u0011d\fjk.s[g-\u0001HQ$Xi}yJ&E|Ne2\u0019\u001c@ZF\u0000\u0003\u0019O\rAF#\u000bzw\u0006/؄\u0011\u00169Ќވ0RYeJ($9\u0002J;C`M􂜇\u0002}0 \u0003\u001aP\u0001\u0019/69\u001f&I\u001fl됼:y*LYT\u0016~?W@lͥt%\u0017SY\u0007BfaC*Pn;ӑW_ހ}]M*\u0005'(bN)%O2qbzȅ)}^K\u0003g\u0010\u001cX\r$'\u0003mo\rN_u_q\u001c\r\ry[\u0003\u0018r=P\u0010\"fUdVp\u001d\u0012\u0005=!\u0012:qܴ.K``Z\u0001J s^9\u001dz5-\u0017&i\t*ઑ9u(I\u0014#ObD\u0004\u001dQHnƖP\rVK\u0003E\u00102\b\u0003jVwn\u000b\u0007'\\\u001dG&ǼԲ֠\u0002m0N\u0003J\\ɰuUH\rZ\u001c\r\u0011%4Y\u001a@\" 5P\u001cog1ip`䉳\u0015ߦq/g\u0007(\u0001M\u0016EɱZ,T\u001b\"V $\u0006K\u0003M\u0000\u00072TjA})Ï\u001d9;\u001ag/(Ė>\u0019Ȝf\u0014+Z\u00125b \fm \u0011@9\u0000\u000f2\bv~\tjl̆q\u0019'G%7B#~̇ސ\u000et&\r\u001bn磛#XB.\u000bx\u0006\u0004\u001b\u0001ю?S]1a<u톖)/W/zfnNcSGq(j9,\tߏO\r%Ɍ\u000ej1!@πt\u0017/,7\u000f]i\u000fu\u0016䁇a\\ŎUq\\3:Z:.g\n8g\u0005:\nEl\u0005A\u0010\u0016,DBHHB\b@¾-\u0010 \t@\u0002%1,\t{ \tE\u001b\"\nZ\u0014D|>^w>LpP\u001d8:H\"Ol@H4@D E> Eߧh\fx\f3{\u0016\u000b=\u0010\u001fp~@bIb\u0015)y`o%65~)\n}\u001eOz\u0011\u001etGr(\u0019\ryĆ_\rx\t{L|@mT+5s\u00077*N\u0011\u001eȁ3GR]\u001cx\u0002څ\u0016)\u001d|9x^d\\\t\\dyb.pPdmkkm_\u0000\"8\u0007'q*\u0006)\u0002\u0004c\u0000{&\b\u0006B?P|5\nb} \u0015\\hXL35j1|\u0007%/h`?\u001c\u000eb!4\u001dУ( \u001c\u0013^@9\tSa\u00016\u0004\u001d\br\u0005\u001e%'Pb\r5A\u001e(\u0007=\u0015)\u0013|FI\u0002S|F!'\u0015\u0014Ac\u0007In#V\u00124jBkn\u001f\f\u001f\f\u001f\f\u001f\f{C.bE\fa\u0017Ԟ\u0006=ag*\"\u0004t\u001cVP*GhHLf)sUQ͚H%PY~5[\u0003y6V!zgkhpw\u0006K\u000b\nL\u0013y\u0004}\\DM\u00193\u000b3\u0012]\u0012W\u0011dki\u0005jJ$#d=U$yA\u0018\n7B-P\u0018\u001a\u0006%\u0007P_6`\u001eׅ3$\u0012}N+5AIL62U<C\u0003TE.3Q*{\u0014Y37@9b\u0005*\u0000>`#%yWF\u001a\u0014SE\u0005\fE[V\\Ks2[nh`\u000fԱCbx.\u000b蕽\u0006|Đ\u0018\n\u0011Cű-\u0002NV>ߊ=jV\u0010y&\tޠe=\u0019<S%tX\u0010+\u001agJyR3\u0014!\u0006鱿A\u001dbhv\u0002W<\u0003Z,2<_\u001e)*46%SK3J2x&a`8?A8ͮbK\f \u0000\u001e18ZAE7]^\u001es\u0001̈́<c]DUT1\u0002v$?P\u001cgGSӸ\u0003i\\~1\u0014 b?C\u0015bh\u001c4Vo;//<=\u001fh\u0017JMm^V\nzE\\\u0003 \u001fN\u0016^禗\u000fp$Fs\f%A\u0018AhSϷ\u000bzO\u001f}\u001e\u0007G\u0005-\u0006rc).\u0012&\u001axũB\bW>ή0ۯk@\u0018G\n*h\\̰O\u000f^LA m\u0016(U42fwO\u0017'\u000fpxa0|YPa47(t%\u0011\b1 \u0006Ο;\u001d\\0^\u001dvw\u001dvgԟg\foB l;e^cdUd\u000b\u0007~Pb07(Pf\u001e\u0014G?\u0016^;87rzĸ\u0017~_|)8Wх\u00105\u0012S\u0015\u000e\u0013S\u0015rI\u0001Td\u0017C!b@\fAs\u001f/\u000e<qv\u0007qXMCAR\u001dFӯ\u0011T\u0006bkt-#sUV%U}8Y@\u0018\u0006@yd;f\u0007ј/\rOy`Q\\GgC\u0005ٝ8\tP\u001b&*)&b\u0003\u0015Wl\u000bM@fv\u0006\u001d\u0014#\u0006\u0001b\u001f\\\u0007MG6lO?w3.}CU\u0013(&:\u0014҇+au\u0011*mDYD+6ZQ(~ʌ&s\u0012PcP|M\r3\u0003[ǿ3E͋KAIT`\f\u001d9IK0s\r^R\u001e\u0018E\b`J\u00032_m\u001cM67\u0010n\u0002Ձ/t]wI}YSԽt\u0013Nx\u0013h*w\f\u001bǼIH\u001eN\u001cd\rr0\u0003 #oH,BS}\u000eĈA7ar>=s߼tD[gnyQAA\u0004$L\u001fN\u0018'3\tc8\u001dFBm\u0016\u0007}.)\u0019u#=g4b\u00054~noUc[\u0016Q\u00118\u0000ܾMYBy͇\u0004fBHOI8t\u0014\u00018\u0018:\u0015K\n\f|H{\u001cȠLd\u001dT}ūoݸ\\7gMӫ[e`\u0004\u001c\u0003G\u0014p=\u0002\u0005ϡn\u0004O\"\u001b@E\u0005dY\u0001s@\u0017\\4yjlflV/o.=ٴBj:\u0019\u001c*\u0013n%}\u0001\u001clNmg[SeJKn/T^\u0017\u0014\u0017P@\u0001QQ\u0011Q@@\u0010\u0015PA\u0004\u0011/],Yinm\u0017yRؽ\ne[\nC>\u001cyE@)H;a\u0013\u0002#ssE\u0002fKϖ?,?_V3|~\u0015l\u0007\u0003EfA\u0004x8䌃\u0010X\u0010H\u0019\u0004?\u0006B\u0000\u001fr\u0003\u001e_({\u001cJ\u0018h3[\u0017^^0_\u0002\u001fS\r\u00163`\u001cp^A\u001fkO\u0010\u0010\u0000o\u0000t\u00027\u001f$磐\bdm\u0001Ð\u0010А\nP\u0007+\u0002\u00066/\nf^\r\r\u0018G\u0010p\u0001\u0011\u00131~)\u000f$T1|RB.玦TM\u001dI千.YoA777SCkCɦC\f?\u0007#4\u001dwPO?Nf\u0011o0qZ\u0011bNYLn\u0019~(VbO\u0014Km\u0016kZeu8\u0012MB\f̵Օ?\u001f?\u0007#Ȏ,kN\u0012\u0019D\u0018s:#:'>V\\9Oe\ft̚R2'L掞8N\u001bhmנ镡\u00141!?m\u0015b\u0010#\u0006~GP\u001eq\u0005E\u0010fV\u001e\u001e\t\u001f7UO$K.R+\r\\f9\\cLu%u\u0013MXy\u001cߪoNhkG\u0013WF\f5Ak\u0015(9\u0015ԁZ$)93Ε\b4Rf\u0019iNb]6*MZIn\u0011AӉW2v\t\b-&Ġڷ\u001e\u000e6\u0000[ɐiuL\rY\u0012e>3\u0016YK\u0002@e\u00046rU/\"4\u000bS\u0015jb\u001eM\u001a\u0011C\u001db\"\u00065b@\f\u0017ЇIUBEI*w:SW.+Է\u0017\u0019[i>9Eߔ+UK\u0006\u0019r\u00137Se@\u0013p^\u001b*6\u000fA3x\u0007!Y\u001f!,!*y-vANEM&ACӫ\fc\u0011\u0004uԆ\u0001nvC$e\u0017^\u0019X_/\u0002.b\u0010m[\u0006rĠ\u0017\u0018\u000eyb\f\rg \\)\u0013\u0005ƴ&}\rIQRV\u0014mz;hg\u0018yn46,\u0004\u001ebhغ\f\u0014;WB;b>t\u0002\u001c\u0012v/KWt:A`jNmg\\}CEŴ\u00156NΠ7\u000e\u0016Ҥ}4E\u000f\u001c1\u0011\u0003\u001f1\u0011\u00121t\"\u0006/,1AaO\\4F\u0015ٴ\u0002C\u000bA\u0012Jd2ȫ(8\u001c\u001bUm3\u001b\u0007R\u000bHaD\u0013 ذ\u0018$[\u000en+A\u0003?\u001d\u001f\n\fcSΙ#\u000bͺvUD֜Zא\u000b)F/\n\u0006(F;Lj!\u0018\n14!\u0006\nrf\u001fס^w\fY]1|6QHUU5gvŹ=utsԚSͳe׈\u00072xRKFE\u0011MP\u00188\u00061H|\u0000ZOgk1\u001e5\u001bzq4`.dzXFPV(3Kd&Z/a\u0010sbP+KV\u0018PB\u001e\u0011CǎOf{~4]=\u0011|RPIZ-`\u0013\rI-|M)z圾\u0004Ђx\u0007ME\f\u0015os\u001d\u001f?߻IocA?c)ґ\b\u001a]쉗RtIZb\u0007Ae򺣕EHE)B)2*\u0003\u0018AW8/1/o\\\u0003\u001e#=\u001as#\u0000\u001aǒF#l{t%/NՓ %\tʸtM~\u0019aB4|}\u0003MG\f5\u000bq\u0011tl^\u001744r\u0017a\u0013\u001f8\u0011\u001b((>\u0017\u001d'\t\u0013)\r1tID\u000fIz*\u000f5\u0014+\f@}\u0015\u0013\u0007;XpgӻG\\^km\u000f'#!_ٴ_DTXr\b\u0012R,-s4A8K`\u000fqqY\u00039UX[~M6®Q\u0005UA۠]tw\u000b\\ԮUGg<<?x_(>6`**9{\".#u<pH\u0019,\\x\u0002\u0018;Jgg\u0006h\u0002\u0001j\u0017_9Lq\u00184ku˽Nswy\u001f(ϗd\u0018y\u001a\u0017IK\u0018;N$\u0011'sOMg]/\n$\u0005^y9h:жrL~`v@\u000b\t(\u0000\u000fW6xϛ<{\u0018q&: YBHTl\u0011)؇\u0005\u0007Kc\u0002ǣ\tڻtK_gaMY\u0018ǙqZG\u0019uֺUjQVn\b,\u0001\u001a!\u001d\u0002\u0004B\bd!\u000bK\u0012 ,d\u001f\u0012\u0012D\u0014\u0005PZq:ZZg~y:E/7\\ߙ}E;Y+\u0000/W\u0016\u001c\n\u0017CA\"f\u0002?\u0015O /8עгV:sMx\f#L]dƨӯӌy.Z\u0007\u0005rp_OF\u001b6\u0012\u001cߙ\ra\u0010\u001f\u0007^\u0013\u000b\u0007cP4\u001e#@9\u001a\u00014p`\u0001X(^\u0011<\u0017|\u0017ͳº<ض\u0006\u001eJsm\u000exok\u0002\u0004Bi팄Á\u0014}\u0012\u0006C3\u0004ȞP'\b{\u0003$N}s]\n݅Tf\u0011\rV;pd}\u0004\u0004l\f\u0010Im\rt\u0013?n;\u000e$TǠC? \u0002\u0005E}\u0003e\u0002 {,\u0005k\r|7(\u0003^\u0003\u0018^B|Xλ_+'QTyZs'1]%~\"0]_,p\r\u001b/\rP\u0014X \u000e\u0000\u0019/O\u0000'7'fiwԬ\u0007uӅܲ)562]ɞHi\u0018OJq\b>\r7\r'8\u001f́j');\u0002\u001bm{k&h\u000bho\u0010'\u0007'DX_A!NW1K)LY\u0013[\u0004\u0019FfZy\fon: \u001bL\u001c㆚\rP\f5ۗ@+@t =\t\u001e 򆶤YIVS~AƷ\u0015ST*e\\W;^^'cF:/\u0015n\u0007΢w\u001a\u0006t@s[\u0002\\d FP\u0000E\u000ft$\u0004H3>\u0011eOsJ0)/(k\u001ch@>Ӭ\u001cn\ffvhN1{\u0019vg\u0003o\u0006'\u0019h9_\r\u001d\u001d\u0001\u0011>u6EgZcin=aqW\u0015u7h4(N~\t=\u0007\"l'h0SF\u000fI721MGMl/\r4d`B\fmȠ8\u00114'<@sgV\u001d\u0017;5Q9Ts\u0001\u000bny*rQ(\u0005\u0018FRi\bھ,\u001d&#{ZsJg\u0003K|ݶ\u0018 ۷\u001a6@\u0007|ftgB&'=TeH[\u0012H}\u0002U{˚6˪Zs}\u0012I/S9K\u0003\u001d\u0019 'h߷\nT\u00077P1!O\fI=\u0019;sc\u0002PcƪQ\u0006m%WY.(IM7\u001aـ A\u000ed\u001c|\u000fLg\u0010\u001fGX\"nJVx+9J\u0012\u0005%rS}Zd\u0018\u00145\u001cLV%THdHm/6%^\u001a\u0018AfdP]\t={}\u001a-*[[|\u001dSJј*9(#6a\"[R\u0006)|Υt9Xe*\u0007\\of{{\u00018\ro@eЅ\fփos{Ȑ選\t\fWtEi2\u0014ȕMe*icAfa<&ZOki\u001d\u000e*QCP:gZd`\"\u0003\u0017\u0019<A72\u0018`/FL]8|ÖT4dHc`JBFF%%*Rmd`l\u000eʨ\u0013kJFLa\u00154g!MP\u000b}ޝnI\u0007#\\IH(tS\u0006M@ ZE<\tY_'lk\u0015WOn:J\u001aT\u001eKIIlP\f,d\u0010.\u000292h\u00190u/\u0006}ݾ\u001b\rtZXi\u0014ڐsM\u0005JLGk6WJX}\"Pb\u0017y\u001e\u000bѤw6[ ܺ\b:y{G=~bxHkQIqF\u0007ډs\u0006B+GC+K\u0015Ub9\u0003#\u001a2 Sڲu\u0018Ad;\u001b ޺\u0010ܗ\u0003<ruzDXbbu\u0003ȳd53MĎJ}X[SL\u0004\u0015\u0007P-i.\u000b^7:gzdC\u0017z_-?\u001dZs-wyޘ\n\f0\u0019\u001eo\u0019C츚P%R_;!Ȋ\u0005]D\u000bYKlCɔh$-q6ଜ\u0003@e>/zn߽ʯ'\u000fmytSqф̚t^s4{\u0002g%wQ5g,lmEڬJg\u0006d୛\u000bm\u001d?g\u001b\u001fz\u001f\u000f݋NP*|3I\u001a;\u001e!\tRŉC䖸\u000b5mkey_goMi\u001c#\u000e֊NǺ_ъbZԊ\"\u0015(\t\bD\u0004\b\tK!\u000bـ\u0000!!@BB\u0002\u0000\t\u0010\u0002\"ua(nXQ\u0014HU^h\u000e?\u0007ܿʪ\u001e\u0003@\u0002\u0003\u001a-g{\u0007\u001f~o٦w7iaݯ'^\tEQG\tT\u001eŶȟEa\u0003|1H\u0012x]&]-E\u001b\"\u0006͚`^?eܡaWtL\u001dmqu~)~?;I _)OԄi_hY\u0011\u0016=A.3+\u0004ݑq\u0003+rnW\u000e-n/\u0019^2禰\u001agl\u001f\u000e}'=$qϛ2 \u0006&\u001c\u0015[ft\u0004\u0014C\u000e\u001f\u001f2.L?+N\nz*\u0006)ShS\u0006es\fs\n\u0012)[+,vU%8Zy\u0010ps \rT z\u0003;v6ُ.3 -#0l\u0013\u001c&\u001f.\b\t\u0016\u0006.\r\u000bx\fD\r\u0019ꞏ|c\u0001es\u001b`\"5^Y\u0002{\u0016\u0006J\u0007OD\b\u0017\u0007\u0004'\"\u000fE\u00025\f2p!8\u0007 ;\u001a\bB\u0000\u0010\u001d\u0007q(\u00057n\\\u0004v{>F\u000f+,Uy\u0018v.\u00055ก\n.I-\n\u0002vA@\u000fDl \r\u001f8p\u001c}!\u0007\u0017:\u001d\u0003\u0005.uXb,15(`ռbYȅK2Uw\r\u0011ׇ\t\u0003\u0016_ yC7^\u0013R\u001f\u001e@q\u0014X;\u0000o;w\u001d]8|6s\\\u0005F\bV[a4,\u000e/\u0000Aqp[\u0005k=;\\ȯ f+7@!H\u001126:C6\u0012 pm \u0016ml\u001cO \u0003+8{\u0016q\u0015\\ׁ\u000eD!P@rԣag\nBdI\bR&ԉ\u0013\u0017qMYϢhc.ƓޜG\u0011{a87N\u000eso5dX\b݋`J\u0010#\u0012o;A\u0014\fccx⇿\u0015LNHV<OxF62\u001fGF_\b#yCaC[yh\u0002\u0016\u0018}!\u0018D?\u0004١u  \u0007\u0012\u000f( \u001bKd\u0016&̒=KU\u001e'U\u001eQjx#$\u0003~Yx/\u000eh0_|%|@t)\u0000MF\fLd0-\u0004\u0001/$m/ߠ\u0003\t,#]@\u001aN\u0019\u00144\u0015<r\bUſP]8Ln\u0010\"e1]}}\u0011}\u0017I;\u0003\"4\u0001\u00071 \u00067VP\u000b\u0015@\fv\u000e2\u0015~oi\u0011E9ќ\"΃,`8U)\u001eJ*AW\fZ1]\u000bU]KWNcKj\u0005\"p\u001a\u0017\u0015k\u000e~X\fu{_\u0011FLUB\ts\u0019#\u00020]\"\u001eL//\u001bj(+$7\u001cS\u001aӭm\"]V\u0018Weh\u0002./Xmkg\u0005❟A\u0019/*\u000fvPs\u001c$nF\u0013\u001d0U\u0014R6*p*\u001a)g\\IQ&$\u001a:)\u0006SL\u0010w^\\R\u0012~!\u001f8%A]\u000eڃ_\u001e\u0005}x\u001aB6>vL7(I\u0015\u000b\u0019sU\rg\rF3Lc\u001dL.SITS\u0004<F\f|dHw\u0013*@\u00154 \u00067v\u0018l\f\u001c%=T'\u0006eY«,<%n5g\rڦfmR[zAҭ-KUAi\u0001\"\u00062=\u0006ngM^iS n)<q},&q,]xQ̐u\bx*3@gd\ncuvu&ѤHom9v(8_-ͼB\u0013\"\u0006ΆyP\u0018\u0017a)!fZ=\u001d\u0002p㭡\u000fє\u001b:\n2E)˖*\u0003\u0015kXF%Tƨo3M\"ZWM\u0011\u001aM,S(C\fUKis໦z2*hgʌ\u00120O\u0017֗\u001ae\n]k\u0016[\u0002F[ TN\u0006M\u0019A\u0018\u0014Ag\u00046W鮣//\u001cw\u001b\u0007\rER\f$zGuY.-*\\]YD i,Wy:3?i5\u001dz\u001e[&\u00181T oeмg]l^u\u001fm;8h=\u0014Co?P\"ՖgWK$BQq#Pn\tf[\u001c~\u0016M\u0019xAb3\u001fԈnm#Ǯ\r\f\u0019F4\u0013i\u0006\n_(\u0019J'u\u0016q<,2\u000eZVP\u0011\\QJUd}=5@ !a\t;D\u0004H\bD\u0016Ȏ\u0012\u0016\u0002\u000bVX\u0004\u0011 Et>󞞹's1\u0017{.bXܛ|mz^y3-9D^鮒\u0004d \rL4T \u0006~\u001am8d{嘳@_h[;V'\u000e(PJ\u0015Iki)%F'\\\u0014WT\u0014onuwWI\u0002e\u0001\u001fU'\u0014z+fjol\u001d/c\u0006}I6\u0012K m+ΨU\\f\\VnFeoÅwE\u0011*I> \u0007\u0002fh:֥ݰ˧֚\u0013.\u0018n\u001f&(\u0005袔[1Z(>D$h\f\u0016$\u001bk\u0012+{*%\u0001K\u0003Gu\u0013\bS[\u0007o{d<5mq|셽q\u0017j??gpzB9(\u001eR\u001cF/\u000foeV\u0013[׃ZE-M]5rI@.i'\u000b\u00077crk]:_Szp؜q봋s\u0007d\u001c\u001b\u001d\u000b2hD\f\u0017Ӌ>n_ҧʫW\\[1(\u0004\\A\u001ax*P&\u000be\u0017\u0007~Qaўw\u00185rr,`\u000b)||dh2e\"\u00191!>L\u0017p\u0005W1CB\u0001zmM><\\(\t\u0006\u0001WyPzѿdf-\u0018-hxomP\u00161^\u0007R#g\u0012¦iIIVD6)/\u0003D~R:.r\u001e\bЬ,N\u0007/T\u0016\u0014V\r֭],[y\n)u߃\u0017\u001c'/RBHoHgyQ0\t\nL=ED]\nDI(\u001e>݂]+Q[W_M\u0016[f\u001b1-\u0017cC\\ÿDa)5:6`5\u001f\u0013\\,\u0015\u0013+E$Eq$\u001brV7z߂jZ'W\u000bۄpN%\u00174X`E\u00073\u0014@\u001bD߅P Y\u0012 &\u0010(\u000bNv\u0004\u000b/W\u0001m\rF\u000fI,ˣF\u00039\"\u0012/*J~\u0012\u000b?\u0001*\\8\u001c\r'C\u0014\u0001| X\u000f\u000bd}\u001f5\u00041\u0006RL܁i\u0006\u000bk\u0002|s'\u0010Z8B\u0003$1\"۳\tu\u001cod\u00158\u0002:;r8\u001c \u001f8\u001e\u0002\u0018DC+D8CN@;\b)/\u0002S\u001e~l\r\bZCDݑA5\"*{&#U\bd8p@>\u0019\u000e3\u0006Nl\u000b\u0001]80\r{`\u0019\u001c\u001dma\rCV\u0010s\u0012\u0012X@\u0011s`\u001c5\u0003Qd\u001d3c&?.n)TC\u0014*בֿ\u0014\u001b$\\\u0014)\u0010/]\u001dN`\u000e,w[\u000f\u0016V6\u0003/\u0015SW1F@g\b\f JU\u001fTC\u001e4\u0004$\"\u00031 Bg\u000b$*A\u000eHP\f'\r`jAj9H7\u0005Z\r$d;A,\u001f\rQ^jC\u0002>\u0011Ak6*\u00128\u0018$l\u0001(|g<5\u00179jCo_j@nE\u001cDioK \u000e0W,\u0007\r`{k\u0001\u0007X3_\u0003*\u0015yBJZJEZ\tn\r$/\u0005\u000eF.\u0004D>y\u001e;5\u001b?5\u0017\u0011HoCI\u0005H>\b,\u001d1S\u0001\u0006d{jC\u0016<, 5\u0011\u0019uj\u001eS h5<\u0003:y)!j\u0014@Ky\u00134@ݿ4$ig>3M\u001bM\b$\"\rq\u0018:y;*C\u0006aӇ,\u0015.1ҽ?'qL.\\|\u0017Q\u0015&$NzEseP\u000bO\u001aN\u000fM%O_\bP@<Ґ\u0000ֻ<\u0013eh@!Z\u0007\r\u001bj\u0003Y\u0014u&o5C\\\u0015D.\u0017S^GU$ͅ`̐n1\u0002\u001fp=\u000e\u0004p\u001dS\u001b4\\:\u0000\u00199\u001dx V\u0007\u000e\u0014a\rd\u001bYˤ\u0007~Hg/$'\u0014gK'd=\u000biN\u0010%\f\u0016\u000e\u0007\f\u0015\u0017t\u0006=n?e5\u0011&S7\u00024!\u0001i\u001f\fHC\u001eJ\u001d9@ї\u0004\u0005^\\Z\u0002;=z4C1O#\n\u001e\u000bFI%>aOЀ\u000e~9x,&i<4\bА͛lG6\u0003\u00078<d\u0014\u001b2K\u0010^QMk\u0000C\u0004Eu:NUb{Ӫ\bnED@.K\u0000!l\u0012H0\u0011BLɞ\f\u0001\u0003A\u0011a\u0012Vb9*xZ{s\u0003\u001a?Ua^W^S/OU&=/ԇD\u0016s(KPٗ.\u0017w\u001aF%vB1.io\r3)\u0000\tiC\u001a[s1\u0006ZО\u0004\u0006̞\u000f\u00107\u0018̯L\"iJ'3؝\\A{DJP[𵪦\u0016uCUcu)t\"\u0015V\u0003\u0005oY\u001cdϒ\u001c\\\u0006kpyW\u000fic\u0014vR\u00105.M\u000fss\n\u0018dV¾[\u00146\u000b\u001aʺL:֐a)V+f\u000eęL{jG\u001aJ6;\u0003o\u000bT\u001dX\nڣƹ\u0006o\u001a.yMG`\u0019bF\u0015)\u0003B+DoS9&j+3\u0010%*MF̹gE\u0016 [\u0019W>`\u0003H\u0003\u00117K\u0016\u0000\u001f\nA\u001aNmtaLs)\u001cJM\u0010\n\n\n.QY2%Y\")u\"bb\u001b]\n\u0016q@$8@50\u0006Eڿ\u0004p\u00130̿\u001abv9YC\u0014u7DrV,8dI6\u0019\u0019\u0010Rr<ĵ\u0007H\u0003\ti(ߴ\u0000\u0017\u0006׵G>trÛV\u001d/,أO[C0\u000fL]5SI\r\u0012=V\u000bE\f\u0019f\u0016Kt\fXBkUS\u001dj\u001aOL~Wi_\r\u0005\u001b\t鶅\t\u001f^9k>=퓝#ۃ\u0006͑QqMz\u001cZA(VIXb>Yʙ,uI\u0019r-\fRzV]@j\n齒B \u001e \rdW'`#g!\fƽßo=Uǹ\u0013C\u000f;|{Z#\"[o]MIjRE6')\u0010\u000boT\u0015WV(\u001cV\u0018X5\u001c֝\u001cU[++\u001f\u0003h(\u0004\\A\u0019j|l>m/^7K>fs,ؐ'NY\u0015\u0015JdXʮK\u00122_f\tdzh\u000bF<ߪ!z\u0019A=P4;A%r\u001f\u0017@Esw]kЙM?\f_p\u000f8#,-:Ym+jQY\u0019ņ<\u001eYK\u0011\f\u0005G*hez}I$jp^ixo\u000f\\G\u001aJ9\u0011t[ivO=W{y\u001f{7\u001aQUmqYd\n݄/4s\n\u0005b)R$\u0018Ī8V}pKsةU\u0000u\u0015\u001a\u0018_8t#Tov\u0007\u00164t_6=s\u0016\u001cꋈw]`X\u0012\u000bҊsdU4a|S$$E#LM\u0001aT\u0010\u001e!\rLdN)σM~kcK\u0006\u001f_o}vvo8~,x8<⻘4j̒\u000ebyƉ_Qy\"\u0012Z4`k0m\u001bz{i\u000f\u0014\u0006\u001a4hހ\u0015&ǁ\u0007qܵy\t\u0013\u00179O\"n|\u001f@\u001cF '\u000fgR> ݈6fYM\\\u0011d2\u0003m&Vp73pp,gn\u000fWA\u00018vx2\f5c\u001b/OO\u0012p>\u0019\u0016D962{\"1>m\"\u001dS^gEYQ\u0018ϸĐ҂\u001fz6\nv|yl\u000f@jGr\u000bj`bC\u0002o+\ro=]ޜ3a93W\u0002gC3\"㧉1ԸkxI!/)uJTm\u000bs\u001aE7\u001eC\u0001j?EX\u0016z\u0016f\u001b?l^s_);xً\u001eٳa'fKf`cf\u0001KʂCgy!\u001f$a~W\u0007\u0014}g{\u0017e\u000f(]P\u0005;#\u000bQ7l\u0006a\n8\n\u000e\u0002` xd( \fyBr&\u0018g\u001d\b\u0001p\u0011>\u0018;~`}\u001d\u001ajuBR*G!lu))6\u001b<קix\u001a\rA;/CԞPH\u0017\fi\u0007 =\u0010H\u0003\u0010\u0016\u00181=\u000bb\u000f\u001fPz\\\u0000Qoh<\u0007-^(\u0011eCUM-tZ':-\"%\u0004,\u0012X8.\u001cλ\u0006\u0000\bی-~\u000f^m灴\u001c\\q\u0016Jw\u0001֮ u\u0012dO~q|\u001b2PG(\u0014\u000b\u0016ac>lpN\u0016j2[\u0003K\u0005e\u00058v\u001cGE\u0001łH\u001d\u001d\u000b\"\u001c\u001eBH\b)$$\u0010{\u000f$!H*(( X.l\"(\b3{9W?p.Y{o\u0003fF0\u001f\u0004\u000b\u000f\u0007 dI\u0000\u001c_\u0007}\u0000\u001bRb/Wx\"\u0003x\u000fW\u0006]^\u0013\f<|s8ųq0}<\u001dNb8!\u0002\u001e\u0003\u0019cV\u0000x}\u000b\u0001s<O86o7\t(G\u000fs\u000e\u000b\u0001\r\u000b]p\u001b0\u0017n\u0005\"\u0017\u0010.\u0002\u0004\bK'@22'0.\u000e@t\u0006gC\u0002:\u0004umtvH\u0013z\u0002I\u0003\u0004π/9\bت#;\n\u001e!\u0010\u001a:\u001a\u0016\t\u0015.񑈾7შQluXk\u000f\u000e@q\u0006\u00008\u001d\u001e2.y\u0000\u0005\u0014?\u0010M\u0000\b*\u0000{&\u00040\ra\u001455sL\u001bCTWH䓘\u0017\u0007㞇\r\u0002RL\u0000\u001c\u0000S1\u001b8\u000b@p\tI\n,.`f@\u0000\u0019\u0002h\r1\\Mפċ_\u0012ſmCDwaޠz\u0003{\u0007q\u000f\"&ޏ\u0018F\u0002\u0003\u001eqH\u0000-Sc\u0016\b9\u0013CA\u0010\r8=\u00070냁\u001fobIu\u001f1M諸6.b?)'|?UjG\u001fo\u0000\t\u001e?NS}\u0016H\u001cA\t u\u0005A^0\u0003Kpt\u000eJˋB.B$T`ΤH\u001aN&6\u0010sރz:hG\rF&\\\u001a\u0002Ȉ\u0003\u0001qHCY6қ\" t\u0004u\u0013h62\r@@e\t̒G}ߥ\u0015G?մ7W-1ۨǼQ}W䋱D[a=<S@6\u0013{9\u0004n\u0000]\n|\u0015W(m\u0006j$\u00162_+ϒj=\u000b7ewbʯt[b\u001fs{3\u0013i\u0012\u0006l\u0001E\u0013 \u0015q`\u0004B3@{\u001e\u0018Cag0Iy&\u0004\u000eK\u0019<^RKe<\"ywqEΤ*y{bVeumus]E\u0003.Iv\r9Tҋt[@\u001a@\\m\u00075@; g5\u000f,zy C^p..蕒\u001a\\Jy%`ܡ+8\u001cэ|U|%\u0019ۤ;ԞޓU&?zY'qϙ@Ze\u0007lyeHN\u0007ι`^:V|`\u0010\u0013~yIϴn)0o$t9ͤh$\u0015j\t)Wr+qe)]bBȚړ]˲\u0005P\u0011\u00072AzS\u0000\u0006\n<@%e׽+\u000fr\u001f*볢C\u001e\u001aR\u001d*\u001aUq+RHs*riN9$XDe:5\u0016}km\u00014dO[i\u0007\u001fAK\u0013F\u0014\u001eJ\u0016yHu\b6\u0012(̌\u0006\u0011WˑJX\u001aU\u0019ä+N/2XL<3fڡϡݕhZ\u0013-9А\u0013\"\u000eZy\n=VCM]j|bCڬ؄\u0016#ب3kel^P$-*U֬\\9j40sf-EhU1\n\u0003g\u000bHG\u001c+@_7\tY@Y{\u0017Uz֧u>w[1\u0017,\u0004b]\u000eYH\u0002LelQuҬ`ZdY-\u0016IVQ¾\u0016guDY@\u001c\u0003\u0003<\t␋\n_x:\u000e[9pˣ!5Q-e'&\n㤞-Pq$FD\u0015k\n(\u0015ܚ|\u001e9ǻenkxn1P`\u000b#|\"Ȝ̍\u001c\u001fj]w{ME\u001eP\u0010[[L('1F:רgKjJPER+.4ŧ3M\b7XN-Kt_\u0012>\u0010\u0003kDP\"ga^c\u0007\u001b'qqK>˞^=SgsוGŜ*OJ)*JS9ZSXW\ntr]:ǐ,ȣ+*,4EC>UuӜХKe\"[\u0000\u0003q`/\bj,\nIgM\u0019k@7\u00026޺|tŦڳ1ѥ\u0018|~y\nM_La˭LQM\u0012-àͥXL$}9UBȹn&;t$=)Y-\u00050\u001d\u0003\u0017\u0019e\u0013pD`aǌ{9vZkgoaG\u001aQudC\r g\tK\u0002v1[F?!RS\nzdH4%Y0aN8u)H\td9s\u001c8\u001bg\u001c\u001c[lIJŴ\\u]I㚚G1\u000fhhjsP+]\u000eռ\\}xn~sDr^G{TA\u0001PI\u001b\r=uz:ڬ5>tk7ͤ﾿Mw/uk\rzDs7u#)y)6YAO9e;\u0016푷T֦P{@!AsS\u0003wZCRs\u0001?\u001eU\u000bO>R\u0005j&;ߨ}M[Z\u0003\nW\u001b}^\u000fw76M\u0016UK,Ց=8RAbyڰsԁ\u000b֫\t\u0003u\u001fTqZV\"D\r'(`A^Iyݿ20duQ琯UPi5w[\"I^OjfƵ<ɕ\u0012awY9*y;z\u001aZ]k^\u001ewiT\u0015\u001f4لݔxwg\t10dBVI۰ՙ!NG\u0007|=xa\u000f\b\u0004~iw\\p7?W^)m,m*m+w4XƋk/\u000bTA!\u0005GRpn\t.q.qst\u0019\t[q\u000f3c>VF\u0003\u001dn=\u001c\u0017R\u0013RL{\u0013\re\"Ibw:C/8\u0019hΎ\u001aC\u001d\u0013B\u0013h$3b\\\u0015\u001aPpJx֮CyK2c~\u0017q_vdrT]ptInp<!IȍN0Y\u0013{،\u0003\\1~dsRd }0b(|(ltT%4\u00114_+gY)FirM2!s:\u0014ω}\u0012\u000027,\te(\"G7EG.\u0014C]\r_\u00165-;F\bE\rKxWh\u0019_L9\u0015Zax/waE\u000e|-\u0011jh$$8r!B+\u0003Y\u001et\u0014nEvxE7\u0015'|_\u0018B\u001f{\u0001AxR9躬N\u0013\u000f5_\fJ\n\u0016\u0015ai&ܖImUlDZ1XK\u000euZO\u001d;rpl@}\u0018v;nS0\u001a\u0002q)\u0000-h.\u0017_t Z;Ո^\n8NaZ\u0005Vha\f\u001bEp6b)\u0003f1\bD̊pV qU\u0010RV\u0007@f\u001c+_\u0014}냊5^Y\rz\u00164[{།\u0007.N!n\u0010\u0004Q=A)Z64X\b\u001b=&\u001ccຄ\n/\u0010\u0004\u001a\u0007\"\u000f˼6pͶBh\u0001rwr,\"\u0005\u0016mگ7\u000e8\u0001T:M \u0014\u0004Q\u0004m\u001c_aΆ&\r:T\u0006q\u001fe\u0005\u0001_!l\u000b8t\u0013\u000e\u001aC`d\u0014\r\u0019G-\nmPjbjRJ\u0010T\u0007F\u0013\\G\u001d\u00002cdD##a5ҥH߈*'\u000fBxr\u000b\u0004-ې\re_ps+\u0000\t}`>\bF\"Sp\u001c},t6\u00156\u001d!l\"FM\u0003l I\u000f\u001e\u00063Ff9X!AN{H+R\u000e<!:\ry?$\u0007\u001d\u0004`{C\u001a\bT3#>ƍQgSwy*\u0010w\u0003lHڨTG=\fcpsdX\"[\u000e,G\\Z\t\u0011\u001f$7\u0005@t6\u0018KH\f\u0007\n/i\u0018m>MKH{\u001d\u0010\nD6XkBA\u001b2\u0007]d\u0018 \u0018\u0005([\"O@~b\u0019N\u0017{@\u001bi\u0003 9\u0019\bZ F?x9\tϙa\u0018c<M\f\u0015cy*\u0010K\"ِ^\u001br۬\"/c\u0004cW\u0015\u001bȬ>\u0004iǩF9\u0017\u0005ݬۜ{1HH@?!i&Ri#g.Qi@sTnB\u0019\u000e\u0012\u0017z!<\u000fy\u001d1v>\feJ\u000b?Vެ#Cbhw/e=(}z,~L:\u0012%|HŞcdA@6}GnRŨj=\u0001˱j*\u001dn_J2}\u0017rcf3\u000e2gҎ$MIٔqQ~7לG᜻\tvfOJsE]Y*HPkPN\u0007aZ\u0017nZ\u0002weCI~T~%c\"7*k\u0010HN\u0014T$Kc͢\u0007ܧEw/\u000bsGxvt'\u0012g@B6$7ϰ&5\u000eoT#G\u001e:\u0000i)E\fe\u0004d\bY$oH\u0002\t\tI؄\u0019\u001e\u0001ld)C@+R\u000f\u0001\u0011\u0015\u0011\u0010\u0005>}/Ç}\u001e\u000507H^\u00060\u0002iƟRO~O$,i,K0)QN|BȢ`\u0007\u0015z@`\u0007/A\\$%%!5v_k\u0001\u0004]7\u0001t\u0004\u000f\u000f\t7S.l\u0005\u0019\u0016t\u001f\u00059nF\u0018\ff\u0004=ް\u001e|\u0011܁Uǵ6[B\u0004!ڐgiz\u0019nT[$\u0014߮sڀxoʐ8\u0005dgW\u0002\u0013os0f3iAp\u0002Z\u0010\u0013\u001b@bڢ2M\u0011\u0005q?\u000bn\u0013\u0013.a\u0015~DX+\"UP\u0017\"\u0002\f\u0007\u0001\u000b\"d&R0\fw~T]\u0012sJ/)h\nk0\u001cx\fQ\u0018bF\u001d-&*E\tjQQDkbaĠ8?R\u0013\u00139Q\u0010_3k\u0001ỵ@\u0014`\u0004 ܦO_,Z_t86]aɿe?'#\u0006a\r<RN`V0epIt&\u0014+٤FI\u00167)DFP^2)$9enUH\u00064 \u0006q\b!\u001duL\u001f(n_َ+;WcT\u0011]vgGjx@c\u00125FȢL\u0015G\u0002Ŧ\t\u00141RI\n.IN迈\u0013<\tE\u0016\u0010d \b^mdF\u000f\u00141Pa]\u000f{f펎_\u001c.\u000fh\"\u0004&%\fJL8YVE\u00121F*dޑ\tY\u0012b\u0005S,A\fu-3АGr\u001akuAK[\u0017~0zd{dڅ\n\u001dU{}.ο2HP%Gs%\u001cF(\u001e\u000b\u00021/SUJp\u000b`\u0003\u0019)\u000e\fFV\u0003\"Ѐ̥\u0010ɑ+O湖vNY\u001fzrG}úMdGҩX\\ʇ\u0013\u0012@.KX\n\u0019C,\u0011\f\u0018c\tL3EGDs\u0006\u0016\u0010#9\u000ehh>dë\u000e\u001dcV[L:<W޺^^\u001cr \fM&3\u00181\\\u000e_.s)\"$WB\u0013I)\r2_F\t0U8M_\u000b \"\u0019X \t\u001c=SvXkΛn\u0019ky^ٖF\u000f+ukQEov1\u0001J̥\n\u000e\u0013)\n118)<^JH'H\u001d\u0013F'阵(|x'\u001aȑ,Р\u0018+=t'n\u001eL}eYK^mwZ%.DR\u0016\u0019/XJVltKI\u000f\u0014\u0014*q$X-\t\u0019\u0013b3'a\\tZ\u0000\t\u0002\r\f޹\u0007\u001d/\u001a}tzcZOUwZ\u0014a2\u001b0Һ AMx\u0018B.gDƱ\tb^HQz|P觪\u0011D~Śx3N`4}-b\u0006\tQ _(PfZiڍ3BMh4\u001c1w~\u0017\u001e/\u0007y-`?v\u0013\u0001\u0017@$P\\FpM\"O.c\u0002/uFx,\u0019Z\u0000\u001d\u0006m(\u001d\u00025ۡ_;@\rЃ='5ǩ\u001e[SRꠇ\u0015\u001b\u001dݍ\u000f\"v\u0012;tbP;L*cZS-\u0005,\u00165zk\u0007z4M=KFV\u0003)[ P\u0019n2FzCC5z_Z~nf:j\"\u001eu>H\u0018A\u001c\u0006\u0003p\u0001\u0011ѽ?گi\u00034\u0013T޹(΅pU\u0001&\u0014Pl\u0001}k\u0000jۯU5{jٮW%/{z9\u0019JԤ#)-p\u001dp\u000354X'M!0Mxw\u0018[^}[Z@\u00014҆\u001eB:ta}~~\u0013\u0001\u001do7Kha]9\u001eڹye|e<o=p㹺Iܮgx:\u0017z]8_\u0018if\u001f\u0005V{Ps\u000eT3\u000flE.\u001b.$\\~ڲe%3K}p7I\f\u000b8KeJJJ݇f{\u000f\u000e6\u001f;X\u0003B\bECMZPՀ6Tу>@?\u001d\u0013}b#o\u001d$`\u001b\u000f\u000f\u0002W\u000f\u0002\u0018{\u0013tC\n5@;\f\u001cA\u0003_\u0003\u0017m@%kPkj\u0005~\u0004CfeK0J\bjn@A((g4:\u0007I?|kXy\u001b\u0007\u0015I*x $%Rt\u001cfffjj3\u0015Q*jS$bZ\\uab'q(\\}\u0005\rTp0zS\u0001s\u0010(\u000b2A\fhBm\u0004Tc4\u0014탱!\u0010\u0004\u001f]~^\u001eqD:M\"!#\u001bM)\u001cXag\n'd&n,\u0016D#fa$ȋO0K\u0002!G\u001f>(B'j\rm6s+.\u0010\\I9M\u0012\u0001D*\u00149N\u0015`\u001e\u000b\f(7Fx\u001a!$\bfツ^\u0000k\u001bx]\u0005\u00052_K,GT-t@B{,Z_]\u001f$\u0013$)\\Na8XE\u0011=\tÌ\u0000\u0018zs\u0007\\\u00112\u0019Nl숄\u000e^\r\u001dRMVBd\u00022ePڠ\u001afV*`\u0010u\u001a}P\\\u0010\\\u001fcB瀿\u001c<\u0012JmQۂ\u001e\u0006G0ց~\u0005Ӯ^\u0000\r7Pz<\u0003^O$B°7yi}>Ǎhc'|>B':8<\u001d\u001cWC𼍑\u00162\u0007M\u00100,؀o\u0007N\u0003Xׂ䣮wv\u001dk\u0005ʯH\u0007\u0017H|;\u001bčW\u0017H^:\r\u00144\u001d.\u0010x\u001a#=h\u000e1\u0010, \u0012-Gr\u0015R:\"\u0019\r`\u001dq\u0007'yq\u0017~=\b\u0000@$=\u000f \u000f\u0005&j\tڐw\tc!o\u0012&\u0013\u0010\u000b0\t\u0007*r4\u0000\u0010bY\b0CFsȒ,!M[t=\u0004NU\"\u0003)\u00173\u0001`^\u000eD`0~\u000e\u0005폰I𱤡\b-Y\u0013I\u001c|8\u00169H\f\u001b #D\u0017:#e\u0001DN3a\u0016fȎ\\\bE%+!_\u0003q\u000bU7xw\u001f܎ pN}!\u001ckH)\n'c\u0018-uh&W؁/1(\"B\u0017`\u0011\u001bp\u00117Yk\u0006e9⬐˶E\u0011TxAT\u0017\u0010\u000eGLro\u001dc\u0018?KO~K\u001b\fRSS?{i_c#:u\u00016ᐼJ\u001fU\u0006O\bjoS\u0014p\u0015\n'r\"\u001dRqΐ1QcM#)'\u001f\u0017X\u0018\u001ekF/%mG{~B\u001f?d%KD.\u0006\u001evX5\u001du3Qi`slB\u0019\u000eE|q볢0H+z/}+K~?H\u001f\u001ecd`v1n\u000bO\r?dh=L-6kq=NƙL\u0005R\b\u0007\n=d,G\u0001Jfb\t*\u0003\u0017`[%ƶh>\u001aU^ذl`\u000e=>ԧٝG\u00190odg>$\u000fnޤ__I\u0019\\2s)\u0000p\u0013Fn\u0002[\u0003lu4v?\u001f5\u0011c5v\u001fwֿ)\u0017\r\u0016eG+\u000b\u0013˙%5oD\u000eH:2p~Lξɹ\u000eΧ\u0015}⏰O2t\u0001.\u0004KC\t7\u0011:y,\r\u000fT\u0003zdVG[ʾ=VF9P\u000fis.)/w\"`8P#\u0010~\u001e\u0011}b\u0002C:1J\"n!ȼ=sSbMsF])c~.SPn\u0017\u0014rn(\u0005W%\u00173\u001b\u0015ʓN\u000fc\u000eQ[=T\u000b,BBx\u0013yɮ\u0006ht9e5hp[Ԋ\u0016˓\u0006vja̭J9jsT}vi.|oC#\u0005$\u0017\n$Z-\u00032d\u001aAC.q \u0017{'i:\u0003\u001e&C\u0001\u000b\u0007D,{ږ^;2(\u0017+r9gJ\u0004'\n*GUYs\u001b\u0007[eu\u0014-FvAdOse}N6V\u000b\t\u0007i(&A\u0006;}_;c䰛p­\u001f\u001fs\u0017}Vt*Y\u0016I\u000f\u0016Ve˯W6嵨~[TsdJiujeje\u000ekq@\u0017H[2\u0015YD,%!iAG\u000f\u001dF>s:\u0019jh[\u0007i~W\u001b#J:Q#gW\t*J-eٍŻu\u0005Mj*UgirYB?uz@Q\u001e5B];s\u0012k:\u0000~\u0010#-4)A)ԡ\u0010Z\tI\t-\u0018\b\u0012\u0002\n\u0003\b\u0002*H\u0017DP\u0014\u0005]\u001d@?\u000e8*~Yѳ}s\u001fs\u001fv:\u001d\u000b{\u001f:,{\u0014~'Š\u0003\u001aBzj\u0003ZƲԨ3Y\t\u0005\u0013i%9ՙ\u0005\u001cp0W(\u0016D/D)췉y@4!M\u0015\u000f?a{g\u00156\u0006-K\u0006R.~\u001b4qj4\u0016h^\u001f\\:\u001aY]\u0019_^+(.*N/\u0014g\u001f\u0017d)\u0017Ԍ\f񟱒@:\u001emC\u0011\u0014y\u0017Sn~c\u0011+\u001dǯx\u0015`\u001aq_8ΩZAd\nёTaiEfF\u0019ajŜ¾#E%/KiG\u000b$\u0014I\u0002;8-88\r\u0007\u0017w>\\/\u000e\u0013~e*=3rpAO^?۶\u000e[cK8!)LjFU^Y\\Q/?//\u0013[>\u0013_LRZbٛ$8I \u0001r\u0015\u001cԫ⾶oý\u001b؁{q{\u0017nvh䘽a\u000f\u0001^k]gOhV0qјĴdL^M0TW\u001bõO5Ki1oxU+q@\u00126\\E\u001cT)I\u0019}QFˣ{*޴!ݖ17ݶa\rL\u0010jiO$3#>$M\u0010r,ȅ#q)MU\u00112Cu\u001e6d\u00057\u001f\u000fm\\N\t;\u001f~8I \u0019\u0002\u000ej\u0014\u0016\u0005<z<!\u001e>TD\u0013\u000ffl\\o,jo\u0004:\r\u0005{\u000fFeǲS{zbb#;\u000bW\u001eק\u001djH\u000fj\u001fNgv̦_\u000b-\u00128$t\u0007%d\u0004iF4;$ݑFSh䑎T^Ŗ86_p&\u001c\u000b\u0004ׄ!\u0005q쁊D$\u0002߁!\u0001c`V761=/{5J\u0012\u0010qP)^^ >\u0012;JBf6gdt\u0016mB᱃F՜ACƾ,ǴPOh\u001fޝ\u00146wB\u0018(\b\u0018\u001dwhñԉ9\u001emb%~cPI _\u0006}8-ۤН\u001b\u0018\u0011\r<F=\u0014Q+\u001d߬O8)4miuy\u001c\u0011(\u0016<\u001b4'\f+d1*9s\\\\gh'ع\u0012_l{$2\u0002ZhBhFI+D>/οQ\u000fKrk{5.T@%uR=w1щ\u001aXE_R\u0016\u001b^K\u001d>\u001eKC\f\u0007\f/>/iE%FoZgaA\u001aլ\fHk\u0016U-ɫV\"WCW9FH\u0004Ք}B[Z~Z\u0001\u000e\u001e\u001f/9})gOrveNf\u0017B82GuRbE\u000e| |#5lYwT\r[`w\u0006\u0007i}\u000bӣ}\u0013\u0018x={ɏPc\u0002Me\bC\u000e0cy\u0010^a[I2ކP_\u001fB-7\u0010:=P\u0002\u001e&\\\u0016h\u0010Ά80d\u000e\u001c\u0004W\u0015\u0006Ph\u001b\u001a\u001e'\rbp\u0001N't<Pm\u000fu༮-t0y'I7V:V\u0012yD8t\f\u0014p|PG.\"\u0017IL0a<\u0005\u001c7y+Д_\u0001*\u0010\u000ebTm\u000fҷZAV\u000b(f\u000eMQ\u00044L_\u0018nHt\u001f\u000b\u0007\b\t#\u0002D\u0014\u0007d\\\u0018(YN\u0005m\"\u0005\fIn`!\f2\u0007Q\u000e䬁\"o\u0005d\u000b`n2M&\u0010`\u0004 Pԇͻ!\u000e+iC\u00164+kBDu\u0019d- _F(\n\u0010\f\u000f\u0005\u0005Tn\bR\u000f7X5\u00147\u001aF\u0003p\u0003.0d!PF\u00138;!\\v\u0007j@n\u001bdʩXN\u0015NȫIC\u0000\u0014o@+\u0012!W2hJ\u0010Q\u0005f:\u0004d\u0000{R\u0007\u0018vO>/\u001b\u0000}\u0010hc{6m\u0004@]Ĭ\u0000\tP\u0002e\u0014t\u001d7|\u0000|ϔ\bA$\u0000י\fT%\u0010O\u0003X黀\r\u0001\u0015>]4\u0004.#`\\5\u0006ƨ\tLϬ\u0019_\u00039,\u0005P-R\u000b\u0005,?S\u0004@5\u0000\u0013\"I\u0010b-\u0003ad\bV\u0010\u001ap\u0003'E\u0013\u000eBP>0O]QM^[\u0018\u000eT\u0014zYuQ\u0016\u0015  Ɛ9!\t\tI@\u0006\f@ \u0010\u0000\u0019A@\u0006\u0015\u0004\u0003(rUZPE\n*\u0014\u0003Ȱw;9]笇ظ\u0006\bm@X\u0007\u000b\u001b o#D\u0000/a\u0014$vl\u001f\u0003a,|Fk\u0000~\u001d`W\u0003e\u00030\u001d;\u0007xۜ{!p\t.B\f\u001c\u0018i+n\th\u0015krx\u001d[6\u0002\u000f\u0010\u0001?\u0010nn\u0002̀\u0013\u0000Q\u0002'q-[FÖ8\b\u0018ā\u0000\bh\u0006=н\u001c\u0011\u001b0\tD\u000bA\u0018\u0002q1\u0003O#pR=\u0016\u0018%\u001b~\u0017h@m\f3@\t\u0002ҵ@\u0017<Ex}!3\u0012)j*t\u0010\u000fo\t5\u0001\u0002\u0007\b\u0010`\r .\u0003*{`^\u0005A\u001a8\u000fda\u000bAu\u0001I\u001bD+ .i5p\r]\u0007\u0019izK$T\u0017J׎\tcg\u0011\u001f\bȷĩ\u0003$\b{A'\u0014\u0002[\u0001$4\u0003e=p<Ar\u0016Ƚ\u0002Ŧy\fY\b=.\n\u00154/qN6KLM()|\u00161L҃\u001d\"_ǽ'=zC|KxEN\n\u0011i\u0010~\u000e\u0001 \u0019h/ykJ=\u001c@+H\u000b\u0005p\u0001\r}F@-\u0012\u0011afG^ANE;V\u001dG\u000343%<9jS]Ck\u001fwS\u0018΀ȟ\t\u0000-0\u001cBw{P\u0000\u001cA5\u0007\u0007}˴\u001e>ez$|\u0010e[IZ؀ ws\u0001*Cf\u0003V=zG\u001d%v?\u0016&\u0005W0\u0017\u0017e\f'\u0006waO\u0017\u001b\"w\u00066x \u0011\u000b\u001d\tÆ9\u001d<cX^O\u0006;-U,iBr3p\u0004Fm^\u0019V!uv3\u0017։ثˌ>~/ϸn\u0018l$;C8\u0005\u000b\u0001T7[ځ|\u001dفa\u0003䮛\rN\u0013!\u000e\u0017F#{4\u001ei!\u0012U!_ٔ>oA%W\u001e;9-<þ$`O\u0007Dfhl\u001b<%n|T\u0000QG\u0004\u0006\fwN\u0005::>r~\u0016u.;Zm`.W&<\u0006AȍԄȾD\rWA3JJb;D|Io\u0017KIyO\u0006%^<A\u0015O\u0013k3\u0004k\u0000\u001d\\!:_:o\u0006\u000fPzD\u001f\u0016\u000e[\u001cꮉw#j4V?VfN$\u0014q[e\u0015qGč\u0016ISV+\"\u0011>H>\u000eJ3*dS\n4\u001ap\u00051:?\u0019,y7s\u0002_pyP]yW~1G\u001cyFԦЎ'\u001bXG\u0006E6&Z,L( %;Hi{I\t2+F,,\u0013jB&)\u0000&:Wn*J.e\u0007W\u000f{;i4IsȒVIT\u001c\u0013|(0g-$Z.UíN2\t+TU%\u0006\tiC\nnE>rSiT\u0019՟՟y\tz\u000b\u001a\u0010߾C7\u001fu27ۉZ\u000f5\u000e/[|ٲ[\u001eWj\u001bʙN[QM*jmU-M-\u00104\u0012cR<7U>42_%di>\n35L\u0004\u001aA,ty\u000b]lrx\u0016Ogwۂ\u0016_;\u0012CO=aCAֶ2fS<֨ThX%\u0019B}0/D=$ק\u001eUR:U)?R\u0010Hӎ1thk\u0000\u0017\u0012uN\u0003\u0012\u001bf\t\u000fGkf,ںkyWS:s-=hUR*S\u0002 Y\u0016#0d\u001ee\u001c\u0015IU+*\"0$N\u0018%ǘq5@:g6t1f_\u000fKm^t?p#`\u0013:Ἇ7R4ԲwVW\te2raS(\u0012hr+F$!ˬe\u000fHP<3Sd[X15@ \u0006cb\u0001fq\u0011݉Ř]K0W4t\rQrFVXY\u001d_aS֗pRK\fq\u0007b\\&-O\u0010\u0017+\u0005=JA]4\u0014\u001f_8̗\u0018-,qi\r\u0010O\u0006\n1P\u0019=\rf<^g̍K\u001ev\u0017;φڻp;iSe\u000b#ݓ &\u0010ZJMr`:/2O\u0018_^*\u0011y\u0011Ni7.*\u0006a^\\\u0015W<ƴ\u0006H=;a\u0013f~.al̽s0W0}Wu8/l_t.ҳWl\u0007:j\u0000~IH\b (\"\u0004\f;\b\u0005\u0016BBB\u0012@\u0002aG(Vԩ#.uSw\n\u0015,0Et\u0000VE\u0005q=c=\fbʎϼO;~|}&GPnj'Stbo~~́\u0019ՍҴ껥\u0019?\f\u0017eUe\u001f\u001f>6\u000bS9G\u000f\u001bg?2ɃV\u0016Env\u001bK\u000e7\u001brk.\u000b\u000e^H\n/usYq[[\u000b\u00127sbMFuaӶ9Y\rk\nU\rE\u001d┆\u0002u\u001f9&NMit\u0004\ftIn3 .3^\u00169w^S\u000fǰVՑ\u001b|פЭ\u001737\\X%XQ\"L{~:ܮԶʬymdmC9\u0013\u0019TeZ\u0017l7$c\u0007hI-if+\fqA3$M\u0017ScC\u0017V\u0011{n\fЭ\t_}#/zq|εI\u0015JŕJ*-A#HOr{kJxBrA7좑ܭt~NZn2I##rߒ\u001cwYQ۞\b7<{<L\u000bYȴ{x)}\u0015\"I_DW%\u00135&u}zR\"Xp\u0007\"]~$\u000fҤGHs\u0017aF%z_\u0015\t_r\u0017|2U^~AɃB\u0006%\u0003h`U,\u001b숋}\u001b\u0017;&.v`\u0017o?O\u0010]GHO#'o\u0007LR9<|5bOrܬ\rW\r7/򬳵b;6ItSh\u000b<eڵމ-\u0004N?#?\u0006Gk\u000b\u001a\u001e\u00129:\"ݻ\u0010v.\u0016: B\u0013!\bB^=)TLmMz0'r'LӧSHRmEӹbGt\u0013ozK^șܹ35\u001e\u0011M᳝찹\u001e\u000bv\u001f\t.5\u0010BAEB\u000e\"Ǆl Po\r\u0004B\u001c+M\u0012\u0011g&<\u000eJ\u0018hK=@±aI\u0018۬\u001e\u00008h\u001b\u0013v8cN-{?po:Lv\ts~B\u0019Be2\u001c\f\u001a#0\u0016Ƒϋ$\f\n\u0010.\bBY\u0000>7ú\u001c{c\u0005\u001bD\u0007\u001afknNS\u0019\u001c2K\u0017\u0012R2LH.\u0018$\r&zrX艨Y?\n^\b3C \b\\?bY>\u0010\u001a.Ԉd#\u000fhݐky˰q\u0003ooLlqd)jMlp\u0006-:\u001d2{-O\b)zIH8!J\u0010\"\u0011\u0002HX>--\u0018t?x9g#0\u000bee:@i\u00035\f\u0016!e\u001296̰p\u0001\u0013\\C8\u0013hՇ\"\t`B\u0016ʂ,\u0018R)\u0012!*B\u0016k\b ;[s@\\#/\u0003\u0013x7)\u001b\u0002{4\u0005<ǃ.fq\u0010q!cB\u0005E1\"ST\u0014,B%\u0010W\"=U\u0010^\u0006\u0019jo3v\u001a+w)n࿡\u001d)\n>Hm\u000fW] f{!և \u0016T\\c\bMPCj1de6C\u001c!>\u0004Q\u000bDHhu\u001d«\u001e\u0010)5\u001bQʤ\u0017\u0004L\u000b\u0010\u0000@JM\f\u00060&\u0014j\u0005Tً\u0016\u000eH\tCָCR\u00166 \rQr\u001eq\u0007\tZلq鄏\u0013\t \u0002gL\u0004Q\u0011غ|AAC\u001fil\u00062}\r\u001dfl)2\u0016HϠY\u001d_8!e+\u0007<8!\u000fvCKľāIp\u00071\\h\"\u0002G$\u001fwH\n.HpAFڕLw\u00068\u0006(XahS-^\u0002\u0007dltf',rw6&`FQ\u00174%o\u000eL:\u001f:!\u001cAz;׈Qɛo%Cҹ7I\b{-GK\u0005\u0002+\u000bD4ȝP*yL\u0004\u0019a5\u0004%B\u000b\u0014)mP1oL6Ɍ=~i\u0007ޫԆ&7rG\u0014Qo1IyCWW/dc\u0001lL\u0012g)\bBC\u0015Bt!ő,\u0016:飔c}!\"LPƷ:̚\fbϱMr\u001a6s_`kcN8MEqkKX\u0017ܪ\u0016 {H\u001e\u0001\u0012 @ \u0001b\t\u0001B-@\u0010\"D@D\n\u0018A^VPֶ^u9ߞ3)1\tŌyD>$\r< \b\u0004\u0012{>p\u000e}n0\t1\u0011[ n3\u001a2+$lw}\u000bb:\u0012XۯQ)G\u001e\u001frU`0kq&LxO1\u000bQ\u0016\f\u001cf#\u0011\u000e@O[ a#\u001aO}k\u001dTm=0}ډ\u0015\u0004}Bs\"oףX}i$\u001a\u00196hW\u0013ѰV0+\ns~1e<c^{\u0010w\u0007\u0003;޶@2\u0006|)ҷ\u0012ld9\u001c\\:زsW? mUwNxLyZe)~W#31\u0002ϫpݜvf'eaOγf_f<U\u0004-\"\u0018,@*2̏Azoh\t\r;\u0016|g%ϋNo5\u0016z%E\u0018O\u001f\u0004Hs\t]\u0011:E\\\u0019j\u00161[\u0005&~77\u001an6\b~\u000fkG@|m$D\u0000[`(2W\n\u0005㐾^t\rhXݫ=)p~\\i)m讱\fH^eWB\n]Il.\fcd5Nĩ\u0011[x\u0006 _/WJ~\teT!r\u0019\f\u00052=H@F:+C\u0016\n7gU\u0007\u0016Tu|L)fx\u0011J.ǽ']yA\u001doV)D\r\u0018K1\rѕJi=,?\u0013',\nuҧXKStrG\u0004\u0002ÐHS\"2(Zl#76u{\u001d\u001c]v2\u0012ξ\u0002ַ\u0017re~j\u0005>9XET\u00142K\u001a^Q9A~E6fL\u001bH\u0017@S@V\u0001@\u0017((C^\nd\u000f!o5\u0015n3aNKǪ]/\u0013wt\u00079Q~u\u0019q\u0006XN-Q1J8yj^NB03S\u001e?*?\u0010g$z\u001f$\u0004\u0016\u0018 \u0006{\u0000\u0000s\u001a羚P?llew]O\u0015~{G\u0019I=V\u001fkȉŔe&\u0011ti\u0005r:NfQ\u0019J8Y9$Q)JRR^y:\u0015m<$\u0007H\u0016\u0001X\u001c|\\\u0001^ԯ\u0004s\u000fv\u0013-K.\u001bO}ݪ7rV>\u0005\u0018VANfgf1ӋjM\u0005Ou^>/NP\u000fJԷ$?I\u0018I\u0014e\u001a\u0002\u0005H\u000e\u0012\\\u0000@\\k\u000b\u0005X\n:G\u000e.5yionm>KWg\u001d(\u0013\u0015K\u0005ɔ4m\u0006#%']ƍϬ\u0015fe\u0019\u0012iƴ$:7<-3.#%.\u000b\u0012lb$\u000bzo\u0012b0[\u0010=\b\\\u0002&:7\u0007;/j;E\tW_\u0013v_\u0011\u0019U*\u000fє(ɧB-K^P\u0015Djω^H;)ʋ*|˔\u0016|J \u0016\u0018d!\u0019\"\u00115.\u00007\u000bEg0ri={vUM-ݥ\f:gv_cĄr5-4\u0019uF\u0011\u0018xb$\u0014[ܒ\\A?LQG\u0018\u0012l2d\u0007\u0016\u001c=\u0003iv\u0002\u000e'po\u0001\u0018\u0012ٻǩѕ\u00177w\u0016\u001e6qiD>\u0006YP|]\u0002>&\u001cQ\u0015*4\u0014q\u001cw\t\u001e\u0019mWB-PA\u0003;\u0002?\u0003k#\u0018t\u0000\u0003{h5h0phUw\u0011-uHy^\u0015\u0016/;\u0017\u0017,1\f\n0idҌ,M6ɍOhoht#$1a-0\t\u0002p\u0012F;0r\u001e]\u0003m3`\u001cfo\u0018uw)\u001e^\u001dlw+{/J#E]\u000bJ\f˒\u0016B'Q:*(v#-3\u0014>xJ÷!\u0011a\b\fm\u0000̝\u0006`,\u0000߷A\u0005\r,hr\u0001O-\u0005\u0017i\u001d<m<`*a|7r$]8$>\u0012~%\u0004s0ɇv9-t9\u001f\u001f(a\u0007x@\u0017!p`\u001c\u00149\u0006 l\u001f\f,\u0000n\u00010a\u0004ߌ\u0002\u0016@\u0011v\u0006;(ݎ[G%]\u0013;\u00181MοÞ\u0012\u001dOʾ\\O<JY1\n\u0000k5o\u001fk\u0002z2[\u001aA\u0013\u0000\u0017,\u00004\u0003P}\u000eq\u0002y\u000f\u00179WzA1\u001c=R0x-'\u0007a[i\u000f\u0004;HvE5}a\u0000\u0001\"e\u0011\u0010\"}_\"\t $!\u001bH$h\u0010\u0011bQtܦZ\u001d\u001d\u0005[-8:Wqj\u0015vTTqÀn|3s3wrs{S|\u0014YYճ-%gOQv@zag(Uzm\u0017rt\u0007G\u000ewNB6_a5dՍ,3kќ*k*reUx\u0014Xsǅ\u001cl*(Z\u00176ɭk#e-Q]1CN-/|/C-5\u0013ұ4\f!.\u0011_\f\u001d\u001br'C̹Cҡ\u0019\u000eL\u0017ݰzz\u001c)񒏔{g,\"\u0019FWL\u0015nK\u001b2\u0012<\u00114\u00158~?0qE`k\u0010 ?I/\u0010\u001a!\b\u0019q$\u0015pg1Y0\u0001\u001c\u001d\u001dT\u0010;ʡpA,L\u0017!f|R2\u0016'c\u0006Vzɱ5\r8\u001d.hR6\u0011Do<!+\u0012&!\u000f\b)\u0004R\u00047b\u0000E S(v\u00068b\t OAC\"\u0013ap|vFS\u0004\u0016\u0017!\u001c\u00045\u0010\u00018O]\bY+4{\u0014Fh\u001d(\u0014\"(V\u0002ӑ#\u0013\u0005\u0019'\u001cJ\u00100>\u0000%(wƁ\u0013fdlfG\u000fmrޟ~\u0003n^BL\tѾ\"4\u0010\t\u001cI\u001a\\\u0019dL\u0007\u0011C\u0011pf\bbc!Ń5\u0005R\u0017\u0014lOh0P¡E\u001ej9Nh8b#MN dB\u0014B\u0006gCb\u0007\u0001rDd\u00169CV\u0006I;hdF\u001eo\b۸\u0010O\u0014\u0014\b@p꣞Sc>\u0010k ᳐ENC\u0001P\u0014@^ᆌE\u001e\fgސlB\u0014@|\u0007\u0013<:S!\u001eRԨ/Do/G\f[1|l\fh\u0016f\u001a\u001b\u0004;\u001dU:A=\u0005*$(j='os背f\u001e2N/d\u001d~~C]'^\u0000OaM\u001b)\u0002^R\u0006q\u0019|m$\ty$\u000b\b\u0016rȋA\u0000C\u0013rr]3CS\u00052.TkyP\u0017\u001d~\u001d@ȏ\u0004A~6\u0010dJ\u001c\n\u001d|\u001d:a9\bz\u0000[ \rgB\u0019Ƅ>\u0005c8\u001bi\u001c\u001480\t:W\u0018=7\u001b9>Эvc\u00004ۂn\u000eAP\u000eAu,l\u001bȗQ!ѿ)^E\u000f*\u0011T'*\rd#d@G\u00194L\u0018X(\faaV4\u0007D{%\u00131K튢|O\u0014\"\u0017Ə\u0003\u000by%~Gnwv?DsdڐT\u000b߳`F\u000f5}E=\u001dz\u0005\u0010\u0000&L\u0006`dcn=\n'\\y0.\u001f+\\\u00122lZ\u001db憘gMOsN\u0018=ɪHӞK{*+y&\u001bO\\\u001b\u00060\u0011TAt\u0007L\u0014i/\u0005vNuĂ\f7uc\u0015ż\u0017s\u0005\u000e\u0007J>?.\\\u001b0s}Իym\u00159,?-wnog\\?]\u001d\u0013}oD|$u0R\u0001.\u0016`ḁS.͇\u0012\u000f=/4[\u001f/[$ɿ\u0014\u0017(*n)1w\u0003ƎKNw=Rv\u001c<[\u00007E\u0010)F\u0012$\u0001z\".\u0003\u00165,uL,X\u001ao?T48˽oҐ17*fhiHRRF酒EMs-3\u0005ԧL4'L]c;ڣ\u0005ϳۋd\u001e)\u0019!J~\u0017r}\u0018EoY{|\u001c\u001a_\u001ey\"űo2ksk\u0012._YB|Ʋ.͊c/5K\u000e\u0016\u001f9P|>wϹ%\u0003VKe\u001cdZ n)J{\u00174/#/\u0006\u001ax\f\nb\u000e}\u0012_`߻FܽR\u0014|~vLU\tk\u0004\u0017,W\u001fTy|zߜ_);q\u0007c2i@Vs%dM\u0010}Q\tỐOs\u001aڷYVp\u00193\u0006?\rc>\u0018 tF}i1\\Ci\u0012\u0017\u001c`mr\u0005kU{*7iw<狹_(o3~n9h2m:oHX\u0005ն\u0005f>L0\u0000?I\u00028XU\u0014\u0015\u0010A)ғ`B(@\u0002( =\u0018j\u0010j\u0010A\u0013@\u0014\u0010\u0014P\u0003((2눸zQ\t3{f\b{vV|\u001d>_NnMF\u001e*1&8xxo\u0002t~\u000b|NΌъXQ\u0015uTY٭\u0012\u00039.}|gWF>UVJoO&51\u0012/\u0005'&Tſ\nNZ\r 4D#/C\u0015\n\u001e\u0011\u0010\u001f+2\u0004T\u0019VkrRtLgve뢰\u0003\u0003%1Gz\u000b\u0012;ry\u001e\u0017r)R~1)ܿ>YƪLa&KEļus\u0004->T\bC\"{٘p#W\u0019\u001a7\u000bưnA:hO6z\u0019Iw\rVzE':J\u000b<Z\u0004Y\u0002$K_ɗ0\u0019!Nvq`Xa\u001dn~\u0013na?C3/F4\\U(|\u0007ɺrp\u000fz*у_Zo2}NfFxDkhS!\tU\u0011u]\u0014\"Lv/⓫\u000b\u0004rA*fIvSHAy%<?\\fg=0_\u0018\u0005#B'-͙\u0001:xwj6\u001dXԅG];\tÚc\u0007Z;z\u001a-/I\"l[+c\u001dŉnyd0VZTWTX\u00147\u0005\u0017p^Mnz<';_\"Q1*\u0014\rP\u000bE&|I\u001bс˦nkaa_\tSyk^icMCc\t4o8D[*\u000e,cةEaIĢ9nb2'E\u001ffz)bJ?RDUp\u0007|M$TW\u0012\u0012<mՀ\u001d0ק\u0005&0wPjAb\u001a\u001ch\u0007qÙ%)^5>9U*\u0007%Ie\u0004Q\u000f'Nt=h\u0016\u0013/L@\nTP\u0002![\r\u0000ד`]\u001d\u001etk\u0015\r5\u0015]Rwҗ]&ok7B\u000fۣKq-I\u001eM\u0019<zJ\u0019WbGW\u000fsEVe1ck\u0011#\u0016I\u0010U\u0015J҂/\u0002\u0015\u0000O0'S^55H\u0011#P\f[:Jzmc.a/\u001e\u0016c\u001c.u嵧{'_\u0016ƶT\u0006D77\u0005E4wrCMC?\u0004D ߨ\u0016DnF\u0014U(\u0004(ƿ\u0004`\u0002\u0001oO\u0012R\u0010ax\u0000qC\u001a \u001ei\u0018q7\u0018\u0010\u000e\u0004\u0015\\\t;w>79'LWBȎr0yL\u001e\u0018,\u001b\f\nM\u00051e?0Y\u000f~rD\u0011#CdU\u000fV\u0004\u0006\u0019\u0019\u0001&z\t0_\u0018@]=hxVr⸁pD0\u001a`ƿޟ:\u0012esZd\u0001\u001bj\u0017J\u0019h\u0005*dA\u0006C1b)VO\u0004(P\u000bT{k\u0015\u0014n\u0017\b~x{o\u0013eF\u001bgC\u00015='ݼios~)wC,D쏹\u001dk\u00135t$9ǐ\u000227zO17ml36E\u0019|blՋ6<ȕ~\u0003\u001dWN\bP\u000f0-\u0003\u000b\u00187\u0001HP5\t\u0005#(^C}lgIqLO΅s\u001fd?8{ \u0001&`V`ǘ\u00159f\u001d32g̠촋\u001b\u0017\u000f#\u001e:JR%\u0005n+Wq\rgC5(~\u0005/r\u0017!Z\u000b\u0017\u0014\u0001Ɯ%\tYgf~\u0017,\"/\u001f|&x6dtmG\u001bU\u001bnߣCnO6\bp\u0003`\u001fs\u0018Y9\u0003P@\u0002\u000b-HU\u001aY.B )RyLR7\u0006*71\u0011[hP),SOeNwen6sew,~^p\\O;C\u0016d\u0012e.|-{\u0000\u0005\u00012\u0013!aY\u001bb3\bV]5+\u0014\u001dꊟJJMWӌV}(\u001b>\u000eo;6kb6ە/\u0018\b\u0007a+~\u000f*p<@\u0012\u0000k:\u0019> }Kې\u001e\u001a_|4k\u001fC:\u000e(r\u001d:k\u000e!\u0001T\n5\u001bC\u0006^\u0010p\u000fZ>}\u0017w \r\u0014<\u0002H[\u0004_\u0000H\u001b\u0018\u0010h\u001b\u000b\u0011\\~\u0013:L:\u001cIvM\u0006Q\u000f\"\u0015\nְD{P9Jڍrw2\u001dI\u0014u|u\r&9+m\u00068)@\fg)\u0001k\u0000\u0014\u000eH\u001f\u0011\u001cE\tvȜ`\u0011\rdYTg\u001a\u0006;Av\u00115&@ $$$\u00106\u0001!)\u001867,\bE*n8RA\u001d[EQ}k=ťӊ֭Uq\u00193_ۙx;}sr\u001epig\u00040\u001d bɴA$\nZ\u0016H2E1ʴ\rJ\u0000\u001bY\u0006ec'6PT9I~\u0003(\u001f\u0014Fp\u0015\u0011\f[83ؘǰ'\f\u000bh\u0013iC\u0004\u0006zu%icj\u001a&v&\u0003ON߃Ѓ`\u001fO\u000bB\u0011\u000bJ\u001d\u0017π_.x\u0015zǂ6\u0003p\u0018\u00180~b8A\\4u\u001exg\u0004\u00143\u001fO>C|\u001ax\u0012\\-,\u0004@0\u0013Yï\u0000\r\b\u0013{M;H\u001c3\u0001)W;=%\u0010\u001fwÔ/x0ȃ&|<\u001a\u0012BD\u0016d,H:τ(}\u0016\f Xi\u0016c\u0004t `)\u001f$\u000e\u001c-\u000b?&^[?i\u001b\u001f\u001f\t>T\u0013h\\H>\u0011D\u0016,Ku \tY\u001eB\f!2\u0014m\b@\u000e\u0012½V\u0010\u001e\"i\rEk\bn\u0004\u000fٓW\u000fB_\u000ba5\u001e\u0004W\u0004\\\u001aR'H#ݘZXc!F\b](\u0017#,\b2S֛C\u0012M\bʆd͔dpG\u0001#v\u001fg&W߉ڏux!px.S\tlH`8\u0004G!ք`g\u001ar{\u001aQv4bg\u0002مD\u000e\u0016)t0\u00001\u0019&*4\f_c3\u0011f\u001fE;v7{^u~%;4\u000bsI\\\u001fI>{7\u0014s~\u0002\u000ec\nRV\u0013$\u000e4\u0019ePͦ24/-!E:\u0013\r>&ϵ|\u001b[a3\u001eSo\"j9O=w\u001260\u001f\u001eG=/xߑI\u0007;vM\t+\u00113\u001a\t\"\t\fD[1`@*\u0019&\u001e\u001eD3>+ߤL_$~YT|?V.z}nFs#b{=bwUywTyߥ7\u000bQ>\u0017\u0003\u000bv&\u0016c\ta$7d;3,\u0019!7#ў\u0013L\u001f\t{\u0019g c\tNr\u001fPչ_Kh\u001aȹ\u001c&v߅s1\u0003D\u001f\r<\u0015}Ip\"Xˀ|ăs8\u0001Ép'4!\u001dιtl2K\r\u0003%d\u0007sobɬ\u0005&?$3K/w)|*Ι\u000e=\u0001G\u0017\u0012\u001e\u001f\f:\u0014Pui㟈&L\u0004Uw(\tdx\rC\u0013Ib̀B\tR2\n{ƛ*WI5GneЌeJѢDNgN˽\u001e^w05@rp_Rhh\u001eɠj_Ȁ꘴?lw\u0003w}\bKo\u0012p[\u0013b\rRH~6[EF\u0014VQlƯuN\u0005V+.Y*Ns:v(@V\u0015o?,r=K%};;R\u0007C\f˷W$VCؓ\u0001/\u0011\u001cM7&wУ(#\u0018Qo\u001b̩G06NX'3<Y\u0013c}\"\u0012۾|sk}ٍ\u001dE6d~ޯZz s)e\u001f\u0019/B;\u001fE\u001dY\b́_g.`H\"{\u0005d\u0007d:}e!uŌΑm3uQb0R\u001feUqhE/ry\u000b\u00025\u0004u6rڥ\u001dY=̾V>Z\u0016Ȗgaks&%C>\u001f\u0005_G\u0003T䷫I+&gRVRZfQ6Qmv>-\"\u0011{\u00179צU[^RZ*^\u0019Q$ސA.o9wGxS#VD5\\j}\\?!m,DPS\u0011\u0002\u0014O\u0013;!oQzR\u001a[3~:7\u001dS\u001b\u000f\u0006o\u000e\u0018hUڻR]\\Qo+\u0011/]%n.Y'k*ڤXUMYW0\u0010Y?\u001cU)aDm{g\u0010ՕAP_\u000e&(TLf\u000b֦CnAlM\u001dU``|wBmMIs\u001b2<;?n-_[])XSY/^],+oWԖ~*鏬(9\u0018]Vr\u0017UQ.r\u0005Օ\u0010T\ti\u001diQohjl5M]_M:4:-p|澮\u0000PѶ[ZT.kzlXпBаliTW\u001a\u0007}\u0013\"\taQ(\u0016\u0004\u0012\u0004B @ؑm( \u0015\u0011\"\u0002\"PYd\u0015\u0017\u0016Y\u0004(.P\u0004jg:\reLm\u000b8ȢTEgǙ3=a>~s>9\n\u000ef?pfތ\u0019=!)\u0019B3&w\u001f7-\u000b\u0010:í\u001cT\u001a~!3߷\u00141\u001a\u0016\fײ~\u0005\\btqjZVW\u0019dx,ҬdX]~at,^}w\u001f:\u0015}.();x{\u001fBr%\u001fFe\u0011T\u001eA:']H\u0003x\u000bu\u0011E:L\u00188˄M|j2\u001a$Z%&EŹ;i\u001dtK+L)(I:Z㟘\u001c\u0018\u0015\u001c7\u00185Qp|o~\t\u0005^BD&\u000f}\u001e8jh]π\u001b4\\nAG\tbyэWYoP|&lmM95qU;\u001cU.pu<c{iG~[\u001a\u0003b.\u0006n.\u001a\b.z\u0018\u0018S7dA\u0019Wm(WI\u0000?e\u0002\u0010ϕ@:@F\n\u0000:@ycC̪ns-9竟\u0014js6@}pom)Ҥ\t5\u0014q'>VnT\u0017Uy?? Ȫ\u0019\u000f=us5:\u0014\u001cr\u0006%\u0000j\u0000\u001a\u0000\u00038Of.-lHa^t\u0016tz/\bZ}=b]Zfx\u001d;\u001b:ƞ͒G7\u0014(=:}B|BF:\u0019V7\u0016^:{Nx\u0014\n۵\u0000W\u0001:?yO^\u0016T]ׇ^+F5);ǃѽAO\u0007ﺴ4BU\\\u000eۘ{>ȔF|rT\u0016^\u0012^\u0016v=#}#mJ\u00116'\u000fjEVH\u0011]r\u0006\u001b\u0001.;hHO2pl`)\u001c\u001d0?cWh-K\u0019jэcǚD&Zn*\u0001Q<\u0012ZG+\u001d2[2Q)'9O7^F;uߑ.> g_\u000fE̟d+\u0005?Āp\u001a{߆L3Np\u0010p~\u0018;\tơwRL2,\u0002X\u000e\n\u0006km\u001db>E\u0003\r!T*\u0006\u0018<M:\u0004\u0001P\rPq\u0013`\u0010 \u0001\u0013RGذst9$QF1_iF}\r\u001f\t\u000b\u001dٴ,hd~j*_վ5^\\#\u000fUZ7\u0019\u0013WU\\g&\u001fL匩_ߘ:Yl\u001a,y\u0003\u0000\r\u0003\u001f|\u0000bBC6Č`Ә\u0011D\tq\u00193dܓa<7\u001e\u001eߢ\u001cs\u001fw\u001d^.\u001f/zO6qrDtↁ\u0006I\u0003Y\u0003\u001fp\"w\np\u0002@U/ɿ.?y\u0004 !\u00036>ք!\u0011\u0004>8^LI\u001f\rd\u0012lT,q*+N׶>~LW4Ӡg3s'|:D\u0004x\u0005\tꩻ\u0002Da5`\u0000ɿ\u000f\u0003 |\f 9\u0007_!(_SW\"y֑vuc8aڽ\u000e\u0010԰ye=c\\\\\u001etm2YYpO\u0018'\u0018-Ba\r-\u0001|\u0001P&(P\u000fq%H\u0018ђ\u0012\u0012BW\u001c=iS\f`0\u0011F3\f1\nӘ+{X\u0002\u001bY2k\u0019\u000e\u0011\u000fY|uS\u0001}.?\u0011@\u0004O\u0000߁2\u000e\u0016`\u0006`Aa1\n5ZJTP+Л^4\u000f#h=up\u0017,\u001608XKt0Ļ\u001475LU$;\u0002x\f \u0004\u0010#0%\u000eu\bj\u0007}4d/K\fP@領F)AWJ\u0013)\r\f(\u0000\u0013t\"\u0006 EƖF;\u0001R!\"J\u0018h`8\u001b A\u0013hy\u0016ǵ\u0014Hs\u0012q'\u0011*.Zo\u0012ω7\u0004r\u000f,\u000f\u0011ɖXD8(g\u0012?\u0016E,A660G\u000b\\\u0014 QJ\\ \u0010\u000eY \u001e\u0011?\u0013ψ\u0004r\u0017ȝ/\u0001j\u0014:YB(>\\E\ft1QB0MƲ!Y\u000b2P\u001b\u0015\u0010ͺ(EQ\u0017K\f\u0001\r\u001eg\u0016ĳoĨ;K\u0012x\u0006\u001d,(RfBҜ\u00100SD\u000f%\u000b݂5%;_\u001b\u001dt߸\u001eJkx(i Z\u0002G>b\u00189<J/$/%&Oߒ\"o\u001d?B\u0014z\u0019Qo34\roh\"\"\u0014 Ut\u0012\t%\u0010\u0010\u0010\u0010\u0002\u0011B \u0010\b5@\b\u0012B\u000b\u0011TY\u0001X8\u000eV\u001d\u001b;zгc\u0019X<?\u001f~yqYA:5\b[\u0001tM\bި\rD\u001d`f/\u0007\u0007^\t4>\r\u0017z\r\u0019}z3u\u0013<\nqz:O|I\u0005~`\u000fV=\u0013\u001a\u0018.\u0006h\u0004`\u0013 t\r\u0001\"7N\rq\u001fQTM\fֆAH\u001e\u0004\u0012$2Ī3\u000fl5c ~\b[>`-c\u001b5Sfe~\t#Ɯ}Ƃٽ\u00000\u0004L \tƋ\u0001\u0005\u0001BF\u0012\t\u0010cJjH}1@LĲQz\u001f#r߇\u0017z\u0013VM#\u0006ٳn'A\u0003F\u001f\u000e}\u0010xiۻ\u0013nzЂL0X^\u0000W6!`\u0018`U8ߐ\u00004|\u0013\u001b3-5\u001c.!q\u001c1\u0005GQ\u0015kG,7[޸VNa\u001b{\u0012rq&ՐΗB;_\fy4\u001dF=\u0013\u000e֧#T\u0004X`̿\u00076M{W\"H7Bd\u0010\u0016]沼5_g\u0006.}ʎ{fk\"f|*k1vWZ\u001d~޴b.#\"\u000e\tt?\u0015>1\u0015>Kg\u000bO.\u0013Qx,\u001aŀ\u0018^\f\u0019\u0011`38\bxػ,\b|\u0007+>Iq峜D\u0019\u0016K\u0005\u0017m%8opks=}2f4\u00113J>\u001a}pIʡ^\u0007~\u00173G\u001b\u000b4\u0000\u000e\u0018@\u0001x{;W`2@_VBkcڝ\"_\u001b!y٦9<B4\u0014&C\t{ㇽ{\u001dH\u001dG\u001d5@\u001aL\u0006ׁ\u0014p\u001aH\u0005@\u0014~${[0||G\n\u0000=/7A*l\t7)\u001aY\u0004QS\u0014ɜ,#\u0005\u00079eN2$ncz?ZN5ӟ<Jݙt֓tƿ;iֿ3\u00153gW:xt+\u0003\u001c\u0017\u00031T{ܥ\b\u0004:hT\u0017\u0015顇U\u0012]\"k\bXSiDQLy9B\"Zr\u001fқͻKݑ֞~Jb(f\u0002Zӟӕ\u001c e;ƹ-{B抵#\u0016#YnKuь\f]OI:\u0013\u0007LƅV#\u0002`iW^[\u000fܙSOٞk2Pd\u001eg3/39\u0003YR\u001b\u0001\u000f\u0005\u000f\\\u0015=;@\u000bq\u0019\u0001ݩDV\u001d\u0004wQ-:D\\\u001czwye\u0016\"Sح@Ln(-M~>z\u001dw,;\u0011XýȒp\u001f\u0006>I\u000fdY>-\u0006-\u0010\\!BE\bݔjoBW\u0014hN(Ԏ}ɂWD\u0011+,z*2m;xB\u0016a\u0005\"\u00174hR~/C);ªțfc?\u0005]Y\b뫊]\bH[@Y1BVaߩSG\u0015B\u0016:j&Z\u001c\u000e4y/#g\u0018$H\u0013;$l61ױTW*H}$B%M\\(/,\u0011\u0012\n\u0006\u0015\tn\u0007\u0015\u0017\u0014OY\txb - \b;jp\u0006:DU\u0006ʎ0\\2\u0010ckY,ͦ&k\\wU\u0016Ebʊ:\u0016NFQ\u0010 _r*(VP~[|\u0002(B\u00110\u001e\u0003l5g>BU t]*щvutc%߱0Nkc,l\t3R5n^Ԑb]P+uH<D5\u0015ZoaU\u0017\u000f0y,h*(Kt#+~U}ͫ\u0002\n_\u0002@&B/\u0016ncV\u0016}\u00044I@\u0007Оn+@fwm!mѦ-IVҦ\f*ES\\^R_ڋ/SPyҾ\u0000N\u0013,v/\f+\u0006oV-Pe@ʀ=\u0013\u001a\u0006\nN\u0010ًo.\u001a3G\\5RuZ;6'XTmڲ\u001d\u0005%ܦ*\nއӠ;dqf\u001a3Y7\u0001(l\u0005\u0016Ѓrf\u0010nE\u0004v8\u001fw\u0004u\f9\u000ezk\u0003WHw\u001b{bJS:;s\u000bݳ\fUWj7IKKPcʫX\u000bZ/\u0004%x&\u0001\t=\u000bp\u000f6&zaG5P\u0011j\u001dW:\u000fjL\u00038r\u0000!\u001c\t\u0001!H\u0000Í\t\u0010nA\u0014\u0011x_N=겻Nm\u0015ƻT\u0010<PT\nV.`j-\u0018>d\u001f|&3e#30x=KvH\u0017U=k\u001ci;\u0016\u0005\u0016m_\u001e<e*դ-OزEm\u001be8\u001ai0,)<ۀ\u001c\u0003\u0006C\t\u0003@-?+m\u001fZI`u'6@pqu\u001c|'QU޾Y\u0005\u001f'W.\u000bȭX޳.$ܠN+\fO)?\u001a/o\rKm\nM-2T\u0012n\u0000\u0018\u00004}\u0001px;\u0000;\u0000?\u0000h\u0006WX\u0010ZtLÛT+U.)>0pt\u0019n\u0013\u000f.>'n_Zm\u0018}W\n>H[\u00164@oƤ`\u001aGLspf=1Ze\u0000_\u0005LRs`\u001f6`a(nQ5\u000bS≧\u001d3JӾU_\u0013\u001bzk;qolcoLc\u001b9a91\r5Rk)C:\u0007\u0007{\u0012P\u0003\u0019W\u0004X\\(nvW(h\u000fdǲs۵\fDQ:8[3.O08ĵ}\u0014ݶY\u001aٶG1ֻ5\u001a]ƶD\\\"ΡKԼ\u000e\n\u0000*/=\r0\u0015\"\u0017&\\\u0015Bֿl!\u0013:!#ԑufq\u0012:':\t;\u0017\b#;?:kXݵ&$F$W\u00121h\u001b|\u001d~z\u001e=}?o\u0019\u001b\u0001\u0013 \u001a\u001b?\u000b \u0016n3\u0006b{XFӛ̊\u001dVsBs>)Kk\u0005\u0001\r\u0016~\u001b\u0007ׅBy\u001b\u000b\u001e\u0014y\u000fV\u0001\u0010?Kv@\u000ex\u0013 \u0005D?\f\u0012BG0\u0017qLd0%\u001fc\fMc{\rxgu\u001c7v+{u+}u+5=Jp\u0007\u001d_A_F9\u0017\u0000\\\u0005\u0002\u0018w\u001b`l7@0\u001f\bJt\u0000t\u0007\u0005\u001fT\u0017a4F1ned8\u0004\u0001\u000bY8ebIeI\r\u001a52@\u001ecs\u001d'?25\u0001P\u0007@\u001c`\f\u0017EԔP\u0011\\\u0015\u000b\u001c\u001f1\bl1\fl0\u00061LF\u0019>ba\f\u000b\r\f\u0018c<iǚ\u0000oܧݢ\u0007\u0010\u000f \u001f\u0000\u0002\u0013\u0019r\u0011-i\u0003\u0012\u00071:\u0015E @?\u0012X4\u0016\u0000&\u001cRD\u0018F\rd\u0007Ojށc\u0014\f*\u0003\u0018\f6SP\u0019B\u00186p+\u001e3辘+gK.\u0015\u001c&'xB:=&\u0005~\f\u0002X\u0018\u0012BE$\u001b\u00039Ei\\^CϿs-Gm\\\u001eU\u001c#M<}ܥ\r!7[G@`83\u0018`z,\u001bCu\u001c\fʦ1\u0016p\u0002>/j\u0001\u0013\u0005wJRC,Hn\u0007\u0016\u0002!?\u0014\f\u0017\u0003۞\fFz0\u0018EY\u0018f&\u0019\\TOal>\u0006/\u0011r\u0005*\tQ\u0010\u0015D('U\u001cDE\n尢O\\\\D\u0012E\u000f\u0000M0Qn\fƹ2\u00188_B\u0011\u001fX=\u0017&P3]\u0011\u000b\u0018^\"°O,ߨ[VeJڤ\u001eRU\u0007UG/Tgs⧪+⇪n}Sq[{j\u001b\u001fVwF@/eP`\u0012}\\zi=\u0012u\\Ԏc|p<˘VtS~\u0016U*~\u0012QV@do}v5uv\u0006^\u0019\u001eͥQw5y2FkH\u0016Wɕ(\u0010a\u000ez{tG\u0006h.\u001eR0#3{g$inuD;nݽov%n=N7coK;bOIǶˮޖ]}$\u00107,5ƣSk<:OQ\u0012\u00110-mH8&\u0000\u0019dհd'\u001edXd\u0014YIgs3e]~õ5NW\u00127HL4\\rA׭][ަm\u0018}^9U3~fݐ{S\"6&d2:HF'6Q7t̓\u0000\u0016М\u0014ЏyTbq~\u0010t[]͙i{iBέ\\ΥM8t\u00162&}w\t}q\u0005_GR\u001cJEϺ4tKGtfmL,+zwNq\u0014Nx\u0007L\u000fdn\u0015G*/\u0016ZN~I\u001c[r\u0017MuG5}qI\u0000\u0011\u0005K\u0015\u0015\u0014@H &\u001a8L\u0016\u0001\t\u00175!\t!!!!\u0004B\u0002\u0001-\u0004D\u0002~\u0013\u0010A\u0014\u0010u\b\u001em\u0001γMzv<gGۭ[y%ɺcF$e\u000bNb1|M\\\nu6~3p:7?M$!q6\u001aOFƒ5(n?`\u000fL\u0007<\u001fh\u001f\u0013;$g/\u0012坳'9}r羜)XLxs*}H3-\u001b)䩠Qa# {d_O4{\u0005`{95(\u0001g}/\u000eg\u000fo\n\u001c[#|Yx\u0000ˏB\u0006q]\u001ac@\u001cﴜq=<+QyOfk}2G2\u001a)m\u001eZ1zW\u001c3~pGڳ`K\u0016ΏA\f\u0014`D$K\u0016x[.9D@|\"|'!K-|\r/{⣰\u0011]\u0014kCT\u0019q<@=Wx\u0015\u001en-zNsP{V'-ky5s:9c9Ԝq)0S[)\u0007QC$5;\u0004x}5?l`K\u000b~qCBXRGͫ;P]dC\u0005\u0002>qwHEӒ\u0004ԫ|\u001390\u001b;Fzx5O\u0011ռ\u0006QQ\u0002BgC$kP\u001e\u0000\u0011\u0003|sKMgZ;\u001e\u001e>\u0015\u001d\r.=w$e@q<;eb6tU!ŕFQ=.Q#\u000e\u0012U\b\u0016\"tGr\u000bVMN|D\u0010#2\u001afo\u0011+)\u000b;i\tDo\u0003kvp\u0002\u0006\u0012a2v\\wz`Ys:P{qG2ˬ6\u0016\u0016d:jH3\u001443!ZHXi\\:!$;D0ut\u0014\u0005\f[8\u0000?\b\u0001^\u001a\u001a|\u001eW\u0011A\r,\u001c9\u000fai;d8У;^rji&F7\u0014Q*Vnbh\nCJdCJ,K!\u001f).R.>H_RT\nDQ\u0015!5(\u0003{\u0011AW\u000bie$J\u001d\u0001\u0006/\u0018\u0019wwT_ZIq<xuاB/Wk(%\u0006R\u0016\"W\u000eKY{O#o\u000bT?1e(\u0004Q0dkP6\u0005\t\u0004;\u001f`͈\u0013\"v&'\u00183{@\u0013x1Z}&ej*\u0003BtB/SPTZ}.+m\rhD\bzW?䫿\u0010)*E2D\u0015\u0000k\u0010\u000f\u0002~\u000f[\u0000Op\u0006\u0000Kf]-\u0000{`\btRm-\u0011泎u.UilRлZJ*R\u0005\u0014\u001a\u0003%Ɠ\u0016@\u0013MFd>ae\u000e\u0011-\u0002Q\u0015(w\u0002=|\u0019\u0002k\u0002Xhރk}\u0017tw\u001c\u0002K\u0007\u001efWvzoUk%ƜyTe\u001f7J|\rEueTam5-hftd֌W\tR\u0004UXz͏\u001a\u0014eD\u0014L5\u0007\u001c;h\u0004ϴ\u0003`\u0007!@[+{}\t=L۪_9w^ܧHr+p\u000eڸVwU9)ECi6P3&\u001a4\u001al\u001d6m&\u0012lbB&\u0014fBdk*=[\\\u0001\u0016?ޅ\u000f;`\u0010@\u0001\u001d\u0002Iv0ʾd Qџ\\ЛvPԓ}-<zg]/&q:+ȩ\u001d\rTv{;-}\u001e߾ԾΈf[\u0005%X\u0010%\r1~ּi%\u0000wp\u0007Ͽэ;\u0007\u0018\u0006h\u00000L9n(h(\u0004Tmi\u0007xp,م7q0k8}D:b\u000f|\u0012\u0007.\rZ\u0002.\u000e\fQ\u000f\u0007\u000e<Ƽ\r8߇/!\u0012ך?\f\u0000V\u0001\u000e\u000e6O\u0002Tb\u00057(\\\u0005\u00027\u001fmǻu!kS\u0015ԛ\\7lYőK3Zϋ3^N\u001e==}\u00143F:5tjO$:@^<w\u0019!\u0002;;\u000ej\b ]\u0001\u0010\u0003'pW\u0003\t\u0011D\u0019KM/nExܲ\u001aS˭G\u0007<<\"<Y˯<Xwz \u000f\":ʺK\u001eoR\u0007\u0000?\u0000\u0005P~\u0017@=T\u0011\u0001Cʆ\u001b$o@&\u0019Eیh\u0017ɱ?sِ(v0hq\u000ew\tݸ\u001ay\u001a+s\r1\u0018~j\u001b\u0017`\u0018\u001b\u0001K\u0000\u0007x5'\u0004Hxf\u0007~\bg\u000e-\u0012l1v4!z\u0002!j;ɰ\t\u0011چ(;:{i7m!CG{w\u00075uoq\u0000?$\u0004\b\u0010 \u0000!\tj\u00038\u0001*,\u0002ɢ\bVi\u000b\u001dtZ\u00147V\\֊Z<\u0017l\":UcQ\u0016Td\u0011+y\u00078g&{{lְ{\u0003ohG\u0001J_CKQ~=@\u0015\u0000S\u001a9o\f>bnV\u0015>h0-\u001c<\u0018m[\u001a8u{\\<Y9?Y9W<<'<\u0001}+[G6\u0012_F_\u0000\u0003D\u0006\b\u000b0w\tFB\fڗrp\u0006WZp~\rN]\u001fcW\u0018ؿ\u0005ew*\u00140/\u0019Y&֪[ֲ\f+J{_\u0016݃E\u0017u)\u001c_\u0006;\u0000\u001f\u0000x5\u0003x<\u0006pf\f\u001c\u0007\u001aRݐ\u001alA6\u0001X/H1\u0018$8\rĘ\u00048\u0007D)#\"\u000473Ƹ\u0011\u0019\bH\u0007#7c/__\u0001\"~\u0003\u00040\u0002w\u0001!\r\u001a5%J)\u0006ơ\nP\u0003\u0005cԃ\u0000P\u0017uB!\u0003\u00104tР!5\u0019\u0004g?w$=!_\u000bv\u0000\u0000/\u0000\u0000,\u00061tƔi\u0006B\u0014\u0003jaPN\"\u001a%^d2$Ʉ6\u0003\u00071Ft\u0001rl\ft2Π;q1gPϢm8$\u000e9sh&\u001bI9$դCI-9K.\u0006L:XxC\t#Z\u0017\u0006uD;R\u0004\u0006\u0006\u0016\u001dBYT&p͡<C\u0017<$d+\u000f+>r\u001c#?\u001cZ_#\u000f3M/\u0019\u0006e\u000eȐ\u001bo\u0007ewbp8S-\u0017\u000f\u001f\u0016]YrNa\u0001\u000fUy,\"_M|Tn'UԐZ\\&MaSހׯ\u001aT%=\u001e\u001cOz{\u0006U\fz9gIO1!E41C׹<ts!\u001f5H\u00005[I\u0005K\u000e\t4\u0004ӂ\u0001M/-\u001bcA\u001d3\n:ȟ@=eOR\u0000\u001alA?ꉯ'\u0006?\u0016}rOT\">z.\u0011\f銌\u0018hԯ-\u0017iw\u000b{=\u001ak\taC,CRDNئC\u0016\u001f\u001d\nG<z\u000f\u0002Y([\u0002\u0006\u0000\tE7i=bAC\u001a\\AOkB+/\u0019wLw<1}?dDUEԬ]@ivY\u0017BQ\u0003鍦7ރ\u001f`Ab0)`\u0004$B\u0003\u0018>\u0019\u000egs\u0003\u0013\u0001Yg\u001f.\u0012/1n_n\u0006ߘ7\u001awϰ_d8\"i46[4\u0018X\\3<oq\u0017%\u0017P|\u000fǝCsɔ;e\u001cT3(#jn\u000fCLo7\u0019\u0011>\r嵄\u000b\u001e37%_\u0018\u0015A_K\u0005n^\r,\u001cPis\u0001c\u000b\u0001?\u0007\\\u0005\u0004tN\u0005 \rB`\u0010h\u0018DSEo\u0002\u0018Ou̐\u0000&ʡ'Q\r\u0013<8H1&FTȅ?G|&\u0018^(=7ت.Dv6ltvS!{lO\u001cVԆ!\u0017a\u0007P~`*Z\u0013pӄqtL:R͠\u0004LCs\u0006R|\u001bI_\u0012\u0017\u0012Euqӱ\u001fKO,^&?\u0016u-Ñ\u0015\u0011\u001d#w6N/►*♺2jw\u0014*vEME4ʈh\u0018n\n\u0018ҵПƃL##\u0014Z3p'S\u00052'2\u0019h\u0014,ď,Q ;\u0018mu\\ݾU{w+iga\u001fˣlns\u0012ۧ.eqhW\u0016D>\u001aF\u0000` \u0015}\u0016l\u000e\u0018A\u001c\u0013m\u0003\u0017stl6+Bx4sPzd\\yʔŊBb\u0012\u00195e\t\u0015Λ]7\u001fw+w_\u0017cmBKI\"KPUvv4\f\u0000t6L睦y\f4,B8\u001a,pc7p5aF\u0007rD{̔=jG\u0002|Ŗ6\\!uSiz)kN>*ve]]q+aMLtX*b7\u001a2)\u0003:F[\\B:qP\u000f?Y@PU/bT5?F37Y-gUYv|cVtbYk25X2}ۗi\u001eӾ-K;4NҌA^6\u000bru\tК\u0003HW?w|\u000698/#\u0005j8g>\t\u0014̛f\u0019M\u000b-KeKr?R|Z9E5.fo/u\u001a\u0001\u0000$F!\u0010\u0002@\bn \u0005ulJA@5@X\u0012\u0001\u0001Y\u0014E#.`ǕxZjUlF2Z\u0015;sng.\u00198g>>&u)1$~*2~DV\u0014]Y$ILLl'bopk\u00069\u0002@[D;W\u0011\"!+H^૫Q\u0004\u001aMmG\u00123ӭ>ȵNSWV:u.NLVH:.K$Mr\"91{b7\u0011\u0004\u001eP\u001f\u0004.\u00128E\u001cC`\u0000{Jm]i\u0017nT\u0006\u0018\u0014\b\u001b\u0015śXVʳmʲ\u000bY咢LSAFK^z<mGV1Yf\u0005όdY\u0019]3T\u001cYL<,Dx]\u000e\\(\u001aPi\u0000V\u0018\u0012\u0015ܦR?\niՅg\u0017$Y(2my\nqAn$/I.ovɒkҳ{=Rd)=uMaND\u0013JTC\u001éj@ك\u001a`g>:kQ;kiZ2E]\\PU\u0016nZV\u0012=CU`QJV\u0014\u0014$Y\u0005NM.)g')v'(\u0006ds8]ٚ&3\u0002&I*`Fga\u000f4\u0007g˨\u0006}=@W\u000e:Eh[+W\u0006\u0019V(DVerی\"ԒJiRqì5M\u001e\u0018\u0011h'\u001e\u001f*o{DZŜb'z\u0000|K}jpvAH{W\u0013ALl\u000f:O^UniCa\u0010n4:vfGɖiY6I5\u00055تzv++\u000eETu\u000f\u001eQO\u0015L9DU0DR/i\u0016?\u001a\u001cWS\r(\u0005l\rBԶ۠r\u001bW~>oJn\n㬖\bu1D\f\u0006mRUjNaug}Pw5n|\u001a\u00035s\fU3\u0007b7\u001d%z\u0016\u0007Ct}v=7\u0001[*\u0011J5\u0016Pjfq\u001ao\u001dEz\u0019\fS:B\u0005L6ψiO3ڐk\u00156V\u001c*Y%]ֺ)s`7΁-\u001cZòf&^l'~L\t!߽\u0011PvK'^\u0001e.\u0014=ӑ#Af'O\u000eЏ\u0011l\u0018=R\u0010-4+Y\u0014֕m\u0016Ydbkuf\u0000M_Osak%[F~mf6\u001dz\u001a\u001cP(\u0006hU\u0007((\u001fH\u0017\"y5\u0012E/_\u0017\u0017f\u0010\u0017m\u001c7A|oi\u0002=3z\u0017j,}{=e{g7>=\u001ef>yz\u0016\f\u001c\u001eLwo\u0005Ty#@\u0014D\rrH!O.tȇ\u0017<Tg`nJ8\u0003T\u0003y\u0006ʦ\f4.8e}GO\u0007\u000e\u0011y\u001db\"\u001e\u001cu\u001ekh\u001d+:\fd\f\u0001lXa\u000buFv\u000e\u0012m H\u001b~P;_7W[<K[g\u0007&CO\u001e#ٯ<\u001a~#p;\u0004n'pc4}S\u001a\u001e\u001e\u001a\u001a\b?K;9\u000e\u00170\t]<\u0007^W|1J ޹\u0012y^YyFy#:.#\u001b#NW?K~^yw4'K.N毛7R~A}\u0012XC(\u0002{\u0019\u0018THoX@zS\nǛC\u0002p+\u0014WC|;\u0003wTY,\u001e,33nNA\r_z\f|J>e|\u00015r\u0003\u000b\u0007B<\u0001x\fGh\u0001f\u000f\u0010L{\u001c\u0003'0yZLA8\rc\u0010<\n0~2\u0006$\u001ao򏁜a?O\u001d@\u000b([\u0017@z\u001b\u00110F\u0010=7\u000b3\u00140z\r׋z9cQ-\r7ö́\u001e1j5򄌑+)?W\u000b$ï\u0002K\u0003(ۍ\u001d(\u001e0\u0011`\n\u00102=\b1\f\t\b|f\t\u0001L<B\u0012_\u0010\u0019!3z\u00193:\u0007B$ՔD(+;`.e\r\u000f3eэ)߀\u0001z]\u0003\" &DD,=q!^d1\t!\u000f5.BCNMĴ[:8e1\u000bOM[1\u0000\t\"8f1\u001c\u001e3(%uc\u0006[\u000eK\u0001M9AΒw>\u0006mo\u001908qLJ8\tƍc\u001cGg\t0H\rYG6.Y\u000fc\f\\#'\u001b+q/?dyTSW\u001e\u0007K¾\u0000!/@\u0002\tZ\u0005\u0002*,ʾ\u0018H\u0010HX\u0002H\u0011Ը\u001b\u0014\u0015ТH݊8\u0014\u001d\u0016m\u001d\u001dک^ENw~\u001c\u001fNr\bOq\u001fw\u0011¢)^/\u0002\u000b\u0002 (\u0002sHlCb\u000e\u0000\u0003h&M+\u0000_\u001e\u001f\u001c\u0001<8\txK\u000fK\bO\u0015\u0000>\u001eNctf\u000e'\fHbG\u0005\u000fZ\u000f\u001a\u0000dAC\u00166=|Gwѽ8}|K ߑgcr?F>c!\u001fS\u000f\u0004\u000fMA\u0019\\=i\u000fOc\u0004Og\u0011#SbH5|'.5Ԙh\u0005Zz%B\u0014SE]3Q\u000fDt\u001a\u0015\u001d\u001eNS\u000fEWG-\u001bM1f\u0019O\u001a\u0011\tu?Ax\u0016\u001b\u001c}aM>nۓ\u0011O_)S\u000b'\u001ezRC*}I\u000bd+d\u0007[}̛~?$'7$XW<\u001e.z60\u0015\u001bs;pv*f}\fτp-\u0010#\u0005k\n,IK`btV\u001c`Y.u˻w52U&߽6\u0019]n|ѳ\u0007\u001e\u0007MF<\u0007My~ozI\u0017fC޿Ʀ76#\u000buAm\u0013a\u001dG\b\u000f\u0005-\bƼ\u0014\\%9Zy%FjM0=favo}OOՀ)c>׬\u0019>~?l\u001f\\\u001bȂ\fa\u001d\u0016h<N;\u0011:\u000b-4\u0018\t\u0004˘'\u0017\u0016\u0014\u000eכ\r\u0004[\u001c\r0X\u00074[\u001f>a߿~}'l_o\u001d0\u001d\b'(\u0010[w\u0005b+`5\u0003\u001c0@hl\u0011FcYq\u0019\u0013eF9\u000b3Й\u0000ۨ(\u0014֑p<\u0003\u000bu}ֽK{BVq\nn\u000en\u001d\n+\bogY^G-=\u0015w[\bk\u000b\u001c\u0006[?\u00170\u0011^\bc\u0010\u0007_\bt-ě\u0004\u001e:\u0006\u0013\u0010a\u0003qFbe=-V؝՜\u0011v\u001d\u0011k\u001cNo\ro\t;(\u001c61'ǖg\u0011;͑ض9\n|/\b=7S\u0011Ѕt\u0006>\bLC\u0003O!l/5ѓ\u0012c;)մ31bGں=\u0016[n\u001a[\u001ccm\\L_&X\u0017\u0014'\\\u0013=*\u000b\r1X\u0000쁭!\fB\u0006wa\u00180$Ѱ\u0006\u0016ѡ\f1&T,ҨCh-Mfٚޔ$7'V94%6ҫ\u0013\bVovZ\u0011C,nKCQQ}܈.K]¸c]\"0\u0017\u0003I\u0013i<d\u0000\u0002^y`\u001c\"!\u0015rFY3]yT\"՚\u0011gQf^`MWsVK\ri\u000eSƔ\u0016amrKuo䳮w]SƄTקa\u001e\u0002I8\n\fF\u001as\u0018r-PZv\u0011s-9!Ek)\u0016\u0015rkCF\u000eg\\ktqC-sL_',IwK\u0007]uҿ\u0015Io\u0015qɰ@\u0018\u0001p'؋i\u000fq\u0016Ꞁٳ\u0000Rcviy]+!hf-yA&uJUtYJN2ϮJQPd68f4\t孢ByVM#\u001fvϓtE\u001d5\n*0\u000f8Lz\u001dпd\u0007\u0006cE0`\u0000]EƨZ?A-E3ɦ@A\u001bnܘ\u001fo^fUδѫTKTܒr8α kPIR(ܳ7ܳ^r*\u001bs1/7\u0007;Lz>q\u001e'\u0000\u0019\fAR\r:J\u0016m(sEM^ğPи(Ƭ Ų\\+gjm܂RZW#P\rBU\u0006QV\u000eW-Su=#*x!Tc'\u001a\u000bjL\u0003ޤQ8\u000f'\u0000\u0019\f\u0010\\CT\"\t\tRFM\u0015.P1ha,\t1(6-+Id,[MQPS\u0015V\t\n;ej׻ȵe=nRq4ew8]\u0002,X\\iP%\u0015\u000128Z\u000e\u001a2\f\u0006\u0003X\u0015Nv\u001aQSK髂X&\u0015\tZ:\\Q-Qg\u00159(J+Fui\u0014WIcn(YS\u000e\u000b\u0000üIwy\u0001\u0010p\u0015B{a\u001f4ܷ\f\u00067XF\u001aU7(oE4\u00042\u000bÍbrkS,klEV^UM*U.\u0015$W4\t\u0013*\\ݢX\u0011q\u00070\u0012\u001f4k\r\u00033\u0000!A4(AD\u0013\u0004\u0019qpU֩Z\u0005\nX+ \n8\"8KlUk+.D:\u001bZu}_Z?y}r?h\u001d<Ozwpf&p{\u0007|\u0005ΠeI\u0006S\u001aaNJ >L1+'Ǫ$;LZ_3~Pec\u001a^:A?iÖ\u001a8g\u0015~\u0013&h;+W&\u0013^I>7A\u001aR9\u001e\u0014{u\u0005{d*`\u0011}¬4=f\u001b15\u0016x/j\\j\u001fѫ\u0006;|v\r\u001fG\rX{EwϔLm\u001cn5l%$\rݓWoy?8lJe\u000fҁ529e\u0003ga:__\u0017qڋQq=C\u00068\u000e\u001a\u00199NwnXۚ]2xuj8\u001dQ\u001dgCls4و<+a\u000fl܃?/\rb, q=0DGcr5\u0018\u0010\u000204/\u0014\"~}Ts{re.r,EvܜGD\u0019\u001b7H}z\u001eQI\u0007\u0007;q-ri9Ѩ\r}>mmV\u000b⭱5^tWt\u000eSYNq̟\u0014X\u0013bߢm_6*m管;k莿+\u0019gs'\u0000\u000b\u0001v\u0003\u0013\u0002\u0001}\u000e\u00028 \u001d\u0005.\bB-\f8Dz 6PF\tmmmmdۤ\u000e}hͮnyc!\u0018xP:շn+9\nd\t;H΢l@@\u0002\u001a\u0014Ѻ\u001fEA0\u0015[\u0010T\u001cV%=вd\u0010\u0002KƠE\u00144++\u0002JDuIU>%Kſ+\n\u001fT\rO\u0003ﳿ\u0004&3{\u0014_3[\u0017\u0001_\f\u000bwE\u000b\u0018.R\u0014.uCK\u0003ɗ\"\u0006ۡrAWY\u000bE\t]\u0014\u000bombj/e?fSXhf?\u0012 \f\u0010r\u000eh^\u000eU\u0002?\u0002mwfp\u001b\u0002\bػ>\u0000p\u0001\u0007bP٭P؋!v\u0019I\u001a/3x\u0000G@\u0000S\u0005`\u001e\n\u0003\u0001j'hjX\u0001U\u000f\u00145\u0001@¨#񥤆\u000f\u001a5kxk ^]zB/Hf\u0002\u000f\u001e,d~\u0019Љٖ@ˀO&\u000e|\u000fP\u0002:\u0001t\u0002^;5o\n@]\f\u0017a\\:$\u000fd\u0017wX<sc\u0001ϺW\u0000[gCp$SHO\u00062R0EP<EY,\u0017\u0013$\u000f<Dߐ~!}ȳ%.\u00049\u001cR\u0015R\f\u0014\u0012h\u001aͥ%2h\u0003NK\u0007+*t~IM\u0011ҟ#e!Xb?!\u001dG\t,r6}Bɔ\u0006ȢMv>NR\u0019]%\nRJ<QI\fhB~l!u?B\u0018\u00173LH{B̤\u0005)\f!\u0016m\u0007Yp>:RpUu~ߜ%\u001eHx]/d\u0001\u0017Ϧ{\u0012̽\u0000j\r\u0007\t~O9^D.Ue纍.O<\u0016Otc\rBTPw\u0017k`w%襸Mt\u001e\u0019\b\u0001\u0019lVGKf\u0016#d<3#Kwa5,\u0011Ն\u0015!]j\u0016\u0018r}va2\u001c\u0016v7Ἰ}[S-.R\\\n@!nӀ\\!Cu~a/Zl\u0006EY`<\u001e7\u001f\"\u001e\u0005\u0013\u000f\u0002{n\\$n\u001b\r\u001aq͸Ah\u0013?\u0018\u0003J\tŀ2EyuŹf)4S6b*B:Ul|\u000b\t2\b\u0002ۚ0#Zŭ\u0011\ti4UT\u0012\u0015$wT9Si̴MuڴWUb*P\u0015ԅJ\u0007c\u001c\u000e\u0005\b\u001d~\f2W\r\u0019:b\\Q\u0017\u000eq}\u0010nE%\u001e\u0017\u0006󖱢2YQjPYl:e^Ɯ>iNs8ar8.hvO8\u001d2\u001c0|aj|tmGF8BF\"\u000exY\u0003;\u001eը&(n1P\u001cO|\u001b3Bq\"z\u000f\u0005Qt8\u001c/ǃKGhE2\rjĪ}Eb\u0013'\u001e{c\\j\u0019l!\u0010B\u0002!$K@\u0002$6Ibر@\u0006\f8\u001bX$vl'\u001dY&vL=i&I:Mm43\u001a3{y9^+b?uUL$L(8/~\u0011\u0014?b.\u001fJϤ\u0012TJ>\u000bFI\fl\n\u0012|,Ki #\u001eޖ_LAYB\te\u0018\"dD\u001eG_ŞvQ\u001ee\fsIZOKB\u000e/yȝK3\u0003kFJ0\u0004}\bn3\u0010уL̽{T\u0013\u0002\n\u0013\u0003rr\u001b\\9fW\u0005\u000b9eAEEr5 \u0007z!֜l=+;ŝ\\2S\u0004\u0007\t\u0017cr0G\u0004Y\b)\u001ekXP!\u000fJ\u0001\u0001\u0016EB\u000el\u0014\u0000kdJ'+RR\u0014D.0ԓy\u0016\t5\u001c\u0019LG\u0015\u000baŸ!5Gh@h@DЯ$\u0004\u001ba!0\\̜\u0011\u001e/񨻍(#AḦ́˚Ͱy\t4iӥr)uQL6WlzU\u0016DQ\u0003s=\\\u001d,\u0018\u001d+\u0014\u000b{xw/\u0013\\\u0013\u0005\u0010:\u000b\t>u\u0016\u0011l\u0015G<>G\u000f~=<𞍄r9\u001d\u00048\tz1iVIE\u001eזƌ\u0019\u001a3SZ\u001cPJ\\ܞ\u0001x\"Y|RԡZoS'&>Ij){|K\t!hQ\u0013< 0*\u000fA\u0005-3^d\u0012 hE\u00100cJ!M\u001aaCqG_NU{ʭ.m#۩mv4BfFԤYJh,]KNi~ɦ[\u0010ڴ\u0004߮%\b'7؇\u001a\u000f1wޭF\u000f0w]żc\u0001X\u0002\u000f[kN&U\u001d&\u000fVfG\fT\u0014F4nQZjFn5r]FЮ\u0016\u0012k/'Yt6~5F_EO\b,\u0006g5\u00100_.|\\}DW1y+\u0019\u001cZu/iВFEtUG9*=QYhc5T4sm&\u0017\u0011Z@bbR&#\nӏJ\u0013!@xU&\u001bK\u0015\u0003>zp\u0013u6\u0007͘79\u001fo=\u001bFlc\r61]ASF\u00164[˩\r\nʪnX;恸Jqʟp|&]ՇȗIz\u000f\"CG\u0004/_p\u00173\u0016\u001du\u001c8\u0007mx\f8ل\u0001ǚ\u0012y\u0007RH\u0014G\"^\u0014mQlFY]gTֵL}qq:\u000646ZGHX#*\u0012qe\u0004_k%xa>}\u0000g6ּ:\u0000:1wv\u0002w\fҠM\bζm֖Ljn=LnhG;\n-\u0006Zeijg\u001b\u001a[nAYè>\u001b_b9Qe5^Rs|^\u0013b;Gxa}x\u0017&ּ+?\u00171s [ܮhhw~\u0011\u001a{I6W*֕IvFVv\u0016ǘ:˩\nzy{-ns[\n[gD<G(Ax\u0007sB<\u0007!@x\u000e\u001b!=\u001a0\r\u0000\u001cGܽ\u0001[f\r5\u0007HURO\u0011a-*-)1\u0016UuyJ8{I(wE2g,׿./w\u0012l'\t\u00063\u0018r,{a\u0010`z\u0018`\u0018Dle\u0001x\u0018\u000e$!v$\u0019ɏ(\u0019VG\u0015\rc\nA;=g%\fpd)^g/=vE'\u001c }\t/}J\t\u000e\u000e\u000ez:`\r?7\u001e\u0007\u00138\u0007^`\u0012f\nT,||\u001e(I*\u0011r/+PNi#*&b3&[iRo\u001fC\u000ey\u0017ة5A[\u001cSxl8:8\u00130wp\u000e7z\u0003wa\u001c\u0000uO`\u001ff\u0000\u001a0N\u0001IP8ς@\u0002\u00052\f!< #\u0002y䌀\"7DH-i\u00071\u0007\u0014߿JKߡ'\u001f}GwEfrÍ\u001e`X\u000f`b\u0016\u000fu\u001d\u0007\u0000\u0001d\u0005c!#\u0003i9H\u000f\u0004Њ\u0004VI\u0007W\nI\u0007V䔕J\u0015;eߊ+bop$rOT२]Q;v.z2\u0011,\u0011c)!+\u001f}s\u0000\u0000@\u0012O5b,+<*_\u000585e\u000e\n \u0016wu\u0017콚\u0002/$'!\u0015\naGJ\u001ej#m\u000byH[C\u0017C/lA޲\ty\u0010_!\"[{e_D\u0019}d\u0001{\r\u0017\u0000*Pt\u001d '\u0004 y\r`\u0000;oQ`뛌]\u001fPQ]y\u00187}\u0018f\u0018\u0006\u0006PPi\f(\u001e\u0005PP%G]O,\u001bIEWE#Qlh\u0010,A\\l(6tQC46\u0004\u0017Kbz\u0012\u0012\u0012.ݏ\u0018wO\u000ewpww\u000b<(v'\u000b܋H\u000f>\u000fd\u0004Z$E,,si\u001eJg|XHCBr<(ds\fr뀯\u0005hf'07!\u0007_R\u0018\u0012\u000e:W\u0015Ɗ2B_\u0019\u0007}(VM*\r6U\tM\t\u000bMe\u00030?;ϋ\u0003gn\bse@\u0013@Ӏs%`\u000e-TMP^q7W;A\u001a\bT(\u001bĉf\u0011\u0017f>XxkU@c^_ c?\\p/0Q\u0006z\u001c\u0007:\u0002U\u0000\u0002\u0017\u0000e@+ \u000en:Ԥ\u0007nZpC͐\u000f7݀\u00073!/o)\u000fca؉\u0007?ǱڏCKswُM>\u000f\u00050U﵀&Ѓ\u001e)yo\u001dc\u0004ܤ\u0003Q}E\u001b.>o9\u0004G윸x~Q`\u0000\u0001:ϞWX\u001ax}ͼ{~｠5i`M󞬉\"CFQ\u001e\u0010l`\u0005.\u000e~  <_\r@]Q\f}Fi\nͦIٴ66*TL'\u0012;<wxPß\u0010-l\u000b\u0019٦-/\u0007!9M\u0014J%rh\u001dS\u0001a\u0001޷\fq%Rճdo6z'D+7\b\u0016l\u00079\u0016/6\u0010B\u0017B\u0016\u001aI\u0013hZ,=eB\u001e32\u0010X'(ar9\u001a\u001e!^\u0011H\u00123D\u001bG\u0001zpts<l9\u001ea\u00104\t3F=@:^\\'WmB\u0000T\u0010~mU5n\u001e5jm\u0004jt\u00026\u00152\u0011\u0000њ.l\u000f\u0011\u0017?%I$\u0018?KQxj\u00050\u000b\f\u0004\fqǰ\u001a\r\u001bp˰\u00157\fPk؏\u001aqT\u001b!ۿ\u0019@IH\u0015T ӍLMD{;\u0010m\u0010\u001e^\u001c\u001f\u000ehpg-{e ;\u000fm1\u0015j)\u0015N\u000bqi).9}\u000bNkpy\u0013:@^T\u001cEylyW*s})\n鈛݄p#?\b\u001f(I\u000eёe=>1E;w<;\u001eA&\u0002W\fE8>\u001eUQ1\u0003=H?y,NxdJ<2uQ-R.i\u0001OeEBvW\u0011jz/+\u0006/\fx=K{+~\u0012rK\fNX2Z*L-!Kel%]ϒ%#/X\n|*\n})v\\UlSl}\u0015M\u001dbc#?4esZ\u000b4\u0006tU\u001e\\q/Q\u001f\u0003]}IEcd\u0015OΔﰦ)[\u0017+ZW(7[sUͪ\r#s5oPt\u0011U]*60>kt&T\u0000\r\u0007Q\u001c\u000e?\u0006wQ=F*\bNm\r\u001e%\u001c4N)h\"/\u001f_\u0006W\u0006fW\u0007dkr\u00026h\u0003vج\fo\"nYo̠\u00176\u0019ABmАc̿B$\u001aQ~<)p0\u001eEa\u001eW\u0016\u001eHiCxڰܰъ_({NV\f^\u001e\n]d\u0019L\u0011k$d>=H(aAha^S}ZO#=vn4\u0013ݛjfWpj/\u001bs'Ϡ?FJ׀\b7GbCd\u0010r#H9\u00111\u0012Pf\u001d蛤^'Ygi3lz2\th\u001a8;8\u0015R\b}J_#\u001b6{\u001a܎\u0000~f췏l\u0001:lvژ\u000eȉ醕1aRVtYFtbaʅ&-jiّ\"\r)\u0011+G7Ni\u001aq4%CrcG\t;ғ=F\u000e\u0000Y\u000fcP'p\u001fFn\u0019X\u0016oEF|\u001eO v\"-6Q͠\u0011\u0003hf\u000eLΈIM\u001a=ߐ\u001ce\u001c41zW\u0007\u001cCR[c@a [5{砚}>\u001a\b)8\t\n|`BV\u0007\f`)-,5!Z>ʔU\u0006L\u001fM\u001c7]?1nݗ\u0019\u0013bW\u0016q\\>r{c\u001a\u000b;ғm|\u000e/\u0006#Y\u0003.h=?goÌX<5\u000f/e\u0002\u0012\u0012\u001c\u0010\b\u000bGAk\u0015Т!\u001c#@\u0002\u0010 \u001c\u0006A\u000ez@TBt]O\u0017Za]-3umn\u000f\u0007~\u0019L\u000b_|?~\u0013i扫t$\u000e))2k89ǹ0ՒJT2k7gk[=LڃYSL\u0007^\u0006&3iH$\u0005%Q\u0010S\u0006{\fKr\u0001ٻ>5`\u0018:d1\u0014U\u0018K\u0012kR$iAzc~97⚣[XV\u0019u\u001d\u001e\u0003'4i^ԛ4#uNpK\tJ\u0018\u0006?sYIj\u001f\u0003eC?\u001b14\u0001LӱظP\\!?kԜsr2\u0019\\\fVAZwmꔌ\u00195I^Z\r\u000fIz-Y/(bk\u0007\u0019ی8\u000f\u0017(bq\u00191;¬Ay</\u001c,Ź9$9\tRSv,3_nvI_^,י*)\rnZc:Ѹ#\u0007M&\u0005x`\u0014D1̧L\u0007ڿbIc\u0005HQbQ`\f,\u0005--)\b\u0013,QLR\u0007}~,=?15/99UWH]\u0011k=OyƘT/6\u000b*5\u000bapݝ\u0007'\u000b\u0012恥.8Vr\u001eVbk}\u00019%`*\tBfIH_PfZIWɖ09%\u0014[\\KEuʘ-nE{#\u000b;\u0011E<\u0016\u0016]UG\u0014\u001eQ(\"\u000b\u0005ed\u0018\\g\u0006S\u0010V\u0003kze\u0015r9*aGF4*CD)⤊EĊx\u0014Lūr\u0016*q*/,ۤ_[\u0015^v-,-*TP[\nm \u001f\u001et3\u0007\u0000[k7ֲ!%u\u0019NH@rXh\u0002v\u0016或Ec떈cj\fiDmlA\nsk\u001a]C[W\u001fQTY\u0019R3\bYsW\u0011Z\u0013א眧\u0007'J#on\u0006\u001eX\u0000\u0014Lm\u0010!Q%#\u00104\u00011M\u0010\u0014pQD\"т\u0004qxN\u0012hr\bm,X!\u000bnwݰyfa^\u0019\r\u001f̨<c<c\u0003Y\u0015<\u0013:z@-\u0001[}\u000e,m\u0006\"[\\\u0003mc0\u0012lAk\u000bEm!^ŊBlIWm\u0006,[$V&޲aZM:lJK,#Y`wm,`+\"8\u000es9?B6nf\r(\td҃@^`n\bJn,\u001f쁘a9x\u001ei0u\u000eS-\u0017\u0005쳊&k\u0013\u0013\u0013O/Ƿ+\u0019g\u001eos~dܛ[\u001fwq\u001d:hg\u001fX\u00161 00{RL>¤c>\t\u001dxc&;b|G\u0014:\u00131S\u0018YQ1\u001d#:\u0004\u000f\u0013\u0011As9|\u000e\u001c\u001c\u0000ҩ\u0019w\fX\u0005\u0004=|}鄓2v\rq~\t x́GO4=ˠ5½\nPB\u0005EE(z\u0006<\u0013\u0005(O=޷z]ɸ-w\u0002\t\u0004\"N\u0000!\rt;<\fJi7\u001aN}7\u001dPHI2$9\u0010CԿ\u0019p;\b7q\u001fBƝIS\u001c\u001e0\"\u0017@!tI\u0004e\u0017\u001bKo4pe\"\u000bWX\u00100/\u0001\u0016#\u0003t\u0003p\u0003L\u0011.#?\u0013\u0019o05w1cbzx;~\u001b~\t3\f'\u0000MJp\u001eT,=/^`Q\u000f|9Y\b0y\u0016\u000f\\t$o>r|O~|F!Dϵg\u0007/P\u001f\bdcE]\u0000c\u0019AnArKĂܑ\u0005\u0002\u001dlX \u0003\u0005\u0000Y,?`/G|\u0001\u000e\u0019bh\u0010EE>{F)[6SDϣ\u001d̘\u0003.\u0003c\tx6\u0005o>&\u0010\u0014w\t-\u0005C}1<%ă\u0002=\u0011&YEy\b<N\u0002\r\u0017>Cp\u001f\u000bm4\u00049q\u0018\u0007\u0001\u001342,&$ Ud=LZțN\u000e\u000er\u000b\u0012q\u0007O\u0013?/\f\nz\u0004\u0004%qx:)$D\u0011-\"\u0005d\u0015%\rd+APg?u\u000e1q\n\u000e\u001exk\b%w~\u0003AE?4\u001bt\u0014N\"|\u0012G҉Xy\u00188&>y;uvQ\r?\u0000uR8ۃo>?pnA+r7\u0010Fx@q\u001fn\u0010T\u001c\u0015\u0010\\9\u0017C4\u001f1$\u001a[1jlf4h:\u0007Ӆ/u<;HT}P\u0005em:X5\u0004$\u001cp\u0004\f1\u0007$\u0010\u0002\u0004$\"B<x-J=pQ깞jkkնVcuWm;\u001d뻏:3̛~۴o\u00177(S韮\u0011W\u0017\u0011_'}Ք\u000f%CCP>\"Qm\u0006CToB\n~Z\u0013C\f\u000fj]\u0001\u001d\u0018\u0015FҊ6\\lU~\\\u001c_qQ\u001d\u0010\u001eBYOU\"\u000e1J\u0005 F* !zR}\u000e/\u0011&\u0001\u000f4\u0019\u0000w\u001e|ku\bWa\\QƗ\u0005#.hVs\u0006|يs=1|\u001cNw\u0016'#\u001ek\"u\u0011q\u001c\u001db\f\u001f\f$?\u0014-2\u0002zp۸%\u0019Wb7;>ŹU8ӽ\u0006\u001fz4Þ8ٳ\u0005'z^m8k\u0007:CO`kO]\"\u0005_ǘ٧\u0013\u00061\u0017-O$.E\u000e&꟏\u0013Q8\u0016Ñ\u0000\u000eEOg`\u001cf_BfOr\u00012\u0006lav\fl\u001bp\u0018xi\u001fxm71Fd7\u0010w_A\u001cB>\f'\u0011\r\u001d]8\\Q|L\u000f|4h\u00109\u0012\u0007'6\u001b{6`ٮf:S-ڙLv.Yݤ]nnbkwrܺ!g5CV\u000e_>T\u0011-ÈG\u001c\u000e<&w銿6\u0016ZY=[\u0012|0,\u0002Ga_pҍ6\t[tyجs0t%zm\u0005u:vMl\u0003*[\u0011/m[bJ,ѝ.ݒ6x,m\u001a!J?\nO?$[FM|@380J]b^q!ވ,fM\\\u00012]\u001eWʶUqKiB}YHҤ_%o5O\bW̸\u0019񢔐O\u0005%RkL\u0006!jy{Io$('C\u000flH\u0003&$\u0003%I\u0016fQmNpM<Cc6̔6$4f&,\u0013'OK!O83\\P\u001a\u001e($>\u0011$2BZ\n\u001dP\r)Ҟs=n#ڌ2tŪh\u000e1hNMaf3sR\u0014\u0017Na\u0019C1,36\nK5\u0014\u000ee0j*`\nG11E\u0014\b٫`\u0000Sg~+Ofz^b)\u0002K29s\bG1s\u001cӐc\u0019\u0013\f7_k*Ԙ\u0002Ґi:A\b/OL_LoWU\u001fPQ\u0012*L,C\u0014h>r\u0016p:\u000e>iBzeE6l\rr1M4侍\u0006>'d[PJ\u0002YҪ2\fܤW(6uy8ƓuE\u0016\u0015\u0010^W\u0007\u0017(6ҜN`g!XK-\t5?OY=1#?\u0006ov\u0018\u001b`\rUyvΟ-\u0015R%(ZBeLUQݭqZ>8,;9,?\u001cy'ʝ\u0016QxɷTd8Gڳ\u0016\bX@~*P`\u001bڢQ3a\u00186=\u0002$fb+\nrٲ\u0002\u001bWZPėX}\u00125 +\t.ka][׫m]\u0002NVM_jUT\u0016XE\u000bgܤ:![G\u0012\u0007\u0012-^]4:u\u001f&rDiי\u0016;\u000b\u001d^Q%k\u0005}j_\u001cooUwj,\u0013\\ub\u0017\u00133^\u001c\u001cwY Gr`C3}Qy\u0003e\u001e\u001d1Lȸfn\u0007ow\u0017KlE~F/zGn)\\)\\*ܮ6\u0017,x2\u0017Js Kt\u0006NR\u000eS*\u000e4~$'\u0002\u0014j+텒\u0018x|Q䋃7q2\t\u0016t\u00027畖Kr!Yw]Q{;TiޣTď\u0012QV\"_ <3:\u0003S\rP4v\u000eNO~%npUFQ9\u0014\u0013FXҘlRir*\u000bJ$?I\u000fRF*ErVe*IXPT!*E9!{\u0019:\u0003\u0006;)\u001a`Tҝu\u0017i\r/>\u0015aB0\u0002\u0005H\u000f\u000e1șldBLf(5\u001c\\ZO\tN$\u0007I2Cp0]\u001e\u001f<\u000f^PU T$\n\u0001QS\u0014o\u0007\u0010&7\u001dh\"i4\bL#UOs\u001d:\r{\\?\u0010a0G!=p:c\f066)a\r~nL\u0014>\\yT\u0019Ɵ3,\nʦ0\f\u0006\u0001'-Dk$F5\u001eO46\u001a\u001a5\"\u0002\u0013\u0015e\u0006\u0010E\u0018\u000b8\u0004Hpj%&*.TӨ(1>\n&\u0001y{E\n9^٬IθI&9]hBm^]u\u000b\u001dKY\u0013\u0001+ǢVwdX'!-'\u001cY0\u00070\u0011g\u001d#Y\u0013T:Gaf)r\n/lV&TƜ\u0013ҘXe\\*T%R=PC_7f1\u0006\u001f&ye\u001eVr\u001f\u0007 dia\u0005=\u0012\u0004H>\u0014}BR8Ο,\u0019$}\u0014oɽ\u001bX{\u001cc?&ؾc~RĬ\u0014\u001dvywR@Դ\u0019\u0002`5\u0001GQk׋W\u0001I%\u001e0P\u001a\u0002Ci4K+MA/@t\fCc4b\u001c\u0013\u0010嘆HG\u0006;r\u0011X/us\u001cRغv)XHk\u0003}/q\u001f\u0014\u0002\u000b;z8x@Mi3\u0010_\u0001pz\"©G3\u0004*\u0011ViDhe\nB*\u0007\"r8*Ǣk$\u0004T͆U\u000e[U\u0003}\u001bV<B@_.S\u001d}\u0017\u0001YԞqp\n5Qod%0\u001a0o6 r'\u0010Է%\\:\u0012\u0004+\u00182Avk\u001c<]SʄeU\u000ee]#9K@U\u0004\u0017\u001c{!my\u0016`<5X:x\u0017k\u00017\u0000A\u0002z>\u0007\u0014\u001c\u0017RS0\\$1\u0010θ\u0007لyY<n& ;|&\u001ay@/ar`:}@O=@@A@w\b:\u0002(\u0017\u0010_\u0014h\u001dʹ\u00198C;2naoai&o-\\\f?$O9_Hg\u0000\u0013FW\u0001 \rc$9ϒj6@WzBW6\u0011\u001c\u0016.Ao\u001dʢw\u0001^KrN`\u0016'\u0003Nfn\u0018uN\u0003__o\u0015J\u0018V\\Wp(y\tes̘|\u001fA%z\u0012pvccp>\u0003&\u00017V\u001b\u001dlc<.=c6$z\f=08WO]\u000bԹԩy$&ߓ\u0007Bwp_<v\u001d1\u0011=H\"a,h`1\u0014\u001b0肉\u0016g\b0\bPB DD*\u0019N@#3I\u0006\"\u00142RNN@I<7>F;~v[.v\u0004B-ӎxJd\"%\"SB\rԩN\r5j\u0010{\u0000q\u000f\u0018|˿C?N?D\u0017_\b/\u0018b\"\u001bOd\nfRg>u\rp\u001f6\u0014Q)\\s;SU[wh\u0005W\u001fp}+\\D Z\u0007BӅ9\tH^!\u0018M?Ө3m&Sǎ\u001bXC\u001d\u000756sjnݸX|8%:Uj-\u000b@oX ^\u0010zXHo2\u001cL77Z3X\u000bȦ\n󸮥F\u00195*phf,Nc<Gia\u0010&\u000b\u0015\bU\u000enOG;\u001f<#pW\u001b\n\u000b.+mWs)hQ窏pJ\u0010'T98Qu\u0001\u000eKpH\u0011nu5uد9\u001e:\u001aP#\"uO\nv\"©\u001dA;*<\u001d\u0001h?p{\u0000}X\u001cN!pkgI;\u000f,.VUOuEhЕ\u0013\u0013u].)lm\n\u0010p-/ XbEw\u001e(\u0006Ke\u001e*\\y>\u0018'Y@*o1\u000fz\u0017uAS;h\u0016v\u0006cGbl\u000b^\u0010;CQ\u0019\t\u001aT6`sQl\nn?Jp!\b!\r\"',Y<\u0011\u001e8\u0014}hHBmc\u0018j\"G:r<QQ\u0011\u0001ʣ>Ħ\flZDB4zT\u0012픊51n(T\u0010{G\u0014U\u001dHOic{\u0019WT^o}k\u001bd4hg7\u0019P\u0019\u0017ih\u00182X8\f\u0013Pbx\u000fņ\u001a\u001ciuBT#'Ib9/a2a\"axFq-ENcEv:Y=k=ן@|U߶^p\u000eĦXcBI\u0001Xc\u001aզQ74QZek!0}$-3-rPe*S,1mU,65*\u0017N*\u0017$Pf\u001f)盅\"\u0005\u0018\u0003JCơqs5>\u000f}{`%\u0011v\u0005,iȵ2\u0018j\u0019/e[&IK-Ŗ\u000f兖\fy%[a)-%y\u0016jť\u001fe\u001e\u0015yޙ{\u0007D\rK]\u0013\rq\u0015D\u0019pFf`\u0006\u0005f\u0019\u0019\u0010\u0006\u0006D\n\u00135.K\u0006q-\u00155zXTkĜ4mz5m<96ij4Iۓd\u00001w=\u0003</*&~,$~#$h\u0013\u0005he3\u0003x9[/ \u001c)I?\u0015-87\u0018`slِ'<kp\n\u001eqJ\u001b4u4\u0017]R՟+\ro\u001bzWryjH\">\f|zemA6\u000eG#ulI\u001b1\u0006kLslJFɄU&3-\u0015\u000eX,V\u001bUZMI[a(\u001bw\u001ecm<+1\u001eVl\u000by+6\"SH\"\u001f\u001b?7wg\u0005:xuH?6#<\u001cMXmE%\u00014X2\u0015\u0016EZ\nS,7{2\nۼZ[b~^*6o]BeKa\u0005?\u0007L\u0002K\u001f^Ze\u0001}%s\u00194\u0002\u0001kah\u000eEI٦\u0016*\u001e\u0015t۲\u0004mPj+\u0010Klbͫq\u001aֵRul:l\u0017sm/ԬkCz\u0007\u0007u]˸\u000f9Dq-빮l-#QW\ne\u000eʔ$\u0015#JLHY\"8\u0015X\u0014\u0005r]+~)W$/U~Q)ʅpEy'<[!\u001d܃Y\u0002ż1t7\u0004|ۊQB\u001aRu&\u0004T\u0014\u0016@\u0016\u001cj:\\L5\u001cIRԀXݭRYVxO^YՐLܢߗuJ\u0007\u000f@\u0002o/K} J#Pd\bc:9pHG#KP\u001dX&.q5َ\u0015,Gjo2;u\u0016\u0011q.,q3l>P/\u0007^\u00120GO4l^\\N\u000fG\u0005V\fG3\n\u0005w><\\$丌X\u0014]9bCJLWcqҦ6H&glt\u001dҥ^եOuo4gH꣰+y|'{X[\u0001r\u001d\u001ezTB^i$1qO➉Ş\u0004dyRaX\u0016,|!S$.TFO&ͽNkpoR\u001drFIII>KB^ޠ\u0007g\u0018\u0001S@-H\u0012 z\u0003dW\fBVHX+' ;\r\u0016<)XTeʆUVU(\u0018ebNL,n\u001e{OKqޫ\u0013)ڸʐ6'.S8\\>84ʕ]\r\u001d\\n\u0000\u0016\r~\u001c\u0016OFo\u0016\f\u0004}HYSs\b\t>\u0010\u0016Ź͚پSX[hbBڟ8\u001etf`\u00135\u000b|?`\u000b4Hn\u001aX<\u0001\tS1?\u0017$0o\u001c.f0\u0015f\u001bi\u0017\u00148Y\u0015c\u0011c\r1Qu@\u0006fύC\u000bPD\u00103I&s[1e\bfƌhLoiqڪ3fL\t(\u001c(@L\u001cс\u0006<\u001d؈\t=x*)\u000f`|W\r~KwQ{s+=\u0004o\u0001^\u0004[6 Q1L\u0001Lj\u001bۢ0m,&MSX<\u0019`*\u000530\u0007`1F\u0005kZن;aX\"FԎG\u0018=a֐Qe۩BFT\u0006\u0001'%`^ v\u001f\u0003\u000e\u0018>\u0010ۣ0}\fڣ1}\u0006t'i\u000e;\u0006w,ǠF\f؂\u000e\fh?[\b?\u0019\u0006\u001c\u001e\u0011CAz\u001cdݛX'$b\u0007\u000f_f\u000f\u000e\u0001\u000e\u00031G\u001c\u0018\tD\u0010qr\u0010º\u001a\u0003+\u001aRW,]\t\u0010L\u0010z?]<XjzbNtx\b|M\u0018=|k\u001b\u0003[=tw\u0000yG_\u0000)hI\u0002\f;\u0003\f>\u000b\u0017 |\u0013d8pa\u001cD8vs 0CK77[7E.\u000b̹\u00173_oI\u001d}\u0003^3vi=\u0005EW\u000e\u0018GA\u0000\ra\u001f:-\u0000Dr\u0000:0\u001a\r3G\u0006_\u001bl\u0005]BG>Z{#=`\u00057ԧ_\u0003_\u0007\tDQԾI@!j{r \u001b\u0005aC\u000e\u001fя\u001e\u000e =\u0018aOpaȞߓ{G\u0013{]E\u000bYbj٬5\u001d{#\u0001|Dc1=GO>\u001d\u0001g`|\u001aC\u000bx\u000f\u0003/y=dO\u001e4\rrjbE 20*;o\u000f!\"\\>'ug_KH\u0006\u001e\b2\u0001kDT}\u000b**\tEZnnh\u001a\u0006\u001b\u0010\u0001\u0011YDQA@\u0012\u0014B\"2bM01rRV&NRV8ff\\*5qܢo~T{=缤O~l\u001cd!Hu'3en\u0000Dٍ^\u0017Ӊ\u000fYDdd\u0015\"d3AvtS\"\u0002oq\u0017?xW\u0018?\u0007\"\u001c\u000b~\f1\u0004\u0010\r1tK\u001alF3`'5ڨqs\u001fs\u001cg#>mj\rO9z<&ȿ\u0006?eg7N\u001c&qd\u0006OT@E\u0002ꬤF\u00055j8s#5P\u001a{8g;V!}\u0000i_\u00182\u0019:2G;C\u001e5\u0012ķQĝL%_AԌ3sӨCBjF%5jH-_'QB//\u0000} Moq~$7 \r/D\u0005Ác\f9}\u0014\u001fr]*|\u000f=c\\|\u000b\u001burQDUԨF-5>V9wd4o鋫˴\u001ewi0Z\"6;ٙ0eG'\u0010\\;kBq5JN&gͣp\ry]U\nDh\u00059YВSG|\u0013k\u001cwqlCye\u001e\u001b\u001e\u0007Æo$O^1\u00177\u0015\u0015x\rҰ,\\p9bu,ǙU85|\u0003z6S\u000b9G#\u001aq\u001aGF^Qߠ1]\u000bsh!ȓx吻|!+ȍpy\u0016~.\u001d)DpM1lt-C[\t:\u0013jtmD6\u001cto\u0001O$xm\u001d}qoc<\u00036WL7OfRߛ\u001f\u000070\u001dL\u0007.Ot%wW􎝆|=^\t\u0018\u0016\u001c}`\u0002M.Ůk:\u0006-ScJ\u000bO9Sy\u0005lv\u000bM=D+4xB \u001b\u0006y4\u0002\u001bO3\r:\n]&s6\u000eL\u0019*\u0011gsf2ϴaR4{\u0015bW\u0019*UY[Q?kP7S+}]s_\\uS^})\u0010ZO.\u0004;\u001d\u0007v{{bs\u0003%}4h1'\u0011\r>VlDo\u001ej|P[*BoηUX3P>G\\=X6rޏb|Y,yP<\\\u001f{-]~tS\\ `<Wl?\u0005M\u001fza?Tӡψ*?\u000b*ұ/\u001b~\u0005jR̯B(o\u0010JwE\u0007\u0015\u0001}bA]iY\u000fb~<@\u0004}6/Gd&8o;蛦\u0000g\u0007GB/*h>*\u0016aRJ=ʔXLAҎ\"eBY$,W\u000b˔br+-]--YtI\u000e#e\u0005?!\u0019,CG߈\u0004.10vƲ1\u0000-Zָ.\tUc6\u0013C}P\u0016\u001a\u0012U\u0018T:\u0014(PL<UTU ʄlU$U%[\u0011)=\"-\"-\"5\u001a.#\u000e\u0010&5\u001cC\u001a4Ўʈa(\u000fwʈ)(F\u000f\u0005\u00105U둣G:\u0005Yj`W\t6M\u00144U*h\u000e+\"*,_(̑o$s,Y!sG\u0003\\{k3{\u001d|n{\rkE\u0014G0j\"^\u0012m\u0010`\u001a M.r\u0014\n1YV%nPGQo(\u001fD1\rrq)jwgeg#߫v\u0014,vFqXL\u000fl\u0000CDހd}\"\fŐ-$\u001a\u000b\trd\fۥؘvELi!B\u001fwȒa\b7\u0019\u0007\u0017\u0013x\u0017P#} \u001av,5@f\u00072Ӑfո\u0000`Xj\u0016#1΄\u0014\u0014)\u0018\tqDFԛJѦ\nG5]SD2X\u0006{\u0017sI,βoW\u0016Lj9.]Þ\u00047$L%a\u0016\u0012\u0013#!1\bp%`4\u001b\u0011kNl\u0013<!\\*jbYҘKj\tEsE>y!E_H^\u0007X<j\u001c#5Y%\u0005\t\u0013`J\u0001c/bS\u0002`H\t\u001a\u0018D[ZӅ(RAc-\u0016\"UbuBǤ+RpR9_Pp\u000e|\tl\u00076\n\u000biG\u0016}dc͝>\n1cx\u000f\u0019\u0016@k[H\u001a\u001ab[\u0011f\u0016B+\u0010:q#1&.\u001f\u0002헥{R\u0014h\u00012q<3I+s\u0015#kvxa>\u0004Y=DlvBP&-~\u0018,\"d%ĞXVjI 5bԴ\u0018c1ZiCvZ3\\o1\\r\u0012{y{lb>Kz\t4&Vq.\u001a\u0015]#\u00134\"!R\u0013\u0006hX0&>\u0013\u0014\u0006'dӀ\u0005~M}̽5G%]3G%>4G%\u0018Vhd\u000feT>`\u0003\n 38\u001fE<\u0013gTJ\u0007&;iHbR48%L\u0003Sh@jT6Q}Ҧ+:mҲ\u0014+3m),)tUSh\u0003ShdArCc#˰\u0000\u000b\u0017Jsz2\u001bgکOzguStV\u0015_\u0011ٱ\nώS\t\n˙М\u0004\u0005SPE\u00019kS+c͹,2L/RX\u0012ݲ|އB}0\t\u0005f\u00158*]A\u0005\n,\fV@a\u000b\u0007\bZƨe|,3mIU7\"ue<-\\Ga<X|\"i\rz˗ЗQbjP\"M1+X\u000baFJԵC]J}U\u0016\"ϲ(y\r{Hkr)Osy)/Sf9\u001dCy9~#ǒr*az.nc[\u001e5(\u0006Xhda\tV>cFg\u000f\u0017WA+%r:!\u0007\u000f\u001a-;klql}Q\u001d3dcMW2UP\u0015\n#[y\u0003\u0015L@^RE7\u0005_W?7Hq؃R\u0016)`+5o\u001ckTg/S\u001d\u001e\u000b|!adg,@PՑX\u001d\u000fuw\\\u0006\fxº2\u0001s\u0001/\u000e)\u0006k\u001aS\n܍>i\u001cޖl\u000eo\u000faH\u000ea\b\u000e1\u001f\u0002~R=Ci}_\u001eCP\u0003\ro,^Ç<\u0003\u0018OXI-A\tGhFo\bz<\u0012^ÒsdwT2\u001fGvN\u0012I8E\u001ca\u0012g0?:\u0014\u0013Ǚg\u0019\n\u0018\u0002hrM@-H\u0005|\f-\u0013\b/:'\u0014\u001e֣?<!9׉\bs\u0003\u0007E\f%o\u0010*q|`\t\u0017N3\rsѼ\u001f&'\u000fgSy\\\u00031)\u001dOI\u001eԾUC\bl'F\u000f\rh§pĨ}j0,\u0019\u0010]o9\u001b-4\u0016^\u0016\u000eW\u000bB-I\u000b\u000f|\u0014rvw\u0007뇮;y:\\XJgp\u000b\u000e_\u0002۪p\u0007{f遭=5\u0018b0\u001b\f)T\u0011\u001b@\u00066\u001038=\u001d/0\u0018\u0004q\u0012LY0\u000fr\u0010C9\u0003+l\u001fn׿(\u0004O=ҏ\u0007wvW\u001arnǥ= \u000b#`<L7 \u00052a!/c\u0015'Dc=\u001a\u001bPڦ[\u000fuP\u000ft\u0002s3?vVFk\f\u0011\u0001\u0017\"`\b<\u0013g::Ih;e\u0016EEh*֯`MbFݤ\u0016ur[׈><ŕ\u0018ldl\u0001l\u0015\u0010j֟%hMFg&\u001a9\u0016GE\u001bq\\#dG\u001d\u0005\u001d(+t|+e`؛\u000f\u001e=vE\u0017Hr\u001ash@\u001e:\u001ast4C\b\u0012jQNFi\u000f-\u001d9c<uj5Y#\n\rԷcbz\u0012\u0007;#w!`sqQ\u001aDʪo1G'\u001d8N\u001c!#ZkuX\u001b9\u0011zZ\u001b{\u0011KBAS\u0018y[x݈:5ud\u0017]hA>֋]\u001dDNg\u001c:ЙCGa\u000eoA:N\u001e:K(gJm\u00165b>\u001di-mP՝\rU\u001a|Ǵ\u001e\u0016U\u000fl';cWC(\u001d<DlvvڽZn\u0017\u001adm\u000bѡPVbU;U&wܭuZ;rrG*u6PS<B+\u0000'INU\t\u000e~2\\\\Fk\u000br\nZ皠nZ6_+T[JU^bZ-8UקtykşVۓV\u001cɵ\u0013׈`z-wV6zku\u001bFXvQ%ݧh\f-N\u0012T-Β'_\u0005>NzM=\u0005~WO2\u0002|u{7W\u0000 \u0000?w1\u0006Ԅ\u0002ZY?T\u0001}40VEq*\f\u001c\u000bzM\u000bf*7h\u0016\u0004+;8WYE\bYy!\u001b\u001eGsC+-)%)a_ڸ\u0019ŵ7+x(0fl\u0016#Yik͊P\u0007-\r%,@=# \u001a^\u0015+eOiJ\u000fWZxR#2\u001cQ\u001f>\u001b_\u001b\nh\u0015- ZE%\u0005H\u0002y!@\u0002$\u0000\t\u0010$\u0010BТ\u0010m\u0002N!Zҭ͵\u001e{3nu;֞vNZ!~>Ͻ`͊\u0017O= S&\u001b',V\u0012\riw\u0000$uLs\b0^5K>\u0005[R)G{Z\n6g-=\u000fXaڌ\npQ\f?|mX\u0019\r\no^:\"YDX\\f!U<ຒX\u0003`d?|lΞH)\u0016E\u0014kӰ:;\u00179:rLh)GCN\u00159u]\u000eQ-\\ʰQ\u000ejIY̡TP/\u001c*IT\u00128\u001f0\u0007\u0017Tf?گ>\u00148b\u001c팣E\u00195yhV-O\u001c\rj\u0005\u000bQ`e\u001d<\u0017y\r[v&*w\u000b_4#2]Y&H\u00074cO79rZM;렂\u001e\u0016\u0019Ʊ\t_3\u001d9j&c6\u0003.\u0012N\u001e:\u0013tpQæ_/'EY\u000eQZ'\u0014\f̆wd%\u001b[\"G\u0014+\f?Xu ;i&\u000b}60\u0005(\u001a\u001eӰ\u0014\u00069\u001clT\u00184\u0019\na+,\u0012ƕ(5`1\u0006h(.z^\u000eɊLC2iTVh#H\u0011Ec[LyB~'Z$[s8ܦIpf\u0014\nbLa5eX\u0002X0QRBq*\u0014[`4\u0007(0\u001f\u0010zOd:yc/\"ɴfI\u0019JG=L+\u0001s3\u001fY&Pa0J\u0017R\fsi:K0PTf̊\u001a\u0018ʽЗ?\u0006]yX\u0011}\"z\\loTBe(me-r\u001eA/{\u0015\u0010\"z`-]\u0015c,M\u0016b{,KQhO|+UA[YJ\u000f*WC]\u000e[:l1p\u0013YUD+~\u0001g9\u0010 ۀ}M\u0005.G\u001b}\\\u0007fN*\u0018KqC0TGB_\u001d\u0003]\"hj!&\u0013y5*\u0005P9P:+ZlW3\u0014\rtu\fWH=*gDjUO!wIB\u001cF\u0012\u0006s/QwZǀ'Ɇ5y\b0(Ȑ_\u0017\u0001{\u000e8\u0013CAGL\t\u0019V;V߈\u0000Vx2o\u000fR/#{Z$y HDG\u0012qKU(=\u0001C\u001b$\ts\u0003[*e^\r\u0018Oo*2}QHGZ\"țRڔ\u0015M*,o6`Y\u0005UHj\"ѿ\u000eK['\u0016\u0007?m$4CB\u0004$\u0016!s\u0003;ڹ\u000e'Zg\u0001\u001b[\u0002#cR3\tHi@R\u001c$bi\u0012,i]G[\u0015Xܪ\t\t\u0001;\u0003u\u000bFl\u0003\u000b\u00021\u000f1man%\r¼\"EB̺1q}~ux@s\u000b`3]9 ;v<Y휋G:㱠3\u0011;ż\u001e\u000f\u0007-\u0013\u000f\u0011\u0015\f!2x\u0010Ø\u0019cf0k\u0013}6J\u0011sl\u0007\u0001O\\\u0006<NDId\t%s\"*\u0014\\\u0012$\u00181#d\u0007SC-\u0012ڊɡ=}\u001c\u0013cӟ1Kmcq[\u0010g<\u0013؎U`\u001d\u00044\fHv\u0007\u0001f'`Z\fLp\f&\u0013 4Ba{y,0\u0013\u001c`=z\nbc\u000e'..v7u7R\u001f\u0006j<x\u0011\u0007\u0014\u0007d\u0012\u0007L{}h?o?pl\u0004\u000e\f\u0004\r\u00193\u001f`!3\u001c\u001bn\u001f\u001b\u0013pHB\u0001\\}C~F\u001d\u00003\b0G\u0014y\f\n\u001bd\u001aa\u001cC\u000488\u0019\bM\b/\u0011\u001e#<hFXHL0\u0007\u0018oM\u0012\t/\u0013s+<^f\r9ZF!0\u0010\u001a0g~?lJ2\u001f\u0018Ǜф\u0006m\u001a\u0002(/Q\u001epaAF\u0017\u001d{|gn\u001b8\u000eN\u0006_I\u0002fs\tg\u0003&EMN\u00068\u0017/%6If\u001es \u0010_e\u001c\u0019K\u001a\u000fY`9\u000fϓɗ[3M?\u0006j8bNS,돚Ԝq-.#\u001e\u0003²b\u0013Gw2)\r&8o\bM-^|x\u0010~wͺI3s\u0017\u001fGԍ\u0005\u0010M}c_\u0019\u000e\u00133IB>#%L-[J\u001f\u0003pmcr\u000560\u0001%&^JI$\"|H\u0014L8x˥\b^ȩI \t@\u0012@ \t\u0000\\*\"\"^\u0005b2T@W=j>gmt]36v[NvݦsT|?D~;K\fNH\u0015#H3i#ϑm%1|I1G,C\u000fy|G\u001e3y\u0013~g\u0004_2\u0013)ѐ,O\"ƯgFCld\u000ebOajWL\u0000#>[_0o6\u00039a\u0012\u0019Oƒ\t#5\t&$dP/:\u001ejT\u001bι_\u001872~\u0007w1N.~v\u0004p:k\u0019ߤ0ڍ\u0011>$\u001f<x\u00110z\u001e\u0010oD2D|Z|\t\u000bkF\t5Zo`&|B\u001f7q\u0003ܲ\u0018 W8_Um/-V\nWțO!S\u001e\\Qs2s\u000bfNKƟ/~lQ@RfV_ǻ\u000ee\u0016}ǛN؃>%qαRgrr\u001eaga\u0006\u0016\u0005oj\u0006^\u0011ԓ24j\u001aZ\u0012}\\\u000bq>)t\u0004vpgp\u0014//^_ğYopjG708\u0011=]\u0018O͙x\u0003ԓ3\u0016I<87+]Jjbf@FRc\u0013n)C\\v\u001e\u001eV{k4Wy?\rC~9\u0019wyD)\u0010B8%3/\u000b\u0007D\u000e\u001bQU^jM\u0019\u001e]c:u\u000et='ye\u0010&I-`S<m^i:?_\f\u0013|px\\\u0010\u000eLމR윤B\u0001=Vt8ǃN2tT9%h]g}w\u00136vc>\u001dG\u001fch\"\u000ex\u0010^Qy1H\u0010}\u0001^\u001eY:9\u001a?\"\u000056\u0005\u0018qj66LubT\u000fZGKB<\u0013\u0014k\u0002W)h\u001dV\u0007ub]X1\b\u001aeG;\u0018Kf\t?6I:\u0001\u0015E1g\r~\u0013\u001es7ڧ\u0007mF\u0004\u0014eV\n5f4\u0006`Up>V.\u0015X6\u0006!Q\u0017Ҍ%!X\u001c\u000350<\u0016_Eugx\bG|Lw\nd*g\u001d>\rIǚl\b\u001f)X\u0013>\u001b#\"BTG\u001aP\u0017\\,SEsajTϭCFTmCyT\u0017G\u001d@Y\u0019̋\u0019 Q\u0012o\u0014\nO}\u0017؂\u001dձ!|u\riKd\u001f煕Q~X\u0016=\u0003u1\u0011cQl2\u0016jP\u001dkDe\r\u0015qN̏,\u001cQ\u0012\u0012⟠H\u0005n\u000b(D\n\u001d\u0011>\u001a.SL\u0006\f>{H\u0001h\u0016%kS'F$\u0010\u000b$Ơ\\*C4\u0015\tz$d(\u000eOB\u0001܉(L\\|2dp:F87`O\u00049I\u0012a\u00180x'29g\u0015Iigk譞>\u0016'B>\u0005e`H![B\u0006IFlp&9H*F^r%K\u0006))w\"Ky\u0014\u0016UȢ(S\b`\b\u0001n:ظ\u000ev`\u0007`볎>VG-}+Ǣ$\u001f\u001et\u0014(#R#O\nJ\u001c\u0005٪\\Rݰ#+\u0016F¤QsDyUd _\u0013Ad\u0000s6x:ْ>\b\u0012(\u0014}T\u0007\"O\u001d\n:\u001a\u0004X5)hĄLm6\u0002KaLAn\u00156tۑ?\fHcNA\u0004F?V'.\u0006\u0012w\u0017/Zd=F.\u0000V}0,9ԋa+`ԧ!Ð\u0001\n}\u0013\u0012\u001b\u0017Bk\\\u0001q=LH5\u001d|Q4@\u0013A4\t\" F\u0001\u0006'Aj?\u0016xK1#M\u001cQ\u00162gLdL3a\u001c\u000bYt\nZ\u000eL\u000bԙyH\u0014!R\u0005U2d\"9k\u001b\u0007^>d{|~\u000fy0Bc{?wp$(^ J\u000e5ři\u001b\u0003\u0017 h!Pۢf\"Ֆ\fU\u0016l\u0013RHqCS\u0001yRHoԾ\u001fs\u0010GBl\u001f$v\u0001a3#{/u+9Tq/𹼜<\\z1:EPyC\u0017YH΋D#\u001e\n\u001crG\u001ad\f$:m:!qAEk-b]\u001d\u0001g\u0010|A\u001e#% 9i?wQ{\"\u001a\u0005>9*VK!G\u0003\u001b%=\u001eB$A\u000e\u001d\r;\u0001\u0014y\u0011 @TQ\t\u0016`NQ#\"7#x\u000fO!m9B\u001e!H@+9Κ\u001f~/;9\u000e_\n4s]QQXW\u001c\u0011eu\u0000eߑE\u0014\u0012=-\u001a\u0006\u0017f\u0000Q(̸ `T\f0q8QU\u000bbզAlVMM`L6\u001e{bCRc4h\u0012ow{\u000bxmcb-\u0018\u0006fJM\u001d`PW`ŘՔhS\u001fE\u0006(4\\\u0011\u0019\u0015ldZ\u0014R[\u0014_yE\u0019\u000f\u0014`oج\u001aloCk\u0003iYΧ6B}3UXO|)uF(<K9]\u0014\u0013\u0018\u0005$*0\u0002r?wrS%/Cy{IydȫW{̻$C\u000f20Mic\u0017vE\u001aFC\t\u0000\u001f\u0018]o\u0015Ǻ*_\u0001c\u000e%N\u0006Ӑ$O,\u000fL[f)e\\,{d39oɥ.߸H\\y`\u0014[\u0018t\u0000C\u0003HH\b\u0000okG[jV'k\\rv:Z\u0007u\u001c$MℵD\u0001\f\\C-i\u001d`|9\u001f1]%^&\u000f*YHh\b\u0002\u001frU\u000e6/֙\u0003\u001d\f4>6\u001a\u0001\u001bVvЫ\ndά<Ȇ3D$\u000fͭlJabWS\u00172\u0006mzAW\bڄf_0'\u0013xn\u0010i\u0002]'\f)vba'luPC!d|\u0011R[Yp\u0016\u001e156v)40wI\u001dw\u001bv\u0000jQ:jXG\r\r\u0018.@\u001aZ.Z}-\u0007Kb\u0015na14\u0002\u0012,tt\u001aN_tb\\K\u000eK\u000e34@\f\u0006o/ua\bh\u0001j!j\b6p\u001bE\u0003Nc$\\\u0003bq'-%r?=\tkgY,zA\u0019&Z\u0001\u0006@\u0003q\u0013.I\u000f\u0003\u0006\u000f\u0002X4iÁ=9]\u0000lix3o'3#MF{\u0004-\u000e ~FK.wuN\u0000Đv>Q@$\u0006M1p2 u1(}\\\b4׸\u00187qț\b|\u0013m3}ld\u0001\u0000Iƿ>_{\u001d\u001c[4Ү)\u0003yWP(]%|\r[6]?>F\u0001C#\u000ec61qF./l\u0000~\u0010\r`0)`\u001c(bJzآ~d|i\u0001s\u000fY;}/\u0006\\pedZ\u000b\u000fAwH\u00110\u0011Ŵ}k1˰_}\u001b-\r\u0012:5\u001b5u]\u0012|\u000egu\rN\u0000\b\u0018|OC\u001a\u000fx̹7T}\u000b\u0017c\fضa{.0.S0I\u000bv͏C8\tZנ\u0017\"\u0007ZIJa\u0002\u001a/`߈\"ih~1/Ƕ\r\u001b\\M\u001a?\u001dЧ<~b\u0003*-a8k\u00077刦\u0017\u0016NƠ\u001bABc\")}\u0013gc\u0000f\u0017cߪ^N*ȎSD2\u0016P\u0004-T+nKK_\u0013\u0004ϡ1L4ʓIg\u001d#?\u000e\bEhX\b\u001erc\u0017;Yv\u0015O^Ö}51%;JU<f\rȋcQ\u0017?=IBg\u0018~E#\u0005ih\u00184SN1ehTh\u0013oֱ5HUDRn\u0013|OFI\u001b7c]O;99(o4ыկٓ\u001ap>hi\u0006#:cFg1v\u0013՜\\;\fkeҧ.]:6k\t8qW:\u001bDy{+\u0010e\u0000Pvw9]\fƧimZq\u001cGiV9hsV8\u001bs\\\neJ]*TNu\u0016A\u0016\u00132_T=\u0015z6k\u0013\\FXᷔaw͆SUnZ\u001e\u0015\u001e=̣U9R%3EiI\u0016\u001c\r*4,\\JhX|~C9>5fSvVfs\u0016\u0013\u000fpN_Fъp\u0005uQ7N\u000b:s<y]Fin*KUtei_f,e\nXm2\u0005WzJ\u000f:\u0019w4#\u0004^oc\u001aZן཭R$\u0016\u0004x(0@s\u001f]}5'df\fӬ\fMVFT\u0019Cӕ\u001e6[3\n5=|W\bFjJQF~Q596>h\u001f\u001c@\fh;\u00033bʹvK| ]9\u0011ʎ\fUVd21fF\r֌\u0011\u0016=Vi)\u001a=MSf)kRb5)\\\u0013c7+9Zh|\u0019qݚy\u000e}\u001b;\u0011`\bs\u0006آ#;EXo\u0006jz\\kj|\u001fMV*%~&unS5Q\u0013r5.at_7W=hTbF&6jd\u001b\u001aѳm\u001c/\u001e\u0015uT@\u0010T@S\u00012\f0\u0003\f]`H\u0019䲨1\u000b\u0016`y ^K$Zf*hY)=Zֶɶv:k%ִܓ?>y}}˚\u001fƎL\u001e}%q4\u0010bb\\\u00109\\0\u000f\r-_EU\u0018\u001e\u0004G$+7ª\\eGڔ\u0015YQ5ʌ5EJTjl,\u00125?NܛE\u001dra\r#Ǌ\f+\tq\u0013-z\n)?zr\u0013\u0013X͎1*#&U,\u0016*-ήԸjY\u001cR)JNإ2%Șx\u0019~)S\u0000'\u0001FNm\u0019\u0018[\u0003q88\u0011GE9^2LTa\u0019J3D)Ր KB\tJI,Pr\\%ͪiV'4˸Q2\u000eː.;\u0000?^b911AaaV٦\u00110QG\u0016\u0010%\u001b#dɔ$cRf%*1D\tɏȐRfř\u0018\u000eE[\u000e*\u000e|\tw)<@75؇\u001d~\u001eg\u0003א2jSHd\u000ed8̓d4\u0007*<S\t\u0018\u0019,\u0014oIU\\jbS\u00156_i\u0015ިu\nnWfZVh\u0017<))}#`/ߎ2z3\u00012\u0012G))NVb5Y]`Ru\u0001͘(Eg$(*3E\u0011\u0015Ye9FY5#kBQp\n><o)8O\b\u001c(^`y\u0001R̳1μgyĘJ\f#\u0015\u001coELQxNr437N3r4=Ϫ|\u0005SP~\u000255U\u0001\u0005K+8)s>yS~NC@SK\u0005o\u0006ޖ\u001at/*zXlȤ,bI&XP,\u001ac\u0015R4QE\u0001\n*(M+NT\u0005\u0014V)\nM-Ճ%4C\u0013Jɧ䔼K>yC6&\u001435Jz\u0001YQ΅Zz\u0001\u0016-\u0017X҉o\u0016ya+>J\u0001\u001e+\u001d)5\u001eI0=hD{&3SV$\u001a_VqOjlyʳ<˳:8e\u001f\u000b,\\~Zʹ4\\SHl2y\u001c1!P&JOոJ?\fHyU%ʳ*UcQe{\"n[FVKի\u001aU\u0007F.wZ\u001bVmh\u000eȠF΅ǩ\u0003zr@L\u0011\u0016\u0004I1Z\u001a(7T:B(GFe遺\u0012\r:\f;л\u000e\u0004\u0003X\u0003_mQg?ߎI~%g#=\u0007Rb|J\rcʥUÛйM\u0010\u0010\u0018\u000e\\\\<lF\nH-4\u00199x\u0010p!̖\u0002bhpj+ވVJxm\u001cH\u0003\u000325?\u0001F\u00135\fm\f[m\fm%E%fnWS,b5:\u0005._\u0001B冴O;o-We97\u00176q&mOI0\u0015|\u00133.O\u000bo\u0007v\u000b0na\u0018`\u001f\u0007 .\u000e\u000e\u000e6t#|NA\u0005s45\u000e{\u0006|w9>k1>$mIgiໝSQ;\u0013v\u0017M\u001cG'$\u001f]\u00150P`C@uQN\fw\u001e+\u001c\n}\u001a|7[ًO\nFwJ]#y\u0012PR\u001d\u0010\u0003a\u0006#>\feԥ8\u0019\ft4v71qz\u001c\u000ejiW|?<g\u0001>-/҃\n܏WO\u000f\u001c1x\u0015NA^SIAN$'g\u0019R,\u0003Y\u001e\u001ahmy\u0001׵u/`ͅ35\u001eb\u000f\u001e%Ұ>\u0004Z\u001a\u0007\f҅\\\u0003Opn!\u0018p8>c\u0010\u0001\"5ec\u0017,\u0017ýKK\u000ff+ų`ߐoO!|\u0004\u0005\u001cz-Kp\\uCѫ\u001b\f7\u0019RnWosܦHv\u001f;;\r\u0001\u001f\bP\u0004eP\r\u000ehfh(M\u0001Ey\u0007Eևb7:󺮢g\u001aKp\u0001>5H\u0018\u000eCa\u0004x$\u000eq`\\,<u}[rlwq8%̾F\u001d^F)^Bg~I\u0012 A\u0017gX\u0014>?Yu\f!yaM\u0017Z\u001c\u0016`{!`{9)E\u000bh̏Q\u001fh\u001f;:.iofp\u0006^\u0013\u0017\u0003'\u0006Ѻ7/}J3\u0015G~1`9U~\u000bYK\u001dm@k6Ӣ?ڵzGOѺѩlS$8AQn<\u001d\u001b\u0010r_\fw_pYX;|\u0017r\"𓈏4-\"el\nֱ\u0010\u000ec\tX:\u001dV;؎t\u0011^\u001e*ׅ5\u0018\u0003\u0007\u001eh\u000b9$\u0012\u0018\u001d\t\u001fV,a߆};\u0017plՐZ|\t-]ɳ|k\u001b\u000f\u001ayF\u000f;\u0018lݘ؀m\u0001\u001b@a\u001cn_\u0004L b \u0004\u0000\u0014-\u0011M&kk^5SWUv6ҤjTiViӤݴnUNC}\u0007>}}.Wy%z\"Y/\u0010\u001f_{Ob>\nۻ3>wiJ>\u0015EO\u001e\u001bOUE\u000e79𓣛\u001c}!\\+q~\u0015F6e\u0014;K\u000b0\"W\u0017ҽ\u0014My\u0005ޑ`HRsxx\u0006/Yڱ8]c~9X\u0019ze\r\u000bTtOҢQ\u0017B|c\u000f29w\u0012\u001dxz8-RL\u001aSγhq\u000fyi'O\u0017oi\u001f=\u0011l\u0018ff1\u0015s\u0018\fc\u0011`4!F?јop4Vc:W\u0001y,=|`oŔ>1\f\u0012D`1*\u0007u`6ƎjLz\u0010a\"Ώn\u001c\u001fh\bF0p\u0006C\t\u001b\u0018LÒ{\u0018_\u0010\u0012CI\"\u0004%M{MlbdK II\u0012%LTc,QcI%\u0018:0,APڀ!i\u000bH;0 El\u0010dc\u0010dsI^EwUtm\u0004DG{+3\u001dwLYfV\u000b37C;1\"##)\u001a\f\u0016/ՆC\u0010Гք6tw`z?:GϘ2іy\u0011Ywz\u000b^ω?9\u001bB\u000e\u001f\rx6`uKlfiq'\u001dL)\f(R\u0014@v9NgѦUG\u0017ޜ!4LE4?\u0006-xo\ts@\u0010Ïy<m66(dᜡgm\u000fGJ*\u0005*%\u001aV@n\rr\u001bјۊ.\u000e>\fuQD\u0006\\,\fNݿ\b{xm\u0012t\u001dM\u0015c[:oC\u001dxhdj2q@FV\u0007\f\fZ'\nܨ-Z\u0017K\u0007g1T\u0015ΡR\u000ea\u0007v+(7~@\u0010\u001fN<_&-7p%~X\tR\u0000u\u001cd\fh,LGz}\u000ej\u001aTp\u0019p\u001a\u001c2Ԣ؄\nc;\u001cE\u0002즣(3@y\u00156uX-/>K\u0013%\"Y=r`w\u001eps\u0007\u0018\u000e:T\u001c:\u0004&9&\u0005*Mp\u000ba7Qn.CŅRK\u0003lm\u0016$iXga]\u0012\u0011\u0012GQ\"}\u0011op\u001cK\u001d\u001fcm*q-$\fRG7u2V<U5\u001e\u000e\f\fYfj-B͆b[\u0015,nK}0ul\u0010\u0010\fۯ@g\u0002ǏuW9D($^#\u001d/cH\u00070u\u0003G'}c1f\u0018I(خٞ\u000f݀\"G\t\u000e\u0007\f\u0015W42\u0000]\u0000\n&ZB\u0012w|\u0007j',r\u0012\u0003<G\b^qqij诲H\u0012\u0014908wQA2U\u000emu5򫛐WGnM\u001fԵǡ=\u000bP}\u001fu\u000f\u0015W>P֊&E&.w\u0003\u0002m\f\u0011\u000bli&IX9㡭BS\u001c5u\u001bv۠T!ӆ^(\u001aFp\n\u0019Ho\u001f\"!R\u001b䳈=%\u000e.p$[;xuwI\u001b\u000eE덂9\u00119r(ݬ«CׂL\u001d:|Hu!7\fyI$lBr\u000bҖHl\bI-_Y̷۴?77s, \u0005ijڥZ\fQn \fY8H!ůܟd\u00112pAф\u0000\u0012;\u0006!\t !3\rO\u0011q\u001dF_|g|\u0013\u001cAfY\u001f㼓#\u000fVA}\u0016FK=J}\u0010\tio\u0002\u0012{eD\u0006$\n\tB\u0001\u0005\u000b\n\n\u001eD\u000b\u0012\u0011!L`0!J{\u001f\be7#b\u001c\u0017ɽ6ɼ0Xa,L\u000f|qzJ]\fPSS\u0006m$;\u001a8D\u000f'!b8\u0005\n\u0007-,FI>\u000b\u001dd0\u0007 1y7ȹf{5\u0007\"I\u001e\u0011q\u001c[\\9\t\u001fN\u0001\u000698\u0016<j%\u0013\u0012\"j:Ùn\u0014\u0010}HWdBLl!\u0006p\u0014!Cm8݉]^|vcwGxKzb\u0004\u0012%\\D\t~\" '$D\u0014߱\u0014\t,[L\"8[.\t[d_d]d]-\u0016\u0018\u000btBFd\u0002 {,J&Dla,.sIJZeNHڶΜA\u001fl\u0002\\D\n!{\u0016\u001f\\\tT\u0015/\u000b\b\u0002\"\f;\f\f& \n\n\u0012\u0014A\u0001WF&%IAbq\u0003\\\u001e\u0015ZkԘU$KxHj\u001bcbXNԦ9{,޷|{\u0003\u0001\u001d\r\f\u001b+#\u00009Ye4Pl\rX&p\u001e?\u0007\u000f(\u0002^{1O`b#=i\u0015uHh2\u0003ë\u0003ϵ+&\u0018n9̠H<6\u0012&\u0006&t4\u0019\u001d-\fF-4f\u001aP3h&M\u00104\u000eubCɗ:Kf\f<pd4KͰ\t͒V6~\n0rC}eHn\r\u001cNsB:@\u0013<@A_Ơ}G{||>|_%~\r/\u000b.\u000e)\f._\\Z!,8\f]u'0B\u0000(5\u001dwN\u0010\f\u0018FO3朜>dPg\b<Y\u001b\u000b]\u0013qp\u001c8{\u0010N\u001c\u0001!d\u0013Թ\u0014^\u0016Z>\\Ҥ}jCtrt\\\\ȯ\u0011k\u0018\u000f\u001aK\u00198D\u001f??8{=<<\u000fw\u0003rx\u0019\\\u0005\u0001O\r&5\u0015y vh}\u0016q-\rt\u0007=\u0007\u0001!\b P\fFj0\u0015ؔf/\u0007TdV\r[=v\u001d]\bKu_}\u0001K7펝ץc+\u0002\u0001 \u0012XAS\u0001\u001c\u001fZQ\u001dvg+tB\u0017-l7\b?ckncgX\b>\u0005Nth\u000fo+\u0013|+{n*\t\u0004^k踂?\u0003t\\B{l\u0017um29wtt\u0019\"w\u001a71p\u0018\u001c\u000ey\u0005G\u0014\\Vx\u0007塿\u0018ۏa\n\u0013]\u0019x:\u0007\u000bk\t%\u001c^i optDoq>!;p\u001c(cv\u0002;i\u0007\tw\u0007|-88,~>^rlWa\u0016د@Z=ZAX\u0003f8Z_m&:-D\u0019`\u0013kwp~\r>s\u001dzK?\"'f)X~vc\u0007N^F[4Eт&tl2!'*,4\u0012\u00062\"^\u000eq\u00176Q{\u0007rר\u0003_\b\\1a#\u0015\u001f\u0006b\u0013P\fG\u0019\u001ccᨆc2pӜ\u001c.E\u0012(>\u000f;F\u000fvf|¤n\u000b3a#<\u0003H#\u0017\u00028\f\n-F\"t<C},\\=;:\u0014':4:\u0004Sp\u0017WhϾ8ֲ\u0001m;Vʛjg\u0015?&xlx\\G\\t<QTSY\f^M\u001bӈT5M!m*Sպ|.GH;=_:\u001c\u0018)DZH\u0013\u001d>\u0005\u0015)\u0016rkKwմ\u0005Z)eZ\u0013TmjKU}*{lVEσ\u001aF]W=x\u001e2und\u0014y>уnOun5W&h{j3T힫q\u001eCU1Bc=U9^=\ty.RJxh\u0001\u0015~Km*\u000f\u001c*qt<O3~\u001d6\u0003+W<Xma`\u0014Z̕7/LZ/o\u001d*ozjwʽw|\u0006ԧP%>\u001aS>\u0013TgYB\u0015*ݨ|V\r{Sy\u001f+\b0w^\u0019s6|\u0017;:rT\u0013\n?Oj_J#5ߤb\u0001*ꛪa}sTw\u0006\u0014+?\\C\u0002o\u000650hv++2*3䞲B\u001c\u0006#\u0014u\r\fjv}L$7T\u001cA\u0001*\f2 (F\u0016\u0005588CB\u0006)7P9!_)\ft21RJq%\u0004ڕ\u001cP\nx\u001dwۜC\u001e^_\u0000\u0018\u0019\u0007\u001a\u001dIqD7\u0015\u0018g C\u0006\u001a\"\u0013\u0016De(#<[J\u0018Ԉ\nDNRRl٣\u0016Z\u0003w\u001a}L֘K\u000ep(щCp`<9k6d>\u0013\u0003FBr<\u001d̨~J2(-*F)QJ+):C\f׀r%j\u0004\"ǭٴ]&\u0014gzWq2\u001d}\u000e61\u0002dZ\u0006ʧ\u0016yo\":*1\u0012\u001dCБ\u0015T\u001bCd3F*\u0018'k\\T%\u0006b.TLje<XKb\u0012*:ᨢ\u0017::\u0010P+\u0002\u0018\u0005֣yé\u0005Ԡ\u001c\u001dE rf.S\u0016_%X\u0002el)!Aq\tɊfh-Plb\u0013)j\u001c@\u0011\u0006۶`?P-^;\u0014\u0006m\u000e&-¸z8Z\u00132>\u001f΁kJJ\u0017%<d(\u0016 -T1(E͊\u0014<'PXX\u0019R*4eBRW(8uR\u000f)0ং\u001c׉\u0004ˣ苌XCK\u0015:J78eS#vbbJwSt\"S\u0014\u0016\b\u0019v\u0000Eyaf]N\u0005E1j'\u000bKX\u0016uw=p\u0011D]Ph@\u0005\u0017\b\u0004<\u001a\u000f0vb\u000eM<9\u0013t$m8Jڤ\\\u001fʤa>QC<fK\u0004%䪳e:Y\u0016)޲Fq;\u0015kŌ}\u000b\u0007\u001eo#f}\u001eV,\u001f=r-\u001eMM켓BCI u\u001ajV\u0017kJVg@uJ\u001b4Ҳ\u0015BE*ddۡ(\u0011Ef\u000e|<ɔ\u001enǦǙ\u0011KTu6v w\u001akl2\u00128\\zfKIv\u00122\u0014\u0019X{b=\u0014m'}(ȔeWT$E:fX\bG\u001d-28\u000e)q\u0006|\nˢs\u0004ho]!l0\u0007=r-,Re\u0018\"\u0004w\bE9͊t&d\u0019]\u0015\u001ap(2dp\u0014➮`w\u0002\"?AIp]~/ON)78OZ5,E`\u0006l\"$\\Fy^3\u0001$2Od5T'FD\u0005zz(=, \u000f\u001bgB\u00065=\u0002:\u0018to9tq9so\\Y\u0019\u0004{\u0013\\\u001fW\u0016m\u0018!TWj\u0014e(\fU@!Crx9l^E^^ǛM\u0017C7\u0013\u00135\"k\u0016COMw%U-a\u001exԀg#+ޝ\u0012H&r\u000b\u0003Qex2\u000eDR*\u0016\u0000\u0011RR>|\u001e`jK0~a|\u001b|}Xzf\u001eX\u0016\u0007d/,`0oJfJ\u001a\u0006\u0002j\u0001_5\u0019\t\tTE\u0015\nWQ%+@3T.¤Vބ;@_Kڕ|VK\u0013H\t\u001aF7D`\u0006a\u001fLr_\u0003hvȣ<\u001aȣ<\u001ai\u001aF\u000eF6\u0006\u0016w\u0003h\fe\u001ds-*\u001c*\u000112eXI\u001b\u00033b3\u001a\u0000Is\u0001m2\u0007<h~\u0018~泙Ư<Zȣpk{SFS\u0015]͖5eģ*R\u0001o\u0011\\9MG-mRR\u001d3p\u0006|a\u001fkG \u0007A:@C|\u0010}G\u001bhcNp[E+\u0013J\u0007s\u00163bƖ\u000b\u00031<\u0002OWb\u001dz\u0010x\u001e\u001co>\u0017Q\"@z\u0019\u001ecn^NVN$)\u0016I&\u0004O/\\T\typײ\r~\f\u0019\u001ch\nx\rNw\f8\u000b^\u0007o7h\u0018\u0005\u000e:9ϚQL3x\u0019m\\\u0000\u0006|\u0005pZ+\u0007>V\u001e4\bX9\u0018np\f9\u0010\u000e\u0001\n\u0000\u0017%p\u0005\u0007b]\u000779E|F\u000ek.=tqߣp_\t\u0000~ \u0010\u0018@\u0014\u0004z! \u00158d\u000f\n%8\u0005b&qO\u001b,\t\u00157G;[\u0014s}F7}\u001d#8\u000f\u0000\u0001>oDX\u001d׏xo\u0001\u0004b\u0010E.!\u0002}F\u001e'W\\G\u001b8?#}\ny\r7{//\u0011\u0002x8xB/?xxd!]\u001fʥ?8\n\u0007J\u001eq\u0017q`2ϓ9cʚv鷈uXi<^^\u0005G\u001c~\u0004_['228}@-1/i\u0004 \u001az]@\"b#v9\u00171::f)d̲%8\f)=`\u0018A\u000e}`7x#\u0007vL*%\u001f\u0002x[f\u0012EA>Nlb=Ӊe2į~xVav];aA-\u001363ڧam\u0002Fnf:iyZ\u001c\u0016G\u00181cW6\u0014\u0018!~>gb\u0011\u0012E,C\r\u0014%F3QV\u001d\u001dX\u0005n\u00018ױ\u0004wl=>t\u000b3mIB6wh=X)p1\u0013b8\u0013{V\fe5YЕ(\u0002އq#%\u001fY/>\u0017`ݍ.F($\u000b\u0001p<\nG\n\f68\u001c\bjȣZӴ<\u0016G\u0005\tU\u0019\u0011J\\\t#J7á{6h^b{?v\u0012[!{8v\u0016\n!J$D\r@2\u001c\u0014-D\u001fʂ\t\u0014xP\u0017\u0012W`k\u0006,@9G\u001e\u0002\u001fY?[ԟ0G^m8rК.5~a\u0004_\u0002\\0A\f\u0002O:YT\tW\u000e*N.gd\rm$VM{Mn+r\u0005ޓ+\u0013}\u0007GXo|/\u001aDA]\u0016\u001aU\u0012\u001c9\u0001fy;kfT\u0010W5-hr,\u001alSNCݚ\u0014;d\\%\u0010X\fmh#aǕ\u0019~I\u0011ww\u001f\u0004[~\u001c\u00038\u0006:Z\u001aڲE7*HFyb\u0013=41\\\u0011\u0018\tT3f(8NYɲGNWfd2\"+\u001eY&YMj:.,/>R+цhk\u0002k\u0006nтҖ\u0015Q|k9T(ƛm,S/My2̣d3[n\u001a\\F\u0017)%fĬШ\u001a\u0019W#^wh\u001d\r\u00178ӂ\u0018%mhY\u000by>̠NSi\u0003\u0002\u0015kTF.\u0013+_l#\f0\f3\u0000ΰl\n(\u00110.D\u00044D\u0012wq;hc\u001b\u00189&\b٬i&VLlkXSi&=iZcܲUt\u001b\u001c\u001e=}kPqQE!\u0016\f0ԩ,+7lFSNx\u00191W\u0019UJ3nUK)rF\u00017r+%.^nrn-d\u001d<Ffx<BjB'e1Ri\nA7)\u0018\u001cM٦$eҔi\u001aQJ,SjK)~T\u000er%7+))%Dvi%X_J\"uww\u0017&|m\u000b#2,\u001cEfJ\u0016\rJQ`U9@a0\u001bf(՜\u00181YrX\n4R؉Jڨ\u000426f#k+;+˳[6\u0019\u0007~v#RGy\u001084R^s\u0013+6T)`9aJF+jS-Yv[\u0012\u0014\u001f_\u0007dK5^%o9IE'ȤeE%}$7èl\nl`\u0006|nK-<&Fehe\u0014kV\u001dh\u000f\u001exIqX\u0012&(6)G\"$WȜT$\u0006N;_T\u0004;pe\u0004Nrn{\u0000=N@`!cp\u0003\\1\u0019;Y\u000fdT\u001f9\u00150P,3^NR\u0014R(SXENVxZ\u0016(4}?!C\u0001\u0005g\t.ʐqw>߂\u0015Y?\u0019=N\u0016#_\u0015<&0ҧ\u0002zs+&OQ\u0019A\b1#R\u0011\u0019Vg&),3]Y\n*հI2dPp<\u0005(0C\u00019?(8/<39AM֪lTi&Sy?;pMgq$*r\u0003\u0014kPHnȐ\u0014\u0005P`~\u0002˿\u0006̖\u001fqHA\u0006\u0017>+#C\r*B\u000bܼg\u001b9G0\u0016s%\\*(EYX'bt\u0019\u0014T\u0014P\u0010%b\u0016\u000f_q\u0014q-OI\u0006,WWҍ1\t%gحNՠ:i\u0015V\u00194x\fi|U<}/!㤀A+\u000bР2|ˌ)h`yr\\\u000erY\bX\n0嘵rC\u0019ƠS\u0004W.jB\u0011豉\u00114\u000e/Ɩd%\u0019\u0016ӛ BM\n\u00100wE=\\\u001c.\u0004BD.\u0018\"\u0001c\u001c'1!Mdb6\u0001\u000e\u00131;-s8K\u0017pG`O+y\u001e\u001dɇK*a@ȡ3$\u0019x\f\u001a\\\f\u001f\\5\\t5\\@5\u0000\u0011д\u001a!`u+-M_M;\"88Lum6{\u0012&P\u001e\\\u0012\t\u0011U\f\u0005jbibh[6ҋP\u0000\u0005@/\u001aDG=l\u0014yC2D-\\X:`\n\u0007XX\u0000\u000bG}\f\u0019\u0004\u001735ã9\u001cp5\u0001XᲈXĢ.$ml||<[\\\nnm 5\u0016ʡ]ֱ\u0017@!H]/Y\u001d@\u000b\u0018&\nVxҏVx£\u0015%R\u000e\u0010Z\u001aq.\u0003|j&UL+q4+ZO\u0015X9HfF$|6K\u0019[\u0000\u0000w+(݋\r\u001d<\u000e\fd۹xvzю(8r965]@:r;z\u0007gAK2>A\u000fb\u0001{\u0005婋t}\fA\u001b=\u001c=\u001c=\u001buh\u000b$߽V3u\"o%9KɓFb\u0006vI\u00039V\u0000\u0011#=\u0018 u̐ǜc@E?e\u001cb(E\u001ba.^z\u0002\u001eCU>\u0004_Z>QA\\%!\u0019Կ_\u001ap\u001b\u001355AG\u0019y1~\t\u0004[/\t\u001eg\u0018?>q\u0011&8Ǣ%Yzq]9@\u000e\"g 57\u001b<Ǽ=f\u001d/΀w9Q|\u001fP5\u0017Xr*\u001e.S\r\u00128y\u0007P\u0010\u000b\u001c \u0017\u0001q\u000f\u001b\u001d-M\\׸p@E~\u001b\u001c_).:\u000bx\u0006~B>G\"QUmp\u0014\u000e\u0007A0ҷx̯5c=U\fK+<.$;\u000f?1?R>@k?eέ\u0004x\u0003\n^?\u001cni 5\u00053|5ezqA#_L\n^.{8\u000b3w𗿂8#=C=:n$2\u001ey\u001d?t,\u0003Y?8\u0006Vr\u0007\u0019\u0015E\u0004r\u0011?أ8\u0002\u001eG:rXD^]M2m\u0011\u0005~A\u000f馲.=\rݠ&救GZq\u0005+YȑLLV8\u0015DDRKX%_\"6cvv'iP6Դ\u001e\u0000l\u0000_\u0012+u:~G-\u0006rE.\u001b9\u001cϢB1į DW\u0012c\rĞ2 YNy:\f߰Z_j%yWx=19v-\u0018\u0017{E'{Cf$Il\u0017q1\tBjrԑdkL\u0015\u001f76`\u001b0`n&&`CbH\u0000'@B(\u0004H\u0013B[Fi.K@%Ye\t(mfi6AZN]5mӺ}m6MӦM۪}ؤjڥ4G.S\t=z?y99\u0019『w\u0010\u000bf\f8$7el\u001f{\u0015\u0013W\u000f('ߡܿ$xqÖ\u000e8\t1Ua\b#f<ߦg3q\u0000;\u0004cX5\u000e#Df\b\u000e\u0012=\u001d\tMSw)h5\u0015졅p$v1iL.x\n8K)gY\u0019BDi\u0015m`\f$\u000e]v>NK<\u0013n\u001b'2LY\u0006%u\t)t\u0005Y='e\u000e*\u0011\\v/<e'\u0004O7sKZꄧ\u000fK\u0006{lYs[Ȩv2oVRZ\f˥_^\u0003\u0017mOa\u001ch\u0006\u0006\u00134\r\u000frx܎\u0010\\\u0011jKmqj\u001b֦iE㏪9ႚ\u0012!\u001a\u0013\u000fՐ\u0000\u001e\u001dxږY>\u001fq~J\u0004\u0019\tM5+ɢmIښQ{rڒ˵9%M)aES\u001b՜\u001aUSj61m\"Z~D\u0019\u000bXR(j\r?R/1~\nb\u0005:m:r\"8\u0014+GS \u0006I\u001fږVQQU\u00066\u001a`(VB\u0011Z7֫޸Qu6Mݪ5Ri3\u000f)yNU\nV\u0003UX>T3\u0010S\u0000\u0005KH\u0010\u0010'bCط\u0013Eȓ&K\"L3TgU\\Z_5ZjUm(hک_Qgͪ,\u0005mUb{S\u001fg\u0015;>S#\u0012{Lo\u001c&\u0017\u0019Yg{\u0002\u0014\u001f\u0010(C$;I!Qk,ekͭ*[*m媰W^2GJ\u001d[SI39O\u0000QsWޜ\u0007w\u001e6\t%3\u001b3IcuKZ~\u000fvl\u000eF9{\u0014IW3SNʜ.*8'\"WH>\u0006\u0015涩 Gyv?<U<w+\\ޘr=1Ht\u001dދ̳[\u0005p\u00003h\u001d]HVr|\r!\u000f\u0003)*v[sg\u0006ETY+7\"w*\u0018PN(\"{m|+[֏e\u0000u\r\u000b̲'4Gx:q\u0013j\b2#%\t\u0015f(,O]y-,T._P9z9Z(iJƕUrT֒K_L_\\O\u001e\u0016g|\\\u001d\u0003e\u000f-#m'J֓#Ħ䗥)oR*)+{il34,kY\u0013营_}2Ú2V*Cʨ%G|GU9\u001581\u001axY:؁fT[s\u001dZO;$G [YY\u0001<Y\u0002>\u0003ʬQ5`\fQ\u0007\u000f)-[J&\u0019RVj0\u001b\u0012vƟ^D\u001fw;X҃][K\u0013>\t'\u0015\u0010dMSfI,\u0019kr@\fʨVz(PRB=J\n\u000f)1<GC\u001cF%-*.E8O#wr'\u0018EXw3ny\u001b~ijl\u0013\u000fq0:\u001bRި\u0016F\u001c()RH#k\u001f\u000f/\u0000- \u0012\t+`ތYtd\u000fwS<o/u(@||EܬŸ)Y)Q\u00124(%J!r$nb\u0017%Q\u000e\u0018\r\u0000M\u0014EPԂZiF56 c\fyx\u001b&\u0017F)F\u0011~o]̞/\u001ebe\u001e\u0013KLR|'\rm\tdI\u001d4\u000e\u001a^\u0007Ť :0\u001f')~M\u0002\u0006v[;~h^r\u0001c6;A>N0uR;\u0005HfbM\t~f/w\u001d\u000f_ዾ\u0002Kax\u001f\u001b\u0001\u0006\u001e\fe\u0002\u0015\"'q\u001c!a$\u001d\u0003|:\u000fx\u001eĞqbM\u0016G#\b\u0011a\u0004\u0010\u0018\u0017{i{sp\u0007 mx\fA\u000eY2\u001a`͐\u000f\u0014ѐb:\u000b\t}0q8k]\bA\u0002(nbL4n\"\u0013L\u0003\u0014vLa\u0014vL\"&i0bK4A<&\b\u0004\u001a?åC){1\u0014ǎJ\u0010\u0011w\fցJ\u00189\b\u0012>\u001fc\u001e;cܘɋ9.\u001c?7Fҳ\u0014B_H\u0004x|\n:;_ \u0006U:G\u000e\u0000;0\u0004\\|H\u0004\u0002v,bb\u001e,R\u0016(2\u000b$y\u001c{8G^~;?o\u0007سEi㗩\u0005W\u0003H*_%p\rp\f\u0006Ǎ' 67%X,\u0013e\n2X&8ҫ>_{\u0003Ŵna\"r܄\u0016*_\u0006a\u0007\u000b|n]\u001bM\u0016>gVc\u0005\u0011B~PW\nI\u0002ʊt9c/g\u0004gT\u0002W6\\ۏ_ݛ¸\u0000\u0007oo=^I/\u0006G\u0003\u0012\b!R\u00066\\{t\u001dƟ6%inmzK4IIKKEZ.\u0016E\u0002\\1AA\u0018\bȠ\u0000\u0015\u001d\u0003\u0018 ás)\u000e`e2q2&s\u0018ӝYiOs~/<\u0017Yz,GG\u0011>\u0012ۇ;\u0005h\n{mf5*c?,k\b\u001cs\u001c51#ꋚ\u000bb԰\u001a\u0007>\u0000\u001f\u0012_8?@}^Gnx7u6v̀/b@2\u0001\u0017(\u0005CA\u0018w6\u0006ڦq-gҿ\u0014u\u00137g8?R<7\u0007\u001f{\b{BGeER?.\u0017j\u0001K?\u0011wvT=\u000e:uч踂89,C%tz\u000bgz@\u0001\u0012\u0007{཮kz\r_\u001a\u0012>\u0004\u000e/߈M\u0019_p귪һܷtɜGG\u001f8qyqa6WqR6K\u0010\u0015'Hz\u001d0\u000fv]_p\u0007|ܟ>\u001bݛ,::)\u0005t\u001cGsc88#8\u0003Zܬ}d/\r_R@\u0011m\u001c!B\u0011\u0000#\u0001_y\u000b\\\u0003b3e'\u0007\"֯MzG<S\u001fq?_;Wh\u0011\u001e\n91\u001e%c\u0019يP9`-\t\u001bђoc\u0003-^,p9=R\tBN<Q?[92tdn=L<Aȑ]Xe\u0005\u001f\\h\u0019E\u0014\u0007x8z\u0014\u0012'mH2G>\u001cek=:\u001eB\u001at5J\u0013R=pt±nѽ(\\\u000eSݰt*\u0015O\u0017\u000f.r\u0003?\u001ab̘\u0003C\"f'\u0014Q~\u0007m\u0016\u000em\u0005IG<4\u0017\u0001v\u0003\u0015PAo ɠy#ynsmE\u000f\u0017\u0018\u0004o\n\u0016\u000e\u000b\u00028\u0014,\u0000O\u0013UB$P]\u0004*,Od_ 2\\G{\u0019?vX\u001a-\u0018\u0016s^tSsd+\u0003\\x\n)\u000fc\u0010:h\u0015_P\n~/\u000ek$\u0015?\u0013f\u0004O\u0018\u0011yF\u0003>Oqm\u0003rѺ\u001c!.s\u0013Sc\u0012\u0019>;\\䱧\"\u001ap\u0005᪇\u0011pMd\u0019ptvZf^\u0006\u001fw@d\u0000G\\ȝ\u0000\n-a4uAL&\u001bcjHָA9ʂ͞*\u001c\u0013P}LHuª\u001d4Z5\u0013\u00149\u001a\u0015_'\u000e`K0\\RE-U$F\u0006p+mw\u001a_ղqlI&&cqjHNQ8:Cj\u0013U`b\u0013+4$JUI\n$5ȗ4VH%o\u0012UqOxBwU`BSDE\u0000O\u0003ƮG\u0000m%\u001e#P\u00071i\u001f(bPɨ!F\u0002t94y4T*Rjܤbs\n\u001d*HW5r[)\\\u0013ʱ\\z\u001bD\u000b$#F\u000f\u0010#\u001fϯw\u0017泥8!7#\u0018\u0011kȍߚ\nY\u0016J-\u0019*RBK\nUX):Jn[rm3/T}Rc\u0017xGi3-»\u0004[\u00181nŌsJnFS'\u0019R*\u001bU`cO۞<{r\u001d%r9|I\u000b);AY㕙>MNgҝ+*{^2^5Ml\u0011\u001e\u0018k\u0019\u0007H=Sl-~@\fF\u0018y24+iSө̌\\P\n93*=+4L={l]< K7#L_O̔\u0000zvx75RxeXՅ|v\u001b\u0006ꤖz\rP#6(e3Ǣ49\\#L*Yek.{LddHO*sLIs#>|o\r#c\u0019`\u0001;3\tmcHrSCn|Ĥ* Y|vY<TO\u0005>\nke,K)EmJ.+x\fU\\Q\u0016y\u001d|;rȻ\u0001\u000b\u0000chiCG3#\bt2\u00147^RL%VJe,u) %\rVRYH\t2*ۡX\u0012xK^n\"/\u001b˴2K-pg]9\u0000]m\t\u000bjF_\u0018-CF2֓\u0007b$&@>*-JLx_b}^\rSH~gC\u0000\u001ac\u0005c\u0003\f~cUE\u0003p>4q*=\u0001Ns\u0013\u001faXFh\u0010\u0013\u000711+)`b\u001c\u001eA\u000e M\u001ch\u0014P\u000ei`\u0001\u00180MA\fC?Vj)x6{Lz\u0002\u0006ӐأVBV7q\u00127\u000b\u0010$K%l\u0005\\xa\u000e0\u001c\u0014t\u001f\\x\u001e\f\rǸcBHuhcC\u000e걓zCON0y\u0016y@0\u0011\"dF\\1R\u001d\u001ckRivHM\u001cdM4p\u0013ġӄ&45GoL\u0003Lk.Khhh\u000bk\\ni)![\r9<tѓh\u0019242\u0001<ù\u0017.\u0002ˍ(\u0018ϐ\bD\u000e\rQA\u0015`\u0013\t1X\u0015<i1QH̡\u001d3&ĤifvjbN1I4c:Iu-lgZ'<.y}{\u001f\u0014C<Vrc`k*c\u001f.rɗ\u0012rQL.i&ԣ\u0018M\u0014\u0013<H\u0007\"\f\\ٜK\u001c|bӣpoA2Mk:\u001cf[|v\u00171TR&N\u001bۉ$_\f.CXL.\u0016qW3\bU1\u0004UJtQI.*9<ԣ\u0002VT\u0000\u0016]\u0013`\u001e0c\u00160͗1\u0006#Z\u0001\u001a\t2hB xD*xX\u0019\u00009S=q,'ı8I\u001dM\\rjG-\u0002e3Z$s\tF!a\rV_s3u@5\u0014\u00007S\u0003wvd\u0004p)\f\u001b\r8\u001aF#[#g\u0011]4r\u001a8\r$7\tajaT0կ\u001a\u0011&(\u0014/\\\u0006$^\u001d\b?h\u0013AF>\u0018<\u0000h#\u0017;\u0011?;:\u0010 6\b\u001e+X\u0012y#tp\u000e\u000b\u001130hs1\u0018\f; 9t\u0013G7&4nrхU]Gy,AU\u0015Epܳ:^J<\u0004a<2h6\u0018\u0000ƺ\t\u001bg\u0001G\u001fI\u0000'M/uE\u001b賏FG.\u0010Y\u001f\u001b\u001e'ṿ;\r1pa0p\u0019\u0007{\u0002\u0013Lߐ\t{%W\u0003@\u0018Ca\u001f!\u0015\u0016WқO\u001c\fc\u0003\f*\u0003\u0001r1@\u0007\u0000\u000f_R\u0019qpf\u0017\u001eLtLRl`ut\u001c^\u0000o\u0001$6hVӐq\r-8.sfp>rFqخR+_W.0Y\u000e\u0018\rāt0Rοgjs;\u0006\u001b\u001apH}A#\u001cGGs\"^@ a\bG>|Tp\u001c\u001f!X4T\f|pƲ~\u0001kg88K8\u0011G\u000f\u0003<\u001eN]<E\u0005D4\u0000(y}YZY;b6\u0000\u0013\u000eԮO\u0011}<\n\u000en-qSM8z\u001d\u0017{Sx8Nk\u001b{M)(3H4z\u0017~=1p\b\u001c\bp;T_+}Xኁ'\t,\u0004?u\u0006\n\u0014q@>zS'u/\r>z:=E\u0013;\u001d\u001cN*ңn<7U#`\u000b:.\u001d_O\u0003Rܠԍp\u001b\u000e/h=k!\u001fG!^7Y\u0010Jgz\\h\u0001Dt*bn\u0015\u0016\f6\u0001^\f489x,؋\u0005h2\u0000G\u001a\u001eM>:p6N\u001cv4\u0015\u0012#ԥY\rE\u001bf\u0012UR0we\u0000\u000bm\u0017\u0003Xu8#\u0014\u000b\u0007teD\u0002\u001ct\b2!Ue\u0005/Z\"\\B.j(f\u0011\u001amV]\u0015O{\u000b\u001ejȭ\u00027\\~t\u0012 \\χc\u0002\u001c9\u0019)\b2xY\u0016ŮC-Z@泳R\u001a\\\t,F}\b9(48ĵ5xW:EiU\u001d5YJϨ.&j$\nn\u00141\rBxS\u000f\u0015(f\u0013YjC(i>'{o\u0010g\u0018G;k}+l$\u0016n9C5\u0019rxxK\u0006<sG\u0015Ή\u000f\u0012x*j\u0019]r~\"}nw\u000eUL%o\u0002 Nq\u001eO*c\u001c}e;W&YC%/\u0019\u001eP8ffc_1)\u001e\u0014\tk.\\p\u0000ṕg\u0001t\u0016\u0014SO\u0011Y:\u0007\u001bo\u0010'\u0019`Q:9\u0000-x\u0006w3ӐQz\u001f\u0012\u0001\u0005>;\\p%'/\\p\rk4\\\u00135hr\u0014#{#PN.\n\u001eidgq\u0001ed\b\u0005Y\u0019\u00181@3zMaL$?\u001cr2\u001c\u0002C&X5>ȡ1A.\u0007%jTPF\u0006giD\b\r\u000f\u0019a!w+'tC\u0019V:7)5C)O(\f\u00171|!OwDt\u001c.Xm)1\u000fPANO!ǁ紆*dT^U\u0006r\f.eGx\u0015\u001cGRZ\u0004ySbdS<J07*\u001e/)|Q1{Z|z\u0012x\u000e-k~\u0005k\u0018\u0005\u0019撧f2\u0019KmFi1)\u001cTs8%dɐ2\\\t\u0016(Z(L%rF5(.춗e]\u0004_[\u0007}vƭIm\u00173\u0006\u0011l4\u001dLb\f\f\tR ͢(b%e*֖\u0018[\u0014m%TvGlFòD(S\u0005/t\u0004N𳛱A\u001d\u001a486S\u000442dS\u0014wF8r:\u001cv\u0011,3\u0013木\u0016\u0012Hf\u001a\\\u0015RW~\u0019M>d{<\r=ZQ\u00151]!2Y\u001fQ,jLN\\\u0011r,rN\u0004i\r9~LSeLȄ*\u0019\u0012W*,qB=\u0007\u00149 \u001b\nN\u0002UHO]pwL,\u0002Xߕ|VLl)f\u001c9#'\u0019CNPEyLxl2{2yeLJUD0\u0019(<eBSf+ĻPA^\f\u0017\u00162z\u00196$;݊%k\u0000K\u0019=+\u001eNǦ\u0002\u001cG,h6\u0013GN\u001c١\u001b\u0015f\u000fu\u0002u}\u0001-m\u000br\u001c-h\u000b\u0014Q`\u001cr*1n \u0002\"ʘTTW\u00001h\u0013\u001d\u0019۹-sn1NM\u0017O̘ۗ{sEH\u001b\\\u0014\u0014Gʐi(\rP,\u0002;Ve\fYb\u0000/9\u000bo\rC?\u0016\u0007p6YMw̕8Gm7;bkR'џ~zIѩY\u0019ii\u0002?Ҿ;R\u001b)K\u0019Zf̰ef2ݧ\u0012Qj\u0019(5OY6l[_s\u0002A^\u001a-//}>-U3Ui0v|:ɮL1v\nͥB\u0011+t\u0015r)\u0015D]᥊y\b\u0016\nݸ~0)\\*ָɽû{Xfmհ2\u0015V|ߵ=růĔTMT۩\u0015jEZ\u001e\u0001\u0002Wj\u0017^\u0005vqq\u0016*B˄ΆKZ[µo5c[_U`8,G bK^2ٓ:\u0013hh5i|1/j\u0015Z\u0005V<jiV\u0000kPV\u0017billZsBcCMk\u001cU;.\u0013nXGj>XA>ך_,N7Ѧ\u0012\r_\\\u0017[=_iu`xD@yy\u0006_2%ʹx\u001d>r؏{Թr`jf>+Te$9\r`c\u000fU:\fI\f\u0005~%\u001dٱ/\u001a袁/\u001a\u0014\u0006h\u0010\f_\u0005s)qql\u001a\u001b\u0000K3[j\u000b\u0006ML_>\u000f7\\\u0001;ֲc4QkTT((kx[\u0012w\nሕ\u0015\u001fKk4U@{.J1P╢\u001d4\fŗqE\u0012`\u0000ƎUn\\\u0016ɼEi]l'$\u001a{.y\u0007ǵ\u001a1Ja\u001b\u000e}\f\u000b!Ϛ\b:mfG3m4I3]4E3\u00015q^\u0017\u001e'$;i츎[u\rr@\n1T\u001a<ȸѹm\t\u000e\u000fa-\u0007߉MKvǀz(j-|BL9\u0011~3\u0016\u001bp.Q3\rxԭGn߶d\u0001N;|ܛ}6\u0007'Ѷ$3'qR<%&4S|qJ~DzR>ދx/9\u0019f |ʸ'yj=\t\u000bk\u0018âٱ\f]0!,\u001dڣp\u0006~ӳq0rN<\u0017Qٗc;ޥ\u000e`|\u0005<\\^\\e>PF<\u0001?\u0004W\u001fOcq|\u0016x\u001diorM\u0006_a{\tu|\t\u0003=&R\u001aK忚6W$dv}*1?X߶i{#_\u0017\u0018\\Y3Nmc}\u0004\r6\u0007>|d)];__\u001d/\u00059Գ\n3%OlOI'\t<!=19Gc&}/\u0005\u001b>\u00053d,mB=E;b\u0004\u0017W8{;\n,g_^U*Ilt\u0015Btl\u000f\u0012\tx\u001f\u001a(\r$\u0005/\u0010g\u001b :{'iv\u0012\u00136\u0007l`\u001egv;8hûC\u0015QO)\u0007͠s'I=.\f\\x\u001e\u001e)\u00159\u0017)#+\u001byJ\u001c9ۉxs'5ۆ\rTx>)3tSI/\u000bWB)t~-\u0006vk~ƻFvNZ\u001fMsEp]z>Dk;\u001addI8,y\u0007b\u001ci|\u001cEN\u001c\u0012bWVf{crVրc\u0005o5(Xe1\u0015/\u0006\u0017sSG\tj+GYv\u0014ꎣ7b\u001c%8pTȊ*J3\u0015L<s,rXy<3/.:jMo&\u000b8c$|(KUV\u0018\u000eu#%n4\u0012xzȂ8\u0006(\u0015e\u0014Y\u0012OL\u001a\u0018fd'gt*jmL\u0013c*Ro\t];\n7i]ƖqQ,.n/\u000fWO<}\fS2c\u001a;:q&yb\"\u000b'D5}Vd%Վ=c(BU\u0004rբ\u001fΞ\rF5T\u001f2\u0013g{̞\u0007@%\fW9*\\p5'\"\u001b-e\u0014]\u001awHe\u001f\u001eϡ5N\u001f\u0015kZ>JYٲ_\u0016h9\u0019\nuk<q쨔+c\u0018v0\f\u0018j\u001dk*z/jWPY2\u0006@\u00158~\u0004R53~ަ\u001e\u001cn0\u0002^i5Ə%F9F\u0019|2fƥeƙW\u0017~5\u0015U\u0019b\u0010\u0015S\u0000'RYo9Z\u0019Rm\u000bUN\u0014u\u0013oֺ\u0007{={V\r1I=L3N9)1k\u0018\u0013%\u0018ҩ \u0006\u0014Q2$(\"t\u001e\u001fӦGQ(L_\u0019=7E(8\u0012\u0019#/|$2ގD#Uyluj6\u0019EWmlqb}\u001a'6t2\"s\f\u001a\u0003DD\u0011E]zG.QuX::zdVEAfmg]\u0016yY#1rHd\u0016|8\u0018Z\u000f\u001d#_y)NRlF0)NEQnf΍yQ3F^HF;9rr\"L.Ñ8\u0019#-*|ָ\u001dߍVkZ;'\u0018}^k\\ʖ9\u0017[C\u0013\u0012k()\u0011=;EaAz%pFnI\u0014Aq2Id\"AB\u0006(\u00047Q\\ \u0018\u0012!\tb)D\u00101\u0004Q5\u000bmQ㫚ؾUZE\u001eJ\u0011I'\u0006n[z^k{9{w)ʢc\ra\u0017eZ\b2R[Xh\ts\u0014q\u0012$z\u0007}&fD\u001eUY\u001f\u0016È\u001a[SF8\u00000\u0015*\b\\L8\u0011V[F8\bk'OaUOX\r\u0012\u0016us3qahua\bqu1vteu92_<\u0013;}G2\u000e\rKB# &`Tq&\u0004I%Yw4\u0013v6NX9\n\u000b7gaV^ha,\u0007\u0001ӽ)C\"G\u0002`CAN\fyb*c4Z̲IhWGV\r\u0001L\u0012gMb\u0002gXޅ8\u001c|DI\u001f\u001bQNh<)\u001aO\u0013z\u0001\u0017D\u0006DF(73@t\u0002iiNi63OLf1;\u0015C\u0004uIمQ|\u0018{\u001db\t\u0002\u0013_?Zj\u0017`&ޱ\u0016\u001a.v?.\u0010_Ə\u000b\u000f\u0002\u0011\u001fς(38яWҗ\u0017\u0017>Tz.?.7i<\u001d\b%oD,!`R8\u0019\\\u0003)\b`. .j\u0010ȥ\u001aH\u0001\u0007B@H\u001c\b\u0002\u00011%\u0019폎@\u0019T\u0002\u0014\u001e\u0001Xb/&\u0010f:\u000e.cK4#1wsb=8|\u0003LfҖ\u000f\u0017\u0010xxCCxt\t$2N(mt\f5\u0019&j0T?\u0012Cp\u0018\u000fmG2\u000eaE\u001eh\u001c\u001a\u00199\u0010K(U\u0001\u0013/0q&\u0016{\u0006\u0017\u0004@Ak\u0000\u0016\u001eX\u0003\u000b=\t=Y&zfͺ\fu\u0018Э>H\u000eV\u0018^iPfPwމЋ\u0012\u0003\u0012\u0006lxH9,4ٲ5f`\f,x\b808\u0011!qM٠)]I\u0013\fl\u0018\u001a\"\u00021\u001a0B\u001c\u0000TI##P$Ccba܍\u00022Sc5#&\u0018F&\u0013G;Τ-gҖ\u001a\u0004H#D\r>[3F5b(\u000bA\u0005b${\u0007\u001fizз9&\u0000l^}p\"F;b2\u0007\u001f!{asE\u0017\nD&x#8j$\u000e,byb!p,dLY\u0013\u0019]ّ!1CHlp\u001d\u0018\\q\u0010\u001c .U%NLH-Rdch\n\u0007^@D\b3Hv\u0001gxq|Dp*жhcH\u0000u}\u001a\u00156\u0006\u001d\u000e7jʌ\n?R#3I3< P\u001bS,\u0012>\u0007 \u001a؞\u0016Eq\u0003\\=-\u0014R'\u00146;9IAzɆ\u001bٜI6|\u0016XdA,@\u0002\u0013W\u0001־+\u0012Y?[ړC\u0006\u000biBF-\u001b(ӊ\t-A[(\u001coq@\u0000j\t\u0015ȡ^s8\u001cj$\u0007,\u0016AE$h\u0011\u0005~?Xhڊ\u0013>\u0015ǁ-\u0019a0|!St+R)5D@*\u0018z\u0005mahCF\u0011nlV7qm\u0006͐p\u0013nyQњ+\u0001{\u0006\u0017O#Ok\tR>5y\u0018]Nbs0\f;P^84~EJc\u001di<rg.\t8`\u0013r\u0014E\tKk\u001bےv\u001dh]\\˹{W*U\u0003\u0005\u0005ר\u000bnz\u001b6j4YZl۾CTtLq]&tѳwb\fM\u001d6bT1cǍ0qR)SeY\u001fΞ3oE9|eXzڿ|Mlb]|?pБrO<u曳ߞ\u000f?^Ͽ\\n߹\u000f{gy\u00051\u0019[ɔKL,Yɴ+ȼ+<@^Cdud\rH̿\u0005\u0000DH\u0004I\b:A\u0004D\u00170$I\u001c%\u0010Abb$XdH02%\u001a1M\u0004d.,|$1Y\u000e($*\u0001\u0006V\tNRBObs\u0018pKtNKx\u0003\u000b\u0012 tEBtCbt\u0017\u001eH~0=/HNL.\\}y\f\n\u0017\u0000).doFX^Kh4ff\u0016``i%Q\u0000JفDi\u0007\u0007G:\u0001\u000b\u0014\"\u0002$`\u0002(\u0002,\u0012B`\f\\z\rB`%,%*)6kB^I\u0007\fJ\u00196j\u0013L\u0017,xrEVˆXk\t\u001a8QH\n$Y&y(ꕫ$uҽyܽ{\u000f!y?zߟUQE\u0015UTQE\u0015UTQE\u0015UTQ!\u000f`y\r\u000ebQE\u0015Uonb}SV\\+e:<=co\u0006*\u0015oWgֈ\t\u0011WG&;D&\u001dN8:<͂[ߝ9qtO\t\u001d*Ʈ*Gr~\\13Ǧ̏.\u0018\u0012K?ja`[ᖰ=7%\u0010¶\n\u0013\u000estP\"M8<[^\bR6+;\u001ck\rk\u001dkeU\t\t\u0013lYj9eKsb\"<.RE?<wx\u0001\u0005cce0e;\u0010Q_\u001a/jn+;P|VlLu`]\u000e:\u0015kfp\u0010]\u001dV\u0018\"C]Cb\fwÊ\u001cQr[+ ,|jw:e\u001bUn3c+:\u0014\u0014|a톣<5aUE\"WvMqФ>l)\u0006%dtU\u001b[PY\u000e#WqrF\u0007tGz]\u0015\u0003(9dj_8`]భK\u0016J7HKwsؗ1TT\u001a..\u000f(rۮѵ}\u001c4f>z{ϟࣵLAϻsƌzfzkfL(ք\bC\f~h?\u0011j}CJ3\u0017E\u001a%/c_TVJ\u000e*pT_xE\u001fy\\\u001a\u0007_^Hڨ;Wi\u0012\u0016\u0015\rY\u0007A\"ҭ[l!Iv^يR9$Vd2nqy>=/<y;s+\u0001N\u0001w\t\u0010$\u000bӟmWy0\u0018\\*c<0gלuN@B!\u001a\r+\u001dG[Yu?R\u001c|^\u0014rrH/\u001e坑\u001b,\u0017~$\u001bK]Kn`l=Z5[7q|gUnr\u001b\"~\u0003F8ߛ-cY\u0017\u0011\fđ\\ೖ-\u0005K1Es\u0007\u0000)\u0005`\u000e[<pb !zٔz{t@E^~˷J\u0001e}yU\u0018-#iږykp?0Z/\u0003j,bh\u0017}\u0017Fu\u0019\u0014DR%\u0006H2\u0000\u000b\u001f\u0000v\u0000&\u0000\u0000e\u0001\u0004u\u0001\u0017\tY\u0002N\u0000N\"\u0005{B^{~ݾV\u000b>>zyH]PF\u0012(볫ܤ;\u001fdqFV\tLk\u000e-zPߔJK{wWy~P'C8d,ߴ.\u0005\u001e\f:J\u0010@7\rdzqF\u0005@\u0001`\u000b\u001b\bV\"\u0011\u0011\r\u00006\u001fX\u0003 \u0000#\u0001\u0019#\u0005\f\u001f\b\tZeW\u0000\u001fŔԃN~a~qf\u001au#E\".lй\u001by.?\u001fXϊ\u000b;m\u0004\rHK=`(tu4G!gn\u0004\u0000_\u0005:\u0000^!\u0018B\u0013@\u0000z\u0002hCL\u0000Z8l\u0004$\u0007@\u000e\n+\u0000<je\u00002\u0010<QQSS}?\u00124iǀ(;jv,_X?j_Xr)zXK=AT\u0010h\u001b\u00160B~[)ܦb\u001fUq\u001b OՆ\u000bF\u0004v\u001dS\b@g\b6_8\u000f\u00021\u0000\u000e\b> \f@\fe\u0000\u0010!\u000f\u0000O\u0004\u0000\u0010\u0014Ax\rC8~ⷎNs]=\u0016/I֣3ѡM*{q6l\u000ejK\u0007~!}\u001e9Ym!!_\u0003\u001d7\u0013Hlް(\u0004Qp\u0005pj\u0006`\u0011\u001a\b\u00010G\u0018X\u0004s\u0001,D\u0000`+\u0000\u0018\u001d/x\u0019\u0001\u0010G\u0000F\u001c@\u0000ҚSШ\n\u001fs=\u0004t\u0014#\u0010#U\u001aRuMT\u0006?|zq+[:\u0014s\u000eM\u0016nִ\u0010䂹33o\\P7\u0016\u0001.\u0007B \u0001<L\u0010\f\u00070\n\u0019\u0000w\u0004z\u0000B\u0011F12\n\u0019Ȇ \u0019D\u0004G\u0015r\u000f\f<6\u0003\u0010\u0000X`3\n\u0011\u001483|\u0012\u00016\f~!]{\u000f\u0019=i5$>*OEtO1o,N4GO\\ٞ~pc݌\u001d)G\u0006\u0006R0X\u0003\u001d\u0018\u0002\u001eQAl\u0006(\bf4\u0005\u0007\u0018 M\u0014<A\u0010\u0004oc0\u0002\u000f\u0000n\b\u0001`\u0000\"\u0003\u0010\u00020E\u000f>)h@<\u0003׹\u0017L\u001c\"]NJ\u001fY\u0017s\u000e\u001er,'%hݹv\n\u001f \u001b݆/U\u0011)\u001d|\u001fJn\u000f\u0005\u0019PW\u0014\nx \u0014kFE\u0006Q`0|=\u0011t\u0005[\r1x}\u0010\u0000\u001cf\u0004p\bc\u00103\u0010\u0002\u0007A&\u0000\u0015ŽpJ \u0011\u0001~\f\u00017%1\u001c,۰PRND,^\u000fHU\u0016\u001d0uf\u0013>\u001d7웻ñ]zQZVq6\f\u0004S\r\u0003\u0014d`\u0000\u0005\u00190X\u0015A#GVJ[\u001f\u0006(9\nR\u0011\u001cWvH\u0000o\u0005\u0001^0\u0011x\u00033\u0002\f\u0000bx\u0013\np`\u0014+gQ\u0003(^\u00011ױ\u0010>9ږ騬*^x#q\u0007b ,Y2aHwcVMOb/f=-\u0012ȁ/}\t-\u0005\f`=\u0004瀾\u001a}\u0006k\u0010\u001f)\u0006\n\u00194\u0003\u0014`\u0002\u0005\"\u000bC\u0000!)p3\u0000:\u0000m\u0011\u0000u@X\u0000oQv \u001fngn3\u0001\u001c\u001bw\u001d:s+\u001e*qBV-\u000bM$Nr\u001feO{\u0007}\u0000v R`\r\u000283J\u0016\u0007yM\u0019O4\u0006)X\u0000ZG\u0019\u0013\u0005y\bQj\u0010{\u0004\u0005<ET\u0000I\u001av\\5\u0014Y\u00008F\u0001\u0010a\u0015\u0001\b\u001ej5\u000bX+~6\u0013\u000eyBUXDCj*+j߯\u001dX9qx;aV,;\u001b\u0010`g\\LZ[ \b6\u000bz\u0014xGP\u0010\bk0\fܢ@\u0006\u0005+\u00188MA\\\u0013\u0004\u0014Z T\u000f\u0016\bg\u0002P\u0000⚖\u0014\u0018 (U \u0010Ͼ?4\r\u0006;Ic@\u0010S\u0005\u0015l|QgVe\u0017\u0013OH\\GIs}-:\u001b\u0019l޸-\u0012P\r4T/\u000e數H\b\u000e1e\u001d\u0019N\u00171@\n\u0019\u001b^\u0006Sp\u0018\u0015|v\b:Q  h\t Z\u0007\u00051\nVK\u0001Ș\u00001>DM\r{_π\u0018Y\u000b̸Ӻ|)weUefᨈ.A]]\u0014dciI~\\w\u0013<\u001c8\u0010/\u0003t\fP\u0006\u0005g+\u0000e\r>*7E`S#\u0005 \f\u0001\u00153\u0010\\G\u0001H\u0002p\u0005χH\u0000n\raKS[\u0014\u0004K\r5uk;mɶc\u0018Vރ\tiE\u000fHD_+߾U\\'9GVXJ¬\u0002\u00179M<~̨\u0007փ\u0000I+q\u0004\u0010\bĳ\u0016L9%\u0019A\u001f\u001d\u0003\u00140pcF\b\"((\u0018`\u0005\u00057\u00027\u0000Q\u0001\u0003#'\u0000q h[:-H,n#\b*Z_YXO\n=Vy!p\u0017\u001eLYzY*K;x2}{\"w7e\u001fr\u001c\"Iw:\u000e\u0017GS\u001cy\\V[<6'Rչ\u001e\u0016n\u0018%:溬'5mDtbZ\u0018L\\&$\nܾ~v\u000fן{}߻<%E\b&gIN\u001d\u001b\u0016\u0006DHJ\u001c\"NƄdD]\tQ!c\u0002@\n\u0011d\t*>7\r\u00158P\u0007W%\u001c\u0003\r \\ h`3\u0006^l:93\u001cc<xWo67!\u0010ʺ\b[ЈZI\u00104z{z?cvTgC\t|ޮX.qDh\u000f\\1yX\u0011\u0003C>M|;\u0000egA :܂\u00178X\u0010J[\u0010\u001a7X\u0010I\u0013|0|N7\u001ew[{Ekv\bcJȬi%J-Q#u|FBѵ<~ԠVTw\u001f<kFK};#9\u0011a\u001bX!ЭѨP5w8Gĥeb\u00125\u0012@\u0016\u0015\nݡP\n`(dB\u001eG $8\u0010\u0002&{j?\u0011S\u000f\u001ep䴥\u0019W5z\u001bNK\u00036\u001dVi\u001f|Q\u0015\u0015Ah\u0004\u000b4ݪ(d\u0017*isZdD(k}P`\u0000͏Gg墂t5RLTc\u0007+ʻ#\f\u000e!\u0007\u0004\u0007 \f1Me\u001f\u0004+ƅ\u001ex\u0005oBj0ǻ8OUN\u0016\u0015\u0016☤\"ţ>\u0012|_JvV{J,͓\u0014ɯ)l/`\rR|Vxfm\u000b96p\u0003L1c3Y0ߜ,\u0014/\u000eNP[@Qt+eKTe9ۏ-p\n\u001cȮ|Bp\u0013W\u0005\u001f$\r%\u000eIHO޿y:~0?_(\u0011gD,rE}K\u0007\u0010\u001ccШ+)\u0014J_*=I,?!\u001e4\u001el=Å[Pծ=\u0004Ğ\t[\u0001\u0011 }g\fOZ\u0018O$o!xL=5dbBC\u0007)\t\tOմ>RIr\\r\"#;@V2[kc\u0005l\u000fzi5a\u0001#*Xm?;62.#\u000f:ĉ\u0012\u0005֙Li\u0007\u0017\u0006\u001f_\u0005\u0018\u00008L+\rendstream\rendobj\r28 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r29 0 obj\r<</BBox[122.199 203.172 167.587 188.178]/Group 36 0 R/Length 128/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 12 0 R>>/ExtGState<</GS0 13 0 R>>/Font<</TT0 5 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n/CS0 cs 0 0 0 0  scn\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0  Ts 100  Tz 0 Tr 14 0 0 14 122.1992 191.1738 Tm\n[(Cuf)18(fdif)18(f)]TJ\nET\n\rendstream\rendobj\r36 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r26 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r27 0 obj\r<</BBox[112.179 343.154 177.391 328.16]/Group 37 0 R/Length 129/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 12 0 R>>/ExtGState<</GS0 13 0 R>>/Font<</TT0 5 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n/CS0 cs 0 0 0 0  scn\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0  Ts 100  Tz 0 Tr 14 0 0 14 112.1787 331.1562 Tm\n[(Cuf)18(fmer)28(ge)]TJ\nET\n\rendstream\rendobj\r37 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r24 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r25 0 obj\r<</BBox[118.178 439.934 172.373 424.939]/Group 38 0 R/Length 125/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 12 0 R>>/ExtGState<</GS0 13 0 R>>/Font<</TT0 5 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n/CS0 cs 0 0 0 0  scn\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0  Ts 100  Tz 0 Tr 14 0 0 14 118.1782 427.9355 Tm\n[(Cuf)18(flinks)]TJ\nET\n\rendstream\rendobj\r38 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r22 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r23 0 obj\r<</BBox[120.977 515.788 165.831 500.794]/Group 39 0 R/Length 121/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 12 0 R>>/ExtGState<</GS0 13 0 R>>/Font<</TT0 5 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n/CS0 cs 0 0 0 0  scn\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0  Ts 100  Tz 0 Tr 14 0 0 14 120.9761 503.79 Tm\n[(T)111(opHat)]TJ\nET\n\rendstream\rendobj\r39 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r7 0 obj\r<</Intent 40 0 R/Name(Layer 1)/Type/OCG/Usage 41 0 R>>\rendobj\r40 0 obj\r[/View/Design]\rendobj\r41 0 obj\r<</CreatorInfo<</Creator(Adobe Illustrator 14.0)/Subtype/Artwork>>>>\rendobj\r6 0 obj\r<</BaseFont/TRJGSG+HelveticaNeue-Bold/Encoding/WinAnsiEncoding/FirstChar 32/FontDescriptor 42 0 R/LastChar 116/Subtype/TrueType/Type/Font/Widths[278 0 0 0 0 0 0 0 0 0 0 0 0 407 0 0 0 556 556 556 556 556 556 0 556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 649 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 574 0 0 0 0 0 0 0 0 0 0 611 0 0 537 352]>>\rendobj\r42 0 obj\r<</Ascent 1141/CapHeight 714/Descent -481/Flags 32/FontBBox[-1018 -481 1437 1141]/FontFamily(Helvetica 55 Roman)/FontFile2 43 0 R/FontName/TRJGSG+HelveticaNeue-Bold/FontStretch/Normal/FontWeight 700/ItalicAngle 0/StemV 144/Type/FontDescriptor/XHeight 517>>\rendobj\r43 0 obj\r<</Filter/FlateDecode/Length 11145/Length1 28040>>stream\r\nH\tPTG\u001aǿ\u001d\"Ȣ^-7fn6Vd\u0005\t^\u0011\u0004]oĬת1V<0A\u0018\u0015x\"\f:xrl3\u0012Teu\u0007\b\u0000`\u001a0\fx͗)\"ׄ\u0012S\u0016]\u0001`\u000f\u0000߇\tigB\u0000~m|a)Ó^To\u000f\u0005Z\r\u001f=af,\u0000AŢߌH5(q\u0001Mw\u001a!\u0002\rJO\u0011~\u0011I=$\u0015\u0000fxH|\u0001 dNJOOi0O*\u0006H+1I\u001b3\u000f -\u0000)R=XI)&8\u0011BW\u0001a\u0001\u0003Yا\u000fZ?B%\u0000Ŝ\u000fH<\u0003`B>@@\u000e\u0018`\"DBW΅PHo\u0013\u000bS$\u0011i j\"k\nN\fp\u0019\u0015n혃{0^02\u0003u4\u0013J4Nh>-e%5\u001c<y<Oy\u0005o-\u000f|G\u001a\"%I\u0013ritH:!JW\n\u0019`^\u0001\u0001U\u001aj>\u0016Eh6X\u001bhDv::\u000fj\u0013SkX7~ }>Yߥӏ\u000bz~C?ҟza1\u0012dcXal5\u0019\u001eS1}Ff\u0019fF6֌6cf\u001f-9\u001cbN5gȦڂlm\u00116M[-\u0016l\u0007CȮ#GE&E&~\u001e5,jtTZtXP\u001d@G,TI\rM\u001eH:&\u0019^\u000b\u000b\\kq3nlA\u0007<ױ):S7MQLAs(S_᥿6VNT3\u0005E 3\tR)-KYqA'\u0001Y/}\u001fj\u0016z\u001fЎX::ۺʺZb}\u001e\u001b:Cin{~Z_\u000b\u0007z^01F\u0019)FXonPG?lb\u001afK[gk\u000e6\fA_\u000bM\u000f=\u001e㢆Gf\u000epX\u001c\u001cA\u000eCЇz\u0000x*<nO6\u0000Wr\\\n G@}[srcB{1d9^eI_\nM&\u0015<QOCO\\R]Q/6]}\u0011R;Wajq;yR}\u0015s>tg\u0003+E?-as\u0005p7#[wwZZppMwMuM\u0001p\u000b\u0013J\u0016\u001a\u001a\tP,)[Qk竿ܙtkh_^E]-D^ѮVy\u0014\n\n+`|ABAŕ\u001b99:[;[:E9yO\u0015ǋ\u0015/3lyAW\r[@wV/\u001ekDגǉ\u0015^\u001c#ԃ{y\u0000'\u000fx\tE\u0016\u001e&)D\n\r\"bl\u0019~dqkY^k>zn,Qb^*Q޾MWq+\u001d_귛b}77ҩNwK)WjTEW\u00005H\rU{e/\u00105Tj\u0015Uz\u0014g):\r8`.̃۰\n\u001e|X\u0006a\u0003\u0007\u0007\b\n`\u000eP\nKa5dqp}\b\u001e<\u00017lp\u001a~\u001d0\u0016V\bȅb\u000bp\u0016yx\f2\\a'|\u0002\u000fsȃ+6rx\b\u000ba\f$A2\u0014\u001468\u0018\u000f\u0006\u0004Hwx*j\u0014\fSakȀ\u00190\u0013fj\fYj!\u001e\u0012\b\u001eŋ䇗(\u0000&Lx0B0\u001a5\ncx\u001cR0^0Qk\u00065B\"jNj7ɊHb6\u0019|#;dûԜZxZ=\u0007\n]<?#j\u000f5\u00114\u001c\u001fS\u0014>vXBѰ\u000b\u0019`)s\u001dğ=\u0001˩#A%VQgNb\ru\u0013\u0015{XD2\u001257Y\u000f\u001cSx\u001a`.T@5))TnOz!O,eP*ʥ\u001a+\u000fB\fPYc+\u000e6d\u001b\u0006bJm܂#v;y\u0017gn\u001aw{D~5Jm\u0007D>ȇ0]Vv\u0011>\u0017/P#|J^jꢬQr\u0001PSR]Jr])PʷwJRT)7BHqu\u000epٟ~r\u0000cR\rR2ˁr&Kr\u001c,f_9C\u00192RT*7RȾrcy\u0016+#E\u000e\u000b\u0012)73ُr5\u00038\u001c!X\rsY(+}߽\u000fd\u0018g\u0004E`a\u0001a\u0018ED\u0004\u0005QD1V\u001aԕ4IjTz\u001a\u0013=xN\u0017O:mc\u0011\u0013\\\u001bmiMԸK,B\f衭'?7~g|\u0006bvb\u0012&M\"xta\u001e1\u001f=X@wЋ\u0007j1|\fA\u00071\u0005p0\u0016c\tb\u0019ל1\u0015\u001a1\r1\u000331\u000b\u0007Q;C'fPr\u001c\"N8'>\u0015g.Va5\u000eaXutuAW2]\u001cU7p\u0004\u001aQ!}@\u000e9:E:H覸':E\u0014R)\tRI\u0003>(Ij\b\u0002\\9p\u000eUZMpF=ŵB\u0000Xlp\u0003nd\f/pN/\u0016܆;p\u0017\to\u0015|>\u0019'\u0011'·p8g.T8<%YImv\u00058AMVh\u001cب&\u0014Щ:]R\t\u0001bUF[60\u0013\u000ea8\"\fD.Kh9\u001f\u000b#zQ.h\u001bm\u0016z^.+d|ަw\u0015^nzY7&ޠ7h,p\u0015|Kn\u001am6]\u001a7z~I~s/ z}\f>ISGq\u001b\n]\u001f\u0006PvЯhޭ__\u001fUU\u000e}]G2\u001c4\f\u0007\u0003*4^p6>7\u0018gSgTJe4ĸn\\6nP5Tc4\u0018_\u0018UqAQFyXF<Q^\u0003|\u001c+\u0002bH\u001f\u0014mb8\u000fWѰ\\UrTإ\n`UJT)CL-\u0012ǕS\rR.VY*O\u001b]8DO\u001ba\u001al\u001a':p6\u0019w4G\t\u0011\fSq\u0016>\u0018\u001dit\u001f#:L?$d|\nauz\u001e\u0005cu~B7qz\"='\u000e\tz\u001eku>k\\ah\t-yj^\fL\u001eBqX/.\u0018_\u0002,,ǸK\u0019\u0014\u0019\f\u000e.m*nd\u0013jaq\u0004jaT4\u001f-y\u000f;2\u000b\u00048\u000eV!ǧ:>Wgk(\u0011\t(|S\t]&\u001b~':_ZV%\u0012KM&dV=/\u000bdsC-m\u001bWi#79|V[kV\bۜ3FZ\u001ff\\6hl˿\u0013\n_\u0003sW~\u001f#\u001eL\u0003;ǝ0W\rM+\u0012\u0015U\u0004VhhwT%}>E\u000f2\u000bsc{r֜3e\u0011}\u000b_kk\u001b\u001d\t<P&EO\u00034GUɊЧ\n=!;윇}g56Us&`&}RQՋ҈ޔ8\u0010RP(<R+l\tR:\u0007\r\u0015\u000faxe7+\u001fp1\u001c\ff?g\u001b\u0013bxcb8Q\u0018{$\u001fp\u0002\u001c\u001fdx\u0003+\u00127+P)OE\u0000a\u0015\u0000Z\fg\t\\0,N0\\{c;jEw\n?ɻ\u0012}\u0002uƾ\u0007:nGYV󒌝邩\u0002&߫=C\nXΐ\b-\u0015\u0015czeoiQܼ\u0006E\u001f\b+YINK\u0002kXQ[vì2b<Vf\u0011\u0017U=\u001e)uP\u0018\u000e}1]ll\u0013O\u0019'#\u001a\\ه \\@\u0004~8 F1ce`elad\u0004g1Fd3{c[4G돈+\u0016A3*\u0014% R\u0004\u0014?SP\u000e1ffL[\u000b\u00143w&&:\u000b\u0006+s\u0000t\u001998%ɼ+lrbWbǖi$4%ЕW:\u0019?89fv7\u0007֮\u0010\u001cxe߀0\\fN%'8KhAbF-ǘXX8ƈl\u000ex\u0001aڄ[\u0016dm̔w7uߏnnnnnn\u000e\u001eފN2|:\u0006\u0014K\u0013!;r\u0005q0I\u0004Lp'AL49Rr!AIE9x\u000b3\fړ^#ѹʼ$\\-Ӫz8+K\u0013\n:`,*(K)TQYiC\fKI*XT61\u0012\u001eWM~WX82/')5%fy:b\u0002@gi%2'myZN@2\"4\u0007S`\u0013v\t^1\u0018uX\u001d2F\u000enۭV77W۷;7رDsA~uy\u000eda\n9M\u001b&t_#\u0013kdn&\u001aX#\u0013kdbL52F&\u001aB\u001a9XE|ȭ{)\u0006D*렝v&۩!}׮<\u0013Rrg8P:3\u0015+cvusϝ\u001bwǳڳ<sgl_$NY\u001a4r6MIY\u001a*EUۇDj\u0016)x%V\nXDQ\u0012!\u0005E\u0011\u0005̢(MP\u0010\tI\u001b|s\u0003bOYM2QGW$\u001b,gRthx\u000e-'֞\t⅞P;Z\u0018;\u0003\u001b.UO&!\u0015hÙ\u001bBtv\u0012+\u0007R\u0004\u0006?`2b\u0007#\u0006#v0b\u0017+F'G'/\u0003\u0002\u000b\u0005\u0010#\u0011\u0018IE,׳\u0006P\u000f\u0004*f`\u0001x\u0018x\u0002x\u000e\u0012\ru'@\u0012T5/o*YRZ\u0005\u0002lD\u0003-\u000eWH&t\u000fr2ł۵\u0011\"9I_\u0011\u001cRg \u0019L\u0005z!38xtK3tW;vS}`x![\u0019RgL\u0014O{\u0013y/\u0017x\u0012y_ \u001fw\r\u0005\u001f955sT}\u0013i\u001e6(!:`0\"g\u0007.\"\u0014(\u0010<\u0016c\u0011<\u0016c\u0011<\u0016c\u0011<\u0016c\u0011<\u0016c\u0011<\u0016c\u0011<\u0016\u001b<\u0016c\u0011<^BXzYQ-\u0007UF3_)Ұ\u0002+\u0002+\u0002+\u0002+\u0002+\u0002+\"˒{\tn~q\u0017uH\u001buH!]t\u001duH!]t\u001duH!]t\u001duWUJ~\ru\t\u0016\u0014LY;P ʬC(zȐ@YI2ryN\r2S\u001c];6mf\u0007'OjzvmىR\u0007\u0018o&؜\u001f9c\u0001.|q_+\u001c󺶳ό{*{F\u000ftZ`jW[;W\u0019u\u0007L+1k?مFҧZdFq\u0014Џ\n^4o\r|k\r5o\r|k[\u0003\u001a\u00065o\r|k[\u0013|oZ\ng\u0016\u0015¹W<=A܏ZevTԤU\nC\u001b\u0015\u0007''-%P\u001b\u001bTw|l-y+t^r~'G\n|j\b\u000b>\u0018`p-;~PuGmx\u0002noզ\u0011{x\u000b)}POUY\bq\u0016NzDsYE^aDRպh~E9l'DkqR2׉\u0014x]ԓJN؂\u0013\u000fN=9}p|3ꤤ^ȋG\u0017J\u000fՇR|5&rvg\u0013F\u001b,ÏB\u0005Y*3GW)\nڰ먰\nc\n\n\n\n*NWw\u0000N\nhz\u00005ڝ7Cq\u001dҳ\u000eDQHxKX\u0019\u0011HR\u0017jwXjx\tܾ4[\bu}0k݅}8^\u0015Kl5\u0012B|5\u0012foLe\u001dֆi\n\u000fY\u000bFg7%'\u0012)\u0019v/Zuf\ng!o\u001c#_/[P,_\u000b=dV>0u}xRv\u000f,d3\u0007HX\u0006\u001d`{rD>m\u001bݛNLN\u0017z+]/Ňbvt8\u001594PH:d7\u001fq:Q_mU1q\u0016ci\u000f*\\a/92_wdnYawz 9qSQŰ\n;Z5o\u0016w/^br\u000f*a.,\u0004c1w[}Ǹ}yT!p\u000f\u001f\u0017!Z\u0002!zS>s{_\u000enZ~vBD!o/\u001b)\u0016bbvP'^eOlMq23,\u00060ʢ\u0018_&\u001b\u001fI/1\u000f_d\u0005%|ixXUzܸn`v\u0001\u000e\u0002:/\u0001#9Ͱ\u001ceq\u0011!k,\t\u0019`7/Bc_\u0010k벂e癗\u001fa\u001dO\u0018wט̗ېvY\u0019\u000bdm^cQ쫠M\ra\rC?*\u0012g1\u0019/0\u0011Fg0k\u0011sm.CN+the\u001eiq\u0001H\"\u0011&н4݉\t=\u001f_3\u0013t4\u0006~\tۤƛa>EY\"(M6?8֏6\u000eXMq\fٰ|Ÿ\u0005={alI\u0018\u0019Lr\u000b\u00079\u0016.E>e;~>\u0019cb\u0019\u001ceGwoci\u0002^$?mpE,)d?̟\n\u0000>Sw؞}8Tw\u000f\u0000g3\u0001\r\u001eo{\n9g3I)\u001a>'A\u0000u{Y\u0010\"\u000esM7k\u0005-\u001a\u0002:n$7nO4t:v@Im\u0017ȕ1\u0013|\u000ekz\u0000y˿\u001a\ncF\u0019;π\u00028_mA9oshCY\u000fd*{\u0017\u001cλ+Kro\u0006/r\u001cVC\u0011\u0006Ū(k\u001dPl\u0000NCU~H-\u001bzw\u001d>\u001c\u0015\u0014)/(?Eu,ϱ\u000e\u0002ƾ\u000e\\]\fW\u0013(\u000e:lc6?Z)\fdE\bԀeWx!V\n\u0016Soy\u0011\u0014\u0007x:y\u001a\u0002+<\u000eL\"͠EQ^ݣmq\u001f\u0012\u0003\\#dSX5B\u000f҇lK\u00032\u0011XUt{ŸÃ;k\u001eB𩿱n\fy\u001d|l<?{l\u0019r-^-7!r\u001f\u00050m\"8\u0010t(\u0014\u0016,fL\u0006\u00038\u0010\u0005ق@D2G2\u0011l\u000e:En\u0003\u0011\b0\u0014\u0005==׏|=9ynq<\u001f}nbOy^\u00170ϚSb;o&\u000e̐2ս}j\u000fzFzw+M\fYeFnl|F\u0003ݻ^c{Vҵ$WXfc7#\nkwh?ѷφ5>\u0014z$W\u000bjTI,_%nY+\r\u001f\u00178|\u0014\u000bv\u0018qQhF#\u001f≋Kh^\u0010gLC07\u001c3?xv\f\t\u0014`ӗP_+6*i\tsjn*1c\\\u001bm͢y8\u001eKśzg#KB{\u0007ϣ-!2\u0007\u000e|\b)a|'gJ=oQy\u001fd@q`G\u001bsҬQy\u0006~\u0004:\u00079mbr<\u0019R\tyP@.wHJ9\r\u0004_f\u0019\u0003>+|\u001et\u001fɗ+>o\tr\u0013\fy\u000ev\u0019?Ѹ>.\u000bY\r:Nmv\u0003~dcc)7|\u00152.\r9= #Aϻ/`?\u0006=r0\rݍ~Ѿ\u0006o\u0010\u001a'9jmV͸QP\u001cd\u00156cx\u0013[M,?D\u001aI\u0018cƫԾΘ\u0005ysO]ד,(<\r=nX=mא#v,xȎ]\r߀vLĒ\r5vlލWb{v]cL?Fp]\n\u0019\u0014czsFZ\u001f\u0018E#`-ÝX\u001a'fIN\u001aM7/[fi2y\u0017\u0014\u0014*;M\u001eVVS{^\u001euQ\u0005K{,1YJjֈM2\u000f=4\u000f;yQ%zLZ$\u0007\u001d4v0o\tY΄m0\u0015lf۩\\Xw|\u0010DJTG\u000f\u0001y\nw\u0016amq\"a,dd%\u001d7mKEҗjBn\\&Ƀz޼?dbS)\\IIZlL͹1Oڏ\u0014O\u0010X\nBd\\\u000fsWx\u001ayV\u000eC\u000e8`OLNa\roޅ4G3\u00070Ogc4o$[y)#qWǷP6\u000bùrcs7cV\u000b\u001aĹyY\u0016\u001c\n9\u000b]kUܚ\u0013?qm4s\u0017ke=ʜE͂.e\u001e;؈~~$Z\u0019=\u000f\u0007m\u001amRW;2\u0018^\u001eVTJqgס\u000b6dxv\tJql`\u00198\u0019|\u0016{[;o6#%g}Y{H\u001f#fr\u000eځu4VxKaȣA;%\u001f\u0013וka9Ý\u001c\u001clƳ(Ǫ\u0006:d\u0019U\u00172Dy<Fm+8\tG5;rB\rQLuB/yCRn\u000f'\f\u0002rbla<,fݫocEV\u0019J]zy{#\u0010\u0005nXS8&~zZ52\u001d,OVSԉǚdl>w\r4L~s8\u001b\u001eڀ\\C\u0007%v!_ǛݏT̙N6{a;*zcݦ8u,P#\u001c\\$/Ljo(\u000e\u0010àXcd6\u001aŒAGll4\u0019sq6ӡVm8m]\u0011_{,c\rϢvA<=i?A~36\r\u0006J\u0006KY6t\u0017\u0006m(ϙc\\>{tִ:\u0005\u001d\\zi\u0017sWY/$\u0001.^/ϹcC!\b\u001a\u0011\u001a\r2d?E\u001e\u0013f~³\u0003\u001b`_\u0006|.38\u0005\u001f[yAq'(G}\u001b[\u0003L\u0007j\u000bM&u^[[L|\u0014X\u0003\u0013f}#]29ZC4w\u0017;ER\u000b\u0005/\"e\\S\u0004ctlu\u0006x\u0011\u001a\u000b\u000e(]oe,$\r`\u001b>owG\u0010{H<T\u0017SfG\"?њ9\u0010\u000eE(3/G=ĮĳmDO*C7s|OKF#\u001e:SC$]$Oxg\u0005qh9y\u0011_6q;F\u001e{[@2ȻNMuR*ik=XcpwIfx}%;\u001f_k\u001bSO\u000bι ~QF.5uTT\"I#w#?\u0018﷒^|7!'x=y\u001c|ղ34w=厙#Md]zCpi\u000b.G\u001eմMuS?e\u0010\u001bڶn\u000bQ\u001dR\u001c \u001d06B\r.kt\u0005Wav\u0015,\fF\f|ԞU\u000eM\\+lܭ7BWM\u0004\u001f=b\u0000}h\u001fkG)\f\u0011C\u000e;\u000b\f\u0019\u0010+\u0011ºe{Irhld\r?)VxO2 Y ϠY\u000f/1:R&\u0002'UJ%2\u0018\u001c,%i:~@1|~/aǻ9\t;d7ych~܄!\u000f\"CX\u0004ȡ?Anu碓m)\u0014_9g`\u001f7cus\u000b)xC[2\u001aL2ܟ37y\u0003ڶ>WaαPkY\u0016WJ^O\u0005\u001f׻H\u001f%\u0017l_\u0012`\u00149\u001bb\u0002Y\u001a{\u001e9B?t\u001cW\u001c3\u0019\u0000Ǟ>b<l~F!m7\u00128\u001er9\u0001I#evdli\u00156>;N^~Kad[2*U<Tx6YPuSqRL}Bʼb/6\"w{?-U)-vEZgPӂ\u0004!нuw= D4b|\"(\t/\u001a_$b>>`4G\u0015$E\u000f\u0013fv^\u0010\u001e}gfv7VxdɗQ{\u0017gᛨe\fըh@Zmc\fN\u0001<?7RԦDQ\u000bԔx\u0003;qv};?M\u001dÙ7y\u0012k\u0010)\u001f\u0000ޕ3YCq\u001fB\u0017Ў{W;#܅\u0007}\u0016:M\u0017s\u0012rs\u001dcԑ:s}HےRV5u\u0015>^w@9?'(\rn`\r~XG{\u0016 [\rȰ^߉R\u001b\u001e\u001b;Se6~\u00026A]ϔp6h\u000b\n!ڪ¾\t3\u0018'\u0013l~\u0005\u001fޅ\b_|%7 FQ3m\u000fxx\u0007<r1\u000eHXŷA!\u001fk7sS{\u0018?b\u000f\u0010p_WQ\u001eBg3y\u0011c>\u0007\u0005\u0002\u0016џG{()u<\u000ft\u0018m\u0007\fޙOm{&\u000f\u0002\u0007Od+\u00139ہ6`\u0002\b;3=i`\u001bx6Iq>ؔt(8@$+{q6\\ɁM{\u001bo&Zug!j{pO!Fx9F\u00181bĈ\u0011#F\u00181bĈ\u0011#F\u00181bĈ\u0011#F\u00181bĈ?B(:$\u0018HB\u0006)mT_\u0015֨\u001dNNGz\u0011]CגGHAG\u001b\u0004\rNRS S4\\[q+\u0017\u0002kP|\u000ezfn 2\u0013\u0013T\\\u000e\"^M\u0014\b|r\u0012zeInYpn\u000b\u000f1t|>Ͻ9n\u000e\u001483E^\u0004eU\u0018\rǄn\u0014͡zwrAY8aFs̒!<\u000b0z\u0006t\u0012\u0006}\f\u000f\u001cVqJLvJ\tC\\\u0005\u0015$\u0017&s{%cj>MeL5\u0015W`-`YU\u00017YɗOSW$YtL\u0013\u0011Ӱ\u001c\u000f|\u000e<s-\u0002\u0018?\"\u001b>+{\"\bn(wG\tGe2;s\u000e\u0001/l\u000fr빎'\u0014Vc*R5fNLOQ9\u001e\bCK|`c.^f1떵e\u0012L^Խٵg0\n**y0d\fRG{\t\u0014F \u001c\u001be'\f9,PRpb\u001aG<lC/e}a\n)_;\u001crB\u001e\tS\u0002bK\u0006\u001d\fٿL\u000fW#Ut\u0006N6\u0011'\u0013I\u0019\u0002\u00128Y̦\u0003\u0015'$(\u0007\u001c\u0006i@_\u0005qev{\u0003\u0018ɡcAf_\u0004W!i\u0010ܱH\u0012zR)˃T\fGSJOt5ZaU`F\u0014!3/E\u001d\u0012\u001dXC;\u0007\u001be\u0015\u0018]<\u0012,yh(ϕ2\u0007f\u000f0AӁ\r3%R\u0014(\u0003\u0015􇩌\t\u0015\u0005_4>ͪlɉ*/թ7\u0019꾤%T\".:\u00072&9\u0014\u001f,,qjP+c\u0001Mg9?a\u0003Τg9\u0015\u0017I^P1N'_2f\u0010e@4{Np孽\u000bGw[vT#ʎanaW\u001e\u0017U\f{u\u0011D+~eoL\u001bSw\u0019i \u001d8)\u000bTu\u000fv.aa\u0007Rk?\u0011Zx}u\u0001]~ԖN\\\u001eI'\u0016Q\u0017mVj3\blU:HMVdeixXi\f\u0015j\u001dyjd/\u0014^r\u0013\u00195HX\u0000\u000bS\u0018Z\u000b\u0018C[`\u00055M\u000b\u00182\u0002돃դ\u0014uS\u0007\\m\nWh\u001dƴ`&Z\n0\u0000V~\rendstream\rendobj\r11 0 obj\r<</LastModified(D:20140325091420-04'00')/Private 44 0 R>>\rendobj\r44 0 obj\r<</AIMetaData 45 0 R/AIPrivateData1 46 0 R/AIPrivateData10 47 0 R/AIPrivateData2 48 0 R/AIPrivateData3 49 0 R/AIPrivateData4 50 0 R/AIPrivateData5 51 0 R/AIPrivateData6 52 0 R/AIPrivateData7 53 0 R/AIPrivateData8 54 0 R/AIPrivateData9 55 0 R/ContainerVersion 11/CreatorVersion 14/NumBlock 10/RoundtripStreamType 1/RoundtripVersion 14>>\rendobj\r45 0 obj\r<</Length 1001>>stream\r\n%!PS-Adobe-3.0 \r%%Creator: Adobe Illustrator(R) 14.0\r%%AI8_CreatorVersion: 14.0.0\r%%For: (Cole Trapnell) ()\r%%Title: (Fig 2 - Tuxedo Workflow.ai)\r%%CreationDate: 3/25/14 9:14 AM\r%%Canvassize: 16383\r%%BoundingBox: 3 -127 249 430\r%%HiResBoundingBox: 3.01709 -126.3613 248.4199 429.3525\r%%DocumentProcessColors: Cyan Magenta Yellow Black\r%AI5_FileFormat 10.0\r%AI12_BuildNumber: 367\r%AI3_ColorUsage: Color\r%AI7_ImageSettings: 0\r%%CMYKProcessColor: 1 1 1 1 ([Registration])\r%AI3_Cropmarks: 0 -144.333 251.666 432\r%AI3_TemplateBox: 108.5 215.5 108.5 215.5\r%AI3_TileBox: -180.167 -252.166 431.833 539.8335\r%AI3_DocumentPreview: None\r%AI5_ArtSize: 14400 14400\r%AI5_RulerUnits: 0\r%AI9_ColorModel: 2\r%AI5_ArtFlags: 0 0 0 1 0 0 1 0 0\r%AI5_TargetResolution: 800\r%AI5_NumLayers: 1\r%AI9_OpenToView: -234.3335 451.3335 1.5 1150 1035 18 1 0 58 178 0 0 0 1 1 0 1 1 1\r%AI5_OpenViewLayers: 7\r%%PageOrigin:0 0\r%AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9\r%AI9_Flatten: 1\r%AI12_CMSettings: 00.MS\r%%EndComments\r\rendstream\rendobj\r46 0 obj\r<</Length 7233>>stream\r\n%%BoundingBox: 3 -127 249 430\r%%HiResBoundingBox: 3.01709 -126.3613 248.4199 429.3525\r%AI7_Thumbnail: 60 128 8\r%%BeginData: 7084 Hex Bytes\r%0000330000660000990000CC0033000033330033660033990033CC0033FF\r%0066000066330066660066990066CC0066FF009900009933009966009999\r%0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66\r%00FF9900FFCC3300003300333300663300993300CC3300FF333300333333\r%3333663333993333CC3333FF3366003366333366663366993366CC3366FF\r%3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99\r%33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033\r%6600666600996600CC6600FF6633006633336633666633996633CC6633FF\r%6666006666336666666666996666CC6666FF669900669933669966669999\r%6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33\r%66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF\r%9933009933339933669933999933CC9933FF996600996633996666996699\r%9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33\r%99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF\r%CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399\r%CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933\r%CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF\r%CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC\r%FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699\r%FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33\r%FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100\r%000011111111220000002200000022222222440000004400000044444444\r%550000005500000055555555770000007700000077777777880000008800\r%000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB\r%DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF\r%00FF0000FFFFFF0000FF00FFFFFF00FFFFFF\r%524C45FD09FF7DA8A8FFA8FF7DA8A8FFA8FFFFFF7EFD21FFA8FD0AFFA87D\r%7D7D525252272752525227A87D27A8FD12FF7D7D7EFD047D52537DA87DA8\r%7D52A8FD0AFF7DFD05A87DA87DA87DFD04A8FD13FF7D7D5253527D525252\r%7D527D7DA827A8FD0DFFFD0AA8FD16FFA8FF7DA87E7D7DA87DA87DFD04A8\r%FD0CFFA8FFAFFD07FFA8FD18FFA8FD08FFA8A8FD0EFFA8FFA8527D537D52\r%FFFFA8A8FFA8A8A8FD0DFFA8FFA8FFA8A8A8FF7D52537D7D7DFFFFA8FD0E\r%FFA8FFFFA8537D7D7EA8FFA8FFA8FFFD05A8FD08FFFD06A8FFA8A8FFFF7D\r%7D53A87DFFFFA8FD0EFFA8A8FFFFFFA8FFAFFFA8A8FD06FFA8A87DA8FD04\r%FFA8A8A8FD07FF7DFFA8FFFFFFA8FFA8A87DFD0EFFFD05A8AFFD05A8FD09\r%FF7EFFFFFFA8A8FD09FFA8A8A9A8A8A8AFA8A8A8FD24FF7DFFA8A8FD38FF\r%5252527DFD38FF537D52A8FD33FF7D7D7DA1FD097DA8FD13FFA8FD05FFA8\r%FD13FF52272727F8F8F827F827FD04F827A8FD12FF522752527DA87DFD13\r%FF7DF852775252527D7D52527676F827A8FFA8FD10FFFD047D52FF7DFD0F\r%FFA8A87DA852F82776527D527D277D7DA852F8F8A8A8A87DA8A8FD20FFA8\r%A8A8FFA8FFFF7DF827F8272752F8F8F827F827F827A8FD04FFA87EFD1DFF\r%7D52A8A8FD05FFA85227522752275227522752275252FD07FF7D277DFD1A\r%FF527DFD1EFF597DFD14FFFD05A87DFD05A8FD18FF7DFD0AA8FD0EFFA8FD\r%09FF84FD17FFA8A8FD08FFA8A8FD0EFFA8A852527D7D7E7D7DA8A8FD18FF\r%A8A852FD057D59FFA8FD0EFFA8FF7D7D52847D7D7DFFA8FFA8FFA8FFA8FD\r%0DFFAFFFA8FFA8A8A87D7D7D537D7DA8FFA8FD0EFFA8FFFF527D527D7DFF\r%FFFD07A87DA8FD08FFA8A87EFD06A8FF7D52597D7D7DFFFFA8FD0EFFA8FF\r%FFA87D7D7DA8A8FFA8FD07FFA8A8AFFD05FFA8FD08FFA8FFFF7D7D7DA87D\r%FFFFAFFD0EFFA8A8FD07FFA8A8FD08FFA884A8FFFFA87DFD09FF7DFFA8FF\r%FFFFA8FFA8A87EFD0EFFFD0BA8FD09FFA8A8FFFFA8FD0AFFFD0AA8FD23FF\r%A82752287DFD38FF7D7D52A8FD31FFA87DA87DA87DA87DA87DA87DA87DA8\r%7DA8A8FD2AFF27F8F827F820F827F827F827F8F8F827F852FD11FF527D7D\r%A87DFF7DFD11FF7D27F827524BF8277D7D275227522727F8F827FD11FF52\r%525227527D52A8FD0DFFAFA8A8A827F85252527D52A87D7DA17DA17DA127\r%F852A8A8A8FD0EFFA8FFFFA8A8FFA8FD0DFF7DA8A8FFA827F8FD05272027\r%2727F8272752F8F827FFA8A87DA8FD1FFF7DFD05FF525227522752275227\r%5227522752275227A1FD04FFA8A8FD1DFF7DFD1DFFA8A8FD1AFFA87DFD1F\r%FFA87DA8FD18FF2752FD1FFFA8F8A8FD13FFA8FFFFFFA87DA8FFA8FD1BFF\r%A8FFFF847EFFFFFFA8FD0EFF7DFD0BA87DA8FD14FF7EFD0DA8AFFD0AFFA8\r%FFFFA9FD04FFA8A8A8FFFFFFA8FD14FFA9FFFFA8FFFFFFA8FFA8FFA8FFA8\r%FD0CFFA8A827FD0852A8A8A8FD14FFA8FF7D522753FD0652A8A8A8FD0AFF\r%A8FD07FFA8FD05FF7DFD04A8FD0DFFFD04A8A9FD07FFA8FFFFFFA8FD0BFF\r%A8A8FF7D7D52FD057D52FFA8FFFFFFA8A87DFD0AFFA87DA8A8FFA8FFA87D\r%527D7DA87D7D527EFFA8A8FD0AFFA8FFFFA87DA87DA8A8A87D7DFFFFA8FD\r%05FF7DFD07FFA8A8A8FD04FFA8FFFF7E7D7D84A8A87D7D7DFFA8FD0CFF7D\r%FD04A8FFFD06A87DFD07FF7DA8FD04FFA8A8A8FD05FFFD0FA8FD0CFFA8FF\r%FFFFA8FFFFFFA8FD0BFF7DFD04FFA8FD0AFFA8FFFFFFA8FFFFFFA8FD24FF\r%7DFFFFA8A8FD3AFFA8FD38FF597D7D7DA8FD37FF7D527D52FD3AFFA8FD32\r%FF5252275251522752515252522752525227A8FD11FFA8FD06FFA9A8FFA8\r%FD0DFFA827F852F8F8F852FD0AF827FD11FF522752527D52A8FD047DFD0D\r%FFA827522752277DA17D5252527D5252527D2752FD11FFFD047D527DA8A8\r%7DA884FD0DFF7D274B52527D76FD0452A17D5252A8A82727FD2AFFFD0627\r%F8272127F827277D5227F852FD2AFFA8FD0F7DA1A8FD32FFA8FD3BFFA8A8\r%FD3AFFA8FD3AFFA87D7DFD3AFF277DFD31FFA8FFA8FFA8FFA8FFA8A8A8FF\r%A8FFA8FFA8FFA8FD28FFFD05A8A9FD05A8FFA8A9A8A8A8A9A8A87DFD27FF\r%A8A8FD06FFA852A87D7DFD07FFA8A8FD26FFA8A9FD06FFA9A8A8A87DFD07\r%FFA8FD27FFA9A8FFFFFFA8A8A8FFA8A8A8FFA8A8A8FD04FFA8A8FD26FFA8\r%FFFFFFA852527D527D5252527D52527DFFFFFFA8FD28FFA8FFFFFFFD06A8\r%7DA87DA8A8FD04FFA8A8FD26FFA8FD05FFA852527D5259527D7DFD05FFA8\r%FD27FFA87DFFA8FFA8FFFD09A8FFA8FFA8A8A8FD26FFFD05A8A9A8FFA8A9\r%A8FFA8FFA8A8A8A9A8A8A8FD30FFAFA8FD27FFA8FFFFFFA8FD0FFFA8FD0F\r%FFA8FFFFFFA8FD11FFA87EFD09A8FD0AFFA8A8FD0CFF7DFD0AA8FD0EFFA8\r%FFA8FD05FFA8FFA8FD0BFFA8FD0BFFAFFFFFA8A8FFFFFFAFFFFFA8FD0EFF\r%A8A8FD04527D5252A8A8A8FD09FFA8A8FD0CFFA8A8275228FD0452FFA8FD\r%0EFFA8FFA9FFA8FFA8FFA8FFFD05A8FD07FFA8FD07FFFD06A8FFFFFFA8A8\r%FD04FFA8FD0EFFA8FFA8527D527D52FFFFA8FFFFA8A87DA8A8FFFFFFA8A8\r%FD05FFA87DA8A8FFA8FFA8FF7D527D7D537DFFFFA8FD0EFFA8FFFFA87D7D\r%7DA8A8FFA8FD05FFA8A8A8FFFFFFA8FD04FFA8A8FD06FFA8FFFF7D7D7DA8\r%7DFD11FFA87DFD07A87DA8FD06FFA8A8A8FFA8A8FFFFFFA8A8FD07FF7DA8\r%A8FFFD06A87DFD10FFA8FFFFFFA8FD0BFFA8277DA827FFA8527DFD0BFFA8\r%FFFFFFA8FD24FF527DFF52FFA827FD30FF7D7D527D527D527D527D527652\r%52527D52A8FD11FFA8FD05FFA8FD11FFA827F8F8F85227F8F852FD0627F8\r%F827FD11FF522752527D8452A8FD10FFA827F8F85227522752A87D527D7D\r%A827F8F852FD11FFFD047D52A87DFD11FF7D27F8F827524B7D5252527652\r%7D5227F8F827FD2AFF27F8F8272727F827F8272727F827F827F852FD29FF\r%A87DFD0652275252524B5252524B52A1FD32FFA8FD3BFFA8A8FD3AFFA8FD\r%3AFFA8527DFD34FFA8FD05FF27A8FD04FFA8FD2BFFA87DFD14A8FD26FFA8\r%FD13FFA8FD27FFA8A8FD04FFA8A87EA8FFFD05A8FD04FFA8A8FD26FFA8A9\r%FD04FF7D7D52525253525227A8FD04FFA8FD27FFA9A8FFA8FFA8A8A8FF7D\r%A8A8FFFD05A8FFFFA8A8FD26FFA8FFFF52527D7D7D5252527D7D7D527D52\r%52A8FFA8FD28FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFFFA8A8FD26\r%FFA8FD13FFA8FD27FFA87DFD14A8FD2AFFA8FFFFFFAFFFA8FD05FFA8FD70\r%FFA852A8FD39FFA8277DFD3AFFA8FD2EFFA8522752FD0B27522727274BFD\r%06277DFD0EFFA8FD05FFA8FFFFFFA8FD08FFA8F8F8275227F82752FD0527\r%FD045227F8FD042752F852FD0DFF2752285252527D527D7E5252A8FD07FF\r%7D27F852277D527D527D7D7D52A8A87D767D7652767D527D4BF827FD0DFF\r%A87D84527D7DA87DA8A8A87DFD08FFA8F8F827522752274B275227525252\r%20525252277627275252F852FD21FFA852FD17F82752FD22FFFD04A8A1A8\r%A8A8A1A8A8A87DA8A8A87DA8A8A8A1FD04A8FD2FFFA8A8FD3AFFA8FD3AFF\r%A8527DFD3AFF52A8FD31FF7DFD09A884FD0AA8FD26FFA8A8FFFFA8FFFFFF\r%AFFFFFFFAFFFFFFFA8FFFFFFA8FD27FFA8A8FD12FFA8A8FD26FFA8A9FFFF\r%FFA8527D7D7D527D7D847DFD05FFA8FD27FFA9A8FFFFFFA87D527D7D7D53\r%7D7D7DA8FD04FFA8A8FD26FFA8FD07FFA87D7DA8A8FD07FFA8FD28FFA8FD\r%06FFA8527D7DA8FD07FFA8A8FD26FFA8FD13FFA8FD27FFA87DA8A8A87DA8\r%A8A87DA8A8A87DA8A8A87DA8A87DA8FD0EFFFF\r%%EndData\r\rendstream\rendobj\r47 0 obj\r<</Length 44863>>stream\r\n\tN3@K\u0007\u0001{d\u0001\t\u0001~\t\u0014\\qU+ߛ U\u0001\u001fW坬sFڇ:\rW\\wUQ5z+\u0014\b@e:b68@b-!<il\u0002ɁO^zG\u001f\u0010:\tHPI\u0013\u001cg@L\\\u001e\u0010~A\u0001\u0010AV٣M~\\a'\u001fZ\u0000KR\u0015F\u001e?7k5:k}=kh\u001fp\u001fTaj\u001clL\u0002ʧ\u0013\u0006\u0018;\u0016\f(\u0004m%\t.\u0007@\u001e\f(,%\u0003.\u0001>zK\u001a|\u001c\u0007 i7\\Sb7\r8\u0018\u000f{6e#\b[j[4-żƆw\u001fS·\u0000~H),K㋏\u0006[\u001f'?`\u0017u\u0013e@[FQ\u000f\u0019|q\u0003\"\u0012Oj\r{\u0001hd4Iﰚ\u0002j1GVo\u0005O\u001a\u0007̦\u0006^\u0014t\\Мv_\u0014\u0005^\u001b\u0006H\u0003Qd \u0015:{g.Q2\u001eU\u0012\u001c\u001b\t^-lnnV{l\u00000\t\u0007K\u0000ӝ&h4ix{lw\tts˽(͟IitڽE\u0016eO\u001aA'.\u0007A$E3\u0018pF\u0005B#\u0002\\\u001d0&8\u0000W瀫\u0004\rp\u0001'Ӏ+q~\u0010pd\u001fsvY(i+\u0000\u001cg\u001e\u0001u,7gA!t\u001bW\u001a(.rRQi%pU+\u0011܃-O8~N2u\u000eIo;\u001b\u0001\bx\u0007B\n\u0001U@fUH\u0005\u0003!'\u001co\u0000\u0004#\u00028,%uEb^q\u0016^\u001ac?XQ\n--QU\n \u0000\u0003\u0013Tjt;0}zq2\u001c`×\u0006V\u0004%؜\u0014\fڕd^\u0004RL\u0000Quv9\u0010C.3MG$ʍ\u0014q£ږC\u0005\u0001\r_oW'\u001a_F\u001a(\u001b\u0005*4\b\n+s\u0010\u0000j\u0001U''Y\u0015f\nP~\u0003nZK9$2NWxP΁8N#%5\u0000Um\u00067|̾mf}EZ*%~C\u0013Kz\t\u0006t\u0003v=sGy\fq\b>\u0001z?$?nۿeF\u000fs\u00139]g\\u-e)K!ϛǟNE9\u0015x1\u0017Z4\u000eڒJ.S\u0006\u0005ގչu~-$'r7?\u0004ۯ\u001cw.Toc\"\\jB7ʩT\u001b?1LI!F޾Kbݻ\fOw\u001d܎E̔~W5Wh^\u0006\u0011[J)n~P\\\u00173<G3IA6\u0007CSżq%*k5n;?\n4{{\u001cE\u0013ژUa\u0019\bq]4oͺ<fO\r0^\u0014\u000f2?`<hL\fGpSt_\u000e\n+d@\u001fJ\u0019\u001dA\u0003_gg5\u001a'c4A\u0010/Q=I73wd\n5_qލ<  ;܅.zi\u0001]kޖZ'\u001a[qv\u00128\u001dGK/?A\"z3:#M*T\u0005>\u001a~mk]~緘^}ȡ>\u0001\u0019\u0004x/W6\r\u001d\u001a~׼4\u000e-~\u0003ʽErhYM#(Z\u001bmq!\f9\u0014g3T5\u0010\r9nn\u0007\u000e^CBXs:\u000e+ʲ\t*2]?~r|WOB\r_ʡm?#\u0013ҭ*a9J3l\u0011-;xtB`->j\u001dAm\\[5taw>Q\u001eTU{R\u000f\\Ófo_|&=0ci8\u001f\\\u0019]ϣ1k\u001d\u00177*-yՏjvM\u0004AW\u001fvv9hUuI\u000fl\u001e/oE̝\u001fy;\u0017~\\ECłu<ߵN8(M;qe=)\u0007dr>&тzMjD-/\u0016\u001d\u0015]뫙\u000bՁgDς\u001fqieP\u0019n\u001b\u0017ji)+xHix*Dx+B0=șz\n\u0013*lN<}˹i\u0017AdOcU\"\u0013{zlb*eeI\b0ߧ;LY\u001c!\u0005}\u0016ߍTa\u001c0o\u0019LK\u0015ߓR0qy$/\u001bH;i9\u001a.%!{Ȫ\bu\\\u0007脖~\u00167[3m!J^0\u001c5gTwM\u0013理-GtG}Qrrf+\u001dwy\u00195TPC}[<n&>\u0016r\u0005jfes͞|:\u0019\u001d}[k{\u001d7Ae6g@˹>k]:q5\"^P\\,5\u0006\u0017 iu+a\t\u0014\u001f\u0016\u0014U\u0018Ol$ZdAU\u001f{|Lܾf7\u000b!\u0017s5fC\u0014l\"rY4b讚hv.ѯL1j\u0011q\u0006ΰR|0WY\u000bmLDRԂ.c6̭h\u0015IAg%f\u001a\u0005VB\u001dIh\u0005Rwҟ\u0017f\u001d9\u001aw\u0011|Ҭ\u0014b\frSқ\u0011M\u0012JJ\u0012*_yKD\"O\u000f\"\u00014%|\rE8\bδuRsɈ\f2:^p<9w9nхnu\u0014FjT~k=amv۱C\u0010-\rH\u0018\u0016r^S\u0005wS\f%Ўi1wy\u0011^\u0014@t\u0001>rM{<\u0012jQr,=\u001b{a\u00051G5\u0018oW\u0010ªSg\u0010:ݣ\u001d\\~톗J)\u001b䍊-7\u0006(N>_kŃ\u001c/YnMxx)؍\"?BOve\u0019Q\u0016\u0018 d\u001dElmjPqm=FtB\u0007tz]Q*\u0004QƳ>Yh8$Sv̲{rfWxm;^(?H\u0015q賥Ȟrf^񹳬h:\"AD{Txؙ~dtfe4\f/\fBGbH\u0007\u0007\u000fB[#nZĊ\u0018\r\u0007C\u001c>w\nx<p¶xqӻ\u001e4g|m٬\u001c%[/\u000509gRFˠ|A2\nr&YXsux`\u0014f52ޅ|]W/?~!d$$\u0014dbte|\u0011;ŉ:}ż衙C7{UpE\u0002lڸM=\u0012kv7\u0003FKb\tvzy\u001ev'VV~>\u0015\bLiػ0\u0002\u0019l\u0010\u0007Q\u001b\u0001dHȑ\u0011\u001f\u000b{\u0002m\u0014n\t:\u0000e\u0004B\b\u0013-\"F?o\rtӷFh;QIdl$#D'Dʬ4$5d\u001a[˪f`~\u001b\u0001\u0017\t\u0011(3gs_@][ʽd_\u0003\u0002eΣڇ-8\nw\n[\u000e[̯P\u0004\u0017pu\u0004<,ZS\u001aʗrGƹ\u0004W~H\u0011>\u0017,\u0002n\t\f:!tk\u0015-jȰzp\u000e\tП\fr+}\\yr`\u001eUE\u000bKSg\n\u0016\u001aϑyhE\u000e\u001e'\nݦ\u000bz_oP~:L~\"\u00077\u000f#\rC#2y$V]<Cgx,^PWOe\nb=\u001f$qe!zavlo\u0006F\u00138^?OE\u0011M)e3X-Yܢ>uв8ہ,\u0017\u0011Gw: Ex\ry\u001c\u001ag/\u0017_'BR\u000f2a8j=V cة2I7\r=z)t\u0015 }\u00040\u0019\u0005\"y\u0001 \u00116S\u0010׃4%.肮$KfSӨ:}\u001a\u0003%\u0005\u0003lV-G\u0002e6{'{\u001d|٧v}A&3=^=\u0010P*\b0ZV$2\u001d\u0013,\u001djICQ\u0000\u0003Tu\u001a\u0006@E6'e\u0003(e7\u001bkتqCm\u0005\u0005\\5\\-\u0017[\u00056)+\\\u000fiMOn6x!{%.HaXuߐ1<C|J\u0000\u001c<:\u0002t1%x\u0000Ԩ\u0004\f3KP%x\u000e\u0000z\t\u000e\u0000XG\u0006~\u000bZ2o?M/;A\u001a@B>\u0010j\u0019LczP/ʀmMDZ\u001blTT!PYu_ptrq\u0005~\u0001XI\u0005:;A\u0011K0\u0001E\u0004bC\u0013`={,\u000f)Z\u000e`-\u000b!W%-9WYW9kz\u0007FåЩ4jdٽ-m&e\u001f\u0017i4Ƽ1)\u0010KF\u000f\u0016\u0004\u0017W'M\u0000V\u0004%b\u0000/\u001fiWX9A-\\\u0006xj'|:Z\u0001\u0003xq\u0002*\u000f\u0001Q<l?hYQpz.\nz9]+esf\b%\rWS\"lO*=\u0017ۿqAnC0L\u001b\u0010\u0014\f\u001e')@4\f J9!A/9JO\u0007\u0010]O\u0019\u00007w7)@<\u0019\u0010y\u0002\b\u001d\u0001 @z\u0014\u000fU3\u0002nXV\u0003\u0016\u0015EeB#A\u000b%]g4Xp\n\fd@A=\u0017uH\u0003r\u00019>H_SGڂk|6AKpj\u0001&؝\u0001f1@R\u0006 3\u0006 \u0016|\u0019\u0001\u000eߐJ7W>\u0014f%nĶ!.}ǁcT\u0010W̙єl\u0016\u001ar>\f\rh\u0002Zt? oG\u0005ԩ1\bw\tfy@-.Vt=A\u0007e\u0005Q)\u0019΍S9<}\u001cv\u001bPu\f\u0007T\u0006i\u0000JQ\u001f_3pRu&P4L~ա֗\u001a$!uܞI\u0014\u0013 S\u0005LE`gF^&&o|)A3Y\u0004\t\u0011`xa}\u00002`\b\u0003\fI\u0000\u0003'\u0001Yu\u0000݁o.pr\u001cfgwzoFַʽw52ZY|\u0004՚:c\u001c\u001f.4s\u000f\u000b\u0005U\u0007Q\b\u0000J7F.\u0001\u001f\u001bBo?5{'\u0005sh\u0001v}*W\u001dq\u000e`qY63r=::\u0011/2p5Z9bq\u000fQ>,~\u0010L;\u000e:D\u0007g\u0006x\u0007\n\r'؋x\u0005o'ar8\u0001~\u0012\u0000?[\u0001o\u0001߼QA1\fkL\u001dJ||*|X[?\u0011۾Oz]Xr\n7\fě%8@'\u0017}\tf@\u0000Hp2\u001f;@|o\u001f@<\u001fE6\u001e7\u000fbu_Ŧ@hEr.g*֡e\u001c.\u0016b\u0015\u00067|\u0012f6Ur#Q\t\u0014\u0007+%@\u000f@s\u0014P\u0002\b\u0006<\u0003J\u0013Á\u001222\u000f<\\G\u000f*S5slo\u0010Woݷ\u0005\u0005XUp;?'>?\u0015ˀg@0ƫON\u001d@Oo@O5\u0011C\t&~z]\u0011F;!w1Jۋw\u001a\u001bA\\<_]p<eQ\u0019wYr\u0007mW]aU\u001a\\mF\u0007Vߴ$~\u001fS%\u0000[~qcD 78^p5}(w٭\\lsSZkWU.p)NEH,K\u0016K-H@\r%'c#N\u001d\u0013|\u00139ۼFQZW?>~Y^\u001fn7~;hA\u001fd\u000e\u000be^gJ\u00064=Z\u0002O,6=&\u00061a<3'3BiO,9+\\\u0017ˍEMΝw\u000fG;vjhrm\u000f}̫_9ۼ\u001cM\u001bXrTS)3h|\u000ei4H\u000eԼl7v\u001c]e4\u001e>ղ٫\u0003&,?!cb6碥{S[3\u0017\u0006jqҷ⬠w\t\u0003\ne\u0019vZ'Aȡ\u0003q!K=m;V?݁:L\u001b\u001dthY{\u0011hZk\u0001%\u0003F\fq*\u0004\u0016AC%剮,,^Bq;4 y\u0004YW?FU~\u0010Vʡ:zƳhm+\f!h*\u0006I7c6T\u00165t^0.U+JΩ\\T\u0004r;\u0017~.Sw{Z}LgLŁ?7\n\nTy~cV?OG\u000bmkDN/6\t\u001cUb_7ʮ\u001dg_zw/ԫtUqwև\u0006|qV\"\u000br2H@w\u0003qe9\fas\u001c.@\u0014l\u001aQVװ[\u0017|aU-q]DS11\u001f?\u0019\u0011\" i\u0019U,ŋ*\u0016h\u0016m\u0017m|+8to̪C\u001cz1D[{^v`6\u000b\rs/6sJF'd$nue|VmӖ\t\u0018Ga8zj/>\u000b19\n|\\*y=\u0007ZU7\u0014\u0006b/qfN!K'W!yv`ri\u0005Y\u0015Zu2:\f'-6\u0017jnL=\u001aFn\u0018]mFi[՘YHoF(c镺\u00105΁\\g?*\u000e2-\u0011\u001a#AtE\u0011+Kōl\u0007fUW6߫aBe80g׉ۡhq\b5줫 \\\r\nN9-mDnaI\u0005 =NP[d~\u001b\t/zq0b\u0010ڳA^sr2/u\u001agZ~<+{6t\u0019<iYg)-Joz\u001eSGMUкfQ^]Z%%,D;]; ¸C\u0004\f\u0015~6\\x7\u000ex\u0012^<{9n4茽\nS\u0001Jc߂o1\u0006\u000e]hWUZ/E\u0012IK@5?i\u001e,\u001fzZye-\u0005IݚIPpTea\u001cW5ѻY~\u001b\u0017y7sq1|8c7陭z\u001a7\u000b\tjDfCΒ@)kN\nTOcRkR!jc\u001d^ҩ\u000e^!E\"YQ3Ap+v3\u001a\u001apLn±\\{-q\u001d\\\t\u000eɒ,[9s9uWg\u001fJv\u0005R{t\u0003$#A\u0012\u0004@\u0010,p\u001bfkhnrƿhqV\bg\u001d[9\u000f)\u001el\r\u0019\u000f502\u001e)c<~l<ygshK\u000f\u0003}>7g۪pϧZg-h\u00004G=\u0013ƙ[\u0013^ee5\u0013i\u001c\u0010\u0018ift\nlNgϜih{*nIn^\u0016*\n(*`C@rPT\u0011.r]kӜ}m\u0019\u0019i[`2\u0017ۆqGuY#j\u0017S\u000bI#hI{z\u0018\u0007\u001deƜEˊB\u0007S#t\u001bR5xwR?LQAbd\u00131IGLPw\u0004w\b~3t=Dr\n\u001a𢌴\u0002~L9n?[ro=\\-WvNg˦j]$/)c(L4lgx\u00166'[4^u:xoAQ-\\aFȘ9!\u00136\u001e h\u0010M\u0007\";<7$X\u0012a^\u0015D΍KAP\fBYr'\u0017KTF\u0018\u0017o)4\rNV^:5pҒgKH\u0007VQ1:\u0018}u\rMm`urXTɘ\u000bm\u001c-;!\u001a\u0010l4/gs\u001f.eM)l\u0002s\u001f%,Z\u0016S>䘧˨}\u001d\u0000}Z]\u0015\u001fp&>x:mf!̴y<`;/GC(\u0019-\u0014\u0017'\u0014\fNcQ(X`J\f8\u0015aMbj\b!k\u000b\u00021& \t/qi>aʅ\n.\t\r\u000f\u001bIa֑Zu@ܑ\n\r\u0013\u001b\u0002hv#$C\t\u0001ǟwgQÌ]?\u0019؝Va\n'\u001eʿ9O\u001b:VV\bRK6h7\u000b\"Gq\u0007zM\u0011\t\r&Xu,_ZzvB\u001baP`1|\u001fGN>ZD]\u0013\u0001^\fT\u0005W\u0000+\t`EҮ\b\nud+\u0003,c|q,T0ay($R%,xYi\u0006f\u000e\u0013sɯm2˞\u0017#M[\u0013b\u000eV=%˻\u0016rHݳ\u001e\"\u001e\u000eڧ\u0003~G\u001c\u0005ةo\u0004Yp\u0000j\u0000Njl\u0016\u0000g}I8\u001b\u0001\u00007\u0006\u0000q\u0013|\u0013D>Jp\u001aM8`þ{~fցS\u0015_DK;1\u001dLN\u001c_\u000ePauf4LD\u000f'\u000e\u0001S(Eu\u0000xC\u0000$\u0000)HM\u001b\u000f\u0011N\u0010L\u0003*\nbΫzT\u00143fz/t\u0003β'f<>1?92Z,B.vsӑ6@Egv%\u0014#@x.}@xi,L!\to i_\u0000aE\u0015\u0011P`@\r\u0000B\u0002\"P\u0003\"\u0016\u0001$:\u0004 ̧Y\u0018Sfn\u0015F\u0001oPs'l;\u0012\u0014P{+eT\u001bpE\u0016fxzLwO\b䬷A\u0013:a`:\u00054\u0007\u0004$XC:\u0002\u0016pH<$+\u0007 \u0019g\u0004q\t{\b\fHi\u0001$T#\u0013\u0007\u0000\u0010G\u000f\u000be0z)]JY\u0016\u0007\u0002Eo\u0003\u0015?IDFfzwh\b\u0005PCM\u0006;\\\u0004\\\u0019O\b\u001eq\u0000\u001c\u00116~\u0007(t\u0000\u0014n9\u0001E 2\u001c̀<z\f<kf<G0@i; G\u001c ]@\u0004dy]\u0000dIeZ4ڗ^\u0001ͥx6\u0006\u001b,)*c\u0013${\rN1\f{u{!a\" \u001d\u000f\u0000\u001d)\u0001\u001c\u0001m_\t\u0006h0Q\u0007\u001aP[V$jd\u001cTڲ w\u0000\u00015[PW*7ʛe@u@dlő\"S\f\u001b\u000b\u000f>VR?J\u0013i3+@8\u0012\u000b|8ZQJ\u001a\u0001S\"I9q\u0004-\u0018`\u001cN\u00120$_ÂS\u0002\u0003;\u0006ɨ\f}\b\u0000M\u0007\nBrj\u00013:)\r,އL\u0012䢧\u0001G\u001e\u0015'YO\u0004h[Eӕ\u0019Gtdi\u001a\u001b\u0006P|\u0003vd4}$\u0005 \u00006W}qR\u0002(Cv\u0002\u0016xH!H\u0019\u0006$\u0019`\u0018\nXl\u0006,9H\u0000\\\u0018\u0000f\u001dQ\u000b\u0007\u0001\u001e, \u001f<x\u0019?\fe\u000fJI%\u001bbfhg/eҢ<\u0013\u000e \u0006\u001d00\u0017#\u000b׍\\\u0003\u0017n j\\\u0004\u0012W\u0012j\tpu\\\u001bY\u001ap\u0016|=\u001e\u0001/\u0000g8T\u001cpT\u0000؋\u0014ʱex\u001e\u0001/fZ̆]J7j,H#=;Ǆ3mB1\u000fx\\ɟwKAJ,\u001d9+\u0017ʐ'ϐl\u0004\nA\u000b\u001aE~\u0002\nz\u0013ĀqbFY\fTN{\u0012\n.\u00142'\u0013\u0019+a\u0019Zμc4n\u0011Vvsn\u0006H޷?\\_\u000e\u0010\u0014\u0006vaj\u0003I\u0001d\u0003P\u0000\u000f\u001f\u0010\u0011\u00148\u0002\b32X&^7\u001c(c\u001eP+\u00068Q[42%&\u001f\u001fj\r\rWW{%\u001eH5\u000e$DJ\u001fHb\u0019H\u0011\u0002HQ\u0011H^)\t$i\n$M\u0000\\\u0003ݾcȈL\u0015WÎ\u0017n\u0013q\u0016&(\u001a\u001dWXu\u0015^xG35hlp}L! 7sVos\u001e\u0000Ez\u0012X}%n\f,\rX6\u0012\u0001hʡxzgs\u0013FVP˛l%Oɨty\u0013\u001c:\\|\u000b\u0001*%~AU/LSnC$U3M`+`;Q<S \u0006e\u0004l#\u0003\u001c\u0003Usۦx;F\u0010\u0002K@N;ۅte反MrwQR\u000e\u0007g=Y|Y&12-\\ig\u001clY`\u0003\t\u0007S3*\rױH̀\u000fY\u001c\u001d%ɭf\u001bP3êP%VEU㞈%mlc\u001bD1\u001b\u0011:or\rȅ=ؑ)`(\"uh\u001d\u001fEjP15-]i״ݎ}1\u0012ut١\u001dT+4mEқmJzhGʩՏ䃷:wQRo~\u001c;Ӿꎓg7>{LnXCN鹴G^;ze6\u0017QoJ\u0013(\b\np\u001bS\u001aNWj\u0006~ݖQ+q^u\u0016SfTM4p*dr;t$~͈zm-`#;JXS\u001a.ujez)mX\u001bw*A0L(<^xWL\u0019ǧ0ۢL\u0005֔U,ΜdhiC\u0003AGN\u0007y\"uuF$4]UCW#^<\u0012#=ruMc6@Wʅ)#4\nM\u0014[\u0016Bٕ/ܮ\r)C6RɬRfB1vt'Tkapqr\u0012\u0010v\"\u0013:RX3DwX;꠪\\8T!tԪ7\f\bQ\u000e]M1y }7[g..\t$~$q-jRH\b9Ƭu%\u0015IOt׀V\u0003MF\f8\u001cHt2h\u0014>v\fuR4D,C`21\u0006Fe?c\u0019d\tW\u0015[t͜Zkx\n\u0001$\u000f8Q[Km^O\u0013\u0018ԓq#׌/rf`/we7뱕Dxa\u0019n0:\u001eBAc\u001c\"fE4\u00181\u0015 jq\u0012rW\u000bۗuǜZlSV4B)Ѵ+\u0006qDͰ(\rq\u0006Eal@D\u0003qX%͐3\u0019\nrx*H/@</y/\u001c-kI[^+v^xʡ}\u001c\u000fZC\\L|ɗ\\Nb;\"NO>j@5,˱v#(ڦ4g\u0002-Y~9ΧikKFwt0\f\u000e] 9:k.\u0015\r=\u000euע2F]ͤ/B\u0017\r\u0016&XuIĀ۹KmKgV3\u001dʅ4\"[pRΜזr8dc\u0015`G%ugo.Uʗ1Ĝ4/\u001bU\u0010_`JElT2\u001e\u0004FI.tn\u001a\u0017\u001dn+㎭ΝN[sD\u0014\u000fZA$b5lR.De7T,dm>.rc<J\u0012EH>{jԱ)i-FeDbY*\u0006\u001c\u0019Lϩrd;Ԍ`\u0004}9H8\u00029҅z\u0011\b\u0012X\u0017\u0005\"{MT5Rה\u001b\u001c\u000eo;m\u001aYf~|o/QS)e~[\u0015\u00194\u0017FF0R\u0001\u000e\u000fN>\u0015/f\u001a\u0017ŸXqHȃ[=e\u0013b\u0013Kd*~ov\u0014\u001d\u001e\u001c}˟\u000e\u0011=Wr!,-\u000en.JY[S:E׊\u0018q)aj\u0019f槽OE\u0018(5a4\u0012\u0007\\!\u001b8͚g˥du8,uL\u00108!qK6n՝\u0004f\u00017.rG1srRі.\u0006\\b+3\bf'Nq?\u0010P\u0018)\u0017\u0018O\u0012s^rkc6\u001b\\\u0015R=[#[2됝^渫$\u0018c_/Ȕy(a\u0005\u001bi\u0003N\u0005#\r\u0015̙\u0004*X89;e϶VJlD*v\bc\u0004wngٸS\u001bikM|*ϙ=Bbo\u001bI+\r\u0016]\u0003Ζ!LfLmZ3\u0012~[ӾEFA\u00106Bt`D2\n yL$]0\u000f\u000b<\u0013B;xC7\u001cFȱpŮ\u0002u*\u0005\u00179T\u001br&ͨ܉\\|̛\n6g\u001ai\u00112N-?]9צ\u0019y@\\9E^J[r0Z#$ˣ\f1>\u0006HTAwxz\u001aI\u0014&'`+49TYl8901ْX\u001c\u001a\u0005\u001c\u001aѦCO#8(;t&f[\u000eɱek\bdaj)̌x:*/Erp.hP$YoJL~HLC8\u0005>7y\u000fx!qSbV\u000f\u001bW\u0019rHВt@\"\"#TB߀#\u0010G Ė\u0000ʝ\u001e.k\u000b8`W\r'{i$mvcW,DhLHՏ\u001b^\u000evX¾KHr\f>Rx4C[\f7-5Hj]lNa2\u001aDRɣv\u0013D\u000e|\u0012qy\u000f\rp\u001b͘8c?@~\u000b\b\u0005('9oh\u001eY\u001a\u0005\u001c2fZ}{63k1us\u0019x4$`'n\u001fqϙ١\\\"\u0004o*L\u0016-X\u001e!b\u0005-}mԞ,0Z!:z\u0001\u0017\u0005IS\u0014\u001d\u0001hyR\u0007h%\u0001h\u0003Ƅ\u0001t\u0001G\tH2l'Ri\u0019:k6k*5\u0016\u0006TR-\u0005]X`\"\b\b3\\eXO\u001a\nnFEt\u0013ȱ\u0004\np*\u001b41\u0001:\u0001Y\u0001uC,\u001c\u0000C\u0003q\u0019\u0016$=99\u0011`;\n0>\u0000٥3,i\u0004w\u001a\u0007^\u0019!t\u0010\n-\u0018\u0005Lqi\u000bzAaKE;\u0001a\u0003uȭkH\u001d,\u0000̵Qn-FXH|\u0004h\r\u0015\u0003,Ϲ!i\u0000w\u0001bN\u0000+\u0000+Ւ\u0000+&\u0000K7\u0004YO&IK5\u001a\u0005\u0018⦊¾\"m+fT\u0014\u001d;6\u0014C\u000b{R =#2ϷQgy\u0000\u0002pB\u0000hß\n}H\u0016s\u001e\u0014\u000ep\"ɝ\u0003\\Br?Y̾\u000b-\r.\u0003pt\u000eq\u0019`t(=ӱĶ<\u000fPAcݠ5?yo\\M`k_uC\u0012G\"&GOSp\u0000%L0{EP\u0002\u0004i\u0001|\u0000|2Ar\u001c\u0003|*!ÊLw\fg^+$\u0010\"$'ʢ\u0001|\u0010w\u0002|kZ6\u0000/SҀ\\\"\u0001\u0007W4\t\u0003i\u0016ugQj]a\u001d[\b]\u001635m+\u001bC\u001d\u0014G\u0013nV({\u0003@. V\u0012ih\u001f\u0003a\u0000\"\u001fX(>|u\u000f\u0011\u0003DCs\u0002hA2\u0001\u0003PH}\b5pUpo\u0002D\n):k\u0015[2J\u0006J4\b'w\bԸ\u0007m!R)\u0019\u0016a\u0003')\u0016/ai'\r\b\u0004\f\u0012\u001a\u000ea\u0002Idh\u0006d䃤\u0010[L37\u0001j\u000f\u0001Ʒ\u0001)( I\u001fliWO\u0016X1\u000e*l$\u001a'+\u000b+CIh/\u0002'Kp>\u001eT⚹Yf\u0019;!#FU \u0014%ㇵXV\u001a;j\u000f*FπJ$\u0001$\r\u0002P\u0011P\u0001\u001dV\u0018PAc\u0001\u0000PN\u0019켘\u0000%M\u0012b*oH\u0005j\u0002r'*Y3bx^\fC\u000eeD&C\u000e3C8K\u001cM`<%&*ԣ&u`u\u0010\u0017\u0000\u0012\u0011)J\u0002\f\u0001ZWrNX\u001a\u0012\u000b%\u001a5C2\u0000:fN@ҩ\u0001:.O_#6@9@9)Q\u0000:V\rg\u0017F$޺F\u0001'wrދ%ݱ^a;\n\u0002c%;.S\u0003]M\u0012mPS<\b\u0015T,`K#`1\u0007X˾\u0005+Y'u%6xf\u0002Lgc\u0001Lt@\u0012\t\u00012\u0002joC2_\u0003&\u001b\u0000㕳Lt_\u0006w\u0005u$\u0003F`k\u001c0\u0007)T\u00066Ye\u0012Pb!arAsOIK|\f\to9t('\u0014>LM\u0005S\u0003noE\u0010p\f\u0000\u001c!9\f\u0001ݱ\u0002$\u0010`g\u0016`{\u000b`kI7`s\tdƘ\u0005\u00074,DZv޹2\u0001M \u001b]eM-B\u0017\u0007\u0012\u0012\u0015ω$\r<fo$7\u000eH,^`\u00020vl-H\u0006\u000b`PHV`RM1\nX3`r$XOg6pcYRt\u0011yd^DLZh|\u0003e}pm݃፼'xH/[@Z'4\u000f@Y9 d\u0017^ i>\b\u0004\u00040\u0007\u0004{l\u000b\u0004q\u000f\u001c*Ɓe+aoz|F62ϑx$\u0005_lߢ{\u001f\\jd\rJ\r#\u0003\u001e\u000e|yh!ƀi\u0000S+u\u0001v\u0003L|\u0013%\u0004\u000e\u0007q[J\u0018uL1x!<$R\u0006~w{$\r?=lxNf@\u0005}_@|ws`N9`\rcb\u001b>3\u0002qdUҎ\fl☲\u0010 N\"!\u0000׻ҮѶ\u001aԸ\r\u0007cΆ\u001c\nkˮnwy`${8/ƚ\u001cJ̐2lV\bl6\u0013\u000b\u0007ܵ8쇙 \u0014D_QtbҝǺ{\u0012_s>\u000fhR\u00148e\u001a\u001dys0\u001dˠ\u001au\u001eȢݞj\u0019i\u000f\\\t\u000ftw\teq\u0004e9\u0016\u0016\u0014H,8\t5\u0013`\u001f%DO˦R0pjx*)SlM\u000f\bJ\u001dE\fxmFtȱ/n\u000b`X\u000fZzd\r\u0007Asv'\u001be#\u0012]\u0019\u0011ui;\u0018y{6<\\d\u0019;1\u000f\"?\u0001_5\u0003ŷk\u0006\\o5\u0003'\\3\u001dm5\u0003\r\u0002\u0000c$\u0011bCy\f[[5)X5P},1\u0018F\u0005\u0015\u0015Jt44nգ`Z$b2F61c&Nhk6rߣ\\\"qG&i;&vg\u0014rf͐\f2%\u0003\u001eu`>l>-G\u001bdXR*l&57*y\u0005Gz#_6 g;/`El\u0019<\u0005[\\3t\u001cפ\\O\u0005\u001aBcL}\u0006\\rOINCwf\tY]N\u000egH9f$\u0014i\u0003<[D\u0016l,ȹjq\b^\u0014ۨz!@\u0006\u0015|k\u001d1/D棐$\fƏs\u0017rD\t#\u0013\u0015ޢ<\u001d\u0014\u001bNN'tJ攖p\u00120ooeqr\u0005$\u0015,Ay`iA>\u000f͖\u001a!v̷ɶxDz(fv\u001d;#Z\u0015g<C2\u000bFs1gÄ<*#ؘ\u000e\u0003d)F\u0006\u000e\u0011U;R\u000fmw*y-ˠh}:~\u001fkukZ\u0007Vgp@'\u0011\u0003+\r<R\u001d\u0017CQ@r5\u0003cӬ\u0011\u0005G&YXS@\u0019ڇ̂q[\u0016\u001e\fv\u001a\u0015VZQ9C7C܀CF\u000bi\u001242\"&F\u0019\nw,M\f\u0016\u0006ݝ}\n\u0013l]`ʐMޕǖ\u0002\b\u0019+\u0003mN\t6,XCP\u0006ÀC.70uG\"N\nM\u0013\u00014\b\u000b#F\u0012dUX3[ [;Ԡ+٪xl N6.]8\u0010Ca~\u0001=y\u00074;2z-\u0003\fŕEh!y\u001dih~\u0004tLVf^4\u001c\u0003f\u001c,XQQR2.o[\u0012\f\b.rѠǿ\u0006\\5\u0017\u0018_E%\u001d\u001f.mA!\u001c_}ｈ(v-{+~Q~Q~Q~QnD\u000e˥g9)m6CzB5\nzg\u000b\\QV[\u000eQw\u001cZ9J,2%QLa8u_0KWfQɀUIG\u000b\u001b2J(^Qq\u001c>\u000164\u0016|XNP\u001cM\r|N\u001d\u0017\u0017\u0017埀bC*M%\u001fmBx\u001c@w\u0001M_<\u000f\u001cF{Ֆ'l0kf*NF0\u0007\u001f*b?\u00107\u0019PTvI+|\u0002\u0016\"陸3뵍ϽKj\u0013ۅÉǴ@ۡ[B,\\J\n=_MO\u0019_((bDn{}Eik{a53\u0000`ZJ\u00149\"\u0015sV\u0018}\u001e4M/T\u0016\u001f0놰\u00174Ӈ5\u000f\u000bDD\u000biXFP\u0006xg~A(6\u0000\u0002\u0018<k$ap\u000e\bF\u0011\u001c\rj53^a\u0005vUo3 ,\u0002\u001d%\r>a\u000b\u001b60o\u001a((\u000b\u001c[~7U\u0015Ka\u0006k~\u0012\u001b\u000bTD\u00113Zx^d1XRXG\u0017J\u0003Eo\u0015F\u0002%E\u0015\u001bJ+m5TDۗidS^^\u0000;x\"ўr\u0006\u0004cjz\u0012\f8o[JebJ\u0019W.S~y1n}p\u0016BadO\u0017+.\nTRboMq\u001fpg\u00175-u#|[@*ENwZf\u001c((\u000fD\u0007I'o}\u001eh\u00133\u0001Sl7\u0013\u0018\u001fD\u000eANF͏\u0003mb*nm\u0003w5\u0017(HKOi3tuBǥ.1|\u000b8(EC{}*i\u0005\"p\u0006\u0019˿jUl\u0005ythviX\u0004-\u001a=S@PާY\t$訕\u0000\u0019aύAr\u0017\u0003n$C\u0017pbp,sGKSx)\n7Z6sbL<\u0012n:PV\t_q\u000fPX&/lN꽓I.G!^q85\u0015hqBV#g\u001bj]9\u001eC&8Y\u00185\u0014Xr0ErW\u0015/09=QǕz\\\u0004{Q\t㗺vR*BSZՄ\b\u001ds/\u0019#\u0002\u000b֧+\n4\u000fon6LT7۲\u0007\r\u00072'\\c0Y̶E\u0017T\u0016R\\XLr\" \u0016/4z;-pl/Dw\u0015[zVTNSGT/Rd\f!M\u0017e\u00032\u0003&\u0014S&?\ng\u0017\u000f\nP>\u000bRu\b\n&ĞgfJ\u0014+7hb*\u001ck2?l]=$M\u0001Y\u001c&58\u0016k\rU0?jAbHe,Z?:\u0015(hVr\u0013=u4sGL\u0012\u0003~<pfY]\u001b(,\u0014k/\u001dѽ\u001bԀ\u0007r[\u0010$+ŢΛܼNW\u0016e\u0006,F.XfVPwУkFkX\u0017;;h\u0015ss4'$Gb\u001f\u0018O\u001c6V\u0014\u001e\u0015<P\u0005F_oy\"_`z\u0006gJ\u001aw_z4D\fIT\u001cǟ\"-R47\u0003^^uGL%$C \u0017\u001d\tU.9S\fF\nG+ůmQ\u0000_(2%Hw.9X}H\u0003\u0012\u000f\u001c\u000b3/(\\E\u001bSe9\u0011xW\u0001\u0007@/ȏuc`%Ey#\u0011A'y{>\t.3U/B.:\u0017难J#YX\ff\u000fy&JO@ao\u0011~\u00166C5[T}KŋUP>pۥsccX:FE)\u000fS\u0016*\u0017S1iMz[M/j-\u0006Zעe\r%)\u0019ʽL`KO1\u000bXV\u0001\u0012(vKlQD\u0004\u0015!\u000b\u0010\f́i\u000b\u001fGc'\u0006>ٿѼEP5x*މeTB٩NÕ\u0004].u\u0013(-#!\u001b\u0013o\fZ5V~\u001a0.dM׉ٵ\u0012u!8\u001f}//v9`-&W1z&\u0004\new~*^hwxԛxO+g\u0001-\b\u000e\u001e&\u0014\\(Y\\>cN㌥tuT\u0011ĳ[\u001enRTcC˩J;vBEMe`ox\u0018O@}.{\r{Q^\b\u0017\u001a\u0001kT|.%\u001a[V?r3\u0003QT-̴Fjx_!@5d~q5E8\u0005n[*XFI4Gj;\u001bujn2q}Y'\u00183^taA\u0003\n_\u0001\u000eX\u0002W\u001dF&jV\u0011{\u0014Si}\u0015N3F65\u0001f\u0014\u001bKGzUw\u0017'\u001fI]T\u001dUZj\u0012nI<b*Qo^T˼V\u0003òiW\u00058rȭWiiٗB\u0007*WͅJiT\u001bI/HF7KӰ'̸;Plq*\t\u0005x'5\r\u000e>Liez\u001c.8L\u00010T:=V&\u0010<Mdn\u0019Һ'\tai}RO_Vt\u00134\u001c,nS\\ta:\u001fԄ[2MwOU\"\u0000ԣq\t\u0013bJ%}M޸Bb<r -?~JOMCR5FCR1O#\u0003\u0017|\u0015VyyU|:@MU\u000bܳLW֌\r\n-P['heWSs\"EsiƗģa(PVk\u000fnD\u0017\fSL0UP?\u001bh=OqyA@x<\u001f\u0013ݫe\u0010~M\u0004\r^(~\u0017\u0019<\u001e|\"\u0000G\f,\t\r\u0011۴~nRHpJϱlXj\b\u00127pc$Es0xkG\u001eȑ4LGXvBOp'{Y'D\\>=q\tD<626Ktl98=烙&k;}Qnܵ\u0019a+59v*58\u0017Io*)v@4\u001eJ\n\u0000E\u001aە+\u001c\u0017o{\u0014n5$zø34!IP\nzvuHӾ\u0004rOXԪ\u001c뱘\ny@^Zd+͇\u000bs\u0018weL\u00174I=Γk\\u\u0014 %\u001c7\u0003yQ4S*B]\u001e=PW/GA)6W+fdȧ*?L*\r\u0005#xtx\u001cGhcx\u001e%,g0?K*jtmˡ+g{q\n娫4\u0003\u0004in\u00028гJs6L?\n\u0013\u001fT\u000b4\u001f+\u0019$VƋ\u0017\nz٭ZwlEt\rH\u0018ϿGX۫G\u001bm$\fx%a$oNx\br|\u00122Bufҷ&ԑ*u-_+:-tl0\u001c}ϧ~Uyv\u0015\u0016;a>N\u001bb\u001c\u0002b4語\u0005HZ$~\\>|\\b?֙Zc\u0010z4#-Sآqqݦv(K}arד@W?\r>z\\Jݫ\u0014mkZ\u0017-Ixi\u001bFWINa :\b\bc5C$ܵ=KUa\u0013᪽L\u000fp\u000f\bE\u000fx.!lE&9rO*h$\f첸\u0011\"\u0011H{ԩ4fm@\nOAW\u0005ƒ7\u0019j\u000b'=\u0016r*(.uuJÖ\u0016\u001fkMfܫ^>*Uh{YZc'ʲh\u0010g65V\u000e@;/h\u0005{U\n\u00009<\u0006\"\u0018$\u0016N|Z+rHx1{\u0016Y5k\u0013kh[Ȓr\u001b4\"7i鶫S4\u0019ɭ=R\u001cRjx@s\u001b\tʣ0~Q~F0I\u0004\nDSJ:r?9꼺\t)\u0006n\u001a\b$<}\u0014{\u000bLr&\"wB%pkq\u0004xn%h퓷i<\n6ŏ\f-^}\u001f%\u0014\u0015#ST0E\u000f\u0003V}Eg:+K&%櫞=Kll^}Nbe]>sիKN4qL7=Znվg-ؓ;fy3(5FR/B\t3e\u001d\rxdR\u0001>igtm>{^.E\"sߌE\u0007)q6NO6\f6|ٮ.\u001fm\u0007{j\u000eEq:)\u0000{q<l'goU4A|a\u001e~hјJO@\"\u001b~_u%ҿ]\u0016X=(6nl\u0019ӂO$!\u000eJ^qh\u0006\t\u0019pt:\u001bO9:\u0012*^ͧC\b0n+\u0014\u0000e\t\u0012OCL\t)/:\u000e>R\b\u0016;\"OI,k>P68<Ts9Yk;oȓ\u00174lL+\u0014I\u0006uP[aкI\u000f(\\\u0016)z,;5O\u0018Mow6UD\u0000h/|\u0010y\u0013\u0002CGmq6-5@w_Oom\\R;INW\n5.\u0006\u0001\"S\u0005:,SMzQm18Sb̈[\u0005̬\u001a{.\u000b\u0001pj\u0012N;{2Ublm.\u001e1ϳȔ|\u001aꧏ'ϓ_'z4\u001e-)\u001aB`\u001b?ɶ7ٻ\u001bE[ۋ}lR\u0015\tO#y>\u001bH6U~U\u0003ϩ\u000b35JFو\u001aԲnx\u0017%\u0005\u0001+_#@z晉l_u\u001aY٨:\u0015mE+IH:!Ԡ\u001bY\bwzmmi'\u000bw,\u001a9\u0013o+5C_6<CŜՀ{h\u001afLۤ^0\u000b%dXE\tZi<0\u0019Ƒgp\u0017w\u001b蕠#v~Gs$:ܱ҇\u0002<dj\u0012ܶbi\t߼QϢJh\u000b\nT#ko\u000f4t>nx\u001a._u~;MXU\u0003Qq7\u001cg\nc7lEoڝF$\nU\r\u0011\u0013^\u001e77\u0014C|ȼQ*^)eI\tr^4\u0011Vf=yo\u001d*b՘w\u001d\u001bF/(\u0007W\u0013\u001e\u0001'EٙIK4*k\u0019u\u001d&jmzx1\u00048e~\u0012\u00156Kr*@\n\u0010S+W=\u0003?>\"\u001dms\u000f8TN_u&ս^fyV7ƜcG{rә\u0010{`[\u001agn&!'EF\u0002,o-k\u001d덞&OhDד^cWR3;+r+^\u000buITFRy\u0014\u001d^m^[VǛC\b\u001aCͣq\u0017\u001c]V̨Bs\u0014\rx&Y-[dr;3\u001e\u0012l-\u001b'h\n\u00175DY=O`AG\"\u0011*\u0006|k\u0017]R<MN4uU0;'\u001aR/nc]\nq{o\tpyNk9\u0010\u000b𢧓^ȼU<\u0006<WՑ8,\u00125f\u000fɇ~R/9տfB\u0013sMBtw9fQែM\bb,,\u0001}t&\u0003Ӎ5ϳ3\"\u0005\r\t7Pu2\u0014͚ś\u001c\\Ԁ\"D1\u000f\u001c\u0012cߢ\u0004l\u0003S\u001d}Ԕ9ɿ脥Kh~\u0018\u0011z W2qd{t[v:7GGh~mĩ!_='mBWM\rV؈~KP(6.HVrk2V.x]Z\t\fxѕ<NҽwdEVĔyN!\"j\u0019|\u0012EȯbAYpX5t&w|jYA\u0003\u0015TqСiqbR_gd\u000e+\u0016qi<\tBd\u001e7T,\u0010e\nv6{%dZxaΛ\u001aDG3c\u0000ޫ\u00027#\u0017\u0017߃R^zkK~XL44\"ݓX[Ջ\u000b%\u000elV'80\u001d0cZ\u0007Ks9gJY\u0005͞En.>~ij1/\u0011W\u0005\u0013-\"-w\u001cR/޲!\rG%*\u0006DIkҀ7\u0005Wr.<Yj\u0017___+50\u001bw`5\u001f\"N\u000fl\u0017\u0015 v[l6;`(=qHNkZ4\u001aAK֠E<\u0014\u0018$\u0002\u0016ZϦat2\u001d5S\u000e\tΑs_w]ʇO85nD,Q\nJ*&|熰}Pr\ruWfB|\u0016z˝3b+[]˞L\u0007s3TÞ\u0012=`\u0011\\Թ\u001cd\u0000:R\u0018w(s\u001b|8<e\u0003^\fOZd\u0019^2j\u000b\u001bx/(kэg9_]cA\u001e[\rZ\u001a?T a\u0013ލ.q7]'\t\u000f\u0003?ݝ82\u0017َ_S^Wh2b[3_\u0010(\u0012\t\u001c'JWX_u(\u0002aYlV~,e\u0011[Ѣg\u0010\rS\u0014s@\u0018\fpzÀ\u0003v\u0001'EC\b\u0002$.\u0016\u0014i\u0007|\u0018\u0003d\njE,\\+IRM;2hxr\f^\"l&]\u000b\u001242pv#0cN\bĭ|\t'ோB ]MLA.ܠ~41q9\u0001F,*\rr\u0003:t\u0000n\u000fS\u001e\u0017gIiU\u0018\u0018Ō$\n\u00066\u0006*2jvڴnnc?Xs1ޛGg\u0018٤?8yqwjnfQz\u0002\u0011lmi!#SxiVO\u001aR؏=>\u001dS\u0019p\tQ\u0002uGU[\u00110ȹB\u001dbN/}m:+{b?\u001a~\b߃L\r\u001aueg˿~l˱eӺE*k\u0001u<6hԆ(dz\"Q\u0007TS\u0003\u0011\u0006m->\u0014\"Ѯ\u0005i-P1\u001aLu@(=\u001e\u001dF׀iV$\u0006܄)+kRYR[p,\u000e#p$jؾx\n(ܫTZh\bj=\r\u0018I\u0001Ԁ\u0007\u001d;mY\u0007?ڢI\u0013\u0017Aa13jkA'EmB\u001eMZ\u000b\u0014r̵vzu*\u0019_ӟ\u00064\u001ab!f5Ă\u00157RN\u0005\u001c{\u001cJNT\u0007Ԋm&\u0007:\u0010c\\\u0005\nJ$&\u0006\tekh2r\u001bhH=חxn썴W;Ц[Lی&\u0005QC[㓝80J\u0010Զli\u001cZQj\u001cj\u001ap\u00056,fC}\u0002M\u001c1[\u0004-H.hjR2*\u0001nk(z4\rO&MiVL\u000bT]+hi^\u000fu\u0018܊ޭ\r6㕨\u0006'\u0011\u0015TYŞZŐ\u001ehNRamЌ7\u0016:\u0007ۊ,vr.\ry\u001c\u0001mim\u0006.\u000eef[{\tV\u0017X\u0003ڨ&\u0000\nQ\u0002\"kDc@Pq\\z\rth\u001f&\rL\u000f\u0018\u0015T\"Ti8\u0003\u0010\u0005r\u000fm.\u000fBs|\u0004=\b\rc\u001fZ\nڃ\u0016}\u0005\r6L\t\u0015TABxx\u0002?K񵥡\u0003(#+ϔ2>\bBno\rץ܌9C{\u001dV\u0001\u0015\u001f[z\fLv7\t\u001e\u0017ry鼭4>gWAo`d7闯dгW*^!;F=+/ϡ\r\u0013:Oa\u001f\u0010lL\u0013S+$89Ϸs~-pu%x1|>蒺_\u0007$9}f>I\u0001O\u000fsS\u001c2\u001auD]9]NɃ\n)cS\u0013||>LV\u000f\u0005#jӣu\u001f0ݧs~\u001f}jWU)X}YE]\u00054)Yu}\u0000D>\u00042É>ǈCLz_\u0007Nr\\x6;)SR.|!܏1O-\\\u0002\u000bc\u0015z5ft=u\u0015\u000bN٫\u0018 Ǥ3X!`L:\u001a\\\u0015+\u0002.\\\f)vo]e\roP\fJ#b%ғ7$:t>>/jV&ir\r0#}KB;~\u0015! \n\u000bϐ\t\u001c/}\u001dwP\u0001\u00064\u000f\u0006\u001d\u0016.#K.j*KH\u000ftZo\u0012\u0001Ԟ\r>\t\u0002}\u0007U7P\u0003{\u0015|\u001b\u001eI\u0017Tu@wv[DO\u0016}PE\u0007Uf\u001dϵA݀\f4MBm\\)t۪\u0014^8^՟n\u001dA{y}{l,ъ\u001ezmAiqł\u0000>uFN\u001b\u001co(\u001ff@;qYi˝wͻ\u0012)\b#-:x\u001dV\u0018\nADA6\t&\u0005\u001boT\u0000U\u0005Vl\u0007\u001d\u000flg}&)B/('a\u0014?j7Y専\u0012i}wAʕ<P\u000bʝ-\u0013\fw1)8\\Ŕ!YR+G*.$\u001c\u0019N\"}\u0007?Z^\u0005R\u0012L}t*oe*#{=-|'=%CBFy\u001dTPyIŵ\u0007w\u001a\u001f?\u0018v&&\u0017d0e|dHddڇops\u001b+zKfN\n6\u001d\u0007˗̺\u0017=F;N\u0001YoDډG\u0006UUnyH\u001bL[m5֞?Ni\r\u001bM3\u000f{hW-g>iJb)⶛Y0ku\u000fyO=\u0002Q\u001bd쭇\u0006)\\C\u001dަqާ\tXzXT\u00157\r02\u0011u٢ez^HV:څ|>yw|Jm\u0007Hi_&b\u0014b?lR<\r\u000b(\u0017H'֡\n\u001d~\u001e\u001b}\u000f2cQZ%\u0003P3ؖsLfH89W\u0007-wo\u001c\u0012KƱָD*t\u0017&-Q{?\u0016\fW/w\u001bSx\u0012ANUu/5ٽ+tZUZ1͙ԩTxtT*i(tok[}gXA+S+\u0007ŷOEo`QVQ~qa\u000bʗR5>7b~Ʊ/4w\u000b9v/~̱]dBA;~׍oq\u0018B@K\u001c|!>(ڳCY\u0019\u001f\u0019g(\u001c3Ɲ\u0006B|^\u001bޖ/\bڊa\\嘶XA7yO\u000f&CE\fߩR((JUt'^\u0001װ\rY%j\u0016W\\׭\u001fXM«ny\u000b3(uNC;\u001bPF|\u0007\u0000\u001f\u001aw:\f\u0005ć\u0004I<\u001d+u_%\u0002Xuw\u0004U'~\"\u0000>o\u001f>c?gWØ?HQL(z}\u0012w9žԱ؟u\u0007\u0001)>Z̺ŏi2SY\u0013܌9Vݎ\u0015)85Kp\"|KH>d\u001fks璽FDi\u0006c\u0014钽䟺IJ\\BFi\u0006\u001b\u000e\u000eX~Y{6H8Hޠ5\u000fS/C7)}\u0017Ș|}\u000f@_A\u0014y\u001aUiQ\u0000<0-v3eZ\u000fR{0\u000fY\t]W\u0006Sw52_\u0017gq~\u001dɩ{qO={o\rRpc~\u00008`G\nB\u0007\u001aѭ鲐;\u000f\u000bݧj޴YN٬\"?o(`xuoQOM\u000f_\u001c\u0011IO׻V;X؛\rRg{2Y4IÒe9\u0017\u0013R\u0014[Q9X\fY\u0010l\u0011U$G8\u0004G!5LOv\u0018>H\u001a~,7JQ\u0012=>]V.'7XiW@?h\u0015$N+\u001b\u0012\rM\"\u0004\u0019?DSWzG\u001a\u0012%n\u0011\u0011?AR\nDє\u0014_ `PoH4÷SvOfxU-Ew7HcAm\u001fGМ9\u001d\u0005}:Tɻrﻸ\u0005F!B7\u001b:˔<,ϝ_\u0014V\u0005K\u0006÷w\u001fܯW?J\u0010Ԥ'a.GG-\u0010[)\u0006;_#\u0002X~_\u000b?(-d\u001fWC7{jE_\r\u0011~_]\u000b,﯆{P\u0007\u0014_w}>k\u001fbJ}å*#^g\u0015Sc^-Eo-Ob#>[\u000b$L𳵰wj;HOwR⻽y{\u0018\u0010\u001d?QO +s\u0016\u0001\"z\u001ezt\u001fnz)sS§cԳ`_r]?~ GQdZ\u0011qEy\u001c\u0013_\u000fF\u001a\\Ƨe)\u000b߲+aIX7<C\u0001׊]{j\u0005z\fOURލF(\u001e\u0016f\\_!\u001cLŸA\u001bz;0\nr\u0017ͨS*}sDdv\u0006M\u001fu꾯g^9մ,n};̀q[\u0001ڍ\u0000cUE\u0013t\u00069C\t'\f|.{\u001f\u0004ӂr\u0013twp\u0013t\u001fO\u000b\u0019O}vZ'g>?AwZ?C\t:8_3t'n\u001fSNݳ\u000b}~֖\u001f\u000bH\u001cPYfGN\u0004W.LV\nf>WoQ\u0004ߢ?\u000b:s1\u001f_J\u0015_:=|z;WC\u0017i\u0019R:TuYaa'ݾ't\u001bU/<WUI5\u001f\u001d\\|;\u0018D[YnpUR÷A6u\u001aiJ\u0019?W5CӴn<PNG}\u0002\u0006\u0000M09c#\u0006\bgsVI\u001dMG`=o͚\u00195T2a=[MG\u0012l$'Bm 5%\\0bj\bn\u0011ZnByPuB>Y\u000eu7\u000ba\u000215D\u001d:\u001b΀Xėmee$\f\u001f\u0004~{6{(bXEÁ9]\u001ep|3O\u0013;\u0014\t3ZYCӬA0\u0006Q1\u0006~a%\u000eV4˲)8>\u0018x~Q[o4üeN\u0018]Wjm\u0012\bQ7\u0001:\u0007xَ_bN\u0019O\u0014szY2\u0004ם\u00193˫>Љl3d9\tbH;nr/\u0006]\u0012\u0010\u001e{\u001ey\u001d3eO\u0015u=w\\+{j\u0007\u001c\u0011Ѕ\t\b2I^9\u0000LW`x˹UO\u0018\u0002ܜϾ#9\f〒ެ$\u0017ᔛĎ+\u001b92?\u000b\u000f5f$g1Vz9j'u]w\f#St\u0011 u\u0011QӍ\u0015c]\u0013w\u0013d1!1{Ѽc\u001c3Z\u001aJ[E\u00069͠\u0004/\u0016\u0019!ш\bwىN)'k:y\u0018$71oY\"챝-2 \u0007oqz\u000e\u0012O\u0004=Yd|\u0001@-2A&\u0003\f͕E>\u0012\u0016\u0019\u0004\u0019\u0011\u000bXd\u00107\u0004\\\u0012\"\u00060\b\u0000ϱR\u001d&,k\u0018+[\u001c;aY,E7\t`$|\u0015\\2y`jCL\r`1\u001dZ>\u000bX[<οݠ\u0005puA>Wec}\u0001$0F]K\u0013q'[_c\u001f\u0015\u001cr>,3b2\"Ζ\u000b,[:+<\u001e[\t\u001e\u000eq\u0016Ep\u0016vx8\u000f\u0011Ktr[5\u001e9#*pvPoɱ\nP\u0018x\u0003\"\u0001\u000fg.9bVn\u001dı-\u000bne1xW&\u0005űYDz9wqA1$!\u0012c\rD\u000eCY\u0001Kdp\u0011\u0003\u0010\\gmxE<o\u001a\u0017$1<_FV\u001dCJ\b]1cx\"4I\u001aGz; \u0006Lq8>nWRGAryo\u001diJ`lZVa)\u0002vvplކ3\n\u0015\"__\u0001\u0001«@\u000e\u000e R\u000fd\rz\nDj\u0010*\u0010\u0017[\u001e\u00028sA;.l\t2G<&riaT0_o1\u0017\u0011=\u000bA\\^\u0001\u00149\u000bA\u0016+@#V\tC/\u000e\fg\u001b(\u0014\u000eߢ\u0003Ù%.\u0005+KD\u00119#|}.@1#<1\u001bZcC)*S\u0001\u001925N.\"%\u0019vt.Xѯ\\p\u0004\u0003+'W%\u0019l\u001cҭe:\nZŠj\u0017'\u0010\u0017~8\u001f\u001b\u001bY\u0017h6+an[\u0015)\u001b޸n+ՎtS%\u001eZr\u0017\u0010(QC?db\u0011\u0019k#nqg٣!`ǃ=Cإ_\"\nwvi\u0007v\u001b%-_ʵNkv\b\u000f6/msK\u0011ǗNԗ\u001an˗ZPDm=dW.O 종O++nn76\b; \u001dO._ܿi[wK[:[U8_>ϻ6\u001es[|3usc*|H'_=I\u0013D\u0019rt[\u000fv\"(F|D率=r\u001d+\bUĺկ+\u001bHSpַT%9:rL*ə-[+Mu}<LE\u0011iS\u0010<\n羈\\}s*6b~$\u000b\u0006ysZ\fɹΈ[;L>/K:16O\u0002tƷ*4z\u000e㈦3\u0003,jq.3N]~\u0018h:3ķr4<wo܃Dә\u001c/24zh:@\u0012o\u0019Bܠc\u0014W3X^\u0017G\u0019\u0014t6\u0005tVբl0#+Dӹs\u001cӼBә]F+J4ِth̰t&\u0015sDәv^V3J\fMg3Ì,[btN\u0014[\r\fKbh:3,\u0015jq49^\u001aMg3MX\u001eMg-z*tfX:[u!4:[{F\u0016EVo<*4^iIt:b\u001d\u000b&s>,\u0000R>fq}zKd]\u000b\u0014@}EO\u000eYtzuJ0:g\u001d-\u0013r*m9\n\u0016\u0000Ap;Uut%+.TlH&\u0014\u0018vC5L\u001cƆNfe-8FTw&\u0006H8\u001467\u0018e\nyWehb/q-*sg3bE%QۅC;@:\u0000\t˔ӣ8-\nyRjQ\\̝EPΒ:ng\u00027)tP\n\\3\u001ek\u001egl/6\u0004njŰԘHH\u0002unW\u0012 ݲi\u0011Fg\u001a<\u00170\u000epJCuء 2&@d-#e\u0013aT}n(ǫ\"-.:\u001d6C<h(̕yE4\u0014t.> \u001fw^Xt]ʳ:Y\u0004&:-\u0002\u0011X{2\u001f4\u0001m\n-\u00062ѺafeISBJ^\fy}\u001exmӡJ\u001b\u001f:\tWL1=\nd0`z.؇+ Cz_ymˈ\u0013l/vQ\u001eYA\u0000Bժ\u000bǺX33 2\u001ep\u0018\u0001\u0019\u0016{pgTk-x\fu]WTڡ[i|\nw,q\u0015мB<㉬*-y\f\r\u0015lps$g\nwn#iT\fX\u000b]9܃jkU\u0011_d7]\u001f7|!< R\u0001i^feEn驢\u0017˳ŷt2\u0018Cc\u000f9,]ˢ1\nb*Ϭo1S\u0018-Hvscg\u0010zTCnN\u001b\u0010V+\"^+-\u0018Wl\u0017$\u0018\u001a\n0&ςaB+jrɰJy^1É\u000b<1\u000f\u001d\"lTuZ]+\u0001kv#\f'.Stq0x'8$רg;l\u0001eߧ~w\u0002;_%w.\u001a\u001bO;'r\u0010!]޶FViA/\u001ebel_:\u0010~X{)-YDd5U7W\u0016x5\b\u0017\u0018\u001e<;W\u0003\f\u0018Q\u000e[8|g\u0005»^J>=G~i{[a\f\u0006s\u0019\u0017a\u001bha\u001a\u000f7\u0004:zhZ%\u001c*|hhtc;oKn쥾\u0000E9\u001b\u000fV0KۛKG\u001b׌\bA+/=C힛\u0014(Fͳ~U7yLK`\"ŤuNa=DU\u0017=FӦvMR\u001dĪRQԋ9lRā\u001fXM\u0011\u0002\u00182d\rI˼U\\\u000f%K<sd*ݐXsie\u0016s\u0011\u0014-\u0012ҁN'N\u001b\\ҼV٠#4M'oQZ=\u0004u)\r͐n\u001d΋{ԝmˠ\u0013x</6qZhbc5\f\u00143|͔T\tkTӭ\rqKOC(k4޼)\u0013%&a̷\u0002N2yn-˾\u0003\np$$W[2+Noqљ>h:hcf]s\nuAkUN\u0011pc\u001boɮX6e\u0003/`k[URs\u0001\u0004ٱ\u000byDnr\u0002Hx\u0012' \u0001ɴ\f*@(\u001eQ\u001aIJ9`}\u0017P@o:C\u0001j\u00182gv\u0006\f賰l3*:j}1/\u0019n(B1\u0000\u0002ϓ\\.F^b\\spaw1\u0014[P+#\nx*0Y5\\\u0000c\u0000\u001a#{C\u0001\u0000*R\u0005KE=3{\u0014[\fCT\u0007\u0014[\fI\u0007\u0014%=\r|\u0016c\u0002t\u0019\tyK\u0003c\u0001֑+t<Z(\u0015<Y\u0003e(Ua5Ez|(|ut-(Aq_MQ>r#c\u0005Zoދ[\u0015pPLF\u001bꧫbPU#ٛ\\^W[2VT~UB\nrC\u000e_l]?<2LvBu\u0014\u00049,\u0011ɵhE}UH\u0005O;~~;<Wΰ|]?\bՕ\u000bx9gzUi|ɺ~\u0017Q\u001e[}U?6W\u0002[>tʷ~.WPϾz|\u0001p-[֬UVul\u001c{gPVjj4n|\u0005uqWǽ.VOC沂~\u0001ֈTou,$~u~.v\u0007~^u~~s('\u001e~V$VPjW]c]?V\u0015d]?|\u001eL]i++A\u0018Z\u000b>~W\u001eV[Q=>\u0007\u001eRǇǷVy=foT\bTuzuRvuE\u0017shDu\u001c\u001d~~\fMPµǷ5K_oz|P1W&u\u0016\u0003\u0013\n鏡1$}uT0]\u0016\u0007:Q\tv~jBaLy[)JwwWzg_oUуU\u0017g_\u0017p!\u001aKk]\u001e\u0010k~#{g_I\u001es\u000fZ\u0014뷈\f㽮J\u000f?ݣk-Χ\\~GK\u001cup=$Mdk<C1*2L27Bi>^\u0007[$h\u000ev?Qh6Rq\"\u0004o,\\IRo Mcake\u001f䒗\u0019\u0015S7J\u0004\u0017'\u001fo~ReU\u001dEBVu\u001b\u001dD\u00018 \u0004\u000e~ӿW7t\"k]&v\u0013cN=Ԏʣ=i?{\u001ezyQ\r\u001aoǻS9\u0006ƕ/i_\u0014Cm)\u000bwexq}ʓ%ɹ?\u0011hAܪpnkyRx<~ȅƓEwq/\r'͡\n\u0004<\u0016˭\u0013\u0012o6ߒ7m\u0010\u001dtU\u001f~\u0006TK@b=\u0003\u001fT+\u001dXT\u0000!\u0016!\u0007Lx\u001a\u001cM6W\u0006[O\u001bקͯq\u0015\u0014RϳH\u001dn\u0016IcޗIW[\u0001ni\u0004zp|`ju\u00062[\u0001[ t5@}ָn=]\u0002_\u001fWN%9\u0019mr\u001b͋x\u000fd*?/o\u001d?^ni%\u0010\u001f} \u0017lc2woRݽG\u001d\u000b&|@n՘hN\\r\u001ahrd:Ň\u0018(3\u0011\u0012u\u0005,\u0003\r\u0018\b\u0018>\u0013\u000f[VSB\u001d.ڈ\u0005fPc[/\u001c,e0H߮\u000e<<(F}\u0001`^T\u001e\u0003v}VV\u001et\u0003qs<8\u0007\u001c:.FH\u001b\u0005[w1p\u0012\u0011m\u0014\u001c\u0016&o<(\u0012шO\f0(\u001e\b\"?f@.E>\u0005R\u001e\u0000\u000e\u000f\b\u000b~\u001cn#fs\n\u001foɻ\b=FK\u001b\r|\u001a\u0017$>U/PAy\u0003_7B0u*4So\f\u001b}yĊfz0d'[\u0005ON:\rdrY[FwT<Wө'!ߐ `\u0000o\u001b\u001eɶ7,I=ㇽn\u0018;\u0017J\r\rDQt!/11N\u0004Qx~)\u001e\u001b}+y\u001f@½_]a7@梿\u0017,\u000b\u0006Yr?Mpa?'Rk7\u001bق|`\u001f9\u0007*ˎ?1f.RaAzH\u0013\u0013>x㓈fZ\u000fH\u0017b9 Es\u0003rN\bz(B#zF#47QfTn\u0012'B\u00045(\\̬\u0002k.J+\u0011D*pC9d\u001a!y/(m\u0015rQ!9%\\K\u000fwM\\5v\n\u001c1#\u0007{.\u001e!\u001e.\u0012z?JV\rƷ\u0013\t\u001dO>iBWPKvbv\t)\r8B|P`RwKCᢀ\u0002֙mD,UQL5wv:??+ۉ\u0019)6nݛ\u000f|9\u0014\n\u00113*\u0013\n#E!<\bOR\f7[\u0004\u0016*\tM\u0019o՝O2Z>R\u001b5蕨-?B\u000b(Xņ\u00107fB<%؁!W\u0004\u000en\u0015l|)譇\u0017\u00142Il5\u0010\u000f\u0003\t\u001aV~1b\f#\b\"Py/-XnHb\u0007a\u0016\"ւ[#\u0018x&dI&P)\u000b.Bx\u0002'!\u0002&*f)c˒\u0010\u001e5wi(+4>#M/\t\u0004s[%kԳ\u0010\u000b'_c\u0018\u001cGr|wVᇿ[{;\ry#\"Jh}r\u0010ē\\Pyi\u0005Oan`c'b-98\u001c\u001eNe\u0013e6*o>>X\u0017W\u001aUq\u000e\u0017\u001cxٵ.\u0013\u0007(?\u001e^\u0004~ց-P\b׆]YZ^mY'F\u0001\u001b|D<\u0007\u000eWJv;\u0019\u000e\r䄿\u0001+Ԇϊܟ='ZQA\f<0H)l\u001a\u0018\u0018EZB3'\u0019]\u0016n*ÖRsB:m8c\\R\u00186:\u001f[g\u0015O\r#B,n\u0011v?ǹ}cn_JKnb<\u0003P\u0001\u0012n.35bX\u0002\u0007a!\u0018l\u0016v\u00143\u001d^\n\t\tNojVnJS8\u001e\u001d\r>\u000bӰR&`C{,)QH8B<lV*'L\u000eG;\u0014ڤF\t[ \u0003\u0017~+V/y V[\f^d7Oֽ䏋b\u000f윋#V_~[:jrXc/!jV^\u0003E\u001d$\u0017m 8Oa}\u0011K=3[X\rlă\u0002\u001f\u000frx\f'yT\nYWjJK\f\u000fx\u0013\u001bp\u0011XpGjO&ZRIJ^\u001dT磉\tiV>2e5Qx\u001cqWc<.>*2?cI\u001b\u0017v/4P?\u001d%m\u001blOa7!3j\f^\u000b;:\u000eCZ+\f=L\r\u0015!Ee@h\u001d\u000e\u001e\tyo\tZ\u0006\u0010E\u001c*am\u001bףf\u000eӪk\u0012.sV©\t\"\u0000dh\u000b\u001e\u0010ې\u0019M,B4VaX!MF?q똱-\u0015g\u000birN6)r\\!\u001a45^\u000e7oz6фn&\u0015R̟\u0004N~%%^nC\u001b\u000f\u001b=\u0014\u001e*\"C@ Hyg\t4\u0018%Bcr\u0012%\u0010$A_̒\u0004F\u0004r\u0014\nD\u0018\u000faH\u0004~vI\u001cI\\#\u0016UйK\u0007\u0014=B7q]&0Yxt`O%a\u001flgtV\u0000S\u0012ɫb7v1XoG]\u0017\f\u000bM\"e-6\rޓTȞ\u000e\u0004Qj\u0007v\u0012!(߿\u000e\" \u001b([Ru\u001a'C5dK01i\u001eOk_\u0019\u0016G{庋1\u0012\u0012\u001e[\u000b\u0017'iXht1۔9\u001bjni\u0007v1R:\u0014sE@\ts:w9߰kc \u0014s\u001aam5\\l*\u0018hpxY\u001bfsb;\rmAOt\u0000\u0005rîndVHB뻈,{>#dW*(\u001ebq\u0014\\dGD]\t\u0014sy\u0013\u0019+MeD]]4}\u00147]\u0012{z{Jn\u0014\u0015\"0FHzބD?Ru1젃:֫?%i>}<\u001bǄց?V\rb=&kg1j\u001exeg$E\u0015TBIܜFNjA\u0005Ī\u0010%\u001a3d7\u000b{\u0005Y\u0012\t\u0004t6e\u0015ee~\u0016\b-W_-Ė2d\u0007u\u000f}*\u001a\u0012J\u001fjrH\tϜK\t$^O %uh8\u001eHGO%yb\fYelfP.S/X\u001cqZd\u000bqv|\r\u0000_DV\u0010xB\u00005\u000ewCbpd\nV\u001eH%\n\r΋ЈO:BX\u001d%>\u0016:#)}cy'W\u001b\u0004#l$\u0005w\b\u0014\u000b\u001eJq}ԧx#>\u001d\u001a^\u0019<e\u001b,|=앹KB\u0002Lx\u0015-\u000b)V\u0012P\r\t\u000fۣ\u0002s˪\tRo\u0014qQ\b\u001fw0\u0019эў懽&~/\u0011|:PŐ\u0004eU\bg\"\u001dbEaU{o\u0018z.xt\u0006mwbP=n|Hu?\r\u000b\u000b \".Yg~p,'Dv擯\b:\u001aua]J\u000f/\u00197\u0006$>%\u001cD\"k\u0007\u0017\u0018^g\u001d)a|\u001f~<!\u001fΒ՗܆*@P~\u001cQ3NIۺh\u0001{C{]{Jþq\u001f\u0014Ѫm\u000b<Ul\u000b1xOo+c\u001cVu1}\r'uWBso'\u0005\u0019\u0016ܟ_с1hA,\u0007aRǅlTIԾ\t\u000b\u000bO#F\u0004\u0017\u000fAOw\u000b\u001c'A_\u0016Vn\u000bN\u0017\u001bG\u001a\u0014c-d\f|\u0016cԳ\u00110Ut?*{4o%FR}:-\u001fW\u001f.z-8ìGZ\u0006Ͷh\u001a:|\u001e#l\u0018\r~C~ )L~Tcފ3Y4k2l\u000b}6\u001aSJ,\"hV~O`o\u0014;@\u0017 \u0005,\u001aZ>|ȉtKcvj\u001az\u0005(_M\b\u001f*kO/P=m6G\u001c\u0006&Zp7A#^\u0003$\u001dʆ\b\f9$u\u000b\u0010xJ5\u0006\\k\u000f\u0005\tsj42͹\n${ȁ4t!<|\r}㭹]ڃ\\j(j\u0018\b\u0014|+4*qI\u0003\u000bA}~a.ս{\u0001q\u000b\u001bPz\u0016ʑTM\u0004֩<t;nV\u00148@'<\\\\HX\u0001;<\u001f4\u0006\u000fx\t{/\u0013-\u0001d\\yx_)NIX>fqsC(\u000bPv*\u0010\u0004\u000e\u00041w?M>\u0014:j\u001cz\u000fYF6;q\u000b\u0019Womt,7m\u001d]\t-sg¸O\"9,3ffyQ׏N\u0018\u0005\u001dY`zu\u0011\u0005ZÔQޏ)2Hi\u00198|W@7-\u0018J<%\u001bb\u0003\u0015˕y\u001e2|}d78\r$\u0000)@o9_\u001e3M\u0012+\u0001F'\u0014\u0003Pz84Ig|z\u0016~dvկ\u000b\"˂T(\u0012H|bf(g\u001e\u0007\u001746Mh\u001cipTB/=\fs\u0003Y,;lQ}: k6|EPGK;|wk&Ը\f\u000e~r:<8j=[$̄Q1\u000f;[\u0015ۣ\"\u0014\u000e(9\u000eB\u0016\u001c3ᠹy^2#Cy,8\u001egav͗$m:\u0016H\u0011{\u0011aYYF)jo,Y\u000f\b@707I(j(Ar\u001b4ܟ~D\"Z5)\tV\u001f>1h SIdt*G+^\u00041\u0017\u0012F\u0019%rЪ>g_,\u0000\u0006mj(nTD|Q;2X2{<ˌcUa<ˌcgiZ\u0004_VO\u0014\b\tJ0Y\rƕດCS\u0002;1/\u001c0\u001do\u001b\u0002|4w2M\\X\u0018,@Mp\u000eo\u0010K/蹎/}\u000f_]/\u001d\u0013|'\u0011iڗ\u000e\u0011-F\\1\u001c\u001a\u0019\n\u001bb`֕GUKc8\u001c\\\tW=,sOTm\u0019_)+k\u0010\u00151xn\"r\u001c\u0003?ybgD\b)QEb\u0003I\u0015G57X\fZ [%hgyDC\u001d'OE\f8\u0013#cPcD\u0018=\u000e-.e\"\u0002-\u0016B*\u001aEQ/x\u0016iScmHDHbb$<WNГޕz~T%Z6$\u001a\u0011-龩\t\u0007F?Ůl\u00119\f#?&3|cq\u0005\u0017J\\#/\r(K9<E\u0014,z4ȳyk\u0019W4;w:[&,\u0014\u001b\u001dY)6OnO\u0017=\f蘸'\u000eJ\u001e\u001d\u0003\u0015\u0005јf\\jQ\bU\u000b\u0011\u0018GM\u0013\u001bO\\2Q5v/ M2W\u0002AhYOh/PG*F\u001a\u001d\u000b&r`.!͍)Hp\u001d(5I\"&X@ǝyˢÅ\u0001eه\u0000\u0018t\u0019|\fGw\u0011\u0019@AZ\"$_۽29\u0010\t^\u0000\\b{; \u0006\u0012\u0016ct,ZZ@\u0013қ΅޶пx\u0006vA\u0017-i\u001bR燽\ns9D\u000bcomɡ\u0000u@>wIߠ\u0000qm\u0012cjƓt^\u001ew\\@p^){\u0012h\u0016\u0011c\u000fC-\u0010smAc\u0015bVJ}Q\u0004If/;v{\u0010I\u000f\u00072?#+ir@,|q甔OFRW_Fr=\u0019#R\u0007W?x\u0011@=(!D_}\u0001HSSVWK\biRx\u001coa\u001f\u00158hv#]6]c]O\u0014?^[EK7;7G7d.\u0004(ߕ&Q5by\u0010o\u0010'ST*Z\u001bBl{娌?v\rp!pf\u00072A3\u0007\u0003.n_1V\u0014\u0011+{U.Oǃ4%j\u001dc%1ӳ\u001f\f\u001233C\u0018n\u0018\u000eׯ4m\u000b1bڛ0K\u0018,Mm\u0015n\u00156KSۜ\u0001\u0012ᥴv2X\fq*\u00106ʑk^`XrI2\n4Q!\u0012o\nc`R[WA\u0016\u001c*!3oq\u0014 _U`+OA\u0001z\u001fc{8=\u0019\u001f]G=|~\u00125ep>~y\u0017\u0003lk}¹h|\u0004 SQ&vR;ј\u0018Ԟ\u001aJn7%ؑ>態\u0018m.jjQ]̚\\cA\u0016:{uc3Zc\nڡԐ\nKIDIf$6$j\u001f\u0019_־z\"Q\t\u000eD]AϛHp( b\u001bKӛ2hQ\u001az><\b]7-cZx!8=2?e1\u0000X*\u0001n;SC^\u0014\u001e\"8HW.\u0011\u001e\"8\bs\u0011,\u001a\u001ew\u0005\u001cZ\u0017wvkp.4n6\u001bfA(P\u0011_Rz\u0013u\fސ\u00059<?)# 2a\u00032zK\rIV\u0001WYg^/H\u001bxn\u00139\u001fؼ!\u000ewLM\u0002\u0012m|t\u0007\u00030`UI|NKeDwtm\b\\D%A\u0017[\u0012\u0013t&0$<{FQ\u001d4\u00179\u0015&O1\u0004c/\u001b|wk\u001aD\u0006\f\"'G$\u0006\u001b\u0003\u0014@p.\u0005$1\u0015QA!jB\rs\u000b[[!\u001bT//*||aAsǺ\bx\u0017\u0013e0#Sl6a}M,0\u0015Ѱ]F~2Hғ>J\u0017SlLCf_I3F\u0017\u000bAm\u0003\b\b7d% a\u0006k\rZ\u001d\u0015n\u001a\u0003E@\u0019#c\u0012x4;TOZ\b!\u0004@ cX_L= \u0006c-bC6./\u0016\u0016\"r7Y]@\u0006\\F޼u|ݨ7\u001a`)d9o$\u0012T9+|f]\u000f\u0010\u0011\t~sמ\t\u001bX0+umϞ_C3YINk=|\u0017vf~8јUN&\u0016c\u001aY\\X\b\u001ey9#\u000b\u0013P;;}\u0016ܟJyA#\u000b\u000f\u0010и!\u0002F$@Dt/\u0017\"`D\u00184&x\b\u0011\u000b=AFȚX>\u0001\u001aP~7́\u0010ὯԳ,\u0000[8\u001c~).\u0018p7oV\u00156\u0015FveU\u0019Pd1GۿMbk]K!PBPiĒ-\t\u0006C+#\t'_ZY\u000bflШUkˆ\u00105d\u0005\u001epir\u00050jNK+W\u0011`&}\u0001K`\u0014K\u001dW\u001a8`.8^0\u0017Ů7x1xqԛhP} eh%yJ:\u0006eFP9꠳H]#\u001bݍZ\u001d!\\ox\u0003\n3z\u0000v\u001cOJP-\u0018\tB7v$$ƚe^\u001dp*,ͥ\u0016q,`<s\u0004\u0013z\u0011!3\u001a'.1\u0006ovO@NB\u0012`\u000b\u000f<DaL\u0005#GcW\u001eDPr\r%sBB1r;\u0014G\u001b\u0016g\u0003[#J\u001bF9* )}\n\u0004\u000f\b\u0007N#j\u001b\bC%<ZEO+GHVs]6E\u0002f\b\u001e-\u0012E`cQ*3#[Ne';ʚWWDo-'ң\u0010iP8#\rSYeI\"=ƄXqbF\u0019Tu>T*ڃK6fkhVd\u0007\u001d\f\u0000&\\xl3\u001bu3pcMpc\u0013&3?=ƒDMAZ(*\u001f \"D(9K\u000ba&l\u001d!\u001c$\u0011\u0019\u0014[Bp\u0011D-rt̓N\u0015\u0002GS.'?@c6xv$\u0012\\\u0014\u0017}{`\"^CRˡf-j\u0016i9B~jV\u0002`9D_D\u0007ڵz3\u0012ce_H/\u0018h_OH\u001ews7\u001fߜ4,#R>B\u0002\n\u0010Y=& is\u0005QeҤr^C5O?6α\u0010&7\fѥ#ܒ\u0003I-\u000b+t_uOK7\r2mИ&;G\u001fL̫mKp\f5|q\u0001q$m\u0007s6)\u0018*\rd^\u001eUm\\}]\u0010޼۽\u00187^\u000ekʞ1F\u0003F\u001f\u000e[y02L}\u0004\f\u0011\u0013z\u000e\u0010\u001a\u0012{Ksf\u0004;\f\r)Aº\u0000-\\j\u0018e\bղ9p4U\u001cMc~x\u0017&!QI+}y\u001b\u0001i齋\u0018)S|(H\u0004\u0003\fηGeYS4`z\u0017\ryu~\\U#K$sMdjg\r&~8w\rmIǝíLl\u0002;\u0012X*I\u0013\u0014^[L\u0000Y*dsJ؜c&ٴX\u0017\u0015&`\u000eA8\u0016\u0013e\u000e\u0005jF$G7эvPmɪ\u001b\u0010Crm!.r:j-Ϸ:\\B\u000f۰\u001a\u0007(\u001ffm1hjSj4(>\u00015aBk^`{`s\u0002+\tD\u001a9HX^Y\u000e5Ƙ\u0019LXճ\u001d\u0005Ўq4.Ƥ\u00157Ɍ\u0016\u0016;\u0001sJ6mL$E\rV,gr±fP\r81H&$b\u0012֘|̍9,gq0ZSZĜ8\u0006\u0001tW&椂\u001c\u0011\u0011\tҜ\u0011\u0004\u0002{`cW4:t:`\u0015\u0011\u0017F|\u0017&|}\u0006.LLF%М\u0002VƔE;}Y1 v\u0014s?^汚D>\u0011\u000e\u0005@\t#\u0018E>%4\u0012\u0016piKK=+BTnS\u000bE_n>hо]\"ZZb\u000eQ0e>$'υrf05\u001a$H\u000b3G.\u0012])dr\u001c/\nYt^\bE@6e\u0014..SrwXŗ.#\u0005,e#x-TSl˲55\\:bUp]cfJ\b8$R1\u001b{gh\fX\u0000\"[\u0015ƛ{\b叽+4Iᵐ0Gز}|^\u0005}l|' ݀LK7)_5\u0013;_ޑbnkUXm0/`\b'+s_\t&\u0003`B\u0017L.`L^Dh91+#G\u0016K1\u0013۸a5\u0006C^9o*Rh\u001f~E?e\n]\u0013\u0011\u001d\u000fR\u0001$턄``s؏%qΈ?@ܘ\u0011T. \"\tf4m\u0004&4Ch|1(2\u0001cxjlzu tp\u0019V4\"u׹\u001di,帳\tBNƍq#L-$9Eۧ6\b\u0016M\u000ep\u000f=a[ ;i45hN\u001e\u000e\u001bľ0*c\u0011S\u0018<wz\u001cR*gǹ9(Nb\u001f7N_XUG-U\t\n+KeS45*b[YJ,ͦ\u0012V'N8S\u00134A\u001f\u0005y7\u0003gSPYdq B5\u0018Ub)\u0010տe\u0000§C3ZKX|6\u0014 eE@#twN5#yH>2uy1X\u0003o\u0019R\u00122o\u0007k8w1bj,V_\u001f7s\u0007Z*'Ë\u0013\u000eǆT\b\u001e\u001fT,vg\rP\u0000ț|'S\u0019@ELd{Vσ\u0004\u001e=\fI\"U=8wGݬ;zYz8\b\u000eq\u0010VRe\u001cG\t\r\u0013=L\u00105q\u001bm\n$.R:(-\u0001e<@x\u0005X\u0005*A>-;s/֩~9$Ȏq\u000eL\u001c랐\"fX])4\u000bR߅?}@Mi`l\u0013ZYT1xwN99]XIA5xrQ!{õe<~ћUz\"\u001b\f5\u001e?Ļ\u000f/85\u001fd\u000b|\u001eqi\fK\u0000Ģ#^kc|GE?O\u001fs|R7ɧtx\u0014GQ?>\u001e\u001bi\u0019<\u0014-\bQnww \u000b-r\u001cyY@\nx.\u000e\u000f/\u001fH&\u001fN\n|xtH\u0011Y\u00065GrIȠl4c\u0018Y\u0018\u001a#V}\fM\n+?CpK\u0007)t\u0019\u0019&R .#+edP]Idx68I\u0002i_m:B\rߞ2UA01\f[ޅrch8\u0018\u0017!s\u0017b\u0012.\u0005m\u0010Bbn:\rIQE\u0001yَϧ58ۉ\u0018|\t\n $}}^\n-\n$\u0016݈9ɫ\u0015PyM\u0016z4G_\u001b);\u0014\u000b\nQ*Rr~\u0017PrG\u001d~+\u0002v\f\u000eVyZ}=A~\r\u001a\u0014\u0002\u0012z{ȼ\u0006\u0015@KTcz\u001dws9&4׬˩uEΰ{IӯǸ\u0007e\u0011-\u0015*sC\u0001r~\u0019?R\u001f%\u0007?\u0003y\u0010(\u000f4vo}K\u0017_o'J\\qO\u001eK'eu.ϑ5;ROTGFQ~e#-I@k~Qc?G\u001cU\u001e;\u0007\r/U\u000b\u0013QH\u000bKL~\u0004\\͝om/Y?%ȬM\u0012ۤSjXU&R(`'~y?]\bZ]qPx-~\u0013=\u001fg:l\u0019\u001e忄4v]+u\\(Goc\u0005vKM}R9P5\u0006\u0019Ip\u0006#'y[Ez#lH\u0010S+4G71\u0018\u0010AhI\u0010*:l\u0011C;|0\u001b\u001dk\u001b[VG%?D^'w\u0002/\t\u0013Gb@\"Xj\u0003tU\u000e/e\u001a\r\u001d%PeZ\u0007\u001fhb!L^Xj\u0013sKN:d·q\u0011b&pL|,%\u001a3f؏\f9\u0014Oh\tDrYq-2k`\u0016m.ϟ}[㧧ӧ6\u001fgO_ӵZzRvi-Fi\u001b{8D+7lɵ;\u001bA\u000fwU2i[?d`D\u0000#n0t\u001fLb\nu&?\u001auηKLaӸ6kFz\u0017l\\6(͋1q=';urߊxgTӛH.Ӡ?\\Oa\u00049ɝ\u000fsldXRqYѣ}Z|\u0017\u001eQ'\u001ca?16\u000bizK\u001aH\t[pGH[Rm8\u001a\f|c^T\u001e\u0001q쬬<&\u0007pZʃ\u0003^}p/KbDkcܮ\u0003\fG̻\u0004J\u0011lf'\u001fAÊw\u001f~V04zz\u001d\u001afi:,\u0003XÃ$J1\u0013ڄg\b]፨ލ\u00044ADxA\u0013n^ܢF5P\u001c\u0014jV7CZ\u0014󼟺*0¯֣YA\u0005S*\u0017M\\\u000b\u0017w@^(\u0002p\u0006Qt!/11\u000eDˤ\u001bN^mCM{\u0007#yp\u0017ria7\u0002\u001aqX\u0013]α\u0019H\u0007p\u0002\u0018ߟ\u0003s6%ޑdP\u0010\u000byKSD\u00113dF&̑.Es h\u001egP,\f:\f;\u0011I\u0011\u0012z\u0003}&\u0004lKY\bkeET-G!A\u001f\n\u0011H\f7\n\nGh`o\u000bJk%Ff;\u0002^å9Q5v\n<ׁ.\u001d\u001eFSꁈF\u0004AR'Y#\u001cNzl0>{`ӹX~\"V\u001b9I-*KVʍ\u0002_\rXWtP(nkE6wR:G0)8S{70\u0017kab\u001b,\u001c\u000ehN\u001eԉVV\u0013nؾy7p?u\u0010]JmIF\u0012`N~Q\u001cS6C\r:/\u0012(\u001f`7ǳ@\u0006y\u0010\u001an\u001e\u0002L\u0001\u000f3ApHT\n-8ha\u0018/p?> \u0006}q\u0010d]j]2?\u0002w3\u0018\u0005/MT!d<PC[\u001cdRL\u001c}9CRu\u0007{xוht'O\u0004@f,\u000e\u0015\"y\b^!BB_+\u0006+2$gI <\u001f$H\u0000sD@A߁\b¾F\u0002j$@9;\u0014H@%qAv|.&%vuc\u000f`xL\u0005H̯\u0011\u0004U\"\\\u0003Aa#\u001es2{Z\u0018]\u0007t]l\u0018N;R헙z*\u0017\\\u001f\u0017{\u001a%ӅaO\u001f-[R\u001e>M4ni9&E<\u0006JJX}Qו.>.#[u^1\u000bϵ:ǆ=\u0013cMy=4]r\f\u001f{\u0013`8V\u0016ƋkRZrqg+\u0019%l\u0018z|x\u0019x\u001a/\u001aW/\u0013Ö)~S]/\u0001Sk4~\u0001i\u0017\u001c*'_ol8Oaru:9a0\u001cZ\u0001̍lG2c 1/KndYn9::{h;c䅎pg?>n>\u00067@K|X],4\nNǨ}[o\u0015\u001d>Q\u0019㲞PRZ+Dy\nGp&z\tgI5\u0019b2\u00167v\u0018\n.cVc\u0016Vyp7ho1v=Eh[ە(cqcni{ \u0019lv/\u001a\u0007\u001c\u0011\u0019}&\u0010\u0018k9GL6\u001cv㊒:Za/Amk4C韇F.KڭX>6Q!\b+~.Y(k):H0:}d7l\u000e1\u0004פ3\u000bAޯz4ϧzΊz,PTO_\u0017\u0014WˎW&]a/`\u0007\u0001rx6Djп\u0006\u0000%/9MmkB~%y!<R\u001dCq.>\u0010\u0018\u001ac\u0011~N)4S\u0005\u0004U3ͬFlVtUa\u001d~ˆr'rTD1v'\bbE6S@LUM0GC\u000fz~7\u001c=ݵI\"*\n]î\u0019\u0004H\u0002)S'*%\bQ:1uIx0IѤ8bŹxփ\\TGSDo݋\u0014˂6BkAOɷ\r[׈1\u0002\u0001h9y~\u000b~7ǯq?7[욐NÇ4\u0010\u001a\u001f^}\u0002du<m>N_\u0006rwmw\u0010÷Q\u0018\u001d[}\u0018aǭUڱ_Ç\u001d\rZ[Fc\u001fJ%Č\u0016D:\u0007\u0003ԚBæ\u000f\t|@J.EK<^gr\t\u0013y5>RiҔMR\\kro\u001f?3y\n2\u0005'k\u0017Sio2-QX\u000f+\u0017~}e\f<1\\JXDNH+D\"Mb:&s\"D*+\u0011\"D.\u0001\"0.QRfO{J%B$R_Sz[\r\fb\u001ay#\u00125\u001a\t0\tl&\u0011\f ͋\u0019B\u0002^\u0012s\u0005\u0011\"3%QG֦\u001dmrp62\t`\u000b)FHO$e`ܰ9o{V ,\u0015)\t\fM\"r9\u001c\u000f/L&#Ҧ,m\u001fpL*\"i2<\br˭$2\\n-U'e'\u0011F{NK䳔$_\u001aM.ïIJ\b{-\u000b\u0011U@?\"\u0014;R'\tfi\u0013%\u0015춹)B$ݞL1Ƴ\u0001{C=\tVho\u0014H\u0012K=ur7v43\t\tVq4&5jSrwB*\rd\u0004yc\b\u001c\\)ϧ9sM#e\u0004.\u0005\u0011\u001aK\u00143+\\*Cv\u000et\u0006\b\u0000$$\u0006?2Y=*64D]r88Bt\"#\u0013\u0011\u000b7OӏS笈($4lqKwI/p.R\u0002%\u0010Orp+bOj[:M\u0004Sb\u001bz[\u0001%<]L\u0010\u000e|nk\u0004,#ߑ2V;Qm\bp\u0005\b\f\u0011<\u0004\u0003N\txJ*#\"ȶ)ƥ\fin9\u0001'\u001c\u001c\u0019[njf.)ɧe\u0006V^I][lF\u0000+pR2BS:\u000b\rԁ~\u0004)-1R\"f\\+\u0003K\nV@9\u0006γt}\r\u0002^5\u001cls`09cvaä`\u0000~$:GIE7\u0004\u0007DAJAJ11JIRV>Vr\r3#<W\u000b^{\u0016\u0019\u0006\u0015:8!8WQf\u000f(f_2#$\n@\u001cOM\u001c\u0007\u0012\u00122\u0010\bH\u000bt2\u001dsxkBocw_3\\ݞhdQ\u0012\u0014\u0013\"\\AP>,y\u0013\r[J\u0001V-f\ng5\u0000Q\u0012\u0005\u001a\u0014H)\r?xR &r<P\u0010.\\PkU\u0019t۫%v$w\u0002\u0001}_J<N~\u0016`Y>\u0007{\u000e<p\u000e\u0013R\u0016x\b-\u0007\u0002I0MH,4\rHmcn\u00157L4WOrN\u00135H$ũ?,\u000e2h\u0018%2\u0012\u001831f,c$\u000e0,aYeV&03d\u001dg ׂ\u00101F\u000e\u001d;\u0005(f\u0005;(\u0011N\u0006\u0002\u0018 w#c\u0004B\u0011Bƈ\u0018#\u0011uk\fcw\u001aƨ)2F\u0017s5'$\"#\u0010\u0003\u0004)\u0016T\nȂ\u0006)Xtskh\u0003\u0005\rF7\u001181\u0007b*\u0014\u0001&Zh1@A\u0006fpg\u001e4\u0001\u0001sYIkC.\u0001%I9\u0005\u001c2Ok\u0003N\u0000\u0017\u0001OR@̗$K\u001dhZHa_\u0010:3RGn\n>+?%%oA\u001e@]\u0018q&u2j(U\r\u001d\rǩR]n-N\u0018b .\r\u001d÷\u0011\t\b\n4|~\u001b>֒'>ڼYyX4)\u0019/\u000f_K־?iTw{<}\u001a`g\b =!??q|0_D:\u001e\u000f1\u001a?}\b2mT%o\bNH $\u001b~=_\u0007xz\f\u001e\u0016?ŐnwNyBT/\u00139e'S°r_!%\u0001JȁN!d͒$$4өmp\u001c0}\u001e\u000f7gA\u0005aA\u0002sfZptkmp\u0010ǶܻؗRmG\u001dRƪA_ t%\u0007LJB+ڻ\"\u0001R۔6eFJڬ元3Ź?\\/\u0017\u0013@j\u000fm\n\u0017CSҦ\"8i\u000e_\u0005]\fY\u0018$x}SY\u001fĂvw-\f\u0013S\u0014&FޭRaEZZ\u000b\u001d\u0002ԑ<Lҹ69jya}٘w٘\u001cdp2sNƯU\u0018uS\u0018Z\u001e\r\u0016iK'ĜDBNL\u0000hm=\rt\\>S6֬Myʘ'LZa_sgs\u0016,D4^\u0001QZzjK\u0007/'\"U~fҤne\u0003\u0005ċC\u0019xVmi-)\u0011ҤIVwy\u000e\u0018^%r)tL\b\u0016RmiM\u001cDPhҤ˞f\"1\u0003\u00159f')-N92,MyFzTwM\u0013\u0005\u0004ZJi%x\u0014t<kI\u00178/.ʖ\nO\u000f\t&1V[\u0018RnQ%DC\u001a#kA\\\nYV(\u0003\u001c##X7^`JteAy\bJ\u0013#S?S$C_jFT\u0006ȓ$~Y\u001a(Q\u0014\u0003)^(i5DDIsQ͚]+dXaP\u001ay=W\u001b\u0019\u001e\u001f\u0012I\tm̏y?A\u0016Ӽ\u0016O\u0012\u0002!9Ǣȴ7NL\u001b\u000fE.r)%\u0007o$\u0006LI\u0013\u00120zҕ\u0006]sؕҹ\u0001q<v\fAik#U\u0014L\u0013,RKZZOmGcZ䙨*G/\u0007\u001ca0}[@\u0010s\u0018ԑe4[d\u0005\u0019j61K\u0005[cjS[:\fjM6Ҭm1\u0015awI\u000bJN9>:atUMSiߚ-J\u0001\u0010SSt]ij\u0013ת4k[P5\u001b{ׇV>t:._\u0006c\u0010\u0006\u0005_\u0003=G\rQԌהV\u0011?7-Q>E(G\nڴΜm\f\u001e:s6Gy(3gdFͯ\u0011\u001f@pt:\u001e~<}ϓ=\r \t\u0004z}Z|\u000b['\u0003A\u0000<ܗ\rendstream\rendobj\r48 0 obj\r<</Length 65536>>stream\r\n%AI12_CompressedDataxks$ \u000b\u001fx\u001fd\"#NvfvJ\u000fSK3'[kحZU\u0015k!M?\u0002d&HLXw1=\u0001\u0004\u0002p;_\u001fo_'7>삠\u0017x˧\u001f\u0011~u1\u0001*~rӛ?klۋ}ۯ.~\u00157oo\u0017/.~?n_]ϻ_/o|#.7j\u0017g/_\u0003o\u000fhrbr\u001d迿iaLCA|\u0002Mlt\u0006h{Ͽx'x~v/o_n.\r^\u001775{\u0019۷ͯn\u0014b}uWo_v0n>_\u0006_7o_˻?z\u0010쾡'\u0018=\b/\u0001ϟa8k_?o\u000e-wo\b-`Wǻ\u000fn>\u0019z\u001ck\u0018/c\u0012݇\u000e/Å\u001d\u0003[jkQ\u0017c\u001e.ǘ.^`\u000fm{p\u0005\u0006mn?[_3x?\f_~7W(<G{}g\u0017~{CSCel\ng_>ӆ\u0004X7\"_}1f*\\x*c\u0018\u0003?L\tOg`؟>\bV'%7߽y3\u0019f>yݖ9ً7E!|^^\u0001k\u000e]_~\rOܽ{K\t7% {woo\u0005``\\/wo?A_@3J_n/FV~_>]>WW߼}{syկ>\u0003^Z\u00167\\zy#`Ƿoo7+Z[nz5MpoΛΛZ=uo\u001d׽պw</\\\u000bWҪ/ﾻx\u001a\u0006x{{\nۏo->ݾB㗷oo?_}3OW|\u000b/݇\u0001I\n[W<w_~{]ۛO2\u0015\u0001û7￴J}^=oo7ow7^}y_\r\u0013뻿Wooџ]@\u001dB\n\u0018\u000b,0\u0003\u001dpo?o<\u0013@|7Պ\u0017c%&\u0010G޿!]ݾ\baS}ҷ\u0006g7y\bR'տx+FJ;Qw7\u001e\u000f׈ mm\u001d }t\u0013Zu(^1fv<5`/ztE\u000bk?}_ssz+\u0005\\k\u000bGw T\u0015m\bҼ՟woo|}\b|Wnݎ(h\u001f\u0013p47Dv_ݡo&wƟp5jZ?\u0018hv\u000b2җ}a )`I0W\u000bmO\u0018\u001f8\n\u0001\u001e`n[\u0012޼\u00166;R\u000bE\u0015,\u0007X_̘G\b@>yͷ^#!ǻ_^\u0001z\u0003=~F\u000brw\\+ O/ƒn>@Q|}\u000b\u001dl) \u0005w \rX-lo\u001f~sN<4\u0003\u001b\u001ckW\u001f\fIy\u0005~w_>w,\u001a\u0003Gx{?K__\u0010e?|u[Zs݇\n}y?o>~߼yo\u0006^`w\n+D_\u0003\u0002\u000fN\n0\f@f\u0006v_c\u0015J'\u001f/\u001f|n?\u0005LPP~\u0013$0\u0012sOڇ\u0000?-\u0001\tĦ7\u001e{}\u0012v\u000eb\u00119z]ç\u000e\u001b$~=\bl\u00015 _|m{\u0001O\u0017_-OTa@ӿ\u0017/\u0010F\u0017/\t3]:\u0000Y\u0000y}X\u00032\u0019V\u001afB\r8P\u0004`>qL<X\u0015\u001dwP\u0000eq\u001b\u0018mmk(\u001b\r\u000ezvǻa$Ԑfi&je\\vŭm\u0016]\u0001\u0006j\u0007\u001f}\u0017W~7~w:\fa]!\u0018RȡUXM؆]\u0003F2\f\u0003L\u0002\u0006z\b\u0003>!C)0c+\r؎fl86c-\u0018d7\u0001M4\u001ddXt40\u001ac+4hxlxm6E\u0019Zbrmh`dxpx`\u0001\r!,#/$,,&.'/(/).*/kE.\u0007 \f=h1\u001dΘ\u0019L\u0011\u0007P\u0007\t1\u00143\u0012Wq\u001d7q\u001bwPaF>I0̘R&NMt\r\u000bba|\u000eKsɫΛ;(eURƒJ.ڔ\rmٕk\u0011\u0016\t\u001b/\"<'\n?f]V׀-#.\"_\u0007K+K /@Gdӡe{㞎ȠiN.zެ\u001aX@1\u000f+\u0014ah\u0019dYo6f\u0006*7\u0002κ߆m&۲]mvma猀\u000eP-%[ֻnqW!\rC4d\u001ba^{e7+B;h0ON}{e\u0002k]f%JqYYfVd\u0012k.q2JRM\u0018\u0004)IR\"e%e-e#e *\u00131111111111\u00062\u000e2\u0016\u0002\u001e\u001aAEFFFGBH( Pi\u0014'Eql2p]KVF\n\u0014)YJ\u0012zy)N\"=q\u0018\u0003\u001bF\u001fd\u000f\u001bX4\b\u0001ըAP\u0016Drы7^\u0012\u00183\u0002]\tyXkoND}ڑ@X9ͪ\u0012d\tK\u0017J%b3/\u0007 SRa\u0015:jTR\u001eVWeyv{\u0016\u0013_y3ȳ0Y@(\f*z)))\u0013\u00198\u0011,Pm4]\u000b5\u0001\u000bIU\f(B[\u0018\u0007\b+\u0011/\u00113-]\f\u0002QDX\tSUHX\u000bEK&]\u0013\ns\u0019X-͎l%}\u0003c17O>+W֯_\u0016\\X\u0002 \u0019@\u0000\u0003X\u0012\"P\u001a@y\u0000%\u0002dP.@`Kd\u001a\u0014\u0010F#\u0015\ba]|6{\u0016)PyXʹ\"\u000eHV$_FMFO..FxYZV7$lֲI\u00161z\u0010X>䀶\u001c\u0006SEs-/n'0;\u001de'Fdt\u0000v`\rM\u000bt\u0000\u001d;x\u0007\u001d\u0006Vd\u0005a$\u0011z0:\u000b\u001c`Ļ.\u001e;\u0018\u0007:Mr2|R\u0019q\u000eK\u0015:c\"\"Y;3&!iщ]Q`k&آ\u0001\u0002i\u0000\u0012\r͖aG\u001e\u0007]; \u0005\u001b\u000e+ \u000e\u0019DI&&g3[bYXGK苑dFsr|V\u000eK\u0015d\u0002fEnH\u0003<XH\"Nok*H\u0014\u0000Kȃp3A]\u0001\u001e\u0001[5\u0015\f\\\u0012;QTEzI?S1!ƽǔ\f9\u00050 >r\u0013a-f\u0018<+V\u001cY֓9\u0001 Dw\u0012fe\u0019\u000e\u0001Ե\u0017x_$(T:\nBiL]`u\"#5C\n+o\u0011\u0016\u000fD±c\\\u0013\u001axh$\u0010Q\u0002`\u0007j\fkpY\u0003-0\u0004bLX{\u0003h\\\u000fmww7W\u0019\\\u0004.^Y\u0003q>9\u0001\u0013\u0002\u0011G<\u0005\t@\u001df\"\\t%:\u0005.~`BdyC$\u001aIu!\u0007]Љ~\u0019F\u0015pz\u0012\u0016%ZGR}\u0015\\0ԋ\u0004B8`5-\u000f\u000e\u0012NN\"6X>\u001b\u0018ޞ\u000b£SwO=\u000b>8\u0019T2bal8r1:\u0018Wr]g4j#\u000e8Ǐ;.\f\u001euΑ;\u001a#;tfUE>tG8KN9-Y\u0018\u0019\u0002o0w3zs\u0006\u0019\u0000\u0011Jp\u0002\t\u001e@@\n-\u001dWtOttrzn\u001b%橈\t\u0012ĜBNE5fbX!2ꖨ)l|\u0006\"H-\u0007[\u000f\u0012̒d\u0018,I\u0006,\u0018h]d\u0006!L*wB&WD\"GG\bN\"\u0013$\u0011Bv\u000bTp鷊Ad\u001e\u001ely\u000e~\u0019\"\u0010?\u00193yϟo\u0001\u0004'\\FY\u0016TBS\u0013+_$wSqoU\u0016j.c\u0018\u000f(h\u0007wA\u001ep\u001cpKX\u0010U:g\u0001~ͻ\u0017\tb_\u0000tx)L\u0002X^\u001d\u00103QtÃ\u0013[6Vk,[\u0015.\u0018\u000bJD#\u0001g=1Q!\\\u0015\u001a}l\u0013sN#ǐh](\u001b{%\u001aD{YIl4\fA`\u001c~t]\u0012Sqj\u0013~+#kN^<)\u001fJc^D&\u0000C׮\u0013s\u0013׌\u0016\u0013\u0004\u0006Ph$Jnjдǚ\u0010\u0001{ޣv@\u0011?m<\u001elce9c\u001em<}\u000f{GHYF(\u0012\u0018EFe^<w5}6bATG`)f[J^(iV⤄V[{ǆA\u000bH\\ԒLf\u001f\f+\u0012NXlg\u00006hu=,@v4(<~M2-̟\u0015I腬lhd@\u0012G\u0012;#鑮UrҠ\"\u0017%\u0013\b\"ǳ$ϲhp7UsU7X\u0004N\u0017=ߒl/݃lo\u0016^zUgyA7$ʳ j9{!\u001dd\rdu\u000b\u00005\b艄s+Jjz\u000e_]S;l)@z̞k\u0013\u0003Ԋ]1*9eM]\u000e]\u0013/3q\u0007]Ś\u001bYohgH;YC5̾+:sQ?$%ڸy\u0004\u0019\rkŊr-\u0016X\u0001d=]-`%\u0000\bj\u0015\b2Lg\u001e\u0018\u0004\u0016r@-\u0005j+ւja\u0012vğ\u000ea\u001cy{V!\\oZ, \t2)yVҬI\t]\u0011\f3qs8ws[tw:|ͅƺ&-j\u0015J*^\u0006$Ur\u0014YQ$D\u0015\nעo-F$(jW/2\n{*x\nuVU\u000bk\u0018\u0010El/E\f\tjU\u0011կ,td3T.C]+He$\u0019\u0010ʒd\"EҨ4%I\u0016BI,\u0003-D\u001a8le iM\nw\u0017~\\yAe1?\u001d\u0014sZ5)'xEn^>h\u001e)\u0005?jY-W^!ǈDV¬L\u0005>f3+Z}-Z@2U*URIK-z7MEk99FJ{z\u001f֟v\u0014A*1\rnb㴕͗H/btށ>\u0017\u001e\f8i3+5\u001d\u000bu<\u0014\\.\u0014\br3Ol8U]6qLSKʧiQ\u0001<kpD')9D#\u0000S\u000f\u0003sw У\u0014I#a\u001aYB59FH:,\u00194o\u001eXH\u001e3\u001f\u0007ҙOm46CJ\u0013\u001b0\u0012FžJ0щ+Gg\u0007wLF#5N;3h\u001e<t\u001a{\t E\u0016l;\u0002@Ku\f.\u0016L\u000b;\t|\u001e4JzC+C'o~\u001a\u001e9ܐ\u001b |JKv\u000e\u0012hb2\u000b2\u0007㻆ٮj\u0010\u0001?xi4k\u001e\u0003iva>Z6}1ӯ]>L=m999C+D=\u0012P5R\r\u0018H/\u0002Q\u0015шk\u000eH\u0018(\u0018pp\u0005\u0012\u0000a\u001b\tР&k1s-bn)g!ȟ.fӸi\u0004P\u0004?-\u0002HcVA@\u001a\u0006\u0007\u0002Q0@\u001c\u000f\"ZLZJ>2F\u0007\r\"KxD\b)ҽjRJ-Zgޘ&ݤ̴IatG\nS\\\b3cϋ\u0007I\u0003\u0001\u000eSy|\u0017w\u001d\u0014$\u00024aI2؁l\u0003\u0005\u0002͔V\u0006J\u0004g;!G\u001c\u001e\u0005p\u0016L+*`:D'\u0010B\u001cL]e\u0001\u0004\u0006<\u0000\tH\u0000$\u0006\u001bܲ5\u001dj$^hv\r\u001em'=I\u0000w&J¸\u0012ʽQ6+WIe,d\u0014!E-HjIWGz;\u000bљt\u0007v\u0018rИg\u001bbA\u0007\u001b\u000e\u0005}H_<r͜VmO-0\u001d6\n\u0004I\nuC'\u0016>\u0019V(-'d1\u0012Y#1$\u0016^]5Z\u0003-+wrDS'#}(u\u001fF}]9nE\u001a_#Dce\u0011op9\u001br\u0019Z\u0004AYD\u0000BD#TYu\t!t\u0014È\u0010\u0010e\u001d%{EY\u0004\u001f<_c\u001avشQG\u001c\u0018@I\"\u001d).a`\\H[1MM7ܦut\bKT\u001bKԀ_8\u0019\u0017t\u001a\u0018\u0017l\u0018WBy^\u0007ُVkeVhoEjOVðJ\u0014\u0016`\u001bKiVO<YZ\u0014W2}8`9O)j'=Yy0q\u0017Ry.'dW}Z\u00178՜+5x§Ć#b\u0013׆+bҙ7 `HVP䬂\u000bd7ɧuW6\u0015m\u0001\u001bU*YCʅ)ܰ\u001e3AuiE\u0016SJ\u001d͎s4\u0014\u0006\u001d\u001c\u0007)R\u0001lb\u0006RBȞsj\u0003\"-qbǠ\u0001%\u0010\u0012`ܮ\u001c1<-?\u0001>fi\rS1\u000e\u001f\\;\u0010|fQ\u000eH\u0016J:\u0005c^\\ sӥ+ee\u000bf\u000bĘ1f;Sg?lIɭ0JX`f\u0007\u000fayx1G>cHrYG=U#dseҔ~\u001bZ\u001aY.ֺҥ54&f]K3lM\tNHdl[~m˷1_k_ƇD.\u000b13tF$\u000fzJAc\u001eQ$(Ǒ\u001cr\u000f}\u000fg93\u0012>{qu\u001f\u000fA>\fDd9\u0003{@\u0002\u001c#t\u001c\u001c\u001cCc<IąT\u001d>wtxb\n҇f.џxq\u0000z\u0018s|\u0000C\u0001\u0019'x2s9\u001f\u00055CHW[Lص\u0018\u001eCF,.Erw\u0011?\u0017ݵ%.\u0003O5\b=d\u0010\r.Mktj\u0003NB:bj4_kRw\u0004DS~Fi:#\u0003:sFEEG\u0014q\u000f*\u001dtxVh}<agYV\u0017?C\u0014</k1'P1e\u0015\u0014^zE.ܗx\u0006\u0005YCw^zV/=~hҏ\u0001;|&a$완\u001a:<ws\u000f\u000eGP?k4C6M\rh&!׌[qKt\u000e5K>B\u000e}ͽ5֋5&Rյ{\u0017<hC.9X~3̟Q\\~\u0019mψC'V$:\r4L\r,;H${\r\u001a7(Y\u0003\u0006\u0010XF@3\f 4\u0005r31Q)\u0010 \u001cc\u0017z9Sx?'_Н\nݮp\u001dW\u001b\u0015\u001cMa&{\u0014%\n\u0012+8Ca~z{\u00048ݛ05ݙ0tG캄T/F}\u00126⢫\u0007ϦXt(>wY]0\u001a_;k\u0011ukV\u0004tqE\u0007QD@V\u0010a V\u000e!,\u001ch*\u00049КDۥ\tzau6]ҥ\u0016r65)5㛙[\n{e~[@k!hMl\u0002*j:5ؠ\u0003lޙw='ޛ\u000bwj݁r=\u0001Y6PBu\u001fR(/>\\}hN|zvx.qrY>u)Jk\u0012taJO'+\u001fy\u000e:|\u0013\u001d>w}\u001d#s\u001a}D\t`\u0017<@S6-\f\u0014koy[v'<'󴷚k󴷚dVs׼V'9\u0007ɝZ\u001ebyPf-n)r舯f$Ҩn?\u001dL-}O+Ԋ9\u0019b/OQ\u001eŽ}/y\"v\u0019JFHԛ\u0019\u000eɴ|9x=ҡ;\u000ee9Jf>`}4.e(fя-ᐳ90~nӜKY Z\u0012Wզ&\u001e\u0016\u0012WOVOSV\u001f\u0004}2j!ē\u001c$ќ]\tr3t\u001e\f\u0010ufdU'DvJ\u0014/z\b\u0015vp\f'o\u000e2( V̤}ŜsI(~ֹӼ-:\\\t9ZR_Ku\u000bTҩ[@ؘ\tքq;B\u0013\"%B\u0015ݙDHrMha\t\u0011\u0002-}^hEGZCOhV4j:8~xJלp?z%˗\u0003\u001f5cf~_f\u0004v}\u001c\u001aFʔޕ\u00126بRF_+mXsJ\u001auWJF.lMrq\u000blgʰ\u001a\u001bS\\FevD_W[(\u001bV&X&\u0004XЄ\u0005K̦\u001dl_ݶ'\u0011\u000535tms\u0011tE\u001f'LʾͿ~Lߓ야W\u001aa>-7o\\0:\u0012Sy\u001dw/\u0018{ԥ뉴26\u0013jeL\u0019x\u001a'M~V\u001c4%9x{9OP}Ҝpot1?aLRHkfC#qg2\u0007}gzaP<<z\u0015ͬow\u001bm\"D̓9rW/qMe҉YefU/WU\u0013zA\u0017d:٩\u0017\u0002S/*Bld&bT$!QL\u0000\u0012+\u0010y\u0005,3r\u0001\u00131<ԋ8Hz.(r)J.\\\u000bW\":,*Q\u000f\u0010if7\\/Knb&}avN/ $Mt_/i\u0007yYV\u001eT.\u000fLj\u00179ϣ?$pN\"\u00042xv\u000f4\u0007Z1)Ә\u000bS3ǛY6gp('\f\u0019\u0017\u000fJ\u001dY5s`\u000e,%\u0014K{h\u000f/y-s/uL\u0012{\u001cÒ#\u0018ers8\u00043\u000bپY 6>\u001bI\u0017\u000f5Bc;f[fYRqǣEK1\u0001\u001e.K\u0007\u00102\u001e\u0012C&K\u0018>怐$i\u0002\u001d;\u000fȍ\u0005}|ƀgs\"NhGG\u0000yh\u0011q Cls\u0013S\t6U\u000ex?\u0006\u001cl\u0007ĺ\u001eq^3\n.k\"\u001e\u001dnUw\u0012&\\\u0018{8\u001d\u0017Nbi6\u000b1,>i\b\b#\u001f󵜩3E/Ǒ>˵r\\,>˵rM\u000e+֕gʳuٺl]\u0001+Ͼ`Ͼ`Ͼ`Ǻz\u0005{\u0005{\u0005;\u00179B9B9B9B9B9B\u0011*&gs>)\u0010!<Cx·ΧG\u0010yK?\u000f֏GCzõ\u001ee\\lw\u0015\r\u0011\u0019=-'PT@#\n'Z\u0013C\u0012dڝ{\u0012\u000fs_\u000b2_&/y,1xiDf#U{.\\2\u000fʘMG.ֿfkv?\\\u000ec7:uv卋!\u0007*?X(&gnUZ\u001ddL5J=P'\u001bӔ7SZha+Y\f3x{\u0003\t\u001cF\u001fmȎ.<Oxa\":!#ӈR`\u0002\r˕\r0\u0014a5$4!\u0007J\u0006XF֧\u0017I\u001fGG\u0016/!t\u0007|GGSxI\u001e\f;R(\u0012\u0003IB;\fC\u001eA;\u0014 i=Vcd\u00076^tqak\u001e;D\u001f{\rdtٛHR\u00177Md쵑>HRWKV$uuF\u0006ʋ)fi%j$V\u001cMV݃tuEhkte}\u0000\n+\u0011q#EUC(]juU<[mS̳\u0005GU3Y\\uδ[vQ=ׅW|ywuU\u000fMoWu>\u0002RZ1@\u0015^hE8ݱ+YWݳ|ת׆Ut*k]e0{+[=[X\u0005b0}lf[YM\bbDbӵg'\u001ajToj5-qA\u000byu;\u001d\u0005lhͭƆA7~6*hpg\u001e \u0018\u001c5:uv:tif\u001ds]gɬ3R\u0018H2\u0001\u0016\f\u0014\u0018sY'\u001c=˞qRɸ(ݕY?7\u0006\u0017]b\r0Pe/\u0000Á'h1{я9;~b\u0016\u00187fBsFc\u001643C͞_Lo5;fSﳙ_NffQM^f`\u000bF\u001a61M:lY\u0013KDN&&\u0019IF,<8 HzڐgMw\u00141'\u0012[dqd$ڐ\u001dhG-lT-\u0013)\t\u0006\u000fk8\u001d3g9ې Qs5xӣu\u0016\u001fZ\u0016\u0003~*11\u001d\u001ek4Y*Qnws/\u001fe\u000b\u0002b:\r1F.KV}\r'\u001c֠⟏YǬbu\u000e\u001c1-lg\u001c\u0011;\u0018#jCx&Gc0<H\u0010E\u0011Z\u001c\u000eys\u001dN|[N.=\u0007nN.b3wce\u001eH AKe\u001enu̢\u000f^8¡å\u0002\u0017<ل\u0018NVmsjaTpzV5⃈R\u000fI|Vm'\\OtN5(T;UTϥH}=rԣT_Rcfvxꦵ\u001eEz\u000eyS\u0005x뚆*Z\u001aE\u0000$qTѬTi*V\u0018W}`%rAyT@9G9E1\b:9\u001cA\u00149ǜ#\"i\u0000f\u0013\u001c76:n|<ocsyMTm]jT{UIvY\u0017Z\bѤ9;K%U6jdZ#QmjTɚLmeL55(f;PԮZG\r\u0001TL7Uq4e\u001aRcNP\u0016G&!PYF[?w:zN;\u001e\u0013?N3\u0011URT@)S4\u000e4\rO>͓֥!د\u001eL\u000bjǶ11KL\u0001\u0014\u001c\u0011\u0016@*p\t὞)eMp\u0019 IiJO\u001c\nV\u00028'lHKe{\u0003ڲge\u0018O6x\\\u0010KY\\r9v>wnx:Ċ?73-\u0000{QԽ5_uđ7Y+bɎvN5\"\n\ri4}J\u00026\u0006ss\u001a%G\u0017\u001b,ًV\u001c-:;5\u0014\u000f@uQH!\u001dH-\u0004Z\u0014gQEQ\u0016\u0005Y\u0014cYE\u0002,6\u001a㪢\nzr\tغ_뒣QpzFQ#Q c)zg \u001aR!yw\u0010d[Pe\u0015KJdd\u0015PZ\u001a\u001bC\u001c&!̪Mj\nd=Px\u0016k!?dm%MJWV}1ǡBFZK,\u0000w)\u0006\u000fOYvw֡\u001b2v\u0001\n+5tLCғA\u000eǱR\u0014<\u0018뱘h\u0011H|ځxLG`\u0001ߛ\bU|7>ŵ\u001e!>\u0017n%;mS}]\n\u0019!C\u001819b$\u0012%%ML@\u00112/G\tIbNuF^8x\"eF(\u001aӴV⬤Yɋ\u0005jVe\u001c\u0017SK#tfL\u0015FxѪ'ВH\n7VU\u0004lM&*6SE\u001c\u0007ɾB|\u000fNI%]%ALSV\u0000U1tR%2,iBY\u0019qYl\\=Daĳ}bӕP4\u001cI}DhBe8F\u0016?P}jDFK<Q\u0012:)\u0006\u0011FH\u0016aIɆ'\u001d%\u001f;\u0012=@C!_H'J @ԁ%\r$\u000bL\u0012\u001cE5o&\u001eT0նvg䅥&0-\u0018&ȑ \u0016~U%yw,PgHjy[Ki^UeIAy]&cBl8'\u001b1\u001d\u0007i>BpMN 3\u0003Z2\u001eg̲WVbxb\u000ewaf8i\n\u0018_`i'\u0018\u0011.x9\u0000Q\u0016~1\u000fqD\u000bq\f~nƴ}^\u0017vt\u001a}J3\u001c8W/\u0000\u0014ڙ\u001fK\nу49n\u001a-Uņڞ\u001c2\\º\u001c\t?f/ͷD\"w^EҚ\r\u000477=\u0017\u0019`(af`Z4Nb-_v7Lٓxy:k;H\u001f\u0015J`Y:4u\u0018BG4'\u0018o\u0018aZs\u001cSjsiHM7x<4/Z98\\&{\nK+Lv$OrnI*hl\u0013ȡPk9!(y<F\rF\"@;Im'T<\u001cqOLL2_|4\u001e(+{Roqq\u0005޳?>\u001bU\u001dL5c(񹫉)XB9L\t\u0004&67Qz9\u0013L9`\u000bye\u001d\u0019\u001al%edѻY\u0005W>br1u(fi<).O}4kqV6{j9kf8D#yz=I6y{\u000bd`9\u0001-0\u0014OFqqĬ\u001bT%\u001d\t\u000fh\u0019`\\\u0018=\r\t\u000e2ӈb-Vl:L\u000eq\u0007g&X\u0019t1p\t4\u001d[f)U\u0014gY㔳3']v}l\u001dG;x΂t#cٲ#&\u0000\u0019a\b\u0012]\u0002r\u0019icm\u0005Bȅ\u000eEaL\u0010'\u0013h<>~Vsȴ/\"\b%\u00189Vab>8,9D4e:C̕\u0006N\u0010Y~a\u0005e\u0019V$e\n\u0013gBdW\u00142W.NH܍NSPw܂*;=JP\u0015\u001b̫\u001eЊ{4وOESM5\u0010w[g\u0014rm\u000f'\f~/\u001doP4\u000bwڿh\u00124],F#\u001d?hx9 \u0015%\t>/e\u0013=\u0012,=A~\u000e\u0017\u001d[\nϥD\f-͵\u00112l\u001e+R\u001d\u001b7DɲXG{G\u0014\u00123[ֹ\u0003\tZhqz8>aC*{ǣl\u001fd~HX>\u001eôGoؿ;cj&\u000e3p5f\u0019c\\a\u0016\u0013\u0006iVL\u001c(ee\u000ez{-\\;uJ13\u0006b\u000e\u000fdi`>ޖLm-\u0007_9vP6v뚏ow(wQinFEJZ^/SR[\u0014\u000fݡpb ȫ|$K_RJUSdRq5KL3\u001aA\u0010\u0018\tie\u001e=\u0019\u001f\u00049Im\u001bNrcxRI\u0017\u0007ʏ+f\u0011\\\u001e^c\u001a?w\u0003u)c+ϖ\u0007CI%%\u0013\t&7rū&\u000f\u001dR\u001ftg\u000eM772K܅I*9\u0018'qxn[q\u0019Vt]#4JO#$ZF\rUe)\u001dm\u0006'u%OJ9-u69|p^N\u0013W\u0002Hw9<Ey|[K/\u001dq;Kɤx%\u000fᐛ9M\u001d\\\u0015)@#\u0000uD!YPNk1eb\u0016@dZ[Nc'SY\t\u0016J\u00063s+tqł\u000b\u0017\u0006\u0001x\rɥ\u0001_\nȡ_4ֻo9(\u000eH\"\u001c5ֻy\u0018i.\u001am\u001cr\u0002Z\u0013Oo\f=\u001c2\u001el4\bSl*MPAŰ'@\u0017\t^dl\u00159JzK2|t3\u0005X\u000fS(7`{Y,Hhr6D\u00018AͿ]el?F{t\u001b<\u0011%>:-[PfJB>ܗo\u001bM.\u0017GM\r\u0015}l\u001f>nӚ}\u000bK\u0010V{\u00177joҚ_,2]Ǯ\u0017nvFGMlF힅Mu:{&~\u0019Nu5d8K\u001e\u0018b\u00075\u0012s$ڎ\u00137YF2D\nt\r4p\u001dUk7d=\u0012,X8ts\u001fqقVѻŔ\u0006Nnٻ)ꑟt8jR/p2B*ޡe^etbaW:)QQ#\u0014QU2\u0012H\u000f_z3\u001a\u0005s(af\u0014SF_{\u0016͍\u001fv!i:\nJӼ/]uW[\u001fK%>8jRԍ2NNSOΒf:o籕)\u001d?o4\u0013,~<m\u001el$yW ܩ\u0010\u0001jdJ.\u0010B`$m9\u001383orJr[eۜTq\\,rҩW0Sd%!LuժM]`d\u0004UYpÓy\u001eS`7\u0015Ergr;5\u0002Y\u0002]Yc$\tZؑVƭa4^\u0018>>+qk 38h{!g!5;d\u0017:A~g\u001cu#\u0006ʤ\u001cX`f_I\u0006_ݟ7\u001d*|5-ܐ\u0007\nzݡKJ64IUj\u0015Fۖg~\u000b4f;m6z!J\u0011љ!{xy\u0017'ہ\u0006\u001f%K]`e_\nEs/K<n9rG$'%d:j\u001csB:GtvCH\u0003sJk*'{g\u0004x.R\u0012\b41#Mȩ\b30\u0015 \u000fjξaoH\"\u0017c\u0012;'C̥^dYMuܗr٦\tCݚ{,6ʱ\u001bt.d\r\u000bىmVS]\foZih[<вvjݷ,\t3SM,y7\u001e)\f\u001bI<s\u001dM$l\";&\u0012zrDI\u0017Hs\u0000FTZ>*\\ς\u0004\u001e\u0011\u0003${9ppīVjM\u001aиbչ_(\b5*\"a\u0004%\u0016Y3aye+\u0012ē;]=,#v!\u000b%5ݪCѤGY2C3KF2w'isx\u0001/\u0016s_s96<mw?Ny\u000bՠ\fD\u0016XB\u0017Z;OU].敏cd\u0018+\u0000t$\u00175dDESQS4\t\u001f\u0017ӥ?\u001d\\\u001bI]\u0016UMe& 5eRPIP#Czo䨝Cǭ@dAr_<CqA@b螋)BLU2(\u001d\u0012h1\u0003dn>;30kkCt1i׋\u000f\u000f/Ii;\u0012\u000f a*\u0017̇-fMzMPã9\u000f)\u000f^\u000esv\u000e\t\u000e\"G\u001b\u001aP\u001f-\u001diZͣ=txrv2o3yr\u0006RBj\u001e;\u0000ڣ\u0006&cm켹ZLĺ]˵\u0012Ks%QzJiuu\u001criE\rx]\u001fLҵL%2suB)\u000bG#\u000f_x<$zvK}'F.\u000f\u000e֭q\u001aY!4\u0011L92/L7\u0015qޏ\u0013\u0012\u0019ai:#\u0011]bY3]nLo/\u001d\ry+\u000b\u0014[ޢT&q3\u001adw8pgrVBz,)duM\r\f8\\BP0Ot_\u001a;aй\u001e\u0016hH:`:7YJ<D\f\u0014\u0007\u0004tsoMP\u0012=܄a\u0011R)1c\u0002!\u001f<-;6S8\u0003\u00047{o~\u0017/:`~\u0001qon>\u001e\u0018O)'_/R\fv\f\u0017n\u001ci\f\u0001}vE\t#~\u0017|\u000b/\u000f\u0003\u0017\u0017_koyk\n|\u0003i\u0004K{z9='O|\u0017.Lߞhg\u0017.\n|\u0019\u000b\u0003\r z\u0003o/\u0012<\u0005j\u0004t\u0000\u001c_pl\fh%\u0015/b+w3V\u001f?o߼/~\u0006J\u0003]\u001a3,w\u0017?]W^}yۻ7X\u0006U\u001f\u000f\u0010\u001e\u0002D;\u001e\u0007w:\u001c.\b\u000f[aݸ[;\u001ex\u0007\u00199zj%\u0013EH0\"?Z~\u0013:\f06\u0018\u001fǋ\fC\u001aRW@_6͗>\u0007x+~\u0019\u000e\u0001c\u0017\t?<N\u0012#\u0012zw\u0002FסZ\u0010-r,|!\u000fcǷL[>=ʌt%)\u0002'\u0012\u0018\"\b\u0012O&!\u00167E2^F`\u0010\roa1u\u001c`vwӉ\u001dG/\rvdfG\npZ\u0004O:s\u001e2$r*pcJ\b_Aƀ\u0005\u0018\u0013\u001c\u0001\tG~\u0004))5+zE<؍}=`G@\u000eEq%\u0007O+\u001a\u0003T\u0005l])(\\\u0014\u0018\fp\u001d\"^@Nx\u001aw4C\u0019~h\u0000\u000eB\u0015H#\\$,\u000f|\u0002hp Kk>݊1B=\u0004\u0003f8y&(\u0011E\u0003nʸ\u0000\n\u0002\u0012\u0010(i\u0016\u0017\u0004f<\u0012 X\u0006\u0004\u0001+\u0016F\t0\u0016P\u0017{|ܟ\u00053\u0001`Pf\u0015\b8m\u0013Cu!''uE\u0011<#ҷX\u001a{7\u0001\u001b\u0001\u0000U%:fW\u0003+'\nZ\u001d,_IH\t\u0002^%&K%\u0000n#tĵ{aolɤz\u001aX=B4U`\u001c\u0013^>^\u000eA\u0018\u0013T\u0000\u0010ْh \u0014ad(b\rB\u001eM$ c@/\u001b&\u00030D ,\u0010>6\f\t0ÂثvNמ\u0000T4VKF\u0000\u0012\u0019o\u0002\rz<\t\u0019\u0003\u0016|L\u0012=r؛J]'\u0014J\u0001Ѩ@c\u0006=K\u0004g\u0011a\u00140\u0019 U\u0005\u0011\u001c\u000fp\u001cP\u0017C\u0014K!\b!$Tѳ**\u0017\u0001v\u0005ֳym\\^AɄ+LXbJ*?\u0006Gv鐼u\u001d6W\b>5Ǝm\bBJ=\u0003a\u000e\u001dk\u00010\u001f\u001esv`O+L9;3Bݞ\u00036lXHP\u0003v!Lz\u0002\tĿu\u0019AyzFA\u0006ڱt\u001cC`8:>/\u0001R\u000eߙv\u001c`\u0001GUvߓ|Gn\u000e\f\u001a\bDsX]Ü Tf{^^aK{\"'9\t#0H\u0006؊ʠy): v\u0007\u0018:Zayk\u000fS:]Gut]~\b\r\u0002S=0a\u0011\u0017Rn\u001bp\u000ecL;p\\\u0000h\f\u0019\u0000@ogT`\u0004`E{\u0012\u0015<[;QfO9\u000eCU~/ձk}q:1ʮqJ=U{GC#\u0010wO\"e\u00074?\u0017L\u0006 \u0011\u0000U@h\u0016=)1%\f\u0001\u000e\ty\u0004*2Ȑ\"\u001df<\u0017\u0012\u0005W\u001c \u0007\tb\u001d\\\f| Xdw>\\|2%(F,L`[r<8\u0007(I^DL\f_P\t_@\u0000n\u001a\u001f\u0006\u0000wt:@\u0000œ\u0010\u0005\u001bZ7\bL\u00004\"!\u0005:,ūHPP\u0000į6J\u0004¤\u0011\u0006\u000f1p\t\u000fl\u0005rvrt\u0005@:\u00068~ZT\u0011Bbewz\u0004\u001e\u001aXa8\u0011h#\u001cUA\u0007\rH\u00029\"9<w\u0015/]\u001dHw\u0001\u000eO\r:\"|\u00019+z\\\u0001G^l;\u001fCk1`1&\f\u000b\"\u000f \u0003\u001e:9\u001c2\u0016#C./C}\u000b+\u0001HK\u0005\u0006o\u001b0_:\u0012\u0014\u0012\u0000\u0015\u001c\u001c,\u0005 Ey\u001c\\'\u0007\u001a[\u0010D£\n\bBE{\u001cWL\u001c\u0014\u0002\u000f\u0013u\u0010O]m*\fqo$.\u00018X\u001f#__h$\u0002q7*=B.H\u0018S\u00043}){Rb33C'Ce{PA}\u001dVGzRqH>\u001em\u0002|`ⰻ \u000bpUR%C\u0012Q}Ha0`!Ë)\u0007\u000ea}\b4K(~\t#L\"\u001eL\f׳\u0000!\u0011R\u001e\u0000- }e\u0002=<\u0000\u0000$(\u0013e\u000b\f\u0019pg\u0003 eA\u0019A>\fD<\u0011J:=#yDVF~\\\u000f\f\u001c0\u0011\u0012*7h\u001dT=!)\u0019O=G0!\u0005\u0010!u\u0012rG\u000fdA\u001dGИ\u0006`Gȹ\u001e{G+Lv!^\u001fұ:\u000e\u001ef(\u000b8\b\u0015,\u0001\u000eOy\u0013\u0000_\u0006\u0014\u001cz8\u0014L\u0001d\u0017\u001bO\u0002*H\n\u001c%*p\u001cHCU~o\tW\b\u0007ulAǢ5d\u0017uzPY\u0019C*\f{sZfrq\u0018N3\u0004\u0013s\u000b\u001c\b\n,jm\u0001)%6\rY4,\u0007\u0007سam\u0000:52Ł\u0006?\u0019Pك`\u0016\u001dj\u0005@\u001d\fj\u0004R\u0006Tk\t\b\u0003:\u0003V\u0013\u0002z\u0013\u0010\u001e׽~\u000f,C& xB$SM@0D\u0001'& \u0005V\u0013\u0010FZ\u0000u\u0003r\u000b7ψ\u0007\u0006\\YTj\u0001\u0000m\u0007AZ\u0007{5b$\u001f7\rbjֱjy\u0000Ʃ\u0007&\u001a\\-Ɵ\u0002{\u0016o,&&\u0019\u0005L?vZ?\nM\f@\u000e1f\u0000Be6M>M\u0001\u0013\u0003P\u00075\u0000!:\u0006 # }8#\u0000(\u0003p\u0007(nU3\u000b\u0002f\u0018>h\u001d8lk;obK\f$ݧR\u0015*solO\f?p\u0018dӳN\u000e<\u001c5%\u001f\u000fa9\u001b\u0003Qe\u000f Cs\u000f\u001dR<-Jx\u000e`\u001d9\u001a\u0018q}AY\u0017z\u0005qAy\u001a\u0017z\u0003\u0019{3*Lx\u001a\u0017z\u0005qA\u0016:~\u0005\u0001eAZ\u0016zf\u0005\u0015jYPVSeA\u0018\u001a\u0016OYg\u0014jVP>&\u0003e\u0013{%*L|A4+,:_I{fZG\u0006\u000fޑ\n\u0013}(ѯy\u001dgб::Vc>?i\n\nS\u001av\n*'\"_Ƚ;\u0000\u0001@~i\u001bTjxA5p:l\u0001\u0011NP$\u001d#\u0014\u0004:!\b擦\u000b{c= ̿?~'Fo+\u0003\u0007_\u0017(\u0013eS9}'^<\"'\u0012\u0017xg\u001d\u0014\f\u0007\b̤\u00125o4\u0006?.\u0000\u0006\u0014\u0011p \u0001]#\u001es\u001c\b\u0000#΁g#.\bT\u0011RCE8\u0004V\u001c`f\u0015\u0015\u0003\u001bb?ɤ\u001bm̤.2)Z\tn:\u0000Wӑ\u00028 \u0011~]6UZ\u0017_6nh\u000b1ߚߛrӯ._\u0013ܼ\u000fe\tp\u0012 ɨ\u0007تٓvE* ]X4\u0013\u0004y\flڇp+HϠN\u0001\u0015,Ў\u0010\f\u0018uњ\u000e\f\u000ff\u0006&/\u000f\u0002\f\b7\tX\u0004:m+r\u0004J@=D\u000e5\u0003 \u001eˑ\u001e\u00010\bU8\u00184\u000b\u001c\u001dw`\u0011G\u0019\u0015\u000f@\u001c#\u0015\u0003\u0003Ʉ \u0000ng\u0000ހ\bD.\u001a\u0004\b\u0013\n\u0011ϏY\u0000%R\u0000Fw\u0000\u0018\"\u000bj\u0016Йġ\u0017<Y)d[O`@h}@\u001dʋK ȰrkF2H\u001f\u001dXvK(+H\u000b\u001bF\u001bÙuq\u0015\u0011\u000fM\u0005e]<k\u0015%ܱ❀\u0019E\u0000c4?\u0018\u001b\u0010\u0018\u0003\u0003rD`\u0019\u0015\u001cAͩ#*\u0012\u0019@#KB\bD(72␼\u001d\u0006[\u0001\fcAg\u0012\u0004FVS\u0007#}Q\u0007\nAKAx`&ݛ 4G\t\u0004Y\u0000\u0016C !b\u0005\u001a0\u0018,hA\u0005ǸF}\u0018 vjQ:\f\u0006;\u0006Z$w\u0002D*\t@\u000e:\u0005%\u00118k\u0010\u001d\u0017A\u0010h{(jw\tD\u001f\fX\u001c6\u0012?\"\u0016\u001cA1*#7P\u0019:<4+B\u0012;a(\u0018\u0011hX\u001150AuH\u00023+\"Җ\u0015liM<-\u0003-~Bځ(M\u001c\"\u001ae(\u0010Gt=l#S<\b\u0015C<\n!0z\u0007G\f\u000b\u0006\u000e\u001e1\b\u0013\u0010\bq\"_\u0012Q{[)&@L\u0000x\f\u0000\u0015>,І&!>9\u001dU\r\r>P_}\u0003$L\u00010n\u0018\u0006+KfrU(\u0014ǐ:+y\u0003Ape5#\u001de\u0006`GF}dk{?Dׁeb\u00171-+y\u0001?\u0006}\t/J\tKR\u0017L\n[E\u001c7Sp\u000e2Iټ\u0004\u0001bFdQ@\u0014#AqƓ(3\r)\b_a6c\u0002>aˠ>x=)}^T\u0002T\u0003\u0019BV\fU%*H\u0015B(Q\u0017=s\"Z\u0014T\f{\u00143*=\bʐ/5=\u0000/ݟ/<ˑBmH3Bu\u0001B\u0007{z\u0003྇%V׼%\u0011wiB\u0007{\u0012\u0001\b{X\u0002/\fsx\u0010&e\u0004#P7aY83ȉ(\u001aC}\\\u0019GAE+0\bP\u0001z\u00178РM0\u000er\u0006 \u0006Y\u0003ɞF\u0016x-&-᫼*\u001b\b\fe\u0011P\u0013lɎǉ]\u000eAd\b(/>\u001ce>ҍ1ImG/\u0013>3QȢO*\u0002T׹H@\u0013\u000e|T p,`xK]\u0012\u0006:>Q\u0001\u0000x\u001a:\u0018-2a \u0016\u0004\u001bynPZp^\u0006K\"K\u0001htvdgu!\u0002<3\u0004D\u0000`\u0013\u0004\u0003I%!j\u0007l#(9\u000eHz\u0005\u0013΀\b\u0015XƬ#34B%ޑ#U\u00106\t\u0002\u001cX\u001d1;\u0000\u0011]f\u0006&ʡx\u001c\nz\u0003jn\u00070o\u0003ϸ\u0011QP6\u000b!bqAA\u0007\u0005\u0016\u001dX{10\u0015KI\u001bde I#\u00059\u0006=z\u0002\u000b@U/sqP:(r\b\\\u001ccS&9B\u001ee6$\u0019x CtPQ@_xe@l.\u000b0\u00061\u000e\u0000#u\t2ʀl\u001daX\u0002\u0002meg\rAFK*t\u0010bLmõF\n꿇{,ex|y(`R{\u0019\r|n\u001a\u0007.\u0002#^\u0010t[Wӧq#&\u000eݤ1U\u0012HW62\u0000v\fIb\u0018YA\u0004\u000f+.\u0018\u0018kF<;\fml>uG@{\u001f\u0018+'0D\r[\u0002T-$ˣe\u0007$\u00040#q\u0017`Nbj\u001dp\u0011u<\u000e\fÝ@\u001fvPD\u001f\u0017w\u0006ˁ\u00100qnhL\u00020\rNf7}T<3\b;o\u0018l7AU\u0005s\u0000u\u001b\u0003]o\u0002t%\u000e+;\u0018\b\u0013['ݻu\n\u0000:غqdUf\u0019uP+ӥ.nE#D\u0016I\"\f$\u001bPTO\"\b{WncNAd)z\u0007$a]P鴔˺Hp\u0005Η\u0002\u001a`\u0007mMfUy\u0012\u0018t\roEh\u001f&MCAv;[\u0016J\u0005ɻ7K\u00004/Y`@u!g\u00128{c{\u000eJ*\u0003\u001d*$Ua\f\u0000]J(\fT%er:\u0000\u0015xAz\u0006[l\n\u0001\u0018D\u0010R\u0011\u0004&4B@2\u001br\rU\t\u000e\u0001R^\n\"9Y\f8Zy\u0018D\u001akJ,n\u000ewTU~o}\u0015x\u00041QZ.\u0005<^W.5\t}%Uu{[*Y\u000e \\F\u0015p_h\u0007V%1BY\\\rB/\u0005B\b\u001cvr\u0003T>Cv\u0002$/Ԋ/H=<DE{J@Yj#\u0011S\u0006@qF`\u0005Q\u0011̤\u001bk\u001fQ%W\u0019h[TPT\u0004A\u0006pM6\nT\u0002+\u000fxyK\u00014&1lgm\u0012\u0019\u0018.Gf݆a\fA\u0003\u00061A'U\u001as|y\u0012E53\n0\u0014%\u001dSe\u0014 \u001dT\u0011,ha1OA+mVx\u0000VT@\\\u0018\u0015璾BfV\r\u0000MR<\u0007RV\r\u0010뢤>8!\u0013H>}S\u0007\u0000tC+TFWFl\u00194T0QWPWqJ\b\u001cu'Qw'A\u0018\u0001$@O+̑\u0000,\b\\JȣnB5ԅ\t\u0013-V\u001b}Y7\u001eM\u0000(\u0002\u001eZt`&ځQ:P\u0013\u001ds\u000b\u0003C1jfV\u0002<\u0018<o&$\f\u0015U\u0019p\u001dH_\nTQ2Q{H^\u000f!I\"¢\u0003ܭGF}#NXC\u0013s(@K\u0000\u001e\n\u0001\u000b\f\fMVqt\u0013Til\u001d<hځ\u0000A%錇X\u001dj\u001f;\b^\u001b\"[\u0015(O.JAu\u0003֬<[ [%\u0014?R7\u0007j;XsAnu\u0016\u00188ȎM\u0012E\u0018e\u001f1086Bf\u0002\u0018X;U\"0D\"pbAɢN!tT:#~ie`ڢb@`mSn\u001d% C\r9Yź\u0004XD܃\u001a­/J#\u0005@_w\u001c\u0019ָԝ!(T\u0000S0GF#Ւ\u000e\u001e\u001d(j{\\uZ=b,%\u0007ueqQpA1&g%\bȣ\u0001v3U0\u001b\u000f5\u0004Eba[/\u0002ɖ$Rp`\u0012ts\u000e\\l:\u00128՘ZA2\u0002T.\u0004xUW\u0016:`\u001b&2/El\u001b\u001fX5RV\u0016U`?ЙATmةj<Z+r!y)\u001cr>\u000e˱*kD!gN\u0012\u0010\u00189\u001f6$20a\u0017\u00065\u0003\u000b\u0014\u0000\u001c::\u000br[QTyW=Dp[v\f\u0013)|^qkT6T;\u001d|\u000e{JM0wj\u001dʧy~\"8\"=+\"!!p\u0004:VL_;H*=<FT(t\u0007_!\u001aJ\\\u001eNU\u0000\u0006à\\\u0015\u001d\u0019wA\u001c\\vA;`a\u001e\u0005\r\u0001UV\u0014\u00173VꬂTJ+t4N׃F\u0010eEBeI#7\u001a\\s\u0001*O[SPUyPi\u001c*<n\u0001\u0015b=}ͤOf+J>Uˍ\u001dZ\u0015Mm2\u0006\u001cCCE\u0012U\u0017>*\u001c%k\u0007\u0014Ǟ&8ʯ\u001ch\u0004uC֞\u0012JM$W0U\u0005`S)z\u0000諤\nYPGɚ'T]\u0013\u0010Xy@s7\u0006W\u0006u\u0014D\u0019:|CF\f_>^\b\u0002\b\u0001\u00118\u0019b\u0007rReX7\u001c)U@\u000e+'J\u0019USu\u0000ra$\u0002y\u0015}SׅjAh\u0015Tpu\u00146\u0001>8%+\u001f\u001d\u0003U3\u0018Y\u001ddxK`9\u0003)\u0003J\u0014g\u00198E!*rLл7=bpy(\u000fX\"WB\u0019Vl\u001c*NFs/UI\u0011/+(v\u0017\u0013R\u000b<?(c \u0015*\u000e\u0006V'\u0000\u001dmP \"<kR\u0015\u0014:a*zQ3\f\u000b$`O\"'E\u0012=ZD\u000b\u0001:ۅ\u0018G\u001bl\u0004/J\u0015\fɸJ\u0000V\u000eI\u0019U\u0019BF\n\u0001\u001d\b\u001a0\"~,2\u0011\u0018\fEɨ\u000bUkU\u001c_\n\u0001ՉY\u001d&5Tqz\u0002l&3ggXv\u001cĺ\nʺ׵jE\u000e\u0001ihTUL%A\u00020\u0003=Re\u00036\u0012PO͞wA@a/iQw7VUAC# h\u0007\u0014\nO\rXM!u\u0013Ka q:)_\nԋ9\bHu[/ȑb֭(M\u0002J#E\u001f\u001fr|\u001d`0WzCEVF3{ۨjT\u0004˩&r\u001e`.(z&t4\"7^?G7m\u000f;zt|d\u001cW\u0002G\u0017UBTm\u0000@I(\u0005\u000bq\u0010JZ+\u0001a\u001bh\u0007*FVI\u0007Չ|\u001cd IuBx\u001c*iwh\u000eFg\u0015Q_\u0001jǔu6UVшi\u0007m\u0012z)`5OM/[uEQ$}\u001c먪\u00155ƒ#K\u001e-N^\u0017WjM9h<rsPbg\u001b\u0001U\u001cַQqj>\u0007m\u001e*=C$\u0000KQY2p{WyjT;T\u00155+l-k/U\u0018\u00153\\i1:\u0014i\u0000\u001encSUt\u001d-UFF\becZ8t\u0011\u000e5PQbaڟb\u0002\u0018ߣDZ9aK\u001b+\u0003) :\u000e|5zj^s%$\u000e)\u001c[\u0007c*\u0015Z\u0006JH=\b+:QU-r\u0014.\u0002\u0010K:\u0015m딺B\t\\c\b$j8\u0005eE6[OJ1⥎I\u0000;\u0013aNIXjc\u0011E:I\u0010A^\t˨><1kU\u001as\u0015IU\u0007rGt,Lt\u000fVeW倦4wN\u0004\u0004QVB5*QB;xvJ \u001fWJ|Sc'#R\u0005y+=#>\u0019e(:'&kQ\u0000\u0016%=\u001a呦c@SSr 4x]J#iYy֋Q|@<3i%F\u000bE妘@fQEbG\u0013%WJS0XJ7\u001fXT:0r7S\u0001\u0005I\\\"\u0018\u0018T?\u0010;k\u0005v[\u000f\u0000w/N&g\u0017h\u0019+r'\u0001\u0000]E\u0017\u0016UtooW\u0012<\u0000S֢'+촪x`0TE:5aEDtV(t\b97\u001bO\u0002^ba[Ȯ;#-;W}K]]\u0006=R\u000b\u0016ʬI\u0005&Ք[Q\n\u0001U\u000f=^\fz\u001c4\u0014/T\u001fvG\u0015\u000e@J\u0003[ڧڊ\u0013qH@ի(<\u0018@/\u0012\u000ei0L&4tKF:IyX]N2詵IJ$tyucJ`\u001dH>}>,6-8\u0002|U<T.֍~&UNYh-^\u0016YВ=:1@بjR\u0000CܨM1\\WNt-j{?dTXB\rZ\u0001`ul]\u0016W&&n'\u0004S2lyI?ΡR)BLh`u.ĆomM<IFRvP\u0006*9T\"\u000bT\u001f铴S\u0013x[:Eβ\u000eɪ4XC:aD(zɥ\u0004%T4\u0012g%.v@7O*tbO\u0018@\u0000暒\u001c+'W\u0019\u0018Nj3\u0004e\nSv:Y;QV)\u0019}yF1MH5xhʶ)-GuU\u001dE҂@mj`h\u0006\u00110T\u0003C\u000eu#b6r\u001d\u0015\u001c\u0012`/QeiQ%ʥ%nB@\u0005\\ ?\u0004zua訐c\u001btz`>*AS\u0002w\u0000\u0015>\u000b)pЕ)\u000bT@\u0017%$SD4̢*7\u000b\u001d\u0013\u0010\u0003;}\u0012^\u0012:4)TKdd3\u0006ڱ<j\u0007M%\u0016J\f;ȊjºΫ\b,U$I;h N+)T֑ih\u0011\u0004]Q۫\u0004P,5󓩗ۋ\u0015;J\u0014hsFMX\u001dP;rɡ TsV)V\u001fp`\\튺\u0013)lÂ٣bp\u000b:yw\u0019*+E_G.5\u001e:?D\u0005]\\S/A\u0012b\u000eS:\n;\u00012Y=K\rӎڢUsUSR7\u001a'А溬\u0006j\u0004F}/3hqjP\u001a]R˫E*\u0014\u001c@¢7@598ud\u001aƲ63\u0010Co1Q*BWj%\u001b?dpCRTpuI\b \u0000f_}[\u001eW\u0000SS]\u001e9Wxf{\u00160FI\\9\u000ewԠ\\\u0003̰;yjbAII{Y;PJ9\u001ft\u001a[,\u0006\u000eU\u0012\u0012\u001b\bE\u0011U\b\u001d\u001cb.\u000e/sm}ҫ\u0006\u0007 \fȳrYq\u0015Kik4\t\u0019/\u0004;B\u0001XUc}?\u0014\u0011IId\u0015d\u001cՅ\u001f\u001aآ\u0010\u001c\u0014=Ōi8\nnA Qo\rE\u0013\n\u0000j|\tMt%D\r\u0018\b+(c܏4bX汊uk`|-\boɋS<gf4:]nYn)aD$!hܠ\u001a3vKRVy}=P\u001b\u0013j;eTo.V\tX$\u0003ȃfţK3E吱\u0012\u000e2ͩ ̓Ut\u0015\u00149\t\\unɋQP4\\J\u001d|1\u000eJ;kujfPGY^֣㺳\u0006d궙5ήr\u0001 \u0000\u0010\u00065á\u001aDl5ٿ \u001c嶪\u0011O )<T\u0015C\u0004\u0016'\u0012T}%&\bN\u001d0P'2Qa\u0018:A<󂕊Ad\u000b[ ը~6F#C@#^\tUqMu\u0015j\u001c\u001a\u001epɗBzU%\u0004Dp||v\u0019ɀXOߎ\u001d[qPdWǒ:P=N\u001cP_T܆\u0004_ݵ\u0001]V\u001f8.cZy(ꪏ%\u001a,Njv[ughS\u000e:dz}A4*顝z-a$\u0004\u0010\u0011XC\u0001\"*\u001fW#D`\u0005\nנ\u0003p\t\u0002*ʻ\u000f+h\\cK\u0001ӫ\r\u001fYsAl\u0006V\u0013LPX\nzAN\u001bmD5\u001a暁\u00036)I2تƵ͍\u0001D$\tuM)ˊ\u001b\u0000FQc2t\ttĜ\u001dv&Br)NыuzxyTLN\u0010P&x,f\n9L;\u0018|.scXOCbMH^oAA%D\u001dcQ 8wjuU>\"\u0002\u001cC\u0018ٷ \u0011Ǿ\u0019/\u0005%V\u0007\u0000?V}\b\feՋqGYW\u0003\u0010}Km$0Z\r~~=\u001c\u00131H\u0007p'\"` w]š|\u000eE7(.W[c.\u001a=5\u0005y\u0006&:݋[\u000e\u001f3dc '\u0002T>\n\r\ro\u001a%z#\u0018&~\fN\u0019~\u0014CAs\u0005X\u0006m\u0001A\u0001Ū`Xn$u6ʫaA\u001a1`RT$\n5\u0001E0d}X\u0011hȹ]\b\u0014ʍb\u00126`k \u0004l\u0006-\u0015\u0018Zt\u001f\u0012^ts\u0007crjȮ\u001cXX5s|\u0010K\u000b\u001cUӌ\u0006n/(NO@\\E-Yز\u0012\r\u0016y0W\f㖅\u0017\u0014\u001f\u0016@EbaA]H\u001ac>Z\u0016l9ȃ;\u0004p5\u0012Ρ^*hp\bk\u000e\u0004a\r\rő*FUrnEil\u000f\u0015=\u0014E-=\u0012 P<l\u0017xy,\u00123{[mx(1mu\u001fRkk\u0001\u0002EۄAn.\u0011\"Gyʈ\n|`lP\u001dt\u001djW*ꒋ#&\u0014\u0004js\u00121ȉ^yq(\fSa\u0016\u0000*ʹuT1eE\u0015KyxF)sLr\u0006e\u0007\u00029J&'iv4IhFr)TOKY\u0005\u0011Q\")\u000fв,p}ɯ\u001e\u0011DD\u0010Q&G\u0004\u000efJ{\t2\u001fxG`CKhĭHD)8Ԉ\u0011P'ouN!0cЌ\u001bU-͑+Ml\u001eIM*\u0012xS\r|=FDc |\u001fa\u001c\u0000V}\u000eܠtߗ@M\u0005i&\t8Uw\u0014$\u000eQ\u0004\u000b1\u0014٨@\u001c\bީ\u001aE6\u001d5_\u00006udz(\u0013\u0014\u001dJ1\u000b\u0012\u0000՝i&R'\\uxlR3\u001a1m\u0012)m20t2ЛfC\u0003K\u0018X\u0016S59^\u0018b'fɬ\u0007¡\u001e}{(\u001eU$\u001clR#POe@\u0011щ&4d!P;PUz(\u00058V$(tRlTv\u0014;\u001afq\u0004\u001cJ\r@C\u0004[j\u0005\u0010\\DzǛ3 \u0019Ꝁ8NCP}4eBj>\u0014\u0016jX\u001eD}Ъ\u0007 kRk\\\u001d\t\u0014\\j\bUxଚ;\\=2_\u001b.;V\u001b\u001aW/V)\u0004 =X\u0007ڄy\u0005\u0017;\bm.<ϳ:穬c<\u0000n\u0003BJh\u0003*_Pr_!D4Xkr\u0018x[]v\u0013:[k\u0014~j:\u00036)\u001c\u0000S\u0000\u0000C3`\u0016\u001c'j5'3\u0010iz2\u0003u\u0006Z6Na\u0006\b\n_rD\u0000U.\u0002G\u0019\u001eG\u001fB3t\u0015Dub\u000e>{@~k0$lLd\u0017Q\u0010\u000f\r\u0000\f\r0kGN>\u001fߚ\r:aa@}\u0001%ċ\b\u0001=\u000bvˈǁYg\n:Ƴ\u0000J~\u001fi.@A\u0016b_\u0001SD2f~I%ɸ`\u0017HhƨP\u0016\u0004\u0015H\u0018J2f\u0006\r(,_`F(zhVHJ1D\t(#2+r\u0010\u000eő5;\u0019\u0000\u001d\u0018ȉT\bWC\u0005D\u001bNle{t\u0006\u001d\u0004IB\u001d;Gm\f\u00041G֖<MUCtޖBA\u0011;/肛\u001a\u0000ђ̂\u0005ߖbtEceG\u0002)9Q\u001fEW18Z`c'i1E\u00024:\u0003P-o\u0014FkZ~\r\u0001)6d\rȽ>\rrG\u0004I\f2\u0018\u001a \u001cIcH\u0019zՋ?\u001c\u000bm@9\"QYT33\u000blxUE\u0004'xH\u001d,\u001b;PciW;`%oz\rYޫ\u001enE\u0015A\u0016ϓ\u0004\u0019,yHXWW(P\u0000d|=\r\u0012dC^ͲK{\u0004ttM08r p*elk9EޫX\r\u0002AW\u0012LQ\u001eF\u0001\fA'\\^@\u0001B\u0015\u0006%|K\u0017K;BwYIq@\\\u0014*\u001el`Ѷ~НOQ\f̩\u00148\u0000C\u0011\u001b7DV\u0012.:%\b<^R\u001d\u001a b2%̿`5IT%f\u0011_\u0006\u0012d\u0000$\u001f\u0000X0y\u0003\u001e \u001dTOvJՖ;+\u0019\u0000M1=*\u0013hQwFۧ`Jl<*k?\u0014\t褯\u001dp%\"R>Bt\u000bvT|78X&FG.\u0012AEɽ%m\\Ui9]̫P,P\u00026\u0017,x~[\u0012H#hn9ۀ'{5\u001d\u0016U̦\u001e\u001e\u0015QPr\u0000\u0017dY%\u001bt<(!{m:\u0003\u001c%`!IL\b6\u0006\u0015\u0002R\u00106WW\u0000\u001bt@W\u0014IK~4\u0017 \t0B\u001817Wqf<GQ!\u0015qI;\u000ba:\u000f(9~rY_Behgks4Dso\u0000No8ʰ\u0014E1i\u0007\u0015r\u000eJ\nE\nDTɦKI\"`(E<*f\u0007ٲ9zqҡ^\u0015\\S\u0014\u0011{Q0\u00124[u5S\u000b|abQ\u0004\u001e$#\rY\u0018.@yN\u001d%(\rz|_P/\u001ab\u0012φBee%\r9\u0016\u0006X\u0005(2tN`zޛ-Gr\u001cۢ_\u0017I\u000e!#\"7n\u0006\u0013%nmv\u0006A\u0012@'X#\"#\"QY=\u0000\u0005tI&\u0001)f9WU_ȷF(-a\u00142EPLFH\b\u0007Y&dd\u0011ߢPN\u0019¡P\u0019%[9 lJA&'\b;;{:T'+I\t>Ad\u0003Ye\u000fjo6!KHPޗ|(abp\u000bj\r\u001b^=Z$>¶W4{Fn9{ќ~ӥr~\u0016ܘ\u0001eo\u001c4\rͻȐ5</\u001f \u001c䔦H\u0011\u0000\tv\u001bnP\u0006!m\u0012ʵIYGD͢P\u001e/S46\u00172)%@|lf6X2\u001eX\u0015걘dͶPhptr\fZ0lqBff~@d\u0005\\r,'\u0014l\u001c;H\u001dB*J\u001b-|}YnD\"\bSL4_2\u0012\u001e2KpH[\u0013<szR|49/CV7[''\u0000\u0006$\\7\u00004=\u000f&\u001b8\u0002\u0000\u001aLYY\u0018\b,\u001c8D\u0006\u0004>W\u0003l<\u0006\u0007q\fX:\u001a \u001fz\"y\u000e\u001fϩ偕J\u0004UÐM\n|\u0000\rH+mwlGT\u0015\u001a0=A\u000e\r1y4z>\u0006\u000ezC<E4d-ċlY:)Il+ɔ~ku`ѻ?\n\u001a*L\u0011pK?@Z\u0018\u001fs\u0000߬C%/i_\\+\u001b|\u001cy0'aY\bL)\t\u000b65\u0011\n\u000eB\r\u0015S^G\u0013Ƶn\"6_V\u001bBmKvoFҒhכ*P|bOAW\u000f(\u001c\u000e\f}e+@(x{%͹sBkka܂޼\f\u001e\u0017\u001e,˷^Z\u0014ݻ!TJ:@Ή0\f\\\u0007hȬҬZ&\u0007NdJIJUU(4#XM \u001fa[:*a(VJ-6d﷥\u0004؇Zނ\\\u001fD9`\rV(յ}rB2\u0015\u0000b`l]&~dy/T\u0015Bay:vu$Ӌ[$tja仌_T׎D?\rll%%#NrYK\u0019rP\u000b~Q#\u000f%\u001a\"\u000f0Nk\u001a2J/\u0014yR_\u0006\u0014v\bKj\u0011'E)ZkG:GO-\u000f\u00014\u0014#*a\u001f&\\ZV2[ܔ\u000brHy\u0011fl]\u0000 Xf'de~iR8\u001b`\u001bpTN\u000f\u001f0`PV:\u0014CVbA]|f\b!SCMƕK\u0001jLI\u0002P\u001c\u0006 \u0001\"˶\u0018+sf*\u0005K`Z%$̖T\u0002\\\\UUIw\bIM\u001fZxec$n\u0006)\\\n\u0012K\u0001~ejy\n]_8\u000b\u001a9zIh0;pݦteUQ\u0010\u00077el\u0010NW\u000f\u001cZxDedY>\u001aֺ HZ/%+J\u001eC\u001bųJ\rSU\f]\u00032ص>sc\",p\"\u001dlAaGZZXj3E\u0019\u0017c\u0014uiڇE\u0015\\k\u0012>Qf\u0011\\M\t\trĈ\u0016Yn@I\u001f\u0004MWf\u0001i\u0018v]RGeq\u0014dQqN|3\u0002crm\u000ew\u0018QHO\u0001\u0010\u00168ԒFM>\b\"\u001dD=\u001d%!3!;PhujL*\u001e\u0017L䡸E0?v-2kJ0\u0004+HHb\t\u0001\u0000\b\u0007/\u001e_\u0015L>k~e*tR!?`\u0014\u0003\u0012Rv\u00069\u0004\u001c݅\u0011\u001f\u000f\b\u0019+:\u0017\nu!\b\u0003FqAׇe?^\t29vtU\f`':;.D\u0011lQm\u001atϱ!*SgӗZ\\^ÐB3ў?\u0014\"Ēa<xv9e>J~X哰]Smuma};Ƿ(S\u001de\u001e\u0004d\u0006$l6@)<*\u001a^VIR\u0000&\b*c%Vk)h|A_\u0017bO\tHI\b\u001e]Jk\u0016g\u0006IL{<->dk\u0003V45+a'Ղ\u0001Yޔ\u000b H4 0o&J\u0018|-dB1\u0010&W\u0005pUwb\f#\u001d/e\rRva\t%\u0004\"%L!&dU~(.5ڹ|?ˏk\u0017;\u0018b]W4u!\r/b;1/|\ns\u0003DQLY\u000bjz\u0006\u00141\u000fαRW}ډpF@\\9՜N\u0018|:\rJl\u000fs\u0003HWA>\u00104ZhP+Y+䀝3\u0011Nj\fST%l(Ȗ\u0012oK:\u000f\u0007qt\u0000.䦛\u001f0+b+B\u0018Rm0d¼twu&\f#\r\rĐ\u0016 ܟ Y6\"\u001d݇nON$>NFz\"$\tEmFqV\u001c2qǯ\u000f\t)\b[v\"fZ\u0012\u000e*x\u001dlߑ\u001db\u0004\u0002\u0010\u0005/E\u001eօ\u001fŮu\u0006\u001aV,MHT\u00126ʵ/\u0013I|0M@P\tdn\\+FY|\"Dgy(fSMf\fNU\u000bNn\t\n\fGQF.&'̵Y\u001e\tt(\u0005Ryr-\u0002\u00168\u0003Te\".F[t^\u0002[\u0007#[i\u0018\u000b\\\u0015$N\u00186tG͐12Ѵ(\u0010h*,t%GcKgCh\u0017`DtZͶs\u0000i%DȻkky\\nIȮm*ȸvm\u000e|A$*\tBkGG\\7\u0006*4}wuQz0a\u001e+\u0015fh-b\u0011vGaSD{ͅpu$~7<\"amDhQ\u0001}\u0016aJh+5?\u0004\u0014ր,sn\fm+EǇw~S6\u001a۵x(\u0011 \f\u001a\u0012va!XVjQhU6:Ǆk\t*\u0018gtL7<\u0002\nk!Լ\u0010\u0012ޕX\u001d5%\u00123\tH\rɵ\b\u0001\u0012)ͺza:>bh\u0018mK[\u0012\u0007;V\u001b`o\b\u000b(\\\u0013>KnO:EGGL5Y絰bu0_tbǛ1t/\u0019\u0003N@8z|gHnJXΧ̞H\u0012D \u0000\u00122*D\u0010\u001a`\u0011'5YXM L$\u000f kJ=X~A.LR\u000b{ߏMCץ\u000f(|_\u000f*A>Sٹ0\"$`.\u0019ǯe,}L\bY\u0012G0;2TxK^7!\u001c\u00131-O\u0015\u001a>/&T&akl\rhmM6\u00032\u00153\u0016\u0010|%\t\u0001ؾzq(\ra<\u0014\rn\u0000/~5\u0018\u0014\u0001)\u000f|&7֗BW\u000b\u00190VX\u0012#\u0013P5ߟPB+J\f%̮FX0\u0001Dا\u0015'\t\u0019\u0000Hiu-Rre\"\u0012X*\u0013r$Aq,9\u001bYcZdPzX2XwCF\u001bo*\u0000 \u0013hռ?HF>\u001e2VuhnMĮ\\\u0013*w;\"i}-\u00071?\u0012\u001eU-(͙(%>`㤇\n~8\u0006t\u0016x)Kv\u000eIv\u0012\u000e+䠺6GtѰ\u0017a~@\\Pl}ˬѡDɘCRD(ԛL\u0001EvNv \u0013Mu<\u0004tIEJ֞:\n\u0007bʥ>?l,O^,+S\u0014\u0003rzQB/ly~IXs8\u0002]NJR̒\u001d\t8\u000eC2yHE\u0018\u0013'B\u0012\u0015L&Ո\u0014D,$\u0002\u001adM\u0015h}\"\u001c\u0004-x\u0005ǗDD}VV/Y|c\u000f$abJW~\u001d\tK'Bnc0rUO5\u000b6\u0015j)MZ\u001e`\u001fYC\u0018&B\u001e.,\u0006Yɗ\u000b\u0012Ι\tħoJbKڴA\\~jY0Z\u0019a$BV0Ǔ\u001d=J\u0012+mb\u0000z\u000e\u0015ڵ\u001aRu\u001bӇFq\u0005hc\u0019\u0002\u0016\u001b)\u000b7K>+AB\tF.\u0006|0G\b=(\u000e0rˢuj'SP|DʙŶfHi\u0000h%1IVrjLtˏnD\ns^m`\b?j\u0013.4Vη/\u0011UY\u0015K?]\t\u00122(}\n/\u0019I\u0019j(ι\u000b.gZ\u0000gLkx*DA1\rFqD\u0010`#)\u0001\u001ada;)'\u000b\u0001ݒ\u0007Tצ/F!\u00070\u0011gT\u00168%\u001d;\u001dBP\u001e&ך\\\u0016\u000ee\u0002V\u0011u&'\u0006//\u001bT؟JDU\r3B(Y\u001f\u0014鵃qV)\t*d\n*Hq\u000b?E|\u0005\u0019yf.a\r|t&\u001cL$\u001b|hzs.\u0011iӍ\u001c@h\u0001kK%3\u00129)c\u001a[\u0005Tvb\t^;\b\b1D\u0012'>47|>=vd\u001f09izm[(T0\u0003Fq\u001f>1W˫܉R\u001bZTQ(P\u0016M5\bÈʌbd܉otS\u0019+ayVe3\u000e⛒mK*n\"A+\u0010悲S]3T&$|1#K\u0001_zX\u0017Zր%\\B\neN\u0002\t|\u001eHɵ\u0019\u0017\"\u0002\u0014Hڨ\u001b\u0011f\u0017D8Nag\u0019\u001fGZ\u0012ʙXⲫk\u0011\u0017K+ltRƳ\u0010vk,8F/]LViOrjX2(\u0004YRJ'b\u0003P\u001fXw\u0001q¼\u0016}!)זݟ\u0006\u0010r`ʙRĥP7\u0019a2bgRB\u001f*ʔ2Pl._\tUe\u001fNٻ?]g9\u000bvG\\[\n\bfֶ*\u000f)O\u0001{e-zW\u000b\u0003|9\u0004]ʂ㆘dyKǬrBY\t'@L\u001b\nD8T*ؽjl9r\u0016@\u001d#\u0004qጫ*\u001aC&B_n&Rc\u0017hKL=ŖIЩ\u0004{\u0016{l\u0017iP\u001d\u0006>\u0012>(A\u0005]*SG\u0003QXGa' \u000f@V{i,W\u0016mH\u0001\u0019:(s_U|\u0001Ϫ3V\tDԖEDA>ՒS}\u001cۼ嬞}6'i2!\u00164Xs`&-U0\u0017a\u0010%\n~rm(kyߩdmX\u001d!%rf\u0015m\bGDu*UG\u001f̘Td\u00135֙|m܃Ѓĥv\u0014LZXJ8WY@$\u00153Z:p'b!\u001cS2\b]u.#@k3\u0014~|\b\u0007]\u000b\u00133vA(EB\u0006'ҩ6QΠtȩL^}.vmZ]@wpkkx\u0018:!\"˷\u001b\u001d6-Bh̆_n/Ǎ^=\u00112zc\u0013\tS^ՅZX6\u001dӄ\u0016\u0007d\u001eɵJֹ.\u0003=?\u0012'#Ǣ)_{HEY'1*\u0007X-c\u0013%d({x-(Gt&c\bS,48']\u0006Z|7&)\u0015q_Fv*Mr\fM.U\fCʚ\u0014aVSI}m-̄\u0013!\u0003T*髕8c#:k6S\u000fP:Gl\rC zUȄ*lmb'I(4؍ks˺\rј8\u0011g*b \b+u\"!*%\u001dN]*\u0015N\u000bX8zd\r]0ictȠSOKY\u0016w6]\t/\u0002'׎\u0007qŧmgd\u001dɖ\u0002zC܏\u0015CW@IJ\u0014g6U\u0018\u0013h\tVb'I`ǡ!Boߚ'\u001b\u000bcMZȨ\u0012^N|v\u0013!Fgr\tL\f\u0005fGIC3k\"FqHKIII,BX\"4F¬\u0002\u001cɵrLȪ^H\u0003*qF1\"\u00128\u0011C\u001eɘ\fe\u0013QW\t(D9L\u0000?ޭ\tG6ĲEG,Z\u000bAZW\u0014c\u0014Q\u0016f\\*\u001bMԱ<'Bq\u0007.l^S+б{~@F\u0016Xt(o]!,:y*\u001fORe~˴!\u0002յ\bS)bhQX\u0007W \t)\f\u0005f&\\*\u0018i!߸6ձ\u0013aEQIA6>2\u0007W\u000b96ߜ\u00011nTDXHb[KCV\u0003:a\u001a\u001fEd׉[X\u0004UVH\u001f0siQQGB`s\u0013\u0001x\u0015\u0018'g\\M-,`\n\\-\u0006O.V\u0015a~@ɵd_\u0014a+\u0015ȋ0? QnL\u001aEjl'Bzx\u0003ئRܕI}lĦ\u00139'#A\u000b?y{\n1\u0016x䱆P<s\u0015MDKB(%FvLZ׍4~xD\u0006_H\u000bQ8\fqJ?>\u0001g?p-F\u0014i\u0018luۉR\u001f$f:_\\uԭ\\oFL6LM3Gg&\u0012Z(\u000fhf\u001fe*xYIi?JUV\u0006V3[\u0001\u0017F\u000eLLn[;\u000bn[\\ɮkݚ\t85Xe\u00186s\u0011g\u0016\u001b9lfe#\u001fs&ws&ϳ\u0011%{tiIm6s]beЖlf^\u001cޒ\f\"nf\u001c\u0012'FZFuq=g==ޚ\u0015^e7s\u001bi\fv|^z\n}3~./a\u0006h\b4\u0006p\u0013Lx\f\u001a|\u0007M^\u0006\fVN0\n`hrM,२8,l\u0017Mf&Focdc\u0007i249GLL'3\f)-6&vee#'3<fhྙiq4wz>M\u0019&Ph\u000bWфרɀ4ÖdVjr0Ͱ55y\u001a\fP3lQ3RM\u000e|U\u0015U\u0005k1k]u;gׄ+a-&\u0017v޲Ɇ6ϜdYk5Z4oM>\u0019\u0019&#V\reyM&+_ע\u0005l\u0013\b\u0006[\u000b+&+,bm˸ñ=6!H|̔3,M&7fGɹfal~6AgDM\u00196&i#M`^mr6_,[\u0019e'\r\u0019N\u0019\u0016QnRw|;dm\u0004p\n\u000fT<jd@p%*78l33,M\u0019n&\u000fuzn}\u0000:65ova{{=\u0007\u000eo07˛<MN&\f\u0016V6vV&|k~a;=|EjS\\1gx\u00003\u0004f\u000e4\u0013leP\u001e4+$,PW^(..Ь\u000f1WKby1m,\u0017\u001a\u0019u9Q\u000bjVh)(Ѭ\u000f2SKdb$[oGZKҬҮҨҬ\u00113_OY{*5cTmFG\u001bⱪNNVOL\u0005jA;\u001b+\u000fh6ZnIͤfuJLͪMNBPQRSB|d:hM\u0019&+[m+[E\tנk̵覴u~*acαk3XM\u0006\\\u0016'&y].ԭ\\g\u0000}*I3K$il%\u0000*dAMZ\r\n<8M5jw\u001bvv̩43RF\u001e\u001aLTN\rڧ&ATLI<5GQդjR_8ش[[(f\u001a_\u0015I\f\fX6>YmjM9mn#[&nRA?$[@jW\bTy3zM\n۹~k\u0014M5b&\t\u001aak+r&\r\feb^I&ml\u0012<6 ۴M6\u0019\fqeņ8\niqPw6i>[C'DMJ9\u0016i\u0014u@Aڤepmҽ\u0011îS˭k\u001a\u0016a\u0006ݘ%r!nd,Si4_2ͬ\\v^O3\u0003h[PYAښT2\u0019P3R̪V\n\\V+\u0003/\u000eM\u001f0Cha\u001073ܶ5f2Y~t%ǰ5oqleCdNnfY61s7ygdV͜ԭUk3+v&m˝m3e\u0011W\u0019yUs#5DJnep{73ײ\u0007427m\\[go7g2m\u001c\u0001\u0015@y`+KA`;OBSɾ0buh?l动x%\f\u0014UT\u0016M\u0006\u0019&\f\u0007\f_Gۣ\u0002d\fi4yHf9K&M&\u0019֔&Jvޖ&v&\f\u001fͭ5k<7\rF\u0019\u0019&'V\nd\u0010j\r\u0012m0H[Y&K-j6&S\u0017jC7dbU1^5fx[3\\[&_M~\u0019.&Xl+Y|HS^kVxf8LuHFM\u0019N6^o+ߔ\u0001\u00158+ l\u00150\u001bΰ 6\u0012p+Nx\u0018Mv&\u0013d3r_Edala6y3rlN8\u001b̝3,MFЭܡM\t'itOʵ:em26^̰3\u001c[fAM\u0006\fm\u001bwEw+nۢm26ف4M&;\f\fq\u001fɤubhnr9o}pD7ؤggX|[\u000bKvM{y^=\bŷpW<\r>6y%ͧ>˽ޢioѹ[\u0014M.\u0013\u0006,}%ɧ?ýo0ϰ7+\u00054k\nl?0UЬjЬЬ*0WUQaLfU\n\u0014j\u0015ͺ\u0016[j`Leԅ5\u000bshhVV\u0005\u0018Ҫ-ҬCҬY2-nr[\u001dv͔*3XU[]Ԃ\u0019ƴ\nբ[ӮpӮӨ3-V]gi+>J@Uՠf}ZDͺE\nGZHͪIJZLͺM3\u0015fA5+G5kLգjծjVZ#+\u000f:#uͻbU_[j+M^\r\u000eG/,dk25Uz]okpm+\u001eIXNm|eI$\t'4\u001ej\u0014NhT\u001f5iڔJM9N5\u0001T*jVIA$!j`5f6i&|]Y\u0017\u001eyĲ+_դ\tB)6\u001f$*!5k\u0013ҶUbjri\u0011M\u0006I66xEQ7Cgנkm%ԛ5hf(ZMS\u0002&U\fa\u0002v\u0019bŚE8Cؠl\u0012FΐK6(-+\"\u0016c\u001c&\u000bgs\u0001gE\u0003$\fB.:!\"mRЛ6P\u001b\rN9\u00117Lu\u001bvIt\u0017^:IM`\u0013_?RzL?6\u0013HިV\u001b\b\u0010`\u00047kd&/nH\u0006!Z)f*6poꏁ\fs2\u001d0Ӈ\u0018\u0000\u0017'yY\u0013{\tܔ\u0004\t([)\u0016ǫKS} Lߤlfl#&/\u0019xJ\u001b$SX\u00120l/\u0003`*{n2%&\u001b!ɷNĪ@\ngA#oSIX\u0014 k\u001er@z!\u001b\u000f$\u0015h~ܤ/\r\u000b\u001fG귿[nY=__]|sc\u0011sY8O~W1G/7yq_^yymj__:o.^n~WgkW|yK]~Ǘoƿ޼\u0002m߭~Qm|˟\u0017;z+WBd.~{~վߋ{hꖷ_/5n\u0017?fqwަW|Zڲ\u0017-5wޔ\u001f'7o_f\u0018[#x׋\u0007lrZТ}&߼}۫\u0017KGn]/=Ъyu/ ZK.8ˏzi^w\u0017\u0017h}˝7ͷo.ߜo9ڡ{@3\rQ4W;/e\u0014x|e\u001eW\u0017xuϗ˛CQ۾olͯ\u0017ܼZܞ{[57׿޼|d|\u000fݿz꫃\u001f8X{ۢ\u0007gكEX{?:J՟o._\u001f콽\u0016c0\u000f[\u001c̽w0\u000e;{҄cX\f]Z&}t&\u000e-z@&ߓw\u0017W|_p!9:i\u0001?󇫷[g\b-\u0013^y\u0019>h\u0007Et?}\u0013\u0019K/\u001e\u0017ˏ\u0017{mX~\ncx\u001d`w\u001f|}]i\u0016>\u0005\u0005\u0005Q7W7_?\u0019p~\u001cJLW\u001f\u0016G\u0017ye=<<`q\u001c뷯~<;l7\u001e\u001cM[\u0017G٫g\u0003yݷrF޼|\u0003\u001a9lc<\u0012ߡ)\rr\u001c]\u0016Q\u00077$>ȋoR&)\u0017\u000fH\u001f \fa}\n;\r\u0007-^d6\u0007/[ԟj(pjg\r1{ݐ{/%/Z[!v7?,\u001f\u0003_.Y[\u000f<{u7G=;\u001f;L򻧁ū.Г\u000fH\tuxc>\u00102\u000e\u001c\u000e-n~iJ\u001d\"\u001eDՓW\u0017\u0017w\u0013=<\u0011u8\u0017ً˷˻$_~Ofڣ\nZސ\u0017\u001br\u001frqC\u001ely\\C41tןon~zLG=lyJΞof.\u0011fvhbow=lt}\u0016\u0010q{܋eߗbrr(/ra(,>(l6ó%\u001a݂)~=|#R\u001eɺxɺ%\u000fdz7糗//8\u0005\u0019ؼ\u001bŞ\u000fmv\u000e=|7:\u0001\u001dFgQ]y\u000f:V_ץoU|\u001e{zFϧ<48\u0014iCvYF\u0016ۯ{F\u0016hxstxe_Vߏ;BxyuK=ftSW7G\u0017߽o_ghl]٫\u0015um\u0001ƖCrݯy-Evž\u000fwV>[\u001eR^^-\u00189?:͋\u001bo\u0007\u0001\u001eUy^]\u0010Xܼ\u0017/.\\ۡq{2I^^^\u001b5C;\u000e`=\u001fM0<4\u0010\f'p\u000eeߗ\tYޒ\u0002<\u0012\u000e0-H\u0010\u000eóX|\u00180;{\u001f\u000eG\u0013\u000e%\u000fl=\u001ca0\u0002aԗ\u0012\u000eÞף\tYޒ\u0006\b=p\u001df־G\u0013\u000e%\u000fE۷p<h\u001dܮ=Cd\r!\u000e0\nm\u0014>\u001f\u0003\u0018\u0001O\u001fJwC\u0016)D\u000fZ\u000e=\u0010֢Gə}9h;hK\u00167\u001dvÎ;ڳWQpP\u000e\u001bھoh\u0017찟-\u000e\na?;ggSݼl[[/ȇwX6K\u001fa\u0017W:{n\u0019\u0018rŠ['SC\u0000euC^]\\lK\u001fX\\/\u0007V*7hiEJ}wW\u000f\u0016ps|\u0004*\u00056\u001e\bT<\u0002;n\u0017\u0017?^\\qq\u000egu\u0013\u000e\bK/K=ߥ-\u000f%V\u0000Xv'fw\u0012|{;u<Hvbx[ö\u000e<r\u000fhCX:\u0005P\u0002o/[ꆘn]ؔO-!\u001e\u001aA:\u001f\u001fr<\u00065v\u0017om_\u0019p\\\u001c\u001f4c\u000f\t|)ɻ1K#rp'ּ;y[\u000e;Nnn.p(6\u000by\\ȇ\u001a\u001c\u000bBkBBoB1Z_\\L}+ر9\u000fe7XLO\u001frn4ݗ\u0006e4_.\u001f/nW?&\u001c|~\u000e&\u0003v\u0000\u000eJ\u0016O..^~\u00155|W.o.|W7^x=\u00144n\u0000\u001d o\u0001;@rw}^~fKz|m\t7%\ropWDS1\u0006I\u0003\tvzy<^=\bKC߿Fg\u0007f{\bWص;R7ރڶ\u0005\f\u000196]\u0007fq\bn@\u001c7\u0007\u001cp\u0003nsm\u000e\u0003m\u0012(B(\u000e \u0007M\u0003D\u001ee*\u0007Q\u0007Yȡa94369\u001c8424u\u000fGY_.\u000f<pgyڷ?og\u0007g~~z<;垝\u000fǽl=pN\u0001G9g/nu_!z8;\u0017.Po;_B\u000bkx<\\=L\rٲ\r\u00007X\u0012.^OvO/la\u0000|>FK`_Fn\n\u000f`@\u000eޙfǪ)\\ϸ\u000f5c,W4CP[ܒ]!0]}-2[êI;o\bj\u001cX\u000f\u00035\u0003\u001e#\u000eު᱀\u001a\u001br\u00005\u001e{\u00005=\u001a\u001f@\u0003\u0006L7g;Ķ\u001c\f\u0007m՟o.Ǣ\u000b{&u\u0002y%a${J%\u000f^N\u0016\u001fpr\u0003mG\u001f\u0017\f|{ہ[7oη\u00005⁫~yC\u0003'<S\u001du'KhY~㫛#Ë>P=&֦\u001d\u000e\u0003uѭ;P\u0017}\u0003@]P\u0017}\u0016o_*n\u000f\u000fG|d+;{n\u001fxI>}P\u001e[ގ=\u001d\u001e]\u000e-z@ca\u0016ꀃq)٣qRU\u000f\u0012\u001e9&8~\u0000o6pgH`=jso-`\u001d\fws0\u000e\u0006\u0017k--\u000f\u0006߃6\u001ek\\4\u0016T<Loq\u000e\u0016;X|\u0007o%\u0007o\u000fx\u0016߱z,6.-stV\u000e-z@Vܼ=`=hQ\u0016)G|w\u001e#bxq\u001b\u001c\u0018/>P<\u0010bo>w6UTdpuvW+\u0011zv~~j9Ɲ\u0018]*ک1\u000fm1=D|@kc\bm\u001d\u0018mi##\u0000g\u0013/cRwxy({\u0000o_xv~.\u001a䦻G\u0017\u001b27/_9V&\u001d2ǿ\u001f/=V߶(h9:!\u0001,^gsyv\u0007V·sP`|J\u0017W\u001f;\u001dc=Mr2G@\u0006ߤMݏ\u0001{ރ\u000f*\u001d*zb\u0007%iU \tn\u0007}tP~÷izң\u0000\u000b\u001e \u0003dj˖+wV![Xpꆘnؚ7dK@G\u0010{\u000f\r\u0015棌\u001d|׳m6;3^]b\"#s6=?;+\u0001{~v.o[cf]y8:|88J>B}K|\u0000c>\u0001MJE\bk}gr?zVC\u0003ҽlgQ\u0019\u0019\u001eƮV]o\"Yd|*\u001f\u001f⭯\u0007=C)/c<B1g\u001d(>w)\u001d/jѐ|\t\u0010umˁ\u001ec_\u000f\u001fw:\u00022#>!!i\u000fe\t\u000f/Gy\u001aǋW/_\u0003D/c\u0010\u0000MZ\u001c`ۿ\rsT\\o_\u0001&nU2\u001f\u000e\u001eR'\u0015bBc\u0007u\u000bH|T}B>DW{\b\fםh\u0007<\u000bC\u00189%x\u0003;T^(e !7/\u001a\u001fAc\u0011?e?gXӷ:yWgח/V;|Ϳ~w6[h\f'_+Ջ(ߎrc՟Xm;:m2}bzݯ9:PYׯ=q\u0004\b7n\u000fc\u0017^Jkl\u001fBUQ?j䧣pBUgV/ݠO\\*\u0017\u0004Gʜ\fUٸQu$\u001bUw2Я\u001f']\u001f\u00073Uuk'5s\u001f\rSw?g}&>_i\u001b\u00174\u000b\ro'4\u001ac\u001c'O\u001e՝t1d}\u001a\u001a\\XQ_mWJt\fc{ҙ8*i\bTetd\u001ca\u0018tw\u000e~|\u001c\u00027\u0013D]At\u000e\u0015\u0017ổ_>\u0013B}q\u000e8i,\u0010N\u001d)>l\u001eFM\u000f6jz\u0018|}7,\u001e\u001dn8qsZ˸u]w&Ħ\u0018:\u001e)\u0015d0(1tX\u001fWl\\3wvS:1\u000f`o،3ju/WW;\u0002nr=N\bS\u0014\u001co\u001aB\u001c`\u0018/4^g]\\&6`%\u0019~\u001c7)\u0015\u000eM\u0019G߰V؄ͧւeV\u000b&\u001eckqU<\u001dƖܪndc\u0013\u0010t0:N\u0015B\u001f_@֍#ˏU,}C|rK\u0007\u0013|R\u001fzMqu}\u0018\u0002Eԫi\u0006p+\u0015\u0017EţYN&\u0013:#{@lpq[7c]) SɸڎDYtFǞ\u001fUOqM\u000bL|\u000f}I\u001bO\bM'\u0013\u001f\u0016R_X咨vsjطk\u001dwΎc\"Bŭ1n\u0018EFIo:v_eiZUS*8/=֯W\u001b4{f+\u001dx\u0019Ս~=K\u001fGy\u00177?\\NϮ.\u0012\ff?~s\u0013\r/,Gb\u000fu;SYn9&ŻZL|te&ܩSfbTQ?Ϗx_τ~7G{tqVk:xqR\u00116j/\u0018^Mp2$g|7\u0017q\u00078\f\r\u0019\u000fឺ)Gܺ>]W7r\r~1Q=vM\u0017\u0000e\u0019\u000bU\u0007W>Iވ\f*H7X$>KHC\u0006/\u001bx]\u0006S:ΏքvFITj^M\bN\u0016\u001e4;\\\\}ڤcz\u00157sv`b\"\u001e=`?oC<\u001bx@a9;vC\r-x\t5\u0002\u0016WUƭkq\u001c\u0005Q\u0013\u0003vuLz!nv\u0012i~0*IlF\u001fF\fa),ǦO\u0007\u001e|:bFC-l):\u001cQ\u0019o4:c7ЯS\u0017\u000fO~=3ug}o\u001d,0p\u0000o|\u0013Qf\u001f+\u001dK\r+n\u000fCۗ\u0017_\u000bǱ/OW\u0017߂QoO/UWG&GuvP\u001df^\u001a猺CۦyT\u0017_?7t#/z?>Og]\u001f->pzC5\u0014ڎ8\u0014dIJsBGqz2K:7n5vǷغܰi0pR0\u001b`y\u000fg\u0014A\u0006\u0017\u0010Ӽ1\u0000\bR0\u0017*Ztq5\u0003TOwKE-rWZxh݉nuIh%a\u00067\txgoT\u001b\u001a\bL-j\u0007j!ԝ\fzm\u0005a'Dg٨/?1\u0001] P`YtnFn֫`>4vi>v\u0015 \u0013\u001b\r_\u0018>cEa\u0018a-G5Ge~frl\\?\u0005l1\u0000tO\u001f/1/ΕO=(\u0015ƨK=LF~N2\u0014\u0014ڸN\u0001\tf \u0012\tVѽ\u001eu\t#E\u0005!jwy\\\u001c4\u0019\f9\u0019/XB s}#\u0004IM?\"Tq\u0011P,he\u0006d%\u0006d\u0014A\u0013\u0017g;_\u0007|jFRn֐ד\u0010 W@F~Q&\"N>\u0002MUR\u0010\u00125m6\u001cc\u0016\u0013*^b:Phsm\u000e8\u0015\u00124N\u0004EYસ[>hQZLx\u001ch)Z\u001e\u00164:{lj1=\u001cI8Li\u0019Ǯ\u001f\rkG49h\rD#\r\u0011z\ftCZ\u000fX3;L\t\u0018ac4F*\u0001q\u001bq\"\f\u0007X\\m\u0012䞄\bcGp\u0007o\u001e2J\u0017|F\u0012_CNh.W\u0000\u0004qQ\"n\u0011\t\n\u0015E~T[T\u001aN\u0013%.7b><͌ZGOQ\u001c\u0012qrXբ(<\"\u0004Z\u001eM\u001a:\u0005yV/\u0017i3rxc|dJ\u001f\u0000/l8?;3<fS\tqҊǡA@\u0010w\u000fx\u001a\u0014;3],m\u001a\u0004\u0013Cl[\u0002)ZmN͏=;\u001dTx~쓧<)D%#Lg'\u001cR\u001cۡ\u001e\u001d'\u001c\u0004އKQWs4R`_\u001021&\u001c\u001d\u001aVsԱ\u00149\n~o\\Eqg^7i\nvn󁳦P~0O\u000bQ_BNE3'.\u001a\rQ\u0011,?7oTq\u0019\u0010\u0017lOZrHsTxĭ!Ҽ5i:$dp+\u001c\u001bqN?fn3y1* \u0012\u000bڈ(\u000b(\u001d1ڳ\u001bn\u0003q\u0016'\u0016l\u0013\u001b40%\u0002qLB[\u0013Ҙ\u0004Ew\u0013&zԯ\u0019NߺQu^8\u000b􉊆\u001dqtuo5^ж!\rcc\u001c\u001a޶;c\u001c\u0004\u0019<\u0006u\u0003l ;\u0001Fvu\u0017\u000f$\u0015\u0016Sq:)\u0003\u0007n\u0003nsQ\n\\<l<\u0017d<'M|\u0004LE\u0003\u0010;㎔\u0000A>v|>@\u00183͌\u0004B\r)'\u001a\u0007\u001el/@\\:(a\u001bA;\u0011o<nRM`\u001f\u0015FmL\n\u0002\u0011\u001cP\u0003\u0019jH&T)\u0010\r)j\u0001\u001d8!;\bܥ\u001cE\u000e2l\n\u0011[$B$*\rFSp\u00075LB\u000f\u00127»x;q'Q\u0013I$_\u0006Ғq)\u0018ST\u0006ze\u0004sa\u0000 SY\u0003Ou\b\\&!u\u0010N-϶PO\u0003IIN\t\u0019pNMr1*\u0005_u\u0014\u001ct1Z{r\u0016C\u000b^L\u0006tҐ;/i\u0014<\u00180Nq\u00181z\u0019e=M杍}\u001byv\u0012'p<B?\u0000@ʮk!dv\u000ez\u0019d\u00125\u0006\u0003I\u001a\u0007\u001d\u0012![z\u0018ʏ6COksz|\u001dόk\u0013avesq\u0016]\u001c)v\u0017JD#z,~'[\u001aq!\u0018y)b\u0003[\u000f-lw9WwGD8N,4HU\u0013iVi6긆U\u000efF\u0000aw?fQStX\u001dVfS4\n;p`]\ne\b\u0016E]\nҢ+Fa%\\!H:\\x#*4n)98,P:SXUl\u0017\u000f\t\u001d?\\vܡ\u001d[x\u0006Ň;*/@C_o\f)\u000fµ1 j\u0018dK\u000bRO)n}hTA\t&\u001clWq7ũ\"\u001d5Kh3\u0013(~1ۙ0YTL㪐(HGɐ>Z.6\nP#as\\ba]xKGI\u0007[S\u001bYC)\n/Yd\u001e\u0018E\u00078\u000f!G\u000e'\u0013t 6\u001cFƠ\u001e\u0011s&h\u0002\u0000cq1\u001fO'9|ϟ?̳az|pn\u0005愿\u001611n\u000eq\u0003>\b\u001cܭ029R,SҭxGyŨ\u000e+7\u001c1:[E\u0001;EL2[EKީd\u000f\u0012Y\u001ala\u001aCCLh݉8gd+\u0004y-H*wߩ[7^Alx/v\u0001iDJ=\f∡zgTD;88,ls\u0004\b]p[k>^\u0019\u0011\u0015\u000f[*\u001e\u0005lB,3i/i>eP\u0011nRct\u0005ߠ\u001eQy/JpQyT\u000b,_}:Ud\fO\n.\u0012hҌ\u0010\u0004i򅹅\u001eP/\u001e\u0011\u0000ڥQmC30&wf>Y\u0002&\f+\u000bkbt\n\u001b^\u0006 N&ĉ 8O@,-S8to|E.\u0007/Zi\u0005\u001cV@h\n^@6P^%&\u0005lk8\u0000-\u0014;\u0001a-=\u0012\u0001P\u0015\u0000T\u0000KJ!(*º\u00068T\u00004+cL\u0003R\u001d\t\r\"&C\u0010\u001c$''M\u0012\u001c\u0018cK\u0018FI\u0002Q˘^>Y\u0014C\u0002{ \t\"\u001d\u0012ٜAY^>K%6ݖ窇\u0003*\u001b\u0013v\u0018&0\u0011\f\u0012ncd8mi)F]\u000e\u0004\u0018\t\u0006FG\u00180D@@a7Dcl])O!ԔI%pW@,mds\u000fB\u0010b$vf7\"@'r`\u000eΜ\u000e\u0004e\u001d\nX\u0015$в\u0004\f\u0004O\u0017/Xa\u001fp>w0\u000f>3}\u001a7Ӈp\u0015'S\t}!*X\u000b\u0013?PE-ڠ8\u000b%ZcLcen~FY:@_$qwe\u0017\u0012u\\f\u0018́[\u001b\u0001\u0006.\u0003I\r\"\u001aoƁ46?\u0002)\u0010\u001dʆ\u001e\u0001@\u000bJ(6J\u0002\u0014&dhAN(a\u000fD\u00063PECHj\u001fr-\u0006kEZhm%\u001dQW\u0001e\t\u001b$+W9xwU\u0000(Ŕ#\b5Dpy\u0002\u0017\u000fn-{YC\u0003[CE`x'Mwte4,{\"\u0000'Eo|T&}{\u0001Nr<GP԰eq.щ\u0010U<-\u000e\bqy\u00044\u0017éyC\u0000\u001a\u0007&(\u001b\rQG\u0001ښ9ɞj\u001d\u0015\u0006g֢\u0016\bgt\u001f@*JB\u001dgLJ-_>{y4<۴y\u0004Cn\u0015[y\u001b\u0000#~l?Fa\u000e\u0017!`FDb00R`\u0006U\u0001IҐ2s鶡T8\u000f3:R\u0007qc^n<o\u001e52:s B\"A\u000f(Rv?Շ\u0000柭\u001b\u0018G`B'=F\u001ff$eoK{/[\u0011\u0015ML\u0006譀\u0004TƟ37j\u0018\u001e'Z\u0019?\u0017X\u000b&,@=\u001d\u0002\u00034\u001ey\u001e@,1`\u000e\u0004I\fNm̂!v!#ľn\u0007#\u0012hAAQc.RHт~6xL.R\b\u001c%_EC\r\u0019\u0003}ǝ\u001do խ<uw?H\u001e+-\u001eHDO`\u0000As\u0017\u0015P\u000er.`\r4\u0004f\u001b-h\u0001&\u0001\u001b\u0003\be@Di<ⓚ7B\u000fĬu|$s3]\u001d:M\u0012'r<$\u00131cx%:*dLme~\u0011C\u000f\u0001I`=\\\u0006Fo\u0012\u0018C\u0016:\f8{t\n<P`{>Eun,\u0014\u001d(f:\u00148\u0005ӎփ\u001b\u0012Jp v\u001diXy' '6t=r~\u001f\u0000\u001e}讠{\u0017\u0012\u0012b\u0015-ႀ6\u0016!\u0016D7!C\\%1PfL\"MػZL\u0004N\u0006zsl(QS%\u0019nuh(BL:။6bG\u0012xIwOi\u000eD,x*jj0nqZ!\u0007Ӡǿݐ\u0012\u0011B\bNXD\u0007\u0007(U\t8k\u001ed4V\u001e\t\r\u001fdd=\u0011ә\u000fS*/tQ\u001c|_1%\t\u0006f \u0014'8N\u001f\u0014\u0013\"9h\u001e0B6(S\u00068j\u0000h\nN\u0002FȸP3}쉁V}<\u00154\u0017\t3\u00031\u0000\u001c\u0000|UE=!Aغ!hU?iRt{2|ܛ\u000f\u0013\ff@\u001a򃢞;\bP)\u0016\u0016#L\u0019qG>\u0001eS#6q\u000fL-q9Xgy.B)o]ΚjsÆ(\u0000\t\u0012?\u0017⫐xeS0^nz?ᓣT\u0018%5D_\u0006L\u0012A\u0004q\u0012ց9I@\u001e\u000e\u0007\u0006&A\u0014%\u0012\u0007M\u0000JE\u0015&m\"='c\u0012Qts\f\f\u001f: \b$\u0018=MM=%h\u001eH`li\u0010YF\u001a\r(Z\u001fS\b\u000f\b\u0018«\u0013X:䔶tl1`\u00141r\u0019\u000frk:'k<>x\u001b:x\u001b% m܈7l?p3B\u001bA\u0015v9aD`\u0005\u001a\u0004f×=[E\u0010`]J\u000f0<\u001eF)4\u0004\tdU`{y\u000e^+0\u0015Hp2\u001cƘʢ@?\"T\t-c\u0010\u0006t7'<}f<{vj\u001a<{>st\u0011˻z?\u0007^\u0003\u001cUAq\u000e~ \u0007!؞n%>f_\u001a[\u0013\u001f!^iyr]\u001fqЬs8%ࣘJkdiƶNל]@c\\'c2\u0007E\u0015XƸ$2ڊK\u0010*pF\u001eIL\u0014\tp8\u0014)\u000f\u0015811Mz\u0000Y'F̲q5\r\u0005\u001b\"\u0011fr\u0002dY3J\u0018FT/\ty\b 8j\u000e\u0013a᭠\u0018V\u0005[\u0017\u000e;kۣ%x4Ͷ\u001eM!\u001c^׀ :aFjުe$1\u0014гS\u001fXl;\u0011 @/M\nk::NL{\u0015bS\u0007Hft$`\u0015\u0011^p\u0012*$\u0004\u001a)\u001cYjr\u0012\u001b\t+j\u0001/\u0001$ZX5\u0003H\u00010\b?Z\u0003t7\u0011;G<H|\u0011Ȍ\u001f\u0000y\u0003,1wG]\u0019\u001c=3gp\r\u0019 :Pܨ\u0002ȥx\u0006.\u000bKB\u000f\f\u00015x\u001d:B]\u0018`{`a*A\u0005I\u0012K\u0015Mz@\b\u0002\u00199\u0010RH#qJDgAcRx\tz\u001c!1\u000e,2S\u0005BNE6L\u0013t.}\u0005ː^Fܯ\u0004Afp@f\td\u0002D\u0012#R6\u001cP_c\"\u001b\u000eqh[\u001f<E\nW&\u0011 ? e\u0012O&#C|z:\r\tF@1!l\u0014ň1fo\u0006\u0007c<?}jt̳g\u001f\u001ej\u0014c\b\u0011\u0017:\u0010_²yO\u0011\u001bFxM\u001dC.\u000b=D2_\u0017P/jk+\u0017\u0000[?C\u00193GnK\u0007JF\u0005ž\u001ea\u0011\"\u0001)( V?\rwm\u0012Vݔ3\u0000NAHZhh;\u0002n=)8\u0012i\\ԉ'\u0010C\u001f}Zq;GLp\fI,4`k\u0002\u0012`%ˌg\bzNdF\u00029\n,h\u0010g\b\u0002\tjc\u0014.\n!\u0001Ν\u0016/n3WBL]6*`H\u0007ڃ\u001a\u0016S)AKG\u0010AQ\u001e\t,c\u001d75\u000f)Bѓ\u000e\u0017N^1}Y3\u001c&ޔ}\u0012B戺#\nH\\`\u000b'U2KH*<+\u0013\b?;TebG\u0018$R\u001aUE> 1fU%N$nE\fjsA|\u0006\u001fgO2QgY?<cpY܈Y[gɞ඀n̮^\u0007\u0001\n4*e)=,\u0000N\u0002\u0016ӭe\u001d\u0016LV>\u0014|||,PnVLJ\n;/Aa\u0016ƍM1Zq84n\f\u001e\u0000;'\u001ax[D6eXEcU~iAGR#!y):C̍Qur#\u001fdI\u001b;\fV0+0\u001dH{\u0019x\u0000\u001ef\u0006dd\fH\u000eĭ\u0017?mH\u0003B \u000e\b*H|\u0002K\u0010?\u0004WF4\u0005녋FP1?1\u001e'ǖQ07dt\u000f%΄Spɗv6\u0012Pן\u001a%P~Ʊ߻a=\"x\u0018cgF;gb\u0000}8B\t@l\u0015O{\u0018y\n03TH-H*THhDܷ(+оbȈ$sF*\u0013?hqh\u001c\bV\u001duvHMޏRfעăKgqb~{bڋ+KK\u0011%O>+|\u001a4LU\b\u0005%6G+\u0001 J(\b\u0013YpK\u0002-\f,ɠ8̈́ 1\fu4Oۉ\u0004\u001d\u0019p C_\u0002\u0000Q[z1\f\u00060Nr\u0002\f`\u0014\u000e|fzܑ$|Vc㣊1d\u0000`r \"\t\u00184\u0004\u0006a\r%)Hc\u0014.Q6\u0004={D\u0014Y$\bz\u0012/\u0010\r8*H\"/V\u0005\u0015T:Q_\\pgYruNR@Du\u0005(΍\u00113\u0016EQ;,n 7Ai`\u001a_53kg\u00141\t\u0015yܚe'\u001e\u0014@lW`\b\u000b\u0001K\u000bC֑(\u0019ZOb\u001anNM%XxiIw\u0019\u0011\u0015S2t\u0013\u0006\u0012[ci!\u0002\u001eQ@C+dvVX9ՁwBf`\u0013F\u0002Lm=RY\u0005N\u0018ru8zb9x8oF뜣5p/5İjǇIvV=Q\u0019Jsg.,CEB\u0001aޚr{oHI\u001d\u0010\u0006d^#\u001c\u0006Ln|\\mr\u001e8Ol<tY֯\u001b \\o\u001d\u0011D\u0001~r츃*=)s5\u0007I\u0002VgwuZ2/\u0001X\u0012>WD$\ne%1Jv%\u0007D;\u0015\u0010+nnSgҹ!m\u001c&\u001a/SqGlZB%[X;\u001bF7\u0019(\u0004\t\u001dq=\u0018&\u001c.NN*ҦW\u000fR~<2@)\u000e\u001c=syltp\niЂ|\u0003:RDQG7S@\u0000'ʍ\u0005\u0014SPLHv*\u0011)6\u001e5;qyUZƅw\u0019\u0015\u0011\u0018\u0002|!'!-3@cnj:\u0006|ֵB\bۓ$~BM&\u0007jWMp)uA\"cAt7T)jR2|\u001aK\u0013K8}|f:\u0001>}y\u001ef\u0012;\u0007(5\u0005Sն9[\u001a-A$?\u0010 U▗ƭ~\u000ekY@jߌ\u0013hslN3Ӝq΅m2Nl\u001dr\"\u0014\u0018^\n) 3]23֝L\f`L<\u00173\u0005R\u000eɊCRf#\t\u000eV0 rik\u0003Up`\u000bKu(.gS8\u0015\u0015lI\u0002\u0006mͅ\"Nե0\f\u0002Ew:\r'\u0001K\u0005D,|mG\u0003\u0007:/Rew\u0002w\n81v\bH윛\fHp#\u00114l(\u0001IF\bEA&GO\u001fRI#^\u0007Y[i[\u0010K<%L\u000f|\u0015@\u0010\u0017N5h\u0006f\u001a\u000b! \u0007j)O\u0014!q*d)$%\u0000u\u001bPak8\u001aT\u0012 dUMX\u000ff VM\t\"JK\u0004\u001bE~낄n\u0012\u000b\u0005\u001f\u00192\u0018\u001cHCZ\u000b6\nP\u0005\u0013E\u0002 )9I&|\tCZO\u001d\u0015*\u001aɉ=\n\u0012SU$1Arɂ\u001b\u00160c%t2Ï\u0014,\u0018%\fU/G\u001c@g97(\tr\"h9v\u0017eN|&(T\u0003\bcܒ\u0001p\u0019S\u0001`T\u0016\n\u0003I\u0005[\fi*\u0012$\u000fX*ig\u0014\u001erV\ncP\u0015_Ict%Ѝya|4=ѱqN\u001cD<WvPKW\u000fP>.\u000b,zF\u0014=q&j~viѨ`㝷\u0004V\u0014ٲM\u001b_6gn\u0001\u0012o\u000f\tX HV\n2\u0004\u0014\b(n$\r$'HдJ䏛k\u001ay8eS\u0001$}61[y:ƈc۶\u0006ɻyX\n+NW\u001fV\u0004!DةXzHĎ#ةI%eU%\u001cXt\u0002vzW]\u0012\u000fUu\"\bNd˜\u0019Zݔ`+E(շL\u001e\u000e6Hk\u0014wax=`CTd\u0018\u0018*\u000eJ\u0018msA]\u001c\u0007'ɢ\u001cOO\u001eL\u0017Tp\u0001i.{\u0016-\u00073q5$y\t#\u000b\u0006/\u0000p0a\u0012,Ӂ\u001cG*\u001c$\u001aЌPL!\u0012aEnċw\u0002\u0015Et'S'Aޮ֑PKȐC-uzO\u000b8)gm9\u0018+}}U\u0011j7ϒh\r.B\u001eU?\u000e\u001fV&aS\"5=\u0002ۿ,t6ym^ۿ\u0017߾?eE\\6\u0017~\u0017\u000f\u0013\u001f\u0012Cjm\u0001a'\u0013fO]\u001ftV\u001e^w=<\u0010pb\\a\u001d.\u001e>p,^\u000f\u001f\u000f`l;A~\u0011B{-\"GQ\u00191`\u0011\f\u0010\u0015(\u0010^\\C^\u000ez䓙ulI߮p[\u0007\u000eC7Zc\u000eFn~!`Pv 2j \u001d\u001e6l,\u0012\u0003/|q\u0006a|'\u0005|\u0001X>XEI/q~%Ӟ,^1{\u001d(\t\u0012Vs\u0010\r#\u0007bV0B;\u0016\u001bES\u00157忏\fPMp\u000f9X\u0016B,\u0007;P$'I;!%m%Byz09i\b\u00013\u0003\u000fq\u000b\b\u0007ȟ\u0015\f\u0013\u000eBr#DCIRъ\u0004\u0014lcDIOFi\u0003\u0013\u001c`ƗDA\u0007:z\u0018\u001d0\u0006{l\"\u0011\u0019$\r\u0002C\u0012!\u0005Ѫ1Ixkfjp0\u0007Ew\u000fY\u0000%\n\u0019\u0006\u0019@\u0011\u0006wc\u0003JH'a\n\u00055<\u001eu,\u0002+-\u0007]'\u000f'B)l{\u0019o b$\u000e\u0003D׉>>^\u001c'\u0010=?r\u001b\u001a4FƩ\u0012\u0005u2;\u0011lwdY\u00140\u000b ^\u001cWA@*!b\u000ffZ\u000e]ޑF\u000bk\u000fߏ@\\xlҲ.\u0014\n-cYcE\u0000͚\u001boQg#^U'_͛3\\[\u001fåj-?4S+pq&\u0003\u00012\u0014p\u001c\u0012[\u0016]vR\r\u001a\u000b\u0018 .#\u0010dkDx>WSG<\u001a&rpYb\u0007ØbWF\u0018\u0006\u0017Hcȫh\u0013\u0010\u001a#Dcc8.\u001bt1q?$I\u001c\fO,Pxa;p\u001b8}\u0006\u0016H5I\u0000۱,\t]\u0016#FJ\u0005K0 \t}P\u0012\u0012\u0019w9\u0018S\f=h\u0006d(+\u0003\f%0M[YkOkV:+_`102~Y#\u0019&:2\u000bj\u0018P\u001dp pJ\u0010\f\nԱ\bf83+M\u001f\u0019䞣aN\u001d`\u0019+k\u0003\\hFp\u0002 y\u000fE \u000eJJXL\u0014v\"X\u0013ǽ\u0016y\u0001\u001a%_7ֽ\u0001Yu-e'W\u0007Gg^PLI\u000fݕ:F񼌛i/I,\u001c\u0003)͒T\r|S\\!\u0000׉NTmtN#Bh+c}H5χ\u0001O}ŽߢLw*[\u0003\u001d\u001c\u0013~\u0000݊{[X\u0018דT&9p S/#+Ot(\u000ff +q\b;\u0018RYC3r̀$#p\u001f8\u0007\u0005~=-s(H\u0006=\u00045QEA^3\u0001g~\u0010rOtx\u0013\u000e?-_\u0010Q}&EbCMD:0!\u001de\u0006p\u0019_4X+\u0001Рl\u0001ܑ!\u0004'D\nb\u001e;Z\u001c(z\u000b  3$;T܍Dc\u0019`IO'z\u0010g\u0001\u0002By\u0006\u000b1e\u001es4H*\u0005+ZN\u001ePa1#\u0004\u0019\nM\u0003[1F\u0017Zc'\u000eU\u000erc\u00183a6\u000b{\\\"\u001ayF\u001axkc'\u0004^A̛\u0004\u0012$\f\u0004j9舃5\u0000\tq80\u0018\u000e#Ap\u0004\u0016N\u001aLypaB=\"kH֎>R,|xV(qV\u00069੯]}C\n)~@C#s\u0013+\u0018\u0014Kv6dŮ2']z\"Q\u0003Zpx[QS\u001bul5*(Աt騉 %ԉw\u0002\u0019\u001a]T\u0010@\u0016QKV\"Ë⚌\u0013\b\u0019ՍE%bOз縋0\u001bXG)|\u0006y\u0006\u0007<|yddT\u001c=X\u0012 \u0014\u001cqB\u000e\u000bz>%`;\u0002ql-.\u000f\tx@)\u0018]JhX\u001d\u000b(~I\"=\u00124a<\u0019X袱4aKRxP쐄\u0017zec8+Z_\u0006\tWL7jB)\u0016I\u0001\u0012\u0012 5\u0006\fH}KT/\u0019\u0011s\b8\u000f}ʐ\u0014\u001f\u0007C\u0015\u0019[Z(\u001c\u001b>\u0005|K\r,\n\u001aMfDƶD]s`\u0002\u000fgbˌD\\?taZw\u0005e!wPhaO))BAINM\u000b:A&W-JaƮ'0yhB\u0013OgKs6.\u000b/\fiu\"\u0016\u0003>v(u^\u0006*G&1\u0013\u0002T\u0001\u0018-\u000f\u001e\u000e\u00124L\u0000E\u0014\u0017\u0014&N\u0001<$\u0016Oi\u0016RВ\u000ejт[;\fN\u001d?\n2\u000bc;\b\\hVz\u0010j\u0010\u0013`:}\u0016\u0000k\u0003UȚnv@\t*\u0010a*\u0015B\u0004\u0014C\u001dMRd, J&s\u0019\u0019̣KaI\u001aio,ջk+4\u001b`{,\u000em;7\u001d%c\u0000#+q&\rqۥ+\u000b@ĥ\ffp\u001b\u0001D)\u001aFzHGk\tӁ>Z\tF\u00173\u0004or=7''Ƿ(W\r,v\u0017\u0010?vn\u0013Ʋq9\\[\u0014~l'6w4\u0005\u0014b,\t\u0002Cl^\u0000=V}ܗpB#݋\u00102:z:*\u0001f\u0016\r\u0000Sp5IDY\u00050K$`\u001a\tYPcQ3|q\u0005\rp^\u000bv0܊\u0014'\nG2hK!\u0016\u0013Z\nu|v\u0019>r>2\u0002_>g\u0010}\bYEw\u0001eS`<\u00031E(ڐl6A(1$Cp\u0004^a>I3rSni9.x|\u0013\u0010.)@xGs\u001cG\nk\u0000ma\u0000\"\u001cq\u001a-\u0006\u001c\u001dq˔\u0017\u001b C6\u0003\u0017@`e@fD\u001dQ\u0003R\u0014\u00045\u0004\u0002U\u000b\u00018S\u0001\u0007\u0006sX%$F\u0005VqcC\u001a'\u0017,j\u0015M/Җl۫#]˱Oen-.\u0013\u0018YRʱUlz\u0007Վ5=\u001f쵝PZ#Js4~\u0000--\u0011&ޡ\u0016ZŒ\u0012V`\fwO@e\u0017\u0017ClyҺb\u0017qOM\u0017㹻i3buR\f\u0015p\u0015C\u001e\u001a>'<\u0010\u001b>1E9$\u0006NFv\u000f9,\t1.J{֝ۡvHT!`)434\r>H\u0017]KVII\u0010G\u0007ebE\u0019_!$\rq#sjKa/!b/F4{\u0012\b]\u001c\\Spxq05DԌy\\@AH,+\u0000|i\u000f1C\u000e\u0007fL\u0007vkmiA*\u0004m&\u0013\u000b[<dYhJ\"\u00024\u001du\u0007M)\u001aR2}!\u000bb\u0010:4\u0010\u0007\u0019sG(\u0005\u000f?'8*V=\u0007PCiҺt\u0004\u0003;0_#`\b\u0015HI\u0015ǽ1Br.\u0002\u0013\u00003>\bE\u001a\u0000H\r\tH$ڒ^\u001cɧ@ \f0\u0001 #t@Q`\u000bߎ3XIrd- \u001c0(\u001dMSRݘ)i\u0012M\u0013,CE\u000bDٵNTs 6k`(h#\bRM7+\u0005\u001aYpצDy'BEB\\\\P]p\u001cD*>`\u000e[az?Ȼ-E*^)P*|UJWI\u000f{^j\u001b}bڠ\u001fHq4\f|8\u0015bG\u0006\u001f9b\f}*\u0002@ۥjNb\u0002H\u00158/lt\u0006Ю$oD+cDwR\nN.\t\u0001z\u001a83a\u0004ȍp];iLCuҠ}\u0007TKy<2`К8!0\u000e26D16go\u0002B@D\n \u0007$!\u001d\u0017{\t[FF;\u0001,\u0013\u0013U\u000bڐ\u0000\u000e-\u000bU\u0011\u0011\u0016\rE%'Wz[?/\u000e\u0005\u0005YT\u0001hP2\u0013\u001cZwGD r\u0002^ߞy\\\u0003?BeU}\u0007\u0018\u0006\fcZ'3!\u0012\u0019,o\u001d0\")\u001b䁟g,lfǭ\u00003BƉKX<ڊ\b3\r3#5enNpO=ޭ=7b4\u0004\u0002!QI'\u0012\u0005Xy<𧩴P@W-mUZ\u0000A>$8X*B,+\u000e5x\u001e+H;ѽD\t\u000e&5Y쐸PR\f\t9~CT$\b\u001fx1\u0017ȅ%o$\u001aAb\u001eTIW}j\u000fʆ\u0000\u0007e\u0015SE}\u0011&(\u00059}\n\u0006N\u0016襃ܳ`SH?\u0016%\b\u0007Öx\u0019ttTv\u0015D\u0012E\u0003܈\u0017\u001697𕼃cN=&tp\u0002e8fƜ\n_sR\u0006\u0003p\u0017\u0012!a<7Q@\u0010\u001e;.<ú\u0017\\>>Y6vA\u0007\u0011bwuĠ6/\u001eH\f-b̝mg\u0015*D~9\u001c|*\u000fn\nq\u0003TkYLbOS\u001d̥\u000f\u0016\u0016K_\u00035bJ̢( 3/\u0004\u0003-\u000bR[~;6\u001c|J*^CH\\|NȊ\u0018bD]:\r'_f\u0011\"1\u0016\u001cA\u0002u\u000fNW\u0000,\u001d\fb\f&T\u0004\u001b\u00045fp'8Hx\u0007Z\u001eӝбXw\tʢ\u001c%\u0007=6\u0018FH舓\u000eFn\u000f(\u0000JwhYn\u0019\u0019%lX?3u0.hF$\b\u0015\t,&\u0004\u001d\u0017\u0013;6$9)P:\u001eԝL<.hOU\u0018\u001fJk\u0004W\u0002A@\u0018dxw\u0007,\u00144vt\u000f6xd\u0012\"\r;F\nkF_|3*\u001c:̓\t\u0002\u00060Xס;B6Y\u0016\u0002\td\r\\a\u001e4k,%\u0014'`\u0001b2&&ݫ\u0014وe7\"FA,F\u0001x\u0010\u0018hc\u001eR^B\u001a$X1ܩA\bփ\u0019kx\t0q1\n\u0017^1Ǔ^\u0005'\u0012\u00197'՜\u0015>E`1\u001cڼ9G\u000e\u0012\rKz߉\u001c\u001c\u0005Sѳhw\u0019\u0015I\u000bn\u0018*\u001e\u0002#[\u0000tC\nuśD0\u0015\u0004]\u0013}\u0007a-\u00169~IcAyn>,ݻr!X;\u001caD+\\߮OKVl\u0006(\u0018\u001f,\u00032Bx\u001e\u0001\u0011:|J=\u0006)`\u0003wp/#\ts68N:r-E\u0011x9\u000eoTH\u000e6FMxD<\u001d28.@\u0016b%c\\h@v\u0004s\u0004GZ\u001cHBI\u0013^\u000ehWO\u0004\u0017\u0017%[q\n`9P')y\u001f{C@\u001b\u000bhU|g\u000f\u001eAn\u000ejm_\u0019C䒾#5%\u0012Jd\u000e\u0018\u0007\b\bI(s\u0011FF4J<zM\nkH-9h\u001d vspoX-\b9\b<q0\u001c*W\u0004\t!\u001cJWcV!1\u001f~5\u000ec!Dr\u0000 \u001d\u001b q\"\u0016Ae>!8\u000edkT5no\u0007{\u001aSH\u0010\u000fKX['\u000fB\bF\ng6)O\u0019:\u0019{!T]\rm;\u000f\u0010V@lK΄[Q\u0017N>l\u0019\u0010f \r12>\u0014f\u00143\u001a\u001cb[\u0011dg>;iJ\u0007\u0016@\\<\u0000\u0010\u0000\u0002?\u001dk;$K\u00179\t\u001e<S-JZ\u0005AN)\u001a\bʒ0\u001eZs1tcg|,9Qw\u0017on^zvJԹ@*sn \u0006^/0VI*\u0000uldw\u001f:tB4q}\u0014?\fHDЫ\u00010h`ʠRBB$\u001a3qs\u001fBdP\tF9$HEuRn2\u0003RELT\u0011j;\u0013ᬁLK\tPNh\u001e\u0006YTӨ\u001fF\u0001\u0000Ԅ\u001b?a8ku\u0005\u001c\nxD\u0015\"n\u0010\u0012\u0000`ɠ!1 j܆c\u0005Ax$㔍Q\r^|\u00051I8ddF\u0002\u0014L ;\u001d\u0012X_\u000b%>H0\u0004\u001d-yŽU<=\u0004\f`<G;Ĝ>; !5@!>֬\u0006'_/ӈA7\u0012\u0002k\u0003w!#$0 \u000e\u0012a7\u001a<d\bm!\u000018N\u0003\t\u0001MF\u0014[1RRaNp\f\u001dE>\u0007\"Z\tA@bo)+9w1nP\u0001\u0000\u0003\u0002u\u0001e&\u0002nʺg\rDT\f8\u001aȁN\u001fB~\u0016AJr\u0013\u001d3I\u000fG\u0013<\"\u0015Öө&\u001cH\u000e\u0012\u0018<\rF\u0010&\u001ew\u001f)ޝƭ@\r**}\t(b<,|r\u000f}\nլ.@`\u0016SN\u0016xO\\W\u001f<&eH-81\u001b\u0012\u0010$AS\u0012lzW\u001e!\u001a6tHȓ\t'bd\u0010`0ԗTA$\u0015\u0013\bZ\u0013t\u00105\u0018\u0014Pn\u000f\"\\\u0018J\u0002E1g41c0L\\(*\"\"cn8Jx\b{ld\u000f9:Ql\tr\u001f];\u0006B!\u0005Fe\u0004!.feDOi㨕y\nYҪ\u001ba!',\u0006/aY\u0006\r\u001d짎RxްӅҖ:Hٱ8e`\u00038\u0019\u001dA\u000eDh\u0003\n\u00116#yH\u001891cQ\u0003\u0010\u000fA\u0000\u0012\u0001gr/\u000b]p\u0018ܣ\u0004\u0019#2S,\u0012\u0014 02\u0006+EE\u00196tK\n,'\"hBr'\u0019R\u0012c\tG8xL\u00168^O\u001aAr;\u0015G\bH\r\u00192\t\u0011C/\u0010\u0018v\u001b&@U)\u0002A3a\u00056,yŅ\u0003\u000e<2)&) \u0016\u00155XK\u0007$\u0011vl\\AzE\u00110I{%ŝL%y \u0012*8z\r_o\u001c\u0019S`\tjQ;'7-c\t,pL\u0012C\u0018\u001f0WY\u0010G\u0004$Gݐ=$SC\nSG\u00197F\u0012PɈչ%Bd\u000b\u0010IuŚ#(q\u0018`4.\u0010{E\u0019\\*,$G)aҡ\u000eYlal#%)\u000b!\t\u0002}J +^ \u001c\u001aC,r\u000eENW\u0002\u0001WA\f.A.^V1sp\u0000;\u0016!\u0013Kǃ\f簇\u000fx\u0012\u00191qy-G*&H\u0001ADY,})\u0016eŒM\u000e7J-G(\u0012M$\u0001e؞N4ΠS|EK촠$?\u0000ߣ,\u000f⹒\u0016iCR\u0018\\Op\"\u001c\u0003\u001e `8J.5E9m;]\u0001ӚE'+B\u0014P\u0012\"mA5~f:Id]b\u001e(\u0012\u001f\u0010p>jlAK&h/*H^\u001dcœ\b-DPA\u000b\u0001?\u0016`D:?-,8\nR\u000b\nһ\u001b\u0019K?8,ﱹ,;F\u001czD\u001fDA\u0016{*Tia\t\b\u001cME1Y*\u000f\f9\u0015n\u001eXagA\u0004 `L!\u0004:-?z\u00074IKGH2dհ\u0004F񄀊bx&I`\u0005:\u0003\u00111ʨ:P@\u0000g\u0000ǟ}N#3B15\b1o\u0018 \u00178ՠ\u0004'\"L\\ګ7mh*ۺ?e\u0004v߈(!\bb!\u0004$&s|>1M\u001a TQeY'\u001cX{կٌ9f$=2\n\t\u0011{J)T\u000b\u0003\u0012\u0011D 'o\u0014d6®o(+\u0012$\" \b&\u0004ORI\u001b\u0003\u0004\u0007{dC<\u0007pNʀLm3%Q\u0017L\ti^`$IJ{9\nKT`\u00133\u0010\u001c9\u0005\u0000#d\r聬\b\u0019bl\u001b\u001e@X<;0\u0000+d\u0019=T\u001e0H\\쁇B\u0015Z\b3\u0004Xh'\u0016H\u00101z\u00104F\f\u001eW+<#\u0001\u0000eMҌM\u0005\u0011**|pM\u0003\u0003s=Q:l1ߋ啜,;ȞD\u000fgOбg\tDJD/~KV\n\u001f\u0002$\u0002x\u001eaů0OzRY\u0017} \u0014\u001d5\u0018{\"PA\u00014\u0019qF0GG\u0015\u000eqsn4\u0000fQ>ek)o\"\td4yD\fW.\"v\u0018\u0011H\u001d§!i=\u0010\u001a1\u001cB4~a\u0016Vl\u0001g3s2\u0016\b\"^a\u000b#AJ\u0014'H+\u0016ަW\u0019\r4Q]搆!T\"\u00149Y\u0014\u0006\u0004\tw\u00125$\u001e.@ݘ]6VR\nۅ\u001b\f/8\n#Z6djܢ=B\u0001)al\u0018y\u001aű=$^;\u0016m~DCaD9tD[\u000f\u000e\u0011,\u001e\u0006\u0012g\u0019\u001f\u0006-\u001c\u00127$P\u0000Q] E \u0006\u0014\\HD\u0014l\u0019H\u0019`ѣ\u0006:\u0012.J)kI\u0003\b\u001b\u0011& %\u001ev'\u0005h@q\u0010r-\u00021\u000f^,*ҁ:șHA5fETP\t2Sݷ\u0018(O\"K\fb\u0017f\u0000\u001ds4f`\u0005qx\u0003ȁ\"^'\u0003]@P`e\u000f&KW2\bF\u0001\u001eit\u0011\u0013\u0003\u0004]p#_\u0014%\u000e_\"[\u001f\u000e\u0002A\n\u0010iC[Ef\u0000X&\r*˦^f\u001cǱAedb\u0000u\u0005c\u0014m\u0019nǴg\u0014i`\t\u0001ã\u0005bIDJ\u00137Ao\u0004jz\u0004N\r-\u0006)K(\u0001eA,+T\u0002Z sԬX­\f\u0013\u000e^p? L$K3\u0005S\u00102\u0016r\u0010I<0@ʪA'|\t>C*p\u0004\u0018\u0015\u0005%EH$$jI\bmxM\u001d#ɰ$\u0006PŠs9Ga\u001c\r\"D;9?\u000e\u0018\b1@)O\u0011\u001a\u000f\u0014+57Y\u0018=B*f\u0015-Mu(#boQ\u0001$\\C\u001bab#h\u000bD\u0001@\u0002NqL<\"Q\u000fIMPO1#\u0016\u001eঐD2.!F~\u0000\u00177*\f<,2s\b(5^c\bJ?K\u0003\u000bKN_H\u001e\u0003\r\"\u001bI\u001ak\t%\u0010D4\u0007\u001f[d;\u000efjE\u0012\u0010!$;JThXT\u0002Z1uR\b\u0002&ل\u001ez\f\u000e`'\u0003f+\u0001\u0019\u0018Q\u0018k\u0000Ò20e]!WP\u00183S\u0011f1+\u0012\u0001$D{61<gHh@N\t'\u0019w?lϤDL@r)A\u0010$\u0013\u0002@e%D;&\u0013NXH]\u001aw,W>-\u001c<!\u00055œ\u0004e>S3P\nsX(ȁ\\96|u\u0010y\u0001B\fK\t\f\u001f$Hߒ(!=db2\bWv'(\u0017_N|\u0011ۢ'|\t\u001f\u0002\u0013\bNZO9 \u00025\u001a\u0018c\u001b\u0004$\u0019\u0012.AhĐW-eb\tZ5\u001d1\u0018T\u0001. Q-of6\\\u00104 &VZl\u0016\u0010`t\b\t.4r\b2P\u0019\u00189\u000b\u000f@\u0019\u000eJ6P\r\"q:e\u0003\u00135~},!7|L\u000ff\u001dɨ+\u001a\u0006\u001ei,0.߱-G\u0000\u0007\f@'$\btA\u0007\\Z.\u0011 H1n{n%J֘HDiN+4<\"\tC\t4F\u0000t;\u001avjXD\u001c\u0013\u0014@\u0000\u0005m6Al[bD\u0000#zB!\u0001\"\u0011\\\u0011BF\u0004C\u0005ր+2h\u000e0-ѳ\"a\u001a\u0011\\\t`d\u0004`\fZ@\n`<c\u0012VN\u0011.cU)\u0011QZ\r{'G\"yW$\nJKC'ˣ\u0015wIx\u0011\u0019\t\u000f)j^-3nf\u0013/ys8xȄ1\u00069}vA]c3R?/\"n.F\t,*iPlP\\`\u0014h\u00018\nHJ,l\u001dP\u0012\u0015LbF\u0002b,%\r\u001ek\b'\u000eg\u0000\u000b!~Yc\u0012=2\u001axe\u0004\u0018ǘՕS\u000fZ\u0007#\u00111\\D\u0004´\u0000ӏņ\u0005ٕ-\"\u0013\u00121k\f%u+\u0012%\u0014\u0013Rj1%\u001bp\u00040:\u0016!a:A\u0018\u0004\u000bHc.@-T\u001b4\"AE\u001eHgv9M_\t \u0004SL@pA/oR\u000e|\\¾r|Д犔)\u0000:\u0010G\\!r\\H|)\u001dۊ\u001623\u00169hRG(\u0015%@O%\u0002᪁\u0001[\"\u0007mq\u00018e]\r*.TX7p\u00032$.sE\"00M\u000f9<ʈʤ\u001bsGm\u0013\f\u0015i<5Kl\u001fw\u0014!%:\u0002\u0000P`ǲ,HkyA\u0007P6\u000eeeNJD])qUP=a\u0016\u0001l\u000b͇\u00027*AE^z\u0014cb!I\u000f{\u001f\u0013)\bO\\'k6\u000b@#߄1'N\u0018$\u0012h]˕\u0001L\u0013n\u0014\n\u0011M,NU@-BGewX,ΐ\u0013KT@؞↕?Ѐb_C[\u0014\b@n\f/fLN\nG\"\u000f\"\u0007zbEk$uC\n\u0011y8i\u0003w`G\u001e2\u0011>e\u0011\u0002 \u0002\u0004-Ik8dł\r|9m̗c6O˞!\u000b\u0002yp\"eQ}M\tHI\u0003b'\u001a.\u0005\u0005\u0012tX\u001e1rDBp\u0010Q\t\u001d1\u000b\u0006;,\u000eHA\".\u0016_ږ@\u0014`L$\u0011\u000f\u0003\u0010`n\fcGĨa!p#C\u0010$QXe \u0014k$:\u0002`&_i+$\u0012p\u0007\f!on9麁\bL5\u00069\u000b\u0017(\u0006\bt4%\f\u0002 <O0x^RE ((6\ba\u0007?+\u0012\f]ie\b\u0016\u0011\u0010IA\u00184\bԑ\nD=T\u0014\u000f\u0012\u0014\u0011<\u001d\\u4\u0010LҾhh'\u0010!Y\"R_\u0003r\u001eZ#U\u001fO)K8\u001fɛ\"F@\fp\t|\u0011\u0012\u001ehy\u000e_\u0003M\u0018<\u0013\u0005QGPq\u0002\u001c*K\u0000RP0\u0017mk\u0000CrY\u0010FZxxRj64\u0001\u0003p\u001d\u001aD5\u0015Oo\u0015'`Q#\u001f\u0005tkj\u000eB=Q3^8H(|\u0011\u000b\u0013)Ka̐\t\u000b8<DGPm\u0010*V1$<\"\u0018E\u0011i|QGG\u0005&#C\u0017\u0014N`\u0000\"C`C/g޾\u0001\f-I\u0007$b|Jlxjɒ;ⵢW^iu1E^\u0012\u0013E\u001b\u0004DRI\u0007\u0000!BŊ\u0013\u0015V:iM]1w\u0018f\u0011\u0019g*\u0014g7\u001c\u0011\u0004g\u0016*Ak\u0014^!kGA\u0014X \nO\u00124?\"\u0005\u0012)I5`tf\u001dX$,E\u00076@T\u0019*U`\u0011*\u0013\u0000\"\"Vxxb9a~\t\u001d\u0004a*\u0016\u001a\u0011\u000f\u0013v-B\u0000&\u0010|/|1ʶC*\u0017y\u0016n\u0014(#\u001c(\u0002\\Uc\t\r\u001a\u0018\u001c=l\u0007\u0010\u000b\u0012P\u00102h\u0005\\^{0\u0001I\b:e\u0017,E\u0005\u0007-[</\u0010aPf\u000b\u0006.'\"&gQ'd\u001dϓC\u0019\"КE5k\u0012_ѶU>2[\u0018LX.\u0006z\u0004\u0018i(\f:\u0018w23\t}\u000fR\u001bn5\u0011֞ĞjYBMȵ'%v%m*\"w.e<iI\"C\u001cw:Ǥ\u0011\fm\u0004씸!=~\f\u0005\u001aXp6\r\u001et\u001c#\u0005f\u0010$m\u0013\u0000G\u0006J(\u0010\u0017\u001dU\\Y(/`zxVڑ\u001e%6#KAZpt\nd6%\u0011\u00167ZmکFsH0ZbIء.\u0005KdP^RQF\u00131\u001e#٤\tK͜oD6_$J\t/\u000b.O[Г\u0001niN?\"\u0007\r$⛹`-'#]N\u0006ªGX\u001bcwMا\u0015(\u0019\u0001>6\u0000\u000f\u0019\u0013\u0001\fI]\u0005FЎx\u0010a\u0007+\u000bg.\u0000\u0013 X\u0002\rvCŪA\u0007S\u0014?}D\t؇\u0002\u000b:/ҭ\n#\f\u001a\u001c\b/\u000e[\u0001|\u000b<0H\u001b<,F\tk&Y\u0005\u0000\u0000b)B\bFA˕,1*$ܴui\"(|w8PB?_Yn[j`e8z3}\"m}s\u0004[H\tyzv$\u0001v+0I\u0002\u000e2/bA\u0004ϾF<\u0013!\u0014\u0002X-Uo<MH<%ⷔ(%f^儶\n<9\u0007vah4jС&k\u0013/Q\u001elh# |ȴ\u0005 )?\\VS*B3YmJp\u0014SA\u0015KꎐnU=ódZ8J\u0010I\u000ey\u001d\u0017N\u000f]\b(w\u0007'\u0017\t-Pii\r)D\u0014o\u0006\u0005Ǟ\u0000Cdi \u0005\u001cV&'9\u0006VIjy\u0002\ba\u001a]\u001dO%G퍡H8<Eb\u0005̧_ߖ\u0017[$#4Ew2\u0007L\u0012¡@c-f\u0014\u000e\u0002\u0011d!S`\fY%cD\u001bͤ>A\u0015(/!xec \\P\"v\u0012G=OXW8 ř\u000fh2\u0016\u0005<\u0006×uf#:\u0005E6Q\u001a\u0019\u000bM\u0014\f<\u0004H1\u0004\u001e\u001dł\u0012\u0012=\"c'9{ż\u00199\u0011O!6}\u000eJ;~\u0013O1k\u001a\u0006`ר0 x\u0019\u0014`\u0004 \u000fLF\u0014\u0011iؼb\u001fY\u0013'\u001f#Ěv\u0002{bGd\",\b0DF\u0001\rFs$\n\u0001#b$9DhA\u001dт\u0010źe\u0004k6\u0016J\u001d*Z \b|\u001d\u0006ĵ :\bB$\u0002D`\u0019\u0000!J&\u001d\u0000B\u0018D,(,C\u0011m\u0000~$$\u0018J\u0001PT-A\u0004.\t\u0003@US\u0000 uR00z\u0004p\u0017?IQa@e \u0014Ąqc\u001a\u0018qO\u001ad\u0014Q\u0007G\u00131!\u001eF\u001fq{0ڂSx,9\\p\")\u0012Mf\u00183VH09ZBI~\u00003vu\u0014\u0001/L\u0016D\u0016\u0006176\u001c\u0005\u0012Q\u0010\u0002AK6\u0004\u000b>\nu]e\u0015\u0002Ec\u0014\u0001\u0005\b\u001e-^W@\u000b\u0004\u0014\u0010/\f\u001c.ӖDעj+\u0001ٞ}G\u0004a\u001414-3\u0015\u0000\u0003_\u0010x\b\u0012hL47\u0016\u0013\u000bJ[2kF5\u0006\u001cLs\u001c\nzD\rA$b<\u00129o7&,%F\u0003&2\u0002X\u0019v+\t<\u0012#<\fb)Ֆ$|p\u0003\u0016n&_s%\u00163Q%FqhBk\u0015N\u00141\f/xL<OD\b2\u0013o\u0004*Ul\u0014v-\u0016I&5.U@,\u001c\rw}*\u0010\u0014#\u0019\u0001jY\"f@41,\u0018@f\f7=\u0003e-3\u0006j[6\u001fHR\u0002b\u0010p\u0010i%:f>[G9@vٖ1%\u001cO\u0002jCp-\u0004\u0000#~˒@\u0003WH\u0003MX\u0005\u0017[\u0010\niTDm\u0006#r\nMJ\u0005\u0015>GF;\u0005p2=\u0002x`\u001a<,bM\u0011Q\u0010D$P#l\u0019\u0011\u000e^\u0005-18G\u0000+\u000e'\u001c8V\u0001m)R \nq\u0010)\fa$:)DL4\u00009\fA\u001eZ \u00066\tr\u0018\bQ\u0004[j*Mj$Y/\u00043ZB_\u0018tR\n\u0019&:\u0019BSf.hWl~6mrt@\u0003-V\u0017N9?\u00018RB@H\u001c0FYl \t\u0005\u001a\bS\u0016u?@=YD\u0003Z\u001aul\u0006vBqʑ+V\u0012#y\u0012!刎\bA\f˵Ks\u000b%$#\n\"\u0015p1 ̍esK[\tDE\u0011\u0016\nXyԨxԽKjS,\u0000|\u0010bOv\u0000\\[2ı\u001c\u001fK\u0005\u001az@\tT9^XĄQ\n07;Xc$P\u001c0u÷lX\u0010H\u0002fw%)\t7\u0012Kdb.\t8o\u000e\u0012\u00160gK|b\u0019o\u0002M-\u0004\u001d%B(56y\u0019$\u001di\u000e\u0001@L\u0007R\t**@-\u001e\u00021p%}wj\u0013\u001a;`P\u0004\u0010!\"\n\u0007'\u0001D\u0003\u0019>WUT\u0007\u0004\u0019:!Q\"\bnJ)g%7\u0013R0ey-\u001f B\\zq\u000ex\bCq'r$1\u0019UJ3\u0005\f\u0018\u00000V\b!\u0016qE\u001fYH\u0000\u0016$Oz(\u0012\u001eUZ(jl\u001e'\u001c1vb*`>m_8=\t@F<W\u0012\u0010J ,c\u0011<\u0002\u0010=O\u0018gqĂ<ĔY\u000e\u0019\bl\"%];\u0001B\u0003ߥVg\u001a\u0011U\u0014\u0019\u0014\u0014n2\u0017\u000bc:a\u0000\u0001kQ\u0014iFm\u0011q\u0013Rsܼף<S\fq2\u0005;DapeM\u0018\u0015Gfp\u0005s\u001fKR[f@<ˑC$S8Z#\nT\u0002u\u0005\u0001j\u001bXbIaD\bu$\u0006\u0019S\u0015h8\bxTi\u0000S\u0003\u0010B\u0002\u0005fR2\u0014TXP#\u0001\u0017(\u001bh\u0011,)\u0016WASD\t\u0013IŐ\r\u0000+[Y\u0002-.\u001c\u0018\u001a8Ch\b0BWш0q@I\n\r\u0016\f_\u000bĬ\u0019H*Da9*D\u0011\u0007\u001d\u0002]-\u0011!$\b\u0004\u0002abXFi`ͳ\u0004k\u0018j\u001aM\b\u0005ǃh\b\u001eA%\u0017\u0010\u000b[:\u001e)\u0003v\nF2t4\u0013}+X.YQ(/\u001c\u001dK\"\u0002\u000f5\u0003B9W#^J\u0004F߄b^9.\t\u0000J\u000f$$C`6\r.N\t)%c\u0005AaZf\n\u001a˄0a\u001c\u0010rK\u000b\u0005υ\u0014)\u00060EK\u000e9[l\u0002p-t\u001aP\u0015J|&rU\u0012wi\u0005U/\fBaVJ.]DJPC4%\u000fPD\u001c(aW2\u0012˪s%\ng/\u0018-\b9`ۋ{\u0013H\r­BUU$\u001cpb\"\u0013h \u0019\u0000Vy.\u0004%2\t90O1*\u001d>\u0005\u0006*\r\\ڴS:_\u0003\u0002\\\u0010\u0003\u0002.\b\u0011(.\u00130pH\u0004\u0016\u000bϡE$\u0002M?*\u000b0\t\u00060aUx?\u001dzD\u0012e'!$G\u001axA\u0013\u001bS*Db\f\u0015\u000b8*\u0004!\"|ݥx7B(fR\u0010\u001bn @wM\u0005&(6\u0012\u000b\b3;\r\t/w\bJ\u00041\"\b\b\u0000q9=\niL]\u0001K̘XdBɕ\r\npB`C\u0011@\u0005HA7SB2]\u0000G\u001d&q:i:_(@ۉ\n <!\r;s\u0016!\u0000\u0012+/8#P\u0007(=t$L8QpUTPmR\u001epSI?C_\b\"\u00178N\u000e21_[IVsGb\b`bu\tqjB\np#\u000f?\u0010\u000bs%4\u0004!\u000eD\u0010!\u001f\u0000]̎\u001fK^B\u0000Ǟ\b\u000e\u0001\"\u0017\u00110c13\u0017\"/<\tA\u0005ElE\u0000#ŔbUو&\u000e\u0011q\t\u0003\u0006#\u001a\u0002`P2C Z3v\tU\u001d\tL+iۘe^a%{*za\u001a\n)BpB\u0015&\u001cN\u0002_e\u0019fpapz\u00137=\rUP4U,`%IHY\u0013P5l\"%c#Re\u0007#cS9\u00015\u000ei§\r\fĄ\u000b0\u0017\u001dB\u0002\f\tb\u000b= \u001b\u0007\u000b\u0018t(L̑El1\u0007*T\u0013$\u00158.$RDh\\ٴmIŐ*'N\u0000\\\u0004A\u0001x\f\bB\u0000\bp\u001f\u0013.\u0017\u0015$4\u0019\b\bU0̹+YC̺r\u001a\u0001 t}b\u0006ù\u0000\u0003\u0007V\u001eIWwQxi?Ѹ@ٺAA\"&\u0018*A[\u0007E \u0014Ӭ\u000b|O\u000b1\u00010\u000b\u0012D-τ_#%\u0002\u0002h[o\u001cNF*ޜ!\u0010J! \u0000\u0000;l\t\u001f\u0013\u0016\nEC~;01\u0016zY1>N\u0016tf`\u001e\".^\u0012\u001c} ar!\"N\u0018]'Mv\u001bH*\u0003 \u001dj\tM\u0011׆b^+ʪeY9{|'3kU\u0004P8BZD\u0017`<fEatNr\u0011>\u0019Z\t9Ұ\u001d\u001c\u0017\u0016@G%\u0010'L2f\b$\u0003:)^,,֕\u001eLqwJ-\u000b\u001013\r\u0014\u0000@;Zߑ3\u001d\u001f]H/)\u0010GH\u000eP\u001dv!OC_A\u001bܑTe n\u001c\u0000bX%1W\fs/\fu\u000314{iV=_N\u001cpB1IR-]4A3\u0001n?U[Y\r_0\b쒷,Ō4d%\b4%\u0017u\u00106!&U\f\u0005QB)\rendstream\rendobj\r49 0 obj\r<</Length 65536>>stream\r\n\b\\+׌$u\u0002qD\n5\b%\u0011tnڣH()\t\u000f=OuY\u0006:zjKOR\u000b*W-ʬpP.-`@R!Ow꣡d\u000e%`\u001f\\\tBLj0 \u0015\u0017h2\u001dY6W>:O\u0013Q \u0006u;%̈\u001d/aQxj\u0006.ӝAK3&J\u00153k8#vJ\u0002KяL\\#\u0001]tp\u000b\u0016'dH*\u0006[#.\u0000&\u0005(b\u001c5cWx\u001e``Z\n43\u0012C\\\u000b\u001c,\u001au_Uk\u0012r\tDQi\u0003M;y\u000f$%g\n``x\u0013rkrg+I\bY&Y@\u00045\u0002#!\u001a\u0001(.\u0006*0\f\u001a\"\u0019\t(/\u001c/(\u0012L V\u0012\n\u00108\u0001\u0004=$\u001a- FIx\u0003}Fa\b\u00119H8DB<K\u001a\u0002Ot\u0018D\\+!\u0017+X\u0011`\b\"ݨ\u001ec4(B!u`\u0015<JL\u0011`c5Bp\u0010\"\u0003@VG6sR\u0006E_\fV6],]\u0005[0\u0004h&YTe09F\u0010f\u000e\u0012ɍX\"W\u0005Bd\u0013'o\u0004=4\b\u0019!\u0006D\u001c\u0015ܹ>3O\u0004d*\u0005\u0003 \u0003jS'\r/+`ottF%TF@3Rҿ\u0002\u000bb\u0004{tg@`8M\u0019\u0004)d:\b6\u0001矧\"b#(7\u0016\u0019e\u001b=\u0005\u00119\u0014\u0001s[\b\u00181=4F1A(\u0006}\u0017evw\fR\u0010\u0012`PDuM\u0018j0#'F\u0002w->D\u0002 \u0006\u0014,(\u0018_4n\u001am\u0012r5\\dE\u00055\u0014X@ُ,9bWN\u001b1Fb\u0002Mp\u0005mp\b]\u0003.\u0010k\u0011z@Hؖ\u0012H\f-dTr\u0006*_ \f.\u0004Ӱ3|\u001e}\u0002fr\u0011N(Gcu\r\u0011Kb\u00017\\a$\u0011U\u0011%!cWT\u0002b˪\u0019q%5\u000ecq\u000b4X⟏SnW\u0018\u0004\u0005h~\u0014H<\u001cg\bΏ\u0014[l \u001e(%7-\u0014u}:\u0004}A3\rţL\u001e#W\";ŗy\u001c$F\fj\u0007\bcl<|\u0005\u000b>+\u0012xl\u0011a$q\u001f,@e\u00168!A\u0011a <H\u0006\u0014$VbpVzX\u000f5ڕyp\u0013Tu\t|\u00045`R\u0004͊dz\u0010&\u0005{=\"T\u0018\u0017XH+63\u000e\u0011\u0010\u0014F)\u0014)y$\u0018rbH\u000fR2rCNDs\b\u0012bg\u0007_f\u0018\u0018\u00022}ꅥ\u0011;i0\u0011\n\u0003\u0013c$\u001c*\b_#yo pG\u000b\u0013a \u0001\u0015f\u0007\u0001ƎZ<\u001fp\u001fa\u0013\f.Q\u0001\u0019(a,Cx.8CU\u001aq|VvcuLbΕJP{ʄ\u0000A$'\t-;#Ѕ\u0012E\u0017 ?\"/\u0012\u000f\ni\u0018\bɹ}S$I\u0000$\t\u0015\u0002\u00062L\u0005rXMC\fDԋK8\u001c\u0001 a CZ\u0007A,\u0010H \bq\u0015\u0019M\u0014\u0012т~PѨO\u001db2\u000fP\u0007\u0002\r\n#q\u00139i#7\u0010\"5\bJ0\u0014\u001f7\u000f\u0007FjKuc^[\u0013b\u000e\u001dF\"\u0000O3\"E0iZ%3.Sjn (K\u0015Q@\u0019\u0007*t{塀U0`\u0000Qt{r3)O-4BON\\\u0010\u0005\u0010zba|\u0005<$/\te\u001a#3U\u001a\u0013F\u0010Q\u000f\u001f\u0004l~\"\u000b'\u0018\u0012q(\u0013\u0005S$HvHȠ2\u001f\"6\u0012\u001fZp%G\u0001\u0000H'$\u001ev%#P\u0014\u001f\"\u0018\u0000H\u001fcF\u001a8|&\fD\f/U \u00013\u00137\bD+AGة+xo\u0004\u0010-q T>9F!\u0005\u0002G3\u001a\u000b\u0016\u000fP\u0018yFA&Xݑsb4Dd|E>sdj\f6D!T\u0012K\t}v\n\bҰѸP|\u0005\u0003ę\u0004\u00141c\n=\u001dm\u001d)A!\b\u001a-\u0004,\ba\u0015$<[3Ҙ@f@H\u001c\u0004\b\u0013a>DDf,FO\u000f\u000e\u0003:\\\u0004!\u001cD\u001eewRőġ\u0010r\u0007)(\nW$\u0006|`\u0013\u001dًnL\u0002@9RrA\u0010eǜK\bMOb[IۇtXYGq`o \ngT!\u0002ڀ\u000101P`XbiP{R8\u0010\u0012I\b^\u0011qA(t\u0005\"Kv\u0017鐙\rh*zpLo\\$W+trҝ䜝TE:\u001a\u0017(\u00159\u0000t?EiId+\rCe%Ɔ3\u0000@:H\u0001>Yf`0\u0017'\u0016=hAi\f6\u0002kQ\u0000a\u0011<j+!\u0017sg3?zl74(a1\bëe\t۱$&,%m\t\b\f\t\u0015\fC=%\u0018/\u0018\u0004\u000bծܷ\u0013RP\u001f4\u0001]Ҩ@F\u0000&B$\n%։\u0007\u0001Jȝk-M\\$<\u0012(4 \u000b\u0001cZ\u0005\u0007Y\u0018c\"O(\u0005\u0015\u0015!VBpE\u0012فb݁ˌ\u001a$Kv*%v\u0012V<sN\u0015Jj\u0014 \u0007-º\u0012\u001dF\u0010me\f=tr\u0012QLY/q\u0014\u0017NBX:a\u001f&r\ngG5\u0011\u000b5\u0015G6\"6.̓AН\u0016\fe\u000e\u0006P\"\u0010Es$m͍ċ<\u001a1(e/)W\u001b;tau(,\u0004]\u0014\u000f\u000b\u0018W\u001fDH\b7(DXP\u001cȡe\u000b!}\u0004\u0004zI3\f\u0017\t?R`\u0019R\t\n5\u001f`*\u001d\\\u0015\u0005\bBɭJ=l\b{\f\r B\u0011qoPIP;i\u0007N\u001d9a/\u0004[2\u0014\u001d\u000b\u00011TBI\u0003\u000fc[HPv\u0014$yp\u0010G\u001cr/\n\u0005^\u000eIJ`R\u001cv\u000b9\u0003T \tvEsՆ< {>\bA\bQ`Z-_6\t![%$\u0013[ݲ%X\r\u001b<H\u0000{\u0011S\u0000Ab\u001a\u001e1JJ\t[yn:ؑB\u0006 %)\u0014\u0002.9\u0014Ͳ{MB\u0004\u00033\u0019J\u0019I\\\u0019\u0004v\u0012R\u0019ڊ\n%|\fs\u0015>\u00148B6!\u000f)\u0018\u0001DO\u00137.y8Q\u0019Op\\\r=Ed\u0019]K\u0003I{:(uEܙC\u0004==&4Crvh\u0006+0[U\tdy{\t'l{.V\t\u0000\u00136\u0000\u0017\u000f&3]\u0001\u0016\u0014$\u0002t\u0005EBXx\u0018\u00064\u0001|eķ:Hnh&e\u0004Q{\u000e$\u001bc\u001ac=dX\u00184\u000458*4w,6[ZWABun5\u000f\nJV8m\u001dO7,Z\rݨzNsYoԞ\u000fj]y}'vѮ[evT:loVQ\u001cm\tކՁ\u0013!\u001dn\u001eSm*\u0017\u0015g^\u001bo5V0\u0003S?x^';\u0018?#ۓN,:팤\u0016L6fj5\u0016\u0000PS3NlYY\u0006ſMM\\\u0001ϱ?龗\u001e.j@K\fylVNk\u0007N^3S\u0014:w5ĝk?^:\u0012kL\f/6G(i\u001f\u00113x1RC\u001e*.ߝNAI\f\u0015Ӎ\u001d \u0000jĺh\u0014h%߱4\u0017-\u0003`\u0014X\u0010y\u00140vFI'\u001f?uxĺqp\u0007\u0017lp6b!\u0019C[n-e\u001c\u001f(>(/ҶME\u0001\u0001.J r\u000e\u0019M7\u0002<gܶc6){#N<sBR\t`\u001a\u0005S/DL\u0003T\u0011\u0016B\u0015\u0018+\u0018S(b(\u001dU\u0013d\u0011eo\u000f\u0012]8^*<L^M32gr) p\u0019y\u00045JL\f\u00146PHr1CGL@X<W_\bN-I4\u0014\u00163Z\u0002)ŶsUl͔\u0014q(Rӵ\u00169=\u0004犓$\u0012\u001dS(V͊k@\t\u0007\u0001gP\u000ec]!.%\\~d\u00045g\u001f@\nd3\u0014\u001c*jbB<]@\b$\u000b*XbdD$co\rIз\u0018\u0010\u0000prh\u0000\u000eoZJ*\\\u001cxϱIqi#G~O\u0018\u0011ʭz\u001dDd^_\rJL\u000bPB\u0013#Z/\u0002G)\u001bHG$$\u0001\u0016pA$\u00047`\u0012{$\u0004%.}>dXP\u0006Ιlq\u0013XP\tKfy\u0012=pA4\u0014\u0004o\"\u0003\u0003|4\u0019Q!w\u0010PFG(P#Qs}aLK\\aM~ch,+\u0012,)+tI\u0001\\ \u0005rq\u001f\u0002\u000e\u0010*`os3>\u0019{\u000b#<9\\Lh,\tA~q\u0018oP\fq\u001c\u001a_O@[F}\u001cTq9\u0006\u0017T4b !\fL+F/+K8BZNTZLeVE:+HCHbE1#kH(J%\u001aEznG,mih\u0015HfI%\"c\u000e:i3~P4\u001au#R{\\6\u001dx_x15m^\u001c\"F\u0002qWWK++K\u0012\\Z<=<Im\u000e;j8\u0017\u0004xf&Zl\u001e\u001b[;3ZqN`\u0000UrEC \n\u000bȓx\u0014r\u0017?\u001f3\u0011-}v\u0013\u000fŎ1\u000e\n\u001cjF[\u000f<\nz}1%\u0003ɕh\u000bU%\u0003}\nҷ\f43/\u000f\reTɅ2e]\u001e_>̘̌f3:B\fL\fyo_s%o\n:8\u00066(\u00198\"F]z\u00128!mi4矣iG\u0001-R*;\\LZ1[iq\u0002\u000ex\tRFҲw\u0018:(PF\"1:E\u0005i\f\"\u00060 [\u001ba\fx*ڡRxz\u0000Փ|\u0006!FbCPnr[gw2\u0010ll@Ӓdӂlf\"@x\fev\u0016\u0000$\u001a\u001aw R\u0018\u001cXaGz\u001ek;} \t\u0004\u0019cn0l`vHΑDu6Y2ݑNIc\u0006\u0014\u001cšO\u0011\u000e\u0011\u000574c!G\u0007\u001d3\"c\u0001@S\"']0y_\u00131Q\u0010h\b^D`\t2\u001b\u001ep\u0010_\u001eD\u0002\u0005&I_\u0005\u0004fN(֑+Ix\u0005Su$\rM\u0017եAHeo`\u00156\u0012Ma\t.\u000b[ q5e\u0015ı\u0007GQpHZp)gE']ȠZXӗ\u0012\u0005\u001e)t\fo{\n1%|y\u0012\u0012\u0015ءf\"&v*l\\-3z`o=[w\u0004\u0018\u001fKW~\u0006׍.\u0011{tJ1Ԑz\u000f\fꟕǖU쮆v\\^rWUYJ?[\u001e\u0006x\u0003y\u0016vC\u0018:(4\r<8HlM8%nwyn\u000bQ\u001bݛz֫u?\u0017fэXk킏\u0018\u000b>\u001ae*\u001dGm˲ך^Y-Wz\u0017@ZZ\f\r 3;U\n~\\I\r9\u001b\u0003ǼLNku\n\u001bIal:wTt\u000bG6Ds\u0000\u0007eV\t\u0007O:C\u0010\u0010i\u001fE!sFB/*!\u0004£\tS\u001a\u0012\u0000\u0000\u0003\u001bh\u001a\u0010\u001e\u0015(\u001c\n\\H\u000e\u0007\u0000&^at0CS%M\u0014\u0001$qof\u0003Yg%=jD\"NV\u0011f*+_ -r\u0010-\u0015}U1\n\b.i<X\u0002\nIYI0| q4\u0003h9\u0004\u0001;BTI7\u0012\u0004H\f\u00015 F)J2\u0000+H\u0004CFvZB5-N\u0015{\u0000D\"H\r\u0007\u0019|C\u0014K2\u000fa\u001b\u0017L\u001aB\u0001\u0002K{\u00117S;\u001e[rhr0\u001fd\"MD(ْ 1+,\u000f-T\u0000\u0017ȉ\n\u0006\u001c`H\u0004\u0000BG1\u0001Cy\tP\u0004m\u000b\u0011a&$\u0002l5\u001fK:\u000bm\u00014dqvM[\u001c\u000f\u001e\u000fA\u001aeLD(\u0016XoraXALKd\u0018a)\u0004ps2\fd.QtΗ\u0007\rqdBSz!=\\}B\u0017\\\u0019$#\u0013mMH\u0014\u0015\u0019.ف(ȖhP\u001cT]%v2\u0013K7\u0002Ð0@ᙇf\n\f\u0000PSl\u0006ut\u0007$w\u0014\u001e].\bpFn\u0015q@|tZ\u0010IkRdL=$lq!\b9-@&\u000eQs|K8z-\u000fu:\u001aa2\u0010\u0000\u0001;baGF0_\u00124ԑ\u0012>1Bi\u0011;|\u001d1)\u001c4\r%\u0006䵀L2#0^Q\r\r&лA,>\f\r\u0014y$\tءS6l8Jg5|dY\u001eB>Yf=%sR,\tARxtF{\u0005\u001bk\u00015\u0001\u001ct>#au\u0010*YP\u0012\"\u000f;+6IKJ~\u00057]ۑd-d #&u\nCPZ\u0015\u0014ׂ}\tH^d#A\rA~:]~e2\u0017Am&Ѥi|vK&!w`/>#P\u001dt\"\u0002#$2Prr<k:<(\u0014pY\u00043AXbDc6(ʩk\u0013R\u0019$a\u0000\u0013jx\u001bֶH_\u0017\u0010.ݢ\u000bV\u001d4!Ld\b\u0004K2\u0000 \nSN0V;c\u0011wafk0R.\"n5VX\u001e$Ӎ\u0002:%A0\u00193\u001bgEP\u0012\u000bxf\u0005P\u0010\u001fJN$\u0005sτ+?L0;\u0004\t'\u0006\u0017kyx@\u0010#~ \u0003nj;\u0005W$\u0000\u0013`~\"kU\u00152\u0017#\u0002%bFd)]\u0015Di\u0015ڈI\nܔU_\n\u001aW]\u0002I\u000e߲j\u0005\u000eѭ(\n+q^w\u00017 z}\u0013|8o3q\t)\u0013&\u0003S H%o[)&gWJфI+N\u0016\ts\u0005 j$NLZ\u0005я\u0013\u0015\u001cg<,\u0002?;-Nx0\u00020HX9aX9M`$\u000e\u00169M\u0017:\u0015˹Xqϑ%\u001d\u0005!\t?\u00059*\u0000i\u0000\u0005Jې/ 5j$CuRઔ\u0014\u0000\u001dj3\u0007PR1Ӏ[~\u001d\u0018\f\u0004\u0011=יb$ձ\"JB5\u0005d؆=3Y+&LW'Le+\u0011H??CkqJB(CTz0\b\u001d`pŔ\tr:drd\bBD\u001e`EIJĢ`p\u0019\u0007&\u000b\bb\u000b\b9&QJCK<Z:K/̈~}\u0010)&\u0015pӇIdS`fz\u0018\u0019\u0005\u0007M_#:%iSZ\b\u0007\f\u0012̫CHp\u0016\b\f\u000fnrBpLz\u0002bs=v\u0014\u0014\u0010\u001e\u0002W\u0004GA_P5-\u0018%is\u00197Q\u0012I'\u0014@\u0014jLaX!rC#\u001dMPZ &\u001dq\u0012\u0013\n\u0010C\u001bQ,oUd\u0005W~2 \u0019\nMVFxZ\u001d,֟\t}`Z\u001d׭ݲBJ\u000f[D\"?\"\u0016pf\"[rަ\u0005\u0010\u0014T߽\u001bŞ-\\0Y.PNmY,DП*ɵ\tC\u0019\u001e#`o'd;ɝ\u0012'\u0016\r\u001bTT?&\u001brpeo~\"P&Eg+un\u000f\fC?]\u000e\fx@B\u00005\u0005cdQBZT\rHД0T\u001c\"i+ԚY%\u0002w|`\u001ei+W@mW:~PBS\bNn4HLCR0\u001c?NG4t}/ggT!\\\tt~}&H>W@#O\u001bQ\u001e7-]Ձ\tRV\u0010&JV\u0014\tN-C< Zy3Q\u001cX\u0010X?\u0004\nF\u0017\u0013j\u001cM\f\u0011L'(/2\nN C\u001c`\u0004!ؼ/\u0016\u0002ӵ@OV$IYL+F7\u0015fPx\u0010\u001e\n&|\b\u001dK9\u001dK\u0017w7\u000eb.Q~OQ$\u001e@O\t&G`8_\fa\u0000^\u0010\u0016K\nfg\fdJ%:\u001b4ׯ 5%1\\R C\u0010DښL䞆\u0016\\hM\u0018MygSXHh^ĘT@,1L[\u0010fzRIJ\n:\u0006\b\u0017i\u0015Ii 9O\u0010\u0016\u0003m\u0017T+\\\u001cߙ \r\u0000\b c\f<|r(3\u0007\bq\u0018&(d\u0015ZxG$XIpN-:\"=2\u001f\u0019I\u0006,\u001a\u0006p`IlLZ\bl9ߨ3@\u0012\u0004\u000b\u0001jÃ\u000eq\"x\u0003e3X(Xk\bRm\u0011\t\u000eY\"C5!\u001afʌuA\"\u0014E\u0010JMmBy\u000fYd7I\u000bE\u0012B\u001c; \u001d\r\u0002\u001d\nSF\u001e\u001a@|n3\f,x?\\J[Lj\u0014X\\saLʰ[K@R\u000e/\u001d\u0011h\u0002<\u0006&-\u00052\u0006\u0006z=~܈#9<\u00165bD\u0007|hN\u0006M|OR\u0001\u0011\u0002E\u0001&Si\u0014\u001f$\u0019k]'w`\u000fIڼᎍ2ԸS2I\u001a\u000f%\u000fu\u0018K\u0005\u0015:8mUw}{\u0000C\u0011G\u001bdi\u0001y.\u000eF\u000fa\u0018\u001e\u001c\u001e\u0019\fm\u0000u5;aJ&\u000b\u0003/~ے\u0014͘4H1\u0006\u000397<6U\\o\u0010\u0002o(_#15\u0014CE\u000fٸS \u001d;4\u0010\u001dDB\u001f\b&ېP%'8\u001dF\u000bTW\u001bA953Ccs\u000f\u001b0%/\u000691\u001eQA\t\u0016%R>\t<h\u0001_Tu\u0016\u0005Ȱe\u000fV0v:\u0004\n1\u0003D4\u000bBL&x\u001d\u0010\t\u0015ND`BRPK3\u0014dh\u001dEFK)ǆ3\u0004;xܵ9?p7\u0006\"\tq<!\u000b\u0019d\u0013ų4B\\pbܙ-\u0005ab#;\u0012PvB\u000b\b/p5\f?x86ț\u001fc߯f|.rG\"\u0011-j̲iL4H_G6L!L\u0011\u0018e\r\u001bhq1kGؚtpSQwx>\t\u0000Lf\u001aX~dT\u001eP2MЋQ}1\u001bFoh=\u00172qz\"\u0006_,\u0006weM\u0004\u0013piF'\u0004\u0019Hӭ/^O?(N+J3VY2tg\b״\u001d>!WK]1z\u0007'j5Y;敄m\u0019XbFH(\\\u00067ƐQr9\\qEI<4,>w\fHJmoX@73v>bȐ3,aA\u001e\u0014MkquS\u0002\u001f\u0011e(0˭צoC)#\u0002>{|u\u0011<G|6by\u000f\b? _L\u000e\u001aL{\u0015?\u0002Ȼ\u0004p\\Y\r0O\u0011EF2O\u001d2d1%i4'pXSQ<+\u0011\u0002#\u0011o\\cGh\r \t\u001b\u001b̒\u001b\u001c\u0018\u0000:;C\u0003\u0006\u0011~Q\u0018QFh\u0016,n\u001e\fi\u0017RxU\u0002QC\u001a\u0006\na:=ezƈZH(}q%\u0006\u0011\u000e#\\sj$\\:\tłK\u001c>k6C\nOA8Ե!Ŕ\r.8\u0006\u0017.~\u0005\u0004\n'h)s^Y[.<((FeݻS\u0017=S1%\u0019R7[Bjum\u0018Vs,yXbBz_\"Fj/\u0017f)\u001c ~¿\u0015.+8vo{{BѼ\"_߿|jһd#Wx <\u0011\u001f~¬WM\u0010e|\\T[Y'M-bDJ֩\u001d\u0014o.|bT\u001av\u00114&\u0015?3#`>8++,t<'\u0000߲KEC\u001f\u00167??Ó~K>\u000et(\u001bisPc~AF6k?1>jEh2_p`ͽ~A\u001d0jv%\b\u0017\\!ᡖ:z+$H\u00158\\F\u0002اНӢsnlgtFۨ3tYuIcI>5\r\u0003\u0001`)w)\u000eGa\n\u0010ԁ\u001c\u0001\u001c\tkܑc\u001d\u001b;Åȿ\nCÁBG\u0006\u0001\u001ac\u0018\u0006\"۲C\u0012ǕWF,1kxQN=o\u000f#R5zK\u0001#\u0019Εdu9'V\r3֨o\u000ez \u0015T\riFj۩wF\u000b߰\u0003oXt\\\u0003Z̓zoG\ns\u001bNot;ړvvΛf!FJm@<Rɘ\u0019~]-\u000e_xՑ\u0007-%fJ[Zed\u0003YDCk;p)cU~\u0005Bvܟ>-\u0014I[t\u0014\u0004xQ\b|Ҁ\u000bnEd͇0?[6\u001d/L\u0015fr\u001fD\u0003!~JI>\u0001l֮5\u000f}&\u001dhgEs#X͌Eۭ? ){ӬW[\u0007DW_wۍ\u000f9(\u0007\u0002WI!5\u0006\u0016R4\nUǗeaXl7\u000b[c\\uO]=/\bZ\u0015#\u000eWZ \u0017\u001dnR}8ݢՙG\u001fo}Lϵ\u000bG<1|mH\f6((Zâŭnoe?9ϯz_\u000bu\u0007vۓc\u001c?X\u001f̿c4k\u001a[[^k: (7sq9zf/,훙\u001e\u0001e;45Febl6#H8Y\"\u0012q_v\rH\f_\u00134`Rzdώw\u0014Ț<&6NFv\u001d˶c\u000f\u0004J\u0010\u0010\u0013yA\u0014\u0006z\u0019cȊ&Ǝ_pO\u001d\u0013cȓ\u0016AMvb{.c\u00193aO\u001d\u0013c #\u0007q\f\u00135v;'\u0000_yOl\u001e\u0013w\u0003<_{?yMK$e1\fO\u001dLL\u001e\u0013_\"ǃ@\u001cƮ#nos]w\u0002X<}\u0016\u000f;B2&Ev\u001fjaĔ\u0013\u001f\u00131x4u\u0017OL\u001e\u001a\t~52y3\u0004g\u001e11zuRr1=.H\\V0\u000e'V_gXr\u001av\u0004V.wO{X=\r1zL\u001e?K'D\u001e%re1\fOp\u001eML\u001e\u0013_'\"\u001b\n\u0015\u0001=a\u0010?\"\"cbU\r\u001f\u001139\u0001dE\u001aDY\u0013/8'cbYkuN\f\u001f%\u0012ƿ\u0012\u0018>ƙkE|oZ>cb\u000b\u001eNxP\u0002l*211}\u000f\u0003d'Ң\u0018@&\u0006_p\u0018@&\u0006\u0001g9}_֫?Mؠ\tǿ\u0011L\u001f\u0011L\u001f\u0013_%!C\u0010\u001dߡD\u0004q\u00101\u000e xb=ufر\u0017TQ&v_xO\u001e\u0013t\u001eO\f\u001f\u0012%21|\u0005\u0000?\b!lǵf?E!-v\nO^D[uX7\u001fO\u001eM\u0003t\u001b䏙~1c*\f~-\u0003O8d;GkΘ?hnKM*BiV9^hُl+UJj\\&\u0017UJUYګ\u001bYO~\u0014\u00064Fhr\u001a#N(w\u001amOۍ4\u0012M[srU4]N\fǓNÉ\u0017s\u0012q\u0010\u0011P\u001dZ_h\u0007n\u0016N\\,\u0013\u0007@7˜T\u0017XV=k[\u001d_J8͇3#=擣|-Bq%\u0002hƄ\u0018pYm\u001bS\u0011,lXQG33\u0014E-\u0013\u0012`ԙ ]n5ZJj~)aIo3o\u000b#cu\u0003(Ӆڡ\u000f:\u0010`ƶS}\\\"G \b1m\u0016PK-B__:#32Y\\/>\u0018q8\u000ecbB?\u000e~\u0015\fDּx\u0015}\u0017C6J\u0007צub<.\u001bӐ7inU^[\u001a4v\u001b6\u0005w\u0006z\bf\u0016~7_Gff\u000e*\u001dL\u0011-\u000e&\u0007}?\u0007<\u0019~\ba\u0003\u0006w\u0013\u0019\u00171۝J{^\u0019{x[:>ɍJϴI;+go֩\u000bA?Vi}FNWkGZm\u001bƧ\u0017qK\u0015icڃ\u001c\u0005}Ǧ\u0016CgghO[ѽ;+̓֩}u\u000eeM~yvZnR?zRv](:Z\u000b)+[\r׵\u0006^:.>&]f\u00150&ֹ[xl\u001dW\u000e\u0000\u001cFwU?WGaS˝Vl5Tz\u0002\u00135m\u0016$~LD0E\u001aڕ\u0005eV\u001bUv*ǿ:\u0014=tNvF\u001dǭ]~\u001fLi46TG\u0003WKkJs]({jntLzX⥚Y\u001bF07J\r\u001b7?3\u001f6_)~ļN\rNmTs}y{\\rXfd}b 3\u0017\u000br|hM?\u0003\u0012\fn\u0017+J\u0007\u000fKZ\u001f^TnUڒyYeXN\u0010[IkY\u000b/R2bT3E\u0017Z@}\"vU|TWu\\胦\u0016C\u00156槍O*9\u0001]p,Y?_\u001f]'\u0014#+\u001b\u0016XTdLӚɘrD]\u001d/\u000fVtܾo>̏\u0007\u0000HEVu/_\u0011l?]\u001b\u000b!a|:ŮpZv\u0003+&\u0002\u001d]sl-rsPڹeru|kd\u001dWgfos|H\u000bsHKu\u0002-:?魗.=|AM/_Ad]\u000fo~LAn\u0014t\u000b\u0005V~\fb hC\\O+U\u0011&!M\u00104!ʵM\u001078\u0004~|P+\u0018flX 1x:.ss\f޴Z9\u0015z\\\u0006KK#Wc\r\u001fҭaO>Zة\u001f5q/^Qd^uU:kvk7&[\u0011;6^h\u0004qAw|ȽS=\u001c^3f\u0018Pqe'ǎY{y\u0001a6BS+E\u0002-\u001c\u0016WQmDめj5\u001a99fzuNj|-uGǽl29l!;\u0007p@2\t\u0011\u001b/\u0001\u0019''\u0006\u0016\u0002rwgv9x\u0005z&\u000e©L0⑍T\u0006NDLKS/\"?/\u0004nݼTTF[n<oCՁp!\u001fTj\u001fpے?m8o5\u000fm(YUzF2E#s\u0010>0ڜ[KfZ5-\u001fMf\u001e\u00146~t*F\u0010\u000f\u0012\u0006yG`Zo=с^nUN͉\\UFS¯ʇ^y\u001f\u000b3=m4͟zY0UM\u0013++ZzSkJ$#+]jvW:y{&|\u0015BR\u0017s\u0001 մ%ݾ_4\u0005p4c\u000e\u0019ۯz4\u001eofqlz/ى}M'G¾p$ߨ/_i?>VG՟ѽY:'_\u000e\u001ft+0\t3[l-(\u001bvi?'on^\u0004n`^:c^wֲCwxg9eO՗H+^?\u001bn|YkPVR+;סVH\u0004ޫN(tmcou֖֩`B׿~v\u0013Nk\\;?َ\u0007j~\u0018gu*\u001f]߮\u001c\"&N+ݓmz\u0003*.LJ\u0002\u000fY=\n\u0012~KlTiP:\nnQtfЮ*ܭ5{V.5j\u0003lld\tNoU\u001c\u00140m\u000fN]*\u00024\u001aT3.4Y?<Il\u0010\u0004\u001d\u0014ౢykF!fF{~\u0012_\u0006n-NLJJ{̇\u0017iam5=H;PZBj2rY\u0004\u0005Z\fF\u0006rLK\u000e|\u001d,tLssb>,B4ҫ5j\u0017V>i'^:kk3T\u0007Z=N\u0003;a]I{F;#\u001an'1V_;^ڦ\u0017ɽvl\u000fӂY]ڊl/\\.v\u000f.Za^aޫ\u001bޏ1j-WGgZaNf0\u0005\t=i+ZMhHjbsj\u0006pn6T2|uIK6wVy>o<OtPa\u0002oԛBŕ\\:m؜\u0001/7_U0SZCj\u001a{uk]\fff*%M6mz׬#3o\u001d==YsJY,Z\u0007U\u001b<Ss\u0011&پ9V[fH6~\f*f~1'WA_ՕFuXoҷ:j=W\u0007k>>n&3[U\u001a\teVOS0W+\u001dBΫ%\rI\\&o}mϚS\u0005Gt2Xm\u0007s\u0016\u001e\rCгJqqIo\u0016ɝ\u000b1ӭ\u000f>:j3W\u0013ͧ\u0007*mZkV!;zrS*S10$|h,leDVmu뽋epf\\ \u0010\f2N\b\u0013!찪ܕs[;oN\rJ@o۵F(:\u0010o.\u001f\u0002\u00191@*?\buGnXI\u0007K_uˇ\u000f\u001c\u0005vgV\f49\u0010/*vt5X/g\bskڡAaGac$Ż\u0017g5\u0013Ձ_)ߐQJ\u0014\u0006>Y6Fg<}Q:\u0007셍:߇.Z\fKui\u0017ڍWԩ6\u0017\r3wzN\u0018^qG'\u0004\u0012}A}rԩ\u001a%&\u001f6{\u0007)\u0019Yk\u0017;KF&člKwv1\u0017Vi֎*zNRNîR~\u001a:O\u0006u+\t#kADLXr\u0007`۳R:\u0010JojW[T^uV88=\u001b؈\ff8Κձ\u000e\u0004֮4yeZ1fvko.2#\u001d\u0014>l}Nsqk\"\u0001\u000b\u0003uHR'楾Ђmd\u001aow^#P($b%Ǵ~6G<>5c7}0e'Fo3sO$mΈAEvt^rf]pJNv]pJ]1J_zsHz9Pm~P֏a+HQ~_җ\u0005|ޗE7{\u000bN\u001cT:\u0001iۜaʹ{qT\u0017EWb\u0003rMCs&O!v\u0016\u0015aWM\u000b\u001b岆ֻ@>][k\\3˙'q1SC\f\u0005Q\u001eU͆/\u000bn:4ݺ.E!]&xp_t/\u0014cvӥC_\u0018nO̽v\bέ~Zt[=F`ncηz\u001aǳnmU)],asj^)\r\u0018ΩgN~a*s\f!\u0003䨚G\u001c]\u0011\u0017\u0013%Pߎ\u001f)>Ĥ\u001azӝ\u0018P?.:/-BGoJIBJK3o,h5[NԬ4\u0005u5\u0014d\u001dϋ\u0003fOM\u00106ZzSI}մ9YOwyΤX\u000e\u001aMz\u000f\u001b)ثIO2{\u00182\u001b\u0013M\u001a\u0004~c?=:\u0006i\u001c>yS\u0002X;0+~XOm\u0017v\u001a5׫vsVz+\u000fR8_U>JNk[u3\u0010];uYu\\\"W\f#ISykjlpS\tFϮ̥K.\u00141\u001c軣NlJ.o\u0003K\u0000;*\\\u0016>s_\u0017ټ\\i/^6D:Huzȳw\u0018mw/ ]XzAs\u0003S\u0005~s\u0005&}ȹl/\u0004Ͷh.BZE0H\u0019\nx/׺f+㯗d:\u0017H\u000f?{1\u0012\u0014_˴st6\u0006\u0019՝dWn^4\u0003\u0007X\f!LsNKV.Tl2N]n\u0011\u001bs\u0015$\u001dWնNz#lUt6<\u0015zW0\u0007Nn?ǵf[Ui\n\n.|'6\u0016tJ/:+\u0004^0WDM\u000eI~Z^w\u0004vz߇\u0017Gǈ.7\nuz}+F\u0007`Tvی\\?ݳ1\\\u0001-{|i\u0006hazp<\u0001%;ک/XlFvusќ1V\u001c9\u000fq+.ƕSlw.2`\u000bq-g\\Fi5eӋ[w2\u0002,_-Ww\u0010\b_x%90K{և{\u000f.ܞ̽yrzy3lӕ7O\u001e\u001e?Xxb\u001a8/inZVw}ϳw\u0017\u001fow\u0017ϝ\u001bҳ\u000fV<;{hS\u0007{OKik[Z\u001d{\u0014<[]~ql~\u000fp\u001f{i\u0007{Vg\u001c\u001cNMsVkpxpW>\u000e}r^\u001en׭ok\u0007k7K[śMiûtu^u꿞)\u001f{{\u000fK{K/Xf\\;hjr\u001c\u001f˗mk\u0012vyP`1vsYi}7cwj:XjVo[x1?\u0017~\\\\-uk\u0007v\u0019v-|Z\u0007\u000f幊_L~m\u0011nJ\u000fvק\u0017k\u000fo]\u001f]3/k\u001fr;\u0007\u001f\u001e87?񵏚ӦC71%\u001f&ɝKs`ݲ?|<Wyxkƽ\u001d|%\u001f>-25m\u001e>=|\\|9ΚY{\u001ew\u001f\u001f-{.<?3g2my߫%_b*-=K\u001b)k=J5e=\u000e9\u001f{ko+ߗ7\u001f>]{T>J\u001bW_\u001d~){<s~ݗg\u0010ɪ[OEdv[ˇ[+\u0007\u001cOʝ{nο\u0019W{;K޻g\u001b9C_\u0004f޿Ԋ?\u000f\u000ee㞌L,^55=olfua/Y\u0007濞Xuyϣ`8w6<\u00033\u001bdunlۜcfq:یk3w}Zsߪm,̧\rH\u0007cIie\u0015;װ\"{_&4vҋȲ\u001f\u000fNwyx'K`m~ͅ6LMV^-?9O~\u0013Ƶ\u000e\u001fm\rv^~I87\u001c\u0018n\\\u0003\u000f\u001bΝkO^\u001e:5;y\u000e׋{\u000b?K>zќc'֗gsUyAiEhqg{\u0012~751\u001dKgVxzV\u0001nFE\u000e[\u001fnqviѾ\u001cplVsj:w'[\u000eo*۶\u000fK?\u0001{wn\u001c\u001bm̖\u00074KIkvufcޣ_K[\u0017z\u0001v\u0003U?Z\\}_їMbqz̚\\}g\u0018=\u0016w/6oJ\u001b8w~\\\u0017Gf\u000bVmcLqZhj\u00192\\¡X\u0019l;\u0005>~%yUaq5˛\n<4g2`9\u0012*#__6Q<5\u001bl\u0012`bSa4\ny,\n_18Dh\u0018޸?|f\u001ee7\u001egC)8\u0019t\b8W\u001eMޣ\u000bv\u0018遉g0Xٻ\rSp,WO*\rSshԒpJW+hSȅ1Ʋ@WR\u0019\\җs\u0007kAzʝ\fBgT~5jP\u0007vt:\u000b\u0003LA+\u001e=˿\u000e|T%w\u00157U\u0018҈2p#=<dJ_V9|CkÅCnf\u001f㘾Ѩ\u0003]KՖ!'DFa\u0001q3;/\u0019a3{h\u000e{qY<<zn\u000b󼹺h'SO1glrz^o⼵qλUV='N䤂A-)_Ϭd(\u0006\"+^N5c<_\nn\u001b·spj=\u0019\u000eݣ05\u001dYJ7/Zi[;]>7b<N;%\u001fX\u0001\u0019FӾ1\u001a(愍pf\u0014~|s˨\u0017J߾6rɓZGE`\\\u001fgSabb\u0001E;eaS\\}\u0011WEv>\\\f\nMM畡lka+Z]v\\\u001a\u001fN\u001f\u0019mї0<hqL>R1v){Yf\u0011M\u0001w\u001e\u0007^\u0018A\\\u0003qEN̲]\u0014as`)|Խ\ty]Tz$<\u0000\u001bO\u001bF~?l:tpoޣxnxh\u0015rx/\u0006_Ɲ\u0003J_^/\u001fĜӫΝ\u0015فTq\u0007rp}~x}\u0015~tJ3\u001dF:\u000f>!\nϖ^o,잾T\u0005lw\u000fboݲ\rk~;ӑ\u0007m\u000e\u00133/7\u001e{do/YYf\f>_:yqψ\u001bٞ}\u0000K\u0013gF\u0010`=88mXD^bg\u000euY$۞}}N[pqoF}<W'\u0007_ͼ,t77b\u0001g`a̩a\u001d\u000f\u001c{|=$ǯ͡jb^]kondmlkiMe|AZ<-\u0001cj:n\u000e[1vZs;ٽ{ݼEk9AWۺt\u001a{dVꝍ޹h7^۽K{\u001cO3/gg˳\u0007\u0007/WvjAoܻd<ok`<ڸ'\u000bz]q;K\u001e[Ox-:sߛܻ\u001b\u001cnla)\u0005\u0016->x>th\u0016=ޟnZӚ1zzjrjDpsݻ2g߲χ;ms=}ej~Z>^>^zqV\u0017K\u001fV\u001b;\u0003Z&Ó\u001a\u0016v^\u0017\rp\u001f,vYicsӃۻf^r\\G\u000bsfŬ5\u00027{s\u001fu\u001e};5|tcj-\u0003\u0014f;LǶV\\iw\u0006dﯯ9+\u0015M~Y\\jZf\u000f\u001e=x8ߎi=̋\u0019F[wϭ*\u000f\u000e\u000e\rWy_\\W˵ऴ\\\u001ar/>x\t˝0C\u000ff,(mn/~\u001b^\u001b7J8x8\u000e\u0003_ƒ\rM7a^yx=~qBNYhσ翗\u000en~\u0007ٲ\u0011wWQ\u000ek-,\u000f\u000f>pe}_E۷~ZݻykǕ_{U Ioe\u0017\u000f[7\u0016je.p9\u000br\u0011\u0011\u0017ޙsl\fIie\u0014ƛGetr:\n.\nT;T<3ZŇo]hZFtrlӅzb^[ff?+'k/`\u0019l{Ө\b\u0015\u000f;\u001b] х/\u000f\u000fNyiٌ9_\u001ce\u001c­/~n\u000b9pl}]>5֧/F7C\u0007֋}\u001e,}\\~ᜈj}8[2ogɿ=\u0017,\u001e-\u0005myҘ\u001e:\u001a\u001bw|Y:|9-7g\u001bVoysQa1;b(Z\u001dQ.sZ ̯ά/o.oZn{py[;Zt{^T1+\u0013+[7%O\u0017\u001f\u0016g\n*z\u0002cGSi\u001dc7OJқ'\u001c$`Y9\u0003f\u0016wsp{+\u000e2?/_kN\u0017T.Dp\u000f\u0002`֓O|z99U~2;E\u0011(!'\u0007/g_\u001d?̭G;\u0003#\u0006yFXl8_;\u000b4ox-SXn\u001f\u001c<\u0012'kǛC>\u0014m\t~;Z:-\u0016%2_J8Fi3|z\\[K`ˋ|\tՃf^\u001c\u001c=݉L\u0011ŭ~iz۷~Z|Y9{%W[\t\u001d@\u0006\t$d\u00057\u0002\u0001BgݻwNĉS\u0011kIFf9\u0018I*RW\u0018[WM}LU?߮Wc˻\u0005eמ\u0016U?*,}lΗʝNx˵\u0019\u0014a.hac|hRa/\nnD^V?\u0011¿,~s5WR\u0017:iԒBX~P!F\u000f%\u0017(kP˦q\u001bc./\u001eJ-7\u0003ü8\u0015z\u0007=G4,Ǹg]\u00111l^\u000f{^[;\u0017\u0004\u0015)\u0003̓d{~\rNXw/Ғ|Q\\N^w>f4ӿ\u001dlϋq?\u0012\f/cy89nѷ#&I/\u0017gUSN\t\\\\\u001fѓ%كP.\rvOl`L׎uofb'0-O\u0016+xM+@k!\u001fǈ鋞M\\4rQnTiWpSWଯƍ៍\u001aE\n͜6\u0004\u001b[\r9Cw9N-\u0018SԗT\u0017g\u0018F|&ϚHg̳msAHȿ3MΟ\u001b,}\u00194>Ӝ'\u00077F]G4Lu,UrluZ,пo~`]#(\t,(j71Bݗ\u001fKGTOWm<bRZT-\u0000ef-}oۃv]\u001cI%/c3*N:\u001fU@G#wwwF/\u0001&\u0000B\\ʿ\u001f69٢ y%\u0016a\u0000/\u0012]\u0004^k\";ɯ^\u001bJ7\u001bƍ/i{I:7n6Vܲ\u0006V\u0015r8\u001b.\u001dw\u0013l^[Y_|o;\u000e\u0014eX\u001fގ\u0014}n\u0004\u0016ShPm*\r+ŋBX\u00054Zj(xa^rOp-rɸߕS\u0010k%[?n羽\u0001Z[{\u001c\u001f-\u0017v?׎}]M?X?ih_S{n\u0004nz?W(jwS\u0004B0\u0003u]g\u000e42\u0000\u0002\u001df\u0005pvF{\u0004㏏#)\u0014)](B\"\u0016^do\u000fw_q6{\u0019\u0002?\u0002ǿ\u001c5rX\n\t\u001cU(\u0000U0ehnw9PC=_\u000eڇǃW?\r@\u0007q#]b\u0018$?\u0003\u0015r\u001c<\u000eyACKWTd\u001f-0U35.ǔS| \u000b&\u0007\u000eh$(\u000e\u0017ǐ1|hT+`\\q4\u000b\u0000\nR5\u001atK\u0003!G\u0014*iԨ¦j:ZF\u0007\\\u0012\u0012ޫ#nPPAP\u001b\u00021\tIJ)\u0015pBEB5Y6.ouY[Vo\u0006:,FJ%\u0003KO\u0000>0H%\u0010p\u0018\u001ej<c\u001f0DpZ\"|\u001aڌdU)\u0011˲;3-AR1ϊ7\u001aF\u001f|\u0004\u000b5\t0\u0013\u0011HJ.~@)PqC&/F\u001b(w{n=\nwR+>\u0003#cSX\u001bVe\fVT\u00116l\bY#[?g77p\\yaj\u0005t\b\u0016\u0011^ʫt8S\u0019\u001f\n\u0015ƍue\u001b\u0005|Y\u0010\u001aY\u001eIy[5\u0001|uS5=8\u0016b]!\u00037'sn]p\u0007\\oswCꌵy\u000f8mmnLwK\u000fl\u0011؟u,vym'd2\u000eN˹\u0005{h|.\u00142Yף˅+-\u0002n\n?ཌ\u001fVwG\u000fdR(>-V|\u0019+,j\r'w\u0019\u0010ߴL\u0004\u0005\u0005Zꧤ\u001a'=gDx(ø~<L\rv\u0003VE_R?\u001f\u0017PM9fLz`@\"C\"q6[r|[U=\u000f\u001d={gj%o\u00166\u0001&\u001aN\n`s6\u0015K6i\u000fXy^h,{\"\u001f+\u0006G[\u0011\u0003S\u0000'N6,G=\bn\u001cxz\u001diS9?gM\u0018Cf;D*?\u001a園,Fl\u0005iR\u0002~1^q\b}\u0000\u001e<5\u001aBi/\u0004DbEⱉ\u0012_\u000f=\u00192\u000ew9\u0010#r\u001atM/򪭁MQAO\u0015TE?G'RՄ/ե\u0005:[[T \u0007ԛ\u0013T\u001d{)ѱ'\u000f#퇟Vfv0Q\u0015%\u001f0[x\rGi\u0012X5XyY<dOTt\u0017UC\rW\r\u0012g\u0002\u0015\r\b\"6`SN<ھuZC>#\\\u0003c69IsF\u00065x\"L\u0015Ý;\"\u0018\u000f\u0005\u0015g\u0014qky\u001b>ˋ\"^X\u0000t7~@:K ݂\u0017\u0004-\u000e9b-\u0006)\t̊DT:\nר\r\u0000W=~\u001f5\b/Pf5\u0004#5\"4'EoFΖFa(O7Z}\u001c=\u0005uzs>2.X\u0017;=2~qT'~\u001c\f>\\B\u001cÖت\u000fE9\u0012\u0003\u0015\u001dy0*jMn&w͞\u0000H\u00167\u001cB\u0006O\r,I0mebnkKcLr\u001aU\u0018e\u0007\u0014\u0016M\u0000I\u001c,\u001dle\n\bJ/;C\u001c˞^\u001d==\fL\u001fW\u0014roVw8OK\u000blEyN$Ύ@WhtqNZ\u000bo\u0010m_0[ep&B}!ٗ2(0撌J\\úA|LQQ\u000b)A\u001c\u0015vU\u0006L\"׺#\u000e{?fql:jjہ\u0001{\u0005G\u001d\u001e]Ns:YR\u00056쾮C~\\\u001ff\u001d{x\u001fc<.x5\u0001\u0018>r5W2X6Ql\u0014\u0013\u0000\u000f\u001e7\u0012\u001dA4tУk\bo/\u001eоw{y?A׬#éb#n6~E\u001az\u0013|imRq?&\u00105Yas9\u0018(q:UW4\u0017[^ۊȢ&l`߾fG\u0016&2\u000e\u0017\u000b\u001egO;Vq\n\u001e7cV\u0018k@-+U\u000e,y*Ct5~05=v(\u0002.SQg}A\u001c$\u000fyQi\u0012\r28V/l*ێ>q;-iW.w]8_Mr=dw_Y\u00104T0D\u001apbt\u0005RWp\u0019r\u0002u+f\u0013GT\u0014>~@57b.\u0014Ot|F\u0012@_fMX$>7_,Fcq&9\u001e\\[ߑ2;\u0014O,~\u000few\u000fV:w3*\u000fv\u0017\u0006p\\bIƼ0\"DtR\u001b!Ux\u000f:3_\u0005۽T\f<J;@F\\\u000e;!C]rnW\u000b\u0018I\u0014Lnhݕz1xPDW\u0005\fukfb\u001ceF2ooB\n\tX_fO&\"B\r2\u0017\u0016ZC$\u0018P+\u001b\u00147-xt;\u0011LfD XA\r5\u0002\u0001\bAm0\u0017J\u0003&\u001f\u0011\u000eHUi\u0017\u0016\u0012l3CZкjjq=\u001cȜ\u001c9\n쉚LWz\u001a)$\\+C9\u00190o#2\u001d_m^\n\u001b\u0016\u0002APFboZ)@Gwi[}a\"3u.7\u0014in\u001e\u001a#2ؼ\u001d\u0017ǜ`11&W\u001c=WBV)\u0017Zc&P\u001f3\u001e\u001f\u001a\u0000Z<\rg_u\u0013eޝ\u0018=\u0006kQ{86]By\b;\u0001Q5uyD&|LAqcϾg\u0014/\u0003\u0013\u001b\u001dxMժ0]CC֕o|l?\u0011\txHT\nϲSZH\u00001\u001aHA_(?\u0004:\u0007܈>zЇ ZEqz`|b?ZޯJ'\u0004|.\u000b)<p\u0018\fO;UUl>R\u0016ڒ)p!W1\u0001^A馝YV09LY\ti\u000eZ;a\u0001@%5Ȕ>,uhNI-+\u0004\u0017<KV\u001f%$jRƼ\n-\u0010Jg掽\u0019-\u000eEVgN\"\n:\u0001\u001dU\r&A!eC\u0002kS4\nl\u001c5T2q\u000e6cW\u001eX\u0019\u001b=q?YfCaJHgFk<` x`bYb\u0000(ya}k\f:R\u00056\u001en4b`m/\f\u0014\u000e1T4Ǳ0\u0016`y\u001e\u0012=#՟oTwk#1|_ /p43ԍG(\u000eWZ^(\u000fºVѳGby\u000fhW\u0004\u0012ߏ8 MOÚ[p\u001b\u0017p\u0016a벶*\"/\u001f&΁Uv#aqc+E1r9Eܟ`3W͎\u000f(6^\u000bMckP*8S@\r]?F\u00140n)s\u0015\u001d7:kX\u001bm\u0011Ov1\u000b]^\b͡85uԘ/A\u0006G9d'\t\u0014\u001et\u0001o3|M\rH\rb:n^B\u001f\bU{LI\u0000ȥ9-6Wa\u0006Us~ʊx]֯6(4j>r\u0019\u00066<}h(DgJ7>bu-ld5?V\u0003p\u0002\u0012XW\u0011$i<*f!x<\u001cB95\fq&(\u0005գRR$rcVy0TU\u0004rk62Ȱ1*q\u0016k4Ͷ+&:s\u0007ɲ'Wy+aU\u0001\u0016@YU\t\u0012_}\u0007w\t{\u001fw\u0002yyomF\u0006\u0005\u0006a?F*#I\u001d\u0001\u0001\u001c\u00065eK\t`\u0004\u0011Oa\\0X]\u001eQߩAZ\u000fr\u0016ڥe<Hb3\u001az^\u0017Oo#P!9,xggHэN5WRznQnqc\u0018ͫ!yu3\\\u0014m'm\u0018\u00047`\u0017}\u0000JGR?IsSn*\u000f\u000b&X4bƿliP`KE7EC/\u0013jʏ>\u000f,f]\u0018\u0000Ea<TumᷦIi\u0018^w/JչW'\r\u001fۍ\u0016<j\r\u0001zq\u0013;WP\u0019\":_jK[49\u001fj\rU&\u0014}%j()[慔\u0015}%5uΤi.:F\u001eέf%f\u0004\"\u0003\u001a\\Շb\u001bRPGa\u001b/U\u0018&]KV1Sr<\u0010\u0002l\u0006XS\u0006\u0006q|6uz\u0005{RQĄCI\"*@\u001ecƕ|nl\u001dj,[\"]M*/8\u001fߺͱomvj\u0000\u0001K:g\u000e\u0007\u0002\u0003\u0004uT:\u0002+0\u0007h\u0016\u0017\u001e--\u0010\u001e\"Z0p}UmҦjgԥo\u0005tU\fZ\u0014mp\u0004eG\u0016xܢsF\u001e+[>R<+\u0001u\u0017ve.L\u0017)0A\u0014\u001bИK\u0010(-%\\EjGachIO\u000en(H\u0010?l9Y_Os`ۓ`\b\u0011\u0013#\u001e\u001a>+fQ\f|\u0012w}ΟUN-(\t\b\f++\u0000goڬink#OAn^5\\e<\u000f=\\|G\u0017\u001cаCZS?Fym\by)Jз\u0014.8&]l\u001f?2mFi5\u001d[u %Lk9r8i\tD&Krtv\u0017FS/juOO\u0015\u0006T,Ƙ*x5\u000bڷY\u001a-&\u0014ii\r\u001c\u0006Qz:؝siYIjv\r\f4.֘Sc̭\u000e^5\u0013\u001e4ez\u000f\u001du\u0015ufW[\u001d\u001f\u0019\u0017#y\u0018N\\>\u000b֮:(;n\t\u001df6]NaUi\\\u00014q\u000b\u0000VڈZ\u0017=(M#!Z\u0010Ћd߮^\u0019\u001e\u000eu~\t\rI.bC4bN\u0015;m9\u001dkQ3\b_KĲaޗ^F\u00000\u001aq#h\u0004L*͔y*%?6\u0015\u001b2\u0016(+\u0016Fi6w\u0012yʡR.V6L;go\u000f\u00010Ly0d\u001bW9::<\u001bC \u0011\r\u001efn\u000e\u001e{\u0019@*ݚ\n\u001f)w҂&HgPs\u0003\u0001\u001cD\u0006,b\nus\u001d\u001b\u0013\nq>}r\u0016뗠\u0011\u0014i\u0006\u001a6;z=sY]\u0000ѻ\u0001t\f.\u001eK\u0019i!|KI>&5zŒ48u,qP:\u001a\u001e\u001cW!3H\u0013́`\u001cU<5\f\u0016+\u0015i,,8\u0006-P\u0006hkձ~mjT᷶>EO\u001a:\u001bݧeDmH;tm1\u001b3h́\u001ei-RZ\fi\u001c\u0018cK\u0001xF\"O}lB\u000fD.:j+%,8B\u0019Y-4\u0018xyc\u001dsŘ]1}ֆʡv\u00060d ]\tU\u001f\u0017l\u000bh\"U\u001eLH8H߂{.@R\u0016Q\u000ez\u001b}^7!\u001c\u0002Tfu\u000bEx϶\u000f\bċFzi:V%{B\u0004T!U4\u0002\u0013on>̈7<u~\u0007\u0002iO^:;|r\u001ah>9(\nrs(%r\u001a\u0018K-WJ\bb\u00193\t\u0012>p\fU\u001cz 4ziJV&\u0005C\u0010lk˨P=y<x! c6Ⴁ)\"Ң\u0018PxȡT9\u0019]\u001dQ\u0012f\u0000\u0010}w>(\u0003\u0015?#\u0017+po\u0003\u001fJo\u001bT6uؔ#/߭^\u001d,>.h͇%0\tf{ս\u0018͂Bo\u00054Yǖ;΁\u001cH\u0014&)OLX}PwtvW$gcUtKճTK\u0003\u000b:\u0002/\u001f\tc\r?6k'qO\u0000m>;[oXg5D'bΚ$(\u0007\u0002lr V&\u001bF\u001d(\u001d\u0003\u0003\\Pqza9\"ǑI:7ZZx\u001ejH\u0003UDf6<Ks;BA^4]X\u001cDaon'\t\u001d(\b`nC)9-,b9\u0003ϣ3r3ܩ\u000fAγ|h<39FLul\u0005!Df8? pc\u001b[\u0019hDvB\n5\u001cO\b\u0001]V=}յ\n\u0005@\"'9\u000emPf{\u00151\u001a[\f:C\u0000&%P\u0001\u000f`T:>JܺWd7kC<\u001aR,*N\u0000f\u0003Q9@:\f\u0013f 97U|q4\f\r]$\u0007?\u0007!r 8\u0019z8\n5jg\u001en\u00124=i.k\naG-V\u0003w\u0017m\u0018jXǽ.\u0012\u0015Tv\u001c\u0017=S-aӣqp7\u00121\u00171t!ǽ\u001f\u0010*\u001b΀ p\fȡ9\u0014?\u0000%u8o\rzL\u0013=7\u0006E5\u001b\u0013<\u0000%,R\u0005f\rN+$$8\u000f\u0018}fuz#Pbh{)Y׵E\u0019)C\u0011\"\u0007\u001cw\u0011\u0011KY/,}\u0010,\u000eicңƋt=\u0011{u?psF\rM\u0015.7ɧj_ܭ\u0019T\u0001-yX\u000fA/!!l!h![\u000e@zu\u0002\u001f<dPxd'9\u0010?4*|F\u001a*a]g!X\t\u001a\u0005A\u0006\"g^\u0017km[!1%)e=xnX(Aӊ=H6\u001d.̖\bk\u00055X`'\u0012CP\u000e3{Y\u0002c*VS'4b?]R\u000b\r鷌=6\u0000.\u0005ű*\u0015N!$7mSaSz}:1̧\u0010\u001b.\nazo(+=޴\u0002o\u0002\u0018Zs\u0005\u0012\u0002g2\u0003\u0001\u0019\u0011lc\u0003棭\u0018s\r.nB4\u0001y\u001fC\u0001ݖ-$O@\u0011\u0011e*ou\u0007\u0012e&\"\u0002/h*D==\u0018Z Fm\u0018'\u0001\u001bb+kz\u000b@@n\u001c\bYΣlEW.\\\\\u001f\u0017Kk:\u0006{/8ujbWm\u001bƴ$ݨ,cR\u0016$M,7}/,yc\\2ITܽgTnK\u001a7`!S-^_(\u001d~G\u001e\u0012Z\u000fʪmޛ_F;Nx3^/@L\u001b?\u0004¿g\u000e,\\'ߺ\u001e oeu4&ȞW!\b\u0014j1/\bN\u0014:vC nհH\u000f:}Y2\u00169Å{LdE\u0007\u001ed_&v.:Bw׻ҽM\u0004ג9[\u0018pt\u001a\u0018ƅG-ՑU:\u0003\u0018.|\u000fN\u000ej¨|$Ld?W-lǹ\u0000Y8b\u0000G츚sJ\u0005v\u0004K9/\u0014\u001ej69\u0007ZgqQ\u0017\\\u000e.;>a5oDěu\u0002\u000fyV*V\u0007|D͹5\u0002\b\u0018\u001frmU[\u0016e\u000eo!b7\u0016{\rN%YJ\u0014qs\u00182Ӧ\u001dHl[0\u001cܺ\u000b7+doHl\">Ĭe:Ni\u0012\u000e\u001b\u0003 }\u001c{>F\u0019ֹ.墊_Vp-y^\nf#F+ԖBcoƸbht\u000f\u000bI'|\u0018_d\\\u000e\te>\u0006,S\u0005*\r\u000b#\u0014\u0017ĭ\u001a(ɤ%+ʽq\u001csUe7g2y\u0013\u0002ŏ3Hg/\u0011bf\rqzVr/\"WQ\u001bQ{Pb;,ۢ2+2\u0006$\u000fUhD\u0017(tE\u0005W\u001aS)Ԇl0bdn\u0011*8wIH={dpMƪYT\fdL7\u0002\u0010N^4ͺc!s({jƍgOZ\u0013w_g,Or];RBF\u0010~ʋhrxP̥\u0007o\u000f\u0010u[3cCXO('5Q88\u0010\u0002UO{ B8\tl5r|*}W\u0013Z\u000eHj{CS\u0005ʉ J!\u000f܍Q\b\u0000Q.>iI\u00020k,b`X%a%~\"j\u000b۔Ki\u0004ly\u0000ϋ0\u0004ukҰBFy}K<\u0017f\u0003:Ɛ~\u0017R\u00040\u0003ٛʍ#\u00157[\u0003P\u000fs\u0019\u0010M\u000b\rb/|\tPkg+o\u001eU>4h^܆ϟ=C\u000f439,(*۬n\u0000HQII\u0018U]MK^˕ٙ0͙\u0001ŽBl\n}uE>R\u0014\u0006\u000eŲ>;i[})/\u000f@yT\u0018/rU7}\u001aŮ\u0015*\u001bF\u001b\u0018)I8jPh\u000124YMۤ/icTv$O\\stV0T)yn9~Ӛ2\u001c)\u001d'\u0018\f}\b#w\nĒJI0^Ą4G[E\"\u000fZS&Dmz48ZٗaXNF6\u0006\u0006@\u000bU\u0005\"\u0007#:{2P\u00011vΖg\u0019gq`Tjwdm\\y/\u000b5FܓLV\u0007i\u001e o)@7/wYN]\u0013\u0005f66d<+/7mtJ4[A<}?x-\u0003+{\u0003;:3Hz\u0002\r\u000b\u000bvGKt\"Cd\bd/@z'I\u0001Lx״$\u0003I~*\u000fQo_W\u001cN\u000e\u001a\"zW8kڳI_TL\u0017)񯒞݋`~m\u000b&5<G\u0000ݫ*m\u000f؛og\u001f:j1F\\\n`\u0019[\u0003\u000f\u001a\tЖؗ6\u0011J:C4e \u0007:\u000e9\rR؞zEe{B#h_䕙WaR7~\u0019~u\u0018J\u0001z\u0002OT\u001a$w\tC\u0000z\u0016Ro'JЏs>lPoI\u0000^R(>%3\u001b\u0018\rZÎl2TRS[GEK/@\u0019{\u0015ԋMڨEJx\u0013\\jp-\u001aF?>\u000e\u0003U\\eJV'\fv\"1^Cq?\u00160Ǻ'\u0001\u0007y\u0016e{>u[i\u00053jk\u0015W\u0007>+.N\u000fYgmUL&NT|nVQ'\u001eDr(U\u0007\"\\f>uJ[{^E\u0002;\u0005}h0ýf/^vE+S-j5]=G\u0017\u0018(tK\u000b\u0002C@rt6K=\u000f\u0001Sk8u'\tmV}\u0018\u001bL)\u0013?\u0015\u000e<1PF:+p:zWd\u001bmHը4\u0017\t\u0011xZ>U7f%\u0010W1ץK_ tYǊ7\u0015\u000b\u0015iA­\u000bdoUd:\u0001MdޒAy6AhSY\n%2\"C.UzR\u0013\u0010\u001a_\u0017wPrS\u000f\u0007S&tZg\u0007\u0003\u00033\u0019:ufr2|5{ov:y\u000f+h\r^a\u0013qrA\u001d3z!\u0015:a<NA{Irx|yR}DoU=\"\u000br:CI/v\u0003&\b;ԕ:}9Vr1Kbx7Tk^nᑪfw-\ru0o˯g\u0016Jᝉe5s\r^\\׾$J\u001b\b\u0001,8*7~`j<'\fKFJwH|#B&\u0010\u0018G\nܚ~\u001af:ꀍ٩t~RMi3ɘO'hy\\+\u000e%}3<+s\u0015%*\u0013buo-E%ڴqBA\u0000(՚=\u000ex\u0013uP*Е/\u001bQ\u000f8\u000e\u0017(\f+\u001bsY᪭F\u0017]pQMa]5Q\u0003ɡ|^\u001e+\u0002Xq\u0015%&\bUZO\u000f«P.\u001fF\u001a,vUG;5Y\u000b)2N?Iua+\u0011\u0004H\u0011{\u000e5y\u0000W|\u0015\n\t{%,\u001b\u0001\\~?r\u0010S3\u001a\"hf,Ю\u001c+yucrc\u0001/p6\u0017\u001501\u001ag]%Iږ\u0013H+SG\"*\u0002v+TAa&yD<P.;\u001fc^}ѓyC]\r\u000eZZli٠\u001b\u0005$4VNj}/Ͷb]m\u0019\u001dDe\u0013^\b\u0010;\u001e\u0005\u000bޓ9\t{1.&\u0014CVWpf(\f)笠u0\u0007rr -ϭ\u001d4V_;\u0019c]e\u0000ɕ~\u0004Si>N:q\u0014j\u0005<ac9\u0012ZN$Ie\u001fI)Et =E1\u0003$;oՇՋ2k\u0015w~-xX\u000edk/\u0010u\u0017\u0018\u000eɍ\"7@r\b69\u0003Gҍn~\u0005\u001dkn{m1)\u0013kFз\u0003\u001f7\u001dӓv{g~\u000bX\fזԱ\u0003\u001cM\fYsd;{;&\u001caз \u0019Lv\u0012GrqELڷCgE|D8-\u0002+\u001c\"\u0016\fqCӞ>\u0007\u001eX\nVu埆W\u0010X}z]0\u001bs\u0017vo߬<\u001cK)?/c2ʁl;*Z\\\u001ds߯'\u001f꽖}>ČT\u0019Vx˫\u0018\u000bɦ@3\tfYl\u0017vf\rܭ!\u0006pp>\u0016tu\u0002,íߐG[fL-x(\t\u0005fa\u000e$\u0003(JJ9ș=?,0֚8h3LRaiza\u0013d\n~H\\Fw\u0014\u0003Y\u000e\nwWm\u00166ہ\u001aL\u0010\u000e8NV{H\u0016\u0011\u00062ʹCIϿk̀.RR\u0016ڳNK\u001e̴-k`\u0012iQ{l\u0012Q6z\u0019΋ȧ`\u0019N.+r#WJIcǘ/\u001a 鿨\u0015fk\u0005\u0017q\u0010d\u0017y~!Y\u0002s \u0014\u001fSt\u0005c\t51\"NYҧކ!<G\u0012PvEn.K~[.*%`\u000eV \u000eګ{\tn@M\u001c9ו,\u00039y\f\twh!1A/\u000b#ì?4zD\\D~!T2\u0000^6\u0007Ut륣\n\u000fY'7oG\u0015\u0005keLV\u00013t~]iFgsIY7ץT\u000ee\\vN\u000b·\u0005\u0002*q8u&^ӸNZ\u001bhGKVf\u0016zCvA\n݉go\u0007=6\u001f0nJ%ӂOʾO&لOzd\rek`Нo?:\u0007\u0012r ot=DUN^ժΖ rJ\u000b\u0013XfZZQZZ_[vi~Jk̰r\u0005ᅝR<\u0019g-5M\u000bc\u000f5ui(;d|Gmi曇_\u000f#~zva\u0011\u001atIj,`H|3wx\u0001\u0018avi)(ƴNle\u000b{\u001eq1,J-\\$ώSL\u001a3*]wj\u0007\\T\\z\u001f6ћl=\u0010+tl[\u00107\u001a_X!{q\"\u0013mYn\u001dà\u0006\u00138\\d^\u0018xىɕv2\u001a7J\t^㡜}Ի\u0017nyޫ^\u001bDI\u000e^\u000b\u000b\u0004H\u001fK#\u000e_2l#*_ao$\u0007̡laŘ-΂bx_i,c\u0001hsަ*\\\u0017\u001akT!Sg \fY\t{M_\u001bu5\u0000Tv\r5\"j@.9G_R}i&akz_yطƇwSH\nFX6hO\u0004\u0000P\rI|]ZR.P\u000fc7z,R{<g-\u0017{gH\u0018s\u001e\\\u0013؇lRkl٩>ZN\u001a(ʿPrZ;\u0014\u001bWt~{yGj\f=]z.\u0003L\u0012\u001fx[2u{I\u0000taSGR}7'+wԛs\u0002 DNtYu/4Ӏ\u0015*\u001a\u001c|t*\u001eݽSNo\u001eeGEFz\u0018\u000bA\\\u0016E\u0004F\u001f\u000bF\"ʀ\u000b\"\u001d\u0016qRiD((5r{8\u001e4W\b%A\f\u000eRGb\u001f\u001b55߹sk\u001bQYXK^(O\u0001,dq\u0013*#\u0003!C\u001fTo\u0016;j_L+,\u0010+5Թ|nbcV\r1o\u0011\"\u0004u\u0007vNXH3P'hrĶV\u0007%\u001b:&\u0007ø+'9u!/i8JMwSW\u001d7\u0014\u0019#Lvw貄\u0016\u001e\u0013^KUZ\u001a'U5*\u0011~ɜ)\u00055H\u000b\u000fD\u001ak1rL9bu\u001a6Dn\u001e~{:\u0004\u001fFqڋ\u00167Nj\u000f23Si\u0012\u001fج\u0007\f\u001e\\dJԸ:͡U\f\u001e]XVi[H~ԙ\u0019k?1\u0005m$cG\u000eű@,\u001c{4\u0011\u0000%w_v+TN¡$֓Q\tGr縆!/{6q=E*vHҭX,v\u001f:>bVHۡ3b5\u0014F&F#\u0014\nN-\u0005z|\u0015*X0\u000b`\u000f#̊\u0014\u000e\u0002&\u000e+0bjYɍ\r%ѓb\u0007p$T\u0012C~N^j&%a$wP\u001b\"\u0014sQXyf3]h\u0003ƞm\u001a\u0001;5\"@U\\O>X\u0019d[\u000f\"X\b[\u001d\u000frXS\u0002,>y}Ѷ\u001bb\u001dƚ!u\u0007/߼FTEZ.\u0014\brf\u000eY>f_j\u001dW6\u001a._|]|.p_O\u0006\u0019r\u000fY2\u001f$Liw\u0017-#$(>\u0017\u00075s\u0015,je#}c|=n\u0005̎\u0010P\u001e|\u0013\u0004~답Y8G\u0016\\RZԸǎ~\f5\u0011.ȗ\u0001xg\f\u000618o*Y~\u001e)Gű\u001a\u000b\fM/o\u0017ՄY\u0017|\u000f|BŖP\r?t\u0011TES+\u000e@-\\X}Q\u000ei7X\u00149)ҟu ])A-p41p#B \u000e/=t((!|yO\u001e%:_>4:MB|ۑP-\u0015g7iQf&o4fݕ\u0001\u0010Ńr\u0014\u0016ⅇLv5{S\u0018\u000b`(>\u0006r\"\n-M%(p\u0019JeA\u0011\u001fG+@l\u000bN'\u0019&ɨY\u0017JB|\u0007\u00143'uT4v_\u001577\u001dM zV0\u0003O]f1qmZ>D{(xNei\u0007ԧIK2e($Ǉ`;Ւ(N&W4@d\u0006w\u0014Sp岩=N\u0007U,=2|M\u001c\u001fI{eZƽ\u0006SGc\b\u0011^Իi}\u0002m\teU]YLb)R0\tc\u0005\b\u0013\u0014qI\u0011\n_iBYN?+H\u0016CCu!ru5kTr;kbZ'=\u0012\"r[\ngI۽)(\u000e,oPSM(\u0011x\u0001\u00153JH}kKC]ga.\u0018ڕ(\u0012r!u6PE\u0019zј=\u00017_\u001e\u0012\u001bW\u0018\u001b}P:<*\u001d,vH*<~\nVCT6\u001fp\u0000UTCJ\u00186k*:+ʪr|\u0005Ӽ\u0018hR\u000eC|^\u0018\u001bl/!)n%i-nHNc<@yi$T:=Y\u0018fE@c\u0001!6+u*\u0013ݷº]N,V\u0011A\"\"\u0006\u0004Q$A9g=~=F/5}OFд&njEi9p\u000f\r^Ԑ\u001a\u0006\u0018D\u001aU[3iu.\u001b!nZ3q72\"6<h\u0016UGX/5>6fý\u0004O{|k%Ϻ\u001d\u0007ڏ\u001d\u0000Ky\t?\u0019\u001bX}#\u0019u2\u0019\u0016\u0018=(wZ{U\r\u001b\u0017\u0016Kk\u0013mix\u0007\u001br\u0017\u0018EYz4\u0011U\u000f;Ǎmt\u000bMXܩ\r\u000b%Z0U2W\u0001\u000f\u00173dY91\u0018\t4\u0006f}\u001czl\u001d[)vV``~\u001b\f3\u0000\u0014/IYar\u000b#k\u000e\u0014a,,G!\fo5JO?\u001e6-o\u0013w\u0016\u0016[=.~(6:B]V\u0007?ؓD6'8\u001bm%{#4K]\u0013\\.۴\u0016\u0013a6Wdi's/\u000b޳Wml\u0002'\u0017=;9hS\u0018;gLA_1;v\u0003\ny\u0018`e\":ȥc\u000e,\r\u0010Nwn}0\u001e<۝u\u0013\u0003e\u0016hysl=|?[-y+Jm}\u000f\u0013ɉ6\u000bBb\u001e\u0003Q_l)3ԩnVX\u001dj\u0019q\u001b_F6[­ra]g1;Q\u0018{[\u0019\u0004-\u000b~mWnӛԾ%,\u001cdG~qw])v~%\u001c;|\rò+o@\u001cbfmuާ-t4\u000b[N!*M{c׹t\u0012G7\u001e\fQ@zmωD\u0006Q2\u001aF`\u0007>G9H>\rc-6SI),\u00178\\|\u0014د/[bU23\npV)>v\u00033cTP8ZUփb\u001fe@^aoi\u001e\u0014\u001aMs\u0011=~:\u0004^n̿r-4qͦ×\u001b\u0001M\\|\\rշɷ7\b(eb}ǥq\nڞ)\u0006jS./-ev\u001bʽShR[H)-/]5lh5&\u0007\u0016r*\u0007yST\u0007<N]\u0010\u000f\u001c\u001e;\r8.ǵdhd,\u000eCp3`/\"t ^%k\u001eL\u0002\u0017n8_t\u000bN_* AnW(/)fN3d\u000eӗOԂ;fMO,\u0006\u001d\u0000=?_;b4\u0018T\r#\u001b@\u0005m7\u000fqpLN\u0000O\u0017v\u0016<\u0019\u0004ޚΪ~\u0003he\u001d\u000f\u0016\u001c\u0004{˔\u000b3z\u000fЋ\u001fs4\u0013DK\u001a}nn\f[\u0003\u0003PR\u0016u-\u0010z}&\u0004|1z?B{B4:\r2u\u0018/N+-(v#}֌@{=OR=x)pf\u0011\n<Z0<!\u0010e\u0015+\u0010N .\u0018e\u0019g}Ah\u0017\u000bZD\u001ahrO\u001ecq/F;h/9Zjܮ\u0005|Ag)\tY4i&\u000b׸6\u0004'͟=Z#C0?8\u0005ȴ:\u0012\u0003uff\u0007}4࠺)ȓvrv0#㕍JQ[Wo\u0015m­r\"YEn'n v.*گ8\u001dw\u000fr\r\u0013AWr2\u0006\u0001Pr:k=ì=\u0004\t\\kY?VcQ\u000e\u0011TWb\u001aҽl}?r\u0010R7r8u<*S[>\\eH~\u0001C6c3?(?#\u0003\tgڶjJ4zT߯l\u0010рKn_\u0002\u0006\u0006\u001bN`\u000fzkVz@J\u00193m<\u001fP𫡜\u001b睄,\u0010\u0017\u0001H.\n m'+_*=Y\\\n!+TQIuj\u0010\u0018)Y\u001a\u0007@ڠA^_\"R)\u0016\u000eW/v)ĉ<Vc誚\u001c\u0000\u0003[>S\u0004@;\u0011\u0017\u000b%Y8WT\u0017WZ/H>,)V\u00188\\#=P徿W_\u0005T+e\u0014цP [5\u000fd\u001fF8F\u0019}KBp̒i7sַg\u0012\u0005gڱnv\u0003\u0006(XlR\\f+)\u001aiv\b:FTĭѪw=#>M虑|$]|igf9tEK}m#\fRge׶\u0007si\u0015|/H}E\u0002^/஘vJ 0*WWF4!V\u0001Z8y0\u00106\u0001T\u0003av\u0000(Seu$\u0015\u0007\u001e˰\u0017.\u001a.ϭ\u0012jnh~Xme\u0001gwѽ\u0002\u000f^ @&\u001fP|T\"ՔIr>{@h\\%\u001a\u0011j\"͇>8B\nkԇEk&{H\t_tYca< !\u0015˜Ԃҷ\u0001-ay\u001fJ[^苞\u0002(x@p\u0010\u0013>j8[UpQ\u001e1\u0002_k0-{\"\u001bAo'P*7x/\u001cv5[0\u001cj=͸\u0013U]$\u0000[i\\\u0000)-Ə}Y\u000f$SS*as+^:\u001f7#?`ojYfJ\u0017[\u0006(B\u001fʦH\u0016\u0001婴~gt\u0016rDyᜂ\u001bY\u0005%ġ\u001bw\u000b\u0012mSqnӋN?n\u00038\u00054UH4Un\u0015h7G\"6\u0010CwSw\u000fd\u0012\u000f\u0017.M5q\u0011t\u001d{ֵ3#gH\u001ech/\u0013QUa\u0000\b!\u000f2\u001b9goB=ص&1^P\u0004YߣS\u0001RV2\u0003VS9\u0005vs?_?tϤu\u001bP\u001c8\u001eohU|?[*Y2\u0003Bal\u0007r#[vx!dD\u001dEr;<Ie#\u00012T\t\u0003*Ƀ[mvm#NAEeN\u0013r7\u000b5R;i\nԨlN\\\u0015=\n\u0015\u0013?\u0007@BTm*AgKUR\u0016غڳy7yZ\u0010yԔ5uuR\u0015!\u0016QZ\u00060p_(cVޢTyj_l~H7fԼH<[΀c\\%((S,:#7wY\u0014\u0004|@\u0003yyj6D~$]U?sJS^\r5Ql~m}^d'+_Ezs)h\u00014ȈTT_\t^3חVP\"f\u0013tY.)6Ǭ\u0005\u0012\u0017O?ה#0\"S[F,#gR\u0011y\u0018̈\"?_\u0014\u001eWiswG\u001e^MoQq\u0010c\u001d\u0004>\u001cm\u001e*|Q=?yE{Paq\u0011%\u00141۽L\u00052;%N\u0011\u0002u\u001a${OЗ8!;4$\r:Lh\u0015\nK^oU@\u00153K\u001dF\u001c+&yWXQS,eՀ=\"r,\u001a2*TUWe\u0007\u001bT:E<ՎZ/4/\u0011<R\rBJO{Y=Unj^VII%\fb\u000e6lk7**\u0014̸:{j\r\u0017=\u0001\nki'\\\t7.s%\u0017S~\u001f<'[٤0\u0002TTocR\\6ar\u0019Z\u0018zTc\u00165}z\f֧&䜕 W9]aM(Z\\\u0013,X'U9oqIh\u0005iYqA\"$2nb`$ХFgM3e. n\u0015i\u0014|4x\u0016W\"pV\u0011oS\u0018ėru9\u0006\u0015r\u0012G2Q$Ғv\u0003\u0011=Ā\u0005ƞ\n\u0004ˢ:U=]\u0001~&GR%\u001a-Z34\u0007\u001eֶ)w\u001b0q\u001d_c\u0006<\b>g\n\u001fd\u001cP\u001c\u0014L\u0011r\u00077\u0014\u001btl\u000b\u0012a\u0014?P3^_Q\u0018aXNkRH15s/2ĀVi@^-[]/#/}rY>_IT<EU\u0018\u0007YKwx6m{ҷ)Scg,&S,Od`rc\u0018\u0003ڑ+)^fExZ\u000eH¦.Fw\u001fmdj*@Cȝ\f\u001fAi:m \u0019&ݵT$\u0011\u0007\u0004\u0010\u001c\u001dGy'q\u0001\u001fL2\u0018\tSu`\u001c\\/֤1,6Rz|}\u0015gC]VPrKLs=T_}vh{5\n\u0004P+B=ɳe#%H̷Ұ\\|{\u0007o\u001ehb\u0014J:N.\u0019fE\u0012:+RSYݰgw\u0018\u0015N\rZsG\u0015`eԯ\n\u0012\u001c\t1\u0014ۤ*X\u0013\b\u0018T-\u0010`\n\u001d*ʝ:'\u0019qèRЀGXy%ᏧӃĎ\u001b#T1~2+̥ۨv\u0003b/}\u0005R%to/\u0017^w\u0016\fD\u0016[N\u0004K.i^+fB\f\u001d\u001c1\\G.<On\u000e\u001fW5\u001dR%y7F`}9c*\riޕm|[\u0007tI\u0013c7'\u0016mM!ObS+@,01g\u0013ql]~X\u0019`v<9(?(z\t0B,\u0007\u000b\u0014yi\u0007fL\u0007%+\u001d֪\u0012G0{~9\u0012\u00185-͌txE˳5Iys3\\\u001b}ɕ\u001fhO7KW['\u0005J\rO\r7h\u0005P@\u0000wʯQn&An\t<\u0018Sn\u0015Lb\u0006\u0006m6AΦM#d\ngØ\u001b\u0013(aY_1\u001a/)\u001d0)/o|-րS\u0012Ow];=\u001d8>7I\u001aH\u001aj+\u0007uYAފz\u001fյ\u0011_rVW.\u0016w[\u0013I\u0017uh:1L:\u0017k\"E\u0015u\u0013S+\u0007$mD\u0003\u0003~\u0018\u0010U}榊k\u001a-\u0007ѯ;k8M,\u0019uI\u001eǌ}\u0017Z{;B~x%2K?c\u0017EkL\t\u0007#YFnYW1~\nLڧi#rag\u000fg\b\te\\5F\t\u0003\u000f\u0005vqHi\"ڶe\u001fֿVoU!䠹P1AT\u0019tDvk\u001f癴\u0006\bOqDo*bq~\u001eۅj!G'ijiqU=7-:i\u0004&}\fmQ\u001c}jk\u0018:vA\b\u001d.Y}\u0002J0bQ؏q\u001dځ\u0017h}'wglۮEX\u0010իli\u0011eT&l5GN5Py4d;;9~po\u000eA65J\b5D\u001d\u0017ŵP@\u0003B^;\u001c\u0017E[lu&f_=B׎l㜗x\u001eX]g_ݘ\u001e\u00053swq&`Jخd:\u000f}\u0014\u0012\\ST\u0014&? @ٍk\u0018ōYԡү\rX6uٟ~0|CY.r-ř\u001b[v\u00070vD\u0000Ϟ\u001f\u0014-\u000b>V\u0001v\u001d'r\u0016wº8bd\u001aXNkΝƬqˊ\u0007A:WO\"/&\u00156H\u001a\t,/-JWƇ/̞Vd*\r\u001dw3\n]Qjז\u0000^\u001f|[?\u0010\"Ofyq.E6K\u000e\u001aJ}P\u0013T56I߹S\u0011>/a?{\u001e1#`UR\u0003}6?\u001e1κ,Lu\u0018=b3Ȋ:g.Nw59x_We'toIi3:m{+_xv-GT7\u00059yoPD\u0018r\u0006\u0005Q\u001f\u001a\rڱ >s\"(\u001fӢ<hwhRR>fm;\u0001+XXSP.\u0018\u0007!M<\f[MoQW}bc\u001d\\'Zw\u0010+\fRlsA7sFK>a\u001cB\u000fXQ\u000bd~ط=aC\u001c\\\nف%ynd\u0005v׾^#=G5<\u0000ڢ\u001dy\u000e6i{\"tX\u0002\u001f_Y[>\u0017\u0005\u001b%׫\u0000P\u0010҈$\u001czW,zE;\u000ez.QI*듿 \u0006y\u0012\u001cZѧiG<^NGTb^\u001b\t\u001b?\u001fʉ\u001f\u0006\u0005imc1\u0018J\u0013e\u0015\u001faLfCb0k(ox\fwy\f\u0019k\u0007,X\u0017E_[\tBƌ\u001d]͚^zI~0L8~\u0013sz׫u+\\oMKL\u000bhG~+\u00130gxX5r`#h;Nj,\u0012\u000f.n3el\f\u0007\"<#*|h\tΚF\u001f\u0006h\u001dNX$\u0000\u001e<'[t\u0006E\u0011^]~纝S^^$̻q\\\u000exFNtGs*\u001e,?\u001f\bZ]±\u0002zj\u000bU\u0013{\u0015\u001fs6\u001b\u0017\u000ez~=݅Xa\u0016\u001eX*=_\u0010H\r?\u001a\u0013A\to\u001aXe43\u000f#ak}#ﶲ\nR<\u001e@P\u0014\u0016^xBN\u0004\u0018\b\rJ\\dt!\u0010`\u0014ŀxǫOhzȴ\u00117W\u0001N\u0000j1XZ(y˭V\n'F&\u0010+W\u001b\u0005f\u0019H-F\u0017D~|ҊґR==\u0013>Eb\r*N˪}j\u0012WQ\u001f\u0010*a\u000b;XPQk~\u0019\u00145:IUn\u000e5q#/C\u001ec\u0004^w8Lq\"BfQ>iSix&Z᳊\u0018\u001b$!\nDsBn\u0018\u0017dOoq#\\N'\u001dc,U*CٲQ\u0002\u0018˓y\u0010\u001d\u001e)\u00006?\u0014x\u001bO\\ge=sm\u001cM\u0007ǜ=pq\u0005x)ۋF\u0016<\u0005\u0019S\u0004^ο,h\bC+\u0005o\u0012mv\u001d<F\u001cyB=\u0019\r>H˵`4d\u0011q\u000bO^\u0007\u0011\n\\`\u0003pEOa'86ԼIfӐ=(dYY\u0005\u0000B}\tWu<:/:p\u000b\u0007N\u0000PrSI B\u0018\"%Nr6\u0019\u0014B<W1sg\u001b&Y:\u0015pv+\u0012I `\u0012/\b՘NSIg+\u001ak\u0015}\f/k\u0001Ҵ4W6LQ\u001cE/\nӥ\u0005\n_@/7WnĻZ)\u001bA\u001f{b\u00126<<@u\u001b|?A\u0006?\u0010\u001c/\fp\tY\u0017|/q*\u001c]r\u0011#@p\u0012|s\u0010w޿:\u001f.\u0015\u0000޸\u0002yOiM.\u00074\u000b#25~s2lg3c&}rзӈt>>\u001f\u0005\u000b{W{KZVWAnR\u0012.DeQ?<ƖOOIj怭(\u001b<zD\nnV6\u0002w\u001312\u0015[\u0012xl\u001dwtfe\u0011r\u0006L٠9Fx;u\r.޵\u0006yĞ\u000feya7tj_ET~\t8$9ٛ|F[uSUݞ4i~3J}$M\\[(?\u0004Mi%V\"YM\u00111\u0015YD<bO@\u0013GF\t5v\u0017-Br:}\u0012dX؈{~X}Xe<K3{Wi\u0001&ȅ+]D+-8\u001bC0ѡ7\u0017Eng\u0004Ϊ$ٌ\u0017m\u0012\u0015fD}ٙl hэoӸs݄\u000eپoo֗\u001dD>\u0015͚얰(Ggn@f.\u0019^5\nawIY'\u0013\u0000Hs{-]\u0011ccм0\u0012ݣ,A\bn\f$\tkZpB&\u0004fuRyP2~ua\u0014\u0012b\u0011r5;3a\u000fX(\u001c/\u0016\u0017B\u0011\u001eQ.\u000bsxP\u0002-i\u001dK\u0010\u0019\";kzޛ|\r̍WG?J\u0013԰M\\){/m\u0012\u0006ޮ\u000f\u001b!&LMZ*:l>φS&\r{[)9\u0000=aJʐ\u0012}ŪރW\u0015sHc_üV~i;oJ5S_j(>)OCi,Xy<ܤveu)|M\u0000n?uL_ֆ\u0012h\u0004fLϒ| \u000fC\u000fh\u0018'gFVv\u0014@\u0017\u0000eUZV A}\u0010le#3\\Wce<Y)#h<D,\u001dy\rH`cl\u00076g*;\u0003\u0014cуg\u001e#\n%\f\u0007\u0017|`\u0010g \u000f&C_]\nݞ\u0004>K~%8=\u000e]\u0019k}wx|`}a\u0015\u001e\u0011\tiHݣwkT^0O=cM\u0010\u000bݸ-\u0011ᦻ]\rnCG\u0013>\u0012jM-5p)\u0019\u001f\u0010Q0&tz\ffo,I}nT\u001b=uAq\u0000\u0012-D\n\u001d'`BxHu\u0005u\f|(\u0004̽ctpΟ\u000b7FɸE?0;&$-\bQ4ѶM\rmd~\rC_D\u0004i;'NCn4\u0003G\u0019_}Gq75֭\u0005ņ7&P3!y\rC/n>\u0010\u001bLjxR\t֞\n^\u001dcY͖tfz_3`U59V?_\r\u000bY}J\n\u001cD\u0004\u0015\u0007b@\u001b{\u0007ZJ\u0000O/ȆحA\t#JW\u000ehSQS_W1S);\f\u0010W9VCǶq\u001c :RWdD\u0002\u0007T~'&w(&kWS(PgQ}g\t(i\u001bkChsY\t\u000frk\u0000>4tne(|\u0013\r\u001dy}8zJه\u001dX((9ݣcs+X[:d\u0007(G%ԡi&\u000fLsf?\u001bs9+:\u001fvY\u001a\u001e:nJL\u001dUPAku\u0000zG|\u000f\u0001,.\u0015}74@J\r(Z\t\rD=c4æc?|\n\u00132u\nLde>wxI\u0018\u0002C26f,\u001d<:CD_N\u0001{iϥWP:Q\u0000F`e\\W\u0019W\u0001\"{Ѻ\u0011WiV4a\b_C\u001eCR\u0018g\\yR3T\u000b\u0001t|Gbk[0Vsҟ֗|\u001f\r|3ʁkIzկ5\"mE莮_Ai]\u000f̛͢\"\u001en뵺T\u0018Ϫv\u0013\u0017u1f=\u0015}7ΡMU\",~fd!gwu\u0000:Jͺ:ҜU\u0016r9\u00065Cncl\u0001:?uȽ~kr>Y\u0000FlM7҂ա R\b2fdi%{c,k~o$0OJ\u0007\u000e{1\u0015HO\\X3{|M\u0007\u0003]=\u001fZ-[q4vAj;d\u000b?f[]u\u0019co<\u0002ԛytCy$\u001fV0Ԭ\u0016E&\u000b:I\u0001t/a8\n{iŅ焮>ܪv<\\/X\u0010J?T\u0010A*P.TL\u0018V\u001d\u0013Kj \nWUҫyJ\u0017ݻN\u00036#[q\"ϫkl\u001d\u00171F-Sh\t\u0001\u000f\n.ˏ>[آ/N\u0014j\\;\u0016`%ȗrEvت\u0016՝\\\u0012{yZ\n\u001d5Yd\u001c\b2h|,GT\u0017^+CufPsW`C@tܯ\u0013<3ט/\u0016\u0016\u001aC\"Ns* l\u0013I\u0007yǘ\t\u001fr9>x\u0015K<jnk`eRnob'*u\u0012xHk0g/ÿ\b\u0017\"(Y[\u00061z1f/Of%{]:]\u0014\u0001ΧCsZ?\u0010~`Ƶ,J۰Uq_`c\f\u001fpY}~ZWT \u001d|i;&g|\u001ckKcjpGa%GU?bg^nЦ<V\u00053n;C&\u0018l\u0019\u0013ZHrbKGw~/$;A׈1\u0011n>:\u0015_\u0010Abs\u0004a\u001eUD\u001f;ǳyrgJ\u0004\u0010\u0011XV\n\t%6˟6\u001f5V\u0017ܫp\\#&_\u0014ZGp@%+Q\u0013e\u0010@J#.]&1G\u0018\u001e,VN#ɲ\u0016**N~j\u0010jt,yn[W\u0004R9k\u001dr\u001fsoE\u0001\u0018d=\"߂;в\u0006N}=5\u001d}r&Xd/DO3Cc\tü\u001d\rzٕ2\u0000\n6Пmeh)eizpx9w\u0000Yjio\u000fT<YBe^w\u001d<lXj|\u001dÑe$ߪ:6yjs_\".1z`K!\u001br{2U\u000f<)7\u0003\u0001\u0004~\u0017 dx\u0010@ڰ;F02u7/lD\u00076\u0006;\u000bSuZS\u0007]Y\u0007.\u0010q^XLwVaRm)[Ao:aL5\u0004207\f\t\u001a!\u0003r$\u00055Xq>\u0002輏Fa\u0006-e>8aZ@*\u000bc\u0018)\u0011!\tY/}\u0006DD\u0007\u000f~Y4.\u00066d\u001a\u0001\u000b\u0012$_o\u0014+*-6\u00128\reQ*Pkb#&%\u0014]+/|\u0006?\u0017̯1?b\u0016i~#/>z:.l\\\u000f\u001c&5t5\u001eE;\u000e?\u0005igj1aӗc']cnRwC]o\u001a.V{sε.K/V\u000f\u000b\u00164B^0R}U^jfh.鮶67\\D9[\u0010\n\u0006T\rd}\u0010A9c\u0007y1\u0003ҷW8CbZug\u0000\u001cv\u0002Vv\u001b\t6\u001b/\u001a}{\u0012\u001a/Y!iǈ{ݝμD\u001b]/ҩe-+?W\u001brzG0n\u0017\u0011\\Ŗeuv\u001dptoAcQB1[z1I=\u0019Y#I<ƀx޶S(o#\t\u0006y$$&=\u0001\u001aozZ\u001a8=Q+'\u0017j\u0012AB.58\u0017Bk(TS8CQy޵P\u000es\u0011x\u0002wEɶXx\u00157%EKĺr׶\rF)@<.[\u0010*Ӿ'J>|\u000f\u00183\n7\u001a,8\u0015ճ>bLyn \u0004d,}7f/L{^kJ\u0011\u0015M}`힓U\u0017\t\"<\u00129W}B\b\u0006(m:IBDEI\u0014$`\u0012\u001a&v<\nq\u0001ߑNt6F:\u0007fQ9 3&z\u000fL\u000fP۶3b\u0010bsHgbWПc\u0007!VX<ՇA\u000fD.η\u001e娶\u0006ΉG\u0004Sڴ\u0019\u0007ޗLnĵ3\nai&ϯ~\u001e}Y\u0002\u0002\u0015@= H{Y<CNE\u0003\nI֑\u0001+Դ\u001f-\u0012hL}iGq&\u000fFz<\u0013\u000e\u0011ydLұ\u0014rr\u0014:yRbv>nB\u0017@%X8m8܋\u0011@\nOΧq\u00172U1)\u0017\r1sZlٌT.qo\u001ewUNsBiE\tXjdnMs߼g\u001fxءX_LO\"^xR\u001a\u0006YKJ%RW1\u0001{U.}hca\u0017C\u0005F#SAU\u0006p\u0006pE\u0013ozٝ~H{K\u001b+hmϏifHPjw\u0002\u0012a\r\tb0>X¸\u001f[Fɖ~N\u001e=Xv@\bXш\u0013\u001d>ǖ\n\"Z%isju\u000bn2Pcd8q\b\t|\u0015ԻJ^#rkgz)\bM\u001f\nz@t\u0018.\u001e-\u0015o1\u0019gCGp7\\[\u000feؔk@N\n*\u0002|\u001d޲\u0016\bJ.\u00064\u0002y\bő00Y\bՏ?]^ST@럪+3-wa\u0011s~A%\n{\u0017\u0016\u0004(\u001eyv%\u0002-/:!\u0019&#s/J\\*:<f39)|n Jt7.'(!\u001ftha\u001f\u000fnEr\u001a\u0007Ʊr;SB\u001d5^G^D\u000f\nzJ\"^\u001bjEu)so`.'\\+Xqܵ+&wY'\u0006\u0018\u000f&\"~\u001a\u0018\u0013Eìr\u000f\u0017A\u0016\u0005\\\u001b|\u001a\u0019nIw4\u0016{6f\u0007\f\u001fYKw\u0002>\\<½t\u0015!\u0003~\\F|»'k\u0010=\u001f~Vyc\u000f}l혔0%H1k\u0003@oW-^\u001c\u0013\u0000\u001eB\u0010q\nWGM|J34\\ڍqL򩾛\u0014\\{Nx\fC\u0005}S#9\u0018֤1w v@\u0006G\u001f65<\u0016C;\u0015Y\rr\u001cN4zc6/?.I\u0000Ѩlu(6#Yg߅O>ZL\u001d&\u000b=\u0013=#\tj>>NQNںL/W5}\u0015Vz\u0013*L\u0017\u0011Ւs\u0013VA)t(>}-_\u0003j\u0013F\rCLצ\"\u0002Ա,mZܖQ̟\u000b2\u0013s{Dky^D/XbGa1/YDY\u0016\u0003&Bc\u0016վR)\u000f.\\c4A2?R[\tn\u0007Q\u001f fX\t&NeS7#p\u000ev=!\u0015\u0002_\u001afm5.~\u0005)6,4Xz\u001db\\3\f>Z(\u001eW^>z\tN\\oEj9׷\u001e頰]p7aQ\u001f\u000e6#=UF\u001em^\u001d\u0006,9Y\\zA#\u001dxCy-S?0F^=&&lcVk^F\u0014(\u0006?̥E\u0014\u001e\u001e'H;h,Bc[\nWBu\u0014\u0007}W{\u0013fv\u0012a3|9*󬎅\n;Q_~NӒ\u0005\u0016pH\u000f\u0015}iS\\W#V8,e\foJ~<Ĕ`Lp!ȩ:j ڵQޙD\u0006P\u001e9\u0014sc\u00040~\u001b\nvߕF\u0019φ\u0007+)h']BT\u001bSa\u0015Y\u0016qyu=ː-\u0012[\u000b!s(`]5j\u0016(\u000e\u00141~NW\u000fdG\u0011/W\u0015mp.}sGPECdr#'Ko\u0014Ѻ\tԗe9jb\u001b(?v7ny8K\b~\u0014gy\u0019l֥}C.\u0017dq*s\u0004{ImE^C\u001e]B\u0002\u0007Eoݺb5\u001c\u00166\u000fT8s\u0014DR96N\t$\n^iq|q(ۯe\t\u001cş\u0012^W{ЩXlA)`Z$hE@!\u0013+\u0007-S+U仭\u0011=\u000b\u001bVN%ҭ4j\u0005ZV\u0005Ah\u0001g;mD\u0015a@\u001a\u0002JԮP\u0011\u0007;1U\f\r\u001c(ĭ_\u0014U\u0003\f`k=\tW  \u0010ϡC~|wzk\u0015\b\bJ0a\u0007o>*\u0006\u0000\u000eX/ֻ\u0012Z2 IWKZg|v\u001e%{\u0005r\\S\u00198\u0004Cz5ZY?E:x7\u001aF\u0004οմ\fQvd\u000f\u0017\n\u0003Ƿ?C\u001aAo&팘^+xU\u001dI)&?w>R\u0011\bnT+\b2qdbT\u001dWMAP\r\u0002é\u001eΗ\u0017s<Z}0f\u000ekԶy)2Z^\u0011\u0014\u000731äk(|*AK͞u\u001e\f4ʭ.Gɦ'ne+\u0015\fC)\u0000Dio-\u0006\u0001i{QuWg\u0013]0\u0015\u000ex1Sjć6oʫuW\tSr'Q\u001f2ުq5\u0003\t7)FRQF\u000042\u0002F8_$;\u000fTp\u00143\tPY|7M\u0002\u0018\b,\u001dеCRB3{ͣBl/\u00016zԎɖ[l,6a<J.[ʴ⁒\u001bϗp\u0014S\nDϴ1,\b\u001a&Evr:\u0019>;\u0003ʠ\t\u0012f\u001b{M#\u00074fH\u0017^Ƨn\u0007F\u0014`\f3/\\W3QPa\f\u001cQ=\u0002ȕ\u001b11ǨKԧKQxAVyjnYI.¹u䪫\u000fE澪J\rc=X`{\u0013\u0002i!z.\u0000il:\u001c5'[I}\u0013{NCu֥YuT\b\u0015\u0004{\u0007\u0012AX-\"y$\u0002\thΣ3F\u0006;l`\u0016\u001dF|\"\\a\u0013ݓF\u0007oPȞ\u001fيMGC\u001bdVߣ*\u001cyzƦXK\"k(?,ԃS\nβXpk\u001b3\u0002L-(^=L+4/0&|_S;۸\u00131ƌ:\u001dH2(k\u0018\nCă\u000b|1 7t?pyQ)m\u0013p\rssUt\u0018Ӵ\u0004>_j5rp\u0001%\u0007<Z194[\u0014_\u0005o\u001bh\u000492B.\u0015d5q\u0002\nM~m]'Xۛ\\)Y\u0011VH$Xݕg)P;\u0011ڋޣGw&(,ݮ\u0017!@B\t\u001bͼE\u0011d9dd0P\u0017\u00137-PxF3iA2q!tw<\u0019rc\u001c\u0015]\u001c,[/n#9;fh9n+cϴ9\u000bc7j>^!X֗ai/Aՙ'I=I\u0017!J&\u0016\u0013\u000bbD0Y|ѝ8!\u0017<;lJr%=;Ю]1\u0004\\5K(W=W6:V\u0013MZͥqb9ggN{^7΅Aξk(&\rF%}\f9Woˀ\u0013G\nh[ZS7fh}C\t禬L\u001f*{\u0005\u0017hę\u0015\u00120\u0006Po>\u0003\u0011]tCwR\u000bk=\f\u0000f\u001eK\u0002@Z|\u0011/\u0010k\u0014No}\tGT*e8yr:Ec\u0019|}S1\u0006\u0013BD\u000fxq.'d7;αD\u0016Y%DQ!\u0006\r\u0006p\\[\u0014xcN\u0001]cZ\u0005k>J^K(x#vGs-JF\u0005\u001c(]#e)_қU?\\k\u0016w|r\u0005\u000eV؝ᖁe\u0013ଡ଼\tB)C}exXi1:7\u0011\u000f0ǘ[\t6eo+\r\u00031GٿhȪv\u0006%\u000bX\u0000]\u000e>@8YRSUK\u001d9\ru\bNX\u0005Io9H\u001bjجl>R(^زaU1a.gzNx!w\u0003\b\r~g.t.W)]ނZ\u00164}\u0002\u0018#m~EPKGI\t[E1`\"ٯ\nR Փ*\u000f/\u001aŕzu~pl\u0018%AbЩHcpVbZ\u0017Ƚ҅\"m\u001eiʷK\u0018GQU\u0003\u0010\u000el˕O[\u0014|7ڙ}\u001a\"ΐV;p/,\u001e\u0006P'E/(\u00105~\u0007l7uUbܶr%'p,p/\u0004X\u0016Mp,VHR+?\u0013킺\u001fC*\rvN\b\u0019-jE\u0005\u001b\u0015-\tGpt\u001c\"ꤶ^@?UG乵@x\u0002KXN\rVK\"7dSNI0&=}OƑuo[k|p0\u000f6\u0011\u0018\u0018暄-EI\nh1ny\u001f\r,kQ\u0002x,Ϗ;&)]n_5 ${LɢCs&q\u001a\fSliƐ;\u00141\u0013E\u0006c`\u0016\u001c~r?IK\fJ|Q\\\u0018GH`5uػp\u0015\u0005*6mg\u0001.`\u001fS򕤵'1B;\f\u000eCA\u0014A\u001f\u0007waߵb\u0014[\r?[~3/5<!Ϣ22\u001e!OFfxl?k,MWC<\u00073\u0010B>N\u001bXNg\u001dQ\u000f\u0010y\u0002L\u0016?W~d8љ,DȞzi ~AŻ1.$z|j܉\u0014NѧIk!0$\u001f[=qV\u0004b֤\u0000\t8͢&ݟA\u0011Q-\u0007ՠ}o~g\u000bG\u001eU飴m.\u0004H9\u000eE3z_/YMێ~\u0000\u0001W\u0005uIވ\u0019Z@=\bkb3/,\u0014\u0005i\u001d°;\u000e\u001a\u0015kqvJO;\fޓDT[\fDv]4gX2\u0018%u kp~*\u001a4\u0001\u001c}{hG`礚\u001a]mڝK\u001e\u001f6-uYe^LvE\u0019LCplyu4G\u001cz^}yPp\u001f8w|v̹Ee\u001dR-\u00078Z\u0016\u001f\u0001\u001d\u0013\u0014v3@oV.\u0002<\u0013\r.z\u001c_\\\t_{T+i&VVW'uP+7\u0013\u0017\u001e\u0018,ҕըwK\\ח\u0007NPW/0źd?Xn!Ɩ\u001ds;}\u000fIk\b>­$ G8HSi>Zˉ'ڕ^\\e|մh\b{\u0017IM<Jxr3+!TQN'[\u001d\u000e\u0001Qq4L\nn9\u000f\bm!=3&\u000f&:xo:|\\(m\u001c99RsrS<\u000e[|&ݹN)k@^lm\u001f\u001b9\u0007T&\"\u0000\f*xYX\"\u0019\u001eS\nP|W(\u0014\u001c\fjr\u0002\u001d}\\/ς{k3rA\\\u0002$|$\u000epL<I.Z}{ͷ\u001fRe!?\u0005\u000e(w\u0012s_\u0010w{I+f֛\t}>\u001f/q֍#laf\u000b\u0011tfXO-S=j\u0017Ff%mgeqD\"~Qrpd0zxM܄3\u0002/x\u001d@\u0005\u0011G\u001d\u000b\u0016ϑżX\u0002<8.\u0003bku4H5+uPj%6Hr#\u0003Ϩ*GAd<\u0013)be?h͏T/w>\u001cM.,\\AjR^nhk\u0005oZ\u0013 c\u001b\tR̓\bt\u0015>/$z\u0017/u~]xTE\u0015us9\u0019t\u0016Or\u000fc1p\u0017~-+t9K/|ʌ\\\u001cd[M\u0014a\u0016*mq[L\tXK-;\u0017\u0001R{\u0007\u0014\u0007$J[\u001d=\bY\u0016ծ\"\n#uO%]mLW* heD\u0019\n0tH\u0019g5d\u0014\u001djWr\r\u000e\r\u0019lsf\u0015ABI\u000ey7\u00160(s{\u00016ہ}\u0001\"8m;.e9b9*}[}\u00009C\u0014E\u0017yɦ{[)V?_Pi3pzVoZ|o\u001b\u0002]\f\u0019Cݼ\u0006]RZs2wgEZ\u0019yܕ>>\u000ff{n \u0004<\rǡ3b~!}u]uT\u0001)}6`}.EU+9r\u001dȚTI~\u001e)Q@T랇7qz\u001cB\u0007k1#zKȶ\u0014~_e3\\\u0016?!c\u000f^M8:uNmHOD$\u001e)^2z\u001dmb4dۊJ>\u001f##t\u001b\u0013XkDX%=\nI֙Ez+k\u0019_Pme8\u000fֆn8ӲޗcUъcWR\u001fIG4*ٵ''h\u0004K>NۈЊ\t(k\u0007Ṯo0VQWnSP-Q_iO\u0007P\u001c:qok#ris`&ktNF{ū\u001cv\n0\u0012G\u0017\u0012w\u0003\u0015T\u0010*\\w\u001f̂7+f\u001eb#;X{eL*\u001aEA b(&9y5Sc\u001cj&zY\n2\u001e\bvcn\\ܩG?32|\u0007Y9)\u0015<\u0007Zr6P[\fZ6\r\u001ee~=:\u0006X\u0000>]aɯ\u0017mYmƋdh9I^$\u00101č%p9e\u000f\u000e/ǳ.\u0015\u0012Z.w֬.T)x< :TTNݲ\"J<y5\u0012\n2xJtcHg\u001cx+.?\u00137FfW\u001a[%g\u001e\u0013)z\u001b\u0017ķt\u000b\u0017ӛ\u0007\u0017;g>gTsgM_zZe#:4S\u0017p\u0015ƽ2Vs=U.zV\u001b^k\fY3y_S#5\u0014Hian nx&=_[Е\u0011PPh\fhOjY:Qڔi>,oyRǖHC\u001f\u000e\u0017ؚ+i\u0007\u000e\u0005.\\\u000boM*\u001a!7>\u0000\u0002oڞ!kb)L\u000f}\u0003ѳ%N5G];瞪:s\u001fsO\u0015\u001a0]Z)o\u001d\r_Z;99D\u0018ʵ1cT0~r{Cm&\u0010q?_owM\"D\r\u0002\n8k×Mp]J\u000f\u0010\u001fC\u0014\u0006DV|Tt\u001e\u0000XWq]O)\u000b4ڙun<.z;qGy-}S#)k\u000bJ\u0002AW%Ql)\u0012q^jL/kHC\u0013x~#X{Y8\u000b\u001dEeE\u0016r.*ugkwܗߖF͚\u001bT=,\u001fN5sWohM{\u0003UWeC\u000fokN\u0013̊qoG}\rLpJXs\u0007V.'\u001eZB6|4ւ\\\u001a\u0014앷,\tsԇXF/(q\u0002r\u0017?\r\u0016Z\bZ cM\u001eR`v,Mz\"\u0003\tk\u0017@*\\_:9\r\u0012zI?\u0011ۇ(#م\u001a;c\u001f{mAGmk˛ȰVG{X4ݜ\u0019\u000f{\u0013ӂ4([:@CS\u0003\u001fC)[z\u001d8BJ)\u0018[#\rh#Yv5Xsu|o3zhlD7V(OOg\u0015f֍*]V\rtSQk0\u0014\u000b6qR;%>\u0017kl|c\u0001U|\u0012\u001f>4\u001ckt&0=|Vwq\u0015\u001e\u0018b\u0010йFG\u0007.z*V\u0012\u001aH'A\u0016^\b'\u0017%])˗A\u0016>tHx\t~SjΊnkY҂j\u0012K'M\\\u001bt\u000e)؅)\u0001\u001beg\u0007xK?\\^7#4uSD0 +Y\u001e\u0019&ieNsn<./`LZR[{'zz*\nn\u0014\u0014\u0002,eRZ5m%\u001fY9Irב&|i?%I\feMg|l?\u0007|\u0015\bZwޯ)7\u0004&\u001d\u0010\t'\u00010+\n\u0005tj!խ<ofRO\ng.'\u0006\u001anc\u0015z#+'\u001d{]\u0007^/X|\u000bu\u001bE\f**\tzfQiCSO\u0012Im$\u0016\u001e}'V\u0012,x\u0001\u0013v`Ѵ\bu\u0006vcz`Տw\f[\u000f \u000e/_ҏU>lk\u00197\u00122dj1\u00047r4Ւ+@\"\u0017yw^\u001e9\bҩNas=L\u0002m\u001e_c겯CkaϴʥJQ3vb<\u0003&WЭ;qSq!\u001f\u0004/i\\]\u0011G5\u0017.][z°\u0004\u0017\u0004cJ*g`\u0012̮IZc\b\u001e>A{?T%k.GfW\b$7e݅'*b*@A'2YټXj!~m[ܹ0dzdz䂅i\f\u001a\u0015\u0018w~#'cx\tZʸ\u0018MZhݨ\n!}{6\u001c\u0006\u0004=C{\u001a\u001c.ۡ3XN<p\u000f\u001eYm{<k^\u001cge\u000bŹb84[\u0012Ɍ\u0002{\ni\u0004R+NnQ\td᝶|\u001bkB9mTt\u000e\u0002:3_>ǐ\u0012\u0006K.:;,*-!\\\u0006kR劁~\u0006\u0013Pq+x똧䒖\u0012P'\bsz\u0007vxJsk9P-)nߙs\"zbMY_S\u000eG\"={\u000bORqFw[\u0016\u0005Qo=(\b[B270U4\b|%mɷ\u0017!ֲ,'FFXC[\u001c;\u001c×;Xk\u000fq<)\u0001CZ}\u0014!.g\u000e{\u000e(ʪa\u0018\u001af\u0011w\"6\u0019MWj,[pD!jRK\u0013\u0012P.kzq*bh7թ?W\u000fID7Rh6_ы,W]\u000f~4v4v\u001f-\f\u0013w'e[O=P!\u0017Zkl0Si #Պ(iO\f\u0007rSȱC0͙OgtQl$.A%\u001fEg[\u0007P\u0001R_Y\u0018\u001b3zyƃMZB;O7=֪`\u0016wq\u0007M\u0018s-/C`e\u000bx\u0015j\u000e\u001a$;hB\t\u0016}\u0003v~AH*=~yؤ)&,۟z]E\u0014Δ\u001b^U˼\u000fwԈ\u0006\u001a=\u001c\u0000P\u0018E`H͉\b\u0007y\u000b\u0014\"\u000fl`7\u0016\u000e\u001fôXy7|\u000597{L_\u000f\u0010s\u0019Ǣe΅P^\u001be\u0001P_y\u000e?e`kJ\u000f\u001e\u0006\u001fegZdl\u000f\\d}KW\u0007ɦL蒂\u0012\f\u0007UTYL\u0018\u0018%N~#X`֮>v4j\u001b\u001aw\\EIH@\u0000gkK]ɬ\r*@aZN;oksRZ}@ H'L\\i<дw\u0016\u0012Y2n{nCM9|\u0017Hl4ݒ\u0007T#r5\n\u00027ylOYP;\u0017kQ\u001fwGjwZ]tp\u0010O3RkÑE?:\u0019\u0005\u0002\fӺt{\rBD\u0000&&]tjV2fQz\r/\u001aJ\u0014)O\u001fh&j&7&*UCs\b>Ί{`\u0003i,Ǆ+o,#\"\f\u000e߹`Ew\u001f&˝\rJA*Gya#⻝\u001fK\u0002>I6\u0014VJ3΀\r~\f\\d\u001540\u0014-wj\\BEaI-溬h\rY:R\u0001\u0019Dg\u0006Y3|g\u001c\u0017Fɽv\u001c@k\u0011\\2*\u001d\u0016\u0001hlD\u0019SX#<\u0018X\n\u0002[EA3ղEVy\u0016z?\u0018+\u0016_>{T\u0017\u000b\f{N'\u0000Imm_2~uśգ\u00040D3lɪvK\u0011EszW`\u001fקÞGy>,E\"<#ޗ,|.N-t+yz\u0013\n\u0015K6U)ӹx\nhUgiZVdҽ0y8a+\u0001?G~F:s-\byN\"Ʃ}\u0007(S\u001b7X\"\u0018巭yobw*΁\u0016e\u0012m;b҃E&R@Ȩś\u0015sҮew`Rta׮Ddoߨܟ0?kt\u0003澧\bJypȾ>O8PS [xs\u0013^<.Zog|dN\r?m6\u001e?\u0014o\u0015V\u0013dӻTپ\rbe\nrC,\u0013ľ\u0010\u0010j\u0007B{_FpT/Q\u001b)IN\u0002\u001e\u0006'm\u0011\u001f%W-*~[P\u0010ΐCkb`\u000b$u\r>2rƆ%N#9\u001fmֹ:2j=1:F/p\u0014s)\u0006Q\u000f\u0007ba'^N\u001f>l\\/k\u0011\u0004[\u000bxBdC\u001drTm\n{葨1<:`#Mʤ\u0000!\u0018'wsx\u001f\u000eN_\u000f\u0019Ua*CMӘ]\u0015e2$%c\u0016\u0016Cl9\u000b=\u0017Ի\u0015UK4\"\u0019l\u0004_W9\nZ\u00136\u0003Ph!=\u0003-!DW?w\u0004\u0001i'!\u001b{\bo\n\u001e?52ar\u0002w*IӖ<d\u001e\u001eC\u000e܌6*\bB|Ghvw-ooV\t+^%:\"3l\u001d\u0000%-E'6'\u0006\u000e\u0005fɼxul\u0015\u0007[Lj:(zF*32\u0019\u0007\u001aB\u001brK\t<\u0016困U}j\u0007Jx\u001arʺJ-5M5tr\u0010t]r_\u0010||Qz(2Ō1GF|e+M\rP]v^>!4\u000b<\u0000\u0001\bS6\u000fp-icYih\u0006 6Ux]l\u0014CJV\t-)^&>Y\t9,'\u001e\u0016/\u001f\u000f\u000f5T={\f4v\"\u001dd\u0005mCſv5o^\u0017\\0Q3\\P><$ʡ\u0012\u0011!2\u000bd&q\u000b\bK!k+\u000eghb\u0001U\u00030JF\u000bx\"jcXa}W\u0016%\\'\u0012;\u001d.\u0012P\u001c\u001eZ\u0000L׋(3\u000f*\u0005#tF\u001dK?Q\u000eKmb,DvMSx\u0011g\u0016TH\feY˛Q\u001f\n@!`0G&\u0003UCǄ\\]{\th__Ey}\bݗR~ʈ~oel\f\u000bTO*\u0014a}ڷ9UsCR`3%\u0017y1՗D3@`HUWߏ:gBV3\u0012\u001f/\bݒ%Haq{Z\u000b?\r5܀>\"\u000e5TM3#7^J\u000e{\u0018hVt+}g6˛voNV/?ڄ6\u0017قؕ:-\u0007'qqr+H\u0014\u0000~NnۅAn)'.,\u0016kT*~Cs^%_KF'%nZ0L:Yέ\u001cO\t@\u0004\u0015pqxA\u0001y)ą[XN\nSiVEN'͘G)s\u001d5`DA4aN\u001cpۈ^b5A\bPհZ4\u000eX\u0013=m8\u0018jm\u0016Y\u0007ӚoVov}>I\f\u0001Pv|\u000f<\n7d7[y\u001e$&qd\f\u000br<7\n\u0006ZBg|RA2b4Pr3i,U.O\nRO\u0017\u0014oFzBuOiz\u000e3\r\t&|\u001bUh_\t\\E4Z31\u0001׾K>Be<XL>xfD):\u0004C\u0019Kj\u0015v\u0000\u001eC8i7%M#D-;V\u001a-K\u001f}htA\u0003\rC /0#?Z.<@gu]`7.X+(Gȩ\u0016|m\u0016\u0012AC<4|hY:2zS㯶`\u001d;\u0013\tixS1~A97jC]\\UC\u001e\u0016=[ccgrGntXp\u000bblywQD\"r\u0013\u0006q\u0006&:/2KG皯i1,Crv8΂|΀\u0000E̎`\u001dŉFN\u0010@)\\B.=PͰ\u0018\u0017T\u001e8d\\\u0000;y\u001d~\u0006%x\u000e6#jXv[w(\u0017\u0006$?ҧyV=\u0005rb>wN{6˩Y!\n)֊lJ55w\u0010}&jR'\u0006bO!\u0018\u001f*`̮\u0014k}]YB\u001b\u001b\u0007\r\u001d*x\u0006[\\xŗb7@\u000eQL\u0004J`$\\hJe|\u000b\";\u0006,2\u0007Zk\u0016\"{3z?~rjRZ\u0017C\u0013N,Sި\u0017?2e˸\u0002ة\u0004Nwa14}Se,v'ܾnr\u0014ӟ5=f\\\u000f\u0001ye\u001ebXmD}\u001fCra\t/!=/F-{G\u0003\u0001\u0003\u0003\u0016\u001d\u000b\u0011Vi\u0019LG{ؚ\u001fk}\u0012_TΝܺ^\u001f5VdqrvtU̿>W[Z\u0018,B£E\u000b[? >\u001fR\u0006PnP\u001b|`wR_\u0017>\u0011ylF2MT\u0007߀{0-Է\u0003ٽ}ȧQ&\u0010#L:ĥ8{CS\u0014\"6vU}_K{q.\u001bu<Vb\\V¢rc~()\"\u0002\u0013<W\bEnOJbUp\u0012'\u0002\u0007X\u001bZ\rEEibS,}\u0012j\u0007u̷\u001e\u000b\u0004jf1$DHV\u001d\rHTV\nam4c\t}g:ϕ]O\n\u0017Gؤ41ٲv\u001d%&sS1\u0002\u000epֶq{븍\u001byۯOks6U\u0013~hVẼE\"5MV\u0004j\\\u0011Ck/O\u0017(1?\"Iz\u0003չ4өgVu3{g4bϰqhP)KҤ&=Ej/_5\u000f\u0010;\u0012\u00142lВ\u0006)aƋ\u001fCXܸQ\u001akN\u001c\u0019_%v\u0005ȷœ\u0010=,\u0017٭\u0010\n;\n!\u0010\u000fkdJ+Ό3\u000b15<֛\u001e2\u0011\u0014\u0011Hɕld\u0018&(A~\u001aᵮ1IOu\\f\u0000\u0015hI/\u0012#v/0 \u0012඗6ج\"\u0007sLq\u001e\u00121Ĳd+.\u000fw\u0019n\b_\u0005Tm3v=%Ҕϖ6b4\n\u0019\u001f\u0018?ʜvʏ!+([}6qFQc&x>3\u0006\u001aZ\u0011YT^\u0019\u0018;D͟?\u000fH:ohR2tywx9,\u0014P\fU<\u001b{1+̓^_[=XUXހP_vf\u0019Q$ی9~.\u0019\u0017ĮX\t,8\u0012)r&\"h\u0017YBSĭl\u0018ۃp,ۗ,'\u0017<{Gvް_S$\u0007=~]4Nԣ>B#r\u001ct\u0005tn\u000bpu{\f\n\u001d|h7\u001edJRPU~-\u0002/=\u0019/\u0002+-N[D.6*V9?R\u0016\n\u0006z95.dj\u0011T)\u001f3.Q\u0002\u0010\u0002)ќ;\u001eA~(V\u0012܈aa8\u0016J'~2[\u000eXM\t#\u001f\fBd\r!~q̘HgFI\u0018=$f\u000e=\u0000K\u0001a\u001b=Kv\u001c=\"\te\u0000?h]l(hF,yۖuL= ˖\u0011)msSDQ{iǹ=BgsHdu̔Kש&cup\u00158qMO\u0012W/M0.?@hwf\u0007\u0006\u000bհ\\\u0003E\u0006ٷs3\u001b[\u0019ͨy?V'g\t-\u0017\u000b\u0001qڲy\u0014\u00186`K'\u0010KGgU/ӿ\tҩkʏm3\u0003[\u001c'O'8=s\r!8j)y\u0011#ϐ\b6EpA5Wwe\n\u000290\\\u000b\b}7\u0005i:\u000efZ\u001a\u0004,+apȺ\u000f\fI[e\u0003왕JZ\u000f%\u001706b4ɗy[܁蘒\"bt\u0013\u0007f<R|\u0014WuY\u0005\r Sj\u0002kzRBcQ}\f\u001b\u0012Ni.܍^ӣ8 [lcsl[4H\u0018E3ƙ0j\\FѨ\fq'-Uɏf5R5\nZ9(5\u0002`\b\u0017Dj\u0003\u000b^\u0004z:kF@`S\u0007\u000f\u0017t;&\u0010j,:-n6H~kA\u001e\u0002&\u000e\u001f7)m7>H/,\u001dY8D\\Ø\u0018A%\u0014e<Ƣ{#v\f|,*ۚ\rѳ6qKѴ0\u0004bhgh\u0000N95YXZ˕/HnvX\u000eq'`k@|\r؇wTd\u0003d\u0015\u0017\u00049>\u001aFa%cp./-]\u001aSҀ]<̕3\u0003VniգW9rȝF8pJ_\u0006_0pJ+\u0015>(2G0'l/Fd=\\\u00058\u000fZQGA\u0002}]\u000f\u0004 ,8u%jǭ@o\u0018Is\u0004\u001d+9C]{5$8\\\u001fw2\u001c˽\u0016\u0010Z GUfL\u0011R7슯.\u0007ԻO\u0015(x\f\u0014\bagZA5Tn\\\u0019%\\yu\u0001ǫt&~\u00009<۶\u0010\u0017ּ\t\rg9W_\u001b*ㄳ!WLævcgJ-}R*ql\"\u0019Bp[*Z~ik^I\nSTޜ\u0000Ě4\"9/*z~\u000e2<3w&i6i\u000b\u0004-U'@ճ\rjq즙oZʸ,xϋmdg95.\u00166j%:T抉\u001fRHˁ>AtGR\u0014^ZGBm-}ZAFGQSDcg\"ĠT\u0018lVX2&B\u0000\u0006=QXp-J\u0017ks~a\\K,\u0014\u0000VejN\n\b\n)\u0003,\u0019Dr\u000bҨ=Ss6m0\u00040\u0019\u0013,:H.0\u0010&n3\u0015h\\\u0018r-sVN:\u0015\u0014\u000fPCK\f\u000e\u001f\u0013\u001ey၉\u0016/,㛂\u0016\r)<\\\u0000I1լ\u0001Xv\u0011/}me\u0004|0ZݙZް3ӟhX\u0014h\u001eS\u0006\"T+eg+\u0000\u0019\u001d.Wl-0g|\u0015\\mS[w~{I;Ƽ*Z`rδ\f<ʈ}E,\u000e^\u0016:!Kj&:*\f#\u0016Vk*3w\u001d\u001c~\u0006_1_\u0000j߯Pkո\\>\u001ae\u000eOO\u001cc}\fSڅj4hV\u0018u*.??NF\u001bݟ_\u0016[o:8Jw\rX\u0017j\u000b֧+˜\u0007S:{M\n\u0010kň|;\u001eq'>\u001f]\u0011 d\u0006Z!\u00160=}K\u0011}w\u0000G}L|S4@7\f\u0003.,Z\u001bRƦ\u0013\u001c=Q©ohYiBvWWa:Tf߲}P\u0007\u0019\u001f{.4\u0015f#w+VbB$\u001e\u0003\u000f7K@\b\u000fPBk8\u00105Hj=3Zd\bOr\u000f￠:<\n4\\ar`yPn\u0010J\u000fC,*`SXYpxQH|]\u00194P_ݤ+J\u000b\u0000klNt0-F((\u0013:`%4C,Ná\u001871Y9MTI\u0014q\u000bs\\T\f5x9ztq^>8-uE\fٲd6OɌNeGxAJI M]W?\f?\f,\u001cG\u000b\t]5*\u0005/OƜ\u001dV Z$yNxd\u001b\u00064\r\u001f֏=8<FIhR}*<^6u`\u0018}YZʕ\u0011`\u0007(?g\u000foP4\u0001:d+6]lmyv~ߞsY[:1\u0010ФsN\u0015']o\rVÇ\bј=r|\u0006M\u000e0\u001d\u0010ղg\u001e\n\u0004E+O&^{Q'\"!;@JZNR:qk\u0000rYl_\u0014ph*~a'Ē\u0013j{\u0012a+\u00055F2'%yyS|Wk\r~\u000fπ$D\u0014\u0010\u0006rۈ.3{+\u0002*\u00155TgV\u0011\u0003_s\t\u001b*Bafz\u0002(\u0019\u0004\u001a/32'p\u0003\u000e9W\u001ej:qW\u0010\u0016\u0006/\u0005S\u00065ri\r\fsU\u001aYyJJ^Po\f\u0001:=I>Қ+IUmhm.\u001d|bz>AqIȚ4,lo\u001e쑬rBǭrxO p\u0007&rnT\u0013k*\u0019u֖J\u0011!\u0006d?Z?\u001b\u00161ǀW\"KZV_hqy(M?\t\u0004NZ:E\fb\u001eי\u000f<&e$\u001a^|\u00019^\u0005qub\r\u001c\u0000t-\u001ahVv>&o3ϳ(^Amw]JԜ|+nKr!h\u0000읅ؙ}\f@0h1>}߉ID\r\tsw)ܸD\nJ.3L|`_=E\rp2ː]5^Qqs\u000e?#\u0016u#d\u001dQW0Z\u0000&~dҨ!9W\u001d_?GL\u001f&4ɟó\u0006\u0011˲\u0016$۹Vk\u0018ԝ{<\t6\nݽf9Ho\\o'b#AH_^\u001b/\\yvm}f\u0019f>ʵF\u0018e\r:*\u0000\fY~/L\r>eKfζ澶d{{\u0011\u000478Y(yY(h\u0015.z+V\u0006\u001fsΩԎK\r/N)K2\u000ea?zږ}Ċ\\Л-4O\u0017r\u0011PQ-.\u0013J3f7+\r\u000bI\u001fC\u0004zTv\u000ee[z0\u0012f9U\u0013T\u0011p&\u0013Y\r\u0006yᴖ\tz\u001f8g\u001aI\u0007q8|ڄ\u0011{avX\\BGu\u001c.n\u000fRGUb/ﮐy>V\n慹,:\u001eo>$\u0000\ndk\u000b\f\tͳ\bxfH\u0018\u000e8Z\u001f%\u0012\fgl]\u000ez4]+= d\b2s\u000e\u001fSr鑓J'\u0007̒i\bx`N\\jZ=PG\u0001l+k\n\u0003˧3\u0014VevWoW7\u001d\u001e\u0010L=!u\u001bռa=1b3S_\u0011\u0007k\u001a7Ik.|^a\tapѵY̘8h2?\u001d~@~bʢ?MhlWՁ_՞iβ>tpX*\u0012Tal,)_Cۗ!)\u0011׼\bJO\u0018p\u0017\u0005t\u0013^Z\u0014}\u001a\u000f.;\u001a\u001b Sz#rU\"\u000b\n\u000bCrP\\\u0010\u0018\f=Ígr~SԀ0y,z7\nd>`Z+,\u001c\u0011S\u001e_18q\u0018?\u0002z]dy|#~VF+KY74%gn2]\u0017-+\u0007\u001bH\u0019\u0019`I\\^\\ۋO\u000bxj\u000e\u0019v)/_3\u0007\u0017AdǔrZ?rD,\u001c\u0004\u0015RCDޖLO\u000f7K6_|\fFkf?@Aم^U\u0014r}n\r9k\u0015\u0006\u0010}4yyd\b`ӿ`ƞ́[㨚Zt\u0015.\u0018h:\u0005季11\nW'di$`\u001bQL塛f\u001c\u0000)n\u001e7[\n֋~38}/)T\u0011a$\u0014$`P[+Ca,l\u0014\u000eu.o5F~!&_m\u000b8\u000bR\u001dlosM6wJ>\u0005\n\u0019\u00173#Vn\u0017&nqdDhz~f\u00051\f\u0004QQ\r%(!׻YFym\u000f\u0000R\b\t,y54x¨rx\u001d\u0019v[caݿ\u0005I\u0004\u0001A\u00003CN~A^R+\"o\\X*ߛz\u0004\u000e{b!\u0017{B/XTY\u0013dq4A&8\u0015RFR<~9a@HWhe3(5V\u0012wt,i\u0010~\u000e>2AI<XRUš\u001fٜƧd|4\u0014BT\u0018O]g0wʼ\u000bl.\u0018;*\u0014-\u0011\u0006i\u0003DvLW\u0013'I\u0012tq\u0006Mǽ>Һg_xo\u0004߻\u0015\b\u0007^\u001c\f\u0015[ɷ\u001a4\b\u0015?kKY`K?\u0010\u0006LH\u0012h@\u0019D\u001c0CY37ݫ//]$dm\u000fK2\u0017W?\u0005\u001fS\u001b+ZĲjT\u000bev(W8^T7%\u0000)\u0000\u0000\u0005\u0004ݩOЌhGIR\u001b\u0017kڞm\t')\u0007\u001euVh[\u001a\u0001ѓ\u001d1\u0005F\u001dOb]\u0007}\u0010qR3\\*^ӗw|\u000b}bxFwn1\u001f@Z#!+KCJ\u0012NaA'1}- :LBfTUhz?pۭ\u001bNWWBezT?LAqp\u0006G,$yy\u0004\"+^D\u0016Ce#\u001bi]b6Rs\u0012=K\\}ܾfZ(\u000fw\u00033fͬ\u001e\u00196u9p+[\u00184K;ڽ\u0005)o_\u001cZ@y\\?2U> ߔS\u0014'jLU\"'\u001bq!5~R6I$f%\u0001|\u000fWBS` Ұ]4hpif'ϡ<ӗ6\u0000\u0014l;מ\u001d3C\t\u000fC\u001bFzŏ+W\u0017t8\u001fpo\bp貜:'|\u001fkum'׫ n3y\u001cNMRQ\u000ft^OxX*?\u0017{§kC)wHO\"\n,ֲ\u0002Ȗ+R]toռ@\u0017\u0000߉3Y\u000e+1m3*M_[j_\u0003hhclQ{F<IpM\u0016\u000ep\"3*`-4\u000b0\u001cfXp\u0019,\u001fI\u001c6*c|_\u0019\u001a\u0015g[\u001aF#v\u0019QY\u0007?oP?9;\u001cu6\u00065MR~M!e \b\\a\f\u001d>\u0018vgmx\u0019N_Er8L&Me'i\u0012JW\u0014\u0005jeNn\u000e=r~\b\u0002<;U#q\twTXn/L5D>#(EPPFR\bi\u0004'\u000bշu\u0019wW6_DDI\u000b(,q4hL:w3qxg\nFT\u001e`\"\u0013/jN6>qtku\n\u0014\u001eB\u0010Ɵa\u0018\u0018t'WO\u0005A8m>\u0013@KM;s\u0016V=ؤ\fd?!\u0003\u001dH\u0010ݶhN\u0012\u001e\u001a\bPĵ|#:S'\r}g\fV}xQv7/-r\u0006+[vݻ\u001a.\u0007\u001a*_\b\u0014\n\u001ao([A\u000fՈ\u0000\u0010jްTݐh\u0018IIsF@kuA\"4s0$QMlZZ82R@e@>:02,k!n \"\u00013\b鿠3=PUWx.F.=e;{\u0014\u0019e=\u0001\u00042Yf4\u00196\bE5\r,kLGsyrt\u0007m\u0015d\u0007[\u0013s\u001duF.xSxǯ\nw\u0002Eً0KK.\u001b>`YLXM1ĪPzyNvQM(V\u000eKs_<k@j\u001cx7<\u0019J\r\u0001fu\u001cɊO`KwLS\u0002WӈC\b/\u000e|KP\u00179'\u000e05Gz[F_\u001aF\\6uzh\u0012YG`Kn7V-\u001fN\u0011Z\ri]i\u0001\u0016ݍۮ\u000477#vOIТrp\u0000}.Z\r&^/(^.:\u0003rEG+Gו\u0018m=ۣj\u0003m^\rΟ\u00037^{5=׭Z\u0007nxT4\u00192T\u0012/J~\n*kswΒ:P\u0006@0{mk=<~֎Y\u0016RF}a9ܫsko\u0004A\u001bJm\u000b\u0006{\u0004=i\r\u0016A\u0014%%\u00012\"˝&Qw\u0012[9*tUiu6/?ЙU\u001cQ\u0006\u0001\u0016\u000e5Y6ti\u001b9a\u001bLzPYbv\u000f\u0018 s\\cx\u0005ב,?qXƋc4rW}N\u0001M\u001b1I2#\"\u001es|8y<?\u0004_]z;\\[-b@%K\u0006\u001dJ[Ql*uε&f#=Xz@+Śȡ)sԪr^mwf㻽&W\u0011˅\u0017v-(z\bl(FO>/\u0011Ԧa=\"umƛue\u001dWRg\u0004<I(pUob*[R:ߖ\f\u0014Dv?;i\u0017U\bg\u0018\u0015:3Nr`$ԧ\u0007GF\u0010\u0010\u001a\u000eRpu#\u001b\u0015H\u0014ZD3~_jzhrD\u001d_5}}׺=s\u0014!lBZ\t[.囎\u0003?%YpKů|\u0003PZJK&\u0015gT5#R\ruA\u0010zZ\u0015ab--/\u001fjYV-~O?ی!#)Q\u0003_GXs)A۝a4Ā+\u001e\u000eL4YR3ьJ\u001fs\"\u001dO5ށvsXkm<IϒTM|\u001dh8EԞA\u0013AإwKz<\u000fc\r|2eH\u0010е@\u000eW\u0005\t\u0015ΛM/wK\u001bB[fT'sVƢ\u0016'\u0000\u000e;abu<8Ȣgy/#\n\u0003sc343\u0013)/(5_Aݥg\u0013&KL/N3-\u0012ie^JG\u001eyi97zublaZHWFםdbh=튝=\u0003\u000fVȊ\u001c!|V\u0017\u0007E\u0003⭴\u001d}9c\u001e\u0006L\u0006m(}.NM\"ru,6wEc7W.>qT\u001cQ~v\u0010UngT;>\u0010FI\u00058|\u0014W.?\u0001Vv/.\u001an$+;R\u001aSr.j;v}\u001cۦ\u0001GS;飷8S+KS6\u0002\u0005y\u00166\u0014/Ƌw-|TXþ\u0019''GcaӁa\u00123A1׫j\"܏=\u0007o~K/b\u000foB9\u0019l,O1?M{gK_A]/9>J\u001d\u0019-1\fO~cPھ2!\n=\u0005\b\u0016*X\n\u0000\rXQDӂ6\u0003\u0001)8,C\u0007YV\u0014~yLkGµ\"C|Ar^u\b\u0019\u0014\t'Ñ߻F'yd|\u001f\u0018Hp\u000f\u0005CUD9!{\u0007ypβ1\\S)IeG%O_d\tG\u000eΓ$\u0003{\u001cm5]\u00059>>\u0003FtZlr\t2Se)OmxI\f7m\u00169\u0007SeSYӦ\u0012~exYA7i4#vo\u0019<ƛ/&է˅A=(^WtH|Ή\u000e\\DJ\"U^_\u001c?kY\u000eQ\u0012-  \u0014*f\u0006YC_QνPѮSH\r0:J\\/I\u0015\fO`#6Q|z<\u0012\u0010oGA^ DHkQ\u0013\u000bG\u001dC-0\u000f՛``:S쀞LAf\u001fJ##jfEٵ-!cw\tnUܛwgW-k$J0E\u0006з{ɇi9\f\u001b5R\u0011<Q`\u001f/\u0014ep٫\u000b\u0018\\f\\D\u000f\u001eZ9#}V穘Bbb®]b/\u000fqկhgUT.C:;\u0015\u0005}d\b]y-~PnrhY&P~\u001d*h-;M\u0003\u0006\u0016>\n|gt~\u001d;\f\u0013]W1K6Q2\f%a2\u0011DB0VϵTC\u0011ߖ5cwo\rendstream\rendobj\r50 0 obj\r<</Length 65536>>stream\r\nr~{m\b\u0007i\u0002S]\u0005\u001b|[ރSǭɲ^cд;z\u000e9\rXa\u0012\t\\cmU<Z5od=E@c\u0000\u0014YL\u0011\r\u0019U\u000e!\u0012Kz]`iK%'W U۬s,r\u0007\u0002P~el|*#@҈].A4\u001ef-]t\u0000qZ\u0018H%/0t{\u0001&p\b#l?A.$[\u0013c\u0015\u0004O3үO@\u00116x)֒ӯI 9M*̌\t\u00025Y8\t+^ʟ\"D}5]Y#ٔ\u000b\\+9\u0004rj\u0014\u001f5kX\u001cu98\u0006[\u001a^\rk\u001a\\+CY\re{\u001ent\u001f}{\u001dUUJފLih\"_2\u0019%U9q꘮S}\u001e5ɨv%#LP]\u000b\u0007HǮ1\u000bMO`Bw?@\u000f\u0017Mq\u001b/KZfܖ9$+nMoTu\u001e^\nO\u001fTDF\u001bej\n\bT^\u000f.jȎ\u0014fk͘'\u001f4pP\u0019EV\u0004&8\u0013Ex$|29O]4>pu-$3ں|\u001fb{)!Io\u0000#AUnB\fBN+ul<;xaou\tw:qR\"jq\u0016V'\u0003y4KF~<v>N3&ԛ\u001e\u001d5i)z\u0015.0QD\u0004\u0013QD\b9#E+)\u0011sf\bu\u0012\"PW~ˁ\rfu@v<\u001f'Wusi,6w{\u001aKX\\*sjCk\u000e58\u0001\u0005kb$\u000bYs'K-m<\u001bcQꒆR&<7q|ky MU\u000e_ \u0014\u001e?\u001eR^\u000eIkȷ|΁\u000f\te\u000fRvU;\u0017\u001e30@*l\t[ϙwZƬkt\u001e@s͍.%\rf{UywsGeA\u001dg`7\\&l}(լU3c4\u0013&z3x\u000bCO%T\u00108O2\u001eʷ41R$Gv۔Z\u0017!ՏQ\u000fy=n\u00179R\bZ\u001bޝD]})!A\u001c\u001d%\u00188þ7M+\u0014ܰs\u0004\u0017 )T[{ht >\u001b\u0001l=1]yZ[N]C&S2*\u0003\u0019p/_\u0001D=,V%YA8c[g\u001b\n[۳w^|\u0007MG!9Ś&Ѫ\b8o\u0014P):(@?\u0013-^\u0014MoI\u000f\u0006=|.5M-D\u0001hOl\u0000\fTX_seDwW\u000e\t>{uE\u001e%Ɨ\u001e\u0018<\u0007F\t\u0002t\u001ag\u0013\u000eBU'guc\u001fEe-^15QLݑ#\u000fH\u0017jL\u0002c\u0016\f<(2^Iw~ؘ*\u0013oӞ\rWɀO.h^،u\u000eSy\f\u0011O<QqY\u0013\rPw\u00068uRkҤ\u0006.~a\u001d<TA$~qEZ,\u0017N56\nf\u0013^?hSl\u001axey\u001e\u0000Q7Xl_[j,IA\u0014%ē\rP?ҧ5\u0012txvU*_T$\u001f>\u0000-X\"ǑY\u001f`Oy\u0014~~j\u001crE@^/t\u0002fpryRZ+v\u001a={\u001fW=Vj(nb,o¿%;\u0005R]_aR?K\nD#cC\u0012kb|NW\u000b\u001dbrܣ?L\"0j8\u001dk\nG|*ǹN\u001b\u0005\\\u0006Ll}}p\u00152u2gim\u0007k-q36^J\u001d\u000f\u001c7Pp\u0011;i0Qg~w\u0019\"l3\u000fZbL̷;x\r+΅\u0017ҿ5n]`\u001b}Uռm\u0000,\u0012/\u000bl?\u0015.n\u0014k\u0000\u00004]\u0005\u000f0\u0014\u0007aW\u001eXw= \u0000E\u000e\u001dy\u0001wAՍŷ\u0019\u001bSou\u0014\r9_c\u001ba\u0016\u001e׍\\ &#O\u0019\u0010\u0018`\u000f\u001bK6>|&Aq}~,:9PTy=C'BTAT\u000fY\u000bW5\u0001#6\u0003\u0002ϨlȢ\u001fsG>z\u001f(k}E7>p\u0017eّ%\"aH\u000e@X:4oG򵇔EIƼ߯W\b\u0019(\u001cLxK_tǾ(.WOi9Z;hQz\u0005+MxQso\u001a,˹+:[\u0019f\u0002l!\u000bwz?ڲ\u0017\u0010\u001c\u0016ݥz\r\r)C-6ge\u0000q@Q:p]\u0007\u0017[y֜p\u0019\u001bd\"w/r#5\u0013'=m4\\\u000f6+G\u0003:{]}\u0013r\u001c\u000b3T3\u001cvK,ˆlUh^kRfe\u0014|V\u0000/,)8]>\u001f\\MQR]o$\r\u001aބaG\u001amUNê9\u0010j\flL!ʃ~\u0016[c|\u0017ښ}r\u0018Qc08dz~s0yV2\u0011Y>(ho+*:َ>\u0018(u\u000fI\u0013Mamj\u00175}b!`mjt5-\b\u001eR;=Ċ\u00033gr{\u000b\u0003\u0016?3{2{\u000f\u0016A\tۣ;k\u0015_1A\u0002j\u001ahɪ-n\u0016*,}t~Rz#nV\b\u0007\rib+\"\u001c俿Ap\b.՚8uSi\u0013O7\u001b\u0005\ng\u0016\u0018\\dpT!fqIUiXz/c\u001d9WL\u001e]1[RoTo5\tWU? L527Se^xӕhu\tv\u0015\u0018\u00113\u0001l\u001cxe]\\f\u001d-\u001d\u001fp|\u0002Ə*/\n5$*Pu\u001c:k}ܢR9V%d1v\u0017\"݀p\u001e7Wo\u0019I;\rFIKXV\nnj䫳T`&w\u0013<a6\u0006{y#\u0018ó`=\u0016\f\u0006&\u000fᵇ[eȥ+ƣY\u001e-k\"9q\u0016l\u0011\u0011l8.\u0002/\u0015lֽ\u0012\rt9x\tad1\u0007iswΣ\u001bSg\u000371pk}֨֜\rK\u000er\u0015C\u0018Fc$uO\"\\\u000fEV\u0005&\f$ܗg*MO^LڧI\u0007\rZܚͱ\u001ejʂ\u001c7DR%?j\u001b(u\\u$LeK%\u000eq\ry}ܐ\u0017\u0000tF\u001c}2\u0014#\u001e^|\u001d;\u0016\u0002\n懶7\u001fJ\u0014\\\f_R\u001dEΊ]2@Zl\r%6\u0017;ϔ?`́yb^7lHcQ? {\u00073;@_1԰g\u0013'Y\u000ejB{\u001cz\t7%ΰj\u0005\u0015d'<\u000b6k81\u0016*_59g?6x+\u001c\b˸jc^IC(G˙\u000fkX>\u0007q\u0016.M<J%qM\u00062pE\u0018̻\u000f[l+\u0017RS~]/\u0003%>#a\u0018rY\\\u000bc-RN\\\u001fu:|hKp\u0006\u0012*`B:h?@!eBG'D؇J\u001a1sZg\u0004Z;wn|WO+\t=1\u0002\t`/>y i<Z!\u0005ۡcGA\u0005{\u0003\u0014l>\u0013d\b!˿5\n饨9\u00167\"\u001f\u000euV\u001fq[r4fal\u0003)X&~d玼Ww\u0017u HVĎAHIr\nd[IJ~2\nYMٯfoZgo1\u000e\u001a1>rqʴ~\u001aTdٍj\u001f8g#\u0013\u0006M`(\u001a;-\u0018\u0003aS\b̜a3鳛\tέ\flZ?Jws;\u000f,H\u0016M\u0010$W6\nʝ}q܉AA\u0019\u0010O}^\u0019.MJ\u001e\u000fr\u001f\u001a6PG%#]q\r\u0001\u000f_@϶V\u000eJu$6:%\u0015$a%瘯-(K_;Oܬ\tzI\u000f\u001c|W`,<\u0007\u0012Ƿ?QsӰs\\%E:k4Rk!U$\u000fx$¤9\u00181\u0019j\u001e˚JНmeÄ;\u0012DpEޟez\u00174\u001c\u0010ۭ\u0011۪8Ӕ\u0004\b1wR[\u0013+P/P\u001c#jepU{\u000e|9ᑨl>\u0001:G+j>GRph\u0004'j\u001c\u0006[O7Z\u0011(]@\u0002W)ݱ\u0018˜!\u0006h:\u0017k\u0002\u0017uyB,`X\u0013ZmE:ktKq&Vr\u0013\u000b֜\u001b50\u0007\u000f\r1/Z\fp5muV\u001b_亞R>~\n=ss-ĮAyBޖ;>j7RdG\u0006س/UT\u0015ZJQ\u0014\u0003\u0005fz\n~r\u0017/S\njmW'n\u00054U(2\u0013fG(\u001cJ7S/t0WK\u000f9\u001d=+tz\u0018JQ¬o&Y\f89\u001ft\u0004\u0018\nV׷E\u0018N\u001be\u0001/CÈ7T\rM\u0013կڀhiVTC],\u001b\u00064Tt\n<pf-G0R\u0015I3\"<}>tv1fb!כ&Yw6UqZ^,\u000e@\\1**|:ܔ#\u000f\f[\u0015\u0013%n.MQYAf\u0005ð;8_S\u0014\u001fc\u0017[ \u0001\u0011,\u0011,l=Sq/TTnYO]3\tqFܟ`ṱ1sELHdױV'%\u0001Ezv\u0015WNv\n5okF\u0006GןWr\"\u00122+d҆A)cU9^STiD\u0000}I\u000e?\u000eoj\u0012շ\u0003Գo@\\z\u0016h\u000fkϕG=^:_TC2\u0002BV|\u001b\tI\u0006tO\u0014Fl\u0003]@ѵ/\u000b5oH\u0013zw#\u0015dǊGS#ZL8W\u001b\f4YgW[u(ߴ{JP\u0014\u001byFUXW\u000bmx\u0019JU\"\u0014/;X,8w4ӺZ\u0004Td8FC\u0013ũ#;L\u0004a\t^\u0014v\u0003L/ρodС(E_2c$\u0000ʓ8ғNn(U\u0005,xwX%\u0017v6<ۍeYXߧFVe\u001e6?++\u001bdtfǉv\u0012\u001d\u001f)\u0019a\u000bdHy\u0000\u0018a0\u0000S`وVYr\u0018GKu+AI\u0016\u0007qf~y\u001e_pԐCN'^\u0010\u0018\u001br*cv4AHYG\u001bB]\u0007\u0007'\u0011(>AvQ宼\f۳,\u0014\ny1LSy\u001fC\nF\u0007o\u001fﮗ7x?&:hw牡-\u0018UΜrz\u0007V\u0003=Z\u0019\f\u0017UĪVE\u0006\u001c%L䝋}W\u001bUy7\u0007E\"CMaL絩P#-\u0000e-N/ܛYJe|b֐p\u00110֥U-kxSv<=E\u001cFUg\"U\u001d\b/\u0005jg86\u0016lao@7T\":mF\u001f\u001f{\u000f[\u00030=7ֆJr:\"'R ;Et$\u0002\u0014!wۜ\u0018quJ\u0017yX-\u0003\\#Ql6~5@!\u0000e\u0018W\u0007xi\u000f͹<)S\u0018Rkf5vCO\u0002<4y_/p3qnGzX\u0015xx-dn޺Zogn iKе\u0019\u00038JǠr9t?\nd?\u0007\u0017K=ފd!\u00166X\u0004I Ԫ`udlJZ\rM#cLxOLk]\u001fqr7~jt\u0010\u0015\u001cgp<ʽώ6##\u0003\b~{Jzա\f岮,$@-,f\u0007-sUp~\u0002bHv#vR\u0005jC\rl\u0013\u001daRC\u0014VLTu\u0004to@|.\u001eTVtcv}euV&t\u001d\u001bv}a\"omB0Oن+rUa\u001bOa\\~\u0014s\\og\u0006,I[MjQc\u001b\u0019S8X}I\tgLg\u0004o\t@=}|1|8:\u000bVZΫױ'vSz~z@Z\fp)QLZT$;\u0001ّ#Yd[̛dIϪݧ\u000eڡTT*BP\u000bB2װJc@A\u0000W֩Ggq^~_\fS\u0003=&9F:)_\u001d~x8?Zoxg5I\u001bk\u0014\u0006ws\u001dc\u0013γ\u001aI\rB\u0017vC_\u0013\fq>K\u001c\u001c\u0010_!\u0018\u000f,\u001bx񘿬z۟\u001dBH7&\u000b\u0006Q6&oFդ\u0012=Q\u001akk诇ͬD\u00159|Z\u0014ZI/ׯ,\u0016c{bOdK̓uCvTZbtẕШNj\u0012'z\u0011P=(5.\u0004\\y\u0013)\u001clݞւw\u001e64.2ʡՃuMMݮI\t\u000eG{XՎe<İ\u001b(\u0002\u0013\t]5.d8LF5v0˹\u0001\u0016\u001avκiH_\u0006\u0007x?eznVeS<L9^u,b\u000bn]W\u0006\r_z\u0018f\u0003u}o>f51\u000e~\u000f&\u0002խ*vf-yhvEZǢ\u001a'N%=)\r?5݁\u0003凶90\u001d5df\u0003N0ly\\B\u0018\u0017볥.i`unDgtQq\r\u0017\u000f*VŖkho\b\u00110`O\u0010@\u000b\u0017T8\u0018uWE\u0015\r\fVp-|dײ//\u001cs_d\\῜ëIYoG0\"'0u(\rE;_$Ҿc\u001ev<Z ;!)Kb\n\u0002i5\u0007\u000b7f9ƠՅcc4qF<+Gcii݃궎Q\u001eƿvV4M\u0015\u0011}\u0004+.r֩F_\u0014\u001fn)LѱWlڜǈc*\u0000*P3LݖZ\t2\u0007ml'\u0001ۇdG\u000br\u000e;pN\n)U\u001a[5xŽe⦊\u000eCu6֛ysS]\u001cMF||\u001cY\u0006GR(͝r[9u\u001bah\u0011\r>\u001b\u0000\b:>J8\n~dX-\r\u000e\t&ǋK\u001fa9;k\u000f4p\u0012oAt\u0001)\u000ek\rc\u001ek޲XE.ʳW\u000e\f`,\u001dC\u0019N>v2|M\u0010ϙA=\u0006FH\u0005YrK K7|=h$\u00078ǿDX[\n6R\u001f`8/I*\u001fd&jZ\tjOE\u0013\u001dO(@\u000f~AM\fP!\tQ*\u0003mAeNǳ}ۻG* W\u0013n?`8!\\mve1\u001bT6JQs(\u0011b8t*zwe\u0010-5.Y}<)\u0012\\\u001cEғh\fJߒGNuwo\u0006i\u0018֖n*l\u001f?N!Ө\u0017Y\r\u001a\n:QR<,Q1.7\n\u001cd,\u000fɀ/i\u0017\u00172\u001fykğ{}F\u0018\u001eJ`\u001c&:]M?QQm6\u0016N0\u001fL\u0017\tG7^n}b\u0016}Hxѓ\u001dG:8#;\u0016\u001fE\u001d\u000eږfdJ\u001e\\\u0002н}29\u001dԄuȞni\u0018]\u000eMWk1]\u001cOeR;o8}ڷ=e\u0015\n*\u0000\"?Dګ@M'Vu|}CF\tַ:!\u001e>\u001dkUshܴs\u000fS\u00156$G'|\u0016\\`7J4qwLΈeZI\f73En֒o$t\u0003-Xj!\bE<\u0010W-i?&\u001a\u001bCn\u0016PZtOIN0{Ql>Џ2#!B\u0007(0R\u0013<W\u001aEe\tUj(\u0012W(b:y/fl|\u0018OY\u001368Yl\u00027\u0004Ѽܺ\u001aZ*\u0015/\u001e\u0005qW\u000e'($\f`\u001em\u0002pw~~3Z\u001a\u001a\u0015h9LFj\u0014ºe\u0018V\u000f}c\fB}:{-lNl};)\\\u0015R>};Zj.fYyujfɢ#\u0001\u001c+[ ^\u001bU#\u0005.{7r\u0019hza$|&mW\u0015y4\u001an5gĤ|Jh5\u000b6G}9;\u001dF\bH\rCLeGT\u001eO\u0007\u001en\\K'\u001fZ6u\u001e>Zg@\bV/ܐlbw\u0003/ay%+\u001a.Eiv+Gޑ.Y<`ΧH/<=.\u0016uՍp\u001cۍeNfSWi)\\\u0004\u0004T+CI\u0017/\u0005}\t\u0019ޒQae~K+mKOI]YJ-\u0013^.2ꋿ\u000bMz9&\u0007\u001dEIk\t-\u0010Ř$wh=m-S\"^,\u0019*>~p]]q_94\u001b\u001a=LpQk 7J\u0007\u0015\u000b#(\u000ewLR&6*~%5\u000bP*28;/hq!\u0001]P\u0018_nWg8Tۓ*ҫ?~S|`\"\u000f\u0011N\f5\u0000\u001aFw16(;;S?!!5_\u0018Rf\\tKҒ-8l=_`%#s^\u0013:\"Ĥ?`\b]Jw&\u0006\"#Cԉe+\r\u0016\u0010%er`\rA_:\u0013AwEؕ띿\u001dl\\E,\u000btS<w&\n7[UիPQ}nX%7TLo \u000bV)\u001bOF#q\u0011=M<]\u0003q:\u001fC\u0019\u0011B$y.lՑ\u001eIg~|\rʕit&\u0014<>M@QIʎ[tM\u0010\u0017yqAB=#XXg'ZoĎ=7ZU!\"k2g3DL?\u001d|)˥GIHk\u00032x\u0015\u0001:Gk^\u00144w\u0001\u0011{QK@cy)\r\\\u000e2٘mp9|\rm$k\u00062f\nûx\n\rh\u0016r+\n'wg\u00062\u001d3褲җE+2\u0015)V\u0005ЦEJ=a\u001b!1dT0nr\u00005~eCd򩾙2\u0003vAr/\u0010ҭBiAN[\u001e\u00054w>?$\u000f\u0011-yZirF\u001c\u00139FtCą\f4~h6Z֕ƬB\u0018_՟9|zX\u0004x-\u0016\u0007#ߖ\\\u0005d\u001ac(ӕ'=Z\u0003)VhM\u0004ʓO+#ÊT%\u0015i3\u001d{t\rKPHzMa\u0005A\u0015]բoW)\u0006S{ۿNRLc\u001feB|Gr\tH)\u0016Ȭ2^\u0015\u001bn\\A޷J\u00198\u0019\u001fU+0F]N\t\\\u001fSr\u0013\\Teu<)NPVxШ\u0016&\u001bjDǖBP&f[!?j\\#'\t(r}\u001d\u0000\u0003i\u0017\u0010w0ՏQ\u0016OE:}suѮ;Bd\u000e\u0000.KB\\Vfc@-W<ƥPz/K16m:f]1쪫\nc\u0006_t(0Ԟ󾴜ݼe_\u0006\u001f\u001c\bSP鏨.i\u001c(\u0013\r|ShlckOmqފ:D\u0002`=ܕ\u000eooKhx$\u0017K\t<NIm]\u0000ћ=Z)͜3\u0012Ze]\u000b\u001ea\u0004cew\u001eׇ\u0018\u0003\u000e_(\b\"gݭ5\u0019T{r4VcW d,i窖Ì#\u00122d;\n_\u001e*108I׫foQ\u001b%l\u001c&w~*vn˜&0\u001b=\u0017YIX^}-{\u0007zB{;\u0018't(\u000fz`L^B\u001a\u001a<}01Q\t\u001f\\\u001fH[\u0012L!K`ѪUB\u0011aQ\b߿?4g]\u0001xùDR1>m\u0003sS;\u0018'Zhvm7#5鄟\\T\u0006\u001drCPn\u0006K\u001d\u0018\u0006\u0001`\u0011ұd\u000fTuSV5{Ѱ\"\u001d%ѹ|\u001f_SLjFzܿ&}r$Z\u0013,\u0018n\u0007{GNtjZL5l,<XE\n\fcX\u0006+\u0012ayO\u000e!Xit݈\u0012$ݦv|;zxG\rP}D:\u001e\u001dbuuVtUp,Ye\u0005=U\u001asG\u0017si\u0011$.h\r*\bj,M2xe\u0018jCƜ9`ͫ?~_%Q\u0019hu5s{X\u0005,\n\u001av\u0010\u0000o=m\n|zW}\u00193ک=K\u0002z\n_5\u0011R;ֽ* 뷊+xϛvJs\u0003!eX\u0007\u000eOݹoox,&\u000b\u000fB=nSz:ZCy\n\u0004Qx\u0005w\u0011\u0006L\"\u0001A49siyfNU_\u0018X7iRK\u000f~~A5\u001c-Y;AR\u001bht\u001d.6YY:\u0015\u001fI\u001bw\u001c\u0019bG\n^+#):*gw\u0004&jާ\t\u0007N̈\\.U\u001b\t6kPʚМ\u000f\t6mkPjz^v\t\u0019q\u0004tTj~]\u000fV>5k\u0016a6vwf\u0010&\u0001H-Wu{npK~dqXb|9jK\b2aV\u001f\t\u001c筪oza\u0001\f>!An7KOl\u0006bi\u001b&s+W\fzs\u0011+z.Tx:C2\u001b<{Iep:\u0004NXfR^|n(Z݌\\=\r\u0012\u000f\u0013\u0018<M\u0001_\u0003[!\u0013\u0017w<ߧ0\u000f6O&G\u0012{L\u0017\u001c{x#`\bVָWcht\u0006#\u0017jR\bڬ\u0018x\u0014zظV $^\bYBb\u0017[͌,m)\u0002\u0013Fq.3;BK\u0016\u0007$\u0014`N\u0002@?+&\u0016҂.j\u001cn\"W-3\"oڼ6۞[g wtC\u001fX\"#\nejcKr\nRcX:Lk8>\\Y˂c%>H9؆]G3*e\u0000!LZb,x\\blCH\u0019ՙDw/g\u00122\u0015ON\"\u0016DX9VؗoIيѹsd)\u0019\u001eduB\u000681yt\u0017Ԍ\u0017bFđWI3\u0005<\u001f0\rL܊tB^aé\u001a,޶\\[=\u00060Éy6]fM%f,z=\b\u0015ij\u0016ut/\u0007be\u0016rc\u001bXl\u001d'R4\r{T3\u0017+=vhw'},E͑*o\u001fh/%\u000510o\u0019=᜞$#[m\\\u0011\u001ejU&ě}7P}l/ئ%}5ô]w\u001b\u001dm2\u0010kS\u0016<r\u0010C40KC@BU\u001fλVaյSn\u0017υ\"\u000eT\u00059ZX\nUG'\u001fA\u001fg\u0005I>Nm)Vt\u000f͚c9Q3\b+545wj^@mÔCv\u0001Ω0TS{)e ,ט\u0007\rw!.ګf\u001dҵa\u000b*ۀ\u0006b\"\u001fP=۩\u001c+q@\u0016F:<[M\u001acNYh0Za\fvΫ\t5\u00015\n4Qa{n\u001e΂n|\u001f\u000f冣l$\f*$2l\r\u0000@7kcuE\u001a\u000bĳCU/D\u00001\u001fZaI{Z\re0`<cY`㞦r\u001d⎬՝#/#6>1h\r0E\u000fS\u001eZ;Zsç1m?#\u0013]\u001dj|\u0013aBMtR|/ub>ܒC7ZY1̛ԧ?x\u0016c3`߹\u0001AB\u0002^1>F[q3IX\u000e𵦵/\u0005i:XZQv\u001eU]4Ţ=T6gBA\u0014_So;4^Fmw4wfr*\u0019Txlo\u001c4xU&VLU?6kP/\u001c߯zL+B䶠w_onVkأ v\u0017~Tп\u001eW+}]\u0017iD\b\\X\u000bmCwx\u00156\u000f>ć\u0017!Uogbx\u0015ɣ\u0018c/\u0017g3\u0018\u0003,mӭ1T\\\u0005`ӽ\u0015ޙ[VnȓD\u00027\nulOrݣ~B޶s&5\u000f\u0015S\tM5\u0017\tiL=ݜ\u0000+Icipd7E\u0019vVEQR*i*ܘ}𬫕_Hq%]e\u0011mm^,&8\u001e\ttrN7\u001eWzo@䧛捣\u000b\u001eNV0ar1nx_.냛=Ȩ?wX\u0004C7x\u0011\u0017 M}U./5P_n> W\u000fj\\\u0019\u001fК,pt+\u001bW\u001eL|b9@Pm>Ov.h\t1#)Яf\u001cM\u000ft$Uþ$\u0001+\u0012;\u001bVD/Չ\u000bzӣ7\u001b砪A\"v`ia\u001e왅݈O\u001djShf\u001d#?ԗK{\u000b6k/n\u0004\u001cؼJ\u000fژ\u000f\u0014\u00051~ګ\f/T:)\tW77%d^\u000eꙁ૟JβjeǴBxO7h\u0004\t\u0014UPv[-5R\u0012\u001a\u0005:]6w8<\u0011ѻ\u0004Vk~h\u001a`%\u0007}fحh>fUu=;j\u0004JL\u0002?t-6Q$Gg5,M\u0018+$4[-ݥ?S\u000eeKX\u0000\u0013qNhS;+y7S078\rbM\u001b2+cֽ)uI竺OU/Zm*VhK(פ7ҩ]YsQpΕi.&ҙܛ|i\u0018}\u0012\u000fs~b\u0018UY\u000fm\u0005.LI{yY\u001cjv\u0017\u0006v1(\u0005^Z\u001bә\"x/\u0002SU08\u000eD|~\u0007\b}F\u0002>㫀`{\u001c\u0014O4V^T\u0012>m8Gh2a5ʰ{T\u0004\u0016YkK\r\u000e\\q)}ΐq[\u0017mqhvLJ~z!fNI\u001fn{\u0016+\u000e-]\b\u0019QzI$xF\u001a̤\u001bӘK\r׷C\u001avW\u001e|OE%zp1\u001ctj\t/e h,c5X}.\n\u000f\\x\u0014cJV\u001e~<v\u0015\u0014\u0013kN2ǰ\u00155n5\npo=0\u0011\u0018\u0010*P\rzYU<x﷧aCu\u00147ǅflNRd\rrZk\u000fdȬ{Y\u0007{n\rhh!klV6{;D3=V\u001akUfg,ÿSI6P2\u0019>V]-v%Vh\u000bSWS]xZ駤3\bfVs:J^(\\\u001b\u001e?$\n\u0003;Ӎ\u001cƤ7M\u000f{d\u001akNV#\u0016cuOiרI{XP\u0011\u000e!Q3\u001dX\u001c\u000ft&\u001dlGK5_+ՠE=X[\u0007A)sꑮY\u001bӡmm\u0005\u0018r.ٓJ\u000b,m\nα\u0005q>c`\u000fݻ`INYgBje\u001a5>\nК{~99\u001b\u0003\t:X0Y\u0010ɛ\u0011\tV,R\u0001{woƜA5\u000e_JpPP78\u001fe\u001b߇\u0003=L;\u0005 Q-e\u000e\u001c_}p\u0014z;ko\u0007|\u0007u\u0010ַM\u0014XG\u0015\u0006L>\u0014-[\u001dJւ\u0002RnF\u0001ꅷ7\u000bus8ڻ}9-\u0002vu|\u0013\u0011э+=J[oGDNL\u0001tgnPܸxAJ5\u000e/['=$#\u001f9,gN(¸/th\u0012zM} 6Y\u001edRa\u0014,J?C?\u0012@M\u0011ʦ_ٛ\u0013:d\u000e4e\u001e&Zo\u001d{Ab\u0002L\u00040>VVClt5]P\u0003B0̰֚\n;3\u0019\u000f#n\u0005\"\u0012\u0004J7LaXej\u0010z\u0005ve/ILJ'w\u0001\u0002Ŝ(Dr\u0010毛f]T!8}\u0015c*0V\u0019g#\u0014\u0014~\u001d؃n\r*Gsnn\\oQ5Lc\u0001{\u0018E+i\u0005?[s0ok\u001b\u001dv@\u0018\u001e[mk06mkv.B\u001972եKN5\r\u001exX/ʈk\u001c?\u001dcR\\ZB\req[\\3De|މ#J8Θ\u0014b\u000fbKGWid Ej60\u0006SM V{$Å\u000bw2?-_kq\u0017[,/k\u0002X\u0006s\u001c#)7QS\nU>D6K\u0018\u001f\u0012t90N_9\n\rVي<i\u0007;\u0019ȱW\u0016a8\t\u0014ԅAdh㘺p]G\u001dm+9zSwy+\u0012b=kj۴\u0001#S%c@7jwnER\u001eQGu\u001eуΓ\f͚H҅R\u001a;+O-Wb:-:QU03𝃞Bt2n^3o[%\\^\u0005\u0016(\u000e5\u0001MI֩\u0002/)\u0010~Ӱ=(qϻ=΁񸾏|֬\bT/Qn-Nub\u001d\\\u0005/~bbn\u0015pZ\u001dim-iϚ\b\u001b|\u0015YIe\u0003\u0012\u0019VA05\fwR\u001b\u00181{\u0017\u0019\t{\u0002<:]]DӞF\u0014\u0017O\u0012\u0011Q&\u001e\u0016P\u001f^Śtu)\u000b̛\u000fĞ8JK_.Mw\"]+ \u0011qidִ\u001a|_%5~͙l\u0004=ziށk=~n;$\u001a#ńj>4FV\u0011\u001eEEA<\u0007-X\u0005f6ټ=+:\u0013Y7ԝ{2\u0013d\u001f~T\u001aV.qe̘\r\u0018S̲w1!s^jp|MOP-\u0004\u0013O-R{Ɠl*\u0019R\u0011UL8s֝APЂV+j,X\u00079c\u000b@w#%s'+SQ\u0007zdE\u0006A-W6Ac\u000bs`>\u0015^n\u000e`vC]xOd&\u0004.Znhk\u0018ݏ^:\u001cySh=gj\u0016vOzs̬~Z~x\rVql&);Ϝ\fZOKZ7RKL\r67{ѭfwqz\u0013-\u0018\u0017ծ{\u001blI++\u0010>\u0001cq{F@N4#n\u001b\u000fՖѧ;S8)m~dk\u0012~BZ\r\u0017+%f\u0012],\u0007{@9\u0015l\u001c\u0014ڹ떈\u001ag3)`\nq\u000b{[#Owoi.2J=iS.}{/\u001cYz `=~_@\u0015\"\\4+vl)-9O%\u0017y)$.-s;үusࠢ1t\u0016իq.Dmw)\u0019s;\u001bE۬.J\u0012?\u001e%KݽNcםy.\tڧumA\u0016U-+syG3&>\u00198º\"\f\u001fwzs󪾰S~S0vfXMYOJ\u0006S!+j'_(NLa~Š\\\u0006\r5SG#Opŀbo\u0005\u0018\u001fh3zOyO]d>B!FpNzswtY!lIG[*\u0019)%ofW4[\u000bRʥY\u001eӟjn^ו\u0014V\u001c\u001eU{l(i7]~f|r<+\u001d<Zʈm\u000e\u0016\u001dhwэW#\u0011 ,<e+~kP:[pyax7)rOZY\u0017E-\u0007\tN>|\u0011KHZ;/*Lh<\u0017ĝycf\u001dWX.$lӸ\u000b\u0015/uovL)\u000b}\u000eQst$CzG:VI.Aқ\u001eg\b@ܶg|\u001a\u001b\" i_1\u000f v\u0016kkWi`Z.W\u0000[ZUQ뇗4\u0007ɲo`@\u000fB\u0007jbv~!W6S*\\|pn{&Տ{\"5F\u0017\u0018_*gR\u001b<\bT\ff\u001asͲp\u001e=̅\u0001\u0018_G%!W~\u00079>n\u00176ئr-\u0015a|6\u0003y\b\u001dc10Ɍ`df\u001a\u000e%ٍo\u001eZ\u0001\u001b#T>\u0000\u0013sί\u0018?9^u>\u001d)\u00176\u001aFh馬\u000e\u001a#ɭEV܉Oذn\u001dKVY!\u0001T2_>-WQn\u001aɥRRJۚ\u0001\u0006o\u0007\u000bM-\u000fK^돉7\fpv\f_\\8לȹM1\u000e4uramTfc/ݽns<:\u000baG=\u0013~7&WC\u000f`[35vʹ=z&;%nhP-05\u001dH9݇\u0013+JmyϏbCC\u000fv`eXB.q|Z΁V>Q\u0011/6g\u0000sH\u0002_\b\u0019_\u0004>70gT6mbW\n\u000e6ƪGkZp\u0018z3b?J*|!\\\u0018%d\be\"C\u0012\u001aQC./1\u0005ӊz{ԥJ$Wһu|\u0001\u0006+w\bj\u0001oj9\u0000\u001b\u0017\u0006@3w\u0001\u0003\u001acnQ\u0001\u0007E\u0000ZHjmSVStjFA芓潍\u000f\u000f\u0012\u001a\u000fyI!2gNo`\u0004ue\u001fZOiDdQ2`p%$ȣO?6+E-\frAC\r8l\u0000Lߢ\u0014:I\\%\u0011\u000fNޛ? `]o7nʋ9\u0016|vT(&\u001fiGz'g\b|}ͿJF7[aVh}\u000baN^I\u0014ΰXZx>a\u0015+MвP7\u0018\u0001\u0019b%^\u001c\u000f5#{GFp9󨏤\u0015*zT@\u0003Y%T޽\\j^~\fuɦR\"\u0010\b%?\u0015\"^˱ֱ47\u0018f\u000bĔr}\\*\u0015^[\u0006{#\u0015\r^%3\u0016\u001a\bO*lANOO\u000b\u000b\b򥐒\u000eƬA!e^r2\u001e !\u001fP#gvs\u0002\u0007(G:P$\u0006-\u0017\u0011k\u0007&;Ǎ`$_\\}#0R4aUQE?mF|\r{4~jPuV*~4\"\u0006~mJ}Z\u0011g\u000ef\u000eF$\u0005ZΜ69<gW4oC g\rb{0\u0005yu\u0004h^hr\u0013[+P9K>\u001bl3>\u000er\\*1\u0017\u000b\u001fM\u0014Q\u000f\u001e~/O^'c/Wҿ\u0018\u0015^}\u0015^{^]8\u0004h^H2=yqNQ\u000eE\u000e ކw0\u00054Uzir*,++/ؘc뼗\u00052p6\u001b1\u000e=*\u001cܶ8lutY*H˛}N/\u0017(Ӯ\t\u0017PUCMCFJT\u0013\u0017?+gY\u0007\u0002\u0000l];n\u000fq(~'\"\u00114D>\u0005[MS0\u000e.peI+N>;D䗌<o5M\u001cVԣřvd6n^4A#q;\u000blN9WIͭ\"*9a\tQkXȷ ~m)q\b\u0004\u0003c\tf3d\"2ROC_.\u0000l\u0007{Hc\u0017uzk^SvIZV}UT\fC:\u0006ЮLmN$Df4´`҇o\u0010T\\\u0010AY/G5&\u0018\u0005]\t?OSNhxoC˃4+S[Vk0]^'#kUm]\u000e*\rѦ3\u001dN|\u0010y$Kٞ\u001ap?6SL\tp\u0019!;0V$4sTJ\u0007+_+ti*=~7pxX{GJٓWqu\b!m|K25nQh\u0005'4-jE\rvP\u0013<<eұ_FN=xZ=F/E\u001fH(H|\u001c6|@\u0005]\u0002T#Ѧ*N}w|Ih`ρZ\n6ٲ\u000fkp\u000eU6٣F9a\u0007C4at\u0016\u000f\u001c6\u0011Y(\u001ey7fokU\u001bA\u0019[<\u001a\u001f@b*\u0007ޙ'\r}NW\u0014D(\u0000\n)\bS\u0018\u0015G!=no=ߢ\u0001ʶY/UϏNvȿOc\u0011}\u0015{z;\u000f\"\u001b:ۉzh|a4 \u0002aए}a]eY^dQ\u0002D\f\nA7R\u0000X_d q3W\b\u0013׿\u0019A,,8VvnGWZȃoڙW4\u0017`\u0000m\u0011S\u001eu!Yd\u0017R],\u0007\u0015U@\u001b%\u001f׵+\\I÷s^/jm\u001dUK渜zC=Z\u001cOz\u0017x\u001eV(h)xq]|dh~djx0'%荜&D/X뀹nWԸɞܫ\rZR\rWW\u001e̼\u0005E_d\u001e\u0001(Qv&)!\u0000MC3\u0006;k~hQQ\u0006#\u001bVj)_Y\u000f4\u0010jN,([.ы\u0015\u0007Eו&\u001b7?jÍe\\ju\u0003OsVRc\u001f՟\u0014Gd?\u001f-C\u0003\u0003>\u0014Gk4қ^\u00001lKKvU)F-m}Gdl,.uz1\f{ڍ:e\u0010\u0011c\u001a&\u0007O,\u001886ÅLrLIepFH\f[8e\u0017\u000f|\u0002`|\u0012.\u0014ZUV 1{jɁY\u001f=\u0010\u0018ˡX\u001f)95I .\u0005\u0006t0\u0014ZAjE\u0017#\rWvno\u001ef\u000f\u0005>l\u0015;{f+iECJ)3w)qg\u0002\u001c៾w\u0005\u0001()mO-r?\rk\u000ȩ\\f\u0016A%4\u0007\u0003ʘGlI/7m6vIxzq\u0017DtNU{o|3?$Ct\u0000\u0002v\u000b\u0001@_ogGWoxq\u0019``\u001f\u000b\u0005};grC\u0003&$>\u001f-6^m\u001f鵯Ce_pV{O\u0000\rRn\u0019[ʯ\u0019˲o\\s:zRmRϚ\u0011uOw\u000bx4:\u0012\u0015\u001b˵B+\u001d@Qnƕ\u001b\u001fdsb\\j03\u001cJN\u001e\u001a|c\u0013lKŵ6\u0018#g^\u001b%hX\u000fZN睎iY׎\u0016}+\u0007oFߎ4I,:-\u0003IV\u0019{+\u000ew˖)\r\u0013NN\u0000\u0004;e\fQ8\u001e\u0018\u0006g]Kf7&Q&D*]\u0018{ڇG3Z勯~\u001bS\u0012\\k6\u001b<=5{\u000f\u0007\u0019G\u0019bs6Y\u001a09F6\u0012\u00058=\u0004>kT\u000ed|d\bɲbo,>3(/k\u000b\u001bRI\u0000W^]\u0005+\u000f2\u001e$N`IcϺy]kC-4\\T1Dk6<GjP5SrP\r&(\n'\u001a+ކ1ߟu`9E\b3\u0007Mz\u001eafX\u0006uqnk{9\nzPMW{Xټ_\tY\u001eg:XgG˨q\u001d\u001e\u0019DÄ<\u0016}\u0010\u0011w~n\"e)O_ul+OYJ\tfr&5Ru\u000e&78䔁n̓u\\s׹Sۖ!\u000bÇ^EL+3lx\u0013J&,V\u001b\u001c\u001a\u00133fXPpz\r 4\u0000,\"«>]_\u00132e+)wWnEy\u0015>^e>\u000f\u000b'#af\\XQI\r(B;KW*\u001ds`\u0013\u0007AX(D%\u001aiw!e8q\u0012:Y\u0018\nl3p\u000fs\u0001gq^;Ř7^4Cͻ\tBn>+ӺZ\f\u0006F\u0006)?ׇ,\u001bVpiX\r)?Lr&&(\tyQP)bKp0F;\b-n5u6T+\u001e\u0012\u001cP$l.?\u001d\u001btw\u0006hD\u00045p*q[E3:iZ4BdTNp!Qj\u001b\u0001g\u001bEt%k^/E/$$.]\u0013c{d\u001e-?0V)mg(<`4bp\bs݃Fr\u0004)I1&L\u001e\u001aǽ?l\u0019\u0015-nzN\u0016WUo}Zx);#WYm<\u000f5D\u0012\u0007N\rEOՕJӍ>\u0014Y鿗yW\u0002I=Zy\u0005\u001b[\u0006¥q4MZ\u0019+{J#l6\u0015l\u0016\rg\u000bBڒcrۧU·V?\u0001Nouz7\u0006baW^q&j%\u0000<\n\u0011\u001bUсf\u001anĖX\fi/:o\u0018X\u0018®޶\u0005\bxr&x{'\u0019b\u0002Ŧ%h>\u001aSs\u0005*hR\u001a\r3r1k\u001fb?_K]k٫\f+u:\u0005n2RlC\u0007\u0018h\u001eӊW\u001b#<v\u001fmF\u001dw0A\u0018de#\u0016*։U5ro<D1jy\nwa{n\u001aRN9kv\u0001mD6\u001b{\u001aRo{h\u001cܱ\u000f̡1v_]8L\u001bjޛa\u0018ZzaXTh\u0019ClN\u0015Q\f\u0019\u001f\u0012\u0019\u000eRnrF%|$)|1.QK~4P>Ws[knMc\u000f$עA\u0005|@(sIzE\u0000AP>h=G؜I㨁ʲ~Z\u001c\u0014Keկʷ\n\u001a!WZO7xΜҬy[{\u001bSTEXzpN)g79n-I\n!(]eW\u001dA$h<\u0017q.=;D\u0012݁5F\b<\u0016B9kq4gpq`3\r\\絽W\u0011u*N\u0011\u0000c\u0007V\rc jlVe塬Of[Bpڣ\t'-U:xv\u0003$rB)6\u0005\u0017\u001beZ#(lQ>2}\u0015\r۲'\u001f4\u001b}c>jFȋr\u0007\u000fھX]u׌\u0007yMY>2?ֈdp:a\u001bN\u000eDg+s{\u0015iܫ|W<\u001bs{\u0001V\u0014C\u001cR\"Y(%e;T\u0007E2tct1mPTwŭr+3߆\u0014`dp$!Qِ\u001cDՏX?6c\u0019o,F73mjV\u0007v*okO֥dl$\u001aN=\u0007gCm@̩\u0006\u001dў͒\t\u0012ϝS\u001cJ82am\u001b=C\u001dF\u0004weဨga\u000bF\u000f^\u0014\u0006mJ\u0002\u0018\u001fZ\u0017v\u0016k^Oz\u0016Se\fݚ'`!]G3\u0016\u001e\u0018;sr\u00007\r\u0012cCY[|\u000emr˻SF3QN?0˻,\u0006ia(Wv\nBцՒD\u0000{81MMS%_\u00141μU#e4al\nD\u0010C޳pKcvg&5-Q\u0006.w?\bF\u000e\u0004&\u001aOiTqk\u0003\u001aƺ4+\u001eo:i\u0004\u0019HC\u0005c\u00138\u0013\u001f+\u00188~糭\u00005KUe5\u0018CA,\u001cMw)/Ӵud\tAe\u001c8Ñ5l.]td8XN;\\R>86-\u001a\u0005񸼞\u0015ڃǇ΃'K\u000bsKE\u001fU^F\u0019HF(ؖcyB7CW\u001c\u000e+BO+_P\u000e5Q>z8<E_S9LoR垩%\r&Wtf\u000eN\\YG{/oe4ב\u001e~\u000e7d\u0016QfUqu!h.&ېfYX\u0015<\u000b\u001aU\u0012\r>\u0005hcjYx\u001drX4\t+>\u001aJ\u0010\u0016{JR!o\u00115\u001elgy:=}jC1K\u000b[9\u0012\u0002G#wxl*'=R;\u0013ұ!mـHdjMƚB0?tE\u0018X6Qx\u0015'JYU\u0005|\u001by\u001a7㢘9w3z\u0006Ҕ\u000f;h\r\u0012ω\u001b\b+thH́rx\u000e%\u00199\u001cb[ʚ!d^+E\u0003\u001e!~HR.B,l\u0011jD$\u0019\r[{פ6n\\_k!\u001f3V\u0015\u0001k]&\u0018?`Wb\nHs\u0005T\tj߸ѼڣvaLD7l#J'-\u0015\u001c`i\u0015dCzjkw\u0019a\"7~]\u00174m\u001f\r(\u0011\t@\u0014\u0012\u0006LdK\u000frsR,kh*\u0015?.Ato|5{3&u(ک7\u0003\u0013e\u0018^\u000bfd/5\n\rS\u0015\u0010\\rv,y<\u0004#Nԩ\u001a`\u001b_t\b*֏\u0018u~u(d73qⵖ+L/!BDs~Q`+L4\u0006\u001a\u0005M\fPa4[_²y8W\"\u0002C|t)O\u0003s;㯣bn]ǃ\u001d\fTkI1uv4\u0016jS\u000f1Oi\"siMYV:>2rRZ;O\u0006e__Gu\u0002>RlT%L;H>SO_\u0002\u0003qa\u001dݦC6[ea㜠\u001d\u000fIvOo44ah7\u0016@Uo/O\u001aC\u001f\u001f\u001e-9\u001c\u0016@q}ըv8ן7g\u00040!}t䄓\u0015uXvf##%k*;\u001fy\n*+jMN:Fo\\\u0006[\u001e_C'\fbX\u001a#-\u000e+\n(f\u0002nVT\u0016ׯ\u0000{:ۻM:\n,1QnyEt\u0014hǉ8\nv\rX\u0001zmCow4?\u0004'}Ry@eY\rw~hMeԚ\rٿG2>:&xOW`_\u001a&OusCrBPZHhU;`\u0000qv&\u0011\\\u000enZ-&\u001f\rkGZ;4\u001bk.ʋ\u001b\u001d\u001eĴ4\tP2\u001fy,=v\u0002uс\u000b;7w!01!=>H\u0015\u0003%\u0010t8RIf\u001an˩r\u001aPVKr[\u001awXrf8\tu\buX{vv&׺(%j\u000f8v{gRP%)e[Ի\u001e\u001a\u000f3/遻qs\u0015V\u0016\u000bڨ]lQTw\u0013R%\u001dyk\u0010nZ\u000f\u001amzw\rV\u00106yadRQ_#9a2Yaٞۜ/4C;­\u0016y\u0000\u001dؾݿH^\u0000»\n3#C_)jid:R\b\u000bSr_K[Ӎ1=7>\\K1\t\u0005ST.1\u0011\u0017\rڧ꽭.@[/\tX%\u000b\u000f4~/m\u001d:\u0001\u00176H\u001a\u0010y\u0016>W+z)Z*\u0000eS&0\u001f\u000e8-/q\u0001lK:\u001f\u000f\u0014\u001b˱e;\u001fӱb\u001d3\u001bMNd\u0014\u000f\u001ezh9-Dˮ~\u0017]^x1K]\tYƿ;Mw+~3뙹K\u001f#ߛk~g]6nfLiL`6O.U_{q7J\u0016\u001f<\u000eU\u0016\u001cUgߌߓ8)KSss҆j\f\":鯩\u0011\u000fi&\u0011+\u001a\u0000\u001b./:zz9\u0007\u0016(Wco\r.\ttߖѼ\u0015>7ضٸ\u0016nT^f|\u0013B}vw/\u0016'F\u0010gT6óƙm\u001bu<i7\u001c̾>E\u0013Кz̡t07g\b=HB^\u0011l3Ri=~\u001d\u0005{;V6\u000e*7jo\u0014ETu\u001f\u000eS{ϹW~a̻H7n\u001b\u000bޏ\\k.\u001b#D\u0003d^\u001f/d\u0003\u0014}\u0001.>ٯ\u0018C=<R\u0016R7\u001b\u0012WD\u001aJ\u0006-m\u00144QgT9j׎Ѿr_#7\u0000j+\u0006!\"\u0011\u0011\u0011\u001a訖\u0018~iͼN\n'+v,\u0018L?dS\u0016*;0nقn\u0005\u001aC\"Z>\\<Ou\u0003<\r\bͿr\tT\u0019\u001dojߺ\u0005P}=2\u0017f\n\\\u0013Cx`QY\u0004@N\u0015@C\u000f\u0014Η.p1\u00134J\u0007]{Z{_-\b%-\u0007p7\r^\u0002>\u000bW\u0006T\u0000}?\bnP\tѧg[]\u0000֕Nͪ\u000f\u000b\u0006\u0001)0ݭɵ\u000fuǑud3QhCgXvw%e-Z-.F\n<!}oCj\u0015\u0012훬cy5 {\u0013vy.vjKiP.C/\u0003\u001f+4\\fYф\u001a%\u0013=Nۓd2*)_\u001eZo韚؟ɢ\u001bںhXעAK֨O3=83\u0007\u001d|s\u001fv1wiiWa\u0007\u001b^\u0003M?)Cf{\u0006\u001e\t\u000eChSn550qٰa;}HTϥݶ^\to5\u000b\u0014q`bwnbrt\u001b^27&qQa\n^3qS\u000evt\fjl,^Ձ\u0000\n5H^ww\u001f[\u0001_9m2{Z^i\u001e\u001ah\u0004ϗDw8|\u001b\u001eu#}᷏GKM2\nz6ԼN6SYu,#Z\u0013Oy)^\u0015\u001ed\u0014.Wxn#s\u001eί1\u0006\u001f@-\u001bwS\u00121{<\"9}#IW73SegBuk!\\u2Ic(s;\u0007Sw(-\u001e@@.\u000e}4~\u00175*/Y\u0014ܞ׎}ju%a)2\"gsz9~}ۖV/|&Ƚ\u0011i\n;EE$҃^\"vk\b33>\u001b<l\u001c\r\u001dh>\u00124\u000b\u000f\u0003!gC\u0007fU\u0012%¨*u0\u0019v\f\u0010?\u001b\"ŝ6oxg_U)3믈\u0014Q}\u0017\u000b[p+\t,M\u0007\u0005;\u0002FW\u00134\u0003Y=P7UcȘS.g@yn\u000eL@0{r=q6}'Y\ru^\u0010\u001eP}콦d\u0011\"҉H15poĲ)!ؖn\u0002o`\u001eXn\u00026#\u0019\u001aRA1Cn\u001e|K\u0004C7Z\u001d8^{#:fL>\u0003ۘM\u001a\u0011NppҠ)@r`y\u001f8,~\u000b\b\u0016,U\u0011ytoڹ^\u0014\u0001С\u0012?9xBe{\u0002#wO\u001eFK[Y]\u000f5Ļ{1[\u001f#\u0019צu\u0004$[]\u0016(ޗL:\u001b׺15,jg9;k}gÇ\u0006eXjL`Y)\u001c\u0003\u0005QDBF<.:Ɂ,A\u0015*ִ{ߥ*xg\u0010=HmN]Bn6$Rrv{۲/a#?\u0000dذT\u001b\u001e)\u0007P}aJ-KOnC5XuG\u001f\u001d\u0013A0K,׃OmK5{\u001felj6rؐY)Bm{\u0001|jVN%4zja\r۞U\u001d\u000eC4w=cksEA-2aR'ɼ;.\bOb\u0004BZ\n\u0007\u001fۃX\u0017t1ʽi5>td\u0006TDuץ9\bKy__\u001f\u0007z椤U\u000e2oQd\u001b~b8+\u000fBt_(|K\u001ff!JK\u001a]\u0000\\p}&T`\u0007<oG\u0017 G\u001a\t(\u001b|CA$9 \tv>z>F.AݍYxeL냰w.2#A\u001esz3{zv!aY%\r*\u0007qT@\u0007lCR\f\u0016w\u0018U.}\"i3:y\u0013[D|(4!SՊ 6v#\u0018!ڴ;LV-S\u0018\u0010\u0010))\u001f!x73Ze\u0019\u0004\u0000t\u0017O\u001bК\u0018~M+à`\u0018vX\u0013]^;DVX\u00169/Ng\u0010m7\t\u001aT$\r!A\u0001 ?^@t'tSU|!vAź=\u001aptPEc\u0018ㅏK\u001b\u0019\u001bGrbsPڎvߩx@1k;%F++|3r.\u0001 Yt]\u0010\u0003?C\u00023^{\u0005zݮ7gX\u0004bWɻ{\u001b\"``\u0002xKLW\u000b\u001ax1`~V\u001f\u0019!فÐL{;X'\"\u0000*:\u001d\t\u001dؠd{FjSzT&m=1*{,Zk\u0001ư쓫Z6kf0^\u0002v\u001eۖ\u00178 >\u001e/\u0012DIPU:=e|Ucl\u001aexB\u0010TZ\u0016{[!Ռ\u0018X^JU\u00183[%*ǣkX|7/M\u0015kw2a찯aS\\\u001anG\u0010\u001cM\b>o_4\rd\u0014+ؐW\bР@2B]rwǠe宀zt?3\u0014\u001e,\u0019\r2t\fd$\\XvTv*M\u0014%wIާ\u001b\u001ai6r\u00116В&8\u00197'nL\u0017&Wi~P9\\\u000f\u0018brn:\\=1QC\u0017.\u0019?teOÆZz=sv\u001a]a\u0017QYVQbĽޓ\u0010#;{\f^\u0001OξCI&K\u0010 \\D@HoV|\u0006\u0010vTnsE\u0011[zs@J\u0017G\u0019rn $.EdlDe#N\u001c5w+2\u0012\u0018H\u0017\u001fc\u0017\u000e\u001e\u0015ҿO\u0006\u00146_6j[iu(r\u001a*G`mly3\u001a  ]l\u000bA\r\\b\u0014ڻ\u0018S-\u0016\u0017PFG~lAm '\u0011\u0016-_l\u001a\u0019^|\u001fzjp}\u001cE<\\pEc4ǔ}OdfʈFzf3MFVw0KԿ!sQ7Yieҥ-Q0\u0014W|vw!Bmm)U\"v\u0003(ݮ`P5ڗ=5Cʉ`?\u001f \u000f2\u0019\u0013\r?@\n\u0007VǍLq_@\u0001UWUhĥ\u001bahB l\"&4<<\u001ck\u0012\f.׷KՇZL˗VNjS+\u001co;˦:Dl3qThDF\u0007d/N0\u001a3d\u001dO9{\to^=HeL5\u001d~񣲠\u000b]DF\u0015~\u0003\u0006˵sPb5\rGUNtқh*f;чG0.!#\u001bȐ8=#'b^01(u\\\u0007M\u00057(8HEoOuވʍ%؜\u001e>eΎ𠍱\u00033_Q/|.ƃH\u000f)\u001bY\\\u0001TY\u0016BZ-\u001b>rp\u001f5b\u0015\rHȖV\u0005-xyF+eڸ_4U35+[OF'?A=40Xe\";RG\u0004ZSwe\fԝL\r%,?\u0001iRlnO\te%۷wܴ\u001f[f{c\u0013\u001ak1oSG\u000e;qlkǰ\u001agq`k3%74/>\\!#esښ\u0013J\u001f';%N׋\\\u0007\u0015y\u000f\u001dcgp*.sCVxp/@}+R*qvk,ss'-\u0018;!\u001dML\u000e\u001d\n\u0005\u0013)\u0014\u000fa8,%[V?ɴQ\u0000Z\u000fK&0KKz\u001fAt f7XZP\u0000Z%A+9\u0001\u0007q\u0012ﺪqeB[::ߔ\u0011\u0002QXrŸ;\u000b~?|\u0018v+,)\t/z;h*q^{{\u001e_eh;S\u001aJ_\u000b4\u0015\u0019\u0002f~\u0019\u0017Fd\u000fG'+\u0015eOv4s<}(@f0\u0006&sg\u0013YV|ń*I\u001a5\u001fibg\r\u0000\u000b^\u0010c\fz\u0004]/wt3af+d\u001capla4=K\u0019zzQW/\u000b\u00134,4!{OѹcN\u001aĪc׮]Fz\u0004koiqo\u0016x}̅1ވ\tWZccR\u0007g-@\u0017cԀIKx8\u0006ApW1p-=2R\fq&\\7ϡ+Wkg\rB\u0002b=\u001f\u0003 \u001dʨOCiD\u000b3L+t\u000bM ^L\u0001e\u001e睩J\\=iN{v\u0017\u001e.xyV.Q\u0010\u0012:aЉ싑e6~\u0016\u001f=YzcD`?L\u0011<TwӸ%\u0011J˃\u0001K\u000f\"{HmAT##\u000f_9zZ\u0011#ث\u0003D\\F3ZZc\u001cɺg`N{\r{TT6jk\u001ffi`O\n'eu3sCE=su#\u0013\u0018\nUy+ xyt\u001b1]:\u001b=l=WFJ\u00068\\˲aZW\u0010秇\u000eNQKn.\u0010\u001f=w\u001dޚ!M̩\nyg'zʟ4\\/eNB_8\u001bq'6)\u000b[V r-w9lmJ-kc\u001c\u001av\r\u001cV%\fM\u00060ǴwOg\u0016\\}~n^5l\u000b\f7օxEZﮖ\u00037od޹~5nB\f\u0002\u0018d5t,O@W\u0002:gfZ-lU;m<\bɨa7HGѵ\u0012Zm\f\u001an4]Ckw˸\u000e8S6sp\u0004\"(Vi\u000b6ԏ\u0007N\f-gdh\u001c\u0019<@\u001fF\u001e7\u001b|\u0000ب)5\u0000\u0007ZȮi|\u001b@HZ;_?\f4\u0014_~nm~\u001f\u001ayX\bҤ.r\u0014Ō\u000ekN\u001c)\u0012ٟ³rZ5!{\tJU)\u001dCe!8\b\u0018^i\u001b慓s,<V\u0019/NW\u0016T_~\u001b{/*M̰x\u0003^r蹲Ɇ8\u0002jcqFӽ\u000eGbO^~qA:Ư\u0018\u001cy\u001d\\mZf8l\u001416$s\u001f󫪞M\u0012#޴){<\u0015\u0017]\u0019V+3gۥh2L87fxtht\u0003\u000fWVYz՟)NF\u0004\u0003qG\u0016Apdp/eVM]\u0004\u0000m7O4\u0014CJ?;ue٩\u001d\u001c6]~`4ӴG*\u001f<V飪\u000b\u001a5\"\u0005'mB\u0018Bۅۿ3\u0014v:)S= ~]`o_G.N\n\u0004%Q\u000buўB^1q\tqko,켗#no\u0019\f!;]Um&>c8=\u001cm۶:\u0000ͽ\u0003^8\u000b4:WnRFrW-$^0`£4\u0011\u0016m\u001f;%\u001a\u0006T\u0006IToq\u0017ү\u00190-\u0004͎ȋūD¥$\u001c!\u0002bUq\u0018\u0007#ƃڏ,Od61з5ͪH\u000b;,k\u0005v\u001d2\u0007\u000e̳L}5>p\fv:ތj5;\f-@׼SXи>Q\u001bg5N\u001e`QlM-;9Q`ͻ:\u001d!owӪOpxM,zl\u0006߄Ua1:V\nݙD(&_-d:Yȴ\u0003b=0_\u001fx[\u001fY\u001awoh\rM_H&/,mk۾zg?߯\u0016F\u0017prnO\u000e쿙2*KcZ\u0000;uB-ӽ\u0005̈Wun\u0002x0JH5\u000b,ݕ5Xj_97\u0011Rv\b:\u0003*!y`8zt2tҠ\u0007Gu̕FO<[W\u0019NmZu߃[t\u0004so\t\u0010Hs߹u+aZ(\u0010bc\"\u0012\u0012\u00167-f,R\u0006KɓlMH>t\u000b<\u0013{fkzE\nsrxƉ\u0017\u0015f3҅W\u0002gF_2q\u0017@K+{Ѯ&\t?5P\u001e\u0011);?(2T|Sܖ\u0007N̂6+\u0015C;\u0015tUm\f,K\u0018_v6UI*_џjyhR1'Lxp\u001d'7mK\u001b)?k+}-\u0014XAWh,d+\u001d\u0012:q]\u0018\u0004J`hhT6\u000fSԑ\u0006\u001b^v݌%\u0014\b^s.E8\u0019J,5wK\u0012J|@6\u0001~\u0007ȨM)5T }\u0016\u001e\u001dH\u0016\\s\u0013ͽ\u001f:)w-8uGKi;:ުf{Sw8\u0002)r>r\u0010\u0005K\b+6\u001aU:\u0001\f}\u0018-9\u0015J27\tp*u\u000b\"\u001ag(YAmxZ=|Dtj\u0005\u001d4*@\u000e\u0013k/vaN\\º\t̃O\u0016T4/I\u0006x!\u001f|?{_\\\u001fz`)v,\u0013(&{\u001en9Q\n_VS¿[,7x\u0011i6\u0016!y\u0016-\\cA\u0017X,rU/\u0014\u0011.Gj\u0011UaBu\t\u0017.R\u0019\u0003v4UbCZĚ9\u0006\u001dsr\u0007¤s\b\u0014\u0014ߐ\u0014ʜ\u001f<\u0010qAl%g/m\u0013N\\\u0007o\npCUP\u000f(F}j\u0004y\n\u0007d8H봟>W};\u000bG`B\u0018\u0013MeǤF7\u001e/\n!\u0012_8P\u000e\u0012\n_/5lc?yN\\vf\u000fζ\u000e0WY\u0016|\u001fɬ.nk3`*\u0014\u0013\u0018X+-\u0014\fvƹY\u0010)bzN/\bfk9\u000ep\nr +#\u0003t^a\rl|tQ~\u0015\u0017\u0012\u001e?:GOu\n\t8n\u001f\u000eNb^d\u001d\\7\u001b\u001eZS۠\u001c\tM\u000fsFu\u001c/P\u0003\"M֥\u0019-怌Nvσ*\u0013; '\u0012 !p{:މ\u0005f\u001a\u0003\u0007-峞\u0017U \u00195wz<=ɚ\u0006Ŝ3'\u0004\u0011u\u0007(xa!lL\u001ax\u000b9!9{\u001e+漗O!b>6\u0002ѿ\u0015A!X_\u0006x\u000b|RZt7\u000e\u0005Y?4(\tB}&M9\u001dR^MnZ5[m\u0007Κ{\rHbtة\u0017-_\u001d\"*\u0003[LOH\u000f>/iY#=\u001b4CrpT5L~<e\b[h\u0014\u0004$'QW\u0001%|r\u00108\u000e*[\u0018G/сcz#{\b6\u000f&֞I.\u0004֠\u000e\u000fh\u00150{:\u001f\u0001BtgrZ\u0019;\fPȯqW\u0004JYBH\u0017i)ϻ9U;K5&{oU\nq\u0002{\u001azQ;\u0003/\u000fBQ\u001ct\u000fK}\u0001\u0005^զ.3q\u0011~cEx\u001bsdG%q4oEVI<'(9\t*1i/\u0018\u000b\u001c?gPnnI-w\u0005!NS:V\u001ck\rx`%{F\u0016]<E-\u0010xf)k\u0004I\"k\u0015\u0018.~ƶM\u0004op\u000el\u0013{짦L.\u000fﮢi}rRF!6^s&1h^5\u000f0iOjbƄ((\u000eE$\\\u0016F4W\u0003=m]n?G\\\ttϯ=\u0001<\u001d\u000b{$鰳Uk\u0019saߩJHS_/V+&J%{m!_9Wyf$w<z:05Iia{\u0010p\u0018+\u001cp\u0015\u001dm}n\u000b2T\u001ft\u0007$xMw?\fFhHҋ%uTg\u0014^\u000eC5\rg=w\u0011A]D\rn\u001c஁EqK\u001b\u0005%\u0018\b\u001c\u001c\"wj/\u0018D/B\u001bw֯4*?dZJ!Oɹ}Wg^\n \r-*ztv\u0017\tʥz\u0011C\u0003Y߈p\u001fs\u0007\rQG!며߾_*yeo/o\u0017}\r0S`0\u0006Eh:\nơ\u001d$(Ml6qB\"\u0017NQ\u001b)]jd\u0002>\u0015w.Jհ\u001cl\u0011\u000e?ʻBw_H'Wގ+M\u001f\u001dD\u0006#=D\u0007\u000fi\u0005f\u0002\u0010mfb.v!ՓhPY\u0003\u0004BleVY/5#. \u0002fΗ2;r-~YՀӯ5qSo%y#o\u0017MKGual+)~h\nѸvwyaͪfeDƸ\u0003\u0003;NZ[w\u001dsk\u0006\u0010\u0000w\u001a\u00067|b\u0014k\u001f\r\rvĻrBZ\u0018<*u:عjOw.~\u0001.WT\u0002\u001d=`\b6]@VS1\u0000*\u0012\u0003Z\u000fY[r\u001arԐ/\u0016ms\u001a'ຠՅu\u0007:<;mzuuߙ4yÓ)*mI0R\u0012\u0018'\u0005S\u0015qp͎q)_4@d<Ɛ|.\u0015\u0015E\u001a\u0017H\u0007\fcx7;ZM4+)Pyl5@\u0000hCUƽi7\u001fiWGy\nXe\t[ַיt+yal3`~\u0005ܼR\u00142ؼ\t׬.?\u001bfV[\\7Ӓ\nO\u0001?2~o5d<%\u0003\u0019g;s\u0011K!\u00061\u001f\u001b\u0016 >0Z\u000f.е\u001enA/lcu\fu'fr|)L7n\u0019Se\u001fonnP䭡p`q*\u0014\u0014/u\u000fμn\u001a\u000f\u000e݅.ua;gbiS\u0000/'g\u0016_񜌬ms+լ\u001d\u0005~Bta\u000fJ_\u0005\u00004~ v'Gn@7<\u0004cO~req~5:\u001ei\u0012\u0018pO7z!P3Hօ]k{uVj5ͥ~\u0011\u000eʪpܗAf\u0005\u0001hog,L}\u0007jl=zX\u0018\u0003Z2\u0004x\u0019TΥ`iº\u001d\u0003=PU\nُO#\u0013C_\u0013ޅX]Wodja\u0013kF˃Ζگ\u0012{S'z\\\u00101\\=\u001c\u001aHFZ>νY>,\u001bSq!1\u001av\u0007B,a%#M\nއ-R\u0010m_z3x朥\tAf*vb*9n\ftM5.\u0005\\2\u001bKxmeR\u001a\u0013M\u0005\u0018i\b\nO\u0002\u0002\u0012yEGgΊ27yA\u0016BiRźU>\u001b|[5ބӸf\u001b\n\u000e\u0018|}\u001b\f6gF/\u0013k&7Ms|U[~]')g}\u0007\u0015\u001e]\u001b\u000em(ihc즳JX؄V+\u0015U\fO\u0011lw\u000eF\u0018̬VW\u001b^H{`\u000bBS<Trs9\bq\\' t}ܘf\u000e\u001f~C̰\u0001ک\u0007s\rq5*׍W\u0013nx}^\u0004\nzQsև h|իtn\b\u0000\n:dK'\u0001xDP\u001e;î!h+\u000bUGc\u000f47(\u001d\u0010NO:/OS7ޠ4\t\u0004_\u0011|#bOںWSLI(6S\u0001NRƨѧ7\t\u0013IZe\u0013ܳ^Dv漏tÂqGstb$9\u0014\u000747\u000eI\u0018,\u0013}Ϩ裁\u001ecu7T\u0005GV~*BI5๶gy3\u00194lvwZTK&uh\u001eSu\u0012!<\u00161wE@~_\u000fSm\t\u0013WVYmntOߎ]\u001aɏlcC1:SHPpG7_!\fz[Nv\u0003Ɋ%_a?mFKוּ\n\u000e}\u00177\u0010@΍j[.1`̃Ʌ\"\u0017z\u001fܰ<\u0017Fk\u0015.|T:,|v%__;m=\u0001_|pϱ7Z+.Q\u001a[g\u000fwWL\u001b$>\u0018\u0019FNۦb\u0005leb~:Ճ~'aXY\tf}\u001a\u00108k<Z{:>\fV+@\u0010Xٗ\u0003z'\u0018;U3N\u0018i.\u0010`;\u0018,r+\f\u0004Dc(\f\b|j7`\u0012AcG^\u00154Ps-.JgK\u001fTI\u0017v\u001fcC5wgvY7\rn\u0005q\u0000K\u0014٥b~4-d@[P3\u001cH\u0013TUC}\u00170C\u001fG+,\u000ee\\\"\u0005\u0016\rū\u0001\u000f\u0013H-}c?y+\toW̒l\u001eF\r쬦rUxkMlˮo\ts;s#\t$\u001fq5t4m,w\u0012\u0018hgERǹ\u001ePTd7Kߍ+?Lo\u0017nI\u0014j2%\u001c\u001cl\u001d]jn+sʊ˦V\u0004\f\tً}BXm\u0003\u0017_^p}}@K8|\u0006n#o\u00174b6<S m\fxWs\u0014+B~<r}I=Yo^\u0001\u0007%gE`ٶn^#6W!8{JX\u0011c}crwmwU\u0012N\u0005dNh?^m+qNfTa*\u001d\u001f\n_fA#Ȧ5D\u001ek\u0017\u0004ےha\u0019\u0012F5M $3\u001c'yp9Pu\u001ce\rRC\u0014\u001bnR`g\u000el\"ZPY\u000e\u0007\u0011\u001e]J3bq̞I\u0010:b\u00197O\b'\u0012\u000exk6MX\nV#Xc\u0019ԠL͹n`d(o=\u0014{8'4\u001c?\"7rSM\u001b\u0015]G\n{\u0015e,wx\ry\bh=svcj<*٭|+9˞Dq1Y;ao\u0000\rFɒ\u001dWCm\r*]tNTuj{%Q\u0017\u001ak\u0016R`]wtԮx\u0001D\"s\u0016;#c`L\\ k5\"X7yqե\f\\QxO0YB6AǽJ\u0003h:N}/ع;[>\u001c.WR\\bWC*-807+74ݼus\u0003\u0016\u0001\u0001V\u001az~f\u000b'lȒ_Ď;\u001cF\u001fmk4F\u001f\u0000[0ƿ^\u0013/1XU7#'\u000b2VA3!8Pjܭ@r8x>s_'e\u00164S+sM^n}? 搜&5B.Q\t\u0015KC \u0001=ǲ[J'xV.\u0016O\u001d\u0019lnSc7Sڽ`=Gh68K\f4\u0011`Ҫj\u0017.fΧe~/G\r1\nF\u0017g\u0003s\u00194\u001diX.\u0004]?\u0016R&~x(Pȗ`Q}y&\u0001O89\u001a\u001dX\u0018i\u00161469'\u0010|8$V\u0017\u0001<wSyc\ta[t\u0014\b|qa>hZ9FB|N\u001a\u0006Mo9G4p';k\u0010B3gN7^spF\u000f֡\u0015]v\r\b5+\u001c:T\u0013tNqs+r:n\u001d\u00179B$9T߿\tps\u0012\u0007Iq<>\u001fGGeq\u0018;:\u000fHvb+Ȫ\r 1پ:\u0012_K{'1\u0013\u001ce~W)\u0007EYW_Q;\u0019YR\u001fb9\u001bd=a\u000b\\|b]G?͔C88\u0000$\u0014-\u0016\u00158^\u0005\u0013\u0003\"w\u001bKrn[?\u0013cf`Ls,\u001drPS;xOv0\tZqAʙKam\u0016fqO3=ˁ\u0010œT\u001d\u0011\u000fWQ0V\u001fT+ϝ椪crr.peu\u001c\u0006o4`m.\u001b߯!<̄;L-ZU\u001ac3\u0017M;g#%\u0014\u001f\u0010VťX7\"jԑF\u0012&\u001c=MOY]XT\r-3,Lߙ'Gi\u00048\u0007+(j\\GԆXbr\u0016\"/\u0002K\u0012\bS쇤߃B,0F\u0018͹|'[Wff &z8\u0019'ݎ\u000f]mgdMSIh\u0003ki4Bcp&\u001bq\fүԠ.qxQW\u0012\u0005\u0005-5ky\\ \u0007z\"\u0018Ke\u0007Qc<T]}mW\ri\u0004k\u00079k\u0006hύSlj$j\u0013أ\r+\u0019ʟJ#yP\nX\\whxdåg`\u0005ϥ\u000f\u0000\u001e\u0002mP\u0019v\u001fq9 4myW4\u0014\n'l\r\u0003?.6vho8\rOִO$\u0015\u0005ckV\b=͋\\Q\u001c_\t\u0019늊=Vc&b\u000f\u0004)нSK^qݺVI a=j\u000eV*Z*os7Aۢuu5C>e*9(\u0016ʌ[23rQ_Hx\u0018NK\t۹#\nNٍهgig\r#c\b\u0002L-\u00171§\u0007S\u001f-m.L\u0006y䭘⯛X\u001ay\u0005R\n5\u001bX6)\u0017;2\u000f`\rպF,݉,p[WR\fZ֑\u0003w\u0017lf{oD\u001a VJl]wb^Gp\u00156?|\r/ͻg\u0005\u000e>R>Ƣt\u0018!9#\u0019j0\u0015\u0006\u0019\u0016\u0017!\\ٜF\\Ȼfs}֙znaH\u0014Z\u001f~;uyo \u001e\u001fWY\r\u001fe8\u0014daچ\f\u0019hc55iw^Z7#\u0007llF4\u001c{gS\u000e&Ԉ\u0018[c\u001cUެB.L!\u0012`kݤ%(~VMk=-;\u001c\u0017gPCR=fҸf\u0010h\u0000՞\u0002\ra\ro#ff0!7e}e\u0007=y[2\r>\u000eW\u0004\u000bYɡ+Rk^Wvpt&]:\u001d\t\u0001ul#H*\u0017Uʲ\u0016\u000e*1#84i\u000fݹo+kzڞ{\u001fW@Z^xt\u0012z\u000b`^[\u0016&.5\u0007={:QetE\rw\t\u001a\u001b(,Þd2to\u0017l@\u0000&*rH]g@k27l+vjnVn\u0003˒md5)k\u0003Tی$8*r]=x\u0017JYd;ٺV~X~\f}e\fa\u0013\u001damP\u000biM{M*QX\f\u0001IuĜ|i\f*I Y\u0016\u001bӫ\u001awüqi\u001e-\u000b}Qk\u0015~eI>C\u0003R;\u0003(7T%X\u001d;;k[B\u0013r'G\u0018m'{JH\u0019W+L*U;gt>àf!{q\u001asrD\f;Mw_*\u001b?@V7hsk\u0018\u00151\u0000\u0013p\rXm=`?;C\u0014?@3}\b[ȕ^_pREfLꘚ4-΍\\P\u001f:|BCqƎfO\u00172\u001dmHO\u0007\u0016iñ槷\bcMtԸ\u00130\u000e&Νwk\u0016S?7\",e\u0007(p*\u0017+]ў|\u0010q\\m{v\u00039\u001fb)},\u0014(Tr}/u?uۤ~_?\"W\u001btP\u0018՝q'T\u001fߣû\u0007_VB\u0010hSeO\r8Ӹ?d#}k1~G[ +᫥\u0004Bj\u0007T9\u000fnD\u000bF$v!\\s㍽86;8kX+\n,y޿hc\u0017\u00137\u0018gj\u0012\u0002ȿ}\u0000\u0019u$2,\u0015\u0005od\r&!%qDx2Ǒ\\\u000e^P.eWϟ*9@v<\u0016VʰcMW)\u00159H\\_B\u001d\u0016`\u001d\t^+#K<ʊ1\u001e[;-;\u0001+8OZR\u001d^\u001aU?\u0000UU\u0001*T,\u0019gtE1\u0016]_e4+Wl\tRv3\u001b(l(Jo\u0016\u000bk6tɭڄ3`=C\u0017UŜ\u0010L\u000f\u00198Mh\u000e\u0019^\nSLe/\u001e\u0007c\u0010UL\u0017d.;a?1\u0006`CdvX\u0006\u0004rp\u001bI\u0014ʥz'֕\b/+M M[q\\B˛]\u0011cuP!󠤹\u000b%'1ua!!~rr툔E!T\u000281}\u000fXnްYB\u0015ܝж}\"ƞA+qıgb.݉+>1\u0002\n0=%7\u001bܷg!D\rkQJ]\u000b\u0012T[\u0005q\u00172Ks\u000el8PN\u0001uM>\u0015 4<m͛h2\u001bLk#V{J\u0011ȾJ\u0004?a\"/sDxA(k-\u0012\bMu\u00179YI9k,\u0019i\u001e\b'b2\u001c\u0018<)mspfVrmIWS:H\u0001#\u001b,>\u0005\u001ei.{1t\u0018\u000beѢmlwΐ\u0003o\u001edlٶKoݾO̱f\u0002:j\u0016I[#K|w\f#)0Y_.v=Zs&ϵW\u0004*Y\u001dG%m\u0004vǩ\u001fۼŌޡȸ.2F-K'D:79r$UO\u001er\u0007uみ:`M}!TU'\u000fK\n\u0016]\u00065Q\b\\7\u0013U#W\u0014,\u0010O):o׼DV\u000fН@\u0019$\u001b4!=O-{gܫl4*<N}iV\u001e}_TH'J^?tMQ[GA8<(\b\bavfW՟\u0007 \u0004\u0004+\\BշhX^g\u00043y>y#kRm$\u001c\u0018X`@VV\u001d\u001f\tScˣVxáEkVi~g9\t6:Oȯ}fTfSaLhD\u0019zw\u0004{cp\u001d %h>3dlk\u0001Gţ8 \u0011Ĺ;s,\u0013Xj\u000ecv.+^[%rlA\u0003~61`RYd0Kt\u0016\t|D+e.\u00065q{^Y\u00126zJ`)\u000eC4M\u0004^b\u001d\u001f\u001cr5|X*{ܪ#vB]S_3G,1ٶ}g\u0016~\nMgǗeJB\u000b,>E'9\u0000]mxfы:7вB\u0015A\u0016\u0011c}\b-\u0016S=kvozR2f\u0013xlW$mp\u0005ZWD*,kBri๜<G\u00112y\u001brT<I^do\u00048yXҳ\u0012%A6j;_i\f~T\"4p\f*yce6hp\u0007La֓\u0019P/3w\u0002\u001e=*y\u0018$V<\u000e\n\u0017&+\u00126y\nurQnpO\u0002\u0014ra#q٥)d\u0002˹\u001a/nkOX|wW$b\u0015*xD\u001f4^xU\tɤ^-4Ӗ煠U\"0XWD[h@؄Z{},O8'\u001cTWpGya\u0019V1/6\u0017ja\\ܫm#m?9b\u0016Qxaޭ0#\u0005>\u0006^FlC_7\ri\u0010j#*fbs5'w\u0018柩2x\u000bU;{_Z$IhtGk]ͪU.>:;ĝ;U5o>$+Ȟ6k\u001b\u0005\u0002kyy[>\u001cSGl6-4ᣇV[8R{[}\u0001](SN:\u0005t[?\\Q:W9}25*Wd\u0015;3Y]M\u00141TJ<&6\r,P}WU[ECő>;sAEs5GO7(dwNѰ{&\u00162\u001d\u0016Z_E0;\u000euB>\u0015sj4\u0006ŧӹ!`0`ާ/X\u000e\u0013wb%n[p]w\nN5\\\u000bS,O\bg\u001a6&D\bn\u000ebUmb\u0014ۣײ,\u0001'5D[+W4|\u0002\"+d2u3ݳ$V%Mi6^6̲r\nN>(4-/\u0011\u0017S_\u0015j 2Q\u0013ڛ|_za\u0004c49\tidwxTѼm!G;ztot\u0013J\u001fUt |2\b❜\u0016ސ\n_\u001b\të\tY (Ã;l4)H@=҅{zYq@O*\t+=Փ]K~ⷢkZk\u0016\u001a9a>H\u0016!n&\rF2Z[\u0015\f\"^%eR}t,\u000eb\u0012\u001a=Oݹ`\u0001;!N\u0003k\u0015R\u0016:\u0017΄\u0011s,f\u0019\u0002Nj\u0007*v\u0019|@&Y-jxYޫr,T&,ʊx47x<Ilc\u0010ؔ@||u\u001cyBRMoAy\"kZ|*\u0017z\u00157+,]KR;*ΌF5S]7Qrߜȗ%MlݦD{k+ŠS+9\u001cy1V;xYg?̢\u0011B,:1\u0018S&h͍C\u001c+=҇\u0012\u0018U1<F9\u0014\u0016M~vݐ v\u001a=m}w|JLv(\u0019{BS:t5oC@\r\u0004t\u0013k}\b/ː\u0016-鞗.n<E\u001f/\u0015v5\u0006]WCw8cnC\u0010<\u0014>;$Ȫ&)^Pm\u001begi-xG6]طB.}X4s$V*y\u0019Wnxe]P\u000fk\u001baurf%[;~e;\u001fnt/f\u001d</*Ҳdx쀋}{}\u0002(2/6T\f\u0002W\u000fv0T@w;*\r6\u0019\u000fgݡ҈Q!:\u001f3{܁\\M0.\u0003\u001e\u0019u\u001fW\t\u0004.l\u000e\u0019f<\u001f\u0002{6kt;vt61>\u0004+5\u001e<~&1[qQ\u000437\u0018\u0015F1@FT\u0016\u0003*ϼX\u0016.vn[\u001f*\u0011\u001d\fojzkA*R:6\u001bڐIxņW1C\u0005\u0004f\fiO`Ơ\u0006\u0004\u000f\"YO`Ơl\u000f\u000b\u0011R<\u001az<co6}xƠl˿g\fW_~bƠl\u00173nޗg/uǘ17\u001bt<co6fb\u0007_Ӊ\u0003LwߴL4A\u0007ܠik{\u0004\u0017+\"\u0017O\u0005J\u000b\\\u001b\u0017\b%\u00068\u00005QHx@^\"̺(װZirpp6^j\u0007Eۤqu\u0002ng$|s3}1+ej*S\u0003\u0007r}%\u000b\nkEL8>-V3Q[̧L\t/CA:g\u000eڷ,,oI\fO\u0007hT<-!6`ϋō׎)\u0019\u0006%cYw}t\u000fݡpH\nTvt\u0007Of\u0016cno{)1軇\u0000\u0007p\r7)0/5'Z-<tړ\u0015m5Ҳl)m/\f>r1\u001d\u0003cfp%t. gh\u0003Qܶ}$CLGuwL\nU5Wce;Pkb<\t\u000f#tX89a\u0015l]Д]A?>]\u00134\u0001}pGޚ\n\u001b~\r]<wQ\u0017[q\u0013Mo^=;3C](h+I\u0019Aj*+\u0000}@\u0000\u0014\u001ej\u0017Gv\u0019\u001cn\u0017lB\u000b<\ngr{}Ĩ]\"˿yW\u000bT\u0018\u0014ZxU\ntg\u0005K\u0011%U:0\n\u0017(1d>5hg\u0015Tŷ\u0014H\u0001?w_?D\u0015Z*i\u0005Һwxҿ\u0010|Z\\͔x}MBK8\rk\u0012\u0011\u0002{wv]4q@DR=\u0010\u00187\u0019?-/\u0010U;\u0000LT=(NhY.DOC\u0018Z]-\u0012(c#\u0017\r\r\u0016:&Y2?eO\u0001_(Q嘨PΏS\u0018%Q0W;)m\u0013G\u001ek\rkY\u0006\u001dzgtmbtjTܬBx[=G\u0012RĠDD\u001e2\u001c|qy\u00167\u00178\u0018\u001b\u0016Mm.q+[F\u00153\u0005\u0011\u0013g9!\u0013b;3\\-S\u001c\u0013LfFb_QuT^\u0017\u0011\u0013LZWčH'#a\u0015C\u001aI\u0013;~\\d\r3ڻ\u001a#\u001ajuT눓4\u0010|\u001fo~H\fkç\u0003PZ_\n+0,E\u0011E\u001d\u0003!\u001b_\u0010/n\\g/l/\u000fEWJ7;\f/3\"k='s$N\u0017֑zd.&~\\܅q??\u0018\u0004ˍ\u0019\u001e)3!\to>\u0015Q\u0017J\f؀F偉DӾӮ&99\u0003\u001bZE\u0001AN^.|gu#<E佝T.)/=ŠOˏ1AO\u0019~\u001aS}*?\u0019~˯'p\u001av\u001a\u000bl<{\u000bO\u0018|[9\u0014\u0018A_~\u00154\u0006f?0co6_wFºӡ\u001c^\u0013\u0001v˷=}Wc~\u0019i&ip\u00197u{N\u0006nTvБYj\u0011\u0017OY\u0012\u0007FӼ3)5+\u0001\u0000}>.{\u0019.Yau\u0019L\u000ev5>\u000fyWMu`SH.\\kÄy{\fg\u0011t).\ne6\u001a}\n]\b\u001e0ɖTrRN\u001ab\u0000}#|\u0011pg%*;ݐ{w\u0005d?<\u000f\u0001L\u0006\u001eK\b*;y)ʧV\u001d/kaZ\u0012}l#ըS\fn\u000b\u0017uR\u001d7N\u001f6R\u0012\u001b\u000e*Ts=ĠI\t0\u0015\u000bZN;#=87T3׃Gy(\\Z.N\ty#~w6s<AbP1)\b`Z\fS1b)t\u0014]'\u0016v.rL,\u001ezg\u0014\u0014$b0x̭qe\u0011\u0018s>Qqjcy(!/`nƣހ\u0000<O]>7^ͮ%#>E;7'= >\u0011O1H+pK~(l@=W]m\u0005d\r\u0000\b]@D/\u000b0K$e\u0014//e}\u0005svXuoV+nJ[67gr RRY3H$\u0012\u0002şG\u000e\\>6?-Q.>\u0005>wf$. o=\u000eN+K\u001e3p(]Rvf6Jՠ~\u0010\f{\u0014CȥͫNY\"oŐ_)g'\u0004>yޢ#\u0011toѹӟ\u0007/l!q\u0012itEdUa\u001b\u0018ħnB1kC\nɈ_#œ>k}t\u0017\"\u0018JS*W\u000f7n:t˗*;\u001e\u001eh\u0004k|)#\u001e\u0017;0\b<#\u0013[szM}2JT\u00032x\u0012/Z$\u001f~\u0007R\nx`|Vf]T\u001di޽Û wݧd5}rstv\u0016[\u0018WY\n#<$9\rx.KU\u001d]\u001du7kpdݦQx}Z}R\u0001~\u0005TGۨ\u0005-ـ3'\\#\u000b9(ln)[\t\u0007++]\r4c\u001b$\u001c\u0018k_\u0016K%Mĳ5>YyHJ~|\\F&);`\u001c^\b\u0011ki3<I\b;QrU9\u000e0Sn]\t\fkv\u001d\u0015\f\u0017\u000eMD\u0013\"p\t6|ID\u00150F\u0005F;iȢh溻Jl,\u0000eY֩^\u001dRLF^M\u001c%\nJ<s\u000eB&\u0002+\nO]J+Lc$\u0006}PTN\u0019\u0010f?\u001cT#<7Q;WQ6}WY\f\\A>^-\u0012&\u0007`@\u0007\u0001\u0010\\j~3F7Dqf\b-/b_3\u000f/jj8\u0007SqXCeY{l\u0016\u001eH\u0018+`\u0006kP$h\u0011g\\ \u0015>\u0015ZڪT\u0013\u0012U3ȹYת8Y5φ\u001bKpG9Bu$\u0005_$`p\u000f\u0015\r\u0001t\u001f{.\\k\u0011\u000e\u000f\u0010HE@pT&ľz{SF\t|}5Ihc^\u001c\b-נ0tm\nUWfZnq`/\u0006\u0003C߅Gu\u0013<W!{[?\u0006K&\u00110*nW\u001eT\u0019Z(\u0017z$d?f\u001d\bp첷9q\u0019\u0013&\frNZ\u0003V\u0005\"hS\"\u001a\u00134%1軇+nzJ/\u001f#I\u0017r2\u001eL\u0015:|ԝ3yoD#;nT\u0005GI\u000b3WkA/w\u001d=g}f\u001e*\u0011R+cxĠ4|\u001d\u00131A?\u0019~\u001a\u0013\u0015~\u0002\u0013{\u0016?0co6\u00033\u0006f3\u0006fޗg\u0007&k\u0007&w\u0019~A9q\u0000@M1*7\u0000x\u0006S{l\nSP\u0012\f7WP*ZsF\u0006ēv;{>=nȆn؀;XY\u001b\u00119\u001cF%\b0sxW\u000ewd Krx}rLԆy\u0015k\u001ezu\u001f0T=%zfnJ\\Ҫ8ocA?>'(\u000f:\u0001e\u0014^IyM\u0003\u0000jAS\u0018\u001fG!XY\u001d0\u0003|m\u0016.ZǺm{rVlW\u0012\u0005!H\"q\bHǷ\t\u0000l2UpyM쥸7NA\u001c\u001f坃X:2\u000eǆ\u0018\u001dfk\u001e\u000fvQp\b\bnVER\u0002%-C\u000e1c/\u00034*!+ܖ{tz^B5wAXO p\u0006F\u001d\u001do\"8q/.:DJMwyq\r['N\u0004;qOnw`|Bbw\u000f\u0007EF͹3\u0013:¤Q*Ǒ=V\u0014\u0007<κ΄Zmޕ0>_HV˦u9]9ٶ\u001cv6\u0018,jk?#\u0000}7W\u0000zn\u001eZ\u00073c'=ĐEP^[&#7ۡ:\u001e\u0017y\u00118B?:|<=i]pi]2h>$\u0006%\u000b\u0014Rw>*?:ǻߨ=/K)8{ki\u0000'}\b\u0011[Ψ 퉩ڛ\u000eV3\r1߿;ҨϞ)\u0002\u001bT5\u0013ꟕ\u0018V}\u000fmطr7iz$Fv\u0007ӡaa<0h~Q\u0012}KQlၗ;\u0018c,\r<\u000eK`d\u0006Deq\u0005@\u0005s+$\u001bm>A&4/0?\twЌ{R2qKgS\u00187:k$yƱf&sfgb&\u0011^_\u0012\t\u00010@\u001e\u000b٨\u001d\u000fK>n\u0011V\u0006+k=\u001e\\\u000f\u0014>uҒ˳ai-5n+L1k!H1\u0019\u001b\u001dqڳ$h;\u00008|xG/2W\u0015\u0013;>Y5kQjk\nCFa\u000fQH\n6^SjJ\u001c\"j4\u0014\u00035g$*\u000fG**\u0006XT#$r1^}:\u000ete#n\u0019\u0017\u00049Il8#m\u0019œv'\u0005ƔA\rNFs\u0001CbзZ+\u0000t\u0005P\u0007\u001cRQ5i\u000fON\u0005\u0017%.\u001dSt\u001b+0\fsP+p;77\u001fDԞS\u0010lC%\u00016_۽܏'\fu\u0000:+\u0013Qu)j;ʫGҤjQs?uԠmaWcG\\.\f1\u0014.4L)2\\D\u0014dK{\u0015.\u0011C\u0000jh\u001fً*>\u0016U@Δ\u001cN`UC\u001bgiR*](\u0014YkJ6.qA5i\u001e#\u001cJH\u001dB%<eT\u0017EW\u0003\u0001]K@ľw\u001f\u0012U \u000eԎ\"\u00140E\u0015^֔et'\u0017\u0014_\u000fYijPR-BƠuA2%\u0012nO[\u00145\u0013\u0014-t\u0019Q\u0012\fDYKA\u001fR\u0000x\u0017JC\u001fm>JZMrV>e8Q\\=\\j\u001c&\u00165blZxzocڤ\"H\u0016\u000ew1hU\u000b\u0001\u0010n3\u0012U\u001b\u0018-Y?f\u001d>{\u0011vIBAglE.뻘1D:N`Of\u0011\u001cjT\\QݰҒoJ˖BW\u0016\u0002 ]w\u0012~|C\u0004w.B9\u001c\f|)\\bQY`IR fL|tB1\u001a \u001ar]5{\fZrc\u0011RV\u00130.\u000eK\u0010*\u0005\u0007|Fdyu>Ro}3)O~=)bD\u0006-1X)\b\u0015j[1\u0016PৗvqqtwOy\u000e\to\u0019lMYv\u0003LU?#~n̚l\u0005T\u0017f>y\u0019\u0013\u000b\u0007WK\\+W\u0001b\u0017ۧ\u0013b 磤838_NZ\b\u0014ͱiqj\u0013g+\t\u001e.IY?\u0018>~ӫ\\};\u0019sFԙt0F6VAي\u0007\u0018\n9_/gf\u0005b\u0007>qET_;*\u0006=Vte\r\u0017\u0010(ŷlF@\n\u0007\u001d%kQJ(Opw\u0016:\r(He\u000f=7?Vݘ;\u001d\u00106k\u0018xO5haZ?JѫY\u0016_7O_\u0007'0AA_>\u000b\t\u0018Ӡ|[\"kA\u001f\u0017\u001a\t`~\u0019~KT\u0015\u001c7{2xT//{\n hUqk~^椝|D\u001bs\tȖM\u0003'~Z!G<7\u001b4O|x\u001a\u0003\u001f\u0012BEJV)dy]o\fk,TJ1y\u0018\u0014nz)\\N9PQ!NG}=ZP\u0015G׎5^\u000f&`φH\u0002_\u001a ^\u001d\u001f\u000b \u0002}\u001av\".cT2չ|VH\u0006+]\nrD\u001f\u0017S߶p{rk|\\*r(\u0007\u0002P\u001aw4\u0006z9;\t.P\u0017HiWG\u0007de\u0010Q=B-\u0019{\u00172\u0014o\tBK\\\u0013^xA\u0006B\u0013G'1[Q<,\u0001ɃQ-\u0015\\N]y\u0017\u0005O\r\u001bHnG.#\u001bo0\u001dWw\u0019#<O\u0018\u0014^s:&zyZz:q\u0005~L\u0016gDow14\bk\u0004@=>zgWEz\u000ev>+YBgCޫ-;KG2觗{kN^wI8}>OSQVZ#{\u0015_X5,cJI\u001dX{w7C⮜=Kq:\nL瞝uA\u001f\u001b\u0000Z\u0000#\u0011Rw}\f2z\u0018buע\nxfvjge=;\r\u0013o\u001d9iZΙymJ\u00193S6\fv:X\n;}wRD*?\u0003RYyw6MĠ4M:\u001eq\ng`bN4^9wsmIiNPUۋ\u0014\u0004@lԘŤ0TIĠ\u001eK\u0001ZWX\u001bmTbO!۰+\u0006\u0019B\\\tty%yʋN\u001e\u0018cjVB-t\u0015\u000b/skˆN[N\u0017L9P\u0017|\u00172Q\u0005OOܶz)tr33;\u000bNk\u0007rRQ\u000f\u0016ۢ]\u0017pO\u0005NW6̡Ҩ5Wjd|\u001aٻ5մ)\u001cw\u0019#9Ѩ\u00170eT\\\u000f/8BN7%\u000bB&\u0013#J\u000e\b\u001b~K|BYƌ;,=~M)\u0014\u00065l6J\fqW>W\u0015\u000b08;\u0000(9\u000fH|N;\fFUD4TWBح\u0017N\f(\u00132\\N:EM!Ă&AåF#c#K\u0001pM㻤7\u0004@\u001d!&cT5;P\u0014An}y\u0013:c;4\u0010F\u0007O\u000bS]sEvMW\u000bIC\u0012l\n\u0019$.\u001eչw-6i_\u0007\u001fi\u000e戏#zL;'1qYܖҢޡ%w-ʀ!*ifb\u000etÈ8YŰz \u0011+HI+GW\u000e\b\u001fK\f!\u0000Z\u0003\u0000t\"DU)4B\u0012A~Ly([?.Vűq]m*ܼ\u0006BG\"AK\u0018ۈ7\u0014W\u0006ex\rA\u0014G\"%\fcWI-K\u0001f7?0?RILj\u001f4\u001dיB[^ā\u001b+w`n^s\u000fݮDo0!o}\u0016\u0007c^JL|\u0001Y\u0010o\u0014\u001e.l\"Z XC[# \u0012Wd\u0005W\u0005\u0007/2<;\u0007]\buf3x(\u0018$1\u0013.'Lۯ\"[\u001a\u0006uG5G\u001bӐ\u0018\u0017\u0018'J\rg\bU\u001bpU!'߭QY\u001f\u0001P],Dk<w\u0015,˅;.\t5\u000e{l%_|<Y`\\#HR͓X#vJ\u000bF\u0007e\u0018\u0016n\u001eWj\u0007t5^6ux\u000e\u00140*G\u0007ҫV\fr5P\r*\u000eRw<\r\u001fuq^LH\u000e=\u0011\"R\u001fEhvRF[,B6\u0017\u000eF}w\u0006\u001f\u0012D\u0014ڗ*?,\".j\u0001Q\u0016QcVKYbṇ@\u0011G$xed\u0017\u0002F\u0016=hUNq*]PĠ4`68Kaʖ]DnP8OD9}]\u000f;\u001b\u0019IŐANyD޲}\rކ\bB\u001f bqq+\u000381OL+ҳ[K*F=|\\\u0006Ǎ<exl~\\)\u001er$~h78IiŖNeA`^9\rL̡\u0005q75'CrK@V1Ġ4X\u001easG8Ut\u0013\u0018;mf>f%\\\u0005q\u000b\u0007CI&EAY8\r|{En?ٲHSkMv?-Z{%\u0014'DjyT6\u0013k|\u000f|Ib_=|\u0019\u001ddڭ\u001a\u0007\u0007no]K. \u001fkw\\\rm\tbԾi\u0019\t90ȱRcMFHq\\o\\\tmsy\u0018{Vqu\u00174g藺[S?]v\u0016YQPsa<\u0018_\u001eU'#\u001eOG\u001e\u001e޵b(jS^\"'\u0003$\u0006|\u000fAjD1\"D\u0019\u00150*2\u000b\u0012A.[8zZ,I\u001em\u0006}\u0014\u0019pMG\n[ޗ\u0005)vڛ\u001f\f\u0007\b\u000f+~:|`X\u001e%A\u001f\u0001\u0004f\fiO`+ς~\u0002\f'0co6f?0V?0co6S\r\u001a\u0004ZD\u0001A\u0005T\u001d`n,I\u0001|` SC2\u0000=\u000f\f\u001f4~8,W\u0006=\u0003Pj\u0014\u001fCvxEb\f\u0018u&*O*Y\u0000ogɝ^St>`Z@h8ZТ)0T\u000f\u0007B\u000eK1\r;1\f늜\rt\b\f+K\nRCP\u0012\u000f\u0002wp#tp\nȑ/\u0012=Wm\u001c8p\u001a\u001fD\u000bҧ\u001dUO\r{43\r8vRwpѝ5\u0012&\bJ\f\";\u0017\u0007\u0000P__Ga\u0010G]k\u0011/\u00079MyA\u001a?n9c'H2u\u001dV\u000ef\u000eC*\u001e\f8nu\tuӼx=R{߁\u0019ߑu\u0003$88^]\u0018\n\u0012\u001e^s:J\u0015\u001fݳ\u001b]gn\u001dǨeI$\u0006D\u00021#v\u001dxT.zuيT^\u0001Hyl EN%*\u0003\u0014\fG\u0019]\u0016\n*$tI_\u000fwV3\u001ewzOۻ|k\u0015M=~\u0013\u0012\fN>`\u001am79˖Ht}C%\u0006}&\u0001(>x1\u0002PE4}3J7}}\u0015_3]sӅIνqӐL>P\rvQ5f~Fa:k*\u001dzct!{>\u001fV\nCGx[ [;\u0013ҷy.\u0007_z4?7$v'\u000eFNDu\u0012nV8H+[LObm|(}&sƠ͗$*\u0007AZ'JTmdԭ\u0006ӿXWt\u0011N~h7\u000b^\u0002ʩõ҇\u001a/a]4oNx\u00037\u0012YUsԖ\u0013\u0012w\u0017\u0007 S\u0000k]a\u000fcjVJ=g\u0017=CY>5\u0017P>;85YK.\u0016\tPaWpI2RcdöHu\u0013|\u0002\u000e+$ݩ\u001cUqeӷ\b\u0013AKw\u001aoγ\u001e'M\u0011m@:`\u0012[QaC\u0018\u001f\u001587\u001b$c\f&\fm{\"\u001f\rK\u0000$?$\u0006\tJ#\u0018V7.\u0004\u001fĉE\u0015\u001cj;?\u001a\u0002L/l3#\u0017GH\u0018dx~\u001fj+xq\u000ba.=iL4\"ה\u0014E5qĠ\u000eZ\u0017;\u0007G\"sl\u001bU\u0012TJ:\tBFeX.s-gp4㦷֔)L9U+FK)\b$.I\u0011\u0012=\u0016\ba_?1[IpM\u0012F. bn1(X,Gzۍoù|J~\"8>\u0016̈\u001f\u0011l\u001f#Ɏ'p9_bSFzyŦ9K@.\rߕ\u0000]-04˨ZP6Qso0h\bSm\u001f\u0006z1CEi\u00184\u0003aRV\u00145Ȯ\u0013\rl4B\u0017Jb '­ t%A\u001f\u0005w\t%\u0000\u0017&\u0018yT]L\u0019יy\r%ܧl\u001bokCґ\u001dx[M\u000e{-x{h~y~9AKJ\u000b-K=Vn$~]xr\u001aU\u000f!s{\u001a\u0007po\u0006y\u0012atR]\\Ɩu\u0006?/\u0012u\\4!D]q⚃=\\}̣',TĠoCr}*K\u0015>~-x`8Ŷwh\tnBյAFbRn^N\u0005]K1h\rb9x@*\u0015(n\u000e\u0016\u001d3R\u001fLZ||\u0004`p¯\u0013XQUoh5S\u001b.8v3N}y=BaFm:ӎ%(ILY\u0016[NyAႛ%]O\u000732<hw&gHsy1_\u0017@]a]M\u0014r d\\Q?\u0017\u0005z{5*I\u001fNL}\u0013P\u0001{`yˏ#nvZQB*lB%x[o/DXjvI9S[\u0012{C\u0005d\u000b@(GlEၕ{}%_B631uzF(\u0004KϽ-'\u001cM8<\u0014|w2TBi\u0016SC.w. e=W\u0006)cٮ\u0007\u0003QvJ%~$B֜0Lsج\u001dc\u000eF\\1l/;o3<v\\<\u001a3]f\u0016jT\flv\u0015\u0005>\u001d)z\u0019R\u001d1I(a\u000f+Gz[msՁN4+k<U9:˛fJmqk?W\u0003ߜ:kβqjӴ\u0010ɑlOcLRJ\f`\u0017gV40{HBf\u0000\u0002Ӳ.ψ0^v(rIfZXÓb=K9f|aj{po9-XyⰄ2L\u000e1m\u001fuw\u001ci&ۗm$=-q\u0018%r\u001d0f%>\u0001\u0015h䆈_Ac!Ƅg`9$2!\u00166-9'J(;K~Ծ\fa\fؖ=\u00072A4oh_\u0017ө^]-\u001e\fuX\bC3l>Bǜ\u0001!lm^]R#\u0006͗BgTd}\u000eƌ\u00183\u001euKJ(^\t%ܚLr T_\u000e\u001fK\fV\u0015\n\\J\u0006`D\f\u0016$g\u0001LGZ㲘B6LcJ9?NvK\u0013\u001d,4\u0006IhO#h?/~Y\u000e\u00101{|I%*΄IT\u0015!޵p0J%\u001eO&sk0Pt\u001cxGwv.!mm\u0010)a)=\n\u001d=v~ԛ-ZM\u0016w=hO\u001d{P\u0003+@\u0010\u0012\u001f\u00049ς~uO`Ơ\u0006\u0004{\u001aj?0co6\u0007輮\u0003m\u00160\"\u000b(tr\u0001\u001b'\u001e3y\u0000^t2\f>RoLy;A7a|\u001c)&؏uk\u000e?@\u000b{*3쟀pnFqɟ$Q\u0011M\"5\u00189@xc}z|$\u0000W3DV4qy\b\u0003\u0019qifH8\\%B}\u0007dޒÄaɬcN\u0000\b7iއo\u000fAX\"oޠ?\u0003Pt=ڂt4\u0000&\u0006($\u0010S*zUN.}Y\u0012N\u00121ǞVYݶ2Cwk\u001cGy'g%\u0006}l\u0000\u0015`*(ɳQ9t0UjD\u0000m=)OO|\u0011u:!mG\nAmkMZם\u0014.\u0007s1\b0fC\u0003M뷽y-6wI~aET\u0012`)E\u0000s^\u00043ȫV|\u000e<;\u0015cX\u001f\u0014cK\u001c-XJ\u000exJ^TsM3M.C\u0001/Vti)Nտ$\u0006[wv\bB)N??2<D-t\u0017J\u0000A%Ɏ\nrٔOƠ}_\u00026\u0007@\u00075dO PuW:i_y&\u000f4ckʊ/{<pTtp\u001bu\u0000\u0012G %yRQQL2ıU\rBs9.+׷e(S_\u0018\u0016^=7MȪ WJ\u00009\u0001zm/Vix\u0004<G_!U-T\u00140#?C1{{r`w#\u0019ey\u001c^v`Qq\t\u000fJ\\0֘ҡ<oK~\u0011NV-sH\fV_\u0012\u0015\u00058#\u0000\u0016K\u001b0t\u001fUpvgLb^%?si3pgsne3AX\to\rVaix\fV\u001dߖ2-֒(\u0004\u0007doI/p\u0017\u0003\u0007nPx\u000f\u0012QeFQE\r\u0013T򖿔ډh\u0003{\u000f\u0007,G\u001aWG녎e@OG:\\R\u001e/\u0004\u000fN\u0018XY\be9F/̗$*%K\u0006[<\u0018z?kxT7 \u001d[T\u0018\u0014d[#h\\ʙ,=UR]LQ\u001bnx?\u001bw\u0005;\tfQByڄ\u001b,\u001a\f7%\u0006}~\u0007eXT9jGou\u0017ԙ~li8\u0010\u0004?Ϧ\u0002TNp>y\u0013\u000e\u001f]v?\u000f\u001c\u0012M<XQUDωY\u0001\u0005$+_\u001cȗO]y\u001f\twwg\u001f:]L\u0017<NxjW\u0007jM\u001dGrM.UI|t\u0019Y!h0wjU\u001a\u00137$guhM\u001f/IT*\u0001hQ~[.Qtj\u0003ϧHTm\u000604\\+;fI0W\u000e\u0014`к!3v̔\u0005\u00119\bUhԨ\"Bť<4X\r\u0014hD[e\u001f\u0001}Aj;h\u001dD\u0015\u000e@*2M\n$7}t\u000erq[9U\\2rkyn_\u0013L/|iEB,jxbpoZx\u001c\"q\u001ase\u0012K;_*.8o\u0013\u0012Z,\u001f8_Ul#_6c,PkTn'mN4\fWiƺ3k_\u001cfmffⳈX[\b]\t׫wjU\u0016`\u0016C\nmDq\u001dJ\u0004!&lD\u0001w`\u001d\u0018k\"әzn6@O%tn^&Y\u0013*'(zL\u0012R;4)<_ʂ%\u0016mX<JHzRw',1\u001f\rR~Bp\u0002x^FU/Re1}>u<\u001eu;{\u000bEa9c^~BT\u0007e\u001363faݞ)G~2wb̳|>/ITb_#Q3- \u0010L壃B}e.rh`\u000by\u0017RrT\u0015+ tÌ|G*W?Zl8\t\u000fgf\u001fS92X\u000e\tn&7\u0014|Vºُzs\u0019̜U=\u0007\b+cףXuYRuT!?E-Ky\u0007;<jg_\u00078TFɮDnj4_,t'3\u0001sp\u0018~T0仂Պ(\b|ɾg#4zd&\rs\u000fZȤmi$\u001d9~U\f9:R/\u001d\u001fmg*-'!lP\u0011\u0015E:;\u0010A\u0004E\u0011^dVe\u001c[ߨ?\u0013F̳^Db\u0007o`\u0013\u001aw1Y\n\u0001Gim*ύH+j&k\u0003\u0004PʛsPn\t\u0016\u001d\\Up\u0006{$8mbh.WO*p\u000b.\u0012t#\b0؞gh\u0005u\u0004\u0019r|&܇\u001f4[%S(yXN\u0017\u0012_\u0007(M\u000b\u0018&\u0006\u001dQ{([\u0019}ݮ3\u000bǺ5R|<Q8ul\u0017\u0001W)ٝkauGəgw!]v\u0004l\r̢\u0003L\u00032c*\u0014\t\u0005\u00064ynr^\u0018c6#+ZiJM{9\u001cK1\u001a5TO\u001an\u000e)oMz\u001e\u001f]ѹ,G[q\u00158OfSn\u0004%\u0019\u0019\"MH#<U\u001eK&^#Jӽ\u001cu\fR\u0012\u001a\u000e\u0004>-\u0015|B8J\rd\f\t%{Cdj9z6\be,i\nb\tI\u0002\u001aaP\u001bSG@\\B\u0002[?រu\"nfP\u000boXZ1@R4._4DК0\u001bzѳ-oF-&:U6\u001fisG^\u001eMU!\u001dy1sIN\u0017Ћ\u000e\"\u001ayhp\u0011`{i݉w:\u0000t$i踚LCG\"\u001f{πG\u000f\u00017oSl\u0019ea4K1PT,ֿDO:qҧIg\u0013\bn\"Ѓ\"6n\u0011vGi[:m\u001bB\u0019+`\"\u0003AN-f{W;R\u001f\u000bSSt\u001bG\u0012k<ۗn]Ld[&*?7\u0018w%bNC\u0002ҿ\u0000ڦ\u0000:!\u0002\u0001<\u00000[\rN_\b>me\u001eq\u0014Me[\u000b8hxC[&\u0010\u000fш\u001eXD̜[pƠrJrpJ\u0002wx8>nel'\tgJ\u000f4\f?\u0015f\u0002E@c\u001fh§\u0003ߧO\u0000'E[M3(jm{^}Ǿ!gLn[\u000f2&g?\u0001\u0019c^śܴ)y\u0019)m\nki\u0014M{z ~e\t9\u0000\u0018ea_Q\t`\u0006^\u0004\u0010&$\n\tclq99@\u0019,\u001d?\u0011^Vo#\u000b\u0013KʶIj\fKn;v݆彺a%u;\u0000{(\u0005\u0003O\u0000\u000ewv\u0000k\u001d\u001c͙\u0007xd6jŐ?\u0001\u001auS\u00055mmG'\u00198\u001bgs{aג}]~k'A4\u001e)\u00006\u0000SX5k7GΠ?m\u00063(v\u0011HޝV6\u0002Yt<\\R΄\u00063F_\u001b\u0018Lg$\u0007i99Xf[?ş|\u0006&\u0000־i\n\u00049?\u001bH\u0013\u0004\u0012n?\f\u0000E(\u0016-\u0018J>e \u0017׍z{8R\u0015ďs[8\u0017~pQa!+\u0012\n\u0000\u000ed\u0000RPvA/8@)ي4BB\u0016A\u0005ɳl-eS\u0019=Я[{R`\u000f)K\ns\u000fo.ѫ}dS^Z\u001d9XB@zˠ7\u000b{Hxȭ\u0015-W\u0019[~+\n\u000b8\u0014gvfhoF~4\f&cnr\u001c\u0006gW~?E]\u001dU{D4}upx98[bYdt1[Nnjn\u00159Ϯ;q#Z^m+`^ץ%݆\u001eU1[\u001e\t{)!ZL\u001f\u0003[\u0012\u0014}O?\u001cx\u00114AMkVrZrT\u001fÌI7ˀli18~ד`S:c]T򫕗3U-df*%}?ş\fM{AjMA2ո?ғE[\u001bt7vg\u000e\u0010߷g|ivpD\u001a՚SF\\y-S\u0019f/;S.%_\u001f\u0000:\u0016*~}k\u0016~L=Sz.z\u001dJ0[xDOl-e.\u001c~)o]WWn\u00153-.z)J+ςB,Sdɏ2R>[Xd\u0018&\"\u0002/\u0002\u00036\u0019\nCtVz̿YخL7݁3?c̤gf9jҨJŢbR\u00198\\\u001c%ɞ-9O\u0001\r+U\u001e\bԜ~6(K8?\tz= ,[2q^w_{\"\u0000#\\\u0001Z~\nBA>G\\\u0012l&MD+!N uS\u001d@Ѡ\u0004Ew%\u0014}x\u0014p 6ެq߫w\u001ewށ\u0015=n¾*n\n?KeRϷVr\u0011_!yNn2i_SmIouy5\u001e\u000br<?\te\u0006{\n*\u0014=l7\bPiB\u00193`Iin\"[6M^OUtm/볿\u000e0-T߫C\u0019H.\u00030{Lj=$x\u0002\u0019g_]q1Wk\fư5)`(:\u00126j\u0000J3Լu=v()&<\u001d̲U_`ָ+nqW\\Gm-'\\ZY(f0&ሿ?\u0007S&!oS^Va\u001bj\\r2\u0012jVVú3x<\nC.W~{\u001enUk753Na{)f\u001fL\u001cӨx,Fػ\nxG\"C_Ζ\u0007EB\u001c|9yt1\u0000߱\u0012g5؊\u0018\u00174\bJ\u0005\"\u0010\u000e:c*\f>!u6pouИGtZ\\i\u0016.˄\u001fo\\9\bwk4\u001ch{\u00028>:N>ǳe@홃\u0002\u0012ag=zVѫǍ\u0010Yw]v\u0012|1'[jx\u0018\u0005$؟6\f}\u001dt*\u001bGɮ5N\u0011|\u0017V6\u0001:\u0003]\u0017\u0000n*\u0004(\u0015(#\u001bl>8^go~_\u001awXߊnafT^ԧtawOp\u0013ke\u0013Za\u0017-7S\u001c^0VZΚlT&\u001cz\n\u0016(u\f*^\u000ff)vv\u0007F@cB>zTGZ6)\u0016ULDN\u001d\\L\u001fU1\\ھ*^N\u001cʜbvZ\u0018L\u0013\b\u001d\u001b\u000e˞\u0000ԅ\u001c@`{:_Vr8\u0013)N\u0002QiW\u000e&,?e\u0003z<ƥTXئ2TZ?2vݑ\u001drb5\u00101\u000b2\u001f2[N\u0015bPO>某@\u0014\u0014\u000f\u0005]fXn\f_h/\u001e+N~*dwM9\u001c\u001d)\u000fM<\u0012kI\u001apwv;%_JW\u0019p\u0013nb*yd\u0002~#2ӪW\u0001ԫP[\u0017(iGP$\u0014\u0018\u0018Ja\u0014\fJ$+&]K1#\u0019\u000ek]bU4U\"*\u0019,\u001eV=w7\u001c;y\u001d\tW|ZZ(>cdr^p(Q\u000f;\u0007\r\u0012Hǐ\u000eW^b?\u0005(\u0013\u000f&8'uR,\u00035:l$<.'Fng\u0015\u0015ﰎ/\fg\u000b[z4?\fxAh#5OY\\P4Q\fInG;]~dLFZ~@__@V\u0010k>U><jmͨ:=덗ޘ=92-\u0000\u001d5WtGZ\u001e~?T96bʝ>y\r/\u0014ˊ|8ӫpS \u001029h̛ܶ}n?\u0005cpcҺQj_\rj\tdY6\\ʋ\tMq^lyŻ\u001av'Γ\r$Q\fs:J\u0019IJjs\r8$_E&6~G{Z#-'VY?Ͷv+X+nB生oC\u0005/lhPᢏ;\u001ao[&Zѹrѭ\u0017\u0002<JD]=6\u001eEP5iP]0bNm糫7\u0003n*ܕ=\u0012_[)^\u000fW̤7RfU>{P|T0mt\u001a=a\u0000q~m}(\u000b>FOH\\b=lݕx*ކpWގOo\u0006뱩KHFd\u0010\u0000}\u00034n@!c\u0000;\u00009>18x\u0000=(GU,x\u001e0O\"vw!\u0006]z\u00100ŗ\u0010$Q酿57>\u0017\f~FT\u001dp{9̭~\u0015f\u0002E`@\u0013`S?5M\u0000\r:(\u0010\u001c`\u000b\b5\u000b}\u0017L\u0004<$T\u001e\u0016\u0019ʣj5ͧ;&x\u0001E \u0019Gf~\u0017M>i2xгm^W9\u0001{B\nA8h²\u0000\u001f\\\u00048\u0001ZV\u0000v-5Ӧ'Ps]Eft\u001fmYXHq\"i:Hq]\u000e\u0013?_d\u001a\u0005k\u0003wJ}\"\u0002\u000f\u0000#V?Eu(\u0003/%p2=\u0014h\u001e\u0000mzRV&\"p\u0007\u000f_¨\u0016|(\u0011hD&q^,ߘz\u0003PA3%\u0010/gWrw.t<#<\u0018?\u0000(4mI\b\rX5ik\u0000߿^m\\|8\u0002<?\n^%V7q\u0007\u000b_\u001b\u0016l_VD\u001c\u0007!Byy|vOrOvpu=0[z)rƪ\u0006e\u0017\u0012_?Ei\u0013>Q\u001c=@1W\u0016\\T|=nW)A,PsB}#U\u0003]#a{1\u0011\u0018z\u0003.紸puj77lާ)I\u001d,gFm튦\u0000߯e\u0015%\u0001+',\u0005\u0014PT8\bS=Bčp~\u001f\f\u000bӢ\u0016pZϊGCS]\u001d큆ֵ\ngwQMT'ؚJ\u0000\u0014F \u0006\u0005e\u0006{Y\u0001<:ĠCXP@M{2=1QA\u0007߁7~>\\1l״!0g.ɺ6\u0019i|:%\u0005\u001aޠimr21P6Gt9۠`\u0017\u0012\n\u0002t<AHg\u0015?o<tS{\u001c\n}\u001cn\u0017ǦpQэJ:\u0004/\u0013z-\u001fݽ~ć\ni91Z*/d[v\u0006U\u0006$\u001c'K^ڟ5@0Y\t>=a&ZEC ͻmߙSK7~$OB\u001f\u001c&O>gՉ$nFMua$;Nͱ&/\u0012ۥ$MF{\u000f\u0000\u001d\u000b/P\b\u000e'(41(T:wն5\u001fz\u0001y89չ̻x:wgo3\u001dh!F栛(Ũk\f#QՎR\u000fV\u0000P\n\n\"\u0014xk:(\u0006__}/Haɮ=mu\"x~*\u000e\u0014\u000e~\u001e՟.2Zz/y-,%5.\u001d*9B3#\u001dZJfe\f\u0016VG\u0000hb$\u0005\u0010kB#4\u000b\u001dgP(\u000f9\u0004#t|wۆYxO\u00079\u001b=w6\u0015gy=\u001aWRK\u0006͠J7-\u0001-r>\u000f#&]\b'ϼ\u000e\u0000\u0017hPL:|\f<v\u001c-#~QE\u0017\u000erZqtv~:!]f9m.gqTUun:TC[qF\u001ac|>6μfN\u0016tgc+\u0012\n\u0014\u0017)PlJcX\u000fPzyPVv}:iWmf(\u0011>4g\u0019L-\u000fV\u001bګm\u000e&Qo~\u000eoÓ\\1sgS\u0011vnM\u001e%\u0003b\u0013I\u0001v$`<GtA]!)s/W\u001a4\"z\u0001VE-ݐF>U4\\묵6F>\u0016\u001ds+\u000ewj;ϟ4ֱ?\u001d:~\u001aS\tD]\u001ab\u0013\u0000\f>\u0000{q\f(n_Z\u0003P!3p\u001bGzkӌvtZ\baK:,}LEP7w\u0002V\u000f7V3]1G\u0013k\u001a2ɋ\u0004P>6VP7\u0011bFh\u0017#\u001dqOE\u0002\u000fQ,BQ߁\u000e;j&|!\u001c\u0015o;k+ݓcGwI\u0018B\nzU4rRt^ϝO^n+m\u000e΃إH|W(\u001eO~|6kv\u0011č\u0011.O\u0000\u0000\tI\u0014\u0006\u001d(#+\u0017TRd\u00026\npD]1\u001bW\u001c=\u00107ӟȇ6_Ӆ<KiTTiA\u001f\r\u001bcZ3'l\fJ\r޶@j?\u00001\u00145\u001c%(=ٯ\u001e?!m3ex'¢sm\u0018a\u0004vuZZ8\u000bV0ba;N\u0014XCOr.\u0017tJ:u}A\u001e\t\u0005`C9\u0005\u0000\u000e\u00065\u000f=䗎۪\\pX맳\u000bf\u0003\u0005/%c&ӭ2\u0015\u0018.Էw\r֙xHru\u0002qvJw{\u0005\u0003\u0000lƎw3g֠R\u0007V2W׾݆|9\u0011R\u0006R2JԞX\u0001Y懝\u0007Sob́x#a\u0017vGC;\u000f\u000f'V*\u001eL_IfFLP\u0019;qlsد\u00010΂\u001bNcaj$u{\u001eʧ`QYÁ\u001d.H\u0005!0&dpL\u0019rR8AN]\u0006CrW\u0017b7\u001eDej]=3n',E\u0013TH7\u0011v\u001f;Se\rAD ?Sʇ:\u0005 1\u0011Zei\u0015a\u0000ҔUr1ޮj\fG;\"\n3֑KWmVw(v/λ/w]\u0007(6&p0\u001cn}\"\u0013\u00103i.u-\u0013\u001af(\u001e\u0017\\1&h/\fwCvn\u0013\u0018U\u0014\nTr[*(:I\u0007&9&s#T%lz\u000b\u0015}O\u0000\\zYnYt\u001cF\u001frg+\u001f\u001fj\u0017gs\u001c;\":\"?nyj\u000fkD\u0002KypZ^yY̑\u000eҨoȁD\u001c|wڧ\u0012\u0005δTҺ\u0004\u0003rW\u0005\u001f֎{To\u001e^8.m248\u0019^Ϟrcv'9\tg\u0003VcA@Д}(v;a;=\u001b\u0007\u0016I\u0014#QP\u0013H\u001b|FON-ح\u0018\u0013\u0002~{9\u001e\u001b\u0017~ez`\n\u000784ڱ>\u000bYpbͦG>?\u0005+c\u000f\u0001Z&)\u0018s:;Q!\nA/2A\u0007mMڤ@:9!uN!j\u0019\u0015\u0019tO?p.Eywxu&zxd-_E0ܔfF3OKb<R*\u0017y~e2jZ֙>ϱ\u0017.W(wm<[*?N)J>rSV&:Ⱥr\rm\u0010\u000b\rm\u0019\u0000&2\rte\u0019:Ѣy3\"U!+ݻXr4VzT\u001fAʴ}g]rly%jo.~ukh sa@4L>|fL\u0010\u0007\u0003,AO\u0004ӹg\u0016\u0019e̹3ʹd\n0\\CxYhA5!Zuh\u00164ԛihG::z\u001b׌?qǲvj4\u00109B`!S)\u0019\u00052̍\u0004h)0\u0016\u001dPX1\u0005\u0004@_!@\u001cɌ\t:=y>6y.\u0013L q9#qft\u001bDc\u001c\u0000<\f#sz?aɶ+\u0007&S\u001fhE\u00142y\u001a\u00034jB&9Լ9PPs\u0004(PS,\u0000Z/¶\u000f׺\u0012y\rRȳ\u00189x3qE6\"\u000f3hn\u001e^>\f\u001f&=\u0013=\u0014F8\u0006/s3\u0019\u0016>\u000f]N^C\u0002[\u0001\u001f\u001d\u0018M\tA\r\u0003Q\u0000<z\u0000\nyHX<(d\n@\t\u0002FH\u0005<G&7,xJ1k\"\u000b8\u001b\u0019\b^PA`)=Ԥ7w\u0002\u0016`\u0003A=1/Z$(\u0018\u000bE\u0005\u0002\u0005\u0018#_j2\u0002\u0005_\u0002H@Qs_\u0016>\u0012O\u0003\u0016yu5[\u0011$RA8e\u0018=f@y==ea{\u0006\u001f\u0000_O(\rްj\npX^<\u0000\u0001˄\b\n\u000f]\u00032U@\u0012\u000b/\u000f$NL<E\u0011cY\u001eaL\u0016JP\u001dV!+]}\f+G\u0015U4X?b0W$\u0001K\u001dA\u001e?Pv\u0000Fϡ(h\u0000\u0018D\u0000Eh\f#{av5w_\u0006s~d\"ţ0?R\fcU\\\u0000\u000e;\b\u001e3N7հr8g@w\u0003Mb[C\u0013MI\u0001N92Pt\u0000\u001f$\u001a`lS[<\u001fď-v\u000f;Χ\u00140ʱVZϜ7Hk{\"K]oR|Fr4O\u0017\td\u0014\u000f\u0000\n\u0002E+j\u0012\u0014.\u001e\u0003\u0013e\u0017wy\u00042\u0000g3OhiS\b&\u00038V\u0006\u001d`Jn6櫚]\n[\u00184kl7k\\<o_O0\u001e\u001e\t\u0005$v\u0002\u0006X!`7.\u001dF\u001dy\n\u0006:\u0013\u001e\u0003\u000ell?逸z2\u001c]st(ͤVU-є\u0019\u0000\u0000W\u0000Ppa׶cMbb\u0014^rh\u001c*?\u0004Jõe˧\n\u0014~wOGz\u001b\u001eG\u0007\n\u001c8HYUp\u001bkT${n&󭹎\rZ\u001c\u000b\u001b\u001bf\u000f@~]~\u000f(ZPT'\u0000;P4\u001c\u0007*\u000e߽\r1ȝܵS%nڵ͕E6M:\u000b徃%\"C=Fټ_\fFW\u0007\ra6\u001e\u0003M.Vg\u001f;VN\u001agؑ\f\\\u0003E|=D\u0001{M\u0003\u001d2\u0013\"\u001bO\u001d\u001e0\u0019\u001d3W7G>0w`S9\u001aӺlsA},Z{\u0013Mؖg=,\u0019X\u0005\u000f\u0000Ps\u0001\u0005\u0001xy\u0005Evk\u0012.ղv;m\u0013SM\u000f-I[16\u0018֓zZyֈV-RZ=ԕyeDEt\u00169v\u0004?OQ?>(.P\u0012\u001e<j-aύ\u001a}w숙9=<Iv3X}\u000e[pi+Tk+\u001f[lV\u001d/xVv]Xs\u0013lT##\u0017tg~\u0013y+~\u0000؆oIn\u0016Ҿ\u0007ۂCP.s\u0015\u0002]6i>n>}\n鲢В~\u001fg\\cY[2~\"b/\u000bBL]Yn\u0013S/\u0005k\u0007%\n\n14˃P\n^|\u00186ᥐ@׾bNe]d}Cjᦸ\u000bU$4wY,tQ1\u001eôaΤeYo9l!M)\u00045\u0004򷂿\u0000\n2=\u0019c\u0017\u0014}gyV\u001axڝit)F2.vLv0Qz]@#3@G\\o~6/\u001f=ep\u0006I;\u001d,\u0013P\u001838\u0015cب\u0000j\u000ew_-ui\u0013[\u001bE!\bNT(u3\u001b+4\u001d{P\u0012Ʊ\u000e\u0010\u0019\fˮ4-\n>W8%㩤+:Nn[1kO#Tw\u0004\"\u0018\u0015._\u001f_\u001b\u001d\u0003S\u0000l}ߒAi2@y\u0019ߣdzo٧먎_\u0014]ֶE\"[\u00128\u0017\u0016}%\u0006EtQAV]as\u001a¦U+mfoH T\n\n)3F\u000b\u000fswxds\u0005g\u00125\tʺL\r0\u0005l%>/>YbKr_\u001cDoA\u0018ߤOA,\u001bӾ;\tޏ g\u001f\u0000\u0014\rB\u0001\t*k&\u0018Kԟ\u001coG#Ǧ$2#V^Y\u000eUMT;\u001bmǔ\u001a\rV(f8brotv\u0006g\u0002fkr/u\u0018{\u0003\u0002\u0003\\%1P\u001aF[*Qzn{=\f\u0003u\u001b\u0003ǗZ#j\u0017\u00163Sϛb\u0011B*QCBvz\nL\rqg\u0015\u0013+.\u0016\u000f5E5G\u0013\u0012\n@٠i%̑k\u001cKaSNW\u001e͎]0\u0007oo\u0016k(d%;$MJH*Bc5\u0006E\u001e/}=Ci4\u000b5eKLϣ#7\u0007̊\u0017\u001df\u0012^4~\u000f+.(n\u0012(K\b7\u0006!8.G\u0013tu\u000e-\u0012k\"%'\\#5Ez+\u000e^U\u0016OÝq\u0015sJ\u0007SsEEǉ8&R\nǨ3R5F\u0000\u0000G&>(u2\u0014}kf^\u0017N\u001e\u001da\u001e`[s#hZ&%i*\u00036;'\u0006o^0Y\n\r:.֐^^;sjtλt]IwN'\u001d\u0000\u0006\u0004=W\fQYw~\u0005P(N䉼,\u00121eg#W\n\u000f^\u001btO\u0012Jրנ#{5:ZzuOoMܙ\u0015&Qx\u0005hW}2e'dVH\u0007(֬\\R;K\u0017/~\u0013\u001e[fm8NC\"I\u001emjCq\u000eq\u001e\njGX;\fP$t#\u0007jRl\u000bG8۹\u0015]ۄr_,˗\u0013\bQ=\u0010{8P;K{j\r\u001a@=\u000b7N\u0019ԛJb34\u0014*W|\\-o]8'\"F\u001fj&\u001e'0r*#jM.u}F#:\\nHGc\u000bk\u0018+\u0012ȯ˅\u001fs\u001bcD\u00037ug*·)9\u0012,!$\"ɨ]!̨hsc4jdQ\u001f\u000b?wBd_;B}}\bw-#5Xc7\"k\\khMAAuLXWtqn\u0000\u0016H\u0015ŭ\u0000+7'\u0018{^\u0012\u001cǓ|T\u0013ڏBk\f]:sji\u000bT4\u001e9oҚ\u0010ኘwۦh4Ω#Y3wUr-ս<دa`\\4VFz2X}g]|ny6h\u001d%O\u0019\"N\u001eV-֦޸E\u00107F\u0012JfJ胯\u0005Eд<g帬+\u0011/\u0007\u0019+Y+b$צr!VՠƔ}f6\u001c:k\u0016M5\u0015y4^Y\u0014}.T+F0@\u0000f;^9.\u0002#W(h/ڇ[oQTIRݷ?\u0000-\u0015!=o80!Ne\u000e\u000b@k\u0005]Q0\u001am\b#[MAm@=@@ +b9ZE%\u0006u-.;e_hޛ<F}\u0013߬\u0015\u001a\u0015\r$ox\u0003_-z}CQIB\u0002S\u0000EuXi /fQ\u0010@ΒU\u001b,_m\u001a)(Ж)Cquk8\rh<\u001190@O2<\f\u0001X+5-I\u0011(j\u0014:E!\u001f7@A\u0011\u0006\u000bE)g\u0001\u0006s`P\u0018d/H\n6\n#ѪV\u001a\u000bXh\u0011.\u0013H|\u000bxO\u000f~zܹh$m\tY\u001e0m\u001dZm4AB&^B\u00022@US\u0012\b\tK\u00039>4vA\u0001 )!X^|Q{Fyw\u0019?q.\u001c\u0010\u001f¨:F\u000b\\0F\u001fB\u0004\u0000Ek\u0007X9i\u0018.\r\nݜ\n\n\u001d\u0014V\u0012Z%v\u001d\u000fV<\u0002'\u0015T\u000fs\u0015{ Gexg\u0013ȋ'\u000b<G~GY,c\u00114\n\u001b\u00075v\u001eWR)g\u0003l\u0007ȅ\u0014w\u0017H`N_\u000bm6(1,S3p\u0000\u0006V\u0000mC\rV\u0018>3ǯW}\"Oq}s\u00138ӏ\\ك}GiPRmv0\u0013eW\u0002da?\u0001I\u0016#@wo\u0002k\u0000_w\u0015\u001c\u0001\u0018FùJ|Z\u0018tF{V'+v{\\0aT`f\u00071GPۥk\u0004t<\re\u001dk\u0018\u0018M:NGc~\u0018۱U@V\u000b _\u0018n\u0004P~CX\u0003\f\u0003y\u000e`\u001b\t}\u0015(v\u001c-Ѯ\u0011M˯\u0004gbOɪ[`#ݫ\u001f7\u0017nkS/5pl^V=@.mA>\u0013~5\u0005+\u0000?\u000b۬\u0000'_īи!ca2U}\u001308kW\t\u0010³ƚ\u0000yQ\u000fs@kv,<y\u0002{vm{b`zw۽\u00003(?(׀ӹ>+\u001b\u0000\u001ffI5݌:M=\u0012>߆iF\"i,횛\\\u0003Ƹo٬\u00032NZ/>bE.}\u0018\u000f%˾{#\u001a\u001b\u0017tσ)cg\u001b\u0016)\nWP0y\u0018Je\b\u001dˡ㻼\\C^}\"\u0011L\u001bծS.<X9{\u001c)\u000b^\u001fulFNN\u0005Fۦ%:ɤwwW3R`dv}۶Lz\u001eZ\u0007-@+%Q(\u001f_+$\tp\u0012\\XYy\u0015\n\u0004gN\u001b0C>?\u0015ܡp\f>ؓپڎ\u001b#X[ݸon'뼎;j>aĴ&m.r\u0000\u001a[?H\u0000m\u000fAltσ\u0011B\u0006R\u0001gJ\"7sK[}隫>\u001cM]Y/8.χUm<aV:XMBp\u000e\u000e=\u0013\u0012_\u0011\u001c>4\u0014=DM)8q\\\u001fOj2ŒSZmX\u0010o\u0014NvnnNF@\u001d,>\u0011S\u0014WQqY1{py7|k2+r!Ǖ\u000f؆L\u0003=\u0017\u0003O6uhe\u0011\u0002FnMol1>c5\u001b=C|n\u001e\u00190rT\u0016̪F\u0007GKLN\fS\u0017Ff'*//+5\u0017ODufc98\"&\\\u0001E[PW6lC\"(\bC0\u000bty۳;YώND|9p>v\u00170eXյ;:˷8g_/Y[_\u001eN'nST|Mky\u0012wE\bӿ#\u0007k9\u0000/K\u0018AYǈUmcU\u0006۝\u001eYL^fI̮ߞ&u\\\f[e-\f\u000ful*\u0001ّϒKWf>IZJsi/uFMtw \u0006 vIGa\\@Cw\u0013Ae4p{?\\~d\u0018ޔ0Z6J'&5YL-\bԴI{zr\u0018V\u0016\u0010S\u001d\u001d7&\"g vX!]?\u001e r9TP9tW\u000f\u000e=N*o/\u00028\u001fz60\u001dm$\u0010]15pY\\k)%*2\u0019q\u00069\u0011F;jߑ텿՜Ψ0yl:\rӄg\u0003C\u0017Kj\u001eնf\n9\u001e\u001c]|d\b\u0017M\rendstream\rendobj\r51 0 obj\r<</Length 65536>>stream\r\n-{\boE%?U\u000f\\8\r1Pmf(Oė8ϲA\u0010\fO\u0003eWN\u000e\u0005:t[/\u0001;ϔ\t0b\b5\u000f)1nGȿ΂\u0002\u001e`~l<ԭ45!#5mbR3!T\u0018\u00146:QY(͡ws+֕{*{5k^n@t˿\u0002\u001eJ|\brT\u0003e$GJ\u001fsu\\6:ck+<)\u001ct5\u0014\u0005\nxu\u0017}K@F-;\u000f8lQ\u001e\u0018dM+n\u0017hS |\f02\u001f܁\n]d\u001eO~w%#\\w7̅nъdr\t \u001f\u0003q[Z]yCjo\u0015L;m$e5:)˝,iUG\u001a\u001dZ7\u00178e{v53`&^\u001dX,{vu\u0004.zҴ]I߷zv2'\u0006]\u0013Q\u001c㵶\u00164IVR\u0006[\u0012r\\x\rVm*U`Ӆ=ӕFSw7Kt}(Ѯ/ῐ@\u001b\u0000։Ϡ4\u0001(\u0013\u001d8]2ZS6'\u0015v\u0018\u0010\u001bj]X<iQyt߰6P\u00001Z{Eǣ,{G%ffMzqu)NIWe-T˝t}~\u000f=;(T\u0002ٺ`Lsl\u001e~w\u001dy-0\u0010=Ju<z$<V\u001c\u0013DN\u001ab\u001f^\u0006\fqqzւ\u0005/f-'ԃmt\u0003[ä\u001fp'wƖV*%\u0019v\u0001;pu\u0012fϴue\u0019-y:6ӻ(\u001db4G\u0005m\u0012nAgO=t9鮇,tfl\u0014;\u0006juCG\u0002k>FG\u0014gr\u001bߙ94!\u0017nc\\|XNNS3[N7x>R\u000b\u0007\u0006Y=>6'\ti]\u001c\u001d{>tj?Knݱ2~?3oI\u0001U|PI]Hv2i9Z[m֘\n},lr$t\t\u00115\re~\u001b[/\nd,\u000eO {&hfn6Sj\u001cȭ9756r9AmgÔ5\u0018Cfݑ<.^O^\u00166N6$ZP6^2*\u00103h\u0006E6@\u001aꧯ6Xg]/ET\t\u001e\u0002Z,5n1G_9YƓc͋^_j5Z\u0002lݻr&/\u0003(\u001fȝ>fh$ꊛ6\u001erVIڧ4\u0015\u001aڠ΃Bz͘\u001aWZ'B)09\u0003m~P!՞KkK­}tРHGO\fΛ(uE\u001e\u0015$ꄝ]ٱ{`+QI\u0007R1r]\u0017!1f-\nj6\u001c\u0007rs|SղHWۿǦZ.V`We\u0006+Ozơ]OݷK\tc\u001f[w'%dayT`w߾*Qk\u0002;4\u0006OH\u0006\u001d:?kƘ*N^(\u0013M|YQ|\u0019J&W\u00169=4*WI\bg\u0015\f?ָ'\u0016C6X\u0018ןo)+\u0011A\u0013\u000e\u0003\"\u0003\"\u000e(*D\u0017s߽dӕTRU\u0000<͑ؒ*]\u0019{\u0002s఩1d[\u0017`*cO;q^Ɉ6\u0017\u001b,*ػ8_lUsƸ&~?V$7\u00016\u0015U\u0003>{\u0014 \u0006 \u0004\u0010\u0016\u00038g\u0000\u0006vem|\u0006`=T\u0002X\u00006\u0001jO\u000056wʷ\bt\n(]'\u0001Z\u0000ZŇ\u0000%9\u0015^'D0Ϙ\u001c\u0018jՂN\u001bW<\u0000Ҁ\u001eZؼ2\u0005Do`\u0001<\u0012Pc\u0006xفBO_W(U\u0000\u001auPԁj\u0007Tx\u0001tJ Pm\u0000.PfAPd\u001flWn*YQl~g+-;?v;\u0013\u0000[.\u0014\u0011\u000b(U:@S2m@]\u0005\u0010t\u0007n|\u0000,ɹP&xu\u0001f7b\u000eЂjgg\u0014@1\u0000貈C\u0012T{\u0000ӞB\u0014mteͧ>Z|sEh\u001eo(3l\u0007\u0001ހB\u0012\t\u001a\u0000❦\u0001Y\u0019+${\u0012\u0000\"f\u0014\b\u0000Q(/\u00016t\u000fnP\t\u000f@\u0015\u0002j\u0015*_޺ɡP^NY.X!]L֗!AQ^,\tݶ*4u\u0005pm@Sr?Sp\u0004d\u0015\u000f\u0001Ed(\u0010\u0015}\u000b=^BjPAq\u001c'(\u0010J%Rt+v\rK\u0016\u0019tݵۓŭdE*[1\"OWh\u0001]\u0000۸\u0007Ŕ\u0006hc@v\u00068JW\u0001\u0010\u0006\u0000ͦɉ.J^yмWK+JtT\u001du0교\u001a !S,.=:ѯջC:q,͟p2\u00139\u0016*\u001csr\u0003\b=\u0003Ra\bݰ 5y\u000b\u000e\t \u001b\u0012ZvVOrfUb\\YTeg\\\u0002\u0005!\u001b\u0007񷔑A\u00114\u001fI3GEg:f|<z\u0004!`_?\u0001p<cN8]E08~\u000f\u0005ׂ3\u0001 ;`\u0019Qs>OnS\u0001^>.z\u0010ҷ2/wiS 9A:HVߥ\u0015O\u000fj-[kO\u0000pB|W4\u001e\u001aܩt\u0003Y\u0013?>\u001b,ga0oW\u0007/K'\u000fz/\u0017\tQ겄yrs?)v\u001c^yn\bfĴA\u00034L\u0014\u0006\u001b_c>Y+Q\u001d|_\u0016oj+\u0013=y[:$\u0015ڍM-ۮO3Na]$G9v\u0018͡\u001e'˅6-vA\u001f6DeIL\u001a_?\u0001~4\u0007jZߋ/E/6\\VѹpM9'[&\tR>\u0014\u001dDQs\u000f\u0013+eik*Zf<lD4\u0007Ҭ!\u001aGR\u0015c^sJFi\u0016\u0000po \u0012OˉkTc#J\\tm1yp}!'U%\u000fM.kyeu\"ޜɖ\rBbW.󺬊;%x~U\u000fyY{;\u0005ө\u0017\u000f\u0013IbY\u0019W(\u0003B-l\u0017QHN[c~x\u000e<},\u0019\u0003I\r[\b+<o\u0010&jc[*@2So\u0007[y\u000eTqa\u0006|\u0017\u001ds[_\u0010\u0002\u0016\u0006;85'\u001cs\u0002\nTGx=\u001ev\u0017ykߧԩ8\u0002\u001d\b\u0016A43LCחv/\u0006GK8d\u0011՜umw\u0019\u000br\u0003TBP\\\u001bWn\u0019\u0007?\u0001A\u001fBŦr\b\\BEv\u0014?\u0001;{\u000e1e[\u000blC-8\u001cepr<΋LYxW>|<#WGi`\u000e\bp#ӑ*u3j\u000e<~r\u0011FB\u000bB]=/?\u0001lK\u0007]\u0016O\u0005\u0014(|JDWc;v\n\u001d\u0014oQUı\\H'Zw{}\tY\u0016VhK)/҃imN?4Pm'\u0010Kt\u0012g\b\u000f\u000fttЇF\u0011( \u001f\u0003o秵-:jSx^&v/. v[\u0006\u0010Is\u0017i\u0019\u0004s>ɨnB(}X)>\u001f\u00180^q\nԻ\u0019w+4\u0004E\u0000f\u0016_\bR\u0001\u000ej\f\nksw\u001ee\"ۻ2Z}HulrK_)iXўZ*\u0006s\u001exzoW\u000b!\"yvB?:qzRjKe\u0010I\nqC\u0012\u000f\u00194%O5i\u000e7rqv\u0004y~,q([gּ;*W^wO!>lwնMhwBS\u0006V%Uzl\u0012&z$\u0012\u001fM\u0003J5350Un?\u0001d\u0005:\u0013\u000f\u0004\u0014|\u0012A/AFBL\u0007dyG4~\u00155\u0018mu\u001d\u0016\u0004o:\u0011]5>\u001c[<ZAF:vnTU,!u=hh\f\u0017ٛ\u000eۇ\u0003c\u000ey\u0006y\u0003@/\\\u001e\u0012sQN\u0013YA\\mOL}VXw+\r\u0013\u0006D\u001czx<O\u0003:\u001e̗(t+G7L\f\u001b&Sf\u0001,QGlJ,mؔKupj\u0017pm\t@!8\u000b\n;>`4|\"?=~ܻ>cq7xĴYle(>RT\u0016t˖;G8*Hi0&\t\"(۵\u001b\u0001-7Ý\t.x?h8\u0006>\u0007\u0006\u0013\t(@a#Ψ2|v\u001866\u0015'\u001a\nH\u000fEyn]C1s7\u001b;Zx\u0019\u001a\u001d~b<t?spiQquK\u0001\u000e\u001eʧ3M~\u000fO\u0003\t#nv9ƬS{QT:\t8^É^-b\u0019ۖ=K\u0013kI\u00007'+vӝYFMZ\u0018􎖯ej\rw.y\u0019qv\u001bg}5$g3rC\u001cHmd%ԬVIuL>\u001a2,㜏\n%-M\u001d5\u000f}gr{Vf4\u0013F\u0019v\u0015\u000f~]\u000fğc=zS\\qcz\u001fS\u001e[i46ua/לr+=tƧUz \u001f-\u0001ze\u001c\u0015\"9U_2_?3O\u0004}t\u001b+FЩrjg:Fz\u0015Gg˾\u0016L\nK-\u0018\u0004\\-\u0017fgjt*痢FáyEv*\u0016\u000f+\u0019>ӞYȍEK\tA]gȱxy\u0017V]z\u0018?]:+\u0014н\u0016\\L7Zp<jUdt\u0002/j:V\u0003oL*ڟi,Eüktjc@'8\u0012\u0017FJj[Y-儆\u000e!bG\u000bۗMi}\tcȢ\r\rcێ{VV´Yno(@\u001e\u001ecC=A\u0007\u001eŨ'΄ɝmX&5>ΌZDO\u00075>#zA\u0010C*\rlf^\u001cA;f&лRa>0\u0005\fmS.!^\u0002\u0013\u001d\u0012бoYm\u000eNg8bo\u000fFk,kٌPV&%\u001f%s\\z'Ap7>\u0003\u0011{)\u0013]r-v>\\m\u0017ZR-;jԸO\nLGv^HzAkL>\u001bVr3]<|ŞZ\u0015\n\u0016\u0019K'#Q\\5M^#\\N\u000fzvBҝTu5YZ+n\u0017sQ1e\fjw\u0007\u0003-I\u0002Ƞz\u001b\u000b\u001b|G\u0015,x/ʣf*W$ufa)qū+\u0016A\u000e?oXi1;ĝ\u000e6vf\u001e&A\u001bP\u001c\\U\u0012ä2͑:O7ZSƛF\u00156H\u0017P\u0017~-Fj\u0015{|\u0011ΧLF[$us\u0016ݵ]aa>8QJ~!F35B;\u000eDA\u001b9EzԊ\u000f7f_HM&Y_(F,+4`zZr\f\u001f'+\u001d3U*<-I-iV\u0019F+xV{Ym~s\u001f/va\u0014dSM~|\u000b'ԩHfT\u0013\u0002\u0004@\bx\nPGZ\u0002\u000e\u0000{>\u0000/j\u0000KX\u000e`k]\u0003\u0018\u001cU+\u0004^\u0000U\u0000L:\u0000v<@\u0014 \u001b\u0000Ȭi\u0001D!nO\u0000WK\u0004b_\u0003H\u001fA\u0005\bC\u0001tNCc|>\u00003\u0017\u0000\u0010\u00142m\u0015y\u0002xсBV\u001d-\u0018\u0002cAj\u0013(\u0019puRZW]b\b\n~ÿ(.;(yvx\u0000W2\u0010\u0017\n B\u001fB Y\u0017vE05=7\u0013)fД-v/S\u0007w<\u0005p @\u0001\t\u0000^y\u0002\u0002\u001e@P\u0004h\u0001\u0014 {\u0000\nu?Lҝ\u001byɰH?4x+a}\u0003zE]~\t)\u0001yCo9:\u0000\u000f0}ʙ-@c\u0012\"\t\u00062SHvGA\u00007F}\u0001P\u0007\rT\fPFh_|ŗ\u0007\u0010[\u0018xR\u0003P<Pc2\f/~\u0002Ԉ\b\u0000#Cqk~\u0006D\u0000yр0i\u0019\u0010\t\u000587\u0003\u0000\u000f9m\ru\u0003\u0013F\u001c䁙\u0010\u0001Z\nח\u0010Ξ~OE5G\u0015Bu{6/]+ǗyVB%\u0000\u0015\u00016TgД\u001af{BRg f\n |\u0002ķvG0e?f;W~m\nO#\u000fHY\u000fc83ߣΗ`%)߫(\u0007Ka\fsw6η}ܙYݓ\u0002O\u0001\nݯPV$^Y@=\nH%e\u0003DD_b]xrTAG!zB\u0018i9ٚMo7~O?\u001f\u001e$?n\txn]G6}U\u000eZX'3\u0019t92-6\u0007?}85?u[\"+\u0007 z\u001ed>\u000e\n3-2Uoq;xz'I=A\u0006Q\rzpVFix?o=\u001f[\u001fVUo\u0002n\u0017#f\u001d,;t>\u001eGhw/\u000f.\b?e\u001c?\u0001J\u0003ʔ\b\u001aZ\u0000ҴO=9˂\\J^nJ͊\u0016`v|\u0015\u001adl8,>u\r.uwf*l\u000fb\u0013v\u000epCڵ\u001eلx[UkU,7-'\u00006O_\u0005L\u001dL.O\r[d2Q\u0003ƥ-(GO҃\u001b=n\u001b'D\u001ccgO)ܜ^:\\Bgc\u0000/)ɮqmx6l+nz\u0016\nYj\u0016\u001bܱl$VEB\u0006\u001b891\u001csJ2wLPc5\u001b/fPކ7[.<t\u001d\u000e=3B\u000e\u0013W\u0019n׵f~䉪E-\u0018mWߴd\"׊\u0019Zҫ/+̋4\u001dkw\u0005\u0013pj\u001aP戅2&y. K丆e\n\u0010>҃w\u001bto94x!e_K\u001b-Vgzl{,oa\u0016j\fw.+2fzMV$\u00053{,zOO\u0000aO\u0000\u001658\t[\u000e-O\u000eSGϲFe[,+\u000e\u0001a\u001a[[\u0013p\u0000_}z晘]\u000bV,\u00155vEשr[{\u0019\u001cl,\u001e-W/3gpZf\u0014\f&r\u0019\u00145CKQ\f\u0003`^)f\\0s%͟>6Imka52w\"&@K\u0016yhLMϱ7X5ӝPoZ*\u0001ea?\u0001m \u0003dB=y\u0001Ȼb\bT\u0017f\u001a\\\u000b~\u00190rT0~e.h\u0000֛XV~0*yR9){v\u001cz%GJi?\u0010*M:V?^\"\u00073ܑEߎ\u0004\u0004\ne\u001d(\\@\u001e\u0006\u001cI=&(u5l\u0015\u001d\u0007-4\u000fM}\u0003'l#7\u001fюi1/s|z>Vds\u0017Im\u0012.;iƤ=cPb!O@WǦ^woU\f ?ޯZCf\u00013qT^s]\u001ab#3\u00147\r9׵,\rg̈́\u0016\u001b\f΁I`4)+Ut\u0013nt\u0006B$#\t\u001b`S@F\u001a\rww\u0014o\u001f\u0019_,R7\u001c3v*eUvolo3[ߤX\\6dBљ\"Xr&\u0005So77ɋ}Ǜ\u0013K\u0003e\u0011:/A[UyYպ\u0017APO pZ_w\u0011|\u0000w\"j\n\u0006\u000e\u001b(Kp^\u0012\u000fݭ|\u000fGame\u0017U:X!$ppT<幚R5Y]q&rJ\f\u0004z&DWn\u0019\u0011}4?*j˿\u0001c\u0007\u0014\u0007\t\u000e\n9\u000b}l^/x]\u001dեL \u00151VԐ\u0006)sHV\u001elX\t#V6v\b\u0015ϣk#k\n>\u001755\\knڜ\u001e\u0001\u0017~hHU?\u0001HLT@֙n\\xV]\u00047dM\u0017SXE},e\u001c&oN٦)Wzs\u000ei+M*2tia.RZv$\u0007\u0007W\u001dCvdT\u001a/\u000f<\u00189\u001a?܊>ۉ\u0017u\u0015*'\u001b/}携\u0019ٺs)\u001ac lܷ`Y=mH\u0011bTOwT_\u001dLuW\u001eMzXu\u00051qQEaWC;}<\u000e{m㯸\u0013\u0018\u00135DNݷ\u001co\u0000ug \u0004~0KrM?uJA=\u001akЬ2E;a\u001a\u001e͊)6qL\u0006+*\u001bAqb\u0007|Zt\f||\u0003=;}2zy\u0016?\u000fܭ~Q&\u0015˹[\u0010%)ߚXM8Ӈt\u0005슂3FY\u0010+<<{{.IT&{lJ \u0015\u0018nmȹ=\fuORy\u001eSBsth:JX6J\u001bBա6_\u0005}\u000fܭ~\u001d=97E:\rq:de\\o#@d%Q]Ԅ*\u0011\u0016>q׋\u001b\u001c\u001a:+S{Eb:%FjnˣNowg^;}] \tk\u0013=;y)ɧ}gfyCԹ*cX2WOY\"\u0015\u0000\u001d=~a\b21!1=\u00181AtJ)2h+N+dwt'\u0011o~j쁗mqXA[أ<RHDOܽq\u001bh=\u001cSFm-\r8}ʫ\tON]l\u0006?H^SMӣw)՛Zt[s|\t'\u001b\u000f6ZNZD=j\nIcߝ[\u001c-_\u001b\"j\u0014Vۿ\u001fa_zŵzE#SY7|XWV.-S\u0019KZ\bLȯq$\u001aH\u0015\u001cy-m\u001aF46tf}c\u001bEkD\tVSj/Ɗ\u001a|\u001aР%>H\u001cJ{a=>xg.cȥ?匴Y~|41\u0005Ui}^$\u001cfe/\u001c\u000ej\u0003+t[:,E]mrtsvޟ\u0007Fӭ\\e5Q\u001a5;ͬzXM#Vx7[O\u00178Vߋj\"l'vuTؔ;\u001aatM\u0002\t:e\u0004\\\nz0{p-GyLm\u001b\u000f/\u0012C9ѹ+TУ[kjɌ\u0016jPU嶚9>\n\n\u0016NQ6ˣv_( 1zl+\r7u73/5)c>Rѣ>#zjrG\u001c\r\"%:e4Qh7`6ˡ\u0019{\n6K\u001ea-9\u000e\u001a3~G|*l|\\T^Iw\fܯed\u0015]P\\O\u0018`&2I\"I/\u001e~棘K\u000b\u0018'9ḓE:Osf)9*X1kkU[Wi^`>.*Iϡxdb9M\u0006\u001aFbseT\u0019c&`f\u0013f*\u0013Fi\u0007\"H\u001e6S~IMwuy\u0019>|m=J~Qp\u0002\u001dQʿNb\u0014Ծ\u0007\u0019o\u0010Q\u0010Z\u0016T\u0018dY\u0004<\u0003|E>\u0010\u0003\u0012Ϧg?[t\u000fb\u00034\u0000Td\f=@\u000b(\u0002t\u001b\u0000:*\u00009̯\u0000\u000f/t>\u0018@0A|\u0013 )\u00072Og\u00042aZ\u0001\u0019оωgl\u00041 n%g sc:=\tҚ5\u00197~\u0003@&](SAu\u0000e\u001c\u001e\u0000Ve\u0001H>\u0000Z*T+nZ\u0006\u0013\u0018\u000eQ\f\u0010f\u0002HCw\u0001 9B\u0005H^Al\u0000^ \u0013i8\u0013~3Ҧ\u0013n辎~\u0013ï\u001a\fk\u001aA\u0006q\bwhAc\u0004\u0001\u0012U\u0000Ɣ\u0006P+\u000beZ\u000ejuP\u000b\u0000+\u0011\u00009︬u\u001avX%\u0001D\u0001\u001dn N\u000e@r\fa\tg<֌%։\u000b\u0013B Blo\u0000N>NPߘ\u0002lh/\u0001vo]\u0000^\f2\u0000Ǫu\u001d{,\u001c`Y\u0006\u0000$s\u0000\u0014{\u001d\u0003uC\t\u0004\u0001d3&;\u0010즈\u0005[^\nga*t\u001c[AT{ p \u0003@?up\u001e)\u0000\u0005;\u0012\fw%\u0006Y󟳣\u0003pNt>ҽ4@w|r(ͩ\u0018;/'^Tr_EmGK\u0016>z-V`?T}vhۛnEiP.\u000683(ǅ^\u0007\rw\u000f\u0010u\u001epH\u0005\u001b\u0006r嘌E%&w~\u0012\".\u0015R\f\u0006c\t{'>u\"3\u000b^=l\u00192s뱫'w(%SK7hPn,;]=J\u0004\u001bXpL3p^ Z\u0010\u0007 \u001e\u000e\t\bhRrp9ѣ:9A{>#\t\u0012\u0019&U'\u0019I?vG}`)D&zċ3bA׷KuJNnX:|;\u001ewy71@/Y\u0016\f\u0010\rH\\x\u0002rJ t\"C1VF>,°3t;\u0005gw\u001eaM_*ν\u0015s/s\u0014\u000fsGMNO\u0013\u0013G~kBq{>g\b\"UXF\u000f#\u0001@\u001f1\u000bpD\u0015\u0001*\u0001\u0001\u001aV}_.9ߖt\\+\u0007a5\u0011)\u000f,\u0004T^x\\!:s\u0018;%:\u0019;q~x8HAJ^K'[nZ VV-, &B\\R\u001bN\\\u0003*\bJT\u0019\u0015\u0012~i}\f,\u0017?Z~\u0000gy\t7[?\u0019,\t\u00071.Ca%{9BOk4e,6y\u0006SD*d7ukZ,oԯ\u0000ش\u0001|{B=\u0000U^\u001aQ@K0=cknf\u00070;싚\u001e\u001f&uf~\u0017\u0016\u0015-v-\u0003\u001f\u001f;D7*v֣;YI\t_FV,_\u001e\u001fZ&z\u001cZ|nF\u0007\u000f7O$\u0001u_,ɼb<{5\u001d{R&ww\\ҝW\u000e~\u0011B,av\u0003mauz\u000b\u0013˽3upU,PtȐÑkF=eum:h;jt?\u0017/674^a4\r\u0000\u0019\u000e\u0010\f6\u0006^y~WԪ?\u0012Xl~|D:|ɭ\u001e<ֱ6kR+b}N֫Jsyt=gD\nҋ7c\u0017=a\u0007iv+p'z*:\u0002.G\u001c\u000b\b5\u000fFE\u0013&LR!v3G455)\u001aֻ`ȭmFN\\]R=͠lif⃥E\u0013{s4~&3cߨ\\|\u0013\t/ >RaTYxw\u00170}E2בMdj\u0007ڼ{e)\u001c8Y\nM\u001dRv:1-Kj\t{34ã\u001bWNј.-2\u0006VϕEϩRӪ*+ї)#^Rr'pq0\u0006\\7\u0017\u001c 1[\u0015\u001bnAnUƔ\r`f᏶/_l^azSō\u00137뫻tO\u0017}̲\\}t3vA^0m\u0012ik1rftzL\u001eqϵp\u0002Qv\u0003! \fN1\u0014zo_<?\n7}nˡ\u0015\u001ds]g[\u0004\u0001#%54\u000e,v`N4-^\u001dKͱR\u0006얓Hۀ\u000f%FEN([\u0013\u000b;@<@g?B\u0001\n}ov _\u001cTnp?ޭ\u0005]1{;گba!{#\u0005\u001a\fBΌZs2\u001bIU0-ʚ'HԡR)\u0017I8M1_:hVF\u00024&Σx7\u0000щFts/v8^\u001apt`\u001dutҥdӈ,Z\u001aTvʨՙ\u0006J_nu\u001d~l=IbQr&\u0012p\u0003\u0015rs{8;1!\u001ft8\u000bhg'\u0019:\u0001:{F>@nf1v7C8%JRZݴy\u0014si=.ꭎԦGhNGȌIV\u00123\u0011LG\u0013cպ\u001bR%ZY#fWT\u0016\"ٕZ[1k!ɻWBŢ\u001e.\u001a'ɽv\u0003ƻ^\u001a\bzl<w\u0004\u000b\u001e-,ש4\u0001:5xvzB\u000ew5Å0\\\u001bkoX&Ŝ\u0007\u0017۝\u000bѷow%\u001a3m^\u0000RG\u0004Ykܽ➹XzD0\u001ezG<:\u000eL#\u001aٕ\u0015^\u000e)\u0007>Z\u0011\u0018^\u0018\u001e'I`7l[\u001dϽ(hbu/Q{ida&>C7O\u0001D8\u001af9(͐T\u0017Mb#\"r\u0017\u0006݇tr,J\r#bkiq+<\u001f¤4zw{1t\u000e\fT\u001c7l0A`ּ \u0003u3z!U6Ҩ|\u0015>X\u0016fKbYjJFc|k\u00030$ơSR\u001aس5\u001fFl/i\u0019/,~N 5\u000e\u001fi\fNnҭ\u000b?k'MLxM[\u0013jd^eݩ[ja~iS\u0005Wt,s\u001du7c*\rٔw1qn}F|F>CZ\u0015t\u0003Tz\u0017NGj\r$$G\u000bF$\u0019vꌧZhYcs|r\u001f7x@ܤS:̑lx#)\u001bxWFLeцbHoVS\"ui7уS/\u0016S\u000f\u0017o\u001dW\u0012\"\u0013`z'^ٞ3jaU<\u0004jk%Y\u0006^\u001a*\n7im\u0015fkaC,i\u0002E5a!\u0001'xDb4\u001a=|\b!e \u0014cwIwV\u0011\u0011qf;GJtn#kl\u001a()=\u0007m\\յ1ΒFRkͨ\u001b\u000bv@.TY\u0005Ɏ2\u0005{Eq9S|ir2\u001a)uAb\u0019\u0019mQ>H\u001a\u001caį6|U\u001e8\u001b[wig6;SJ-~gl5Yg(\u001bJ.U]@\u0018VA=ϯNqS\u001fÊߒM\r]=\u0011LΝC2٧D,@_ߍ\u0010i4پ`˖*S{OS{\u001aKWL5\u000bmyL5\u000fZ|xjtnUzT7z\u000evK\u000b|ZM[\rۃAW\u000bцL1|\u0013n\u001c=\u0005\u001fÌHXQiTtC\u0001\u0018\u0018ӻ5klE,Q\r|2\f}גW?XxU\u0005a\u0005k\u000fZ\u000f\u0003L't53%y,Cga]oomϠ:k}a6y\u001c.o;@:\u001fD\u001c9C<OaSRT#\u0015.m]\u0018}ӕS|^\u001eQ{t5UnUr=PM%\u001f8m~!vF7\ni\u001f?b=8>\u001a\u0000W\u001dͮ;\u001f)И[RY6<Z\u0016\fV%3U8vŖN8dp|R\u0013gzڤYY\u001e&zAֶ9CbN{\u001fx9ȓF{jU\u001d\u0010:H0:| gƶ'*)\u0019,h6V[=\u001ajSF\u0013\u0018T3S>B$5PR\u000b̝/873\u0004MU%˔:ٯM)]\u0002{C&y8\u0019+\u001e\u001e\u001e\t(C\u0014s\u0001dC\u0003d\u000e\u000e@Z\u0003\u0016 %A<\u000016@s\b)N\u00007Am xߧk3\u000b\u0002\u0019L_\u000fAqNA|p)\u0010<E\u000b2K\u0004\u0019lh@<\u001d\u001b\u0001\u00032'\u001e\u0017<\u001a\u0005\u0001/~OB\u0013\u001c@ܓ\u0004LV\u000f\u0010Q\f\u0003Rn\u0001dx\u0016\u0000B|4\t`9On Pu=FBt* 3͡\u000f2,*A !.\u0004\u0017%6ɼ9X|.\u0000*\u0006Q&4e\u0005tg,@\u0018bVGg\u0007\u0012\u0002h_\u0003\u0014\u0000%J\u0000H?\u0000=/yf\u0010\b\nЅB4Xw\u0016dv\tl\u001cr}\u001dl\u0018'wO\u000f\u001aL\u0011J\u001b\u000b=\u001c\rp}(T;P\u0003\u0000m\u0000Ff.\u0010\u0007]\u0004\"b\u0000ڄi4o'+\u000f\u0010\u0006\bS\u0001R\u0015 t*/f'.5RZ,i) TD\u001c\u0018 zX`=g&\u0000\u0006 %\u0005\u0018<\u0000#\u0013M\u0003\u0013`\u0015N\u0001J\u0000\u0000}\u0014\r윓!\u0004\u0001/\u0011ee1\u0011\u0018Q\u00140b}u\u0018>\u001359\u0015\u00033\u0017)\u0003<^<\u0010xs]x\u001b\u00002)B]\n\u0011{U\u0005xj\u0001Q\u0016C\u0000Q\u0015\u001d^rN䗨Pp;H?e>Ig#ȳ).\u0003 a~\u0005?4oB=oc%N3y\u0001.ڬrG\u001blBS\u0017Z6ay[\rg\u0000D\u0000굗tӑ矇ᢽ>4\fV^ۆbZg\u0007K/'0.\u0012w\u0014yaz/k\u0013w\u0006k8y+>\rxhtC?~_B\u001b`\u0007pD\u001a\u0001RҾ\u001e/ \f\u00001W\u0011ƞ?۠-?8ixK\u0019zw<rU^w삋%m9\u001c٫)^NNle>?\u0019g\u0001/wzo?\u0000\fʜ\"]K[\u0001*\u0014x|eX\u001aK\u0018!\u001e\u001er-84/%nvo݆Fa̝Ot];>qi|<\u001c!?>aF\u001eyʥ6Zا*p{A͞#\u001b6\u0003@\u001f\u0016\u0014\u001aנ=?\u0018&vS'Z\u001050\fs =r\\mal]m\u0007͌I\u001f .^>/uۋg]\u000f\u000fF~x\fn&Ijˤ͜m͍-\rެ5~^V,\u0017o#~i\u00001*ɀlﵡXu'sSnQ\u0012\u0005G'=aѱ\u000bCڴm:dw\u0012\u0015pn7-S3dc\"\u0003q;\u001e-\u000f:FzUxUF\u0003\t\rԏ\"ȝ>hˌ\r\u0000\u001em/Ί6\u0006\u001cƇ\u001f>T\u0018^c;\u000e|\u0019WY~0mZ\u0007C\u001cOq$.=_\u0015zY~,F͕]]+mc-\u001e=qrŦQ\u0017]|b-Ra>+Hر~\u0003\\R45=+6\u0005LeɃෞ;9nݗ\u0003^\u0018c%\u001f\u0014q9bXm-.4؄ʵ\u001b\r2ћZh^l?9?aZ\u0011EFRO/o\nN񉥸\rpj4 Wi\u0002R1M<\u0010[%4\u0016LYXr\u001fgǎn_[0ӛ'VT\tnPF֒__\"}stg<g9rAc\u0010Nu7;U2\u0016?j\u001a}8\u001d9m~\u0003\u000b\u000e h\bȝ;\u0007YS0uX>ęt9v\u0010\u000eM\u001d\r7\u0005\u0012`Ƴ(iLvF-2:=$t:\u0019)nSw\\e)&LZ\\^$oX\u001f\u0000x\u0001U\u0004?2` OK&\u00023_X۔pkY/:\u0003ªsnE~Y6Rj\u001e蝩C9\u0018QI4jSƝxz\u0007#eԦ\fa `\u001b\u000f̤*,^ύ\u001foq\u0019\u0002\u001e3/;b~}-k\\Bls\u0002-e~+S\\La8Ғ\u001b#7\u0006H H\u001fJy-b\bp@$%0\u001a\f\rO\u0000,1TŒQ\nYok<lm>\u0015,o?.曳\u000f,/jwp1Z[erxvҨR\u001c[RP.bw\u0018<02F=7,\tyq?\u0017x9Hk\u00109U\u0001_\u001f\u0005~\u0005D{ިLXdvUaƓn3;\u000eƈKQ.:?k(UI˺'t)Ү`T[j\u000b\u001eBY+\u0018\u0018F=Ń&<!\u000b1gon@{\u001b+h\b\nܑG|X\rkSLχ}eV`R#SlÒnYJ#.P}wssƮx3xmW\u000eL2\u0006f\u000fނ@\u001aKov\u0000\b}]=Ԯx[J{TV1\u001aY`ne}s\u000br͜Ys\u000e\u0013S>i_#j\u0003qBφ\u001b5.!2}yRU\u0010\u0017}\u001f\u0001zAjJf\u001d\u000fۙ8Bn⭰VƲ%\u000b;<,\u0015_=t钢L0#\u0000\u0019E\u0004D\u0006\u0011\u0001\u0010\u0001EDp\u0019\u001cI=\u000f\u0011\u0015\\iu\"!pN\r\u0017\r꣧J[,\t錉|\u001c\b\u0019z\u000b)Rs\u0013Z3_\\`RՃRzBR>%ŁtzǚrPڥcvC\f\u0007%\u001fWjf6B\n贑\u0012%X\u001fǜ'\\]<~x\u001d{;V,}uG\u0001yZmISYX.\u000eB&i-O\u0007婒\u0014\fx\nm84cm|53\u0000\řW\u0019@\u001f\u0007\u0014`\u001byk[M:\u00106QEEBAnr3A\u000b \u000b1\u001f<\u0018*ڍt^7ܥ4ܕhOx_(yQL\u000bX2No;yi\u000e\u0017ĸ\u0013IU\rv\\W55s֙e\u001b\n׻֪]\u001eL?%\u0011\"f֕;U9\u00114\u001a3W\u001a\u0010\u0005,Vr\u001a+\u0016i\\_,]՗aR\u0017'JSB\u001c\u001b!>_t4Nƫ4L0߆XIŅ\u000e\u0017A.\b$)\u000f8P\u001fe{{R踫&\u000fb5!c\u0012ۺ\u0015\u001b\u0003lMtJF0=[0,`BYAuc\nآ\u000fHOvcq\u0011B΋׆L$}7O\u001c\u000f%\u001a77@чaH[]70\u0016G\u0017\u0018Y\ry\u0016hHJ\u0003f\u0012w;\rم\u0016S*\fZ\u001f\u0002wC&T\u0004\u001d\u001aE_\u001bJ \u00022xnV91旧nP;un\u0005ë9V\u0011sŉV\b`phccf~T},h}<ԨJ4j\u001d&\nwM\u001cUVZ=8\u001eYb<ثdV/GVh\n4B\tuޑ5Kk$\u0016*<V:'Q\u0012Q}\u001a.\u001b\u0005}\u001a{&o\u0014YB5'\u0014H\u00140;$\u001dUiG)/\"lWE*/8Y{y\u0019FŨ<eq-g;hmɥU7/6Y\u000e\u0015z]\"SU+i\u0006KSFq@?Y{I|wH\u0014fX].\u001fB/J1£\u000fu:r%-[:\u0007/{9_nZ\u000e_0 \u0013c+N\u0002?\\KN\\#\u0007Տ\u0005\fgsRϧFG#/\")ej\u001by\u001c\u0012e\\)&;\u000be\u0012$iRn2ݕc?#\n\u0011\u000bL\u00173/8cE;\u0001FW/~9e7Nd+j}\u001e,Oީ\u0006y\u0004<\tbm\u001bK\u0017j\bG\u0017\u000e(8OT;/\u0010 'Q]N,l˿8Z=QnY~д1QU,U1iJՈ]\u0001?7\b\u0001::Fp\\hE\\P\u0016{\u001999l7AHz\"DCF}Fj*s==\u0014A\u001a\u0000M\u0013 Ӿ:,6fܷ\u000023JI\u0019 Ӎ\u0002\u0011\bd\n&\f\u0002e\u0007\u0003X\u001c:?\u0002n)\u000b\u001f;x\u0001`J籴NS+\u0000cj.㫳\u001f\u001c\u0005w|\u001a@bA&)\u0000:ݔ\r2\u0011\u0004m7\u0006\u0019s| SlǞqT\u0000?.\u0013\u0000 \u0001x?\u001f\u0000?\u0000vs\u0014HYs\u0000zvmR34ӳOnOnN\u000354\u0000Y\u0001uHo[i\u001fS\u0003\u0006Hÿ\u0001\u0004\u0007\u0018Lz@Q\u000bd\u001b\rd4=Y5撲O_ǂ\u001c\u0012A3\u0014bAb\u000bKQ1CT<I:\u0018=\u000b5\u0002 h\u00155CZN\u000243\u000b\u0001rOk9t\u00064@6ȼ\u0013\u0003dv\u00157\u0001\u0019~N`uTwK\u001fW\u0011\u001dl<Ӊr4o-vma+{qxVbb\u001d~v弚\bS\u0000E\u0016m\u000ba\u0000h\u0001:\u0001: \u00132z\u0001dcd$ηcY\u0012\u001fx\u001f\u0004/QZ\b\u001arQ͞j74\r\u001cP\"$n.\u0016y8oVù۹\u001eN\u0007\u000fig\u001bmi=\u000e7\u0001XǱχ\u000e\u0000G\u0006HguY\u0019Q\u0015K;UAq\u0017w\u0000\u000fzi\u001b\u0003#^cG2\u0018JӸ((uH:yˊ{$'5+M\u000eQ\u0014o=|gf7E]c\u0013w\u0002T\u0006cXߗ#W\u001be~\tp:'zVHn]\u001b[7\u0013\u0018RJ\u0013u\\3˫P؟ʕj|\u001cvvVJ:yoo`[\u0014.7Y<\f_z|](_\u0017$\u0006}P\u0007<KN\u0013U?ON\u000f\u0013Os_f\b;\u001eҺ,hh>\u0006ci\\\u001fos9\u000fr]`~vͺlZ.̒\\,7_P\r,f_~пάV\u0001)=\t\u0011E\u0005ٚ$a~zfaZ.置QU7\u0013y\"l&}sSe\u001d^ںX2\u001ftuLwy\u000e%\u0017V{\u000fa\u0016\u000bb<Tf\u0016\u000bx\u001cM<\fێ\u0005@M.\r\u001dP\u0000\u001f|W\u0019k9\rd7\u0007}Ƌ\u00037Zhm\u000eu:`v0\u0013U*.Yby9\u001e%\t\u0016OځS\u0006~ҵL\u000f|,=xr\u0000\u0006.wOs\u00188FSU\u00157k9\u0017\u00055\u0005@\"\u0001\u0006՗A6-t@\u0012:Gh9:W▽OZ\u0013/Iչ\u0004?蒢-(xz$\u0003-S!X#̒\u001dGmN9-\u0002g:թʹL!A\u001b\u001f?:vt\u001c7\u001aNl|\u0019%͔Mzjz]\"̟uFMK\u0011KZ6v\u000f\u0014\u0017\u001c<w\u000b(^y\\u\u0006m|㈒\u0016tE\r'\u0012\u000f:շ\tcG`?gg(\u0005C\u0007#h\u000bi9\u001ds^f|Կh&n,_#s^cAH{\u0019\rq=%jA\u001coߵЊ\u0019\u0000g\t4Ht;o}6Yym\u0004;1kb{U\u001a?_e\u0006WRVZYx`YėrK1co\r\u0006\u0018gC5ʈ\u000eO+f\u000b94]\u0003KNy^\u0006\u0015\u0011yH\u0014mZ6Wс\u0019,\u001aϩKNvu[=\u000e\u001ftJxrO\u001ak9\u0017bւ5F!\u0002\u0018嚢\u000f㹧G\tvש^OmOS6T\u0003GA\u000e(WI\u00182'h\u000e)SY\u0012O\u000fBnmկ\u0002;i`oWk\u001dCG\u001aE2<\u001b\tk_r\u0013-)[;W2{g\u0007Y3xo\u00053\u001a3iY?6\u0007ZW;-L1a<``,;:+<I -m\u001aVc܃\u0019\u000b\f/MF(5\u001epOFW\u00060GYc%Jy?h\u001f+\u0017>V\u0013 \rX\nL$Nm\u0006\bۆS\u0002] HA͗\u00157\rޜL#\u0019CIɷ:\u0007\u001dijoeXO*dU\u0006y28xx\u001cawWnĮ\u001cLn\u001dwt\f!~\f$rv&T\u0010\"ѼgfEh*<pvG\u001f7\u000bչf0V\u00056%WUXe\u0003)ۓ[m\u001f;POMEWnj粯:#uw錴M3Y!hw.G\u000f/[\u0010N\tä\u0000m\u0013Z]{1S#h\u0007ZL\u0019)?oht8yQ}$iUWˣZ\u001bfaYv̜ʵǈٕXGyo\u0017R\u0012N~m/_cV\tU<>\u0014v\u001eRFxxxhANf\fo{#\u001c \u0018ec==S\u0016d\u000e\n8\n\u000b窜v҉\"־稲B(ζ\u001c[-\u0018)RF\u0016n\u0016a(WI:Z\u000bٴ{\u0006\r\u0005IVEx\u000535e\u001avr<F\u001b-#bN,\u0006AM*~?#+E:t_\u001f\u0014np\u00050J1j*Dhf禙X3\u001bM%\u000f\u0017 뎘d2;Ia\\\u0002>6;\u001bCٙ~`\n\u001fmujT|]\rP}A^.a^\u0016\u001b6ڶqg.hIGj\\38\u0000G%(uX-r\u0011*FMО;IN\u000f-S}bZ>6gLO)Bώ+\u000f\u0011Y5ȵ\u0006<\u001fmUlҩkyzJ^AZH\u0011\u0011\u0010\u0019\u0017ؙ[nrU6\u0016T\u0017S6\u0012g~\u0017Q7+`+Ѕ\u0010؊8ڟԱŸw@O .\\\u0013|[mZ;>\u0016\n\u0010i\nꀳp'/k\u0006w\u0011\u0007{\u00149yTe癥z/N\u0005_W:#ws-~4\u0007<NFʇZPBb\u00153\\݋]\u0013]3)\"7P\u0013붖q(uY\"\u0005O$JJUKGq\u0000FyA瀖X\t;\u0005dVIRǖ6l\u001aG\u0010&e\u000f*`M.W =0*GG9X\u0003j\u001d>[B6y>\tj`y'VXdh5ս\u0013Jw(P\u0003i\u000es\\\u00166v)b[=]h\\nT)\n]Zu\u0007/eΥ\u0005kR~FE:[Vzz#<?}\u0018C\u0016yD\u000f\u000e2\u0016f\u001ce9\u0003i'^sM\u001d;VEr\u0004z\\2\u0018\f\u001aald̔²\u001cӿtev\u0011\\KgK\\,'k[)rTjVد&?#gOo|\u001ec~T\u001bIkeyA\u001c\u000e]i\u001d1R\u000btT\u0005\t9TqbN\"\u001bıa[o-Ie`1%*Rj-SSDNt\u001a\u0019\u000f'.U\u0010'_~пUgw2^([-yu\u0004Hm\tu\u00187\u0016Uܐzq/3Z\\chA\bԵ-(\u0014m?h)\u000eh΂˩\u0018f\u0016RXj\u0017\"R%0^U6\u0018l*QQ\"1zhҴ\u0007.vn~>\u000f#0bɿ7]oF}\u0010\u000bkFHG:j;Os\u0012j\u001cv\"H{WM\"/!:ݼ^qP:rKýT,Uգ\u0016cV6f\u0014\u0019)RV(Rj\u0017ON;&Խ5kf_m\\\u001d&ֱI\tkn9HbxW|\u000f#rNRJYҥJt,\u0017/8ŕOߵ}\u0013 'w*ݜf|m\u000b+\u000f\u0006N\u0007/d?lb,s\u0005zQ}wk\u0013\"]mk\"w5sx,W޽4jE-\nNz\u0003\nIbdc^l\u001d\r\u001e.唠zʣDޤQtR/SX\u000f\n@;3r%UNw\f\fXuk\u0015%3IJ1\u0019.^*^\u0017I!\\grS2q\u001e\n6f[l9{l ./q\u0004{#\r\u0004;#fc\u0005\tugB\u0002[\u0018\u001b\u0012\u001a\u0019\u0017\u0000\u001c\u0000r\u0000E\u0000U\u0000\n\u0003\u0005Vv\brg\u000eW\u0007\u0006z\u0002h&\u0000\u001aM)\u0002 \u0000')sS>K\u0000=}r\u0000h,\"T\u0004Z\u000b\u000b\u000b疁/_|Wz\u000bK\u0003%)\u000b\u0016d \u0003=7\u0002p\u0005\u0000V\t,\u0003\u0000\rC\"\n@ ~(h\u0000\u0014Fn\u0001\u0014\u001b\u00001Ž%d\u0000S*I0\u000e[\u001f5RyPQɣ\u0004\u0016_\u0000J4.2\u00072R\u0004\u0019cR 3kA;\u001eKv[\fL\u0001|\u0018\u0001ا=?KiA\u0002p#q\u0001U\u0016).ō\u001d>A^k,?ì!<\u000eE{\u001f\u0002wxfލ.v&zg\u0002+\u0006iIڟ\u0004\b]^f=\u0015 \u0001X7AA S\u0014\u001a ;ܰ\u001f4Az)?}e;\u0019Ng9>\u000br}h\"\u000b\u001e\u0015I\u0002֎_INZq\u0012oI,m\u001c'\u0011|ٿ\u0000\u0019~p\u0001R_\u0000(\u0000O\u00140\u0004ȑq\u0001B467d\u0011Y<˯<ћ > NJ/\u001b6\u0007/\u001d?q\"31բݖ.ذ=8笮}\u001fKXyhe\u001c.oғ̦\u0011i\bPQe\u0001j޾\u0011@-g\u000ePzA_(z6G*n||}2Y\u0018\u0016x\u0016f1\u000e\"Y\u001dE\u0019P\\\u001e7pk},r\u001e۾N^t\\ꍽ=+\u0006_ÙuB>h?w&\u0001\u0010TK\u0003\rֹ4r\u0005ъ\u0003XP\u0000f2j=fqꌣ{t@\u0014lyZvT}AOG:O`fָrX'm@M\u001bT_\u0013\u0013,\u001c{ѨC\u0000l\b\u0000K\u001b`ϣpWV\bc_ṯΣf\u0007j\u0015/yQP\u000e}@0qۖ\u00126+mXd@\u001ftJey:\u000bFxZ\u001bW\u0007:>'F\u001bʿ\u0000~\u0006jf\u001a\u0011F\u00044Jv{\u001a#v%\u001eGJ۳`\u000e}tQ::ฅU9rɥQX\u00055`\u0002j?M-\f_sX}W<tTg[5\u0006\u001bP\u0007\"s\u001ahT\u001c:h^-9qjU)\u001fY\u0007yŕ\u001e\fՊd\u000fKr\u0017t~\u0005&^}\u001fdT7;6-\u000fG)^r%K9M!i9\u001f8\u001cVX˦\u000bvY5z%3%W*w\u001a뼜e·^ܿzغ\u0000isjɚ$)_Qϥ'ڍsm!w'{[yvhR_\u000ei\u0013\u0006Y?Qcv@,? l~\u0014x'X~\u0005@\u001c^\u0005v?\u0019^OT:Rrp0xߪbX+8ƃfi8.s}f[}rZDyZ0<a\u0018\u001f;ֽb'Wl%\u0015{ٮ\u0012f*\u0012^\u001fK\u0017Kc\u0000\u0014Ts\u0000쉴+usJM\u001c\u0017D\u0000mv^qEP*HDW3JS{h\b\u0000y֓zi\u001bO;j\u001e= !\u000b9\u0013Ĩ;#\u001b\u001eR\u0014Z~\u0018\u0012&\u0011իu\u00136\u00010I*\u0018\u0016æA\u000fN}v`\u0016Ƥg..[l\u001cM&9\u001es\u0016jM{3\nQ5y\u001a*?'.ԡZijc\u00063~Pyk`u\bu:_s1\r\u0002DDo5ĩR>\t]\u000f\nl\u0017R)9W\u000fQ&zgմd01\u0015vP0\u001c~ȫn0C\bS_E:x5n \u0000.b~i\u000bL}%5V\u0016;r~\u001ce3xmOڳ\u0017\u0005NydgC8\u0006R4Uz¶gmc\r34\u001f_6;n\f沗/\u0004G[Ip9n7\u0014n/\u0016R\u0014\u001bZ\u001fH\u000eRT6*w6?5*کt=\u0010?f\u0012Fq2(;[_`b\f\"O\u000ejk\u000e=s\u0019]\f|X\u0017\t\u0013\\[̉\r<Y4\u001f/RaYҨT\u0010\"\u001dC*~|\u0012\u0010\u000e\u0010\u0006yakruR\u0017rG<?\u0016:2JU\\H\u0006q\u0018ITt\b\u0017&\u0003\u0004&},\rt'(uFHھv:R>v>DmzEvA|_\u0013R3G\n<} p\\~g\u0017zԚY%w\u0012hG6&\u0000U^\u0006+{s\u001d\\O\u001fTOc:V\\#\u0003\u0015AgQl:8fn)J^~K_\u0000|~+]XySFiW_,Y?;\"?\u001e?l\u001e\u001ffG\u0015\r\u000bkd7\u001c,h[w\"A\u0015dTN\u0013A\u0016\u000ewsً[Ӡ\u001641\n\u001cX\t8j|LB\u0000\u0010[*IU/)\u0011\u001dPt\u0010!ULN\u000f{o繑^-}:\fbsf>ƨ}uUg\\L\u001c.^\b\u001a6A\u001d\u001a\u0019N}ӂM\"\u001a4;\u001b%/ˈ\u0005\u0019<bi(\u001f\nwPp`~ُo%|8og\u0004\u0005\u0013@\u001c}\u0016澅\u001c|\u001c .\fpH\u0006%ls]?#\u0005<Vy-x,\n'?+<\u0005mLbQ\u0015\u0014V\u0001ORz\u001b}(R*})\"\u0017/몱:\u0006\u00062rnS:*ri83pէ\u001az\u000f\u000f+\u0017\u0012mL!\f}[fOZ\u0015asW'\u001e.\u0004w(@E\u001c\u001bd\u0013\rgb'?h@bi@_.5Q-\u000e>E&\"L:\u0013mkW1}\u0007g\u001c.3\nw\u000bmWWPY\u0016:RR\u0015@Pp6\u001fW\nsφ\u0017wΰ X\u0018yI\u001cLL׃\u0013\u0007=/BN못?\u0005~U<NykCgig55!e\u001c\u0007$*JZil\"Z\u001ems[\u0005f1beUzC\u001az6=lӭGuW f\u0019-4\u001c\u001f3F\u0007\u0004EHR\u0017ۭY,yw\u001d0\u001d+\u00185Ȱ\u001cFSO92`Akuǫ#/f\ne)I+I݀f\"]o^#g\t]ދxj\b!\u0016ߒ\"4!`k\u0011-.UlrΝhl\u0013q[\fY<\u001eP7^*R\u0014O\u0017\rI:\ntVl\u0005s<!klnvb\"Y] \u0014^uG\u0019ūF\nY6ȉ\u0018}_zbdr,T_Y\u0017\u000b9Npf\u0017X\u0010\f:\u001dl܋\u0017MFώh6Dh\u0017F\r1^4JtbQN`%\u001cS\u0012\u0004M\nuj6k7\u0018\u001csAGw*$E4\u0011m\b0HHM \u000fN 'y)\u0017Io\\a0SM<R~ΐe鋗aOѺ{$/aC2gvCmt5\u0016Y#9I>\u0007תsU'!\u0016+$lWAX\u000ecw\u0011\\TJ]oK{Yd24bzG\u0018wk\u0003jgcMy\tx9y\n\u0007u\u0002b[s\u001eM\u000eÛ\fψ6\u00128T6rVm>SZ\\2]t\\XJLsb-Z-\nc\u001a\u000b\u0014O;\u0010K-ϑ>\u0007+\u0007ƕ/\u000b\u0019|!ǺvcoKj6\u0014#dk\u0004ݰɔ\t[cE!\u000f*!\u001aBI+\r\u0013eUƾHܨp\u001f\u0002>༫|X5[<]594O7\u0010`sv\u0013@o6LYaV.B\u000bYzw\u001c\u0011\u001c7¸E\"O\u0013tU4<IqTxlrB#sB3I\",nqso\r7z\\0To\u000f*e7ZdGz\u001f1a.p餵؟/{g5tM0Ğ\u001b-\u000fnӆMU\u0015`h\u0012۲Z'6.|\u001dKd\u0012\r\u001e-/zd,Ô\u0005ܨ\u000evxJ%S\u001d\u0012~J2\u0004H_(f~\u0001 \u0001Q\u0000\f[\u0019\"\u001aW\u0012@ي|bm|³|*\fz=H>j\u0001OTRLIH>- '\u001fH!G)ic||6&Œg_\u0017]|*m>s^\u0000h|\u00001Rh\u001f\u0006pq?>\n\u0000z\fV\fA\u0007\u0010u\u0001km'\u0002!sr)jʩ|RSRzNzAnS8ɀ\u000bO1QxIw}IQ\u001fҝ(\u001fAN\u0000/!\u0000[/4P.\u0003ض\u001aijxV\u0000\\.\u0000\u001df\u001d@#.]\u0007/\u0001(E\u0000CF;\t\nA\"\u001dt$_{/sKag~2'.\"uIjK:͚Wf7ی%7\u0000nN00\u0015\u0002\u0019\foUK\u0004|\u0007j\u00038.\u0000A:3\t.*qQǵ<e=c|\u0016rC\u001drfOgdr\u001f\u001a5\u0016]ۻ_^׺w\t'H\u001cքK\u0010K˂\u000bJݚ}4\u001bdqA-ݢw\n X\t2\u0017S\u0005~\u00022=|Zg>\u000e;=/yޫpWF7{[x?`9~9~6Q:h.z\b>Bymr)tG5\u000eF=-.d{s\u001fO_.\fX\b jX>]^DzwglQ1\u0019xe5Q0rD\u0019%_\\0A+9\u001fѽ\u0011acw\u000fFi\u001d&JaiԶ-7#+\u0017EX\u0000\t&\b@\u000bh\t={9jד7=_s;1b!i:\u00112fm\u000e۝Ot<0,?%@LmU9j@yń3#\u0012JeHfΒixGȪu(k\t-F\\Ԉ}\u0017 *;\u001fb\u0002Pb_\u00130\u0016m^E9\u001dv񼵯#iv\u0011%mexj\u000e_\u001bѠfysRZ\rsjy̹~+*\u0016\f-\u001bjnU\u001c\u001ae+^@˞tKnqigކ!\u00010=?ݽ\u0016\u000fq\u0019:C7v{RN+ZP<C\r\u0011.-0]\u001e>;3:Ov\u0007&u\u0014Z\\әݞX-TTҴLW\n\"=ݝ7@\u0005F(\u0016\u0000xī\u0004u6n\r?聡ZX\u0007YbBv]j\u0014{\u000bk\u0019\u0005,\fs}dxtY=eGÌۻMC٫M3s\u0019: M,L\u0006{e~\u0007_\u0000\u00142Ӯ3i/vy]!q\u0001}\u001d8\u0012'xos%\"Ju(˺<3}ON07ݕOsӊ\u001dcœ8\t]\\ ~(ٯ]]ӳޏg5\\\u0011j[֔-51:^eaD\u0016y\u001eC%w\u0013fze\u001fWk)p\\`\u0005\u001f:5j^\u001e5fZÁsVuV*'4x\u000eZى:Xj5S%I?K#eI\u0006[F?ٞGAc\u000f\u0002\u000bvIڕ\u0015jl\u000e\u0017ej\tf\u0019O\u001f4pk`J,[jN.1}hĢo{6!?\u001am_J|f6<E25\u001aBi1N4?#ѴEz΃$\u0012+0GpѢM8?W筶\b\u0012/m\u0016n[N:Y*gfl/Rx+Xrc+\u001bm\u0007\u0017w6c4_·3?k}R\bW\u001bf6\u0000Ԭ;\u0010r @8i\u0000\u001ao\u0000l}guws\u0017ls|u!\u0014w`1ovk/g2^\u000e=xgMB&-tcG!\u0013CɑwGݢD\u0017@nu\u001b\u001f\u001f8Ǖުz{\u001dʽ:4\u0006:?\u0001X\u0003>\u001fj#\f\u0016寏bqf\u0013o3\u0006q+\u001dɛ}LW\u001f;󘹁HHtY=\u0013vw\u0006*\u0017~nzg\u0014uq\u0004\u0005&-OOPTw0U\r}IS\u0016m/\u0000FhbKۯʺF4\u0000Ş/O5+ٴ6ly\u001b/enx\u0015z\u0013j'\u0007Un\u001c4[n_{zOaZn8-CsTi1s\u001dl;\u001e~XNRSYI6r/|4^bx/\u001e?czyOj2y\u0018Z'\u000bwQI\r?n\fG\u0014\u0010U\u0007~w\u0016ېݕ\n\u0003E-,\u001d]ݷ-K1\u0001OpecQ+Ɏ2)$'k7eiv\bqk\u001c\u0017^\u000030\u0003\u001dfߩ;X\u001c|cQzu\u001dFk\u0017̓ɨ\u001e\u000fʹ[-'\u000blT|7\u0015\u0002\u001a|\u0018m6N-޶fU*\u0019ɯԼ\u0003m%>S\u0007:\u0003V|nsҎ\u001f\u0015:kX\fCk͡Aoqkr~z3@+\u0001\u0006BwR2_\tAh\u000b\u000bEbA\u0013\u0005\u0017k\t!חf@M,\u0013&)M\u0004Sk\u0013'v/_Ȃy6ڬ;8XLžޑ;\u001a4>(XZ\u001b\u001d \u0005wrPuޏׯ\rn\\+U\u001f%FH/Z!2PTG\u000e\u001ec\u0000~дZ\u0014Jw)\u0016J\u0007!\u000579t\u001a= Y\nOq\u001eɰ\u001e0\u001dڵ%늧J6a6˹W\u000fjA\u001d۬~(gNJHM>ɚ4QU\u000e\\ܟ<9\u00158괐8\u001c\u0004\u001c!.\f_\u001eA>\u0019i{Vg\b\u00119wXw&\u0002\u0019f\tWCFٵ4a\u000f\u0006fFE:\u00076'Y\u0002xϤOڲQiv\u0005AA\u0005\u0015~Đ\u0006gWIa=\u000fvF|r,\u001f\"\u001e;\u000b\u000f\u000b_y\u001d\nׄ_^\u0005\b;N4AmF@`p{ef(qE:}I\n]ZmȊjW)\n\u0016KѺq7\u001b)\u001d\u0016r\u0004:be\u001fYsY1Y#|\u001f,\u0011b`_:іk8\u0003(i4v*:nvX˟~,gE:*7H&`\u0014\u001c+9nbnpH葵\u0019\u0005/\u0017tXDfpP\u0007\u000eA;\u001fO\u001eMФ\u000e^\u0005\u0013Ж\\p\u0002[z55@K]jYYj\"!VBMVO<#n\\Ł(b}\"ӺgY\u0017\u000e=hGޛ~t9S\u0011/V>o`v#mDA7ZOηW\u0001pxXH;F^h\u0005c;K[qMדaMƳ\u0006l˅O'{g)tr\u0018\u0012u.L-&xF*9>,ꋀi*geJ<%!xf[n.7]{֌b\u001cxl\u000fG\u000f{pxߔz߻\u0019Ŋ2ueH%iLk\u000fڥ+KkCpT\u001a}8|HrI6\u0011ՙ7\u0012\u0012v+^yS\u000eGy\u0017J07㪬ɩ?/_lP8y0NS}Vx+vR[\n\u0019N\u0010BL]P\"9\\1U\u0015T5\bфh@̾\nk%[Vr\u0003D7K喡\u0017\u00154(VGj\\B\u00107v<μLv\u0005ſp8B\rl[oV:m\tdAHDY \\+[Yg|R9\u0017\u0014#\u0015I/\u0018\u0014=`\u0017\"1/ЏA88?|*sIӹ_ D\u001bgsv\u0005E\u0004AUa퉿\u000b[)HATg[#e|ܨ-E:\u0002}\u000bl{̧\u001d\u0013<Er$#WX9\u001dfj\u0007E)B`\rC\u000fZE\u000feW\u00051:\u0016$@Z:a{;q\u00027ڗZ'`[T\\|\njtC@H8'LVֲ\f\"\u001bq26.zl*&Z9O\u001ddįu\u0017m3L\fpD\u0014:INVO)/8ECtt5EC@e\u000e۩+|.6HBRpFW䍅;6\u0015?*K:rY\u001bkod\t7\bR\u0004*'J\u001c&@)9\r\u00134|\u001b;Um{N\"$\u001b5qK>cy$\u0002$PNދ\u0019۬\u001br\u000f7G)jNk7_pT0}#\u0000\rRqq\u000bjm\u0004\u000bGXދ\u0007@$\rS|\u0012mA\u00019|\u0012|Y5|t?y?4+y\u001f\u000f~>)-eNyc\\-)z^L\u0017HI#BOhTї~Ќ|vśa 7\u00003ipK,\u000f'q]\u001b\u0014\u0000eh\u0000eV'Zcy|\u0006w\u001d}&\u001f\u0015$~K2JZKq\u000b\u001btrIp{츛(\u001a\\׾\u000fc-Eg\u0016+ߦ\u000b\u0000=*1dR\u0000V\u001e\u0000n\u001e\u0011\u0000K$\u0001`Df\u0001tw\u00004}\u0019\u0000Rn\"՞\u000fM<z=v\u000f\u0003~\u001a\u0006K][\u0004m[^p\u001a71DyA\u0002vno\n4qO!\u000f\u0016_qi\u0016F8o~\u0007\u000b\u0004dr\u0005A\u0002\u001a\u0000k=Ϟ3\u001e;]RU\u001aF}\u0005u\u0011\"H+(=\nb=\u001fv8\u0015\f3!s䀐fO5̿)v\n7e5\u000b\u000bV8xxbT쟩n\u001d?\u0017>,{bF\u0003\u001ey\u0016\f#x)j\u0013-|qLve-FGgSǌK7\\BF77\u0014.}fUt!fUaw\u0006}{bK\u001d\u0006c͋T'\",;S\u001b\u0014tho_\bmx\bI7lf¦\u001d|UZ\u000fmr,N\u0007GZoy9\u0002<n64BtQ<\u0014F\u0017s\u0003\u0006\u000eoF\to\u001cWn!\\\u0017V6~n*h\u000e_G%y\u001fƛť{\r>n_/\u0007|;C\u0016yܜzp3ߧmSq?uA`[6[{(zAm[b9\"\bXg  M:k7aCv3{yPas5Ư,E$[x1ϧw\n\u001c3,˯_ |?b_}ɂ)Hl//r?3v5_WDWA\u0019:qٝl\u0017\u00178ֽ\u000e\u001e#Y\tNyԵ\u001a\u0001;Y`0U\u001cn\r#l1;\u001fI\u000e\trQ.ہc~J\u0015\nDfyoKZh\\ⴰk^kxw\u0015ϗu\u0014\u001a\u0010챖&(]RUq1z;ض\u0001\u0005\u0011^'\u001fШ5xg5UNzU{NwPW|\u000el\rc̓.G7:Wu(h\u0017u?R\u0010®ά\u000eg{\u001fy\u0018y֩#MD%?\u001fOC\u000e\u001e9/v*\u0006>X\rj><zىU^W{lqt}\u0001\u0007\u0019U;T\u000e7㐺Bl\u0007o\u0010F3-mK<\u0013\u001f҂My|r\u000f\u001e\u001e̵l\u000b,V\u001dŇF*GJl\u0006e[3V\u000b[Yv\u000fHK[\u0002Y$f\u001e\\y\u0014\u001f3f|c_y%\u0004u[\u000e%1|:3:i\u0017_Nҵ2\u000fd\u000exzt\u0014Mc{j\u001b5\\f-'~7$\u0017Mo]8\\oZq\\L\u00175e+XEr=xD9W\u001ePP>ܲ\u0006tv'\u0015\u0019|&!Ԟ C\u0014ꈉ;&;~9C6ͱ=\\Y[\u001cL|(?ZZMIl.odoq\u0006lq0\u000f\u0007lWؗۈMs%N\u001e'W\u0016M\u0013>S\u0018u\u0011l/{y3c}sݓ+/CF@k6\u0017ݗ\u0010Nhլ^]`{;R=<+QdX~~pU:SBg-\rv\u0004=5qѪtX\u0011\u0018d`\u0006?\u000bֵ֕\u0012W͒&v].\u001dT\u000f3#afrF\u001fYE\u000fjcѱ+b\u0017buZ~\u0005>gk|6rӞ\u0001\u0012<\u0015'^\u0015̩#\t(R\u0017=K'\u001cޙ{vi?0x\u001c\u001a*)Oe\u000f>ߝ\u001a\fm)^Oc&`\u0016C\u0019\f\u0001ꅦ\u0017f~+\u0015$\t.:=I}:1KG@]\u0002\u001aܶMC\\g\tI,#\u00073e|\u0001lgܣ\u0007z\u00114] \u001a\u001f^l>\u0004/?\\M=(5\tUח\u001dVe\u000fS_$gw\u000f^DM1ǜ^ZZ\u001a\u0004<\u001cF\u000fV7ؙ|z[e[b-t\u00121}_t4bM譽\r푍{\t\u0019\\\u000b=š\u000eg\nj\u000fRRS0\u000eI\u001f|_\u001bq>p6\u001d\u001bKY\u0004n)-ö3\u0001[ \u0007ʉދ*9f\u000e$\u0015~4\u0007dp&@\nȎ*QA$-{OE\u001ad\u0011&$=Om\u001b\u000bKi\u0010\r\u0017>u5٩lqNX)7\u0000h\u0007R\u0017\n3Q\u001dNovCV60X>_];b1\u0013V\u0003ZQ<SF%Nϓc1\r\u0011\t\u0010\u001b*!6A!2@\"͗U7vQ\u0005WU?3F9\u0012\u001e(\f3YEF%LY\u0003\u0013᮸}aⲲ\resx1hI(\u000b#wU5&aC&\u001aS$ŝ\u000b\u0015~\u0006oG\u001f\u000e\n\u0003Aгg.\u001dl.\u0005uzoLb'7*!7\u0013D~v˰56ӎa/\u001ey 7\u0003Ce<\t\u0016\u001c\u00130\u0006gxpPxX<\"\t\"MZp^\u0005ff|\u0013\u0015HVggeݻ? w`8;\u001f9\u0006gtߗǼT~ݒAwv +z\u001feM\u0004wP\u001dSC\u001e1B^tDdW9$$j``~@xV\u0016=kݥh\u000bj\nJݪ;(%ve\u001b'JWG4 \u0013042ukJk8`w9֖\u0018T\rP\u000e]h\u00151\u0003\bv\u0001\u0001\u0017`L~\u0010>>Dw>WW>WL\u000e[_iz6[\"f8S\u000370\u0014׵Em\u0012m\u0005\"\u0005QsTf?(\u0010v8y3BK\\ym!\"*ސz^nP\u001a\u00135(\u0013c_E[5\u0005t\u0002*!$F\u0002ɞB\u0014Crvv,\u0003K0m\u0018k\u001f],/j:\u0012+Y6E76d\u0014f\u00038\u0017lQ\u0017\u0010[\u0002js'+<=o\u0017A˟\u0007\u0015\u000bjw\u0006u\f\u0013}Mp]zP:\u000f/\u0013\u001d1/wfv\u0001?~ov-7tL542LY\bOz\u0014\\lQB\u0001)\u0015x\u000b!W\u0001 \u001ahjR5qYO\u000eRK%iw:+\u001cSG#0m\u0003\u001bm֢F5O&\u0014Z\u00056dmaE@Y.R+m\u0014e\r\u0007Ѓh͒\u0018G\t\u001a\u001eᤎ-?][\u0000\u001dN}Ձ\":u\f!uFi~?\tMbܾ{\u0016MFf\rԚ,3F\u001aKe}\rAC\u001dҜb\u0012\u0011.[lzE\u0017󎜓%\u000b-{\u001b\u0014JNB\u0017[=*\\\u000e\u001cty_m'\f{ڬV`#ѭ0F\u0003>Qc6OVoWN-⨦ڷ\u001a)uT\u0007<VtTNו|95jt9rfFo\u000e\u0003Cij*}Z3?o\u000bvtsn\u0015$.AZn;VѬμkMa[\u0005+0˹p\\.[\u000fVI\u0001FK,nض\u0018\u0014v\"锊)F\u0018Oo@IA\u001d\u0014\u000eP\u0001뫵\rZiһ\u0005Q~\b\fV+Уں_ZߨA\u0003o\u0017\u0014*i4+^4bL\"ѩ\u0018Tk\u000bEpW\u0013+xw`C?Å2*mR(c]+ý(\u0018S\u001c\\:U\u0000? wS\u0000+k\u0000k\"o\u0000k\u0015\u0019\u0017\u0019Ц_jj6]YY(;\u0012\u0006\f#\u00192\u000eDdR>uszV^oV\u0019\u0007\u0004VZz^F~Z9\u0004 \u0000o\u0019&p\u0000B\u0000l\u001c\u0000G\f\u0003\u0018HY\u0000\u001d\u000b9\u0014\u0001\\;K]\u0018\u0016+p/\u0013\u0001WU\u001f>Ojlm\u000b+\u0000\u001f~\u0014q\u0005\u001beW6-'\u000f`\u0007 @@D%c\u0004꼝?\u0013[u\u0019qZ\u0002Dp\u00001K\u00191\u0002\u0010&\u0003\u0004]gln\u0000\n\u0019tC\f4L>v\u001bq\t.?`\\nn$$㌫|Ș3$\u0015r׌^$\td̲2^$\u001du\fNn\u0000,\nh\b;\u0007|TU.qzь\u000f\u0014@q\u0016\b\u000fPZ'\u001dK\u000b񖼩]>yJ]$=;YqqAga]!I/[\u0006f}%K#\u0001\u001e]\u0006/\nϵ\b_\u001b]dvq!*\u0016\\{uqirW\u001f\u001al2fps\u001eGYszJ>F1yG:<C7\u0013$9Q\u0002)ggZZc5'g\t7񭣃~0\u0018{g\u001bg\u001egB\\\u0004H\u0001d\u0019\u0000=_@kf\u0014\u0018m|b.V\u0004%\u001fH&½P\"=Yx\by*]Z?f\u0006y^>:(L6k\u00179C\u0011AK'9Ǡ~?\u001c~/'Ż3Mǻy\u00119\u0002^\u0005w@=Ks>{O\u0001ZOFq{r\u0012}4`\u0006\ne`ry\\\u0006\u0005\u0013oz9rb\u0002\u0006gG\u0011wQO;|]ƈ\u001e[(5\u0006| *Xnh\u001d)$V1\u00041p?dqEo=wX9\u0013-y\u001fiξ_L,OBz{\u0017=΅3EJ7?VOth\\{^\u001e]\u001d6тĢ\bj,gXOhZ\b\u001cp@;ySκ֮u\u001fȂK4g%4_wi\u001eSi?^\u0015|.L>;\u00038\n]u,\u0007b\"\u0015H\u000bs\u0014P\u0012a^}gS6p\u001fw_*dyՉuúWno\u001br%\u000fx#bXZ?钌;v5mLQxf\t֖miHޠ|P4\u001aME+±4\u000f*\u0003-D{CUp!p\u001e5v=hsi}zESĤ`]ۨHd\u0012fU7+H&ͯiۆԽkN[\u001erq\u001e\f\u000b2pG-}c,jNy\u0016;M;\u0005ʐMP5:#k8:m@\u0017F@J\u0003~ul\u0014r0-\u001c9Z-r\u0018`S_{?ye\u00113ý\u0015\u0011wd\u0005\n4\u001d_>n:ٖxZԀk.\u001aԌ&%\u0004^\u001e}b)hF\u0011ZҿoZ,\u0000֞&VE\u001c[V}yBSF-˩])\\C6܈ML-\u00190bצtْ#\u0013c\u0014M6k\u0005F؎/~,O/V{f֞\u001fa)ZX\u0005KIH1_Wo^.Wpfy&^33:TiZ\u0016\nRp}ƩvȈ\u000fl\u0010@p}(\u000f\u001118ٔ\u0017Y6+)dezh\u0016\b\\kx瑪p+(8(n\\؟m\u0010̘'<=!U\u0007vLb+])iwrV\fϜn|Y\u0016\u0013ZQ/͙am{d!q\u001b\"Y簘}\u0017]>8~VNI)\u000f>T\u001b؜v@Rg\u001drr\u000e\t2h![㍫`;VE )q,RQ\u0013,YܩYQN*}ȞNJؐ]ۆhP'\u00145:B\u00075RϢ \u0007x[mڽZ\u000f(i\r#?YvԊ\bj[}\u001d\u0011Җ\u0011kӇ\u0005Ɂc/`!WqyFYq\u0003ST\u001fbhx\u0015GD0mvr^]Ҩx(\r+\u0003VY\ry瞋Y\fi\f˞tR[i \u000eO\u0013DnW\nB>\u0002\u001d'ȤEV$6*\u001c<0b\u00010\u0004cڝ4[|ј<_q5@>\u001agWrYe\u001cd\u001e*p7mjC\u0006+Ǎzo\u0005x^̧ʄYJpcO\u0002\u0016\u0015F͑_;_o>\\uX\u0014ucE3)r\t_з\u0011ڭ{\u0013MhQվ_\u001fbm{yP=\u001ci0c/ֻwl]pʦ@Z\u0018ʳ\"L{.,M^xY\u0015i)뽺ZU2X\t/FGq숍1\u0010z\u0005ci\u0014\n+(]_\u001ets\u0019@\u00162bK_GL\u000b\u0015Ga>85kb\u000bɳ飳>VA\u0005/Te^KkMy&5\u0011~\u0003!\u0002\u00184\u0006W\u000bpm-#*Ǳr\u0004аܨR\u000b\u001f\"5\u001aN\u0019\u001f\u0007$)UB$q\u0019+to9W\u001d]\t!Q2\t_\u0015zan^GNy;+\u0003&#ļ`7\t\u0017h̴̺=\u0001}\\4R?_)}HG6+r>%\u0012D\u000e7dXlu\u001eĖ3^̰(_q:O\u00016\u001dNhco)\u0015\f--q(~dKU\u00129\u0014\u001fq\\_`[I}tŸ|X4r|ʬ\u0007v\u001fp\u0017Y-p\u0006\u0016\u0011\u0001)NiH%S\\-s[äH%\u0007Ec?`ߋ;xFT-ǏWHǵ\u00117hvk\u001b!לP\u001aC=8\f+a!Aw`\u001d\u0015ZHzӐ\u000fBx\u0000?V\r\r\b6\n\u001czu\u0005Q\u000f\u000ef\u0019\b\u0014j3*\u001f\u00114ufJ\u000exfCb\nէ#Ry=)eiof{|\u0007#~U|/ܭ6\u001bNK=51G{\\&+\u0016/\u000f\u0006\u001a:*}d58\u0011Va\fa\u000b\u0012\u000bU\t8\u001d\u0015hxw2EPGSڥv,b,r\n:;^\u0019\u001a_\u000bu\u0000\u0006;S\rFJ$ɍ-r풘\fkX#Z9g\bc*آ\u0005>\n\u0006\t]%n\u0010w\nZ&\u00194\u000f@\u0013\u0007`k;.]+N'Kx\u00012jy\u001e`dsr}4\u0012OT^5QߕHS\u000e~\u0003#hY`W1Ic.pa\u0003\u0011&~`?0~E]=Y{܃\u000ex?[zu-v\u000f\u0006<\u0014{\u001cFG\u000f\u0005َ筦8|j*__U\u0000ԮW27\u000eÆ~\u0010=Õ\\nf8@nH|A\u0017YbS\u0004R\r\nOcf\u0001PJ~u]&\u001e\u0000\u001dI\u0013j\u001fB\u000b.;\u0012ֽwnT߹\u0006۹\u001b\u001f\\bd3o^(Qe\u001fX_\u0007\u0003j,'9*$\u000fB6#b\u0013b\u000f\u0007[mǖpFSA\u0012\u0002fɽ{Άf8^\u0007դJ\u0015p\u0010\u001aB}\u001b\u0011\u001bײƸeWNRl'،V5\u001f\u0007\"\u0012\u0000,}?w\\ r\u000bi\fZԯ_qo_B@h>5!Cn\u001d\\\rg\u001dt,in\t:ܷyo\u0015jb[f\r0 /\u001b:58\u0001\u001b:jTIފ\u0018x'ab\u000f#a[![\u00008FFl|\u001d{]\"a{#疛\u0012-j̷Ƶ\u00036קJ\u0018$,*\b?[U}I>՛SofXU\b)^p=Z\u0004vXur{\u0018\u001fK$IU5YvqӜa8UẁRZ\u0019\u0005?k\u00176}.'>\u0007.j2}3H+\u000f\u001e(V5YASl\"\u000fLE\u0013\u000fXr4R\t\u000eڝ\u0014,\u0017Kv8\u001e։qn&+e\u0016\u0013\u000fcn^|\u0012H}2RlC%\u0005{\nHH\u001bfV\u0011FiTŪWr\u001b_d\u0016\f\u0011=c\bRɸA\u000b\u001a\u0016&T(4٫^hrd?U|Gk\u000br'sJ:Qsm{\u000f4ۿ\u0000zC3\u001fS9H\rCtx\t\u0010j3\\/-`{30fZ\\\u00154%\u0011 VB\nݱuȩj_=e\u0005\u0000_+\u0003A\u0002#%\u0001I\u0000H,\u0000\u0013\"\u0002/\u0014@+\u0019@4Cg4#\u0002)pLqD\u0007[c~Y\u000eӴ0i\u001c\u0003a\u0015;RIՙ}JCJm\u000bAPmr%\u0003\u0002(G\u0000c\u0000\u000f\u0000ݶ?\u0000z\u0000;\u0000V\u0019\u0000G\"I[O6{\u0000\u000b\u001cm{=\u0000\u0002\u0013\u0000\u001e\u0003\r\u0012\u001fȜ7k8fV!\u0006j\u001d~5vq;;G0\u000f?oo[`\u0019Sk\u0000M\u0010\u000b1\u0017\u0015\u0000x`\t\u001c\u0001p)\u0002j\u0000\u0000Q-4\u000f\u0005K{H\u001c䭹fn0z{$:$y3$S$IFJƺ$T\u0018\u000b\u00190n\u00196CF?k6\u0004\u000f˩zW~\u0012\u0014P}\u0004ݤ,Z=7󻐔ہ脷)\u0000Cm!yYbU]o\r8t\u000e-\\2$U&I\u0014g,PW3,P/\u0005\u0004OZCWޭ\u001fc\u001e?\u0002~T.\u0016\u001aہAv\u0001F^va\u0019tng\u0014CS+t\u001d\u001dvֽm\u0006{V$5~\u0010e;9˅#U\u0005s|G8\u0007*wr\u001d뭽|7,J\u001c\u0018\r\u000f귖'w'͆ǵ\u0004\u0019\u001f%\u00053̎,<f$\u001fN7t\u0017VRh\b/kQ\u001fG&co\u0015KK\\{MKuYl_B\u0010g+.BC_\\U\u0001O9\tON|'83R\u000b\u0003;\u001d!{{;KIJJ0O7-aÿ9%\u001f|n>\\S^W\u0016OsxN*qGv\u0000*K\u001eݷ`7\u001b\u000f%\u001eQ\u0017b!0b@z+}\u0017\u0015cS3u\u0000aH\u0001\u001aZ\u0000RR@GO>-\u0006h?~x\u001dx=ʗT<\u000b\u0003b?miݜXBuh\u0000:Y:\u0016\u001c\u0014ϳh|`#wӦTupBھ\u0018covp![8p\u00036YdD\u0016޾fa䥹Z~4+󲂍 W\u000e9wJo\u0012e\u001a\u0002Y\u0005Tݪnc)no\\d]\u001fG\u0015g;>\u0011\u0003'\n\u001b\rUh1tnsq\u0016|\u0003W[VVLjPMyP!\u000bi9\\\u001b'].jovYX1;\u0018\u001dzqŶ;=Н){v]\u000boܧ9ـV\fEۚ7\u001d%\u0006y\u0013[xіݨe\u001dŤތe:2B)Ym]\u0007\\\u0012l>ѹ~Z\u000fin \u0018ȸ];E(<tˮ_dЁ\u0003%ygZ:}kS6[ZNi{mb!o\u0016G`kc\u0015\u0001J*Pl\u0016:[[\\[ˢ?5\fU8Y*9#nBh.uG\u001d\u000fЍ\u0002o\u0005Žp\u001fq\u0007bwl\u001dDGif\u0003\u0018^\tV,-\u000fen$\u000f}.>:T)\u000bMִǱ\u00015bj徏iSřF+ewsߎrRC@gg~E'\u000f늒u\b˒YF*^,^kٙ\"*K,\u0017MnsRfK]\u0019\u0002C}i\u0013;\r}gj\u000f*\fRe\u000bukX24\u000b!U\u0017;N\u0016\u0013@\u001e\tԟ!Œ\tҮ%(\n\u0012\"r\u0019hy\u000e\u0015\n^r׋E\u0007SGE\u000b\u001c\u0016jF,3\u0010 ^\u0004\bk\u001c0\\9zm\ne|}\u001cf|wW+\r\u000f!ŗ@5rBIĕS=(m\n|$X'??]𶗶=AnpMi:\u001ahg7dP\u001c'\u0005BN\u0010Sj>\u000b\tfEM^MSn^stVe>H}u-ƕ\u000f(ba-5\u0016\u0013rAq\u001brlqlapl`0\\L\u001dN8-Y\u001ag3p\u001d޴1h)_\u0007o\u0002XU\u0014\u0017ol\u0016u/|\u0018d\u001bsg3u]<Jj+\u001a\u001e\u001b\bp\u0014HBz˩q,~[Hu3eHS1bd$ۉKm\\,AQwc\u000b*NLxΫ4y[v/ϫXVϳ<pQvC'\u001eO\u001e>\"U@\u0002\u0018M\\G\u001c{lԭl]CKts\u001cC\u00035ZP/?\u0003\u000f5o1|svrBwsn#\u001ftluZD&8\u0012\u0001d[\u000b_Ǭ)sill)g߹R\\`II=|\bH3Jt\\Qr\fP\u001felΊpM߬\u000f\r}N?\u001aEssrxS\u0011\u0014&O+\u0016\u0004\n<\u0003NG\u001c\u00191n@\u0011fL[mcҷ`K\u000fхZ\u0015`ڈ?\u0011#xr\u00069Z\u000frb\u0019yG_?{=\u000fxT_J\u0002\u0013ѷ´|\\K\u0007UHġU\u0004\u0010\u001ar\u0013k\u001bg\u0002t:%\u0007\u001cj7^HOz\u0006Ojfdх\b\b$dpMC\b0R0]\u0012!߿\u0010Po\u000eK\rq\"\f1{}>\u0018\"[_>X5R:hnS+\u0004\u000b>gk\u001f<I\u000b\u0000\u0016T)@,DjFz.d\u0017P\"ݗ \u000f\u0019'}\u0012V\u0001\u001aNu';&\u001c&r㓥eC|\u001drO~x8VM\u0001\u0006:ҪV\u0014\u0017\u0017&x\u0005\u001a|]@v\\~;MSw@%9p\u001dHB\u0011HUd\u0012|)W.!\f-_oxrcAu\b\u0018٩Nв^\u0014\u0004`\u001e:@u+=I\u0018-\u001ch<#SBn$\u000b儨\u0011U8\nЋ~,)F\"r\u0013h4*(\u0013\f9\favU\u000e+\u001bJ\"P\u000f#pum9FՇA\u001e諁\u0017\fG\u0010u'ɀ\u000b\u0004\u0016\b\"\u0015> t\u000b#,IX=G,r=ۿUU!cˉ̧݂;~܈J[\u00029`4:Ur|ðڃ]3$\u001a\u001eOōALo\u000e,\u0011NKJ\n\u0013m\u0007\u001c8~\u0019\u0019ƋɠP\bGs0æY\u0015\u00075\\\bG!(-7;\u001f܂,*;ƈz\u001brNYU2\u00121q-\u0004}RX|SbW\u0019\u0011\u0004\u00177݁k5w\u00030<\fb\u0014{z<pz\r\u000bW\u001f\u0017\u000e\u001e/\nM+f\u0015w_#mtwx\f\u0016&q\u0019Q&7jX;|d#1U&\u00015T7]$\u0011\u0004\u001fH\u000ee2߄e_5z\u0011A\u0012\u0017\u0016ug%;Êcv\u0015\u0003k\\\u001bC\nOSds,;\u0011M\u001e!\u001d\u0006?&\u0006!z\t_\t<\u001apD7\u0007c^9ɦ{\u0013z\rh?=s.\u0004P\\}\n\u000f6\n=mIh~j#3F\u000e\u0011\u0013jk@4:\telVN\u0013\u0012\u000b\\i)\u001eyg.,\u0006k@>efSJ+*Aiu/@U>Q,Yl$\u00186&u\u001dZ\u0019i}I-T\u0013zc}>\u001b,h\u0015\u001fny\u001f\u0007m8_&VڭT?m\u0005fP$=:\u0011bX\u0007oѽ\u001ce\u0007!\t۶q8_[vK\u0003lʓ~G\fӤ\u000f,2YݲF\"lp,?uYդOŬzS\u001aTdlKU/$/߹yq&&fN\u001fݷ?lN\u000b(&nnt0ۦ^4KnY5C.nA\b\u0015N5\u0019@\u001fdUcʭV[mrsle\u0001\nky姧e\u0007Ki\u000e~%4'a\u0016T\"N\u0010T\"6#&8\f]uF\u001d\u0002`\u000f~ǣɩֽm;]EN#\fzM>1J5}Ql*u-\u000epT%c\u0016i,W,\f\u00017\u0015\u0006n\"\u0003Yq\u0000+kXؾؤ \u001eF\u000e.Ҳ\u001fߎ%8͖\u0003N\u0005]\u001f%[\u001f`\ra\u001a\u0002R\bگ7\r\u001aȮuex?f`#\u001ak6ubW\u000e\u001f\u0010A&0@4C恁_Xe\u0007`p\u001c`ƛ\u0002\u000fA\u00173nPFe3~\u0002f\u000b2{\u0016\bFPN\u0015t+l'쪴\u0017}CuUk>2P\u0012\n\u0014T\u0000x,3\u0004\u001b\ro\u0003\u0001\u0007\u0000'^\u001e@ڝ\u0016\u0016\u000e 24\b,\u000013)ﳣ\u0001d\b3\u0014@\"#H\u0003\"N-#\u000blL\u0014\u000fu[y\"_\u001a\rjϊ%P\u0002@\\o=b\u0003Ƚ\u0019\u0000h9\u0000hmu\u0001^\u0002P\u0001\u0006\u0001TZ\u0000\u001a5p\u0000\u0013\u0000H;r\u0002^\u00040\u0001L,)\u0019N\u0000`#/g:Ae\u00180cg!dy\u0014#\u001fG!\\X\fb\u0000\u0014g\u001d\u000f@Cf\u0003$ot\u000e5C\u0007V\u0016\b`BL/8E\u0001\b\u0000{\u0006\u001f#?\u0002@\u0014B\u0018 @N\u0002Vk\u0000]g_~KIz\u0004$\u001do$$\u0019\n$p{|k^1cxbIB\r41AG{}Xgr*ʋ\u001bI\u001f\u001fgQď[y<*Zs\u0006]x:\u000137jsg\nk{O?$\u0011&FmIHT\u000eo@,&úds\u0019F\u0011Nm\"I\u001f#h\u001f?=pO{}YnRZZV{=\u000f˵_\u0017*^a\u001f/kS.FgLl}3~Z5jZ\u0016ǞO'ivN\u0012a:Y蔲jgq#2\u001d=vk\u0019u91׮\u0012/Z>795~eD5\u0007<Gpr:WO#CC\u000e\u000fʮzG2r\u0016mO8y\u000f@1^XN\u0006\n#Owq΂6W/k\u0011?nb\u0015l\u0015\f[9S\u0017c/\u001f;\u001d\bi\u001b\u0004% s\u0006m\u0017;\u001d>\u001cbr6.AzzK]&$./%O/\u000b2[\f\u0017-^xQ^[G\u0005Þ <69Q=\u0002<2\bZ=\u0004O[\u0000vMcT\u001aX\u0014gckN0iv\u0010#?Q`}''-F>s~ͮޞ\u000fXH\u0007o';\u001fÝ%\u001fv>7ru9~M9'\u0011cyQuM;Dqz34\u0017\u0010\\1f='a\r0zc*u\u0005X0e_oU]Os'V\u001cL0\u0019\u001bMV2\u0019l/\u00102x&\u0005൘\u0014ɡ/z\u001d39wу{q[$)ٸ|\u0016oco\u001drʝ|\u0011ݽL\bɻ5^vt[\tr4c?]\u0017\u001d\"Eh\u0001\r,gE(1\u000eѪ:u\u001fYڋ/Yx\u0016\u0002xr?Z\u0006\u0019[+{ZV\u0018`u7Lf,\u0012S伣\\Z_:eq\u0006ikczزh^~.7\u0007nY3֓\b2J3xU\u0003Hy9\fk,.z\u0007\u0017D{6\u0016A\u000f0{/\u0016رފ;_6z*\u0003ks\u001a3y%sڈ3Y$L5Z\u0018\u001b|l\u0019eWBA.x\\N~\">ˇe|.z᳣݅vv\u0007ekyXػUlSTrG71\u0001\u000fDHs5h~61\"9$BF+:OU&n*9\u0003[\rQU[bK]\\{j׮ݍ@N5nXB'z9RY\u0000*<rT%\\Y\u000f\u00011iN[\u0001\u0007Μ\u000f\u001a\u0018>nq?XuF9V:$\u0018\\M_=j\u0005.ʻϗ \u0018\u0010RoV5D\u0005>Wok^?\u001b\u001c,b`Ӆi;?kH\u0006rh\f\u0006ㇸ\\jrC\"Bۚpyj;Nc(\u0002?\r$9>Z\\uFIԕ:˲|=\"ҚefU\u001b\u0011I\u001e1M\u0016bHJ\u000e$\u0013H$TDCYyH B].tR:\u0005Xu$K+H\u0004̱.fjBclajkv9h\u0018{+3K-6kv&\u0013\u0000Oe/\"8\thGDd\u0015\"G`i'\u0000랧[;P+\u0017&\u001b#Yd֠ڞ\u0005fw\u001bB_MBWM\rv]DT\"x/O[븸\u0013\u00152T\u0015rm\u0005:0\"\u001c4ѡl\fx@\bY\u0012WF{ʃ2\u001csA-v\u001f\u0007lm*IlLSIc1\u001d?\u0012\u000b#i\u0002h{ie;p.*\u001dR?N\u001d\u0007&UC\u0004ޟ\u000eU>|zz\u0010MO*=7iI4)'{\u001d\u0017kc!nÝsHQ\u001f;J{Z'/*EJz\u0014\u001be둷39kd/?\rɅ'D=u;%Vgǚ5횣A\u000e\u001e3sɕǂ>*K\u001eb\n6`;Ȑ\u001ew@7jN=Ap;J6\u0017<\u000eIn\u0014I\u0006AyI~-m\u001f_~\u0018o˹ޱJYѯC\u001dQh\u00161-UuaW\u0017\b J \b*(}Ȭc}CNA\u0010\u0010\u0011o\u0019\u0006\u001d\u001e7c\u001dz2\tl\\\t\u001brT2hWK\u0010b+\u001f/Ҹ.?V\n\u001ek\u001fK˖P\u001e]h2qṰ\u0013\b˫hɫ֗W}㑓!*\u0014@α8X\r~|b\u0013Ro\u0000a\u001eoZug\u0016w\u001dz\u00001J\u001a<;ztn\u0005cvnK؈^$5]ƌ<g\u0006KC|Mȼ\"%\u001ff\u001cH\u001dECv1\u001f\u0003_\u001cÒd/|\u000b>47r\u00061h)U8RJ[{k?J}вڍҜ]\u0003\u001f[-X̥m\u0005 ]Dܲ6|\\\u0003mZՉ,ܶ\u000eܨBi\u0017^RP؉@\u0018\u0011]T\u0010Bf\u0012Bv{\u0016ν\u0000'2s\u000f;TXaVf\u0001FJ4w.v!ymZ{o-ٹw\u000b\u0019\u0018w4_砋C)\u0013Ί$B\u0016)ֆ'\r&q2\u001a\\xBo\u000e\u000fp\\\tt\u0003\raWs/s9\u0002s:\u0018I^\r#\u0015r\u0003ԩ}d0d%N#~,\\HEv3}߫مl_Ej}\u0016X+\\\u001bP\u0017e9g\nR\u0016e\u0005\u0011ikR0bHe\u0019\u0002Sc|Q{k]p~Vd\u001d;cUQeUL@\n\u0000vi(;fʿ,Z\u0014*'n\b\u0019E\u0005hWv\\ƊL\u0006=}\u001b\u001a(\u001de~c\u0005ܣth\u001fRm?5iY$kU\u0007?z\u0019s\t\u0005GvYΘ99<1\r.+%\u0015ڴ.UWj^~J\b\u0003\u001f\u0018-n'U=\\^Jߠ͙YitJzYv?\t ⹒ND\u000fo(#/\u0002r)nq#|Ep=g~0fJΖ\u001cSK\u001e\u0011\u0006Ϲ\u001bd;/c!]&\u000fb*ƖˍKjr}0\u0016f¨\u0006rbgf{4d\u0006\u000e|Qm^\u00017&KN#;\u0007/)lX[\u00077Հ\u001bǉLs4 [G$!.%2߫\u0018V\u001dgjwZL뽕G^g\r\u001c.1DunRw>y-jf^^;4>W2\u001ca\u0016gq6YC\u0005\u001dܺS\u0019ú17P\u0007@T-dJ*dBՉ+#D\u000faެG\\K@f]\u0017>~\u0011\\\u001dw%\\4\u0007doOa\\\u0016I}Z?[ىJ\u001e\t'hT\u0007\u0017?\u001ad\u0006R[E:4Yx \u001c2\u0016\u0011a`;YIAކFp\u0013ɫ)Z\u0003:O\nu\u0019/5'_-%\u0005V;V\u001fJN0\u0004]tG\u0010o(^\u0014epf4=B+Ų73J[(vOǜP\u000ecv Q\u0013\u0015\r\u001cjUZW\u0011=6Zs\u0019C\u0017\u0017\u000b #4אV!^%\u001f\f\u0011ҕ}e<<\u000b{\rǖen ާQ?,\u0010%Zsk2<_\u001bqpӰ6[3$¯\u0017WgD\u0014\u001f3[,\u001fc)\t{IBIVN\u0012\u0000\\ލ4-X3o\u00114\u00072J8@%@p?\u0013H\u0011\u0019ݱ&\u000e\u0019ﶀ{*\u0013nϏϒq}rL2\u000b_\u0003^\u000b\u0005\u000fY\u001a5\u000f\u001a\f!+\u0007\u000fGX\\\u0018J\"*{p]\u000e\u0006Ai֩\u0017N\u0003\u0001\u00175\u0004\b\u0011\u0004\u0001\u0001t\u000b|N\u0000mSM\u0016BOU9z\u001b\u0018+PS\u0018v)?[F\u000e\u0003lHi5\u0016\u0018\u0007Z\u000eSis@v\u001d\u000f`b\u00003&\u00009\t`7JΌ\u0005\u0001\u0016>\u000f\u0001\u0014\u0000Lr\"\"\u000e\u0002\u0006`\u000bB~-lAb_]@K]Cف,m\\i{l\fo\u0001kx\bѶ\u000f!)uv\u000e &n&~ε\u000bWdO~o\u0000\u000e\u0001\u0012?\u0000眰|6n97//M0\u0002-Q\u0001P\u0005;\u0005{\u000bX\u0006j\u00145埵ԥ]nWD>E?K\rF5Ԥx\u00186{e~\u001b\u001d\u001fM\u001b|\u0003{\u001d\u0010\u0010\u001c}h\r3\u0004\u0003\u0010r\u0011\u0010\u0006\b^E\u0001ɼ\u0005\bS~_{\u0001>\u0002£a\u0002b>̙\u0001\u0011^9\u001eC&kQ?6\u001cU\u001e\u001d!;\u001e<kƫ}D;ag\u0018Z\u0001J={,y[\u001agEp\u0001afp\u0017G@,\u0017Ho@z@\r\u0010_\fH<\u0019\u0000q\u0001Rк\u0003Ҁr: -\u0003@Z{@J/\u000f;ظٻd\u001bY&?,S@%GmYr54\u0014idB3\u0007˺ RrW8j'\u0015YfG/tW}lﷃ~n\\Nvpr\u0012\"{\u001f.y1M_2e\ny\t\u0019+wѼ,'̈́?/uORU\u0010\u001eHH-Xw/6n\u0007\nn~\f_;@\\z8Dt}~>i\u0014Kt:K?iBUݓzshp\u0002{^qi?\u000fxMv,{y=u\u001e|^F$9$/}k.?IZx[{_ |M%\u0018\u0004_\"B_\u0005)2\ro\t;t0ӤntN`hpȧ\u0004Y{y\u0017HiW[um\\mil\\\u001b_~\u001c6F^cU̟\u0003Ws\u0010n^ed|;0ɕ\u001c\u0017f=6/n<M\u0004wѸÊ]c8\u0005\\9zal\"t\u001f3\\xy%=Dpȥ%</{J5\u001c_\u0019kyV0웏6m͊fA^1ޠw4haooD^S\u001f\\!J}l\u0005 Cby3n_(|UzJtv\u0003M79%*%~r޾\"lr^Z>Y^Pwuﻉ]z;i\u000b5Φz`j\u0014\u0019\nx\u001fhf\u0018/a7\u00030۝Sx\fi+ɥԶ'tc\u0013\u0019O!tZ<h2)\tr83ĿdE'\u0013/\u0005\u000b\u0012{|yCl݆\u0016\u0017r}U.E8)\tx2f\u0013\u0006i{\u001c:z}Hy\u000f|!\u0001MTۡk\"\u000f\r/{4@:3zn\u001f@zkRȾvY}:B[*~*9Pq_GOm%Iƨn*Mf>\u001fZO\u001b%Vh'O4fMq04d\bˁ\u0002A\u0005c/\u0010^q*pu\u0019Jq\u0014]\u001d)\u0003o[\rG+\u0016-/kO:1n ]\u00178,|{m<\u001eؔhS\u001f'nPIOJܤV{y?y]^9\u001e\rmJ#\u000e6yH\u0015=\u0014*\\֙\u000eE砽u6<\u001a\\i2\u0017fi\u000b\u000e\u0003\u0018냬3tŧ\tQ~ms\u001d}\u0004dܻH-kla{wX%\"P0~XaG\u0018q'|M{ime\u0003\\\u000e\u0001\u0004Mcmu7m^\u0016\u0010Rκ/ҿ辫\u001ey^OayQ%ISz$\u001d\famo\u000f\u000fc<\b\u0007\bL\u0010:AWHh#FUl-(r\u0003:)Nmi2M_AͤUM\u0000RqݫKC}y\u000f4_\\$QwQG,״ZQO=Ү`{ߌ\u001a6&d\u0011j1v[r\u0010窟noO\u0015yoٌd\u0011bR˕z^ECc3/\u0014e{xj]\u000b{\u0001kZ\u0016t^*\u0011\"\u0017xV\u001f4}\u000erc\u000f)#\u0002u1gQTWR,M&PJޠWݷk<ƴKbҝ#v?NK\u001d\rl~ ˻wf\u0006(ngFX\u000b\u000fv3'T\u0007<ҳ\u0011\u001e:\u001a,A85+A{\\[k\u0017i^c=w\u0006-\u0014NK\"9aN\u00198~a$ZM`ii\u0012\u00103paůqa]{fUK{6X/9ov\u0014\u0007\u0004؟낰\\O\u001df*z\u0016۸S~prO[x{1\u001dycr\u0006[73qAk\u001b%\u000bo\u001bo6a\\X5Pⲡs}G{&.v\u001fU٢XNW\u000bT-{\nP\u000b/;P\u0017~aXH\t<\u0007c\u000b^\u000f\u001by\u0019'\u0013K-f]gٜM{h̻q\u0019?\n\u0006\u0003>`ofΗ\u0011R\u001b5A0TA;P\u000bPu\u001fH\u001eS^{DEKm\u001c˶\f_r?,?lF\u0005;o}|^\"8nntmLa#'Ѯ֘lAp21Id\u0019S'o:\u001ft\u001cN\u0010u|TOYe5\u0005VHOgv_FJrM\u001axʢxVm*aM#a:/\f\u0019n# \u0014c6\rRj2Lq\u0010kZ'u\u000e\u001a\u0011\u0001&z\u000b-&ɳ:Q\n27\u001c81xaIh\u0019٭dïd$\u0006;\u0017kUd1\u000b{\u0017\u000b\u001d1>\t\u001d\"!m\u00163)\u0003\u001fn%0֩g\u001dBc ۫l>\u001dŸ\u001e:\u001e\u000b\u0006u\u001be~NJU}\\/J;@Fn\u0012b0tx.ML3\u001bh\r;u@{V4D{\u0011\u0003\u0004/U\u000f/?\u0018A\u0013U\u0007n\u0007t'w\n֫qS\u0006\u001dg\f+\u0018$\u0011\u001dV*\u0006uW-v}\u0015,IYȕd/U^x\u0015A*!B(Uk\u0002u\u00158::\u001c$\u0001'|\t\u0003H|Y\u0005HV\u000e+ۜɎ?@yBX[bxLohwF\u0010[v\u0007F\u000f\u0013\u0004m\u0018Z+J\u0019Yr\u0007ؗp[\u0011\t/J\u0018\u0005..\u0017s81~SG\u0014V\u0019;\u001e3}$1\u000f-\u0003^|\u001amM.\u001eV.\u0019\b52;=*]xoճn6\u001e|\u001a(*KE!Jĥ\u00104\u0014\u0018=Ғ\t\rڕ c^U5F;\u000bOͪC#Nr\u001b@\u0003\u0016%ǥC%OW\nM%=܃)\u001e\u0015EXS\u0003\u001c\fe\u0011p-h>\u0006\u000b2ebߗ\u0017Za:eỹʙ1^\n@;t\u000bA²@\u0006$kwKt8Ƚ~\u001d%z\u001aF\u001aY;_W\u0005{K\u0018`ayֺ}\u0006\\5j˛@+SvO;Q\u000epK:u\u0002cN*/.j\u0002֜F{<^V\rx>\u0011R\"V\u001aLǭ3)uj\u00039ጏx\rGBMG\u0004>GA'\u001dO.\u001fɦf{U\u0011i(}k^l<~2/lP-}ڽ\u0018lm泪At〠\u0017^_\u0015_^r\rֽ&>_3x!X\"H0Q\\UhY\u001fcK{bvʯ\u0005+\u001e\u0012VGX9P^\fXYh\u0018&>5=8`\u000bOƭ\u000e nKѱ#@\\]!k6|\u001f8|\u001ed\\}:\u0017jAx*0\u0007}0A<m\u0016QOUQ\u0003\t@UJ\u001d<\u000et\u001d\u0010\u0003׉ɔS?F}y3}G?yܩ2D)1@ZzJXZ\u001bt>ĵmsyFWKI\u001dUZ,WBU\u001eڏ\u001eBWqvS^9n@gJ&K|ь\u000eaX`tt\u0003t\raJ\u0005\n@<iB\u0007\u0002XaĮ\u0019L$rlD|&\u0001\u001a92ٹzmR\n\u001f\\$\u000bdo\t\u000b8X\r2*\u0016\f\u0012\u000f>^a\u0002\u0019\u0013p\u0003t-1P\u0017\u000fؒ\u0000ۙ\u0007b:1.\u0019H+߳(R)QH-\u001f}\f:>*]\rIn\u0014\u000f\u0013\u0007\u0005!E\bf]Lqj[VIkX9'\u001b\u0005`\u0012=1?K=Q$,7\r \u0004F\u001e@M!@qN\u0000u0+\u0005P\u0000\u0013@,\u0018U\tF\u0018CG;\u0001HwdC+Q!ek{Lאy\\O\nvuý\u0019pKUX\u001c~\u0016IY\u0000s\u0001]\tr>S);!||\u0001\u0018[\u0006\u0018g\u0001F.89\u0004`\u0014\n0j\u00020\\\u0001\u0018\u0001.\u0000M@iG9]ҧS-K\u001f_=}u0RWV>\rɁQXO\u0003S\u0002Y\u0002X\u0003,9A\u0000̼\u000b7\u0001XOZ\u0002l4>\u0001\u000e}\u0003\u001c0\u0000\u000b\u0000|)UGNZ\u00038m8g\u0003UmG9TmTuO^Q\u0014\u001aћ<\u0007WUq7x96Ǖ݈Jj!\u0007f<^\u0000\u0015\fD\u000e\u0011s\u0017ĭ\u0007p#=K\u0001\u001f\u0001i6\u0007Zy\u000fF\u000e;\b\u0016\u0001\bՊ\u000e\bl~-nl\u0000\u0018@\bz> Ӝ\u0004\u0013\u001fkՈJ;\"\u001dCr#aYaNǤT,C\u0011T\u0002]̚\u0000zI%7}m\u0002\u0010p\u000f\b\u0015\u0010.\u0017 \u0012y[\u0016\"{rb\u0000b&E\u0004T\u0001$6Y@ :\u0007q|Ȳ\u0011,eeL(o̺Y^e\u001acMRX\u000bIy@h={-x\b/e}Tgw,f7-\u001cnyqv\nJ΁%*EƅـU\u0018fg@sÿd\u0012[Є\u001f~K`zN\u0019\u0005m\u0004\\<^z\u0006<1vR3WOҭ6ܫwoeG/KT<5/9Woˣ4ӷ%\u001eN%|\u001d,\u001fAS=؟EsU\u0017?\u000e?{doSʋ~K\u00189\u0013,T1Ocg\u001e_kt\rە\u001c%\u0002\u0003\u001cL8\u001af%MРv\u001eyRS=)G8\u001aN^cݯ\u000e\u0013jf2DU0_:&욿2ENgZu:ռQR__=U]S^J{0̓\u000ftRѸ\u0007$^hp\u0005c\u001alK&\reg*kot=O'2\u0010\u0017ƷWz6w\u0016<GzΙm5\u0003\u001d\u0007Ҽn\tyB\u0005=?Y56]eycW\"-\r\u0005kūV\u0005/'yе\u0004cp\u0003-\u0002.Q>w\nl̴̃D䴶[IN\rx>\u00146f\u000bmp\u000fK_d\u001f[Vg\u0019,\r}hm?Mф.&2w@7q\"S\u0016%|gΝѝm֬ʞ\u0019Os4l\tUHcvF',$ouZIÛ\u0012`C\u001d&us\u001bX:R\u001cq\f'\u0010FQ>\u0018Cf\u0005[^\u0004\u001dHǈx=Z\rcߑV֫\u0011uK\u0017=oh\f/߫S\u0002O\u0016^¸7.h\u0017XF9%\u0012JFk\u0014Pn8ޛaލm\u0007l}\u0019;np\u0016ofGwRG\u001c4\n&\u00101%\r\u001fo`m7+VRp\u0002v\u001d=\u001fj*eޥ\u000eg{mq=GR\u000b&*E\u0006\rS\u0019 \u0010&ƛ%\u0018XzZh@ӳ\u001fHq<.&b?r.?\u0018Ci\u000e;Kض6$\u0007xypo\u000f,v<k\u0005M`0vn~ɵĄ\u0007\u0004쁋F6b@(YQ\\u#ٽI\b\u0001LV߸SDim\u000fN-'9JC{`\u001bQ-VryvȄ:6\u0012\u001e˛ܯK+\fG\u001d\f\u000bq\u0007B<%g\u0015w\u0015\u0011(/!0\u001d\u001d\u001dE{]oknbnXr\u001a-M}\u001a/ak{l\u0012z\u00008\u001dQ>rŤ6>r\u000fcykn5G\u000b/Kx$\u0004\u0000&~u>\u001a=z\t(m\u001dϧVr\u0007{\u000e\u00052\u0006Ǜ]\f'A~]~ \u00156\u001cwHO;O8lѺQX{w@א\u0003=L^\u000em[ 8-:ΒϑЩ\u0012x@ׂrO7oyys&(7?37+96VXCmv\tg1h\n(=\u0015{\u0016j,}<\u0007\u0006L[YB#5u_\u001cՎXZqʮй\u0010ޭz2lt]nm1_\u000eoGym8qehnL\u0007j1\u0003\u001f\u0005!@\u001ai\u001e\u0006`\u0006b2eP=ѯGeGuk=i:\u0019?N옗\u0007߹e};a5\u001dJ~\u0006&?\u00147>䘵\u001aE\u0012\u0012Llg@9XظGxu\u001aRT2F7@@:\u001b\u0016IW\u0013FX\u001d\u0015KU>\u000f\u0015\bN\n2%i_lm:o\bsp:;ݐ \tޓVHl\u0014[fvfcUlq\u001bʮGy\\t=\u000ej\"L!T\u0012\t*:^CBsy|r\u0019\u0018F.\u0017d39Z;\\\u0019MKW\u001dk]i\u0007z7\u001c\\`\u001dK6\n\u0002׫IuߠzW%P{\u0001B\u001eiQ?wP\u0015;\u0005rV\u001b@\u001cɋ\u0017eѥwے\u001a;f*IHHl\u001fUlCyv9\u001fD*{&,i\u0013c3\u00184LwGX\u0003f\u000b\u000blSΠ{\u0003E\u000bG\u001b\"ǖn=U9Gʌ\u0004\n\u0014\u0001kyV]4ry+HnyT3o/_(\"~©u\u001d\tm8\n\u0001P/^, \u0013f]t\"bvC8\u001bgIpZ\u000e|o\u0006iWUHju҆6'H7³)w \u0011p46Jr[A_J7\u001f4`\u001d\u000f\u0002)D;<F\u0003Qw\\rqʣ>:s[Q*\f\u001b\u001d\f[3&dwVU}^]Hdɧ~\u000f̝Q`\u0006-F\u0007\u0012\u0016= FyF\\HV\u000b\rDg\r\u0011bM\u0004JN\u0010Nшz\u000bV\u001da.+\tM\b\u001beoص\u00177\u00056\u000e)z&\u0018 PuB\f?êcA\f.'tr(P4=wkƳ|c=щW'\nl'P6\u001fk)ҥ.=w\u0019ï־Mm}NϗͿL\u001a:nɻ;i6AگްQ*\u001b\u0011 I(%̅%o y}&tRonp\tK}'1;%\u0000ց+\u000f_zaʴUA)jݴ4\u001fT%\u0015s#X\u000fc;\u000fϣqrk26T%R\u0013\u0019\u0002Ѹ3_a\tq~4|G~%7\u0015\u0012\u001a떥\u0006\t!\u0005yb\u001e'X\u001b\u001e;\fm?\u0010,g,o͝VQ7T'6!\u0013k\u0018\u0010D\u000f/\\R\u0002ZԥfR:ryE\u0010\"\u000f㢘a\u0006<ޓ\\xooJ5Eu[4}D\b_o\u0016\u0006^6^ˏLצ2#n{Dْ֘8=G=@\u001fˇ/Իn\u0000O\u000fT/D[\u0011!\t\u001fne|86ae/Iby_һ\u0006:auNÅ5THX(Z^afv\nԖ\u0018\u0019J\u0015\"\ruC<A1k=2:\u000bĵ85v7xv]WQjjsk\u0014Linc&U\u001f\b3R:C֙8\u001b\u0010ofkʹ.WXi#\u00173֞|\u001e.0|$I\\TY׫:+\u000e,!fI\u001c+\u0003\u0001]O\u0007з\u0010\u0018\nB\u0011r6H+\u0001Ւu%^{ȱ.--uN'c6}!dy/yJ3̻5z]dµ\u0017(Tg^G\u0005A]Q'+:\u0010+5l\"#!V=DHLʗ|]sd(RYS~ 8Cmx×pz|Ò1aC:_\u000bl\u0005\u00062\\~po}^敺w40aTs\"R䉸u\"i\n[+@HGy\u0015Kl_.\tΥ\n\u0002#Jpo_\u001c\u00170 Sh!mt}AEU@\u000bp\u0017ͅ䃫x\f:\u0013\n:\u0007\u0003>\u0004\u001d\u0019j\u0003tݮe7\tj{07\tJ8o\b\u001b`3(f1\u00128x\u0017F\u0010X\u00016.\u0015\f+\u001a!\fظ~d\u0010\u000fTh8\u000f[}d\u0017\u0000+rz\u0000@J\t\u0010sc\u0000\u0010\b\u0010e\t ڣ\u000eωf\u0000\u000b+[\n٫\"J\u0004Ƌw~ii\u0004kw(}e]*\u0013\bXWρFٹP.\"\u000bZmU<\u001axN\u0002E\u0002\u0017jX>@A\u00182'\u0000TRI(*\u000f\u001f>cBFW\u0002\n@\u0015J:@ޯ#|\u001cT>yP\u0016\u00063_\u0006|l;L%*6]Y\u001e\u0014}&\"dLBf\u0010AV#\u0000\t\u001cZ\u0004hL\u001b\u0000\u0000\u001dn#\u000e\u000f[w\u001eo\u0000=o\u001e{0\u0003Y\u001eyb\r\t\u0003c\b9%RE^.S֚\u0003r\u001455mX<\u0011v\u0004j'.hE\n`\u0006\u001f\f0\u0004\u0002l\u0001a'?S-\u001a{e\u0019>\u0006~YΙ\u00016V\u0000B9)\u0003nQ'\b`;caw60\u0017t'nv,t\u0019b \u0011.\u001e{\u001bEo.@O>YjIq,.~6\u0018$u\u0004p\nR\u0002\bq\u0002E\u0002j\u0000'B 9\u001f\u0015ߣ\b?eN?\u0004pI9 u@Hfi֙\u0010{\u001aۇ\u0015\u000el}\u001f<l\u001f\u0012I%/_,+os\rdp\u000b\f\u0010hk\u0007\b\u0019\u0010@\u001eT2 JU\u0016\u0010\u000b\u0018\u0010\u0015\u0010\u001f\u0014\u0010?\u000b\u001d`\u0000H\u0015pc?r,_FʄYB!gg_E@?CC~\raC羥[ݽZw?l\u0014jz\u0003]S\u00129F|&t@&DNo&4+\u0016\u000eA\u0007zMJb4ajہ#k*a+9U#֯>,^9eH3W]6O\u000fO;8\u001aV޻ѧvA`@ښئ/S<c\t=p\ttО6~!X7\u001bjwu*9WiT&ӷ9y\u0003\u001d\b<Ѩt\"vyvJ6\u0006/u\\uWYHWY~c\r_N_,~KX*}U_\r`wܫ_$L--lqTѸ\u0010N]\u0000\u000e4nla:\u000fk<\u0012by_I;i]%\u0018?LxJE92ՙWӃ.\u00016}N\u0005O\u0016\u0017YKX\u0004\u0007tM\u001c\u0017W\u0003ʻ\u001d\u0010U\u000f.zI[~Ê\u000402 d ;@?dA`WږO:U<!^6^q讫#\tI\":;\u00019\u000f4h?haGbjw\\2r>՘.WY_Nma<\u001b\u00074(Ip\twqTKm̤mc\u0014Smg߆~pN\"6p\"&CpZ\u000fL+~\u000e/g_u.`5\u000fu'>gocޛj\bE[@\u001e^n\u0016}{ĩaVO:\u001dr?}\u0014O\\b\u0002h^e-<|X\"j`n\"nPꮔy\u0012_ݾ~zG\u0017{-Lg\u00169n#=woZa}.|>\u001bPn·ѵt\u0007>>˜_{?ꋞE8gJ\u001e\u0019߆?\u0012Y'N\n`\u0017\br=Ĩ\u0012\b)kvht({\u000b].\u0001%םP\nΧ\u0019\u000f;il6\u0000\u0007h-+*V\u0019q\u0000C\u000fw{qǍTq5\u0019}o\u001d<̫\u001c\u001d\u001fM[NT0\u0014Pk[k45Po\u00121hGSzn$\u001exs/t@\u000e|lC0Q\u0017i!(\u0007[0t\u0002,Xw|LX6;yjG\nCXd<2ƍ_hlosшx\u0010\u000f\u0016޺!\u0003Dױ}zfg\u0012z\u001dkr!خK\u000f?~ƀ45&%5\u0006Y7+t,\u001107\u0019pn\u0000~\u000fvupc0\u0017\u0007\u000bd\u0016JR^+cz>W\t4#I\u00047]\u0012<FN\n5\rA\u0013F\u001f?:LϯIz\u000b/o3;Swo7Ț\u0014\u001a\nqEi79:[6lZXqP\u0005{,tM]\u001a'Ʃr'\u0006{hi\u000fXY\u001eڿo52B8\u001a\u0000\u000fp\\&zj`/xkQ0\u000fsG_\u001f\u000eȎ~ߗT\u000exS\u0005\u000b\u001d\u0017:ﯲѮ#AݾU+\u0001ŧTiZmv&9_6\r\u0003\u0016'f0]\u0007Vh-\u0010gZs͕J;g1m/GF\nr`yf\u001dsm֨h:\u0017\u001d@q*U\u00138oƦp\u001eR,)_~S|4zMeR\u0014XäJMV^\"HP)Z|Ԡ}&`\r5+\u000el5\u001bq\u0014z>\u00173W\u00184\b\f2Wm7ԙq=JŃEMMX|\u0017\u0003DX7J\u0001UUGQ w\"/,V\f*ִ\u001b<'jtc\n0qI\u00170ff4n\u001e\u00068\u000b`\u000b^P\u0010F>_\u0010ȃ4qD\u001dM @>VOF\u0002`8S40J>\u000bK\f^V\u0006.9$U,\u0013M4\u0014\u0011vyjn\u000bGފj:\u0016`b:\u0000c ԍ\u001fv\u0016ρ+y#VYJv\u0005}`\u0006\fʲaUM۴\n(c]fˆR4.-L_\\\nˉ(4]&|\u0002c\u0018B~vs,?y\u0014k\u001ev|hOC󡬏~I$YDC<~vCo5*5-m\u001b~[\u000b}i\u0003\u0006+#\u0001.+\u0006VS{d&ҺcRfb\u0003ob\u0011\u0013⛼zA3\u001d\u001eY\u001c#\u000b-b\u0002bU}U/]\t5/O>qN\n`.~\u000b`\u0005gq,֬\u000e\u0005i\"\u0005\u0000ȋ]R\u0001PiKIʉ\u000eB\u0002}B\u0011\u001f~#?\u0010wס#\u0017jwavHIV):̘\u0017V\ng\u001fF-\n|\u001df,~\u0012fL܇\ff\u0019]k\u001bΰ\u0017\u0010\u0013vSۍ\u00117¨\u000f@\u0018~^\fndf\u00124\u000bxe]p2}|0\u0007z\u001c_uQ\u001dAJ~|\u001b3E\u0006,klYPhnh*%M27\u001can,\u00074\fcP7Pt\nK;vI6l\u0018ȄZ6̌S._\"w\u001d (\u0015GrO21JqGea&GQ7p\u0001]fLϙ6\u001e\u000b\u0012>_U\n\u0019o$r>\u0015\u0017\u0013\u0012[jw\u0012[9\u001cȀt~LgOnx\\x\u001fSe\u001bC+7\u001c\r\r\u0007zq,L\u001dy@F(!'_.Mɗv%f\u0012\u0014\\aHiS\t,THjvRN\u0000J_@\u0017\u001aGJ2+D\u0010zXOIZLL;x.tH\u00109~u\\\u0011Ol:\u0010,V\u0007Y\u0010\u0003\\z2r\u000f\u00176{kGfrn\u00026tis\u001bT&ȝ\u0001\bd\u0013jdu%7\u0013\u0016\u001aϽtV\u000fyd_2Q%R+ 4\u001d|`\u00079\u0007\u0007R\u000fk?;`\u001fYo\u0010@ouz\u00115\u0003g I\u00008ʕ\u0012\\\u0010:K\tՕ\u000bZ'@J68\u001fRf\u001enCNGkvgf4kPC\u001bv~:M\u0003Z&6.}L7\u000f\u0018\u0014[UL?6/n>\u001dҮV\u001fȓ-ڷ(S'ԢxGţ\u0005yg,ܨ\r\\M8ԙV\u000b\u001f3\u0000\u0017R˵xñUT 3A)`\u000bjo\u0013٧:x=fZ\u0005k]P)l\u0010wCaW0FT0L\u0011\u0001x\n9l,лg\u0011%\r*G\u001d\u0017koFU5r3'T;\u0011/\"Z+mWW\n!ǂ@Y/DqT+2\u0015\u0006ҍ~WJ#Jl\u0005.=\fX*\u0004A?:i\u0014+ޭF7{\u0007c^\u000f\tK\u001eU\r3V\u001a\u000f+?^SVC`\u0007*N\fZ6\t.\u000f\u000f\u001b\u001d\u001eP\u001f\u0016\u0018{.lmG\u0007Q\n(9gA\u0015\u00139'z/ksa\u0017ݓP5=\u0007w#L`cGLI&*C֔!X^!V Q\t|߆ƃ}Xg*fˮvү?̮f\u0016V\u0003+|2BM\rܝp{\u000bFMu\"zqU\u000eg'-\u0007MI\"BH=(d\u0017Ϣs34\u0004\u0016\u000bT?%\u001ac`\u0003\u0002\u0001]S(@;\"]hT\u0006\u000fJ\u0011jŴ[\u001d\u0016M\u0006ߏ8I9jDu2Wq\fK{\u0016\u0017Pܞa޳X/x=\u0001@Z>ł\u0006\rURxvm\u001d0wa\bXh\u0003,l8y>`Nt|\u0006j@+ik|\t\u00013\r)\u001f=zZ\u0015?kR \u0015Rn+p9iύs)gs}FE~BnqT;`O\u0017`_\u000b(EO\t*)\u0000\u0018R\n\r82\u0005_<@+5%\u0005\\\u0005p9Q<\u0000'\f\u0014b:\u0002\u001cK\\wA\u0019:QS<-&OW\u001a\u0010XE\u0006=CK\"7\u00105\u0014Dg\u0004B6\u0004\u0007d\u0016\u0000^\u0012\u0014\u0001\u0001\u0001| \u0002\u0000lUo\u001ee5.B\u0002\u0001\u0014\u0006\u0010\nO\r\u0000!\u0000ˀ\u0007\u0014{J№z-r\u0002Y\u001bLpH\u0018WI9gaǩ\u0016&'[\u0002\b\u0007\u0005(C\u0003aAq)\u0001\u0001b\u000e\u0004@d\n- :\u0011\u0010\u0016\u000bs\u0004]\u0004\u001f\u0002U>\u0000S\n@4\u001a\n\u0000\u001aeޚ\u001aA\u0014֩N!c<S\r\u0000eL'vn3\u0002\b`\u0000I̙@\n~U4ڵx:hu\u0006d?s\u0002b\u0004\u0001$\u000b@ɧ_Ca1P\r(\u0005\u0005J)_J1\u001c\u0000%ȭ.'E\u001duHn>sD\u0017oL\u001a̽A\u0000{4ޤ?\u0001omu\u0017\n| \u001aߎi\u001f\u0012x\u0000\tU\u000b\u0003\u001a\u0001k\u0001`\u0001\u0001Z[Rj@)D\u001bg\b{\u0012ů\u0012j ?/kf>\u001b<;wW\u0007#G0\u001fu?kp+K.tV&`\u001b\t7:\u00106s\u001e\u001e\u001f4iB!m\u0006z෪3~EЯ\u001cUB\u00152\u0011#>\u000ewX\u001dD8H.tH\u001a\b\u001334BOt<>K!}X8|{cqG:\u001e6M\r:GۯuCCڥ\u0002R\u001f\u001dc^\u000f|]L\u0013rxI8a'e\u000f\n4?d\u001eiv;v:m,2&2\u0002\u001f~uN/Гka\u001ey\u001dX:yfȸ\u0003M\u0017֋\u001f\u001f\u0011\u0014\u0002;\\\u0013M\u001c9)*~\t'Sݡ]\u0000ꭹ-Xc\u0007^Eg<\u0016v<]OgS%Y͐(M}p;O>)#df%tLo|.nR1Jhc$^V+RTaOj\u001eޗE\u001dNuG\u001a\u001eIU#Ke}\u0016\u000bK\u0007OO^y}Bq-\u000f;1qoBF[K\u001e\u000e{;6ҟd\u0010\u0017Av\u000eN/Ȓ\t{Ro\u000fH$\\<|E٩\u001eZsePᤜQ\u001ab\u001f\\GI%x\u000fo\r';T\u0012'\u0017EGL\u000fb\u000fwSOͦw~߬\\8szw]zv\u000e\u001dwj\u000e5;\u0007n'\u000e5\u0016ߕqmT='7d?k\u0015s3S55b`\roS#}o\u0010+qZا!\u0003w%֗g9AFcacv\u0012b[\u001bz6{-57\u0010\f\u001alĳŽ\u0001e>r}Ư\u0006u\u0017\\x\u001bqOTZq\u0018^\u0006ҙ\u0006ӆF/&#\u000eH縑J\u001cd\u000e\u0013gERήҙݷqo\u000e\u001d4r\u0001\u0018h\u0012&\u000f\\urUa\\j\u001aWJwRz\u0010[aiP>Ktܺ\u0013r\u001b/;*ʇ#et\u0006vϒzNn,ڭQW~}vg1[\u0013ZjӓJa-Q}\tֵ\u0015\u0015kRGcP9\u0014w\n;QsCTB\u00128AW\u001a\u0003\u0005\u001cJ:/c?`oVka\u0007Y/bN\u001aWg!,z\nR5\\rD\u0003~`B\u001dEB %Z*a1\r%fYo\u0002>ZһqԼo.}ƛ\nSݳoH.\u001ccnYǭS@\u0014L!\\ņ\u001c\u00120Azz\u001aq5D\u001e}S#F\u0016\\9,\f+BY\u000bJ\u000f󸯔\n{/7]䦞3+w)ߜf\u0016Ny~'=FJv\u0012I>\u0016b-~y\u0015/V;bG\u001c5.6ܟW\u001aGЄ,S\\rH;\n?\\Rsɥ5OIoK-z39_r\u0003qK\\vp*\u0015;Ӕal3j%cKSYLS+;5M\u001ec-Mg1\u0018\u0014F_,lؼt\u001au\u000fbe\u0016Z@\u0016t\\\u0001pc@{X:8I9YMci[ιm4)^Uz:(\u0013S[Z\u001bcWΆq=\u0000#c\u0019\u0005xy\u000fy\u001c>L)V)p_Q]F!m(=Jco+'g-e.û7'7nNzv\n6\u0017ч)*h\u000elT7uD/5#siIg>, y\u00175K\u001fXG-\u0005\u0013J\b㩻\u001cUwVkV&bU6\f\u0006gw˄)o\u0003('6y\u0003loh[KT$=cJ\u000f\u0019\u001f\u0019f#d\n'\u0016xW\u0017ֽ'Q\u000fkkiD8ߨ58sUC(ƁW\u0005QxɴLɌv~tӨq2\f}\u00128{5! \u001ap\u001fKޮx>+3BG#T\nH>%\u0019\u0016euv~\u0013MGoqY9NtHYo)'Y\u000ec\"+K\u0006#ݩZC-Ml-Cֱ(m\u0017\u0001W{]u=\u0001t:S`G!}^\u0006s׏>NI6f[,콷\u0017Iǈ]#ZCDe\r4'\u0017N wY\u0018S\u000eO/K.ݍc_gљmӧR\u001c\"%\u0016sC\u0004\u0014B\u0018[0CC\u0018;٪\bz\u001fv1l`\u0003.+\u000bw^\u001d,\u0019Yh<7\u0019T[JZjd(\f/U++w:*ݛ-JcA &9G\u001cRE4fG\u0004E,NS37\u0002wk\u001a;3>am:\u0005|\u0011ͤ:TQN\u001fV0ʜW\u0012ܼ*j\u001f\u000b3)ZY2UZe#w*tܯV\u0000o\rXD4*\u001a!f\u0012'\u000f4\u0015\u0012\u0002\b9`\r|eV4}J\u0018![cPf6f\u0010\u000bحV)+`Pbe\u001b܊6/\"R\n-Y8\u0012:wj}\nf\u001cYo\u0015d\b\u0013i\u00145Ͻ\f{(!qep48~۹4`^sh0M\u0001Fe'2b1ϯӓ>g\u0012q\u0005Bix~E6*S`,go(\u001b6RN賓H49y* \u0010JW\u000el]`p9GtKt=3G՘ٲ\u0019nԯЉy!DNhq<R7z\\K6=9ɀ|v+WJEJ\u001d\u0007hIu9+Di\u0003,e*\u0016<|yk|FLn)\r60#޻]G\u001c.ؚ2^4\u001dI'K=C OKiDݮ\u0007)=J1ҠHW\"~D\u0016\u0002~G\u0002\"z\u0013񞤉b=\b\u0013;\u0004O\u0004$\u001cQ,\r-h,=\"\u001eP͸dpӜvH\u0015\u0007\u0011\\\u001f'y9wGYYbk|f_lm8\u0018;Rw`G:\u000b9/D \u0012D\"N#,l\u0011i\"S]2s\n[\u000e\u0007V26\u000fقn!\fh-\u0019L(td\r\f[/^i /h1G%Ms\u0015+h?>I \u0003mZpd\u001fЗIcHӳA\u001ft\u001a\u0010ǭ9j\u001e|Xa+iJ5'n=NDgzT\u001f0ߠi=lܹrm愫_C=b\\4\u0013f+-z/V\u00071Z:R\u0017\u001b4\u000eiJ)vӳ0_[R,-*37\"l3.Fz?2u\u001b>Do0\u0014|N.\b\u0016ճ*c\u0015\u0007Q\u0006l?Fp$\u0007X?їO\u0013+C1@1\u0019Ȱ>:޾ؗ,&\u0003'\u000b3\u00128ҹ/-\u0003skj=ω)\b&X9\u001b曵Z\u001f\u000b\t6mS\u001c\u0013pʾ`b h,8\u0004T\u0004\b&fvj2Kʔ3Mw\u0001e\u0001rrr&\"\u0006'\u0014f<$-\u001c\u0013W!٘yyJcq\u0004Po\u0011N304:4[g_q\f\u001b0\u0010\u001cV%3߁WL@\u0015=\u0001`t\"\u0001u5;)K@*Y\u0016P\u000b?\u0000B\u0000jHjU\u0014s\u0006B#`[]4o3tlxq5:zҽBB=m6],`tg\u0017t\u0004\u0006MQ;\u0001\u0003\t2A\nXux\u0001 f:\u0000\f[\u0002A\b\u0018\t`2\u0007`[\u0005wLa1<yInHEd\u0001i }~͋\t)@\u0003\f}\u0016>74\u0005#`q{\u0002V35<`K\u001f\u0006m]I1r\u0000\u001b\u00141`)\f\u0001Q\u0001;%wa{\u0015`\u001b\ff.?t9,ӟ&\u000f3\u0007A,\\k\u000e-v<K\u000b1܂\u0004p9=\u001a\\\u0001\u001d\u000f8gI/\u0007\u0001\\\u00007i\u0007\"\u000f\u0003\u0015\u0000^w\u0001\u000b\u001dN\u0019\u0007K)\u000eox\u0004|A\u0001\u0000zu\bxQ۪un\u001bp\u001d\\<Yd46\u0015*\fN&\u0017\"/<b\"\u000f\u0004Bj\u00164_\u0007H\u001ay&\u0004\u0010\f\u000f\u0002/߮9v~5X\u0015\u000eGw@dG\u001f r\n\u00020\u001b\u0001hށ(2T\rDnx/Y2hIR\r3%٦bo\u000b9=@\u001cR$\fd?zw&3@-xE#\u0003;Tj7\u001fG\u00071\u0003)H@\u0019>3n\u000eȆ\u0000t\u00019@\u000enrGS\\+@ZQͺPC%z\u0011]a\u0014̠۪l\t)\"A\u0000}Hۥo\u001f\u0002Z\u0002J|_2\u001d_'A\u0004.\u0000ʵt\u0000z]5-.@d{@\u000e@ˤA#J\u0016H\u000b4)ZA}⋯>Up-;z#<\\v\u001d\u001bڬR%D]\u001c4>9)vs\bM͝TNj<FĶ]-\u000b\u001ebV\u001fղ\u0005\r\"\u001d\u0010P\u0006\u0007~gA퇹@w{C7 DH\u000b'6\t7Bgq~\\2\u0007p\u000f\u001dݧO\n[Hwv\u001bgfgn\r=ݛfUZ%\u0001ZdcR9/3$E$e\u001fQB\u001a}ԢP1N7\u001f#R;drk\u00106x>\u0006\u001a8Gk;Ysb\u0015\u000feܞ\u0016?\u00157h}FT):m&j\u001f\u001a6\u0006?\u001f\u001dV\u001f/\u0007׽}_@\u001b:ư57#-ų\u0006y/ݝM{0C\u0006\u001aS42tw}4y|,cQ\u0016h\u0002\u000f{➍}ފs4~O\u001f\u0007\u001a\u001c[S/LvhH\u000eWm\u0017J>|f\\'k\u0013OsAXʢ1͒Jp#\u001e(CB\u001bQ$\u0013\u001f?u:0?A؟\u0016\u001bQ\u001f=?we-UkPNm\u0006\u001d¬c\u0017x%Q_\u001c\u001bzH\u0017\u0011IӅR;t&UG!t=\u001fEva1|\u0015NQ-R#u+\u000f-c-tN\u001aᱱ4B.9y5C\u001dzzm|YUYN#\u001by/n\u001c]Y[:s6\u0015t\u001c%\u0001D\u001brWOQC]v'.v;50\f4Ne;i=mz=n̥<s4\u000b\u0019\u0002n67H ԧ~PG6+\u0007-v\r=j_uUTvZ_;V=Y!&5\u001f]K)\u00029wMK,y$<VI4\u0019uZKy\u000f܌DY덢\f\u001b{4;ZoTGYO~\r#C\\F*Q!_a+7wBpr\u0010ҽߗr,qP\u001d\u001f9qy\u0014\u0007\u000b*ABaڝіws\bi1x}fڲWkkiU+ƯR{R\nzV+7,\u000b\u00023N_\u0005R<ڭˬ?ܼH?C7~F\u0007\u0017\u001dwio]w&|\u001f7bfRc(\u001bcJ%\u0007jL>4{c=-ϵuxV\u0016#P_VhXU?K~\u0017J\n\u0003^\r\u001b3l\u001dypxڗ\u0013H\u0002bo\u0015֮\u00173\u000fIa5dn5Ɵm\u0007_,A\u0018NDG\\RD#3\u0019V/'uY\u0016!Påo:OěQ\u0007\"󛮺^3u:[waWuT#/!\u001c!0{jT1+lD5\n\u0016*:\u0007r`\u001aYԢ\u0011\u0010Xi̺!Vr\u001e&W-|0Ye99qxq]\u0010fή\u0015B:լbr\u0015af\u0017%\u001e\tޘN#%S\u0011\u001dcXm\u000bc\u0000\u000bq/@hם+sVSAϭi/bԚ;q\u0014;\u0016N:t5JFE>yQ7_\u00128\u001bl:pN\\p}-vǼ{\u00001(I\u00182\u001aC(\u001b\u0014\ncf\u0017(ggR+iYH$\r^􌩔驔\u001dޕCNeS*$\u0017q#\f\u000775'n V\u001br.\u001fhӛ뙣;ҮuQSffάY:\u0018\u000bi9\u001d\u000bGrniIJ=PptmΩe\u001cDsf6;(G\be\u0011gY@tLKw\\=\u000e~Ntr\u001b(A{\u0006`7x#a(w\u000b\u0013|3+Fw\u0012]'8PSE(\u0007e\u0006֒\u00154s瞎rۖZH#m$_3 'a\u001b`hz}\u0013Ɛ\u0010\u0007Gh~\u0011M^TN\\4ݛ}d{KwssP&?9\u0005Z\u001fge\u0011Jk\u001c\u000eD#MV@nלt?\b;xI\fM|r\u001dG\u001c$ɾ+!>w|0!\u001b}4!;\u001cL|jZk~Z1H[ǘW-z\u0017l)V--JJ|z2TZ:*]#qr_b,\u001f\u001e]~`j\u000f1\u0007\u0019Q?PB\\e\bE!oi}\u001d]'p\rOV8jV9\u0017_g\u0014bv)\bS+o:N[eڟ\u000eeȩ[WF\\.kĂ\ncmʡ6Iv$>wX`ksz\u001c\nPөNM9f.pӣ#!\u001cf[솸Oxb\u000f&1B6Hq1{0{$d{=Ʒ\rendstream\rendobj\r52 0 obj\r<</Length 65536>>stream\r\n:\u001bw\u0019w\u00173:\"ۂS\u001aX=\u0019^=&\u0012P\u0004\u0017C/gxc;ю[ғ3?O\u000e\u001b\"Yvc\u0018[\u001cKnG*^\u001d\ryGi\u001dVЭ2\u0002`Z\u0010-0@\u001cW#iF<\u0014B#a\u000b,i\u0018c4*\u000bޕ%\u000e;]rhw\u0005-D8e+f),823\u000e0gi\u001fYUԨ\u0018Prw!\u001f&\u0007\u0013Kj+!5=$1!\u0007̑\u000fRhBzrl\u0004MOi0IS2Z#,ChՖ\u00003D[uRI\u001cca>W%-\u001c\u001duM$yOJD\u0010w89<SA\u000f4\u0013'Fw0ywId.\u0007>)|2%-vv}\u000e/|2h3DpVhY9PtJ-\u001d\u0016 Y/õrF6\u0013]{\u000bܪIJz*9\t\r\n6\u0007\u001cMH^\u0011\u001fv FwF\u0002 n-OS\u0006WO\u0015GB\u0016Ҩy\fC\u0007+.\u0018Z\u0006\u0002JL!JL4@;Ak*rT\u0004:nebŇ&\u000bs;iTx\"fV>^V;\u0006p*3\u0015\"N\u00132\"{c2\u0011sll8旦g\fÏ\u000ft} +\u0010(b~:\u0016Rϝ(\u0014|d\u0005\u0006rI7\u0016X٦/jJV\u0014s\u0013ϛ#\u0013^UГe-.é`\u001f\u0011G\u000e=n-J\u001a\u0011\nTNuo}g(\"\"wZH\\we!.ɦh\u0016\u0010YI?0|\u0003?<a X+eu\u001fV#it5d}'+U\u0002n:D\u001bvҪI\u0011kFΌGw!]ٵ\u0005ς*JrN8T\u001aHWou\u0010\u001fx9\u0007\u001a)B\u0010F\u000b\u0005<@K1OsGW\u0013<\u001aW;mF\u0019ܽ\u00073X\n\r̮Yt3?\b)Smog)*a\u001b!Ulu\u0019rb\u000bzN\u0015՛P\\wӺ:liY+(d\f}\u0002ěBRX@|V\u0007$@)wIi@(\u0017\u0010\u0010\u0010\u001b\u0010sH}4y\u001amai$6/P\u0015\u0011+&\u00108ʮ(+vr\u0012ho@ct\u0018f\u0003\u0015\u0002\u0001&\fSf)\u001b@e_\t b\u0001\n\u0014e;'\u001d\u0001to@3BY\u0019\u001f?ŁR<\u0005@nieq8\u0004?n'j\u000bn%C]_m!?y>A\u00198IK\u0000\u000fLWOOL\u0000:W\u0006z&)s@\u0006Мz\u0002{U:E\u0001D\u0004)\u0006}@\u0007.\u0015\u0002ty\u0002*4\u0000-V/o ͼ}\u0013\nu\tЯ%xr\u001dp\nǗu@\u001es\u0006x4Ο\u0018슯!`\b0\u00143KQ\\\u0003F\u000e\u000f\u0016\t`*ǯ341lo\u0002`nfOY0\u000bY\u0014f\u001e\u001d\u00140b\u0000sZĹ]'žiiS(tWW\u0013\u0017}\u0019\u0018e^\u0003,\u001dU\u001c>\"\u0011TٳbvgS^\u0000_l\u0000';6{\u000e\u0013`omp6c\u00184\u0005;\u00007}͇]-eW]\fVtk\u0000.\u001e\u0001(u\"n$Gw\u0003\u0002\u0013^(\u0003\u00107h?\\[Ov\u001a7Mߣog\u001f\u0005\u0017,v\u001e\u0002*\u0000@*6\u0010\n?f\u000e\u0003\u0010=\b\b\"\u0001aI/x\u0002¤\u0001TMz\u0012\u0010z/I[\u0015uu!\u0000m\tK:UDO\u0016k\u0019\u0004F9oi2'+~8R,\u0010\u0002W6::T_\u001e\u0002qW\u0002XwT6\u0017@\n7 8\u0001mw\u0004=J\u001ez87b\u0003\t\t\u000e[g\\Z\u000eQM%\u0003\u0012|8;ە?\u001dԿտ__\u001fexݤ\n\u0003\nu\u0001k\u001dFXbV\u0011@¯\u0014u:\u0002uƌگ)X~ߍ\u0016\u0014ifFO}ʮ\u001e\u0012~-wr]sǕ\b\u001fK~\u001d\u000fg>F7\u0014Y~EB\u000bgG}\u00041\u001b`.՞h{ږ3mjs2M-Upwݬ\u0011\u0019so\"aΛ\u001d)׬\u001bZ\u000fW\u001d\u001a\u000eaƏO=ę\u001f#L]\u0000=d\u001bqo'd[HmsK\f_M-G'.aj\u0015┸єx6\ro\u0011p۹\u0002yvXgS\u000b'J3d[jΖkpgc\u0005n\u0001~]\u0007>|O6xΆ\u001e#}*+qԯ>k\"bnJyMfl~0\u0014\u0010I\u0019Qq\r[k*bp6\u0018$7\u0012]\u000f~w{\\\u0013^\u001f١ay>*Ae\u000f=\u0017\u0011CsAgMMͳ8!g>1Zbn.`\u0015Op\u0013h\\y\u0014)\u0013\ro\"8C-p}'\u0016h[\u0004JW?h`@{%ηẙBI2u58g\u0019s\u001b0\u0012\u000fe\u0019b 9h\u0010kPn`1|\u001d1t\u001a0|\u001fJϩTt~.-W:ӡ8<]]vfZ\u0015\u000bVgo\u001f:T1E\u0007\u0017!n]iأR\u0014\t\u0019c\u0010+\u0003|\u0000a!=y%ڲS#M\u001bj;vҮ⭚mz|Kysxll\u000e\u001b4V>-ud'j:#5K5˶k\"9ʙMT㣛ǇQ\u000e\u00112-|Slؤr;if[D^'Ǖs0m6O\u001c6>z\u000371ndgi}Vu\u0007kr\\C裺\u0017*q.\u0013\u0018K\u0015uMMiv\u0016$(\u001b,\u0005\u0012ܱOKC$\u0017 nb\u0001?||\u001e\u001d\u001dI<zhFՈ7NDQ\\mQb\u001a\u0015\nu5_WvMR/V|TrS\fdЉP_.KtK*\f=\u0005y\r(zEIC'\u001cSCJ1ѿX\u000bΫ?>:N̴ڥ1Ͷ\rN7I/|S-KS|<2/!X\u0010\b:\\E,κZR۞Ć\u0017zՒ\u000fQ+.'\u0007C׹ngRnq3N\u0015Tۥfgӵ?DuJ\bMHѾOB{8nu`\u0012-|=tVA\\>C|ꛋcrRaKyƓ\u0010`GŔwf>r,8vp\u0005\rJDԭ\u0003EMcR<S]u?k!.PMy[\u001a2\u0006\u001aK\u0013R\u0017Q\u001b Ӗ9;\bit\u0015j\u001e9gJ\u001bZMĝS女{\u0007{W{[\\lj{Ǭ\u0006\ns\tŶī/fWs<\n \u000b;2OQ?H\n\u000e'k\u0019p)$XbJwf|-窵3y\u000fNfC\"7u\u0017Q8p\u0016v\bwٲM:6qz]8,y˂d18YyC\u001fBiq\u0005s2V)4u\u0004J:ҒZi\u001a\u001cuO׎Vv#Rvka*+Ř͞Sv;?,AxB}cpco\u001f]lq\u001c{Y[լULvZ(Tlψlc\\,e\u001a\"v즓#mF[\f=\u0005T\u001bW\u0015MUI(0>6OXm-7/t}B8)ura\u000fÕ\u0014}N-vEIUFI'漉\u0017\u001b\u001fخwzqw;j5!v-\u001b@\ntםxזyaun8|\u0013%^Fa|J\u0013_m\u0005\u0012\r#Y$Cˮo`4\u0017ӸUx\u0003\fK1Յn\u000b]=M8.\fg2#!$6ga֟Po/32M0\f*\u001d\u000eݒK@f]f)Q0Plc\",F;&R~[6#{\u001c*jN\nof\t\u0015\u00122fOH5&Ã\u000b\u000677g\u001e\u001e\u001eP\u001e\u001e\u001f֗K^\u0013\u0015-\u001bn\u0018|0^>\u000fUm\tJjeu\nʭ!]O(-$\u0012\u001f\u0002=\u0011.\u0014޶w\u0010FH\"\u0018\u0007\u00162\u001bO\u0004-vns\u001a\\<5opbW\u0016\u0006\u0012\u0012\u0006v.ŁfWt\u0014b=Pt\rjwn\u000b\u0003SdP\u000bIUf'[k[v\u0017%\u0011E\u0015Q\u0007QC\u0018YӮO#vS\u001eNn+nA\u000egw\u000ek\u0019\u000e8:\"<\u001bD\u0012y٥n\u001f{r>\u001bn2Tw;\u0003c!\u001b5%z;XT\u0006ӹU/rR\"[+)v\u0012uq\u0004R\fx{V~r]C\u0011\u001bzsv̎}&LýS4\fޱtS\u00064$6T?WX|6D~Th\u0017?pQF%xܷ7u\u000f4g\u0005dԝnɉkV$epWTLna>\u000e^\u0001K^5fg:\f#8*Nf\u0010nhd92\u0015I(E$w޺!\u000e\"^EDO&\n%\ndID) ^\u001cA|Ѵg+|k`\u001e:O+4Q^\u0003\u0018[?t[49cE\u000ec7\u0005\u0014683n6Uo]ZTx(ɻ.~ߓw%^K\u0018\u0018F\u0018ٲH.ĭdCCɃfͺ\u001cv;\u000eíl7U[8v/M\u0015\u0017h\u0012],f7dD@VZ\u001eٯ\u001fԔ~\u0018F0\nˈȀ\u0014\u001fo\rnU3\u000eӵ\u00176{;8,o\u0006\u001ckhijQx巜`+\u001b,o\u001d\r?=V_\u0013Dw@wSAoa|*\\*~uhA\u0014\u0015׈\u0011=\u0006r\u0005[Z\u0013R\u000f;1jlh\u000e(~a3vJPj-<`ZhsRv\u00119\b$YGM5!\fk(\u0005roĒN\u0001\u001f2fkn(:ҭ\"\u001f- L:a@ح<\u001dQb\u0007ݘYg$&AB\u0014(ሸ#pO^4ݥ+l5dv۰v).\u0010\u0003\u0018\u001a!R\b\f/FeDz\u0011\u001bmtU\u00196}Jaf61E\u001cif\nh\u001cfQDif\u0016T\u0006)\r<pǰ֖)'%^PtP_{Y\u0016cef\u0006ۯ3\u0019'\u0007kL#\u000bC\u0004$c\u000bA#N-\u001bn\u0014!Mw\u0003\u001esn4Q7\u000fOk\u001f㷙;i4V;W 䕠\f^fA;kUWxd\u0016\u00059A[\u0005\u0000W\u0004UMKq\u0002\\kN\u0001\u0014\t\rp~\u0003\u001c\u001f\u0000Ni\u001bQ~m\u0003\u0006\u0005\u000f\u0013a\u001bYSazG\u001cQRB:i,\u001adӫ;V0ɝ\u000f\u000b\u0003\u0013n#';i5J\u0013\u0000e\u0014\\=E\u0005\u0004\u001a\u0003B)Km\u0016\u0010@\u0019F\u0002\u0010\r\b\u001d%\u0018\u0002|n\u000b0V\u0017$K\u001fDIVX\u0012W9n6YC+q9צd\u001fQ8؃>گ\u0007ʊY\u0002aHH1\t\u0001I!UmOq\u0003R\u0011@K\u001e:cX\u0001Yր4l\u00024N\u0001$o\u0001I\u0015P@!k)\u001b\n/,Gb#j#|3mL#q@n|+׾,sPBq,Tڻ\fk\u0007TPOn\u0003`\u0012\u0011\fPi\u000b\u0000*n\u00147qQIq,\u0001j\r\u00005\u000f)y@E@\r.\tP,\u0003\u00170*a޾F'\u001c%UVN\t]0\u001d¡ԅ%LJ3lg\u0004ԙm\u0002:o\u0001ջ)C@_3@\u000f\u0015\u001d\u000fa\u0002\u0005\u0018Z\u0001F9[\u0007FMRl;4`Ҍ\u00050\u0002:Uz\u001d0J\u0002\f$xLϐ\u001a\u000b>4g\u001f< Oisȁ=uz\u0004\u001e\tqvFdI)\u00003vE\\0b3``K\u0007(m[e)*\u000f\u001fph\u000b8\fSD\u001f\u0004,HN۠y\u0016\u000fK\u0002\u0013}kقB>Lr)c296\tV\\7llam[<\u001e\u0000\u0012πcߊZ\u000e\u0001\u0005{6\u000bxqt8K\u0018\u0016\u0010[m))ng d<\u0010 \u0000\u0002R\u0012?\u0018\u0010rE\u0013]]m\u000e8oה΁\u0013啻\u001d\u001b<2,n6]vv~V~\u0005F\u0000B@G_GܯvU *'\u001b55\u0005\u0012R_@,h\u0007S<6w-*xb\u001bC\u0013ʃf\u001aR鈲A6 \u0001\u0006\u0007/WҟJ÷W/\u001f\u00071g\u001ek\u001f\u0005W/*@ߥӪ\u000bPz8\n\u0000}/\u0004\u0003\u0015QP\"PY\bT\u0016<\u0005,x}\u0010TQf}v|7\rmtW\"l\u001c,x\u0007s_gqgݬ\"z2ϺY5y?囅Bn:۵\u001eV6b\u0014Ξu\u0013*F\u001e\u0003կ\u0003t>b!Hbk\\v«x{d\u001c{fç<l3-D+ޮUa\u0019نu\u0013kn\u001fW!_\n\\*\u000718\u001d6j\fԇ\u0014/\u0017Z\u0016\u0016޼\u001d%u;)\u0010>λLNorkn[@g\r*,\u0013dc\u0001N\u0017~]\u0002\t1q\r\u0016bn_z?;\u0012'jؓTs<8z\u000e\u000e(* l\u00061Bmp\u000f?Y~GO#3gCx;exg_?czcnˍBjCB\u000f{ܑ\u001b*MG\u001c|\u000670?t?-*\u00035F;Yf}FwvӠS㋻?/Y`n8o8l+2&e3⣻)`_\u001ajzl;Q$B V?-|ϻ\u000b\u001b{u}-c8*ySX4<6X2lrN\u000e׺/#<\u0014}\u0005u\u0011s\u0006AP\u0014\u0013OiˬEZs`,\u000e}/\\\u001d\u0014jǫf\\a\u000fF~;/ұ#ʞØ\u001eO';!\u0011U[iU\u0018&\u001f\u001f*R9R\u0019+jqkKF0Fg_M}^>cc]\u001be\u000fZڭj@<\u0015rϘU/3e\\ڶEbD\u00122Kkc~*2\f.6䯭m97iv|8 \u001bw\u001do\f_ZMU\u0016\r2/ts\u0015r-Wq\u001cFi[J\u0015y/$\u001b`\u0019IOX\u001dY[x\u0005\u0013s?h\u000fGСuU\u0014K#by@x)1\u000e;\\u\\&:y:b٢\u0012m9bgҶE\u0010cd$ݱ{-TTߌZ\r%qm7|&\u001f\u0003\u0010:x\u001f\u0015qޣ\\R.ry\u0006\u0007r\u0015\u0002U\u0017:_Ȏ\u0014s*~-IP%hzV.Ar;à)a>q9C\u0007\u001d]5%\u001a\u0005a\u0017\u0017k\u0014\u0012Xp~P?Ҽ\\vۍJn\u000e+xœ33[q9\u0014Z\u0003l\\m0\u0000ę\u0014\u0014;\u0016C,uj^Y\u0016\n\u00147/A\u001fYᨶ4\u0007\u000bx\u0004TXkuݩ3[u8+$Yk\u0019ړ\rɽ4ƆCk7sOb\u0012y\u001d3\u0018'\u0007C\u001e'tlgu6\b\u0014\rA/3[zk&_JR\u001dZ~e<&\u000b\u001cq\u001f\u0003zH\u0003\"ݑhfEy2qXf\u000fayPg*M63x\u0019'd{\u0002\u0014ΎK5U#\u0003sD[\bn\u001f\u00040Q\u0016E((zc=Ƴ\u0011y꺞J5S)Z3?ry͎\u000eԝ쉵Oax:X\bYy{[F͢R&#fݙe,]klKq>Mk.ꞦSMd\u001e)\u0017\u001df}\bF%o\u001dCoςh\u001dr[w;G1}ǘ\u0016W\u0019\u00079\u001bW\u0005+\u000e,RfC\u000eLƔ\u0012crWFyQ;\u0007vkK7Lk>?.lM\u0015zj\\\u001f5噔\u0012\u001fϊ#V\tsfӭȟ4R\u0000xՀ\u0015GV7j\r]J\u0016\u0001d5v\u0005\u0001INΘgpb[\u0010Pɚ$\b\f\u0010\u0014C=%niV2A8{j\u001aYwzS0\u0013JqOY\u001e\u001de\u0019#iJ\u000fR\u00151\tM\t\u001e\u0012^k@_Z\u000b\u0015v\u0017\n\u0019\u000eA)<LVd\u0014bOk*7όeT&@Տ\u0018h4\u001e=\u0012fM+/l+Nl\u0015U\u0018eo:H\r~JSIC\u0013?VXԢH=}awBYBB\u0005B)r)\u001e\u001d¸qilvrw*F䄕g\bW.E:SqWSQ\u0006Sp8&]KOP\\4XpӑUXo/i!U\u00168{\u0013UËc͝\u0013l<ikt\u000eÝ,lj\u0007Գʊ0\u0013&Dqf(t[6[ҝZwU˫J&Kr\u001bt\u0012!(Xh(9V%~P[\u001d+_&^Wixq\u0010SBrMFV86\nkٶ5\\\u0006j/2\u001aj\u001abۮ#.\u001c^\u000eF2)\u0014b>Kx<\u0007Z7\u001dZu\u0005fei=x\"ݿ\u001aBz8\u001aO\u0014SpMǊSJ\u0016u\u0003lm>Xha\u0013{I?([x\u001ec\u0017uxP^!ʚ\u0007\u0011F_\u0018:{ۋ=Mg*@\u0005G\u0003]ʻ$\u0016Mz\tRkΝ\u001e=S\u0013<^=JSG\u001b)\u001e{\u0012ƞ-'#9ep\u001bqďT\t-zWr^T\u0019r\u001e!\u000fJ\u0005N\u0005*[\u0002\u0019-{efx\nFm/iF+\u000bHwA\u0013I\u000fNYco{#`^ѡ?b\u001eUE\u0013i_IçGJbbH\u0005^vIHHw\u000f\u0019tҹ*\u0011\u0011#\"/\u0004(|/\u0003S\"\u0005\u0017b<K\\~[8qGAP#w\u00029^r3\u001a%..yִ\u0019q\"^.QS1q)Ʌ,m\u0016T'{JKk\u0007^e\u0004^eJÅ\u001d{\u0001pc\u0015)P-5V\u001dc\u001d#Q|-4zi\u0010*W:E&Ҽ{tҹ\u000bΣ(0 )Qʍ'\u000bL7\u0007(o6{~xu\u0014p1cTS4;\tZN\u0016`J%sK։S\fr\u0014=#\u0014>y\u001by\u0000+t\u0006U9m\u000f\f⧭)y\u0015I?;\u0004z/\u001ch\u0006{o-\u0015&#\"dZ\"a\u0011SbMgdb*Xụo=jF=B\u001e\n53b+y\b~_7<<.욻&4\u0019\u000bwo:\n4iMbh\u00170\u0019a\n;]>8xΜB=VC\u0007\u0016\u0019\b4õ\n\f\u0013F#[\"\u000e5\u0015\u0001P\u001d\rs\rj}\u001f\u001eI\"o5(\u000e\u0014v\u0002a\u000e\u00015O\u0019iOne@&4E5H\u0015\u0013\u00147uZ\u0017Đ/JW}\ru\u00059JzF2pYkC[/Mtr\u0015o|$,6FB:bz_FV߀\u00113\u0002\r@U)'\u0013S[I\u0014-\u0013P&\r\u0001a\u00011\u0002*\u0001\u00153\u001f@E[\u0005Pe\u0003P~uxArݐgŞ)6Ғ:\u0005qǱe`C̐+oh\u0012\u0002XUԜe\u0004*G\u00065L9b?ż\u0000\u0012;])3@C'Ń\u0003t\u0002J5R\u001cրu\u0010@v=\u0005\u0005h\u0017?(Aߴ\u0013p?쌓qj=TݾSAd#ZoV:\u00105@*&H~\u001e`[\u000e0\u000eY\u0004LhW\u0001So\u0001ӿ\u00013\u0010W)\u001a\u0014o\u00040Ò\u0004\u0011S~b\u001e0mHqr\u0001S\u0019t\u0001SM^ST7\u000f'`$1yө2\u0013\u0012Q\u0005\u0015\u0012N\u0007\\fvAm<n\u001eE\u0014v\bXV\u0006l9ol\u0006l\"\u000e\u0001-\u0001{[\u0001ȯ؂Y#Ũ\bا:\u0000\u001c\u000e]\u0000=U=;c\u001d8YvȰvR;\u000e^e\u0018\nr\u0019vԤ0U%$-aFM/\"#\u000f*@0I>\u00078W\u0000\u0000W\u0001Dk\u001b--K?`/\u0000of\u0010\u0001ֹ\u0003\u000fWHL\u0000?\u0000?Dg)\u0016/\r\u0015-\n2LL?\u001cLl;rov\u001b\u001d`6]\"\u0001%;\u00074I$\u001dB:\n1f~u\u0018$Kv\u001b`F+i\u0015tb.\u0006|\u0001t\u0003\u001f[o䃐u@hu@\u0018oO@\u000f !\f́\u0005b5Sl\n@= F\u001d\u0010K\u0003W\f\u0010+nS}\u0004a(5\u0002S\u0015_x\u0010%nrO\u0018]VyJ4\b\n!\u001e\u0001(ݿՔog\u0005ʂ<L\u0005;T\u001f MI\u001cHw\u00052;M\u0014:\rȕ\u000e\u0007j\u0000>\u0005\u0003)\u00123fNuH.;\u001fM'&x;R֘\bv--䏔\u0015.Dok0ތ\u0016Y\u0006B\tv\u0000ԩKA:\u0018@\u0017@\u001d[6q\u0002Õ\rԑ]V{\u001fNHz^\u0014qEr򷮯?\u001cp7ែφn2m\u000b~\u0001g\u0001\f!U'0¢\u0002\u0018v\u0012~\u0011nֳ\u000fIk\u000f8w\u00139@&\u0017\u000b/9h̓wݬ_h߻kH]h]l\u001eԆ\u0019V5U\u001d\u001fd1=\r\u0017\nZ\u0018nWCO}9_|_9>Br_WB\u0019\\{i\u0004{w\u000ese\u0016m~vu%2&xq΢OF\u001d4_7w4SG\u0013rp\bXm\\\u001dWa\bȪ\u0010a/jB\u000bߢ\u000e<2ْq_˪\u000e梁(!h9KFL\u0013\u0016X\u0004VԚ0S(3_QAhu\u001e֠(]g\u001fPσ2b\u000fNZ7\u0014|\u0006}\u0003l)]\u001eol溾Tgh\u001a)>\u0013'\u0011\u0004\u000f[\u000e!\u0019s?s<\u001d蹯ZIfw\u0003t8W\u0005jG\u0019Jg.gtus\u0007暱\u0005U껑K]k]=\u001a\t?^\u001d2hq\u00067\"땄yg}&\u001f?\u000e9}mfy궶o\u001fI\\\u0017X:s\u00135\u001btj:ĭaw90к\u0003L3驿(I(W\u0003:˯Ce^J(Σ?7ayIqXϽy*\u001dK.hRzQk^V\u001aƃu\u0007>#!y\b\u001bU\u001cU\u0006ШbK]\t\u0019W!\u001c\tά\u001cM\u0012~P\nbIrE\rڅ[>\u0015nӷTͪ\u000fZ\u000b\u0017qLNJǎ:p\u001cX5[fZ\u001bee5ɾUl\u000e\u001d*!E˫\u0012)G5.g_\u000eqQZ(e\u0018[M\u0007-^p\u001b΢\tϪ3C\u0007\u000f󟥲{Lᜇ{$\u0017Nl\u000e;{`r_)|0o\u0017Deǆi]\u000fZ!Fi[\u0019Q]*Q>IO\u0005\u0013\u000fs|\u000ez~?s\u0000G!5B\u0012\u0002NrԃP2<G\u001fig8푓tnw\u0018mW\u001a''c'㝷{^\\/FG%uwӰHdW)qt\u001cZEmB\u000bf\u000f\u001d*G9V=\u00170v0d\u0007?h\u0010\ni@\u001e\u0007k?R;Nm{}V;OWwބ'C\u0004'jX\\Ƥ5\u0011FN;CWϩ״G?uz\u001dK\u0019cƊsWs*\u001c\u000b\\MBX\f=,>sي.ޡ=c4︱W\u001efnr䚋I\f9Nx8@h*\u0011W-6\",+\u0018A{`K3\u0007\u000f8c\nƺ0\u001b\"wN}vDԇs.4|o:LsG\u0007N\u0016lWiݎ1I\u0019\b\u001c\r{v\u0016Ɔ605\rԥ\u0013{\u000b?.fAi>M\u001aڢ:Y\u0013\f]\u001d{9:$\u001fT;H7MXME\u0005M\u0014sǽUSפ\\lܜA#&7Loa1R\u001dC\u000ed\n=>ʖʵw1\u0017O32\u000bfNel@oDsۥ^vX'I6>2tPT@zʣ^)\fI,\u0013='\u000fsD\u001e;r(P|ϐ\u001f\u00074\u001c*f\u001cډX\u001c\u0017\u0014wYԫYD\u0007\u001b\u0006^cǾ.\u0005TT4ti\u0018mO\u001e\u0006-~P\u000bw-nte\u0013X\u0019F4Ñj\u0003qy9\u0018bb~Rp|\u0012\f9I{~s_\u00030\u001eދFEmȴ\u0016\u0007؎/J^;Ӕ.y45^ߨ\u001a.a)OX^\t\u000f)c!AWXJ`d%a\u0001u\u0010B\u0012\u0007*DL\u0017\u001d^am+\u0004\u0015\u0007J\u0006hb{\u0005]\u001c\u0015\u0007^\u000bnԝ1\u000ep\u0018;Zl,iqꭳ!T#2O'~L,)\u0000\u001bO׼8Ѳ\u0018JSXխ\u00109E\r~+,\u000bZ⎸\u0013pŶEw^\u000f`DgǴ^\foP^r\u0015'|>oQF?q]V%Q5\u0010\u0017CB\u001eM\fDJ\u0006%ʊaI\u0012^MGZ\u0002+\u0015=~\u0019\u0016hY\u0012掜-^B\u001afuctΘی~-O\u0015LGLq坨=B^f=\u00194ĪXyZ8ZvT͊1\u0006\u0006\u001bZF.&u\u0018\u0016\tI;,r\rrrKUٖ\u0016Yݬ3t#tXZ@7=\fɷl\u001a*5$\u001f\u001a_\u0007`\"\rj|_iw\u0006sj~]>x\u0019oA\u0004 ךɉ4)qї0 !xJHripiu$;\u001bUfWLܦ`P\u0013\u0002RSI\rI4 ȱL\u0012`L,\u000b\fW<,k$1,$dF:6hSCt\u0019w\u0018{\u0019hmLU\u0010%V\u001aþ&&N\u0019\u001fVO<\u000eI\u001b^::WOvR\u0013P>\r?蓳\u001ay8AI\u0012ڬeB߈bP\bF4|sj\u0014rL\rS8G\f\u001b2^(\u0013|mm6 c̻2m[G\u0015hZU<tMSY)\u000e(.F\u0010ӫ0oz8!\u001a\u0005xΓ|TH\tLb\u0005\u001eQ\\\u0004Sz-/\u001d2*饂ՙ\\\u0001\u0001&F\u001f\u0014%Fϡ[¤\u0005:Nۄ\u0013T<fOy\u000f17fIWW%ռ\u0005iN\u0018z\u0010=|\u001fʿ?d^P\"v\u0004\u000fW\u000b(a줨zm^ddٟq}D\t\u0003ߖ;NR{Hgh\u0010ӽc=sHg<#+k\u0013{ɤw1\u0014\n߰v0\n祒A\u0016G\u0003S\u0000BG/|BQ\u001b<\u001dP)v<\"\n\")\u001bVܣbB:=y\u001900\u0018\u000f3W\u001aP\u0016-!d!\u001d6\u00147۵cglx%ϖ\u0011<nm+UWHCe\u0018\u0019Y\u001c=\f' \b\u0000;\u00060pA(*6X\f$x]\u001bprwaHBh|rj\u0010{`\u0006\u001f\u0016ȑ\u0014}\f\u0010yH\u0002\u0000~;qu@xd\u0013\u0010Z~]jdVdu\\xյ-l;ʝmy$C{IB\u0005\b\u000e\u0003\bvL!\fPg\rHe\n\u0014䛙_b>#rޞ\u001aV]\u0000Ht\u0001<\u0017d\u0014\u001f\u0012\\;\b\u0001U)\u0004w\u0002ħMq]|CYp\u001c\u001aiɳBv|qu\u001a\u00115D\u0006$\"&I`:hָ[\u0013\u001c`nfi@\u000e,\u0016\bTOr\u0001y\u0014y\u0000ȳՓ\u0007 /v.W\u0007A\fȭ\u0001\u000eOߝ3]Ggwg`kIC\u00053\u0013|=NC:d*#\u0005X_=\u0019\u0014\"\u0014\f$\u001c\u0005\u0003\u0001yR6\u000fݨ\u0002ޝ\u0000uP>)f\u001c\u0019\u000fP'\u0003\u0000U~M$@M\ns@\u0003Kد\u000e4\u00186\u0000\bJ26aQQS#KX핈v8c֋\u00014<\u0000\u0005@{\nȳ\u0000\u001dW2zh\u0003zu+\u0002\"\u0001\u0003j\u00149` b\u0000\u0006N\r\u0006\u0001t\u0006~W@\u001fH>#o\u001a\u0016JCg_P\u001d,_,?(kgJv4*<xWRE@e\t0\\\u00120vE\u0003L>\u0001SeSC\u001c\u0012`:`S\u0017&7\u0001lئx=\u0001+PJoe\u0002֮\u0000\u001b\t`3\u001bR\u0005,S\u0000\u0000Yc̥_\u001ac\u00056[\"oct\u0002b=rJgֶ\f\u0016x??_=\u0019s\u0001[6|^{ſ`n\u0001\u001b\u0000n8H\u0000wz\u0001O\u0006\u0014k\u0004&Xe\u0001O1a(}\u0017cw3\u0007\u001dӯsxKU\u0019K̢n C7:UĮ31D>5\u000f\u0007oI_rf_#roWJ\"\r߽^T[th\u0016z\u00139\u000bD7SL\" \"\u0010\boÔ\u0005!.\u0000aaO0\u001e)N\\\u001b9\u001ce|m\u000e\tmnE-=_ݨA\u001c]I\u0004\u0019+\u000fo\u0019k=G '\u0003\u0002\u0000>р\u0014WĜ\u0015q\u0000@Z\u001a@:v@Z\u0013\u0018SSE6^бy/\"3ĵcBև\u0018vnSҟB\u0012_,,r\u001c\nW6&YN\u0001N3Z\u0018V\u0002T*m@\u0003B\u0003(7VHd\\簴\u000b&Dg\u0001\u000e\f|]\u001djn9:o%'\u000f5Cϡ]\u001e\f\b!ܮ>@\u001f\u001dޕ+~\u0011\b+\u001e\u001f\u0001\u001dnk4/|=3xј;\u0016\u0016{wv\u0004۹z9lq\f%͇R]\u000fEKtf\u001e:=3E\u000b$s\u001fWۨi\u0003獬\u000bZSD\u001d\u001cFُ_yk]4KuYI\u000bc})>\r4sre\u0018rc?N2waB$B۴C/CF\u001e+b\u001bZֶ>\u0003i7\u0007\u001cKZg:Zba\u0007\u001f\\{$D0\u000f\u0001\u0005C4\tØgN\u0003YNz?h~\u0018k=xTv\u0003d6ЩCh;m2툗'm\u0010W׺xu\u0015.er&+]:\u000ecR\u001e;7|U\u0018\u001b2\u001f\u0007֢:\u001eګ܎ͬV}@-~q]9Vz:*4]{΢ \u000fZ16\n'ռӥ1g\u001bhgXL:t;\u0013-V~zq?-j[ύ:L7kzu\u001cFmRPxQg̶\u001a2g%dXyU\u000be\f;m\\,u\u001c\u001dz\u000f4:wnt\u0018\b?|\u001asaIt\u0013˿y}ߌ\u001c:WX\u001beZ\u001a<\u0019|R<jʼ\u0000I\u0015r\u0003iU\u0001͔u/\u00174\u0017\u001dZt1Jx)blg{i'~\u001bBǛn~\u000f\u001dRUWɏJl$\t\u0018bhX_>Փ;!<ōO?b3UgT\u0011\u000e8L~Ш|s\u0007\u0015c\u0014՗*t2\u000eT0\u0000\u000bG\u000e\u0016ϼ\"Gau%\u000bm> j\u001fcvǠlũY\u0001E:\u001fvY\u0001\u0014\u000e7[cfoyie^xnBǮ*(?e*yxib\u000b8n\u0011+M\u0010\nj\\.\u000eU\u001bn;4_\u0004\u001d\u0006\n3Y=O\n\u001b s\u001f+NA\u001bdL:9ϭ\u0000~e.;kӯs\u0017i3dSYp5AX\u000b\u00123'%- \u000f3\u0017,ݶl0JQtG͡!$s\u0016Nnɘ</_2=\fĢl%a\n4law_{3\u0019:m\u0019%.\u0012l<kJu\u0019\u001dX7u)(4\u001e~ZW-Tb9\u001b\u0017Y)sK\u0010\u0007͘y.(\u0017qhhNaÇJJq\n.9o&xUy\u0019\u0013v\u0011J\u0005,_\u000eD\u0017rg^\u0014\u001fTGZ%jK̺y$\n}L\u000b$l\u0006K+SʴGn9\u001b%8\u0010cq}\n6e\u0005+E>fe\u0014ծ7ꠔv8\u000b\u001d\u0011$;mGFV҆T-RGy(Q\u001e8CR\u001ed\u0005yj=yP냏p׳)Zf\u001e\u000fvX7,eҹ\u0007j6A\u00191J̕w\u000bǫ\u001d׷^\u0012.\u0002%Ru<SSFG6#R\u000by \u00079\u00138\u0017)%e.j \u0010/Hz>ű+\u0012\u0005yV\u0005]\u0010A/Z\u001f\u0006;LL+ec1\f\u0011\u0004\u000f\u0011@k\u001c}4/J!OKz((CYUzӔЕ3a CSIﺔs]\t\r3\u00131wilD\tK_\u0004zސM\u0001e\u001b\u0003\u000f{\u000e=.\nC\u00176\b:}~X(gb(ݏ\u0004S\r)%{[H\u001eJ\u0007L-)M\u001b'ӏ,!I)Dbe\u0007Bu\u0002}o7MwybW\u0013I:ͳGcs9fpdnt\b17en,bը1)\u000e*?wN3Y3=\u001fT?\u0007(<\u0017ML\u001e\f{\u000fir\u0012ƺOq6\rH\u0012\u001e\"\u0014\u000e.0LJ(׹kp9\"SfόbUЎ\u0010\u0007eӒ}m]7>ϋ\f0_\u0006mQ:F_A]Ȓ%W><.?Dwb~<<߾}\bqR1xѬaEV6uc=x&\u000594~A\u001dЎ^\u0000()\u0019DlUL%d\u0010dZdPWP2<E\u0013\u0019\u0003V\u0017ڙ|*Z\u000b\u001aB\u001bԻg\n(\fIi\u0018o!\u001awR؞æs`χjrdn·1\u0016L{-<Ŏ\u00101\u001aPM.aZ\nd]rʻ\u000b28L.$`0b\u0019D\u0001K\u0004:\u0017unk)\u0013TRB\r~os\u001d$\u0019]~5եBmR\\\u001fX\u0017/\f\u001b'G'V{{\u000b3zwڙOjLj\u001f;\u00170r\u0015\u0014c!\u0017gTXԂ\u0012Q-\"\u001d)\u001eGT:y\u0015\u001dEh\fjӼb&X5zݺ\u000b\u0011טf.\u0006s\u0018Ati*\u0019\u0011夜'u8zN\u0007\u0019Z`\u000f?(+9\u001d!w`\u0017q0QZ$A9\u000e_\u0007\u001a^\u001a28ڳA\u00131V}\u0007L H2\u0004\u0010mB\u0001$)K@骈6\u001eF\u0007-Ľ'M\u0010Q*g\u000b'V\\\u001c\\B-\u001dOm7M'jm;ӄ\r/'-\u0000\u0017!\f\n\flRrr\u001dU0g\\\u000fҎ?\u0002b\u0000~<\u000e8,vpQ\")\n\u0010Cƙ7^hXu9\u0010*Ҍ>q|047}ntf\u001dY\u001e9\u0010zo\u0001ۿWL*L\u001f^抦oNaIM(HH7:\u0004\u0015:=\u000fЧݡ\u0018}]a\u000e\u0004G\u0006H8}\t\u0012@ By\u0015_ƿJ\u001f\u0007'VF\u0016\u00151s\bf-՝B\u0012u·b\u001d1ύ\rmOoyp'aG~ig(i!R\b1\u00068MMRt\u0000g4<\u00068Ү\u0003\u001c\u0000h\u00048\u0005+xmRKgJv\u001e}T\r̩2ze~X%\tN%F\bH\u001f\u001a\u000f2?}Cg}D\u0019;</h,\u0010\u0003tS&b#=2ާRB{Z\"8\u0001\u0000_\u0019\u001b\u0006,\u0006NKq3g1ҦݠyŒHrr\u0007LF1NJ]`\u001fr\u001d=\tcް#_ыy \u0006\u000f'\r[o@p\u0013\u0010z\u0011\u0002Dvr95E\u0005D\u0018\u0001bvR$s@T[\u0003\r|Ξ,(@wk\u001cvE}]\u00122\u001c{}HTP*(\b0\u0011Fo\u0018yO2\u0015\u001eȃ\u001f\u0010!ͷ$մ\u0004\u0006$8ဤ\t\u0006JF\u0002df`\u0007t* N\u000f\u001eN{\u0002R\u0014'\u001f|\u000fH!\u00014l֪\\Pe\u0014_B(_O:_~hjWpb]\u0011\\\u0016\u0010z\u001a\u0000Y\u0007vU\u0005f\u0003\u0007\u0003\b\u0005B$\u0001y̦[~5D@\u000b\rP\"\u0001\u0015CYI\u0003P63N\u0001A?\u0002\u0014+\u000f(J`\u000e\u000f@!}\u0019I\u000b\u0014\u001cE T\u0018|X\u0002RYs_\u0016idI:SpqN_Dա+VL\u000e\u0006T5t\u001a\u001d(\u0015@q\u001dЬ\u0000Z\u0003@G\nKF?`\fh\u0000:H\u000f\u000b:E:_׎ @˒\u0001hK?\u000e~)m2ey*w?~o]!\fz)dQ\bYC48\r\u0005\u0001VS\u0005t\fx@(w++3'zO\u001e0u\fy;\u0006=\u00061Ix\u0000fP)\u0016`VQ\r0ci\u0005\t\u000f<\u0003&\u0003f$\u000bӎ-qBSF;DYO\u00003zp!-Ĕ*_[_\u00117~er\u0011e\r7\r857\u0002\\q`q\u000eq\u0017\u0001\\\u0001W\u0007.\u0002\u00048\u0001N\u001cS\u0010\u0007\"T>螜{IuA\"\"ɴ|3xhh71,\u0007g=[Y'x\fxW\u001b\u0000?Cx\u001b o\u0004o\u00018)f5 T33 7\u0010wTG\r \u001a\b0}cDD\r7)S\u000b\\O\u001cC{}\u0000[ҷoWE\n_-9n)_߁$l\u0011 U%\u0006HӉ\u0001XH\u0003\u001f\u001c4`I 5>!\u0015H:JQ4\u0003ߡAtև>g\n\u001cܹ]Z\u0018E8<o\u001d#*W\u0017y\u0003)nK\u001f\r\u0005(k\u0002q\r \\Կ10pGdE\u001d0*t\u0010\u000e$o]?.?i{)7\u0019wp?]57/\u0001h(\u0004:^K}=)\f3\r\u001f\u0007:K~V\u0000>\u001f_\u00102O\u001fpjort:;7\u000f}rڏnwvf\u0018\u00194AWuf2\u001dv\u000bc9=\u001bi0>M,Fbb&\t\u0011(1ȁ0aV\r~xnlEK\u001d!\u001bz[\u000fzRGg\u0003+w7\u001fr;ܚ\u001fi2_,}\u00183Rէ^XI\\vI6We50\u0016\u0016:\u0003}Օ{#7n<$Zʡm=}\u0006kr?5?+[~_ۻZ}6\u0012{iS3YL\"\u0019W\u0007\u001d)296դ833}\u0017bnj\u001axU!fnU\u0004r\u0016\u001f\u001ak,xyfؚWEÄL\u00011'Ț؜0*]jOr/oާu>mszF[xZcI\\\u0017NX:^X9m~Цz}\u001f\u001b\u001d}m\u0018/SgTj\u0012^*:y\"Wӡ/u\u001cIkF!|c\u0006Z!63uDćR\u001eKʫ\u0019K-\u0017t\u0016_{hFѭί&%\u0018UK\u0012үFyU~ˑ\u000fJ\u0006*\u000e\u0012I1TWڋ\u00155(\u0014:^01|.J$38 \u0016uֶ*mܚi\u0003^\u0015G\u0015r'\u0017)z2JSOYQ]}\u0012tbl~B'Q\u000b&3 YQޣz\u001e/y\u0004\u0003FslyA\" \u001fϴ䯞<W׋oy\u0019բC\nޠP0>j\u0006A\u0016gz\u0019?3vHvW!\u00179{0z \u0014\u000bp@\u001f%\u0007[n;S5˿ֶw\u0018\"yO{NcWßmYA212RfWia_>\u001av;+H1|D/C+m.\u0016\u0007#Y|\u0006m-h׳\u0015}e߫˱'}3<{l]\rEON\u001efL~9ϕ8H۟][GSƆ\\JnYXN-1F-Zk9u\u0002+GZ77r\b\u0010\u000b²g+^{u\u000b\u0010\u0006#R㿔#\u001f\u001drN\u0010\u0016Pǡ+\u0015{T4llYI=\u0019[Y1mdOa\u001ebDΈ׷㛥W|\u000bi\u000bx\u001d:\u001dVa];.Pnz,0e6a\u001c\u0017ux\n2R2]\u0017\u001cP%\u001c \u000fJW\n\u0007mag71&\u001a&y2ƪ*\u0006U+\u000b\u0006D\tdY-HmwҩbbJb[~^LK,?o椆,YՈ9R^c[E\u001buZCI\u00133\u00075ǈ\u0012\u00172\u0017\tJ\u0006u\u0001\"q0\u0018\u001b&cyCը)Cf\u0015?r\u000edG\u0016=K~$\u0011ŤP1\u0019Dm1p\u0018x\u0018\u0017,q#UkϲlLz\u0011\u001dI\u0010_\u0012^jKbz\u001e$\u0010A.e:\u0012d \u0015it\u001a7=\t8e\u0018\u001daam\u0012!{Z5>\u0004|kdyܮ_qF\u0005vMK\u001ffگj5Փb\u001e\u001cxP}\"\u000f>Q\u001e<\fvS⟗,qH65Bo2-,:&/\u0014@\u0011hcK[*cN\f[Dp/챬\u0012+\u001es\u0016MVǑ\u0014\f\u000fR-|zA*D26fʊuZS&6[v4\u001d\u0011\u0012lwbO\u0018\u001dE\"3\bINjG/4\u001f\u0000\u000b\u0017\u00184W]\u0004Nl\u000b:{2\fxCjL;m[\u0018_=crDS̡UA)\u0017,(h(\u0017g(\u0017U|m令K#RE\u0011G%az\u0011Ip\u0010xo&/Ԋۇ\u0013ԙ=\u000f*{\\k\u0019iK\u0005?\u0003~v\u0006\"Y\u00125UZkf\u0014\f3g\u0013x$fS7J\t/\u001f\"\u001f\u00161[͋!-l<B\u0007nέ_ri!j\u001a\u0014\u00072{䔹\b`~js`OU\u001b\u0010;q\u001ah[\u001d\\m;\u001d\u001cMSɩeb$\t\rbv&\u0004Y\u001d]A\b\u001aΌ\u001115^Olk^tV\n_w{/6v[a\u0012Tܐg8\u001f5\u0002zcu|Zϙ\u000eRM觕0F@ْB<X#wO\u0003<s\"\u0010F\u0005ܦWU\u0015y\u001cbjU&+\u0007\u0015\u0013Z\u001e\u000e8,\u0003\u0017*zXo,un,JL]?r?J|d>1kŘxN;5<\u0006\u001aI\u0005؋X\u0011}٢ȶ\u0017\bV\u0004Ǿ\u0017;\u0004\u0017^\u0014~\rY+w֩SOVef=\f-$\u0011s\u0006D\r \u0003'iB6'\u000b]5O3Nz*~\u00165\u000f\u0017Y\fdS5L{Ml\bgl%\u0012gJ%5\u0000^-r:r\u0002|L6\u0019\u0017;{D-qeJg\u0014\u001a\"\\m/\u0016\u0013Y/]r&#:\u0004u!K1<cc\u000eUcH\u000eL\t\rKG\u0003K\u0015z[-訡D\fw.\u0019~#G\u001e\b<Fr`Ul T|'\u0018WIq\\ D܍\u00137\u0002Ze&Tg\tX٣\u0014:$'D8]\u000e\u0013v\u0005\u001d\u001bN\u0004%y\nG\":ڟ2h\u0017GI1Gr\u0005Aʀ\u0001Sȁ\u0001߾݃EʁⰘ)$b'K:\\)OaI٪P\u0011|\u0015\"}iCchFeIȜlնd1O\nv[,y^qs~4s[_D,#\u000b\u0017f#\u000eJ\u0000=X\u000e\t#\u0005#$\u001a-7x\u0004({vzc\u001c\n1=6X\t[Ot_eܨXk\u00183jCS\\eEnIvAt\u001erlm\u0017x\u001c?\u0017{\b*Vwd7Nw\b\u0007\u0014\u0010\u0005А\u0001Ѽ\u0000z!\u001f) 3 (|(\u0000\u001bf\u000eP\u0012GE\fO,3\u0015\u0016ȖzS\u0017?\u00067.S?zY%Vd\u0005\nK-\u001e$l\u000f*\u001d N= \u0005\u0001@@hD\u0000ISd\n\u0004\u000fH6:\u0002kĄ2\t\u0005lz+$Qif긙\u001c ۵dq\u001as¾\"B-;Oi_H!\u0012R?[E\u0003E\u001cwh\u0003dez\u0004dg\u0001\u0018yD.R\b :\u0003a/\u0002 f!\f<!\u0004u\t\u0013}\u0007z\u0006vk$'\u0001 \r\u0006lxYm$RĢ%{'Q*)σ\u001f0bJ_\u0014f\u0003!={\u0014w#%zDn\u0000y[x'@EX\u001fPd\u0000V\u0017\u0001pA\u0002j\u00015M!\f\u0010\u001e-@#\bgO@i\u0011µ\td\u0001z\u0005V\u0004T!;NI\u0019.\u0018F]\u0002h-xy#<v!bxϨwN\b\u001ec4;H%\u00029^*7@\u0013\u001a\u0005t\u000e\u0000]\u00179@[-\tЫM\u0006k\u0002AA\u001d@;\u001d\u0004\u001f\u0001D\u0003ZϩVy\u0017\u001b\u000e̹\u0004i\u0006g\u0006dtHBwT\u0002oPgu&N׆7@/AX:Լsە\u000f\u0016\u0005б\u0015<\u0000\u000e\u0000`q=\u001f\to=y\u0000s+\u0017!8M\t\u001dB{\u0001\fC\u0004̊JC\f\u0000\u001ctT\u00060j\r0\u001bWY5F\u001e9\u0019/&? `\u0019ҪnJBv(6T\u00002\u0017Q$\u0000u(C\u001aܜ\u00067q:,`ϳ\"W\u001dp\u0000\u0001\\@\u0018\u0005ˑw\u00008^5\u0000/\r\u0004W\u001c\u0016`Av\u0002.-dA8F$\u00187Dy*UY\"4mH_B6\r'c#\u0000OH\u0015\u0006mFo\u0011Z\bO^A\u0004\u00108f\u0013\u0014\u00133\t\u0007D?\u001fEβiD\u0013T\nD\"A\u001ejH}דR\u001f.XN\u001b_\u000eP[׻\u0010*)\u0010\u0016\rFf\u0017\u0010ME1\u0010\u0015(F\"!\u0010N-\u0010\b\u0005\rV\u0002pi\u0002ݽJͲ%G~\b\u0019\"qI,󓠑-al'%B*!P@n\u0001\u000e%\u001cB\u0007n(\u0007b>O\u0007\u001cHR\u0014H\u0002n\u0003J\u0011\u0000MK@B\u000e\u0010\n;\u001dDe{\u001douzdU\u00171{\u0017A3x\t)w\u0017(\"߶Q~JO\tf'\u0007#hAY@^ùl\u0014.\\rc \u000b9\u001bIgm\u000e8\u001f\u001b\f-uNn|\u0015\bm\n\u0012J~i߫wY2=\f7\u0012Bi~\u0019m'\u000f$\u0006\u00022\u0000I\u0001\t_[ļ\u0012zU\u0004mFhm\">\u001c\u0013\t}n0/\u001ebr0\\c߱\u001dѿ[7ew6biJhe4Enpz\u001aaNX`FOkĴIDesP3\u0007\u001en\u0015ʡvPB߯ȇհh)np,\u0012lpܺi?`}li\n\u0011|?ygf甛y[x+W4QI=>\u0011Vvc>\u001d?,\u001aVf:\u001ejNQ\u0019Ʋj\u00185BraozL:h!(\u0013\u0007\u001enJRal*34&'^\u001d9=ڴNYSyif2\nq\u001cG\\\u001a^\u0019QnƲ~\u00182nBܦ\u000fPd)vi\f7O\u00023K\u0003ILXrU]v9\u000e^GVh\rk2\u001b\u0005\u0018\u001d\u0018\bh0\u0001\u0006=\u0016^+k\u0007kґh:XkOa/\u0018\t:\u0016pbݙU]LDTz7MnyZe]=yՁBjT_[7>醯ȇQ&\u001dOE/0Z^Qu\\- \u0000\tJWZ]ֶJoѶ:mnO5Iz\u0016\u0007^nH)Ye#Qh-j|~).:JZ\u001f*?+>Ch*e\u0012Xf`j;+\u0002W|<<ӝt-\f\u001bZJ\u0019AM F<8r>}{\u0010T_\u001b\u0016\u000bVE\u0007U0R0\n5))ZLh:z;E5+,;]\u000b\"\u0016b\\C!\u0006\u0010C;\f`ն<6Q\u0005럹*\u001a+Ķ//J&2}Xou\f!V)GE5%B\n\u0007x,\u0010\u0003 |\u0002ɜGriPM(a7:`Ӭ.ق\u001c㲨_g[&\u0010<t\u001deaRrH\u000f%lD\u000bQ+HO^ky>O\u0004B6j\u0005\bf-gӕ`5*f\u0014=p4[\u0012̬Ol3eY:ek)H/uHӁ'\\KȦ9[M8MzxRV[\u000e!S~r\u001azI)]O*H\u0007|R\u001dW\u001ad-O\"3O%,\fq\u0016e\bLzZ_NV5)9$={%ni0DR>kǵƍ'rVw~G6݅lJlG5\u0018\u0014\u001c?\u0019/֍Zm\u001bR*ʲNf\u0015I=NT3u&=\u0014$UJF\u000fߔPMJq!\u0011#yYJƵZ#\u001bO0݂oUh-Z`}\u0014Sb\\z]Z{\u0019R!Hh+33ę\b\u0001kR=wPbptbM\u001f\f\\@\u0010\bWy&˫]\u0006v\u0017v:8F#8iǂ\u001d@cfG!cX`$gR!^>\tՄ83LE,ݲH<^ҖZ=2~/,\"4+ӕ3\fC9Z\u001bIDYv]ŞY\u0016j\u0011.?R\u0007.#s\f.@\\ƀl\tJI\u0018؉3=\u0017˩Y$\u0002\u0016]g(\u0003N,Nh\u0016WT[ňZ+4#Q\u001c-޽4p ˝Or;I;_x\u0001YK\u0016;˒\\BJ7$\u001dֿ-;\u000bG蹞XY5/6\u0005F\u0011ń\n|Fv9\u0012lnQޙ\"K\u001e㆘\u0012Gu\u0003v\f\u0010c2\u0018\u0014OCv\u0018Y2ʳO1\u0019s*7\nFfK#<d\\Ϙm_%;z\u0015%\u0010\"49!EDLtq^\\Jq]\u001bs{.ɵ.\u001b\u0006HWf\u001eO*Xb5\n$>=զtqt>QB@xʤۦRdNQ\bNQQ\u0016}k\u0012IJ-!'4uze.1H7;'N8]l.i=\u001d.9g}LdsX\u000f, ⓞ\"\u0003.n\u0011j!\u0013T,Qeuu\u001esHSp-`\u0004\u0016\u0014іR*\u0011qO\u000b\"D˥6(ϓLs\u000ec<fׁĸsHw|[\u0003?NbͲ1c1\u000b\u0007 '\u0005(7T\u0015_\u001c(jq5\u001cF,ϐE\u0011=OK\u0016!\u0010\u0013\u0010\u001e7\u0018\u001d\u0012\u00145q\u001fOӾ\u000bpI\u0010b-\n5\u0013··4{M\u0007PJq\u001dpy\u0011\u0012\r.)!_!UM#r=zF\u0016I\u0016ov}\"\u0001#&$Q\u0002?%\u0011.,=\r\\u\f6h/,>#\"mVP\u0019\u001fK\u000eP_:E\n\u0003s\\\u0012t<{˦E%ޣ;FzBz\t+٠0bВnЄ\u0012רH\u0017\u0007$W9D{\ba!\u001b{XK\r;w\u000e\u0018v\n<e),WP\"\u000ftZ \u0013b6\u0011Da\u0005:xͶ\u0017D\u0006l^4\u0019bVؘ\u0010(݄(b\u001exl46Z٧<a׽IAU/\u0002dx\r\b\r\byߪuރ\u001dSL+,!r\u001e?KW԰\u0007/483ȃb)\u0011wL@ٝ\u0001Vl\u0000K1y\b\u0010`)<&V\\v/\u0016C\u0018HّHO\u000e͚֜q\u0006\t=kMjk\u0018\u0014}I$w{iZx>\u0018؅;Xlx,'ȣ.\u0010=o\u0010C`\u0016XQ\u0000f9\u0011%\u0005\u0002t .\u0000LxM\"f\b`\u00070LQ \u0011T4ɏ\t\u0017j|\"?*OK[bAInH\u000bB{\\ĒA\u001eǙd\u00011\u00038a \u001c\u0000Jw\b=\u001c\u001f\u0005W\u0000\u0000϶&\u00001W\bǷBF\u0005\\\u00028|\u0000\u001cG,\u0019?䒱%tѦ\u001dGag}A||BM67\u0011%\u0003?v!MX2\u001e3ٰ!9\u0001kO\u000b\b\u00063\u0004\u0001/\u001d($\t#a\u000e\u001bW\flo\u0000\u001eO\u0001Q\u000f\\g\u0013ղV\u0017cشM}\u0016?~fon\u0014KYl©I\u0003&vÆ\u001f1.W%ѡ!G÷:@f\u0013@\u0005 \u000bF\u0000aC\u0000 \rnٍ\u0013}@\u0001<\u0004(bۀ<\u0014 bR#\u00172cea\u0003\u000b\r=\u001fV\u0014K\"3b\u000f\u0016{hOpyv\u0014\u0017F@\r?\u0005M\u000b\u001b@<\u001b;@\u000bk\u0000HI!y\b\u0014 c*\u0010ra\r8\u0002$&\u0000\r8W\b*< FJ0\u000b-dOP82ţh}MF,|AH\u001c\r\u0014q\u0012\t(G_6 )z\nL~\u0005J_\u00129Z\u001f\u00019BH\u0000H\u00030e <%@\t\u001cU\u0013P\u0018Pr\u000b(\u0002%\u0001y~jܬ\u0005@\u000eT#~xs\"-DSݎl\u001bBmv+. \fi,\u0001y׀\u001e\tP-\u0007Ԥv\u0006/=4eYIB8+\u001et\u0017\u00014\u001f?\u0000\u001a;\u0010m؂5\u00021}\u0001:!\u0003)\nb#~Pz\u000beozW.\u0017\u001cC\u001bOZ{\"\"\u001e7\u0017j.%*S\u0007G>A>\u000b\rе[1}B$\u0003\u0018#\u0000|L\u0000\u0013\u0003RC8\f\u0001M- lUYȑ\"`8`\u0003\u0006=}}I\u0000zwbD*tPfJ\u0017i+v6\u00174\u00015D_BQg\u0001}8>!\u0011\u0004|jS1}ވ\u0005,z\u0011\u0001[H\u0000hy5T\u001f\u0006\u0015\u0000\u0000;H\u0010uv9`*\u0002X%\u0005,[Jce\u000be6#>o6=\u0013{xRCRQ\n֓?\u0011\u001co]^RLZ\u001cp]'\rū\bx\u0004|i\u0007,bA\u001b7\u001f\u000e\u0003.\u0005|u\u0003\u0002^ӀG\u0012#1<\u001b\u0014\u0016u&N5@`\u00016ǑY>~)\u0014o6o!'\u0000\u001e\u0000\nPpPS\rٽU\u0016\b\u000f\u0003C\u0000a@\u001a\u0010k\u001b\b\u000e!3s~XF^'=E\u001c2O#uQx||sNE/-DGo_^\r6j\u001ar~]\u000f eP\u001aB)\u0006$q_\u0002\u0012]\u0019\u0002\t\u001e\u00107+\u0002nv\u0004\nr$<KH4y8>\u00128Y{G,KmR\t!zC(~\n\ra]P1~7bi/\u0002rݶ\u0000+w\tA\u0001\u0002\u0011\u0003rb\u0006{\u0005bC\u001c\rR?O;\u0015!9d\u0013\u0012\tcZ\u001f\u001f&ۤnwOY\u0005.XrXd/y\u0003Ieσ<\u001f5Ab_Abd\u001fxv|\tTB\u001bާ7߯z\u0019Fs#\u0017A'\rȩI2{KZr&]\bNPvW]N}epfkiFUu\u000f|5}NekV\u0003bčDӋ`}jy;~RV\u001b?\u0015C?x\n/>Ʒ[Ji?vpvH4#|\\g'{6Q9J/s߬\u001eSu`\u0010\f\u0013@;$WN\u0016QGꌈy4jt7y\u000f]\u0019\n\u0017lI:C;V\bݡ!o`etM$c&J;=jƤlkܱe\u0019]^-m\u000fL[nYQ;\u000bݭW:V6C\u000f]mp\u001et^?&Fz\u001b\u00056\u0014:E3k\u001e*\u001db\u001f\u001f<CU}bhH\u0003i֢=,ls}(lO\b\u000f|(l\u0013vhc\u0003-\u0016K$}ُB)`.:\u0007άB;\u001a\u0006ǌ>&&mXXTY=6\u000fՔ\u001eL\\#\nú?oa՚d&\u001a\u0015\u0015\u000bP\u000e\r]\u001a\u001f5:}_YZ@з\u00106;[xz5\u000f3֔\u00038\u001b>ۈ?Αob_\u0005Wf|*UmWmcX\u000bY8rMegS\u001fx\u001daF-%eF\u000byKo\r\u000f2pL>\u001dGUlAt!t\bGoM2}K\u0000J8,z\u0006\u0014t,\nM\\!#%v|L\u00189n4'{`qDb2O\\½>P\u001bJ27R嚀ʡ\u001cZ\u0014n5p\u0018iB/cd ,\u0010j\u0015#Z!>'8gTV.MeJ.-\u0015*\n\u001f:\u001al\u0003Yҙ /g\b\\L/G ]LiUDRlԃp:\u0010Cf\u0016|а}B\t2(\fd\u0016N\u0012a\u0019\b\b\u0004aʢ)KV!CR4ҵQMӷ[?厁jf\u0019+Ž\u0012ZP6(]\u0012\u0011I\t!\u0011y\u001aĵ}VGO>\u0010\u0013z\\x\u0010LSL1?[G\u001a2ֲXkqr)\u0005˧\u0012ק#T\t$<\"h0mojiJ\b=\u001b?/x+Y7eui\u001dǂCn\u001e3{}L=\u0012$JR!m\u001aR!ӽH(\u0015\u0018S|\u0010\u0013\u0019\u0003W\u0000âxOz资m<?\tjFp\u0006W9s\u000f\bi$fv\u0012xL\u0011\u0015Zzʼ\fT\u0012;Yqfx%~5?pxƵNi\u0017e<\u00105&4ЬBnpB1h\bگ\u0005nXA\\yLzUYdGxa2=\u0006K7\u0006\u001cT\u001d'o\rrm%tl\u0003߉T(\u0012A\u001a]J\u0010)W\u0001uLp'}Zh\u0016'x[\u0002%\u0012H<{m8\tgE\fw>%(Ɲω\u0013wԒ|L&\u001aU,\u0014b7#-*-:\u0015^d|YIŲ\u0016s\u0016G,[d2,c\u0003AE:\u0012r\u0007\u001f\u0003k/|\u0007ٛi.!\"럒i\b\u001akhƦ\u0013\u0005\u0013^7&\u00044\u0015ƴ)cu\t^|\\g\\ndN\u001186FZL&1\r1~:c\u0005t]رizc\fAwX?NYԗћntl{`ʘS\u0000QJ%\u0001XigyUB=ل1iSlvĩ\\KSEi@͖\u001bpb;J\u0000BubqcF\u001cDʪB뾛ED-g\b\u0019qXc``K!\u0011:0%b4\u0004\u001b1E$M^Z@ni=Rsizʯ\u0017Nx\u0004!WmAօΈdGl\u0016Fl\u001a\u0004pLl\u0012'x4\u0013;,.E\u0007\u000f7nHW콿̶1`rK \nѧ\u000fy\u001e8i|\u001cRLȧk~>Lz>XfjO|'6;\u0007!6w.Bƍ4\u0011^\u001bɍ\u00102lbl\t\u000fo^2\u0003ױlX1+Ead\u0000K~P8\\q\u001d1i[c\u0010WХ\u0016e:Z\\.Y_׺$W\u0016U\u0010:њi\u0016\u000e\u000b\"A=|/J\u0017P\\\u000f<.:q8Vb]\u0006\u0011Jhg\u0017\u0002\u0012Gu\\GuNIeNxtKS'~66\"I9w\u001cvߏ\u001fХ\u0018ڥL%\u001d`pm\u0014:D\u001bD`T\u0013<TKF\u0007x,!hSԟ! z`qT\u001cCNu\u001f3Kd]\u001eH6\u0011U \u001c{@qt,ծFh9@D$О*\u001b~Nl@Q\u0016cOu.S\u0003ja\u0000GJ&d8(@r~L\u0006bhc\u0015\u0006uY\u0012dzMX\u0010T8a\u001d\u000fM\u0002\u001f\u0019x\u0014{\u0002xpuc6\u001b)@3p%f\u0002@K\u0019\u0003PVdKiFJv'\u0015{%O\u000f.A\u0012jh\u0004|P4vF\u0010u\u0013F1_\u0019ƻ*b\u0007b:Gq\u0011]\u0013)kČ\u0013_/N\u001c]QtmAxB\u001d\bP3Z\u0007(\u0003j&&\u0006G8\u001c#ҒqԮ5\u000b\u0015ozFJ}r}s$qzD{P\u0010B\\Q?p;9@\u0016AS[\u0017QU\u00178\u0000\u0014\u000e\u0006\u0018H hG\b\u000b`l\u0010d\u0001uU\u001c\u00010܊\u0001A\u001awŃtcƍ\b*;\u0007>Y3~jބYթ\u001bݡOx%AwD\u001b;fwдu\u0011:\u0000Z]Uw\u001a\u0007'\u0003Bm xgc\b\u00000[AXӝ\u0012`C\u001e`H\u0002=\u000e`\u0015=\u0012z\u0003\u0017k=\u001a\u0019q*bqƠ\u0013\\YPZI\t\u0011*et^\u00009z%1\u0015M\u000e\u0002Z7wa(C\u00038\u0011\u001dAPl\b\u0005\u000eQ&/\u0007\"j\u001e\u0012ɒ\u00028SMe\u0013\u0019#\u0001;l\u001aK]8\u0016q,q_ڞK\u0017vkƱ)=V(͓\"V\u001e\u001b:xuĬA\u001e}\u0012>\u0011\u0005\u001d.S\f.\u0001v9\u0000#F\u0000pL\u0001!l\u0000g)\u0015$r\u0000\u0006\u001db&np8SK\u0002\u0015\u0013%|՚)\f3>\u0014\u0013k\u001dN\u000fc\u001d`I#\u0005+BJL\u000fQ@zc@3\u0007\u0010`\u0001\u0002._!\u0001 8\u000bN\u0002bV!L\f@i\u000f\u0010\u0006I\u0002B,,@dPY\u0015\u0019~O[m\\\u0006kdTI~6z2\u001dr\u001bAG쨦\\\u0018@Re\r U0\u0001SX\u0000Rn\u000f1P\" ,_5'Q\u000b}҄<F\u0001d![\u0001d22\u0005\u0010y\u0017(4\n\bD,|~riG\u0017]\u001b\u0017U\u001b3\u001f\u001b0\u0004\u0012~{\u00046D+~*\u0012\u0006P\bd\u0007T\u0004fM@xrlV\u0011P\u0006م`L\u0001\u0011.y@e\u0017u@ņ\u000b@C\u0012P\u0005c\"p>v|\n߸RY\u0011\u001d\u0010t9P\u001b⛨Wm\u0006h\u0005#DX>F1\b7\u0005ЧD\u001dL\u00079\u0006}\u0000zҖ\u0000gڀV\u001b@g\u0000\u0005h)ۋ\u0014UdF\u0004,2,*,āo\u0014i\r|wخ#h'ñ\u0011'\u00057v#w9ޚ\u0002XmY\u0005\u0001v\u0000[|\u001e\u0000\u001aX\n\f\u0000s5\u001d\u001e0q3x=>k\bk+Z\u001eT\u0019OJt<ؼkm\u001cUBqV>!'Cv|\u0003.6\u0000_Z\u000f\u0000_-\u001bG/\u0001N\u0004p/\b\u0004d\u0003݈\u0001\b\u0007sA!˽덻;>O\u000f'w>Izrh\u0006\u000e%ҷ\u0002u\u001cJ8\u0015g\u001cg@X\u0014v@\u0018;w x\u0006\b\u0001\u0002\u001b\u0002\u0001@ěb 2j) ҍ\r#dC\b\u000bg5ks\"ۤ\u0007=K\u001d\rpd]\rEiX4j'޵m(2\u001c\u0007$\u0002\u000bo\u0001\u001dM؊uK1\u0010(, h̹\\!Ѭ|`I9tK!P\u001d\r\u000bm\r9*+]\rˆbi\u0010s\u001f2h\u0002yZ@\u001e\u0016q\u00022σ؂\u001aXwubD6\u0007f)N\f_w\u0010k>)ܶ6\r!\u0002B\t\u001a\tF[J?\u001c\u000b\u0003pd ٳ\t\u0019\u001e{ 1 Q\u000f\u0007\u0014\u0019Ann\u0019_c8c[(8\u0015Xeq$}d\u0000h2*p\u0016ӃXYo`\\E\u0013wrJ\r$\u0011rUm^~\u0017o\u0015G\u001c\u000bAf!^k\u0015\u0005nM=&zN\\\u001fxL~<ic\u0013^02\u0001G>EC/NM;LMa0<w\u001f\u001dVqzY9W^}6I\u000e~zhp\u0004u_XH<G\u0017Qc_WG\u0003}\u0015_\u0011\u000fGzD\u00033QL>\u0003\u000b<$:\u001b)61ү#\u001b2B-sq0ݐ\u001b5B<h{ˉn2ڍ\u0011\u000ft&\u0017%n\u0015\u0017g\u0014e|NY\u0019Od\n}~0X~q*'\u0007أr`H|]\u001asy4\u0007Θ\ny!9H',60XE4l\u001dO9-Y5)\u0018]\u001fƔRK`oN\u001dJ-~2˸@\u001b\u000ei8\u001bf9n+\bM9\u0010=w!՛Z=\u001d\u0007\u000ezZ/E\u0007wdY\u0006٦yF&\u0003\u0005ޣ\u0016\u001f\\YT?pi^U\\\u0007U\u0011\u001c3\f\\ه^pdF:J~zG~I'e-V.W%FywNzmOt9wVj\bׂ9%a=7,pW>HU觥Z3sĬݺ+8\u0007u]uQrwO\u0005vc\u001a\u0016nZM>Uq\"ՀcP׸S\u001a3$?.F\u0016*'-hy\u001d\u0015С<[u\u0007^q\u0011wv,\u0003\u001d^nNƸ+\u001c~\u000bߣqqdp`\u0006=\u001d\u0004xv\u000bewox5\\4/\u000e\u0011j.]w\u000f\u0006Tu4\f?\u000bXK`\f\u0018&g\u0019cY;\u0000+~惜\"6vyC\\\u000fwN(;L{uZ-'\u0015UJzCUj\u0006V0Kt\u000f\\#'~DQo\u001cΰ7NE\u0018\u0007|L(=]/R96G~uXx=\r&x\f\u0011\u001a;d\u0010KU\u0001(\u000ezp`츧\u00188\u000e\u0011\u0003eSk=ԮoSee\u0005\u001f\u0011c0>{/\"\u001c\":8(~\u0015ǿNnJ'憎<9k\u0002\to\"%.M~+η3%\u0001WեO;e\u001b+X'H%̝PH,\u001cئ\u001aD\u001f4?&\u000f#/\u0000Mߛ?%fs-?\u001dO8V7'We\u0007h~9?Ԗ_\u0013Oߛ\u0007\u0013\u000bs\u001b\t^&>\t07?\u0014\u000f7'W?ALoi'Mξ:N'> [\u0007s@\u0016\\owoo4/Ʃj0v#qD3\u001dҊ4D'b|<X\u0006Uڸ\u0002\u0003Ӂ7±7nV)~nyȲϻ[kn\u0017$\u001a\u000e\u001dS(m\b\u0010枣 r\u0011\u001a\u001fk\u0007/\u0004\u000f\u0007m_GV^\u0007Fo<o(\u0010K\fr4O;\u0003ǡ\u001e\u0019˵6\u0018\r'q`dC\u0007^6\u0001m3C\b\u001e\u0018\u0013\u0015z憑\\GN\u000b\u00199!\u0007f;3XEq0\u0007Sq#?t-{\u001bb\u000fk\u0003+K{\u0011y赱\\bhV:3θSI=Ɛs`|j_^R\u000f{\u0012Oqz\u001dNI1\u000f\u0006\u000fC\u000et]\u000ekeRv\u001b߁@u'T\u000f&툚|9\u000f}$}#3?u$_=j \rCQlz\f&\u00159Y.J<Fy&\t\\On\u001an\t\u00195>yX0ҕ\u0016̋=Ozm\u0007kqEz\u000b\u0003\u000f?v&ama'*_l)o\u001a)V^>0\u0006Ci\u001e㸰qK<ve\u001bVêM\u0016̿\u0007\u0003\u0012 geȧ,~i܆3j]3[*g.q\u001bQp:\u0018ljX\u000e\u001alޏ,\u0012qgIe uԅFlvyS/4\tz2\u000f\u00151S\u001d\u0016:J]m1K-`\u001fk(޴.&=EZ]_\u001a>\rSÓzp[1.<O'\ty֎v'a\u001eAj\u0004^/(W[a&д{q\u000e40\u0013|u\u001f<_nK\u0011m&̓!>Tfuu+[pDfd\u0014+CruQwp\u001d;\u000e :\u0017׻\u001d_z\u001cҴ4OH\u0011\u0019_ce4B\u0010\u001e\u000bCQa9\u00071U0{lդ2Jo\u001aǁ]Y_\r> ;[pl,\u0016\u0006U\u0004\u001c\u001dK\u000e\u001a\u0013?9}X\u001c[պ㻅A'GY~ۯզWO?\u0000O̟V2'^嶁L\\fVY\nFL[IɀW\u0017Vp΍6 fmhOU*Ln\t-\u0019L,mq\"iOi\u001b\fJ\u0015t٭\u0001ޱ6\u00127ܲ^'h=]U+**$z\r:\u001andθ݇6ݓk\\\u0017\u000b}\u0017,5'oy6ҫ)\u0018I1l\u001e8jwdWŦo{r`58\u0013|u\u0007;\u001f4\u001fn?\"\u00034g\u0000MFć4U~oCp{\u0013o/\tg}7-%!GM?\u0003͉c[~_o4\u0017T,)4?Š\u001aO\u0010Cl/e\u0002V.z)D\u001f\u0016{\u000f\u0000l}m\fg\u0010v/UH4[76'\u0018\u000b\u0002YeNZc2<\u000ea`Tѷ\u001a\u0018X\\,\u0007~\u0006\u000e_{\u0004bo{ay\u0000xk1Ff\u0014\u001692'\u0002Lsz9)ЇSջ\u001267ݎ  \u0017*^0I~/f6Ƒu\\o'4oH\u0013d\u001f8$ʞfYJBHPXi./o\u000fjpyO\u0011\u001f<\u0014>܋\u001a㖹O[h[7.0\u0007\u0006D\"'/\u0013\u0007i\u0006,\u0018\fث\u0010,D,3X#ץB\u0018(+jkx\u0003\u0013\u0012纞p\u0011D\u0006$\u001aBɴmbBbc=`;l~\u0010\u001a\u0004?\u0002\u001fy^{=\u0005s7i\u001aҜac8\u0010!̈́x3\u0017%@Sp\u0018a7\u0015aE\u00062>>\u0011Stt\u0005y\u0018NO\u001d@[C\u001f5\u001ft-\u001d^T ~o7\u0005<(\u0014$O7+B'ӫO;Zb\u00073\u001dӸG\\qK4Ӏ-\u0006KU6|7\u0007\u0002;A\nkn\u001a&*O)'\u0007v[\u0007gF\u000b# n܋UӰhp\u001a8^5V=]>\t>\u0003pnXBG%j\\7fl\u000fi\"=\ti*k@X\u0019ʡ\u0004O3\u0018%/l\u000fi*\u0007Fʫ^L.\u0004XsxcI(J+(/\u001bl\u0001\u0012]!Q3R[h37\u0016q8Ca(z_l:Zj2\u000e\u001a\\|\"=iZ\"8\f1Zr˵ċpԐ\u000b;ѫ-.oWqRz`yI\u0012*\u0011Qg!WdsJ\u0016۬쿂>7?-Lr\u0014,eQ۬7QZEKR\u0016dXll\u001eH٣fpn9҃I%4\u00184:ۍ=ظs6c~%|:\u001ek,gWg7j덊`NnXZKbi\u001eikWÌM\u0019uZjU1\u001bp\u000bEIUe܍\u001f;b\u0006sr&'ߋ<\t6`1\fl۩ӱ6yt\u0005<Җt$N_\u00050=\u0018uق\u000b䰓2v\u0003uh\u000b0b?vVb\u0005y\\]\u000eބB\u0006.'*wg\u0015\t-Y#\f\u0000Vd\u00188oq;\f\u000fcWջ2\u0018<\u001a/\u00035{\u0006`[}\u001cm:\u001al6m\u001eNKdbq+n<z\u0000PSe5OE!Åu\u0013tS\u0018ʹIç(\r;72q[\u0004C\u000egs\u0018pJ:KyQ\u000fhy2hV?K\u0019X1\u0018vL3\u000bjȮd^۱\u0007\u0015\u0010ޭA;mw%SM഼AR\u001b}HcDwƜ֭q\u001d\u000e6\u0005\u000f}ԋ\u0010>{0$IkjO}$j}U\u0019%z*\u0010n9a?\u000fUl\u0012aCM+uTP\u0004YV~\u001f+.zA\u0003\rn7=ɒdjifSjS\u0005Z=[\"\u0015k5n\u001f?\r`PsivǏg⡳?o\u0013n6Sy Qy\u0016Cń8Zj.t+M\rbFäIr\u0015K%`(Na6\u0018v~\u0004>\u001f8\u0011\rV#`h?Y\u0019~?0g*\r*Kڎ\u0016&/ux3Z:Of]uO^|b?Ga{\u0013>9:kL#)=7+\u000f\u0000MY?@\u0013\u000fE짉\u0000Mߛ;5?\u0014_\u0013OF\u000bo$ߛ;5?\u0014OߛҖ_\u0004'\u001f7CB%:$*D|8g/jej.I~\u001f&(y98\u0014*\u0017\u0007Ou\u0002%\u0003>\u000fC$6C$\u0019Ht`<5\u0003]E\u0012o47M\u0018ھ-1\u000bUe_&<M\u0011srJ\u0010Hd/ڕ]\tr7rh\u0003soh\u0011|::0}\u0011͜ Qu[2\u001b\u001djֻ:\u000esqKJ>m\u000b2:5矁( (\u000fi\u001eo\u0007\u000e#ZDB֐<9.mO&\u00145ֺtr\u001a\u001c\nȸ[Y\u00048?\u001bzY:\tl/-h\u0000jt9.tpHs\u0007T[x\u0014AT^Qfj\nŻ)\u0014\u001217w= \u0005\u000e\u001f0?t\u0014\u0012}Thi\u000b\u001a\b$b\u0004SRm{ھ\u001c|\u001a{XizA\u0003Q&E\u000bW\t}0i\u0018\u0006A{Q\u001aί\u000fx7m\u0018I_g|1OK:[Eծ\u0003M\u0001s13z\u0018ئ\u001a1\u0018:\u0016wf-qgWOoZO\"YԪ[HT\u0005\u0018st\u001a.\u0017\u0005i&4\\ߍ0ΐھ%,nd(\u0017s\u0003e1XޗAk\u001c%M\u0017W\u0016\u001cW-4\u0011զ0󓶈K\u0011HL_b\u001cL\u0007ʩ*ifws\b62%`FOyn;k\nE8sΑh2\f&\u0018c\u001cUUǪ^Ĩ9T\u0011%1\u001b#2W'\u00144J\u001aȳ8\\\u001bǘ\u0003Ak\u000f;\u0000rT(r6\u000e8)%&\\3qvgnOoD\u0007*\u001f_o\u001f>\t>-\u0000cУ<ױ}\u001d\u001ecUvg\u0012`\u0014w`fv\u001b-D\u0016yP,,N=\u001c\u0007OP:D>G$0 I\bŽ\u001f'\u0019_F\u00005rU3_CoK}?-\u000f2\n׌w\u0015\r\u0017'\u001d\rѲ\u0003f!\u0013yP\u0019\u0013*h\u0002c\u0000\u0013߾\rx󺅀Yu\u001eq}\u000b;8;I3|i6t¦HG$$݈=\"ܘU\u0010n\u001a-q|?x\u0004\u001f &A\u001e6]_E\u0006y\u0003\u0006ZRvL\u0004Gʇ<;>\u001eo(ڤv[R,őP\"\u001cgW\u0011`\u001cA\u0006#%q\u0000ct\u001f\f\u000f'O\\̵\f42rڡ)N\u0019<<m\u00140+0\u0007֖\bd\tq$ڻ4\u0016\u0012p\u0006Eâ=\t<f>ߔkόn/ol߇ػ\u000f\r`ûUsʘ\u000eĲ\u001f\u0010D\u0012il'\\:u\rr]\u0012e\u0005<SX,XPJƹ\u0007ܓD^~Eg[-VoFżMVM\\aGIWAHS\u001eG0ۗ<ß#>JIC>\u0016HԒ)\u0016o<\u0007\u000b\ne\u0003d\"\u0002\u0019F'\u0002>\u0005\u0002&$\u0018\u0003kAK\u001fUafgO\u0005\u001dZp}ˌ3\r-5QNGj͔u3\u0005\u0002\u0011\u001cSo:2R-X\u0013(CN\ty\u0011h\u001e\"$SS-\u0015viEڑ@M\u0016=;4\u001dz6Բ-Hc\u0017y1d,\u001e\tq\u001aص$\u000ef\u001dP!\u000e5\u0012HT\b}\u001a\u0001%}U>#\u000f儝JDgKJBٵ+\u0007}\u0011\u0001n\u0012s\u0011(\"\"|K 1*\"|̼\u0004=L4E\u00045\u001eg^b\u0001Y쟈,#k~0w\u0002\"\u0001qh\u001cX}ObRF-\u00012i<`]Wg\f>_lg}슰?\u0019#|@\u0018gq3Gs|,h7r w\u000f{^+DHXkMx9o\u0005+\u0000]\u0019ڤL:\u000ennM`\u000bDVLwS\\\u001e\r*@ߒ\u000f\u000f\u0015z\u0007r\u000eKY\r\u0012$8'\u000e[\"\u0016a;G\u0006P״5Vܢd/L\"?/:WQ8_}0ʵpv̾\u0014DZs\u0007r:G07\tٵpZة6#Ӝ5\\\u0002wVЏ'?;WMGfݚ'\u000fٳ</Rd&B\t\fR>\no_˯@\u0001c/?\u0004\u0002&S/`~@Ğ\u001fп~W]b9{\u001f\u0013xug\u0001]T\u001b1(\u0018U\u0015\nI\n-\u0001\u0001@wּׯ*k\u0017fJϻy3\u0000ԕ\u0007nٓ^Y\u0012\fߗ\u0004\rqѽ}@Gi.=ea\u0010M\u0001\u001b`ɋj\u001c\u0000J\u0000lKw\u001c\u001855^Վ\u0005\ncO.S2&\u0001޽Jb?R%]dR\u001d%Z}k*\u0014\u000fO\u0003q\tQX\u0004t+\u0006\u0005\u001ct\u0012\u0000tz\u0012c~0چJ_\u00042\u0005&wjRwG%\\3z\u001f\u001cg0\u0010s֝?\u000b\u001e0o\n c]`b\u000f@\u00156vt6uw!zes\u001aABqx9\u0017((+p{GX\u0010HڗR˴\u0005r} jM2ěaȡ&\r,\u0012\u0002\b7ۨ_=[\u0015`O\u0007\u001a}\u0001L\u001f`\u001c\u0017.^I?㶑ˉU\u0010J:8*i\u0017q՛bN\u001fGB\u001clKLHY-\u001fП\u0002(p<\u0003{Re\u000b4w\r\u001e^\u000eJ\u0000dA4\fnR\u000e\u0019\u001aLYU0ݻ\u001d\r\u001c6\u001fl6\u000f\u0002\b=}7'\u000fiT[8x\u0017\r.l[\u001dm#i\b\u001e}q\u0017u?\u000b\u0016\u000b%櫳|mW7\u0011}uulj=;(\u0005mu\\4\u0000f6Yvq0\u000e\"\u0018_\u001eIyloٶYw\rzH\u001e\t\u001ekF%N~.zw\bΤ`N\u001cC/\b@=\u0000\u001a;\u0014ӉA;6\u000eaX?XaJ\nI2ţU1yBGm%MMǙ\u001b(>ܝ\u000e`jM\u0001\u000fM\u000f_\r?@oQk\u001d@XKS{\u0016\u0000]r*\u0019dں\u00117w۹\u0003:L\u0016{Sg,\u001fBX!v)\u001fW;~A+\u0016SQK\u001dA\u0007I1\u0018](Cuác\n2͵x0K]-VCy\u0011值ngZ3*\u001f\u001f*\u001bhi\u0007+*Ŷ[\u001e\u000e L#2+ꢌ:t*>#!\u001fCq8p\u0015(fN_AB\u001c\t]_@\r\u0019#\u0014@H\u0000s\u0014cֻ\u001f%XI\u0016R\u001cgQ\u0017Ղ+uT3VdYs\u000f:KlHOrCH!*(5t4d>\u001a.\u0017>J5|@k\u0001z\u0007%\u0015\u000e`uJ?w#Q4Lrlz(\u0013HVr9xs\u000fz\u001bIp?Lje\u001cJ\tE7thȨ\u0002\u0010\b\u0011\u0019\u0016%\r\u0019\u001d$(\u0003Fj\u0013՞\u001dՌV\u0007t\u00035X]OgBf)u_*ѣ\u001c\u0010}*\u001b\u0017\u001eo>өAh~C&]^㼾֒EzÓ9\u0013&M\u0001&g\u0013\u0000\u0002L\rV\u0004F}N^͓)kt5>\u001aD\u0015\u0017\u0010R8M_>vzS\u000e%\"sM\u0016x5\t[{\n`X\"?g~\u0013\u001f\u0003U$g\u0004\u0000ZK\u0000\u0018\n\u001b/\u0002*\f6HIK\u0017j\u001aW_d\u0019l0<\u001f6F-\u001az\u0010HTO|\u001f\u0000tC\u0011ޓ{\u0019~g/hzֆn\u0013u#35yw\u001ee|ai\b\u0019f\u0012\u0013WP{ҥ1o^g%TR$bQ \nL\u001c\u0012ʩIѕ҃NgU\u0017.\u0006q\n}޷y%+mZZWt~&]\nTv5'Mca{:\u0011^-ɷt 9K\u0001\u0016[?\u000b\u00194}{y->٫)MYHweώJ\u0013\u0012iڔ,\\lG%$|&]\u0012\u000f4F>nx[%\u001faI\u0015\u0007\t\b+w\u0005/k\u0007\t3$\u00146a\u0014)ٚ28:\n'_ N4&p\u00190\u0001~r8\u0012ƺ\u000ee\u001e\u000e\u0019w-ﶰCv\u000b,,F}־s;p֍ b\u001bڧv\u0013g>jސc8\"^\ng,_n\u001avCD}[_?/\u001bW[//W>7?8[V~9\u0015\u001aZ6\u0002l?R EgN\u001d޴g^\u0017-8\fokj;[\u0001ئZOBb\u0019͈Rr-pY\u001cnv1sS̪ၞ_c{ǌL\u0017_m\u0015QHa3^\u0015]3K_\rq9B\u0006\"\u0003\\H{\u000b\u0016$\u0017ٶgEs\u0015u\n+6_\n)z'3\u0015e`V)rh[Mn\u0007}T&ö\t5n\u0017\u0003oV\u001e31u\u001b<9\u0010fw\u0004g\u00179JW䡣m\u0018wJ4\u000fOoE=\u0000ѢjŬD\u0015.\u001e\u0004=y)AO,'P1\u001f^+,<ap\u001a$zgl96\u00180Uo\u0006Ez\n5E|*.\no\ny#//?1q?\u0004\u0002\u0007A\u0019GH!\u0017~,\u001f\u001d\t?1]?:\u0013\u0013c,19\u0001\u0001(|\u000f[G2\u0006EQ\u001dGI\u0002{I\u00008\u0001pQ[^(aw\u0014ާvOЋqQww>X?|DU*\u0007I\u0001f\u0004$\u0018?Z-\u001eLY\u0016C+\u001c#:\"z^,\rws̚gLN\\K\u0001F\u0002oU'&\u0010\u001fw\u001flFvL)\u001f\u0017\u00040BF3\u000f8{Qr{\u0018\u0013\u0019`Ӂi${\u001d1=A\u0011z\u0000z >\u0003̞r]^)-8\f \r\u00163wQ\u001dm.\u0006ʹ_8wG9J9\u0000*\u0015\u0000j\u0003>\u0001\u0015}F!\u0006؜O\u001e\u0004˾)|ޞ\bpW:#O\u001e\u0014EQ l$L\u0011`\u0005¦\u0002y|e~_\u001bs}bҏ\u0016\n?>˦t;w\u0012lVɤҕJe@'W8\u000e~9\u000baIBt=K\u0011H8Mt!\u001fp\u0012f\u000f\u000f\u0015*AOwj\u0006a}rl&\u001c<v:&\u0001mu1LjZ\\+x_p\u001e<<\"gIDqrq6^f\fJNtY606~K>\u000b`,\u0000.1h\u000er=\u0018ûX5?e!O\u000e{\u001cȼ\f8[,Ϊz 0R\u0017糗a(?oҏS}cVs9<px%okqC\u001agQ\u001eʠx}^Gq)Yބb_9\u0005,q\u001bzL[X9*\u00100{E\u001f\u00040fQJJ\u0000\u0014\u0002\u001c\u0014hf1X(\u001dK#)e%_E1vn@j\u001cY\u001e<\u0012\f*S/I7\tkBߗxt\u0000w~1vy\fu8|u\u0002d\u000b,\u0016\u001c\u0016C,NOY\u000fSlpv&3\u0001\u001bd&V\u000f_~`$]={\u0018\u00138\u001cؐF\u000fܜ\u0000t´V?a0p\u0015mEuKK\u0010ތlJ(gzGg\u001cX}ȓ}5ت\u0005W\u0001O\u0001iTKPq\u0013x\u0000{ N׋ziM+6S\u0004zc6;U\f`Q;9'u\u0014bMILN\u0004qj\u0017<\u001dٸ\u0016\fa\u001a\u000b Մo!H\u0010XT\rSnoLS꺋+*h(Ϸm5'fY;̯OZka#'\u001cFg \rվ\u001a-1܈4\f'\u000b \u0000{\u0016Xy}\u0001{sa\u0018Ʉ\u0014,\u001f6[9ڔ\u001d9]υ%xD\"qT\r[\r톊҃RbFqdTWT\u0002Y\f\u001a\u0007'\\$\u0006k笥+R,\u001bR,Msh=gz?\"\u001d\u0013a[\u00039N䑇AFed8:ȰT\u001cY\bK\u000b \u0003{6\u0005bT+V./\"j'WMZL1Ӽ*~:q_rVT|K1t d>`T\u0015TjZ\u001a+7~_\u0000c\u000b$VI)W\u00077Eh=Η#\u001cE\u000e^\u0003\u0012O'kl\u001a>.X\u001d?-?S-@\u001d>S$Jf38zgxg_K\u001cQ\u000b@*\u0000m%\u000bQծfrzuZﷁ\u001fX\u0006*\u0017V,[\f%&QpMR\n\bm{%tʇoY$uϟ>ݺ\n_\u0000\u0000`1m|d$6\u001b#С~2M$+S\u0011化FKN7\u001cBz8<12r-\u000ejw,N\nM\u0013=tbv$~@ߒ/\u0001~\u0002B1\u0017Ո1rK5d́\bֆ\u001b/LZ,ZQ|%zْ<D\u0005\u0012%]a-8˲=O2]<a\u0005,;\u001evk` Y\"\u0000\nQ/f\u001e];9t_~Y\u0010|v(#\u0011~tr܄po&L\u000b}\u0002+\\-\u001d\u0002[SbﳰO쌪}\t$xyQ1-,\u0004%)R\\|C\u0004M4Y;m\nU\r\u0010\u0004\u0011W\u0019,w\t\f~yiNwf)1mtW^Wʈ]lPX}\u0007\u0005q\u001fvP3⪷/\u0015d\n761K\u0018*6\n2\u001b.H%A\u000f]grBGʹEaL͙I6[^\u0007kn6WW\fzܬW\u0003Yv&\u0010uq\bG\u000e5\u0018s\"KU.\fM\u000f\b\tf_gNÀv]|5rge\u0012l\u0000E=zc?/;hu\u000bVҿ/4Z2R jQROd<ǟYC3xow]u7k\u001aa5b:\u00153kuTg#MBȜVir5\t&IcR\u000b~\u0007?\u0015\u0013\u0016hS\u001dg}ri\u0002\u0010L4#d\u0012{gw\rW;_Xq17.66\u001f}zB'Ĕ&4I,B\u001dw)?oMQ_è1~K>ϋr\\xu\u0015d\u0019\u0019\r\u0016h\u0017\u0019\u0001~O)hA\u0014/;6 \u00188\u0003r>\u0014\u000fp^oIg\u001bȋ>\u0001\u0002\u001f̢a\u0000\tSKTY6\u001aQب&[\\Fm\u0003#T=;ع-q4﬩Cb:ICfœmV'\r\r{\r[W3V{<Ϫ?x^U~RHy\u00140{ߊ__~\u0001\u0003Ǡ_8\u000fA\u0001c/`~@?\u0004w\u001d\u001fU^3AW\t\u0000-\u0000i\u0003\\\u001ac\u0014~b<tjt4؞4,9\u0004|rT\u000b\\_\u00057S|\\S\u001fߒOP\t1Q\u0005&J^^Ee\u0012ؓd\n@s-\u001a~@lnEA`]Uhآf\u000bI|2z7W%\u0012yWG6w\u001d\u0010:1(\u0012W\u0012gɭNZQŠ7\u0000\u001dSN\u0006U:z\u001f\u001b+sEihz-sslFkn\u0017\nf\u0016*\u0005J`6GOr!`&%oITQWO\u0004\u0018X!Ǡ\u001e\u0000\u0013O<ۼ^4tdPZ9hxt\u0006vՋp\u00168ͻH\u0015\u0004\ny'2Z<\u0000O<h\u0012oI\f\n(\u0002{r\u001b`ϡ\t\u001co\u0001{R&\u001c\u0000fֵGD55 u\u0010zmZq5|qԠ5\u0016W-Vtӳqס|_\"/)\u0001_C`eLXb|@*.\u000ecPm\u001d]}\u0005*V,zٱGF0R#b(i~\u0019frV\rzW\u001b<X=,2[\u0003;§P\\&PВ6\u001ed\u0015L-Y*0cL\u0000\u001aڶ\u0001({l٣(\u0005%\u0014d\u0017`o{RtI\u00040FbV\u0013\u001a:\u001c:M@\fETߒr?t\u0000h\u0002\u0014}|?\u00008\u0004^1]='4TG? \u001d=\u0004'ߓ;\u001b0Yg\u0016/[M\\\u0016W~?0]^-\u001fLwQhZ>?TD4׍:\u0003\u00148\u0001ǛgANT\u0001(\u001eD\u001dU|hW\u0018(\r\u0017\u0001r,%\u0013\u0018[\u001eg+u\u0012PF^M^]Kƚ\"\u0000{>\b٫u\u000f\u0007\u0015ƙsoTm\u001c\u001b~G.Vvg*MZ\u001cYއ޵oL4'\n5x䑜\u0011\u0001^W\u0002W/\u001e.+t@g\fWlqfoѽY\u000bc\u0005\u001bjHή\n^r\\z\u001c\u0017h&l񋡑j@{\"elP0\u000eqz<#O/\u0007\u001cUr/v\u0014h\u0014\u0000\u0015K:_SDWwc׵EumT\u000b3Ro(Mы©$ɔa\u0014<5R{j\u0011V\u0012[,\u0013[|$J˂@\u0006\u0005b<@vY])W/\u001eI/\u000bK\u0003~FڵdS\u001f%*y>đ{k\t_\u001bǫB}\n\u0012U;f?κ4>\u000b@\u000b繨=\u000e%\fSr\u0011\u000e*lv>Cef\u0007kܬhm'+wkZ\u000b?\u000f'Ʊ|v\t^\u001d\u000f8*(i\u001bG4\b]\u0011\rl|@\u001f-\u0007\bFk86\u0013}-zt>rR5{n:\u0006\u0010\u001e\u000b6~L?{&W\\LEzâ|mU=Ƞj(\b[UȽg\b%Qu\r~\u0000\u0015\u0000w\u0001lfZ|\u001bwM~#tŽ5U#b!*7]g\u0019iG\u000e%!N'q??G^\u0016\r\r\u001e#,)ᧀgߊ_IT]b.g}>\\{TF}wByiV\u000e:\u001fɐ;[&T|ZPF]\u0019`'!J3Ê.ut2UR\u0013u-גv\u001ep<\u0018b\u0000\u0011k\u0019ՊKjQf c^hbmBKo7v\u001df\fS\u000b:}N,L\u001e\"\u0019:\u000e08E v:ϲ\u0011EOvW1(+(%Q\u0000Li\f0)\u0015`$\u0019\u0014q!E(ׄf&Qܬ8E\u0013n_k/E~-\u0015OXnOq!U A>_z\f\u0001i\u0006@%\tLY=x\u0013B\tLM5Ml\u001a3UF\u0001^>z׶\u0004໏\u0013\u001bu)\u001cv8-ަoat\u0015pٞiq<\f$\u0006j\u0010UF|\fθ\u001a\u0006쩴w1\u0011\f#\u001a\u001cv\u001c\u0002G$\u000ez*\u0016F\u0000%Ws=Hr9ŮX5\u0016=.\u0002\u0005\u0016sO\u0002A\u0006w#$\u0015^Tk\t 6Ymj88So\u0017\u0007q\u0005X\u0019\nF\n\u001a#b\u0005!GzR_dc\u0015-Lߛ\u001bl7\u0002]\u001fh\u0015j^ˇ5-~+#r+\u0013-@ZwD;9-/L\t4Ub\u0005X\u001bl8\u001bw!\rl\u0003Zg?\u0017$h՟\u0011%r[X\u001cVy1-ks\u0005-6z[r\u0013rT{*؊<\u000b7\u0000\u0003U\u001a\u0002>>`J\u000bD\u001d=F;7Aִ\ba-ZN\u0012?_Z`vن-gz9=]r8rKO\\`\u0012Q<Gޱ> Li$iEk Z\u000e%\u0019kv_ǗR\u001b\u0017\u000bt\u0000Õ35<0u4\u0017䌎\t^ZٷJ\u001fO%ηJZz\\ե9JNY80puW-\u001dձ \u0017C8\u0017dV\tۋi]-'Z\u000e]\u0014G:XsM\u0006)9|\u0016P`F0\u0011uāDt\u0012T\u001c{l,\u00050mM\u001b$/a\u000e/7>ޖ\u000b(J\\rЄecfx\u001aU;<\u000eaꀌ\u0006Ji7\u001d̕|Y}-Z+b\u0004̰@-ܧ~Ks\u0002\r;\u0019ؚ;s\\\u0004ЗKjT\u001f\u0004{\tÔ\u000e\u0016糯d?_]Z:[\"]٭>Ι\u000f:0t\u0003CET:QDhEt\u001a!\u0016\u00068FؗyEPߺR\rpfK4)/\nִ}\u0011? +xblTji*ًk΍7\"t3V㡗xU\u0015&)\u00170~\u0001\u0003Ǡ_gW\u001c\u0019{GT\u0000D;Er\u001e9}{`~*\u001eh%.Ve\u000e\t{Д\u0018ԨVz\u0012\u001eMű\u0015st3sohǲo-;4V!U6L\t\u0019_ Q9yFm~\u001a\u000f\u0017'*wڍn\u000f@dFpm\u0017=k\u000fΰ>ܸ%\\-A~@'2u\u0005S݆يadiX\u0013i\u0014[[䕧[4v-X4d}*$\u0004r;Al[p<\u0000=TgQY|Qy:lF;F\u0002\u0007>Y\u0011/I;WڹH\u001e)IQ\u0005\rG3ecS\u0003\u0005\u00016Sqn;y6V\u000e\u0003>Zs\b\u0018s(Ex|FW\u00054j\u0004\bI\u00134\u0003\t92~X'Q\u0017-]5Cp$\t֚W\frUd^\u000e{\u001bK\u0017\r\u001b7\r'q|>.\u0000|wDڟ\u0012GGTp\u0011\u0017\u0000#F\u0000\u00037wp'Bx=w:&zY\n!@IBnEC疆Kfgg\u00026>kr2'.NIX?W\u0005/\u001d/\u0013\u0000\u001a@; \u0000tJ\u0003P\u0002@_;\u001cITV춇c4G)WA*ҼG\u001dܛp\u0006ǩzbv9\t\u0005ne}U\u001b]I\u0000\nO\u000fb@>p\u0010lx95:זt sv\u0000\u0012/)<];\u0017\u0015\u000fO\u0001\u0010\u0010\u001a`t'~O\u001cZ\u0014g8|@DebʯU\u001c\u0001\u001fW\u0000(Z\u0014\nl^#\u001d\r\u001bK\r?trZ9+;Zn*\u0005\taqz6|a\u0003N0\u0017Dme\u0012CmzW%*\u000bd\u001cQ\u0000\u001eU\n4,46g/;Wp8r\u0006irsJ,tG\u001d\u0015O\u001a\\0.)xJݎR\b\u0006\u001c\u0016Va('яdU\u00077U\u0004*\u001a`\u0016=-[C:g<R2\n_L9\u0001\u00059m\\;\u0005ﰖ<oi,H#Vp$<yޕ\u001fYZ$\u0014ܗJ\u0007p%fH*g\u001as\u0016O%\n\u0007~U)QSA\u001bu`O+^\ni\u0000/jOYy܆i&X\u0019C4V'\r~t\u0018\u001aQn\u0005qu5s\\\"l:\u000b7L=eJx(\"\\\u0002)7xH=h5U96\nh\u0010/\f}T9էw=n\u0005O\u0007zӯUso\u001byeO\u0014f`]\u001aly(ă\u0019\u001a?HwAۍê\u0007\u0016;\u000eCh\u0002DeI\u0002\u0016g\u0000\u001c_.*Q\u0015\u0006]\u0017>\u0018]{]˕\u0013\u001dꔝC@^(\u001020}:+&nV&J˴;4ۯ4\u000b$%K\u0003)P\u000fWA\u0016ց=pF@\u0014^:ZP#\u001e{\u000bd'\u00172{R6\u001d[ͧ#\u0017%CUF\u0010fFXv\u0019\fO^i\f\u000b}\u0012#\u001e`.O\u001f\u0000㵎Rj-7xP=3}\u001bKU{sO7BfrLZP\u000f*B3\u0011#\u001b$\u000f\u000e[\u001a%\t\u0014\"ܞBw2\u0012=D\u0002X\u000f4U\u0003Bףj5ឋjB=\u001b\f]Ԏ\u00038,[cVG\u0011\u0001üG,Xu\u001ewN_ɭE̝FQ^\u0012\"<n\u0002,4\t\u0016F\u0014\u0014\u0001\"ԬwP\u000b@9\u0012'ΣژռB\u0000\u0018+\u001ez\r5lڠ`u}K(\u0015O=\r]*o$l\u001c0Rv+h/KԞ\u0013Ԓ|TSgqyvGk\u001c\" A]wv5ATP'ؤ\"˃\u001aH;\u001d*?:M\bo\u0007m0Bqz\u0007\u0017\u0015\u0015p޸q%}\fQi]-]q\u001fN},JTYrQ\r\u00016]Tȁޣk\\\u000069U]1)b\u0018\u0019o HT&\u0000<C\u0007zj\tCj~\"\u001bWϝ\u0015\u00115K\u001b8؈R~|@?Q\u0005y\u0001@\u0017gzj^p'T\u00070\b\u0015*]\u0011\u001e|B.wU2\u0018ӗ萞y\u001fmy\u0003ݺ\u0019ĪKr\n/\u0015\u000e\ny\u0018U+\u0010h\u0003Ln\"f2ė\u0016`\u0014\b00M'Q\u001aNy3*\u0017r\u00058\u0013\u00045}^\u0007\t\nYo\b\u0006%-Î,D\u0016\u0015rj@/\b0e\f\r.S\"gk\u00149~S\u0004(\u0017@8k\u00070\u0016eA$\u0011c>I\u0000#%xIwBpk4QziJU\u00168N[EwWk\u0004\u0004]3DA>KTը/n\fkW4؂o\u000bT\u000bWplT$zx&\u0010r{Wv\u0002do\u000e28\u0006\u0003/fQ4_+`<63\u0006\u00104+\u0010.֦[3-3\u000bJT%Ee[R־Y̫\u0006\u0003e\bޗ\f(\r\u001d_\u000eD\u0018\u0003\u0004%\u0007}F\u001aejT\u0017byĞmfr'X\u001a_\u0016PjLD%*5h~\u0007\u0012UߗgUr[:海؆C\u0002\u0010-@aVCtc\u0002Cl¹_\t^\u000e^\n\u0006mlx!ng).Lpv\u001d<\u001fv;\u001dgMԋ!j>p!!k[\f59bc_\u0019ͯ\u000fc{,H2Yn*Eù23XMؼ4\u001c\u001aŘ.cG\u000bA\u0018\u000e\u000f\u00117q0\u001bԾ*7*brTW\u0016.\taV\u0013t \u001e6\t\u001dG'7ܪ\u001e>wׅAǀlFOo\\\u001b=zyVp[\u0003e\u000e\u0016%d\u0017I\u0015M=k<Za+}T\u0017T\u0017\u0017OP\u0007Q^\u001b\u0014\u0016edj\u0018rhQ*v~,͍\u0018V#JIl79z\f\u001bhzKi\r\u0016E*gȵP{\u0017^\u0003Mu>ib;8R69:*\f*b\u0015> \u0006\u001a=\u0017DW)t0},k.Y,1=c\u0015\fMvļk\u0018C\u001apz\u000e>\u0010v R\\M\u0016`V?+\u001fPi\u0018AsTTo\u001bGDAdE\u0015h\u001d\u0015G)*BT,\"K \b]>GMZoãp\u0005\u0011Le\u001e'\nt~[\\u0^\t0)^(^eӑ]/920A\t\u001a_\u0004|@)_\u0005\u0002\u0007A\tFJ\u0014\u000b\u001f\u0006]OQ\u0011\u0013Q_llGd\u0018\u00157G!%GIvO(x~xyQTIkv\u0006年l=VCj&\\(\u0017+[GN5\u000ew\\ gCS,]cU?\u0007Z\u0005\tU}\u0005F9qZm\u001f\u0015/\rio{;\u0001@CLV\u0002i\fw.\u000b=?\u000b\\\u001e*s50J:D;\u0017\u0010C:-ͷ^fY7yDE\fX=\u0017`]}EE\u0003Gz\u001eJmto]L88\u0016kl|c\u0011ms랙46\u0013\u001cN,e=gӫhCJkaʇ\u0019n:h\u0018J{j_\u0010`&0㚍J#\fXRViF%E%N]|#?w}\u001d+\u000f(6߬3sYe^mٻ\u001dsȦDcF۽@8=3\u0004u\u0016\u00105M7Ii\u001ft])+P\u0001q\u0012\u0014RUGbԸDEЎJw\u0000t)m>_qm_īK\u000f][H\u0011݃u4<\u0016%]\u0018;\rdyVƾأȷє~Y9N\u0013\u0017\u0004r\u0002t>*,l/W\u0013T;*\u000f\u0004\u0010|:\u0019Q:w=滵ۣ\u001dQf\\,f\tpŅ\u0013cZ\u0013\u0016T\u0015\u001ay8\rʽ<, \t:\u0011 \u000b\u000f0\u0016\nQi~FRm\u0012Ft\u001bGm󌧛DN\u001ee9rv/8S\u0003\u0012J\u0012\ngMۡd*}0\u0019+ZU[3=\u001d&f+[AESSmRew\u0006e\u0000\n@\\loqދG\u0019CʧbtRLPՋ΄3\u0001\u001dK>)\u001fND04Hߖh2\u001c0}SR*=oSGTN.\u0014-/G<G4\u0005\u0001k`OYJ\u001bJ\u0001`n\u001c\u001b\u000f48\u0014*~5L8NՋQ:g\u0016n{35N\u0013Y\u0000:\u001aFӍB\u0012ғ(5rŅ\u001aQW94\u001dY\t\f՚y\t\u0005J]\u0004ؓ\u0001oM{\u0000+:#H*BP(j\u001cn:~Y0\u0018\r< )y8syxIFAL}\u0007á|8\u0016_\u0016_*KiC\r\u001e\f\u0015=S_\u0007yJ3\u000e\u000eQtyQVTYs{r*}8tKm\"u^L=>ꐧ\u0014~\u0011r8$\u00003>\u000e-\ns5V\"yzAo\u001a\u001cJ6,\u0002|ǔ;\u0005L;A\u001egW=l\u000f9׮r/[:?c1b*U\\K*\u00066#4/\u0012K\u0019La^\u0004/bّHhP\u0007\u001c\u000eKwM|@Ai+\r\u0012>\u0015\u0000:-qd|+lȹ?w\u0003\nfI鐰z]`)<||\fo0q@B=\u000bS\u0014a.\u0007b@_\u00004DQ9գ@<\n&֢j\b@ej{tp\u0015\u0014^8\"ge\u001baz%pu4\u0014>\u001cSxu\u001cg\u000fKDVDv\u0002H1j))\u0017\u0007\u0002愎#hr\u001ckͣZ2GC͹\u0012;2>v7\u001d1\u001a\u0019^c2VFXp̈:#\u0013i\bk\u000b\f,\u0001%\u0006\u0019\u0015G\t\u001a\u001f\u0015\u000fgW\u0012$=^BƁ=+64\u00068|\u0017o?'\u001f[\bq8;9ݷbò\u0018qCĻeC\u0013\u001dl\u001fN\u001c=\u0004-i8_\u001e`'~\"\u0010f-\b$\u0010K\u0017$*[Y.2<ƛaTzy(\n}׼~[{;ЦT2r\"/2\u001a9\rz\u001b\r'J\rxa2\\\u0005\u0005Yuf*\u00070{]\u000e[~c\th\fã+\u0012kTn\u001dQyq=\u0005Qzd\u001a\u001f]X_\u0010\nZz\u0017$7UB\u0000\u0013vAt~y\u0001%Y]%j+\f\u0007\u000bD\u0017ѡ˯ATEb[\u0016qŻ\u000eF$OOʉ\u001bu\u0000*<2>~\u0012\bRҕڴ7zã-onTFB\u0018e?zzo\u001aZ]>bR-\u0016\t,m:\u0018/l^Ȧ&aК\u0017$*\u0017[I\u001b+\u0017>(\u0007\u0018\u0013^\n\u0013C\u0011\\΄:ݕc5<X{[H\u0005\u00187|\u0010m.\u0014r\u0018jԲ8+9v?[)0\u0003V.\u0012\u000bX<\u0007\u0015]_\u0010\u0014n}W=I#Lf\u0017:ٚ&\u0006y\u0018\u0014u#`<9=FGyTtI9\u0016\u0006LatW\u0017\\mBJ\u0017gfM\u000eO\u0017<?\u000f\u00016*o*}n9ħ\u001f̴B;'\fRʒ\u0012\"k+v\"\u0018^\t\u000e6U\u0001لi`{53ne\u0015dvO\u0015k\u0013\u001dLi?'inR\u0005zb]l\u0017\u0004r\u0002z\u0017U\u0001hlw$u6HbzPrMl״:;ZS\u0012]\u0018{!\u001cd\u0003!2˭o)JOY'ǜ\u001a;+`Z9d:L\t#W\u001a6(,VqD`GE\u00197'\u000b\u0012m\u0014UTz\u0018^dqEL\u000bd;!\u0012\u001e&W3ۡf\u0001t\u000b3b)\"|3)rdN\u001ayF6#=VEօ#x\u000e@FQ\fDE\u0014T\f\u00180`\u00001\u0000s\u001aw5^\\3(Z\u0016[\bIR9\u0016`\u00027w)x1VZ<(?:e\u0014[ۚi\u0011s\u001au=\\W\u000eTSY;v-=\u000eVJkiF>2g=\u000fR\u0016\u0016@ɕv*(%*j+%fQ\u00103IT\u0016vB\u0000_r\u001c\u0016lX8\u0017;έs3b3\u00132\u001a_\rEOi]JN\u0016z*0*3/+ҫ^^.*!)6L8+5\u000f\u0002w/1<~\u0010mR<E\u0002~5w^9lmt~>ذ{Gn[\u001exo\\4i٩܂r~p\u001fI}½5CϾOI\n/MZ)\u000bN_\u0011\u0005(|\u0012Z<\u001e{\\/G\u001cc*jPo̭[ \u001f\u0007,9hR^Da刿\u0001jyq\u001d?fmw\u001b?߭\u0005嘥%;qvӛyЀ\u001fs\u0007H}h6Dʯ/ZzY\u001fzY >T\u0016޽fQZ5[>\u000b\u0007{굵\u0003ƿn*\"zz\u0002eb59&\u001ah\u0018mVU5\u001bRrKvu`?։]\u00067VaQqgnS?\b<\u000bs\u0007Hu3'E_\tƃBRPa'8Fѯ\u00063\u000b}i$׶*\u000bl\u0013c<]`3>[)6YF(w^)J@Du1C\u000bA~\u001d\u0000V\u001e >\nVK\u0001\u001b\u0019\u0013\u000fE\u0005# |,'\u001a\u0015[5ZY<-U\u0015\u001f\u001f\u0012|S\u0012<6\u0003n8vs%*~*2*9ßgMx+_h \u001fD9\u0017\u00107\u0001A\u001b\u001eG@\b \bH0\u0000]X\u0003B>Ѱr^clL gSzr*=\u001f\"I(w2/Abu\b\u0007\u0013\\\u000bAp:,vπ%FfP`W%zEH@\u0007m@\"\u0005\u0017\t\u0003\u0014\u000e*жK<y{~>\u0015\u0015xyrg'p}4\\Ҿ~\b8K\n7\u000e7\u001c\u001cE-\u000e?͇m4[\u0017)\u000f\u0000.CK\u0004\u0000:l(΂]\u0004Nĳם>Hc\u001e\u000b&*WL\u0005p3tF>0YxCϽ2S\u0014N2;n*^9퍿A~\u001d~\u000b@VD(j{h7\u0000y]\u0001UM6Q7ށt3\nrU\u001c'?\u0014\u001f\u0012p?ȽN$r91ߵoZu{|k]Q7 C&<[+sC~ѱOeg\u0000|K΀9@=@\u000f\u0003-\u00006s\u000bWd\\zs\u000f\u0010R\u000fݺ~fp탶H~Ȟ^>r\u001d\u0014>ʯ`}Μ\u0001Nk\u0003\u000bu\u000e5F\u001eVv\u0000(M/\fE\rbe͍{\t \u001agCu*\u0011CVnh\u0003\u000f\u0002_\u001d' /}c4񮃩j츲\u000fzxT']\u001a\u000f?\u0000ȱ\u0001i}s\u0001d\u0000Q2;g\".5\u0007[dwT\u0006SG=;\u001bݴh~%~~^}\u000ef\u0007כ㚡g\tb\u0005s^1k.\u0015*-?\u0003\u0001/ڟ\u0018\foRm\u0012U]\u0013=@Gnv:S\\}3\u001as!}j\u0007obR5|C2/!ygn=x\u0012wafqS\u000e9YKnn<}\u0000 ]k\u0007\u000bt\u00057/\u0002ʞM\u0000}Y\u001a<7Yx?[O4H)I5\\>\u0002F\tsS\u000bٻir\u0019sg\fwwsXjB\u0017u/ăY[\u0019\u0012?/\u00002\\a^}\u0002*,軈\u0015NF>\u0005=+m*\u0012O[Bݛh\u00195便0>-gEyuسZ^N4>=p6\bәö\f@7P}\u001c;k\nrw]$Ȁ\u0014@^nB7.IWt飏\rC.\u0007=.Jmqטz=;vu-uy6\u000fa<\u000f2%l\u0002rc^ұR@3\u0012\rA\u0000(Z݇}w14\\@[\u0005\u00065)O\u0018)='l{m4(<Wj\\m\u001c|2wkJȪvVkb|(9\f%:0&=޷Lm\u001f\u001f\u001f\u0017\u0000\u001f\u000f07@\nl,\u0014\u0014_ ?~7^\u0014i<>~޵3\u001d\u0005An\\\u0007mrN\u001dXPmjY\u0016ү\u001dB|UӨW\u0019[5\"\u0018L\u001auoOc\u001coGGWGЂ\u000f\u0000xu`Q\u0012T\u00156Muk%\u0000y.\u0001ݏ#!_\\={2Lx}&C\"٭|0\u0015q\u0011\u000b\u000bN6Rmܚ+\u0011)t3Mq\u0005\u000ffXE1X6Ɂ\\\u0000y\u0000\f$B\u001e\fL\u0014v\u0007\u0007/笳:v0\u0000c~\u0016*e}\t:V'dVe\u0010\u0006.ĩ3\bS{\u0010G\r\na\u0010_P\u0013~\u0001%ޠ(%\u001a\u0014`\u0016];\u0004A!mќi8\u001es}⢿i\u001f66_ӥ!\u0019jE\u0007c\u0010W{R{6z\tgaA4Fjj-g\u0000\u0015\u001d\u0001%-Qx{\u0017}1n[\nInԲ\u0019\\Nn0ɩ4wθ~\r,4%6vU8\u001cgW.\u0016֩!\u001en7̽\u001aOaY\u0011cG\u000b\u0000jr\u0001\t\u000f@<w{'1ǴrÂju]K:`qGoƳl\u0010[S[3\u0010#E?hyxmL5zlt[8w5\bA~\u001d\u0000<h+Cѳ\rE\u00020\f\n*wCXlɧvj<\u0018,\tNUۏ\u0006ڡn\\󏦽\tEUtC3ۦVn\u001bz>ݣ/Oػg\u0000@BC\u0017+ˁ\u0000{y~\n\n\u0013[B\u0000b|\u001fs&i\u0018n[-2Sx1XrԨA`N\u001fWo^ݯ\u001b\u00074V\u000fPj=κWj3vVJJ\u00165m4u\u001fD\u001bҟ\u0001(p\u0002T<Ae$p\u0018\u0016evzU\u0015vj,3Cm{ŢS\u001aZm0#\fGfn\u0007p[t2\u0014Vk%f3мs\u0016Z,MRj(\u0019{%\"\u0001}\u001d\u00190\u000f\u001fܠ]\u0018:Jf.s\u001c\njuYj\u0016=[&oyݞֶ\u001d6kwRa|\u0011;7?NIp\u001bX[48U\u000b\u00004_\u0001m\u0000Gn\r\u0014lK؉8\b.mE/\u001fS:3W\\~r劜)ZωrNI.v\u0014U\bfJokz,\nXJ\u001a.Iꆗ3cՒ)ː\u0007\u0006^Ԯg\u0007u-\u0000m0\u0016j+)m]5;\u000e;sqc-m<GZ{285[z.:Cj\u0007\u0004_M*eX/\u001cхYr,{#\\\u0004\u0011'fn^,Ix\u0003iְte?\u0003\u000f;Z曗uh]9=7\u001dʹy\u001dn4\\\\1Ls\u0017\u001dtYu_\u0007\br\\{;#[R\n\bkAɞW\u001fDe?re\u000ezBBXb=\u001b93@NI]\u0015ػ@Ew\u0016\u001fC\u001dƕSn\f/\u000eΤ( j9SJ0J@Te;Uh6\u0011\u000eK\u0014<;~r\u0019\u000f\u000fpiS~}ĝ\u000b?c[<2ǻUy_7֥F2Yj\fv7nz>vJE*yͤ\u0015>&\u001c-+\"z\u0016\u0004VPЮ\u0006lVSsQ\u001bS Rq\nJvKHi\u0007;fW̠Ӝ1V\fǫi\u0017lߑU`W]T鴸v\tVz%ǲϥq\u0011^{f],1\u0012WُL\u0006Q~bY-=Jv75(ɹ\\g.s3SYwa~\u000b[-Ԇgyޙ0DڥT\u0007'\u001e!u9\u000f\u0018\u000f\u001bc\"L0˯]cZ\u0016IP*,6K!QDHLk2D[\u001b??.t\\Wfk.[\u001e²O\u001f\r9\u000b3os(&d9[K\u0019G8\nz>{.j\nV\\zLgyP\u0007w&e!S-wV&A7LWMx\u000fN|!'{*n<G7l\u001c5-t\u0006s]K5>qNx[8`:mT&r]\u0016\u0010_\tf*9tVl\u0016^v\u00197\u0005\u0019\u001c.\u0017ۻ\u000b6$WB\u001ei`UdשZ|S\u0006u~\u0004T\u00069\u0000k$\b[\u0005u\u0006xg\u0013\u0002\u0001\u000b\u0000\u0011`-\u0004'\u0005\u0000YTTb]JBj\u0012\\q\u00102b9>\u000fDn<\u0004E[\u0003??.\u0000ܔ(\t0\u0003E{\u0019\u0014e\u0001\u0002{{\u0002|\u0000WD\t\u001a=h<8y5z\u0000~k\u0011K\u001cB%\u001e/ 'Rո\u0013\u0016k\u0010F;;K3\u001e\u0017>9\u0019::\u000bp}\u001f\u0000\u0001^O\f]MQ\u0018\u0003|n\u0001=\u0000F\u0000ihې|\bmkog\rŤ|&ѻi<v|\u0015\u000e\u0011!ݲ\u001a]\r#FWP9vMށ%\u0016kN\u0011Q\u0019\u0015NSXD\n0<\n\u0000!\u0019jԠ\u0012j*/\u001aH6\u0000؁L\u0012 )$nYsX\\.\u001c+x3b.\\\u001549\u001cm=\u001b[S<\u001c\u0017@lաR?\u0007\u001c\u0006E1,\u0003xC\u0002Blu\u0000qH\u001d\u0000\u000f<[\u0016\u00066\u0015Mj\u000fp\u000e%\u0005\u0006SĹؙٙ\n\u0003\n\u0007\u0018L5_\u001f=1[0\u0013kS$Um/ώ6?3\u0000\u001emt\u0000?h@Br\u000b&\r\u001ee@Q\u0013Fc@H\u0007V\u001f\t%>щhPr[~*\u001e\u001cω>^[\rכ>B<EZu* α\u001e\u001fr\u0000x2\n|X\u00170-{|DY@\u000b\u001c {6 \u0014\u0010z*.Ⳇ#?s&^ۢ*=;\u0015\u0018GgԚ\\\f\u001fM:~\rȎz:E\u000bafoC!d_\u0013{\u0019\u0005-\u0007@S\u000ba\rk?\u0002b\u0017#9\u0004T9\u0003]B!\u0002I\u0017Ss\u0001mc3f8\u0015\u0015/.*{ŧիszD#\u001dp\u001d tnXk9Dq,h,\u000fbaFWtk^1B\u0000\u0004\u000b5Gi\u001fY\b(Ri\u0001\u0005\u001c\u0011^\u0001U,te\u0019\u0005\u0012y߬RG\u001d<\b=Ivxe$O.և֛n7\\\u000frg\u0000BuaO\rlT\u0000\u0004({2\u0002 ]\b@\t\u0018\u0001_9nbCMRORK\u000fѡ{MyM+1\u0017zc|ls\u000e޷ΠZƸg|ΰ1\u00166Z\b\fh\u001b\u00032\\Aک0\u0001_bE_Oz{\ny|_ol׹\u001b\u000b\u0015HNҵؘkgk2\u001a{K \u001eqleRaQTk><84\u000e\u0010㛼\u0004*~#\u001f[\u000406]u󨏯P4p5)\u0019`$CN7>Y쾿\u0014>7g`ؘJl*p[\u0000b\u001a`3},UY)\u001e\u0000\u000e\n\u0014\u0013\u0014s\u00075\u0012+ː,~ }\u000f)H$UFsjpZjo/_0g{6ǭ@V\u0014K2z~&J\u0002 ^D\u0013\u0001>=\u0001T9Xo:%@ƥhZ\u001ckϴ\u0019`gk}Gծ׷\u001dWŢUS\u0019l#Q>\u0011g\u0014PbT+{)\u0013e~w4}at\u00038q\u0001\u0011&\u001c/ /說x\u001cz~\u0007y~hv6N;\brESh*Qmf\u000ek55z4ℴe{23Yx_ѱ#r'Y\u0012L\u0003qfHV\u0007\u001fKt\u0003r}i \u0017, \u0000\fFi?v}]]\nGwxCg\u0010ENx,\u0016k\u0014(0\u001e{^k7{N{Gk\u0019\u0005~׍F\u00007&&\u0002)\u000f\u0007f$\f\u00070,\"nX$v\f@PsW,)ŀ>\u0004g65\t\u0018$\u001d߈bpY\t8x=_1\u001bDb'\u0011Mg[h[Sf7rw7A;\\w\u0004\u000fK?E|ߊUeo\u0001\f\u000eo2\u001evv!\u00029.VI-\u0000ߜtٱ\tm\u0006k<1^\u001d\u001ed_fF\u0006s\u001bV\u0003U'#mR%ŨqW98c5\u0011kTV\u000f\u000b\u0000Oކ;\u0000j A%.3XW\u0005? mb-l}Mr\u0007m1i]Ɣ\\ޒ-Xu]p\nΕ\\ՎSLh\u000b/w\u0001UnEKUs\u0000ϒhAI\u0012lnf.\u001eB_|AE^\u0017\u001d\u0010)m\u000eQo2TsB\f<=\u0007Ngz\"ߌ;ֲqU31,1?ݖڹ_j{\u0010g\u0000Rm\u00014wy|3Z(j~N\u0012ٝ[Y>8|\u0007))/\u001a\u0011-<w#微wuv`f0jTWwe\u0003D =)n\u0016G\u000eKZYL\u000bz9\u0013\u000bp@\u00009\u001f\u0001|@~}+M?۷`^kp\u00072ِZ\u0013(R[8@\u001cT\u001e9EE\u0007i\tvfBѯ[ﾃLMEa;U5͹5,1g@\nP\u0003\u0006L.xRڈz\"te\u0011!I)h\u0006ҳ%W\fBl8\n\u0001)\u0016nrSxV\u001bcW\u000e=6#\u001by6\u001eĺRqq\u0001Hw\u0001ԡpn1\u0003E7\u0015OI7S\u001fJA?-1wvx\u0007\u001a2%赌wS\u0000&<\nG=5|\u0004͊\u0011uWʣ}(\u0006C\u000eٺ\n\t?|Ϸ6&\u0001\u0012:ϋg#p\u000e[OJ+mr|ٯOe6M/\u001av\u001b;dEhRΨ\u0007_(Ye\u0007r!~U\u0003T̴_\u0003WbrXtX\u0016gYG\u0015g\u0000J.W<~T<L={\u0005K6ΜօDe\u0016`\u0015(3ܜon,=:%'RJZ\u001fkB)bI8tQy9\u0005'\u001f;m'\"衠2vGX\u0007\u0011evS\u0013\u0017\u001e\u0019I玫}J;͢\u0016=_Ɒ_;fnJMsʸ_ezӣ<)?׏\u001fDK﯑)\u0014J1v\u001aiiթVD\u0004\u0014\u0014+\u001e\f\u0003Ckv\f7F^oRQxuߟ\n\u0007uH.sz`\u0015ίECzX\u0011Fު\u000fTx+0.\u000e[\u0006M/\u0015r\u001eGR-\u0004O\u0012<\nv\u001e`J\u0015\u0002~B^\u0012RZz֟qgcjMk9O6\u001e\u0010_>3SrפnwN\t΃k>\u0017l{p}\u0004C>*l>U\u00162U;\u0006_Ʈ\u0007؄U3U>f\u001e9S8^-uf8tSlq\u000bI\u001d\u0017KK\u000b/\u0002:UԔ'fe)s,p\u000f0QeߢVV,`e$S55l?c)8֛)|V }@Vԟ\u0001J'e,ZxT0s\u0002g}EczPLVxNPp.GTe]~mLY]\u001btLiW\n\u0007ayg6\u001d悽ʙE.gja\u000e o94G\u000f#E\u00197\u0019^ynM%\u0018Oyxդa\u0001gةLŠ, \t*nY\u0015kW /kb'N)dz\u0004WjL|g@&\u0001 m~A~\u001d~Z\b0.\u0007.XV4X<O9IAp*^\r(3$2f.R1*YW\u0018[/\u000b֣z\u001dIkЦ^G\t`Dь\u001bB)=|7@~0gY!?\u0003`9\u001e\u001f:7\u0007\u0000ys{.\fЊ\u00000f5go\u00077.\u0006rH\u0001\u0001J:@^\u0018 \u0017q\t\u0000d\u0001҇s-\t>\u0000\u00118@\u0006\u000b\u00106ۂ\u0010M\u0013bgǨ\t#\u00078ˋVXg(@!@\u0002^\u000e\u0000,z=\u0019Ҥ5b\u0016<\re\u001dE\u000bvB\r\u0012\f,@Z\u001c\r\u0001\"\u0015ж?MZk{\u001d9fNhny\u001c\u001c.O\u0002\u0013(z]\u0000-\u000b#\u0004\u0005yQxO\u00006+\u0000>-@׸\u00061n@Wn\n];fߵp\u000bs.B\f\u0010M\u0018Bq;n^C:\u000fc\u0011f廀7\u0017*3-\u0000ذXDT\u0000=\u001e\f\u0001pU\u0000^)N\u0001i\u0001vYmX\u0004X\u0011Q\u0000\u001a\u0007ж\u0006Z}\u0000Ee\u001f@k\u0004[2\u0005]\u0007\u0015zS\u0001\u0012| Q>,l\u001fSZ\u0019=B}ra\u000f-t~\u000bu\u0010Yo\u0004Жc\u0003,a\u0004\n25lW(|ֈEi\u0016`|\u0003`\u001d\n\u0007\u000em7@sy\u001c\u0006,h\u0003ǌ\u0004d;:υ\u001fa/\u000eX\t\u001cxru@\u001f\u0001Ӆ\u0002E\u0007\u0002`\u0002\u0006DQ\u0000!\f\u0000r|\tM\rt\u0006\u0015^\u0000Pȷ^\u0014.\u0007ꠚ\u001c\u001b5`\u0014yO?\u000eaG>}cfY\u001cJm`8\u000f-\u0000f5B\u0015'}_y[b?\u0001\u0011g7\u0007 \u001a\n{\f\u0002xv\u000e|\u00070~9M\u0011\u0011;!$lz0b۷C1;+S<\u0001汹\u0015{n-^ݕ\\T-\u0000\u0005\u0006l/X:\rf\u0005\u0011r\u0014\f[\u0007\u00031{\u00012'\u0001|F?s(:99\u0016\u0007 DW\u00102\u0006x)R1'\u001e{bw6\u001ef-  ѷV؈\t#qS\u000f\u000b\u0000ߡs\u0001! \r\u0018E?r\u0006J;8!-g\u0000 98\u0005$@\u0004\u000e Ji|nm1mEҖ>zA\u001e3\u000b\u0013WÏ\u0005zg9m={Og:M>:\tK\\s\u0005>I\u000f`\u001b\u0002xi\fo|H%%Ms\b\u001bA\u001f@-\u0002T(U:Q\to\r&|,^A`\r;_\u0001ih?gׂYDi\u00165>nw}\f\u000f<d\u000e[)V.\u0016\u0000'>PDCQs\u0005d\u0004\u0014fm/&3gA\u0006̈́Y)\u0006F\u0017\u001a\u0013w]o{Sp\t)\\\"'رUT6\u00171讶daQmEBN1-\u0003?\u001cQ(`yW\u0005(A\u0003Ull\u0002%\n#Son1n׽w碑)!]%,O9\u0012l8ڜe|aJ\r+VYK\u001aG\"\n\u0005e\u0007T2b@3\u001b2\u0004&5\u0019kΛ#;81p*MU}cۏ\u001apc*O327psXm06ξ|\u0017,\u001ba+ukf|)՗\u001b73\u000e[\u0000\\g~\u0014!@ތ\u0007t\u0002D\u001a=Lr:l{ąsLEjcutm#?UsBlo],\u0018[z$\u000f\u0012OKyܤmvH\u0017y[\n4\u001f:vY\u0019ڗK<\u0000J&~\u00067\u001dj%>Q^szk\r\"\n,Xp(\b\u0007zj\u001ai-\u00061|^c'6,w{\\\u0011)4Y\u0016W*\u001f\u0018=,4\u0014\f-&\u000b\u0001Io+D/'?H<\"gQ'_\u0001r|B1/9efʲ7yxզ\u0014hV-Ƙs\u0006\f\u0007T8\u0019`?\u0007%8\bǱC\u0013\u0010\u00036\u000f\u0019`\u001f\u001a9F<(:8y%jvw:\u0015_%\u0007.&zY(UfPaڈ\np\u00107ghn\u0013'<\u0001m=QiS=\" \f\\\u001b-\u0017>}\u0001E\u0011\ru\u000b\u000f:\bgsu{uֵckQ\u001dEX\u0014,ǅIsbG3\u0012\u0007wNl11.ǎ>Mu\u001bo6Bn<nE\u000eXD\u000b)\r\u0000\u0017߬\u000bh8\u0013{\u001f\u001e\b\u0016y%$-7/<\u001b,5H gf\u0016VQ\u001e\u0017\nnU{rǗͲlwKP絭\u0016ؕKVdVd=?\u000e|b\u001dNc?HGK\u0002:\u00044a[&hI\tiW2ˡ!E\u0017'\u0013\fyn\\-y[B\b\u0017Aű1_L]+]_f,Bt\u0011kÍBs\"98d\u000bX,\u0012+ȍ<fe\u0018\u00139zQ\u0018(^mb]ķYpƧ=f޺D%t\\/Ջǻvc+\u0016?H\u0003YMaQ)uDs\u0016wV롭5ji{\u0000\u0002ҍo\u000ee\t3W?;r\rA\u000eJ٢W\\\u000e\u001f}\u001b{\u0013\u000f͑zk\nz<7[3ɫJ\u0014i]b.iX*h:hL$LMy<\u0002M˪+\u00048#@aK?=<.@|+l=?\u001e\u000e\u0019,믮fw!hÈ\u001dN\u000fB\fVy}wk\\eԆUv^]\u0017U\u001e>c,7Z\u0015k\u0005GiQGCV6\u001f\u0000a\u0002y[\u0007̽vn;\u0003Y:MYvq\u0011QcjqY\u000ecom[+7_SJ'ֈZP+re7%~7v\u0016 nb\\\u000bң>e^as(!\u0005 B\u001f^CϱSfG\u0012L7Jb\u00074X,\u00121ӮEw(\u0015=nv(\u0007M4wr:vC\\r\bB_\u0015Yn&4 (F\u0010>rI1/U_[R/ \r@C\u000evm;nѴXrM\t\"h2\u001d65l؞(⬵V+UG2ҧ\u000fR\u001c*\u001b$\rޙ<,Df\u0001\u000ey)cqweYȈeF\u0017\u0011\u0000T_b\u001d\u0019=F\u001bW\f*\u000baƷ:&>6=\u001adh1M(?GFonI˩\u0019\bi?q^Y`TBS\u0013\u0007{ZoF\"Gi\n.>\"/-;YUr)X\u0014(iv\u001e֙bǣ겅&tIK̓K\rFv\u0015\u001dR?n+hik\u0006Lr|yV|ȥd-\u000fKrsb?\u0001Sbץa9ZR\n\u0018R߀_8!(\u0005[]\\R\u001eIn.\u000e\u0017\u0006w\r:ߞ~CEDR\u0007Za\u001f<[w^R~Mpz&-a\u0006DO^]\u0017Yx(uw\u001bqL\u0011}n\u001a\u0005]h\nĻaU\u0016ј\u0016w\u001c_-\u000e\u0015^]uXn.^Ga\f3X\u0011S0N\u001bS\t\ns\u001e,T^+&;=f\"\u000f9\u0014\u001c\u0004|md\u001c+\u0013K2\u0015X%U}+\u0010yП+b\u000bs6hJ=3d\u001a}\u0018_-6UiL\u001dL^K\t\u0006A\u0003Y\u0014\u0004t\u0005=7\u001f eܰ,\u0017)aŹ,v^Q_LWZ\u0013ϙjHOY\u0019\u001e%0쒴ͩOe\u0006%JE|^?}>EtBف|\tҝ-[n\\fފP\u000fvHe8Y\u0006\u0019ǳL.6\u000bM@<\u000bMN0=|+eo\nU4fǊ\u000fX@f\u000fv\u000esW\t.=H\u000e;_;Cxt7kK\u0007O\u0011t:\u001fW\u0003k\u001c_k\"f?u\\l2wx\u0014S͕2,]ņ8%P*IڽzX\"yT*xEYUh\u001dGh.믑\u0010@\"\b\u001fC\n$-\u0000r\u0001Rj ;=AEN\u0001R\u0000\u0013x\"@N\u0019\r 4\u0003\bi\u0011\u0013\r\b\u00120Y[*9~h4AL- \u0014!Km\u0002͔eEy\u0001\td*l\u000bY/B5`e\u001b\tp&=O\u000f\u001dgl\u0001\u0000%\u001c\u0016)\u00029^\u0013\u0000\u0004e(hVX.d=\u001el\u0002ٚB7w4\b\u0015\u001aбi|\u001d\u0007Ij\u000e+}ɶ\u0016q_-\u0000\u0002nP}\u0000\u001a6;p\u0000ߌ\":L*\u0000ե\u000e@ɡ\r\ni\u0003\u0010\u0002k\u0003\tv\u0002Y'g ;\u0012\u0010+Tb\u000f\u0010@rU\u001d\u001cbE0|eaZ!ͺ[\u0000\u0014(aQfh؟CG\u0005\u00004\u0000\r:]%@KO\u001f O:\r]\f@ԩ'3gXI\fAr&\u0004\u0015\u0006\u0006.ل\u000e3wz |kH78\bjjŷ\n\u0000.\u0001\u0014]\u0000ޘ\u0017\u0000_\u001d\u0001`\u000704\\\u0003H\u0000\u001b{n6zO\u0003 \u0002n\u0001P\u0002\u0004. \u000b\u001e(C\u000e\u0007Y!k-@~f?Gu\u0012$|#}a\t]\u0016ǽ[@\u0014\f6@\tl}x\u0006x\u0001}_\f\u0010`\u0016`x\u0007(1\f:ږ\u0001J_Ұ\"f\u0005@\u0011*+\u0014z\u0001\u0006A &\u0004٫g?fa\u001d|B\u0015k\bo\u0000h\u000b\u001f\u00168J+S8\u000f)\u0005°\u0000<\u0013`3\u0001B\u00015v^*\u0006%\u001c\u0011.'@lzY*Q~y?m\u001e֥ۼztܫG\u000ewa*\u0005@\u0005)xd\u0019\u0003$-#\u001e\u0000}whB怐RT\u0002*B\u0001,X\u0014;wG1}K/~\u0002\u001e\t^E\u001fϸS/~\u0007\t3ŧue]׬[;s\nqeY-\u0000/\u0000-:J/x\r\b}\u0007dV\u0000\u0012\u0001\u0010q2\u0001?\tȯ)O㻏ه\u0018g\u0015G!̜\u0003D?I\u0004;by%\u001aַ_/I\u001f\u0012s7\u0000ЄutaQ\u0012\u00138[>o\u0000q?\u0001ӟv\u0000E׀|\u00040&I{<\u0014׋\u000e\u0017\"}\u0011\u001c\u0018\u001ca|=hn\u001f=EXt;RX|l}aP!}VkT+Y\u0018}\u000e\rK-`eP\u0005_yF%\u0015\u0001\u0005e.n6.\u001efg\\\u0000Fσ`\u0001}\nWV3S<27F\u0003\u001d08[\u001fry_US\" \u001aY8,-|~\u0016|jV`\u001d:o\u0001l\u0005m\u0000,X\u0001^)fm߭\u00078(}VD\u001d8&o뭓~Q(NF̳;jW:]Y\u0017GcMLwvY޷\n\u00197J\u001d|\u0016R\u0005=\u001a$\u000b?\u0003*Mu\u001d(\u001a\f-@VF.._\u001bW\u001e\"us{J\u0013\u001e.^n\u000fWK\u0014\u001f-C\bW/scSvgoμh22Ԥ^Ow1ZXgGڨ-`QPӻ|]mK7\u001e\u00163(]cyiO\u001dm߬\"\u0003%a(\u001dNޛZ\u0003m{Jq\u001c\u0002~v\u001akXΞ|N<T\u0002\u0018Ì\u001cFHGSȘ\u001e^x[\u0000ڇ\u0015̚\fo'@#7QA9RrG9-e2\u000fW\u000fa)Pӎ׃M:0_K\u0017?~\u0016%K\u00195Ks\t㝼oAŤ%lWId\u0010\u001c@f`j\u0014D\u001a\u001f\u000f\r8\u0017dDږ\u000b'_W\u0010=~E5O*F\u000fjv:Fg.K/afSd{\fFy\u001b\u000f<\u0012Hmp˖\u0007'M_ӽjzQ|C޽\u0004_EԢ݄s.\u0015T;P\t\r|̷۱vC5e^]\u00042ݪ+t4֨y4N\b6B+\u0005\u0003Q+P+#.TXN F-}\f-\r9&\u0010\u0001L\u0003\u0015]$zť\u0012\u001ez\rW<yh\u0004nk6\u001cDͶ\u000f}?^\u0006'k}c\u001d\u000b\u001e&c\"\u001eEStZ\u000fvA\\\u001d&V/J:]*g\u001fA>\u0007\u0000vEk@sf]s\\>7\u0006ޗzrI\u001cJNf|oy~9ڨ쌏]3\u000bӾ?V\u001fO\u0013?H\u0017^X\u000b\rendstream\rendobj\r53 0 obj\r<</Length 65536>>stream\r\n:#ڲ*\u001aH\u001fX~֏I2Q~\u000fw: ԩ\t~\u000b&o>_|\fɷ&g}q7wrZL4.ޚ:\u0003N.z)w\u0014t_IF+\n|\u0014^MSm77gZݪ,\u001a\u000fҺ#FA\r\u0000݃\u0018Pspӳel︔G\u000fݴz\u001e3\u000fb\u0000\u0006ZX\u000eggKGqE9Ѳ<Pߙ\u001c,\u000b\u0015etVs7<PS|&\u00185yl?\u0007u\u0000p\u0001)ѺwΤźu,j3W\u0003o6m܂۱\u0014!J:冃H'=E\u001do&Eg\u0015mb\u0018R0v\u000e&z7ZkqS?T[Ÿ'\u000b؇.liB&zśv\u000f\u0017oGs̔vK\u000f/^)6>ʸ׼))n\u0019bإ򲥏ݚ^UFլ|C -iOҤf|ԩ:\u0015Տc[;f\u00005^z-E\r\n\"D\u001cp\u0006Q\u0004A\u0010\u0014\u0011\u0015\u0011\u0007\u0010GD%O{U<]*\u001c\"2#L!P=iW!\u001dEǝ\u0015EEv'98x\r3\u001f\u001ek`5^umۧbvʑJv)j:\u001b*x\rF#NuW=p}npW\u0013k2d݌\u0017owDF\u001d\u00109KxSi.\u0002?2m\u0015׫1_,wǌvZ{9ہ7yMP'YkD<ý:ޒ[sE\u000eϺ8u2ݥ҈phǹyk4n;k%j\u001b͚9fُ+Zʨ;b[˸iVD\u0017{LF>FL\\t慗oQ\u0011iFi\u0003XWNʹh])J説C6{ΓLo\u0001\nl֣X嘆;:\u000e\u001bE[ƊٍMU\u0017ܸ,m^\u001e\r\u0013\u0004`4Ϊ\u0017$Qt/ev\b,\u00079+?DN\"<\u001cj\u0013)L{ο\u000f\u001fC\u000eS]\t_VquzB5\\= \u0013aL30+ݛUjrSX+?;hE~ߝc\u000buz;9{f\u0016K1b\n\\d@AV\u00177]6-Ƭ\u001d\u0011<Vm\b=u\nf#\u0017AT^\u0011t\u0003\u000bU\u0006ql8bߛIG2Ye!m\u000e\tjF[p(kxnAXG8\u0016~)I+Fp끹ɲ\u0006c\u0015\u0019\u00045\u0006붫\u001c}o|W+QL\u0002T\b\u0016CuaAQY-߰^xbnv\tZ0j?MW{w#(BwԒ\u0002Uң۪\u0003\\J]K%sqmm?DՑZ\n)\"]O2~\u000fV\u000bzCjӆ`\u0017t랋t17G9vv\u0010KbnP-^\u0007\u001f-7n/g߽dٓ\u00132K-~-7E]<ʰG+l2\u0014N.Wxꖱc+awv!,t\u0011y\n<uz8=jr5\u0013\u0014j9\u001cJd+%rڛ\t\u000f\u0007ol<j<5bIl-<4E|\u000e8XG\b=LQʬ'X\bCp-l\u000b\u001ft5Ǥ\t6e_\f_rRm\u00191%3HO3O\u0019⸛6>#n\u001fo/sc{(R\u0006wNxϩw\u0004c1˟=w(\u00078ށ.c.KQkG7J,+\u000fT\u001b\u0005\n\u0016E4*i9\u001a\u001a^:\"\u0014v}<H\u0012\u000b\u00012\u001712s\tY\u0006,\u000f08տ\u0003~\u0018\u0001#\u0010\r+\t4S\u0007ot\u00016:N\u0001Ƥ|;p\u0007\u0005\u0001+W\u0003Y\u0012\u0000]h\u0000\r:\u0000/N\nVw\u0016\u0000r\u0000+#\u0017g\u0006WhJ\u0000P\u001c\u0003ܩ\u0000ywOI\n\rZgx\u001f#\u0017`\u0001`=|B\u0003\u0010}\tJ\u000e\u0007\u0000M\u001aK^\u000eW(\u0000t?BLB\u0004LEPxǹ?!\u0000aH\u0017;2\u0007\b,3׀E\u000f@L\u0016\u001b\tή\u000frj\u0001y\u0004\u0006P%\r\u001eX[h\u0002uo[\u0002Xz\u001c#[g\u0000q|5V\u00016-/ue\u001fJ|g\u0006k:\u0016Z7\u0000<fz\t\\O:޿'4o\u001e|I=\u00011\u0010\u0003\u0001\u0010\u0004f\u0002|[_\u0003\\1/\u0000\u001f#\u0018\u001c{\u0006C_\bu6\u001e,L\u00021@<k\u000fx3V\u001al4MJїN%\u0006@/\u0016ԀE\u0000۰Ao*\u0007EBR\u0012 V\u0011 ڣ+\tsb\u0001>\u0017\u0000\u0014pHZ(lKu\u0001\u00001o\u0003$_l@\f]lVռ5tGD7\\h\u001d\u000f!a\u0017P\u0002uW<q\u0000R`\nRZ\u0000H:sl\u0006R;\u0005Vua\u000b2\u0000\u0010a\u0005~\u0013Y\u0001Dj+|\u001a%hk\t\u000b޼<tWd_{\r͙SH;ՃMNBʒ\u0012\u0001\u0010N\u001dv\u0000|*Hm\u0003@{>y\u001e\u0001\u0019I@v\u001dY\u0007d=\u0003k\bR\u0016\u0000\t$DI_jl=C\"?{;=̝\u001dߘ1}mO\u0013&݅Yz\r&|M@\u0003 V\u0003b%T\u0000\tL@ޕ%H+H\u00175\u000fB\u0000䣱\u0000=\n~tpsEk4\u000b\u001bz=\u0012\u0017\u001e\u000fk\fwqs,3HS\u0011e \u0000F\u0002\u000e\u0004\n^Ez]@\u001e!H\u000f}\u000fA\u0006\u000e\n*͇h\u001f7b'zvnO\u0014\u001bJW>p\u0017j\u0003f8\u0015:t(;%Ua-E^,Ol.klPo\u0000|\u001fק\bP$\u00053x+\u00072*'_^p3rt)xTS\u000bg1\u0017K\u001fe/n\u0011m0z7w*f\nAq<9R?\u000b\u0011l:@`Z\\\u001d^\u0001\u0010U\u0013ZN\r ed\u0003k0\u0012\u0005\u000f\t64i\u0017D9j\u000b:\u001dvC\u0004Ixc'$˄įJޕ7Q֌\u001c8sx^+$5o#s]PmM&q\u001b\u001e溁B\\\u001b\u0006;\u0001\u0005F+\u0005܃=V+Q}! 9Y*78NeziߜC2ǚUCXSK/.fwnwKWi)\u0013\u0013d;B'q=n9\u0018_њ<?~d*YIZ]Y\u001c\u000e \f&~`:{ZЬ\"k\u001dZ7KW`k<\"\u001b+UoKaԺ,\u0002m\u000fqòCM\u0007'X#q\u001aM^:~9dB0\"R#cC/ݿ~\u0003H'(Ta^}ؕ9Ȧ$N4sS#<ܤr\n\u0014moM{lK\u001foTfl\u001b\u0005vv<mkNyv,dh-\u0011qM\u001d,\nUo>\u0002\u000fΟmp\u001e\u0000Ry%\u0019d@\u0015\u0001he\u0006.֧I)%iu+ܷM>>\u0015\"hOfb69v<0u͊\tr\u0005h0x[2\u000b&\u00199(/\u0001'\u0018ͨmf\u0017\u0000)\u0003xPf\u001e'y=3<O}z<W8>`s\u001bƔղ;l/(qgf:1[Fm\u0018vD*PNf1 FWrmd\u001azKrKn7\u001bLN?\u0004,o\u0010\tx3RY1\u000b|}21p\u0017~9^TyK2͙(O޷\bF|cbO{ZS\u001fT\u001es9zHbtNMyq\u0003sI\u000b \"r\rP|/ɾF 9I<;W_Cvgr^\u0013\u0017[\u0011ܱ0GWv:~\u0010ͳ8\r+>Gf\u0019︆]#ޛ_zTZ:/clځR_Mz'pf\u0010&7@cZІr*\t}):?pB\u0016M?7.ۚ}q\u001aJ`\reʵNӪ\r.!?od[f?sӨh'\u0016\u000bm{\u0016\u001cN]ywn\u000eGwttй)m8vQ9{\u0007&oS\u0003hb\u000bP\r\nkE!\u0010-1ئ\u0007\u001d?'L]O<>.U,g.O8U\u0010\u0013n\u001d\u001e`ZRF5S\u000fh,M)z\\RR^=Yivc;}'Δrlj\b:֧}\rԇp\u000b.1ႍ6A\"d\u000fK%sc>L\u001dؘCFfbzhDv(Zb\u0012\u001bw&`!\u0013Wq,n\u0003)\u0010\"]lE:7\u001a?l(5;D Ӵ\u001b@ a\u001e> ێVfBsɛFSM\u001f^\u0001SJ\u001e+\u0018:SI9꯶Z5S>h\u0005614B,_[hEgkkEȬ_Ga\u0017\u0007Q\u0002?m\u001f\u001bA\nSDUk\u0001iۤɬ?ڱ\u0017 D|\u000e{q+^\u0018`z\u001d,iQUsKN>\u0002J\tF=Q-,m!wp<~H\u0019\u0018ߠ\u001a\u000f^5\u001ey\u000b?Vr>z[\u001b[2\u001d];ݩ\u000f5\u0005T[C\nfdliɨ@j\u001bg:)\u0005\u001d;{J\u0000(_[9Zb6\u0006nW\tox\u0006\u0003[\u0004Z%˵2\u0010\u0013s3tk'S#>az\b\u0000Xe*[3Cް7'UlP\"¢Uh7a,\u0002K\u0006u\u000f˪P8lBʹh]\u0012%*\u001b9Rfý0)\u001c뒫})SފR;۹tuR=՗\u0017P_\u0010\u0011~Y\u000e\"*[k˯$\u000bfr71T75dZXJ\u0003inC5F0{G'i3\u001faB\t\u000fsD0\u0006\t?D\u0003YKFU\u0006l&I\u0018\u0019,k'ՊCp\u001d!޳p.}>\u0002煠9MF1\u001f\u000fd\u001dBpT;Fkme>:moKj\fh&\nJ6Wf*'6aaʠSYu}\\Ap]Z\u001fjeCJR9\u0018j~\u00038C\u0013i޾zuG\u0013Qt\u001b\u0013\u0007U~$lŧ͕#\u001f7{Iޖj\u001dq\u0018UIɭ4<i2R\u0019-a2rKlr*屴\\C)ՒY\u000e6u\t\u0018wi֍fSHM>p 3cV=K*ͅy7\u001a)|?kɂ-p\u001dSZZ?xU34W.C+I[+mHm\u000f^\u000bytfG9B@d7,\u00016}Xx?=:W ʫz{\u0018j\u0007aT(aضpjʳ\u0011*1[cQI#\ti\u0019;WM\u0017ap.䀙Et=ar^rL6g\u001f#\fVp&g23$\u00113pGzMȱ7m9wӃ?)p\u0013sמ5!\u001e\u0018uL.XmQdcK~$\u0017բZ%Ӆϩ{5Ǥ7&Ȉ<RأeZL޲L\u0019)\u0004̐\u0016~\u000f1>\u0019\u001bԵGEQiHV \u001eKɷ/z6lW\u001d;?{\\\u000bHE;}n\u001e}*xgl\u0019\u0005\nILBjQ!R\u0012kxM%9/~ÇzW<\u0016-l<\u0010o\u0018ZGS)\u001e*(D\u0019J\u0015O.[T\t\r\u0003i~ز\u001c\u0012f[RAJ5gE\u0016%k> )\u000fU9=\u0011\\#<A\\\u001b\bϪ\u0006ױ5\u001d\u0010\bR\u0010Z7\u0000Lh\u0006J\u0005\u001f\u000ef\u0002\u0018\u0000,S\u0003q\u0000:\u0001*O\u0016:Y$\u0006@\u0006\u0000/O7E#@\u0016\u0007@FC\f\"\u0003d܄Wo}LX\u0017b8\u001d\u000f!@V#@\u0015U\u0010}2\r\u000037\u001bi\u0015q\u000b\b\u0001\u0000l\u001d\u00002\u0002\f\u0007\u0000\r+\t@I\u001eJ~\u0000-2=\bg\nP\u0005hp\u0001[zAx)|\"\u0003$z\u0000w\u0016߶\u0001@bU\u0016}\u0001k\"uWB+<ſ\u0001`\u0000\u000fe7(3\u0005:*Mi\u00063$XB\u0000V\u0016\u0001U\u0000=\u000eMz\u0005@\u0014l@\u001b\u001f\u0007\u0005PP\u0018\t\u0000Ui\u000bbj\u000b|uAX:\u0011F\u000f\u0011\u0007o\u0000օwV\u0016U(\u0000o\u0000]X;\u00007yp)+5-t\u0019`Z0\u0002\u0018!3\u0016\u0003NI\fV\u0002hRB\u000fP!7JMmQ\u0018H\u0018ѯ粈\u0003\u000b(|}\u0012\u0014\u001a\u000fD@d\u000f]@Ԋc\u0006\u0010G\f'C\u0001|3t\u001a˔\u0003\u0007X\u0000\u0016>\u0000[Q\u0014T\u0006mB؝7|L<NOE<B'\\\u0010\\<K\u001b\u0000ږ\u0000ξk@;T\u0006ҳS<\u0012\u001f\u0010\u001f{l}I=z\u0003-\u000f\u0000R\u0016\u0000.B\u0013j\u0001h\u0005ȓE+!X{.\u0019\u0007n\u001eqEߢ߬<\u00159#~?o5\u0007\u001fO\u000f\u0000N\u0000ON4F$\u001a\u0006H>s:K04=\u001fQ2?EmBL+ٶe6\u0017WV\u001ct=N8C<Je)zA=K~_\u0014\u0006w\u0016/ns˿^Wv\\6È:{Fp\u0007*Ѳ\u0015\u0003v\u001b`WJp\u001b?-E\tov\" g@9\fRITUj?f0\u001f\u0017'\u001eۻݟ\"WudZ\tu]W+\u0016zKڔ's\u0019\u0016\u0003;AcEvM)ζy^*pzz\u0000v\fv;5\u0014\u0017 ]Yx ݥo\u0010#՛Ջ\u000f=y\u0016e9y>O묶69d7>'\u001c\rsC|(\\\u0007M\u0002^\u000f{{\u0013)\u0016\u0013ν\u001cv\u001c\u001fo\u000f\u0000\u001eˀN\u00188dPU>\u0001Tq\u0010\n;;*ZL麥pjb\u0018!3QP嵿4\"u\u001fb׎\u001anv87\u000by1X^n x9'\\Ήg7\u000faw.\u001be*\u0018@2\f\u000fDM\\\u001bP\u0006{\u001d9~\u0004=\u001e%ho+\u0007Wm6\u0002s;n2qޜץwo{zz^=\u001e+.Hso~v^C\u0015:W\u0017(<vy7\u0000BΕ\u0005Roփa훵\u001d\u001fwG\u0010^\u000e~%4$B\u0016خ4n+oJ`5ɲU\u0017vyQqjz*%̴8^ʶLT=w\u000bݍUų6vy\u0017?: \nH=: ?2\u001aoNc0ڜ\u001c\u001eЬw\u0000\u0016<^\u0003fޭ%|;\u0014Y.\u0005.\u0012juv3idt\bF(:vs?S0$k3.\u0000f\u0002'S\u0007i\"7(T\u001fY݈p>\u0019Foam\u0012mIs5V./H\f&N/%\u001cn`ݼ3i1:>\u001cF\u0014[ K\u000e5̺c\f\u0018v`27(=q\u001b\u0000R\u0005\f\u0007ۏ\fpk\u0017\u001c7蚫F\f6\u0003Wm,\u0017|\u0011zBvꇘv=\u00196lH\u0013\u001e9cL\u0019\f\u000eQike20\u0012bW\u0018M\u0011ۨu~ַ}{ub\u000f~?\u0005HqS(tsJ\u0015Dms%-h5N#\u001epv8[WKd\u0017/(썸gqb|Y\u001bX\u001d2ֈl:6L\u001aNgz/U\u001e\u001dzzC-S8\u0010O_\u0016/\u00162uu\u0003C\u0015\fe˝et\u0013Jش\u0016p?\u0019u+m+K{\u001d2uV>؀iOvݵb\u001dnā\u00063=@ᭂN6F.8`CtwBKݧ3-u\u0001\u001atH\u0006\u0014j7;^FV\b<I(Cڮj6X`1׃q\u001a=c\u0002\u0014CR\u001e\u0014̳N0|k\u0015ShIK.j\u000f=^̧AI*ruJ͛oۮ\r7|?M\u0000\u0014j:ܳ7\u001a\u000e\u0018 wӱa[ѣȲZap;6Kۂ~:e^Fx\u0014~S\u0012Z\bZzj\u0019\u000f\fByѱvF(O\u000ewTf$O\u001e\u001ce'f\u001dKLO;W\u0003 \f\u0003gm4\u001f\u0002+\u001f\u0015Nn\nrX^[/zgfcղI[FGi^Sxt\u001fAMZ3j7hxM`rg\u0018rǧR-;{\u0005~'=m7h/ҫxvdVٿ\u0001\u0010\u0002m=]jw<fu\u0002K\u0017f<\u0010qoX]0,͒8# uv祤\\s:a\u0015QO-2(2S^zSP\u000b-\\lmk\u0005\u001e\u00069h/hPdNU\t;3\u001aE\u001ep/)͆y6=u.kYV\u001dS\u001e7v>\u001fz:^ ]K),'O\\EB\t\u00147˫*t\u001b\u000f?k~c}\\\u00001-}8r[P\u0005墍\u0003tr{\u0007ѩ^~ŗm33\u001f׷\u0003\u000b䇰8θ7qxm\u0006\u0003nqJkzV/D:\u0014D\ftxS;\u001ay_6lM\u001auF5DjѼq\tNb\u0005bn\u0006@\u0011y \u0019e|Äwl삝dv3EA5ޅۜǖKՒVAgʖNIZWtL/lë{\u001a\r{u9$7՗OZ\u0017ʰEh\u000eפcլY!\u00123a\u001fb{\u001a\fy_8%z>dvZ32>h__ԼFt8>L\b\rD}%G\u0019&d\u00023\r\u000e\u001dpz\u0018\r\u0002ѧT8dxt%фo};\u000f\u001c5R\u001btA\u0014.b]<ݠO\u001e.ď\u0018bg\u0016NZwoiL9;\u0011\f'^*Qg\u000f'6lUͤ\u001dѵĩ\u001dOکfffak6=z.\u001fO\u000f\u000e\fܳwtf[6\u0017ok9\u0019\u0002-\u001fq?(ӂut&ݐhgWDU0oU=ˊE=\u0010\\\u001eiw`\u0019Л\\+E):bQFJ|ҕX\u0017{u.OkRv\"\r;DA\u0003ڋXoV\tàF\u000f4u޶\u0017*8\u001d\u001d\\\\\u001cr]U>4\rSuqʳdˀV7萔\u0010i<*p-\u0019|R؍\u000f߰\u0006)2;;^6Wk\u001c֋5n;{-NhliYC4\"EpjfTa\u0006P)\u0001eT\u001a'./\u001aui-\baqkMX\u001a\u000bPг{tT\u001fʟ\u000fEr ?xe\u0018C<\u00146OgFķQ~;\u0019\u000b~ c)^nl⤾_z\u001e{l\u0013fHxX\u0016yj\u001fY/cG/,]*\u0004!\nd8p\u0010uSH\u0019Q8NSKg*@\u0014J60޷SG J0Ԭ!\u0004\u0011s\f\u001bZm$+ˮz-\u0005..\u0015\u0006\u0014r4J\u0017>h*\u0017ya:tˆ\f_X\tiʣ\u00132\fT?DJTukW\u0018Բ\u0010o\u0018gJ1\u0011}\u000f\u0012KLb3Ϋ\u0001vMe{w\u000f\u001dde\u0017v^|\u0011.scir\u0019mG}5\"*L؅#JOB\u001c=\u0012#d%W\\\u0015c\n:Z!3;N\u0010\u0017\u0010\u0010)\u001f\u001dp^\u0018v,N6E<2UfD\u0016rr!\u0007PWJ>C93.\u001c0zZ\u0002OS?s8C\n}\u00103$V\b_k\u0010\b4\u00061)!<[!.SOPm\nXT~\u0003@\u0004\u0005H\u0000eXϸCR\u0013 ~\u0007 iw|nE\t:3ϤDCX\u001cĵ|<ĖwV\u00100\u0018\u0007%|\u0006:BN>&\nsK/O|Iyu\u0000!z#\u0014}r\u0000]\n\u0000\r$(tg\u0011\u000f.Tlc\r\u000f \u0015 \u0015\u0002\u0007HS%sh\u0001\u0004Ż\u0010\u00051A\\\u0000rg~\u0002d\u0001\u0018M\u001bޞb\u000e\u0010vLV|`\u0017-\u0002\u0003\n\u001dSPI\u0003l\u0001FPh\u0000BuY\u001bt\u0007\u0014\u0000ȥ\u0005`\u0002d!>c\u0003:\u00002J\u0005\u0010\rCm\u0019p_\u0004Ȥd@Lo{~\u0004?Ϸl^?zSt\u000f\u0000:J̨\u0001/\u0000]W\u0000\u0000\u001b\u0012߷`j\u0007\u0001!@C\u0011\u0000^V\u00198\u0007PYT\u00019\u0016D4\u0007hm)\t'\b\t\u0010\u0000-K%V\u000e`\fq_'u&|u\u0007nN\u001f[\u001c\u001e4Wc׋)i\u000fHM!\u000bK\u0003U\u0000^O\u0001.\r\u0014X;\u0000NfV\u0000\u0017(4\u001c6&\u0000[~O\u000ec\u0006\u0018^\u0000Ԏ\u0010;@O\u0007Z\u0006­%R9^\nˎ[?\n\u0010\u0003\u0010}Խ\u0005P]M:+\u001f|?M\u0014(\u0007\u00000[\u0001\u0004m\u0002\u0001cl?[{\b|\n\r\n'\u0001얘fIT۾v\u001d\u0019\bf(G%\u001b/V\\>V\r+W\u0011i\u0017\u0019GC.\u00074$\u001f\u0006\u0019?-d\u0000ήǬ\u0002 Z\r(s}țC,m\t\u0003Bŀ\u0010$]2jσ'\u001bD\\Ｚ3\u0013\u0014=Y\u0011q\u001c͢\u0003u'E\nsB\u000e\u001e\u0015\u0015l\u0003=m7+7~\u0007p6*\u0014W\u001cHC`R\u0003AE\u0006̄!Y^w֣FЕni\u000buuL.ckqIݹNu7>\u0011z\u001c!\u001dVS\u0014L'*7V6v\u001d.\\m\u000e0[ߨbpjp?\u0013>\u001fȼk\bRƉ\u0001dP\u0000ozyңQ.Ow=obm5Tmi\u0007[\f\u0013>\f~+<\u001eT\u0014n\u0006Nh]@YM׷g\u0006m\u0002\rv6\u0019\u0014g\u0003\u0019@tY\"TXl|t6z\u001d^e7I\u0007䨥fW:NR\u0012\u0019\u0011$o2RK=S+u-&|ZPr\u000ej\u001e\u0019x\u0015X\t\u001b\u0019.\\~>O\rx?g\u001f1߷S^\u0000C\b^\u001by6%@oL\u001e#aiEB\u001d\u001f_Fwz\r_->]7&y.x\\x?\u0002zLv`HpVs\u001eg(S98H¹:u.fֶǂoM\u001c\u001cgVYB\u0007pc\n7C\u0003Uf\u0002HrW\nKw\u0010\u0010\u0014f{*[b^H\\m\u0000\u00036L{x\u001d\u0012\u000f7N\u0010\u001e[\u001c5q\u001f\tx<*\n-ֆ,Ru\u0003\u001c&I\u0001ve\u0006\u0003Qe6\u001aJm\u0006WNV)z͐Ϭ{r\\.0~\u0000\bt8\u001d- ؓ;<?0\u00126b/i۝9ܛG<cd}p\u0016]\u000f\u000014 #y\u0019Is\\ʙSe^\u001fZTTwkگ\fs3_2}qkjSKM?5ioƨ\u000fa<\u0019fƤxpzAR1\r{FI\u000fԬf\u0001mh8+\u001a\u000fʜ.\u0000\r\u001fZ!\u001b|~;2E]jv]$ܸƲ\u001c:>D~?m\u0018oazne/Hʠt\u000f\u0011_m*\u0010WoQlsEH&:_\u0000V\u000eM.FL'|-V\u0001琌gOJ'#=̥sw\u0012\u0002$<\u0016'sz/a`(i@sA|0FMڽ$}\u001f,rtS?h t\u0007פICӤ^UѤ6-!\u0010\u000e\u0003jl\u001c\u001bs1\u000e\"y}Kvt<\u0004lZ}VuY_=jT\rk\u0019\u000fai$k\u0016\bc\u0006>8\u0015M͓yk.evN:)UODU/\u001a(DW\r\u001aoE\rJE\u001f@\u001bA>oR\r=2=!!1xk3U\u0019MK9_*s5Xg'\u0019Kuye][`sˠʿ梞\u001bSH\u0019g\u0003\u0002$fpXlyֹb~W)\u001d-ڿ\u0001\u001ctG%aȁ=\u001e7\u0018g!Zz\rm\u001d\u0016D\u000e\u0017l\u001ft;\u0015Ǿ\u000e\u001e\u000b/m.\u0012ݮ̩tf_\\+Q/}9\u0005sA-\u001fR#siWJy_&\"\u000f\u000eh}\u000e4g\u0003\u0002\u000b\u001e{z[u~Z\u000fڗRΔW'1j2\u001f\u0016\u0019\f\u00187^(Q\\\u0005RF,RNQzF{nwۨwI\u0015ׅ\u001aYiԞsB\u001b\u000b\u0002*\u0013O\u0005\u000bt^6ģ\u001fbܬn=Vo}rALV0Z气t\u0007{5\u0012\fM7x6Ch6K?z)/z,+찪\"Pii~ҖbGmA\"\u000b\nEb\t\"$gr^\u0015\u0006+\\kZ\u0017zX\u001c8\u0010sq*54\f3`Whֱkm퍵rS\u000eڝ$0m1\"\"9HS\u0003'Wm59ppPE\r<jG<hr\u0003ؖo\u001c8\u001e<\u0002{p\rq?V*f\u00173=q#>\u001aZ%n6Zln?ZIBf[E\ng\u0005BTVx\u001aq\u0016\u001al7 7M\u0017\u000e7\u001d]d9ڵ\u001bcjD\u0019\u000f%\u000e̽P\b~=.{\u0012@{h7\f+\u0003~\u001f=R+'*pmu\b\u001ae~7\u0015k\u001db\u000fK{vL\\%Oe>c\u001e42Vr\u001ep\\XɈ$vm\u0004by%\n\u0018ˇTb/tn\bm- z\u0006hLzJ5Zj-\u0003\nkj\u0019y~9&\u00115J\u0014ã&дcH5'\u0003\u000en\u000fr3*V@meNn3xe2cvh5FI|\"ւ3l\u001f\"\u0002ؚ6\u001f>+^\u0005[\u001b<-{i2=U\u001fŖ\u0017R\u0004,\b\u00110\n#\u0011vd\r$8a/#\u0006b\u001fl+U\u0005-U3LUsSVn7[԰P\u001dU\u001fR.9\u000f\u0015\u0012{\u0006{uܦr\u0018\u0005-o7x2U/]\u001fB\u001d5Y`Q\u000b<.g/4\u001aRd\u000e'{әOj'K\\Պ\\$Oe\u0014P*O\raQvt\tF\u000fQB8/.\u0002_\u0014?.cѭuoS<\n7\u0007r\u0018L\u001d)͏C8\u0006xLz:n[\u001f֬f0W6mZ\u0014Z|<jT,JG3*ꔛ񮴬<\u001e%樢\n^\u001b\u0017vէ˳\u0002թ&xZM:]7rqq4o69\u001cْg]ֵ\u001a-asY\rz*\u0013ʴP\u00019\"ȪW(g-v{_{L:4]>,?XR󥝫ζ\\zSd\u001ed'2fY\".6/\u0004\\o\\בn4jY,dIXlWRJ(\u000btwQZ]qT(\u001a7.\bg2o\u001etn&jه@ht3M0\u0019SsGaGd!z;\u001drt}r7IA$L*E\u001f؋e`\u0015\u000b&K5\"BWd_QZZ+\u0005gb)\u0005\u0003#p^+r}Ĳ\u0019&w1ARo/҅!L\u0014\b\u0004\u0000\u001f[\u0014\u001d\u0016.-\rq\u0006vv\u0006>|?\u0013/$/\t\u001fEXV=kbKT.:\u000167n\fW{X⌴\\˛!V*#6q\\]5>T=6\u0011uL\f`A\u0001L\u001b|ϭ}\u0014'd\u0010Q\u0011\u0010?0ӧ5's?Q63\u000b{rȪd+c\u0014vpT2}3<6\tCy\u0018Sx+\u0005\u0016$\bIXX\u00109Z߬>Z\u001bi;\u0007ΆP\u0000QA3Ϲ?m_\u0000b\u0003\u0010G\u0000\fq\u0018C\u0002H'K>YCONJO޲2{OލR\u00041B n\u001d\u0016Xe{/yIVݭ?!<2yk\u0014RS_4\u000b/-F?\nP=߼{Dee>̽j01ԤAֳ}B}\u0003\"ē9KCk\u0010s\u0001&KބDU@$o[k\u0017gBS\u0000 r\u0003P\u0001T\u0000L/\u00012(p\u0000))𯼷V\u0002Lg>B\u001c@\u0014D\fo&\u001f\u001b&Ù>18S\b!$L\u00055nKkR{H\u0011\u0004_\u0010۟TC)\u0002 G\u0003<(tqBou\u0000:\u0016*\u0000\u0015\u0016@1L\u0000q{[(+@,* \u000fqb\u0001ʴ!Dx]˱R=\u0000RB\u0002\u0000\u0011Zw\u001cg\tǁ[\u000f\u001e4\u0018ħ4W\u000f\u001f^A\u0007\u0006r\n\u0007R#9fj2\u0012\u0001t\u000e\u0000P\u0000>!\u0001Z\u0001Zz\u00173!>nְuBksTntq<5pe\u001f^\u000bhK\u0011$E]i/w\u0001#\nua\u0010\u001a\u0014R\u0000\u00024\u0007BO\u0001X\u0000'\u0000'o8RCS\u001fͧ&!G#B&3ϫ,.\u0013wm}\u001c_=nͦ޸b^xxV䯁qҤk?,%%k\u0007?:Wc\u0001\u00058`\u0000Ph-\u0003\";i\u0001\u0002\u0000?'\u0000wK\r+g'B{rw\u0006G\u0011FL@\u001bץ̎+6o.^k3X┋\u0007lX7t?Y4\u0016]io-\\\u001d!\u0003\u0010+\u0013\u0005DE\u0001b};6 #^`IӸ*vhhn\"a\n;,,I~qpx\f{1\u000e\u0005Σ\u0001׏}D\rYhm0\u0007Gw*;W\u001cՄ|iu\u0003\u000fE\r\u001a}\u001ccs m弘(7F{'\u0003-r/\u000eӳR6':2wq\u000f?Kޠo+\u001df\tz.\u000fng:\u001c\u0016نƑ7Lu\u0006\u0015(*F*-빸@SlsOsٿ;o\u0001;\u0000\u0002qag^\u0004HV\u0001oz\u0017\u001eÝՊx-\u0014.P蜊dpp84X>Q%zMTҞY\u0015\nQ]`WP\u0010`\u001eҥG[׋֡\u0014ۯ[q jKt?QRU\u001a@'@\u0005{T:QD@\u001a\u0011FQAoPAs}\u001bq#f|Ő&\u00199\u0019-\"lg2$7\u00190]6A\r4AF2nA|wY·a!B\u0016\r\u00177mk}J\u001f޼;NSH\u0017\u001c.\u0004Us\u0011q8bU\u0014rə[\u001b{\u0016#L@\u0000\u0019\fǭ{O'3[/~ݔ7\u0010L6=^K\u0015\r4{\u001d k6H^=4Q6\u0019~elx\u0003/f6pupr<EIc\u0015\u0017cT7|\nk+jnSfT{VeBCxw:i1k݄U6w\u0006lL\u001e}XL5>\u001fq֘_\u000ff_L\u001d\bFib7{\u001f2cd'h6\u0012.zPͯ\u000et1\u001feFWE\u001d`-3_Q\u001a+\u001dipZbTŹVS+\u000bWNGO{Lk^K/$}.r^\n㌐\"xwk\u0004Η $ya/v2;.PnXRf,,xkF{\u0016ـ&ڨ|5BQj\\_[ =wI2|O\"4\u0003\u0017+h7&ָTE\u0002O\u000f`Sʥrޓ2!\u000bDr\\N\n2Cn\u0012ړ\u001a141a|\u001c\u001e5\u0010\u0004Z>ӒgGjURVaRg\u001aR?'\u0004\u001bH#}\u0016IDO\u000b&f:旺\u001cHg#\rp?ba۠YY\u0019?\\\u000e\u000bA/ּ3Mck=5Z@GT+6[ZH1}M$'~P\u0007\u00163n\u000e\u0017`>Gqc6/\u001a_\b_C3\u0012/;\u0004g}-¼bڞ\u0007;>-=sN\u001c\u001b#N-x+\t'Lyx\u0014Sy\bkDN\u0000R\bte\u0019\u001f6[\u0000I>ȓ9iޫq,\"Ajs6ҳT^ìs&᯻yD\u0004հ|ڷ\"d|\u000es|W\u0015x*CSPZ\n1+7'|\u0014\u0019M\t(ҹEpG.zޕ\u0001`GvKiꭴlSq\u0017\u000eͻ˞?qf-s\u001bx-|\nqGw,\f_MR\nb}8\n4ZYrDD($S^\u001d<_lƕ09r>Cv\u001f$X\u001aPsC\u001bPV\u001cP:pacTA^xu]E\u001b6\u001c\u0002l]Y\u000ek;w\u0010bd\u001eO-亰zI]\u001c\u0007j\u0016B:VǇa\u001c\u0015wv\u0005>Z:d2\u000fxDw/#\u0006/7\\gryaR\u00033^aZE\u001c\u001cy\" GBu\r\u0005,\nTϳe\u000foͽ\u0017H\u0014׏ʘE\tzmm<i>d\fǌ5O3$fGg\u0006踟py7;TEJw.\u0015ÈQ\u0007\u0002)\u0013U%'UOod\u0013뮕\u000fCs;Wlg>6\te\u0010][m'likM1XD7qd=J3̨&aRȃN1\u0019\u0016.vwO/{0<\u001fЛ1+GB/%yB֫\u001dkU&V,j\u001f-NؓpZ-(p\u0016:\u001a9jL\u001bMm$\u0003\t.;S.d\u0018Ň~\u001d\u000e+G^'|סa{K{\u0019\u001cOF/J;\u0004M[{!=\u0017W{NR\u0012\u0014-8\u0014~?\\vܡTrX\u0015:\\\"Ξʄ\u001d[ۧ,$±P\u0016RY-gǨ3%+\rk)\u0010.I\u001f<\u0003S֞3m\u0010VioҟVv|\u0015t|>\u0007wFQ\u0019\u001dP\n*usW\u0017Gls->s$p̉r9׹d]q\u000b\u000fFYX\u0017ݡW\f\u000f\u0003\u001c>eS(SE\u0001ERuSӆc&U˪D\u0019\u000b\u0013U\u0011\u0003гh f>\u001e:ٶcZP,kNЮq\u000f\u0017\r9{\u0015(\"kԝi\u001bR?6\u0015\ty6\foLrS\u001f>_K6B\u000fd$_[n.\u0019*\u001b\rS\u0006Vu[yV{hͨ'xZh\u001exaMh\u001a\u0007o'[\u00033=<RiBENF\u001a1;f@SpAˮ0[\u001e[T\u000eq}vBÎC\t h~K\u0017\u001bRyF|\u000e\r\r(KmԗS?g\u0010S6\u0019/VfrrN*4?s\u001d.9Wv*.}\u0004]\u001fSoHa\nǳoide\u0017e{Vۦu\u001b>i,RN}p}\u000fk~j6\u0014]-}!<*?p09*\u000b\u0002W1W>ݝlY\u0011/\u0016E\u0019>έ\u0010g\u0015\u000eG~0\u00176zɠ@>8\n\"Z)\u0013$S濾9m\fwZL\"yw\"\u0016V{^K|E\n4zGJzԘ\u0017_CP\\!ADeȠb@)l\u001a\u001dd\u0003YX?\u001c-ưE(3a5&_<CBxonհ.U\u001aM_B/EZZyίW/sG~5R\u0016&\u0016P\u001fbh!`#=\"q\u0004\u001fKE\u001e>\u0007,G\u0004e\u000e/!謪c1A/o[ÄcT l{jxlSp*2):sH_LizV`jh!)A^YYUˇ\u00043*nNU̧8\u0005ŏp\n9\u0010B\u0014^}+Dc\bQ\u0004Q\u0014\n/Vn9\u00199g5mP)#s I\u0019NpjV,P&G:Zx[He\u001f\u0018>z\u0019\u001a~\rb3\u001eڪ\f8!\nkl\u0000\u0015:-\u0006Q]Y\u001eN3\u0000^#}\u0010k\u0007߿\u0000\u0018H$1V\u0018PVHka\to\u000ed4UEj\u0014_S\u000b\b\b:VKl}{/dҲ\u0004Q-˴\u0006p\u0003H)\u0010fnL\u0001\u001d\u0010h\u000fH> Z;Ж\u0001_W[\u0003\f\u000b}\u0005\u000f_)|ip|4\u0004gq\rp$ǉɴC\t5\u001a\u0000n\r؝⤟\u0001\u0019Y\u0000\u001c\u0019\u0003i\u000b>1@M\u0010'\u001b _*ʿoR\u0018%\u0010\u0012\u0003Y\u0010h\u001cc\u001dhOSCk\u00078\u001c8b`ׅ\u001f'\u0005@k9\u0014'w\u0001 z\u0000c\u0000q1Na\u00028\u00164-v)7_\b<\u0010@g\u0002ɵW\u0002\u00176N\u00144qO~\u000b9߄9ǟQ\u0006P\u0012\u0001?\u001c\\\u0006\u0010͜F\u0002l\u0019\u0017el|\u0014u&^`H\u001b\u000e/?>\u0001_\u001b\u0019%l@|\u0016&Us`\u001b+qz\u0002cTq8tqZaSAqZ֘\u0006i7\u0019i#\u00023ӋtFr\u0019]bֱfA]t\u001f\u0017<Դ\u00181d\u0017\u0001\u0013@ZH2\u001d@/N \u0017\u0012\u0018\t$V\tTp\tTxo13?{}ެ\u0012\r^c?K}vݎNi.{g\t\u0015oVչ&xҹRS\n\u001b\u0000b\u0017//̊/@}\u0010N\u001fv\u0019J\u0003۷\u000b\u0001$ì߃$$3M:ڼṿ\u001e*25YU\u001fmzݣLD޻Fi)m\u001f%y\u0016Un\u001fΕuh^q}[ kq,T\u001c/B'ن\rP|&z&9xI6l@o\r?S:Ө/\u001317\u0018\u001d)lF>i.e^ܱzFir6\u001e\u001eQY:\u0002ig5m\"mx\u0007ɼg>\u00056,)%M\u0010\u0003n$7!$_!O5\u001dޫY\u0010\u0007oI92b>?:xh!m߁:\u000f\u0003:m#A}d&-۰z\u0001\u0012Mh]J)xwW+{:͗N.,Z\u001e]\u000f$;Zr\u00070\u000f\u0016o1B\u0013VP[\u0017|\u001dx\\\"PMA:\u000f+7j,MAn\u0011rf}5\u000b\u0014-Xcx\u0003/澠\u0011zO黒þf?\u000fr/I\u0014EIn\b(;(y]\u0017ݖ5\u0004\u0012z\u0004zl\u000bW\u001c=i}-/\r\u0006y.>JfA\u0005[S-73=\u0007kM\u00143oސ#\u00051\f/g\u00031\u0003\u0002ݗn\t<\u001e=^s5- pJp\t*A&ݒ\\C7r1n\\@zk:Z3F^ٖ\u000e\"8Kb%U\u001b獐ʖ3\"#I>~\u000b-\"<\u0017]_M\t?\u0012ظ&poYГϕ;AϽcf߷ZtțLy\t5ж^]igLyc[*%\u0017F|=N;uFO&b\u000eYZ2\u001blVב\u0003O'zrk\u000fQCT}ɪuQ\u001a*v$UA\u0014}p:'tM\u001bvT^+;6U;x\u0004Wx/\u0006\u0003\u0001[lku'+\t3\u0003{\u000bƫ~\u0011\\͘}\u000e\u0012%bPR˛\u0005a\"_Qv\u0019d_2|$\u0000=Nr*1z{{/\u000efb_\u001d\u001fu[ˏ\u000bx=;\bG8o+amRw5\rjD\u001bA6v\u0011\u0007VWN,_KnQD객\u001e\u0013\\XmŤ3KD7_OX,?ۏWoִl3\u0001yg&\u001eYii\u000b\\_:euTC\rlg+\u001ajsLO2V'RQnʚ,{É5\u001cE@\"mk\u0002\u0013W@\u000fGc\u00156o@F\u0007~$Fȿ~_\\|u03aMklT<rY\u0014\u0016Cw+9egcY54MgCV\n\u0014S\u000fTT\u001d3\f\u0017%^&\u0001E~l~=w3q=wIE\u00019_/o_~?\u000b\u0016MC\u000f\u000elڨךTY+\u0001oM\r0_\u0005#06cg\u001a\u001aZ\u000b5>\u0013\u0018^\u0016V\u000bz<Qc9E|FG[֜\u0019\u001b@HG\f_$1~\u0019^ \u0016\u001a{ĳ2dA-\u001eo]\u000bi?\u0001Y%o6ʖN=~uՁe}%ŅD\u001b\u0001\u000bChܱuGrwQ>|\u001chv#l\u0010OA\b? n֒aO\u001e|\u000eM\u001b~\u0011sS/j\u000fGwKl:}25|mLڀd6@Ox\u001fC]E!M$bQz>._\b;%=zχ\u001fć̕IR0Y\u001e\u0006\u0012=\fSNc>_\u0012Ȥ:\u00121>\u0003G|t\u000eK}KΗ^s9sKj\u0003`\u0018ڵT\t\u0002/weh 8X`~\u0007)&Z\"Q\u001b\rn \u000e\u0012g\u0001\u0001d,<&>*sn|U\u0014V?I\u0007I\u0010zr\u0003G-@~ n`b$u[ͼ\u0014\u001e?sPħ*dٛA\u000bS+ÝDat[k:C\"Z\u0003b\u0019x)<'tQCjb/RY\"%\u001cX}lIA\u000eC*\u001cAU\"'֛qz9ԘGVW36}'9,g K[(\u0018\u0017\u0005ml\t\u000e~.\rU\u0019^1!]z\u0013LI\f\u0003b63\u001fx\u0016\u001e`^sxM\u001b\u000e\\xr\u000e\u0004ug\u000bڶ`\f#5&\u0016mN,.\u0007Ǜdiy\u001b\r>ٴ\u0017H|ʴ'۔|&i%DgԜ}kު[\u000fg.#,.Ü6]JE]Q}t]]V[_\u001cgy*a1!Aq͆j\u0019xV\rS\u001b<ڕx,skǭc_(\u0011=G)z(ٶk5\u00178a=zVy\u0019i\tF\f\u00178+%sb\u0015-гa再o,k\u0003y\u000b-L\fI>2 d^8\u0001\u001aL\u0014Ⱦܾ#K6u\u001a>y6N?0\"<V˙^\u0017mtY\u0014䲀5rޖEغOKMΝzV\u001b)5o:*^~\u0011Tƣ#\u0013\\\u001c]NRϊ`tW rp:\u0006NM\"J\u0014I#'KLdnű\u001ewN\u001afI^j+\u0018k]ڰX\r\u001fى\u00177^\rn6\\Ū's;N::%ѢH\u000b7,Oz:\u001eOq?\\\u001dd@L\u0010\u0016ٍ\r\u0004;\u0018:&\u0014VC:^\u001bf\u001bYff\u0013dc2j:j=D?%rkHz\u0006ȧR?Y/\u000fS?Uv,u+;sr\u0005vk\u0014{Ơ]jIY'/GjBWY+rl֝g˭ڻRmwjzPv5T,[B\u000fEJ2L\u001brg\n)\u0019/i\u0003ZآZj]mA-\n\u0007=p]M*&Br=ӗ7N̥\tk|KJ:\u001dŕKM\b\u0015޷\u000bZxKd/M`I4F|ty5\u000f\u0016Ϻ\u0003kAZl(LP(\u0012\u001b\u0014:g$(GP_YJՒ<\u001erl_\u001aU)ܗ\u001d/\u000b6\u0003۫#(k/t)TPtSk\"[E \u0011\u0018M!\u0013\u000bs+)>59\"{\u0002-;+L$ct-лS9gL\u0011\u0016󫺫vUOi/m\u0006\f>.vN]̔nOR o\u000bE\u0003)\f,mܥ1\u000bYi\u00002<%\u0019\"\u0005j\u0000p#|u\u0010\u0005\u0018|\u0007dAdZ\u0001\u0004\n/Tl3ESGV\u0014ǎłrV\u0014bAߕRفase\r[GN\nq\u0005hyX\u0016 g*_%t\u0002\\z\u0010.\u000f\u0000\b\u0019\u0010\f]\u001dn} v\"hC\u0014\u0000Wey:\u0007}\u0003)1A\u0011)cmZ\u0014\u0015\n9Al?;\u0013qN]K+\u0007i!ퟐ`&o\u0016\u0011n Z\u001d\u0014\u0000R\u0017z~X:D\u0011\fxXj\u000f\u000f\u001f\u0014ꄀ.\u0018m]q\u000fqp/q$q\fJ+\u001e\u0003|\fp4@A\u0005΀]\u0004|@\u000f,\n`\u0000i\u001cs\r\u0002R1\nCbA>N)j\u0007b0Wa#Nl\u001c-\u0017\u0006>\u0002,Jԉc\f\u0000\u0013\u0000\u0002q\u001c\u001c+\u0002V8V`\nL@pE\u000fo\u000fN.;\r\u0013>r\u0018ߤ~Ӌ\u000e\u0002\rD\u0010\u0005\u001bQ\f\u0000ǟ*󌓳\u000b\u000er8~\u0013\u001eѿ߅<\u000f\u0016'B;\u0006H9\bxψm\u001c\r\u0001\u001a'5}\u0005s;g[{\u000f/~Yi\u001c\u00126\u0001-x*\u0006 Z\u0006<\u000ba\u001cV|\u0019s<\u0006`\u0002|\u000e'}\u0000\u000f`ğB\u0012\"\u0004%Si\u0003\u001eab<w9h\u0015MvC9v\u001bNg3F\u0016y@`@z\u000bp|T^\u001a[S\u001bGlnrnbaf2P/87w/nx\n\u0014Y.H2{\u0013Z\u000f1G;&li\u0012^,?yx3)П^/\ttL\u0005\u001cj$S^I&\u001b~\u0004\u001aaěg\u0007b+\u0016>.;8+\u001fNv!=3lz+5\u001a×N.]\u0011;_Y\u0012(\u001e~\u001a@5\u001ev&\u0013$&Lŷ\u0006Gpf\"\u001b$[\u0013<HW.N2a\u0016ycY׻w\u000e6\u0019_cN=o8KTq2-\u001e\u000fwom\u000f%]ܽs\u001axK/u/G닟\u0017\r\u0014y'}=٢uu\\\u0002\"ilIzL#Z+sg\u0017F\nt2K\u0002\u000e{\u0018=wnurλ\u0000\r3/`0'׵\u0017.>Zą\u0007^ M+/@}%\u0000\\ewJr=^GdA\tO\u0015zwsV\u0019\u0000_,,\u00071̒_#G]]\u0016\r<~\u001e</y\u001f\u0017.(tv\u001d&9bc\u0007nt\nW\u0012٪ ӗ_@;:}['{\u0006\u001dG˨Ѯ91?hsy\u000f6AHVG~׺xݥ0\u000b\u0005dx˼sgz\u000e_C{[]Tې%'0s\\GΆQ/K\tN_p\u0000%\u0014\u001a09+H}W[\fH?/\u0014Xw\u0012ދL$3UhAǥ\u000bﺓWn=\u0018P~\u000b3zV\r<7{m<ҍn$T'\f>yмgkx4$E'\u0017ȅ/$ٗ\u001dd߭w=Kپg\u0015]v\u000e\u00030~\u001ffWotj\";NNt߶pRsV+͛x\rL)!\u0003}):Yf}`k+\u000e\u000b4xٿN\u001cRw\\³H]>Po(me/}#>\u0002\u001cm|]\u000b$&F/\u0018\u0010+,24.I.;vxoz\u0003C1\u0011ѝS=2!\n;rYP)5\u0001k-Q,a\u0002O̧MzVfee%%10js\u001aVH\u0011M)(NZ˻g!\u0012.\b\u0017WcpUn\u0007cᇍىV'mI\u0007S.؂jjxpK\u0016tR\u000e's\n\nDgP\u000b=a\u0004tld_v_@v]_6Irx\u001bթ\u0016\u0014O6ʠ>\t@{\u001dtk\u000em\u001aV-uzks6.:79Ei[ ڤ!\u0019Aob@LHZ\u0014\u000e\u000b\u0005wvf\u0019\r>.r틵ݗ`\\\u001c//$0T\u001ca\u0003\u0007|8YhӴ;z\u001d\nzB\u00196Hz&@l7\"8)g\\Z4$F'־T\u0015]?\t\"3{:.\u001e>.7w?kɨl٫\u0001`T=///K}\"\"\fbW\u0017bH7h\u00109a\u0006byqP\u000fs16~/h,~QNX\u0011\u0000/&/qI3\\U2Qcl[w\bi>\u000fm\u0015fh/\u001f\u0012lp\u000ebD\u0014v\u0016$VmS0\u001bQL+\u0014\rJUOƕZk;!ϯ_n#\u0001!/`\u001cȓ:Yjf{Dj4\u00151qh\u000e?|<Gb U>)L\u001f\u0006e\u0001817y\u0006:mYVW{<\u0001W5sҚSa*Zǯ($i~E\tTuhr\u001b}:d\u001cˍrkp^9fd5&V}?0\u0002y\t\u001ddrkڏrG\u001fj\u001d\u0000__n#_BRs\n\u001d\u0006gMAT\\\f\u0010et+r'{$p\u00177\u0013F\u0005c\u00177;\u001b\u0015G9@\u0006NTfwa\u001f\u001e\u0015\u000bJg чEhoTZQuI\u0004\u0000?\u001f\u000f59yi.T&NeʎZ㦢UD\"\u0006$|\u0004\u001f.19PƓS\u001aB~F~.\u000f\u0003( {MK}&Qu>!뇵Ehh]\u001c\u0010v\u001c`&.Zn<\u000bb\u001az/᫲ގn3c5.\u0005i\u000fl\u001f?=T;M؟a\u0011\u000e\f/\u0010X$#a7 `yG\u0006K~4Х\u001bR#U'\u001b[ +vw\u0003x#VS\u0007~X{\u0010\u0003G(#FʢgY\u00164\u001b\u001eԧ*9F+]\u0010Wg\u001f\u0019]2{<;0>\fA4X:Ĭ\r\u00076CRGw!/ڋ(?b\u0017KEG\u0006Zg]EM:f3\u001dO[\u001d<Zt,v}\u001e\r?\u0016rul,F\u001dQ\u001bQ\u001as\u001e[1%K\u0013eqg\u0018\u000fs!eF\u0005ߊ^Gt%*T#XF +gC\u001aמK=A\u0006ۃV(9hz>6~J{OWʦZzl\u001d:^\tuܶ_yt\u000en-C\u0005a\u0001\u0005ΗMFipZ\u000e}CW읜\fَUd\u0004޲\u001cNjo!9V/s\t]w\t0m\u001f\f:uHe9cn\u0013gF\u0014,z?p#\u0007\r@\rc\bb\u0014\u001eX\u0019@W\\Q*nı\u000bdCQ..re:ڮRH\u0015\u001c\u000b'\u000e\u0013'ixzٴxl_Ϋ!H\u0003grͺau(4jP8՘ڨ1Z\u0006\u0013nX\u000fCqj#2)\u000fj{3h\u0011v\u001c12L\tZq\u001f\u00138P>\tiLG\u0015iZ\t\u00061;O=?WZӮ;gǺ6X\u001fT\\\u001d]\u000ekQQ\u0007-O@G<\u0013R5J'\u0001K_ݣ喩dD%U\u0010}K\u001fSfY\u000eڱi:AOe=\u001ai!,\u001f\\eBFJ~X/M+\u0005<\rΕb09\u0015L07V\u0001U|\\\r3yg\u0001-Lah3OFd_X0\fWoH\f'7n\t=ؔ#*_0V}FoՀ$\u000fz=\u0016\u0015.͹sCF #UDT\r\u0001+e\u0015%?3\u0017^pi3r\u00073I\u0014J '\u001bv}/_\fF ?w\bM\u0014\u0002M\rs\u0016bRm@\r\n%bS8Z0̻NGk\u0003\u001b0{^ls\u0003=2Q+\r\b=\u0017\u00164\u0017+\fwt\u0007Am\u0005= \\U |Ώ!\u0010A\u001b\u00165\bB;4-CJ{=|O73noV:2A\u000bSgbWOj*\u0010.ru\u000b\u00062\bx\u0018n\u001b?\u001cDU q\u0002\"ԋ\b\u0011Bĵz䖇ۇ܅,Hz\u0007߅\u0014\u001d@~!h*TFf\u0001\u001f\u0012Ͼvexz.Y@e%=\nм#\u0001\nL\u001d3sDBdCds\"\u0001\fDv^(Dve]\\!#\u0016ƿCW;0s;=;3B߱\u0018\".2u\u000e0F3\u0006kKj\u001fh^,yL>=\u0014ܲW@\u0004C<9o:}(vPX\u0001\u001bb?m};?\u0003mF+\u001c@\u0018T\b%0\u0015[ğɆ\u0003㘎8;\u0015\f`-\u0016ǃ\u0000 K\u000bx簼\u0002\fCy\u0001Y\u0004\u0002PZ\u0005q<\u0000/k9\u0016;>WqQ,\u001f \u001e\u0004*Zvɍq2 P_\u0007166\u0000\u000e\"\u0000F\u001d\u0004\u0007Q\u0000\u0007g\u000b|te\u0002o\u001fF1\b\u0006>r%\u0015;L?&w,_Wu~gnP__ⴈ\u0002a޷2\u0011'\u000e%\u0006k8^l \u0003\u0002ˀ\u0013:\u0016\u000b٨\u0005\u000fg\u001eDw:s\u0001)r\u00193=\u000bFGaDBl39=?%N\u0015 )yǟP\u0013.(N8%\u0017'S[O.V8\u0011 T$Sbg[\u0010Bn̸|\u000b\u000eϱ}.Q2<ꍰw}\u001cV3s\u001fN>C^ZK@ΊSa)(_\u000e\u0015?xc\u0019ȯS=!\u00077bQs:B\u0016\u0019J\u001b֌yqP\u0004y\u0003?\u001ayxd|o׏ϛ;[)^5\u0010i>0^s\u0012;\u001cip\u0017\u0002\u0016/eZ\u0000Zv\u0002rF\u0002!'#-Ab\u0017\u0012=~#\u0005-\u0014FnTms\u000e\u0004}}_ѕl\r&k[+p\u0005'\u001eS<\u001c\u0019PcF޸\u0016f7ṶӠ6\u0012 k-\u0017\td\u0001+\u0002P-\"\u00018+Z`}zt\u001f5޷ߗř4Kb<\u001cr-{B}Eʻ\u0017ҟ1goR\u0018,Q\u0014&\u001b):\re]W\u0017;^kw\u000b8_,d2e)fiS$-\u001d}\u001d\u000fVM\b}#sތz㤎{gn^6SU\u0003bȪnJ}\\ׇ^)[gj\u001dkמŻG6m7q3\u0003\u0005ˁ\u0017Iv\\\u0010l$$_e2\n\u001bY\u001crWrCŅf'n\u0017zn\u0019 \\=>KxwT0\\^\u0003_pw}^pӂ}ulujnw\r\u000b\u0003f\u0003Ϗ>cen6\u0015Eٮctu,Ƨs\u001fZWw?;O;r&-CX(b|\u0001X@eF}aX\u000ed\u001e\u0012i4*\u0019s2+ݼ\u00047Ϝq?ѩӄ7\f\u001cf\fB/\f\\/?ş\u0018\bYH=\u0017qP|FAw\u001eZ+\r\u0016K\u000brs[<Z{S}O\u001f2lj]b<Tet\u000e\u0003Ve\u0012(Ϩ[jk^՘5ݐenZ<^-\u0019_te̾hIxx!Ը撼7Qg\u001d\u00166́?rݘ\u000ba\u001d+\u000by,;\u0005\u0014Y\u00030o30\"y6S'\u0016t^Y\u0006V5bӑmR\u0002Vo2|\u0017Yqt+c\u001fXj˶9E2EKӡv\u0015ee]Ym\u0019\"N!7-\u0011\u0019^%ü˦n\u000f<[P[\u001dv^B\reW$]\u001eK7\u0018Jt\"O̎ko+ً6ie~:\u0010\u0016RA\u0017eE{77wf釙\tA@_,ǰc\u000eBn&zz\u001c\u0016R)j\u001a鸖lTx=(2Sp\r*'a֪4-V-{\u0007ZX\\\u000f`\u001f\u0007\u0001I2\u0016Wr\\\u0010*ѾyR\u0018u0JD{ާ`͚\u001d&\u0015Z/>\u0018 S3\r\r;ݖ6*^\\SRnq@җd!@3h|D\\6\u0003\u001bqt67:JhTKFQS`/\u0017y$\u0013\u0011])9lǔڰ;>w\\4EjV\u0017thQژ24\u0002ZA[\f\u0013)mD\u0017׾]t~\u001d\u0017'A\u0013K{$1^̶8a1:LaGN\u0000/<ԏ9/jh\u001a\u0004hX\u0018{\u001cx\u0006hu><bB\u0001:T\u0014\fo[7\u000fv3\u0005pMd\u0007|fƥ3R89j\u000fkN\u000e^P\u001c௬$yb\\n0.\u0000O\"1\t}n+\u0001\u000bgoQ#:ո+G\u001cAZ~HZ5|SydV/\u0000_U\u001f8{\\\n\u0015WcHWVKBs7Ѫ2\u001fchY\u001ckha\fӛWJo%\u000fw\u0015p*?\u000f&\u001fĿ\u000e\u001d\u0005HSw\u0004όX\rJV5v$.?bJ`\ra|pdN\nj&8T/벳M\u001a\f8x?/\u000fs\rS&\u0013]a\u001dhT\u001cR;iQB-QkZJhD\u0012\n\tŧ\rڑqמ\u0004\u001b\tT\r2a1eqEX\\\u00074\u000e{;z`t\t{_޵ss\u0007bb|d]\u001fF.\u0016J\tM\u0007&\u0017C֦\u001dP\u001fkhKh3Pן\u001782\u0017/\u0003\u0016s#6c*\u0002>[돢ZG6\u001f1=\u0002Z\fw?X'wj:6\u0007P×pDq\u0001$L\r&ǲN݊\u0001=^1GJtA\u001a~O7\u0014$\u001e{=\\9\u0013{\r0{q,CymE]\\.'ΩԪ\u0003si-c\bvNt7jW7K!!J\u00032\u0007\u001f,.8>\u0005\u0012ݚS^qI*Ќ\r7\u000f4uIBwvdM\u0012IwJx=B\u000204\"L\u0018̊\u000bLɺNϮ'I\u001e|\b9\u000f\n\u001a\fǞ\u0019Ũo'HP4hA\u00124}L5#{Ǧg+ɩ\u000bRwg\u000e|\u001ba?0a[Zv[ ϶PDzm\u0001R5\u0003\u0014q{\u0007q\u0004zdX\u0017\u001dp\t\u0001f#G8Q\u0010a=pM${e\u0019hEz\u0003SLNmBOЍA\u001b\u0015\u001aI9KO.7~Ewؘ\u0002ζnUGAkͩޚAlqifS~S_HXlr-nH7vV\u0015;4/9\u0019zx\u0017k\u001d2A\u000fy.\u0001t٬N\u0001\u0006\u0005Vh|y\u0018-㞚5i\u0018n\\g\fN9A/ {NZ\u00125\u0004ÿxSQc θ\u0015\bz.l\u001a\u001b(nEvRiHjv{=K3YhbZ,rd|z=u;۵\"Z3\u001e5Fx+A%Uz[qRhpJc˻YaP\tO}ޚI k\\0>;\u000760S\u0014R\u0016\u001f*\u000e\u001ftAQeO\u000f\u0011\n 2O\"\u0002<+*hU:t\u000fL6\u0011$bW\u000f\"/ϞdR]\f}9\n)%UJޘF]FZ9FJxhvE\nAZI,|{H>l\u0010wN2N\u0010\\z\"n=qmw>\u001aV}\u001bEE5\u0006ƀO\u001a%;D\\0*N\u0017.>5\rX}\u001b(s\u0017׵#ogzA̦ᦙ=LOsFv+<JI2=K\u0018f2IѽmL5̭\u0005ԏʵ\u001fX\u0004\u0004\u0010\u000eS\n\u000e==u@EfQ*a3ٷr3ڃ\b*i<}(ik\u00134ðԙq\u0014& lo[ڔ`@\u001eM\u0015qw\r\u0001\u0003%Yu\u0001\u000fxrmQ\u0005?Ʋ\u0013m\f\\\nl\u000e!\\4,o\u0011iy7~z\u000fFj\u001fP\u0003s\u0004n\u0005\u0013v\u0001tf\u0004\u0000\u0010@7&\u001cm\u0005i\f\u0003R\u0000L\u00194aI\u001bEr.caL\u0017\u0010]óXW\u0011ݸB!\u0013aTiG9[\u000e4(Jk\bZ8>'\u0004e\bTm\u0005b\u0000\u0018a{\u0003QN}Q\u0004k\u0005l~\u0002,\u0001\u0017\u0004G\u0004\u0006l\u0001I\u0000\u0001v\u0000ۛ/\u0001;\u00070GK\r]Y4N-\t\u0006//\u0003WKXe\\JcVz\u001e.>\u0005L5\u0002K\u0000sn-,:\u0000V\u0001g|\u001c\u0006l\u0004\u0010\u0014̌\u0006z\u0000}\u0002|\u001fu\u001fG\n\u001c\u0018&]B:=+|۔31\u000b=[^ggkV\u000e\u0003D.EZ寸~{\u001e\u000fՖ\u0001G6_2.7\u001eG\u0007O˭UmuI0ZlmB\u0012-HO:\u0000Ϳpz﷢hq<l7X0\u0004;?\"<c\t\b}QB\u0004.\u0012q#J ݶ\u001bTmi\u001d_~Ar\u000b/ˊفDH\t\u0006N\u0012a\u0007\u001bS\u0012#\f\u0012J`}rBrf\u0005\u000f\t\u0016ɩ3\u000ey(Vt1zZ4.^QR\f.\u001fpyd:\u0007/\tp\u0011<7\tTb$ZL\u0006u%1f?\u001a\u0005I69\t&x\u0012\u001c$\u001a\u0000OO#q\u0013\fts9{JC>ć\u0012{_mH\u0006\u0019\u0000\u000b\u001cI\r+@Z\u001fW/׵cFO\u001bI\u000b=\u0019۝\u001d?\u0004v9z+.!:{_z՛qpOnhOFW\u0007lk/y95\u0016\u0004=\u0005\u0015\\9q^8ǃcվ\u001bĚ\u0017\u0017\t7\u000b\u0017K.2pWxƍIhm*kZ.ģBsY839q\n\f8>{S~GpY5\u000b>6g5=^(\r~뮠'󲦊\u001b)\u0017{k&\u0016\u001b%^\u00053IB\u0006Q\u0010\"Vͭ\u000fy\r\u000f>kN\u0016\u0003WG\u0013ݕaGjOۜ3kzw\u001dFɚ*ʟr\u0004\u001b~\u001dis\u0015\u001afkEmΌ\u001cg\u0003uU\"~Gd<Xr\u001aIC;~s}Ož[A\u001c\u0019f_Sh<7K?{Y֥xM#jЫ\u0017.E%\\XY/Ki\u0017\nI7\u0014\f1O2tHc\"\u001eG\f\ba<q\t\u0013PC=ٛ\u001bѼ\\h֎nh\"^\u0017N\u001f@*KLnޚ+.%<]d\u000b\\\nYs>Z\u001b??9F\tn/qȾ19Ω$8#f\u000eCy\u0018\u0002o\u000fE\u001fd7K@\u0017a'V\u0017`0{n=$]͕9.Otbb@\u001bR\u0013<CW|}V.U)ƊI0c26}\u001a\u0007\u001e\ne*f6٠|W\u0006b\u001c̊_WT_t\u0006^\u0015F^ٟ}lEV=+\u001e\u0015SNJTq4ݑcӤ\u0002CVoHRsH0=\u001aLi|[Ih0MfCtz@\u0006\"ZNlGͱg^E\u0005ooVD{Uhcf#3pic\u0019sfKS\u0007R[]_<SԹ\u001dB4kU[/<\u0013+Z\u0017[Uq8z('`^?@Blg=\u0004\u000bA\u001beg#]x\fS8ua\u0001)*厧zM64\t^NB]ȠY.w!\u0016ʤ\u0005H\u0013\u0007\u000fLn\u0014$[筩Z\u000f=zy8f\u0003mxKZ?wth)^_д=w)\u0003\u00173G)6?p{N}ح\b\u000e\"g}#MT[8.\\6\u001f!da5\u000bG4\u00071$\u0007R\r\u000bܚ[J Z)ViGר\u000eIߎZ\u001enwRHsr^dCԵ[K`\u001dhaamk$!g*&\u00121ܩL[?>9:L䀶H)MC\u0007\u0007\u0007\u0017uNIG_*I6V]qL`\u0011kr\u0006۹ԞI\u0016\u000fI6&m\u000eF:^\fê\u0012m$Po:jF;uiN\u0010\u000bM\u000e\u001f%M\u0019uݪj8\u0018(;Ǎ\u0015SP\b\u001a\u001fpJe>\u001b\u000eCi+bWy0@^\u0013=e%u̝n{'\f62z\u0017S]5FkݭҌtm߮1d\u0002=I\u001cF4ʵH_Tcy){\b+\u0015E#\u001aR%+wP&\u0017L&\u001c;K6;5\u0016R\u001c\u001f\u001b6FBr\u001fs\u0006|\u0005zyΪܴQ*\u001b\u001bM\u0013\u0016d¬b\rMݐcMo-=O̝@E^\\p]\u000e\u000f\u0019\u0003cxI37\u0002<H<dV\u0012D\u0014a\u0003Z\n\u0017\u0017\u0017ζ7\u0003'-ŌS\r\n3'£\u0003Qm{39_zj1ɟ\\\f)q\u0011I%\u0019C9#pTIa1;ò8ކ(\r[=\u001bav \t\ba/(\u0011-/~\fg73\\Ѥ\u0015:zÑ&a]\u001a2gV[\u001d!T^r?\u0005\u0005 Q=-k>\u0019\u001a'#>WI\\z\u000bP\u0014!\u0005\u0017%_\u000b|aN-ݡ? yn\u0012ᨇ7{\tPiJkp~T+d;uwxd{z}}ήu;N)GcRRhVsNF}\u0019\u001aKRd&\u0003\u0011_ry5V(X{~`^r=\u000f(p8f\u000bI3\u0004F^u\u0016vs\u001eZ\u001cng_ύZMfq\u0015\u001e\u001b{ \u001aJRYȴΦR\u0011t\u0019X0\u0005UUzݼʯw0aa\\Ґ\u0012Lԛo~>1\u001d`NV\u001ct\u001d\u001eGx\u0010n\u001avmEJV}ҠFV\u001bɽ\u0007&'$eR8ӊ5aʱBXfhpV)fO6TluM-\u0018b\\^OQ\u001ea\u0014\u0017dmC\u00019\u0017R䛻仺Q\\@=4̥bzW%Sdl\u0005dti\u0007Vt/ZG\u000eS_Tl,GaU՟B\u001bdcQ\u000eE`EaE?K3=xJ\u001cO\u0012\u0017e1,\nDV8U:~D4Ɖ,4\u0011GJ4\u0019N4JAvr\t{\u0003#>SNS,M\u0006[_夷l@mGY\b1^{a[Ⱥ|R37+0ݻY#ЬK62I<rH?\u000e\t|w[ӏnfة\u001ezX7adCGR/\u00188}\u0000U_'-ėTs\u0017V2[\u0007>]b.M.<#ꝩ&7\u0011ǸSi|&Hf|Xfh\\fLT\u0013~\u0007yJ]QbzP?mkhTQ1GI/&\u0006\u001fG^׋dW\b)#WdVR=\r`x\u0011=:6fms(uk%\u0019WíM<]=b9\u00048\u0016{\u000e\u0019\r}H2ss\\\t^C\u0005H\b(O)^TY4R\u000f\\Mq4Khiff+1N\u0000(Ij\u001a\u0013m\tV~R\nk\bc澧}r\u000e[m;41J\u000bW:a8\u001cU3ɔ*)\u0019\u0015\u0017U\fZZ\b<_RSQM>bd5R\\]E\u0013\u0011+!\u0016mP8\u0000)\u001c\u000b\u0005p\u0004\u0010V8l_\u0004[nYK2Xu֭;rMH5z|&\u001453|oj2$\u0006'\u0018KEΨY̦NԸ\r\n\u000eV[\u0016\u0017v&QޓR<\th>s^;dJ9\fq?g2eSʂlky[,:WzhXߡW74ҫw1\u0015\u001f:tyL{\u001ch1\u001d-\b~`,p!\"gqd|lmK`L`59ڀU }PQ\u0018ӻ4Hfg8xꘗ鲶}[nrLo}<]UBw\\f[n7Ҭ>T@#&\u0015*>fLlVѦJN2ȶsɯi\u00057J4\u001f\u0018tA\u0017\u0010\u0018\u0010sb`p\u0007\u0011&\u0018\u0010kZs\u0000g\u0010\u0002⥕\u0001u@\u0005n\u0015\u0010\u0003/t1ܲfW/u*n&\u0002φ)\bM*u6enUx87ӄ|HvO\u0005:\t\\\\@^}@Y\u001eP8\u0016\u0001\u001f\u0000tR߆\\5\u0002Ԇ\u0003j`\t^-@\u000eP\u0006\u0005(o%\\ؖ[\n%i+\u0015e\u001f\u000f)GaE˱\u0017˂W~\f>amphXM~rJ\u000e\u0010U\u001d@\u000e)\u0000V4\u0007m\u0001/I=ހ!t\u00040M\u0002f<\u0000\u0011`nQ\r0C\u001br\u000fX~tKV/Z2i\u001e\u001539j,ӅJqu,\u000b\u001d!K61=@w\u0007=\u00100Bq\u0002\u0018\u001d\u0002f(̿:(\t,\u001e\u0001ֶSI@\u0000\u0007;,\t86\u0005l\u0012\u0001nc;j6N\u000epO\u0000\u0017\u0003>Ϭ\u00138/4Q\n9`TMrK왞JwO{Zz.'5\u001d7Za2\u0012s[\u0006K\u001b \td\u000b/4˿m#L;\u001f=&22\u0012\u000fxzz\u0005<c~{\u00052HpiEv\u001fY\"'\u0010?\u001fGn\u001ci9\\+%\b?\u0012J/\u001d@#ԒoS0s\u0019s_ǋo/(ƫj\u0012(\u001fsIH=A;Ax%?Ql?\u0016\u000e¡`^KˊIpi\nvɹ\u0004Q\u0018i\u001c\u000btnŅǬ6\u001a;ۆ{\u0017~˴\u001a?QNH\\&T$\u00115_\u001d]\u000eV\u0000[9~Q5\u001f>26޻\u0017|xwmC477Bٻ\u0003:iz6N\u000f|rt|7مX߽s\u000fB\"SFJ/S8\u000e`\u001b%෿:x\u0002\u0018+w]=s?\bpO2\u00180{$^r]Bos/\u0017uO\nN!7?$AOwA~Rh5}{lko(_$yg\u0013\u001e\fH'\u0000ᒐ\u0005+\u001b17\u001dt\u0011\u0019{23_K/^6\u001d\"\u0000Ƿ\u001eSx\u0005閈\u001aɼ1\u0010\u0016\u000456'T׌\u0010oǊJ˸f\\\u0004.޳+\u001876ܯ ~]jLdP+\u001fc\f/'\u000fzkb|!&v\u0014u(>ZCf\u001a(5Z\u000282u\\_Oۚĕ\u001ev\u0015S\u001f\u0015b.A~G.$%. j\u001b\u0003۟aV\u001cyb\u001aL\u0019C\u0017w(ǯ˂_\u0011\u001dF>\u0015M\u00152\b\u001bzzJ7\fb{iaz,y\u0015r)dQW\u0002\r\u000e[=gz\rOw9\u0004jurD\fn}qm\r~-\u001b.\u0011N\f\u001a\u000b2\nW'\u000fjͥH\u000fثW\fTb\u001f:zl\u000fcMyR|@ٙ!04\u001bxjz+qg\\vD\u000fa!%\u001f8xH \u001e{;\u0006 6\u001d5=\u001dGծ`]G5.+_HW޸8A9C_UwɈQt?x<9ukZ08L`ZY\u0001dAc\u001cW\u0018Kiۊ̥J[Oþ=Nd\u0015\f{A籞F/U\u0006]E0\u0017Ҩ3qO+|\u000enG8\u000eQn%|-.\u000f2ΦZ\u001e~\u001e\n\u000f\u00028Fۑ2+\u001f>߾aVBSn-`\u0003svwAyr\u001dṼ겸S\\сV\u000bmTs\u0015ĥ/C\u0012h~p+Wjlu&g\u0013G&6\u001a\nd~1|=㩚v&4&ӉἎ\u001eفȣidˢ^{{~`\u001b1e͒yB\u0017پZݶ\u001cnra\u0017\u001byQVb7#l\u001e-\u0014j<\u001cR\rƒK*q\u001dU]j\\:v߯}хWfl[㺽ٽu-r]tL&\u0016klZ$?z6{}Έ|yC1@꒕\u0003:*I\u000f\nb_XN;jIXMtf4\u001f\u0003]q7=40t\u001d?O[q<zحZlt0A\u0002R|\fvyzPM\rlu\u0015ߴdPuja+V+RZ4((*(%\u001fd\b\t#Όܓ9&Ln)3޽g߱\u0017ȠIۙd]\u000b{\u0017\u000b/f\u001d[\u0010`I\u0019/\u000e0*\u0014*t-2B\u0007:/\"<'x+1,5\u0006ɗ#]y\\k\u000fr\u001fd嚔\u001f\\\u0002zm\u001e;@<\u001eg\u0001Ba׎N9b\u00166\u000eǭ[\u001bڵ\u00145\r\u001b\"f#u>d4Hz8mn)&\u001bG</NxTy;_\u0006Ӗl\"q9:\u0012\"\u001fd\f\u0015ZhOY\u001fUFcl8ptVgiv$ݢY{\u0010{PE-Z^ݠ\u0014S\u001bUGhʝmݭN'\u001bi9w\u0011ŶK\n0\u00127$5 \n{&\rqE\n\u001e\b\u000f<lNŝq\u000bovB9x>^h.?ٙ\u0015>\n\n.FrǩŋBJ)U\u0017Ŷ\u0014{\u0004Q\u000baؗ\u001fXȬ\u0010A*tnwF\tf\u0019>\u001f,\u0000Pzg\u001a\\ &LA\u0004\u0005L{v42\u001cm\u0006K7һif6R\u000eڮq.a\u0003S\u0017\u001bU7\"1$\u001bY7FoWj\u0017\b5{IU^P\u001a*JކE\r^\u0003\u0007f\u0005m\u00177'\u0018KmH{@%;=m=g@ŝ\u0015xBV\u001anɡX\u0014:j9\u001b\u001a\u0013[>Š\u00050%^GUۺ\u001d+FC֮D;RO\u0006\rJtأdJk[-$W\u001eP\u0013pd\u0017\u001b.%j\u001fA\u000b\u0002y*Yfh9VV\b\fUA\u001fq]vF?O\u000b\u0013'0\u001aiz}\u0013\u0015\b*k$]VƵ\b\u001eLdܓ9[EE\u0007'@@|!7 4Œ_d\u0007SJ\\u\rb7)\u001b\u001b0fw\u0014(DiZ\rQN9#3+#vęf\u00008V%t{Ewo\u001at+]\u0015\u0019\u000bR.BbErL-8\u0002c\u0002>b\u0002^\u001dDyN}\u0003\u0013\u0016|4\u000f\u0007&R\u0007ېkp~\u0019iʕ}.!)\bjR\u0017\u001a\u0005\u001a\u001dT6\\\u0019\u0012\u0010/>Ѳ4\u0003[B\u0005W#\u001eGJR%fJ\u0012\r1iy7\u0015J\u001dT{?I\u00071\u001d&\u0017sFɚW+.e.\u00076::RϜ[\u0019]OK\"{YƛO\u001atjQO\tQCQw 'FJd '\u001a\u000fR[\fU+4\to\u0003zh܃*\u000e\u001eJ\u001c54l]4\u001b\u001a\u0016t@zאya8x1y\u0015>X\u001f\u0017OJ{O\u000f\u0016l\r\u0007F\r\"w9\u0001\u00128.G\f\u000f\\[XOZ\f\u0017\u000e-\u001cֳ~NMUlN6ˡ7Pj+JgY\u001e\u0011i,ovY?.e˂Zz\u0005.\u0007nƩ\u0015%\f*)ARɺȘ-[\u0015%\u000e:?Bauj2S&H!`DUjG\bW;yQ?Qz,*?Tjpa1\u001ceLQŲ\u0018D9=8K\r:Ȳ\u0010-ܑrS.ni\u0011qA腯a\u001dbbR/[\u00119b^c\u001d%w\u0018\u001bxE\u001eQ?Tjƹ(`ׁIWx^+5v'\u001eYq\u0003ў\u0015\u0013)^qOV-[3S\u0005ٕ\nH]5Rv\u000b\u000f9m3Gn\u0014ϑ5ȑ;GW4\u0017\u0003t5\u0014ۘ1Dk.V.\\2+lۧg\u0011q֫4W\f\u0006Wd]`\u001f8YLv\u0004M#ˑN\u000f3\u0005N0\b3\u001a3\u0002WNe_pa\u0019f\u000e@z\tge|g\u000f\u0017In\u0019rj'V\u0004f쒎X\u000e  4>=zn$\u0003+zM\u000b\u0013xPe􁀴ՖK7}!]\u000fZꐅ),\u0005\\s>s;]\u0000S\t\u0018\u0002A.Hp\u000e\u0001\u001eL*\u0000\u001f:\u0000\\n\u0000h\bj\u001a\u0012G\u000bASi9k_Q̆Q}ECc\u0003mQnm\np(\u0016-gT1@FH\u00017\u0019P\u000bl\u0001Ԗ[\u0015VY\u001bA\u0012^\u0015\u0010=\fXK\u0010i(\fG(jw@ LRW\u0002D\u0001Q\u0000a\t_MW-\u001d\bz\u0019/m<YۖsӞ@XoX*a'Cvl(p\u001dS\u0017\u0001be?G=\u0004@\u0019=f\u0002\u0012y$#@J\u0006\u000eȭ\u0003-G'\u00186\u0001y'O@ϛWn.\u001bP9\u0007Q¦2i9[~c삉%xcM1\u0012ٹ OKe73+MY} i\r@5\u0005P\u0000\u0014i\u0002JjWZGv\u000b@\t\u000b%\u0002`J=\u00070\u0006\\I\u0003\u0001󀱡 ;\u0006#*\t^}\u0017M5\u000bJ̒6\u000b\tsg$/t6ٿ:\"m@:>O{1wUp\u00120\u00110\r\u0006\u0012\u0001De\u000ePx\u000b8\b\u0001NY\tk/\u001f_\u0005g\u0014\u0003n8\u00007\u00017Ʒ_De$٩\u0003)\u0012{\u0018\"(_w8NmS_6_\u0012>z_-ArI6\u000bx`\u001amM\u0013Dq\u0000<9\u0002ro\u0011+NlXH\u000b\t\b%Aǎc15J`\u001f<UB\b\u0012}_mm\u0013(\u001am83\u001eѸ\u0014xpz\u000b/xq?\"IvpI\u000e/7\t{C-\u001bA\n?ֻhrfO[}\u0010s8zkE$n3(ݪ\u001exG/}_V]\r+/\u0001#\u0016\u001aC\u000bP/ѼI\f\u0013A\u001f\u001d\u001c$+D\u001cFiN>ߗhKݖ\u00036yC\u001by/\u0004ćku]Lv!n+Slz)\u0004_u/Y[\fĥ97K\tKhEoyЋzȴۦ\u000b={^O\u001eVGK_{㎟՝:\u0005;w\u00198F1\"A\u0011ݽ\u001aɊk\u0002yE9ibuSNkk\u0003^yEJ\u001f\u0013q's\u0004N;LaoH _OLɼ\\\u0005I\f>>q(\u001e\u000b|N||!ckI>B_{[yuoj+\u0004\u0000\u001awW\u0017b\u001ag|3g&l)gk3\r~__J}\u0012?e1~&\u0015]\u001c/Ǖ,w.\\\u0000>ŊY:{/k\u001c\u0019y@ocMܽe^\u0007{\u001d/}\u0003/ҽn.?R@3-ŃFrSd\u0013a'\u0013ibt\u001d*ш,.rm\u001b#~\u0019\u0006KT~m&\u0015ؗuP\u001effCy}\u001aI)糮B̖\u0016?+Tʴ\r\u0003r&*\u0018q\u000fZB9y6c]\u0010<;|0J\u000f\u001c\u000eUz֟oٞý\"{z(\u0006ʟuPqk|WL\u0016@tҍ&u\u001b4\nڈro{5\u00172\u0002aUl\u0007)\u0007]R+[G(b\u0019g_>mq8\u001b{^ֹ=\u001bR\u001dZ'$9\u001b2/wݍ_\u0015v\u0005VO2-?\u001eGwV\u0014E7&#:\u0007p\u0018L\u001adwx8\u0019\u0011u|z4\u001fFw\u0017#M>.\u001dC\\Zf]\u0000@V\u000f^^go[z_(߲\u001f<_]4/ZǉzLk\u00187v\u001e\u0017\u0012><xxݴV<\u001aVÜ{tuWHtg\"mEzNLJ?+\u000btj\tr\u0007H41m#ժ\u0019A/76wN<G\"V\u001f{9\\\rS+\u001f^_g5`\u0014n-:Qu_\u0015'L%=N}{ȵ\u0017\u0005\u0010a\u001b \t.[&\u0018Qf:\u000eZ\u0017jբsI\u0015cP\u001b-T؏~c>\u001bRzW\u0015\rMP1֢\u0004WL]DZtEx;0oh#\\a\u001b!)vKJzչ\u0016s^zT|F̬\u0005<-\u0013]5v\fEZ-Kb,~gl8\u0018o]Aƹx+kUYh\n<fͺ!x\u001a8\tN5{C\u001dQC\u0011M_yl2\r6\u000b1FWeJ5LVղ\u0015jZlR\u0014\rie\u001aPJ\u000bٙe2ޘ^\u0012\\s\u001a\u0007/ΣI_?XyvXQ*Ӽby\u001cי\u0017Z[e\u000b~E^\u0019ưX;|zziC|'e'#\\٪SZ)}hG+U}^\u000fNFpZz\f\u0002'),>M|_Kl̮{T\u0013\u001c(!~p-Ʊb3ku\u0015U\u0000[XSZ]]ZR\u001aJ#\r{LW\u000b$\u0012rMQ\u001f]U)B\u0016ZH\u001c;Q0/a(W\u0000\b }\u0010`\u001cF!s\u0016Zš֘e.+Mhh\u0006w\u0011=j\u0005ma\u001e-0pwmh9n5Û8Wʇѱ\u00167ٽ\u0004}ZaI\u0003\u0011a׌nS0\u0018\b,\u0015ձ­C\u0007RK\u0010\u0001]/\u001f9?qk~njҘSzp\u001f:wfhl\f=-H\u001eW&(\u0018\u0018=$HF̟q:mcipw-ȋ\u0019iF\b\u0019$nr9.lVYo2ǗI02KpƧ/6L4Lc6m р2}\nڷsHew,ʝ3ڨ߅fNf\u0014TN\u000b=L\u001fD)\u000fx\t\f\u000fKM*m\u0013皰^le\u0013w\u0018Lϙqq=Z\u001b\u001eZ&h^hb8^:ӝvb۵igxl0hݛiMshr.t{xV\u0014q%J<\u0015fDh\u001b~\u0019ϼ6x\u0016@)T/YkP07I1ɴ79\u0015O(FN\u0013fฮ0d0dd|&OdB\u000f_,\u0017d6C4(g\u0019O^[\u001b-jfЧLM\u0011INC6*2\tw\u0015;kmlLr\u0014tu\u000eMB\u001f\u0018=tЖh\u0001\bϢ\"\u001ci&)Cb G\u0004iyݞ\u0012\u000f\b<~p z')8,\\\u0011\u001f\u0003\u0018)3\u0015b1JjCBTKͷTg9.JQ¯uk5\"=\\\u0012J]?&\rt`TJI9R\u0018N0b:s?0\u00017JFMY5:L\u0002xѮxQ\u0015x;buu\u001e׹/̜T\u000f\\o6Uy?}me\r]\u0012\b5^DO\u0017(0]J􈡢M\"l[O|wJaGLᅐl\\[0z\u0019_4Z5͒\u001dO\nk\u0013\u0004zG\u00032{2z{\f;\u0012̕\u0017GX\u000bλ\tIjbcluiL\u000eZ;Luƒ(w\t;Vh\u0015ɏ:1+gp\"3ڒkk5-sMx8\u0012w\u001bV-nN(p\u0019G\u000b[B٩Z̼\u001c\u001fr8rO{@\u0014\u000e\u0000v ]ܖcb\f{yh+'uINs]yuKK5QC\u0013yݥ\u0018b@ɱ/4K\u00121)cgƫan*b:aGv.\u0007(y_+k_asؽ\\\u001bX\u0000'kef\t<'BjW$\u001b\u0015${RHv\b!Y햀?nF\u0010便Jm3\u0010nr<Www+\u000b)ft^bO^xj+2F~mXJ?2e(<T+ɀ\u0011JҐE}l#j9#Su^\\;h먈n&\nM\u001fW\u00126e?/.]ڃM\u001e[,\u001a9\rF<_\fk;[m\u001e\u0005ˣL⠂/IdɗdR\u0018\u0010ƫG6t/*SlBJ6\u001a\t#<p9F\u001c5z%e{)H+6L\f^:\u0019PxWaZI2ĭgTpX?\n.뫶e0Ӝ/Xdn  wVD\u0012-|\u0014)6\\.3>fIx)%+\n4BXi$Xِ2\u0006PNuj|M\u0017-\bJͤL\u0019\u001d\u001c\u0011\u00040\u001c\u0002{Aq\u0010\u001cRY\u0017BGmuxW\\\\J곗զ\u0001jȹ&j-C\u0013Q,J2b7edFV1\u0007gK.G\bh?\u0012*Ώ<.Z\u0002\u0005s\u0002'\u0001@laz&_DcPL\u001e\u001d:'o\u0012L\u001f\u0018T{\u00172ъ*ha-6۫mY\u0013dL)}U(V*K:׃ZFB(<\u000b\u0015\n\u0000.\t\u001a\u0001M|y\u0015V-P+fVf&/\t\u001c\bԤ|?\u0001ju7,@AҠsPtu/ڧo6WA!i3\u0016;z`\u001eoxܓrzP%\u0014SBhu:Jn\f_zr'aku\"\u0003\u0001\f@4\u0007$5\u0000\u0010\n\u00062Kpa\u0000Iw?޶$'_bd\b\u0013@\nz\u0011b6(\u0016/,ݼm\u0013p\u001d\u0017R\rF*u\u001f\u0014سi(GO&ls\f\u000e\u000e#RpK\u0000\u0000Z\u0003JmO\u00015t_nP\u0015@2=\u001f\u000b\u0004%\u0000zU8+@_(C{tcpY81`jjA+S(Vm?;\u001ep>[)\\qɋ\u000bX~뷿\u001c>m<7\b\u001e0ۄp\u000e*`F\u0000s\nW\u0002|\u0002\\!\u0003\\1]\u0004\u001cRN>\"EpЋbMlN\b3\\\u0003v\u001f4RwE<L\u00055\u0017'_--\u0006/u\u000by6\u0007x=~mP\u0001I\u0013\t\u00137\u001b~\u001a,\u001f@mC_3~mK\t\u000e_\u000e\r\u0012b\u001cdḒj4FH<0Y~\u0005:,Vѯ\u0015j\u001f|EDFXw<?\bz~\u001bm>\u000e\u001as\u000b\u0019U͉č֍M'xJC>|\u001cKt!xpFhw\u000eoa:*^OWQ0\u0019Ԏuo}\u001cWhݥ\u001e.w_V֥{UoFx=uB3z\u0013Үu֋X{Z鍽=qn׊Gz\u000f3\nw\u001cCfP/9ʲyS*$ <{\tDcx\n\u0019,W\u0007M~~s\u000b1$w\u0003\"\u000el\u0016j\u0000wo-(l\\\u001a&j\u001ae@o꯽CĿr}\u000bɄ\u0010H~.\u0006\r{;\u0017k:z\u0006u܃)\u0014\u0005㘶~I;$8n._Wb\u000f2%w\u0017c\f2_l)t[f5\u001cj*\t_{_Kq_a\u000e#cK\r_os/q\u0003o+\u0010Z_\u001b?eP931~\u00103j՘g\u0006[c\u000ft#\u001d:&\u001cL*L*\u001bh9vJzo#\u000fk3,\f\f\u0002a\fcd9\u0018K~[\u000e$h\u0010Bzގ\"~Nr2N\u0015$fL[\u001an\u001b-6Yzγ(\u0017Otz|c\fWAoxw\u0010zH\u0015!t#\"9x\u000fLg ~&M\u0006\u0014zKxfor_~:y.\u001a,Y]=лWT~(->\u0003_\"x\u001e\u0016qSrؾ\u000b%35\u000eɾ\u0015tx~6\u001e>6xb5\u0000k \u001dP?gb?n`=\u001d^\u001e\b~\u00197Fb\b==26u#$F\u0001wFI5=E?Po4\u0013aU|揙yv\u0001֟\u001cim(7ƣ\u001c<f2/5+ҴWѭߺI׮\u001dKwZ$us[w^PѪFuBἶ鈔巧-飽o;_V-#عX_\u0015['F\u0005|q_{+\u001fՌ_Ȩ\u00132ZtQq[ny\u0005w>u\u0003:o{~u!nK\u0007nge;\bk3y\u000f]﹥*\u0013n^A_DH\u0019\u0004%(\nb\u0016sYЮη\u001eyTF\u00049&v{\tk\u0014]\u001cTáS\u0019\f\u001fxr/v\u0007պ\u001cf\r:ba\u00195;y\u0014\u0017~iCjpZ\u001a*Onަ5%Ҍ\u001dȻ^ݹefZF\u0001\u0010/:WzUJ\u001aIMĿǔrNw_\r֫\u0019 W3g4.RmTǎ[)̨Y˲ۑ\u0016\u00110/N]aVa;7]1m1qg6f`Eos(hLk7j\n\u0001!!^v\u001a]j\u0015\u000b_^_=~C\u0011̌Dq`\u001chUS+3V\u0014v1\\bohgJD&|j8ŠE鴾+it2mƇ]ڇШ\u0015+N\u0010%ElT<\u000e\u001e\u0010#\u001azU\u0014>]3+\u0007VCe^h\n5?\u00156ϗ`Kص㍷&cZ[Z:^_\u0016~\u000e^UgC,>ә\u0019}$AOv\u001cMzr\u0007j0֘OF\u0010PYz\u0016eo/EOY8Qcg52\u000f⸂\u001cA׷2l @6EO+\\|asXj@f\u0016z@\u001f>x=[db*LK7LOӅ}v\u001dV?2j{Z5^Yy\u0006kReȱ\u0016U)\\\u0005/;jTZ\u0019Y<YZɾ$7K>+\u00041`Y\u0000-[GM[GD]WՅZ\\M|\u0003&\u0018(6nt۷D5\u0016Wz\u0001㚝\u0011RY\\ڸBZHeK\"riV~`*\";5ސ5JP\u001d^\u00179m;Z\u001b%\u0015;\rZݧr#\u0012ikȴ\u00059\u001duk\u0007KqL=w5ʳ[J;JdzNY+H}fwUPa02iG\u001fӯ\u000e`\u0004j\u0015U]*GEQAeL/t&=&q; ^뇢f\u001e.F?j\u0014l}|*Q\u001bOr]b\u0019m1\u0004\rDqw\rVB=Gٻg\u000181{\u0005\u000f2|\u0013721ΔYrR﫞=\u0018u(uRH\u001eɍ\u0002KKJ<וvl`\u0015T#\\\u000fe\u0012z\nHLguhҫǹiÊj<^pq 7ю,]YT\u000b\u0006027\u0016\u0018!޸X(û\u0003#\u001fH\u000e3t.ޜGF6(*ɒQ76mkn\"\u0010g+.g\u000b\tg\u001b\np\fDCYC˶Gtt!ԩT~_xDjztk\u0011\tO\u0015\u001b\nr\u0016kV:}IHx{fbOO\u0017\u0010B\u0004\u0000|2\u0017\\qvյ~d,r\u0007FV4dVS¬:]0\u001bv?\u001c*w\u00004?\"8Xpr\u0005\u0006\u001f\"RRV[ōtAx\u0017\u0002DLz]^*\f\u0010,hJ pL?{.\u0012olq*\u001a.t]ͨc֢nO\u001d:r\u0001ME\u0014t\u0000\u001en;ڬ&0ȅe\u001fh@Ԋ2S#\tg!\f\u001f\r\u0010\u000fa\u0002M>\u0015.^\u0007u:zR`1Sݎ?\u00106'~*|\u0013o\u0014\u0019+Uk8\u001c݉\u001e\u0014\u0018D)u\\\u0013\u000f\u00077<`}aGctX6*\"cY\r\u0017\u0011!\nV\u0011\u0006+_\u000b\u001e\u000fC.LG;nԊ\"͐I\u000eKZAK,uK<ɴUg\u0001p\u0015\u00117\u001b\u0017\u001b\u0001f\r^\u001f\bYYbY\u0007c\u001b,\u0011&[p\u001c^nտ~B%=\u0010\t%;v\u00007\u000f֗/T\f+)}\nt\u0007\"4L]KM5ُ\u0010b$c\\\u00134LquSEl#A#\u000b\"$0&=dۜ\u0014FY~>0q\tT23]Rkٴ9\u0012\t\u0017xe<\bm8:a{CL\u0013\u0014qHK\u001c<Rw\t\r9)\u001c\u0010_\u001f*yo֒E\u0007hpw'ER7&`E7kமu{dAFMCOQ4\n|7J=ok\b4qI\t-*M!G]CL\u0015\u0005נC\u001dpo\u0019\u0002jS\f\u0005hx^n\u001cCYq1ɍ1g\u001cSB2N,\"K\u001f(0J\u0014Y\u001f\u0003\u0007q6^\u0017\u0002;;Y~hkhL\u001cH\u00161ù\u001bFs2\u000e\u0013C\u001cx!\u0007.;Z\f撳W-Š\n\u0015\u0004\u0005\u0002i}@Mnh\u0005YbA\u0001T\u00005`\u0012@53O@ť2>J?|ejF\u000398\u001faנ\"uu/g\u0002}\u001a\u001eH\u000b([0\u0012.3|2x\n\u001d4'\u0017LU\u001e'La~/-@\u00000`\u0016]\u0011\u0000\f*`)`rC\u0000\u0001a;\u0007\u0011;\fQ\u0010MɾL.?^j\u0010\u0002KLH䯍\u001asIh:@w,m\te\n~v\u0002l\u000eΦP\u001b$`%\u000f\u0012\u0001꺀m횀\u001dk\u0014\u0013`'&#\u0002v:\u0003\u0017\u0001/\u001d8#\u001fj=.wjz.\u0019n\u001e^WLF\u0006[\u0006.f%\n\\<\u0019i(O_=F\u0000W9k<\b\u0019WO+\"\u000eú\fW\u0006x*\u0002^~\u0001_o\u0000)\u001aQ\f}\u0000P#\u0000>G\u0007e:EW{\t&/,+~m\u001a\u000eLHJ᫹%N)vI\u0004Q\u0005B\u0001\u0001\u0003_\u0011*@h&u ,- |\u0004f\u000b7,P:Ţ\fS8\u0000\u0012R{\u0000@BK1x\u0006$a\u0003IV5r\u0018-AU:u\u0016OE*v\nm10c}['\u001b\ti\u0003wJ[\u0016\" j?NWi\u0000\u0019u@v7 /<P\u0018J\u0002z\u000e@qk\u00194:Pbg\u0000\u001cVƞ\nI\u001djsHA#KfOr\"fF]ƍl;i.jA?\u0003o<7\u001du\u0002j}ZQ^\nиv\u0003h8a==&z@\u0019fF\u0013A\u0017s?\u000fq?Jxy>-rN;>TJشă?):oJ\u0017_\u0007W=\u0012G*_|yo??7\u0019A\u0003S)\\\u001eYޭv6\riRfWl/W|\u0017|\u000e|f|t.gv\t\u001cjYl&\u0017OvЯ\u00125~\u001d^ߦna,\u001d\u0015.7$,ޅ]j\u000fp>\u0018~n|xt6yO\u001doetVǼ\u00134{8\u001c&i;c\f\u001e\u0006.\u001fV,:Q\n\u001aw\u0001[\n\u001bR˗-o\u0007Oq\u001e\u001e<=ka7ng\\(6XogM\u001f*͐K~\n\u000egzsH,,;\u0000ũ?\u0014\u001fC+2;2?q=s]'^.>\u001bv1z>U;%L܅\u0007>Տfߞ\u0019~:z\u0016vM2kͅ\\kd\u0012\u0012\u001dux\u000e0f\u001f!e\u0007\u001d]|TO\u001bd|g{c\\Jqz!\u0017٧xͲ\u0006̕qq2\u0018Q\tYØ\\Cp\no鰏x ]A/qާ_L\u0010ݻ\u0006sbA6񲽪\u0017~\u001fI\u0004NVn.\u0015&s\u0018cm'9T?\u00068N{_>Dz\u000bN<х'y3Y,\u0004r}mz+ '\u0010ަ1ssҢ\u0010QDrV\u0019\u0011>'苴sȕ:\u001eC\u0015gPs'EKG[s!\r^Y\u0019HG}ڢf\u0017N\u000e2+M~֯[=ġzlamަ\u0014\u0004:]T[\nn5\u00040wC[\\=6+Β\u0000\u001b?н@c\u0003ƓLb%NNX\u001a(:\u0007\u00193GMgT\fE-k^Qe/E\n^I\u0018fkc\r\br鵁@c\u0005^pkM)\u0011ݬZ*=yۮ^[<u/\\WakEra?ɛ\u001d\u001f<\f#?PP||%xSl'|vFP?{\r(;J\u0011\u0006\u00163\u000e\u0007*ƮF\"޹ڈۯ*#s~{@\u001b^{U)OaVw^f|*\u0014KoL$ܫp[A\u00028\u0005\u001fI5|M\u0007\fRo\u0006-=\u0016\u00124=̇\t\u0005\u0017<9\u0016R5e?\u000f\u000f\u000bٰݶ'S|=..Ȓo\f̼t\u001eܴ\"Kzegi\r\u0012v l!ctۢz__!Ws\u000b?B_7ɵ\u0017\u001ebq.\u000fKч\u001a\u000e\u0007=|׶'\u001dTÎc񺙁\u000eE\u0005{6R&I%eW\u000b\u000ee\u0014$w{~~  U\u000fMѢFc$6pmn\u0016\u0014etoݎI2l\u0006]ant5?2̓RG\tQŨte\u000fZs(\u0006\u001d%J$\u001aewemϴm\u0013qh5̢tjh\u0012\t>f\u001c\u0014L)b^E0*n*<\rq\u0003i^5+5\u0002U/Vf#;ص\u000f\u000fFԐjL}fݡ~8cQ?Wʟҧ^tǴ_ndVt?P/+y+]}\u001a'?]\u001a\u0014pד\u000eYEikp]\u000e)IT$6nJ(,D)X\u000e_3R\r옥\u001f[^yN`;DS18ҙ\u001c3tkSi5NX\u0014g%ܼ\u00055mx\u000eNe٢-=\t=Sm2hm|ftQwWӸUYѻ/\u0007֗)y\u000egXxِB\u00139\u000bC\u0016\u0001M:>\u0016N8\u0005J-\\ywgL\u0019[W\u0010,\u0019Vψ\u00012YZO6礚M=_;H]\u0014]\u0014j&\u0014zu@ŉ\u0012;o9wEa\u000b`\tr-җ^\u000bQ|\u0003gS>Zp!\\\u0015և\u000fŲ\u0000+<.=S\u001btGxj\bi#qMP\"f(@JU\u0004\nhl3i4kt/qx\u0017/^A\u0014+'t[-(\u000fږuu:o\r~UB~`\u0018?d\u0015zJd\u0002)k*AhSǼ뽓=[7ZU\u0014R͢B\b1#קsE7K:1dUj$qq'ͱ(vkd2\u001fC42%tv\u001cʯٙ|z,5\u000bsL68B\u00133h`AvnJ^\tru\\BJל1ҪMWN'\u0011Ynd\u000f/T\u0006ĝ(B6mAl\u001b}C[G@PiſOj\u000f%O%_?\u001c6Hbuf9E\u001bW^,\u000ec08)\u001fA/t\u0004,`IK\fpFQo_#݀E\u0015V^#\u0007eSl\u0006omv܄g\u0011ں(×3;>gm&!\u0007n=vNaS\u0016\u001dzO\u0006k?te(498\u0005T-O)f\u0016(g)\tƬ\u000f<aݔ\u000bC_E-#<X|\u0011*\u0018\u0006_x\u0018=ʌ\u0011n1\u0014e\u001bOp&\u000eb\tJ{E8XqQ\u001c/3\u0018\u0018\u001fҔYSaQ\u000b\u0019aH\b\u001eY#B\nYB6\u0016!\u000bvN@tL3}'աəYσ\u0003kxYˤ~'eog\u0016[,<SMוll\u0018:;z\u000fD$\n\u0014k䥾-U'3%I8#N\u0003l\u0016ב>H\u0005+\u0011>;t_Xn150_S1\u001d1sHnf\u001bI_\u0003iֹD\u00195pH,\u0017ڎ\u0015Sŕ\u0019\u00155\u0005ٚ{'.DX\u0010JonC,Ô>\f<c.VZB\fCt\u001b鿊K\u0005'_B6fZ\u0012\u0005>\u0015\u0015\u000b\u001fY?G^\u0011~\u0011%^7\u001fa1\u0007\nRߥ }\u001c\u0016\u001dX~Ļ\u0004g֫:I16\u001e5lܡ\"S\\\u0001PFF:\"&R;\u0014\b\u0019;e0+0%|ӫ\u0007E\u0015\bd\u0007}K\r*yy^,\u0003-y\u0004G=\u0019S;TMm]5(\u0011tpcC@ֆxf\u00056)6:j`By.Bv9/x\u001b<ܹ\u001dHs'%Xz6R\rAD;\b\\n\u0004MŜ97\u0014<\u0017a93&\\~Qҫ9?7BAo\u0019\u0010Tf@-|*N7ֹ\u0013lؤZ\u0016}eV\u0018\u000e&\u0013H\u001fֹ1J5\u00078P-=cBͧ2Krd#\r6A:\u0002#\u0000͐)\u0016\u0015@4\u0011 U\u0011\u0010n\u0002\u0001ͼ/\u001aDyc\u0011\rK604tE3R;-x\u0011ƚY|v\\_]:\u0014%\u0012V\u0019E,\u0012&\u001bP{h\u001b@\u0003 g\u0007  \u0007ȃMXɀ<2Na\u000b'zb\u00027\u000f\u0016\u0017\n\r2\u0003D\u0000\u0014\u000e \u0017[u\u0011z׳a``(\u0014\u0004S0\u0016o0y_\u001f\u001c^bM/_7f\\{,\u000f\u000f%\u0016P\u0005PW\u0001茙\u00014\u0014\u0001g\u0014\u000ehc_\u0005S\u001c.ճ\u0004\t6\u001c\u0001Zl\u0000M/1@\u0017sq\u0012 ^|VIV˰1@xI\u001c\u0018ȡ%ڶVo\u0000\u0015\u0003\u0005\u0002}Bj++\u0003`\u00190u\u0001<|8C(`V:\u0001tү/؀yD!`1`\u0019y\u0019I\u0001\u0001@D\u0003z\u001b\u0002fۻX>`W\u000fvK&bg+<B\u001a$\u0001f|*/us{Y\"\u000f\rfF\u0006|wb\u0005$\u0003X\u0000X0`W^\u001e!\u0006b\u0003\u001cɀӪ&]z\u000f6%N\u00070\u0001\u0006<\u0018$J5x\u0001H{,c\u0007\u0007s܎*3L1^\u0010ci|Mg#Bv\u0010Q]靶'|\u0006.\u0000\u0012ʸ\n[\u0006B֮\u0002O\" d\u0002r\u000fD`eB<\u0010]\r|g\u000eD\u0003\u0003QlX@)\u0010;\tr~,o}[.f/h4\u00126)(O\t!%^woC6k寊\nW'/ǡ\t*b\ri(\u001b s\u0007\u0011\u0006D0|\u001fِ@u\u001dPCQ\u001frb\b2(u:D\"\u0013=\u0016{$\u0014BhN2^&T_G\u001fWoM\u001f\u0002o?ҭ\u0000e^s@m4PX\u0019\u0001а\rhkb?\u0004>\u0000M0)\r48~/\u001f{\u0017f\u001bS__%W#|ݶq=Ūg;>M_=zx\u0018>!:\u001d\u000e7mէ\u0000`گku[yߣ?aeZ\u0007_9O7\b֗2b\u000b\u0003\u001cz\"{tSv\u001cuŕ+vj5/d=\u001f]:\u001c8[\u0017رQ3@L}~!yB3}\u001bu/S\u001d7G\u0002\u0007?Z\u000fg7\\Bx>(\u0019z\u0013?3Ǜ\u001d\"@\u000f}4 ZC,&lY`%ΚU\u001c\u0015)r\u0005^ߗ+y\u0015[\u000eUGln-;v\u000bg?^]T\u000f}\u0015u=y^:\u0000PUߊ]W\u0018y\u00177q^Hcg\u0013̸KtԔ)<\\\u0013'\fǫJ=.9V\u001fK$!)\u000ecn_-RNvy\u001b\u001b벭\\dVa6Ņ?kk~\t\u0017,\u001a\u0019S1'O˙ ɨ6sp-O#r\u0018$\u0007m1#̐?U\u0003.n'%fYWr_\u001bosu>3boꠗㅴ3MNs2A\u0006t43ˈ\u000f\taL$A\u0003霐O7\u0011{zN߅X\u0014A\u0007Y6m\u001f\\Z:\tɈC!\u0007C1\u000f/\r֩\u0006\u000e\u0013.P\bIXXv(}nx]\u001b\u0017y #[k\u001f_?P+\u0014!9f,ZtvHzðo憍6\n\u001aOV+_xr;p@l7\u0011fr07H\u0019zhxx\u0017N\u0010*Jkav|\b0?fL،9\u00130$k\"@%wjPQTLF`^!~bUWaG\u001aJu?\u001c\u0015?\u001c5?\\V\b\\87R\u0013,0^{޻]A\u001c\u0012#σB$i\u001fjEnƫTn=`QAѳۙNgYهcZѣr>{s\b%''\u0016\u0010z^y3;'-i'Ì\u0014jetS[?sHnAa\u001b֮kDz437\"Á)s\t\u000bY\u0005\u000bP\bTOpyx\u000b9\r an\u000ffN~\tNҳȗgm+[l/k&imhJס_\u0018\u0017xEa\u0004\u001d*4I\u000eHx\t0m,}_k?Uw\r1\u001a2*\u0015g8}\u001cRp+3]X*~2mMUa3Y[YdJ\u000eWzKJg97ǳh38ˊ\u0017`=&~|9d0wM\u0000\u0006*[\u001b%:l>I2?Pz]\u0013C\u001d^դھݴqYAik\u0014N\nIŅ\u0019\u001fG΍FV]UA^Ձ猴\u00105\u001aZW)ka\u0003}_6\u001eѨƎ\u0017\u0018lX\u0019\n\u001fQyL1~Z\\ts\tR::+\u0014qYѼIlYjŸύ\r\u001fPqO\u001f6\u0013]Н6\u000f\r*\njAU\u001c*\u0010*qSM\u000e`}Z\n*`Boߔ6S;!\u001a\u0003\n{~y@\u000eԀ\u000eewb-jxXsU:o{\n)V}8:>D&\u000ei!Vz`u\rmu\u0012e\u0015)ހ:d2]+@R4J\f<yKL>Ql\u0012OѼ$ǃ5!6R~,uo\u0002~;YGآ$c8\u0013'[=\\t6s\u00052eJM5^c]EIYY\u000eU\u00053>Myc\u00062Y6ҡ0<IL͊gƈ|d\t\u0012p\u0015&؂\u000bZ\\\u0007z{snk\u000e[\u000b =7-޾ėsGp\u001bYZ^i\u001d6|H\u0014u\u0014lg\u0000djt\b\u0002W\ny\u0003+\u00062\u0015n\u0013u/t07{&1t_'\u0000ϙY\u0012\u0007M3'sbO\u0013e/U=}2X{٘uc'\u001a<XUds+\u0001u)\u0004&*H4\"sǋ\"˖;j\u0004\u0016K:ym\u0000oy{/\u001co1v5^lYSY@E͋?\u0010yc\u0014Gc\bvc@K\b\"Cc\u000erM\u00192TZԓ~k,J؂'CnQG\u0005bWk*\u0003R<q#GR1\u0018d\u000f\u001b\b\u0003AGf&eOG/\u0016.\u0006V%tF7`4\\^ӫK|ݜ)x{:N'Dz g0\u001d?W^7O@P+UP\u0018gƖQ-\u0006.V9]]ԞaODĒU2<\u0016dtI2ڎ\f\u001a6п\u00186f@z[s]W\u0019nz*!;uA\u0017K}\u0001\u0015>up\u001dbg4wd-\f9Ί\f}JtK4q|a,bdl\u001fHp\u0011m_nF{\u0003p=㏁\"*i(ktF\u0013-^^\u0015)P;܊akV\u0010\u000e[τGI\u0019m,\u0007\u0001)]k/74)=?\u0010uo`q8yFg\u001cɷO*q\n~\u001aSo~\u0016lm$\tΏPko\u0015\tjXV\"R\u0005\u00153jc\",\u0003\u0018Q\u001b}]#Wrn\u000f\u001bĀe\\)\u000e\u0016&c\u0016\u0019\u0002PDdm\t]~'k,I\u0000x\"&iuND\u001b\u0017|\u0017!cDpnCp\u0003!QUO\u0011/\"(k4\u0013Ak\u001bV\u00153'\u0015h\b0.Dɹ9kUH\u000bϷa̴;pm:bi`aNMds\rO+[\biK!\u0018`\u000bnQ+Q|\u0017\u001c#\u001bg~ 4<\u0010:ek\u000ebv$\u000fuLdIbU*pZ9[e\u0012r}.2p#\u000b\u0011R=R^gFƞ@\u0005z\u001c'k~7)\u0000݋g6aUGуz\n\u0010ʽ\u0013Qu=?{nH~\u0015HH\u0010:W_\u000f\u001cЦcj\u0000(C\tϗ`Aʙ1)V\u001fg\u0007-\f&BA#W\u0017\u0011,͎=\\\u0012H\u0017OKا\u001fD\\r3g' fm)@Yxif\u001cؚsz\u0000ll\u0010\u0000\u0010\u000e\u001a`=\u0001\u0003~\"\u001542H \u0007ǌsб.\u0018%\u001a\u001e\u000bJBsK\u0019aTr\tn\u0014\b\"dl\u0005\u00144~\u001dY(\u0001f!'Y\u000e#\u000b82\u0000kfm\u0003\u0014G\u0002|9\u0002<l\u0000Zm\u0002x/}QjNZRWΉR \u0015vg'uew\u000f\u0019Qᘝ\u000f໫u!]wϢ\u00056J\u0003Ĳ>M\u0006\u0010\u001f풢\u0001d1p\u00142 J\u000bXfb\u0001$\u001eɀ\b\u0010O\u0000'\u0003V\u00034]\u0013T1ܪoJt{QjLl:T:ͪp<sZ&\u001ce\u0011\u001a\u0002r\u0001\u0001F)\u0005 \u0007(\u0002x{\u0002\u0012 @$Eb\u000f;\u0016;\u0003W\u0003/\n?]@E\u001b|\u0006T)7HE>m]W\u0017E!x\u0011\u0010\u0006@ݣ{.4\u001b=NMnֿz<I\u001bu\t\u0017fk@k\r\u0001N\u0007\u0015\fw\u0016\u0003L\u0001,z\b}\n\u0018'\u0001\u0015\b\n`kzL\u0001\u0010/\u00070Tv\u0017\u0000\u001b|R\bKٽ\u0018 \u00041]ᶣ']{\\?Ҿ\u001cA\nG>>ų\u0000zz\u001e\t!\u0000vMk\u0003\u0003\u000fp\u001cI47>r\u001cN5o\u001bY\"yw\ft\u0001\u001cC\u0002\u001cH=ns^xU(\u0019r?\u0010<)p-\bl\u000f8M\u001f\u0015LZ\u000b_\u0019\u0017VXKu\u0011\t\t\u0001\u0016G@\u00101\u0010\t\bU[Q-ť\u0005*=]1@mҿ\u001c\u0014)^\"\u0010ikIHL,\u0019JjʖP\u0015\u0007\r!R%ڿOmoWF8~=\t$b9\u0006R[\u00029\u0006@ƺ\f\u0005\u0003r\u0000:\t.;\u0002r\u00009~rvlk!A;aN4n\u001d37Wϥ2?\u001fW5_?7+\u0017OB\u0013ۮ\u0000j\u0007j/\u0003m5:@ݡ\u0007^\u0006\u001a/Gr)\u001e\u001a\no߇e~Sb\u0017D)h\u0011<%/ֶxNT&\u001eY[6gǭr\u000e\u000b7(WAtد&E12\b~\bϮ\u001f$\u0004@wDoÒ!ቻztيWR{fA33B\u001b\u0018D\u000e\u001c~usXuo׵:3^\u001d\rV\u0013<i>yֻ[k$!\rw 8\u001coxx:A]\u001fv\u0013fM wa^\u0007ف\n#cyv/REZ\u001dfZigVkX>CO몵+\u0016e2dC\u001cI8ˇP{59\"\u00153%D\u000el͟7Wdp,ɮ2\t26sc\u001f\u000e#r#ՒB?P\u001c\u001cm\n_kX5\u0018\u0012s\u001fm\r\u001azhQ7M|Uڭ\u00167r?x\u0013L*16^\u00193\u0007\u001am\u001e7\"\u0017=)\tў:s\u0006pY\u001bݫ~/zV:k\u00193wvՎg\u0017ٜO_w>\u001cZӓ?u]\u000eysuGVp{}\u0010TGwFIt\u0006\u0018L\u0007\u001dt:^v\u0010<v&tq+qVGx/Nֶ~Q\u0012C1s1[sk2mO\u001cuN13\u001fj.$\u0003p۝OǨ_v2r鹙V;}f^אp,uҵ8l\u0005ذ\u001d\u001f fq3`&lGz\r\u0019j\u0019$H,\u0006md\u0016WOY׏Z0\u0006\u0001r\u001dj>H+\u001av\u0013\u0004N?ܜ,\u001cm/uvȅ\u001fȤ\u0007{q̫u^ >Tpx-~C/5\u00124_wG.a\u001d^^lQͧy\r;jy`K^o]6{n̽r9\u0015g/.e\u0015M\u001fh\\\u001dK}\u0003Qi#mum\n\r`\fC#;voux^\u0003\u0001n\u0014j>&Ɛ\u001f3_-{<}\r[\u0002ŮCsWNk~G[J:}*)bn\u0006\u0015gc;\u000ffj\u0017Ǟ\u001fc\u0001:}%\u001e<\u001eyhSBwc,C-]A\\\u0005k+Xh1{{\f]9!:\u0003\u001c(+W/O\u0007è\\̺b(\b\u0013E).0O\u0018p\u0016\u00176d}E<[\u000eIծLS}\u0013O4\u001b't\u0019iBc&)mu\u001d>%B6S\u001aܣ4ڕՐF^UǼ~r6\u001c\u0017\u0015Z\u0016s-^\u001b\u000e6hJ\nͱ\u0005ͻ\u00179DJz\u0015+\n\u0006Ü\u0018oZܿɻĔyF\u0000fq1n\u0002+\u001acrP$>sGK\u00042l;vU(\u000e,+>\u001aɫ(/zՀUTfSޜG\u001f\u000b!-k}ʴ\u0019Ziu\u0007*%1c0nK`ȼ|ןjFVA\u0007)%;帗NnmW\u00160V$\u0018N#\u00053)QJI<@\u0012$]Z[l\u0011tf'U2.Ύ\u001b\rv\u0015/fK7V2\u0019\"5.ݰndrdQkX\u001bK{eTEM)@+i\u001crU2Q|9RVlH4i(LV\"3/5#b\u0015\nxŏ?&?\u0018֨Ct\u0010\u001aL;i lҲxzB\u001d\\5-,ղC\u000fťPP7&\u0013G3TDtNlBeE~$\\+@\u0010/.\u0013\u000f+Ý\u001bjB3JeV%f͎%/\u0014\"\u0011u\u001a\\I{[)SAb8li<Z\u001bA[+mІZh9?\\{ҾH\rU܊D?M?z<>\t\f\u0011$M\u000f!D7Oqݱe\u0019|Zqpaa\u0011\u0014Jϗ\u0019Dc*<U0\b \u0018D\u000fG?\u0015s\u001d\b`oѼ>\u0017\u001aʲw5Q\u001aJ]<\u001dƉn\u0016ԅ\u000e|]\u0000ǫ5\f`=3n'oޜ\r7bzDN\u0003ƬHC\";E\u001e6\u0014\u0015'\u000fj\rշ\u0006^\u0014ƌ|\u0010OD\u0001Ce%)-{xV$_yXvF,\u001aS\u001b.{ݟIdmɱ2L\u0011\u001d.ӸLԩ`\u000e(J 2$ky\"^5Bg\"\u001e5\u0014m8_z\u0014\u0016Tw%\u0019o\u000b\tx\u0011\u0017y>sՓ\\lb\u0004G|^\u000e.g\u0007b'O[X,`u8^+_fo\u001a\u001f}\"\t\u000e[\u0002yt\u001a\u0006\u0019\u001aqi=BxFk>@\u0001dZ\f>6({'l2\u0018J\u0016g\u0016\u0003}_:\u0014\r|ҽ*q5z&wg@\nPKjڗ¸D'׍~?\u001eKn\u0013&+gd0$v~K|VE|\u0018\u0001*7\\lZޢ\u0017XF\\R#QH;-C!\u0010\u000e\u0013hD\bt\u0014cD+N`5UPJܗ1 PY_pk G\u0007\u00132`\u000b v\nw.4kYv\u001f\u0010?\u001f\u0016\t\u000b\"/l\u0010f\u0014b\u0002,\u000f\u0012jᰍB;/*V\u0004Y\u0007B<\u00156t\\:&\u000b\bXA\u001a{e'\u0016K)K,\nRT\u0007lZ\u001cDau\u0006}\b\u000eq\u001cm\\~\u001fn.!%/-t*\u000eQk QXwy-VO\u0011\t\"\u001d~E\u001dP\u0005c\rg5\u0004s\u000eǐO\nϤ\u0019+t+\u0017G*WJ\nO<=F\u001dpb.ܠJry\u0007W\u0007#\u001b],r\u0015n\u0003V\u00104\u0006\u0002Ŭg\u0005a@yT\u0017h(\u0013\u001dΦ䀁\u0019cE=\u0015բ+\u00171$\u001c\u0014\u0004DQ̢(sZ^gZ\fB1ާhuI/`2HZ\u0019$\\a~)Uk0gq+{==\fj*6W{Zv\u0010?a[#Tڷ:\f2cb\"5\u0019Ěd\u001dX{\u0017v\u001aǢH\u001d]\"\u0019aw_g\u0005\u0003\u0007H\u001d/\u001br\f\u000eo\u0014^|1%`1^#\u0017*5-\u0000Gt+E#\tv}\u000b\u0005\u0012فX::ܹm04]ԱD\u001b\u0002v|r6ظ?\bи9BuH:0U#KPfONu?\u0010:f\u00060Se;\u0005ԣ\u0004Ӑ\u0001u\u0014\u001a:+B\u001aog\u001f$\r'?@8\u001fTr\\H\f\b?lRӁT#󑏵XCu\u0011)\u001fT\fJ=q\u0007Я(LGlt2X\u001cbi!`+\u0001\u0018R_\u0000BSIӀڀ~\u0010\u0013\rгy:\"\u0016\\P9J\u0016\u001e\u0006\u0003\u0006/-\fΦK?FlwnDԆm\ruYԐȖaۦw\\\u0016\u0001\u0019c95\u0001sC:2\u00039`\u001ev\u0019K\u001f\u0003Cʱ.`s\\;\u0016 AlIa\u0001+MHR\u001c`S\u001d\u000f0zFR\u0016kȴQz\u0012Yf\u001fε!Q.f6g/\u00014\u001d6`)>W;Y\u001e\u0018p\u0006X\u0000\u0001\u0017\\\u00017\u0000w?W\f\u000fS\u0004\u0013\u0016\u0003[,N\u001fm zxl:}#Ѩ}n\u001f+F(SLs\u000fc${\u000e!x\u0013.\u0000\u000e?\u0006|ۜu\u0001|\u0002\u0002= \u0000\b9\u0001\u0016(\n\u0003܊e=\u0007}\u0002a,@\b\u0006\u0010=\u0010)\u001e\b\r7\u0002w\u0000\\s\u0002eG_;\u001c-k>\u0007\u0017 B\u001e}2\r\u0002-\u0004%/m\u0006ǐ\u00187\u001c?C\u0011 9\u001aHLO\u0004R\u001974j@\u001acX?9\u000eS.A/\u0005R\u0004iR\u001fN\u0003\u0003?IS7ۆL#hgT\u0012E\u0014Rlч*`(@\u0010$uOO!\u000f@N\\\u0006:\u000edb@~=\tM2\u001d\u0012{(@AY\u0007o\u0002eNc\u0019܀(q@y\n\u0005b\u00148\u0000s@%+\\+B2.kԑ`0fz\u0015y&2\u001aW,}tOQI_\u001fpb\u0000\u001eOӿ\b\u00045&\t\u0005:\u0000ڬ'\u0011a\n\u0005d\u0001.\f{\u0005ƺM\u0013H\u00137\u0003AQ&DKȲo#ڞL飜]B|DXOIo*\u0012vD&ۄ&\r_|_t;o` \f\u0007\f\u0002C\u001f\u000f\u001f5`&4`#\u001ahVd`j?^տ4i$#$\u0019?F$ѶCf^\u0011.~U!]y\f\t|{\u001a\\7:^W*\u0003.ی_^=\u001f,\tM$\t_\u001c\u000f\u000b\u0018%4\t\tfE7NiLj\u0007Ttnܦ\u0015\u000e9rnK\u0007#'a!}\nuR=/{CD/;O=APK>n\u000bf7\u0000kM3_q\u001d_l<\u0001\u0015l}+\"J?)H>̂W\b۹r9lJi]MuoC^\u001eT3j<\u0012\u001f\u0019\u001b}e\u000b|exQԟ3RaM]b/s;07h\u000fU.w\b8uŭ$\u0019gg&ά+\u0013\u001dh]L<\u0000ʁ{czFGUBZ\r\u000f{\u001e3\b#ݿ\u0005i\u001fj0zNFID\\\u0012&x2Mb\u0006v\u0013 ՛jύ>Yt]7z\u001a}g\u001eB[}H_ާ\u001bW\u000fnׅp'X\u001aO?H{[}|Ua\u001b\u001cװut޼\rj\u001aQpu奕lN\bh#n:\f\u0002:oc֍\"\\}:\u0007E좣(漳*4\u001dzܷL\u0014\u001cj[ jֹՃZmL4oUho$݈,-_L}M6\u001e>j\u0013?0j.+6k^i: 7\u0013<\u001d_H\u001f/άa\u0003{Q$A{GpHL|-TRL܈\u001dzM\u0011U\u001a\u00115aԮpحCɰw/C\u0011/pyrU9\u0018~#3\u001eg*\u0005N>\u0013ˢ\u001fpmj掙ʄؿ4.:~@cf\rտԇŻ6-T#BeU~\u0015zȔ*s\u0017$\u001fڬ\u000fV:|Q1b\u001a\u001e(yx&!\nC \u0005%\u0005h'3w\u001fُ҅̉2#tփ\u00104>6&V:/\u0014\u0015Q&mM_śu-\u0005\u0007)UNU\t9\u000eYDCOMN\u0002>G\u000fD$\u00122kk~\u001a6ç50NaJ\u0012H_\u0013Gڡjuvjiã6㻛\n[\u001d.j\u0014tv14A{A3#g\u0005[TI`\u0018>\u000br\u0018 NuQH\u0017;lY\u00170ڌqkT+r\nfE_~gY}AJs\\u_F[nx=\u0017/7,Ԍǖ\u0005g\u0014\u0010_-~3-Q!y\u000fsb\u0016Sk7xcv3`[v^9K+vlw32\u0010xf7l14Ʃ@\\as\u0007%^CzhX,YLJ}#m>\rJ\u0007$7ܕj6b9AB\rSS;v+tk\u001dZ!AFy5@jG9p\bcy\u0003jf\u0019\u0002ӥ%LӤ+]?yZGgW\u0013Z\u0013K'4+\u0016G\u0013\u000f^q>y2G\u001ef\tu\u001a\u001e\u000e\\ʷBZzr5?DnZ~'4!u?6r@\u000b!SX\f\u00118J izڣm~\u0013un0/{xo\u0006j9NUc_^\u0013J\u001a-y\u0018,䨙Kc\u0007: ݄ňgip*e@_Tsu>ؗ~\u0010s83r&tzf\u0015\rt'V3[\tҫAfTn\u001b\u001aNuk%ҤA6ǩj+*ܐP{,\u0003ue\u001e1\u0010qSq \u0016\u001d+HZ]$Vj6(\u0010|vl\u00070Ͳ5\u0013w\u0006\u0016Nۮi8;y|P׎.դxfnV;\u0017[\fzC~`l(ҨS$G?UB\u001b85:\b\b\u0014Nmį˗@\u0010+E\u0013{)ܲ?\u0019~jbe&錑Zf)\u0015w\u001d7^\u000e^AFEyIdH~?k9\u001bY'9eV\u001e3\nR\u0012Rޒb~2XBR)\u001bm+hq+\tʞ\u0013v''L\u0010W~%|>n\\Q^\u0012=^ud\u0003\nc\u0014u?w~\u0010Mئ0Y<`ui\\\bRę?\u0005\u0013\u0007}\u0015=-*oV\u0013\f+\u001e'\u000ejV?L'$FJx-tZ\u0014s=\u0010s]6R\u001dJ܄-\u000f[?\u0015\fM̪(\u0010z݄HCԅ.wG-\u0005\u0010\u0015P@(Mx/yopWN\u0013\u0005Г\u0019\u0013.\u0006xgB\ngm>U=B}f6&v,a\u001a\u0004q۩rRIL?Hm\u001f;=2J\u000fOV\u001fO=}G\u001a\u0017iq4a\rt]<wչC\u001a\u0016?d\u0013u\u0006eU>2\u00110i\u0005\u0010f~=f:ӠR}FNv\u0007\t-U\u0012#gbW&M\u0012\fOdB|8ʆ[g.9tqW\u0016S;\t\fxg5N\u0016\u001bl2yV\u0014]﷘t4/8)͍zARPpΓj\u0012\\X!\u00187\u0015g\"H\tgf\u0007ꃯ4&Ӆgf9t\u000by\u0012\t4U(T\u0015S_y0X\fwLk:^N\nA\u0006ݯ\u001d\u001a\u0005jԦ*8\u001fBZF3\u0012'\u0016\u001bbqDIG˽K\u001a\u0003\tΤP6O\u0012\"\u001a\u001f\u001d\fox\u000e?@D:\u001e\u001b%\u0000-m\u0001bzK#\u0003'z{m`EJLFJ,r\u0004y\u0015\u001d5]g3#&/e8e\u0007A{\u0001\u0014=D'\u0003XqJ$\u001d-G *.Xb6jLrbĪ'_\u000e{Ŋ&\u0019#٧@%.Eh\u0018rYVrhe\u0015Q_#8Di\u0013j\u001d%\f\u001b'V>\u0003YW35\u0011\u0014\u001a@\u001f0W\u000f\u0014ZƱ|V&\u0010 |M͗u\u001c^(Kx\u000fnmߖ\u001dV-r'czY'K{t<jixyTp1a\u0003\u0013\u0010Ȏ&\u0004^j\n\u0006\u0014lv\u001e\nD,\u000f\u001dn\u0015%{\u000eH\u001bL\u0003R\u0017&\\\u0011H\u0012y;\u0011{8;FLy.\u001c JHx\u0013u,zzPNHb7p\u001e44B\n>U\u0018\\nf*_b\u0004y@*4\u0013Ke\u001ci\u0007(=eI\u0001*v2ү:2%D\u001f\u0002d+@e\u0018PPH\u0017\u000e\u000f?[]\u0013\u0011}~7mkl|{M$)Q6OY]*\u00195q44&\u000f\u001aXև\u0006>\u0013;\u000bh\u0012*\u0001Z2\u001a6\u0007Q,\u0019c,K\u0000hKfcY[\u0016\u001dq\u000b\u001cJ\u0000Z?\u0000-;@$\rh>꣊:\nTȺg(V/;\u0012E%I\u000fd,r\".hj˥\u0003-\u001bBe\u0004l\u0001\u0019)\u0016\u0000*z\r'W1`\u00060\r0<\nN\u0002L\u0003&lN9>`\u00010V7ـ\t˹|֥-8-\u0017s!m$/&|2}\u0013By@\u0016X\r;j>>lbkt,\u0017^\u0011\u001b\nq\u0002$\u0001G]&=]#'\u000fL%\u0000.+V\u0000'/ANi>\u0000Uf\u0013ph\n̉?\u00133\u00075\\@\u0015L\u000f>]Vȝ d\u001930\u0001|ϻع\u0004HX4axUk2\u0015W\u0013w/n\u0011E g9`\u0007\f1\u0002\u0001X.\u0010\u0018\u001dt\r\u0004\b\u0003\u0002\u000f\u00002R_*\u001fD~\u0010;\u0005JT05;EbcNlDk*3\u0012 \u000fÓYxK\u0005\u0010.X\u0016\b\u0017\n/\u0004Dr\u0007M}=]\u0000\"\u0000\t~@be qv$nx\u0006\u00123@u\u000fs\u0015@\u00045\nx뜓\b\u0007sY/+^ѩ\u0004rwM8_<r\f\u0005e\u001d?am\n~\u0013\t$!1&9\u000e\u0010?H|hg\"PA\u0007(5n\u001d!\u0005B]*x&]c\u0012PV\b\u0014m\u000f\u0003ˈ\u0019I-i\\M\f*!BF/4\u000b\u0007T<-oxrRA\\-h{W:o\u0013\\?\tA\u0011h\"\u0006l<\u0005\n\u0017\u0012Kc\u001e|\u0004tc\u000b\u0001݌o{x\u0000iQO\u001b\b]\u0007rO\u00006\u0017ɚV&`\u000f_˴4\"O/\u001bۯ6I^r\u0002Z\u001b\u0006^Zg<\\\u0003d^\u0016\u00188B\u0003 +\u001d0d\"Ra+V\u0013[o\u0013j+IF5nY0\u001f-\u0002b\u0012\u0004$X[c\u0006ǐ\u0000\u0007{n5\tUGW:4WIF칑:bN\u001fo\u0007Ia\u0013\u001c]Ǚ&kjx7\u0019!Ɉ݇\t^G>í\\~g\u001f|Sgq0GO\u00014'7w\u001dx\u000etsf?nDz۹\u0006\u001b\u001fu\u0015YV\r^B\u00129\fW,߀Y\u001ePN\u0011՗v-\u0018Xȁf}?d.wʄ[\"{\u001b:z\u000fh?Z5l\u0019\u0010o\u000b}w΍̬\u0013N20[9!&w1*3\tENIjZq]_?VG}yLI#\f\u00117MziD\u0013\t1c\u001fF68#n\u0014x98W@9j~(\u0017gQ7O{TsK8XU]ğk\u0013c~HF_ӷ\u0019&25:}f/0E_^a<NF@*7\"Bb>e;>:e\u001cS\b\u000e\r\u0011h\nϾyB\u0019f?Sn^b]=\u001f*>l\u0011xeL'gw's2C\u000f;|ޖZP\u0003X\u00022l:IS\u0016gT4L:ևNVf\u0013PhKGל\\ؒSYſSB_k_꿤v+Iy[8]3\u0018\u0013V\u0004w襞6ϭs=}k\u0002Y\u0007iD<0mnCMbe:/G\u000bUY\\V6rUZtC{=q^:G̱\u0002]\f>ULXڋjًgu^\u001f$'\u0011dRك1?g\u0018\u0004\\!A\u0005f8\fj3\u0012ʼ3My[i\u000f\u0003T:+\u0014t?t\u001c+{f\u000b\u0005+\f_6F#r^\u001e=,\u0017'#\u0017VМ_՜s{{џu\u0006Heį\u001aLuT]宻;ZmD u\u001aWVOPvoj<ɠ\u0018XE\u000e<LD\u0017\u0000S~{<ք]TrVBtZse\u001f\u0006dnX^<Γ\nR!\r}1\rq6͑X\u001cWJ\u0019Ir<ؠ\u0019}\u001euʂDG<|ĨT\u0018B\u0000-K]Kr .qx\u00079_F\"g\u000e!\u00126v\u001c(s\u0002'T\u0005go1M\u0013\u001b|iZ\u0018֛-Ö̀.[f!\f& \fwe\u0006˷_l.e<h\f\fR7Ӣ:=T\u000b湬;kK\u0006ZXԠ\u0010fp}MO{3/צy\u001f&z܌\u0001\u0003hfZp\u0019ҋ;lK/GS%[\u0018V^U4A\u001fo4\u0015e0-+VSsL\n%W\u0019d}\u0015rV!6ײ\u000fa\u0007|Cu\u000fect\fE2\u001b='\"mzui8x\u001b\u0000l\b>+Я;jodZL\u000eȏV{[{Nn\u001b&U~gjgх+U%zW\u000eH)\u001bicZU\u0018om`8/5ɼc3.nY4M\"ExL\u001disgYm5\n\u001fzi`\r9\u0012lx4Xo\u0012{q|8a\"*/\n\"j\u001dbnh\\\u0012Aٺt\u000b/Mm\u001c(+`y4f%J&L\u0010vf>\t3U\u0011ӥNHT+uZ;\u0010\u0017[\u0013{A=k|MUz|K\u0019fO\tDW\u000f\"Gd/\u001bC\u001a\u001a$$Y\u001f\u0011'P\u0017\u0013<\u0015cZ\u0005c\f\u0016yu;~\u0006:'ҩ:{6@)=·\u001c\u000elu[k#mPByiiu޹ZP4pj`46\u0019JZi˦u\u0000\u0006\u001di]mE\u0015^\u0005\u0014\u000f)FkTx\u0014\\Nw~\u0010\u000el#Xi4VLNl:?GpnKX-\bM}+\u001bƴ*鹥\u001d;^\u000bYU,)Zޔ$\u0003\u0011\u0012\\\u0017DUX\u0014\u0016]O(R@n\u0015_#ϼ\u001a/bq\u0012٦:em1\u001a/nu3BO3nHw\u001bϫ򃴺W*LӜlJ\u0016Z?\u0013֕nД~QqIΌ\u0013\",oCïr/w:\u000eWw\u0007?\b{\"_;V7檗\u0011F<KY:3\u000e\u001a+\u0006QbIJ ޞt#H/\u0015\bοB3*+#\u0013j+hTÊ/JӼ$!++\u000e%P\u0012͗/-;\u001d#,'Ny%ˬ|̵uS0:2нB\u001b$\u00062K\u001ek̙RD*\u001e'\u0013qǗ\u000bH\\=1cD\u001a|fK=HLߖ\u0001z\u0006z\u0006-gNrxF\u0012%W$\u000e!s 1ftbOf\\{}6j65P\u0003\u001af\u0017\u0014ddnx\rendstream\rendobj\r54 0 obj\r<</Length 65536>>stream\r\n\u0011s\"E\u0010s3W\u0019{\bgkOxCr[-\u0015o(Z{Ջ2k\f-njZ,(H\u0010<BIag#[ҙGB8gRpI䓮2h\u0012p%{ĈRm3\fX\u0005=E\u0011H\u0003TR\u000f\u0017$W9$h,;ď\u000euh#W9`S\u001e䯎R~.\\Mz\u0005y\b\"\u0014O,s\u0014\u001d\u000e\u0004e\u0001N͈#\u0016\u0014O&\u001a\u000eY?|8*.[hcTo\u001es%\u000b*-J0r)^%M\u0017\u000bz]qAtrR\u001dR\u0006g\u0007Dm\u000fe%3{IL\u00061.\tVUAF%\u0012˚W\u0006\nG\bɄ e]%Q fclTv%䊢\r=7\"DZsApw#\u0002Y(xXPJn\u0006)\nV`z)D)D\\NSG H\u0019a.wfDdAcaP'Ly\u000e\u000b\u0012ji\u0011=d&|xjdC\f\"\u0012/wT\f\u0013\u001a\u0018\\$\b#½mBB\u0003?,C\u0016\rRsr\u0002r\u0005}\u0002Q\u0001dkܗ\u0000?Na>>9!\u0011o\"N\u0018Lw$3I'h\u0007bN WĄJ \u000bL\u0007Aȧа/\u0000ߔcY\u001b\u0018`XZ,\u001e \u0002\u0010\r\u0010k\u0000h\u0001ĸ\u0004$\u0001ĔG&zF\u0005\u0010Qv\u0007FH~!)\u001d\rrOK\nbԤ<\b<9]l݌ߗR%g.EϨG#!)Qp`\u0014\u0004/\u000e6\u0017tr,\u0017\r5\u0002dQe\u0004d\u001b\u00002B(@l,6 [\u0003 \u0006dW\u0005dx\"@A\u0007d\u001dO<w7xhFu\u0014km1kUO÷(J@(a3\u001e\u0006\u0014f\u00012T5\r(\u0002\u001f\u0001\u0015<+\u001a\u0019X\u0006\u0013@o\u0007vj\\\u0000jprz=@\u000b\"Z\u0004Tm\u0001ſR0v\u00132\u001fc@\u0007䂙CHʿ\u0006/\u0012v\u001d.Fx\u0016N[iڗ'O\u0015\u001a#\u0019,EI\u0000Y\u0012\u0001M\n0\u0003h\u0000ڃ\nG[-@?\u001f\u0003`ٯ-xz\u0005Bb\u0019ş|_.u@o_Cx\u0002н\u0005'}c\u000by|GBJ4.Sn[weAۃN\u0016~W-\u0013B'\u0010h\u001f\fp\u0005Ms\u0019J_\u0001\u000b\u001d*>`\f\u0001|\u0000\u0012\u0003vT5\u0001ہj,\u0017\r\u0007\b`km\u0007`\u0002,$\u0005\u0006Es jR\\M]ɩ\u0011ԦYRv\u0007\u000fS!ERܿyrv_\u0006\u0000w֚ó-em]uc\u0015\u0001\tr&a\u0000.\u0003|mz\u0004|\u0000}g+\u001b)\u0013:7@\u000e\u0019ּݏ\u0003\b\u000eа}l\\\u00077R'\u000b\"'N\u0000?rg̷pǁKp\u000b\u0010^\u000f\u0010\u001f\u001c\u0000\u0002\u0000✜\u00031\fT Z\u001d ;\u0010%g7d\u0004F1v\u000buguA\b\u001b\u001c\fq\u001b'Eɉ\u000b81\u0000z\u0007?4MPTO|¯e G,P0\u001cK\u0007\n\u001c?=\u001d c wF(y\u0001=\u001aˉz\u000f.þ+E\u0015#\u0016(6[l2\u00107&}\u0007淨\u0007P&8&\\6韖tM2\f\u0007i\u0016\u0001\n\u0016\\\u0007Z\u0000\u001d&DU&Ъ\u0013h5T\u0011״Ӆa6\u0007\u001bq3A\u0010wBm&_<'!)?\u0004&[jr)V 3\u000f\u0011\f\u0018\u000b2^e\u00042\u0007dZ5\u000bd\u0018dd6\"w51&\bucTb9uiA\u0018mfX\u0013vWx\u001aӮ\u0018\u0003*u\t\bkF4\u0017kz^*HShZgIawk]\u001dDOpú^iz!Ai\u0007&9Y\\Wbk{ܭVN܎7~\u001e\u0005\u0003\u000e\u0011 !\u0011{۹)\u00076\u0014V2\u001d,v,Ba+$(9\tJNKphb\u0011\n}\fȵt\u000b\u0011A/Y\u001e\u0005C}~[\u001fd5p\u0000Ֆ\nj-BәG-}̺Ai\u0005'^W9\u001b\u001dm06P~(\u001e\u001e9C\u0007ʵ\u000e%G}\u001d\u0010͓P}W'݄\rGm>\\5RRO׋0>_=fPL\u00124^Y9luur-\u0014f(nh~\u0010pԿ5\b_x\u001fE>=ܳ>vׅ;pCbe:>\u0018q=8I\u0016H**,a'ePu9yDhcz2l\\Z\u0014\u0006XjX'2^z.]\u0017\u0019-CbtsL\u001f6\u0004i\u00024o]DiӈvFu\u001bo~s+XCV7Vu:Zƍ,\u000e\u0001O\nP\u001d¹e}:+7\rE\tos\u001b\u000b\u000e\u001al)F\u0019j\rKG\rϯ^>:45\u0017T\u001dW=:ZVVɾB\u001fϏrU!Q\u0010/N<:v%\u0015qVU/bxrovMhmg\u001f\u0003qwY6afV\u001ffUmC5\u0017\u0015չ=\u001eY+r(o\u0005̝\u000b\b/+ҹʖw+W\r\u0006b\u001a~\u0010/r7mđQaX6\u0005h|'\u0014GOEÝ\u0007R4/;\u001fILq=[y$a#\u001a:\u0013\u0015\u001eCk s씔\u0019\u0015oQuZL{&GD&°0y\u0016lbO\u001dw\u000bGs=\u0011H.qf9_lg۵KN5\u0013\u0005a\r;w-fg\u000fb\u0005ni\u0005>\u001c\u001a+\t\"H\u0005fPNz)Ц8O<])@w+x;jRQΗhCUw!\u001eY\u0012hi,\u0015\u0019edJ3L4v\u001caKـ\u0018i@7l@wm\u001fK+:}%P9$\u0007w|e\\Şڿ*iu]Z7r~&;`:}\u001b=\u000fVy+neKF6Cl\u001a#3*#ӤZ\u001bcX\u000bбrLCd\\F!!tW}C-g3m\u000bE>}vv'8׺խJURb/\b]칖eSLU\u0007\u0003H$9_I.TcX^\u001bs\u0006t\u0019W+\u00194M{7W\\íΈV\u001da@\u001dV\u001bHS%.)S\n܉A\r.>]ᶖuh\u0013aTc g\u0014TF5\u0012?mí8\rx\u00031Tf1i)dGYJ/&W]K/3]Wg\u0015ڮ{k5\u0003\u0015W:Ue(npV#w0)glOsIJF$ΧhuRDiMD\"`%:aT\u000fV+\u0013qwu[i\f\\sf2\u0017)>oz\u0002W\u0007oRgmjӔpDS'RVoy_fC~.#݂@QR*t?0e\u0001y~\u001eBZZ[@8WѲ5\u0019s0U\rʖj<zSB@A:/I;\u0014\u001cF=+W\\m\u001d\u0007Gj\u0005H[ґ[\u0018\u000f$@Ǻ>wϠ*H+R\u0016\u001d)r0B\u001bxK\u001d\r6϶qacŜi-\b6i\u0013L,X8ΚQJJŃ)adoN5fHO<\u0010gi%tl\u0016d'}t\u001a\u0006AHsbnd\"Z\u001bBa_\u0010\u000f<~ej\u000fRmnP\u0003<\r\ns[`\u0018ҡ5(\u000f\u00103EX@EzN\u0013:~L\u001b6\n@쮁߳\u0017[A\fwE8NVu\"6_Fk6{d\u0017\u0004o\u0011=ρ0\u000f@o4?\u0002\u0010mWUR=+>\u000eFLBfgtk~\u0010%I\f\f\u0005]{攘|obR\u0014J\rH{SvRǈէ\u00187\\پ.gIxr\u000fl\u001e\u0004w\n5 H9ܓ\t\u0001`JİM 3\u0017fbԓVFo\u000e,T?l)CwpbZK\u0004v*\n8y<us^\u001e#\u0002۲\u001a<T_$\u001c}*Vi&YAr\u0019%bO\u00036j\u0017{\u001cp\u000fV$&Fߏi}dCz\u0018oy*[+(HY\u001a\u0010xE\u0005_b\u0016Sť\u0010\u000fh-~\\aw\u001ac:KQ+n]:t?b\u0012_cVhrJ`y1Q\u0002%(ORls\u0018rE\u0018Be70N:<C:OI$։\u0017D\u0017ePK\u001cũgaU\tݏ>\u000fsu\u0019\u00151!@\u0015Q`@\u0014$EZZo\nĿl^<\u0016V&\u001c3K'[ɬ֚XAXr-g\u0010ʞ2aѶt\\X\u0012H\u0014\u0019\u0001P\"\u0004!\t\u0014Xv`\u0005\"Ufq\u001es/\u0014\u0015#zl\u0001D\u0000k\u0001\u001e{ޏP)P\u0003`\u001a~0)e\u001akno~fNo\u000b-\u0005F\u001a;h#M)H>9~bUIn\u001eE\u001b2\u0019T@% yEH%De\u0016|\u001dQy]Bs\tN\r{9+\u0005}\u0001p\u001a\u0003L¨v05sb]8-g55є\u0013XT\u001eOےr\u001a?asdbO'F?i\u001f&{xRM\u0003:\u0010`ni8܅\u001c\u0006NO2r\u0006..\u0004Zd55Rn\n\u000e\u0019p_3\u0006\u001e\u0016+!m\u0000,ط\u0000n\u0001\u0019q\u0000\u001b\u0000Dl\u0016I\ne[ZD\u0014叩ZVo:w\u0015:G3\u0016>\u0007\f\u0003|^X\u0017TIODõ\u0014X\u0004J\bB+\u0001W\u0003˱䳱L\u0000OA,\u0014\u0019\u001c\u0010\u00073\u0001n\n\u001dK\u0003\u0015 \u0002XƫDwe?f4JWTK\r-\u0007|\u000f\u001a_E\"<\u001469NN6#sʌBZ\r\rh*BOXce\u0012)}\u0019ljj\u0003\u0002ʱ׵\u0000\u0004S\u0001\u0002@fOf\u000f/\u0002\u0002\u001b\u00118A71\u001c\u001bRIRA1\u0014\u001cI(&\u0018;\bS\b~t\u0000\u001a\f\u000f\u0014 )4\u0016*a\u0000hJx]\f@|,Z,\b\u0010\u001fk\u001d\tHPb\u0001b/\u0010\u0010\u0013\u0010m\u0006\u0010\u0007![g\"V\u001f\u0015w\u0019\u001bj4\u0017\u0017\b$j\u0003rl#bHaǑ\u0002A\u0011\u0006YO/T.Sx@G\u0019SX\u0007ݶ\u0001\u0005\u000fKb \u0018Pf\u0007(\u0002<D@a\" \u0004\u001f;\u0005ȋe\u0003r\u0003rG\u00131[<O\u000bhv@vg\u0015\f5\u0016;\nQʠ\u0002&\u001a\f\u0012Ji\u001a65Ja.\u001eo\u0001\n꓀R4|\u0003*\u0014@\u0006\u0013\u0007\u0003iԿ\f\u001b\u0000]Lc)_\u0000]Jatu@j\u0015\u000e\u0002\u0001ͽ=q\u0001\u0005\r7\u001cM[w%ypV51\"s%A'$u\u001abqQ\u0004h\u0002\u001el\t\u0018N\u0003F/\u001aBB)`\u001e\u0001,f\u00016`P;Kz\u001b\u001e0E-~It6q\u0004g8|ӮLFqg*c.\u001eIIdJ\u0006B\u0007OIy\u00172זX\u0019\u0011\tmxpw6\u0000\\f:\u0000\\\u001d\u0003n\u0001ϞL\"x<\u0001N\u0000wZ<\u0000\u001bM<aJb>\bcL\u001d?-zM\u000f'Mr1`\u000e(y\u000fOƥ?$(9s\u001c/~`\"z\u0002¢I\u0012to8\u0010%9\u000bD\u0001lH^0 R<\u0010nx@{P@\u001e\u0010\u001a\u0016n''4\u0017\\{\u001bR*\u0005JLʩT'%}uR_\u001fpb\bڹG\u0001YT G]\u0007\u000b\u0011|\u0006A\t䀖lWc\u0017 \u0019\u0015H<`\u000eVƟv-\u0003E9~#$>_\u0010C%\u0006J|)\u001b_rll^/xr$̾oM\u0015cy\u0019h\u0004\\\u0001\r2@0P{S\u0015P\u0017;Qvo<.dJW2\u001as\u0011h\u0001\u0011?%(_mِ7n/Mܶߔ4nۢ0\u0006\f2xtK0-\f8}{\u0004a\u0000dX\u00022\u001c\u0003W?Y\u0003I2'#6iA\u0012m~\u001d\u001c\u001b`L?\reFOvGYW/]zq>LǛ\u0007\u000eQ\u000f%D!$?y#n'ӿ_\u001c@Agv\u0012\u0018=z7.\u000e/[\u0015\u000f\u0014cFӋ?SPݻ~oV\u0019\u0019ZW!X50YX\u0006c,C47`4/l:ɺZjzJVpN\u0006~d!n,}Z\ntR3\u0018'yomKf57s3\u0016i-΍#_\rxv2ѱ\u0014\u0003|o#x-oC\u001cFx%%]ߕ\u0004&k-nSc7٧Ϭu\u0004\u000e \u0013<ex\\xou\u0013s\u001a\"5>]Y4u!U\tmĢu|jjW884s@\\v~\u0005[F?o\u0007d\u00117\f!1&}~sW8tx@\\\u0018qiOa:US9$F^΂vuCu6r\f͡׆\t\u001e0GuhnI5\u001c8y\u0005iVCwY\u000f}\u001bYT:\u0019ϷDkݘAM_\u001fK<\t\\A:>\u001a\u001d\u0006[\\\u00197\u0000\u001aϮ7L\u000fT&5b5׿JlnQR\u001f\u0017\u001fa)0m\u0004)\"_l'{&i\u0016\u000b,\f\u00151+бO\u0015}`j_?(Pj[ʩ=}:/\u0010Ae\u0013Qy[\fU\u000f\u0007[QR^ֻ\u0018fmN\u0017<3\u0006_\u0018zU`les^\\rvk\u001fS5\u000bçX>L\u0017M 2$R\u001fr\u0016 $J,Ah2~Iyt^dkg\u000b6U֌˻tΫK\u001cܪ8l;S\u001f໗؍,NY1+XAIgov>\u001bzܘS3\u0007u^j\u0012~\u0010r\u0006\u0007rN&L`Gh>T/\u001a0e#[\u001f鹟\t<\u0004H5\u0011{tA\u0015f+׊=7ɧ\u0003WUl\u001b'=\u001dxZ~lԩJ|'ʧ\u000f[M^'Z3i\u0011Z7\u0011.QfS/dVްT{= tSJ\u0000\\N4\n)`?\u0012\u000e\u000f+vErLr\u0001esrAP^\u0012N\\ѣ}2}B3,)ia#:9/ZdoXjg72Ie\rMI@tšnt^uĶ]Y\u0003}fgąO\u0018\u000b&#VKsuZ\u0014\u0007)󺋷v1\rmZʫfZ|e\u001a\u000f+\\\u001aFZɭK\u0017<\u001cCV=I<%;Ms\tYwC]]0g͆\u001b)ݍx~cjI&\u0013Sp`汪N4bl\u00173#ܯwF\u0006nH}\\gy\u0013\u0006ڤߺj)wj)ن\u001e<j.L\u0015g)0\u001cC̑@?\u000e'vfRdqtIKSydl\\xpnݪIts+#ҽ4Ҧ\\lv͓݁J\u000fcv\u001fR)bu@9&r\\ќk\u0006v$,jVftX0M[^\u00153E,2;Mhvv٩Xnqap$'Ht>HZRsVCe@)\u000bwcG2i#q\u0017\u0012/%6wp{p\u001b\u0015{bQ\u000fY30+J2^']*k2-X`I1橏įzbyX*fD\u0019\\VLOTROU6f\u0010WaP\\Y!eiSJ\r;\u0015/^4.SU^=\u0004?pM=\n`)ܸ*]\r3~P }2ceӠ\u0012\u001bӶ\u0012o\u0001\u0018\u001bQ|U2lZ[CUeENRXO(/tG򐏰̚w;QLK6g\u000e;\u000b\u000fRz,7Y~\u0012Kf|Ys\\ڝN^<t\u0012I<\u001b*\u001f6_\u0015a:\u0001Vr}NT!iCW}Mm0\u001e<sr{\u001bָI,qHXBR+\u0014d\n]+\u000b*\u0015\u0019Z8tY\f}z6dYrVʋɝnڵ'&=\u000fV\f.i\u001f%-bӏB8nBF=w*pA&S`s$1[-Fk~)3'\u001c\u0012\u0001\u0006U˔II\u001d3SZ\u001f^x{\u0015%\u00186E{]5[o8-{\u0012\b+\u000fA\u0017}\u001e\u000e\u0000\\)K\\j˽8l*r,/JL}Hл2(\u0015nRzmL@)\u0002F6Nj\r\u000fIt\u0012CtL:EZ&oVb3J\u0003t-\"O\u00133N]\u0017(B\u0011\u0017t.xίB_84߰2\u0014dxw\u0017+-U%3QP9O9'Ԉ4J=ko\"V(Sp\u0019`c=ŝl&JfIJhT\u000bTk:VQ\u0016\u0006&W\\JoPx\u000bG.;YƬl\u0018VӕWB\u001djR\u001bR\u0003#[\n)-hk!C\u0015X\u001c\u0017 [Xc6ĒŃYm\u0004&\u0006ָ\u0002rWA\u0006`<=\u0017Go9Ų\u0019\u00191\u00121\u0006HVKw-vPp˓%.C掖^\u001d\u0019\u0013ٚn<j~jF\u0011E\u0007wݮa(Wp\u0004m\nL\f,@\trZ=@ux\\\u0000O=@\u0019\u000fFK2&\u0012MǷ+\u00076g>\u000b\u0005߼d# $待g\u0013#\u0007)Ӏ\u001c6;\u00136\u001e~S\u0002&\u0015G\u0019yå\u0001u͈lb\u0006R\u0016J\u00074FϠ\fS<\u001eT\u001ae\b.\u0002ԙB\u0001\u000eҗXo3ɏ(g7\u0005_t\bk\u001f=>L,{c6WpHib@\u0013\u0003agrW\u001c\r,\r\u0003\u0003\r@)1P\n\rrfuң\u0002Jx\u0007'\u0000zROu)\u0006\u0006Z\u00049mY>\u001bV\u0006.l.I&3!AOpɲ\rNׄ˓ř\u0013aGlZ0.~<!\u0007`$\rX\u0000Lz\u0003*\u0019P*\t(\u0012`jV\u0017j\r\u0004p4\u0000&)\u00020]\u0001&ѧ\u0000cF_BX_HȖ۳\u0019eY=s9P}k;>S|,\u0002\u0010Z[\u000f)\u000f׽C\f\u000e\u00014\u0001+\r\u0000`d\u00026\u0011\u0001[ĠҀ-YU(!`\u001e\u0003tF\u0003lƀO\u000e*\u0001\u0006\u000bX⮚QhՍϩV\u00045ƀ\u0017|OkC~A̛xb'\u0007X\u001b`\u001dG\u0001\u0005ָ&a\u0004\u000f85\b\r9\u000fpr\u0001\u0001׀k̾D\u0004\n\u0017\u000bp\u0005|*;\u0002j7\u0004p\u0005qLgh.{ySw\u00170b5m>D\u0004I\u0019\u001dA\f\u0015\f\u001b-\u0016=>\u0014\t\u0007\\!\t.\u0017xg\u0005\u0012\u0003|\u0001~2\u0002\u0001\b5(>o\u0015;'\u0007\t_rHu\u0001\u001b-\u0017)'\u0017uxsǛ^nhU__轂R\u00176&$\u0004>!7e\u0016tp\u001fg\u0006\u001c`5\u001d\u000fOn\u0003\u0019[Qo\t|k~]I+\u0000QnՁXw8O/؛\u001e؇\u0017րOX\u0010\r\u000f\u0010M2\u0001DBY\u0002ك[<\u0006NK\u0006\u000et$ufϸ8\u000e\u0017+\bPdP,\u001d\u0014%)}\u001f\u0003Wj\u0002\u001c\u0002y,<H\u001dܾ\u0005 \u000f\u0003m} '-7\u0003d\t\u0014\u0014Q\u0001΃$\u0004Vu\\_\u001a\u001dʖ+B\nd\u0003񨘐t\b\bjOĆo4\u0005\u0018[|x\u0015a\u0004u\u0005\rUӪqd\u0019\u00183.\u0013\u0015@\u0019\u000f\u000b,Wp<V檂][d4*Q<'8[o n\fɨ\u0010T\u0003B#mgSd.%`x1\u001b\u0018]\u0001\u0018M\u00075\u0000FrH\u0003êA\u0016@?UhUK%ғʏ\u0016x4;jZɨu\u0010ހ@\u0018E%]5_\r߸ݿy\"/1ںqm3\u0016g\u001fX\u0002z`\u0000+\u0002W)Ts;!\r\u001e^(I\u0019\u0001C.`ހJm[|}\u0017\u0004\u0014uR\u0012dhbm=p\u0018\u0005N\u0006W\u0004\u0004,C\u0001Wq'\u0005ۖh_\b(#Ur\u001fh<Bم(\u001e>grd\u001es?S\tq\u001as\u000b\u0018\u001cWTjSu\u000e\u0014DSCE\u0003ЉvKO}h?C9h\b\u0003w]/=\u0002^\t\u0017Zd\u0007k<>4q\"a޶A>¨~ܞ2Z(aŬL[Ncr1w\u0013* VC\"Z@1nں\u000f뿡a~9舉^;4g\u000e\tvY|S7z'rO}xp\u0016gڞtbNҙY\u00155&]JZLGas\u001fFs\u0019%A\n6YF(XT\u0017Zu\nPd\u0010E\u0016\f|\u0017\u001bW\u0017i\u0003>x\u0016װL-f]do6g)`3\nsq.|g1[ew]n˱RW~Ȏ|mzη1\f\u0007u\u0006\u001e\u000f3Q1\"\bV]AL\u0014řUvH*#7uu|l>5\u001eRUri\u000f\u001ej=vڝ\u0018%ڧ5ӺAeނJ\u0017hmCk|&Q#Efy.ԩX+򳺭gpY\u0019%ʧrT>w\u0006\u001f\u0012YV\u000b2eGRZW\f\u000f9k\u0011m\u001f\fl\u0004n3f_g\u0013\u0003\u0000\u0015\u0016]VZ|%h$_!˾7K~&^j;D1\u001cW3^rP*DYїA~RbVy<rڝQ]Sl!33ewh&:3\bv\u0016n_jѯnK[\u001bDԎ*pQ)\u001cB4\u0017a:c>\u0016y9\u001bC*ʮMKv3;|l.?3\u001dѱ^Ix. i15,\u0011nI\u001d+?+}\nBh\fҵs(\u0014<떝]Ue+\u00057S5)\u0019\u0016ϥN\feLA7u\u001a,G)3&۩2i\u0011m\"\\\\\t\\hΣ\u0011>\\r8vdΡ#^\r\u0015{5&?$G\u0015t\"\u001a\u0010\\O2µN}EH^Gg6\u0011\u0016|¦֊\u0017v7,cްH'<W\u0014ݔlU]_u\u001cV\u0018ګ?\u000b&\u001d\u001b=\"X-]Sb\nI[UcE5t\u0017-].[˯\b;$\bͣ\\jw\u001e\u001cm4\u001f2j⁭Y\u0019Mӗ37_\u000eu59f!G-^X01\u0005gri-?4,.v?1-~6\u0000\\\u000eZ\u001aӣBч\u0019\u000ecv>\u001aMOGmx1M\u0013.qsh?r(=bAjf\u000fi፷y]H(\u0011oZl(\u0019\u000e׍^ёuaCK랖,jkM˾aKu>լ$T\u001aLe5UBT8$+\u001c}cRm\u001f*Rneg&9,7=\n6{15k;X͘9\u001bv2zWlGApՇC}.4LP\u0014~Hu\u00155k,z<e5\u0014\u000e\u000bjvNr6.J.')=!\u000e7P+M`0:1>HycM:\u001a\u0006fvpGm\u001aZ:;\f4=<iD?\u000bvULe\u0014N#\\5#＇$W0B\u000e\u00198BSvZRNԷ]Q\u001fRKW>\f\u0018u]\u000e\u0006o?{5\b{\r\u0005\fJUmMd{]M\u00197C\f'nY]fʌ\n[\b\u000bR3}Uu+\u0005*K\u001d#\")^>/6kU4\u0011)!V|wxgp]pcxpXzΰd3Kgr\u000evdDPn\u0011(Wʉ\u0013w\u001dV?(1-y\u001e{8\\pk88,\u0006;]Hn#^Xhw\u0017\u0007eyLm\r\u0007VZG\u0012[&K.S&ϬNtI<ԾSU\bV}Bs+\u001ad%}ԓc\u000bl\rO\u001bc+Q)(U{'iJlMsѴ*3H̄8^Mn\u000fJ#\n\u001b7\".iq\u000e{=Y6d\u0012`wU2\ftE}Xw\u0017\u0014\u001c\fcdc\"WI-ܐZFr\u0016I/U\u0005wn\u000e|lfեy~\u0014&QVV4'#s>r\t6ߣ\u001f\u001b\u001c\u000e5;=Y'*:wfe?\fm6\u0011R6h\u001a߬R1$}ޓ\u0000k`\u0010f\u0018>^a_O\u0010j\u0001~~\u0016)s;Z9\u001eٴ\u000b\f~L F\u001f:\u00197Ibc\u000el\u0016\u00051+b8p@3\u0016)\u0015\u001cOy\u0002X\u001f\r=RϤčZ\bH\u0007{vSẗÀ``^ZuᴙoJ;is]1J>'I\\\u001bE/R\u00077yla&cc\u001186'xH@uH:Ė\u001bJ\u0019wP.gCə\u0018,q\fT:nl3yܾ%(6a`}WI\u0011\u000fY*\u00030\u0002D\u0000A:P\ffI\u00002\u001fx%f\u001e-dTʇ|$U|\u0007je\u00114c}pxD\u001d*%x)YFwMܮ-iw\u000fDZ\u0018\u0001N`oV\u0013D9i`8Nt^\u0005\u001e\u0003R'P\u000e\" v\u000eBi\u0006Hb\u0003,\u0001\u0014ҧCzD\u0019`\u0019#\u0007\u0013\u0011\u000fdys\u001f\u001d7e+6\u001bJsHݧxk(U*沵 :\u001a\u001f\r'X\u001eL@\u0006~Ǖ<`\u00005(Y5() W\u001dkZ\u0006T\u0004x\u0002dT\u001cʣMYٌu[,}<\n*\u0010ycFb\u001a^\u00058=\u001e\u0006,\u000e;vQʭMQlJ躭%Z\r̹[@\rL\u0000\u0005Y)s\u0001T堔\f(4҉\u0006\u001cP\u0003P~yU\u0001p\u0013złPR4PzNMmq_\n\u0012#\u0011Mn\u001c9Yu^ӕ3\u001a}A9\u001dt.-H\fk\u0000\u0014ad\u0000K\f\t\u000fK@\bP\u001695\u000be\u00024o\u0000\"@\u0013\u0007\u0006,Y9\u0002t\u0000t\u0011YҝwOz1\u0016;\u000f\u0004\u0004Żi~fxbtOW\u0015gC54%\u0011_.a+~Z\u000b0K@\rF\u0000\u00023\u0004@Pʗ'$\u0007J\u00003х҆﹘EW*\u0006\r\n^\nK] ϲikgԴ@É\u0014擠}g.}s{Ҽ;<:7:[\u000b@\u001fZ\u001e\u00000\u0002t\tJ\u0003\u0004\u001d\u00138\u0006Q\u00120!]\u0005LP\u001b\u0002w\u001c\u0004`%\u00070w>3Fi]ˀ)ﷀI\u001d\u0013Qo'8a*U%J\u0012ܬt\b\u0013~vKl\u001c0zÒ;\u0001VÜ\u0000s3.'ן6\u00007\u0005ؑ\u0003\u0000G\u001c1\u0016\fo\u000f5ҽ\u00001PIocox\u0005~\n\fcE+I\u001e]Њe1҈2\u001fQ\u000b|\u0013oQ?uoX\b\u0006۬5D/\u0003n\u0003@V\fl68\u0011\u0017\t(\u000fx\u0004ܧ\u0006}[V&D^4_P;/nM[jwZ\n?\tW,\u0004l\u001f♳8vDs[\f\u00150\u001f\u001c\u0019\u000b\u000b\u001e o\u0019@p'.\u0010T\u000e\bQ\n\u0007DE]@\u0019]H\u001c\u0005k\u0006\u0007,)}Io-\u0003y@вo6uvWl\u0016F\u0016s\fE3e4\u0001'j\u000b~]\"IBl\u0004\u00171S'K772\u0004X\u00019:\u0003\u0019\u000e@-\u0005\\\u0001ҽ:\u0000R܁wb@jC/RPzHVje`g1qT!im\u001fċ+\u0018}/<\u001bP?߯\u0016o>-Z:R[\u000eˈzaen`N&P˻-Pc\u001d\n\u0003ʹ\u0002\u0003B\ful»R&(pP3<{֟vB\u0016(@!\u000bOp|N׿ymM5t\u001bI\u0001\tHf\u0010\u0007P\u0007\u0004zp^a\u0003]L\bSժ1G+=FLӈ'\u0012r7E\r\bݢB7\u00161oJ¯Icv\u0015\u001a\u0005y\r=\u001c5+9`9r\u001e\r,6^\u0000mt\u001c?>\u0004!ۦzRE\u0016'vBmzP)m,~ݶ1u^Ͷ5\u0005xq,pT\u00028@\u0003{\u000el`g_'??\u0017h\b\nX\u0004ٲP[ퟣ!~<'ċcAU[d?VJw3o``_8}1\u00179y9d./Nn\u001d6J\u0019\u0014k\u000bF\u0014f]cȣ9H\u001cx&a\u0016Ӟ#[\\=z&h\u001c_Ӑ]wC\\fF\u001aObuO<^VC^&\u001f8ȼ֜(f̓EU\u0010o3E\u000bx}1U\b\"9-\np@9>;y<âY\re\u0006_&wjyy=\u0013fX\t>Z\u001dgF?.K{Fl\u0002Ω%g[rBw[\u001d\u0006\"P;\u001fo)h\u0012?2]M\u001b@LtV\u001ciySn\\yvs\u0014։0j\u0015y07V.n;A~ȇY3e\u0017ղrg~\u00186M9<*\u000e\u0011blf\u000bH!\"mj\u001b\\-\u000fС{\u0010q얩ɹ#aTȶ/B\u0013jgL?\u001a\u0000\u0019\u0012\u0014~Ns\u001fڪ\u0003~+e\u0005\fYWjF*(G:<0%\u000bb/sj\u0014\rŴ)e\u000f\u0013EQ\b\u000b+\u0017_V`h\n\f\u0006Ⱥ\n?e[Uဏ+AAq\u001b\rZxW\u0001\u0014{,\u00120S\u0016U_my|sr6a%[ޟEX\u0011Y7\n\u0001\bUoS:\u0011;\u0014Zi\f5 \n\u001a@\f\u000feIhK67/>U\u0018\u001c\u0015\u0007قm3Ȕ6\u001dtA\u0016Sa+yd;}\u0012%z\u0005'EN\u001bVũɫ;i\u0016\u00147e>h־3ןN= s-*\u000e o5\u001eïa&cBJp=\u0006%Ae\u0013|^J\r\u0013mwRw)9)\\:Y=\u000eu\u0017.ylfadˉR!.(\u0016waӱZ!)\\2+^\na隕5z\u0002Cav\u0018rd\u001cr\u001dJ*-v2zd;]\u0005J5\u0015:=΀.)W\u0012:\u0011\u001e\bՇE֒ѣKңО!1l3;Gg#:Ҩ\u0015\u0016\u00136 `].-^/ϱ`8\u0014P \u0012jn\u0004e\u0005S8CG2-Ҍp'XF\u000fކLF{Z}6\u000b\r:'u>jK[*\u00115e5;\"(Qi2Ub\u000f5e1|.\n\u001cQr,\u001f8\u0002+3peByGӇ\u0011{\u000e%|i\rh)EjxH'Jjֶtzem(\f\u0016,j;EzyMjwBRu_RJb\u0016dRVU˭O=lښte27䣞\u0010&[-Mp\\\u0011Ts5\u001b[/T[+n\u000bqP\n\u001e(\u001cCy;\u0015_HJ\u0014,cTDIa;x\u001e\u0012_J.\u0015:BZ\n>\u0016)|P{Ŏ\r8\u000b0Wn*VXIف0&֜:f\u000257J˻h\"WD.*3Y,R0R.-$E56?pzq\u0002/9'Q\u0017rw\u001a_B6&\u0004~|L7.\u0017>p\u0005=\u0000\u001fɄTj벩r\f\u0012ԁbk52R\u0012sZ7xg5w\n%\u0018M%\u0018\u00033\u0010\u000bi,6LL5s?z}\u0005;Kr\u0013qD\t\u0012؀ilZ\u0013,qT\u001b0t\u001duLEշin5]:\u0011Q\fCqDUKp'\u001a0\u0006C\bR2R[XK8\u0011u\u0012^+㟉e\u0003_y'3poj6\u0012g6%\u001f,\u001971f\u0011Y)\f4z=\u00134_U^\u000f(I\u001fȣ1%z٤Z\u001fT\u001b\u0003]!U?슑0hj\r\\\u001f\u000fZ\\*\u001b̄!6Kwn\u001bg]\u000e\u001b;\u001c滰ӓC6s,55\fZ\u0007z\u0012P\nESU)Rq\r^\"՛#.ݎhs\u0018~\u001f>L\u00188q!18bUWq[]'1l+ 5V`-\u0018f}YKm6-Q-&o-yD]z\f蒋\u0004SղR:S8F}KK哄#q5Zx<[b\u0011G0`Μ@2`<nI$r>#w\u0005r^\u000eīX\u000b~bʻcl%\u001e֗\u0016ZQ.M*`Vm\tܺFx\u0007&v NF!ҖAaCUK`eP\u0003\u0013c\u0000x#!\u0003WJ\u0000o\u0002/\"n,ŏ973Zf\u0014\"-@\b\u0015?TcSn_\\n\u0015'\n+8p\u0015:\u0016%omOnu>\u001f\u0012`\u000eM\r{\u0013,\u0001&\u0004\b>t\u0000!*\u0010) \u0003\u0010H\u0007xT\u0001u_Z\u001aYK7-\u000bs:~\u0010!%\u0002\u0016+Q\u001a\f\u001c`u2\u0011~5W-om\r\u000e2\u001cbDm\f\u0003\nN\u0000\u0010\u0006A鉀hߵ֠\nvl\u0006\u000e\u0002Dl\u0002m\u0002\"G\u0001pT\"2\u0001ô=\u0011\u0007o=\u0002>zVxqĬR\u000e\n\u0016'\u0001q\u0013t\u001b_\u001f\u0000\u001b%\u00030w&1\u0012Tp\u0000$͆P\u0004\fH\\d\u000b@r\u0007\u0018\u0007$v\u0001(8:_/\u001cq罔+;F3\u00169q\t\u000f]\txYq:cR\u0016cBR\u0011<EZA\u0007׆]l\r\u0000\u0019{\u0000\u001d\u0001\u001dο<yv\u0002r.#(+\u001f\fG R\u001cր\\p@jV\u0006n\u0000Y\u0015\u0001>W\\IYT׉YQC\u001d\u0017|yr戤1g\nو\u0016;>\u001c\u001et.i`%~\u00175#@\u001cPg\rR\u0000z\u0000̲P\u0006w\u0016Pw%#\u0000\u0011^O\u0001[_ML\u0012#U2\f{ƿ⁛:\rJ9]c^\u001d\u00120!15¢\u001e+X\u0003k\u001b@3\u0003\u0005\thW#4D(𼣽t\u0001ʣ\u000fD\u001b\u0018@Z\u0016Ф\u0011ܗ\u000f\u0019`\u0005\u001cCUB.L\u0017|MK^䂪6p0&uD\\LȎ@\u001d\u0004C@1FfW`3X2Q&]Š,YdH\rJ:q\u0000N\u0000\u0017+\u001e0\b\u00180\u00022\u0000}ppc\u0015;)NnTMv28\u00116K_ WyQ~R;~m&lQZ\u001bX?\u0004W5*\u0011`\r\u000e\u0004\u0000\tG9\u0003E\u0000[*4D\u000b[Z\u0005\u001cɚxnQ8Oc\u0005FSEA'|\u001b,q\u0017Կ.t(r\u0007\u0016\"DчOI\u001d\b\u0018'o8\u0017?\u0004\u0000-rU=\u0018\u0016m\u00156\u0000s\u0007)\u000e\u0000z\u001b\u001d+m֞;'d\u00057\u00157=1uya\u0010\u0016pqB+\"\u0001¯\u0015\u001fUg.\u0001*OIy_tk\u0005!7SGY 5(.\u0010\u0012\b#x-U\u000e\b]\u0002\b\u0000\bR\u0005h\u0004\u000b\u0001zJBbx(?\u0004٨~IDbOQ_3oĿJ\u000f\bwrB\u0011wմ\rH5\te\u0002ظTti 1\"\u0010\u0010n\u0002_贕\u0011i\t`LeeFK\u0011F%.࿖[~M\u0003w\u0011\u001bKP|\u000ff\u0005\u0006jKЁZ*Ɔ@9<n@Y\f\u0014N\u001d\u0007^W\u000eW\u0011U\f\u001e\u0017Ttʄ\u0017|*/mp߆7\u001aQj\u0017YnR\"\\\ts.u\u0001\u0018\txy0\u0001A\u0001z\u0000]%8ͶC{ \nԭ'\u0002\u001d_̎ҀaIq\u0016\u0005\"N_n[N\u000f'E\t lM@\u0001^%u$Z[\u0007X6\u0004f\u001e\u00078\u0016\u0016QaJ,O|c\u000egn׽Ț\u000b_j_4qۢ\u0018mcm\"qC7\u0000pH\u0018p\u0001\u001c9\u0000{6A]>\u0017\u0007!Ih> \u001e?32b\"d?F[u\u0001\u0012<?\\y+\u0012eng\\ܤ~s?\r\u001a\u0011o.gAv5F(\u0000\u0001-=0՝~I(~'ȣ9HCx*1g\u001e#\u0015p%ڰ\u001f\u000b-:}mD9Lw!\u001c:S\reu\u0017xv5aY\u001e\u0007sr/2\u0019f\u000bjT\u0006mf\"Oji\u0014vd,ON?k%l\"\u001cz\u001734\u001fP6pK^7_N\u001ero1W=6/+G}ζI3\r2\u001fl*>\u000f9vWvܖ(l\\Q\u001aņ\u001cL\\ܟ2*7^we2\u0004w#\rj;\u0014#\u001cZD41´t!Q\u0000b6?c\t?t4F=ETO(\u001eY\u0015K[f6NP:r\u001c}e9m]e˼/\u0004\u000e\u001f7RT\\XaS{6>\u0014\bߧq+[S\u0006\u0001dD \u000fX\u001e66{fgی\u0013ݏ\u001bePIR,#թ5\n<iVUҮ\n'̫t,]>uBY{2RUp\u0018\u0017m+\fsM%?<~*Q\u0000\"\b)\u0001\u001cb֢0\u0004T^3lU\u0016~g۫Tjá*Z\nU\u0018y\u0006ua.eOJTY|gע*#6mM\u0010t'imS~O|L^\u0017'&\u001fIϾ\u0014$~DQ)I߬\u001f\u0012\u001c7̶\u0011hvҾ:Cy(jZ~:$OSI\"\\T^M7۝)M\u0019ՙfɯw2\u000e`څ;9}Eƙ\"{-\u0011\u001d*\u000e4WS%z\"E+\u0003<NI%&@)?$妤ujC]w\u0005`*6qxڍ]q\u001c\u000b&2VKi1|Z~,m;ug6v\u001d}#FU[ot\u000evO\u001b\u0017dT/\t]{|=^B48ł\n\u0012j\u0013%p<\u0016\\6`hf\u0019ҩa^W.4\u0012O52F2.\u0019ti{{zl}n6J<\r]\r\u000f\"u>UkP}$p$0\u001a|\u000f\u001diԊ:Y5@u!*3-f2z°\u0012JoG\be5^\u0016E\u0012@\u0018J3\u001a\u001e*:ٚ\u000bqe5%BbUR8\u001coyf.\u000f)LE62)&\u0005AD\u0016Y\u00035%\u0002\u0004x0³\u000bm\u001fFSXR\bJ\u0006@3k\u0003W\np\u0000rEHR%Z>K\n[v~\u0005E]J1X\nm?\u001f\t!e\r>|T0D?\u0005+\u000b\u0006sdʃ鍨&cso>Jη\u001a1JY\u001f+ߕ%\u0005qSeg\u001dI}(\u0011T<\u000b/akQ\u0017p\rԳЮ9\u000f)XJÇ\u0001\u0017MᢰR[|\u0014L$;Kv2Pn\u001e\u0007\b(\u0000ȤPG&XFF`4ήb\fba\u001b\u001b#FU_\u0018\u0019_\u001aÈmI=_.\u000ffNa]r^,c?\f6\u0011r?$Ķ\u0003f\nCS\u000fI^m8.q.TZ\u0004]J&Ǭ\\uO%cjAG'ZA`R<}!Vl>sos!s\t69%$\u001c(o\u001cH\u0005mvJz,\u000e|f̂VLvk\u001e\u0018kq\b!i.YԎ\u001dNSbzqx#%B\u0006׮LRط\u001fނ+%n<ӃF&{y\u001f{,K\u0019\t׾;LK:;\u0004ULk13ðWM~:z<|LxvoIna^J$fˑ`r+O\u0012'ёh\u0016,a`DCsC\u0007&EFN\u001fN\u0018k-L\u000fJ7Yv'#\u000fA\u0007X\"|6}\r\u001aV\u0018^\u001b\\TK^^^S\u001dJ\u0016\u0006P3H\u0007[~.r\u001crD3Lĳx`ϔ!\u0001Q3\u0018F`\u0000\u0018j(Y}j)GǶ\u001a<FLS!N\u00078i\u0002`U\ne\u0014ԾdW*T)iUaI=F֣WlJTV4\u000b\u0013(5aW\u0007<ms+ \u0011%{A\u0001\u0019\u0000\u0014\u001dujcu{a\u000f]\u001a7\u0017nkp\u0005ߦUabkXgGBBڷ<Xi()P`]\nj\u0012FD0y\u0000V\u0019\no\r'W\u0001\u000f\u0018t\u0001o\u0003kP\u0000g\u0000-X\u0002~e\u0000\u0016Zyx5/`|^tN\u0014\u0011\u000bg}M\u0014&/[Y*4YMz5J:UR^\u0015+x\b\u000e5<^Yױ(vna\u0005\u001f\u0017&@\\\u0001\u001d_\u0000*<\u000bZ\u0001\u001c<=\u0001\u00007e\u0011B@,&RJ\todeޔ}awP\u0005կQMNɂ]#\u0002+\tX\u0001+\u000fp$Eu\r|:HMX\u00066\u0002Mj'(7Y\u0011\u0010'\u0001\u0003\u0001\u0019c\u0001~R\u0000_7.\u0000\u001f7tqRDj{Zk'\u0005I45^_MoA\u000bħB<zjthE2\u001e:\u0012M\u00150\u00194+٩\u0003\"hCy\u0000Q\u0010'P\n\u001b@`\u0001D\u0006DL\u0001\u0017r'\u0000D\u0003\"S.\u0001¾<\u0000m@X\u000f\rUD!B[s\u00123aTo\u0007>\u0015=x)y\\\u0018(eme?p(ɳ_\u0006\u0004\u0005\u0004D\u0000I#(9\u001e\u0010BI(\u001f\rL)\rH@\u0000\tv\u0012 w_\u000e\u001bnǁ1Hg\n9U\r/Q#D~oE,\\$',uj\u0019v'jPW'u!U%=D\u0019v\"H#\u0004u\u0015%\u0018\u0002J\u0001d(Rj\u0004\u0005~AG҄r\u0003X\u0003_\u0000\u0016U@\u0005\u001f/YnlEщLDA'5L}^\b2Uw@+rRIOtZ\u0003_z\r\u0003G\u0005V.Í`3\u0011~=\u0001\u0014\u001b\u0002\u0018-\u00005ֶP\u0006w(!\u00006yv\u0019\u0007.V\u00020\u0002Ԭ\u0007\u0006r6=\u0006(,Ð[:o\u0017{\u000b\u001c\u000eBwH՞BlQ\t\u0016VZ\tf\u0000^\u0001y-@%.>\u0011\u0019a\u000eh'\u0001ty\u0002\u0011\u000b\u00014P\u001a_[Q\u0005)\u0003z/\u001eO@B\u000bw\u001fq\t:\u000bh3֧뷤T!!\u0019&\u0014\u001c;\u00123\u000e\u001f\u001d}lj,b<%e8)1~yry\u0004LǸ\u0003\u0000VҀ5T\t|%\u0006\u0003,j\u0003&\u0005sW\u001ffYu\u00013\u0001S\u001cQ#\u00142GK\t'\n:a\u0017)\"#7يgD-M\u0002\u001fi,\u0004ߢ#\u0005oo\u001f)\u000e'w\u0001bP47!\u0001\u0001%x\u001e>\u000b\u001et\u0016\f82{YV\u001f!,2\u0002>\n(hl\b1vSɈ\"302\t\r'\u0007\u0004?^\u0005Ba\u0007B\u0002D@U\u0005\u0004E\u0003|>\u0000oԿxU\u0002jZL`\"|Xv\r)v\u0010\\d\u0014-A\u0005K~rdl\u00022By4\u001e@*8 R\u001ed\u000b\u000e;\u0006Ĕ8\u001b\u0018Jtf>\u001cG\u001b\"Nۅ\u0017ѿ\u0010O\u001c\u0011Or_BAQ\t\b?\u0016I5KEg|\u0000Ԫq\u0007\u0001~e\u0003F\u0002\ng|77@\u001d\u0013{|Z1n1d<u'SQ[ĴQ5wlx㯿/E)\tse\u0011'UOj\u0000\u0003+/>g_@WV&޳\u000eж\u0007w5>ߔF\n\u0005\u0010_6\u0011bڨaP5\u0010E_\u0016?ٶ#e\u0011'.c\u0014Ď-\u0015\b~.*2ho\u000b̍-\u0000sq睠:k\u0019p\u00137~97l/OF\u0016%\u0011#\u001ao-\ni@d(\u0019\u001eV\rlGCۛ)k[F8<\u000f ʠ\"(\n2\"|YݫWU]U\u000e<b#\u0003햵C\u0012$\u0019+G#\u0015mWx#:t\u0016QţkBѮD\u0017c='\u0012r\u0003m5a.^\u0007\u00115~.L\nCN\u0004)9\u0016_!}-!{jleiF{qh#V\u0017\u0005p>u>Fn\u0015+AmL\u0011DC:`7I8V҂̫Z\u001e\u0011d\u001e\u0003\u0011y\u000eɓrԖ޶jj?55 \u000e2O\u0018\u0001lZ\\G9m-:\u000e\u000fH2n@vWn=n\u0005^-?\tH\u00124셠)\u0015_wZ\u0004^~w\"Q mm\u0012\b+Q mm_\u001aB\u000bXjDrv\u0012׊*%\u0001wJQ\u001b\"6{r6H\u0013-c\u0017恖\\|Wr\u001aؼ\u0004q:^o5yh\u0013Ū3[s)ܹp}\u0005yն2\u001a<\u0015Ї\u000e\u00150rs8\f]u{\u0007gR73]Cb\f-VQH,\u0013\u0017\t\rR4\u0007\b\u001c\u0014ߢ}z6xGy\reCߖ`wY&Zm\u0018jO1Jgwa4.\"G\r\u000e\u001dMN[_pu\u001dr̟\f2@|\u0004ǬRH\u0016UoE\u0001a3\u0018~+ߋr\u0004q^#\u001cA~w2b\u0016J\u000f\u0000g\u0018z\u000fӝN,\u0013\u0001)I7%Y<\u001d{\u0007wlir\u001f2IfsU\u0019Ѭ_\u0014h/ŪF9*\u0003-Q'M Dmֺw>\u000eu\u000b\u000e\f\nf;\u001es}utdq撨<nQ\u0015c\u001bT]\u0013RjP\\m3knS5=\u0018'Ch\b\u0000F)Ar#\u0014z\u000e{H#\\\u0016N1҄q:Ώ(ι/`͜k%\r<\u000fk̢ީ\u001aP'W/H;vP2򽟺Y\u0012񎏿\u0018A\u0017\u001d\b8(F(=F⹷\u0005(r\n\u0000V\r[\u000e\u0014PMRA<^q<l31\u001fV5BP].g-\u001fp\u001d򫠟 \f\t\bˠ\u0018\u0019A\u001f?kxП5'u`Zl<\u0019A߯6˗\txF?l\u001f1C̷/W\u0019A˟3s\b|] ^\u0006Z\u0000G!襂ryԸ8뵺v)1T|!W!\u001c*-JIM$O,X7i9l\u001b>R\u0000\u0000\u0010JAi@yݛG`wA\u000f<?<u`j\u0017\u0019ݍ\u000ffa/xZ0F\u0012AW%;&}\u0000l[ҹ{\bH\u000b#\\pW5؏\u0007݇\u001a%nS5\".K==|V̫ǥu ?\u000e.2@W\u0018\u0000݂q\u0017I'\u0013\fNcs^+О.vW\u001c[f6kKZ\r\u0018D 3ss\u0014Ӎ\\npQ\u0001z>\u0001$z4BQ2hOsQ9\u001cb1[w[*b]τ9&Lf`I\u0001D\u001f>VYe!B\u0003?xR߃rM\u000fԁ\u000eD]j@G\u0010x.:\"-ʗuMF\\Z,줺b5ڴvD\u001f>%\r\u0002,7}\u001cR=6Ez|z݁nvaZ\u0004\u0012\u001d'R\u0004<Ͻro62\u0015#\bC\nE;o\u0017\u000e\u001b\u0010.\\<\u0018\u0010\u0015B\u0015\u0016yȶ\\\bٰ@H\u0019\u0017ۮS6k2\u0010;d6`\u000b?\b?\u00142=hP\u0000ff_&1a\u0006]uR\u0004aWL|eF3\u001azJnk\u001aLutii[V3Tͥ|bK\u0012AW\n\b~\u0007\u001b'\fչQlyԕhdaD1-_\u001dQ[\u001a2-C]*>e\u0003!E\u001d'Ĥ,`DN\u0016\u0017s4\u000b1$xT;˹}a\u0017ϣ*Ϊ|\\\u0012U[,6j l\u001a'h&\u0017\u001b\u001d\u000bKt\u0004\u001a%|!\u0000\u0010Ԛ:^\u0011,\u001dlhF4?V!.Mj\u0005Ģ>jF#,<\f\u00054ڕ\u0018+ 7\u0018\u0018mc\u0019\u0002\u000b\u0000V/\\6i7P**9b4n\u000bx!\u0019hLz[.ECHIh{#e\u0016\u0015f\u001f(\u0000\u0013笙>/[C\u0016-9\u0002(XZ\u001d`_ǯ\u001cn\u0007\u0007IkҸ(\u000e+6ٓRP\u001fi}\"\u0013\u0012A>\u001f\u0012v@ܞ!GEeTzb49,7fm\u0011g\u0004B\u001fw\u0007gd2I\bL\u0015¬tU\"\u00144:'\f<OF#O\u0018l\u001d[9X>d\\BNV_7ScE \\Mh\u001fw\u000bO\u00169<pZO\u0007.\u0006\\M]|H\u0004\u0005\u0014l\u000f\u0014\u001c\u0014%\u001bj\u0006`{w\u0014\u0013^6ҷ]߸.RuZ]͢\u001dnW+v\u001f\u0014,\u0015\u0000F\u000fkϗK\u0004\u000f}\u000fA?\u0019A~\u0019u\u0015O`~>b\u0012Ϸ\u0019A]\u00023a?U\u0013\b|G\r60G\u001b;R\u0004`_g\u0004.\u00074\u001c,\u0016\u0003J\u000bJ\u001dr_ۨ\u0011]nI6m;5hI\u001en1(\u0003sݎsso\u0003\u0007d~F9\u0003\u00162WPK*1naQu+{>g΁c,cA}9Qeݦ\u001fp3{R7_I\u0004\u001f\n(7\u0010Sc MO!a\u0003q_\r\u0014ᖾMr!bqӹ&2g5A\u0013׭,<BN+\u001c,t\u0012AQwd\u000f\"\u000f+\u0007A\r\u0007eѺ7\u0007sKz(5t9\"R=.3|;^\"EW.\u00159\u0017{\u001bf\n\u0000P]x\f%P*+.s\\P\u0007S'6?6Uw\u000fV=ʸ\u000b)\u001f}.\ntC ?\u000f\u0001f\r<~W\u0000Ɂrq\u001b\u0003k\u0005\ncp>=~P\u0013\u001a\u0013%Tw'O뎻\u000eӪ߾x\u0017?q\u0017W$u\rtt\u0001\u0010/R=q\u000f\u001f\f\u0012#]z˩+1_u|f̵\u001b+f/tSe#,ZpȜ\u0018(\u0002=j&\f\u0005~xc!e\u00047\u001c\u0014T76-[F6l;4-G\u001bus \u000f\u0001\u0013\u0004\u0010HVf\u001e\u0004ؼvx³OA\u001fĜ<GWk8ȫ\\,qK>D\u0006gSNIN\u000eOe \u001fo\u0002qᨔ-=x2)Dͻiq-'ڎ\\-u5\u001b-7F|\u001cmaa;ɴ\u00147 \u001f_\u0016P\u0019C8&!0Z\nNAnޤ܅O\\\u001en\u0004\u001a]s\u00034b(Lo\u0005gKϏ-ƴW՘@UƜ4>!\u0011\u0013?\u0004\u0003\u000eG\u0000X\u000bNA#\u001a(-a1\u0006V|ju\fv\fiwbd;\u001cj<R1]:$T%\u0015/\u0011=^)W\bz.-a/\u0012Vղe\u001fW/*)\u001a`38Uf҂-'diJާ&s\u001c\u0012ZrS\u0016}?$u/\u0005;\u0001D\u0004\u0018 oEs#B\u0017hQ\\ǧP\fYg\tm\u0005%Aal|,p(BQocD|J?+.?}\u000e\u0019\u0011@o'Qw@2#.\"\u001dbN\u001bZ\u001eK\u00156-\u000bx)5\u000fb|(s\u00175#pTՓ\fA\u001ey\u0012*9~A7\t%=W-o[6g\u0011\u0015.*\u001e%)r\u000bu8Kp|мS\\7'3\u000f:^-;\u0018ūlHl\u001fD\u0014|I\u0000\u001fNCE>`s3\re\u0005v\u0013_ zQp~Y4ͱ3K{\u0007G:ՏЯHy~;Qgw\u0019\r\u0013+A\\KWܪ|<ރ/\tˏ\u001e\u0001̼Mˁ]1heWuKMۜT>f=]XO\u0002%_=E!MZ\u001f%\u001dA\u000e\u0000̒\f\u0012up}\u000f\u000f|\u00185{$ž<\u001cđJ}\u0015C k\u000f\u0004K'\u001c^Ԓd\\\u001b\bs\\>5b\u001b\u001eg0Bq^Ci.\nP|O}ܵoA\nqysP6u}\u001d:+{\u001fg2!8 xA^i\u001c\u001a}O,B@i\u000b'J%|\u0014\u0014G\u0015\u0014\b\u0014j\bsE\u0000sI\u0003Ae\rt\u0007R\u000f\u00034`q)<\u0017˓4Cgڒ\u001c1#XYq>$\rc:흫g\u001b\r<m[_`G_\u0004\u0004&\u0015\u0013\u0011A?!.\u000fL`s?jq_3aO]\u001fpL`_g\u0004.\u000f\b[jpn60\tC\u0006{W3\u001f\u0000+$V[2\\-#\u001eFS/)&;%\u0011s,ƒ;\u0003H2uaV\u001dwxPnD?\tP\u0010\u0000jj\u000b`Tr\u0002-|2t\u000b 󪓊\\ig՘n\u0011\f\u001elM\u0004\u0017l;[ژ\"0b\u0005;\u000eA&4޶%P_\u001e\u0000O\u001dm-l\fʸ\u001f\u0000vy>kR=:edDްݟԨ=l0K+\u001dz\u0000\u0000\u0017y5UP*\u0012Ӷ\u001d\u0005\u000f*\\<\u0002^5\u00177-6w\u001e,\u0011\u001d\u0019\u0016j̎\u0006\n/%ח\u0011\u001bY]_{ID?x\u001a(l>}\u0019E\u0000Ak.]\rqqD+ïSlxtvu^)_WuP[\u000f1:{]sm2Fv_\u000f̷ob\u0005(}\u0002R!\u001f|H\u0006|B\u0016m9-89\u0019|2œkJJyReuz\u0006xP\"_Y, &C\u00150q}6s_\u000e\\\u0006}\\Wxgpnm嫷\u0013Y\u001e\u0018\u000f\u000f\u0019iIN<qRܔO\b~\u001bMAF\u0014:\u0004ݠz63b\u0017,]1&صSL:Kg\u001e\u001bL^E\u0003~wX\u0014h4&;mv\blh\u0003c\\Tԃ]\u000e5Q뙰H?j\u0017n3\u001d\u0003f.¦y[\u001a\u001bZn\nEX\u0014;5&ˬZ\u001f\u0012A\u0017\u0014o\u001a@\u000fC\u0018+1ֽ\t`0[Vo\\̭+CN]Nj:;Jɵnvm\bf~/X0wufewm4>+\u0011{\u00104\u000fRxcQi\u0016\u001fi8\u0013O[qrQ-Qmn\u0005\u0015e*׋i/ 3XO;Efce3mi^^ü3{Ir\u0002FP#\u0018IP\u001b.jA;5|oG3i}\u001f)2uFXRqYv#A=ׁ-G卆F\rK\"?\n>!@\t\u001c<\u0006&$(Q\u0003fٕĵL\fkJ6a]Ķ\u0004<_!~J|:SЯ]+h%\fM\nSwGW\u0001(\rHC\u0004\u0005\u0015%>y3\u0001\u0018\u0010{Ǻ.\u000e\u0017bv<1E\t:-Cq_sȽ8\"-˜Z\u0012W&&C+\u0002~\u0013n)؇6(\u00198Z*Vz2[G\u00196\u001ba\u001fK5\\Z5\tt<\u001bN-+39sHz\\ݱѽ\u0010{CF*\b!\u0011{?\u0014P\u001c-Pi4+[\u001160\u000fYlqh\u001f\r)/{V%&cH\u0015/\u001ed0wLRm\n\u0019{(N{xը8\u0011Oɡ\u0006!9r_\b=(-\u0004)N\u0001vA|Ӥw\u0016\u001dRF\u0003\u0017PgoB58,3ɂ^\u001a\u0001{\u0011+\u0011#Cl8^a6}\u0010|^b|x9dl\u0016-\u001ed-il8le<,V\u0017ײ`J\f\u000fHdÉW\u0019\u001d\u000e d\u001c#|\r'E|\u001bb\u0013\u0018\u001f=\u0000p\u0001LN-o`/\u001f\fYm\u0007Q\\UD]\u001e\u0007ԉ,\u0001~Lq\bS\u0001e.\u0017̮#%\u001cnnD*v\u000ec\u0015\u000e\n\u001co\u0015X\u0005 4SL-\u000f:bz\u0014\u0006\u0017\u0016GrR%OL\rC׎|S\u0015k(!F%稙;d5\fNz\b~E\u0000cK[ICn\u0007\tQ1~u2_ۇގ\u0015X:S޼\u001fGq@ 2łC%R!D\u0001\u000fAY\u000fO}X\"ϟ1^<\u0005n\u001aP\u0007rZo!ZŁ=5{\u0003\u0015\u000bɸzJ\u0012&i8]XֆҤ\t#ހMA9}Odb~\r0؛PH\u00041kfF$IY+!>t\u001c=(\u0001s9RVD\"c\u0014Y?qBsv\u0005\u0012\u001b9}T\n\nJC\"<y\u0019|z\u0004MW\u0004}\"\u000b\u0002yc`t\"N\u00014\u0018\u0001\u0014ޫ>Ј\b\u0003\u0012\\\u0001s%#et*\u00126\u0016#n8 sS߶5d\u001a\u001a\u0007xD?\u0004'0#/~\u0002\u0013FWA??jc\u0007f\u0004`xF?lO\u001b B}\\\u000e\u0013s`\u0006\u0001\u0000b&@[8(^Vp/-!\rf\u0017Vs\u0006\u0019\u0003B܃NGIϚM`[2\u0016\u0015C`?\u0015Pqy?\u0010+\u00071X\u00067?vm(j^L\u0004FTp\u0018\u001eJp)}Z^mg\u00166\u0019\u0019M}kKQC\u001d_\u0005@}\r\n\u0014\u0014ˍ\u0003@j\u001eA\u0014k\u0001`KNC50fW2\u0016ϋs}x]v𥼵cV3`D]¨rU^ݜM\u001aʿ\u0014P\nŬi&x/\u000f\fx\u00040![xpW\u0004Ǣ|Z^͋M'Yt\u0018pT\bq56cS`DD\u0014\\\u0003Z\u001dP\u0010t>9\u0002\u001d\u0015\u0000֯\u000ez-~`\u0016/ӊn>5g'ҺU\u0014uC\r7ܣ*?NZ\u001b\fhm|I\"_\u0007(-\u001b3l\u000b\u0014R&y\u00012]\ngt'n\u0005\u001b\u0006\u0014-'MЖ9 oZOfg۴+ut\u0018\u000e}\u0011%8ӛeCR@'\u0015a,Yva,wHA\u001b¶\f&7#;R\u000b\u0007esl\nuc\nѮ22\u001c>5O\u0019eo^WR\u0004dPYC\"J'@s\u001e\u00040\u001d\u0004e\u0018ϫ08h:R-}\u001bJ\u001e͇#N\u0006I\r59Lk;}\r()cՑ{\u0001\u0005%|\\\u0007\u0014v%{\u0002,\u0000\u0015Mx\u000e^~Sύi;\ro\u0018B\u0011촘Ϫ\\,*\rI\u0014R^@|_PΡ=Y_K\u0001^\u0001y-O\u0017U/%P*9<tQ\u001f}\u0007\u00155q;\u001f\u0018Iij%+\n)e6<\u0017{..U\u0002]VC\u0016Chs\u0002v3ɬg\u0002X}O\"\u000f\u001f%\u0010T\u0007>@!\u0002l\u0002ʠ4G\u0013\u0012ۘ\u0005Wio\u00047ŬN\u001f65`Q\\r\u0015ۮ\u0004ގ\u001e\u0005V(!\u001aɂJ{͂lo/=W\u0005Z\npTJx\u000fe+\u000b[\u0018,ʜ`vlTEQ斦K-\fḳq3\u001dz\u001e'>3\u001c6$fX\u001fQ>cR\u0001b^\u0007߉\u000baP#صąQ]V\u0005\tyx\u0011\u001c2Eg\u000b,\u0017ggНɞcpsZNINuC ?\rJBMQRzP7\u000e\u0017zm6>qF˱犳rڙ\u0010\t5\u0014,4\u001cUK\t3*4́2v=f7v_\n(hY=8|6D؋\u0001W\u000f\u0014ztx-\f=кcZG,#s5\"8m\rfgu)_kˈu=\u001e$Nɜ p7p,ag\u0001&{3ުLE_:wK9\u0003ڽV{\\ayr-˱P&\u001aEdd13hy\u0019\u0015x>.\rG\u001d#hwG\b\u0014.\u000f\fJ\u001d\bɠz=8D/\u0017D9\\iYֲjKj\u001aUfѩSYY\u000fR\u00115W5\u001c\u001a17x)\u0000^\u0018(6{%{?^O~LlW>b/)vQ1Z,m\u0007j\\*NRlLGQBQ J&\u00074\u001b>._\u00178\u001cˠ\u0018I]ho\u0003\\3\u001d[F\u001a<\u001e|\u0016Dl\u0004EfX=h'LAnZc͡\u0018nLEt8\u0012\u0003NO:|\u0014\u0014g\n@\u0013:\u0005ٽ鍍3-o<ڮ\u0016u?guή,\\'HyWXu!\u0013Im\u0013\u0019\t\fK5`ϩxMȿ\u0014PQ5+w'\u001fPpr:ͱP̴sҜZE>ٮ3R_؅H\u0016.>Fp7a\u0001\u0001vAx\u000f\u0011\n@{+wrć+^hYI3oX`3]lyS-}v,\u0005\u0019ׄ(i[\"5gwc\tC\u000e\u001b\u001f\u0006s`\u001a|V`]w}ɤ[N!1w/'W\u0013yOTӌ־\\xN E\u000eb\u0012pǙ\u000fz~\u001d\u0007+В~\rrOZ\u0015S)N\u000e]w\u000fW%mngm\u0012AӘsgiD[RK hK#2\u001a\u001e'oUwבֿDҽ@\u000b={(ZCK4<]，;Q/\u001d{E\u000bJlz+@B36s$3IӯtGd\u0000b^EU_W\u001a2 ;:ujsm\u0013\rqo'\u0006hS'\u001acG\u0004JDo@xBAn\\遼X)\tx0Q1҆)sv퀂j@\u0001Ѫy]nV[4az\u0019/K\\|\u0019%hW拖~*Α\u0007êRت<|]~Fꯁ~\u000232'0#/~B\u0019\t`_g\u00047G\u0001\u00039\u000eA\u001a\u0004\u0015ro\u001e\u0004\u0010tHBP\u000f7\u001c6琹m9753ܪȧrn\u001cy \u0007,xvh6\u001f_\u0017oo,;\u001eB\t\u000e@Q@]so\u0011\u0014{H1+A\u0000\u0002G+8c[?UZ!Pi,ƛ+;9aNn\u0019gw$ч<\u001e|\u0012àp\u0010`(\u0010\u0014\u001f\u0006@=L\u000b^Qb}\u001fȏG0Qo\u0017$\"p-;/:qlظq,_\f\u001ct\u001a#R. ?\u0004￿z\t\u0010K\u0016f\u0007d\u001cAP1\u0001sQ\u0001Xcw\u001e/~obJ8{u\f<dkRfe\u000eeˤ@E[;\u00181e{c^H_\u0017g\u00130h\u0005Ɠu\bP\u0010sh |׭~Z[\\xECG\u001cH<Z֔WӍ)\u001c\f\u0014&2ZS0*It,P\"\u000f\u001f}\u0003m`<5}0W`yy\u0002t%\u0001V#$(z`j9l%\u001bnw9\f)\u0007j=f\ncQ1ck]z}Jֶ%:\u000f\u001b5'˯\u000bȯ7! @1h\u0000E\u000b}']\u0000j%r-da:?\u000b\u0013N\u00024X{;\u001eOڽN\u001bj\u001f!z:^sc#\n}B\u0015\u000b_o\u0004;{}2\u0002{E\u0001\u0016u\u0001f+ǅp[\u001fFc>_\u0013s쑾\nf'\u001b#Le\u0005YlWڪ\u0018)֪e\u0010e\u0013\u000b\\[~\u0014]/h>\u0003Aɪ\u000e\u001bg)\u0006N\u0000tGz\u0006ܲr\u001b-c\u000bf:%ݗvZ\u001aSкsGPV\bVج\u0001\u000bi\tAjN\u0005?Z7Lv\\\u0006\u001aqrن\u00146\u0000RW3ˊG%}\n|ym+`&\u0017|S>\u000b)8jE\u0015\u00169-rv\u0016F%/(\u0001/[\u000e!6\u0003l\u001a\u000fj]\u000fʕ\u001d`]Nyt\u0017KVp(\u0011f\u0005;\u001cd\u0019ov\u0006©6\u0010A9?!\u0011\u001f\u0005T`\u001fZ0|\u0002;;c\u0000ԟ!\u0000agxv)sU\u0002һDɔ/I^\tɅ\u000b?>\u0019\u0018ٜoY1YNʐ\u0006w-I6?vH\u000eV_q-PZ9\u0010CǶڄ+!)nv{r\u0018Ԇ|n\u0011\\)\u000fƳeoIO\u0005vo5\u001b-\u00169;\u001c>$u\t\u0001ys\u00158x4@\u0005\u0004BܛKyeʩlt\u0015\u001bD\u0010V\u0006j)8gG+gY\"6\u001e3}iF\u001bpVS؂\u001eeJ\u0004\u001e֑\u0016[\u0006\u0006\fҏ-\u0011Im\u001e*3*\u001fR\u00064\u0005Rh̥#]+C/m!Km\u001cǘC\f;l\u001co!UdDQ\u0006NX$NS0alu\u0001X\u0017 @}(ᨐ =\u0007~*G\u001e;\"\u0014zm5\u001b㌩\u001fWs9-RڙiM,-:;nt&\u0013\u001fW(&SqEi\bD\u0014P@!G`P*(S45\u0004I}=qY]i@^،['LK缲*p~yp;le\u00169u+\u00015FE6koԞ\u001eH79L\u001e5\u0012r!~I\"\u0005\u0014\u0014#\\qa;\u0016#\u001cIϹn3q\u001dLb\u001ciFwq9Y\b&0׉bMzzf6\u0017Ir\u0011ylpm\u0012ϿOu\"Gl`\u001e\u0005\u0014z4:l\u0002Rǳ߄<P\u001a'خ̵ѵ\u001er2DbӸ9@g516\b \u00181k1<iifc7YKG\u001f\u0012AW\u000f\u0001\u0006R\u0005%}0\u001e&c2N^[a\u001e_E8O\"hҭG#\bc\u0007Y@%0ns0'xO<\u00156OO]6[D\u0004̂bhR\u0011o*\u001dY\r\u0017&YAj$^Muޣ\u001a7v}jy}#;!mchp\u0000Mr\\}]@\u00019xAiwE\u001dR\u0000GJ+OyޟJf\u0015s蒓w&\u0005+8u%F\u0015ċ~T9\u0001~\u0014=Af'\u0011䇏>\u0004\u001a>\u0018::* ڕԸni\u000b9-y4gzy:9\u001aKDYN d\u0013F=dap\u0016`ޒu\u0007[%\u0005ι\ns8b֢<r\u001alDJ_땆+D6\t;(\u0015\u0019\beR\u0011QDf\u001fm:nO\u001c'^~\r^ _`&k.C\u000b\u000e,Qd1\u001eq\u0010)`)1Gr\u000b#6\t\u0016/\u001cD{b)x,\u0017\u001dtzE\bT T\u0013\u000eD\r/H\u0012diyegm(\u0011䇏+)nT-x/Sqa0ӛ\u0001RXjbQriq\u0017\u001a\u0013;}(gMϝο`GGg:q'ht&&\n\\;yBі9kV[RuђTZΞp_Q].2;KJx.\u001fiRL3\u000bOyf\u0013\u0014<TkVUbr3sqy4\u001aт86G\u0012Aꮔ. i b\u0010\u0017e\u0013w@j\u0002sOSأzt\u0005:\u0018\u0006\u0012}`nR:^'+\u0007ы:<owW4\u000et\u000f7\u0012AW%O`F_\u0006\u0004&د~\u0002\u0011\u0012'0um\u0007&t\u000f\u001a\u0010\u0015ߟ\u0005)\bZGc@kmP\u0018j\u0015\u001e@~މ,gc7\u0015\u0017CurSP+7 ;[]nnԹ\u001dn \u001f\nȑ]3$=UA\u001eu\u0018PoLPP\u0004(=Pؿϕ,g\u0017ʧ\u001e2>mvn\u001c2^\u0002=/&Y\\2d|tf[~.^i3opӘeѭ\t ݃ܜ\b@LB\tk00?ؐG@q\\\u001abw&bT !w\u001d\u001d|m\u0007'x_󱳼9'\u0018-G~u\u000e+\u0012\\)vc0+]_/\tm\u0010/@֡)\fe=Z\u0016;6\\C\u001c@[\u0000tν/gebn,\u0010N\u0015Y>m\u000ew\u0006nVz\\#sVC\"_?\u0006Ɂ;\u0006(\u001c\u00014ySA}<J;\u0016.irG_\u0013'ù\u001bLת갎އۚ\u0013'l'ۓ~WJa;E\u0015e߯:b-?+\u0011\u0002r\u0014*\u0004}tP9P4\"Yra83\r\u0003\rڻ6lJ܅zCP\u0006ٍv[\u001aq̻}7몝DjF&R\u000bŗoyt\f19\u000f\u001d\u001f`\u0014K~v{3xtM_d_u?HyZpMr|e\u0010o\nV\u000bu{S96XjXs\u000bmD\u0014|O@,ao ߤ!(/3@a\u0001`2ga,\u0015<w\u000erۅrI>\\jU\u001b*\u000ewMRE\u0005Ζu9痿@Y\u0001\u000e&v\u0001b h\r\u001fCu%(rӊ}\u0012h\"&vC|(DAV\f-O;+\u0015\u001a)ŷL!^\u0002Rݗ3]F]zt\u0001\u0001bޭ\u000b@\u000f'\u001d7iw0S\u000bC|X-^tk\u0016\u0003Ħdcqx1/{.uaƏf\u0004˧K4\u000f +K \b\u0016z0۠.\u0001Z\\\u0001\u00160ixƖ?45\u0014\rg~41ij2\\F\u0010%5Ygz$_\u001c\u0004<CLy@CbC?pl\u001c$\u001foK\u001a\u0014b^\u0017\b\u001bg{`@)6w\u000b.|pG\u0015\u0018H]STdnblY[Fc%\u001eMA\u001f\u0012\u001d>C\"O\u0014RQ8Ϯ愙]\u001d\u00056<<a\u001e=؇r\u0010sUASG?e<6©$^n#\u000bA͊\\4e`[j@`(_\u0016v\u0015p^&arwi\u0013b\u001a)`J\f\t5mwI\u0004o0\u0003'$\u00045\u001a\u001b8>\u001cW)9\u0002fpF8=J>0n̈́y5U\u00173\u001775\u001fA\bB\u0017s\u0005/\b6\rRȀQ9֯W\u0019U\u0019tz\u0004&c|4q޲\fp\u0003\u001c*jx?r\\uw\u0017.\u000f\u0006KX\u000ec\u001d9-Z\\^d|E)?z%F}]khu(z\u0018M\u0003\u001bAI=MS֠:|\u0001 Ld\u0019>\u0004\u001dD\n\u001fU[\tr}nE\u0002\u001eͧ\fq5\u001d\u0013R>&Wjwq2=\f\"=X4oy>mJ\u0013b+sΌϥ\u0012AW\rY>'\u0000ʨ2=\u0010\t6\u0013eʧ>5\u000ebܢ[$`\u00171nHƦr=\u0015[a\nCfTc\u0004]gVAЅ\u0016\u001ci\\y\u000bB\u000e.\u0017a9wF>?\u000fƦ\u0013lBtXS(Sy?<\u00192xQE\u0011\u001fWgh}\u000bDoBVq׆8|a!D\u0010\\M\u0015g_\u0012g<\u0000$\u0000\u0018z^\r.y㫝8=>?pV-4#d\u000e\u0011D돋8d\u001e\u001el)Ϙ\u0016RX\u0001`9:\u001eֹ84i^\u0007c\u0007e'\rbs (3Q\u001c&C#\u0006a\u0002Fpn[mWي\u0019?ծR1vf\u0013M+\u0016lv\u001cy5A):.D>6^a=noz\u0015D.%\u0001y\u0010M3_\u0001XtA;+X&\u0016}^:tEn/lӽZ\u0016uə%*3C?;|\f(8yaF\u0007E{a\u0000rׯ.;\u0004\u0002\u0007z\fz>\u0003\u0005S/\u000fΣ=d\u0018H9imag\u0015k򀍙ғo@\f5_a\u000eHǢ\u0016y\u001cقKF 좇g`Xl\u0000Ch$z \u0006n\u000bA\u0013\u0002?s|\u001f\fMv,,-c]:AiY*\tnqڛ%\tW\u000b:qgaj#l\u0019Lq*;\u000e\u0019\u001bҤWܳ2H\u001eEv#_.U1Ytf6z\u0018],I4\u001b&q0W\u0004l抙ʤ\u0019]RqQҬDf\tx\f+P\u0007\\\r}O\u0004~r5\u000bn\u001ex#3\u001f\u0002#??\u0017P<\u001d1w JR.ǈdڞVfzkc\u0019Þ\u0004<JW\u000fFIcšg\u0007\u0007.kBF_\u0003Q/{t\u0015ͻ\u000fmJL̙Q2L;j]\u001cKȻ(R\u0018\"(H\u001e]Q_hjv$]>>qњ0<N{A/ڣxPEj;\nI\u0016;q\u0007/GNS6Qw\u0006o3nKd\u0006t{T\u0011vr\u001a!iM3j\bgڥR$E\u0019w&=w3Hfm\"1.Kme.I,&]-ͼ\u001bUޘ6h\u0003}LuW\u0012\u000b'J02'\u0004l5\u0017etbOĊp\u001b%u6Dϰ\u0017Km\"{KKI\b8\nVVzijv?\t\u0013[/jHuN)P\u0004Εپz\u0004`\u001fO`@n,Rރ<vy3\u0005-΃\\mnQ{{\u0014˦:X#*h:</pTJ\br\u000b/k\u0003pw\u001d\u0010۵ùЊ\u001bO`\b\t\bˠ \f\tL\u0018?k\u0007&_~\rT>l\u00041w4za\u0007$e\u0001\t#O\u001f0on7{\u001fϗ o ?<AV z\u001fy_\u0019Qi@s\u0015c\u000epAzZ~\u001bS𞱡yUɧuIupo\b\u000f\u0001Yjw\u000fh6QL\\%ۅ\u0000.č\u000b!\u0005\u0013^|?ԅLQ^>\u0006D-t\u0004:}m=\u0017%iE:OfX;ߩJ0g\u0005d\tE7Jg\u0007췃Df\u0005,B\u001eA\u0004\u00153PG\u001bRN\u001a\u0006hbJ39f^;/r\"\u001bV\u001cNb\n~2ۊ*Q\u00150\u0010,\u0018\bfQ\tb\u0016Q\u0010J+y{w1+Y*Ϳ\f7\n@/P(`Ӕ3$Rvm\u0001ta\u0007\u000bVb5y*b\u0002C4ņAMj\u0005lڑ\u001f\tvw=Hm˜\u0000ޥ8tC.vxy:W\u000b6\u0013oܧ\u0014s\u0011dSCeT\u00009\u0007ه`\u0014Gކ<7\u001eDna=\u0018g7\"<zz7g*\u001f\u0015\u000f)8)Ε#VVSsP\u0002\u0015}\fȄI}JИ\u0015\u001b!u^%CW\u0015gue\u0002cج?R]o\u001dѵ \tX\u001e^v{k\\mOLjk)eeF:`7B\u000b׭C)\u001bg?\u001d\fw\u001c\u0014_\\I@U@\u001e5X+;]aY晻C @OScRӢkv\u000e\u001bћ0\u00113j=\u00136/Vpt5[hEe=\u001fV\u0000H\t-:!E \u0007O\u0003\u00029N\\9t\u0017rU$z 3)s;br7qm8쾽r\u0012\u001bm66Q5o<UӨ=\u001b謡ؠVAQ\u0004O\u0001wWg\u0007@'ߒOF0\u001aLמg-\u001aAJ\t\"Mב\u001f7a'di{]Q\u001d\u0010<cnL\u00114Yu՗b\u001c\u0015c7\u0004u>g^جw:?ſB7?\u0019Y&\u001cW)|z@(5ٽkyU\u0013ckJ]lgW=o\nS\\qt4fR%~1yd\u000fM\u0013TwbTB~\u000e\u0000y(Sa@n~\u0012m3{\u0002]\\*.HAg\u0003f6MZ2ran1\nb'\u0019` RiN\u001bپ<q=S@i_{\u000fk\\~ &[\u0012O<jqgO\u0013I+q5j6={)bƕىť-`Fb\u000fN7Y\u001fW%\b\t0ߗ\u001f\u0000dJ$71IcDV'5\u0015-{UqUl'\u0006\u0019omM{S{\u0019j>^T\\rv'Ȥu%>\\e,W4m6Ա\u000e#\\q\u0017ԱL?\u0000?yhӼ\fr\u0010\u00153\u001dM[Z F?tX\u0012w E[\u0015\u000f\u0014հxĳF2\u0000\u0013L,$FYjhz\bJR;\"!mHC\u0003Y\u0010O\u0001͂\u000fv + \u000e>=Aanc{u7X'˟\u001cv\u001f\\Um1{9j0i\u001bp@+\u001aI#DuI\re/V_g\u0011A>\u0012#Ь\u00072Q\u0002d+^\u0015\n9o#kHĢU\u0005du$6gG\u000bI'ΫD|/v)*\u0014oXk$\u001cG<\u0010ToqhsE9\u001br\u0016|l\u001eh4o)@f@VШ:Q|\u0002q,/iW9,\u0019v4_Wݨa\u001a2ʫ'CueqlNݎO'[b)@FCo\rA{MSAa\u001fll\bNȍ)25,mVV{;\u0017ow||;a.\n>nzm$j0%\u0019j]z{A_ZƑ$X\u000b_o\u0005\u0001Nٜ}ł9\u001dţq\f\u0001\u001f*i\u0006?[6ﵞ7t\u001ad}iNE7Spm}</DYwn_wzx\u001c;u\u001b:\u000b \u0013Y*%:z*#\tiQ_\u0002D\u0016\u0000~\nX{gJ\u0019N%\u000f\ns\u0012\f\u000blͦｧmܨv׍鋟|Grc3 5Sә#I-\u0016h}L'sy\u001f\u001eu!?k\faKVSM\u0014 \u0013)\u000fm8W#!Ƀp%yqS*_EY~5)\u0015Ms6أRZBwmI,Ny\\)\u0014S1_9a1\u001c?=5!egݻi\u000bo\u0000*7\u000f@\u000e)PHb9\u0001jϷ<#8\u0019eWUSY{\u00127Q\u0006I?\u001f\u001f\u0017pۀqem\u0007{IJή\nJ\u001075t\t-Coq)\u00005=?Aa$~39Ta*5m]\t6Nk=3)ӢJ>$Yf O\bY-wF\u001bIvk\u0017O@MU¨J53iPW˻ʭJ\\\u000fO\u0001#\u0001Fk*Vd\u0002G,u\r\u0016Zysh=csB4A\"ý%\\Ƙ\bBO\u001fZ1\u001eu;\twlw\u0013lj7g(zX9n=j\\C\u0017_ g9\u0007;\u0012-2i}O\u0015&OfW\u001es4P\bߗ1\u0017uޫ4F\\_Uų:m4޿/\u000f\u0004\u001aCL+>V[h\u001d۽ܹ&\u0000\\Y{(\u0014zqrRnٽ\u000bY#^%\u001b\u001eM\u0004jt].ۨ\u00036-5&gXe1$\u001f\u0002#\u0018mk\u0012AJ9|¢p]>\u0014;TUc\u0013)spMtFiq4DI\u000eG|ڬ֡\u0013>*[Ɯ\u0013\u0014ܦ\u0019\\j/جD\u000e,z\u001ezuWu6{\u000e#\u0017+\u001eUwQ\u001a\u0007tꭸ\u001fY\u001d\u001f\u0005m[}oζw{LwM\b\u0006`ླྀ\u001bOXrK{@?=SJr\u000e\u000bLc\\z`-Fa.\n\n|eGһ:憞4.]MONy\u001cU#SJC}0MvD/ڊ/glaM'}KO8\u001aށʥv\u001bsê^\u0000&jV=Y\\eҥ1`KK(5TJy^\u00198Z\u0016rcS\u0000\u0001~\\\u0000>b\"@H\u0016գ\bHSL\">\u000194\u0000YG\u0000J/j=\u0000Ӏy*g^\u0003J\u000bz^\u0003\u0018 q`O[Eu\u001dT{\tn\u000bo2}\u0019B~\u0014\u0003]o@g}R\u000fd-3\u0019\u0006\u0014z\u0001ٿA{>\u00054(g\f\n\u001cǀ,\r?0h\u000e4\u000e%@$=\u0016\r[\u0000\u0006\u00008S\u000e˲?\u000bo\u0011TWO\u000e\u000b\u001cYs'#\u0002\b\tB\t\u0018\u0005\u0000\u0015\u0007\u0006\u00196@f'<@fw\u000ba~\u0006y\u0004\r-{A* *f8jt*('\u001ap\fG}r\u0015TѼO#|#,\u0000@(\u0019\u0007*\\\u000bR-@.ȸa\u0000\"<\u0014/\bKvxj4T\u001bBSF\u000b\u000ehw{ϫ0\u000fG\u00190s_ͩ\u0006k*\u001f\u0012e|_\u000e@sPhB\u001bF'qY\u0001P\u0000l#@T\u0011PŖ\fjkuCg4>4a\u0015\u0019彮,\raH\u0017`FHZ@'v:H'\u000ebNő\u001b\u001f\u00166ӆ\u0007\u0006\u0019\u0002vam\u0003*\u0000Ȧ;4\u0000PކjOfgY=v~<8)3ʷr׭p\\k?}sOr+3NSv?#~'AFǠV@-6O\u0006Qɀl5\u001al#\u001ea0Kp\n\u0015˲fk[\u000fAu({z\u001dͥ\u001e\u000b9i\u001dh=43j}sB~\u0017\u0000qfPI,U>\u0007xT?\u0019\nu\u0007\u001eA\u001ddQT\u001e[N8]Z-n;T2굋\u001a'\tm\u000fl\u0017b\u0002Qa5\u000fV쮑G\u0003n|/\fi@OF0}R\u000f W`\u0017y 1}m'^ K\u0002*\u000eUع\u0006\u001d\u0015b\rrIF\u000fuz\u0006\u000e%?P؛\u0006\u001elg\u0001\u0016*\fG|O\u0015\u0006!Y;҃M[zL\f3?>XL240:\u00132kUь[2yrs\u0012UgRQޅ\u0019,k3\u000f#q>\u0007/|!\u0015\u0002 S\u001dl\u001bp^sz\fr\u001d\fr1Ewz>\nmr\u000btѶh.aK\u00194S1I]h90\u001eVge,.z0[,\u0014$4ajC\u0007\u0000$%CY\u0018P@\u0005bh{\u0001\u001a?i\rVH(<ν{Y;Xr\u001dF\u0018TrY݉gOĮ\u001eBݞH9IwP~\u0010)\u0007G(I s}|-\r+F\u0013G.^D\"dC8#\u0017JEgwۑ\u001e,\u001b{^ǹ/5\u001c\t\u0001ųŠ/O4V\u001a;nkh76\u0011\u0019\u001a,;*\u0005$\u0001)\u001e\u000f%PB;\f䙧\u0017]\u0016\u000f\u0013툹gYh#\f%ֻ<vT(fzޭ\u000e\u0016v\\jO>6ͼZL=&\"\u001cox}\u001ee*jV\u001fX\u000fNbv-u(7k?G&gq\u0007T\u001e#ɷ\u0014>\fV\u0016U\f\u001a}s#wY@\u0016g8*-![kY\u001bhz率2}\u001eo_ۈʁv%ު'\t%Vh%0\u001d_+U`Y\rc~\u0000h\u0011\u0014I@{\n$l\u001d\u0016}^Y\u0014\u0007.ʷRr=Y'-wj6e^+ZinoZS3my̛h|.u*\u000eo\u001f\u00057xvM\u001c/䷂1(ԒO\b|oɮ\u001f6L\tOkIG\u001d\nҭNԆ/\u0002/5xw6e9\t\\&\u001e{8\r.&%:NUF\u001fK\\\u001f\f>\f\u001f\u0000b\u000f\u0007\u0002t\u0002%ɷ>&LehկxM/\\w\u000fLap\u0019(ɜ_fp;ׯgS8G\fW۩w\u0016CO\u000479⮚An!XK\u000fEΎ+U\u0017\u0002@WPh\u0019le\u00039oB\u0002\u000b#{z\u0010E\u0010{\u000fϞ0VK,MxDŢѦb4\u001e)T\r\u0005c>\\\u001fFSe6I\u000en\u0018ځ8\u000eJު\u0003)w*uT\n\bG|!\u0001v\u000elȎ\u0002\u001cP5B!\u001d|E<h\u001fgԲ9T286\u0007\u001cUQ굤\r77~v̙\u00143\\y˒bsh;G+7R͔ʭ\r\u0019\tw\"I\\&\u0013\u0000r;\u0000*gG Bn8\u0017_ȣsYM>\u0004pFWNcaքb\u001d-p_=%ً}yUbV\u001duTr.J/;M4)pХ\"/DDQ\u0007\u00009\u0002|@N\u0015ʠP᚛jN\u0004aY;݊\u001d 6(,-|6D\u000bﯛl\u0006vPrI\u000e1j \u0015g֌f;|toh\u001d4(冦\u000fz+Ɉ#;\u000b\u0013l\u0004gt<W;\u0005֍\u0013ݤGlfNylβ2j\u000buD4PLn!,A\u001e5v\u001bL˲\u001e\u001fU{Sg%_KVfi\u0007|uiܳ0S\\h<m\u001f\u00006\u0005d=^J\u0001\u001cII歹&m'WXnj'xzԸL2{k\u0007Ǝ̌Љq[AQs(PI\u0006t|m\u0003H2[*M댡|!ߗ\u0003PӍ\u000fcN,\u0006@I;\u001dMq}\u0003ll\fj_G1PA\u001e\u001c\u0017<\u001b.OXoɖ,\u000ecYx\u0016B9\r\u0018_EߊzF\u0006GWXp\",t4\u0001>s~^iڟ2C m\u0015\u0018~c<a\u001eVEiOw|9Wg=\u0018amȷz\u001c#\u000e{fu\u0005\u001ci\fY1Z#?&+'L\u00071bN\u000422\fvf\u000fp;-#}3gYMu[\u0018Ox*O\r=%BY.\u0017TC\u001f{Jh+&>ט*\u001fA{o\u000e$^*:\u0016\u0017c\u001d\u0016.nɉă\u000ei\u001b_ȯQ*Ug!-H\\\u001c;ϲ&838wu9\u001c)B'HCkzK\u0015h?k{\u000bm\u001bڟ݋,zI\u0011n(\tVXQ9OS&J\u0010\u000f2/dKz+nN{b,b!zT`Viɕ^,\u0016yC8T&f𬔙Kn^\u000eDQɌ9O\r\\-j\u001d\u0007_\b}77=\u0011y\u0012nʼc \u000e\u000f9*5p9Y$?uqg2\nd|PKg_~i0JMVu5S)ZK\fWcblbgT\u0019NfYR-J\u0015\"{([(OԴqJeHL\u001e6j\u0005Z\bQ\u0003\bæub.\u00187\u0012ؕJ s\u001b\u001c<C?_Rr\nRq\u001f\u0017QK\u0016\u0019)\u0010a\u001f\u0016BRt؜\"p-N\u0007\u0000x\u0000ٲ>떦u\u0005\u0000\u0004*\u0002y6 \u0014\u001f\u0010\u0005\u0007\u0004Y\u0001~+\u0000\u001e6\u0000o.\u0000b]\u001f,C\u0015`F\u0003\u001b\u0000=eItX0zU,ԋ\"=^~_B \u0013_\n//B=\u001b`=\u0014\u001b&\u0001%@,\u0016\u001d@\\I(4<\u0000a$2\r@$t\u0015j,\b\u000fC\u0001\u0006l5\u0005ZكXաڸ\t0\u0001X\u0018dFY3Y\u0006\u0013j<jߦ\u0013\u0000@\u000f\u00018Y\\\u0000\u0015@/2 \u0006\u0017\u0002\u0012RpM@t1l\u0005x\u0003ܒRPNABSP\u0000\u0018Hu\u0001#xl\fd\u0004U~3^we\u0003\u0000;\\BC\u001br\u0003tJC2tN\u0007\u0000\u0002\t\u00009l\u0016Vs=\u001eP{\u0007\n\u001dB\u0012\u0002N\nP]j6\u000b\u001aF)q;j6<~*؞{Hn.g0[\u0017\n\u0000kK'Т\"lv9qރWA<8 S\u0001 \u0003\u0004m@9 n\u0013 d4BB2j7bt8ûZ4\u0018؋6)/\u00015s{+Y7ߋc}~er\u000elNޟ,\u00062\u0005\u0000\u0019@L2aN\u0000YA9&|Y|^'\u000fY\\pwaL\u0003\u0006Aa\u0018y|z\u0018IS\u0001\u0000n`3-?\u00074%A\u0005\u001ed\u0018P\u0018\u0007}!\u00052\u0014\u000320\u001e(\u000bԗ8dY4^Gt\u000fֳ1沣pyÜխ\u0003-vNC\u001e\u000f\u001d/=?YPB#\u0002j\u0004(\u000fdX΀(\u0016\u0002\u0017Up\u0003(\u000eI&m=9,T\u0003\u0006ʋ*\u0011wN\fY&\u0018.\u0019Gɽ]ai\\B\u0007\u0000gd0O\u001d?M8\u0019@\u001d\u001cdS'L7\u0005<V\u0016=9 uGr\u001ayx\u0014<q)h8tKٽhQ\u0013\u000e/\u000fmM\u0000;\u000f7\r\u000f#5b\u001b?\u0000-\u0014EPB\u0007\u0005\u0005$.\u0000`3ǚf\u0003=I,ncPӢ]\u000e5{ۣ>p\u0010oOBꀴql\u0005JV0oFB^mk;r\b=pb/P\u0002C>8\u0003\u0011lG~GT\u0010EE\u001d1u|-m:\u00166{ol#?>l\u000b\\bOoլdV\u0007\u0007mPE\u000b梤^!\u000f\u0000\b}rM\u0010}\u000e2N\u001c\u001b&?}<E\u0007\u000b\u0004\te=W\\oVF;a8ӹSaC˪DZj\u0015G\u0002Se~\u000b=٩'846g)[ҟQx;\u0000Bs\u0000\u001bg3Z\u0004ٞ$nb=<P#oju\u0019UU'\u0007>̕f/u^όTBw{޼ʔYTMMɤ8M\u0011ؾձ4Jc//+s\b2>o*N`D\u000f6t>\u001fnz.ͣݠ;\u0013o;4kW_o\u001fϩq\u0017\u0017\u000b?3^͙2aOOLJ3h7r\u0013&܈'~6>\u000f\u0000Z\u0000\u0019О\u000bdn\u0005p\u0007r|\u0017Tva6Kr\u0007\u0011Km[A\n8w\u0006bƳϧ\rXjd9tRJZSWd]+V\nU\u0016TKh\u000bu_G(I=oI\f Ϙfh#/oQWw\n:\u001aŊ&¡ cxRa<&Rٙ>,\u001fZq;ڪ0=40\u001b=:0b\u000fr\u0007 Z{W\u0004([ zqi\u0004W\u001foLaߖGf\u0017Q\u0007qy\u001ci^t\u001f\u0013\u0004\u000e\u000bR5O\f\u0014[\u001ary 4@^\u001fo\u001c;XOZh\u001fU\typM#\u0003\u0018\u0012@9s\u0016\bFѪ\u001bWD\u0014\u001a\u0017\u0017Z\u0015\u0007Иdf-k#\f.3-GJ\u0012\u000b^~\u000b\u0017\u0000$?Ο3Sq\u0018\u0017\u001bg}Ҙ3b{Կ\u001d\u0001J)\u0013o{%\u001d3ANYL/-wa(\u000e\u00121ߚw/drcS6RnnAB\n]Ed\u00008&!\u001b8&?_:\u001c2۽\u001a\u001fG0qɍ|>X]v؟dD\u00195qE\u001a&U'=V)^IYaʭ>nG<8\rOtKmŁ;!\u0012߿\u000fm\u001c\u0014J2\u0003@\u0007$9Mp\u001cleY\u001eHC~Ax\u0013}?=Iϔ+W/>\u001c-SS%gp|ļܴ\\\u0015G*չo3f#\u0003+^:חWtZ\u001fh]裈\u0016@+ӂZoB\u0014J\u0015\u000bd\"\u0003ٝ|Z\u0004\"`غ\u0013!W,\u001d&ɕbs\n\fr{Y1;\fraMͰgkٔxSEMh\u0014\u000eAX߯L$^f\u001e\u0014~\u00006\u0006\u0003緤\u0002c\u0003\u001e2ĥ[<\fHlbm\u000bfD\u0004&r=\":4է\u001aRߝr{Ԥ{\u0012v\bfMm\\Yn(g\u0007~M_\b?f\fT>(\u001d|9[͠OOsԭꃣK,5QAq(X.vl-^\u0002T~5B}x\u0003E$_ MGi\u001b]eYZ$3ɆhN4Z<\u00049r͂܈Ef\u0005͖V\u00002[l\u000fz7#.-wR0;mٰLĮpW~vةs?ŉL\u0002^\u001b\u001b\n\u00051\u0013>a\u000bZe%4*H\"S\u001dd\u0005qeAnY\u0006\u0003v\u001f\u0000PS|Osn\u001d\u0006/\u001a6KYy0oc}\u0019t'\u0019t\u0012-I;\u001a\u0017Hk*CU(\u001b\u0006\u001c6cy\u001byz;mԥ~PGCm\u0003D-?\t=rG\u0002,4\u0017h,_Q\u00147\u000fI[\u0017F=_?ɏ\u0016}\u0007w1gU@qx#\r&\u0019}MN\n\u0003R3\u0016v#nu\"I\n_u\u001c\rb\u0017_\u0017&0`,qym[)<=OdLOvj`\u000b2vRfb(\u0011XXCϊn#4\u001e\u001f'\u0012\tI\"^Zl[ڵxtd0En(m\u001aB\u001d>nv,5VͲۜc\u001a\u001e+Ϸ\u001c)\u001dr.#bAT[Z0\u0002\u001bB\u000eR΢-V0\"\u000e~3\u0010u_|j\"ZR\u0010\u000f`P_Nϛ9\u001ekg]\u0013[gOwN=\\:k3GtFCaY\u0004Z\f=\u0002N\\\u001auT>;٪M]z\"\u0000\u0012:Yr\u000feKU(\u000f,\u0016J\u0010\u001f|_VY0\u0017\u0016Na\\\u0000b\u0013Ai`э'ǙJYӄyc^&5 QP敾Jh\r::xn/Uz\u001f{PCB6,\u0015^V\u0002}6;cΛ\u0007iv\\bMٞ,\rt[ԑh\u0011\u000eyۈfeZyx;ŞZ6:¸\u0012ӢT\u0017\u0005w\u0014\u000bDp͝!WH/Y]<2\u0012ԤHRU@fj!Sk_\u0000X\u00008,\u0000E\u001d\r7\u000543\ni\u0003pJ]\u0002<\u0001(U\u0015`D\u0007`\u000b\u0018l\u0000\u000f\u0000>@\u0017\u0001\u0000\r\u000eKm\u0001@k=-&%yzzx7zX\u0005#ԝ\u00034o\u0001f}C\u0000\u0000\u0015\u0010+\u0018W;m\u001cu\u0018i\u001f\u001d~\u00020nnC\tj\u001f\u0000KT\u0000}\u0014z\u0002\">yփj[JqkzD5cgQX\u0012q@Ku\u0000X\u0000e:\u0005r\u0016\u000ep\u0002|b\u00000\u0005/\r7\u0010)\tm{\u0003J\u0000\u0019:\u0015`<\u001a\u0001\f]Dd\u0005hB\u001aw(&8I0\u000e\f\u0014\u0018}֓\u0000X\u0001z/aJ\u0001\u001a\u0003DX\u000e\u0000!m@\u0010\b]\u0016\u0004\u000f\\y\bpD_AS/;l\u0018:\u0006XF'%(k\u0000,Y\u001aD}\"^{2\u000bh0{v\u001e\u0010-FǷO\\:x\u0007U%\u0000D\u0003B\u0015Y@87\r\u0010W~\u000b\b\u0000(=\u000b\u0000\u0014DO%\u001d\u0004\u001a:]\u0000\u0016\u0000si\u0019,ԪF̟?+q/\b0\u001beg7&m\u0016\u0007whgY\u000e\u0000\u0007b\b\u0005\u0001dz\u0000d\u000e\u0001(Oćxo@\u0012 x^,O\u0000nڰ\u000eĳ\u0007վ_HcLb(bը-4lGB7\u001eaX#EYYsUS\u0001c7\u0000l\u0012C2\u0001\u0000\bi\u0014\u00022\u0002rl\u0002lN\u0000y<\u0011*\u0001YkҀ. <\u0013\rf/Ydsp$$|K\u0014pAuʏpj\u001ba{ɼ\u0014\u001aYr*\ff\u001d\u0000ۼi\u00177\u0003\u001c0ʁ\fY>\u0019\u000b\u000b4( \u0003\u001egIxV\u0010FG4\u000fVQҾ\u0019?ݳ+7i~hzqjt\u0016>+P4;$Tlk'wCTyK4\u0007l(2\u0007VM|\u001d@Fw@{\u001b \u0003Z\u001eā'\u0012\u0013>.vP}{J=2ی.j.:\u000fITugCBR;bO\u000ebԵ\u001ehF)ٶ\u001bP#\u0005\u001bZy2\u000bn'#\f(ԕ\u0001%րo\u001f`옭>@\u001f፬&W%4i\u001d5B\u000ek48s36s%6hA(\u0013KWk-rήw@\u001861y?_\u0010'x\u001aK\u0000\u0015͸P3/!M)\u001d=$9?fo\u0017Zv_\u0014\u001e:Um&E\u0016Ps\u0011$Mí\\h\u001a{\u0015FTCV;؞t\u001b@R3tVQMO\b\u001elj=\u001f\u000b\u001a;J!jZo\u001cDi^ҡSؚ'nssy57\u001b)Vq]m{+یyenRB;<\u000b+oB~+\u0003R\tZ4>A\u001d/'ֆB{a\n\u0015.N\u0003\u0019[\u000ee.\tU9%Q=ٻh=B`zWb\u000b\u001d\u000bԼ\u001dsZg:5rҔɆ[fd\u0012\u0004}B?%e\u001a[5(uЈkG>Gq\"dw})9rj-{\u0012\u0012fs\u0007R|?Of󶻞\u001apč$DIcI\u0014XΏ\u000bM\u001d\u000f&hw\u0006(\u0018\u000be?߻W\fX.\u001fhro\u001dqj?[#l\\Xk\u0015vy-\u001bJ>%\u0016Չ<6Iױ\u0018`֨;_C|Aca^MNώ܌v\u001c\u0017\u001e<\u0007q\u0013dJHs6rI5dmv'sN`;\u0010/3ЄJnM\u001c\u0017G]Tbg\u0010&_eŻ~NGڥ\u001ao\u001eQRG-2\u000fQϪ\u0015IB(s\u0002\u0019\u0003* jqpA \u0004\u0015Q2\u0007ˁíu;@\u001a\u000eNq\\\u0018쨗w\u0004=7\u0015۪O\u0014e b_t\u0006/j\u0011\u000e\u0017c\u000e\u0002P_p!;%\u0003J)\r\u001b\u0003d3:\tr?Cj{`\u0016q2\u0007\u001chwLN\u001ebJG\u0019?&RU)GUHSi\u000eo\rʾ?\u0010coNf\u001fU~\u0015}K]d Dj_?\u000b\u0000\\@\u0000\n +\u00149[\u0018ևmȧ0=⥁zX\u000fYgM\u001c-F}j1*)5W\u001bײL݃.*La=Nge^Ȑ!z\u0004=B\u000e8xj3@[@'<\nW>h%\u000b\u001b}~]u?xfV\u0013Ζ\u001e7E$NU\u0003F\u000b,D&?0m57P[r)5kO&]\u0012\u001d}\u001doW#L7\u000f\u001a\u000b\u0000Qf\u001c~FwvY`\u0014Uqt[wlϷؾ.Z0kV\u0000^L'4L+\u0002\u001bXdǴΨ\f\u0012:Z+v[e)%-\u0006AFz\u0010]2-u^\u0011\tðܢ\r*^8_E'nFfGh\u0015OM\u0000~L\u0002%>g\u0013\u0003[\u001c yud+\u000eaYZ|@m:\"3vw\u001d!zҕ\u0012-⊷\u0000;\u0000a\u0005s؇ϮW|pYP|ΩZ\u0002\u001cI];\teoރu\u0005N|\u0019\u0015g}0p8wWYH{\b)\u000eDϙ&\u0001&-_9h]\u001a\u0012B6C54j!ߗ?\u0002t\u0000\u0014=\\aN=:?ۮnSN2)o\u0006E|2LjhqԸ<8\u000fQjvBzCV.ٸ͞dJpsp\fLC\u001dE~4U.Z&7\u0011_\u0014M+\u001b\u0005-G\u001d`iMkutzw\u0015v5B^f\u001d@sq\f\u0017i\u000bj\u000e-@;wí\u0017gKBAP!rraBXiQ\blS kp\u000eƄIs5bU;@fq\u0002\u001e\f̓\u001aZO\u001c\u0000&\u0016kZkEF\\cuuI^v8և\u0015]'eN\u001atЛ᥅\u000bGsʂ-\u0011~9帅s&q]\\n\u001dLh4kuӘ\u000buB~\u0006@M΅9M\u0006,\u0018د$3\tQWX&js]ʙ\u000b\u001a? !Y(wz:+lbnpm켡B\u0019|x:\\]qٮK\u001e'N;ZwNUk]iܮuwx*\u001dB鋛}Sk\u0019UZE0\u001bMs\u001c\u0016;?S8Uyu\u001ad1זU\u0015\u0007r,v4\u0011d['>*\nwE\u000bo.)u\t\u0016zd4jZ8BjU~\u0019RCɝ_u&(Q|.D'<,e7Y;7eo9y\n\u0014\u001a%}-|\u001bm3xΟ8tFmSܥ6\u0004^6-Į\u00179g^o!_)};z\"S],\u0017[7ܒq6Q^\u0006F<ufiTjj+\u0007v˓CݽwR\u001b,l3W ҍ9{&ϱܥ\u000e:\u000f=\u001ah|U\u001aۀ\u001eJUB'\u0006:Ab \u0015F×\u001c@읿ÔIq\u0019\u0010ԥ\u001b/DNݼ辞э.-.Y7=mlByĖ۴#\u001e\u0015vQYPY$I8^\t\u0017UcRِZ}ʉfloR4;\u001c\nZ\u000e!'\u000bDlf\u000e88\u0010zu;ćD1OVx\u001eP\u001d\u000e\u000e>\u001e\u001cc1_\u001cUyqFO\u001aIRGN2OXN틶:>\u0017Q|+tq?g<\u00056hNi\u001crY\n26֣&6\u0019k\u001b\nf\u000b'K\u000e\u0019\u0003ҭ3ٔErW+<P,\n56+WKq̛!J,z+\u0015:\n\u000bMSw\tUef{npI]͸\u0010\u0010J(\u0018\u000eY\u0019 \n\u0000\u0012rF\u001d`H\bR\u0019޲\u0003]\u0000hp\u0001\u001c$\u0001J\u0017\u0000B\u001c@SN\u0007 !\u0000,/\u0000r;\u0010+@\u000bB\f@|\u0003 FM)FŹ<G\u0000XW(n+1f\u0000ؐ\u0000U\u0001V;\u0000*+\u0002\u0007>˘-\u0002h\u0000T\u0000Z\u0000\u001fe';7\"\u0004@M\u0001 q\u0005WjAܡ\u0012\u0007>uKFw[\u000buu\u0001\nU\u000fK\u001d\u0000`\u001a\u000e\u0001l\u0016\u0000&Ghh<\u0002oCC\u001d\u0000\fB2\u0001ڜ\u001fjy\u0017\u0002hΆ'\u0000E9\u0019bF{3>Y\t5A\u0005c\u000eBG@+L\u0001\u0012\u001a\u0000\u001b\u0000{D/\u0015-\u0003\u0000C\u000b\u001b`6oЮ7(\r{\u001aC\u00156M\u0001Ām\u0002tP/$4@[yw\u000eTghk\u001fv/\u0011b=&o\b\u0006M\u0011\\\u0004\u0016F\\\u0003\u0006e\u000bj9\u0006s@\u0001l֓\u000f&J\u0004`\u0004]A?@\u001b:6\u0017@*\t霉\tDBhL\u0002ZN>\u000bۺ\u001e~J;7Ԑ\u000b(\u0005V7\u000f\u0015\u001d\u001a3a\u0015\n\u0000\u0010d\u001e\u0010g\u001f5{\u001c\u0003 \u0000?H/\u0002\u0006iheu\u0019\u0013w'9:\\GgUNJN\tP\u001fs\u0014ԙ`乓ڗ5?\u0002\u000b\u000f2\u0000%O7 \u001c/\u0004kz\n?\u0003c\u0000^&Fbأp\u001blB=h\u0007\\!>\u001fQH=0w7S\u0017M\"S/h&.B\u000e:o\u001c\u0011\u0000u\u0003eϣW\u0019\u000b\u0015L\u0001\u0000rBHK\b\u001a\u001f7$;\u0013|\u0010>|#q\u001d[;-\"\u000e7\u0014z74G^|ðZMt·\u000e\t9tBtetź;\u0011߿&(}1\r\u0004zO\n2d\u00072&\u001eLsT\u001d$'=GzO\u0011)Oz<A2\u0014\u001c{>hv{|w>L%\u0016\u001aovNkM{샑\u0013÷t<+\u0011<\u0012\u0013\u0018\u0006gW\u0007@[ٗ\u00149&]'H\nح;6\ns#]?wQ8F}{yvΒX^lnRxfQS=*Y\u001aŹzmeu\r\bAt}/6 \n4\n\b6\u001dJw|;\u001a.2\u000es2\u0002NE\u001ffm\u0000S\u001b\u0003\u0011ȥP=u\u0007\u0005T2A_qX\"6\u0018RnӴ\u000b(\u0018\u0001 \u001eȉ-\u001eY.\t޵׏i>?ҍK\u0016v\u001d\u001f|;Xju\u0011b\u000b\u0005\u0011SΖM^\u0001\n\u001f\u0010\u0012&N\"\\\u001d)緗1^O3\u000f\u000eCl̲k}U]c\u001eࡴ徸%5%N\u0017̴aUJRŜ\u0011Y\nbw@\u001bZJphs@fz>:\u000bb#\u0007rjҙ\u000fz\u0015jY;z}\u0016\\!\\\t\u0017tЯyFs\u0019:d\f,U%ss\u0011|_Fk/ϗhXw6לTY\u0007\\~\u0003\u0004\u0010\u0000d_\u0002jA\u0006\u0003~\u0017?\bz>\r5:\u0017Ց\u0019>oF\u0019J7-W)\u0016j֬\u001btX\u001d\u001f^{1\u001b\u001bg3Ͱg?;\u0016\n;\u0007\u0013hCo\u0012I\u0003\u0001ؘz>Qrc٫X&[\u0007vUvy\u000f\u001cFqqtGM\u0012|M[{Ϙ!Y֝Иq՟M\u001dWAգ|õ\u0010d\u0013\u0015\u001cW\u000e_\u0001p'!=\u0015\u0004k^Ukŭ t/E9:.^\u0007HdovBEey$\u000euQxoL@\u0015-@[jIG9\u0010_%WRM8B/\u0018X\u001f\u00000Aָ\"\u0001I\u001bWq\\zi*ug\u000f^!\u0015^\u0003sk'X\u000fyQLoFy\u0006~c#jjP\u0015QPju}z\u0012\b\u0017cWJ/ސ|I\u001d\u0005\u001ch\u0003Q;2÷\u0005#<|\u0007ߙ}\u0018'R;Yؼ\u0013@ܘm\u000bfqYi^j9S\u0011o\u0011\u0011cj%@d?&Sғ\n=F\u0016/\u000e\u000f1&\u00126Fsdnz^o\u001fsRNƎZ\u00152U$w&F>\u000eЕݩq~~P\u0017cU!<9;\u001dvJ\u001d\u001f]ܺ.Ғ1֌\u000bb6\u001b5\u000f\u0018i\u0015\n9F\\{\u0012DYC/y\u0001\u0010ZE^[\u001cABKƗ/Y5t[iW|1;h+ÖNvġr_v/\u00130Z)1f-n\u000f\tYRȒ+L\rqp5\u000eo\u000f\u0014\u0019UӅH\u0000w9\u000f\u001e \u0011_4\u0017vrkpY\u0005\u001bv\u001d-/f&gn1ǦCw:ՍZO\u001f\u000fD$\\EA iM'b4\u0000\u001c\u0019\u0004]dzk\u000eQ:řI͙\u0011\t\n-NThC+\u0017\u000enpSm{!\u0012oPmEajK\u0007\f\\\fD'|ZʝJ\u0018}?\u0012{+64\u001a\rdJ\u0005fCZ\f1ф\rcY6xgX\u0003[ƾ\u0001Jx/m3>\f1k\u001c8-Yu\u0006b}:pp[\u001bLG~\u0016\u0007U\u0007.2R%f-2>\\\u0018\u001eðG\u001cz\u0014aRwlU\u001bRQɄ\u0016i/*t2\u0005 \u000e|\u0005Ki9yc䫆KM綪V\u000b\u00065=Ȍ6[OEV\u0016D,s\\)-G\u000f|Xy7`\u001bG_*q^Pj;j04\u00133[^[jA\u0019F\u0001}x$<|ya$`0TqtZjg`\u0014=\u0017RjJ^:\u0016y|\u001cʷ\u0007X\u0019z(ug+1\f\u0017˨+|\u000e\u001fN>>?tqsk~\u000f\u0002\\1u\u000bĔ4\u0004[\u0015{`\u0017-[\\<o\\[\\t\bW$a\u0005\f\u0011]q\u001c[NYx'Ip{J/6N+\u0005̨\u000f2T\u0001jbk\u0010[>K\b(fW\\G9<ְaw\u0015zu&]k`o\u0010FNEp#){b*=>J=J\u001f7gq\u001eln&+}\u00154^}M\u001f\u0006(jcz9\u001a=v3\u000f8;^7).\u0014\u000f\u0014Cv^3bR_)\u0006S:n1'\u0003;muSep\"xw\u0013΄(OZ9\u001f)n|\u0012Jg5\u0019[?\u001f\u001f\u0004ZTv6%)Ui^\fP6([kKꗵZ+w!3;VV\u0001^0ߧUA\u001flI}M\ry\\\u000e!ϣt\u000fA\r0=6\u0007gʝ\fmX.#DכGTwE5+rGq̣f\\ţ}z\u0014d@lKq7\u001e^JwTR\n\u0017ۋ\u001ft\u000e6\u0016נ\u0017[S)iA/26izf[\rkm|'WӪ|v7K!nk\u00177T29ƔU#A!YP\u0019q wi~Js$n\u0002jר\u0000iӛf6F_]\u0012޻#>̹\u0005\f%1\u0015\u0003k/{pt\b 3PBs>ڠ)\u001aWXOM.v'\u0019ey|Ɠ\"\u001au%t0\u001e۬vS:\u0005fk\\!2z#5\u001aVME=`V>\u0002KUA:^>r}q\u001cl1@\\*Ku&\u0015~n\u001f5cӿBW鏒\u001c\u0017`\\\u0018%y*ɲ9FZK\u000eL+},s\u0013U~{)|4*Rk\u001a\u0004ѦL\u0011\u0011e52ט\u0012jݦ\u0005\u000bwvƃ447\u0000\u0001byq\u0005Wm\u00010\u0005Xr\u0003GC\u0001\u001a\u0000[\u0005\u0001\f\tPl\u0001\u0014O\u0000\u0002j\u0005\u0002$\u0016 \u0017\u00175C0k\u0006[;\raR\u0010Q\u0005 LF2l\u001cd7'oKP\bC\f\u001e\u0000x8BT\u0004v\u0004d\ns\u0016m\u0002v\u0000Zr\u0010'\u0019\u0004nBp\u001eD\u0000hA ·l\u0000(YA\u001fkw6_TY\u0015\u0000\u0018I?v\tM\u0011<\u001bOX\u0000uuo\u0015ҽ\u0013@\u0007J~Q\u000056L\u000fPم]T\u000eK\u000et\u0012\u0003\u0013\u0010\u0001.\u0006oᒡe_\u001ft~܌ϹF\u000fo\u0001О\u000b.?P̿-\u0001\u000e?\u00120\u0001x\u0003X2h\u0003,\n'\u0000[\u0000\u0013\u000bja\u001a`9\b\f\u0006h<M\toy@\u0007p\u0000jipX\u000b8\u0007ql$~콄m >*ۏZ\u0015i\u0004)\u000e\u0000\u000f7X\u0000\u0002CU>&1͚\u0015J\u000f`\u0015E\u0003\u0018X\u0010\r@fl#xu2\f|#>J\u001fq5G\u001d\u0007wC{o\u000bץ\u001fTj\u0015\u0000\u0015|(\u0017\u0001~wm\u0018O\u0010Fi}\u0019\u0010}b\u0000\u001c;\u0003qm\u00172\t7H&YO\u001a2}\u0004z\u001es910>G8j^o;݃5\u000fW\f\u0011\\0Qh\u001f?/\u0000tc\u0000F7D7)8q\u0000\"@\u0000\u001b\u0001Y\u0002=\u001c\u0002b2\u0000!>\u000f_|ZaYnq0\u001b>n\u000bC~o\u0006+&ڷVus~rI*&wAI\u001ds\u0019{{^x2\u0002\u0013\u000bG%?\u0006&C7ܖn k+\u000bM\bjj\nY~HQ-\"))lۼZۣ\u000bW*Ѷ7眚\u000fN\u001b\u001f\u001f+K\u001ď_\t\u0012a\u000eRtӗҖ\n_\u0001݅\u00058I\u0010{1 \u001b, ]\u000b,>~ɌuA\u0017\u0007eSBH`s>h6\u0017bz\u000er&\u0006DγŞw;O*-_\u0019Q\u0000F\u001b)l'x\u0017[\u0019\u001f\u0006\u0000g<\t\u0006ʃ޻{`\u0013E\u0002w^3\"͒4ԫsŉN\u00184qT5P{qʻ!7Bۃ\u0002\rDUe4\u0017uucdw\\Ov\u0001W)3\u00019Ba\u00002#'9M~%!t}\u0018r#⬴-ans$[ꍤ%+)W>o\u0003|\u0018b}a9p_\r>\u001an\u000fwܒrb?\u0005*\u0014I& '!:jUaI\u00128\u000f\rnianN'UpMWʱE\u0003Qn5\fs\u001e+ҋ0U\u0016@yk5mBם55)c<\u001e7{\u0001ة\u000b͹B=\r\nx\u001f\u001bp\u0005\u0018\\7Nh#Y0ty$c+mǯ_qƼr\f{\u0011\u001cR\u001c\u0019(\u001b\u0019ӝd^ӗ|q\u0012\u0012%tsN}\u0015І8(S+B1\u0004T6u\u00049NQ\u0003nr%\u0003L\nc|r߭ OwB8Fج\u001f<鹈)N)=CNkt\u0018L7[\\Vy\u001dfӭ\"Brʗ\u0017\u0002Λc\u000e\u0010ۖ\fzӆ2\u0002\tzS)t6Rb\n֞\u000fܦZO\u000b\u0010\u000ez{Z?\u0012kB[V\u000eFF\u00145g޲n%\u0014ׂ\u0011ZR\fAE\u001fFRѨS\u0004L&^\u0006/c}\b'\u0002\u0007'>oCa>\u0015[y?s\u0015v(rg\u0017`S+[En&ԕ[:xL\u0003w\u001asE;*j\u0007U4sBTOu8ip<\u001fyN\u001a_\u0001}\teT\u0015\u000eͩ\u000b?2>z4\u000f.\u0001cGɦ\"[-njr{:\u00156mO\u0016N͸j\u0015N}\u0015\u001a\u0011\u000f])0i?ԍح\u000e1 ,)uoj\u0003jQ3\f\u001f\u0005o\u0011N\u0016\u001a\b\u00039ּ$%#\u000bϷp;pi\u001bsLy\u000bZw|0˓\u000e\u0004K?\u0016\u0014[\u00180~\u0019\u001cT4zvVR6\u0017}\u001c2#\u000eN^؝3]̦\"!\u0017qS\u000f\u00125F\u0000D6-\r)\u0003\u0014z~}q\u0007\u0003SlWU\nb8\u0003l\u001fc\u0016Xt5R\u000bKdqLoLj\u0011.\u0016\u0017~BtɑӚ)7\u0019\u000f#\u001f^/!/c\u0002_\u0001G'+FY`lZ4O변;4K@-lAa\u0019aZ|SvκkaFezT5ٰIW,ƞ즿L2R/d8;\"8g\\\u001a55=\n\\<\u0005Ûx*!\u001cU\f\n#7@c/\rQs88Ԏ𽔵\u0003jzM\u001f\u001d\u0000;O(+vK5ﱽ~\u000en)(%P\u0012\u000eKzn3\u0013gs\u000f\b묑2\u0014!ď`\u0005OU!x8W\r;Pgr6/\u0004\u001b)5s7\u0001\u001bG\u0018M#@ͮ,@h\\+-\u001fN4\u001eiU/M\u001euޝ\u0019.n\u0003}پ0=\u001eb\u0016-/m\u0002DCS2Q\u0007֚\u000ev:4ƴ{'AX'ZṘKM浦X0Z\u0019Ċ\u0017z%L\u0018W\u001fDή?8Du>=Us5l\u0001{u*$\u001d\u0007^/\u0000^O\u001eBN\bXz4Rgf\f\u0011\u001bpUuk^\f]\u000fU70aj\u001drQ3\n?(\u00182+3\u000f?~.\u0010]:M?\u000bd6\u001eC~i֭sA \u0002t]'\u0018\n/\u0018on^;Ae\u001fO2Wӏj\u001b'\u0013nc\u0015[6\u0018.vBK'\u0001;jp6zj\u001eM\u0019\">m,2˶ӫ׶ԣV7M\\W *Ʈ\u0010-\u001dC+/\u001en̜K^ȗ\u0006өT\f\u001bӫx<\u0013Y\u001epd\u000ed/\rQY(\u001dsrmgZailMas\u000b.\u0016^\u0016Nx\u0016GoAY>^\u0018j^BDeU\u000by\u001b\u0003[)d 5ԅJzJ늕~!\u0018%ɭ\u0003\u000ea;@1ElUͤ!me\u00131Wlqo\u0011bojܘ+1Qmc2IP\u001dB]W\u001bԩ4:)eu['\u0012ǥ:e\u000ff7Ι/g: ]nQfZ`ks)Syv>\u001b=_)Y>S0JتɩvI^9b\u001crewS긇\u0019lxFZȮ|CƓu\u0013\f6\u001e׌#39355s҉s,\u00177a\u0005\u0019ZrVF%p+幪jOYU`Yb?A-3x\\j\u001abEzs)oQfߣJr<\u0010.q2vKxmgm󨧎|Ut]aT=|UD\u0005UZi;\u0012J\u001dKل{\u0017X\u001c\u001c8\u0017bU\fj\u00193~\u00002R<xAc#fV:4U@Gb\u0016UzV]\fU)#]Š\u0007=\u000brOK磵W:.,fvT|d#G0k\u0001LJ^1\u0016y\r?ݸ\u000f(\u001c\u0011\u0012qimhL\u0016;A\u001ceRm\u000fW̽\u0000S(~.|\u0015\t9}xPxxXse3\r@pm$0p[@̤S\u001ev\u0017.\u001bDKO?nN_[\u001d5*֭D#2\u0016Ub0O%\u0005>k\fզ:\u0018-\u0016(glI`L\u0015;X\u000b\u000b\u001c呖Cqh+D1\u001d#ռ+\u0000\u0000߬t\bS\u0006hj\u0002439أw\u0001%E\u00018TZ:@\u000b\u000fd>3@R\u0017G\u0019u\u000eU\u0005G\u000b2\u00111![ \u0002\u0013\u0006\u0001k\u0017\u0003)-P\u001d\u0001BE\u0002h?\u001b@6\u000eӲ\u000e\u00103\u0002:\u0003d\u0002^e\u00000s\u0001 T\u001a{\u0010\b\u001cnB\u0001Dr\u0007H'5hD=eG\u0007(\u001bo^^\u0000z\u0003\u0000\u001d\t6ME\u0001 \u0005c\u0007m\rּ{\u0012 ګ\f\u0010\u0018\u0000D\u0018\u0010\u0004 \"i}k\u0011\u0013@\u0004B>NZ9ſ\u0017i\u00026%\u0001e\u0012\u0003P\u0002e*\u0012`\u0001b\u00029؏\u0005!\u0006|4\u0001\u0014\u0000\"B\u0016o~\u0000$9\u0001\u0002\u0006@.ߦy\u0014 \r\u0011\u0013T\t~j@IjᙏS\u0006X\u0019\\\u001fr\u0015O_\u0001\u0001'a^\u0011\u001e`7\u001c\u0000\u001a )->y.\u0002\u0001h<\u0003t=\u00038@h\u0005\\\u0006h[\u0018@r_Ns̓ 4\u001dbŘ\u0012rZ?iޜ\u000fsW&o\u000bI\u0016^7\u001e//\u001dZ\u0015\u00004u\u0017M\u0004p#\u0001`P\u000686\u0003,zM\u0001<-<tl%vʋ礰aYY.z\\\u0007?F[3˺/^\u0006M.ژF6\u001aq3}N\\L\u0013`P\u001fO\u00012|@P\u0018CF( M\u001b\u0001ͦ<n^8үI\\#Qy-kV\u0016S\u0005kz\u0017:=!R+ȅuC\u000e1ä~C<ӿ\u0001\u0006~\u001aa\u0001\u0004\u0003B;o\u0001qa\u001f\u0000!\u0001+H\f5|4eԃܮ2\\<v\u0017LU\nQkgѢ;#-׋`\u001e\u001e1X,ko?j}1'vDAv\\KJpon\u001b`[P>S\u0005=\u0011j [*\u0007 +Od\"gE\u001fNrȼQ׍=<Q!~}2A\u0012\u001cA\u0017\tuYymoɑ\u001d]+78G\u0002~<A\u000b<*\u0001j\u000b=~\u0003]\u0017\b\u0003s2\u0002d=\u0000|*\u0001$#QZ\u0019\u0015+W\u000eayT~&zuN\u001bw{9Uؒ\u0013w\u0015ԗJT\u0005?I|`?R\u0016g/`\u001f\u0000\f?\u0000g\u0003@Y\tFw\u0015 \u0011A*\u0013\u0005Awu؏Q~\u001b\u0005Nu6d.[խ7u.\u000f\u0005\u0014Z}ڣ\u0012\u0006\f\u00155\u001dN\u0007K2\u001e?T=z-~XHp\u001b\u0000=;\u0000wL\u000e\u0010QGfH\u0003Hr\u0004TG{\u0006H\u0006\u000e\u0016MJN!|\u0000ٮz\u001bѴ-{u0w_Oa}·(\fVCw\u0011-\u0005U\u0017ҘKY'LZaN\f\u000fvGa\u001e\u0014tn<ճa\f7Bo\u000e\u0016,N;\"y~?Eu\u0011n4`-R\u001ftG?mٵy>\b\u0014d{\blW\\.sѳγ80g%/2\u001e_UFW3Mgn\u0007E\u0017\u001f\u0000`'\u0003q\b`S*߇2VO:8y=Gq\u0004nj\u0017`\u001bʿQmm=jGe+FGsSKbi{=\f\u0007=\u0001\u0019z$QjqQ甪Fq7\ntE\u001c~\u0011\u0006hC. F1\u0019g|\u0017w~$r@sZ<\u00058xm\u0011dGjOi;\u001aV0#̻=|g·\fs,_\u000bP=؇\u0012ჴR-\u001cJJ\u0014j@\"{\u001b\u0000h@,\u000f\\z\u000e('Exg\u0006mT\u000eawﾾf\\WA6zXG#\u001bt_\u001e鮐\u001aϸNIg+a+nxs\"%\u001c%uS\\rbpG/'\u000b\u0018_\u0019.BE(O\u0019R#\u0011j<L`贽m_`\u0016~\u001cn.JlͶ!.\u0019tG4nJj\t=5yvg|Ǳs\u00131p[ۢ\tkԫ`/v_l\u00034q\u001fPKCiƏq?⫓0=ohP~ھꅮ\u0019qEw\u0019[3}5˒6\f\u0007u\u0016y'4/\u001aRUE_vNR.\u0007Pawoš_)m~\u0003\f\b+m\\\u0019\u001eێ;ʊ\u000fFeԦ}zo\u001dbں/\r!mZ-\u001bcsƊK3ݨk2j+|\u0001G\u0001,ZaGgj{\u001e^=^p6ԑZp=~Rc\u000e|8\u001do\u0007?\u000b4v\u000f\n\rggWm4\u001crכcyH;j&\u0018VT|9y+=+5'ڑ\u0018l2\u0018c @>\u001bwG4\u000e\u00072\u0019,Ra0\u0013\bXw8K\u000eoŒ\u001b\u0000F, ){|vV@_y\u0019~\u001f\u0019\u0013;ŭfGDPLO\u000bL*\u000fTS&}[U}!?LF#ԥabfd[]\u001f\u0011\r\u001f3\b\u0018\tc\u001fteN\u0000 \u00017\u0000✰ɡJ\u000fHoSI[hvLE~y!\u0013\u0003F;v\u0015w~^\u0015V)\t]K\u0010\u0019uF)/\fzXUc\u0011\u0017_0N;0lOB@]\f~\u0019_9lX?V0z\blL9ɨ_^y\u0015\u0014\u0019Re@;\u001b߅{mi\t;\t392\u001fT>irc\u00063dFժ3i\nA~-U\u0010Y%\u0018vu+\u0017\u000e^(\u0000fg\u0010\u00156jmYON/:d\u001a-`~[\u0006j>Y-QA7r7$\u0016<XN\u0018\u0017\u001aSz\u001flAOfRW4N\u0003i9o$H\u0010!&\u000b:)\u001f\u0017x\u000eα%K;\u0014\u001d>\u0005ȥvS\bsnz˳2j,(r_W}\u000bP6\\d\u0006\"}\u0019+\u000bm{%~jc\ny{^;MD\u0016;-v>\u001aܰl\u001d^C\u0014\u000f\u001a`\t\u0014/b;nC\\߭x\u00065*\u0003RZϨx]\tU&r \u001c8$\u0005n,YGz6׭'INnvFٲ-2^s_m\u0004Khf׮̚Ⱦ9:Km~C؍[\u0011KX\u0015o4bj.\u001aϒ90\u0017ϼ\u0013ҭ;z=qiƀ\u00105#5oݻӡ\u0016NrPk\r|4kHźQ[]/u+-)o,õp7ʍc5:V՞\u001f]8P@k­pe@zl\u0001_õmsYta\u000fJg\u001b,\"ӳ\\s<\r0VӮ\u0010HI9FՔu\u001cby\u0016U:Zt\u000e!R\r&\u0014>+d \f5\u0014zG9ңL\u001eڒݢަY\u0010z\u0012\u000e4\u0011ӵGwFU_V\u000fbW\u000b\u000fZ駬uy>heE3/b}\r~3jJE2OT\u001f]n\u0017~G΃}\u00182*\"{qYƺ\u001dz\u0010Hl;k\tbSFeXZIگvI48\u0012q-{*[\u0005-ebqL:1.L,/5N^2D0\u001e^ŭJP\u001ff*m\u0017z7kp0Ӈ;\u00148CFd+F*ۨ&~ҩ|7\u000e\f&a\\RJ^5V_y\u0018S\u0002YK6 Ֆ^1\u0004b\u0006\u0003\u001e,S\nG\tM?\fr5\u001ea}-nۢ\u0013ڙϳ\u001deofJ|U\u0017-\u0014?\u0005*_Eb*T:Jg\u001d-dC Knab+\u001c1{J&<fɢ\u001d\u0006횫\\&\u001dfz\u0015\u0017kYy\u0018\"F]//7%;\u0002WbIoM\u00049}8Rmrq$9T\u0017kT֪ξq\u001f?zm\u0012-L\tR\\+OL.mjURcO-\u001d\u001f\u001fLV,h]\u0007\u0004\u0000\u001b@LO_\u0007-X̴{\u0001\u0001\u001c\u0002ߜ \u001d\u0007\u0013>a&D\r\bA\u000f A\u000f//\"HoQ\u001ao\u0002]\u001bo8C8d.u(2')d\u001a\u0003dp\u0003\u0004\u001d\fo  3VA1 S Ө/@&?@O SH\u0010\u0014J\f\u0015\u0010\u00022\nBA\u001cgreJ\u001f$k\u0010]%9\u0006L\u001e\r(\ts\u000e \u0004#\t}$o\u0003\u001c\u0000I\u001c ĸ\u00012{Bn&MA\u0019\u0010\u0000d\u0017t^N D7\u0019.j 3\u0010\u0019]92l\u0013l\u0015/>k\f\u0006_a\u001b\u0015Phw\\9S\u0013\u0012\u0003@\u0000\u0002rZ\u0000\u0019~xt+\u000b\u000fu\u0002\bYx@R\u0000I\u0019\u0004{V\u001a.!\u0014>ziPcĽRt\\RCs\u0017\u00002}\u0015 r\f\u001ep\u0001\u0007;\u00024\u0001:6s\u0000m4@:\u001c\u0016/+@,\u0000f`_\u0013\u0010V\u0013\\zw^|D\r_&Ly\u001et%O^n[o\u001c\u0001{zB\u001b\u0000RV\u0001ݮ\u00072}\u0002r\ns\u0003F\u0000L\u0000F\u0005Z\f@\u000f3%47pyE1)Y׳P>cE\fKJ)4\u001e5hr{z{\u00125ӏߥ_P{}|;\u000b&:S\u001f.\u0000P 5\u0001VC'}2>\u0019\u0003\u0006{Rx\u0003x\u000bC\u0000\tO\u000e籂\b\u0018%^\u001fތmAn!^ܛ\u000f{?|DT4tr>85x;\u0018%'\n^+-\f\u0016|\b:\u0014\rh\nPł2-\u000bp\u0011\u0001~o}\u000b\u0001G\u001e\u001ea/+{۾?q~x[NJʵ{Z8?EN\u001c \u001d^\u0016qx;C<j\u0007F͂[\u001dH_\u001dmM6I\u0003\u001c*ڇ3}&i\u0017\u0000\b<_y<&q[]_݈\"\u001d&`6{\u0007OL/1َ\u000b\u001f@~+6h\u001d5O]\u0017\u0006kh\u0007\u0006޺qd_ßo\u00135w(T\u001f3\u000eb3a:#\u001e_\fy;vx9:蕷o3v& I-cpZ{u\u0015yfi8(:c60̕l\b+}V>qsW~9q~\u0003s\u0005|\"m\u001c\u0016\u0010~\u00002c*\u0019\u001eEy\u001eo\u0003\tχmfLeK-AW6ӁW˗uVvx6Ҷmf>\u001ayg\u0017\u001f߰E)֬cX'r\u0014\u0012RC`l)=\u0012 \u0001Ϫ\u000e-_ehPc~\u001aO6\u0017apܝjR\u0014X˾̦<zVu\u0017ܾ:08dmvY\u0017VD>;\u0017R=-\u0005_n)圍\u0018][`n\u0017\u0015c\u001b\u0000?&twu8n\\7gyVc\t۝W2ksQF)؃u\u0007\"LRs]ޜl\u000f@[\u000b+\u0013\\glFsoO{PXU\rb6)7yypT\u0005@_: SAoDKk0!v\u001ft?jݍn\u001dׯt9>2\tFf}l\u001bga\u0003VV͘\u0012\tG:TR\u000b3\u0016N:Q\u0006ߓ%6~\u0003: :\u0014:\u0018\u0001G)*׍ϕ\u0005\u0010\u0002]Vf=L΍M`qR#Ī*ݬa\u001aD6rZ3\u001a=(A(c)az+}b}bbL\\Wx]֑)$lTu7\u0000\u001cI5\u00001;\f!qtj:Z'\\\u000ek=\nM7֝7kUcԏa8>Oisj-̅u-\u0007\u0012\u0019|[I\r)\f34!\u001fOMZ4SJ|\u001e\u0000ml\u0002b0\u0017Վ~pjv#=\rU\u001cz>\u0003\u0017Ǜs*g\u000e\u001a/k\u0000.3\u001bMB;9UղR5-c}|݄\u001ah\u0012'\u0014-QGī,x\u00183|֗3x/\u0000q\t\n=\u001f\u001d1{ge-\u001d>Ԡ\u0014`I;T[uc:exoJEf+ųQUha'e Pn\u0015'K=\u0011[\u001b\u0002)->?1w#yJӸ7\u001f槹 ș۵\u0001N\twl\u0007=>d5\u001fx\\a7vb\u0005%n/i4V(xS<̶M;\u0016\u001aZӲ!\tdu,Ci\tf\u00022F·5\\Z޹fQ~\u0015i6:7o\u0013<\u0002I\u001fI9x?>rPy\u001csTaShQ\u0014\u00075Vѹw\u0007F]\u001d[\u0015<-}&Et<pY1[|\u001a#\rkÈk\u0006>\u0001+̅ݫA\u0007WԜq>\u000e땝\u0007??V4n>\b>]3*\u0015\f6Gb+ro:]p[\n2הxaM\u000fqW,\u0017V~\\Mx\u0012\u0002_>A7Y¡3X|!۷,\u0019ػ\u00151E\u0011\u0019!Snj\u0012\u0000mHk\\q6\u000f\u00175\u0005\u0016>M/X͜hz/a&*\\n\u001aw#q\u0014\u001eB!\u0001#%\u001d\u0000Pdx)\u000bݲI)u\u000b\u0019O\u000eZ+O\u0019\\\u0000葎W\u001b6`Ұ\tq3Zm&=n >\u000b@fS|\u0013rϷeT'f1AXT}~^ĴU<E\\òS\u0013!]Nm\u0019tZ*=/_avy\u000e\u0019\u0004u6M62'\u00005/}'߳ת\\G\u0006@J{&w\u0015-a|\u001cnnre=!bxA9gGu#z^.\u001d}NfcV\u000fO\"ô^[C0\u000bT^,э'\u0011wW\u0013\u000e\u000fNs\\ߵkW^S\u001e{^E/\u0016L0\u0019=Z1%\u0019p\u0012x\u001f֕GO|w\u001aK\r\u001dNBIsz\u001c\u0012]\u0007m>BԇBb\u001bNSoDr6ѭ\u000bbSW\u0000X\u0018>眳MEN4\u000e\u0018)\u001eP9V8>?dvK\f&'^DMlۺtZREwF8bk0$[͑\u001bn4rO1el#\r\u000f\u0007s\t\u0006#\u0013\u0014\u001c*\u000e\u00164>Uf>8?\u0013?\u001a\u000b\"\u001bw\n:װw1Jw^3N;\u0011t/5\n̫skqNpdC\"F$\u0006z锝צeu_vT6%{,\u0010ZuRkUiMt3.;g>J{4>=AB9pi}՟`;I{ѣ?=[h{}̛j\u0006ٶq΍n\u0015kfO\u001a;j봘V\u0012,;TeI^?hKO?ER\rr^=i|\u0016,mA\u0016\u001d}vO,\rendstream\rendobj\r55 0 obj\r<</Length 65536>>stream\r\nA\"jN7gid)vz\u000bT\rY\u0011NQ݃\n͎_⹲z\u0001^fzɿF%0{dz,QX\u00144)\n]fR\u0014]7@7U<%Y:vC\u0011\u001eK٢5\u000eEaxo\u0013'\f\u000f\u001fq2L\u001b0T;qPG\u00067b|bn=\u00059z䣁+Q\\ݦaN=\\#$\u0015\u0002=ʬ`U'Hi\u001528r:A[\u001b|tֳFg 1E)_\fJp\u001bșUbr\rb>Lѕɥ\u001bezBx4MptB`\u0000ډݡlN8vߠoOꇱ\u0018_qR\u001f8gԝ75I\u0019-ר|vuٓ\u0012_qb\u001c\u000bŷpW3\u000fJ;I&w\u000fcw(\u0005\n\nE0\t\u000e88\u0001\u000e ((\bN \ti߉Q'<P\u0016LaUI[\u000e\bJ\u0019|\u0016R'YMI\\:\u001d(R\nO\u00192+yŞ\u0017izN \u0001;MzMٶZ,\nRu;uE\u0018LiaT004hX)p\u0012\n߽A=@\u0003 I\"ں4\u000f15\u001cv\u0001j\u0005L\u0003<)\u0003\u0002#\u0002t\u0002'j\u0012\u0015 ߇%!\u00075\u000b\u0010^\u0007ȺC\u0014\u0019r\u0003d\u0016\u0000\n\u000e\u00001\n@6\u000eD \u0006y\u00009\u0003/(\u000fP\t\u0002,\u0003}^\u001d`\rV\u000fp\u000ef\u000bP\u001d\u0001\u0010\u001664@&@I\u0001\u000bi{\u0014*o }\u0017\u0001\u0012C;)ȣ\nL[l۳\u0012R͛\fV\u0002v:\u0003#\u001c\u00179?\"f,@}q\u0004k\u0000l\u001c\u0000ƴ\u0000C8@/\b]\u000b\u0016a\f!\f\u001a2\u0003T\u0010\u0001I\u0016Vd|j\u0000ߧ\u0001&XDvC_?[(YG0\u0001Ф\f\u0003y2\f\u0002p4\u0001^\u0000v7߯!\tQ\u00077z<\u0018`2<\u0017X\u000e|>\u0002\u0018-RFO\\9nm\u0005yO\u001cq.M]V{Y[?w\u0005,L>\u000bc@\u0004\f]\u0003\"\u0001\u0002\"7\u0000~5/\u00007\bb\u00034E\u001e\"\tdlE;I?D\u0002Xr.πOIܭ_\u000b7|ƨl`0ǏݣU8nIﶹZ\u000bXZ\u000ew\u0001\u0006W*ɏeI{- l\u0003DM\u0000Oi߮͏;:Y)!>\u0019>AqtS?^\tT\u0015i\u001c\u0003dvEpf;H\\2&Łuuv˫\u0019Ei\u0000\u00120\u0005);\\\u000eR}\u001ds䓍kS5\u0004\u0010~-๴]\u0001³hΛf\u001eν\"y{:F!\u0016/k2Sx\u000eGq~\u001fѴ<s7\u000f??¼@e3\u0018iùN>&x\th\u001f\rH*,RXK훹\u0007F\u0013Uq\u001f.-]z2{\u000fq~ݹry\u001c8>CiA4FםK{pYk߫'ʗ/\u0000z0&\fSq*\u000e)R\u0000\u0019\"l탙\u0012\u001c_{{*F\n\u0011ToF\u0014uu\u0018\u000f]\u0013~\u001fg=uiyR#ޕnyp\u0004%C#٫ab«bs˝/\u00009*R9\tԠ\f4WLx۵j<\u0012sS\u0004]\u00046G`.҇L]|)\\>[}\u0019otQhڜ\u001d,'\u001e\u00165/\u001a!%\u000f~i?T4@/ÿ\u0010ᝓ*K\u0018Tal)~$|H\u001aS?9mr-gq=c^\u0017\u00188%l_ʈ,B6ӓ*X걓An7[\u0014ʹqdQרQeUfk\u0005 M\u001an\tO\u0003!~\u001bˏ>ܪn\u001f\"\u000f*7+2\u001bh\u001d{@ZWQYذ,NCިwI_°_\u001c\u0010ܟ9R6\u0019;>I?U#\u000bxh@^e@\u001cH\n|ۉ/w\n,qϷ\u0016\"[o\u0003g\u0013!\u000b0V樖\u000bW2x!x2&hKy\u001b'xmӤ3\u0003p\u000eL}S\u000e'AzGқ\u001e\u000bU/?ğ\rH\t\u0002 G\u0004\u0005ZL7âo3/_:\u0011=II՞\u00062ar̜,'}7Y|\u00142ojjǼF\b:C̨5Ͳ$_\u0019OTU,S2[yQ\f;jɑDuB:{\rH\u0019K\u0018n\u00071y4u\u0006\u001d\u0005[\u00183n\u001aT\u001cfKv7LG7\tk-+A7u\u001ck.?}ӣ[&\u0017\u001d+$)\u000f)b R^E'\u000f!\u0002D\u0018bo\u001f\u0001/N\u0007CO\u0018hk]\u001c~i\rԳ[R\u0017>\u001c\u0012\u001630/jIJ_f\u0007\u001fbQ\u0013m\u000ea@\u0007Ly8%\u000e;@Bv\u001f0\u001f\u001fm1+a5/u[W\u001bH[JL\u0017\u0012s\u000b⬕\u001fMK*\u0015=m5=8z(0._\u0006kͯJ\u001eN_y\u001c޾Zq\u00139r*))h8\u001e0#ÎR\f?L`Ϸܬ\u0013\u000fNV\u001d?YtGdm\u000b@Vo0̉TO\u0002vi|8p\u0014$\u0011ڱE\u0002mr*\u0005\u0018)5ZXCerzݤT]嵱e[\u000e\u0016J5G${\u000e3\u0015:n_Ldq*\u0017a?\u000f\u0002\u000frrBaҿ@/_{Fƭ)\b=\u0002p\u00109Ov\u0010mM\t\u00040z`k9\u0016sԹS|MhG1\u0006\u0014=wU,t\u001f9\u001f\f\f,WjYՖ\u0017#>\u0014\u00158)w>^BضE\u0006Ls\u0002֋!\u001dJ]_UrhJkd2\u0006ok\t`U9|^n3ȓii6W(^I^J[6^Wk\t8S7[\u001f\u001e[ͭ4߳Pm_\u000f\bo\u0000dCEy7Cׂ\u001d^VZW39dcI^Z2o=woC%c\u0004PI\u0003\u0005ݝ\u000bA\u0018Q:,ngjgod\u000e\u0005Zh\u000eԲ!Ct\u0017/Xi,jO.R57rG,7y\u001a\u0017xhC0OK&*B\u0018#%fCu\u0015\n\rv[}ÂW9.i1ܝ[w{:8\n!i]Q{Uɜ\u0017W뫵CoT<|vYս\u001bg2:ivM\u0005<JD;1\u0012z\u000fS_kTj!|X/aM(N\u0006ܢMߧ8Wy\u0013M5ZI7\u0017k|-nV4#3ɄXyȝN\r>-\u001f/Bɍ֧>'\u0018]S\u001e\u001bF@\bh9KoU\u000bofR+;5UUd\u000el'G5zqfR-wW\u0013=\nΘB|_+\ry{zGbϳ>ݫ\rlbcq\u001e\u000e^Ew\u001a\u0012zy;2!ʳjMo\u001dWӾSw5DQ;\u0017´Y\u001dރ}mtu\u0012꩐ms+}Y\u001fn\u0018T\u001e'&1\u0007W\r{V\u00169иץYT$aF>\u0016ҸƼٌkV\u001d\u0014]\u0007*%a$檗\u0006X5%ew;\u0013|J\\Q</`kl\u0017\u001de0>u\u000f4Y \u0015gLTgL엂,/{BdûRv[޼\u0004ik\" 6pdk3F3µ\u001ff:uҕ\u001bW[C\u0004֩Ԛ\u001cY\u000e\u001eZ9.ͲQ]!Zy2wVa֛D~\u0004[Lϻt:\\4-b7ѥ7zq.\u001f\"S>Z>\u000e`M\u001aҔڊYyocs8\u001cCJۨ:l2,a~[BKJq[sŞv{2e:lz\u001dN\u0016\u001fSUs\u001b\b\u0013nl(O҈vjk׫\u0015\u001b&V\u000e|_2`N\u0019a{(NN.\u000b\\\u0018|O!s\u0018r\n[<}h雘[iXc\u0017fiy2+򆫠n8٢kv8\u0003;i-hWc2\u000b@?De-eP\t˨)b%b#f7,\u0016Fe\u001fwgms\"].&9m\u0001=gYdr-f;:j\u0006i+i-ҝ6\u001f?}=IpT*p>\u001aRE5BXi4srgJ)uRȅG^i: 7\u0017t,k\f'T&yx*neՠœ[%3Hi:lJK\u0018\\%nmH\\\u001d\u0010\u0013Bϓ#Ψfl,;1v\u001cWi](v(`bjh\u0013z\u001e-rs\u001a:cʹM[\nvP\u001eȃq=ipRR&(!$Ia\u0006\u001a\u0010m0\u000fDo킘\u0006\u001a#ƈFZM\u0003)\tPuz?\u001a`Ud\u001e\u0006oj%헺S9Zn;tNn$Of7k;ɜ\rS4\"K\u001b*\u0017Ԝd #FZՒ\u0003y\u0010 @^\rUW\u0014Ŧ6\t\u0006@_|7\u0000\u001a8@\u0014@G\u0011\u0005P)\u0003hP\u0002\u0002Y\u0000QxĮDZ!1\u001e%r;\u000fY֣wnG\t!\r\u00052CN\u001f\"J\u0011\u0007Q3\u0010'Y/\u0000l\u0018'\u0000zJ0O\u0005\u0018Z\u0004(־P\u0017\u0000&\u0000\u0000)(In\u001f \f\tYufM\b2BN(\t0X\u0001\u000f?\u0011\u001c(\t\u001c@p\u0005\bQ(!Q_\u001fs_>\u00131\u0005,\u001d\u0006cD\u0000,]\u0000V\u0000Mx\u0018s\u0001Ԏ\u00001s\u0012\u0016 \u0003ȁ\u0006\u00001\f@\\f6ۇ\u0018\n_\u0000DK[\u0001b\u0000\u00131*\u0002dmG'f\u001c\u000eiB\u000e3׏\u0014\u0015o鵞8\f/\u0002؄FYU\u0006I\u00016h\u0000,\f^\u0007;@*\nPL\u0003A\u0010\u0007h\u0011Q8%\u0004h);wu%yV\u0013\u001bo@\u001eo~Q^\u000ff5~\u0013}f\u0000h0Wl\n$_\u0011*d]\r~\u001f\u0019\tu\b4\u0000\u0018sgV\u0004H\u0011և=;C:\u000fGu\u0013f\u0018\\\u0005?(mw6'˦\u0007ʍS!02y\u001c\u0002`\u001c\u000ec@\u0015\u0005\u0006Dv؀23Z6\u0015\n\u001f}\u000e[\bO\u000f\u000b\u0016\u0014<C[nWvמ\u0001\u0007=\u0013}DRn=Q\u001d׏3IW.ֹ~n\u0016yޓ{_\u0000}S\u00185\u0002\u0010G\u0001b\u0014\u0001:\u001c \u001e\u0001 \u0003\r\u0010nqt\fn\u0007zx=\u001e\u0007PG˽蓕\u001d^e&M>UǗ\u001fynk!n\u001bǖ\u0010\r\u0010]\\z\u0007\u001cu g}\u0017\u0000`y0AL}eR6H-%\t\u001d\u0016ᕬ6M\u001c\u0012\u00035w_<?\"/^\u0016Ns٨Q:/b\u0014V5$٘=D\u000eNϼ\u001cT:gRɡ?;nܵ3~-ӝ7\u0000B\u0001z\u0000w \u0003HM/ۣ\u000f\u0011WYn\tae\n{\u000eȝwX!8g:qy\u0007q.OӁ\fSA\u0012-3ۛwv\u001f2OfYٰci{cz;\u0006\u0016\u0005t):]\u0001IjN4Y\u000f\u0010<9KeOOH^ٟD\u0003浛\u0004j+?kגWֲDkOZx\n^8&uը6),/OcyPxOԖc/[]\u0016&h\u0017\\`d\ty\u0014`:v7xdǖTTG\u0017ǎD5k{߫и_{X\r<\bQW­\rr|\u0006=Oc<ht|-D-\f2,\u0006__4\u000e\u0005\u0016b\u000b@L?)\u0012$ \u000b+π?QgKF*stݛ~\\nv\"mfm\\혙p^X\u0016[dhL\u0017\u00048\bqqƜQ^;l'lj\u0014f;oW>\f6\t/_:>ۨ\u0013@xR\u0007yi8F{<#\u0011T\u0006}Î#N\bWaK\u000fM\u001d}!-ϋesx\u0003M\u0011C5]Hτ-W\u000eL^\u000f1@\\FP5\u0016Y&\t}&t(|\u0001o\u001f\n\u0006\u001a~!R~6:%;yׁN`7׎\u0019;to>y\u001etVW;X3Wk}y\u001by&\u000e鰷L+Pos#\u0016oRy5\u0007ă\u001c/EiF7)\u0005YXe[\u001fdz\u0018[ޑdHp&ΞSYfMvRJ&]7e@\n:I.Mm,F\u001eؘ\\UYx*[:\u001e/8)0$d-\"9Ε\u001aJ3UJ3/ŦL\u0002^y\u001c-wZp1(Ӈ\u000eN\\\u000egsqy\u001c\u001f6JP<?\u0019V9R7l2>\ruLlEӞXWN\u001aBbh#bqcbT!e^C}$~sK\u000f·\u001e܈/Y\u0012Jˡ>r\u0003\u001d^})wF|ؠm=[$\ni=_o>y5lj\u0012SI\f'LYU|lT͕ldh\u001b\u001e\u0012\u000f^vKXr~!5\u0005v\u0014~nӶ`d\u0007\u0018v_~ um\u0013ϵCD9:@6w7VYԦsZys.0*I,,dy>=I\u0002qC32Bt\tG\u000f1JE;L\u0010_8Xv0z=z\u0004P}\u0003i&iq*r]e\u0001܌z\\s1J2ygg؋5A|ߘI]Vs\u001d\u0013av̤O8eq2wCi\b\u0019\u0016'~+{\u0015G'\u0010#\u00015B\u000f`v%,\u001f\u0012g\u000fm7,\u001fٌP[_\u0000rf{9%\u001diezty&c<yr2qo>yZɱH<6폨YE\u001efydֿ%R뭰\u0013Tz8F\u001b~\u0007qi\u0019)n,5C>If_|7}ƽ\u0007GyΣl:ZH߯ohw~4;}\u000fbB\t\u0004XN6?\u000eDvXǇrUz\u001f\u0007k\u0017\u001bMช\u00187\u000e5\u001dѺ\u0014\u0005^haXǚ\u000f/1y\u001e{7r]bT0@1\"Lf\u001d箄e2FlZ\"E8vS3mq>]<\u0017\u000f\u001ef0njw:q\rQ sinj\\yw-79\u0018SRU\u0010dkؿy\u0010\u0007Wm4`y\fYe5hfXv4Y\u0016\u00070߱aܟ\u0010zɯ%Q+bm3\u0000Ѧuj*N\u000bWYTxFcXP\r㊠0'eB}IƇQC\u0016:\u000f0lm\fe.}M\u0016R\r\u001bG\u001a\u0010\u0003r@\t\u001cKyyu\u0019Ue=.ǭ%q́߬oc/\u0005lf\u0016_1޾4\u000eSg\u0006I}sY(Q__\\\u001ak~^n5=ݟ0I⻲<Bq\u0001{1\u001c+CE;\u0017\u001bbKy/DәHVF3U!\u001d2f#U4ZH~v\tƭIQ;t5vޕ/\u000fRF:UGTCTOY%A\u0017G޺XiY\u001du]\u0001c;j\\>Hrcd\u0004 JO\\jzw$.0xsr!{Fm7\u001bhD$)\"?\r]UT.(S*狕Wf[2cteV0,5Mb_BWnpJW~Wߙ]SE[\u001emCl~]zYh=s\u0014\u0005\b5\u0012%\u00136Y\u001ecSz>[Gu6zk.2>TJ\\F\u001a\u0001e$Kf\u001eKf!V>.qӀ*q\u0003,&Mb75FTpVتriJ8SS)rCTD2N=sbyRkr\u001dU\\Uː\u0018Џle\"ҦZ\u0018\u000fKmQ^\u00147Gw_$̻LA\\\u0005\u001c\u000bTɻz\u001a+|\u0004!2yf:Zf$@c)!+Tol2\u001aWGQw2Dj})a\u0007laN>,<^8(:]Hɢ<5\u0015ZQ\u0016],eZ\u0012JXϾh\u001e|\u001aR%W!;\u0017)\u001d=_F\u0016\u001bI8Om\u0015+ծz9^^m\u001bLQ\u0018\f\u0005wV\u000bl\u00156c~C\"DZ=7;_>w>u3ͬ2\\5\u001d˓n\u001f\"M\u000eO)rom\bd\u000fIʊ\b\u001a\u0005_,FpN\u0007\u0018\u000f@\u0017|2W[/q3da\u001egdp?-\u0002=K|blO\u0016h3'Kwө#r\u001e\nYl5;IdIdJ\u001cJu\u0017qD~zYwB?HMl>m|\u0017/f\u001buDwyl\u001fy\u000bLUx6\u0001ЊՄR/eZ4NwKH\t}@\u001e: f{+iwh6J7\tz\u000bVIAnuU-\u0012 F?Mض!/\u0014丰ebkB:!Z\u000fi\u0014W\u0002!i\u0015\fYͰR>^LTjeSIIܥB\\m}j`㨁\u001aJEiDZL\u000b\u0006\u0010Mx.\u001clB\u000bm0F\u001f\u0012)\u001b$9\u0017\u0000i\u0014\"\u0018\u001c\u0000Ȏ\u0000\u0001\b@dV#$+\u0014bsQ'(\u0016:v\u0017Mʃ\f#\u001e֌sQ1\u0015Ȱ\u0011e\u0017r\u0014g\u0015L\u000eђ(`\u001dt{\u000b1\u0003bc\u0018h0\u001aS<J\u0012wWa҉*'GqQ|\u001c~@6𠷘}>\u000f\u0011?_rߣB\u0014\u001f23\u0007A\u001c(v;3\u0015\u0007W\u001a\u0011\u001a`\u0007(\u0005@\b\t\f}ovoFO\u001a j\u001a$(9(׏Q\"-_<8,y*s3é\u001e2H\u0013oY!3K9곫V%\u001cZp\u001a\u001a w\u000ex_k\u001701\fԲ`c\f1\f`v\u0004Ю\u0001\u0014?\u000e\u0000Q\u001a@&\r@7B>\u00004^eY\u0000a\u000ecf\f%\u0016@!=v})UYy2g5[?n\u001f>\fj\u0015\u0001@/\u0004`\u0013٪\u0000E\u0002R\u001f\u0003t#\u001b\u0000{\u001d\u0005!z\u0003PĂ\t5\u0017On Kg؋\u0005y:T\u0004KͥsGSsJW#\tUD}\u0007.*\u0000h\r\u0001?\u0000\b\u0004\u0002},U\u0007xA\u0001UM(ջ\u001fss\r\u0016[*?lc?\u0019;YT\u0017Se#L\u0018_ΚfNǶtb1Fjס\u00010у~\u000f\f\u0004\u00038 P\u0000\u0011Y\u001d1r؛\u001aJ^O{Ox\fޗ\u001cnVO_~ʶS^z9FQ^oL[\u0010st7>\u0005|<.{r\u001e\u001dR\u001b\u001fw}3rid\u001c,CrDa=\u0006x\u001eˉͨ@P3\u0004\u0003\nO|&nyDNƋ|\u001fANH\u0019%\\Y]Η2:vNAhൽc\u001b|*a{%%\u000b0̳\b`[\u0004\u00105ո\u001a+K#!5\u0019[>n\bgHG+ݞevu\u00105\u000fǟ#\u000f>\u0012\u0011`\u00196\u0013\u0006\u0012&5;\\HQ/Gk<\u00123ŮG\u0014}I}!Vnx~\u0001E\u001bX\u0010FAJ\u0010 sJRg\u000b}ީO[\u001f<Q;\u001cr>\u001ev^lu\u0013c7ўG+VNvO\u0016=%kh\n#,//P\u0001\n2?4k\u0014\u0005~y\raY\b`\u0016}G\u001f0\u000fs \u0011n\u0019\u0017v;nӮkMiduɚw3_{\u001d{Y\u0016˘or=7WqfkQ7ʜ\u001bG-\u000eH-\\<\u0001լ@F/\u0000\u0001;\rX4%w\b.\u001e\u001dJ\u0012\u001e/h\u0010G(\u001bO\u001edCtWB\u001d.~[5]F%\\\u0004#t`m\u001dfDal.=\u000e3= [qߪiZ''I9%__\u0000b0T\u0015?\u00019{tݩ}펽=}\u000f/Jе\u0003¬-krF?\"\u00149h\u001c)s;୙cÊNI?B\u0001SW|RݕT]D\u0015L/\u001f>\u0000\b`O1s8uR_r[;!;\u001f.\u0015\u001eھ:\u0011m̙$+=i\tm\u001dlhخ2\\l<\"9,i1%Ƽ\u0004E$\u001bɍ$|\t~\u0003U\u000f!_+uܽGYu=bJ[m4dfxf(DgRF%ئjcM.X\u0018*1\u0019Ec\\Vr3Eu\u001emz=|73h\fb|\u0018:\u0016\u001e\u0011!F=u\u0011~y\u0002R7o\u001e>=:hoN5LIh엕\u0014lFs;7\"f\u0007\u0014MGCeR\u0007\u001fByXm\u0019$iR{G\u0003\t_ρ l^\u001bߗWmR\u0001G'#\t~\u0001R,H\u001e,\u0007\u001c+c:nenKZt^\u0001[=,߮s!\u0007\u001aIiγI\nyE1;27tNo1\u0018\u000e>8]2\u001fB\u00045\u0012K%#<F-K,#8\u0019\\B;ߢǯ_wiw^_é^ܴb\u0019eU\u0013N,a/ڸ|DJGӔRkY9܊=XTGz\u001b\u001e\f?8Y\bM1\u0014F#0Wڮ<+d\u001elƗ<F\u001e\u001fԵ\u0010\u0017avL72z%Û6\u001c\u0016<\u0003E{5'f\u000es\u0014{[}:5aA^C\f3\\1sq_$\u001fC^B5:|\u0003y\u001c{&!]Xbg\u000enr*{2ꙓ\u0017\u0010^7{\u001dS\u000bف~8ڛ6_5ǚ/\u001f㳲^_\u000b{Il]1\u0016KDaM\fݳ\u001d|V?5qVEv痩[#kV.YR%X09.);\u001d}w\u001crųuן\u0017}T9\u001d>ۆʶi4\u000b`aX\u0007t_t\\ٺ|)^?Qk\r\u001eCQ\u0017ނW?-[Gcy\u000b؛w,-Y|\"ĕ9U.Mۅ>:0x.6;dEww_Sj񌭗ZP/:<UTGñrlG2WobD\u0004xz\t3\u001eV\u0018Tv\u00047j]¬U\rWGצǍS(4^CScW󡟞__xr\u0012a8\u0016F<;1Lay2usҴ\u0016KJ\b\u000bB4\u0007D\u0004ex\u001e*@-LKn2\u001butd'Nү<n\u0015\u0001W˓fF\u0003Ϭ)l\u001fmQB=9zb{_Y1\u001el4qѭezM<8ѫY֪j䗳i\u0011X1J+6\u0007͹g\u000e\u001cޕ\u001f\u0016\u0005νR\rdy\ro[\\TplYFTVv[{aMt\fA\u0001&\u0012\u0007d9u\u001fq7}v\u000b)گj`,cΧTDݎȮ\nohԞKiU7m+^[>gELA\u001aQJ\u0012Kj\u001a\nzZj}׫v`.wQ)4\u0019){&\u001fL93\u0003\u001d7:v\u0018t=7\u001da[y2\u0018LHL;v\u001c+kL46\"5Z^)d\u0002Z\u0017\\6˥ZhTigVNՠ^9Xqrvrm.a/}xB|(\u0005yŮ~c֠w\u000b*.\bbNxo>\u001cF2:lui~6n;\nصCjAKcvVZ68zq\u00112:B+mTt\u000fnsє\u0012W5\u000eE\ft\u0016^=N~w!l]:f\u0004Ԟ响plD$68\u001d޲MN\u001fl1UjS)\b.\u001bgA.7Q\u0002,̈V?,n\u0010\u001b!\u0017\u0004?\n?\u000f^\u0015}f\u0017ZN1v\u0016Mk;;wâ[N1~NQ/L5q8lJd\u0016sSť]=.\u001a:N\u000b\u001dq%`7\u0005c] ߠ\u000bzPM\u0006b^rN\u0012ft7nr&R݌hZ=i3\u0004iU\b*\u0019\u000eVT</TK=)kXZ\u001d\u001aMԼi\u0018Rt\u0004`+3-[Bl*?bxYS:\u0012eZi0\u0016閯*i<\u001bT\u000fym(R>\u000fI2:\u0013)׭SAH\r`G\\K@\u0007=D/\"\u0004_\u0010lT|+S9\u001cp6\u0007ZYl@4]MOƨI\u001a8R\u001fJ\u0017RES\"8%\u0012\u0016/D\u001a6ɭDg\u0012i&>j\u001abfpIŅ\u001cBs~[b*z\r҇-\u0012_ϦSlg`R/\\ٟ\u0010%iqjtsW\t5hq|4nw\u0011s\nHK\u001ciU\rDB@jj\u001eiՋIZ?+T\fjR\u001d_]i9`YoP莹R\u0007KʕWn5RlmT7~0\u0012QxL2X-kH\u000b(.<JE\u0001T\fx'U\u000eUH@ߐc\u0003\u0016`B\u0016I\u0018Wh4T\u0018\u0017\u0011%\u000e6> #W\u0014\u0013K4\u0002\u0017\u001d\u0001ш\u0018D\u0015i\u0011hw6\u0019\u0012?#a\u0000dC\f]@C\u001dFG\u0001\nrF} \n|5e\u0000$?\u0000\u0006z>d`0_F\u0010ŋ;\u001eoQ\ba\u0004\u0005DB\u001b2F [\u0012ED!M\u0016Aq\u0004]\u00189\"pzKz\u0015)!\u00106i\u0001\u0010>?%hT\u001c%\u001a\u0015%R˵\u0013FZb_@(\u00167\bOB|PQQyH8Y\u0016BIn\u001fbc=\u0007\u0015~_8zqH?\u00015}\u0007pR'=\u0004i\u0018\u0007\u0007H@G\tHQb(\u0019M(^VQBS{\u0010\u0015FQ'oΤY>g'U[>aC\u0016?Dv/^gu=ƚz`F=XWP$f(C\u0005\u000fQ\u0003V2D\u0015\u0014@k\u0012@\u0011\u0007}dD5\u0019+i\u0007wp.eEF/\u0017\u000e^LK{kzx=L<$t!gZǮmy%V'A0G\u00060j\u0001?\u0000G\u0013q\\\u001a`i\u0001Ҏz{\u0018\u001e1]\tDؾb*Yr?93znw$4)״i\u001f}\u0013;\u0011ws&E5.\u001b=\u0006O\u001eS+qׯ\u0011pۋNj\u000b}\u0018ATq\u0000|+,<I;/bg@\u0007U;\u001a\u000bS\bG\u0001aw˾\u001bǋgK\u0019Z\u0018+\u0006=Փf#%\u001fⰝ+}izhjv\u0014l{/`;n{\u001f4,\u0012|nu\fK&j5\u0003@'I\u00177:=%G>̵dGPyxvN,89L\u0014S=JڦzV]_?\u0007V+yⱶ%\u0019/6\u0001}o; 27y{?Y|9Gb\\̱cK\u0007gbu\u001fn弄vp_O\u0007;$\u000f\u00171>-\u0012VK)}q$1W\u0003r[k)ޗے^\u0000\u001c{\u0017@TpL\u001d<?\u0011P\u0011ex<\u000f{\u001e\u000e].AzW+ͻOձԹof\u001ctViOg\u001aΗY=\u0003$Z+ebn\u0010k-\u0016.}!ޗ|$\u0000Ѿ\b/\u001c}m/7ײ\u001a\u0017>\u001aǎZS!wMѯkZZIVChkqu5*=e\u0010\fO؏z;5\\vQ7ȯ}U[GѬwymf!fNMp\u0015\u001f>\u0015tHsǓ\u001c$\u0017P]^Og(ls׸Y؛\fA-2N?\u001b\\m\u0011d<\"ޜ\u001b`Ԭ\r6\u000f\u0011IʙkDQU/v{J-ԝZ._N_\\ _+ʋ|]~8n)+\u0017U}5\u0013k\u0011qݕq/1\u001f}MEuJ[uu\u00123\u0013VszhɩӐ&91SZ\u0019Uc9\u0010\u0003Fd:l^6jltE/˗Ǝiݽ,\u000e5:F\u0011>μ\rkqЛIskT\b/\u0013`8U\u0003R&3\b0۷Zd7Me:ّs\u0016r#}JF׊Gݲ[\u001ca/[\u001dh3\u000e\u001f;\u001c8_v!l\u00001\u0010_D>{۱=ZUپ'ag/PjTC˽׋U:46\u0013'k$O:Z|\u0019ڙKi\u0010:]cn}2P`0p9\u0019\r2S\u001a\fa0L//ۿD&9<4MFl+ۥb[]Cƣ\u0007h\u001cͬO&鮪@\t\u0014F% fcq<v\u0018ސ{ s\\$m~*QX?Xʅ.x{uv_\t\u000f\\SU\u0002}\u0005}\u0011\u0003\u0006rΈHT\u0011\u00119aNo=yq4.\njԠf-O\u0016\u0011lϽo\u001c=\u0018$xEt]ǲg:ܗ7K˻*\u001dtOS\u000b]N.jAYXCRO)\u0012%5y^\u0012m\u000b\u0017`1ȻK\n\ryHBo\u000fޢ?wX wƸ\u0011e\u001c\u000fW\u0015;Iy\u0010\u0014_<\u0019H\u0017\u001b)%k-'p?GF'V]M-/R'rԩJZ-\u000e\u0016\u0003\n6U\u0017\u000b\u000f\u000f8ط[\u0001؀{\u0012l\u001cw\"D݄_f\\S۟hU\u0004ȩ~l#\u0018ʣ\u001b23;imK^\u0010\u0014k>:CA\u001f\u0000\u000b5Mw.V=A\u0013M -\ts\u00132A\u0014}S0\u0003aŋ^|l)RS\u0007d)\u00151Qi0g(22sv|\u0016p4ѓ\u001d\b\u000fĘ\u0018xcæU\u001a\u001a\u0003\u001dր\u0007U\u000fl\u001f\u0013UJu,@a\u0013'\feɭz\u000fpS䲩LYe>\bpգ+֊`I\u001fX?!!]#\u0004csI3&6\t\u0010\"{Z+Wq\u00147X>7\u0007߼KkjW˒ȻF&\u0019Ao)N@\u000bO4O,W*X1\u001fL\u001eCB5\"x!wE8\u0019\t\u00199H\u001b8\u0011m4Bhx\u00143ߙ\u001cЛۊ]Rс7\u001a9j-ua:D%x4'Dl89?|N\u0018 }5!\u001d̶#Daĥ'\bDOwL=]#n6Ǟ0apT;\u0004\u0005{?ǋS8*\u000f\u001dy执l\u000eZMh^E:\u0005Îԭ9!9?u׏\u000e7SVh\u0006ˬɕ\n\u0013<1\u0014H\\q'.\u0018ai\u000e\u000f<9#ZE秆ˮ\u0011\u0007(#\u001e2M\u001ePd~\u0019Hy\u001eys\r\u0004H#R+\u001c$:ȿO#\u0018t0k\u0012+v=\u001e\u0011ݸJshH\u001bj3'­\u000f|\\j\u0000KA\u0018whA\u001f\u0010\u0011Bs\u0000S\u0000WeVJo{MbLj=}\tRfOd\u00040$\u00063͈:p\tI<}:Y%D4E7\u001f{\u001aĔv\u0014\u0006\u0018{G-Ɣ\u0017\u0015SdCExM5Zp-\u0014^sh]\u001fw!s\\Js\u0011J:[㎵\u0006?`ǚ~\n\u0018\u00139t.M\u001d\u001c2/jfkt腧U\u0019Z\u000e9S\fL\r\u0016UQDN\u000bx\u0013&{Q'=Z\u0000&רu\u000b\u0001m'\u001b\bJ\u0016\u0016\bJOt\fU\u0000p/ 6{8^Pwca\u0019]W+5|\u0012iH\u001ae7R+^p\u0003z\u0011^\n\u000fk- s~\fg?\tc󄦗W\u0011!N\u001b\u000f،߉\u0014gYùf\u001a5\u0014*\u001bJwo\u00024ǈOؽyË\b\u000e[EMO\u0013\u000f^\"\u0002wMo]C<lENşV%]\u0013r3]8ilǢAS\u001a}\u0003֨CyƨuL\\^uU\u0007*Ux2͎fǤ+,\u0014G\u000fR]W x \n482\t7\u0010t\u000b]8S큷\u0019^5T\u001e\t#\\!}n׳Q,\f}t9/4T7@{Z\u0012¼Ί\u0012\u001d<\u0012sg⃳b<\u0015űa\u0018\u001f\u001e\rSk'F\u0003r\u001e*IFi\u0019#\bRKڈV|T:\rZQ?̆*\u001a\\\u0014^]i\bnvf3㄂ڨŃ\r\\\u000bz\\\u0018k\u0002dI|Pq?w딆9\\\u0003\u000fT.\u0000t(\u00039b\u0000\u0012\u001f\n&T\u0005&]x\u0012\u001b=\u0000\fA\u001a86\\WN\u0015_~Rќ\u001dA\u000fcoP,w~=oFW:ob\u0000q\u001c1\u0019\u0006\u0010'-\u0001=2u<@\\\u0007>@\u0002\r s6@9'\u0006F\u0003n~1Feժ4\u00140B#(JB.7ka4vi9\u001foj5:\u0017\u0006O픻\u000f$H>j\u0011 j\u00060O])\tP\\\bPu\u0004P&q\u0003\u0000׿\u00178\u0000E\u0016@\u000fm՝XSٺ\u0013g\u0016/\f|\u001fT[\u0014+i||Jx+\u0001\u001b-w', \u0017\u0016\u001f)ݚY7S]m#8\u0000\u0014,]\u0016d=k֘GCSm,ҷswa\u0015/qJꔦ㕦,W8`ie\u0007_ʍ?`I&iw\f}1f4\u0015\fA\u0019w<MEBxdM>IS\u0004}㏯m2,PZ\u001f\u0005\u001euخפqK_O_W\u0016hHea~\u0006ی9HQ\u001de`g/\u001c\u001c45z|bVϏ&\u001fQJ\u001eB}<|\u0014)Y{\"8\u0015\rbuݷ\u0006I\u0006W`:geFJ*N4Xl26\u001f\u0019'+fK\u0003\u0019\u001cR\u0007K~\u0010\u001eeR\r{#?0h<o\u0006^}ޠ\u0017\u0005`\u000bEHhԲ9\f|Stnj\u00187#\bKIi}JsZ\u0006\u0013Cܓݤ{\nom]\u001b9?,i#\u0016-qSPA4/|kh\u0002v8{_/;^\u0012K?+~\r~,UϗcMJ1?J+X݆Cr\\\u0015F~\u0011N|3օSm\u000f|WWI0\u001d\\_rL/\"AYҝl\n\u0017t-Wg\\.#\u001biRuNWirbTSr^\u000fժQ\rn}{ܰ\rd\u0007u4[Qc\f\u0007\\\u0016Tvj!\u001bEiPX)i\u00164\u0002]%WLn3*π\u0016h\u0015/@O=+o|P\u0017\u000f\u0006\u000b}s;\r;Nc\u0012^}N*kޗ\u001cO\u0002xi7\u00165pG*J\u001ct4wz]o=b\u0014[+\u001fۻhʿ}x4t{<\u0015\u0001-[ɯ\u0002,\u0013\u0007_W]\u001f\u0014ǵҍtfϏM4oN\\,\u0004[\bׅ\u001b,;\"A4LuW/bLxۭ+oW!-r-;8V\u0015n6ƫ19.#\u0004q>\u001aVyn\u0016\u0014:\u0002\u0012ߠfح\u0007>j\u0001\f\u0013yg;m\u0017'DXrзGgf\u000ffu\u000bɿxX\u001b㣟D\u0017 \u0011j\u000f\u000f\u000fDYd\\_$n\\\n!r;?0\u00043/O\u000b]\u0001}amw'^ےΌD\u0019\u001drp\u0004YW0ȽG?\u0003\u001c|\u001aYNljߘ0Q߼\u0007&~\u0015u֓/ytTkG~Yn\u0012(|Զa.i@\u001f{)ղ~Xzǻ3:K;Cgm\u001dFC4=5N\rlX\\\n\u0007n:\\Psް\u001a/#c\u0014*4gp?\u001d`鯙),+ZLĻu\u0013򎜑B\u0001p&$\bǭ.'޷y.o\u001d<\n6*\u001cAw@̲~\u0018Z4:\u0012\f~ж\n9ݺhݮ\u0007\u001f=ܿ|6\u0017Ƽ>Q*8iP墶V\u001b\\t\u001cN#u`)I}\u0019:&$tfm3kh|3)\u001d\u001bSlmh0Pr9\u001d(z#y4?\rB `Ǹ_l5K\u0017Tlw\u0017Rã\u0003\u0004/RbǠ\u0000\u0014kh\u001e3»Ug\u000f}˞\u001d%ܬJa\u0003x\u001cs{\u001btTw\u001a|?\u0011'>w42\n\buVIj~?`֏zs(WYZ۲te\u0015Y\\mY\u001fIuE1ݼ\npY]:zrΦ\u001bJk|نv!yM\\\nn3Ԁq4\u000e\u001b\u001dc\u001f\u00177\u000f/u\u0016U\njU+BK礍\u000f$Ž<\u0003]\u0013\u0007C\u0014\u0007i\u0014(Ǿ\u001b㏻u:\r\u001e밌\u0019&+\t\u0000twdWOZ^\u000b8¡m2\u0015+\u0018X}]\t\rD!\u0017iV\"ƕ5+%s\u0003$i}G<T\u0012JuM0\u0017̈u[޹ \rw!c\f5Z\u001fn͏\u000ePN\u001czq\u0010YϮ\u0003\u0002N+\u001a\u001f_Kl܂cT^\"j\u001cy\u001f\u0000?ɜMH\r\u0012셼Z\u001bVU/R\u0013$A\u0005<\u001bx;1q~@(+v*>T.St68\u0002*sA\u0019\u0010.k>Ȫ\u001c\n7w&̦=\u001f⹊1?;\u0003.k\f\u001evNڒKͰ\u0016g(Xύ#\u001c\u001aP#l\u0004f{csd8;\u001f1 <O\u0019\u0010Y\u0013\f\u0017:3\u0007\u0017Q7\u0007rKB6\u0002BB8ٔ#i\u0011k-sSm\u0002\t5aiyeIRM1%ݯ{\u00198\u0013._Y\u0006cӕ#ӛ\rG\u000f.\u0003\u001a\f-dZ뛐R!A!JFր.?:-5?Nr\u00149bhGpϘ?9d5kR-[>:y*j\u0014`=E\u00160ZnZ\u0004\u0015[\u0005\u0000?)]6\u0011G&Q6B3\u0013FOE\" J\ro$/vu%;oj\u001b1w`\fO\u001b\u0017u*\u000b\t \tl\u000b\u001e&ߢ@ѧ\u0017Oe՛\u0015-%\u0012Qi `4bü\u001f2kw@W[jt\u001c9M\u001c\u0004~<\u0014\u000b\u0013,9&',98\u0002\u001deɆ/\u001a~=\u0007\u0013:Yx\n0V\u0007m6E'L\u0014_-cR\u0017hm\u001e}\u001f_#>\"\r/#\u0003^)]\t\u000bYĳOȕ8ꃻX\u001e1\u0011N%dҕk6!&\u001d\u0005\u0012:er::=Ue&׸k7f\u00052&\u0011`O\u00163|T%\u0016mi䟏{\u001f o@m7\u0004lA\u0001էvg&;dL\\NPHUhc`M$\u0006,ZFs | \u000bRc\u0001bӂ\u00162}xѺh_?k\u001d{'slgCSH\u001f<k\u000b[L+S-\u001fZS\u001aN\u0017Cv{%@\u0014<\u000b\u000b\u000eT\u001f@pbz\u001a|\u0016q\u000eӮ\\V续pu\u0017\u001f06K7*39ڐ}B6\u001bHG5[R7\u0014X\\ިvu#a|'P\\!ޠa4p\u0013(ؚhj}\u000eZ\u0003^]u\r`>A\u0007]u\u001bE:X,51C(y}4U\u000b7JZ7\u0011:emxux\u001d\u001870p\u0003w~c\t֧'5\u0003\u001b\u0013\"\u0003^':\bu\u000be{|*zw7\u0015\u001aO;\u0015/vRH{L\u0011biќ\u000f؜o<ɳk#D?J,K\u001d--h\u0003a՚BE<oR\u0018\u0015I\u0007S4rcoy\u000eJ\u00186H\u0019\u001f[Mڒ\b\u0004\u001e\nѣbSn\u0015|\"hmUPr}+X_>\u001dFr@LmpYh:j\u0010+r,L\u0019Y\u0002#.p3֠̍P\u0016\u001bo\u001eoUs\u0001Gq}g9z+\u0017]jS;Fl6\u0014N\u0003]R-YUe\u0017\u000f\u0015LrZ)wʓk,I\rJAz>\u000eUz~ҵR@\u001f$\u0011Ǝ\bNu}=ܒ\\yr68N\u0013y}h.U\n޹KlZ\u0016y_;PR\u0014JX\u001a+\u0019\b*\u0004\u0016\u0013eZZ|ｩB#\u0019X>\u000f\u0013?;*\u0007\u0013\n\r\u0019\u000b\u0010]8ԆzZWdSh<Aqglnݭ-iY»ZWqi\u0011\u0016\rZc4Ύ|4>.3g۵B\u000ef&EY\u0019\b`c\u0001Ek~\u0001r\u00053\u0007Ku\u0001`\u0012\b\u0000\u0000m=ﶛa5\u001dփo\u000f\u0006E\u000f{s\u0014\u0013Nwꋅ6P\u0012\rٖ@u\u0001ǇR(\u0007z!Uq\u0000pzu\u0003p\u0001p_\u0005\u0003\u0003Dc\u0000\u0000k>\u0000~B\u0000nU9@\u000b <\u0012\u0003Q\u0005(\u0018Lo\u0014\u001c}\\=\t-ݞ\u0019N\u00105U&L'w\u001dX_T7]\u0000ާ4^\u0017q\u0002\b0r\u0000\u0011o\u0000D\u0000\t4@Y%\u0004Ⱥ\u0001\u0001\u0001\u0001\u0014x\u0001\u0018\u0000\nh\u0002\u0014jb_ޫ\"\"4>2X\u0001\r\b/z{g(wg\u0002$u\u0000~g-\u0002\u0017\u001d\u0000\u0012\u0011nzf&\u00009{Sj\u0001\u0004P{\u0004Lʘ\u0000\u0005\u0016wY0\"\u0002\u0014\u000f~\u0005\u0003\u0014\fH߳,};\u000e@xiz:iJ\u001fGim,QΈ{i5ϞW\f&{\u001eo\u001f3;M\u000e3\u001621J8+)#Oeі7O\u0015\b<Bwpҗ\bi΍\bqFx\"l\u00162\\跞\fP\u001912R͘3,\"ASr7\u0010y2 {x(9x/?_ҏ\\\u001f6ɢ\rv֨팱\u0012/\"ܤ\u0005Բ\u000fe:8\u0005\u00074*2e\u0017,x~dd\u00115W\bջX\tO0ct5\u000b\u0013\u001fWι\\_eu~&Q\u0016kh/x<}.}-$}ME[%2\u001c) \u0005\u001b\u000eO#^RcHml7\b?.}_<?Jlzƕ<M\u0004Ց+1ca\u0005/3<Vg\u000b(6&\u0019,N?J?&\u001f\nYpL}[)UG\u001cz~QԐ\u00071;b֮m\u001ft\\-<?ՙJo\\O9\u0000y\u001d9Ψ\u001ce@H^C7v\u0001b_{,\u0019AϷim?ģ_^N\u0019\u0011^\u0000\u000fe0*Ȃ\u001f,N\bxݎc\nW's1lޛa;\f#\u000ezthVC=\b6bq͛\u001aC7Ex%\u00126hÁn\u0015N>.\u001f/>f N\u0006dr5r~[\u001b-\u001e\u0011X)ĖAnwS-nf\u001eMn֍(bE,ł,\"ZE\t^<:]<E\u0007:\u0003݀WgnvX\u0001\u000f+G;\f~妎ʭɳ\u001f\u0016\\]sadoE\u0016|M n\u0019\u0006\u000fj\u001aV|ݕQUk\rݛ4\u0011Z.nOE\u0019<>q@ݔS,4}\u0013؉u\u001c`09>iT\u001fwOxYY\u000b\u00145>QRM(F\b\u0014z\u00150XL9/-۳mB{<<\u0004q=}[i.!>3Yv1YLUfR\rz6s:ҕvԪ\u0000+kO\u000f\u000ebE{m&<\t8֏&)\u0017oF\u000b\u0003SZ;\u0017:\u001b^g>ۺ7$jG\u0016,=0XhQH=#ܫ.|\u0018PNb,\u000f$#Ц\n5\u001fr)e,E\u00171M\u000b˧\t>'+t)\n梪wsaSKt\u001a_Z.\u0007m?FF;\u0013\u00167qu\u001eprHNl%mV@[M)\u0007v\u0001aGFƶ\u0019\rkT\u001b\f\n5\"U\"g\u0011@\u001fW\u0013b,S\u0003mm\u001d]zi8\u001abj=7FtK~|B]J#$w`8OַsD\u0007Võ)p\bZe1\u0003\u000e\u000e5hW@\\ئпŢw[=a^\u001b\u0002\u0011IԈ~\"|p$%;}*\u0005::1`/\u001c\u0001p=\b\u0002*\u0003\u0012\u0010k٢\u000b;Ͻ؁e(\u0016\fSPm}Cਕ׃v\f\u001e:w{[{\nFL\u001aTJ;]S;\u0012\u0005wh\u0017,+|0\u0007KMNefnH+\u0012\u0017GH\u0011\u000bf%\u0000\u0018gMw!#eE\u001cfJ\u001c?kGhl\u0014\u001btԹÂ={\\ՕNPz]'eC\u0014aGT.\u0018Qy\u0014w^Kܝ\u001f{/\u0017V3a\u0017UkBt.[%/zSr\u000f\u0001du?sm\t]:,&=cԠ~\u0012aNF+ʤy_:i\u0014F?T\u001f\u0006=^Bǩ\u0015Yly\u0007\\y(U/\u0017+!;{KYFMU t_/8\u001e-?ڢ\u000e\u000e΍JSw.\u0015{\u001fZDTFU\u00047dYs\u001ci\u0013(;8`F{\u0014Ey\u001d\nÔ\\\u0012Q4f\u0006NKװ2j\u000fm\bé>\u0011˅^[\u0000{Wp<\"\u0002\u0011\u001ag\u0000,e8\u000e,8kY^eW\r\u0019\u0015\u0016\"&\u001ePl\u0013\u0004\t\u001by\u0012X4\u0005\u0010\u0019K# Ga\u0017 ń`B{af|\u0013gW\n\u001bٴVw\u0002\u0003M\u001d`\u001f:\u000fqP\u0005xC)\u0014,m\rB<\u001c\u0000VlKЫt\u001f6X>|\u0001\u000bvʗ,D\u0014b\u0016A\u0017K˂B(^V\u0010ؑtr'\u001cթ譄Fzč\u000fJ\u000e\t{NnؼA\u0006\u0017't\u0003styQ#M*W[\u001c_`4\u000e\u0012W\u001aCpUĀaO!IDn?\\϶\u0012\u00048\u0016\u000f\u0014n}\u001f\u0005\u0017/;W<§⧒f\u0001C~V%h$R硶\u001b|/c!\u000e\u0003\u000b\u0014hRpinL,C\u0019\n3\u000f-^L\u0014.\u0019-\u001b1DQp:j+a i6_02ș;fhggK\r|#gLbE{紼_Z\u0015&t^\u000b\u000e\f\\$\"r\\\u0012kg'vX\u00191/teT}C;@O+ӿpبД!\u0018ԯ?\\<\\\u000fn /p4\u001dd`\u001dufd \u0004\"_`ltO^_\u0005n-\u001c^\u00076\u001eRLoB\u0002Pj(>\u0012rj*a>\u0016\\#\u0001b\f\u001fGodv5\u0010vf\u0003+6轼uԄ[\u001eG\n\"\u0003~7\u001f_\b\nN8^\u0013?oQY\u001fv\u0005y*\fY[\u000bճkx\u001b/G\u001ecl\u001b\u000eae=\u001eowl3i\u001cT#a\u0013\u0014T{U#ۻktwy\u001ezw\u001b_/hw;#Gy369}\u001b\u001f߫oe\u00196miWzsqL7\"y/\"`awvc6S&QkAyz'f'\u000e/һ\u0000ϠWkӏ\t\b ޾\u0016ǃm;\u0010m>am[ݠm?\u001cLWЫۙ6ga~m)\u001bM\u0005\\3b\"`c@3\u0001\u0002Y\"qѻ\"%y\u0002;۶H0y{zJ\u0017rf|\u001e\u0002WmEo9)^T\u000emM\u0001ߢºEj\u000b(Ehd\u0019\r'mhS6\u0010\u001a42\u0015҄2\u000e!,^xaB,\u001dR\u001ai{\rF\u000f3\bz\u001a׬A\u0013ŷ3\nXk]>scJTkITj\u0015j\u000eԕ\fx3\u0003Ӑ?ʘFN18ӽQB\u001cy7i/;u 0t{D$ˋ:W\u0019>m\nôY\u0015Ǟ\u001b26z5*XLKFhQ~\u0018Y\tVM\\!\u0003VqM - B\u0000\u0003\u0002VN\u0014Ǥ\u0003C˂n5< *\u0011Z.,LTlAH,\nܡk.\u0018tC\u0007m\u001aI&b˄H.W\n\ntDc\u0013o\\)7ԬsM\u0017A/_\u0007\u0017XKA\u0016`|\b0 /?ƣiW\\@\u0006)zr{\u001a\u001cJy4{=\u0010m$Q6-M8\u000f3}n\u00176~0)hEXߞk_\u0003LyN\u001a1r\u0001{y\u00058F\r Y\u0017@*\u0006 ]e\u0007 5q3^\u001fNi(\u000e=Zjxk`\\\tmffG%\u001a{Q+{+0X쀫\u001fL\u0004a\u0005\u000eg\u0011=ʽ\u0007A\u0011@\u000e\u001c^\u0010;\u0002\r7\u0012\u0001\u0001\u000e\u00195>J͌%\u000fϺ\u001ab?t\u0014'$\u0017\r?-to\u000e\b\u001cPi>\u0010\u0016c56](>\u0005t\u0017\u0004w\f`\u0016v3no\u0000e\u0000gV=\u0000w(\u0001g\u000b[{\u0003\u0007\u0013\u00108\u0000\u0018e?{jE\u0000Ou\u0011_ќ\u0003\f9r|J\u0010\"XAj]\u0004>o5\u000bJweZ\u00168\t=\u0003:{\u001e8\u0003p=O\u0016_)mG(\u0012 \u000f@\u0018ʷ\u0000\u0019q\u00006@\n\u0015@\u000e7@]\\\u0003\\\u0019W\u0000 Wv\u000f ע:(\u0003{$ĥF0C](\u0016[;z\u0006v\u0001Ks܁O=Bm\u0016 \u0006=@ą,\u0007t\u0006\u0006u\u0005HDK\u0000R;\u00012U[\u0003P<3\u000e\u0019+f<o=\u0019]:\u001b\b/г9Hӕ)-i\u0019\u000b'M\"#)\u00063[\u001d[\u001dWBRg--T\bR\"Sr\u0013=]e\u000e_oMq\u0015E7L_g?}A^>tGȘY0=e1Jhq]\u0011=3\u0007.\n%%#>YS\u0001y|D-\t Y x${`鮦^7\u001dH5\\Jӳ$fa)n-Ɯn\u0016^mG\u0006Ofڏ!\u001fa0KAHQ\u0016\u001d\u001djsߍ\fk'/W\\0>'\u0014QH?\u0015LWZ6'dΧ蘅,沽z)OT%k/'\u0012ML^-`ozT'_M\u0000.W\u0018]\u00051='Rq673́G\b)dmx?+Vhɾ\u001bP6'e!\u001b\u000eF6\u0011g\"c\u0012p\u001bpuڭ$78N>x^8\u0016Jp (p/\u001dw\u000f\u001dbs\u0006kb\u000b,\u0018\u0003kq/KIwڿH?m\u0016Phk\\g\u001d#\u0007W\u0002\u000e2\u000en0/^Cڞ*|>Pq,܋j(춼=]u7ַGYDI\\=ވ\"\u0018YNp?\u0005\u0017*qyQ-Ks\u0011ã\u0011~pؚ\u0005g\u0005_7HMx}Fx{8=t{53v+e]LD-a\u0001\u0017Ep^\u0017{3tHusxTP~/8-<U,'8xv\u0012,W{\b\u0016]g+\u0000\u001f\u001b\u000bp\u0017ji $y\u000fx\u0013ޙmM85\\-/ω\u0015ˬ:4Þ\u0007p\u00151\nY_/\u0004]Z<4\u001dl\nR\u0016x\u001cM\u001f\tX\u0019K\"\u001d\u0014｠]pz\u00195\\kz?>vqk{i/[3),-J\u001d5>\u0017\u0019φ\u0001!ϼ)ݟ\u0005~x\u0016>&?WS2V&\u00000~Qޱ ^[\u001c\u000fܞ\u001dYؓݱ\u001cY2X>\u001f\";\u0018U\rvY\u0000}R]znGwZI֛>7zox\rF9Iuzk{\u000fxxVf?՗MbN-9\u000fϢx8o\ni\u0018jG: _;ʹ9-'5Y\u001f[)z%:t&y\u0015]fܧa\u0019Tb6M3\u001e\r=\u0019Me}633jYܴwC%GCmhIywA\u0001Yvq\u001a\r$u\u0005J}\u001f\"gyvک[ɥ\u0018ڑ\u00105O@\u00174n\bJ!<d!b\u001d1c$K\u0010WmI\u001bVm4D\u0006\u0007H\u0007Ǻyw[kr#\u0006FLGӉR+zGa\u0015q|i+*7Fl\u001eW\u000eZYFG(\u001c{n<#\u0003ϭ]?ۯmqbR6٬hX\u0012h\u0012zNn{KC{\u001c,׈rIhC)\\٢,\"\\zyITZO#A_Z⚼ý1++£n\u0007\u001fcS֓Ox.\u001a\u000ev7xnZ$\u0006GK\u0017]呂j>N!ĩ(\u00064P@\nu]Jy\u0016w9'6jS0\u00129;*c\u0017\teEεYn}\u001f5LpA\u0011Pc\u0005\r=\u0002<އ\u0007ﭣt*S:-\f]?\u001d-Y\"PZly4 >|)|Lʒ4Vzne:5\u0017:ҞyݗV\u0017aр}&މ}>\u0012\u0016\u0016//_ls.}\u0017ظu!Й U\u001fUFg8RdJot9\u0010φ1\u001fgQ\"_Rv!WFJW[\u0004\"w\u0014N\u0018\u000b\u001d~@޾\u0016u\u0010&M;%^\tVa.#-0yo0EXK?k2XSp\u001b\rBoOV\\iGԙ\b\u0000\u001a>Dj>9Ry0'5J\bUM\u001dxc<R1܈}l\u0000\u0007,Ui-Б.+ѡY\u0001)\u0019ݬ(\u0019s\u0017rԪ\u001f\u001ct0ЗȓM\t\u001e\u001b+ꎯ}\u0012u<zD\u001f~ +c-i*\u000e;cm\u000e3r\u000fr\u000eq\u0013l6\u00196it\\\u001cDsJ\u000e\u0003Ue,s\u0010\u0010-8T9q2\u001f!'///_~\u001dtԅ=kDu\u0005\u001aUu\u0002Və5v\u0013H՞)m-p,\u001a\u0018\u0018\t;\u001eG)\u0011\u001dN5ɄeMбqti)Y)&'\u001da@\u000b?[:n1\u0004\ni6㪿p[f?Cg//_6Uwls:]ϛu{~\u0010Vy֓\u000b瑴+\u001euҜ{\r\u0002nXٷf\rȀ\u0006٠5֦u\u0012j\u0003&gI\"5}H[\u0006O\fU\u0014:~\u001dFL|>U/Η\tq-ae0p\u001a\"p\t>ܐ&\u001b\u0018\u0007R\u0014#-\rv$OvJ\u0016ق*01Z\u0014~\"v?\u0018e<tzKߑ$H\u001e\u0011|n9|ܑ\u0003\"C0\rR^jR]\u0013\u0005>r\n2\u001c\u001e͂\\<\u0002~·L':-N6\u00113~&䠧߈\t?񫿯\bpb#.tP\n(f>2`\u0017/\u0018\u0016*koU^衽I\u001b*AQ**6P#6!`;dYR\b\f\u000b/Z\u0012\u001f\u00035G&] h~#\t\u001bw\u0007ߴ<:E*\nL\u0016~|\u0004)N\f,<rO~fwa\u0011ۧA\u0017:F}}\u000eu(u ̽Kf\u0013@nu\u0016\u000b$yOA<'\u001dAVY{dۋ\u00181)QzSy\u0003\u000f\u0010o\u0011p|z2 o<k5K{Xv\u001cU_anW\u00022{ȫ:I&Ʊ5\u0001B5ťx;-1\u000b+oD{\u00125.\r3(zz}І\u000f\t\u0014Xէ;ȅn/D\u0000wLhpo_-vzR\u001bɗ (p\fK2iG`qs&`f~\u0015\u001bB\u000e5(ƯC8qFQrK4LP\u001e[>-;sFbL1=\u0015BHl좐\u0007LJ;־֓3{\u0010B%K:Jk\u0007\u0016DG-hDp\u0018\\qk@\u000fhġRi\\i\u0007YW\\U\u001d'ZD}\u0015zp\u001fr6R,\u0012\u000b5F\u0016kS0Cʘ&hEfA\u0019\u0005cۑz~s\u001c.Z\u000b5qs\u0003V;js[ֹk޻\n<TI-cRl\u0002;/qM\u0006%^UảM1؃b\u0010*`\u001fF\u001ehNQ&TY\u0006\u000b\u0000\"\u001bڥMO\u0016\u0003\r\u000e\u001c^3Eh\nbL\t\u0018΄\"hE\u000e(`u\u0019\u0015(3(\u0016\u001fTC\nJa[}\u0010\u001d83sDhNhҏ܁W\r]OmILJ\u0015@\u001aS\u001fy\u0002\u000fڮ:\t[Q\u0001kE(?K\\7<(u6b^7FZS=`M\u0000}?#]\u00020\\2\u0000\u0000KX+cM\u0003eOQ\nL>\u0000h0\u0000\u0010Q\u000eX\u0003f\u001b]eq)\u0010\"f;=U~Q\"Jczn.ZP\u001b6ny2\u0018E~hφWc \u0000\u0019a>\u0005qZ3\u0000ی\r@n|\u0001@G{)uQGP\u0007TH AQ1(bNPhu|ύvU\u0017SҚk\\ñpj*`K\u0019'\u0001l\u0006,B\t^=\u0013`'\u0001؜\"'p/כ륮EjQc9Y\b\u0003\u000f3-\u001c\u0013l|;\"z3\\\u0014.Ճ\u0007\u000f-o3+}\u000e`\tn\u0006\"\u0005Q\u001e\u0000\u000eM\u0001<V#\u0018pA1\u0007h\u0000\u0013}\u0004<\"J\u0010\fx3\u0001o\tv\u0017-kCN\u0005\u0015vה:~Y{4פ\\`4l\u0006+\u0007\u0015KAX\u0001tmp\u001b\u0003\u0000R\u0002!|̷\u0003O\u001b\u0010r\u000b\b4\u000f\u0004\u0013p\f@\u001e\u0010a<\u0004\"\u0001\u0011@\u0014\u0011\u0010%\u0002F`]`%A3Z+XVOc/\u0014\b}}w:AmfoI_=+~#~3\";\u0010GeJ@߀Io7wNMFW\u001fk\u0013/gh\u0011ǽ\u001cǕ@\u0014ʤ\u00172\u0012$\u0018Xɥ\u0012\u0004W>U\u0011_-^n5\rxG\r\u001f6ݭ%\f\u0014\u001aq+q,]՚I\r8)Yp($XIquV\t<+eTV^^RW}[=@{|~\u0015(o\u001bN]~%^R^\"\u0005v?w\u0013T3~Fj4#*dXLj\u001b*W\u0007c8\u000f?\u001fv'#ZbW3Ϡ\u001fwkFOZ%]r\u0010d32ԓ[[aI\u0013CߓP\f//ok}+ӾJ\u000b59\u0018?,\u001bV%\u0015{GQEKTx6\fJ}|EG\u001aq1:{(xv2vjv&0nz_G\u001f:\u000eY7wm*\u001a+͎G\u001ds-Ux56\\\u001fįMN_E%9\u001c\u001d?\u0010?ݶܬqi<ޚݏ#]Q7/\u0014i)\u0007:[Q>\u001e2\u0007̪\bSl\u0016\rƂǕY\u0018<\\zYQ\u0001Z|\u0015_\u001dn\u001e,~^t\u0017,h\u0002ƯKm~˳\u0000ϔEi\u0013'WZ4\u001d9\u0004Z\tpoif\u001bkP\\\u001d\u000fگ w^j\u0016R2¿|\fա\u0005L\r\nWgf\u001bY({=N9=\u000fԤ?\u0013֧f2\u000f鋇֑h\n{]2^c@yɄXg6'//Y$/tg\u000b(f~\u0016UPì5.cQN;'QSֆ\f[39\u001eegCoBnY\u0006\bz.a\u001e̐A~4j{!h7\u0013tK\u001f\u0016\u0007qַ\u0019)=V\u0001d\u0017Z\t`:ym4mĵS&\u0005pq>3\u001aNy\u0019~Ck}`,\u001dC^&ݍTzo\u000eh߷wڹl8q\f0LlGt\u001f@7x*W١\u000fEQG-a2\u000fHe'<B b\f]GU\u0017ׇ\u0015vE\u001a;\u001d\u001cІ?֢\">9=$WӇ^)YRE{Xh1gƜ[\u000627d\u0007VѬq\tR\u0017ZV4]>i^\f^fI</Fav\u001eS\u0017\u0016?9B/Nι-KD\u0007ݩ{\u000bMrny]sXٰvMW^J>.,5xE.\u0017K\u0003[N\u001ddS?)\u0004U\u00176>Z~ie'g\u0003L\u001e~\u000e\u0013\u0010z\u001b&ЗȾv8i\u000fՀ/@b+f\u001e\rnZ%o}6!ч\u0005\u0016n`#ʢ'fLM1?\u001a\u00005|\u0018\u000fn\u000b\u001f\u0003r,^S\t>ꍛ7AamOIE7+\u000ew\r4t:ēlE\"\u001eJ\u0011\u0011\u00053ՌU)OREsyj(B\u001etHǚsv\u001fzu\u0005d \u0017\u0019͎zȬ.|֙sǘ\u0003Y0\u0005-\u000fQE\u0005-]\r~ tM$^zF\u001d=}zQՌ]Q+ꁯJUlB\u000fݴ~\u0006\"8@\f[WvNCb?hnj~of1uިM\u0016[:\f\u0001;=\u0015\b\u001a-W{iYkT_o^x<ZKJU)ҩvP;-K_u+@*\u0019\u001e}\u001c+\rM\baUS\t\b]N0\u00056R\u001c\\~=.\\;\u001d\\\u0011ɑJ\u0017\u0006M\ni@\u001a{זColTmhp\r1b{q-iZ`W\u001b>kIkS\u001e\f\u0014a8\u001aȕJʩV#AN\r\u0016\u000f^C+֖\u000bAϒۡ<\u000er}\u000b{\u0001!κ(4ӱ٬v'ƠdX\u001dsxjmv'QJQV\u001dTJ2j\u0012\"<]9Zx\u0015V\u0016C\btakHr+\u000bS%\u0003}6?z,]@Fedu4재A\u0007mK)Mzԛ#ѩw\\iyPyUTF'7\u0003o˓\u0006\\T4T\u0015%Pdk\u001f¾8*\u000bRC\u0017ڇJ#?l\u001e\u00152oqڗT\u001a\u0019my\u0005\u0006},\u000f\u0011\u001fv})+׫V)j\u000e\u0016Kfo\u0014񉆲_rzƽ+VVK$\u000b\u0016)KI4!-/fL-XĳqIa\u0013#A\u001f\u0013,\u0005EM2f\u001e\u0019\u001eVR?T߽qxiT&PK/7\f&24\u001dWQLf\u001d[\u0001h0\u0015+\\Ukt*-K*HXF4dA,UB,:<5TBs\u0016\u00193{'\u001c^2\u000f\u0001F~ĺ{A2*K\\\u0019=1|~#iuuPktU_\rέj\u000f+*dyʁn\u00052j9spb\bNb\u0012>.sO0\u0002|O,gX5vXM9L\u0018pgi&\u00175i0`Չ`\\}(+Z;+\u001ailp1\u0005']fUn8_*dj+Z2T\"5VҀ\b|y\"LSC݄ͱm\u001dOeV431\nɀ\u0014\u0004\u001ee?\u0010U[)*\u001cT]8Q96`_1/N\t=B7ޏ9[\u001aPM-\u0011[yU)6h\u0014p?kzrѥ^\u001b!π}\u001d+6%#fN/äy\u001a+Z\"ǰ&u\u0016n\tT\u0004*R#\u0002%NG\u0002%\u001b\u0016\u001f軙8֡\t^7*j\u0019\u00135۾#Y\u001dw˩ʁ{isƳb|\u0019Q4\u0018:t0M*7_zcF\u0015ROVfr\u0011Uǭ4.a\u0018\u0014mQ\u001aa|@F\u001f&>o'GeD'\u0017϶&\u001e'v\u001a5z)j}fZaxBS\rH\u0017ȭ9-!Wh@\u001c\u0019U\u001b<\u0019xNxO>\fo!%E\u001a,:4Uyȸo\u0010\u001f?PyXY̜Je5ݻbJ1ɦrrFbzA;'k.W\\;2jߢ.TdYlPK'=\fh\u001d\u001d5.*ғ!3d2,\u0017$Vz/kF*-\u000eRһ\u00070b\u000b\u0014v+VծШ\\R\u0007bז\u001bw5rj\u0011k^:T\f@MyO>\tK]o2Z\\n9Rԋ,\u001a3nT,k͠pv\nXH筝^Γ흐bl+ǌW>|+F\"\u000f\u0016\rz-\u0019o\u000f/=XS[uh։E\u001aCe<azjƪV\u0006|r3\u001f\u0006Q\u0019¡ɾ ;\u0011 ;\u0011C\u001fٔ*Ґ\u0006u\bZVFt:fT+3W2<Ԏ{&}=2GoHo,U\u0017`:F!5s%~?p<D2\u0018[FYj\f<\u001c\u00192\u000etj.76y-];\nsSF=\u0000;\u0000\u001dǀĔBH\u0000$>0\u0001I\b+@o@\u0016, S\u0004\u0019\u0010\u000fN6$%J\u0011Su?-\u001d\u0003'b@5yk_E`\u0005\u0006\u0011G\u0006fؖ\u0001l\u0007T&%\u0018V\u0001e=;1\u0004n\u0000I\u0003%;\u001b\u0001oՄ\t;@\r\u0019@U\u0001PC\u0003Y\u0013\n\tn/ze]k?\u001dCl5R{B})\u0003^\n7xlg7$wǦ\\c\u000bUHϻJ\u001aa\u0011Ѓ1\u0007٩\u0002蠠\u0003z\u0001\u001dv\u0003LX\u0002<:\u0003F%2i-\bj\u000bw\u0004L(\u0000FG[ƀiPo6\u0014`\u0017\"RۉkL.=<67ݪ؋%_r~`\u0014\u0019\u0018S$^\u0000c\t\u001d\u001d0/-\u0012i\u001b\"7\u0002i\u0000x\u0000\u001bSyɧ|+\u0007q\u0012\u0001.l;\t\u0006\u001cp+\u0000&\u0000w;_\u00185)\\J1y*\u0005\u0001!z\u0018{]G_2\u000fƱ){Z7k\u001c\"ۀk\u0003G\u001f\u00169+={+\u001b'@\u0010y\u0001\b^\u000bl\u000e\u0000\u0019'.t\u0012Dk \u0002\u000f\u00001%R@L#/t\u000b\u000f)2B-'ZMn?j\u000fӸ7zW?n[[\u0011o\u001fP\u001a\u000f 2\f\u0010L\u0019׽g\u001dUV\b\u000e$4m]7}\u0011?a]zǱ\u0014růuƱ\f_.\u0015%-\u0013jA~<^\u0006$\u0004߀dLc}ku\u001eo\u0003\u001f~z~\u000b_O\u001a?;vR))3>{j'\u001bA$8ܓ\u001aY#X\u000bȁ\u0013{P8E<}x=@ǻv=u\u0010\u0017I<p\u0018t{%+:EP6\u0003Wm\fl%~tS\u0012I\rҞM*?Fۙ7᫂C9Uxk\n\u0007%g;\u0014'Unּu=׵x8x|v~^-0nmP\f'Q:co_@^\u0011?#\u0012?].9SNj4J#ݷ\u000f?k0GKdwmھ/Pg\u0017y?\u001e9\bƞBq\u0017>\u001a*Ǵ\u0015\u000e5j컷k/y\u0007P\u001bb.\u001bXEfSKꊻ?į)$\u00075ϬGgBmɵOgg'\rNܲ\u001f߭6vO]9>m;m\u0013jxC,GS\u0018eWQkR\\q\u0019\u001dx;7y!?rl@RA\u001djAA~qgF~J\u001e?iQ>)t\u0016#q2{/'%xr9ߋgmf¸.\u001f\u001d7Zڶo\u0007\u0010󨹊2\u0004xZ\u000bL\u0016&k~\u001d,\u0010䧗H>t_Ϥ\\-D\"'\u0017S'pu\u001a\t{^܆=Ӓq\"~M\u0006lE^\u001a\u0019&_Q=tLpWo}x[.6\u001aLP\u001f7kNn[3\u000f4at|<7c\t1]{ P3#\u0015GsF\u001advW\u0007\u00160=hM\u0000izd߹x1q1\u0010W]{I\bٜ\u0015c!_lƋ|\u000fgC1&SU4a{\u0003r,\fl\u001bǃj#u0\u000bdm\u000esﮉ-Nՠ\r\u0001}ι_L0n\r{`Y^<zb+zZod\u001f[c5\n\\k7}\u0002pIVtJGVs!6\\\\w7\u0019+j.2@mꛑ\tw#;\u000e|\u0011l{ˍ{S_Zd)\f:\\ɬ7\\o\u0002#];Ɛt\u0002v\u001c6OS<Ur{\u001eYp\u000fXu;\u001d[d\bsݱ\bj\u0019?\u001f`Mdm\t\u0003\u001d0Ús\u0012L_HnaTuZyw)o.v\u0017_ɶfmQŔk۽C\u001eOo͡׿\u000f&\u001dsQX;Mh^w?\u001a`?ШvXnOSa\u000bao<:ͭ\u0016\u001c\u0010uWo-*\bi͑|h\u001b\u0005u\u001bBr\u000e\r\u001d(\rO\u001boLQ9X2\u0017)he:t,^>8::}q\u001eYq{iVL;zf?^A\u00043кjo\r\u000b\u0011R^-Qu>n->N7\u001f \u0014A1NȆlqSY\u0012ikk\u000bZWEZmGbPE\u000b-\u0007\u001f`fFX{\\98a\u0017*+\u001fn[O;X=\u0005\bjw\u001dj\u0007m4\u001b\u000bgFTMqkl۱!z\u001f*NK=\u000bM\\\u0018\\rJ\u0007YvpScOT#3^\u0019!V\u0012]\u0012Pq\t_*\u001eKfpW[\u001d7i2AX?YUɋjSbVCѳz!|}yVzA\u000f5c]vv\u0002\u000bh'؁5k1UV;&\u00157\u0018O9A\rTF)q'\u000e\u001f \u001fv.VYi\u001eWTvM{xpFA`-xtg\u0017>ۘf\f^Mcv\u0016\u001c\f>锪.\\i=WVtVk|WBJc,'?\u0006!W\n(mܬ(=dZUr\u000f)ZR.}uռI\\}yr^]苂\u0019m\ncGۇNVz2V5Tq\nnj\u0003=rRu\f\\;g9E\u0004r*\u0010\u000b?4\u0013;UqĢJυ\u001d\t\bHe\n\u0012H_\u0017٧\u0002<\u0013y݁\u0015\u0011MsEge\u0018l5+s\u0002^=SZ]:5e_qrUfsV\u001c\u0016\fvL.Mbqv\u0019S\u0004tySxxݾpi\u001auUxÝ\u0003l\u000f+Q\u0019-qT\u0013y:O~xVy{!9lL5n0.\be\u0017iyⰲ\u001a\u0015Mb2L1)\u001eO\u0014]\u0017vg*m\u001f#5˛\u0018.]f?a\u0007\u00074d>0`9i27D)%>yuWɺJHbn\u001dsfBrX_zZ%f[\\\u0011r%HJz\u0013|㡉\bi%\bg\u0013q/j[t@9\u0018\u0005QOM1\ry&vA\u0011ʐ~\u00037,G\rZAjSW\u001du%$_\u001a\u0019O&;`\tmC{,ۖ a#ݸz~2U*=\u0016Frd60<7y\u0007YVt9g8F{v\u001a|}ugW\"*K+J[a@UaR\\\u001a|\u0017x(h\u0007y;\u0013\u0010\u001f\u0017h_tS=8wCsg\u0005s\fH\u000f\u00026(x\\ լCva'o\u00191S\u00019\u0003ꞞzW:s\u001c\u001aqS\u0015\u0006۪\u0012&Z&'\u000f\u001fG\u000f\u000e\u0019Hoe_ʮbI\u000f#+U҆7HyR!)'/\"I)y^\n̫DJ0)\u0011Uh\u001a44MjQ\r<r&!\u001bbH\u0016\u001d5&Zw3K 3\u00037`gclĨެ\u001a!z\u0016\u00185I%?=\u0016_h\u000f8)ڽ\u0015voTf\n\u0015\u0002\u0011\u00157K2_ :N6;@P#ړt@eô~]\u001dm:F\u0000E9VAF/CP~+{G\\y\u0012s$\u0016_L Ĥf'RVA͹8tPǜL\u0005\u0012\u000fٲ\u001bEÙ ;]\u0012\f\u0014pFUC\u0003|=@EG6B\u0000788\u0002LT,S\u0003\u0004kVq\u0005wb}]\u0015\u000b\u0006 \u00055\u0014\u000blsQ, ڼXW_xM\f\u0005P_-t}\u0002z7\u001a=Te@1\u0000\\e\u0014G\"\u0015BR^DHi~\u0018S^)Ă^\\n\u0002oX,\u001aCB=\nl2VŐ\tU(|^RJ\u001cd_\u001ct>\f&\u001f\u0017cWDX\u000byc&j@'o\u00047bT{8݌\u001f\bI'؜㙼y{Cr\u0017s\u000eܓsj^݄\u00126nxz\u0002Ί/>Q|f1G\bb\u0011J.$\u0000\u001f\b/\\`K<޳IdX\u000bR7<\u000f+\u001b]\u001e0H+r sC\u0016ĵ'L\\@д?)@*àBXHF\u001ar2Tf^͔}vU(!\u0016\u0000{\u0017\u0000{o]j\u001a!\u0005\u0002\u0017,Jr\u0000+*\u0018~@\nlWCẠ\u0016,T\u000fIzm\u0015S\u0003}<ots4)\u0001sN\u0014\u0001Q\u0004#>M\u0003v\u0000a=@XM\u0002\u0001\u001e^U\u0000Di\u0003wPn[\u0002\u0001\u0011\u0004勯l\u0012G#*\n!X<K#;8\u0003t\u0012FynyjqY>$O\u0018\b\u001ah\u001c\u000bG\u0004G2\u0005VH>\u0004n\u0003Jm\u000eJs\u0004{\u0014P\u0019]\u0005\u0014\f\u00018\u0000\u0019\u000fr2j<Ov\u0014\tdDekL׽si'C\u000fnʵ[3wJ(B91Q8b\u0005\t\tV*g\u001d<xz\u000bN<\u0007P?\u0001z\u00008\u0000\u001d/\tO\u001d\u000e\u000eh\u0000z[\u0003z\u0013ߛQ\u0006R\u0017\bm҅\n\u0017\u0000/W\n7\u0013fڬ{CrJo@\u000b=P.&L.\u0001ee\u00050MR\u0005m4\u00003Y\u0007ys\u0013\u0012\r`-\u000e\u0001ˑ&x-e\np@\u0000\u001cUs\u0000G3!\u0018H\u0010j\tosU'hep\u001a}Tw\"^\u0014\u001bz\u0001ճ\n\u000fn폞rꀭ\u0003.\u0014oWݥ\u0002*[S3m\u0004\u0000B@\u0018*\u0010R\u001f\b\u001e\b\u0019\f\u0004S\u001f\u0003O\u0012De \f\u0016zWr^jܢH,]{F\u000e\u0007&}*2S؟\u00030\u0010\u0000;|wTOm+\u000e3GO>c OY \u0014\u001c\u0006$]쓍f*\t.ÿabiǫa_|T_%.5%1)5UB\u0004ŢA\u0002m`\u0010Gȧ~\u001e<cq]=jHw\u000bB\u0003ݵ3y/2\u000bW#V+~\u0011vBv7¡\u00039,.\u001b1\u0006A\u000fnxxK:m\u00182}+\r\r~+ꏆ\u0017+s[}a%@ZWp*\u001d$AW\t\rƒ``v\u000f>\u000f\u001f>gA\\\u000e֙5ggok;NU/j\\i}}\u0017\u0007:E:\u000bc\tz\u0014|L;S\u001d;\u0019a?(\u0005NIIu\u001eN+g\u0012(G6\u0012\u001e>\u00146m@~,n\u001bB^^wn!&L\u0007[e_Ww;at\b\u0002v\u000bn#]ihp6V\u000enRYE\u001dcΥw2gp\u0018Eɓ\u000e\u00031\u001a3oRkVA/WOڨ^:ʇJo];8\u0010Eҏba\u001d祇޽\u0016rt\u0001\u001f\u0017I\bAI\u0019ޘ\u001b\u0014n\n>q忘\\z\u00172m\u001c\u001b'޵5vv'\u0018DU\u0007۽X7<&\u001ezM>)yR\u0001ͳ\u0011CwQ\u000e4?\ri'\u000f4l,\u001es!>zO:R(=aPjN5qFT2C Np:NanqȚ\t+-T\u001d\u0006\tٌ\u001f6\t\u001dɱKY/EO|d{G\f\u0003Etٹ>v9{9pPa1o:'\u0012[8sk8}V\t!N\u0011zk3\r\u001dݭ_\u000fxB)k\tQ7X\u000et\r\u0007>Gf\u000fޘFS&\u001ak\u0005h\b\u0005Q*'eApø*UwzmPh}==Rܡ7\u000b\"VhRnB鮻ǻn=_\b3\u000fCz@+ix<k\u0006]lYzj8\u001a#5\f-wLݾ\n/=\u0016ӽ\u0011z»X\u0013E%ԼX3ՙ\u00073EY\u000bΝ\u0012Tmn\"<hm\\\u0017\u001a.|\bE\u000enkl.1oX\u0019\r\u001f\u0016/O)#9/\u000b\f[~\u000e_\u0001Mͬ˞Sw6\r\u001dtmv#\u0015z7EqLA=Mb\u001a\u00126a__E]Y\u001fL?LڹIfmzxrMFcl\u000e\u000eϭ\\\tՋ(k)UT1a6\u0005Ms:e=iwe=\u001b\u000fB_$Kn,MI7t!KD\u0003XW˓>mF\u000e\u000fjEkE0gvQmy\u000fKEN\nZo8e\\.`R5,\u001fuutTzZGn4kߛ:~\u001f\\\u0000kkI\u001aN|ں\u0015X\u0015\u0019f³P=۷JgNU\f?5/FPne*Xy?63åS\n]Gd(\r6XaMSjfj]ð1I^Ճnihkǭ{\bďUi(\u0011\u000b`i1(\u001cmdq,+oYV2% \u0015?S拭J-tIF\u0018y9z\u0018~}svfLtQ-Xj\u001bА{WQsQ/v:LjϤT| \u000es=X;]QJU\n\f'U\u0011t)e\u001fǗn\\]q9>Mze5}:^A7U'A\u0010\u0003r\u0016@\u0019\u000f-[tC5O\u0015msaΨf\t\u000fVl\u0012\u001du\u001c+,H\u0006ެTJ\u0006ކRzޥ]eź{mNJξ`73\u001f5EU\t?@\u0017+?:\u0016gZֿS%v\u0016v̼h>\u001f\u0001o82&:kf2Gˠ2Q+lVdsW\u000fG{9O\\Q\\l{a\rB+{N\t\u0015^TO\b^t<rT!KP\u0019q\u0014`G?w┝wR^w<\rwk47;l\nl\b!\u001c\u000e̋Nc.*F\\\bZ$,Y\u0013\u000bW)X#Ե+ -CydCtQdoYeie{̘yP\u0019F!\f\u000b\u0019>r\u0007#fxL\rX\u0014/FzԼZ\u0001cW\u0003\\Fmuas\u001d@drl\u0017\u0012\u0013Z~\nɵ3t{\u001c\u0018`o*t`٣`\u001e(\b\u001bEjuS'\u000bSk8SKW^\u0017\u0011\u0013VÎډ|g|Um\u0017\u0005\u0013ÛW:ziXgՁUpt\u0017\u000b% \u001b&ÛQNyP-,E6kH\u001b,WF-qhEa'׍\u0015\u0011f\tAifQ!)#YH\u0001a;pc\u000e~@G\u0017մUj5ݮC\u0015\u00133\u0015T\u001a\u0015NZHI[7t\u0013\u0011\u0015Xqf\u0014),#L:Q\u0001\u000fDiQsMeٙ\\\ni@:Flg(\u001d\u001eVxG\\e\u000e<`/x\u000e\u000f\r#mOO\u0011c\u001d\u0004F\u0016|\rQ\",*ݛMHEIqV{\n\u0019VHSF.wn76Y@c<%Q!~H-^8V͖\u0013lJ\u0018iLJ\u0012u4<\u001azEK\u0003qy\u001d_QyEf\u000f-\u001aGTvG#iԃzTՇ)izI3c~y!s'W\n´:ň\u0007\u000bx8vUiXO0*ߣxGYr_@\u0003G\u0004n.?BP\u001eOWy3Zy山tM/?3\u000e^a\u0007\u001a\u0015&6ÌI\u001d\u001dz\bt_}c\u0003.+\u001470w\u00021W\u001c^cw~dX,7FLGJE\u001ef\b.\u001ce`\u0019o]d67ӕlIˇL\tj͢'\\8\u0017sC,X{u\u0012vq[א\u001fK1\u000ezyxi,\u000bO敂Ũ,\u0005rCE/̾_/6nɳ,\tTN'JA)G=+VWݢ\u0002F\u0005#IfQ=$<c=\u0017:#\u001e\u0007\u0011*,\u00186s!Oڹ\u0010+\u0018\u001e;\u000es][\u0016\u001co\u0016o4!%*UhpnMW\u0014!A\u00047s8>nA|\u0017H\u001eIUr=\u0014oWb}29\rA\u001drw$?-\rzNJ.4ghB\u001c4F\u001d^,?\u0003Nm^x\u00072\u000fv7~u:b\u0017Q\u001b\u0005p\u0016k\u0015\u0012YpуB\u0001q\u0001!'xQmtϊ;+9hb\u0004M\u000e\u0013\u0015\u0011\u0003j2df|(\\Rk˱R[ijrY.ꩵ2t9g8u{\r\u0015úT*dhя;N\u001b-y\u0005Cm\u0003aU(\ft\u0004\bQFY]3U{\u0012\u000bL\u0019j*U<\f|\f`܅\u0003XU\u0013m\t,\f0Q\u0001&\u0001\u0011`\u0003\u0018o\u0001V\u0012?YXLu\u0001z?y_pɘGLcUn4DJ7ѥ\t+ލ#z%J]:(jHf\u0015҅*+MwH=\u0000\u001f[ \u000b>\u000e\t2'4\rHIj\u0001|\tNko;w 4І\u0000\u0017O\u0000\u001f\u0010[\u001e\"A\u0003~E.\u0017rt+@5f0{˫f$G쒩#\u001dD\f\"Y\"˧7\u0000\u0002Dt~\u00012$\u0010\u000b\tH\u0011\tC\u0004$B\u0000\u000eM@j$sh\u0002H〬iu@i\u0003Ҋ\u0002$u\u0019\u000248%=\u0013D[\u0003Ez=Yl 1@\u0002*nI\u0011@P5\u0012,W\u0006{\u0007+\r\u0005T\u001dg\u0000e5$@yc-\u0000I\u0003\f\u0000΀/Y@\u0013m\u0016$Np_\u0002ڦ\u0001M\u0002\"'Q\b,NΤ #^`#b\u0003q I\t!.\u0006\\a2SH!jd\u0004Z\u0001lnv\u0012?\u0012Y\u0003\fi\u0003F\u000ezq\u001e`6\u0006\u0005\u0001Xr]\u0002l!\u0003V.8mF\u0007\u001a\u0002`[\u001a`\u0007)`~\u001aCKi̗Rhˈ9F\u0006%{#&\u0011LqR\u0012Q?>_7ǡ\u0016\u0011Kz\u001fp\u0007\f\u0000>?\u0003^FҀ__Ozj\u0000\" \u001e$\u0010JW\u0013\b`\u000b\u0004\u0003\u0001\u0004m$:YnU\u0014nW(\u000e\u0005{1vAe͔ɼ\u0001u\u0005QW@\u001e?\u0016\u0019\u0002a^\u0002\u0003e1@q\u0006ҹ\u0000H\u0013H9\r$6%<|W\u001fmu\u0002?\u0011-J\u0010\u0015׺]}%^]jY_75#ɫF/no@\u0019{p\tz\u001b\"w#{]72Tkʡ'nOL_kX_|=K#_'V~\u001a+_ylǻv\u001f~Y{\r`܃rk\u0007v%/,۝\u00199\u000fWt^@\u0017bZg'g~SbyدPUG?2Yb*tk]\u001bfn\u001e>ڎGz%Oour+:\u0012K(udʙՓa\u001ctCq?#\u0007ksȺc\u001fɤ\u00105\u00106r_|R\u0007Ѯ@\u0004`J_\u0011\u000bWh~\u000bg\rI]~+َuE]otT\u001a+G\u001fQNǴ\u000eY]\u0000$v9\u0007ڄbi}i@ؚ\u00152\u001aͥx\u000f\u0016rL\u001et\u0014Cϳ3\u000e\u001aL\u0005uIC\u001c[X*3\u0003\"}_ht\u0017g=ȆqSd\u000eɔw\u001bNmiޝUԌz+n\u001f\r\u001e\u0016y\u000b`?kqg\u0018Sl_ҒG|\u000bŌ[?Є.6h@=\"b\u000fM}_{\u001bK\tw6}vgzҞ\u001fbv0Jq\u001bI/|2\u0007l\u000e\r׃L/FN՛4EW7շ7}riߌ\t\u001d޺c|8^<Hy\u0018炑/QQz^Uhv\u000bwy{iK@pP\n\u0017e\u001c-rw6\u0007ku>N1y3䓽!f+<9'ȏtK*\u000e\u0013\u0007)].Qzz\u001e\u0003F!\u001dɯBq\u001802\u0006\u0005]VIͯ\u000f40Ro}4tE.\u001fl:+xOMV\u001cƖWVr\u0001\u0007̵P=yXTwmHN)՝ç6Xd\u0017?+ӭy\u001e\u001ff[Av?<X˾\u0017i\u0017p\r\u001e_h;S\u0015\u000bjTك߅m>\u0014tJ\u0006n2I\u001b!\u00156Y;CvwrV`\u0007\u001b=&3heLmþ\u0006vf\u0013\u0007ƳJe\u0007S\u001f\u0018ukWr\u0001l(\u0011\u000e46Vxk\u001bg\u0012\u0019\u001a6\fjB\u0001W\u001bm*!\u0016bd.=}1x\u0019&3G\u001b\\\u0003<y9T*\u0004O!T.ѻ4ˁ\r䃿Y˔åq\u000e.;#/۹hr4\u001aq*5꒩Oi.ۺ\u0007ckCϚ=V\u0007\u0005b ̴\u001b\u0000<\u00199?ZўTUǪD\u0019٤׌i~\u000b~LJ4֌V{fz\r\u00020+(6CiWI%aŵj,V\r*V:3Ӱ[2kQɼ?#\rZ,\u0016mꤘ\u0017\bDœޫ\u0007Lw+mLކ=2M*5$/GՕiQ\b[a\bZ_TeTڡ֟ijI1J[y_\n'k\u001cȂ*eAӱ\u000bÛI`n\u0006r;=/-y}dQ}\u0002\u0006{[G\u0007Q\u0012$\f YQ9'\f\u0018k~?wNT#T=5QցZmY,H4WTL\u0017=ݮ\u001bswM\u001e-\u000boTWkp*;Kϒ\u001bo8\u0017xkV-6Y0=uZ4=\ri\u001eə\u0000݆\u0013\u0011{=\u000b\u001f{\u00057WAmr=ҴӺW_.3<~\u001c~\u001ag\u000b\u0012*I2cs6rm#rdi.L:*o\u0013'.\u0015LVU}ugz5ӹXc]\u0007i,g&>(okJF`\u0005\u000f\u0011=\u0004n&A\\,g75#reZ'K'0qj\u0018\u001b܌ nO5\u0004{좊ifFӄk1P)\u0018x~н԰~Q\u0007]Y\u0010\t\rryCw{ά0V:+ٙr\u001fX\u001e|\u0016:\u0006Y)ҜQo^e4f\u001aj\"\u001fNqUS򀻒\u0012\u001d\u0019_\u001bD~f2缾=v4lr<\u001dUy:)\u0014^v:s V\u0016\u000bO&AծF6\u001c9iKiUPCUYVó[RVP\u001eSOAB<\u0019ٺh\fFGW=>Ru\u0014\u001a\n\u0007\u0013Y\u0011\u0018\u0016=:p@$f\tzj\fFP+֍5/oF\u0005\u000ezŝ\u0016$굚˨\u001d+fQz$Y(\u0006x\u0017fuaժ9ّ3IpL-\u0010+\u0016k\u0019LWXga\rJeEX]e\u0011\u00137\u0015\u0011#fFj\u001ewn\u001cIU\u0011\u0000unc:aZk:>h\u0017U;Ay$׫bX-qU\fJ0 MүF*\u000f\u0005\t@ .\b-\u0016͑u;\n\u000f\"\u0019|-Wcg=wO\u00049}YA\u0015i\u0006^7bZ(!nÅ~?J\u000ftP\u000e`cwծxX H7r&2yH\u0011\u0017^\u0006\u0017=aE,.:l@Y\u001eY5:e$'m/uV\r+\u0007>lm\u0015\u0007a!W=7϶V9|%-\u0011_\u0007)\u0006&]\u0019JB\u0015u-\u0006\u0017\u001a\u000b=5EHl=V}܉\r]6[\u00156]V>ps^bF\u00109\u000eUzP*\\tz)\u000e.=_%z]/]ĉý韘7Z7\r~<9_/X|jDhWSK|NkV'6>#w6lɀU$\u000fc\u001e>DӝnƦ_YɧߢP;w\u0015sHwl9ʔ N&#nHn\u0013o@p\u001c4:]8Fh\tqEAhL^}$\f\u000fy\u0010gUkR9}q&'D\u0015DɓNC'Kb(V'V \u0016ޔ7hs\u000e;\"V\u001fA#O{,\u001e-찕\\!r\u001f\u0004g\u000e-\u000e\u0018q\u0007jy#S\u0017&\t?>{g\u0003n\u0002eH\u000b۵% 6В\bhhK\u0007\u0013!3=`1$a\u0004\u001dd/\u0005u\u0003vr4\u0002<\u0007}?@/LT\u0012\u0017\u001a?)xmR7>\u0010\u001e̳\u0002M\u0003\u0007\u000e}^\"0\u0017r5rKl\u0004\u0013^4dj\u0014=zޯhTc?iϦ\u0018sȠאA[\u0010K=ǽ\u0015Λ\b@q˂H\u0005\f:%Bڢ\bC\u001f1\u001fb󒩤7Epr\u001e$:ͯ\u000bX/e\u0019'Z'\u001c\u001f\u0004\rg3$pT\b\u0011v@\u000b0#3~3/eHq`J'\u0000F).\u0007m\u00040x5\u0001@\u0003&\u0015RtK5\u001f代`ZJ2\u0012b?\u0012\u000e[\u0018\u00026Ux.NWe+P\u0005xcj\\'\u001d\u0010{\u0004!9ށjb\u0000wOm\u0014\f`\u0007\nnv\u0010)\u001dB.`[N#m\nv%\u0006lȓ-\u001flV\b5d%E\u001fQ\ruʨs˖QR\u0014`cm<Q\u001c<.\u001a|f)y U2\u0012$8^!b\u001e\u0000\u000fG`$=gR\f\u0014!L\u0001\u000fc\u00145\u0011\u0001]YϽ\t.\u0013p\u001b#\u000fm\u0007I~E\u0017ŚV\u001b&.ܖn\u0018˾Wk\u0017\u0017ʠZ\u0006Em#ڋ\u0007\u0010u鱻\u0001)(\u00108\u0001ͥ@\u001d ,\u0014\u0011\u00101\u000b\u0002BZ\u0003ad׀0f@\b\u0013\u0018\bk\u0001\b\"(璢z\u001b.M\u0016\u0006ثQ\u0018\u001bjV0仭s+bSErKR\u0000PXa \u001d\u0014 /\u0014\u0010\b$@j@\"\n6ĉސ˶\u001áf)68B\u0004R\u000fԅO@) Ֆ% Փ\u0003\u001am\bHގGT~\u0002a_m8)jrMN&Ĺ%\u0000IXG$\fN\fx\u0016~\u0003|}\u001fT:\u0002g\u000f{\u0001\u0014*\u0003\\\u00022Yp@\u0016\\!P\u000eh\u001e2P\u0016\u0001(\t\r\u000bm\u0011\u001db\fs鮢\u000fc/t\u0000;Wy\u001bDm\u001f-,fyʽM\fYMr`[@C#9\u001ah]\u0001\tJ\u0001zF\u001e\u0005a\u001d%\u000few,[M\u0005\u0006(-լ!#\r\u0014X?sɿ~ݶOo+~}_Vf\u001a\u0016\u0000&Ci\u000f\u00023\u001d9\t`\u001ei\u000fO|\u0002+`aЯEcE:'\u001b\u00125\u001c(WP,>Ia\u0003?e+l\u0002UMᜒ\u0003muwv\u0007:k\t~w׫?rK\u001bfpȌ\u0003\u0011x9\u000bT)Bb+cFխ;ϫ4oނ9\u000e^\u00130-.!zw?\u001ej_7p++f3_g\u0011W\u00079\u0018M\u001evF\u001c@0c\u0010S绻O^:\rȽvTO}L|\u0003?nc`n7'\tuȌF\u001c\u0018XدHG\u0004\"\u0019#\u0000{\u0005xe\u00133\u0016\u0006[\"O\u001f㧼\u001d\u001ef|o_ʭ.x\u0015ZFmNt\bK)^\u0015Ҏ6\u001c\b\u001emi\u0001y_2_\u0018\u0005\u0016=ٗ}\u001fdRsT'?\"3דZ$\u0007'¶Տmh.5\bo\u0001uA0w6[Z b3|\u00022\u0002\u0006SjA&5[4w\u001cu>/\u0015h\u0018\u0013z\u0011\u0007q9pه䏉\u0002~-8M--\u0007;*:!j\n?[1;\u000f2sJ̄]AqDQ|Z\u001fK}hz.,Ѳ\"|^:Ը\u000f\u0014m5l*~\u001dvh̗a\u0017ɧyht\u001b^T{+\u0007p\u001d\"<@9\u001d\u0014M\\lҙC4x\u000f20oCЗh\bO+n`2}A;5F%SB!PֽZ{h\u000eנF\u001e[~rd]ju(w~/>6Ϝ\rϸl4^\u0006XcZC\u0016Q\u001c \\};ik2MwjS\u000bOjz\tZ^-߂I+҂E9\b6́>Ϥ\u001d7H7ϼ\u0001%V+wiFR\nrɐe:b˪\u0005WI\u0006\f\u00074߻}qXex<\u001bN4w\u001e\u00057XDȿ{n\u001fpz+ي/i\u0019/1n}lQoJkSA|/O+\u0007pp_n,O\t\f-7J\u001eorzwQ`}̛żW\u0018O\u001e\u0004q\u0017Z/v\nFZ\u001c^\u0018%L\b\u001dkM\u001cW}΀\"xb\u001fR2j\u001avY*\u0015-\u0003Ri-ΠLfL\nG\u0010\u0017\u0017\u0002)\u0016\u0016W\r|5S\u0015ca3#p%?hT*Eǃdʁ\"Q[Vk7аO85l}0;7\u001dU\r\u000f\u001ab8AkA\\Jj=qXW\u0016\u001aʭ nh}煼<vq];\u0012G9AsvsJqfZmmP!\\ބzo\u0004]L\u000bj\u001dӟ}ޕ>fY'..8!RAz\u001baVh\u0016>v>^||X}6l]\u001ds혳J\u001a_2\u001fĂU˜gã^\u0006~\u0004\u001fTUn۸M\u0005\r4j%\u001bTt\u001e7\u0012\u0019*Mm\u0010kg,w3~\u0016Ä\u000fl},WCʁzZK\u0014X(n<>4\u0007gcꋻ\u001aa+\u0015WVgt\u00197.G_QǑC73\u0013*j\u0003\u0017T\u001aq+i\u0017\u0015xZ?mޢ9ϫ{E\u001b[\u000ek\u001fP\u000bɮ(oy\u0013#\u00139Թt&o_)q3gE\r^JdA)iBn?S!~\u001d\rNľ\ryGe^\u000b~ڡ}̗c7U%3e!i.7<Ϭ6X\u0018\u001c5W\u0002\u001dKE^k\u0010-Uۼz|mUFm>&@~fwYl֍l;l\u000el6`훩\u001c\u001d\"4h^ヷ\u001b\f\u001bM#\nI\u0010\u000f\u001bG\u0011ǦF`sZqQO>ј'%^\u0003\u001d޲PJw\f)r?>es\"\u000eO!JczKsIPsYDf\u0014g]U9qV\u0000\u0017+wObu^\\d\u001ey԰\u0011VU'EIE:y>[:=4\u001aXMfcD\u001aϢ\u0003,eKyLc\u0012tUY\u001a_g\bm\u0011\bd\u000b1o\u001dU %\u0010bhoߍr\u0016Y!A\u0018\u0018VLG\fn;6K\u0017zt\u0012)z(?өlq9'')/o\u0012\f\u001fq6Qѭi1-$aH\u0005\"\u0018v-\r/#s\u0007\u0013\u0010\\\u001d,ۚXqթա{Zu\u000b\u001d:{ӻg)p;ݛQi+KU9$l\u001a})F✬.Dw7 ^\u0014!\nۜL\u0015*njp(qu=bϫɔm\u0005\u0015\\\u001ftz\u0016\f3b\nIgg\u000fF\u0019gGAA\u000e~\u0013kDeU[\u0005m\u00119\u0014]$]*\u0015|\u0007%>+%m3b\u001d\u0007W\u0001;\u0010ƶ\u0014J%[en(\u001d5IkiqD'D\u001b\u001cL[/\u001aɃ:{,H\u001dqԻ־\u001d\u000f\u0016\u0011\t=!6,\u001d\u001d\u0004Z/\u001e';?\u0018U⠴ׅ(H wxk.{)ol~.X[ߌY}8~yO&\u0003IQTl\u000bIqK:U$ClO\"\u0016gLx#/}*El3bUH\u0014c.?'})\u001f\u001e޺;F_\u001f{>|\u001c{R(fL\u0003Z^$W(xvv١|DpB}\u0007P|9t\u000e\u0019_I2㉥}7\u0012,\b|v@e\u0001YT{aclf\u0013xMESƩ|ôzoaqAjz-JI)sk^n%|\u0010%ͮ\"1U#\u001atkpH,p()AJ\u001b|xyIp\u00050vȊ\u0014ƵJ,-J)ۼS8kQ}\u001d ʦUDz@i\fA$\u001eO)gB\u001dY:zTǸo\u0005^]4䓕\re=$m\u001dVtl?\u001fd%<Co\u0000ަb>Z9`H\u0012\u0002;mhj;LQ&¹J\u0019ڇw^\tgę\bJ{\u0019\u001e.J'1P\u001byP? \u001e>o\u001a2 B\u0017\u001ba\u00035\u0003\u0014CNV؋m,{\u001eNҳ\u000e5l7\t\u00041q\u0005,\u0011xR\u00006\u0007\u0002K\u0011Àr:t?\u0004\u0011=\u0001e\f\u0004W\"\u001cmh,cZ->˓OJ\u0018\u000b)߳2zFV\u0005殥P3Q>zU\u000f\u0007\u0001]\u0018.\u000f{\u0001:\u0006)r\u0014=k+|&E\u0006t\u00036R4?\b0\fh\u0001\u001d06G\u0011ս\u0002h\rO_c\\;\u000b\u00067cDK\u0004޾\\|\fiY\u000e\u0014$\f,KZ\u0019\u001c\u0016ӿ\u00056\u00065^\u001cvPe\bv\u00100$v\u0001\u0018R(q;\u0019\u0003URC!s\u0013Mg\u0017\u001e9\u001c`[\u000f00\u001e\u0007Ln\u0017\n?'k3\u0013.pK\u0001\"\u000bq\t}\u0003F$\u0016kBܔ0\u0016j;jѣ\u0013|6`f+\u000bmby`\u001dBGSDl\u000e8S\"\u0015+M\f8(\u0013:$g\u0003*\u0000\u001c\\\u0000qKb\u0012=w{;#<Z1K\u000bk\bu$z\r׸jRIdN@\"h\u0006^2\u0002<\u0000~\u0010)B\u0000\u0006M\u0000\u0014<\u0010pb2\u0006\u0002_~^\u0001!\u0013Y;]?\u000b\u0005Oi~\u0018ziќ7\u0000qRZo]x\u001bz\"Zj\nȧu+\u0006.,\u0014,\f\u0010fϿ>`\u001a\u0002BA)l\u001c.\u000bN\u0002b\u000738= ^_!\u0010o%\u0010#Ō\u0006#p&@|r/ a\u0015ka\"}\u001bl\u001fQywث'F\u000e{\u001eM*x7\u001c,**2u\u0002%\u0002_\u0017Wbaĸܢe'9 k\"kz\r\u0010(pp\u0000\nB@a\nPJ\u0015(\u0006\nd\"P\u0005\u0004($I׵\u0017N^g\u0005\u001fn{Ԗ_O6R\u0013Z?\rՎn~7+]o\r6\u0001Аd\rj/\u0001̠v_\u001fc\u0007:2\u0001\u001d@϶\u001a@\u001dq\u0005\u0003:\u000b6P܁t\u0019M\u0012\u0010g\u001b\u0001\t\u0002hO{?.j_&C'\u001fOm}\u0005\f>{\u0003F\u0007\u0003#I;\u0000\u0013\u0004.s`\u000f0C\u001d(\u0002\u001a\u0003sHl~\u0016lzw\u001am\u0003p#\u0001=}|J\u0007I-Ky}8@\u001b{\u0014\u001d[l\u001d)\b_|_v[\u001au\\Y{it_\u0015FF~ݶm\bs\u0000]8{C\u0012O{%x+6\u0012Q]ҹ5ɿ\u0003\u0016,\u0013\u000b\u0012\"\u001dNgm+A\u0001\u000brOA\u0006~_a5~5ޫɧp/$P\t<\n\u001e0\u0015|\u0011\f|wmt;ϴ<k4 \u00018~*/8f\t\b5\t\\iq%Yu\u0017|m\r\u00167M<\\\u0007\r5i'ڛ_\u001b:a\u000f\u0012WOp-83pHnE\u001e6's8G\u000em]jcs*xFXxu{սV[-\u0007[|ya\u001b<X=\u0002stgtMYԚj}sq;\"\u0005Biu$+NǏ/l^<mQ>`ױk%_\u0003\u0017gNkM\u001e3\u001cOE8aL0nRLm\u0014H>a$妃g\u001d^\u001f[LZ I\\\u000f]\u001eD6\u0017?HKwSݜ_\u001b\u001f=7\n!n<n듹<\rw\u001byXˋcmi\u001es\u0017~pwTvB]\u0006\u0018<C=0\u001f0\u0006ol3ZJYZn|R;R=<5^(\\vQq>\u0018-=k]Eߣgy\u0019~\u001e3L_q\u001c\\~y[|j\u001bs\beRW(RX˽%e\u001b\u0019u\r?hi\u0013!\u0014.\u001d{[\u001bVP9t~\u001a;}\u0001-wKfe|_-K=J\u0015jk\u001fCsJV808:R5>0lODwF\u000fawe1\u0014Ne-_ḰY6>ZkXum\\[\u0006Ѣ\u0007j\u001b*Qao\u000f\t*y5P2\u001fP׳si\u0010tӿ4(\u001fXt&-퐟̽N5n/(+#\u00156ҭ\u0015)4_w\u0003\u001eڲ&kWZԄQa[Zʭ\u0018Ľ[\u0010fH43(\rG/oϟ\u0001nW껥x\u0012MVmvS\u001c?2t'zA@Jf:\"[$~63PV}V^GmD'_\u0002ӧMjgPR\u001185w%ȩ4/=V8km \u000bz\u0013奀؝\u0007\r]a\u001fWt7pao\u0015N*\u0019W\u0011\u001bg3}\r{37=U_)WBg*\u0016_%;٬SI\ba\"_8yfMt\u0018.lj\fr˙e\u001a\u0002m¶2W?2c:5QAL'ҥ\u0017IqdHA'baNj\u0004\u0010W\u001fCPVJ4&âd{.M7\u000beA>nWvv7A消\u001f$_O$kt\u001a}9-Ϊ5xnxwj%1Jө˭SW\"-,\u0002\u0007Q}t;!W~ez\b\u0015ҁ\\?\u0015W}ⰗC7/\u000fr@Ϡs\u0017[2]1\u001b3J\u0016\u0018\u0004$}3)=)j㹡\u0006V:S`pT;\u0011V^QztU>Ŭw1mLG(nVT>?Q\b\u001d[4s\u0004i^w9$_ZDfV\"2\b9\r\u001ftX|iѸ^\u001bSƔQ[[UeV:_QtR!?\u0016N6Gz]-^\u001aN@\u001aԓ4<0T\u001cHù}U\u0007yn=Z=󍆏\u0018Ū؂\u0014s`ō\nf\u001b-36mi%iu1QϳJr]b'iͯ2\u000bˏIȆ[\u0015wvjH\u000bKߑ2k-\u0016\u000e_0g.;a[`)\u0017\"2¸|\u0015&ͻ\u0012\u0007j~\u0013\u001b~J\u000f[+|+U:z`WKYS\u001a\u001a*35\u0013FWXIo;J#qr[48(Ft2&\"]Q8)`\u0007#\u0007)u]Xscy]0|P=\u0017J{6\u0015sBjnv4s~\u0011\u0012]QN\u000b\u00122kӻ#M劢>g_\u001aDuiT\u0018Wg1\u001bH|_\u000b\u000ez\u0014\u0010p\r\u0007MH)s{q՝:ʞt`5l\u0016&f&]=Y]Rclu\u0015Ugr&ri9]Br5hWPFr :}\",>zSƥB#>G\u000bܞU\u001fW\u001f\u001d쩼&ZT+LOLXj.QwnҺ>\u001b)IL1\ncC\n\u000e\u0011?cVQ_\u001b76fmS\u0014w\u0017X1mͯQk󱢷͚\u001e9߄ \u0007q\u001eط8`Om\u0006\u0015ٙ'\u00138Q5~`\u001bb9^JG\r\u0011Pb\rSTȉȉ\\}S xA)\u001a}\u0001\u001d횴iC=mP_oz\rVEvDH\u0007\u000b sa/E{\u0016|\u0014p\\mUJyUaҶt c\u0019=\u001f{ϳ\u00075\u000e\u0019*\u0007\u0014\u0005f%NE\u001db^ob\u0003\u0004 2Z<j>\b,;&>#y'z<<N߶\\s`Xǫvi6<WiŶ]Ԥ:]uz-Mi\u001cK>iu<r%p\u000b\\02kNNv,t'ڛ(\u000eV\u0018A\u0001'&Ӄ%Vy#/\u0019Ml׳1S\u0017*\u001f\u0012\u000eZҾY\u001bZ+sʶS\"y7\r#Z(!\u0015\tfBdH:\u0004\u0011\n\u0016 c1\u001e\u0018N~\u001eGZ>0)\"qf\u001bͬ\u0015\u0019v\u0007Ae7\t\u0017r%\u000eG\u0003\u000f\u001a'zll7msς\u0010y`]-$rh[Ѯ[@\u0011s\u0007\r\nux\u0019|]O)UM*ie\u0003C:ECߤ^QCfا(0\u0010W1f\u0006}n\u0010\u0005\"ydE\u001f\u0010xP\u0000\u0017G\u001eӱ_߱>TA1x7(,UͩgȵZMϞG\u0007UfU\u0017eRi\u001dI\u0004\u0018\u001e\u001a\u000f\u0002oQQ\u0014y1=c\u0003 6.\u0002\u0003Ĵ0\u0007,\u0004>TςʆC\\O{Z>su\u0001-s~\u001dQL>JZ\\\u0005o\"\\UѮx;Z\u0007񂌇j\f6`m5z)\u001d Gu\u00163UN\u00009/\u0001΀~\u0001\n$/\u0006n;E\t4e=K\u0004\u0017O\u001apm\tn*\u0002\u000f${\\kkr޷\u0016b\t*nөh7S,:%c@U%E\u0002\u0000u))\u000e\u0006b3\u0001vt\u0007a\u00015cJ[@5h\"E~ܴyv\u0015;t'3\r{㜟\u000e޺?\u0017dLY\u0010\u0004,Y5-C L\u0000cgn\nc\u0018R<NQ$E//\u00010L\u0000\u0018\u0016jo\u001a\u001f`\u0002\u000exs\u00046\u0016\u0001=\u0014GTMF`Aݒb\u001bvy䤎vTWU\u0010\u0004O\u0018rMBTG\u0019\u001d\u0010{YAxӚ\u0000v5ORׄ);`\u0017/\bKN\u0001\u0003\u000e\u0017\u0018\u0015ҷ,`\u001f?sة\u0000O-\u001aFk\u0006&\u0016WlfxǛs+kbc끚WK5\u0005\u0016p{=,\u001b='?L\u0005\u0007\u001ax\u0003xq\u001e7\u0010#I\u0006xI~(e\u0000[\u0012!\u0001A#\u000f2\u0004|5\u0003|NW2%5>\u0001<K%,j*YcѳsZ[\u001eR^rO<_U6WnH>d\u0011d\u0012\fso߀9W ;\u0010Q`{\u0003ဣ)4\u0012\b*\u0007D\u0003QE\u0005nq@4;U@\u0014\u000b\u0004\u0010%7\u0000\"R\u001c\u0013\u00136PW\u001f86[̤*\u001eu@jndф\u001b\u0007<w!*x\u0006\u001e\rxGG?\u000eܯ]h \r\u0018\u0011Hˊ\t\u00052'ցn@.:\u0017 7p<.\u0007f/\u0002r+\u0003y\"C\tJ+}I\u000eh|ӓEk'S<̣Ebj(*{?mW@OzrJoUp_\u0005}j\u00004\u0007@]ܶ@CG\u0000h\\A\u0002AWA\u0014O\u0014hͷ\u000bv\u0004\t0RX\u001f\u0019\u001d|7݊{aZG\u001dN\u0005?d҉̿)\u00047Oo܄\u001c9\u0001\u0005\u0006F<~ݶ-\u0001~\u0002\u0002ş\f0l%s\rLb\u0001&iVW\u0013:Y\u0011,MFf~w'r໷Y\u0013\u0015;@b \u0019z=7ΟX\u0010\u0006wwЂoc)ݨ}\u0001rw?o\nWA{Q}\u0015ǿ+/l^iΌ]br\u0019;IFԐ\u001b^u+wdVăqú{\u001ca\u0019$y \u00171_\u001eP\u0015\u000e\u001c\t@~\u0006.Ig]J?H)(;\u000b\r߬\\Z\u0012ӳ$Ώ\n>Gz\tmdG\r\u001fm-7'\u0017!6!j\u0015f,\u001bXug2w3Uk?rh9ic\u0002\u0015mÞq#=G{/\u0007E۽6Mx̓Bg\u0015QYUXr{\u0001uyUIi6Ʉݼq\u0011nY{Ǚ\f\n\f\u0006\u0016\n_A\u0012\u0013$_P\u0018mhu/U\u0016\u0001\u0017v\\Σ#-3frvRjԸI(R(deuxo\nP\n\u000f2xvlo`&^?6>4\u000f{.[E%,t7e\rRV\u000e{UvaS7xhiﯞ| m_\n\u000b_1wR\u000b}A5rQHa+y'm{\u001cqS\"J(%\t\u001e+|Sc\f*<5r|(ľNgӅVd\fmZ0UGG\u0003ڄz}V\rt\u001d2她q4\u0006=W\\\ttԨ\u0004.\u0016Na\u001b?H;niֽZρ6oZ@^5\u0005y#Υ>G\u001d@D\u000f~\u0012+Ӫ\u0014R>֣$AX0\u0014+/Pa/~R|\u0003DI\r3o\u000e\u001fvݻWg_B8̴a\u0007k\u000e\n\u0018\u0015>s}*Z8MRRJo\u001a\u0015\nMAB>]\b*YyD\f\u0015ghXtAX1\u0001r\u0015)\u000bax{\u000bqDw\u0019\tBҚ_w\u000bexܔp\u0010G'<_1GX(=RJb,'>E\u000fQmwٴ\u0007.~mz\u0016\u0003\n.ԬOS7]zo\u001eH^4h/6Ҝ6\u0005,\u001cE{G\u0013s<DИRc/\u001cZ\u000f\u001a\u0005q<#+?-\r\n\u001b{ރR:,J.筌K𽬳)|\u0000=\u0002羬|B{y6\u000e4\u001e\u001esz57\u001c+VV\u0006-fRɿX\u0003nL[gP`aɵ{5f,Ts\u000f&QuC\u0000.ζV\u0019:(s]^\u0012m\fK2$3\u001cl1\\2*0\u000bWh,(.7\u0003>y=No@'\u0017dV'<=7vzksVHVOl-I\u0010hEn{-ٖSJWNo\u0012o\u0019\u001aїvTȜGJE^\u0018\u001ee\rlަ_:\u0019gZUQ\u001a\u000bFj#\u000e ark?ҞVGJ{RL\u001e0vj8\u000b\u0016\u0017O6\n4\u001eN7\u000fO<X{;=+s\u0004&z\r/\u0006Nɣ\u001fD\u000fj\\`UՓ7D*TY%(Vi\u0002]禞\u001cQ|W40daWIl]sM%9_Lcg:@s\n\u001a7[zYJ(\u000fyR$#oSp8\rkDg{G\u000fnZ˰6\nH\tLF/ٳ\u001cǷ\u00061H\u0003\u0012@\u001dG7-\u00110\\;sBl\nF7\u0016\u0003\u0014J>\u0019=X3[ަZublVT;Pm\u001cuN\u000eo傝~z!Ȣσ\u001c\u0010y%\u0000W~ p ^.\u0004+\rH\u0002Ji&NV\u0017\u0011n/a.XY\u0005~-g:O\u001coSn;h9&P\u001cC\u0011i1|J1\u0003\\|127yڃPfva\u0005CR)ĭ\u0016ǚKSV4[9\tE\u0000M\"<;4\u0010=t\u0005\u001e6}tI(q\u0003*u\u0018c`\u000fZfr{\\T>fZɎ`cUgX:m\u000fs1B0+E-\u001bp4\bQ\fU\u0001Bq[%tsМ\u0018yi(nٖr!)`\u001co~K*Tpn1N'u\u001e솭1\u000fA6e-!i\rd~Rn(3p{EUj\u0019{\u0013-\u0017_rqT,od5ę~\u001fD~j#\"ΓD㪿~c%)\r\u0016K1m+adP\u001922qXѷ\u001d|]I%V/_\u0012eK~OD\u0003\t\u0015Yao\u0011\u0007!E+M^ces[\u000e5,]G6\"i\u000fwӛ\u001b\u0002o<\u0017w`O1125\u0018ٛ\u001d?zV>SEZT?{g\u001bȱUIh2቙C\u0017\b4\beK%\thj\u0004/;?U*L&isqkc\u0001K^Z;1Z4v`@q(M\\ʗs\t+;zM` ?C룀:\t].1\u001b\u0013\u00177D_R\u0006p1?\b,.쁉WکrC[r$[{ Ԟ\u00185Q\u0003R\u000fӘ56rPO ,\u0003xrs\u0014t\u00191XtR5Л,VJ\\=8zAV\tjDl\u0016=Doc[2{=\u00041[;,wO\b<\u0018h\u00035T\u0007\u000b^H+H'ʍ끸 D[OTێm;\rZUeIG\u0001<bjC\u0001*|\u001bL^O7\u0017feUrǝިU\u001b%{x.l}Nx\u001fӳ\\Hv^7zJ\u0011v@nz!A#kU`[;\u0006F.ޭ\u00116p\u00021>}OϿ[̧Wȫl\u001b`nk\u0001>*^}s\u0019K?O^bb\u0011.f$#k!8!C'jw=q\u0007}H\u000e\u0000 \" \u0019ghx`7+\u0001n8M\n\u0001Nѹũw\u000fV˾z\u000b\r\u0005\u000bAٞ`è\u0003Bɹ\u001dlzT~Md<~\u0015J-h'I\u0012ydB't2n~\u0010d\t\u000bt\u0000\b\\X_\u0000!p\u0000\bR*xJc@e\u001a\u0010HP\u0005iq\u0000ßwǍ*>U5[\u0004ĝz{+<Mlu2!-Z\u000f-=\u0012!aHoopr\u0019L\b-@/n?$)q\u000e,H1\u00011* \u0000Xi\n\u000fH\u0011\u001e\u001b\u0017\u0014l˓VI] qł̽Dˢy\u0018F˿i庮E\u0014j<=%\u0018k6se؞M]A>y@yO\u0017P\u0016TJ~uS\u0006\u0012o\u000b@I)\u0003(gRL,@)zW饟+@1\f m\u0001\u0006de\u0000!ޙ\u0012z\u0002\u001e:XdUYoUCLq*>T1\u001eqnC\u001e)Fp>g\u0010Å\u000fi=\u0017UU֭+\u0017QsF(\tE0眳Ak̽ΟG\u0014 PznQ\u00150Ѻ\u0016l\u0013\t72h\u0004$xĀq-`Jy\u001c0Y\u0006\nzaU\f0FK~xz8_99\u001b34#Ru\"z\u0005\u00052\f_D]KN\u0001yu\u001c\u0002\u000e|\u0012\u0016\nR\u0004W`2J\u0002\rV\u001f\rN\t\u0000p$$\b\rr\u0000\u00057\u0007\u0001v:K>؃&?-&W*wr\u0007w]8N{;_ij-=\u0010f\\!)b۾n;Nx~aҧQM˚\u000f\u0004:t\u0001~%p1O\u00127|K\u0013\u001cSq\u000e@\u001a}21\u0003)'\ro\u0004Wsٗ6 m\u000f\rP\u0015\u001cPI\u0001hxø1\u0000\u001d\u0010\u000e\u0001ym+;\u0010e\n\u0005\b\u0007b\u001e@^U\u00173w\u000f\u001e%@@\f\u000f &\u0006\u0010+!\u0010\u001ds_\n-{Vog+նX\u001d\u001dL~D2ڏ\u0005\u0002Z?f\u0004\u0012t\u0003?_\rs+\u0013G`u \u0007<L`<\u0001x\u0007rr\u0006\u0000|>́^a@ތ5w}g3SvSS#1\u0015d}[\u0011[d?\rW;\u001a\u000b\u0019~C\u0013ׁ\rkͪo4@ڼ@j\" ]\u0018 ݔZ\u001f\u001f;@zM%Kn\u0006'͖\u0016ީFӆeZ\u0014'yҡr!I߆|VmMѓ;\u0001IN_XY\u0003\u0006!<E`3\u000f\u0018n4\u0001F\t\u0001߲11ԮXC?aX_\u0005\u001bp)Ff6v \u001amKÜRE˸CоUVWu߂+\u0004eHHB\\y>O\u0001t*I4[׺y\u0010W\u000e(_yS0-\u0011c&7<]^ba|Ob\u0000\u001fCh\u001f9R?J\u001buoOn=\u001d *Ō7G}j?\u0014\u001f\u001b4mZTgC!9q%C3\u0017\u001dr\u0010\fX~\u001d\u000bh3SzS&J؊\u001b\u0000y-\u0017kPV<fQ\u0017yӁZW&coO\u0001\u001c\b|\u0019-mTI\u001bj_2 r>Mm\u000e14\u0006Tr)E\u0003徦ۏra\u000be>z\"}Of-}2N2\u0013ʏFq\u001b4j*h\u000eŤ;\bոjY]P|6>ղJr\u00167\u000be38#W}Ykǅ\u000eJ_9x<7\rf\u000fԘfhye\\7=OeֻgO;InWЮy\u000e8صb\u0017\u000b\nѲ4Fz\u001f{\u0012\u0006y\f˃l*ϵ߸F-|1u\u000eEy\u001dTve\u0000Y~g\u0007\\!&=k]i\u0007#yGׁr[11eO\b\u0017f-n.@`?H(\u001ec3Tk\u001aφԠɓ\"mtdTCrrEehQ\u0015_q\u0015\u001ae]N2H[N0?)\bIUk=3HCX<v;TXB\u0014jR͆vV \u0019gסZ9Ԭ\u000b]uiWYVqey\be2v@~\u0010/\u0000t\u001df)/c^\u0016/\u0006p~Pq\u001agBA\u0002@@I\u0007\u0006f(d<T^s(U]U|B7:_NM\u000fkwj-Oysk?*t(ݮө\u0017i\\\u001c¸\u000b9\bw+z_Cn3\u0004\u0001䪶~-ܞ\u0014u $3^|T^,y\u0018&ͻ&uh\u0018U6*W\u0005bꋗtn%\u001dήlAq.\r)\u001bQ@7\u0007qfuXt\u0013!o䪆S0%h3Ɇ\u0005U.}\"Yy\\\u000e\u001e4Ŭ_iD\u0003\u0013p'6|\u001c K\"5\u001dy*\n\u0007n\u0005E\u001b/\u0005ti;._\u0018}93ӗ*W{{-jܳa\rs#4sNN\u0005B\fb9\u001a?i1\u001e:g=I\u0003E}ݗ\\h<b\u0002#svg%MwJ\u0003!^]֘KY,祎<9Wvmf\u000eqeVYFxYO\u001b[Wsa\u00015dݘo\u0004Ͻ({Ec^Az\u0004Ǵ1p\u0011\u0001G};6\u000e[J\u000efN\u000bG}U?v~ݗKvlڙvs255TX1\nAS\u0007^\n6\u00033<|'dӇtm&BPգ4cTH+VTҳ][7J[ٸa\u0015kJil\"ep^N~CUzz\fX+;l_6J{9\tT24\u001e0͹U>]0yԦ\b|b:%GJ\u000b>\tr&R?\u0005).mq4U/拋J058v\f&7Mz\u0018nfe/Ŝ\u0014buk0捚\u0005r\u001b\bH2\u0012W&+\"rgqe)U7jJF-Av$`)ID\u0016\u0010\u0003-\u0010}}hVm~mj\u001bW5w2W\u001dZZ\u001eMo.\u0017\u001blfr(1STz\u001bh\u001bfz<kODTbz$H\u0003nHP05D\u0007m\u0011\u001d^,T\u0004\u0017\u0015\u0002/$}\u0018~\u0019<\u0003V[nf\u001e\\R9^{٠xA\u0003LG'&y<vZ-&|8[\u0005/޴\u0013\u0005\u0004ͯ[\u0010͎\u0019\u001fĎ5jZ\u0011깳Ud /XqE^ YSz\u0019ѳͻ_⪃u˩=\r5+uV\u0017ER\b\u001a\u0012}\"?\u000fB=ځy\u0010MLz\r\\[ ]ǥFV]6\u001b\\n\u0017.UwR\u000e\u001f\u001e4gr]Ke\u001cAs[=6Jkbi\tYQ_Q-v]3PKGy[\u0010\u00141̑ó\u001dcKL\u0001ALKD\n\u0005-9۶\u001f{\u001d޷BV\u0010)ƈ0\\\\?ò\u0003^$5ObE~%5\tƆ`׀dZqҷg,L5KhHf8c)g7!G8#sڋ*;(¥,O\u0010xSg\u001bũKT=<\u0017m\u000bDE\u0006W\u0003+U\u0004X˃\u0005Y\u00071ʩ0\u001dn\ryy\u0012,);\u0004՗U\\lJ\u0002\u001c\u0007\u0016G7\u000e\u001c\n1m(!Q4b4]^4\u001f%X\u0018\u001d\u0006\u001e\u0016?\bZߑ0Zg=tϧ\u0018_DYg\u001c\u001b3M\u001b\u0007MH\u001b\u000bfM% r޶Hql4\u0013(MA%#>b`X\u0018\u0011_\u0002]ýUmҏ\u0006Vy$`[Y{rE\u0003*n QGB#*~K!*I\u0014\u0010\u0015\\HɬSi]h\u0018\u001fYY\\\u001cۥ\u001f\u001fQUG\u0019!b\u0010z]ƎJ)sl7͐\u0018e8^f}1e~gР\u0017QI\u001cԐ/H8fZ\u001e\u0011`pa!g6q\u0001YzHԁ\u001a(\t8)~ub_\u0017ppt\t\f/-o@\u0004\u0013֭Mm=\u0019j4\u0005|5\b\u0010n\tTN(%\f\u00047\u0005Qߌ\u0005\u0006V\u0001nȀ1q3(#\u000f\u00108mT.-)vA\u0000\u000e\u001f\u0002O=%PV\fL[V09\u0013QUZ\u0007=\u001fl_\u001fy\u0011gl0&Ӏ;i\u0003^쌓Ή\\ˑ\u0004fH\u001cH\u000f\u001f\u00045\u0006lz\u0012Ȁ)`uB!'6A\b\u0000>\u0004;\u0017\u0000s\u0006\u0000|P$\u0000>DvM-͜Up`syT,?|_Fy\u000f)Ì\u001762bӬA9F\u0001\u0016<\rU\u001e!\u0007w\u0012\u001a+\u0013\u000e\u0014\u000f9\u0016\u0010`'x\u0001+\t1 Bh`);jE* \"#{9\u0001Du\u0002D|\u001b\u0002\u001c\u0012/eD\u0007_\u0017\u001ec93/,;\u0018\u0016tk $nEϋ\u0005?K\u0019\fV\u0004d|V\u0000ن\u0004\rȚ_J0\u000b\u0000Y'z\t\u0004; \n\t\u0006n\u00024\u0003󗀴%\u00189:l\u000be\u000f@\b\bpK~\u0003VE灣KR[\u001f\u0016gļa5e\u001f1~\u000eː\u0001$\bL@-Z\u0001`\u0002j\u0012d\u0004\tF\u0001PQ\u001d\u0000*Nq\t9@uh\u000f\u0004)\u0000J>l\u0001P@CV?0\u000f.\u0019ҀYݓ5J\u0012\b4gmE3\\6ҝ$\u0000á?@9'AKP\u0002Q1\u0005?^\u0003@?e\u0015G\nǡ\nZ\u0002\u0007jt\u0003\u0013\u0000\u001d'\u0003\u0016&K\u0016u\u000eЦTղq\u000b2ĺNl4̊|\u00074xc#/OΗ \u0017~mZ7J\n`= \u001d'u\u0013Ԇ\t&s!\u0006}`\u0000s\u0004:`fu/'!Z\u0005G\u001de.\u0001W\u0018&\n͹2[~w+J16|IȻ:\u0006v)v\u0001\u001e~};\u0018~;?\u0003<n\u0012\u0004\u001b9\u0015K0\u0001kEc\u0018xm\u0007w\u0000<\u000b;@0&`G\u001f{q';?LSӋU$\u001fD8#\u000bqF6GH}\u0004BO\u0006\u0002u\u001f\u0005W՝k\u0004\u0017\u0010\u000e3\u0004\b/\u0001\"\u001e@$؏o\\$Vc \r)I\u0000\"DWpKpG\u0018 73lٚ\u0007\u001a&\u0014\u001bF\bC\u001aM\u0005#(n.ne\u0000OzW\b\r+~3yG]\u001c d+Ar6j\u0006B\fd\u0002 ?JVX5iR|/\t[>`!+[AƼL\tYw\u001fW5~t\u000en\u0013UpW(97TM\u0013@\u001d\\.@]X^\u001a.HC)Po.\u0002]>\u000fԽ,r(r\u001f̤=p6ڮ\u0012fQ8bw\u0005\u0001uۿnof\u0017_\u0005k[:tRez\n\u001f\u0003:\u0001_x\u000bg(\u0002\u0006A>Ҟ\r`-0!\u0005Ư\u0010R7\u0019\u0011[X\u001am\u0004\u000e젏::\u00111bnh%\\g<^\u0007,ex{hS\u0000)]\u001e\u0019?M9heo2W\u0013~JO}q\u0004#t\\~t|NPɩ|,aj9\\A/x\r\u0006\rAgۢ\u0014ﰺOkU\u0019w\u0019Vs\u0011ҳ<\u0016B+~#\u0007)\brr?w3oc<\u0019,-y6u\\\u0010վ{s6vPudoJaDw\u0011R\u0012EH\u0010GE\u000e&:fz2֕\u0004_c7\u0015#\u001f\u001d*\u0005\u0007%#\u000f\u0002~6k^E\u0017$k\u001b)l~\u001bP|Tr\u0010}|d\u0013cOˈ\u001e7a\u0015KCn\u0006\u0001\u0015S%!7*λf׼\u001f;0sj;H\u001f]bb\u000f\u0016X_aOz7$ɡ\u000f,N4&p\u000bA@q?dA/\u0016i8@׷\u001d\u001fNJё]4\u0003A\",M}ߵ0\u0010'fJk\u0007\u000e\u001b۞\u0004]{s{>pV\u001dZ5_|]Uxm\\񠍹ᚎչ\u0014ICn\"ZW) \u001d\u000egiF˂om<\u0014J5\u0014\u000fZ\u0019ZܸFJ=AеďU[\u00079mS\u0010{u\u0007p؎/<&2w~`~w\u001aۼZWk\u0003~`A+&.=ZUrj\rЈ\u0012\u001at\u0002U\u001fd3\\m\u0018r\rgKe2?He܉+(7A/s\\\u000fҹw\u0014^hF`t\u001fѵKrqg\"d\n*әE\u001a*b\u0016qWV?zt\\\u0013o}ڸ\u0019\nY`&8ZUt[Ԣo֯xm<YJqTL|\u0017߳P*\u000e܁VVaygV~\u00108FM\\f\u0004aKHdfO0\u001bW\u0015U!ż]h\u0019\u001c/\u0010\u0011\u000f\u001b\u0016<ɧqŸ\u001e\u001fd$)\u000f>d8(Fw\u0015yy\u0010Gp\n\u0014q|sU\u001dG}\u000f' #sP*\fbZնiY\u001c36\u001c4$҄.W'\u0019\u0018k\u0014~\u001f\rm=d%zo\"xZP[|S#Zp-8u}f5+\r[|\u0017iPeU>A2q>xgmuhgYb\u000ei\rM6Ы^lf1LZ|Z\u001ck.\u0013x4Of7#Yt\u0007\u001d=\u001fmSl\u0007i7\u001bEl\u0011^qDN)s}M\u000eN3#V{\u0014L}c\u001c5ÑԦNܫS7Uz\u001c\u001cUA'Ԡ\u0013(ʙx\u0014p-c|;NpZ}1P\u001dj%s\u001e\f{\u000fZV)?|\u000e\u0010Cg\to9aߴ3w<T\u0010sh$Ùf\u0004]ʲR3ƴ3(\u0015\u0007]W\u001b6V񶧴\f0o\u000bf#=*==XaAJռ8\\B-\u0011a*KarW`<c%\u00140=\u00172D5.OB\u001ePf}E0\"ElMqhfc2rՒ.äkR\u001bQ.HP*ѩ)\u001b:H/^z\u0017*4)LO\u001a3aJ\u000ewBa\rBQ|q0uɩs\u00151\u0018I?yU40\u000e/t=\u001bxlQ\u0007)+\u001b^J{r}^ܢ껆jz\t%MTzկ9\bq^Y1w$ajBiH\u0019\u0001_f\u000b¯y7u*&wu\"k(L\u0018r\u0007\u0012tf髚2J\u001e3\u0018u\u001c\u001aGk@CnbQc\u0013jt8,k1\u001a,챷B\"\nWS\u0002RSb<M4N\u001cǇ*{.3lw-U\u0013]u:a6cK.R]\\;%ߝ\u001c\u000f|/\u000fBYxzE۫?ڗʿ\u0012iޓ`lx\u0007\u0000vT훅\u001aaFi3iNQ\u0002⽗bC\u0015O\tb5kEOӱ\u0016شyc\u000e5n\u001cP<P\u0000b_D\u001c\tlpTϑP%|I8׀\u0018_SO,LO嶷 E29=f\u000652+H7ANms8.7\u0013\u0006\u0007}=oZO ia\t,eB\u00017/vk\\'<%}vI`IhVN!\u0002Ø$beI\u000bU0~7wش6|N3YJå-\u0016V4kk\u0006f\tPʧUP{IߒmxʋW;eM\u00079$7\t\u0019%pn-(7d\u000e\nN\u00071\u001aX\\`,&>Z\bQ! A2\u0017aĿ/B0VP*\u001f\u001fpT ;N=\u0002\u001c/QX\\.2IL\u0019Ϸ,ScWAr`lvAw\f%[hBG;!Mb!M3\u0011B5KZK{_F{};J#P@\u001cQ˾?.ݺ6^鷹7\u001b\rTX\u000f$gh;<K#\u001b#d>}v*ꎱ;@wM\u001cC늜kNB㞅4(L0\u001e×7w5Jp\u001aj޲\u0001ފ[L\u001fmC\u000f;\u0013\u0014y'v7[|_-G&|-aKI{Nq\u0012ɻ^`]\u00014\u0010e\u0007OtoI\u001eޑeF JLp,X;KPW\u001ayu\u00063ۦl\\M7\u0000UJ\u0006F\to\u001e\\n\b\u001cM\ts7<\u0006W\\Q;\u001fF79k}\u001bܐbB+Әߙ˴49.)\u0000*\u0017\u001c&OPwC\u0011J\r.HrH\u0003g6\u0001\u0004w\u0013\u001by\fH\u0001G\u00153S\u0014\u001c\u0006XA\u001c5FonP̓n|<WJtr*u$\u0019Y\u0018|P-p[K\u0019śY.e\u0010\u001evУxt\u0000A%BN\nl\u0005N0\"\u0013Dsi#A\b~#?J8\u0000\\\b\u0010ѓW\u0000pr\u00048\u0000\u000e\u0000ɒpg\u0011\u0006ڸò!\u000fP[\u0015KƱ28sZK4\u001f\u0004.\u0005>S0\u001a3\u0017`CD3F$7|􀠀 \t(\u0002D\u0012\u0014\u0004\u0013\u001b\u0010\u0010VN\rendstream\rendobj\r8 0 obj\r[7 0 R]\rendobj\r56 0 obj\r<</CreationDate(D:20140325091422-04'00')/Creator(Adobe Illustrator CS4)/ModDate(D:20140325091422-04'00')/Producer(Adobe PDF library 9.00)/Title(Fig 2 - Tuxedo Workflow)>>\rendobj\rxref\r0 57\r0000000000 65535 f\r\n0000000016 00000 n\r\n0000000144 00000 n\r\n0000069043 00000 n\r\n0000000000 00000 f\r\n0000074287 00000 n\r\n0000479466 00000 n\r\n0000479280 00000 n\r\n0001069711 00000 n\r\n0000069094 00000 n\r\n0000069582 00000 n\r\n0000491330 00000 n\r\n0000087418 00000 n\r\n0000087305 00000 n\r\n0000072404 00000 n\r\n0000072683 00000 n\r\n0000072962 00000 n\r\n0000073240 00000 n\r\n0000073519 00000 n\r\n0000071312 00000 n\r\n0000071843 00000 n\r\n0000071891 00000 n\r\n0000478786 00000 n\r\n0000478848 00000 n\r\n0000478288 00000 n\r\n0000478350 00000 n\r\n0000477787 00000 n\r\n0000477849 00000 n\r\n0000477286 00000 n\r\n0000477348 00000 n\r\n0000073798 00000 n\r\n0000073860 00000 n\r\n0000074225 00000 n\r\n0000074687 00000 n\r\n0000074949 00000 n\r\n0000087453 00000 n\r\n0000477725 00000 n\r\n0000478226 00000 n\r\n0000478724 00000 n\r\n0000479218 00000 n\r\n0000479350 00000 n\r\n0000479381 00000 n\r\n0000479827 00000 n\r\n0000480100 00000 n\r\n0000491404 00000 n\r\n0000491756 00000 n\r\n0000492808 00000 n\r\n0000500092 00000 n\r\n0000545007 00000 n\r\n0000610595 00000 n\r\n0000676183 00000 n\r\n0000741771 00000 n\r\n0000807359 00000 n\r\n0000872947 00000 n\r\n0000938535 00000 n\r\n0001004123 00000 n\r\n0001069734 00000 n\r\ntrailer\r<</Size 57/Root 1 0 R/Info 56 0 R/ID[<E02F3D4EAD7F4398B10BE26FCC9EB74B><673AF5C8AE8E475195C4BC2A6D342F23>]>>\rstartxref\r1069921\r%%EOF\r"
  },
  {
    "path": "external_tests/tiny_tests/2x75/accepted_hits.sam",
    "content": "@HD\tVN:1.5\tSO:coordinate\n@SQ\tSN:test_chromosome\tLN:650\ntest_mRNA_3_187_51\t99\ttest_chromosome\t53\t255\t75M\t=\t163\t0\tTACTATTTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTCGGACTACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_4_191_5d\t163\ttest_chromosome\t54\t255\t75M\t=\t167\t0\tACTATCTGACGAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTACCATTACGCGGATGACGACTAGGACTACGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_5_197_46\t99\ttest_chromosome\t55\t255\t75M\t=\t173\t0\tCTATCTGACTAGACTCGAGGCGCTTGCGTCTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_6_182_59\t99\ttest_chromosome\t56\t255\t75M\t=\t158\t0\tTATCTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCAGTACGGGGATGACGACTAGGACTACGGAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_8_155_9\t163\ttest_chromosome\t58\t255\t75M\t=\t131\t0\tTGTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_8_197_1\t99\ttest_chromosome\t58\t255\t75M\t=\t173\t0\tTCTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGACACTACGGGGATGGCGACTAGGACTACGGACGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_9_179_52\t163\ttest_chromosome\t59\t255\t75M\t=\t155\t0\tCTGACTAGACTGGAGGCGCTCGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_11_190_1a\t99\ttest_chromosome\t61\t255\t75M\t=\t166\t0\tGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_16_194_10\t163\ttest_chromosome\t66\t255\t75M\t=\t170\t0\tGACTGGATGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTCGGACTACGGACGGACTTAAAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_21_208_24\t163\ttest_chromosome\t71\t255\t75M\t=\t184\t0\tGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_22_173_62\t99\ttest_chromosome\t72\t255\t75M\t=\t149\t0\tAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_23_186_42\t163\ttest_chromosome\t73\t255\t75M\t=\t162\t0\tGGCGCTTGTGACTGAGCTAGGACGTGCCACTACGGGGATGAAGACTAGGACTACGGACGGACTTAGAGCGTCAGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_26_189_30\t163\ttest_chromosome\t76\t255\t75M\t=\t165\t0\tGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_28_188_11\t99\ttest_chromosome\t78\t255\t75M\t=\t164\t0\tTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGAACGGACTTAGAGCGTCAGATGCAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_28_206_1f\t73\ttest_chromosome\t78\t255\t75M\t*\t0\t0\tTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGACGCAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_30_231_3c\t163\ttest_chromosome\t80\t255\t75M\t=\t207\t0\tGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_33_223_4e\t73\ttest_chromosome\t83\t255\t75M\t*\t0\t0\tACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_36_146_27\t163\ttest_chromosome\t86\t255\t75M\t=\t122\t0\tGCGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACAGACGGACTTAGAGCGTCAGATGCAGCGACTGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_36_218_12\t99\ttest_chromosome\t86\t255\t75M\t=\t194\t0\tGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGCCTTAGAGCGTCAGATGCAGCGACTGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_38_199_29\t99\ttest_chromosome\t88\t255\t75M\t=\t175\t0\tGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_39_219_5c\t99\ttest_chromosome\t89\t255\t75M\t=\t195\t0\tCTAGGACGTCCCACTATGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGGCTGGACTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_41_236_55\t99\ttest_chromosome\t91\t255\t75M\t=\t212\t0\tAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGAATATT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_42_209_25\t99\ttest_chromosome\t92\t255\t75M\t=\t185\t0\tGGACGTGCCACTACGTGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_44_193_3f\t99\ttest_chromosome\t94\t255\t75M\t=\t169\t0\tACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGTCTATTTAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_44_197_35\t99\ttest_chromosome\t94\t255\t75M\t=\t173\t0\tACGTGCAACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_44_225_1e\t137\ttest_chromosome\t94\t255\t75M\t*\t0\t0\tACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCGGGTGCAGCGACTGGACTATTTAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_46_195_17\t137\ttest_chromosome\t96\t255\t75M\t*\t0\t0\tGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_46_232_2f\t99\ttest_chromosome\t96\t255\t75M\t=\t208\t0\tGTGCCACTACGGGGATGACGACTAGGACTACGGCCGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_48_207_39\t73\ttest_chromosome\t98\t255\t75M\t*\t0\t0\tGCCCCTACGGGGATGACGACTAGGACTACGGACGGATTTAGACCGTCAGATGCAGCGACTGGACTATTTAGGACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_48_249_20\t137\ttest_chromosome\t98\t255\t75M\t*\t0\t0\tGCCACTACGGGGATGACGACTAGGACGACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_50_224_2d\t137\ttest_chromosome\t100\t255\t75M\t*\t0\t0\tCACTACGAGGATGACGTCTAGGACTACGGACGGACTTAGAGCGTCAGACGCAGCGACTGGACTATTTAGGACGAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_51_194_47\t163\ttest_chromosome\t101\t255\t75M\t=\t170\t0\tACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_51_194_49\t99\ttest_chromosome\t101\t255\t75M\t=\t170\t0\tACTACGGGGATGACGACTAGGCCTACGGATGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_51_237_a\t99\ttest_chromosome\t101\t255\t75M\t=\t213\t0\tACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_51_248_14\t73\ttest_chromosome\t101\t255\t75M\t*\t0\t0\tACTACGGGGATGACGACGAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGAACTTTTTAGGACGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_52_261_1b\t73\ttest_chromosome\t102\t255\t75M\t*\t0\t0\tCTACGGGAATGACGACTAGGGCTACGGAGGGACTTACAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_53_212_19\t73\ttest_chromosome\t103\t255\t75M\t*\t0\t0\tTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGAATATTTAGGACGATCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_53_272_5a\t137\ttest_chromosome\t103\t255\t75M\t*\t0\t0\tTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_56_183_56\t99\ttest_chromosome\t106\t255\t75M\t=\t159\t0\tGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTGGGACGATCGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_57_231_8\t99\ttest_chromosome\t107\t255\t75M\t=\t207\t0\tGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCACCGACTGGACTATTTAGGACGATCGGACTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_58_218_16\t163\ttest_chromosome\t108\t255\t75M\t=\t194\t0\tGGATGACGACTAGGACTACGGACGGACTTAGAACGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_58_220_3d\t137\ttest_chromosome\t108\t255\t75M\t*\t0\t0\tGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_58_234_7\t163\ttest_chromosome\t108\t255\t75M\t=\t210\t0\tGGATGACGCCTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_63_229_4c\t163\ttest_chromosome\t113\t255\t75M\t=\t205\t0\tACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGGGACTGGACTATTTAGGACGATCGGACTGAGGAGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_65_238_2e\t99\ttest_chromosome\t115\t255\t75M\t=\t214\t0\tGACTAGGACTACGGACGGACTTAGAGCGTCAGAAGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_69_229_23\t163\ttest_chromosome\t119\t255\t75M\t=\t205\t0\tAGGACTACGGACGGACTTATAGGGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_36_146_27\t83\ttest_chromosome\t122\t255\t75M\t=\t86\t0\tACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGTGCAGTAGGT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_72_258_4\t137\ttest_chromosome\t122\t255\t75M\t*\t0\t0\tACTACGGACGGACTTAGAGCGTCAGATGCAGCAACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_73_240_34\t99\ttest_chromosome\t123\t255\t75M\t=\t216\t0\tCTACGGACGGACTTAGAGCGTCAGATGCAGCGAATGGACTATTTAGGACGCTCGGACTGAGGAGGGCAGTAGGAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_73_259_5e\t99\ttest_chromosome\t123\t255\t75M\t=\t235\t0\tCTACGGACGGACTTAGAGCGTCAGATGCTGCGACTGGACTATTTGGGACGATCGGACTGAGGAGGGCAGTAGGAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_75_204_54\t73\ttest_chromosome\t125\t255\t75M\t*\t0\t0\tACGGACGGACTTCGAGCCTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_75_235_21\t73\ttest_chromosome\t125\t255\t75M\t*\t0\t0\tACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGCACGATCGGACTGAGGAGGGCAGTAGAACGT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_75_277_3b\t73\ttest_chromosome\t125\t255\t75M\t*\t0\t0\tACGGACGGACTTAAAGCTTCAGATGCAGCGACAGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_77_256_2c\t99\ttest_chromosome\t127\t255\t75M\t=\t232\t0\tGGACGGACTTAGAGCATCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_78_276_4b\t73\ttest_chromosome\t128\t255\t75M\t*\t0\t0\tGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGGCGCTAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_79_256_31\t137\ttest_chromosome\t129\t255\t75M\t*\t0\t0\tACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_81_228_3a\t163\ttest_chromosome\t131\t255\t75M\t=\t204\t0\tGGACTGAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGTAGTAGGACGCTACGTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_81_245_4d\t163\ttest_chromosome\t131\t255\t75M\t=\t221\t0\tGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGATGAGGGCAGTAGGACGCTACGTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_8_155_9\t83\ttest_chromosome\t131\t255\t75M\t=\t58\t0\tGGACTTCGAGCGTCAGATGCAGCGACTGTACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_82_255_2\t163\ttest_chromosome\t132\t255\t75M\t=\t231\t0\tGACTTAGAGCGTCAGATGCAGCGACTGGACTTTTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_82_271_58\t73\ttest_chromosome\t132\t255\t75M\t*\t0\t0\tGACTTAGAGCGTCAGTTGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_85_268_53\t99\ttest_chromosome\t135\t255\t75M\t=\t244\t0\tTTAGTGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_87_250_57\t137\ttest_chromosome\t137\t255\t75M\t*\t0\t0\tAGAGCGTCAGATGCAGAGACTGGACTATTTAGGACGATCGGACTGAGGAGTGCAGTAGGACGCTACGTATTTGGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_87_279_5f\t163\ttest_chromosome\t137\t255\t75M\t=\t355\t0\tAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACCGAGGAGGGCAGTAGGACGCTACGTATTTGGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_88_257_50\t163\ttest_chromosome\t138\t255\t75M\t=\t233\t0\tGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_89_230_b\t163\ttest_chromosome\t139\t255\t75M\t=\t206\t0\tAGCGTCAGGTGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_89_245_15\t99\ttest_chromosome\t139\t255\t75M\t=\t221\t0\tAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_89_267_32\t137\ttest_chromosome\t139\t255\t75M\t*\t0\t0\tAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGAGTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_91_256_41\t99\ttest_chromosome\t141\t255\t75M\t=\t232\t0\tCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_92_250_44\t73\ttest_chromosome\t142\t255\t75M\t*\t0\t0\tGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_92_266_43\t73\ttest_chromosome\t142\t255\t75M\t*\t0\t0\tGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTCAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_96_238_3\t163\ttest_chromosome\t146\t255\t75M\t=\t214\t0\tGATGCAGCGACTGGACTATTTAGGACGATCGGACGGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGACC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_97_275_26\t73\ttest_chromosome\t147\t255\t75M\t*\t0\t0\tATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_22_173_62\t147\ttest_chromosome\t149\t255\t75M\t=\t72\t0\tGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_103_284_2a\t163\ttest_chromosome\t153\t255\t75M\t=\t360\t0\tCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_104_278_3e\t137\ttest_chromosome\t154\t255\t75M\t*\t0\t0\tGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTTTTTGGCGCGCGGCCCTACGGCTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_105_266_13\t137\ttest_chromosome\t155\t255\t75M\t*\t0\t0\tACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_105_276_c\t137\ttest_chromosome\t155\t255\t75M\t*\t0\t0\tACTGGACTATTTAGGACGATCGGACTGAGGAAGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_9_179_52\t83\ttest_chromosome\t155\t255\t75M\t=\t59\t0\tACTGGACCATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_106_253_45\t137\ttest_chromosome\t156\t255\t75M\t*\t0\t0\tCTGGACTATTTAGGTCGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_107_286_5\t163\ttest_chromosome\t157\t255\t75M\t=\t362\t0\tTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGCATTTGGCGCGCGGCCCTACGGCTGAGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_6_182_59\t147\ttest_chromosome\t158\t255\t75M\t=\t56\t0\tGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_56_183_56\t147\ttest_chromosome\t159\t255\t75M\t=\t106\t0\tGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_110_267_22\t163\ttest_chromosome\t160\t255\t75M\t=\t243\t0\tACTAGTTAGGGCGATCGGACTGAGGAGGGCAGTAGGACGCTACGTAGTTGGCGCGCGGCCCTACGACTGAGCGTC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_110_271_28\t73\ttest_chromosome\t160\t255\t75M\t*\t0\t0\tACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_111_297_61\t137\ttest_chromosome\t161\t255\t75M\t*\t0\t0\tCTATTTAGGACGATCGGACTGGGGAGGGCAGTAGGACGCTACGGATTTGGCGCGCGGCCCTACGGCTGAGCGTCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_23_186_42\t83\ttest_chromosome\t162\t255\t75M\t=\t73\t0\tTATTTAGGACGATCGGACGGAGGAGGGCAGAAGGACGCTACGTATTTGGCGCGCGGCCCTACGACTGAGCGTCGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_3_187_51\t147\ttest_chromosome\t163\t255\t75M\t=\t53\t0\tATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_114_277_5b\t137\ttest_chromosome\t164\t255\t75M\t*\t0\t0\tTTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGCCTGAGCGTCGAGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_28_188_11\t147\ttest_chromosome\t164\t255\t75M\t=\t78\t0\tTTTAGGACGATCGGACTGAGGAAGGCAGTAGGACGCTTCGTATTTGGCGCGAGGCCCTACGGCTGAGCGTCGAGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_26_189_30\t83\ttest_chromosome\t165\t255\t75M\t=\t76\t0\tTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGGTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_33_189_4a\t89\ttest_chromosome\t165\t255\t75M\t*\t0\t0\tTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACCTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGGGCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_116_271_2b\t137\ttest_chromosome\t166\t255\t75M\t*\t0\t0\tTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_116_295_63\t163\ttest_chromosome\t166\t255\t75M\t=\t371\t0\tTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_11_190_1a\t147\ttest_chromosome\t166\t255\t75M\t=\t61\t0\tTAGGTCGATGGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGTGGCCCTACGGCTGAGCGTCGAGCTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_4_191_5d\t83\ttest_chromosome\t167\t255\t75M\t=\t54\t0\tAGGACGATCGGACTGAGTAGGGCAGTAGGACACTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_118_297_f\t137\ttest_chromosome\t168\t255\t75M\t*\t0\t0\tGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_44_193_3f\t147\ttest_chromosome\t169\t255\t75M\t=\t94\t0\tGACGATCGGACTGGGGAGAGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_16_194_10\t83\ttest_chromosome\t170\t255\t75M\t=\t66\t0\tACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_51_194_47\t83\ttest_chromosome\t170\t255\t75M\t=\t101\t0\tACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_51_194_49\t147\ttest_chromosome\t170\t255\t75M\t=\t101\t0\tACGTTCGGACTGAGGAGGGCAGTAGGACGCCACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_122_299_6\t137\ttest_chromosome\t172\t255\t75M\t*\t0\t0\tGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_44_197_35\t147\ttest_chromosome\t173\t255\t75M\t=\t94\t0\tATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGATCGTCGAGCTTGCGATAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_5_197_46\t147\ttest_chromosome\t173\t255\t75M\t=\t55\t0\tATCGGACGGAGGAGGGCAGTAGGACGCTACGTATTTGGCGGGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_8_197_1\t147\ttest_chromosome\t173\t255\t75M\t=\t58\t0\tATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_125_280_48\t99\ttest_chromosome\t175\t255\t75M\t=\t356\t0\tCGGACTGAGGAGGGCAGTAGGACGCTATGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGAAACGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_125_293_60\t163\ttest_chromosome\t175\t255\t75M\t=\t369\t0\tCGGACTGAGGAGGGCAGTAGGACGCTATGTATTTGGCGCGCGGCCCTACGGCTGAGCTTCGAGGTTGCGATACGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_38_199_29\t147\ttest_chromosome\t175\t255\t75M\t=\t88\t0\tCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_126_282_18\t163\ttest_chromosome\t176\t255\t75M\t=\t358\t0\tGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\ntest_mRNA_21_208_24\t83\ttest_chromosome\t184\t255\t67M100N8M\t=\t71\t0\tGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGCCTGAGCGTCGAGCTTGCGATACGCCACTATTAC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_42_209_25\t147\ttest_chromosome\t185\t255\t66M100N9M\t=\t92\t0\tAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_36_218_12\t147\ttest_chromosome\t194\t255\t57M100N18M\t=\t86\t0\tGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_58_218_16\t83\ttest_chromosome\t194\t255\t57M100N18M\t=\t108\t0\tGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_39_219_5c\t147\ttest_chromosome\t195\t255\t56M100N19M\t=\t89\t0\tGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCCAGCTTGCGATACGCCACTATTACTTTATTATCTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_81_228_3a\t83\ttest_chromosome\t204\t255\t47M100N28M\t=\t131\t0\tTATTTGGCGCGCGGCCCTATGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGTAGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_63_229_4c\t83\ttest_chromosome\t205\t255\t46M100N29M\t=\t113\t0\tATTTGGCGCGCGGCCCTACGGCTGAGTGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_69_229_23\t83\ttest_chromosome\t205\t255\t46M100N29M\t=\t119\t0\tCTTTGGCGCGCGGCCCTACGGCTGAGCGTCTAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_89_230_b\t83\ttest_chromosome\t206\t255\t45M100N30M\t=\t139\t0\tTCTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTAACTCACTCGGACGTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_30_231_3c\t83\ttest_chromosome\t207\t255\t44M100N31M\t=\t80\t0\tTTGGCGCGCGGCCCTACGGCTAAGCGTCGAGCTTGCGATACGCCACTATTACTTTAATATCTTACTCGCACGTAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_57_231_8\t147\ttest_chromosome\t207\t255\t44M100N31M\t=\t107\t0\tTTGGCGCGCGGCCCTAGGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_46_232_2f\t147\ttest_chromosome\t208\t255\t43M100N32M\t=\t96\t0\tTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_58_234_7\t83\ttest_chromosome\t210\t255\t41M100N34M\t=\t108\t0\tGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTAGTTTATTATCTGACTCGGACGTAGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_41_236_55\t147\ttest_chromosome\t212\t255\t39M100N36M\t=\t91\t0\tGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_51_237_a\t147\ttest_chromosome\t213\t255\t38M100N37M\t=\t101\t0\tCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGAT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_65_238_2e\t147\ttest_chromosome\t214\t255\t37M100N38M\t=\t115\t0\tGCGGCCCTACGGCTGCGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_96_238_3\t83\ttest_chromosome\t214\t255\t37M100N38M\t=\t146\t0\tGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCTACTAGTACTTTATTATCTTACGCGGACGTAGACGGATC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_73_240_34\t147\ttest_chromosome\t216\t255\t35M100N40M\t=\t123\t0\tGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTTCTCGGACGTAGACGGATCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_81_245_4d\t83\ttest_chromosome\t221\t255\t30M100N45M\t=\t131\t0\tTACGGCTGAGCGTCGAGGTTGCGATACGCCACTATTACTTTATAATCTTACTCGGACGTAGACGGATCGGCAACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_89_245_15\t147\ttest_chromosome\t221\t255\t30M100N45M\t=\t139\t0\tTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTTCTCTATTATCTTACTCGGACGTAGACGGATCGGCAACG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_172_294_4f\t99\ttest_chromosome\t222\t255\t29M100N46M\t=\t370\t0\tACGGATGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTCCTCGGACGTAGACGGATCGCCAACGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_82_255_2\t83\ttest_chromosome\t231\t255\t20M100N50M100N5M\t=\t132\t0\tCGTCGAGCTTGCGATACGCCACTATTACTTTACTATATTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTC\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_77_256_2c\t147\ttest_chromosome\t232\t255\t19M100N50M100N6M\t=\t127\t0\tGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_91_256_41\t147\ttest_chromosome\t232\t255\t19M100N50M100N6M\t=\t141\t0\tGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_88_257_50\t83\ttest_chromosome\t233\t255\t18M100N50M100N7M\t=\t138\t0\tTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_73_259_5e\t147\ttest_chromosome\t235\t255\t16M100N50M100N9M\t=\t123\t0\tGAGCTTGCGATACGCCACTATTACTGTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_110_267_22\t83\ttest_chromosome\t243\t255\t8M100N50M100N17M\t=\t160\t0\tGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_85_268_53\t147\ttest_chromosome\t244\t255\t7M100N50M100N18M\t=\t135\t0\tATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGTCAACGGGACTTTTTCTACTTGAGACTGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_87_279_5f\t83\ttest_chromosome\t355\t255\t46M100N29M\t=\t137\t0\tTTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_125_280_48\t147\ttest_chromosome\t356\t255\t45M100N30M\t=\t175\t0\tTACTTTATTATCTTACTCTGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGAGCGAGGCGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_126_282_18\t83\ttest_chromosome\t358\t255\t43M100N32M\t=\t176\t0\tCTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_103_284_2a\t83\ttest_chromosome\t360\t255\t41M100N34M\t=\t153\t0\tTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_107_286_5\t83\ttest_chromosome\t362\t255\t39M100N36M\t=\t157\t0\tATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTT\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_125_293_60\t83\ttest_chromosome\t369\t255\t32M100N43M\t=\t175\t0\tTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_172_294_4f\t147\ttest_chromosome\t370\t255\t31M100N44M\t=\t222\t0\tACTCGGACGTAGACGGGTCGGCAGCGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACGTTTTAGGACGGG\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\ntest_mRNA_116_295_63\t83\ttest_chromosome\t371\t255\t30M100N45M\t=\t166\t0\tCTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGA\tIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\tXS:A:+\n"
  },
  {
    "path": "external_tests/tiny_tests/2x75/test_ref.fa",
    "content": ">test_chromosome\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nACTACTATCTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCC\nACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGC\nAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCT\nACGTATTTGGCGCGCGGCGCTACGGCTGAGCGTCGAGCTTGCGATACGCC\nGTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG\nACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACT\nGTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG\nTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACTTGC\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
  },
  {
    "path": "index.md",
    "content": "---\nlayout: page\npermalink: /\ntags: [cufflinks, RNA-Seq]\nmodified: 2013-09-13\n---\n\nCufflinks assembles transcripts, estimates their abundances, and tests for differential expression and regulation in RNA-Seq samples. It accepts aligned RNA-Seq reads and assembles the alignments into a parsimonious set of transcripts. Cufflinks then estimates the relative abundances of these transcripts based on how many reads support each one, taking into account biases in library preparation protocols. \n\nCufflinks was originally developed as part of a collaborative effort between the [Laboratory for Mathematical and Computational Biology](http://bio.math.berkeley.edu/), led by Lior Pachter at UC Berkeley, Steven Salzberg's [computational genomics group](http://ccb.jhu.edu/people/salzberg/) at the Institute of Genetic Medicine at Johns Hopkins University, and [Barbara Wold's lab](http://woldlab.caltech.edu/) at Caltech. The project is now maintained by [Cole Trapnell's](http://cole-trapnell-lab.github.io/) lab at the University of Washington.\n\nCufflinks is provided under the OSI-approved [Boost License](http://en.wikipedia.org/wiki/Boost_Software_License)\n\n# News\n\n*To get the latest updates on the Cufflinks project and the rest of the \"Tuxedo tools\", please subscribe to our [**mailing list**](https://lists.sourceforge.net/lists/listinfo/bowtie-bio-announce)* \n\n<ul class=\"post-list\">\n{% for post in site.posts %} \n  <li><article><a href=\"{{ site.url }}{{ post.url }}\">{{ post.title }} <span class=\"entry-date\"><time datetime=\"{{ post.date | date_to_xmlschema }}\">{{ post.date | date: \"%B %d, %Y\" }}</time></span></a></article></li>\n{% endfor %}\n</ul>\n"
  },
  {
    "path": "make_bin.sh",
    "content": "#!/bin/bash\n#simple script to pack up a precompiled binary package, with the boost thread\n# library statically linked in; on x86_64 Linux, libstc++ and libgcc are linked statically also\nif [[ -z \"$2\" ]]; then\n echo -e \"Usage:\\n./make_bin.sh <package_base_name> <boost_prefix> [<bam_prefix> [<Eigen_prefix>]]\"\n exit 1\nfi\n\necho \"packing up $1.tar.gz, using boost in $2, linking against $3 and using BAM in $4, using Eigen in $5\"\nmkdir $1\n#make clean\nmake distclean\nif [[ $(uname) = \"Darwin\" ]]\nthen\n    export CFLAGS=\"-mmacosx-version-min=10.7 -stdlib=libc++\"\n    export LDFLAGS=\"-stdlib=libc++\"\nelif [ $(uname -m) = \"x86_64\"]\nthen\n    echo \"Linking statically on x86_64 (only for gcc 4.5+)..\"\n    export LDFLAGS=\"-static-libgcc -static-libstdc++\"\nelse\n    echo \"Unrecognized architecture\"\nfi\n\n\nl2=\"$2\"\nl3=\"$3\"\nif [[ -z \"$l3\" ]]; then\n  l3=\"$l2\"\nfi\nl4=\"$4\"\nif [[ -z \"$l4\" ]]; then\n  l4=\"$l2\"\nfi\n# l5=\"$5\"\n# if [[ -z \"$l5\" ]]; then\n#   l5=\"$l2\"\n# fi\n\n\n#./configure --enable-intel64 --with-boost=$l2 --with-boost-thread=$l3 --with-bam=$l4 --with-eigen=$l5\n./configure --with-boost=$l2 --with-boost-thread=$l2/lib/libboost_thread.a --with-boost-system=$l2/lib/libboost_system.a --with-bam=$l3 --with-eigen=$l4 --with-boost-serialization=$l2/lib/libboost_serialization.a\nmake\ncp src/cufflinks $1\ncp src/cuffcompare $1\ncp src/cuffdiff $1\ncp src/cuffmerge $1/cuffmerge\ncp src/gffread $1\ncp src/gtf_to_sam $1\ncp src/cuffnorm $1\ncp src/cuffquant $1\ncp README $1\ncp LICENSE $1\ncp AUTHORS $1\n\ntar cvfz $1.tar.gz $1\n"
  },
  {
    "path": "src/GArgs.cpp",
    "content": "#include \"GBase.h\"\n#include \"GArgs.h\"\n#include <ctype.h>\n\nGArgs::GArgs(int argc, char* const argv[], const char* format, bool nodigitopts) {\n   /* format can be:\n      <string>{;|=} e.g. disable-test;PID=S= for --disable-test PID=50 (or --PID 50) S=3.5 etc.\n      <letter>[:]  e.g. p:hT  for -p testing (or -ptesting) -h -T\n   */\nconst char* fstr=format;\nfmtcount=0;\ncount=0;\nnonOptCount=0;\nnonOptPos=0;\noptPos=0;\nerrarg=0;\nerr_valmissing=false;\nargs=NULL;\nfmt=NULL;\n_argc=argc;\n_argv=argv;\nint fmtlen=strlen(format);\n//---- first parse the format string\nwhile (fstr-format < fmtlen ) {\n  int l=strcspn(fstr, \";=:\");\n  if (fstr[l]==0) { //end of string reached\n      //all previous chars are just switches:\n       GREALLOC(fmt, (fmtcount+l)*sizeof(fmtdef));\n       //store each switch\n       for (int i=0; i<l;i++) { \n         fmt[fmtcount+i].longopt=NULL;\n         fmt[fmtcount+i].opt=fstr[i];\n         fmt[fmtcount+i].req_value = false;\n         fmt[fmtcount+i].code=fmtcount+i+1;\n         }\n       fmtcount+=l;\n       break;\n     }\n   else {\n     if (fstr[l]==':') {\n         //fstr[l-1] is an argument, but all the previous are just switches\n         GREALLOC(fmt, (fmtcount+l)*sizeof(fmtdef));\n         //store each switch AND the option\n         for (int i=0; i<l;i++) { \n           fmt[fmtcount+i].longopt=NULL; //one char length\n           fmt[fmtcount+i].opt=fstr[i];\n           fmt[fmtcount+i].req_value = (i==l-1);\n           fmt[fmtcount+i].code=fmtcount+i+1;\n           }\n         fmtcount+=l;\n         }\n      else { // fstr[l]=='=' or ';' \n         GREALLOC(fmt, (fmtcount+1)*sizeof(fmtdef));\n         fmt[fmtcount].longopt=Gstrdup(fstr, fstr+l-1);\n         fmt[fmtcount].opt=0;\n         fmt[fmtcount].req_value=(fstr[l]=='=');\n         fmt[fmtcount].code=fmtcount+1;\n         fmtcount++;\n         }\n     fstr+=l+1;\n     }\n  }\n //-- now parse the arguments based on the given format specification\n parseArgs(nodigitopts);\n }\n \nint GArgs::parseArgs(bool nodigitopts) {\n  int p=1; //skip program name\n  int f=0;\n  while (p<_argc) {\n   if (_argv[p][0]=='-' && (_argv[p][1]==0 || _argv[p][1]!='-')) { \n     //single-dash argument\n     int cpos=1;\n     char c=_argv[p][cpos];\n     if (c==0 || (nodigitopts && isdigit(c)) || \n            (c=='.' && isdigit(_argv[p][cpos+1]))) { \n        //special case: plain argument '-' or just a negative number\n        GREALLOC(args, (count+1)*sizeof(argdata));\n        args[count].opt=NULL;\n        args[count].fmti=-1;\n        if (c==0) {\n          GCALLOC(args[count].value, 2);\n          args[count].value[0]='-';\n          }\n         else { //negative number given\n          args[count].value=Gstrdup(_argv[p]);\n          }\n        count++;\n        nonOptCount++;\n        }\n      else { //single-dash argument or switch\n       COLLAPSED:\n        if ((f=validShortOpt(c))>=0) {\n          GREALLOC(args, (count+1)*sizeof(argdata));\n          GCALLOC(args[count].opt, 2);\n          args[count].opt[0]=c;\n          args[count].fmti=f;\n          if (!fmt[f].req_value) {//switch type\n            GCALLOC(args[count].value,1);//so getOpt() functions would not return NULL\n            count++;\n            // only switches can be grouped with some other switches or options\n            if (_argv[p][cpos+1]!='\\0') {\n               cpos++;\n               c=_argv[p][cpos];\n               goto COLLAPSED;\n               }\n            }\n           else {\n              //single-dash argument followed by a value\n            if (_argv[p][cpos+1]=='\\0') {\n                if (p+1<_argc && _argv[p+1][0]!=0) { //value is the whole next argument\n                   p++;\n                   args[count].value=Gstrdup(_argv[p]);\n                   }\n                  else {\n                   errarg=p;\n                   err_valmissing=true;\n                   return errarg;\n                   }\n                }\n               else { //value immediately follows the dash-option\n                args[count].value=Gstrdup(_argv[p]+cpos+1);\n                }\n            count++;\n            }\n          } //was validShortOpt\n         else { //option not found in format definition!\n           errarg=p;\n           return errarg;\n           }\n        }\n     } //-single-dash\n   else {//not a single-dash argument\n     char* ap=_argv[p];\n     bool is_longopt=false;\n     if (*ap=='-' && ap[1]=='-') { //double-dash option\n        is_longopt=true;\n        ap+=2;\n        }\n     char* e=strchr(ap+1,'=');\n     while (e!=NULL && *(e-1)=='\\\\') e=strchr(e,'=');\n     if (e==NULL && is_longopt) {\n        e=ap;\n        while (*e!=0 && *e!=' ') e++;\n        //e will be on eos or next space\n        }\n     if (e!=NULL && e>ap) {\n       //this must be a long option\n       //e is on eos, space or '='\n       if ((f=validLongOpt(ap,e-1))>=0) {\n            GREALLOC(args, (count+1)*sizeof(argdata));\n            args[count].opt=Gstrdup(ap,e-1);\n            args[count].fmti=f;\n            if (fmt[f].req_value) {\n               if (*e==0) {\n                   //value is the next argument\n                   if (p+1<_argc && _argv[p+1][0]!=0) {\n                      p++;\n                      args[count].value=Gstrdup(_argv[p]);\n                      }\n                    else {\n                      errarg=p;\n                      err_valmissing=true;\n                      return errarg;\n                      }\n                   }\n                else { //value is in the same argument\n                   //while (*e!=0 && (*e==' ' || *e=='=')) e++;\n                   if (*e=='=') e++;\n                   if (*e==0) {\n                      errarg=p;\n                      err_valmissing=true;\n                      return errarg;\n                      }\n                   args[count].value=Gstrdup(e);\n                   }\n               } //value required\n              else { //no value expected\n               GCALLOC(args[count].value,1); //do not return NULL\n               }\n            count++;\n            }\n          else { //error - this long argument not recognized\n           errarg=p;\n           return errarg;\n           }\n        }\n      else { //just a plain non-option argument\n       if (e==ap) { //i.e. just \"--\"\n          errarg=p;\n          return errarg;\n          }\n       GREALLOC(args, (count+1)*sizeof(argdata));\n       args[count].opt=NULL; //it's not an option\n       args[count].value=Gstrdup(_argv[p]);\n       args[count].fmti=-1;\n       count++;\n       nonOptCount++;\n       }\n     }\n   p++;//check next arg string\n   } //while arguments\n return errarg;\n}\n\nvoid GArgs::printError(FILE* fout, const char* usage, bool exitProgram) {\n if (errarg==0) return;\n if (usage) fprintf(fout, \"%s\\n\", usage);\n if (err_valmissing) \n     fprintf(fout, \"Error: value required for option '%s'\\n\", _argv[errarg]);\n    else \n     fprintf(fout, \"Error: invalid argument '%s'\\n\", _argv[errarg]);\n if (exitProgram)\n     exit(1);\n}\n\nvoid GArgs::printError(const char* usage, bool exitProgram) {\n printError(stderr, usage, exitProgram);\n}\n\nvoid GArgs::printCmdLine(FILE* fout) {\n if (_argv==NULL) return;\n for (int i=0;i<_argc;i++) {\n   fprintf(fout, \"%s%c\", _argv[i], (i==_argc-1)?'\\n':' ');\n   }\n}\n\nGArgs::GArgs(int argc, char* const argv[], const GArgsDef fmtrecs[], bool nodigitopts) {\n fmtcount=0;\n count=0;\n nonOptCount=0;\n nonOptPos=0;\n optPos=0;\n errarg=0;\n err_valmissing=false;\n args=NULL;\n fmt=NULL;\n _argc=argc;\n _argv=argv;\n if (fmtrecs==NULL) return;\n \n const GArgsDef* frec=fmtrecs;\n while ((frec->longopt || frec->opt) && fmtcount<255) {\n     fmtcount++;\n     frec=&(fmtrecs[fmtcount]);\n     }\n GCALLOC(fmt, fmtcount*sizeof(fmtdef));\n for (int i=0;i<fmtcount;i++) {\n   fmt[i].longopt=Gstrdup(fmtrecs[i].longopt); //do we need to use Gstrdup here?\n   fmt[i].opt=fmtrecs[i].opt;\n   fmt[i].req_value=fmtrecs[i].req_value;\n   fmt[i].code=fmtrecs[i].code;\n   }\n parseArgs(nodigitopts);\n}\n\n\nGArgs::~GArgs() {\n int i;\n for (i=0; i<fmtcount; i++)\n    GFREE(fmt[i].longopt);\n GFREE(fmt);\n for (i=0; i<count; i++) {\n  GFREE(args[i].opt);\n  GFREE(args[i].value);\n  }\n GFREE(args);\n}\n\nint GArgs::validShortOpt(char o) {\n for (int i=0; i<fmtcount; i++) \n  if (fmt[i].opt==o) return i;\n return -1; \n}\n\nint GArgs::validLongOpt(char* o, char* to) {\n char* pstr=Gstrdup(o,to);\n for (int i=0; i<fmtcount; i++) {\n  if (fmt[i].longopt && strcmp(fmt[i].longopt, pstr)==0) {\n       GFREE(pstr);\n       return i;\n       }\n  }\n GFREE(pstr); \n return -1;\n}\n\nint GArgs::validOpt(int code) {\n for (int i=0; i<fmtcount; i++) \n   if (fmt[i].code==code) return i;\n return -1;\n}\n\n\nint GArgs::isError() { // returns the offending argv position or 0 if no error\n return errarg;\n }\n\nchar* GArgs::getOpt(const char* o) { /* retrieve the value for option o\n                   returns \n                       NULL    if option not given at all\n                     !=NULL    if boolean option was given\n                     opt.value if value option was given\n                     */\n for (int i=0; i<count; i++) \n  if (args[i].opt!=NULL && strcmp(args[i].opt, o)==0) \n           return args[i].value;\n return NULL;\n}\n\nchar* GArgs::getOpt(const char o) {\n for (int i=0; i<count; i++) \n  if (args[i].opt!=NULL && args[i].opt[0]==o && args[i].opt[1]=='\\0') \n      return args[i].value;\n return NULL;\n}\n\nchar* GArgs::getOpt(int c) {\n for (int i=0; i<count; i++) \n  if (args[i].fmti>=0 && fmt[args[i].fmti].code==c)\n      return args[i].value;\n return NULL;\n}\n\nchar* GArgs::getOptName(int c) {\n for (int i=0; i<count; i++) \n  if (args[i].fmti>=0 && fmt[args[i].fmti].code==c)\n      return args[i].opt;\n return NULL;\n}\n\n\nint GArgs::startNonOpt(){ //reset iteration through non-option arguments\n   //returns the number of non-option arguments\nnonOptPos=0;\nreturn nonOptCount;   \n}\n   \n   \nchar* GArgs::nextNonOpt() { //get the next non-dashed argument\n               //or NULL if no more \nfor (int i=nonOptPos;i<count;i++)\n if (args[i].opt==NULL) {\n      nonOptPos=i+1;\n      return args[i].value;\n      }\nreturn NULL;\n}\n\nint GArgs::startOpt(){ //reset iteration through option arguments\n   //returns the number of option arguments\noptPos=0;\nreturn count-nonOptCount;\n}\n   \n   \nchar* GArgs::nextOpt() { //get the next non-dashed argument\n               //or NULL if no more \nfor (int i=optPos;i<count;i++)\n if (args[i].opt!=NULL) {\n      optPos=i+1;\n      return args[i].opt;\n      }\nreturn NULL;\n}\n\nint GArgs::nextCode() { //get the next non-dashed argument\n               //or NULL if no more \nfor (int i=optPos;i<count;i++)\n if (args[i].opt!=NULL && args[i].fmti>=0) {\n      optPos=i+1;\n      return fmt[args[i].fmti].code;\n      }\nreturn 0; //must make sure that codes are > 0 for this to work properly\n}\n\n"
  },
  {
    "path": "src/GArgs.h",
    "content": "/*\nGArgs is a quick'n'dirty object oriented replacement for the standard \n   getopts library available on many unix platforms;\n   it accepts the regular single letter, single-dash style options \n     -<letter>[ ][<value>] \n   but also attr=value style options:\n     <optname>=<value>\n     or\n     --<optname>[=]<value>\n*/\n\n#ifndef G_ARGS_DEFINED\n#define G_ARGS_DEFINED\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n\nstruct GArgsDef {\n  const char* longopt;\n  char opt; //equivalent one-char option, if any\n  bool req_value; //true if the string that follows must be a value\n  int code; //an enum code to be associated with this option\n};\n\nclass GArgs {\n   //structure for parsing arguments format definition\n   struct fmtdef {\n     char* longopt;\n     char opt; //equivalent one-char option, if any\n     bool req_value; //true if the string that follows must be a value\n     int code; //an enum code to be associated with this option\n     };\n   int fmtcount;\n   fmtdef* fmt; //this will store format definition after parsing it\n   struct argdata {\n     char*  opt; // this is NULL for non-dashed arguments\n                 // a single character for single dash style arguments\n                //  a string for ARG=VALUE or --long_option style arguments\n     char* value; // is NULL for switches (dashed flags)\n     int fmti; //index in fmt table\n     //int code; // if GArgsDef[] constructor was used, for getOpt\n     };\n   int _argc;            \n   char* const *_argv; //the original main() values\n   argdata* args; //arguments table after parsing it\n   int count; //total count of elements in 'args' array\n   int nonOptCount; //count of non-dashed, non= arguments\n   int nonOptPos; //current position for nonOpt arguments iterator\n   int optPos; //current position for options iterator\n   int errarg; //argv error position after parsing\n   bool err_valmissing; //if the error is strictly about missing value for errarg option\n   int parseArgs(bool nodigitopts=false);\n   //parsing helper functions\n   int validOpt(int c);  \n   int validShortOpt(char o);  \n   int validLongOpt(char* o, char* to);\n public:\n \n   GArgs(int argc, char* const argv[], const char* format, bool nodigitopts=false);\n   /* format can be:\n       <string>{;|=} e.g. disable-test;PID=S= for --disable-test PID=50 (or --PID 50) S=3.5 etc.\n       <letter>[:]  e.g. p:hT  for -p testing (or -ptesting) -h -T\n   This means that the long options, if present, should be given at the beginning\n   of the format string, before the single-dash, single-char options\n   */\n   GArgs(int argc, char* const argv[], const GArgsDef fmtrecs[], bool nodigitopts=false);\n   \n   ~GArgs();\n   int isError(); // returns the offending argv position or 0 if no error\n   int getCount() { return count; } //total number of arguments given\n   int getFmtCount() { return fmtcount; } //total number of option definitions\n   int getNonOptCount() { return nonOptCount; } //total number of non-option arguments\n   char* getOpt(const char* o); /* retrieve the value for option o\n                   returns \n                       NULL    if option not given at all\n                     !=NULL    if boolean option was given\n                     opt's value if value option was given\n                     */\n   char* getOpt(const char o);\n   char* getOpt(int c); //retrieve value by enum code\n   char* getOptName(int c); //retrieve name of by enum code\n   int startOpt(); //init iteration through option arguments\n       // returns number of option args\n       \n   char* nextOpt(); //get next option argument's string\n   int nextCode(); //get next option argument's code\n\n   int startNonOpt(void); //init iteration through non-option arguments\n             // returns the number of non-option arguments\n   void printError(FILE* fout, const char* usage=NULL,\n                      bool exitProgram=false);\n   void printError(const char* usage=NULL, bool exitProgram=false);\n   void printCmdLine(FILE* fout);\n   char* nextNonOpt(); //get the next non-option argument\n};\n\n#endif\n"
  },
  {
    "path": "src/GBase.cpp",
    "content": "#include \"GBase.h\"\n#include <stdarg.h>\n#include <ctype.h>\n\n#ifndef S_ISDIR\n#define S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)\n#endif\n\n#ifndef S_ISREG\n#define S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)\n#endif\n\n/*\n#ifdef _DEFINE_WIN32_FSEEKO\n int fseeko(FILE *stream, off_t offset, int whence) {\n   \n   }\n#endif\n\n#ifdef _DEFINE_WIN32_FTELLO\n off_t ftello(FILE *stream) {\n  \n  }\n#endif\n*/\n\n/*\nint saprintf(char **retp, const char *fmt, ...) {\n  va_list argp;\n  int len;\n  char *buf;\n\n  va_start(argp, fmt);\n  len = vsnprintf(NULL, 0, fmt, argp);\n  va_end(argp);\n  GMALLOC(buf, (len + 1));\n  if(buf == NULL)\n    {\n    *retp = NULL;\n    return -1;\n    }\n\n  va_start(argp, fmt);\n  vsnprintf(buf, len+1, fmt, argp);\n  va_end(argp);\n\n  *retp = buf;\n  return len;\n}\n*/\n\n//************************* Debug helpers **************************\n// Assert failed routine\nvoid GAssert(const char* expression, const char* filename, unsigned int lineno){\n  char msg[4096];\n  sprintf(msg,\"%s(%d): ASSERT(%s) failed.\\n\",filename,lineno,expression);\n  fprintf(stderr,\"%s\",msg);\n  #ifdef DEBUG\n  // modify here if you [don't] want a core dump\n    abort();\n  #endif\n  exit(1);\n}\n\n// Error routine (prints error message and exits!)\nvoid GError(const char* format,...){\n  #ifdef __WIN32__\n    char msg[4096];\n    va_list arguments;\n    va_start(arguments,format);\n    _vsnprintf(msg, 4095, format, arguments);\n    vfprintf(stderr, format, arguments); // if a console is available\n    msg[4095]=0;\n    va_end(arguments);\n    OutputDebugString(msg);\n    MessageBox(NULL,msg,NULL,MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);\n  #else\n    va_list arguments;\n    va_start(arguments,format);\n    vfprintf(stderr,format,arguments);\n    va_end(arguments);\n    #ifdef DEBUG\n     // modify here if you [don't] want a core dump\n     abort();\n    #endif\n  #endif\n    exit(1);\n  }\n  \n// Warning routine (just print message without exiting)\nvoid GMessage(const char* format,...){\n  #ifdef __WIN32__\n    char msg[4096];\n    va_list arguments;\n    va_start(arguments,format);\n    vfprintf(stderr, format , arguments); // if a console is available\n    _vsnprintf(msg, 4095, format, arguments);\n    msg[4095]=0;\n    va_end(arguments);\n    OutputDebugString(msg);\n  #else\n    va_list arguments;\n    va_start(arguments,format);\n    vfprintf(stderr,format,arguments);\n    va_end(arguments);\n  #endif\n  }\n\n/*************** Memory management routines *****************/\n// Allocate memory\nbool GMalloc(pointer* ptr,unsigned long size){\n  //GASSERT(ptr);\n  if (size!=0) *ptr=malloc(size);\n  return *ptr!=NULL;\n  }\n\n// Allocate cleaned memory (0 filled)\nbool GCalloc(pointer* ptr,unsigned long size){\n  GASSERT(ptr);\n  *ptr=calloc(size,1);\n  return *ptr!=NULL;\n  }\n\n// Resize memory\nbool GRealloc(pointer* ptr,unsigned long size){\n  //GASSERT(ptr);\n  if (size==0) {\n    GFree(ptr);\n    return true;\n    }\n  if (*ptr==NULL) {//simple malloc\n   void *p=malloc(size);\n   if (p != NULL) {\n     *ptr=p;\n     return true;\n     }\n    else return false;\n   }//malloc\n  else {//realloc\n   void *p=realloc(*ptr,size);\n   if (p) {\n       *ptr=p;\n       return true;\n       }\n   return false;\n   }\n }\n// Free memory, resets ptr to NULL afterward\nvoid GFree(pointer* ptr){\n  GASSERT(ptr);\n  if (*ptr) free(*ptr);\n  *ptr=NULL;\n  }\n\nchar* Gstrdup(const char* str) {\n  if (str==NULL) return NULL;\n  char *copy=NULL;\n  GMALLOC(copy, strlen(str)+1);\n  strcpy(copy,str);\n  return copy;\n  }\n\nchar* newEmptyStr() {\n  char* zs=NULL;\n  GMALLOC(zs,1);\n  zs[0]=0;\n  return zs;\n}\n\nchar* Gstrdup(const char* sfrom, const char* sto) {\n  if (sfrom==NULL || sto==NULL) return NULL;\n  char *copy=NULL;\n  if (sfrom[0]==0 || sto<sfrom) return newEmptyStr();\n  GMALLOC(copy, sto-sfrom+2);\n  strncpy(copy, sfrom, sto-sfrom+1);\n  copy[sto-sfrom+1]=0;\n  return copy;\n  }\n\nint Gstrcmp(const char* a, const char* b, int n) {\n if (a==NULL || b==NULL) {\n   return a==NULL ? -1 : 1;\n   }\n else {\n   if (n<0) return strcmp(a,b);\n       else return strncmp(a,b,n);\n }\n\n}\n\nint G_mkdir(const char* path, int perms=0775) {\n #ifdef __WIN32__\n     return _mkdir(path);\n #else\n //#if _POSIX_C_SOURCE\n //    return ::mkdir(path);\n //#else\n     return mkdir(path, perms); // not sure if this works on mac\n //#endif\n #endif\n}\n\n\nint Gmkdir(const char *path, bool recursive, int perms) {\n\tif (path==NULL || path[0]==0) return -1;\n\tif (!recursive) return G_mkdir(path, perms);\n\tint plen=strlen(path);\n\tchar* gpath=NULL;\n\t//make sure gpath ends with /\n\tif (path[plen-1]=='/') {\n\t\tgpath=Gstrdup(path);\n\t}\n\telse {\n\t\tGMALLOC(gpath, plen+2);\n\t\tstrcpy(gpath,path);\n\t\tgpath[plen]='/';\n\t\tgpath[plen+1]=0;\n\t}\n\tchar* ss=gpath;\n\tchar* psep = NULL;\n\twhile (*ss!=0 && (psep=strchr(ss, '/'))!=NULL)  {\n\t\t*psep=0; //now gpath is the path up to this /\n\t\tss=psep; ++ss; //ss repositioned just after the /\n\t\t// create current level\n\t\tif (fileExists(gpath)!=1 && G_mkdir(gpath, perms)!=0) {\n\t\t\tGFREE(gpath);\n\t\t\treturn -1;\n\t\t}\n\t\t*psep='/';\n\t}\n\tGFREE(gpath);\n\treturn 0;\n}\n\nbool GstrEq(const char* a, const char* b) {\n\t if (a==NULL || b==NULL) return false;\n\t register int i=0;\n\t while (a[i]==b[i]) {\n\t\t if (a[i]==0) return true;\n\t\t ++i;\n\t }\n\t return false;\n}\n\nbool GstriEq(const char* a, const char* b) {\n\t if (a==NULL || b==NULL) return false;\n\t register int i=0;\n\t while (tolower((unsigned char)a[i])==tolower((unsigned char)b[i])) {\n\t\t if (a[i]==0) return true;\n\t }\n\t return false;\n}\n\nint Gstricmp(const char* a, const char* b, int n) {\n if (a==NULL || b==NULL) return a==NULL ? -1 : 1;\n register int ua, ub;\n if (n<0) {\n   while ((*a!=0) && (*b!=0)) {\n    ua=tolower((unsigned char)*a);\n    ub=tolower((unsigned char)*b);\n    a++;b++;\n    if (ua!=ub) return ua < ub ? -1 : 1;\n    }\n    return (*a == 0) ? ( (*b == 0) ? 0 : -1 ) : 1 ;\n  }\n else {\n   while (n && (*a!=0) && (*b!=0)) {\n    ua=tolower((unsigned char)*a);\n    ub=tolower((unsigned char)*b);\n    a++;b++;n--;\n    if (ua!=ub) return ua < ub ? -1 : 1;\n    }\n    //return (*a == 0) ? ( (*b == 0) ? 0 : -1 ) : 1 ;\n   if (n==0) return 0;\n   else { return (*a == 0) ? ( (*b == 0) ? 0 : -1 ) : 1 ; }\n  }\n}\n\nint strsplit(char* str, char** fields, int maxfields, const char* delim) {\n //splits by placing 0 where delim chars are found, setting fields[] to the beginning\n //of each field (stopping after maxfields); returns number of fields parsed\n int tidx=0;\n bool afterdelim=true;\n int i=0;\n while (str[i]!=0 && tidx<maxfields) {\n    if (afterdelim) {\n        fields[tidx]=str+i;\n        tidx++;\n        }\n    afterdelim=false;\n    if (chrInStr(str[i],(char*)delim)) {\n        str[i]=0;\n        i++;\n        while (str[i]!=0 && chrInStr(str[i], (char*)delim)) i++;\n        afterdelim=true;\n        continue;\n        }\n    i++;\n    }\n return tidx;\n}\n\nint strsplit(char* str, char** fields, int maxfields, const char delim) {\n  //splits by placing 0 where delim is found, setting fields[] to the beginning\n  //of each field (stopping after maxfields); returns number of fields parsed\n  int tidx=0;\n  bool afterdelim=true;\n  int i=0;\n  while (str[i]!=0 && tidx<maxfields) {\n     if (afterdelim) {\n         fields[tidx]=str+i;\n         tidx++;\n         }\n     afterdelim=false;\n     if (str[i]==delim) {\n         str[i]=0;\n         i++;\n         while (str[i]!=0 && str[i]==delim) i++;\n         afterdelim=true;\n         continue;\n         }\n     i++;\n     }\n  return tidx;\n}\n\nint strsplit(char* str, char** fields, int maxfields) {\n  //splits by placing 0 where delim is found, setting fields[] to the beginning\n  //of each field (stopping after maxfields); returns number of fields parsed\n  int tidx=0;\n  bool afterdelim=true;\n  int i=0;\n  while (str[i]!=0 && tidx<maxfields) {\n     if (afterdelim) {\n         fields[tidx]=str+i;\n         tidx++;\n         }\n     afterdelim=false;\n     if (str[i]==' ' || str[i]=='\\t') {\n         str[i]=0;\n         i++;\n         while (str[i]!=0 && (str[i]=='\\t' || str[i]==' ')) i++;\n         afterdelim=true;\n         continue;\n         }\n     i++;\n     }\n  return tidx;\n}\n\n\nchar* Gsubstr(const char* str, char* from, char* to) {\n //extract (and allocate) a substring, including boundaries (from/to)\n if (str==NULL || from==NULL) return NULL;\n if (from[0]==0 || str[0]==0) return newEmptyStr();\n if (from<str) return NULL;\n if (to==NULL) {\n    to=from;\n    while (to[1]) to++;\n    }\n if (to<from) return newEmptyStr();\n int newlen=to-from+1;\n char* subs=NULL;\n GMALLOC(subs, newlen);\n memcpy(subs, str, newlen-1);\n subs[newlen]='\\0';\n return subs;\n }\n\nchar* replaceStr(char* &str, char* newvalue) {\n if (str!=NULL) GFREE(str);\n if (newvalue==NULL) { return NULL; }\n GMALLOC(str, strlen(newvalue)+1);\n strcpy(str,newvalue);\n return str;\n }\n\nvoid* Gmemscan(void *mem, unsigned int len,\n                   void *part, unsigned int partlen) {\nchar* p;\nunsigned int restlen=len-partlen+1;\nvoid* oldp=mem;\nwhile ( (p=(char*)memchr(oldp, ((char*)part)[0], restlen))!=NULL) {\n  //located first char, try to match the rest:\n  p++;\n  if (memcmp(p, &((char*)part)[1], partlen-1)==0) return p-1;\n  //no string match, prepare next iteration\n  restlen-=(p-(char*)oldp);\n  oldp=p;\n  }//while\nreturn NULL;\n}\n\n//rindex function is missing on some platforms ?\nchar* rstrchr(char* str, char ch) {  /* returns a pointer to the rightmost\n  occurence of ch in str  */\n char *p;\n if (str==NULL) return NULL;\n p=str+strlen(str)-1;\n while (p>=str) {\n    if (*p==ch) return p;\n    p--;\n    }\n return NULL;\n }\n\n\n/* DOS/UNIX safer fgets : reads a text line from a (binary) file and\n  update the file position accordingly and the buffer capacity accordingly.\n  The given buf is resized to read the entire line in memory\n    -- even when it's abnormally long\n  */\nchar* fgetline(char* & buf, int& buf_cap, FILE *stream, off_t* f_pos, int* linelen) {\n  //reads a char at a time until \\n and/or \\r are encountered\n  int i=0;\n  int c=0;\n  off_t fpos=(f_pos!=NULL) ? *f_pos : 0;\n  while ((c=getc(stream))!=EOF) {\n    if (i>=buf_cap-1) {\n       buf_cap+=1024;\n       GREALLOC(buf, buf_cap);\n       }\n    if (c=='\\n' || c=='\\r') {\n       if (c=='\\r') {\n         if ((c=getc(stream))!='\\n') ungetc(c,stream);\n                                else fpos++;\n         }\n       fpos++;\n       break;\n       }\n    fpos++;\n    buf[i]=(char)c;\n    i++;\n    } //while i<buf_cap-1\n  if (linelen!=NULL) *linelen=i;\n  if (f_pos!=NULL) *f_pos=fpos;\n  if (c==EOF && i==0) return NULL;\n  buf[i]='\\0';\n  return buf;\n  }\n\nchar* GLineReader::getLine(FILE* stream, off_t& f_pos) {\n   if (pushed) { pushed=false; return buf; }\n   //reads a char at a time until \\n and/or \\r are encountered\n   len=0;\n   int c=0;\n   while ((c=getc(stream))!=EOF) {\n     if (len>=allocated-1) {\n        allocated+=1024;\n        GREALLOC(buf, allocated);\n     }\n     if (c=='\\n' || c=='\\r') {\n       buf[len]='\\0';\n       if (c=='\\r') { //DOS file -- special case\n         if ((c=getc(stream))!='\\n') ungetc(c,stream);\n                                else f_pos++;\n         }\n       f_pos++;\n       lcount++;\n       return buf;\n       }\n     f_pos++;\n     buf[len]=(char)c;\n     len++;\n     } //while i<buf_cap-1\n   if (c==EOF) {\n     isEOF=true;\n     if (len==0) return NULL;\n     }\n   buf[len]='\\0';\n   lcount++;\n   return buf;\n}\n\n\n//strchr but with a set of chars instead of only one\nchar* strchrs(const char* s, const char* chrs) {\n  if (s==NULL || chrs==NULL || *chrs=='\\0' || *s=='\\0')\n         return NULL;\n  unsigned int l=strlen(s);\n  unsigned int r=strcspn(s, chrs);\n  if (r==l) return NULL;\n  return ((char*)s+r);\n}\n\nchar* upCase(const char* str) {\n if (str==NULL) return NULL;\n int len=strlen(str);\n char* upstr=NULL;\n GMALLOC(upstr, len+1);\n upstr[len]='\\0';\n for (int i=0;i<len;i++) upstr[i]=toupper(str[i]);\n return upstr;\n }\n\nchar* loCase(const char* str) {\n if (str==NULL) return NULL;\n int len=strlen(str);\n char* lostr=NULL;\n GMALLOC(lostr, len+1);\n lostr[len]='\\0';\n for (int i=0;i<len;i++) lostr[i]=tolower(str[i]);\n return lostr;\n }\n\nchar* strlower(char * str) {//changes string in place\n  if (str==NULL) return NULL;\n  int i=0;\n  while (str[i]!=0) { str[i]=tolower(str[i]); i++; }\n  return str;\n}\n\nchar* strupper(char * str) {//changes string in place\n  if (str==NULL) return NULL;\n  int i=0;\n  while (str[i]!=0) { str[i]=toupper(str[i]); i++; }\n  return str;\n}\n\n\n\n//test if a char is in a given string (set)\nbool chrInStr(char c, const char* str) {\n if (str==NULL || *str=='\\0') return false;\n for (const char* p=str; (*p)!='\\0'; p++) {\n   if ((*p)==c) return true;\n   }\n return false;\n }\n\n\n\nchar* rstrfind(const char* str, const char* substr) {\n/* like rindex() for a string */\n int l,i;\n if (str==NULL || *str=='\\0') return NULL;\n if (substr==NULL || *substr=='\\0') return NULL;\n l=strlen(substr);\n char* p=(char*)str+strlen(str)-l;\n   //rightmost position that could match\n\n while (p>=str) {\n    for (i=0; i<l && *(p+i) == *(substr+i); i++) ;\n    if (i==l) return p; //found!\n    p--;\n    }\n return NULL;\n}\n\n\nchar* strifind(const char* str,  const char* substr) {\n // case insensitive version of strstr -- finding a string within another\n  int l,i;\n  if (str==NULL || *str==0) return NULL;\n  if (substr==NULL || *substr==0) return NULL;\n  l=strlen(substr);\n  char* smax=(char*)str+strlen(str)-l;\n  //rightmost position that could match\n  char* p=(char*)str;\n  while (p<=smax) {\n     for (i=0; i<l && tolower(*(p+i))==tolower(*(substr+i)); i++) ;\n     if (i==l) return p;\n     p++;\n     }\n  return NULL;\n}\n\n\n\n// tests if string s has the given prefix\nbool startsWith(const char* s, const char* prefix) {\n if (prefix==NULL || s==NULL) return false;\n int i=0;\n while (prefix[i]!='\\0' && prefix[i]==s[i]) i++;\n return (prefix[i]=='\\0');\n }\n\nbool startsiWith(const char* s, const char* prefix) {\n if (prefix==NULL || s==NULL) return false;\n int i=0;\n while (prefix[i]!='\\0' && tolower(prefix[i])==tolower(s[i])) i++;\n return (prefix[i]=='\\0');\n }\n\n\n// tests if string s ends with given suffix\nbool endsWith(const char* s, const char* suffix) {\n if (suffix==NULL || s==NULL) return false;\n if (suffix[0]==0) return true; //special case: empty suffix\n int j=strlen(suffix)-1;\n int i=strlen(s)-1;\n if (i<j) return false;\n while (j>=0 && s[i]==suffix[j]) { i--; j--; }\n return (j==-1);\n }\n\n\nchar* reverseChars(char* str, int slen) {\n  if (slen==0) slen=strlen(str);\n  int l=0;\n  int r=slen-1;\n  char c;\n  while (l<r) {\n     c=str[l];str[l]=str[r];\n     str[r]=c;\n     l++;r--;\n     }\n  return str;\n}\n\n\nchar* rstrstr(const char* rstart, const char *lend, const char* substr) {  /*like strstr, but starts searching\n from right end, going up to lend and returns a pointer to the last (right)\n matching character in str */\n char *p;\n int l,i;\n l=strlen(substr);\n p=(char*)rstart-l+1;\n while (p>=lend) {\n    for (i=0;i<l;i++) if (*(p+i) != *(substr+i)) break;\n    if (i==l) return p+l-1;\n    p--;\n    }\n return NULL;\n }\n\n\n//hash function used for strings in GHash\nint strhash(const char* str){\n  register int h=0;\n  register int g;\n  while (*str) {\n    h=(h<<4)+*str++;\n    g=h&0xF0000000;\n    if(g) h^=g>>24;\n    h&=0x0fffffff;\n    }\n  GASSERT(h<=0x0fffffff);\n  return h;\n  }\n\n// removes the last part (file or directory name) of a full path\n// this is a destructive operation for the given string!!!\n// the trailing '/' is guaranteed to be there\nvoid delFileName(char* filepath) {\n char *p, *sep;\n if (filepath==NULL) return;\n for (p=filepath, sep=filepath;*p!='\\0';p++)\n     if (*p=='/' || *p=='\\\\') sep=p+1;\n *sep='\\0'; // truncate filepath\n}\n\n// returns a pointer to the last file or directory name in a full path\nconst char* getFileName(const char* filepath) {\n const char *p, *sep;\n if (filepath==NULL) return NULL;\n for (p=filepath, sep=filepath;*p!='\\0';p++)\n     if (*p=='/' || *p=='\\\\') sep=p+1;\n return sep;\n}\n\n// returns a pointer to the file \"extension\" part in a filename\nconst char* getFileExt(const char* filepath) {\n const char *p, *dp, *sep;\n if (filepath==NULL) return NULL;\n for (p=filepath, dp=filepath, sep=filepath;*p!='\\0';p++) {\n     if (*p=='.') dp=p+1;\n       else if (*p=='/' || *p=='\\\\') \n                  sep=p+1;\n     }\n return (dp>sep) ? dp : NULL ;\n}\n\nint fileExists(const char* fname) {\n  struct stat stFileInfo;\n  int r=0;\n  // Attempt to get the file attributes\n  int fs = stat(fname,&stFileInfo);\n  if (fs == 0) {\n      r=3;\n      // We were able to get the file attributes\n      // so the file obviously exists.\n      if (S_ISREG (stFileInfo.st_mode)) {\n         r=2;\n         }\n      if (S_ISDIR (stFileInfo.st_mode)) {\n          r=1;\n          }\n      }\n  return r;\n}\n\n/*bool fileExists(const char* filepath) {\n  if (filepath==NULL) return false;\n  FILE* ft=fopen(filepath, \"rb\");\n  if (ft==NULL) return false;\n  fclose(ft);\n  return true;\n}\n*/\nint64 fileSize(const char* fpath) {\n  struct stat results;\n  if (stat(fpath, &results) == 0)\n      // The size of the file in bytes is in\n      return (int64)results.st_size;\n  else\n      // An error occurred\n    //GMessage(\"Error at stat(%s)!\\n\", fpath);\n    return 0;\n}\n\nbool parseNumber(char* &p, double& v) {\n //skip any spaces..\n while (*p==' ' || *p=='\\t') p++;\n char* start=p;\n /*if (*p=='-') p++;\n       else if (*p=='+') { p++;start++; }*/\n\n /* while ((*p>='1' && *p<='9') || *p=='0' ||\n          *p=='.' || *p=='-' || tolower(*p)=='e') p++; */\n int numlen=strspn(start, \"0123456789eE.-+\");\n p=start+numlen;\n //now p is on a non-digit;\n if (*start=='-' && p==start+1) return false;\n char saved=*p;\n *p='\\0';\n char* endptr=p;\n v=strtod(start,&endptr);\n *p=saved;\n if (endptr!=p) return false;\n return true;\n}\n\n\nbool parseDouble(char* &p, double& v) {\n return parseNumber(p,v);\n}\n\nbool parseInt(char* &p, int& i) {\n while (*p==' ' || *p=='\\t') p++;\n char* start=p;\n if (*p=='-') p++;\n       else if (*p=='+') { p++;start++; }\n while ((*p>='1' && *p<='9') || *p=='0') p++;\n //now p is on a non-digit;\n if (*start=='-' && p==start+1) return false;\n char saved=*p;\n *p='\\0';\n char* endptr=p;\n long l=strtol(start,&endptr,10);\n i=(int)l;\n *p=saved;\n if (endptr!=p || i!=l) return false;\n return true;\n}\n\nbool parseUInt(char* &p, uint& i) {\n while (*p==' ' || *p=='\\t') p++;\n char* start=p;\n if (*p=='-') return false;\n       else if (*p=='+') { p++;start++; }\n while ((*p>='1' && *p<='9') || *p=='0') p++;\n //now p is on a non-digit;\n if (*start=='-' && p==start+1) return false;\n char saved=*p;\n *p='\\0';\n char* endptr=p;\n unsigned long l=strtoul(start,&endptr,10);\n i=(uint) l;\n *p=saved;\n if (endptr!=p || i!=l) return false;\n return true;\n}\n\nbool parseHex(char* &p, uint& i) {\n //skip initial spaces/prefix\n while (*p==' ' || *p=='\\t' || *p=='0' || *p=='x') p++;\n char* start=p;\n if (*p=='-') return false;\n       else if (*p=='+') { p++;start++; }\n while (isxdigit(*p)) p++;\n //now p is on a non-hexdigit;\n if (p==start+1) return false;\n char saved=*p;\n *p='\\0';\n char* endptr=p;\n unsigned long l=strtoul(start,&endptr,16);\n i=(uint) l;\n *p=saved;\n if (endptr!=p || i!=l) return false;\n return true;\n}\n\n//write a formatted fasta record, fasta formatted\nvoid writeFasta(FILE *fw, const char* seqid, const char* descr,\n        const char* seq, int linelen, int seqlen) {\n  fflush(fw);\n  // write header line only if given!\n  if (seqid!=NULL) {\n    if (descr==NULL || descr[0]==0)\n             fprintf(fw,\">%s\\n\",seqid);\n        else fprintf(fw,\">%s %s\\n\",seqid, descr);\n    }\n  fflush(fw);\n  if (seq==NULL || *seq==0) return; //nothing to print\n  if (linelen==0) { //unlimited line length: write the whole sequence on a line\n     if (seqlen>0)\n             fwrite((const void*)seq, 1, seqlen,fw);\n        else fprintf(fw,\"%s\",seq);\n     fprintf(fw,\"\\n\");\n     fflush(fw);\n     return;\n     }\n  int ilen=0;\n  if (seqlen>0) { //seq length given, so we know when to stop\n    for (int i=0; i < seqlen; i++, ilen++) {\n            if (ilen == linelen) {\n                 fputc('\\n', fw);\n                 ilen = 0;\n                 }\n            fputc(seq[i], fw);\n            }\n    fputc('\\n', fw);\n    }\n  else { //seq length not given, stop when 0 encountered\n    for (int i=0; seq[i]!=0; i++, ilen++) {\n            if (ilen == linelen) {\n                 fputc('\\n', fw);\n                 ilen = 0;\n                 }\n            fputc(seq[i], fw);\n            } //for\n    fputc('\\n', fw);\n    }\n  fflush(fw);\n }\n\nchar* commaprintnum(uint64 n) {\n  int comma = ',';\n  char retbuf[48];\n  char *p = &retbuf[sizeof(retbuf)-1];\n  int i = 0;\n  *p = '\\0';\n  do {\n    if(i%3 == 0 && i != 0)\n        *--p = comma;\n    *--p = '0' + n % 10;\n    n /= 10;\n    i++;\n  } while(n != 0);\n  return Gstrdup(p);\n}\n"
  },
  {
    "path": "src/GBase.h",
    "content": "#ifndef G_BASE_DEFINED\n#define G_BASE_DEFINED\n#ifndef _POSIX_SOURCE\n//mostly for MinGW\n#define _POSIX_SOURCE\n#endif\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n#include <string.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <math.h>\n#include <limits.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <stdint.h>\n\n#if defined __WIN32__ || defined WIN32 || defined _WIN32 || defined _WIN32_\n  #ifndef __WIN32__\n    #define __WIN32__\n  #endif\n  #include <windows.h>\n  #include <direct.h>\n  #include <io.h>\n  #define CHPATHSEP '\\\\'\n  #undef off_t\n  #define off_t int64_t\n  #ifndef popen\n   #define popen _popen\n  #endif\n  #ifndef fseeko\n\t\t#ifdef _fseeki64\n\t\t\t#define fseeko(stream, offset, origin) _fseeki64(stream, offset, origin)\n\t\t#else\n\t\t\t/*\n\t\t\t#define _DEFINE_WIN32_FSEEKO\n\t\t\tint fseeko(FILE *stream, off_t offset, int whence);\n\t\t\t*/\n\t\t\t#define fseeko fseek\n\t\t#endif\n  #endif\n #ifndef ftello\n  #ifdef _ftelli64\n    #define ftello(stream) _ftelli64(stream)\n  #else\n    #define ftello ftell\n  #endif\n #endif\n #else\n  #define CHPATHSEP '/'\n  #include <unistd.h>\n#endif\n\n#ifndef fseeko\n #define fseeko fseek\n#endif\n#ifndef ftello\n #define ftello ftell\n#endif\n\n#ifdef DEBUG\n#undef NDEBUG\n#define _DEBUG 1\n#define _DEBUG_ 1\n#endif\n\ntypedef int32_t int32;\ntypedef uint32_t uint32;\ntypedef int16_t int16;\ntypedef uint16_t uint16;\n\ntypedef unsigned char uchar;\ntypedef unsigned char byte;\n\n#ifndef MAXUINT\n#define MAXUINT ((unsigned int)-1)\n#endif\n\n#ifndef MAXINT\n#define MAXINT INT_MAX\n#endif\n\n#ifndef MAX_UINT\n#define MAX_UINT ((unsigned int)-1)\n#endif\n\n#ifndef MAX_INT\n#define MAX_INT INT_MAX\n#endif\n\ntypedef int64_t int64;\ntypedef uint64_t uint64;\n\n/****************************************************************************/\n\n#ifndef EXIT_FAILURE\n#define EXIT_FAILURE 1\n#endif\n\n#ifndef EXIT_SUCCESS\n#define EXIT_SUCCESS 0\n#endif\n\n/****************************************************************************/\n#define ERR_ALLOC \"Error allocating memory.\\n\"\n\n//-------------------\n\n// Debug helpers\n#ifndef NDEBUG\n #define GASSERT(exp) ((exp)?((void)0):(void)GAssert(#exp,__FILE__,__LINE__))\n #ifdef TRACE\n  #define GTRACE(exp)  (GMessage exp)\n #else\n  #define GTRACE(exp)  ((void)0)\n #endif\n#else\n #define GASSERT(exp) ((void)0)\n #define GTRACE(exp)  ((void)0)\n#endif\n\n#define GERROR(exp) (GError exp)\n/**********************************  Macros  ***********************************/\n// Abolute value\n#define GABS(val) (((val)>=0)?(val):-(val))\n\n// Min and Max\n#define GMAX(a,b) (((a)>(b))?(a):(b))\n#define GMIN(a,b) (((a)>(b))?(b):(a))\n\n// Min of three\n#define GMIN3(x,y,z) ((x)<(y)?GMIN(x,z):GMIN(y,z))\n\n// Max of three\n#define GMAX3(x,y,z) ((x)>(y)?GMAX(x,z):GMAX(y,z))\n\n// Return minimum and maximum of a, b\n#define GMINMAX(lo,hi,a,b) ((a)<(b)?((lo)=(a),(hi)=(b)):((lo)=(b),(hi)=(a)))\n\n// Clamp value x to range [lo..hi]\n#define GCLAMP(lo,x,hi) ((x)<(lo)?(lo):((x)>(hi)?(hi):(x)))\n\ntypedef void* pointer;\ntypedef unsigned int uint;\n\ntypedef int GCompareProc(const pointer item1, const pointer item2);\ntypedef long GFStoreProc(const pointer item1, FILE* fstorage); //for serialization\ntypedef pointer GFLoadProc(FILE* fstorage); //for deserialization\n\ntypedef void GFreeProc(pointer item); //usually just delete,\n      //but may also support structures with embedded dynamic members\n\n#define GMALLOC(ptr,size)  if (!GMalloc((pointer*)(&ptr),size)) \\\n                                     GError(ERR_ALLOC)\n#define GCALLOC(ptr,size)  if (!GCalloc((pointer*)(&ptr),size)) \\\n                                     GError(ERR_ALLOC)\n#define GREALLOC(ptr,size) if (!GRealloc((pointer*)(&ptr),size)) \\\n                                     GError(ERR_ALLOC)\n#define GFREE(ptr)       GFree((pointer*)(&ptr))\n\ninline char* strMin(char *arg1, char *arg2) {\n    return (strcmp(arg1, arg2) < 0)? arg1 : arg2;\n}\n\ninline char* strMax(char *arg1, char *arg2) {\n    return (strcmp(arg2, arg1) < 0)? arg1 : arg2;\n}\n\ninline int iround(double x) {\n   return (int)floor(x + 0.5);\n}\n\nint Gmkdir(const char *path, bool recursive=true, int perms=0775);\n\n\n/****************************************************************************/\n\ninline int Gintcmp(int a, int b) {\n //return (a>b)? 1 : ((a==b)?0:-1);\n  return a-b;\n}\n\nint Gstrcmp(const char* a, const char* b, int n=-1);\n//same as strcmp but doesn't crash on NULL pointers\n\nint Gstricmp(const char* a, const char* b, int n=-1);\nbool GstrEq(const char* a, const char* b);\nbool GstriEq(const char* a, const char* b);\n\n//basic swap template function\ntemplate<class T> void Gswap(T& lhs, T& rhs) {\n //register T tmp=lhs;\n T tmp=lhs; //requires copy operator\n lhs=rhs;\n rhs=tmp;\n}\n\n\n/**************** Memory management ***************************/\n\nbool GMalloc(pointer* ptr, unsigned long size); // Allocate memory\nbool GCalloc(pointer* ptr, unsigned long size); // Allocate and initialize memory\nbool GRealloc(pointer* ptr,unsigned long size); // Resize memory\nvoid GFree(pointer* ptr); // Free memory, resets ptr to NULL\n\n\n//int saprintf(char **retp, const char *fmt, ...);\n\nvoid GError(const char* format,...); // Error routine (aborts program)\nvoid GMessage(const char* format,...);// Log message to stderr\n// Assert failed routine:- usually not called directly but through GASSERT\nvoid GAssert(const char* expression, const char* filename, unsigned int lineno);\n\n// ****************** string manipulation *************************\nchar *Gstrdup(const char* str);\n//duplicate a string by allocating a copy for it and returning it\nchar* Gstrdup(const char* sfrom, const char* sto);\n//same as GStrdup, but with an early termination (e.g. on delimiter)\n\nchar* Gsubstr(const char* str, char* from, char* to=NULL);\n//extracts a substring, allocating it, including boundaries (from/to)\n\nint strsplit(char* str, char** fields, int maxfields, const char* delim);\nint strsplit(char* str, char** fields, int maxfields, const char delim);\nint strsplit(char* str, char** fields, int maxfields); //splits by tab or space\n\nchar* replaceStr(char* &str, char* newvalue);\n\n//conversion: to Lower/Upper case\n// creating a new string:\nchar* upCase(const char* str);\nchar* loCase(const char* str);\n// changing string in place:\nchar* strlower(char * str);\nchar* strupper(char * str);\n\n//strstr but for memory zones: scans a memory region\n//for a substring:\nvoid* Gmemscan(void *mem, unsigned int len,\n                  void *part, unsigned int partlen);\n\n// test if a char is in a string:\nbool chrInStr(char c, const char* str);\n\nchar* rstrchr(char* str, char ch);\n/* returns a pointer to the rightmost\n  occurence of ch in str - like rindex for platforms missing it*/\n\nchar* strchrs(const char* s, const char* chrs);\n//strchr but with a set of chars instead of only one\n\nchar* rstrfind(const char* str, const char *substr); \n// like rindex() but for strings;  right side version of strstr()\n\nchar* reverseChars(char* str, int slen=0); //in place reversal of string \n\nchar* rstrstr(const char* rstart, const char *lend, const char* substr);\n/*the reversed, rightside equivalent of strstr: starts searching\n from right end (rstart), going back to left end (lend) and returns\n a pointer to the last (right) matching character in str */\n\nchar* strifind(const char* str,  const char* substr);\n// case insensitive version of strstr -- finding a string within another string\n// returns NULL if not found\n\n//Determines if a string begins with a given prefix\n//(returns false when any of the params is NULL,\n// but true when prefix is '' (empty string)!)\nbool startsWith(const char* s, const char* prefix);\n\nbool startsiWith(const char* s, const char* prefix); //case insensitive\n\n\nbool endsWith(const char* s, const char* suffix);\n//Note: returns true if suffix is empty string, but false if it's NULL\n\n\n// ELF hash function for strings\nint strhash(const char* str);\n\n\n\n//---- generic base GSeg : genomic segment (interval) --\n// coordinates are considered 1-based (so 0 is invalid)\nclass GSeg {\n public:\n  uint start; //start<end always!\n  uint end;\n  GSeg(uint s=0,uint e=0) {\n    if (s>e) { start=e;end=s; }\n        else { start=s;end=e; }\n    }\n  //check for overlap with other segment\n  uint len() { return end-start+1; }\n  bool overlap(GSeg* d) {\n     //return start<d->start ? (d->start<=end) : (start<=d->end);\n     return (start<=d->end && end>=d->start);\n     }\n\n  bool overlap(GSeg& d) {\n     //return start<d.start ? (d.start<=end) : (start<=d.end);\n     return (start<=d.end && end>=d.start);\n     }\n\n  bool overlap(GSeg& d, int fuzz) {\n     //return start<d.start ? (d.start<=end+fuzz) : (start<=d.end+fuzz);\n     return (start<=d.end+fuzz && end+fuzz>=d.start);\n     }\n\n  bool overlap(uint s, uint e) {\n     if (s>e) { Gswap(s,e); }\n     //return start<s ? (s<=end) : (start<=e);\n     return (start<=e && end>=s);\n     }\n\n  //return the length of overlap between two segments\n  int overlapLen(GSeg* r) {\n     if (start<r->start) {\n        if (r->start>end) return 0;\n        return (r->end>end) ? end-r->start+1 : r->end-r->start+1;\n        }\n       else { //r->start<=start\n        if (start>r->end) return 0;\n        return (r->end<end)? r->end-start+1 : end-start+1;\n        }\n     }\n  int overlapLen(uint rstart, uint rend) {\n     if (rstart>rend) { Gswap(rstart,rend); }\n     if (start<rstart) {\n        if (rstart>end) return 0;\n        return (rend>end) ? end-rstart+1 : rend-rstart+1;\n        }\n       else { //rstart<=start\n        if (start>rend) return 0;\n        return (rend<end)? rend-start+1 : end-start+1;\n        }\n     }\n\n  //fuzzy coordinate matching:\n  bool coordMatch(GSeg* s, uint fuzz=0) {\n    if (fuzz==0) return (start==s->start && end==s->end);\n    uint sd = (start>s->start) ? start-s->start : s->start-start;\n    uint ed = (end>s->end) ? end-s->end : s->end-end;\n    return (sd<=fuzz && ed<=fuzz);\n    }\n  //comparison operators required for sorting\n  bool operator==(GSeg& d){\n      return (start==d.start && end==d.end);\n      }\n  bool operator<(GSeg& d){\n     return (start==d.start)?(end<d.end):(start<d.start);\n     }\n};\n\n\n\n//--------------------------------------------------------\n// ************** simple line reading class for text files\n\n//GLineReader -- text line reading/buffering class\nclass GLineReader {\n   bool closeFile;\n   int len;\n   int allocated;\n   char* buf;\n   bool isEOF;\n   FILE* file;\n   off_t filepos; //current position\n   bool pushed; //pushed back\n   int lcount; //line counter (read lines)\n public:\n   char* chars() { return buf; }\n   char* line() { return buf; }\n   int readcount() { return lcount; } //number of lines read\n   void setFile(FILE* stream) { file=stream; }\n   int length() { return len; }\n   int size() { return len; } //same as size();\n   bool isEof() {return isEOF; }\n   bool eof() { return isEOF; }\n   off_t getfpos() { return filepos; }\n   off_t getFpos() { return filepos; }\n   char* nextLine() { return getLine(); }\n   char* getLine() { if (pushed) { pushed=false; return buf; }\n                            else return getLine(file);  }\n   char* getLine(FILE* stream) {\n                 if (pushed) { pushed=false; return buf; }\n                          else return getLine(stream, filepos); }\n   char* getLine(FILE* stream, off_t& f_pos); //read a line from a stream and update\n                           // the given file position\n   void pushBack() { if (lcount>0) pushed=true; } // \"undo\" the last getLine request\n            // so the next call will in fact return the same line\n   GLineReader(const char* fname) {\n      FILE* f=fopen(fname, \"rb\");\n      if (f==NULL) GError(\"Error opening file '%s'!\\n\",fname);\n      closeFile=true;\n      init(f);\n      }\n   GLineReader(FILE* stream=NULL, off_t fpos=0) {\n     closeFile=false;\n     init(stream,fpos);\n     }\n   void init(FILE* stream, off_t fpos=0) {\n     len=0;\n     isEOF=false;\n     allocated=1024;\n     GMALLOC(buf,allocated);\n     lcount=0;\n     buf[0]=0;\n     file=stream;\n     filepos=fpos;\n     pushed=false;\n     }\n   ~GLineReader() {\n     GFREE(buf);\n     if (closeFile) fclose(file);\n     }\n};\n\n\n/* extended fgets() -  to read one full line from a file and\n  update the file position correctly !\n  buf will be reallocated as necessary, to fit the whole line\n  */\nchar* fgetline(char* & buf, int& buflen, FILE* stream, off_t* f_pos=NULL, int* linelen=NULL);\n\n\n//print int/values nicely formatted in 3-digit groups\nchar* commaprintnum(uint64 n);\n\n/*********************** File management functions *********************/\n\n// removes the last part (file or directory name) of a full path\n// WARNING: this is a destructive operation for the given string!\nvoid delFileName(char* filepath);\n\n// returns a pointer to the last file or directory name in a full path\nconst char* getFileName(const char* filepath);\n// returns a pointer to the file \"extension\" part in a filename\nconst char* getFileExt(const char* filepath);\n\n\nint fileExists(const char* fname);\n//returns 0 if file entry doesn't exist\n//        1 if it's a directory\n//        2 if it's a regular file\n//        3 otherwise (?)\n\nint64 fileSize(const char* fpath);\n\n//write a formatted fasta record, fasta formatted\nvoid writeFasta(FILE *fw, const char* seqid, const char* descr,\n        const char* seq, int linelen=60, int seqlen=0);\n\n//parses the next number found in a string at the current position\n//until a non-digit (and not a '.', 'e','E','-','+') is encountered;\n//updates the char* pointer to be after the last digit parsed\nbool parseNumber(char* &p, double& v);\nbool parseDouble(char* &p, double& v); //just an alias for parseNumber\n\nbool parseInt(char* &p, int& i);\nbool parseUInt(char* &p, uint& i);\nbool parseHex(char* &p,  uint& i);\n\n#endif /* G_BASE_DEFINED */\n"
  },
  {
    "path": "src/GFaSeqGet.cpp",
    "content": "#include \"GFaSeqGet.h\"\n#include \"gdna.h\"\n#include <ctype.h>\n\nvoid GSubSeq::setup(uint sstart, int slen, int sovl, int qfrom, int qto, uint maxseqlen) {\n     if (sovl==0) {\n       GFREE(sq);\n       sqstart=sstart;\n       uint max_len=(maxseqlen>0) ? maxseqlen : MAX_FASUBSEQ;\n       sqlen = (slen==0 ? max_len : slen);\n       GMALLOC(sq, sqlen);\n       return;\n       }\n  //overlap -- copy the overlapping region\n  char* newsq=NULL;\n  GMALLOC(newsq, slen);\n  memcpy((void*)&newsq[qto], (void*)&sq[qfrom], sovl);\n  GFREE(sq);\n  sq=newsq;\n  sqstart=sstart;\n  sqlen=slen;\n}\n\nvoid GFaSeqGet::finit(const char* fn, off_t fofs, bool validate) {\n fh=fopen(fn,\"rb\");\n if (fh==NULL) {\n   GError(\"Error (GFaSeqGet) opening file '%s'\\n\",fn);\n   }\n fname=Gstrdup(fn);\n initialParse(fofs, validate);\n lastsub=new GSubSeq();\n}\n\nGFaSeqGet::GFaSeqGet(const char* faname, uint seqlen, off_t fseqofs, int l_len, int l_blen) {\n//for GFastaIndex use mostly -- the important difference is that\n//the file offset is to the sequence, not to the defline\n  fh=fopen(faname,\"rb\");\n  if (fh==NULL) {\n    GError(\"Error (GFaSeqGet) opening file '%s'\\n\",faname);\n    }\n  fname=Gstrdup(faname);\n  line_len=l_len;\n  line_blen=l_blen;\n  seq_len=seqlen;\n  if (line_blen<line_len)\n       GError(\"Error (GFaSeqGet): invalid line length info (len=%d, blen=%d)\\n\",\n              line_len, line_blen);\n  fseqstart=fseqofs;\n  lastsub=new GSubSeq();\n}\n\nGFaSeqGet::GFaSeqGet(FILE* f, off_t fofs, bool validate) {\n  fname=NULL;\n  fseqstart=0;\n  if (f==NULL) GError(\"Error (GFaSeqGet) : null file handle!\\n\");\n  seq_len=0;\n  fh=f;\n  initialParse(fofs, validate);\n  lastsub=new GSubSeq();\n}\n\nvoid GFaSeqGet::initialParse(off_t fofs, bool checkall) {\n static const char gfa_ERRPARSE[]=\"Error (GFaSeqGet): invalid FASTA file format.\\n\";\n if (fofs!=0) { fseeko(fh,fofs,SEEK_SET); } //e.g. for offsets provided by cdbyank\n //read the first two lines to determine fasta parameters\n fseqstart=fofs;\n int c=getc(fh);\n fseqstart++;\n if (c!='>') GError(\"Error (GFaSeqGet): not a fasta header?\\n\");\n while ((c=getc(fh))!=EOF) {\n   fseqstart++;\n   if (c=='\\n' || c=='\\r') { break; } //end of defline\n   }\n\n if (c==EOF) GError(gfa_ERRPARSE);\n line_len=0;\n int lendlen=0;\n while ((c=getc(fh))!=EOF) {\n  if (c=='\\n' || c=='\\r') { //end of line encountered\n     if (line_len>0) { //end of the first \"sequence\" line\n        lendlen++;\n        break;\n        }\n      else {// another EoL char at the end of defline\n        fseqstart++;\n        continue;\n        }\n     }// end-of-line characters\n  line_len++;\n  }\n //we are at the end of first sequence line\n while ((c=getc(fh))!=EOF) {\n   if (c=='\\n' || c=='\\r') lendlen++;\n      else {\n       ungetc(c,fh);\n       break;\n       }\n   }\n line_blen=line_len+lendlen;\n if (c==EOF) return;\n // -- you don't need to check it all if you're sure it's safe\n if (checkall) { //validate the rest of the FASTA record\n   int llen=0; //last line length\n   int elen=0; //length of last line ending\n   bool waseol=true;\n   while ((c=getc(fh))!=EOF) {\n     if (c=='>' && waseol) { ungetc(c,fh); break; }\n     if (c=='\\n' ||  c=='\\r') {\n        // eol char\n        elen++;\n        if (waseol) continue; //2nd eol char\n        waseol=true;\n        elen=1;\n        continue;\n        }\n     if (c<=32) GError(gfa_ERRPARSE); //invalid character encountered\n     //--- on a seq char here:\n     if (waseol) {//beginning of a seq line\n       if (elen && (llen!=line_len || elen!=lendlen))\n           //GError(gfa_ERRPARSE);\n         GError(\"Error: invalid FASTA format for GFaSeqGet; make sure that\\n\\\n  the sequence lines have the same length (except for the last line)\");\n       waseol=false;\n       llen=0;\n       elen=0;\n       }\n     llen++;\n     } //while reading chars\n   }// FASTA checking was requested\n fseeko(fh,fseqstart,SEEK_SET);\n}\n\nconst char* GFaSeqGet::subseq(uint cstart, int& clen) {\n  //cstart is 1-based genomic coordinate within current fasta sequence\n   int maxlen=(seq_len>0)?seq_len : MAX_FASUBSEQ;\n   //GMessage(\"--> call: subseq(%u, %d)\\n\", cstart, clen);\n  if (clen>maxlen) {\n    GMessage(\"Error (GFaSeqGet): subsequence cannot be larger than %d\\n\", maxlen);\n    return NULL;\n    }\n  if (seq_len>0 && clen+cstart-1>seq_len) {\n     GMessage(\"Error (GFaSeqGet): end coordinate (%d) cannot be larger than sequence length %d\\n\", clen+cstart-1, seq_len);\n     }\n  if (lastsub->sq==NULL || lastsub->sqlen==0) {\n    lastsub->setup(cstart, clen, 0,0,0,seq_len);\n    loadsubseq(cstart, clen);\n    lastsub->sqlen=clen;\n    return (const char*)lastsub->sq;\n    }\n  //allow extension up to MAX_FASUBSEQ\n  uint bstart=lastsub->sqstart;\n  uint bend=lastsub->sqstart+lastsub->sqlen-1;\n  uint cend=cstart+clen-1;\n  int qlen=0; //only the extra len to be allocated/appended/prepended\n  uint qstart=cstart; //start coordinate of the new seq block of length qlen to be read from file\n  int newlen=0; //the new total length of the buffered sequence lastsub->sq\n  int kovl=0;\n  int czfrom=0;//0-based offsets for copying a previously read sequence chunk\n  int czto=0;\n  uint newstart=cstart;\n  if (cstart>=bstart && cend<=bend) { //new reg contained within existing buffer\n     return (const char*) &(lastsub->sq[cstart-bstart]) ;\n    }\n  //extend downward\n  uint newend=GMAX(cend, bend);\n  if (cstart<bstart) { //requested start < old buffer start\n    newstart=cstart;\n    newlen=(newend-newstart+1);\n    if (newlen>MAX_FASUBSEQ) {\n       newlen=MAX_FASUBSEQ;\n       newend=cstart+newlen-1; //keep newstart, set newend\n       }\n    qlen=bstart-cstart;\n    if (newend>bstart) { //overlap\n       if (newend>bend) {// new region is larger & around the old one - so we have two regions to update\n         kovl=bend-bstart+1;\n         czfrom=0;\n         czto=bstart-cstart;\n         lastsub->setup(newstart, newlen, kovl, czfrom, czto, seq_len); //this should realloc and copy the kovl subseq\n         qlen=bstart-cstart;\n         loadsubseq(newstart, qlen);\n         qlen=newend-bend;\n         int toread=qlen;\n         loadsubseq(bend+1, qlen);\n         clen-=(toread-qlen);\n         lastsub->sqlen=clen;\n         return (const char*)lastsub->sq;\n         }\n        //newend<=bend\n       kovl=newend-bstart+1;\n       }\n     else { //no overlap with previous buffer\n       if (newend>bend) kovl=bend-bstart+1;\n                   else kovl=newend-bstart+1;\n       }\n     qlen=bstart-cstart;\n     czfrom=0;\n     czto=qlen;\n    } //cstart<bstart\n   else { //cstart>=bstart, possibly extend upwards\n    newstart=bstart;\n    newlen=(newend-newstart+1);\n    if (newlen>MAX_FASUBSEQ) {\n       newstart=bstart+(newlen-MAX_FASUBSEQ);//keep newend, assign newstart\n       newlen=MAX_FASUBSEQ;\n       if (newstart<=bend) { //overlap with old buffer\n          kovl=bend-newstart+1;\n          czfrom=newstart-bstart;\n          czto=0;\n          }\n       else { //not overlapping old buffer\n         kovl=0;\n         }\n       } //newstart reassigned\n    else { //we can extend the buffer to include the old one\n      qlen=newend-bend; //how much to read from file\n      qstart=bend+1;\n      kovl=bend-bstart+1;\n      czfrom=0;\n      czto=0;\n      }\n    }\n  lastsub->setup(newstart, newlen, kovl, czfrom, czto, seq_len); //this should realloc but copy any overlapping region\n  lastsub->sqlen-=qlen; //appending may result in a premature eof\n  int toread=qlen;\n  loadsubseq(qstart, qlen); //read the missing chunk, if any\n  clen-=(toread-qlen);\n  lastsub->sqlen+=qlen;\n  return (const char*)(lastsub->sq+(cstart-newstart));\n}\n\nchar* GFaSeqGet::copyRange(uint cstart, uint cend, bool revCmpl, bool upCase) {\n  if (cstart>cend) { Gswap(cstart, cend); }\n  int clen=cend-cstart+1;\n  const char* gs=subseq(cstart, clen);\n  if (gs==NULL) return NULL;\n  char* r=NULL;\n  GMALLOC(r,clen+1);\n  r[clen]=0;\n  memcpy((void*)r,(void*)gs, clen);\n  if (revCmpl) reverseComplement(r,clen);\n  if (upCase) {\n       for (int i=0;i<clen;i++)\n            r[i]=toupper(r[i]);\n       }\n  return r;\n }\n\nconst char* GFaSeqGet::loadsubseq(uint cstart, int& clen) {\n  //assumes enough lastsub->sq space allocated previously\n  //only loads the requested clen chars from file, at offset &lastsub->sq[cstart-lastsub->sqstart]\n  int sofs=cstart-lastsub->sqstart;\n  int lendlen=line_blen-line_len;\n  char* seqp=lastsub->sq+sofs;\n  //find the proper file offset and read the appropriate lines\n  uint seqofs=cstart-1;\n  uint startlno = seqofs/line_len;\n  int lineofs = seqofs % line_len;\n  off_t fstart=fseqstart + (startlno*line_blen);\n  fstart+=lineofs;\n\n  fseeko(fh, fstart, SEEK_SET);\n  int toread=clen;\n  int maxlen=(seq_len>0)? seq_len-cstart+1 : MAX_FASUBSEQ ;\n  if (toread==0) toread=maxlen; //read max allowed, or to the end of file\n  int actualrlen=0;\n  int sublen=0;\n  if (lineofs>0) { //read the partial first line\n    int reqrlen=line_len-lineofs;\n    if (reqrlen>toread) reqrlen=toread; //in case we need to read just a few chars\n    actualrlen=fread((void*)seqp, 1, reqrlen, fh);\n    if (actualrlen<reqrlen) { //eof reached prematurely\n      while (seqp[actualrlen-1]=='\\n' || seqp[actualrlen-1]=='\\r') actualrlen--;\n      //check for new sequences in between\n      clen=actualrlen;\n      sublen+=actualrlen;\n      return (const char*)seqp;\n      }\n    toread-=reqrlen;\n    sublen+=reqrlen;\n    fseeko(fh, lendlen, SEEK_CUR);\n    }\n  //read the rest of the lines\n  while (toread>=line_len) {\n    char* rseqp=&(seqp[sublen]);\n    actualrlen=fread((void*)rseqp, 1, line_len, fh);\n    /*\n    char dbuf[256];dbuf[255]=0;\n    strncpy(dbuf,rseqp, actualrlen);\n    dbuf[actualrlen]=0;\n    GMessage(\"<<<read line: %s\\n\",dbuf);\n    */\n    if (actualrlen<line_len) {\n      while (rseqp[actualrlen-1]=='\\n' || rseqp[actualrlen-1]=='\\r') actualrlen--;\n      sublen+=actualrlen;\n      clen=sublen;\n      return (const char*)seqp;\n      }\n    toread-=actualrlen;\n    sublen+=actualrlen;\n    fseeko(fh, lendlen, SEEK_CUR);\n    }\n  // read the last partial line, if any\n  if (toread>0) {\n    char* rseqp=&(seqp[sublen]);\n    actualrlen=fread((void*)rseqp, 1, toread, fh);\n    if (actualrlen<toread) {\n      while (rseqp[actualrlen-1]=='\\n' || rseqp[actualrlen-1]=='\\r')\n          actualrlen--;\n      }\n    sublen+=actualrlen;\n    }\n  //lastsub->sqlen+=sublen;\n  clen=sublen;\n\n  return (const char*)seqp;\n  }\n\n\n"
  },
  {
    "path": "src/GFaSeqGet.h",
    "content": "#ifndef GFASEQGET_H\n#define GFASEQGET_H\n#include \"GList.hh\"\n\n#define MAX_FASUBSEQ 0x20000000\n//max 512MB sequence data held in memory at a time\n\nclass GSubSeq {\n public:\n  uint sqstart; //1-based coord of subseq start on sequence\n  uint sqlen;   //length of subseq loaded\n  char* sq; //actual subsequence data will be stored here\n                // (with end-of-line characters removed)\n\n  /*char* xseq; //the exposed pointer to the last requested subsequence start\n  off_t xstart; //the coordinate start for the last requested subseq\n  off_t xlen; //the last requested subseq len*/\n  GSubSeq() {\n     sqstart=0;\n     sqlen=0;\n     sq=NULL;\n     /* xseq=NULL;\n     xstart=0;\n     xlen=0;*/\n     }\n  void forget() { //forget about pointer data, so we can reuse it\n  \tsq=NULL;\n  \tsqstart=0;\n  \tsqlen=0;\n  }\n  ~GSubSeq() {\n     GFREE(sq);\n     }\n  // genomic, 1-based coordinates:\n  void setup(uint sstart, int slen, int sovl=0, int qfrom=0, int qto=0, uint maxseqlen=0);\n    //check for overlap with previous window and realloc/extend appropriately\n    //returns offset from seq that corresponds to sstart\n    // the window will keep extending until MAX_FASUBSEQ is reached\n};\n\nclass GFaSeqGet {\n  char* fname;\n  FILE* fh;\n  //raw offset in the file where the sequence actually starts:\n  off_t fseqstart;\n  uint seq_len; //total sequence length, if known (when created from GFastaIndex)\n  int line_len; //length of each line of text\n  int line_blen; //binary length of each line\n                 // = line_len + number of EOL character(s)\n  GSubSeq* lastsub;\n  void initialParse(off_t fofs=0, bool checkall=true);\n  const char* loadsubseq(uint cstart, int& clen);\n  void finit(const char* fn, off_t fofs, bool validate);\n public:\n  GFaSeqGet() {\n    fh=NULL;\n    fseqstart=0;\n    seq_len=0;\n    line_len=0;\n    line_blen=0;\n    fname=NULL;\n    lastsub=NULL;\n    }\n  GFaSeqGet(const char* fn, off_t fofs, bool validate=false) {\n     seq_len=0;\n     finit(fn,fofs,validate); \n     }\n  GFaSeqGet(const char* fn, bool validate=false) {\n     seq_len=0;\n     finit(fn,0,validate);\n     }\n\n  GFaSeqGet(const char* faname, uint seqlen, off_t fseqofs, int l_len, int l_blen);\n  //constructor from GFastaIndex record\n\n  GFaSeqGet(FILE* f, off_t fofs=0, bool validate=false);\n\n  ~GFaSeqGet() {\n    if (fname!=NULL) {\n       GFREE(fname);\n       fclose(fh);\n       }\n    delete lastsub;\n    }\n  const char* subseq(uint cstart, int& clen);\n  const char* getRange(uint cstart=1, uint cend=0) {\n      if (cend==0) cend=(seq_len>0)?seq_len : MAX_FASUBSEQ;\n      if (cstart>cend) { Gswap(cstart, cend); }\n      int clen=cend-cstart+1;\n      //int rdlen=clen;\n      return subseq(cstart, clen);\n      }\n\n  //caller is responsible for deallocating the return string\n  char* copyRange(uint cstart, uint cend, bool revCmpl=false, bool upCase=false);\n\n  //uncached, read and return allocated buffer\n  //caller is responsible for deallocating the return string\n  char* fetchSeq(int* retlen=NULL) {\n  \tint clen=(seq_len>0) ? seq_len : MAX_FASUBSEQ;\n  \tif (lastsub) { delete lastsub; lastsub=NULL; }\n  \tsubseq(1, clen);\n  \tif (retlen) *retlen=clen;\n  \tchar* r=lastsub->sq;\n  \tlastsub->forget();\n  \tif (clen>0) {\n  \t   r[clen]=0;\n  \t}\n  \telse {\n  \t\tr=NULL;\n  \t}\n  \treturn r;\n  }\n\n  void loadall(uint32 max_len=0) {\n    //TODO: better read the whole sequence differently here - line by line\n    //so when EOF or another '>' line is found, the reading stops!\n    int clen=(seq_len>0) ? seq_len : ((max_len>0) ? max_len : MAX_FASUBSEQ);\n    subseq(1, clen);\n    }\n  void load(uint cstart, uint cend) {\n     //cache as much as possible\n      if (seq_len>0 && cend>seq_len) cend=seq_len; //correct a bad request\n      int clen=cend-cstart+1;\n      subseq(cstart, clen);\n     }\n  int getsublen() { return lastsub!=NULL ? lastsub->sqlen : 0 ; }\n  int getseqlen() { return seq_len; } //known when loaded with GFastaIndex\n  off_t getseqofs() { return fseqstart; }\n  int getLineLen() { return line_len; }\n  int getLineBLen() { return line_blen; }\n  //reads a subsequence starting at genomic coordinate cstart (1-based)\n };\n\n\n#endif\n"
  },
  {
    "path": "src/GFastaIndex.cpp",
    "content": "/*\n * GFastaIndex.cpp\n *\n *  Created on: Aug 25, 2010\n *      Author: gpertea\n */\n\n#include \"GFastaIndex.h\"\n#define ERR_FAIDXLINE \"Error parsing fasta index line: \\n%s\\n\"\n#define ERR_FALINELEN \"Error: sequence lines in a FASTA record must have the same length!\\n\"\nvoid GFastaIndex::addRecord(const char* seqname, uint seqlen, off_t foffs, int llen, int llen_full) {\n     GFastaRec* farec=records.Find(seqname);\n     if (farec!=NULL) {\n          GMessage(\"Warning: duplicate sequence ID (%s) added to the fasta index! Only last entry data will be kept.\\n\");\n          farec->seqlen=seqlen;\n          farec->fpos=foffs;\n          farec->line_len=llen;\n          farec->line_blen=llen_full;\n          }\n     else {\n         farec=new GFastaRec(seqlen,foffs,llen,llen_full);\n         records.Add(seqname,farec);\n         farec->seqname=records.getLastKey();\n         }\n}\n\nint GFastaIndex::loadIndex(const char* finame) { //load record info from existing fasta index\n    if (finame==NULL) finame=fai_name;\n    if (finame!=fai_name) {\n      fai_name=Gstrdup(finame);\n      }\n    if (fai_name==NULL) GError(\"Error: GFastaIndex::loadIndex() called with no file name!\\n\");\n    records.Clear();\n    haveFai=false;\n    FILE* fi=fopen(fai_name,\"rb\");\n    if (fi==NULL) {\n       GMessage(\"Warning: cannot open fasta index file: %s!\\n\",fai_name);\n       return 0;\n       }\n    GLineReader fl(fi);\n    char* s=NULL;\n    while ((s=fl.nextLine())!=NULL) {\n      if (*s=='#') continue;\n      char* p=strchrs(s,\"\\t \");\n      if (p==NULL) GError(ERR_FAIDXLINE,s);\n      *p=0; //s now holds the genomic sequence name\n      p++;\n      uint len=0;\n      int line_len=0, line_blen=0;\n#ifdef __WIN32__\n         long offset=-1;\n         sscanf(p, \"%d%ld%d%d\", &len, &offset, &line_len, &line_blen);\n#else\n         long long offset=-1;\n         sscanf(p, \"%d%lld%d%d\", &len, &offset, &line_len, &line_blen);\n#endif\n      if (len==0 || line_len==0 || line_blen==0 || line_blen<line_len)\n          GError(ERR_FAIDXLINE,p);\n      addRecord(s,len,offset,line_len, line_blen);\n      }\n    fclose(fi);\n    haveFai=(records.Count()>0);\n    return records.Count();\n}\n\nint GFastaIndex::buildIndex() {\n    //this parses the whole fasta file, so it could be slow\n    if (fa_name==NULL)\n       GError(\"Error: GFastaIndex::buildIndex() called with no fasta file!\\n\");\n    FILE* fa=fopen(fa_name,\"rb\");\n    if (fa==NULL) {\n       GMessage(\"Warning: cannot open fasta index file: %s!\\n\",fa_name);\n       return 0;\n       }\n    records.Clear();\n    GLineReader fl(fa);\n    char* s=NULL;\n    uint seqlen=0;\n    int line_len=0,line_blen=0;\n    bool newSeq=false; //set when FASTA header is encountered\n    off_t newSeqOffset=0;\n    int prevOffset=0;\n    char* seqname=NULL;\n    int last_len=0;\n    bool mustbeLastLine=false; //true if the line length decreases\n    while ((s=fl.nextLine())!=NULL) {\n     if (s[0]=='>') {\n        if (seqname!=NULL) {\n         if (seqlen==0)\n            GError(\"Warning: empty FASTA record skipped (%s)!\\n\",seqname);\n         else { //seqlen!=0\n           addRecord(seqname, seqlen,newSeqOffset, line_len, line_blen);\n           }\n         }\n        char *p=s;\n        while (*p > 32) p++;\n        *p=0;\n        GFREE(seqname);\n        seqname=Gstrdup(&s[1]);\n        newSeq=true;\n        newSeqOffset=fl.getfpos();\n        last_len=0;\n        line_len=0;\n        line_blen=0;\n        seqlen=0;\n        mustbeLastLine=false;\n     } //defline parsing\n     else { //sequence line\n       int llen=fl.length();\n       int lblen=fl.getFpos()-prevOffset;\n        if (newSeq) { //first sequence line after defline\n          line_len=llen;\n          line_blen=lblen;\n        }\n        else {//next seq lines after first\n          if (mustbeLastLine) {\n              //could be empty line, adjust for possible spaces\n              if (llen>0) {\n                char *p=s;\n                //trim spaces, tabs etc. on the last line\n                while (*p > 32) ++p;\n                llen=(p-s);\n              }\n              if (llen>0) GError(ERR_FALINELEN);\n          }\n          else {\n              if (llen<last_len) mustbeLastLine=true;\n                 else if (llen>last_len) GError(ERR_FALINELEN);\n          }\n        }\n        seqlen+=llen;\n        last_len=llen;\n        newSeq=false;\n     } //sequence line\n     prevOffset=fl.getfpos();\n     }//for each line of the fasta file\n    if (seqlen>0)\n       addRecord(seqname, seqlen, newSeqOffset, line_len, line_blen);\n    GFREE(seqname);\n    fclose(fa);\n    return records.Count();\n}\n\n\nint GFastaIndex::storeIndex(const char* finame) { //write the hash to a file\n    if (records.Count()==0)\n       GError(\"Error at GFastaIndex:storeIndex(): no records found!\\n\");\n    FILE* fai=fopen(finame, \"w\");\n    if (fai==NULL) GError(\"Error creating fasta index file: %s\\n\",finame);\n    int rcount=storeIndex(fai);\n    GFREE(fai_name);\n    fai_name=Gstrdup(finame);\n    return rcount;\n}\n\nint GFastaIndex::storeIndex(FILE* fai) {\n  int rcount=0;\n  GList<GFastaRec> reclist(true,false,true); //sorted, don't free members, unique\n  records.startIterate();\n  GFastaRec* rec=NULL;\n  while ((rec=records.NextData())!=NULL) {\n    reclist.Add(rec);\n    }\n  //reclist has records sorted by file offset\n  for (int i=0;i<reclist.Count();i++) {\n#ifdef __WIN32__\n    int written=fprintf(fai, \"%s\\t%d\\t%ld\\t%d\\t%d\\n\",\n            reclist[i]->seqname,reclist[i]->seqlen,(long)reclist[i]->fpos,\n              reclist[i]->line_len, reclist[i]->line_blen);\n#else\n    int written=fprintf(fai, \"%s\\t%d\\t%lld\\t%d\\t%d\\n\",\n            reclist[i]->seqname, reclist[i]->seqlen, (long long)(reclist[i]->fpos),\n              reclist[i]->line_len, reclist[i]->line_blen);\n#endif\n    if (written>0) rcount++;\n       else break; //couldn't write anymore\n    }\n  fclose(fai);\n  haveFai=(rcount>0);\n  return rcount;\n}\n"
  },
  {
    "path": "src/GFastaIndex.h",
    "content": "/*\n * GFaIdx.h\n *\n *  Created on: Aug 25, 2010\n *      Author: gpertea\n */\n\n#ifndef GFAIDX_H_\n#define GFAIDX_H_\n\n#include \"GHash.hh\"\n#include \"GList.hh\"\n\nclass GFastaRec {\n public:\n  char* seqname;\n  uint seqlen;\n  off_t fpos;\n  int line_len; //effective line length (without EoL)\n  int line_blen; //length of line including EoL characters\n  GFastaRec(uint slen=0, off_t fp=0, int llen=0, int llenb=0) {\n    seqname=NULL; //only a pointer copy\n    seqlen=slen;\n    fpos=fp;\n    line_len=llen;\n    line_blen=llenb;\n    }\n  bool operator==(GFastaRec& d){\n      return (fpos==d.fpos);\n      }\n  bool operator>(GFastaRec& d){\n     return (fpos>d.fpos);\n     }\n  bool operator<(GFastaRec& d){\n    return (fpos<d.fpos);\n    }\n\n};\n\nclass GFastaIndex {\n  char* fa_name;\n  char* fai_name;\n  bool haveFai;\n public:\n  GHash<GFastaRec> records;\n  void addRecord(const char* seqname, uint seqlen,\n                    off_t foffs, int llen, int llen_full);\n\n  GFastaRec* getRecord(const char* seqname) {\n    return records.Find(seqname);\n    }\n  bool hasIndex() { return haveFai; }\n  int loadIndex(const char* finame);\n  int buildIndex(); //build index in memory by parsing the whole fasta file\n  int storeIndex(const char* finame);\n  int storeIndex(FILE* fai);\n  int getCount() { return records.Count(); }\n  GFastaIndex(const char* fname, const char* finame=NULL):records() {\n    if (fileExists(fname)!=2) GError(\"Error: fasta file %s not found!\\n\",fname);\n    if (fileSize(fname)<=0) GError(\"Error: invalid fasta file %s !\\n\",fname);\n    fa_name=Gstrdup(fname);\n    fai_name=finame!=NULL ? Gstrdup(finame) : NULL;\n    if (fileSize(fa_name)==0) {\n      GError(\"Error creating GFastaIndex(%s): invalid fasta file!\\n\",fa_name);\n      }\n    haveFai=false;\n    if (fai_name!=NULL && fileSize(fai_name)>0) {\n       //try to load the index file if it exists\n       loadIndex(fai_name);\n       haveFai=(records.Count()>0);\n       }\n    }\n  ~GFastaIndex() {\n    GFREE(fa_name);\n    GFREE(fai_name);\n    }\n};\n\n#endif /* GFAIDX_H_ */\n"
  },
  {
    "path": "src/GHash.hh",
    "content": "/********************************************************************************\n*                  Hash table class template (char* based)                               *\n*********************************************************************************/\n\n#ifndef GHash_HH\n#define GHash_HH\n#include \"GBase.h\"\n\n/**\n* This class maintains a fast-access hash table of entities\n* indexed by a character string (essentially, maps strings to pointers)\n*/\n\n\ntemplate <class OBJ> class GHash {\n protected:\n\tstruct GHashEntry {\n\t     char*   key;              // Key string\n\t     bool    keyalloc;         //shared key flag (to not free the key chars)\n\t     int     hash;             // Hash value of key\n\t     pointer data;              // Data\n\t     bool    mark;             // Entry is marked\n\t     };\n  GHashEntry* hash;         // Hash\n  int         fCapacity;     // table size\n  int         fCount;        // number of valid entries\n  int  fCurrentEntry;\n  char* lastkeyptr; //pointer to last key string added\n    //---------- Raw data retrieval (including empty entries\n  // Return key at position pos.\n  const char* Key(uint pos) const { return hash[pos].key; }\n  // return data OBJ* at given position\n  OBJ* Data(uint pos) const { return (OBJ*) hash[pos].data; }\n  // Return mark flag of entry at position pos.\n  bool Mark(uint pos) const { return hash[pos].mark; }\n  // Return position of first filled slot, or >= fCapacity\n  int First() const;\n  // Return position of last filled slot or -1\n  int Last() const;\n  // Return position of next filled slot in hash table\n  // or a value greater than or equal to fCapacity if no filled\n  // slot was found\n  int Next(int pos) const;\n  //Return position of previous filled slot in hash table\n  //or a -1 if no filled slot was found\n  int Prev(int pos) const;\n\nprivate:\n  GHash(const GHash&);\n  GHash &operator=(const GHash&);\n  GFreeProc* fFreeProc; //procedure to free item data\nprotected:\npublic:\n  static void DefaultFreeProc(pointer item) {\n      delete (OBJ*)item;\n      }\npublic:\n  GHash(GFreeProc* freeProc); // constructs of an empty hash\n  GHash(bool doFree=true); // constructs of an empty hash (free the item objects)\n  void setFreeItem(GFreeProc *freeProc) { fFreeProc=freeProc; }\n  void setFreeItem(bool doFree) { fFreeProc=(doFree)? &DefaultFreeProc : NULL; }\n  int Capacity() const { return fCapacity; } // table's size, including the empty slots.\n  void Resize(int m);  // Resize the table to the given size.\n  int Count() const { return fCount; }// the total number of entries in the table.\n  // Insert a new entry into the table given key and mark.\n  // If there is already an entry with that key, leave it unchanged,\n  const OBJ* Add(const char* ky, const OBJ* ptr=NULL, bool mrk=false);\n  //same as Add, but the key pointer is stored directly, no string duplicate\n  //is made (shared-key-Add)\n  const OBJ* shkAdd(const char* ky, const OBJ* ptr, bool mrk=false);\n\n  // Replace data at key, if the entry's mark is less than\n  // or equal to the given mark.  If there was no existing entry,\n  // a new entry is inserted with the given mark.\n  OBJ* Replace(const char* ky, const OBJ* ptr, bool mrk=false);\n  // Remove a given key and its data\n  OBJ* Remove(const char* ky);\n  // Find data OBJ* given key.\n  OBJ* Find(const char* ky, char** keyptr=NULL);\n  bool hasKey(const char* ky);\n  char* getLastKey() { return lastkeyptr; }\n  OBJ* operator[](const char* ky) { return Find(ky); }\n  void startIterate(); //iterator-like initialization\n  char* NextKey(); //returns next valid key in the table (NULL if no more)\n  OBJ* NextData(); //returns next valid hash[].data\n  OBJ* NextData(char*& nextkey); //returns next valid hash[].data\n                                //or NULL if no more\n                                //nextkey is SET to the corresponding key\n  GHashEntry* NextEntry() { //returns a pointer to a GHashEntry\n  \t register int pos=fCurrentEntry;\n  \t while (pos<fCapacity && hash[pos].hash<0) pos++;\n  \t if (pos==fCapacity) {\n  \t                 fCurrentEntry=fCapacity;\n  \t                 return NULL;\n  \t                 }\n  \t              else {\n  \t                 fCurrentEntry=pos+1;\n  \t                 return &hash[pos];\n  \t                 }\n  }\n  /// Clear all entries\n  void Clear();\n\n  /// Destructor\n  virtual ~GHash();\n  };\n//\n//======================== method definitions ========================\n//\n/*\n  Notes:\n  - The hash algorithm should yield a fCount in the range [0...GHash::EMPTY)\n     GHash::EMPTY and GHash::UNUSED are needed for flag purposes.\n  - Since the algorithm doubles the table size when exceeding MAX_LOAD,\n    it would be prudent to keep MIN_LOAD less than 1/2 MAX_LOAD;\n    otherwise, the algorithm might hip-hop between halving and doubling,\n    which would be quite expensive!!\n  - Not many people seem to know that hash tables don't have to be prime\n    numbers; in fact, a table size of 2**n and odd probe distance are very\n    easy to arrange, and this works just as well!\n  - We store the hash key, so that 99.999% of the time we can compare hash numbers;\n    only when hash numbers match do we need to compare keys.\n    Thus, with a good hash function, the fCount of calls to strcmp() should be\n    roughly the same as the fCount of successful lookups.\n  - The hash table should NEVER get full, or stuff will loop forever!!\n*/\n\n// Initial table size (MUST be power of 2)\n#define DEF_HASH_SIZE      32\n// Maximum hash table load factor (%)\n#define MAX_LOAD           80\n// Minimum hash table load factor (%)\n#define MIN_LOAD           10\n// Probe Position [0..n-1]\n#define HASH1(x,n) (((unsigned int)(x)*13)%(n))\n// Probe Distance [1..n-1]\n#define HASH2(x,n) (1|(((unsigned int)(x)*17)%((n)-1)))\n\n#define FREEDATA (fFreeProc!=NULL)\n\n/*******************************************************************************/\n// Construct empty hash\ntemplate <class OBJ> GHash<OBJ>::GHash(GFreeProc* freeProc) {\n  GMALLOC(hash, sizeof(GHashEntry)*DEF_HASH_SIZE);\n  fCurrentEntry=-1;\n  fFreeProc=freeProc;\n  lastkeyptr=NULL;\n  for (uint i=0; i<DEF_HASH_SIZE; i++)\n         hash[i].hash=-1; //this will be an indicator for 'empty' entries\n  fCapacity=DEF_HASH_SIZE;\n  fCount=0;\n  }\n\ntemplate <class OBJ> GHash<OBJ>::GHash(bool doFree) {\n  GMALLOC(hash, sizeof(GHashEntry)*DEF_HASH_SIZE);\n  fCurrentEntry=-1;\n  lastkeyptr=NULL;\n  fFreeProc = (doFree)?&DefaultFreeProc : NULL;\n  for (uint i=0; i<DEF_HASH_SIZE; i++)\n         hash[i].hash=-1; //this will be an indicator for 'empty' entries\n  fCapacity=DEF_HASH_SIZE;\n  fCount=0;\n  }\n\n\n// Resize table\ntemplate <class OBJ> void GHash<OBJ>::Resize(int m){\n  register int i,n,p,x,h;\n  GHashEntry *k;\n  GASSERT(fCount<=fCapacity);\n  if(m<DEF_HASH_SIZE) m=DEF_HASH_SIZE;\n  n=fCapacity;\n  while((n>>2)>m) n>>=1;            // Shrink until n/4 <= m\n  while((n>>1)<m) n<<=1;            // Grow until m <= n/2\n  GASSERT(m<=(n>>1));\n  GASSERT(DEF_HASH_SIZE<=n);\n  if(n!=fCapacity){\n    GASSERT(m<=n);\n    GMALLOC(k, sizeof(GHashEntry)*n);\n    for(i=0; i<n; i++) k[i].hash=-1;\n    for(i=0; i<fCapacity; i++){\n      h=hash[i].hash;\n      if(0<=h){\n        p=HASH1(h,n);\n        GASSERT(0<=p && p<n);\n        x=HASH2(h,n);\n        GASSERT(1<=x && x<n);\n        while(k[p].hash!=-1) p=(p+x)%n;\n        GASSERT(k[p].hash<0);\n        k[p]=hash[i];\n        }\n      }\n    GFREE(hash);\n    hash=k;\n    fCapacity=n;\n    }\n  }\n\n// add a new entry, or update it if it already exists\ntemplate <class OBJ> const OBJ* GHash<OBJ>::Add(const char* ky,\n                      const OBJ* pdata,bool mrk){\n  register int p,i,x,h,n;\n  if(!ky) GError(\"GHash::insert: NULL key argument.\\n\");\n  GASSERT(fCount<fCapacity);\n  h=strhash(ky);\n  GASSERT(0<=h);\n  p=HASH1(h,fCapacity);\n  GASSERT(0<=p && p<fCapacity);\n  x=HASH2(h,fCapacity);\n  GASSERT(1<=x && x<fCapacity);\n  i=-1;\n  n=fCapacity;\n  while(n && hash[p].hash!=-1){\n    if ((i==-1)&&(hash[p].hash==-2)) i=p;\n    if (hash[p].hash==h && strcmp(hash[p].key,ky)==0) {\n      //replace hash data for this key!\n      lastkeyptr=hash[p].key;\n      hash[p].data = (void*) pdata;\n      return (OBJ*)hash[p].data;\n      }\n    p=(p+x)%fCapacity;\n    n--;\n    }\n  if(i==-1) i=p;\n  GTRACE((\"GHash::insert: key=\\\"%s\\\"\\n\",ky));\n  //GMessage(\"GHash::insert: key=\\\"%s\\\"\\n\",ky);\n  GASSERT(0<=i && i<fCapacity);\n  GASSERT(hash[i].hash<0);\n  hash[i].hash=h;\n  hash[i].mark=mrk;\n  hash[i].key=Gstrdup(ky);\n  hash[i].keyalloc=true;\n  lastkeyptr=hash[i].key;\n  hash[i].data= (void*) pdata;\n  fCount++;\n  if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);\n  GASSERT(fCount<fCapacity);\n  return pdata;\n  }\n\ntemplate <class OBJ> const OBJ* GHash<OBJ>::shkAdd(const char* ky,\n                      const OBJ* pdata,bool mrk){\n  register int p,i,x,h,n;\n  if(!ky) GError(\"GHash::insert: NULL key argument.\\n\");\n  GASSERT(fCount<fCapacity);\n  h=strhash(ky);\n  GASSERT(0<=h);\n  p=HASH1(h,fCapacity);\n  GASSERT(0<=p && p<fCapacity);\n  x=HASH2(h,fCapacity);\n  GASSERT(1<=x && x<fCapacity);\n  i=-1;\n  n=fCapacity;\n  while(n && hash[p].hash!=-1){\n    if((i==-1)&&(hash[p].hash==-2)) i=p;\n    if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){\n      //replace hash data for this key!\n      lastkeyptr=hash[p].key;\n      hash[p].data = (void*) pdata;\n      return (OBJ*)hash[p].data;\n      }\n    p=(p+x)%fCapacity;\n    n--;\n    }\n  if(i==-1) i=p;\n  GTRACE((\"GHash::insert: key=\\\"%s\\\"\\n\",ky));\n  //GMessage(\"GHash::insert: key=\\\"%s\\\"\\n\",ky);\n  GASSERT(0<=i && i<fCapacity);\n  GASSERT(hash[i].hash<0);\n  hash[i].hash=h;\n  hash[i].mark=mrk;\n  hash[i].key=(char *)ky;\n  lastkeyptr=hash[i].key;\n  hash[i].keyalloc=false;\n  hash[i].data= (void*) pdata;\n  fCount++;\n  if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);\n  GASSERT(fCount<fCapacity);\n  return pdata;\n  }\n\n\n// Add or replace entry\ntemplate <class OBJ>  OBJ* GHash<OBJ>::Replace(const char* ky,const OBJ* pdata, bool mrk){\n  register int p,i,x,h,n;\n  if(!ky){ GError(\"GHash::replace: NULL key argument.\\n\"); }\n  GASSERT(fCount<fCapacity);\n  h=strhash(ky);\n  GASSERT(0<=h);\n  p=HASH1(h,fCapacity);\n  GASSERT(0<=p && p<fCapacity);\n  x=HASH2(h,fCapacity);\n  GASSERT(1<=x && x<fCapacity);\n  i=-1;\n  n=fCapacity;\n  while(n && hash[p].hash!=-1){\n    if((i==-1)&&(hash[p].hash==-2)) i=p;\n    if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){\n      if(hash[p].mark<=mrk){\n        GTRACE((\"GHash::replace: %08x: replacing: \\\"%s\\\"\\n\",this,ky));\n        if (FREEDATA) (*fFreeProc)(hash[p].data);\n        hash[p].mark=mrk;\n        hash[p].data=pdata;\n        }\n      return hash[p].data;\n      }\n    p=(p+x)%fCapacity;\n    n--;\n    }\n  if(i==-1) i=p;\n  GTRACE((\"GHash::replace: %08x: inserting: \\\"%s\\\"\\n\",this,ky));\n  GASSERT(0<=i && i<fCapacity);\n  GASSERT(hash[i].hash<0);\n  hash[i].hash=h;\n  hash[i].mark=mrk;\n  hash[i].key=Gstrdup(ky);\n  hash[i].data=pdata;\n  fCount++;\n  if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);\n  GASSERT(fCount<fCapacity);\n  return pdata;\n  }\n\n\n// Remove entry\ntemplate <class OBJ> OBJ* GHash<OBJ>::Remove(const char* ky){\n  register int p,x,h,n;\n  if(!ky){ GError(\"GHash::remove: NULL key argument.\\n\"); }\n  OBJ* removed=NULL;\n  if(0<fCount){\n    h=strhash(ky);\n    GASSERT(0<=h);\n    p=HASH1(h,fCapacity);\n    GASSERT(0<=p && p<fCapacity);\n    x=HASH2(h,fCapacity);\n    GASSERT(1<=x && x<fCapacity);\n    GASSERT(fCount<fCapacity);\n    n=fCapacity;\n    while(n && hash[p].hash!=-1){\n      if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){\n        GTRACE((\"GHash::remove: %08x removing: \\\"%s\\\"\\n\",this,ky));\n        hash[p].hash=-2;\n        hash[p].mark=false;\n        if (hash[p].keyalloc) GFREE((hash[p].key));\n        if (FREEDATA) (*fFreeProc)(hash[p].data);\n            else removed=(OBJ*)hash[p].data;\n        hash[p].key=NULL;\n        hash[p].data=NULL;\n        fCount--;\n        if((100*fCount)<=(MIN_LOAD*fCapacity)) Resize(fCount);\n        GASSERT(fCount<fCapacity);\n        return removed;\n        }\n      p=(p+x)%fCapacity;\n      n--;\n      }\n    }\n  return removed;\n  }\n\n\n// Find entry\ntemplate <class OBJ> bool GHash<OBJ>::hasKey(const char* ky) {\n  register int p,x,h,n;\n  if(!ky){ GError(\"GHash::find: NULL key argument.\\n\"); }\n  if(0<fCount){\n    h=strhash(ky);\n    GASSERT(0<=h);\n    p=HASH1(h,fCapacity);\n    GASSERT(0<=p && p<fCapacity);\n    x=HASH2(h,fCapacity);\n    GASSERT(1<=x && x<fCapacity);\n    GASSERT(fCount<fCapacity);\n    n=fCapacity;\n    while(n && hash[p].hash!=-1){\n      if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){\n        return true;\n        }\n      p=(p+x)%fCapacity;\n      n--;\n      }\n    }\n  return false;\n}\n\ntemplate <class OBJ> OBJ* GHash<OBJ>::Find(const char* ky, char** keyptr){\n  register int p,x,h,n;\n  if(!ky){ GError(\"GHash::find: NULL key argument.\\n\"); }\n  if(0<fCount){\n    h=strhash(ky);\n    GASSERT(0<=h);\n    p=HASH1(h,fCapacity);\n    GASSERT(0<=p && p<fCapacity);\n    x=HASH2(h,fCapacity);\n    GASSERT(1<=x && x<fCapacity);\n    GASSERT(fCount<fCapacity);\n    n=fCapacity;\n    while(n && hash[p].hash!=-1){\n      if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){\n        if (keyptr!=NULL) *keyptr = hash[p].key;\n        return (OBJ*)hash[p].data;\n        }\n      p=(p+x)%fCapacity;\n      n--;\n      }\n    }\n  return NULL;\n  }\n\n\ntemplate <class OBJ> void GHash<OBJ>::startIterate() {// initialize a key iterator; call\n fCurrentEntry=0;\n}\n\ntemplate <class OBJ> char* GHash<OBJ>::NextKey() {\n register int pos=fCurrentEntry;\n while (pos<fCapacity && hash[pos].hash<0) pos++;\n if (pos==fCapacity) {\n                 fCurrentEntry=fCapacity;\n                 return NULL;\n                 }\n              else {\n                 fCurrentEntry=pos+1;\n                 return hash[pos].key;\n                 }\n}\n\ntemplate <class OBJ> OBJ* GHash<OBJ>::NextData() {\n register int pos=fCurrentEntry;\n while (pos<fCapacity && hash[pos].hash<0) pos++;\n if (pos==fCapacity) {\n                 fCurrentEntry=fCapacity;\n                 return NULL;\n                 }\n              else {\n                 fCurrentEntry=pos+1;\n                 return (OBJ*)hash[pos].data;\n                 }\n\n}\n\ntemplate <class OBJ> OBJ* GHash<OBJ>::NextData(char* &nextkey) {\n register int pos=fCurrentEntry;\n while (pos<fCapacity && hash[pos].hash<0) pos++;\n if (pos==fCapacity) {\n                 fCurrentEntry=fCapacity;\n                 nextkey=NULL;\n                 return NULL;\n                 }\n              else {\n                 fCurrentEntry=pos+1;\n                 nextkey=hash[pos].key;\n                 return (OBJ*)hash[pos].data;\n                 }\n\n}\n\n\n// Get first non-empty entry\ntemplate <class OBJ> int GHash<OBJ>::First() const {\n  register int pos=0;\n  while(pos<fCapacity){ if(0<=hash[pos].hash) break; pos++; }\n  GASSERT(fCapacity<=pos || 0<=hash[pos].hash);\n  return pos;\n  }\n\n// Get last non-empty entry\ntemplate <class OBJ> int GHash<OBJ>::Last() const {\n  register int pos=fCapacity-1;\n  while(0<=pos){ if(0<=hash[pos].hash) break; pos--; }\n  GASSERT(pos<0 || 0<=hash[pos].hash);\n  return pos;\n  }\n\n\n// Find next valid entry\ntemplate <class OBJ> int GHash<OBJ>::Next(int pos) const {\n  GASSERT(0<=pos && pos<fCapacity);\n  while(++pos <= fCapacity-1){ if(0<=hash[pos].hash) break; }\n  GASSERT(fCapacity<=pos || 0<=hash[pos].hash);\n  return pos;\n  }\n\n\n// Find previous valid entry\ntemplate <class OBJ> int GHash<OBJ>::Prev(int pos) const {\n  GASSERT(0<=pos && pos<fCapacity);\n  while(--pos >= 0){ if(0<=hash[pos].hash) break; }\n  GASSERT(pos<0 || 0<=hash[pos].hash);\n  return pos;\n  }\n\n\n// Remove all\ntemplate <class OBJ> void GHash<OBJ>::Clear(){\n  register int i;\n  for(i=0; i<fCapacity; i++){\n    if(hash[i].hash>=0){\n      if (hash[i].keyalloc) GFREE((hash[i].key));\n      if (FREEDATA)\n            (*fFreeProc)(hash[i].data);\n      }\n    }\n  GFREE(hash);\n  GMALLOC(hash, sizeof(GHashEntry)*DEF_HASH_SIZE);\n  //reinitialize it\n  for (i=0; i<DEF_HASH_SIZE; i++)\n         hash[i].hash=-1; //this will be an indicator for 'empty' entries\n  fCapacity=DEF_HASH_SIZE;\n  fCount=0;\n  }\n\n\n// Save data\n/*\nvoid GHash::Save(Stream& store) const {\n  Object::save(store);\n  store << fCapacity;\n  store << fCount;\n  for(int i=0; i<fCapacity; i++){\n    store << hash[i].hash;\n    if(hash[i].hash>=0){\n      uint len=strlen(hash[i].key);\n      store << len;\n      store << hash[i].mark;\n      store.save(hash[i].key,len);\n      }\n    }\n  }\n\n\n// Load data\nvoid GHash::Load(Stream& store){\n  Object::load(store);\n  store >> fCapacity;\n  store >> fCount;\n  for(int i=0; i<fCapacity; i++){\n    store >> hash[i].hash;\n    if(hash[i].hash>=0){\n      uint len;\n      store >> len;\n      store >> hash[i].mark;\n      GMALLOC(hash[i].key,len+1);\n      store.load(hash[i].key,len);\n      hash[i].key[len]='\\0';\n      }\n    }\n  }\n*/\n\n// Destroy table\ntemplate <class OBJ> GHash<OBJ>::~GHash(){\n  register int i;\n  for(i=0; i<fCapacity; i++){\n    if(hash[i].hash>=0){\n      if (hash[i].keyalloc) GFREE((hash[i].key));\n      if (FREEDATA) (*fFreeProc)(hash[i].data);\n      }\n    }\n  GFREE(hash);\n  }\n\n#endif\n"
  },
  {
    "path": "src/GList.hh",
    "content": "//---------------------------------------------------------------------------\n/*\nSortable collections of objects and object pointers\n*/\n#ifndef _GList_HH\n#define _GList_HH\n\n#include \"GVec.hh\"\n\n#define GLIST_SORTED_ERR \"Operation not allowed on a sorted list!\\n\"\n#define GLIST_UNSORTED_ERR \"Operation not allowed on an unsorted list!\\n\"\n\n//------ useful macros:\n#define BE_UNSORTED if (fCompareProc!=NULL) { GError(GLIST_SORTED_ERR); return; }\n#define BE_SORTED if (fCompareProc==NULL) { GError(GLIST_UNSORTED_ERR); return; }\n\n#define SORTED (fCompareProc!=NULL)\n#define UNSORTED (fCompareProc==NULL)\n\n// GArray is the sortable array type, requires the comparison operator < to be defined\ntemplate <class OBJ> class GArray:public GVec<OBJ> {\n  protected:\n    bool fUnique;\n    static int DefaultCompareProc(const pointer item1, const pointer item2) {\n      //operator< MUST be defined for OBJ class!\n      if (*((OBJ*)item2) < *((OBJ*)item1)) return 1;\n        else if (*((OBJ*)item1) < *((OBJ*)item2)) return -1;\n                                             else return  0;\n      }\n    GCompareProc* fCompareProc;\n  public:\n    GArray(GCompareProc* cmpFunc=NULL);\n    GArray(bool sorted, bool unique=false);\n    GArray(int init_capacity, bool sorted, bool unique=false);\n    GArray(GArray<OBJ>& array); //copy constructor\n    const GArray<OBJ>& operator=(GArray<OBJ>& array);\n    //~GArray();\n    //assignment operator\n    void setSorted(GCompareProc* cmpFunc);\n    void setSorted(bool sorted) {\n     if (sorted) {\n         if (fCompareProc!=&DefaultCompareProc) {\n             fCompareProc=&DefaultCompareProc;\n             Sort();\n             }\n          }\n      else fCompareProc=NULL;\n      }\n    //sort the array if cmpFunc not NULL or changes\n    int Add(OBJ* item); // specific implementation if sorted\n    int Add(OBJ& item) { return Add(&item); } //both will CREATE a new OBJ and COPY to it\n                       // using OBJ new operator=\n    int cAdd(OBJ item) { return Add(&item); }\n    int cPush(OBJ item) { return Add(&item); }\n    int Push(OBJ& item) { return Add(&item); }\n\n    void Add(GArray<OBJ>& list); //add copies of all items from another list\n    //this will reject identical items in sorted lists only!\n    void setUnique(bool beUnique) { fUnique = beUnique; };\n    void Sort(); //explicit sort may be requested\n    bool Sorted() { return fCompareProc!=NULL; }\n    void Replace(int idx, OBJ& item); //Put, use operator= to copy\n    int  Unique() { return fUnique; }\n    int IndexOf(OBJ& item);\n         //this needs the == operator to have been defined for OBJ\n    bool Found(OBJ& item, int& idx); // for sorted arrays only;\n         //search by content; if found, returns true and idx will be the index\n         //of the first item found matching for which fCompareProc returns 0\n    bool Exists(OBJ& item); //same as above without existing index info\n    //unsorted only, place item at position idx:\n    void Move(int curidx, int newidx);\n    void Insert(int idx, OBJ* item);\n    void Insert(int idx, OBJ item) { Insert(idx,&item); }\n};\n\n//GList is a sortable collection of pointers to objects; requires operator< to be defined, or a custom compare function\ntemplate <class OBJ> class GList:public GPVec<OBJ> {\n  protected:\n    bool fUnique;\n    GCompareProc* fCompareProc; //a pointer to a Compare function\n    \n    static int DefaultCompareProc(const pointer item1, const pointer item2) {\n      //operator< MUST be defined for OBJ class!\n      if (*((OBJ*)item2) < *((OBJ*)item1)) return 1;\n        else if (*((OBJ*)item1) < *((OBJ*)item2)) return -1;\n                                             else return  0;\n      }\n  public:\n    void sortInsert(int idx, OBJ* item); //special insert in sorted lists\n         //WARNING: the caller must know the insert index such that the sort order is preserved!\n    GList(GCompareProc* compareProc=NULL); //free by default\n    GList(GCompareProc* compareProc, //unsorted by default\n        GFreeProc *freeProc,\n        bool beUnique=false);\n    GList(bool sorted, bool free_elements=true, bool beUnique=false);\n    GList(int init_capacity, bool sorted, bool free_elements=true, bool beUnique=false);\n    GList(GList<OBJ>& list); //copy constructor?\n    GList(GList<OBJ>* list); //kind of a copy constructor\n    const GList<OBJ>& operator=(GList<OBJ>& list);\n    //void Clear();\n    //~GList();\n    void setSorted(GCompareProc* compareProc);\n       //sorted if compareProc not NULL; sort the list if compareProc changes !\n    bool Sorted() { return fCompareProc!=NULL; }\n    void setSorted(bool sorted) {\n     if (sorted) {\n         if (fCompareProc!=&DefaultCompareProc) {\n             fCompareProc=&DefaultCompareProc;\n             Sort();\n             }\n          }\n      else fCompareProc=NULL;\n      }\n    int Add(OBJ* item); //-- specific implementation if sorted - may become an Insert()\n    void Add(GList<OBJ>& list); //add all pointers from another list\n\n    OBJ* AddIfNew(OBJ* item, bool deleteIfFound=true, int* fidx=NULL);\n    // default: delete item if Found() (and pointers are not equal)!\n    //returns the equal (==) object if it's in the list already\n    //or the item itself if it is unique and actually added\n\n    int AddedIfNew(OBJ* item);\n    // if Found(item) (and pointers are not equal) delete item and returns -1\n    // if added, returns the new item index\n\n\n    int Unique() { return fUnique; }\n    //this will reject identical items in sorted lists only!\n    void setUnique(bool beUnique) { fUnique = beUnique; };\n\n    GCompareProc* GetCompareProc() {return fCompareProc;}\n    int IndexOf(OBJ* item); //this has a specific implementation for sorted lists\n               //if list is sorted, item data is located by binary search\n               //based on the Compare function\n               //if not, a linear search is performed, but\n               //this needs the == operator to have been defined for OBJ\n    \n    void Put(int idx, OBJ* item, bool re_sort=false);\n    bool Found(OBJ* item, int & idx); // sorted only;\n               //search by content; if found, returns true and idx will be the index\n               //of the first item found matching for which GTCompareProc returns 0\n    bool Exists(OBJ* item); //same as above without existing index info\n    bool Exists(OBJ& item); //same as above without existing index info\n    void Sort(); //explicit sort may be requested using this function\n    int Remove(OBJ* item); //search for pointer, using binary search if sorted\n    void Insert(int idx, OBJ* item); //unsorted only, place item at position idx\n    void Move(int curidx, int newidx);\n}; //GList \n\n\n\n//-------------------- TEMPLATE IMPLEMENTATION-------------------------------\n\ntemplate <class OBJ> GArray<OBJ>::GArray(GArray<OBJ>& array):GVec<OBJ>(0) { //copy constructor\n this->fCount=array.fCount;\n this->fCapacity=array.fCapacity;\n this->fArray=NULL;\n if (this->fCapacity>0) {\n    //GMALLOC(this->fArray, this->fCapacity*sizeof(OBJ));\n    this->fArray=new OBJ[this->fCapacity];\n    }\n this->fCount=array.fCount;\n fUnique=array.fUnique;\n fCompareProc=array.fCompareProc;\n // uses OBJ operator=\n for (int i=0;i<this->fCount;i++) this->fArray[i]=array[i];\n }\n\ntemplate <class OBJ> const GArray<OBJ>& GArray<OBJ>::operator=(GArray<OBJ>& array) {\n if (&array==this) return *this;\n GVec<OBJ>::Clear();\n this->fCount=array.fCount;\n this->fUnique=array.fUnique;\n this->fCapacity=array.fCapacity;\n if (this->fCapacity>0) {\n    //GMALLOC(this->fArray, this->fCapacity*sizeof(OBJ));\n    this->fArray=new OBJ[this->fCapacity];\n    }\n this->fCompareProc=array.fCompareProc;\n this->fCount=array.fCount;\n // uses OBJ operator=\n for (int i=0;i<this->fCount;i++) {\n   this->fArray[i]=array[i];\n   }\n return *this;\n}\n\ntemplate <class OBJ> GArray<OBJ>::GArray(GCompareProc* cmpFunc):GVec<OBJ>(0) {\n  fCompareProc = cmpFunc;\n  fUnique = false; //only affects sorted lists\n}\n\ntemplate <class OBJ> GArray<OBJ>::GArray(bool sorted, bool unique):GVec<OBJ>(0) {\n  fUnique=unique;\n  fCompareProc = sorted ? DefaultCompareProc : NULL;\n}\n\ntemplate <class OBJ> GArray<OBJ>::GArray(int init_capacity,\n                        bool sorted, bool unique):GVec<OBJ>(init_capacity) {\n  fUnique=unique;\n  fCompareProc=sorted ? DefaultCompareProc : NULL;\n}\n\ntemplate <class OBJ> void GArray<OBJ>::setSorted(GCompareProc* cmpFunc) {\n  GCompareProc* old_proc=fCompareProc;\n  fCompareProc=cmpFunc;\n  if (fCompareProc!=old_proc && fCompareProc!=NULL)\n       Sort(); //new compare method\n}\n\ntemplate <class OBJ> int GArray<OBJ>::IndexOf(OBJ& item) {\n int result=0;\n if (Found(item, result)) return result;\n                     else return -1;\n }\n\ntemplate <class OBJ> bool GArray<OBJ>::Exists(OBJ& item) {\n int result=0;\n if (Found(item, result)) return true;\n                     else return false;\n }\n\n\ntemplate <class OBJ> int GArray<OBJ>::Add(OBJ* item) {\n if (item==NULL) return -1;\n int result;\n if (SORTED) {\n   if (Found(*item, result))\n      if (fUnique) return -1; //cannot add a duplicate!\n   //Found sets result to the position where the item should be!\n   GVec<OBJ>::Insert(result, *item);\n   }\n  else {\n   if (fUnique && Found(*item,result)) return -1; //set behaviour\n   result = this->fCount;\n   if (result==this->fCapacity) GVec<OBJ>::Grow();\n   this->fArray[result] = *item; //operator=, copies the item\n   this->fCount++;\n   }\n return result;\n}\n\n\ntemplate <class OBJ> void GArray<OBJ>::Add(GArray<OBJ>& list) {\n  if (list.Count()==0) return;\n  if (SORTED) {\n    for (int i=0;i<list.fCount;i++) Add(&list[i]);\n    }\n  else { //simply copy\n    this->setCapacity(this->fCapacity+list.fCount);\n    int s=this->fCount;\n    for (int i=0;i<list.fCount;i++)\n           this->fArray[s+i]=list.fArray[i];\n    this->fCount+=list.fCount;\n    }\n}\n\ntemplate <class OBJ> bool GArray<OBJ>::Found(OBJ& item, int& idx) {\n //search the list by using fCompareProc (if defined)\n //or == operator for a non-sortable list\n //for sorted lists, even when the result is false, the idx is\n //set to the closest matching object!\n int i;\n idx=-1;\n if (this->fCount==0) { idx=0;return false;}\n if (SORTED) { //binary search based on fCompareProc\n   //do the simplest tests first:\n   if ((*fCompareProc)(&(this->fArray[0]),&item)>0) {\n                       idx=0;\n                       return false;\n                       }\n   if ((*fCompareProc)(&item, &(this->fArray[this->fCount-1]))>0) {\n                       idx=this->fCount;\n                       return false;\n                       }\n\n   int l=0;\n   int h = this->fCount - 1;\n   int c;\n   while (l <= h) {\n       i = (l + h) >> 1;\n       c = (*fCompareProc)(&(this->fArray[i]), &item);\n       if (c < 0)  l = i + 1;\n         else {\n            h = i - 1;\n            if (c == 0) { //found!\n                 idx=i;\n                 return true;\n                }\n            }\n       } //while\n   idx = l;\n   return false;\n   }\n else {//not sorted: use linear search\n   // needs == operator to compare user defined objects !\n   i=0;\n   while (i<this->fCount) {\n      if (this->fArray[i]==item) { //requires operator==\n         idx=i;\n         return true;\n         }\n      i++;\n      }\n   return false;\n   }\n}\n\ntemplate <class OBJ> void GArray<OBJ>::Insert(int idx, OBJ* item) {\n //idx can be [0..fCount] so an item can be actually added\n BE_UNSORTED; //forbid this operation on sorted data\n GVec<OBJ>::Insert(idx, item);\n}\n\n\ntemplate <class OBJ> void GArray<OBJ>::Move(int curidx, int newidx) {\n BE_UNSORTED; //cannot do this in a sorted list!\n if (curidx!=newidx || newidx>=this->fCount)\n     GError(GVEC_INDEX_ERR, newidx);\n\n OBJ tmp=this->fArray[curidx]; //copy constructor here\n this->fArray[curidx]=this->fArray[newidx];\n this->fArray[newidx]=tmp;\n}\n\ntemplate <class OBJ> void GArray<OBJ>::Replace(int idx, OBJ& item) {\n //TEST_INDEX(idx);\n if (idx<0 || idx>=this->fCount) GError(GVEC_INDEX_ERR, __FILE__,__LINE__, idx);\n this->fArray[idx]=item;\n if ( SORTED ) Sort(); //re-sort ! this could be very expensive, don't do it\n}\n\ntemplate <class OBJ> void GArray<OBJ>::Sort() {\n if (fCompareProc==NULL) { fCompareProc=DefaultCompareProc; }\n if (this->fArray!=NULL && this->fCount>0)\n     this->qSort(0, this->fCount-1, fCompareProc);\n}\n\n//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n//*=> GList implementation -- sortable array of pointers to OBJ\n\ntemplate <class OBJ> GList<OBJ>::GList(GList<OBJ>& list):GPVec<OBJ>(list) { //copy constructor\n fUnique=list.fUnique;\n fCompareProc=list.fCompareProc;\n}\n\ntemplate <class OBJ> GList<OBJ>::GList(GList<OBJ>* plist):GPVec<OBJ>(0) { //another copy constructor\n this->fCapacity=plist->fCapacity;\n this->fList=NULL;\n if (this->fCapacity>0) {\n     GMALLOC(this->fList, this->fCapacity*sizeof(OBJ*));\n     }\n fUnique=plist->fUnique;\n fCompareProc=plist->fCompareProc;\n this->fFreeProc=plist->fFreeProc;\n this->fCount=plist->fCount;\n memcpy(this->fList, plist->fList, this->fCount*sizeof(OBJ*));\n //for (int i=0;i<list->fCount;i++) Add(plist->Get(i));\n}\n\ntemplate <class OBJ> void GList<OBJ>::Add(GList<OBJ>& list) {\n  if (list.Count()==0) return;\n  if (SORTED) {\n    for (int i=0;i<list.Count();i++) Add(list[i]);\n    }\n  else { //simply copy\n    this->setCapacity(this->fCapacity+list.fCount);\n    memcpy( & (this->fList[this->fCount]), list.fList, list.fCount*sizeof(OBJ*));\n    this->fCount+=list.fCount;\n    }\n}\n\n\ntemplate <class OBJ> GList<OBJ>::GList(GCompareProc* compareProc,\n       GFreeProc* freeProc, bool beUnique) {\n  fCompareProc = compareProc;\n  this->fFreeProc    = freeProc;\n  fUnique = beUnique; //only affects sorted lists\n}\n\ntemplate <class OBJ> GList<OBJ>::GList(GCompareProc* compareProc) {\n  fCompareProc = compareProc;\n  this->fFreeProc = GPVec<OBJ>::DefaultFreeProc;\n  fUnique = false; //only affects sorted lists\n}\n\ntemplate <class OBJ> GList<OBJ>::GList(bool sorted,\n    bool free_elements, bool beUnique) {\n  if (sorted) {\n     if (free_elements) {\n        fCompareProc=&DefaultCompareProc;\n        this->fFreeProc = GPVec<OBJ>::DefaultFreeProc;\n        fUnique=beUnique;\n        }\n       else {\n        fCompareProc=&DefaultCompareProc;\n        this->fFreeProc=NULL;\n        fUnique=beUnique;\n        }\n     }\n   else {\n     if (free_elements) {\n        fCompareProc=NULL;\n        this->fFreeProc=GPVec<OBJ>::DefaultFreeProc;\n        fUnique=beUnique;\n        }\n      else {\n        fCompareProc=NULL;\n        this->fFreeProc=NULL;\n        fUnique=beUnique;\n        }\n     }\n}\n\n\ntemplate <class OBJ> GList<OBJ>::GList(int init_capacity, bool sorted,\n    bool free_elements, bool beUnique):GPVec<OBJ>(init_capacity, free_elements) {\n  if (sorted) {\n      fCompareProc=&DefaultCompareProc;\n      fUnique=beUnique;\n      }\n   else {\n      fCompareProc=NULL;\n      fUnique=beUnique;\n      }\n}\n\ntemplate <class OBJ> const GList<OBJ>& GList<OBJ>::operator=(GList& list) {\n if (&list!=this) {\n     GPVec<OBJ>::Clear();\n     fCompareProc=list.fCompareProc;\n     this->fFreeProc=list.fFreeProc;\n     //Attention: the object pointers are copied directly,\n     //but the actual objects are NOT duplicated\n     for (int i=0;i<list.Count();i++) Add(list[i]);\n     }\n return *this;\n}\n\ntemplate <class OBJ> void GList<OBJ>::setSorted(GCompareProc* compareProc) {\n GCompareProc* old_proc=fCompareProc;\n fCompareProc=compareProc;\n if (fCompareProc!=old_proc && fCompareProc!=NULL)\n       Sort(); //new compare method\n}\n\ntemplate <class OBJ> int GList<OBJ>::IndexOf(OBJ* item) {\n int result=0;\n if (Found(item, result)) return result;\n                     else return -1;\n }\n\ntemplate <class OBJ> bool GList<OBJ>::Exists(OBJ& item) {\n int result=0;\n if (Found(&item, result)) return true;\n                      else return false;\n }\n\ntemplate <class OBJ> bool GList<OBJ>::Exists(OBJ* item) {\n int result=0;\n if (Found(item, result)) return true;\n                      else return false;\n }\n\ntemplate <class OBJ> int GList<OBJ>::Add(OBJ* item) {\n int result;\n if (item==NULL) return -1;\n if (SORTED) {\n   if (Found(item, result))\n      if (fUnique) return -1; //duplicates forbidden\n   //Found sets result to the position where the item should be!\n   sortInsert(result, item);\n   }\n  else {\n   if (fUnique && Found(item,result)) return -1; //set behaviour\n   result = this->fCount;\n   if (result==this->fCapacity) GPVec<OBJ>::Grow();\n   this->fList[result]=item;\n   this->fCount++;\n   }\n return result;\n}\n\n//by default, it deletes the item if it has an equal in the list!\n//returns the existing equal (==) object if it's in the list already\n//or returns the item itself if it's unique (and adds it)\ntemplate <class OBJ> OBJ* GList<OBJ>::AddIfNew(OBJ* item,\n                                     bool deleteIfFound, int* fidx) {\n int r;\n if (Found(item, r)) {\n    if (deleteIfFound && (pointer)item != (pointer)(this->fList[r])) {\n       this->deallocate_item(item);\n       }\n    if (fidx!=NULL) *fidx=r;\n    return this->fList[r]; //found\n    }\n //not found:\n if (SORTED) {\n   //Found() set result to the position where the item should be inserted:\n   sortInsert(r, item);\n   }\n  else {\n   r = this->fCount;\n   if (r==this->fCapacity) GPVec<OBJ>::Grow();\n   this->fList[r]=item;\n   this->fCount++;\n   }\n if (fidx!=NULL) *fidx=r;\n return item;\n}\n\n//if item is found already in the list DELETE it and return -1\n//otherwise the item is added and its index is returned\ntemplate <class OBJ> int GList<OBJ>::AddedIfNew(OBJ* item) {\n int r;\n if (Found(item, r)) {\n    if ((pointer)item != (pointer)(this->fList[r])) {\n        this->deallocate_item(item);\n        }\n    return -1;\n    }\n //not found:\n if (SORTED) {\n   //Found() set r to the position where the item should be inserted:\n   sortInsert(r, item);\n   }\n  else {\n   r = this->fCount;\n   if (r==this->fCapacity) GPVec<OBJ>::Grow();\n   this->fList[r]=item;\n   this->fCount++;\n   }\n return r;\n}\n\n\ntemplate <class OBJ> bool GList<OBJ>::Found(OBJ* item, int& idx) {\n //search the list by using fCompareProc (if defined)\n //or == operator for a non-sortable list\n //for sorted lists, even when the result is false, the idx is\n //set to the closest matching object!\n int i;\n idx=-1;\n if (this->fCount==0) { idx=0;return false;}\n if (SORTED) { //binary search based on fCompareProc\n   //do the simple test first:\n\n   if ((*fCompareProc)(this->fList[0],item)>0) {\n                       idx=0;\n                       return false;\n                       }\n   if ((*fCompareProc)(item, this->fList[this->fCount-1])>0) {\n                       idx=this->fCount;\n                       return false;\n                       }\n\n   int l, h, c;\n   l = 0;\n   h = this->fCount - 1;\n   while (l <= h) {\n       i = (l + h) >> 1;\n       c = (*fCompareProc)(this->fList[i], item);\n       if (c < 0)  l = i + 1;\n         else {\n            h = i - 1;\n            if (c == 0) {\n                 idx=i;\n                 return true;\n                }\n            }\n       } //while\n   idx = l;\n   return false;\n   }\n else {//not sorted: use linear search\n   // needs == operator to compare user defined objects !\n   i=0;\n   while (i<this->fCount) {\n      if (*this->fList[i]==*item) {\n         idx=i;\n         return true;\n         }\n      i++;\n      }\n   return false;\n   }\n}\n\ntemplate <class OBJ> void GList<OBJ>::sortInsert(int idx, OBJ* item) {\n //idx must be the new position this new item must have\n //so the allowed range is [0..fCount]\n //the current fList[idx] and all the above will be shifted +1\n if (idx<0 || idx>this->fCount) GError(GVEC_INDEX_ERR, idx);\n if (this->fCount==this->fCapacity) {\n    GPVec<OBJ>::Grow(idx, item);\n    //expand and also copy/move data and insert the new item\n    return;\n    }\n //room still left, just move data around and insert the new one\n if (idx<this->fCount) //copy/move pointers only!\n      memmove(&(this->fList[idx+1]), &(this->fList[idx]), (this->fCount-idx)*sizeof(OBJ*));\n this->fList[idx]=item;\n this->fCount++;\n}\n\ntemplate <class OBJ> void GList<OBJ>::Insert(int idx, OBJ* item) {\n //idx can be [0..fCount] so an item can be actually added\n BE_UNSORTED; //cannot do that with a sorted list!\n GPVec<OBJ>::Insert(idx,item);\n}\n\ntemplate <class OBJ> void GList<OBJ>::Move(int curidx, int newidx) {\n BE_UNSORTED; //cannot do this in a sorted list!\n GPVec<OBJ>::Move(curidx,newidx);\n}\n\ntemplate <class OBJ> void GList<OBJ>::Put(int idx, OBJ* item, bool re_sort) {\n //WARNING: this will never free the replaced item!\n // this may BREAK the sort order unless the \"re_sort\" parameter is given\n if (idx<0 || idx>this->fCount) GError(GVEC_INDEX_ERR, idx);\n this->fList[idx]=item;\n if (SORTED && item!=NULL && re_sort) Sort(); //re-sort\n}\n\ntemplate <class OBJ> int GList<OBJ>::Remove(OBJ* item) {\n//removes an item if it's in our list\n int result=IndexOf(item);\n if (result>=0) GPVec<OBJ>::Delete(result);\n return result;\n}\n\ntemplate <class OBJ> void GList<OBJ>::Sort() {\n if (fCompareProc==NULL) fCompareProc = DefaultCompareProc;\n if (this->fList!=NULL && this->fCount>0)\n     this->qSort(0, this->fCount-1, fCompareProc);\n}\n\n//---------------------------------------------------------------------------\n#endif\n"
  },
  {
    "path": "src/GStr.cpp",
    "content": "//---------------------------------------------------------------------------\n#include \"GStr.h\"\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include \"GBase.h\"\n#include <stdarg.h>\n#include <errno.h>\n\n//---------------------------------------------------------------------------\n\nGStr::Data GStr::null_data;\n\n//=========================================\n\nGStr::Data * GStr::new_data(int length) {\n//static method to return a new Data object (allocate length)\n//content is undefined, but it's null terminated\n    if (length > 0) {\n        Data* data;\n        GMALLOC(data, sizeof(Data)+length);\n        data->ref_count = 0;\n        data->length = length;\n        data->chars[length] = '\\0';\n        return data;\n        }\n    else\n        return &null_data;\n }\n\nGStr::Data* GStr::new_data(const char* str) {\n//static method to return a new Data object (allocate length)\n//as a copy of a given string\n if (str==NULL) return &null_data;\n int length=strlen(str);\n if (length > 0) {\n        Data* data;\n        GMALLOC(data, sizeof(Data)+length);\n        strcpy(data->chars, str);\n        data->ref_count = 0;\n        data->length = length;\n        data->chars[length] = '\\0';\n        return data;\n        }\n    else\n        return &null_data;\n }\n \nvoid GStr::replace_data(int len) {\n\n    if (len == my_data->length && my_data->ref_count <= 1)\n        return;\n\n    if (my_data != &null_data && --my_data->ref_count == 0)\n        GFREE(my_data);\n\n    if (len > 0) {\n        //my_data = (Data *) malloc(sizeof(Data) + len);\n        GMALLOC(my_data, sizeof(Data) + len);\n        my_data->ref_count = 1;\n        my_data->length = len;\n        my_data->chars[len] = '\\0';\n    }\n    else\n        my_data = &null_data;\n}\n\nvoid GStr::replace_data(Data *data) {\n    if (my_data != &null_data && --my_data->ref_count == 0)\n        GFREE(my_data);\n    if (data != &null_data)\n        data->ref_count++;\n    my_data = data;\n}\n\nvoid GStr::make_unique() {//make sure it's not a reference to other string\n    if (my_data->ref_count > 1) {\n        Data *data = new_data(length());\n        ::memcpy(data->chars, chars(), length());\n        my_data->ref_count--;\n        my_data = data;\n        my_data->ref_count++;\n    }\n}\n\nbool operator==(const char *s1, const GStr& s2){\n  if (s1==NULL) return s2.is_empty();\n  return (strcmp(s1, s2.chars()) == 0);\n  }\n\nbool operator<(const char *s1, const GStr& s2) {\n  if (s1==NULL) return !s2.is_empty();\n  return (strcmp(s1, s2.chars()) < 0);\n  }\n\nbool operator<=(const char *s1, const GStr& s2){\n if (s1==NULL) return true;\n return (strcmp(s1, s2.chars()) <= 0);\n }\n\nbool operator>(const char *s1, const GStr& s2) {\n  if (s1==NULL) return false;\n return (strcmp(s1, s2.chars()) > 0);\n }\n\n\nGStr::GStr():my_data(&null_data) {\n fTokenDelimiter=NULL;\n fTokenizeMode=tkCharSet;\n fLastTokenStart=0;\n readbuf=NULL;\n readbufsize=0;\n }\n\nGStr::GStr(const GStr& s): my_data(&null_data){\n fTokenDelimiter=NULL;\n fTokenizeMode=tkCharSet;\n fLastTokenStart=0;\n readbuf=NULL;\n readbufsize=0;\n replace_data(s.my_data);\n }\n\nGStr::GStr(const char *s): my_data(&null_data) {\n  fTokenDelimiter=NULL;\n  fTokenizeMode=tkCharSet;\n  fLastTokenStart=0;\n  readbuf=NULL;\n  readbufsize=0;\n  my_data=new_data(s);\n  my_data->ref_count = 1;\n }\n\nGStr::GStr(const int i): my_data(&null_data) {\n fTokenDelimiter=NULL;\n fTokenizeMode=tkCharSet;\n fLastTokenStart=0;\n readbuf=NULL;\n readbufsize=0;\n char buf[20];\n sprintf(buf,\"%d\",i);\n const int len = ::strlen(buf);\n replace_data(len);\n ::memcpy(chrs(), buf, len);\n }\n\nGStr::GStr(const double f): my_data(&null_data) {\n fTokenDelimiter=NULL;\n fTokenizeMode=tkCharSet;\n fLastTokenStart=0;\n readbuf=NULL;\n readbufsize=0;\n char buf[20];\n sprintf(buf,\"%f\",f);\n const int len = ::strlen(buf);\n replace_data(len);\n ::memcpy(chrs(), buf, len);\n }\n\nGStr::GStr(char c, int n): my_data(&null_data) {\n  fTokenDelimiter=NULL;\n  fTokenizeMode=tkCharSet;\n  fLastTokenStart=0;\n  readbuf=NULL;\n  readbufsize=0;\n  replace_data(n); ::memset(chrs(), c, n);\n  }\n\nGStr::~GStr() {  \n  if (my_data != &null_data && --my_data->ref_count == 0)\n             GFREE(my_data);\n  GFREE(fTokenDelimiter);\n  GFREE(readbuf);\n  }\n\nchar& GStr::operator[](int idx){\n//returns reference to char (can be l-value)\n  if (idx < 0) idx += length();\n  if (idx < 0 || idx >= length()) invalid_index_error(\"operator[]\");\n  make_unique();  //because the user will probably modify this char!\n  return chrs()[idx]; \n  }\n\nchar GStr::operator[](int idx) const {\n//returns char copy (cannot be l-value!)\n  if (idx < 0) idx += length();\n  if (idx < 0 || idx >= length()) invalid_index_error(\"operator[]\");\n  return chars()[idx];\n  }\n\nGStr& GStr::operator=(const GStr& s) {\n  make_unique(); //edit operation ahead\n  replace_data(s.my_data); \n  return *this;\n  }\n\nGStr& GStr::operator=(const char *s) {\n  make_unique(); //edit operation ahead\n  if (s==NULL) {\n    replace_data(0);\n    return *this;\n    }\n  const int len = ::strlen(s); replace_data(len);\n  ::memcpy(chrs(), s, len); \n  return *this;\n  }\n\nGStr& GStr::operator=(const double f) {\n make_unique(); //edit operation ahead\n char buf[20];\n sprintf(buf,\"%f\",f);\n const int len = ::strlen(buf);\n replace_data(len);\n ::memcpy(chrs(), buf, len);\n return *this;\n}\n\nGStr& GStr::operator=(const int i) {\n make_unique(); //edit operation ahead\n char buf[20];\n sprintf(buf,\"%d\",i);\n const int len = ::strlen(buf);\n replace_data(len);\n ::memcpy(chrs(), buf, len);\n return *this;\n}\n\nbool GStr::operator==(const GStr& s) const {\n  if (s.is_empty()) return is_empty();\n  return (length() == s.length()) &&\n    (memcmp(chars(), s.chars(), length()) == 0);\n  }\n\nbool GStr::operator==(const char *s) const {\n if (s==NULL) return is_empty();\n return (strcmp(chars(), s) == 0);\n }\n\nbool GStr::operator<(const GStr& s) const {\n if (s.is_empty()) return false;\n return (strcmp(chars(), s.chars()) < 0);\n }\n\nbool GStr::operator<(const char *s) const {\n if (s==NULL) return false;\n return (strcmp(chars(), s) < 0);\n }\n\nbool GStr::operator<=(const GStr& s) const {\n if (s.is_empty()) return is_empty();\n return (strcmp(chars(), s.chars()) <= 0);\n }\n\nbool GStr::operator<=(const char *s) const {\n if (s==NULL) return is_empty();\n return (strcmp(chars(), s) <= 0);\n }\n\nbool GStr::operator>(const GStr& s) const {\n if (s.is_empty()) return !is_empty();\n return (strcmp(chars(), s.chars()) > 0);\n }\n\nbool GStr::operator>(const char *s) const {\n if (s==NULL) return !is_empty();\n return (strcmp(chars(), s) > 0);\n }\n\nbool GStr::operator>=(const GStr& s) const {\n if (s.is_empty()) return true;\n return (strcmp(chars(), s.chars()) >= 0);\n }\n\nbool GStr::operator>=(const char *s) const {\n if (s==NULL) return true;\n return (strcmp(chars(), s) >= 0);\n }\n\nbool GStr::operator!=(const GStr& s) const {\n  if (s.is_empty()) return !is_empty();\n  return (length() != s.length()) ||\n         (memcmp(chars(), s.chars(), length()) != 0);\n  }\n\nbool GStr::operator!=(const char *s) const {\n if (s==NULL) return !is_empty();\n return (strcmp(chars(), s) != 0);\n }\n\nGStr& GStr::append(char c) {\n char buf[5];\n sprintf(buf,\"%c\",c);\n return append(buf);\n }\n\nGStr& GStr::append(int i) {\n char buf[20];\n sprintf(buf,\"%d\",i);\n return append(buf);\n }\n\nGStr& GStr::append(uint i) {\n char buf[20];\n sprintf(buf,\"%u\",i);\n return append(buf);\n }\n\nGStr& GStr::append(long l) {\n char buf[20];\n sprintf(buf,\"%ld\",l);\n return append(buf);\n }\n\nGStr& GStr::append(unsigned long l) {\n char buf[20];\n sprintf(buf,\"%lu\", l);\n return append(buf);\n }\n\nGStr& GStr::append(double f) {\n char buf[30];\n sprintf(buf,\"%f\",f);\n return append(buf);\n }\n \nbool GStr::is_empty() const {\n  //return my_data == &null_data;\n  return (length()==0);\n  }\n\nGStr GStr::copy() const {\n GStr newstring(*this);\n return newstring;\n }\n\nGStr& GStr::clear() {\n  make_unique(); //edit operation ahead\n  replace_data(0);\n  return *this;\n  }\n\nint GStr::index(const GStr& s, int start_index) const {\n return index(s.chars(), start_index);\n }\n\nbool GStr::contains(const GStr& s) const {\n return (index(s, 0) >= 0);\n }\n\nbool GStr::contains(const char *s) const {\n return (index(s, 0) >= 0);\n }\n\nbool GStr::startsWith(const char *s) const {\n //return (index(s, 0) == 0);\n return ::startsWith(this->chars(), s);\n }\n\nbool GStr::startsWith(const GStr& s) const {\n //return (index(s, 0) == 0);\n return ::startsWith(this->chars(), s.chars());\n }\n\nbool GStr::endsWith(const char *s) const {\n //return (index(s, 0) == 0);\n return ::endsWith(this->chars(), s);\n }\n\nbool GStr::endsWith(const GStr& s) const {\n //return (index(s, 0) == 0);\n return ::endsWith(this->chars(), s.chars());\n }\n\nbool GStr::contains(char c) const {\n return (index(c, 0) >= 0);\n }\n\nGStr& GStr::format(const char *fmt,...) {\n// Format as in sprintf\n  make_unique(); //edit operation ahead\n  char* buf;\n  GMALLOC(buf, strlen(fmt)+1024);\n  va_list arguments;\n  va_start(arguments,fmt);\n  //+1K buffer, should be enough for common expressions\n  int len=vsprintf(buf,fmt,arguments);\n  va_end(arguments);\n  replace_data(len); //this also adds the '\\0' at the end!\n                     //and sets the right len\n  ::memcpy(chrs(), buf, len);\n  GFREE(buf);\n  return *this;\n  }\n\nGStr& GStr::appendfmt(const char *fmt,...) {\n// Format as in sprintf\n  make_unique(); //edit operation ahead\n  char* buf;\n  GMALLOC(buf, strlen(fmt)+1024);\n  va_list arguments;\n  va_start(arguments,fmt);\n  //+1K buffer, should be enough for common expressions\n  vsprintf(buf,fmt,arguments);\n  va_end(arguments);\n  append(buf);\n  GFREE(buf);\n  return *this;\n  }\n\nGStr& GStr::trim(char c) {\n register int istart;\n register int iend;\n for (istart=0; istart<length() && chars()[istart]==c;istart++) ;\n if (istart==length()) {\n       make_unique(); //edit operation ahead\n       replace_data(0); //string was entirely trimmed\n       return *this;\n       }\n for (iend=length()-1; iend>istart && chars()[iend]==c;iend--) ;\n int newlen=iend-istart+1;\n if (newlen==length())  //nothing to trim\n           return *this; \n make_unique(); //edit operation ahead\n Data *data = new_data(newlen);\n ::memcpy(data->chars, &chars()[istart], newlen);\n replace_data(data);\n return *this;\n }\n\nGStr& GStr::trim(const char* c) {\n register int istart;\n register int iend;\n for (istart=0; istart<length() && strchr(c, chars()[istart])!=NULL ;istart++) ;\n if (istart==length()) {\n        replace_data(0); //string was entirely trimmed\n        return *this;\n        }\n for (iend=length()-1; iend>istart && strchr(c, chars()[iend])!=NULL;iend--) ;\n int newlen=iend-istart+1;\n if (newlen==length())  //nothing to trim\n           return *this; \n make_unique(); //edit operation ahead\n Data *data = new_data(newlen);\n ::memcpy(data->chars, &chars()[istart], newlen);\n replace_data(data);\n return *this;\n }\n\nGStr& GStr::trimR(char c) {\n //only trim the right end\n //register int istart;\n register int iend;\n for (iend=length()-1; iend>=0 && chars()[iend]==c;iend--) ;\n if (iend==-1) {\n       replace_data(0); //string was entirely trimmed\n       return *this;\n       }\n int newlen=iend+1;\n if (newlen==length())  //nothing to trim\n           return *this; \n make_unique(); //edit operation ahead\n\n Data *data = new_data(newlen);\n ::memcpy(data->chars, chars(), newlen);\n replace_data(data);\n return *this;\n }\n\nGStr& GStr::trimR(const char* c) {\n register int iend;\n for (iend=length()-1; iend>=0 && strchr(c,chars()[iend])!=NULL;iend--) ;\n if (iend==-1) {\n       replace_data(0); //string was entirely trimmed\n       return *this;\n       }\n int newlen=iend+1;\n if (newlen==length())  //nothing to trim\n           return *this; \n make_unique(); //edit operation ahead\n Data *data = new_data(newlen);\n ::memcpy(data->chars, chars(), newlen);\n replace_data(data);\n return *this;\n }\n\n\nGStr& GStr::chomp(const char* cstr) {\n register int iend;\n if (cstr==NULL || *cstr==0) return *this;\n //check if this ends with cstr\n int cend=strlen(cstr)-1;\n iend=my_data->length-1;\n while (iend>=0 && cend>=0) {\n  if (my_data->chars[iend]!=cstr[cend]) return *this;\n  iend--;\n  cend--;\n  }\n if (iend==-1) {\n       replace_data(0); //string will be entirely trimmed\n       return *this;\n       }\n int newlen=iend+1;\n make_unique(); //edit operation ahead\n Data *data = new_data(newlen);\n ::memcpy(data->chars, chars(), newlen);\n replace_data(data);\n return *this;\n }\n\nGStr& GStr::trimL(char c) {\n register int istart;\n for (istart=0; istart<length() && chars()[istart]==c;istart++) ;\n if (istart==length()) {\n       replace_data(0); //string was entirely trimmed\n       return *this;\n       }\n int newlen=length()-istart;\n if (newlen==length())  //nothing to trim\n           return *this; \n make_unique(); //edit operation ahead\n Data *data = new_data(newlen);\n ::memcpy(data->chars, &chars()[istart], newlen);\n replace_data(data);\n return *this;\n }\n\nGStr& GStr::trimL(const char* c) {\n register int istart;\n for (istart=0; istart<length() && strchr(c,chars()[istart])!=NULL;istart++) ;\n if (istart==length()) {\n       replace_data(0); //string was entirely trimmed\n       return *this;\n       }\n int newlen=length()-istart;\n if (newlen==length())  //nothing to trim\n           return *this; \n make_unique(); //edit operation ahead\n\n Data *data = new_data(newlen);\n ::memcpy(data->chars, &chars()[istart], newlen);\n replace_data(data);\n return *this;\n }\n\nGStr& GStr::padR(int len, char c) {\n //actually means align right in len\n if (length()>=len) return *this; //no room for padding\n make_unique(); //edit operation ahead\n Data *data = new_data(len);\n ::memset(data->chars,c,len-length());\n ::memcpy(&data->chars[len-length()], chars(), length());\n replace_data(data);\n return *this;\n }\n\nGStr& GStr::padL(int len, char c) { //align left the string\n if (length()>=len) return *this; //no room for padding\n make_unique(); //edit operation ahead\n Data *data = new_data(len);\n ::memcpy(data->chars, chars(), length());\n ::memset(&data->chars[length()],c,len-length());\n replace_data(data);\n return *this;\n }\n\nGStr& GStr::padC(int len, char c) {\n if (length()>=len) return *this; //no room for padding\n make_unique(); //edit operation ahead\n int istart=(len-length())/2;\n Data *data = new_data(len);\n if (istart>0)\n      ::memset(data->chars, c, istart);\n ::memcpy(&data->chars[istart], chars(), length());\n int iend=istart+length();\n if (iend<len)\n      ::memset(&data->chars[iend],c,len-iend);\n replace_data(data);\n return *this;\n }\n\nGStr operator+(const char *s1, const GStr& s2) {\n    const int s1_length = ::strlen(s1);\n\n    if (s1_length == 0)\n        return s2;\n    else {\n        GStr newstring;\n        newstring.replace_data(s1_length + s2.length());\n        ::memcpy(newstring.chrs(), s1, s1_length);\n        ::memcpy(&(newstring.chrs())[s1_length], s2.chars(), s2.length());\n        return newstring;\n        }\n}\n\n//=========================================\n\nGStr GStr::operator+(const GStr& s) const {\n    if (length() == 0)\n        return s;\n    else if (s.length() == 0)\n        return *this;\n    else {\n        GStr newstring;\n        newstring.replace_data(length() + s.length());\n        ::memcpy(newstring.chrs(), chars(), length());\n        ::memcpy(&(newstring.chrs())[length()], s.chars(), s.length());\n        return newstring;\n        }\n}\n\n//=========================================\n\nGStr GStr::operator+(const char *s) const {\n\n    const int s_length = ::strlen(s);\n\n    if (s_length == 0)\n        return *this;\n    else {\n        GStr newstring;\n        newstring.replace_data(length() + s_length);\n        ::memcpy(newstring.chrs(), chars(), length());\n        ::memcpy(&(newstring.chrs())[length()], s, s_length);\n        return newstring;\n        }\n}\n\nGStr GStr::operator+(const int i) const {\n    char buf[20];\n    sprintf(buf, \"%d\", i);\n    const int s_length = ::strlen(buf);\n    GStr newstring;\n    newstring.replace_data(length() + s_length);\n    ::memcpy(newstring.chrs(), chars(), length());\n    ::memcpy(&(newstring.chrs())[length()], buf, s_length);\n    return newstring;\n}\n\nGStr GStr::operator+(const char c) const {\n    char buf[4];\n    sprintf(buf, \"%c\", c);\n    const int s_length = ::strlen(buf);\n    GStr newstring;\n    newstring.replace_data(length() + s_length);\n    ::memcpy(newstring.chrs(), chars(), length());\n    ::memcpy(&(newstring.chrs())[length()], buf, s_length);\n    return newstring;\n}\n\nGStr GStr::operator+(const double f) const {\n    char buf[30];\n    sprintf(buf, \"%f\", f);\n    const int s_length = ::strlen(buf);\n    GStr newstring;\n    newstring.replace_data(length() + s_length);\n    ::memcpy(newstring.chrs(), chars(), length());\n    ::memcpy(&(newstring.chrs())[length()], buf, s_length);\n    return newstring;\n}\n\n\n//=========================================\n\nbool GStr::is_space() const {\n\n    if (my_data == &null_data)\n        return false;\n\n    for (register const char *p = chars(); *p; p++)\n        if (!isspace(*p))\n            return false;\n\n    return true;\n}\n\n//=========================================\n\nGStr GStr::substr(int idx, int len) const {\n    // A negative idx specifies an idx from the right of the string.\n    if (idx < 0)\n        idx += length();\n\n    // A length of -1 specifies the rest of the string.\n    if (len < 0  || len>length()-idx)\n        len = length() - idx;\n    \n    if (idx<0 || idx>=length() || len<0 )\n        invalid_args_error(\"substr()\");\n\n    GStr newstring;\n    newstring.replace_data(len);\n    ::memcpy(newstring.chrs(), &chars()[idx], len);\n    return newstring;\n}\n\nGStr& GStr::reverse() {\n  make_unique();\n  int l=0;\n  int r=my_data->length-1;\n  char c;\n  while (l<r) {\n     c=my_data->chars[l];\n     my_data->chars[l]=my_data->chars[r];\n     my_data->chars[r]=c;\n     l++;r--;\n     }\n  return *this;\n}\n\n\n//transform: any character from 'from' is replaced with a coresponding\n//char from 'to'\n\nGStr&  GStr::tr(const char *rfrom, const char* rto) {\n if (length() == 0 || rfrom==NULL || strlen(rfrom)==0)\n        return *this;\n unsigned int l=strlen(rfrom);       \n if (rto!=NULL && strlen(rto)!=l)\n      invalid_args_error(\"tr()\");\n make_unique(); //edit operation ahead\n Data *data = new_data(length());\n      \n if (rto==NULL) { //deletion case \n   char* s = my_data->chars;\n   char* p;\n   char* dest = data->chars;\n   do {\n      if ((p=strpbrk(s,rfrom))!=NULL) {\n        memcpy(dest,s,p-s);\n        dest+=p-s;\n        s=p+1;\n        }\n       else { \n        strcpy(dest, s); \n        dest+=strlen(s);\n        }\n      } while (p!=NULL);\n   (*dest)='\\0';   \n   }\n  else { //char substitution case - easier!\n   const char* p;\n   for (int i=0; i<length(); i++) {\n    if ((p=strchr(rfrom, my_data->chars[i]))!=NULL) \n         my_data->chars[i]=rto[p-rfrom];\n    }\n   }\n data->length=strlen(data->chars);\n replace_data(data);\n return *this;\n}\n\n\n// search and replace all the occurences of a string with another string\n// or just remove the given string (if replacement is NULL)\nGStr&  GStr::replace(const char *rfrom, const char* rto) {\n if (length() == 0 || rfrom==NULL || strlen(rfrom)==0)\n        return *this;\n unsigned int l=strlen(rfrom);\n unsigned int tl= (rto==NULL)?0:strlen(rto);\n make_unique(); //edit operation ahead\n char* p;\n char* dest;\n char* newdest=NULL;\n char* s = my_data->chars;\n if (tl!=l) { //reallocation\n   if (tl>l) {  //possible enlargement\n       GMALLOC(newdest, length()*(tl-l+1)+1);\n       }\n      else  {//delete or replace with a shorter string\n       GMALLOC(newdest, length() + 1);\n       }\n      dest=newdest; \n      if (tl==0) {//deletion\n           while ((p=strstr(s,rfrom))!=NULL) {\n               //rfrom found at position p\n                memcpy(dest,s,p-s);\n                dest+=p-s;\n                s+=p-s+l; //s positioned in string after rfrom\n                }\n           //no more occurences, copy the remaining string\n           strcpy(dest, s);\n          }\n        else { //replace with another string\n          while ((p=strstr(s,rfrom))!=NULL) {\n              memcpy(dest,s,p-s); //copy up rto the match\n              dest+=p-s;\n              memcpy(dest,rto,tl); //put the replacement string\n              dest+=tl;\n              s+=p-s+l;\n              }\n          //not found any more, copy rto end of string\n          strcpy(dest, s);\n          }\n       Data* data=new_data(newdest);\n       replace_data(data);\n       GFREE(newdest);\n       }\n  else { //inplace editing: no need rto reallocate\n    while ((p=strstr(s,rfrom))!=NULL) {\n        memcpy(p,rto,l);\n        s+=p-s+l;\n        }    \n   }\n return *this;\n}\n\n\n\nGStr&  GStr::cut(int idx, int len) {\n\n    if (len == 0)\n        return *this;\n    make_unique(); //edit operation ahead\n\n    // A negative idx specifies an idx from the right of the string,\n    // so the left part will be cut out\n    if (idx < 0)\n        idx += length();\n\n    // A length of -1 specifies the rest of the string.\n    if (len == -1)\n        len = length() - idx;\n\n    if (idx<0 || idx>=length() || len<0 || len>length()-idx)\n        invalid_args_error(\"cut()\");\n\n    Data *data = new_data(length() - len);\n    if (idx > 0)\n        ::memcpy(data->chars, chars(), idx);\n    ::strcpy(&data->chars[idx], &chars()[idx+len]);\n    replace_data(data);\n\n    return *this;\n}\n\n//=========================================\n\nGStr&  GStr::paste(const GStr& s, int idx, int len) {\n    // A negative idx specifies an idx from the right of the string.\n    if (idx < 0)\n        idx += length();\n    make_unique(); //edit operation ahead\n\n    // A length of -1 specifies the rest of the string.\n    if (len == -1)\n        len = length() - idx;\n\n    if (idx<0 || idx>=length() || len<0 || len>length()-idx)\n        invalid_args_error(\"replace()\");\n\n    if (len == s.length() && my_data->ref_count == 1)\n        ::memcpy(&chrs()[idx], s.chars(), len);\n    else {\n        Data *data = new_data(length() - len + s.length());\n        if (idx > 0)\n            ::memcpy(data->chars, chars(), idx);\n        if (s.length() > 0)\n            ::memcpy(&data->chars[idx], s.chars(), s.length());\n        ::strcpy(&data->chars[idx+s.length()], &chars()[idx+len]);\n        replace_data(data);\n    }\n\n    return *this;\n}\n\n//=========================================\n\nGStr& GStr::paste(const char *s, int idx, int len) {\n\n    // A negative idx specifies an idx from the right of the string.\n    make_unique(); //edit operation ahead\n    if (idx < 0)\n        idx += length();\n\n    // A length of -1 specifies the rest of the string.\n    if (len == -1)\n        len = length() - idx;\n\n    if (idx<0 || idx>=length() || len<0 || len>length()-idx)\n        invalid_args_error(\"replace()\");\n\n    const int s_length = ::strlen(s);\n\n    if (len == s_length && my_data->ref_count == 1)\n        ::memcpy(&chrs()[idx], s, len);\n    else {\n        Data *data = new_data(length() - len + s_length);\n        if (idx > 0)\n            ::memcpy(data->chars, chars(), idx);\n        if (s_length > 0)\n            ::memcpy(&data->chars[idx], s, s_length);\n        ::strcpy(&data->chars[idx+s_length], &chars()[idx+len]);\n        replace_data(data);\n    }\n\n    return *this;\n}\n\n//=========================================\n\nGStr& GStr::insert(const GStr& s, int idx) {\n    make_unique(); //edit operation ahead\n\n    // A negative idx specifies an idx from the right of the string.\n    if (idx < 0)\n        idx += length();\n\n    if (idx < 0 || idx >= length())\n        invalid_index_error(\"insert()\");\n\n    if (s.length() > 0) {\n        Data *data = new_data(length() + s.length());\n        if (idx > 0)\n            ::memcpy(data->chars, chars(), idx);\n        ::memcpy(&data->chars[idx], s.chars(), s.length());\n        ::strcpy(&data->chars[idx+s.length()], &chars()[idx]);\n        replace_data(data);\n    }\n\n    return *this;\n}\n\n//=========================================\n\nGStr& GStr::insert(const char *s, int idx) {\n    // A negative idx specifies an idx from the right of the string.\n    make_unique(); //edit operation ahead\n    if (idx < 0)\n        idx += length();\n\n    if (idx < 0 || idx >= length())\n        invalid_index_error(\"insert()\");\n\n    const int s_length = ::strlen(s);\n\n    if (s_length > 0) {\n        Data *data = new_data(length() + s_length);\n        if (idx > 0)\n            ::memcpy(data->chars, chars(), idx);\n        ::memcpy(&data->chars[idx], s, s_length);\n        ::strcpy(&data->chars[idx+s_length], &chars()[idx]);\n        replace_data(data);\n    }\n\n    return *this;\n}\n//=========================================\n\nGStr& GStr::append(const char* s) {\n  make_unique(); //edit operation ahead\n  int len=::strlen(s);\n  int newlength=len+my_data->length;\n  if (newlength<=my_data->length) return *this;\n  if (my_data->length==0) {\n    replace_data(len);\n    ::memcpy(my_data->chars, s, len);\n    return *this;\n   }\n  //faster solution with realloc\n  GREALLOC(my_data, sizeof(Data)+newlength);\n  ::strcpy(&my_data->chars[my_data->length], s);\n  my_data->length=newlength;\n  my_data->chars[newlength]='\\0';\n  return *this;\n}\n\nGStr& GStr::append(const GStr& s) {\n return append((const char *)s);\n}\n\n\nGStr& GStr::upper() {\n  make_unique(); //edit operation ahead\n  for (register char *p = chrs(); *p; p++)\n            *p = (char) toupper(*p);\n\n    return *this;\n}\n\n//=========================================\n\nGStr& GStr::lower() {\n    make_unique();\n\n    for (register char *p = chrs(); *p; p++)\n          *p = (char) tolower(*p);\n\n    return *this;\n}\n\n//=========================================\n\nint GStr::index(const char *s, int start_index) const {\n    // A negative index specifies an index from the right of the string.\n    if (strlen(s)>(size_t)length()) return -1;\n    if (start_index < 0)\n        start_index += length();\n\n    if (start_index < 0 || start_index >= length())\n        invalid_index_error(\"index()\");\n    const char* idx = strstr(&chars()[start_index], s);\n    if (!idx)\n        return -1;\n    else\n        return idx - chars();\n}\n\n//=========================================\n\nint GStr::index(char c, int start_index) const {\n    // A negative index specifies an index from the right of the string.\n    if (length()==0) return -1;\n    if (start_index < 0)\n        start_index += length();\n     \n    if (start_index < 0 || start_index >= length())\n        invalid_index_error(\"index()\");\n\n\n    if (c == '\\0')\n        return -1;\n    const char *idx=(char *) ::memchr(&chars()[start_index], c,\n                                         length()-start_index);\n    if (idx==NULL)\n        return -1;\n    else\n        return idx - chars();\n}\n\nint GStr::rindex(char c, int end_index) const {   \n    if (c == 0 || length()==0 || end_index>=length()) return -1;\n    if (end_index<0) end_index=my_data->length-1; \n    for (int i=end_index;i>=0;i--) {\n      if (my_data->chars[i]==c) return i;\n      }\n    return -1;\n}\n\nint GStr::rindex(const char* str, int end_index) const {\n    if (str==NULL || *str == '\\0' || length()==0 || end_index>=length())\n        return -1;\n    int slen=strlen(str);\n    if (end_index<0) end_index=my_data->length-1;\n    //end_index is the index of the right-side boundary \n    //the scanning starts at the end\n    if (end_index>=0 && end_index<slen-1) return -1;\n    for (int i=end_index-slen+1;i>=0;i--) {\n       if (memcmp((void*)(my_data->chars+i),(void*)str, slen)==0)\n           return i;\n       }\n    return -1;\n}\n\nGStr GStr::split(const char* delim) {\n           /* splits \"this\" in two parts, at the first (left) \n                 encounter of delim:\n                 1st would stay in \"this\",\n                 2nd part will be returned \n                 as a new string!\n           */\n GStr result;\n int i=index(delim);\n if (i>=0){\n      result=substr(i+strlen(delim));\n      cut(i);\n      return result;\n      }\n return result;\n}\n\nGStr GStr::split(char c) {\n           /* splits \"this\" in two parts, at the first (left) \n                 encounter of delim:\n                 1st would stay in \"this\",\n                 2nd part will be returned \n                 as a new string!\n           */\n GStr result;\n int i=index(c);\n if (i>=0){\n      result=substr(i+1);\n      cut(i);\n      return result;\n      }\n return result;\n}\n\nGStr GStr::splitr(const char* delim) {\n GStr result;\n int i=rindex(delim);\n if (i>=0){\n      result=substr(i+strlen(delim));\n      cut(i);\n      return result;\n      }\n return result;\n}\n\nGStr GStr::splitr(char c) {\n GStr result;\n int i=rindex(c);\n if (i>=0){\n      result=substr(i+1);\n      cut(i);\n      return result;\n      }\n return result;\n}\n\n\nvoid GStr::startTokenize(const char* delimiter, enTokenizeMode tokenizemode) {\n GFREE(fTokenDelimiter);\n if (delimiter) {\n    GMALLOC(fTokenDelimiter,strlen(delimiter)+1);\n    strcpy(fTokenDelimiter, delimiter);\n    }\n fLastTokenStart=0;\n fTokenizeMode=tokenizemode;\n}\n\nbool GStr::nextToken(GStr& token) {\n if (fTokenDelimiter==NULL) {\n    GError(\"GStr:: no token delimiter; use StartTokenize first\\n\");\n    }\n if (fLastTokenStart>=length()) {//no more\n    GFREE(fTokenDelimiter);\n    fLastTokenStart=0;\n    return false;\n    }\n int dlen=strlen(fTokenDelimiter);\n char* delpos=NULL; //delimiter position\n int tlen=0;\n if (fTokenizeMode==tkFullString) { //exact string as a delimiter\n   delpos=(char*)strstr(chars()+fLastTokenStart,fTokenDelimiter);\n   if (delpos==NULL) delpos=(char*)(chars()+length());\n   //empty records may be returned\n   if (chars()+fLastTokenStart == delpos) { //empty token\n     fLastTokenStart=(delpos-chars())+dlen;\n     token=\"\";\n     return true;\n     }\n    else {\n     tlen=delpos-(chars()+fLastTokenStart);\n     token.replace_data(tlen);\n     ::memcpy(token.chrs(), &chars()[fLastTokenStart], tlen);\n     fLastTokenStart=(delpos-chars())+dlen;\n     return true;\n     } \n   }\n  else { //tkCharSet - any character is a delimiter\n   //empty records are never returned !\n   if (fLastTokenStart==0) {//skip any starting delimiters\n     delpos=(char*)chars();   \n     while (*delpos!='\\0' && strchr(fTokenDelimiter, *delpos)!=NULL) \n       delpos++;\n     if (*delpos!='\\0')\n         fLastTokenStart = delpos-chars();\n       else { //only delimiters here,no tokens\n         GFREE(fTokenDelimiter);\n         fLastTokenStart=0;\n         return false;\n         }\n     }\n   //now fLastTokenStart is on a non-delimiter char\n   //GMessage(\"String at fLastTokenStart=%d is %s\\n\", fLastTokenStart, delpos);\n   char* token_end=NULL;\n   delpos=(char*)strpbrk(chars()+fLastTokenStart,fTokenDelimiter);\n   if (delpos==NULL) delpos=(char*)(chars()+length());\n   token_end=delpos-1;\n   while (*delpos!='\\0' && strchr(fTokenDelimiter, *delpos)!=NULL) \n      delpos++; //skip any other delimiters in the set!\n   //now we know that delpos is on the beginning of next token\n   tlen=(token_end-chars())-fLastTokenStart+1;\n   if (tlen==0) {\n       GFREE(fTokenDelimiter);\n       fLastTokenStart=0;\n       return false;\n       }\n   token.replace_data(tlen);\n   ::memcpy(token.chrs(), &chars()[fLastTokenStart], tlen);\n   fLastTokenStart=delpos-chars();\n   return true;\n   }\n //return true;\n}\n\nsize_t GStr::read(FILE* stream, const char* delimiter, size_t bufsize) {\n//read up to (and including) the given delimiter string\n if (readbuf==NULL) {\n    GMALLOC(readbuf, bufsize);\n    readbufsize=bufsize;\n    }\n  else if (bufsize!=readbufsize) {\n            GFREE(readbuf);\n            if (bufsize>0) {\n              GMALLOC(readbuf, bufsize);\n              }\n            readbufsize=bufsize;\n            }\n if (bufsize==0) {\n    replace_data(0);\n    return 0; //clear the string and free the buffer\n    }\n size_t numread;\n size_t acc_len=0; //accumulated length\n int seplen=strlen(delimiter);\n void* p=NULL;\n Data *data = new_data(0);\n do {\n   numread=fread(readbuf, 1, bufsize, stream);\n   if (numread) {\n     p=Gmemscan(readbuf, bufsize, (void*) delimiter, seplen);\n     if (p!=NULL) {//found the delimiter\n           //position the stream after it\n           int l = (char*)p-(char*)readbuf;\n           fseek(stream, l+seplen-numread, SEEK_CUR);\n           numread=l+seplen;\n           }\n        else {//not found, go back if not eof\n           if (numread==bufsize) {\n               fseek(stream, -seplen, SEEK_CUR); //check if this works!\n               numread-=seplen;\n               }\n           }\n      if (data==&null_data) {\n        data=new_data(numread);\n        ::memcpy(data->chars, readbuf, numread);\n        acc_len+=numread;\n        }\n       else {\n        GREALLOC(data, sizeof(Data)+acc_len+numread);\n        memcpy(&data->chars[acc_len], readbuf, numread);\n        acc_len+=numread;\n        data->length=acc_len;\n        data->chars[acc_len]='\\0';\n        }\n      } //if something read\n   } while (p==NULL && numread!=0);\n  replace_data(data); \n  return acc_len;\n}\n\n\nint GStr::asInt(int base /*=10 */) {\n return strtol(text(), NULL, base);\n}\n\nbool GStr::asInt(int& r, int base) {\n errno=0;\n char*endptr;\n long val=strtol(text(), &endptr, base);\n if (errno!=0) return false;\n if (endptr == text()) return false;\n /* If we got here, strtol() successfully parsed a number */\n r=val;\n return true;\n}\n\ndouble GStr::asReal() {\n return strtod(text(), NULL);\n}\n\nbool GStr::asReal(double& r) {\n  errno=0;\n  char* endptr;\n  double val=strtod(text(), &endptr);\n  if (errno!=0) return false;\n  if (endptr == text()) return false; //no digits to parse\n  r=val;\n  return true;\n}\n\n\nint GStr::peelInt() const {\n if (is_empty()) return 0;\n char buf[24];\n bool started=false;\n int j=0;\n int i;\n for (i=0;i<length();i++) {\n  if (started) {\n    if (isdigit(my_data->chars[i])) j++; //set coord\n                               else break; //finished\n    }\n   else\n    if (isdigit(my_data->chars[i])) {\n        j++; started=true;\n        }\n  }\n if (j>0) {\n   strncpy(buf, &my_data->chars[i-j], j);\n   buf[j]='\\0';\n   return strtol(buf, NULL, 10);\n   }\n return 0;\n}\n\nint GStr::peelIntR() const {\n if (is_empty()) return 0;\n char buf[24];\n bool started=false;\n int j=0;\n int i;\n for (i=length()-1;i>=0;i--) {\n  if (started) {\n    if (isdigit(my_data->chars[i])) j++; //set length\n                               else break; //finished\n    }\n   else\n    if (isdigit(my_data->chars[i])) {\n      j++; started=true;\n      }\n  }\n if (j>0) {\n   strncpy(buf, &my_data->chars[i+1], j);\n   buf[j]='\\0';\n   return strtol(buf, NULL, 10);\n   }\n return 0;\n}\n\nGStr GStr::to(char c) { //return the first part up to first occurence of c\n int i=index(c);\n if (i>=0) return substr(0,i);\n      else return (*this);\n}\n                           //or whole string if c not found\nGStr GStr::from(char c) { //same as to, but starting from the right side\n int i=rindex(c);\n if (i>=0) return substr(i+1);\n      else return (*this);\n}\n\nint GStr::count(char c){\n //return the number of occurences of char c within the string\n int result=0;\n for (int i=0;i<length();i++)\n    if (my_data->chars[i]==c) result++;\n return result;\n }\n\n//=========================================\n\nvoid GStr::invalid_args_error(const char *fname) {\n    GError(\"GStr:: %s  - invalid arguments\\n\", fname);\n}\n\n//****************************************************************************\n\nvoid GStr::invalid_index_error(const char *fname) {\n    GError(\"GStr:: %s  - invalid index\\n\", fname);\n}\n//****************************************************************************\n\n"
  },
  {
    "path": "src/GStr.h",
    "content": "//---------------------------------------------------------------------------\n#ifndef GSTR_H\n#define GSTR_H\n//---------------------------------------------------------------------------\n#include \"GBase.h\"\n#include <string.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n// This class uses reference counting and copy-on-write semantics\n\n// All indexes are zero-based.  For all functions that accept an index, a\n// negative index specifies an index from the right of the string.  Also,\n// for all functions that accept a length, a length of -1 specifies the rest\n// of the string.\nenum enTokenizeMode {\n tkFullString,\n tkCharSet\n };\n\nclass GStr {\n        friend GStr operator+(const char* s1, const GStr& s2);\n        friend bool operator==(const char* s1, const GStr& s2);\n        friend bool operator<(const char* s1, const GStr& s2);\n        friend bool operator<=(const char* s1, const GStr& s2);\n        friend bool operator>(const char* s1, const GStr& s2);\n        friend bool operator>=(const char* s1, const GStr& s2);\n        friend bool operator!=(const char* s1, const GStr& s2);\n        friend void Gswap(GStr& s1, GStr& s2);\n    public:\n        GStr();\n        GStr(const GStr& s);\n        GStr(const char* s);\n        GStr(const int i);\n        GStr(const double f);\n        GStr(char c, int n = 1);\n        ~GStr();\n        operator const char* () const { return my_data->chars;} //inline here\n        char& operator[](int index);\n        char operator[](int index) const;\n        GStr& operator=(const GStr& s);\n        GStr& operator=(const char* s);\n        GStr& operator=(const int i);\n        GStr& operator=(const double f);\n        GStr operator+(const GStr& s) const;\n        GStr operator+(const char* s) const;\n        GStr operator+(const char c) const;\n        GStr operator+(const int i) const;\n        GStr operator+(const double f) const;\n        bool operator==(const GStr& s) const;\n        bool operator==(const char* s) const;\n        bool operator<(const GStr& s) const;\n        bool operator<(const char* s) const;\n        bool operator<=(const GStr& s) const;\n        bool operator<=(const char* s) const;\n        bool operator>(const GStr& s) const;\n        bool operator>(const char* s) const;\n        bool operator>=(const GStr& s) const;\n        bool operator>=(const char* s) const;\n        bool operator!=(const GStr& s) const;\n        bool operator!=(const char* s) const;\n        GStr& operator+=(const GStr& s) { return append(s.chars()); }\n        GStr& operator+=(const char* s) { return append(s); }\n        GStr& operator+=(char c) { return append(c); }\n        GStr& operator+=(int i) { return append(i); }\n        GStr& operator+=(uint i) { return append(i); }\n        GStr& operator+=(long l) { return append(l); }\n        GStr& operator+=(unsigned long l) { return append(l); }\n        GStr& operator+=(double f);\n      //interface:\n      public:\n        int length() const;\n        bool is_empty() const;\n        bool is_space() const;\n        GStr substr(int index = 0, int len = -1) const;\n        GStr to(char c); //return the first part up to first occurence of c\n                           //or whole string if c not found\n        GStr from(char c); //same as to, but starting from the right side\n        GStr copy() const;\n        GStr& format(const char *fmt,...);\n        GStr& reverse();\n        GStr& appendfmt(const char *fmt,...);\n        GStr& cut(int index = 0, int len = -1); //delete a specified length\n        GStr& remove(int from, int to) {\n            return cut(from, to-from+1);\n            }\n\n        //paste a string at the specified position\n        GStr& paste(const GStr& s, int index = 0, int len=-1);\n        GStr& paste(const char* s, int index = 0, int len = -1);\n        GStr& replace(const char* from, const char* to=NULL);\n        GStr& insert(const GStr& s, int index = 0);\n        GStr& insert(const char* s, int index = 0);\n        GStr& append(const char* s);\n        GStr& append(const GStr& s);\n        GStr& append(char c);\n        GStr& append(int i);\n        GStr& append(long l);\n        GStr& append(double f);\n        GStr& append(uint i);\n        GStr& append(unsigned long l);\n\n        GStr& upper();\n        GStr& lower();\n        GStr& clear();//make empty\n        //character translation or removal:\n        GStr& tr(const char* from, const char* to=NULL);\n        //number of occurences of a char in the string:\n        int count(char c);\n        void startTokenize(const char* delimiter=\" \\t\\n\", enTokenizeMode tokenizemode=tkCharSet);\n        bool nextToken(GStr& token);\n        int asInt(int base=10);\n        double asReal();\n        double asDouble() { return asReal(); }\n        bool asReal(double& r);\n        bool asDouble(double& r) { return asReal(r); }\n        bool asInt(int& r, int base=10);\n        int index(const GStr& s, int start_index = 0) const;\n        int index(const char* s, int start_index = 0) const;\n        int index(char c, int start_index = 0) const;\n        int rindex(char c, int end_index = -1) const;\n        int rindex(const char* str, int end_index = -1) const;\n        bool contains(const GStr& s) const;\n        bool contains(const char* s) const;\n        bool contains(char c) const;\n        bool startsWith(const char* s) const;\n        bool startsWith(const GStr& s) const;\n        bool endsWith(const char* s) const;\n        bool endsWith(const GStr& s) const;\n        GStr split(const char* delim);\n        GStr split(char c);\n           /* splits \"this\" in two parts, at the first (leftmost)\n                 encounter of delim:\n                 1st would stay in \"this\"\n                 (which this way is truncated)\n                 2nd will go to the returned string\n           */\n        GStr splitr(const char* delim);\n        GStr splitr(char c);\n           /* splits \"this\" in two parts, at the last (rightmost)\n                 encounter of delim:\n                 1st would stay in \"this\"\n                 2nd will be returned\n           */\n\n        int peelInt() const; //extract an integer, (left to right), from a\n                //mixed alphanumeric string, e.g. 'T24HC1234b'=> 2\n        int peelIntR() const; //same as above, but starts from the right side\n        //e.g. 'T2HC1234b'=> 1234\n        GStr& trim(char c);\n        GStr& trim(const char* c=\" \\t\\n\\r\"); //trim both ends of characters in given set\n        GStr& trimR(const char* c=\" \\t\\n\\r\"); //trim only right end\n        GStr& trimR(char c=' ');\n        GStr& chomp(char c='\\n') { return trimR(c); }\n        GStr& chomp(const char* cstr); //like trimR, but given string is taken as a whole\n        GStr& trimL(const char* c=\" \\t\\n\\r\"); //trim only left end\n        GStr& trimL(char c=' ');\n        GStr& padR(int len, char c=' '); //align it in len spaces to the right\n        GStr& padL(int len, char c=' '); //align it in len spaces to the left\n        GStr& padC(int len, char c=' '); //center it\n        size_t read(FILE* stream, const char* delimiter=\"\\n\", size_t bufsize=4096);\n          //read next token from stream, using the given string as\n          //a marker where the block should stop\n        const char* chars() const;\n        const char* text() const;\n    protected:\n        char* fTokenDelimiter;\n        int fLastTokenStart;\n        enTokenizeMode fTokenizeMode;\n        void* readbuf; //file read buffer for the read() function\n        size_t readbufsize; //last setting for the readbuf\n        static void invalid_args_error(const char* fname);\n        static void invalid_index_error(const char* fname);\n        struct Data {//structure holding actual\n                     //string data and reference count information\n               Data() { ref_count=0; length=0; chars[0] = '\\0'; }\n               unsigned int ref_count;\n               int length;\n               char chars[1];\n              };\n        static Data* new_data(int length); //alloc a specified length string's Data\n        static Data* new_data(const char* str); //alloc a copy of a specified string\n        void replace_data(int length);\n        void replace_data(Data* data);\n        void make_unique();\n        char* chrs(); // this is dangerous, length should not be affected\n        static Data null_data; //a null (empty) string Data is available here\n        Data* my_data; //pointer to a Data object holding actual string data\n};\n\n/***************************************************************************/\n\ninline int GStr::length() const {\n return my_data->length;\n }\n\n\ninline const char *GStr::chars() const {\n return my_data->chars;\n }\n\ninline char *GStr::chrs() { //protected version, allows modification of the chars\n return my_data->chars;\n }\n\ninline const char *GStr::text() const {\n return my_data->chars;\n }\n\ninline bool operator>=(const char *s1, const GStr& s2) {\n return (strcmp(s1, s2.chars()) >= 0);\n }\n\ninline bool operator!=(const char *s1, const GStr& s2) {\n return (strcmp(s1, s2.chars()) != 0);\n }\n\ninline void Gswap(GStr& s1, GStr& s2) {\n GStr::Data *tmp = s1.my_data; s1.my_data = s2.my_data;\n s2.my_data = tmp;\n }\n\n#endif\n"
  },
  {
    "path": "src/GVec.hh",
    "content": "//---------------------------------------------------------------------------\n/*\nSortable collection of pointers to objects\n*/\n\n#ifndef _GVec_HH\n#define _GVec_HH\n\n#include \"GBase.h\"\n\n#define GVEC_INDEX_ERR \"GVec error: invalid index: %d\\n\"\n #if defined(NDEBUG) || defined(NODEBUG) || defined(_NDEBUG) || defined(NO_DEBUG)\n #define TEST_INDEX(x) \n#else \n #define TEST_INDEX(x) \\\n if (x<0 || x>=fCount) GError(GVEC_INDEX_ERR, x)\n#endif\n\n#define GVEC_CAPACITY_ERR \"GVec error: invalid capacity: %d\\n\"\n#define GVEC_COUNT_ERR \"GVec error: invalid count: %d\\n\"\n\n#define MAXLISTSIZE INT_MAX-1\n\n#define FREEDATA (fFreeProc!=NULL)\n\ntemplate<class T> struct IsPrimitiveType {\n    enum { VAL = 0 };\n};\n\ntemplate<> struct IsPrimitiveType<bool> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<void*> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<char*> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<float> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<double> { enum { VAL = 1 }; };\n\ntemplate<> struct IsPrimitiveType<int> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<unsigned int> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<char> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<unsigned char> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<short> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<unsigned short> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<long> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<unsigned long> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<long long> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<unsigned long long> { enum { VAL = 1 }; };\n\n/*\ntemplate<> struct IsPrimitiveType<int64_t> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<uint64_t> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<int32_t> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<uint32_t> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<int16_t> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<uint16_t> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<int8_t> { enum { VAL = 1 }; };\ntemplate<> struct IsPrimitiveType<uint8_t> { enum { VAL = 1 }; };\n*/\n\n\ntemplate <class OBJ> int DefLTCompareProc(const pointer p1, const pointer p2) {\n const OBJ& o1 = *((OBJ*) p1);\n const OBJ& o2 = *((OBJ*) p2);\n if (o1 < o2) return -1;\n   else return ((o2 < o1) ? 1 : 0 );\n}\n\n//basic template for array of objects;\n//so it doesn't require comparison operators to be defined\ntemplate <class OBJ> class GVec {\n  protected:\n    OBJ* fArray;\n    int fCount;\n    int fCapacity;\n    void qSort(int L, int R, GCompareProc* cmpFunc);\n  public:\n    GVec(int init_capacity=2);\n    GVec(int init_count, const OBJ init_val);\n    GVec(int init_count, OBJ* init_val, bool delete_initval=true); //convenience constructor for complex vectors\n    GVec(const GVec<OBJ>& array); //copy constructor\n    const GVec<OBJ>& operator=(GVec<OBJ>& array); //copy operator\n    virtual ~GVec();\n    void Insert(int idx, OBJ item) { Insert(idx, &item); }\n    void Insert(int idx, OBJ* item);\n    void idxInsert(int idx, OBJ& item) { Insert(idx, &item); }\n    void Grow();\n    void Grow(int idx, OBJ& item); //grow and add/insert item copy\n    void Reverse(); //WARNING: will break the sort order if SORTED!\n    int Add(OBJ* item); // simply append to the end of fArray, reallocating as needed\n    int Add(OBJ& item) { return Add(&item); } \n    int cAdd(OBJ item) { return Add(&item); } //all these will CREATE a new OBJ and COPY to it\n    //                   // using OBJ copy operator=\n    // -- stack/queue usage:\n    //int Push(OBJ& item) { return Add(&item); }\n    int Push(OBJ& item) { return Add(&item); }\n    int cPush(OBJ item) { return Add(&item); }\n    OBJ Pop();// Stack use; removes and returns a copy of the last item\n    OBJ Shift(); //Queue use: removes and returns a copy of the first item\n\n    void Add(GVec<OBJ>& list); //append copies of all items from another list\n\n    OBJ& Get(int idx) {\n          TEST_INDEX(idx);\n          return fArray[idx];\n          }\n    inline OBJ& operator[](int i) {\n          TEST_INDEX(i);\n          return fArray[i];\n          }\n    OBJ& Last() {\n         TEST_INDEX(fCount-1);\n         return fArray[fCount-1];\n         }\n    OBJ& First() {\n         TEST_INDEX(0);\n         return fArray[0];\n         }\n    void Clear();\n    void Delete(int index);\n    void Replace(int idx, OBJ& item); //Put, use operator= to copy\n    void Exchange(int idx1, int idx2);\n    void Swap(int idx1, int idx2)  { Exchange(idx1, idx2); } \n    int  Capacity() { return fCapacity; }\n    //this will reject identical items in sorted lists only!\n    void setCapacity(int NewCapacity);\n    int  Count() { return fCount; }\n\n    void setCount(int NewCount);         // will trim or expand the array as needed\n    void setCount(int NewCount, OBJ* v); //same as setCount() but new objects are set to v\n    void setCount(int NewCount, OBJ v);\n    void Resize(int NewCount) { setCount(NewCount); }\n    //void Resize(int NewCount, OBJ* v) { setCount(NewCount, v); }\n    void Resize(int NewCount, OBJ v) { setCount(NewCount, &v); }\n\n    //void Move(int curidx, int newidx);\n    bool isEmpty() { return fCount==0; }\n    bool notEmpty() { return fCount>0; }\n\n    void Sort(GCompareProc* cmpFunc);\n    void Sort();\n};\n\n//---- template for dynamic array of object pointers\n//---- it's faster than GVec<OBJ*> and has item deallocation awareness\ntemplate <class OBJ> class GPVec {\n  protected:\n    OBJ** fList; //pointer to an array of pointers to objects\n    int fCount; //total number of entries in list\n    int fCapacity; //current allocated size\n    GFreeProc* fFreeProc; //useful for deleting objects\n    //---\n    void Expand();\n    void Grow();\n    void Grow(int idx, OBJ* newitem);\n    void qSort(int L, int R, GCompareProc* cmpFunc);\n  public:  \n    static void DefaultFreeProc(pointer item) {\n      delete (OBJ*)item;\n      }\n    virtual ~GPVec();\n    GPVec(int init_capacity=2, bool free_elements=true); //also the default constructor\n    GPVec(bool free_elements);\n    GPVec(GPVec<OBJ>& list); //copy constructor?\n    GPVec(GPVec<OBJ>* list); //kind of a copy constructor\n    const GPVec<OBJ>& operator=(GPVec<OBJ>& list);\n    OBJ* Get(int i);\n    OBJ* operator[](int i) { return this->Get(i); }\n    void Reverse(); //reverse pointer array; WARNING: will break the sort order if sorted!\n    void freeItem(int idx); //calls fFreeProc (or DefaultFreeProc) on fList[idx] and sets NULL there, doesn't pack!\n                      //it will free even if fFreeProc is NULL!\n    void setFreeItem(GFreeProc *freeProc) { fFreeProc=freeProc; }\n    void setFreeItem(bool doFree) {\n       if (doFree) fFreeProc=DefaultFreeProc;\n             else  fFreeProc=NULL;\n       }\n    // -- stack usage:\n    int Push(OBJ* item) { return Add(item); }\n    OBJ* Pop();// Stack use; removes and returns last item,but does NOT FREE it\n    OBJ* Shift(); //Queue use: removes and returns first item, but does NOT FREE it\n    void deallocate_item(OBJ*& item); //forcefully call fFreeProc or delete on item\n    void Clear();\n    void Exchange(int idx1, int idx2);\n    void Swap(int idx1, int idx2)  { Exchange(idx1, idx2); }\n    OBJ* First() { return (fCount>0)?fList[0]:NULL; }\n    OBJ* Last()  { return (fCount>0)?fList[fCount-1]:NULL;}\n    bool isEmpty() { return fCount==0; }\n    bool notEmpty() { return fCount>0; }\n    int Capacity() { return fCapacity; }\n    int Count()   { return fCount; }\n    void setCapacity(int NewCapacity);\n    void setCount(int NewCount); //the same as setCapacity() but the new item range is filled with NULLs\n    int Add(OBJ* item); //simply append the pointer copy\n    void Add(GPVec<OBJ>& list); //add all pointers from another list\n    void Insert(int idx, OBJ* item);\n    void Move(int curidx, int newidx);\n    void Put(int idx, OBJ* item);\n    void Pack();\n    void Delete(int index); //also frees the item if fFreeProc!=NULL, and shifts the successor items\n    void Forget(int idx); //simply places a NULL at fList[idx], nothing else\n    int RemovePtr(pointer item); //always use linear search to find the pointer! calls Delete() if found\n    int IndexOf(pointer item); //a linear search for pointer address!\n    void Sort(GCompareProc* cmpFunc);\n    void Sort();\n };\n\n//-------------------- TEMPLATE IMPLEMENTATION-------------------------------\n\ntemplate <class OBJ> GVec<OBJ>::GVec(int init_capacity) {\n  fCount=0;\n  fCapacity=0;\n  fArray=NULL;\n  setCapacity(init_capacity);\n  //if (set_count) fCount = init_capacity;\n}\n\n\ntemplate <class OBJ> GVec<OBJ>::GVec(int init_count, const OBJ init_val) {\n  fCount=0;\n  fCapacity=0;\n  fArray=NULL;\n  setCapacity(init_count);\n  fCount = init_count;\n  for (int i=0;i<fCount;i++)\n    fArray[i]=init_val;\n}\n\ntemplate <class OBJ> GVec<OBJ>::GVec(int init_count, OBJ* init_val, bool delete_initval) {\n\t  fCount=0;\n\t  fCapacity=0;\n\t  fArray=NULL;\n\t  setCapacity(init_count);\n\t  fCount = init_count;\n\t  for (int i=0;i<fCount;i++)\n\t    fArray[i]=*init_val;\n\t  if (delete_initval) { delete init_val; }\n}\n\n\ntemplate <class OBJ> GVec<OBJ>::GVec(const GVec<OBJ>& array) { //copy constructor\n this->fCount=array.fCount;\n this->fCapacity=array.fCapacity;\n this->fArray=NULL;\n if (this->fCapacity>0) {\n   if (IsPrimitiveType<OBJ>::VAL) {\n     GMALLOC(fArray, fCapacity*sizeof(OBJ));\n     memcpy(fArray, array.fArray, fCount*sizeof(OBJ));\n   }\n   else {\n     fArray=new OBJ[this->fCapacity]; //]()\n     // uses OBJ operator=\n     for (int i=0;i<this->fCount;i++) fArray[i]=array.fArray[i];\n   }\n }\n this->fCount=array.fCount;\n }\n\ntemplate <class OBJ> const GVec<OBJ>& GVec<OBJ>::operator=(GVec<OBJ>& array) {\n if (&array==this) return *this;\n Clear();\n fCapacity=array.fCapacity;\n fCount=array.fCount;\n if (fCapacity>0) {\n   if (IsPrimitiveType<OBJ>::VAL) {\n     GMALLOC(fArray, fCapacity*sizeof(OBJ));\n     memcpy(fArray, array.fArray, fCount*sizeof(OBJ));\n     }\n   else {\n    fArray=new OBJ[this->fCapacity]; // ]()\n    // uses OBJ operator=\n    for (int i=0;i<fCount;i++) {\n      fArray[i]=array.fArray[i];\n    }\n   }\n }\n return *this;\n}\n\ntemplate <class OBJ> GVec<OBJ>::~GVec() {\n this->Clear();\n}\n\n\ntemplate <class OBJ> void GVec<OBJ>::setCapacity(int NewCapacity) {\n  if (NewCapacity < fCount || NewCapacity > MAXLISTSIZE)\n    GError(GVEC_CAPACITY_ERR, NewCapacity);\n    //error: NewCapacity MUST be > fCount\n   //if you want to shrink it use Resize() or setCount()\n  if (NewCapacity!=fCapacity) {\n   if (NewCapacity==0) {\n      if (IsPrimitiveType<OBJ>::VAL) {\n       GFREE(fArray);\n      } else {\n       delete[] fArray;\n       fArray=NULL;\n      }\n   }\n   else {\n      if (IsPrimitiveType<OBJ>::VAL) {\n        GREALLOC(fArray, NewCapacity*sizeof(OBJ));\n      } else {\n        OBJ* oldArray=fArray;\n\t\t//fArray=new OBJ[NewCapacity]();\n\t\tfArray=new OBJ[NewCapacity];\n        for (int i=0;i<this->fCount;i++) {\n          fArray[i] = oldArray[i]; \n          }// we need operator= here\n        //wouldn't be faster to use memcpy instead?\n        //memcpy(fArray, oldArray, fCount*sizeof(OBJ));\n        if (oldArray) delete[] oldArray;\n      }\n   }\n  fCapacity=NewCapacity;\n  }\n}\n\ntemplate <class OBJ> void GVec<OBJ>::Clear() {\n  fCount=0;\n  if (IsPrimitiveType<OBJ>::VAL) {\n    GFREE(fArray);\n  }\n  else {\n    delete[] fArray;\n    fArray=NULL;\n  }\n  fCapacity=0;\n}\n\ntemplate <class OBJ> void GVec<OBJ>::Grow() {\n int delta = (fCapacity>8) ? (fCapacity>>2) : 1 ;\n setCapacity(fCapacity + delta);\n}\n\ntemplate <class OBJ> void GVec<OBJ>::Reverse() {\n  int l=0;\n  int r=fCount-1;\n  OBJ c;\n  while (l<r) {\n     c=fArray[l];fArray[l]=fArray[r];\n     fArray[r]=c;\n     l++;r--;\n     }\n}\n\ntemplate <class OBJ> void GVec<OBJ>::Grow(int idx, OBJ& item) {\n int delta = (fCapacity>8) ? (fCapacity>>2) : 1 ;\n int NewCapacity=fCapacity+delta;\n if (NewCapacity <= fCount || NewCapacity >= MAXLISTSIZE)\n    GError(GVEC_CAPACITY_ERR, NewCapacity);\n    //error: capacity not within range\n //if (NewCapacity!=fCapacity) { \n if (idx==fCount) { //append item\n         //GREALLOC(fArray, NewCapacity*sizeof(OBJ));\n         setCapacity(NewCapacity);\n         fArray[idx]=item;\n }\n else { //insert item at idx\n   OBJ* newList;\n   if (IsPrimitiveType<OBJ>::VAL) {\n        GMALLOC(newList, NewCapacity*sizeof(OBJ));\n        //copy data before idx\n        memcpy(&newList[0],&fArray[0], idx*sizeof(OBJ));\n        newList[idx]=item;\n        //copy data after idx\n        memmove(&newList[idx+1],&fArray[idx], (fCount-idx)*sizeof(OBJ));\n        //..shouldn't do this:\n        memset(&newList[fCount+1], 0, (NewCapacity-fCount-1)*sizeof(OBJ));\n        //data copied:\n        GFREE(fArray);\n   } else {\n        newList=new OBJ[NewCapacity]; //]()\n        // operator= required!\n        for (int i=0;i<idx;i++) {\n          newList[i]=fArray[i];\n          }\n        newList[idx]=item;\n        //copy data after idx\n        //memmove(&newList[idx+1],&fArray[idx], (fCount-idx)*sizeof(OBJ));\n        for (int i=idx+1;i<=fCount;i++) {\n          newList[i]=fArray[i-1];\n          }\n        delete[] fArray;\n   }\n   fArray=newList;\n   fCapacity=NewCapacity;\n }\n fCount++;\n}\ntemplate <class OBJ> int GVec<OBJ>::Add(OBJ* item) {\n if (item==NULL) return -1;\n if (fCount==fCapacity) Grow();\n fArray[fCount] = *item; //OBJ::operator= must copy OBJ properly!\n fCount++;\n return fCount-1;\n}\n\n\ntemplate <class OBJ> void GVec<OBJ>::Add(GVec<OBJ>& list) {\n  if (list.Count()==0) return;\n  //simply copy\n  setCapacity(fCapacity+list.fCount);\n  if (IsPrimitiveType<OBJ>::VAL) {\n    memcpy( &fArray[fCount], list.fArray, list.fCount*sizeof(OBJ));\n    }\n   else {\n    for (int i=0;i<list.fCount;i++)\n          fArray[fCount+i]=list.fArray[i];\n    }\n  fCount+=list.fCount;\n}\n\n//Stack usage:\ntemplate <class OBJ> OBJ GVec<OBJ>::Pop() {\n if (fCount<=0) GError(\"Error: invalid GVec::Pop() operation!\\n\");\n fCount--;\n //OBJ o(fArray[fCount]); //copy constructor\n //o=fList[fCount];\n //fArray[fCount]=NULL;\n return fArray[fCount]; //copy of the last element (copy constructor called)\n}\n\n//Queue usage:\ntemplate <class OBJ> OBJ GVec<OBJ>::Shift() {\n if (fCount<=0) GError(\"Error: invalid GVec::Shift() operation!\\n\");\n fCount--;\n OBJ o(fArray[0]); //copy constructor\n if (fCount>0)\n   memmove(&fArray[0], &fArray[1], (fCount)*sizeof(OBJ));\n //fList[fCount]=NULL; //not that it matters..\n return o;\n}\n\ntemplate <class OBJ> void GVec<OBJ>::Insert(int idx, OBJ* item) {\n //idx must be the new position this new item must have\n //so the allowed range is [0..fCount]\n //the old idx item all the above will be shifted to idx+1\n if (idx<0 || idx>fCount) GError(GVEC_INDEX_ERR, idx);\n if (fCount==fCapacity) { //need to resize the array\n    Grow(idx, *item); //expand and also copy/move data and insert the new item\n    return;\n    }\n //move data around to make room for the new item\n if (idx<fCount) {\n   //copy after-idx items (shift up) \n   if (IsPrimitiveType<OBJ>::VAL) {      \n      memmove(&fArray[idx+1],&fArray[idx], (fCount-idx)*sizeof(OBJ));\n   }\n   else {\n      for (int i=fCount; i>idx; i--) {\n          fArray[i]=fArray[i-1];\n          }\n   }\n }\n fArray[idx]=*item;\n fCount++;\n}\n\n\n/*template <class OBJ> void GVec<OBJ>::Move(int curidx, int newidx) { //swap\n if (curidx!=newidx || newidx>=fCount)\n     GError(GVEC_INDEX_ERR, newidx);\n OBJ tmp=fArray[curidx]; //copy constructor here\n fArray[curidx]=fArray[newidx];\n fArray[newidx]=tmp;\n}*/\n\n\ntemplate <class OBJ> void GVec<OBJ>::Replace(int idx, OBJ& item) {\n TEST_INDEX(idx);\n fArray[idx]=item;\n}\n\ntemplate <class OBJ> void GVec<OBJ>::Exchange(int idx1, int idx2) {\n TEST_INDEX(idx1);\n TEST_INDEX(idx2);\n OBJ item=fArray[idx1];\n fArray[idx1]=fArray[idx2];\n fArray[idx2]=item;\n}\n\n\ntemplate <class OBJ> void GVec<OBJ>::Delete(int index) {\n TEST_INDEX(index);\n fCount--;\n if (IsPrimitiveType<OBJ>::VAL) {\n   if (index<fCount) \n    //move higher elements if any (shift down)\n      memmove(&fArray[index], &fArray[index+1], (fCount-index)*sizeof(OBJ));\n   }\n else {\n   while (index<fCount) {\n      fArray[index]=fArray[index+1];\n      index++;\n      }\n  }\n}\n\ntemplate <class OBJ> void GVec<OBJ>::setCount(int NewCount) {\n\tif (NewCount<0 || NewCount > MAXLISTSIZE)\n\t   GError(GVEC_COUNT_ERR, NewCount);\n\t//if (NewCount > fCapacity) setCapacity(NewCount);\n\twhile(NewCount > fCapacity) Grow();\n\tfCount = NewCount; //new items will be populated by the default object constructor(!)\n}\n\ntemplate <class OBJ> void GVec<OBJ>::setCount(int NewCount, OBJ* v) {\n\tif (NewCount<0 || NewCount > MAXLISTSIZE)\n\t  GError(GVEC_COUNT_ERR, NewCount);\n\twhile (NewCount > fCapacity) Grow();\n\tif (NewCount>fCount) {\n\t\tfor (int i=fCount;i<NewCount;i++)\n\t\t  fArray[i]=*v;\n\t}\n\tfCount = NewCount;\n}\n\ntemplate <class OBJ> void GVec<OBJ>::setCount(int NewCount, OBJ v) {\n\tif (NewCount<0 || NewCount > MAXLISTSIZE)\n\t   GError(GVEC_COUNT_ERR, NewCount);\n\twhile (NewCount > fCapacity) Grow();\n\tif (NewCount>fCount) {\n\t\tfor (int i=fCount;i<NewCount;i++)\n\t\t  fArray[i]=v;\n\t}\n\tfCount = NewCount;\n}\n\n\ntemplate <class OBJ> void GVec<OBJ>::qSort(int l, int r, GCompareProc* cmpFunc) {\n int i, j;\n OBJ p,t;\n do {\n    i = l; j = r;\n    p = this->fArray[(l + r) >> 1];\n    do {\n      while (cmpFunc(&(this->fArray[i]), &p) < 0) i++;\n      while (cmpFunc(&(this->fArray[j]), &p) > 0) j--;\n      if (i <= j) {\n        t = this->fArray[i];\n        this->fArray[i] = this->fArray[j];\n        this->fArray[j] = t;\n        i++; j--;\n        }\n      } while (i <= j);\n    if (l < j) qSort(l, j, cmpFunc);\n    l = i;\n    } while (i < r);\n}\n\ntemplate <class OBJ> void GVec<OBJ>::Sort(GCompareProc* cmpFunc) {\n if (cmpFunc==NULL) {\n   GMessage(\"Warning: NULL compare function given, useless Sort() call.\\n\");\n   return;\n }\n if (this->fArray!=NULL && this->fCount>0)\n     qSort(0, this->fCount-1, cmpFunc);\n}\n\ntemplate <class OBJ> void GVec<OBJ>::Sort() {  \n  GCompareProc* cmpFunc = DefLTCompareProc<OBJ>;\n  Sort(cmpFunc);\n}\n\n\n//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n//*=> GPVec implementation\n\ntemplate <class OBJ> GPVec<OBJ>::GPVec(GPVec& list) { //copy constructor\n fCount=list.fCount;\n fCapacity=list.fCapacity;\n fList=NULL;\n if (fCapacity>0) {\n      GMALLOC(fList, fCapacity*sizeof(OBJ*));\n      }\n fFreeProc=list.fFreeProc;\n fCount=list.fCount;\n memcpy(fList, list.fList, fCount*sizeof(OBJ*));\n //for (int i=0;i<list.Count();i++) Add(list[i]);\n}\n\ntemplate <class OBJ> GPVec<OBJ>::GPVec(GPVec* plist) { //another copy constructor\n fCount=0;\n fCapacity=plist->fCapacity;\n fList=NULL;\n if (fCapacity>0) {\n     GMALLOC(fList, fCapacity*sizeof(OBJ*));\n     }\n fFreeProc=plist->fFreeProc;\n fCount=plist->fCount;\n memcpy(fList, plist->fList, fCount*sizeof(OBJ*));\n //for (int i=0;i<list->fCount;i++) Add(plist->Get(i));\n}\n\ntemplate <class OBJ> const GPVec<OBJ>& GPVec<OBJ>::operator=(GPVec& list) {\n if (&list!=this) {\n     Clear();\n     fFreeProc=list.fFreeProc;\n     //Attention: the object *POINTERS* are copied,\n     // but the actual object content is NOT duplicated\n     //for (int i=0;i<list.Count();i++) Add(list[i]);\n     fCount=list.fCount;\n     GMALLOC(fList, fCapacity*sizeof(OBJ*));\n     memcpy(fList, list.fList, fCount*sizeof(OBJ*));\n     }\n return *this;\n}\n\n\ntemplate <class OBJ> void GPVec<OBJ>::Add(GPVec<OBJ>& list) {\n  if (list.Count()==0) return;\n  //simply copy the pointers! -- the objects will be shared\n  setCapacity(fCapacity+list.fCount);\n  memcpy( & (fList[fCount]), list.fList, list.fCount*sizeof(OBJ*));\n  fCount+=list.fCount;\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Reverse() {\n  int l=0;\n  int r=fCount-1;\n  OBJ* c;\n  while (l<r) {\n     c=fList[l];fList[l]=fList[r];\n     fList[r]=c;\n     l++;r--;\n     }\n}\n\ntemplate <class OBJ> GPVec<OBJ>::GPVec(int init_capacity, bool free_elements) {\n  fCount=0;\n  fCapacity=0;\n  fList=NULL;\n  fFreeProc=(free_elements) ? DefaultFreeProc : NULL;\n  if (init_capacity>0)\n    setCapacity(init_capacity);\n}\n\ntemplate <class OBJ> GPVec<OBJ>::GPVec(bool free_elements) {\n  fCount=0;\n  fCapacity=0;\n  fList=NULL;\n  fFreeProc=(free_elements) ? DefaultFreeProc : NULL;\n}\n\ntemplate <class OBJ> GPVec<OBJ>::~GPVec() {\n this->Clear();//this will free the items if fFreeProc is defined\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::setCapacity(int NewCapacity) {\n  if (NewCapacity < fCount || NewCapacity > MAXLISTSIZE)\n    GError(GVEC_CAPACITY_ERR, NewCapacity);\n    //error: capacity not within range\n  if (NewCapacity!=fCapacity) {\n   if (NewCapacity==0) {\n      GFREE(fList);\n      }\n    else {\n      GREALLOC(fList, NewCapacity*sizeof(OBJ*));\n      }\n   fCapacity=NewCapacity;\n   }\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::deallocate_item(OBJ* &item) {\n if (item==NULL) return;\n if (FREEDATA) {\n   (*fFreeProc)(item);\n   item=NULL;\n   }\n else {\n  delete item;\n  item=NULL;\n  }\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Clear() {\n if (FREEDATA) {\n   for (int i=0; i<fCount; i++) {\n     (*fFreeProc)(fList[i]);\n     }\n   }\n GFREE(fList);\n fCount=0;\n fCapacity=0;\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Exchange(int idx1, int idx2) {\n TEST_INDEX(idx1);\n TEST_INDEX(idx2);\n OBJ* item=fList[idx1];\n fList[idx1]=fList[idx2];\n fList[idx2]=item;\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Expand() {\n if (fCount==fCapacity) Grow();\n //return this;\n}\n\ntemplate <class OBJ> OBJ* GPVec<OBJ>::Get(int idx) {\n TEST_INDEX(idx);\n return fList[idx];\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Grow() {\n /*\n int delta;\n if (fCapacity > 64 ) {\n   delta = (fCapacity > 0xFFF) ? 0x100 : (fCapacity>>4);\n }\n else {\n   delta = (fCapacity>8) ? (fCapacity>>2) : 1 ;\n }\n */\n\tint delta = (fCapacity>8) ? (fCapacity>>2) : 1;\n\tsetCapacity(fCapacity + delta);\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Grow(int idx, OBJ* newitem) {\n /*\n int delta;\n if (fCapacity > 64 ) {\n   delta = (fCapacity > 0xFFF) ? 0x100 : (fCapacity>>4);\n }\n else {\n   delta = (fCapacity>8) ? (fCapacity>>2) : 1 ;\n }\n */\n int delta = (fCapacity>8) ? (fCapacity>>2) : 1 ;\n int NewCapacity=fCapacity+delta;\n if (NewCapacity <= fCount || NewCapacity > MAXLISTSIZE)\n    GError(GVEC_CAPACITY_ERR, NewCapacity);\n    //error: capacity not within range\n //if (NewCapacity!=fCapacity) {\n /*if (NewCapacity==0) {\n      GFREE(fList);\n }\n else  {//add the new item\n */\n if (idx==fCount) {\n    GREALLOC(fList, NewCapacity*sizeof(OBJ*));\n    fList[idx]=newitem;\n    }\n else {\n   OBJ** newList;\n   GMALLOC(newList, NewCapacity*sizeof(OBJ*));\n   //copy data before idx\n   memcpy(&newList[0],&fList[0], idx*sizeof(OBJ*));\n   newList[idx]=newitem;\n   //copy data after idx\n   memmove(&newList[idx+1],&fList[idx], (fCount-idx)*sizeof(OBJ*));\n   memset(&newList[fCount+1], 0, (NewCapacity-fCount-1)*sizeof(OBJ*));\n   //data copied:\n   GFREE(fList);\n   fList=newList;\n   }\n fCount++; \n fCapacity=NewCapacity;\n}\n\ntemplate <class OBJ> int GPVec<OBJ>::IndexOf(pointer item) {\n for (int i=0;i<fCount;i++) {\n     if (item==(pointer)fList[i]) return i;\n     }\n return -1;\n }\n\ntemplate <class OBJ> int GPVec<OBJ>::Add(OBJ* item) {\n int result;\n if (item==NULL) return -1;\n result = fCount;\n if (result==fCapacity) this->Grow();\n fList[result]=item;\n fCount++;\n return fCount-1;\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Insert(int idx, OBJ* item) {\n //idx can be [0..fCount] so an item can be actually added\n if (idx<0 || idx>fCount) GError(GVEC_INDEX_ERR, idx);\n if (fCount==fCapacity) {\n   Grow(idx, item);\n   return;\n   }\n if (idx<fCount)\n      memmove(&fList[idx+1], &fList[idx], (fCount-idx)*sizeof(OBJ*));\n fList[idx]=item;\n fCount++;\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Move(int curidx, int newidx) { //s\n //BE_UNSORTED; //cannot do that in a sorted list!\n if (curidx!=newidx || newidx>=fCount)\n     GError(GVEC_INDEX_ERR, newidx);\n OBJ* p;\n p=Get(curidx);\n //this is a delete:\n fCount--;\n if (curidx<fCount)\n    memmove(&fList[curidx], &fList[curidx+1], (fCount-curidx)*sizeof(OBJ*));\n //-this was instead of delete\n Insert(newidx, p);\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Put(int idx, OBJ* item) {\n //WARNING: this will never free the replaced item!\n TEST_INDEX(idx);\n fList[idx]=item;\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Forget(int idx) {\n TEST_INDEX(idx);\n fList[idx]=NULL; //user should free that somewhere else\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::freeItem(int idx) {\n  TEST_INDEX(idx);\n  if (fFreeProc!=NULL) {\n      (*fFreeProc)(fList[idx]);\n      }\n    else this->DefaultFreeProc(fList[idx]);\n  fList[idx]=NULL;\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Delete(int index) {\n TEST_INDEX(index);\n if (fFreeProc!=NULL && fList[index]!=NULL) {\n   (*fFreeProc)(fList[index]); //freeItem\n   }\n fList[index]=NULL;\n fCount--;\n if (index<fCount) //move higher elements if any\n   memmove(&fList[index], &fList[index+1], (fCount-index)*sizeof(OBJ*));\n}\n\n//Stack usage:\ntemplate <class OBJ> OBJ* GPVec<OBJ>::Pop() {\n if (fCount<=0) return NULL;\n fCount--;\n OBJ* o=fList[fCount];\n fList[fCount]=NULL;\n return o;\n}\n\n//Queue usage:\ntemplate <class OBJ> OBJ* GPVec<OBJ>::Shift() {\n if (fCount<=0) return NULL;\n fCount--;\n OBJ* o=fList[0];\n if (fCount>0)\n   memmove(&fList[0], &fList[1], (fCount)*sizeof(OBJ*));\n fList[fCount]=NULL; //not that it matters..\n return o;\n}\n\n//linear search for the pointer address\ntemplate <class OBJ> int GPVec<OBJ>::RemovePtr(pointer item) {\nif (item==NULL) return -1;\nfor (int i=0;i<fCount;i++)\n   if ((pointer)fList[i] == item) {\n       Delete(i);\n       return i;\n       }\nreturn -1; //not found\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Pack()  {\n for (int i=fCount-1; i>=0; i--)\n    if (fList[i]==NULL) Delete(i); //shift rest of fList content accordingly\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::setCount(int NewCount) {\n  if (NewCount<0 || NewCount > MAXLISTSIZE)\n     GError(GVEC_COUNT_ERR, NewCount);\n  if (NewCount > fCapacity) setCapacity(NewCount);\n  if (NewCount > fCount) //pad with NULL pointers\n    memset(& fList[fCount], 0, (NewCount - fCount) * sizeof(OBJ*));\n  fCount = NewCount;\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::qSort(int L, int R, GCompareProc* cmpFunc) {\n int I, J;\n OBJ* P;\n OBJ* T;\n do {\n    I = L;\n    J = R;\n    P = this->fList[(L + R) >> 1];\n    do {\n      while (cmpFunc(this->fList[I], P) < 0) I++;\n      while (cmpFunc(this->fList[J], P) > 0) J--;\n      if (I <= J) {\n        T = this->fList[I];\n        this->fList[I] = this->fList[J];\n        this->fList[J] = T;\n        I++;\n        J--;\n        }\n      }\n    while (I <= J);\n    if (L < J) qSort(L, J, cmpFunc);\n    L = I;\n    }\n while (I < R);\n}\n\ntemplate <class OBJ> void GPVec<OBJ>::Sort(GCompareProc* cmpFunc) {\n if (cmpFunc==NULL) {\n    GMessage(\"Warning: NULL compare function given, useless Sort() call.\\n\");\n    return;\n    }\n if (this->fList!=NULL && this->fCount>0)\n     qSort(0, this->fCount-1, cmpFunc);\n}\n\n\ntemplate <class OBJ> void GPVec<OBJ>::Sort() {\n  GCompareProc* cmpFunc = DefLTCompareProc<OBJ>;\n  Sort(cmpFunc);\n}\n\n\n//---------------------------------------------------------------------------\n#endif\n"
  },
  {
    "path": "src/LICENSE",
    "content": "\n==================================================================\n                        LICENSE\n==================================================================\n\nFSA is licensed under the GNU GPL.\nMAD is licensed under the GNU GPL.\n\nPlease see the file COPYING for the text of version 3 of the\nGNU General Public License.\n\nThe bundled Java Media Framework 2.1.1e API,\nlocated in display/JMF-2.1.1e/\nis covered by the\nJavaTM Media Framework (JMF) 2.1.x Binary Code License Agreement.\n\nPlease see the file display/JMF-2.1.1e/readme.html for a \ncopy of the JavaTM Media Framework (JMF) 2.1.x Binary Code License Agreement.\n"
  },
  {
    "path": "src/Makefile.am",
    "content": "#include $(top_srcdir)/build-aux/cufflinks.mk\n\nAM_CPPFLAGS = -I$(top_srcdir)/src \n\nEXTRA_DIST = \\\n    $(top_srcdir)/AUTHORS $(top_srcdir)/make_bin.sh\n\nAM_CXXFLAGS =\n\nbin_PROGRAMS = \\\n\tcufflinks \\\n\tcuffcompare \\\n\tcuffdiff \\\n    gtf_to_sam \\\n    compress_gtf \\\n    gffread \\\n    cuffquant \\\n    cuffnorm\n#    cuffcluster \n#\tgtf_reads\n\nnoinst_HEADERS = \\\n\tupdate_check.h \\\n\tbiascorrection.h \\\n\tcodons.h \\\n\tclustering.h \\\n\tdifferential.h \\\n\tGArgs.h \\\n\tGBase.h \\\n\tgdna.h \\\n\tGFaSeqGet.h \\\n\tGFastaIndex.h \\\n\tgff.h \\\n\tGHash.hh \\\n\tGVec.hh \\\n\tGList.hh \\\n\tGStr.h \\\n\tassemble.h \\\n\tbundles.h \\\n\tfilters.h \\\n\thits.h \\\n\ttokenize.h \\\n\tscaffolds.h \\\n\tabundances.h \\\n\tgenes.h \\\n\ttransitive_closure.h \\\n\ttransitive_reduction.h \\\n\tgff_utils.h \\\n\tgtf_tracking.h \\\n\tprogressbar.h \\\n\tbundles.h \\\n    scaffold_graph.h \\\n    matching_merge.h \\\n    graph_optimize.h \\\n    jensen_shannon.h \\\n    sampling.h \\\n\tlemon/maps.h \\\n\tlemon/bin_heap.h \\\n\tlemon/fib_heap.h \\\n\tlemon/bipartite_matching.h \\\n\tlemon/topology.h \\\n\tlemon/bucket_heap.h \\\n\tlemon/smart_graph.h \\\n\tlemon/list_graph.h \\\n\tlemon/error.h \\\n\tlemon/graph_utils.h \\\n\tlemon/bfs.h \\\n\tlemon/dfs.h \\\n\tlemon/math.h \\\n\tlemon/tolerance.h \\\n\tlemon/graph_adaptor.h \\\n\tlemon/concept_check.h \\\n\tlemon/bits/default_map.h \\\n\tlemon/bits/array_map.h \\\n\tlemon/bits/vector_map.h \\\n\tlemon/bits/debug_map.h \\\n\tlemon/bits/map_extender.h \\\n\tlemon/bits/base_extender.h \\\n\tlemon/bits/graph_adaptor_extender.h \\\n\tlemon/bits/graph_extender.h \\\n\tlemon/bits/invalid.h \\\n\tlemon/bits/path_dump.h \\\n\tlemon/bits/traits.h \\\n\tlemon/bits/utility.h \\\n\tlemon/bits/alteration_notifier.h \\\n\tlemon/bits/variant.h \\\n\tlemon/concepts/graph.h \\\n\tlemon/concepts/bpugraph.h \\\n\tlemon/concepts/graph_components.h \\\n\tlemon/concepts/ugraph.h \\\n\tlemon/concepts/heap.h \\\n\tlemon/concepts/maps.h \\\n\tlemon/concepts/path.h \\\n\tlemon/concepts/matrix_maps.h \\\n    locfit/design.h\t\\\n    locfit/lfcons.h\t\\\n    locfit/lfstruc.h \\\n    locfit/local.h \\\n    locfit/imatlb.h\t\\\n    locfit/lffuns.h\t\\\n    locfit/lfwin.h \\\n    locfit/mutil.h \\\n    locfit/vari.hpp \\\n    replicates.h \\\n    multireads.h \\\n    rounding.h \\\n    negative_binomial_distribution.h \\\n    tracking.h \\\n\tcommon.h\n\nnoinst_LIBRARIES = libcufflinks.a libgc.a\n\nlibcufflinks_a_SOURCES = \\\n\tclustering.cpp \\\n\tdifferential.cpp \\\n\tcommon.cpp \\\n\tassemble.cpp \\\n\ttokenize.cpp \\\n\tabundances.cpp \\\n\tscaffolds.cpp \\\n\thits.cpp \\\n\tgenes.cpp \\\n\tbundles.cpp \\\n\tfilters.cpp \\\n    scaffold_graph.cpp \\\n    matching_merge.cpp \\\n    graph_optimize.cpp \\\n    biascorrection.cpp \\\n    sampling.cpp \\\n    locfit/adap.c \\\n    locfit/ar_funs.c \\\n    locfit/arith.c \\\n    locfit/band.c \\\n    locfit/c_args.c \\\n    locfit/c_plot.c \\\n    locfit/cmd.c \\\n    locfit/dens_haz.c \\\n    locfit/dens_int.c \\\n    locfit/dens_odi.c \\\n    locfit/density.c \\\n    locfit/dist.c \\\n    locfit/ev_atree.c \\\n    locfit/ev_interp.c \\\n    locfit/ev_kdtre.c \\\n    locfit/ev_main.c \\\n    locfit/ev_trian.c \\\n    locfit/family.c \\\n    locfit/fitted.c \\\n    locfit/frend.c \\\n    locfit/help.c \\\n    locfit/lf_dercor.c \\\n    locfit/lf_fitfun.c \\\n    locfit/lf_robust.c \\\n    locfit/lf_vari.c \\\n    locfit/lfd.c \\\n    locfit/lfstr.c \\\n    locfit/linalg.c \\\n    locfit/locfit.c \\\n    locfit/m_chol.c \\\n    locfit/m_eigen.c \\\n    locfit/m_jacob.c \\\n    locfit/m_max.c \\\n    locfit/makecmd.c \\\n    locfit/math.c \\\n    locfit/minmax.c \\\n    locfit/nbhd.c \\\n    locfit/pcomp.c \\\n    locfit/pout.c \\\n    locfit/preplot.c \\\n    locfit/random.c \\\n    locfit/readfile.c \\\n    locfit/scb.c \\\n    locfit/scb_cons.c \\\n    locfit/simul.c \\\n    locfit/solve.c \\\n    locfit/startlf.c \\\n    locfit/strings.c \\\n    locfit/vari.cpp \\\n    locfit/wdiag.c \\\n    locfit/weight.c \\\n    replicates.cpp \\\n    multireads.cpp \\\n    jensen_shannon.cpp \\\n    tracking.cpp\n\t\nlibgc_a_SOURCES = \\\n\tcodons.cpp \\\n\tGArgs.cpp \\\n\tGBase.cpp \\\n\tgdna.cpp \\\n\tGStr.cpp \\\n\tGFaSeqGet.cpp \\\n\tGFastaIndex.cpp \\\n\tgff.cpp \\\n\tgff_utils.cpp \\\n\tgtf_tracking.cpp \n\n#-- scripts to be installed in $prefix/bin\ndist_bin_SCRIPTS = \\\n\tcuffmerge\n\nCLEANFILES = $(bin_SCRIPTS)\n\n#SUFFIXES = .py\n#.py:\n#\t(echo '#!$(PYTHON)'; sed '/^#!/d' $<) > $@\n\ncufflinks_SOURCES = cufflinks.cpp  \ncufflinks_LDADD = libcufflinks.a libgc.a $(BOOST_THREAD_LIB) $(BOOST_SYSTEM_LIB)  $(BOOST_SERIALIZATION_LIB) $(BOOST_FILESYSTEM_LIB)  $(BAM_LIB) \ncufflinks_LDFLAGS =  $(LDFLAGS) $(BOOST_LDFLAGS) $(BAM_LDFLAGS) #$(ZLIB_LDFLAGS) \n\ncuffcompare_SOURCES = cuffcompare.cpp\ncuffcompare_LDADD = libgc.a\n\ngffread_SOURCES = gffread.cpp\ngffread_LDADD = libgc.a\n\ncuffdiff_SOURCES = cuffdiff.cpp\ncuffdiff_LDADD = libcufflinks.a libgc.a $(BOOST_THREAD_LIB) $(BOOST_SYSTEM_LIB) $(BOOST_SERIALIZATION_LIB) $(BOOST_FILESYSTEM_LIB) $(BAM_LIB)\ncuffdiff_LDFLAGS =  $(LDFLAGS) $(BOOST_LDFLAGS) $(BAM_LDFLAGS) \n\ncuffquant_SOURCES = cuffquant.cpp\ncuffquant_LDADD = libcufflinks.a libgc.a $(BOOST_THREAD_LIB) $(BOOST_SYSTEM_LIB) $(BOOST_SERIALIZATION_LIB) $(BOOST_FILESYSTEM_LIB) $(BAM_LIB)\ncuffquant_LDFLAGS =  $(LDFLAGS) $(BOOST_LDFLAGS) $(BAM_LDFLAGS) \n\ncuffnorm_SOURCES = cuffnorm.cpp\ncuffnorm_LDADD = libcufflinks.a libgc.a $(BOOST_THREAD_LIB) $(BOOST_SYSTEM_LIB) $(BOOST_SERIALIZATION_LIB) $(BOOST_FILESYSTEM_LIB) $(BAM_LIB)\ncuffnorm_LDFLAGS =  $(LDFLAGS) $(BOOST_LDFLAGS) $(BAM_LDFLAGS)\n\n\ngtf_to_sam_SOURCES = gtf_to_sam.cpp\ngtf_to_sam_LDADD = libcufflinks.a libgc.a $(BOOST_THREAD_LIB) $(BOOST_SYSTEM_LIB) $(BOOST_SERIALIZATION_LIB) $(BOOST_FILESYSTEM_LIB) $(BAM_LIB)\ngtf_to_sam_LDFLAGS =  $(LDFLAGS) $(BOOST_LDFLAGS) $(BAM_LDFLAGS) \n\n#cuffcluster_SOURCES = cuffcluster.cpp\n#cuffcluster_LDADD = libcufflinks.a libgc.a $(BOOST_THREAD_LIB) $(BOOST_SYSTEM_LIB) $(BOOST_SERIALIZATION_LIB) $(BOOST_FILESYSTEM_LIB) $(BAM_LIB)\n#cuffcluster_LDFLAGS =  $(LDFLAGS) $(BOOST_LDFLAGS) $(BAM_LDFLAGS) \n\ncompress_gtf_SOURCES = compress_gtf.cpp\ncompress_gtf_LDADD = libcufflinks.a libgc.a $(BOOST_THREAD_LIB) $(BOOST_SYSTEM_LIB) $(BOOST_SERIALIZATION_LIB) $(BOOST_FILESYSTEM_LIB) $(BAM_LIB)\ncompress_gtf_LDFLAGS =  $(LDFLAGS) $(BOOST_LDFLAGS) $(BAM_LDFLAGS) \n\n#gtf_reads_SOURCES = gtf_reads.cpp\n#gtf_reads_LDADD = libcufflinks.a libgc.a $(BOOST_THREAD_LIB) $(BOOST_SYSTEM_LIB) $(BOOST_SERIALIZATION_LIB) $(BOOST_FILESYSTEM_LIB) $(BAM_LIB) \n#gtf_reads_LDFLAGS =  $(LDFLAGS) $(BOOST_LDFLAGS) $(BAM_LDFLAGS) #$(ZLIB_LDFLAGS)\n"
  },
  {
    "path": "src/abundances.cpp",
    "content": "/*\n *  abundances.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 4/27/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n *  NOTE: some of the code in this file was derived from (Eriksson et al, 2008)\n */\n\n\n//#define BOOST_MATH_INSTRUMENT 1\n//#include <iostream>\n//#include <iomanip>\n\n#include \"abundances.h\"\n#include <numeric>\n#include <limits>\n#include <algorithm>\n\n#include <boost/numeric/ublas/vector.hpp>\n#include <boost/numeric/ublas/vector_proxy.hpp>\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/triangular.hpp>\n\n//#define BOOST_UBLAS_TYPE_CHECK 0\n#include <boost/numeric/ublas/lu.hpp>\n\n#include <boost/numeric/ublas/io.hpp>\n\n#include <boost/random/mersenne_twister.hpp>\n#include <boost/random/normal_distribution.hpp>\n#include <boost/random/uniform_int.hpp>\n#include <boost/random/variate_generator.hpp>\n#include <boost/math/constants/constants.hpp>\n#include <boost/math/tools/roots.hpp>\n#include <complex>\n#include <boost/math/tools/tuple.hpp>\n\n#include <boost/math/distributions/chi_squared.hpp>\n\n#include \"filters.h\"\n#include \"replicates.h\"\n#include \"sampling.h\"\n#include \"jensen_shannon.h\"\n#include \"rounding.h\"\n#include \"clustering.h\"\n\n\n#include \"negative_binomial_distribution.h\"\n\n\n#include <Eigen/Dense>\n//using Eigen::MatrixXd;\n\n//#ifdef  __USE_ISOC99\n///* INFINITY and NAN are defined by the ISO C99 standard */\n//#else\n//double my_infinity(void) {\n//    double zero = 0.0;\n//    return 1.0/zero;\n//}\n//double my_nan(void) {\n//    double zero = 0.0;\n//    return zero/zero;\n//}\n//#define INFINITY my_infinity()\n//#define NAN my_nan()\n//#endif\n\n#define EulerGamma 0.57721566490153286060651209008240243104215933593992\n\n/* The digamma function is the derivative of gammaln.\n \n Reference:\n J Bernardo,\n Psi ( Digamma ) Function,\n Algorithm AS 103,\n Applied Statistics,\n Volume 25, Number 3, pages 315-317, 1976.\n \n From http://www.psc.edu/~burkardt/src/dirichlet/dirichlet.f\n (with modifications for negative numbers and extra precision)\n */\ndouble digamma(double x)\n{\n    double neginf = -INFINITY;\n    static const double c = 12,\n    d1 = -EulerGamma,\n    d2 = 1.6449340668482264365, /* pi^2/6 */\n    s = 1e-6,\n    s3 = 1./12,\n    s4 = 1./120,\n    s5 = 1./252,\n    s6 = 1./240,\n    s7 = 1./132;\n    /*static const double s8 = 691/32760.0, s9 = 1/12.0, s10 = 3617/8160.0;*/\n    double result;\n#if 0\n    static double cache_x = 0;\n    static int hits = 0, total = 0;\n    total++;\n    if(x == cache_x) {\n        hits++;\n    }\n    if(total % 1000 == 1) {\n        printf(\"hits = %d, total = %d, hits/total = %g\\n\", hits, total,\n               ((double)hits)/total);\n    }\n    cache_x = x;\n#endif\n    if( x==1.0 )\n        return d1;\n    \n    /* Illegal arguments */\n    if((x == neginf) || isnan(x)) {\n        return NAN;\n    }\n    /* Singularities */\n    if((x <= 0) && (floor(x) == x)) {\n        return neginf;\n    }\n    /* Negative values */\n    /* Use the reflection formula (Jeffrey 11.1.6):\n     * digamma(-x) = digamma(x+1) + pi*cot(pi*x)\n     *\n     * This is related to the identity\n     * digamma(-x) = digamma(x+1) - digamma(z) + digamma(1-z)\n     * where z is the fractional part of x\n     * For example:\n     * digamma(-3.1) = 1/3.1 + 1/2.1 + 1/1.1 + 1/0.1 + digamma(1-0.1)\n     *               = digamma(4.1) - digamma(0.1) + digamma(1-0.1)\n     * Then we use\n     * digamma(1-z) - digamma(z) = pi*cot(pi*z)\n     */\n    if(x < 0) {\n        return digamma(1-x) + M_PI/tan(-M_PI*x);\n    }\n    /* Use Taylor series if argument <= S */\n    if(x <= s) return d1 - 1/x + d2*x;\n    /* Reduce to digamma(X + N) where (X + N) >= C */\n    result = 0;\n    while(x < c) {\n        result -= 1/x;\n        x++;\n    }\n    /* Use de Moivre's expansion if argument >= C */\n    /* This expansion can be computed in Maple via asympt(Psi(x),x) */\n    if(x >= c) {\n        double r = 1/x, t;\n        result += log(x) - 0.5*r;\n        r *= r;\n#if 0\n        result -= r * (s3 - r * (s4 - r * (s5 - r * (s6 - r * s7))));\n#else\n        /* this version for lame compilers */\n        t = (s5 - r * (s6 - r * s7));\n        result -= r * (s3 - r * (s4 - r * t));\n#endif\n    }\n    return result;\n}\n\n\n/* The trigamma function is the derivative of the digamma function.\n \n Reference:\n \n B Schneider,\n Trigamma Function,\n Algorithm AS 121,\n Applied Statistics,\n Volume 27, Number 1, page 97-99, 1978.\n \n From http://www.psc.edu/~burkardt/src/dirichlet/dirichlet.f\n (with modification for negative arguments and extra precision)\n */\ndouble trigamma(double x)\n{\n    double neginf = -INFINITY,\n    small = 1e-4,\n    large = 8,\n    c = 1.6449340668482264365, /* pi^2/6 = Zeta(2) */\n    c1 = -2.404113806319188570799476,  /* -2 Zeta(3) */\n    b2 =  1./6,\n    b4 = -1./30,\n    b6 =  1./42,\n    b8 = -1./30,\n    b10 = 5./66;\n    double result;\n    /* Illegal arguments */\n    if((x == neginf) || isnan(x)) {\n        return NAN;\n    }\n    /* Singularities */\n    if((x <= 0) && (floor(x) == x)) {\n        return neginf;\n    }\n    /* Negative values */\n    /* Use the derivative of the digamma reflection formula:\n     * -trigamma(-x) = trigamma(x+1) - (pi*csc(pi*x))^2\n     */\n    if(x < 0) {\n        result = M_PI/sin(-M_PI*x);\n        return -trigamma(1-x) + result*result;\n    }\n    /* Use Taylor series if argument <= small */\n    if(x <= small) {\n        return 1/(x*x) + c + c1*x;\n    }\n    result = 0;\n    /* Reduce to trigamma(x+n) where ( X + N ) >= B */\n    while(x < large) {\n        result += 1/(x*x);\n        x++;\n    }\n    /* Apply asymptotic formula when X >= B */\n    /* This expansion can be computed in Maple via asympt(Psi(1,x),x) */\n    if(x >= large) {\n        double r = 1/(x*x), t;\n#if 0\n        result += 0.5*r + (1 + r*(b2 + r*(b4 + r*(b6 + r*(b8 + r*b10)))))/x;\n#else\n        t = (b4 + r*(b6 + r*(b8 + r*b10)));\n        result += 0.5*r + (1 + r*(b2 + r*t))/x;\n#endif\n    }\n    return result;\n}\n\n// Returns the log likelihood of the negative binomial with a given r and the mle value of p\nlong double negbin_log_likelihood(const vector<double>& samples, long double r, long double p)\n{\n    if (samples.empty() || r == 0 || p == 0)\n    {\n        return 1.0;\n    }\n    \n    long double T1 = 0;\n    for (size_t i = 0; i < samples.size(); ++i)\n    {\n        T1 += lgamma(samples[i] + r);\n    }\n    \n    long double T2 = 0;\n    for (size_t i = 0; i < samples.size(); ++i)\n    {\n        T2 += lgamma(samples[i] + 1);\n    }\n    \n    long double T3 = samples.size() * lgamma(r);\n    long double T4 = samples.size() * r * logl(1 - p);\n    \n    long double T5 = 0;\n    for (size_t i = 0; i < samples.size(); ++i)\n    {\n        T5 += samples[i] * logl(p);\n    }\n    \n    assert ((isnan(T1) || isnan(T2) || isnan(T3) || isnan(T4) || isnan(T5)) == false);\n    long double log_likelihood = T1 - T2 - T3 + T4 + T5;\n    return log_likelihood;\n}\n\n\n// Returns the log likelihood of the negative binomial with a given r and the mle value of p\nlong double poisson_log_likelihood(const vector<double>& samples, long double lambda)\n{\n    if (samples.empty() || lambda == 0.0)\n    {\n        return 1.0;\n    }\n    \n    long double T1 = 0;\n    for (size_t i = 0; i < samples.size(); ++i)\n    {\n        T1 += samples[i] * logl(lambda);\n    }\n    \n    long double T2 = samples.size() * lambda;\n        \n    assert ((isnan(T1) || isnan(T2)) == false);\n    long double log_likelihood = T1 - T2;\n    return log_likelihood;\n}\n\n\n\n// Returns the log likelihood of the negative binomial with a given r and the mle value of p\nlong double negbin_log_likelihood_helper(const vector<double>& samples, long double r)\n{\n    long double p = 0;\n    long double mean_count = accumulate(samples.begin(), samples.end(), 0.0);\n    \n    if (r == 0 || mean_count == 0)\n    {\n        fprintf(stderr, \"Error: r must be > 0!\\n\");\n        return 0;\n    }\n    \n    if (samples.empty() == false)\n        mean_count /= samples.size();\n    \n    p = mean_count / (r + mean_count);\n    \n    long double T1 = 0;\n    for (size_t i = 0; i < samples.size(); ++i)\n    {\n        T1 += lgamma(samples[i] + r);\n    }\n\n    long double T2 = 0;\n    for (size_t i = 0; i < samples.size(); ++i)\n    {\n        T2 += lgamma(samples[i] + 1);\n    }\n\n    long double T3 = samples.size() * lgamma(r);\n    long double T4 = samples.size() * r * log(1 - p);\n    \n    long double T5 = 0;\n    for (size_t i = 0; i < samples.size(); ++i)\n    {\n        T5 += samples[i] * log(p);\n    }\n    \n    assert ((isnan(T1) || isnan(T2) || isnan(T3) || isnan(T4) || isnan(T5)) == false);\n    long double log_likelihood = T1 - T2 - T3 + T4 + T5;\n    return log_likelihood;\n}\n\n\n// Returns the log likelihood of the negative binomial with a given r and the mle value of p\nlong double negbin_log_likelihood_prime_helper(const vector<double>& samples, long double r)\n{\n    long double T1 = 0;\n    for (size_t i = 0; i < samples.size(); ++i)\n    {\n        T1 += digamma(samples[i] + r);\n    }\n    \n    long double T2 = samples.size() * digamma(r);\n    \n    long double mean_count = accumulate(samples.begin(), samples.end(), 0.0);\n    if (samples.empty() == false)\n        mean_count /= samples.size();\n\n    long double T3 = samples.size() * log(r / (r + mean_count));\n    \n    assert ((isnan(T1) || isnan(T2) || isnan(T3)) == false);\n    \n    long double log_likelihood_prime = T1 - T2 + T3;\n    return log_likelihood_prime;\n}\n\n\nstruct negbin_ll_functor\n{\n    negbin_ll_functor(const vector<double>& count_samples) : samples(count_samples){}\n    boost::math::tuple<long double, long double> operator()(long double r)\n    {\n        long double llk = negbin_log_likelihood_helper(samples, r);\n        long double llk_d = negbin_log_likelihood_prime_helper(samples, r);\n        return boost::math::make_tuple(llk, llk_d);\n    }\nprivate:\n    const vector<double>& samples;\n};\n\n\nbool fit_negbin_dist(const vector<double> samples, double& r, double& p)\n{\n    \n    if (samples.size() == 0)\n    {\n        r = 0;\n        p = 0;\n        return true;\n    }\n    \n    long double guess = accumulate(samples.begin(), samples.end(), 0.0); \n    if (samples.empty() == false)\n        guess /= samples.size();\n    \n    if (guess == 0)\n    {\n        r = 0;\n        p = 0;\n        return true;\n    }\n    \n    long double min = 0;\n    long double max = *std::max_element(samples.begin(), samples.end());\n    max *= max;\n    int digits = std::numeric_limits<double>::digits; // Maximum possible binary digits accuracy for type T.\n    \n    boost::uintmax_t max_iters = 50;\n    \n    r = boost::math::tools::newton_raphson_iterate(negbin_ll_functor(samples), guess, min, max, digits, max_iters);\n    \n    long double mean_count = accumulate(samples.begin(), samples.end(), 0.0);\n    if (samples.empty() == false)\n        mean_count /= samples.size();\n    \n    p = mean_count / (r + mean_count);\n    \n    //fprintf(stderr, \"r = %lg, p = %lg, max_r = %Lg\\n\", r, p, max);\n    \n    if (isnan(r) || isnan(p))\n    {\n        fprintf(stderr, \"warning: negative binomial parameters are Nan!\\n\");\n        return false;\n    }\n    return true;\n}\n\n\n//#define USE_LOG_CACHE\n\nvoid compute_compatibilities(const vector<boost::shared_ptr<Abundance> >& transcripts,\n                             const vector<MateHit>& alignments,\n\t\t\t\t\t\t\t vector<vector<char> >& compatibilities)\n{\n\tint M = alignments.size();\n\tint N = transcripts.size();\n\t\n\tvector<Scaffold> alignment_scaffs;\n\t\n\tfor (size_t i = 0; i < alignments.size(); ++i)\n\t{\n\t\tconst MateHit& hit = alignments[i];\n\t\talignment_scaffs.push_back(Scaffold(hit));\n\t} \n\t\n    for (int j = 0; j < N; ++j) \n    {\n\t\tboost::shared_ptr<Scaffold> transfrag_j = transcripts[j]->transfrag();\n\t\tfor (int i = 0; i < M; ++i) \n        {\n\t\t\tif (transfrag_j->contains(alignment_scaffs[i])\n\t\t\t\t&& Scaffold::compatible(*transfrag_j, alignment_scaffs[i]))\n            {\n\t\t\t\tcompatibilities[j][i] = 1;\n            }\n        }\n\t}\n}\n\nAbundanceGroup::AbundanceGroup(const vector<boost::shared_ptr<Abundance> >& abundances,\n                               const ublas::matrix<double>& gamma_covariance,\n                               const ublas::matrix<double>& iterated_exp_count_covariance,\n                               const ublas::matrix<double>& count_covariance,\n                               const ublas::matrix<double>& fpkm_covariance,\n                               const set<boost::shared_ptr<ReadGroupProperties const> >& rg_props) :\n    _abundances(abundances), \n    _iterated_exp_count_covariance(iterated_exp_count_covariance),\n    _count_covariance(count_covariance),\n    _fpkm_covariance(fpkm_covariance),\n    _gamma_covariance(gamma_covariance),\n    _salient_frags(0.0),\n    _total_frags(0.0),\n    _read_group_props(rg_props)\n{\n    // Calling calculate_FPKM_covariance() also estimates cross-replicate\n    // count variances\n    // calculate_FPKM_covariance();\n    double fpkm_var = 0.0;\n    for (size_t i = 0; i < _fpkm_covariance.size1(); ++i)\n    {\n        for (size_t j = 0; j < _fpkm_covariance.size2(); ++j)\n        {\n            assert (!isnan(_fpkm_covariance(i,j)) && !isinf(_fpkm_covariance(i,j)));\n            fpkm_var += _fpkm_covariance(i,j);\n        }\n    }\n    \n    _FPKM_variance = fpkm_var;\n    \n    if (FPKM() > 0 && final_est_run && library_type != \"transfrags\")\n    {\n        \n        ublas::matrix<double> test = _fpkm_covariance;\n        double ret = cholesky_factorize(test);\n        if (ret != 0 || (_FPKM_variance < 0 && status() == NUMERIC_OK))\n        {\n            //fprintf(stderr, \"Warning: total FPKM covariance is not positive definite (ret = %lg)!\\n\", ret);\n            for (size_t j = 0; j < _abundances.size(); ++j)\n            {\n                _abundances[j]->status(NUMERIC_FAIL);\n            }\n        }\n        \n       if(!(FPKM() == 0 || fpkm_var > 0 || status() != NUMERIC_OK))\n       {\n           //cerr << _count_covariance << endl;\n           //cerr << _fpkm_covariance << endl;\n       }\n        \n       // assert (FPKM() == 0 || fpkm_var > 0 || status() != NUMERIC_OK);\n    }\n    \n    for (size_t i = 0; i < _abundances.size(); ++i)\n    {\n        if (_fpkm_samples.empty())\n        {\n            _fpkm_samples = vector<double>(_abundances[i]->fpkm_samples().size(), 0);\n            _member_fpkm_samples = vector<Eigen::VectorXd>(_abundances[i]->fpkm_samples().size(), Eigen::VectorXd::Zero(_abundances.size()));\n        }\n        for (size_t j = 0; j < _abundances[i]->fpkm_samples().size(); ++j)\n        {\n            _fpkm_samples[j] += _abundances[i]->fpkm_samples()[j];\n            _member_fpkm_samples[j](i) = _abundances[i]->fpkm_samples()[j];\n        }\n    }\n    \n    calculate_conf_intervals();\n    \n    if (no_js_tests == false && _read_group_props.size() >= min_reps_for_js_test)\n    {\n        calculate_kappas();\n    }\n}\n\nAbundanceStatus AbundanceGroup::status() const\n{\n    bool has_lowdata_member = false;\n    bool has_ok_member = false;\n\tBOOST_FOREACH(boost::shared_ptr<Abundance> ab, _abundances)\n\t{\n\t\tif (ab->status() == NUMERIC_FAIL)\n\t\t{\n\t\t\treturn NUMERIC_FAIL;\n\t\t}\n        else if (ab->status() == NUMERIC_LOW_DATA)\n\t\t{\n\t\t\thas_lowdata_member = true;\n            //return NUMERIC_LOW_DATA;\n\t\t}\n        else if (ab->status() == NUMERIC_HI_DATA)\n\t\t{\n\t\t\treturn NUMERIC_HI_DATA;\n\t\t}\n        else if (ab->status() == NUMERIC_OK)\n\t\t{\n\t\t\thas_ok_member = true;\n\t\t}\n\t}\n    \n    if (has_ok_member == false)\n        return NUMERIC_LOW_DATA;\n    \n\treturn NUMERIC_OK;\n}\n\nvoid TranscriptAbundance::FPKM_variance(double v)\n{ \n    assert (v >= 0); \n    assert(!isnan(v));\n    _FPKM_variance = v; \n}\n\nbool AbundanceGroup::has_member_with_status(AbundanceStatus member_status) const\n{\n    BOOST_FOREACH(boost::shared_ptr<Abundance> ab, _abundances)\n\t{\n\t\tif (ab->status() == member_status)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n    return false;\n}\n\ndouble AbundanceGroup::num_fragments() const\n{\n\tdouble num_f = 0;\n\t\n\tBOOST_FOREACH(boost::shared_ptr<Abundance> ab, _abundances)\n\t{\n\t\tnum_f += ab->num_fragments();\n\t}\n    assert (!isnan(num_f));\n\treturn num_f;\n}\n\nCountPerReplicateTable AbundanceGroup::num_fragments_by_replicate() const\n{\n\tCountPerReplicateTable cpr;\n\t\n\tBOOST_FOREACH(boost::shared_ptr<Abundance> ab, _abundances)\n\t{\n\t\tif (cpr.empty())\n        {\n            cpr = ab->num_fragments_by_replicate();\n        }\n        else\n        {\n            CountPerReplicateTable ab_cpr = ab->num_fragments_by_replicate();\n            for (CountPerReplicateTable::const_iterator itr = ab_cpr.begin(); \n                 itr != ab_cpr.end();\n                 ++itr)\n            {\n                CountPerReplicateTable::iterator cpr_itr = cpr.find(itr->first);\n                assert (cpr_itr != cpr.end());\n                cpr_itr->second += itr->second;\n            }\n        }\n\t}\n    \n    //assert (cpr.empty() != false);\n\treturn cpr;\n}\n\nFPKMPerReplicateTable AbundanceGroup::FPKM_by_replicate() const\n{\n\tFPKMPerReplicateTable fpr;\n\t\n\tBOOST_FOREACH(boost::shared_ptr<Abundance> ab, _abundances)\n\t{\n        FPKMPerReplicateTable ab_fpr = ab->FPKM_by_replicate();\n        \n        for (FPKMPerReplicateTable::const_iterator itr = ab_fpr.begin();\n             itr != ab_fpr.end();\n             ++itr)\n        {\n            FPKMPerReplicateTable::iterator fpr_itr = fpr.find(itr->first);\n            if (fpr_itr != fpr.end())\n                fpr_itr->second += itr->second;\n            else\n                fpr[itr->first] = itr->second;\n        }\n\t}\n    \n    //assert (cpr.empty() != false);\n\treturn fpr;\n}\n\nStatusPerReplicateTable AbundanceGroup::status_by_replicate() const\n{\n\tStatusPerReplicateTable fpr;\n\t\n\tBOOST_FOREACH(boost::shared_ptr<Abundance> ab, _abundances)\n\t{\n\t\tif (fpr.empty())\n        {\n            fpr = ab->status_by_replicate();\n        }\n        else\n        {\n            StatusPerReplicateTable ab_fpr = ab->status_by_replicate();\n            for (StatusPerReplicateTable::const_iterator itr = ab_fpr.begin(); \n                 itr != ab_fpr.end();\n                 ++itr)\n            {\n                StatusPerReplicateTable::iterator fpr_itr = fpr.find(itr->first);\n                assert (fpr_itr != fpr.end());\n                \n                AbundanceStatus s = itr->second;\n                \n                if (s == NUMERIC_FAIL)\n                {\n                    fpr_itr->second = NUMERIC_FAIL;\n                }\n                else if (s == NUMERIC_LOW_DATA && (fpr_itr->second != NUMERIC_HI_DATA && fpr_itr->second != NUMERIC_FAIL && fpr_itr->second != NUMERIC_OK))\n                {\n                    fpr_itr->second = NUMERIC_LOW_DATA;\n                }\n                else if (s == NUMERIC_HI_DATA)\n                {\n                    fpr_itr->second = NUMERIC_HI_DATA;\n                }\n                else if (s == NUMERIC_OK && (fpr_itr->second != NUMERIC_HI_DATA && fpr_itr->second != NUMERIC_FAIL))\n                {\n                    fpr_itr->second = NUMERIC_OK;\n                }\n            }\n        }\n\t}\n    \n    //assert (cpr.empty() != false);\n\treturn fpr;\n}\n\ndouble AbundanceGroup::mass_variance() const\n{\n    double mass_var = 0;\n\t\n\tBOOST_FOREACH(boost::shared_ptr<Abundance> ab, _abundances)\n\t{\n\t\tmass_var += ab->mass_variance();\n\t}\n\treturn mass_var;\n}\n\n// This tracks the final modeled variance in the assigned counts.\ndouble AbundanceGroup::num_fragment_var() const\t\t\t\n{ \n    double frag_var = 0.0;\n    for (size_t i = 0; i < _abundances.size(); ++i)\n    {\n        for (size_t j = 0; j < _abundances.size(); ++j)\n        {\n            frag_var += _count_covariance(i,j);\n        }\n    }\n    return frag_var;\n}\n\n// This tracks the final modeled variance in the assigned counts.\ndouble AbundanceGroup::num_fragment_uncertainty_var() const\t\t\t\n{ \n    double frag_var = 0.0;\n    for (size_t i = 0; i < _abundances.size(); ++i)\n    {\n        for (size_t j = 0; j < _abundances.size(); ++j)\n        {\n            frag_var += _iterated_exp_count_covariance(i,j);\n        }\n    }\n    return frag_var;\n}\n\ndouble AbundanceGroup::FPKM() const\n{\n\tdouble fpkm = 0;\n\t\n\tBOOST_FOREACH(boost::shared_ptr<Abundance> ab, _abundances)\n\t{\n\t\tfpkm += ab->FPKM();\n\t}\n\t\n\treturn fpkm;\n}\n\ndouble AbundanceGroup::gamma() const\n{\n\tdouble gamma = 0;\n\t\n\tBOOST_FOREACH(boost::shared_ptr<Abundance> ab, _abundances)\n\t{\n\t\tgamma += ab->gamma();\n\t}\n\t\n\treturn gamma;\n}\n\nvoid TranscriptAbundance::clear_non_serialized_data()\n{\n    _fpkm_samples.clear();\n    std::vector<double>().swap(_fpkm_samples);\n    \n    if (_cond_probs)\n    {\n        _cond_probs->clear();\n        std::vector<double>().swap(*_cond_probs);\n    }\n    \n    if (_transfrag)\n    {\n        _transfrag->clear_hits();\n        _transfrag = boost::shared_ptr<Scaffold>();\n    }\n}\n\nvoid AbundanceGroup::clear_non_serialized_data()\n{\n    \n    for (size_t i = 0; i < _abundances.size(); ++i)\n    {\n        _abundances[i]->clear_non_serialized_data();\n    }\n    \n    _fpkm_samples.clear();\n    std::vector<double>().swap(_fpkm_samples);\n    _member_fpkm_samples.clear();\n    std::vector<Eigen::VectorXd>().swap(_member_fpkm_samples);\n    _assigned_count_samples.clear();\n    std::vector<Eigen::VectorXd>().swap(_assigned_count_samples);\n}\n\nvoid AbundanceGroup::filter_group(const vector<bool>& to_keep, \n\t\t\t\t\t\t\t\t  AbundanceGroup& filtered_group) const\n{\n\t//filtered_group = AbundanceGroup();\n\t\n\tassert (to_keep.size() == _abundances.size());\n\t\n\tsize_t num_kept = 0;\n\tBOOST_FOREACH(bool keeper, to_keep)\n\t{\n\t\tnum_kept += keeper;\n\t}\n\t\n\tublas::matrix<double> new_cov = ublas::zero_matrix<double>(num_kept,num_kept);\n    ublas::matrix<double> new_iterated_em_count_cov = ublas::zero_matrix<double>(num_kept,num_kept);\n    ublas::matrix<double> new_count_cov = ublas::zero_matrix<double>(num_kept,num_kept);\n    ublas::matrix<double> new_fpkm_cov = ublas::zero_matrix<double>(num_kept,num_kept);\n    \n\tvector<boost::shared_ptr<Abundance> > new_ab;\n    \n\t//vector<vector<double> > new_fpkm_samples(_fpkm_samples.size(), vector<double>(num_kept, 0));\n\t\n    // rebuild covariance matrix and abundance vector after filtration\n\t\n\tsize_t next_cov_row = 0;\n\tfor (size_t i = 0; i < _abundances.size(); ++i)\n\t{\n\t\tif (to_keep[i])\n\t\t{\n\t\t\tnew_ab.push_back(_abundances[i]);\n\t\t\tsize_t next_cov_col = 0;\n\t\t\tfor (size_t j = 0; j < _abundances.size(); ++j)\n\t\t\t{\n\t\t\t\tif (to_keep[j])\n\t\t\t\t{\n\t\t\t\t\tnew_cov(next_cov_row,next_cov_col) = _gamma_covariance(i, j);\n                    new_iterated_em_count_cov(next_cov_row,next_cov_col) = _iterated_exp_count_covariance(i, j);\n                    new_count_cov(next_cov_row,next_cov_col) = _count_covariance(i, j);\n                    new_fpkm_cov(next_cov_row,next_cov_col) = _fpkm_covariance(i, j);\n\t\t\t\t\tnext_cov_col++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnext_cov_row++;\n\t\t}\n\t}\n    \n    \n//    size_t curr_abundance_idx = 0;\n//    for (size_t i = 0; i < _abundances.size(); ++i)\n//    {\n//        if (to_keep[i])\n//\t\t{\n//            for (size_t j = 0; j < _fpkm_samples.size(); ++j)\n//            {\n//                new_fpkm_samples[j][curr_abundance_idx] = _fpkm_samples[j][i];\n//            }\n//            curr_abundance_idx++;\n//        }\n//        \n//    }\n    \n   \n    \n\tfiltered_group = AbundanceGroup(new_ab, \n                                    new_cov, \n                                    new_iterated_em_count_cov, \n                                    new_count_cov, \n                                    new_fpkm_cov,\n                                    _read_group_props);\n    //assert (filtered_group.FPKM() == 0 || new_fpkm_samples.size() > 0);\n    \n    filtered_group.description(_description);\n}\n\nvoid AbundanceGroup::get_transfrags(vector<boost::shared_ptr<Abundance> >& transfrags) const\n{\n\ttransfrags.clear();\n\tBOOST_FOREACH(boost::shared_ptr<Abundance> pA, _abundances)\n\t{\n\t\tboost::shared_ptr<Scaffold> pS = pA->transfrag();\n\t\tif (pS)\n\t\t{\n\t\t\ttransfrags.push_back(pA);\n\t\t}\n\t}\n}\n\nset<string> AbundanceGroup::gene_id() const\t\n{\n\tset<string> s;\n\t\n\tBOOST_FOREACH (boost::shared_ptr<Abundance> pA, _abundances)\n\t{\n\t\tset<string> sub = pA->gene_id();\n\t\ts.insert(sub.begin(), sub.end());\n\t}\n\t\n\treturn s;\n}\n\nset<string> AbundanceGroup::gene_name() const\t\n{\n\tset<string> s;\n\t\n\tBOOST_FOREACH (boost::shared_ptr<Abundance> pA, _abundances)\n\t{\n\t\tset<string> sub = pA->gene_name();\n\t\ts.insert(sub.begin(), sub.end());\n\t}\n\t\n\treturn s;\n}\n\n\nset<string> AbundanceGroup::tss_id() const\t\n{\n\tset<string> s;\n\n\tBOOST_FOREACH (boost::shared_ptr<Abundance> pA, _abundances)\n\t{\n\t\tset<string> sub = pA->tss_id();\n\t\ts.insert(sub.begin(), sub.end());\n\t}\n\n\treturn s;\n}\n\nset<string> AbundanceGroup::protein_id() const\t\n{\n\tset<string> s;\n\t\n\tBOOST_FOREACH (boost::shared_ptr<Abundance> pA, _abundances)\n\t{\n\t\tset<string> sub = pA->protein_id();\n\t\ts.insert(sub.begin(), sub.end());\n\t}\n\t\n\treturn s;\n}\n\nconst string& AbundanceGroup::locus_tag() const\t\n{\n\tstatic string default_locus_tag = \"-\";\n\tconst string* pLast = NULL;\n\tBOOST_FOREACH (boost::shared_ptr<Abundance> pA, _abundances)\n\t{\n\t\tif (pLast)\n\t\t{\n\t\t\tif (pA->locus_tag() != *pLast)\n\t\t\t{\n\t\t\t\tassert (false);\n\t\t\t\treturn default_locus_tag;\n\t\t\t}\n\t\t}\n\t\tpLast = &(pA->locus_tag());\n\t}\n\tif (pLast)\n\t{\n\t\treturn *pLast;\n\t}\n\t//assert (false);\n\treturn default_locus_tag;\n}\n\nconst string& AbundanceGroup::reference_tag() const\t\n{\n\tstatic string default_reference_tag = \"-\";\n\tconst string* pLast = NULL;\n\tBOOST_FOREACH (boost::shared_ptr<Abundance> pA, _abundances)\n\t{\n\t\tif (pLast)\n\t\t{\n\t\t\tif (pA->reference_tag() != *pLast)\n\t\t\t{\n\t\t\t\tassert (false);\n\t\t\t\treturn default_reference_tag;\n\t\t\t}\n\t\t}\n\t\tpLast = &(pA->reference_tag());\n\t}\n\tif (pLast)\n\t{\n\t\treturn *pLast;\n\t}\n\t//assert (false);\n\treturn default_reference_tag;\n}\n\ndouble AbundanceGroup::effective_length() const\n{\n\tdouble eff_len = 0.0;\n\tdouble group_fpkm = FPKM();\n\tif (group_fpkm == 0)\n\t\treturn 0;\n\tBOOST_FOREACH (boost::shared_ptr<Abundance> ab, _abundances)\n\t{\n\t\teff_len += (ab->effective_length() * (ab->FPKM() / group_fpkm));\n\t}\n\treturn eff_len;\n}\n\n//void AbundanceGroup::collect_read_group_props()\n//{\n//    size_t M = alignments.size();\n//    \n//\tfor (size_t i = 0; i < M; ++i)\n//\t{\t\n//\t\tif (!alignments[i].left_alignment())\n//\t\t\tcontinue;\n//        boost::shared_ptr<ReadGroupProperties const> rg_props = alignments[i].read_group_props();\n//           \n//        _read_group_props.insert(rg_props;\n//    }\n//}\n\nvoid AbundanceGroup::collect_per_replicate_mass(const vector<MateHit>& alignments,\n                                                vector<boost::shared_ptr<Abundance> >& transcripts)\n{\n    size_t M = alignments.size();\n\tsize_t N = transcripts.size();\n\t\n    //_count_per_replicate.clear();\n    \n    for (map<boost::shared_ptr<ReadGroupProperties const>, double>::iterator itr = _count_per_replicate.begin(); \n         itr != _count_per_replicate.end();\n         ++itr)\n    {\n        itr->second = 0.0;\n    }\n    \n\tif (transcripts.empty())\n\t\treturn;\n    \n    //map<boost::shared_ptr<ReadGroupProperties const>, double> count_per_replicate;\n\n    vector<boost::shared_ptr<Abundance> > mapped_transcripts; // This collects the transcripts that have alignments mapping to them\n\tcompute_cond_probs_and_effective_lengths(alignments, transcripts, mapped_transcripts);\n    \n\tfor (size_t i = 0; i < M; ++i)\n\t{\t\n\t\tif (!alignments[i].left_alignment())\n\t\t\tcontinue;\n\t\t\n\t\tbool mapped = false;\n\t\tfor (size_t j = 0; j < N; ++j)\n        {\n\t\t\tif (_abundances[j]->cond_probs()->at(i) > 0)\n            {\n\t\t\t\tmapped = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (mapped)\n        {\n            boost::shared_ptr<ReadGroupProperties const> rg_props = alignments[i].read_group_props();\n            //assert (parent != NULL);\n            pair<map<boost::shared_ptr<ReadGroupProperties const>, double>::iterator, bool> inserted;\n            inserted = _count_per_replicate.insert(make_pair(rg_props, 0.0));\n            _read_group_props.insert(rg_props);\n            \n            // these are the *internally* scaled masses.\n            double more_mass = alignments[i].collapse_mass();\n            double curr_mass = inserted.first->second;\n            assert (isnan(more_mass) == false);\n            inserted.first->second += more_mass;\n        }\n    }\n}\n\nvoid AbundanceGroup::calculate_locus_scaled_mass_and_variance(const vector<boost::shared_ptr<Abundance> >& transcripts)\n{\n\tsize_t N = transcripts.size();\n\t\n\tif (transcripts.empty())\n\t\treturn;\n    \n    double avg_X_g = 0.0;\n    double avg_mass_fraction = 0.0;\n    \n    // as long as all the read groups share the same dispersion model (currently true)\n    // then all the variances from each read group will be the same, so this\n    // averaging step isn't strictly necessary.  Computing it this way is simply\n    // convenient.\n    vector<double> avg_mass_variances(N, 0.0);\n    \n    double external_scale_factor = -1.0;\n    for (map<boost::shared_ptr<ReadGroupProperties const>, double>::iterator itr = _count_per_replicate.begin();\n         itr != _count_per_replicate.end();\n         ++itr)\n    {\n        boost::shared_ptr<ReadGroupProperties const> rg_props = itr->first;\n        \n        if (external_scale_factor < 0)\n        {\n            external_scale_factor = rg_props->external_scale_factor();\n        }\n        else\n        {\n            assert (external_scale_factor == rg_props->external_scale_factor());\n        }\n        \n        // Since the _count_per_replicate table stores internally scaled\n        // fragment counts, we need to scale the fragment counts up so we \n        // can compare between conditions, rather than just between replicates\n        // of this condition.\n        double scaled_mass = itr->second;\n        double scaled_total_mass = rg_props->normalized_map_mass();\n        avg_X_g += scaled_mass;\n        boost::shared_ptr<MassDispersionModel const> disperser = rg_props->mass_dispersion_model();\n        for (size_t j = 0; j < N; ++j)\n        {\n            double scaled_variance;\n            //scaled_variance = disperser->scale_mass_variance(scaled_mass * _abundances[j]->gamma());\n            scaled_variance = _abundances[j]->gamma() * disperser->scale_mass_variance(scaled_mass);\n            avg_mass_variances[j] += scaled_variance;\n        }\n        assert (disperser->scale_mass_variance(scaled_mass) != 0 || scaled_mass == 0); \n        \n        //assert (scaled_total_mass != 0.0);\n        avg_mass_fraction += (scaled_mass / scaled_total_mass);\n    }\n    \n    double num_replicates = _count_per_replicate.size();\n    \n    if (num_replicates)\n    {\n        avg_X_g /= num_replicates;\n        avg_mass_fraction /= num_replicates;\n        for (size_t j = 0; j < N; ++j)\n        {\n            avg_mass_variances[j] /= num_replicates;\n        }\n    }\n    \n    for (size_t j = 0; j < _abundances.size(); ++j)\n\t{\n\t\t_abundances[j]->num_fragments(_abundances[j]->gamma() * avg_X_g);\n        \n        double j_avg_mass_fraction = _abundances[j]->gamma() * avg_mass_fraction;\n        \n        _abundances[j]->mass_variance(avg_mass_variances[j]);\n        \n        if (j_avg_mass_fraction > 0)\n        {\n            double FPKM = j_avg_mass_fraction * 1000000000/ _abundances[j]->effective_length();\n            FPKM *= 1.0 / external_scale_factor;\n            \n            _abundances[j]->FPKM(FPKM);\n        }\n        else \n        {\n            _abundances[j]->FPKM(0);\n            _abundances[j]->mass_variance(0);\n        }\n\t}\n\n}\n\nint total_cond_prob_calls = 0;\nvoid collapse_equivalent_hits(const vector<MateHit>& alignments,\n                              vector<boost::shared_ptr<Abundance> >& transcripts,\n                              vector<MateHit>& nr_alignments,\n                              vector<double>& log_conv_factors, \n                              bool require_overlap = true)\n{\n    int N = transcripts.size();\n\tint M = alignments.size();\n    \n    nr_alignments.clear();\n    \n\tvector<vector<char> > compatibilities(N, vector<char>(M,0));\n\tcompute_compatibilities(transcripts, alignments, compatibilities);\n    \n    vector<vector<double> > cached_cond_probs (M, vector<double>());\n    \n    vector<bool> replaced(M, false);\n    int num_replaced = 0;\n    \n    vector<BiasCorrectionHelper> bchs;\n    for (size_t j = 0; j < N; ++j)\n    {\n        bchs.push_back(BiasCorrectionHelper(transcripts[j]->transfrag()));   \n    }\n    \n    double total_mass_pre_collapse = 0.0;\n    \n    for(int i = 0 ; i < M; ++i)\n    {\n        total_mass_pre_collapse += alignments[i].collapse_mass();\n        \n        vector<double> cond_probs_i(N,0);\n        if (replaced[i] == true)\n            continue;\n        \n        if (cached_cond_probs[i].empty())\n        {\n            for (int j = 0; j < N; ++j)\n            {\n                boost::shared_ptr<Scaffold> transfrag = transcripts[j]->transfrag();\n                \n                if (compatibilities[j][i]==1)\n                {\n                    total_cond_prob_calls++;\n                    cond_probs_i[j] = bchs[j].get_cond_prob(alignments[i]);\n                }\n                \n            }\n            cached_cond_probs[i] = cond_probs_i;\n        }\n        else\n        {\n            cond_probs_i = cached_cond_probs[i];\n        }\n        \n        MateHit* curr_align = NULL;\n        \n        nr_alignments.push_back(alignments[i]);\n        curr_align = &nr_alignments.back();\n        log_conv_factors.push_back(0);\n        \n        if (corr_multi && alignments[i].is_multi()) // don't reduce other hits into multihits\n            continue;\n        \n        bool seen_olap = false;\n        \n        for(int k = i + 1 ; k < M; ++k)\n        {\n            if (replaced[k] || (corr_multi && alignments[k].is_multi()) || alignments[i].read_group_props() != alignments[k].read_group_props())\n                continue;\n            if (require_overlap && !::overlap_in_genome(curr_align->left(), curr_align->right(),\n                                     alignments[k].left(), alignments[k].right()))\n            {\n                if (seen_olap) \n                    break;\n                else\n                    continue;\n            }\n            else\n            {\n                seen_olap = true;   \n            }\n            \n            vector<double>* cond_probs_k;\n            double last_cond_prob = -1;\n            \n            bool equiv = true;\n            \n            if (cached_cond_probs[k].empty())\n            {\n                cached_cond_probs[k] = vector<double>(N, 0.0);\n                cond_probs_k = &cached_cond_probs[k];\n                for (int j = 0; j < N; ++j)\n                {\n                    boost::shared_ptr<Scaffold> transfrag = transcripts[j]->transfrag();\n                    \n                    if (compatibilities[j][k]==1)\n                    {\n                        total_cond_prob_calls++;\n                        (*cond_probs_k)[j] = bchs[j].get_cond_prob(alignments[k]);\n                    }\n                }\n                //cached_cond_probs[k] = cond_probs_k;\n            }\n            else\n            {\n                cond_probs_k = &cached_cond_probs[k];\n            }\n               \n            \n            for (int j = 0; j < N; ++j)\n            {\n                if ((*cond_probs_k)[j] != 0 && cond_probs_i[j] != 0)\n                {\n                    double cp_j = (*cond_probs_k)[j];\n                    double cp_i = cond_probs_i[j];\n                    double ratio =  cp_j / cp_i;\n                    if (last_cond_prob == -1)\n                    {\n                        //assert(ratio < 5);\n                        last_cond_prob = ratio;\n                    }\n                    else\n                    {\n                        if (last_cond_prob != ratio)\n                        //if (abs(last_cond_prob - ratio) > 0.001)\n                        {\n                            equiv = false;\n                            break;\n                        }\n                    }\n                }\n                else if ((*cond_probs_k)[j] == 0 && cond_probs_i[j] == 0)\n                {\n                    // just do nothing in this iter.\n                    // last_cond_prob = 0.0;\n                }\n                else\n                {\n                    equiv = false;\n                    break;\n                }\n            }\n            \n            // cond_prob_i vector is a scalar multiple of cond_prob_k, so we\n            // can collapse k into i via the mass.\n            if (equiv)\n            {\n                if (last_cond_prob > 0.0)\n                {\n                    //assert(curr_align->read_group_props() == alignments[k].read_group_props());\n                    assert (last_cond_prob > 0);\n                    //double mass_muliplier = sqrt(last_cond_prob);\n                    double mass_multiplier = log(last_cond_prob);\n                    //assert(last_cond_prob < 5);\n                    assert (!isinf(mass_multiplier) && !isnan(mass_multiplier));\n                    log_conv_factors[log_conv_factors.size() - 1] += mass_multiplier; \n                    replaced[k] = true;\n                    cached_cond_probs[k].clear();\n                    vector<double>(cached_cond_probs[k]).swap(cached_cond_probs[k]);\n                    num_replaced++;\n                    double more_mass = alignments[k].collapse_mass();\n                    curr_align->incr_collapse_mass(more_mass);\n                }\n                else\n                {\n                    replaced[k] = true;\n                    num_replaced++;\n                    cached_cond_probs[k].clear();\n                    vector<double>(cached_cond_probs[k]).swap(cached_cond_probs[k]);\n                }\n            }\n            \n        }\n    }\n    \n    N = transcripts.size();\n\t//M = nr_alignments.size();\n        \n\tfor (int j = 0; j < N; ++j) \n    {\n\t\tboost::shared_ptr<Scaffold> transfrag = transcripts[j]->transfrag();\n\t\tvector<double>& cond_probs = *(new vector<double>(nr_alignments.size(),0));\n\t\t\n\t\tBiasCorrectionHelper& bch = bchs[j];\n\t\t\n        size_t last_cond_prob_idx = 0;\n\t\tfor(int i = 0 ; i < M; ++i)\n\t\t{\n            if (!cached_cond_probs[i].empty())\n            {\n                if (compatibilities[j][i]==1)\n                {\n                    assert (cached_cond_probs[i].size() > j);\n                    cond_probs[last_cond_prob_idx] = cached_cond_probs[i][j];\n                }\n                last_cond_prob_idx++;\n            }\n        }\n\t\t\n        assert (last_cond_prob_idx == nr_alignments.size());\n        \n\t\ttranscripts[j]->effective_length(bch.get_effective_length());\n\t\ttranscripts[j]->cond_probs(&cond_probs);\n\t}\n    \n    double total_mass_post_collapse = 0.0;\n    for(int i = 0 ; i < nr_alignments.size(); ++i)\n    {\n        total_mass_post_collapse += nr_alignments[i].collapse_mass();\n    }\n    \n    //assert(abs(total_mass_pre_collapse - total_mass_post_collapse) < 1);\n    \n    if (nr_alignments.size())\n    {\n        verbose_msg(\"\\nReduced %lu frags to %lu (%lf percent)\\n\", alignments.size(), nr_alignments.size(), 100.0 * (1 - nr_alignments.size()/(double)alignments.size()));\n    }\n}\n\nvoid collapse_equivalent_hits_helper(const vector<MateHit>& alignments,\n                                     vector<boost::shared_ptr<Abundance> >& transcripts,\n                                     vector<MateHit>& nr_alignments,\n                                     vector<double>& log_conv_factors)\n{\n    int N = transcripts.size();\n\tint M = alignments.size();\n    \n    if (N == 1)\n    {\n        nr_alignments = alignments;\n        log_conv_factors = vector<double>(M, 0.0);\n        return;\n    }\n    // TODO: Remove this short cut after verifying that it doesn't really make sense\n    // for large bundles.  The collapse is almost certainly more efficient.\n    // If there's a lot of transcripts, just use the old, overlap constrained \n    // version of the equivalence collapse.\n    if (N > 24)\n    {\n        collapse_equivalent_hits(alignments,\n                                 transcripts,\n                                 nr_alignments,\n                                 log_conv_factors, \n                                 true);\n        return;\n    }\n    \n    vector<vector<const MateHit*> > compat_table(1 << N);\n    vector<vector<char> > compatibilities(N, vector<char>(M,0));\n    compute_compatibilities(transcripts, alignments, compatibilities);\n    \n    for(int i = 0; i < M; ++i)\n    {\n        size_t compat_mask = 0;\n        for (int j = 0; j < N; ++j)\n        {\n            compat_mask |= ((compatibilities[j][i] !=0) << j);\n        }\n        assert (compat_mask < compat_table.size());\n        compat_table[compat_mask].push_back(&(alignments[i]));\n    }\n    \n    for (size_t i = 0; i < compat_table.size(); ++i)\n    {\n        vector<MateHit> tmp_hits;\n        vector<MateHit> tmp_nr_hits;\n        vector<double> tmp_log_conv_factors;\n        \n        for (size_t j = 0; j < compat_table[i].size(); ++j)\n        {\n            tmp_hits.push_back(*(compat_table[i][j]));\n        }\n        if (tmp_hits.empty())\n            continue;\n        collapse_equivalent_hits(tmp_hits,\n                                 transcripts,\n                                 tmp_nr_hits,\n                                 tmp_log_conv_factors, \n                                 false);\n        copy(tmp_nr_hits.begin(), tmp_nr_hits.end(), back_inserter(nr_alignments));\n        copy(tmp_log_conv_factors.begin(), tmp_log_conv_factors.end(), back_inserter(log_conv_factors));\n    }\n}\n\n\n\n\n // Sample from a multivariate normal to estimate the gamma distribution\nbool generate_count_assignment_samples(int num_draws,\n                                       const vector<double>& count_mean,\n                                       const ublas::matrix<double>& count_covariance,\n                                       vector<ublas::vector<double> >& assigned_count_samples)\n{\n    double total_frag_counts = accumulate(count_mean.begin(), count_mean.end(), 0.0);\n    \n    if (total_frag_counts == 0)\n    {\n        assigned_count_samples = vector<ublas::vector<double> > (num_draws, ublas::zero_vector<double>(count_mean.size()));\n        return true;\n    }\n    \n    boost::mt19937 rng(random_seed);\n    \n    ublas::vector<double> mle_frag_counts = ublas::zero_vector<double>(count_mean.size());\n    \n    for (size_t j = 0; j < count_mean.size(); ++j)\n    {\n        mle_frag_counts(j) = count_mean[j];\n    }\n    \n    //    cerr << \"********************\" << endl;\n    //    cerr << \"initial MLE counts: \" << mle_frag_counts << endl;\n    \n    ublas::matrix<double> mle_count_covar = count_covariance;\n    \n    ublas::matrix<double> epsilon = ublas::zero_matrix<double>(count_mean.size(),count_mean.size());\n    for (size_t i = 0; i < count_mean.size(); ++i)\n    {\n        epsilon(i,i) = 1e-6;\n    }\n    \n    mle_count_covar += epsilon; // modify matrix to avoid problems during inverse\n    \n    double ret = cholesky_factorize(mle_count_covar);\n    if (ret != 0)\n    {\n        fprintf(stderr, \"Warning: Iterated expectation count covariance matrix cannot be cholesky factorized!\\n\");\n        //fprintf(stderr, \"Warning: FPKM covariance is not positive definite (ret = %lg)!\\n\", ret);\n        //        for (size_t j = 0; j < _abundances.size(); ++j)\n        //        {\n        //            _abundances[j]->status(NUMERIC_FAIL);\n        //        }\n        return false;\n    }\n    \n    //    cerr << endl << \"Cholesky factored covariance matrix: \" << endl;\n    //    for (unsigned i = 0; i < _count_covariance.size1 (); ++ i)\n    //    {\n    //        ublas::matrix_row<ublas::matrix<double> > mr (mle_count_covar, i);\n    //        cerr << i << \" : \" << _abundances[i]->num_fragments() << \" : \";\n    //        std::cerr << i << \" : \" << mr << std::endl;\n    //    }\n    //cerr << \"======\" << endl;\n    \n    multinormal_generator<double> generator(mle_frag_counts, mle_count_covar);\n    //vector<Eigen::VectorXd> multinormal_samples;\n    \n    assigned_count_samples = vector<ublas::vector<double> > (num_draws, ublas::zero_vector<double>(count_mean.size()));\n    \n    boost::uniform_01<> uniform_dist;\n    boost::mt19937 null_rng(random_seed);\n    boost::variate_generator<boost::mt19937&, boost::uniform_01<> > uniform_gen(null_rng, uniform_dist);\n    \n    \n    for (size_t assign_idx = 0; assign_idx < num_draws; ++assign_idx)\n    {\n        \n        boost::numeric::ublas::vector<double> random_count_assign = generator.next_rand();\n        //cerr << random_count_assign << endl;\n        \n        for (size_t r_idx = 0; r_idx < random_count_assign.size(); ++r_idx)\n        {\n            if (random_count_assign(r_idx) < 0)\n                random_count_assign(r_idx) = 0;\n        }\n        \n        double total_sample_counts = accumulate(random_count_assign.begin(), random_count_assign.end(), 0.0);\n        if (total_sample_counts > 0)\n            random_count_assign = total_frag_counts * (random_count_assign / total_sample_counts);\n        else\n            random_count_assign = ublas::zero_vector<double>(count_mean.size());\n        assigned_count_samples[assign_idx] = random_count_assign;\n    }\n    \n    return true;\n}\n \nvoid calculate_gamma_mle_covariance(const std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<AbundanceGroup> >& ab_group_per_replicate,\n                                    ublas::vector<double>& estimated_gamma_mean,\n                                    ublas::matrix<double>& estimated_gamma_covariance)\n{\n    vector<ublas::vector<double> > all_assigned_count_samples;\n    \n    if (ab_group_per_replicate.empty())\n        return;\n    int num_transcripts = ab_group_per_replicate.begin()->second->abundances().size();\n    if (num_transcripts == 1)\n    {\n        estimated_gamma_mean = ublas::vector<double>(1);\n        estimated_gamma_mean(0) = 1.0;\n        \n        estimated_gamma_covariance = ublas::matrix<double>(1,1);\n        estimated_gamma_covariance(0,0) = 0.0;\n        return;\n    }\n    \n    for(std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<AbundanceGroup> >::const_iterator itr = ab_group_per_replicate.begin();\n        itr != ab_group_per_replicate.end();\n        ++itr)\n    {\n        ublas::vector<double> count_mean = ublas::zero_vector<double>(itr->second->abundances().size());\n        for (size_t i = 0; i < itr->second->abundances().size(); ++i)\n        {\n            count_mean(i) = itr->second->abundances()[i]->gamma();\n        }\n        \n        all_assigned_count_samples.push_back(count_mean);\n    }\n    \n    //    for (size_t i = 0; i < all_assigned_count_samples.size(); ++i)\n    //    {\n    //        double total = accumulate(all_assigned_count_samples[i].begin(), all_assigned_count_samples[i].end(), 0.0);\n    //        if (total > 0)\n    //            all_assigned_count_samples[i] /= total;\n    //    }\n    \n    estimated_gamma_mean = ublas::zero_vector<double>(num_transcripts);\n    estimated_gamma_covariance = ublas::zero_matrix<double>(num_transcripts, num_transcripts);\n    \n    for (size_t i = 0; i < all_assigned_count_samples.size(); ++i)\n    {\n        for (int j = 0; j < all_assigned_count_samples[i].size(); ++j)\n        {\n            assert (!isnan(all_assigned_count_samples[i](j)) && !isinf(all_assigned_count_samples[i](j)));\n        }\n        \n        estimated_gamma_mean += all_assigned_count_samples[i];\n        //\n        //expected_relative_abundances += relative_abundances[i];\n    }\n    \n    if (all_assigned_count_samples.size() > 1)\n    {\n        estimated_gamma_mean /= (all_assigned_count_samples.size() - 1);\n    }\n    \n    for (size_t i = 0; i < num_transcripts; ++i)\n    {\n        for (size_t j = 0; j < num_transcripts; ++j)\n        {\n            for (size_t k = 0 ; k < all_assigned_count_samples.size(); ++k)\n            {\n                double c = (all_assigned_count_samples[k](i) - estimated_gamma_mean(i)) * (all_assigned_count_samples[k](j) - estimated_gamma_mean(j));\n                estimated_gamma_covariance(i,j) += c;\n                \n                assert (!isinf(estimated_gamma_covariance(i,j)) && !isnan(estimated_gamma_covariance(i,j)));\n            }\n        }\n    }\n    \n    if (all_assigned_count_samples.size() > 1)\n    {\n        estimated_gamma_covariance /= (all_assigned_count_samples.size() - 1);\n    }\n}\n\nvoid calculate_fragment_assignment_distribution(const std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> >& ab_group_per_replicate,\n                                                ublas::vector<double>& estimated_gamma_mean,\n                                                ublas::matrix<double>& estimated_gamma_covariance,\n                                                vector<ublas::vector<double> >& all_assigned_count_samples)\n{\n    \n    all_assigned_count_samples.clear();\n    \n    if (ab_group_per_replicate.empty())\n        return;\n    int num_transcripts = ab_group_per_replicate.begin()->second->abundances().size();\n    if (num_transcripts == 1)\n    {\n        estimated_gamma_mean = ublas::vector<double>(1);\n        estimated_gamma_mean(0) = 1.0;\n        \n        estimated_gamma_covariance = ublas::matrix<double>(1,1);\n        estimated_gamma_covariance(0,0) = 0.0;\n        return;\n    }\n    \n    for(std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> >::const_iterator itr = ab_group_per_replicate.begin();\n        itr != ab_group_per_replicate.end();\n        ++itr)\n    {\n        vector<double> count_mean;\n        for (size_t i = 0; i < itr->second->abundances().size(); ++i)\n        {\n            count_mean.push_back(itr->second->abundances()[i]->num_fragments());\n        }\n        \n        ublas::matrix<double> count_covariance = itr->second->iterated_count_cov();\n        ublas::matrix<double> mle_error = ublas::zero_matrix<double>(count_mean.size(), count_mean.size());\n        boost::shared_ptr<const MleErrorModel> mle_model = itr->first->mle_error_model();\n        if (mle_model != NULL)\n        {\n            for (size_t i = 0; i < count_mean.size(); ++i)\n            {\n                double mle_var = mle_model->scale_mle_variance(count_mean[i]);\n                mle_error(i,i) = max(0.0, mle_var);\n            }\n            count_covariance += mle_error;\n//            cerr << endl << \"MLE error correction: \" << endl;\n//            for (unsigned i = 0; i < mle_error.size1 (); ++ i)\n//            {\n//                ublas::matrix_row<ublas::matrix<double> > mr (mle_error, i);\n//                cerr << i << \" : \" << count_mean[i] << \" : \";\n//                std::cerr << i << \" : \" << mr << std::endl;\n//            }\n//            cerr << \"======\" << endl;\n        }\n        \n        \n        vector<ublas::vector<double> > assigned_count_samples;\n        generate_count_assignment_samples(num_frag_assignments,\n                                          count_mean,\n                                          count_covariance,\n                                          assigned_count_samples);\n\n        all_assigned_count_samples.insert(all_assigned_count_samples.end(), assigned_count_samples.begin(), assigned_count_samples.end());\n    }\n    \n    for (size_t i = 0; i < all_assigned_count_samples.size(); ++i)\n    {\n        double total = accumulate(all_assigned_count_samples[i].begin(), all_assigned_count_samples[i].end(), 0.0);\n        if (total > 0)\n            all_assigned_count_samples[i] /= total;\n        //cerr << all_assigned_count_samples[i] << endl;\n    }\n    \n    estimated_gamma_mean = ublas::zero_vector<double>(num_transcripts);\n    estimated_gamma_covariance = ublas::zero_matrix<double>(num_transcripts, num_transcripts);\n    \n    for (size_t i = 0; i < all_assigned_count_samples.size(); ++i)\n    {\n        for (int j = 0; j < all_assigned_count_samples[i].size(); ++j)\n        {\n            assert (!isnan(all_assigned_count_samples[i](j)) && !isinf(all_assigned_count_samples[i](j)));\n        }\n        \n        estimated_gamma_mean += all_assigned_count_samples[i];\n        //\n        //expected_relative_abundances += relative_abundances[i];\n    }\n    \n    if (all_assigned_count_samples.size() > 1)\n    {\n        estimated_gamma_mean /= (all_assigned_count_samples.size() - 1);\n    }\n       \n    for (size_t i = 0; i < num_transcripts; ++i)\n    {\n        for (size_t j = 0; j < num_transcripts; ++j)\n        {\n            for (size_t k = 0 ; k < all_assigned_count_samples.size(); ++k)\n            {\n                double c = (all_assigned_count_samples[k](i) - estimated_gamma_mean(i)) * (all_assigned_count_samples[k](j) - estimated_gamma_mean(j));\n                estimated_gamma_covariance(i,j) += c;\n                \n                assert (!isinf(estimated_gamma_covariance(i,j)) && !isnan(estimated_gamma_covariance(i,j)));\n            }\n        }\n    }\n    \n    if (all_assigned_count_samples.size() > 1)\n    {\n        estimated_gamma_covariance /= (all_assigned_count_samples.size() - 1);\n    }\n    \n//    cerr << \"Gamma covariance: \" << endl;\n//    for (unsigned i = 0; i < estimated_gamma_covariance.size1 (); ++ i)\n//    {\n//        ublas::matrix_row<ublas::matrix<double> > mr (estimated_gamma_covariance, i);\n//        cerr << i << \" : \" << estimated_gamma_mean[i] << \" : \";\n//        std::cerr << i << \" : \" << mr << std::endl;\n//    }\n\n}\n\n\n#define PERFORM_EQUIV_COLLAPSE 1\n\n//void AbundanceGroup::calculate_abundance_for_replicate(const vector<MateHit>& alignments)\n//{\n//    \n//}\n\n\nvoid AbundanceGroup::calculate_abundance_group_variance(const vector<boost::shared_ptr<Abundance> >& transcripts,\n                                                        const std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> >& ab_group_per_replicate)\n{\n\tif (final_est_run) // Only on last estimation run\n\t{\n        // Simulate NB draws and fragment assignment under uncertainty to sample\n        // from the BNBs.\n        \n        ublas::matrix<double> count_assign_covariance;\n        \n        ublas::vector<double> estimated_gamma_mean;\n        ublas::matrix<double> estimated_gamma_covariance;\n        \n        vector<ublas::vector<double> > gamma_samples;\n        calculate_fragment_assignment_distribution(ab_group_per_replicate,\n                                                   estimated_gamma_mean,\n                                                   estimated_gamma_covariance,\n                                                   gamma_samples);\n        ublas::vector<double> estimated_count_mean = estimated_gamma_mean * num_fragments();\n        ublas::matrix<double>  estimated_count_covariance = estimated_gamma_covariance * num_fragments() * num_fragments();\n        \n        //cerr << estimated_count_mean << endl;\n        //cerr << estimated_count_covariance << endl;\n        vector<double> frags_per_transcript;\n        vector<double> frag_variances;\n        \n        for (size_t i = 0; i < _abundances.size(); ++i)\n        {\n            assert (estimated_count_mean.size() > i);\n            frags_per_transcript.push_back(estimated_count_mean[i]);\n            //frags_per_transcript.push_back(_abundances[i]->num_fragments());\n            \n            frag_variances.push_back(_abundances[i]->mass_variance());\n        }\n        \n        simulate_count_covariance(frags_per_transcript, frag_variances, estimated_count_covariance, transcripts, _count_covariance, _assigned_count_samples, &gamma_samples);\n        \n        generate_fpkm_samples();\n        \n        calculate_FPKM_covariance();\n        \n        // Derive confidence intervals from the FPKM variance/covariance matrix\n        calculate_conf_intervals();\n        \n        // Calculate the inter-group relative abundances and variances\n        if (no_js_tests == false && _read_group_props.size() >= min_reps_for_js_test)\n        {\n            calculate_kappas();\n        }\n        \n    }\n    \n//    //cerr << _count_covariance << endl;\n//    for (size_t i = 0; i < _abundances.size(); ++i)\n//    {\n//        for (size_t j = 0; j < _abundances.size(); ++j)\n//        {\n//            if (i != j)\n//            {\n//                assert(!isinf(_fpkm_covariance(i,j)) && !isnan(_fpkm_covariance(i,j)));\n//                if (_abundances[i]->transfrag()->contains(*_abundances[j]->transfrag()) &&\n//                    Scaffold::compatible(*_abundances[i]->transfrag(),*_abundances[j]->transfrag()))\n//                {\n//                    _abundances[j]->status(NUMERIC_LOW_DATA);\n//                }\n//            }\n//        }\n//    }\n    \n    //assert (FPKM() == 0 || _assigned_count_samples.size() > 0);\n    \n    //fprintf(stderr, \"Total calls to get_cond_prob = %d\\n\", total_cond_prob_calls);\n\n}\n\nvoid AbundanceGroup::calculate_abundance_for_replicate(const vector<MateHit>& alignments, bool perform_collapse)\n{\n    vector<boost::shared_ptr<Abundance> > transcripts;\n    \n\tget_transfrags(transcripts);\n\tvector<boost::shared_ptr<Abundance> > mapped_transcripts; // This collects the transcripts that have alignments mapping to them\n    \n\tvector<MateHit> nr_alignments;\n    vector<double> joint_mle_gammas;\n    \n    vector<MateHit> non_equiv_alignments;\n    vector<double> log_conv_factors;\n    \n    if (final_est_run || corr_multi || corr_bias)\n    {\n        compute_cond_probs_and_effective_lengths(alignments, transcripts, mapped_transcripts);\n        collect_per_replicate_mass(alignments, transcripts);\n        calculate_gammas(alignments, log_conv_factors, transcripts, mapped_transcripts);\n        for (size_t i = 0; i < _abundances.size(); ++i)\n        {\n            joint_mle_gammas.push_back(_abundances[i]->gamma());\n        }\n    }\n    \n    calculate_iterated_exp_count_covariance(joint_mle_gammas, alignments, transcripts, _iterated_exp_count_covariance);\n    \n    for (size_t i = 0; i < _abundances.size(); ++i)\n    {\n        _abundances[i]->num_fragment_uncertainty_var(_iterated_exp_count_covariance(i,i));\n    }\n    \n    if (corr_multi && !final_est_run)\n    {\n        update_multi_reads(alignments, mapped_transcripts);\n    }\n    \n    // Calculate the initial estimates for the number of fragments originating\n    // from each transcript, the FPKMs, and set the NB variances\n    calculate_locus_scaled_mass_and_variance(transcripts);\n}\n\nvoid AbundanceGroup::aggregate_replicate_abundances(const map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> >& ab_group_per_replicate)\n{\n    for (size_t i = 0; i < _abundances.size(); ++i)\n    {\n        CountPerReplicateTable cpr;\n        FPKMPerReplicateTable fpr;\n        StatusPerReplicateTable spr;\n        \n        double avg_fpkm = 0.0;\n        double avg_num_frags = 0.0;\n        double avg_gamma = 0.0;\n        double avg_mass_variance = 0.0;\n        double avg_effective_length = 0.0;\n        \n        map<AbundanceStatus, int> status_table;\n        status_table[NUMERIC_OK] = 0;\n        status_table[NUMERIC_LOW_DATA] = 0;\n        status_table[NUMERIC_FAIL] = 0;\n        status_table[NUMERIC_HI_DATA] = 0;\n        \n        for (std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> >::const_iterator itr = ab_group_per_replicate.begin();\n             itr != ab_group_per_replicate.end();\n             ++itr)\n        {\n            status_table[itr->second->abundances()[i]->status()] += 1;\n        }\n        \n        for (std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> >::const_iterator itr = ab_group_per_replicate.begin();\n             itr != ab_group_per_replicate.end();\n             ++itr)\n        {\n            const vector<boost::shared_ptr<Abundance> >& sc_ab = itr->second->abundances();\n            assert(itr->second->abundances().size() == _abundances.size());\n            cpr[itr->first] = itr->second->abundances()[i]->num_fragments();\n            //fprintf(stderr, \"FPKM = %lg\\n\", itr->second->abundances()[i]->FPKM());\n            fpr[itr->first] = itr->second->abundances()[i]->FPKM();\n            spr[itr->first] = itr->second->abundances()[i]->status();\n            \n            /*\n            if (itr->second->abundances()[i]->status() == NUMERIC_OK)\n            {\n                avg_fpkm += itr->second->abundances()[i]->FPKM() / (double)status_table[NUMERIC_OK];\n                avg_num_frags += itr->second->abundances()[i]->num_fragments() / (double)status_table[NUMERIC_OK];\n                avg_gamma += itr->second->abundances()[i]->gamma() / (double)status_table[NUMERIC_OK];\n                avg_mass_variance += itr->second->abundances()[i]->mass_variance() / (double)status_table[NUMERIC_OK];\n                avg_effective_length += itr->second->abundances()[i]->effective_length() / (double)status_table[NUMERIC_OK];\n            }\n            */\n            avg_fpkm += itr->second->abundances()[i]->FPKM() / (double)ab_group_per_replicate.size();\n            avg_num_frags += itr->second->abundances()[i]->num_fragments() / (double)ab_group_per_replicate.size();\n            avg_gamma += itr->second->abundances()[i]->gamma() / (double)ab_group_per_replicate.size();\n            avg_mass_variance += itr->second->abundances()[i]->mass_variance() / (double)ab_group_per_replicate.size();\n            avg_effective_length += itr->second->abundances()[i]->effective_length() / (double)ab_group_per_replicate.size();\n            \n        }\n        \n        _abundances[i]->FPKM(avg_fpkm);\n        _abundances[i]->gamma(avg_gamma);\n        _abundances[i]->num_fragments(avg_num_frags);\n        _abundances[i]->mass_variance(avg_mass_variance);\n        _abundances[i]->effective_length(avg_effective_length);\n        \n        \n        // if there was at least one good replicate, set the status to OK.  The reduced power will be reflected\n        // during testing\n        if (status_table[NUMERIC_OK] >= 1)\n        {\n            _abundances[i]->status(NUMERIC_OK);\n        }\n        else\n        {\n            if (status_table[NUMERIC_LOW_DATA] >= status_table[NUMERIC_FAIL])\n            {\n                _abundances[i]->status(NUMERIC_LOW_DATA);\n            }\n            else if (status_table[NUMERIC_HI_DATA] >= status_table[NUMERIC_FAIL])\n            {\n                _abundances[i]->status(NUMERIC_HI_DATA);\n            }\n//            else if (status_table[NUMERIC_HI_DATA] >= status_table[NUMERIC_LOW_DATA]) // not sure this ever happens in practice\n//            {\n//                _abundances[i]->status(NUMERIC_FAIL);\n//            }\n            else\n            {\n                _abundances[i]->status(NUMERIC_FAIL);\n            }\n        }\n        \n        _abundances[i]->num_fragments_by_replicate(cpr);\n        _abundances[i]->FPKM_by_replicate(fpr);\n        _abundances[i]->status_by_replicate(spr);\n    }\n}\n\nvoid AbundanceGroup::calculate_abundance(const vector<MateHit>& alignments, bool perform_collapse, bool calculate_variance)\n{\n\tvector<boost::shared_ptr<Abundance> > transcripts;\n    \n\tget_transfrags(transcripts);\n    \n    map<boost::shared_ptr<ReadGroupProperties const >, vector<MateHit> > alignments_per_read_group;\n    \n    for(std::set<boost::shared_ptr<ReadGroupProperties const > >::iterator itr = _read_group_props.begin();\n        itr != _read_group_props.end();\n        ++itr)\n    {\n        alignments_per_read_group[*itr] = vector<MateHit>();\n        \n        vector<MateHit>& rep_hits = alignments_per_read_group[*itr];\n        \n        for (size_t i = 0; i < alignments.size(); ++i)\n        {\n            if (alignments[i].read_group_props() == *itr)\n            {\n                rep_hits.push_back(alignments[i]);\n            }\n        }\n    }\n    \n    collect_per_replicate_mass(alignments, transcripts);\n    \n    std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<AbundanceGroup> > ab_group_per_replicate;\n    \n    calculate_per_replicate_abundances(transcripts,\n                                       alignments_per_read_group,\n                                       ab_group_per_replicate);\n    \n    std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> > const_ab_group_per_replicate;\n    \n    for (std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<AbundanceGroup> >::iterator itr = ab_group_per_replicate.begin();\n         itr != ab_group_per_replicate.end(); ++itr)\n    {\n        const_ab_group_per_replicate[itr->first] = itr->second;\n    }\n    \n    aggregate_replicate_abundances(const_ab_group_per_replicate);\n    \n    if (calculate_variance)\n    {\n        calculate_abundance_group_variance(transcripts, const_ab_group_per_replicate);\n    }\n}\n\nvoid AbundanceGroup::update_multi_reads(const vector<MateHit>& alignments, vector<boost::shared_ptr<Abundance> > transcripts)\n{\n\tsize_t M = alignments.size();\n\tsize_t N = transcripts.size();\n\t\n\tif (transcripts.empty())\n\t\treturn;\n    \n    for (size_t i = 0; i < M; ++i)\n\t{\n\t\tif (alignments[i].is_multi())\n\t\t{\n\t\t\tdouble expr = 0.0;\n\t\t\tfor (size_t j = 0; j < N; ++j)\n\t\t\t{\n\t\t\t\texpr += _abundances[j]->cond_probs()->at(i) * _abundances[j]->FPKM() * _abundances[j]->effective_length();\n\t\t\t}\n\t\t\talignments[i].read_group_props()->multi_read_table()->add_expr(alignments[i], expr);\n\t\t}\n\t}\n}\n\n\nlong double solve_beta(long double A, long double B, long double C)\n{\n    long double a = -C/B;\n    long double b = (A + 4*A*C/(B*B) - (4*C/B));\n    long double c = -A + B - 5*A*A*C/(B*B*B) + 10*A*C/(B*B) - 5*C/B;\n    long double d = 2*A*A*A*C/(B*B*B*B) - 6*A*A*C/(B*B*B) + 6*A*C/(B*B) - 2*C/B;\n    complex<long double> q((3*a*c - b*b)/(a*a*9.0));\n    complex<long double> r((9.0*a*c*b - 27.0*a*a*d - 2.0*b*b*b)/(a*a*a*54.0));    \n    complex<long double> s1 = std::pow((r + std::sqrt(q*q*q + r*r)),complex<long double>(1/3.0));\n    complex<long double> s2 = std::pow((r - std::sqrt(q*q*q + r*r)),complex<long double>(1/3.0));\n    complex<long double> R1 = s1 + s2 - complex<long double>(b/(a*3.0));   \n    complex<long double> R2 = -(s1+s2)/complex<long double>(2.0) - complex<long double>(b/(a*3.0)) + (s1-s2) * complex<long double>(0, sqrtl(3.0)/2.0);  \n    complex<long double> R3 = -(s1+s2)/complex<long double>(2.0) - complex<long double>(b/(a*3.0)) - (s1-s2) * complex<long double>(0, sqrtl(3.0)/2.0);\n  \n    vector<long double> roots;\n    if (R1.imag() == 0)\n        roots.push_back(R1.real());\n    if (R2.imag() == 0)\n        roots.push_back(R2.real());\n    if (R3.imag() == 0)\n        roots.push_back(R3.real());\n    sort(roots.begin(), roots.end());\n\n    if (roots.empty())\n        return 0;\n    \n    long double root = roots.back();\n    return root;\n}\n\n\n// This function takes the point estimate of the number of fragments from\n// a transcript, the iterated expection count matrix, and the locus level\n// cross replicate variance, and calculates the transcript-level cross-replicate\n// count variance\nbool estimate_count_variance(long double& variance,\n                             double gamma_t, \n                             double psi_t_count_var, \n                             double X_g, \n                             double V_X_g_t,\n                             double l_t)\n{\n    if (l_t == 0)\n    {\n        return true;\n    }\n\n    long double A = X_g * gamma_t;\n    \n    long double B = V_X_g_t;\n    \n    long double C = psi_t_count_var;\n    \n    variance = 0.0;\n    bool numeric_ok = true;\n    \n    long double dispersion = V_X_g_t - (X_g * gamma_t);\n    \n    if (psi_t_count_var < 0)\n    {\n        //fprintf (stderr, \"Warning: psi_t is negative! (psi_t = %lf)\\n\", psi_t);\n        psi_t_count_var = 0;\n    }\n    assert (psi_t_count_var >= 0);\n    \n    // we multiply A with the constants here to make things work out \n    // at the end of the routine when we multiply by the square of those\n    // constants\n    long double poisson_variance = A + psi_t_count_var;\n    long double alpha = 0.0;\n    long double beta = 0.0;\n    long double bnb_mean = 0.0;\n    long double r = 0.0;\n    \n    if (dispersion < -1 || abs(dispersion) < 1)\n    {\n        // default to poisson dispersion\n        variance = poisson_variance;\n    }\n    else // there's some detectable overdispersion here, use mixture of negative binomials\n    {\n        if (psi_t_count_var < 1) \n        {\n            // default to regular negative binomial case.\n            variance = V_X_g_t;\n        }\n        else\n        {\n            r = ceil((A * A) / (B - A));\n            \n            if (r < 0)\n            {\n                numeric_ok = false;\n            }\n\n            // exact cubic\n            beta = solve_beta(A,B,C);\n            alpha = 1.0 - (A/(A-B)) * beta;\n            //fprintf(stdout, \"%Lg\\t%Lg\\t%Lg\\n\",A,alpha,beta);\n            //if (beta <= 2 || alpha <= 1)\n            if (alpha <= 2)\n            {\n                //printf (\"Warning: beta for is %Lg\\n\", beta);\n                numeric_ok = false;\n                variance = V_X_g_t;\n            }\n            else\n            {                \n                bnb_mean = r * beta / (alpha - 1.0);\n                variance = r * (alpha + r - 1.0) * beta * (alpha + beta - 1);\n                variance /= (alpha - 2.0) * (alpha - 1.0) * (alpha - 1.0);\n            }\n            if (variance < 0)\n            {\n                numeric_ok = false;\n                variance = V_X_g_t;\n            }\n            \n            if (variance == 0 && A != 0)\n            {\n                variance = poisson_variance;\n            }\n            \n            assert (!numeric_ok || variance >= poisson_variance);\n            assert (!numeric_ok || variance >= V_X_g_t);\n            \n            if (variance < poisson_variance)\n                variance = poisson_variance;\n            \n            if (variance < V_X_g_t)\n                variance = V_X_g_t;\n            \n            //assert (abs(FPKM - mean) < 1e-3);\n        }\n    }\n    \n    if (variance < 0)\n        variance = 0;\n    \n    variance = ceil(variance);\n    \n    assert (!numeric_ok || (!isinf(variance) && !isnan(variance)));\n    assert (!numeric_ok || variance != 0 || A == 0);\n    return numeric_ok;\n}\n\n// This version of the function draws directly from the iterated expectation count covariance matrix\n// and treats the betas as normally distributed (which is a good approximation), allowing good capture\n// of their covariance without resorting to lots of expensive fragment level sampling.\nbool simulate_count_covariance(const vector<double>& num_fragments,\n                               const vector<double>& frag_variances,\n                               const ublas::matrix<double>& iterated_exp_count_covariance,\n                               const vector<boost::shared_ptr<Abundance> >& transcripts,\n                               ublas::matrix<double>& count_covariance,\n                               vector<Eigen::VectorXd>& assigned_count_samples,\n                               vector<ublas::vector<double> >* gamma_samples = NULL)\n{\n    count_covariance = ublas::zero_matrix<double>(transcripts.size(), transcripts.size());\n    \n    if (frag_variances.size() <= 1)\n    {\n        count_covariance(0,0) = frag_variances[0];\n        //return;\n    }\n    \n    double total_frag_counts = accumulate(num_fragments.begin(), num_fragments.end(), 0.0);\n    double total_var = accumulate(frag_variances.begin(), frag_variances.end(), 0.0);\n    \n    if (total_frag_counts == 0)\n    {\n        count_covariance = ublas::zero_matrix<double>(transcripts.size(), transcripts.size());\n        \n        size_t num_frags = num_frag_assignments;\n        if (gamma_samples && gamma_samples->empty() == false)\n            num_frags = gamma_samples->size();\n        \n        assigned_count_samples = vector<Eigen::VectorXd> (num_frag_count_draws * num_frags, Eigen::VectorXd::Zero(transcripts.size()));\n        return true;\n    }\n    \n    vector<ublas::vector<double> > assigned_gamma_samples;\n    \n    boost::mt19937 rng(random_seed);\n    \n    if (gamma_samples == NULL || gamma_samples->empty())\n    {\n        vector<Eigen::VectorXd > generated_counts (num_frag_count_draws, Eigen::VectorXd::Zero(transcripts.size()));\n        ublas::vector<double> mle_frag_counts = ublas::zero_vector<double>(transcripts.size());\n        \n        for (size_t j = 0; j < transcripts.size(); ++j)\n        {\n            mle_frag_counts(j) = num_fragments[j];\n        }\n        \n        //    cerr << \"********************\" << endl;\n        //    cerr << \"initial MLE counts: \" << mle_frag_counts << endl;\n        \n        ublas::matrix<double> mle_count_covar = iterated_exp_count_covariance;\n        \n        ublas::matrix<double> epsilon = ublas::zero_matrix<double>(transcripts.size(),transcripts.size());\n        for (size_t i = 0; i < transcripts.size(); ++i)\n        {\n            epsilon(i,i) = 1e-6;\n        }\n        \n        mle_count_covar += epsilon; // modify matrix to avoid problems during inverse\n        \n        double ret = cholesky_factorize(mle_count_covar);\n        if (ret != 0)\n        {\n            fprintf(stderr, \"Warning: Iterated expectation count covariance matrix cannot be cholesky factorized!\\n\");\n            //fprintf(stderr, \"Warning: FPKM covariance is not positive definite (ret = %lg)!\\n\", ret);\n            //        for (size_t j = 0; j < _abundances.size(); ++j)\n            //        {\n            //            _abundances[j]->status(NUMERIC_FAIL);\n            //        }\n            return false;\n        }\n        \n        multinormal_generator<double> generator(mle_frag_counts, mle_count_covar);\n        \n        for (size_t assign_idx = 0; assign_idx < num_frag_assignments; ++assign_idx)\n        {\n            boost::numeric::ublas::vector<double> random_count_assign;\n            double total_sample_counts = 0;\n            do {\n                random_count_assign = generator.next_rand();\n                //cerr << random_count_assign << endl;\n                \n                for (size_t r_idx = 0; r_idx < random_count_assign.size(); ++r_idx)\n                {\n                    if (random_count_assign(r_idx) < 0)\n                        random_count_assign(r_idx) = 0;\n                }\n                \n                total_sample_counts = accumulate(random_count_assign.begin(), random_count_assign.end(), 0.0);\n                if (total_sample_counts > 0)\n                    random_count_assign = total_frag_counts * (random_count_assign / total_sample_counts);\n                else\n                    random_count_assign = boost::numeric::ublas::zero_vector<double>(transcripts.size());\n            } while(total_sample_counts <= 0);\n            \n            assigned_gamma_samples.push_back(random_count_assign);\n        }\n    }\n    else\n    {\n        for (size_t assign_idx = 0; assign_idx < gamma_samples->size(); ++assign_idx)\n        {\n            boost::numeric::ublas::vector<double> random_count_assign = total_frag_counts * (*gamma_samples)[assign_idx];\n            assigned_gamma_samples.push_back(random_count_assign);\n        }\n    }\n    \n    assigned_count_samples = vector<Eigen::VectorXd> (num_frag_count_draws * assigned_gamma_samples.size(), Eigen::VectorXd::Zero(transcripts.size()));\n    \n    Eigen::VectorXd expected_generated_counts = Eigen::VectorXd::Zero(transcripts.size());\n    \n    \n    boost::uniform_01<> uniform_dist;\n    boost::mt19937 null_rng(random_seed);\n    boost::variate_generator<boost::mt19937&, boost::uniform_01<> > uniform_gen(null_rng, uniform_dist);\n    \n    \n    for (size_t assign_idx = 0; assign_idx < assigned_gamma_samples.size(); ++assign_idx)\n    {\n        boost::numeric::ublas::vector<double>& random_count_assign = assigned_gamma_samples[assign_idx];\n        \n        //cerr << random_count_assign << endl;\n        for (size_t gen_idx = 0; gen_idx < num_frag_count_draws; ++gen_idx)\n        {\n            Eigen::VectorXd generated_and_assigned_counts = Eigen::VectorXd::Zero(transcripts.size());\n            \n            for (size_t j = 0; j < transcripts.size(); ++j)\n            {\n                double r =  random_count_assign(j);\n                \n                //r = r < 1 ? 1 : r;\n                \n                if (r > 0)\n                {\n                    //double fit_var = _abundances[j]->mass_variance();\n                    \n                    double fit_var = total_var * (random_count_assign(j) / total_frag_counts);\n                    double frags = random_count_assign(j);\n                    \n                    if (fit_var - frags > 1e-1)\n                    {\n                        r *= r;\n                        double over_disp_scale = fit_var - frags;\n                        r /= over_disp_scale;\n                        \n                        double after_decimal = r - (long)r;\n                        //fprintf( stderr, \"after decimal = %lg\\n\", after_decimal);\n                        if (uniform_gen() < after_decimal)\n                            r = floor(r);\n                        else\n                            r = ceil(r);\n                        \n                        if (r == 0)\n                        {\n                            generated_and_assigned_counts(j) = 0;\n                            continue;\n                        }\n                        \n                        //double p = _abundances[j]->num_fragments() / fit_var;\n                        double p = r / (r + frags);\n                        \n                        negative_binomial_distribution<int, double> nb_j(r, p);\n                        \n                        generated_and_assigned_counts(j) = nb_j(rng);\n                        \n                    }\n                    else\n                    {\n                        double after_decimal = r - (long)r;\n                        //fprintf( stderr, \"after decimal = %lg\\n\", after_decimal);\n                        if (uniform_gen() < after_decimal)\n                            r = floor(r);\n                        else\n                            r = ceil(r);\n                        \n                        if (r == 0)\n                        {\n                            generated_and_assigned_counts(j) = 0;\n                            continue;\n                        }\n                        \n                        boost::random::poisson_distribution<int, double> nb_j(r);\n                        \n                        generated_and_assigned_counts(j) = nb_j(rng);\n                        \n                    }\n                }\n                else\n                {\n                    generated_and_assigned_counts(j) = 0;\n                }\n            }\n            //cerr << \"     assigned count sample: \" << generated_and_assigned_counts.transpose() << endl;\n            assigned_count_samples[assign_idx*num_frag_count_draws + gen_idx] = generated_and_assigned_counts;\n        }\n    }\n    \n    Eigen::VectorXd expected_counts = Eigen::VectorXd::Zero(transcripts.size());\n    Eigen::VectorXd expected_relative_abundances = Eigen::VectorXd::Zero(transcripts.size());\n    \n    for (size_t i = 0; i < assigned_count_samples.size(); ++i)\n    {\n        for (int j = 0; j < assigned_count_samples[i].size(); ++j)\n        {\n            assert (!isnan(assigned_count_samples[i](j)) && !isinf(assigned_count_samples[i](j)));\n        }\n        \n        \n        expected_counts += assigned_count_samples[i];\n        //\n        //expected_relative_abundances += relative_abundances[i];\n    }\n    if (assigned_count_samples.size() > 0)\n    {\n        expected_counts /= assigned_count_samples.size();\n        //expected_generated_counts /= assigned_counts.size();\n        //expected_relative_abundances /= assigned_counts.size();\n    }\n    \n    //    if (num_frag_assignments > 0)\n    //    {\n    //        expected_generated_counts /= num_frag_assignments;\n    //        //expected_relative_abundances /= assigned_counts.size();\n    //    }\n    \n    \n    //    cerr << \"======\" << endl;\n    //    cerr << \"updated expected counts #1: \" << endl;\n    //    std::cerr << expected_counts << std::endl;\n    //    cerr << \"updated expected generated counts #1: \" << endl;\n    //    std::cerr << expected_generated_counts << std::endl;\n    //    cerr << \"======\" << endl;\n    \n    for (size_t i = 0; i < transcripts.size(); ++i)\n    {\n        for (size_t j = 0; j < transcripts.size(); ++j)\n        {\n            for (size_t k = 0 ; k < assigned_count_samples.size(); ++k)\n            {\n                double c = (assigned_count_samples[k](i) - expected_counts(i)) * (assigned_count_samples[k](j) - expected_counts(j));\n                count_covariance(i,j) += c;\n                \n                assert (!isinf(count_covariance(i,j)) && !isnan(count_covariance(i,j)));\n                //double r = (relative_abundances[k](i) - expected_relative_abundances(i)) * (relative_abundances[k](j) - expected_relative_abundances(j));\n                //_kappa_covariance(i,j) +=\n            }\n        }\n    }\n    \n    if (assigned_count_samples.empty() == false)\n        count_covariance /= assigned_count_samples.size();\n    \n    for (size_t i = 0; i < transcripts.size(); ++i)\n    {\n        // Make sure we aren't below the fit for the single isoform case\n        if (count_covariance(i,i) < ceil(frag_variances[i]))\n        {\n            //fprintf(stderr, \"Counts for %d (var = %lg) are underdispersed, reverting to fitted variance model (%lg)\\n\", i, _count_covariance(i,i), ceil(_abundances[i]->mass_variance()));\n            count_covariance(i,i) = ceil(frag_variances[i]);\n            assert (!isinf(count_covariance(i,i)) && !isnan(count_covariance(i,i)));\n        }\n        \n        // Check that we aren't below what the Poisson model says we ought to be at\n        if (count_covariance(i,i) < ceil(num_fragments[i] + iterated_exp_count_covariance(i,i)))\n        {\n            //fprintf(stderr, \"Counts for %d (var = %lg) are underdispersed, reverting to additive variance model (%lg)\\n\", i, _count_covariance(i,i),  ceil(_abundances[i]->num_fragments() + _iterated_exp_count_covariance(i,i)));\n            count_covariance(i,i) = ceil(num_fragments[i] + iterated_exp_count_covariance(i,i));\n            assert (!isinf(count_covariance(i,i)) && !isnan(count_covariance(i,i)));\n        }\n        for (size_t j = 0; j < transcripts.size(); ++j)\n        {\n            assert (!isinf(count_covariance(i,j)) && !isnan(count_covariance(i,j)));\n        }\n    }\n    \n    return true;\n}\n\n\nvoid AbundanceGroup::generate_fpkm_samples()\n{\n    double external_scale_factor = -1.0;\n    \n    double M = 0;\n    \n    for (set<boost::shared_ptr<ReadGroupProperties const> >::iterator itr = _read_group_props.begin();\n         itr != _read_group_props.end();\n         ++itr)\n    {\n        boost::shared_ptr<ReadGroupProperties const> rg_props = *itr;\n        M += rg_props->normalized_map_mass();\n        \n        if (external_scale_factor < 0)\n        {\n            external_scale_factor = rg_props->external_scale_factor();\n        }\n        else\n        {\n            assert (external_scale_factor == rg_props->external_scale_factor());\n        }\n    }\n    \n    M /= _read_group_props.size();\n    \n    // set up individual vectors of FPKM samples for each abundance object in this group.\n    vector<vector<double> > fpkm_sample_vectors(_abundances.size());\n    vector<double> group_sum_fpkm_samples;\n    \n    vector<double> fpkm_means(_abundances.size(), 0);\n    \n    for(size_t i = 0; i < _assigned_count_samples.size(); ++i)\n    {\n        const Eigen::VectorXd sample = _assigned_count_samples[i];\n        double total_fpkm = 0;\n        \n        for (size_t j = 0; j < sample.size(); ++j)\n        {\n            double fpkm_sample =  sample[j] / M;\n            \n            if (_abundances[j]->effective_length() > 0)\n            {\n                fpkm_sample *= 1000000000;\n                fpkm_sample /= _abundances[j]->effective_length();\n                fpkm_sample /= external_scale_factor;\n                //double standard_fpkm = _abundances[j]->FPKM();\n                //fprintf(stderr, \"count = %lg, fpkm = %lg, standard fpkm = %lg\\n\", sample[j], fpkm_sample, standard_fpkm);\n            }\n            else\n            {\n                fpkm_sample = 0;\n            }\n            \n            assert (isnan(fpkm_sample) == false);\n            \n            fpkm_sample_vectors[j].push_back(fpkm_sample);\n            fpkm_means[j] += fpkm_sample;\n            total_fpkm += fpkm_sample;\n        }\n        \n        if (effective_length() > 0)\n        {\n            group_sum_fpkm_samples.push_back(total_fpkm);\n        }\n        else\n        {\n            group_sum_fpkm_samples.push_back(0);\n        }\n    }\n    \n    for (size_t i = 0; i < _abundances.size(); ++i)\n    {\n        fpkm_means[i] /= _assigned_count_samples.size();\n        _abundances[i]->fpkm_samples(fpkm_sample_vectors[i]);\n        //fprintf(stderr, \"standard fpkm = %lg, sample mean = %lg\\n\", _abundances[i]->FPKM(), fpkm_means[i]);\n    }\n    \n    vector<Eigen::VectorXd> mem_fpkm_samples;\n    for (size_t i = 0; i < fpkm_sample_vectors.size(); ++i)\n    {\n        Eigen::VectorXd sample(fpkm_sample_vectors[i].size());\n        mem_fpkm_samples.push_back(sample);\n        for (size_t j = 0; j < fpkm_sample_vectors[i].size(); ++j)\n        {\n            mem_fpkm_samples[i](j) = fpkm_sample_vectors[i][j];\n        }\n    }\n    \n    member_fpkm_samples(mem_fpkm_samples);\n    \n    fpkm_samples(group_sum_fpkm_samples);\n    \n    assert (group_sum_fpkm_samples.empty() == false);\n}\n\nvoid AbundanceGroup::calculate_FPKM_covariance()\n{\n\tif (effective_length() == 0)\n\t{\n\t\t_fpkm_covariance = ublas::zero_matrix<double>(_abundances.size(), _abundances.size());\n\t\treturn;\n\t}\n    \n    //estimate_count_covariance();\n    \n    long double total_var = 0.0;\n    \n    double abundance_weighted_length = 0.0;\n    double total_abundance = 0.0;\n    \n    double external_scale_factor = -1.0;\n    \n    double M = 0;\n    \n    for (map<boost::shared_ptr<ReadGroupProperties const>, double>::iterator itr = _count_per_replicate.begin();\n         itr != _count_per_replicate.end();\n         ++itr)\n    {\n        boost::shared_ptr<ReadGroupProperties const> rg_props = itr->first;\n        M += rg_props->normalized_map_mass();\n        \n        if (external_scale_factor < 0)\n        {\n            external_scale_factor = rg_props->external_scale_factor();\n        }\n        else\n        {\n            assert (external_scale_factor == rg_props->external_scale_factor());\n        }\n    }\n    \n    M /= _count_per_replicate.size();\n    \n    for (size_t j = 0; j < _abundances.size(); ++j)\n    {\n        abundance_weighted_length += _abundances[j]->effective_length() * _abundances[j]->FPKM();\n        total_abundance += _abundances[j]->FPKM();\n        \n        for (size_t i = 0; i < _abundances.size(); ++i)\n        {\n            _fpkm_covariance(i,j) = _count_covariance(i,j);\n            \n            // FPKMs need to be on the external scale, so we can compare them\n            // between conditions.  Counts are internally scaled up until here.\n            _fpkm_covariance(i,j) *= 1.0 / (external_scale_factor * external_scale_factor);\n            assert (!isinf(_count_covariance(i,j)) && !isnan(_fpkm_covariance(i,j)));\n            \n            long double length_i = _abundances[i]->effective_length();\n            long double length_j = _abundances[j]->effective_length();\n            assert (!isinf(length_i) && !isnan(length_i));\n            assert (!isinf(length_j) && !isnan(length_j));\n            if (length_i > 0 && length_j > 0 & M > 0)\n            {\n                _fpkm_covariance(i,j) *=\n                    ((1000000000.0 / (length_j *M)))*((1000000000.0 / (length_i *M)));\n                assert (!isinf(_fpkm_covariance(i,j)) && !isnan(_fpkm_covariance(i,j)));\n            }\n            else\n            {\n                _fpkm_covariance(i,j) = 0.0;\n            }\n            \n            if (i == j)\n            {\n                double fpkm = _abundances[i]->FPKM();\n                double fpkm_var = _fpkm_covariance(i,j);\n//                if (fpkm > 0 && fpkm_var == 0 )\n//                {\n//                    cerr << _count_covariance << endl;\n//                }\n                assert (fpkm == 0 || fpkm_var > 0 || _abundances[i]->status() != NUMERIC_OK);\n                assert (!isinf(fpkm_var) && !isnan(fpkm_var));\n                _abundances[i]->FPKM_variance(fpkm_var);\n                _abundances[i]->num_fragment_var(_count_covariance(i,j));\n                \n            }\n            \n            total_var += _fpkm_covariance(i,j);\n\n            assert (!isinf(_fpkm_covariance(i,j)) && !isnan(_fpkm_covariance(i,j)));\n        }\n    }\n    \n    _FPKM_variance = total_var;\n    \n    if (final_est_run && library_type != \"transfrags\")\n    {\n        ublas::matrix<double> test = _fpkm_covariance;\n        double ret = cholesky_factorize(test);\n        if (ret != 0 || (_FPKM_variance < 0 && status() == NUMERIC_OK))\n        {\n            //fprintf(stderr, \"Warning: FPKM covariance is not positive definite (ret = %lg)!\\n\", ret);\n            for (size_t j = 0; j < _abundances.size(); ++j)\n            {\n                _abundances[j]->status(NUMERIC_FAIL);\n            }\n        }\n\n        assert (FPKM() == 0 || _FPKM_variance > 0 || status() != NUMERIC_OK);\n    }\n    \n//    cerr << \"FPKM covariance: \" << endl;\n//    for (unsigned i = 0; i < _fpkm_covariance.size1 (); ++ i)\n//    {\n//        ublas::matrix_row<ublas::matrix<double> > mr (_fpkm_covariance, i);\n//        cerr << i << \" : \" << _abundances[i]->FPKM() << \" : \";\n//        std::cerr << i << \" : \" << mr << std::endl;\n//    }\n    \n    assert (!isinf(_FPKM_variance) && !isnan(_FPKM_variance));\n}\n\nvoid AbundanceGroup::calculate_conf_intervals()\n{\n    // We only really ever call this function for primary abundance groups\n    // (i.e. the transcript groups and read bundles with which we calculate\n    // transcript MLE expression levels.  Genes, TSS groups, etc get broken\n    // off of primary bundles, so we should not call this function on those\n    // secondary groups.  The group splitting code needs to manage the task\n    // of splitting up all the variout covariance matrices we're calculating\n    // here.\n\tif (status() == NUMERIC_OK)\n\t{\n\t\t// This will compute the transcript level FPKM confidence intervals\n\t\tfor (size_t j = 0; j < _abundances.size(); ++j)\n\t\t{\n            long double fpkm_var = _abundances[j]->FPKM_variance();\n            double FPKM_hi = 0.0;\n            double FPKM_lo = 0.0;\n            if (_abundances[j]->status() != NUMERIC_FAIL)\n            {\n                FPKM_hi = _abundances[j]->FPKM() + 2 * sqrt(fpkm_var);\n                FPKM_lo = max(0.0, (double)(_abundances[j]->FPKM() - 2 * sqrt(fpkm_var)));\n                if (!(FPKM_lo <= _abundances[j]->FPKM() && _abundances[j]->FPKM() <= FPKM_hi))\n                {\n                    //fprintf(stderr, \"Error: confidence intervals are illegal! var = %Lg, fpkm = %lg, lo = %lg, hi %lg, status = %d\\n\", fpkm_var, _abundances[j]->FPKM(), FPKM_lo, FPKM_hi, _abundances[j]->status());\n                }\n                assert (FPKM_lo <= _abundances[j]->FPKM() && _abundances[j]->FPKM() <= FPKM_hi);\n                ConfidenceInterval conf(FPKM_lo, FPKM_hi);\n                _abundances[j]->FPKM_conf(conf);\n                //_abundances[j]->FPKM_variance(fpkm_var);\n            }\n            else\n            {\n                // we shouldn't be able to get here\n                assert(false);\n                // TODO: nothing to do here?\n            }\n\t\t}\n\t\t\n        // Now build a confidence interval for the whole abundance group\n\t\tdouble group_fpkm = FPKM();\n\t\tif (group_fpkm > 0.0)\n\t\t{\n\t\t\tdouble FPKM_hi = FPKM() + 2 * sqrt(FPKM_variance());\n\t\t\tdouble FPKM_lo = max(0.0, FPKM() - 2 * sqrt(FPKM_variance()));\n\t\t\tConfidenceInterval conf(FPKM_lo, FPKM_hi);\n\t\t\tFPKM_conf(conf);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_FPKM_variance = 0.0;\n\t\t\tConfidenceInterval conf(0.0, 0.0);\n\t\t\tFPKM_conf(conf);\n\t\t}\n\t}\n\telse\n\t{\n\t\tdouble sum_transfrag_FPKM_hi = 0;\n        double max_fpkm = 0.0;\n        //double min_fpkm = 1e100;\n        \n        double avg_X_g = 0.0;\n        double avg_mass_fraction = 0.0;\n        \n        int N = _abundances.size();\n        \n        vector<double> avg_mass_variances(_abundances.size(), 0.0);\n        \n        for (map<boost::shared_ptr<ReadGroupProperties const>, double>::iterator itr = _count_per_replicate.begin();\n             itr != _count_per_replicate.end();\n             ++itr)\n        {\n            boost::shared_ptr<ReadGroupProperties const> rg_props = itr->first;\n            double scaled_mass = itr->second;\n            double scaled_total_mass = rg_props->normalized_map_mass();\n            avg_X_g += scaled_mass;\n            boost::shared_ptr<MassDispersionModel const> disperser = rg_props->mass_dispersion_model();\n            for (size_t j = 0; j < N; ++j)\n            {\n                double scaled_variance;\n                //scaled_variance = disperser->scale_mass_variance(scaled_mass * _abundances[j]->gamma());\n                scaled_variance = _abundances[j]->gamma() * disperser->scale_mass_variance(scaled_mass);\n                avg_mass_variances[j] += scaled_variance;\n            }\n            assert (disperser->scale_mass_variance(scaled_mass) != 0 || scaled_mass == 0);\n            \n            //assert (scaled_total_mass != 0.0);\n            avg_mass_fraction += (scaled_mass / scaled_total_mass);\n        }\n        \n        double num_replicates = _count_per_replicate.size();\n        \n        if (num_replicates)\n        {\n            avg_X_g /= num_replicates;\n            avg_mass_fraction /= num_replicates;\n            for (size_t j = 0; j < N; ++j)\n            {\n                avg_mass_variances[j] /= num_replicates;\n            }\n        }\n                \n\t\tBOOST_FOREACH(boost::shared_ptr<Abundance> pA, _abundances)\n\t\t{\n\t\t\tdouble FPKM_hi;\n\t\t\tdouble FPKM_lo;\n\t\t\tif (pA->effective_length() > 0 && avg_mass_fraction > 0)\n\t\t\t{\n                double norm_frag_density = 1000000000;\n                norm_frag_density /= pA->effective_length();\n                \n                norm_frag_density *= avg_mass_fraction;\n                double fpkm_high = norm_frag_density;\n                \n                double total_mass = (num_fragments() / avg_mass_fraction);\n                double fpkm_constant = 1000000000 / pA->effective_length() / total_mass;\n                double var_fpkm = mass_variance() * (fpkm_constant * fpkm_constant);\n                \n\t\t\t\tFPKM_hi = fpkm_high + 2 * sqrt(var_fpkm);\n\t\t\t\tFPKM_lo = 0.0;\n\t\t\t\tConfidenceInterval conf(FPKM_lo, FPKM_hi);\n\t\t\t\t//assert (FPKM_lo <= pA->FPKM() && pA->FPKM() <= FPKM_hi);\n\t\t\t\tpA->FPKM_conf(conf);\n                //pA->FPKM_variance(var_fpkm);\n\t\t\t\tmax_fpkm = max(sum_transfrag_FPKM_hi, FPKM_hi);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tFPKM_hi = 0.0;\n\t\t\t\tFPKM_lo = 0.0;\n\t\t\t\tConfidenceInterval conf(0.0, 0.0);\n\t\t\t\tpA->FPKM_conf(conf);\n                //pA->FPKM_variance(0.0);\n\t\t\t}\n            \n\t\t}\n\t\t// In the case of a numeric failure, the groups error bars need to be\n\t\t// set such that\n\t\tFPKM_conf(ConfidenceInterval(0.0, max_fpkm + 2 * sqrt(FPKM_variance())));\n\t}\n}\n\n\n/*\nvoid AbundanceGroup::calculate_conf_intervals()\n{\n    for (size_t j = 0; j < _abundances.size(); ++j)\n    {\n        double FPKM_hi = 0.0;\n        double FPKM_lo = numeric_limits<double>::max();\n        const vector<double> ab_j_samples = _abundances[j]->fpkm_samples();\n        vector<pair<double, double> > fpkm_samples;\n        double target_fpkm = _abundances[j]->FPKM();\n        for (size_t i = 0; i < ab_j_samples.size(); ++i)\n            fpkm_samples.push_back(make_pair(abs(ab_j_samples[i] - _abundances[j]->FPKM()), ab_j_samples[i]));\n        \n        sort(fpkm_samples.begin(), fpkm_samples.end());\n        \n        for (size_t i = 0; i < 0.95*fpkm_samples.size(); ++i)\n        {\n            if (FPKM_lo > fpkm_samples[i].second)\n                FPKM_lo = fpkm_samples[i].second;\n            if (FPKM_hi < fpkm_samples[i].second)\n                FPKM_hi = fpkm_samples[i].second;\n        }\n        \n        if (fpkm_samples.size() > 0 && FPKM_lo > target_fpkm)\n        {\n            fprintf(stderr, \"Warning: transcript confidence interval lower bound is > FPKM\\n\");\n        }\n        \n        if (fpkm_samples.size() > 0 && FPKM_hi < target_fpkm)\n        {\n            fprintf(stderr, \"Warning: transcript confidence interval upper bound is < FPKM\\n\");\n        }\n        \n        ConfidenceInterval conf(FPKM_lo, FPKM_hi);\n        _abundances[j]->FPKM_conf(conf);\n    }\n    \n    double FPKM_hi = 0.0;\n    double FPKM_lo = numeric_limits<double>::max();\n    const vector<double>& ab_j_samples = _fpkm_samples;\n    vector<pair<double, double> > fpkm_samples;\n    for (size_t i = 0; i < ab_j_samples.size(); ++i)\n        fpkm_samples.push_back(make_pair(abs(ab_j_samples[i] - FPKM()), ab_j_samples[i]));\n    \n    sort(fpkm_samples.begin(), fpkm_samples.end());\n    \n    for (size_t i = 0; i < 0.95*fpkm_samples.size(); ++i)\n    {\n        if (FPKM_lo > fpkm_samples[i].second)\n            FPKM_lo = fpkm_samples[i].second;\n        if (FPKM_hi < fpkm_samples[i].second)\n            FPKM_hi = fpkm_samples[i].second;\n    }\n    \n    double target_fpkm = FPKM();\n    \n    if (fpkm_samples.size() > 0 && FPKM_lo > target_fpkm)\n    {\n        fprintf(stderr, \"Warning: group confidence interval lower bound is > FPKM\\n\");\n    }\n    \n    if (fpkm_samples.size() > 0 && FPKM_hi < target_fpkm)\n    {\n        fprintf(stderr, \"Warning: group confidence interval upper bound is < FPKM\\n\");\n    }\n    \n    ConfidenceInterval conf(FPKM_lo, FPKM_hi);\n    FPKM_conf(conf);\n    \n    return;\n}\n\n*/\nvoid compute_cond_probs_and_effective_lengths(const vector<MateHit>& alignments,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  vector<boost::shared_ptr<Abundance> >& transcripts,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  vector<boost::shared_ptr<Abundance> >& mapped_transcripts)\n{\t\t\n\tint N = transcripts.size();\n\tint M = alignments.size();\n\n\tvector<vector<char> > compatibilities(N, vector<char>(M,0));\n\tcompute_compatibilities(transcripts, alignments, compatibilities);\n\n\tfor (int j = 0; j < N; ++j) \n    {\n\t\tboost::shared_ptr<Scaffold> transfrag = transcripts[j]->transfrag();\n\t\tvector<double>& cond_probs = *(new vector<double>(M,0));\n\t\t\n\t\tBiasCorrectionHelper bch(transfrag);\n\t\t\n\t\tfor(int i = 0 ; i < M; ++i)\n\t\t{\n\t\t\tif (compatibilities[j][i]==1)\n            {\n                total_cond_prob_calls++;\n\t\t\t\tcond_probs[i] = bch.get_cond_prob(alignments[i]);\n            }\n\t\t}\n\t\t\n\t\ttranscripts[j]->effective_length(bch.get_effective_length());\n\t\ttranscripts[j]->cond_probs(&cond_probs);\n\t\t\n\t\tif (bch.is_mapped()) \n\t\t\tmapped_transcripts.push_back(transcripts[j]);\n\t}\n}\n\n\ndouble trace(const ublas::matrix<double>& m)\n{\n    \n    double t = 0.0;\n    for (size_t i = 0.0; i < m.size1(); ++i)\n    {\n        t += m(i,i);\n    }\n    \n    return t;\n}\n\n\n// FIXME: This function doesn't really need to copy the transcripts out of \n// the cluster.  Needs refactoring\nbool AbundanceGroup::calculate_gammas(const vector<MateHit>& nr_alignments, \n                                      const vector<double>& log_conv_factors,\n\t\t\t\t\t\t\t\t\t  const vector<boost::shared_ptr<Abundance> >& transcripts, \n\t\t\t\t\t\t\t\t\t  const vector<boost::shared_ptr<Abundance> >& mapped_transcripts)\n{\n\tif (mapped_transcripts.empty())\n    {\n\t\t//gammas = vector<double>(transfrags.size(), 0.0);\n\t\tBOOST_FOREACH (boost::shared_ptr<Abundance> ab, _abundances)\n\t\t{\n\t\t\tab->gamma(0);\n\t\t}\n\t\t_gamma_covariance = ublas::zero_matrix<double>(transcripts.size(), \n                                                       transcripts.size());\n        _count_covariance = ublas::zero_matrix<double>(transcripts.size(), \n                                                       transcripts.size());\n        _iterated_exp_count_covariance = ublas::zero_matrix<double>(transcripts.size(), \n                                                       transcripts.size());\n        _fpkm_covariance = ublas::zero_matrix<double>(transcripts.size(), \n                                                      transcripts.size());\n        \n\t\treturn true;\n    }\n\t\n\tvector<double> gammas;\n\t\n\tverbose_msg( \"Calculating intial MLE\\n\");\n\t\n\tAbundanceStatus mle_success = gamma_mle(mapped_transcripts,\n                                                  nr_alignments,\n                                                  log_conv_factors,\n                                                  gammas);\n\t\n\tverbose_msg( \"Tossing likely garbage isoforms\\n\");\n\t\n\tfor (size_t i = 0; i < gammas.size(); ++i)\n\t{\n\t\tif (isnan(gammas[i]))\n\t\t{\n\t\t\tverbose_msg(\"Warning: isoform abundance is NaN!\\n\");\n\t\t}\n\t}\n\t\n    double locus_mass = 0.0;\n   \n    for (size_t i = 0; i < nr_alignments.size(); ++i)\n    {\n        const MateHit& alignment = nr_alignments[i];\n        locus_mass += alignment.collapse_mass();\n    }\n    \n\tvector<boost::shared_ptr<Abundance> > filtered_transcripts = mapped_transcripts;\n\tvector<double> filtered_gammas = gammas;\n\tfilter_junk_isoforms(filtered_transcripts, filtered_gammas, mapped_transcripts, locus_mass);\n\t\n\tif (filtered_transcripts.empty())\n\t{\n\t\t//gammas = vector<double>(transfrags.size(), 0.0);\n\t\tBOOST_FOREACH (boost::shared_ptr<Abundance> ab, _abundances)\n\t\t{\n\t\t\tab->gamma(0);\n\t\t}\n\t\t_gamma_covariance = ublas::zero_matrix<double>(transcripts.size(), \n\t\t\t\t\t\t\t\t\t\t\t\t\t  transcripts.size());\n        _count_covariance = ublas::zero_matrix<double>(transcripts.size(), \n                                                       transcripts.size());\n        _iterated_exp_count_covariance = ublas::zero_matrix<double>(transcripts.size(), \n                                                                    transcripts.size());\n        _fpkm_covariance = ublas::zero_matrix<double>(transcripts.size(), \n                                                      transcripts.size());\n        \n\t\treturn true;\n\t}\n\t\n    if (filtered_transcripts.size() != mapped_transcripts.size())\n    {    \n        filtered_gammas.clear();\n        \n        verbose_msg( \"Revising MLE\\n\");\n        \n        mle_success = gamma_mle(filtered_transcripts,\n                                        nr_alignments,\n                                        log_conv_factors, \n                                        filtered_gammas);\n    }\n\n\tfor (size_t i = 0; i < filtered_gammas.size(); ++i)\n\t{\n\t\tif (isnan(filtered_gammas[i]))\n\t\t{\n\t\t\tverbose_msg(\"Warning: isoform abundance is NaN!\\n\");\n\t\t}\n\t}\n\t\n\tsize_t N = transcripts.size();\n\t\n    set<boost::shared_ptr<ReadGroupProperties const> > rg_props;\n\tfor (size_t i = 0; i < nr_alignments.size(); ++i)\n\t{\n        rg_props.insert(nr_alignments[i].read_group_props());\n\t}\n    \n    AbundanceStatus map_success = NUMERIC_OK;\n\tif (final_est_run) // Only on last estimation run.\n\t{\n        ublas::vector<double> gamma_mle(filtered_gammas.size());\n        std::copy(filtered_gammas.begin(), filtered_gammas.end(), gamma_mle.begin());\n    }\n\t\n\tfor (size_t i = 0; i < filtered_gammas.size(); ++i)\n\t{\n\t\tif (isnan(gammas[i]))\n\t\t{\n\t\t\tverbose_msg( \"Warning: isoform abundance is NaN!\\n\");\n\t\t\tmap_success = NUMERIC_FAIL;\n\t\t}\n\t}\n\t\n\t// Now we need to fill in zeros for the isoforms we filtered out of the \n\t// MLE/MAP calculation\n\tvector<double> updated_gammas = vector<double>(N, 0.0);\n    \n    \n\tublas::matrix<double> updated_gamma_cov;\n\tupdated_gamma_cov = ublas::zero_matrix<double>(N, N);\n    \n    ublas::matrix<double> updated_count_cov;\n    updated_count_cov = ublas::zero_matrix<double>(N, N);\n    ublas::matrix<double> updated_iterated_exp_count_cov;\n    updated_iterated_exp_count_cov = ublas::zero_matrix<double>(N, N);\n    ublas::matrix<double> updated_fpkm_cov;\n    updated_fpkm_cov = ublas::zero_matrix<double>(N, N);\n\t\n\tsize_t cfs = 0;\n\tboost::shared_ptr<Scaffold> curr_filtered_scaff = filtered_transcripts[cfs]->transfrag();\n\tStructurallyEqualScaffolds se;\n\tvector<size_t> scaff_present(N, N);\n\t\n\tfor (size_t i = 0; i < N; ++i)\n\t{\n\t\tboost::shared_ptr<Scaffold> scaff_i = transcripts[i]->transfrag();\n\t\tif (cfs < filtered_transcripts.size())\n\t\t{\n\t\t\tcurr_filtered_scaff = filtered_transcripts[cfs]->transfrag();\n\t\t\tif (se(scaff_i, curr_filtered_scaff))\n\t\t\t{\n\t\t\t\tscaff_present[i] = cfs;\n\t\t\t\tcfs++;\n\t\t\t}\n\t\t}\n\t}\n    \n\tfor (size_t i = 0; i < N; ++i)\n\t{\n\t\tif (scaff_present[i] != N)\n\t\t{\n\t\t\t// then scaffolds[i] has a non-zero abundance, we need to fill\n\t\t\t// that in along with relevant cells from the covariance matrix\n\t\t\tupdated_gammas[i] = filtered_gammas[scaff_present[i]];\n            //cerr << updated_gammas[i] << \",\";\n            \n\t\t\tfor (size_t j = 0; j < N; ++j)\n\t\t\t{\n\t\t\t\tif (scaff_present[j] != N)\n\t\t\t\t{\n\t\t\t\t\tupdated_gamma_cov(i,j) = _gamma_covariance(scaff_present[i],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   scaff_present[j]);\n                    \n                    updated_iterated_exp_count_cov(i,j) = _iterated_exp_count_covariance(scaff_present[i],\n                                                                                         scaff_present[j]);\n                    // Should still be empty but let's do these for consistency:\n                    updated_count_cov(i,j) = _count_covariance(scaff_present[i],\n                                                               scaff_present[j]);\n                    updated_fpkm_cov(i,j) = _fpkm_covariance(scaff_present[i],\n                                                             scaff_present[j]);\n\t\t\t\t\tassert (!isinf(updated_gamma_cov(i,j)));\n\t\t\t\t\tassert (!isnan(updated_gamma_cov(i,j)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n    \n    //cerr << endl;\n\t\n    AbundanceStatus numeric_status = NUMERIC_OK;\n    if (mle_success == NUMERIC_LOW_DATA)\n    {\n        numeric_status = NUMERIC_LOW_DATA;\n    }\n    else if (mle_success == NUMERIC_FAIL)\n    {\n        numeric_status = NUMERIC_FAIL;\n    }\n    else\n    {\n        assert (mle_success == NUMERIC_OK);\n        if (map_success == NUMERIC_FAIL)\n        {\n            numeric_status = NUMERIC_FAIL;\n        }\n        else if (map_success == NUMERIC_LOW_DATA)\n        {\n            numeric_status = NUMERIC_LOW_DATA;\n        }\n        // otherwise, we're cool.\n    }\n    \n    \n    \n\t// All scaffolds that go in get abundances, but those that get \"filtered\"\n\t// from the calculation get zeros.\n\t//gammas = updated_gammas;\n\tfor (size_t i = 0; i < _abundances.size(); ++i)\n\t{\n\t\t_abundances[i]->gamma(updated_gammas[i]);\n\t\t_abundances[i]->status(numeric_status);\n\t}\n\t_gamma_covariance = updated_gamma_cov;\n    _count_covariance = updated_count_cov;\n    _iterated_exp_count_covariance = updated_iterated_exp_count_cov;\n    _fpkm_covariance = updated_fpkm_cov;\n\t\n\treturn (status() == NUMERIC_OK);\n}\n\nvoid calculate_assignment_probs(const Eigen::VectorXd& alignment_multiplicities, \n                                const Eigen::MatrixXd& transcript_cond_probs,\n                                const Eigen::VectorXd& proposed_gammas,\n                                Eigen::MatrixXd& assignment_probs)\n{\n//    vector<double> u(nr_alignments.size());\n//    for (size_t i = 0; i < alignment_multiplicity.size(); ++i)\n//    {\n//        u[i] = nr_alignments[i].collapse_mass();\n//    }\n    \n    //ublas::vector<double> total_cond_prob = ublas::prod(proposed_gammas,transcript_cond_probs);\n    Eigen::VectorXd total_cond_prob = proposed_gammas.transpose() * transcript_cond_probs ;\n    \n    // Compute the marginal conditional probability for each fragment against each isoform\n    //ublas::matrix<double>  marg_cond_prob = ublas::zero_matrix<double>(transcript_cond_probs.size1(), transcript_cond_probs.size2());\n    Eigen::MatrixXd marg_cond_prob(transcript_cond_probs.rows(), transcript_cond_probs.cols());\n    \n    for (size_t i = 0; i < alignment_multiplicities.size(); ++i)\n    {\n        marg_cond_prob.array().col(i) = proposed_gammas.array() * transcript_cond_probs.array().col(i);\n        \n        if (total_cond_prob(i) > 0)\n        {\n            marg_cond_prob.array().col(i) /= total_cond_prob(i);\n            //column(marg_cond_prob,i) /= total_cond_prob(i);\n        }\n    }\n    \n    assignment_probs = marg_cond_prob;\n}\n\nvoid calculate_average_assignment_probs(const Eigen::VectorXd& alignment_multiplicities, \n                                        const Eigen::MatrixXd& transcript_cond_probs,\n                                        const Eigen::VectorXd& proposed_gammas,\n                                        Eigen::MatrixXd& assignment_probs)\n{\n    //ublas::vector<double> total_cond_prob = ublas::prod(proposed_gammas,transcript_cond_probs);\n    Eigen::VectorXd total_cond_prob = proposed_gammas.transpose() * transcript_cond_probs ;\n    \n    // Compute the marginal conditional probability for each fragment against each isoform\n    //ublas::matrix<double>  marg_cond_prob = ublas::zero_matrix<double>(transcript_cond_probs.size1(), transcript_cond_probs.size2());\n    Eigen::MatrixXd marg_cond_prob(transcript_cond_probs.rows(), transcript_cond_probs.cols());\n    \n    for (size_t i = 0; i < alignment_multiplicities.size(); ++i)\n    {\n        marg_cond_prob.array().col(i) = proposed_gammas.array() * transcript_cond_probs.array().col(i);\n        \n        if (total_cond_prob(i) > 0)\n        {\n            marg_cond_prob.array().col(i) /= total_cond_prob(i);\n            //column(marg_cond_prob,i) /= total_cond_prob(i);\n        }\n    }\n    \n    assignment_probs = Eigen::MatrixXd::Zero(proposed_gammas.size(), proposed_gammas.size());\n    \n    vector<double> num_compatible(proposed_gammas.size(), 0);\n    \n    for (size_t i = 0; i < alignment_multiplicities.size(); ++i)\n    {\n        for (size_t j = 0; j < proposed_gammas.size(); ++j)\n        {\n            if (marg_cond_prob(j,i) > 0)\n            {\n                assignment_probs.col(j) += marg_cond_prob.col(i) * alignment_multiplicities[i];\n                num_compatible[j] += alignment_multiplicities[i];\n            }\n        }\n    }\n    \n//    cerr << \"marg cond prob:\" << endl;\n//    cerr << marg_cond_prob << endl;\n    \n    for (size_t j = 0; j < proposed_gammas.size(); ++j)\n    {\n        if (num_compatible[j] > 0)\n            assignment_probs.col(j) /= num_compatible[j];\n    }\n    \n//    cerr << \"multiplicities:\" << endl;\n//    cerr << alignment_multiplicities << endl;\n//    cerr << \"avg matrix:\" << endl;\n//    cerr << assignment_probs << endl;\n    //assignment_probs = marg_cond_prob;\n}\n\n\n\nvoid calculate_iterated_exp_count_covariance(const vector<double>& gammas,\n                                             const vector<MateHit>& nr_alignments,\n                                             const vector<boost::shared_ptr<Abundance> >& transcripts,\n                                             ublas::matrix<double>& count_covariance)\n{\n    // Now calculate the _iterated_exp_count_covariance matrix via iterated expectation\n    vector<vector<double> > cond_probs(transcripts.size(), vector<double>());\n    for(size_t j = 0; j < transcripts.size(); ++j)\n    {\n        cond_probs[j]= *(transcripts[j]->cond_probs());\n    }\n    \n    vector<double> u(nr_alignments.size());\n    for (size_t i = 0; i < nr_alignments.size(); ++i)\n    {\n        u[i] = nr_alignments[i].collapse_mass();\n    }\n    \n    count_covariance = ublas::zero_matrix<double>(transcripts.size(), transcripts.size());\n    \n    ublas::vector<double> total_cond_prob = ublas::zero_vector<double>(nr_alignments.size());\n    \n    for (size_t i = 0; i < nr_alignments.size(); ++i)\n    {\n        // the replicate gamma mles might not be available, if one of the\n        // replicates returned an error, we'll consider all to be unreliable\n        for (size_t j = 0; j < cond_probs.size(); ++j)\n        {\n            if (cond_probs[j][i] > 0)\n            {\n                total_cond_prob(i) += gammas[j] * cond_probs[j][i];\n                assert (!isnan(total_cond_prob(i) && ! isinf(total_cond_prob(i))));\n            }\n        }\n    }\n    \n    // Compute the marginal conditional probability for each fragment against each isoform\n    ublas::matrix<double>  marg_cond_prob = ublas::zero_matrix<double>(transcripts.size(), nr_alignments.size());\n    \n    for (size_t i = 0; i < nr_alignments.size(); ++i)\n    {\n        // the replicate gamma mles might not be available, if one of the\n        // replicates returned an error, we'll consider all to be unreliable\n        for (size_t j = 0; j < cond_probs.size(); ++j)\n        {\n            if (total_cond_prob(i))\n            {\n                if (cond_probs[j][i] > 0)\n                {\n                    marg_cond_prob(j,i) = (gammas[j] * cond_probs[j][i])/total_cond_prob(i);\n                }\n            }\n        }\n    }\n    \n    double total_var = 0.0;\n    \n    ublas::vector<double> expected_counts = ublas::zero_vector<double>(cond_probs.size());\n\n    //iterate over fragments\n    for (size_t i = 0; i < marg_cond_prob.size2(); ++i)\n    {\n        \n        // iterate over transcripts\n        for (size_t j = 0; j < marg_cond_prob.size1(); ++j)\n        {\n            double c_j_i = marg_cond_prob(j,i);\n            \n            expected_counts(j) += u[i] * marg_cond_prob(j,i);\n            \n            //if (c_j_i == 0 || c_j_i == 1.0)\n            //    continue;\n            \n            for (size_t k = 0; k < marg_cond_prob.size1(); ++k)\n            {\n                double c_k_i = marg_cond_prob(k,i);\n                //if (c_k_i == 0 || c_k_i == 1.0)\n                //    continue;\n                \n                if (j == k)\n                {\n                    if (c_k_i != 0 && c_k_i != 1.0)\n                    {\n                        double var = u[i] * c_k_i * (1.0 - c_k_i);\n                        count_covariance(k,k) += var;\n                        assert (var >= 0);\n                        assert (!isnan(var) && !isinf(var));\n                        total_var += var;\n                    }\n                }\n                else\n                {\n                    if (c_k_i != 0 && c_k_i != 1.0 &&\n                        c_j_i != 0 && c_j_i != 1.0)\n                    {\n                        double covar = -u[i] * c_k_i * c_j_i;\n                        assert (covar <= 0);\n                        assert (!isnan(covar) && !isinf(covar));\n                        count_covariance(k,j) += covar;\n                    }\n                } \n            }\n        }\n\n    }\n    //cerr << \"expected counts\" << endl;\n    //cerr << expected_counts << endl;\n    \n//    // take care of little rounding errors\n//    for (size_t i = 0; i < _iterated_exp_count_covariance.size1(); ++i)\n//    {\n//        for (size_t j = 0; j < _iterated_exp_count_covariance.size2(); ++j)\n//        {\n//            if (i == j)\n//            {\n//                double c = _iterated_exp_count_covariance(i,j);\n//                if (c < 0)\n//                    _iterated_exp_count_covariance(i,j) = 0;\n//                //assert(c >= 0);\n//            }\n//            else\n//            {\n//                double c = _iterated_exp_count_covariance(i,j);\n//                if (c > 0)\n//                    _iterated_exp_count_covariance(i,j) = 0;\n//                //assert(c <= 0);\n//            }\n//        }\n//        _abundances[i]->num_fragment_uncertainty_var(_iterated_exp_count_covariance(i,i));\n//    }\n}\n\nvoid AbundanceGroup::calculate_kappas()\n{\n    size_t num_members = _abundances.size();\n    _kappa_covariance = ublas::matrix<double>(num_members, \n\t\t\t\t\t\t\t\t\t\t\t  num_members);\n\t//cerr << gamma_cov <<endl;\n\t\n\tassert (_gamma_covariance.size1() == num_members);\n\tassert (_gamma_covariance.size2() == num_members);\n\t\n\t//tss_group.sub_quants = vector<QuantGroup>(isos_in_tss);\n\t\n\tdouble S_FPKM = 0.0;\n\tBOOST_FOREACH (boost::shared_ptr<Abundance> pA, _abundances)\n\t{\n\t\tif (pA->effective_length() > 0)\n\t\t{\n\t\t\tS_FPKM += pA->FPKM();\n\t\t}\n\t}\n\t\n    //fprintf (stderr, \"*********\\n\");\n\tBOOST_FOREACH (boost::shared_ptr<Abundance> pA, _abundances)\n\t{\n\t\tif (S_FPKM > 0)\n\t\t{\n\t\t\tpA->kappa(pA->FPKM() / S_FPKM);\n        }\n\t\telse\n\t\t{\n\t\t\tpA->kappa(0); \n\t\t}\n\t}\n    \n\tfor (size_t k = 0; k < num_members; ++k)\n\t{\n\t\tfor (size_t m = 0; m < num_members; ++m)\n\t\t{\n            double L = _abundances[k]->effective_length() * \n            _abundances[m]->effective_length();\n            if (L == 0.0)\n            {\n                _kappa_covariance(k,m) = 0.0;\n            }\n            else if (m == k)\n            {\n                // Use the modeled count variance here instead\n                double kappa_var;\n                if (S_FPKM)\n                {\n                    kappa_var = _fpkm_covariance(k,k) / (S_FPKM * S_FPKM);\n                }\n                else\n                {\n                    kappa_var = 0.0;\n                }\n                \n                if (isnan(kappa_var) || isinf(kappa_var)) // to protect against underflow\n                    kappa_var = 0;\n                _kappa_covariance(k,m) = kappa_var;\n            }\n            else\n            {\n                double kappa_covar;\n                if (S_FPKM)\n                {\n                    kappa_covar = _fpkm_covariance(k,m) / (S_FPKM * S_FPKM);\n                }\n                else\n                {\n                    kappa_covar = 0.0;\n                }\n                _kappa_covariance(k,m) = kappa_covar;\n            }\n\t\t}\n\t}\n\n    \n//\tsize_t num_members = _abundances.size();\n//\t_kappa_covariance = ublas::zero_matrix<double>(num_members, \n//\t\t\t\t\t\t\t\t\t\t\t  num_members);\n//    if (FPKM() == 0)\n//    {\n//        for (size_t k = 0; k < num_members; ++k)\n//        {\n//            _abundances[k]->kappa(0);\n//        }\n//        return;\n//    }\n//\n    \n    // FIXME:\n    size_t num_count_draws = _assigned_count_samples.size();\n    vector<Eigen::VectorXd > relative_abundances (num_count_draws, Eigen::VectorXd::Zero(num_members));\n    \n    // We'll use the effective lengths to transform counts into relative abundances,\n    // and then use that to calculate the kappa variances and covariances.\n    Eigen::VectorXd effective_length_recip = Eigen::VectorXd::Zero(_abundances.size());\n    for (size_t i = 0; i < _abundances.size(); ++i)\n    {\n        if (_abundances[i]->effective_length() > 0)\n            effective_length_recip(i) = 1.0 / _abundances[i]->effective_length();\n    }\n    \n    for (size_t i = 0; i < num_count_draws; ++i)\n    {\n        \n        Eigen::VectorXd relative_abundance = effective_length_recip.array() * _assigned_count_samples[i].array();\n        double total = relative_abundance.sum();\n        if (total > 0)\n            relative_abundance /= total;\n        //cerr << relative_abundance.transpose() << endl;\n        relative_abundances[i] = relative_abundance;\n    }\n}\n\nvoid get_alignments_from_scaffolds(const vector<boost::shared_ptr<Abundance> >& abundances,\n\t\t\t\t\t\t\t\t   vector<MateHit>& alignments)\n{\n\tset<const MateHit*> hits_in_gene_set;\n\n\tBOOST_FOREACH(boost::shared_ptr<Abundance> pA, abundances)\n\t{\t\t\t\n\t\tboost::shared_ptr<Scaffold> pS = pA->transfrag();\n\t\tassert (pS);\n\t\thits_in_gene_set.insert(pS->mate_hits().begin(),\n\t\t\t\t\t\t\t\tpS->mate_hits().end());\n\t}\n\t\n\tfor(set<const MateHit*>::iterator itr = hits_in_gene_set.begin();\n\t\titr != hits_in_gene_set.end();\n\t\t++itr)\n\t{\n\t\talignments.push_back(**itr);\n\t}\n\t\n\tsort(alignments.begin(), alignments.end(), mate_hit_lt);\n}\n\n//void round(Eigen::VectorXd&  p) {\n//\t\n//\tdouble KILLP = 0; // kill all probabilities below this\n//\t\n//\tfor (size_t i = 0; i < p.size(); ++i) {\n//\t\tif (p(i) < KILLP) \n//\t\t\tp(i) = 0;\n//\t}\n//}\n\nvoid Estep (int N, \n\t\t\tint M, \n\t\t\tconst Eigen::VectorXd& p,\n\t\t\tEigen::MatrixXd& U,\n\t\t\tconst Eigen::MatrixXd& cond_probs,\n\t\t\tconst Eigen::VectorXd& alignment_multiplicities) {\n\t// given p, fills U with expected frequencies\n\tint i,j;\t\n    \n//    Eigen::VectorXd frag_prob_sums = Eigen::VectorXd::Zero(M);\n//    \n//    for (j = 0; j < N; ++j) \n//    {\n//        for (i = 0; i < M; ++i) \n//        {\n//            frag_prob_sums(i) += cond_probs(j,i) * p(j);\n//        }\n//    }\n//    \n//    for (i = 0; i < M; ++i) \n//    {\n//        frag_prob_sums(i) = frag_prob_sums(i) ? (1.0 / frag_prob_sums(i)) : 0.0;\n//    }\n//    \n//    for (j = 0; j < N; ++j) \n//    {\n//        for (i = 0; i < M; ++i) \n//        {\n//            double ProbY = frag_prob_sums(i);\n//            double exp_i_j = alignment_multiplicities(i) * cond_probs(j,i) * p(j) * ProbY;\n//            U(j,i) = exp_i_j;\n//        }\n//    }\n    \n    Eigen::VectorXd frag_prob_sums;// = Eigen::VectorXd::Zero(M);\n    \n//    for (j = 0; j < N; ++j) \n//    {\n//        for (i = 0; i < M; ++i) \n//        {\n//            frag_prob_sums(i) += cond_probs(j,i) * p(j);\n//            assert (!isnan(cond_probs(j,i)) && !isinf(cond_probs(j,i)));\n//        }\n//    }\n    \n    frag_prob_sums = p.transpose() * cond_probs;\n    \n    for (i = 0; i < M; ++i) \n    {\n        assert (!isnan(frag_prob_sums(i)) && !isinf(frag_prob_sums(i)));\n        //double x = frag_prob_sums(i);\n        frag_prob_sums(i) = frag_prob_sums(i) ? (1.0 / frag_prob_sums(i)) : 0.0;\n        if (isnan(frag_prob_sums(i)) || isinf(frag_prob_sums(i)))\n        {\n            frag_prob_sums(i) = 0; // protect against overflow/underflow\n        }\n    }\n    \n    Eigen::VectorXd x = frag_prob_sums.array() * alignment_multiplicities.array();\n//    Eigen::MatrixXd y = p.transpose() * cond_probs;\n//    Eigen::MatrixXd UU = y.array() * x.array();\n    \n//    cerr << UU <<endl;\n//    for (j = 0; j < N; ++j) \n//    {\n//        for (i = 0; i < M; ++i) \n//        {\n//            //double ProbY = frag_prob_sums(i);\n//            double exp_i_j = cond_probs(j,i) * p(j) * x(i);\n//            U(j,i) = exp_i_j;\n//        }\n//    }\n    \n    U = Eigen::MatrixXd(N,M);\n\n    for (i = 0; i < M; ++i) \n    {\n        //double ProbY = frag_prob_sums(i);\n        //double exp_i_j = cond_probs(j,i) * p(j) * x(i);\n        //U.r = exp_i_j;\n        U.col(i) = cond_probs.col(i).array() * p.array();\n    }\n    for (j = 0; j < N; ++j) \n    {\n        U.array().row(j) *= x.transpose().array();\n    }\n    \n    //cerr << UU << endl;\n    //cerr << \"==========\" << endl;\n    //cerr << U << endl;\n    //cerr << \"**********\" << endl;\n    //Eigen::ArrayXXd a_cond_probs = cond_probs.array();\n    //Eigen::ArrayXXd a_p = p.array();\n    //Eigen::ArrayXXd a_U = a_p * a_cond_probs.colwise();\n    //U = (.colwise() * p.transpose().array()).matrix();\n    //U = cond_probs.colwise() * p.array();\n    //U = alignment_multiplicities.array() * p.array() * cond_probs.array() * frag_prob_sums.array();\n    //U = (frag_prob_sums.array() * alignment_multiplicities.array()).rowwise() * p.array().colwise() * cond_probs.array().colwise();\n}\n\n\nvoid Mstep (int N, \n            int M, \n            Eigen::VectorXd& p, \n            const Eigen::MatrixXd& U) \n{\n\tEigen::VectorXd v;// = Eigen::VectorXd::Zero(N);\n    \n\tdouble m = 0;\n    \n\tv = U.rowwise().sum();\n    m = v.colwise().sum()(0);\n    \n\tif (m)\n\t{\n\t\tp = v / m;\n\t}\n\telse\n\t{\n        p = Eigen::VectorXd::Zero(N);\n\t}\n}\n \n\ndouble logLike (int N, \n\t\t\t\tint M, \n\t\t\t\tEigen::VectorXd& p,\n\t\t\t\tconst Eigen::MatrixXd& cond_prob, \n\t\t\t\tconst Eigen::VectorXd& alignment_multiplicities,\n                const vector<double>& log_conv_factors) {\n\t//int i,j;\n\t\n\tdouble ell = accumulate(log_conv_factors.begin(), log_conv_factors.end(), 0.0);\n\t//double Prob_Y;\n//\tfor (int i= 0; i < M; i++) {\n//\t\tProb_Y = 0;\n//\t\tfor (int j= 0; j < N; j++) {\n//\t\t\tProb_Y += cond_prob(j,i) * p(j);\n//\t\t}\n//\t\tif (Prob_Y > 0) {\n//\t\t\tell += (alignment_multiplicities(i) * log(Prob_Y));\n//\t\t}\n//\t}\n    Eigen::VectorXd Prob_Ys = p.transpose() * cond_prob;\n    Eigen::VectorXd log_Prob_Ys = Prob_Ys.array().log();\n    //log_Prob_Ys *= alignment_multiplicities;\n    for (int i = 0; i < M; i++) {\n        if (Prob_Ys(i) > 0)\n        {\n            ell += alignment_multiplicities(i) * log_Prob_Ys(i);\n        }\n    }\n\treturn ell;\n}\n\ndouble EM(int N, int M, \n          Eigen::VectorXd&  newP, \n          const Eigen::MatrixXd& cond_prob, \n\t\t  const Eigen::VectorXd& alignment_multiplicities,\n          vector<double> const & log_conv_factors,\n          bool& converged) \n{\n    converged = true;\n\t//double sum = 0;\n\tdouble newEll = 0;\n    Eigen::VectorXd p = Eigen::VectorXd::Zero(N);\n    Eigen::MatrixXd  U = Eigen::MatrixXd::Zero(N,M);\n\tdouble ell = 0; \n\tint iter = 0;\n\tint j;\n    \n    if (N == 0 || M == 0)\n        return NUMERIC_OK;\n    \n    for (j = 0; j < N; ++j) {\n        //p[j] = drand48();\n        //sum += p[j];\n        p(j) = 1.0/(double)N;\n    }\n  \n    \n\n    static const double ACCURACY = mle_accuracy; // convergence for EM\n    \n\twhile (((iter <= 2) || (abs(ell - newEll) > ACCURACY)) && (iter < max_mle_iterations)) {\n\t\tif (iter > 0) {\n\t\t\t//round(newP);\n\t\t\tp = newP;\n\t\t\tell = newEll;\n\t\t}\n\t\t\n\t\tEstep(N, M, p, U, cond_prob, alignment_multiplicities); //  fills U\n\t\tMstep(N, M, newP,U); // fills p\n\t\t\n\t\tnewEll = logLike(N, M, newP, cond_prob,alignment_multiplicities, log_conv_factors);\n\t\t\n\t\t//fprintf(stderr, \"%d\\t%lf\\n\", iter, newEll);\n\t\t\n\t\t//printf(\"%.3f %.3f %.3f \", newP[0], newP[1], newP[2]);\n\t\t//printf(\"%.3f %.3f %.3f \", newP[3], newP[4], newP[5]);\n\t\t//printf(\"%.3f %.3f %.3f\\n\", newP[6], newP[7], newP[8]);\n\t\titer++;\n\t}\n\tif (iter >= max_mle_iterations)\n    {\n\t\tverbose_msg(\"Warning: ITERMAX reached in abundance estimation, estimation hasn't fully converged\\n\");\n        converged = false;\n    }\n    verbose_msg(\"Convergence reached in %d iterations \\n\", iter);\n\treturn newEll;\n}\n\nvoid compute_fisher(const vector<boost::shared_ptr<Abundance> >& transcripts,\n\t\t\t\t\tconst ublas::vector<double>& abundances,\n\t\t\t\t\tconst vector<MateHit>& alignments,\n\t\t\t\t\tconst vector<double>& u,\n\t\t\t\t\tboost::numeric::ublas::matrix<double>& fisher)\n{\n\tint M = alignments.size();\n\tint N = transcripts.size();  \n\t\n\tvector<long double> denoms(M, 0.0);\n\tvector<vector<long double> > P(M,vector<long double>(N,0));\n\n\tfor (int j = 0; j < N; ++j)\n\t{\n\t\tconst vector<double>& cond_probs_j = *(transcripts[j]->cond_probs());\n\t\tfor (int x = 0; x < M; ++x)\n\t\t{\n\t\t\tif (cond_probs_j[x]==0)\n\t\t\t\tcontinue;\n\t\t\tlong double alpha = 0.0;\n\t\t\talpha = cond_probs_j[x];\n\t\t\talpha *= abundances(j);\n\t\t\tdenoms[x] += alpha;\n\t\t}\n\t}\n\t\n\tfor (int x = 0; x < M; ++x)\n\t\tdenoms[x] *= denoms[x];\n\t\n\t\n\tfor (int j = 0; j < N; ++j)\n\t{\n\t\tconst vector<double>& cond_probs_j = *(transcripts[j]->cond_probs());\n\t\tfor (int k = 0; k < N; ++k)\n\t\t{\n\t\t\t\n\t\t\tconst vector<double>& cond_probs_k = *(transcripts[k]->cond_probs());\n\n\t\t\tfor (int x = 0; x < M; ++x)\n\t\t\t{\n\t\t\t\tif (cond_probs_j[x]==0 && cond_probs_k[x]==0)\n\t\t\t\t\tcontinue;\n\t\t\t\t\n\t\t\t\tassert(denoms[x] != 0.0);\n\t\t\t\t\n\t\t\t\tdouble fisher_x_j_k = cond_probs_j[x] * cond_probs_k[x] / denoms[x];\n\t\t\t\t\n\t\t\t\tfisher(j,k) += u[x] * fisher_x_j_k;\n\t\t\t}\n\t\t}\n\t}\n}\n\nAbundanceStatus compute_posterior_expectation(const vector<ublas::vector<double> >& weighted_samples,\n                                              const vector<pair<size_t, double> >& sample_weights,\n                                              ublas::vector<double>& expectation,\n                                              long double& log_total_weight)\n{\n    ublas::vector<double> log_expectation(expectation.size());\n    log_total_weight = 0.0;\n    \n    // compute the weighted sum of the samples from the proposal distribution,\n    // but keep the result in log space to avoid underflow.\n\tfor (size_t i = 0; i < weighted_samples.size(); ++i)\n\t{\n\t\tconst ublas::vector<double>& scaled_sample = weighted_samples[i];\n\t\tdouble log_weight = sample_weights[i].second;\n\t\tif (log_total_weight == 0.0)\n\t\t{\n\t\t\tlog_expectation = weighted_samples[i];\n\t\t\tlog_total_weight = log_weight;\n\t\t}\n\t\telse\n\t\t{\t\t\t\n\t\t\tfor (size_t e = 0; e < log_expectation.size(); ++e)\n\t\t\t{\n\t\t\t\tlog_expectation(e) = log_space_add<long double>(log_expectation[e], scaled_sample[e]);\n\t\t\t}\n\t\t\tlog_total_weight = log_space_add<long double>(log_total_weight, log_weight);\n\t\t}\t\n\t}\n    \n    if (log_total_weight == 0 || sample_weights.size() < 100)\n\t{\n\t\tverbose_msg(\"Warning: restimation failed, importance samples have zero weight.\\n\\tResorting to MLE and observed Fisher\\n\");\n\t\treturn NUMERIC_FAIL;\n\t}\n\t\n    // compute the weighted mean, and transform back out of log space\n    for (size_t e = 0; e < expectation.size(); ++e)\n\t{\n\t\texpectation(e) = (long double)log_expectation(e) - log_total_weight;\n\t\texpectation(e) = exp(expectation(e));\n\t}\n\t\n\tfor (size_t e = 0; e < expectation.size(); ++e)\n\t{\n\t\tif (isinf(expectation(e)) || isnan(expectation(e)))\n\t\t{\n\t\t\tverbose_msg(\"Warning: isoform abundance is NaN, restimation failed.\\n\\tResorting to MLE and observed Fisher.\");\n\t\t\treturn NUMERIC_FAIL;\n\t\t}\n\t}\n\t\n\tfor (size_t j = 0; j < expectation.size(); ++j) \n\t{\n\t\tif (expectation(j) < 0)\n\t\t\texpectation(j) = 0;\n\t}\n\t\n\tlong double m = sum(expectation);\n\t\n\tif (m == 0 || isinf(m) || isnan(m))\n\t{\n\t\tverbose_msg(\"Warning: restimation failed, could not renormalize MAP estimate\\n\\tResorting to MLE and observed Fisher.\");\n\t\treturn NUMERIC_FAIL;\n\t}\n\t\n\tfor (size_t j = 0; j < expectation.size(); ++j) {\n\t\texpectation(j) = expectation(j) / m;\n\t}\n    return NUMERIC_OK;\n}\n\nAbundanceStatus AbundanceGroup::calculate_per_replicate_abundances(vector<boost::shared_ptr<Abundance> >& transcripts,\n                                                                   const map<boost::shared_ptr<ReadGroupProperties const >, vector<MateHit> >& alignments_per_read_group,\n                                                                   std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<AbundanceGroup> >& ab_group_per_replicate,\n                                                                   bool perform_collapse)\n{\n    for(std::set<boost::shared_ptr<ReadGroupProperties const > >::iterator itr = _read_group_props.begin();\n        itr != _read_group_props.end(); \n        ++itr)\n    {\n        vector<boost::shared_ptr<Abundance> > new_transcripts;\n        BOOST_FOREACH(boost::shared_ptr<Abundance> ab, transcripts)\n        {\n            boost::shared_ptr<TranscriptAbundance> d = boost::static_pointer_cast<TranscriptAbundance>(ab);\n            //new_transcripts.push_back(boost::shared_ptr<Abundance>(new TranscriptAbundance(*boost::static_pointer_cast<TranscriptAbundance>(ab))));\n            TranscriptAbundance* pT = new TranscriptAbundance;\n            pT->transfrag(d->transfrag());\n            boost::shared_ptr<Abundance> ab_new(pT);\n            ab_new->description(ab_new->description());\n            ab_new->locus_tag(\"\");\n            new_transcripts.push_back(ab_new);\n        }\n        boost::shared_ptr<AbundanceGroup> ab_group(new AbundanceGroup(new_transcripts));\n        std::set<boost::shared_ptr<ReadGroupProperties const > > rg_props;\n        rg_props.insert(*itr);\n        ab_group->init_rg_props(rg_props);\n        \n        map<boost::shared_ptr<ReadGroupProperties const >, vector<MateHit> >::const_iterator al_itr =\n            alignments_per_read_group.find(*itr);\n        \n        assert(al_itr != alignments_per_read_group.end());\n        const vector<MateHit>& rep_hits = alignments_per_read_group.find(*itr)->second;\n       \n        vector<MateHit> nr_alignments;\n        vector<MateHit> non_equiv_alignments;\n        vector<double> log_conv_factors;\n        vector<boost::shared_ptr<Abundance> > mapped_transcripts;\n        \n        if (perform_collapse)\n        {\n            collapse_hits(rep_hits, nr_alignments);\n            collapse_equivalent_hits_helper(nr_alignments, transcripts, non_equiv_alignments, log_conv_factors);\n            assert (non_equiv_alignments.size() == log_conv_factors.size());\n            log_conv_factors = vector<double>(nr_alignments.size(), 0);\n            nr_alignments.clear();\n        }\n        else\n        {\n            nr_alignments = rep_hits;\n            non_equiv_alignments = nr_alignments;\n            log_conv_factors = vector<double>(nr_alignments.size(), 0);\n        }\n        \n        ab_group->calculate_abundance_for_replicate(non_equiv_alignments, false);\n        \n        //fprintf (stderr, \"FPKM = %lg\\n\", ab_group->FPKM());\n        ab_group_per_replicate[*itr] = ab_group;\n    }\n\n    return NUMERIC_OK;\n}\n\nAbundanceStatus calculate_inverse_fisher(const vector<boost::shared_ptr<Abundance> >& transcripts,\n                                         const vector<MateHit>& alignments,\n                                         const ublas::vector<double>& gamma_mean,\n                                         ublas::matrix<double>& inverse_fisher)\n{\n//    size_t N = gamma_covariance.size1();\t\n\t\n//\tgamma_map_covariance = ublas::zero_matrix<double>(N);\n    \n\ttypedef ublas::matrix<double> matrix_type;\n\tmatrix_type fisher = ublas::zero_matrix<double>(gamma_mean.size(),gamma_mean.size());\n\t\n\tvector<double> u(alignments.size());\n\tfor (size_t i = 0; i < alignments.size(); ++i)\n\t{\n\t\tu[i] = alignments[i].collapse_mass();\n\t}\n    \n\tcompute_fisher(transcripts,\n\t\t\t\t   gamma_mean,\n\t\t\t\t   alignments,\n\t\t\t\t   u,\n\t\t\t\t   fisher);\n\t\n\tublas::matrix<double> epsilon = ublas::zero_matrix<double>(gamma_mean.size(),gamma_mean.size());\n\tfor (size_t i = 0; i < gamma_mean.size(); ++i)\n\t{\n\t\tepsilon(i,i) = 1e-6;\n\t}\n\t\n\tfisher += epsilon; // modify matrix to avoid problems during inverse\n    \n\tublas::matrix<double> fisher_chol = fisher;\n\t\n\tdouble ch = cholesky_factorize(fisher_chol);\n\tif (ch != 0.0)\n\t{\n\t\tverbose_msg(\"Warning: Fisher matrix is not positive definite (bad element: %lg)\\n\", ch);\n\t\treturn NUMERIC_FAIL;\n\t}\n\t\n\tinverse_fisher = ublas::zero_matrix<double>(gamma_mean.size(),gamma_mean.size());\n\tbool invertible = chol_invert_matrix(fisher_chol, inverse_fisher);\n    \n    ublas::matrix<double> test_fisher = inverse_fisher;\n\tch = cholesky_factorize(test_fisher);\n\tif (ch != 0.0 || !invertible)\n\t{\n\t\tverbose_msg(\"Warning: Fisher matrix is not inverible\\n\", ch);\n\t\treturn NUMERIC_FAIL;\n\t}\n    \n    return NUMERIC_OK;\n}\n\nAbundanceStatus revise_map_mean_and_cov_estimate(double log_total_weight,\n                                                 const ublas::vector<double>& expectation,\n                                                 const vector<pair<size_t, double> >& sample_weights,\n                                                 const vector<ublas::vector<double> >& weighted_samples,\n                                                 ublas::vector<double>& gamma_map_estimate,\n                                                 ublas::matrix<double>& gamma_map_covariance)\n{\n    int N = expectation.size();\n    \n\t// revise gamma by setting it to the posterior expectation computed via the\n\t// importance sampling\n\tgamma_map_estimate = expectation;\n    \n\t// calculate the sample - mean vectors, store them in log space\n\tvector<ublas::vector<double> > sample_expectation_diffs;\n\t\n    ublas::vector<double> check_expectation = ublas::zero_vector<double>(expectation.size());\n    \n\tfor (size_t j = 0; j < weighted_samples.size(); ++j)\n\t{\n\t\tublas::vector<double> sample = weighted_samples[j];\n\t\tdouble log_sample_weight = sample_weights[j].second;\n        \n\t\tfor (size_t e = 0; e < expectation.size(); ++e)\n\t\t{\n\t\t\t// sample is already log transformed after it was weighted, so we\n\t\t\t// need to divide by the sample weight to recover the original sample\n\t\t\t// value, then undo the log transform, then subtract the mean from it\n\t\t\tsample(e) = (exp(((long double)sample(e) - log_sample_weight)) - expectation(e));\n\t\t\t//sample(e) *= exp((log_sample_weight - log_total_weight));\n\t\t}\n\t\t//cerr << sample << endl;\n\t\tsample_expectation_diffs.push_back(sample);\n\t}\n     \n    // We want to revise the covariance matrix from the samples, since we'll \n    // need it later for the CIs.\n    ublas::matrix<double> revised_cov = ublas::zero_matrix<double>(N,N);\n    \n    // accumulate the contributions from the other samples (doing one cell of \n\t// covariance matrix per outer (i x j) loop iteration.\n    \n    for (size_t j = 0; j < sample_expectation_diffs.size(); ++j)\n    {\n        double log_sample_weight = sample_weights[j].second;\n        double w = exp((log_sample_weight - log_total_weight));\n        ublas::vector<double> sample = weighted_samples[j];\n        \n        for (size_t e = 0; e < expectation.size(); ++e)\n\t\t{\n\t\t\t// sample is already log transformed after it was weighted, so we\n\t\t\t// need to divide by the sample weight to recover the original sample\n\t\t\t// value, then undo the log transform, then subtract the mean from it\n\t\t\tsample(e) = exp(sample(e) - log_sample_weight);\n\t\t\t//sample(e) *= exp((log_sample_weight - log_total_weight));\n\t\t}\n        \n        revised_cov += w * (outer_prod(sample,sample));\n\t}\n    \n    revised_cov -= outer_prod(expectation,expectation);\n    \n\t//cerr << \"Revised COV\" << endl;\n\t//cerr << revised_cov << endl;\n\tgamma_map_covariance = revised_cov;\n\t\n    //cerr << \"Revised MAP estimate: \" << expectation << endl;\n    //cerr << \"Revised Covariance matrix:\" << endl;\n    //cerr << gamma_map_covariance << endl;\n    //cerr << \"*************\" << endl;\n    \n    return NUMERIC_OK;\n}\n\nAbundanceStatus calc_is_scale_factor(const ublas::matrix<double>& covariance_chol,\n                                     double& is_scale_factor)\n{\n    double det = determinant(covariance_chol);\n    is_scale_factor = pow(2.0*boost::math::constants::pi<double>(), covariance_chol.size1()/2.0);\n\tdouble s = sqrt(det);\n\tis_scale_factor *= s;\n\t\n\t//assert (det);\n\tif (s == 0.0)\n\t{\n\t\tverbose_msg(\"Error: sqrt(det(cov)) == 0, %lf after rounding. \\n\", det);\n\t\t//cerr << covariance << endl;\n\t\treturn NUMERIC_FAIL;\n\t}\n\tassert (s);\n\tassert (is_scale_factor);\n    return NUMERIC_OK;\n}\n\ntemplate<class M, class PM>\nbool is_identifiable(M &m, PM &pm)\n{\n    using namespace ublas;\n    typedef M matrix_type;\n    typedef typename M::size_type size_type;\n    typedef typename M::value_type value_type;\n\n    int singular = 0;\n    size_type size1 = m.size1 ();\n    size_type size2 = m.size2 ();\n    size_type size = (std::min) (size1, size2);\n    for (size_type i = 0; i < size; ++ i) {\n        matrix_column<M> mci (column (m, i));\n        matrix_row<M> mri (row (m, i));\n        size_type i_norm_inf = i + index_norm_inf (project (mci, boost::numeric::ublas::range (i, size1)));\n        if (m (i_norm_inf, i) != value_type/*zero*/()) {\n            if (i_norm_inf != i) {\n                pm (i) = i_norm_inf;\n                row (m, i_norm_inf).swap (mri);\n            } else {\n                //BOOST_UBLAS_CHECK (pm (i) == i_norm_inf, external_logic ());\n            }\n            project (mci, boost::numeric::ublas::range (i + 1, size1)) *= value_type (1) / m (i, i);\n        } else if (singular == 0) {\n            singular = i + 1;\n        }\n        project (m, boost::numeric::ublas::range (i + 1, size1), boost::numeric::ublas::range (i + 1, size2)).minus_assign (outer_prod (project (mci, boost::numeric::ublas::range (i + 1, size1)),\n                                                                              project (mri, boost::numeric::ublas::range (i + 1, size2))));\n    }\n    return singular == 0;\n}\n\nAbundanceStatus gamma_mle(const vector<boost::shared_ptr<Abundance> >& transcripts,\n                          const vector<MateHit>& nr_alignments,\n                          const vector<double>& log_conv_factors,\n                          vector<double>& gammas,\n                          bool check_identifiability)\n{\n\t//gammas.clear();\n    gammas = vector<double>(transcripts.size(), 0);\n\tif (transcripts.empty())\n\t\treturn NUMERIC_OK;\n\t\n\t\n\tif (transcripts.size() == 1)\n\t{\n\t\tgammas = vector<double>(1,1.0);\n\t\treturn NUMERIC_OK;\n\t}\n\t\n\tsize_t M = nr_alignments.size();\n\tsize_t N = transcripts.size();\n\n    bool converged = true;\n    bool identifiable = true;\n    \n\tif (M > 0)\n\t{\n\t\t\n\t\t//vector<vector<double> > saliencies (M,vector<double>(N,0));\n\t\t\n\t\t\n\t\t//compute_saliencies(cond_probs, saliencies, saliency_weight);\n\t\t\n        Eigen::VectorXd prob = Eigen::VectorXd::Zero(N);\n        Eigen::VectorXd _phint = Eigen::VectorXd::Zero(N);\n        \n\t\tdouble logL;\n\t\t\n        Eigen::MatrixXd cond_probs(N, M);\n\t\t\n        for (size_t j = 0; j < cond_probs.rows(); ++j)\n        {\n            for (size_t i = 0; i < cond_probs.cols(); ++i)\n            {\n                cond_probs(j,i) = (*(transcripts[j]->cond_probs()))[i];\n            }\n        }\n        \n        if (check_identifiability)\n        {\n            ublas::matrix<double> compat = ublas::zero_matrix<double>(M,N);\n            \n            for (size_t j = 0; j < N; ++j)\n            {\n                for (size_t i = 0; i < M; ++i)\n                {\n                    if (cond_probs(j,i))\n                    {\n                        //compat(i,j) = cond_probs[j][i];\n                        compat(i,j) = 1;\n                    }\n                }\n            }\n            \n            vector<size_t> transcripts_with_frags;\n            for (size_t j = 0; j < N; ++j)\n            {\n                bool has_fragment = false;\n                for (size_t i = 0; i < M; ++i)\n                {\n                    if (compat(i,j))\n                    {\n                        has_fragment = true;\n                        break;\n                    }\n                }\n                if (has_fragment)\n                    transcripts_with_frags.push_back(j);\n            }\n            ublas::matrix<double> reduced_compat = ublas::zero_matrix<double>(M,transcripts_with_frags.size());\n            for (size_t j = 0; j < transcripts_with_frags.size(); ++j)\n            {\n                column(reduced_compat, j) = column(compat, transcripts_with_frags[j]);\n            }\n            \n            \n            typedef ublas::permutation_matrix<std::size_t> pmatrix;\n            \n            // create a permutation matrix for the LU-factorization\n            pmatrix pm(reduced_compat.size1());\n            \n            // cerr << compat.size2() <<endl;\n            // perform LU-factorization\n            identifiable = is_identifiable<ublas::matrix<double>,pmatrix>(reduced_compat,pm);\n        }\n        \n        Eigen::VectorXd alignment_multiplicities(M);\n\t\tfor (size_t i = 0; i < M; ++i)\n\t\t{\n\t\t\talignment_multiplicities[i] = nr_alignments[i].collapse_mass();\n\t\t}\n        \t\t\n        logL = EM(N, M, prob, cond_probs, alignment_multiplicities, log_conv_factors, converged);\n        \n\t\tgammas = vector<double>(N, 0.0);\n\t\t\n\t\tfor (size_t i = 0; i < gammas.size(); ++i)\n\t\t{\n            gammas[i] = prob(i);\n\t\t\tif (isnan(gammas[i]) || isinf(gammas[i]))\n            {\n                return NUMERIC_FAIL;\n            }\n\t\t}\n\t}\n\telse\n\t{\n\t\tgammas = vector<double>(N, 0.0);\n\t}\n    \n    double round_err = 0.0;\n    double num_good = 0;\n    BOOST_FOREACH (double& g, gammas)\n    {\n        if (g < min_isoform_fraction)\n        {\n            round_err += g;\n            g = 0.0;\n        }\n        else\n        {\n            num_good += 1;\n        }\n    }\n    BOOST_FOREACH (double& g, gammas)\n    {\n        if (g != 0)\n        {\n            g += (round_err/num_good);\n        }\n    }\n    \n    if (converged && identifiable)\n        return NUMERIC_OK;\n    else\n    {\n        if (!identifiable)\n            //return NUMERIC_LOW_DATA;\n            return NUMERIC_OK;\n        else\n            return NUMERIC_FAIL;\n    }\n    \n    return NUMERIC_OK;\n}\n\nvoid calc_isoform_fpkm_conf_intervals(double FPKM,\n\t\t\t\t\t\t\t\t\t  double variance,\n\t\t\t\t\t\t\t\t\t  ConfidenceInterval& FPKM_conf)\n{\n\tdouble FPKM_lo = 0.0;\n\tdouble FPKM_hi = 0.0;\n\tFPKM_hi = FPKM + 2 * sqrt(variance);\n\tFPKM_lo = max(0.0, FPKM - 2 * sqrt(variance));\n\tFPKM_conf = ConfidenceInterval(FPKM_lo, FPKM_hi);\n}\n\nbool not_intronic(int p, vector<float>& depth_of_coverage, vector<float>& intronic_cov, float min_intra_intron_fraction,\n      int& intronic_status) {\n  bool not_an_intron = (intronic_cov[p]==0 ||\n        depth_of_coverage[p]/intronic_cov[p] >= min_intra_intron_fraction);\n if (not_an_intron) intronic_status--;\n               else intronic_status++;\n return not_an_intron;\n}\n\n\ndouble compute_doc(int bundle_origin, \n\t\t\t\t   const vector<Scaffold>& scaffolds,\n\t\t\t\t   vector<float>& depth_of_coverage,\n\t\t\t\t   map<pair<int, int>, float>& intron_depth_of_coverage,\n\t\t\t\t   bool exclude_intra_intron,\n\t\t\t\t   vector<float>* intronic_cov,\n\t\t\t\t   vector<int>* scaff_intronic_status)\n{\n  vector<int> i_status;\n  if (scaff_intronic_status==NULL)\n    scaff_intronic_status=&i_status;\n  *scaff_intronic_status = vector<int>(scaffolds.size(), 0);\n  vector<float> intronic;\n  if (intronic_cov==NULL)\n    intronic_cov=&intronic;\n  *intronic_cov = vector<float>(depth_of_coverage.size(), 0);\n  //vector<bool> intronic(depth_of_coverage.size(), false);\n\tdepth_of_coverage = vector<float>(depth_of_coverage.size(), 0);\n\t\t\n\tset<const MateHit*> hits_in_gene_set;\n\tfor (size_t i = 0; i < scaffolds.size(); ++i)\n\t{\n\t\thits_in_gene_set.insert(scaffolds[i].mate_hits().begin(),\n\t\t\t\t\t\t\t\tscaffolds[i].mate_hits().end());\n\t}\n\t\n\tvector<Scaffold> hits;\n\t\n\tfor(set<const MateHit*>::iterator itr = hits_in_gene_set.begin();\n\t\titr != hits_in_gene_set.end();\n\t\t++itr)\n\t{\n\t\thits.push_back(Scaffold(**itr));\n        hits.back().fpkm((**itr).mass());\n\t}\n\n\t/*\n\t//no need for this here, we do it below with depth_of_coverage\n\tfor (size_t i = 0; i < hits.size(); ++i)\n\t{\n\t\tconst vector<AugmentedCuffOp>& aug_ops = hits[i].augmented_ops();\n\t\tfor (size_t j = 0; j < aug_ops.size(); ++j)\n\t\t{\n\t\t\tconst AugmentedCuffOp& op = aug_ops[j];\n\t\t\tif (op.opcode == CUFF_INTRON)\n\t\t\t{\n\t\t\t\tfor (int K = op.g_left(); K < op.g_right(); ++K)\n\t\t\t\t{\n\t\t\t\t\tintronic[K - bundle_origin] = true; \n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t*/\n\tfor (size_t i = 0; i < hits.size(); ++i)\n\t{\n\t\tconst vector<AugmentedCuffOp>& aug_ops = hits[i].augmented_ops();\n\t\tfor (size_t j = 0; j < aug_ops.size(); ++j)\n\t\t{\n\t\t\tconst AugmentedCuffOp& op = aug_ops[j];\n\t\t\tif (op.opcode == CUFF_MATCH)\n\t\t\t{\n\t\t\t\tfor (int K = op.g_left(); K < op.g_right(); ++K)\n\t\t\t\t{\n\t\t\t\t\tdepth_of_coverage[K - bundle_origin] += hits[i].fpkm();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (op.opcode == CUFF_INTRON)\n\t\t\t{\n        for (int K = op.g_left(); K < op.g_right(); ++K)\n        {\n          (*intronic_cov)[K - bundle_origin] += hits[i].fpkm();\n          //intronic[K - bundle_origin] = true;\n        }\n\n\t\t\t\tpair<map<pair<int,int>,float>::iterator, bool> is = intron_depth_of_coverage.insert(make_pair(make_pair(op.g_left(), op.g_right()), 0));\n\t\t\t\tis.first->second += hits[i].fpkm();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tvector<float> knockout(depth_of_coverage);\n\t\n\tdouble total_doc = 0;\n\tint total_len = 0;\n\tfloat min_intra_intron_fraction = min(pre_mrna_fraction, min_isoform_fraction);\n\t//for (size_t i = 0; i < hits.size(); ++i)\n\tfor (size_t i = 0; i < scaffolds.size(); ++i)\n\t{\n\t\t//const vector<AugmentedCuffOp>& aug_ops = hits[i].augmented_ops();\n\t  const vector<AugmentedCuffOp>& aug_ops = scaffolds[i].augmented_ops();\n\t\tfor (size_t j = 0; j < aug_ops.size(); ++j)\n\t\t{\n\t\t\tconst AugmentedCuffOp& op = aug_ops[j];\n\t\t\tif (op.opcode == CUFF_MATCH)\n\t\t\t{\n\t\t\t\tfor (int K = op.g_left(); K < op.g_right(); ++K)\n\t\t\t\t{\n\t\t\t\t\t//if (!exclude_intra_intron || !intronic[K - bundle_origin])\n\t\t\t\t  if (!exclude_intra_intron ||\n\t\t\t\t       not_intronic(K-bundle_origin, depth_of_coverage, *intronic_cov, min_intra_intron_fraction,\n\t\t\t\t           (*scaff_intronic_status)[i]) )\n\t\t\t\t\t{\n\t\t\t\t\t\ttotal_doc += knockout[K - bundle_origin];\n\t\t\t\t\t\ttotal_len += (knockout[K - bundle_origin] != 0);\n\t\t\t\t\t\tknockout[K - bundle_origin] = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn total_doc/(double)total_len;\n}\n\ndouble major_isoform_intron_doc(map<pair<int, int>, float>& intron_doc)\n{\n\tdouble major_isoform_intron_doc = 0;\n\tint num_major_introns = 0;\n\tfor(map<pair<int, int>, float>::const_iterator itr = intron_doc.begin();\n\t\titr != intron_doc.end(); \n\t\t++itr)\n\t{\n\t\tbool heaviest = true;\n\t\t\n\t\tfor (map<pair<int,int>, float>::const_iterator itr2 = intron_doc.begin();\n\t\t\t itr2 != intron_doc.end();\n\t\t\t ++itr2)\n\t\t{\t\n\t\t\tif (itr != itr2 &&\n\t\t\t\titr->second < itr2->second &&\n\t\t\t\toverlap_in_genome(itr->first.first,\n\t\t\t\t\t\t\t\t  itr->first.second,\n\t\t\t\t\t\t\t\t  itr2->first.first,\n\t\t\t\t\t\t\t\t  itr2->first.second))\n\t\t\t{\n\t\t\t\theaviest = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (heaviest)\n\t\t{\n\t\t\tmajor_isoform_intron_doc += itr->second;\n\t\t\tnum_major_introns++;\n\t\t}\n\t}\n\tif (num_major_introns)\n\t{\n\t\treturn major_isoform_intron_doc / num_major_introns;\n\t}\n\telse\n\t{\n\t\treturn 0.0;\n\t}\t\n}\n\nvoid record_min_doc_for_scaffolds(int bundle_origin, \n\t\t\t\t\t\t\t\t  const vector<Scaffold>& hits,\n\t\t\t\t\t\t\t\t  const vector<float>& depth_of_coverage,\n\t\t\t\t\t\t\t\t  const map<pair<int, int>, float>& intron_depth_of_coverage,\n\t\t\t\t\t\t\t\t  vector<double>& scaff_doc)\n{\n\tfor (size_t h = 0; h < hits.size(); ++h)\n\t{\n\t\tdouble doc = 99999999.0;\n\t\tif (hits[h].has_intron())\n\t\t\tdoc = get_intron_doc(hits[h], intron_depth_of_coverage);\n\t\t\n\t\tdoc = min(doc, get_scaffold_min_doc(bundle_origin, \n\t\t\t\t\t\t\t\t\t\t\thits[h], \n\t\t\t\t\t\t\t\t\t\t\tdepth_of_coverage));\n\t\tscaff_doc.push_back(doc);\n\t}\n}\n\nvoid record_doc_for_scaffolds(int bundle_origin, \n\t\t\t\t\t\t\t  const vector<Scaffold>& hits,\n\t\t\t\t\t\t\t  const vector<float>& depth_of_coverage,\n\t\t\t\t\t\t\t  vector<double>& scaff_doc)\n{\n\tfor (size_t h = 0; h < hits.size(); ++h)\n\t{\n\t\tdouble doc;\n\t\tdoc = get_scaffold_doc(bundle_origin, \n\t\t\t\t\t\t\t   hits[h], \n\t\t\t\t\t\t\t   depth_of_coverage);\n\t\tscaff_doc.push_back(doc);\n\t}\n}\n\nvoid record_doc_for_scaffolds(int bundle_origin, \n\t\t\t\t\t\t\t  const vector<Scaffold>& hits,\n\t\t\t\t\t\t\t  const vector<float>& depth_of_coverage,\n\t\t\t\t\t\t\t  const map<pair<int, int>, float>& intron_depth_of_coverage,\n\t\t\t\t\t\t\t  vector<double>& scaff_doc)\n{\n\tfor (size_t h = 0; h < hits.size(); ++h)\n\t{\n\t\tdouble doc;\n\t\tif (hits[h].has_intron())\n\t\t\tdoc = get_intron_doc(hits[h], intron_depth_of_coverage);\n\t\telse\n\t\t\tdoc = get_scaffold_doc(bundle_origin, \n\t\t\t\t\t\t\t\t   hits[h], \n\t\t\t\t\t\t\t\t   depth_of_coverage);\n\t\tscaff_doc.push_back(doc);\n\t}\n}\n\ndouble get_intron_doc(const Scaffold& s,\n\t\t\t\t\t  const map<pair<int, int>, float >& intron_depth_of_coverage)\n{\n\tconst vector<AugmentedCuffOp>& aug_ops = s.augmented_ops();\n\tint num_introns = 0;\n\tdouble doc = 0;\n\tfor (size_t j = 0; j < aug_ops.size(); ++j)\n\t{\n\t\tconst AugmentedCuffOp& op = aug_ops[j];\n\t\tif (op.opcode == CUFF_INTRON)\n\t\t{\n\t\t\tnum_introns++;\n\t\t\tpair<int,int> op_intron(op.g_left(), op.g_right());\n\t\t\tmap<pair<int, int>, float >::const_iterator itr = intron_depth_of_coverage.find(op_intron);\n\t\t\t//\t\t\tassert (itr != intron_depth_of_coverage.end());\n\t\t\tif (itr == intron_depth_of_coverage.end())\n\t\t\t{\n\t\t\t\tmap<pair<int, int>, float >::const_iterator zi;\n\t\t\t\tfor (zi = intron_depth_of_coverage.begin();\n\t\t\t\t\t zi != intron_depth_of_coverage.end();\n\t\t\t\t\t ++zi)\n\t\t\t\t{\n\t\t\t\t\tverbose_msg( \"Warning: intron not within scaffold ([%d-%d], %d)\\n\", zi->first.first, zi->first.second, zi->second);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdoc += itr->second;\n\t\t}\n\t}\n\treturn doc / (double)num_introns;\n}\n\ndouble get_scaffold_doc(int bundle_origin, \n\t\t\t\t\t\tconst Scaffold& s,\n\t\t\t\t\t\tconst vector<float>& depth_of_coverage)\n{\n\tconst vector<AugmentedCuffOp>& aug_ops = s.augmented_ops();\n\tint m_len = 0;\n\tdouble doc = 0;\n\tfor (size_t j = 0; j < aug_ops.size(); ++j)\n\t{\n\t\tconst AugmentedCuffOp& op = aug_ops[j];\n\t\tif (op.opcode == CUFF_MATCH)\n\t\t{\n\t\t\tfor (int K = op.g_left(); K < op.g_right(); ++K)\n\t\t\t{\n\t\t\t\tm_len++;\n\t\t\t\tdoc += depth_of_coverage[K - bundle_origin];\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn doc/(double)m_len;\n}\n\ndouble get_scaffold_min_doc(int bundle_origin, \n\t\t\t\t\t\t\tconst Scaffold& s,\n\t\t\t\t\t\t\tconst vector<float>& depth_of_coverage)\n{\n\tconst vector<AugmentedCuffOp>& aug_ops = s.augmented_ops();\n\tfloat min_doc = 99999999;\n\t\n\tfor (size_t j = 0; j < aug_ops.size(); ++j)\n\t{\n\t\tconst AugmentedCuffOp& op = aug_ops[j];\n\t\tif (op.opcode == CUFF_MATCH)\n\t\t{\n\t\t\tfor (int K = op.g_left(); K < op.g_right(); ++K)\n\t\t\t{\n\t\t\t\tif (min_doc > depth_of_coverage[K - bundle_origin])\n\t\t\t\t\tmin_doc = depth_of_coverage[K - bundle_origin];\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn min_doc;\n}\n\nvoid tss_analysis(const string& locus_tag, SampleAbundances& sample)\n{\n    // Cluster transcripts by start site (TSS)\n    vector<AbundanceGroup> transcripts_by_tss;\n    \n    ublas::matrix<double> tss_gamma_cov;\n    ublas::matrix<double> tss_count_cov;\n    ublas::matrix<double> tss_iterated_exp_count_cov;\n    ublas::matrix<double> tss_fpkm_cov;\n    vector<Eigen::VectorXd> tss_assigned_counts;\n    \n    vector<bool> mask(sample.transcripts.abundances().size(), true);\n    for (size_t i = 0; i < sample.transcripts.abundances().size(); ++i)\n    {\n        if (*(sample.transcripts.abundances()[i]->tss_id().begin()) == \"\")\n        {\n            mask[i] = false;\n        }\n    }\n    \n    AbundanceGroup trans_with_tss;\n    sample.transcripts.filter_group(mask, trans_with_tss);\n    \n    cluster_transcripts<ConnectByAnnotatedTssId>(trans_with_tss,\n                                                 transcripts_by_tss,\n                                                 &tss_gamma_cov,\n                                                 &tss_iterated_exp_count_cov,\n                                                 &tss_count_cov,\n                                                 &tss_fpkm_cov);\n    \n    \n    BOOST_FOREACH(AbundanceGroup& ab_group, transcripts_by_tss)\n    {\n        ab_group.locus_tag(locus_tag);\n        set<string> tss_ids = ab_group.tss_id();\n        assert (tss_ids.size() == 1);\n        string desc = *(tss_ids.begin());\n        assert (desc != \"\");\n        ab_group.description(*(tss_ids.begin()));\n    }\n    \n    sample.primary_transcripts = transcripts_by_tss;\n    \n    // Group TSS clusters by gene\n    vector<boost::shared_ptr<Abundance> > primary_transcript_abundances;\n    set<boost::shared_ptr<ReadGroupProperties const> > rg_props;\n    BOOST_FOREACH (AbundanceGroup& ab_group, sample.primary_transcripts)\n    {\n        primary_transcript_abundances.push_back(boost::shared_ptr<Abundance>(new AbundanceGroup(ab_group)));\n        rg_props.insert(ab_group.rg_props().begin(), ab_group.rg_props().end());\n    }\n    \n    AbundanceGroup primary_transcripts(primary_transcript_abundances,\n                                       tss_gamma_cov,\n                                       tss_iterated_exp_count_cov,\n                                       tss_count_cov,\n                                       tss_fpkm_cov,\n                                       rg_props);\n    \n    vector<AbundanceGroup> primary_transcripts_by_gene;\n    \n    cluster_transcripts<ConnectByAnnotatedGeneId>(primary_transcripts,\n                                                  primary_transcripts_by_gene);\n    \n    BOOST_FOREACH(AbundanceGroup& ab_group, primary_transcripts_by_gene)\n    {\n        ab_group.locus_tag(locus_tag);\n        set<string> gene_ids = ab_group.gene_id();\n        if (gene_ids.size() > 1)\n        {\n            BOOST_FOREACH (string st, gene_ids)\n            {\n                fprintf(stderr, \"%s\\n\", st.c_str());\n            }\n            ab_group.gene_id();\n        }\n        assert (gene_ids.size() == 1);\n        ab_group.description(*(gene_ids.begin()));\n    }\n    \n    sample.gene_primary_transcripts = primary_transcripts_by_gene;\n}\n\nvoid cds_analyis(const string& locus_tag, SampleAbundances& sample)\n{\n    // Cluster transcripts by CDS\n    vector<AbundanceGroup> transcripts_by_cds;\n    ublas::matrix<double> cds_gamma_cov;\n    ublas::matrix<double> cds_count_cov;\n    ublas::matrix<double> cds_iterated_exp_count_cov;\n    ublas::matrix<double> cds_fpkm_cov;\n    \n    vector<bool> mask(sample.transcripts.abundances().size(), true);\n    for (size_t i = 0; i < sample.transcripts.abundances().size(); ++i)\n    {\n        if (*(sample.transcripts.abundances()[i]->protein_id().begin()) == \"\")\n        {\n            mask[i] = false;\n        }\n    }\n    \n    AbundanceGroup trans_with_p_id;\n    sample.transcripts.filter_group(mask, trans_with_p_id);\n    \n    cluster_transcripts<ConnectByAnnotatedProteinId>(trans_with_p_id,\n                                                     transcripts_by_cds,\n                                                     &cds_gamma_cov,\n                                                     &cds_iterated_exp_count_cov,\n                                                     &cds_count_cov,\n                                                     &cds_fpkm_cov);\n    \n    BOOST_FOREACH(AbundanceGroup& ab_group, transcripts_by_cds)\n    {\n        ab_group.locus_tag(locus_tag);\n        set<string> protein_ids = ab_group.protein_id();\n        assert (protein_ids.size() == 1);\n        string desc = *(protein_ids.begin());\n        //if (desc != \"\")\n        //{\n        assert (desc != \"\");\n        ab_group.description(*(protein_ids.begin()));\n        //}\n    }\n    \n    sample.cds = transcripts_by_cds;\n    \n    // Group the CDS clusters by gene\n    vector<boost::shared_ptr<Abundance> > cds_abundances;\n    \n    set<boost::shared_ptr<ReadGroupProperties const> > rg_props;\n    BOOST_FOREACH (AbundanceGroup& ab_group, sample.cds)\n    {\n        //if (ab_group.description() != \"\")\n        {\n            cds_abundances.push_back(boost::shared_ptr<Abundance>(new AbundanceGroup(ab_group)));\n            rg_props.insert(ab_group.rg_props().begin(), ab_group.rg_props().end());\n        }\n    }\n    AbundanceGroup cds(cds_abundances,\n                       cds_gamma_cov,\n                       cds_iterated_exp_count_cov,\n                       cds_count_cov,\n                       cds_fpkm_cov,\n                       rg_props);\n    \n    vector<AbundanceGroup> cds_by_gene;\n    \n    cluster_transcripts<ConnectByAnnotatedGeneId>(cds,\n                                                  cds_by_gene);\n    \n    BOOST_FOREACH(AbundanceGroup& ab_group, cds_by_gene)\n    {\n        ab_group.locus_tag(locus_tag);\n        set<string> gene_ids = ab_group.gene_id();\n        assert (gene_ids.size() == 1);\n        ab_group.description(*(gene_ids.begin()));\n    }\n    \n    sample.gene_cds = cds_by_gene;\n\n}\n\nvoid sample_abundance_worker(const string& locus_tag,\n                             const set<boost::shared_ptr<ReadGroupProperties const> >& rg_props,\n                             SampleAbundances& sample,\n                             boost::shared_ptr<HitBundle> sample_bundle,\n                             bool perform_cds_analysis,\n                             bool perform_tss_analysis,\n                             bool calculate_variance)\n{\n    vector<boost::shared_ptr<Abundance> > abundances;\n    \n    BOOST_FOREACH(boost::shared_ptr<Scaffold> s, sample_bundle->ref_scaffolds())\n    {\n        TranscriptAbundance* pT = new TranscriptAbundance;\n        pT->transfrag(s);\n        boost::shared_ptr<Abundance> ab(pT);\n        ab->description(s->annotated_trans_id());\n        ab->locus_tag(locus_tag);\n        abundances.push_back(ab);\n    }\n    \n    sample.transcripts = AbundanceGroup(abundances);\n    \n    sample.transcripts.init_rg_props(rg_props);\n    \n    vector<MateHit> hits_in_cluster;\n    \n    if (sample_bundle->hits().size() < (size_t)max_frags_per_bundle)\n    {\n        get_alignments_from_scaffolds(sample.transcripts.abundances(),\n                                      hits_in_cluster);\n        \n        // Compute the individual transcript FPKMs via each sample's\n        // AbundanceGroup for this locus.\n        \n        sample.transcripts.calculate_abundance(hits_in_cluster, true, calculate_variance);\n    }\n    else\n    {\n        BOOST_FOREACH(boost::shared_ptr<Abundance>  ab, abundances)\n        {\n            ab->status(NUMERIC_HI_DATA);\n            \n            CountPerReplicateTable cpr;\n            FPKMPerReplicateTable fpr;\n            StatusPerReplicateTable spr;\n            for (set<boost::shared_ptr<ReadGroupProperties const> >::const_iterator itr = rg_props.begin();\n                 itr != rg_props.end();\n                 ++itr)\n            {\n                cpr[*itr] = 0;\n                fpr[*itr] = 0;\n                spr[*itr] = NUMERIC_HI_DATA;\n            }\n            ab->num_fragments_by_replicate(cpr);\n            ab->FPKM_by_replicate(fpr);\n            ab->status_by_replicate(spr);\n        }\n    }\n    \n    // Cluster transcripts by gene_id\n    vector<AbundanceGroup> transcripts_by_gene_id;\n    cluster_transcripts<ConnectByAnnotatedGeneId>(sample.transcripts,\n                                                  transcripts_by_gene_id);\n    \n\tBOOST_FOREACH(AbundanceGroup& ab_group, transcripts_by_gene_id)\n    {\n        ab_group.locus_tag(locus_tag);\n        set<string> gene_ids = ab_group.gene_id();\n        assert (gene_ids.size() == 1);\n        ab_group.description(*(gene_ids.begin()));\n    }\n\t\n    sample.genes = transcripts_by_gene_id;\n    \n    if (perform_cds_analysis)\n    {\n        cds_analyis(locus_tag, sample);\n    }\n    \n    if (perform_tss_analysis)    {\n        tss_analysis(locus_tag, sample);\n    }\n}\n\n// This function applies library size factors to pre-computed expression entries\nvoid AbundanceGroup::apply_normalization_to_abundances(const map<boost::shared_ptr<const ReadGroupProperties>, boost::shared_ptr<const AbundanceGroup> >& unnormalized_ab_group_per_replicate,\n                                                       map<boost::shared_ptr<const ReadGroupProperties>, boost::shared_ptr<AbundanceGroup> >& normalized_ab_group_per_replicate)\n{\n    for (map<boost::shared_ptr<const ReadGroupProperties>, boost::shared_ptr<const AbundanceGroup> >::const_iterator itr = unnormalized_ab_group_per_replicate.begin();\n         itr != unnormalized_ab_group_per_replicate.end(); ++itr)\n    {\n        boost::shared_ptr<AbundanceGroup> norm_ab = boost::shared_ptr<AbundanceGroup>(new AbundanceGroup(*itr->second));\n        boost::shared_ptr<const ReadGroupProperties> rg_props = itr->first;\n        boost::shared_ptr<const MassDispersionModel> disp_model = rg_props->mass_dispersion_model();\n        \n        boost::shared_ptr<const ReadGroupProperties> old_rg_props = *(itr->second->rg_props().begin());\n        \n        double fpkm_correction_factor = 1.0;\n        fpkm_correction_factor = old_rg_props->normalized_map_mass() / rg_props->normalized_map_mass();\n        \n        double internal_scale_factor = rg_props->internal_scale_factor();\n        \n        double total_mass = 0.0;\n        \n        for (size_t i = 0; i < norm_ab->_abundances.size(); ++i)\n        {\n            norm_ab->_abundances[i]->num_fragments(itr->second->_abundances[i]->num_fragments() / internal_scale_factor);\n            \n            total_mass += norm_ab->_abundances[i]->num_fragments();\n            \n            norm_ab->_abundances[i]->FPKM(fpkm_correction_factor * itr->second->_abundances[i]->FPKM() / internal_scale_factor);\n            norm_ab->_iterated_exp_count_covariance = norm_ab->iterated_count_cov() / (internal_scale_factor*internal_scale_factor);\n            norm_ab->_fpkm_covariance = norm_ab->_fpkm_covariance * (fpkm_correction_factor * fpkm_correction_factor)/ (internal_scale_factor*internal_scale_factor);\n            norm_ab->_count_covariance = norm_ab->_count_covariance/ (internal_scale_factor*internal_scale_factor);\n        }\n        \n        double locus_mass_variance = disp_model->scale_mass_variance(total_mass);\n        \n        for (size_t i = 0; i < norm_ab->_abundances.size(); ++i)\n        {\n            norm_ab->_abundances[i]->mass_variance(locus_mass_variance * norm_ab->_abundances[i]->gamma());\n        }\n        \n        normalized_ab_group_per_replicate[itr->first] = norm_ab;\n    }\n}\n\nvoid merge_precomputed_expression_worker(const string& locus_tag,\n                                         const vector<boost::shared_ptr<PrecomputedExpressionBundleFactory> >& expression_factories,\n                                         SampleAbundances& sample,\n                                         boost::shared_ptr<HitBundle> sample_bundle,\n                                         bool perform_cds_analysis,\n                                         bool perform_tss_analysis,\n                                         bool calculate_variance)\n{\n    map<boost::shared_ptr<const ReadGroupProperties>, boost::shared_ptr<const AbundanceGroup> > unnormalized_ab_group_per_replicate;\n    map<boost::shared_ptr<const ReadGroupProperties>, boost::shared_ptr<AbundanceGroup> > normalized_ab_group_per_replicate;\n    map<boost::shared_ptr<const ReadGroupProperties>, boost::shared_ptr<const AbundanceGroup> > const_ab_group_per_replicate;\n    \n    set<boost::shared_ptr<const ReadGroupProperties> > rg_props;\n    for (size_t i = 0; i < expression_factories.size(); ++i)\n    {\n        boost::shared_ptr<PrecomputedExpressionBundleFactory> pBundleFac = expression_factories[i];\n        boost::shared_ptr<const PrecomputedExpressionHitFactory> pHitFac = boost::dynamic_pointer_cast<const PrecomputedExpressionHitFactory> (pBundleFac->hit_factory());\n        assert (pHitFac);\n        \n        boost::shared_ptr<const ReadGroupProperties> rg_prop = pBundleFac->read_group_properties();\n        rg_props.insert(rg_prop);\n        \n        boost::shared_ptr<const AbundanceGroup> ab = pBundleFac->get_abundance_for_locus(sample_bundle->id());\n        pBundleFac->clear_abundance_for_locus(sample_bundle->id());\n        if (!ab)\n        {\n            fprintf(stderr, \"Error: no bundle with id %d in precomputed expression file\\n\", sample_bundle->id());\n        }\n        else if(ab->abundances().size() != sample_bundle->ref_scaffolds().size())\n        {\n            fprintf(stderr, \"Error: bad bundle merge %s != %s\\n\", ab->description().c_str(), locus_tag.c_str());\n        }\n        unnormalized_ab_group_per_replicate[rg_prop] = ab;\n    }\n    \n    AbundanceGroup::apply_normalization_to_abundances(unnormalized_ab_group_per_replicate, normalized_ab_group_per_replicate);\n    \n    for (map<boost::shared_ptr<const ReadGroupProperties>, boost::shared_ptr<AbundanceGroup> >::const_iterator itr = normalized_ab_group_per_replicate.begin();\n         itr != normalized_ab_group_per_replicate.end(); ++itr)\n    {\n        const_ab_group_per_replicate[itr->first] = itr->second;\n    }\n    \n    vector<boost::shared_ptr<Abundance> > abundances;\n    \n    BOOST_FOREACH(boost::shared_ptr<Scaffold> s, sample_bundle->ref_scaffolds())\n    {\n        TranscriptAbundance* pT = new TranscriptAbundance;\n        pT->transfrag(s);\n        boost::shared_ptr<Abundance> ab(pT);\n        ab->description(s->annotated_trans_id());\n        ab->locus_tag(locus_tag);\n        abundances.push_back(ab);\n    }\n    \n    sample.transcripts = AbundanceGroup(abundances);\n    \n    sample.transcripts.init_rg_props(rg_props);\n    \n    vector<MateHit> hits_in_cluster;\n    \n    if (sample_bundle->hits().size() < (size_t)max_frags_per_bundle)\n    {\n        sample.transcripts.collect_per_replicate_mass(const_ab_group_per_replicate);\n        sample.transcripts.aggregate_replicate_abundances(const_ab_group_per_replicate);\n        if (calculate_variance)\n        {\n            sample.transcripts.calculate_abundance_group_variance(abundances, const_ab_group_per_replicate);\n        }\n    }\n    else // FIXME: THIS needs to do the right thing with sample.transcripts...\n    {\n        BOOST_FOREACH(boost::shared_ptr<Abundance>  ab, abundances)\n        {\n            ab->status(NUMERIC_HI_DATA);\n            \n            CountPerReplicateTable cpr;\n            FPKMPerReplicateTable fpr;\n            StatusPerReplicateTable spr;\n            for (set<boost::shared_ptr<ReadGroupProperties const> >::const_iterator itr = rg_props.begin();\n                 itr != rg_props.end();\n                 ++itr)\n            {\n                cpr[*itr] = 0;\n                fpr[*itr] = 0;\n                spr[*itr] = NUMERIC_HI_DATA;\n            }\n            ab->num_fragments_by_replicate(cpr);\n            ab->FPKM_by_replicate(fpr);\n            ab->status_by_replicate(spr);\n        }\n    }\n    \n    // Cluster transcripts by gene_id\n    vector<AbundanceGroup> transcripts_by_gene_id;\n    cluster_transcripts<ConnectByAnnotatedGeneId>(sample.transcripts,\n                                                  transcripts_by_gene_id);\n    \n\tBOOST_FOREACH(AbundanceGroup& ab_group, transcripts_by_gene_id)\n    {\n        ab_group.locus_tag(locus_tag);\n        set<string> gene_ids = ab_group.gene_id();\n        assert (gene_ids.size() == 1);\n        ab_group.description(*(gene_ids.begin()));\n    }\n\t\n    sample.genes = transcripts_by_gene_id;\n    \n    if (perform_cds_analysis)\n    {\n        cds_analyis(locus_tag, sample);\n    }\n    \n    if (perform_tss_analysis)\n    {\n        tss_analysis(locus_tag, sample);\n    }\n}\n\n\n//BOOST_CLASS_EXPORT(Abundance)\nBOOST_CLASS_EXPORT(TranscriptAbundance)\nBOOST_SERIALIZATION_SHARED_PTR(TranscriptAbundance);\nBOOST_CLASS_EXPORT(AbundanceGroup);\nBOOST_SERIALIZATION_SHARED_PTR(AbundanceGroup);\nBOOST_SERIALIZATION_ASSUME_ABSTRACT(Abundance);\n\n"
  },
  {
    "path": "src/abundances.h",
    "content": "#ifndef ABUNDANCES_H\n#define ABUNDANCES_H\n/*\n *  abundances.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 4/27/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdint.h>\n#include <vector>\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/vector.hpp>\n\n#include <Eigen/Dense>\n\n#include \"hits.h\"\n#include \"scaffolds.h\"\n#include \"bundles.h\"\n#include \"biascorrection.h\"\n\nnamespace ublas = boost::numeric::ublas;\n\nstruct ConfidenceInterval\n{\n\tConfidenceInterval(double Low = 0.0, double High = 0.0) \n\t: low(Low), high(High) {}\n\tdouble low;\n\tdouble high;\n    \nprivate:\n    friend std::ostream & operator<<(std::ostream &os, const ConfidenceInterval &gp);\n    friend class boost::serialization::access;\n    template<class Archive>\n    void serialize(Archive & ar, const unsigned int /* file_version */){\n        ar & low & high;\n    }\n};\n\nenum AbundanceStatus { NUMERIC_OK, NUMERIC_FAIL, NUMERIC_LOW_DATA, NUMERIC_HI_DATA };\n\ntypedef map<boost::shared_ptr<ReadGroupProperties const>, double> CountPerReplicateTable;\ntypedef map<boost::shared_ptr<ReadGroupProperties const>, double> FPKMPerReplicateTable;\ntypedef map<boost::shared_ptr<ReadGroupProperties const>, AbundanceStatus> StatusPerReplicateTable;\n\nbool fit_negbin_dist(const vector<double> samples, double& r, double& p);\nlong double negbin_log_likelihood(const vector<double>& samples, long double r, long double p);\nlong double poisson_log_likelihood(const vector<double>& samples, long double lambda);\n\nnamespace bser = boost::serialization;\n\nclass Abundance\n{\npublic:\n\tvirtual ~Abundance() {}\n\t\n\t// Status of the numerical calculation performed on this object.  Safe to\n\t// do testing only if status == NUMERIC_OK\n\tvirtual AbundanceStatus status() const = 0;\n\tvirtual void status(AbundanceStatus s) = 0;\n\t\n\t// Fragments Per Kilbase of transcript per Million fragments mapped\n\tvirtual double\t\t\t\tFPKM() const = 0;\n    virtual void\t\t\t\tFPKM(double fpkm) = 0;\n\tvirtual double\t\t\t\tFPKM_variance() const = 0;\n\tvirtual void\t\t\t\tFPKM_variance(double v) = 0;\n\t\n\tvirtual ConfidenceInterval\tFPKM_conf() const = 0;\n\tvirtual void FPKM_conf(const ConfidenceInterval& cf) = 0;\n\t\n\t// gamma is a fixed property of each transcript or transcript group.  It's\n\t// the probability that one would draw a fragment from this object, scaled\n\t// to an arbitrary locus' worth of fragments.\n\tvirtual double\t\t\tgamma() const = 0;\n\tvirtual void\t\t\tgamma(double g) = 0;\n\t\n\t// Kappa is only really meaningful when this Abundance record is part of a\n\t// group - it's the relative abundance of this object within the larger\n\t// group.\n\tvirtual double\t\t\tkappa() const\t= 0;\n\tvirtual void\t\t\tkappa(double k)\t= 0;\n\t\n    // This tracks the final modeled variance in the assigned counts.\n\tvirtual double\t\t\tnum_fragments() const = 0;\n\tvirtual void\t\t\tnum_fragments(double nf) = 0;\n    \n    // This tracks the final modeled variance in the assigned counts.\n    virtual double num_fragment_var() const\t= 0;\n\tvirtual void num_fragment_var(double nfv) = 0;\n    \n    virtual CountPerReplicateTable num_fragments_by_replicate() const = 0;\n    virtual void            num_fragments_by_replicate(CountPerReplicateTable& cpr) = 0;\n    \n    virtual FPKMPerReplicateTable FPKM_by_replicate() const = 0;\n    virtual void            FPKM_by_replicate(CountPerReplicateTable& cpr) = 0;\n    \n    virtual StatusPerReplicateTable status_by_replicate() const = 0;\n    virtual void status_by_replicate(StatusPerReplicateTable& fpr) = 0;\n    \n    // This tracks the fitted variance from the overdispersion model,\n    // and does not include the fragment assignment uncertainty.\n    virtual double          mass_variance() const = 0;\n\tvirtual void            mass_variance(double mv) = 0;\n    \n    // This tracks the fragment assignment uncertainty,\n    // and does not include the overdispersion.\n    virtual double          num_fragment_uncertainty_var() const = 0;\n\tvirtual void            num_fragment_uncertainty_var(double mv) = 0;\n    \n\tvirtual double\t\t\teffective_length() const= 0;\n\tvirtual void\t\t\teffective_length(double el) = 0;\n    \n\tvirtual const vector<double>*\tcond_probs() const\t\t{ return NULL; }\n\tvirtual void\t\t\t\t\tcond_probs(vector<double>* cp) = 0;\n\t\n\t// The structural information for the object, if defined.\n\tvirtual boost::shared_ptr<Scaffold> transfrag() const\t\t{ return boost::shared_ptr<Scaffold>(); }\n\t\n    virtual const vector<double>& fpkm_samples() const = 0;\n    virtual void  fpkm_samples(const vector<double>& s) = 0;\n    \n\t\n\tvirtual set<string>\t\tgene_id() const = 0;\n\tvirtual set<string>\t\tgene_name() const = 0;\n\tvirtual set<string>\t\ttss_id() const = 0;\n\tvirtual set<string>\t\tprotein_id() const = 0;\n\t\n\tvirtual const string&\tdescription() const = 0;\n\tvirtual void\t\t\tdescription(const string& d) = 0;\n\t\n\tvirtual const string&\tlocus_tag() const = 0;\n\tvirtual void\t\t\tlocus_tag(const string& L) = 0;\n\t\n\tvirtual const string&\treference_tag() const = 0;\n\tvirtual void\t\t\treference_tag(const string& r) = 0;\n    \n    template<class Archive>\n    void serialize(Archive & ar, const unsigned int file_version)\n    {\n        \n    }\n    \n    virtual void clear_non_serialized_data() = 0;\n};\n\nBOOST_SERIALIZATION_ASSUME_ABSTRACT(Abundance);\n\nclass TranscriptAbundance : public Abundance\n{\npublic:\n\t\n\tTranscriptAbundance() : \n\t\t_status(NUMERIC_OK), \n\t\t_transfrag(boost::shared_ptr<Scaffold>()), \n\t\t_FPKM(0), \n\t\t_FPKM_variance(0),\n\t\t_gamma(0), \n\t\t_kappa(1.0), \n\t\t_num_fragments(0),\n        _num_fragment_var(0),\n        _num_fragment_uncertainty_var(0),\n\t\t_eff_len(0),\n\t\t_cond_probs(NULL),\n        _sample_mass_variance(0.0){}\n\t\n\t~TranscriptAbundance()\n\t{\n\t\tif (_cond_probs != NULL)\n\t\t{\n\t\t\tdelete _cond_probs;\n\t\t\t_cond_probs = NULL;\n\t\t}\n\t}\n\t\n\tAbundanceStatus status() const\t\t\t{ return _status; }\n\tvoid status(AbundanceStatus s)\t\t\t{ _status = s; }\n\t\n\tdouble FPKM() const\t\t\t\t\t\t{ return _FPKM; }\n    void FPKM(double fpkm)                  \n\t{ \n\t\t_FPKM = fpkm;\n        if (_transfrag)\n            _transfrag->fpkm(fpkm);\n\t}\n\tdouble FPKM_variance() const\t\t\t{ return _FPKM_variance; }\n\tvoid   FPKM_variance(double v);\t\t\t\n\t\n\tConfidenceInterval\tFPKM_conf() const   { return _FPKM_conf; }\n\tvoid FPKM_conf(const ConfidenceInterval& cf) { _FPKM_conf = cf; }\n\t\n\tdouble gamma() const\t\t\t\t\t{ return _gamma; }\n\tvoid gamma(double g)\t\t\t\t\t{ assert(!isnan(g)); _gamma = g; };\n\t\n\tdouble kappa() const\t\t\t\t\t{ return _kappa; }\n\tvoid kappa(double k)\t\t\t\t\t{ _kappa = k; }\n\t\n    // This returns the estimated number of fragments\n\tdouble num_fragments() const\t\t\t{ return _num_fragments; }\n\tvoid num_fragments(double nf)\n    {\n        assert (!isnan(nf));\n        _num_fragments = nf;\n        if (_transfrag)\n            _transfrag->num_fragments(nf);\n    }\n    \n    // This tracks the final modeled variance in the assigned counts.\n    double num_fragment_var() const\t\t\t{ return _num_fragment_var; }\n\tvoid num_fragment_var(double nfv)\t\t{ assert (!isnan(nfv)); _num_fragment_var = nfv; }\n    \n    // This tracks the fragment assignment uncertainty,\n    // and does not include the overdispersion.\n    double          num_fragment_uncertainty_var() const { return _num_fragment_uncertainty_var; }\n\tvoid            num_fragment_uncertainty_var(double nfv) { assert (!isnan(nfv)); _num_fragment_uncertainty_var = nfv; }\n    \n    CountPerReplicateTable num_fragments_by_replicate() const { return _num_fragments_per_replicate; }\n    void num_fragments_by_replicate(CountPerReplicateTable& cpr) { _num_fragments_per_replicate = cpr; }\n    \n    FPKMPerReplicateTable FPKM_by_replicate() const { return _fpkm_per_replicate; }\n    void FPKM_by_replicate(FPKMPerReplicateTable& fpr) { _fpkm_per_replicate = fpr; }\n    \n    StatusPerReplicateTable status_by_replicate() const { return _status_per_replicate; }\n    void status_by_replicate(StatusPerReplicateTable& fpr) { _status_per_replicate = fpr; }\n    \n    double mass_variance() const\t\t\t{ return _sample_mass_variance; }\n\tvoid mass_variance(double mv)\t\t\t{ _sample_mass_variance = mv; }\n\t\n\tvoid transfrag(boost::shared_ptr<Scaffold> tf)\t\t{ _transfrag = tf; }\n\tboost::shared_ptr<Scaffold> transfrag() const\t\t{ return _transfrag; }\n\t\n\tdouble effective_length() const\t\t\t{ return _eff_len; }\n\tvoid effective_length(double el)\t\t{ _eff_len = el; }\n\t\n\tconst vector<double>* cond_probs() const\t{ return _cond_probs; }\n\tvoid cond_probs(vector<double>* cp) \t\n\t{ \n\t\tif(_cond_probs != NULL) { delete _cond_probs; };\n\t\t_cond_probs = cp;\n\t}\n\t\n    const vector<double>& fpkm_samples() const { return _fpkm_samples; }\n    void  fpkm_samples(const vector<double>& s) { _fpkm_samples = s; }\n\t\n\tset<string> gene_id() const\n\t{\n\t\tif (_transfrag)\n\t\t{\n\t\t\tset<string> s;\n\t\t\ts.insert(_transfrag->annotated_gene_id());\n\t\t\treturn s;\n\t\t}\n\t\telse \n\t\t{\n\t\t\tassert (false);\n\t\t\treturn set<string>();\n\t\t}\n\t}\n\t\n\tset<string> gene_name() const\t\n\t{\n\t\tif (_transfrag)\n\t\t{\n\t\t\tset<string> s;\n\t\t\ts.insert(_transfrag->annotated_gene_name());\n\t\t\treturn s;\n\t\t}\n\t\telse \n\t\t{\n\t\t\tassert (false);\n\t\t\treturn set<string>();\n\t\t}\n\t}\n\t\n\tset<string> tss_id() const\t\n\t{\n\t\tif (_transfrag)\n\t\t{\n\t\t\tset<string> s;\n\t\t\ts.insert(_transfrag->annotated_tss_id());\n\t\t\treturn s;\n\t\t}\n\t\telse \n\t\t{\n\t\t\tassert (false);\n\t\t\treturn set<string>();\n\t\t}\n\t}\n\t\n\tset<string> protein_id() const\t\n\t{\n\t\tif (_transfrag)\n\t\t{\n\t\t\tset<string> s;\n\t\t\ts.insert(_transfrag->annotated_protein_id());\n\t\t\treturn s;\n\t\t}\n\t\telse \n\t\t{\n\t\t\tassert (false);\n\t\t\treturn set<string>();\n\t\t}\n\t}\n\t\n\tvirtual const string&\tdescription() const\t{ return _description; }\n\tvirtual void\t\t\tdescription(const string& d) { _description = d; }\n\t\n\tvirtual const string&\tlocus_tag() const { return _locus_tag; }\n\tvirtual void\t\t\tlocus_tag(const string& L) { _locus_tag = L; }\n\t\n\tvirtual const string&\treference_tag() const { return _ref_tag; }\n\tvirtual void\t\t\treference_tag(const string& r) { _ref_tag = r; } \n    \n\tvoid clear_non_serialized_data();\nprivate:\n\t\n    friend std::ostream & operator<<(std::ostream &os, const TranscriptAbundance &gp);\n    friend class boost::serialization::access;\n    \n    template<class Archive>\n    void serialize(Archive & ar, const unsigned int /* file_version */){\n        \n        ar & _status;\n        //ar & _transfrag;\n        ar & _FPKM;\n        ar & _FPKM_conf;\n        ar & _gamma;\n        ar & _kappa;\n        ar & _num_fragments;\n        ar & _num_fragment_var;\n        ar & _num_fragment_uncertainty_var;\n        ar & _eff_len;\n        //ar & _cond_probs;\n        ar & _description;\n        ar & _locus_tag;\n        ar & _ref_tag;\n        ar & _sample_mass_variance;\n        ar & _num_fragments_per_replicate;\n        ar & _fpkm_per_replicate;\n        ar & _status_per_replicate;\n    }\n    \n\tvoid calculate_FPKM_err_bar(double variance);\n\t\n\tAbundanceStatus _status;\n\tboost::shared_ptr<Scaffold> _transfrag;\n\tdouble _FPKM;\n\tdouble _FPKM_variance;\n\tConfidenceInterval _FPKM_conf;\n\tdouble _gamma;\n\tdouble _kappa;\n\tdouble _num_fragments;\n    double _num_fragment_var;\n    double _num_fragment_uncertainty_var;\n\tdouble _eff_len;\n\tvector<double>* _cond_probs;\n    \n    vector<double> _fpkm_samples;\n\t\n\tstring _description;\n\tstring _locus_tag;\n\tstring _ref_tag;\n\t\n    long double _sample_mass_variance;\n    \n    CountPerReplicateTable _num_fragments_per_replicate;\n    FPKMPerReplicateTable _fpkm_per_replicate;\n    StatusPerReplicateTable _status_per_replicate;\n};\n\n//BOOST_CLASS_EXPORT_GUID(TranscriptAbundance, \"TranscriptAbundance\");\n//BOOST_SERIALIZATION_boost::shared_ptr(TranscriptAbundance)\n\nclass AbundanceGroup : public Abundance\n{\npublic:\n\tAbundanceGroup() :\n        _kappa(1.0),\n        _FPKM_variance(0.0),\n        _salient_frags(0.0),\n        _total_frags(0.0) {}\n\t\n\tAbundanceGroup(const vector<boost::shared_ptr<Abundance> >& abundances) :\n\t\t_abundances(abundances), \n        _iterated_exp_count_covariance(ublas::zero_matrix<double>(abundances.size(), abundances.size())), \n        _count_covariance(ublas::zero_matrix<double>(abundances.size(), abundances.size())), \n        _fpkm_covariance(ublas::zero_matrix<double>(abundances.size(), abundances.size())), \n\t\t_gamma_covariance(ublas::zero_matrix<double>(abundances.size(), abundances.size())), \n\t\t_kappa_covariance(ublas::zero_matrix<double>(abundances.size(), abundances.size())),\n\t\t_kappa(1.0),\n\t\t_FPKM_variance(0.0),\n        _salient_frags(0.0),\n        _total_frags(0.0) {}\n    \n\tAbundanceGroup(const vector<boost::shared_ptr<Abundance> >& abundances,\n\t\t\t\t   const ublas::matrix<double>& gamma_covariance,\n                   const ublas::matrix<double>& iterated_exp_count_covariance,\n                   const ublas::matrix<double>& count_covariance,\n                   const ublas::matrix<double>& fpkm_covariance,\n                   const std::set<boost::shared_ptr<ReadGroupProperties const > >& rg_props);\n\t\n\tAbundanceStatus status() const;\n\tvoid status(AbundanceStatus s)\t\t\t{ }\n\tbool has_member_with_status(AbundanceStatus member_status) const;\n    \n\tdouble FPKM() const;\n    void   FPKM(double fpkm)                { }\n    \n\tdouble FPKM_variance() const\t\t\t{ return _FPKM_variance; }\n\tvoid   FPKM_variance(double v)\t\t\t{ }\n\t\n\tConfidenceInterval\tFPKM_conf() const   { return _FPKM_conf; }\n\n\t\n\tdouble gamma() const;\n\tvoid gamma(double g)\t\t\t\t\t{  };\n\t\n\tdouble kappa() const\t\t\t\t\t{ return _kappa; }\n\tvoid kappa(double k)\t\t\t\t\t{ _kappa = k; }\n\t\n\tdouble num_fragments() const;\n\tvoid num_fragments(double nf)\t\t\t{  }\n    \n    // This tracks the final modeled variance in the assigned counts.\n    double num_fragment_var() const;\n\tvoid num_fragment_var(double nfv)\t\t{  }\n    \n    // This tracks the uncertainty in the assigned counts\n    double num_fragment_uncertainty_var() const;\n\tvoid num_fragment_uncertainty_var(double nfv)\t\t{  }\n    \n    CountPerReplicateTable num_fragments_by_replicate() const;\n    void num_fragments_by_replicate(CountPerReplicateTable& cpr) { }\n    \n    FPKMPerReplicateTable FPKM_by_replicate() const;\n    void FPKM_by_replicate(FPKMPerReplicateTable& fpr) { }\n    \n    StatusPerReplicateTable status_by_replicate() const;\n    void status_by_replicate(StatusPerReplicateTable& fpr) { }\n    \n    double mass_variance() const;\n\tvoid mass_variance(double mf)\t{  }\n\t\n\tset<string> gene_id() const;\t\n\tset<string> gene_name() const;\n\tset<string> tss_id() const;\n\tset<string> protein_id() const;\n\t\n\tvirtual const string&\tdescription() const\t{ return _description; }\n\tvirtual void\t\t\tdescription(const string& d) { _description = d; }\n\t\n\tvirtual const string&\tlocus_tag() const;\n\tvirtual void\t\t\tlocus_tag(const string& L) { }\n\t\n\tvirtual const string&\treference_tag() const;\n\tvirtual void\t\t\treference_tag(const string& r) { } \n\t\n\tdouble effective_length() const;\n\t\n\t//DUMMY FUNCTIONS\n\tvoid effective_length(double ef) {}\n\tvoid cond_probs(vector<double>* cp) {}\n\n\tvoid filter_group(const vector<bool>& to_keep,\n\t\t\t\t\t  AbundanceGroup& filtered_group) const;\n\t\n\tvoid get_transfrags(vector<boost::shared_ptr<Abundance> >& transfrags) const;\n\t\t\t\t\t\t\t\t\t\t\t\t \n\tvector<boost::shared_ptr<Abundance> >& abundances() { return _abundances; }\n\tconst vector<boost::shared_ptr<Abundance> >& abundances() const { return _abundances; }\n\t\n\tconst ublas::matrix<double>& gamma_cov() const { return _gamma_covariance; }\n    \n    const ublas::matrix<double>& iterated_count_cov() const { return _iterated_exp_count_covariance; }\n    \n    const ublas::matrix<double>& count_cov() const { return _count_covariance; }\n    \n\tconst ublas::matrix<double>& kappa_cov() const { return _kappa_covariance; }\n    \n    const ublas::matrix<double>& fpkm_cov() const { return _fpkm_covariance; }\n\t\n\tconst vector<Eigen::VectorXd>& assigned_counts() const { return _assigned_count_samples; }\n    \n    const vector<double>& fpkm_samples() const { return _fpkm_samples; }\n    void  fpkm_samples(const vector<double>& s) { _fpkm_samples = s; }\n    void clear_fpkm_samples() {\n        _fpkm_samples.clear();\n        std::vector<double>().swap(_fpkm_samples);\n        for (size_t i = 0; i < _member_fpkm_samples.size(); ++i)\n        {\n            _member_fpkm_samples.clear();\n            std::vector<Eigen::VectorXd>().swap(_member_fpkm_samples);\n        }\n    }\n    \n    const vector<Eigen::VectorXd>& member_fpkm_samples() const { return _member_fpkm_samples; }\n    void  member_fpkm_samples(const vector<Eigen::VectorXd>& s) { _member_fpkm_samples = s; }\n    \n\tvoid calculate_abundance(const vector<MateHit>& alignments,\n                             bool perform_collapse = true,\n                             bool calculate_variance = true);\n\t\n    double salient_frags() const { return _salient_frags; }\n    void salient_frags(double nf) { _salient_frags = nf; }\n    \n    double total_frags() const { return _total_frags; }\n    void total_frags(double nf) { _total_frags = nf; }\n    \n    const std::set<boost::shared_ptr<ReadGroupProperties const> >& rg_props() const { return _read_group_props; }\n    \n    void init_rg_props(const std::set<boost::shared_ptr<ReadGroupProperties const> >& rg) \n    {\n        _read_group_props = rg;\n        _count_per_replicate.clear();\n        for ( std::set<boost::shared_ptr<ReadGroupProperties const> >::const_iterator itr = rg.begin();\n             itr != rg.end();\n             ++itr)\n        {\n            _count_per_replicate[*itr] = 0;\n        }\n    }\n    \n    void fit_gamma_distributions();\n    \n    void clear_non_serialized_data();\n    \n    void aggregate_replicate_abundances(const std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> >& ab_group_per_replicate);\n    \n    void calculate_abundance_group_variance(const vector<boost::shared_ptr<Abundance> >& transcripts,\n                                            const std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> >& ab_group_per_replicate);\n\n    void collect_per_replicate_mass(std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> >& ab_group_per_replicate)\n    {\n        _count_per_replicate.clear();\n        for (std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<const AbundanceGroup> >::const_iterator itr = ab_group_per_replicate.begin();\n             itr != ab_group_per_replicate.end(); ++itr)\n        {\n            _count_per_replicate[itr->first] = itr->second->num_fragments();\n        }\n    }\n    \n    static void apply_normalization_to_abundances(const map<boost::shared_ptr<const ReadGroupProperties>, boost::shared_ptr<const AbundanceGroup> >& unnormalized_ab_group_per_replicate,\n                                                  map<boost::shared_ptr<const ReadGroupProperties>, boost::shared_ptr<AbundanceGroup> >& normalized_ab_group_per_replicate);\n    \nprivate:\n    \n    void calculate_abundance_for_replicate(const vector<MateHit>& alignments, bool perform_collapse);\n    \n    \n\t\n\tvoid FPKM_conf(const ConfidenceInterval& cf)  { _FPKM_conf = cf; }\n\t\n\tbool calculate_gammas(const vector<MateHit>& nr_alignments, \n                          const vector<double>& log_conv_factors,\n\t\t\t\t\t\t  const vector<boost::shared_ptr<Abundance> >& transcripts,\n\t\t\t\t\t\t  const vector<boost::shared_ptr<Abundance> >& mapped_transcripts);\n\tvoid calculate_FPKM_covariance();\n\n    void calculate_conf_intervals();\n\tvoid calculate_locus_scaled_mass_and_variance(const vector<boost::shared_ptr<Abundance> >& transcripts);\n   \n    \n    AbundanceStatus calculate_per_replicate_abundances(vector<boost::shared_ptr<Abundance> >& transcripts,\n                                                       const std::map<boost::shared_ptr<ReadGroupProperties const >, vector<MateHit> >& alignments_per_read_group,\n                                                       std::map<boost::shared_ptr<ReadGroupProperties const >, boost::shared_ptr<AbundanceGroup> >& ab_group_per_replicate,\n                                                       bool perform_collapse = true);\n    \n        \n\tvoid calculate_kappas();\n    \n    \n\tvoid update_multi_reads(const vector<MateHit>& alignments, vector<boost::shared_ptr<Abundance> > transcripts);\n    \n    void collect_per_replicate_mass(const vector<MateHit>& alignments,\n                                    vector<boost::shared_ptr<Abundance> >& transcripts);\n    \n    void generate_fpkm_samples();\n    \n    friend std::ostream & operator<<(std::ostream &os, const AbundanceGroup &gp);\n    friend class boost::serialization::access;\n    \n    template<class Archive>\n    void save(Archive & ar, const unsigned int version) const\n    {\n        //ar & _abundances;\n        vector<TranscriptAbundance*> tmp;\n        BOOST_FOREACH(boost::shared_ptr<Abundance> ab, _abundances)\n        {\n            tmp.push_back((TranscriptAbundance*)&(*ab));\n        }\n        ar & tmp;\n        ar & _iterated_exp_count_covariance;\n        ar & _count_covariance;\n        ar & _fpkm_covariance;\n        ar & _gamma_covariance;\n        \n        //ar & _FPKM_conf;\n        //ar & _kappa_covariance;\n        //ar & _assign_probs;\n        \n        ar & _kappa;\n        ar & _FPKM_variance;\n        ar & _description;\n        //ar & _salient_frags;\n        ar & _total_frags;\n        //ar & _fpkm_samples; // don't save the samples\n        ar & _read_group_props;\n        //ar & _member_fpkm_samples // don't save the member samples either\n        ar & _count_per_replicate;\n\n    }\n    template<class Archive>\n    void load(Archive & ar, const unsigned int version)\n    {\n\n        vector<TranscriptAbundance*> tmp;\n        ar & tmp;\n        BOOST_FOREACH(TranscriptAbundance* ab, tmp)\n        {\n            _abundances.push_back(boost::shared_ptr<Abundance>(ab));\n        }\n        \n        //ar & _abundances;\n        \n        ar & _iterated_exp_count_covariance;\n        ar & _count_covariance;\n        ar & _fpkm_covariance;\n        ar & _gamma_covariance;\n        \n        //ar & _FPKM_conf;\n        //ar & _kappa_covariance;\n        //ar & _assign_probs;\n        \n        ar & _kappa;\n        ar & _FPKM_variance;\n        ar & _description;\n        //ar & _salient_frags;\n        ar & _total_frags;\n        //ar & _fpkm_samples; // don't save the samples\n        ar & _read_group_props;\n        //ar & _member_fpkm_samples // don't save the member samples either\n        ar & _count_per_replicate;\n    }\n    BOOST_SERIALIZATION_SPLIT_MEMBER()\n    \n    //void collect_read_group_props();\n\t\n\tvector<boost::shared_ptr<Abundance> > _abundances;\n\t\n    // _iterated_exp_count_covariance is the ITERATED EXPECTATION count covariance matrix.  It's not the \n    // estimated count covariance matrix (i.e. it doesn't include biological variability from\n    // the fitted model.\n    ublas::matrix<double> _iterated_exp_count_covariance;\n    \n    // _count_covariance is the final count covariance matrix.  It's includes our estimates\n    // of transcript-level biological variability on counts\n    ublas::matrix<double> _count_covariance;\n    \n    ublas::matrix<double> _fpkm_covariance;\n\tublas::matrix<double> _gamma_covariance;\n    \n\tConfidenceInterval _FPKM_conf;\n\t\n\tublas::matrix<double> _kappa_covariance;\n    ublas::matrix<double> _assign_probs;\n    \n\tdouble _kappa;\n\tdouble _FPKM_variance;\n\tstring _description;\n    double _salient_frags;\n    double _total_frags;\n    \n    vector<double> _fpkm_samples;\n    vector<Eigen::VectorXd> _member_fpkm_samples;\n    \n    std::set<boost::shared_ptr<ReadGroupProperties const > > _read_group_props;\n    vector<Eigen::VectorXd> _assigned_count_samples;\n    \n    map<boost::shared_ptr<ReadGroupProperties const>, double> _count_per_replicate;\n    //std::map<boost::shared_ptr<ReadGroupProperties const >, ublas::vector<double> > _mles_for_read_groups;\n};\n\nstruct SampleAbundances\n{\n    string locus_tag;\n\tAbundanceGroup transcripts;\n\tvector<AbundanceGroup> primary_transcripts;\n\tvector<AbundanceGroup> gene_primary_transcripts;\n\tvector<AbundanceGroup> cds;\n\tvector<AbundanceGroup> gene_cds;\n\tvector<AbundanceGroup> genes;\n\tdouble cluster_mass;\n};\n\nvoid compute_cond_probs_and_effective_lengths(const vector<MateHit>& alignments, \n                                              vector<boost::shared_ptr<Abundance> >& transcripts,\n                                              vector<boost::shared_ptr<Abundance> >& mapped_transcripts);\n\nvoid compute_compatibilities(const vector<boost::shared_ptr<Abundance> >& transcripts,\n\t\t\t\t\t\t\t const vector<MateHit>& alignments,\n\t\t\t\t\t\t\t vector<vector<char> >& compatibilities);\n\nvoid get_alignments_from_scaffolds(const vector<boost::shared_ptr<Abundance> >& abundances,\n\t\t\t\t\t\t\t\t   vector<MateHit>& alignments);\n\nAbundanceStatus empirical_replicate_gammas(vector<boost::shared_ptr<Abundance> >& transcripts,\n                                           const vector<MateHit>& nr_alignments,\n                                           const vector<double>& log_conv_factors,\n                                           ublas::vector<double>& gamma_map_estimate,\n                                           ublas::matrix<double>& gamma_map_covariance,\n                                           std::map<boost::shared_ptr<ReadGroupProperties const >, ublas::vector<double> >& mles_for_read_groups);\n\nAbundanceStatus gamma_mle(const vector<boost::shared_ptr<Abundance> >& transcripts,\n                          const vector<MateHit>& nr_alignments,\n                          const vector<double>& log_conv_factors,\n                          vector<double>& gammas,\n                          bool check_identifiability = true);\n\ndouble compute_doc(int bundle_origin, \n\t\t\t\t   const vector<Scaffold>& scaffolds,\n\t\t\t\t   vector<float>& depth_of_coverage,\n\t\t\t\t   map<pair<int, int>, float>& intron_depth_of_coverage,\n\t\t\t\t   bool exclude_intra_intron=false,\n\t\t\t\t   vector<float>* intronic_cov=NULL,\n\t\t\t\t   vector<int>* scaff_intronic_status=NULL);\n\ndouble major_isoform_intron_doc(map<pair<int, int>, float>& intron_doc);\n\nvoid record_doc_for_scaffolds(int bundle_origin, \n\t\t\t\t\t\t\t  const std::vector<Scaffold>& hits,\n\t\t\t\t\t\t\t  const std::vector<float>& depth_of_coverage,\n\t\t\t\t\t\t\t  const std::map<std::pair<int, int>, float>& intron_depth_of_coverage,\n\t\t\t\t\t\t\t  std::vector<double>& scaff_doc);\n\nvoid record_doc_for_scaffolds(int bundle_origin, \n\t\t\t\t\t\t\t  const std::vector<Scaffold>& hits,\n\t\t\t\t\t\t\t  const std::vector<float>& depth_of_coverage,\n\t\t\t\t\t\t\t  std::vector<double>& scaff_doc);\n\nvoid record_min_doc_for_scaffolds(int bundle_origin, \n\t\t\t\t\t\t\t\t  const std::vector<Scaffold>& hits,\n\t\t\t\t\t\t\t\t  const std::vector<float>& depth_of_coverage,\n\t\t\t\t\t\t\t\t  const std::map<std::pair<int, int>, float>& intron_depth_of_coverage,\n\t\t\t\t\t\t\t\t  std::vector<double>& scaff_doc);\n\n\ndouble get_intron_doc(const Scaffold& s,\n\t\t\t\t\t  const map<pair<int, int>, float>& intron_depth_of_coverage);\n\ndouble get_scaffold_doc(int bundle_origin, \n\t\t\t\t\t\tconst Scaffold& s,\n\t\t\t\t\t\tconst vector<float>& depth_of_coverage);\n\ndouble get_scaffold_min_doc(int bundle_origin, \n\t\t\t\t\t\t\tconst Scaffold& s,\n\t\t\t\t\t\t\tconst vector<float>& depth_of_coverage);\n\nAbundanceStatus calculate_inverse_fisher(const vector<boost::shared_ptr<Abundance> >& transcripts,\n                                         const vector<MateHit>& alignments,\n                                         const ublas::vector<double>& gamma_mean,\n                                         ublas::matrix<double>& inverse_fisher);\n\nvoid calculate_assignment_probs(const Eigen::VectorXd& alignment_multiplicities, \n                                const Eigen::MatrixXd& transcript_cond_probs,\n                                const Eigen::VectorXd& proposed_gammas,\n                                Eigen::MatrixXd& assignment_probs);\n\nvoid calculate_average_assignment_probs(const Eigen::VectorXd& alignment_multiplicities, \n                                        const Eigen::MatrixXd& transcript_cond_probs,\n                                        const Eigen::VectorXd& proposed_gammas,\n                                        Eigen::MatrixXd& assignment_probs);\n\nvoid calculate_iterated_exp_count_covariance(const vector<double>& gammas,\n                                             const vector<MateHit>& nr_alignments,\n                                             const vector<boost::shared_ptr<Abundance> >& transcripts,\n                                             ublas::matrix<double>& count_covariance);\n\nbool simulate_count_covariance(const vector<double>& num_fragments,\n                               const vector<double>& frag_variances,\n                               const ublas::matrix<double>& iterated_exp_count_covariances,\n                               const vector<boost::shared_ptr<Abundance> >& transcripts,\n                               ublas::matrix<double>& count_covariances,\n                               vector<Eigen::VectorXd>& assigned_count_samples,\n                               vector<ublas::vector<double> >* gamma_samples);\n\nvoid sample_abundance_worker(const string& locus_tag,\n                             const set<boost::shared_ptr<ReadGroupProperties const> >& rg_props,\n                             SampleAbundances& sample,\n                             boost::shared_ptr<HitBundle> sample_bundle,\n                             bool perform_cds_analysis,\n                             bool perform_tss_analysis,\n                             bool calculate_variance);\n\nvoid merge_precomputed_expression_worker(const string& locus_tag,\n                                         const vector<boost::shared_ptr<PrecomputedExpressionBundleFactory> >& expression_factories,\n                                         SampleAbundances& sample,\n                                         boost::shared_ptr<HitBundle> sample_bundle,\n                                         bool perform_cds_analysis,\n                                         bool perform_tss_analysis,\n                                         bool calculate_variance);\n#endif\n"
  },
  {
    "path": "src/assemble.cpp",
    "content": "/*\n *  assemble.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/23/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <map>\n#include <list>\n#include <vector>\n#include <iostream>\n\n#include <lemon/topology.h>\n\n//#include <lemon/graph_utils.h>\n#include <lemon/bipartite_matching.h>\n\n#include <boost/ref.hpp>\n// DON'T move this, or mystery compiler errors will result. Affects gcc >= 4.1\n#include <boost/graph/vector_as_graph.hpp>\n\n#include <boost/graph/adjacency_list.hpp>\n\n#include <boost/graph/graph_traits.hpp>\n//#include <boost/numeric/ublas/io.hpp>\n\n#include <boost/version.hpp>\n\n#if (BOOST_VERSION < 103800)\n#include <boost/vector_property_map.hpp>\n#else\n#include <boost/property_map/vector_property_map.hpp>\n#endif\n\n#include <boost/math/distributions/normal.hpp> // for normal_distribution\nusing boost::math::normal; // typedef provides default type is double.\n\n#include \"transitive_closure.h\"\n#include \"transitive_reduction.h\"\n\n#include \"common.h\"\n#include \"assemble.h\"\n\n#include \"bundles.h\"\n//#include \"filters.h\"\n//#include \"genes.h\"\n#include \"scaffolds.h\"\n#include \"clustering.h\"\n#include \"matching_merge.h\"\n#include \"graph_optimize.h\"\n\nusing namespace boost;\nusing namespace std;\n\nbool mate_graphs(const HitBundle& bundle, BundleStats* stats);\n\ntypedef lemon::SmartBpUGraph ReachGraph;\n\nlong long weight_of_merge(Scaffold& lhs, \n\t\t\t\t\t\t  Scaffold& rhs, \n\t\t\t\t\t\t  double source_psi,\n\t\t\t\t\t\t  double target_psi)\n{\n\t//double expected_cov_diff = max(1.0, 0.1 * (source_doc + target_doc));\n\t//normal cov_norm(0, expected_cov_diff);\n\t\n\tnormal cov_test_norm(0, 1.0);\n\n\tdouble score = 0.0;\n\t\n\t// HACK: This early breakout prevents spliced reads that cross exactly one\n\t// intron from being matched up if they both cross the same intron.\n\t// Otherwise, we get phasing problems, as introns aren't matched up long \n\t// distance.  Ugh..\n\tif (Scaffold::overlap_in_genome(lhs, rhs, 0))\n\t{\n\t\tbool lh_intron = lhs.has_intron();\n\t\tbool rh_intron = rhs.has_intron();\n\t\t\n\t\tif (lh_intron && rh_intron)\n\t\t{\n\t\t\tvector<pair<int, int> > lh_gaps = lhs.gaps();\n\t\t\tvector<pair<int, int> > rh_gaps = rhs.gaps();\n\t\t\tif (lh_gaps.size() == 1 && lh_gaps == rh_gaps)\n\t\t\t\treturn 999999999;\n\t\t}\n\t}\n\n\tif (source_psi > 0 && target_psi > 0 )\n\t{\n\t\tdouble test_stat = log(1.0 - abs(source_psi - target_psi));\n\t\tscore = test_stat;\n\t\tassert (score <= 0.0);\n\t}\n\telse\n\t{\n\t\treturn 999999999;\n\t}\n\t\n\tassert (score <= 0.0);\n\tif (score >= -1e-6)\n\t\tscore = -1e-6;\n\tint weight = (int)(score * -1e6);\n\treturn weight;\n}\n\n\ntypedef map<DAGNode, pair<int, int> > DagToBp;\nvoid create_reachability_bp_graph(DAG& dag,\n                                  ReachGraph& reach_graph,\n                                  vector<ReachGraph::BNode> b_to_a,\n                                  DagToBp& dag_to_bp,\n                                  const adjacency_list<>& TC,\n                                  const vector<bool>& scaffold_mask)\n{\t\n\t//typedef graph_traits<DAG>::vertex_descriptor Vertex;\n\tHitsForNodeMap hits_for_node = get(vertex_name, dag);\n\t\n\t//fprintf (stdout, \"\\tclosure edges:\\t\\t\\t\\%d\\n\", num_edges(TC));\n\tgraph_traits < adjacency_list<> >::vertex_iterator v, vend;\n\t\n\tb_to_a.resize(num_vertices(TC));\n\t\n\tfor (tie(v, vend) = vertices(TC); v != vend; ++v)\n\t{\n\t\tDagToBp::iterator itr = dag_to_bp.find(*v);\n\t\tif (itr == dag_to_bp.end())\n\t\t{\n\t\t\tReachGraph::ANode A = reach_graph.addANode();\n\t\t\tint a = reach_graph.aNodeId(A);\n\t\t\t\n\t\t\tReachGraph::BNode B = reach_graph.addBNode();\n\t\t\tint b = reach_graph.bNodeId(B);\n\t\t\tb_to_a[b] = A;\n\t\t\tdag_to_bp[*v] = make_pair(a, b);\n\t\t\t\n\t\t}\n\t}\t\t\n\t\n\treach_graph.reserveEdge(num_edges(TC));\n\treach_graph.reserveANode(num_vertices(TC));\n\treach_graph.reserveBNode(num_vertices(TC));\n\t\n\tgraph_traits < adjacency_list<> >::edge_iterator i, end;\n\tfor (tie(i, end) = edges(TC); i != end; ++i)\n\t{\n\t\tint a_id = -1;\n\t\tint b_id = -1;\n\t\tDAGNode s = source(*i, TC);\n\t\tDAGNode t = target(*i, TC);\n\n\t\tDagToBp::iterator itr = dag_to_bp.find(s);\n\t\tif (itr == dag_to_bp.end())\n\t\t{\n\t\t\tassert (false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ta_id = itr->second.first;\n\t\t}\n\t\t\n\t\titr = dag_to_bp.find(t);\n\t\t\n\t\tif (itr == dag_to_bp.end())\n\t\t{\n\t\t\tassert(false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tb_id = itr->second.second;\n\t\t}\n\t\t\n\t\tif (in_degree(s, dag) == 0  /* virtual \"source\"? */|| \n            out_degree(t, dag) == 0 /* virtual \"sink\"?*/)\n\t\t\tcontinue;\n\t\t\n\t\tassert (a_id != -1);\n\t\tassert (b_id != -1);\n\t\t\n\t\tReachGraph::ANode a_node = reach_graph.nodeFromANodeId(a_id);\n\t\tReachGraph::BNode b_node = reach_graph.nodeFromBNodeId(b_id);\n\t\tReachGraph::ANode a_for_b = b_to_a[b_id];\n\t\t\n\t\tassert (a_for_b != a_node);\n\t\t\n\t\tif (scaffold_mask[a_id] && \n\t\t\tscaffold_mask[b_id])\n\t\t{\n\t\t\treach_graph.addEdge(a_node, \n\t\t\t\t\t\t\t\tb_node);\n\t\t}\n\t}\n}\n\nvoid add_weights_to_reachability_bp_graph(ReachGraph& bp,\n\t\t\t\t\t\t\t\t\t   const HitsForNodeMap& hits_for_node,\n\t\t\t\t\t\t\t\t\t   const vector<Scaffold>& hits,\n\t\t\t\t\t\t\t\t\t   const vector<Scaffold>& scaffolds,\n\t\t\t\t\t\t\t\t\t   ReachGraph::UEdgeMap<long long>& weights)\n{\n\t// number of reads of reads spliced in to each scaffold\n\tvector<double> spliced_in(scaffolds.size(), 0.0);\n\t\n\t// number spliced in / length of scaffold\n\tvector<double> density(scaffolds.size(), 0.0);\n\t\n\t// number of reads spliced in to scaffold + those that just overlap it\n\t//vector<double> overlapping(scaffolds.size(), 0.0);\n\t\n\tfor (size_t i = 0; i < scaffolds.size(); ++i)\n\t{\n\t\tfor (size_t j = 0; j < hits.size(); ++j)\n\t\t{\n\t\t\tif (!hits[j].is_ref() && scaffolds[i].contains(hits[j]))\n\t\t\t{\n\t\t\t\tif (Scaffold::compatible(scaffolds[i],hits[j]))\n\t\t\t\t{\n\t\t\t\t\tspliced_in[i]++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdensity[i] = spliced_in[i] / scaffolds[i].length();\n\t}\n\t\n\t// percent spliced in = density / (total density of overlapping scaffolds) \n\tvector<double> psi(scaffolds.size(), 0.0);\n\tvector<double> local_density(scaffolds.size(), 0.0);\n\tfor (size_t i = 0; i < scaffolds.size(); ++i)\n\t{\n\t\tdouble total_density = 0.0;\n\t\tint num_overlaps = 0;\n\t\tdouble compatible_density = 0.0;\n\t\tfor (size_t j = 0; j < scaffolds.size(); ++j)\n\t\t{\n\t\t\tif (Scaffold::overlap_in_genome(scaffolds[i],scaffolds[j], 0))\n\t\t\t{\n\t\t\t\ttotal_density += density[j];\n\t\t\t\tnum_overlaps++;\n\t\t\t\tif (Scaffold::compatible(scaffolds[i], scaffolds[j]))\n\t\t\t\t{\n\t\t\t\t\tcompatible_density += density[j];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (total_density)\n\t\t\tpsi[i] = compatible_density / total_density;\n\t\tlocal_density[i] = compatible_density;\n\t}\n\t\n\tfor (ReachGraph::UEdgeIt i(bp); i!=lemon::INVALID; ++i)\n\t{\n\t\tReachGraph::ANode a = bp.source(i);\n\t\tReachGraph::BNode b = bp.target(i);\n\t\tDAGNode a_dag = bp.aNodeId(a);\n\t\tint a_id_for_b = bp.aNodeId(b);\n\t\tReachGraph::ANode a_for_b = bp.nodeFromANodeId(a_id_for_b);\n\t\tassert (a_for_b != lemon::INVALID);\n\t\tDAGNode b_dag = a_id_for_b;\n\t\t\n\t\tScaffold* a_scaff = hits_for_node[a_dag];\n\t\tScaffold* b_scaff = hits_for_node[b_dag];\n\n\t\tsize_t aidx = a_scaff - &scaffolds[0];\n\t\tsize_t bidx = b_scaff - &scaffolds[0];\n\t\t\n\t\tdouble a_psi = psi[aidx];\n\t\t\n\t\tdouble b_psi = psi[bidx];\n\t\t\n\t\t\n\t\t//assert (a_psi != 1.0);\n\t\t//assert (b_psi != 1.0);\n\t\t\n\t\tlong long weight = weight_of_merge(*a_scaff, \n\t\t\t\t\t\t\t\t\t\t   *b_scaff, \n\t\t\t\t\t\t\t\t\t\t   a_psi,\n\t\t\t\t\t\t\t\t\t\t   b_psi);\n\t\t\n\t\tif (weight < 0)\n\t\t\tweight = 10000000;\n        \n\t\t//fprintf(stderr, \"Similarity between %d, %d = %.20lf\\n\", bp.aNodeId(a), a_id_for_b, weight);\n\t\tweights[i] = weight;\n\t}\t\n}\n\nvoid holdout_transitivity_hazards(vector<Scaffold>& hits, \n\t\t\t\t\t\t\t\t  vector<Scaffold>& hazards)\n{\n\tvector<pair<int,int> > introns;\n\tfor (size_t i = 0; i < hits.size(); ++i)\n\t{\n\t\tconst vector<AugmentedCuffOp>& ops = hits[i].augmented_ops();\n\t\tfor (size_t j = 0; j < ops.size(); ++j)\n\t\t{\n\t\t\tconst AugmentedCuffOp& op = ops[j];\n\t\t\tif (op.opcode == CUFF_INTRON)\n\t\t\t\tintrons.push_back(make_pair(op.g_left(), op.g_right()));\n\t\t}\n\t}\n\n\tsort(introns.begin(), introns.end());\n\tvector<pair<int, int> >::iterator new_end = unique(introns.begin(), \n\t\t\t\t\t\t\t\t\t\t\t\t\t   introns.end());\n\tintrons.erase(new_end, introns.end());\n\t\n\tvector<pair<int, int> > evil_introns;\n\tfor (size_t i = 0; i < introns.size(); ++i)\n\t{\n\t\tfor (size_t j = i + 1; j < introns.size(); ++j)\n\t\t{\n\t\t\tif (overlap_in_genome(introns[i].first, introns[i].second,\n\t\t\t\t\t\t\t\t  introns[j].first, introns[j].second))\n\t\t\t{\n\t\t\t\tevil_introns.push_back(introns[i]);\n\t\t\t\tevil_introns.push_back(introns[j]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tsort(evil_introns.begin(), evil_introns.end());\n\tnew_end = unique(evil_introns.begin(), evil_introns.end());\n\tevil_introns.erase(new_end, evil_introns.end());\n\t\n\tvector<Scaffold> filtered_hits;\n\tfor (size_t i = 0; i < hits.size(); ++i)\n\t{\n\t\tbool overlaps_evil_intron = false;\n\t\tconst vector<AugmentedCuffOp>& ops = hits[i].augmented_ops();\n\t\tfor (size_t j = 0; j < ops.size(); ++j)\n\t\t{\n\t\t\tconst AugmentedCuffOp& op = ops[j];\n\t\t\tif (op.opcode == CUFF_UNKNOWN)\n\t\t\t{\n\t\t\t\tfor (size_t k = 0; k < evil_introns.size(); ++k)\n\t\t\t\t{\n\t\t\t\t\t\n\t\t\t\t\tif (overlap_in_genome(op.g_left(), op.g_right(),\n\t\t\t\t\t\t\t\t\t\t  evil_introns[k].first, evil_introns[k].second))\n\t\t\t\t\t{\n\t\t\t\t\t\toverlaps_evil_intron = true;\n\t\t\t\t\t}\n\t\t\t\t}\t\t\t\t  \n\t\t\t}\n\t\t}\n\t\tif (overlaps_evil_intron)\n\t\t{\n//            if (hits[i].has_intron())\n//            {\n//                fprintf(stderr, \"&&& Holding out intron-containing hazard at %d-%d\\n\", hits[i].left(), hits[i].right());\n//            }\n\t\t\thazards.push_back(hits[i]);\n\t\t}\t\n\t\telse\n\t\t{\n\t\t\tfiltered_hits.push_back(hits[i]);\n\t\t}\n\t}\n\t\n\tverbose_msg( \"%s\\tHeld out %lu scaffolds as transitivity hazards\\n\", bundle_label->c_str(), hazards.size());\n\t\n\thits = filtered_hits;\n}\n\nbool make_scaffolds(int bundle_left,\n\t\t\t\t\tint bundle_length,\n\t\t\t\t\tvector<Scaffold>& hits,\n\t\t\t\t\tvector<Scaffold>& scaffolds)\n{\n\tif (hits.empty())\n\t\treturn true;\n\n\tbool intron_hits = false;\n\tfor (size_t i = 0; i < hits.size(); ++i)\n\t{\n\t\tif (hits[i].has_intron())\n\t\t{\n\t\t\tintron_hits = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tif (!intron_hits)\n\t{\n\t\tverbose_msg( \"%s\\tNo introns in bundle, collapsing all hits to single transcript\\n\", bundle_label->c_str());\n\t\tscaffolds.push_back(Scaffold(hits));\n\t\tfill_gaps(scaffolds, 2 * olap_radius);\n\t}\n\telse\n\t{\n\t\tverbose_msg( \"%s\\tBundle has spliced reads\\n\", bundle_label->c_str());\n\n\t\tvector<Scaffold> hazards;\n\t\tholdout_transitivity_hazards(hits, hazards);\n\t\t\n        vector<Scaffold> split_hazards;\n        // Cleave the partials at their unknowns to minimize FPKM dilation on  \n        // the low end of the expression profile. \n        for (size_t i = 0; i < hazards.size(); ++i) \n        { \n            vector<Scaffold> c; \n            hazards[i].get_complete_subscaffolds(c); \n            split_hazards.insert(split_hazards.end(), c.begin(), c.end()); \n        } \n        \n\t\tvector<Scaffold> orig_hits = hits;\n\t\t\n        hits.insert(hits.end(), split_hazards.begin(), split_hazards.end());\n\t\t\n\n        compress_fragments(hits);\n\n        verbose_msg( \"%s\\tAssembling bundle with %lu hits\\n\", bundle_label->c_str(), hits.size());\n       \n\t\tvector<float> depth_of_coverage(bundle_length,0);\n\t\tmap<pair<int,int>, float> intron_depth_of_coverage;\n\t\tcompute_doc(bundle_left, \n\t\t\t\t\thits, \n\t\t\t\t\tdepth_of_coverage, \n\t\t\t\t\tintron_depth_of_coverage,\n\t\t\t\t\tfalse);\n\n\t\tnormal norm(0, 0.1);\n\t\t\n\t\tvector<const MateHit*> prev_chaff;\n\t\twhile (true)\n\t\t{\t\t\n\t\t\tstatic size_t MAX_BUNDLE_ALIGNMENTS = 0xFFFF;\n\t\t\t\n\t\t\tsort(hits.begin(), hits.end(), scaff_lt);\n           \n            //fprintf(stderr, \"\\tCurrent bundle has %d non-constitutive fragments\\n\", hits.size());            \n\t\t\t\n\t\t\tDAG bundle_dag;\n\t\t\t\n\t\t\tif (hits.empty())\n\t\t\t\treturn true;\n\t\t\tverbose_msg( \"%s\\tCalculating scaffold densities\\n\", bundle_label->c_str());\n\t\t\tvector<double> scaff_doc;\n\t\t\trecord_doc_for_scaffolds(bundle_left, \n\t\t\t\t\t\t\t\t\t hits, \n\t\t\t\t\t\t\t\t\t depth_of_coverage, \n\t\t\t\t\t\t\t\t\t intron_depth_of_coverage,\n\t\t\t\t\t\t\t\t\t scaff_doc);\n\t\t\tverbose_msg( \"%s\\tCreating compatibility graph\\n\", bundle_label->c_str());\n\t\t\t\n\t\t\tif (!create_overlap_dag(hits, bundle_dag))\n\t\t\t{\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n            \n            HitsForNodeMap hits_for_node = get(vertex_name, bundle_dag);\n\n            compress_overlap_dag_paths(bundle_dag, hits);\n            \n            if (hits.size() >= MAX_BUNDLE_ALIGNMENTS)\n\t\t\t{\n\t\t\t\tverbose_msg( \"%s\\tWarning: bundle too large, skipping assembly\\n\", bundle_label->c_str());\n\t\t\t\treturn false;\n\t\t\t}\n            \n            pair<DAGNode, DAGNode> terminal = add_terminal_nodes(bundle_dag);\n            DAGNode source = terminal.first;\n            DAGNode sink = terminal.second;\n            \n\t\t\tReachGraph bp;\n\t\t\t\n\t\t\tverbose_msg( \"%s\\tConstructing reachability graph\\n\", bundle_label->c_str());\n\t\t\t\n\t\t\tvector<ReachGraph::BNode> b_to_a;\n\t\t\tadjacency_list<> TC;\n\t\t\t\n\t\t\ttransitive_closure(bundle_dag, TC);\n\t\t\tDagToBp dag_to_bp;\n            \n            // TODO: deprecate dependence of create_reachability_bp_graph() on scaffold_mask\n\t\t\tvector<bool> scaffold_mask(num_vertices(bundle_dag), true);\n            \n\t\t\tcreate_reachability_bp_graph(bundle_dag, bp, b_to_a, dag_to_bp, TC, scaffold_mask);\n\t\t\t\n\t\t\tReachGraph::UEdgeMap<long long> cov_weights(bp);\n\t\t\tadd_weights_to_reachability_bp_graph(bp, hits_for_node, orig_hits, hits, cov_weights);\t\t\t\t\n\n            verbose_msg( \"%s\\tPerforming weighted matching\\n\", bundle_label->c_str());\n\n            typedef lemon::MinCostMaxBipartiteMatching<ReachGraph,ReachGraph::UEdgeMap<long long> > Matcher;\n            Matcher matcher(bp, cov_weights);\n            matcher.run();\n            \n            vector<vector<DAGNode> > chains;\n            make_chains_from_matching<Matcher>(bp, matcher, chains);\n\t\t\t\n\t\t\tverbose_msg( \"%s\\tFound %d distinct chains\\n\", bundle_label->c_str(), (int)chains.size());\n\t\t\t\n\t\t\tvector<vector<DAGNode> > paths;\n\t\t\textend_chains_to_paths(bundle_dag, chains, TC, source, sink, paths);\n\n\t\t\tverbose_msg( \"%s\\tCreating scaffolds for %d paths\\n\", bundle_label->c_str(), (int)paths.size());\n\t\t\t\n\t\t\tvector<Scaffold> new_scaffs;\n\t\t\tmake_scaffolds_from_paths(bundle_dag, paths, new_scaffs);\n\t\t\t\n\t\t\tverbose_msg( \"%s\\tCollapsing scaffolds\\n\", bundle_label->c_str());\n           \n\t\t\tcollapse_contained_transfrags(new_scaffs);\n\t\t\thits = new_scaffs;\n\t\t}\n\t\n\t\tscaffolds = hits;\n\t\t\n\t\t// One last collapse attempt...\n\t\tvector<Scaffold> new_scaffs = scaffolds;\n\t\t\n\t\tverbose_msg( \"%s\\tPerforming final collapse round\\n\", bundle_label->c_str());\n\t\t\n\t\tfill_gaps(new_scaffs, 2 * olap_radius);\n        \n\t\tscaffolds = new_scaffs;\n        \n        // Cleave the partials at their unknowns to minimize FPKM dilation on  \n        // the low end of the expression profile. \n        vector<Scaffold> completes; \n        for (size_t i = 0; i < scaffolds.size(); ++i) \n        { \n            vector<Scaffold> c; \n            scaffolds[i].get_complete_subscaffolds(c); \n            completes.insert(completes.end(), c.begin(), c.end()); \n        } \n        \n        verbose_msg( \"Extracted %lu contiguous transfrags from %lu scaffolds\\n\", completes.size(), scaffolds.size());\n        \n        new_scaffs = completes;\n        sort(new_scaffs.begin(), new_scaffs.end(), scaff_lt);\n        \n\t\tcollapse_contained_transfrags(new_scaffs);\n\t\tsort(new_scaffs.begin(), new_scaffs.end(), scaff_lt);\n\t\tscaffolds = new_scaffs;\n\t}\n    \n    // TODO: refactor into subroutine.  This routine shouldn't actually be \n    // necessary, and should be eliminated after thorough testing that it really\n    // isn't needed\n\tfor (size_t i = 0; i < scaffolds.size(); ++i)\n\t{\n\t\t//assert(!scaffolds[i].has_unknown());\n\t\t\n\t\tconst vector<const MateHit*>& supporting = scaffolds[i].mate_hits();\n\t\tCuffStrand s = CUFF_STRAND_UNKNOWN;\n\t\tfor (size_t j = 0; j < supporting.size(); ++j)\n\t\t{\n//\t\t\tassert (supporting[j]->strand() == CUFF_STRAND_UNKNOWN || \n//\t\t\t\t\ts == supporting[j]->strand());\n\t\t\tif (supporting[j]->strand() != CUFF_STRAND_UNKNOWN)\n\t\t\t\ts = supporting[j]->strand();\n\t\t}\n        if (scaffolds[i].strand() == CUFF_STRAND_UNKNOWN)\n            scaffolds[i].strand(s);\n\t}\n    // end refactor\n\t\n\treturn true;\n}\n"
  },
  {
    "path": "src/assemble.h",
    "content": "#ifndef ASSEMBLE_H\n#define ASSEMBLE_H\n\n/*\n *  assemble.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/23/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <vector>\n#include <map>\n\n\n#include \"bundles.h\"\n#include \"scaffolds.h\"\n\nclass BiasLearner;\n\nbool assemble_hits(BundleFactory& bundle_factory, boost::shared_ptr<BiasLearner> bl_ptr);\n\n//bool intron_compatible(const MateHit& lhs, const MateHit& rhs);\nbool read_hits_overlap(const ReadHit* lhs, const ReadHit* rhs);\nbool read_hits_intron_agree(const ReadHit* h1, const ReadHit* h2);\n\nint  match_length(const MateHit& m, int left, int right);\n\n\nbool mate_graphs(const HitBundle& bundle, BundleStats* stats);\n\n\n\nbool make_scaffolds(int bundle_left,\n\t\t\t\t\tint bundle_length,\n\t\t\t\t\tvector<Scaffold>& hits,\n\t\t\t\t\tvector<Scaffold>& scaffolds);\n\n#endif\n"
  },
  {
    "path": "src/biascorrection.cpp",
    "content": "/*\n *  biascorrection.cpp\n *  cufflinks\n *\n *  Created by Adam Roberts on 5/20/10.\n *  Copyright 2010 Adam Roberts. All rights reserved.\n *\n */\n\n#include \"biascorrection.h\"\n#include \"scaffolds.h\"\n#include \"abundances.h\"\n#include \"progressbar.h\"\n#include \"bundles.h\"\n\n#include <iostream>\n#include <fstream>\n\nusing namespace std;\n\nvoid output_vector(vector<double>& v, char* fname)\n{\n\tofstream myfile1;\n\tstring filename = output_dir + \"/\" + fname;\n\tmyfile1.open (filename.c_str());\n\t\n\tfor (size_t i = 0; i < v.size(); ++i)\n\t\tmyfile1 << v[i] <<\",\";\n\tmyfile1 << endl;\n\t\n\tmyfile1.close();\n}\n\ndouble colSums(const ublas::matrix<long double>& A, vector<long double>& sums)\n{\n\tlong double total = 0.0;\n\tsums = vector<long double>(A.size2(),0.0);\n\tfor (size_t i = 0; i < A.size1(); ++i)\n\t\tfor (size_t j = 0; j < A.size2(); ++j)\n\t\t{\n\t\t\tsums[j] += A(i,j);\n\t\t\ttotal += A(i,j);\n\t\t}\n\treturn total;\n}\n\ndouble fourSums(const ublas::matrix<long double>& A, ublas::matrix<long double>& sums)\n{\n\tlong double total = 0.0;\n\tsums = ublas::zero_matrix<long double>(A.size1(), A.size2()/4);\n\tfor (size_t i = 0; i < A.size1(); ++i)\n\t\tfor (size_t j = 0; j < A.size2(); ++j)\n\t\t{\n\t\t\tsums(i,j/4) += A(i,j);\n\t\t\ttotal += A(i,j);\n\t\t}\n\t\n\treturn total;\n}\n\nvoid ones(ublas::matrix<long double>& A)\n{\n\tfor (size_t i = 0; i < A.size1(); ++i)\n\t\tfor (size_t j = 0; j < A.size2(); ++j)\n\t\t\tA(i,j) = 1;\n}\n\nvoid get_compatibility_list(const vector<boost::shared_ptr<Scaffold> >& transcripts,\n                            const vector<MateHit>& alignments,\n                            vector<list<int> >& compatibilities)\n{\n\tint M = alignments.size();\n\tint N = transcripts.size();\n\t\n\tvector<Scaffold> alignment_scaffs;\n\t\n\tfor (size_t i = 0; i < alignments.size(); ++i)\n\t{\n\t\tconst MateHit& hit = alignments[i];\n\t\talignment_scaffs.push_back(Scaffold(hit));\n\t} \n\t\n\tfor (int i = 0; i < M; ++i) \n\t{\n\t\tfor (int j = 0; j < N; ++j) \n\t\t{\n\t\t\tif (transcripts[j]->strand() != CUFF_STRAND_UNKNOWN\n\t\t\t\t&& transcripts[j]->contains(alignment_scaffs[i]) \n\t\t\t\t&& Scaffold::compatible(*transcripts[j],alignment_scaffs[i]))\n\t\t\t{\n\t\t\t\tcompatibilities[i].push_back(j);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid learn_bias(BundleFactory& bundle_factory, BiasLearner& bl, bool progress_bar)\n{\n\tHitBundle bundle;\n\tRefSequenceTable& rt = bundle_factory.ref_table();\n\n\tProgressBar p_bar;\n\tif (progress_bar)\n\t\tp_bar = ProgressBar(\"Learning bias parameters.\", bundle_factory.read_group_properties()->total_map_mass());\n\n\twhile(true)\n\t{\n\t\tHitBundle* bundle_ptr = new HitBundle();\n\t\t\n\t\tif (!bundle_factory.next_bundle(*bundle_ptr, false))\n\t\t{\n\t\t\tdelete bundle_ptr;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tHitBundle& bundle = *bundle_ptr;\n\t\t\n\t\tchar bundle_label_buf[2048];\n\t\tsprintf(bundle_label_buf, \"%s:%d-%d\", rt.get_name(bundle.ref_id()),\tbundle.left(), bundle.right());\n\t\tif (progress_bar)\n\t\t\tp_bar.update(bundle_label_buf, bundle.raw_mass());\n\t\t\n\t\tif (bundle.non_redundant_hits().size()==0)// || bundle.ref_scaffolds().size() != 1)\n\t\t{\n\t\t\tdelete bundle_ptr;\n\t\t\tcontinue;\n\t\t}\n\n\t\t//bl.preProcessTranscript(*(bundle.ref_scaffolds()[0]));\n\t\t\n        for (size_t j = 0; j < bundle.ref_scaffolds().size(); ++j)\n        {\n            bl.preProcessTranscript(*(bundle.ref_scaffolds()[j]));\n        }\n        \n\t\tdelete bundle_ptr;\n\t}\n\t\n\tif (progress_bar)\n\t\tp_bar.complete();\n\t\t\n\tbl.normalizeParameters();\n    \n//    if (output_bias_params)\n//        bl.output();\n}\n\nconst int BiasLearner::pow4[] = {1,4,16,64};\nconst int BiasLearner::siteSpec[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};\nconst int BiasLearner::vlmmSpec[] = {1,1,1,1,1,2,2,2,3,3,3,3,3,3,3,3,2,2,2,1,1}; //Length of connections at each position in the window\nconst int BiasLearner::MAX_SLICE = 3; // Maximum connection length\nconst int BiasLearner::CENTER = 8; //Index in paramTypes[] of first element in read\nconst int BiasLearner::_m = 21; //Number of positions spanned by window\nconst int BiasLearner::_n = 64; //Length of maximum connection in VLMM\nconst int BiasLearner::lengthBins[] = {791,1265,1707,2433}; //Quantiles derived from human mRNA length distribution in UCSC genome browser\nconst double BiasLearner::positionBins[] = {.02,.04,.06,.08,.10,.15,.2,.3,.4,.5,.6,.7,.8,.85,.9,.92,.94,.96,.98,1};\n\nBiasLearner::BiasLearner(boost::shared_ptr<EmpDist const> frag_len_dist)\n{\n\tparamTypes = vlmmSpec;\n\tif (bias_mode==SITE || bias_mode==POS_SITE)\n\t{\n\t\tparamTypes = siteSpec;\n\t}\n\t_frag_len_dist = frag_len_dist;\n\t    \n    _startSeqParams = ublas::zero_matrix<long double>(_m,_n);\n\t_startSeqExp = ublas::zero_matrix<long double>(_m,_n);\n\t_endSeqParams = ublas::zero_matrix<long double>(_m,_n);\n\t_endSeqExp = ublas::zero_matrix<long double>(_m,_n);\n\t_startPosParams = ublas::zero_matrix<long double>(20,5);\n\t_startPosExp = ublas::zero_matrix<long double>(20,5);\n\t_endPosParams = ublas::zero_matrix<long double>(20,5);\n\t_endPosExp = ublas::zero_matrix<long double>(20,5);\n}\n\n\ninline int BiasLearner::seqToInt(const char* seqSlice, int n) const\n{\n\tint c = 0;\n\tfor(int i = 0; i < n; i++)\n\t{\t\n\t\tif (seqSlice[i] == 4) return -1;//N\n\t\tc += (seqSlice[i])*pow4[n-i-1];\n\t}\n\treturn c;\n}\n\ninline void BiasLearner::getSlice(const char* seq, char* slice, int start, int end) const// INCLUSIVE!\n{\n\tif (end >= start)\n\t{\n\t\tfor (int i = start; i <= end; ++i)\n\t\t{\n\t\t\tslice[i-start] = seq[i];\n\t\t}\n\t}\n\telse \n\t{\n\t\tfor(int i = start; i >= end; --i)\n\t\t{\n\t\t\tslice[start-i] = seq[i];\n\t\t}\n\t}\n}\n\nvoid BiasLearner::preProcessTranscript(const Scaffold& transcript)\n{\n\tif (transcript.strand()==CUFF_STRAND_UNKNOWN || transcript.fpkm() < 1 || transcript.seq()==\"\")\n\t\treturn;\n\t\t\n\tvector<double> startHist(transcript.length()+1, 0.0); // +1 catches overhangs\n\tvector<double> endHist(transcript.length()+1, 0.0);\n\n\tBOOST_FOREACH (const MateHit* hit_p, transcript.mate_hits())\n\t{\n\t\tconst MateHit& hit = *hit_p;\n\t\tif (!hit.left_alignment() && !hit.right_alignment())\n\t\t\tcontinue;\n\t\t\n\t\tdouble mass = hit.mass();\n\t\t\n\t\tint start;\n\t\tint end;\n\t\tint frag_len;\n\t\t\n\t\ttranscript.map_frag(hit, start, end, frag_len);\n\t\tstartHist[start] += mass;\n\t\tendHist[end] += mass;\n\t}\n\tprocessTranscript(startHist, endHist, transcript);\n}\n\n\nvoid BiasLearner::processTranscript(const std::vector<double>& startHist, const std::vector<double>& endHist, const Scaffold& transcript)\n{\n\tdouble fpkm = transcript.fpkm();\n\tint seqLen = transcript.length();\n\t\n\tchar seq[seqLen];\n\tchar c_seq[seqLen];\n\tencode_seq(transcript.seq(), seq, c_seq);\n\t\t\n\tchar seqSlice[MAX_SLICE];\n\t\n\tint lenClass=0;\n\twhile (seqLen > lengthBins[lenClass] && lenClass < 4)\n\t{\n\t\tlenClass++;\n\t}\n\t\n\t// We want to only use the portion of the transcript where fragments can start/end\n\tint min_frag_len = _frag_len_dist->min();\n\tint currStartBin = 0;\n\tint startBinCutoff = positionBins[currStartBin]*(seqLen - min_frag_len);\n\tint currEndBin = 0;\n\tint endBinCutoff = positionBins[currStartBin]*(seqLen - min_frag_len);\n\n#if ENABLE_THREADS\n\tboost::mutex::scoped_lock lock(_bl_lock);\n#endif\t\n\t\t\n\tfor (int i=0; i < seqLen; i++)\n\t{\n\t\t\n\t\t//Position Bias\n\t\tif (i > startBinCutoff && currStartBin < (int)_startPosParams.size1()-1)\n\t\t\tstartBinCutoff=positionBins[++currStartBin]*(seqLen - min_frag_len);\n\t\tif (i - min_frag_len > endBinCutoff)\n\t\t\tendBinCutoff = positionBins[++currEndBin]*(seqLen - min_frag_len);\n\t\t\t\n\t\t_startPosParams(currStartBin, lenClass) += startHist[i];\n\t\t_startPosExp(currStartBin, lenClass) += fpkm*(_frag_len_dist->cdf(seqLen-i));\n\t\t_endPosParams(currEndBin, lenClass) += endHist[i];\n\t\t_endPosExp(currEndBin, lenClass) += fpkm*(_frag_len_dist->cdf(i+1));\n\n\t\t\n\t\tbool start_in_bounds = i-CENTER >= 0 && i+(_m-1)-CENTER < seqLen;\n\t\tbool end_in_bounds = i+CENTER-(_m-1) >= 0 && i+CENTER < seqLen;\n\t\t\n\t\tif (!start_in_bounds && !end_in_bounds) // Make sure we are in bounds of the sequence\n\t\t\tcontinue;\n\t\t\n\t\t//Sequence Bias\n\t\tfor(int j=0; j < _m; j++)\n\t\t{\n\t\t\t// Start Bias\n\t\t\tif (start_in_bounds) // Make sure we are in bounds of the sequence\n\t\t\t{\n\t\t\t\tint k = i+j-CENTER;\n\t\t\t\tgetSlice(seq, seqSlice, k-(paramTypes[j]-1), k);\n\t\t\t\tint v = seqToInt(seqSlice,paramTypes[j]);\n\t\t\t\tif (v >= 0)\n\t\t\t\t{\n\t\t\t\t\t_startSeqParams(j,v) += startHist[i];\n\t\t\t\t\t_startSeqExp(j,v) += fpkm*(_frag_len_dist->cdf(seqLen-i));\n\t\t\t\t}\n\t\t\t\telse // There is an N.  Average over all possible values of N\n\t\t\t\t{\n\t\t\t\t\tlist<int> nList(1,0);\n\t\t\t\t\tgenNList(seqSlice, 0, paramTypes[j],nList);\n\t\t\t\t\tfor (list<int>::iterator it=nList.begin(); it!=nList.end(); ++it)\n\t\t\t\t\t{\n\t\t\t\t\t\t_startSeqParams(j,*it) += startHist[i]/((double)nList.size());\n\t\t\t\t\t\t_startSeqExp(j,*it) += fpkm*(_frag_len_dist->cdf(seqLen-i))/(double)nList.size();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// End Bias\n\t\t\tif (end_in_bounds) // Make sure we are in bounds of the sequence\n\t\t\t{\n\t\t\t\tint k = i+CENTER-j;\n\t\t\t\tgetSlice(c_seq, seqSlice, k+(paramTypes[j]-1), k); \n\t\t\t\tint v = seqToInt(seqSlice, paramTypes[j]);\n\t\t\t\tif (v >= 0)\n\t\t\t\t{\n\t\t\t\t\t_endSeqParams(j,v) += endHist[i];\n\t\t\t\t\t_endSeqExp(j,v) += fpkm*(_frag_len_dist->cdf(seqLen-i));\n\t\t\t\t}\n\t\t\t\telse // There is an N.  Average over all possible values of N\n\t\t\t\t{\n\t\t\t\t\tlist<int> nList(1,0);\n\t\t\t\t\tgenNList(seqSlice, 0, paramTypes[j], nList);\n\t\t\t\t\tfor (list<int>::iterator it=nList.begin(); it!=nList.end(); ++it)\n\t\t\t\t\t{\n\t\t\t\t\t\t_endSeqParams(j,*it) += endHist[i]/((double)nList.size());\n\t\t\t\t\t\t_endSeqExp(j,*it) += fpkm*(_frag_len_dist->cdf(seqLen-i))/(double)nList.size();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid BiasLearner::getBias(const Scaffold& transcript, vector<double>& startBiases, vector<double>& endBiases) const\n{\n\tif (transcript.seq()==\"\")\n\t\treturn;\n\t\t\n\tint seqLen = transcript.length();\n\t\n\tchar seq[seqLen];\n\tchar c_seq[seqLen];\n\tencode_seq(transcript.seq(), seq, c_seq);\n\t\n\tchar seqSlice[MAX_SLICE];\n\t\n\tint lenClass=0;\n\twhile (seqLen > lengthBins[lenClass] && lenClass < 4)\n\t{\n\t\tlenClass++;\n\t}\n\t\n\tint min_frag_len = _frag_len_dist->min();\n\tint currStartBin = 0;\n\tint startBinCutoff = positionBins[currStartBin]*(seqLen - min_frag_len);\n\tint currEndBin = 0;\n\tint endBinCutoff = positionBins[currEndBin]*(seqLen - min_frag_len);\n\t\n\tfor (int i=0; i < seqLen; i++)\n\t{\n\t\t//Position Bias\n\t\tif (i > startBinCutoff && currStartBin < (int)_startPosParams.size1()-1)\n\t\t\tstartBinCutoff=positionBins[++currStartBin]*(seqLen - min_frag_len);\n\t\tif (i - min_frag_len > endBinCutoff)\n\t\t\tendBinCutoff = positionBins[++currEndBin]*(seqLen - min_frag_len);\n\n\t\tdouble startBias = _startPosParams(currStartBin, lenClass);\n\t\tdouble endBias = _endPosParams(currEndBin,lenClass);\n\t\t\n\t\t//Sequence Bias\n\t\t\n\t\tbool start_in_bounds = i-CENTER >= 0 && i+(_m-1)-CENTER < seqLen;\n\t\tbool end_in_bounds = i+CENTER-(_m-1) >= 0 && i+CENTER < seqLen - _frag_len_dist->mean(); // don't count bias near end since we're over-counting these fragments\n\t\t\n\t\tif (start_in_bounds || end_in_bounds) // Make sure we are in bounds of the sequence\n\t\t{\n\t\t\tfor(int j=0; j < _m; j++)\n\t\t\t{\n\t\t\t\t// Start Bias\n\t\t\t\tif (start_in_bounds) // Make sure we are in bounds of the sequence\n\t\t\t\t{\n\t\t\t\t\tint k = i+j-CENTER;\n\t\t\t\t\tgetSlice(seq, seqSlice, k-(paramTypes[j]-1), k);\n\t\t\t\t\tint v = seqToInt(seqSlice, paramTypes[j]);\n\t\t\t\t\tif (v >= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tstartBias *= _startSeqParams(j,v);\n\t\t\t\t\t}\n\t\t\t\t\telse // There is an N.  Average over all possible values of N\n\t\t\t\t\t{\n\t\t\t\t\t\tlist<int> nList(1,0);\n\t\t\t\t\t\tdouble tot = 0;\n\t\t\t\t\t\tgenNList(seqSlice, 0, paramTypes[j],nList);\n\n\t\t\t\t\t\tfor (list<int>::iterator it=nList.begin(); it!=nList.end(); ++it)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttot += _startSeqParams(j,*it);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstartBias *= tot/nList.size();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// End Bias\n\t\t\t\tif (end_in_bounds) // Make sure we are in bounds of the sequence\n\t\t\t\t{\n\t\t\t\t\tint k = i+CENTER-j;\n\t\t\t\t\tgetSlice(c_seq, seqSlice, k+(paramTypes[j]-1), k);\n\t\t\t\t\tint v = seqToInt(seqSlice,paramTypes[j]);\n\t\t\t\t\tif (v >= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tendBias *= _endSeqParams(j,v);\n\t\t\t\t\t}\n\t\t\t\t\telse // There is an N.  Average over all possible values of N\n\t\t\t\t\t{\n\t\t\t\t\t\tlist<int> nList(1,0);\n\t\t\t\t\t\tdouble tot = 0;\n\t\t\t\t\t\tgenNList(seqSlice, 0, paramTypes[j],nList);\n\t\t\t\t\t\tfor (list<int>::iterator it=nList.begin(); it!=nList.end(); ++it)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttot += _endSeqParams(j,*it);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tendBias *= tot/nList.size();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n        assert(finite(startBias) && finite(endBias));\n\t\tstartBiases[i] = startBias;\n\t\tendBiases[i] = endBias;\n\t}\n}\n\nvoid BiasLearner::genNList(const char* seqSlice, int start, int n, list<int>& nList) const\n{\n\n\tif (n > 1) \n\t\tgenNList(seqSlice, start+1, n-1, nList);\n\t\n\t\n\tif (n==1 && seqSlice[start]==4)\n\t{\n\t\tfor (int j=0; j<4; ++j) \n\t\t\tnList.push_back(j);\n\t}\n\telse if (n==1)\n\t{\n\t\tnList.push_back(seqSlice[start]);\n\t}\n\telse if (seqSlice[start]==4)\n\t{\n\t\tfor (int i = nList.size()-1; i>=0; --i)\n\t\t{\n\t\t\tfor (int j=0; j<4; ++j) \n\t\t\t\tnList.push_back(nList.front()+j*pow4[n-1]);\n\t\t\tnList.pop_front();\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (list<int>::iterator it=nList.begin(); it!=nList.end(); ++it)\n\t\t\t(*it)+=seqSlice[start]*pow4[n-1];\n\t}\n\t\n}\n\nvoid BiasLearner::normalizeParameters()\n{\n    double THRESH = 100;\n\n    \n\t//Normalize position parameters\t\n\tvector<long double> startPosParam_sums;\n\tvector<long double> startPosExp_sums;\n\tdouble start_tot = colSums(_startPosParams, startPosParam_sums); // Total starts for each length class\n\tcolSums(_startPosExp, startPosExp_sums); // Total FPKM for each length class\n\t\n\tvector<long double> endPosParam_sums;\n\tvector<long double> endPosExp_sums;\n\tdouble end_tot = colSums(_endPosParams, endPosParam_sums); // Total starts for each length class\n\tcolSums(_endPosExp, endPosExp_sums); // Total FPKM for each length class\n\n\tfor(size_t i=0; i < _startPosParams.size1(); i++)\n\t{\n\t\tfor(size_t j=0; j < _startPosParams.size2(); j++)\n\t\t{\n            if (startPosParam_sums[j] < THRESH)\n\t\t\t{\n\t\t\t\t_startPosParams(i,j) = 1;\n\t\t\t}\n            else\n            {\n                _startPosParams(i,j) /= startPosParam_sums[j];\n                _startPosExp(i,j) /= startPosExp_sums[j];\n                if (_startPosExp(i,j) == 0)\n                    _startPosParams(i,j) = numeric_limits<long double>::max();\n                else\n                    _startPosParams(i,j) /= _startPosExp(i,j);\n            }\n\t\t\t\n            if (endPosParam_sums[j] < THRESH)\n\t\t\t{\n\t\t\t\t_endPosParams(i,j) = 1;\n\t\t\t}\n            else\n            {\n                _endPosParams(i,j) /= endPosParam_sums[j];\n                _endPosExp(i,j) /= endPosExp_sums[j];\n                if (_endPosExp(i,j) == 0)\n                    _endPosParams(i,j) = numeric_limits<long double>::max();\n                else\n                    _endPosParams(i,j) /= _endPosExp(i,j);\n            }\n\t\t}\n\t}\n\t\n\tif (start_tot == 0.0)\n\t\tones(_startPosParams);\n\tif (end_tot == 0.0)\n\t\tones(_endPosParams);\n\t\n\tublas::matrix<long double> startSeqExp_sums;\n\tublas::matrix<long double> startParam_sums;\n\tstart_tot = fourSums(_startSeqParams, startParam_sums);\n\tfourSums(_startSeqExp, startSeqExp_sums);\n\t\n\tublas::matrix<long double> endSeqExp_sums;\n\tublas::matrix<long double> endParam_sums;\n\tend_tot = fourSums(_endSeqParams, endParam_sums);\n\tfourSums(_endSeqExp, endSeqExp_sums); \n\t    \n\t//Normalize sequence parameters\n\tfor(int i=0; i < _m; i++)\n\t{\n\t\tfor(int j=0; j < pow4[paramTypes[i]]; j++)\n\t\t{\n\t\t\tif (startParam_sums(i,j/4) < THRESH)\n\t\t\t{\n\t\t\t\t_startSeqParams(i,j) = 1;\n\t\t\t}\n\t\t\telse \n\t\t\t{\n\t\t\t\t_startSeqParams(i,j) /= startParam_sums(i,j/4);\n\t\t\t\t_startSeqExp(i,j) /= startSeqExp_sums(i,j/4);\n\t\t\t\t_startSeqParams(i,j) /= _startSeqExp(i,j);\n\t\t\t}\n\t\t\tif (endParam_sums(i,j/4) < THRESH)\n\t\t\t{\n\t\t\t\t_endSeqParams(i,j) = 1;\n\t\t\t}\n\t\t\telse \n\t\t\t{\n\t\t\t\t_endSeqParams(i,j) /= endParam_sums(i,j/4);\n\t\t\t\t_endSeqExp(i,j) /= endSeqExp_sums(i,j/4);\n\t\t\t\t_endSeqParams(i,j) /= _endSeqExp(i,j);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif (start_tot==0.0)\n\t\tones(_startSeqParams);\n\tif (end_tot==0.0)\n\t\tones(_endSeqParams);\n\t\n\tif (bias_mode==VLMM || bias_mode==SITE)\n\t{\n\t\tones(_startPosParams);\n\t\tones(_endPosParams);\n\t}\n\telse if (bias_mode == POS)\t\n\t{\n\t\tones(_startSeqParams);\n\t\tones(_endSeqParams);\n\t}\n}\n\nvoid BiasLearner::output(FILE* output_file, const string& condition_name, int replicate_num) const\n{\n\t// StartSeq\n\tfor (int i = 0; i < _n; ++i)\n\t{\n\t\tfor(int j = 0; j < _m; ++j)\n        {\n\t\t\tfprintf(output_file, \"%s\\t%d\\tstart_seq\\t%d\\t%d\\t%Lg\\n\",condition_name.c_str(), replicate_num, i, j,  _startSeqParams(j,i));\n        }\n\t}\n\n    // EndSeq\n    for (int i = 0; i < _n; ++i)\n    {\n        for(int j = 0; j < _m; ++j)\n        {\n            fprintf(output_file, \"%s\\t%d\\tend_seq\\t%d\\t%d\\t%Lg\\n\",condition_name.c_str(), replicate_num, i, j,  _startSeqParams(j,i));\n        }\n    }\n\n\t// Start Pos\n\tfor (size_t i = 0; i < _startPosParams.size2(); ++i)\n\t{\n\t\tfor(size_t j = 0; j < _startPosParams.size1(); ++j)\n        {\n\t\t\tfprintf(output_file, \"%s\\t%d\\tstart_pos\\t%lu\\t%lu\\t%Lg\\n\",condition_name.c_str(), replicate_num, i, j,  _startPosParams(j,i));\n        }\n\t}\n\n\t// End Pos\n\tfor (size_t i = 0; i < _endPosParams.size2(); ++i)\n\t{\n\t\tfor(size_t j = 0; j < _endPosParams.size1(); ++j)\n        {\n\t\t\tfprintf(output_file, \"%s\\t%d\\tend_pos\\t%lu\\t%lu\\t%Lg\\n\",condition_name.c_str(), replicate_num, i, j,  _endPosParams(j,i));\n        }\n\t}\n}\n\n\n\nint BiasCorrectionHelper::add_read_group(boost::shared_ptr<ReadGroupProperties const> rgp)\n{\n\tint trans_len = _transcript->length();\n\t_rg_index.insert(make_pair(rgp, _size));\n\t\n\t// Defaults are values for a run not using bias correction\n\tvector<double> start_bias(trans_len+1, 1.0);\n\tvector<double> end_bias(trans_len+1, 1.0);\n\tdouble eff_len = 0.0;\n\t\n\tboost::shared_ptr<EmpDist const> fld = rgp->frag_len_dist();\n\t\n\tvector<double> tot_bias_for_len(trans_len+1, 0);\n\tvector<double> start_bias_for_len(trans_len+1, 0);\n\tvector<double> end_bias_for_len(trans_len+1, 0);\n\n\ttot_bias_for_len[trans_len] = trans_len;\n\tstart_bias_for_len[trans_len] = trans_len;\n\tend_bias_for_len[trans_len] = trans_len;\n\n\tif (final_est_run && corr_bias && _transcript->strand()!=CUFF_STRAND_UNKNOWN)\n\t{\n\t\trgp->bias_learner()->getBias(*_transcript, start_bias, end_bias);\n\n\t\tfor(int l = fld->min(); l <= trans_len; l++)\n\t\t{\n\t\t\tfor(int i = 0; i <= trans_len - l; i++)\n\t\t\t{\n\t\t\t\tdouble tot_bias = start_bias[i]*end_bias[i+l-1];\n\t\t\t\ttot_bias_for_len[l] += tot_bias;\n\t\t\t\tstart_bias_for_len[l] += start_bias[i];\n\t\t\t\tend_bias_for_len[l] += end_bias[i+l-1];\n\t\t\t\t\n\t\t\t\tdouble frag_prob = (bias_mode == POS || bias_mode == POS_VLMM || bias_mode == POS_SITE) ? fld->npdf(l, trans_len-i) : fld->pdf(l);\n\t\t\t\teff_len += tot_bias * frag_prob;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor(int l = fld->min(); l <= trans_len; l++)\n\t\t{\n\t\t\ttot_bias_for_len[l] = trans_len - l + 1;\n\t\t\tstart_bias_for_len[l] = trans_len - l + 1;\n\t\t\tend_bias_for_len[l] = trans_len - l + 1;\n\t\t\teff_len += fld->npdf(l, trans_len) * (trans_len - l + 1);\n\t\t}\n\t}\n\t\n\tassert(eff_len > 0);\n\t_start_biases.push_back(start_bias);\n\t_end_biases.push_back(end_bias);\n\t_tot_biases_for_len.push_back(tot_bias_for_len);\n\t_eff_lens.push_back(eff_len);\n\t_start_biases_for_len.push_back(start_bias_for_len);\n\t_end_biases_for_len.push_back(end_bias_for_len);\n\t_rg_masses.push_back(0.0);\n\t\n\treturn _size++; // Index of new element\n}\n\nint num_adds = 0;\nint BiasCorrectionHelper::get_index(boost::shared_ptr<ReadGroupProperties const> rgp)\n{\n    boost::unordered_map<boost::shared_ptr<ReadGroupProperties const>, int>::iterator iter;\n\titer = _rg_index.find(rgp);\n\t\n\tif (iter==_rg_index.end()) //This rg is not yet in the index, so add it.\n\t{\n        num_adds++;\n\t\treturn add_read_group(rgp);\n\t}\n\t\n\treturn iter->second;\n}\n\n// Hit needs to be from the collapsed (non_redundant) list to match indexing \ndouble BiasCorrectionHelper::get_cond_prob(const MateHit& hit)\n{\n\tboost::shared_ptr<ReadGroupProperties const> rgp = hit.read_group_props();\n\t\n\tint i = get_index(rgp);\n\t\n\tint start;\n\tint end;\n\tint frag_len;\n\tint trans_len = _transcript->length();\n\t\n\t_transcript->map_frag(hit, start, end, frag_len);\n\n\tboost::shared_ptr<const EmpDist> fld = rgp->frag_len_dist();\n\t\n\tdouble cond_prob = 1.0;\n\tcond_prob *= _start_biases[i][start];\n\tcond_prob *= _end_biases[i][end];\n\tdouble frag_prob = (bias_mode == POS || bias_mode == POS_VLMM || bias_mode == POS_SITE) ? fld->npdf(frag_len, trans_len-start) : fld->pdf(frag_len);\n\tcond_prob *= frag_prob; \n\t\n\tif (cond_prob==0.0)\n\t\treturn 0.0;\n\t\n    if (hit.is_pair() || hit.read_group_props()->complete_fragments())\n    {\n        if (frag_len >= (int)_tot_biases_for_len[i].size())\n            cond_prob = 0.0;\n        else\n            cond_prob /= _tot_biases_for_len[i][frag_len];\n    }\n\telse if (start!=trans_len && end==trans_len) // The hit is a singleton at the start of a fragment\n\t\tcond_prob /= _start_biases_for_len[i][frag_len];\n\telse if (start==trans_len && end!=trans_len) // The hit is a singleton at the end of a fragment\n\t\tcond_prob /= _end_biases_for_len[i][frag_len];\n\telse if (frag_len==trans_len)  // We don't actually know where we start or end and can't subtract off the frag_len or we'll get inf\n\t\tcond_prob /= trans_len;\n\telse\n    {\n        if (trans_len < frag_len)\n        {\n            cond_prob = 0;\n        }\n        else \n        {\n            // Single-end read w/ library type FF or RR\n            cond_prob /= trans_len-frag_len;\n        }\n    }\n\n\tif (cond_prob > 0 && hit.collapse_mass() > 0)\n\t{\n\t\t_rg_masses[i] +=  hit.collapse_mass();\n\t\t_mapped = true;\n\t}\n\t\n#if DEBUG\n    if (isinf(cond_prob))\n    {\n        double cond_prob = 1.0;\n        cond_prob *= _start_biases[i][start];\n        cond_prob *= _end_biases[i][end];\n        double frag_prob = (bias_mode == POS || bias_mode == POS_VLMM || bias_mode == POS_SITE) ? fld->npdf(frag_len, trans_len-start) : fld->pdf(frag_len);\n        cond_prob *= frag_prob; \n        \n        if (cond_prob==0.0)\n            return 0.0;\n        \n        if (hit.is_pair())\n        {\n            if (frag_len >= _tot_biases_for_len[i].size())\n                cond_prob = 0.0;\n            else\n                cond_prob /= _tot_biases_for_len[i][frag_len];\n        }\n        else if (start!=trans_len && end==trans_len) // The hit is a singleton at the start of a fragment\n            cond_prob /= _start_biases_for_len[i][frag_len];\n        else if (start==trans_len && end!=trans_len) // The hit is a singleton at the end of a fragment\n            cond_prob /= _end_biases_for_len[i][frag_len];\n        else if (frag_len==trans_len)  // We don't actually know where we start or end and can't subtract off the frag_len or we'll get inf\n            cond_prob /= trans_len;\n        else\n        {\n            if (trans_len < frag_len)\n            {\n                cond_prob = 0;\n            }\n            else \n            {\n                // Single-end read w/ library type FF or RR\n                cond_prob /= trans_len-frag_len;\n            }\n        }\n    }\n#endif\n    \n\tassert(!isinf(cond_prob));\n\tassert(!isnan(cond_prob));\n    \n    if (isinf(cond_prob) || isnan(cond_prob))\n        cond_prob = 0.0;\n    \n\treturn cond_prob;\n}\n\ndouble BiasCorrectionHelper::get_effective_length()\n{\n\t\n\tif (_size==0)\n\t\treturn _transcript->length();\n\n    if (no_effective_length_correction)\n        return _transcript->length();\n    \n    if (no_length_correction)\n        return 1;\n\t\n\tdouble tot_mass = accumulate( _rg_masses.begin(), _rg_masses.end(), 0.0 );\n\tdouble eff_len = 0.0;\n\t\n\tif (tot_mass==0)\n\t\treturn _transcript->length();\n\t\n    for (boost::unordered_map<boost::shared_ptr<ReadGroupProperties const>, int>::iterator itr = _rg_index.begin();\n         itr != _rg_index.end();\n         ++itr)\n\t{\n\t\tint i = itr->second;\n\t\tdouble rg_eff_len = _eff_lens[i];\n\t\teff_len += rg_eff_len * (_rg_masses[i]/tot_mass);\n\t}\n\t\n\tassert(eff_len>0);\n    //assert(eff_len>1);\n\tassert(!isnan(eff_len));\n\treturn eff_len;\n}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n"
  },
  {
    "path": "src/biascorrection.h",
    "content": "#ifndef BIASCORRECTION_H\n#define BIASCORRECTION_H\n\n/*\n *  biascorrection.h\n *  cufflinks\n *\n *  Created by Adam Roberts on 5/20/10.\n *  Copyright 2010 Adam Roberts. All rights reserved.\n *\n */\n\n\n#include <boost/numeric/ublas/matrix.hpp>\n#include <vector>\n#include <list>\n#include <string>\n#include <boost/unordered_map.hpp>\n#include <boost/thread.hpp>\n#include \"common.h\"\n\nclass MateHit;\nclass Scaffold;\nclass BundleFactory;\nclass HitBundle;\n\nnamespace ublas = boost::numeric::ublas;\n\nvoid get_compatibility_list(const std::vector<Scaffold>& transcripts,\n\t\t\t\t\t\t\tconst std::vector<MateHit>& alignments,\n\t\t\t\t\t\t\tstd::vector<std::list<int> >& compatibilities);\n\nclass BiasLearner{\n\tstatic const int pow4[];\n\tstatic const int MAX_SLICE;\n\tstatic const int CENTER;\n\tstatic const int _m;\n\tstatic const int _n;\n\t\n\tstatic const int lengthBins[];\n\tstatic const double positionBins[];\n\tstatic const int siteSpec[];\n\tstatic const int vlmmSpec[];\n\t\n\tconst int* paramTypes;\n\tboost::shared_ptr<EmpDist const> _frag_len_dist;\n\tublas::matrix<long double> _startSeqParams;\n\tublas::matrix<long double> _startSeqExp;\n\tublas::matrix<long double> _endSeqParams;\n\tublas::matrix<long double> _endSeqExp;\n\tublas::matrix<long double> _startPosParams;\n\tublas::matrix<long double> _startPosExp;\n\tublas::matrix<long double> _endPosParams;\n\tublas::matrix<long double> _endPosExp;\n\n\tint seqToInt(const char* seqSlice, int n) const;\n\tvoid getSlice(const char* seq, char* slice, int start, int end) const;\n\tvoid genNList(const char* seqSlice, int start, int n, std::list<int>& nList) const;\n\n#if ENABLE_THREADS\t\n\tboost::mutex _bl_lock;\n#endif\n    \npublic:\n\t\n\tBiasLearner(boost::shared_ptr<EmpDist const> frag_len_dist);\n\tvoid preProcessTranscript(const Scaffold& transcript);\n\t\n\tvoid processTranscript(const std::vector<double>& startHist, const std::vector<double>& endHist, const Scaffold& transcript);\n\tvoid normalizeParameters();\n\tvoid output(FILE* output_file, const std::string& condition_name, int replicate_num) const;\n    \n\tvoid getBias(const Scaffold& transcript, std::vector<double>& startBiases, std::vector<double>& endBiases) const;\n\n};\n\nvoid learn_bias(BundleFactory& bundle_factory, BiasLearner& bl, bool progress_bar = true);\nvoid process_bundle(HitBundle& bundle, BiasLearner& bl);\n\n// Helps with the complexities of bias correction with replicates in cond_probs and eff_lens\nclass BiasCorrectionHelper{\n\t\n\tboost::shared_ptr<Scaffold> _transcript;\n    boost::unordered_map<boost::shared_ptr<ReadGroupProperties const>, int> _rg_index;\n\tint _size;\n\tbool _mapped;\n\t\n\tstd::vector<std::vector<double> > _start_biases;\n\tstd::vector<std::vector<double> > _end_biases;\n\tstd::vector<std::vector<double> > _pos_biases;\n\tstd::vector<std::vector<double> > _tot_biases_for_len;\n\tstd::vector<std::vector<double> > _start_biases_for_len;\n\tstd::vector<std::vector<double> > _end_biases_for_len;\n\t\n\tstd::vector<double> _eff_lens;\n\tstd::vector<double> _rg_masses;\n\t\n\tint add_read_group(boost::shared_ptr<ReadGroupProperties const> rgp);\t\n\tint get_index(boost::shared_ptr<ReadGroupProperties const> rgp);\n\t\npublic:\n\t\n\tBiasCorrectionHelper(boost::shared_ptr<Scaffold> transcript) \n\t{ \n\t\t_transcript = transcript;\n\t\t_mapped = false;\n\t\t_size = 0; \n\t}\n\t\n\n\tdouble get_cond_prob(const MateHit& hit);\n\t\n\tdouble get_effective_length();\n\tbool is_mapped() { return _mapped; }\n\n};\n\n#endif\n"
  },
  {
    "path": "src/bundles.cpp",
    "content": "/*\n *  bundles.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 9/6/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <list>\n#include <map>\n#include <numeric>\n#include <boost/math/distributions/binomial.hpp>\n#include <boost/crc.hpp>\n\n#include \"common.h\"\n#include \"bundles.h\"\n#include \"scaffolds.h\"\n\n#include \"abundances.h\"\n\nusing namespace std;\nusing boost::math::binomial;\n\n//struct ScaffoldSorter\n//{\n//\tScaffoldSorter(RefSequenceTable& _rt) : rt(_rt) {} \n//\tbool operator()(boost::shared_ptr<Scaffold const> lhs, boost::shared_ptr<Scaffold const> rhs)\n//\t{\n//        assert (lhs);\n//        assert (rhs);\n//\t\tconst char* lhs_name = rt.get_name(lhs->ref_id());\n//\t\tconst char* rhs_name = rt.get_name(rhs->ref_id());\n//\t\tint c = strcmp(lhs_name, rhs_name);\n//\t\tif (c != 0)\n//\t\t{\n//\t\t\treturn c < 0;\n//\t\t}\n//\t\tif (lhs->left() != rhs->left())\n//\t\t{\n//\t\t\treturn lhs->left() < rhs->left();\n//\t\t}\n//        return false;\n//\t}\n//\t\n//\tRefSequenceTable& rt;\n//};\n\nstruct ScaffoldSorter\n{\n\tScaffoldSorter(RefSequenceTable& _rt) : rt(_rt) {} \n\tbool operator()(boost::shared_ptr<Scaffold const> lhs, boost::shared_ptr<Scaffold const> rhs)\n\t{\n        //assert (lhs);\n        //assert (rhs);\n        if (!lhs || !rhs)\n            return false;\n\t\tint lhs_order = rt.observation_order(lhs->ref_id());\n        assert (lhs_order != -1);\n\t\tint rhs_order = rt.observation_order(rhs->ref_id());\n        assert (rhs_order != -1);\n\n\t\tif (lhs_order != rhs_order)\n\t\t{\n\t\t\treturn lhs_order < rhs_order;\n\t\t}\n\t\tif (lhs->left() != rhs->left())\n\t\t{\n\t\t\treturn lhs->left() < rhs->left();\n\t\t}\n        return false;\n\t}\n\t\n\tRefSequenceTable& rt;\n};\n\n//FIXME: needs refactoring\nvoid load_ref_rnas(FILE* ref_mRNA_file, \n\t\t\t\t   RefSequenceTable& rt,\n\t\t\t\t   vector<boost::shared_ptr<Scaffold> >& ref_mRNAs,\n                   boost::crc_32_type& gtf_crc_result,\n\t\t\t\t   bool loadSeqs,\n\t\t\t\t   bool loadFPKM) \n{\n\tif (loadSeqs)\n\t\tProgressBar p_bar(\"Loading reference annotation and sequence.\",0);\n    else\n        ProgressBar p_bar(\"Loading reference annotation.\",0);\n\n\tGList<GSeqData> ref_rnas;\n\t\n\t// If the RefSequenceTable already has entries, we will sort the GTF records\n\t// according to their observation order.  Otherwise, we will sort the \n\t// RefSequenceTable's records lexicographically.\n\tbool reorder_GTF_recs_lexicographically = false;\n\tif (rt.size() == 0)\n\t{\n\t  reorder_GTF_recs_lexicographically = true;\n\t}\n\n\tif (ref_mRNA_file)\n\t{\n\t\tgtf_tracking_verbose=cuff_verbose;\n\t\tread_transcripts(ref_mRNA_file, ref_rnas, gtf_crc_result, true);\n\t}\n\t\n\tint last_gseq_id = -1;\n\tGFaSeqGet* faseq = NULL;\n\tGFastaHandler gfasta(fasta_dir.c_str());\n\t// Geo groups them by chr.\n\tif (ref_rnas.Count()>0) //if any ref data was loaded\n\t{\n\t\tfor (int j = 0; j < ref_rnas.Count(); ++j) \n\t\t{    //ref data is grouped by genomic sequence\n\t\t\t//const char* name = ref_rnas[j]->gseq_name;\n\t\t\t\n\t\t\tint f = 0;\n\t\t\tint r = 0;\n\t\t\tint u  = 0;\n\t\t\tGffObj* rna_p;\n\t\t\tRefID ref_id = rt.get_id(ref_rnas[j]->gseq_name, NULL);\n\t\t\tint f_count = ref_rnas[j]->mrnas_f.Count();\n\t\t\tint r_count = ref_rnas[j]->mrnas_r.Count();\n\t\t\tint u_count = ref_rnas[j]->umrnas.Count();\n\t\t\t\n\t\t\twhile(!(f==f_count && r==r_count && u==u_count))\n\t\t\t{\t\n\t\t\t\tCuffStrand strand;\n\t\t\t\t\n\t\t\t\tif (f < f_count)\n\t\t\t\t{\n\t\t\t\t\trna_p = ref_rnas[j]->mrnas_f[f++];\n\t\t\t\t\tstrand = CUFF_FWD;\n\t\t\t\t}\n\t\t\t\telse if (r < r_count) \n\t\t\t\t{\n\t\t\t\t\trna_p = ref_rnas[j]->mrnas_r[r++];\n\t\t\t\t\tstrand = CUFF_REV;\n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t{\n\t\t\t\t\trna_p = ref_rnas[j]->umrnas[u++];\n\t\t\t\t\tstrand = CUFF_STRAND_UNKNOWN;\n\t\t\t\t}\n\n\t\t\t\tGffObj& rna = *rna_p;\n\n\t\t\t\tif (loadSeqs && rna.gseq_id != last_gseq_id) //next chromosome\n\t\t\t\t{\n\t\t\t\t\tdelete faseq;\n\t\t\t\t\tfaseq = NULL;\n\t\t\t\t\tlast_gseq_id = rna.gseq_id;\n\t\t\t\t\tfaseq = gfasta.fetch(last_gseq_id);\n\t\t\t\t\tif (faseq==NULL)\n\t\t\t\t\t{\n\t\t\t\t\t\tfprintf(stderr,\"This contig will not be bias corrected.\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvector<AugmentedCuffOp> ops;\n\t\t\t\tfor (int e = 0; e < rna.exons.Count(); ++e)\n\t\t\t\t{\n\t\t\t\t\tGffExon& ex = *(rna.exons[e]);\n\t\t\t\t\tops.push_back(AugmentedCuffOp(CUFF_MATCH, ex.start - 1, ex.end - ex.start + 1));\n\t\t\t\t\t\n\t\t\t\t\tif (e + 1 < rna.exons.Count())\n\t\t\t\t\t{\n\t\t\t\t\t\tGffExon& next_ex = *(rna.exons[e+1]);\n\t\t\t\t\t\tops.push_back(AugmentedCuffOp(CUFF_INTRON, ex.end, next_ex.start - ex.end - 1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tScaffold ref_scaff(ref_id, strand, ops, true);\n\t\t\t\t\n\t\t\t\tchar* rna_seq = 0;\n\t\t\t\tint seqlen=0;\n\t\t\t\tif (loadSeqs && faseq){ \n\t\t\t\t\trna_seq = rna.getSpliced(faseq, false, &seqlen);\n\t\t\t\t}\n\n\t\t\t\tif (rna.getID())\n\t\t\t\t\tref_scaff.annotated_trans_id(rna.getID());\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif (rna.getGeneID())\n\t\t\t\t\tref_scaff.annotated_gene_id(rna.getGeneID());\n\t\t\t\t\n\t\t\t\tif (rna.getGeneName())\n\t\t\t\t\tref_scaff.annotated_gene_name(rna.getGeneName());\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tchar* nearest_ref_match = rna.getAttr(\"nearest_ref\");\n\t\t\t\tchar* class_code = rna.getAttr(\"class_code\");\n\t\t\t\t\n\t\t\t\tif (nearest_ref_match && class_code)\n\t\t\t\t{\n\t\t\t\t\tref_scaff.nearest_ref_id(nearest_ref_match);\n\t\t\t\t\tref_scaff.nearest_ref_classcode(*class_code);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tchar* protein_id = rna.getAttr(\"p_id\");\n\t\t\t\tif (protein_id)\n\t\t\t\t\tref_scaff.annotated_protein_id(protein_id);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tchar* tss_id = rna.getAttr(\"tss_id\");\n\t\t\t\tif (tss_id)\n\t\t\t\t\tref_scaff.annotated_tss_id(tss_id);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif (loadFPKM)\n\t\t\t\t{\n\t\t\t\t\tconst char* expr = rna.getAttr(\"FPKM\");\n\t\t\t\t\tif (expr!=NULL) {\n\t\t\t\t\t\tif (expr[0]=='\"') expr++;\n\t\t\t\t\t\tref_scaff.fpkm(strtod(expr, NULL));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (loadSeqs)\n                {\n\t\t\t\t\tstring rs = (rna_seq) ? rna_seq:\"\";\n\t\t\t\t\tstd::transform(rs.begin(), rs.end(), rs.begin(), (int (*)(int))std::toupper);\n\t\t\t\t\tref_scaff.seq(rs);\n\t\t\t\t\tGFREE(rna_seq);\n\t\t\t\t}\n                \n\t\t\t\tboost::shared_ptr<Scaffold> scaff(new Scaffold());\n                *scaff = ref_scaff;\n                assert (scaff);\n\t\t\t\tref_mRNAs.push_back(scaff); \n\t\t\t}\n\t\t}\n        \n        BOOST_FOREACH (boost::shared_ptr<Scaffold> s, ref_mRNAs)\n        {\n            assert (s);\n        }\n        \n        if (reorder_GTF_recs_lexicographically)\n        {\n            rt.order_recs_lexicographically();\n        }\n        \n\t\tScaffoldSorter sorter(rt);\n\t\tsort(ref_mRNAs.begin(), ref_mRNAs.end(), sorter);\n        \n\t}\n\tdelete faseq;\n}\n\n\nint HitBundle::_next_id = 0;\n\nbool HitBundle::add_hit(const MateHit& hit)\n{\n\tif (_final)\n    {\n\t\treturn false;\n    }\n\t\n\t// Update the bounds on the span\n\tif (hit.left() < _leftmost)\n\t\t_leftmost = hit.left();\n\tif (hit.right() > _rightmost)\n\t\t_rightmost = hit.right();\n\t\n\t\n\t_hits.push_back(hit);\n\treturn true;\n}\n\nstruct HitlessScaffold\n{\n\tbool operator()(boost::shared_ptr<Scaffold> x)\n\t{\n\t\treturn x->mate_hits().empty();\n\t}\n};\n\nbool unmapped_hit(const MateHit& x)\n{\n\treturn !(x.is_mapped());\n}\n\n\nbool HitBundle::add_open_hit(boost::shared_ptr<ReadGroupProperties const> rg_props,\n                             const ReadHit* bh,\n\t\t\t\t\t\t\t bool expand_by_partner)\n{\n    assert (bh != NULL);\n    \n\t_leftmost = min(_leftmost, bh->left());\n\t_ref_id = bh->ref_id();\n    \n\tif (bh->is_singleton() || no_read_pairs)\n\t{\n\t\t_rightmost = max(_rightmost, bh->right());\n\t\tMateHit m(rg_props, bh->ref_id(), bh, NULL);\n        if (m.right() - m.left() > max_gene_length)\n        {\n            fprintf(stderr, \"Warning: hit is longer than max_gene_length, skipping\\n\");\n            return false;\n        }\n\t\tadd_hit(m);\n\t}\n\telse\n\t{\n        if (abs(bh->right() - bh->partner_pos()+1) > max_gene_length)\n        {\n            fprintf(stderr, \"Warning: hit is longer than max_gene_length, skipping\\n\");\n            return false;\n        }\n\t\tif (expand_by_partner)\n\t\t\t_rightmost = max(max(_rightmost, bh->right()), bh->partner_pos()+1);\n\t\t\n\t\tuint64_t search_key = bh->insert_id() ^ bh->left();\n\t\tstd::pair<OpenMates::iterator, OpenMates::iterator> its = _open_mates.equal_range(search_key);\n\n\t\t// Does this hit close an open mate?\n\t\tbool found_partner = false;\n\t\tfor(OpenMates::iterator it = its.first; it != its.second; ++it) {\n\t\t\n\t\t\tMateHit& pm = it->second;\n\n\t\t\tif(pm.left_alignment()->partner_pos() != bh->left())\n\t\t\t\tcontinue;\n\n\t\t\tif(pm.insert_id() != bh->insert_id())\n\t\t\t\tcontinue;\n\n\t\t\t{\n\t\t\t\t\t\n\t\t\t\tScaffold L(MateHit(rg_props, bh->ref_id(), pm.left_alignment(), NULL));\n\t\t\t\tScaffold R(MateHit(rg_props, bh->ref_id(), bh, NULL));\n\t\t\t\t\n\t\t\t\tbool strand_agree = L.strand() == CUFF_STRAND_UNKNOWN ||\n\t\t\t\t\tR.strand() == CUFF_STRAND_UNKNOWN ||\n\t\t\t\t\tL.strand() == R.strand();\n\t\t\t\t\n\t\t\t\t//bool orientation_agree = pm.left_alignment()->antisense_align() != bh->antisense_align();\n\t\t\t\t\n\t\t\t\tif (strand_agree && \n\t\t\t\t\t(!Scaffold::overlap_in_genome(L, R, olap_radius) ||\n\t\t\t\t\t Scaffold::compatible(L,R)))\n\t\t\t\t\t{\t\t\t\t\t\n\t\t\t\t\t\tpm.right_alignment(bh);\n\t\t\t\t\t\tadd_hit(pm);\n\t\t\t\t\t\t_open_mates.erase(it);\n\t\t\t\t\t\t// Boost unordered_multimap ordinarily never shrinks.\n\t\t\t\t\t\t// Compel it to do so if significantly underloaded.\n\t\t\t\t\t\tif(_open_mates.size() > _rehash_size_threshold && _open_mates.load_factor() < _rehash_threshold) {\n\t\t\t\t\t\t  _open_mates.rehash(0);\n\t\t\t\t\t\t  if(_open_mates.load_factor() < _rehash_threshold) {\n\t\t\t\t\t\t\t// It didn't shrink -- looks like this Boost implementation has a minimum\n\t\t\t\t\t\t\t// size limit, or other reason to keep the table large. Don't keep rehashing with every remove op:\n\t\t\t\t\t\t\t_rehash_size_threshold = _open_mates.size();\n\t\t\t\t\t\t  }\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfound_partner = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif(!found_partner) {\n\n\t\t\t// Add it to the list of open mates, unless we would\n\t\t\t// already have seen it's partner\n\t\t\tif(bh->left() <= bh->partner_pos())\n\t\t\t\t{\n\t\t\t\t\tMateHit open_hit(rg_props,\n\t\t\t\t\t\t\t\t\t bh->ref_id(), \n\t\t\t\t\t\t\t\t\t bh, \n\t\t\t\t\t\t\t\t\t NULL);\n\t\t\t\t\t\n\t\t\t\t\tuint64_t insert_key = bh->insert_id() ^ bh->partner_pos();\n\t\t\t\t\t_open_mates.insert(make_pair(insert_key, open_hit));\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// This should never happen during hit_driven or ref_guided bundling, and in the case of\n\t\t\t\t\t// ref_driven, this read clearly shouldn't map to any of the transcripts anyways.\n\t\t\t\t\t// Adding this hit would cause problems with multi-reads that straddle boundaries after assembly.\n\t\t\t\t\t// add_hit(MateHit(rg_props,bh->ref_id(), bh, NULL));\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t}\n\n\t}\n    return true;\n}\n\nvoid HitBundle::collapse_hits()\n{\n\t::collapse_hits(_hits, _non_redundant);\n    //_non_redundant = _hits;\n}\n\nvoid HitBundle::finalize_open_mates()\n{\n    // We don't want to split reads accross boundaries since this would only occur\n    // in ref_driven mode and the read shouldn't map to any of the references in this case.\n\n    for(OpenMates::iterator itr = _open_mates.begin(); itr != _open_mates.end(); ++itr)\n    {\n\t\tdelete itr->second.left_alignment();\n\t\tdelete itr->second.right_alignment();\n    }\n    _open_mates.clear();\n}\n\nvoid HitBundle::remove_hitless_scaffolds()\n{\n\tvector<boost::shared_ptr<Scaffold> >::iterator new_end = remove_if(_ref_scaffs.begin(),\n\t\t\t\t\t\t\t\t\t\t\t\t   _ref_scaffs.end(),\n\t\t\t\t\t\t\t\t\t\t\t\t   HitlessScaffold());\n\t_ref_scaffs.erase(new_end, _ref_scaffs.end());\t\n}\n\n\n\nvoid HitBundle::combine(const vector<HitBundle*>& in_bundles,\n                        HitBundle& out_bundle)\n{\n    out_bundle._hits.clear();\n    out_bundle._non_redundant.clear();\n    out_bundle._ref_scaffs.clear();\n    \n    for (size_t i = 1; i < in_bundles.size(); ++i)\n    {\n        assert(in_bundles[i]->ref_id() == in_bundles[i-1]->ref_id());\n    }\n    \n    // Merge  hits\n    vector<size_t> indices(in_bundles.size(),0);\n    while(true)\n    {\n        int next_bundle = -1;\n        const MateHit* next_hit=NULL; \n        for(size_t i = 0; i < in_bundles.size(); ++i)\n        {\n            const vector<MateHit>& curr_hits = in_bundles[i]->hits();\n            \n            if (indices[i] == curr_hits.size())\n                continue;\n            \n            const MateHit* curr_hit = &curr_hits[indices[i]];\n            \n            if (next_bundle == -1 || mate_hit_lt(*curr_hit, *next_hit))\n            {\n                next_bundle = i;\n                next_hit = curr_hit;\n            }\n        }\n        \n        if(next_bundle==-1)\n            break;\n        \n        out_bundle._hits.push_back(*next_hit);\n        indices[next_bundle]++;\n    }\n    \n    // Merge collapsed hits\n    indices = vector<size_t>(in_bundles.size(), 0);\n    while(true)\n    {\n        int next_bundle = -1;\n        const MateHit* next_hit = NULL; \n        for(size_t i = 0; i < in_bundles.size(); ++i)\n        {\n            const vector<MateHit>& curr_non_redundant_hits = in_bundles[i]->non_redundant_hits();\n            \n            if (indices[i] == curr_non_redundant_hits.size())\n                continue;\n            \n            const MateHit* curr_hit = &curr_non_redundant_hits[indices[i]];\n            \n            if (next_bundle == -1 || mate_hit_lt(*curr_hit, *next_hit))\n            {\n                next_bundle = i;\n                next_hit = curr_hit;\n            }\n        }\n        \n        if(next_bundle==-1)\n            break;\n        \n        out_bundle._non_redundant.push_back(*next_hit);\n        indices[next_bundle]++;\n    }\n    \n    for(size_t i = 0; i < in_bundles.size(); ++i)\n    {\n        for (size_t j = 0; j < in_bundles[i]->_ref_scaffs.size(); ++j)\n        {\n            in_bundles[i]->_ref_scaffs[j]->clear_hits();\n        }\n    }\n    \n    /*\n    // Merge ref scaffolds\n    indices = vector<size_t>(in_bundles.size(), 0);\n    while(true)\n    {\n        int next_bundle = -1;\n        boost::shared_ptr<Scaffold> next_scaff; \n        for(size_t i = 0; i < in_bundles.size(); ++i)\n        {\n            const vector<boost::shared_ptr<Scaffold> >& curr_scaffs = in_bundles[i]->_ref_scaffs;\n            \n            if (indices[i] == curr_scaffs.size())\n                continue;\n            \n            boost::shared_ptr<Scaffold> curr_scaff = curr_scaffs[indices[i]];\n            \n            if (next_bundle == -1 || scaff_lt_rt_oplt(*curr_scaff, *next_scaff))\n            {\n                next_bundle = i;\n                next_scaff = curr_scaff;\n            }\n        }\n        \n        if(next_bundle==-1)\n            break;\n        \n        if (out_bundle._ref_scaffs.size()==0 || out_bundle._ref_scaffs.back()->annotated_trans_id() != next_scaff->annotated_trans_id()) \n            out_bundle.add_ref_scaffold(next_scaff);\n        indices[next_bundle]++;\n    }\n\t*/\n    \n    for (size_t i = 0; i < in_bundles.size(); ++i)\n    {\n        for (size_t j = 0; j < in_bundles[i]->ref_scaffolds().size(); ++j)\n        {\n            out_bundle.add_ref_scaffold(in_bundles[i]->ref_scaffolds()[j]);\n        }\n    }\n    \n    sort(out_bundle._ref_scaffs.begin(), out_bundle._ref_scaffs.end(), scaff_lt_rt_oplt_sp);\n    vector<boost::shared_ptr<Scaffold> >::iterator new_end = unique(out_bundle._ref_scaffs.begin(),\n                                                             out_bundle._ref_scaffs.end(),\n                                                             StructurallyEqualScaffolds());\n    out_bundle._ref_scaffs.erase(new_end, out_bundle._ref_scaffs.end());\n    vector<boost::shared_ptr<Scaffold> >(out_bundle._ref_scaffs).swap(out_bundle._ref_scaffs);\n    \n    out_bundle.finalize(true); // true means everything is already sorted, etc.\n    out_bundle._num_replicates = (int)in_bundles.size();\n}\n\n\nvoid HitBundle::finalize(bool is_combined)\n{\n\t_final = true;\n    if (!is_combined)\n\t{\n        // only perform read skipping on primary bundles \n        // (i.e. don't do it on bundles we're making by combining two or more other bundles)\n        size_t num_skipped = _hits.size() * read_skip_fraction;\n        if (num_skipped > 0 && num_skipped < _hits.size())\n        {\n            random_shuffle(_hits.begin(), _hits.end());\n            for (int i = (int)_hits.size() - num_skipped; i >= 0 && i < (int)_hits.size(); ++i)\n            {\n                delete _hits[i].left_alignment();\n                _hits[i].left_alignment(NULL);\n                \n                delete _hits[i].right_alignment();\n                _hits[i].right_alignment(NULL);\n            }\n            _hits.resize(_hits.size() - num_skipped);\n            is_combined = false;\n        }\n        else if (num_skipped >= _hits.size())\n        {\n            for (size_t i = 0; i < _hits.size(); ++i)\n            {\n                delete _hits[i].left_alignment();\n                delete _hits[i].right_alignment();\n            }\n            _hits.clear();\n        }\n\n\t\tsort(_hits.begin(), _hits.end(), mate_hit_lt);\n        if (cond_prob_collapse)\n        {\n            collapse_hits();\n        }\n        else\n        {\n            BOOST_FOREACH (MateHit& hit, _hits)\n            {\n                hit.incr_collapse_mass(hit.internal_scale_mass());\n            }\n            _non_redundant = _hits;\n            \n        }\n\t\tsort(_ref_scaffs.begin(), _ref_scaffs.end(), scaff_lt_rt_oplt_sp);\n\t\tvector<boost::shared_ptr<Scaffold> >::iterator new_end = unique(_ref_scaffs.begin(), \n\t\t\t\t\t\t\t\t\t\t\t\t_ref_scaffs.end(),\n\t\t\t\t\t\t\t\t\t\t\t\tStructurallyEqualScaffolds());\n\t\t_ref_scaffs.erase(new_end, _ref_scaffs.end());\n        vector<boost::shared_ptr<Scaffold> >(_ref_scaffs).swap(_ref_scaffs);\n\t}\n\t\n    for (size_t j = 0; j < _ref_scaffs.size(); ++j)\n\t{\n\t\t_ref_scaffs[j]->clear_hits();\n\t}\n    \n    _compatible_mass = 0.0;\n    \n\tfor (size_t i = 0; i < _hits.size(); ++i)\n\t{\n\t\tMateHit& hit = _hits[i];\n\t\t\n\t\tScaffold hs(hit);\n\t\t\n        if (i >= 1)\n        {\n            assert (hit.ref_id() == _hits[i-1].ref_id());\n        }\n\t\thit.is_mapped(false);\n\t\tfor (size_t j = 0; j < _ref_scaffs.size(); ++j)\n\t\t{\n\t\t\t// add hit only adds if the hit is structurally compatible\n\t\t\tif (_ref_scaffs[j]->contains(hs))\n\t\t\t{\n\t\t\t\tbool added = _ref_scaffs[j]->add_hit(&hit);\n                if (added)\n                    hit.is_mapped(true);\n\t\t\t}\n\t\t}\n        if (hit.is_mapped())\n        {\n            _compatible_mass += hit.internal_scale_mass();\n        }\n\t}\n    \n}\n\nvoid print_sort_error(const char* last_chr_name, \n                      int last_chr_pos, \n                      const char* bh_name, \n                      int bh_pos)\n{\n    fprintf(stderr, \"\\nError: this SAM file doesn't appear to be correctly sorted!\\n\");\n    fprintf(stderr, \"\\tcurrent hit is at %s:%d, last one was at %s:%d\\n\", \n            bh_name,\n            bh_pos,\n            last_chr_name,\n            last_chr_pos);\n    fprintf(stderr, \"Cufflinks requires that if your file has SQ records in\\nthe SAM header that they appear in the same order as the chromosomes names \\nin the alignments.\\nIf there are no SQ records in the header, or if the header is missing,\\nthe alignments must be sorted lexicographically by chromsome\\nname and by position.\\n \\n\");\n}\n\n\ndouble BundleFactory::next_valid_alignment(const ReadHit*& bh)\n{\n    bh = NULL;\n    \n\t// Keep track of mass of hits we skip\n\tdouble raw_mass = 0; \n\t\n    while (_hit_fac->records_remain())\n    {\n        ReadHit tmp;\n        if (!_hit_fac->next_hit(tmp))\n            continue;\n        \n\t\tif (tmp.ref_id() == 12638153115695167477)  // corresponds to SAM \"*\" under FNV hash. unaligned read record \n            continue;\n        \n\t\traw_mass += tmp.mass();\n\t\t\n        if (_hit_fac->ref_table().get_name(tmp.ref_id())==NULL) // unaligned read record (!?)\n            continue;\n            \n        if (spans_bad_intron(tmp))\n            continue;\n\n\t\t// Check for reads with no matching CIGAR entries. Generally such a read should have been rejected\n\t\t// as unmapped, but such records have been seen in the wild. If they were allowed to stay they would cause\n\t\t// trouble when converted to Scaffolds, yielding an invalid aug_ops vector.\n\t\tconst vector<CigarOp>& cig = tmp.cigar();\n\t\tbool found_match = false;\n\t\tfor(vector<CigarOp>::const_iterator it = cig.begin(), itend = cig.end(); it != itend && !found_match; ++it)\n\t\t\tif(it->opcode == MATCH)\n\t\t\t\tfound_match = true;\n\n\t\tif(!found_match) {\n\t\t\tfprintf(stderr, \"Skipping hit with no Match operators in its CIGAR string\\n\");\n\t\t\tcontinue;\n\t\t}\n        \n        int order = _hit_fac->ref_table().observation_order(tmp.ref_id());\n        if (_prev_pos != 0)\n        {\n            int prev_order = _hit_fac->ref_table().observation_order(_prev_ref_id);\n            \n            if (prev_order > order || (prev_order == order && _prev_pos > tmp.left()))\n            {\n                const char* bh_chr_name = _hit_fac->ref_table().get_name(tmp.ref_id());\n                const char* last_bh_chr_name = _hit_fac->ref_table().get_name(_prev_ref_id);\n                                \n                print_sort_error(last_bh_chr_name, \n                                 _prev_pos, \n                                 bh_chr_name, \n                                 tmp.left());\n                exit(1);\n            }\n        }\n        \n        _prev_ref_id = tmp.ref_id();\n        _prev_pos = tmp.left();\n        \n        bool hit_within_mask = false;\n        \n        // We want to skip stuff that overlaps masked GTF records, so \n        // sync up the masking chromosome\n        if (!mask_gtf_recs.empty() && \n            next_mask_scaff != mask_gtf_recs.end() &&\n            (*next_mask_scaff)->ref_id() != tmp.ref_id())\n        {\n            bool found_scaff = false;\n            vector<boost::shared_ptr<Scaffold> >::iterator curr_mask_scaff = mask_gtf_recs.begin();\n            for (size_t i = 0; i < _mask_scaff_offsets.size(); ++i)\n            {\n                if (_mask_scaff_offsets[i].first == tmp.ref_id())\n                {\n                    curr_mask_scaff = _mask_scaff_offsets[i].second;\n                    found_scaff = true;\n                    break;\n                }\n            }\n            \n            next_mask_scaff = curr_mask_scaff;\n        }\n        \n        //check that we aren't sitting in the middle of a masked scaffold\n        while (next_mask_scaff != mask_gtf_recs.end() && \n               (*next_mask_scaff)->ref_id() == tmp.ref_id() &&\n               (*next_mask_scaff)->right() <= tmp.left())\n        {\n            if ((*next_mask_scaff)->left() >= tmp.left())\n            {\n                break;\n            }\n            \n            next_mask_scaff++;\n        }\n        \n        if (next_mask_scaff != mask_gtf_recs.end() &&\n            (*next_mask_scaff)->ref_id() == tmp.ref_id() &&\n            (*next_mask_scaff)->left() <= tmp.left() &&\n            (*next_mask_scaff)->right() >= tmp.right())\n        {\n            hit_within_mask = true;\n        }\n        \n        if (hit_within_mask)\n            continue;\n\n        // if the user's asked for read trimming, do it here.\n        if (trim_read_length > 0)\n        {\n            tmp.trim(trim_read_length);\n        }\n        \n        bh = new ReadHit(tmp);\n        \n        break;\n    }\n    \n    return raw_mass;\n}\n\ndouble BundleFactory::rewind_hit(const ReadHit* rh)\n{\n\tdouble mass = rh->mass();\n\tdelete rh;\n\t_hit_fac->undo_hit();\n\treturn mass;\n}\n\nbool BundleFactory::next_bundle_hit_driven(HitBundle& bundle)\n{\n\tconst ReadHit* bh = NULL;\n    \n    bool skip_read = false;\n    \n\twhile(bh == NULL)\n\t{\n\t\tif (!_hit_fac->records_remain())\n\t\t{\n\t\t\treturn false;\n\t\t}\n        \n        // If we are randomly throwing out reads, check to see\n        // whether this one should be kept.\n        if (bundle.hits().size() >= max_frags_per_bundle)\n        {\n            skip_read = true;\n            next_valid_alignment(bh);\n        }\n        else\n        {\n            double raw_mass = next_valid_alignment(bh);\n            if (bh && bh->num_hits() > max_frag_multihits)\n            {\n                skip_read = true;\n            }\n            else\n            {\n                bundle.add_raw_mass(raw_mass);\n            }\n        }\n\t}\n\t\n\tif ((skip_read || !bundle.add_open_hit(read_group_properties(), bh)) && bh != NULL)\n    {\n        delete bh;\n        bh = NULL;\n    }\n\t_expand_by_hits(bundle);\n\n    assert(bundle.left() != -1);    \n\tbundle.finalize_open_mates();\n\tbundle.finalize();\n    assert(bundle.right() != -1);\n    \n    return true;\n}\n\nbool BundleFactory::next_bundle_ref_driven(HitBundle& bundle)\n{\n\tif (next_ref_scaff == ref_mRNAs.end())\n\t{\n\t\tconst ReadHit* bh = NULL;\n\t\twhile(_hit_fac->records_remain())\n\t\t{\n            double raw_mass = next_valid_alignment(bh);\n            if (bundle.hits().size() < max_frags_per_bundle)\n            {\n                if (bh && bh->num_hits() > max_frag_multihits)\n                {\n                    \n                }\n                else\n                {\n                    bundle.add_raw_mass(raw_mass);\n                }\n                if (bh) { delete bh; }\n            }\n            else\n            {\n                delete bh;\n                bh = NULL;\n            }\n\t\t    \n\t\t}\n\t\tbundle.finalize();\n\t\treturn false;\n\t}\n\t\n\tbundle.add_ref_scaffold(*next_ref_scaff);\n    \n\t++next_ref_scaff;\n    \n\t_expand_by_refs(bundle);\n    \n//    for (size_t i = 0; i < bundle.ref_scaffolds().size(); ++i)\n//    {\n//        boost::shared_ptr<Scaffold> s = bundle.ref_scaffolds()[i];\n//        if (s->annotated_gene_id() == \"ERCC-00002\")\n//        {\n//                int a = 4;\n//        }\n//    }\n\n    \n\t// The most recent RefID and position we've seen in the hit stream\n\tRefID last_hit_ref_id_seen = 0;\n\tint last_hit_pos_seen = 0;\n\t\n\t// include hits that lay within the bundle interval\n\twhile(true)\n\t{\t\t\n\t\tconst ReadHit* bh = NULL;\n        \n        bool skip_read = false;\n\t\t// If we are randomly throwing out reads, check to see\n        // whether this one should be kept.\n        if (bundle.hits().size() >= max_frags_per_bundle)\n        {\n            next_valid_alignment(bh);\n            skip_read = true;\n        }\n        else\n        {\n            double raw_mass = next_valid_alignment(bh);\n            if (bh && bh->num_hits() > max_frag_multihits)\n            {\n                skip_read = true;\n            }\n            else\n            {\n                bundle.add_raw_mass(raw_mass);\n            }\n        }\n        \n        if (bh == NULL)\n        {\n\t\t\tif (_hit_fac->records_remain())\n\t\t\t\tcontinue;\n\t\t\telse\n\t\t\t\tbreak;\n        }\n        \n\t\tlast_hit_ref_id_seen = bh->ref_id();\n\t\tlast_hit_pos_seen = bh->left();\n\t\t\n\t\t// test if the hit stream needs to catch up or has gone too far based on ref_id\n\t\tif (bh->ref_id() != bundle.ref_id())\n\t\t{\n\t\t\tint bh_chr_order = _hit_fac->ref_table().observation_order(bh->ref_id());\n\t\t\tint bundle_chr_order = _hit_fac->ref_table().observation_order(bundle.ref_id());\n\t\t\t\n\t\t\tif (bh_chr_order < bundle_chr_order) // the hit stream has not caught up, skip\n\t\t\t{\n\t\t\t\tdelete bh;\n                bh = NULL;\n\t\t\t\tcontinue; \n\t\t\t}\n\t\t\telse // the hit stream has gone too far, rewind and break\n\t\t\t{\n                rewind_hit(bh);\n                bh = NULL;\n                break;\n\t\t\t}\n\t\t}\n        \n        if (bh == NULL) // the hit stream has gone too far, break\n            break;\n\t\t\n        if (bh->left() >= bundle.left() && bh->right() <= bundle.right())\n\t\t{\n            if (skip_read)\n            {\n                delete bh;\n                bh = NULL;\n            }\n\t\t\telse\n            {\n                if (!bundle.add_open_hit(read_group_properties(), bh, false))\n                {\n                    delete bh;\n                    bh = NULL;\n                }\n            }\n\t\t}\n\t\telse if (bh->left() >= bundle.right())\n\t\t{\n            if (skip_read == false)\n            {\n                bundle.rem_raw_mass(rewind_hit(bh));\n                bh = NULL;\n            }\n            else\n            {\n                delete bh;\n                bh = NULL;\n            }\n\t\t\tbreak;\n\t\t}\n\t    else\n        {\n            // It's not within the bundle bounds, but it's also not past the \n            // right end, so skip it.\n            delete bh;\n            bh = NULL;\n        }\n        \n        if (skip_read == true && bh != NULL)\n        {\n            delete bh;\n            bh = NULL;\n        }\n\t}\n\t\n    assert(bundle.left() != -1);\n    bundle.finalize_open_mates();\n\tbundle.finalize();\n    assert(bundle.right() != -1);\n    \n    return true;\n}\n\n// NOTE: does not support read skipping yet or max hits per bundle yet.\nbool BundleFactory::next_bundle_ref_guided(HitBundle& bundle)\n{\n\t\n\tif (next_ref_scaff == ref_mRNAs.end())\n\t{\n\t\treturn next_bundle_hit_driven(bundle);\n\t}\n\t\n\tconst ReadHit* bh = NULL;\n\twhile(bh == NULL)\n\t{\n\t\tif (!_hit_fac->records_remain())\n\t\t{\n\t\t\treturn next_bundle_ref_driven(bundle);\n\t\t}\n\t\tbundle.add_raw_mass(next_valid_alignment(bh));\n\t}\n\t\n\tif (bh->ref_id() != (*next_ref_scaff)->ref_id())\n\t{\n\t\tint bh_chr_order = _hit_fac->ref_table().observation_order(bh->ref_id());\n\t\tint scaff_chr_order = _hit_fac->ref_table().observation_order((*next_ref_scaff)->ref_id());\n\t\t\n\t\tbundle.rem_raw_mass(rewind_hit(bh));\n\t\tbh = NULL;\n        \n\t\tif (bh_chr_order < scaff_chr_order)\n\t\t{\n\t\t\treturn next_bundle_hit_driven(bundle);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn next_bundle_ref_driven(bundle);\n\t\t}\n\t}\n\t\t\n\tif (bh->left() < (*next_ref_scaff)->left())\n\t{\n\t\tif (!bundle.add_open_hit(read_group_properties(), bh))\n        {\n            delete bh;\n            bh = NULL;\n        }\n\t}\n\telse \n\t{\n\t\tbundle.rem_raw_mass(rewind_hit(bh));\n        bh = NULL;\n        \n\t\tbundle.add_ref_scaffold(*next_ref_scaff);\n\t\tnext_ref_scaff++;\n\t\t_expand_by_refs(bundle);\n\t}\n\t\n\twhile(_expand_by_hits(bundle) || \n\t\t  _expand_by_refs(bundle)) {}\n\t\n\tassert(bundle.left() != -1);    \n\tbundle.finalize_open_mates();\n\tbundle.finalize();\n\tassert(bundle.right() != -1);\n\t\n\treturn true; \n}\n\n// expand the bundle interval as far as needed to include the overlapping\n// chain of reference transcripts that also overlap the initial bundle\n// interval\nbool BundleFactory::_expand_by_refs(HitBundle& bundle)\n{\n\tint initial_right = bundle.right();\n\twhile(next_ref_scaff < ref_mRNAs.end())\n\t{\t\t\n\t\tassert(bundle.ref_id() != (*next_ref_scaff)->ref_id() || (*next_ref_scaff)->left() >= bundle.left());\n//        if (*next_ref_scaff && (*next_ref_scaff)->annotated_gene_id() == \"XLOC_009372\")\n//        {\n//            int a = 5;\n//        }\n\t\tif (bundle.ref_id() == (*next_ref_scaff)->ref_id()\n\t\t\t&& overlap_in_genome((*next_ref_scaff)->left(),(*next_ref_scaff)->right(),bundle.left(), bundle.right()))\n\t\t{\n\t\t\tbundle.add_ref_scaffold(*next_ref_scaff);\n            next_ref_scaff++;\n\t\t}\n\t\telse \n\t\t{\n\t\t\tbreak;\n\t\t}\t\t\n\t}\n\n\t\n\treturn (bundle.right() > initial_right);\n}\n\n// expand bundle by chaining overlapping hits\nbool BundleFactory::_expand_by_hits(HitBundle& bundle)\n{\n\tint initial_right = bundle.right();\n\twhile(true)\n\t{\n        bool skip_read = false;\n        const ReadHit* bh = NULL;\n        \n        double raw_mass = next_valid_alignment(bh);\n        if (bh && bh->num_hits() > max_frag_multihits)\n        {\n            skip_read = true;\n        }\n        else\n        {\n            bundle.add_raw_mass(raw_mass);\n        }\n\n\t\tif (bh == NULL)\n\t\t{\n\t\t\tif (_hit_fac->records_remain())\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\t\n\t\t}\n\t\t\n\t\tif (bh->ref_id() == bundle.ref_id() && bh->left() < bundle.right() + olap_radius)\n\t\t{\t\t\t\n\t\t\tif (skip_read || !bundle.add_open_hit(read_group_properties(), bh))\n            {\n                delete bh;\n                bh = NULL;\n            }\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbundle.rem_raw_mass(rewind_hit(bh));\n\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\treturn (bundle.right() > initial_right);\n}\n\nbool BundleFactory::next_bundle(HitBundle& bundle, bool cache_bundle)\n{    \n#if ENABLE_THREADS\n    boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n    bool got_bundle = false;\n\tswitch(_bundle_mode)\n\t{\n\t\tcase HIT_DRIVEN:\n            _curr_bundle++;\n\t\t\tgot_bundle = next_bundle_hit_driven(bundle);\n            bundle.id(_curr_bundle);\n\t\t\tbreak;\n\t\tcase REF_DRIVEN:\n            _curr_bundle++;\n\t\t\tgot_bundle = next_bundle_ref_driven(bundle);\n            bundle.id(_curr_bundle);\n\t\t\tbreak;\n\t\tcase REF_GUIDED:\n            _curr_bundle++;\n\t\t\tgot_bundle = next_bundle_ref_guided(bundle);\n            bundle.id(_curr_bundle);\n\t\t\tbreak;\n\t}\n\treturn got_bundle;\n}\n\n\nstruct IntronSpanCounter\n{\n\tIntronSpanCounter() : left_reads(0), little_reads(0), total_reads(0), multimap_reads(0), fwd_strand_frags(0) {}\n\tsize_t left_reads;\n\tsize_t little_reads; // small span overhang\n\tsize_t total_reads;\n\tsize_t multimap_reads;\n    size_t fwd_strand_frags;\n\tvector<size_t> hist;\n};\n\ntypedef map<AugmentedCuffOp, IntronSpanCounter> IntronCountTable;\n\nvoid count_introns_in_read(const ReadHit& read,\n\t\t\t\t\t\t   IntronCountTable& intron_counts)\n{\n\tconst vector<CigarOp>& cig = read.cigar();\n\t\n\tint read_len = read.read_len();\n\tint small_anchor = (int)floor(read_len * small_anchor_fraction);\n\t\n\tint r_left = 0;\n\tint g_left = read.left();\n\t\n\tfor (size_t i = 0; i < cig.size(); ++i)\n\t{\n\t\tassert(cig[i].length >= 0);\n\t\tswitch(cig[i].opcode)\n\t\t{\n\t\t\tcase MATCH:\n\t\t\t\t//ops.push_back(AugmentedCuffOp(CUFF_MATCH, g_left, cig[i].length));\n\t\t\t\tg_left += cig[i].length;\n\t\t\t\tr_left += cig[i].length;\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase REF_SKIP:\n\t\t\t{\t\n\t\t\t\tAugmentedCuffOp intron(CUFF_INTRON, g_left, cig[i].length);\n\t\t\t\tpair<IntronCountTable::iterator, bool> ins_itr;\n\t\t\t\tins_itr = intron_counts.insert(make_pair(intron, IntronSpanCounter()));\n\t\t\t\tIntronCountTable::iterator itr = ins_itr.first;\n\t\t\t\titr->second.total_reads++;\n\t\t\t\t\n\t\t\t\tif (read.num_hits() > 10)\n\t\t\t\t{\n\t\t\t\t\titr->second.multimap_reads++;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( r_left <= small_anchor || (read_len - r_left) < small_anchor)\n\t\t\t\t{\n\t\t\t\t\titr->second.little_reads++;\n\t\t\t\t}\n                \n                if (read.source_strand() == CUFF_FWD)\n                {\n                    //itr->second.fwd_strand_frags;\n                }\n                else \n                {\n                    assert(read.source_strand() == CUFF_REV);\n                }\n\n\t\t\t\t\n\t\t\t\tvector<size_t>& hist = itr->second.hist;\n\t\t\t\tif (hist.size() < (size_t)read_len)\n\t\t\t\t{\n\t\t\t\t\tsize_t num_new_bins = read_len - hist.size();\n\t\t\t\t\tsize_t new_left_bins = (size_t)floor(num_new_bins / 2.0);\n\t\t\t\t\tsize_t new_right_bins = (size_t)ceil(num_new_bins / 2.0);\n\t\t\t\t\thist.insert(hist.begin(), new_left_bins, 0);\n\t\t\t\t\thist.insert(hist.end(), new_right_bins, 0);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tassert (r_left < hist.size());\n\t\t\t\thist[r_left]++;\n\t\t\t\t//ops.push_back(AugmentedCuffOp(CUFF_INTRON, g_left, cig[i].length));\n\t\t\t\tg_left += cig[i].length;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\t\n\t\t\tcase SOFT_CLIP:\n\t\t\t\tg_left += cig[i].length;\n\t\t\t\tbreak;\n            case HARD_CLIP:\n\t\t\t\tbreak;\n            case INS:\n                g_left -= cig[i].length;\n                break;\n            case DEL:\n                g_left += cig[i].length;\n                break;\n\t\t\tdefault:\n\t\t\t\tassert(false);\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid minor_introns(int bundle_length,\n\t\t\t\t   int bundle_left,\n\t\t\t\t   const IntronCountTable& intron_counts,\n\t\t\t\t   vector<AugmentedCuffOp>& bad_introns,\n\t\t\t\t   double fraction)\n\n{\n\tfor(IntronCountTable::const_iterator itr = intron_counts.begin();\n\t\titr != intron_counts.end(); \n\t\t++itr)\n\t{\n\t\tpair<AugmentedCuffOp, IntronSpanCounter> itr_cnt_pair = *itr;\n\t\tconst IntronSpanCounter itr_spans = itr_cnt_pair.second;\n\t\t\n\t\tdouble doc = itr_spans.total_reads;\n\t\t\n\t\tfor (IntronCountTable::const_iterator itr2 = intron_counts.begin();\n\t\t\t itr2 != intron_counts.end(); \n\t\t\t ++itr2)\n\t\t{\t\n\t\t\tif (itr == itr2 ||\n\t\t\t\t!AugmentedCuffOp::overlap_in_genome(itr->first, itr2->first))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t\n\t\t\tpair<AugmentedCuffOp, IntronSpanCounter> itr2_cnt_pair = *itr2;\n\t\t\tconst IntronSpanCounter itr2_spans = itr2_cnt_pair.second;\n\t\t\t\n\t\t\tdouble thresh = itr2_spans.total_reads * fraction;\n\t\t\tif (doc < thresh)\n\t\t\t{\n\t\t\t\t//#if verbose_msg\n\t\t\t\t//\t\t\t\t\t\t\tfprintf(stderr, \"\\t Filtering intron (due to overlap) %d - %d: %f thresh %f\\n\", itr->first.first, itr->first.second, doc, bundle_avg_thresh);\n\t\t\t\t//#endif\t\n\t\t\t\tbool exists = binary_search(bad_introns.begin(), \n\t\t\t\t\t\t\t\t\t\t\tbad_introns.end(), \n\t\t\t\t\t\t\t\t\t\t\titr->first);\n\t\t\t\tif (!exists)\n\t\t\t\t{\n\t\t\t\t\tverbose_msg(\"Filtering intron %d-%d spanned by %lu reads based on overlap with much more abundant intron: %d-%d spanned by %lu reads\\n\", \n\t\t\t\t\t\t\titr->first.g_left(), \n\t\t\t\t\t\t\titr->first.g_right(), \n\t\t\t\t\t\t\titr->second.total_reads,\n\t\t\t\t\t\t\titr2->first.g_left(), \n\t\t\t\t\t\t\titr2->first.g_right(), \n\t\t\t\t\t\t\titr2->second.total_reads);\n\t\t\t\t\t\n\t\t\t\t\tbad_introns.push_back(itr->first);\n\t\t\t\t\tsort(bad_introns.begin(), bad_introns.end());\n\t\t\t\t}\n\t\t\t}\n            \n//            if ((itr->second.fwd_strand_frags == 0 &&\n//                 itr2->second.fwd_strand_frags != 0) ||\n//                (itr2->second.fwd_strand_frags == 0 &&\n//                 itr->second.fwd_strand_frags != 0))\n//            {\n//                int itr1_L = itr->first.g_left();\n//                int itr1_R = itr->first.g_right();\n//                int itr2_L = itr2->first.g_left();\n//                int itr2_R = itr2->first.g_right();\n//                \n//                if (abs(itr1_L - itr2_L) < 25 && abs(itr1_R - itr2_R) < 25)\n//                {\n//                    int a = 3;\n//                }\n//            }\n\t\t}\n\t}\n}\n\nvoid multimapping_introns(int bundle_length,\n\t\t\t\t\t\t  int bundle_left,\n\t\t\t\t\t\t  const IntronCountTable& intron_counts,\n\t\t\t\t\t\t  vector<AugmentedCuffOp>& bad_introns,\n\t\t\t\t\t\t  double fraction)\n\n{\n\tfor(IntronCountTable::const_iterator itr = intron_counts.begin();\n\t\titr != intron_counts.end(); \n\t\t++itr)\n\t{\n\t\tpair<AugmentedCuffOp, IntronSpanCounter> itr_cnt_pair = *itr;\n\t\tconst IntronSpanCounter itr_spans = itr_cnt_pair.second;\n\t\t\n\t\tdouble doc = itr_spans.total_reads;\n\t\tdouble multi = itr_spans.multimap_reads;\n\t\t\n\t\tdouble multi_fraction = multi / doc;\n\t\t\n\t\tif (multi_fraction > fraction)\n\t\t{\n\t\t\tbool exists = binary_search(bad_introns.begin(), \n\t\t\t\t\t\t\t\t\t\tbad_introns.end(), \n\t\t\t\t\t\t\t\t\t\titr->first);\n\t\t\tif (!exists)\n\t\t\t{\n\t\t\t\tverbose_msg(\"Filtering intron %d-%d spanned by %lu reads because %lg percent are multireads.\\n\", \n\t\t\t\t\t\titr->first.g_left(), \n\t\t\t\t\t\titr->first.g_right(), \n\t\t\t\t\t\titr->second.total_reads,\n\t\t\t\t\t\tmulti_fraction * 100);\n\t\t\t\t\n\t\t\t\tbad_introns.push_back(itr->first);\n\t\t\t\tsort(bad_introns.begin(), bad_introns.end());\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid identify_bad_splices(const HitBundle& bundle, \n\t\t\t\t\t\t  BadIntronTable& bad_splice_ops)\n{\n\t// Tracks, for each intron, how many reads\n\tIntronCountTable intron_counts;\n\t\n\tRefID ref_id = bundle.ref_id();\n\t\n\tpair<BadIntronTable::iterator, bool> ins_itr;\n\tins_itr = bad_splice_ops.insert(make_pair(ref_id, vector<AugmentedCuffOp>()));\n\tvector<AugmentedCuffOp>& bad_introns = ins_itr.first->second;\n\t\n\tBOOST_FOREACH (const MateHit& hit, bundle.hits())\n\t{\n\t\tif (hit.left_alignment())\n\t\t{\n\t\t\tcount_introns_in_read(*hit.left_alignment(), intron_counts);\n\t\t}\n\t\tif (hit.right_alignment())\n\t\t{\n\t\t\tcount_introns_in_read(*hit.right_alignment(), intron_counts);\n\t\t}\n\t}\n\t\n\tminor_introns(bundle.length(), bundle.left(), intron_counts, bad_introns, min_isoform_fraction);\n\t// [Geo] disable filtering of multi-mapped introns:\n  // multimapping_introns(bundle.length(), bundle.left(), intron_counts, bad_introns, 0.5);\n\tfor (IntronCountTable::iterator itr = intron_counts.begin();\n\t\t itr != intron_counts.end();\n\t\t ++itr)\n\t{\n\t\tif (binary_search(bad_introns.begin(), \n\t\t\t\t\t\t  bad_introns.end(), \n\t\t\t\t\t\t  itr->first))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t\tpair<AugmentedCuffOp, IntronSpanCounter> cnt_pair = *itr;\n\t\ttry\n\t\t{\n\t\t\tconst IntronSpanCounter spans = cnt_pair.second;\n\t\t\t\n\t\t\t//\t\t\tbinomial read_half_dist(spans.total_reads, success_fraction);\n\t\t\t//\t\t\tdouble left_side_p = cdf(read_half_dist, spans.total_reads - spans.left_reads);\n\t\t\t//\t\t\tdouble right_side_p = cdf(complement(read_half_dist, spans.left_reads));\n\t\t\t\n\t\t\t\n\t\t\tdouble success = 2 * small_anchor_fraction;\n\t\t\t\n\t\t\tbinomial read_half_dist(spans.total_reads, success);\n\t\t\tdouble right_side_p;\n\t\t\t\n\t\t\t// right_side_p describes the chance that we'd observe at least \n\t\t\t// this many small overhang reads by chance with an unbiased \n\t\t\t// distribution over a normal (e.g. non-artifact) junction\n\t\t\tif (spans.little_reads > 0)\n\t\t\t{\n\t\t\t\tright_side_p = 1.0 - cdf(read_half_dist, spans.little_reads - 1);\n\t\t\t}\n\t\t\telse \n\t\t\t{\n\t\t\t\tright_side_p = 1.0;\n\t\t\t}\n\t\t\t\n\t\t\tdouble left_side_p = 0;\n\t\t\tdouble expected = success * spans.total_reads;\n\n            //double excess = spans.little_reads - expected;\n\t\t\t\n\t\t\t// left_side_p describes the chance that we'd observe this few or\n\t\t\t// fewer small overhang reads by chance with an unbiased \n\t\t\t// distribution over a normal (e.g. non-artifact) junction\n\t\t\tif (spans.little_reads > 0)\n\t\t\t{\n\t\t\t\tleft_side_p = cdf(read_half_dist, spans.little_reads);\n\t\t\t}\n\t\t\telse \n\t\t\t{\n\t\t\t\tleft_side_p = cdf(read_half_dist, 0);\n\t\t\t}\n\t\t\t\n\t\t\t//double alpha = 0.05;\n\t\t\t//double right_side_p = 0;\n\t\t\t\n\t\t\t// Two-tailed binomial test:\n//\t\t\tif (left_side_p < (binomial_junc_filter_alpha / 2.0) || \n//\t\t\t\tright_side_p < (binomial_junc_filter_alpha / 2.0))\n\t\t\t// One-tailed binomial test\n\t\t\t\n\t\t\tbool filtered = false;\n\t\t\t\n\t\t\tconst IntronSpanCounter& counter = itr->second;\n\t\t\t\n\t\t\tif (right_side_p < (binomial_junc_filter_alpha))\n\t\t\t{\n\t\t\t\tdouble overhang_ratio = counter.little_reads / (double) counter.total_reads;\n\t\t\t\tif (counter.total_reads < 100 || overhang_ratio >= 0.50)\n\t\t\t\t{\n\t\t\t\t\tverbose_msg(\"Filtering intron %d-%d spanned by %lu reads (%lu low overhang, %lg expected) left P = %lg, right P = %lg\\n\", \n\t\t\t\t\t\t\titr->first.g_left(), \n\t\t\t\t\t\t\titr->first.g_right(), \n\t\t\t\t\t\t\titr->second.total_reads, \n\t\t\t\t\t\t\titr->second.little_reads, \n\t\t\t\t\t\t\texpected,\n\t\t\t\t\t\t\tleft_side_p,\n\t\t\t\t\t\t\tright_side_p);\n\t\t\t\t\tfiltered = true;\n\t\t\t\t\t\n\t\t\t\t\tbool exists = binary_search(bad_introns.begin(), \n\t\t\t\t\t\t\t\t\t\t\t\tbad_introns.end(), \n\t\t\t\t\t\t\t\t\t\t\t\titr->first);\n\t\t\t\t\tif (!exists)\n\t\t\t\t\t{\n\t\t\t\t\t\tbad_introns.push_back(itr->first);\n\t\t\t\t\t\tsort(bad_introns.begin(), bad_introns.end());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvector<size_t> hist = itr->second.hist;\n\t\t\tif (itr->second.total_reads > 1000)\n\t\t\t{\n\t\t\t\tsort(hist.begin(), hist.end());\n\t\t\t\tsize_t median = (size_t)floor(hist.size() / 2);\n\t\t\t\tif (median <= hist.size() && hist[median] == 0)\n\t\t\t\t{\n\t\t\t\t\tverbose_msg(\"Filtering intron %d-%d spanned by %lu reads (%lu low overhang, %lg expected) left P = %lg, right P = %lg\\n\", \n\t\t\t\t\t\t\titr->first.g_left(), \n\t\t\t\t\t\t\titr->first.g_right(), \n\t\t\t\t\t\t\titr->second.total_reads, \n\t\t\t\t\t\t\titr->second.little_reads, \n\t\t\t\t\t\t\texpected,\n\t\t\t\t\t\t\tleft_side_p,\n\t\t\t\t\t\t\tright_side_p);\n\t\t\t\t\t\n\t\t\t\t\tfiltered = true;\n\t\t\t\t\t\n\t\t\t\t\tbool exists = binary_search(bad_introns.begin(), \n\t\t\t\t\t\t\t\t\t\t\t\tbad_introns.end(), \n\t\t\t\t\t\t\t\t\t\t\t\titr->first);\n\t\t\t\t\tif (!exists)\n\t\t\t\t\t{\n\t\t\t\t\t\tbad_introns.push_back(itr->first);\n\t\t\t\t\t\tsort(bad_introns.begin(), bad_introns.end());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (!filtered)\n\t\t\t{\n\t\t\t\tverbose_msg(\"Accepting intron %d-%d spanned by %lu reads (%lu low overhang, %lg expected) left P = %lg, right P = %lg\\n\", \n\t\t\t\t\t\titr->first.g_left(), \n\t\t\t\t\t\titr->first.g_right(), \n\t\t\t\t\t\titr->second.total_reads, \n\t\t\t\t\t\titr->second.little_reads, \n\t\t\t\t\t\texpected,\n\t\t\t\t\t\tleft_side_p,\n\t\t\t\t\t\tright_side_p);\n\t\t\t\t\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\tcatch(const std::exception& e)\n\t\t{\n\t\t\t//\n\t\t\t/*`\n\t\t\t [#coinflip_eg_catch]\n\t\t\t It is always essential to include try & catch blocks because\n\t\t\t default policies are to throw exceptions on arguments that\n\t\t\t are out of domain or cause errors like numeric-overflow.\n\t\t\t \n\t\t\t Lacking try & catch blocks, the program will abort, whereas the\n\t\t\t message below from the thrown exception will give some helpful\n\t\t\t clues as to the cause of the problem.\n\t\t\t */\n\t\t\tstd::cout <<\n\t\t\t\"\\n\"\"Message from thrown exception was:\\n   \" << e.what() << std::endl;\n\t\t}\n\t\t\n\t}\n}\n\nbool BundleFactory::spans_bad_intron(const ReadHit& read)\n{\n\n\tconst vector<CigarOp>& cig = read.cigar();\n\t\n\tsize_t g_left = read.left();\n\tBadIntronTable::const_iterator itr = _bad_introns.find(read.ref_id());\n\tif (itr == _bad_introns.end())\n\t\treturn false;\n\t\n\tconst vector<AugmentedCuffOp>& bi = itr->second; \n\tfor (size_t i = 0; i < cig.size(); ++i)\n\t{\n\t\tassert(cig[i].length >= 0);\n\t\tswitch(cig[i].opcode)\n\t\t{\n\t\t\tcase MATCH:\n\t\t\t\t//ops.push_back(AugmentedCuffOp(CUFF_MATCH, g_left, cig[i].length));\n\t\t\t\tg_left += cig[i].length;\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase REF_SKIP:\n\t\t\t{\t\n\t\t\t\tAugmentedCuffOp intron(CUFF_INTRON, g_left, cig[i].length);\n\t\t\t\tif (binary_search(bi.begin(), bi.end(), intron))\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//ops.push_back(AugmentedCuffOp(CUFF_INTRON, g_left, cig[i].length));\n\t\t\t\tg_left += cig[i].length;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\t\n\t\t\tcase SOFT_CLIP:\n\t\t\t\tg_left += cig[i].length;\n\t\t\t\tbreak;\n                \n            case HARD_CLIP:\n\t\t\t\tbreak;\n            case INS:\n                g_left -= cig[i].length;\n                break;\n            case DEL:\n                g_left += cig[i].length;\n                break;\n\t\t\tdefault:\n\t\t\t\tassert(false);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\t\n\treturn false;\n}\n\nvoid inspect_map(boost::shared_ptr<BundleFactory> bundle_factory,\n                 BadIntronTable* bad_introns,\n                 vector<LocusCount>& compatible_count_table,\n                 vector<LocusCount>& total_count_table,\n                 IdToLocusMap& id_to_locus_map,\n                 bool progress_bar,\n                 bool show_stats)\n{\n\n\tProgressBar p_bar;\n\tif (progress_bar)\n\t\tp_bar = ProgressBar(\"Inspecting reads and determining fragment length distribution.\",bundle_factory->ref_table().size());\n\tRefID last_chrom = 0;\n\n\tlong double map_mass = 0.0;\n    long double norm_map_mass = 0.0;\n\t\n\tint min_len = numeric_limits<int>::max();\n\tint max_len = def_max_frag_len;\n\tvector<double> frag_len_hist(def_max_frag_len+1,0);\n\tbool has_pairs = false;\n\n\tint num_bundles = 0;\n\tsize_t total_hits = 0;\n\tsize_t total_non_redundant_hits = 0;\n\t\n\t//To be used for quartile normalization\n\tvector<long double> mass_dist; \t\n\t\n\t// Store the maximum read length for \"first\" and \"second\" reads to report to user.\n\tint max_1 = 0;\n\tint max_2 = 0;\n\t\n\tboost::shared_ptr<MultiReadTable> mrt(new MultiReadTable());\n\t\n\twhile(true)\n\t{\n\t\tHitBundle* bundle_ptr = new HitBundle();\n\t\t\n\t\tbool valid_bundle = bundle_factory->next_bundle(*bundle_ptr, false);\n\t\tHitBundle& bundle = *bundle_ptr;\n\n        if (use_compat_mass) //only count hits that are compatible with ref transcripts\n        {\n            // Take raw mass even if bundle is \"empty\", since we could be out of refs\n            // with remaining hits\n            map_mass += bundle.compatible_mass();\n//            if (lib_norm_method == QUARTILE && bundle.compatible_mass() > 0)\n//            {\n//                mass_dist.push_back(bundle.compatible_mass());\n//            }\n        }\n        else if (use_total_mass) //use all raw mass\n        { \n            \n            // Take raw mass even if bundle is \"empty\", since we could be out of refs\n            // with remaining hits\n            map_mass += bundle.raw_mass();\n//            if (lib_norm_method == QUARTILE && bundle.raw_mass() > 0)\n//            {\n//                mass_dist.push_back(bundle.raw_mass());\n//            }\n        }\n        else\n        {\n            fprintf(stderr, \"Error: hit counting scheme for normalization is not set!\\n\");\n            assert(false);\n            exit(1);\n        }\n\t\t\n\t\tconst RefSequenceTable& rt = bundle_factory->ref_table();\n\t\tconst char* chrom = rt.get_name(bundle.ref_id());\n\t\tchar bundle_label_buf[2048];\n        if (chrom)\n        {\n            sprintf(bundle_label_buf, \"%s:%d-%d\", chrom, bundle.left(), bundle.right());\n            verbose_msg(\"Inspecting bundle %s with %lu reads\\n\", bundle_label_buf, bundle.hits().size());\n            \n            vector<string> gene_ids;\n            vector<string> gene_short_names;\n            BOOST_FOREACH(boost::shared_ptr<Scaffold> s, bundle.ref_scaffolds())\n            {\n                if (s->annotated_gene_id() != \"\")\n                    gene_ids.push_back(s->annotated_gene_id());\n                if (s->annotated_gene_name() != \"\")\n                    gene_short_names.push_back(s->annotated_gene_name());\n                \n//                if (s->annotated_gene_id() == \"ENSG00000268467.1\")\n//                {\n//                    int a = 4;\n//                }\n                \n            }\n            compatible_count_table.push_back(LocusCount(bundle_label_buf, floor(bundle.compatible_mass()), bundle.ref_scaffolds().size(), gene_ids, gene_short_names));\n            total_count_table.push_back(LocusCount(bundle_label_buf, floor(bundle.raw_mass()), bundle.ref_scaffolds().size(), gene_ids, gene_short_names));\n\t\t}\n        \n        if (!valid_bundle)\n\t\t{\n\t\t\tdelete bundle_ptr;\n\t\t\tbreak;\n\t\t}\n\t\tnum_bundles++;\n        \n        BOOST_FOREACH(boost::shared_ptr<Scaffold> s, bundle.ref_scaffolds()){\n            id_to_locus_map.register_locus_to_id(s->annotated_trans_id(), bundle_label_buf);\n            id_to_locus_map.register_locus_to_id(s->annotated_gene_id(), bundle_label_buf);\n            \n            if (s->annotated_tss_id().empty() == false)\n            {\n                id_to_locus_map.register_locus_to_id(s->annotated_tss_id(), bundle_label_buf);\n            }\n            \n            if (s->annotated_protein_id().empty() == false)\n            {\n                id_to_locus_map.register_locus_to_id(s->annotated_protein_id(), bundle_label_buf);\n            }\n        }\n        \n        if (progress_bar) \n        {\n\t\t\tdouble inc_amt = last_chrom == bundle.ref_id() ? 0.0 : 1.0;\n\t\t\tp_bar.update(bundle_label_buf, inc_amt);\n\t\t\tlast_chrom = bundle.ref_id();\n        }\n        \n        if (bad_introns != NULL)\n\t\t{\n\t\t\tidentify_bad_splices(bundle, *bad_introns);\n\t\t}\n\t\t\n\t\tconst vector<MateHit>& hits = bundle.non_redundant_hits();\n\t\tif (hits.empty())\n\t\t{\n\t\t\tdelete bundle_ptr;\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\tlist<pair<int, int> > open_ranges;\n\t\tint curr_range_start = hits[0].left();\n\t\tint curr_range_end = numeric_limits<int>::max();\n\t\tint next_range_start = -1;\n\t\t\n\t\ttotal_non_redundant_hits += bundle.non_redundant_hits().size();\n\t\ttotal_hits += bundle.hits().size();\n\t\t\n\t\t// This first loop calclates the map mass and finds ranges with no introns\n\t\t// Note that we are actually looking at non-redundant hits, which is why we use collapse_mass\n\t\t// This loop will also add multi-reads to the MultiReads table \n\t\tfor (size_t i = 0; i < hits.size(); ++i) \n\t\t{\n\t\t\tassert(hits[i].left_alignment());\n            \n            // Add to table if multi-read\n\t\t\tif (hits[i].is_multi())\n\t\t\t{\n\t\t\t\tmrt->add_hit(hits[i]);\n\t\t\t}\n\t\t\t\n\t\t\t// Find left length\n\t\t\tint left_len = hits[i].left_alignment()->right()-hits[i].left_alignment()->left();\n\t\t\tmin_len = min(min_len, left_len);\n\t\t\tif (!hits[i].left_alignment()->contains_splice())\n            {\n\t\t\t\tif (hits[i].left_alignment()->is_first())\n                    max_1 = max(max_1, left_len);\n                else\n                    max_2 = max(max_2, left_len);\n            }\n\t\t\t\n\t\t\t// Find right length\n\t\t\tif (hits[i].right_alignment())\n\t\t\t{\n\t\t\t\tint right_len = hits[i].right_alignment()->right()-hits[i].right_alignment()->left();\n\t\t\t\tmin_len = min(min_len, right_len);\n\t\t\t\tif (!hits[i].right_alignment()->contains_splice())\n                {\n                    if (hits[i].right_alignment()->is_first())\n                        max_1 = max(max_1, right_len);\n                    else\n                        max_2 = max(max_2, right_len);\n                }\n                has_pairs = true;\n\t\t\t}\n\t\t\t\n\t\t\t// Find fragment length\n\t\t\tif (bundle.ref_scaffolds().size()==1 && hits[i].is_pair())\n\t\t\t// Annotation provided and single isoform gene\n\t\t\t{\n\t\t\t\tint start, end, mate_length;\n\t\t\t\tboost::shared_ptr<Scaffold> scaff = bundle.ref_scaffolds()[0];\n\t\t\t\tif (scaff->map_frag(hits[i], start, end, mate_length))\n\t\t\t\t{\n\t\t\t\t\tif (mate_length >= min_len && mate_length <= max_len)\n\t\t\t\t\t\tfrag_len_hist[mate_length] += hits[i].collapse_mass();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (bundle.ref_scaffolds().empty())\n\t\t\t// No annotation provided.  Look for ranges.\n\t\t\t{\n\t\t\t\tif (hits[i].left() > curr_range_end)\n\t\t\t\t{\n\t\t\t\t\tif (curr_range_end - curr_range_start > max_len)\n\t\t\t\t\t\topen_ranges.push_back(make_pair(curr_range_start, curr_range_end));\n\t\t\t\t\tcurr_range_start = next_range_start;\n\t\t\t\t\tcurr_range_end = numeric_limits<int>::max();\n\t\t\t\t}\n\t\t\t\tif (hits[i].left_alignment()->contains_splice())\n\t\t\t\t{\n\t\t\t\t\tif (hits[i].left() - curr_range_start > max_len)\n\t\t\t\t\t\topen_ranges.push_back(make_pair(curr_range_start, hits[i].left()-1));\n\t\t\t\t\tcurr_range_start = max(next_range_start, hits[i].left_alignment()->right());\n\t\t\t\t}\n\t\t\t\tif (hits[i].right_alignment() && hits[i].right_alignment()->contains_splice())\n\t\t\t\t{\n\t\t\t\t\tassert(hits[i].right_alignment()->left() >= hits[i].left());\n\t\t\t\t\tcurr_range_end = min(curr_range_end, hits[i].right_alignment()->left()-1);\n\t\t\t\t\tnext_range_start = max(next_range_start, hits[i].right());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n        \n        if (bundle.ref_scaffolds().empty() && has_pairs) // No annotation provided\n\t\t{\n\t\t\tpair<int, int> curr_range(-1,-1);\n\t\t\t\n\t\t\t// This second loop uses the ranges found above to find the estimated frag length distribution\n\t\t\t// It also finds the minimum read length to use in the linear interpolation\n\t\t\tfor (size_t i = 0; i < hits.size(); ++i)\n\t\t\t{\n\t\t\t\tif (hits[i].left() > curr_range.second && open_ranges.empty())\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tif (hits[i].left() > curr_range.second)\n\t\t\t\t{\n\t\t\t\t\tcurr_range = open_ranges.front();\n\t\t\t\t\topen_ranges.pop_front();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (hits[i].left() >= curr_range.first && hits[i].right() <= curr_range.second && hits[i].is_pair())\n\t\t\t\t{\n\t\t\t\t\tint mate_len = hits[i].right()-hits[i].left();\n\t\t\t\t\tif (mate_len <= max_len)\n\t\t\t\t\t\tfrag_len_hist[mate_len] += hits[i].collapse_mass();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n        open_ranges.clear();\n\t\tdelete bundle_ptr;\n\t}\n\t\n    norm_map_mass = map_mass;\n    \n//\tif (lib_norm_method == QUARTILE && mass_dist.size() > 0)\n//\t{\n//\t\tsort(mass_dist.begin(),mass_dist.end());\n//\t\tint upper_quart_index = mass_dist.size() * 0.75;\n//\t\tnorm_map_mass = mass_dist[upper_quart_index];\n//\t}\n\n    if (bad_introns != NULL)\n    {\n        size_t alloced = 0;\n        size_t used = 0;\n        size_t num_introns = 0;\n        for (BadIntronTable::const_iterator itr = bad_introns->begin();\n             itr != bad_introns->end();\n             ++itr)\n        {\n            alloced += itr->second.capacity() * sizeof(AugmentedCuffOp);\n            used += itr->second.size() * sizeof(AugmentedCuffOp);\n            num_introns += itr->second.size();\n        }\n        \n        verbose_msg( \"Bad intron table has %lu introns: (%lu alloc'd, %lu used)\\n\", num_introns, alloced, used);\n    \tverbose_msg( \"Map has %lu hits, %lu are non-redundant\\n\", total_hits, total_non_redundant_hits);\n    } \n    \n\tif (progress_bar)\n\t\tp_bar.complete();\n\t\n\tvector<double> frag_len_pdf(max_len+1, 0.0);\n\tvector<double> frag_len_cdf(max_len+1, 0.0);\n    long double tot_count = accumulate(frag_len_hist.begin(), frag_len_hist.end(), 0.0 );\n    bool empirical = false;\n\t\n\tif (user_provided_fld && has_pairs && tot_count >= 10000)\n\t{\n\t\tfprintf(stderr, \"Warning: Overriding empirical fragment length distribution with user-specified parameters is not recommended.\\n\");\n\t}\n\t\n\tif (!has_pairs || tot_count < 10000)\n\t{\n\t\tif (has_pairs && !user_provided_fld)\n\t\t{\n\t\t\tfprintf(stderr, \"Warning: Using default Gaussian distribution due to insufficient paired-end reads in open ranges.  It is recommended that correct parameters (--frag-len-mean and --frag-len-std-dev) be provided.\\n\");\n\t\t}\n\t\ttot_count = 0;\n\t\tnormal frag_len_norm(def_frag_len_mean, def_frag_len_std_dev);\n\t\tmax_len = def_frag_len_mean + 3*def_frag_len_std_dev;\n\t\tfor(int i = min_len; i <= max_len; i++)\n\t\t{\n\t\t\tfrag_len_hist[i] = cdf(frag_len_norm, i+0.5)-cdf(frag_len_norm, i-0.5);\n\t\t\ttot_count += frag_len_hist[i];\n\t\t}\n\t}\n\telse\n\t// Calculate the max frag length and interpolate all zeros between min read len and max frag len\n\t{\t\n\t\tempirical = true;\n\t\tdouble curr_total = 0;\n\t\tsize_t last_nonzero = min_len-1;\n\t\tfor(size_t i = last_nonzero+1; i < frag_len_hist.size(); i++)\n\t\t{\n\t\t\tif (frag_len_hist[i] > 0)\n\t\t\t{\n\t\t\t\tif (last_nonzero != i-1)\n\t\t\t\t{\n\t\t\t\t\tdouble b = frag_len_hist[last_nonzero];\n\t\t\t\t\tdouble m = (frag_len_hist[i] - b)/(i-last_nonzero);\n\t\t\t\t\tfor (size_t x = 1; x < i - last_nonzero; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tfrag_len_hist[last_nonzero+x] = m * x + b;\n\t\t\t\t\t\ttot_count += frag_len_hist[last_nonzero+x];\n\t\t\t\t\t\tcurr_total += frag_len_hist[last_nonzero+x];\n\t\t\t\t\t}\t\n\t\t\t\t}\n\t\t\t\tlast_nonzero = i;\n\t\t\t}\n\t\t\t\n\t\t\tcurr_total += frag_len_hist[i];\n\t\t\t\n\t\t\tif (curr_total/tot_count > 0.9999)\n\t\t\t{\n\t\t\t\tmax_len = i; \n\t\t\t\ttot_count = curr_total;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n    double mean = 0.0;\n\n    if (output_fld)\n    {\n        FILE* fhist = fopen(string(output_dir + \"/frag_len_hist.csv\").c_str(),\"w\");\n        fprintf(fhist, \"Length,Count\\n\");\n        for(size_t i = 1; i < frag_len_hist.size(); i++)\n        {\n            fprintf(fhist, \"%zu,%f\\n\", i, frag_len_hist[i]);\n        }\n        fclose(fhist);\n    }\n\n\t// Convert histogram to pdf and cdf, calculate mean\n\tint frag_len_mode = 0;\n\tfor(size_t i = min_len; i <= (size_t)max_len; i++)\n\t{\n\t\tfrag_len_pdf[i] = frag_len_hist[i]/tot_count;\n\t\tfrag_len_cdf[i] = frag_len_cdf[i-1] + frag_len_pdf[i];\n        \n\t\tif (frag_len_pdf[i] > frag_len_pdf[frag_len_mode])\n\t\t\tfrag_len_mode = i;\n        mean += frag_len_pdf[i] * i;\n\t}\n    \n    double std_dev =  0.0;\n    for(size_t i = 1; i < frag_len_hist.size(); i++)\n    {\n        std_dev += frag_len_pdf[i] * ((i - mean) * (i - mean));\n    }\n    \n    std_dev = sqrt(std_dev);\n\t\n\tboost::shared_ptr<ReadGroupProperties> rg_props = bundle_factory->read_group_properties();\n\n    FLDSource source = DEFAULT;\n    if (empirical)\n    {\n        source = LEARNED;\n    }\n    else if (user_provided_fld)\n    {\n        source = USER;\n    }\n\n\tboost::shared_ptr<EmpDist const> fld(new EmpDist(frag_len_pdf, frag_len_cdf, frag_len_mode, mean, std_dev, min_len, max_len, source));\n\trg_props->multi_read_table(mrt);\n\trg_props->frag_len_dist(fld);\n\trg_props->normalized_map_mass(norm_map_mass);\n    rg_props->total_map_mass(map_mass);\n    \n    if (show_stats)\n    {\n        fprintf(stderr, \"> Map Properties:\\n\");\n        //if (lib_norm_method == QUARTILE)\n        //    fprintf(stderr, \">\\tUpper Quartile: %.2Lf\\n\", norm_map_mass);\n        fprintf(stderr, \">\\tNormalized Map Mass: %.2Lf\\n\", norm_map_mass);\n        fprintf(stderr, \">\\tRaw Map Mass: %.2Lf\\n\", map_mass);\n        if (corr_multi)\n            fprintf(stderr,\">\\tNumber of Multi-Reads: %zu (with %zu total hits)\\n\", mrt->num_multireads(), mrt->num_multihits()); \n    //\tif (has_pairs)\n    //\t\tfprintf(stderr, \">\\tRead Type: %dbp x %dbp\\n\", max_1, max_2);\n    //\telse\n    //\t\tfprintf(stderr, \">\\tRead Type: %dbp single-end\\n\", max(max_1,max_2));\n\n        if (empirical)\n        {\n            fprintf(stderr, \">\\tFragment Length Distribution: Empirical (learned)\\n\");\n            fprintf(stderr, \">\\t              Estimated Mean: %.2f\\n\", mean);\n            fprintf(stderr, \">\\t           Estimated Std Dev: %.2f\\n\", std_dev);\n        }\n        else\n        {\n            if (user_provided_fld)\n            {\n                fprintf(stderr, \">\\tFragment Length Distribution: Truncated Gaussian (user-specified)\\n\");\n            }\n            else\n            {\n                fprintf(stderr, \">\\tFragment Length Distribution: Truncated Gaussian (default)\\n\");\n            }\n            fprintf(stderr, \">\\t              Default Mean: %d\\n\", def_frag_len_mean);\n            fprintf(stderr, \">\\t           Default Std Dev: %d\\n\", def_frag_len_std_dev);\n        }\n    }\n\tbundle_factory->num_bundles(num_bundles);\n\tbundle_factory->reset();\n\treturn;\n}\n\n//////////////////////\n\n\nbool PrecomputedExpressionBundleFactory::next_bundle(HitBundle& bundle, bool cache_bundle)\n{\n#if ENABLE_THREADS\n    boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n    bool got_bundle = BundleFactory::next_bundle(bundle, cache_bundle);\n    if (got_bundle)\n    {\n        RefSequenceTable& rt = ref_table();\n        \n        char bundle_label_buf[2048];\n        sprintf(bundle_label_buf, \"%s:%d-%d\", rt.get_name(bundle.ref_id()),\tbundle.left(), bundle.right());\n        \n        boost::shared_ptr<const AbundanceGroup> ab = _hit_fac->next_locus(bundle.id(), cache_bundle);\n        if (ab)\n        {\n            double compatible_mass = _hit_fac->get_compat_mass(bundle.id());\n            double total_mass  = _hit_fac->get_total_mass(bundle.id());\n            \n            /*\n            double compatible_mass = _hit_fac->get_compat_mass(bundle_label_buf);\n            double total_mass  = _hit_fac->get_total_mass(bundle_label_buf);\n            */\n            \n            bundle.finalize();\n            bundle.add_raw_mass(total_mass);\n            bundle.compatible_mass(compatible_mass);\n            \n            //fprintf (stderr, \"Reconstituting bundle %s (%d) with mass %lf\\n\", bundle_label_buf, bundle.id(), compatible_mass);\n            if (bundle.ref_scaffolds().size() != ab->abundances().size())\n            {\n                fprintf (stderr, \"Error in file %s: reconstituted expression bundle %s (%lu transcripts)  does not match GTF (%lu transcripts):\\n\", read_group_properties()->file_path().c_str(),  bundle_label_buf, ab->abundances().size(), bundle.ref_scaffolds().size());\n                fprintf(stderr, \"Reconstituted:\\n\");\n                for (size_t i = 0; i < ab->abundances().size(); ++i)\n                {\n                    fprintf(stderr, \"%s\\n\", ab->abundances()[i]->description().c_str());\n                }\n                fprintf(stderr, \"GTF:\\n\");\n                for (size_t i = 0; i < bundle.ref_scaffolds().size(); ++i)\n                {\n                    fprintf(stderr, \"%s\\n\", bundle.ref_scaffolds()[i]->annotated_trans_id().c_str());\n                }\n                exit(1);\n            }\n        }\n        else\n        {\n            fprintf (stderr, \"Error: no abundance info for locus %s\\n\", bundle_label_buf);\n        }\n        \n    }\n    return got_bundle;\n}\n\nboost::shared_ptr<const AbundanceGroup> PrecomputedExpressionBundleFactory::get_abundance_for_locus(int locus_id)\n{\n#if ENABLE_THREADS\n    boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n    return _hit_fac->get_abundance_for_locus(locus_id);\n}\n\nvoid PrecomputedExpressionBundleFactory::clear_abundance_for_locus(int locus_id)\n{\n#if ENABLE_THREADS\n    boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n    _hit_fac->clear_abundance_for_locus(locus_id);\n}\n"
  },
  {
    "path": "src/bundles.h",
    "content": "#ifndef BUNDLES_H\n#define BUNDLES_H\n/*\n *  bundles.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 9/6/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n#include <boost/bind.hpp>\n#include <boost/random.hpp>\n#include <boost/unordered_map.hpp>\n#include <vector>\n#include <numeric>\n#include <cmath>\n#include \"common.h\"\n#include \"hits.h\"\n#include \"scaffolds.h\"\n#include \"gtf_tracking.h\"\n#include \"progressbar.h\"\n#include \"rounding.h\"\n\n#include <boost/accumulators/accumulators.hpp>\n#include <boost/accumulators/statistics/density.hpp>\n#include <boost/accumulators/statistics/stats.hpp>\n\nstruct BundleStats\n{\t\t\n\tBundleStats() : \n\tcompatible(0), \n\tuncollapsible(0),\n\tclosure_edges(0),\n\tmatched_edges(0)\n\t{}\n\t\n\tint compatible;\n\tint uncollapsible;\n\tint closure_edges;\n\tint matched_edges;\n};\n\ntypedef map<RefID, vector<AugmentedCuffOp> > BadIntronTable;\n\n\n/*******************************************************************************\n HitBundle is a set of MateHit objects that, were you to look at the interval\n graph of their spanning intervals in genomic coordinates, you'd see a single\n connected component. Note that bundles do not correspond to single transcripts,\n or even single genes\n *******************************************************************************/\nclass HitBundle\n{\nprivate:\n    HitBundle(const HitBundle& rhs) {} \npublic:\n\tHitBundle() \n\t\t: _leftmost(INT_MAX), _rightmost(-1), _final(false), _id(++_next_id), _ref_id(0), _raw_mass(0.0), _num_replicates(1), _compatible_mass(0.0) {\n\t\t// Shrink the open mates table when it is less than 10% full and larger than 10,000 items.\n\t\t_rehash_threshold = _open_mates.max_load_factor() / 10;\n\t\t_rehash_size_threshold = 10000;\n\t}\n\t\n    ~HitBundle()\n    {\n        vector<boost::shared_ptr<Scaffold> >& bundle_ref_scaffs = ref_scaffolds();\n        BOOST_FOREACH(boost::shared_ptr<Scaffold>& ref_scaff, bundle_ref_scaffs)\n        {\n            // This bundle and the factory that actually owns the ref_mRNAs\n            // are the only objects that should have access to these scaffolds\n            // so if the use count is 2, we can clear these guys.\n\t\t\t// Updated to 3 since the bias learner now uses them.\n            if (ref_scaff.use_count() <= 3)\n            {\n                ref_scaff->clear_hits();\n            }\n            else if (ref_scaff->mate_hits().size() > 0)\n            {\n                fprintf(stderr, \"Warning: bundle %d-%d shared reference scaffolds with others.  Possible soft memory leak.\\n\", left(), right());\n            }\n        }   \n        \n        BOOST_FOREACH (MateHit& hit, _hits)\n\t\t{\n\t\t\tdelete hit.left_alignment();\n\t\t\tdelete hit.right_alignment();\n\t\t}\n        \n        for(OpenMates::iterator itr = _open_mates.begin(); itr != _open_mates.end(); ++itr)\n\t\t{\n\t\t\tdelete itr->second.left_alignment();\n\t\t\tdelete itr->second.right_alignment();\n\t\t}\n\t\t\n    }\n\tint left()   const { return _leftmost;  }\n\tint right()  const { return _rightmost; }\n\tint length() const { return _rightmost - _leftmost; }\n\t\n\t// Returns true if the hit was added successfully.\n\tbool add_hit(const MateHit& hit);\n    \n\t// This is to keep track of mass of all hits, including\n\t// thosethat are not added to any bundle\n\t// but are skipped during the creation of this bundle\n\tvoid add_raw_mass(double rm) { _raw_mass += rm; }\n\tvoid rem_raw_mass(double rm) { _raw_mass -= rm; }\n\tdouble raw_mass() { return _raw_mass; }\n    \n    double compatible_mass() const \n    {\n        return _compatible_mass;\n    }\n    \n    void compatible_mass(double c) { _compatible_mass = c; }\n    \n\tvoid clear_hits() \n    {\n        _hits.clear(); \n        _non_redundant.clear();\n        vector<boost::shared_ptr<Scaffold> >& bundle_ref_scaffs = ref_scaffolds();\n        BOOST_FOREACH(boost::shared_ptr<Scaffold>& ref_scaff, bundle_ref_scaffs)\n        {\n            if (ref_scaff.use_count() <= 3)\n            {\n                ref_scaff->clear_hits();\n            }\n            else \n            {\n                fprintf(stderr, \"Warning: bundle %d-%d shared reference scaffolds with others.  Possible soft memory leak.\\n\", left(), right());\n            }\n        } \n    }\n\t\n    const std::vector<MateHit>& hits() const { return _hits; } \n\tconst std::vector<MateHit>& non_redundant_hits() const { return _non_redundant; } \n\t\n\tRefID ref_id()  const {return _ref_id; }\n\t\n\tint id() const { return _id; }\n    void id(int i) { _id = i; }\n\t\n\tvoid add_ref_scaffold(boost::shared_ptr<Scaffold> scaff)\n\t{\n\t\tif (scaff->left() < _leftmost)\n\t\t\t_leftmost = scaff->left();\n\t\tif (scaff->right() > _rightmost)\n\t\t\t_rightmost = scaff->right();\n\t\t_ref_scaffs.push_back(scaff);\n        _ref_id = scaff->ref_id();\n\t}\n\t\n\tvector<boost::shared_ptr<Scaffold> >& ref_scaffolds() { return _ref_scaffs; }\n\t\n\t// Adds a Bowtie hit to the open hits buffer.  The Bundle will handle turning\n\t// the Bowtie hit into a properly mated Cufflinks hit record\n\tbool add_open_hit(boost::shared_ptr<ReadGroupProperties const> rg_props,\n                      const ReadHit* bh,\n\t\t\t\t\t  bool expand_by = true);\n\t\n\t// Commits any mates still open as singleton hits\n\tvoid finalize_open_mates();\n\t\n\t// Sorts the hits, and performs other functions needed to prepare this \n\t// bundle for assembly and quantitation\n\tvoid finalize(bool is_combined=false);\n\t\n\tvoid remove_hitless_scaffolds();\n\n\tvoid collapse_hits();\n\t\n    int num_replicates() const { return _num_replicates; }\n    \n\tdouble mass() const\n\t{\n\t\tdouble mass = 0;\n\t\tfor(size_t i = 0; i < _non_redundant.size(); i++)\n\t\t{\n\t\t\tmass += _non_redundant[i].collapse_mass();\n\t\t}\n\t\treturn mass;\n\t}\n\t\n    static void combine(const vector<HitBundle*>& in_bundles,\n                        HitBundle& out_bundle);\n    \nprivate:\n    int _leftmost;\n\tint _rightmost;\n\tstd::vector<MateHit> _hits;\n\tstd::vector<MateHit> _non_redundant;\n\tstd::vector<boost::shared_ptr<Scaffold> > _ref_scaffs; // user-supplied reference annotations overlapping the bundle\n\tbool _final;\n\tint _id;\n    RefID _ref_id;\n\tdouble _raw_mass;\n\n\t\n\tstatic int _next_id;\n\t\n\t// InsertIDs are already hashes of SAM record names; no need\n\t// to hash them again. Note on 32-bit this will take the truncate\n\t// the larger InsertID hash to size_t.\n\tstruct identity_hash {\n\t\tsize_t operator()(const InsertID& in) const { return (size_t)in; }\n\t};\n\n\ttypedef boost::unordered_multimap<uint64_t, MateHit, identity_hash> OpenMates;\n\tOpenMates _open_mates;\n    int _num_replicates;\n    double _compatible_mass;\n\tfloat _rehash_threshold;\n\tOpenMates::size_type _rehash_size_threshold;\n\n};\n\nvoid load_ref_rnas(FILE* ref_mRNA_file, \n\t\t\t\t   RefSequenceTable& rt,\n\t\t\t\t   vector<boost::shared_ptr<Scaffold> >& ref_mRNAs,\n                   boost::crc_32_type& gtf_crc_result,\n\t\t\t\t   bool loadSeqs=false,\n\t\t\t\t   bool loadFPKM=false);\n\nclass BundleFactory\n{\npublic:\n    \n\tBundleFactory(boost::shared_ptr<HitFactory> fac, BundleMode bm)\n    : _hit_fac(fac), _bundle_mode(bm), _prev_pos(0), _prev_ref_id(0), _curr_bundle(0),  rng(boost::mt19937(random_seed)), _zeroone(rng)\n\t{\n\t\t_rg_props = boost::shared_ptr<ReadGroupProperties>(new ReadGroupProperties(fac->read_group_properties()));\n        next_ref_scaff = ref_mRNAs.begin(); \n        next_mask_scaff = mask_gtf_recs.begin();\n\t}\n\n    virtual ~BundleFactory() {} \n    boost::shared_ptr<const HitFactory> hit_factory() const { return _hit_fac; }\n    \n    bool bundles_remain()  \n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n        return _curr_bundle < num_bundles();\n    }\n    \n\tvirtual bool next_bundle(HitBundle& bundle_out, bool cache_bundle);\n\tbool next_bundle_hit_driven(HitBundle& bundle_out);\n\tbool next_bundle_ref_driven(HitBundle& bundle_out);\n\tbool next_bundle_ref_guided(HitBundle& bundle_out);\n\n    \n    RefSequenceTable& ref_table() { return _hit_fac->ref_table(); }\n    \n    // Not available until after inspect_bundle\n    int num_bundles() const { return _num_bundles; }\n    void num_bundles(int n) { _num_bundles = n; }\n    \n\tvirtual void reset()\n\t{ \n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n        _curr_bundle = 0;\n\t\t//rewind(hit_file); \n\t\t_hit_fac->reset();\n\t\tnext_ref_scaff = ref_mRNAs.begin(); \n        next_mask_scaff = mask_gtf_recs.begin();\n        \n        BOOST_FOREACH(boost::shared_ptr<Scaffold> ref_scaff, ref_mRNAs)\n        {\n            ref_scaff->clear_hits();\n        }\n        \n        _prev_pos = 0;\n        _prev_ref_id = 0;\n\t}\n\t\n    // This function NEEDS to deep copy the ref_mRNAs, otherwise cuffdiff'd\n    // samples will clobber each other. Deep copying is necessary whenever\n    // you need to set fpkm or num fragments in Scaffold objects (e.g. during bias correction or multiread correction)\n    void set_ref_rnas(const vector<boost::shared_ptr<Scaffold> >& mRNAs, bool deep_copy = true)\n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n        ref_mRNAs.clear();\n        if (deep_copy)\n        {\n            for (vector<boost::shared_ptr<Scaffold> >::const_iterator i = mRNAs.begin(); i < mRNAs.end(); ++i)\n            {\n                ref_mRNAs.push_back(boost::shared_ptr<Scaffold>(new Scaffold(**i)));\n            }\n        }\n        else\n        {\n            ref_mRNAs = mRNAs;\n        }\n        \n        RefID last_id = 0;\n        for (vector<boost::shared_ptr<Scaffold> >::iterator i = ref_mRNAs.begin(); i < ref_mRNAs.end(); ++i)\n        {\n            if ((*i)->ref_id() != last_id)\n            {\n                _ref_scaff_offsets.push_back(make_pair((*i)->ref_id(), i));\n            }\n            last_id = (*i)->ref_id();\n        }\n        \n        next_ref_scaff = ref_mRNAs.begin();\n    }\n    \n    void set_mask_rnas(const vector<boost::shared_ptr<Scaffold> >& masks)\n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n        mask_gtf_recs = masks;\n        RefID last_id = 0;\n        for (vector<boost::shared_ptr<Scaffold> >::iterator i = mask_gtf_recs.begin(); i < mask_gtf_recs.end(); ++i)\n        {\n            if ((*i)->ref_id() != last_id)\n            {\n                _mask_scaff_offsets.push_back(make_pair((*i)->ref_id(), i));\n            }\n            last_id = (*i)->ref_id();\n        }\n        \n        next_mask_scaff = mask_gtf_recs.begin();\n    }\n        \n\tvoid bad_intron_table(const BadIntronTable& bad_introns) \n\t{ \n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n\t\t_bad_introns = bad_introns;\n\t}\n    \n    void read_group_properties(boost::shared_ptr<ReadGroupProperties> rg)\n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n        _rg_props = rg;\n    }\n    \n    boost::shared_ptr<ReadGroupProperties> read_group_properties()\n    {\n        return _rg_props;\n    }\n\t\n\tbool spans_bad_intron(const ReadHit& read);\n\t\nprivate:\n\t\n\tbool _expand_by_hits(HitBundle& bundle);\n\tbool _expand_by_refs(HitBundle& bundle);\n\t\n\tboost::shared_ptr<HitFactory> _hit_fac;\n    \n\tvector<boost::shared_ptr<Scaffold> > ref_mRNAs;\n\t//FILE* ref_mRNA_file;\n\tvector<pair<RefID, vector<boost::shared_ptr<Scaffold> >::iterator> > _ref_scaff_offsets;\n\tvector<boost::shared_ptr<Scaffold> >::iterator next_ref_scaff;\n    \n    vector<boost::shared_ptr<Scaffold> > mask_gtf_recs;\n\t//FILE* mask_file;\n\tvector<pair<RefID, vector<boost::shared_ptr<Scaffold> >::iterator> > _mask_scaff_offsets;\n\tvector<boost::shared_ptr<Scaffold> >::iterator next_mask_scaff;\n\t\n\tBadIntronTable _bad_introns;\n    \n    boost::shared_ptr<ReadGroupProperties> _rg_props;\n    \n\t// Sets nva to point to the next valid alignment\n\t// Returns the mass of any alignments that are seen, valid or not\n    double next_valid_alignment(const ReadHit*& nva);\n\t\n\t// Backs up the factory to before the last valid alignment\n\t// and returns the mass of that alignment (rh)\n\tdouble rewind_hit(const ReadHit* rh);\n\n    BundleMode _bundle_mode;\n    int _prev_pos;\n    RefID _prev_ref_id;\n    int _num_bundles;\n    int _curr_bundle;\n    \n    boost::mt19937 rng;\n    boost::uniform_01<boost::mt19937> _zeroone;\n    \n#if ENABLE_THREADS    \n    boost::mutex _factory_lock;\n#endif\n};\n\nclass PrecomputedExpressionBundleFactory : public BundleFactory\n{\npublic:\n    PrecomputedExpressionBundleFactory(boost::shared_ptr<PrecomputedExpressionHitFactory> fac)\n\t: BundleFactory(fac, REF_DRIVEN), _hit_fac(fac)\n\t{\n\t\t\n\t}\n    \n    bool next_bundle(HitBundle& bundle_out, bool cache_bundle);\n    \n    boost::shared_ptr<const AbundanceGroup> get_abundance_for_locus(int locus_id);\n    void clear_abundance_for_locus(int locus_id);\n    \n    void reset() { BundleFactory::reset(); }\n    \nprivate:\n    \n    boost::shared_ptr<PrecomputedExpressionHitFactory> _hit_fac;\n#if ENABLE_THREADS\n    boost::mutex _factory_lock;\n#endif\n};\n\nvoid identify_bad_splices(const HitBundle& bundle, \n\t\t\t\t\t\t  BadIntronTable& bad_splice_ops);\n\nclass IdToLocusMap\n{\n    \n#if ENABLE_THREADS\n\tboost::mutex _bl_lock;\n#endif\n    \n    IdToLocusMap(const IdToLocusMap& rhs) {}\npublic:\n    \n    IdToLocusMap(boost::shared_ptr<map<string, set<string> > > id_to_locus_map) :\n        _id_to_locus_map(id_to_locus_map) {}\n    \n    void register_locus_to_id(const string& ID, const string& locus_desc)\n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_bl_lock);\n#endif\n\n        pair< map<string, set<string> >::iterator, bool> p = _id_to_locus_map->insert(make_pair(ID, set<string>()));\n        p.first->second.insert(locus_desc);\n    }\n    \n    int unregister_locus_from_id(const string& ID, const string& locus_desc)\n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_bl_lock);\n#endif\n\n        map<string, set<string> >::iterator itr = _id_to_locus_map->find(ID);\n        if (itr != _id_to_locus_map->end()){\n            itr->second.erase(locus_desc);\n            return itr->second.size();\n        }\n        return 0;\n    }\n    \n    int num_locus_registered(const string& ID) {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_bl_lock);\n#endif\n\n        map<string, set<string> >::const_iterator itr = _id_to_locus_map->find(ID);\n        if (itr == _id_to_locus_map->end())\n            return 0;\n        return itr->second.size();\n    }\nprivate:\n    boost::shared_ptr<map<string, set<string> > > _id_to_locus_map;\n};\n\nvoid inspect_map(boost::shared_ptr<BundleFactory> bundle_factory,\n                 BadIntronTable* bad_introns,\n                 vector<LocusCount>& compatible_count_table,\n                 vector<LocusCount>& total_count_table,\n                 IdToLocusMap& id_to_locus_map,\n                 bool progress_bar = true,\n                 bool show_stats = true);\n\n#endif\n"
  },
  {
    "path": "src/clustering.cpp",
    "content": "/*\n *  clustering.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/15/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include \"clustering.h\"\n\nvoid ConnectByExonOverlap::operator()(const AbundanceGroup& cluster,\n\t\t\t\t\t\t\t\t\t  AbundanceGraph& G)\n{\n\tconst vector<boost::shared_ptr<Abundance> >& abundances = cluster.abundances();\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tadd_vertex(G);\n\t}\n\t\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tboost::shared_ptr<Scaffold> scaff_i = abundances[i]->transfrag();\n\t\tassert (scaff_i);\n\t\t\n\t\tfor (size_t j = i + 1; j < abundances.size(); ++j)\n\t\t{\n\t\t\tboost::shared_ptr<Scaffold> scaff_j = abundances[j]->transfrag();\n\t\t\tassert (scaff_j);\n\t\t\t\n\t\t\tif (Scaffold::exons_overlap(*scaff_i, *scaff_j))\n\t\t\t\tadd_edge(i, j, G);\n\t\t}\n\t}\n}\n\nvoid ConnectByAnnotatedGeneId::operator()(const AbundanceGroup& cluster,\n\t\t\t\t\t\t\t\t\t\t  AbundanceGraph& G)\n{\n\tconst vector<boost::shared_ptr<Abundance> >& abundances = cluster.abundances();\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tadd_vertex(G);\n\t}\n\t\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tset<string> i_gene_id = abundances[i]->gene_id();\n\t\tfor (size_t j = i + 1; j < abundances.size(); ++j)\n\t\t{\n\t\t\tset<string> j_gene_id = abundances[j]->gene_id();\n\t\t\tif (i_gene_id == j_gene_id)\n\t\t\t{\n\t\t\t\tadd_edge(i, j, G);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid ConnectByAnnotatedTssId::operator()(const AbundanceGroup& cluster,\n\t\t\t\t\t\t\t\t\t\t  AbundanceGraph& G)\n{\n\tconst vector<boost::shared_ptr<Abundance> >& abundances = cluster.abundances();\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tadd_vertex(G);\n\t}\n\t\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tset<string> i_tss_id = abundances[i]->tss_id();\n\t\tfor (size_t j = i + 1; j < abundances.size(); ++j)\n\t\t{\n\t\t\tset<string> j_tss_id = abundances[j]->tss_id();\n\t\t\tif (i_tss_id == j_tss_id)\n\t\t\t{\n\t\t\t\tadd_edge(i, j, G);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid ConnectByAnnotatedProteinId::operator()(const AbundanceGroup& cluster,\n\t\t\t\t\t\t\t\t\t\t\t AbundanceGraph& G)\n{\n\tconst vector<boost::shared_ptr<Abundance> >& abundances = cluster.abundances();\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tadd_vertex(G);\n\t}\n\t\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tset<string> i_p_id = abundances[i]->protein_id();\n\t\tfor (size_t j = i + 1; j < abundances.size(); ++j)\n\t\t{\n\t\t\tset<string> j_p_id = abundances[j]->protein_id();\n\t\t\tif (i_p_id == j_p_id)\n\t\t\t{\n\t\t\t\tadd_edge(i, j, G);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid ConnectByStrand::operator()(const AbundanceGroup& cluster,\n\t\t\t\t\t\t\t\t AbundanceGraph& G)\n{\n\tconst vector<boost::shared_ptr<Abundance> >& abundances = cluster.abundances();\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tadd_vertex(G);\n\t}\n\t\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tboost::shared_ptr<Scaffold> scaff_i = abundances[i]->transfrag();\n\t\tassert (scaff_i);\n\t\t\n\t\tfor (size_t j = i + 1; j < abundances.size(); ++j)\n\t\t{\n\t\t\tboost::shared_ptr<Scaffold> scaff_j = abundances[j]->transfrag();\n\t\t\tassert (scaff_j);\n\t\t\tif (scaff_i->strand() == scaff_j->strand())\n\t\t\t{\n\t\t\t\tadd_edge(i, j, G);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/clustering.h",
    "content": "#ifndef CLUSTERING_H\n#define CLUSTERING_H\n/*\n *  abundances.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 4/27/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n// DON'T move this, or mystery compiler errors will result. Affects gcc >= 4.1\n#include <boost/graph/vector_as_graph.hpp>\n\n#include <boost/graph/adjacency_list.hpp>\n#include <boost/graph/depth_first_search.hpp>\n#include <boost/graph/visitors.hpp>\n#include <boost/graph/graph_traits.hpp>\n#include <boost/graph/connected_components.hpp>\n\n#ifdef DEBUG\n#include <boost/numeric/ublas/io.hpp>\n#endif\n\n#include <boost/version.hpp>\n\n#if (BOOST_VERSION < 103800)\n#include <boost/vector_property_map.hpp>\n#else\n#include <boost/property_map/vector_property_map.hpp>\n#endif\n\n\n#include \"abundances.h\"\n\ntypedef boost::adjacency_list <boost::vecS, boost::vecS, boost::undirectedS> AbundanceGraph;\n\nstruct ConnectByExonOverlap\n{\n\tvoid operator()(const AbundanceGroup& cluster,\n\t\t\t\t\tAbundanceGraph& G);\n};\n\nstruct ConnectByAnnotatedGeneId\n{\n\tvoid operator()(const AbundanceGroup& cluster,\n\t\t\t\t\tAbundanceGraph& G);\n};\n\nstruct ConnectByAnnotatedTssId\n{\n\tvoid operator()(const AbundanceGroup& cluster,\n\t\t\t\t\tAbundanceGraph& G);\n};\n\nstruct ConnectByAnnotatedProteinId\n{\n\tvoid operator()(const AbundanceGroup& cluster,\n\t\t\t\t\tAbundanceGraph& G);\n};\n\nstruct ConnectByStrand\n{\n\tvoid operator()(const AbundanceGroup& cluster,\n\t\t\t\t\tAbundanceGraph& G);\n};\n\n// A \"transcript cluster is a set of transcripts whose projections into the\n// genome overlap on the same strand.  They may thus share fragment alignments,\n// and so they need to be quantitated together.  After quantitation, they\n// can be picked apart.\ntemplate<class cluster_policy>\nvoid cluster_transcripts(const AbundanceGroup& transfrags,\n\t\t\t\t\t\t vector<AbundanceGroup>& transfrags_by_cluster,\n\t\t\t\t\t\t ublas::matrix<double>* new_gamma = NULL,\n                         ublas::matrix<double>* new_iterated_count = NULL,\n                         ublas::matrix<double>* new_count = NULL,\n                         ublas::matrix<double>* new_fpkm = NULL)\n{\n\tboost::adjacency_list <boost::vecS, boost::vecS, boost::undirectedS> G;\n\t\n\ttransfrags_by_cluster.clear();\n\t\n\tcluster_policy cp;\n\t\n\tcp(transfrags, G);\n\t\n\tstd::vector<int> component(num_vertices(G));\n\tconnected_components(G, &component[0]);\n\t\n\tvector<vector<bool> > clusters(transfrags.abundances().size(), \n\t\t\t\t\t\t\t\t   vector<bool>(transfrags.abundances().size(), false));\n\t\n\tvector<vector<size_t> > cluster_indices(transfrags.abundances().size());\n\tfor (size_t i = 0; i < transfrags.abundances().size(); ++i)\n\t{\n        clusters[component[i]][i] = true;\n        cluster_indices[component[i]].push_back(i);\n\t}\n\tfor (size_t i = 0; i < cluster_indices.size(); ++i)\n\t{\n\t\tif (cluster_indices[i].empty())\n\t\t{\n\t\t\tcluster_indices.resize(i);\n\t\t\tbreak;\n\t\t}\n\t}\n    \n\tfor (size_t i = 0; i < clusters.size(); ++i)\n\t{\n\t\tAbundanceGroup cluster;\n\t\ttransfrags.filter_group(clusters[i], cluster);\n\t\tif (!cluster.abundances().empty())\n\t\t\ttransfrags_by_cluster.push_back(cluster);\n\t}\n\t\n\tif (new_gamma != NULL)\n\t{\n\t\tconst ublas::matrix<double>& trans_gamma_cov = transfrags.gamma_cov();\n        const ublas::matrix<double>& trans_iterated_count_cov = transfrags.iterated_count_cov();\n        const ublas::matrix<double>& trans_count_cov = transfrags.count_cov();\n        const ublas::matrix<double>& trans_fpkm_cov = transfrags.fpkm_cov();\n        \n\t\tublas::matrix<double>& cov = *new_gamma;\n        ublas::matrix<double>& iterated_count_cov = *new_iterated_count;\n        ublas::matrix<double>& count_cov = *new_count;\n        ublas::matrix<double>& fpkm_cov = *new_fpkm;\n        \n\t\t// number of primary transcripts for this gene\n\t\tsize_t num_pt = cluster_indices.size();\n\t\tcov = ublas::zero_matrix<double>(num_pt, num_pt);\n        \n        count_cov = ublas::zero_matrix<double>(num_pt, num_pt);\n        iterated_count_cov = ublas::zero_matrix<double>(num_pt, num_pt);\n        fpkm_cov = ublas::zero_matrix<double>(num_pt, num_pt);\n        \n\t\t//cerr << \"combined \" << combined << endl;\n\t\t\n\t\t//cerr << \"locus isoform gamma cov\" << gamma_cov << endl;\n\t\tfor (size_t L = 0; L < cluster_indices.size(); ++L)\n\t\t{\n\t\t\tconst vector<size_t>& L_isos = cluster_indices[L];\n\t\t\tfor (size_t K = 0; K < cluster_indices.size(); ++K)\n\t\t\t{\n\t\t\t\tconst vector<size_t>& K_isos = cluster_indices[K];\n\t\t\t\tfor (size_t l = 0; l < L_isos.size(); ++l)\n\t\t\t\t{\n\t\t\t\t\tfor (size_t k = 0; k < K_isos.size(); ++k)\n\t\t\t\t\t{\n\t\t\t\t\t\tcov(L,K) += trans_gamma_cov(L_isos[l],K_isos[k]);\n                        count_cov(L,K) += trans_count_cov(L_isos[l],K_isos[k]);\n                        iterated_count_cov(L,K) += trans_iterated_count_cov(L_isos[l],K_isos[k]);\n                        fpkm_cov(L,K) += trans_fpkm_cov(L_isos[l],K_isos[k]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n#endif\n\n"
  },
  {
    "path": "src/codons.cpp",
    "content": "#include \"codons.h\"\n\nstatic char codonTable[32768]; //32K table for fasta codon decoding\n       // codons are encoded as triplets of 5-bit-encoded nucleotides\n       // (so any codon can be encoded/decoded as a unique 15-bit value)\n\nstatic char codonData[]={ //long list of 3+1 characters (codon+translation)\n'A','A','A','K', 'A','A','C','N', 'A','A','G','K', 'A','A','R','K', 'A','A','T','N',\n'A','A','Y','N', 'A','C','A','T', 'A','C','B','T', 'A','C','C','T', 'A','C','D','T',\n'A','C','G','T', 'A','C','H','T', 'A','C','K','T', 'A','C','M','T', 'A','C','N','T',\n'A','C','R','T', 'A','C','S','T', 'A','C','T','T', 'A','C','V','T', 'A','C','W','T',\n'A','C','Y','T', 'A','G','A','R', 'A','G','C','S', 'A','G','G','R', 'A','G','R','R',\n'A','G','T','S', 'A','G','Y','S', 'A','T','A','I', 'A','T','C','I', 'A','T','G','M',\n'A','T','H','I', 'A','T','M','I', 'A','T','T','I', 'A','T','W','I', 'A','T','Y','I',\n'C','A','A','Q', 'C','A','C','H', 'C','A','G','Q', 'C','A','R','Q', 'C','A','T','H',\n'C','A','Y','H', 'C','C','A','P', 'C','C','B','P', 'C','C','C','P', 'C','C','D','P',\n'C','C','G','P', 'C','C','H','P', 'C','C','K','P', 'C','C','M','P', 'C','C','N','P',\n'C','C','R','P', 'C','C','S','P', 'C','C','T','P', 'C','C','V','P', 'C','C','W','P',\n'C','C','Y','P', 'C','G','A','R', 'C','G','B','R', 'C','G','C','R', 'C','G','D','R',\n'C','G','G','R', 'C','G','H','R', 'C','G','K','R', 'C','G','M','R', 'C','G','N','R',\n'C','G','R','R', 'C','G','S','R', 'C','G','T','R', 'C','G','V','R', 'C','G','W','R',\n'C','G','Y','R', 'C','T','A','L', 'C','T','B','L', 'C','T','C','L', 'C','T','D','L',\n'C','T','G','L', 'C','T','H','L', 'C','T','K','L', 'C','T','M','L', 'C','T','N','L',\n'C','T','R','L', 'C','T','S','L', 'C','T','T','L', 'C','T','V','L', 'C','T','W','L',\n'C','T','Y','L', 'G','A','A','E', 'G','A','C','D', 'G','A','G','E', 'G','A','R','E',\n'G','A','T','D', 'G','A','Y','D', 'G','C','A','A', 'G','C','B','A', 'G','C','C','A',\n'G','C','D','A', 'G','C','G','A', 'G','C','H','A', 'G','C','K','A', 'G','C','M','A',\n'G','C','N','A', 'G','C','R','A', 'G','C','S','A', 'G','C','T','A', 'G','C','V','A',\n'G','C','W','A', 'G','C','Y','A', 'G','G','A','G', 'G','G','B','G', 'G','G','C','G',\n'G','G','D','G', 'G','G','G','G', 'G','G','H','G', 'G','G','K','G', 'G','G','M','G',\n'G','G','N','G', 'G','G','R','G', 'G','G','S','G', 'G','G','T','G', 'G','G','V','G',\n'G','G','W','G', 'G','G','Y','G', 'G','T','A','V', 'G','T','B','V', 'G','T','C','V',\n'G','T','D','V', 'G','T','G','V', 'G','T','H','V', 'G','T','K','V', 'G','T','M','V',\n'G','T','N','V', 'G','T','R','V', 'G','T','S','V', 'G','T','T','V', 'G','T','V','V',\n'G','T','W','V', 'G','T','Y','V', 'M','G','A','R', 'M','G','G','R', 'M','G','R','R',\n'N','N','N','X', 'R','A','Y','B', 'S','A','R','Z', 'T','A','A','.', 'T','A','C','Y',\n'T','A','G','.', 'T','A','R','.', 'T','A','T','Y', 'T','A','Y','Y', 'T','C','A','S',\n'T','C','B','S', 'T','C','C','S', 'T','C','D','S', 'T','C','G','S', 'T','C','H','S',\n'T','C','K','S', 'T','C','M','S', 'T','C','N','S', 'T','C','R','S', 'T','C','S','S',\n'T','C','T','S', 'T','C','V','S', 'T','C','W','S', 'T','C','Y','S', 'T','G','A','.',\n'T','G','C','C', 'T','G','G','W', 'T','G','T','C', 'T','G','Y','C', 'T','R','A','.',\n'T','T','A','L', 'T','T','C','F', 'T','T','G','L', 'T','T','R','L', 'T','T','T','F',\n'T','T','Y','F', 'X','X','X','X', 'Y','T','A','L', 'Y','T','G','L', 'Y','T','R','L'\n};\n\n\nstatic bool isCodonTableReady=codonTableInit();\n\nunsigned short packCodon(char n1, char n2, char n3) {\n //assumes they are uppercase already!\n byte b1=n1-'A';\n byte b2=n2-'A';\n byte b3=n3-'A';\n b1 |= (b2 << 5); \n b2 = (b2 >> 3) | (b3 << 2);\n return ( ((unsigned short)b2) << 8) + b1;\n }\n\nbool codonTableInit() {\n memset((void*)codonTable, 'X', 32768);\n int cdsize=sizeof(codonData);\n for (int i=0;i<cdsize;i+=4) {\n   unsigned short aacode=packCodon(codonData[i], codonData[i+1], codonData[i+2]);\n   codonTable[aacode]=codonData[i+3];\n   } \n return true;\n }\n\n\nchar Codon::translate() {\n for (byte i=0;i<3;i++) nuc[i]=toupper(nuc[i]);\n unsigned short aacode=packCodon(nuc[0], nuc[1], nuc[2]);\n return codonTable[aacode];\n }\n\n//simple 1st frame forward translation of a given DNA string\n// allocate and returns the translation string\nchar* translateDNA(const char* dnastr, int& aalen, int dnalen) {\n if (dnastr==NULL || *dnastr==0) return NULL;\n if (dnalen==0) dnalen=strlen(dnastr);\n aalen=dnalen/3;\n char* r=NULL;\n GMALLOC(r, aalen+1);\n r[aalen]=0;\n int ai=0;\n for (int i=0;i+2<dnalen;i+=3,ai++) {\n   r[ai]=codonTable[packCodon(toupper(dnastr[i]),toupper(dnastr[i+1]),toupper(dnastr[i+2]))];\n   }\n return r;\n}\n"
  },
  {
    "path": "src/codons.h",
    "content": "#ifndef CODONS_H\n#define CODONS_H\n#include \"GBase.h\"\n#include <ctype.h>\n\nunsigned short packCodon(char n1, char n2, char n3);\n//assumes n1,n2,n3 are UPPERCASE!\n\nstruct Codon {\n char nuc[3];\n Codon(char* str=NULL) {\n  if (str==NULL) {\n   nuc[0]='N';\n   nuc[1]='N';\n   nuc[2]='N';\n   }\n  else {\n   nuc[0]=toupper(str[0]);\n   nuc[1]=toupper(str[1]);\n   nuc[2]=toupper(str[2]);\n   }\n  }\n\n Codon(char s1, char s2, char s3) {\n   nuc[0]=toupper(s1);\n   nuc[1]=toupper(s2);\n   nuc[2]=toupper(s3);\n   }\n \n   \n char& operator[](int idx) {\n   if (idx<0 || idx>2) \n      GError(\"Error: Codon index out of bounds!\\n\");\n   return nuc[idx];\n   }\n\n char operator[](int idx) const {\n   if (idx<0 || idx>2) \n      GError(\"Error: Codon index out of bounds!\\n\");\n   return nuc[idx];\n   }\n \n char translate();\n };\n\n//simple 1st frame forward translation of a given DNA string\n//will allocated memory for the translation --  the caller is\n// responsible for freeing the returned string!\nchar* translateDNA(const char* dnastr, int& aalen, int dnalen=0);\n\n\nbool codonTableInit();\n \n#endif\n"
  },
  {
    "path": "src/common.cpp",
    "content": "/*\n *  common.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/23/09.\n *  Copyright 2008 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <cstdio>\n#include <cstring>\n#include <cstdlib>\n#include <iostream>\n#include <stdarg.h>\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <errno.h>\n#include <libgen.h>\n#include <string.h>\n\n#include \"getopt.h\"\n#include \"common.h\"\n#include \"replicates.h\"\n\nusing namespace std;\n\n\n// Non-option globals\nbool final_est_run = true;\nbool allow_junk_filtering = true;\nbool user_provided_fld = false;\n\n// Behavior options\nint num_threads = 1;\nbool no_update_check = false;\nbool cuff_quiet = false;\n#if ASM_VERBOSE\nbool cuff_verbose = true;\n#else\nbool cuff_verbose = false;\n#endif\nbool output_fld = false;\nbool output_bias_params = false;\n\n// General options\nBundleMode bundle_mode = HIT_DRIVEN;\nBundleMode init_bundle_mode = HIT_DRIVEN;\nint max_partner_dist = 50000;\nuint32_t max_gene_length = 3500000;\nstd::string ref_gtf_filename = \"\";\nstd::string mask_gtf_filename = \"\";\nstd::string contrast_filename = \"\";\nbool use_sample_sheet = false;\nstd::string norm_standards_filename = \"\";\nstd::string output_dir = \"./\";\nstd::string fasta_dir;\nstring default_library_type = \"fr-unstranded\";\nstring library_type = default_library_type;\n\n\n// Abundance estimation options\nbool corr_bias = false;\nbool corr_multi = false;\n\nBiasMode bias_mode = VLMM;\nint def_frag_len_mean = 200;\nint def_frag_len_std_dev = 80;\nint def_max_frag_len = 800;\nint max_frag_len = 800;\nint min_frag_len = 1;\nfloat min_isoform_fraction = 0.1;\nint max_mle_iterations = 5000;\nint num_importance_samples = 10000;\nbool use_compat_mass = false;\nbool use_total_mass = false;\nbool model_mle_error = false;\n\n// Ref-guided assembly options\nint overhang_3 = 600;\nint ref_merge_overhang_tolerance = 30;\nint tile_len = 405;\nint tile_off = 15;\nbool enable_faux_reads = true;\nbool enable_5_extend = true;\n\n// Assembly options\nuint32_t min_intron_length = 50;\nuint32_t max_intron_length = 300000;\nint olap_radius = 50;\nint bowtie_overhang_tolerance = 8; // Typically don't need to change this, except in special cases, such as meta-assembly.\nint min_frags_per_transfrag = 10;\nint microexon_length = 25;\nfloat pre_mrna_fraction = 0.15;\nfloat high_phred_err_prob = 0.50; // about MAPQ = 3\ndouble small_anchor_fraction = 7 / 75.0;\ndouble binomial_junc_filter_alpha = 0.001;\ndouble trim_3_dropoff_frac = .1;\ndouble trim_3_avgcov_thresh = 10.0;\nstd::string user_label = \"CUFF\";\n\nbool cond_prob_collapse = true;\n\nbool emit_count_tables = false;\nbool use_fisher_covariance = true;\nbool split_variance = false;\n\nint max_frags_per_bundle = 1000000;\n//bool analytic_diff = false;\nbool no_differential = false;\ndouble num_frag_count_draws = 100;\ndouble num_frag_assignments = 50;\ndouble max_multiread_fraction = 0.75;\ndouble max_frag_multihits = 10000000;\nint min_reps_for_js_test = 3;\nbool no_effective_length_correction = false;\nbool no_length_correction = false;\nbool no_js_tests = false;\n\nbool no_scv_correction = false;\n\ndouble min_outlier_p = 0.0001;\n\n\n// SECRET OPTIONS: \n// These options are just for instrumentation and benchmarking code\n\nfloat read_skip_fraction = 0.0;\nbool no_read_pairs = false;\nint trim_read_length = -1;\ndouble mle_accuracy = 1e-5;\n\n\n\n\n// END SECRET OPTIONS\n\nbool bias_run = false;\n\nstd::string cmd_str;\n\nmap<string, ReadGroupProperties> library_type_table;\nconst ReadGroupProperties* global_read_properties = NULL;\n\nmap<string, DispersionMethod> dispersion_method_table;\nstring default_dispersion_method = \"pooled\";\nDispersionMethod dispersion_method = DISP_NOT_SET;\n\nmap<string, LibNormalizationMethod> lib_norm_method_table;\nstring default_lib_norm_method = \"geometric\";\nstring default_cufflinks_lib_norm_method = \"classic-fpkm\";\nLibNormalizationMethod lib_norm_method = LIB_NORM_NOT_SET;\n\nboost::shared_ptr<const std::map<std::string, LibNormStandards> > lib_norm_standards;\n\n// Output format table for Cuffnorm:\nmap<string, OutputFormat> output_format_table;\nstring default_output_format = \"simple-table\"; // note: the default is only for cuffnorm, Cuffdiff always uess the cuffdiff format\nOutputFormat output_format = OUTPUT_FMT_NOT_SET;\n\n\n#if ENABLE_THREADS\nboost::thread_specific_ptr<std::string> bundle_label;\n#else\nboost::shared_ptr<std::string> bundle_label;\n#endif\n\nlong random_seed = 0;\n\nextern void print_usage();\n\nbool gaurd_assembly()\n{\n\treturn ref_gtf_filename == \"\";\n}\n\nvoid asm_verbose(const char* fmt,...)\n{\n#if !ASM_VERBOSE\n\treturn;\n#endif\n     va_list argp;\n     va_start(argp, fmt);\n     vfprintf(stderr, fmt, argp);\n     va_end(argp);\n}\n\nvoid verbose_msg(const char* fmt,...) {\n\n\tif (!cuff_verbose)\n\t\treturn;\n\t\n   va_list argp;\n   va_start(argp, fmt);\n   vfprintf(stderr, fmt, argp);\n   va_end(argp);\n}\n\n\n/**\n * Parse an int out of optarg and enforce that it be at least 'lower';\n * if it is less than 'lower', than output the given error message and\n * exit with an error and a usage message.\n */\n \n\nint parseInt(int lower, const char *errmsg, void (*print_usage)()) {\n    long l;\n    char *endPtr= NULL;\n    l = strtol(optarg, &endPtr, 10);\n    if (endPtr != NULL) {\n        if (l < lower) {\n            cerr << errmsg << endl;\n            print_usage();\n            exit(1);\n        }\n        return (int32_t)l;\n    }\n    cerr << errmsg << endl;\n    print_usage();\n    exit(1);\n    return -1;\n}\n\n/**\n * Parse an int out of optarg and enforce that it be at least 'lower';\n * if it is less than 'lower', than output the given error message and\n * exit with an error and a usage message.\n */\nfloat parseFloat(float lower, float upper, const char *errmsg, void (*print_usage)()) {\n    float l;\n    l = (float)atof(optarg);\n\t\n    if (l < lower) {\n        cerr << errmsg << endl;\n        print_usage();\n        exit(1);\n    }\n\t\n    if (l > upper)\n    {\n        cerr << errmsg << endl;\n        print_usage();\n        exit(1);\n    }\n\t\n    return l;\n\t\n    cerr << errmsg << endl;\n    print_usage();\n    exit(1);\n    return -1;\n}\n\n/* Function with behaviour like `mkdir -p'  */\n\nint mkpath(const char *s, mode_t mode)\n{\n    namespace fs = boost::filesystem;\n    namespace bs = boost::system;\n\n    // First try create the directory\n    try {\n        fs::create_directories(s);\n        try {\n            // Then make sure it is writable\n            fs::permissions(s, fs::owner_all | fs::add_perms);\n            errno = 0;\n            // Otherwise, exit\n        } catch (const fs::filesystem_error & ep) {\n            std::cerr << ep.what() << '\\n';\n            exit(-1);\n        }\n    } catch (const fs::filesystem_error & e) {\n        std::cerr << e.what() << '\\n';\n        exit(-1);\n    }\n\n    return 0;\n}\n\nvoid init_library_table()\n{\n    ReadGroupProperties fr_unstranded;\n    fr_unstranded.platform(UNKNOWN_PLATFORM);\n\tfr_unstranded.mate_strand_mapping(FR);\n    fr_unstranded.std_mate_orientation(MATES_POINT_TOWARD);\n    fr_unstranded.strandedness(UNSTRANDED_PROTOCOL);\n    \n    library_type_table[\"fr-unstranded\"] = fr_unstranded;\n        \t\n\tReadGroupProperties fr_firststrand;\n    fr_firststrand.platform(UNKNOWN_PLATFORM);\n\tfr_firststrand.mate_strand_mapping(RF);\n    fr_firststrand.std_mate_orientation(MATES_POINT_TOWARD);\n    fr_firststrand.strandedness(STRANDED_PROTOCOL);\n\t\n    library_type_table[\"fr-firststrand\"] = fr_firststrand;\n\n\tReadGroupProperties fr_secondstrand;\n    fr_secondstrand.platform(UNKNOWN_PLATFORM);\n\tfr_secondstrand.mate_strand_mapping(FR);\n    fr_secondstrand.std_mate_orientation(MATES_POINT_TOWARD);\n    fr_secondstrand.strandedness(STRANDED_PROTOCOL);\n\t\n    library_type_table[\"fr-secondstrand\"] = fr_secondstrand;\n\t\n\tReadGroupProperties ff_unstranded;\n    ff_unstranded.platform(UNKNOWN_PLATFORM);\n\tff_unstranded.mate_strand_mapping(FF);\n    ff_unstranded.std_mate_orientation(MATES_POINT_TOWARD);\n    ff_unstranded.strandedness(UNSTRANDED_PROTOCOL);\n    \n    library_type_table[\"ff-unstranded\"] = ff_unstranded;\n\t\n\tReadGroupProperties ff_firststrand;\n    ff_firststrand.platform(UNKNOWN_PLATFORM);\n\tff_firststrand.mate_strand_mapping(FF);\n    ff_firststrand.std_mate_orientation(MATES_POINT_TOWARD);\n    ff_firststrand.strandedness(STRANDED_PROTOCOL);\n\t\n    library_type_table[\"ff-firststrand\"] = ff_firststrand;\n\t\n\tReadGroupProperties ff_secondstrand;\n    ff_secondstrand.platform(UNKNOWN_PLATFORM);\n\tff_secondstrand.mate_strand_mapping(RR);\n    ff_secondstrand.std_mate_orientation(MATES_POINT_TOWARD);\n    ff_secondstrand.strandedness(STRANDED_PROTOCOL);\n\t\n    library_type_table[\"ff-secondstrand\"] = ff_secondstrand;\n    \n    ReadGroupProperties transfrags;\n    transfrags.platform(UNKNOWN_PLATFORM);\n\ttransfrags.mate_strand_mapping(FR);\n    transfrags.std_mate_orientation(MATES_POINT_TOWARD);\n    transfrags.strandedness(UNSTRANDED_PROTOCOL);\n\ttransfrags.complete_fragments(true);\n    \n    library_type_table[\"transfrags\"] = transfrags;\n\t\n    //global_read_properties = &(library_type_table.find(default_library_type)->second);\n}\n\nvoid print_library_table()\n{\n    fprintf (stderr, \"\\nSupported library types:\\n\");\n    for (map<string, ReadGroupProperties>::const_iterator itr = library_type_table.begin();\n         itr != library_type_table.end();\n         ++itr)\n    {\n        if (itr->first == default_library_type)\n        {\n            fprintf(stderr, \"\\t%s (default)\\n\", itr->first.c_str());\n        }\n        else            \n        {\n            fprintf(stderr, \"\\t%s\\n\", itr->first.c_str());\n        }\n    }\n}\n\nvoid init_dispersion_method_table()\n{\n    dispersion_method_table[\"pooled\"] = POOLED;\n    dispersion_method_table[\"blind\"] = BLIND;\n    dispersion_method_table[\"per-condition\"] = PER_CONDITION;\n    dispersion_method_table[\"poisson\"] = POISSON;\n}\n\nvoid print_dispersion_method_table()\n{\n    fprintf (stderr, \"\\nSupported dispersion methods:\\n\");\n    for (map<string, DispersionMethod>::const_iterator itr = dispersion_method_table.begin();\n         itr != dispersion_method_table.end();\n         ++itr)\n    {\n        if (itr->first == default_dispersion_method)\n        {\n            fprintf(stderr, \"\\t%s (default)\\n\", itr->first.c_str());\n        }\n        else\n        {\n            fprintf(stderr, \"\\t%s\\n\", itr->first.c_str());\n        }\n    }\n}\n\n\nvoid init_lib_norm_method_table()\n{\n    lib_norm_method_table[\"geometric\"] = GEOMETRIC;\n    lib_norm_method_table[\"classic-fpkm\"] = CLASSIC_FPKM;\n    lib_norm_method_table[\"quartile\"] = QUARTILE;\n}\n\nvoid init_cufflinks_lib_norm_method_table()\n{\n    lib_norm_method_table[\"classic-fpkm\"] = CLASSIC_FPKM;\n    //lib_norm_method_table[\"quartile\"] = QUARTILE;\n    //lib_norm_method_table[\"absolute\"] = ABSOLUTE;\n}\n\n\nvoid print_lib_norm_method_table()\n{\n    fprintf (stderr, \"\\nSupported library normalization methods:\\n\");\n    for (map<string, LibNormalizationMethod>::const_iterator itr = lib_norm_method_table.begin();\n         itr != lib_norm_method_table.end();\n         ++itr)\n    {\n        if (itr->first == default_lib_norm_method)\n        {\n            fprintf(stderr, \"\\t%s (default)\\n\", itr->first.c_str());\n        }\n        else if(itr->first == \"estimated-absolute\") // hide this one for now.\n        {\n            continue;\n        }\n        {\n            fprintf(stderr, \"\\t%s\\n\", itr->first.c_str());\n        }\n    }\n}\n\nvoid init_output_format_table()\n{\n    output_format_table[\"cuffdiff\"] = CUFFDIFF_OUTPUT_FMT;\n    output_format_table[\"simple-table\"] = SIMPLE_TABLE_OUTPUT_FMT;\n}\n\nvoid print_output_format_table()\n{\n    fprintf (stderr, \"\\nSupported output formats:\\n\");\n    for (map<string, OutputFormat>::const_iterator itr = output_format_table.begin();\n         itr != output_format_table.end();\n         ++itr)\n    {\n        if (itr->first == default_output_format)\n        {\n            fprintf(stderr, \"\\t%s (default)\\n\", itr->first.c_str());\n        }\n        else\n        {\n            fprintf(stderr, \"\\t%s\\n\", itr->first.c_str());\n        }\n    }\n}\n\n\n\n// c_seq is complement, *NOT* REVERSE complement\nvoid encode_seq(const string seqStr, char* seq, char* c_seq)\n{\n    \n\tfor (size_t i = 0; i < seqStr.length(); ++i)\n\t{\n\t\tswitch(seqStr[i])\n\t\t{\n\t\t\tcase 'A' : \n\t\t\tcase 'a' : seq[i] = 0; c_seq[i] = 3; break;\n\t\t\tcase 'c' : \n\t\t\tcase 'C' : seq[i] = 1; c_seq[i] = 2; break;\n\t\t\tcase 'G' :\n\t\t\tcase 'g' : seq[i] = 2; c_seq[i] = 1; break;\n\t\t\tcase 'T' :\n\t\t\tcase 't' : seq[i] = 3; c_seq[i] = 0; break;\n\t\t\tdefault  : seq[i] = 4; c_seq[i] = 4; break; // N\n\t\t}\n\t}\n}\n\n\nReadGroupProperties::ReadGroupProperties() : \n    _strandedness(UNKNOWN_STRANDEDNESS), \n    _std_mate_orient(UNKNOWN_MATE_ORIENTATION),\n    _platform(UNKNOWN_PLATFORM),\n    _total_map_mass(0.0),\n    _norm_map_mass(0.0),\n    _internal_scale_factor(1.0),\n    _external_scale_factor(1.0),\n    _complete_fragments(false)\n{\n    _mass_dispersion_model = boost::shared_ptr<MassDispersionModel const>(new PoissonDispersionModel(\"\"));\n} \n"
  },
  {
    "path": "src/common.h",
    "content": "#ifndef COMMON_H\n#define COMMON_H\n/*\n *  common.h\n *  Cufflinks\n *\n *  Created by Cole Trapnell on 11/26/08.\n *  Copyright 2008 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <boost/version.hpp>\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#else\n#define PACKAGE_VERSION \"INTERNAL\"\n#define SVN_REVISION \"XXX\"\n#define BOOST_VERSION 104700\n#endif\n\n#include <stdint.h>\n#include <cassert>\n#include <string>\n#include <utility>\n\n#include <boost/math/distributions/normal.hpp> \nusing boost::math::normal;\n\n#include <boost/archive/tmpdir.hpp>\n\n#include <boost/archive/binary_iarchive.hpp>\n#include <boost/archive/binary_oarchive.hpp>\n\n#include <boost/serialization/base_object.hpp>\n#include <boost/serialization/utility.hpp>\n#include <boost/serialization/list.hpp>\n#include <boost/serialization/map.hpp>\n#include <boost/serialization/set.hpp>\n#include <boost/serialization/vector.hpp>\n#include <boost/serialization/assume_abstract.hpp>\n#include <boost/serialization/shared_ptr.hpp>\n#include <boost/serialization/export.hpp>\n\n#include <boost/foreach.hpp>\n\n#include <boost/thread.hpp>\n#include <boost/shared_ptr.hpp>\n\n#include <boost/crc.hpp>\n\n#include <boost/filesystem.hpp>\n\n// Non-option globals\nextern bool final_est_run;\nextern bool allow_junk_filtering;\nextern bool user_provided_fld;\nextern int def_max_frag_len;\nextern int max_frag_len;\nextern int min_frag_len;\n\n// Behavior options\nextern int num_threads;\nextern bool no_update_check;\nextern bool cuff_quiet;\nextern bool cuff_verbose;\nextern bool output_fld;\nextern bool output_bias_params;\n\n// General options\nextern int max_partner_dist;\nextern uint32_t max_gene_length;\nextern std::string ref_gtf_filename;\nextern std::string mask_gtf_filename;\nextern std::string contrast_filename;\nextern std::string norm_standards_filename;\nextern bool use_sample_sheet;\nextern std::string output_dir;\nextern std::string fasta_dir;\nextern std::string library_type;\n\n// Abundance estimation options\nextern bool corr_bias;\nextern bool corr_multi;\n\nextern int def_frag_len_mean;\nextern int def_frag_len_std_dev;\nextern int max_mle_iterations;\nextern int num_importance_samples;\nextern float min_isoform_fraction;\nextern bool cond_prob_collapse;\nextern bool use_compat_mass;\nextern bool use_total_mass;\nextern bool model_mle_error;\n\n// Ref-guided assembly options\nextern int overhang_3;\nextern int ref_merge_overhang_tolerance;\nextern int tile_len;\nextern int tile_off;\nextern bool enable_faux_reads;\nextern bool enable_5_extend;\n\n// Assembly options\nextern uint32_t min_intron_length;\nextern uint32_t max_intron_length;\nextern int olap_radius;\nextern int bowtie_overhang_tolerance;\nextern int min_frags_per_transfrag;\nextern int microexon_length;\nextern float pre_mrna_fraction;\nextern float high_phred_err_prob;\nextern double trim_3_dropoff_frac;\nextern double trim_3_avgcov_thresh;\nextern double small_anchor_fraction;\nextern double binomial_junc_filter_alpha;\nextern std::string user_label;\nextern long random_seed;\nextern bool emit_count_tables;\nextern bool use_fisher_covariance;\nextern bool split_variance;\n\nextern int max_frags_per_bundle;\n//extern bool analytic_diff;\nextern bool no_differential;\nextern double num_frag_count_draws;\nextern double num_frag_assignments;\nextern double max_multiread_fraction;\nextern double max_frag_multihits;\nextern int min_reps_for_js_test;\nextern bool no_effective_length_correction;\nextern bool no_length_correction;\nextern bool no_js_tests;\n\nextern bool no_scv_correction;\n\nextern double min_outlier_p;\n\n\nextern std::string default_dispersion_method;\nextern std::string default_lib_norm_method;\nextern std::string default_cufflinks_lib_norm_method;\nextern std::string default_output_format;\n\n// SECRET OPTIONS: \n// These options are just for instrumentation and benchmarking code\n\nextern bool no_read_pairs;\nextern float read_skip_fraction;\nextern int trim_read_length;\nextern double mle_accuracy;\n\n// END SECRET OPTIONS\n\n#define ASM_VERBOSE 0\n#define ENABLE_THREADS 1\n\n#if ENABLE_THREADS\nextern boost::thread_specific_ptr<std::string> bundle_label; // for consistent, traceable logging\n#else\nextern boost::shared_ptr<std::string> bundle_label;\n#endif\n\n// Global switch to mark when we're in the middle of learning bias.\nextern bool bias_run;\n\n// Hold the command line string used to run the program\nextern std::string cmd_str;\n\nbool gaurd_assembly();\n\nvoid asm_verbose(const char* fmt,...);\nvoid verbose_msg(const char* fmt,...); \n\nint parseInt(int lower, \n\t\t\t const char *errmsg, \n\t\t\t void (*print_usage)());\n\nfloat parseFloat(float lower, \n\t\t\t\t float upper, \n\t\t\t\t const char *errmsg, \n\t\t\t\t void (*print_usage)());\n\nvoid encode_seq(const std::string seqStr, char* seq, char* c_seq);\nint mkpath(const char *s, mode_t mode);\n\n\ntemplate<typename InputIterator,\n\t\t typename OutputIterator,\n\t\t typename Predicate>\nOutputIterator copy_if(InputIterator begin,\n\t\t\t\t\t   InputIterator end,\n\t\t\t\t\t   OutputIterator destBegin,\n\t\t\t\t\t   Predicate p)\n{\n\twhile (begin != end)\n\t{\n\t\tif (p(*begin)) *destBegin++ = *begin;\n\t\t++begin;\n\t}\n\treturn destBegin;\n}\n\nenum BundleMode\n{\n\tHIT_DRIVEN,\n\tREF_DRIVEN,\n\tREF_GUIDED\n};\nextern BundleMode bundle_mode;\nextern BundleMode init_bundle_mode;\n\nenum BiasMode\n{\n\tSITE,\n\tVLMM,\n\tPOS,\n\tPOS_VLMM,\n    POS_SITE\n};\nextern BiasMode bias_mode;\n\nenum Strandedness \n{\n    UNKNOWN_STRANDEDNESS,\n\tSTRANDED_PROTOCOL,\n    UNSTRANDED_PROTOCOL\n};\n\nenum StandardMateOrientation\n{\n    UNKNOWN_MATE_ORIENTATION,\n    MATES_POINT_TOWARD,\n    MATES_POINT_SAME,\n    MATES_POINT_AWAY,\n    UNPAIRED,\n};\n\nenum MateStrandMapping\n{\n\tFF,\n\tFR,\n\tRF, // This is really FR with first-strandedness\n\tRR // This is really FF with first-strandedness\n};\n\nenum Platform\n{\n    UNKNOWN_PLATFORM,\n    ILLUMINA,\n    SOLID\n};\n\nenum FLDSource\n{\n    LEARNED,\n    USER,\n    DEFAULT\n};\n\nenum DispersionMethod\n{\n    DISP_NOT_SET,\n    BLIND,\n    PER_CONDITION,\n    POOLED,\n    POISSON\n};\n\nenum LibNormalizationMethod\n{\n    LIB_NORM_NOT_SET,\n    GEOMETRIC,\n    CLASSIC_FPKM,\n    TMM,\n    QUARTILE,\n    ABSOLUTE // Requires spike-in controls, not yet implemented\n};\n\nenum OutputFormat\n{\n    OUTPUT_FMT_NOT_SET,\n    CUFFDIFF_OUTPUT_FMT,\n    SIMPLE_TABLE_OUTPUT_FMT\n};\n\n\nclass EmpDist\n{\n\t//Vectors only valid between min and max!\n\tstd::vector<double> _pdf;\n\tstd::vector<double> _cdf;\n\tint _mode;\n\tdouble _mean;\n    double _std_dev;\n\tint _min;\n\tint _max;\n\tFLDSource _source;\n    \n    EmpDist() {}\n    \n    friend std::ostream & operator<<(std::ostream &os, const EmpDist &gp);\n    friend class boost::serialization::access;\n    \n    template<class Archive>\n    void serialize(Archive & ar, const unsigned int /* file_version */){\n        ar & _pdf;\n        ar & _cdf;\n        ar & _mode;\n        ar & _mean;\n        ar & _std_dev;\n        ar & _min;\n        ar & _max;\n        ar & _source;\n    }\n    \npublic:\n\tEmpDist(std::vector<double>& pdf, std::vector<double>& cdf, int mode, double mean, double std_dev, int min, int max, FLDSource source)\n\t: _pdf(pdf), _cdf(cdf), _mode(mode), _mean(mean), _std_dev(std_dev), _min(min), _max(max), _source(source) {}\n\t\n\tvoid pdf(std::vector<double>& pdf)\t{ _pdf = pdf; }\n\tdouble pdf(int l) const\n\t{\n\t\tif (!valid_len(l))\n\t\t\treturn 0.0;\n\t\treturn _pdf[l];\n\t}\n\t\n\t// pdf renomalized over the lengths <= r\n\tdouble npdf(int l, int r) const\n \t{\n\t\tif (!valid_len(l))\n\t\t\treturn 0.0;\n\t\t\n\t\tif (r > _max || r == 0)\n\t\t\treturn pdf(l);\n\t\t\n\t\treturn pdf(l)/cdf(r);\n\t}\n\t\n\tvoid cdf(std::vector<double>& cdf)\t{ _cdf = cdf; }\n\tdouble cdf(int l) const\n\t{\n\t\tif (l > _max)\n\t\t\treturn 1.0;\n        if (l < 0)\n            return 0.0;\n\t\treturn _cdf[l];\n\t}\n\t\n\tbool valid_len(int l) const { return (l >= _min && l <= _max); }\n\tbool too_short(int l) const { return (l < _min); }\n\t\n\tvoid mode(int mode)\t\t\t\t{ _mode = mode; }\n\tint mode() const\t\t\t\t{ return _mode; }\n\t\n\tvoid max(int max)\t\t\t\t{ _max = max;  }\n\tint max() const\t\t\t\t\t{ return _max; }\n\t\n\tvoid min(int min)\t\t\t\t{ _min = min;  }\n\tint min() const\t\t\t\t\t{ return _min; }\n    \n    void mean(double mean)\t\t\t\t{ _mean = mean;  }\n\tdouble mean() const\t\t\t\t\t{ return _mean; }\n    \n    void std_dev(double std_dev)\t\t\t\t{ _std_dev = std_dev;  }\n\tdouble std_dev() const\t\t\t\t\t{ return _std_dev; }\n    \n    FLDSource source() const        { return _source; }\n    void source(FLDSource source)   { _source = source; } \n};\n\nclass BiasLearner;\nclass MultiReadTable;\n\nclass MassDispersionModel;\nclass MleErrorModel;\n\nstruct LocusCount\n{\n    LocusCount(std::string ld, double c, int nt, const std::vector<std::string>& gids, const std::vector<std::string>& gnms) :\n        locus_desc(ld), count(c), num_transcripts(nt), gene_ids(gids), gene_short_names(gnms) {}\n    std::string locus_desc;\n    double count;\n    int num_transcripts;\n    std::vector<std::string> gene_ids;\n    std::vector<std::string> gene_short_names;\n    \nprivate:\n    \n    LocusCount() {} //needs an empty constructor for serialization\n\n    friend std::ostream & operator<<(std::ostream &os, const LocusCount &gp);\n    friend class boost::serialization::access;\n    \n//    template<class Archive>\n//    void serialize(Archive & ar, const unsigned int /* file_version */){\n//        ar & locus_desc;\n//        ar & count;\n//        ar & num_transcripts;\n//        ar & gene_ids;\n//        ar & gene_short_names;\n//    }\n    template<class Archive>\n    void save(Archive & ar, const unsigned int version) const\n    {\n        ar & locus_desc;\n        ar & count;\n        ar & num_transcripts;\n        ar & gene_ids;\n        ar & gene_short_names;\n    }\n    template<class Archive>\n    void load(Archive & ar, const unsigned int version)\n    {\n        // create some temporaries, because we don't want to load the whole LocusCount;\n        std::string dsc;\n        ar & dsc;\n        ar & count;\n        ar & num_transcripts;\n        std::vector<std::string> gids;\n        ar & gids;\n        std::vector<std::string> gsns;\n        ar & gsns;\n    }\n    BOOST_SERIALIZATION_SPLIT_MEMBER()\n\n};\n\n// This class stores user-supplied options that affect quantification\n// We'll serialize these into abundance files (i.e. CXB files)\n// so we can ensure that they're consistent across all samples\n// provided to cuffnorm and cuffdiff.\nstruct CheckedParameters\n{\n    CheckedParameters() :\n        frag_len_mean(0.0),\n        frag_len_std_dev(0.0),\n        corr_bias(0.0),\n        frag_bias_mode(VLMM),\n        corr_multireads(false),\n        max_mle_iterations(false),\n        min_mle_accuracy(0.0),\n        max_bundle_frags(0.0),\n        max_frags_multihits(0.0),\n        no_effective_length_correction(false),\n        no_length_correction(false),\n        ref_gtf_file_path(\"\"),\n        ref_gtf_crc(0),\n        mask_gtf_file_path(\"\"),\n        mask_gtf_crc(0)\n    {} //needs an empty constructor for serialization\n    \n    double frag_len_mean;\n    double frag_len_std_dev;\n    \n    // TODO: add CRCs for reference GTF, mask file\n    bool corr_bias;\n    \n    BiasMode frag_bias_mode;\n    bool corr_multireads;\n    \n    double max_mle_iterations;\n    double min_mle_accuracy;\n    \n    double max_bundle_frags;\n    double max_frags_multihits;\n    \n    bool no_effective_length_correction;\n    bool no_length_correction;\n    \n    std::string ref_gtf_file_path;\n    boost::crc_32_type::value_type ref_gtf_crc;\n    \n    std::string mask_gtf_file_path;\n    boost::crc_32_type::value_type mask_gtf_crc;\n    \n    friend std::ostream & operator<<(std::ostream &os, const CheckedParameters &gp);\n    friend class boost::serialization::access;\n    \n    template<class Archive>\n    void serialize(Archive & ar, const unsigned int /* file_version */){\n        ar & frag_len_mean;\n        ar & frag_len_std_dev;\n        ar & corr_bias;\n        ar & frag_bias_mode;\n        ar & corr_multireads;\n        ar & max_mle_iterations;\n        ar & min_mle_accuracy;\n        ar & max_bundle_frags;\n        ar & max_frags_multihits;\n        ar & no_effective_length_correction;\n        ar & no_length_correction;\n        ar & ref_gtf_file_path;\n        ar & ref_gtf_crc;\n        ar & mask_gtf_file_path;\n        ar & mask_gtf_crc;\n    }\n    \n    bool operator!=(const CheckedParameters& rhs) const {\n        return !(*this == rhs);\n    }\n    \n    bool operator==(const CheckedParameters& rhs) const\n    {\n        return (frag_len_mean == rhs.frag_len_mean &&\n                frag_len_std_dev == rhs.frag_len_std_dev &&\n                corr_bias == rhs.corr_bias &&\n                frag_bias_mode  == rhs.frag_bias_mode &&\n                corr_multireads == rhs.corr_multireads &&\n                max_mle_iterations  == rhs.max_mle_iterations &&\n                min_mle_accuracy == rhs.min_mle_accuracy &&\n                max_bundle_frags == rhs.max_bundle_frags &&\n                max_frags_multihits == rhs.max_frags_multihits &&\n                no_effective_length_correction == rhs.no_effective_length_correction &&\n                no_length_correction == rhs.no_length_correction &&\n                ref_gtf_file_path == rhs.ref_gtf_file_path &&\n                ref_gtf_crc == rhs.ref_gtf_crc &&\n                mask_gtf_file_path == rhs.mask_gtf_file_path &&\n                mask_gtf_crc == rhs.mask_gtf_crc);\n                \n    }\n\n};\n\nclass ReadGroupProperties\n{\npublic:\n    \n    ReadGroupProperties(); \n    \n    Strandedness strandedness() const { return _strandedness; }\n    void strandedness(Strandedness s) { _strandedness = s; }\n    \n    StandardMateOrientation std_mate_orientation() const { return _std_mate_orient; }\n    void std_mate_orientation(StandardMateOrientation so)  { _std_mate_orient = so; }\n    \n\tMateStrandMapping mate_strand_mapping() const { return _mate_strand_mapping; }\n\tvoid mate_strand_mapping(MateStrandMapping msm) { _mate_strand_mapping = msm; }\n\t\n    Platform platform() const { return _platform; }\n    void platform(Platform p)  { _platform = p; }   \n    \n    long double total_map_mass() const { return _total_map_mass; }\n    void total_map_mass(long double p)  { _total_map_mass = p; }  \n    \n    long double normalized_map_mass() const { return _norm_map_mass; }\n    void normalized_map_mass(long double p)  { _norm_map_mass = p; }  \n    \n    boost::shared_ptr<EmpDist const> frag_len_dist() const { return _frag_len_dist; }\n    void frag_len_dist(boost::shared_ptr<EmpDist const> p)  { _frag_len_dist = p; }\n    \n\tboost::shared_ptr<BiasLearner const> bias_learner() const { return _bias_learner; }\n    void bias_learner(boost::shared_ptr<BiasLearner const> bl)  { _bias_learner = bl; } \n\t\n    // The internal scaling factor relates replicates to each other, so\n    // that replicates with larger library sizes don't bias the isoform\n    // deconvolution over smaller libraries\n    void internal_scale_factor(double sf) { _internal_scale_factor = sf; }\n    double internal_scale_factor() const  { return _internal_scale_factor; }\n    \n    void external_scale_factor(double sf) { _external_scale_factor = sf; }\n    double external_scale_factor() const  { return _external_scale_factor; }\n    \n    void complete_fragments(bool c)  { _complete_fragments = c; }\n    bool complete_fragments() const { return _complete_fragments; }\n    \n    double internally_scale_mass(double unscaled_mass) const \n    { \n        if (_internal_scale_factor == 0)\n            return unscaled_mass;\n        \n        return unscaled_mass * (1.0 / _internal_scale_factor);\n    }\n    \n    boost::shared_ptr<const MassDispersionModel> mass_dispersion_model() const\n    { \n        return _mass_dispersion_model; \n    };\n    \n    void mass_dispersion_model(boost::shared_ptr<const MassDispersionModel> nm) \n    { \n        _mass_dispersion_model = nm; \n    }\n    \n    boost::shared_ptr<const MleErrorModel> mle_error_model() const\n    {\n        return _mle_error_model;\n    };\n    \n    void mle_error_model(boost::shared_ptr<const MleErrorModel> nm)\n    {\n        _mle_error_model = nm;\n    }\n    \n    const std::vector<LocusCount>& common_scale_compatible_counts() { return _common_scale_compatible_counts; }\n    void common_scale_compatible_counts(const std::vector<LocusCount>& counts) { _common_scale_compatible_counts = counts; }\n    \n    const std::vector<LocusCount>& common_scale_total_counts() { return _common_scale_total_counts; }\n    void common_scale_total_counts(const std::vector<LocusCount>& counts) { _common_scale_total_counts = counts; }\n    \n    const std::vector<LocusCount>& raw_compatible_counts() { return _raw_compatible_counts; }\n    void raw_compatible_counts(const std::vector<LocusCount>& counts) { _raw_compatible_counts = counts; }\n    \n    const std::vector<LocusCount>& raw_total_counts() { return _raw_total_counts; }\n    void raw_total_counts(const std::vector<LocusCount>& counts) { _raw_total_counts = counts; }\n    \n    void clear_count_tables() {\n        _common_scale_compatible_counts.clear();\n        std::vector<LocusCount>().swap(_common_scale_compatible_counts);\n        \n        _common_scale_total_counts.clear();\n        std::vector<LocusCount>().swap(_common_scale_total_counts);\n        \n        _raw_compatible_counts.clear();\n        std::vector<LocusCount>().swap(_raw_compatible_counts);\n        \n        _raw_total_counts.clear();\n        std::vector<LocusCount>().swap(_raw_total_counts);\n    }\n    \n\tboost::shared_ptr<MultiReadTable> multi_read_table() const {return _multi_read_table; }\t\n\tvoid multi_read_table(boost::shared_ptr<MultiReadTable> mrt) { _multi_read_table = mrt;\t}\n\t\n//    const string& description() const { return _description; }\n//    void description(const string& d) { _description = d; }\n    \n    const std::string& condition_name() const { return _condition_name; }\n    void condition_name(const std::string& cd) { _condition_name = cd; }\n    \n    const std::string& file_path() const { return _file_path; }\n    void file_path(const std::string& fp) { _file_path = fp; }\n    \n    int replicate_num() const { return _replicate_num; }\n    void replicate_num(int rn) { _replicate_num = rn; }\n    \n    void ref_gtf(const std::string& file_path, const boost::crc_32_type& gtf_crc )\n    {\n        _checked_params.ref_gtf_file_path = file_path;\n        _checked_params.ref_gtf_crc = gtf_crc();\n    }\n\n    void mask_gtf(const std::string& file_path, const boost::crc_32_type& gtf_crc )\n    {\n        _checked_params.mask_gtf_file_path = file_path;\n        _checked_params.mask_gtf_crc = gtf_crc();\n    }\n\n    \n    const CheckedParameters& checked_parameters() const { return _checked_params; }\n    void checked_parameters(const CheckedParameters& rhs) { _checked_params = rhs; }\n    \n    // NOTE: this only picks up user-supplied options, not GTF files!\n    void collect_checked_parameters() {\n        \n        _checked_params.frag_len_mean = def_frag_len_mean;\n        _checked_params.frag_len_std_dev = def_frag_len_std_dev;\n        \n        // TODO: add CRCs for reference GTF, mask file, norm standards file if using.\n        _checked_params.corr_bias = corr_bias;\n        \n        _checked_params.frag_bias_mode = bias_mode;\n        _checked_params.corr_multireads = corr_multi;\n        \n        _checked_params.max_mle_iterations = max_mle_iterations;\n        _checked_params.min_mle_accuracy = mle_accuracy;\n        \n        _checked_params.max_bundle_frags = max_frags_per_bundle;\n        _checked_params.max_frags_multihits = max_frag_multihits;\n        \n        _checked_params.no_effective_length_correction = no_effective_length_correction;\n        _checked_params.no_length_correction = no_length_correction;\n    }\n    \n    \nprivate:\n    \n    friend std::ostream & operator<<(std::ostream &os, const ReadGroupProperties &gp);\n    friend class boost::serialization::access;\n    \n    template<class Archive>\n    void serialize(Archive & ar, const unsigned int /* file_version */){\n        ar & _strandedness;\n        ar & _std_mate_orient;\n        ar & _mate_strand_mapping;\n        ar & _platform;\n        ar & _total_map_mass;\n        ar & _norm_map_mass;\n        ar & _frag_len_dist;\n        // TODO: probably should serialize the bias parameters somehow.\n        //ar & _bias_learner;\n        //ar & _multi_read_table; // we should never need this, I think.\n        ar & _internal_scale_factor;\n        ar & _external_scale_factor;\n        //ar & _mass_dispersion_model;\n        ar & _common_scale_compatible_counts;\n        ar & _common_scale_total_counts;\n        ar & _raw_compatible_counts;\n        ar & _raw_total_counts;\n        //ar & _mle_error_model;\n        ar & _complete_fragments;\n        ar & _condition_name;\n        ar & _file_path;\n        ar & _replicate_num;\n        ar & _checked_params;\n    }\n    \n    Strandedness _strandedness;\n    StandardMateOrientation _std_mate_orient;\n\tMateStrandMapping _mate_strand_mapping;\n    Platform _platform;\n    long double _total_map_mass;\n    long double _norm_map_mass;\n    boost::shared_ptr<EmpDist const> _frag_len_dist;\n\tboost::shared_ptr<BiasLearner const> _bias_learner;\n\tboost::shared_ptr<MultiReadTable> _multi_read_table;\n    \n    double _internal_scale_factor;\n    double _external_scale_factor;\n    boost::shared_ptr<const MassDispersionModel> _mass_dispersion_model;\n    std::vector<LocusCount> _common_scale_compatible_counts;\n    std::vector<LocusCount> _common_scale_total_counts;\n    std::vector<LocusCount> _raw_compatible_counts;\n    std::vector<LocusCount> _raw_total_counts;\n\n    boost::shared_ptr<const MleErrorModel> _mle_error_model;\n    \n    bool _complete_fragments;\n    \n    std::string _condition_name;\n    std::string _file_path;\n    int _replicate_num;\n    \n    CheckedParameters _checked_params;\n};\n\nBOOST_SERIALIZATION_SHARED_PTR(ReadGroupProperties)\n\nextern std::map<std::string, ReadGroupProperties> library_type_table;\n\nextern const ReadGroupProperties* global_read_properties;\n\nextern std::map<std::string, DispersionMethod> dispersion_method_table;\nextern DispersionMethod dispersion_method;\n\nextern std::map<std::string, LibNormalizationMethod> lib_norm_method_table;\nextern LibNormalizationMethod lib_norm_method;\n\nextern std::map<std::string, OutputFormat> output_format_table;\nextern OutputFormat output_format;\n\n\nvoid print_library_table();\nvoid init_library_table();\n\nvoid print_dispersion_method_table();\nvoid init_dispersion_method_table();\n\nvoid print_lib_norm_method_table();\nvoid init_lib_norm_method_table();\nvoid init_cufflinks_lib_norm_method_table();\n\nvoid print_output_format_table();\nvoid init_output_format_table();\n\n\nstruct LibNormStandards\n{\n    \n};\n\nextern boost::shared_ptr<const std::map<std::string, LibNormStandards> > lib_norm_standards;\n\ntemplate<typename T>\nstd::string cat_strings(const T& container, const char* delimiter=\",\")\n{\n    std::string cat;\n\tif (container.empty())\n\t{\n\t\tcat = \"\";\n\t}\n\telse\n\t{\n\t\ttypename T::const_iterator itr = container.begin();\n\t\t//cat = *(itr);\n\t\tfor (; itr != container.end(); itr++)\n\t\t{\n\t\t\tif (!(*itr).empty()) {\n\t\t\t\tif (!cat.empty()) cat += delimiter;\n\t\t\t\tcat += *itr; \n            }\n\t\t}\n\t}\n    \n\treturn cat;\n}\n\n#define OPT_NUM_IMP_SAMPLES         260\n#define OPT_MLE_MAX_ITER            261\n#define OPT_FDR                     262\n#define OPT_LIBRARY_TYPE            263\n#define OPT_OVERHANG_TOLERANCE      264\n#define OPT_MAX_BUNDLE_LENGTH       265\n#define OPT_MIN_FRAGS_PER_TRANSFRAG 266\n#define OPT_BIAS_MODE               267\n#define OPT_MIN_INTRON_LENGTH       268\n#define OPT_3_PRIME_AVGCOV_THRESH\t269\n#define OPT_3_PRIME_DROPOFF_FRAC    270\n#define OPT_POISSON_DISPERSION      271\n#define OPT_NO_UPDATE_CHECK         272\n#define OPT_OUTPUT_FLD              273\n#define OPT_OUTPUT_BIAS_PARAMS      274\n#define OPT_USE_EM                  275\n#define OPT_COLLAPSE_COND_PROB      276\n#define OPT_RANDOM_SEED             277\n#define OPT_NO_FAUX_READS           278\n#define OPT_3_OVERHANG_TOLERANCE    279\n#define OPT_INTRON_OVERHANG_TOLERANCE 280\n#define OPT_EMIT_COUNT_TABLES       281\n#define OPT_USE_COMPAT_MASS         282\n#define OPT_USE_TOTAL_MASS          283\n#define OPT_USE_FISHER_COVARIANCE   284\n#define OPT_USE_EMPIRICAL_COVARIANCE   285\n#define OPT_SPLIT_MASS              286\n#define OPT_SPLIT_VARIANCE          287\n#define OPT_TILE_LEN                291\n#define OPT_TILE_SEP                292\n#define OPT_NO_5_EXTEND             293\n#define OPT_MAX_FRAGS_PER_BUNDLE    294\n#define OPT_READ_SKIP_FRACTION      295\n#define OPT_NO_READ_PAIRS           296\n#define OPT_TRIM_READ_LENGTH        297\n#define OPT_MAX_DELTA_GAP           298\n#define OPT_MLE_MIN_ACC             299\n//#define OPT_ANALYTIC_DIFF           300\n#define OPT_NO_DIFF                 301\n#define OPT_GEOMETRIC_NORM          302\n#define OPT_RAW_MAPPED_NORM         303\n#define OPT_NUM_FRAG_COUNT_DRAWS    304\n#define OPT_NUM_FRAG_ASSIGN_DRAWS   305\n#define OPT_MAX_MULTIREAD_FRACTION  306\n#define OPT_LOCUS_COUNT_DISPERSION  307\n#define OPT_MIN_OUTLIER_P           308\n#define OPT_FRAG_MAX_MULTIHITS      309\n#define OPT_MIN_REPS_FOR_JS_TEST    310\n#define OPT_OLAP_RADIUS             311\n#define OPT_NO_LENGTH_CORRECTION    312\n#define OPT_NO_EFFECTIVE_LENGTH_CORRECTION    313\n#define OPT_NO_JS_TESTS             314\n#define OPT_DISPERSION_METHOD       315\n#define OPT_LIB_NORM_METHOD         316\n#define OPT_NO_SCV_CORRECTION       317\n#define OPT_NORM_STANDARDS_FILE     318\n#define OPT_USE_SAMPLE_SHEET        319\n#define OPT_OUTPUT_FORMAT           320\n#endif\n"
  },
  {
    "path": "src/compress_gtf.cpp",
    "content": "/*\n *  gtf_to_sam.cpp\n *  Cufflinks\n *\n *  Created by Cole Trapnell on 8/1/10.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <stdlib.h>\n#include <getopt.h>\n#include <string>\n#include <algorithm>\n\n#include <boost/version.hpp>\n#include <boost/graph/adjacency_list.hpp>\n#include <boost/graph/depth_first_search.hpp>\n#include <boost/graph/visitors.hpp>\n#include <boost/graph/graph_traits.hpp>\n#include <boost/graph/connected_components.hpp>\n\n#include \"common.h\"\n#include \"hits.h\"\n#include \"bundles.h\"\n\n#include \"gtf_tracking.h\"\n#include \"scaffolds.h\"\n#include \"tokenize.h\"\n#include \"genes.h\"\n\nusing namespace boost;\nusing namespace std;\n\n#if ENABLE_THREADS\nconst char *short_options = \"r:F\";\n#else\nconst char *short_options = \"r:F\";\n#endif\n\nbool raw_fpkm = false;\nbool proj_union = false;\nbool proj_intersection = false;\n\nstatic struct option long_options[] = {\n{\"reference-seq\",\t\trequired_argument,\t\t 0,\t\t\t 'r'},\n{\"raw-fpkm\",            no_argument,             0,\t\t\t 'F'},\n{\"union\",               no_argument,             0,\t\t\t 'U'},\n{\"intersection\",        no_argument,             0,\t\t\t 'I'},\n\n\n{0, 0, 0, 0} // terminator\n};\n\nvoid print_usage()\n{\n\t//NOTE: SPACES ONLY, bozo\n\tfprintf(stderr, \"compress_gtf v%s\\n\", PACKAGE_VERSION);\n\tfprintf(stderr, \"linked against Boost version %d\\n\", BOOST_VERSION);\n\tfprintf(stderr, \"-----------------------------\\n\"); \n\tfprintf(stderr, \"Usage:   compress_gtf [options] <reference.gtf> <compressed_reference.gtf>\\n\");\n\tfprintf(stderr, \"Options:\\n\\n\");\n\tfprintf(stderr, \"-r/--reference-seq\t\t\t  reference fasta file                     [ default:   NULL ]\\n\");\n    fprintf(stderr, \"-F/--raw-fpkm\t\t\t      use FPKM instead of isoform fraction                        \\n\");\n    fprintf(stderr, \"-U/--union                   report projective union                  [ default:   OFF  ]\\n\");\n    fprintf(stderr, \"-I/--intersection            report projective intersection           [ default:   ON   ]\\n\");\n}\n\nint parse_options(int argc, char** argv)\n{\n    int option_index = 0;\n    int next_option;\n    do {\n        next_option = getopt_long(argc, argv, short_options, long_options, &option_index);\n        switch (next_option) {\n\t\t\tcase -1:     /* Done with options. */\n\t\t\t\tbreak;\n            case 'r':\n\t\t\t{\n\t\t\t\tfasta_dir = optarg;\n\t\t\t\tbreak;\n            }    \n            case 'F':\n\t\t\t{\n\t\t\t\traw_fpkm = true;\n\t\t\t\tbreak;\n            }   \n            case 'U':\n\t\t\t{\n\t\t\t\tproj_union = true;\n\t\t\t\tbreak;\n            } \n            case 'I':\n\t\t\t{\n\t\t\t\tproj_intersection = true;\n\t\t\t\tbreak;\n            }  \n\t\t\tdefault:\n\t\t\t\tprint_usage();\n\t\t\t\treturn 1;\n        }\n    } while(next_option != -1);\n\n    if (proj_union && proj_intersection)\n    {\n        fprintf (stderr, \"Error: please specify only one of --union and --intersection\");\n        exit(1);\n    }\n    \n//    if (!proj_union && !proj_intersection)\n//        proj_intersection =  true;\n\treturn 0;\n}\n\nvoid compress_genes(FILE* ftranscripts,\n                    RefSequenceTable& rt,\n                    vector<boost::shared_ptr<Scaffold> >& ref_mRNAs)\n{\n    adjacency_list <vecS, vecS, undirectedS> G;\n    \n\tfor (size_t i = 0; i < ref_mRNAs.size(); ++i)\n\t{\n\t\tadd_vertex(G);\n\t}\n\t\n    for (size_t i = 0; i < ref_mRNAs.size(); ++i)\n\t{\n        boost::shared_ptr<Scaffold> scaff_i = ref_mRNAs[i];\n        for (size_t j = 0; j < ref_mRNAs.size(); ++j)\n        {\n            boost::shared_ptr<Scaffold> scaff_j = ref_mRNAs[j];\n\t\t\tif (scaff_i->annotated_gene_id() == scaff_j->annotated_gene_id())\n\t\t\t\tadd_edge(i, j, G);\n\t\t}\n\t}\n    \n    std::vector<int> component(num_vertices(G));\n\tconnected_components(G, &component[0]);\n\t\n\tvector<vector<bool> > clusters(ref_mRNAs.size(), \n\t\t\t\t\t\t\t\t   vector<bool>(ref_mRNAs.size(), false));\n\t\n\t//vector<vector<size_t> > cluster_indices(three_prime_ends.size());\n    \n    vector<vector<boost::shared_ptr<Scaffold> > > grouped_scaffolds(ref_mRNAs.size());\n\tfor (size_t i = 0; i < ref_mRNAs.size(); ++i)\n\t{\n\t\tclusters[component[i]][i] = true;\n\t\tgrouped_scaffolds[component[i]].push_back(ref_mRNAs[i]);\n\t}\n    \n    for (size_t i = 0; i < grouped_scaffolds.size(); ++i)\n    {\n        vector<boost::shared_ptr<Scaffold> >& gene = grouped_scaffolds[i];\n        vector<Scaffold> gene_scaffs;\n        string gene_id;\n        BOOST_FOREACH (boost::shared_ptr<Scaffold> s, gene)\n        {\n            if (gene_id == \"\")\n                gene_id = s->annotated_gene_id();\n            \n            gene_scaffs.push_back(*s);\n        }\n        \n        if (gene_scaffs.empty())\n            continue;\n        \n        next_gene_id++;\n        \n        Scaffold smashed_gene;\n        if (!proj_intersection && !proj_union)\n        {\n            BOOST_FOREACH (boost::shared_ptr<Scaffold> s, gene)\n            {\n                /*\n                 *transfrag,\n                 gene_id,\n                 (int)isoforms.size() + 1,\n                 FPKM,\n                 iso_ab->effective_length(),\n                 iso_ab->gamma(),\n                 iso_ab->FPKM_conf(),\n                 density_per_bp, \n                 estimated_count,\n                 density_score,\n                 iso_ab->status(),\n                 ref_gene_id)*/\n                \n                Isoform iso(*s,\n                            -1,\n                            1,\n                            0.0,\n                            s->length(),\n                            0.0,\n                            ConfidenceInterval(0.0,0.0),\n                            0,\n                            0,\n                            0,\n                            NUMERIC_OK,\n                            gene_id);\n                vector<string> isoform_exon_recs;\n                \n                iso.get_gtf(isoform_exon_recs, rt);\n                \n                for (size_t g = 0; g < isoform_exon_recs.size(); ++g)\n                {\n                    fprintf(ftranscripts, \"%s\", isoform_exon_recs[g].c_str());\n                }\n            }\n        }\n        else\n        {\n            if (proj_union)\n                Scaffold::merge(gene_scaffs, smashed_gene, false);\n            else if (proj_intersection)\n            {\n                vector<AugmentedCuffOp> iso_ops;\n                \n                int gmax = -1;\n                int gmin = numeric_limits<int>::max();\n                \n                BOOST_FOREACH (boost::shared_ptr<Scaffold> s, gene)\n                {\n                    //iso_ops.push_back(s->augmented_ops());\n                    //sort (iso_ops.back().begin(), iso_ops.back().end());\n                    if (s->left() < gmin)\n                        gmin = s->left();\n                    if (s->right() > gmax)\n                        gmax = s->right();\n                }\n                \n                BOOST_FOREACH (boost::shared_ptr<Scaffold> s, gene)\n                {\n                    if (s->left() > gmin)\n                    {\n                        iso_ops.push_back(AugmentedCuffOp(CUFF_INTRON, gmin, s->left() - gmin)); \n                    }\n                    if (s->right() < gmax)\n                    {\n                        iso_ops.push_back(AugmentedCuffOp(CUFF_INTRON, s->right(), gmax - s->right())); \n                    }\n                    iso_ops.insert(iso_ops.end(), s->augmented_ops().begin(), s->augmented_ops().end());\n                }\n//                vector<AugmentedCuffOp> intersect = iso_ops.front();\n//                for (size_t j = 1; j < iso_ops.size(); ++j)\n//                {\n//                    vector<AugmentedCuffOp> tmp;\n//                    const vector<AugmentedCuffOp>& iso_ops_j = iso_ops[j];\n//                    //set_intersection(intersect.begin(), intersect.end(), iso_ops_j.begin(), iso_ops_j.end(), back_inserter(tmp));\n//                    intersect.insert(intersect.end(), iso_ops_j.begin(), iso_ops_j.end());\n//                    \n//                    intersect.push_back(\n//                    assert (tmp.size() <= intersect.size());\n//                    //intersect = tmp;\n//                    //sort(intersect.begin(), intersect.end());\n//                }\n//                \n                sort(iso_ops.begin(), iso_ops.end(), AugmentedCuffOp::g_left_lt);\n//                \n//                while (!intersect.empty() && intersect.front().opcode != CUFF_MATCH)\n//                {\n//                    intersect.erase(intersect.begin());\n//                }\n//                \n//                while (!intersect.empty() && intersect.back().opcode != CUFF_MATCH)\n//                {\n//                    intersect.pop_back();\n//                }\n//                \n//                if (intersect.empty())\n//                    continue;\n                \n                vector<AugmentedCuffOp> merged_ops;\n                AugmentedCuffOp::merge_ops(iso_ops, merged_ops, true, true);\n                vector<AugmentedCuffOp>::iterator first_match = merged_ops.begin();\n                vector<AugmentedCuffOp>::iterator last_match = merged_ops.end();\n                last_match--;\n                while(first_match < merged_ops.end())\n                {\n                    if (first_match->opcode == CUFF_MATCH)\n                        break;\n                    first_match++;\n                }\n                while(last_match >= merged_ops.begin() && last_match< merged_ops.end())\n                {\n                    if (last_match->opcode == CUFF_MATCH)\n                        break;\n                    last_match--;\n                }\n                \n                vector<AugmentedCuffOp> internal_matches;\n                if (last_match >= first_match && last_match < merged_ops.end())\n                {\n                    last_match++;\n                    \n                    internal_matches.insert(internal_matches.end(), first_match, last_match);\n                    smashed_gene = Scaffold(gene.front()->ref_id(), gene.front()->strand(), internal_matches);\n                }\n                else\n                {\n                    \n                    fprintf(stderr, \"Could not find consitutive region for %s\\n\", gene_id.c_str());\n                    continue;\n                }\n                \n            }\n            else\n                assert(false);\n            assert (smashed_gene.ref_id());\n            \n            Isoform iso(smashed_gene,\n                        -1,\n                        1,\n                        0.0,\n                        smashed_gene.length(),\n                        0.0,\n                        ConfidenceInterval(0.0,0.0),\n                        0, \n                        0,\n                        0,\n                        NUMERIC_OK,\n                        gene_id);\n            vector<string> isoform_exon_recs;\n            \n            iso.get_gtf(isoform_exon_recs, rt);\n            \n            for (size_t g = 0; g < isoform_exon_recs.size(); ++g)\n            {\n                fprintf(ftranscripts, \"%s\", isoform_exon_recs[g].c_str());\n            }\n        }\n        \n        fflush(ftranscripts);\n    }\n}\n\nvoid driver(vector<FILE*> ref_gtf_files, FILE* gtf_out)\n{\n\tReadTable it;\n\tRefSequenceTable rt(true, false);\n\t\n\tvector<vector<boost::shared_ptr<Scaffold> > > ref_mRNA_table;\n\tvector<pair<string, vector<double> > > sample_count_table;\n    \n    BOOST_FOREACH (FILE* ref_gtf, ref_gtf_files)\n    {\n        vector<boost::shared_ptr<Scaffold> > ref_mRNAs;\n        boost::crc_32_type gtf_crc_result;\n        ::load_ref_rnas(ref_gtf, rt, ref_mRNAs, gtf_crc_result, false, true);\n        ref_mRNA_table.push_back(ref_mRNAs);\n    }\n    \n    for (size_t j = 0; j < ref_mRNA_table.size(); ++j)\n    {\n        vector<boost::shared_ptr<Scaffold> > ref_mRNAs = ref_mRNA_table[j];\n        \n        if (!raw_fpkm)\n            compress_genes(gtf_out, rt, ref_mRNAs);\n    }\n}\n\nint main(int argc, char** argv)\n{\n    init_library_table();\n    \n\tint parse_ret = parse_options(argc,argv);\n    if (parse_ret)\n        return parse_ret;\n\t\n    \n    if(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n\t\n    string ref_gtf_in_filenames = argv[optind++];\n    \n    if(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n\t\n    string gtf_out_filename = argv[optind++];\n    \n    vector<string> ref_gtf_filenames;\n    tokenize(ref_gtf_in_filenames, \",\", ref_gtf_filenames);\n    \n    vector<FILE*> ref_gtf_files;\n    \n    BOOST_FOREACH (const string& ref_gtf_in_filename, ref_gtf_filenames)\n    {\n        FILE* ref_gtf = NULL;\n        if (ref_gtf_in_filename != \"\")\n        {\n            ref_gtf = fopen(ref_gtf_in_filename.c_str(), \"r\");\n            if (!ref_gtf)\n            {\n                fprintf(stderr, \"Error: cannot open GTF file %s for reading\\n\",\n                        ref_gtf_in_filename.c_str());\n                exit(1);\n            }\n            ref_gtf_files.push_back(ref_gtf);\n        }\n    }\n    \n    FILE* gtf_out = NULL;\n\tif (gtf_out_filename != \"\")\n\t{\n\t\tgtf_out = fopen(gtf_out_filename.c_str(), \"w\");\n\t\tif (!gtf_out)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open GTF file %s for writing\\n\",\n\t\t\t\t\tgtf_out_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n    \n    driver(ref_gtf_files, gtf_out);\n\t\n\treturn 0;\n}\n"
  },
  {
    "path": "src/cuffcluster.cpp",
    "content": "/*\n *  sorting_hat.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 8/30/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <stdlib.h>\n#include <getopt.h>\n#include <string>\n\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/matrix_proxy.hpp>\n#include <boost/numeric/ublas/vector.hpp>\n#include <boost/numeric/ublas/vector_proxy.hpp>\n#include <boost/numeric/ublas/io.hpp>\n#include <boost/random/linear_congruential.hpp>\n#include <boost/random/uniform_real.hpp>\n#include <boost/random/variate_generator.hpp>\n\n\n#include \"common.h\"\n#include \"tokenize.h\"\n\n#include \"differential.h\"\n\nusing namespace std;\nusing namespace boost;\n\nbool compute_row_matrix = false;\nbool log_transform_fpkm = false;\nbool output_row_density = false;\n\nint k_clusters = 0;\nint max_iterations = 1000;\n\nstring row_matrix_out_filename = \"\";\nstring row_density_out_filename = \"\";\n\n#if ENABLE_THREADS\nconst char *short_options = \"o:p:d:P:k:I:l\";\n#else\nconst char *short_options = \"o:d:P:k:I:l\";\n#endif\n\nstatic struct option long_options[] = {\n    {\"output-dir\",\t\t\t    required_argument,\t\t 0,\t\t\t 'o'},\n    {\"row-matrix\",\t\t\t    required_argument,       0,\t\t\t 'd'},\n    {\"row-densities\",\t\t\trequired_argument,       0,\t\t\t 'P'},\n    {\"log-fpkm\",\t\t\t    no_argument,             0,\t\t\t 'l'},\n    {\"k-means\",                 required_argument,       0,\t\t\t 'k'},\n    {\"max-iterations\",          required_argument,       0,\t\t\t 'I'},\n#if ENABLE_THREADS\n    {\"num-threads\",\t\t\t\trequired_argument,       0,          'p'},\n#endif\n    {0, 0, 0, 0} // terminator\n};\n\nvoid print_usage()\n{\n\tfprintf(stderr, \"sorting_hat v%s (%s)\\n\", PACKAGE_VERSION, SVN_REVISION); \n\tfprintf(stderr, \"-----------------------------\\n\"); \n\t\n\t//NOTE: SPACES ONLY, bozo\n    fprintf(stderr, \"Usage:   cuffdiff [options] <input.fpkm_tracking> <output.shout>\\n\");\n\tfprintf(stderr, \"Options:\\n\\n\");\n\tfprintf(stderr, \"-o/--output-dir              write all output files to this directory              [ default:     ./ ]\\n\");  \n    fprintf(stderr, \"-d/--row-matrix              compute row distance matrix                           [ default:     off ]\\n\");\n    fprintf(stderr, \"-l/--log-fpkm                JS on log(fpkm+1) instead of                          [ default:     off ]\\n\");\n#if ENABLE_THREADS\n\tfprintf(stderr, \"-p/--num-threads             number of threads used during assembly                [ default:      1 ]\\n\");\n#endif\n}\n\nint parse_options(int argc, char** argv)\n{\n    int option_index = 0;\n    int next_option;\n    do {\n        next_option = getopt_long(argc, argv, short_options, long_options, &option_index);\n        switch (next_option) {\n\t\t\tcase -1:     /* Done with options. */\n\t\t\t\tbreak;\n\n            case 'd':\n\t\t\t{\n\t\t\t\tcompute_row_matrix = true;\n                row_matrix_out_filename = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n                \n            case 'P':\n\t\t\t{\n\t\t\t\toutput_row_density = true;\n                row_density_out_filename = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n                \n            case 'l':\n\t\t\t{\n\t\t\t\tlog_transform_fpkm = true;\n\t\t\t\tbreak;\n\t\t\t}\n                \n            case 'k':\n\t\t\t{\n\t\t\t\tk_clusters = (int)parseInt(1, \"-k/--k-means arg must be at least 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\t}\n                \n            case 'I':\n\t\t\t{\n\t\t\t\tmax_iterations = (int)parseInt(1, \"-I/--max-iterations arg must be at least 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\t}\n                \n            case 'o':\n\t\t\t{\n\t\t\t\toutput_dir = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n  \n\t\t\tdefault:\n\t\t\t\tprint_usage();\n\t\t\t\treturn 1;\n        }\n    } while(next_option != -1);\n\t\n\tallow_junk_filtering = false;\n\t\n\treturn 0;\n}\n\n\nstruct ExprRecord\n{\n    ExprRecord() : \n        total_FPKM(0.0),\n        total_FPKM_conf_hi(0.0),\n        total_FPKM_conf_lo(0.0),\n        max_FPKM(0.0),\n        total_log_FPKM(std::numeric_limits<double>::infinity()),\n        total_log_FPKM_conf_hi(std::numeric_limits<double>::infinity()),\n        total_log_FPKM_conf_lo(std::numeric_limits<double>::infinity()),\n        max_log_FPKM(std::numeric_limits<double>::infinity()),\n        cluster_id(-1) {} \n    \n    string tracking_id;\n    string class_code;\n    string nearest_ref_id;\n    string gene_id;\n    string gene_short_name;\n    string tss_id;\n    string locus; \n    \n    string length;\n    string coverage;\n    string status;\n    \n    vector<double> FPKMs;\n    vector<double> FPKM_conf_los;\n    vector<double> FPKM_conf_his;\n    \n    vector<double> log_FPKMs;\n    vector<double> log_FPKM_conf_los;\n    vector<double> log_FPKM_conf_his;\n    \n    double total_FPKM;\n    double total_FPKM_conf_hi;\n    double total_FPKM_conf_lo;\n    double max_FPKM;\n    \n    double total_log_FPKM;\n    double total_log_FPKM_conf_hi;\n    double total_log_FPKM_conf_lo;\n    double max_log_FPKM;\n    \n    ublas::vector<double> cond_density;\n    vector<double> cond_specificities;\n    \n    int cluster_id;\n};\n\nstruct ClusterStats\n{\n    ClusterStats(int dim) \n    {\n        mean = ublas::zero_vector<double>(dim);\n        variance = 0.0;\n    }\n    \n    ublas::vector<double> mean;\n    double variance;\n    vector<size_t> members;\n};\n\nstruct SortByVariance\n{\n    bool operator()(const ClusterStats& lhs, const ClusterStats& rhs)\n    {\n        if (lhs.variance != rhs.variance)\n            return lhs.variance < rhs.variance;\n        else if (lhs.members.size() != rhs.members.size())\n            return lhs.members.size() < rhs.members.size();\n        return false;\n    }\n};\n\n\nvoid assign_to_nearest_cluster(vector<ExprRecord>& expr_records, vector<ClusterStats>& clusters)\n{\n    \n    int num_clusters = clusters.size();\n    int num_conditions = expr_records.front().cond_density.size();\n    \n    BOOST_FOREACH(ClusterStats& c, clusters)\n    {\n        c.members.clear();\n    }\n    \n    // E step - assign each record to nearest cluster\n    for (size_t r = 0; r < expr_records.size(); ++r)\n    {\n        ExprRecord& rec = expr_records[r];\n        \n        // Skip unexpressed records;\n        if (log_transform_fpkm)\n        {\n            if (rec.total_log_FPKM == 0 ||\n                rec.total_log_FPKM == std::numeric_limits<double>::infinity())\n            {\n                continue;\n            }\n        }\n        else\n        {\n            if (rec.total_FPKM == 0)\n            {\n                continue;\n            }\n        }    \n\n        double min_dist = std::numeric_limits<double>::max();\n        size_t closest_mean = 0;\n        vector<ublas::vector<double> >  kappas;\n        \n        kappas.push_back(rec.cond_density);\n        //cerr << rec.cond_density << endl;\n        kappas.push_back(ublas::zero_vector<double>());\n        \n        for (size_t m = 0; m < clusters.size(); ++m)\n        {\n            kappas[1] = clusters[m].mean;\n            double js = jensen_shannon_distance(kappas);\n            if (js < min_dist)\n            {\n                closest_mean = m;\n                min_dist = js;\n            }\n        }\n        \n        clusters[closest_mean].members.push_back(r);\n    }\n    \n    // M step - calculate new means\n    \n    vector<ublas::vector<double> > tmp_means(num_clusters, \n                                             ublas::zero_vector<double>(num_conditions));\n    // Calculate mean\n    \n    for (size_t c = 0; c < clusters.size(); ++c)\n    {\n        ClusterStats& cluster = clusters[c];\n        BOOST_FOREACH(int m, cluster.members)\n        {\n            tmp_means[c] += expr_records[m].cond_density;\n        }\n    }\n    \n    for (size_t c = 0; c < clusters.size(); ++c)\n    {\n        if (clusters[c].members.size() > 0)\n        {\n            clusters[c].mean = tmp_means[c] / clusters[c].members.size();\n        }\n    }\n    \n    // And now the variance\n    for (size_t c = 0; c < clusters.size(); ++c)\n    {\n        ClusterStats& cluster = clusters[c];\n        if (cluster.members.empty())\n            continue;\n        \n        vector<ublas::vector<double> >  kappas;\n        kappas.push_back(cluster.mean);\n        kappas.push_back(ublas::zero_vector<double>());\n        BOOST_FOREACH (int m, cluster.members)\n        {\n            kappas[1] = expr_records[m].cond_density;\n            double js = jensen_shannon_distance(kappas);\n            cluster.variance += (js * js);\n        }\n        \n        cluster.variance /= cluster.members.size();\n    }\n}\n\nvoid get_assignments(const vector<ClusterStats>& clusters, \n                     vector<int>& assignments)\n{\n    BOOST_FOREACH (int& i, assignments)\n    {\n        i = -1;\n    }\n    \n    for (size_t c = 0; c < clusters.size(); ++c)\n    {\n        for (size_t r = 0; r < clusters[c].members.size(); ++r)\n        {\n            assignments[clusters[c].members[r]] = c;\n        }\n    }\n}\n\n\nvoid split_cluster(const vector<ExprRecord>& expr_records, \n                   ClusterStats& to_split, \n                   vector<ClusterStats>& new_clusters)\n{\n    \n    fprintf (stderr, \"Splitting cluster...\\n\");\n    \n    int num_conditions = expr_records.front().cond_density.size();\n    \n    vector<ublas::vector<double> >  kappas;\n    kappas.push_back(to_split.mean);\n    \n    vector<double> dist_from_mean;\n    \n    for (size_t m = 0; m < to_split.members.size(); ++m)\n    {\n        kappas.push_back(expr_records[to_split.members[m]].cond_density);\n        double js = jensen_shannon_distance(kappas);\n        dist_from_mean.push_back(js);\n    }\n    \n    // pick the point farthest from the mean and the point closest.\n    \n    double largest_dist = -1.0;\n    size_t farthest_point = 0;\n    \n    double smallest_dist = std::numeric_limits<double>::max();\n    size_t closest_point = 0;\n    \n    for (size_t i = 0; i < dist_from_mean.size(); ++i)\n    {\n        if (largest_dist > dist_from_mean[i])\n        {\n            largest_dist = dist_from_mean[i];\n            farthest_point = i;\n        }\n        \n        if (smallest_dist < dist_from_mean[i])\n        {\n            smallest_dist = dist_from_mean[i];\n            closest_point = i;\n        }\n    }\n    \n    vector<ublas::vector<double> > a_kappas;\n    a_kappas.push_back(expr_records[to_split.members[closest_point]].cond_density);\n    a_kappas.push_back(ublas::zero_vector<double>());\n    \n    vector<ublas::vector<double> > b_kappas;\n    b_kappas.push_back(expr_records[to_split.members[farthest_point]].cond_density);\n    b_kappas.push_back(ublas::zero_vector<double>());\n    \n    ClusterStats a_cluster(num_conditions);\n    ClusterStats b_cluster(num_conditions);\n    \n    a_cluster.mean = ublas::zero_vector<double>(num_conditions);\n    b_cluster.mean = ublas::zero_vector<double>(num_conditions);\n    \n    for (size_t m = 0; m < to_split.members.size(); ++m)\n    {\n        a_kappas[1] = expr_records[to_split.members[m]].cond_density;\n        double a_js = jensen_shannon_distance(a_kappas);\n        \n        b_kappas[1] = expr_records[to_split.members[m]].cond_density;\n        double b_js = jensen_shannon_distance(b_kappas);\n        \n        if (a_js < b_js)\n        {\n            a_cluster.members.push_back(to_split.members[m]);\n            a_cluster.mean += expr_records[to_split.members[m]].cond_density;\n        }\n        else \n        {\n            b_cluster.members.push_back(to_split.members[m]);    \n            b_cluster.mean += expr_records[to_split.members[m]].cond_density;\n        }\n    }  \n    \n    a_cluster.mean /= a_cluster.members.size();\n    b_cluster.mean /= b_cluster.members.size();\n    \n    // Calculate the variances of the split clusters.\n    a_kappas[0] = a_cluster.mean;\n    b_kappas[0] = b_cluster.mean;\n    \n    for (size_t m = 0; m < a_cluster.members.size(); ++m)\n    {\n        a_kappas[1] = expr_records[a_cluster.members[m]].cond_density;\n        double js = jensen_shannon_distance(a_kappas);\n        a_cluster.variance += (js * js);\n    }\n    \n    a_cluster.variance /= a_cluster.members.size();\n    \n    for (size_t m = 0; m < b_cluster.members.size(); ++m)\n    {\n        b_kappas[1] = expr_records[b_cluster.members[m]].cond_density;\n        double js = jensen_shannon_distance(b_kappas);\n        b_cluster.variance += (js * js);\n    }\n    \n    b_cluster.variance /= b_cluster.members.size();\n    \n    new_clusters.push_back(a_cluster);\n    new_clusters.push_back(b_cluster);\n}\n\nvoid kmeans(vector<ExprRecord>& expr_records, int num_clusters, int num_iterations)\n{\n    // generate k random means\n    size_t num_conditions = 0;\n    for (size_t i = 1; i < expr_records.size(); ++i)\n    {\n        if (expr_records[i - 1].FPKMs.size() != expr_records[i].FPKMs.size())\n        {\n            fprintf(stderr, \"Error: not all records have the same number of conditions!\\n\");\n            exit(1);\n        }\n        num_conditions = expr_records[i].FPKMs.size();\n    }\n    \n    // This is a typedef for a random number generator.\n    typedef boost::minstd_rand base_generator_type;\n    base_generator_type generator(time(NULL));\n\n    boost::uniform_real<> uni_dist(0,1);\n    boost::variate_generator<base_generator_type&, boost::uniform_real<> > uni(generator, uni_dist);\n    \n    // each mean gets an accumulation vector and a counter.  For now,\n    // let's just keep ClusterStats thin and do all this outside the class. \n    vector<ClusterStats> clusters(num_clusters, ClusterStats(num_conditions));\n    \n    for (size_t i = 0; i < clusters.size(); ++i)\n    {\n        ClusterStats& c = clusters[i];\n        ublas::vector<double>& mean_i = c.mean;\n        \n        for (size_t j = 0; j < mean_i.size(); ++j)\n        {\n            mean_i(j) = uni();\n        }\n        double total = accumulate(mean_i.begin(), mean_i.end(), 0.0);\n        mean_i /= total;\n        //cerr << mean_i << endl;\n    }\n    \n    vector<int> assignments(expr_records.size());\n    vector<int> prev_assignments;\n    \n    size_t iter = 0;\n    for (;iter < num_iterations; ++iter)\n    {        \n        if (iter % 5 == 0)\n        {\n            fprintf(stderr, \"Iteration # %d\\n\", iter);\n        }\n        \n        assign_to_nearest_cluster(expr_records, clusters);\n        get_assignments(clusters, assignments);\n        \n        sort(clusters.begin(), clusters.end(), SortByVariance());\n        \n        vector<ClusterStats> empty_clusters;\n        vector<ClusterStats> full_clusters;\n        \n        // Look for empty clusters, and if found split others (in order of \n        // largest variance)\n        for(size_t p = 0; p < clusters.size(); ++p)\n        {\n            const ClusterStats& P = clusters[p];\n            if (P.members.size() == 0) // found empty cluster\n            {\n                empty_clusters.push_back(P);\n            }\n            else\n            {\n                full_clusters.push_back(P);   \n            }\n        }\n        \n        if (!empty_clusters.empty())\n        {\n            vector<ClusterStats> new_clusters;\n            for (size_t c = 0; c < empty_clusters.size(); ++c)\n            {\n                //size_t full = 0;\n                // split this cluster.\n                ClusterStats to_split = full_clusters.back();\n                full_clusters.pop_back();\n                split_cluster(expr_records, to_split, new_clusters);\n                //get_assignments(clusters, assignments);\n                //prev_assignments = assignments;\n            }\n            \n            full_clusters.insert(full_clusters.end(), new_clusters.begin(), new_clusters.end());\n            clusters = full_clusters;\n            get_assignments(clusters, assignments);\n            prev_assignments = assignments;\n        }\n        \n        else \n        {\n            if (assignments == prev_assignments)\n            {\n                break;\n            }\n            else \n            {\n                prev_assignments = assignments;\n            }\n            \n        }\n    }\n    \n    for (size_t a = 0; a < assignments.size(); ++a)\n    {\n        expr_records[a].cluster_id = assignments[a];\n    }\n    \n    if (iter == num_iterations)\n    {\n        fprintf(stderr, \"Warning: clustering did not converge after %d iterations\\n\", iter);\n    }\n}\n\nvoid driver(FILE* fpkm_file, FILE* spec_out, FILE* row_matrix_out, FILE* row_density_out)\n{\n    char buf[10 * 1024];\n    \n    vector<string> sample_names;\n    \n    int line_num = 1;\n    \n    while(fgets(buf, sizeof(buf), fpkm_file))\n    {\n        if (buf[0])\n        {\n            // Chomp the newline\n            char* nl = strrchr(buf, '\\n');\n            if (nl) *nl = 0;\n            \n            vector<string> tokens;\n            tokenize(buf, \"\\t\", tokens);\n            \n            if (tokens.size() < 16)\n            {\n                fprintf(stderr, \"Error:  FPKM tracking files must have at least 12 columns\\n\");\n                exit(1);\n            }\n            \n            if ((tokens.size() - 10) % 3 != 0)\n            {\n                fprintf(stderr, \"Error:  FPKM tracking files must have FPKM, FPKM_lo, and FPKM_hi columns for each sample\\n\");\n                exit(1);\n            }\n            \n            static const size_t first_sample_idx = 10;\n            \n            for (size_t i = first_sample_idx; i < tokens.size(); i += 3)\n            {\n                string FPKM_label = tokens[i];\n                string::size_type name_end = FPKM_label.rfind(\"_FPKM\");\n                if (name_end == string::npos)\n                {\n                    fprintf(stderr, \"Error:  Malformed FPKM column header %s.  Should end in \\\"_FPKM\\\".\\n\", FPKM_label.c_str());\n                    exit(1);\n                }\n                string name = FPKM_label.substr(0, name_end);\n                sample_names.push_back(name);\n            }\n            \n            break;\n        }\n        \n        line_num++;\n    }\n    \n    fprintf(spec_out, \"tracking_id\\tclass_code\\tnearest_ref\\tgene_id\\tgene_short_name\\ttss_id\\tlocus\\tlength\\tcoverage\\tstatus\\ttotal_FPKM\\ttotal_FPKM_lo\\ttotal_FPKM_hi\\tmax_FPKM\\tcluster_id\");\n\n    for (size_t i = 0; i < sample_names.size(); ++i)\n    {\n        fprintf(spec_out, \"\\t%s\", sample_names[i].c_str());\n    }\n    fprintf(spec_out, \"\\n\");\n    \n    vector<ExprRecord> expr_records;\n    \n    while(fgets(buf, sizeof(buf), fpkm_file))\n    {\n        // Chomp the newline\n\t\tchar* nl = strrchr(buf, '\\n');\n\t\tif (nl) *nl = 0;\n        \n        vector<string> tokens;\n        tokenize(buf, \"\\t\", tokens);\n        \n        if (((tokens.size() - 10) / 3) != sample_names.size())\n        {\n            fprintf(stderr, \"Error:  Line %d has %lu columns, should have %lu\\n\", line_num, tokens.size(), (sample_names.size() * 3) + 6);\n            exit(1);\n        }\n        \n        ExprRecord rec;\n        \n        rec.tracking_id = tokens[0];\n        rec.class_code = tokens[1];\n        rec.nearest_ref_id = tokens[2];\n        rec.gene_id = tokens[3];\n        rec.gene_short_name = tokens[4];\n        rec.tss_id = tokens[5];\n        rec.locus = tokens[6];\n        \n        rec.length = tokens[7];\n        rec.coverage = tokens[8];\n        rec.status = tokens[9];\n        \n        static const size_t first_sample_idx = 10;\n        \n        size_t num_samples = sample_names.size();\n        ublas::vector<double> u1 = ublas::unit_vector<double>(sample_names.size(), 0);\n        ublas::vector<double> u2 = ublas::unit_vector<double>(sample_names.size(), 1);\n        \n        vector<ublas::vector<double> > norm_kappas;\n        norm_kappas.push_back(u1);\n        norm_kappas.push_back(u2);\n        \n        double norm_js = jensen_shannon_distance(norm_kappas);\n        double max_FPKM = -1;\n        double max_log_FPKM = -1;\n        \n        for (size_t i = first_sample_idx; i < tokens.size() - 2; i += 3)\n        {\n            string FPKM_string = tokens[i];\n            double fpkm = atof(FPKM_string.c_str());\n            \n            string FPKM_conf_lo_string = tokens[i+1];\n            double fpkm_conf_lo = atof(FPKM_conf_lo_string.c_str());\n            \n            string FPKM_conf_hi_string = tokens[i+2];\n            double fpkm_conf_hi = atof(FPKM_conf_hi_string.c_str());\n            \n            double log_fpkm = log10(fpkm + 1.0);\n            double log_fpkm_conf_lo = log10(fpkm_conf_lo + 1.0);\n            double log_fpkm_conf_hi = log10(fpkm_conf_hi + 1.0);\n            \n            if (isnan(fpkm) || isnan(fpkm_conf_lo) || isnan(fpkm_conf_hi))\n            {\n                fprintf (stderr, \"Warning: gene %s (%s) on line %d has FPKM = NaN\\n\", \n                         rec.tracking_id.c_str(), rec.gene_short_name.c_str(), line_num); \n                fpkm = 0.0;\n                fpkm_conf_lo = 0;\n                fpkm_conf_hi = 0;\n                \n                log_fpkm = std::numeric_limits<double>::infinity();\n                log_fpkm_conf_lo = std::numeric_limits<double>::infinity();\n                log_fpkm_conf_hi = std::numeric_limits<double>::infinity();\n            }\n            else\n            {\n                if (log_fpkm > max_log_FPKM)\n                {\n                    max_log_FPKM = log_fpkm;\n                }\n                \n                if (fpkm > max_FPKM)\n                {\n                    max_FPKM = fpkm;\n                }\n            }\n            \n            rec.FPKMs.push_back(fpkm);\n            rec.FPKM_conf_los.push_back(fpkm_conf_lo);\n            rec.FPKM_conf_his.push_back(fpkm_conf_hi);\n\n            rec.log_FPKMs.push_back(log_fpkm);\n            rec.log_FPKM_conf_los.push_back(log_fpkm_conf_lo);\n            rec.log_FPKM_conf_his.push_back(log_fpkm_conf_hi);\n        }\n        \n        rec.total_FPKM = accumulate(rec.FPKMs.begin(), rec.FPKMs.end(), 0.0);\n        rec.total_FPKM_conf_lo = accumulate(rec.FPKM_conf_los.begin(), rec.FPKM_conf_los.end(), 0.0);\n        rec.total_FPKM_conf_hi = accumulate(rec.FPKM_conf_his.begin(), rec.FPKM_conf_his.end(), 0.0);\n        rec.max_FPKM = max_FPKM;\n        \n        rec.total_log_FPKM = accumulate(rec.log_FPKMs.begin(), rec.log_FPKMs.end(), 0.0);\n        rec.total_log_FPKM_conf_lo = accumulate(rec.log_FPKM_conf_los.begin(), rec.log_FPKM_conf_los.end(), 0.0);\n        rec.total_log_FPKM_conf_hi = accumulate(rec.log_FPKM_conf_his.begin(), rec.log_FPKM_conf_his.end(), 0.0);\n        rec.max_log_FPKM = max_log_FPKM;\n        \n        assert (!isnan(rec.total_FPKM) && !isinf(rec.total_FPKM));\n        \n        rec.cond_density = ublas::vector<double>(sample_names.size());\n        rec.cond_specificities = vector<double>(sample_names.size(), std::numeric_limits<double>::max());\n        \n                \n        if (rec.total_FPKM == 0.0 || (log_transform_fpkm && (rec.total_log_FPKM == 0.0 || rec.total_log_FPKM == std::numeric_limits<double>::infinity())))\n        {\n             rec.cond_density = ublas::zero_vector<double>(sample_names.size());\n        }\n        else \n        {\n            for (size_t i = 0; i < rec.cond_density.size(); ++i)\n            {\n                if (log_transform_fpkm)\n                {\n\n                    rec.cond_density(i) = rec.log_FPKMs[i] / rec.total_log_FPKM;\n                }\n                else \n                {\n                    rec.cond_density(i) = rec.FPKMs[i] / rec.total_FPKM;\n                }\n\n                \n            }\n        \n            //fpkm_dists.push_back(FPKM_dist);\n            \n            //cerr << tracking_id << FPKM_dist<< endl;\n            \n            const size_t N = sample_names.size();\n            \n            assert (N >= 2);\n            \n            vector<ublas::vector<double> > kappas;\n            kappas.push_back(rec.cond_density);\n            kappas.push_back(ublas::zero_vector<double>(sample_names.size()));\n            \n            for (size_t i = 0; i < sample_names.size(); ++i)\n            {\n                ublas::vector<double> specific_vec = ublas::unit_vector<double>(N, i);\n                kappas[1] = specific_vec;\n                \n                double js = jensen_shannon_distance(kappas);\n                js /= norm_js;\n                \n                rec.cond_specificities[i] = 1.0 - js;\n            }\n        }\n        \n        expr_records.push_back(rec);\n        \n        line_num++;\n    }\n    \n    if (k_clusters > 0)\n    {\n        kmeans(expr_records, k_clusters, max_iterations);\n    }\n    \n    \n    for (size_t i = 0; i < expr_records.size(); ++i)\n    {\n        const ExprRecord& rec = expr_records[i];\n        \n        char cluster_str[256];\n        \n        if (k_clusters == 0)\n        {\n            sprintf(cluster_str, \"-\");\n        }\n        else \n        {\n            sprintf(cluster_str, \"%d\", rec.cluster_id);\n        }\n        \n        fprintf(spec_out, \n                \"%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%g\\t%g\\t%g\\t%lg\\t%s\",\n                rec.tracking_id.c_str(),\n                rec.class_code.c_str(),\n                rec.nearest_ref_id.c_str(),\n                rec.gene_id.c_str(),\n                rec.gene_short_name.c_str(),\n                rec.tss_id.c_str(),\n                rec.locus.c_str(),\n                rec.length.c_str(),\n                rec.coverage.c_str(),\n                rec.status.c_str(),\n                rec.total_FPKM,\n                rec.total_FPKM_conf_lo,\n                rec.total_FPKM_conf_hi,\n                rec.max_FPKM,\n                cluster_str);\n        \n        for (size_t i = 0; i < rec.cond_density.size(); ++i)\n        {\n            fprintf(spec_out, \"\\t%g\", rec.cond_specificities[i]);\n        }\n        \n        fprintf(spec_out, \"\\n\");\n    }\n    \n//    if (row_matrix_out)\n//    {\n//         for (size_t i = 0; i < fpkm_dists.size(); ++i)\n//         {\n//             const ublas::vector<double>& i_vec = fpkm_dists[i];\n//             vector<ublas::vector<double> > kappas;\n//             kappas.push_back(i_vec);\n//             kappas.push_back(ublas::zero_vector<double>(i_vec.size()));\n//             if (i % 100 == 0)\n//             {\n//                 fprintf(stderr, \"%lu of %lu (%g percent)\\n\", i, fpkm_dists.size(), (double)i/(double)fpkm_dists.size()); \n//             }\n//             \n//             for(size_t j = 0; j < fpkm_dists.size(); ++j)\n//             {\n//                 const ublas::vector<double>& j_vec = fpkm_dists[j];\n//                 kappas[1] = j_vec;\n//                 double i_j_js = jensen_shannon_distance(kappas);\n//                 if (j == fpkm_dists.size() - 1)\n//                 {\n//                     fprintf(row_matrix_out, \"%g\\n\", i_j_js);\n//                 }\n//                 else \n//                 {\n//                     fprintf(row_matrix_out, \"%g\\t\", i_j_js);\n//                 }\n//\n//             }\n//         }\n//    }\n//    \n    if (row_density_out)\n    {\n        for (size_t i = 0; i < expr_records.size(); ++i)\n        {\n            const ExprRecord& rec = expr_records[i];\n            const ublas::vector<double>& i_vec = rec.cond_density;\n            fprintf(row_density_out, \"%s\\t\", rec.tracking_id.c_str());                    \n            for (size_t j = 0; j < i_vec.size(); ++j)\n            {\n                if (j == i_vec.size() - 1)\n                {\n                    fprintf(row_density_out, \"%g\\n\", i_vec(j));\n                }\n                else \n                {\n                    fprintf(row_density_out, \"%g\\t\", i_vec(j));\n                }\n            }\n        }\n    }\n}\n\nint main(int argc, char** argv)\n{\n\tint parse_ret = parse_options(argc,argv);\n    if (parse_ret)\n        return parse_ret;\n\t\n\tif(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n\t\n    string fpkm_filename = argv[optind++];\n\n    if(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n\t\n    string spec_out_filename = argv[optind++];\n    \n    \n    FILE* fpkm_file = fopen(fpkm_filename.c_str(), \"r\");\n    if (!fpkm_file)\n    {\n        fprintf(stderr, \"Error: cannot open FPKM tracking file %s for reading\\n\",\n                fpkm_filename.c_str());\n        exit(1);\n    }\n    \n    FILE* spec_out_file = fopen(spec_out_filename.c_str(), \"w\");\n    if (!spec_out_file)\n    {\n        fprintf(stderr, \"Error: cannot open output file %s for writing\\n\",\n                spec_out_filename.c_str());\n        exit(1);\n    }\n    \n    FILE* row_matrix_out = NULL;\n    if (compute_row_matrix)\n    {\n        row_matrix_out = fopen(row_matrix_out_filename.c_str(), \"w\");\n        if (!row_matrix_out)\n        {\n            fprintf(stderr, \"Error: cannot open output file %s for writing\\n\",\n                    row_matrix_out_filename.c_str());\n            exit(1);\n        }\n    }\n    \n    FILE* row_density_out = NULL;\n    if (output_row_density)\n    {\n        row_density_out = fopen(row_density_out_filename.c_str(), \"w\");\n        if (!row_density_out)\n        {\n            fprintf(stderr, \"Error: cannot open output file %s for writing\\n\",\n                    row_density_out_filename.c_str());\n            exit(1);\n        }\n    }\n    \n    driver(fpkm_file, spec_out_file, row_matrix_out, row_density_out);\n\t\n\treturn 0;\n}\n\n\n"
  },
  {
    "path": "src/cuffcompare.cpp",
    "content": "#ifdef HAVE_CONFIG_H\n#include <config.h>\n#else\n#define PACKAGE_VERSION \"INTERNAL\"\n#define SVN_REVISION \"SVN\"\n#endif\n\n#include \"GArgs.h\"\n#include <ctype.h>\n#include <errno.h>\n#include \"gtf_tracking.h\"\n\n#ifdef HAVE_CONFIG_H\n#include \"update_check.h\"\n#endif\n\n#define USAGE \"Usage:\\n\\\ncuffcompare [-r <reference_mrna.gtf>] [-R] [-T] [-V] [-s <seq_path>] \\n\\\n    [-o <outprefix>] [-p <cprefix>] \\n\\\n    {-i <input_gtf_list> | <input1.gtf> [<input2.gtf> .. <inputN.gtf>]}\\n\\\n\\n\\\n Cuffcompare provides classification, reference annotation mapping and various\\n\\\n statistics for Cufflinks transfrags.\\n\\\n Cuffcompare clusters and tracks transfrags across multiple samples, writing\\n\\\n matching transcripts (intron chains) into <outprefix>.tracking, and a GTF\\n\\\n file <outprefix>.combined.gtf containing a nonredundant set of transcripts \\n\\\n across all input files (with a single representative transfrag chosen\\n\\\n for each clique of matching transfrags across samples).\\n\\\n\\n\\\n Options:\\n\\\n -i provide a text file with a list of Cufflinks GTF files to process instead\\n\\\n    of expecting them as command line arguments (useful when a large number\\n\\\n    of GTF files should be processed)\\n\\\n\\n\\\n -r reference annotation file (GTF/GFF)\\n\\\n\\n\\\n -R for -r option, consider only the reference transcripts that\\n\\\n    overlap any of the input transfrags (Sn correction)\\n\\\n -Q for -r option, consider only the input transcripts that\\n\\\n    overlap any of the reference transcripts (Precision correction);\\n\\\n    (Warning: this will discard all \\\"novel\\\" loci!)\\n\\\n -M discard (ignore) single-exon transfrags and reference transcripts\\n\\\n -N discard (ignore) single-exon reference transcripts\\n\\\n\\n\\\n -s path to genome sequences (optional); this can be either a multi-FASTA\\n\\\n    file or a directory containing single-fasta files (one for each contig);\\n\\\n    repeats must be soft-masked (lower case) in order to be able to classify\\n\\\n    transfrags as repeats\\n\\\n\\n\\\n -e max. distance (range) allowed from free ends of terminal exons of reference\\n\\\n    transcripts when assessing exon accuracy (100)\\n\\\n -d max. distance (range) for grouping transcript start sites (100)\\n\\\n -p the name prefix to use for consensus transcripts in the \\n\\\n    <outprefix>.combined.gtf file (default: 'TCONS')\\n\\\n -C include the \\\"contained\\\" transcripts in the .combined.gtf file\\n\\\n -F do not discard intron-redundant transfrags if they share the 5' end\\n\\\n    (if they differ only at the 3' end)\\n\\\n -G generic GFF input file(s): do not assume Cufflinks GTF, i.e. do not\\n\\\n    discard intron-redundant transfrags\\n\\\n -T do not generate .tmap and .refmap files for each input file\\n\\\n -V verbose processing mode (also showing GFF parser warnings)\\n\\\n -D (debug mode) enables -V and generates additional files: \\n\\\n    <outprefix>.Qdiscarded.lst and <outprefix>.missed_introns.gtf\\n\\\n\"\nbool debug=false;\nbool perContigStats=false; // -S to enable stats for every single contig\n//bool generic_GFF=false;\n//true if -G: won't discard intron-redundant transfrags\n\nbool showContained=false; // -C\nbool reduceRefs=false; //-R\nbool reduceQrys=false; //-Q\nbool checkFasta=false;\nbool tmapFiles=true;\nbool only_spliced_refs=false;\nint debugCounter=0;\n\nint polyrun_range=2000; //polymerase run range 2KB\ndouble scoreThreshold=0;\nchar* cprefix=NULL;\nFILE* ffasta=NULL; //genomic seq file\nFILE *f_ref=NULL; //reference mRNA GFF, if provided\nFILE* f_in=NULL; //sequentially, each input GFF file\nFILE* f_out=NULL; //stdout if not provided\nGFastaHandler gfasta;\nint xlocnum=0;\nint tsscl_num=0; //for tss cluster IDs\nint protcl_num=0; //for \"unique\" protein IDs within TSS clusters\nint tssDist=100;\nuint exonEndRange=100; // -e value, only used for exon level Sn/Sp\n//int total_tcons=0;\nint total_xloci_alt=0;\n\nvoid openfwrite(FILE* &f, GArgs& args, char opt) {\n  GStr s=args.getOpt(opt);\n  if (!s.is_empty()) {\n      if (s=='-')\n       f=stdout;\n      else {\n       f=fopen(s,\"w\");\n       if (f==NULL) GError(\"Error creating file: %s\\n\", s.chars());\n       }\n     }\n}\n\n//-- structure to keep track of data from multiple qry input files for a single genomic seq\nclass GSeqTrack {\n  int gseq_id;\n public:\n  const char* gseq_name;\n  GList<GLocus>* rloci_f; //reference loci for this genomic sequence\n  GList<GLocus>* rloci_r;\n  GList<GXLocus> xloci_f; // extended super-loci across all qry datasets\n  GList<GXLocus> xloci_r; // extended super-loci across all qry datasets\n  GList<GXLocus> xloci_u; // extended super-loci across all qry datasets\n  GSeqData* qdata[MAX_QFILES]; //fixed order array with GSeqData for each qry input\n                 //element in array is NULL if a qry file has no transcripts on this genomic sequence\n  int get_gseqid() { return gseq_id; }\n  GSeqTrack(int gid=-1):xloci_f(true,true,false),\n        xloci_r(true,true,false), xloci_u(true,true,false) {\n    gseq_id=gid;\n    if (gseq_id>=0) {\n      gseq_name=GffObj::names->gseqs.getName(gseq_id);\n      }\n    rloci_f=NULL;\n    rloci_r=NULL;\n    for (int i=0;i<MAX_QFILES;i++) qdata[i]=NULL;\n    }\n  bool operator==(GSeqTrack& d){\n      return (gseq_id==d.gseq_id);\n      }\n  bool operator<(GSeqTrack& d){\n     return (gseq_id<d.gseq_id);\n     }\n};\n\n//char* getFastaFile(int gseq_id);\n\n// ref globals\nbool haveRefs=false;  //true if a reference annotation (-r) is provide\n\nGList<GSeqData> ref_data(true,true,true); //list of reference mRNAs and loci data for each genomic seq\n              //each locus will keep track of any superloci which includes it, formed during the analysis\n\nvoid processLoci(GSeqData& seqdata, GSeqData* refdata=NULL, int qfidx=0);\n\nvoid reportStats(FILE* fout, const char* setname, GSuperLocus& stotal,\n       GSeqData* seqdata=NULL, GSeqData* refdata=NULL);\n\nGSeqData* getQryData(int gid, GList<GSeqData>& qdata);\nvoid trackGData(int qcount, GList<GSeqTrack>& gtracks, GStr& fbasename, FILE** ftr, FILE** frs);\n\n#define FWCLOSE(fh) if (fh!=NULL && fh!=stdout) fclose(fh)\n#define FRCLOSE(fh) if (fh!=NULL && fh!=stdin) fclose(fh)\n\nFILE* f_mintr=NULL; //missed ref introns (debug only)\nFILE* f_qdisc=NULL; //missed ref introns (debug only)\n\nbool multiexon_only=false;\nbool multiexonrefs_only=false;\n\nGHash<GStr> refdescr;\nvoid loadRefDescr(const char* fname);\n\nGList<GStr> qryfiles(false,true,false);\n\n//list of GSeqTrack data, sorted by gseq_id\nGList<GSeqTrack> gseqtracks(true,true,true);\nGSeqTrack* findGSeqTrack(int gsid);\n\n\nint cmpGTrackByName(const pointer p1, const pointer p2) {\n return strcmp(((GSeqTrack*)p1)->gseq_name, ((GSeqTrack*)p2)->gseq_name);\n}\n\n\nvoid show_usage() {\n  GMessage(\"cuffcompare v%s (%s)\\n\", PACKAGE_VERSION, SVN_REVISION);\n  GMessage( \"-----------------------------\\n\");\n  GMessage(\"%s\\n\", USAGE);\n  }\n\nint main(int argc, char * const argv[]) {\n\n#ifdef HEAPROFILE\n  if (!IsHeapProfilerRunning())\n      HeapProfilerStart(\"./cuffcompare_dbg.hprof\");\n#endif\n\n  GArgs args(argc, argv, \"XDTMNVFGSCKQRLhp:e:d:s:i:n:r:o:\");\n  int e;\n  if ((e=args.isError())>0) {\n    show_usage();\n    GMessage(\"Invalid argument: %s\\n\", argv[e]);\n    exit(1);\n    }\n  if (args.getOpt('h')!=NULL){\n    show_usage();\n    exit(1);\n    }\n  showContained=(args.getOpt('C')!=NULL);\n  debug=(args.getOpt('D')!=NULL);\n  tmapFiles=(args.getOpt('T')==NULL);\n  multiexon_only=(args.getOpt('M')!=NULL);\n  multiexonrefs_only=(args.getOpt('N')!=NULL); \n  perContigStats=(args.getOpt('S')!=NULL);\n  checkFasta=(args.getOpt('K')!=NULL);\n  gtf_tracking_verbose=((args.getOpt('V')!=NULL) || debug);\n  FILE* finlst=NULL;\n  GStr s=args.getOpt('i');\n  if (!s.is_empty()) {\n      if (s=='-')\n       finlst=stdin;\n      else {\n       finlst=fopen(s,\"r\");\n       if (finlst==NULL) GError(\"Error opening file: %s\\n\", s.chars());\n             }\n           }\n        int numqryfiles=0;\n        if (finlst) {\n          GLineReader* lr=new GLineReader(finlst);\n          char* l=NULL;\n          while ((l=lr->getLine())!=NULL) {\n            if (strlen(l)<2 || startsWith(l,\"# \") || isspace(*l)) continue;\n            if (!fileExists(l)) GError(\"Error: cannot locate input file: %s\\n\", l);\n            qryfiles.Add(new GStr(l));\n            }\n          delete lr;\n          //if (qryfiles.Count()>10) \n          gtf_tracking_largeScale=true;\n          }\n         else {\n          numqryfiles=args.startNonOpt();\n          char *infile=NULL;\n          if (numqryfiles>0) {\n            if (numqryfiles>6) \n               gtf_tracking_largeScale=true;\n            while ((infile=args.nextNonOpt())!=NULL) {\n              if (!fileExists(infile)) GError(\"Error: cannot locate input file: %s\\n\", infile);\n              qryfiles.Add(new GStr(infile));\n              } //for each argument\n            }\n          }\n        numqryfiles=qryfiles.Count();\n        if (numqryfiles==0) {\n          show_usage();\n          exit(1);\n          }\n      if (numqryfiles>MAX_QFILES) {\n           GMessage(\"Error: too many input files (limit set to %d at compile time)\\n\",MAX_QFILES);\n           GMessage(\"(if you need to raise this limit set a new value for\\nMAX_QFILES in gtf_tracking.h and recompile)\\n\");\n           exit(0x5000);\n           }\n  #ifdef HAVE_CONFIG_H\n  check_version(PACKAGE_VERSION);\n  #endif\n  gfasta.init(args.getOpt('s'));\n   // determine if -s points to a multi-fasta file or a directory\n  //s=args.getOpt('c');\n  //if (!s.is_empty()) scoreThreshold=s.asReal();\n  s=args.getOpt('p');\n  if (!s.is_empty()) cprefix=Gstrdup(s.chars());\n               else  cprefix=Gstrdup(\"TCONS\");\n  s=args.getOpt('e');\n  if (!s.is_empty()) exonEndRange=s.asInt();\n  s=args.getOpt('d');\n  if (!s.is_empty()) tssDist=s.asInt();\n\n  s=args.getOpt('n');\n  if (!s.is_empty()) loadRefDescr(s.chars());\n  s=args.getOpt('r');\n  if (!s.is_empty()) {\n    f_ref=fopen(s,\"r\");\n    if (f_ref==NULL) GError(\"Error opening reference gff: %s\\n\",s.chars());\n    haveRefs=true;\n    if (gtf_tracking_verbose) GMessage(\"Loading reference transcripts..\\n\");\n    read_mRNAs(f_ref, ref_data, &ref_data, 1, -1, s.chars(), (multiexonrefs_only || multiexon_only));\n    haveRefs=(ref_data.Count()>0);\n    reduceRefs=(args.getOpt('R')!=NULL);\n    reduceQrys=(args.getOpt('Q')!=NULL);\n    //if (gtf_tracking_verbose) GMessage(\"..reference annotation loaded\\n\");\n    }\n  int discard_redundant=1; //discard intron-redundant input transfrags\n  //generic_GFF=args.getOpt('G');\n  if (args.getOpt('G')) discard_redundant=0; //generic GTF, don't try to discard \"redundant\" transcripts\n  if (args.getOpt('F')) {\n  \tif (discard_redundant==0) {\n  \t\tshow_usage();\n  \t\tGMessage(\"Error: options -F and -G are mutually exclusive!\\n\");\n  \t\texit(1);\n  \t}\n    else {\n  \tdiscard_redundant=2; // don't discard \"redundant\" transcripts if they start with the same 5' intron\n    }\n  }\n  //if a full pathname is given\n  //the other common output files will still be created in the current directory:\n  // .loci, .tracking, .stats\n  GStr outbasename; //include path, if provided\n  GStr outprefix; //without path and/or extension\n  GStr outstats=args.getOpt('o');\n  if (outstats.is_empty() || outstats==\"-\") {\n       outstats=\"cuffcmp\";\n       }\n  outbasename=outstats;\n  GStr outext(getFileExt(outstats.chars()));\n  if (outext.is_empty()) {\n    outext=\"stats\";\n    outstats.append(\".stats\");\n    outbasename=outstats;\n    }\n    else outext.lower();\n  if (outext==\"txt\" || outext==\"out\" || outext==\"stats\" || outext==\"summary\") {\n      outbasename.cut(outbasename.length()-outext.length()-1);\n      }\n\n  outprefix=outbasename;\n  int di=outprefix.rindex(CHPATHSEP);\n  if (di>=0) outprefix.cut(0,di+1);\n  \n  if (debug) { //create a few more files potentially useful for debugging\n        s=outbasename;\n        s.append(\".missed_introns.gtf\");\n        f_mintr=fopen(s.chars(),\"w\");\n        if (f_mintr==NULL) GError(\"Error creating file %s!\\n\",s.chars());\n        if (reduceQrys) {\n           s=outbasename;\n           s.append(\".Qdiscarded.lst\");\n           f_qdisc=fopen(s.chars(),\"w\");\n           if (f_qdisc==NULL) GError(\"Error creating file %s!\\n\",s.chars());\n        }\n        /*\n        s=outbasename;\n        s.append(\".noTP_introns.gtf\");\n        f_nintr=fopen(s.chars(),\"w\");\n        s=outbasename;\n        s.append(\".wrong_Qintrons.gtf\");\n        f_qintr=fopen(s.chars(),\"w\");\n        */\n        }\n\n  f_out=fopen(outstats, \"w\");\n  if (f_out==NULL) GError(\"Error creating output file %s!\\n\", outstats.chars());\n  if (gtf_tracking_verbose) GMessage(\"Prefix for output files: %s\\n\", outprefix.chars());\n  fprintf(f_out, \"# Cuffcompare v%s | Command line was:\\n#\", PACKAGE_VERSION);\n  for (int i=0;i<argc-1;i++) \n    fprintf(f_out, \"%s \", argv[i]);\n  fprintf(f_out, \"%s\\n#\\n\", argv[argc-1]);\n  //int qfileno=0;\n  GList<GSeqData>** qrysdata=NULL;\n  FILE** tfiles=NULL;\n  FILE** rtfiles=NULL;\n  GMALLOC(qrysdata, numqryfiles*sizeof(GList<GSeqData>*));\n  if (tmapFiles) {\n      GMALLOC(tfiles, numqryfiles*sizeof(FILE*));\n      if (haveRefs) {\n          GMALLOC(rtfiles, numqryfiles*sizeof(FILE*));\n          }\n      }\n  for (int fi=0;fi<qryfiles.Count();fi++) {\n    GStr in_file(qryfiles[fi]->chars());\n    GStr infname(getFileName(qryfiles[fi]->chars())); //file name only\n    GStr indir(qryfiles[fi]->chars());\n    di=indir.rindex(CHPATHSEP);\n    if (di>=0) indir.cut(di+1); //directory path for this input file\n          else indir=\"\"; //current directory\n    \n    if (debug || (gtf_tracking_verbose && !gtf_tracking_largeScale))\n        GMessage(\"Loading query file #%d: %s\\n\",fi+1, in_file.chars());\n    if (in_file==\"-\") { f_in=stdin; in_file=\"stdin\"; }\n      else {\n        f_in=fopen(in_file.chars(),\"r\");\n        if (f_in==NULL) \n            GError(\"Cannot open input file %s!\\n\",in_file.chars());\n        }\n    //f_in is the query gff file to process\n    GStr sbase(indir);\n    sbase.append(outprefix);\n    sbase.append(\".\");\n    sbase.append(infname);\n    if (tmapFiles) {\n        //-- we should keep the infname path, otherwise the remaining file names \n        //   may be the same and clobber each other\n        s=sbase;\n        s.append(\".tmap\");\n        tfiles[fi]=fopen(s.chars(),\"w\");\n        if (tfiles[fi]==NULL)\n          GError(\"Error creating file '%s'!\\n\",s.chars());\n        fprintf(tfiles[fi],\"ref_gene_id\\tref_id\\tclass_code\\tcuff_gene_id\\tcuff_id\\tFMI\\tFPKM\\tFPKM_conf_lo\\tFPKM_conf_hi\\tcov\\tlen\\tmajor_iso_id\\tref_match_len\\n\");\n        if (haveRefs) {\n          s=sbase;\n          s.append(\".refmap\");\n          rtfiles[fi]=fopen(s.chars(),\"w\");\n          if (rtfiles[fi]==NULL)\n             GError(\"Error creating file '%s'!\\n\",s.chars());\n          fprintf(rtfiles[fi],\"ref_gene_id\\tref_id\\tclass_code\\tcuff_id_list\\n\");\n          }\n        }\n\n      GList<GSeqData>* pdata=new GList<GSeqData>(true,true,true);\n      qrysdata[fi]=pdata;\n      //if (gtf_tracking_verbose) GMessage(\"Loading transcripts from %s..\\n\",in_file.chars());\n      read_mRNAs(f_in, *pdata, &ref_data, discard_redundant, fi, in_file.chars(), multiexon_only);\n      GSuperLocus gstats;\n      GFaSeqGet *faseq=NULL;\n      for (int g=0;g<pdata->Count();g++) { //for each seqdata related to a genomic sequence\n        int gsid=pdata->Get(g)->get_gseqid();\n        GSeqData* refdata=getRefData(gsid, ref_data);//ref data for this contig\n        if (!gtf_tracking_largeScale)\n          processLoci(*(pdata->Get(g)), refdata, fi);\n        GSeqTrack* seqtrack=findGSeqTrack(gsid); //this will add a gseqtrack if it doesn't exist\n        // for gsid\n        if (refdata!=NULL) {\n          seqtrack->rloci_f=&(refdata->loci_f);\n          seqtrack->rloci_r=&(refdata->loci_r);\n        }\n        seqtrack->qdata[fi]=pdata->Get(g);\n        //will only gather data into stats if perContig==false\n        if (!gtf_tracking_largeScale) reportStats(f_out, getGSeqName(gsid), gstats,\n              pdata->Get(g), refdata);\n        if (faseq!=NULL) delete faseq;\n      } //for each genomic sequence data\n      //there could be genomic sequences with no qry transcripts\n      //but with reference transcripts\n      if (haveRefs && !reduceRefs && !gtf_tracking_largeScale) {\n        for (int r=0;r<ref_data.Count();r++) {\n          GSeqData* refdata=ref_data[r];\n          int gsid=refdata->get_gseqid();\n          if (getQryData(gsid, *pdata)==NULL) {\n            reportStats(f_out, getGSeqName(gsid), gstats, NULL, refdata);\n            }//completely missed all refdata on this contig\n        }\n      }\n      //now report the summary:\n      if (!gtf_tracking_largeScale) reportStats(f_out, in_file.chars(), gstats);\n      if (f_in!=stdin) fclose(f_in);\n      //qfileno++;\n  }//for each input file\n  if (f_mintr!=NULL) fclose(f_mintr);\n  if (f_qdisc!=NULL) fclose(f_qdisc);\n  gseqtracks.setSorted(&cmpGTrackByName);\n  if (gtf_tracking_verbose)\n\t   GMessage(\"Tracking transcripts across %d query file(s)..\\n\", numqryfiles);\n  trackGData(numqryfiles, gseqtracks, outbasename, tfiles, rtfiles);\n  fprintf(f_out, \"\\n Total union super-loci across all input datasets: %d \\n\", xlocnum);\n  if (numqryfiles>1) {\n      fprintf(f_out, \"  (%d multi-transcript, ~%.1f transcripts per locus)\\n\",\n           total_xloci_alt, ((double)(GXConsensus::count))/xlocnum);\n      }\n  if (gtf_tracking_verbose) GMessage(\"Cleaning up..\\n\");\n  GFREE(cprefix);\n  // clean up\n  for (int i=0;i<numqryfiles;i++) {\n    delete qrysdata[i];\n    }\n  GFREE(qrysdata);\n  GFREE(tfiles);\n  GFREE(rtfiles);\n  gseqtracks.Clear();\n  FRCLOSE(f_ref);\n  FWCLOSE(f_out);\n  if (gtf_tracking_verbose) GMessage(\"Done.\\n\");\n  ref_data.Clear();\n  //getchar();\n} //main ends here\n\nvoid show_exons(FILE* f, GffObj& m) {\n  fprintf(f,\"(\");\n  int imax=m.exons.Count()-1;\n  for (int i=0;i<=imax;i++) {\n    if (i==imax) fprintf(f,\"%d-%d)\",m.exons[i]->start, m.exons[i]->end);\n            else fprintf(f,\"%d-%d,\",m.exons[i]->start, m.exons[i]->end);\n    }\n}\n\nbool ichainMatch(GffObj* t, GffObj* r, bool& exonMatch, int fuzz=0) {\n  //t's intron chain is considered matching to reference r\n  //if r's intron chain is the same with t's chain\n  //OR IF fuzz!=0 THEN also accepts r's intron chain to be a SUB-chain of t's chain\n  exonMatch=false;\n  int imax=r->exons.Count()-1;\n  int jmax=t->exons.Count()-1;\n  if (imax==0 || jmax==0) {   //single-exon mRNAs\n     if (imax!=jmax) return false;\n     exonMatch=r->exons[0]->coordMatch(t->exons[0],fuzz);\n     /*if (exonMatch) return true;\n       else return (r->exons[0]->start>=t->exons[0]->start &&\n                    r->exons[0]->end<=t->exons[0]->end);*/\n     return exonMatch;\n     }\n\n  if (r->exons[imax]->start<t->exons[0]->end ||\n      t->exons[jmax]->start<r->exons[0]->end ) //intron chains do not overlap at all\n          {\n           return false;\n          }\n  //check intron overlaps\n  int i=1;\n  int j=1;\n  bool exmism=false; //any mismatch\n  while (i<=imax && j<=jmax) {\n     uint rstart=r->exons[i-1]->end;\n     uint rend=r->exons[i]->start;\n     uint tstart=t->exons[j-1]->end;\n     uint tend=t->exons[j]->start;\n     if (tend<rstart) { j++; continue; }\n     if (rend<tstart) { i++; continue; }\n     break; //here we have an intron overlap\n     }\n  if (i>1 || i>imax || j>jmax) {\n      //first ref intron not matching\n      //OR no intron match found at all\n      return false;\n      }\n  //from now on we expect intron matches up to imax\n  if (i!=j || imax!=jmax) { \n      exmism=true; //not all introns match, so obviously there's \"exon\" mismatch\n      //FIXME: fuzz!=0 determines acceptance of *partial* chain match \n      // but only r as a sub-chain of t, not the other way around!\n      if (jmax<imax) return false; // qry ichain cannot be a subchain of ref ichain\n      if (fuzz==0) return false;\n      }\n  for (;i<=imax && j<=jmax;i++,j++) {\n    if (abs((int)(r->exons[i-1]->end-t->exons[j-1]->end))>fuzz ||\n        abs((int)(r->exons[i]->start-t->exons[j]->start))>fuzz) {\n        return false; //intron mismatch found\n        }\n    }\n  //if we made it here, we have matching intron chains up to MIN(imax,jmax)\n  if (!exmism) {\n          //check terminal exons:\n          exonMatch = ( abs((int)(r->exons[0]->start-t->exons[0]->start))<=fuzz &&\n               abs((int)(r->exons[imax]->end-t->exons[jmax]->end))<=fuzz );\n          }\n        // else exonMatch is false\n  return true;\n}\n\nbool exon_match(GXSeg& r, GXSeg& q, uint fuzz=0) {\n uint sd = (r.start>q.start) ? r.start-q.start : q.start-r.start;\n uint ed = (r.end>q.end) ? r.end-q.end : q.end-r.end;\n uint ex_range=exonEndRange;\n if (ex_range<=fuzz) ex_range=fuzz;\n if ((r.flags&1) && (q.flags&1)) {\n\tif (sd>ex_range) return false;\n }\n else {\n\tif (sd>fuzz) return false;\n }\n if ((r.flags&2) && (q.flags&2)) {\n\tif (ed>ex_range) return false;\n }\n else {\n\tif (ed>fuzz) return false;\n }\n return true;\n}\n\nvoid compareLoci2R(GList<GLocus>& loci, GList<GSuperLocus>& cmpdata,\n                             GList<GLocus>& refloci, int qfidx) {\n cmpdata.Clear();//a new list of superloci will be built\n if (refloci.Count()==0 || loci.Count()==0) return;\n //reset cmpovl and stats\n for (int i=0;i<refloci.Count();i++) refloci[i]->creset();\n //find loci with overlapping refloci\n //and store cmpovl links both ways for ALL loci and refloci on this strand\n for (int l=0;l<loci.Count();l++) {\n   GLocus* locus=loci[l];\n   locus->creset();\n   for (int j=0;j<refloci.Count();j++) {\n     //if (refloci[j]->start>locus->end) break;\n     if (refloci[j]->start>locus->end) {\n         if (refloci[j]->start-locus->end > GFF_MAX_LOCUS) break;\n         continue;\n         }\n     if (locus->start>refloci[j]->end) continue;\n     // then we must have overlap here:\n     //if (locus->overlap(refloci[j]->start, refloci[j]->end)) {\n        locus->cmpovl.Add(refloci[j]);\n        refloci[j]->cmpovl.Add(locus);\n        //}\n     }//for each reflocus\n   } //for each locus\n\n //create corresponding \"superloci\" from transitive overlapping between loci and ref\n for (int l=0;l<loci.Count();l++) {\n  if (loci[l]->v!=0) continue; //skip, already processed\n  GSuperLocus* super=new GSuperLocus();\n  super->qfidx=qfidx;\n  //try to find all other loci connected to this locus loci[l]\n  GList<GLocus> lstack(false,false,false);  //traversal stack\n  lstack.Push(loci[l]);\n  while (lstack.Count()>0) {\n      GLocus* locus=lstack.Pop();\n      if (locus->v!=0 || locus->cmpovl.Count()==0) continue;\n      super->addQlocus(*locus);\n      locus->v=1;\n      for (int r=0;r<locus->cmpovl.Count();r++) {\n        GLocus* rloc=locus->cmpovl[r];\n        if (rloc->v==0) {\n          super->addRlocus(*rloc);\n          rloc->v=1;\n          for (int ll=0;ll<rloc->cmpovl.Count();ll++) {\n              if (rloc->cmpovl[ll]->v==0) lstack.Push(rloc->cmpovl[ll]);\n              }\n           }\n        } //for each overlapping reflocus\n      } //while linking\n\n  if (super->qloci.Count()==0) {\n    delete super;\n    continue; //try next query loci\n    }\n  //--here we have a \"superlocus\" region data on both qry and ref\n  // -- analyze mexons matching (base level metrics)\n  cmpdata.Add(super);\n  //make each ref locus keep track of all superloci containing it\n    for (int rl=0;rl<super->rloci.Count();rl++) {\n      super->rloci[rl]->superlst->Add(super);\n      }\n  for (int x=0;x<super->rmexons.Count();x++) {\n    super->rbases_all += super->rmexons[x].end-super->rmexons[x].start+1;\n    }\n  for (int x=0;x<super->qmexons.Count();x++) {\n    super->qbases_all += super->qmexons[x].end-super->qmexons[x].start+1;\n    }\n  int i=0; //locus mexons\n  int j=0; //refmexons\n  while (i<super->qmexons.Count() && j<super->rmexons.Count()) {\n     uint istart=super->qmexons[i].start;\n     uint iend=super->qmexons[i].end;\n     uint jstart=super->rmexons[j].start;\n     uint jend=super->rmexons[j].end;\n     if (iend<jstart) { i++; continue; }\n     if (jend<istart) { j++; continue; }\n     //v--overlap here:\n     uint ovlstart = jstart>istart? jstart : istart;\n     uint ovlend = iend<jend ? iend : jend;\n     uint ovlen=ovlend-ovlstart+1;\n     super->baseTP+=ovlen; //qbases_cov\n     if (iend<jend) i++;\n               else j++;\n     } //while mexons ovl search\n  /* if (reduceRefs) {\n    super->baseFP=super->qbases_all-super->baseTP;\n    super->baseFN=super->rbases_all-super->baseTP;\n    }\n  */\n  // -- exon level comparison:\n  int* qexovl; //flags for qry exons with ref overlap\n  GCALLOC(qexovl,super->quexons.Count()*sizeof(int));\n  int* rexovl; //flags for ref exons with qry overlap\n  GCALLOC(rexovl,super->ruexons.Count()*sizeof(int));\n  for (int i=0;i<super->quexons.Count();i++) {\n\t  uint istart=super->quexons[i].start;\n\t  uint iend=super->quexons[i].end;\n\t  for (int j=0;j<super->ruexons.Count();j++) {\n\t\t  uint jstart=super->ruexons[j].start;\n\t\t  uint jend=super->ruexons[j].end;\n\t\t  if (iend<jstart) break;\n\t\t  if (jend<istart) continue;\n\t\t  //--- overlap here between quexons[i] and ruexons[j]\n\t\t  qexovl[i]++;\n\t\t  rexovl[j]++;\n\t\t  /*if (exon_match(super->quexons[i], super->ruexons[j],5)) {\n\t\t\t  if (!ATPfound) { //count a ref approx match only once\n\t\t\t\t  super->exonATP++;\n\t\t\t\t  ATPfound=true;\n\t\t\t  }*/\n\t\t\t  if (exon_match(super->quexons[i], super->ruexons[j])) {\n\t\t\t\t  if ((super->ruexons[j].flags & 4)==0) {\n\t\t\t\t      super->exonTP++;\n\t\t\t\t      super->ruexons[j].flags |= 4;\n\t\t\t\t  }\n\t\t\t\t  if ((super->quexons[i].flags & 4)==0) {\n\t\t\t\t      super->exonQTP++;\n\t\t\t\t      super->quexons[i].flags |= 4;\n\t\t\t\t  }\n\t\t\t  } //exact match\n\t\t  //} //fuzzy match\n\t  } //ref uexon loop\n  } //qry uexon loop\n  //DEBUG only:\n  //if (super->exonTP > super->total_rexons)\n  //   GMessage(\"Warning: superlocus %d-%d has exonTP %d > total rexons %d\\n\",\n  //      super->start, super->end, super->exonTP, super->total_rexons);\n  super->m_exons=0; //ref exons with no query overlap\n  super->w_exons=0; //qry exons with no ref overlap\n  for (int x=0;x<super->quexons.Count();x++)\n       if (qexovl[x]==0) super->w_exons++;\n  for (int x=0;x<super->ruexons.Count();x++)\n       if (rexovl[x]==0) super->m_exons++;\n  GFREE(rexovl);\n  GFREE(qexovl);\n\n  //-- intron level stats:\n  //query:\n  int* qinovl=NULL; //flags for qry introns with at least some ref overlap\n  int* qtpinovl=NULL; //flags for qry introns with perfect ref overlap\n  if (super->qintrons.Count()>0) {\n   GCALLOC(qinovl,super->qintrons.Count()*sizeof(int));\n   GCALLOC(qtpinovl,super->qintrons.Count()*sizeof(int));\n   }\n  //-- reference:\n  int* rinovl=NULL; //flags for ref introns with qry overlap\n  int* rtpinovl=NULL; //ref introns with perfect qry intron overlap\n  if (super->rintrons.Count()>0) {\n   GCALLOC(rinovl,super->rintrons.Count()*sizeof(int));\n   GCALLOC(rtpinovl,super->rintrons.Count()*sizeof(int));\n   }\n  for (int i=0;i<super->qintrons.Count();i++) {\n    uint istart=super->qintrons[i].start;\n    uint iend=super->qintrons[i].end;\n    for (int j=0;j<super->rintrons.Count();j++) {\n      uint jstart=super->rintrons[j].start;\n      uint jend=super->rintrons[j].end;\n      if (iend<jstart) break;\n      if (jend<istart) continue;\n      //--- overlap here between qintrons[i] and rintrons[j]\n      qinovl[i]++;\n      rinovl[j]++;\n      /*if (super->qintrons[i].coordMatch(&super->rintrons[j],5)) {\n         super->intronATP++;*/\n         if (super->qintrons[i].coordMatch(&super->rintrons[j])) {\n             super->intronTP++;\n             qtpinovl[i]++;\n             rtpinovl[j]++;\n             } //exact match\n         //} //fuzzy match\n      } //ref intron loop\n   } //qry intron loop\n  super->m_introns=0; //ref introns with no query overlap\n  super->w_introns=0; //qry introns with no ref overlap\n  for (int x=0;x<super->qintrons.Count();x++) {\n       if (qinovl[x]==0) { super->w_introns++;\n                 //qry introns with no ref intron overlap AT ALL\n                 super->i_qwrong.Add(super->qintrons[x]);\n                 }\n          else\n             if (qtpinovl[x]==0) {\n               super->i_qnotp.Add(super->qintrons[x]);\n             }\n       }\n  for (int x=0;x<super->rintrons.Count();x++) {\n       if (rinovl[x]==0) { //no intron overlap at all\n             super->m_introns++;\n             super->i_missed.Add(super->rintrons[x]);\n             }\n       else if (rtpinovl[x]==0) { //no perfect intron match\n            super->i_notp.Add(super->rintrons[x]);\n            }\n       }\n  GFREE(rinovl);\n  GFREE(rtpinovl);\n  GFREE(qinovl);\n  GFREE(qtpinovl);\n\n  // ---- now intron-chain and transcript comparison\n  GVec<int> matched_refs(super->rmrnas.Count(), 0); //keep track of matched refs\n  //GVec<int> amatched_refs(super->rmrnas.Count(), 0); //keep track of fuzzy-matched refs\n  for (int i=0;i<super->qmrnas.Count();i++) {\n\t  uint istart=super->qmrnas[i]->exons.First()->start;\n\t  uint iend=super->qmrnas[i]->exons.Last()->end;\n\t  for (int j=0;j<super->rmrnas.Count();j++) {\n\t\t  if (matched_refs[j]) continue; //already counted a TP here\n\t\t  uint jstart=super->rmrnas[j]->exons.First()->start;\n\t\t  uint jend=super->rmrnas[j]->exons.Last()->end;\n\t\t  if (iend<jstart) break;\n\t\t  if (jend<istart) continue;\n\t\t  //--- overlap here --\n\t\t  //bool exonMatch=false;\n\t\t  if (super->qmrnas[i]->udata & 2) continue; //already found a good matching ref\n\t\t  GLocus* qlocus=((CTData*)super->qmrnas[i]->uptr)->locus;\n\t\t  GLocus* rlocus=((CTData*)super->rmrnas[j]->uptr)->locus;\n\t\t  int ovlen=0;\n\t\t  //look for a transcript match ('=' code)\n\t\t  if (tMatch(*(super->qmrnas[i]),*(super->rmrnas[j]), ovlen, true)) {\n\t\t\t  super->qmrnas[i]->udata|=2;\n\t\t\t  matched_refs[j]++;\n\t\t\t  //fprintf(stderr, \"%s\\n\", super->qmrnas[i]->getID()); //DEBUG ONLY\n\t\t\t  super->mrnaTP++;\n\t\t\t  qlocus->mrnaTP++;\n\t\t\t  rlocus->mrnaTP++;\n\t\t\t  /*super->mrnaATP++;\n\t\t\t  qlocus->mrnaATP++;\n\t\t\t  rlocus->mrnaATP++;*/\n\t\t\t  if (super->qmrnas[i]->exons.Count()>1) {\n\t\t\t\t  super->ichainTP++;\n\t\t\t\t  qlocus->ichainTP++;\n\t\t\t\t  rlocus->ichainTP++;\n\t\t\t\t  /*super->ichainATP++;\n\t\t\t\t  qlocus->ichainATP++;\n\t\t\t\t  rlocus->ichainATP++;*/\n\t\t\t  }\n\t\t  }\n\t\t  /* else { //not an '=' match, look for a fuzzy coord match\n\t\t\t  if (amatched_refs[j]) continue; //this reference already counted as a TP fuzzy match\n\t\t\t  if (super->qmrnas[i]->udata & 1) continue; //fuzzy match already found\n\t\t\t  if (ichainMatch(super->qmrnas[i],super->rmrnas[j],exonMatch, 5)) {\n\t\t\t\t  //NB: also accepts the possibility that ref's i-chain be a subset of qry's i-chain\n\t\t\t\t  super->qmrnas[i]->udata|=1;\n\t\t\t\t  amatched_refs[j]++;\n\t\t\t\t  if (super->qmrnas[i]->exons.Count()>1) {\n\t\t\t\t\t  super->ichainATP++;\n\t\t\t\t\t  qlocus->ichainATP++;\n\t\t\t\t\t  rlocus->ichainATP++;\n\t\t\t\t  }\n\t\t\t\t  if (exonMatch) {\n\t\t\t\t\t  super->mrnaATP++;\n\t\t\t\t\t  qlocus->mrnaATP++;\n\t\t\t\t\t  rlocus->mrnaATP++;\n\t\t\t\t  }\n\t\t\t  }\n\t\t  } //fuzzy match check */\n\t  } //ref loop\n  } //qry loop\n  for (int ql=0;ql<super->qloci.Count();ql++) {\n      if (super->qloci[ql]->mrnaTP>0)\n                 super->locusQTP++;\n      //if (super->qloci[ql]->mrnaATP>0)\n      //          super->locusAQTP++;\n      }\n  for (int rl=0;rl<super->rloci.Count();rl++) {\n      if (super->rloci[rl]->mrnaTP >0 )\n                 super->locusTP++;\n      //if (super->rloci[rl]->mrnaATP>0)\n      //           super->locusATP++;\n      }\n  }//for each unlinked locus\n}\n\n//look for qry data for a specific genomic sequence\nGSeqData* getQryData(int gid, GList<GSeqData>& qdata) {\n  int qi=-1;\n  GSeqData f(gid);\n  GSeqData* q=NULL;\n  if (qdata.Found(&f,qi))\n        q=qdata[qi];\n  return q;\n}\n\nconst char* findDescr(GffObj* gfobj) {\n  if (refdescr.Count()==0) return NULL;\n  GStr* s=refdescr.Find(gfobj->getID());\n  if (s==NULL) {\n       s=refdescr.Find(gfobj->getGeneName());\n       if (s==NULL) s=refdescr.Find(gfobj->getGeneID());\n       }\n  if (s!=NULL)\n     return s->chars();\n  return NULL;\n}\n\nconst char* getGeneID(GffObj* gfobj) {\n //returns anything that might resemble a gene identifier for this transcript\n //or, if everything fails, returns the transcript ID\n const char* s=gfobj->getGeneName();\n if (s) return s;\n if ((s=gfobj->getGeneID())!=NULL) return s;\n if ((s=gfobj->getAttr(\"Name\"))!=NULL) return s;\n return gfobj->getID();\n}\n\nconst char* getGeneID(GffObj& gfobj) {\n return getGeneID(&gfobj);\n}\n\nvoid writeLoci(FILE* f, GList<GLocus> & loci) {\n for (int l=0;l<loci.Count();l++) {\n   GLocus& loc=*(loci[l]);\n   fprintf(f,\"%s\\t%s[%c]%d-%d\\t\", loc.mrna_maxcov->getID(),\n       loc.mrna_maxcov->getGSeqName(),\n           loc.mrna_maxcov->strand, loc.start,loc.end);\n   //now print all transcripts in this locus, comma delimited\n   int printfd=0;\n   for (int i=0;i<loc.mrnas.Count();i++) {\n      if (loc.mrnas[i]==loc.mrna_maxcov) continue;\n      if (printfd==0) fprintf(f,\"%s\",loc.mrnas[i]->getID());\n          else fprintf(f,\",%s\",loc.mrnas[i]->getID());\n      printfd++;\n      }\n   const char* rdescr=findDescr(loc.mrna_maxcov);\n   if (rdescr==NULL)  fprintf(f,\"\\t\\n\");\n                 else fprintf(f,\"\\t%s\\n\",rdescr);\n   }\n}\n\nvoid printXQ1(FILE* f, int qidx, GList<GLocus>& qloci) {\n  int printfd=0;\n  //print\n  for (int i=0;i<qloci.Count();i++) {\n     if (qloci[i]->qfidx!=qidx) continue;\n      for (int j=0;j<qloci[i]->mrnas.Count();j++) {\n        if (printfd==0) fprintf(f,\"%s\",qloci[i]->mrnas[j]->getID());\n            else fprintf(f,\",%s\",qloci[i]->mrnas[j]->getID());\n        printfd++;\n        }\n      }\n  if (printfd==0) fprintf(f,\"-\");\n }\n\nvoid numXLoci(GList<GXLocus>& xloci, int& last_id) {\n  for (int l=0;l<xloci.Count();l++) {\n    if (xloci[l]->qloci.Count()==0) continue; //we never print ref-only xloci\n    last_id++;\n    xloci[l]->id=last_id;\n    }\n}\n\n\nclass GProtCl {\n public:\n   GList<GXConsensus> protcl;\n   GProtCl(GXConsensus* c=NULL):protcl(true,false,false) {\n    if (c!=NULL)\n       protcl.Add(c);\n    }\n   bool add_Pcons(GXConsensus* c) {\n    if (c==NULL || c->aalen==0) return false;\n    if (protcl.Count()==0) {\n        protcl.Add(c);\n        return true;\n        }\n    if (protcl[0]->aalen!=c->aalen) return false;\n    if (strcmp(protcl[0]->aa,c->aa)!=0) return false;\n    protcl.Add(c);\n    return true;\n    }\n\n   void addMerge(GProtCl& pcl, GXConsensus* pclnk) {\n    for (int i=0;i<pcl.protcl.Count();i++) {\n      if (pcl.protcl[i]!=pclnk) {\n          protcl.Add(pcl.protcl[i]);\n          }\n      }\n    }\n\n   int aalen() {\n    if (protcl.Count()==0) return 0;\n    return protcl[0]->aalen;\n   }\n   bool operator==(GProtCl& cl) {\n    return this==&cl;\n    }\n   bool operator<(GProtCl& cl) {\n    return (this<&cl);\n    }\n};\n\nclass GTssCl:public GSeg { //experiment cluster of ref loci (isoforms)\n public:\n   uint fstart; //lowest coordinate of the first exon\n   uint fend; //highest coordinate of the first exon\n   GList<GXConsensus> tsscl;\n   GTssCl(GXConsensus* c=NULL):tsscl(true,false,false) {\n     start=0;\n     end=0;\n     fstart=0;\n     fend=0;\n     if (c!=NULL) addFirst(c);\n     }\n\n   void addFirst(GXConsensus* c) {\n     tsscl.Add(c);\n     start=c->start;\n     end=c->end;\n     GffExon* fexon=(c->tcons->strand=='-') ? c->tcons->exons.Last() :\n                                             c->tcons->exons.First();\n     fstart=fexon->start;\n     fend=fexon->end;\n     }\n   bool add_Xcons(GXConsensus* c) {\n     if (tsscl.Count()==0) {\n            addFirst(c);\n            return true;\n            }\n     //check if it can be added to existing xconsensi\n     uint nfend=0;\n     uint nfstart=0;\n     /*\n     if (tsscl.Get(0)->tcons->getGeneID()!=NULL && \n             c->tcons->getGeneID()!=NULL && \n            strcmp(tsscl.Get(0)->tcons->getGeneID(), c->tcons->getGeneID()))\n        //don't tss cluster if they don't have the same GeneID (?)\n        //FIXME: we might not want this if input files are not from Cufflinks\n        //       and they could simply lack proper GeneID\n          return false;\n      */\n     if (c->tcons->strand=='-') {\n        //no, the first exons don't have to overlap\n        //if (!c->tcons->exons.Last()->overlap(fstart,fend)) return false;\n        nfstart=c->tcons->exons.Last()->start;\n        nfend=c->tcons->exons.Last()->end;\n        //proximity check for the transcript start:\n        if (nfend>fend+tssDist || fend>nfend+tssDist)\n                return false;\n        }\n      else {\n        //if (!c->tcons->exons.First()->overlap(fstart,fend)) return false;\n        nfstart=c->tcons->exons.First()->start;\n        nfend=c->tcons->exons.First()->end;\n        if (nfstart>fstart+tssDist || fstart>nfstart+tssDist)\n            return false;\n        }\n     // -- if we are here, we can add to tss cluster\n\n     tsscl.Add(c);\n     if (fstart>nfstart) fstart=nfstart;\n     if (fend<nfend) fend=nfend;\n     if (start>c->start) start=c->start;\n     if (end<c->end) end=c->end;\n     return true;\n     }\n\n   void addMerge(GTssCl& cl, GXConsensus* clnk) {\n     for (int i=0;i<cl.tsscl.Count();i++) {\n         if (cl.tsscl[i]==clnk) continue;\n         tsscl.Add(cl.tsscl[i]);\n         }\n     if (fstart>cl.fstart) fstart=cl.fstart;\n     if (fend<cl.fend) fend=cl.fend;\n     if (start>cl.start) start=cl.start;\n     if (end<cl.end) end=cl.end;\n     }\n};\n/*\nclass IntArray { //two dimensional int array\n    int* mem;\n    int xsize;\n    int ysize;\n  public:\n   IntArray(int xlen, int ylen) {\n     xsize=xlen;\n     ysize=ylen;\n     GMALLOC(mem, xsize*ysize*sizeof(int));\n     }\n   ~IntArray() {\n     GFREE(mem);\n     }\n   int& data(int x, int y) {\n    return mem[y*xsize+x];\n    }\n};\n\nint aa_diff(GXConsensus* c1, GXConsensus* c2) {\n int diflen=abs(c1->aalen-c2->aalen);\n if (diflen>=6) return diflen;\n //obvious case: same CDS\n if (diflen==0 && strcmp(c1->aa, c2->aa)==0) return 0;\n //simple edit distance calculation\n IntArray dist(c1->aalen+1, c2->aalen+1);\n for (int i=0;i<=c1->aalen;i++) {\n     dist.data(i,0) = i;\n     }\n for (int j = 0; j <= c2->aalen; j++) {\n     dist.data(0,j) = j;\n     }\n for (int i = 1; i <= c1->aalen; i++)\n     for (int j = 1; j <= c2->aalen; j++) {\n         dist.data(i,j) = GMIN3( dist.data(i-1,j)+1,\n             dist.data(i,j-1)+1,\n                 dist.data(i-1,j-1)+((c1->aa[i-1] == c2->aa[j-1]) ? 0 : 1) );\n         }\n int r=dist.data(c1->aalen,c2->aalen);\n return r;\n}\n*/\nvoid printConsGTF(FILE* fc, GXConsensus* xc, int xlocnum) {\n for (int i=0;i<xc->tcons->exons.Count();i++) {\n   fprintf(fc,\n     \"%s\\t%s\\texon\\t%d\\t%d\\t.\\t%c\\t.\\tgene_id \\\"XLOC_%06d\\\"; transcript_id \\\"%s_%08d\\\"; exon_number \\\"%d\\\";\",\n     xc->tcons->getGSeqName(),xc->tcons->getTrackName(),xc->tcons->exons[i]->start, xc->tcons->exons[i]->end, xc->tcons->strand,\n       xlocnum, cprefix, xc->id, i+1);\n    //if (i==0) {\n  const char* gene_name=NULL;\n  if (xc->ref) {\n     gene_name=xc->ref->getGeneName();\n     if (gene_name==NULL) gene_name=xc->ref->getGeneID();\n     if (gene_name) {\n       fprintf (fc, \" gene_name \\\"%s\\\";\", gene_name);\n       }\n   }\n   if (!haveRefs) {\n      if (gene_name==NULL && xc->tcons->getGeneName())\n        fprintf (fc, \" gene_name \\\"%s\\\";\", xc->tcons->getGeneName());\n      char* s=xc->tcons->getAttr(\"nearest_ref\", true);\n      if (s) fprintf(fc, \" nearest_ref \\\"%s\\\";\",s);\n      s=xc->tcons->getAttr(\"class_code\", true);\n      if (s) fprintf(fc, \" class_code \\\"%s\\\";\", s);\n      }\n   fprintf(fc, \" oId \\\"%s\\\";\",xc->tcons->getID());\n   if (xc->contained) {\n     fprintf(fc, \" contained_in \\\"%s_%08d\\\";\", cprefix, xc->contained->id);\n     }\n   if (haveRefs) {\n     if (xc->ref!=NULL)\n       fprintf(fc, \" nearest_ref \\\"%s\\\";\",xc->ref->getID());\n     fprintf(fc, \" class_code \\\"%c\\\";\",xc->refcode ? xc->refcode : '.');\n     }\n   if (xc->tss_id>0) fprintf(fc, \" tss_id \\\"TSS%d\\\";\",xc->tss_id);\n   if (xc->p_id>0) fprintf(fc, \" p_id \\\"P%d\\\";\",xc->p_id);\n   //      }\n   fprintf(fc,\"\\n\");\n   }\n}\n\nvoid tssCluster(GXLocus& xloc) \n{\n    GList<GTssCl> xpcls(true,true,false);\n    for (int i=0;i<xloc.tcons.Count();i++) \n    {\n        GXConsensus* c=xloc.tcons[i];\n        //if (c->tcons->exons.Count()<2) continue;  //should we skip single-exon transcripts ??\n        GArray<int> mrgloci(true);\n        int lfound=0;\n        for (int l=0;l<xpcls.Count();l++) \n        {\n            if (xpcls[l]->end<c->tcons->exons.First()->start) continue;\n            if (xpcls[l]->start>c->tcons->exons.Last()->end) break;\n            if (xpcls[l]->add_Xcons(c)) \n            {\n                lfound++;\n                mrgloci.Add(l);\n                \n            }\n            \n        } // for each xpcluster\n        if (lfound==0) \n        {\n            //create a xpcl with only this xconsensus\n            xpcls.Add(new GTssCl(c));\n            \n        }\n        else if (lfound>1) \n        {\n            for (int l=1;l<lfound;l++) \n            {\n                int mlidx=mrgloci[l]-l+1;\n                xpcls[mrgloci[0]]->addMerge(*xpcls[mlidx], c);\n                xpcls.Delete(mlidx);\n            }\n        }\n        \n    }//for each xconsensus in this xlocus\n    for (int l=0;l<xpcls.Count();l++) \n    {\n        //if (xpcls[l]->tsscl.Count()<2) continue;\n        tsscl_num++;\n        for (int i=0;i<xpcls[l]->tsscl.Count();i++)\n            xpcls[l]->tsscl[i]->tss_id=tsscl_num;\n        //processTssCl(xcds_num, xpcls[l], faseq);\n    }\n}\n\nvoid protCluster(GXLocus& xloc, GFaSeqGet *faseq) {\n  if (!faseq)\n    return;\n  GList<GProtCl> xpcls(true,true,false);\n  for (int i=0;i<xloc.tcons.Count();i++) {\n    GXConsensus* c=xloc.tcons[i];\n    if (c->ref==NULL || c->ref->CDstart==0) continue;  //no ref or CDS available\n    if (c->refcode!='=') continue;\n    //get the CDS translation here\n    if (c->aa==NULL) {\n       c->aa=c->ref->getSplicedTr(faseq, true, &c->aalen);\n       if (c->aalen>0 && c->aa[c->aalen-1]=='.') {\n             //discard the final stop codon\n             c->aalen--;\n             c->aa[c->aalen]=0;\n             }\n       }\n    GArray<int> mrgloci(true);\n    int lfound=0;\n    for (int l=0;l<xpcls.Count();l++) {\n        if (xpcls[l]->aalen()!=c->aalen) continue;\n        if (xpcls[l]->add_Pcons(c)) {\n            lfound++;\n            mrgloci.Add(l);\n            }\n        } // for each xpcluster\n    if (lfound==0) {\n        //create a xpcl with only this xconsensus\n        xpcls.Add(new GProtCl(c));\n        }\n      else if (lfound>1) {\n        for (int l=1;l<lfound;l++) {\n              int mlidx=mrgloci[l]-l+1;\n              xpcls[mrgloci[0]]->addMerge(*xpcls[mlidx], c);\n              xpcls.Delete(mlidx);\n              }\n        }\n    }//for each xconsensus in this xlocus\n for (int l=0;l<xpcls.Count();l++) {\n      protcl_num++;\n      for (int i=0;i<xpcls[l]->protcl.Count();i++)\n           xpcls[l]->protcl[i]->p_id=protcl_num;\n      }\n for (int i=0;i<xloc.tcons.Count();i++) {\n   GXConsensus* c=xloc.tcons[i];\n   if (c->aa!=NULL) { GFREE(c->aa); }\n   }\n}\n\nvoid printXLoci(FILE* f, FILE* fc, int qcount, GList<GXLocus>& xloci, GFaSeqGet *faseq) {\n  for (int l=0;l<xloci.Count();l++) {\n    if (xloci[l]->qloci.Count()==0) continue;\n    GXLocus& xloc=*(xloci[l]);\n    xloc.checkContainment(); \n    tssCluster(xloc);//cluster and assign tss_id and cds_id to each xconsensus in xloc\n    protCluster(xloc,faseq);\n    for (int c=0;c<xloc.tcons.Count();c++) {\n       if (showContained || xloc.tcons[c]->contained==NULL)\n         printConsGTF(fc,xloc.tcons[c],xloc.id);\n       }\n    fprintf(f,\"XLOC_%06d\\t%s[%c]%d-%d\\t\", xloc.id,\n        xloc.qloci[0]->mrna_maxcov->getGSeqName(),\n            xloc.strand, xloc.start,xloc.end);\n    //now print all transcripts in this locus, comma delimited\n    //first, ref loci, if any\n    int printfd=0;\n    if (xloc.rloci.Count()>0) {\n       for (int i=0;i<xloc.rloci.Count();i++) {\n          for (int j=0;j<xloc.rloci[i]->mrnas.Count();j++) {\n            if (printfd==0) fprintf(f,\"%s|%s\",getGeneID(xloc.rloci[i]->mrnas[j]),\n                                                    xloc.rloci[i]->mrnas[j]->getID());\n                else fprintf(f,\",%s|%s\",getGeneID(xloc.rloci[i]->mrnas[j]),\n                                                    xloc.rloci[i]->mrnas[j]->getID());\n            printfd++;\n            }\n          }\n       }\n    else {\n      fprintf(f,\"-\");\n      }\n   //second, all the cufflinks transcripts\n    for (int qi=0;qi<qcount;qi++) {\n       fprintf(f,\"\\t\");\n       printXQ1(f,qi,xloc.qloci);\n       }\n    fprintf(f,\"\\n\");\n    }\n}\n\nvoid writeIntron(FILE* f, char strand, GFaSeqGet* faseq, GSeg& iseg,\n                GList<GffObj>& mrnas, bool wrong=false) {\n//find a ref mrna having this intron\n  GffObj* rm=NULL;\n  for (int i=0;i<mrnas.Count();i++) {\n   GffObj* m=mrnas[i];\n   if (m->start>iseg.end) break;\n   if (m->end<iseg.start) continue;\n   //intron coords overlaps mrna region\n   for (int j=1;j<m->exons.Count();j++) {\n      if (iseg.start==m->exons[j-1]->end+1 &&\n            iseg.end==m->exons[j]->start-1) { rm=m; break; } //match found\n      }//for each intron\n   if (rm!=NULL) break;\n   } //for each ref mrna in this locus\n if (rm==NULL) GError(\"Error: couldn't find ref mrna for intron %d-%d! (BUG)\\n\",\n                         iseg.start,iseg.end);\n int ilen=iseg.end-iseg.start+1;\n fprintf(f,\"%s\\t%s\\tintron\\t%d\\t%d\\t.\\t%c\\t.\\t\",\n            rm->getGSeqName(),rm->getTrackName(),iseg.start,iseg.end,strand);\n if (faseq!=NULL) {\n   const char* gseq=faseq->subseq(iseg.start, ilen);\n   char* cseq=Gstrdup(gseq, gseq+ilen-1);\n   if (strand=='-') reverseComplement(cseq, ilen);\n   fprintf(f,\"spl=\\\"%c%c..%c%c\\\"; \", toupper(cseq[0]),toupper(cseq[1]),\n           toupper(cseq[ilen-2]),toupper(cseq[ilen-1]));\n   GFREE(cseq);\n   }\n  fprintf(f,\"transcript_id \\\"%s\\\";\", rm->getID());\n  if (wrong) fprintf(f,\" noOvl=1;\");\n  fprintf(f,\"\\n\");\n\n}\n\nvoid reportMIntrons(FILE* fm, FILE* fn, FILE* fq, char strand,\n            GList<GSuperLocus>& cmpdata) {\n  if (fm==NULL) return;\n  for (int l=0;l<cmpdata.Count();l++) {\n    GSuperLocus *sl=cmpdata[l];\n    //cache the whole locus sequence if possible\n    //write these introns and their splice sites into the file\n    for (int i=0;i<sl->i_missed.Count();i++)\n      writeIntron(fm, strand, NULL, sl->i_missed[i], sl->rmrnas);\n    if (fn!=NULL) {\n        for (int i=0;i<sl->i_notp.Count();i++)\n          writeIntron(fn, strand, NULL, sl->i_notp[i], sl->rmrnas);\n        }\n    if (fq!=NULL) {\n     for (int i=0;i<sl->i_qwrong.Count();i++) {\n       writeIntron(fq, strand, NULL, sl->i_qwrong[i], sl->qmrnas, true);\n       }\n     for (int i=0;i<sl->i_qnotp.Count();i++) {\n       writeIntron(fq, strand, NULL, sl->i_qnotp[i], sl->qmrnas);\n       }\n     }\n    }\n}\n\n\nvoid processLoci(GSeqData& seqdata, GSeqData* refdata, int qfidx) {\n    //GList<GSeqLoci>& glstloci, GList<GSeqCmpRegs>& cmpdata)\n\n  if (refdata!=NULL) {\n     //if (gtf_tracking_verbose) GMessage(\" ..comparing to reference loci..\\n\") ;\n     compareLoci2R(seqdata.loci_f, seqdata.gstats_f, refdata->loci_f, qfidx);\n     compareLoci2R(seqdata.loci_r, seqdata.gstats_r, refdata->loci_r, qfidx);\n     // -- report\n\n     if (f_mintr!=NULL) {\n       //GMessage(\" ..reporting missed ref introns..\\n\");\n       //reportIntrons(f_mintr, f_nintr, f_qintr, faseq, '+', seqdata.gstats_f);\n       //reportIntrons(f_mintr, f_nintr, f_qintr, faseq, '-', seqdata.gstats_r);\n       reportMIntrons(f_mintr, NULL, NULL, '+', seqdata.gstats_f);\n       reportMIntrons(f_mintr, NULL, NULL, '-', seqdata.gstats_r);\n       }\n     }\n}\n\n//adjust stats for a list of unoverlapped (completely missed) ref loci\nvoid collectRLocData(GSuperLocus& stats, GLocus& loc) {\n\tstats.total_rmrnas+=loc.mrnas.Count();\n\tstats.total_rexons+=loc.uexons.Count();\n\tstats.total_rintrons+=loc.introns.Count();\n\tstats.total_rmexons+=loc.mexons.Count();\n\tstats.total_richains+=loc.ichains;\n\tstats.m_exons+=loc.uexons.Count();\n\tstats.m_introns+=loc.introns.Count();\n\tstats.total_rloci++;\n\tstats.m_loci++; //missed ref loci\n\tfor (int e=0;e<loc.mexons.Count();e++) {\n\t\t stats.rbases_all+=loc.mexons[e].end-loc.mexons[e].start+1;\n\t}\n}\n\nvoid collectRData(GSuperLocus& stats, GList<GLocus>& loci) {\n for (int l=0;l<loci.Count();l++)\n      collectRLocData(stats,*loci[l]);\n}\n\n//adjust stats for a list of unoverlapped (completely \"wrong\" or novel) qry loci\nvoid collectQLocData(GSuperLocus& stats, GLocus& loc) {\n stats.total_qmrnas+=loc.mrnas.Count();\n stats.total_qexons+=loc.uexons.Count();\n stats.total_qmexons+=loc.mexons.Count();\n stats.total_qintrons+=loc.introns.Count();\n stats.total_qichains+=loc.ichains;\n stats.total_qloci++;\n stats.w_loci++; //add to the count of novel/wrong loci\n if (loc.ichains>0 && loc.mrnas.Count()>1)\n    stats.total_qloci_alt++;\n stats.w_exons+=loc.uexons.Count();\n stats.w_introns+=loc.introns.Count();\n for (int e=0;e<loc.mexons.Count();e++) {\n   stats.qbases_all+=loc.mexons[e].end-loc.mexons[e].start+1;\n   }\n}\n\nvoid collectQData(GSuperLocus& stats, GList<GLocus>& loci) {\n for (int l=0;l<loci.Count();l++) {\n     //this is called when no refdata is given, so all these loci are nloci\n     //nloci.Add(loci[l]);\n     collectQLocData(stats,*loci[l]);\n     }\n}\n\nvoid collectQNOvl(GSuperLocus& stats, GList<GLocus>& loci, GList<GLocus>& nloci) {\n  for (int l=0;l<loci.Count();l++) {\n    if (loci[l]->cmpovl.Count()==0) {//locus with no ref loci overlaps\n      nloci.Add(loci[l]);\n      if (!reduceQrys) collectQLocData(stats,*loci[l]);\n      }\n  }\n}\n\nvoid collectQU(GSuperLocus& stats, GList<GLocus>& nloci) {\n  for (int l=0;l<nloci.Count();l++) {\n    //stats.w_loci++; //novel/wrong loci\n    collectQLocData(stats, *nloci[l]);\n    }\n}\n\nvoid printLocus(FILE* f, GLocus& loc, const char* gseqname) {\n  fprintf(f, \"## Locus %s:%d-%d\\n\",gseqname, loc.start, loc.end);\n  for (int m=0;m<loc.mrnas.Count();m++) {\n    loc.mrnas[m]->printGtf(f);\n    }\n}\n\nvoid collectRNOvl(GSuperLocus& stats, GList<GLocus>& loci) { //, const char* gseqname) {\n  for (int l=0;l<loci.Count();l++) {\n    if (loci[l]->cmpovl.Count()==0) {\n      //if (f_mloci!=NULL)\n      //      printLocus(f_mloci,*loci[l], gseqname);\n      collectRLocData(stats,*loci[l]);\n      }\n  }\n}\n\n\nvoid collectCmpData(GSuperLocus& stats, GList<GSuperLocus>& cmpdata) { //, const char* gseqname) {\n for (int c=0;c<cmpdata.Count();c++) {\n   stats.addStats(*cmpdata[c]);\n   /*\n   if (f_nloci!=NULL && cmpdata[c]->locusTP==0 && cmpdata[c]->rloci.Count()>0) {       \n      fprintf(f_nloci, \"# Superlocus %s:%d-%d\\n\",gseqname, cmpdata[c]->start, cmpdata[c]->end);\n      for (int l=0;l<cmpdata[c]->rloci.Count();l++) {\n         printLocus(f_nloci,*cmpdata[c]->rloci[l], gseqname);\n         }\n      }\n   */   \n   }\n}\n\nvoid printLociQ(FILE* f, GList<GLocus>& loci, char c=' ') {\n  for (int i=0;i<loci.Count();i++) {\n     GLocus& loc=*(loci[i]);\n     for (int j=0;j<loc.mrnas.Count();j++) {\n        fprintf(f, \"%s\\t%c\\t%c\\t%s\\n\", loc.mrnas[j]->getID(), loc.mrnas[j]->strand, c, loc.mrnas[j]->getGSeqName());\n     }\n  }\n}\n\nvoid printLocQ(FILE *f, GLocus& loc) {\n    for (int j=0;j<loc.mrnas.Count();j++) {\n       fprintf(f, \"%s\\n\", loc.mrnas[j]->getID());\n    }\n}\n\n\nvoid collectStats(GSuperLocus& stats, GSeqData* seqdata, GSeqData* refdata) {\n //collect all stats for a single genomic sequence into stats\n if (seqdata==NULL) {\n   if (reduceRefs || refdata==NULL) return;\n   //special case with completely missed all refs on a contig/chromosome\n   collectRData(stats, refdata->loci_f);\n   collectRData(stats, refdata->loci_r);\n   return;\n   }\n\n if (refdata==NULL) {//reference data missing on this contig\n\t for (int l=0;l<seqdata->loci_f.Count();l++) {\n\t     seqdata->nloci_f.Add(seqdata->loci_f[l]);\n\t }\n\t for (int l=0;l<seqdata->loci_r.Count();l++) {\n\t     seqdata->nloci_r.Add(seqdata->loci_r[l]);\n\t }\n   if (reduceQrys) return;\n\n   collectQData(stats, seqdata->loci_f);\n   collectQData(stats, seqdata->loci_r);\n   collectQU(stats, seqdata->nloci_u);\n   return;\n   }\n //collect data for overlapping superloci (already in seqdata->gstats_f/_r)\n collectCmpData(stats, seqdata->gstats_f);\n collectCmpData(stats, seqdata->gstats_r);\n //for non-overlapping qry loci, add them as false positives FP\n\n collectQNOvl(stats, seqdata->loci_f , seqdata->nloci_f);\n collectQNOvl(stats, seqdata->loci_r , seqdata->nloci_r);\n if (!reduceQrys) {\n   collectQU(stats, seqdata->nloci_u);\n }\n if (!reduceRefs) { //find ref loci with empty cmpovl and add them\n  collectRNOvl(stats, refdata->loci_f);\n  collectRNOvl(stats, refdata->loci_r);\n  }\n}\n\nvoid reportStats(FILE* fout, const char* setname, GSuperLocus& stotal,\n                          GSeqData* seqdata, GSeqData* refdata) {\n  GSuperLocus stats;\n  bool finalSummary=(seqdata==NULL && refdata==NULL);\n  GSuperLocus *ps=(finalSummary ? &stotal : &stats );\n  if (!finalSummary) { //collecting contig stats\n    //gather statistics for all loci/superloci here\n    collectStats(stats, seqdata, refdata);\n    if (f_qdisc!=NULL) {\n    \tprintLociQ(f_qdisc, seqdata->nloci_f, 'F');\n    \tprintLociQ(f_qdisc, seqdata->nloci_r, 'R');\n    \tprintLociQ(f_qdisc, seqdata->nloci_u, 'U');\n    }\n    stotal.addStats(stats);\n    if (!perContigStats) return;\n    }\n  ps->calcF();\n  if (seqdata!=NULL) fprintf(fout, \"#> Genomic sequence: %s \\n\", setname);\n                else fprintf(fout, \"\\n#= Summary for dataset: %s \\n\", setname);\n\n  fprintf(fout,   \"#     Query mRNAs : %7d in %7d loci  (%d multi-exon transcripts)\\n\",\n          ps->total_qmrnas, ps->total_qloci, ps->total_qichains);\n  fprintf(fout, \"#            (%d multi-transcript loci, ~%.1f transcripts per locus)\\n\",\n          ps->total_qloci_alt, ((double)ps->total_qmrnas/ps->total_qloci));\n\n  if (haveRefs) {\n    fprintf(fout, \"# Reference mRNAs : %7d in %7d loci  (%d multi-exon)\\n\",\n            ps->total_rmrnas, ps->total_rloci, ps->total_richains);\n    if (ps->baseTP+ps->baseFP==0 || ps->baseTP+ps->baseFN==0) return;\n    fprintf(fout, \"# Super-loci w/ reference transcripts:  %7d\\n\",ps->total_superloci);\n\n    /*if (seqdata!=NULL) {\n      fprintf(fout, \"          ( %d/%d on forward/reverse strand)\\n\",\n             seqdata->gstats_f.Count(),seqdata->gstats_r.Count());\n       }*/\n    fprintf(fout, \"#-----------------| Sensitivity | Precision  |\\n\");\n    double sp=(100.0*(double)ps->baseTP)/(ps->baseTP+ps->baseFP);\n    double sn=(100.0*(double)ps->baseTP)/(ps->baseTP+ps->baseFN);\n    fprintf(fout, \"        Base level:   %5.1f     |   %5.1f    |\\n\",sn, sp);\n    //sp=(100.0*(double)ps->exonQTP)/(ps->exonTP+ps->exonFP);\n    sp=(100.0*(double)ps->exonQTP)/ps->total_qexons;\n    //sn=(100.0*(double)ps->exonTP)/(ps->exonTP+ps->exonFN);\n    sn=(100.0*(double)ps->exonTP)/ps->total_rexons;\n    /*double fsp=(100.0*(double)ps->exonATP)/(ps->exonATP+ps->exonAFP);\n    double fsn=(100.0*(double)ps->exonATP)/(ps->exonATP+ps->exonAFN);\n    if (fsp>100.0) fsp=100.0;\n    if (fsn>100.0) fsn=100.0;\n    */\n    //DEBUG only:\n    //fprintf(fout, \"======> Exon stats: %d total_qexons, %d total_rexons, %d exonTP, %d exonFP, %d exonFN\\n\",\n    //   ps->total_rexons, ps->total_qexons, ps->exonTP, ps->exonFP, ps->exonFN);\n    fprintf(fout, \"        Exon level:   %5.1f     |   %5.1f    |\\n\",sn, sp);\n  if (ps->total_rintrons>0) {\n    //intron level\n    sp=(100.0*(double)ps->intronTP)/(ps->intronTP+ps->intronFP);\n    sn=(100.0*(double)ps->intronTP)/(ps->intronTP+ps->intronFN);\n    /*fsp=(100.0*(double)ps->intronATP)/(ps->intronATP+ps->intronAFP);\n    fsn=(100.0*(double)ps->intronATP)/(ps->intronATP+ps->intronAFN);\n    if (fsp>100.0) fsp=100.0;\n    if (fsn>100.0) fsn=100.0;*/\n    fprintf(fout, \"      Intron level:   %5.1f     |   %5.1f    |\\n\",sn, sp);\n    //intron chains:\n    //sp=(100.0*(double)ps->ichainTP)/(ps->ichainTP+ps->ichainFP);\n    //sn=(100.0*(double)ps->ichainTP)/(ps->ichainTP+ps->ichainFN);\n    sp=(100.0*(double)ps->ichainTP)/ps->total_qichains;\n    sn=(100.0*(double)ps->ichainTP)/ps->total_richains;\n    //if (sp>100.0) sp=100.0;\n    //if (sn>100.0) sn=100.0;\n    /*fsp=(100.0*(double)ps->ichainATP)/ps->total_qichains;\n    fsn=(100.0*(double)ps->ichainATP)/ps->total_richains;\n    if (fsp>100.0) fsp=100.0;\n    if (fsn>100.0) fsn=100.0;\n    */\n    fprintf(fout, \"Intron chain level:   %5.1f     |   %5.1f    |\\n\",sn, sp);\n    }\n  /*else {\n    fprintf(fout, \"      Intron level: \\t  -  \\t  -  \\t  -  \\t  -  \\n\");\n    fprintf(fout, \"Intron chain level: \\t  -  \\t  -  \\t  -  \\t  -  \\n\");\n    }*/\n    /*\n    sp=(100.0*(double)ps->mrnaTP)/(ps->mrnaTP+ps->mrnaFP);\n    sn=(100.0*(double)ps->mrnaTP)/(ps->mrnaTP+ps->mrnaFN);\n    fsp=(100.0*(double)ps->mrnaATP)/(ps->mrnaATP+ps->mrnaAFP);\n    fsn=(100.0*(double)ps->mrnaATP)/(ps->mrnaATP+ps->mrnaAFN);\n    */\n    sp=(100.0*(double)ps->mrnaTP)/ps->total_qmrnas;\n    sn=(100.0*(double)ps->mrnaTP)/ps->total_rmrnas;\n    /*fsp=(100.0*(double)ps->mrnaATP)/ps->total_qmrnas;\n    fsn=(100.0*(double)ps->mrnaATP)/ps->total_rmrnas;\n    if (fsp>100.0) fsp=100.0;\n    if (fsn>100.0) fsn=100.0;\n    */\n    fprintf(fout, \"  Transcript level:   %5.1f     |   %5.1f    |\\n\",sn, sp);\n    //sp=(100.0*(double)ps->locusTP)/(ps->locusTP+ps->locusFP);\n    sp=(100.0*(double)ps->locusQTP)/ps->total_qloci;\n    sn=(100.0*(double)ps->locusTP)/ps->total_rloci;  //(ps->locusTP+ps->locusFN);\n    /*fsp=(100.0*(double)ps->locusAQTP)/ps->total_qloci; //(ps->locusATP+ps->locusAFP);\n    fsn=(100.0*(double)ps->locusATP)/ps->total_rloci; //(ps->locusATP+ps->locusAFN);\n    */\n    fprintf(fout, \"       Locus level:   %5.1f     |   %5.1f    |\\n\",sn, sp);\n    //fprintf(fout, \"                   (locus TP=%d, total ref loci=%d)\\n\",ps->locusTP, ps->total_rloci);\n    fprintf(fout,\"\\n     Matching intron chains: %7d\\n\",ps->ichainTP);\n    fprintf(fout,  \"       Matching transcripts: %7d\\n\",ps->mrnaTP);\n    fprintf(fout,  \"              Matching loci: %7d\\n\",ps->locusTP);\n    fprintf(fout, \"\\n\");\n    sn=(100.0*(double)ps->m_exons)/(ps->total_rexons);\n    fprintf(fout, \"          Missed exons: %7d/%d\\t(%5.1f%%)\\n\",ps->m_exons, ps->total_rexons, sn);\n    sn=(100.0*(double)ps->w_exons)/(ps->total_qexons);\n    fprintf(fout, \"           Novel exons: %7d/%d\\t(%5.1f%%)\\n\",ps->w_exons, ps->total_qexons,sn);\n    if (ps->total_rintrons>0) {\n    sn=(100.0*(double)ps->m_introns)/(ps->total_rintrons);\n    fprintf(fout, \"        Missed introns: %7d/%d\\t(%5.1f%%)\\n\",ps->m_introns, ps->total_rintrons, sn);\n    }\n    if (ps->total_qintrons>0) {\n    sn=(100.0*(double)ps->w_introns)/(ps->total_qintrons);\n    fprintf(fout, \"         Novel introns: %7d/%d\\t(%5.1f%%)\\n\",ps->w_introns, ps->total_qintrons,sn);\n    }\n    if (ps->total_rloci>0) {\n    sn=(100.0*(double)ps->m_loci)/(ps->total_rloci);\n    fprintf(fout, \"           Missed loci: %7d/%d\\t(%5.1f%%)\\n\",ps->m_loci, ps->total_rloci, sn);\n    }\n    if (ps->total_qloci>0) {\n    sn=(100.0*(double)ps->w_loci)/(ps->total_qloci);\n    fprintf(fout, \"            Novel loci: %7d/%d\\t(%5.1f%%)\\n\",ps->w_loci, ps->total_qloci,sn);\n    }\n\n  }\n}\n\nint inbuf_len=1024; //starting inbuf capacity\nchar* inbuf=NULL; // incoming buffer for sequence lines.\n\nvoid loadRefDescr(const char* fname) {\n  if (inbuf==NULL)  { GMALLOC(inbuf, inbuf_len); }\n  FILE *f=fopen(fname, \"rb\");\n  if (f==NULL) GError(\"Error opening exon file: %s\\n\",fname);\n  char* line;\n  int llen=0;\n  off_t fpos;\n  while ((line=fgetline(inbuf, inbuf_len, f, &fpos, &llen))!=NULL) {\n   if (strlen(line)<=2) continue;\n   int idlen=strcspn(line,\"\\t \");\n   char* p=line+idlen;\n   if (idlen<llen && idlen>0) {\n     *p=0;\n      p++;\n      refdescr.Add(line, new GStr(p));\n      }\n  }\n}\n\nGSeqTrack* findGSeqTrack(int gsid) {\n  GSeqTrack f(gsid);\n  int fidx=-1;\n  if (gseqtracks.Found(&f,fidx))\n     return gseqtracks[fidx];\n  fidx=gseqtracks.Add(new GSeqTrack(gsid));\n  return gseqtracks[fidx];\n}\n\nGffObj* findRefMatch(GffObj& m, GLocus& rloc, int& ovlen) {\n ovlen=0;\n CTData* mdata=((CTData*)m.uptr);\n if (mdata->eqref!=NULL && ((CTData*)(mdata->eqref->uptr))->locus==&rloc) {\n\t  mdata->eqref=mdata->ovls.First()->mrna; //this should be unnecessary\n      //check it?\n      return mdata->ovls.First()->mrna;\n      }\n //if (rloc==NULL|| m==NULL) return NULL;\n GffObj* ret=NULL;\n for (int r=0;r<rloc.mrnas.Count();r++) {\n    int olen=0;\n\tif (tMatch(m, *(rloc.mrnas[r]),olen, true)) { //return rloc->mrnas[r];\n\t  /*\n\t  if (ovlen<olen) {\n\t\t  ovlen=olen;\n\t\t  ret=rloc.mrnas[r]; //keep the longest matching ref\n\t\t\t //but this is unnecessary, there can be only one matching ref\n\t\t\t // because duplicate refs were discarded\n\t\t  }\n\t  */\n\t  mdata->addOvl('=',rloc.mrnas[r], olen);\n\t  ret=mdata->ovls.First()->mrna;\n      //this must be called only for the head of an equivalency chain\n      CTData* rdata=(CTData*)rloc.mrnas[r]->uptr;\n      rdata->addOvl('=',&m,olen);\n      //if (rdata->eqnext==NULL) rdata->eqnext=&m;\n      }\n    }\n if (ret!=NULL)\n   mdata->eqref=ret;\n return ret;\n }\n\n\nvoid addXCons(GXLocus* xloc, GffObj* ref, char ovlcode, GffObj* tcons, CEqList* ts) {\n GXConsensus* c=new GXConsensus(tcons, ts, ref, ovlcode);\n //xloc->tcons.Add(c);\n //this will also check c against the other tcons for containment:\n xloc->addXCons(c); \n}\n\n\nconst uint pre_mrna_threshold = 100;\n\nchar getOvlCode(GffObj& m, GffObj& r, int& ovlen) {\n  ovlen=0;\n  if (!m.overlap(r.start,r.end)) return 0;\n  int jmax=r.exons.Count()-1;\n  \n  if (m.exons.Count()==1) { //single-exon transfrag\n     GSeg mseg(m.start, m.end);\n     if (jmax==0) { //also single-exon ref\n         //ovlen=mseg.overlapLen(r.start,r.end);\n         if (singleExonTMatch(m, r, ovlen)) \n                  return '=';\n         if (m.covlen<r.covlen && ovlen >= m.covlen*0.8) return 'c'; //fuzzy containment\n         return 'o'; //just plain overlapping\n         }\n     //single-exon qry overlaping multi-exon ref\n     for (int j=0;j<=jmax;j++) {\n        //check if it's contained by an exon\n        if (m.start>r.exons[j]->start-8 && m.end<r.exons[j]->end+8)\n            return 'c';\n        if (j==jmax) break;\n        //check if it's contained by an intron\n        if (m.end<r.exons[j+1]->start && m.start>r.exons[j]->end)\n           return 'i';\n        // check if it's a potential pre-mRNA transcript\n        // (if overlaps an intron at least 10 bases)\n        uint iovlen=mseg.overlapLen(r.exons[j]->end+1, r.exons[j+1]->start-1);\n        if (iovlen>=10 && mseg.len()>iovlen+10) return 'e';\n        }\n     return 'o'; //plain overlap, uncategorized\n     } //single-exon transfrag\n  //-- from here on we have a multi-exon transfrag --\n  // * check if contained by a ref intron\n  for (int j=0;j<jmax;j++) {\n     if (m.end<r.exons[j+1]->start && m.start>r.exons[j]->end) \n           return 'i';\n     }\n  //> check if m's intron chain is a subset of  r's intron chain\n  int imax=m.exons.Count()-1;// imax>0 here\n  if (m.exons[imax]->start<r.exons[0]->end ||\n      r.exons[jmax]->start<m.exons[0]->end ) //intron chains do not overlap at all\n           return 'o'; //but terminal exons do, otherwise we wouldn't be here\n  int i=1; //index of exon to the right of current qry intron\n  int j=1; //index of exon to the right of current ref intron\n  //find first intron overlap\n  while (i<=imax && j<=jmax) {\n     if (r.exons[j]->start<m.exons[i-1]->end) { j++; continue; }\n     if (m.exons[i]->start<r.exons[j-1]->end) { i++; continue; }\n     break; //here we have an intron overlap\n     }\n  if (i>imax || j>jmax)\n      return 'o'; //no initial intron overlap found\n  //from here on we check all qry introns against ref introns\n  bool jmatch=false; //true if at least a junction match is found\n  bool icmatch=(i==1); //intron chain match - it will be updated as introns are checked\n  //bool exovli=false; // if any terminal exon of qry extends into a ref intron\n  int jmstart=j; //index of first intron overlap of reference\n  int jmend=0;  //index of last intron overlap of reference\n  int imend=0;  //index of last intron overlap of query\n  //check for intron matches\n  while (i<=imax && j<=jmax) {\n    uint mstart=m.exons[i-1]->end;\n    uint mend=m.exons[i]->start;\n    uint rstart=r.exons[j-1]->end;\n    uint rend=r.exons[j]->start;\n    if (rend<mstart) { j++; icmatch=false; continue; } //skipping ref intron, no ichain match\n    if (mend<rstart) { i++; icmatch=false; continue; } //skipping qry intron, no ichain match\n    //overlapping introns here, test junction matching\n    jmend=j; //keep track of last overlapping intron\n    imend=i;\n    bool smatch=(mstart==rstart);\n    bool ematch=(mend==rend);\n    if (smatch || ematch) jmatch=true;\n    if (smatch && ematch) { i++; j++; } //perfect match for this intron\n                     else { //at least one junction doesn't match\n                          icmatch=false;\n                          if (mend>rend) j++; else i++;\n                          }\n    } //while checking intron overlaps\n  \n  if (icmatch && imend==imax) { // qry intron chain match\n     if (jmstart==1 && jmend==jmax) return '='; //identical intron chains\n     // -- qry intron chain is shorter than ref intron chain --\n     int l_iovh=0;   // overhang of leftmost q exon left boundary beyond the end of ref intron to the left\n     int r_iovh=0;   // same type of overhang through the ref intron on the right\n     if (jmstart>1 && r.exons[jmstart-1]->start>m.start) \n        l_iovh = r.exons[jmstart-1]->start - m.start;\n     if (jmend<jmax && m.end > r.exons[jmend]->end)\n        r_iovh = m.end - r.exons[jmend]->end;\n     if (l_iovh<4 && r_iovh<4) return 'c';\n     return 'j';\n     }\n  return jmatch ? 'j':'o';\n}\n\nchar getRefOvl(GffObj& m, GLocus& rloc, GffObj*& rovl, int& ovlen) {\n  rovl=NULL;\n  ovlen=0;\n  if (m.start>rloc.end || m.end<rloc.start) {\n     //see if it's a polymerase run ?\n     /*\n       if ((m.strand=='+' && m.end<=rloc.end+polyrun_range) ||\n         (m.strand=='-' && m.start>=rloc.start-polyrun_range)) {\n            rovl=rloc.mrna_maxcov;\n            ((CTData*)m.uptr)->addOvl('p',rloc.mrna_maxcov);\n            return 'p';\n            }\n     */\n     return 0; //unknown -> intergenic space\n     }\n  for (int i=0;i<rloc.mrnas.Count();i++) {\n     GffObj* r=rloc.mrnas[i];\n     int olen=0;\n     char ovlcode=getOvlCode(m,*r,olen);\n     if (ovlcode!=0) { //has some sort of overlap with r\n       ((CTData*)m.uptr)->addOvl(ovlcode,r,olen);\n       if (olen>ovlen) ovlen=olen;\n       if (ovlcode=='c' || ovlcode=='=') //keep match/containment for each reference transcript\n          ((CTData*)r->uptr)->addOvl(ovlcode,&m,olen);\n       }\n     }//for each ref in rloc\n  // i,j,o\n  return ((CTData*)m.uptr)->getBestCode();\n}\n\nvoid findTMatches(GTrackLocus& loctrack, int qcount) {\n //perform an all vs. all ichain-match for all transcripts across all loctrack[i]->qloci\nfor (int q=0;q<qcount-1;q++) { //for each qry dataset\n  if (loctrack[q]==NULL) continue;\n  for (int qi=0;qi<loctrack[q]->Count();qi++) { // for each transcript in q dataset\n    GffObj* qi_t=loctrack[q]->Get(qi);\n    CTData* qi_d=(CTData*)qi_t->uptr;\n    if (qi_d->eqlist!=NULL && qi_t->exons.Count()>1) {\n         continue; //this is part of an EQ chain already\n         }\n    for (int n=q+1;n<qcount;n++) { // for every successor dataset\n       if (loctrack[n]==NULL) continue;\n       for (int ni=0;ni<loctrack[n]->Count();ni++) {\n          GffObj* ni_t=loctrack[n]->Get(ni);\n          CTData* ni_d=(CTData*)ni_t->uptr;\n          bool singleExon=(ni_t->exons.Count()==1 && qi_t->exons.Count()==1);\n          if (ni_d->eqlist!=NULL && \n                 (ni_d->eqlist==qi_d->eqlist || !singleExon)) continue;\n          int ovlen=0;\n          if ((ni_d->eqlist==qi_d->eqlist && qi_d->eqlist!=NULL) ||\n                  tMatch(*qi_t,*ni_t, ovlen, singleExon)) {\n             qi_d->joinEqList(ni_t);\n             }\n          }\n       } // for each successor dataset\n    } //for each transcript in qry dataset\n  } //for each qry dataset\n}\n\n\nint cmpTData_qset(const pointer* p1, const pointer* p2) {\n CTData* d1=(CTData*)(((GffObj*)p1)->uptr);\n CTData* d2=(CTData*)(((GffObj*)p2)->uptr);\n return (d1->qset - d2->qset);\n }\n\nvoid printITrack(FILE* ft, GList<GffObj>& mrnas, int qcount, int& cnum) {\n  for (int i=0;i<mrnas.Count();i++) {\n   GffObj& qt=*(mrnas[i]);\n   CTData* qtdata=(CTData*)qt.uptr;\n   int qfidx=qtdata->qset;\n   char ovlcode=qtdata->classcode;\n   CEqList* eqchain=qtdata->eqlist;\n   GffObj* ref=NULL; //related ref -- it doesn't have to be fully matching\n   //GffObj* eqref=NULL; //fully ichain-matching ref\n   GffObj* tcons=NULL; //\"consensus\" (largest) transcript for a clique\n   int tmaxcov=0;\n   //eqchain.Add(&qt);\n   //eqref=qtdata->eqref;\n   if (qtdata->ovls.Count()>0 && qtdata->ovls[0]->mrna!=NULL) {\n       //if it has ovlcode with a ref\n       ref=qtdata->ovls[0]->mrna;\n\t   //consistency check: qtdata->ovls[0]->code==ovlcode\n\t   // -- let tcons be a transfrag, not a ref transcript\n\t   //tcons=eqref;\n       //if (tcons!=NULL) tmaxcov=tcons->covlen;\n       }\n   //chain pre-check\n   if (tcons==NULL || mrnas[i]->covlen>tmaxcov) {\n       tcons=mrnas[i];\n       tmaxcov=tcons->covlen;\n       }\n   if (qtdata->eqhead) {//head of a equivalency chain\n      //check if all transcripts in this chain have the same ovlcode\n      for (int k=0;k<qtdata->eqlist->Count();k++) {\n         GffObj* m=qtdata->eqlist->Get(k);\n        if (m->covlen>tmaxcov) {\n            tmaxcov=m->covlen;\n            tcons=m;\n            }\n        char ocode=((CTData*)m->uptr)->getBestCode();\n        if (ocode && ovlcode!='=' && ovlcode!='.' && ocode!=ovlcode) {\n              ovlcode='.'; //non-uniform ovlcode\n              }\n         }\n      }//chain check\n   //if (ovlcode=='p') ref=NULL; //ignore polymerase runs?\n   if (ovlcode==0 || ovlcode=='-' || ovlcode=='.') {\n\t   ovlcode = (ref==NULL) ? 'u' : '.';\n   }\n   //-- print columns 1 and 2 as LOCUS_ID and TCONS_ID\n   //bool chainHead=(qtdata->eqnext!=NULL && ((qtdata->eqdata & EQHEAD_TAG)!=0));\n   bool chainHead=qtdata->eqhead;\n   //bool noChain=((qtdata->eqdata & EQCHAIN_TAGMASK)==0);\n   bool noChain=(eqchain==NULL);\n   if (chainHead || noChain) {\n     cnum++;\n     if (ft!=NULL) fprintf(ft,\"%s_%08d\\t\",cprefix,cnum);\n     GXLocus* xloc=qtdata->locus->xlocus;\n     if (xloc!=NULL) {\n         if (ft!=NULL) fprintf(ft, \"XLOC_%06d\\t\",xloc->id);\n         if (tcons->exons.Count()>1) {\n            //! only multi-exon mRNAs are counted for multi-transcript xloci !\n              xloc->num_mtcons++;\n              if (xloc->num_mtcons==2)\n                 total_xloci_alt++;\n              }\n         }\n      else {\n        //should NEVER happen!\n        int fidx=qtdata->qset;\n        GError(\"Error: no XLocus created for transcript %s (file %s) [%d, %d], on %s%c:%d-%d\\n\", qt.getID(),\n                           qryfiles[qtdata->locus->qfidx]->chars(), qtdata->locus->qfidx, fidx, qt.getGSeqName(), qt.strand, qt.start, qt.end);\n        }\n     addXCons(xloc, ref, ovlcode, tcons, eqchain);\n     } // if chain head or uniq entry (not part of a chain)\n   if (ft==NULL) continue;\n   if (chainHead) {\n      //this is the start of a equivalence class as a printing chain\n      if (ref!=NULL) fprintf(ft,\"%s|%s\\t%c\", getGeneID(ref),ref->getID(), ovlcode);\n                else fprintf(ft,\"-\\t%c\", ovlcode);\n      GffObj* m=mrnas[i];\n      CTData* mdata=(CTData*)m->uptr;\n      \n      int lastpq=-1;\n      /*\n      for (int ptab=mdata->qset-lastpq; ptab>0;ptab--)\n             if (ptab>1) fprintf(ft,\"\\t-\");\n                    else fprintf(ft,\"\\t\");\n      lastpq=mdata->qset;\n      fprintf(ft,\"q%d:%s|%s|%d|%8.6f|%8.6f|%8.6f|%8.6f|%d\", lastpq+1, getGeneID(m), m->getID(),\n          iround(m->gscore/10), mdata->FPKM, mdata->conf_lo, mdata->conf_hi, mdata->cov, m->covlen);\n      //traverse linked list of matching transcripts\n      while (mdata->eqnext!=NULL) {\n         m=mdata->eqnext;\n         mdata=(CTData*)m->uptr;\n         for (int ptab=mdata->qset-lastpq;ptab>0;ptab--)\n             if (ptab>1) fprintf(ft,\"\\t-\");\n                    else fprintf(ft,\"\\t\");\n         lastpq = mdata->qset;\n         fprintf(ft,\"q%d:%s|%s|%d|%8.6f|%8.6f|%8.6f|%8.6f|%d\", lastpq+1, getGeneID(m), m->getID(),\n            iround(m->gscore/10), mdata->FPKM,mdata->conf_lo,mdata->conf_hi,mdata->cov, m->covlen);\n         } //traverse and print row\n      */\n      eqchain->setUnique(false);\n      eqchain->setSorted((GCompareProc*) cmpTData_qset);\n      \n      for (int k=0;k<eqchain->Count();k++) {\n         m=eqchain->Get(k);\n         mdata=(CTData*)m->uptr;\n         if (mdata->qset==lastpq) {\n            //shouldn't happen, unless this input set is messed up (has duplicates/redundant transfrags)\n            fprintf(ft,\",%s|%s|%d|%8.6f|%8.6f|%8.6f|%8.6f|%d\", getGeneID(m), m->getID(),\n               iround(m->gscore/10), mdata->FPKM,mdata->conf_lo,mdata->conf_hi,mdata->cov, m->covlen);\n            continue;\n            }\n         for (int ptab=mdata->qset-lastpq;ptab>0;ptab--)\n             if (ptab>1) fprintf(ft,\"\\t-\");\n                    else fprintf(ft,\"\\t\");\n         lastpq = mdata->qset;\n         fprintf(ft,\"q%d:%s|%s|%d|%8.6f|%8.6f|%8.6f|%8.6f|%d\", lastpq+1, getGeneID(m), m->getID(),\n            iround(m->gscore/10), mdata->FPKM,mdata->conf_lo,mdata->conf_hi,mdata->cov, m->covlen);\n         }\n      for (int ptab=qcount-lastpq-1;ptab>0;ptab--)\n            fprintf(ft,\"\\t-\");\n      fprintf(ft,\"\\n\");\n      continue;\n      } //start of eq class (printing chain)\n\n   if (eqchain!=NULL) continue; //part of a matching chain, dealt with previously\n\n   //--------- not in an ichain-matching class, print as singleton\n\n   if (ref!=NULL) fprintf(ft,\"%s|%s\\t%c\",getGeneID(ref), ref->getID(), ovlcode);\n             else fprintf(ft,\"-\\t%c\",ovlcode);\n   for (int ptab=qfidx;ptab>=0;ptab--)\n      if (ptab>0) fprintf(ft,\"\\t-\");\n             else fprintf(ft,\"\\t\");\n   fprintf(ft,\"q%d:%s|%s|%d|%8.6f|%8.6f|%8.6f|%8.6f|-\",qfidx+1, getGeneID(qt), qt.getID(),iround(qt.gscore/10),\n       qtdata->FPKM, qtdata->conf_lo,qtdata->conf_hi,qtdata->cov);\n   for (int ptab=qcount-qfidx-1;ptab>0;ptab--)\n         fprintf(ft,\"\\t-\");\n   fprintf(ft,\"\\n\");\n   } //for each transcript\n}\n\n\nvoid findTRMatch(GTrackLocus& loctrack, int qcount, GLocus& rloc) {\n //requires loctrack to be already populated with overlapping qloci by findTMatches()\n  // which also found (and tagged) all matching qry transcripts\n for (int q=0;q<qcount;q++) { //for each qry dataset\n  if (loctrack[q]==NULL) continue;\n  for (int qi=0;qi<loctrack[q]->Count();qi++) { // for each transcript in q dataset\n    //if (loctrack[q]->cl[qi]->exons.Count()<2) continue; //skip single-exon transcripts\n    GffObj& qt=*(loctrack[q]->Get(qi));\n    CTData* qtdata=(CTData*)qt.uptr;\n    GffObj* rmatch=NULL; //== ref match for this row\n    int rovlen=0;\n    //if (qtdata->eqnext!=NULL && ((qtdata->eqdata & EQHEAD_TAG)!=0)) { \n    if (qtdata->eqhead) {\n        //EQ chain head -- transfrag equivalency list starts here\n        if (qtdata->eqref==NULL) { //find rloc overlap\n           if (qt.overlap(rloc.start, rloc.end)) {\n                 rmatch=findRefMatch(qt, rloc, rovlen);\n                 }\n           } else rmatch=qtdata->eqref;\n       if (rmatch!=NULL) {\n         /*\n          GffObj* m=loctrack[q]->Get(qi);\n          //traverse linked list of matching transcripts\n          while (((CTData*)m->uptr)->eqnext!=NULL) {\n            m=((CTData*)m->uptr)->eqnext;\n            if (rmatch!=NULL) {\n              ((CTData*)m->uptr)->addOvl('=',rmatch,rovlen);\n              }\n            } //traverse qry data sets\n          continue;\n          }\n         */\n          for (int k=0;k<qtdata->eqlist->Count();k++) {\n            GffObj* m=qtdata->eqlist->Get(k);\n            ((CTData*)m->uptr)->addOvl('=',rmatch,rovlen);\n            continue;\n            }\n         }\n        //if (rmatch!=NULL) continue;\n        } //equivalence class (chain of intron-matching)\n    //if ((qtdata->eqdata & EQCHAIN_TAGMASK)!=0) continue; //part of a matching chain, dealt with previously\n\n    //--------- qry mrna not in a '=' matching clique\n    if (qtdata->eqref==NULL) { //find any rloc overlap\n       if (qt.overlap(rloc.start, rloc.end)) {\n          rmatch=findRefMatch(qt, rloc, rovlen);\n          if (rmatch==NULL) {\n            //not an ichain match, look for other codes\n            GffObj* rovl=NULL;\n            int rovlen=0;\n            //char ovlcode=\n            getRefOvl(qt, rloc,rovl,rovlen);\n            }\n          }\n       }\n     else rmatch=qtdata->eqref;\n    } //for each qry transcript\n  }//for each qry dataset\n}\n\n\nbool inPolyRun(char strand, GffObj& m, GList<GLocus>* rloci, int& rlocidx) {\n //we are only here if there is no actual overlap between m and any locus in rloci\n if (rloci==NULL || rloci->Count()==0) return false; // || m.exons.Count()>1\n  if (strand=='-') {\n        rlocidx=qsearch_loci(m.end, *rloci);\n        //returns index of locus starting just ABOVE m.end\n        // or -1 if last locus start <= m.end\n        GLocus* rloc=NULL;\n        if (rlocidx<0) return false;\n        while (rlocidx<rloci->Count()) {\n           rloc=rloci->Get(rlocidx);\n           if (rloc->start>m.end+polyrun_range) break;\n           if (rloc->start+6>m.end) return true;\n           rlocidx++;\n           }\n        }\n      else { // strand == '+' (or '.' ?)\n        rlocidx=qsearch_loci(m.end, *rloci);\n        GLocus* rloc=NULL;\n        //returns index of closest locus starting ABOVE m.end\n        // or -1 if last locus start <= m.end\n        if (rlocidx<0) rlocidx=rloci->Count(); //this may actually start below m.end\n        while ((--rlocidx)>=0) {\n          rloc=rloci->Get(rlocidx);\n          if (m.start>rloc->start+GFF_MAX_LOCUS) break;\n          if (m.start+6>rloc->end && m.start<rloc->end+polyrun_range) return true;\n          }\n        }\n  return false;\n}\n\nCTData* getBestOvl(GffObj& m) {\n //CTData* mdata=(CTData*)m.uptr;\n //return mdata->getBestCode();\n  if ( ((CTData*)m.uptr)->ovls.Count()>0)\n     return (CTData*)m.uptr;\n  return NULL;\n}\n\nvoid reclass_XStrand(GList<GffObj>& mrnas, GList<GLocus>* rloci) {\n  //checking for relationship with ref transcripts on opposite strand\n  if (rloci==NULL || rloci->Count()<1) return;\n  int j=0;//current rloci index\n  for (int i=0;i<mrnas.Count();i++) {\n     GffObj& m=*mrnas[i];\n     char ovlcode=((CTData*)m.uptr)->getBestCode();\n     if (ovlcode>47 && strchr(\"=cjeo\",ovlcode)!=NULL) continue;\n     GLocus* rloc=rloci->Get(j);\n     if (rloc->start>m.end) continue; //check next transfrag\n     while (m.start>rloc->end && j+1<rloci->Count()) {\n           j++;\n           rloc=rloci->Get(j);\n           }\n     if (rloc->start>m.end) continue; //check next transfrag\n     //m overlaps rloc:\n     //check if m has a fuzzy intron overlap -> 's' (shadow, mapped on the wrong strand)\n     //  then if m is contained within an intron -> 'i'\n     //  otherwise it's just a plain cross-strand overlap: 'x'\n     int jm=0;\n     do { //while rloci overlap this transfrag (m)\n       rloc=rloci->Get(j+jm);\n       bool is_shadow=false;\n       GffObj* sovl=NULL;\n       bool is_intraintron=false;\n       GffObj* iovl=NULL;\n       if (rloc->introns.Count()>0) {\n           for (int n=0;n<rloc->introns.Count();n++) {\n              GISeg& rintron=rloc->introns[n];\n              if (rintron.start>m.end) break;\n              if (m.start>rintron.end) continue;\n              //overlap between m and intron\n              if (m.end<=rintron.end && m.start>=rintron.start) {\n                  is_intraintron=true;\n                  if (iovl==NULL || iovl->covlen<rintron.t->covlen) iovl=rintron.t;\n                  continue;\n                  }\n              //check if any intron of m has a fuzz-match with rintron\n              for (int e=1;e<m.exons.Count();e++) {\n                 GSeg mintron(m.exons[e-1]->end+1,m.exons[e]->start-1);\n                 if (rintron.coordMatch(&mintron,10)) {\n                    is_shadow=true;\n                    if (sovl==NULL || sovl->covlen<rintron.t->covlen) sovl=rintron.t;\n                    break;\n                    }\n                 } //for each m intron\n              } //for each intron of rloc\n           }//rloc has introns\n       bool xcode=true;\n       if (is_shadow) { ((CTData*)m.uptr)->addOvl('s', sovl); xcode=false; }\n             // else\n       if (ovlcode!='i' && is_intraintron) { ((CTData*)m.uptr)->addOvl('i', iovl); xcode=false; }\n       if (xcode) {\n               // just plain overlap, find the overlapping mrna in rloc\n               GffObj* maxovl=NULL;\n               int ovlen=0;\n               GffObj* max_lovl=NULL; //max len ref transcript\n                       // having no exon overlap but simply range overlap (interleaved exons)\n               for (int ri=0;ri<rloc->mrnas.Count();ri++) {\n                  if (!m.overlap(*(rloc->mrnas[ri]))) continue;\n                  int o=m.exonOverlapLen(*(rloc->mrnas[ri]));\n                  if (o>0) {\n                     if (o>ovlen) {\n                        ovlen=o;\n                        maxovl=rloc->mrnas[ri];\n                        }\n                     }\n                    else { //no exon overlap, but still overlapping (interleaved exons)\n                     if (max_lovl==NULL || max_lovl->covlen<rloc->mrnas[ri]->covlen)\n                         max_lovl=rloc->mrnas[ri];\n                     }\n                  }\n               if (maxovl) ((CTData*)m.uptr)->addOvl('x',maxovl);\n                 else if (max_lovl) ((CTData*)m.uptr)->addOvl('x',max_lovl);\n               } //'x'\n       jm++;\n       } while (j+jm<rloci->Count() && rloci->Get(j+jm)->overlap(m));\n     } //for each transfrag\n}\n\nvoid reclass_mRNAs(char strand, GList<GffObj>& mrnas, GList<GLocus>* rloci, GFaSeqGet *faseq) {\n  int rlocidx=-1;\n  for (int i=0;i<mrnas.Count();i++) {\n    GffObj& m=*mrnas[i];\n    char ovlcode=((CTData*)m.uptr)->getBestCode();\n    //if (ovlcode=='u' || ovlcode=='i' || ovlcode==0) {\n    if (ovlcode=='u' || ovlcode<47) {\n      //check for overlaps with ref transcripts on the other strand\n      if (m.exons.Count()==1 && inPolyRun(strand, m, rloci, rlocidx)) {\n         ((CTData*)m.uptr)->addOvl('p',rloci->Get(rlocidx)->mrna_maxcov);\n         }\n      else { //check for repeat content\n         if (faseq!=NULL) {\n            int seqlen;\n            char* seq=m.getSpliced(faseq, false, &seqlen);\n            //get percentage of lowercase\n            int numlc=0;\n            for (int c=0;c<seqlen;c++) if (seq[c]>='a') numlc++;\n            if (numlc > seqlen/2)\n               ((CTData*)m.uptr)->addOvl('r');\n            GFREE(seq);\n            }\n         }\n      } //for unassigned class\n  }//for each mrna\n\n}\n\nvoid reclassLoci(char strand, GList<GLocus>& qloci, GList<GLocus>* rloci, GFaSeqGet *faseq) {\n  for (int ql=0;ql<qloci.Count();ql++) {\n    reclass_mRNAs(strand, qloci[ql]->mrnas, rloci, faseq);\n    //find closest upstream ref locus for this q locus\n  } //for each locus\n}\n\n//for a single genomic sequence, all qry data and ref data is stored in gtrack\n//check for all 'u' transfrags if they are repeat ('r') or polymerase run 'p' or anything else\nvoid umrnaReclass(int qcount,  GSeqTrack& gtrack, FILE** ftr, GFaSeqGet* faseq=NULL) {\n    for (int q=0;q<qcount;q++) {\n        if (gtrack.qdata[q]==NULL) continue; //no transcripts in this q dataset for this genomic seq\n        reclassLoci('+', gtrack.qdata[q]->loci_f, gtrack.rloci_f, faseq);\n        reclassLoci('-', gtrack.qdata[q]->loci_r, gtrack.rloci_r, faseq);\n        reclass_mRNAs('+', gtrack.qdata[q]->umrnas, gtrack.rloci_f, faseq);\n        reclass_mRNAs('-', gtrack.qdata[q]->umrnas, gtrack.rloci_r, faseq);\n        //and also check for special cases with cross-strand overlaps:\n        reclass_XStrand(gtrack.qdata[q]->mrnas_f, gtrack.rloci_r);\n        reclass_XStrand(gtrack.qdata[q]->mrnas_r, gtrack.rloci_f);\n        // print all tmap data here here:\n        for (int i=0;i<gtrack.qdata[q]->tdata.Count();i++) {\n            CTData* mdata=gtrack.qdata[q]->tdata[i];\n            if (mdata->mrna==NULL) continue; //invalidated -- removed earlier\n            //GLocus* rlocus=NULL;\n            mdata->classcode='u';\n            GffObj* ref=NULL;\n            if (mdata->ovls.Count()>0) {\n                mdata->classcode=mdata->ovls[0]->code;\n                ref=mdata->ovls[0]->mrna;\n            }\n            //if (mdata->classcode<33) mdata->classcode='u';      \n            if (mdata->classcode<47) mdata->classcode='u'; // if 0, '-' or '.'\n            if (tmapFiles) {\n                char ref_match_len[2048];\n                if (ref!=NULL) {\n                    sprintf(ref_match_len, \"%d\",ref->covlen);\n                    fprintf(ftr[q],\"%s\\t%s\\t\",getGeneID(ref),ref->getID());\n                    //rlocus=((CTData*)(ref->uptr))->locus;\n                }\n                else {\n                    fprintf(ftr[q],\"-\\t-\\t\");\n                    strcpy(ref_match_len, \"-\");\n                }\n                //fprintf(ftr[q],\"%c\\t%s\\t%d\\t%8.6f\\t%8.6f\\t%d\\n\", ovlcode, mdata->mrna->getID(),\n                //    iround(mdata->mrna->gscore/10), mdata->FPKM, mdata->cov, mdata->mrna->covlen);\n                const char* mlocname = (mdata->locus!=NULL) ? mdata->locus->mrna_maxcov->getID() : mdata->mrna->getID();\n                fprintf(ftr[q],\"%c\\t%s\\t%s\\t%d\\t%8.6f\\t%8.6f\\t%8.6f\\t%8.6f\\t%d\\t%s\\t%s\\n\", mdata->classcode, getGeneID(mdata->mrna), mdata->mrna->getID(),\n                        iround(mdata->mrna->gscore/10), mdata->FPKM, mdata->conf_lo,mdata->conf_hi, mdata->cov, mdata->mrna->covlen, mlocname, ref_match_len);\n            }\n        } //for each tdata\n    } //for each qdata\n}\n\nvoid buildXLoci(GTrackLocus& loctrack, int qcount, GSeqTrack& gtrack, char strand,\n    GList<GXLocus>* retxloci=NULL) {\n  GList<GXLocus>* dest_xloci=NULL;\n  GList<GXLocus> tmpxloci(true,false,true); //local set of newly created xloci\n  GList<GXLocus>* xloci=&tmpxloci;\n  if (strand=='+') {\n       dest_xloci=& gtrack.xloci_f;\n       }\n    else if (strand=='-') {\n      dest_xloci = & gtrack.xloci_r;\n      }\n   else dest_xloci= & gtrack.xloci_u;\n\n  if (retxloci==NULL) {\n     //if no return set of build xloci was given\n     //take it as a directive to work directly on the global xloci\n     xloci=dest_xloci;\n     dest_xloci=NULL;\n   }\n for (int q=-1;q<qcount;q++) {\n   GList<GLocus>* wrkloci=NULL;\n   if (q<0) {\n      if (loctrack.rloci.Count()==0) continue;\n      //loci=new GList<GLocus>(true,false,false);\n      //loci->Add(loctrack.rloc);\n      wrkloci = &(loctrack.rloci);\n      }\n     else {\n      if (loctrack[q]==NULL) continue;\n      wrkloci = &(loctrack[q]->qloci);\n      }\n   \n   for (int t=0;t<wrkloci->Count();t++) {\n      GLocus* loc=wrkloci->Get(t);\n      int xfound=0; //count of parent xloci\n      if (loc->xlocus!=NULL) continue; //already assigned a superlocus\n      GArray<int> mrgxloci(true);\n      for (int xl=0;xl<xloci->Count();xl++) {\n         GXLocus& xloc=*(xloci->Get(xl));\n         if (xloc.start>loc->end) {\n            if (xloc.start-loc->end > GFF_MAX_LOCUS) break;\n            continue;\n            }\n         if (loc->start>xloc.end) continue;\n         if (xloc.add_Locus(loc)) {\n            xfound++;\n            mrgxloci.Add(xl);\n            }\n         } //for each existing Xlocus\n      if (xfound==0) {\n         xloci->Add(new GXLocus(loc));\n         }\n      else {\n         int il=mrgxloci[0];\n         GXLocus& xloc=*(xloci->Get(il));\n         if (xfound>1) {\n            for (int l=1;l<xfound;l++) {\n              int mlidx=mrgxloci[l]-l+1;\n              xloc.addMerge(*(xloci->Get(mlidx)));\n              GXLocus* ldel=xloci->Get(mlidx);\n              xloci->Delete(mlidx);\n              if (retxloci!=NULL)\n                    delete ldel;\n              }\n            }\n         //in case xloc.start was decreased, bubble-down until it's in the proper order\n         while (il>0 && xloc<*(xloci->Get(il-1))) {\n            il--;\n            xloci->Swap(il,il+1);\n            }\n         } //at least one locus is being merged \n      }//for each locus\n   }//for each set of loci in the region (refs and each qry set)\n  //-- add xloci to the global set of xloci unless retxloci was given,\n  if (retxloci!=NULL) retxloci->Add(*xloci);\n                 else dest_xloci->Add(*xloci);\n}\n\nvoid singleQData(GList<GLocus>& qloci, GList<GTrackLocus>& loctracks) {\n for (int i=0;i<qloci.Count();i++) {\n  if (qloci[i]->t_ptr==NULL) {\n    GTrackLocus* tloc=new GTrackLocus();\n    tloc->addQLocus(qloci[i],0);\n    loctracks.Add(tloc);\n    }\n  }\n}\n/*\nvoid recheckUmrnas(GSeqData* gseqdata, GList<GffObj>& mrnas,\n     GList<GLocus>& loci, GList<GLocus>& nloci,  GList<GLocus>& oloci) {\n GList<GLocus> reassignedLocs(false,false);\n for (int u=0;u<gseqdata->umrnas.Count();u++) {\n   for (int l=0;l<oloci.Count();l++) {\n     if (gseqdata->umrnas[u]==NULL) break;\n     if (gseqdata->umrnas[u]->end<oloci[l]->start) break; //try next umrna\n     if (oloci[l]->end<gseqdata->umrnas[u]->start) continue; //try next locus\n     if (gseqdata->umrnas[u]->strand=='+' || gseqdata->umrnas[u]->strand=='-') {\n       gseqdata->umrnas.Forget(u);\n       continue; //already reassigned earlier\n       }\n     //umrna overlaps locus region\n     GffObj* umrna=gseqdata->umrnas[u];\n     for (int m=0;m<oloci[l]->mrnas.Count();m++) {\n        if (oloci[l]->mrnas[m]->exonOverlap(umrna)) {\n            gseqdata->umrnas.Forget(u);\n            CTData* umdata=((CTData*)umrna->uptr);\n            //must be in a Loci anyway\n            if (umdata==NULL || umdata->locus==NULL)\n                GError(\"Error: no locus pointer for umrna %s!\\n\",umrna->getID());\n            for (int i=0;i<umdata->locus->mrnas.Count();i++) {\n               GffObj* um=umdata->locus->mrnas[i];\n               um->strand=oloci[l]->mrnas[m]->strand;\n               }\n            reassignedLocs.Add(umdata->locus);\n            break;\n            }\n        } //for each mrna in locus\n      } //for each locus\n   } //for each umrna\n if (reassignedLocs.Count()>0) {\n   gseqdata->umrnas.Pack();\n   gseqdata->nloci_u.setFreeItem(false);\n   for (int i=0;i<reassignedLocs.Count();i++) {\n     GLocus* loc=reassignedLocs[i];\n     for (int m=0;m<loc->mrnas.Count();m++) {\n        mrnas.Add(loc->mrnas[m]);\n        }\n     loci.Add(loc);\n     nloci.Add(loc);\n     gseqdata->nloci_u.Remove(loc);\n     }\n   gseqdata->nloci_u.setFreeItem(true);\n   }\n}\n*/\n\nvoid umrnasXStrand(GList<GXLocus>& xloci, GSeqTrack& gtrack) {\n  //try to determine the strand of unoriented transfrags based on possible overlaps\n  //with other, oriented transfrags\n for (int x=0;x<xloci.Count();x++) {\n   if (xloci[x]->strand=='.') continue;\n   if (xloci[x]->qloci.Count()==0) continue;\n   //go through all qloci in this xlocus\n   for (int l = 0; l < xloci[x]->qloci.Count(); l++) {\n     char locstrand=xloci[x]->qloci[l]->mrna_maxcov->strand;\n     if (locstrand=='.') {\n        //this is a umrna cluster\n        GLocus* qloc=xloci[x]->qloci[l];\n        //we don't really need to update loci lists (loci_f, nloci_f etc.)\n        /*\n        if (xloci[x]->strand=='+') {\n           }\n         else { // - strand\n           }\n        */\n        for (int i=0;i<qloc->mrnas.Count();i++) {\n           qloc->mrnas[i]->strand=xloci[x]->strand;\n           int uidx=gtrack.qdata[qloc->qfidx]->umrnas.IndexOf(qloc->mrnas[i]);\n           if (uidx>=0) {\n                gtrack.qdata[qloc->qfidx]->umrnas.Forget(uidx);\n                gtrack.qdata[qloc->qfidx]->umrnas.Delete(uidx);\n                if (xloci[x]->strand=='+')\n                     gtrack.qdata[qloc->qfidx]->mrnas_f.Add(qloc->mrnas[i]);\n                   else\n                     gtrack.qdata[qloc->qfidx]->mrnas_r.Add(qloc->mrnas[i]);\n                }\n           }\n        } //unknown strand\n     } //for each xloci[x].qloci (l)\n\n   } //for each xloci (x)\n}\n\n//cluster loci across all datasets\nvoid xclusterLoci(int qcount, char strand, GSeqTrack& gtrack) {\n  //gtrack holds data for all input qry datasets for a chromosome/contig\n  //cluster QLoci\n  GList<GTrackLocus> loctracks(true,true,false);\n  //all vs all clustering across all qry data sets + ref\n  //one-strand set of loci from all datasets + ref loci\n  GList<GLocus>* wrkloci=NULL;\n  //build xloci without references first\n  //then add references only if they overlap an existing xloci\n  \n  int nq=0;\n  for (int q=0;q<=qcount+1;q++) {\n    bool refcheck=false;\n    if (q==qcount) { // check the unoriented loci for each query file\n       while (nq<qcount &&\n              (gtrack.qdata[nq]==NULL || gtrack.qdata[nq]->nloci_u.Count()==0))\n                 nq++; //skip query files with no unoriented loci\n       if (nq<qcount) {\n             wrkloci=&(gtrack.qdata[nq]->nloci_u);\n             nq++;\n             if (nq<qcount) q--; //so we can fetch the next nq in the next q cycle\n             }\n          else continue; //no more q files with unoriented loci\n       }\n    else if (q==qcount+1) { // check the reference loci\n           if (strand=='+') wrkloci=gtrack.rloci_f;\n                       else wrkloci=gtrack.rloci_r;\n            \n           if (wrkloci==NULL) break; //no ref loci here\n           refcheck=true;\n           }\n     else  {\n          if (gtrack.qdata[q]==NULL) continue;\n          if (strand=='+') wrkloci=&(gtrack.qdata[q]->loci_f);\n                      else wrkloci=&(gtrack.qdata[q]->loci_r);\n         }\n   // now do the all-vs-all clustering thing:\n   for (int t=0;t<wrkloci->Count();t++) {\n      GLocus* loc=wrkloci->Get(t);\n      int xfound=0; //count of parent loctracks\n      if (loc->t_ptr!=NULL) continue; //already assigned a loctrack\n      GArray<int> mrgloctracks(true);\n      for (int xl=0;xl<loctracks.Count();xl++) {\n         GTrackLocus& trackloc=*loctracks[xl];\n         if (trackloc.start>loc->end) break;\n         if (loc->start>trackloc.end) continue;\n         if (trackloc.add_Locus(loc)) {\n            xfound++;\n            mrgloctracks.Add(xl);\n            }\n         } //for each existing Xlocus\n      if (xfound==0) {\n         if (!refcheck) //we really don't care about ref-only clusters\n           loctracks.Add(new GTrackLocus(loc));\n         }\n      else {\n         int il=mrgloctracks[0];\n         GTrackLocus& tloc=*(loctracks.Get(il));\n         if (xfound>1) {\n           for (int l=1;l<xfound;l++) {\n             int mlidx=mrgloctracks[l]-l+1;\n             tloc.addMerge(loctracks[mlidx], qcount, loc);\n             loctracks.Delete(mlidx);\n             }\n           }\n         //in case tloc.start was decreased, bubble-down 'til it's in the proper place\n         while (il>0 && tloc<*(loctracks[il-1])) {\n            il--;\n            loctracks.Swap(il,il+1);\n            }\n        } //at least one locus found\n      }//for each wrklocus\n     } //for each set of loci (q)\n   //loctracks is now set with all x-clusters on this strand\n for (int i=0;i<loctracks.Count();i++) {\n   if (!loctracks[i]->hasQloci) continue; //we really don't care here about reference-only clusters\n   GTrackLocus& loctrack=*loctracks[i];\n   findTMatches(loctrack, qcount); //find matching transfrags in this xcluster\n   for (int rl=0; rl < loctrack.rloci.Count(); rl++) {\n      findTRMatch(loctrack, qcount, *(loctrack.rloci[rl]));\n      //find matching reference annotation for this xcluster and assign class codes to transfrags\n      }\n    GList<GXLocus> xloci(false,false,false);\n    buildXLoci(loctrack, qcount, gtrack, strand, &xloci);\n    //the newly created xloci are in xloci\n    umrnasXStrand(xloci, gtrack);\n    //also merge these xloci into the global list of xloci\n    for (int l=0; l < xloci.Count(); l++) {\n       if (xloci[l]->strand=='+') {\n           gtrack.xloci_f.Add(xloci[l]);\n           }\n          else if (xloci[l]->strand=='-') {\n              gtrack.xloci_r.Add(xloci[l]);\n              }\n            else gtrack.xloci_u.Add(xloci[l]);\n       }\n    }//for each xcluster\n}\n\n\nvoid printRefMap(FILE** frs, int qcount, GList<GLocus>* rloci) {\n  if (rloci==NULL) return;\n\n  for (int l=0;l<rloci->Count(); l++) {\n    for (int r=0;r<rloci->Get(l)->mrnas.Count(); r++) {\n      GffObj& ref = *(rloci->Get(l)->mrnas[r]);\n      CTData* refdata = ((CTData*)ref.uptr);\n      GStr* clist = new GStr[qcount];\n      GStr* eqlist = new GStr[qcount];\n      for (int i = 0; i<refdata->ovls.Count(); i++) {\n        GffObj* m=refdata->ovls[i]->mrna;\n        char ovlcode=refdata->ovls[i]->code;\n        if (m==NULL) {\n          GMessage(\"Warning: NULL mRNA found for ref %s with ovlcode '%c'\\n\",\n               ref.getID(), refdata->ovls[i]->code);\n          continue;\n        }\n        int qfidx = ((CTData*)m->uptr)->qset;\n        if (ovlcode == '=') {\n          eqlist[qfidx].append(getGeneID(m));\n          eqlist[qfidx].append('|');\n          eqlist[qfidx].append(m->getID());\n          eqlist[qfidx].append(',');\n        }\n        else if (ovlcode == 'c') {\n          clist[qfidx].append(getGeneID(m));\n          clist[qfidx].append('|');\n          clist[qfidx].append(m->getID());\n          clist[qfidx].append(',');\n        }\n      }//for each reference overlap\n      for (int q=0;q<qcount;q++) {\n        if (!eqlist[q].is_empty()) {\n          eqlist[q].trimR(',');\n          fprintf(frs[q],\"%s\\t%s\\t=\\t%s\\n\", getGeneID(ref), ref.getID(),eqlist[q].chars());\n        }\n        if (!clist[q].is_empty()) {\n          clist[q].trimR(',');\n          fprintf(frs[q],\"%s\\t%s\\tc\\t%s\\n\",getGeneID(ref), ref.getID(),clist[q].chars());\n        }\n      }\n      delete[] clist;\n      delete[] eqlist; \n    }// ref loop\n  }//ref locus loop\n}\n\n\n\nvoid trackGData(int qcount, GList<GSeqTrack>& gtracks, GStr& fbasename, FILE** ftr, FILE** frs) {\n  FILE* f_ltrack=NULL;\n  FILE* f_itrack=NULL;\n  FILE* f_ctrack=NULL;\n  FILE* f_xloci=NULL;\n  int cnum=0; //consensus numbering for printITrack()\n  GStr s=fbasename;\n  //if (qcount>1 || generic_GFF) { //doesn't make much sense for only 1 query file\n    s.append(\".tracking\");\n    f_itrack=fopen(s.chars(),\"w\");\n    if (f_itrack==NULL) GError(\"Error creating file %s !\\n\",s.chars());\n  //  }\n  s=fbasename;\n  s.append(\".combined.gtf\");\n  f_ctrack=fopen(s.chars(),\"w\");\n  if (f_ctrack==NULL) GError(\"Error creating file %s !\\n\",s.chars());\n  \n  s=fbasename;\n  s.append(\".loci\");\n  f_xloci=fopen(s.chars(),\"w\");\n  if (f_xloci==NULL) GError(\"Error creating file %s !\\n\",s.chars());\n  for (int g=0;g<gtracks.Count();g++) { //for each genomic sequence\n    GSeqTrack& gseqtrack=*gtracks[g];\n\n    xclusterLoci(qcount,  '+', gseqtrack);\n    xclusterLoci(qcount,  '-', gseqtrack);\n\n    //count XLoci, setting their id\n    numXLoci(gseqtrack.xloci_f, xlocnum);\n    numXLoci(gseqtrack.xloci_r, xlocnum);\n    numXLoci(gseqtrack.xloci_u, xlocnum);\n    //transcript accounting: for all those transcripts with 'u' or 0 class code\n    // we have to check for polymerase runs 'p' or repeats 'r'\n\n    GFaSeqGet *faseq=gfasta.fetch(gseqtrack.get_gseqid(), checkFasta);\n\n    umrnaReclass(qcount, gseqtrack, ftr, faseq);\n\n    // print transcript tracking (ichain_tracking)\n    //if (qcount>1)\n    for (int q=0;q<qcount;q++) {\n         if (gseqtrack.qdata[q]==NULL) continue;\n         printITrack(f_itrack, gseqtrack.qdata[q]->mrnas_f, qcount, cnum);\n         printITrack(f_itrack, gseqtrack.qdata[q]->mrnas_r, qcount, cnum);\n         //just for the sake of completion:\n         printITrack(f_itrack, gseqtrack.qdata[q]->umrnas, qcount, cnum);\n         }\n    //print XLoci and XConsensi within each xlocus\n    //also TSS clustering and protein ID assignment for XConsensi\n    printXLoci(f_xloci, f_ctrack, qcount, gseqtrack.xloci_f, faseq);\n    printXLoci(f_xloci, f_ctrack, qcount, gseqtrack.xloci_r, faseq);\n    printXLoci(f_xloci, f_ctrack, qcount, gseqtrack.xloci_u, faseq);\n    if (tmapFiles && haveRefs) {\n      printRefMap(frs, qcount, gseqtrack.rloci_f);\n      printRefMap(frs, qcount, gseqtrack.rloci_r);\n      }\n    delete faseq;\n    }\n  if (tmapFiles) {\n   for (int q=0;q<qcount;q++) {\n        fclose(ftr[q]); \n        if (haveRefs) fclose(frs[q]); \n        }\n   }\n  if (f_ltrack!=NULL) fclose(f_ltrack);\n  if (f_itrack!=NULL) fclose(f_itrack);\n  if (f_ctrack!=NULL) fclose(f_ctrack);\n  if (f_xloci!=NULL) fclose(f_xloci);\n\n}\n"
  },
  {
    "path": "src/cuffdiff.cpp",
    "content": "/*\n *  cuffdiff.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 10/21/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <stdlib.h>\n#include <getopt.h>\n#include <string>\n#include <numeric>\n#include <cfloat>\n#include <iostream>\n\n#include \"common.h\"\n#include \"hits.h\"\n#include \"bundles.h\"\n#include \"abundances.h\"\n#include \"tokenize.h\"\n#include \"biascorrection.h\"\n#include \"update_check.h\"\n\n#include <boost/thread.hpp>\n#include <boost/version.hpp>\n#include <boost/graph/adjacency_list.hpp>\n#include <boost/graph/graph_traits.hpp>\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/matrix_proxy.hpp>\n#include <boost/numeric/ublas/vector.hpp>\n#include <boost/numeric/ublas/vector_proxy.hpp>\n#include <boost/numeric/ublas/io.hpp>\n#include <boost/algorithm/string.hpp>\n\n#include \"differential.h\"\n\nextern \"C\" {\n#include \"locfit/local.h\"\n}\n\n// Need at least this many reads in a locus to do any testing on it\n\nvector<string> sample_labels;\n\ndouble FDR = 0.05; \nbool samples_are_time_series = false;\nusing namespace std;\nusing namespace boost;\n\n// We leave out the short codes for options that don't take an argument\n#if ENABLE_THREADS\nconst char *short_options = \"m:p:s:c:I:j:L:M:o:b:TNqvuF:C:\";\n#else\nconst char *short_options = \"m:s:c:I:j:L:M:o:b:TNqvuF:C:\";\n#endif\n\n\n\nstatic struct option long_options[] = {\n{\"frag-len-mean\",\t\t\trequired_argument,       0,          'm'},\n{\"frag-len-std-dev\",        required_argument,       0,          's'},\n{\"transcript-score-thresh\", required_argument,       0,          't'},\n{\"pre-mrna-fraction\",\t\trequired_argument,\t\t 0,\t\t\t 'j'},\n{\"max-intron-length\",\t\trequired_argument,\t\t 0,\t\t\t 'I'},\n{\"labels\",\t\t\t\t\trequired_argument,\t\t 0,\t\t\t 'L'},\n{\"min-alignment-count\",     required_argument,\t\t 0,\t\t\t 'c'},\n{\"FDR\",\t\t\t\t\t    required_argument,\t\t 0,\t\t\t OPT_FDR},\n{\"seed\",                    required_argument,\t\t 0,\t\t\t OPT_RANDOM_SEED},\n{\"mask-file\",               required_argument,\t\t 0,\t\t\t 'M'},\n{\"contrast-file\",           required_argument,\t\t 0,\t\t\t 'C'},\n{\"norm-standards-file\",     required_argument,\t\t 0,\t\t\t OPT_NORM_STANDARDS_FILE},\n{\"use-sample-sheet\",        no_argument,             0,\t\t\t OPT_USE_SAMPLE_SHEET},\n{\"output-dir\",\t\t\t    required_argument,\t\t 0,\t\t\t 'o'},\n{\"verbose\",\t\t\t    \tno_argument,\t\t\t 0,\t\t\t 'v'},\n{\"quiet\",\t\t\t    \tno_argument,\t\t\t 0,\t\t\t 'q'},\n{\"frag-bias-correct\",       required_argument,\t\t 0,\t\t\t 'b'},\n{\"multi-read-correct\",      no_argument,\t\t\t 0,\t\t\t 'u'},\n{\"time-series\",             no_argument,             0,\t\t\t 'T'},\n{\"upper-quartile-norm\",     no_argument,\t \t\t 0,\t         'N'},\n{\"geometric-norm\",          no_argument,\t \t\t 0,\t         OPT_GEOMETRIC_NORM},\n{\"raw-mapped-norm\",         no_argument,\t \t\t 0,\t         OPT_RAW_MAPPED_NORM},\n{\"min-isoform-fraction\",    required_argument,       0,          'F'},\n#if ENABLE_THREADS\n{\"num-threads\",\t\t\t\trequired_argument,       0,          'p'},\n#endif\n{\"library-type\",\t\t    required_argument,\t\t 0,\t\t\t OPT_LIBRARY_TYPE},\n{\"seed\",                    required_argument,\t\t 0,\t\t\t OPT_RANDOM_SEED},\n{\"no-collapse-cond-prob\",   no_argument,             0,\t\t\t OPT_COLLAPSE_COND_PROB},\n{\"num-importance-samples\",  required_argument,\t\t 0,\t\t\t OPT_NUM_IMP_SAMPLES},\n{\"max-mle-iterations\",\t\trequired_argument,\t\t 0,\t\t\t OPT_MLE_MAX_ITER},\n{\"min-mle-accuracy\",\t\trequired_argument,\t\t 0,\t\t\t OPT_MLE_MIN_ACC},\n{\"poisson-dispersion\",\t\tno_argument,             0,\t\t     OPT_POISSON_DISPERSION},\n{\"bias-mode\",               required_argument,\t\t 0,\t\t\t OPT_BIAS_MODE},\n{\"no-update-check\",         no_argument,             0,          OPT_NO_UPDATE_CHECK},\n{\"emit-count-tables\",       no_argument,             0,          OPT_EMIT_COUNT_TABLES},\n{\"compatible-hits-norm\",    no_argument,\t \t\t 0,\t         OPT_USE_COMPAT_MASS},\n{\"total-hits-norm\",         no_argument,\t \t\t 0,\t         OPT_USE_TOTAL_MASS},\n//{\"analytic-diff\",           no_argument,\t \t\t 0,\t         OPT_ANALYTIC_DIFF},\n{\"no-diff\",                 no_argument,\t \t\t 0,\t         OPT_NO_DIFF},\n{\"num-frag-count-draws\",\trequired_argument,\t\t 0,\t\t\t OPT_NUM_FRAG_COUNT_DRAWS},\n{\"num-frag-assign-draws\",\trequired_argument,\t\t 0,\t\t\t OPT_NUM_FRAG_ASSIGN_DRAWS},\n    \n// Some options for testing different stats policies\n{\"max-bundle-frags\",        required_argument,       0,          OPT_MAX_FRAGS_PER_BUNDLE}, \n{\"read-skip-fraction\",      required_argument,\t     0,          OPT_READ_SKIP_FRACTION},\n{\"no-read-pairs\",           no_argument,\t \t\t 0,          OPT_NO_READ_PAIRS},\n{\"trim-read-length\",        required_argument,\t     0,          OPT_TRIM_READ_LENGTH},\n{\"cov-delta\",               required_argument,\t     0,          OPT_MAX_DELTA_GAP},\n{\"locus-count-dispersion\",  no_argument,             0,          OPT_LOCUS_COUNT_DISPERSION},\n{\"max-frag-multihits\",      required_argument,       0,          OPT_FRAG_MAX_MULTIHITS},\n{\"min-outlier-p\",           required_argument,       0,          OPT_MIN_OUTLIER_P},\n{\"min-reps-for-js-test\",      required_argument,     0,          OPT_MIN_REPS_FOR_JS_TEST},\n{\"no-effective-length-correction\",  no_argument,     0,          OPT_NO_EFFECTIVE_LENGTH_CORRECTION},\n{\"no-length-correction\",    no_argument,             0,          OPT_NO_LENGTH_CORRECTION},\n{\"no-js-tests\",             no_argument,             0,          OPT_NO_JS_TESTS},\n{\"dispersion-method\",       required_argument,       0,          OPT_DISPERSION_METHOD},\n{\"library-norm-method\",     required_argument,       0,          OPT_LIB_NORM_METHOD},\n{\"no-scv-correction\",       no_argument,             0,          OPT_NO_SCV_CORRECTION},\n{0, 0, 0, 0} // terminator\n};\n\nvoid print_usage()\n{\n\tfprintf(stderr, \"cuffdiff v%s (%s)\\n\", PACKAGE_VERSION, SVN_REVISION); \n\tfprintf(stderr, \"-----------------------------\\n\"); \n\t\n\t//NOTE: SPACES ONLY, bozo\n    fprintf(stderr, \"Usage:   cuffdiff [options] <transcripts.gtf> <sample1_hits.sam> <sample2_hits.sam> [... sampleN_hits.sam]\\n\");\n\tfprintf(stderr, \"   Supply replicate SAMs as comma separated lists for each condition: sample1_rep1.sam,sample1_rep2.sam,...sample1_repM.sam\\n\");\n    fprintf(stderr, \"General Options:\\n\");\n    fprintf(stderr, \"  -o/--output-dir              write all output files to this directory              [ default:     ./ ]\\n\");\n    fprintf(stderr, \"  -L/--labels                  comma-separated list of condition labels\\n\");\n\tfprintf(stderr, \"  --FDR                        False discovery rate used in testing                  [ default:   0.05 ]\\n\");\n\tfprintf(stderr, \"  -M/--mask-file               ignore all alignment within transcripts in this file  [ default:   NULL ]\\n\");\n    fprintf(stderr, \"  -C/--contrast-file           Perform the constrasts specified in this file         [ default:   NULL ]\\n\"); // NOT YET DOCUMENTED, keep secret for now\n    //fprintf(stderr, \"  --norm-standards-file        Housekeeping/spike genes to normalize libraries       [ default:   NULL ]\\n\"); // NOT YET DOCUMENTED, keep secret for now\n    fprintf(stderr, \"  -b/--frag-bias-correct       use bias correction - reference fasta required        [ default:   NULL ]\\n\");\n    fprintf(stderr, \"  -u/--multi-read-correct      use 'rescue method' for multi-reads                   [ default:  FALSE ]\\n\");\n#if ENABLE_THREADS\n\tfprintf(stderr, \"  -p/--num-threads             number of threads used during quantification          [ default:      1 ]\\n\");\n#endif\n    fprintf(stderr, \"  --no-diff                    Don't generate differential analysis files            [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --no-js-tests                Don't perform isoform switching tests                 [ default:  FALSE ]\\n\");\n\tfprintf(stderr, \"  -T/--time-series             treat samples as a time-series                        [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --library-type               Library prep used for input reads                     [ default:  below ]\\n\");\n    fprintf(stderr, \"  --dispersion-method          Method used to estimate dispersion models             [ default:  below ]\\n\");\n    fprintf(stderr, \"  --library-norm-method        Method used to normalize library sizes                [ default:  below ]\\n\");\n    \n    fprintf(stderr, \"\\nAdvanced Options:\\n\");\n    fprintf(stderr, \"  -m/--frag-len-mean           average fragment length (unpaired reads only)         [ default:    200 ]\\n\");\n    fprintf(stderr, \"  -s/--frag-len-std-dev        fragment length std deviation (unpaired reads only)   [ default:     80 ]\\n\");\n    fprintf(stderr, \"  -c/--min-alignment-count     minimum number of alignments in a locus for testing   [ default:   10 ]\\n\");\n    fprintf(stderr, \"  --max-mle-iterations         maximum iterations allowed for MLE calculation        [ default:   5000 ]\\n\");\n    fprintf(stderr, \"  --compatible-hits-norm       count hits compatible with reference RNAs only        [ default:   TRUE ]\\n\");\n    fprintf(stderr, \"  --total-hits-norm            count all hits for normalization                      [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  -v/--verbose                 log-friendly verbose processing (no progress bar)     [ default:  FALSE ]\\n\");\n\tfprintf(stderr, \"  -q/--quiet                   log-friendly quiet processing (no progress bar)       [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --seed                       value of random number generator seed                 [ default:      0 ]\\n\");\n    fprintf(stderr, \"  --no-update-check            do not contact server to check for update availability[ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --emit-count-tables          print count tables used to fit overdispersion         [    DEPRECATED   ]\\n\");\n    fprintf(stderr, \"  --max-bundle-frags           maximum fragments allowed in a bundle before skipping [ default: 500000 ]\\n\");\n    fprintf(stderr, \"  --num-frag-count-draws       Number of fragment generation samples                 [ default:    100 ]\\n\");\n    fprintf(stderr, \"  --num-frag-assign-draws      Number of fragment assignment samples per generation  [ default:     50 ]\\n\");\n    fprintf(stderr, \"  --max-frag-multihits         Maximum number of alignments allowed per fragment     [ default: unlim  ]\\n\");\n    fprintf(stderr, \"  --min-outlier-p              Min replicate p value to admit for testing            [    DEPRECATED   ]\\n\");\n    fprintf(stderr, \"  --min-reps-for-js-test       Replicates needed for relative isoform shift testing  [ default:      3 ]\\n\");\n    fprintf(stderr, \"  --no-effective-length-correction   No effective length correction                  [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --no-length-correction       No length correction                                  [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  -N/--upper-quartile-norm     Deprecated, use --library-norm-method                 [    DEPRECATED   ]\\n\");\n    fprintf(stderr, \"  --geometric-norm             Deprecated, use --library-norm-method                 [    DEPRECATED   ]\\n\");\n    fprintf(stderr, \"  --raw-mapped-norm            Deprecated, use --library-norm-method                 [    DEPRECATED   ]\\n\");\n    fprintf(stderr, \"  --poisson-dispersion         Deprecated, use --dispersion-method                   [    DEPRECATED   ]\\n\");\n    fprintf(stderr, \"\\nDebugging use only:\\n\");\n    fprintf(stderr, \"  --read-skip-fraction         Skip a random subset of reads this size               [ default:    0.0 ]\\n\");\n    fprintf(stderr, \"  --no-read-pairs              Break all read pairs                                  [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --trim-read-length           Trim reads to be this long (keep 5' end)              [ default:   none ]\\n\");\n    fprintf(stderr, \"  --no-scv-correction          Disable SCV correction                                [ default:  FALSE ]\\n\");\n    print_library_table();\n    print_dispersion_method_table();\n    print_lib_norm_method_table();\n}\n\nint parse_options(int argc, char** argv)\n{\n    int option_index = 0;\n    int next_option;\n    string sample_label_list;\n    string dispersion_method_str;\n    string lib_norm_method_str;\n    do {\n        next_option = getopt_long_only(argc, argv, short_options, long_options, &option_index);\n        if (next_option == -1)     /* Done with options. */\n            break;\n        switch (next_option) {\n            case 0:\n                /* If this option set a flag, do nothing else now. */\n                if (long_options[option_index].flag != 0)\n                    break;\n                break;\n                \n\t\t\tcase 'm':\n\t\t\t\tuser_provided_fld = true;\n\t\t\t\tdef_frag_len_mean = (uint32_t)parseInt(0, \"-m/--frag-len-mean arg must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase 'c':\n\t\t\t\tmin_read_count = (uint32_t)parseInt(0, \"-c/--min-alignment-count arg must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase 's':\n\t\t\t\tuser_provided_fld = true;\n\t\t\t\tdef_frag_len_std_dev = (uint32_t)parseInt(0, \"-s/--frag-len-std-dev arg must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase 'p':\n\t\t\t\tnum_threads = (uint32_t)parseInt(1, \"-p/--num-threads arg must be at least 1\", print_usage);\n\t\t\t\tbreak;\n            case 'F':\n\t\t\t\tmin_isoform_fraction = parseFloat(0, 1.0, \"-F/--min-isoform-fraction must be between 0 and 1.0\", print_usage);\n\t\t\t\tbreak;\n            case 'L':\n\t\t\t\tsample_label_list = optarg;\n\t\t\t\tbreak;\n\t\t\tcase OPT_FDR:\n\t\t\t\tFDR = (double)parseFloat(0.00, 1.00, \"--FDR arg must be between 0 and 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase OPT_NUM_IMP_SAMPLES:\n\t\t\t\tnum_importance_samples = parseInt(1, \"--num-importance-samples must be at least 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase OPT_MLE_MAX_ITER:\n\t\t\t\tmax_mle_iterations = parseInt(1, \"--max-mle-iterations must be at least 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase OPT_BIAS_MODE:\n\t\t\t\tif (!strcmp(optarg, \"site\"))\n\t\t\t\t\tbias_mode = SITE;\n\t\t\t\telse if (!strcmp(optarg, \"pos\"))\n\t\t\t\t\tbias_mode = POS;\n\t\t\t\telse if (!strcmp(optarg, \"pos_vlmm\"))\n\t\t\t\t\tbias_mode = POS_VLMM;\n\t\t\t\telse if (!strcmp(optarg, \"vlmm\"))\n\t\t\t\t\tbias_mode = VLMM;\n                else if (!strcmp(optarg, \"pos_site\"))\n\t\t\t\t\tbias_mode = POS_SITE;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Unknown bias mode.\\n\");\n\t\t\t\t\texit(1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'M':\n\t\t\t{\n\t\t\t\tmask_gtf_filename = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case 'C':\n\t\t\t{\n\t\t\t\tcontrast_filename = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OPT_NORM_STANDARDS_FILE:\n\t\t\t{\n\t\t\t\tnorm_standards_filename = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_USE_SAMPLE_SHEET:\n\t\t\t{\n                use_sample_sheet = true;\n\t\t\t\tbreak;\n\t\t\t}\n            case 'v':\n\t\t\t{\n\t\t\t\tif (cuff_quiet)\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Warning: Can't be both verbose and quiet!  Setting verbose only.\\n\");\n\t\t\t\t}\n\t\t\t\tcuff_quiet = false;\n\t\t\t\tcuff_verbose = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'q':\n\t\t\t{\n\t\t\t\tif (cuff_verbose)\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Warning: Can't be both verbose and quiet!  Setting quiet only.\\n\");\n\t\t\t\t}\n\t\t\t\tcuff_verbose = false;\n\t\t\t\tcuff_quiet = true;\n\t\t\t\tbreak;\n\t\t\t}\n            case 'o':\n\t\t\t{\n\t\t\t\toutput_dir = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'b':\n\t\t\t{\n\t\t\t\tfasta_dir = optarg;\n\t\t\t\tcorr_bias = true;\n\t\t\t\tbreak;\n            }    \n                \n            case 'T':\n\t\t\t{\n                samples_are_time_series = true;\n\t\t\t\tbreak;\n            }\n            case 'N':\n            {\n            \tlib_norm_method_str = \"quartile\";\n            \tbreak;\n            }\n            case 'u':\n            {\n                corr_multi = true;\n                break;\n            }\n            case OPT_LIBRARY_TYPE:\n\t\t\t{\n\t\t\t\tlibrary_type = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_POISSON_DISPERSION:\n\t\t\t{\n\t\t\t\tfprintf (stderr, \"Warning: --poisson-dispersion is deprecated, use --dispersion-method poisson instead.\\n\");\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_NO_UPDATE_CHECK:\n            {\n                no_update_check = true;\n                break;\n            }\n            case OPT_RANDOM_SEED:\n            {\n                random_seed = parseInt(0, \"--seed must be at least 0\", print_usage);\n                break;\n            }\n            case OPT_EMIT_COUNT_TABLES:\n            {\n                emit_count_tables = true;\n                break;\n            }    \n            case OPT_COLLAPSE_COND_PROB:\n            {\n                cond_prob_collapse = false;\n                break;\n            }\n            case OPT_USE_COMPAT_MASS:\n            {\n                use_compat_mass = true;\n                break;\n            }\n            case OPT_USE_TOTAL_MASS:\n            {\n                use_total_mass = true;\n                break;\n            }\n            case OPT_USE_FISHER_COVARIANCE:\n            {\n                use_fisher_covariance = true;\n                break;\n            }\n            case OPT_USE_EMPIRICAL_COVARIANCE:\n            {\n                use_fisher_covariance = false;\n                break;\n            }\n            case OPT_SPLIT_MASS:\n            {\n                split_variance = false;\n                break;\n            }\n            case OPT_SPLIT_VARIANCE:\n            {\n                split_variance = true;\n                break;\n            }\n\n            case OPT_MAX_FRAGS_PER_BUNDLE:\n            {\n                max_frags_per_bundle = parseInt(0, \"--max-bundle-frags must be at least 0\", print_usage);\n                break;\n            }\n            case OPT_READ_SKIP_FRACTION:\n            {\n                read_skip_fraction = parseFloat(0, 1.0, \"--read-skip-fraction must be between 0 and 1.0\", print_usage);\n                break;\n            }\n            case OPT_NO_READ_PAIRS:\n            {\n                no_read_pairs = true;\n                break;\n            }\n            case OPT_TRIM_READ_LENGTH:\n            {\n                trim_read_length = parseInt(0, \"--trim-read-length must be at least 1\", print_usage);\n                break;\n            }\n\n            case OPT_NO_DIFF:\n            {\n                no_differential = true;\n                break;\n            }\n            case OPT_GEOMETRIC_NORM:\n            {\n                lib_norm_method_str = \"geometric\";\n                break;\n            } \n            case OPT_RAW_MAPPED_NORM:\n            {\n                lib_norm_method_str = \"classic-fpkm\";\n                break;\n            } \n            case OPT_NUM_FRAG_COUNT_DRAWS:\n            {\n                num_frag_count_draws = parseInt(1, \"--num-frag-count-draws must be at least 1\", print_usage);\n                break;\n            }\n            case OPT_NUM_FRAG_ASSIGN_DRAWS:\n            {\n                num_frag_assignments = parseInt(1, \"--num-frag-assign-draws must be at least 1\", print_usage);\n                break;\n            }\n            case OPT_FRAG_MAX_MULTIHITS:\n            {\n                max_frag_multihits = parseInt(1, \"--max-frag-multihits must be at least 1\", print_usage);\n                break;\n            }\n            case OPT_MIN_OUTLIER_P:\n            {\n                min_outlier_p = parseFloat(0, 1.0, \"--min-outlier-p must be between 0 and 1.0\", print_usage);\n                break;\n            }\n            case OPT_MIN_REPS_FOR_JS_TEST:\n            {\n                min_reps_for_js_test = parseInt(1, \"--min-reps-for-js-test must be at least 1\", print_usage);\n                break;\n            }\n            case OPT_NO_EFFECTIVE_LENGTH_CORRECTION:\n            {\n                no_effective_length_correction = true;\n                break;\n            }\n            case OPT_NO_LENGTH_CORRECTION:\n            {\n                no_length_correction = true;\n                break;\n            }\n            case OPT_NO_JS_TESTS:\n            {\n                no_js_tests = true;\n                break;\n            }\n            case OPT_DISPERSION_METHOD:\n\t\t\t{\n\t\t\t\tdispersion_method_str = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_LIB_NORM_METHOD:\n\t\t\t{\n\t\t\t\tlib_norm_method_str = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_NO_SCV_CORRECTION:\n            {\n                no_scv_correction = true;\n                break;\n            }\n\t\t\tdefault:\n\t\t\t\tprint_usage();\n\t\t\t\treturn 1;\n        }\n    } while(next_option != -1);\n\t\n\tif (library_type != \"\")\n    {\n        map<string, ReadGroupProperties>::iterator lib_itr = \n\t\tlibrary_type_table.find(library_type);\n        if (lib_itr == library_type_table.end())\n        {\n            fprintf(stderr, \"Error: Library type %s not supported\\n\", library_type.c_str());\n            exit(1);\n        }\n        else \n        {\n            if (library_type == \"transfrags\")\n            {\n                allow_junk_filtering = false;\n            }\n            global_read_properties = &lib_itr->second;\n        }\n    }\n    else\n    {\n        \n    }\n    \n    // Set the count dispersion method to use\n    if (dispersion_method_str == \"\")\n    {\n        dispersion_method_str = default_dispersion_method;\n    }\n    \n    map<string, DispersionMethod>::iterator disp_itr = \n    dispersion_method_table.find(dispersion_method_str);\n    if (disp_itr == dispersion_method_table.end())\n    {\n        fprintf(stderr, \"Error: Dispersion method %s not supported\\n\", dispersion_method_str.c_str());\n        exit(1);\n    }\n    else \n    {\n        dispersion_method = disp_itr->second;\n    }\n\n    // Set the library size normalization method to use\n    if (lib_norm_method_str == \"\")\n    {\n        lib_norm_method_str = default_lib_norm_method;\n    }\n    \n    map<string, LibNormalizationMethod>::iterator lib_norm_itr =\n    lib_norm_method_table.find(lib_norm_method_str);\n    if (lib_norm_itr == lib_norm_method_table.end())\n    {\n        fprintf(stderr, \"Error: Dispersion method %s not supported\\n\", lib_norm_method_str.c_str());\n        exit(1);\n    }\n    else\n    {\n        lib_norm_method = lib_norm_itr->second;\n    }\n\n\n    \n    if (use_total_mass && use_compat_mass)\n    {\n        fprintf (stderr, \"Error: please supply only one of --compatibile-hits-norm and --total-hits-norm\\n\");\n        exit(1);\n    }\n    \n    tokenize(sample_label_list, \",\", sample_labels);\n    \n\tallow_junk_filtering = false;\n\t\n\treturn 0;\n}\n\nvoid print_tests(FILE* fout,\n                 const char* sample_1_label,\n                 const char* sample_2_label,\n\t\t\t\t const SampleDiffs& de_tests)\n{\n\tfor (SampleDiffs::const_iterator itr = de_tests.begin(); \n\t\t itr != de_tests.end(); \n\t\t ++itr)\n\t{\n\t\tconst SampleDifference& test = itr->second;\n        \n        string all_gene_ids = cat_strings(test.meta_data->gene_ids);\n\t\tif (all_gene_ids == \"\")\n\t\t\tall_gene_ids = \"-\";\n        \n\t\tstring all_gene_names = cat_strings(test.meta_data->gene_names);\n\t\tif (all_gene_names == \"\")\n\t\t\tall_gene_names = \"-\";\n\t\t\n\t\tstring all_protein_ids = cat_strings(test.meta_data->protein_ids);\t\n\t\tif (all_protein_ids == \"\")\n\t\t\tall_protein_ids = \"-\";\n\t\t\n\t\tfprintf(fout, \"%s\\t%s\\t%s\\t%s\\t%s\\t%s\", \n                itr->first.c_str(), \n                all_gene_ids.c_str(),\n                all_gene_names.c_str(), \n                test.meta_data->locus_desc.c_str(),\n                sample_1_label,\n                sample_2_label);\n\t\t\n        double t = test.test_stat;\n        double r1 = test.value_1;\n        double r2 = test.value_2;\n        double d = test.differential;\n        double p = test.p_value;\n        double q = test.corrected_p;\n        const char* sig;\n        if (test.significant && test.test_status == OK)\n            sig = \"yes\";\n        else\n            sig = \"no\";\n        \n        const char* status = \"OK\";\n        if (test.test_status == OK)\n            status = \"OK\";\n        else if (test.test_status == LOWDATA)\n            status = \"LOWDATA\";\n        else if (test.test_status == HIDATA)\n            status = \"HIDATA\";\n        else if (test.test_status == NOTEST)\n            status = \"NOTEST\";\n        else\n            status = \"FAIL\";\n        \n        fprintf(fout, \"\\t%s\\t%lg\\t%lg\\t%lg\\t%lg\\t%lg\\t%lg\\t%s\", status, r1, r2, d, t, p, q, sig);\n        fprintf(fout, \"\\n\");\n\t}\n}\n\nvoid print_FPKM_tracking(FILE* fout, \n\t\t\t\t\t\t const FPKMTrackingTable& tracking)\n{\n\tfprintf(fout,\"tracking_id\\tclass_code\\tnearest_ref_id\\tgene_id\\tgene_short_name\\ttss_id\\tlocus\\tlength\\tcoverage\");\n\tFPKMTrackingTable::const_iterator first_itr = tracking.begin();\n\tif (first_itr != tracking.end())\n\t{\n\t\tconst FPKMTracking& track = first_itr->second;\n\t\tconst vector<FPKMContext>& fpkms = track.fpkm_series;\n\t\tfor (size_t i = 0; i < fpkms.size(); ++i)\n\t\t{\n\t\t\tfprintf(fout, \"\\t%s_FPKM\\t%s_conf_lo\\t%s_conf_hi\\t%s_status\", sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str());\n\t\t}\n\t}\n\tfprintf(fout, \"\\n\");\n\tfor (FPKMTrackingTable::const_iterator itr = tracking.begin(); itr != tracking.end(); ++itr)\n\t{\n\t\tconst string& description = itr->first;\n\t\tconst FPKMTracking& track = itr->second;\n\t\tconst vector<FPKMContext>& fpkms = track.fpkm_series;\n\t\t\n        AbundanceStatus status = NUMERIC_OK;\n        BOOST_FOREACH (const FPKMContext& c, fpkms)\n        {\n            if (c.status == NUMERIC_FAIL)\n                status = NUMERIC_FAIL;\n        }\n        \n        string all_gene_ids = cat_strings(track.gene_ids);\n\t\tif (all_gene_ids == \"\")\n\t\t\tall_gene_ids = \"-\";\n        \n\t\tstring all_gene_names = cat_strings(track.gene_names);\n\t\tif (all_gene_names == \"\")\n\t\t\tall_gene_names = \"-\";\n\t\t\n\t\tstring all_tss_ids = cat_strings(track.tss_ids);\n\t\tif (all_tss_ids == \"\")\n\t\t\tall_tss_ids = \"-\";\n\t\t\n        char length_buff[33] = \"-\";\n        if (track.length)\n            sprintf(length_buff, \"%d\", track.length);\n        \n        fprintf(fout, \"%s\\t%c\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\", \n                description.c_str(),\n                track.classcode ? track.classcode : '-',\n                track.ref_match.c_str(),\n                all_gene_ids.c_str(),\n                all_gene_names.c_str(), \n                all_tss_ids.c_str(),\n                track.locus_tag.c_str(),\n                length_buff,\n                \"-\");\n       \t\t\n\t\tfor (size_t i = 0; i < fpkms.size(); ++i)\n\t\t{\n\t\t\tdouble fpkm = fpkms[i].FPKM;\n\t\t\t//double std_dev = sqrt(fpkms[i].FPKM_variance);\n\t\t\tdouble fpkm_conf_hi = fpkms[i].FPKM_conf_hi;\n\t\t\tdouble fpkm_conf_lo = fpkms[i].FPKM_conf_lo;\n            const char* status_str = \"OK\";\n            \n            if (fpkms[i].status == NUMERIC_OK)\n            {\n                status_str = \"OK\";\n            }\n            else if (fpkms[i].status == NUMERIC_FAIL)\n            {\n                status_str = \"FAIL\";\n            }\n            else if (fpkms[i].status == NUMERIC_LOW_DATA)\n            {\n                status_str = \"LOWDATA\";\n            }\n            else if (fpkms[i].status == NUMERIC_HI_DATA)\n            {\n                status_str = \"HIDATA\";\n            }\n            else\n            {\n                assert(false);\n            }\n            \n\t\t\tfprintf(fout, \"\\t%lg\\t%lg\\t%lg\\t%s\", fpkm, fpkm_conf_lo, fpkm_conf_hi, status_str);\n\t\t}\n\t\t\n\t\tfprintf(fout, \"\\n\");\n\t}\n}\n\nvoid print_count_tracking(FILE* fout, \n\t\t\t\t\t\t  const FPKMTrackingTable& tracking)\n{\n\tfprintf(fout,\"tracking_id\");\n\tFPKMTrackingTable::const_iterator first_itr = tracking.begin();\n\tif (first_itr != tracking.end())\n\t{\n\t\tconst FPKMTracking& track = first_itr->second;\n\t\tconst vector<FPKMContext>& fpkms = track.fpkm_series;\n\t\tfor (size_t i = 0; i < fpkms.size(); ++i)\n\t\t{\n\t\t\tfprintf(fout, \"\\t%s_count\\t%s_count_variance\\t%s_count_uncertainty_var\\t%s_count_dispersion_var\\t%s_status\", sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str());\n\t\t}\n\t}\n\tfprintf(fout, \"\\n\");\n\tfor (FPKMTrackingTable::const_iterator itr = tracking.begin(); itr != tracking.end(); ++itr)\n\t{\n\t\tconst string& description = itr->first;\n\t\tconst FPKMTracking& track = itr->second;\n\t\tconst vector<FPKMContext>& fpkms = track.fpkm_series;\n\t\t\n        AbundanceStatus status = NUMERIC_OK;\n        BOOST_FOREACH (const FPKMContext& c, fpkms)\n        {\n            if (c.status == NUMERIC_FAIL)\n                status = NUMERIC_FAIL;\n        }\n        \n        fprintf(fout, \"%s\", \n                description.c_str());\n        \n\t\tfor (size_t i = 0; i < fpkms.size(); ++i)\n\t\t{\n            const char* status_str = \"OK\";\n            \n            if (fpkms[i].status == NUMERIC_OK)\n            {\n                status_str = \"OK\";\n            }\n            else if (fpkms[i].status == NUMERIC_FAIL)\n            {\n                status_str = \"FAIL\";\n            }\n            else if (fpkms[i].status == NUMERIC_LOW_DATA)\n            {\n                status_str = \"LOWDATA\";\n            }\n            else if (fpkms[i].status == NUMERIC_HI_DATA)\n            {\n                status_str = \"HIDATA\";\n            }\n            else\n            {\n                assert(false);\n            }\n            \n            double external_counts = fpkms[i].count_mean;\n            double external_count_var = fpkms[i].count_var;\n            double uncertainty_var = fpkms[i].count_uncertainty_var;\n            double dispersion_var = fpkms[i].count_dispersion_var;\n\t\t\tfprintf(fout, \"\\t%lg\\t%lg\\t%lg\\t%lg\\t%s\", external_counts, external_count_var, uncertainty_var, dispersion_var, status_str);\n\t\t}\n\t\t\n\t\tfprintf(fout, \"\\n\");\n\t}\n}\n\nvoid print_read_group_tracking(FILE* fout, \n                               const FPKMTrackingTable& tracking)\n{\n\tfprintf(fout,\"tracking_id\\tcondition\\treplicate\\traw_frags\\tinternal_scaled_frags\\texternal_scaled_frags\\tFPKM\\teffective_length\\tstatus\");\n\t\n\tfprintf(fout, \"\\n\");\n\tfor (FPKMTrackingTable::const_iterator itr = tracking.begin(); itr != tracking.end(); ++itr)\n\t{\n\t\tconst string& description = itr->first;\n\t\tconst FPKMTracking& track = itr->second;\n\t\tconst vector<FPKMContext>& fpkms = track.fpkm_series;\n                \n\t\tfor (size_t i = 0; i < fpkms.size(); ++i)\n\t\t{\n            for (size_t j = 0; j != fpkms[i].tracking_info_per_rep.size();\n                 ++j)\n            { \n                double FPKM = fpkms[i].tracking_info_per_rep[j].fpkm;\n                double internal_count = fpkms[i].tracking_info_per_rep[j].count;\n                double external_count = internal_count / fpkms[i].tracking_info_per_rep[j].rg_props->external_scale_factor();\n                double raw_count = internal_count * fpkms[i].tracking_info_per_rep[j].rg_props->internal_scale_factor();\n                const  string& condition_name = fpkms[i].tracking_info_per_rep[j].rg_props->condition_name();\n                AbundanceStatus status = fpkms[i].tracking_info_per_rep[j].status;\n                \n                int rep_num = fpkms[i].tracking_info_per_rep[j].rg_props->replicate_num();\n                \n                const char* status_str = \"OK\";\n                \n                if (status == NUMERIC_OK)\n                {\n                    status_str = \"OK\";\n                }\n                else if (status == NUMERIC_FAIL)\n                {\n                    status_str = \"FAIL\";\n                }\n                else if (status == NUMERIC_LOW_DATA)\n                {\n                    status_str = \"LOWDATA\";\n                }\n                else if (status == NUMERIC_HI_DATA)\n                {\n                    status_str = \"HIDATA\";\n                }\n                else\n                {\n                    assert(false);\n                }\n                \n                fprintf(fout, \"%s\\t%s\\t%d\\t%lg\\t%lg\\t%lg\\t%lg\\t%s\\t%s\\n\",\n                        description.c_str(),\n                        condition_name.c_str(),\n                        rep_num,\n                        raw_count,\n                        internal_count,\n                        external_count,\n                        FPKM,\n                        \"-\",\n                        status_str);\n            }\n\t\t}\n\t}\n}\n\nvoid print_read_group_info(FILE* fout, \n                           const vector<boost::shared_ptr<ReadGroupProperties> >& all_read_groups)\n{\n    fprintf(fout, \"file\\tcondition\\treplicate_num\\ttotal_mass\\tnorm_mass\\tinternal_scale\\texternal_scale\\n\");\n    for (size_t i = 0; i < all_read_groups.size(); ++i)\n    {\n        boost::shared_ptr<ReadGroupProperties const> rg_props = all_read_groups[i];\n        fprintf(fout, \"%s\\t%s\\t%d\\t%Lg\\t%Lg\\t%lg\\t%lg\\n\",\n                rg_props->file_path().c_str(),\n                rg_props->condition_name().c_str(),\n                rg_props->replicate_num(),\n                rg_props->total_map_mass(),\n                rg_props->normalized_map_mass(),\n                rg_props->internal_scale_factor(),\n                rg_props->external_scale_factor());\n                \n    }\n}\n\nvoid print_run_info(FILE* fout)\n{\n    fprintf(fout, \"param\\tvalue\\n\");\n    fprintf(fout, \"cmd_line\\t%s\\n\", cmd_str.c_str());\n    fprintf(fout, \"version\\t%s\\n\", PACKAGE_VERSION);\n    fprintf(fout, \"SVN_revision\\t%s\\n\",SVN_REVISION); \n    fprintf(fout, \"boost_version\\t%d\\n\", BOOST_VERSION);\n}\n\nbool p_value_lt(const SampleDifference* lhs, const SampleDifference* rhs)\n{\n\treturn lhs->p_value < rhs->p_value;\n}\n\n// Benjamani-Hochberg procedure\nint fdr_significance(double fdr, \n                     vector<SampleDifference*>& tests)\n{\n\tsort(tests.begin(), tests.end(), p_value_lt);\n\tvector<SampleDifference*> passing;\n    \n\tfor (int k = 0; k < (int)tests.size(); ++k)\n\t{\n\t\tif (tests[k]->test_status == OK)\n\t\t{\n\t\t\tpassing.push_back(tests[k]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttests[k]->significant = false;\n\t\t}\n\t}\n\tint significant = 0;\n\tfloat pmin=1;\n\tint n = (int) passing.size();\n    //use the same procedure as p.adjust(...,\"BH\") in R\n\tfor (int k = n-1; k >= 0; k--)\n\t{\n\t\tdouble corrected_p = (double) passing[k]->p_value * ((double) n/(double) (k+1));\n        //make sure that no entry with lower p-value will get higher q-value than any entry with higher p-value\n\t\tif (corrected_p < pmin) \n\t\t{\n\t\t\tpmin = corrected_p;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcorrected_p = pmin;\n\t\t}\n        // make sure that the q-value is always <= 1 \n\t\tpassing[k]->corrected_p = (corrected_p < 1 ? corrected_p : 1); \n\t\tpassing[k]->significant = (corrected_p <= fdr);\n        significant += passing[k]->significant;\n\t}\n    \n\treturn passing.size();\n}\n\n\nvoid extract_sample_diffs(SampleDiffs& diff_map,\n\t\t\t\t\t\t  vector<SampleDifference*>& diffs)\n{\n\tfor (SampleDiffs::iterator itr = diff_map.begin();\n\t\t itr != diff_map.end();\n\t\t ++itr)\n\t{\n\t\tdiffs.push_back(&(itr->second));\n\t}\n}\n\n#if ENABLE_THREADS\nboost::mutex inspect_lock;\n#endif\n\nvoid inspect_map_worker(ReplicatedBundleFactory& fac,\n                        int& tmp_min_frag_len, \n                        int& tmp_max_frag_len,\n                        IdToLocusMap& id_to_locus_map)\n{\n#if ENABLE_THREADS\n\tboost::this_thread::at_thread_exit(decr_pool_count);\n#endif\n    \n    int min_f = std::numeric_limits<int>::max();\n    int max_f = 0;\n    \n    fac.inspect_replicate_maps(min_f, max_f, id_to_locus_map);\n    \n#if ENABLE_THREADS\n    inspect_lock.lock();\n#endif\n    tmp_min_frag_len = min(min_f, tmp_min_frag_len);\n    tmp_max_frag_len = max(max_f, tmp_max_frag_len);\n#if ENABLE_THREADS\n    inspect_lock.unlock();\n#endif\n}\n\nvoid learn_bias_worker(boost::shared_ptr<BundleFactory> fac)\n{\n#if ENABLE_THREADS\n\tboost::this_thread::at_thread_exit(decr_pool_count);\n#endif\n\tboost::shared_ptr<ReadGroupProperties> rg_props = fac->read_group_properties();\n\tBiasLearner* bl = new BiasLearner(rg_props->frag_len_dist());\n\tlearn_bias(*fac, *bl, false);\n\trg_props->bias_learner(boost::shared_ptr<BiasLearner>(bl));\n}\n\n\nboost::shared_ptr<TestLauncher> test_launcher;\n\nbool quantitate_next_locus(const RefSequenceTable& rt,\n                           vector<boost::shared_ptr<ReplicatedBundleFactory> >& bundle_factories,\n                           boost::shared_ptr<TestLauncher> launcher)\n{\n    for (size_t i = 0; i < bundle_factories.size(); ++i)\n    {\n        boost::shared_ptr<SampleAbundances> s_ab = boost::shared_ptr<SampleAbundances>(new SampleAbundances);\n        \n#if ENABLE_THREADS\t\t\t\t\t\n        while(1)\n        {\n            locus_thread_pool_lock.lock();\n            if (locus_curr_threads < locus_num_threads)\n            {\n                break;\n            }\n            \n            locus_thread_pool_lock.unlock();\n            \n            boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n            \n        }\n        \n        locus_curr_threads++;\n        locus_thread_pool_lock.unlock();\n        \n        boost::shared_ptr<HitBundle> pBundle = boost::shared_ptr<HitBundle>(new HitBundle());\n        bool non_empty = bundle_factories[i]->next_bundle(*pBundle, true);\n        \n        if (pBundle->compatible_mass() > 0)\n        {\n            thread quantitate(sample_worker,\n                              non_empty,\n                              pBundle,\n                              boost::ref(rt),\n                              boost::ref(*(bundle_factories[i])),\n                              s_ab,\n                              i,\n                              launcher,\n                              true);\n        }\n        else\n        {\n            sample_worker(non_empty,\n                          pBundle,\n                          boost::ref(rt),\n                          boost::ref(*(bundle_factories[i])),\n                          s_ab,\n                          i,\n                          launcher,\n                          true);\n            locus_thread_pool_lock.lock();\n            locus_curr_threads--;\n            locus_thread_pool_lock.unlock();\n        }\n#else\n        HitBundle bundle;\n        bool non_empty = sample_factory.next_bundle(bundle);\n        \n        sample_worker(non_emtpy,\n                      pBundle,\n                      boost::ref(rt),\n                      boost::ref(*(bundle_factories[i])),\n                      s_ab,\n                      i,\n                      launcher,\n                      true);\n#endif\n    }\n    return true;\n}\n\nvoid parse_contrast_file(FILE* contrast_file,\n                         const vector<boost::shared_ptr<ReplicatedBundleFactory> >& factories,\n                         vector<pair<size_t, size_t > >& contrasts)\n{\n    \n    char pBuf[10 * 1024];\n    size_t non_blank_lines_read = 0;\n    \n    map<string, pair<string, string> > contrast_table;\n    map<string, size_t > factor_name_to_factory_idx;\n    \n    for (size_t j = 0; j < factories.size(); ++j)\n    {\n        string factor_name = factories[j]->condition_name();\n        if (factor_name_to_factory_idx.find(factor_name) != factor_name_to_factory_idx.end())\n        {\n            fprintf(stderr, \"Error in contrast file: condition names must be unique! (%s is duplicated)\", factor_name.c_str());\n            exit(1);\n        }\n        factor_name_to_factory_idx[factor_name] = j;\n    }\n    \n    while (fgets(pBuf, 10*1024, contrast_file))\n    {\n        if (strlen(pBuf) > 0)\n        {\n            char* nl = strchr(pBuf, '\\n');\n            if (nl)\n                *nl = 0;\n            \n            string pBufstr = pBuf;\n            string trimmed = boost::trim_copy(pBufstr);\n            \n            if (trimmed.length() > 0 && trimmed[0] != '#')\n            {\n                non_blank_lines_read++;\n                vector<string> columns;\n                tokenize(trimmed, \"\\t\", columns);\n                \n                if (non_blank_lines_read == 1)\n                    continue;\n                \n                if (columns.size() < 2)\n                {\n                    if (columns.size() > 0)\n                        fprintf(stderr, \"Malformed record in contrast file: \\n   >  %s\\n\", pBuf);\n                    else\n                        continue;\n                }\n                \n                string factor_1 = columns[0];\n                string factor_2 = columns[1];\n                \n                if (columns.size() >= 3)\n                {\n                    string contrast_name = columns[2];\n                    contrast_table.insert(make_pair(contrast_name, make_pair(factor_1, factor_2)));\n                }\n                else\n                {\n                    char contrast_name[1024];\n                    sprintf(contrast_name, \"contrast_%lu\", contrast_table.size());\n                    contrast_table.insert(make_pair(contrast_name, make_pair(factor_1, factor_2)));\n                }\n            }\n        }\n    }\n    \n    for (map<string, pair<string, string> >::const_iterator itr = contrast_table.begin();\n         itr != contrast_table.end(); ++itr)\n    {\n        string factor_1 = itr->second.first;\n        map<string, size_t >::iterator f1_itr = factor_name_to_factory_idx.find(factor_1);\n        if (f1_itr == factor_name_to_factory_idx.end())\n        {\n            fprintf (stderr, \"Error: condition %s not found among samples\\n\", factor_1.c_str());\n            exit(1);\n        }\n        size_t f1_idx = f1_itr->second;\n        \n        string factor_2 = itr->second.second;\n        map<string, size_t >::iterator f2_itr = factor_name_to_factory_idx.find(factor_2);\n        if (f2_itr == factor_name_to_factory_idx.end())\n        {\n            fprintf (stderr, \"Error: condition %s not found among samples\\n\", factor_2.c_str());\n            exit(1);\n        }\n        size_t f2_idx = f2_itr->second;\n        contrasts.push_back(make_pair(f2_idx, f1_idx));\n    }\n }\n\nvoid parse_sample_sheet_file(FILE* sample_sheet_file,\n                             vector<string>& sample_labels,\n                             vector<string>& sam_hit_filename_lists)\n{\n    \n    char pBuf[10 * 1024];\n    size_t non_blank_lines_read = 0;\n    \n    sample_labels.clear();\n    \n    map<string, vector<string> > sample_groups;\n    \n    while (fgets(pBuf, 10*1024, sample_sheet_file))\n    {\n        if (strlen(pBuf) > 0)\n        {\n            char* nl = strchr(pBuf, '\\n');\n            if (nl)\n                *nl = 0;\n            \n            string pBufstr = pBuf;\n            string trimmed = boost::trim_copy(pBufstr);\n            \n            if (trimmed.length() > 0 && trimmed[0] != '#')\n            {\n                non_blank_lines_read++;\n                vector<string> columns;\n                tokenize(trimmed, \"\\t\", columns);\n                \n                if (non_blank_lines_read == 1)\n                    continue;\n                \n                if (columns.size() < 2)\n                {\n                    if (columns.size() > 0)\n                        fprintf(stderr, \"Malformed record in sample sheet: \\n   >  %s\\n\", pBuf);\n                    else\n                        continue;\n                }\n                \n                string sam_file = columns[0];\n                string sample_group = columns[1];\n                \n                pair<map<string, vector<string> >::iterator, bool> inserted = sample_groups.insert(make_pair(sample_group, vector<string>()));\n                inserted.first->second.push_back(sam_file);\n            }\n        }\n    }\n    \n    for (map<string, vector<string> >::iterator itr = sample_groups.begin();\n         itr != sample_groups.end(); ++itr)\n    {\n        sample_labels.push_back(itr->first);\n        string sam_list = boost::join(itr->second, \",\");\n        sam_hit_filename_lists.push_back(sam_list);\n    }\n}\n\n\nvoid init_default_contrasts(const vector<boost::shared_ptr<ReplicatedBundleFactory> >& factories,\n                            bool samples_are_time_series,\n                            vector<pair<size_t, size_t > >& contrasts)\n{\n    \n    for (size_t i = 1; i < factories.size(); ++i)\n    {\n        //bool multi_transcript_locus = samples[i]->transcripts.abundances().size() > 1;\n\n        int sample_to_start_test_against = 0;\n\n        if (samples_are_time_series)\n            sample_to_start_test_against = i - 1;\n\n        for (size_t j = sample_to_start_test_against; j < i; ++j)\n        {\n            contrasts.push_back(make_pair(i,j));\n        }\n    }\n}\n\nvoid parse_norm_standards_file(FILE* norm_standards_file)\n{\n    char pBuf[10 * 1024];\n    size_t non_blank_lines_read = 0;\n    \n    boost::shared_ptr<map<string, LibNormStandards> > norm_standards(new map<string, LibNormStandards>);\n    \n    while (fgets(pBuf, 10*1024, norm_standards_file))\n    {\n        if (strlen(pBuf) > 0)\n        {\n            char* nl = strchr(pBuf, '\\n');\n            if (nl)\n                *nl = 0;\n            \n            string pBufstr = pBuf;\n            string trimmed = boost::trim_copy(pBufstr);\n            \n            if (trimmed.length() > 0 && trimmed[0] != '#')\n            {\n                non_blank_lines_read++;\n                vector<string> columns;\n                tokenize(trimmed, \"\\t\", columns);\n                \n                if (non_blank_lines_read == 1)\n                    continue;\n                \n                if (columns.size() < 1) // \n                {\n                    continue;\n                }\n                \n                string gene_id = columns[0];\n                LibNormStandards L;\n                norm_standards->insert(make_pair(gene_id, L));\n            }\n        }\n    }\n    lib_norm_standards = norm_standards;\n}\n\n\nvoid print_variability_models(FILE* var_model_out, const vector<boost::shared_ptr<ReplicatedBundleFactory> >& factories)\n{\n\n    fprintf(var_model_out, \"condition\\tlocus\\tcompatible_count_mean\\tcompatible_count_var\\ttotal_count_mean\\ttotal_count_var\\tfitted_var\\n\");\n    \n    for (size_t i = 0; i < factories.size(); ++i)\n    {\n        string factor_name = factories[i]->condition_name();\n        boost::shared_ptr<ReadGroupProperties> rg = factories[i]->factories()[0]->read_group_properties();\n        boost::shared_ptr<MassDispersionModel const> model = rg->mass_dispersion_model();\n//        const vector<double>& means = model->scaled_compatible_mass_means();\n//        const vector<double>& raw_vars  = model->scaled_compatible_variances();\n        \n        const vector<LocusCount>& common_scale_compatible_counts = rg->common_scale_compatible_counts();\n        for (size_t j = 0; j < common_scale_compatible_counts.size(); ++j)\n        {\n            string locus_desc = common_scale_compatible_counts[j].locus_desc;\n            pair<double, double> compat_mean_and_var = model->get_compatible_mean_and_var(locus_desc);\n            pair<double, double> total_mean_and_var = model->get_total_mean_and_var(locus_desc);\n//            double total_compat_count = 0;\n//            if (itr != locus_to_total_count_table.end())\n//                total_compat_count = itr->second.count;\n            \n            \n            fprintf(var_model_out, \"%s\\t%s\\t%lg\\t%lg\\t%lg\\t%lg\\t%lg\\n\",\n                    factor_name.c_str(),\n                    locus_desc.c_str(),\n                    compat_mean_and_var.first,\n                    compat_mean_and_var.second,\n                    total_mean_and_var.first,\n                    total_mean_and_var.second,\n                    model->scale_mass_variance(compat_mean_and_var.first));\n        }\n    }\n    fclose(var_model_out);\n\n}\n\nstruct DispModelAverageContext\n{\n    double compatible_count_mean;\n    double total_count_mean;\n    double compatible_count_var;\n    double total_count_var;\n    \n    double fitted_var;\n    double weight;\n};\n\nvoid fit_dispersions(vector<boost::shared_ptr<ReplicatedBundleFactory> >& bundle_factories)\n{\n    if (dispersion_method == PER_CONDITION)\n    {\n        for (size_t i = 0; i < bundle_factories.size(); ++i)\n        {\n            bundle_factories[i]->fit_dispersion_model();\n        }\n    }\n    else if (dispersion_method == BLIND)\n    {\n        size_t num_samples = 0;\n        for (size_t cond_idx = 0; cond_idx < bundle_factories.size(); ++cond_idx)\n        {\n            const vector<boost::shared_ptr<BundleFactory> >& factories = bundle_factories[cond_idx]->factories();\n            for (size_t fac_idx = 0; fac_idx < factories.size(); ++fac_idx)\n            {\n                num_samples++;\n            }\n        }\n        vector<double> scale_factors;\n        \n        vector<LocusCountList> sample_compatible_count_table;\n        vector<LocusCountList> sample_total_count_table;\n        size_t curr_fac = 0;\n        for (size_t cond_idx = 0; cond_idx < bundle_factories.size(); ++cond_idx)\n        {\n            vector<boost::shared_ptr<BundleFactory> > factories = bundle_factories[cond_idx]->factories();\n            for (size_t fac_idx = 0; fac_idx < factories.size(); ++fac_idx)\n            {\n                boost::shared_ptr<BundleFactory> fac = factories[fac_idx];\n                \n                boost::shared_ptr<ReadGroupProperties> rg_props = fac->read_group_properties();\n                const vector<LocusCount>& compatible_count_table = rg_props->common_scale_compatible_counts();\n                const vector<LocusCount>& total_count_table = rg_props->common_scale_total_counts();\n                \n                for (size_t i = 0; i < compatible_count_table.size(); ++i)\n                {\n                    const LocusCount& c = compatible_count_table[i];\n                    double common_scale_compatible_count = c.count;\n                    double common_scale_total_count = total_count_table[i].count;\n                    \n                    if (i >= sample_compatible_count_table.size())\n                    {\n                        LocusCountList locus_count(c.locus_desc, num_samples, c.num_transcripts, c.gene_ids, c.gene_short_names);\n                        sample_compatible_count_table.push_back(locus_count);\n                        sample_compatible_count_table.back().counts[0] = common_scale_compatible_count;\n                        sample_total_count_table.push_back(locus_count);\n                        sample_total_count_table.back().counts[0] = common_scale_total_count;\n                    }\n                    else\n                    {\n                        if (sample_compatible_count_table[i].locus_desc != c.locus_desc)\n                        {\n                            fprintf (stderr, \"Error: bundle boundaries don't match across replicates!\\n\");\n                            exit(1);\n                        }\n                        sample_compatible_count_table[i].counts[curr_fac + fac_idx] = common_scale_compatible_count;\n                        sample_total_count_table[i].counts[curr_fac + fac_idx] = common_scale_total_count;\n                    }\n                }\n                scale_factors.push_back(rg_props->internal_scale_factor());\n                \n            }\n            \n            curr_fac += factories.size();\n        }\n\n        boost::shared_ptr<MassDispersionModel> disperser = fit_dispersion_model(\"blind\", scale_factors, sample_compatible_count_table);\n        \n        vector<pair<double, double> > compatible_means_and_vars;\n        calculate_count_means_and_vars(sample_compatible_count_table,\n                                       compatible_means_and_vars);\n        \n        for (size_t i = 0; i < sample_compatible_count_table.size(); ++i)\n        {\n            const LocusCountList& p = sample_compatible_count_table[i];\n            double mean = compatible_means_and_vars[i].first;\n            double var = compatible_means_and_vars[i].second;\n            disperser->set_compatible_mean_and_var(p.locus_desc, make_pair(mean, var));\n        }\n        \n        vector<pair<double, double> > total_means_and_vars;\n        calculate_count_means_and_vars(sample_total_count_table,\n                                       total_means_and_vars);\n        \n        for (size_t i = 0; i < sample_total_count_table.size(); ++i)\n        {\n            const LocusCountList& p = sample_compatible_count_table[i];\n            double mean = total_means_and_vars[i].first;\n            double var = total_means_and_vars[i].second;\n            disperser->set_total_mean_and_var(p.locus_desc, make_pair(mean, var));\n        }\n\n        for (size_t cond_idx = 0; cond_idx < bundle_factories.size(); ++cond_idx)\n        {\n            bundle_factories[cond_idx]->mass_dispersion_model(disperser);\n        }\n    }\n    else if (dispersion_method == POOLED)\n    {\n        for (size_t i = 0; i < bundle_factories.size(); ++i)\n        {\n            bundle_factories[i]->fit_dispersion_model();\n        }\n        // now need to replace them with the average\n        \n        boost::shared_ptr<MassDispersionModel> pooled_model;\n        // Let's compute the pooled average of the dispersion models\n        if (dispersion_method != BLIND)\n        {\n            vector<boost::shared_ptr<MassDispersionModel const> > disp_models;\n            double total_replicates = 0.0;\n            vector<double> disp_model_weight;\n            BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> fac, bundle_factories)\n            {\n                total_replicates += fac->num_replicates();\n            }\n            BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> fac, bundle_factories)\n            {\n                if (fac->num_replicates() > 1)\n                {\n                    disp_models.push_back(fac->mass_dispersion_model());\n                    disp_model_weight.push_back((double)fac->num_replicates() / total_replicates);\n                }\n            }\n            \n            double max_mass = 0.0;\n            \n            BOOST_FOREACH(boost::shared_ptr<MassDispersionModel const> disp, disp_models)\n            {\n                if (disp->scaled_compatible_mass_means().empty() == false && max_mass < disp->scaled_compatible_mass_means().back())\n                {\n                    max_mass = disp->scaled_compatible_mass_means().back();\n                }\n            }\n            \n            map<std::string, vector<DispModelAverageContext> > disp_info_by_locus;\n            for (size_t disp_idx = 0; disp_idx < disp_models.size(); ++disp_idx)\n            {\n                boost::shared_ptr<MassDispersionModel const> disp = disp_models[disp_idx];\n                \n                const std::map<std::string, std::pair<double, double> >& total_mv_by_locus = disp->total_mv_by_locus();\n                const std::map<std::string, std::pair<double, double> >& compatible_mv_by_locus = disp->compatible_mv_by_locus();\n                \n                for (map<std::string, std::pair<double, double> >::const_iterator itr = compatible_mv_by_locus.begin();\n                     itr != compatible_mv_by_locus.end(); ++itr)\n                {\n                                        \n                    std::map<std::string, std::pair<double, double> >::const_iterator total_itr = total_mv_by_locus.find(itr->first);\n                    if (total_itr == total_mv_by_locus.end())\n                        continue;\n                    \n                    pair<map<std::string, vector<DispModelAverageContext> >::iterator, bool> ins_pair =\n                    disp_info_by_locus.insert(make_pair(itr->first, vector<DispModelAverageContext>()));\n                    \n                    \n                    DispModelAverageContext ctx;\n                    ctx.compatible_count_mean = itr->second.first;\n                    ctx.compatible_count_var = itr->second.second;\n                    ctx.total_count_mean = total_itr->second.first;\n                    ctx.total_count_var = total_itr->second.second;\n                    if (use_compat_mass)\n                        ctx.fitted_var = disp->scale_mass_variance(ctx.compatible_count_mean);\n                    else\n                        ctx.fitted_var = disp->scale_mass_variance(ctx.total_count_mean);\n                    \n                    ctx.weight = disp_model_weight[disp_idx];\n                    \n                    ins_pair.first->second.push_back(ctx);\n                }\n            }\n            \n            map<string, DispModelAverageContext> pooled_info_by_locus;\n            \n            for (map<std::string, vector<DispModelAverageContext> >::const_iterator itr = disp_info_by_locus.begin();\n                 itr != disp_info_by_locus.end();\n                 ++itr)\n            {\n                DispModelAverageContext avg_ctx;\n                avg_ctx.compatible_count_mean = 0;\n                avg_ctx.compatible_count_var = 0;\n                avg_ctx.total_count_mean = 0;\n                avg_ctx.total_count_var = 0;\n                avg_ctx.fitted_var = 0;\n                \n                double total_weight = 0.0;\n                for (size_t i = 0; i < itr->second.size(); ++i)\n                {\n                    total_weight += itr->second[i].weight;\n                }\n                \n                for (size_t i = 0; i < itr->second.size(); ++i)\n                {\n                    avg_ctx.compatible_count_mean += (itr->second[i].weight / total_weight) * itr->second[i].compatible_count_mean;\n                    avg_ctx.compatible_count_var += (itr->second[i].weight / total_weight) * itr->second[i].compatible_count_var;\n                    avg_ctx.total_count_mean += (itr->second[i].weight / total_weight) * itr->second[i].total_count_mean;\n                    avg_ctx.total_count_var += (itr->second[i].weight / total_weight) * itr->second[i].total_count_var;\n                }\n                pooled_info_by_locus[itr->first] = avg_ctx;\n            }\n            \n            vector<double> compatible_mass;\n            vector<double> compatible_variances;\n            vector<double> est_fitted_var;\n            double epsilon = 0.2;\n            for (double frag_idx = 0.0; frag_idx < max_mass; frag_idx += epsilon)\n            {\n                compatible_mass.push_back(frag_idx);\n                double var_est = 0.0;\n                for(size_t i = 0; i < disp_models.size(); ++i)\n                {\n                    boost::shared_ptr<MassDispersionModel const> disp = disp_models[i];\n                    double weight = disp_model_weight[i];\n                    var_est += disp->scale_mass_variance(frag_idx) * weight;\n                }\n                compatible_variances.push_back(var_est);\n                est_fitted_var.push_back(var_est);\n            }\n            \n            pooled_model = boost::shared_ptr<MassDispersionModel>(new MassDispersionModel(\"pooled\", compatible_mass, compatible_variances, est_fitted_var));\n            \n            for (map<std::string, DispModelAverageContext>::iterator itr = pooled_info_by_locus.begin();\n                 itr != pooled_info_by_locus.end();\n                 ++itr)\n            {\n                const string& locus = itr->first;\n                pair<double, double> cmv = make_pair(itr->second.compatible_count_mean, itr->second.compatible_count_var);\n                pooled_model->set_compatible_mean_and_var(locus, cmv);\n\n                pair<double, double> tmv = make_pair(itr->second.total_count_mean, itr->second.total_count_var);\n                pooled_model->set_total_mean_and_var(locus, tmv);\n            }\n        }\n        \n        if (dispersion_method == POOLED)\n        {\n            BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> fac, bundle_factories)\n            {\n                fac->mass_dispersion_model(pooled_model);\n            }\n        }\n        \n        \n    }\n    else if (dispersion_method == POISSON)\n    {\n        boost::shared_ptr<MassDispersionModel> disperser = boost::shared_ptr<MassDispersionModel>(new PoissonDispersionModel(\"\"));\n        for (size_t i = 0; i < bundle_factories.size(); ++i)\n        {\n            bundle_factories[i]->mass_dispersion_model(disperser);\n        }\n\n    }\n    else\n    {\n        fprintf (stderr, \"Error: unknown dispersion method requested\\n\");\n    }\n}\n\nvoid driver(FILE* ref_gtf, FILE* mask_gtf, FILE* contrast_file, FILE* norm_standards_file, vector<string>& sam_hit_filename_lists, Outfiles& outfiles)\n{\n\n\tReadTable it;\n\tRefSequenceTable rt(true, false);\n    \n\tvector<boost::shared_ptr<Scaffold> > ref_mRNAs;\n\t\n\tvector<boost::shared_ptr<ReplicatedBundleFactory> > bundle_factories;\n    vector<boost::shared_ptr<ReadGroupProperties> > all_read_groups;\n    \n\tfor (size_t i = 0; i < sam_hit_filename_lists.size(); ++i)\n\t{\n        vector<string> sam_hit_filenames;\n        tokenize(sam_hit_filename_lists[i], \",\", sam_hit_filenames);\n        \n        vector<boost::shared_ptr<BundleFactory> > replicate_factories;\n        \n        string condition_name = sample_labels[i];\n        \n        for (size_t j = 0; j < sam_hit_filenames.size(); ++j)\n        {\n            boost::shared_ptr<HitFactory> hs;\n            boost::shared_ptr<BundleFactory> hf;\n            try\n            {\n                hs = boost::shared_ptr<HitFactory>(new PrecomputedExpressionHitFactory(sam_hit_filenames[j], it, rt));\n                hf = boost::shared_ptr<BundleFactory>(new PrecomputedExpressionBundleFactory(static_pointer_cast<PrecomputedExpressionHitFactory>(hs)));\n            }\n            \n            catch(boost::archive::archive_exception & e)\n            {\n\t\t\t\ths = boost::shared_ptr<HitFactory>(createSamHitFactory(sam_hit_filenames[j], it, rt));\n                hf = boost::shared_ptr<BundleFactory>(new BundleFactory(hs, REF_DRIVEN));\n            }\n            \n            \n            boost::shared_ptr<ReadGroupProperties> rg_props(new ReadGroupProperties);\n            \n            if (global_read_properties)\n            {\n                *rg_props = *global_read_properties;\n            }\n            else \n            {\n                *rg_props = hs->read_group_properties();\n            }\n            \n            rg_props->checked_parameters(hs->read_group_properties().checked_parameters());\n            rg_props->condition_name(condition_name);\n            rg_props->replicate_num(j);\n            rg_props->file_path(sam_hit_filenames[j]);\n            \n            all_read_groups.push_back(rg_props);\n            \n            hf->read_group_properties(rg_props);\n            \n            replicate_factories.push_back(hf);\n            //replicate_factories.back()->set_ref_rnas(ref_mRNAs);\n        }\n        \n        bundle_factories.push_back(boost::shared_ptr<ReplicatedBundleFactory>(new ReplicatedBundleFactory(replicate_factories, condition_name)));\n\t}\n    \n    boost::crc_32_type ref_gtf_crc_result;\n    ::load_ref_rnas(ref_gtf, rt, ref_mRNAs, ref_gtf_crc_result, corr_bias, false);\n    if (ref_mRNAs.empty())\n        return;\n    \n    vector<boost::shared_ptr<Scaffold> > mask_rnas;\n    if (mask_gtf)\n    {\n        boost::crc_32_type mask_gtf_crc_result;\n        ::load_ref_rnas(mask_gtf, rt, mask_rnas, mask_gtf_crc_result, false, false);\n    }\n    \n    BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> fac, bundle_factories)\n    {\n        fac->set_ref_rnas(ref_mRNAs);\n        if (mask_gtf) \n            fac->set_mask_rnas(mask_rnas);\n    }\n    \n    vector<pair<size_t, size_t > > contrasts;\n    if (contrast_file != NULL)\n    {\n        parse_contrast_file(contrast_file, bundle_factories, contrasts);\n    }\n    else\n    {\n        init_default_contrasts(bundle_factories, samples_are_time_series, contrasts);\n    }\n    \n    if (norm_standards_file != NULL)\n    {\n        parse_norm_standards_file(norm_standards_file);\n    }\n    \n    validate_cross_sample_parameters(all_read_groups);\n    \n#if ENABLE_THREADS\n    locus_num_threads = num_threads;\n#endif\n    \n    // Validate the dispersion method the user's chosen.\n    int most_reps = -1;\n    int most_reps_idx = 0;\n    \n    bool single_replicate_fac = false;\n    \n    for (size_t i = 0; i < bundle_factories.size(); ++i)\n    {\n        ReplicatedBundleFactory& fac = *(bundle_factories[i]);\n        if (fac.num_replicates() > most_reps)\n        {\n            most_reps = fac.num_replicates();\n            most_reps_idx = i;\n        }\n        if (most_reps == 1)\n        {\n            single_replicate_fac = true;\n            if (dispersion_method == PER_CONDITION)\n            {\n                fprintf(stderr, \"Error: Dispersion method 'per-condition' requires that all conditions have at least 2 replicates.  Please use either 'pooled' or 'blind'\\n\");\n                exit(1);\n            }\n        }\n    }\n    \n    if (most_reps == 1 && (dispersion_method != BLIND || dispersion_method != POISSON))\n    {\n        fprintf(stderr, \"Warning: No conditions are replicated, switching to 'blind' dispersion method\\n\");\n        dispersion_method = BLIND;\n    }\n\n    \n    //bool pool_all_samples = ((most_reps <= 1 && dispersion_method == NOT_SET) || dispersion_method == BLIND);\n    \n    \n\tint tmp_min_frag_len = numeric_limits<int>::max();\n\tint tmp_max_frag_len = 0;\n\t\n\tProgressBar p_bar(\"Inspecting maps and determining fragment length distributions.\",0);\n    \n    IdToLocusMap id_to_locus_map(boost::shared_ptr<map<string, set<string> > >(new map<string, set<string> >()));\n\tBOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> fac, bundle_factories)\n    {\n#if ENABLE_THREADS\t\n        while(1)\n        {\n            locus_thread_pool_lock.lock();\n            if (locus_curr_threads < locus_num_threads)\n            {\n                break;\n            }\n            \n            locus_thread_pool_lock.unlock();\n            \n            boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n        }\n        \n        locus_curr_threads++;\n        locus_thread_pool_lock.unlock();\n        \n        thread inspect(inspect_map_worker,\n                       boost::ref(*fac),\n                       boost::ref(tmp_min_frag_len),\n                       boost::ref(tmp_max_frag_len),\n                       boost::ref(id_to_locus_map));\n#else\n        inspect_map_worker(boost::ref(*fac),\n                           boost::ref(tmp_min_frag_len),\n                           boost::ref(tmp_max_frag_len),\n                           id_to_locus_map);\n#endif\n    }\n    \n    // wait for the workers to finish up before reporting everthing.\n#if ENABLE_THREADS\t\n    while(1)\n    {\n        locus_thread_pool_lock.lock();\n        if (locus_curr_threads == 0)\n        {\n            locus_thread_pool_lock.unlock();\n            break;\n        }\n        locus_thread_pool_lock.unlock();\n        \n        boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n    }\n#endif\n    \n    normalize_counts(all_read_groups);\n    fit_dispersions(bundle_factories);\n \n    print_variability_models(outfiles.var_model_out, bundle_factories);\n    \n    for (size_t i = 0; i < all_read_groups.size(); ++i)\n    {\n        boost::shared_ptr<ReadGroupProperties> rg = all_read_groups[i];\n        fprintf(stderr, \"> Map Properties:\\n\");\n        \n        fprintf(stderr, \">\\tNormalized Map Mass: %.2Lf\\n\", rg->normalized_map_mass());\n        fprintf(stderr, \">\\tRaw Map Mass: %.2Lf\\n\", rg->total_map_mass());\n        if (corr_multi)\n            fprintf(stderr,\">\\tNumber of Multi-Reads: %zu (with %zu total hits)\\n\", rg->multi_read_table()->num_multireads(), rg->multi_read_table()->num_multihits()); \n        \n        if (rg->frag_len_dist()->source() == LEARNED)\n        {\n            fprintf(stderr, \">\\tFragment Length Distribution: Empirical (learned)\\n\");\n            fprintf(stderr, \">\\t              Estimated Mean: %.2f\\n\", rg->frag_len_dist()->mean());\n            fprintf(stderr, \">\\t           Estimated Std Dev: %.2f\\n\", rg->frag_len_dist()->std_dev());\n        }\n        else\n        {\n            if (rg->frag_len_dist()->source() == USER)\n                fprintf(stderr, \">\\tFragment Length Distribution: Truncated Gaussian (user-specified)\\n\");\n            else //rg->frag_len_dist()->source == FLD::DEFAULT\n                fprintf(stderr, \">\\tFragment Length Distribution: Truncated Gaussian (default)\\n\");\n            fprintf(stderr, \">\\t              Default Mean: %d\\n\", def_frag_len_mean);\n            fprintf(stderr, \">\\t           Default Std Dev: %d\\n\", def_frag_len_std_dev);\n        }\n    }\n    \n    long double total_norm_mass = 0.0;\n    long double total_mass = 0.0;\n    BOOST_FOREACH (boost::shared_ptr<ReadGroupProperties> rg_props, all_read_groups)\n    {\n        total_norm_mass += rg_props->normalized_map_mass();\n        total_mass += rg_props->total_map_mass();\n    }\n\n\tmin_frag_len = tmp_min_frag_len;\n    max_frag_len = tmp_max_frag_len;\n\t\n\tfinal_est_run = false;\n\t\n\tdouble num_bundles = (double)bundle_factories[0]->num_bundles();\n\t\n//    if (corr_bias && corr_multi)\n//        p_bar = ProgressBar(\"Calculating initial abundance estimates for bias and multi-read correction.\", num_bundles);\n//    else if (corr_bias)\n//        p_bar = ProgressBar(\"Calculating initial abundance estimates for bias correction.\", num_bundles);\n//    else if (corr_multi)\n//        p_bar = ProgressBar(\"Calculating initial abundance estimates for multi-read correction.\", num_bundles);\n//    else\n    \n    p_bar = ProgressBar(\"Calculating preliminary abundance estimates\", num_bundles);\n    \n    Tracking tracking;\n    \n    test_launcher = boost::shared_ptr<TestLauncher>(new TestLauncher(bundle_factories.size(), contrasts, NULL, &tracking, &p_bar, true));\n    \n\tif (model_mle_error || corr_bias || corr_multi) // Only run initial estimation if correcting bias or multi-reads\n\t{\n\t\twhile (1) \n\t\t{\n\t\t\tboost::shared_ptr<vector<boost::shared_ptr<SampleAbundances> > > abundances(new vector<boost::shared_ptr<SampleAbundances> >());\n\t\t\tquantitate_next_locus(rt, bundle_factories, test_launcher);\n\t\t\tbool more_loci_remain = false;\n            BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories) \n            {\n                if (rep_fac->bundles_remain())\n                {\n                    more_loci_remain = true;\n                    break;\n                }\n            }\n            \n\t\t\tif (!more_loci_remain)\n            {\n                // wait for the workers to finish up before breaking out.\n#if ENABLE_THREADS\t\n                while(1)\n                {\n                    locus_thread_pool_lock.lock();\n                    if (locus_curr_threads == 0)\n                    {\n                        locus_thread_pool_lock.unlock();\n                        break;\n                    }\n                    \n                    locus_thread_pool_lock.unlock();\n                    \n                    boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n                    \n                }\n#endif\n\t\t\t\tbreak;\n            }\n\t\t}\n        \n        BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories)\n\t\t{\n\t\t\trep_fac->reset();\n        }\n        \n\t\tp_bar.complete();\n\t}\n    if (corr_bias)\n    {\n        bias_run = true;\n        p_bar = ProgressBar(\"Learning bias parameters.\", 0);\n\t\tBOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories)\n\t\t{\n\t\t\tBOOST_FOREACH (boost::shared_ptr<BundleFactory> fac, rep_fac->factories())\n\t\t\t{\n#if ENABLE_THREADS\t\n\t\t\t\twhile(1)\n\t\t\t\t{\n\t\t\t\t\tlocus_thread_pool_lock.lock();\n\t\t\t\t\tif (locus_curr_threads < locus_num_threads)\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tlocus_thread_pool_lock.unlock();\n\t\t\t\t\t\n\t\t\t\t\tboost::this_thread::sleep(boost::posix_time::milliseconds(5));\n\t\t\t\t}\n\t\t\t\tlocus_curr_threads++;\n\t\t\t\tlocus_thread_pool_lock.unlock();\n\t\t\t\t\n\t\t\t\tthread bias(learn_bias_worker, fac);\n#else\n\t\t\t\tlearn_bias_worker(fac);\n#endif\n\t\t\t}\n    \t}\n    \n    // wait for the workers to finish up before reporting everthing.\n#if ENABLE_THREADS\t\n\t\twhile(1)\n\t\t{\n\t\t\tlocus_thread_pool_lock.lock();\n\t\t\tif (locus_curr_threads == 0)\n\t\t\t{\n\t\t\t\tlocus_thread_pool_lock.unlock();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tlocus_thread_pool_lock.unlock();\n\t\t\t\n\t\t\tboost::this_thread::sleep(boost::posix_time::milliseconds(5));\n\t\t}\n#endif\n        BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories)\n\t\t{\n\t\t\trep_fac->reset();\n        }\n        bias_run = false;\n\t}\n    \n    fprintf(outfiles.bias_out, \"condition_name\\treplicate_num\\tparam\\tpos_i\\tpos_j\\tvalue\\n\");\n    BOOST_FOREACH (boost::shared_ptr<ReadGroupProperties> rg_props, all_read_groups)\n    {\n        if (rg_props->bias_learner())\n            rg_props->bias_learner()->output(outfiles.bias_out, rg_props->condition_name(), rg_props->replicate_num());\n    }\n    \n    \n    // Allow the multiread tables to do their thing...\n    BOOST_FOREACH (boost::shared_ptr<ReadGroupProperties> rg_props, all_read_groups)\n    {\n        rg_props->multi_read_table()->valid_mass(true);\n    }\n    \n    test_launcher->clear_tracking_data();\n\t\n\tTests tests;\n    \n    int N = (int)sam_hit_filename_lists.size();\n    \n    tests.isoform_de_tests = vector<vector<SampleDiffs> >(N);\n    tests.tss_group_de_tests = vector<vector<SampleDiffs> >(N);\n    tests.gene_de_tests = vector<vector<SampleDiffs> >(N);\n    tests.cds_de_tests = vector<vector<SampleDiffs> >(N);\n    tests.diff_splicing_tests = vector<vector<SampleDiffs> >(N);\n    tests.diff_promoter_tests = vector<vector<SampleDiffs> >(N);\n    tests.diff_cds_tests = vector<vector<SampleDiffs> >(N);\n    \n\tfor (int i = 0; i < N; ++i)\n    {\n        tests.isoform_de_tests[i] = vector<SampleDiffs>(N);\n        tests.tss_group_de_tests[i] = vector<SampleDiffs>(N);\n        tests.gene_de_tests[i] = vector<SampleDiffs>(N);\n        tests.cds_de_tests[i] = vector<SampleDiffs>(N);\n        tests.diff_splicing_tests[i] = vector<SampleDiffs>(N);\n        tests.diff_promoter_tests[i] = vector<SampleDiffs>(N);\n        tests.diff_cds_tests[i] = vector<SampleDiffs>(N);\n    }\n\t\n\tfinal_est_run = true;\n\tp_bar = ProgressBar(\"Testing for differential expression and regulation in locus.\", num_bundles);\n                                                     \n    test_launcher = boost::shared_ptr<TestLauncher>(new TestLauncher(bundle_factories.size(), contrasts, &tests, &tracking, &p_bar));\n                                                                                              \n\twhile (true)\n\t{\n        //boost::shared_ptr<vector<boost::shared_ptr<SampleAbundances> > > abundances(new vector<boost::shared_ptr<SampleAbundances> >());\n        quantitate_next_locus(rt, bundle_factories, test_launcher);\n        bool more_loci_remain = false;\n        BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories) \n        {\n            if (rep_fac->bundles_remain())\n            {\n                more_loci_remain = true;\n                break;\n            }\n        }\n        if (!more_loci_remain)\n        {\n            // wait for the workers to finish up before doing the cross-sample testing.\n#if ENABLE_THREADS\t\n            while(1)\n            {\n                locus_thread_pool_lock.lock();\n                if (locus_curr_threads == 0)\n                {\n                    locus_thread_pool_lock.unlock();\n                    break;\n                }\n                \n                locus_thread_pool_lock.unlock();\n                \n                boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n                \n            }\n#endif\n            break;\n        }\n    }\n\t\n\tp_bar.complete();\n\n\t//double FDR = 0.05;\n\tint total_iso_de_tests = 0;\n\t\n\tvector<SampleDifference*> isoform_exp_diffs;\n    fprintf(outfiles.isoform_de_outfile, \"test_id\\tgene_id\\tgene\\tlocus\\tsample_1\\tsample_2\\tstatus\\tvalue_1\\tvalue_2\\tlog2(fold_change)\\ttest_stat\\tp_value\\tq_value\\tsignificant\\n\");\n    \n\n    for (size_t i = 0; i < tests.isoform_de_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < i; ++j)\n        {\n            total_iso_de_tests += tests.isoform_de_tests[i][j].size();\n            extract_sample_diffs(tests.isoform_de_tests[i][j], isoform_exp_diffs);\n        }\n    }\n    \n    int iso_exp_tests = fdr_significance(FDR, isoform_exp_diffs);\n    fprintf(stderr, \"Performed %d isoform-level transcription difference tests\\n\", iso_exp_tests);\n    \n    for (size_t i = 0; i < tests.isoform_de_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < i; ++j)\n        {\n            print_tests(outfiles.isoform_de_outfile, sample_labels[j].c_str(), sample_labels[i].c_str(), tests.isoform_de_tests[i][j]);\n        }\n    }\n\n    \n\tint total_group_de_tests = 0;\n\tvector<SampleDifference*> tss_group_exp_diffs;\n    fprintf(outfiles.group_de_outfile, \"test_id\\tgene_id\\tgene\\tlocus\\tsample_1\\tsample_2\\tstatus\\tvalue_1\\tvalue_2\\tlog2(fold_change)\\ttest_stat\\tp_value\\tq_value\\tsignificant\\n\");\n    \n    for (size_t i = 0; i < tests.tss_group_de_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < i; ++j)\n        {\n            extract_sample_diffs(tests.tss_group_de_tests[i][j], tss_group_exp_diffs);\n            total_group_de_tests += tests.tss_group_de_tests[i][j].size();\n        }\n    }\n\n    int tss_group_exp_tests = fdr_significance(FDR, tss_group_exp_diffs);\n    fprintf(stderr, \"Performed %d tss-level transcription difference tests\\n\", tss_group_exp_tests);\n    \n    for (size_t i = 0; i < tests.tss_group_de_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < i; ++j)\n        {\n            print_tests(outfiles.group_de_outfile, sample_labels[j].c_str(), sample_labels[i].c_str(), tests.tss_group_de_tests[i][j]);\n        }\n    }\n\n\t\n\tint total_gene_de_tests = 0;\n\tvector<SampleDifference*> gene_exp_diffs;\n    fprintf(outfiles.gene_de_outfile, \"test_id\\tgene_id\\tgene\\tlocus\\tsample_1\\tsample_2\\tstatus\\tvalue_1\\tvalue_2\\tlog2(fold_change)\\ttest_stat\\tp_value\\tq_value\\tsignificant\\n\");\n\n    for (size_t i = 0; i < tests.gene_de_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < tests.gene_de_tests.size(); ++j)\n        {\n            total_gene_de_tests += tests.gene_de_tests[i][j].size();\n            extract_sample_diffs(tests.gene_de_tests[i][j], gene_exp_diffs);\n        }\n    }\n\n    //fprintf(stderr, \"***There are %lu difference records in gene_exp_diffs\\n\", gene_exp_diffs.size());\n    int gene_exp_tests = fdr_significance(FDR, gene_exp_diffs);\n    fprintf(stderr, \"Performed %d gene-level transcription difference tests\\n\", gene_exp_tests);\n    \n    for (size_t i = 0; i < tests.gene_de_tests.size(); ++i)\n    {        \n        for (size_t j = 0; j < tests.gene_de_tests.size(); ++j)\n        {\n            print_tests(outfiles.gene_de_outfile, sample_labels[j].c_str(), sample_labels[i].c_str(), tests.gene_de_tests[i][j]);\n        }\n    }\t\n\n    \n\tint total_cds_de_tests = 0;\n\tvector<SampleDifference*> cds_exp_diffs;\n    fprintf(outfiles.cds_de_outfile, \"test_id\\tgene_id\\tgene\\tlocus\\tsample_1\\tsample_2\\tstatus\\tvalue_1\\tvalue_2\\tlog2(fold_change)\\ttest_stat\\tp_value\\tq_value\\tsignificant\\n\");\n    \n\n    for (size_t i = 0; i < tests.cds_de_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < tests.cds_de_tests.size(); ++j)\n        {\n            total_cds_de_tests += tests.cds_de_tests[i][j].size();\n            extract_sample_diffs(tests.cds_de_tests[i][j], cds_exp_diffs);\n        }\n    }\n\n\n    int cds_exp_tests = fdr_significance(FDR, cds_exp_diffs);\n    fprintf(stderr, \"Performed %d CDS-level transcription difference tests\\n\", cds_exp_tests);\n    \n    for (size_t i = 0; i < tests.cds_de_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < tests.cds_de_tests.size(); ++j)\n        {\n            print_tests(outfiles.cds_de_outfile, sample_labels[j].c_str(), sample_labels[i].c_str(), tests.cds_de_tests[i][j]);\n        }\n    }\n\n    \n\tint total_diff_splice_tests = 0;\n\tvector<SampleDifference*> splicing_diffs;\n    fprintf(outfiles.diff_splicing_outfile, \"test_id\\tgene_id\\tgene\\tlocus\\tsample_1\\tsample_2\\tstatus\\tvalue_1\\tvalue_2\\tsqrt(JS)\\ttest_stat\\tp_value\\tq_value\\tsignificant\\n\");\n\n    for (size_t i = 0; i < tests.diff_splicing_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < tests.diff_splicing_tests.size(); ++j)\n        {\n            total_diff_splice_tests += tests.diff_splicing_tests[i][j].size();\n            extract_sample_diffs(tests.diff_splicing_tests[i][j], splicing_diffs);\n        }\n    }\n\n    int splicing_tests = fdr_significance(FDR, splicing_diffs);\n    fprintf(stderr, \"Performed %d splicing tests\\n\", splicing_tests);\n    \n    for (size_t i = 0; i < tests.diff_splicing_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < tests.diff_splicing_tests.size(); ++j)\n        {\n            const SampleDiffs& diffs = tests.diff_splicing_tests[i][j];\n            print_tests(outfiles.diff_splicing_outfile, sample_labels[j].c_str(), sample_labels[i].c_str(), diffs);\n        }\n    }\n\n    \n\tint total_diff_promoter_tests = 0;\n\tvector<SampleDifference*> promoter_diffs;\n    fprintf(outfiles.diff_promoter_outfile, \"test_id\\tgene_id\\tgene\\tlocus\\tsample_1\\tsample_2\\tstatus\\tvalue_1\\tvalue_2\\tsqrt(JS)\\ttest_stat\\tp_value\\tq_value\\tsignificant\\n\");\n\n    for (size_t i = 1; i < tests.diff_splicing_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < tests.diff_splicing_tests.size(); ++j)\n        {\n            total_diff_promoter_tests += tests.diff_promoter_tests[i][j].size();\n            extract_sample_diffs(tests.diff_promoter_tests[i][j], promoter_diffs);\n        }\n    }\n\n\n    int promoter_tests = fdr_significance(FDR, promoter_diffs);\n    fprintf(stderr, \"Performed %d promoter preference tests\\n\", promoter_tests);\n    \n    for (size_t i = 1; i < tests.diff_promoter_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < tests.diff_promoter_tests.size(); ++j)\n        {\n            print_tests(outfiles.diff_promoter_outfile, sample_labels[j].c_str(), sample_labels[i].c_str(), tests.diff_promoter_tests[i][j]);\n        }\n    }\n    \n\tint total_diff_cds_tests = 0;\n\tvector<SampleDifference*> cds_use_diffs;\n    fprintf(outfiles.diff_cds_outfile, \"test_id\\tgene_id\\tgene\\tlocus\\tsample_1\\tsample_2\\tstatus\\tvalue_1\\tvalue_2\\tsqrt(JS)\\ttest_stat\\tp_value\\tq_value\\tsignificant\\n\");\n    \n    for (size_t i = 1; i < tests.diff_cds_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < tests.diff_cds_tests.size(); ++j)\n        {\n            extract_sample_diffs(tests.diff_cds_tests[i][j], cds_use_diffs);\n            total_diff_cds_tests += tests.diff_cds_tests[i][j].size();\n        }\n    }\n\n\n    int cds_use_tests = fdr_significance(FDR, cds_use_diffs);\n    fprintf(stderr, \"Performing %d relative CDS output tests\\n\", cds_use_tests);\n    \n    for (size_t i = 1; i < tests.diff_cds_tests.size(); ++i)\n    {\n        for (size_t j = 0; j < tests.diff_cds_tests.size(); ++j)\n        {\n            print_tests(outfiles.diff_cds_outfile, sample_labels[j].c_str(), sample_labels[i].c_str(), tests.diff_cds_tests[i][j]);\n        }\n    }\n\n\t\n    // FPKM tracking\n    \n\tFILE* fiso_fpkm_tracking =  outfiles.isoform_fpkm_tracking_out;\n\tfprintf(stderr, \"Writing isoform-level FPKM tracking\\n\");\n\tprint_FPKM_tracking(fiso_fpkm_tracking,tracking.isoform_fpkm_tracking); \n\t\n\tFILE* ftss_fpkm_tracking =  outfiles.tss_group_fpkm_tracking_out;\n\tfprintf(stderr, \"Writing TSS group-level FPKM tracking\\n\");\n\tprint_FPKM_tracking(ftss_fpkm_tracking,tracking.tss_group_fpkm_tracking);\n\t\n\tFILE* fgene_fpkm_tracking =  outfiles.gene_fpkm_tracking_out;\n\tfprintf(stderr, \"Writing gene-level FPKM tracking\\n\");\n\tprint_FPKM_tracking(fgene_fpkm_tracking,tracking.gene_fpkm_tracking);\n\t\n\tFILE* fcds_fpkm_tracking =  outfiles.cds_fpkm_tracking_out;\n\tfprintf(stderr, \"Writing CDS-level FPKM tracking\\n\");\n\tprint_FPKM_tracking(fcds_fpkm_tracking,tracking.cds_fpkm_tracking);\n\n    // Count tracking\n    \n    FILE* fiso_count_tracking =  outfiles.isoform_count_tracking_out;\n\tfprintf(stderr, \"Writing isoform-level count tracking\\n\");\n\tprint_count_tracking(fiso_count_tracking,tracking.isoform_fpkm_tracking); \n\t\n\tFILE* ftss_count_tracking =  outfiles.tss_group_count_tracking_out;\n\tfprintf(stderr, \"Writing TSS group-level count tracking\\n\");\n\tprint_count_tracking(ftss_count_tracking,tracking.tss_group_fpkm_tracking);\n\t\n\tFILE* fgene_count_tracking =  outfiles.gene_count_tracking_out;\n\tfprintf(stderr, \"Writing gene-level count tracking\\n\");\n\tprint_count_tracking(fgene_count_tracking,tracking.gene_fpkm_tracking);\n\t\n\tFILE* fcds_count_tracking =  outfiles.cds_count_tracking_out;\n\tfprintf(stderr, \"Writing CDS-level count tracking\\n\");\n\tprint_count_tracking(fcds_count_tracking,tracking.cds_fpkm_tracking);\n    \n    // Read group tracking\n    \n    FILE* fiso_rep_tracking =  outfiles.isoform_rep_tracking_out;\n\tfprintf(stderr, \"Writing isoform-level read group tracking\\n\");\n\tprint_read_group_tracking(fiso_rep_tracking,tracking.isoform_fpkm_tracking); \n\t\n\tFILE* ftss_rep_tracking =  outfiles.tss_group_rep_tracking_out;\n\tfprintf(stderr, \"Writing TSS group-level read group tracking\\n\");\n\tprint_read_group_tracking(ftss_rep_tracking,tracking.tss_group_fpkm_tracking);\n\t\n\tFILE* fgene_rep_tracking =  outfiles.gene_rep_tracking_out;\n\tfprintf(stderr, \"Writing gene-level read group tracking\\n\");\n\tprint_read_group_tracking(fgene_rep_tracking,tracking.gene_fpkm_tracking);\n\t\n\tFILE* fcds_rep_tracking =  outfiles.cds_rep_tracking_out;\n\tfprintf(stderr, \"Writing CDS-level read group tracking\\n\");\n\tprint_read_group_tracking(fcds_rep_tracking,tracking.cds_fpkm_tracking);\n    \n    FILE* fread_group_info =  outfiles.read_group_info_out;\n\tfprintf(stderr, \"Writing read group info\\n\");\n\tprint_read_group_info(fread_group_info,all_read_groups);\n\n    FILE* frun_info =  outfiles.run_info_out;\n\tfprintf(stderr, \"Writing run info\\n\");\n\tprint_run_info(frun_info);\n}\n\nint main(int argc, char** argv)\n{\n    for (int i = 0; i < argc; ++i)\n    {\n        cmd_str += string(argv[i]) + \" \";\n    }\n    \n    init_library_table();\n    init_dispersion_method_table();\n    init_lib_norm_method_table();\n    \n    min_isoform_fraction = 1e-5;\n    \n\tint parse_ret = parse_options(argc,argv);\n    if (parse_ret)\n        return parse_ret;\n\t\n    if (!use_total_mass && !use_compat_mass)\n    {\n        use_total_mass = false;\n        use_compat_mass = true;   \n    }\n    \n\tif(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n    \n    if (!no_update_check)\n        check_version(PACKAGE_VERSION);\n    \n    string ref_gtf_filename = argv[optind++];\n    vector<string> sam_hit_filenames;\n    \n    if (use_sample_sheet)\n    {\n        if  (optind < argc)\n        {\n            \n            string sample_sheet_filename = argv[optind++];\n            FILE* sample_sheet_file = NULL;\n            if (sample_sheet_filename != \"\")\n            {\n                sample_sheet_file = fopen(sample_sheet_filename.c_str(), \"r\");\n                if (!sample_sheet_file)\n                {\n                    fprintf(stderr, \"Error: cannot open sample sheet file %s for reading\\n\",\n                            sample_sheet_filename.c_str());\n                    exit(1);\n                }\n            }\n            parse_sample_sheet_file(sample_sheet_file, sample_labels, sam_hit_filenames);\n        }\n        else\n        {\n            fprintf(stderr, \"Error: option --use-sample-sheet requires a single sample sheet filename instead of a list of SAM/BAM files\\n\");\n        }\n    }\n    else\n    {\n        while(optind < argc)\n        {\n            string sam_hits_file_name = argv[optind++];\n            sam_hit_filenames.push_back(sam_hits_file_name);\n        }\n        \n        if (sample_labels.size() == 0)\n        {\n            for (size_t i = 1; i < sam_hit_filenames.size() + 1; ++i)\n            {\n                char buf[256];\n                sprintf(buf, \"q%lu\", i);\n                sample_labels.push_back(buf);\n            }\n        }\n    }\n    \t\n\twhile (sam_hit_filenames.size() < 2)\n    {\n        fprintf(stderr, \"Error: cuffdiff requires at least 2 SAM files\\n\");\n        exit(1);\n    }\n\t\n    \n    if (sam_hit_filenames.size() != sample_labels.size())\n    {\n        fprintf(stderr, \"Error: number of labels must match number of conditions\\n\");\n        exit(1);\n    }\n    \n    if (random_seed == -1)\n        random_seed = boost::mt19937::default_seed;\n    \n\t// seed the random number generator - we'll need it for the importance\n\t// sampling during MAP estimation of the gammas\n\tsrand48(random_seed);\n\t\n\tFILE* ref_gtf = NULL;\n\tif (ref_gtf_filename != \"\")\n\t{\n\t\tref_gtf = fopen(ref_gtf_filename.c_str(), \"r\");\n\t\tif (!ref_gtf)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open reference GTF file %s for reading\\n\",\n\t\t\t\t\tref_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\t\n\tFILE* mask_gtf = NULL;\n\tif (mask_gtf_filename != \"\")\n\t{\n\t\tmask_gtf = fopen(mask_gtf_filename.c_str(), \"r\");\n\t\tif (!mask_gtf)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open mask GTF file %s for reading\\n\",\n\t\t\t\t\tmask_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\n\t\n    FILE* contrast_file = NULL;\n\tif (contrast_filename != \"\")\n\t{\n\t\tcontrast_file = fopen(contrast_filename.c_str(), \"r\");\n\t\tif (!contrast_file)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open contrast file %s for reading\\n\",\n\t\t\t\t\tcontrast_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\n    FILE* norm_standards_file = NULL;\n\tif (norm_standards_filename != \"\")\n\t{\n\t\tnorm_standards_file = fopen(norm_standards_filename.c_str(), \"r\");\n\t\tif (!norm_standards_file)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open contrast file %s for reading\\n\",\n\t\t\t\t\tnorm_standards_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n    \n\n\t// Note: we don't want the assembly filters interfering with calculations \n\t// here\n\t\n\tpre_mrna_fraction = 0.0;\n    olap_radius = 0;\n\t\n\tOutfiles outfiles;\n\t\n    if (output_dir != \"\")\n    {\n        int retcode = mkpath(output_dir.c_str(), 0777);\n        if (retcode == -1)\n        {\n            if (errno != EEXIST)\n            {\n                fprintf (stderr, \n                         \"Error: cannot create directory %s\\n\", \n                         output_dir.c_str());\n                exit(1);\n            }\n        }\n    }\n    \n    static const int filename_buf_size = 2048;\n    \n    char out_file_prefix[filename_buf_size];\n    sprintf(out_file_prefix, \"%s/\", output_dir.c_str());\n    char iso_out_file_name[filename_buf_size];\n    sprintf(iso_out_file_name, \"%sisoform_exp.diff\", out_file_prefix);\n    FILE* iso_out = fopen(iso_out_file_name, \"w\");\n    if (!iso_out)\n    {\n        fprintf(stderr, \"Error: cannot open differential isoform transcription file %s for writing\\n\",\n                iso_out_file_name);\n        exit(1);\n    }\n    \n    char group_out_file_name[filename_buf_size];\n    sprintf(group_out_file_name, \"%stss_group_exp.diff\", out_file_prefix);\n    FILE* group_out = fopen(group_out_file_name, \"w\");\n    if (!group_out)\n    {\n        fprintf(stderr, \"Error: cannot open differential TSS group transcription file %s for writing\\n\",\n                group_out_file_name);\n        exit(1);\n    }\n    \n    char gene_out_file_name[filename_buf_size];\n    sprintf(gene_out_file_name, \"%sgene_exp.diff\", out_file_prefix);\n    FILE* gene_out = fopen(gene_out_file_name, \"w\");\n    if (!group_out)\n    {\n        fprintf(stderr, \"Error: cannot open gene expression file %s for writing\\n\",\n                gene_out_file_name);\n        exit(1);\n    }\n    \n    char cds_out_file_name[filename_buf_size];\n    sprintf(cds_out_file_name, \"%scds_exp.diff\", out_file_prefix);\n    FILE* cds_out = fopen(cds_out_file_name, \"w\");\n    if (!cds_out)\n    {\n        fprintf(stderr, \"Error: cannot open cds expression file %s for writing\\n\",\n                cds_out_file_name);\n        exit(1);\n    }\n    \n    char diff_splicing_out_file_name[filename_buf_size];\n    sprintf(diff_splicing_out_file_name, \"%ssplicing.diff\", out_file_prefix);\n    FILE* diff_splicing_out = fopen(diff_splicing_out_file_name, \"w\");\n    if (!diff_splicing_out)\n    {\n        fprintf(stderr, \"Error: cannot open differential splicing file %s for writing\\n\",\n                diff_splicing_out_file_name);\n        exit(1);\n    }\n    \n    char diff_promoter_out_file_name[filename_buf_size];\n    sprintf(diff_promoter_out_file_name, \"%spromoters.diff\", out_file_prefix);\n    FILE* diff_promoter_out = fopen(diff_promoter_out_file_name, \"w\");\n    if (!diff_promoter_out)\n    {\n        fprintf(stderr, \"Error: cannot open differential transcription start file %s for writing\\n\",\n                diff_promoter_out_file_name);\n        exit(1);\n    }\n    \n    char diff_cds_out_file_name[filename_buf_size];\n    sprintf(diff_cds_out_file_name, \"%scds.diff\", out_file_prefix);\n    FILE* diff_cds_out = fopen(diff_cds_out_file_name, \"w\");\n    if (!diff_cds_out)\n    {\n        fprintf(stderr, \"Error: cannot open differential relative CDS file %s for writing\\n\",\n                diff_cds_out_file_name);\n        exit(1);\n    }\n    \n    outfiles.isoform_de_outfile = iso_out;\n    outfiles.group_de_outfile = group_out;\n    outfiles.gene_de_outfile = gene_out;\n    outfiles.cds_de_outfile = cds_out;\n    outfiles.diff_splicing_outfile = diff_splicing_out;\n    outfiles.diff_promoter_outfile = diff_promoter_out;\n    outfiles.diff_cds_outfile = diff_cds_out;\n\t\n\tchar isoform_fpkm_tracking_name[filename_buf_size];\n\tsprintf(isoform_fpkm_tracking_name, \"%s/isoforms.fpkm_tracking\", output_dir.c_str());\n\tFILE* isoform_fpkm_out = fopen(isoform_fpkm_tracking_name, \"w\");\n\tif (!isoform_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open isoform-level FPKM tracking file %s for writing\\n\",\n\t\t\t\tisoform_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.isoform_fpkm_tracking_out = isoform_fpkm_out;\n\n\tchar tss_group_fpkm_tracking_name[filename_buf_size];\n\tsprintf(tss_group_fpkm_tracking_name, \"%s/tss_groups.fpkm_tracking\", output_dir.c_str());\n\tFILE* tss_group_fpkm_out = fopen(tss_group_fpkm_tracking_name, \"w\");\n\tif (!tss_group_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open TSS group-level FPKM tracking file %s for writing\\n\",\n\t\t\t\ttss_group_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.tss_group_fpkm_tracking_out = tss_group_fpkm_out;\n\n\tchar cds_fpkm_tracking_name[filename_buf_size];\n\tsprintf(cds_fpkm_tracking_name, \"%s/cds.fpkm_tracking\", output_dir.c_str());\n\tFILE* cds_fpkm_out = fopen(cds_fpkm_tracking_name, \"w\");\n\tif (!cds_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open CDS level FPKM tracking file %s for writing\\n\",\n\t\t\t\tcds_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.cds_fpkm_tracking_out = cds_fpkm_out;\n\t\n\tchar gene_fpkm_tracking_name[filename_buf_size];\n\tsprintf(gene_fpkm_tracking_name, \"%s/genes.fpkm_tracking\", output_dir.c_str());\n\tFILE* gene_fpkm_out = fopen(gene_fpkm_tracking_name, \"w\");\n\tif (!gene_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open gene-level FPKM tracking file %s for writing\\n\",\n\t\t\t\tgene_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.gene_fpkm_tracking_out = gene_fpkm_out;\n\n    char isoform_count_tracking_name[filename_buf_size];\n\tsprintf(isoform_count_tracking_name, \"%s/isoforms.count_tracking\", output_dir.c_str());\n\tFILE* isoform_count_out = fopen(isoform_count_tracking_name, \"w\");\n\tif (!isoform_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open isoform-level count tracking file %s for writing\\n\",\n\t\t\t\tisoform_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.isoform_count_tracking_out = isoform_count_out;\n    \n\tchar tss_group_count_tracking_name[filename_buf_size];\n\tsprintf(tss_group_count_tracking_name, \"%s/tss_groups.count_tracking\", output_dir.c_str());\n\tFILE* tss_group_count_out = fopen(tss_group_count_tracking_name, \"w\");\n\tif (!tss_group_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open TSS group-level count tracking file %s for writing\\n\",\n\t\t\t\ttss_group_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.tss_group_count_tracking_out = tss_group_count_out;\n    \n\tchar cds_count_tracking_name[filename_buf_size];\n\tsprintf(cds_count_tracking_name, \"%s/cds.count_tracking\", output_dir.c_str());\n\tFILE* cds_count_out = fopen(cds_count_tracking_name, \"w\");\n\tif (!cds_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open CDS level count tracking file %s for writing\\n\",\n\t\t\t\tcds_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.cds_count_tracking_out = cds_count_out;\n\t\n\tchar gene_count_tracking_name[filename_buf_size];\n\tsprintf(gene_count_tracking_name, \"%s/genes.count_tracking\", output_dir.c_str());\n\tFILE* gene_count_out = fopen(gene_count_tracking_name, \"w\");\n\tif (!gene_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open gene-level count tracking file %s for writing\\n\",\n\t\t\t\tgene_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.gene_count_tracking_out = gene_count_out;\n    \n    char isoform_rep_tracking_name[filename_buf_size];\n\tsprintf(isoform_rep_tracking_name, \"%s/isoforms.read_group_tracking\", output_dir.c_str());\n\tFILE* isoform_rep_out = fopen(isoform_rep_tracking_name, \"w\");\n\tif (!isoform_rep_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open isoform-level read group tracking file %s for writing\\n\",\n\t\t\t\tisoform_rep_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.isoform_rep_tracking_out = isoform_rep_out;\n    \n\tchar tss_group_rep_tracking_name[filename_buf_size];\n\tsprintf(tss_group_rep_tracking_name, \"%s/tss_groups.read_group_tracking\", output_dir.c_str());\n\tFILE* tss_group_rep_out = fopen(tss_group_rep_tracking_name, \"w\");\n\tif (!tss_group_rep_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open TSS group-level read group tracking file %s for writing\\n\",\n\t\t\t\ttss_group_rep_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.tss_group_rep_tracking_out = tss_group_rep_out;\n    \n\tchar cds_rep_tracking_name[filename_buf_size];\n\tsprintf(cds_rep_tracking_name, \"%s/cds.read_group_tracking\", output_dir.c_str());\n\tFILE* cds_rep_out = fopen(cds_rep_tracking_name, \"w\");\n\tif (!cds_rep_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open CDS level read group tracking file %s for writing\\n\",\n\t\t\t\tcds_rep_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.cds_rep_tracking_out = cds_rep_out;\n\t\n\tchar gene_rep_tracking_name[filename_buf_size];\n\tsprintf(gene_rep_tracking_name, \"%s/genes.read_group_tracking\", output_dir.c_str());\n\tFILE* gene_rep_out = fopen(gene_rep_tracking_name, \"w\");\n\tif (!gene_rep_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open gene-level read group tracking file %s for writing\\n\",\n\t\t\t\tgene_rep_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.gene_rep_tracking_out = gene_rep_out;\n    \n    char read_group_info_name[filename_buf_size];\n\tsprintf(read_group_info_name, \"%s/read_groups.info\", output_dir.c_str());\n\tFILE* read_group_out = fopen(read_group_info_name, \"w\");\n\tif (!read_group_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open read group info file %s for writing\\n\",\n\t\t\t\tread_group_info_name);\n\t\texit(1);\n\t}\n\toutfiles.read_group_info_out = read_group_out;\n    \n    char run_info_name[filename_buf_size];\n\tsprintf(run_info_name, \"%s/run.info\", output_dir.c_str());\n\tFILE* run_info_out = fopen(run_info_name, \"w\");\n\tif (!run_info_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open run info file %s for writing\\n\",\n\t\t\t\trun_info_name);\n\t\texit(1);\n\t}\n\toutfiles.run_info_out = run_info_out;\n\n    char bias_name[filename_buf_size];\n\tsprintf(bias_name, \"%s/bias_params.info\", output_dir.c_str());\n\tFILE* bias_out = fopen(bias_name, \"w\");\n\tif (!bias_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open run info file %s for writing\\n\",\n\t\t\t\tbias_name);\n\t\texit(1);\n\t}\n\toutfiles.bias_out = bias_out;\n    \n    char var_model_name[filename_buf_size];\n\tsprintf(var_model_name, \"%s/var_model.info\", output_dir.c_str());\n\tFILE* var_model_out = fopen(var_model_name, \"w\");\n\tif (!var_model_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open run info file %s for writing\\n\",\n\t\t\t\tvar_model_name);\n\t\texit(1);\n\t}\n\toutfiles.var_model_out = var_model_out;\n\n    \n    driver(ref_gtf, mask_gtf, contrast_file, norm_standards_file, sam_hit_filenames, outfiles);\n\t\n#if 0\n    if (emit_count_tables)\n    {\n        dump_locus_variance_info(output_dir + string(\"/locus_var.txt\"));\n    }\n#endif\n    \n\treturn 0;\n}\n"
  },
  {
    "path": "src/cuffdiff_to_gct.py",
    "content": "#!/usr/bin/env python2\n# encoding: utf-8\n\"\"\"\ncuffdiff_to_gct.py\n\nCreated by Cole Trapnell on 2010-08-30.\nCopyright (c) 2010 Cole Trapnell. All rights reserved.\n\"\"\"\n\nimport sys\nimport getopt\nimport math\n\nhelp_message = '''\nThis script transforms a Cuffdiff FPKM tracking file to an IGV-compatible GCT expression file\n\nUsage:\n    cuffdiff_to_gct.py <input.fpkm_tracking> <output.gct>\n'''\n\n\nclass Usage(Exception):\n    def __init__(self, msg):\n        self.msg = msg\n\n\ndef main(argv=None):\n    if argv is None:\n        argv = sys.argv\n    try:\n        try:\n            opts, args = getopt.getopt(argv[1:], \"ho:v\", [\"help\", \"output=\"])\n        except getopt.error, msg:\n            raise Usage(msg)\n    \n        # option processing\n        for option, value in opts:\n            if option == \"-v\":\n                verbose = True\n            if option in (\"-h\", \"--help\"):\n                raise Usage(help_message)\n            if option in (\"-o\", \"--output\"):\n                output = value\n            \n        if len(args) < 2:\n            raise Usage(help_message)\n        \n        fpkm_tracking = open(args[0])\n        gct_out = open(args[1], \"w\")\n        \n        num_descriptor_cols = 6\n        sample_names = []\n        while True:\n            h = fpkm_tracking.readline()\n            h = h.strip()\n            if h != \"\":\n                h_cols = h.split(\"\\t\")\n                if len(h_cols) < 12:\n                    print >> sys.stderr, \"Error: malformed header\"\n                    sys.exit(1)\n                num_samples = (len(h_cols) - num_descriptor_cols) / 3\n                for i in range(0, num_samples):\n                    FPKM_label = h_cols[num_descriptor_cols + (3 * i)]\n                    name_end = FPKM_label.rfind(\"_FPKM\")\n                    name = FPKM_label[:name_end]\n                    sample_names.append(name)\n                break \n        \n        #print sample_names\n        expr_records = []\n        for line in fpkm_tracking.readlines():\n            line = line.strip()\n            if line == \"\":\n                continue\n            cols = line.split(\"\\t\")\n            if len(cols) != 6 + (3 * num_samples):\n                print >> sys.stderr, \"Error: malformed record\"\n                sys.exit(1)\n            expr_strs = []\n            for i in range(0, num_samples):\n                FPKM_string = cols[num_descriptor_cols + (3 * i)]\n                FPKM = float(FPKM_string)\n                if math.isnan(FPKM) or math.isinf(FPKM):\n                    FPKM = 0.0\n                FPKM = str(FPKM)\n                expr_strs.append(FPKM)\n            rec = []\n            rec.append(cols[0])\n            desc = \"na|@%s|\" % cols[5]\n            rec.append(desc)\n            rec.extend(expr_strs)\n            expr_records.append(rec)\n        \n        print >> gct_out, \"#1.2\"\n        print >> gct_out, \"%d\\t%d\" %  (len(expr_records), num_samples)\n        print >> gct_out, \"NAME\\tDescription\\t%s\" % (\"\\t\".join(sample_names))   \n        for rec in expr_records:\n            print >> gct_out, \"%s\" % \"\\t\".join(rec) \n        \n        \n    except Usage, err:\n        print >> sys.stderr, sys.argv[0].split(\"/\")[-1] + \": \" + str(err.msg)\n        print >> sys.stderr, \"\\t for help use --help\"\n        return 2\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n"
  },
  {
    "path": "src/cufflinks.cpp",
    "content": "/*\n *  cufflinks.cpp\n *  Cufflinks\n *\n *  Created by Cole Trapnell on 3/23/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <stdlib.h>\n#include <getopt.h>\n#include <string>\n\n#include \"common.h\"\n#include \"hits.h\"\n\n#include <boost/thread.hpp>\n\n#include \"update_check.h\"\n#include \"clustering.h\"\n#include \"abundances.h\"\n#include \"bundles.h\"\n#include \"filters.h\"\n#include \"genes.h\"\n#include \"assemble.h\"\n#include \"biascorrection.h\"\n#include \"multireads.h\"\n#include \"replicates.h\"\n\nusing namespace std;\n\n#if ENABLE_THREADS\nconst char *short_options = \"m:p:s:F:I:j:Q:L:G:g:o:M:b:a:A:Nqvu\";\n#else\nconst char *short_options = \"m:s:F:I:j:Q:L:G:g:o:M:b:a:A:Nqvu\";\n#endif\n\nstatic struct option long_options[] = {\n// general options\n{\"GTF\",\t\t\t\t\t    required_argument,\t\t 0,\t\t\t 'G'},\n{\"GTF-guide\",\t\t\t    required_argument,\t\t 0,\t\t\t 'g'},\n{\"mask-file\",                required_argument,\t\t 0,\t\t\t 'M'},\n{\"library-type\",\t\t    required_argument,\t\t 0,\t\t\t OPT_LIBRARY_TYPE},\n{\"seed\",                    required_argument,\t\t 0,\t\t\t OPT_RANDOM_SEED},\n\n// program behavior\n{\"output-dir\",\t\t\t    required_argument,\t\t 0,\t\t\t 'o'},\n{\"verbose\",\t\t\t    \tno_argument,\t\t \t 0,\t\t\t 'v'},\n{\"quiet\",\t\t\t    \tno_argument,\t\t\t 0,\t\t\t 'q'},\n{\"no-update-check\",         no_argument,             0,          OPT_NO_UPDATE_CHECK},\n#if ENABLE_THREADS\n    {\"num-threads\",\t\t\trequired_argument,       0,          'p'},\n#endif    \n{\"output-fld\",              no_argument,             0,          OPT_OUTPUT_FLD},\n{\"output-bias-params\",      no_argument,             0,          OPT_OUTPUT_BIAS_PARAMS},\n    \n// abundance estimation\n{\"frag-len-mean\",\t\t\trequired_argument,       0,          'm'},\n{\"frag-len-std-dev\",\t\trequired_argument,       0,          's'},\n{\"min-isoform-fraction\",    required_argument,       0,          'F'},\n{\"upper-quartile-normalization\",  no_argument,\t \t\t 0,\t         'N'},\n{\"frag-bias-correct\",       required_argument,\t\t 0,\t\t\t 'b'},\n{\"multi-read-correct\",      no_argument,\t\t\t 0,\t\t\t 'u'},\n\n{\"num-importance-samples\",  required_argument,\t\t 0,\t\t\t OPT_NUM_IMP_SAMPLES},\n{\"max-mle-iterations\",\t\trequired_argument,\t\t 0,\t\t\t OPT_MLE_MAX_ITER},\n{\"bias-mode\",               required_argument,\t\t 0,\t\t\t OPT_BIAS_MODE},\n{\"use-grad-ascent\",         no_argument,             0,\t\t\t OPT_USE_EM},\n{\"no-collapse-cond-prob\",   no_argument,             0,\t\t\t OPT_COLLAPSE_COND_PROB},\n{\"compatible-hits-norm\",    no_argument,\t \t\t 0,\t         OPT_USE_COMPAT_MASS},\n{\"total-hits-norm\",         no_argument,\t \t\t 0,\t         OPT_USE_TOTAL_MASS},\n    \n// assembly\n{\"pre-mrna-fraction\",\t\trequired_argument,\t\t 0,\t\t\t 'j'},\n{\"junc-alpha\",\t\t\t\trequired_argument,\t\t 0,\t\t\t 'a'},\t\n{\"small-anchor-fraction\",\trequired_argument,\t\t 0,\t\t\t 'A'},\n{\"max-intron-length\",\t\trequired_argument,\t\t 0,\t\t\t 'I'},\n{\"label\",\t\t\t\t\trequired_argument,\t\t 0,\t\t\t 'L'},\n{\"overhang-tolerance\",      required_argument,\t\t 0,\t\t\t OPT_OVERHANG_TOLERANCE},\n{\"min-frags-per-transfrag\",required_argument,\t\t 0,\t\t\t OPT_MIN_FRAGS_PER_TRANSFRAG},\n{\"min-intron-length\",       required_argument,\t     0,\t\t\t OPT_MIN_INTRON_LENGTH},\n{\"max-bundle-length\",       required_argument,\t\t 0,\t\t\t OPT_MAX_BUNDLE_LENGTH},\n{\"trim-3-dropoff-frac\",     required_argument,\t\t 0,\t\t\t OPT_3_PRIME_DROPOFF_FRAC},\n{\"trim-3-avgcov-thresh\",\trequired_argument,\t\t 0,\t\t\t OPT_3_PRIME_AVGCOV_THRESH},\n    \n{\"3-overhang-tolerance\",\trequired_argument,\t\t 0,\t\t\t OPT_3_OVERHANG_TOLERANCE},\n{\"intron-overhang-tolerance\",\trequired_argument,\t\t 0,\t\t OPT_INTRON_OVERHANG_TOLERANCE},\n{\"no-faux-reads\",           no_argument,             0,          OPT_NO_FAUX_READS},\n{\"no-5-extend\",             no_argument,             0,          OPT_NO_5_EXTEND},\n{\"tile-read-len\",           required_argument,       0,          OPT_TILE_LEN}, \n{\"tile-read-sep\",           required_argument,       0,          OPT_TILE_SEP}, \n    \n{\"max-bundle-frags\",        required_argument,        0,          OPT_MAX_FRAGS_PER_BUNDLE}, \n{\"num-frag-count-draws\",\trequired_argument,\t\t 0,\t\t\t OPT_NUM_FRAG_COUNT_DRAWS},\n{\"num-frag-assign-draws\",\trequired_argument,\t\t 0,\t\t\t OPT_NUM_FRAG_ASSIGN_DRAWS},\n{\"max-multiread-fraction\",\trequired_argument,\t\t 0,\t\t\t OPT_MAX_MULTIREAD_FRACTION},\n{\"overlap-radius\",       \trequired_argument,\t\t 0,\t\t\t OPT_OLAP_RADIUS},\n{\"max-frag-multihits\",      required_argument,       0,          OPT_FRAG_MAX_MULTIHITS},\n{\"no-effective-length-correction\",  no_argument,     0,          OPT_NO_EFFECTIVE_LENGTH_CORRECTION},\n{\"library-norm-method\",     required_argument,       0,          OPT_LIB_NORM_METHOD},\n{\"no-length-correction\",  no_argument,     0,          OPT_NO_LENGTH_CORRECTION},\n{0, 0, 0, 0} // terminator\n};\n\nvoid print_usage()\n{\n    //NOTE: SPACES ONLY, bozo\n    fprintf(stderr, \"cufflinks v%s\\n\", PACKAGE_VERSION);\n    fprintf(stderr, \"linked against Boost version %d\\n\", BOOST_VERSION);\n    fprintf(stderr, \"-----------------------------\\n\"); \n    fprintf(stderr, \"Usage:   cufflinks [options] <hits.sam>\\n\");\n    fprintf(stderr, \"General Options:\\n\");\n    fprintf(stderr, \"  -o/--output-dir              write all output files to this directory              [ default:     ./ ]\\n\");\n#if ENABLE_THREADS\n    fprintf(stderr, \"  -p/--num-threads             number of threads used during analysis                [ default:      1 ]\\n\");\n#endif    \n    fprintf(stderr, \"  --seed                       value of random number generator seed                 [ default:      0 ]\\n\");\n    fprintf(stderr, \"  -G/--GTF                     quantitate against reference transcript annotations                      \\n\");\n    fprintf(stderr, \"  -g/--GTF-guide               use reference transcript annotation to guide assembly                    \\n\");\n    fprintf(stderr, \"  -M/--mask-file               ignore all alignments within transcripts in this file                    \\n\");\n    fprintf(stderr, \"  -b/--frag-bias-correct       use bias correction - reference fasta required        [ default:   NULL ]\\n\");\n    fprintf(stderr, \"  -u/--multi-read-correct      use 'rescue method' for multi-reads (more accurate)   [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --library-type               library prep used for input reads                     [ default:  below ]\\n\");\n    fprintf(stderr, \"  --library-norm-method        Method used to normalize library sizes                [ default:  below ]\\n\");\n    \n    fprintf(stderr, \"\\nAdvanced Abundance Estimation Options:\\n\");\n    fprintf(stderr, \"  -m/--frag-len-mean           average fragment length (unpaired reads only)         [ default:    200 ]\\n\");\n    fprintf(stderr, \"  -s/--frag-len-std-dev        fragment length std deviation (unpaired reads only)   [ default:     80 ]\\n\");\n    fprintf(stderr, \"  --max-mle-iterations         maximum iterations allowed for MLE calculation        [ default:   5000 ]\\n\");\n    fprintf(stderr, \"  --compatible-hits-norm       count hits compatible with reference RNAs only        [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --total-hits-norm            count all hits for normalization                      [ default:  TRUE  ]\\n\");\n    fprintf(stderr, \"  --num-frag-count-draws       Number of fragment generation samples                 [ default:    100 ]\\n\");\n    fprintf(stderr, \"  --num-frag-assign-draws      Number of fragment assignment samples per generation  [ default:     50 ]\\n\");\n    fprintf(stderr, \"  --max-frag-multihits         Maximum number of alignments allowed per fragment     [ default: unlim  ]\\n\");\n    fprintf(stderr, \"  --no-effective-length-correction   No effective length correction                  [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --no-length-correction       No length correction                                  [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  -N/--upper-quartile-norm     Deprecated, use --library-norm-method                 [    DEPRECATED   ]\\n\");\n    fprintf(stderr, \"  --raw-mapped-norm            Deprecated, use --library-norm-method                 [    DEPRECATED   ]\\n\");\n    \n    fprintf(stderr, \"\\nAdvanced Assembly Options:\\n\");\n    fprintf(stderr, \"  -L/--label                   assembled transcripts have this ID prefix             [ default:   CUFF ]\\n\");\n    fprintf(stderr, \"  -F/--min-isoform-fraction    suppress transcripts below this abundance level       [ default:   0.10 ]\\n\");\n    fprintf(stderr, \"  -j/--pre-mrna-fraction       suppress intra-intronic transcripts below this level  [ default:   0.15 ]\\n\");\n    fprintf(stderr, \"  -I/--max-intron-length       ignore alignments with gaps longer than this          [ default: 300000 ]\\n\");\n    fprintf(stderr, \"  -a/--junc-alpha              alpha for junction binomial test filter               [ default:  0.001 ]\\n\");\n    fprintf(stderr, \"  -A/--small-anchor-fraction   percent read overhang taken as 'suspiciously small'   [ default:   0.09 ]\\n\");\n    fprintf(stderr, \"  --min-frags-per-transfrag    minimum number of fragments needed for new transfrags [ default:     10 ]\\n\");\n    fprintf(stderr, \"  --overhang-tolerance         number of terminal exon bp to tolerate in introns     [ default:      8 ]\\n\");\n    fprintf(stderr, \"  --max-bundle-length          maximum genomic length allowed for a given bundle     [ default:3500000 ]\\n\");\n    fprintf(stderr, \"  --max-bundle-frags           maximum fragments allowed in a bundle before skipping [ default: 500000 ]\\n\");\n    fprintf(stderr, \"  --min-intron-length          minimum intron size allowed in genome                 [ default:     50 ]\\n\");\n    fprintf(stderr, \"  --trim-3-avgcov-thresh       minimum avg coverage required to attempt 3' trimming  [ default:     10 ]\\n\");\n    fprintf(stderr, \"  --trim-3-dropoff-frac        fraction of avg coverage below which to trim 3' end   [ default:    0.1 ]\\n\");\n    fprintf(stderr, \"  --max-multiread-fraction     maximum fraction of allowed multireads per transcript [ default:   0.75 ]\\n\");\n    fprintf(stderr, \"  --overlap-radius             maximum gap size to fill between transfrags (in bp)   [ default:     50 ]\\n\");\n    \n    fprintf(stderr, \"\\nAdvanced Reference Annotation Guided Assembly Options:\\n\");\n//    fprintf(stderr, \"  --tile-read-len              length of faux-reads                                  [ default:    405 ]\\n\");\n//    fprintf(stderr, \"  --tile-read-sep              distance between faux-reads                           [ default:     15 ]\\n\");\n    fprintf(stderr, \"  --no-faux-reads              disable tiling by faux reads                          [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --3-overhang-tolerance       overhang allowed on 3' end when merging with reference[ default:    600 ]\\n\");\n    fprintf(stderr, \"  --intron-overhang-tolerance  overhang allowed inside reference intron when merging [ default:     30 ]\\n\");\n    \n    fprintf(stderr, \"\\nAdvanced Program Behavior Options:\\n\");\n    fprintf(stderr, \"  -v/--verbose                 log-friendly verbose processing (no progress bar)     [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  -q/--quiet                   log-friendly quiet processing (no progress bar)       [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --no-update-check            do not contact server to check for update availability[ default:  FALSE ]\\n\");\n    print_library_table();\n    print_lib_norm_method_table();\n}\n\nint parse_options(int argc, char** argv)\n{\n    int option_index = 0;\n    int next_option;\n\tbool F_set = false;\n\tstring lib_norm_method_str;\n    do {\n        next_option = getopt_long(argc, argv, short_options, long_options, &option_index);\n        switch (next_option) {\n\t\t\tcase -1:     /* Done with options. */\n\t\t\t\tbreak;\n\t\t\tcase 'm':\n\t\t\t\tuser_provided_fld = true;\n\t\t\t\tdef_frag_len_mean = (uint32_t)parseInt(0, \"-m/--frag-len-mean arg must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase 's':\n\t\t\t\tuser_provided_fld = true;\n\t\t\t\tdef_frag_len_std_dev = (uint32_t)parseInt(0, \"-s/--frag-len-std-dev arg must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase 'p':\n\t\t\t\tnum_threads = (uint32_t)parseInt(1, \"-p/--num-threads arg must be at least 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase 'F':\n\t\t\t\tmin_isoform_fraction = parseFloat(0, 1.0, \"-F/--min-isoform-fraction must be between 0 and 1.0\", print_usage);\n\t\t\t\tF_set = true;\n\t\t\t\tbreak;\n\t\t\tcase 'I':\n\t\t\t\tmax_intron_length = parseInt(1, \"-I/--max-intron-length must be at least 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase 'j':\n\t\t\t\tpre_mrna_fraction = parseFloat(0, 1.0, \"-I/--pre-mrna-fraction must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase 'a':\n\t\t\t\tbinomial_junc_filter_alpha = parseFloat(0, 1.0, \"-a/--junc-alpha must be between 0 and 1.0\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase 'A':\n\t\t\t\tsmall_anchor_fraction = parseFloat(0, 1.0, \"-A/--small-anchor-fraction must be between 0 and 1.0\", print_usage);\n\t\t\t\tbreak;\n            case OPT_OVERHANG_TOLERANCE:\n\t\t\t\tbowtie_overhang_tolerance = parseInt(0, \"--overhang-tolerance must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase OPT_NUM_IMP_SAMPLES:\n\t\t\t\tnum_importance_samples = parseInt(1, \"--num-importance-samples must be at least 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase OPT_MLE_MAX_ITER:\n\t\t\t\tmax_mle_iterations = parseInt(1, \"--max-mle-iterations must be at least 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase OPT_BIAS_MODE:\n\t\t\t\tif (!strcmp(optarg, \"site\"))\n\t\t\t\t\tbias_mode = SITE;\n\t\t\t\telse if (!strcmp(optarg, \"pos\"))\n\t\t\t\t\tbias_mode = POS;\n\t\t\t\telse if (!strcmp(optarg, \"pos_vlmm\"))\n\t\t\t\t\tbias_mode = POS_VLMM;\n\t\t\t\telse if (!strcmp(optarg, \"vlmm\"))\n\t\t\t\t\tbias_mode = VLMM;\n                else if (!strcmp(optarg, \"pos_site\"))\n\t\t\t\t\tbias_mode = POS_SITE;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Unknown bias mode.\\n\");\n\t\t\t\t\texit(1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'L':\n\t\t\t{\n\t\t\t\tuser_label = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'G':\n\t\t\t{\n\t\t\t\tref_gtf_filename = optarg;\n\t\t\t\tbundle_mode = REF_DRIVEN;\n                init_bundle_mode = REF_DRIVEN;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'g':\n\t\t\t{\n\t\t\t\tref_gtf_filename = optarg;\n\t\t\t\tbundle_mode = REF_GUIDED;\n                init_bundle_mode = REF_GUIDED;\n\t\t\t\tbreak;\n\t\t\t}\n            case 'M':\n\t\t\t{\n\t\t\t\tmask_gtf_filename = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'v':\n\t\t\t{\n\t\t\t\tif (cuff_quiet)\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Warning: Can't be both verbose and quiet!  Setting verbose only.\\n\");\n\t\t\t\t}\n\t\t\t\tcuff_quiet = false;\n\t\t\t\tcuff_verbose = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'q':\n\t\t\t{\n\t\t\t\tif (cuff_verbose)\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Warning: Can't be both verbose and quiet!  Setting quiet only.\\n\");\n\t\t\t\t}\n\t\t\t\tcuff_verbose = false;\n\t\t\t\tcuff_quiet = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'N':\n            {\n            \t//lib_norm_method_str = \"quartile\";\n                break;\n            }\n\n            case 'o':\n\t\t\t{\n\t\t\t\toutput_dir = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case 'b':\n\t\t\t{\n\t\t\t\tfasta_dir = optarg;\n\t\t\t\tcorr_bias = true;\n\t\t\t\tbreak;\n            }    \n\t\t\tcase 'u':\n\t\t\t{\n\t\t\t\tcorr_multi = true;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_LIBRARY_TYPE:\n\t\t\t{\n\t\t\t\tlibrary_type = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_MAX_BUNDLE_LENGTH:\n\t\t\t{\n\t\t\t\tmax_gene_length = parseInt(1, \"--max-bundle-length must be at least 1\", print_usage);;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_MIN_FRAGS_PER_TRANSFRAG:\n\t\t\t{\n\t\t\t\tmin_frags_per_transfrag = parseInt(0, \"--min-frags-per-transfrag must be at least 0\", print_usage);;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_MIN_INTRON_LENGTH:\n\t\t\t{\n\t\t\t\tmin_intron_length = parseInt(0, \"--min-intron-length must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OPT_3_PRIME_AVGCOV_THRESH:\n\t\t\t{\n\t\t\t\ttrim_3_avgcov_thresh = parseFloat(0, 9999999, \"--trim-3-avgcov-thresh must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_3_PRIME_DROPOFF_FRAC:\n\t\t\t{\n\t\t\t\ttrim_3_dropoff_frac = parseFloat(0, 1.0, \"--trim-3-dropoff-frac must be between 0 and 1.0\", print_usage);\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_NO_UPDATE_CHECK:\n            {\n                no_update_check = true;\n                break;\n            }\n            case OPT_OUTPUT_FLD:\n            {\n                output_fld = true;\n                break;\n            }\n            case OPT_OUTPUT_BIAS_PARAMS:\n            {\n                output_bias_params = true;\n                break;\n            }\n            case OPT_COLLAPSE_COND_PROB:\n            {\n                cond_prob_collapse = false;\n                break;\n            }\n            case OPT_NO_FAUX_READS:\n            {\n                enable_faux_reads = false;\n                break;\n            }\n            case OPT_NO_5_EXTEND:\n            {\n                enable_5_extend = false;\n                break;\n            }\n            case OPT_3_OVERHANG_TOLERANCE:\n            {\n                overhang_3 = parseInt(0, \"--3-overhang-tolernace must be at least 0\", print_usage);\n                break;\n            }\n            case OPT_TILE_LEN:\n            {\n                tile_len = parseInt(0, \"--tile-read-len must be at least 0\", print_usage);\n                break;\n            }\n            case OPT_TILE_SEP:\n            {\n                tile_off = parseInt(0, \"--tile-read-sep must be at least 0\", print_usage);\n                break;\n            }\n            case OPT_INTRON_OVERHANG_TOLERANCE:\n            {\n                ref_merge_overhang_tolerance = parseInt(0, \"--intron-overhang-tolerance must be at least 0\", print_usage);\n                break;\n            }\n            case OPT_RANDOM_SEED:\n            {\n                random_seed = parseInt(0, \"--seed must be at least 0\", print_usage);\n                break;\n            }\n            case OPT_USE_COMPAT_MASS:\n            {\n                use_compat_mass = true;\n                break;\n            }\n            case OPT_USE_TOTAL_MASS:\n            {\n                use_total_mass = true;\n                break;\n            }\n            case OPT_MAX_FRAGS_PER_BUNDLE:\n            {\n                max_frags_per_bundle = parseInt(0, \"--max-bundle-frags must be at least 0\", print_usage);\n                break;\n            }\n            case OPT_NUM_FRAG_COUNT_DRAWS:\n            {\n                num_frag_count_draws = parseInt(1, \"--num-frag-count-draws must be at least 1\", print_usage);\n                break;\n            }\n            case OPT_NUM_FRAG_ASSIGN_DRAWS:\n            {\n                num_frag_assignments = parseInt(1, \"--num-frag-assign-draws must be at least 1\", print_usage);\n                break;\n            }\n            case OPT_MAX_MULTIREAD_FRACTION:\n            {\n                max_multiread_fraction = parseFloat(0, 1.0, \"--max-multiread-fraction must be between 0 and 1.0\", print_usage);\n                break;\n            }\n            case OPT_FRAG_MAX_MULTIHITS:\n            {\n                max_frag_multihits = parseInt(1, \"--max-frag-multihits must be at least 1\", print_usage);\n                break;\n            }\n            case OPT_OLAP_RADIUS:\n            {\n                olap_radius = parseInt(1, \"--olap-radius must be at least 1\", print_usage);\n                break;\n            }\n            case OPT_NO_EFFECTIVE_LENGTH_CORRECTION:\n            {\n                no_effective_length_correction = true;\n                break;\n            }\n            case OPT_NO_LENGTH_CORRECTION:\n            {\n                no_length_correction = true;\n                break;\n            }\n\t\t\tdefault:\n\t\t\t\tprint_usage();\n\t\t\t\treturn 1;\n        }\n    } while(next_option != -1);\n\t\n    \n\tif (bundle_mode == REF_DRIVEN)\n\t{\n        if (!F_set)\n        {\n            min_isoform_fraction = 0.0;\n        }\n\t}\n\t\n\tif (bundle_mode == REF_DRIVEN)\n\t{\n\t\tallow_junk_filtering = false;\n\t}\n\t\n    if (library_type != \"\")\n    {\n        map<string, ReadGroupProperties>::iterator lib_itr = \n            library_type_table.find(library_type);\n        if (lib_itr == library_type_table.end())\n        {\n            fprintf(stderr, \"Error: Library type %s not supported\\n\", library_type.c_str());\n            exit(1);\n        }\n        else \n        {\n//            if (library_type == \"transfrags\")\n//            {\n//                allow_junk_filtering = false;\n//            }\n            global_read_properties = &lib_itr->second;\n        }\n    }\n    \n    // Set the library size normalization method to use\n    if (lib_norm_method_str == \"\")\n    {\n        lib_norm_method_str = default_cufflinks_lib_norm_method;\n    }\n    \n    map<string, LibNormalizationMethod>::iterator lib_norm_itr =\n    lib_norm_method_table.find(lib_norm_method_str);\n    if (lib_norm_itr == lib_norm_method_table.end())\n    {\n        fprintf(stderr, \"Error: Dispersion method %s not supported\\n\", lib_norm_method_str.c_str());\n        exit(1);\n    }\n    else\n    {\n        lib_norm_method = lib_norm_itr->second;\n    }\n    \n    if (use_total_mass && use_compat_mass)\n    {\n        fprintf (stderr, \"Error: please supply only one of --compatible-hits-norm and --total-hits-norm\\n\");\n        exit(1);\n    }\n    if (use_compat_mass && bundle_mode != REF_DRIVEN)\n    {\n        fprintf (stderr, \"Error: cannot use --compatible-hits-norm without --GTF\\n\");\n        exit(1);\n    }\n\t\n    return 0;\n}\n\nvoid combine_strand_assemblies(vector<Scaffold>& lhs, \n\t\t\t\t\t\t   vector<Scaffold>& rhs,\n\t\t\t\t\t\t   vector<Scaffold>& scaffolds,\n\t\t\t\t\t\t   vector<boost::shared_ptr<Scaffold> >* ref_scaffs)\n{\n\t// first check for strand support\n    for (size_t l = 0; l < lhs.size(); ++l)\n    {\n\t\tif (!lhs[l].has_strand_support(ref_scaffs))\n\t\t\tlhs[l].strand(CUFF_STRAND_UNKNOWN);\n\t}\n\tfor (size_t r = 0; r < rhs.size(); ++r)\n    {\n\t\tif (!rhs[r].has_strand_support(ref_scaffs))\n\t\t\trhs[r].strand(CUFF_STRAND_UNKNOWN);\n\t}\n\t\n    vector<bool> kept_lhs(lhs.size(), true);\n    vector<bool> kept_rhs(rhs.size(), true);\n    \n\t// next filter both lists based on reference transcripts (if available)\n\tif (ref_scaffs != NULL)\n\t{\n\t\tfor(size_t l = 0; l < lhs.size(); ++l)\n\t\t{\t\t\t\n\t\t\tBOOST_FOREACH(boost::shared_ptr<Scaffold> ref_scaff, *ref_scaffs)\n\t\t\t{\n                // if we're past all the overlaps, just stop\n\t\t\t\tif (ref_scaff->left() >= lhs[l].right() + overhang_3)\n\t\t\t\t{\n\t\t\t\t\t//break;\n\t\t\t\t}\n                // don't emit assembled transfrags that are contained within reference ones\n\t\t\t\telse if (ref_scaff->contains(lhs[l], 0, overhang_3) && Scaffold::compatible(*ref_scaff, lhs[l], ref_merge_overhang_tolerance))\n\t\t\t\t{\n\t\t\t\t\tkept_lhs[l] = false;\n\t\t\t\t}\n                // if they're compatible but not equal, let's check a few more criteria before \n                // we decide to emit the assembled guy\n\t\t\t\telse if (ref_scaff->overlapped_3(lhs[l], 0, overhang_3) && Scaffold::compatible(*ref_scaff, lhs[l], ref_merge_overhang_tolerance))\n\t\t\t\t{\n\t\t\t\t\tif (ref_scaff->gaps() == lhs[l].gaps())\n                    {\n                        kept_lhs[l] = false;\n                    }\n                    else\n                    {\n//                        if (enable_5_extend)\n//                        {\n//                            ref_scaff->extend_5(lhs[l]);\n//                            kept_lhs[l] = false;\n//                        }\n                    }\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor(size_t r = 0; r < rhs.size(); ++r)\n\t\t{\t\t\t\n\t\t\tBOOST_FOREACH(boost::shared_ptr<Scaffold> ref_scaff, *ref_scaffs)\n\t\t\t{\n\t\t\t\tif (ref_scaff->left() >= rhs[r].right() + overhang_3)\n\t\t\t\t{\n\t\t\t\t\t//break;\n\t\t\t\t}\n\t\t\t\telse if (ref_scaff->contains(rhs[r], 0, overhang_3) && Scaffold::compatible(*ref_scaff, rhs[r], ref_merge_overhang_tolerance))\n\t\t\t\t{\n\t\t\t\t\tkept_rhs[r] = false;\n\t\t\t\t}\n\t\t\t\telse if (ref_scaff->overlapped_3(rhs[r], 0, overhang_3) && Scaffold::compatible(*ref_scaff, rhs[r], ref_merge_overhang_tolerance))\n\t\t\t\t{\n                    if (ref_scaff->gaps() == rhs[r].gaps())\n                    {\n                        kept_rhs[r] = false;\n                    }\n                    else\n                    {\n//                        if (enable_5_extend)\n//                        {\n//                            ref_scaff->extend_5(rhs[r]);\n//                            kept_rhs[r] = false;\n//                        }\n                    }\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n    // We want to keep all fwd, all reverse, and only the non-redundant unknowns\n    // if two unknown strand frags olap, merge them.\n    for (size_t l = 0; l < lhs.size(); ++l)\n    {\t\t \n\t\tif (!kept_lhs[l])\n\t\t\tcontinue;\n\t\tbool lhs_support = (lhs[l].strand() != CUFF_STRAND_UNKNOWN);\n        \n\t\tfor (size_t r = 0; r < rhs.size(); ++r)\n\t\t{\n\t\t\tif (!kept_rhs[r])\n\t\t\t\tcontinue;\n\t\t\tif (Scaffold::overlap_in_genome(lhs[l], rhs[r], 0))\n\t\t\t{\n\t\t\t\tif (Scaffold::compatible(lhs[l], rhs[r]))\n\t\t\t\t{\n\t\t\t\t\tbool rhs_support = (rhs[r].strand() != CUFF_STRAND_UNKNOWN);\n\t\t\t\t\tif (!lhs_support && !rhs_support)\n\t\t\t\t\t{\n\t\t\t\t\t\tScaffold merged;\n\t\t\t\t\t\tScaffold::merge(lhs[l],rhs[r],merged, true);\n\t\t\t\t\t\tscaffolds.push_back(merged);\n\t\t\t\t\t\tkept_lhs[l] = false;\n\t\t\t\t\t\tkept_rhs[r] = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\telse if (lhs_support && !rhs_support)\n\t\t\t\t\t{\n\t\t\t\t\t\tkept_rhs[r] = false;\n\t\t\t\t\t}\n\t\t\t\t\telse if (!lhs_support && rhs_support)\n\t\t\t\t\t{\n\t\t\t\t\t\tkept_lhs[l] = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\t\n    }\n    \n    // first trim off any polymerase run-ons, and make 3' ends consistent\n    clip_by_3_prime_dropoff(lhs);\n    clip_by_3_prime_dropoff(rhs);\n\n    for (size_t i = 0; i < lhs.size(); ++i)\n    {\n        if (kept_lhs[i])\n            scaffolds.push_back(lhs[i]);\n    }\n    \n    for (size_t i = 0; i < rhs.size(); ++i)\n    {\n        if (kept_rhs[i])\n            scaffolds.push_back(rhs[i]);\n    }\n}\n\nvoid guess_strand(int bundle_origin, \n\t\t\t\t  const vector<Scaffold>& hits,\n\t\t\t\t  vector<uint8_t>& strand_guess)\n{\n\t\n\tfor (size_t i = 0; i < hits.size(); ++i)\n\t{\n\t\tif (hits[i].strand() == CUFF_STRAND_UNKNOWN)\n\t\t\tcontinue;\n        \n\t\tfor (int K = hits[i].left(); K < hits[i].right(); ++K)\n\t\t\tstrand_guess[K - bundle_origin] |= hits[i].strand();\n        \n\t}\t\n}\n\nCuffStrand guess_strand_for_interval(const vector<uint8_t>& strand_guess, \n\t\t\t\t\t\t\t\t\t int left, \n\t\t\t\t\t\t\t\t\t int right)\n{\n\tuint8_t guess = CUFF_STRAND_UNKNOWN;\n\t\n\tfor (int i = left; i < right; ++i)\n\t{\n\t\tif (guess == CUFF_BOTH)\n\t\t\treturn (CuffStrand)guess;\n\t\tguess |= strand_guess[i];\n\t}\n\treturn (CuffStrand)guess;\n}\n\n\nbool scaffolds_for_bundle(const HitBundle& bundle, \n\t\t\t\t\t\t  vector<boost::shared_ptr<Scaffold> >& scaffolds,\n\t\t\t\t\t\t  vector<boost::shared_ptr<Scaffold> >* ref_scaffs = NULL,\n\t\t\t\t\t\t  BundleStats* stats = NULL)\n{\n    if (bundle.hits().size() >= max_frags_per_bundle)\n        return false;\n    \n\tbool ref_guided = (ref_scaffs != NULL);\n\t\n\tvector<Scaffold> hits;\n\tvector<Scaffold> tmp_scaffs;\n\t\n\tfor (size_t i = 0; i < bundle.hits().size(); ++i)\n\t{\n\t\tconst MateHit& hit = bundle.hits()[i];\n\t\thits.push_back(Scaffold(hit));\n\t}\n    \n  vector<float> depth_of_coverage(bundle.length(),0);\n\tvector<double> scaff_doc;\n\tmap<pair<int,int>, float> intron_doc;\n\t\n\t// Make sure the avg only uses stuff we're sure isn't pre-mrna fragments\n\tdouble bundle_avg_doc = compute_doc(bundle.left(), \n\t\t\t\t\t\t\t\t\t\thits, \n\t\t\t\t\t\t\t\t\t\tdepth_of_coverage, \n\t\t\t\t\t\t\t\t\t\tintron_doc,\n\t\t\t\t\t\t\t\t\t\ttrue);\n    \n    if (bundle_avg_doc > 3000)\n    {\n        filter_introns(bundle.length(), \n                       bundle.left(), \n                       hits, \n                       min_isoform_fraction, \n                       false,\n                       true);\n    }\n    \n\tif (ref_guided && enable_faux_reads && !hits.empty())\n\t{\n\t\tvector<Scaffold> pseudohits;\n\t\tBOOST_FOREACH(boost::shared_ptr<Scaffold const> ref_scaff, *ref_scaffs)\n\t\t{\n\t\t\tref_scaff->tile_with_scaffs(pseudohits, tile_len, tile_off);\n\t\t}\n\t\thits.insert(hits.end(),\n\t\t\t\t\tpseudohits.begin(),\n\t\t\t\t\tpseudohits.end());\n\t\tinplace_merge(hits.begin(),hits.end()-pseudohits.size(), hits.end(), scaff_lt);\n\t}\n\t\n\tvector<uint8_t> strand_guess(bundle.length(), CUFF_STRAND_UNKNOWN);\n\tguess_strand(bundle.left(),\n\t\t\t\t hits,\n\t\t\t\t strand_guess);\n\t\n\tfor (size_t i = 0; i < hits.size(); ++i)\n\t{\n\t\tif (hits[i].strand() == CUFF_STRAND_UNKNOWN)\n\t\t{\n            assert (!hits[i].has_intron());\n\t\t\tuint8_t guess = CUFF_STRAND_UNKNOWN;\n\t\t\tScaffold& hit = hits[i];\n\t\t\tconst vector<AugmentedCuffOp>& ops = hit.augmented_ops();\n            \n\t\t\tfor (size_t j = 0; j < ops.size(); ++j)\n\t\t\t{\n\t\t\t\tconst AugmentedCuffOp& op = ops[j];\n\t\t\t\tif (op.opcode == CUFF_UNKNOWN && op.genomic_length > (int)min_intron_length)\n\t\t\t\t{\n\t\t\t\t\tguess |= guess_strand_for_interval(strand_guess, \n\t\t\t\t\t\t\t\t\t\t\t\t\t   hit.left() - bundle.left(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t   hit.right() - bundle.left());\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n            \n\t\t\tif (guess != CUFF_BOTH && guess != CUFF_STRAND_UNKNOWN)\n\t\t\t\thits[i].strand((CuffStrand)guess);\n\t\t\t//else\n\t\t\t//\tfprintf(stderr, \"Unknown strand for pair [%d-%d]\\n\", hit.left(), hit.right());\n\t\t}\n\t}\n\t\n\tbool saw_fwd = false;\n\tbool saw_rev = false;\n\t\n\tfor (size_t i = 0; i < hits.size(); ++i)\n\t{\n\t\tconst Scaffold& hit = hits[i];\n\t\tCuffStrand hs = hit.strand();\n\t\t\t\t\t\t\n\t\tif (hs == CUFF_FWD)\n\t\t\tsaw_fwd = true;\n\t\tif (hs == CUFF_REV)\n\t\t\tsaw_rev = true;\n\t\t\n//\t\tif (hs != CUFF_REV) \n//\t\t\tfwd_hits.push_back(hit);\n//\t\tif (hs != CUFF_FWD)\n//\t\t\trev_hits.push_back(hit);\n\t}\n\n    \n\tvector<Scaffold> fwd_scaffolds;\n\tvector<Scaffold> rev_scaffolds;\n\t\n\tbool assembled_successfully = false;\n\t\n\tif (saw_fwd && saw_rev)\n\t{\n        // Forward strand hits\n        {\n            vector<Scaffold> fwd_hits;\n            for (size_t i = 0; i < hits.size(); ++i)\n            {\n                const Scaffold& hit = hits[i];\n                CuffStrand hs = hit.strand();\n                if (hs != CUFF_REV) \n                    fwd_hits.push_back(hit);\n            }\n            \n            verbose_msg (\"%s\\tFiltering forward strand\\n\", bundle_label->c_str());\n            filter_hits(bundle.length(), bundle.left(), fwd_hits);\n            assembled_successfully |= make_scaffolds(bundle.left(), \n                                                     bundle.length(), \n                                                     fwd_hits, \n                                                     fwd_scaffolds);\n        }\n        \n        // Reverse strand hits\n        {\n            vector<Scaffold> rev_hits;\n            for (size_t i = 0; i < hits.size(); ++i)\n            {\n                const Scaffold& hit = hits[i];\n                CuffStrand hs = hit.strand();\n                if (hs != CUFF_FWD)\n                    rev_hits.push_back(hit);\n            }\n            \n            verbose_msg (\"%s\\tFiltering reverse strand\\n\", bundle_label->c_str());\n            filter_hits(bundle.length(), bundle.left(), rev_hits);\n            assembled_successfully |= make_scaffolds(bundle.left(), \n                                                     bundle.length(), \n                                                     rev_hits, \n                                                     rev_scaffolds);\n        }\n\t}\n\telse\n\t{\n\t\tif (saw_fwd || (!saw_fwd && !saw_rev))\n\t\t{\n            // Forward strand hits\n            {\n                vector<Scaffold> fwd_hits;\n                for (size_t i = 0; i < hits.size(); ++i)\n                {\n                    const Scaffold& hit = hits[i];\n                    CuffStrand hs = hit.strand();\n                    if (hs != CUFF_REV) \n                        fwd_hits.push_back(hit);\n                }\n                \n                verbose_msg (\"%s\\tFiltering forward strand\\n\", bundle_label->c_str());\n                filter_hits(bundle.length(), bundle.left(), fwd_hits);\n                assembled_successfully |= make_scaffolds(bundle.left(), \n                                                         bundle.length(), \n                                                         fwd_hits, \n                                                         fwd_scaffolds);\n            \n            }\n\t\t}\n\t\telse\n\t\t{\n            // Reverse strand hits\n            {\n                vector<Scaffold> rev_hits;\n                for (size_t i = 0; i < hits.size(); ++i)\n                {\n                    const Scaffold& hit = hits[i];\n                    CuffStrand hs = hit.strand();\n                    if (hs != CUFF_FWD)\n                        rev_hits.push_back(hit);\n                }\n                \n                verbose_msg (\"%s\\tFiltering reverse strand\\n\", bundle_label->c_str());\n                filter_hits(bundle.length(), bundle.left(), rev_hits);\n                assembled_successfully |= make_scaffolds(bundle.left(), \n                                                         bundle.length(), \n                                                         rev_hits, \n                                                         rev_scaffolds);\n            }\n\t\t}\n\t}\n\t\n\tcombine_strand_assemblies(fwd_scaffolds, rev_scaffolds, tmp_scaffs, ref_scaffs);\n\n\t\n\t// Make sure all the reads are accounted for, including the redundant ones...\n\tfor (size_t i = 0; i < tmp_scaffs.size(); ++i)\n\t{\n\t\ttmp_scaffs[i].clear_hits();\n\t\tfor (size_t j = 0; j < bundle.hits().size(); ++j)\n\t\t{\n\t\t\tconst MateHit& h = bundle.hits()[j];\n\t\t\ttmp_scaffs[i].add_hit(&h);\n\t\t}\n\t}\n\t\n\tif (ref_guided)\n\t{\n\t\tscaffolds = *ref_scaffs;\n\t}\n\tif (assembled_successfully)\n\t{\n\t\tBOOST_FOREACH(Scaffold& scaff, tmp_scaffs)\n\t\t{\n\t\t\tscaffolds.push_back(boost::shared_ptr<Scaffold>(new Scaffold(scaff)));\n\t\t}\n\t}\n\tsort(scaffolds.begin(), scaffolds.end(), scaff_lt_sp);\n\t\n\treturn assembled_successfully;\n}\n\n//static long double min_abundance = 0.000001;\n\n#if ENABLE_THREADS\nboost::mutex out_file_lock;\nboost::mutex thread_pool_lock;\nint curr_threads = 0;\n\nvoid decr_pool_count()\n{\n\tthread_pool_lock.lock();\n\tcurr_threads--;\n\tthread_pool_lock.unlock();\t\n}\n#endif\n\nvoid quantitate_transcript_cluster(AbundanceGroup& transfrag_cluster,\n\t\t\t\t\t\t\t\t   //const RefSequenceTable& rt,\n                                   double total_map_mass,\n                                   vector<Gene>& genes,\n                                   bool bundle_too_large)\n{\n\tif (transfrag_cluster.abundances().empty())\n\t\treturn;\n\t\n\tvector<double> gammas;\n    \n\tvector<MateHit> hits_in_cluster;\n    \n\tget_alignments_from_scaffolds(transfrag_cluster.abundances(),\n\t\t\t\t\t\t\t\t  hits_in_cluster);\n\t\n\t// need the avg read length for depth of coverage calculation \n\tdouble avg_read_length = 0;\n\tBOOST_FOREACH (MateHit& hit, hits_in_cluster)\n\t{\n\t\tif (hit.left_alignment())\n\t\t\tavg_read_length += hit.left_alignment()->read_len(); \n\t\tif (hit.right_alignment())\n\t\t\tavg_read_length += hit.right_alignment()->read_len(); \n\t}\n\t\n    if (hits_in_cluster.size())\n        avg_read_length /= hits_in_cluster.size();\n\t\n    if (library_type != \"transfrags\")\n    {\n        if (bundle_too_large == false)\n        {\n            transfrag_cluster.calculate_abundance(hits_in_cluster);\n        }\n        else\n        {\n            BOOST_FOREACH(boost::shared_ptr<Abundance>  ab, transfrag_cluster.abundances())\n            {\n                ab->status(NUMERIC_HI_DATA);\n            }\n        }\n\t}\n    else\n    {\n        vector<boost::shared_ptr<Abundance> >& abundances = transfrag_cluster.abundances();\n        \n        int N = abundances.size();\n        double total_fpkm = 0.0;\n        vector<double> gammas;\n        for (size_t j = 0; j < N; ++j)\n        {\n            double FPKM = abundances[j]->transfrag()->fpkm();\n            abundances[j]->FPKM(FPKM);\n            total_fpkm += FPKM;\n            gammas.push_back(FPKM);\n        }\n        \n        for (size_t j = 0; j < N; ++j)\n        {\n            if (total_fpkm)\n                gammas[j] /= total_fpkm;\n        }\n        \n        vector<boost::shared_ptr<Abundance> > filtered_transcripts = abundances;\n        filter_junk_isoforms(filtered_transcripts, gammas, abundances, 0);\n        vector<bool> to_keep (abundances.size(), false);\n        for(size_t i = 0; i < abundances.size(); ++i)\n        {\n            boost::shared_ptr<Abundance> ab_i = abundances[i];\n            bool found = false;\n            BOOST_FOREACH (boost::shared_ptr<Abundance> ab_j, filtered_transcripts)\n            {\n                if (ab_i == ab_j)\n                {\n                    found = true;\n                    break;\n                }\n            }\n            if (found)\n                to_keep[i] = true;\n        }\n        \n        AbundanceGroup kept;\n        transfrag_cluster.filter_group(to_keep, kept);\n        transfrag_cluster = kept;\n    }\n    \n\tvector<AbundanceGroup> transfrags_by_strand;\n\tcluster_transcripts<ConnectByStrand>(transfrag_cluster,\n\t\t\t\t\t\t\t\t\t\t transfrags_by_strand);\n\t\n\t\n\tBOOST_FOREACH (const AbundanceGroup& strand_group, transfrags_by_strand)\n\t{\t\n\t\tvector<AbundanceGroup> transfrags_by_gene;\n\t\t\n\t\tif (bundle_mode == REF_DRIVEN)\n\t\t{\n\t\t\tcluster_transcripts<ConnectByAnnotatedGeneId>(strand_group, transfrags_by_gene);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcluster_transcripts<ConnectByExonOverlap>(strand_group, transfrags_by_gene);\n\t\t}\n\n\t\tBOOST_FOREACH(const AbundanceGroup& gene, transfrags_by_gene)\n\t\t{\n\t\t\tconst vector<boost::shared_ptr<Abundance> >& iso_abundances = gene.abundances();\n\t\t\tvector<Isoform> isoforms;\n\t\t\t\n\t\t\tint gene_id = -1;\n\t\t\tint num_ref_gene_ids = 0;\n            bool has_novel_isoform = false;\n\t\t\tstring ref_gene_id = \"\";\n\t\t\t\n\t\t\tdouble major_isoform_FPKM = 0;\n\t\t\tBOOST_FOREACH (boost::shared_ptr<Abundance> iso_ab, iso_abundances)\n\t\t\t{\n\t\t\t\tif (iso_ab->transfrag()->is_ref())\n\t\t\t\t{\n\t\t\t\t\tif (iso_ab->transfrag()->annotated_gene_id() != ref_gene_id)\n\t\t\t\t\t{\n\t\t\t\t\t\tref_gene_id = iso_ab->transfrag()->annotated_gene_id();\n\t\t\t\t\t\tnum_ref_gene_ids++;\n\t\t\t\t\t}\n\t\t\t\t}\n                else\n                {\n                    has_novel_isoform = true;\n                }\n\t\t\t\tmajor_isoform_FPKM = max(iso_ab->FPKM(), major_isoform_FPKM);\n\t\t\t}\n\t\t\t\n\t\t\tBOOST_FOREACH (boost::shared_ptr<Abundance> iso_ab, iso_abundances)\n\t\t\t{\n\t\t\t\t// Calculate transcript depth of coverage and FMI from FPKM\n\t\t\t\tdouble FPKM = iso_ab->FPKM();\n\t\t\t\tdouble density_score = major_isoform_FPKM ? (FPKM / major_isoform_FPKM) : 0;\n\t\t\t\tdouble density_per_bp = FPKM;\n\t\t\t\t\n\t\t\t\tboost::shared_ptr<Scaffold> transfrag = iso_ab->transfrag();\n\t\t\t\tassert(transfrag);\n\t\t\t\t\n\t\t\t\tdouble s_len = transfrag->length();\n\t\t\t\t\n\t\t\t\tdensity_per_bp *= (total_map_mass / 1000000.0); // yields (mass/(length/1000))\n\t\t\t\tdensity_per_bp *= (s_len/ 1000.0);\n                double estimated_count = density_per_bp;\n\t\t\t\tdensity_per_bp /= s_len;\n\t\t\t\tdensity_per_bp *= avg_read_length;\n\t\t\t\t//double density_per_bp = (FPKM * (map_mass / 1000000.0) * 1000.0);\n\t\t\t\t\n\t\t\t\tif (!allow_junk_filtering || transfrag->is_ref() || density_score > min_isoform_fraction)\n\t\t\t\t{\n\t\t\t\t\tif (gene_id == -1 && (has_novel_isoform || num_ref_gene_ids > 1))\n\t\t\t\t\t\tgene_id = get_next_gene_id();\n\t\t\t\t\t\n\t\t\t\t\tisoforms.push_back(Isoform(*transfrag,\n\t\t\t\t\t\t\t\t\t\t\t   gene_id,\n\t\t\t\t\t\t\t\t\t\t\t   (int)isoforms.size() + 1,\n\t\t\t\t\t\t\t\t\t\t\t   FPKM,\n\t\t\t\t\t\t\t\t\t\t\t   iso_ab->effective_length(),\n\t\t\t\t\t\t\t\t\t\t\t   iso_ab->gamma(),\n\t\t\t\t\t\t\t\t\t\t\t   iso_ab->FPKM_conf(),\n\t\t\t\t\t\t\t\t\t\t\t   density_per_bp, \n                                               estimated_count,\n\t\t\t\t\t\t\t\t\t\t\t   density_score,\n\t\t\t\t\t\t\t\t\t\t\t   iso_ab->status(),\n\t\t\t\t\t\t\t\t\t\t\t   ref_gene_id));\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (!isoforms.empty())\n\t\t\t{\n\t\t\t\tGene g(isoforms, gene.FPKM(), gene.FPKM_conf(), gene.status());\n\t\t\t\tgenes.push_back(g);\t\n\t\t\t}\n\t\t}\n\t\t\n\t}\n    \n}\n\nvoid quantitate_transcript_clusters(vector<boost::shared_ptr<Scaffold> >& scaffolds,\n\t\t\t\t\t\t\t\t\tboost::shared_ptr<ReadGroupProperties> rg_props,\n\t\t\t\t\t\t\t\t\tvector<Gene>& genes,\n                                    bool bundle_too_large)\n{\t\n\t//vector<boost::shared_ptr<Scaffold> > partials;\n\t//vector<boost::shared_ptr<Scaffold> > completes;\n    \n    long double total_map_mass = rg_props->normalized_map_mass();\n    \n    vector<boost::shared_ptr<Scaffold> > split_partials;\n    // Cleave the partials at their unknowns to minimize FPKM dilation on  \n    // the low end of the expression profile. \n    for (size_t i = 0; i < scaffolds.size(); ++i) \n    { \n        vector<Scaffold> c; \n        scaffolds[i]->get_complete_subscaffolds(c); \n        BOOST_FOREACH (Scaffold& s, c)\n        {\n            split_partials.push_back(boost::shared_ptr<Scaffold>(new Scaffold(s))); \n        }\n    } \n    \n    scaffolds = split_partials;\n\t\n\tvector<boost::shared_ptr<Abundance> > abundances;\n\tBOOST_FOREACH(boost::shared_ptr<Scaffold> s, scaffolds)\n\t{\n\t\tTranscriptAbundance* pT = new TranscriptAbundance;\n\t\tpT->transfrag(s);\n\t\tboost::shared_ptr<Abundance> ab(pT);\n\t\tabundances.push_back(ab);\n\t}\n\t\n\tAbundanceGroup transfrags = AbundanceGroup(abundances);\n\t\n    set<boost::shared_ptr<ReadGroupProperties const> > read_groups;\n    read_groups.insert(rg_props);\n    \n    transfrags.init_rg_props(read_groups);\n    \n\tvector<AbundanceGroup> transfrags_by_cluster;\n\t\n\tcluster_transcripts<ConnectByExonOverlap>(transfrags,\n                                              transfrags_by_cluster);\n\t\n\tBOOST_FOREACH(AbundanceGroup& cluster, transfrags_by_cluster)\n\t{\n\t\tquantitate_transcript_cluster(cluster, total_map_mass, genes, bundle_too_large);\n\t}\n    verbose_msg( \"%s\\tBundle quantitation complete\\n\", bundle_label->c_str());\n}\n\nvoid assemble_bundle(const RefSequenceTable& rt,\n\t\t\t\t\t HitBundle* bundle_ptr, \n\t\t\t\t\t boost::shared_ptr<ReadGroupProperties> rg_props,\n                     boost::shared_ptr<BiasLearner> bl_ptr,\n\t\t\t\t\t FILE* ftranscripts,\n\t\t\t\t\t FILE* fgene_abundances,\n\t\t\t\t\t FILE* ftrans_abundances,\n\t\t\t\t\t FILE* fskipped)\n{\n    long double map_mass = rg_props->normalized_map_mass();\n    \n\tHitBundle& bundle = *bundle_ptr;\n    \n    char bundle_label_buf[2048];\n    sprintf(bundle_label_buf, \n            \"%s:%d-%d\", \n            rt.get_name(bundle.ref_id()),\n            bundle.left(),\n            bundle.right());\n\n#if ENABLE_THREADS\n    bundle_label.reset(new string(bundle_label_buf));\n#else\n    bundle_label = boost::shared_ptr<string>(new string(bundle_label_buf));\n#endif\n\n    verbose_msg( \"%s\\tProcessing new bundle with %d alignments\\n\", \n            bundle_label->c_str(),\n            (int)bundle.hits().size());\n\n#if ENABLE_THREADS\t\n\tboost::this_thread::at_thread_exit(decr_pool_count);\n#endif\n\t\n\tvector<boost::shared_ptr<Scaffold> > scaffolds;\n\t\n    bool successfully_assembled = true;\n    \n\tswitch(bundle_mode)\n\t{\n\t\tcase REF_DRIVEN:\n\t\t\tscaffolds = bundle.ref_scaffolds();\n\t\t\tbreak;\n\t\tcase REF_GUIDED:\n\t\t\tsuccessfully_assembled = scaffolds_for_bundle(bundle, scaffolds, &bundle.ref_scaffolds());\n\t\t\tbreak;\n\t\tcase HIT_DRIVEN:\n\t\t\tsuccessfully_assembled = scaffolds_for_bundle(bundle, scaffolds);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tassert(false);\n\t}\n\t\n    if (successfully_assembled == false)\n    {\n\n#if ENABLE_THREADS\t\n        out_file_lock.lock();\n#endif\n        \n        int mask_region_id = get_next_skipped_region_id();\n        fprintf(fskipped, \n                \"%s\\tCufflinks\\texon\\t%d\\t%d\\t%d\\t%s\\t.\\tgene_id \\\"mask_%d\\\"; transcript_id \\\"mask_id%d/+\\\";\\n\",\n                rt.get_name(bundle.ref_id()),\n                bundle.left() + 1,\n                bundle.right(), // GTF intervals are inclusive on both ends, but ours are half-open\n                0,\n                \"+\",\n                mask_region_id,\n                mask_region_id);\n        \n        fprintf(fskipped, \n                \"%s\\tCufflinks\\texon\\t%d\\t%d\\t%d\\t%s\\t.\\tgene_id \\\"mask_%d\\\"; transcript_id \\\"mask_id%d/-\\\";\\n\",\n                rt.get_name(bundle.ref_id()),\n                bundle.left() + 1,\n                bundle.right(), // GTF intervals are inclusive on both ends, but ours are half-open\n                0,\n                \"-\",\n                mask_region_id,\n                mask_region_id);\n        \n        \n#if ENABLE_THREADS\t\n        out_file_lock.unlock();\n#endif\n        delete bundle_ptr;\n\t\treturn;\n    }\n    \n\tif (scaffolds.empty())\n\t{\n\t\tdelete bundle_ptr;\n\t\treturn;\n\t}\n\t\t\n\tvector<Gene> genes;\n    \n    bool bundle_too_large = bundle_ptr->hits().size() >= max_frags_per_bundle;\n    \n    // FIXME: this routine does more than just quantitation, and should be \n    // renamed or refactored.\n    quantitate_transcript_clusters(scaffolds,\n                                   rg_props,\n                                   genes,\n                                   bundle_too_large);\n    \n    verbose_msg( \"%s\\tFiltering bundle assembly\\n\", bundle_label->c_str());\n    \n    if (allow_junk_filtering)\n        filter_junk_genes(genes);\n\n\t\n\tif (!final_est_run && bundle_mode==REF_DRIVEN) // Bias needs to be learned\n\t{\n\t\tfor (size_t i = 0; i < genes.size(); ++i)\n\t\t{\n            for (size_t j = 0; j <genes[i].isoforms().size(); ++j)\n            {\n                bl_ptr -> preProcessTranscript(genes[i].isoforms()[j].scaffold()); \n\t\t\t}\n\t\t}\n\t}\n\t\n#if ENABLE_THREADS\t\n\tout_file_lock.lock();\n#endif\n    \n    // Get hit_introns for full_read_support test if ref-guided\n    set<AugmentedCuffOp>* hit_introns = NULL;\n    if (init_bundle_mode == REF_GUIDED)\n    {\n        hit_introns = new set<AugmentedCuffOp>();\n        BOOST_FOREACH(const MateHit& h, bundle.non_redundant_hits())\n        {\n            Scaffold s(h);\n            BOOST_FOREACH (AugmentedCuffOp a, s.augmented_ops())\n            {\n                if (a.opcode == CUFF_INTRON)\n                {\n                    hit_introns->insert(a);\n                }\n            }\n        }\n    }\n    \n\t\n\tsize_t num_scaffs_reported = 0;\n\tfor (size_t i = 0; i < genes.size(); ++i)\n\t{\n\t\tconst Gene& gene = genes[i];\n\t\tconst vector<Isoform>& isoforms = gene.isoforms();\n        set<string> annotated_gene_names;\n        set<string> annotated_tss_ids;\n\t\tfor (size_t j = 0; j < isoforms.size(); ++j)\n\t\t{\n\t\t\tconst Isoform& iso = isoforms[j];\n\t\t\t\n\t\t\tvector<const MateHit*> H(iso.scaffold().mate_hits().size(), 0);\n\t\t\tcopy(iso.scaffold().mate_hits().begin(), \n\t\t\t\t iso.scaffold().mate_hits().end(),\n\t\t\t\t H.begin());\n\t\t\t\n\t\t\tvector<string> isoform_exon_recs;\n            \n\t\t\tiso.get_gtf(isoform_exon_recs, rt, hit_introns);\n\t\t\t\n\t\t\tfor (size_t g = 0; g < isoform_exon_recs.size(); ++g)\n\t\t\t{\n\t\t\t\tfprintf(ftranscripts, \"%s\", isoform_exon_recs[g].c_str());\n\t\t\t}\n\t\t\t\n\t\t\tfflush(ftranscripts);\n\t\t\t\n\t\t\tconst char* status;\n\t\t\tif (iso.status()==NUMERIC_OK) \n\t\t\t\tstatus = \"OK\";\n\t\t\telse if (iso.status() == NUMERIC_LOW_DATA)\n                status = \"LOWDATA\";\n            else if (iso.status() == NUMERIC_HI_DATA)\n                status = \"HIDATA\";\n            else if (iso.status() == NUMERIC_FAIL)\n\t\t\t\tstatus = \"FAIL\";\n            else\n                assert (false);\n\t\t\t\n\t\t\tfprintf(ftrans_abundances,\"%s\\t%c\\t%s\\t%s\\t%s\\t%s\\t%s:%d-%d\\t%d\\t%lg\\t%lg\\t%lg\\t%lg\\t%s\\n\", \n\t\t\t\t\tiso.trans_id().c_str(),\n                    (iso.scaffold().nearest_ref_classcode() == 0 ? '-' : iso.scaffold().nearest_ref_classcode()),\n                    (iso.scaffold().nearest_ref_id() == \"\" ? \"-\" : iso.scaffold().nearest_ref_id().c_str()),\n                    gene.gene_id().c_str(),\n                    (iso.scaffold().annotated_gene_name() == \"\" ? \"-\" : iso.scaffold().annotated_gene_name().c_str()), \n                    (iso.scaffold().annotated_tss_id() == \"\" ? \"-\" : iso.scaffold().annotated_tss_id().c_str()),\n\t\t\t\t\trt.get_name(bundle.ref_id()),\n\t\t\t\t\tiso.scaffold().left(),\n\t\t\t\t\tiso.scaffold().right(),\n                    iso.scaffold().length(),\n                    iso.coverage(),\n                    iso.FPKM(),\n\t\t\t\t\tiso.confidence().low,\n\t\t\t\t\tiso.confidence().high,\n                    status);\n\t\t\tfflush(ftrans_abundances);\n\t\t\t\n            annotated_gene_names.insert(iso.scaffold().annotated_gene_name());\n            annotated_tss_ids.insert(iso.scaffold().annotated_tss_id());\n            \n\t\t\tnum_scaffs_reported++;\n\t\t}\n\t\t\n\t\tconst char* status = \"OK\";\n        if (gene.status()==NUMERIC_OK) \n            status = \"OK\";\n        else if (gene.status() == NUMERIC_LOW_DATA)\n            status = \"LOWDATA\";\n        else if (gene.status() == NUMERIC_HI_DATA)\n            status = \"HIDATA\";\n        else if (gene.status() == NUMERIC_FAIL)\n            status = \"FAIL\";\n        else\n            assert (false);\n\n        string gene_names = cat_strings(annotated_gene_names);\n        if (gene_names == \"\") gene_names = \"-\";\n        string tss_ids = cat_strings(annotated_tss_ids);\n        if (tss_ids == \"\") tss_ids = \"-\";\n        \n        fprintf(fgene_abundances,\"%s\\t%c\\t%s\\t%s\\t%s\\t%s\\t%s:%d-%d\\t%s\\t%s\\t%lg\\t%lg\\t%lg\\t%s\\n\",\n                gene.gene_id().c_str(),\n                '-',\n                \"-\",\n                gene.gene_id().c_str(),\n                gene_names.c_str(), \n                tss_ids.c_str(),\n                rt.get_name(bundle.ref_id()),\n                gene.left(),\n                gene.right(),\n                \"-\",\n                \"-\",\n                gene.FPKM(),\n                gene.confidence().low,\n                gene.confidence().high,\n                status);\n\t\tfflush(fgene_abundances);\n\t}\n    delete hit_introns;\n\t//fprintf(fbundle_tracking, \"CLOSE %d\\n\", bundle.id());\n\t\n\tif (bundle_mode==REF_DRIVEN && num_scaffs_reported > bundle.ref_scaffolds().size())\n    {\n\t\tfprintf(stderr, \"Error: reported more isoforms than in reference!\\n\");\n\t\texit(1);\n\t}\n\t\n    verbose_msg( \"%s\\tBundle complete\\n\", bundle_label->c_str());\n    \n#if ENABLE_THREADS\n\tout_file_lock.unlock();\n#endif\n\n    genes.clear();\n    scaffolds.clear();\n\tdelete bundle_ptr;\n}\n\nbool assemble_hits(BundleFactory& bundle_factory, boost::shared_ptr<BiasLearner> bl_ptr)\n{\n\t//srand(time(0));\n\t\t\n\tRefSequenceTable& rt = bundle_factory.ref_table();\n    \n\t//FILE* fbundle_tracking = fopen(\"open_bundles\", \"w\");\n    \n\t//FILE* fstats = fopen(\"bundles.stats\", \"w\");\n\tFILE* ftrans_abundances = fopen(string(output_dir + \"/\" + \"isoforms.fpkm_tracking\").c_str(), \"w\");\n\t//fprintf(ftrans_abundances,\"trans_id\\tbundle_id\\tchr\\tleft\\tright\\tFPKM\\tFMI\\tfrac\\tFPKM_conf_lo\\tFPKM_conf_hi\\tcoverage\\tlength\\teffective_length\\tstatus\\n\");\n\tfprintf(ftrans_abundances,\"tracking_id\\tclass_code\\tnearest_ref_id\\tgene_id\\tgene_short_name\\ttss_id\\tlocus\\tlength\\tcoverage\\tFPKM\\tFPKM_conf_lo\\tFPKM_conf_hi\\tFPKM_status\\n\");\n\tFILE* fgene_abundances = fopen(string(output_dir + \"/\" + \"genes.fpkm_tracking\").c_str(), \"w\");\n\t//fprintf(fgene_abundances,\"gene_id\\tbundle_id\\tchr\\tleft\\tright\\tFPKM\\tFPKM_conf_lo\\tFPKM_conf_hi\\tstatus\\n\");\n    fprintf(fgene_abundances,\"tracking_id\\tclass_code\\tnearest_ref_id\\tgene_id\\tgene_short_name\\ttss_id\\tlocus\\tlength\\tcoverage\\tFPKM\\tFPKM_conf_lo\\tFPKM_conf_hi\\tFPKM_status\\n\");\n    \n\tFILE* ftranscripts = fopen(string(output_dir + \"/\" + \"transcripts.gtf\").c_str(), \"w\");\n    FILE* fskipped = 0;\n\tif(bundle_mode != REF_DRIVEN)\n\t\tfskipped = fopen(string(output_dir + \"/\" + \"skipped.gtf\").c_str(), \"w\");\n    \n\tstring process;\n\tif (corr_bias && corr_multi && final_est_run)\n\t\tprocess = \"Re-estimating abundances with bias and multi-read correction.\";\n\telse if (corr_multi && final_est_run)\n\t\tprocess = \"Re-estimating abundances with multi-read correction.\";\n\telse if (corr_bias && final_est_run)\n\t\tprocess = \"Re-estimating abundances with bias correction.\";\n\telse if (bundle_mode==REF_DRIVEN && final_est_run)\n\t\tprocess = \"Estimating transcript abundances.\"; \n\telse if (bundle_mode==REF_DRIVEN && corr_bias)\n\t\tprocess = \"Learning bias parameters.\";\n\telse if (bundle_mode==REF_DRIVEN && corr_multi)\n\t\tprocess = \"Initializing transcript abundances for multi-read correction.\";\n\telse if (corr_multi)\n\t\tprocess = \"Assembling transcripts and initializing abundances for multi-read correction.\";\n\telse\n\t\tprocess = \"Assembling transcripts and estimating abundances.\";\n\t\t\n\tProgressBar p_bar(process, bundle_factory.read_group_properties()->total_map_mass());\n\n\twhile(true)\n\t{\n\t\tHitBundle* bundle_ptr = new HitBundle();\n\t\t\n\t\tif (!bundle_factory.next_bundle(*bundle_ptr, true))\n\t\t{\n\t\t\tdelete bundle_ptr;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tHitBundle& bundle = *bundle_ptr;\n        \n\t\tchar bundle_label_buf[2048];\n\t\tsprintf(bundle_label_buf, \n\t\t\t\t\"%s:%d-%d\", \n\t\t\t\trt.get_name(bundle.ref_id()),\n\t\t\t\tbundle.left(),\n\t\t\t\tbundle.right());\n\n\t\tif (bundle.right() - bundle.left() > max_gene_length)\n\t\t{\n\t\t\tfprintf(stderr, \"\\n%s\\tWarning: Skipping large bundle.\\n\", bundle_label_buf);\n\t\t\tdelete bundle_ptr;\n\t\t\tcontinue;\n\t\t}\n\n\t\tBundleStats stats;\n#if ENABLE_THREADS\t\t\t\n\t\twhile(1)\n\t\t{\n\t\t\tthread_pool_lock.lock();\n\t\t\tif (curr_threads < num_threads)\n\t\t\t{\n\t\t\t\tthread_pool_lock.unlock();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tthread_pool_lock.unlock();\n\t\t\t\n\t\t\tboost::this_thread::sleep(boost::posix_time::milliseconds(5));\n\t\t\t\n\t\t}\n#endif\n\t\tp_bar.update(bundle_label_buf, bundle.raw_mass());\t\n\n#if ENABLE_THREADS\t\t\t\n\t\tthread_pool_lock.lock();\n\t\tcurr_threads++;\n\t\tthread_pool_lock.unlock();\n\t\t\n\t\tboost::thread asmbl(assemble_bundle,\n\t\t\t\t\t boost::cref(rt), \n\t\t\t\t\t bundle_ptr,\n                     bundle_factory.read_group_properties(),\n\t\t\t\t\t bl_ptr,\n\t\t\t\t\t ftranscripts, \n\t\t\t\t\t fgene_abundances,\n\t\t\t\t\t ftrans_abundances,\n                     fskipped);\n#else\n\t\tassemble_bundle(boost::cref(rt), \n\t\t\t\t\t\tbundle_ptr, \n\t\t\t\t\t\tbundle_factory.read_group_properties(),\n                        bl_ptr,\n\t\t\t\t\t\tftranscripts,\n\t\t\t\t\t\tfgene_abundances,\n\t\t\t\t\t\tftrans_abundances,\n                        fskipped);\n#endif\t\t\t\n\t\t\n\t}\n\n#if ENABLE_THREADS\t\n\twhile(1)\n\t{\n\t\tthread_pool_lock.lock();\n\t\tif (curr_threads == 0)\n\t\t{\n\t\t\tthread_pool_lock.unlock();\n\t\t\tbreak;\n\t\t}\n\t\tp_bar.remaining(curr_threads);\n\t\t\n\t\tthread_pool_lock.unlock();\n\t\t//fprintf(stderr, \"waiting to exit\\n\");\n\t\tboost::this_thread::sleep(boost::posix_time::milliseconds(5));\n\t}\n#endif\n\t\n\tp_bar.complete();\n\t\n\tif(!final_est_run && bundle_mode==REF_DRIVEN) // We are learning bias\n\t{\n\t\tbl_ptr->normalizeParameters();\n        if (output_bias_params)\n        {\n            \n            FILE* output_file = fopen(string(output_dir + \"/bias_params.info\").c_str(), \"w\");\n            bl_ptr->output(output_file, user_label, 0);\n        }\n\t}\n\t\n\tfclose(ftranscripts);\n\tfclose(ftrans_abundances);\n\tfclose(fgene_abundances);\n\tif(fskipped)\n\t  fclose(fskipped);\n\treturn true;\n}\n\t\nvoid driver(const string& hit_file_name, FILE* ref_gtf, FILE* mask_gtf)\n{\t\n    ReadTable it;\n\tRefSequenceTable rt(true, false);\n\t    \n\tboost::shared_ptr<HitFactory> hit_factory(createSamHitFactory(hit_file_name, it, rt));\n\t\n\tboost::shared_ptr<BundleFactory> bundle_factory = boost::shared_ptr<BundleFactory>(new BundleFactory(hit_factory, bundle_mode));\n\tboost::shared_ptr<ReadGroupProperties> rg_props = bundle_factory->read_group_properties();\n\tBadIntronTable bad_introns;\n    \n    rt.print_rec_ordering();\n    \n    vector<boost::shared_ptr<Scaffold> > ref_mRNAs;\n    if (ref_gtf)\n    {\n        boost::crc_32_type ref_gtf_crc_result;\n        ::load_ref_rnas(ref_gtf, bundle_factory->ref_table(), ref_mRNAs, ref_gtf_crc_result, corr_bias && bundle_mode == REF_DRIVEN, false);\n        bundle_factory->set_ref_rnas(ref_mRNAs);\n    }\n    rt.print_rec_ordering();\n    vector<boost::shared_ptr<Scaffold> > mask_rnas;\n    if (mask_gtf)\n    {\n        boost::crc_32_type mask_gtf_crc_result;\n        ::load_ref_rnas(mask_gtf, bundle_factory->ref_table(), mask_rnas, mask_gtf_crc_result, false, false);\n        bundle_factory->set_mask_rnas(mask_rnas);\n    }\n    \n    vector<LocusCount> compatible_count_table;\n    vector<LocusCount> total_count_table;\n    IdToLocusMap id_to_locus_map(boost::shared_ptr<map<string, set<string> > >(new map<string, set<string> >()));\n    \n    if (bundle_mode != HIT_DRIVEN)\n        inspect_map(bundle_factory, NULL, compatible_count_table, total_count_table, id_to_locus_map);\n    else \n        inspect_map(bundle_factory, &bad_introns, compatible_count_table, total_count_table, id_to_locus_map);\n    \n    rg_props->raw_compatible_counts(compatible_count_table);\n    rg_props->raw_total_counts(total_count_table);\n    \n    vector<boost::shared_ptr<ReadGroupProperties> > read_groups;\n    read_groups.push_back(rg_props);\n    \n    normalize_counts(read_groups);\n\n    \n    verbose_msg(\"%d ReadHits still live\\n\", num_deleted);\n    verbose_msg(\"Found %lu reference contigs\\n\", rt.size());\n    \n    BOOST_FOREACH(boost::shared_ptr<Scaffold> ref_scaff, ref_mRNAs)\n    {\n        ref_scaff->clear_hits();\n    }\n    \n    //fprintf(stderr, \"ReadHit delete count is %d\\n\", num_deleted);\n    \n\tboost::shared_ptr<BiasLearner> bl_ptr(new BiasLearner(rg_props->frag_len_dist()));\n    bundle_factory->read_group_properties(rg_props);\n\n\t//if (ref_gtf) -- why? bad introns are bad\n\t\tbundle_factory->bad_intron_table(bad_introns);\n\t\n\tmax_frag_len = rg_props->frag_len_dist()->max();\n\tmin_frag_len = rg_props->frag_len_dist()->min();\n\tverbose_msg(\"\\tTotal map density: %Lf\\n\", rg_props->total_map_mass());\n\n\tif (corr_bias || corr_multi) final_est_run = false;\n\n\tassemble_hits(*bundle_factory, bl_ptr);\n\n\tif (final_est_run) \n\t{\n\t  //delete bl_ptr;\n\t  ref_mRNAs.clear();\n\t  return;\n\t}\n\n\thit_factory->reset();\n\t\n\tBundleFactory bundle_factory2(hit_factory, REF_DRIVEN);\n\trg_props->bias_learner(boost::shared_ptr<BiasLearner const>(bl_ptr));\n\trg_props->multi_read_table()->valid_mass(true);\n\tbundle_factory2.read_group_properties(rg_props);\n\n    if (bundle_mode==HIT_DRIVEN || bundle_mode==REF_GUIDED)\n    {\n\t\tref_gtf = fopen(string(output_dir + \"/transcripts.gtf\").c_str(), \"r\");\n        ref_mRNAs.clear();\n        boost::crc_32_type ref_gtf_crc_result;\n        ::load_ref_rnas(ref_gtf, bundle_factory2.ref_table(), ref_mRNAs, ref_gtf_crc_result, corr_bias, true);\n    }    \n\tbundle_factory2.set_ref_rnas(ref_mRNAs);\n    if (mask_gtf)\n    {\n        mask_rnas.clear();\n        boost::crc_32_type mask_gtf_crc_result;\n        ::load_ref_rnas(mask_gtf, bundle_factory2.ref_table(), mask_rnas, mask_gtf_crc_result, false, false);\n        bundle_factory2.set_mask_rnas(mask_rnas);\n    }    \n\tbundle_factory2.reset();\n\t\n\tif(corr_bias && (bundle_mode==HIT_DRIVEN || bundle_mode==REF_GUIDED)) \n\t{\n        // We still need to learn the bias since we didn't have the sequences before assembly\n\t\tlearn_bias(bundle_factory2, *bl_ptr);\n\t\tbundle_factory2.reset();\n\t}\n\n    bundle_mode = REF_DRIVEN;\n\tfinal_est_run = true;\n\tassemble_hits(bundle_factory2, bl_ptr);\n\tref_mRNAs.clear();\n\t//delete bl_ptr;\n}\n\nint main(int argc, char** argv)\n{\t\n    init_library_table();\n    init_cufflinks_lib_norm_method_table();\n    \n  string cmdline;\n  for (int i=0;i<argc;i++) {\n    cmdline+=argv[i];\n    cmdline+=\" \";\n    }\n\tint parse_ret = parse_options(argc,argv);\n    if (parse_ret)\n        return parse_ret;\n\t\n    if (!use_total_mass && !use_compat_mass)\n    {\n        use_total_mass = true;\n        use_compat_mass = false;   \n    }\n    \n    if(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n\t\n    if (!no_update_check)\n        check_version(PACKAGE_VERSION);\n    \n    if (cuff_quiet || cuff_verbose)\n      fprintf(stderr, \"Command line:\\n%s\\n\", cmdline.c_str());\n    string sam_hits_file_name = argv[optind++];\n\t\n\n\tif (random_seed == -1)\n        random_seed = boost::mt19937::default_seed;\n    \n\tsrand48(random_seed);\n\t\n\tFILE* ref_gtf = NULL;\n\tif (ref_gtf_filename != \"\")\n\t{\n\t\tref_gtf = fopen(ref_gtf_filename.c_str(), \"r\");\n\t\tif (!ref_gtf)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open reference GTF file %s for reading\\n\",\n\t\t\t\t\tref_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n    \n    FILE* mask_gtf = NULL;\n\tif (mask_gtf_filename != \"\")\n\t{\n\t\tmask_gtf = fopen(mask_gtf_filename.c_str(), \"r\");\n\t\tif (!mask_gtf)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open mask GTF file %s for reading\\n\",\n\t\t\t\t\tmask_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\t\n    if (output_dir != \"\")\n    {\n        int retcode = mkpath(output_dir.c_str(), 0777);\n        if (retcode == -1)\n        {\n            if (errno != EEXIST)\n            {\n                fprintf (stderr, \n                         \"Error: cannot create directory %s\\n\", \n                         output_dir.c_str());\n                exit(1);\n            }\n        }\n    }\n    \n    driver(sam_hits_file_name, ref_gtf, mask_gtf);\n\t\n\treturn 0;\n}\n"
  },
  {
    "path": "src/cufflinks.xcodeproj/cole.pbxuser",
    "content": "// !$*UTF8*$!\n{\n\t08FB7793FE84155DC02AAC07 /* Project object */ = {\n\t\tactiveBuildConfigurationName = Debug;\n\t\tactiveExecutable = ED27F9E00F7950E80072CA01 /* cufflinks */;\n\t\tactiveTarget = D28A88AD04BDD90700651E21 /* cufflinks */;\n\t\taddToTargets = (\n\t\t\tD28A88AD04BDD90700651E21 /* cufflinks */,\n\t\t);\n\t\tbreakpoints = (\n\t\t\tED7A92ED1131E9C1000EA5B4 /* bundles.cpp:523 */,\n\t\t\tED7A92F51131EA34000EA5B4 /* gtf_tracking.cpp:139 */,\n\t\t\tED7A92FE1131EAF9000EA5B4 /* bundles.cpp:498 */,\n\t\t\tED7A93101131EBA2000EA5B4 /* bundles.cpp:365 */,\n\t\t\tED7A934E1131F07A000EA5B4 /* gtf_tracking.cpp:139 */,\n\t\t\tED0A973A1147289600484F91 /* scaffolds.cpp:462 */,\n\t\t\tED0A973C1147289900484F91 /* scaffolds.cpp:393 */,\n\t\t\tED0A977C114740EB00484F91 /* abundances.cpp:886 */,\n\t\t\tED0A97A8114745EB00484F91 /* abundances.cpp:1118 */,\n\t\t\tED0A97BF114AC28F00484F91 /* bundles.cpp:528 */,\n\t\t\tED0A97C1114AC29100484F91 /* bundles.cpp:527 */,\n\t\t\tED0A97DE114AC5EB00484F91 /* assemble.cpp:2123 */,\n\t\t);\n\t\tcodeSenseManager = EDD5751A0F536FC70029FDB4 /* Code sense */;\n\t\texecutables = (\n\t\t\tED27F9D40F7950C60072CA01 /* test_cufflinks */,\n\t\t\tED27F9E00F7950E80072CA01 /* cufflinks */,\n\t\t\tEDF061F51055D39400196C88 /* cuffcompare */,\n\t\t\tED5A962C1096AD1F001BA454 /* cuffdiff */,\n\t\t);\n\t\tperUserDictionary = {\n\t\t\t\"PBXConfiguration.PBXBreakpointsDataSource.v1:1CA23EDF0692099D00951B8B\" = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t20,\n\t\t\t\t\t20,\n\t\t\t\t\t299,\n\t\t\t\t\t20,\n\t\t\t\t\t202,\n\t\t\t\t\t201,\n\t\t\t\t\t135,\n\t\t\t\t\t20,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXBreakpointsDataSource_ActionID,\n\t\t\t\t\tPBXBreakpointsDataSource_TypeID,\n\t\t\t\t\tPBXBreakpointsDataSource_BreakpointID,\n\t\t\t\t\tPBXBreakpointsDataSource_UseID,\n\t\t\t\t\tPBXBreakpointsDataSource_LocationID,\n\t\t\t\t\tPBXBreakpointsDataSource_ConditionID,\n\t\t\t\t\tPBXBreakpointsDataSource_IgnoreCountID,\n\t\t\t\t\tPBXBreakpointsDataSource_ContinueID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_LocationID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t20,\n\t\t\t\t\t300,\n\t\t\t\t\t520,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXErrorsWarningsDataSource_TypeID,\n\t\t\t\t\tPBXErrorsWarningsDataSource_MessageID,\n\t\t\t\t\tPBXErrorsWarningsDataSource_LocationID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_CommentsID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t22,\n\t\t\t\t\t300,\n\t\t\t\t\t715,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXExecutablesDataSource_ActiveFlagID,\n\t\t\t\t\tPBXExecutablesDataSource_NameID,\n\t\t\t\t\tPBXExecutablesDataSource_CommentsID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t20,\n\t\t\t\t\t827,\n\t\t\t\t\t20,\n\t\t\t\t\t48,\n\t\t\t\t\t43,\n\t\t\t\t\t43,\n\t\t\t\t\t20,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXFileDataSource_FiletypeID,\n\t\t\t\t\tPBXFileDataSource_Filename_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Built_ColumnID,\n\t\t\t\t\tPBXFileDataSource_ObjectSize_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Errors_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Warnings_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Target_ColumnID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t670,\n\t\t\t\t\t72,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXFindDataSource_MessageID,\n\t\t\t\t\tPBXFindDataSource_LocationID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.PBXSymbolsDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXSymbolsDataSource_SymbolNameID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t16,\n\t\t\t\t\t200,\n\t\t\t\t\t50,\n\t\t\t\t\t704,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXSymbolsDataSource_SymbolTypeIconID,\n\t\t\t\t\tPBXSymbolsDataSource_SymbolNameID,\n\t\t\t\t\tPBXSymbolsDataSource_SymbolTypeID,\n\t\t\t\t\tPBXSymbolsDataSource_ReferenceNameID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXFileTableDataSource3.XCSCMDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t20,\n\t\t\t\t\t20,\n\t\t\t\t\t673,\n\t\t\t\t\t20,\n\t\t\t\t\t48.16259765625,\n\t\t\t\t\t43,\n\t\t\t\t\t43,\n\t\t\t\t\t20,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXFileDataSource_SCM_ColumnID,\n\t\t\t\t\tPBXFileDataSource_FiletypeID,\n\t\t\t\t\tPBXFileDataSource_Filename_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Built_ColumnID,\n\t\t\t\t\tPBXFileDataSource_ObjectSize_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Errors_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Warnings_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Target_ColumnID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = {\n\t\t\t\tPBXFileTableDataSourceColumnSortingDirectionKey = \"-1\";\n\t\t\t\tPBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;\n\t\t\t\tPBXFileTableDataSourceColumnWidthsKey = (\n\t\t\t\t\t20,\n\t\t\t\t\t787,\n\t\t\t\t\t60,\n\t\t\t\t\t20,\n\t\t\t\t\t48,\n\t\t\t\t\t43,\n\t\t\t\t\t43,\n\t\t\t\t);\n\t\t\t\tPBXFileTableDataSourceColumnsKey = (\n\t\t\t\t\tPBXFileDataSource_FiletypeID,\n\t\t\t\t\tPBXFileDataSource_Filename_ColumnID,\n\t\t\t\t\tPBXTargetDataSource_PrimaryAttribute,\n\t\t\t\t\tPBXFileDataSource_Built_ColumnID,\n\t\t\t\t\tPBXFileDataSource_ObjectSize_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Errors_ColumnID,\n\t\t\t\t\tPBXFileDataSource_Warnings_ColumnID,\n\t\t\t\t);\n\t\t\t};\n\t\t\tPBXPerProjectTemplateStateSaveDate = 294857015;\n\t\t\tPBXWorkspaceStateSaveDate = 294857015;\n\t\t};\n\t\tperUserProjectItems = {\n\t\t\tED0A973E114728B000484F91 /* PBXTextBookmark */ = ED0A973E114728B000484F91 /* PBXTextBookmark */;\n\t\t\tED0A973F114728B000484F91 /* PBXTextBookmark */ = ED0A973F114728B000484F91 /* PBXTextBookmark */;\n\t\t\tED0A9756114736D000484F91 /* PBXTextBookmark */ = ED0A9756114736D000484F91 /* PBXTextBookmark */;\n\t\t\tED0A975C114736F800484F91 /* PBXTextBookmark */ = ED0A975C114736F800484F91 /* PBXTextBookmark */;\n\t\t\tED0A977F114741A700484F91 /* PBXTextBookmark */ = ED0A977F114741A700484F91 /* PBXTextBookmark */;\n\t\t\tED0A97B811474BFF00484F91 /* PBXTextBookmark */ = ED0A97B811474BFF00484F91 /* PBXTextBookmark */;\n\t\t\tED0A97C3114AC29600484F91 /* PBXTextBookmark */ = ED0A97C3114AC29600484F91 /* PBXTextBookmark */;\n\t\t\tED0A97C4114AC29600484F91 /* PBXTextBookmark */ = ED0A97C4114AC29600484F91 /* PBXTextBookmark */;\n\t\t\tED0A97C6114AC29600484F91 /* PBXTextBookmark */ = ED0A97C6114AC29600484F91 /* PBXTextBookmark */;\n\t\t\tED0A97D3114AC2B000484F91 /* PBXTextBookmark */ = ED0A97D3114AC2B000484F91 /* PBXTextBookmark */;\n\t\t\tED0A97E9114AC74400484F91 /* PBXTextBookmark */ = ED0A97E9114AC74400484F91 /* PBXTextBookmark */;\n\t\t\tED0A97FD114AED8200484F91 /* PBXTextBookmark */ = ED0A97FD114AED8200484F91 /* PBXTextBookmark */;\n\t\t\tED11ECCA112DBE9C00BCC333 /* PBXTextBookmark */ = ED11ECCA112DBE9C00BCC333 /* PBXTextBookmark */;\n\t\t\tED11ECCC112DBE9C00BCC333 /* PBXTextBookmark */ = ED11ECCC112DBE9C00BCC333 /* PBXTextBookmark */;\n\t\t\tED352ECC10DDC130004B91A6 /* PBXTextBookmark */ = ED352ECC10DDC130004B91A6 /* PBXTextBookmark */;\n\t\t\tED7A92501131DAC7000EA5B4 /* PBXTextBookmark */ = ED7A92501131DAC7000EA5B4 /* PBXTextBookmark */;\n\t\t\tED7A925F1131DDC4000EA5B4 /* PBXTextBookmark */ = ED7A925F1131DDC4000EA5B4 /* PBXTextBookmark */;\n\t\t\tED7A92941131E29D000EA5B4 /* PBXTextBookmark */ = ED7A92941131E29D000EA5B4 /* PBXTextBookmark */;\n\t\t\tED7A93251131EE43000EA5B4 /* PBXTextBookmark */ = ED7A93251131EE43000EA5B4 /* PBXTextBookmark */;\n\t\t\tED7A938611320528000EA5B4 /* PBXTextBookmark */ = ED7A938611320528000EA5B4 /* PBXTextBookmark */;\n\t\t\tED7A93CD113458B4000EA5B4 /* PBXTextBookmark */ = ED7A93CD113458B4000EA5B4 /* PBXTextBookmark */;\n\t\t\tED8508E41006979D00F262EA /* PBXTextBookmark */ = ED8508E41006979D00F262EA /* PBXTextBookmark */;\n\t\t\tED898863100CDF6A00AB035E /* PBXTextBookmark */ = ED898863100CDF6A00AB035E /* PBXTextBookmark */;\n\t\t\tED898864100CDF6A00AB035E /* PBXTextBookmark */ = ED898864100CDF6A00AB035E /* PBXTextBookmark */;\n\t\t\tED898865100CDF6A00AB035E /* PBXTextBookmark */ = ED898865100CDF6A00AB035E /* PBXTextBookmark */;\n\t\t\tED9B7E2A11932B8300C9F9A2 /* PBXTextBookmark */ = ED9B7E2A11932B8300C9F9A2 /* PBXTextBookmark */;\n\t\t\tED9B7E2B11932B8300C9F9A2 /* PBXTextBookmark */ = ED9B7E2B11932B8300C9F9A2 /* PBXTextBookmark */;\n\t\t\tEDA0C849101E5EA9008C7854 /* PBXTextBookmark */ = EDA0C849101E5EA9008C7854 /* PBXTextBookmark */;\n\t\t\tEDA0C909101F6823008C7854 /* PBXTextBookmark */ = EDA0C909101F6823008C7854 /* PBXTextBookmark */;\n\t\t\tEDA0C940101FEBC2008C7854 /* PBXTextBookmark */ = EDA0C940101FEBC2008C7854 /* PBXTextBookmark */;\n\t\t\tEDABA3D30F7C600A00EEAAD3 /* PBXTextBookmark */ = EDABA3D30F7C600A00EEAAD3 /* PBXTextBookmark */;\n\t\t\tEDABA3D60F7C600A00EEAAD3 /* PBXTextBookmark */ = EDABA3D60F7C600A00EEAAD3 /* PBXTextBookmark */;\n\t\t\tEDABA68C0F8184D000EEAAD3 /* PBXTextBookmark */ = EDABA68C0F8184D000EEAAD3 /* PBXTextBookmark */;\n\t\t\tEDABB8070F954EA400EEAAD3 /* PBXTextBookmark */ = EDABB8070F954EA400EEAAD3 /* PBXTextBookmark */;\n\t\t\tEDB0FABF111F5B780090C1F2 /* PBXTextBookmark */ = EDB0FABF111F5B780090C1F2 /* PBXTextBookmark */;\n\t\t\tEDB0FAC0111F5B780090C1F2 /* PBXTextBookmark */ = EDB0FAC0111F5B780090C1F2 /* PBXTextBookmark */;\n\t\t\tEDB265351144180C00BEB9F7 /* PBXTextBookmark */ = EDB265351144180C00BEB9F7 /* PBXTextBookmark */;\n\t\t\tEDD24D081140220200CA15DC /* PBXTextBookmark */ = EDD24D081140220200CA15DC /* PBXTextBookmark */;\n\t\t\tEDD24D091140220200CA15DC /* PBXTextBookmark */ = EDD24D091140220200CA15DC /* PBXTextBookmark */;\n\t\t\tEDD24D0C1140220200CA15DC /* PBXTextBookmark */ = EDD24D0C1140220200CA15DC /* PBXTextBookmark */;\n\t\t\tEDD24D0D1140220200CA15DC /* PBXTextBookmark */ = EDD24D0D1140220200CA15DC /* PBXTextBookmark */;\n\t\t\tEDD30E2B0F782E6200192B4D /* PBXTargetBookmark */ = EDD30E2B0F782E6200192B4D /* PBXTargetBookmark */;\n\t\t\tEDD30EA60F783C8A00192B4D /* PBXTextBookmark */ = EDD30EA60F783C8A00192B4D /* PBXTextBookmark */;\n\t\t\tEDF061391055C2F100196C88 /* PBXTextBookmark */ = EDF061391055C2F100196C88 /* PBXTextBookmark */;\n\t\t\tEDF9448710EBEFD0000A80F7 /* PBXTextBookmark */ = EDF9448710EBEFD0000A80F7 /* PBXTextBookmark */;\n\t\t\tEDFCFE5A0F9ECBFC001AFBAF /* PBXTextBookmark */ = EDFCFE5A0F9ECBFC001AFBAF /* PBXTextBookmark */;\n\t\t};\n\t\tsourceControlManager = EDD575190F536FC70029FDB4 /* Source Control */;\n\t\tuserBuildSettings = {\n\t\t\tSYMROOT = \"/Users/cole/Data/Documents/CBCB/sr_mapping/RNA-seq/cufflinks/build\";\n\t\t};\n\t};\n\tD28A88AD04BDD90700651E21 /* cufflinks */ = {\n\t\tactiveExec = 0;\n\t};\n\tED0A973A1147289600484F91 /* scaffolds.cpp:462 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDCFD37C0F81B974002B1976 /* scaffolds.cpp */;\n\t\tfunctionName = \"Scaffold::merge_ops(const vector<AugmentedCuffOp>& ops, vector<AugmentedCuffOp>& merged, bool introns_overwrite_matches)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 462;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113864.4693061;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 1;\n\t};\n\tED0A973C1147289900484F91 /* scaffolds.cpp:393 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDCFD37C0F81B974002B1976 /* scaffolds.cpp */;\n\t\tfunctionName = \"Scaffold::merge_ops(const vector<AugmentedCuffOp>& ops, vector<AugmentedCuffOp>& merged, bool introns_overwrite_matches)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 393;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113864.469499;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 1;\n\t};\n\tED0A973E114728B000484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDD30EE70F78436D00192B4D /* hits.h */;\n\t\tname = \"hits.h: 467\";\n\t\trLen = 16;\n\t\trLoc = 10656;\n\t\trType = 0;\n\t\tvrLen = 844;\n\t\tvrLoc = 442;\n\t};\n\tED0A973F114728B000484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDD30EE60F78436D00192B4D /* hits.cpp */;\n\t\tname = \"hits.cpp: 329\";\n\t\trLen = 0;\n\t\trLoc = 8351;\n\t\trType = 0;\n\t\tvrLen = 665;\n\t\tvrLoc = 8488;\n\t};\n\tED0A9756114736D000484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDDC3B31103B12D300C386C1 /* cuffcompare.cpp */;\n\t\tname = \"cuffcompare.cpp: 1884\";\n\t\trLen = 7;\n\t\trLoc = 67508;\n\t\trType = 0;\n\t\tvrLen = 1297;\n\t\tvrLoc = 66807;\n\t};\n\tED0A975C114736F800484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDDC40CE1042467A00C386C1 /* genes.h */;\n\t\tname = \"genes.h: 118\";\n\t\trLen = 0;\n\t\trLoc = 2651;\n\t\trType = 0;\n\t\tvrLen = 511;\n\t\tvrLoc = 2303;\n\t};\n\tED0A977C114740EB00484F91 /* abundances.cpp:886 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = ED7E56000FA65536007F93A7 /* abundances.cpp */;\n\t\tfunctionName = \"gamma_map(const vector<Scaffold>& transcripts, const vector<MateHit>& alignments, const vector<int>& collapse_counts, vector<double>& gamma_map_estimate, ublas::matrix<double>& gamma_covariance)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 886;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113864.469693;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 2;\n\t};\n\tED0A977F114741A700484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDCFD37C0F81B974002B1976 /* scaffolds.cpp */;\n\t\tname = \"scaffolds.cpp: 391\";\n\t\trLen = 0;\n\t\trLoc = 8995;\n\t\trType = 0;\n\t\tvrLen = 646;\n\t\tvrLoc = 8750;\n\t};\n\tED0A97A8114745EB00484F91 /* abundances.cpp:1118 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = ED7E56000FA65536007F93A7 /* abundances.cpp */;\n\t\tfunctionName = \"calculate_gammas(const vector<Scaffold>& scaffolds, const vector<MateHit>& hits_in_gene, vector<double>& gammas, ublas::matrix<double>& gamma_covariance)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 1118;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113864.4698861;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 2;\n\t};\n\tED0A97B811474BFF00484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDD30F260F78473D00192B4D /* common.cpp */;\n\t\tname = \"common.cpp: 68\";\n\t\trLen = 0;\n\t\trLoc = 1278;\n\t\trType = 0;\n\t\tvrLen = 450;\n\t\tvrLoc = 0;\n\t};\n\tED0A97BF114AC28F00484F91 /* bundles.cpp:528 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = ED9FADA910546FEE006548BB /* bundles.cpp */;\n\t\tfunctionName = \"BundleFactory::next_bundle(HitBundle& bundle_out)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 528;\n\t\tmodificationTime = 290113864.4700789;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 2;\n\t};\n\tED0A97C1114AC29100484F91 /* bundles.cpp:527 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = ED9FADA910546FEE006548BB /* bundles.cpp */;\n\t\tfunctionName = \"BundleFactory::next_bundle(HitBundle& bundle_out)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 527;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113864.470273;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 2;\n\t};\n\tED0A97C3114AC29600484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDD30F250F78473D00192B4D /* common.h */;\n\t\tname = \"common.h: 43\";\n\t\trLen = 1;\n\t\trLoc = 910;\n\t\trType = 0;\n\t\tvrLen = 1271;\n\t\tvrLoc = 390;\n\t};\n\tED0A97C4114AC29600484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDD30ECB0F783E3200192B4D /* cufflinks.cpp */;\n\t\tname = \"cufflinks.cpp: 148\";\n\t\trLen = 0;\n\t\trLoc = 5206;\n\t\trType = 0;\n\t\tvrLen = 1489;\n\t\tvrLoc = 3753;\n\t};\n\tED0A97C6114AC29600484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED9FADA810546FEE006548BB /* bundles.h */;\n\t\tname = \"bundles.h: 118\";\n\t\trLen = 0;\n\t\trLoc = 3036;\n\t\trType = 0;\n\t\tvrLen = 1671;\n\t\tvrLoc = 411;\n\t};\n\tED0A97D3114AC2B000484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDCFD37B0F81B974002B1976 /* scaffolds.h */;\n\t\tname = \"scaffolds.h: 468\";\n\t\trLen = 12;\n\t\trLoc = 11890;\n\t\trType = 0;\n\t\tvrLen = 2131;\n\t\tvrLoc = 6063;\n\t};\n\tED0A97DE114AC5EB00484F91 /* assemble.cpp:2123 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = EDE162B00F789F1500F7A98B /* assemble.cpp */;\n\t\tfunctionName = \"assemble_bundle(const RefSequenceTable& rt, HitBundle* bundle_ptr, long double map_mass, FILE* ftranscripts, FILE* fgene_abundances, FILE* ftrans_abundances)\";\n\t\thitCount = 1;\n\t\tignoreCount = 0;\n\t\tlineNumber = 2123;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113878.89033;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 1;\n\t};\n\tED0A97E9114AC74400484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED9FADA910546FEE006548BB /* bundles.cpp */;\n\t\tname = \"bundles.cpp: 527\";\n\t\trLen = 0;\n\t\trLoc = 13230;\n\t\trType = 0;\n\t\tvrLen = 1313;\n\t\tvrLoc = 12666;\n\t};\n\tED0A97FD114AED8200484F91 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7E56000FA65536007F93A7 /* abundances.cpp */;\n\t\tname = \"abundances.cpp: 1191\";\n\t\trLen = 62;\n\t\trLoc = 30765;\n\t\trType = 0;\n\t\tvrLen = 1378;\n\t\tvrLoc = 30704;\n\t};\n\tED11ECCA112DBE9C00BCC333 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED5A97241097AF23001BA454 /* filters.h */;\n\t\tname = \"filters.h: 20\";\n\t\trLen = 20;\n\t\trLoc = 273;\n\t\trType = 0;\n\t\tvrLen = 820;\n\t\tvrLoc = 0;\n\t};\n\tED11ECCC112DBE9C00BCC333 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7E55FF0FA65536007F93A7 /* abundances.h */;\n\t\tname = \"abundances.h: 47\";\n\t\trLen = 16;\n\t\trLoc = 1003;\n\t\trType = 0;\n\t\tvrLen = 1393;\n\t\tvrLoc = 417;\n\t};\n\tED2606FD108FAF80004BF73E /* cuffdiff.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1165, 39351}}\";\n\t\t\tsepNavSelRange = \"{34015, 0}\";\n\t\t\tsepNavVisRange = \"{33571, 860}\";\n\t\t};\n\t};\n\tED27F9D40F7950C60072CA01 /* test_cufflinks */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t);\n\t\targumentStrings = (\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 1;\n\t\tconfigStateDict = {\n\t\t\t\"PBXLSLaunchAction-0\" = {\n\t\t\t\tPBXLSLaunchAction = 0;\n\t\t\t\tPBXLSLaunchStartAction = 1;\n\t\t\t\tPBXLSLaunchStdioStyle = 2;\n\t\t\t\tPBXLSLaunchStyle = 0;\n\t\t\t\tclass = PBXLSRunLaunchConfig;\n\t\t\t\tcommandLineArgs = (\n\t\t\t\t);\n\t\t\t\tdisplayName = \"Executable Runner\";\n\t\t\t\tenvironment = {\n\t\t\t\t};\n\t\t\t\tidentifier = com.apple.Xcode.launch.runConfig;\n\t\t\t\tremoteHostInfo = \"\";\n\t\t\t\tstartActionInfo = \"\";\n\t\t\t};\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlaunchableReference = ED27F9D50F7950C60072CA01 /* test_cufflinks */;\n\t\tlibgmallocEnabled = 0;\n\t\tname = test_cufflinks;\n\t\tsavedGlobals = {\n\t\t};\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t\tstartupPath = \"<<ProductDirectory>>\";\n\t\tvariableFormatDictionary = {\n\t\t};\n\t};\n\tED27F9D50F7950C60072CA01 /* test_cufflinks */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = \"compiled.mach-o.executable\";\n\t\tname = test_cufflinks;\n\t\tpath = \"/Users/cole/Data/Documents/CBCB/sr_mapping/RNA-seq/cufflinks/src/test_cufflinks\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED27F9E00F7950E80072CA01 /* cufflinks */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tYES,\n\t\t);\n\t\targumentStrings = (\n\t\t\t\"--inner-dist-mean 37  --inner-dist-stddev 33 --max-intron-length 1000000 --min-isoform-fraction 0.0 --pre-mrna-fraction 0.0  --GTF genes.slim.7.gtf xxx.sam\",\n\t\t\t\"-G MB8_plus_exons.cannonical_chr_names.gtf -F 0.0\",\n\t\t\ttsr.sam,\n\t\t\tnanog.sam,\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 1;\n\t\tconfigStateDict = {\n\t\t\t\"PBXLSLaunchAction-0\" = {\n\t\t\t\tPBXLSLaunchAction = 0;\n\t\t\t\tPBXLSLaunchStartAction = 1;\n\t\t\t\tPBXLSLaunchStdioStyle = 2;\n\t\t\t\tPBXLSLaunchStyle = 0;\n\t\t\t\tclass = PBXLSRunLaunchConfig;\n\t\t\t\tcommandLineArgs = (\n\t\t\t\t);\n\t\t\t\tdisplayName = \"Executable Runner\";\n\t\t\t\tenvironment = {\n\t\t\t\t};\n\t\t\t\tidentifier = com.apple.Xcode.launch.runConfig;\n\t\t\t\tremoteHostInfo = \"\";\n\t\t\t\tstartActionInfo = \"\";\n\t\t\t};\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlaunchableReference = ED27F9E10F7950E80072CA01 /* cufflinks */;\n\t\tlibgmallocEnabled = 0;\n\t\tname = cufflinks;\n\t\tsavedGlobals = {\n\t\t};\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t\tstartupPath = /Users/cole/tmp/nanog/;\n\t\tvariableFormatDictionary = {\n\t\t\t$cs = 1;\n\t\t\t$ds = 1;\n\t\t\t$eax = 1;\n\t\t\t$ebp = 1;\n\t\t\t$ebx = 1;\n\t\t\t$ecx = 1;\n\t\t\t$edi = 1;\n\t\t\t$edx = 1;\n\t\t\t$eflags = 1;\n\t\t\t$eip = 1;\n\t\t\t$es = 1;\n\t\t\t$esi = 1;\n\t\t\t$esp = 1;\n\t\t\t$gs = 1;\n\t\t\t$ss = 1;\n\t\t};\n\t};\n\tED27F9E10F7950E80072CA01 /* cufflinks */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = \"compiled.mach-o.executable\";\n\t\tname = cufflinks;\n\t\tpath = \"/Users/cole/Data/Documents/CBCB/sr_mapping/RNA-seq/cufflinks/src/cufflinks\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED352E1D10D4436B004B91A6 /* stl_vector.h */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.h;\n\t\tname = stl_vector.h;\n\t\tpath = \"/usr/include/c++/4.0.0/bits/stl_vector.h\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED352ECC10DDC130004B91A6 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED352ECD10DDC130004B91A6 /* thread_data.hpp */;\n\t\tname = \"thread_data.hpp: 111\";\n\t\trLen = 0;\n\t\trLoc = 3530;\n\t\trType = 0;\n\t\tvrLen = 817;\n\t\tvrLoc = 2831;\n\t};\n\tED352ECD10DDC130004B91A6 /* thread_data.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = thread_data.hpp;\n\t\tpath = \"/usr/local/include/boost-1_40/boost/thread/pthread/thread_data.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED5A962C1096AD1F001BA454 /* cuffdiff */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tYES,\n\t\t\tYES,\n\t\t\tYES,\n\t\t);\n\t\targumentStrings = (\n\t\t\t\"-c 10\",\n\t\t\t\"~/sr_mapping/RNA-seq/cufflinks/data/C2C12/analysis/differential/consensus.gtf\",\n\t\t\tMef2c.gtf,\n\t\t\tMef2c.sam,\n\t\t\tMef2c.sam,\n\t\t\tdown/cuff_out/transcripts.gtf,\n\t\t\tdown/tophat_out/accepted_hits.sam,\n\t\t\tup/tophat_out/accepted_hits.sam,\n\t\t\tchrX_end.gtf,\n\t\t\tconsensus.gtf,\n\t\t\texp_small.sam,\n\t\t\t60hr_small.sam,\n\t\t\t\"-p 2\",\n\t\t\t\"--FDR 0.01\",\n\t\t\t\"-m 34\",\n\t\t\tref_genes.gtf,\n\t\t\tsample1/tophat_out/accepted_hits.sam,\n\t\t\tsample2/tophat_out/accepted_hits.sam,\n\t\t\tsample3/tophat_out/accepted_hits.sam,\n\t\t\trequant.consensus.gtf,\n\t\t\texp_gene.sam,\n\t\t\t60hr_gene.sam,\n\t\t\tconsensus.gtf,\n\t\t\tbad_chr19_exp.sam,\n\t\t\tbad_chr19_60hr.sam,\n\t\t\tbad_chr19_5day.sam,\n\t\t\tLrp5_exp.sam,\n\t\t\tLrp5_60hr.sam,\n\t\t\tbad_chr19_7day.sam,\n\t\t\tsample_cuffcompare_combined.gtf,\n\t\t\tskelMuscle_sample.sam,\n\t\t\tliver2_sample.sam,\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 1;\n\t\tconfigStateDict = {\n\t\t\t\"PBXLSLaunchAction-0\" = {\n\t\t\t\tPBXLSLaunchAction = 0;\n\t\t\t\tPBXLSLaunchStartAction = 1;\n\t\t\t\tPBXLSLaunchStdioStyle = 2;\n\t\t\t\tPBXLSLaunchStyle = 0;\n\t\t\t\tclass = PBXLSRunLaunchConfig;\n\t\t\t\tcommandLineArgs = (\n\t\t\t\t);\n\t\t\t\tdisplayName = \"Executable Runner\";\n\t\t\t\tenvironment = {\n\t\t\t\t};\n\t\t\t\tidentifier = com.apple.Xcode.launch.runConfig;\n\t\t\t\tremoteHostInfo = \"\";\n\t\t\t\tstartActionInfo = \"\";\n\t\t\t};\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlaunchableReference = ED5A962D1096AD1F001BA454 /* cuffdiff */;\n\t\tlibgmallocEnabled = 0;\n\t\tname = cuffdiff;\n\t\tsavedGlobals = {\n\t\t};\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t\tstartupPath = /Users/cole/tmp;\n\t\tvariableFormatDictionary = {\n\t\t};\n\t};\n\tED5A962D1096AD1F001BA454 /* cuffdiff */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = \"compiled.mach-o.executable\";\n\t\tname = cuffdiff;\n\t\tpath = \"/Users/cole/Data/Documents/CBCB/sr_mapping/RNA-seq/cufflinks/src/cuffdiff\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED5A97241097AF23001BA454 /* filters.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {896, 599}}\";\n\t\t\tsepNavSelRange = \"{273, 20}\";\n\t\t\tsepNavVisRange = \"{0, 820}\";\n\t\t};\n\t};\n\tED5A97251097AF23001BA454 /* filters.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1165, 6643}}\";\n\t\t\tsepNavSelRange = \"{9230, 0}\";\n\t\t\tsepNavVisRange = \"{9741, 1184}\";\n\t\t};\n\t};\n\tED7A92501131DAC7000EA5B4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED352E1D10D4436B004B91A6 /* stl_vector.h */;\n\t\tname = \"stl_vector.h: 403\";\n\t\trLen = 0;\n\t\trLoc = 14113;\n\t\trType = 0;\n\t\tvrLen = 1626;\n\t\tvrLoc = 13312;\n\t};\n\tED7A925F1131DDC4000EA5B4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7A92601131DDC4000EA5B4 /* ref.hpp */;\n\t\tname = \"ref.hpp: 71\";\n\t\trLen = 0;\n\t\trLoc = 1552;\n\t\trType = 0;\n\t\tvrLen = 852;\n\t\tvrLoc = 1117;\n\t};\n\tED7A92601131DDC4000EA5B4 /* ref.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = ref.hpp;\n\t\tpath = \"/usr/local/include/boost-1_40/boost/ref.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED7A92731131DE1D000EA5B4 /* addressof.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = addressof.hpp;\n\t\tpath = \"/usr/local/include/boost-1_40/boost/utility/addressof.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED7A92941131E29D000EA5B4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7A92731131DE1D000EA5B4 /* addressof.hpp */;\n\t\tname = \"addressof.hpp: 59\";\n\t\trLen = 0;\n\t\trLoc = 1267;\n\t\trType = 0;\n\t\tvrLen = 885;\n\t\tvrLoc = 808;\n\t};\n\tED7A92ED1131E9C1000EA5B4 /* bundles.cpp:523 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = ED9FADA910546FEE006548BB /* bundles.cpp */;\n\t\tfunctionName = \"BundleFactory::next_bundle(HitBundle& bundle_out)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 523;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113864.468098;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 2;\n\t};\n\tED7A92F51131EA34000EA5B4 /* gtf_tracking.cpp:139 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = ED9FACAA10532C16006548BB /* gtf_tracking.cpp */;\n\t\tfunctionName = \"parse_mRNAs(GList<GffObj>& mrnas, GList<GSeqData>& glstdata, bool is_ref_set, int qfidx)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 139;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113864.4685251;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 2;\n\t};\n\tED7A92FE1131EAF9000EA5B4 /* bundles.cpp:498 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = ED9FADA910546FEE006548BB /* bundles.cpp */;\n\t\tfunctionName = \"BundleFactory::next_bundle(HitBundle& bundle_out)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 498;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113864.468727;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 2;\n\t};\n\tED7A93101131EBA2000EA5B4 /* bundles.cpp:365 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = ED9FADA910546FEE006548BB /* bundles.cpp */;\n\t\tfunctionName = \"BundleFactory::next_bundle(HitBundle& bundle_out)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 365;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113864.468922;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 2;\n\t};\n\tED7A93251131EE43000EA5B4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED5A97251097AF23001BA454 /* filters.cpp */;\n\t\tname = \"filters.cpp: 380\";\n\t\trLen = 0;\n\t\trLoc = 9230;\n\t\trType = 0;\n\t\tvrLen = 1570;\n\t\tvrLoc = 9526;\n\t};\n\tED7A934E1131F07A000EA5B4 /* gtf_tracking.cpp:139 */ = {\n\t\tisa = PBXFileBreakpoint;\n\t\tactions = (\n\t\t);\n\t\tbreakpointStyle = 0;\n\t\tcontinueAfterActions = 0;\n\t\tcountType = 0;\n\t\tdelayBeforeContinue = 0;\n\t\tfileReference = ED9FACAA10532C16006548BB /* gtf_tracking.cpp */;\n\t\tfunctionName = \"parse_mRNAs(GList<GffObj>& mrnas, GList<GSeqData>& glstdata, bool is_ref_set, int qfidx)\";\n\t\thitCount = 0;\n\t\tignoreCount = 0;\n\t\tlineNumber = 139;\n\t\tlocation = cufflinks;\n\t\tmodificationTime = 290113864.469113;\n\t\toriginalNumberOfMultipleMatches = 0;\n\t\tstate = 2;\n\t};\n\tED7A938611320528000EA5B4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA7A58810C2DFEB0074A7B7 /* gtf_reads.cpp */;\n\t\tname = \"gtf_reads.cpp: 115\";\n\t\trLen = 0;\n\t\trLoc = 2429;\n\t\trType = 0;\n\t\tvrLen = 1079;\n\t\tvrLoc = 2022;\n\t};\n\tED7A93CD113458B4000EA5B4 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED2606FD108FAF80004BF73E /* cuffdiff.cpp */;\n\t\tname = \"cuffdiff.cpp: 1249\";\n\t\trLen = 0;\n\t\trLoc = 34015;\n\t\trType = 0;\n\t\tvrLen = 1313;\n\t\tvrLoc = 33381;\n\t};\n\tED7E55FF0FA65536007F93A7 /* abundances.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {896, 1846}}\";\n\t\t\tsepNavSelRange = \"{1003, 16}\";\n\t\t\tsepNavVisRange = \"{417, 1393}\";\n\t\t};\n\t};\n\tED7E56000FA65536007F93A7 /* abundances.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1005, 22256}}\";\n\t\t\tsepNavSelRange = \"{30765, 62}\";\n\t\t\tsepNavVisRange = \"{30704, 1378}\";\n\t\t};\n\t};\n\tED7E578B0FA7C19D007F93A7 /* bfs.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {845, 20579}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1610}\";\n\t\t};\n\t};\n\tED7E578C0FA7C19D007F93A7 /* bin_heap.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {967, 4537}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 942}\";\n\t\t};\n\t};\n\tED7E578D0FA7C19D007F93A7 /* bipartite_matching.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1212, 22594}}\";\n\t\t\tsepNavSelRange = \"{11741, 9}\";\n\t\t\tsepNavVisRange = \"{10936, 1708}\";\n\t\t};\n\t};\n\tED7E578F0FA7C19D007F93A7 /* alteration_notifier.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1143, 6773}}\";\n\t\t\tsepNavSelRange = \"{11937, 0}\";\n\t\t\tsepNavVisRange = \"{11452, 924}\";\n\t\t};\n\t};\n\tED7E57900FA7C19D007F93A7 /* array_map.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1143, 4511}}\";\n\t\t\tsepNavSelRange = \"{5091, 0}\";\n\t\t\tsepNavVisRange = \"{9297, 575}\";\n\t\t};\n\t};\n\tED7E57910FA7C19D007F93A7 /* base_extender.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1143, 6214}}\";\n\t\t\tsepNavSelRange = \"{7607, 0}\";\n\t\t\tsepNavVisRange = \"{7244, 869}\";\n\t\t};\n\t};\n\tED7E57930FA7C19D007F93A7 /* default_map.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {953, 2288}}\";\n\t\t\tsepNavSelRange = \"{1010, 0}\";\n\t\t\tsepNavVisRange = \"{661, 1386}\";\n\t\t};\n\t};\n\tED7E57940FA7C19D007F93A7 /* graph_adaptor_extender.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {953, 9542}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1379}\";\n\t\t};\n\t};\n\tED7E57950FA7C19D007F93A7 /* graph_extender.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {953, 17745}}\";\n\t\t\tsepNavSelRange = \"{24257, 10}\";\n\t\t\tsepNavVisRange = \"{23991, 1379}\";\n\t\t};\n\t};\n\tED7E57970FA7C19D007F93A7 /* map_extender.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {953, 4069}}\";\n\t\t\tsepNavSelRange = \"{950, 11}\";\n\t\t\tsepNavVisRange = \"{915, 1175}\";\n\t\t};\n\t};\n\tED7E579D0FA7C19D007F93A7 /* bucket_heap.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1328, 10608}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1784}\";\n\t\t};\n\t};\n\tED7E57A00FA7C19D007F93A7 /* bpugraph.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {953, 13026}}\";\n\t\t\tsepNavSelRange = \"{24767, 8}\";\n\t\t\tsepNavVisRange = \"{25544, 1645}\";\n\t\t};\n\t};\n\tED7E57A20FA7C19D007F93A7 /* graph_components.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {953, 27534}}\";\n\t\t\tsepNavSelRange = \"{52824, 14}\";\n\t\t\tsepNavVisRange = \"{50913, 1591}\";\n\t\t};\n\t};\n\tED7E57A80FA7C19D007F93A7 /* dfs.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {967, 20332}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 920}\";\n\t\t};\n\t};\n\tED7E57AA0FA7C19D007F93A7 /* graph_adaptor.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1001, 35893}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1887}\";\n\t\t};\n\t};\n\tED7E57AB0FA7C19D007F93A7 /* graph_utils.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1089, 42042}}\";\n\t\t\tsepNavSelRange = \"{83899, 4}\";\n\t\t\tsepNavVisRange = \"{83070, 1218}\";\n\t\t};\n\t};\n\tED7E57AD0FA7C19D007F93A7 /* maps.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {962, 21632}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{20722, 1966}\";\n\t\t};\n\t};\n\tED7E57AE0FA7C19D007F93A7 /* math.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {953, 806}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1746}\";\n\t\t};\n\t};\n\tED7E57AF0FA7C19D007F93A7 /* smart_graph.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {977, 14989}}\";\n\t\t\tsepNavSelRange = \"{23673, 8}\";\n\t\t\tsepNavVisRange = \"{23270, 710}\";\n\t\t};\n\t};\n\tED7E57B10FA7C19D007F93A7 /* topology.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1005, 20813}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1559}\";\n\t\t};\n\t};\n\tED7E612F0FBCE05F007F93A7 /* thread_data.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = thread_data.hpp;\n\t\tpath = \"/usr/local/include/boost-1_38/boost/thread/pthread/thread_data.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tED8508E41006979D00F262EA /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7E57AF0FA7C19D007F93A7 /* smart_graph.h */;\n\t\tname = \"smart_graph.h: 972\";\n\t\trLen = 8;\n\t\trLoc = 23673;\n\t\trType = 0;\n\t\tvrLen = 710;\n\t\tvrLoc = 23270;\n\t};\n\tED898863100CDF6A00AB035E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7E57B10FA7C19D007F93A7 /* topology.h */;\n\t\tname = \"topology.h: 1\";\n\t\trLen = 0;\n\t\trLoc = 0;\n\t\trType = 0;\n\t\tvrLen = 983;\n\t\tvrLoc = 0;\n\t};\n\tED898864100CDF6A00AB035E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7E57A80FA7C19D007F93A7 /* dfs.h */;\n\t\tname = \"dfs.h: 1\";\n\t\trLen = 0;\n\t\trLoc = 0;\n\t\trType = 0;\n\t\tvrLen = 920;\n\t\tvrLoc = 0;\n\t};\n\tED898865100CDF6A00AB035E /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7E579D0FA7C19D007F93A7 /* bucket_heap.h */;\n\t\tname = \"bucket_heap.h: 1\";\n\t\trLen = 0;\n\t\trLoc = 0;\n\t\trType = 0;\n\t\tvrLen = 951;\n\t\tvrLoc = 0;\n\t};\n\tED898BAD1010C29D00AB035E /* README */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {978, 962}}\";\n\t\t\tsepNavSelRange = \"{2919, 0}\";\n\t\t\tsepNavVisRange = \"{0, 2774}\";\n\t\t};\n\t};\n\tED898BAE1010C2A800AB035E /* LICENSE */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {710, 701}}\";\n\t\t\tsepNavSelRange = \"{43, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1516}\";\n\t\t};\n\t};\n\tED898BAF1010C2BC00AB035E /* AUTHORS */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {710, 701}}\";\n\t\t\tsepNavSelRange = \"{440, 0}\";\n\t\t\tsepNavVisRange = \"{0, 443}\";\n\t\t};\n\t};\n\tED91BC060FAE1BFD00BDDEBC /* fib_heap.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1013, 5798}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{2604, 1614}\";\n\t\t};\n\t};\n\tED91C29D0FA6CE9400B5E75C /* ax_boost_base.m4 */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1629, 2938}}\";\n\t\t\tsepNavSelRange = \"{695, 13}\";\n\t\t\tsepNavVisRange = \"{0, 1777}\";\n\t\t};\n\t};\n\tED91C29E0FA6CF1F00B5E75C /* ax_boost_thread.m4 */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {843, 2002}}\";\n\t\t\tsepNavSelRange = \"{1431, 0}\";\n\t\t\tsepNavVisRange = \"{502, 2048}\";\n\t\t};\n\t};\n\tED9B7E2A11932B8300C9F9A2 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDE162B00F789F1500F7A98B /* assemble.cpp */;\n\t\tname = \"assemble.cpp: 1905\";\n\t\trLen = 0;\n\t\trLoc = 48984;\n\t\trType = 0;\n\t\tvrLen = 1213;\n\t\tvrLoc = 48882;\n\t};\n\tED9B7E2B11932B8300C9F9A2 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7E57B10FA7C19D007F93A7 /* topology.h */;\n\t\tname = \"topology.h: 1\";\n\t\trLen = 0;\n\t\trLoc = 0;\n\t\trType = 0;\n\t\tvrLen = 1559;\n\t\tvrLoc = 0;\n\t};\n\tED9FACA210532A50006548BB /* gtf_tracking.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {948, 13533}}\";\n\t\t\tsepNavSelRange = \"{887, 3}\";\n\t\t\tsepNavVisRange = \"{271, 1166}\";\n\t\t};\n\t};\n\tED9FACAA10532C16006548BB /* gtf_tracking.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {948, 7826}}\";\n\t\t\tsepNavSelRange = \"{9043, 6}\";\n\t\t\tsepNavVisRange = \"{8461, 1451}\";\n\t\t};\n\t};\n\tED9FADA810546FEE006548BB /* bundles.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1005, 2054}}\";\n\t\t\tsepNavSelRange = \"{3036, 0}\";\n\t\t\tsepNavVisRange = \"{411, 1671}\";\n\t\t};\n\t};\n\tED9FADA910546FEE006548BB /* bundles.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1005, 7332}}\";\n\t\t\tsepNavSelRange = \"{13230, 0}\";\n\t\t\tsepNavVisRange = \"{12666, 1313}\";\n\t\t\tsepNavWindowFrame = \"{{71, 195}, {772, 578}}\";\n\t\t};\n\t};\n\tED9FAE4110547AB8006548BB /* GList.hh */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1115, 15093}}\";\n\t\t\tsepNavSelRange = \"{22112, 5}\";\n\t\t\tsepNavVisRange = \"{0, 1706}\";\n\t\t};\n\t};\n\tEDA0C849101E5EA9008C7854 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA0C84A101E5EA9008C7854 /* shared_ptr.hpp */;\n\t\tname = \"shared_ptr.hpp: 419\";\n\t\trLen = 0;\n\t\trLoc = 10254;\n\t\trType = 0;\n\t\tvrLen = 498;\n\t\tvrLoc = 9919;\n\t};\n\tEDA0C84A101E5EA9008C7854 /* shared_ptr.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = shared_ptr.hpp;\n\t\tpath = \"/usr/local/include/boost-1_38/boost/shared_ptr.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDA0C909101F6823008C7854 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDAB9EE20F7AAAEC00EEAAD3 /* stl_algo.h */;\n\t\tname = \"stl_algo.h: 2163\";\n\t\trLen = 25;\n\t\trLoc = 70569;\n\t\trType = 0;\n\t\tvrLen = 747;\n\t\tvrLoc = 70082;\n\t};\n\tEDA0C940101FEBC2008C7854 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDA0C941101FEBC2008C7854 /* operators.hpp */;\n\t\tname = \"operators.hpp: 140\";\n\t\trLen = 73;\n\t\trLoc = 6538;\n\t\trType = 0;\n\t\tvrLen = 1080;\n\t\tvrLoc = 5862;\n\t};\n\tEDA0C941101FEBC2008C7854 /* operators.hpp */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.h;\n\t\tname = operators.hpp;\n\t\tpath = \"/usr/local/include/boost-1_38/boost/operators.hpp\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDA7A58810C2DFEB0074A7B7 /* gtf_reads.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {905, 5018}}\";\n\t\t\tsepNavSelRange = \"{2429, 0}\";\n\t\t\tsepNavVisRange = \"{2022, 1079}\";\n\t\t};\n\t};\n\tEDAB9EE20F7AAAEC00EEAAD3 /* stl_algo.h */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.h;\n\t\tname = stl_algo.h;\n\t\tpath = \"/usr/include/c++/4.0.0/bits/stl_algo.h\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDABA25B0F7C330600EEAAD3 /* transitive_closure.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {892, 5135}}\";\n\t\t\tsepNavSelRange = \"{4137, 6}\";\n\t\t\tsepNavVisRange = \"{0, 1692}\";\n\t\t};\n\t};\n\tEDABA3D30F7C600A00EEAAD3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDABA3D40F7C600A00EEAAD3 /* new_allocator.h */;\n\t\tname = \"new_allocator.h: 88\";\n\t\trLen = 0;\n\t\trLoc = 2986;\n\t\trType = 0;\n\t\tvrLen = 1310;\n\t\tvrLoc = 2241;\n\t};\n\tEDABA3D40F7C600A00EEAAD3 /* new_allocator.h */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.h;\n\t\tname = new_allocator.h;\n\t\tpath = \"/usr/include/c++/4.0.0/ext/new_allocator.h\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDABA3D60F7C600A00EEAAD3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDABA3D70F7C600A00EEAAD3 /* vector.tcc */;\n\t\tname = \"vector.tcc: 275\";\n\t\trLen = 0;\n\t\trLoc = 9128;\n\t\trType = 0;\n\t\tvrLen = 1600;\n\t\tvrLoc = 8389;\n\t};\n\tEDABA3D70F7C600A00EEAAD3 /* vector.tcc */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.cpp.cpp;\n\t\tname = vector.tcc;\n\t\tpath = \"/usr/include/c++/4.0.0/bits/vector.tcc\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDABA68C0F8184D000EEAAD3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDABA68D0F8184D000EEAAD3 /* stl_list.h */;\n\t\tname = \"stl_list.h: 135\";\n\t\trLen = 0;\n\t\trLoc = 4602;\n\t\trType = 0;\n\t\tvrLen = 1141;\n\t\tvrLoc = 3821;\n\t};\n\tEDABA68D0F8184D000EEAAD3 /* stl_list.h */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.h;\n\t\tname = stl_list.h;\n\t\tpath = \"/usr/include/c++/4.0.0/bits/stl_list.h\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDABB72E0F953E0500EEAAD3 /* stl_map.h */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.h;\n\t\tname = stl_map.h;\n\t\tpath = \"/usr/include/c++/4.0.0/bits/stl_map.h\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDABB8070F954EA400EEAAD3 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDABB72E0F953E0500EEAAD3 /* stl_map.h */;\n\t\tname = \"stl_map.h: 166\";\n\t\trLen = 0;\n\t\trLoc = 6643;\n\t\trType = 0;\n\t\tvrLen = 2505;\n\t\tvrLoc = 5426;\n\t};\n\tEDB0FABF111F5B780090C1F2 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDD30EC80F783E2B00192B4D /* configure.ac */;\n\t\tname = \"configure.ac: 6\";\n\t\trLen = 0;\n\t\trLoc = 117;\n\t\trType = 0;\n\t\tvrLen = 817;\n\t\tvrLoc = 0;\n\t};\n\tEDB0FAC0111F5B780090C1F2 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDD30ECA0F783E3200192B4D /* Makefile.am */;\n\t\tname = \"Makefile.am: 11\";\n\t\trLen = 9;\n\t\trLoc = 171;\n\t\trType = 0;\n\t\tvrLen = 654;\n\t\tvrLoc = 0;\n\t};\n\tEDB265351144180C00BEB9F7 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDDC40CF10424B5D00C386C1 /* genes.cpp */;\n\t\tname = \"genes.cpp: 23\";\n\t\trLen = 4;\n\t\trLoc = 338;\n\t\trType = 0;\n\t\tvrLen = 639;\n\t\tvrLoc = 857;\n\t};\n\tEDCFD37B0F81B974002B1976 /* scaffolds.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1005, 6162}}\";\n\t\t\tsepNavSelRange = \"{11890, 12}\";\n\t\t\tsepNavVisRange = \"{6063, 2131}\";\n\t\t\tsepNavWindowFrame = \"{{102, 574}, {772, 578}}\";\n\t\t};\n\t};\n\tEDCFD37C0F81B974002B1976 /* scaffolds.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1208, 16900}}\";\n\t\t\tsepNavSelRange = \"{8995, 0}\";\n\t\t\tsepNavVisRange = \"{8792, 455}\";\n\t\t\tsepNavWindowFrame = \"{{147, 139}, {763, 971}}\";\n\t\t};\n\t};\n\tEDD24D081140220200CA15DC /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED9FACA210532A50006548BB /* gtf_tracking.h */;\n\t\tname = \"gtf_tracking.h: 41\";\n\t\trLen = 3;\n\t\trLoc = 887;\n\t\trType = 0;\n\t\tvrLen = 1166;\n\t\tvrLoc = 271;\n\t};\n\tEDD24D091140220200CA15DC /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED9FACAA10532C16006548BB /* gtf_tracking.cpp */;\n\t\tname = \"gtf_tracking.cpp: 275\";\n\t\trLen = 6;\n\t\trLoc = 9043;\n\t\trType = 0;\n\t\tvrLen = 1451;\n\t\tvrLoc = 8461;\n\t};\n\tEDD24D0C1140220200CA15DC /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDF05F8B104EF5D100196C88 /* gff.cpp */;\n\t\tname = \"gff.cpp: 108\";\n\t\trLen = 0;\n\t\trLoc = 2438;\n\t\trType = 0;\n\t\tvrLen = 1255;\n\t\tvrLoc = 2263;\n\t};\n\tEDD24D0D1140220200CA15DC /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDF05F8A104EF5D100196C88 /* gff.h */;\n\t\tname = \"gff.h: 384\";\n\t\trLen = 6;\n\t\trLoc = 10413;\n\t\trType = 0;\n\t\tvrLen = 1977;\n\t\tvrLoc = 7718;\n\t};\n\tEDD30E1B0F782D7A00192B4D /* test */ = {\n\t\tactiveExec = 0;\n\t};\n\tEDD30E2B0F782E6200192B4D /* PBXTargetBookmark */ = {\n\t\tisa = PBXTargetBookmark;\n\t\ttrg = EDD30E1B0F782D7A00192B4D /* test */;\n\t};\n\tEDD30EA60F783C8A00192B4D /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDD5753A0F537A3C0029FDB4 /* bamtk.c */;\n\t\tname = \"bamtk.c: 1\";\n\t\trLen = 0;\n\t\trLoc = 0;\n\t\trType = 0;\n\t\tvrLen = 1484;\n\t\tvrLoc = 0;\n\t};\n\tEDD30EC80F783E2B00192B4D /* configure.ac */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {979, 1820}}\";\n\t\t\tsepNavSelRange = \"{117, 0}\";\n\t\t\tsepNavVisRange = \"{0, 817}\";\n\t\t};\n\t};\n\tEDD30ECA0F783E3200192B4D /* Makefile.am */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {979, 1456}}\";\n\t\t\tsepNavSelRange = \"{171, 9}\";\n\t\t\tsepNavVisRange = \"{0, 654}\";\n\t\t};\n\t};\n\tEDD30ECB0F783E3200192B4D /* cufflinks.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1005, 2795}}\";\n\t\t\tsepNavSelRange = \"{5206, 0}\";\n\t\t\tsepNavVisRange = \"{3753, 1489}\";\n\t\t\tsepNavWindowFrame = \"{{87, 595}, {772, 578}}\";\n\t\t};\n\t};\n\tEDD30EE60F78436D00192B4D /* hits.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {948, 6591}}\";\n\t\t\tsepNavSelRange = \"{8351, 0}\";\n\t\t\tsepNavVisRange = \"{8488, 665}\";\n\t\t};\n\t};\n\tEDD30EE70F78436D00192B4D /* hits.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {948, 8255}}\";\n\t\t\tsepNavSelRange = \"{10656, 16}\";\n\t\t\tsepNavVisRange = \"{442, 844}\";\n\t\t\tsepNavWindowFrame = \"{{81, 202}, {888, 971}}\";\n\t\t};\n\t};\n\tEDD30F0F0F78469B00192B4D /* tokenize.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {808, 520}}\";\n\t\t\tsepNavSelRange = \"{0, 0}\";\n\t\t\tsepNavVisRange = \"{0, 1103}\";\n\t\t};\n\t};\n\tEDD30F100F78469B00192B4D /* tokenize.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {821, 784}}\";\n\t\t\tsepNavSelRange = \"{412, 0}\";\n\t\t\tsepNavVisRange = \"{0, 412}\";\n\t\t};\n\t};\n\tEDD30F250F78473D00192B4D /* common.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1005, 1027}}\";\n\t\t\tsepNavSelRange = \"{910, 1}\";\n\t\t\tsepNavVisRange = \"{390, 1271}\";\n\t\t};\n\t};\n\tEDD30F260F78473D00192B4D /* common.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {948, 1625}}\";\n\t\t\tsepNavSelRange = \"{1278, 0}\";\n\t\t\tsepNavVisRange = \"{0, 450}\";\n\t\t};\n\t};\n\tEDD575190F536FC70029FDB4 /* Source Control */ = {\n\t\tisa = PBXSourceControlManager;\n\t\tfallbackIsa = XCSourceControlManager;\n\t\tisSCMEnabled = 0;\n\t\tscmConfiguration = {\n\t\t\trepositoryNamesForRoots = {\n\t\t\t\t\"\" = \"\";\n\t\t\t};\n\t\t};\n\t};\n\tEDD5751A0F536FC70029FDB4 /* Code sense */ = {\n\t\tisa = PBXCodeSenseManager;\n\t\tindexTemplatePath = \"\";\n\t};\n\tEDD5753A0F537A3C0029FDB4 /* bamtk.c */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.c;\n\t\tname = bamtk.c;\n\t\tpath = /Users/cole/Data/Documents/CBCB/sr_mapping/samtools/bamtk.c;\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDDC3B31103B12D300C386C1 /* cuffcompare.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1118, 32786}}\";\n\t\t\tsepNavSelRange = \"{67508, 7}\";\n\t\t\tsepNavVisRange = \"{66807, 1297}\";\n\t\t};\n\t};\n\tEDDC40CE1042467A00C386C1 /* genes.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1208, 1924}}\";\n\t\t\tsepNavSelRange = \"{2651, 0}\";\n\t\t\tsepNavVisRange = \"{2303, 511}\";\n\t\t};\n\t};\n\tEDDC40CF10424B5D00C386C1 /* genes.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1419, 1352}}\";\n\t\t\tsepNavSelRange = \"{338, 4}\";\n\t\t\tsepNavVisRange = \"{857, 639}\";\n\t\t};\n\t};\n\tEDE162AF0F789F1500F7A98B /* assemble.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {828, 728}}\";\n\t\t\tsepNavSelRange = \"{864, 14}\";\n\t\t\tsepNavVisRange = \"{470, 815}\";\n\t\t};\n\t};\n\tEDE162B00F789F1500F7A98B /* assemble.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {1005, 28327}}\";\n\t\t\tsepNavSelRange = \"{48984, 0}\";\n\t\t\tsepNavVisRange = \"{48882, 1213}\";\n\t\t\tsepNavWindowFrame = \"{{102, 181}, {763, 971}}\";\n\t\t};\n\t};\n\tEDF05F8A104EF5D100196C88 /* gff.h */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {978, 10439}}\";\n\t\t\tsepNavSelRange = \"{10413, 6}\";\n\t\t\tsepNavVisRange = \"{7718, 1977}\";\n\t\t};\n\t};\n\tEDF05F8B104EF5D100196C88 /* gff.cpp */ = {\n\t\tuiCtxt = {\n\t\t\tsepNavIntBoundsRect = \"{{0, 0}, {948, 15873}}\";\n\t\t\tsepNavSelRange = \"{2438, 0}\";\n\t\t\tsepNavVisRange = \"{2263, 1255}\";\n\t\t};\n\t};\n\tEDF061391055C2F100196C88 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = ED7E612F0FBCE05F007F93A7 /* thread_data.hpp */;\n\t\tname = \"thread_data.hpp: 111\";\n\t\trLen = 0;\n\t\trLoc = 3530;\n\t\trType = 0;\n\t\tvrLen = 1564;\n\t\tvrLoc = 2092;\n\t};\n\tEDF061F51055D39400196C88 /* cuffcompare */ = {\n\t\tisa = PBXExecutable;\n\t\tactiveArgIndices = (\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tNO,\n\t\t\tYES,\n\t\t\tYES,\n\t\t);\n\t\targumentStrings = (\n\t\t\t\"-V\",\n\t\t\t\"-r sim3.expressed.gtf\",\n\t\t\t\"-T transcripts.gtf\",\n\t\t\t\"-r ref_genes.gtf\",\n\t\t\tsample1/cuff_out/transcripts.gtf,\n\t\t\tsample2/cuff_out/transcripts.gtf,\n\t\t\t\"-r ucsc+ensembl+vega_pseudo.gtf\",\n\t\t\txxx.gtf,\n\t\t);\n\t\tautoAttachOnCrash = 1;\n\t\tbreakpointsEnabled = 1;\n\t\tconfigStateDict = {\n\t\t\t\"PBXLSLaunchAction-0\" = {\n\t\t\t\tPBXLSLaunchAction = 0;\n\t\t\t\tPBXLSLaunchStartAction = 1;\n\t\t\t\tPBXLSLaunchStdioStyle = 2;\n\t\t\t\tPBXLSLaunchStyle = 0;\n\t\t\t\tclass = PBXLSRunLaunchConfig;\n\t\t\t\tcommandLineArgs = (\n\t\t\t\t);\n\t\t\t\tdisplayName = \"Executable Runner\";\n\t\t\t\tenvironment = {\n\t\t\t\t};\n\t\t\t\tidentifier = com.apple.Xcode.launch.runConfig;\n\t\t\t\tremoteHostInfo = \"\";\n\t\t\t\tstartActionInfo = \"\";\n\t\t\t};\n\t\t};\n\t\tcustomDataFormattersEnabled = 1;\n\t\tdataTipCustomDataFormattersEnabled = 1;\n\t\tdataTipShowTypeColumn = 1;\n\t\tdataTipSortType = 0;\n\t\tdebuggerPlugin = GDBDebugging;\n\t\tdisassemblyDisplayState = 0;\n\t\tdylibVariantSuffix = \"\";\n\t\tenableDebugStr = 1;\n\t\tenvironmentEntries = (\n\t\t);\n\t\texecutableSystemSymbolLevel = 0;\n\t\texecutableUserSymbolLevel = 0;\n\t\tlaunchableReference = EDF061F61055D39400196C88 /* cuffcompare */;\n\t\tlibgmallocEnabled = 0;\n\t\tname = cuffcompare;\n\t\tsavedGlobals = {\n\t\t};\n\t\tshowTypeColumn = 0;\n\t\tsourceDirectories = (\n\t\t);\n\t\tstartupPath = /Users/cole/tmp;\n\t\tvariableFormatDictionary = {\n\t\t};\n\t};\n\tEDF061F61055D39400196C88 /* cuffcompare */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = \"compiled.mach-o.executable\";\n\t\tname = cuffcompare;\n\t\tpath = \"/Users/cole/Data/Documents/CBCB/sr_mapping/RNA-seq/cufflinks/src/cuffcompare\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n\tEDF9448710EBEFD0000A80F7 /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDE162AF0F789F1500F7A98B /* assemble.h */;\n\t\tname = \"assemble.h: 40\";\n\t\trLen = 14;\n\t\trLoc = 864;\n\t\trType = 0;\n\t\tvrLen = 815;\n\t\tvrLoc = 470;\n\t};\n\tEDFCFE5A0F9ECBFC001AFBAF /* PBXTextBookmark */ = {\n\t\tisa = PBXTextBookmark;\n\t\tfRef = EDFCFE5B0F9ECBFC001AFBAF /* stl_algobase.h */;\n\t\tname = \"stl_algobase.h: 116\";\n\t\trLen = 25;\n\t\trLoc = 4255;\n\t\trType = 0;\n\t\tvrLen = 1788;\n\t\tvrLoc = 3254;\n\t};\n\tEDFCFE5B0F9ECBFC001AFBAF /* stl_algobase.h */ = {\n\t\tisa = PBXFileReference;\n\t\tlastKnownFileType = sourcecode.c.h;\n\t\tname = stl_algobase.h;\n\t\tpath = \"/usr/include/c++/4.0.0/bits/stl_algobase.h\";\n\t\tsourceTree = \"<absolute>\";\n\t};\n}\n"
  },
  {
    "path": "src/cufflinks.xcodeproj/cole.perspectivev3",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>ActivePerspectiveName</key>\n\t<string>Project</string>\n\t<key>AllowedModules</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXSmartGroupTreeModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Groups and Files Outline View</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Editor</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>XCTaskListModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Task List</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>XCDetailModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>File and Smart Group Detail Viewer</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>1</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXBuildResultsModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Detailed Build Results Viewer</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>1</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXProjectFindModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Project Batch Find Tool</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>XCProjectFormatConflictsModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Project Format Conflicts List</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXBookmarksModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Bookmarks Tool</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXClassBrowserModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Class Browser</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXCVSModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Source Code Control Tool</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXDebugBreakpointsModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debug Breakpoints Tool</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>XCDockableInspector</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Inspector</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXOpenQuicklyModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Open Quickly Tool</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>1</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debugger</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>1</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>PBXDebugCLIModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debug Console</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>BundleLoadPath</key>\n\t\t\t<string></string>\n\t\t\t<key>MaxInstances</key>\n\t\t\t<string>n</string>\n\t\t\t<key>Module</key>\n\t\t\t<string>XCSnapshotModule</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Snapshots Tool</string>\n\t\t</dict>\n\t</array>\n\t<key>BundlePath</key>\n\t<string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string>\n\t<key>Description</key>\n\t<string>AIODescriptionKey</string>\n\t<key>DockingSystemVisible</key>\n\t<false/>\n\t<key>Extension</key>\n\t<string>perspectivev3</string>\n\t<key>FavBarConfig</key>\n\t<dict>\n\t\t<key>PBXProjectModuleGUID</key>\n\t\t<string>EDD575180F536FC70029FDB4</string>\n\t\t<key>XCBarModuleItemNames</key>\n\t\t<dict/>\n\t\t<key>XCBarModuleItems</key>\n\t\t<array/>\n\t</dict>\n\t<key>FirstTimeWindowDisplayed</key>\n\t<false/>\n\t<key>Identifier</key>\n\t<string>com.apple.perspectives.project.defaultV3</string>\n\t<key>MajorVersion</key>\n\t<integer>34</integer>\n\t<key>MinorVersion</key>\n\t<integer>0</integer>\n\t<key>Name</key>\n\t<string>All-In-One</string>\n\t<key>Notifications</key>\n\t<array/>\n\t<key>OpenEditors</key>\n\t<array/>\n\t<key>PerspectiveWidths</key>\n\t<array>\n\t\t<integer>1326</integer>\n\t\t<integer>1326</integer>\n\t</array>\n\t<key>Perspectives</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>ChosenToolbarItems</key>\n\t\t\t<array>\n\t\t\t\t<string>XCToolbarPerspectiveControl</string>\n\t\t\t\t<string>NSToolbarSeparatorItem</string>\n\t\t\t\t<string>active-combo-popup</string>\n\t\t\t\t<string>action</string>\n\t\t\t\t<string>active-architecture-popup</string>\n\t\t\t\t<string>active-executable-popup</string>\n\t\t\t\t<string>NSToolbarFlexibleSpaceItem</string>\n\t\t\t\t<string>debugger-enable-breakpoints</string>\n\t\t\t\t<string>build-and-go</string>\n\t\t\t\t<string>com.apple.ide.PBXToolbarStopButton</string>\n\t\t\t\t<string>get-info</string>\n\t\t\t\t<string>NSToolbarFlexibleSpaceItem</string>\n\t\t\t\t<string>com.apple.pbx.toolbar.searchfield</string>\n\t\t\t</array>\n\t\t\t<key>ControllerClassBaseName</key>\n\t\t\t<string></string>\n\t\t\t<key>IconName</key>\n\t\t\t<string>WindowOfProject</string>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>perspective.project</string>\n\t\t\t<key>IsVertical</key>\n\t\t\t<false/>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>PBXBottomSmartGroupGIDs</key>\n\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t<string>1C37FBAC04509CD000000102</string>\n\t\t\t\t\t\t\t<string>1C37FAAC04509CD000000102</string>\n\t\t\t\t\t\t\t<string>1C37FABC05509CD000000102</string>\n\t\t\t\t\t\t\t<string>1C37FABC05539CD112110102</string>\n\t\t\t\t\t\t\t<string>E2644B35053B69B200211256</string>\n\t\t\t\t\t\t\t<string>1C37FABC04509CD000100104</string>\n\t\t\t\t\t\t\t<string>1CC0EA4004350EF90044410B</string>\n\t\t\t\t\t\t\t<string>1CC0EA4004350EF90041110B</string>\n\t\t\t\t\t\t\t<string>1C77FABC04509CD000000102</string>\n\t\t\t\t\t\t</array>\n\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t<string>1CA23ED40692098700951B8B</string>\n\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t<string>Files</string>\n\t\t\t\t\t\t<key>PBXProjectStructureProvided</key>\n\t\t\t\t\t\t<string>yes</string>\n\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnData</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<real>22</real>\n\t\t\t\t\t\t\t\t<real>216</real>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<string>SCMStatusColumn</string>\n\t\t\t\t\t\t\t\t<string>MainColumn</string>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<string>08FB7794FE84155DC02AAC07</string>\n\t\t\t\t\t\t\t\t<string>ED7E578A0FA7C19D007F93A7</string>\n\t\t\t\t\t\t\t\t<string>1C37FBAC04509CD000000102</string>\n\t\t\t\t\t\t\t\t<string>ED9B7E2911932B8300C9F9A2</string>\n\t\t\t\t\t\t\t\t<string>1C37FAAC04509CD000000102</string>\n\t\t\t\t\t\t\t\t<string>1C77FABC04509CD000000102</string>\n\t\t\t\t\t\t\t\t<string>1C3E0DCA080725EA00A55177</string>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<integer>56</integer>\n\t\t\t\t\t\t\t\t\t<integer>55</integer>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>\n\t\t\t\t\t\t\t<string>{{0, 393}, {238, 1032}}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>PBXTopSmartGroupGIDs</key>\n\t\t\t\t\t\t<array/>\n\t\t\t\t\t\t<key>XCIncludePerspectivesSwitch</key>\n\t\t\t\t\t\t<false/>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t<string>{{0, 0}, {255, 1050}}</string>\n\t\t\t\t\t\t<key>GroupTreeTableConfiguration</key>\n\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t<string>SCMStatusColumn</string>\n\t\t\t\t\t\t\t<real>22</real>\n\t\t\t\t\t\t\t<string>MainColumn</string>\n\t\t\t\t\t\t\t<real>216</real>\n\t\t\t\t\t\t</array>\n\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t<string>380 87 1326 1091 0 0 1920 1178 </string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t<string>PBXSmartGroupTreeModule</string>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>255pt</string>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>EDD575130F536FC70029FDB4</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>topology.h</string>\n\t\t\t\t\t\t\t\t<key>PBXSplitModuleInNavigatorKey</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>Split0</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>EDD575140F536FC70029FDB4</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>topology.h</string>\n\t\t\t\t\t\t\t\t\t\t<key>_historyCapacity</key>\n\t\t\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t\t\t<key>bookmark</key>\n\t\t\t\t\t\t\t\t\t\t<string>ED9B7E2B11932B8300C9F9A2</string>\n\t\t\t\t\t\t\t\t\t\t<key>history</key>\n\t\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDD30E2B0F782E6200192B4D</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDD30EA60F783C8A00192B4D</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDABA3D30F7C600A00EEAAD3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDABA3D60F7C600A00EEAAD3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDABA68C0F8184D000EEAAD3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDABB8070F954EA400EEAAD3</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDFCFE5A0F9ECBFC001AFBAF</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED8508E41006979D00F262EA</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED898864100CDF6A00AB035E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED898865100CDF6A00AB035E</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDA0C849101E5EA9008C7854</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDA0C909101F6823008C7854</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDA0C940101FEBC2008C7854</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDF061391055C2F100196C88</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED352ECC10DDC130004B91A6</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDF9448710EBEFD0000A80F7</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDB0FABF111F5B780090C1F2</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDB0FAC0111F5B780090C1F2</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED11ECCA112DBE9C00BCC333</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED11ECCC112DBE9C00BCC333</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED7A92501131DAC7000EA5B4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED7A925F1131DDC4000EA5B4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED7A92941131E29D000EA5B4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED7A93251131EE43000EA5B4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED7A938611320528000EA5B4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED7A93CD113458B4000EA5B4</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDD24D081140220200CA15DC</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDD24D091140220200CA15DC</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDD24D0C1140220200CA15DC</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDD24D0D1140220200CA15DC</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>EDB265351144180C00BEB9F7</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A973E114728B000484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A973F114728B000484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A9756114736D000484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A975C114736F800484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A977F114741A700484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A97B811474BFF00484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A97C3114AC29600484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A97C4114AC29600484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A97C6114AC29600484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A97D3114AC2B000484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A97E9114AC74400484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED0A97FD114AED8200484F91</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED9B7E2A11932B8300C9F9A2</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>ED898863100CDF6A00AB035E</string>\n\t\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>SplitCount</key>\n\t\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>StatusBarVisibility</key>\n\t\t\t\t\t\t\t\t<true/>\n\t\t\t\t\t\t\t\t<key>XCSharingToken</key>\n\t\t\t\t\t\t\t\t<string>com.apple.Xcode.CommonNavigatorGroupSharingToken</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {1066, 751}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>380 87 1326 1091 0 0 1920 1178 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>751pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>294pt</string>\n\t\t\t\t\t\t\t<key>Tabs</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1CA23EDF0692099D00951B8B</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>Detail</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t\t\t<string>{{10, 27}, {1066, 267}}</string>\n\t\t\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t\t\t<string>380 87 1326 1091 0 0 1920 1178 </string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t\t\t<string>XCDetailModule</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1CA23EE00692099D00951B8B</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>Project Find</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t\t\t<string>{{10, 27}, {1066, 261}}</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t\t\t<string>PBXProjectFindModule</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXCVSModuleFilterTypeKey</key>\n\t\t\t\t\t\t\t\t\t\t<integer>1032</integer>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1CA23EE10692099D00951B8B</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>SCM Results</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t\t\t<string>{{10, 27}, {1297, 285}}</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t\t\t<string>PBXCVSModule</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>XCMainBuildResultsModuleGUID</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>Build Results</string>\n\t\t\t\t\t\t\t\t\t\t<key>XCBuildResultsTrigger_Collapse</key>\n\t\t\t\t\t\t\t\t\t\t<integer>1021</integer>\n\t\t\t\t\t\t\t\t\t\t<key>XCBuildResultsTrigger_Open</key>\n\t\t\t\t\t\t\t\t\t\t<integer>1011</integer>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t\t\t<string>{{10, 27}, {1066, 267}}</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t\t\t<string>PBXBuildResultsModule</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>1066pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Project</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>XCModuleDock</string>\n\t\t\t\t<string>PBXSmartGroupTreeModule</string>\n\t\t\t\t<string>XCModuleDock</string>\n\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t<string>XCDockableTabModule</string>\n\t\t\t\t<string>XCDetailModule</string>\n\t\t\t\t<string>PBXProjectFindModule</string>\n\t\t\t\t<string>PBXCVSModule</string>\n\t\t\t\t<string>PBXBuildResultsModule</string>\n\t\t\t</array>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>ED9B7E261193295100C9F9A2</string>\n\t\t\t\t<string>1CA23ED40692098700951B8B</string>\n\t\t\t\t<string>ED9B7E271193295100C9F9A2</string>\n\t\t\t\t<string>EDD575130F536FC70029FDB4</string>\n\t\t\t\t<string>ED9B7E281193295100C9F9A2</string>\n\t\t\t\t<string>1CA23EDF0692099D00951B8B</string>\n\t\t\t\t<string>1CA23EE00692099D00951B8B</string>\n\t\t\t\t<string>1CA23EE10692099D00951B8B</string>\n\t\t\t\t<string>XCMainBuildResultsModuleGUID</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfigUserDefaultsMinorVersion</key>\n\t\t\t<string>2</string>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.defaultV3</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>ChosenToolbarItems</key>\n\t\t\t<array>\n\t\t\t\t<string>XCToolbarPerspectiveControl</string>\n\t\t\t\t<string>NSToolbarSeparatorItem</string>\n\t\t\t\t<string>build-and-go</string>\n\t\t\t\t<string>go</string>\n\t\t\t\t<string>NSToolbarFlexibleSpaceItem</string>\n\t\t\t\t<string>debugger-fix-and-continue</string>\n\t\t\t\t<string>debugger-restart-executable</string>\n\t\t\t\t<string>debugger-pause</string>\n\t\t\t\t<string>debugger-step-over</string>\n\t\t\t\t<string>debugger-step-into</string>\n\t\t\t\t<string>debugger-step-out</string>\n\t\t\t\t<string>debugger-step-instruction</string>\n\t\t\t\t<string>NSToolbarFlexibleSpaceItem</string>\n\t\t\t</array>\n\t\t\t<key>ControllerClassBaseName</key>\n\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t<key>IconName</key>\n\t\t\t<string>DebugTabIcon</string>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>perspective.debug</string>\n\t\t\t<key>IsVertical</key>\n\t\t\t<true/>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t<string>1CCC7628064C1048000F2A68</string>\n\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t<string>Debugger Console</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t<string>{{0, 0}, {1326, 345}}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t<string>PBXDebugCLIModule</string>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>345pt</string>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Debugger</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HorizontalSplitView</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>_collapsingFrameDimension</key>\n\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t<key>_indexOfCollapsedView</key>\n\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t<key>_percentageOfCollapsedView</key>\n\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t<key>isCollapsed</key>\n\t\t\t\t\t\t\t\t<string>yes</string>\n\t\t\t\t\t\t\t\t<key>sizes</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {535, 219}}</string>\n\t\t\t\t\t\t\t\t\t<string>{{535, 0}, {791, 219}}</string>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>VerticalSplitView</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>_collapsingFrameDimension</key>\n\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t<key>_indexOfCollapsedView</key>\n\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t<key>_percentageOfCollapsedView</key>\n\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t<key>isCollapsed</key>\n\t\t\t\t\t\t\t\t<string>yes</string>\n\t\t\t\t\t\t\t\t<key>sizes</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {1326, 219}}</string>\n\t\t\t\t\t\t\t\t\t<string>{{0, 219}, {1326, 481}}</string>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>LauncherConfigVersion</key>\n\t\t\t\t\t\t<string>8</string>\n\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t<string>1CCC7629064C1048000F2A68</string>\n\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t<string>Debug</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>DebugConsoleVisible</key>\n\t\t\t\t\t\t<string>None</string>\n\t\t\t\t\t\t<key>DebugConsoleWindowFrame</key>\n\t\t\t\t\t\t<string>{{200, 200}, {500, 300}}</string>\n\t\t\t\t\t\t<key>DebugSTDIOWindowFrame</key>\n\t\t\t\t\t\t<string>{{200, 200}, {500, 300}}</string>\n\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t<string>{{0, 350}, {1326, 700}}</string>\n\t\t\t\t\t\t<key>PBXDebugSessionStackFrameViewKey</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>DebugVariablesTableConfiguration</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<string>Name</string>\n\t\t\t\t\t\t\t\t<real>280</real>\n\t\t\t\t\t\t\t\t<string>Value</string>\n\t\t\t\t\t\t\t\t<real>174</real>\n\t\t\t\t\t\t\t\t<string>Summary</string>\n\t\t\t\t\t\t\t\t<real>312</real>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t<string>{{535, 0}, {791, 219}}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>700pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debug</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>XCModuleDock</string>\n\t\t\t\t<string>PBXDebugCLIModule</string>\n\t\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t\t<string>PBXDebugProcessAndThreadModule</string>\n\t\t\t\t<string>PBXDebugProcessViewModule</string>\n\t\t\t\t<string>PBXDebugThreadViewModule</string>\n\t\t\t\t<string>PBXDebugStackFrameViewModule</string>\n\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t</array>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>ED0A9748114728B000484F91</string>\n\t\t\t\t<string>1CCC7628064C1048000F2A68</string>\n\t\t\t\t<string>1CCC7629064C1048000F2A68</string>\n\t\t\t\t<string>ED0A9749114728B000484F91</string>\n\t\t\t\t<string>ED0A974A114728B000484F91</string>\n\t\t\t\t<string>ED0A974B114728B000484F91</string>\n\t\t\t\t<string>ED0A974C114728B000484F91</string>\n\t\t\t\t<string>ED0A974D114728B000484F91</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.debugV3</string>\n\t\t</dict>\n\t</array>\n\t<key>PerspectivesBarVisible</key>\n\t<true/>\n\t<key>ShelfIsVisible</key>\n\t<false/>\n\t<key>SourceDescription</key>\n\t<string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecification.xcperspec'</string>\n\t<key>StatusbarIsVisible</key>\n\t<true/>\n\t<key>TimeStamp</key>\n\t<real>0.0</real>\n\t<key>ToolbarDisplayMode</key>\n\t<integer>1</integer>\n\t<key>ToolbarIsVisible</key>\n\t<true/>\n\t<key>ToolbarSizeMode</key>\n\t<integer>1</integer>\n\t<key>Type</key>\n\t<string>Perspectives</string>\n\t<key>UpdateMessage</key>\n\t<string></string>\n\t<key>WindowJustification</key>\n\t<integer>5</integer>\n\t<key>WindowOrderList</key>\n\t<array>\n\t\t<string>/Users/cole/Data/Documents/CBCB/sr_mapping/RNA-seq/cufflinks/src/cufflinks.xcodeproj</string>\n\t</array>\n\t<key>WindowString</key>\n\t<string>380 87 1326 1091 0 0 1920 1178 </string>\n\t<key>WindowToolsV3</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.debugger</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Debugger</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>HorizontalSplitView</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>_collapsingFrameDimension</key>\n\t\t\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t\t\t<key>_indexOfCollapsedView</key>\n\t\t\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t\t\t<key>_percentageOfCollapsedView</key>\n\t\t\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t\t\t<key>isCollapsed</key>\n\t\t\t\t\t\t\t\t\t\t<string>yes</string>\n\t\t\t\t\t\t\t\t\t\t<key>sizes</key>\n\t\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {317, 164}}</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>{{317, 0}, {377, 164}}</string>\n\t\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>VerticalSplitView</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>_collapsingFrameDimension</key>\n\t\t\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t\t\t<key>_indexOfCollapsedView</key>\n\t\t\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t\t\t<key>_percentageOfCollapsedView</key>\n\t\t\t\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t\t\t\t<key>isCollapsed</key>\n\t\t\t\t\t\t\t\t\t\t<string>yes</string>\n\t\t\t\t\t\t\t\t\t\t<key>sizes</key>\n\t\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {694, 164}}</string>\n\t\t\t\t\t\t\t\t\t\t\t<string>{{0, 164}, {694, 216}}</string>\n\t\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>LauncherConfigVersion</key>\n\t\t\t\t\t\t\t\t<string>8</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1C162984064C10D400B95A72</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Debug - GLUTExamples (Underwater)</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>DebugConsoleDrawerSize</key>\n\t\t\t\t\t\t\t\t<string>{100, 120}</string>\n\t\t\t\t\t\t\t\t<key>DebugConsoleVisible</key>\n\t\t\t\t\t\t\t\t<string>None</string>\n\t\t\t\t\t\t\t\t<key>DebugConsoleWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>{{200, 200}, {500, 300}}</string>\n\t\t\t\t\t\t\t\t<key>DebugSTDIOWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>{{200, 200}, {500, 300}}</string>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {694, 380}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>321 238 694 422 0 0 1440 878 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>100%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>100%</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debugger</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXDebugSessionModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1CD10A99069EF8BA00B06720</string>\n\t\t\t\t<string>1C0AD2AB069F1E9B00FABCE6</string>\n\t\t\t\t<string>1C162984064C10D400B95A72</string>\n\t\t\t\t<string>1C0AD2AC069F1E9B00FABCE6</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.debugV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>321 238 694 422 0 0 1440 878 </string>\n\t\t\t<key>WindowToolGUID</key>\n\t\t\t<string>1CD10A99069EF8BA00B06720</string>\n\t\t\t<key>WindowToolIsVisible</key>\n\t\t\t<integer>0</integer>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.build</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CD0528F0623707200166675</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>&lt;No Editor&gt;</string>\n\t\t\t\t\t\t\t\t<key>PBXSplitModuleInNavigatorKey</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>Split0</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1CD052900623707200166675</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>SplitCount</key>\n\t\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>StatusBarVisibility</key>\n\t\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {500, 215}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>192 257 500 500 0 0 1280 1002 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>218pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>XCMainBuildResultsModuleGUID</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Build</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 222}, {500, 236}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>192 257 500 500 0 0 1280 1002 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXBuildResultsModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>236pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>458pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Build Results</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXBuildResultsModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1C78EAA5065D492600B07095</string>\n\t\t\t\t<string>1C78EAA6065D492600B07095</string>\n\t\t\t\t<string>1CD0528F0623707200166675</string>\n\t\t\t\t<string>XCMainBuildResultsModuleGUID</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.buildV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>192 257 500 500 0 0 1280 1002 </string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.find</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1CDD528C0622207200134675</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t\t\t<string>&lt;No Editor&gt;</string>\n\t\t\t\t\t\t\t\t\t\t<key>PBXSplitModuleInNavigatorKey</key>\n\t\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t\t<key>Split0</key>\n\t\t\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t\t\t<string>1CD0528D0623707200166675</string>\n\t\t\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t\t\t<key>SplitCount</key>\n\t\t\t\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t\t<key>StatusBarVisibility</key>\n\t\t\t\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {781, 167}}</string>\n\t\t\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t\t\t<string>62 385 781 470 0 0 1440 878 </string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t\t\t<string>781pt</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>50%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CD0528E0623707200166675</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Project Find</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{8, 0}, {773, 254}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>62 385 781 470 0 0 1440 878 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXProjectFindModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>50%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>428pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Project Find</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXProjectFindModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1C530D57069F1CE1000CFCEE</string>\n\t\t\t\t<string>1C530D58069F1CE1000CFCEE</string>\n\t\t\t\t<string>1C530D59069F1CE1000CFCEE</string>\n\t\t\t\t<string>1CDD528C0622207200134675</string>\n\t\t\t\t<string>1C530D5A069F1CE1000CFCEE</string>\n\t\t\t\t<string>1CE0B1FE06471DED0097A5F4</string>\n\t\t\t\t<string>1CD0528E0623707200166675</string>\n\t\t\t</array>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>62 385 781 470 0 0 1440 878 </string>\n\t\t\t<key>WindowToolGUID</key>\n\t\t\t<string>1C530D57069F1CE1000CFCEE</string>\n\t\t\t<key>WindowToolIsVisible</key>\n\t\t\t<integer>0</integer>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>FirstTimeWindowDisplayed</key>\n\t\t\t<false/>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.snapshots</string>\n\t\t\t<key>IsVertical</key>\n\t\t\t<true/>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>EDF9412A10E7FF21000A80F7</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Snapshots</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {300, 509}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>215 205 300 550 0 0 1280 778 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>XCSnapshotModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>509pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>509pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Snapshots</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>XCSnapshotModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<true/>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>EDF9412B10E7FF21000A80F7</string>\n\t\t\t\t<string>EDF9412C10E7FF21000A80F7</string>\n\t\t\t\t<string>EDF9412A10E7FF21000A80F7</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.snapshots</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>215 205 300 550 0 0 1280 778 </string>\n\t\t\t<key>WindowToolGUID</key>\n\t\t\t<string>EDF9412B10E7FF21000A80F7</string>\n\t\t\t<key>WindowToolIsVisible</key>\n\t\t\t<false/>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>FirstTimeWindowDisplayed</key>\n\t\t\t<false/>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.debuggerConsole</string>\n\t\t\t<key>IsVertical</key>\n\t\t\t<true/>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1C78EAAC065D492600B07095</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Debugger Console</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {440, 359}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>172 755 440 400 0 0 1920 1178 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXDebugCLIModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>359pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>359pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debugger Console</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXDebugCLIModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<true/>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1C530D5B069F1CE1000CFCEE</string>\n\t\t\t\t<string>ED91C6AE0FAABBA400B5E75C</string>\n\t\t\t\t<string>1C78EAAC065D492600B07095</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.consoleV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>172 755 440 400 0 0 1920 1178 </string>\n\t\t\t<key>WindowToolGUID</key>\n\t\t\t<string>1C530D5B069F1CE1000CFCEE</string>\n\t\t\t<key>WindowToolIsVisible</key>\n\t\t\t<false/>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.scm</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1C78EAB2065D492600B07095</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>&lt;No Editor&gt;</string>\n\t\t\t\t\t\t\t\t<key>PBXSplitModuleInNavigatorKey</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>Split0</key>\n\t\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t\t\t<string>1C78EAB3065D492600B07095</string>\n\t\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t\t<key>SplitCount</key>\n\t\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>StatusBarVisibility</key>\n\t\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {452, 0}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>743 379 452 308 0 0 1280 1002 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>0pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CD052920623707200166675</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>SCM</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>ConsoleFrame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 259}, {452, 0}}</string>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 7}, {452, 259}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>743 379 452 308 0 0 1280 1002 </string>\n\t\t\t\t\t\t\t\t<key>TableConfiguration</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>Status</string>\n\t\t\t\t\t\t\t\t\t<real>30</real>\n\t\t\t\t\t\t\t\t\t<string>FileName</string>\n\t\t\t\t\t\t\t\t\t<real>199</real>\n\t\t\t\t\t\t\t\t\t<string>Path</string>\n\t\t\t\t\t\t\t\t\t<real>197.09500122070312</real>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<key>TableFrame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {452, 250}}</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXCVSModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>262pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>266pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>SCM</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXCVSModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1C78EAB4065D492600B07095</string>\n\t\t\t\t<string>1C78EAB5065D492600B07095</string>\n\t\t\t\t<string>1C78EAB2065D492600B07095</string>\n\t\t\t\t<string>1CD052920623707200166675</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.scmV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>743 379 452 308 0 0 1280 1002 </string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.breakpoints</string>\n\t\t\t<key>IsVertical</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXBottomSmartGroupGIDs</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>1C77FABC04509CD000000102</string>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CE0B1FE06471DED0097A5F4</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Files</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectStructureProvided</key>\n\t\t\t\t\t\t\t\t<string>no</string>\n\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnData</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>\n\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t<real>168</real>\n\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>\n\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t<string>MainColumn</string>\n\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>\n\t\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>\n\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t<string>1C77FABC04509CD000000102</string>\n\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>\n\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t\t<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>\n\t\t\t\t\t\t\t\t\t<string>{{0, 0}, {168, 350}}</string>\n\t\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t\t<key>PBXTopSmartGroupGIDs</key>\n\t\t\t\t\t\t\t\t<array/>\n\t\t\t\t\t\t\t\t<key>XCIncludePerspectivesSwitch</key>\n\t\t\t\t\t\t\t\t<integer>0</integer>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {185, 368}}</string>\n\t\t\t\t\t\t\t\t<key>GroupTreeTableConfiguration</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>MainColumn</string>\n\t\t\t\t\t\t\t\t\t<real>168</real>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>315 424 744 409 0 0 1440 878 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXSmartGroupTreeModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>185pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CA1AED706398EBD00589147</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Detail</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{190, 0}, {554, 368}}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>315 424 744 409 0 0 1440 878 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>XCDetailModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>554pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>368pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>MajorVersion</key>\n\t\t\t<integer>3</integer>\n\t\t\t<key>MinorVersion</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>Name</key>\n\t\t\t<string>Breakpoints</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXSmartGroupTreeModule</string>\n\t\t\t\t<string>XCDetailModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1CDDB66807F98D9800BB5817</string>\n\t\t\t\t<string>1CDDB66907F98D9800BB5817</string>\n\t\t\t\t<string>1CE0B1FE06471DED0097A5F4</string>\n\t\t\t\t<string>1CA1AED706398EBD00589147</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.breakpointsV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>315 424 744 409 0 0 1440 878 </string>\n\t\t\t<key>WindowToolGUID</key>\n\t\t\t<string>1CDDB66807F98D9800BB5817</string>\n\t\t\t<key>WindowToolIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.debugAnimator</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>100%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>100%</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Debug Visualizer</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXNavigatorGroup</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.debugAnimatorV3</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>100 100 700 500 0 0 1280 1002 </string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.bookmarks</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXBookmarksModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>166pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>166pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Bookmarks</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXBookmarksModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>538 42 401 187 0 0 1280 1002 </string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.projectFormatConflicts</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>XCProjectFormatConflictsModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>100%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>100%</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Project Format Conflicts</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>XCProjectFormatConflictsModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>WindowContentMinSize</key>\n\t\t\t<string>450 300</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>50 850 472 307 0 0 1440 877</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.classBrowser</string>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>ContentConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>OptionsSetName</key>\n\t\t\t\t\t\t\t\t<string>Hierarchy, all classes</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleGUID</key>\n\t\t\t\t\t\t\t\t<string>1CA6456E063B45B4001379D8</string>\n\t\t\t\t\t\t\t\t<key>PBXProjectModuleLabel</key>\n\t\t\t\t\t\t\t\t<string>Class Browser - NSObject</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>ClassesFrame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {369, 96}}</string>\n\t\t\t\t\t\t\t\t<key>ClassesTreeTableConfiguration</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>PBXClassNameColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>208</real>\n\t\t\t\t\t\t\t\t\t<string>PBXClassBookColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>22</real>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 0}, {616, 353}}</string>\n\t\t\t\t\t\t\t\t<key>MembersFrame</key>\n\t\t\t\t\t\t\t\t<string>{{0, 105}, {369, 395}}</string>\n\t\t\t\t\t\t\t\t<key>MembersTreeTableConfiguration</key>\n\t\t\t\t\t\t\t\t<array>\n\t\t\t\t\t\t\t\t\t<string>PBXMemberTypeIconColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>22</real>\n\t\t\t\t\t\t\t\t\t<string>PBXMemberNameColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>216</real>\n\t\t\t\t\t\t\t\t\t<string>PBXMemberTypeColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>94</real>\n\t\t\t\t\t\t\t\t\t<string>PBXMemberBookColumnIdentifier</string>\n\t\t\t\t\t\t\t\t\t<real>22</real>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<key>PBXModuleWindowStatusBarHidden2</key>\n\t\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>597 125 616 374 0 0 1280 1002 </string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>PBXClassBrowserModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>354pt</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>354pt</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Class Browser</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>PBXClassBrowserModule</string>\n\t\t\t</array>\n\t\t\t<key>StatusbarIsVisible</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>TableOfContents</key>\n\t\t\t<array>\n\t\t\t\t<string>1C78EABA065D492600B07095</string>\n\t\t\t\t<string>1C78EABB065D492600B07095</string>\n\t\t\t\t<string>1CA6456E063B45B4001379D8</string>\n\t\t\t</array>\n\t\t\t<key>ToolbarConfiguration</key>\n\t\t\t<string>xcode.toolbar.config.classbrowser</string>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>597 125 616 374 0 0 1280 1002 </string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Identifier</key>\n\t\t\t<string>windowTool.refactoring</string>\n\t\t\t<key>IncludeInToolsMenu</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>Layout</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Dock</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>BecomeActive</key>\n\t\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t\t\t<key>GeometryConfiguration</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>Frame</key>\n\t\t\t\t\t\t\t\t<string>{0, 0}, {500, 335}</string>\n\t\t\t\t\t\t\t\t<key>RubberWindowFrame</key>\n\t\t\t\t\t\t\t\t<string>{0, 0}, {500, 335}</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Module</key>\n\t\t\t\t\t\t\t<string>XCRefactoringModule</string>\n\t\t\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t\t\t<string>100%</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Proportion</key>\n\t\t\t\t\t<string>100%</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>Name</key>\n\t\t\t<string>Refactoring</string>\n\t\t\t<key>ServiceClasses</key>\n\t\t\t<array>\n\t\t\t\t<string>XCRefactoringModule</string>\n\t\t\t</array>\n\t\t\t<key>WindowString</key>\n\t\t\t<string>200 200 500 356 0 0 1920 1200 </string>\n\t\t</dict>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "src/cufflinks.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 45;\n\tobjects = {\n\n/* Begin PBXFileReference section */\n\t\tED2606FD108FAF80004BF73E /* cuffdiff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cuffdiff.cpp; sourceTree = \"<group>\"; };\n\t\tED5A97241097AF23001BA454 /* filters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filters.h; sourceTree = \"<group>\"; };\n\t\tED5A97251097AF23001BA454 /* filters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filters.cpp; sourceTree = \"<group>\"; };\n\t\tED7E55FF0FA65536007F93A7 /* abundances.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abundances.h; sourceTree = \"<group>\"; };\n\t\tED7E56000FA65536007F93A7 /* abundances.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abundances.cpp; sourceTree = \"<group>\"; };\n\t\tED7E578B0FA7C19D007F93A7 /* bfs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bfs.h; sourceTree = \"<group>\"; };\n\t\tED7E578C0FA7C19D007F93A7 /* bin_heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bin_heap.h; sourceTree = \"<group>\"; };\n\t\tED7E578D0FA7C19D007F93A7 /* bipartite_matching.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bipartite_matching.h; sourceTree = \"<group>\"; };\n\t\tED7E578F0FA7C19D007F93A7 /* alteration_notifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alteration_notifier.h; sourceTree = \"<group>\"; };\n\t\tED7E57900FA7C19D007F93A7 /* array_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = array_map.h; sourceTree = \"<group>\"; };\n\t\tED7E57910FA7C19D007F93A7 /* base_extender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base_extender.h; sourceTree = \"<group>\"; };\n\t\tED7E57920FA7C19D007F93A7 /* debug_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_map.h; sourceTree = \"<group>\"; };\n\t\tED7E57930FA7C19D007F93A7 /* default_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = default_map.h; sourceTree = \"<group>\"; };\n\t\tED7E57940FA7C19D007F93A7 /* graph_adaptor_extender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graph_adaptor_extender.h; sourceTree = \"<group>\"; };\n\t\tED7E57950FA7C19D007F93A7 /* graph_extender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graph_extender.h; sourceTree = \"<group>\"; };\n\t\tED7E57960FA7C19D007F93A7 /* invalid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = invalid.h; sourceTree = \"<group>\"; };\n\t\tED7E57970FA7C19D007F93A7 /* map_extender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = map_extender.h; sourceTree = \"<group>\"; };\n\t\tED7E57980FA7C19D007F93A7 /* path_dump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = path_dump.h; sourceTree = \"<group>\"; };\n\t\tED7E57990FA7C19D007F93A7 /* traits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = traits.h; sourceTree = \"<group>\"; };\n\t\tED7E579A0FA7C19D007F93A7 /* utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utility.h; sourceTree = \"<group>\"; };\n\t\tED7E579B0FA7C19D007F93A7 /* variant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = variant.h; sourceTree = \"<group>\"; };\n\t\tED7E579C0FA7C19D007F93A7 /* vector_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vector_map.h; sourceTree = \"<group>\"; };\n\t\tED7E579D0FA7C19D007F93A7 /* bucket_heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bucket_heap.h; sourceTree = \"<group>\"; };\n\t\tED7E579E0FA7C19D007F93A7 /* concept_check.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = concept_check.h; sourceTree = \"<group>\"; };\n\t\tED7E57A00FA7C19D007F93A7 /* bpugraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bpugraph.h; sourceTree = \"<group>\"; };\n\t\tED7E57A10FA7C19D007F93A7 /* graph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graph.h; sourceTree = \"<group>\"; };\n\t\tED7E57A20FA7C19D007F93A7 /* graph_components.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graph_components.h; sourceTree = \"<group>\"; };\n\t\tED7E57A30FA7C19D007F93A7 /* heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = heap.h; sourceTree = \"<group>\"; };\n\t\tED7E57A40FA7C19D007F93A7 /* maps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = maps.h; sourceTree = \"<group>\"; };\n\t\tED7E57A50FA7C19D007F93A7 /* matrix_maps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrix_maps.h; sourceTree = \"<group>\"; };\n\t\tED7E57A60FA7C19D007F93A7 /* path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = path.h; sourceTree = \"<group>\"; };\n\t\tED7E57A70FA7C19D007F93A7 /* ugraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ugraph.h; sourceTree = \"<group>\"; };\n\t\tED7E57A80FA7C19D007F93A7 /* dfs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfs.h; sourceTree = \"<group>\"; };\n\t\tED7E57A90FA7C19D007F93A7 /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error.h; sourceTree = \"<group>\"; };\n\t\tED7E57AA0FA7C19D007F93A7 /* graph_adaptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graph_adaptor.h; sourceTree = \"<group>\"; };\n\t\tED7E57AB0FA7C19D007F93A7 /* graph_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graph_utils.h; sourceTree = \"<group>\"; };\n\t\tED7E57AC0FA7C19D007F93A7 /* list_graph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = list_graph.h; sourceTree = \"<group>\"; };\n\t\tED7E57AD0FA7C19D007F93A7 /* maps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = maps.h; sourceTree = \"<group>\"; };\n\t\tED7E57AE0FA7C19D007F93A7 /* math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = math.h; sourceTree = \"<group>\"; };\n\t\tED7E57AF0FA7C19D007F93A7 /* smart_graph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smart_graph.h; sourceTree = \"<group>\"; };\n\t\tED7E57B00FA7C19D007F93A7 /* tolerance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tolerance.h; sourceTree = \"<group>\"; };\n\t\tED7E57B10FA7C19D007F93A7 /* topology.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = topology.h; sourceTree = \"<group>\"; };\n\t\tED898BAD1010C29D00AB035E /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README; path = ../README; sourceTree = SOURCE_ROOT; };\n\t\tED898BAE1010C2A800AB035E /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = SOURCE_ROOT; };\n\t\tED898BAF1010C2BC00AB035E /* AUTHORS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = AUTHORS; path = ../AUTHORS; sourceTree = SOURCE_ROOT; };\n\t\tED91BC060FAE1BFD00BDDEBC /* fib_heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fib_heap.h; sourceTree = \"<group>\"; };\n\t\tED91C29D0FA6CE9400B5E75C /* ax_boost_base.m4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = ax_boost_base.m4; path = ../ax_boost_base.m4; sourceTree = SOURCE_ROOT; };\n\t\tED91C29E0FA6CF1F00B5E75C /* ax_boost_thread.m4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = ax_boost_thread.m4; path = ../ax_boost_thread.m4; sourceTree = SOURCE_ROOT; };\n\t\tED9FACA210532A50006548BB /* gtf_tracking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gtf_tracking.h; sourceTree = \"<group>\"; };\n\t\tED9FACAA10532C16006548BB /* gtf_tracking.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gtf_tracking.cpp; sourceTree = \"<group>\"; };\n\t\tED9FADA810546FEE006548BB /* bundles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bundles.h; sourceTree = \"<group>\"; };\n\t\tED9FADA910546FEE006548BB /* bundles.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bundles.cpp; sourceTree = \"<group>\"; };\n\t\tED9FAE4110547AB8006548BB /* GList.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = GList.hh; sourceTree = \"<group>\"; };\n\t\tEDA7A58810C2DFEB0074A7B7 /* gtf_reads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gtf_reads.cpp; sourceTree = \"<group>\"; };\n\t\tEDABA25B0F7C330600EEAAD3 /* transitive_closure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = transitive_closure.h; sourceTree = \"<group>\"; };\n\t\tEDCFD37B0F81B974002B1976 /* scaffolds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scaffolds.h; sourceTree = \"<group>\"; };\n\t\tEDCFD37C0F81B974002B1976 /* scaffolds.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scaffolds.cpp; sourceTree = \"<group>\"; };\n\t\tEDD30EC80F783E2B00192B4D /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = configure.ac; path = ../configure.ac; sourceTree = SOURCE_ROOT; };\n\t\tEDD30ECA0F783E3200192B4D /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.am; sourceTree = \"<group>\"; };\n\t\tEDD30ECB0F783E3200192B4D /* cufflinks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cufflinks.cpp; sourceTree = \"<group>\"; };\n\t\tEDD30EE60F78436D00192B4D /* hits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hits.cpp; sourceTree = \"<group>\"; };\n\t\tEDD30EE70F78436D00192B4D /* hits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hits.h; sourceTree = \"<group>\"; };\n\t\tEDD30F0F0F78469B00192B4D /* tokenize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tokenize.cpp; sourceTree = \"<group>\"; };\n\t\tEDD30F100F78469B00192B4D /* tokenize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tokenize.h; sourceTree = \"<group>\"; };\n\t\tEDD30F250F78473D00192B4D /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = \"<group>\"; };\n\t\tEDD30F260F78473D00192B4D /* common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = common.cpp; sourceTree = \"<group>\"; };\n\t\tEDDC3B31103B12D300C386C1 /* cuffcompare.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cuffcompare.cpp; sourceTree = \"<group>\"; };\n\t\tEDDC40CE1042467A00C386C1 /* genes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = genes.h; sourceTree = \"<group>\"; };\n\t\tEDDC40CF10424B5D00C386C1 /* genes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = genes.cpp; sourceTree = \"<group>\"; };\n\t\tEDE162AF0F789F1500F7A98B /* assemble.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assemble.h; sourceTree = \"<group>\"; };\n\t\tEDE162B00F789F1500F7A98B /* assemble.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assemble.cpp; sourceTree = \"<group>\"; };\n\t\tEDF05F8A104EF5D100196C88 /* gff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gff.h; sourceTree = \"<group>\"; };\n\t\tEDF05F8B104EF5D100196C88 /* gff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gff.cpp; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXGroup section */\n\t\t08FB7794FE84155DC02AAC07 /* cufflink */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tEDD30ECA0F783E3200192B4D /* Makefile.am */,\n\t\t\t\tEDD30EC80F783E2B00192B4D /* configure.ac */,\n\t\t\t\tED898BAD1010C29D00AB035E /* README */,\n\t\t\t\tED898BAE1010C2A800AB035E /* LICENSE */,\n\t\t\t\tED898BAF1010C2BC00AB035E /* AUTHORS */,\n\t\t\t\tED91C29D0FA6CE9400B5E75C /* ax_boost_base.m4 */,\n\t\t\t\tED91C29E0FA6CF1F00B5E75C /* ax_boost_thread.m4 */,\n\t\t\t\tED7E55FF0FA65536007F93A7 /* abundances.h */,\n\t\t\t\tED7E56000FA65536007F93A7 /* abundances.cpp */,\n\t\t\t\tEDE162AF0F789F1500F7A98B /* assemble.h */,\n\t\t\t\tEDE162B00F789F1500F7A98B /* assemble.cpp */,\n\t\t\t\tED9FADA810546FEE006548BB /* bundles.h */,\n\t\t\t\tED9FADA910546FEE006548BB /* bundles.cpp */,\n\t\t\t\tEDD30F250F78473D00192B4D /* common.h */,\n\t\t\t\tEDD30F260F78473D00192B4D /* common.cpp */,\n\t\t\t\tEDDC3B31103B12D300C386C1 /* cuffcompare.cpp */,\n\t\t\t\tED2606FD108FAF80004BF73E /* cuffdiff.cpp */,\n\t\t\t\tEDD30ECB0F783E3200192B4D /* cufflinks.cpp */,\n\t\t\t\tEDD30EE60F78436D00192B4D /* hits.cpp */,\n\t\t\t\tEDD30EE70F78436D00192B4D /* hits.h */,\n\t\t\t\tED5A97241097AF23001BA454 /* filters.h */,\n\t\t\t\tED5A97251097AF23001BA454 /* filters.cpp */,\n\t\t\t\tEDF05F8A104EF5D100196C88 /* gff.h */,\n\t\t\t\tEDF05F8B104EF5D100196C88 /* gff.cpp */,\n\t\t\t\tEDDC40CE1042467A00C386C1 /* genes.h */,\n\t\t\t\tEDDC40CF10424B5D00C386C1 /* genes.cpp */,\n\t\t\t\tED9FACA210532A50006548BB /* gtf_tracking.h */,\n\t\t\t\tED9FACAA10532C16006548BB /* gtf_tracking.cpp */,\n\t\t\t\tED9FAE4110547AB8006548BB /* GList.hh */,\n\t\t\t\tEDA7A58810C2DFEB0074A7B7 /* gtf_reads.cpp */,\n\t\t\t\tEDCFD37B0F81B974002B1976 /* scaffolds.h */,\n\t\t\t\tEDCFD37C0F81B974002B1976 /* scaffolds.cpp */,\n\t\t\t\tEDD30F0F0F78469B00192B4D /* tokenize.cpp */,\n\t\t\t\tEDD30F100F78469B00192B4D /* tokenize.h */,\n\t\t\t\tEDABA25B0F7C330600EEAAD3 /* transitive_closure.h */,\n\t\t\t\tED7E578A0FA7C19D007F93A7 /* lemon */,\n\t\t\t);\n\t\t\tname = cufflink;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tED7E578A0FA7C19D007F93A7 /* lemon */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tED7E578B0FA7C19D007F93A7 /* bfs.h */,\n\t\t\t\tED7E578C0FA7C19D007F93A7 /* bin_heap.h */,\n\t\t\t\tED7E578D0FA7C19D007F93A7 /* bipartite_matching.h */,\n\t\t\t\tED7E578E0FA7C19D007F93A7 /* bits */,\n\t\t\t\tED7E579D0FA7C19D007F93A7 /* bucket_heap.h */,\n\t\t\t\tED7E579E0FA7C19D007F93A7 /* concept_check.h */,\n\t\t\t\tED7E579F0FA7C19D007F93A7 /* concepts */,\n\t\t\t\tED7E57A80FA7C19D007F93A7 /* dfs.h */,\n\t\t\t\tED7E57A90FA7C19D007F93A7 /* error.h */,\n\t\t\t\tED7E57AA0FA7C19D007F93A7 /* graph_adaptor.h */,\n\t\t\t\tED7E57AB0FA7C19D007F93A7 /* graph_utils.h */,\n\t\t\t\tED91BC060FAE1BFD00BDDEBC /* fib_heap.h */,\n\t\t\t\tED7E57AC0FA7C19D007F93A7 /* list_graph.h */,\n\t\t\t\tED7E57AD0FA7C19D007F93A7 /* maps.h */,\n\t\t\t\tED7E57AE0FA7C19D007F93A7 /* math.h */,\n\t\t\t\tED7E57AF0FA7C19D007F93A7 /* smart_graph.h */,\n\t\t\t\tED7E57B00FA7C19D007F93A7 /* tolerance.h */,\n\t\t\t\tED7E57B10FA7C19D007F93A7 /* topology.h */,\n\t\t\t);\n\t\t\tpath = lemon;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tED7E578E0FA7C19D007F93A7 /* bits */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tED7E578F0FA7C19D007F93A7 /* alteration_notifier.h */,\n\t\t\t\tED7E57900FA7C19D007F93A7 /* array_map.h */,\n\t\t\t\tED7E57910FA7C19D007F93A7 /* base_extender.h */,\n\t\t\t\tED7E57920FA7C19D007F93A7 /* debug_map.h */,\n\t\t\t\tED7E57930FA7C19D007F93A7 /* default_map.h */,\n\t\t\t\tED7E57940FA7C19D007F93A7 /* graph_adaptor_extender.h */,\n\t\t\t\tED7E57950FA7C19D007F93A7 /* graph_extender.h */,\n\t\t\t\tED7E57960FA7C19D007F93A7 /* invalid.h */,\n\t\t\t\tED7E57970FA7C19D007F93A7 /* map_extender.h */,\n\t\t\t\tED7E57980FA7C19D007F93A7 /* path_dump.h */,\n\t\t\t\tED7E57990FA7C19D007F93A7 /* traits.h */,\n\t\t\t\tED7E579A0FA7C19D007F93A7 /* utility.h */,\n\t\t\t\tED7E579B0FA7C19D007F93A7 /* variant.h */,\n\t\t\t\tED7E579C0FA7C19D007F93A7 /* vector_map.h */,\n\t\t\t);\n\t\t\tpath = bits;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tED7E579F0FA7C19D007F93A7 /* concepts */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tED7E57A00FA7C19D007F93A7 /* bpugraph.h */,\n\t\t\t\tED7E57A10FA7C19D007F93A7 /* graph.h */,\n\t\t\t\tED7E57A20FA7C19D007F93A7 /* graph_components.h */,\n\t\t\t\tED7E57A30FA7C19D007F93A7 /* heap.h */,\n\t\t\t\tED7E57A40FA7C19D007F93A7 /* maps.h */,\n\t\t\t\tED7E57A50FA7C19D007F93A7 /* matrix_maps.h */,\n\t\t\t\tED7E57A60FA7C19D007F93A7 /* path.h */,\n\t\t\t\tED7E57A70FA7C19D007F93A7 /* ugraph.h */,\n\t\t\t);\n\t\t\tpath = concepts;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXLegacyTarget section */\n\t\tD28A88AD04BDD90700651E21 /* cufflinks */ = {\n\t\t\tisa = PBXLegacyTarget;\n\t\t\tbuildArgumentsString = \"$(ACTION)\";\n\t\t\tbuildConfigurationList = 1DEB918F08733D9F0010E9CD /* Build configuration list for PBXLegacyTarget \"cufflinks\" */;\n\t\t\tbuildPhases = (\n\t\t\t);\n\t\t\tbuildToolPath = /usr/bin/make;\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = cufflinks;\n\t\t\tpassBuildSettingsInEnvironment = 1;\n\t\t\tproductName = cufflink;\n\t\t};\n\t\tEDD30E1B0F782D7A00192B4D /* test */ = {\n\t\t\tisa = PBXLegacyTarget;\n\t\t\tbuildArgumentsString = check;\n\t\t\tbuildConfigurationList = EDD30E220F782D8C00192B4D /* Build configuration list for PBXLegacyTarget \"test\" */;\n\t\t\tbuildPhases = (\n\t\t\t);\n\t\t\tbuildToolPath = /Users/cole/bin/xcodemake;\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = test;\n\t\t\tpassBuildSettingsInEnvironment = 1;\n\t\t\tproductName = test;\n\t\t};\n/* End PBXLegacyTarget section */\n\n/* Begin PBXProject section */\n\t\t08FB7793FE84155DC02AAC07 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tBuildIndependentTargetsInParallel = YES;\n\t\t\t\tORGANIZATIONNAME = \"Cole Trapnell\";\n\t\t\t};\n\t\t\tbuildConfigurationList = 1DEB919308733D9F0010E9CD /* Build configuration list for PBXProject \"cufflinks\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.1\";\n\t\t\thasScannedForEncodings = 1;\n\t\t\tmainGroup = 08FB7794FE84155DC02AAC07 /* cufflink */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tD28A88AD04BDD90700651E21 /* cufflinks */,\n\t\t\t\tEDD30E1B0F782D7A00192B4D /* test */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin XCBuildConfiguration section */\n\t\t1DEB919008733D9F0010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUGGING_SYMBOLS = YES;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_ENABLE_FIX_AND_CONTINUE = YES;\n\t\t\t\tGCC_GENERATE_DEBUGGING_SYMBOLS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tOTHER_CFLAGS = \"\";\n\t\t\t\tOTHER_LDFLAGS = \"\";\n\t\t\t\tPRODUCT_NAME = cufflinks;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB919108733D9F0010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tGCC_ENABLE_FIX_AND_CONTINUE = NO;\n\t\t\t\tOTHER_CFLAGS = \"\";\n\t\t\t\tOTHER_LDFLAGS = \"\";\n\t\t\t\tPRODUCT_NAME = cufflink;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t1DEB919408733D9F0010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_32_BIT)\";\n\t\t\t\tGCC_VERSION = 4.2;\n\t\t\t\tGCC_VERSION_i386 = 4.2;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPREBINDING = NO;\n\t\t\t\tSDKROOT = macosx10.5;\n\t\t\t\tSYMROOT = \"/Users/cole/Data/Documents/CBCB/sr_mapping/RNA-seq/cufflinks/src/\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB919508733D9F0010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_32_BIT)\";\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tPREBINDING = NO;\n\t\t\t\tSDKROOT = macosx10.5;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tEDD30E1C0F782D7A00192B4D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tPRODUCT_NAME = test;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tEDD30E1D0F782D7A00192B4D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_ENABLE_FIX_AND_CONTINUE = NO;\n\t\t\t\tPRODUCT_NAME = test;\n\t\t\t\tZERO_LINK = NO;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t1DEB918F08733D9F0010E9CD /* Build configuration list for PBXLegacyTarget \"cufflinks\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB919008733D9F0010E9CD /* Debug */,\n\t\t\t\t1DEB919108733D9F0010E9CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t1DEB919308733D9F0010E9CD /* Build configuration list for PBXProject \"cufflinks\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB919408733D9F0010E9CD /* Debug */,\n\t\t\t\t1DEB919508733D9F0010E9CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tEDD30E220F782D8C00192B4D /* Build configuration list for PBXLegacyTarget \"test\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tEDD30E1C0F782D7A00192B4D /* Debug */,\n\t\t\t\tEDD30E1D0F782D7A00192B4D /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 08FB7793FE84155DC02AAC07 /* Project object */;\n}\n"
  },
  {
    "path": "src/cuffmerge",
    "content": "#!/usr/bin/env python2\n# encoding: utf-8\n\"\"\"\ncuffmerge.py\n\nCreated by Cole Trapnell on 2011-03-17.\nCopyright (c) 2011 Cole Trapnell. All rights reserved.\n\"\"\"\n\nimport sys\nimport getopt\nfrom datetime import datetime, date, time\nimport shutil\nimport subprocess\nimport errno\nimport os\nimport tempfile\nimport warnings\nimport types\n\nhelp_message = '''\ncuffmerge takes two or more Cufflinks GTF files and merges them into a\nsingle unified transcript catalog.  Optionally, you can provide the script\nwith a reference GTF, and the script will use it to attach gene names and other\nmetadata to the merged catalog.\n\nUsage:\n    cuffmerge [Options] <assembly_GTF_list.txt>\n\nOptions:\n    -h/--help                               Prints the help message and exits\n    -o                     <output_dir>     Directory where merged assembly will be written  [ default: ./merged_asm  ]\n    -g/--ref-gtf                            An optional \"reference\" annotation GTF.\n    -s/--ref-sequence      <seq_dir>/<seq_fasta> Genomic DNA sequences for the reference.\n    --min-isoform-fraction <0-1.0>          Discard isoforms with abundance below this       [ default:           0.05 ]\n    -p/--num-threads       <int>            Use this many threads to merge assemblies.       [ default:             1  ]\n    --keep-tmp                              Keep all intermediate files during merge\n'''\n\noutput_dir = \"./merged_asm/\"\nlogging_dir = output_dir + \"logs/\"\nrun_log = None\nrun_cmd = None\ntmp_dir = output_dir + \"/tmp/\"\nbin_dir = sys.path[0] + \"/\"\nrun_meta_assembly = True\nfail_str = \"\\t[FAILED]\\n\"\nparams = None\n\nclass Usage(Exception):\n    def __init__(self, msg):\n        self.msg = msg\n\nclass TestParams:\n\n    class SystemParams:\n        def __init__(self,\n                     threads,\n                     keep_tmp):\n            self.threads = threads\n            self.keep_tmp = keep_tmp\n\n        def parse_options(self, opts):\n            for option, value in opts:\n                if option in (\"-p\", \"--num-threads\"):\n                    self.threads = int(value)\n                if option in (\"--keep-tmp\"):\n                    self.keep_tmp = True\n\n        def check(self):\n            pass\n\n    def __init__(self):\n        self.system_params = self.SystemParams(1,               # threads\n                                               False)           # keep_tmp\n        self.ref_gtf = None\n        self.fasta = None\n        self.min_isoform_frac = 0.05\n\n    def check(self):\n        self.system_params.check()\n\n    def parse_options(self, argv):\n        try:\n            opts, args = getopt.getopt(argv[1:],\n                                       \"hvp:o:g:M:s:q:F:\",\n                                       [\"version\",\n                                        \"help\",\n                                        \"ref-sequence=\",\n                                        \"ref-gtf=\",\n                                        \"output-dir=\",\n                                        \"num-threads=\",\n                                        \"keep-tmp\",\n                                        \"min-isoform-fraction=\"])\n        except getopt.error, msg:\n            raise Usage(msg)\n\n        self.system_params.parse_options(opts)\n\n        global output_dir\n        global logging_dir\n        global tmp_dir\n\n        # option processing\n        for option, value in opts:\n            if option in (\"-v\", \"--version\"):\n                print \"merge_cuff_asms v%s\" % (get_version())\n                exit(0)\n            if option in (\"-h\", \"--help\"):\n                raise Usage(help_message)\n            if option in (\"-g\", \"--ref-gtf\"):\n                self.ref_gtf = value\n            if option in (\"-s\", \"--ref-sequence\"):\n                self.fasta = value\n            if option in (\"-F\", \"--min-isoform-fraction\"):\n                self.min_isoform_frac = float(value)\n            if option in (\"-o\", \"--output-dir\"):\n                output_dir = value + \"/\"\n                logging_dir = output_dir + \"logs/\"\n                tmp_dir = output_dir + \"tmp/\"\n\n        return args\n\n\ndef right_now():\n    curr_time = datetime.now()\n    return curr_time.strftime(\"%c\")\n\ndef prepare_output_dir():\n\n    print >> sys.stderr, \"[%s] Preparing output location %s\" % (right_now(), output_dir)\n    if os.path.exists(output_dir):\n        pass\n    else:\n        os.makedirs(output_dir)\n\n    #print >> sys.stderr, \"Checking for %s\", logging_dir\n    if os.path.exists(logging_dir):\n        pass\n    else:\n        #print >> sys.stderr, \"Creating %s\", logging_dir\n        os.makedirs(logging_dir)\n\n    if os.path.exists(tmp_dir):\n        pass\n    else:\n        os.makedirs(tmp_dir)\n\ndef formatTD(td):\n    hours = td.seconds // 3600\n    minutes = (td.seconds % 3600) // 60\n    seconds = td.seconds % 60\n    return '%02d:%02d:%02d' % (hours, minutes, seconds)\n\ndef tmp_name(prefix):\n    tmp_root = output_dir + \"tmp/\"\n    if os.path.exists(tmp_root):\n        pass\n    else:\n        os.mkdir(tmp_root)\n    return tmp_root + prefix + os.tmpnam().split('/')[-1]\n\ndef cufflinks(out_dir,\n              sam_file,\n              min_isoform_frac,\n              gtf_file=None,\n              extra_opts=[\"-q\", \"--overhang-tolerance\", \"200\", \"--library-type=transfrags\",  \"-A\",\"0.0\", \"--min-frags-per-transfrag\", \"0\", \"--no-5-extend\"],\n              lsf=False,\n              curr_queue=None):\n    if gtf_file != None:\n        print >> sys.stderr, \"[%s] Quantitating transcripts\" % (right_now())\n    else:\n        print >> sys.stderr, \"[%s] Assembling transcripts\" % (right_now())\n\n    cmd = [\"cufflinks\"]\n\n    if out_dir != None and out_dir != \"\":\n        cmd.extend([\"-o\", out_dir])\n\n    cmd.extend([\"-F\", str(min_isoform_frac)])\n\n    if gtf_file != None:\n        cmd.extend([\"-g\", gtf_file])\n\n    if extra_opts != None:\n        cmd.extend(extra_opts)\n    global params\n    # Run Cufflinks with more than one thread?\n    cmd.extend([\"-p\", str(params.system_params.threads)])\n\n    cmd.append(sam_file)\n\n    try:\n        print >> run_log, \" \".join(cmd)\n        ret = subprocess.call(cmd)\n        if ret != 0:\n            print >> sys.stderr, fail_str, \"Error: could not execute cufflinks\"\n            exit(1)\n    # cufflinks not found\n    except OSError, o:\n        if o.errno == errno.ENOTDIR or o.errno == errno.ENOENT:\n            print >> sys.stderr, fail_str, \"Error: cufflinks not found on this system.  Did you forget to include it in your PATH?\"\n        exit(1)\n\ndef cuffcompare(prefix, ref_gtf, fasta, cuff_gtf):\n\n    print >> sys.stderr, \"[%s] Comparing reference %s to assembly %s\" % (right_now(), ref_gtf, cuff_gtf)\n    cmd = [\"cuffcompare\"]\n\n    if  prefix != None:\n        cmd.extend([\"-o\", prefix])\n    if  ref_gtf != None:\n        cmd.extend([\"-r\", ref_gtf])\n    if  fasta != None:\n        cmd.extend([\"-s\", fasta])\n    if type(cuff_gtf) == types.ListType:\n        for g in cuff_gtf:\n            cmd.extend([g])\n    else:\n        cmd.extend([cuff_gtf])\n\n    try:\n        print >> run_log, \" \".join(cmd)\n        ret = subprocess.call(cmd)\n        if ret != 0:\n            print >> sys.stderr, fail_str, \"Error: could not execute cuffcompare\"\n            exit(1)\n    # cuffcompare not found\n    except OSError, o:\n        if o.errno == errno.ENOTDIR or o.errno == errno.ENOENT:\n            print >> sys.stderr, fail_str, \"Error: cuffcompare not found on this system.  Did you forget to include it in your PATH?\"\n        exit(1)\n\ndef gtf_to_sam(gtf_filename):\n\n    sam_out = tmp_name(\"gtf2sam_\")\n\n    cmd = [\"gtf_to_sam\"]\n    cmd.append(\"-F\")\n    cmd.append(gtf_filename)\n    cmd.append(sam_out)\n    try:\n        print >> run_log, \" \".join(cmd)\n        ret = subprocess.call(cmd)\n        if ret != 0:\n            print >> sys.stderr, fail_str, \"Error: could not execute gtf_to_sam\"\n            exit(1)\n    # gtf_to_sam not found\n    except OSError, o:\n        if o.errno == errno.ENOTDIR or o.errno == errno.ENOENT:\n            print >> sys.stderr, fail_str, \"Error: gtf_to_sam not found on this system.  Did you forget to include it in your PATH?\"\n        exit(1)\n    return sam_out\n\ndef test_input_files(filename_list):\n    \"\"\"This function takes a file that contains a list of GTF files,\n       tests accessibility of each, and returns the list of filenames\"\"\"\n\n    OK = True\n    input_files = []\n    for line in filename_list:\n        line = line.strip()\n\n        # Skip comment line\n        if len(line) == 0 or line[0] == \"#\":\n            continue\n        try:\n            g = open(line,\"r\")\n            input_files.append(line)\n\n        except OSError, o:\n            if o.errno == errno.ENOTDIR or o.errno == errno.ENOENT:\n                print >> sys.stderr, fail_str, \"Error: could not open %s\" % line\n            OK = False\n    if not OK:\n        sys.exit(1)\n    return input_files\n\ndef convert_gtf_to_sam(gtf_filename_list):\n    \"\"\"This function takes a list of GTF files, converts them all to\n       temporary SAM files, and returns the list of temporary file names.\"\"\"\n    print >> sys.stderr, \"[%s] Converting GTF files to SAM\" % (right_now())\n    OK = True\n    sam_input_filenames = []\n    for line in gtf_filename_list:\n        try:\n            sam_out = gtf_to_sam(line)\n            sam_input_filenames.append(sam_out)\n        except OSError, o:\n            if o.errno == errno.ENOTDIR or o.errno == errno.ENOENT:\n                print >> sys.stderr, fail_str, \"Error: could not open %s\" % line\n            OK = False\n    if not OK:\n        sys.exit(1)\n    return sam_input_filenames\n\ndef merge_sam_inputs(sam_input_list, header):\n    sorted_map_name = tmp_name( \"mergeSam_\")\n\n    sorted_map = open(sorted_map_name, \"w\")\n\n    #print header\n\n    # The header was built from a dict keyed by chrom, so\n    # the records will be lexicographically ordered and\n    # should match the BAM after the sort below.\n    print >> sorted_map, header,\n\n    sorted_map.close()\n    sort_cmd =[\"sort\",\n               \"-k\",\n               \"3,3\",\n               \"-k\",\n               \"4,4n\",\n               \"--temporary-directory=\"+tmp_dir]\n    sort_cmd.extend(sam_input_list)\n\n    print >> run_log, \" \".join(sort_cmd), \">\", sorted_map_name\n    subprocess.call(sort_cmd,\n                   stdout=open(sorted_map_name, \"a\"))\n    return sorted_map_name\n\ndef compare_to_reference(meta_asm_gtf, ref_gtf, fasta):\n    global tmp_dir\n    print >> sys.stderr, \"[%s] Comparing against reference file %s\" % (right_now(), ref_gtf)\n    ref_str = \"\"\n    if ref_gtf != None:\n        ref_str = \" -r %s \" % ref_gtf\n\n    if fasta != None:\n        comp_cmd = '''cuffcompare -o %s -C -G %s -s %s %s''' % (tmp_dir, ref_str, fasta, meta_asm_gtf)\n    else:\n        comp_cmd = '''cuffcompare -o %s -C -G %s %s''' % (tmp_dir, ref_str, meta_asm_gtf)\n\n    #cmd = bsub_cmd(comp_cmd, \"/gencode_cmp\", True, job_mem=8)\n    cmd = comp_cmd\n\n    try:\n        print >> run_log, cmd\n        ret = subprocess.call(cmd,shell=True)\n        if ret != 0:\n            print >> sys.stderr, fail_str, \"Error: could not execute cuffcompare\"\n            exit(1)\n        #tmap_out = meta_asm_gtf.split(\"/\")[-1] + \".tmap\"\n        tfpath, tfname = os.path.split(meta_asm_gtf)\n        if tfpath: tfpath+='/'\n        tmap_out = tfpath+'.'+tfname+\".tmap\"\n        return tmap_out\n    # cuffcompare not found\n    except OSError, o:\n        if o.errno == errno.ENOTDIR or o.errno == errno.ENOENT:\n            print >> sys.stderr, fail_str, \"Error: cuffcompare not found on this system.  Did you forget to include it in your PATH?\"\n        exit(1)\n\ndef select_gtf(gtf_in_filename, ids, gtf_out_filename):\n    f_gtf = open(gtf_in_filename)\n    #print >> sys.stderr, \"Select GTF: Ids are: \"\n    #print >> sys.stderr, ids\n    #print >> sys.stderr, \"reference gtf file name:\"\n    #print >> sys.stderr, gtf_in_filename\n    out_gtf = open(gtf_out_filename, \"w\")\n    for line in f_gtf:\n        line = line.strip()\n        cols = line.split('\\t')\n        if len(cols) < 9:\n            continue\n        attrs = cols[8]\n        attr_cols = attrs.split(';')\n        for col in attr_cols:\n            if col.find(\"transcript_id\") != -1:\n                first_quote = col.find('\"')\n                last_quote = col.find('\"', first_quote + 1)\n                transcript = col[first_quote + 1:last_quote]\n                #print >> sys.stderr, transcript\n                if transcript in ids:\n                    print >> out_gtf, line\n\n\ndef merge_gtfs(gtf_filenames, merged_gtf, ref_gtf=None):\n    print >> sys.stderr, \"[%s] Merging linc gtf files with cuffcompare\" % (right_now())\n    cmd = [\"cuffcompare\"]\n\n    cmd.extend([\"-o\", merged_gtf])\n    if ref_gtf != None:\n        cmd.extend([\"-r\", ref_gtf])\n\n    cmd.extend(gtf_filenames)\n    cmd = \" \".join(cmd)\n    #cmd = bsub_cmd(cmd, \"/merge_gtf\", True, job_mem=8)\n\n    try:\n        print >> run_log, cmd\n        ret = subprocess.call(cmd, shell=True)\n        if ret != 0:\n            print >> sys.stderr, fail_str, \"Error: could not execute cuffcompare\"\n            exit(1)\n        return merged_gtf + \".combined.gtf\"\n    # cuffcompare not found\n    except OSError, o:\n        if o.errno == errno.ENOTDIR or o.errno == errno.ENOENT:\n            print >> sys.stderr, fail_str, \"Error: cuffcompare not found on this system.  Did you forget to include it in your PATH?\"\n        exit(1)\n\ndef compare_meta_asm_against_ref(ref_gtf, fasta_file, gtf_input_file, class_codes=[\"c\", \"i\", \"r\", \"p\", \"e\"]):\n    #print >> sys.stderr, \"Cuffcmpare all assemblies GTFs\"\n\n    tmap = compare_to_reference(gtf_input_file, ref_gtf, fasta_file)\n\n    #print >> sys.stderr, \"Cuffcmpare all assemblies GTFs : filter %s\" % \",\".join(class_codes)\n    selected_ids= set([])\n    f_tmap = open(tmap)\n    #out = open(\"tmp_meta_asm_selectedIds.txt\", \"w\")\n    for line in f_tmap:\n        line = line.strip()\n        cols = line.split('\\t')\n        if len(cols) < 5:\n            continue\n        class_code = cols[2]\n        name = cols[4]\n        if class_code not in class_codes:\n            selected_ids.add(name)\n\n    global output_dir\n    asm_dir = output_dir\n\n    if os.path.exists(asm_dir):\n        pass\n    else:\n        os.mkdir(asm_dir)\n    current_asm_gtf = output_dir +\"transcripts.gtf\"\n    select_gtf(current_asm_gtf, selected_ids, output_dir + \"/merged.gtf\")\n    mtmap = compare_to_reference(output_dir + \"/merged.gtf\", ref_gtf, fasta_file)\n    if os.path.exists(mtmap):\n        os.remove(mtmap)\n    if os.path.exists(mtmap.split(\".tmap\")[0]+\".refmap\"):\n        os.remove(mtmap.split(\".tmap\")[0]+\".refmap\")\n\n    global tmp_dir\n    shutil.move(tmp_dir+\".combined.gtf\", output_dir + \"/merged.gtf\")\n\n#    os.remove(\"tmp_meta_asm.combined.gtf\")\n    if os.path.exists(tmap):\n        os.remove(tmap)\n    if os.path.exists(tmap.split(\".tmap\")[0]+\".refmap\"):\n        os.remove(tmap.split(\".tmap\")[0]+\".refmap\")\n    #tmp_dir = asm_dir\n    #tmp_files = os.listdir(tmp_dir)\n    #for t in tmp_files:\n    #    os.remove(tmp_dir+t)\n    #os.rmdir(tmp_dir)\n\n#os.remove(\"tmp_meta_asm.tmap\")\n\ndef get_version():\n    return \"1.0.0\"\n\ndef get_gtf_chrom_info(gtf_filename, known_chrom_info=None):\n    gtf_file = open(gtf_filename)\n    if known_chrom_info == None:\n        chroms = {}\n    else:\n        chroms = known_chrom_info\n    for line in gtf_file:\n        line = line.strip()\n\n        if len(line) == 0 or line[0] == \"#\":\n            continue\n        cols = line.split('\\t')\n        if len(cols) < 8:\n            continue\n        chrom = cols[0]\n        left = int(cols[3])\n        right = int(cols[4])\n        bounds = chroms.setdefault(chrom, [9999999999,-1])\n        if bounds[0] > left:\n            bounds[0] = left\n        if bounds[1] < right:\n            bounds[1] = right\n    return chroms\n\ndef header_for_chrom_info(chrom_info):\n    header_strs = [\"\"\"@HD\\tVN:1.0\\tSO:coordinate\"\"\"]\n    chrom_list = [(chrom, limits) for chrom, limits in chrom_info.iteritems()]\n    chrom_list.sort(lambda x,y: cmp(x[0],y[0]))\n    #print chrom_list\n    for chrom, limits in chrom_list:\n        line = \"@SQ\\tSN:%s\\tLN:\\t%d\" % (chrom, limits[1])\n        header_strs.append(line)\n    header_strs.append(\"@PG\\tID:cuffmerge\\tVN:1.0.0\\n\")\n    header = \"\\n\".join(header_strs)\n    return header\n\ndef main(argv=None):\n    \n    # Set this so sort is consistent across platforms and python versions \n    # (and always character-lexicographic)\n    os.environ['LC_ALL']='C'\n    warnings.filterwarnings(\"ignore\", \"tmpnam is a potential security risk\")\n    global params\n    params = TestParams()\n\n    try:\n        if argv is None:\n            argv = sys.argv\n            args = params.parse_options(argv)\n            params.check()\n\n        if len(args) < 1:\n            raise(Usage(help_message))\n\n        global run_log\n        global run_cmd\n\n        print >> sys.stderr\n        print >> sys.stderr, \"[%s] Beginning transcriptome assembly merge\" % (right_now())\n        print >> sys.stderr, \"-------------------------------------------\"\n        print >> sys.stderr\n\n        start_time = datetime.now()\n        prepare_output_dir()\n\n        run_log = open(logging_dir + \"run.log\", \"w\", 0)\n        run_cmd = \" \".join(argv)\n        print >> run_log, run_cmd\n\n        transfrag_list_file = open(args[0], \"r\")\n\n        if params.ref_gtf != None:\n            test_input_files([params.ref_gtf])\n        else:\n            print >> sys.stderr, \"Warning: no reference GTF provided!\"\n\n        # Check that all the primary assemblies are accessible before starting the time consuming stuff\n        gtf_input_files = test_input_files(transfrag_list_file)\n\n        all_gtfs = []\n        all_gtfs.extend(gtf_input_files)\n        if params.ref_gtf != None:\n            all_gtfs.append(params.ref_gtf)\n        chrom_info = {}\n        for gtf in all_gtfs:\n            chrom_info = get_gtf_chrom_info(gtf, chrom_info)\n\n        header = header_for_chrom_info(chrom_info)\n\n        #Meta assembly option:\n        global run_meta_assembly\n        if run_meta_assembly:\n            # Convert the primary assemblies to SAM format\n            sam_input_files = convert_gtf_to_sam(gtf_input_files)\n            # Merge the primary assembly SAMs into a single input SAM file\n            merged_sam_filename = merge_sam_inputs(sam_input_files, header)\n            # Run cufflinks on the primary assembly transfrags to generate a meta-assembly\n            cufflinks(output_dir, merged_sam_filename, params.min_isoform_frac, params.ref_gtf)\n            compare_meta_asm_against_ref(params.ref_gtf, params.fasta, output_dir+\"/transcripts.gtf\")\n        #Meta Cuffcompare option:\n        else:\n            cuffcompare_all_assemblies(gtf_input_files) #FIXME: where is this function ?\n\n\n        if not params.system_params.keep_tmp:\n            tmp_files = os.listdir(tmp_dir)\n            for t in tmp_files:\n                os.remove(tmp_dir+t)\n            os.rmdir(tmp_dir)\n            os.remove(output_dir + \"/transcripts.gtf\")\n            os.remove(output_dir + \"/skipped.gtf\")\n            os.remove(output_dir + \"/genes.fpkm_tracking\")\n            os.remove(output_dir + \"/isoforms.fpkm_tracking\")\n    except Usage, err:\n        print >> sys.stderr, sys.argv[0].split(\"/\")[-1] + \": \" + str(err.msg)\n        return 2\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n"
  },
  {
    "path": "src/cuffnorm.cpp",
    "content": "/*\n *  cuffdiff.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 10/21/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <stdlib.h>\n#include <getopt.h>\n#include <string>\n#include <numeric>\n#include <cfloat>\n#include <iostream>\n\n#include \"common.h\"\n#include \"hits.h\"\n#include \"bundles.h\"\n#include \"abundances.h\"\n#include \"tokenize.h\"\n#include \"biascorrection.h\"\n#include \"update_check.h\"\n\n#include <boost/thread.hpp>\n#include <boost/version.hpp>\n#include <boost/graph/adjacency_list.hpp>\n#include <boost/graph/graph_traits.hpp>\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/matrix_proxy.hpp>\n#include <boost/numeric/ublas/vector.hpp>\n#include <boost/numeric/ublas/vector_proxy.hpp>\n#include <boost/numeric/ublas/io.hpp>\n#include <boost/algorithm/string.hpp>\n\n#include <boost/random/mersenne_twister.hpp>\n\n#include \"differential.h\"\n\nextern \"C\" {\n#include \"locfit/local.h\"\n}\n\n// Need at least this many reads in a locus to do any testing on it\n\nvector<string> sample_labels;\n\ndouble FDR = 0.05; \nbool samples_are_time_series = false;\nusing namespace std;\nusing namespace boost;\n\n// We leave out the short codes for options that don't take an argument\n#if ENABLE_THREADS\nconst char *short_options = \"m:p:s:c:I:j:L:M:o:b:TNqvuF:C:\";\n#else\nconst char *short_options = \"m:s:c:I:j:L:M:o:b:TNqvuF:C:\";\n#endif\n\nstatic struct option long_options[] = {\n{\"labels\",\t\t\t\t\trequired_argument,\t\t 0,\t\t\t 'L'},\n{\"seed\",                    required_argument,\t\t 0,\t\t\t OPT_RANDOM_SEED},\n{\"norm-standards-file\",     required_argument,\t\t 0,\t\t\t OPT_NORM_STANDARDS_FILE},\n{\"use-sample-sheet\",        no_argument,             0,\t\t\t OPT_USE_SAMPLE_SHEET},\n{\"output-dir\",\t\t\t    required_argument,\t\t 0,\t\t\t 'o'},\n{\"verbose\",\t\t\t    \tno_argument,\t\t\t 0,\t\t\t 'v'},\n{\"quiet\",\t\t\t    \tno_argument,\t\t\t 0,\t\t\t 'q'},\n#if ENABLE_THREADS\n{\"num-threads\",\t\t\t\trequired_argument,       0,          'p'},\n#endif\n{\"library-type\",\t\t    required_argument,\t\t 0,\t\t\t OPT_LIBRARY_TYPE},\n{\"no-update-check\",         no_argument,             0,          OPT_NO_UPDATE_CHECK},\n{\"compatible-hits-norm\",    no_argument,\t \t\t 0,\t         OPT_USE_COMPAT_MASS},\n{\"total-hits-norm\",         no_argument,\t \t\t 0,\t         OPT_USE_TOTAL_MASS},\n    \n// Some options for testing different stats policies\n{\"max-bundle-frags\",        required_argument,       0,          OPT_MAX_FRAGS_PER_BUNDLE}, \n{\"library-norm-method\",     required_argument,       0,          OPT_LIB_NORM_METHOD},\n{\"output-format\",           required_argument,       0,          OPT_OUTPUT_FORMAT},\n{0, 0, 0, 0} // terminator\n};\n\nvoid print_usage()\n{\n\tfprintf(stderr, \"cuffnorm v%s (%s)\\n\", PACKAGE_VERSION, SVN_REVISION);\n\tfprintf(stderr, \"-----------------------------\\n\"); \n\t\n\t//NOTE: SPACES ONLY, bozo\n    fprintf(stderr, \"Usage:   cuffnorm [options] <transcripts.gtf> <sample1_expr.cxb> <sample2_expr.cxb> [... sampleN_expr.cxb]\\n\");\n\tfprintf(stderr, \"   Supply replicate CXB files as comma separated lists for each condition: sample1_rep1.cxb,sample1_rep2.cxb,...sample1_repM.cxb\\n\");\n    fprintf(stderr, \"General Options:\\n\");\n    fprintf(stderr, \"  -o/--output-dir              write all output files to this directory              [ default:     ./ ]\\n\");\n    fprintf(stderr, \"  -L/--labels                  comma-separated list of condition labels\\n\");\n    fprintf(stderr, \"  --norm-standards-file        Housekeeping/spike genes to normalize libraries       [ default:   NULL ]\\n\"); // NOT YET DOCUMENTED, keep secret for now\n#if ENABLE_THREADS\n\tfprintf(stderr, \"  -p/--num-threads             number of threads used during quantification          [ default:      1 ]\\n\");\n#endif\n    fprintf(stderr, \"  --library-type               Library prep used for input reads                     [ default:  below ]\\n\");\n    fprintf(stderr, \"  --library-norm-method        Method used to normalize library sizes                [ default:  below ]\\n\");\n    fprintf(stderr, \"  --output-format              Format for output tables                              [ default:  below ]\\n\");\n    \n    fprintf(stderr, \"\\nAdvanced Options:\\n\");\n    fprintf(stderr, \"  --compatible-hits-norm       count hits compatible with reference RNAs only        [ default:   TRUE ]\\n\");\n    fprintf(stderr, \"  --total-hits-norm            count all hits for normalization                      [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  -v/--verbose                 log-friendly verbose processing (no progress bar)     [ default:  FALSE ]\\n\");\n\tfprintf(stderr, \"  -q/--quiet                   log-friendly quiet processing (no progress bar)       [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --seed                       value of random number generator seed                 [ default:      0 ]\\n\");\n    fprintf(stderr, \"  --no-update-check            do not contact server to check for update availability[ default:  FALSE ]\\n\");\n    print_library_table();\n    print_lib_norm_method_table();\n    print_output_format_table();\n}\n\nint parse_options(int argc, char** argv)\n{\n    int option_index = 0;\n    int next_option;\n    string sample_label_list;\n    string dispersion_method_str;\n    string lib_norm_method_str;\n    string output_format_str;\n\n    do {\n        next_option = getopt_long_only(argc, argv, short_options, long_options, &option_index);\n        if (next_option == -1)     /* Done with options. */\n            break;\n        switch (next_option) {\n            case 0:\n                /* If this option set a flag, do nothing else now. */\n                if (long_options[option_index].flag != 0)\n                    break;\n                break;\n                \n\t\t\tcase 'p':\n\t\t\t\tnum_threads = (uint32_t)parseInt(1, \"-p/--num-threads arg must be at least 1\", print_usage);\n\t\t\t\tbreak;\n            case 'F':\n\t\t\t\tmin_isoform_fraction = parseFloat(0, 1.0, \"-F/--min-isoform-fraction must be between 0 and 1.0\", print_usage);\n\t\t\t\tbreak;\n            case 'L':\n\t\t\t\tsample_label_list = optarg;\n\t\t\t\tbreak;\n\n\n\t\t\tcase OPT_NORM_STANDARDS_FILE:\n\t\t\t{\n\t\t\t\tnorm_standards_filename = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_USE_SAMPLE_SHEET:\n\t\t\t{\n                use_sample_sheet = true;\n\t\t\t\tbreak;\n\t\t\t}\n            case 'v':\n\t\t\t{\n\t\t\t\tif (cuff_quiet)\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Warning: Can't be both verbose and quiet!  Setting verbose only.\\n\");\n\t\t\t\t}\n\t\t\t\tcuff_quiet = false;\n\t\t\t\tcuff_verbose = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'q':\n\t\t\t{\n\t\t\t\tif (cuff_verbose)\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Warning: Can't be both verbose and quiet!  Setting quiet only.\\n\");\n\t\t\t\t}\n\t\t\t\tcuff_verbose = false;\n\t\t\t\tcuff_quiet = true;\n\t\t\t\tbreak;\n\t\t\t}\n            case 'o':\n\t\t\t{\n\t\t\t\toutput_dir = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n\n\n            case OPT_LIBRARY_TYPE:\n\t\t\t{\n\t\t\t\tlibrary_type = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n\n            case OPT_NO_UPDATE_CHECK:\n            {\n                no_update_check = true;\n                break;\n            }\n            case OPT_RANDOM_SEED:\n            {\n                random_seed = parseInt(0, \"--seed must be at least 0\", print_usage);\n                break;\n            }\n            case OPT_USE_COMPAT_MASS:\n            {\n                use_compat_mass = true;\n                break;\n            }\n            case OPT_USE_TOTAL_MASS:\n            {\n                use_total_mass = true;\n                break;\n            }\n            case OPT_LIB_NORM_METHOD:\n\t\t\t{\n\t\t\t\tlib_norm_method_str = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_OUTPUT_FORMAT:\n\t\t\t{\n\t\t\t\toutput_format_str = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tprint_usage();\n\t\t\t\treturn 1;\n        }\n    } while(next_option != -1);\n\t\n\tif (library_type != \"\")\n    {\n        map<string, ReadGroupProperties>::iterator lib_itr = \n\t\tlibrary_type_table.find(library_type);\n        if (lib_itr == library_type_table.end())\n        {\n            fprintf(stderr, \"Error: Library type %s not supported\\n\", library_type.c_str());\n            exit(1);\n        }\n        else \n        {\n            if (library_type == \"transfrags\")\n            {\n                allow_junk_filtering = false;\n            }\n            global_read_properties = &lib_itr->second;\n        }\n    }\n    else\n    {\n        \n    }\n    \n    // Set the count dispersion method to use\n    if (dispersion_method_str == \"\")\n    {\n        dispersion_method_str = default_dispersion_method;\n    }\n    \n    map<string, DispersionMethod>::iterator disp_itr = \n    dispersion_method_table.find(dispersion_method_str);\n    if (disp_itr == dispersion_method_table.end())\n    {\n        fprintf(stderr, \"Error: Dispersion method %s not supported\\n\", dispersion_method_str.c_str());\n        exit(1);\n    }\n    else \n    {\n        dispersion_method = disp_itr->second;\n    }\n\n    // Set the library size normalization method to use\n    if (lib_norm_method_str == \"\")\n    {\n        lib_norm_method_str = default_lib_norm_method;\n    }\n    \n    map<string, LibNormalizationMethod>::iterator lib_norm_itr =\n    lib_norm_method_table.find(lib_norm_method_str);\n    if (lib_norm_itr == lib_norm_method_table.end())\n    {\n        fprintf(stderr, \"Error: Normalization method %s not supported\\n\", lib_norm_method_str.c_str());\n        exit(1);\n    }\n    else\n    {\n        lib_norm_method = lib_norm_itr->second;\n    }\n\n    // Set the count dispersion method to use\n    if (output_format_str == \"\")\n    {\n        output_format_str = default_output_format;\n    }\n    \n    map<string, OutputFormat>::iterator output_itr =\n    output_format_table.find(output_format_str);\n    if (output_itr == output_format_table.end())\n    {\n        fprintf(stderr, \"Error: Output format %s not supported\\n\", output_format_str.c_str());\n        exit(1);\n    }\n    else\n    {\n        output_format = output_itr->second;\n    }\n\n    if (use_total_mass && use_compat_mass)\n    {\n        fprintf (stderr, \"Error: please supply only one of --compatibile-hits-norm and --total-hits-norm\\n\");\n        exit(1);\n    }\n    \n    tokenize(sample_label_list, \",\", sample_labels);\n    \n\tallow_junk_filtering = false;\n\t\n\treturn 0;\n}\n\n#if ENABLE_THREADS\nboost::mutex inspect_lock;\n#endif\n\nvoid inspect_map_worker(ReplicatedBundleFactory& fac,\n                        int& tmp_min_frag_len, \n                        int& tmp_max_frag_len,\n                        IdToLocusMap& id_to_locus_map)\n{\n#if ENABLE_THREADS\n\tboost::this_thread::at_thread_exit(decr_pool_count);\n#endif\n    \n    int min_f = std::numeric_limits<int>::max();\n    int max_f = 0;\n    \n    fac.inspect_replicate_maps(min_f, max_f, id_to_locus_map);\n    \n#if ENABLE_THREADS\n    inspect_lock.lock();\n#endif\n    tmp_min_frag_len = min(min_f, tmp_min_frag_len);\n    tmp_max_frag_len = max(max_f, tmp_max_frag_len);\n#if ENABLE_THREADS\n    inspect_lock.unlock();\n#endif\n}\n\nboost::shared_ptr<TrackingDataWriter> tracking_data_writer;\n\nbool quantitate_next_locus(const RefSequenceTable& rt,\n                           vector<boost::shared_ptr<ReplicatedBundleFactory> >& bundle_factories,\n                           boost::shared_ptr<TestLauncher> launcher)\n{\n    for (size_t i = 0; i < bundle_factories.size(); ++i)\n    {\n        boost::shared_ptr<SampleAbundances> s_ab = boost::shared_ptr<SampleAbundances>(new SampleAbundances);\n        \n#if ENABLE_THREADS\t\t\t\t\t\n        while(1)\n        {\n            locus_thread_pool_lock.lock();\n            if (locus_curr_threads < locus_num_threads)\n            {\n                break;\n            }\n            \n            locus_thread_pool_lock.unlock();\n            \n            boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n            \n        }\n        \n        locus_curr_threads++;\n        locus_thread_pool_lock.unlock();\n        \n        boost::shared_ptr<HitBundle> pBundle = boost::shared_ptr<HitBundle>(new HitBundle());\n        bool non_empty = bundle_factories[i]->next_bundle(*pBundle, true);\n        \n        if (pBundle->compatible_mass() > 0)\n        {\n            thread quantitate(sample_worker,\n                              non_empty,\n                              pBundle,\n                              boost::ref(rt),\n                              boost::ref(*(bundle_factories[i])),\n                              s_ab,\n                              i,\n                              launcher,\n                              false);\n        }\n        else\n        {\n            sample_worker(non_empty,\n                          pBundle,\n                          boost::ref(rt),\n                          boost::ref(*(bundle_factories[i])),\n                          s_ab,\n                          i,\n                          launcher,\n                          false);\n            locus_thread_pool_lock.lock();\n            locus_curr_threads--;\n            locus_thread_pool_lock.unlock();\n        }\n#else\n        HitBundle bundle;\n        bool non_empty = sample_factory.next_bundle(bundle);\n        \n        sample_worker(non_emtpy,\n                      pBundle,\n                      boost::ref(rt),\n                      boost::ref(*(bundle_factories[i])),\n                      s_ab,\n                      i,\n                      launcher,\n                      false);\n#endif\n    }\n    return true;\n}\n\nvoid parse_sample_sheet_file(FILE* sample_sheet_file,\n                             vector<string>& sample_labels,\n                             vector<string>& sam_hit_filename_lists)\n{\n    \n    char pBuf[10 * 1024];\n    size_t non_blank_lines_read = 0;\n    \n    sample_labels.clear();\n    \n    map<string, vector<string> > sample_groups;\n    \n    while (fgets(pBuf, 10*1024, sample_sheet_file))\n    {\n        if (strlen(pBuf) > 0)\n        {\n            char* nl = strchr(pBuf, '\\n');\n            if (nl)\n                *nl = 0;\n            \n            string pBufstr = pBuf;\n            string trimmed = boost::trim_copy(pBufstr);\n            \n            if (trimmed.length() > 0 && trimmed[0] != '#')\n            {\n                non_blank_lines_read++;\n                vector<string> columns;\n                tokenize(trimmed, \"\\t\", columns);\n                \n                if (non_blank_lines_read == 1)\n                    continue;\n                \n                if (columns.size() < 2)\n                {\n                    if (columns.size() > 0)\n                        fprintf(stderr, \"Malformed record in sample sheet: \\n   >  %s\\n\", pBuf);\n                    else\n                        continue;\n                }\n                \n                string sam_file = columns[0];\n                string sample_group = columns[1];\n                \n                pair<map<string, vector<string> >::iterator, bool> inserted = sample_groups.insert(make_pair(sample_group, vector<string>()));\n                inserted.first->second.push_back(sam_file);\n            }\n        }\n    }\n    \n    for (map<string, vector<string> >::iterator itr = sample_groups.begin();\n         itr != sample_groups.end(); ++itr)\n    {\n        sample_labels.push_back(itr->first);\n        string sam_list = boost::join(itr->second, \",\");\n        sam_hit_filename_lists.push_back(sam_list);\n    }\n}\n\nvoid parse_norm_standards_file(FILE* norm_standards_file)\n{\n    char pBuf[10 * 1024];\n    size_t non_blank_lines_read = 0;\n    \n    boost::shared_ptr<map<string, LibNormStandards> > norm_standards(new map<string, LibNormStandards>);\n    \n    while (fgets(pBuf, 10*1024, norm_standards_file))\n    {\n        if (strlen(pBuf) > 0)\n        {\n            char* nl = strchr(pBuf, '\\n');\n            if (nl)\n                *nl = 0;\n            \n            string pBufstr = pBuf;\n            string trimmed = boost::trim_copy(pBufstr);\n            \n            if (trimmed.length() > 0 && trimmed[0] != '#')\n            {\n                non_blank_lines_read++;\n                vector<string> columns;\n                tokenize(trimmed, \"\\t\", columns);\n                \n                if (non_blank_lines_read == 1)\n                    continue;\n                \n                if (columns.size() < 1) // \n                {\n                    continue;\n                }\n                \n                string gene_id = columns[0];\n                LibNormStandards L;\n                norm_standards->insert(make_pair(gene_id, L));\n            }\n        }\n    }\n    lib_norm_standards = norm_standards;\n}\n\n\nvoid print_variability_models(FILE* var_model_out, const vector<boost::shared_ptr<ReplicatedBundleFactory> >& factories)\n{\n\n    fprintf(var_model_out, \"condition\\tlocus\\tcompatible_count_mean\\tcompatible_count_var\\ttotal_count_mean\\ttotal_count_var\\tfitted_var\\n\");\n    \n    for (size_t i = 0; i < factories.size(); ++i)\n    {\n        string factor_name = factories[i]->condition_name();\n        boost::shared_ptr<ReadGroupProperties> rg = factories[i]->factories()[0]->read_group_properties();\n        boost::shared_ptr<MassDispersionModel const> model = rg->mass_dispersion_model();\n//        const vector<double>& means = model->scaled_compatible_mass_means();\n//        const vector<double>& raw_vars  = model->scaled_compatible_variances();\n        \n        const vector<LocusCount>& common_scale_compatible_counts = rg->common_scale_compatible_counts();\n        for (size_t j = 0; j < common_scale_compatible_counts.size(); ++j)\n        {\n            string locus_desc = common_scale_compatible_counts[j].locus_desc;\n            pair<double, double> compat_mean_and_var = model->get_compatible_mean_and_var(locus_desc);\n            pair<double, double> total_mean_and_var = model->get_total_mean_and_var(locus_desc);\n//            double total_compat_count = 0;\n//            if (itr != locus_to_total_count_table.end())\n//                total_compat_count = itr->second.count;\n            \n            \n            fprintf(var_model_out, \"%s\\t%s\\t%lg\\t%lg\\t%lg\\t%lg\\t%lg\\n\",\n                    factor_name.c_str(),\n                    locus_desc.c_str(),\n                    compat_mean_and_var.first,\n                    compat_mean_and_var.second,\n                    total_mean_and_var.first,\n                    total_mean_and_var.second,\n                    model->scale_mass_variance(compat_mean_and_var.first));\n        }\n    }\n    fclose(var_model_out);\n\n}\n\nvoid driver(FILE* ref_gtf, FILE* mask_gtf, FILE* contrast_file, FILE* norm_standards_file, vector<string>& sam_hit_filename_lists, Outfiles& outfiles)\n{\n\n\tReadTable it;\n\tRefSequenceTable rt(true, false);\n    \n\tvector<boost::shared_ptr<Scaffold> > ref_mRNAs;\n\t\n\tvector<boost::shared_ptr<ReplicatedBundleFactory> > bundle_factories;\n    vector<boost::shared_ptr<ReadGroupProperties> > all_read_groups;\n    set<boost::shared_ptr<ReadGroupProperties> > serialized_read_groups;\n    \n\tfor (size_t i = 0; i < sam_hit_filename_lists.size(); ++i)\n\t{\n        vector<string> sam_hit_filenames;\n        tokenize(sam_hit_filename_lists[i], \",\", sam_hit_filenames);\n        \n        vector<boost::shared_ptr<BundleFactory> > replicate_factories;\n        \n        string condition_name = sample_labels[i];\n        \n        for (size_t j = 0; j < sam_hit_filenames.size(); ++j)\n        {\n            boost::shared_ptr<HitFactory> hs;\n            boost::shared_ptr<BundleFactory> hf;\n            try\n            {\n                hs = boost::shared_ptr<HitFactory>(new PrecomputedExpressionHitFactory(sam_hit_filenames[j], it, rt));\n                hf = boost::shared_ptr<BundleFactory>(new PrecomputedExpressionBundleFactory(static_pointer_cast<PrecomputedExpressionHitFactory>(hs)));\n            }\n            \n            catch(boost::archive::archive_exception & e)\n            {\n\t\t\t\ths = boost::shared_ptr<HitFactory>(createSamHitFactory(sam_hit_filenames[j], it, rt));\n                hf = boost::shared_ptr<BundleFactory>(new BundleFactory(hs, REF_DRIVEN));\n            }\n            \n            \n            boost::shared_ptr<ReadGroupProperties> rg_props(new ReadGroupProperties);\n            \n            if (global_read_properties)\n            {\n                *rg_props = *global_read_properties;\n            }\n            else \n            {\n                *rg_props = hs->read_group_properties();\n            }\n            \n            rg_props->checked_parameters(hs->read_group_properties().checked_parameters());\n            rg_props->condition_name(condition_name);\n            rg_props->replicate_num(j);\n            rg_props->file_path(sam_hit_filenames[j]);\n            \n            all_read_groups.push_back(rg_props);\n            \n            hf->read_group_properties(rg_props);\n            \n            replicate_factories.push_back(hf);\n            //replicate_factories.back()->set_ref_rnas(ref_mRNAs);\n        }\n        \n        bundle_factories.push_back(boost::shared_ptr<ReplicatedBundleFactory>(new ReplicatedBundleFactory(replicate_factories, condition_name)));\n\t}\n    \n    boost::crc_32_type ref_gtf_crc_result;\n    ::load_ref_rnas(ref_gtf, rt, ref_mRNAs, ref_gtf_crc_result, corr_bias, false);\n    if (ref_mRNAs.empty())\n        return;\n    \n    vector<boost::shared_ptr<Scaffold> > mask_rnas;\n    if (mask_gtf)\n    {\n        boost::crc_32_type mask_gtf_crc_result;\n        ::load_ref_rnas(mask_gtf, rt, mask_rnas, mask_gtf_crc_result, false, false);\n    }\n    \n    BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> fac, bundle_factories)\n    {\n        // NOTE: we aren't deep copying here to save memory.  We can pull this off\n        // because unless bias correction or multiread correction is enabled,\n        // we don't need to write into Scaffold objects.\n        fac->set_ref_rnas(ref_mRNAs, false);\n        if (mask_gtf) \n            fac->set_mask_rnas(mask_rnas);\n    }\n    \n    if (norm_standards_file != NULL)\n    {\n        parse_norm_standards_file(norm_standards_file);\n    }\n\n    validate_cross_sample_parameters(all_read_groups);\n    \n    vector<pair<size_t, size_t > > contrasts;\n    \n#if ENABLE_THREADS\n    locus_num_threads = num_threads;\n#endif\n\n\tint tmp_min_frag_len = numeric_limits<int>::max();\n\tint tmp_max_frag_len = 0;\n\t\n    boost::shared_ptr<IdToLocusMap> id_to_locus_map(new IdToLocusMap(boost::shared_ptr<map<string, set<string> > >(new map<string, set<string> >())));\n    \n\tProgressBar p_bar(\"Inspecting maps and determining fragment length distributions.\",0);\n\tBOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> fac, bundle_factories)\n    {\n#if ENABLE_THREADS\t\n        while(1)\n        {\n            locus_thread_pool_lock.lock();\n            if (locus_curr_threads < locus_num_threads)\n            {\n                break;\n            }\n            \n            locus_thread_pool_lock.unlock();\n            \n            boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n        }\n        \n        locus_curr_threads++;\n        locus_thread_pool_lock.unlock();\n        \n        thread inspect(inspect_map_worker,\n                       boost::ref(*fac),\n                       boost::ref(tmp_min_frag_len),\n                       boost::ref(tmp_max_frag_len),\n                       boost::ref(*id_to_locus_map));\n#else\n        inspect_map_worker(boost::ref(*fac),\n                           boost::ref(tmp_min_frag_len),\n                           boost::ref(tmp_max_frag_len),\n                           boost::ref(*id_to_locus_map));\n#endif\n    }\n    \n    // wait for the workers to finish up before reporting everthing.\n#if ENABLE_THREADS\t\n    while(1)\n    {\n        locus_thread_pool_lock.lock();\n        if (locus_curr_threads == 0)\n        {\n            locus_thread_pool_lock.unlock();\n            break;\n        }\n        locus_thread_pool_lock.unlock();\n        \n        boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n    }\n#endif\n    \n    normalize_counts(all_read_groups);\n    \n    long double total_norm_mass = 0.0;\n    long double total_mass = 0.0;\n    BOOST_FOREACH (boost::shared_ptr<ReadGroupProperties> rg_props, all_read_groups)\n    {\n        total_norm_mass += rg_props->normalized_map_mass();\n        total_mass += rg_props->total_map_mass();\n        rg_props->clear_count_tables();\n    }\n\n\tmin_frag_len = tmp_min_frag_len;\n    max_frag_len = tmp_max_frag_len;\n\t\n\tfinal_est_run = false;\n\t\n\tdouble num_bundles = (double)bundle_factories[0]->num_bundles();\n\t\n    p_bar = ProgressBar(\"Calculating preliminary abundance estimates\", num_bundles);\n    \n    Tracking tracking;\n    \n\tfinal_est_run = true;\n\tp_bar = ProgressBar(\"Normalizing expression levels for locus\", num_bundles);\n                                                     \n    tracking_data_writer = boost::shared_ptr<TrackingDataWriter>(new TrackingDataWriter(bundle_factories.size(), &outfiles, &tracking, all_read_groups, sample_labels, &p_bar, id_to_locus_map));\n    \n\twhile (true)\n\t{\n        //boost::shared_ptr<vector<boost::shared_ptr<SampleAbundances> > > abundances(new vector<boost::shared_ptr<SampleAbundances> >());\n        quantitate_next_locus(rt, bundle_factories, tracking_data_writer);\n        bool more_loci_remain = false;\n        BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories) \n        {\n            if (rep_fac->bundles_remain())\n            {\n                more_loci_remain = true;\n                break;\n            }\n        }\n        if (!more_loci_remain)\n        {\n            // wait for the workers to finish up before doing the cross-sample testing.\n#if ENABLE_THREADS\t\n            while(1)\n            {\n                locus_thread_pool_lock.lock();\n                if (locus_curr_threads == 0)\n                {\n                    locus_thread_pool_lock.unlock();\n                    break;\n                }\n                \n                locus_thread_pool_lock.unlock();\n                \n                boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n                \n            }\n#endif\n            break;\n        }\n    }\n\t\n\tp_bar.complete();\n    \n}\n\nvoid open_outfiles_for_writing_cuffdiff_format(Outfiles& outfiles)\n{\n    \n    static const int filename_buf_size = 2048;\n    \n\tchar isoform_fpkm_tracking_name[filename_buf_size];\n\tsprintf(isoform_fpkm_tracking_name, \"%s/isoforms.fpkm_tracking\", output_dir.c_str());\n\tFILE* isoform_fpkm_out = fopen(isoform_fpkm_tracking_name, \"w\");\n\tif (!isoform_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open isoform-level FPKM tracking file %s for writing\\n\",\n\t\t\t\tisoform_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.isoform_fpkm_tracking_out = isoform_fpkm_out;\n    \n\tchar tss_group_fpkm_tracking_name[filename_buf_size];\n\tsprintf(tss_group_fpkm_tracking_name, \"%s/tss_groups.fpkm_tracking\", output_dir.c_str());\n\tFILE* tss_group_fpkm_out = fopen(tss_group_fpkm_tracking_name, \"w\");\n\tif (!tss_group_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open TSS group-level FPKM tracking file %s for writing\\n\",\n\t\t\t\ttss_group_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.tss_group_fpkm_tracking_out = tss_group_fpkm_out;\n    \n\tchar cds_fpkm_tracking_name[filename_buf_size];\n\tsprintf(cds_fpkm_tracking_name, \"%s/cds.fpkm_tracking\", output_dir.c_str());\n\tFILE* cds_fpkm_out = fopen(cds_fpkm_tracking_name, \"w\");\n\tif (!cds_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open CDS level FPKM tracking file %s for writing\\n\",\n\t\t\t\tcds_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.cds_fpkm_tracking_out = cds_fpkm_out;\n\t\n\tchar gene_fpkm_tracking_name[filename_buf_size];\n\tsprintf(gene_fpkm_tracking_name, \"%s/genes.fpkm_tracking\", output_dir.c_str());\n\tFILE* gene_fpkm_out = fopen(gene_fpkm_tracking_name, \"w\");\n\tif (!gene_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open gene-level FPKM tracking file %s for writing\\n\",\n\t\t\t\tgene_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.gene_fpkm_tracking_out = gene_fpkm_out;\n    \n    char isoform_count_tracking_name[filename_buf_size];\n\tsprintf(isoform_count_tracking_name, \"%s/isoforms.count_tracking\", output_dir.c_str());\n\tFILE* isoform_count_out = fopen(isoform_count_tracking_name, \"w\");\n\tif (!isoform_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open isoform-level count tracking file %s for writing\\n\",\n\t\t\t\tisoform_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.isoform_count_tracking_out = isoform_count_out;\n    \n\tchar tss_group_count_tracking_name[filename_buf_size];\n\tsprintf(tss_group_count_tracking_name, \"%s/tss_groups.count_tracking\", output_dir.c_str());\n\tFILE* tss_group_count_out = fopen(tss_group_count_tracking_name, \"w\");\n\tif (!tss_group_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open TSS group-level count tracking file %s for writing\\n\",\n\t\t\t\ttss_group_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.tss_group_count_tracking_out = tss_group_count_out;\n    \n\tchar cds_count_tracking_name[filename_buf_size];\n\tsprintf(cds_count_tracking_name, \"%s/cds.count_tracking\", output_dir.c_str());\n\tFILE* cds_count_out = fopen(cds_count_tracking_name, \"w\");\n\tif (!cds_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open CDS level count tracking file %s for writing\\n\",\n\t\t\t\tcds_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.cds_count_tracking_out = cds_count_out;\n\t\n\tchar gene_count_tracking_name[filename_buf_size];\n\tsprintf(gene_count_tracking_name, \"%s/genes.count_tracking\", output_dir.c_str());\n\tFILE* gene_count_out = fopen(gene_count_tracking_name, \"w\");\n\tif (!gene_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open gene-level count tracking file %s for writing\\n\",\n\t\t\t\tgene_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.gene_count_tracking_out = gene_count_out;\n    \n    char isoform_rep_tracking_name[filename_buf_size];\n\tsprintf(isoform_rep_tracking_name, \"%s/isoforms.read_group_tracking\", output_dir.c_str());\n\tFILE* isoform_rep_out = fopen(isoform_rep_tracking_name, \"w\");\n\tif (!isoform_rep_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open isoform-level read group tracking file %s for writing\\n\",\n\t\t\t\tisoform_rep_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.isoform_rep_tracking_out = isoform_rep_out;\n    \n\tchar tss_group_rep_tracking_name[filename_buf_size];\n\tsprintf(tss_group_rep_tracking_name, \"%s/tss_groups.read_group_tracking\", output_dir.c_str());\n\tFILE* tss_group_rep_out = fopen(tss_group_rep_tracking_name, \"w\");\n\tif (!tss_group_rep_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open TSS group-level read group tracking file %s for writing\\n\",\n\t\t\t\ttss_group_rep_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.tss_group_rep_tracking_out = tss_group_rep_out;\n    \n\tchar cds_rep_tracking_name[filename_buf_size];\n\tsprintf(cds_rep_tracking_name, \"%s/cds.read_group_tracking\", output_dir.c_str());\n\tFILE* cds_rep_out = fopen(cds_rep_tracking_name, \"w\");\n\tif (!cds_rep_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open CDS level read group tracking file %s for writing\\n\",\n\t\t\t\tcds_rep_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.cds_rep_tracking_out = cds_rep_out;\n\t\n\tchar gene_rep_tracking_name[filename_buf_size];\n\tsprintf(gene_rep_tracking_name, \"%s/genes.read_group_tracking\", output_dir.c_str());\n\tFILE* gene_rep_out = fopen(gene_rep_tracking_name, \"w\");\n\tif (!gene_rep_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open gene-level read group tracking file %s for writing\\n\",\n\t\t\t\tgene_rep_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.gene_rep_tracking_out = gene_rep_out;\n    \n    char read_group_info_name[filename_buf_size];\n\tsprintf(read_group_info_name, \"%s/read_groups.info\", output_dir.c_str());\n\tFILE* read_group_out = fopen(read_group_info_name, \"w\");\n\tif (!read_group_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open read group info file %s for writing\\n\",\n\t\t\t\tread_group_info_name);\n\t\texit(1);\n\t}\n\toutfiles.read_group_info_out = read_group_out;\n    \n    char run_info_name[filename_buf_size];\n\tsprintf(run_info_name, \"%s/run.info\", output_dir.c_str());\n\tFILE* run_info_out = fopen(run_info_name, \"w\");\n\tif (!run_info_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open run info file %s for writing\\n\",\n\t\t\t\trun_info_name);\n\t\texit(1);\n\t}\n\toutfiles.run_info_out = run_info_out;\n\n}\n\nvoid open_outfiles_for_writing_simple_table_format(Outfiles& outfiles)\n{\n    static const int filename_buf_size = 2048;\n    \n\tchar isoform_fpkm_tracking_name[filename_buf_size];\n\tsprintf(isoform_fpkm_tracking_name, \"%s/isoforms.fpkm_table\", output_dir.c_str());\n\tFILE* isoform_fpkm_out = fopen(isoform_fpkm_tracking_name, \"w\");\n\tif (!isoform_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open isoform-level FPKM table %s for writing\\n\",\n\t\t\t\tisoform_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.isoform_fpkm_tracking_out = isoform_fpkm_out;\n    \n\tchar tss_group_fpkm_tracking_name[filename_buf_size];\n\tsprintf(tss_group_fpkm_tracking_name, \"%s/tss_groups.fpkm_table\", output_dir.c_str());\n\tFILE* tss_group_fpkm_out = fopen(tss_group_fpkm_tracking_name, \"w\");\n\tif (!tss_group_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open TSS group-level FPKM table %s for writing\\n\",\n\t\t\t\ttss_group_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.tss_group_fpkm_tracking_out = tss_group_fpkm_out;\n    \n\tchar cds_fpkm_tracking_name[filename_buf_size];\n\tsprintf(cds_fpkm_tracking_name, \"%s/cds.fpkm_table\", output_dir.c_str());\n\tFILE* cds_fpkm_out = fopen(cds_fpkm_tracking_name, \"w\");\n\tif (!cds_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open CDS level FPKM table %s for writing\\n\",\n\t\t\t\tcds_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.cds_fpkm_tracking_out = cds_fpkm_out;\n\t\n\tchar gene_fpkm_tracking_name[filename_buf_size];\n\tsprintf(gene_fpkm_tracking_name, \"%s/genes.fpkm_table\", output_dir.c_str());\n\tFILE* gene_fpkm_out = fopen(gene_fpkm_tracking_name, \"w\");\n\tif (!gene_fpkm_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open gene-level FPKM table %s for writing\\n\",\n\t\t\t\tgene_fpkm_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.gene_fpkm_tracking_out = gene_fpkm_out;\n    \n    char isoform_count_tracking_name[filename_buf_size];\n\tsprintf(isoform_count_tracking_name, \"%s/isoforms.count_table\", output_dir.c_str());\n\tFILE* isoform_count_out = fopen(isoform_count_tracking_name, \"w\");\n\tif (!isoform_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open isoform-level count table %s for writing\\n\",\n\t\t\t\tisoform_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.isoform_count_tracking_out = isoform_count_out;\n    \n\tchar tss_group_count_tracking_name[filename_buf_size];\n\tsprintf(tss_group_count_tracking_name, \"%s/tss_groups.count_table\", output_dir.c_str());\n\tFILE* tss_group_count_out = fopen(tss_group_count_tracking_name, \"w\");\n\tif (!tss_group_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open TSS group-level count table %s for writing\\n\",\n\t\t\t\ttss_group_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.tss_group_count_tracking_out = tss_group_count_out;\n    \n\tchar cds_count_tracking_name[filename_buf_size];\n\tsprintf(cds_count_tracking_name, \"%s/cds.count_table\", output_dir.c_str());\n\tFILE* cds_count_out = fopen(cds_count_tracking_name, \"w\");\n\tif (!cds_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open CDS level count table %s for writing\\n\",\n\t\t\t\tcds_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.cds_count_tracking_out = cds_count_out;\n\t\n\tchar gene_count_tracking_name[filename_buf_size];\n\tsprintf(gene_count_tracking_name, \"%s/genes.count_table\", output_dir.c_str());\n\tFILE* gene_count_out = fopen(gene_count_tracking_name, \"w\");\n\tif (!gene_count_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open gene-level count table %s for writing\\n\",\n\t\t\t\tgene_count_tracking_name);\n\t\texit(1);\n\t}\n\toutfiles.gene_count_tracking_out = gene_count_out;\n \n    char isoform_attr_name[filename_buf_size];\n\tsprintf(isoform_attr_name, \"%s/isoforms.attr_table\", output_dir.c_str());\n\tFILE* isoform_attr_out = fopen(isoform_attr_name, \"w\");\n\tif (!isoform_attr_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open isoform-level attribute table %s for writing\\n\",\n\t\t\t\tisoform_attr_name);\n\t\texit(1);\n\t}\n\toutfiles.isoform_attr_out = isoform_attr_out;\n    \n\tchar tss_group_attr_name[filename_buf_size];\n\tsprintf(tss_group_attr_name, \"%s/tss_groups.attr_table\", output_dir.c_str());\n\tFILE* tss_group_attr_out = fopen(tss_group_attr_name, \"w\");\n\tif (!tss_group_attr_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open TSS group-level attribute table %s for writing\\n\",\n\t\t\t\ttss_group_attr_name);\n\t\texit(1);\n\t}\n\toutfiles.tss_group_attr_out = tss_group_attr_out;\n    \n\tchar cds_attr_name[filename_buf_size];\n\tsprintf(cds_attr_name, \"%s/cds.attr_table\", output_dir.c_str());\n\tFILE* cds_attr_out = fopen(cds_attr_name, \"w\");\n\tif (!cds_attr_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open CDS level attribute table %s for writing\\n\",\n\t\t\t\tcds_attr_name);\n\t\texit(1);\n\t}\n\toutfiles.cds_attr_out = cds_attr_out;\n\t\n\tchar gene_attr_name[filename_buf_size];\n\tsprintf(gene_attr_name, \"%s/genes.attr_table\", output_dir.c_str());\n\tFILE* gene_attr_out = fopen(gene_attr_name, \"w\");\n\tif (!gene_attr_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open gene-level attribute table %s for writing\\n\",\n\t\t\t\tgene_attr_name);\n\t\texit(1);\n\t}\n\toutfiles.gene_attr_out = gene_attr_out;\n    \n    char read_group_info_name[filename_buf_size];\n\tsprintf(read_group_info_name, \"%s/samples.table\", output_dir.c_str());\n\tFILE* read_group_out = fopen(read_group_info_name, \"w\");\n\tif (!read_group_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open read group info file %s for writing\\n\",\n\t\t\t\tread_group_info_name);\n\t\texit(1);\n\t}\n\toutfiles.read_group_info_out = read_group_out;\n    \n    char run_info_name[filename_buf_size];\n\tsprintf(run_info_name, \"%s/run.info\", output_dir.c_str());\n\tFILE* run_info_out = fopen(run_info_name, \"w\");\n\tif (!run_info_out)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open run info file %s for writing\\n\",\n\t\t\t\trun_info_name);\n\t\texit(1);\n\t}\n\toutfiles.run_info_out = run_info_out;\n    \n}\n\nvoid open_outfiles_for_writing(Outfiles& outfiles)\n{\n    if (output_format == CUFFDIFF_OUTPUT_FMT)\n    {\n        open_outfiles_for_writing_cuffdiff_format(outfiles);\n    }\n    else if (output_format == SIMPLE_TABLE_OUTPUT_FMT)\n    {\n        open_outfiles_for_writing_simple_table_format(outfiles);\n    }\n    else{\n        fprintf(stderr, \"Error: unrecognized output format!\\n\");\n        exit(1);\n    }\n\n}\n\nint main(int argc, char** argv)\n{\n    for (int i = 0; i < argc; ++i)\n    {\n        cmd_str += string(argv[i]) + \" \";\n    }\n    \n    init_library_table();\n    init_dispersion_method_table();\n    init_lib_norm_method_table();\n    init_output_format_table();\n    \n    min_isoform_fraction = 1e-5;\n    \n\tint parse_ret = parse_options(argc,argv);\n    if (parse_ret)\n        return parse_ret;\n\t\n    if (!use_total_mass && !use_compat_mass)\n    {\n        use_total_mass = false;\n        use_compat_mass = true;   \n    }\n    \n\tif(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n    \n    if (!no_update_check)\n        check_version(PACKAGE_VERSION);\n    \n    string ref_gtf_filename = argv[optind++];\n    vector<string> sam_hit_filenames;\n    \n    if (use_sample_sheet)\n    {\n        if  (optind < argc)\n        {\n            \n            string sample_sheet_filename = argv[optind++];\n            FILE* sample_sheet_file = NULL;\n            if (sample_sheet_filename != \"\")\n            {\n                sample_sheet_file = fopen(sample_sheet_filename.c_str(), \"r\");\n                if (!sample_sheet_file)\n                {\n                    fprintf(stderr, \"Error: cannot open sample sheet file %s for reading\\n\",\n                            sample_sheet_filename.c_str());\n                    exit(1);\n                }\n            }\n            parse_sample_sheet_file(sample_sheet_file, sample_labels, sam_hit_filenames);\n        }\n        else\n        {\n            fprintf(stderr, \"Error: option --use-sample-sheet requires a single sample sheet filename instead of a list of SAM/BAM files\\n\");\n        }\n    }\n    else\n    {\n        while(optind < argc)\n        {\n            string sam_hits_file_name = argv[optind++];\n            sam_hit_filenames.push_back(sam_hits_file_name);\n        }\n        \n        if (sample_labels.size() == 0)\n        {\n            for (size_t i = 1; i < sam_hit_filenames.size() + 1; ++i)\n            {\n                char buf[256];\n                sprintf(buf, \"q%lu\", i);\n                sample_labels.push_back(buf);\n            }\n        }\n    }\n    \t\n\twhile (sam_hit_filenames.size() < 2)\n    {\n        fprintf(stderr, \"Error: cuffdiff requires at least 2 SAM files\\n\");\n        exit(1);\n    }\n\t\n    \n    if (sam_hit_filenames.size() != sample_labels.size())\n    {\n        fprintf(stderr, \"Error: number of labels must match number of conditions\\n\");\n        exit(1);\n    }\n    \n    if (random_seed == -1)\n        random_seed = boost::mt19937::default_seed;\n        \n\t// seed the random number generator - we'll need it for the importance\n\t// sampling during MAP estimation of the gammas\n\tsrand48(random_seed);\n\t\n\tFILE* ref_gtf = NULL;\n\tif (ref_gtf_filename != \"\")\n\t{\n\t\tref_gtf = fopen(ref_gtf_filename.c_str(), \"r\");\n\t\tif (!ref_gtf)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open reference GTF file %s for reading\\n\",\n\t\t\t\t\tref_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\t\n\tFILE* mask_gtf = NULL;\n\tif (mask_gtf_filename != \"\")\n\t{\n\t\tmask_gtf = fopen(mask_gtf_filename.c_str(), \"r\");\n\t\tif (!mask_gtf)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open mask GTF file %s for reading\\n\",\n\t\t\t\t\tmask_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\n\t\n    FILE* contrast_file = NULL;\n\tif (contrast_filename != \"\")\n\t{\n\t\tcontrast_file = fopen(contrast_filename.c_str(), \"r\");\n\t\tif (!contrast_file)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open contrast file %s for reading\\n\",\n\t\t\t\t\tcontrast_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\n    FILE* norm_standards_file = NULL;\n\tif (norm_standards_filename != \"\")\n\t{\n\t\tnorm_standards_file = fopen(norm_standards_filename.c_str(), \"r\");\n\t\tif (!norm_standards_file)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open contrast file %s for reading\\n\",\n\t\t\t\t\tnorm_standards_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n    \n\n\t// Note: we don't want the assembly filters interfering with calculations \n\t// here\n\t\n\tpre_mrna_fraction = 0.0;\n    olap_radius = 0;\n\t\n\tOutfiles outfiles;\n\t\n    if (output_dir != \"\")\n    {\n        int retcode = mkpath(output_dir.c_str(), 0777);\n        if (retcode == -1)\n        {\n            if (errno != EEXIST)\n            {\n                fprintf (stderr, \n                         \"Error: cannot create directory %s\\n\", \n                         output_dir.c_str());\n                exit(1);\n            }\n        }\n    }\n\n    open_outfiles_for_writing(outfiles);\n    \n    driver(ref_gtf, mask_gtf, contrast_file, norm_standards_file, sam_hit_filenames, outfiles);\n\t\n#if 0\n    if (emit_count_tables)\n    {\n        dump_locus_variance_info(output_dir + string(\"/locus_var.txt\"));\n    }\n#endif\n    \n\treturn 0;\n}\n"
  },
  {
    "path": "src/cuffquant.cpp",
    "content": "/*\n *  cuffdiff.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 10/21/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <stdlib.h>\n#include <getopt.h>\n#include <string>\n#include <numeric>\n#include <cfloat>\n#include <iostream>\n#include <fstream>\n\n#include \"common.h\"\n#include \"hits.h\"\n#include \"bundles.h\"\n#include \"abundances.h\"\n#include \"tokenize.h\"\n#include \"biascorrection.h\"\n#include \"update_check.h\"\n\n#include <boost/thread.hpp>\n#include <boost/version.hpp>\n#include <boost/graph/adjacency_list.hpp>\n#include <boost/graph/graph_traits.hpp>\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/matrix_proxy.hpp>\n#include <boost/numeric/ublas/vector.hpp>\n#include <boost/numeric/ublas/vector_proxy.hpp>\n#include <boost/numeric/ublas/io.hpp>\n#include <boost/algorithm/string.hpp>\n\n#include \"replicates.h\"\n#include \"tracking.h\"\n\n// Need at least this many reads in a locus to do any testing on it\n\nvector<string> sample_labels;\n\nusing namespace std;\nusing namespace boost;\n\n// We leave out the short codes for options that don't take an argument\n#if ENABLE_THREADS\nconst char *short_options = \"m:p:s:c:I:j:L:M:o:b:TNqvuF:C:\";\n#else\nconst char *short_options = \"m:s:c:I:j:L:M:o:b:TNqvuF:C:\";\n#endif\n\n\n\nstatic struct option long_options[] = {\n{\"frag-len-mean\",\t\t\trequired_argument,       0,          'm'},\n{\"frag-len-std-dev\",        required_argument,       0,          's'},\n{\"seed\",                    required_argument,\t\t 0,\t\t\t OPT_RANDOM_SEED},\n{\"mask-file\",               required_argument,\t\t 0,\t\t\t 'M'},\n{\"output-dir\",\t\t\t    required_argument,\t\t 0,\t\t\t 'o'},\n{\"verbose\",\t\t\t    \tno_argument,\t\t\t 0,\t\t\t 'v'},\n{\"quiet\",\t\t\t    \tno_argument,\t\t\t 0,\t\t\t 'q'},\n{\"frag-bias-correct\",       required_argument,\t\t 0,\t\t\t 'b'},\n{\"multi-read-correct\",      no_argument,\t\t\t 0,\t\t\t 'u'},\n#if ENABLE_THREADS\n{\"num-threads\",\t\t\t\trequired_argument,       0,          'p'},\n#endif\n{\"library-type\",\t\t    required_argument,\t\t 0,\t\t\t OPT_LIBRARY_TYPE},\n{\"seed\",                    required_argument,\t\t 0,\t\t\t OPT_RANDOM_SEED},\n{\"no-collapse-cond-prob\",   no_argument,             0,\t\t\t OPT_COLLAPSE_COND_PROB},\n{\"max-mle-iterations\",\t\trequired_argument,\t\t 0,\t\t\t OPT_MLE_MAX_ITER},\n{\"min-mle-accuracy\",\t\trequired_argument,\t\t 0,\t\t\t OPT_MLE_MIN_ACC},\n{\"bias-mode\",               required_argument,\t\t 0,\t\t\t OPT_BIAS_MODE},\n{\"no-update-check\",         no_argument,             0,          OPT_NO_UPDATE_CHECK},\n    \n// Some options for testing different stats policies\n{\"max-bundle-frags\",        required_argument,       0,          OPT_MAX_FRAGS_PER_BUNDLE}, \n{\"max-frag-multihits\",      required_argument,       0,          OPT_FRAG_MAX_MULTIHITS},\n{\"no-effective-length-correction\",  no_argument,     0,          OPT_NO_EFFECTIVE_LENGTH_CORRECTION},\n{\"no-length-correction\",    no_argument,             0,          OPT_NO_LENGTH_CORRECTION},\n{0, 0, 0, 0} // terminator\n};\n\nvoid print_usage()\n{\n\tfprintf(stderr, \"cuffquant v%s (%s)\\n\", PACKAGE_VERSION, SVN_REVISION); \n\tfprintf(stderr, \"-----------------------------\\n\"); \n\t\n\t//NOTE: SPACES ONLY, bozo\n    fprintf(stderr, \"Usage:   cuffquant [options] <transcripts.gtf> <sample1_hits.sam> <sample2_hits.sam> [... sampleN_hits.sam]\\n\");\n\tfprintf(stderr, \"   Supply replicate SAMs as comma separated lists for each condition: sample1_rep1.sam,sample1_rep2.sam,...sample1_repM.sam\\n\");\n    fprintf(stderr, \"General Options:\\n\");\n    fprintf(stderr, \"  -o/--output-dir              write all output files to this directory              [ default:     ./ ]\\n\");\n\tfprintf(stderr, \"  -M/--mask-file               ignore all alignment within transcripts in this file  [ default:   NULL ]\\n\");\n    //fprintf(stderr, \"  --norm-standards-file        Housekeeping/spike genes to normalize libraries       [ default:   NULL ]\\n\"); // NOT YET DOCUMENTED, keep secret for now\n    fprintf(stderr, \"  -b/--frag-bias-correct       use bias correction - reference fasta required        [ default:   NULL ]\\n\");\n    fprintf(stderr, \"  -u/--multi-read-correct      use 'rescue method' for multi-reads                   [ default:  FALSE ]\\n\");\n#if ENABLE_THREADS\n\tfprintf(stderr, \"  -p/--num-threads             number of threads used during quantification          [ default:      1 ]\\n\");\n#endif\n    fprintf(stderr, \"  --library-type               Library prep used for input reads                     [ default:  below ]\\n\");\n    \n    fprintf(stderr, \"\\nAdvanced Options:\\n\");\n    fprintf(stderr, \"  -m/--frag-len-mean           average fragment length (unpaired reads only)         [ default:    200 ]\\n\");\n    fprintf(stderr, \"  -s/--frag-len-std-dev        fragment length std deviation (unpaired reads only)   [ default:     80 ]\\n\");\n    fprintf(stderr, \"  -c/--min-alignment-count     minimum number of alignments in a locus for testing   [ default:   10 ]\\n\");\n    fprintf(stderr, \"  --max-mle-iterations         maximum iterations allowed for MLE calculation        [ default:   5000 ]\\n\");\n    fprintf(stderr, \"  -v/--verbose                 log-friendly verbose processing (no progress bar)     [ default:  FALSE ]\\n\");\n\tfprintf(stderr, \"  -q/--quiet                   log-friendly quiet processing (no progress bar)       [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --seed                       value of random number generator seed                 [ default:      0 ]\\n\");\n    fprintf(stderr, \"  --no-update-check            do not contact server to check for update availability[ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --max-bundle-frags           maximum fragments allowed in a bundle before skipping [ default: 500000 ]\\n\");\n    fprintf(stderr, \"  --max-frag-multihits         Maximum number of alignments allowed per fragment     [ default: unlim  ]\\n\");\n    fprintf(stderr, \"  --no-effective-length-correction   No effective length correction                  [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --no-length-correction       No length correction                                  [ default:  FALSE ]\\n\");\n    \n    fprintf(stderr, \"\\nDebugging use only:\\n\");\n    fprintf(stderr, \"  --read-skip-fraction         Skip a random subset of reads this size               [ default:    0.0 ]\\n\");\n    fprintf(stderr, \"  --no-read-pairs              Break all read pairs                                  [ default:  FALSE ]\\n\");\n    fprintf(stderr, \"  --trim-read-length           Trim reads to be this long (keep 5' end)              [ default:   none ]\\n\");\n    fprintf(stderr, \"  --no-scv-correction          Disable SCV correction                                [ default:  FALSE ]\\n\");\n    print_library_table();\n}\n\nint parse_options(int argc, char** argv)\n{\n    int option_index = 0;\n    int next_option;\n    string sample_label_list;\n    string dispersion_method_str;\n    string lib_norm_method_str;\n    do {\n        next_option = getopt_long_only(argc, argv, short_options, long_options, &option_index);\n        if (next_option == -1)     /* Done with options. */\n            break;\n        switch (next_option) {\n            case 0:\n                /* If this option set a flag, do nothing else now. */\n                if (long_options[option_index].flag != 0)\n                    break;\n                break;\n                \n\t\t\tcase 'm':\n\t\t\t\tuser_provided_fld = true;\n\t\t\t\tdef_frag_len_mean = (uint32_t)parseInt(0, \"-m/--frag-len-mean arg must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase 's':\n\t\t\t\tuser_provided_fld = true;\n\t\t\t\tdef_frag_len_std_dev = (uint32_t)parseInt(0, \"-s/--frag-len-std-dev arg must be at least 0\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase 'p':\n\t\t\t\tnum_threads = (uint32_t)parseInt(1, \"-p/--num-threads arg must be at least 1\", print_usage);\n\t\t\t\tbreak;\n            case 'L':\n\t\t\t\tsample_label_list = optarg;\n\t\t\t\tbreak;\n\t\t\tcase OPT_NUM_IMP_SAMPLES:\n\t\t\t\tnum_importance_samples = parseInt(1, \"--num-importance-samples must be at least 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase OPT_MLE_MAX_ITER:\n\t\t\t\tmax_mle_iterations = parseInt(1, \"--max-mle-iterations must be at least 1\", print_usage);\n\t\t\t\tbreak;\n\t\t\tcase OPT_BIAS_MODE:\n\t\t\t\tif (!strcmp(optarg, \"site\"))\n\t\t\t\t\tbias_mode = SITE;\n\t\t\t\telse if (!strcmp(optarg, \"pos\"))\n\t\t\t\t\tbias_mode = POS;\n\t\t\t\telse if (!strcmp(optarg, \"pos_vlmm\"))\n\t\t\t\t\tbias_mode = POS_VLMM;\n\t\t\t\telse if (!strcmp(optarg, \"vlmm\"))\n\t\t\t\t\tbias_mode = VLMM;\n                else if (!strcmp(optarg, \"pos_site\"))\n\t\t\t\t\tbias_mode = POS_SITE;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Unknown bias mode.\\n\");\n\t\t\t\t\texit(1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'M':\n\t\t\t{\n\t\t\t\tmask_gtf_filename = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OPT_NORM_STANDARDS_FILE:\n\t\t\t{\n\t\t\t\tnorm_standards_filename = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case 'v':\n\t\t\t{\n\t\t\t\tif (cuff_quiet)\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Warning: Can't be both verbose and quiet!  Setting verbose only.\\n\");\n\t\t\t\t}\n\t\t\t\tcuff_quiet = false;\n\t\t\t\tcuff_verbose = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'q':\n\t\t\t{\n\t\t\t\tif (cuff_verbose)\n\t\t\t\t{\n\t\t\t\t\tfprintf(stderr, \"Warning: Can't be both verbose and quiet!  Setting quiet only.\\n\");\n\t\t\t\t}\n\t\t\t\tcuff_verbose = false;\n\t\t\t\tcuff_quiet = true;\n\t\t\t\tbreak;\n\t\t\t}\n            case 'o':\n\t\t\t{\n\t\t\t\toutput_dir = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'b':\n\t\t\t{\n\t\t\t\tfasta_dir = optarg;\n\t\t\t\tcorr_bias = true;\n\t\t\t\tbreak;\n            }    \n            \n            case 'u':\n            {\n                corr_multi = true;\n                break;\n            }\n            case OPT_LIBRARY_TYPE:\n\t\t\t{\n\t\t\t\tlibrary_type = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            case OPT_NO_UPDATE_CHECK:\n            {\n                no_update_check = true;\n                break;\n            }\n            case OPT_RANDOM_SEED:\n            {\n                random_seed = parseInt(0, \"--seed must be at least 0\", print_usage);\n                break;\n            }  \n            case OPT_COLLAPSE_COND_PROB:\n            {\n                cond_prob_collapse = false;\n                break;\n            }\n            case OPT_USE_COMPAT_MASS:\n            {\n                use_compat_mass = true;\n                break;\n            }\n            case OPT_USE_TOTAL_MASS:\n            {\n                use_total_mass = true;\n                break;\n            }\n            case OPT_MAX_FRAGS_PER_BUNDLE:\n            {\n                max_frags_per_bundle = parseInt(0, \"--max-bundle-frags must be at least 0\", print_usage);\n                break;\n            }\n            case OPT_READ_SKIP_FRACTION:\n            {\n                read_skip_fraction = parseFloat(0, 1.0, \"--read-skip-fraction must be between 0 and 1.0\", print_usage);\n                break;\n            }\n            case OPT_NO_READ_PAIRS:\n            {\n                no_read_pairs = true;\n                break;\n            }\n            case OPT_TRIM_READ_LENGTH:\n            {\n                trim_read_length = parseInt(0, \"--trim-read-length must be at least 1\", print_usage);\n                break;\n            }\n            case OPT_FRAG_MAX_MULTIHITS:\n            {\n                max_frag_multihits = parseInt(1, \"--max-frag-multihits must be at least 1\", print_usage);\n                break;\n            }\n            case OPT_NO_EFFECTIVE_LENGTH_CORRECTION:\n            {\n                no_effective_length_correction = true;\n                break;\n            }\n            case OPT_NO_LENGTH_CORRECTION:\n            {\n                no_length_correction = true;\n                break;\n            }\n            case OPT_LIB_NORM_METHOD:\n\t\t\t{\n\t\t\t\tlib_norm_method_str = optarg;\n\t\t\t\tbreak;\n\t\t\t}\n            \n\t\t\tdefault:\n\t\t\t\tprint_usage();\n\t\t\t\treturn 1;\n        }\n    } while(next_option != -1);\n\t\n\tif (library_type != \"\")\n    {\n        map<string, ReadGroupProperties>::iterator lib_itr = \n\t\tlibrary_type_table.find(library_type);\n        if (lib_itr == library_type_table.end())\n        {\n            fprintf(stderr, \"Error: Library type %s not supported\\n\", library_type.c_str());\n            exit(1);\n        }\n        else \n        {\n            if (library_type == \"transfrags\")\n            {\n                allow_junk_filtering = false;\n            }\n            global_read_properties = &lib_itr->second;\n        }\n    }\n    else\n    {\n        \n    }\n    \n    // Set the count dispersion method to use\n    if (dispersion_method_str == \"\")\n    {\n        dispersion_method_str = default_dispersion_method;\n    }\n    \n    map<string, DispersionMethod>::iterator disp_itr = \n    dispersion_method_table.find(dispersion_method_str);\n    if (disp_itr == dispersion_method_table.end())\n    {\n        fprintf(stderr, \"Error: Dispersion method %s not supported\\n\", dispersion_method_str.c_str());\n        exit(1);\n    }\n    else \n    {\n        dispersion_method = disp_itr->second;\n    }\n\n    // Set the library size normalization method to use\n    if (lib_norm_method_str == \"\")\n    {\n        lib_norm_method_str = default_lib_norm_method;\n    }\n    \n    map<string, LibNormalizationMethod>::iterator lib_norm_itr =\n    lib_norm_method_table.find(lib_norm_method_str);\n    if (lib_norm_itr == lib_norm_method_table.end())\n    {\n        fprintf(stderr, \"Error: Normalization method %s not supported\\n\", lib_norm_method_str.c_str());\n        exit(1);\n    }\n    else\n    {\n        lib_norm_method = lib_norm_itr->second;\n    }\n\n\n    \n    if (use_total_mass && use_compat_mass)\n    {\n        fprintf (stderr, \"Error: please supply only one of --compatibile-hits-norm and --total-hits-norm\\n\");\n        exit(1);\n    }\n    \n    tokenize(sample_label_list, \",\", sample_labels);\n    \n\tallow_junk_filtering = false;\n\t\n\treturn 0;\n}\n\nstruct Outfiles\n{\n\tFILE* isoform_fpkm_tracking_out;\n\tFILE* tss_group_fpkm_tracking_out;\n\tFILE* gene_fpkm_tracking_out;\n\tFILE* cds_fpkm_tracking_out;\n    \n    FILE* isoform_count_tracking_out;\n\tFILE* tss_group_count_tracking_out;\n\tFILE* gene_count_tracking_out;\n\tFILE* cds_count_tracking_out;\n    \n    FILE* run_info_out;\n    FILE* read_group_info_out;\n    FILE* bias_out;\n    FILE* var_model_out;\n};\n\nvoid print_FPKM_tracking(FILE* fout, \n\t\t\t\t\t\t const FPKMTrackingTable& tracking)\n{\n\tfprintf(fout,\"tracking_id\\tclass_code\\tnearest_ref_id\\tgene_id\\tgene_short_name\\ttss_id\\tlocus\\tlength\\tcoverage\");\n\tFPKMTrackingTable::const_iterator first_itr = tracking.begin();\n\tif (first_itr != tracking.end())\n\t{\n\t\tconst FPKMTracking& track = first_itr->second;\n\t\tconst vector<FPKMContext>& fpkms = track.fpkm_series;\n\t\tfor (size_t i = 0; i < fpkms.size(); ++i)\n\t\t{\n\t\t\tfprintf(fout, \"\\t%s_FPKM\\t%s_conf_lo\\t%s_conf_hi\\t%s_status\", sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str());\n\t\t}\n\t}\n\tfprintf(fout, \"\\n\");\n\tfor (FPKMTrackingTable::const_iterator itr = tracking.begin(); itr != tracking.end(); ++itr)\n\t{\n\t\tconst string& description = itr->first;\n\t\tconst FPKMTracking& track = itr->second;\n\t\tconst vector<FPKMContext>& fpkms = track.fpkm_series;\n\t\t\n        AbundanceStatus status = NUMERIC_OK;\n        BOOST_FOREACH (const FPKMContext& c, fpkms)\n        {\n            if (c.status == NUMERIC_FAIL)\n                status = NUMERIC_FAIL;\n        }\n        \n        string all_gene_ids = cat_strings(track.gene_ids);\n\t\tif (all_gene_ids == \"\")\n\t\t\tall_gene_ids = \"-\";\n        \n\t\tstring all_gene_names = cat_strings(track.gene_names);\n\t\tif (all_gene_names == \"\")\n\t\t\tall_gene_names = \"-\";\n\t\t\n\t\tstring all_tss_ids = cat_strings(track.tss_ids);\n\t\tif (all_tss_ids == \"\")\n\t\t\tall_tss_ids = \"-\";\n\t\t\n        char length_buff[33] = \"-\";\n        if (track.length)\n            sprintf(length_buff, \"%d\", track.length);\n        \n        fprintf(fout, \"%s\\t%c\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\", \n                description.c_str(),\n                track.classcode ? track.classcode : '-',\n                track.ref_match.c_str(),\n                all_gene_ids.c_str(),\n                all_gene_names.c_str(), \n                all_tss_ids.c_str(),\n                track.locus_tag.c_str(),\n                length_buff,\n                \"-\");\n       \t\t\n\t\tfor (size_t i = 0; i < fpkms.size(); ++i)\n\t\t{\n\t\t\tdouble fpkm = fpkms[i].FPKM;\n\t\t\t//double std_dev = sqrt(fpkms[i].FPKM_variance);\n\t\t\tdouble fpkm_conf_hi = fpkms[i].FPKM_conf_hi;\n\t\t\tdouble fpkm_conf_lo = fpkms[i].FPKM_conf_lo;\n            const char* status_str = \"OK\";\n            \n            if (fpkms[i].status == NUMERIC_OK)\n            {\n                status_str = \"OK\";\n            }\n            else if (fpkms[i].status == NUMERIC_FAIL)\n            {\n                status_str = \"FAIL\";\n            }\n            else if (fpkms[i].status == NUMERIC_LOW_DATA)\n            {\n                status_str = \"LOWDATA\";\n            }\n            else if (fpkms[i].status == NUMERIC_HI_DATA)\n            {\n                status_str = \"HIDATA\";\n            }\n            else\n            {\n                assert(false);\n            }\n            \n\t\t\tfprintf(fout, \"\\t%lg\\t%lg\\t%lg\\t%s\", fpkm, fpkm_conf_lo, fpkm_conf_hi, status_str);\n\t\t}\n\t\t\n\t\tfprintf(fout, \"\\n\");\n\t}\n}\n\nvoid print_count_tracking(FILE* fout, \n\t\t\t\t\t\t  const FPKMTrackingTable& tracking)\n{\n\tfprintf(fout,\"tracking_id\");\n\tFPKMTrackingTable::const_iterator first_itr = tracking.begin();\n\tif (first_itr != tracking.end())\n\t{\n\t\tconst FPKMTracking& track = first_itr->second;\n\t\tconst vector<FPKMContext>& fpkms = track.fpkm_series;\n\t\tfor (size_t i = 0; i < fpkms.size(); ++i)\n\t\t{\n\t\t\tfprintf(fout, \"\\t%s_count\\t%s_count_variance\\t%s_count_uncertainty_var\\t%s_count_dispersion_var\\t%s_status\", sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str());\n\t\t}\n\t}\n\tfprintf(fout, \"\\n\");\n\tfor (FPKMTrackingTable::const_iterator itr = tracking.begin(); itr != tracking.end(); ++itr)\n\t{\n\t\tconst string& description = itr->first;\n\t\tconst FPKMTracking& track = itr->second;\n\t\tconst vector<FPKMContext>& fpkms = track.fpkm_series;\n\t\t\n        AbundanceStatus status = NUMERIC_OK;\n        BOOST_FOREACH (const FPKMContext& c, fpkms)\n        {\n            if (c.status == NUMERIC_FAIL)\n                status = NUMERIC_FAIL;\n        }\n        \n        fprintf(fout, \"%s\", \n                description.c_str());\n        \n\t\tfor (size_t i = 0; i < fpkms.size(); ++i)\n\t\t{\n            const char* status_str = \"OK\";\n            \n            if (fpkms[i].status == NUMERIC_OK)\n            {\n                status_str = \"OK\";\n            }\n            else if (fpkms[i].status == NUMERIC_FAIL)\n            {\n                status_str = \"FAIL\";\n            }\n            else if (fpkms[i].status == NUMERIC_LOW_DATA)\n            {\n                status_str = \"LOWDATA\";\n            }\n            else if (fpkms[i].status == NUMERIC_HI_DATA)\n            {\n                status_str = \"HIDATA\";\n            }\n            else\n            {\n                assert(false);\n            }\n            \n            double external_counts = fpkms[i].count_mean;\n            double external_count_var = fpkms[i].count_var;\n            double uncertainty_var = fpkms[i].count_uncertainty_var;\n            double dispersion_var = fpkms[i].count_dispersion_var;\n\t\t\tfprintf(fout, \"\\t%lg\\t%lg\\t%lg\\t%lg\\t%s\", external_counts, external_count_var, uncertainty_var, dispersion_var, status_str);\n\t\t}\n\t\t\n\t\tfprintf(fout, \"\\n\");\n\t}\n}\n\nvoid print_run_info(FILE* fout)\n{\n    fprintf(fout, \"param\\tvalue\\n\");\n    fprintf(fout, \"cmd_line\\t%s\\n\", cmd_str.c_str());\n    fprintf(fout, \"version\\t%s\\n\", PACKAGE_VERSION);\n    fprintf(fout, \"SVN_revision\\t%s\\n\",SVN_REVISION); \n    fprintf(fout, \"boost_version\\t%d\\n\", BOOST_VERSION);\n}\n\n\n#if ENABLE_THREADS\nboost::mutex inspect_lock;\n\nboost::mutex _recorder_lock;\nboost::mutex locus_thread_pool_lock;\nint locus_curr_threads = 0;\nint locus_num_threads = 0;\n\nvoid decr_pool_count()\n{\n\tlocus_thread_pool_lock.lock();\n\tlocus_curr_threads--;\n\tlocus_thread_pool_lock.unlock();\n}\n\n#endif\n\n\n\nvoid inspect_map_worker(ReplicatedBundleFactory& fac,\n                        int& tmp_min_frag_len, \n                        int& tmp_max_frag_len,\n                        IdToLocusMap& id_to_locus_map)\n{\n#if ENABLE_THREADS\n\tboost::this_thread::at_thread_exit(decr_pool_count);\n#endif\n    \n    int min_f = std::numeric_limits<int>::max();\n    int max_f = 0;\n    \n    fac.inspect_replicate_maps(min_f, max_f, id_to_locus_map);\n    \n#if ENABLE_THREADS\n    inspect_lock.lock();\n#endif\n    tmp_min_frag_len = min(min_f, tmp_min_frag_len);\n    tmp_max_frag_len = max(max_f, tmp_max_frag_len);\n#if ENABLE_THREADS\n    inspect_lock.unlock();\n#endif\n}\n\nvoid learn_bias_worker(boost::shared_ptr<BundleFactory> fac)\n{\n#if ENABLE_THREADS\n\tboost::this_thread::at_thread_exit(decr_pool_count);\n#endif\n\tboost::shared_ptr<ReadGroupProperties> rg_props = fac->read_group_properties();\n\tBiasLearner* bl = new BiasLearner(rg_props->frag_len_dist());\n\tlearn_bias(*fac, *bl, false);\n\trg_props->bias_learner(boost::shared_ptr<BiasLearner>(bl));\n}\n\ntypedef map<int, vector<AbundanceGroup> > light_ab_group_tracking_table;\n\n// Similiar to TestLauncher, except this class records tracking data when abundance groups report in\nstruct AbundanceRecorder\n{\nprivate:\n    AbundanceRecorder(AbundanceRecorder& rhs) {}\n    \npublic:\n    AbundanceRecorder(int num_samples,\n                      Tracking* tracking,\n                      ProgressBar* p_bar)\n        :\n        _orig_workers(num_samples),\n        _tracking(tracking),\n        _p_bar(p_bar)\n        {\n        }\n    \n    void operator()();\n    \n    void register_locus(int locus_id);\n    void abundance_avail(int locus_id,\n                         boost::shared_ptr<SampleAbundances> ab,\n                         size_t factory_id);\n    void record_finished_loci();\n    void record_tracking_data(int locus_id, vector<boost::shared_ptr<SampleAbundances> >& abundances);\n    bool all_samples_reported_in(vector<boost::shared_ptr<SampleAbundances> >& abundances);\n    bool all_samples_reported_in(int locus_id);\n    \n    void clear_tracking_data() { _tracking->clear(); }\n    \n    typedef list<pair<int, vector<boost::shared_ptr<SampleAbundances> > > > recorder_sample_table;\n    \n    const light_ab_group_tracking_table& get_sample_table() const { return _ab_group_tracking_table; }\n    \nprivate:\n    \n    recorder_sample_table::iterator find_locus(int locus_id);\n    \n    int _orig_workers;\n    \n    recorder_sample_table _samples;\n    \n    Tracking* _tracking;\n    ProgressBar* _p_bar;\n    \n    light_ab_group_tracking_table _ab_group_tracking_table;\n};\n\n\nAbundanceRecorder::recorder_sample_table::iterator AbundanceRecorder::find_locus(int locus_id)\n{\n    recorder_sample_table::iterator itr = _samples.begin();\n    for(; itr != _samples.end(); ++itr)\n    {\n        if (itr->first == locus_id)\n            return itr;\n    }\n    return _samples.end();\n}\n\nvoid AbundanceRecorder::register_locus(int locus_id)\n{\n#if ENABLE_THREADS\n\tboost::mutex::scoped_lock lock(_recorder_lock);\n#endif\n    \n    recorder_sample_table::iterator itr = find_locus(locus_id);\n    if (itr == _samples.end())\n    {\n        pair<recorder_sample_table::iterator, bool> p;\n        vector<boost::shared_ptr<SampleAbundances> >abs(_orig_workers);\n        _samples.push_back(make_pair(locus_id, abs));\n    }\n}\n\nvoid AbundanceRecorder::abundance_avail(int locus_id,\n                                        boost::shared_ptr<SampleAbundances> ab,\n                                        size_t factory_id)\n{\n#if ENABLE_THREADS\n\tboost::mutex::scoped_lock lock(_recorder_lock);\n#endif\n    recorder_sample_table::iterator itr = find_locus(locus_id);\n    if (itr == _samples.end())\n    {\n        assert(false);\n    }\n    itr->second[factory_id] = ab;\n    //itr->second(factory_id] = ab;\n}\n\n// Note: this routine should be called under lock - it doesn't\n// acquire the lock itself.\nbool AbundanceRecorder::all_samples_reported_in(vector<boost::shared_ptr<SampleAbundances> >& abundances)\n{\n    BOOST_FOREACH (boost::shared_ptr<SampleAbundances> ab, abundances)\n    {\n        if (!ab)\n        {\n            return false;\n        }\n    }\n    return true;\n}\n\n\n// Note: this routine should be called under lock - it doesn't\n// acquire the lock itself.\nvoid AbundanceRecorder::record_tracking_data(int locus_id, vector<boost::shared_ptr<SampleAbundances> >& abundances)\n{\n    assert (abundances.size() == _orig_workers);\n    \n    // Just verify that all the loci from each factory match up.\n    for (size_t i = 1; i < abundances.size(); ++i)\n    {\n        const SampleAbundances& curr = *(abundances[i]);\n        const SampleAbundances& prev = *(abundances[i-1]);\n        \n        assert (curr.locus_tag == prev.locus_tag);\n        \n        const AbundanceGroup& s1 = curr.transcripts;\n        const AbundanceGroup& s2 =  prev.transcripts;\n        \n        assert (s1.abundances().size() == s2.abundances().size());\n        \n        for (size_t j = 0; j < s1.abundances().size(); ++j)\n        {\n            assert (s1.abundances()[j]->description() == s2.abundances()[j]->description());\n        }\n    }\n    \n    vector<AbundanceGroup> lightweight_ab_groups;\n    \n    // Add all the transcripts, CDS groups, TSS groups, and genes to their\n    // respective FPKM tracking table.  Whether this is a time series or an\n    // all pairs comparison, we should be calculating and reporting FPKMs for\n    // all objects in all samples\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tconst AbundanceGroup& ab_group = abundances[i]->transcripts;\n        /*\n        //fprintf(stderr, \"[%d] count = %lg\\n\",i,  ab_group.num_fragments());\n\t\tBOOST_FOREACH (boost::shared_ptr<Abundance> ab, ab_group.abundances())\n\t\t{\n\t\t\tadd_to_tracking_table(i, *ab, _tracking->isoform_fpkm_tracking);\n            //assert (_tracking->isoform_fpkm_tracking.num_fragments_by_replicate().empty() == false);\n\t\t}\n\t\t\n\t\tBOOST_FOREACH (AbundanceGroup& ab, abundances[i]->cds)\n\t\t{\n\t\t\tadd_to_tracking_table(i, ab, _tracking->cds_fpkm_tracking);\n\t\t}\n\t\t\n\t\tBOOST_FOREACH (AbundanceGroup& ab, abundances[i]->primary_transcripts)\n\t\t{\n\t\t\tadd_to_tracking_table(i, ab, _tracking->tss_group_fpkm_tracking);\n\t\t}\n\t\t\n\t\tBOOST_FOREACH (AbundanceGroup& ab, abundances[i]->genes)\n\t\t{\n\t\t\tadd_to_tracking_table(i, ab, _tracking->gene_fpkm_tracking);\n\t\t}\n        */\n        \n        abundances[i]->transcripts.clear_non_serialized_data();\n        lightweight_ab_groups.push_back(abundances[i]->transcripts);\n\t}\n    \n    if (_ab_group_tracking_table.find(locus_id) != _ab_group_tracking_table.end())\n    {\n        fprintf (stderr, \"Error: locus %d is already recorded!\\n\", locus_id);\n    }\n    _ab_group_tracking_table[locus_id] = lightweight_ab_groups;\n}\n\nvoid AbundanceRecorder::record_finished_loci()\n{\n#if ENABLE_THREADS\n\tboost::mutex::scoped_lock lock(_recorder_lock);\n#endif\n    \n    recorder_sample_table::iterator itr = _samples.begin();\n    while(itr != _samples.end())\n    {\n        if (all_samples_reported_in(itr->second))\n        {\n            // In some abundance runs, we don't actually want to perform testing\n            // (eg initial quantification before bias correction).\n            // _tests and _tracking will be NULL in these cases.\n            if (_tracking != NULL)\n            {\n                if (_p_bar)\n                {\n                    verbose_msg(\"Estimating expression in locus [%s]\\n\", itr->second.front()->locus_tag.c_str());\n                    _p_bar->update(itr->second.front()->locus_tag.c_str(), 1);\n                }\n            }\n            record_tracking_data(itr->first, itr->second);\n            \n            // Removes the samples that have already been tested and transferred to the tracking tables,\n            itr = _samples.erase(itr);\n        }\n        else\n        {\n            \n            ++itr;\n        }\n    }\n}\n\n\nboost::shared_ptr<AbundanceRecorder> abundance_recorder;\n\nvoid sample_worker(const RefSequenceTable& rt,\n                   ReplicatedBundleFactory& sample_factory,\n                   boost::shared_ptr<SampleAbundances> abundance,\n                   size_t factory_id,\n                   boost::shared_ptr<AbundanceRecorder> recorder,\n                   bool calculate_variance)\n{\n#if ENABLE_THREADS\n\tboost::this_thread::at_thread_exit(decr_pool_count);\n#endif\n    \n    boost::shared_ptr<HitBundle> bundle(new HitBundle);\n    bool non_empty = sample_factory.next_bundle(*bundle, true);\n    \n    char bundle_label_buf[2048];\n    sprintf(bundle_label_buf,\n            \"%s:%d-%d\",\n            rt.get_name(bundle->ref_id()),\n            bundle->left(),\n            bundle->right());\n    string locus_tag = bundle_label_buf;\n    \n    abundance->cluster_mass = bundle->mass();\n    \n    recorder->register_locus(bundle->id());\n    \n    abundance->locus_tag = locus_tag;\n\n//    if (rt.get_name(bundle->ref_id()) == \"chr13_random\")\n//    {\n//        int a = 5;\n//    }\n    if (!non_empty || (bias_run && bundle->ref_scaffolds().size() != 1)) // Only learn on single isoforms\n    {\n//#if !ENABLE_THREADS\n        // If Cuffdiff was built without threads, we need to manually invoke\n        // the testing functor, which will check to see if all the workers\n        // are done, and if so, perform the cross sample testing.\n        recorder->abundance_avail(bundle->id(), abundance, factory_id);\n        recorder->record_finished_loci();\n        //launcher();\n//#endif\n    \treturn;\n    }\n    \n    bool perform_cds_analysis = false;\n    bool perform_tss_analysis = false;\n    \n    BOOST_FOREACH(boost::shared_ptr<Scaffold> s, bundle->ref_scaffolds())\n    {\n        if (s->annotated_tss_id() != \"\")\n        {\n            perform_tss_analysis = final_est_run;\n        }\n        if (s->annotated_protein_id() != \"\")\n        {\n            perform_cds_analysis = final_est_run;\n        }\n    }\n    \n    set<boost::shared_ptr<ReadGroupProperties const> > rg_props;\n    for (size_t i = 0; i < sample_factory.factories().size(); ++i)\n    {\n        boost::shared_ptr<BundleFactory> bf = sample_factory.factories()[i];\n        rg_props.insert(bf->read_group_properties());\n    }\n    \n    sample_abundance_worker(boost::cref(locus_tag),\n                            boost::cref(rg_props),\n                            boost::ref(*abundance),\n                            bundle,\n                            perform_cds_analysis,\n                            perform_tss_analysis,\n                            calculate_variance);\n    \n    ///////////////////////////////////////////////\n    \n    \n    BOOST_FOREACH(boost::shared_ptr<Scaffold> ref_scaff,  bundle->ref_scaffolds())\n    {\n        ref_scaff->clear_hits();\n    }\n    \n    recorder->abundance_avail(bundle->id(), abundance, factory_id);\n    recorder->record_finished_loci();\n}\n\nbool quantitate_next_locus(const RefSequenceTable& rt,\n                           vector<boost::shared_ptr<ReplicatedBundleFactory> >& bundle_factories,\n                           boost::shared_ptr<AbundanceRecorder> recorder)\n{\n    for (size_t i = 0; i < bundle_factories.size(); ++i)\n    {\n        boost::shared_ptr<SampleAbundances> s_ab = boost::shared_ptr<SampleAbundances>(new SampleAbundances);\n        \n#if ENABLE_THREADS\t\t\t\t\t\n        while(1)\n        {\n            locus_thread_pool_lock.lock();\n            if (locus_curr_threads < locus_num_threads)\n            {\n                break;\n            }\n            \n            locus_thread_pool_lock.unlock();\n            \n            boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n            \n        }\n        \n        locus_curr_threads++;\n        locus_thread_pool_lock.unlock();\n        \n        thread quantitate(sample_worker,\n                          boost::ref(rt),\n                          boost::ref(*(bundle_factories[i])),\n                          s_ab,\n                          i,\n                          recorder,\n                          false);\n#else\n        sample_worker(boost::ref(rt),\n                      boost::ref(*(bundle_factories[i])),\n                      s_ab,\n                      i,\n                      recorder,\n                      false);\n#endif\n    }\n    return true;\n}\n\nvoid parse_norm_standards_file(FILE* norm_standards_file)\n{\n    char pBuf[10 * 1024];\n    size_t non_blank_lines_read = 0;\n    \n    boost::shared_ptr<map<string, LibNormStandards> > norm_standards(new map<string, LibNormStandards>);\n    \n    while (fgets(pBuf, 10*1024, norm_standards_file))\n    {\n        if (strlen(pBuf) > 0)\n        {\n            char* nl = strchr(pBuf, '\\n');\n            if (nl)\n                *nl = 0;\n            \n            string pBufstr = pBuf;\n            string trimmed = boost::trim_copy(pBufstr);\n            \n            if (trimmed.length() > 0 && trimmed[0] != '#')\n            {\n                non_blank_lines_read++;\n                vector<string> columns;\n                tokenize(trimmed, \"\\t\", columns);\n                \n                if (non_blank_lines_read == 1)\n                    continue;\n                \n                if (columns.size() < 1) // \n                {\n                    continue;\n                }\n                \n                string gene_id = columns[0];\n                LibNormStandards L;\n                norm_standards->insert(make_pair(gene_id, L));\n            }\n        }\n    }\n    lib_norm_standards = norm_standards;\n}\n\nboost::shared_ptr<AbundanceRecorder> abx_recorder;\n\nvoid driver(const std::string& ref_gtf_filename, const std::string& mask_gtf_filename, FILE* norm_standards_file, vector<string>& sam_hit_filename_lists, Outfiles& outfiles)\n{\n\n    FILE* ref_gtf = NULL;\n\tif (ref_gtf_filename != \"\")\n\t{\n\t\tref_gtf = fopen(ref_gtf_filename.c_str(), \"r\");\n\t\tif (!ref_gtf) // we actually already did this check, leave this code here in case we remove the upstream one\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open reference GTF file %s for reading\\n\",\n\t\t\t\t\tref_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\t\n\tFILE* mask_gtf = NULL;\n\tif (mask_gtf_filename != \"\")\n\t{\n\t\tmask_gtf = fopen(mask_gtf_filename.c_str(), \"r\");\n\t\tif (!mask_gtf) // we actually already did this check, leave this code here in case we remove the upstream one\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open mask GTF file %s for reading\\n\",\n\t\t\t\t\tmask_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n    \n\tReadTable it;\n\tRefSequenceTable rt(true, false);\n    \n\tvector<boost::shared_ptr<Scaffold> > ref_mRNAs;\n\t\n\tvector<boost::shared_ptr<ReplicatedBundleFactory> > bundle_factories;\n    vector<boost::shared_ptr<ReadGroupProperties> > all_read_groups;\n    vector<boost::shared_ptr<HitFactory> > all_hit_factories;\n    \n\tfor (size_t i = 0; i < sam_hit_filename_lists.size(); ++i)\n\t{\n        vector<string> sam_hit_filenames;\n        tokenize(sam_hit_filename_lists[i], \",\", sam_hit_filenames);\n        \n        vector<boost::shared_ptr<BundleFactory> > replicate_factories;\n        \n        string condition_name = sample_labels[i];\n        \n        for (size_t j = 0; j < sam_hit_filenames.size(); ++j)\n        {\n            boost::shared_ptr<HitFactory> hs(createSamHitFactory(sam_hit_filenames[j], it, rt));\n            \n            all_hit_factories.push_back(hs);\n            \n            boost::shared_ptr<BundleFactory> hf(new BundleFactory(hs, REF_DRIVEN));\n            boost::shared_ptr<ReadGroupProperties> rg_props(new ReadGroupProperties);\n            \n            if (global_read_properties)\n            {\n                *rg_props = *global_read_properties;\n            }\n            else \n            {\n                *rg_props = hs->read_group_properties();\n            }\n            \n            rg_props->condition_name(condition_name);\n            rg_props->replicate_num(j);\n            rg_props->file_path(sam_hit_filenames[j]);\n            \n            all_read_groups.push_back(rg_props);\n            \n            hf->read_group_properties(rg_props);\n            \n            replicate_factories.push_back(hf);\n            //replicate_factories.back()->set_ref_rnas(ref_mRNAs);\n        }\n        \n        bundle_factories.push_back(boost::shared_ptr<ReplicatedBundleFactory>(new ReplicatedBundleFactory(replicate_factories, condition_name)));\n\t}\n    \n    boost::crc_32_type ref_gtf_crc_result;\n    ::load_ref_rnas(ref_gtf, rt, ref_mRNAs, ref_gtf_crc_result, corr_bias, false);\n    \n//    for (size_t i = 0; i < ref_mRNAs.size(); ++i)\n//    {\n//        boost::shared_ptr<Scaffold> s = ref_mRNAs[i];\n//        if (s->annotated_gene_id() == \"ENSG00000268467.1\")\n//        {\n//            int a = 4;\n//        }\n//    }\n//    \n    if (ref_mRNAs.empty())\n        return;\n    \n    boost::crc_32_type mask_gtf_crc_result;\n    vector<boost::shared_ptr<Scaffold> > mask_rnas;\n    if (mask_gtf)\n    {\n        ::load_ref_rnas(mask_gtf, rt, mask_rnas, mask_gtf_crc_result, false, false);\n    }\n    \n    BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> fac, bundle_factories)\n    {\n        fac->set_ref_rnas(ref_mRNAs);\n        if (mask_gtf) \n            fac->set_mask_rnas(mask_rnas);\n    }\n    \n    if (norm_standards_file != NULL)\n    {\n        parse_norm_standards_file(norm_standards_file);\n    }\n    \n    for (size_t i = 0; i < all_read_groups.size(); ++i)\n    {\n        all_read_groups[i]->collect_checked_parameters();\n        all_read_groups[i]->ref_gtf(ref_gtf_filename, ref_gtf_crc_result);\n        all_read_groups[i]->mask_gtf(mask_gtf_filename, mask_gtf_crc_result);\n    }\n    \n#if ENABLE_THREADS\n    locus_num_threads = num_threads;\n#endif\n    \n    dispersion_method = POISSON;\n    \n\tint tmp_min_frag_len = numeric_limits<int>::max();\n\tint tmp_max_frag_len = 0;\n\t\n    IdToLocusMap id_to_locus_map(boost::shared_ptr<map<string, set<string> > >(new map<string, set<string> >()));\n    \n\tProgressBar p_bar(\"Inspecting maps and determining fragment length distributions.\",0);\n\tBOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> fac, bundle_factories)\n    {\n        \n#if ENABLE_THREADS\t\n        while(1)\n        {\n            locus_thread_pool_lock.lock();\n            if (locus_curr_threads < locus_num_threads)\n            {\n                break;\n            }\n            \n            locus_thread_pool_lock.unlock();\n            \n            boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n        }\n        \n        locus_curr_threads++;\n        locus_thread_pool_lock.unlock();\n        \n        thread inspect(inspect_map_worker,\n                       boost::ref(*fac),\n                       boost::ref(tmp_min_frag_len),\n                       boost::ref(tmp_max_frag_len),\n                       boost::ref(id_to_locus_map));\n#else\n        inspect_map_worker(boost::ref(*fac),\n                           boost::ref(tmp_min_frag_len),\n                           boost::ref(tmp_max_frag_len),\n                           boost::ref(id_to_locus_map));\n#endif\n    }\n    \n    // wait for the workers to finish up before reporting everthing.\n#if ENABLE_THREADS\t\n    while(1)\n    {\n        locus_thread_pool_lock.lock();\n        if (locus_curr_threads == 0)\n        {\n            locus_thread_pool_lock.unlock();\n            break;\n        }\n        locus_thread_pool_lock.unlock();\n        \n        boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n    }\n#endif\n    \n    normalize_counts(all_read_groups);\n    \n    for (size_t i = 0; i < all_read_groups.size(); ++i)\n    {\n        boost::shared_ptr<ReadGroupProperties> rg = all_read_groups[i];\n        fprintf(stderr, \"> Map Properties:\\n\");\n        \n        fprintf(stderr, \">\\tNormalized Map Mass: %.2Lf\\n\", rg->normalized_map_mass());\n        fprintf(stderr, \">\\tRaw Map Mass: %.2Lf\\n\", rg->total_map_mass());\n        if (corr_multi)\n            fprintf(stderr,\">\\tNumber of Multi-Reads: %zu (with %zu total hits)\\n\", rg->multi_read_table()->num_multireads(), rg->multi_read_table()->num_multihits()); \n        \n        if (rg->frag_len_dist()->source() == LEARNED)\n        {\n            fprintf(stderr, \">\\tFragment Length Distribution: Empirical (learned)\\n\");\n            fprintf(stderr, \">\\t              Estimated Mean: %.2f\\n\", rg->frag_len_dist()->mean());\n            fprintf(stderr, \">\\t           Estimated Std Dev: %.2f\\n\", rg->frag_len_dist()->std_dev());\n        }\n        else\n        {\n            if (rg->frag_len_dist()->source() == USER)\n                fprintf(stderr, \">\\tFragment Length Distribution: Truncated Gaussian (user-specified)\\n\");\n            else //rg->frag_len_dist()->source == FLD::DEFAULT\n                fprintf(stderr, \">\\tFragment Length Distribution: Truncated Gaussian (default)\\n\");\n            fprintf(stderr, \">\\t              Default Mean: %d\\n\", def_frag_len_mean);\n            fprintf(stderr, \">\\t           Default Std Dev: %d\\n\", def_frag_len_std_dev);\n        }\n    }\n    \n    long double total_norm_mass = 0.0;\n    long double total_mass = 0.0;\n    BOOST_FOREACH (boost::shared_ptr<ReadGroupProperties> rg_props, all_read_groups)\n    {\n        total_norm_mass += rg_props->normalized_map_mass();\n        total_mass += rg_props->total_map_mass();\n    }\n\n\tmin_frag_len = tmp_min_frag_len;\n    max_frag_len = tmp_max_frag_len;\n\t\n\tfinal_est_run = false;\n\t\n\tdouble num_bundles = (double)bundle_factories[0]->num_bundles();\n    \n    p_bar = ProgressBar(\"Calculating preliminary abundance estimates\", num_bundles);\n    \n    Tracking tracking;\n    \n    abundance_recorder = boost::shared_ptr<AbundanceRecorder>(new AbundanceRecorder(bundle_factories.size(), &tracking, &p_bar));\n    \n\tif (model_mle_error || corr_bias || corr_multi) // Only run initial estimation if correcting bias or multi-reads\n\t{\n\t\twhile (1) \n\t\t{\n\t\t\tboost::shared_ptr<vector<boost::shared_ptr<SampleAbundances> > > abundances(new vector<boost::shared_ptr<SampleAbundances> >());\n\t\t\tquantitate_next_locus(rt, bundle_factories, abundance_recorder);\n\t\t\tbool more_loci_remain = false;\n            BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories) \n            {\n                if (rep_fac->bundles_remain())\n                {\n                    more_loci_remain = true;\n                    break;\n                }\n            }\n            \n\t\t\tif (!more_loci_remain)\n            {\n                // wait for the workers to finish up before breaking out.\n#if ENABLE_THREADS\t\n                while(1)\n                {\n                    locus_thread_pool_lock.lock();\n                    if (locus_curr_threads == 0)\n                    {\n                        locus_thread_pool_lock.unlock();\n                        break;\n                    }\n                    \n                    locus_thread_pool_lock.unlock();\n                    \n                    boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n                    \n                }\n#endif\n\t\t\t\tbreak;\n            }\n\t\t}\n        \n        BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories)\n\t\t{\n\t\t\trep_fac->reset();\n        }\n        \n\t\tp_bar.complete();\n\t}\n    if (corr_bias)\n    {\n        bias_run = true;\n        p_bar = ProgressBar(\"Learning bias parameters.\", 0);\n\t\tBOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories)\n\t\t{\n\t\t\tBOOST_FOREACH (boost::shared_ptr<BundleFactory> fac, rep_fac->factories())\n\t\t\t{\n#if ENABLE_THREADS\t\n\t\t\t\twhile(1)\n\t\t\t\t{\n\t\t\t\t\tlocus_thread_pool_lock.lock();\n\t\t\t\t\tif (locus_curr_threads < locus_num_threads)\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tlocus_thread_pool_lock.unlock();\n\t\t\t\t\t\n\t\t\t\t\tboost::this_thread::sleep(boost::posix_time::milliseconds(5));\n\t\t\t\t}\n\t\t\t\tlocus_curr_threads++;\n\t\t\t\tlocus_thread_pool_lock.unlock();\n\t\t\t\t\n\t\t\t\tthread bias(learn_bias_worker, fac);\n#else\n\t\t\t\tlearn_bias_worker(fac);\n#endif\n\t\t\t}\n    \t}\n    \n    // wait for the workers to finish up before reporting everthing.\n#if ENABLE_THREADS\t\n\t\twhile(1)\n\t\t{\n\t\t\tlocus_thread_pool_lock.lock();\n\t\t\tif (locus_curr_threads == 0)\n\t\t\t{\n\t\t\t\tlocus_thread_pool_lock.unlock();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tlocus_thread_pool_lock.unlock();\n\t\t\t\n\t\t\tboost::this_thread::sleep(boost::posix_time::milliseconds(5));\n\t\t}\n#endif\n        BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories)\n\t\t{\n\t\t\trep_fac->reset();\n        }\n        bias_run = false;\n\t}\n    \n    // Allow the multiread tables to do their thing...\n    BOOST_FOREACH (boost::shared_ptr<ReadGroupProperties> rg_props, all_read_groups)\n    {\n        rg_props->multi_read_table()->valid_mass(true);\n    }\n    \n    \n    abundance_recorder->clear_tracking_data();\n    \n    abundance_recorder = boost::shared_ptr<AbundanceRecorder>(new AbundanceRecorder(bundle_factories.size(), &tracking, &p_bar));\n    \n\tfinal_est_run = true;\n\tp_bar = ProgressBar(\"Quantifying expression levels in locus.\", num_bundles);\n                                                     \n\twhile (true)\n\t{\n        //boost::shared_ptr<vector<boost::shared_ptr<SampleAbundances> > > abundances(new vector<boost::shared_ptr<SampleAbundances> >());\n        quantitate_next_locus(rt, bundle_factories, abundance_recorder);\n        bool more_loci_remain = false;\n        BOOST_FOREACH (boost::shared_ptr<ReplicatedBundleFactory> rep_fac, bundle_factories) \n        {\n            if (rep_fac->bundles_remain())\n            {\n                more_loci_remain = true;\n                break;\n            }\n        }\n        if (!more_loci_remain)\n        {\n            // wait for the workers to finish up before doing the cross-sample testing.\n#if ENABLE_THREADS\t\n            while(1)\n            {\n                locus_thread_pool_lock.lock();\n                if (locus_curr_threads == 0)\n                {\n                    locus_thread_pool_lock.unlock();\n                    break;\n                }\n                \n                locus_thread_pool_lock.unlock();\n                \n                boost::this_thread::sleep(boost::posix_time::milliseconds(5));\n                \n            }\n#endif\n            break;\n        }\n    }\n\t\n\tp_bar.complete();\n\n    \n    string expression_cxb_filename = output_dir + \"/abundances.cxb\";\n    std::ofstream ofs(expression_cxb_filename.c_str());\n    boost::archive::binary_oarchive oa(ofs);\n    \n    vector< pair<int, AbundanceGroup> > single_sample_tracking;\n    \n    const light_ab_group_tracking_table& sample_table = abundance_recorder->get_sample_table();\n    for (light_ab_group_tracking_table::const_iterator itr = sample_table.begin(); itr != sample_table.end(); ++itr)\n    {\n        \n        assert (itr->second.size() == 1);\n        single_sample_tracking.push_back(make_pair(itr->first, itr->second[0]));\n    }\n    \n    std::sort(single_sample_tracking.begin(), single_sample_tracking.end(),\n              boost::bind(&std::pair<int, AbundanceGroup>::first, _1) <\n              boost::bind(&std::pair<int, AbundanceGroup>::first, _2));\n    \n    size_t num_loci = single_sample_tracking.size();\n    oa << num_loci;\n    \n    \n    \n    for (int i = 0; i < single_sample_tracking.size(); ++i)\n    {\n        oa << single_sample_tracking[i];\n    }\n    \n//    // FPKM tracking\n//    \n//\tFILE* fiso_fpkm_tracking =  outfiles.isoform_fpkm_tracking_out;\n//\tfprintf(stderr, \"Writing isoform-level FPKM tracking\\n\");\n//\tprint_FPKM_tracking(fiso_fpkm_tracking,tracking.isoform_fpkm_tracking); \n//\t\n//\tFILE* ftss_fpkm_tracking =  outfiles.tss_group_fpkm_tracking_out;\n//\tfprintf(stderr, \"Writing TSS group-level FPKM tracking\\n\");\n//\tprint_FPKM_tracking(ftss_fpkm_tracking,tracking.tss_group_fpkm_tracking);\n//\t\n//\tFILE* fgene_fpkm_tracking =  outfiles.gene_fpkm_tracking_out;\n//\tfprintf(stderr, \"Writing gene-level FPKM tracking\\n\");\n//\tprint_FPKM_tracking(fgene_fpkm_tracking,tracking.gene_fpkm_tracking);\n//\t\n//\tFILE* fcds_fpkm_tracking =  outfiles.cds_fpkm_tracking_out;\n//\tfprintf(stderr, \"Writing CDS-level FPKM tracking\\n\");\n//\tprint_FPKM_tracking(fcds_fpkm_tracking,tracking.cds_fpkm_tracking);\n//\n//    // Count tracking\n//    \n//    FILE* fiso_count_tracking =  outfiles.isoform_count_tracking_out;\n//\tfprintf(stderr, \"Writing isoform-level count tracking\\n\");\n//\tprint_count_tracking(fiso_count_tracking,tracking.isoform_fpkm_tracking); \n//\t\n//\tFILE* ftss_count_tracking =  outfiles.tss_group_count_tracking_out;\n//\tfprintf(stderr, \"Writing TSS group-level count tracking\\n\");\n//\tprint_count_tracking(ftss_count_tracking,tracking.tss_group_fpkm_tracking);\n//\t\n//\tFILE* fgene_count_tracking =  outfiles.gene_count_tracking_out;\n//\tfprintf(stderr, \"Writing gene-level count tracking\\n\");\n//\tprint_count_tracking(fgene_count_tracking,tracking.gene_fpkm_tracking);\n//\t\n//\tFILE* fcds_count_tracking =  outfiles.cds_count_tracking_out;\n//\tfprintf(stderr, \"Writing CDS-level count tracking\\n\");\n//\tprint_count_tracking(fcds_count_tracking,tracking.cds_fpkm_tracking);\n//    \n//    // Run info\n//    FILE* frun_info =  outfiles.run_info_out;\n//\tfprintf(stderr, \"Writing run info\\n\");\n//\tprint_run_info(frun_info);\n}\n\nint main(int argc, char** argv)\n{\n//    boost::serialization::void_cast_register<TranscriptAbundance, Abundance>(\n//                                                                             static_cast<TranscriptAbundance *>(NULL),\n//                                                                             static_cast<Abundance *>(NULL)\n//                                                                             );\n    \n    for (int i = 0; i < argc; ++i)\n    {\n        cmd_str += string(argv[i]) + \" \";\n    }\n    \n    init_library_table();\n    init_dispersion_method_table();\n    init_lib_norm_method_table();\n    \n    min_isoform_fraction = 0;\n    \n\tint parse_ret = parse_options(argc,argv);\n    if (parse_ret)\n        return parse_ret;\n\t\n    if (!use_total_mass && !use_compat_mass)\n    {\n        use_total_mass = false;\n        use_compat_mass = true;   \n    }\n    \n\tif(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n    \n    if (!no_update_check)\n        check_version(PACKAGE_VERSION);\n    \n    string ref_gtf_filename = argv[optind++];\n    vector<string> sam_hit_filenames;\n    \n    if(optind < argc)\n    {\n        string sam_hits_file_name = argv[optind++];\n        sam_hit_filenames.push_back(sam_hits_file_name);\n    }\n    \n    if (sample_labels.size() == 0)\n    {\n        for (size_t i = 1; i < sam_hit_filenames.size() + 1; ++i)\n        {\n            char buf[256];\n            sprintf(buf, \"q%lu\", i);\n            sample_labels.push_back(buf);\n        }\n    }\n    \t\n\twhile (sam_hit_filenames.size() < 1)\n    {\n        fprintf(stderr, \"Error: cuffquant requires exactly 1 SAM/BAM file\\n\");\n        exit(1);\n    }\n\t\n    \n    if (sam_hit_filenames.size() != sample_labels.size())\n    {\n        fprintf(stderr, \"Error: number of labels must match number of conditions\\n\");\n        exit(1);\n    }\n    \n    if (random_seed == -1)\n        random_seed = boost::mt19937::default_seed;\n    \n\t// seed the random number generator - we'll need it for the importance\n\t// sampling during MAP estimation of the gammas\n\tsrand48(random_seed);\n\t\n\tFILE* ref_gtf = NULL;\n\tif (ref_gtf_filename != \"\")\n\t{\n\t\tref_gtf = fopen(ref_gtf_filename.c_str(), \"r\");\n\t\tif (!ref_gtf)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open reference GTF file %s for reading\\n\",\n\t\t\t\t\tref_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\t\n\tFILE* mask_gtf = NULL;\n\tif (mask_gtf_filename != \"\")\n\t{\n\t\tmask_gtf = fopen(mask_gtf_filename.c_str(), \"r\");\n\t\tif (!mask_gtf)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open mask GTF file %s for reading\\n\",\n\t\t\t\t\tmask_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\n    FILE* norm_standards_file = NULL;\n\tif (norm_standards_filename != \"\")\n\t{\n\t\tnorm_standards_file = fopen(norm_standards_filename.c_str(), \"r\");\n\t\tif (!norm_standards_file)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open contrast file %s for reading\\n\",\n\t\t\t\t\tnorm_standards_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n    \n\n\t// Note: we don't want the assembly filters interfering with calculations \n\t// here\n\t\n\tpre_mrna_fraction = 0.0;\n    olap_radius = 0;\n\t\n\tOutfiles outfiles;\n\t\n    if (output_dir != \"\")\n    {\n        int retcode = mkpath(output_dir.c_str(), 0777);\n        if (retcode == -1)\n        {\n            if (errno != EEXIST)\n            {\n                fprintf (stderr, \n                         \"Error: cannot create directory %s\\n\", \n                         output_dir.c_str());\n                exit(1);\n            }\n        }\n    }\n    \n    static const int filename_buf_size = 2048;\n    \n    char out_file_prefix[filename_buf_size];\n    sprintf(out_file_prefix, \"%s/\", output_dir.c_str());\n    \n    driver(ref_gtf_filename, mask_gtf_filename, norm_standards_file, sam_hit_filenames, outfiles);\n    \n\treturn 0;\n}\n"
  },
  {
    "path": "src/differential.cpp",
    "content": "/*\n *  differential.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/15/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <algorithm>\n#include <functional>\n#include <numeric>\n#include <boost/numeric/ublas/vector.hpp>\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/matrix_proxy.hpp>\n#include <boost/math/special_functions/gamma.hpp>\n#include <boost/math/distributions/chi_squared.hpp>\n#include <boost/math/distributions/fisher_f.hpp>\n\n#include \"abundances.h\"\n#include \"differential.h\"\n#include \"clustering.h\"\n#include \"differential.h\"\n#include \"sampling.h\"\n\nusing namespace std;\n\ndouble min_read_count = 10;\n\n#if ENABLE_THREADS\nboost::mutex _launcher_lock;\nboost::mutex locus_thread_pool_lock;\nint locus_curr_threads = 0;\nint locus_num_threads = 0;\n\nvoid decr_pool_count()\n{\n\tlocus_thread_pool_lock.lock();\n\tlocus_curr_threads--;\n\tlocus_thread_pool_lock.unlock();\t\n}\n#endif\n\nSampleDifference::SampleDifference():\n    sample_1(-1),\n    sample_2(-1),\n    value_1(0.0),\n    value_2(0.0),\n    test_stat(0.0),\n    p_value(1.0),\n    corrected_p(1.0),\n    test_status(NOTEST),\n    significant(false) {}\n\n\nTestLauncher::launcher_sample_table::iterator TestLauncher::find_locus(const string& locus_id)\n{\n    launcher_sample_table::iterator itr = _samples.begin();\n    for(; itr != _samples.end(); ++itr)\n    {\n        if (itr->first == locus_id)\n            return itr;\n    }\n    return _samples.end();\n}\n\nvoid TestLauncher::register_locus(const string& locus_id)\n{\n#if ENABLE_THREADS\n\tboost::mutex::scoped_lock lock(_launcher_lock);\n#endif\t\n    \n    launcher_sample_table::iterator itr = find_locus(locus_id);\n    if (itr == _samples.end())\n    {\n        pair<launcher_sample_table::iterator, bool> p;\n        vector<boost::shared_ptr<SampleAbundances> >abs(_orig_workers);\n        _samples.push_back(make_pair(locus_id, abs));\n    }\n}\n\nvoid TestLauncher::abundance_avail(const string& locus_id, \n                                   boost::shared_ptr<SampleAbundances> ab, \n                                   size_t factory_id)\n{\n#if ENABLE_THREADS\n\tboost::mutex::scoped_lock lock(_launcher_lock);\n#endif\t\n    launcher_sample_table::iterator itr = find_locus(locus_id);\n    if (itr == _samples.end())\n    {\n        assert(false);\n    }\n    itr->second[factory_id] = ab;\n    //itr->second(factory_id] = ab;\n}\n\n// Note: this routine should be called under lock - it doesn't\n// acquire the lock itself. \nbool TestLauncher::all_samples_reported_in(vector<boost::shared_ptr<SampleAbundances> >& abundances)\n{    \n    BOOST_FOREACH (boost::shared_ptr<SampleAbundances> ab, abundances)\n    {\n        if (!ab)\n        {\n            return false;\n        }\n    }\n    return true;\n}\n\n#if ENABLE_THREADS\nboost::mutex test_storage_lock; // don't modify the above struct without locking here\n#endif\n\n// Note: this routine should be called under lock - it doesn't\n// acquire the lock itself. \nvoid TestLauncher::perform_testing(vector<boost::shared_ptr<SampleAbundances> > abundances)\n{\n//#if ENABLE_THREADS\n//\t_launcher_lock.lock();\n//#endif\n    assert (abundances.size() == _orig_workers);\n    \n    // Just verify that all the loci from each factory match up.\n    for (size_t i = 1; i < abundances.size(); ++i)\n    {\n        const SampleAbundances& curr = *(abundances[i]);\n        const SampleAbundances& prev = *(abundances[i-1]);\n        \n        assert (curr.locus_tag == prev.locus_tag);\n        \n        const AbundanceGroup& s1 = curr.transcripts;\n        const AbundanceGroup& s2 =  prev.transcripts;\n        \n        assert (s1.abundances().size() == s2.abundances().size());\n        \n        for (size_t j = 0; j < s1.abundances().size(); ++j)\n        {\n            assert (s1.abundances()[j]->description() == s2.abundances()[j]->description());\n        }\n    }\n\n    test_differential(abundances.front()->locus_tag, abundances, _contrasts, *_tests, *_tracking);\n//#if ENABLE_THREADS\n//\t_launcher_lock.unlock();\n//#endif\n}\n\nvoid TestLauncher::record_tracking_data(vector<boost::shared_ptr<SampleAbundances> >& abundances)\n{\n    assert (abundances.size() == _orig_workers);\n    \n    // Just verify that all the loci from each factory match up.\n    for (size_t i = 1; i < abundances.size(); ++i)\n    {\n        const SampleAbundances& curr = *(abundances[i]);\n        const SampleAbundances& prev = *(abundances[i-1]);\n        \n        assert (curr.locus_tag == prev.locus_tag);\n        \n        const AbundanceGroup& s1 = curr.transcripts;\n        const AbundanceGroup& s2 =  prev.transcripts;\n        \n        assert (s1.abundances().size() == s2.abundances().size());\n        \n        for (size_t j = 0; j < s1.abundances().size(); ++j)\n        {\n            assert (s1.abundances()[j]->description() == s2.abundances()[j]->description());\n        }\n    }\n    \n#if ENABLE_THREADS\n\ttest_storage_lock.lock();\n#endif\n    \n    // Add all the transcripts, CDS groups, TSS groups, and genes to their\n    // respective FPKM tracking table.  Whether this is a time series or an\n    // all pairs comparison, we should be calculating and reporting FPKMs for \n    // all objects in all samples\n\tfor (size_t i = 0; i < abundances.size(); ++i)\n\t{\n\t\tconst AbundanceGroup& ab_group = abundances[i]->transcripts;\n        //fprintf(stderr, \"[%d] count = %lg\\n\",i,  ab_group.num_fragments());\n\t\tBOOST_FOREACH (boost::shared_ptr<Abundance> ab, ab_group.abundances())\n\t\t{\n\t\t\tadd_to_tracking_table(i, *ab, _tracking->isoform_fpkm_tracking);\n            //assert (_tracking->isoform_fpkm_tracking.num_fragments_by_replicate().empty() == false);\n\t\t}\n\t\t\n\t\tBOOST_FOREACH (AbundanceGroup& ab, abundances[i]->cds)\n\t\t{\n\t\t\tadd_to_tracking_table(i, ab, _tracking->cds_fpkm_tracking);\n\t\t}\n\t\t\n\t\tBOOST_FOREACH (AbundanceGroup& ab, abundances[i]->primary_transcripts)\n\t\t{\n\t\t\tadd_to_tracking_table(i, ab, _tracking->tss_group_fpkm_tracking);\n\t\t}\n\t\t\n\t\tBOOST_FOREACH (AbundanceGroup& ab, abundances[i]->genes)\n\t\t{\n\t\t\tadd_to_tracking_table(i, ab, _tracking->gene_fpkm_tracking);\n\t\t}\n\t}\n    \n#if ENABLE_THREADS\n    test_storage_lock.unlock();\n#endif\n    \n}\n\nvector<vector<boost::shared_ptr<SampleAbundances> > > TestLauncher::test_finished_loci()\n{\n#if ENABLE_THREADS\n\t_launcher_lock.lock();\n#endif  \n\n    vector<vector<boost::shared_ptr<SampleAbundances> > > samples_for_testing;\n    \n    launcher_sample_table::iterator itr = _samples.begin(); \n    while(itr != _samples.end())\n    {\n        if (all_samples_reported_in(itr->second))\n        {\n            if (_p_bar)\n            {\n                //verbose_msg(\"Estimating expression in locus [%s]\\n\", itr->second.front()->locus_tag.c_str());\n                _p_bar->update(itr->second.front()->locus_tag.c_str(), 1);\n            }\n            record_tracking_data(itr->second);\n            if (!_track_only)\n                samples_for_testing.push_back(itr->second);\n            \n            // Removes the samples that have already been tested and transferred to the tracking tables,\n            itr = _samples.erase(itr);\n        }\n        else\n        {\n            \n            ++itr;\n        }\n    }\n    \n#if ENABLE_THREADS\n\t_launcher_lock.unlock();\n#endif\n    return samples_for_testing;\n//    for (size_t i = 0; i < samples_for_testing.size(); ++i)\n//    {\n//        vector<boost::shared_ptr<SampleAbundances> > samples_i = samples_for_testing[i];\n//        perform_testing(samples_i);\n//    }\n}\n\n//// Sampling-based test:\nSampleDifference test_diffexp(const FPKMContext& curr,\n                              const FPKMContext& prev)\n{\n\tbool performed_test = false;\n    \n    SampleDifference test = SampleDifference();\n    \n    test.p_value = 1.0;\n    test.differential = 0.0;\n    test.test_stat = 0.0;\n    test.test_status = NOTEST;\n    test.value_1 = 0;\n    test.value_2 = 0;\n    test.significant = 0;\n    test.corrected_p = 1.0;\n    \n    double p_value = 1.0;\n        \n    double differential = 0.0;\n    \n    // static const long double min_gamma_params = 1e-20;\n    \n    vector<double> null_log_ratio_samples;\n    \n    static const size_t num_null_ratio_samples = 10000;\n    \n    boost::random::mt19937 rng(random_seed);\n    \n    if ((curr.FPKM != 0 || prev.FPKM != 0) && (prev.fpkm_samples.size() > 0 && curr.fpkm_samples.size() > 0))\n    {\n        boost::random::uniform_int_distribution<> prev_sampler(0, prev.fpkm_samples.size()-1);\n        boost::random::uniform_int_distribution<> curr_sampler(0, curr.fpkm_samples.size()-1);\n    \n        vector<double> prev_rep_samples;\n        vector<double> curr_rep_samples;\n        \n        \n        for (size_t i = 0; i != curr.tracking_info_per_rep.size(); ++i)\n        {\n            if (curr.tracking_info_per_rep[i].status == NUMERIC_LOW_DATA)\n                continue;\n            curr_rep_samples.push_back(curr.tracking_info_per_rep[i].fpkm);\n        }\n        \n        for (size_t i = 0; i != prev.tracking_info_per_rep.size(); ++i)\n        {\n            if (prev.tracking_info_per_rep[i].status == NUMERIC_LOW_DATA)\n                continue;\n            prev_rep_samples.push_back(prev.tracking_info_per_rep[i].fpkm);\n        }\n\n        \n        double curr_fpkm = accumulate(curr_rep_samples.begin(), curr_rep_samples.end(), 0.0);\n        if (curr_rep_samples.size() > 0)\n            curr_fpkm /= curr_rep_samples.size();\n        \n        double prev_fpkm = accumulate(prev_rep_samples.begin(), prev_rep_samples.end(), 0.0);\n        if (prev_rep_samples.size() > 0)\n            prev_fpkm /= prev_rep_samples.size();\n        \n        \n        if (curr_fpkm > 0.0 && prev_fpkm > 0.0)\n            differential = log2(curr_fpkm) - log2(prev_fpkm);\n        else if (curr_fpkm)\n            differential = numeric_limits<double>::infinity();\n        else if (prev_fpkm)\n            differential = -numeric_limits<double>::infinity();\n\n        // set the asymptotic delta method test stat for backward compatibility\n        double curr_log_fpkm_var = (curr.FPKM_variance) / (curr.FPKM * curr.FPKM);\n        double prev_log_fpkm_var = (prev.FPKM_variance) / (prev.FPKM * prev.FPKM);\n        double numerator = log(curr.FPKM / prev.FPKM);\n        double denominator = sqrt(prev_log_fpkm_var + curr_log_fpkm_var);\n        if (denominator > 0.0)\n            test.test_stat = numerator / denominator;\n        else if (numerator > 0)\n            test.test_stat = numeric_limits<double>::infinity();\n        else if (numerator < 0)\n            test.test_stat = -numeric_limits<double>::infinity();\n        else\n            test.test_stat = 0;\n\n        \n        test.test_stat = numerator / denominator;\n        \n        \n        // Draw from prev fpkm_samples to make the first half of the null\n        for (size_t i = 0; i < num_null_ratio_samples; ++i)\n        {\n            double curr_set_sample = 0.0;\n            for (size_t k = 0; k < curr_rep_samples.size(); ++k)\n            {\n                int next_sample_idx = prev_sampler(rng);\n                if (next_sample_idx >= 0 && next_sample_idx < prev.fpkm_samples.size())\n                    curr_set_sample += prev.fpkm_samples[next_sample_idx] / (double)curr_rep_samples.size();\n            }\n            \n            double prev_set_sample = 0.0;\n            for (size_t k = 0; k < prev_rep_samples.size(); ++k)\n            {\n                int next_sample_idx = prev_sampler(rng);\n                if (next_sample_idx >= 0 && next_sample_idx < prev.fpkm_samples.size())\n                    prev_set_sample += prev.fpkm_samples[next_sample_idx] / (double)prev_rep_samples.size();\n            }\n            \n            double null_ratio_sample = 0.0;\n            if (curr_set_sample > 0.0 && prev_set_sample > 0.0)\n                null_ratio_sample = log2(curr_set_sample) - log2(prev_set_sample);\n            else if (curr_set_sample > 0.0)\n                null_ratio_sample = numeric_limits<double>::infinity();\n            else if (prev_set_sample)\n                null_ratio_sample = -numeric_limits<double>::infinity();\n            \n            null_log_ratio_samples.push_back(null_ratio_sample);\n        }\n        \n        // Draw from curr's fpkm_samples to make the other half of the null\n        for (size_t i = 0; i < num_null_ratio_samples; ++i)\n        {\n            double curr_set_sample = 0.0;\n            for (size_t k = 0; k < curr_rep_samples.size(); ++k)\n            {\n                int next_sample_idx = curr_sampler(rng);\n                if (next_sample_idx >= 0 && next_sample_idx < curr.fpkm_samples.size())\n                    curr_set_sample += curr.fpkm_samples[next_sample_idx] / (double)curr_rep_samples.size();\n            }\n            \n            double prev_set_sample = 0.0;\n            for (size_t k = 0; k < prev_rep_samples.size(); ++k)\n            {\n                int next_sample_idx = curr_sampler(rng);\n                if (next_sample_idx >= 0 && next_sample_idx < curr.fpkm_samples.size())\n                    prev_set_sample += curr.fpkm_samples[next_sample_idx] / (double)prev_rep_samples.size();\n            }\n            \n            double null_ratio_sample = 0.0;\n            if (curr_set_sample > 0.0 && prev_set_sample > 0.0)\n                null_ratio_sample = log2(curr_set_sample) - log2(prev_set_sample);\n            else if (curr_set_sample > 0.0)\n                null_ratio_sample = numeric_limits<double>::infinity();\n            else if (prev_set_sample)\n                null_ratio_sample = -numeric_limits<double>::infinity();\n            \n            null_log_ratio_samples.push_back(null_ratio_sample);\n        }\n\n        \n        sort(null_log_ratio_samples.begin(), null_log_ratio_samples.end());\n        \n        double lower_tail_val;\n        double upper_tail_val;\n        if (differential > 0)\n        {\n            upper_tail_val = differential;\n            lower_tail_val = -differential;\n        }\n        else\n        {\n            upper_tail_val = -differential;\n            lower_tail_val = differential;\n        }\n        \n        vector<double>::iterator lower_tail_null_range_iter = upper_bound(null_log_ratio_samples.begin(), null_log_ratio_samples.end(), lower_tail_val);\n        vector<double>::iterator upper_tail_null_range_iter = upper_bound(null_log_ratio_samples.begin(), null_log_ratio_samples.end(), upper_tail_val);\n        size_t num_smaller_lower_tail = lower_tail_null_range_iter - null_log_ratio_samples.begin();\n        size_t num_smaller_upper_tail = upper_tail_null_range_iter - null_log_ratio_samples.begin();\n        \n        size_t num_samples_more_extreme = (null_log_ratio_samples.size() - num_smaller_upper_tail) + num_smaller_lower_tail;\n        \n        p_value = num_samples_more_extreme / (double)null_log_ratio_samples.size();\n        if (p_value == 0)\n            p_value = 1.0 / (double)null_log_ratio_samples.size();\n        if (p_value > 1)\n            p_value = 1.0;\n        \n        \n        \n        performed_test = true;\n\n        //test = SampleDifference(sample1, sample2, prev.FPKM, curr.FPKM, stat, p_value, transcript_group_id);\n        test.p_value = p_value;\n        test.differential = differential;\n        //test.test_stat = stat;\n        test.value_1 = prev.FPKM;\n        test.value_2 = curr.FPKM;\n    }\n    else\n    {\n        test.p_value = 1.0;\n        test.test_stat = 0.0;\n        test.value_1 = prev.FPKM;\n        test.value_2 = curr.FPKM;\n        test.differential = 0;\n        performed_test = false;\n    }\n    \n\ttest.test_status = performed_test ? OK : NOTEST;\n\treturn test;\n}\n\nSampleDiffMetaDataTable meta_data_table;\n#if ENABLE_THREADS\nboost::mutex meta_data_lock;\n#endif\n\nboost::shared_ptr<SampleDifferenceMetaData> get_metadata(const string description)\n{\n#if ENABLE_THREADS\n    boost::mutex::scoped_lock lock(meta_data_lock);\n#endif\n    pair<SampleDiffMetaDataTable::iterator, bool> p;\n    p = meta_data_table.insert(make_pair(description, new SampleDifferenceMetaData()));\n    return p.first->second;\n}\n\n// This performs between-group tests on isoforms or TSS groupings in a single\n// locus, on two different samples.\nSampleDifference get_de_tests(const string& description,\n                 const FPKMContext& prev_abundance,\n\t\t\t\t const FPKMContext& curr_abundance,\n\t\t\t\t //SampleDiffs& de_tests,\n\t\t\t\t bool enough_reads)\n{\n\tint total_iso_de_tests = 0;\n\t\t\t\n\tSampleDifference test;\n    \n    const FPKMContext& r1 = curr_abundance;\n    const FPKMContext& r2 = prev_abundance;\n    \n\tif (curr_abundance.status == NUMERIC_FAIL || \n        prev_abundance.status == NUMERIC_FAIL ||\n        prev_abundance.status == NUMERIC_HI_DATA ||\n        curr_abundance.status == NUMERIC_HI_DATA)\n    {\n        test = test_diffexp(r1, r2);\n        test.test_stat = 0;\n\t\ttest.p_value = 1.0;\n\t\ttest.differential = 0.0;\n        if (curr_abundance.status == NUMERIC_FAIL || \n            prev_abundance.status == NUMERIC_FAIL)\n        {\n            test.test_status = FAIL;\n        }\n        else if (prev_abundance.status == NUMERIC_HI_DATA ||\n                 curr_abundance.status == NUMERIC_HI_DATA)\n        {\n            test.test_status = HIDATA;\n        }\n    }\n    else if (curr_abundance.status == NUMERIC_LOW_DATA || \n             prev_abundance.status == NUMERIC_LOW_DATA)\n    {\n        // perform the test, but mark it as not significant and don't add it to the \n        // pile. This way we don't penalize for multiple testing, but users can still\n        // see the fold change.\n\t\ttest = test_diffexp(r1, r2);\n        test.test_stat = 0;\n        test.p_value = 1.0;\n        //test.differential = 0.0;\n\t\t\n\t\ttest.test_status = LOWDATA;\n    }\n    else // at least one is OK, the other might be LOW_DATA\n\t{\n        test = test_diffexp(r1, r2);\n        if (test.test_status == OK && enough_reads)\n        {\n            total_iso_de_tests++;\n        }\n        else\n        {\n            test.test_status = NOTEST;\n\t\t\ttest.test_stat = 0;\n\t\t\ttest.p_value = 1.0;\n\t\t\t//test.differential = 0.0;\n        }\n//\t\tif (test_diffexp(r1, r2, test))\n//\t\t{\n//\t\t\ttotal_iso_de_tests++;\n//\t\t}\n//\t\telse\n//\t\t{\n//\t\t\ttest.test_stat = 0;\n//\t\t\ttest.p_value = 1.0;\n//\t\t\ttest.differential = 0.0;\n//\t\t}\n//\t\tif (enough_reads)\n//\t\t\ttest.test_status = OK;\n//\t\telse\n//\t\t\ttest.test_status = NOTEST;\n\t\t\n\t}\n\t\n    \n\t//inserted.first->second = test;\n\t\n\t//return make_pair(total_iso_de_tests, inserted.first);\n    return test;\n}\n\nbool test_js(const AbundanceGroup& prev_abundance,\n             const AbundanceGroup& curr_abundance,\n             double& js,\n             double& p_val)\n{\n    vector<Eigen::VectorXd> sample_kappas;\n//    Eigen::VectorXd curr_kappas(Eigen::VectorXd::Zero(curr_abundance.abundances().size()));\n//    for (size_t i = 0; i < curr_abundance.abundances().size(); ++i)\n//    {\n//        curr_kappas(i) = curr_abundance.abundances()[i]->kappa();\n//    }\n//    \n//    Eigen::VectorXd prev_kappas(Eigen::VectorXd::Zero(prev_abundance.abundances().size()));\n//    for (size_t i = 0; i < prev_abundance.abundances().size(); ++i)\n//    {\n//        prev_kappas(i) = prev_abundance.abundances()[i]->kappa();\n//    }\n    \n    \n    ////////////\n    \n    Eigen::VectorXd prev_kappas = Eigen::VectorXd::Zero(prev_abundance.abundances().size());\n    for (size_t i = 0; i < prev_abundance.abundances().size(); ++i)\n    {\n        FPKMPerReplicateTable ab_i_by_rep = prev_abundance.abundances()[i]->FPKM_by_replicate();\n        for (FPKMPerReplicateTable::const_iterator itr = ab_i_by_rep.begin(); itr != ab_i_by_rep.end(); ++itr)\n        {\n            prev_kappas(i) += itr->second;\n        }\n        prev_kappas(i) /= ab_i_by_rep.size();\n    }\n    \n    if (prev_kappas.sum() > 0)\n        prev_kappas /= prev_kappas.sum();\n\n    Eigen::VectorXd curr_kappas = Eigen::VectorXd::Zero(curr_abundance.abundances().size());\n    for (size_t i = 0; i < curr_abundance.abundances().size(); ++i)\n    {\n        FPKMPerReplicateTable ab_i_by_rep = curr_abundance.abundances()[i]->FPKM_by_replicate();\n        for (FPKMPerReplicateTable::const_iterator itr = ab_i_by_rep.begin(); itr != ab_i_by_rep.end(); ++itr)\n        {\n            curr_kappas(i) += itr->second;\n        }\n        curr_kappas(i) /= ab_i_by_rep.size();\n    }\n    \n    if (curr_kappas.sum() > 0)\n        curr_kappas /= curr_kappas.sum();\n    \n    ////////////\n    \n    sample_kappas.push_back(prev_kappas);\n    sample_kappas.push_back(curr_kappas);\n    \n    js = jensen_shannon_distance(sample_kappas);\n    \n    if (isinf(js) || isnan(js))\n        return false;\n    \n    vector<double> null_js_samples;\n    \n    static const size_t num_null_js_samples = 10000;\n    \n    boost::random::mt19937 rng(random_seed);\n    boost::random::uniform_int_distribution<> prev_sampler(0, prev_abundance.member_fpkm_samples().size()-1);\n    boost::random::uniform_int_distribution<> curr_sampler(0, curr_abundance.member_fpkm_samples().size()-1);\n    \n    for (size_t i = 0; i < num_null_js_samples; ++i)\n    {\n        // Draw k values, from prev's fpkm_samples to make the first half of the null, where k is the number of replicates in *curr*, and compute their average\n        Eigen::VectorXd curr_set_sample = Eigen::VectorXd::Zero(curr_abundance.abundances().size());\n        for (size_t k = 0; k < curr_abundance.rg_props().size(); ++k)\n        {\n            int next_sample_idx = prev_sampler(rng);\n            if (next_sample_idx >= 0 && next_sample_idx < prev_abundance.member_fpkm_samples().size())\n                curr_set_sample += prev_abundance.member_fpkm_samples()[next_sample_idx] / (double)curr_abundance.rg_props().size();\n        }\n        double total_curr_set_sample_fpkm = curr_set_sample.sum();\n        if (total_curr_set_sample_fpkm > 0.0)\n            curr_set_sample /= total_curr_set_sample_fpkm;\n        \n        // Draw k values, from prev's fpkm_samples to make the first half of the null, where k is the number of replicates in *prev*, and compute their average\n        Eigen::VectorXd prev_set_sample = Eigen::VectorXd::Zero(prev_abundance.abundances().size());\n        for (size_t k = 0; k < prev_abundance.rg_props().size(); ++k)\n        {\n            int next_sample_idx = prev_sampler(rng);\n            if (next_sample_idx >= 0 && next_sample_idx < prev_abundance.member_fpkm_samples().size())\n                prev_set_sample += prev_abundance.member_fpkm_samples()[next_sample_idx] / (double)prev_abundance.rg_props().size();\n        }\n        double total_prev_set_sample_fpkm = prev_set_sample.sum();\n        if (total_prev_set_sample_fpkm > 0.0)\n            prev_set_sample /= total_prev_set_sample_fpkm;\n        \n        vector<Eigen::VectorXd> sample_kappas;\n        \n        sample_kappas.push_back(curr_set_sample);\n        sample_kappas.push_back(prev_set_sample);\n        \n        double js_sample = jensen_shannon_distance(sample_kappas);\n        \n        //cerr << curr_set_sample.transpose() << \" vs. \" << prev_set_sample.transpose() << \" : \" << js_sample << endl;\n        \n        null_js_samples.push_back(js_sample);\n    }\n    \n    for (size_t i = 0; i < num_null_js_samples; ++i)\n    {\n        // Draw k values, from curr's fpkm_samples to make the first half of the null, where k is the number of replicates in *curr*, and compute their average\n        Eigen::VectorXd curr_set_sample = Eigen::VectorXd::Zero(curr_abundance.abundances().size());\n        for (size_t k = 0; k < curr_abundance.rg_props().size(); ++k)\n        {\n            int next_sample_idx = curr_sampler(rng);\n            if (next_sample_idx >= 0 && next_sample_idx < curr_abundance.member_fpkm_samples().size())\n                curr_set_sample += curr_abundance.member_fpkm_samples()[next_sample_idx] / (double)curr_abundance.rg_props().size();\n        }\n        double total_curr_set_sample_fpkm = curr_set_sample.sum();\n        if (total_curr_set_sample_fpkm > 0.0)\n            curr_set_sample /= total_curr_set_sample_fpkm;\n        \n        // Draw k values, from curr's fpkm_samples to make the first half of the null, where k is the number of replicates in *prev*, and compute their average\n        Eigen::VectorXd prev_set_sample = Eigen::VectorXd::Zero(curr_abundance.abundances().size());\n        for (size_t k = 0; k < prev_abundance.rg_props().size(); ++k)\n        {\n            int next_sample_idx = curr_sampler(rng);\n            if (next_sample_idx >= 0 && next_sample_idx < curr_abundance.member_fpkm_samples().size())\n                prev_set_sample += curr_abundance.member_fpkm_samples()[next_sample_idx] / (double)prev_abundance.rg_props().size();\n        }\n        double total_prev_set_sample_fpkm = prev_set_sample.sum();\n        if (total_prev_set_sample_fpkm > 0.0)\n            prev_set_sample /= total_prev_set_sample_fpkm;\n        \n        vector<Eigen::VectorXd> sample_kappas;\n        \n        sample_kappas.push_back(curr_set_sample);\n        sample_kappas.push_back(prev_set_sample);\n        \n        double js_sample = jensen_shannon_distance(sample_kappas);\n        \n        null_js_samples.push_back(js_sample);\n    }    \n    \n    sort(null_js_samples.begin(), null_js_samples.end());\n    \n    double upper_tail_val = js;\n    \n    vector<double>::iterator upper_tail_null_range_iter = upper_bound(null_js_samples.begin(), null_js_samples.end(), upper_tail_val);\n    \n    size_t num_smaller_upper_tail = upper_tail_null_range_iter - null_js_samples.begin();\n    \n    size_t num_samples_more_extreme = (null_js_samples.size() - num_smaller_upper_tail);\n    \n    p_val = num_samples_more_extreme / (double)null_js_samples.size();\n    if (p_val == 0)\n        p_val = 1.0 / (double)null_js_samples.size();\n    if (p_val > 1)\n        p_val = 1.0;\n    \n    return true;\n}\n\n\n// This performs within-group tests on a set of isoforms or a set of TSS groups.\n// This is a way of looking for meaningful differential splicing or differential\n// promoter use.\nSampleDifference get_ds_tests(const AbundanceGroup& prev_abundance,\n                              const AbundanceGroup& curr_abundance,\n//                              SampleDiffs& diff_tests,\n                              bool enough_reads)\n{\n\tSampleDifference test;\n    \n\ttest.p_value = 1.0;\n    test.differential = 0.0;\n    test.test_stat = 0.0;\n    test.test_status = NOTEST;\n    test.value_1 = 0;\n    test.value_2 = 0;\n    test.significant = 0;\n    test.corrected_p = 1.0;\n\n\t\n\tAbundanceStatus prev_status = curr_abundance.status();\n\tAbundanceStatus curr_status = prev_abundance.status();\n    \n    if (prev_abundance.abundances().size() == 1 ||\n        prev_abundance.num_fragments() == 0 ||\n        curr_abundance.num_fragments() == 0 ||\n        prev_abundance.member_fpkm_samples().size() == 0 ||\n        curr_abundance.member_fpkm_samples().size() == 0)\n    {\n        test.p_value = 1;\n        test.value_1 = 0;\n        test.value_2 = 0;\n        test.differential = 0;\n        test.test_status = NOTEST;\n    }\n\telse if (prev_abundance.abundances().size() > 1 &&\n        /*prev_abundance.has_member_with_status(NUMERIC_LOW_DATA) == false &&\n        filtered_curr.has_member_with_status(NUMERIC_LOW_DATA) == false &&*/ \n        prev_status == NUMERIC_OK && prev_abundance.num_fragments() > 0 &&\n\t\tcurr_status == NUMERIC_OK && curr_abundance.num_fragments() > 0)\n\t{\n\t\tvector<ublas::vector<double> > sample_kappas;\n\t\tublas::vector<double> curr_kappas(curr_abundance.abundances().size());\n        \n        for (size_t i = 0; i < curr_abundance.abundances().size(); ++i)\n\t\t{\n\t\t\tcurr_kappas(i) = curr_abundance.abundances()[i]->kappa();\n\t\t}\n\t\t\n\t\tublas::vector<double> prev_kappas(prev_abundance.abundances().size());\n        for (size_t i = 0; i < prev_abundance.abundances().size(); ++i)\n\t\t{\n\t\t\tprev_kappas(i) = prev_abundance.abundances()[i]->kappa();\n\t\t}\n\t\t\n\t\tsample_kappas.push_back(prev_kappas);\n\t\tsample_kappas.push_back(curr_kappas);\n\t\t\n        double js = 0.0;\n        double p_val = 1.0;\n        \n        bool success;\n        success = test_js(prev_abundance, curr_abundance, js, p_val);\n        \n\t\tif (js == 0.0 || success == false)\n\t\t{\n\t\t\ttest.test_stat = 0;\n\t\t\ttest.p_value = 1.0;\n\t\t\ttest.value_1 = 0;\n\t\t\ttest.value_2 = 0;\n\t\t\ttest.differential = 0;\n\t\t\ttest.test_status = NOTEST;\n\t\t}\n\t\telse\n\t\t{\n            //test.test_stat = 0;\n\t\t\ttest.p_value = p_val;\n\t\t\ttest.value_1 = 0;\n\t\t\ttest.value_2 = 0;\n\t\t\ttest.differential = js;\n\t\t\ttest.test_status = enough_reads ? OK : NOTEST;\n        }\n\t}\n\telse // we won't even bother with the JS-based testing in LOWDATA cases.\n\t{\n        if (prev_status == NUMERIC_OK && curr_status == NUMERIC_OK && \n            prev_abundance.has_member_with_status(NUMERIC_LOW_DATA) == false &&\n            curr_abundance.has_member_with_status(NUMERIC_LOW_DATA) == false)\n            test.test_status = NOTEST;\n        else if (prev_status == NUMERIC_FAIL || curr_status == NUMERIC_FAIL)\n            test.test_status = FAIL;\n        else\n            test.test_status = LOWDATA;\n            \n\t\ttest.test_stat = 0;\n\t\ttest.p_value = 0.0;\n\t\ttest.differential = 0.0;\n\t}\n    \n    return test;\n}\n\nstring make_ref_tag(const string& ref, char classcode)\n{\n\tchar tag_buf[1024];\n\n\tsprintf(tag_buf, \n\t\t\t\"%s(%c)\",\n\t\t\tref.c_str(),\n\t\t\tclasscode);\n\t\n\treturn string(tag_buf);\n}\n\nstring bundle_locus_tag(const RefSequenceTable& rt, \n\t\t\t\t\t\tconst HitBundle& bundle)\n{\n\tchar locus_buf[1024];\n\tRefID bundle_chr_id = bundle.ref_id();\n\tassert (bundle_chr_id != 0);\n\tconst char* chr_name = rt.get_name(bundle_chr_id);\n\t\n\tsprintf(locus_buf, \n\t\t\t\"%s:%d-%d\",\n\t\t\tchr_name,\n\t\t\tbundle.left(),\n\t\t\tbundle.right());\n\t\n\treturn string(locus_buf);\n}\n\nstruct LocusVarianceInfo\n{\n    int factory_id;\n    double count_mean;\n    double count_empir_var;\n    double locus_count_fitted_var;\n    double isoform_fitted_var_sum;\n    double cross_replicate_js;\n    int num_transcripts;\n    double bayes_gamma_trace;\n    double empir_gamma_trace;\n    vector<double> gamma;\n    vector<double> gamma_var;\n    vector<double> gamma_bootstrap_var;\n    vector<string> transcript_ids;\n    vector<double> count_sharing;\n    double locus_salient_frags;\n    double locus_total_frags;\n\n};\n\n#if ENABLE_THREADS\nboost::mutex variance_info_lock; // don't modify the above struct without locking here\n#endif\n\nvector<LocusVarianceInfo> locus_variance_info_table;\n\n// We'll use this tracking table to collect per replicate counts for each \n// transcript, so we can re-fit the variance model.\nFPKMTrackingTable transcript_count_tracking; \n\n\nvoid sample_worker(bool non_empty,\n                        boost::shared_ptr<HitBundle> bundle,\n                        const RefSequenceTable& rt,\n                        ReplicatedBundleFactory& sample_factory,\n                        boost::shared_ptr<SampleAbundances> abundance,\n                        size_t factory_id,\n                        boost::shared_ptr<TestLauncher> launcher,\n                        bool calculate_variance)\n{\n#if ENABLE_THREADS\n\tboost::this_thread::at_thread_exit(decr_pool_count);\n#endif\n    \n    char bundle_label_buf[2048];\n    sprintf(bundle_label_buf,\n            \"%s:%d-%d\",\n            rt.get_name(bundle->ref_id()),\n            bundle->left(),\n            bundle->right());\n    string locus_tag = bundle_label_buf;\n    \n    if (!non_empty || (bias_run && bundle->ref_scaffolds().size() != 1)) // Only learn on single isoforms\n    {\n#if !ENABLE_THREADS\n        // If Cuffdiff was built without threads, we need to manually invoke\n        // the testing functor, which will check to see if all the workers\n        // are done, and if so, perform the cross sample testing.\n        launcher->abundance_avail(locus_tag, abundance, factory_id);\n        vector<vector<boost::shared_ptr<SampleAbundances> > > to_be_tested = launcher->test_finished_loci();\n        launcher->perform_testing(to_be_tested);\n        //launcher();\n#endif\n    \treturn;\n    }\n    \n    abundance->cluster_mass = bundle->mass();\n    \n    launcher->register_locus(locus_tag);\n    \n    abundance->locus_tag = locus_tag;\n    \n    bool perform_cds_analysis = false;\n    bool perform_tss_analysis = false;\n    \n    BOOST_FOREACH(boost::shared_ptr<Scaffold> s, bundle->ref_scaffolds())\n    {\n        if (s->annotated_tss_id() != \"\")\n        {\n            perform_tss_analysis = final_est_run;\n        }\n        if (s->annotated_protein_id() != \"\")\n        {\n            perform_cds_analysis = final_est_run;\n        }\n    }\n    \n    std::vector<boost::shared_ptr<BundleFactory> > factories = sample_factory.factories();\n    vector<boost::shared_ptr<PrecomputedExpressionBundleFactory> > hit_factories;\n    for (size_t i = 0; i < factories.size(); ++i)\n    {\n        boost::shared_ptr<BundleFactory> pFac = factories[i];\n        boost::shared_ptr<PrecomputedExpressionBundleFactory> pBundleFac = boost::dynamic_pointer_cast<PrecomputedExpressionBundleFactory> (pFac);\n        if (pBundleFac)\n        {\n            // If we get here, this factory refers to a pre computed expression object.\n            \n            hit_factories.push_back(pBundleFac);\n        }\n    }\n    \n    if (hit_factories.size() == factories.size())\n    {\n        merge_precomputed_expression_worker(boost::cref(locus_tag),\n                                            hit_factories,\n                                            boost::ref(*abundance),\n                                            bundle,\n                                            perform_cds_analysis,\n                                            perform_tss_analysis,\n                                            calculate_variance);\n    }\n    else if (hit_factories.empty())\n    {\n        set<boost::shared_ptr<ReadGroupProperties const> > rg_props;\n        for (size_t i = 0; i < sample_factory.factories().size(); ++i)\n        {\n            boost::shared_ptr<BundleFactory> bf = sample_factory.factories()[i];\n            rg_props.insert(bf->read_group_properties());\n        }\n        \n        sample_abundance_worker(boost::cref(locus_tag),\n                                boost::cref(rg_props),\n                                boost::ref(*abundance),\n                                bundle,\n                                perform_cds_analysis,\n                                perform_tss_analysis,\n                                calculate_variance);\n    }\n    else\n    {\n        fprintf (stderr, \"Error: mixing pre-computed input with SAM/BAM files not yet supported!\\n\");\n        exit(1);\n    }\n    ///////////////////////////////////////////////\n    \n    \n    BOOST_FOREACH(boost::shared_ptr<Scaffold> ref_scaff,  bundle->ref_scaffolds())\n    {\n        ref_scaff->clear_hits();\n    }\n    \n    launcher->abundance_avail(locus_tag, abundance, factory_id);\n    vector<vector<boost::shared_ptr<SampleAbundances> > > to_be_tested = launcher->test_finished_loci();\n    \n    for (size_t i = 0; i < to_be_tested.size(); ++i)\n        launcher->perform_testing(to_be_tested[i]);\n\n#if !ENABLE_THREADS\n    // If Cuffdiff was built without threads, we need to manually invoke\n    // the testing functor, which will check to see if all the workers\n    // are done, and if so, perform the cross sample testing.\n    //launcher->test_finished_loci();\n#endif\n\n}\n\nvoid dump_locus_variance_info(const string& filename)\n{\n#if ENABLE_THREADS\n    variance_info_lock.lock();\n#endif\n    \n    FILE* fdump = fopen(filename.c_str(), \"w\");\n    \n    fprintf(fdump, \n            \"condition\\tdescription\\tlocus_counts\\tempir_var\\tlocus_fit_var\\tsum_iso_fit_var\\tcross_replicate_js\\tnum_transcripts\\tbayes_gamma_trace\\tempir_gamma_trace\\tcount_mean\\tgamma_var\\tlocus_salient_frags\\tlocus_total_frags\\tcount_sharing\\n\");\n    BOOST_FOREACH (LocusVarianceInfo& L, locus_variance_info_table)\n    {\n        for (size_t i = 0; i < L.gamma.size(); ++i)\n        {\n            fprintf(fdump, \"%d\\t%s\\t%lg\\t%lg\\t%lg\\t%lg\\t%lg\\t%d\\t%lg\\t%lg\\t%lg\\t%lg\\t%lg\\t%lg\\t%lg\\n\", L.factory_id, L.transcript_ids[i].c_str(), L.count_mean, L.count_empir_var, L.locus_count_fitted_var, L.isoform_fitted_var_sum, L.cross_replicate_js, L.num_transcripts, L.bayes_gamma_trace, L.empir_gamma_trace,L.gamma[i],L.gamma_var[i], L.locus_salient_frags, L.locus_total_frags, L.count_sharing[i]);\n        }\n        \n    }\n    \n#if ENABLE_THREADS\n    variance_info_lock.unlock();\n#endif\n}\n\nvoid filter_group_for_js_testing(vector<vector<AbundanceGroup> >& source_groups)\n{\n    if (source_groups.empty())\n        return;\n    \n    // iterate over transcript groups\n    for (size_t ab_group_idx = 0; ab_group_idx < source_groups[0].size(); ++ab_group_idx)\n    {\n        vector<bool> to_keep(source_groups[0][ab_group_idx].abundances().size(), false);\n        // iterate over samples\n        for (size_t sample_idx = 0;  sample_idx < source_groups.size(); ++sample_idx)\n        {\n            // iterate over each member of the current abundance group\n            AbundanceGroup& ab_group = source_groups[sample_idx][ab_group_idx];\n            for (size_t ab_idx = 0; ab_idx < ab_group.abundances().size(); ++ab_idx)\n            {\n                const Abundance& ab = *(ab_group.abundances()[ab_idx]);\n                if (ab.num_fragments() && ab.effective_length())\n                {\n                    double frags_per_kb = ab.num_fragments() / (ab.effective_length() / 1000.0);\n                    if (frags_per_kb >= min_read_count)\n                        to_keep[ab_idx] = true;\n                }\n                \n            }\n        }\n        \n        // Now that we know which ones we want to keep, get rid of the rest\n        for (size_t sample_idx = 0;  sample_idx < source_groups.size(); ++sample_idx)\n        {\n            AbundanceGroup& ab_group = source_groups[sample_idx][ab_group_idx];\n            AbundanceGroup f = ab_group;\n            ab_group.filter_group(to_keep, f);\n            ab_group = f;\n        }\n    }\n}\n\n// The two functions below just clear the FPKM samples and other data used to estimate\n// the FPKM distributions during testing.  Once testing for a locus is complete,\n// we can throw that stuff out.  We do so to save memory over the run.\nvoid clear_samples_from_fpkm_tracking_table(const string& locus_desc, FPKMTrackingTable& fpkm_tracking)\n{\n    FPKMTrackingTable::iterator itr = fpkm_tracking.find(locus_desc);\n    if (itr == fpkm_tracking.end())\n        return;\n    \n    for (size_t i = 0; i < itr->second.fpkm_series.size(); ++i)\n    {\n        vector<double>& fpkm_samples = itr->second.fpkm_series[i].fpkm_samples;\n        fpkm_samples.clear();\n        std::vector<double>().swap(fpkm_samples);\n        //itr->second.fpkm_series[i].fpkm_samples.swap(vector<double>(itr->second.fpkm_series[i].fpkm_samples));\n    }\n}\n\nvoid clear_samples_from_tracking_table(boost::shared_ptr<SampleAbundances> sample, Tracking& tracking)\n{\n    for (size_t k = 0; k < sample->transcripts.abundances().size(); ++k)\n    {\n        const Abundance& abundance = *(sample->transcripts.abundances()[k]);\n        const string& desc = abundance.description();\n        clear_samples_from_fpkm_tracking_table(desc, tracking.isoform_fpkm_tracking);\n    }\n\n    for (size_t k = 0; k < sample->cds.size(); ++k)\n    {\n        const Abundance& abundance = sample->cds[k];\n        const string& desc = abundance.description();\n        clear_samples_from_fpkm_tracking_table(desc, tracking.cds_fpkm_tracking);\n    }\n    \n    for (size_t k = 0; k < sample->primary_transcripts.size(); ++k)\n    {\n        const Abundance& abundance = sample->primary_transcripts[k];\n        const string& desc = abundance.description();\n        clear_samples_from_fpkm_tracking_table(desc, tracking.tss_group_fpkm_tracking);\n    }\n\n    for (size_t k = 0; k < sample->genes.size(); ++k)\n    {\n        const Abundance& abundance = sample->genes[k];\n        const string& desc = abundance.description();\n        clear_samples_from_fpkm_tracking_table(desc, tracking.gene_fpkm_tracking);\n    }\n}\n\nint total_tests = 0;\nvoid test_differential(const string& locus_tag,\n                       const vector<boost::shared_ptr<SampleAbundances> >& samples,\n                       const vector<pair<size_t, size_t> >& contrasts,\n\t\t\t\t\t   Tests& tests,\n\t\t\t\t\t   Tracking& tracking)\n{\n\tif (samples.empty())\n\t\treturn;\n    \n    if (no_differential == true)\n    {\n//#if ENABLE_THREADS\n//        test_storage_lock.unlock();\n//#endif\n        for (size_t i = 0; i < samples.size(); ++i)\n        {\n            clear_samples_from_tracking_table(samples[i], tracking);\n        }\n        return;\n    }\n\t\n    vector<vector<AbundanceGroup> > filtered_primary_trans_groups;\n    vector<vector<AbundanceGroup> > filtered_promoter_groups;\n    vector<vector<AbundanceGroup> > filtered_cds_groups;\n\n    for (size_t i = 0; i < samples.size(); ++i)\n    {\n        filtered_primary_trans_groups.push_back(samples[i]->primary_transcripts);\n        filtered_promoter_groups.push_back(samples[i]->gene_primary_transcripts);\n        filtered_cds_groups.push_back(samples[i]->gene_cds);\n    }\n    \n    filter_group_for_js_testing(filtered_primary_trans_groups);\n    filter_group_for_js_testing(filtered_promoter_groups);\n    filter_group_for_js_testing(filtered_cds_groups);\n    \n    \n    // Perform pairwise significance testing between samples. If this is a\n    // time series, only test between successive pairs of samples, as supplied \n    // by the user.\n    \n    for (size_t contrast_idx = 0; contrast_idx < contrasts.size(); ++contrast_idx)\n    {\n        size_t i = contrasts[contrast_idx].first;\n        size_t j = contrasts[contrast_idx].second;\n        //            bool enough_reads = (samples[i]->cluster_mass >= min_read_count ||\n        //                                 samples[j]->cluster_mass >= min_read_count);\n        assert (samples[i]->transcripts.abundances().size() ==\n                samples[j]->transcripts.abundances().size());\n        for (size_t k = 0; k < samples[i]->transcripts.abundances().size(); ++k)\n        {\n            const Abundance& curr_abundance = *(samples[j]->transcripts.abundances()[k]);\n            const Abundance& prev_abundance = *(samples[i]->transcripts.abundances()[k]);\n            const string& desc = curr_abundance.description();\n            FPKMTrackingTable::iterator itr = tracking.isoform_fpkm_tracking.find(desc);\n            assert (itr != tracking.isoform_fpkm_tracking.end());\n            \n            bool enough_reads = false;\n            if (curr_abundance.num_fragments() && curr_abundance.effective_length())\n            {\n                double frags_per_kb = curr_abundance.num_fragments() / (curr_abundance.effective_length() / 1000.0);\n                if (frags_per_kb >= min_read_count)\n                    enough_reads = true;\n            }\n            if (prev_abundance.num_fragments() && prev_abundance.effective_length())\n            {\n                double frags_per_kb = prev_abundance.num_fragments() / (prev_abundance.effective_length() / 1000.0);\n                if (frags_per_kb >= min_read_count)\n                    enough_reads = true;\n            }\n            \n//            if (enough_reads)\n//            {\n//                if (is_badly_fit(curr_abundance) || is_badly_fit(prev_abundance))\n//                    enough_reads = false;\n//            }\n            \n            SampleDifference test;\n            test = get_de_tests(desc,\n                                itr->second.fpkm_series[j],\n                                itr->second.fpkm_series[i],\n                                //tests.isoform_de_tests[i][j],\n                                enough_reads);\n#if ENABLE_THREADS\n            test_storage_lock.lock();\n#endif\n            pair<SampleDiffs::iterator, bool> inserted;\n            inserted = tests.isoform_de_tests[i][j].insert(make_pair(desc,\n                                                                     test));\n            \n            boost::shared_ptr<SampleDifferenceMetaData> meta_data = get_metadata(desc);\n            \n            meta_data->gene_ids = curr_abundance.gene_id();\n            meta_data->gene_names = curr_abundance.gene_name();\n            meta_data->protein_ids = curr_abundance.protein_id();\n            meta_data->locus_desc = curr_abundance.locus_tag();\n            meta_data->description = curr_abundance.description();\n            inserted.first->second.meta_data = meta_data;\n#if ENABLE_THREADS\n            test_storage_lock.unlock();\n#endif\n        }\n        \n        for (size_t k = 0; k < samples[i]->cds.size(); ++k)\n        {\n            const Abundance& curr_abundance = samples[i]->cds[k];\n            const Abundance& prev_abundance = samples[j]->cds[k];\n            \n            const string& desc = curr_abundance.description();\n            FPKMTrackingTable::iterator itr = tracking.cds_fpkm_tracking.find(desc);\n            assert (itr != tracking.cds_fpkm_tracking.end());\n            \n            bool enough_reads = false;\n            if (curr_abundance.num_fragments() && curr_abundance.effective_length())\n            {\n                double frags_per_kb = curr_abundance.num_fragments() / (curr_abundance.effective_length() / 1000.0);\n                if (frags_per_kb >= min_read_count)\n                    enough_reads = true;\n            }\n            if (prev_abundance.num_fragments() && prev_abundance.effective_length())\n            {\n                double frags_per_kb = prev_abundance.num_fragments() / (prev_abundance.effective_length() / 1000.0);\n                if (frags_per_kb >= min_read_count)\n                    enough_reads = true;\n            }\n            \n//            if (enough_reads)\n//            {\n//                if (is_badly_fit(curr_abundance) || is_badly_fit(prev_abundance))\n//                    enough_reads = false;\n//            }\n            \n            \n            SampleDifference test;\n            test = get_de_tests(desc,\n                                itr->second.fpkm_series[j],\n                                itr->second.fpkm_series[i],\n                                //tests.cds_de_tests[i][j],\n                                enough_reads);\n#if ENABLE_THREADS\n            test_storage_lock.lock();\n#endif\n            \n            pair<SampleDiffs::iterator, bool> inserted;\n            inserted = tests.cds_de_tests[i][j].insert(make_pair(desc,\n                                                                 test));\n            \n            boost::shared_ptr<SampleDifferenceMetaData> meta_data = get_metadata(desc);\n            \n            meta_data->gene_ids = curr_abundance.gene_id();\n            meta_data->gene_names = curr_abundance.gene_name();\n            meta_data->protein_ids = curr_abundance.protein_id();\n            meta_data->locus_desc = curr_abundance.locus_tag();\n            meta_data->description = curr_abundance.description();\n            inserted.first->second.meta_data = meta_data;\n#if ENABLE_THREADS\n            test_storage_lock.unlock();\n#endif\n        }\n        \n        for (size_t k = 0; k < samples[i]->primary_transcripts.size(); ++k)\n        {\n            const Abundance& curr_abundance = samples[i]->primary_transcripts[k];\n            const Abundance& prev_abundance = samples[j]->primary_transcripts[k];\n            \n            const string& desc = curr_abundance.description();\n            FPKMTrackingTable::iterator itr = tracking.tss_group_fpkm_tracking.find(desc);\n            assert (itr != tracking.tss_group_fpkm_tracking.end());\n            \n            bool enough_reads = false;\n            if (curr_abundance.num_fragments() && curr_abundance.effective_length())\n            {\n                double frags_per_kb = curr_abundance.num_fragments() / (curr_abundance.effective_length() / 1000.0);\n                if (frags_per_kb >= min_read_count)\n                    enough_reads = true;\n            }\n            if (prev_abundance.num_fragments() && prev_abundance.effective_length())\n            {\n                double frags_per_kb = prev_abundance.num_fragments() / (prev_abundance.effective_length() / 1000.0);\n                if (frags_per_kb >= min_read_count)\n                    enough_reads = true;\n            }\n            \n//            if (enough_reads)\n//            {\n//                if (is_badly_fit(curr_abundance) || is_badly_fit(prev_abundance))\n//                    enough_reads = false;\n//            }\n            \n            \n            SampleDifference test;\n            test = get_de_tests(desc,\n                                itr->second.fpkm_series[j],\n                                itr->second.fpkm_series[i],\n                                //tests.tss_group_de_tests[i][j],\n                                enough_reads);\n#if ENABLE_THREADS\n            test_storage_lock.lock();\n#endif\n            pair<SampleDiffs::iterator, bool> inserted;\n            inserted = tests.tss_group_de_tests[i][j].insert(make_pair(desc,\n                                                                       test));\n            \n            \n            boost::shared_ptr<SampleDifferenceMetaData> meta_data = get_metadata(desc);\n            \n            meta_data->gene_ids = curr_abundance.gene_id();\n            meta_data->gene_names = curr_abundance.gene_name();\n            meta_data->protein_ids = curr_abundance.protein_id();\n            meta_data->locus_desc = curr_abundance.locus_tag();\n            meta_data->description = curr_abundance.description();\n            inserted.first->second.meta_data = meta_data;\n#if ENABLE_THREADS\n            test_storage_lock.unlock();\n#endif\n        }\n        \n        for (size_t k = 0; k < samples[i]->genes.size(); ++k)\n        {\n            const AbundanceGroup& curr_abundance = samples[i]->genes[k];\n            const AbundanceGroup& prev_abundance = samples[j]->genes[k];\n            const string& desc = curr_abundance.description();\n            FPKMTrackingTable::iterator itr = tracking.gene_fpkm_tracking.find(desc);\n            assert (itr != tracking.gene_fpkm_tracking.end());\n            \n            bool enough_reads = false;\n            if (curr_abundance.num_fragments() && curr_abundance.effective_length())\n            {\n                double frags_per_kb = curr_abundance.num_fragments() / (curr_abundance.effective_length() / 1000.0);\n                if (frags_per_kb >= min_read_count)\n                    enough_reads = true;\n            }\n            if (prev_abundance.num_fragments() && prev_abundance.effective_length())\n            {\n                double frags_per_kb = prev_abundance.num_fragments() / (prev_abundance.effective_length() / 1000.0);\n                if (frags_per_kb >= min_read_count)\n                    enough_reads = true;\n            }\n            \n            SampleDifference test;\n            test = get_de_tests(desc,\n                                itr->second.fpkm_series[j],\n                                itr->second.fpkm_series[i],\n                                //tests.gene_de_tests[i][j],\n                                enough_reads);\n#if ENABLE_THREADS\n            test_storage_lock.lock();\n#endif\n            pair<SampleDiffs::iterator, bool> inserted;\n            inserted = tests.gene_de_tests[i][j].insert(make_pair(desc,\n                                                                  test));\n            \n            boost::shared_ptr<SampleDifferenceMetaData> meta_data = get_metadata(desc);\n            \n            meta_data->gene_ids = curr_abundance.gene_id();\n            meta_data->gene_names = curr_abundance.gene_name();\n            meta_data->protein_ids = curr_abundance.protein_id();\n            meta_data->locus_desc = curr_abundance.locus_tag();\n            meta_data->description = curr_abundance.description();\n            inserted.first->second.meta_data = meta_data;\n#if ENABLE_THREADS\n            test_storage_lock.unlock();\n#endif\n        }\n        \n        // Skip all the JS based testing for genes with an isoform switch?\n        if (no_js_tests)\n            continue;\n        \n        // FIXME: the code below will not properly test for differential\n        // splicing/promoter use when a gene (e.g.) occupies two\n        // disjoint bundles.  We need to store the covariance matrices (etc)\n        // in the FPKMContexts to handle that case properly.\n        \n        // Differential promoter use\n        for (size_t k = 0; k < samples[i]->gene_primary_transcripts.size(); ++k)\n        {\n            const AbundanceGroup& curr_abundance = filtered_promoter_groups[i][k];\n            const AbundanceGroup& prev_abundance = filtered_promoter_groups[j][k];\n            const string& desc = curr_abundance.description();\n            \n            bool enough_reads = (curr_abundance.FPKM_by_replicate().size() >= min_reps_for_js_test &&\n                                 prev_abundance.FPKM_by_replicate().size() >= min_reps_for_js_test);\n            SampleDifference test;\n            test = get_ds_tests(prev_abundance,\n                                curr_abundance,\n                                enough_reads);\n            \n            // The filtered group might be empty, so let's grab metadata from\n            // the unfiltered group\n            boost::shared_ptr<SampleDifferenceMetaData> meta_data = get_metadata(desc);\n            \n            meta_data->gene_ids = samples[i]->gene_primary_transcripts[k].gene_id();\n            meta_data->gene_names = samples[i]->gene_primary_transcripts[k].gene_name();\n            meta_data->protein_ids = samples[i]->gene_primary_transcripts[k].protein_id();\n            meta_data->locus_desc = samples[i]->gene_primary_transcripts[k].locus_tag();\n            meta_data->description = samples[i]->gene_primary_transcripts[k].description();\n            \n            test.meta_data = meta_data;\n            \n#if ENABLE_THREADS\n            test_storage_lock.lock();\n#endif\n            \n            pair<SampleDiffs::iterator, bool> inserted;\n            inserted = tests.diff_promoter_tests[i][j].insert(make_pair(desc,test));\n            inserted.first->second = test;\n            \n#if ENABLE_THREADS\n            test_storage_lock.unlock();\n#endif\n        }\n        \n        // Differential coding sequence output\n        for (size_t k = 0; k < samples[i]->gene_cds.size(); ++k)\n        {\n            const AbundanceGroup& curr_abundance = filtered_cds_groups[i][k];\n            const AbundanceGroup& prev_abundance = filtered_cds_groups[j][k];\n            const string& desc = curr_abundance.description();\n            \n            bool enough_reads =  (curr_abundance.FPKM_by_replicate().size() >= min_reps_for_js_test &&\n                                  prev_abundance.FPKM_by_replicate().size() >= min_reps_for_js_test);\n            SampleDifference test;\n            test = get_ds_tests(prev_abundance,\n                                curr_abundance,\n                                enough_reads);\n            \n            // The filtered group might be empty, so let's grab metadata from\n            // the unfiltered group\n            boost::shared_ptr<SampleDifferenceMetaData> meta_data = get_metadata(desc);\n            \n            meta_data->gene_ids = samples[i]->gene_cds[k].gene_id();\n            meta_data->gene_names = samples[i]->gene_cds[k].gene_name();\n            meta_data->protein_ids = samples[i]->gene_cds[k].protein_id();\n            meta_data->locus_desc = samples[i]->gene_cds[k].locus_tag();\n            meta_data->description = samples[i]->gene_cds[k].description();\n            \n            test.meta_data = meta_data;\n            \n#if ENABLE_THREADS\n            test_storage_lock.lock();\n#endif\n            pair<SampleDiffs::iterator, bool> inserted;\n            inserted = tests.diff_cds_tests[i][j].insert(make_pair(desc,test));\n            inserted.first->second = test;\n            \n#if ENABLE_THREADS\n            test_storage_lock.unlock();\n#endif\n        }\n        \n        // Differential splicing of primary transcripts\n        for (size_t k = 0; k < samples[i]->primary_transcripts.size(); ++k)\n        {\n            const AbundanceGroup& curr_abundance = filtered_primary_trans_groups[i][k];\n            const AbundanceGroup& prev_abundance = filtered_primary_trans_groups[j][k];\n            const string& desc = curr_abundance.description();\n            \n            bool enough_reads = (curr_abundance.FPKM_by_replicate().size() >= min_reps_for_js_test &&\n                                 prev_abundance.FPKM_by_replicate().size() >= min_reps_for_js_test);\n            \n            SampleDifference test;\n            test = get_ds_tests(prev_abundance, \n                                curr_abundance,\n                                enough_reads);\n            \n            // The filtered group might be empty, so let's grab metadata from\n            // the unfiltered group\n            boost::shared_ptr<SampleDifferenceMetaData> meta_data = get_metadata(desc);\n            \n            meta_data->gene_ids = samples[i]->primary_transcripts[k].gene_id();\n            meta_data->gene_names = samples[i]->primary_transcripts[k].gene_name();\n            meta_data->protein_ids = samples[i]->primary_transcripts[k].protein_id();\n            meta_data->locus_desc = samples[i]->primary_transcripts[k].locus_tag();\n            meta_data->description = samples[i]->primary_transcripts[k].description();\n            \n            test.meta_data = meta_data;\n            \n#if ENABLE_THREADS\n            test_storage_lock.lock();\n#endif\n            pair<SampleDiffs::iterator, bool> inserted;\n            inserted = tests.diff_splicing_tests[i][j].insert(make_pair(desc,test)); \n            inserted.first->second = test;\n            \n#if ENABLE_THREADS\n            test_storage_lock.unlock();\n#endif\n        }\n        \n    }\n    \n    for (size_t i = 0; i < samples.size(); ++i)\n    {\n        clear_samples_from_tracking_table(samples[i], tracking);\n    }\n}\n\nvoid print_checked_params_table(const vector<boost::shared_ptr<ReadGroupProperties> >& all_read_groups)\n{\n    string param_check_error_out_filename = output_dir + \"/checked_params.txt\";\n    FILE* param_check_error_out_file = fopen(param_check_error_out_filename.c_str(), \"w\");\n    \n    fprintf(param_check_error_out_file, \"file\\tdefault frag length mean\\tdefault frag length std dev\\tbias correction\\tbias mode\\tmultiread correction\\tmax-mle-iterations\\tmin-mle-accuracy\\tmax-bundle-frags\\tmax-frag-multihits\\tno-effective-length-correction\\tno-length-correction\\n\");\n    for (size_t i = 0; i < all_read_groups.size(); ++i)\n    {\n        const CheckedParameters& cp_i = all_read_groups[i]->checked_parameters();\n        fprintf(param_check_error_out_file, \"%s\\t\", all_read_groups[i]->file_path().c_str());\n        fprintf(param_check_error_out_file, \"%lg\\t\", cp_i.frag_len_mean);\n        fprintf(param_check_error_out_file, \"%lg\\t\", cp_i.frag_len_std_dev);\n        fprintf(param_check_error_out_file, \"%s\\t\", cp_i.corr_bias ? \"yes\" : \"no\");\n        fprintf(param_check_error_out_file, \"%d\\t\", cp_i.frag_bias_mode);\n        fprintf(param_check_error_out_file, \"%s\\t\", cp_i.corr_multireads ? \"yes\" : \"no\");\n        fprintf(param_check_error_out_file, \"%lg\\t\", cp_i.max_mle_iterations);\n        fprintf(param_check_error_out_file, \"%lg\\t\", cp_i.min_mle_accuracy);\n        fprintf(param_check_error_out_file, \"%lg\\t\", cp_i.max_bundle_frags);\n        fprintf(param_check_error_out_file, \"%lg\\t\", cp_i.max_frags_multihits);\n        fprintf(param_check_error_out_file, \"%s\\t\", cp_i.no_effective_length_correction ? \"yes\" : \"no\");\n        fprintf(param_check_error_out_file, \"%s\\t\", cp_i.no_length_correction? \"yes\" : \"no\");\n        fprintf(param_check_error_out_file, \"\\n\");\n    }\n    fclose(param_check_error_out_file);\n\n}\n\nvoid validate_cross_sample_parameters(const vector<boost::shared_ptr<ReadGroupProperties> >& all_read_groups)\n{\n    bool dump_params = false;\n    for (size_t i = 1; i < all_read_groups.size(); ++i)\n    {\n        const CheckedParameters& cp_i = all_read_groups[i - 1]->checked_parameters();\n        const CheckedParameters& cp_j = all_read_groups[i]->checked_parameters();\n        \n        if (cp_i.ref_gtf_crc != cp_j.ref_gtf_crc)\n        {\n            fprintf(stderr, \"Error reference gene annotation differs between samples!\\n\");\n            fprintf(stderr, \"\\t%s\\t%s:\\t%u!\\n\", all_read_groups[i - 1]->file_path().c_str(), cp_i.ref_gtf_file_path.c_str(), cp_i.ref_gtf_crc);\n            fprintf(stderr, \"\\t%s\\t%s:\\t%u!\\n\", all_read_groups[i]->file_path().c_str(), cp_j.ref_gtf_file_path.c_str(), cp_j.ref_gtf_crc);\n            exit(1);\n        }\n        \n        if (cp_i != cp_j)\n        {\n            dump_params = true;\n            fprintf(stderr, \"Warning: quantification parameters differ between CXB files!\\n\\tSee %s/checked_params.txt for more info\\n\", output_dir.c_str());\n            break;\n//            fprintf(stderr, \"CXB files:\\n\");\n//            fprintf(stderr, \"%s:\\n\", all_read_groups[i - 1]->file_path().c_str());\n//            fprintf(stderr, \"\\tdefault-frag-length-mean:\\t%lg\\n\", cp_i.frag_len_mean);\n//            fprintf(stderr, \"\\tdefault-frag-length-std-dev:\\t%lg\\n\", cp_i.frag_len_std_dev);\n//            fprintf(stderr, \"\\tbias correction:\\t%s\\n\", cp_i.corr_bias ? \"yes\" : \"no\");\n//            fprintf(stderr, \"\\tbias mode:\\t%d\\n\", cp_i.frag_bias_mode);\n//            fprintf(stderr, \"\\tmultiread correction:\\t%s\\n\", cp_i.corr_multireads ? \"yes\" : \"no\");\n//            fprintf(stderr, \"\\tmax-mle-iterations:\\t%lg\\n\", cp_i.max_mle_iterations);\n//            fprintf(stderr, \"\\tmin-mle-accuracy:\\t%lg\\n\", cp_i.min_mle_accuracy);\n//            fprintf(stderr, \"\\tmax-bundle-frags:\\t%lg\\n\", cp_i.max_bundle_frags);\n//            fprintf(stderr, \"\\tmax-frag-multihits:\\t%lg\\n\", cp_i.max_frags_multihits);\n//            fprintf(stderr, \"\\tno-effective-length-correction:\\t%s\\n\", cp_i.no_effective_length_correction ? \"yes\" : \"no\");\n//            fprintf(stderr, \"\\tno-length-correction:\\t%s\\n\", cp_i.no_length_correction? \"yes\" : \"no\");\n//            \n//            fprintf(stderr, \"%s\\n\", all_read_groups[i]->file_path().c_str());\n//            fprintf(stderr, \"\\tdefault-frag-length-mean:\\t%lg\\n\", cp_j.frag_len_mean);\n//            fprintf(stderr, \"\\tdefault-frag-length-std-dev:\\t%lg\\n\", cp_j.frag_len_std_dev);\n//            // TODO: add CRCs for reference GTF, mask file, norm standards file if using.\n//            fprintf(stderr, \"\\tbias correction:\\t%s\\n\", cp_j.corr_bias ? \"yes\" : \"no\");\n//            fprintf(stderr, \"\\tbias mode:\\t%d\\n\", cp_j.frag_bias_mode);\n//            fprintf(stderr, \"\\tmultiread correction:\\t%s\\n\", cp_j.corr_multireads ? \"yes\" : \"no\");\n//            fprintf(stderr, \"\\tmax-mle-iterations:\\t%lg\\n\", cp_j.max_mle_iterations);\n//            fprintf(stderr, \"\\tmin-mle-accuracy:\\t%lg\\n\", cp_j.min_mle_accuracy);\n//            fprintf(stderr, \"\\tmax-bundle-frags:\\t%lg\\n\", cp_j.max_bundle_frags);\n//            fprintf(stderr, \"\\tmax-frag-multihits:\\t%lg\\n\", cp_j.max_frags_multihits);\n//            fprintf(stderr, \"\\tno-effective-length-correction:\\t%s\\n\", cp_j.no_effective_length_correction ? \"yes\" : \"no\");\n//            fprintf(stderr, \"\\tno-length-correction:\\t%s\\n\", cp_j.no_length_correction? \"yes\" : \"no\");\n            \n        }\n        \n    }\n    if (dump_params)\n        print_checked_params_table(all_read_groups);\n}\n\nvoid TrackingDataWriter::perform_testing(vector<boost::shared_ptr<SampleAbundances> > abundances)\n{\n#if ENABLE_THREADS\n    _launcher_lock.lock();\n    test_storage_lock.lock();\n#endif\n    if (headers_written == false)\n    {\n        write_header_output();\n        headers_written = true;\n    }\n    \n    write_output(abundances);\n    //test_differential(abundances.front()->locus_tag, abundances, _contrasts, *_tests, *_tracking);\n#if ENABLE_THREADS\n    test_storage_lock.unlock();\n    _launcher_lock.unlock();\n#endif\n    \n}\n\n"
  },
  {
    "path": "src/differential.h",
    "content": "#ifndef DIFFERENTIAL_H\n#define DIFFERENTIAL_H\n/*\n *  differential.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/15/10.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <cstdlib>\n#include <set>\n#include <map>\n#include <utility>\n#include <vector>\n#include <string>\n\n#include <boost/thread.hpp>\n#include <boost/graph/adjacency_list.hpp>\n#include <boost/graph/graph_traits.hpp>\n\n#include \"abundances.h\"\n#include \"jensen_shannon.h\"\n#include \"replicates.h\"\n#include \"tracking.h\"\n\nusing namespace std;\n\nenum TestStatus {\n\tNOTEST,  // successful calculation, test not performed\n    LOWDATA, // unsuccessful calculation due to low data, test not performed\n    HIDATA,  // skipped calculation due to too many reads data, test not performed\n\tOK,      // successful numerical calc, test performed\n\tFAIL     // numerical exception, test not performed\n}; \n\nstruct SampleDifferenceMetaData\n{\n    string locus_desc;\n    set<string> gene_ids;\n\tset<string> gene_names;\n\tset<string> protein_ids;\n\tstring description; // isoforms or tss groups (e.g.) involved in this test\n};\n\n// Stores the differential expression of an isoform or set of isoforms in two\n// different samples, along with a significance test statistic for the difference.\nclass SampleDifference\n{\npublic:\n\tSampleDifference();\n\t\n\tsize_t sample_1;\n\tsize_t sample_2;\n\t\n\tdouble value_1;\n\tdouble value_2;\n\tdouble differential;\n\tdouble test_stat;\n\tdouble p_value;\n\tdouble corrected_p;\n\t\n    boost::shared_ptr<SampleDifferenceMetaData> meta_data;\n\n\tTestStatus test_status;\n\tbool significant;\n    \n//    double sample_1_param_1;\n//    double sample_1_param_2;\n//    \n//    \n//    double sample_2_param_1;\n//    double sample_2_param_2;\n//    \n//    double null_param_1;\n//    double null_param_2;\n};\n\ntypedef map<string, SampleDifference > SampleDiffs;\ntypedef map<string, boost::shared_ptr<SampleDifferenceMetaData> > SampleDiffMetaDataTable;\n\nstruct Outfiles\n{\n\tFILE* isoform_de_outfile;\n\tFILE* group_de_outfile;\n\tFILE* gene_de_outfile;\n\tFILE* cds_de_outfile;\n\t\n\tFILE* diff_splicing_outfile;\n\tFILE* diff_promoter_outfile;\n\tFILE* diff_cds_outfile;\n\t\n\tFILE* isoform_fpkm_tracking_out;\n\tFILE* tss_group_fpkm_tracking_out;\n\tFILE* gene_fpkm_tracking_out;\n\tFILE* cds_fpkm_tracking_out;\n    \n    FILE* isoform_count_tracking_out;\n\tFILE* tss_group_count_tracking_out;\n\tFILE* gene_count_tracking_out;\n\tFILE* cds_count_tracking_out;\n    \n    FILE* isoform_rep_tracking_out;\n\tFILE* tss_group_rep_tracking_out;\n\tFILE* gene_rep_tracking_out;\n\tFILE* cds_rep_tracking_out;\n\n    FILE* isoform_attr_out;\n\tFILE* tss_group_attr_out;\n\tFILE* gene_attr_out;\n\tFILE* cds_attr_out;\n    \n    FILE* run_info_out;\n    FILE* read_group_info_out;\n    FILE* bias_out;\n    FILE* var_model_out;\n};\n\nstruct Tests\n{\n\tvector<vector<SampleDiffs> > isoform_de_tests;\n\tvector<vector<SampleDiffs> > tss_group_de_tests;\n\tvector<vector<SampleDiffs> > gene_de_tests;\n\tvector<vector<SampleDiffs> > cds_de_tests;\n\t\n\tvector<vector<SampleDiffs> > diff_splicing_tests; // to be performed on the isoforms of a single tss group\n\tvector<vector<SampleDiffs> > diff_promoter_tests; // to be performed on the tss groups of a single gene\n\tvector<vector<SampleDiffs> > diff_cds_tests; // to be performed on the cds groups of a single gene\n};\n\n#if ENABLE_THREADS\n    extern boost::mutex _launcher_lock;\n#endif\n\n#if ENABLE_THREADS\nextern boost::mutex test_storage_lock; \n#endif\n\nstruct TestLauncher\n{\nprivate:\n    TestLauncher(TestLauncher& rhs) {}\n    \npublic:\n    TestLauncher(int num_samples,\n                 const vector<pair<size_t, size_t> >& contrasts,\n                 Tests* tests,\n                 Tracking* tracking,\n                 ProgressBar* p_bar,\n                 bool track_only = false)\n    :\n    _orig_workers(num_samples),\n    _contrasts(contrasts),\n    _tests(tests),\n    _tracking(tracking),\n    _p_bar(p_bar),\n    _track_only(track_only)\n    {\n    }\n    \n    virtual ~TestLauncher() {} \n    \n    void operator()();\n    \n    void register_locus(const string& locus_id);\n    void abundance_avail(const string& locus_id, \n                         boost::shared_ptr<SampleAbundances> ab, \n                         size_t factory_id);\n    virtual vector<vector<boost::shared_ptr<SampleAbundances> > > test_finished_loci();\n    virtual void perform_testing(vector<boost::shared_ptr<SampleAbundances> > abundances);\n    void record_tracking_data(vector<boost::shared_ptr<SampleAbundances> >& abundances);\n    bool all_samples_reported_in(vector<boost::shared_ptr<SampleAbundances> >& abundances);\n    bool all_samples_reported_in(const string& locus_id);\n    \n    void clear_tracking_data() { _tracking->clear(); }\n    \n    typedef list<pair<string, vector<boost::shared_ptr<SampleAbundances> > > > launcher_sample_table;\n    \nprivate:\n    \n    launcher_sample_table::iterator find_locus(const string& locus_id);\n    \n    int _orig_workers;\n    vector<pair<size_t, size_t> > _contrasts;\n    launcher_sample_table _samples;\n    Tests* _tests;\n    Tracking* _tracking;\n    ProgressBar* _p_bar;\n    bool _track_only;\n    \n};\n\n// This routine doesn't actually do any tests.  Use this when you just want to\n// Flush tracking data once all samples have reported in.\nclass TrackingDataWriter : public TestLauncher\n{\n    \npublic:\n    TrackingDataWriter(int num_samples,\n                       Outfiles* outfiles,\n                       Tracking* tracking,\n                       const vector<boost::shared_ptr<ReadGroupProperties> >& all_read_groups,\n                       vector<string> sls,\n                       ProgressBar* p_bar,\n                       boost::shared_ptr<IdToLocusMap> id_to_locus_map)\n    : TestLauncher(num_samples, vector<pair<size_t, size_t> >(), NULL, tracking, p_bar),\n    _tracking(tracking),\n    _outfiles(outfiles),\n    _all_read_groups(all_read_groups),\n    sample_labels(sls),\n    headers_written(false),\n    _id_to_locus_map(id_to_locus_map)\n    {\n        \n    }\n    \n    void perform_testing(vector<boost::shared_ptr<SampleAbundances> > abundances);\n    \nprivate:\n    Tracking* _tracking;\n    Outfiles* _outfiles;\n    const vector<boost::shared_ptr<ReadGroupProperties> >& _all_read_groups;\n    bool headers_written; // this flag records whether we've written out the file headers yet.\n    boost::shared_ptr<IdToLocusMap> _id_to_locus_map;\n    vector<string> sample_labels;\n    \n    void print_FPKM_tracking_header(FILE* fout,\n                                    const FPKMTrackingTable& tracking)\n    {\n        fprintf(fout,\"tracking_id\\tclass_code\\tnearest_ref_id\\tgene_id\\tgene_short_name\\ttss_id\\tlocus\\tlength\\tcoverage\");\n        FPKMTrackingTable::const_iterator first_itr = tracking.begin();\n        if (first_itr != tracking.end())\n        {\n            const FPKMTracking& track = first_itr->second;\n            const vector<FPKMContext>& fpkms = track.fpkm_series;\n            for (size_t i = 0; i < fpkms.size(); ++i)\n            {\n                fprintf(fout, \"\\t%s_FPKM\\t%s_conf_lo\\t%s_conf_hi\\t%s_status\", sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str());\n            }\n        }\n        fprintf(fout, \"\\n\");\n        fflush(fout);\n    }\n    \n    void print_count_tracking_header(FILE* fout,\n                                     const FPKMTrackingTable& tracking)\n    {\n        fprintf(fout,\"tracking_id\");\n        FPKMTrackingTable::const_iterator first_itr = tracking.begin();\n        if (first_itr != tracking.end())\n        {\n            const FPKMTracking& track = first_itr->second;\n            const vector<FPKMContext>& fpkms = track.fpkm_series;\n            for (size_t i = 0; i < fpkms.size(); ++i)\n            {\n                fprintf(fout, \"\\t%s_count\\t%s_count_variance\\t%s_count_uncertainty_var\\t%s_count_dispersion_var\\t%s_status\", sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str(), sample_labels[i].c_str());\n            }\n        }\n        fprintf(fout, \"\\n\");\n        fflush(fout);\n    }\n    \n    void print_FPKM_simple_table_header(FILE* fout,\n                                        const FPKMTrackingTable& tracking)\n    {\n        fprintf(fout,\"tracking_id\");\n        FPKMTrackingTable::const_iterator first_itr = tracking.begin();\n        if (first_itr != tracking.end())\n        {\n            const FPKMTracking& track = first_itr->second;\n            const vector<FPKMContext>& fpkms = track.fpkm_series;\n            for (size_t i = 0; i < fpkms.size(); ++i)\n            {\n                for (size_t j = 0; j != fpkms[i].tracking_info_per_rep.size();\n                     ++j)\n                {\n                    const  string& condition_name = fpkms[i].tracking_info_per_rep[j].rg_props->condition_name();\n                    int rep_num = fpkms[i].tracking_info_per_rep[j].rg_props->replicate_num();\n                    fprintf(fout, \"\\t%s_%d\", condition_name.c_str(), rep_num);\n                }\n            }\n            fflush(fout);\n        }\n    }\n    \n    void print_count_simple_table_header(FILE* fout,\n                                         const FPKMTrackingTable& tracking)\n    {\n        fprintf(fout,\"tracking_id\");\n        FPKMTrackingTable::const_iterator first_itr = tracking.begin();\n        if (first_itr != tracking.end())\n        {\n            const FPKMTracking& track = first_itr->second;\n            const vector<FPKMContext>& fpkms = track.fpkm_series;\n            for (size_t i = 0; i < fpkms.size(); ++i)\n            {\n                for (size_t j = 0; j != fpkms[i].tracking_info_per_rep.size();\n                     ++j)\n                {\n                    const  string& condition_name = fpkms[i].tracking_info_per_rep[j].rg_props->condition_name();\n                    int rep_num = fpkms[i].tracking_info_per_rep[j].rg_props->replicate_num();\n                    fprintf(fout, \"\\t%s_%d\", condition_name.c_str(), rep_num);\n                }\n            }\n            fflush(fout);\n        }\n    }\n    \n    void print_FPKM_tracking(const string& target_desc,\n                             FILE* fout,\n                             const FPKMTrackingTable& tracking)\n    {\n        FPKMTrackingTable::const_iterator itr = tracking.find(target_desc);\n        if (itr != tracking.end())\n        {\n            const string& description = itr->first;\n            const FPKMTracking& track = itr->second;\n            const vector<FPKMContext>& fpkms = track.fpkm_series;\n            \n            AbundanceStatus status = NUMERIC_OK;\n            BOOST_FOREACH (const FPKMContext& c, fpkms)\n            {\n                if (c.status == NUMERIC_FAIL)\n                    status = NUMERIC_FAIL;\n            }\n            \n            string all_gene_ids = cat_strings(track.gene_ids);\n            if (all_gene_ids == \"\")\n                all_gene_ids = \"-\";\n            \n            string all_gene_names = cat_strings(track.gene_names);\n            if (all_gene_names == \"\")\n                all_gene_names = \"-\";\n            \n            string all_tss_ids = cat_strings(track.tss_ids);\n            if (all_tss_ids == \"\")\n                all_tss_ids = \"-\";\n            \n            char length_buff[33] = \"-\";\n            if (track.length)\n                sprintf(length_buff, \"%d\", track.length);\n            \n            fprintf(fout, \"%s\\t%c\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\",\n                    description.c_str(),\n                    track.classcode ? track.classcode : '-',\n                    track.ref_match.c_str(),\n                    all_gene_ids.c_str(),\n                    all_gene_names.c_str(),\n                    all_tss_ids.c_str(),\n                    track.locus_tag.c_str(),\n                    length_buff,\n                    \"-\");\n       \t\t\n            for (size_t i = 0; i < fpkms.size(); ++i)\n            {\n                double fpkm = fpkms[i].FPKM;\n                //double std_dev = sqrt(fpkms[i].FPKM_variance);\n                double fpkm_conf_hi = fpkms[i].FPKM_conf_hi;\n                double fpkm_conf_lo = fpkms[i].FPKM_conf_lo;\n                const char* status_str = \"OK\";\n                \n                if (fpkms[i].status == NUMERIC_OK)\n                {\n                    status_str = \"OK\";\n                }\n                else if (fpkms[i].status == NUMERIC_FAIL)\n                {\n                    status_str = \"FAIL\";\n                }\n                else if (fpkms[i].status == NUMERIC_LOW_DATA)\n                {\n                    status_str = \"LOWDATA\";\n                }\n                else if (fpkms[i].status == NUMERIC_HI_DATA)\n                {\n                    status_str = \"HIDATA\";\n                }\n                else\n                {\n                    assert(false);\n                }\n                \n                fprintf(fout, \"\\t%lg\\t%lg\\t%lg\\t%s\", fpkm, fpkm_conf_lo, fpkm_conf_hi, status_str);\n            }\n            \n            fprintf(fout, \"\\n\");\n            fflush(fout);\n        }\n    }\n    \n    void print_count_tracking(const string& target_desc,\n                              FILE* fout,\n                              const FPKMTrackingTable& tracking)\n    {\n        FPKMTrackingTable::const_iterator itr = tracking.find(target_desc);\n        if (itr != tracking.end())\n        {\n            const string& description = itr->first;\n            const FPKMTracking& track = itr->second;\n            const vector<FPKMContext>& fpkms = track.fpkm_series;\n            \n            AbundanceStatus status = NUMERIC_OK;\n            BOOST_FOREACH (const FPKMContext& c, fpkms)\n            {\n                if (c.status == NUMERIC_FAIL)\n                    status = NUMERIC_FAIL;\n            }\n            \n            fprintf(fout, \"%s\",\n                    description.c_str());\n            \n            for (size_t i = 0; i < fpkms.size(); ++i)\n            {\n                const char* status_str = \"OK\";\n                \n                if (fpkms[i].status == NUMERIC_OK)\n                {\n                    status_str = \"OK\";\n                }\n                else if (fpkms[i].status == NUMERIC_FAIL)\n                {\n                    status_str = \"FAIL\";\n                }\n                else if (fpkms[i].status == NUMERIC_LOW_DATA)\n                {\n                    status_str = \"LOWDATA\";\n                }\n                else if (fpkms[i].status == NUMERIC_HI_DATA)\n                {\n                    status_str = \"HIDATA\";\n                }\n                else\n                {\n                    assert(false);\n                }\n                \n                double external_counts = fpkms[i].count_mean;\n                double external_count_var = fpkms[i].count_var;\n                double uncertainty_var = fpkms[i].count_uncertainty_var;\n                double dispersion_var = fpkms[i].count_dispersion_var;\n                fprintf(fout, \"\\t%lg\\t%lg\\t%lg\\t%lg\\t%s\", external_counts, external_count_var, uncertainty_var, dispersion_var, status_str);\n            }\n            \n            fprintf(fout, \"\\n\");\n            fflush(fout);\n        }\n    }\n    \n    void print_FPKM_simple_table(const string& target_desc,\n                                 FILE* fout,\n                                 const FPKMTrackingTable& tracking)\n    {\n        FPKMTrackingTable::const_iterator itr = tracking.find(target_desc);\n        if (itr != tracking.end())\n        {\n            const string& description = itr->first;\n            fprintf(fout, \"\\n%s\", description.c_str());\n\n            const FPKMTracking& track = itr->second;\n            const vector<FPKMContext>& fpkms = track.fpkm_series;\n            \n            for (size_t i = 0; i < fpkms.size(); ++i)\n            {\n                for (size_t j = 0; j != fpkms[i].tracking_info_per_rep.size();\n                     ++j)\n                {\n                    double FPKM = fpkms[i].tracking_info_per_rep[j].fpkm;\n                    fprintf(fout, \"\\t%lg\", FPKM);\n                }\n            }\n            fflush(fout);\n        }\n    }\n    \n    void print_count_simple_table(const string& target_desc,\n                                  FILE* fout,\n                                  const FPKMTrackingTable& tracking)\n    {\n        FPKMTrackingTable::const_iterator itr = tracking.find(target_desc);\n        if (itr != tracking.end())\n        {\n            const string& description = itr->first;\n            fprintf(fout, \"\\n%s\", description.c_str());\n\n            const FPKMTracking& track = itr->second;\n            const vector<FPKMContext>& fpkms = track.fpkm_series;\n            \n            for (size_t i = 0; i < fpkms.size(); ++i)\n            {\n                for (size_t j = 0; j != fpkms[i].tracking_info_per_rep.size();\n                     ++j)\n                {\n                    double count = fpkms[i].tracking_info_per_rep[j].count;\n                    fprintf(fout, \"\\t%lg\", count);\n                }\n            }\n            fflush(fout);\n        }\n    }\n    \n    void remove_abundance_from_tracking_table(const string& target_desc,\n                                              FPKMTrackingTable& tracking)\n    {\n        FPKMTrackingTable::iterator itr = tracking.find(target_desc);\n        if (itr != tracking.end())\n        {\n            tracking.erase(itr);\n        }\n    }\n    \n    void print_read_group_tracking_header(FILE* fout,\n                                          const FPKMTrackingTable& tracking)\n    {\n        fprintf(fout,\"tracking_id\\tcondition\\treplicate\\traw_frags\\tinternal_scaled_frags\\texternal_scaled_frags\\tFPKM\\teffective_length\\tstatus\");\n        fprintf(fout, \"\\n\");\n    }\n    \n    void print_read_group_tracking(const string& target_desc,\n                                   FILE* fout,\n                                   const FPKMTrackingTable& tracking)\n    {\n        FPKMTrackingTable::const_iterator itr = tracking.find(target_desc);\n        if (itr != tracking.end())\n        {\n            const string& description = itr->first;\n            const FPKMTracking& track = itr->second;\n            const vector<FPKMContext>& fpkms = track.fpkm_series;\n            \n            for (size_t i = 0; i < fpkms.size(); ++i)\n            {\n                for (size_t j = 0; j != fpkms[i].tracking_info_per_rep.size();\n                     ++j)\n                {\n                    double FPKM = fpkms[i].tracking_info_per_rep[j].fpkm;\n                    double internal_count = fpkms[i].tracking_info_per_rep[j].count;\n                    double external_count = internal_count / fpkms[i].tracking_info_per_rep[j].rg_props->external_scale_factor();\n                    double raw_count = internal_count * fpkms[i].tracking_info_per_rep[j].rg_props->internal_scale_factor();\n                    const  string& condition_name = fpkms[i].tracking_info_per_rep[j].rg_props->condition_name();\n                    AbundanceStatus status = fpkms[i].tracking_info_per_rep[j].status;\n                    \n                    int rep_num = fpkms[i].tracking_info_per_rep[j].rg_props->replicate_num();\n                    \n                    const char* status_str = \"OK\";\n                    \n                    if (status == NUMERIC_OK)\n                    {\n                        status_str = \"OK\";\n                    }\n                    else if (status == NUMERIC_FAIL)\n                    {\n                        status_str = \"FAIL\";\n                    }\n                    else if (status == NUMERIC_LOW_DATA)\n                    {\n                        status_str = \"LOWDATA\";\n                    }\n                    else if (status == NUMERIC_HI_DATA)\n                    {\n                        status_str = \"HIDATA\";\n                    }\n                    else\n                    {\n                        assert(false);\n                    }\n                    \n                    fprintf(fout, \"%s\\t%s\\t%d\\t%lg\\t%lg\\t%lg\\t%lg\\t%s\\t%s\\n\",\n                            description.c_str(),\n                            condition_name.c_str(),\n                            rep_num,\n                            raw_count,\n                            internal_count,\n                            external_count,\n                            FPKM,\n                            \"-\",\n                            status_str);\n                }\n            }\n            fflush(fout);\n        }\n    }\n    \n    void print_read_group_cuffdiff_info(FILE* fout,\n                                        const vector<boost::shared_ptr<ReadGroupProperties> >& all_read_groups)\n    {\n        fprintf(fout, \"file\\tcondition\\treplicate_num\\ttotal_mass\\tnorm_mass\\tinternal_scale\\texternal_scale\\n\");\n        for (size_t i = 0; i < all_read_groups.size(); ++i)\n        {\n            boost::shared_ptr<ReadGroupProperties const> rg_props = all_read_groups[i];\n            fprintf(fout, \"%s\\t%s\\t%d\\t%Lg\\t%Lg\\t%lg\\t%lg\\n\",\n                    rg_props->file_path().c_str(),\n                    rg_props->condition_name().c_str(),\n                    rg_props->replicate_num(),\n                    rg_props->total_map_mass(),\n                    rg_props->normalized_map_mass(),\n                    rg_props->internal_scale_factor(),\n                    rg_props->external_scale_factor());\n            \n        }\n    }\n    \n    void print_read_group_simple_table_info(FILE* fout,\n                                            const vector<boost::shared_ptr<ReadGroupProperties> >& all_read_groups)\n    {\n        //fprintf(fout, \"file\\tcondition\\treplicate_num\\ttotal_mass\\tnorm_mass\\tinternal_scale\\texternal_scale\\n\");\n        fprintf(fout, \"sample_id\\tfile\\ttotal_mass\\tinternal_scale\\texternal_scale\\n\");\n        for (size_t i = 0; i < all_read_groups.size(); ++i)\n        {\n            boost::shared_ptr<ReadGroupProperties const> rg_props = all_read_groups[i];\n            fprintf(fout, \"%s_%d\\t%s\\t%Lg\\t%lg\\t%lg\\t%lg\\n\",\n                    rg_props->condition_name().c_str(),\n                    rg_props->replicate_num(),\n                    rg_props->file_path().c_str(),\n                    rg_props->total_map_mass(),\n                    rg_props->internal_scale_factor(),\n                    rg_props->external_scale_factor());\n            \n        }\n    }\n\n    void print_feature_attr_simple_table_header(FILE* fout,\n                                         const FPKMTrackingTable& tracking)\n    {\n        fprintf(fout,\"tracking_id\\tclass_code\\tnearest_ref_id\\tgene_id\\tgene_short_name\\ttss_id\\tlocus\\tlength\");\n        fprintf(fout, \"\\n\");\n    }\n\n    \n    void print_feature_attr_simple_table(const string& target_desc,\n                                         FILE* fout,\n                                         const FPKMTrackingTable& tracking)\n    {\n        FPKMTrackingTable::const_iterator itr = tracking.find(target_desc);\n        if (itr != tracking.end())\n        {\n            const string& description = itr->first;\n            const string& locus_tag = itr->second.locus_tag;\n            const string& ref_match = itr->second.ref_match;\n            int length = itr->second.length;\n            char length_buff[33] = \"-\";\n            if (length)\n                sprintf(length_buff, \"%d\", length);\n            const set<string>& gene_names = itr->second.gene_names;\n            const set<string>& gene_ids = itr->second.gene_ids;\n            const set<string>& tss_ids = itr->second.tss_ids;\n            char class_code = itr->second.classcode ? itr->second.classcode : '-';\n            string all_gene_names = cat_strings(gene_names);\n            if (all_gene_names == \"\")\n                all_gene_names = \"-\";\n            string all_gene_ids = cat_strings(gene_ids);\n            if (all_gene_ids == \"\")\n                all_gene_ids = \"-\";\n            string all_tss_ids = cat_strings(tss_ids);\n            if (all_tss_ids == \"\")\n                all_tss_ids = \"-\";\n            fprintf(fout, \"%s\\t%c\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\n\",\n                    description.c_str(),\n                    class_code,\n                    ref_match.c_str(),\n                    all_gene_ids.c_str(),\n                    all_gene_names.c_str(),\n                    all_tss_ids.c_str(),\n                    locus_tag.c_str(),\n                    length_buff);\n        }\n    }\n    \n    void print_run_info(FILE* fout)\n    {\n        fprintf(fout, \"param\\tvalue\\n\");\n        fprintf(fout, \"cmd_line\\t%s\\n\", cmd_str.c_str());\n        fprintf(fout, \"version\\t%s\\n\", PACKAGE_VERSION);\n        fprintf(fout, \"SVN_revision\\t%s\\n\",SVN_REVISION);\n        fprintf(fout, \"boost_version\\t%d\\n\", BOOST_VERSION);\n    }\n    \n    void write_header_output_cuffdiff_format()\n    {\n        // FPKM tracking\n        \n        FILE* fiso_fpkm_tracking =  _outfiles->isoform_fpkm_tracking_out;\n        //fprintf(stderr, \"Writing isoform-level FPKM tracking\\n\");\n        print_FPKM_tracking_header(fiso_fpkm_tracking,_tracking->isoform_fpkm_tracking);\n        \n        FILE* ftss_fpkm_tracking =  _outfiles->tss_group_fpkm_tracking_out;\n        //fprintf(stderr, \"Writing TSS group-level FPKM tracking\\n\");\n        print_FPKM_tracking_header(ftss_fpkm_tracking,_tracking->tss_group_fpkm_tracking);\n        \n        FILE* fgene_fpkm_tracking =  _outfiles->gene_fpkm_tracking_out;\n        //fprintf(stderr, \"Writing gene-level FPKM tracking\\n\");\n        print_FPKM_tracking_header(fgene_fpkm_tracking,_tracking->gene_fpkm_tracking);\n        \n        FILE* fcds_fpkm_tracking =  _outfiles->cds_fpkm_tracking_out;\n        //fprintf(stderr, \"Writing CDS-level FPKM tracking\\n\");\n        print_FPKM_tracking_header(fcds_fpkm_tracking,_tracking->cds_fpkm_tracking);\n        \n        // Count tracking\n        \n        FILE* fiso_count_tracking =  _outfiles->isoform_count_tracking_out;\n        //fprintf(stderr, \"Writing isoform-level count tracking\\n\");\n        print_count_tracking_header(fiso_count_tracking,_tracking->isoform_fpkm_tracking);\n        \n        FILE* ftss_count_tracking =  _outfiles->tss_group_count_tracking_out;\n        //fprintf(stderr, \"Writing TSS group-level count tracking\\n\");\n        print_count_tracking_header(ftss_count_tracking,_tracking->tss_group_fpkm_tracking);\n        \n        FILE* fgene_count_tracking =  _outfiles->gene_count_tracking_out;\n        //fprintf(stderr, \"Writing gene-level count tracking\\n\");\n        print_count_tracking_header(fgene_count_tracking,_tracking->gene_fpkm_tracking);\n        \n        FILE* fcds_count_tracking =  _outfiles->cds_count_tracking_out;\n        //fprintf(stderr, \"Writing CDS-level count tracking\\n\");\n        print_count_tracking_header(fcds_count_tracking,_tracking->cds_fpkm_tracking);\n        \n        // Read group tracking\n        \n        FILE* fiso_rep_tracking =  _outfiles->isoform_rep_tracking_out;\n        //fprintf(stderr, \"Writing isoform-level read group tracking\\n\");\n        print_read_group_tracking_header(fiso_rep_tracking,_tracking->isoform_fpkm_tracking);\n        \n        FILE* ftss_rep_tracking =  _outfiles->tss_group_rep_tracking_out;\n        //fprintf(stderr, \"Writing TSS group-level read group tracking\\n\");\n        print_read_group_tracking_header(ftss_rep_tracking,_tracking->tss_group_fpkm_tracking);\n        \n        FILE* fgene_rep_tracking =  _outfiles->gene_rep_tracking_out;\n        //fprintf(stderr, \"Writing gene-level read group tracking\\n\");\n        print_read_group_tracking_header(fgene_rep_tracking,_tracking->gene_fpkm_tracking);\n        \n        FILE* fcds_rep_tracking =  _outfiles->cds_rep_tracking_out;\n        //fprintf(stderr, \"Writing CDS-level read group tracking\\n\");\n        print_read_group_tracking_header(fcds_rep_tracking,_tracking->cds_fpkm_tracking);\n        \n        FILE* fread_group_info =  _outfiles->read_group_info_out;\n        //fprintf(stderr, \"Writing read group info\\n\");\n        print_read_group_cuffdiff_info(fread_group_info,_all_read_groups);\n        \n        FILE* frun_info =  _outfiles->run_info_out;\n        //fprintf(stderr, \"Writing run info\\n\");\n        print_run_info(frun_info);\n        \n    }\n    \n    void write_header_output_simple_table_format()\n    {\n        // FPKM tracking\n        \n        FILE* fiso_fpkm_tracking =  _outfiles->isoform_fpkm_tracking_out;\n        //fprintf(stderr, \"Writing isoform-level FPKM tracking\\n\");\n        print_FPKM_simple_table_header(fiso_fpkm_tracking,_tracking->isoform_fpkm_tracking);\n        \n        FILE* ftss_fpkm_tracking =  _outfiles->tss_group_fpkm_tracking_out;\n        //fprintf(stderr, \"Writing TSS group-level FPKM tracking\\n\");\n        print_FPKM_simple_table_header(ftss_fpkm_tracking,_tracking->tss_group_fpkm_tracking);\n        \n        FILE* fgene_fpkm_tracking =  _outfiles->gene_fpkm_tracking_out;\n        //fprintf(stderr, \"Writing gene-level FPKM tracking\\n\");\n        print_FPKM_simple_table_header(fgene_fpkm_tracking,_tracking->gene_fpkm_tracking);\n        \n        FILE* fcds_fpkm_tracking =  _outfiles->cds_fpkm_tracking_out;\n        //fprintf(stderr, \"Writing CDS-level FPKM tracking\\n\");\n        print_FPKM_simple_table_header(fcds_fpkm_tracking,_tracking->cds_fpkm_tracking);\n        \n        // Count tracking\n        \n        FILE* fiso_count_tracking =  _outfiles->isoform_count_tracking_out;\n        //fprintf(stderr, \"Writing isoform-level count tracking\\n\");\n        print_count_simple_table_header(fiso_count_tracking,_tracking->isoform_fpkm_tracking);\n        \n        FILE* ftss_count_tracking =  _outfiles->tss_group_count_tracking_out;\n        //fprintf(stderr, \"Writing TSS group-level count tracking\\n\");\n        print_count_simple_table_header(ftss_count_tracking,_tracking->tss_group_fpkm_tracking);\n        \n        FILE* fgene_count_tracking =  _outfiles->gene_count_tracking_out;\n        //fprintf(stderr, \"Writing gene-level count tracking\\n\");\n        print_count_simple_table_header(fgene_count_tracking,_tracking->gene_fpkm_tracking);\n        \n        FILE* fcds_count_tracking =  _outfiles->cds_count_tracking_out;\n        //fprintf(stderr, \"Writing CDS-level count tracking\\n\");\n        print_count_simple_table_header(fcds_count_tracking,_tracking->cds_fpkm_tracking);\n        \n        // We can also take care of all this metadata about samples and genes\n        FILE* fiso_attr =  _outfiles->isoform_attr_out;\n        //fprintf(stderr, \"Writing isoform-level attributes\\n\");\n        print_feature_attr_simple_table_header(fiso_attr,_tracking->isoform_fpkm_tracking);\n        \n        FILE* ftss_attr =  _outfiles->tss_group_attr_out;\n        //fprintf(stderr, \"Writing TSS group-level attributes\\n\");\n        print_feature_attr_simple_table_header(ftss_attr,_tracking->tss_group_fpkm_tracking);\n        \n        FILE* fgene_attr =  _outfiles->gene_attr_out;\n        //fprintf(stderr, \"Writing gene-level attributes\\n\");\n        print_feature_attr_simple_table_header(fgene_attr,_tracking->gene_fpkm_tracking);\n        \n        FILE* fcds_attr =  _outfiles->cds_attr_out;\n        //fprintf(stderr, \"Writing CDS-level attributes\\n\");\n        print_feature_attr_simple_table_header(fcds_attr,_tracking->cds_fpkm_tracking);\n        \n        FILE* fread_group_info =  _outfiles->read_group_info_out;\n        //fprintf(stderr, \"Writing read group info\\n\");\n        print_read_group_simple_table_info(fread_group_info,_all_read_groups);\n        \n        FILE* frun_info =  _outfiles->run_info_out;\n        //fprintf(stderr, \"Writing run info\\n\");\n        print_run_info(frun_info);\n        \n    }\n    \n    void write_output(const vector<boost::shared_ptr<SampleAbundances> >& abundances)\n    {\n        if (output_format == CUFFDIFF_OUTPUT_FMT)\n        {\n            write_cuffdiff_output(abundances);\n        }\n        else if (output_format == SIMPLE_TABLE_OUTPUT_FMT)\n        {\n            write_simple_table_output(abundances);\n        }\n        else{\n            fprintf(stderr, \"Error: unrecognized output format!\\n\");\n            exit(1);\n        }\n    }\n    \n    void write_header_output()\n    {\n        if (output_format == CUFFDIFF_OUTPUT_FMT)\n        {\n            write_header_output_cuffdiff_format();\n        }\n        else if (output_format == SIMPLE_TABLE_OUTPUT_FMT)\n        {\n            write_header_output_simple_table_format();\n        }\n        else{\n            fprintf(stderr, \"Error: unrecognized output format!\\n\");\n            exit(1);\n        }\n    }\n    \n    void write_cuffdiff_output(const vector<boost::shared_ptr<SampleAbundances> >& abundances)\n    {\n        const AbundanceGroup& ab_group = abundances.front()->transcripts;\n        //fprintf(stderr, \"[%d] count = %lg\\n\",i,  ab_group.num_fragments());\n        BOOST_FOREACH (boost::shared_ptr<Abundance> ab, ab_group.abundances())\n        {\n            int num_remaining = _id_to_locus_map->unregister_locus_from_id(ab->description(), ab->locus_tag());\n            if (num_remaining == 0)\n            {\n                print_FPKM_tracking(ab->description(), _outfiles->isoform_fpkm_tracking_out, _tracking->isoform_fpkm_tracking);\n                print_count_tracking(ab->description(), _outfiles->isoform_count_tracking_out, _tracking->isoform_fpkm_tracking);\n                print_read_group_tracking(ab->description(), _outfiles->isoform_rep_tracking_out, _tracking->isoform_fpkm_tracking);\n                remove_abundance_from_tracking_table(ab->description(), _tracking->isoform_fpkm_tracking);\n            }\n        }\n        \n        BOOST_FOREACH (AbundanceGroup& ab, abundances.front()->cds)\n        {\n            int num_remaining = _id_to_locus_map->unregister_locus_from_id(ab.description(), ab.locus_tag());\n            if (num_remaining == 0)\n            {\n                print_FPKM_tracking(ab.description(), _outfiles->cds_fpkm_tracking_out, _tracking->cds_fpkm_tracking);\n                print_count_tracking(ab.description(), _outfiles->cds_count_tracking_out, _tracking->cds_fpkm_tracking);\n                print_read_group_tracking(ab.description(), _outfiles->cds_rep_tracking_out, _tracking->cds_fpkm_tracking);\n                remove_abundance_from_tracking_table(ab.description(), _tracking->cds_fpkm_tracking);\n                \n            }\n        }\n        \n        BOOST_FOREACH (AbundanceGroup& ab, abundances.front()->primary_transcripts)\n        {\n            int num_remaining = _id_to_locus_map->unregister_locus_from_id(ab.description(), ab.locus_tag());\n            if (num_remaining == 0)\n            {\n                print_FPKM_tracking(ab.description(), _outfiles->tss_group_fpkm_tracking_out, _tracking->tss_group_fpkm_tracking);\n                print_count_tracking(ab.description(), _outfiles->tss_group_count_tracking_out, _tracking->tss_group_fpkm_tracking);\n                print_read_group_tracking(ab.description(), _outfiles->tss_group_rep_tracking_out, _tracking->tss_group_fpkm_tracking);\n                remove_abundance_from_tracking_table(ab.description(), _tracking->tss_group_fpkm_tracking);\n            }\n        }\n        \n        BOOST_FOREACH (AbundanceGroup& ab, abundances.front()->genes)\n        {\n            int num_remaining = _id_to_locus_map->unregister_locus_from_id(ab.description(), ab.locus_tag());\n            if (num_remaining == 0)\n            {\n                print_FPKM_tracking(ab.description(), _outfiles->gene_fpkm_tracking_out, _tracking->gene_fpkm_tracking);\n                print_count_tracking(ab.description(), _outfiles->gene_count_tracking_out, _tracking->gene_fpkm_tracking);\n                print_read_group_tracking(ab.description(), _outfiles->gene_rep_tracking_out, _tracking->gene_fpkm_tracking);\n                remove_abundance_from_tracking_table(ab.description(), _tracking->gene_fpkm_tracking);\n            }\n        }\n    }\n    \n    \n    void write_simple_table_output(const vector<boost::shared_ptr<SampleAbundances> >& abundances)\n    {\n        const AbundanceGroup& ab_group = abundances.front()->transcripts;\n        //fprintf(stderr, \"[%d] count = %lg\\n\",i,  ab_group.num_fragments());\n        BOOST_FOREACH (boost::shared_ptr<Abundance> ab, ab_group.abundances())\n        {\n            int num_remaining = _id_to_locus_map->unregister_locus_from_id(ab->description(), ab->locus_tag());\n            if (num_remaining == 0)\n            {\n                print_FPKM_simple_table(ab->description(), _outfiles->isoform_fpkm_tracking_out, _tracking->isoform_fpkm_tracking);\n                print_count_simple_table(ab->description(), _outfiles->isoform_count_tracking_out, _tracking->isoform_fpkm_tracking);\n                print_feature_attr_simple_table(ab->description(), _outfiles->isoform_attr_out, _tracking->isoform_fpkm_tracking);\n                remove_abundance_from_tracking_table(ab->description(), _tracking->isoform_fpkm_tracking);\n            }\n\n        }\n        \n        BOOST_FOREACH (AbundanceGroup& ab, abundances.front()->cds)\n        {\n            int num_remaining = _id_to_locus_map->unregister_locus_from_id(ab.description(), ab.locus_tag());\n            if (num_remaining == 0)\n            {\n                print_FPKM_simple_table(ab.description(), _outfiles->cds_fpkm_tracking_out, _tracking->cds_fpkm_tracking);\n                print_count_simple_table(ab.description(), _outfiles->cds_count_tracking_out, _tracking->cds_fpkm_tracking);\n                print_feature_attr_simple_table(ab.description(), _outfiles->cds_attr_out, _tracking->cds_fpkm_tracking);\n                remove_abundance_from_tracking_table(ab.description(), _tracking->cds_fpkm_tracking);\n            }\n\n        }\n        \n        BOOST_FOREACH (AbundanceGroup& ab, abundances.front()->primary_transcripts)\n        {\n            int num_remaining = _id_to_locus_map->unregister_locus_from_id(ab.description(), ab.locus_tag());\n            if (num_remaining == 0)\n            {\n                print_FPKM_simple_table(ab.description(), _outfiles->tss_group_fpkm_tracking_out, _tracking->tss_group_fpkm_tracking);\n                print_count_simple_table(ab.description(), _outfiles->tss_group_count_tracking_out, _tracking->tss_group_fpkm_tracking);\n                print_feature_attr_simple_table(ab.description(), _outfiles->tss_group_attr_out, _tracking->tss_group_fpkm_tracking);\n                remove_abundance_from_tracking_table(ab.description(), _tracking->tss_group_fpkm_tracking);\n            }\n        }\n        \n        BOOST_FOREACH (AbundanceGroup& ab, abundances.front()->genes)\n        {\n            int num_remaining = _id_to_locus_map->unregister_locus_from_id(ab.description(), ab.locus_tag());\n            if (num_remaining == 0)\n            {\n                print_FPKM_simple_table(ab.description(), _outfiles->gene_fpkm_tracking_out, _tracking->gene_fpkm_tracking);\n                print_count_simple_table(ab.description(), _outfiles->gene_count_tracking_out, _tracking->gene_fpkm_tracking);\n                print_feature_attr_simple_table(ab.description(), _outfiles->gene_attr_out, _tracking->gene_fpkm_tracking);\n                remove_abundance_from_tracking_table(ab.description(), _tracking->gene_fpkm_tracking);\n            }\n        }\n    }\n};\n\n\nextern double min_read_count;\n\nvoid sample_worker(bool non_empty,\n                   boost::shared_ptr<HitBundle> bundle,\n                   const RefSequenceTable& rt,\n                   ReplicatedBundleFactory& sample_factory,\n                   boost::shared_ptr<SampleAbundances> abundance,\n                   size_t factory_id,\n                   boost::shared_ptr<TestLauncher> launcher,\n                   bool calculate_variance);\n\nvoid test_differential(const string& locus_tag,\n\t\t\t\t\t   const vector<boost::shared_ptr<SampleAbundances> >& samples,\n                       const vector<pair<size_t, size_t> >& constrasts,\n\t\t\t\t\t   Tests& tests,\n\t\t\t\t\t   Tracking& tracking);\n\nvoid dump_locus_variance_info(const string& filename);\n\n#if ENABLE_THREADS\nvoid decr_pool_count();\nextern boost::mutex locus_thread_pool_lock;\nextern int locus_curr_threads;\nextern int locus_num_threads;\n#endif\n\n#endif\n\nvoid validate_cross_sample_parameters(const vector<boost::shared_ptr<ReadGroupProperties> >& all_read_groups);\n"
  },
  {
    "path": "src/filters.cpp",
    "content": "/*\n *  filters.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 10/27/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#include \"filters.h\"\n#include <algorithm>\n#include <numeric>\n#include <boost/graph/adjacency_list.hpp>\n#include <boost/graph/depth_first_search.hpp>\n#include <boost/graph/visitors.hpp>\n#include <boost/graph/graph_traits.hpp>\n#include <boost/graph/connected_components.hpp>\n\nusing namespace std;\nusing namespace boost;\n\nvoid filter_introns(int bundle_length,\n\t\t\t\t\tint bundle_left,\n\t\t\t\t\tvector<Scaffold>& hits, \n\t\t\t\t\tdouble fraction,\n\t\t\t\t\tbool filter_on_intron_overlap,\n\t\t\t\t\tbool filter_with_intron_doc)\n{\n\tvector<float> depth_of_coverage(bundle_length,0);\n\tvector<double> scaff_doc;\n\tmap<pair<int,int>, float> intron_doc;\n\tvector<Scaffold> filtered_hits;\n\tvector<bool> toss(hits.size(), false);\n\t\n\tdouble bundle_avg_doc = compute_doc(bundle_left, \n\t\t\t\t\t\t\t\t\t\thits, \n\t\t\t\t\t\t\t\t\t\tdepth_of_coverage, \n\t\t\t\t\t\t\t\t\t\tintron_doc,\n\t\t\t\t\t\t\t\t\t\tfalse);\n\t\n\tdouble bundle_avg_thresh = bundle_avg_doc * fraction;\n\t\n\tif (filter_with_intron_doc && !intron_doc.empty())\n\t{\n\t\tbundle_avg_doc = major_isoform_intron_doc(intron_doc);\n\t\tbundle_avg_thresh = fraction * bundle_avg_doc;\n\t\tverbose_msg(\"\\tFiltering bundle introns, avg (intron) doc = %lf, thresh = %f\\n\", bundle_avg_doc, bundle_avg_thresh);\n\t}\n\telse\n\t{\n\t\tverbose_msg(\"\\tFiltering bundle introns, avg bundle doc = %lf, thresh = %f\\n\", bundle_avg_doc, bundle_avg_thresh);\n\t}\n\t\n\tfor(map<pair<int, int>, float>::const_iterator itr = intron_doc.begin();\n\t\titr != intron_doc.end(); \n\t\t++itr)\n\t{\n\t\tfor (size_t j = 0; j < hits.size(); ++j)\n\t\t{\n\t\t\t//fprintf(stderr, \"considering read [%d-%d] with min doc = %lf contained in intron with doc = %lf\\n\", hits[j].left(), hits[j].right(), doc, idoc);\n\n\t\t\tif(hits[j].is_ref())\n\t\t\t\tcontinue;\n\n\t\t\tconst vector<AugmentedCuffOp>& ops = hits[j].augmented_ops();\n\t\t\t\n\t\t\tfor (size_t i = 0; i < ops.size(); ++i)\n\t\t\t{\n\t\t\t\tif (ops[i].opcode == CUFF_INTRON)\n\t\t\t\t{\n\t\t\t\t\tmap<pair<int, int>, float>::const_iterator itr;\n\t\t\t\t\titr = intron_doc.find(make_pair(ops[i].g_left(), ops[i].g_right()));\n\t\t\t\t\t\n\t\t\t\t\tdouble doc = itr->second;\n\t\t\t\t\tif (doc < bundle_avg_thresh)\n\t\t\t\t\t{\n\t\t\t\t\t\ttoss[j] = true;\n\t\t\t\t\t\tverbose_msg(\"\\t Filtering intron %d - %d: %f thresh %f\\n\", itr->first.first, itr->first.second, doc, bundle_avg_thresh);\n\t\t\t\t\t\tcontinue; \n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (!filter_on_intron_overlap)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\n\t\t\t\t\tfor (map<pair<int,int>, float>::const_iterator itr2 = intron_doc.begin();\n\t\t\t\t\t\t itr2 != intron_doc.end();\n\t\t\t\t\t\t ++itr2)\n\t\t\t\t\t{\t\n\t\t\t\t\t\tif (itr == itr2 ||\n\t\t\t\t\t\t\t!overlap_in_genome(itr->first.first,\n\t\t\t\t\t\t\t\t\t\t\t   itr->first.second,\n\t\t\t\t\t\t\t\t\t\t\t   itr2->first.first,\n\t\t\t\t\t\t\t\t\t\t\t   itr2->first.second))\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdouble thresh = itr2->second * fraction;\n\t\t\t\t\t\tif (doc < thresh)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tverbose_msg(\"\\t Filtering intron (due to overlap) %d - %d: %f thresh %f\\n\", itr->first.first, itr->first.second, doc, bundle_avg_thresh);\n\t\t\t\t\t\t\ttoss[j] = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tfor (size_t j = 0; j < hits.size(); ++j)\n\t{\t\n\t\tif (!toss[j])\n\t\t{\n\t\t\tfiltered_hits.push_back(hits[j]);\n//#if verbose_msg\n//\t\t\tif (hits[j].has_intron())\n//\t\t\t{\n//\t\t\t\tfprintf(stderr, \"KEEPING intron scaff [%d-%d]\\n\", hits[j].left(), hits[j].right());\n//\t\t\t}\n//#endif\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (hits[j].has_intron())\n\t\t\t{\n\t\t\t\t\n\t\t\t\tverbose_msg(\"\\tFiltering intron scaff [%d-%d]\\n\", hits[j].left(), hits[j].right());\n\t\t\t}\n\t\t}\n\t}\n\t\n\t\n\tverbose_msg(\"\\tIntron filtering pass finished: excluded %d fragments\\n\", (int)hits.size() - (int)filtered_hits.size());\n\thits = filtered_hits;\n}\n\ndouble background_rate(const vector<float> depth_of_coverage,\n                       int left, \n                       int right)\n{\n    vector<float> tmp;\n    \n    size_t r_bound = (size_t)min(right, (int) depth_of_coverage.size());\n    size_t l_bound = (size_t)max(left, 0);\n    \n    tmp.insert(tmp.end(), \n               depth_of_coverage.begin() + l_bound, \n               depth_of_coverage.begin() + r_bound);\n    \n    if (tmp.empty())\n        return 0;\n    \n    vector<float>::iterator new_end =  remove(tmp.begin(), tmp.end(), 0);\n    tmp.erase(new_end, tmp.end());\n    sort(tmp.begin(), tmp.end());\n    \n    size_t median = (size_t)floor(tmp.size() / 2);\n    double median_doc = tmp[median];\n    return median_doc;\n}\n\nvoid pre_mrna_filter(int bundle_length,\n\t\t\t\t\t int bundle_left,\n\t\t\t\t\t vector<Scaffold>& hits)\n{\n\tvector<float> depth_of_coverage(bundle_length,0);\n\tvector<double> scaff_doc;\n\tmap<pair<int,int>, float> intron_doc;\n\tvector<Scaffold> filtered_hits;\n\tvector<bool> toss(hits.size(), false);\n\tvector<float> through_introns; //for each location, how many introns pass through\n    \n\tvector<int> scaff_intron_status;\n\t// Make sure the avg only uses stuff we're sure isn't pre-mrna fragments\n    double bundle_avg_doc = compute_doc(bundle_left,\n\t\t\t\t\t\t\t\t\t\thits, \n\t\t\t\t\t\t\t\t\t\tdepth_of_coverage, \n\t\t\t\t\t\t\t\t\t\tintron_doc,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\t&through_introns,\n\t\t\t\t\t\t\t\t\t\t&scaff_intron_status);\n    verbose_msg(\"Pre-mRNA flt: bundle average doc = %lf\\n\", bundle_avg_doc);\n    /*\n     //2nd call not needed, the vectors won't change, only the return value\n     compute_doc(bundle_left, \n     hits, \n     depth_of_coverage, \n     intron_doc,\n     false);\n     */\n\trecord_doc_for_scaffolds(bundle_left, \n\t\t\t\t\t\t\t hits, \n\t\t\t\t\t\t\t depth_of_coverage, \n\t\t\t\t\t\t\t intron_doc,\n\t\t\t\t\t\t\t scaff_doc);\n    \n\tfor(map<pair<int, int>, float >::const_iterator itr = intron_doc.begin();\n\t\titr != intron_doc.end(); \n\t\t++itr)\n\t{\n\t\tint i_left = itr->first.first;\n\t\tint i_right = itr->first.second;\n\t\tint i_doc   = itr->second;\n        double intron_background = background_rate(depth_of_coverage,\n                                                   i_left - bundle_left,\n                                                   i_right - bundle_left);\n        double cumul_cov = 0;\n        for (int i = 0; i < i_right - i_left; ++i)\n        {\n            size_t pos = (i_left - bundle_left) + i;\n            cumul_cov += depth_of_coverage[pos];\n        }\n        cumul_cov /= i_right - i_left;\n        verbose_msg(\"Pre-mRNA flt: intron %d-%d : background: %lf, inner coverage: %lf, junction coverage: %f\\n\",\n                    i_left, i_right, intron_background, cumul_cov, i_doc);\n        if (cumul_cov / bundle_avg_doc >= pre_mrna_fraction)\n        {\n            //fprintf(stderr, \"\\tskipping\\n\");\n            continue;\n        }\n        \n        ////double thresh = (1.0/pre_mrna_fraction) * intron_background;\n        double thresh = pre_mrna_fraction * intron_background;\n        \n        \n        for (size_t j = 0; j < hits.size(); ++j)\n        {\n            if (hits[j].left()>i_right) break;\n            if (hits[j].is_ref())\n                continue;\n            if (toss[j])\n                continue;\n            //find maximum intron support in the hit region\n            \n            int len = 0;\n            double doc = 0.0;\n            size_t curr_op = 0;\n            const vector<AugmentedCuffOp>& ops = hits[j].augmented_ops();\n            while (curr_op != ops.size())\n            {\n                const AugmentedCuffOp&  op = ops[curr_op];\n                if (op.opcode == CUFF_MATCH)\n                {\n                    int op_len = 0;\n                    double op_doc = 0.0;\n                    int left_off = op.g_left();\n                    if (left_off + op.genomic_length > i_left && left_off < i_right)\n                    {\n                        if (left_off > i_left)\n                        {\n                            if (left_off + op.genomic_length <= i_right + 1)\n                            {\n                                op_len += op.genomic_length;\n                                int L = left_off - bundle_left;\n                                int R = L + op.genomic_length;\n                                op_doc += accumulate(depth_of_coverage.begin() + L, depth_of_coverage.begin() + R, 0.0);\n                            }\n                            else\n                            {\n                                op_len += i_right - left_off;\n                                int L = left_off - bundle_left;\n                                int R = L + (i_right - left_off);\n                                op_doc += accumulate(depth_of_coverage.begin() + L, depth_of_coverage.begin() + R, 0.0);\n                            }\n                        }\n                        else\n                        {\n                            if (left_off + op.genomic_length <= i_right + 1)\n                            {\n                                op_len += (left_off + op.genomic_length - i_left);\n                                int L = left_off - bundle_left;\n                                int R = L + (left_off + op.genomic_length - i_left);\n                                op_doc += accumulate(depth_of_coverage.begin() + L, depth_of_coverage.begin() + R, 0.0);\n                            }\n                            else\n                            {\n                                op_len = i_right - i_left;\n                                int L = left_off - bundle_left;\n                                int R = L + (i_right - i_left);\n                                op_doc = accumulate(depth_of_coverage.begin() + L, depth_of_coverage.begin() + R, 0.0);\n                            }\n                        }\n                    }\n                    \n                    len += op_len;\n                    doc += op_doc;\n                }\n                \n                if (op.g_left() >= i_right)\n                    break;\n                ++curr_op;\n            }\n            \n            if (len)\n            {\n                double hit_doc_in_region = doc / len;\n                if (hit_doc_in_region < thresh)\n                {\n                    toss[j] = true;\n                    if (hits[j].has_intron())\n                    {\n                        //    fprintf(stderr, \"\\t$$$ Filtering intron scaff [%d-%d]\\n\", hits[j].left(), hits[j].right());\n                        \n                        verbose_msg(\"\\t@@@ Filtering intron scaff [%d-%d] (scaff_doc=%lf, doc_in_region=%lf)\\n\",\n                                    hits[j].left(), hits[j].right(), scaff_doc[j], hit_doc_in_region);\n                    }\n                }\n            }\n\t\t} //for each scaffold\n\t} //for each intron\n\tfor (size_t j = 0; j < hits.size(); ++j)\n\t{\t\n\t\tif (!toss[j])\n\t\t{\n\t\t\tfiltered_hits.push_back(hits[j]);\n\t\t}\n\t\t/*else\n         {\n         if (hits[j].has_intron())\n         {\n         \n         verbose_msg( \"\\t@@@ Filtering intron scaff [%d-%d]\\n\", hits[j].left(), hits[j].right());\n         }\n         }\n         */\n\t}\n    \n\tif (cuff_verbose && hits.size()>filtered_hits.size())\n        verbose_msg(\"\\tPre-mRNA flt tossed %lu fragments\\n\", hits.size() - filtered_hits.size());\n\t\n\thits = filtered_hits;\n}\n\nvoid filter_hits(int bundle_length,\n\t\t\t\t int bundle_left,\n\t\t\t\t vector<Scaffold>& hits)\n{\n\t\n\tpre_mrna_filter(bundle_length, bundle_left, hits);\n\t\n\tvector<float> depth_of_coverage(bundle_length+1,0);\n\tvector<double> scaff_doc;\n\tmap<pair<int,int>, float> intron_doc;\n\tvector<Scaffold> filtered_hits;\n\tvector<bool> toss(hits.size(), false);\n\t\n\t// Make sure the avg only uses stuff we're sure isn't pre-mrna fragments\n\tdouble bundle_avg_doc = compute_doc(bundle_left, \n\t\t\t\t\t\t\t\t\t\thits, \n\t\t\t\t\t\t\t\t\t\tdepth_of_coverage, \n\t\t\t\t\t\t\t\t\t\tintron_doc,\n\t\t\t\t\t\t\t\t\t\ttrue);\n\t\n\t// recompute the real DoCs\n\t/* not needed, vectors are not changed\n\tcompute_doc(bundle_left, \n\t\t\t\thits, \n\t\t\t\tdepth_of_coverage, \n\t\t\t\tintron_doc,\n\t\t\t\tfalse);\n\t*/\n\t\n\trecord_min_doc_for_scaffolds(bundle_left, \n\t\t\t\t\t\t\t\t hits, \n\t\t\t\t\t\t\t\t depth_of_coverage, \n\t\t\t\t\t\t\t\t intron_doc,\n\t\t\t\t\t\t\t\t scaff_doc);\n\t\n\t//double bundle_avg_thresh = min_isoform_fraction * bundle_avg_doc;\n\t\n\tif (!intron_doc.empty())\n\t{\n\t\tdouble intron_avg_doc = major_isoform_intron_doc(intron_doc);\n\t\tdouble intron_multiplier = intron_avg_doc / bundle_avg_doc;\n\t\t\n\t\t// we don't want this to be more than 1.0 ...\n\t\tintron_multiplier = min(intron_avg_doc, 1.0);\n\t\t//bundle_avg_thresh = min_isoform_fraction * bundle_avg_doc;\n\t\t\n\t\tset<pair<int, int> > tossed_introns;\n\t\tfor(map<pair<int, int>, float>::const_iterator itr = intron_doc.begin();\n\t\t\titr != intron_doc.end(); \n\t\t\t++itr)\n\t\t{\n\t\t\tfor (size_t j = 0; j < hits.size(); ++j)\n\t\t\t{\n\t\t\t\tif (hits[j].is_ref())\n                {\n\t\t\t\t\tcontinue;\n                }\n\t\t\t\tint i_left = itr->first.first;\n\t\t\t\tint i_right = itr->first.second;\n\t\t\t\tint j_match_len = hits[j].match_length(i_left, i_right); \n\t\t\t\tif (j_match_len > 0)\n\t\t\t\t{\n\t\t\t\t\tdouble idoc = itr->second;\n\t\t\t\t\tdouble doc = scaff_doc[j];\n\t\t\t\t\t\n\t\t\t\t\tif (!hits[j].has_intron() && \n\t\t\t\t\t\tdoc < pre_mrna_fraction * (idoc * intron_multiplier))\n                    {\n\t\t\t\t\t\ttoss[j] = true;\n                    }\n\t\t\t\t\t\n\t\t\t\t\tconst vector<AugmentedCuffOp>& ops = hits[j].augmented_ops();\n\t\t\t\t\t\n\t\t\t\t\tunsigned int num_mismatches = 0;\n\t\t\t\t\tassert (hits[j].mate_hits().size() == 1);\n\t\t\t\t\tconst MateHit& hit = **(hits[j].mate_hits().begin());\n\t\t\t\t\tnum_mismatches = hit.edit_dist();\n\t\t\t\t\t\n\t\t\t\t\tdouble percent_mismatches = num_mismatches / (double)hits[j].length();\n\t\t\t\t\t\n\t\t\t\t\tbool intron_pokin_read = false;\n\t\t\t\t\t\n\t\t\t\t\tconst AugmentedCuffOp& first = ops.front();\n\t\t\t\t\t// intron                    =========================\n\t\t\t\t\t// hit                     ******************\n\t\t\t\t\tif (first.g_left() < i_left && first.g_right() > i_left  && first.g_right() < i_right)\n\t\t\t\t\t{\n\t\t\t\t\t\tintron_pokin_read = true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// intron          =========================\n\t\t\t\t\t// hit                      ******************\n\t\t\t\t\tif (first.g_left() < i_right && first.g_right() > i_right  && first.g_left() > i_left)\n\t\t\t\t\t{\n\t\t\t\t\t\tintron_pokin_read = true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tconst AugmentedCuffOp& last = ops.back();\n\t\t\t\t\t// intron          =========================\n\t\t\t\t\t// hit                     ******************\n\t\t\t\t\tif (last.g_left() < i_left && last.g_right() > i_left  && last.g_right() < i_right)\n\t\t\t\t\t{\n\t\t\t\t\t\tintron_pokin_read = true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// intron          =========================\n\t\t\t\t\t// hit                            ******************\n\t\t\t\t\tif (last.g_left() < i_right && last.g_right() > i_right  && last.g_left() > i_left)\n\t\t\t\t\t{\n\t\t\t\t\t\tintron_pokin_read = true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (intron_pokin_read)\n\t\t\t\t\t{\n\t\t\t\t\t\tdouble fraction;\n//\t\t\t\t\t\tif (!hits[j].has_intron())\n//\t\t\t\t\t\t{ \n//\t\t\t\t\t\t\tfraction = (3 * pre_mrna_fraction) + percent_mismatches;\n//\t\t\t\t\t\t}\n//\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfraction = pre_mrna_fraction + percent_mismatches;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdouble thresh = fraction * (intron_avg_doc * intron_multiplier);\n\t\t\t\t\t\tif (doc < thresh)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttoss[j] = true; \n//\t\t\t\t\t\t\tif (hits[j].has_intron())\n//\t\t\t\t\t\t\t{\n//\t\t\t\t\t\t\t\tfprintf(stderr, \"\\t^^^Filtering intron scaff [%d-%d]\\n\", hits[j].left(), hits[j].right());\n//\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tfor (size_t j = 0; j < hits.size(); ++j)\n\t{\t\n\t\tif (!toss[j])\n\t\t{\n\t\t\tfiltered_hits.push_back(hits[j]);\n//#if verbose_msg\n//\t\t\tif (hits[j].has_intron())\n//\t\t\t{\n//\t\t\t\t\n//\t\t\t\tfprintf(stderr, \"KEEPING intron scaff [%d-%d]\\n\", hits[j].left(), hits[j].right());\n//\t\t\t}\n//#endif\t\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (hits[j].has_intron())\n\t\t\t{\n\t\t\t\t\n\t\t\t\tverbose_msg(\"\\t!!!Filtering intron scaff [%d-%d]\\n\", hits[j].left(), hits[j].right());\n\t\t\t}\n\t\t}\n\t}\n\t\n//#if verbose_msg\n//\tfprintf(stderr, \"\\tInitial filter pass complete\\n\");\n//#endif\n\t\n\thits = filtered_hits;\n\t\n\tscaff_doc.clear();\n\tfiltered_hits.clear();\n\t\n\ttoss = vector<bool>(hits.size(), false);\n\t\n\tmap<pair<int, int>, float> dummy;\n\tbundle_avg_doc = compute_doc(bundle_left, \n\t\t\t\t\t\t\t\t hits, \n\t\t\t\t\t\t\t\t depth_of_coverage, \n\t\t\t\t\t\t\t\t dummy,\n\t\t\t\t\t\t\t\t false);\n\t\n//#if verbose_msg\n//\tfprintf(stderr, \"\\tUpdated avg bundle doc = %lf\\n\", bundle_avg_doc);\n//#endif\n\t\n\trecord_doc_for_scaffolds(bundle_left, \n\t\t\t\t\t\t\t hits, \n\t\t\t\t\t\t\t depth_of_coverage, \n\t\t\t\t\t\t\t intron_doc,\n\t\t\t\t\t\t\t scaff_doc);\n\t\n\t\n\t\n//#if verbose_msg\n//    double bundle_thresh = pre_mrna_fraction * bundle_avg_doc;\n//\tfprintf(stderr, \"\\tthreshold is = %lf\\n\", bundle_thresh);\n//#endif\n\t\n\tif (!intron_doc.empty())\n\t{\n//\t\tfilter_introns(bundle_length, \n//\t\t\t\t\t   bundle_left, \n//\t\t\t\t\t   hits, \n//\t\t\t\t\t   min_isoform_fraction, \n//\t\t\t\t\t   true,\n//\t\t\t\t\t   true);\n\t\tif (bundle_avg_doc > 3000)\n\t\t{\n\t\t\tfilter_introns(bundle_length, \n\t\t\t\t\t\t   bundle_left, \n\t\t\t\t\t\t   hits, \n\t\t\t\t\t\t   min_isoform_fraction, \n\t\t\t\t\t\t   true,\n\t\t\t\t\t\t   false);\n\t\t}\n\t}\n\t\n\tfor (size_t j = 0; j < hits.size(); ++j)\n\t{\t\n\t\tif (!toss[j])\n\t\t{\n\t\t\tfiltered_hits.push_back(hits[j]);\n//#if verbose_msg\n//\t\t\tif (hits[j].has_intron())\n//\t\t\t{\n//\t\t\t\t\n//\t\t\t\tfprintf(stderr, \"KEEPING intron scaff [%d-%d]\\n\", hits[j].left(), hits[j].right());\n//\t\t\t}\n//#endif\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (hits[j].has_intron())\n\t\t\t{\n\t\t\t\tverbose_msg(\"\\t***Filtering intron scaff [%d-%d]\\n\", hits[j].left(), hits[j].right());\n\t\t\t}\n\t\t}\n\t}\n\t\n\t//fprintf(stderr, \"\\tTossed %d hits as noise\\n\", (int)hits.size() - filtered_hits.size());\n\t\n\thits = filtered_hits;\n}\n\n\nvoid filter_junk_isoforms(vector<boost::shared_ptr<Abundance> >& transcripts,\n\t\t\t\t\t\t  vector<double>& abundances,\n                          const vector<boost::shared_ptr<Abundance> >& mapped_transcripts,\n                          double locus_mass)\n{\n\t//\tvector<double>::iterator max_ab = std::max_element(abundances.begin(),\n\t//\t\t\t\t\t\t\t\t\t\t\t\t\t   abundances.end());\n\tdouble max_fwd_ab = -1.0;\n\tdouble max_rev_ab = -1.0;\n\t\n\tfor (size_t t = 0; t < transcripts.size(); ++t)\n\t{\n\t\tboost::shared_ptr<Scaffold> scaff = transcripts[t]->transfrag();\n\t\tif (scaff->strand() == CUFF_FWD || scaff->strand() == CUFF_STRAND_UNKNOWN)\n\t\t{\n\t\t\tif (abundances[t] > max_fwd_ab)\n\t\t\t\tmax_fwd_ab = abundances[t];\n\t\t}\n\t\tif (scaff->strand() == CUFF_REV || scaff->strand() == CUFF_STRAND_UNKNOWN)\n\t\t{\t\t\t\n\t\t\tif (abundances[t] > max_rev_ab)\n\t\t\t\tmax_rev_ab = abundances[t];\n\t\t}\n\t}\n\t\n\t// Try to categorize the crap transcripts for suppression\n\tvector<bool> pre_mrna_junk(transcripts.size(), false); //intra-intron, much lower abundance than container\n\tvector<bool> chaff(transcripts.size(), false); // only a single MateHit, impossible to reliably quantitate\n\tvector<bool> repeats(transcripts.size(), false); // too many low-quality hits\n\tvector<bool> too_rare(transcripts.size(), false); // too rare to be reliably quantitated, could be error\n\t\n\t//cerr << \"Chucked : \";\n\tfor (size_t t = 0; t < transcripts.size(); ++t)\n\t{\n\t\tboost::shared_ptr<Scaffold> scaff = transcripts[t]->transfrag();\n        \n\t\tif (!(scaff->is_ref()) && allow_junk_filtering)\n\t\t{\n\t\t\tconst vector<const MateHit*> hits = scaff->mate_hits();\n\t\t\t\n\t\t\tconst vector<AugmentedCuffOp>& ops = scaff->augmented_ops();\n\t\t\t\n\t\t\tif (ops.size() == 1 && ops[0].opcode == CUFF_MATCH)\n\t\t\t{\n\t\t\t\tfor (size_t j = 0; j < transcripts.size(); ++j)\n\t\t\t\t{\n\t\t\t\t\tconst vector<AugmentedCuffOp>& j_ops = scaff->augmented_ops();\n\t\t\t\t\tfor (size_t L = 0; L < j_ops.size(); L++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (AugmentedCuffOp::overlap_in_genome(ops[0], j_ops[L]) &&\n\t\t\t\t\t\t\tj_ops[L].opcode == CUFF_INTRON)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpre_mrna_junk[t] = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n            if (library_type != \"transfrags\")\n            {\n                double multi_hits = 0.0;\n                //static const double low_qual_err_prob = high_phred_err_prob; // hits with error_prob() above this are low quality;\n                //static const double low_qual_thresh = 0.75; // hits with more than this fraction of low qual hits are repeats\n                for (vector<const MateHit*>::const_iterator itr = hits.begin();\n                     itr != hits.end();\n                     ++itr)\n                {\n                    if ((*itr)->is_multi())\n                        multi_hits += 1.0;\n                }\n            \n                double low_qual_frac = multi_hits / (double)hits.size();\n                if (low_qual_frac > max_multiread_fraction)\n                    repeats[t] = true;\n            }\n            if (scaff->strand() == CUFF_FWD &&\n                (abundances[t] / max_fwd_ab) < min_isoform_fraction)\n                too_rare[t] = true;\n            if ((scaff->strand() == CUFF_REV ||  scaff->strand() == CUFF_STRAND_UNKNOWN) &&\n                (abundances[t] / max_rev_ab) < min_isoform_fraction)\n                too_rare[t] = true;\n\n            const vector<double>* cond_probs = (mapped_transcripts[t]->cond_probs());\n            if (cond_probs)\n            {\n                assert (library_type != \"transfrags\");\n                double supporting_hits = abundances[t] * locus_mass;\n                if (supporting_hits < min_frags_per_transfrag)\n                    chaff[t] = true;\n            }\n\t\t}\n\t}\n\t\n\tvector<boost::shared_ptr<Abundance> > non_junk_transcripts;\n\tvector<double> non_junk_abundances;\n\tfor (size_t t = 0; t < transcripts.size(); ++t)\n\t{\n\t\tif (!repeats[t] && !pre_mrna_junk[t] && !too_rare[t] && !chaff[t])\n\t\t{\n\t\t\tnon_junk_transcripts.push_back(transcripts[t]);\n\t\t\tnon_junk_abundances.push_back(abundances[t]);\n\t\t}\n        else\n        {\n            verbose_msg( \"Filtering isoform %d-%d\\n\", transcripts[t]->transfrag()->left(), transcripts[t]->transfrag()->right());\n        }\n\t}\n\t\n\ttranscripts = non_junk_transcripts;\n\tabundances = non_junk_abundances;\n}\n\n// Designed to strip out remaining pre-mrna genes, assembled repeats, and \n// fragments from isoforms too short to be reliably quantitated.\nvoid filter_junk_genes(vector<Gene>& genes)\n{\n\tvector<Gene> good_genes;\n\tvector<Isoform> all_isoforms;\n\tfor (size_t i = 0; i < genes.size(); ++i)\n\t{\n\t\tall_isoforms.insert(all_isoforms.end(), \n\t\t\t\t\t\t\tgenes[i].isoforms().begin(), \n\t\t\t\t\t\t\tgenes[i].isoforms().end());\n\t}\n\t\n\tfor (size_t i = 0; i < genes.size(); ++i)\n\t{\n\t\tconst Gene& g = genes[i];\n\t\t\n\t\tif(g.has_ref_trans())\n\t\t{\n\t\t\tgood_genes.push_back(g);\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\tbool good_gene = true;\n\t\tfor (size_t j = 0; j < all_isoforms.size(); ++j)\n\t\t{\n\t\t\tvector<pair<int, int> > introns = all_isoforms[j].scaffold().gaps();\n            \n            //assert (!allow_junk_filtering || all_isoforms[j].scaffold().mate_hits().size() >= min_frags_per_transfrag);\n\t\t\tfor (size_t k = 0; k < introns.size(); ++k)\n\t\t\t{\n\t\t\t\tif (g.left() > introns[k].first && g.right() < introns[k].second &&\n\t\t\t\t\tg.FPKM() / all_isoforms[j].FPKM() < pre_mrna_fraction)\n\t\t\t\t{\n\t\t\t\t\tgood_gene = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n        if (allow_junk_filtering)\n        {\n            if (g.FPKM() == 0)\n            {\n                good_gene = false;\n            }\n        }\n\t\tif (good_gene)\n        {\n\t\t\tgood_genes.push_back(g);\n        }\n        else\n        {\n            verbose_msg(\"Filtering transfrags from gene %d-%d\\n\", g.left(), g.right());\n        }\n\t}\n\t\n\tgenes = good_genes;\n\t\n}\n\nvoid clip_by_3_prime_dropoff(vector<Scaffold>& scaffolds)\n{\n    vector<pair<double, Scaffold*> > three_prime_ends;\n    \n    if (library_type != \"transfrags\")\n    {\n        BOOST_FOREACH (Scaffold& scaff, scaffolds)\n        {\n            if (!(scaff.strand() == CUFF_FWD || scaff.strand() == CUFF_REV))\n                continue;\n\n            int scaff_len = scaff.length();\n            vector<double> coverage(scaff_len, 0.0);\n            \n            double total = 0;\n            BOOST_FOREACH(const MateHit* hit, scaff.mate_hits())\n            {\n                int start, end, frag_len;\n                if (!scaff.map_frag(*hit, start, end, frag_len)) continue;\n                \n                if (scaff.strand() == CUFF_REV)\n                {\n                    start = scaff_len - 1 - start;\n                    end = scaff_len - 1 - end;\n                    swap(start, end);\n                }\n                \n                for(int i = start; i <= end; ++i)\n                {\n                    coverage[i] += hit->mass();\n                    total += hit->mass();\n                }\n            }\n            double avg_cov = total/scaff_len;\n    //        if (avg_cov < trim_3_avgcov_thresh)\n    //            continue;\n            \n            const AugmentedCuffOp* exon_3 = NULL;\n            int mult;\n            int offset;\n            \n            if (scaff.strand() == CUFF_REV)\n            {\n                mult = 1;\n                offset = 0;\n                exon_3 = &scaff.augmented_ops().front(); //last exon at 3' end\n            }\n            else if (scaff.strand() == CUFF_FWD)\n            {\n                mult = -1;\n                offset = scaff_len - 1;\n                exon_3 = &scaff.augmented_ops().back();//last exon at 3' end\n            }\n            else\n            {\n                continue;\n            }\n\n            int to_remove;\n            double min_cost = numeric_limits<double>::max();\n            double mean_to_keep = 0.0;\n            double mean_to_trim = 0.0;\n            double tmp_mean_to_trim = 0.0;\n            double tmp_mean_to_keep = 0.0;\n            double tmp_mean_3prime = 0.0;\n            for (int i = 0; i < exon_3->genomic_length; i++)\n            {\n                tmp_mean_3prime += coverage[offset + mult*i];\n            }\n            tmp_mean_3prime /= exon_3->genomic_length;\n            \n            double base_cost = 0.0;\n            for (int i = 0; i < exon_3->genomic_length; i++)\n            {\n                double d = (coverage[offset + mult*i] - tmp_mean_3prime);\n                d *= d;\n                base_cost += d;\n            }\n            base_cost /= exon_3->genomic_length;\n            \n            size_t min_cost_x = -1;\n            for (to_remove = 1; to_remove < exon_3->genomic_length - 1; to_remove++)\n            {\n                tmp_mean_to_trim = 0.0;\n                tmp_mean_to_keep = 0.0;\n                for (int i = 0; i < exon_3->genomic_length; i++)\n                {\n                    if (i <= to_remove)\n                    {\n                        tmp_mean_to_trim += coverage[offset + mult*i];\n                    }\n                    else \n                    {\n                        tmp_mean_to_keep += coverage[offset + mult*i];\n                    }\n                }\n                \n                tmp_mean_to_trim /= to_remove;\n                tmp_mean_to_keep /= (exon_3->genomic_length - to_remove);\n                \n                double tmp_mean_trim_cost = 0.0;\n                double tmp_mean_keep_cost = 0.0;\n                for (int i = 0; i < exon_3->genomic_length; i++)\n                {\n                    if (i <= to_remove)\n                    {\n                        double d = (coverage[offset + mult*i] - tmp_mean_to_trim);\n                        d *= d;\n                        tmp_mean_trim_cost += d;\n                    }\n                    else \n                    {\n                        double d = (coverage[offset + mult*i] - tmp_mean_to_keep);\n                        d *= d;\n                        tmp_mean_keep_cost += d;\n                    }\n                }\n                \n                tmp_mean_trim_cost /= to_remove;\n                tmp_mean_keep_cost /= (exon_3->genomic_length - to_remove);\n                \n                double new_cost = tmp_mean_trim_cost + tmp_mean_keep_cost;\n                \n                if (new_cost < min_cost && trim_3_dropoff_frac * tmp_mean_to_keep > tmp_mean_to_trim && new_cost < base_cost && to_remove > scaff_len * 0.05)\n                {\n                    min_cost = tmp_mean_trim_cost + tmp_mean_keep_cost;\n                    min_cost_x = to_remove;\n                    mean_to_keep = tmp_mean_to_keep;\n                    mean_to_trim = tmp_mean_to_trim;\n                }\n            }\n            \n            // If trimming reduces the overall mean squared error of the coverage\n            // do it\n            if (avg_cov >= trim_3_avgcov_thresh && min_cost_x < exon_3->genomic_length)\n            {\n                scaff.trim_3(min_cost_x);\n            }\n            \n            // store the mean squared error for this exon\n            tmp_mean_3prime = 0.0;\n            for (int i = 0; i < exon_3->genomic_length; i++)\n            {\n                tmp_mean_3prime += coverage[offset + mult*i];\n            }\n            tmp_mean_3prime /= exon_3->genomic_length;\n            \n            base_cost = 0.0;\n            for (int i = 0; i < exon_3->genomic_length; i++)\n            {\n                double d = (coverage[offset + mult*i] - tmp_mean_3prime);\n                d *= d;\n                base_cost += d;\n            }\n            base_cost /= exon_3->genomic_length;\n            three_prime_ends.push_back(make_pair(base_cost, &scaff));\n        }\n    }\n    else\n    {\n        BOOST_FOREACH (Scaffold& scaff, scaffolds)\n        {\n            if (!(scaff.strand() == CUFF_FWD || scaff.strand() == CUFF_REV))\n                continue;\n            \n            int scaff_len = scaff.length();\n            vector<double> coverage(scaff_len, 0.0);\n            \n            double total = 0;\n            BOOST_FOREACH(const MateHit* hit, scaff.mate_hits())\n            {\n                int start, end, frag_len;\n                if (!scaff.map_frag(*hit, start, end, frag_len)) continue;\n                \n                if (scaff.strand() == CUFF_REV)\n                {\n                    start = scaff_len - 1 - start;\n                    end = scaff_len - 1 - end;\n                    swap(start, end);\n                }\n                \n                for(int i = start; i <= end; ++i)\n                {\n                    coverage[i] += hit->mass();\n                    total += hit->mass();\n                }\n            }\n            \n            const AugmentedCuffOp* exon_3 = NULL;\n            int mult;\n            int offset;\n            \n            if (scaff.strand() == CUFF_REV)\n            {\n                mult = 1;\n                offset = 0;\n                exon_3 = &scaff.augmented_ops().front();\n            }\n            else if (scaff.strand() == CUFF_FWD)\n            {\n                mult = -1;\n                offset = scaff_len - 1;\n                exon_3 = &scaff.augmented_ops().back();\n            }\n            else\n            {\n                continue;\n            }\n            \n            three_prime_ends.push_back(make_pair(scaff.fpkm(), &scaff));\n        }\n        \n    }\n    \n    adjacency_list <vecS, vecS, undirectedS> G;\n\t\n\tfor (size_t i = 0; i < three_prime_ends.size(); ++i)\n\t{\n\t\tadd_vertex(G);\n\t}\n\t\n\tfor (size_t i = 0; i < three_prime_ends.size(); ++i)\n\t{\n\t\tScaffold* scaff_i = three_prime_ends[i].second;\n\t\t//assert (scaff_i);\n\t\t\n        const AugmentedCuffOp* scaff_i_exon_3 = NULL;\n        \n        if (scaff_i->strand() == CUFF_REV)\n        {\n            scaff_i_exon_3 = &(scaff_i->augmented_ops().front());\n        }\n        else if (scaff_i->strand() == CUFF_FWD)\n        {\n            scaff_i_exon_3 = &(scaff_i->augmented_ops().back());\n        }\n        \n\t\tfor (size_t j = i + 1; j < three_prime_ends.size(); ++j)\n\t\t{\n\t\t\tScaffold* scaff_j = three_prime_ends[j].second;\n            \n            if (scaff_i->strand() != scaff_j->strand())\n                continue;\n            \n            const AugmentedCuffOp* scaff_j_exon_3 = NULL;\n            \n            if (scaff_j->strand() == CUFF_REV)\n            {\n                scaff_j_exon_3 = &(scaff_j->augmented_ops().front());\n            }\n            else if (scaff_j->strand() == CUFF_FWD)\n            {\n                scaff_j_exon_3 = &(scaff_j->augmented_ops().back());\n            }\n\t\t\t\n\t\t\tif (AugmentedCuffOp::overlap_in_genome(*scaff_j_exon_3, *scaff_i_exon_3) && \n                AugmentedCuffOp::compatible(*scaff_j_exon_3, *scaff_i_exon_3, 0))\n\t\t\t\tadd_edge(i, j, G);\n\t\t}\n\t}\n\t\n\tstd::vector<int> component(num_vertices(G));\n\tconnected_components(G, &component[0]);\n\t\n\tvector<vector<bool> > clusters(three_prime_ends.size(), \n\t\t\t\t\t\t\t\t   vector<bool>(three_prime_ends.size(), false));\n\t\n\t//vector<vector<size_t> > cluster_indices(three_prime_ends.size());\n    \n    vector<vector<pair<double, Scaffold*> > > grouped_scaffolds(three_prime_ends.size());\n\tfor (size_t i = 0; i < three_prime_ends.size(); ++i)\n\t{\n\t\tclusters[component[i]][i] = true;\n\t\tgrouped_scaffolds[component[i]].push_back(three_prime_ends[i]);\n\t}\n    \n    for (size_t i = 0; i < grouped_scaffolds.size(); ++i)\n    {\n        vector<pair<double, Scaffold*> >& group = grouped_scaffolds[i];\n        sort(group.begin(), group.end());\n        if (group.empty())\n            continue;\n        \n        Scaffold* group_leader = NULL;\n        int trim_point = -1;\n        \n        const AugmentedCuffOp* group_exon_3 = NULL;\n        vector<pair<double, Scaffold*> >::iterator l_itr = group.begin();\n        while (l_itr != group.end())\n        {\n            Scaffold* possible_leader = l_itr->second;\n            bool ok_clip_leader = true;\n            vector<pair<double, Scaffold*> >::iterator g_itr = group.begin();\n            const AugmentedCuffOp* l_exon_3 = NULL;\n            CuffStrand s = possible_leader->strand();\n\n            if (s != CUFF_STRAND_UNKNOWN)\n            {  \n                if (s == CUFF_REV)\n                    l_exon_3 = &(possible_leader->augmented_ops().front());\n                else \n                    l_exon_3 = &(possible_leader->augmented_ops().back());\n                for (; g_itr != group.end(); ++g_itr)\n                {\n                    const AugmentedCuffOp* g_exon_3 = NULL;\n                    if (s == CUFF_REV)\n                    {\n                        //  bad:\n                        //              leader  \n                        //    follower\n                        g_exon_3 = &(g_itr->second->augmented_ops().front());\n                        if (g_exon_3->g_right() <= l_exon_3->g_left())\n                            ok_clip_leader = false;\n                        \n                        // for meta-assembly libraries, don't ever allow clipping, just extension\n                        // bad:\n                        //             leader\n                        //         follower\n                        if (library_type == \"transfrags\" && \n                            g_exon_3->g_left() < l_exon_3->g_left())\n                            ok_clip_leader = false;\n                    }\n                    else \n                    {\n                        //  bad:\n                        //          follower  \n                        //  leader\n                        g_exon_3 = &(g_itr->second->augmented_ops().back());\n                        if (g_exon_3->g_left() >= l_exon_3->g_right())\n                            ok_clip_leader = false;\n                        \n                        // for meta-assembly libraries, don't ever allow clipping, just extension\n                        // bad:\n                        //             leader\n                        //                follower\n                        if (library_type == \"transfrags\" && \n                            g_exon_3->g_right() > l_exon_3->g_right())\n                            ok_clip_leader = false;\n                    }\n                }\n            }\n            else\n            {\n                ok_clip_leader = false;\n            }\n            \n            if (ok_clip_leader)\n            {\n                if (s == CUFF_REV)\n                {\n                    if (trim_point == -1)\n                        trim_point = l_exon_3->g_left();\n                    else if (l_exon_3->g_left() < trim_point)\n                        ok_clip_leader = false;\n                }\n                else \n                {\n                    if (trim_point == -1)\n                        trim_point = l_exon_3->g_right();\n                    else if (l_exon_3->g_right() > trim_point)\n                        ok_clip_leader = false;\n                }\n            }\n            \n            if (ok_clip_leader)\n            {\n                group_leader = possible_leader;\n                group_exon_3 = l_exon_3;\n                break;\n            }\n            ++l_itr;\n        }\n        \n        if (!group_leader || !group_exon_3)\n            continue;\n        \n        for (size_t j = 0; j < group.size(); ++j)\n        {\n            const AugmentedCuffOp* exon_3 = NULL;\n            int end_diff = 0;\n            if (group_leader->strand() == CUFF_REV)\n            {\n                exon_3 = &(group[j].second->augmented_ops().front());\n                end_diff = group_exon_3->g_left() - exon_3->g_left();\n            }\n            else \n            {\n                exon_3 = &(group[j].second->augmented_ops().back());                \n                end_diff = exon_3->g_right() - group_exon_3->g_right();\n            }\n            \n            if (end_diff > 0)\n            {\n                // leader\n                //     follower\n                group[j].second->trim_3(end_diff);\n            }\n            else if (end_diff < 0)\n            {\n                //        leader\n                //   follower\n                group[j].second->extend_3(-end_diff);\n            }\n        }\n    }\n    \n    \n\treturn;\n\t\n}\n"
  },
  {
    "path": "src/filters.h",
    "content": "#ifndef FILTERS_H\n#define FILTERS_H\n\n/*\n *  filters.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 10/27/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include \"scaffolds.h\"\n#include \"genes.h\"\n\nvoid filter_junk_isoforms(vector<boost::shared_ptr<Abundance> >& transcripts,\n\t\t\t\t\t\t  vector<double>& abundances,\n                          const vector<boost::shared_ptr<Abundance> >& mapped_transcripts,\n                          double locus_mass);\n\n\nvoid filter_introns(int bundle_length,\n\t\t\t\t\tint bundle_left,\n\t\t\t\t\tvector<Scaffold>& hits, \n\t\t\t\t\tdouble fraction,\n\t\t\t\t\tbool filter_on_intron_overlap,\n\t\t\t\t\tbool filter_with_intron_doc);\n\n// Designed to strip out remaining pre-mrna genes, assembled repeats, and \n// fragments from isoforms too short to be reliably quantitated.\nvoid filter_junk_genes(vector<Gene>& genes);\n\n\nvoid filter_hits(int bundle_length, int bundle_left, vector<Scaffold>& hits);\n\nvoid clip_by_3_prime_dropoff(vector<Scaffold>& scaff);\n\n#endif\n"
  },
  {
    "path": "src/gdna.cpp",
    "content": "#include \"gdna.h\"\n#include <string.h>\n\nconst char* IUPAC_2BIT  =\"AACCTTGGTTAAAAAACCCCGGAAAAAACCAAAAAA\";\nconst char* IUPAC_2BITN =\"001133223300000011112200000011000000\";\nconst char* IUPAC_DEFS  =\"AaCcTtGgUuMmRrWwSsYyKkVvHhDdBbNnXx-*\";\nconst char* IUPAC_COMP  =\"TtGgAaCcAaKkYyWwSsRrMmBbDdHhVvNnXx-*\";\n\n#define A_2BIT 0 // 00\n#define C_2BIT 1 // 01\n#define G_2BIT 2 // 10\n#define T_2BIT 3 // 11\n\nstatic byte ntCompTable[256];\nstatic byte nt2bit[256]; //maps any character to a 2bit base value (with N = A)\nstatic char v_2bit2nt[4] = {'A','C','G','T'};\n\n//----------------------\n\nstatic bool gdna_Ready=gDnaInit();\n\n//----------------------\n\nbyte gdna2bit(char* &nt, int n) {\n// Pack n bases into a byte (n can be 1..4)\nbyte out = 0;\nwhile (n && *nt) {\n    n--;\n    out <<= 2;\n    out += nt2bit[(int)*nt];\n    nt++;\n    }\n#ifdef GDEBUG\nif (n) {\n     GError(\"Error: attempt to read 6-mer beyond the end of the string!\\n\");\n     }\n#endif\nreturn out;\n}\n\n\nchar ntComplement(char c) {\n return ntCompTable[(int)c];\n }\n\nchar g2bit2base(byte v2bit) {\n return v_2bit2nt[v2bit & 0x03 ];\n}\n\n//in place reverse complement of nucleotide (sub)sequence\nchar* reverseComplement(char* seq, int slen) {\n   if (slen==0) slen=strlen(seq);\n   //reverseChars(seq,len);\n   int l=0;\n   int r=slen-1;\n   register char c;\n   while (l<r) {\n      c=seq[l];seq[l]=seq[r];\n      seq[r]=c;   //this was: Gswap(str[l],str[r]);\n      l++;r--;\n      }\n   for (int i=0;i<slen;i++) seq[i]=ntComplement(seq[i]);\n   return seq;\n }\n\nbool gDnaInit() {\n       if (gdna_Ready) return true;\n       int l=strlen(IUPAC_DEFS);\n       ntCompTable[0]=0;\n       nt2bit[0]=0;\n       for (int ch=1;ch<256;ch++) {\n          ntCompTable[ch]=0;\n          nt2bit[ch]=0;\n          for (int i=0;i<l;i++)\n                if (ch==IUPAC_DEFS[i]) {\n                  ntCompTable[ch]=IUPAC_COMP[i];\n                  nt2bit[ch] = IUPAC_2BITN[i]-'0';\n                  break;\n                  }\n          if (ntCompTable[ch]==0) {\n              ntCompTable[ch]='N';\n              }\n          }\n      gdna_Ready=true;\n      return true;\n     }\n\n\n\n\n"
  },
  {
    "path": "src/gdna.h",
    "content": "#ifndef GDNA_H\n#define GDNA_H\n#include \"GBase.h\"\n\nchar ntComplement(char c);\n\n//in-place reverse complement of a nucleotide (sub)sequence\nchar* reverseComplement(char* seq, int slen=0);\n\nbool gDnaInit();\n\nbyte gdna2bit(char* &nt, int n=4); //pack n bases into a byte (n can be 1..4)\nchar g2bit2base(byte v2bit); //convert the 2-bit value into 'A', 'C', 'G' or 'T'\n\n#endif\n"
  },
  {
    "path": "src/genes.cpp",
    "content": "/*\n *  genes.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 8/23/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n#include <boost/thread.hpp>\n#include \"genes.h\"\n\nusing namespace boost;\n\n#if ENABLE_THREADS\nboost::mutex gene_id_lock;\n#endif\n\nint next_isoform_id = 1;\n\nint get_next_isoform_id()\n{\n#if ENABLE_THREADS\n\tgene_id_lock.lock();\n#endif\n\tint next = next_isoform_id++;\n#if ENABLE_THREADS\n\tgene_id_lock.unlock();\n#endif\n\treturn next;\n}\n\nvoid Isoform::get_gtf(vector<string>& gff_recs, \n\t\t\t\t\t  const RefSequenceTable& rt,\n                      set<AugmentedCuffOp>* hit_introns) const\n{\n\tconst char* ref_name = rt.get_name(_scaffold.ref_id());\n\t\n    assert (ref_name != NULL);\n    \n\tconst char* strand_str = NULL;\n\tif (_scaffold.strand() == CUFF_STRAND_UNKNOWN)\n\t\tstrand_str = \".\";\n\telse if (_scaffold.strand() == CUFF_FWD)\n\t\tstrand_str = \"+\";\n\telse\n\t\tstrand_str = \"-\";\n\t\n\tint score = (int)(_FMI * 1000);\n\tscore = min(1000, score);\n\tif (score == 0)\n\t\tscore = 1;\n\t\n\tchar buf[2048];\t\n\n\tif (hit_introns != NULL)\n    {\n        sprintf(buf, \n\t\t\t\"%s\\tCufflinks\\ttranscript\\t%d\\t%d\\t%d\\t%s\\t.\\tgene_id \\\"%s\\\"; transcript_id \\\"%s\\\"; FPKM \\\"%10.10lf\\\"; frac \\\"%lf\\\"; conf_lo \\\"%lf\\\"; conf_hi \\\"%lf\\\"; cov \\\"%lf\\\"; full_read_support \\\"%s\\\";\\n\",\n\t\t\tref_name,\n\t\t\t_scaffold.left() + 1,\n\t\t\t_scaffold.right(), // GTF intervals are inclusive on both ends, but ours are half-open\n\t\t\tscore,\n\t\t\tstrand_str,\n\t\t\tgene_id().c_str(),\n\t\t\ttrans_id().c_str(),\n\t\t\t_FPKM,\n\t\t\t_fraction,\n\t\t\t_confidence.low, \n\t\t\t_confidence.high,\n\t\t\t_coverage,\n            (_scaffold.has_struct_support(*hit_introns)) ? \"yes\":\"no\");\n    }\n    else\n    {\n        sprintf(buf, \n                \"%s\\tCufflinks\\ttranscript\\t%d\\t%d\\t%d\\t%s\\t.\\tgene_id \\\"%s\\\"; transcript_id \\\"%s\\\"; FPKM \\\"%10.10lf\\\"; frac \\\"%lf\\\"; conf_lo \\\"%lf\\\"; conf_hi \\\"%lf\\\"; cov \\\"%lf\\\";\\n\",\n                ref_name,\n                _scaffold.left() + 1,\n                _scaffold.right(), // GTF intervals are inclusive on both ends, but ours are half-open\n                score,\n                strand_str,\n                gene_id().c_str(),\n                trans_id().c_str(),\n                _FPKM,\n                _fraction,\n                _confidence.low, \n                _confidence.high,\n                _coverage);\n    }\n    \n    \n\tgff_recs.push_back(buf);\n\t\n\tint exon_num = 1;\n\tfor (size_t op_id = 0; op_id < _scaffold.augmented_ops().size(); ++op_id)\n\t{\n\t\tconst AugmentedCuffOp& op = _scaffold.augmented_ops()[op_id];\n\t\tif (op.opcode == CUFF_MATCH || op.opcode == CUFF_UNKNOWN)\n\t\t{\n\t\t\tconst char* type = op.opcode == CUFF_MATCH ? \"exon\" : \"missing_data\";\n\t\t\t\n\t\t\tsprintf(buf, \n\t\t\t\t\t\"%s\\tCufflinks\\t\\%s\\t%d\\t%d\\t%d\\t%s\\t.\\tgene_id \\\"%s\\\"; transcript_id \\\"%s\\\"; exon_number \\\"%d\\\"; FPKM \\\"%10.10lf\\\"; frac \\\"%lf\\\"; conf_lo \\\"%lf\\\"; conf_hi \\\"%lf\\\"; cov \\\"%lf\\\";\\n\",\n\t\t\t\t\tref_name,\n\t\t\t\t\ttype,\n\t\t\t\t\top.g_left() + 1,\n\t\t\t\t\top.g_right(), // GTF intervals are inclusive on both ends, but ours are half-open\n\t\t\t\t\tscore,\n\t\t\t\t\tstrand_str,\n\t\t\t\t\tgene_id().c_str(),\n\t\t\t\t\ttrans_id().c_str(),\n\t\t\t\t\texon_num,\n\t\t\t\t\t_FPKM,\n\t\t\t\t\t_fraction,\n\t\t\t\t\t_confidence.low, \n\t\t\t\t\t_confidence.high,\n\t\t\t\t\t_coverage);\n\t\t\tgff_recs.push_back(buf);\n\t\t\t\n\t\t\texon_num++;\n\t\t}\n\t\t//gff_recs.push_back(buf);\n\t}\n\t\n}\n\n\nint next_gene_id = 1;\n\nint get_next_gene_id()\n{\n#if ENABLE_THREADS\n\tgene_id_lock.lock();\n#endif\n\tint next = next_gene_id++;\n#if ENABLE_THREADS\n\tgene_id_lock.unlock();\n#endif\n\treturn next;\n}\n\n\nint next_skipped_region_id = 1;\n\nint get_next_skipped_region_id()\n{\n#if ENABLE_THREADS\n\tgene_id_lock.lock();\n#endif\n\tint next = next_skipped_region_id++;\n#if ENABLE_THREADS\n\tgene_id_lock.unlock();\n#endif\n\treturn next;\n}\n"
  },
  {
    "path": "src/genes.h",
    "content": "#ifndef ISOFORM_H\n#define ISOFORM_H\n\n/*\n *  genes.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 8/23/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include \"scaffolds.h\"\n#include \"abundances.h\"\n#include \"common.h\"\n\nextern int next_isoform_id; \n\nint get_next_isoform_id();\n\nextern int next_gene_id; \n\nint get_next_gene_id();\n\nextern int next_skipped_region_id; \n\nint get_next_skipped_region_id();\n\nclass Isoform\n{\npublic:\n\tIsoform(const Scaffold& s,\n\t\t\tint gid,\n\t\t\tint tid,\n\t\t\tdouble FPKM = 0.0, \n\t\t\tdouble eff_len = 0.0,\n\t\t\tdouble fraction = 0.0,\n\t\t\tConfidenceInterval ci = ConfidenceInterval(),\n\t\t\tdouble cov = 0.0,\n            double est_frag_count = 0.0,\n\t\t\tdouble fmi = 0.0,\n\t\t\tAbundanceStatus status = NUMERIC_FAIL,\n\t\t\tstring ref_gene_id = \"\") :\n\t\t_scaffold(s),\n\t\t_FPKM(FPKM),\n\t\t_eff_len(eff_len),\n\t\t_fraction(fraction),\n\t\t_confidence(ci),\n\t\t_coverage(cov),\n        _estimated_count(est_frag_count),\n\t\t_FMI(fmi),\n\t\t_status(status)\n\t{\n\t\t_id = get_next_isoform_id();\n\t\t\n\t\tchar trans_id_str[256];\n\t\tif (_scaffold.annotated_trans_id() != \"\")\n\t\t\tstrncpy(trans_id_str, _scaffold.annotated_trans_id().c_str(), 255);\n\t\telse if (gid == -1)\n\t\t\tsprintf(trans_id_str, \"%s.%s.%d\", user_label.c_str(), ref_gene_id.c_str(), tid);\n\t\telse\n\t\t\tsprintf(trans_id_str, \"%s.%d.%d\", user_label.c_str(), gid, tid);\n\t\t\n\t\t_trans_id = trans_id_str;\n\t\t\n\t\tchar gene_id_str[256];\n\t\tif(gid == -1)\n\t\t\tstrncpy(gene_id_str, ref_gene_id.c_str(), 255);\n\t\telse\n\t\t\tsprintf(gene_id_str, \"%s.%d\", user_label.c_str(), gid);\n\t\t_gene_id = gene_id_str;\n\t}\n\t\n\tconst Scaffold& scaffold() const { return _scaffold; }\n\tdouble FPKM() const { return _FPKM; } \n\tvoid   FPKM(double fpkm) { _FPKM = fpkm; }\n\t\n\tdouble effective_length() const { return _eff_len; } \n\tvoid   effective_length(double eff_len) { _eff_len = eff_len; }\n\t\n\tAbundanceStatus status() const { return _status; } \n\tvoid   status(AbundanceStatus status) { _status = status; }\n\t\n\tdouble fraction() const {return _fraction; }\n\tvoid fraction(double f) { _fraction = f; }\n\t\n\tConfidenceInterval confidence() const { return _confidence; }\n\tvoid   confidence(ConfidenceInterval c) { _confidence = c; }\n\t\n\tdouble coverage() const { return _coverage; }\n\tvoid   coverage(double cov) { _coverage = cov; }\n\t\n\t// fraction of major isoform expression\n\tdouble FMI() const { return _FMI; }\n\tvoid   FMI(double fmi) { _FMI = fmi; }\n\t\n\tint ID() const { return _id; }\n\n\tvoid get_gtf(vector<string>& gtf_recs, \n\t\t\t\t const RefSequenceTable& rt,\n                 set<AugmentedCuffOp>* hit_introns=NULL) const;\n\t\n\tvoid gene_id(string& gid) { _gene_id = gid; }\n\tconst string& gene_id() const { return _gene_id; }\n\tconst string& trans_id() const {return _trans_id; }\n\t\n\tbool is_ref_trans() const { return _scaffold.is_ref(); }\n\t\n    double estimated_count() const { return _estimated_count; }\n    void estimated_count(double est) { _estimated_count = est; }\nprivate:\n\t\n\tScaffold _scaffold;\n\tdouble _FPKM;\n\tdouble _eff_len;\n\tdouble _fraction;\n\tConfidenceInterval _confidence;\n\tdouble _coverage;\n    double _estimated_count;\n\tdouble _FMI;\n\tint _id;\n\tstring _gene_id;\n\tstring _trans_id;\n\tAbundanceStatus _status;\n};\n\nclass Gene\n{\npublic:\n\tGene(const vector<Isoform>& isoforms, \n\t\t double FPKM = 0.0,\n\t\t const ConfidenceInterval& ci = ConfidenceInterval(),\n\t\t AbundanceStatus status=NUMERIC_FAIL) : \n\t\t_isoforms(isoforms), \n\t\t_FPKM(FPKM),\n\t\t_confidence(ci),\n\t\t_status(status)\n\t{\t\t\n\t\tvector<Scaffold> scaffolds;\n\t\tfor (size_t i = 0; i < isoforms.size(); ++i)\n\t\t\tscaffolds.push_back(isoforms[i].scaffold());\n\t\t\n\t\t// Now compute FPKM for the whole gene\n\t\tScaffold smashed_gene;\n\t\tScaffold::merge(scaffolds, smashed_gene, false);\n\t\t_left = smashed_gene.left();\n\t\t_right = smashed_gene.right();\n\t\t\n\t\t_gene_id = _isoforms.front().gene_id();\n\t}\n\t\n\tconst vector<Isoform>& isoforms() const { return _isoforms; }\n\tdouble FPKM() const { return _FPKM; } \n\t\n\tConfidenceInterval confidence() const { return _confidence; }\n\tvoid   confidence(ConfidenceInterval c) { _confidence = c; }\n\t\n\tAbundanceStatus status() const { return _status; }\n\tvoid   status(AbundanceStatus status) { _status = status; }\n\t\n\tint left() const { return _left; }\n\tint right() const { return _right; }\n\t\n\tconst string& gene_id() const { return _gene_id; }\n\t\n\tbool has_ref_trans() const\n\t{\n\t\tBOOST_FOREACH (const Isoform& iso, _isoforms)\n\t\t{\n\t\t\tif (iso.is_ref_trans())\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n    \n    double estimated_count() const \n    {\n        double est = 0.0;\n        BOOST_FOREACH (const Isoform& iso, _isoforms)\n\t\t{\n\t\t\test += iso.estimated_count(); \n\t\t}\n\t\treturn est;\n    }\n    \n    double effective_length() const \n    {\n        double eff = 0.0;\n        double total_fpkm = 0;\n        BOOST_FOREACH (const Isoform& iso, _isoforms)\n\t\t{\n\t\t\teff += iso.FPKM() * iso.effective_length();\n            total_fpkm += iso.FPKM();\n\t\t}\n        if (total_fpkm)\n            return eff / total_fpkm;\n\t\telse\n            return 0;\n    }\n\t\nprivate:\n\t\n\tvector<Isoform> _isoforms;\n\tdouble _FPKM;\n\tConfidenceInterval _confidence;\n\tint _id;\n\tint _left;\n\tint _right;\n\tstring _gene_id;\n\tAbundanceStatus _status;\n};\n\n#endif\n"
  },
  {
    "path": "src/gff.cpp",
    "content": "#include \"gff.h\"\n\nGffNames* GffObj::names=NULL;\n//global set of feature names, attribute names etc.\n// -- common for all GffObjs in current application!\n\nconst uint GFF_MAX_LOCUS = 7000000; //longest known gene in human is ~2.2M, UCSC claims a gene for mouse of ~ 3.1 M\nconst uint GFF_MAX_EXON  =   30000; //longest known exon in human is ~11K\nconst uint GFF_MAX_INTRON= 6000000; //Ensembl shows a >5MB human intron \nbool gff_show_warnings = false; //global setting, set by GffReader->showWarnings()\nconst int gff_fid_mRNA=0;\nconst int gff_fid_transcript=1;\nconst int gff_fid_exon=2;\n\nconst uint gfo_flag_HAS_ERRORS       = 0x00000001;\nconst uint gfo_flag_CHILDREN_PROMOTED= 0x00000002;\nconst uint gfo_flag_IS_GENE          = 0x00000004;\nconst uint gfo_flag_IS_TRANSCRIPT    = 0x00000008;\nconst uint gfo_flag_HAS_GFF_ID       = 0x00000010; //found GFF3 feature line with its own ID\nconst uint gfo_flag_BY_EXON          = 0x00000020; //created by subfeature (exon) directly\nconst uint gfo_flag_DISCARDED        = 0x00000100;\nconst uint gfo_flag_LST_KEEP         = 0x00000200;\nconst uint gfo_flag_LEVEL_MSK        = 0x00FF0000;\nconst byte gfo_flagShift_LEVEL           = 16;\n\nvoid gffnames_ref(GffNames* &n) {\n  if (n==NULL) n=new GffNames();\n  n->numrefs++;\n}\n\nvoid gffnames_unref(GffNames* &n) {\n  if (n==NULL) GError(\"Error: attempt to remove reference to null GffNames object!\\n\");\n  n->numrefs--;\n  if (n->numrefs==0) { delete n; n=NULL; }\n}\n\n\nconst char* strExonType(char xtype) {\n\tstatic const char* extbl[7]={\"None\", \"start_codon\", \"stop_codon\", \"CDS\", \"UTR\", \"CDS_UTR\", \"exon\"};\n\tif (xtype>0 && xtype<7)\n\t   return extbl[(int)xtype];\n\telse return \"NULL\";\n}\n\nint gfo_cmpByLoc(const pointer p1, const pointer p2) {\n GffObj& g1=*((GffObj*)p1);\n GffObj& g2=*((GffObj*)p2);\n if (g1.gseq_id==g2.gseq_id) {\n             if (g1.start!=g2.start)\n                    return (int)(g1.start-g2.start);\n               else if (g1.getLevel()!=g2.getLevel())\n                        return (int)(g1.getLevel()-g2.getLevel());\n                    else\n                        if (g1.end!=g2.end)\n                              return (int)(g1.end-g2.end);\n                        else return strcmp(g1.getID(), g2.getID());\n             }\n             else return (int)(g1.gseq_id-g2.gseq_id);\n}\n\nchar* GffLine::extractAttr(const char* attr, bool caseStrict, bool enforce_GTF2) {\n //parse a key attribute and remove it from the info string\n //(only works for attributes that have values following them after ' ' or '=')\n static const char GTF2_ERR[]=\"Error parsing attribute %s ('\\\"' required) at GTF line:\\n%s\\n\";\n int attrlen=strlen(attr);\n char cend=attr[attrlen-1];\n //char* pos = (caseStrict) ? strstr(info, attr) : strifind(info, attr);\n //must make sure attr is not found in quoted text\n char* pos=info;\n char prevch=0;\n bool in_str=false;\n bool notfound=true;\n int (*strcmpfn)(const char*, const char*, int) = caseStrict ? Gstrcmp : Gstricmp;\n while (notfound && *pos) {\n   char ch=*pos;\n   if (ch=='\"') {\n     in_str=!in_str;\n     pos++;\n     prevch=ch;\n     continue;\n     }\n   if (!in_str && (prevch==0 || prevch==' ' || prevch == ';')\n          && strcmpfn(attr, pos, attrlen)==0) {\n      //attr match found\n      //check for word boundary on right\n      char* epos=pos+attrlen;\n      if (cend=='=' || cend==' ' || *epos==0 || *epos==' ') {\n        notfound=false;\n        break;\n        }\n      //not a perfect match, move on\n      pos=epos;\n      prevch=*(pos-1);\n      continue;\n      }\n   //not a match or in_str\n   prevch=ch;\n   pos++;\n   }\n if (notfound) return NULL;\n char* vp=pos+attrlen;\n while (*vp==' ') vp++;\n if (*vp==';' || *vp==0)\n      GError(\"Error parsing value of GFF attribute \\\"%s\\\", line:\\n%s\\n\", attr, dupline);\n bool dq_enclosed=false; //value string enclosed by double quotes\n if (*vp=='\"') {\n     dq_enclosed=true;\n     vp++;\n     }\n if (enforce_GTF2 && !dq_enclosed)\n      GError(GTF2_ERR,attr, dupline);\n char* vend=vp;\n if (dq_enclosed) {\n    while (*vend!='\"' && *vend!=';' && *vend!=0) vend++;\n    }\n else {\n    while (*vend!=';' && *vend!=0) vend++;\n    }\n if (enforce_GTF2 && *vend!='\"')\n     GError(GTF2_ERR, attr, dupline);\n char *r=Gstrdup(vp, vend-1);\n //-- now remove this attribute from the info string\n while (*vend!=0 && (*vend=='\"' || *vend==';' || *vend==' ')) vend++;\n if (*vend==0) vend--;\n for (char *src=vend, *dest=pos;;src++,dest++) {\n   *dest=*src;\n   if (*src==0) break;\n   }\n return r;\n}\n\n\n\nGffLine::GffLine(GffReader* reader, const char* l):_parents(NULL), _parents_len(0),\n\t\tdupline(NULL), line(NULL), llen(0), gseqname(NULL), track(NULL),\n\t\tftype(NULL), info(NULL), fstart(0), fend(0), qstart(0), qend(0), qlen(0),\n\t\tscore(0), strand(0), flags(0), exontype(0), phase(0),\n\t\tgene_name(NULL), gene_id(NULL),\n\t\tparents(NULL), num_parents(0), ID(NULL) {\n llen=strlen(l);\n GMALLOC(line,llen+1);\n memcpy(line, l, llen+1);\n GMALLOC(dupline, llen+1);\n memcpy(dupline, l, llen+1);\n skipLine=1; //reset only if it reaches the end of this function\n char* t[9];\n int i=0;\n int tidx=1;\n t[0]=line;\n char fnamelc[128];\n while (line[i]!=0) {\n  if (line[i]=='\\t') {\n   line[i]=0;\n   t[tidx]=line+i+1;\n   tidx++;\n   if (tidx>8) break;\n   }\n  i++;\n  }\n\n if (tidx<8) { // ignore non-GFF lines\n  // GMessage(\"Warning: error parsing GFF/GTF line:\\n%s\\n\", l);\n  return;\n  }\n gseqname=t[0];\n track=t[1];\n ftype=t[2];\n info=t[8];\n char* p=t[3];\n if (!parseUInt(p,fstart)) {\n   //chromosome_band entries in Flybase\n   GMessage(\"Warning: invalid start coordinate at line:\\n%s\\n\",l);\n   return;\n   }\n p=t[4];\n if (!parseUInt(p,fend)) {\n   GMessage(\"Warning: invalid end coordinate at line:\\n%s\\n\",l);\n   return;\n   }\n if (fend<fstart) Gswap(fend,fstart); //make sure fstart>=fend, always\n p=t[5];\n if (p[0]=='.' && p[1]==0) {\n  score=0;\n  }\n else {\n  if (!parseDouble(p,score))\n       GError(\"Error parsing feature score from GFF line:\\n%s\\n\",l);\n  }\n strand=*t[6];\n if (strand!='+' && strand!='-' && strand!='.')\n     GError(\"Error parsing strand (%c) from GFF line:\\n%s\\n\",strand,l);\n phase=*t[7]; // must be '.', '0', '1' or '2'\n // exon/CDS/mrna filter\n strncpy(fnamelc, ftype, 127);\n fnamelc[127]=0;\n strlower(fnamelc); //convert to lower case\n bool is_t_data=false;\n if (strstr(fnamelc, \"utr\")!=NULL) {\n\t exontype=exgffUTR;\n\t is_exon=true;\n\t is_t_data=true;\n }\n else if (endsWith(fnamelc, \"exon\")) {\n\t exontype=exgffExon;\n\t is_exon=true;\n\t is_t_data=true;\n }\n else if (strstr(fnamelc, \"stop\") &&\n\t\t (strstr(fnamelc, \"codon\") || strstr(fnamelc, \"cds\"))){\n\t exontype=exgffStop;\n\t is_cds=true; //though some place it outside the last CDS segment\n\t is_t_data=true;\n }\n else if (strstr(fnamelc, \"start\") &&\n\t\t ((strstr(fnamelc, \"codon\")!=NULL) || strstr(fnamelc, \"cds\")!=NULL)){\n\t exontype=exgffStart;\n\t is_cds=true;\n\t is_t_data=true;\n }\n else if (strcmp(fnamelc, \"cds\")==0) {\n\t exontype=exgffCDS;\n\t is_cds=true;\n\t is_t_data=true;\n }\n else if (startsWith(fnamelc, \"intron\") || endsWith(fnamelc, \"intron\")) {\n\t exontype=exgffIntron;\n }\n else if (endsWith(fnamelc,\"rna\") || endsWith(fnamelc,\"transcript\")) { // || startsWith(fnamelc+1, \"rna\")) {\n\t is_transcript=true;\n\t is_t_data=true;\n }\n else if (endsWith(fnamelc, \"gene\") || startsWith(fnamelc, \"gene\")) {\n\t is_gene=true;\n\t is_t_data=true; //because its name will be attached to parented transcripts\n }\n\n ID=extractAttr(\"ID=\",true);\n if (reader->transcriptsOnly && !is_t_data) {\n\t //can_discard=1;\n\t if (ID!=NULL) {\n\t\t //ban GFF3 parent if not recognized as transcript\n\t\t reader->discarded_ids.Add(ID, new int(1));\n\t\t GFREE(ID);\n\t }\n\t //skip non-transcript recognized features\n\t return;\n }\n char* Parent=extractAttr(\"Parent=\",true);\n is_gff3=(ID!=NULL || Parent!=NULL);\n if (is_gff3) {\n\t //parse as GFF3\n\t if (ID!=NULL) {\n\t\t //has ID attr so it's likely to be a parent feature\n\t\t //look for explicit gene name\n\t\t gene_name=extractAttr(\"gene_name=\");\n\t\t if (gene_name==NULL) {\n\t\t\t gene_name=extractAttr(\"geneName=\");\n\t\t\t if (gene_name==NULL) {\n\t\t\t\t gene_name=extractAttr(\"gene_sym=\");\n\t\t\t\t if (gene_name==NULL) {\n\t\t\t\t\t gene_name=extractAttr(\"gene=\");\n\t\t\t\t }\n\t\t\t }\n\t\t }\n\t\t gene_id=extractAttr(\"geneID=\");\n\t\t if (gene_id==NULL) {\n\t\t\t gene_id=extractAttr(\"gene_id=\");\n\t\t }\n\t\t if (is_gene) { //WARNING: this might be mislabeled (e.g. TAIR: \"mRNA_TE_gene\")\n\t\t\t //special case: keep the Name and ID attributes of the gene feature\n\t\t\t if (gene_name==NULL)\n\t\t\t\t gene_name=extractAttr(\"Name=\");\n\t\t\t if (gene_id==NULL) //the ID is also gene_id in this case\n\t\t\t\t gene_id=Gstrdup(ID);\n\t\t\t //skip=false;\n\t\t\t //return;\n\t\t\t //-- we don't care about gene parents.. unless it's a mislabeled \"gene\" feature\n\t\t\t //GFREE(Parent);\n\t\t } //gene feature (probably)\n\t }// has GFF3 ID\n\t if (Parent!=NULL) {\n\t\t //keep Parent attr\n\t\t //parse multiple parents\n\t\t num_parents=1;\n\t\t p=Parent;\n\t\t int last_delim_pos=-1;\n\t\t while (*p!=';' && *p!=0) {\n\t\t\t if (*p==',' && *(p+1)!=0 && *(p+1)!=';') {\n\t\t\t\t num_parents++;\n\t\t\t\t last_delim_pos=(p-Parent);\n\t\t\t }\n\t\t\t p++;\n\t\t }\n\t\t _parents_len=p-Parent+1;\n\t\t _parents=Parent;\n\t\t GMALLOC(parents, num_parents*sizeof(char*));\n\t\t parents[0]=_parents;\n\t\t int i=1;\n\t\t if (last_delim_pos>0) {\n\t\t\t for (p=_parents+1;p<=_parents+last_delim_pos;p++) {\n\t\t\t\t if (*p==',') {\n\t\t\t\t\t char* ep=p-1;\n\t\t\t\t\t while (*ep==' ' && ep>_parents) ep--;\n\t\t\t\t\t *(ep+1)=0; //end the string there\n\t\t\t\t\t parents[i]=p+1;\n\t\t\t\t\t i++;\n\t\t\t\t }\n\t\t\t }\n\t\t }\n\t } //has Parent field\n } //GFF3\n else { // GTF-like expected\n\t if (reader->transcriptsOnly && !is_t_data) {\n\t\t return; //skipping unrecognized non-transcript feature\n\t }\n\t Parent=extractAttr(\"transcript_id\",true);\n\t if (Parent!=NULL) { //GTF2 format detected\n\t\t if (is_transcript) {\n\t\t\t // atypical GTF with a parent transcript line declared\n\t\t\t ID=Parent;\n\t\t\t Parent=NULL;\n\t\t }\n\t\t gene_id=extractAttr(\"gene_id\"); // for GTF this is the only attribute accepted as geneID\n\t\t if (gene_id==NULL)\n\t\t\t gene_id=extractAttr(\"geneid\");\n\t\t gene_name=extractAttr(\"gene_name\");\n\t\t if (gene_name==NULL) {\n\t\t\t gene_name=extractAttr(\"gene_sym\");\n\t\t\t if (gene_name==NULL) {\n\t\t\t\t gene_name=extractAttr(\"gene\");\n\t\t\t\t if (gene_name==NULL)\n\t\t\t\t\t gene_name=extractAttr(\"genesymbol\");\n\t\t\t }\n\t\t }\n\t\t //prepare for parseAttr by adding '=' character instead of spaces for all attributes\n\t\t //after the attribute name\n\t\t p=info;\n\t\t bool noed=true; //not edited after the last delim\n\t\t bool nsp=false; //non-space found after last delim\n\t\t while (*p!=0) {\n\t\t\t if (*p==' ') {\n\t\t\t\t if (nsp && noed) {\n\t\t\t\t\t *p='=';\n\t\t\t\t\t noed=false;\n\t\t\t\t\t p++;\n\t\t\t\t\t continue;\n\t\t\t\t }\n\t\t\t }\n\t\t\t else nsp=true; //non-space\n\t\t\t if (*p==';') { noed=true; nsp=false; }\n\t\t\t p++;\n\t\t }\n\t } //GTF2 detected (no parent line)\n\t else {// Parent is NULL, check for jigsaw format or other pre-GTF2 format\n\t\t //char* fexon=strstr(fnamelc, \"exon\");\n\t\t //if (fexon!=NULL) {\n\t\t if (exontype==exgffExon) {\n\t\t\t if (startsWith(track,\"jigsaw\")) {\n\t\t\t\t is_cds=true;\n\t\t\t\t strcpy(track,\"jigsaw\");\n\t\t\t\t p=strchr(info,';');\n\t\t\t\t if (p==NULL) { Parent=Gstrdup(info); info=NULL; }\n\t\t\t\t else { Parent=Gstrdup(info,p-1);\n\t\t\t\t info=p+1;\n\t\t\t\t }\n\t\t\t }\n\t\t } //exon feature?\n\t\t if (Parent==NULL) {\n\t\t    //something is very wrong here, cannot parse the GTF ID\n\t\t\t if (is_transcript || exontype)\n\t\t       GMessage(\"Warning: invalid GTF record, transcript_id not found:\\n%s\\n\",\n\t\t       l);\n\t\t\t else return; //skip unrecognized GTF line (from GTF we only care about transcripts for now)\n\n\t\t }\n\t } //Parent was NULL, attempted to find it\n\t if (Parent!=NULL) { //GTF transcript_id for exon/CDS feature\n\t\t _parents=Parent;\n\t\t GMALLOC(parents,sizeof(char*));\n\t\t num_parents=1;\n\t\t parents[0]=_parents;\n\t }\n } //GTF-like\n\n //parse other potentially useful features\n if (is_gff3) {\n\t if ((p=strstr(info,\"Target=\"))!=NULL) { //has Target attr\n\t\t p+=7;\n\t\t while (*p!=';' && *p!=0 && *p!=' ') p++;\n\t\t if (*p!=' ') {\n\t\t\t GError(\"Error parsing target coordinates from GFF line:\\n%s\\n\",l);\n\t\t }\n\t\t if (!parseUInt(p,qstart))\n\t\t\t GError(\"Error parsing target start coordinate from GFF line:\\n%s\\n\",l);\n\t\t if (*p!=' ') {\n\t\t\t GError(\"Error parsing next target coordinate from GFF line:\\n%s\\n\",l);\n\t\t }\n\t\t p++;\n\t\t if (!parseUInt(p,qend))\n\t\t\t GError(\"Error parsing target end coordinate from GFF line:\\n%s\\n\",l);\n\t }\n\t if ((p=strifind(info,\"Qreg=\"))!=NULL) { //has Qreg attr\n\t\t p+=5;\n\t\t if (!parseUInt(p,qstart))\n\t\t\t GError(\"Error parsing target start coordinate from GFF line:\\n%s\\n\",l);\n\t\t if (*p!='-') {\n\t\t\t GError(\"Error parsing next target coordinate from GFF line:\\n%s\\n\",l);\n\t\t }\n\t\t p++;\n\t\t if (!parseUInt(p,qend))\n\t\t\t GError(\"Error parsing target end coordinate from GFF line:\\n%s\\n\",l);\n\t\t if (*p=='|' || *p==':') {\n\t\t\t p++;\n\t\t\t if (!parseUInt(p,qlen))\n\t\t\t\t GError(\"Error parsing target length from GFF Qreg|: \\n%s\\n\",l);\n\t\t }\n\t }//has Qreg attr\n\t if (qlen==0 && (p=strifind(info,\"Qlen=\"))!=NULL) {\n\t\t p+=5;\n\t\t if (!parseUInt(p,qlen))\n\t\t\t GError(\"Error parsing target length from GFF Qlen:\\n%s\\n\",l);\n\t }\n }//parsing some useful attributes in GFF3 records\n if (ID==NULL && parents==NULL) {\n\t if (reader->gff_warns)\n\t\t GMessage(\"Warning: could not parse ID or Parent from GFF line:\\n%s\\n\",dupline);\n\t return; //skip\n }\n skipLine=0;\n}\n\n\nvoid GffObj::addCDS(uint cd_start, uint cd_end, char phase) {\n  if (cd_start>=this->start) {\n        this->CDstart=cd_start;\n        if (strand=='+') this->CDphase=phase;\n        }\n      else this->CDstart=this->start;\n  if (cd_end<=this->end) {\n      this->CDend=cd_end;\n      if (strand=='-') this->CDphase=phase;\n      }\n     else this->CDend=this->end;\n  isTranscript(true);\n  exon_ftype_id=gff_fid_exon;\n  if (monoFeature()) {\n     if (exons.Count()==0) addExon(this->start, this->end,0,'.',0,0,false,exgffExon);\n            else exons[0]->exontype=exgffExon;\n     }\n}\n\nint GffObj::addExon(GffReader* reader, GffLine* gl, bool keepAttr, bool noExonAttr) {\n  //this will make sure we have the right subftype_id!\n  //int subf_id=-1;\n  if (!isTranscript() && gl->is_cds) {\n          isTranscript(true);\n          exon_ftype_id=gff_fid_exon;\n          if (exons.Count()==1) exons[0]->exontype=exgffExon;\n          }\n  if (isTranscript()) {\n     if (exon_ftype_id<0) {//exon_ftype_id=gff_fid_exon;\n          if (gl->exontype>0) exon_ftype_id=gff_fid_exon;\n                         else exon_ftype_id=names->feats.addName(gl->ftype);\n          }\n     //any recognized mRNA segment gets the generic \"exon\" type (also applies to CDS)\n     if (gl->exontype==0 && !gl->is_transcript) {\n          //extraneous mRNA feature, discard\n          if (reader->gff_warns)\n            GMessage(\"Warning: discarding unrecognized transcript subfeature '%s' of %s\\n\",\n                gl->ftype, gffID);\n          return -1;\n          }\n     }\n  else { //non-mRNA parent feature, check this subf type\n    int subf_id=names->feats.addName(gl->ftype);\n    if (exon_ftype_id<0 || exons.Count()==0) //never assigned a subfeature type before (e.g. first exon being added)\n       exon_ftype_id=subf_id;\n     else {\n       if (exon_ftype_id!=subf_id) {\n         //\n         if (exon_ftype_id==ftype_id && exons.Count()==1 && exons[0]->start==start && exons[0]->end==end) {\n            //the existing exon was just a dummy one created by default, discard it\n            exons.Clear();\n            covlen=0;\n            exon_ftype_id=subf_id; //allow the new subfeature to completely takeover\n            }\n         else { //multiple subfeatures, prefer those with \n             if (reader->gff_warns)\n               GMessage(\"GFF Warning: multiple subfeatures (%s and %s) found for %s, discarding \", \n                  names->feats.getName(subf_id), names->feats.getName(exon_ftype_id),gffID);\n            if (gl->exontype!=0) { //new feature is an exon, discard previously parsed subfeatures\n               if (reader->gff_warns) GMessage(\"%s.\\n\", names->feats.getName(exon_ftype_id));\n               exon_ftype_id=subf_id;\n               exons.Clear();\n               covlen=0;\n               }\n              else { //discard new feature\n               if (reader->gff_warns) GMessage(\"%s.\\n\", names->feats.getName(subf_id));\n               return -1; //skip this 2nd subfeature type for this parent!\n               }\n            }\n         } //incoming subfeature is of different type\n       } //new subfeature type\n    } //non-mRNA parent\n  int eidx=addExon(gl->fstart, gl->fend, gl->score, gl->phase,\n         gl->qstart,gl->qend, gl->is_cds, gl->exontype);\n  if (eidx<0) return eidx; //this should never happen\n  if (keepAttr) {\n     if (noExonAttr) { \n         if (attrs==NULL) //place the parsed attributes directly at transcript level\n           parseAttrs(attrs, gl->info);\n         }\n       else { //need all exon-level attributes\n         parseAttrs(exons[eidx]->attrs, gl->info, true);\n         }\n      }\n  return eidx;\n}\n\n\nint GffObj::addExon(uint segstart, uint segend, double sc, char fr, int qs, int qe, bool iscds, char exontype) {\n  if (exons.Count()==0) {\n      if (iscds) isCDS=true; //for now, assume CDS only if first \"exon\" given is a CDS\n      if (exon_ftype_id<0) {\n         exon_ftype_id = isTranscript() ? gff_fid_exon : ftype_id;\n         }\n      }\n  //special treatment of start/stop codon features, they might be broken/split between exons \n  //and in that case some providers will still give the wrong end coordinate as start+2 (e.g. UCSC)\n  //so we should not trust the end coordinate for such features\n  if (exontype==exgffStart || exontype==exgffStop) {\n     if (strand=='-') segstart=segend;\n                else  segend=segstart;\n     if (exontype==exgffStart) {\n           if (CDstart==0 || segstart<CDstart) CDstart=segstart;\n           }\n         else {\n           if (segstart>CDend) CDend=segstart;\n           }\n     }\n    else if (iscds) { //update CDS anchors:\n     if (CDstart==0 || segstart<CDstart)  {\n           CDstart=segstart;\n           if (exontype==exgffCDS && strand=='+') CDphase=fr;\n           }\n     if (segend>CDend) {\n           if (exontype==exgffCDS && strand=='-') CDphase=fr;\n           CDend=segend;\n           }\n     }\n   else { // not a CDS/start/stop \n     isCDS=false;\n     }\n  if (qs || qe) {\n    if (qs>qe) Gswap(qs,qe);\n    if (qs==0) qs=1;\n\t}\n  int ovlen=0;\n  if (exontype>0) { //check for overlaps between exon-type segments\n      int oi=exonOverlapIdx(segstart, segend, &ovlen);\n      if (oi>=0) { //overlap existing segment\n         if (ovlen==0) {\n\t\t\t  //adjacent segments will be merged\n\t\t\t  //e.g. CDS to (UTR|exon)\n\t\t\t  if ((exons[oi]->exontype>=exgffUTR && exontype==exgffCDS) ||\n\t\t\t\t  (exons[oi]->exontype==exgffCDS && exontype>=exgffUTR)) {\n\t\t\t\t\texpandExon(oi, segstart, segend, exgffCDSUTR, sc, fr, qs, qe);\n\t\t\t\t\treturn oi;\n\t\t\t\t\t}\n\t\t\t  //CDS adjacent to stop_codon: UCSC does (did?) this\n\t\t\t  if ((exons[oi]->exontype==exgffStop && exontype==exgffCDS) ||\n\t\t\t\t  (exons[oi]->exontype==exgffCDS && exontype==exgffStop)) {\n\t\t\t\t\texpandExon(oi, segstart, segend, exgffCDS, sc, fr, qs, qe);\n\t\t\t\t\treturn oi;\n\t\t\t\t\t}\n        }\n\t\t //only allow this for CDS within exon, stop_codon within (CDS|UTR|exon),\n         //                   start_codon within (CDS|exon)\n        if (exons[oi]->start<=segstart && exons[oi]->end>=segend) {\n          //larger segment given first, now the smaller included one is redundant\n           if (exons[oi]->exontype>exontype &&\n             !(exons[oi]->exontype==exgffUTR && exontype==exgffCDS)) {\n              return oi; //only used to store attributes from current GffLine\n              }\n           else {\n          \t if (gff_show_warnings && (exons[oi]->start<segstart || exons[oi]->end>segend)) {\n          \t\t GMessage(\"GFF Warning: unusual segment inclusion: %s(%d-%d) within %s(%d-%d) (ID=%s)\\n\",\n          \t\t\t\t strExonType(exontype), segstart, segend, strExonType(exons[oi]->exontype),\n          \t\t\t\t exons[oi]->start, exons[oi]->end, this->gffID);\n          \t }\n            return oi;\n           }\n        }\n        if (exontype>exons[oi]->exontype && \n             segstart<=exons[oi]->start && segend>=exons[oi]->end &&\n             !(exontype==exgffUTR && exons[oi]->exontype==exgffCDS)) {\n               //smaller segment given first, so we have to enlarge it\n\t\t\t  expandExon(oi, segstart, segend, exontype, sc, fr, qs, qe);\n\t\t\t\t//this should also check for overlapping next exon (oi+1) ?\n              return oi;\n              }\n        //there is also the special case of \"ribosomal slippage exception\" (programmed frameshift)\n        //where two CDS segments may actually overlap for 1 or 2 bases, but there should be only one encompassing exon\n\t\t//if (ovlen>2 || exons[oi]->exontype!=exgffCDS || exontype!=exgffCDS) {\n\t\t// had to relax this because of some weird UCSC annotations with exons partially overlapping the CDS segments\n\t\t/*\n\t\tif (ovlen>2 && exons[oi]->exontype!=exgffUTR && exontype!=exgffUTR) {\n\t\t   if (gff_show_warnings)\n\t\t\t   GMessage(\"GFF Warning: discarding overlapping feature segment (%d-%d) (vs %d-%d (%s)) for GFF ID %s on %s\\n\",\n\t\t\t   segstart, segend, exons[oi]->start, exons[oi]->end, getSubfName(), gffID, getGSeqName());\n\t\t   hasErrors(true);\n\t\t   return -1; //segment NOT added\n\t\t   }\n\t\t*/\n\n\t\t if ((ovlen>2 || ovlen==0) || exons[oi]->exontype!=exgffCDS || exontype!=exgffCDS) {\n\t\t  /*if (gff_show_warnings)\n\t\t\t GMessage(\"GFF Warning: merging overlapping/adjacent feature segment %s (%d-%d) with %s (%d-%d) for GFF ID %s on %s\\n\",\n\t\t\t\t\t strExonType(exontype), segstart, segend, strExonType(exons[oi]->exontype), exons[oi]->start, exons[oi]->end, gffID, getGSeqName());\n\t\t   */\n\t\t\texpandExon(oi, segstart, segend, exontype, sc, fr, qs, qe);\n\t\t\treturn oi;\n\t\t }\n\t\t// else add the segment if the overlap is small and between two CDS segments\n\t\t//TODO: we might want to add an attribute here with the slippage coordinate and size?\n        covlen-=ovlen;\n\t\t}//overlap or adjacent to existing segment\n\t } //check for overlap\n   // --- no overlap, or accepted micro-overlap (ribosomal slippage)\n   // create & add the new segment\n   /*\n   if (start>0 && exontype==exgffCDS && exons.Count()==0) {\n      //adding a CDS directly as the first subfeature of a declared parent\n      segstart=start;\n      segend=end;\n      } \n   */\n   GffExon* enew=new GffExon(segstart, segend, sc, fr, qs, qe, exontype);\n   int eidx=exons.Add(enew);\n   if (eidx<0) {\n    //this would actually be acceptable if the object is a \"Gene\" and \"exons\" are in fact isoforms\n     if (gff_show_warnings) \n       GMessage(\"GFF Warning: failed adding segment %d-%d for %s (discarded)!\\n\",\n            segstart, segend, gffID);\n     delete enew;\n     hasErrors(true);\n     return -1;            \n     }\n   covlen+=(int)(exons[eidx]->end-exons[eidx]->start)+1;\n   //adjust parent feature coordinates to contain this exon\n   if (start==0 || start>exons.First()->start) {\n     start=exons.First()->start;\n     }\n   if (end<exons.Last()->end) end=exons.Last()->end;\n     \n   return eidx;\n}\n\nvoid GffObj::expandExon(int oi, uint segstart, uint segend, char exontype, double sc, char fr, int qs, int qe) {\n  //oi is the index of the *first* overlapping segment found that must be enlarged\n  covlen-=exons[oi]->len();\n  if (segstart<exons[oi]->start)\n    exons[oi]->start=segstart;\n  if (qs && qs<exons[oi]->qstart) exons[oi]->qstart=qs;\n  if (segend>exons[oi]->end)\n    exons[oi]->end=segend;\n  if (qe && qe>exons[oi]->qend) exons[oi]->qend=qe;\n  //warning: score cannot be properly adjusted! e.g. if it's a p-value it's just going to get worse\n  if (sc!=0) exons[oi]->score=sc;\n  covlen+=exons[oi]->len();\n  //if (exons[oi]->exontype< exontype) -- always true\n  exons[oi]->exontype = exontype;\n  if (exontype==exgffCDS) exons[oi]->phase=fr;\n  //we must check if any more exons are also overlapping this \n  int ni=oi+1; //next exon index after oi\n  while (ni<exons.Count() && segend>=exons[ni]->start) { // next segment overlaps new enlarged segment\n     //only allow this if next segment is fully included, and a subordinate\n     if (exons[ni]->exontype<exontype && exons[ni]->end<=segend) {\n/* I guess we have to relax this due to stupid UCSC hg18 files having a start_codon sticking out\nchr1\thg18_knownGene\tstart_codon\t69806911\t69806913\t0.000000\t+\t.\nchr1\thg18_knownGene\tCDS\t69806911\t69806912\t0.000000\t+\t0\nchr1\thg18_knownGene\texon\t69805456\t69806912\t0.000000\t+\t.     \n*/\n         if (exons[ni]->qstart<exons[oi]->qstart) exons[oi]->qstart=exons[ni]->qstart;\n         if (exons[ni]->qend>exons[oi]->qend) exons[oi]->qend=exons[ni]->qend;\n         exons.Delete(ni);\n         }\n      else {\n         if (gff_show_warnings) GMessage(\"GFF Warning: overlapping existing exon(%d-%d) while expanding to %d-%d for GFF ID %s\\n\",\n                exons[ni]->start, exons[ni]->end, segstart, segend, gffID);\n         //hasErrors(true);\n         break;\n         }\n     }\n  // -- make sure any other related boundaries are updated:\n  start=exons.First()->start;\n  end=exons.Last()->end;\n  if (uptr!=NULL) { //collect stats about the underlying genomic sequence\n    GSeqStat* gsd=(GSeqStat*)uptr;\n    if (start<gsd->mincoord) gsd->mincoord=start;\n    if (end>gsd->maxcoord) gsd->maxcoord=end;\n    if (this->len()>gsd->maxfeat_len) {\n        gsd->maxfeat_len=this->len();\n        gsd->maxfeat=this;\n        }\n    }\n}\n\nvoid GffObj::removeExon(int idx) {\n  /*\n   if (idx==0 && segs[0].start==gstart)\n                  gstart=segs[1].start;\n   if (idx==segcount && segs[segcount].end==gend)\n                  gend=segs[segcount-1].end;\n  */\n  if (idx<0 || idx>=exons.Count()) return;\n  int segstart=exons[idx]->start;\n  int segend=exons[idx]->end;\n  exons.Delete(idx);\n  covlen -= (int)(segend-segstart)+1;\n  start=exons.First()->start;\n  end=exons.Last()->end;\n  if (isCDS) { CDstart=start; CDend=end; }\n}\n\nvoid GffObj::removeExon(GffExon* p) {\n  for (int idx=0;idx<exons.Count();idx++) {\n     if (exons[idx]==p) {\n        int segstart=exons[idx]->start;\n        int segend=exons[idx]->end;\n        exons.Delete(idx);\n        covlen -= (int)(segend-segstart)+1;\n\n\tif (exons.Count() > 0) {\n\t  start=exons.First()->start;\n\t  end=exons.Last()->end;\n\t  if (isCDS) { CDstart=start; CDend=end; }\n\t}\n        return;\n        }\n     }\n}\n\n\n\nGffObj::GffObj(GffReader *gfrd, GffLine* gffline, bool keepAttr, bool noExonAttr):\n     GSeg(0,0), exons(true,true,false), children(1,false) {\n  xstart=0;\n  xend=0;\n  xstatus=0;\n  partial=false;\n  isCDS=false;\n  uptr=NULL;\n  ulink=NULL;\n  parent=NULL;\n  udata=0;\n  flags=0;\n  CDstart=0;\n  CDend=0;\n  CDphase=0;\n  geneID=NULL;\n  gene_name=NULL;\n  attrs=NULL;\n  gffID=NULL;\n  track_id=-1;\n  gseq_id=-1;\n  ftype_id=-1;\n  exon_ftype_id=-1;\n  strand='.';\n  if (gfrd==NULL)\n    GError(\"Cannot use this GffObj constructor with a NULL GffReader!\\n\");\n  gffnames_ref(names);\n  if (gfrd->names==NULL) gfrd->names=names;\n  //qlen=0;qstart=0;qend=0;\n  gscore=0;\n  uscore=0;\n  covlen=0;\n  qcov=0;\n  start=gffline->fstart;\n  end=gffline->fend;\n  gseq_id=names->gseqs.addName(gffline->gseqname);\n  track_id=names->tracks.addName(gffline->track);\n  strand=gffline->strand;\n  qlen=gffline->qlen;\n  qstart=gffline->qstart;\n  qend=gffline->qend;\n  //setup flags from gffline\n  isCDS=gffline->is_cds; //for now\n  isGene(gffline->is_gene);\n  isTranscript(gffline->is_transcript || gffline->exontype!=0);\n  //fromGff3(gffline->is_gff3);\n\n  if (gffline->parents!=NULL && !gffline->is_transcript) {\n    //GTF style -- create a GffObj directly by subfeature\n    //(also possible orphan GFF3 exon line, or an exon given before its parent (chado))\n    if (gffline->exontype!=0) { //recognized exon-like feature\n       ftype_id=gff_fid_transcript; //so this is some sort of transcript\n       exon_ftype_id=gff_fid_exon; //subfeatures MUST be exons\n       }\n     else {//unrecognized subfeatures\n       //make this GffObj of the same feature type\n       ftype_id=names->feats.addName(gffline->ftype);\n       }\n    if (gffline->ID==NULL) { //typical GTF2 without \"transcript\" line\n        gffID=Gstrdup(gffline->parents[0]);\n        this->createdByExon(true);\n        //this is likely the first exon/segment of the feature\n        addExon(gfrd, gffline, keepAttr, noExonAttr);\n        }\n      else { //a parented feature with an ID: orphan or premature GFF3 subfeature line\n        if (gffline->is_gff3 && gffline->exontype!=0) {\n             //premature exon given before its parent transcript\n             //create the transcript entry here\n             gffID=Gstrdup(gffline->parents[0]);\n             this->createdByExon(true);\n             //this is the first exon/segment of the transcript\n             addExon(gfrd, gffline, keepAttr, noExonAttr);\n             }\n        else { //unrecognized non-exon feature ? use the ID instead\n             this->hasGffID(true);\n             gffID=Gstrdup(gffline->ID);\n             if (keepAttr) this->parseAttrs(attrs, gffline->info);\n             }\n        }\n    } //non-transcript parented subfeature given directly\n  else {\n\t//non-parented feature OR a recognizable transcript\n    //create a parent feature in its own right\n    gscore=gffline->score;\n    if (gffline->ID==NULL || gffline->ID[0]==0)\n      GError(\"Error: no ID found for GFF record start\\n\");\n    this->hasGffID(true);\n    gffID=Gstrdup(gffline->ID); //there must be an ID here\n    //if (gffline->is_transcript) ftype_id=gff_fid_mRNA;\n      //else\n    ftype_id=names->feats.addName(gffline->ftype);\n    if (gffline->is_transcript)\n      exon_ftype_id=gff_fid_exon;\n    if (keepAttr) this->parseAttrs(attrs, gffline->info);\n    }//no parent\n\n  if (gffline->gene_name!=NULL) {\n     gene_name=Gstrdup(gffline->gene_name);\n     }\n  if (gffline->gene_id) {\n     geneID=Gstrdup(gffline->gene_id);\n     }\n  else if (gffline->is_transcript && gffline->parents) {\n\t geneID=Gstrdup(gffline->parents[0]);\n     }\n\n  //GSeqStat* gsd=gfrd->gseqstats.AddIfNew(new GSeqStat(gseq_id,names->gseqs.lastNameUsed()),true);\n  GSeqStat* gsd=gfrd->gseqstats.AddIfNew(new GSeqStat(gseq_id,gffline->gseqname), true);\n  uptr=gsd;\n  /*\n  if (start<gsd->mincoord) gsd->mincoord=start;\n  if (end>gsd->maxcoord) gsd->maxcoord=end;\n    if (this->len()>gsd->maxfeat_len) {\n        gsd->maxfeat_len=this->len();\n        gsd->maxfeat=this;\n        }\n  */\n}\n\nGffLine* GffReader::nextGffLine() {\n if (gffline!=NULL) return gffline; //caller should free gffline after processing\n while (gffline==NULL) {\n    int llen=0;\n    buflen=GFF_LINELEN-1;\n    char* l=fgetline(linebuf, buflen, fh, &fpos, &llen);\n    if (l==NULL) {\n         return NULL; //end of file\n         }\n#ifdef CUFFLINKS\n     _crc_result.process_bytes( linebuf, llen );\n#endif\n    int ns=0; //first nonspace position\n    while (l[ns]!=0 && isspace(l[ns])) ns++;\n    if (l[ns]=='#' || llen<10) continue;\n    gffline=new GffLine(this, l);\n    if (gffline->skipLine) {\n       delete gffline;\n       gffline=NULL;\n       continue;\n       }\n    if (gffline->ID==NULL && gffline->parents==NULL)  { //it must have an ID\n        //this might not be needed, already checked in the GffLine constructor\n        if (gff_warns)\n            GMessage(\"Warning: malformed GFF line, no parent or record Id (kipping\\n\");\n        delete gffline;\n        gffline=NULL;\n        //continue;\n        }\n    }\nreturn gffline;\n}\n\n\nchar* GffReader::gfoBuildId(const char* id, const char* ctg) {\n//caller must free the returned pointer\n char* buf=NULL;\n int idlen=strlen(id);\n GMALLOC(buf, idlen+strlen(ctg)+2);\n strcpy(buf, id);\n buf[idlen]='~';\n strcpy(buf+idlen+1, ctg);\n return buf;\n}\n/*\nvoid GffReader::gfoRemove(const char* id, const char* ctg) {\n char* buf=gfoBuildId(id,ctg);\n phash.Remove(buf);\n GFREE(buf);\n}\n*/\nGffObj* GffReader::gfoAdd(GffObj* gfo) {\n GPVec<GffObj>* glst=phash.Find(gfo->gffID);\n if (glst==NULL)\n\t glst=new GPVec<GffObj>(false);\n //GfoHolder gh(gfo); //,idx);\n int i=glst->Add(gfo);\n phash.Add(gfo->gffID, glst);\n return glst->Get(i);\n}\n\nGffObj* GffReader::gfoAdd(GPVec<GffObj>& glst, GffObj* gfo) {\n int i=glst.Add(gfo);\n return glst[i];\n}\n\nbool GffReader::pFind(const char* id, GPVec<GffObj>*& glst) {\n\tglst = phash.Find(id);\n\treturn (glst!=NULL);\n}\n\nGffObj* GffReader::gfoFind(const char* id, GPVec<GffObj>*& glst,\n\t\tconst char* ctg, char strand, uint start, uint end) {\n\tGPVec<GffObj>* gl=NULL;\n\tif (glst) {\n\t\tgl=glst;\n\t} else {\n\t\tgl = phash.Find(id);\n\t}\n\tGffObj* gh=NULL;\n\tif (gl) {\n\t\tfor (int i=0;i<gl->Count();i++) {\n\t\t\tGffObj& gfo = *(gl->Get(i));\n\t\t\tif (ctg!=NULL && strcmp(ctg, gfo.getGSeqName())!=0)\n\t\t\t\tcontinue;\n\t\t\tif (strand && gfo.strand!='.' && strand != gfo.strand)\n\t\t\t\tcontinue;\n\t\t\tif (start>0) {\n\t\t\t\tif (abs((int)start-(int)gfo.start)> (int)GFF_MAX_LOCUS)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (end>0 && (gfo.start>end || gfo.end<start))\n\t\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t//must be the same transcript, according to given comparison criteria\n\t\t\tgh=&gfo;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!glst) glst=gl;\n\treturn gh;\n}\n/*\nGffObj* GffReader::replaceGffRec(GffLine* gffline, bool keepAttr, bool noExonAttr, int replaceidx) {\n  GffObj* newgfo=new GffObj(this, gffline, keepAttr, noExonAttr);\n  GffObj* r=NULL;\n  if (replaceidx>=0) {\n     gflst.Put(replaceidx,newgfo);\n     r=gfoAdd(newgfo);\n     }\n   else {\n     int gfoidx=gflst.Add(newgfo);\n     r=gfoAdd(newgfo);\n     }\n  return r;\n} */\n\nGffObj* GffReader::updateParent(GffObj* newgfo, GffObj* parent) {\n  //assert(parent);\n  //assert(newgfo);\n  parent->children.Add(newgfo);\n  if (newgfo->parent==NULL) newgfo->parent=parent;\n  newgfo->setLevel(parent->getLevel()+1);\n  if (parent->isGene()) {\n      if (parent->gene_name!=NULL && newgfo->gene_name==NULL)\n        newgfo->gene_name=Gstrdup(parent->gene_name);\n      if (parent->geneID!=NULL && newgfo->geneID==NULL)\n        newgfo->geneID=Gstrdup(parent->geneID);\n      }\n\n  return newgfo;\n}\n\nGffObj* GffReader::newGffRec(GffLine* gffline, bool keepAttr, bool noExonAttr,\n                          GffObj* parent, GffExon* pexon, GPVec<GffObj>* glst) {\n  GffObj* newgfo=new GffObj(this, gffline, keepAttr, noExonAttr);\n  GffObj* r=NULL;\n  //int gfoidx=gflst.Add(newgfo);\n  gflst.Add(newgfo);\n  r=(glst) ? gfoAdd(*glst, newgfo) : gfoAdd(newgfo);\n  if (parent!=NULL) {\n    updateParent(r, parent);\n    if (pexon!=NULL) parent->removeExon(pexon);\n    }\n  /*\n  if (gff_warns) {\n    int* pcount=tids.Find(newgfo->gffID);\n    if (pcount!=NULL) {\n       if (gff_warns) GMessage(\"Warning: duplicate GFF ID: %s\\n\", newgfo->gffID);\n       (*pcount)++;\n       }\n     else {\n       tids.Add(newgfo->gffID,new int(1));\n       }\n    }\n  */\n  return r;\n}\n\nGffObj* GffReader::updateGffRec(GffObj* prevgfo, GffLine* gffline,\n                                         bool keepAttr) {\n if (prevgfo==NULL) return NULL;\n //prevgfo->gffobj->createdByExon(false);\n prevgfo->ftype_id=prevgfo->names->feats.addName(gffline->ftype);\n prevgfo->start=gffline->fstart;\n prevgfo->end=gffline->fend;\n prevgfo->isGene(gffline->is_gene);\n prevgfo->isTranscript(gffline->is_transcript || gffline->exontype!=0);\n prevgfo->hasGffID(gffline->ID!=NULL);\n if (keepAttr) {\n   if (prevgfo->attrs!=NULL) prevgfo->attrs->Clear();\n   prevgfo->parseAttrs(prevgfo->attrs, gffline->info);\n   }\n return prevgfo;\n}\n\n\nbool GffReader::addExonFeature(GffObj* prevgfo, GffLine* gffline, GHash<CNonExon>& pex, bool noExonAttr) {\n  bool r=true;\n  if (gffline->strand!=prevgfo->strand) {\n        if (prevgfo->strand=='.') {\n            prevgfo->strand=gffline->strand;\n        }\n     else {\n       GMessage(\"GFF Error at %s (%c): exon %d-%d (%c) found on different strand; discarded.\\n\",\n       prevgfo->gffID, prevgfo->strand,\n       gffline->fstart, gffline->fend, gffline->strand, prevgfo->getGSeqName());\n       //r=false;\n       return true;\n       }\n   }\n  int gdist=(gffline->fstart>prevgfo->end) ? gffline->fstart-prevgfo->end :\n                      ((gffline->fend<prevgfo->start)? prevgfo->start-gffline->fend :\n                         0 );\n  if (gdist>(int)GFF_MAX_LOCUS) { //too far apart, most likely this is a duplicate ID\n    GMessage(\"Error: duplicate GFF ID '%s' (or exons too far apart)!\\n\",prevgfo->gffID);\n    //validation_errors = true;\n    r=false;\n    if (!gff_warns) exit(1);\n    }\n  int eidx=prevgfo->addExon(this, gffline, !noExonAttr, noExonAttr);\n  if (eidx>=0 && gffline->ID!=NULL && gffline->exontype==0)\n      subfPoolAdd(pex, prevgfo);\n  return r;\n}\n\nCNonExon* GffReader::subfPoolCheck(GffLine* gffline, GHash<CNonExon>& pex, char*& subp_name) {\n  CNonExon* subp=NULL;\n  subp_name=NULL;\n  for (int i=0;i<gffline->num_parents;i++) {\n    if (transcriptsOnly && discarded_ids.Find(gffline->parents[i])!=NULL)\n        continue;\n    subp_name=gfoBuildId(gffline->parents[i], gffline->gseqname); //e.g. mRNA name\n    subp=pex.Find(subp_name);\n    if (subp!=NULL)\n       return subp;\n    GFREE(subp_name);\n    }\n  return NULL;\n}\n\nvoid GffReader::subfPoolAdd(GHash<CNonExon>& pex, GffObj* newgfo) {\n//this might become a parent feature later\nif (newgfo->exons.Count()>0) {\n   char* xbuf=gfoBuildId(gffline->ID, gffline->gseqname);\n   pex.Add(xbuf, new CNonExon(newgfo, newgfo->exons[0], gffline));\n   GFREE(xbuf);\n   }\n}\n\nGffObj* GffReader::promoteFeature(CNonExon* subp, char*& subp_name, GHash<CNonExon>& pex,\n    bool keepAttr, bool noExonAttr) {\n  GffObj* prevp=subp->parent; //grandparent of gffline (e.g. gene)\n  //if (prevp!=gflst[subp->idx])\n  //  GError(\"Error promoting subfeature %s, gflst index mismatch?!\\n\", subp->gffline->ID);\n  subp->gffline->discardParent();\n  GffObj* gfoh=newGffRec(subp->gffline, keepAttr, noExonAttr, prevp, subp->exon);\n  pex.Remove(subp_name); //no longer a potential parent, moved it to phash already\n  prevp->promotedChildren(true);\n  return gfoh; //returns the holder of newly promoted feature\n}\n\n//have to parse the whole file because exons and other subfeatures can be scattered, unordered in the input\n//Trans-splicing and fusions are only accepted in proper GFF3 format, i.e. multiple features with the same ID\n//are accepted if they are NOT overlapping/continuous\n//  *** BUT (exception): proximal xRNA features with the same ID, on the same strand, will be merged\n//  and the segments will be treated like exons (e.g. TRNAR15 (rna1940) in RefSeq)\nvoid GffReader::readAll(bool keepAttr, bool mergeCloseExons, bool noExonAttr) {\n\tbool validation_errors = false;\n\t//loc_debug=false;\n\tGHash<CNonExon> pex; //keep track of any \"exon\"-like features that have an ID\n\t//and thus could become promoted to parent features\n\twhile (nextGffLine()!=NULL) {\n\t\tGffObj* prevseen=NULL;\n\t\tGPVec<GffObj>* prevgflst=NULL;\n\t\tif (gffline->ID && gffline->exontype==0) {\n\t\t\t//>> for a parent-like IDed feature (mRNA, gene, etc.)\n\t\t\t//look for same ID on the same chromosome/strand/locus\n\t\t\tprevseen=gfoFind(gffline->ID, prevgflst, gffline->gseqname, gffline->strand, gffline->fstart);\n\t\t\tif (prevseen!=NULL) {\n\t\t\t\t//same ID/chromosome combo encountered before\n\t\t\t\tif (prevseen->createdByExon()) {\n\t\t\t\t\tif (gff_show_warnings && (prevseen->start<gffline->fstart ||\n\t\t\t\t\t\t\tprevseen->end>gffline->fend))\n\t\t\t\t\t\tGMessage(\"GFF Warning: invalid coordinates for %s parent feature (ID=%s)\\n\", gffline->ftype, gffline->ID);\n\t\t\t\t\t//an exon of this ID was given before\n\t\t\t\t\t//this line has the main attributes for this ID\n\t\t\t\t\tupdateGffRec(prevseen, gffline, keepAttr);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t//- duplicate ID -- this must be a discontinuous feature according to GFF3 specs\n\t\t\t\t\t//   e.g. a trans-spliced transcript\n\t\t\t\t\tif (prevseen->overlap(gffline->fstart, gffline->fend)) {\n\t\t\t\t\t\t//overlapping with same ID not allowed\n\t\t\t\t\t\tGMessage(\"GFF Error: duplicate/invalid '%s' feature ID=%s\\n\", gffline->ftype, gffline->ID);\n\t\t\t\t\t\t//validation_errors = true;\n\t\t\t\t\t\tif (gff_warns) {\n\t\t\t\t\t\t\tdelete gffline;\n\t\t\t\t\t\t\tgffline=NULL;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse exit(1);\n\t\t\t\t\t}\n\t\t\t\t\t//create a new entry with the same ID\n\t\t\t\t\tint distance=INT_MAX;\n\t\t\t\t\tif (prevseen->isTranscript() && prevseen->strand==gffline->strand) {\n\t\t\t\t\t\tif (prevseen->start>=gffline->fstart)\n\t\t\t\t\t\t\tdistance=prevseen->start-gffline->fend;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tdistance=gffline->fstart-prevseen->end;\n\t\t\t\t\t}\n\t\t\t\t\tif (distance<1000) {//FIXME: arbitrary proximity threshold (yuck)\n\t\t\t\t\t\t//exception: make this an exon of previous ID\n\t\t\t\t\t\t//addExonFeature(prevseen, gffline, pex, noExonAttr);\n\t\t\t\t\t\tprevseen->addExon(this, gffline, false, true);\n\t\t\t\t\t}\n\t\t\t\t\telse { //create a separate entry (true discontinuous feature)\n\t\t\t\t\t\tprevseen=newGffRec(gffline, keepAttr, noExonAttr,\n\t\t\t\t\t\t\t\tprevseen->parent, NULL, prevgflst);\n\t\t\t\t\t}\n\t\t\t\t} //duplicate ID on the same chromosome\n\t\t\t} //prevseeen != NULL\n\t\t} //parent-like ID feature\n\t\tif (gffline->parents==NULL) {//start GFF3-like record with no parent (mRNA, gene)\n\t\t\tif (!prevseen) newGffRec(gffline, keepAttr, noExonAttr, NULL, NULL, prevgflst);\n\t\t}\n\t\telse { //--- it's a child feature (exon/CDS but could still be a mRNA with gene(s) as parent)\n\t\t\t//updates all the declared parents with this child\n\t\t\tbool found_parent=false;\n\t\t\tGffObj* newgfo=prevseen;\n\t\t\tGPVec<GffObj>* newgflst=NULL;\n\t\t\tGVec<int> kparents; //kept parents (non-discarded)\n\t\t\tGVec< GPVec<GffObj>* > kgflst(false);\n\t\t\tGPVec<GffObj>* gflst0=NULL;\n\t\t\tfor (int i=0;i<gffline->num_parents;i++) {\n\t\t\t\tnewgflst=NULL;\n\t\t\t\tif (transcriptsOnly && (discarded_ids.Find(gffline->parents[i])!=NULL ||\n\t\t\t\t\t\t  !pFind(gffline->parents[i], newgflst)))\n\t\t\t\t\tcontinue; //skipping discarded parent feature\n\t\t\t\tkparents.Add(i);\n\t\t\t\tif (i==0) gflst0=newgflst;\n\t\t\t\tkgflst.Add(newgflst);\n\t\t\t}\n\t\t\tif (gffline->num_parents>0 && kparents.Count()==0) {\n\t\t\t\tkparents.cAdd(0);\n\t\t\t\tkgflst.Add(gflst0);\n\t\t\t}\n\t\t\tfor (int k=0;k<kparents.Count();k++) {\n\t\t\t\tint i=kparents[k];\n\t\t\t\tnewgflst=kgflst[k];\n\t\t\t\tGffObj* parentgfo=NULL;\n\t\t\t\tif (gffline->is_transcript || gffline->exontype==0) {//possibly a transcript\n\t\t\t\t\tparentgfo=gfoFind(gffline->parents[i], newgflst, gffline->gseqname,\n\t\t\t\t\t\t\tgffline->strand, gffline->fstart, gffline->fend);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t//for exon-like entities we only need a parent to be in locus distance,\n\t\t\t\t\t//on the same strand\n\t\t\t\t\tparentgfo=gfoFind(gffline->parents[i], newgflst, gffline->gseqname,\n\t\t\t\t\t\t\tgffline->strand, gffline->fstart);\n\t\t\t\t}\n\t\t\t\tif (parentgfo!=NULL) { //parent GffObj parsed earlier\n\t\t\t\t\tfound_parent=true;\n\t\t\t\t\tif (parentgfo->isGene() && gffline->is_transcript\n\t\t\t\t\t\t\t&& gffline->exontype==0) {\n\t\t\t\t\t\t//not an exon, but a transcript parented by a gene\n\t\t\t\t\t\tif (newgfo) {\n\t\t\t\t\t\t\tupdateParent(newgfo, parentgfo);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tnewgfo=newGffRec(gffline, keepAttr, noExonAttr, parentgfo);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse { //potential exon subfeature?\n\t\t\t\t\t\t//always discards dummy \"intron\" features\n\t\t\t\t\t\tif (!(gffline->exontype==exgffIntron && (parentgfo->isTranscript() || parentgfo->exons.Count()>0))) {\n\t\t\t\t\t\t\tif (!addExonFeature(parentgfo, gffline, pex, noExonAttr))\n\t\t\t\t\t\t\t\tvalidation_errors=true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} //overlapping parent feature found\n\t\t\t} //for each parsed parent Id\n\t\t\tif (!found_parent) { //new GTF-like record starting here with a subfeature directly\n\t\t\t\t//or it could be some chado GFF3 barf with exons coming BEFORE their parent :(\n\t\t\t\t//check if this feature isn't parented by a previously stored \"exon\" subfeature\n\t\t\t\tchar* subp_name=NULL;\n\t\t\t\tCNonExon* subp=subfPoolCheck(gffline, pex, subp_name);\n\t\t\t\tif (subp!=NULL) { //found a subfeature that is the parent of this gffline\n\t\t\t\t\t//promote that subfeature to a full GffObj\n\t\t\t\t\tGffObj* gfoh=promoteFeature(subp, subp_name, pex, keepAttr, noExonAttr);\n\t\t\t\t\t//add current gffline as an exon of the newly promoted subfeature\n\t\t\t\t\tif (!addExonFeature(gfoh, gffline, pex, noExonAttr))\n\t\t\t\t\t\tvalidation_errors=true;\n\t\t\t\t}\n\t\t\t\telse { //no parent seen before,\n\t\t\t\t\t//loc_debug=true;\n\t\t\t\t\tGffObj* ngfo=prevseen;\n\t\t\t\t\tif (ngfo==NULL) {\n\t\t\t\t\t\t//if it's an exon type, create directly the parent with this exon\n\t\t\t\t\t\t//but if it's recognized as a transcript, the object itself is created\n\t\t\t\t\t\tngfo=newGffRec(gffline, keepAttr, noExonAttr, NULL, NULL, newgflst);\n\t\t\t\t\t}\n\t\t\t\t\tif (!ngfo->isTranscript() &&\n\t\t\t\t\t\t\tgffline->ID!=NULL && gffline->exontype==0)\n\t\t\t\t\t\tsubfPoolAdd(pex, ngfo);\n\t\t\t\t\t//even those with errors will be added here!\n\t\t\t\t}\n\t\t\t\tGFREE(subp_name);\n\t\t\t} //no previous parent found\n\t\t} //parented feature\n\t\t//--\n\t\tdelete gffline;\n\t\tgffline=NULL;\n\t}//while gff lines\n\tif (gflst.Count()>0) {\n\t\tgflst.finalize(this, mergeCloseExons, keepAttr, noExonAttr); //force sorting by locus if so constructed\n\t\tgseqStats.setCount(gseqstats.Last()->gseqid+1);\n\t\tfor (int gi=0;gi<gseqstats.Count();gi++) {\n\t\t\tgseqStats.Put(gseqstats[gi]->gseqid, gseqstats[gi]); //copy the pointer only\n\t\t}\n\t}\n\t// all gff records are now loaded in GList gflst\n\t// so we can free the hash\n\tphash.Clear();\n\t//tids.Clear();\n\tif (validation_errors) {\n\t\texit(1);\n\t}\n}\n\nvoid GfList::finalize(GffReader* gfr, bool mergeCloseExons,\n             bool keepAttrs, bool noExonAttr) { //if set, enforce sort by locus\n  if (mustSort) { //force (re-)sorting\n     this->setSorted(false);\n     this->setSorted((GCompareProc*)gfo_cmpByLoc);\n     }\n  GList<GffObj> discarded(false,true,false);\n  for (int i=0;i<Count();i++) {\n    //finish the parsing for each GffObj\n    fList[i]->finalize(gfr, mergeCloseExons, keepAttrs, noExonAttr);\n    if (fList[i]->isDiscarded()) {\n       discarded.Add(fList[i]);\n       if (fList[i]->children.Count()>0) {\n      \t for (int c=0;c<fList[i]->children.Count();c++) {\n      \t\t fList[i]->children[c]->parent=NULL;\n      \t\t if (keepAttrs)\n      \t\t\t fList[i]->children[c]->copyAttrs(fList[i]); //inherit the attributes of discarded parent (e.g. pseudo=true; )\n      \t }\n       }\n       this->Forget(i);\n    }\n  }\n  if (discarded.Count()>0) {\n          this->Pack();\n          }\n}\n\nGffObj* GffObj::finalize(GffReader* gfr, bool mergeCloseExons, bool keepAttrs, bool noExonAttr) {\n //merge\n //always merge adjacent or overlapping segments\n //but if mergeCloseExons then merge even when distance is up to 5 bases\n udata=0;\n uptr=NULL;\n if (gfr->transcriptsOnly && !(isTranscript() || (isGene() && children.Count()==0))) {\n       isDiscarded(true);\n       }\n if (ftype_id==gff_fid_transcript && CDstart>0) {\n    ftype_id=gff_fid_mRNA;\n    //exon_ftype_id=gff_fid_exon;\n    }\n if (exons.Count()>0 && (isTranscript() || exon_ftype_id==gff_fid_exon)) {\n   if (mergeCloseExons) {\n     int mindist=mergeCloseExons ? 5:1;\n     for (int i=0;i<exons.Count()-1;i++) {\n       int ni=i+1;\n       uint mend=exons[i]->end;\n       while (ni<exons.Count()) {\n         int dist=(int)(exons[ni]->start-mend);\n         if (dist>mindist) break; //no merging with next segment\n         if (gfr!=NULL && gfr->gff_warns && dist!=0 && (exons[ni]->exontype!=exgffUTR && exons[i]->exontype!=exgffUTR)) {\n            GMessage(\"GFF warning: merging adjacent/overlapping segments of %s on %s (%d-%d, %d-%d)\\n\",\n                 gffID, getGSeqName(), exons[i]->start, exons[i]->end,exons[ni]->start, exons[ni]->end);\n            }\n         mend=exons[ni]->end;\n         covlen-=exons[i]->len();\n         exons[i]->end=mend;\n         covlen+=exons[i]->len();\n         covlen-=exons[ni]->len();\n         if (exons[ni]->attrs!=NULL && (exons[i]->attrs==NULL ||\n              exons[i]->attrs->Count()<exons[ni]->attrs->Count())) {\n                //use the other exon attributes, if more\n                delete(exons[i]->attrs);\n                exons[i]->attrs=exons[ni]->attrs;\n                exons[ni]->attrs=NULL;\n                }\n         exons.Delete(ni);\n         } //check for merge with next exon\n     } //for each exon\n   } //merge close exons\n   //shrink transcript to the exons' span\n   this->start=exons.First()->start;\n   this->end=exons.Last()->end;\n   //also update the stats for the reference sequence\n   if (uptr!=NULL) { //collect stats about the underlying genomic sequence\n       GSeqStat* gsd=(GSeqStat*)uptr;\n       if (start<gsd->mincoord) gsd->mincoord=start;\n       if (end>gsd->maxcoord) gsd->maxcoord=end;\n       if (this->len()>gsd->maxfeat_len) {\n          gsd->maxfeat_len=this->len();\n          gsd->maxfeat=this;\n          }\n       }\n   this->uptr=NULL;\n   this->udata=0;\n }\n //attribute reduction for GTF records\n if (keepAttrs && !noExonAttr && !hasGffID()\n          && exons.Count()>0 && exons[0]->attrs!=NULL) {\n   bool attrs_discarded=false;\n   for (int a=0;a<exons[0]->attrs->Count();a++) {\n      int attr_name_id=exons[0]->attrs->Get(a)->attr_id;\n      char* attr_name=names->attrs.getName(attr_name_id);\n      char* attr_val =exons[0]->attrs->Get(a)->attr_val;\n      bool sameExonAttr=true;\n      for (int i=1;i<exons.Count();i++) {\n         char* ov=exons[i]->getAttr(attr_name_id);\n         if (ov==NULL || (strcmp(ov,attr_val)!=0)) { \n             sameExonAttr=false; \n             break;\n             }\n         }\n      if (sameExonAttr) {\n             //delete this attribute from exons level\n             attrs_discarded=true;\n             this->addAttr(attr_name, attr_val);\n             for (int i=1;i<exons.Count();i++) {\n                 removeExonAttr(*(exons[i]), attr_name_id);\n                 }\n             exons[0]->attrs->freeItem(a);\n             }\n      }\n   if (attrs_discarded) exons[0]->attrs->Pack();\n   }\n return this;\n}\n\nvoid GffObj::parseAttrs(GffAttrs*& atrlist, char* info, bool isExon) {\n  if (names==NULL)\n     GError(ERR_NULL_GFNAMES, \"parseAttrs()\");\n  if (atrlist==NULL)\n      atrlist=new GffAttrs();\n  char* endinfo=info+strlen(info);\n  char* start=info;\n  char* pch=start;\n  while (start<endinfo) {\n    //skip spaces\n    while (*start==' ' && start<endinfo) start++;\n    pch=strchr(start, ';');\n    if (pch==NULL) pch=endinfo;\n       else {\n            *pch='\\0';\n            pch++;\n            }\n    char* ech=strchr(start,'=');\n    if (ech!=NULL) { // attr=value format found\n       *ech='\\0';\n       //if (noExonAttr && (strcmp(start, \"exon_number\")==0 || strcmp(start, \"exon\")==0)) { start=pch; continue; }\n       if (strcmp(start, \"exon_number\")==0 || strcmp(start, \"exon\")==0 ||\n              strcmp(start, \"exon_id\")==0)\n           { start=pch; continue; }\n       ech++;\n       while (*ech==' ' && ech<endinfo) ech++;//skip extra spaces after the '='\n       //atrlist->Add(new GffAttr(names->attrs.addName(start),ech));\n       //make sure we don't add the same attribute more than once\n       if (isExon && (strcmp(start, \"protein_id\")==0)) {\n             //Ensembl special case\n             this->addAttr(start, ech);\n             start=pch;\n             continue;\n             }\n       atrlist->add_or_update(names, start, ech);\n       }\n      /*\n      else { //not an attr=value format\n        atrlist->Add(new GffAttr(names->attrs.addName(start),\"1\"));\n        }\n      */\n    start=pch;\n    }\n  if (atrlist->Count()==0) { delete atrlist; atrlist=NULL; }\n}\n\nvoid GffObj::addAttr(const char* attrname, const char* attrvalue) {\n  if (this->attrs==NULL)\n      this->attrs=new GffAttrs();\n  //this->attrs->Add(new GffAttr(names->attrs.addName(attrname),attrvalue));\n  this->attrs->add_or_update(names, attrname, attrvalue);\n}\n\nvoid GffObj::copyAttrs(GffObj* from) { //typically from is the parent gene, and this is a transcript\n\tif (from==NULL || from->attrs==NULL) return;\n\tif (this->attrs==NULL) {\n\t\tthis->attrs=new GffAttrs();\n\t}\n\t//special RefSeq case\n\tint desc_attr_id=names->attrs.getId(\"description\"); //from gene\n\tint prod_attr_id=names->attrs.getId(\"product\"); //from transcript (this)\n\tchar* prod = (prod_attr_id>=0) ? this->attrs->getAttr(prod_attr_id) : NULL;\n\n\tfor (int i=0;i<from->attrs->Count();++i) {\n\t\t//this->attrs->add_no_update(names, from->attrs->Get(i)->attr_id, from->attrs->Get(i)->attr_val);\n\t\tint aid=from->attrs->Get(i)->attr_id;\n\t\t//special case for GenBank refseq genes vs transcripts:\n\t\tif (prod && aid==desc_attr_id && strcmp(from->attrs->getAttr(desc_attr_id), prod)==0)\n\t\t\tcontinue; //skip description if product already there and the same\n\t\tbool haveit=false;\n\t\tfor (int ai=0;ai<this->attrs->Count();++ai) {\n\t\t\t//do we have it already?\n\t\t\tif (aid==this->attrs->Get(i)->attr_id) {\n\t\t\t\thaveit=true;\n\t\t\t\tbreak; //skip this, don't replace\n\t\t\t}\n\t\t}\n\t\tif (!haveit)\n\t\t\tthis->attrs->Add(new GffAttr(aid, from->attrs->Get(i)->attr_val));\n\t}\n}\n\nvoid GffObj::setFeatureName(const char* feature) {\n //change the feature name/type for a transcript\n int fid=names->feats.addName(feature);\n if (monoFeature() && exons.Count()>0) \n    this->exon_ftype_id=fid;\n this->ftype_id=fid;\n}\n\nvoid GffObj::setRefName(const char* newname) {\n //change the feature name/type for a transcript\n int rid=names->gseqs.addName(newname);\n this->gseq_id=rid;\n}\n\n\n\nint GffObj::removeAttr(const char* attrname, const char* attrval) {\n  if (this->attrs==NULL || attrname==NULL || attrname[0]==0) return 0;\n  int aid=this->names->attrs.getId(attrname);\n  if (aid<0) return 0;\n  int delcount=0;  //could be more than one ?\n  for (int i=0;i<this->attrs->Count();i++) {\n     if (aid==this->attrs->Get(i)->attr_id) {\n       if (attrval==NULL || \n          strcmp(attrval, this->attrs->Get(i)->attr_val)==0) {\n             delcount++;\n             this->attrs->freeItem(i);\n             }\n       }\n     }\n  if (delcount>0) this->attrs->Pack(); \n  return delcount;\n}\n\nint GffObj::removeAttr(int aid, const char* attrval) {\n  if (this->attrs==NULL || aid<0) return 0;\n  int delcount=0;  //could be more than one ?\n  for (int i=0;i<this->attrs->Count();i++) {\n     if (aid==this->attrs->Get(i)->attr_id) {\n       if (attrval==NULL || \n          strcmp(attrval, this->attrs->Get(i)->attr_val)==0) {\n             delcount++;\n             this->attrs->freeItem(i);\n             }\n       }\n     }\n  if (delcount>0) this->attrs->Pack(); \n  return delcount;\n}\n\n\nint GffObj::removeExonAttr(GffExon& exon, const char* attrname, const char* attrval) {\n  if (exon.attrs==NULL || attrname==NULL || attrname[0]==0) return 0;\n  int aid=this->names->attrs.getId(attrname);\n  if (aid<0) return 0;\n  int delcount=0;  //could be more than one\n  for (int i=0;i<exon.attrs->Count();i++) {\n     if (aid==exon.attrs->Get(i)->attr_id) {\n       if (attrval==NULL || \n          strcmp(attrval, exon.attrs->Get(i)->attr_val)==0) {\n             delcount++;\n             exon.attrs->freeItem(i);\n             }\n       }\n     }\n  if (delcount>0) exon.attrs->Pack(); \n  return delcount;\n}\n\nint GffObj::removeExonAttr(GffExon& exon, int aid, const char* attrval) {\n  if (exon.attrs==NULL || aid<0) return 0;\n  int delcount=0;  //could be more than one\n  for (int i=0;i<exon.attrs->Count();i++) {\n     if (aid==exon.attrs->Get(i)->attr_id) {\n       if (attrval==NULL || \n          strcmp(attrval, exon.attrs->Get(i)->attr_val)==0) {\n             delcount++;\n             exon.attrs->freeItem(i);\n             }\n       }\n     }\n  if (delcount>0) exon.attrs->Pack(); \n  return delcount;\n}\n\n\nvoid GffObj::getCDS_ends(uint& cds_start, uint& cds_end) {\n  cds_start=0;\n  cds_end=0;\n  if (CDstart==0 || CDend==0) return; //no CDS info\n  int cdsadj=0;\n  if (CDphase=='1' || CDphase=='2') {\n      cdsadj=CDphase-'0';\n      }\n  cds_start=CDstart;\n  cds_end=CDend;\n  if (strand=='-') cds_end-=cdsadj;\n              else cds_start+=cdsadj;\n  }\n\nvoid GffObj::mRNA_CDS_coords(uint& cds_mstart, uint& cds_mend) {\n  //sets cds_start and cds_end to the CDS start,end coordinates on the spliced mRNA transcript\n  cds_mstart=0;\n  cds_mend=0;\n  if (CDstart==0 || CDend==0) return; //no CDS info\n  //restore normal coordinates, just in case\n  unxcoord();\n  int cdsadj=0;\n  if (CDphase=='1' || CDphase=='2') {\n      cdsadj=CDphase-'0';\n      }\n  /*\n   uint seqstart=CDstart;\n   uint seqend=CDend;\n  */\n  uint seqstart=exons.First()->start;\n  uint seqend=exons.Last()->end;\n  int s=0; //resulting nucleotide counter\n  if (strand=='-') {\n    for (int x=exons.Count()-1;x>=0;x--) {\n       uint sgstart=exons[x]->start;\n       uint sgend=exons[x]->end;\n       if (seqend<sgstart || seqstart>sgend) continue;\n       if (seqstart>=sgstart && seqstart<=sgend)\n             sgstart=seqstart; //seqstart within this segment\n       if (seqend>=sgstart && seqend<=sgend)\n             sgend=seqend; //seqend within this segment\n       s+=(int)(sgend-sgstart)+1;\n       if (CDstart>=sgstart && CDstart<=sgend) {\n             //CDstart in this segment\n             //and we are getting the whole transcript\n             cds_mend=s-(int)(CDstart-sgstart);\n             }\n       if (CDend>=sgstart && CDend<=sgend) {\n             //CDstart in this segment\n             //and we are getting the whole transcript\n             cds_mstart=s-(int)(CDend-cdsadj-sgstart);\n             }\n      } //for each exon\n    } // - strand\n   else { // + strand\n    for (int x=0;x<exons.Count();x++) {\n      uint sgstart=exons[x]->start;\n      uint sgend=exons[x]->end;\n      if (seqend<sgstart || seqstart>sgend) continue;\n      if (seqstart>=sgstart && seqstart<=sgend)\n            sgstart=seqstart; //seqstart within this segment\n      if (seqend>=sgstart && seqend<=sgend)\n            sgend=seqend; //seqend within this segment\n      s+=(int)(sgend-sgstart)+1;\n      /* for (uint i=sgstart;i<=sgend;i++) {\n          spliced[s]=gsubseq[i-gstart];\n          s++;\n          }//for each nt\n          */\n      if (CDstart>=sgstart && CDstart<=sgend) {\n            //CDstart in this segment\n            cds_mstart=s-(int)(sgend-CDstart-cdsadj);\n            }\n      if (CDend>=sgstart && CDend<=sgend) {\n            //CDend in this segment\n            cds_mend=s-(int)(sgend-CDend);\n            }\n      } //for each exon\n    } // + strand\n  //spliced[s]=0;\n  //if (rlen!=NULL) *rlen=s;\n  //return spliced;\n}\n\nchar* GffObj::getUnspliced(GFaSeqGet* faseq, int* rlen, GList<GSeg>* seglst) \n{\n    if (faseq==NULL) { GMessage(\"Warning: getUnspliced(NULL,.. ) called!\\n\");\n        return NULL;\n    }\n    //restore normal coordinates:\n    unxcoord();\n    if (exons.Count()==0) return NULL;\n    int fspan=end-start+1;\n    const char* gsubseq=faseq->subseq(start, fspan);\n    if (gsubseq==NULL) {\n        GError(\"Error getting subseq for %s (%d..%d)!\\n\", gffID, start, end);\n    }\n    char* unspliced=NULL;\n\n    int seqstart=exons.First()->start;\n    int seqend=exons.Last()->end;\n    \n    int unsplicedlen = 0;\n\n    unsplicedlen += seqend - seqstart + 1;\n\n    GMALLOC(unspliced, unsplicedlen+1); //allocate more here\n    //uint seqstart, seqend;\n\n    int s = 0; //resulting nucleotide counter\n    if (strand=='-') \n    {\n        if (seglst!=NULL)\n            seglst->Add(new GSeg(s+1,s+1+seqend-seqstart));\n        for (int i=seqend;i>=seqstart;i--) \n        {\n            unspliced[s] = ntComplement(gsubseq[i-start]);\n            s++;\n        }//for each nt\n    } // - strand\n    else \n    { // + strand\n        if (seglst!=NULL)\n            seglst->Add(new GSeg(s+1,s+1+seqend-seqstart));\n        for (int i=seqstart;i<=seqend;i++) \n        {\n            unspliced[s]=gsubseq[i-start];\n            s++;\n        }//for each nt\n    } // + strand\n    //assert(s <= unsplicedlen);\n    unspliced[s]=0;\n    if (rlen!=NULL) *rlen=s;\n    return unspliced;\n}\n\nchar* GffObj::getSpliced(GFaSeqGet* faseq, bool CDSonly, int* rlen, uint* cds_start, uint* cds_end,\n          GList<GSeg>* seglst) {\n  if (CDSonly && CDstart==0) return NULL;\n  if (faseq==NULL) { GMessage(\"Warning: getSpliced(NULL,.. ) called!\\n\");\n              return NULL;\n              }\n  //restore normal coordinates:\n  unxcoord();\n  if (exons.Count()==0) return NULL;\n  int fspan=end-start+1;\n  const char* gsubseq=faseq->subseq(start, fspan);\n  if (gsubseq==NULL) {\n        GError(\"Error getting subseq for %s (%d..%d)!\\n\", gffID, start, end);\n        }\n  if (fspan<(int)(end-start+1)) { //special case: stop coordinate was extended past the gseq length, must adjust\n     int endadj=end-start+1-fspan;\n     uint prevend=end;\n     end-=endadj;\n     if (CDend>end) CDend=end;\n     if (exons.Last()->end>end) {\n         exons.Last()->end=end; //this could get us into trouble if exon start is also > end\n         if (exons.Last()->start>exons.Last()->end) {\n            GError(\"GffObj::getSpliced() error: improper genomic coordinate %d on %s for %s\\n\",\n                  prevend,getGSeqName(), getID());\n            }\n         covlen-=endadj;\n         }\n     }\n  char* spliced=NULL;\n  GMALLOC(spliced, covlen+1); //allocate more here\n  uint seqstart, seqend;\n  int cdsadj=0;\n  if (CDphase=='1' || CDphase=='2') {\n      cdsadj=CDphase-'0';\n      }\n  if (CDSonly) {\n     seqstart=CDstart;\n     seqend=CDend;\n     if (strand=='-') seqend-=cdsadj;\n           else seqstart+=cdsadj;\n     }\n   else {\n     seqstart=exons.First()->start;\n     seqend=exons.Last()->end;\n     }\n  int s=0; //resulting nucleotide counter\n  if (strand=='-') {\n    for (int x=exons.Count()-1;x>=0;x--) {\n       uint sgstart=exons[x]->start;\n       uint sgend=exons[x]->end;\n       if (seqend<sgstart || seqstart>sgend) continue;\n       if (seqstart>=sgstart && seqstart<=sgend)\n             sgstart=seqstart; //seqstart within this segment\n       if (seqend>=sgstart && seqend<=sgend)\n             sgend=seqend; //seqend within this segment\n       if (seglst!=NULL)\n           seglst->Add(new GSeg(s+1,s+1+sgend-sgstart));\n       for (uint i=sgend;i>=sgstart;i--) {\n            spliced[s] = ntComplement(gsubseq[i-start]);\n            s++;\n            }//for each nt\n\n       if (!CDSonly && cds_start!=NULL && CDstart>0) {\n          if (CDstart>=sgstart && CDstart<=sgend) {\n             //CDstart in this segment\n             //and we are getting the whole transcript\n             *cds_end=s-(CDstart-sgstart);\n             }\n          if (CDend>=sgstart && CDend<=sgend) {\n             //CDstart in this segment\n             //and we are getting the whole transcript\n             *cds_start=s-(CDend-cdsadj-sgstart);\n             }\n         }//update local CDS coordinates\n      } //for each exon\n    } // - strand\n   else { // + strand\n    for (int x=0;x<exons.Count();x++) {\n      uint sgstart=exons[x]->start;\n      uint sgend=exons[x]->end;\n      if (seqend<sgstart || seqstart>sgend) continue;\n      if (seqstart>=sgstart && seqstart<=sgend)\n            sgstart=seqstart; //seqstart within this segment\n      if (seqend>=sgstart && seqend<=sgend)\n            sgend=seqend; //seqend within this segment\n      if (seglst!=NULL)\n          seglst->Add(new GSeg(s+1,s+1+sgend-sgstart));\n      for (uint i=sgstart;i<=sgend;i++) {\n          spliced[s]=gsubseq[i-start];\n          s++;\n          }//for each nt\n      if (!CDSonly && cds_start!=NULL && CDstart>0) {\n         if (CDstart>=sgstart && CDstart<=sgend) {\n            //CDstart in this segment\n            //and we are getting the whole transcript\n            *cds_start=s-(sgend-CDstart-cdsadj);\n            }\n         if (CDend>=sgstart && CDend<=sgend) {\n            //CDstart in this segment\n            //and we are getting the whole transcript\n            *cds_end=s-(sgend-CDend);\n            }\n        }//update local CDS coordinates\n      } //for each exon\n    } // + strand\n  spliced[s]=0;\n  if (rlen!=NULL) *rlen=s;\n  return spliced;\n}\n\nchar* GffObj::getSplicedTr(GFaSeqGet* faseq, bool CDSonly, int* rlen) {\n  if (CDSonly && CDstart==0) return NULL;\n  //restore normal coordinates:\n  unxcoord();\n  if (exons.Count()==0) return NULL;\n  int fspan=end-start+1;\n  const char* gsubseq=faseq->subseq(start, fspan);\n  if (gsubseq==NULL) {\n    GError(\"Error getting subseq for %s (%d..%d)!\\n\", gffID, start, end);\n    }\n\n  char* translation=NULL;\n  GMALLOC(translation, (int)(covlen/3)+1);\n  uint seqstart, seqend;\n  int cdsadj=0;\n  if (CDphase=='1' || CDphase=='2') {\n      cdsadj=CDphase-'0';\n      }\n  if (CDSonly) {\n     seqstart=CDstart;\n     seqend=CDend;\n     if (strand=='-') seqend-=cdsadj;\n           else seqstart+=cdsadj;\n     }\n   else {\n     seqstart=exons.First()->start;\n     seqend=exons.Last()->end;\n     }\n  Codon codon;\n  int nt=0; //codon nucleotide counter (0..2)\n  int aa=0; //aminoacid count\n  if (strand=='-') {\n    for (int x=exons.Count()-1;x>=0;x--) {\n       uint sgstart=exons[x]->start;\n       uint sgend=exons[x]->end;\n       if (seqend<sgstart || seqstart>sgend) continue;\n       if (seqstart>=sgstart && seqstart<=sgend)\n             sgstart=seqstart; //seqstart within this segment\n       if (seqend>=sgstart && seqend<=sgend) {\n             sgend=seqend; //seqend within this segment\n             }\n       for (uint i=sgend;i>=sgstart;i--) {\n            codon.nuc[nt]=ntComplement(gsubseq[i-start]);\n            nt++;\n            if (nt==3) {\n               nt=0;\n               translation[aa]=codon.translate();\n               aa++;\n               }\n            }//for each nt\n      } //for each exon\n    } // - strand\n   else { // + strand\n    for (int x=0;x<exons.Count();x++) {\n      uint sgstart=exons[x]->start;\n      uint sgend=exons[x]->end;\n      if (seqend<sgstart || seqstart>sgend) continue;\n      if (seqstart>=sgstart && seqstart<=sgend)\n            sgstart=seqstart; //seqstart within this segment\n      if (seqend>=sgstart && seqend<=sgend)\n            sgend=seqend; //seqend within this segment\n      for (uint i=sgstart;i<=sgend;i++) {\n          codon.nuc[nt]=gsubseq[i-start];\n          nt++;\n          if (nt==3) {\n             nt=0;\n             translation[aa]=codon.translate();\n             aa++;\n             }\n          }//for each nt\n        } //for each exon\n    } // + strand\n translation[aa]=0;\n if (rlen!=NULL) *rlen=aa;\n return translation;\n}\n\nvoid GffObj::printSummary(FILE* fout) {\n if (fout==NULL) fout=stdout;\n fprintf(fout, \"%s\\t%c\\t%d\\t%d\\t%4.2f\\t%4.1f\\n\", gffID,\n          strand, start, end, gscore, (float)qcov/10.0);\n}\n\nvoid decodeHexChars(char* dbuf, const char* s, int maxlen=1023) {\n\tint dlen=0;\n\tdbuf[0]=0;\n\tif (s==NULL) return;\n\tfor (const char* p=s;(*p)!=0 && dlen<maxlen;++p) {\n\t\tif (p[0]=='%' && isxdigit(p[1]) && isxdigit(p[2])) {\n\t\t\tint a=p[1];\n\t\t\tif (a>'Z') a^=0x20; //toupper()\n\t\t\tif (a>'9') a=10+(a-'A');\n\t\t\t      else a-='0';\n\t\t\tint b=p[2];\n\t\t\tif (b>'Z') b^=0x20;\n\t\t\tif (b>'9') b=10+(b-'A');\n\t\t\t      else b-='0';\n\t\t\tchar c=(char)((a<<4)+b);\n\t\t\tif (c==';') c='.';\n\t\t\tif (c>' ') {\n\t\t\t\tdbuf[dlen]=c;\n\t\t\t\t++p;++p;\n\t\t\t\t++dlen;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tdbuf[dlen]=*p;\n\t\t++dlen;\n\t}\n\tdbuf[dlen]=0;\n}\n\nvoid GffObj::printGxfLine(FILE* fout, const char* tlabel, const char* gseqname, bool iscds,\n                             uint segstart, uint segend, int exidx, char phase, bool gff3, bool cvtChars) {\n  char dbuf[1024];\n  strcpy(dbuf,\".\");\n  GffAttrs* xattrs=NULL;\n  if (exidx>=0) {\n     if (exons[exidx]->score) sprintf(dbuf,\"%.2f\", exons[exidx]->score);\n     xattrs=exons[exidx]->attrs;\n  }\n  if (phase==0 || !iscds) phase='.';\n  const char* ftype=iscds ? \"CDS\" : getSubfName();\n  const char* attrname=NULL;\n  const char* attrval=NULL;\n  if (gff3) {\n    fprintf(fout,\n      \"%s\\t%s\\t%s\\t%d\\t%d\\t%s\\t%c\\t%c\\tParent=%s\",\n      gseqname, tlabel, ftype, segstart, segend, dbuf, strand,\n      phase, gffID);\n    if (xattrs!=NULL) {\n      for (int i=0;i<xattrs->Count();i++) {\n        attrname=names->attrs.getName(xattrs->Get(i)->attr_id);\n        if (cvtChars) {\n          decodeHexChars(dbuf, xattrs->Get(i)->attr_val);\n          fprintf(fout,\";%s=%s\", attrname, dbuf);\n        } else {\n          fprintf(fout,\";%s=%s\", attrname, xattrs->Get(i)->attr_val);\n        }\n      }\n    }\n    fprintf(fout, \"\\n\");\n    } //GFF3\n  else {//for GTF -- we print only transcripts\n    //if (isValidTranscript())\n    fprintf(fout, \"%s\\t%s\\t%s\\t%d\\t%d\\t%s\\t%c\\t%c\\ttranscript_id \\\"%s\\\";\",\n           gseqname, tlabel, ftype, segstart, segend, dbuf, strand, phase, gffID);\n    //char* geneid=(geneID!=NULL)? geneID : gffID;\n    if (geneID)\n      fprintf(fout,\" gene_id \\\"%s\\\";\",geneID);\n    if (gene_name!=NULL) {\n       //fprintf(fout, \" gene_name \");\n       //if (gene_name[0]=='\"') fprintf (fout, \"%s;\",gene_name);\n       //              else fprintf(fout, \"\\\"%s\\\";\",gene_name);\n       fprintf(fout,\" gene_name \\\"%s\\\";\",gene_name);\n       }\n    if (xattrs!=NULL) {\n          for (int i=0;i<xattrs->Count();i++) {\n            if (xattrs->Get(i)->attr_val==NULL) continue;\n            attrname=names->attrs.getName(xattrs->Get(i)->attr_id);\n            fprintf(fout, \" %s \",attrname);\n            if (cvtChars) {\n              decodeHexChars(dbuf, xattrs->Get(i)->attr_val);\n              attrval=dbuf;\n            } else {\n              attrval=xattrs->Get(i)->attr_val;\n            }\n\n            if (attrval[0]=='\"') fprintf(fout, \"%s;\",attrval);\n                           else fprintf(fout, \"\\\"%s\\\";\",attrval);\n             }\n          }\n    //for GTF, also append the GffObj attributes to each exon line\n    if ((xattrs=this->attrs)!=NULL) {\n          for (int i=0;i<xattrs->Count();i++) {\n            if (xattrs->Get(i)->attr_val==NULL) continue;\n            attrname=names->attrs.getName(xattrs->Get(i)->attr_id);\n            fprintf(fout, \" %s \",attrname);\n            if (cvtChars) {\n              decodeHexChars(dbuf, xattrs->Get(i)->attr_val);\n              attrval=dbuf;\n            } else {\n              attrval=xattrs->Get(i)->attr_val;\n            }\n            if (attrval[0]=='\"') fprintf(fout, \"%s;\",attrval);\n                           else fprintf(fout, \"\\\"%s\\\";\",attrval);\n             }\n           }\n    fprintf(fout, \"\\n\");\n    }//GTF\n}\n\nvoid GffObj::printGxf(FILE* fout, GffPrintMode gffp, \n                   const char* tlabel, const char* gfparent, bool cvtChars) {\n //char tmpstr[255];\n char dbuf[1024];\n if (tlabel==NULL) {\n    tlabel=track_id>=0 ? names->tracks.Get(track_id)->name :\n         (char*)\"gffobj\" ;\n    }\n unxcoord();\n //if (exons.Count()==0) return;\n const char* gseqname=names->gseqs.Get(gseq_id)->name;\n bool gff3 = (gffp>=pgffAny);\n bool showCDS = (gffp==pgtfAny || gffp==pgtfCDS || gffp==pgffCDS || gffp==pgffAny || gffp==pgffBoth);\n bool showExon = (gffp<=pgtfExon || gffp==pgffAny || gffp==pgffExon || gffp==pgffBoth);\n if (gff3) {\n   //print GFF3 mRNA line:\n   if (gscore>0.0) sprintf(dbuf,\"%.2f\", gscore);\n          else strcpy(dbuf,\".\");\n   uint pstart, pend;\n   if (gffp==pgffCDS) {\n      pstart=CDstart;\n      pend=CDend;\n      }\n   else { pstart=start;pend=end; }\n   //const char* ftype=isTranscript() ? \"mRNA\" : getFeatureName();\n   const char* ftype=getFeatureName();\n   fprintf(fout,\n     \"%s\\t%s\\t%s\\t%d\\t%d\\t%s\\t%c\\t.\\tID=%s\",\n     gseqname, tlabel, ftype, pstart, pend, dbuf, strand, gffID);\n   if (CDstart>0 && !showCDS/* && !isCDS*/) fprintf(fout,\";CDS=%d-%d\",CDstart,CDend);\n   if (gfparent!=NULL) {\n      //parent override\n      fprintf(fout, \";Parent=%s\",gfparent);\n      }\n     else {\n       if (parent!=NULL && !parent->isDiscarded())\n           fprintf(fout, \";Parent=%s\",parent->getID());\n       }\n   if (geneID!=NULL)\n      fprintf(fout, \";geneID=%s\",geneID);\n   if (gene_name!=NULL)\n      fprintf(fout, \";gene_name=%s\",gene_name);\n   if (attrs!=NULL) {\n      for (int i=0;i<attrs->Count();i++) {\n        const char* attrname=names->attrs.getName(attrs->Get(i)->attr_id);\n        if (cvtChars) {\n          decodeHexChars(dbuf, attrs->Get(i)->attr_val);\n          fprintf(fout,\";%s=%s\", attrname, dbuf);\n        } else {\n          fprintf(fout,\";%s=%s\", attrname, attrs->Get(i)->attr_val);\n        }\n      }\n    }\n   fprintf(fout,\"\\n\");\n   }// gff3 mRNA line\n bool is_cds_only = (gffp==pgffBoth) ? false : isCDS;\n if (showExon) {\n   //print exons\n    if (isCDS && exons.Count()>0 &&\n        ((strand=='-' && exons.Last()->phase<'0') || (strand=='+' && exons.Last()->phase<'0')))\n         updateExonPhase();\n    for (int i=0;i<exons.Count();i++) {\n      printGxfLine(fout, tlabel, gseqname, is_cds_only, exons[i]->start, exons[i]->end, i, exons[i]->phase, gff3, cvtChars);\n      }\n    }//printing exons\n if (showCDS && !is_cds_only && CDstart>0) {\n\t  if (isCDS) {\n\t    for (int i=0;i<exons.Count();i++) {\n\t      printGxfLine(fout, tlabel, gseqname, true, exons[i]->start, exons[i]->end, i, exons[i]->phase, gff3, cvtChars);\n\t      }\n\t  }\n\t  else {\n\t\t\tGArray<GffCDSeg> cds(true,true);\n\t\t\tgetCDSegs(cds);\n\t\t\tfor (int i=0;i<cds.Count();i++) {\n\t\t\t\tprintGxfLine(fout, tlabel, gseqname, true, cds[i].start, cds[i].end, -1, cds[i].phase, gff3, cvtChars);\n\t\t\t\t}\n\t  }\n  } //showCDS\n}\n\nvoid GffObj::updateExonPhase() {\n  if (!isCDS) return;\n  int cdsacc=0;\n  if (CDphase=='1' || CDphase=='2') {\n      cdsacc+= 3-(CDphase-'0');\n      }\n  if (strand=='-') { //reverse strand\n     for (int i=exons.Count()-1;i>=0;i--) {\n         exons[i]->phase='0'+ (3-cdsacc%3)%3;\n         cdsacc+=exons[i]->end-exons[i]->start+1;\n         }\n     }\n    else { //forward strand\n     for (int i=0;i<exons.Count();i++) {\n         exons[i]->phase='0'+ (3-cdsacc%3)%3;\n         cdsacc+=exons[i]->end-exons[i]->start+1;\n         }\n     }\n}\n\n\nvoid GffObj::getCDSegs(GArray<GffCDSeg>& cds) {\n  GffCDSeg cdseg;\n  int cdsacc=0;\n  if (CDphase=='1' || CDphase=='2') {\n      cdsacc+= 3-(CDphase-'0');\n      }\n  if (strand=='-') {\n     for (int x=exons.Count()-1;x>=0;x--) {\n        uint sgstart=exons[x]->start;\n        uint sgend=exons[x]->end;\n        if (CDend<sgstart || CDstart>sgend) continue;\n        if (CDstart>=sgstart && CDstart<=sgend)\n              sgstart=CDstart; //cdstart within this segment\n        if (CDend>=sgstart && CDend<=sgend)\n              sgend=CDend; //cdend within this segment\n        cdseg.start=sgstart;\n        cdseg.end=sgend;\n        cdseg.exonidx=x;\n        //cdseg.phase='0'+(cdsacc>0 ? (3-cdsacc%3)%3 : 0);\n        cdseg.phase='0'+ (3-cdsacc%3)%3;\n        cdsacc+=sgend-sgstart+1;\n        cds.Add(cdseg);\n       } //for each exon\n     } // - strand\n    else { // + strand\n     for (int x=0;x<exons.Count();x++) {\n       uint sgstart=exons[x]->start;\n       uint sgend=exons[x]->end;\n       if (CDend<sgstart || CDstart>sgend) continue;\n       if (CDstart>=sgstart && CDstart<=sgend)\n             sgstart=CDstart; //seqstart within this segment\n       if (CDend>=sgstart && CDend<=sgend)\n             sgend=CDend; //seqend within this segment\n       cdseg.start=sgstart;\n       cdseg.end=sgend;\n       cdseg.exonidx=x;\n       //cdseg.phase='0'+(cdsacc>0 ? (3-cdsacc%3)%3 : 0);\n       cdseg.phase='0' + (3-cdsacc%3)%3 ;\n       cdsacc+=sgend-sgstart+1;\n       cds.Add(cdseg);\n       } //for each exon\n   } // + strand\n}\n"
  },
  {
    "path": "src/gff.h",
    "content": "#ifndef GFF_H\n#define GFF_H\n\n#define CUFFLINKS 1\n\n#include \"GBase.h\"\n#include \"gdna.h\"\n#include \"codons.h\"\n#include \"GFaSeqGet.h\"\n#include \"GList.hh\"\n#include \"GHash.hh\"\n\n#ifdef CUFFLINKS\n#include <boost/crc.hpp>  // for boost::crc_32_type\n#endif\n\n/*\nconst byte exMskMajSpliceL = 0x01;\nconst byte exMskMajSpliceR = 0x02;\nconst byte exMskMinSpliceL = 0x04;\nconst byte exMskMinSpliceR = 0x08;\nconst byte exMskTag = 0x80;\n*/\n\n//reserved Gffnames::feats entries -- basic feature types\nextern const int gff_fid_mRNA; // \"mRNA\" feature name\nextern const int gff_fid_transcript; // *RNA, *transcript feature name\nextern const int gff_fid_exon;\n\nextern const uint GFF_MAX_LOCUS;\nextern const uint GFF_MAX_EXON;\nextern const uint GFF_MAX_INTRON;\n\nextern const uint gfo_flag_CHILDREN_PROMOTED;\nextern const uint gfo_flag_HAS_ERRORS;\nextern const uint gfo_flag_IS_GENE;\nextern const uint gfo_flag_HAS_GFF_ID; //found a GFF3 formatted main feature with its own ID\nextern const uint gfo_flag_BY_EXON;  //created by subfeature (exon) directly\n                      //(GTF2 and some chado gff3 dumps with exons given before their mRNA)\nextern const uint gfo_flag_IS_TRANSCRIPT; //recognized as '*RNA' or '*transcript'\nextern const uint gfo_flag_DISCARDED; //should not be printed under the \"transcriptsOnly\" directive\nextern const uint gfo_flag_LST_KEEP; //GffObj from GffReader::gflst is to be kept (not deallocated)\n                                     //when GffReader is destroyed\nextern const uint gfo_flag_LEVEL_MSK; //hierarchical level: 0 = no parent\nextern const byte gfo_flagShift_LEVEL;\n\nextern bool gff_show_warnings;\n\n#define GFF_LINELEN 2048\n#define ERR_NULL_GFNAMES \"Error: GffObj::%s requires a non-null GffNames* names!\\n\"\n\n\nenum GffExonType {\n  exgffIntron=-1, // useless \"intron\" feature\n\texgffNone=0,  //not a recognizable exon or CDS segment\n  exgffStart, //from \"start_codon\" feature (within CDS)\n  exgffStop, //from \"stop_codon\" feature (may be outside CDS)\n  exgffCDS,  //from \"CDS\" feature\n  exgffUTR,  //from \"UTR\" feature\n  exgffCDSUTR, //from a merge of UTR and CDS feature\n  exgffExon, //from \"exon\" feature\n};\n\nconst char* strExonType(char xtype);\n\nclass GffReader;\n\nclass GffLine {\n    char* _parents; //stores a copy of the Parent attribute value,\n       //with commas replaced by \\0\n    int _parents_len;\n public:\n    char* dupline; //duplicate of original line\n    char* line; //this will have tabs replaced by \\0\n    int llen;\n    char* gseqname;\n    char* track;\n    char* ftype; //feature name: mRNA/gene/exon/CDS\n    char* info; //the last, attributes' field, unparsed\n    uint fstart;\n    uint fend;\n    uint qstart; //overlap coords on query, if available\n    uint qend;\n    uint qlen; //query len, if given\n    double score;\n    char strand;\n    union {\n    \tuint8_t flags;\n    \tstruct {\n    \t\tbool is_exonlike:2;\n    \t};\n    \tstruct {\n    \t    bool is_cds:1; //\"cds\" or \"start/stop_codon\" features\n    \t    bool is_exon:1; //\"exon\" and \"utr\" features\n    \t    bool is_transcript:1; //if current feature is *RNA or *transcript\n    \t    bool is_gene:1; //if current feature is *gene\n    \t    bool is_gff3:1; //if the line appears to be in GFF3 format\n    \t    bool can_discard:1; //flag unwanted/unrecognized parent features\n    \t    bool skipLine:1;\n    \t};\n    };\n    char exontype; // gffExonType\n    char phase;  // '.' , '0', '1' or '2'\n    // -- allocated strings:\n    char* gene_name; //value of gene_name attribute (GTF) if present or Name attribute of a gene feature (GFF3)\n    char* gene_id; //value of gene_id attribute (GTF) if present or ID attribute of a gene feature (GFF3)\n    //\n    char** parents; //for GTF only parents[0] is used\n    int num_parents;\n    char* ID;     // if a ID=.. attribute was parsed, or a GTF with 'transcript' line (transcript_id)\n    GffLine(GffReader* reader, const char* l); //parse the line accordingly\n    void discardParent() {\n    \tGFREE(_parents);\n    \t_parents_len=0;\n    \tnum_parents=0;\n    \tparents=NULL;\n    }\n    char* extractAttr(const char* pre, bool caseStrict=false, bool enforce_GTF2=false);\n    GffLine(GffLine* l):_parents(NULL), _parents_len(0),\n    \t\tdupline(NULL), line(NULL), llen(0), gseqname(NULL), track(NULL),\n    \t\tftype(NULL), info(NULL), fstart(0), fend(0), qstart(0), qend(0), qlen(0),\n    \t\tscore(0), strand(0), flags(0), exontype(0), phase(0),\n    \t\tgene_name(NULL), gene_id(NULL),\n    \t\tparents(NULL), num_parents(0), ID(NULL) { //a copy constructor\n    \tif (l==NULL || l->line==NULL)\n    \t\tGError(\"Error: invalid GffLine(l)\\n\");\n    \tmemcpy((void*)this, (void*)l, sizeof(GffLine));\n    \tGMALLOC(line, llen+1);\n    \tmemcpy(line, l->line, llen+1);\n    \tGMALLOC(dupline, llen+1);\n    \tmemcpy(dupline, l->dupline, llen+1);\n    \t//--offsets within line[]\n    \tgseqname=line+(l->gseqname-l->line);\n    \ttrack=line+(l->track-l->line);\n    \tftype=line+(l->ftype-l->line);\n    \tinfo=line+(l->info-l->line);\n    \tif (num_parents>0 && parents) {\n    \t\tparents=NULL; //re-init, just copied earlier\n    \t\tGMALLOC(parents, num_parents*sizeof(char*));\n    \t\t//_parents_len=l->_parents_len; copied above\n    \t\t_parents=NULL; //re-init, forget pointer copy\n    \t\tGMALLOC(_parents, _parents_len);\n    \t\tmemcpy(_parents, l->_parents, _parents_len);\n    \t\tfor (int i=0;i<num_parents;i++) {\n    \t\t\tparents[i]=_parents+(l->parents[i] - l->_parents);\n    \t\t}\n    \t}\n    \t//-- allocated string copies:\n    \tID=Gstrdup(l->ID);\n    \tif (l->gene_name!=NULL)\n    \t\tgene_name=Gstrdup(l->gene_name);\n    \tif (l->gene_id!=NULL)\n    \t\tgene_id=Gstrdup(l->gene_id);\n    }\n    GffLine():_parents(NULL), _parents_len(0),\n    \t\tdupline(NULL), line(NULL), llen(0), gseqname(NULL), track(NULL),\n    \t\tftype(NULL), info(NULL), fstart(0), fend(0), qstart(0), qend(0), qlen(0),\n    \t\tscore(0), strand(0), flags(0), exontype(0), phase(0),\n    \t\tgene_name(NULL), gene_id(NULL),\n    \t\tparents(NULL), num_parents(0), ID(NULL) {\n    }\n    ~GffLine() {\n    \tGFREE(dupline);\n    \tGFREE(line);\n    \tGFREE(_parents);\n    \tGFREE(parents);\n    \tGFREE(ID);\n    \tGFREE(gene_name);\n    \tGFREE(gene_id);\n    }\n};\n\nclass GffAttr {\n public:\n   int attr_id;\n   char* attr_val;\n   GffAttr(int an_id, const char* av=NULL) {\n     attr_id=an_id;\n     attr_val=NULL;\n     setValue(av);\n     }\n  ~GffAttr() {\n     GFREE(attr_val);\n     }\n  void setValue(const char* av) {\n     if (attr_val!=NULL) {\n        GFREE(attr_val);\n        }\n     if (av==NULL || av[0]==0) return;\n     //trim spaces\n     const char* vstart=av;\n     while (*vstart==' ') av++;\n     const char* vend=vstart;\n     bool keep_dq=false;\n     while (vend[1]!=0) {\n        if (*vend==' ' && vend[1]!=' ') keep_dq=true;\n          else if (*vend==';') keep_dq=true;\n        vend++;\n        }\n     //remove spaces at the end:\n     while (*vend==' ' && vend!=vstart) vend--;\n     //practical clean-up: if it doesn't have any internal spaces just strip those useless double quotes\n     if (!keep_dq && *vstart=='\"' && *vend=='\"') {\n               vend--;\n               vstart++;\n               }\n     attr_val=Gstrdup(vstart, vend);\n     }\n  bool operator==(GffAttr& d){\n      return (this==&d);\n      }\n  bool operator>(GffAttr& d){\n     return (this>&d);\n     }\n  bool operator<(GffAttr& d){\n    return (this<&d);\n    }\n\n };\n\nclass GffNameList;\nclass GffNames;\n\nclass GffNameInfo {\n  friend class GffNameList;\n public:\n   int idx;\n   char* name;\n   GffNameInfo(const char* n=NULL):idx(-1),name(NULL) {\n     if (n) name=Gstrdup(n);\n     }\n\n   ~GffNameInfo() {\n      GFREE(name);\n     }\n\n   bool operator==(GffNameInfo& d){\n       return (strcmp(this->name, d.name)==0);\n       }\n   bool operator<(GffNameInfo& d){\n     return (strcmp(this->name, d.name)<0);\n     }\n};\n\nclass GffNameList:public GList<GffNameInfo> {\n  friend class GffNameInfo;\n  friend class GffNames;\nprotected:\n  GHash<GffNameInfo> byName;//hash with shared keys\n  int idlast; //fList index of last added/reused name\n  void addStatic(const char* tname) {// fast add\n     GffNameInfo* f=new GffNameInfo(tname);\n     idlast=this->Add(f);\n     f->idx=idlast;\n     byName.shkAdd(f->name,f);\n     }\npublic:\n GffNameList(int init_capacity=6):GList<GffNameInfo>(init_capacity, false,true,true), byName(false) {\n    idlast=-1;\n    setCapacity(init_capacity);\n    }\n char* lastNameUsed() { return idlast<0 ? NULL : Get(idlast)->name; }\n int lastNameId() { return idlast; }\n char* getName(int nid) { //retrieve name by its ID\n   if (nid<0 || nid>=fCount)\n         GError(\"GffNameList Error: invalid index (%d)\\n\",nid);\n   return fList[nid]->name;\n   }\n\n int addName(const char* tname) {//returns or create an id for the given name\n   //check idlast first, chances are it's the same feature name checked\n   /*if (idlast>=0 && strcmp(fList[idlast]->name,tname)==0)\n       return idlast;*/\n   GffNameInfo* f=byName.Find(tname);\n   int fidx=-1;\n   if (f!=NULL) fidx=f->idx;\n     else {//add new entry\n      f=new GffNameInfo(tname);\n      fidx=this->Add(f);\n      f->idx=fidx;\n      byName.shkAdd(f->name,f);\n      }\n   idlast=fidx;\n   return fidx;\n   }\n\n int addNewName(const char* tname) {\n    GffNameInfo* f=new GffNameInfo(tname);\n    int fidx=this->Add(f);\n    f->idx=fidx;\n    byName.shkAdd(f->name,f);\n    return fidx;\n    }\n\n int getId(const char* tname) { //only returns a name id# if found\n    GffNameInfo* f=byName.Find(tname);\n    if (f==NULL) return -1;\n    return f->idx;\n    }\n int removeName() {\n   GError(\"Error: removing names from GffNameList not allowed!\\n\");\n   return -1;\n   }\n};\n\nclass GffNames {\n public:\n   int numrefs;\n   GffNameList tracks;\n   GffNameList gseqs;\n   GffNameList attrs;\n   GffNameList feats; //feature names: 'mRNA', 'exon', 'CDS' etc.\n   GffNames():tracks(),gseqs(),attrs(), feats() {\n    numrefs=0;\n    //the order below is critical!\n    //has to match: gff_fid_mRNA, gff_fid_exon\n    feats.addStatic(\"mRNA\");//index 0=gff_fid_mRNA\n    feats.addStatic(\"transcript\");//index 1=gff_fid_transcript\n    feats.addStatic(\"exon\");//index 1=gff_fid_exon\n    //feats.addStatic(\"CDS\"); //index 2=gff_fid_CDS\n    }\n};\n\nvoid gffnames_ref(GffNames* &n);\nvoid gffnames_unref(GffNames* &n);\n\nenum GffPrintMode {\n  pgtfAny, //print record as read\n  pgtfExon,\n  pgtfCDS,\n  pgffAny, //print record as read\n  pgffExon,\n  pgffCDS,\n  pgffBoth,\n};\n\n\nclass GffAttrs:public GList<GffAttr> {\n  public:\n    GffAttrs():GList<GffAttr>(false,true,false) { }\n    void add_or_update(GffNames* names, const char* attrname, const char* val) {\n      int aid=names->attrs.getId(attrname);\n      if (aid>=0) {\n         //attribute found in the dictionary\n         for (int i=0;i<Count();i++) {\n            //do we have it?\n            if (aid==Get(i)->attr_id) {\n                //update the value\n                Get(i)->setValue(val);\n                return;\n                }\n            }\n         }\n        else {\n         aid=names->attrs.addNewName(attrname);\n         }\n      this->Add(new GffAttr(aid, val));\n      }\n\n    char* getAttr(GffNames* names, const char* attrname) {\n      int aid=names->attrs.getId(attrname);\n      if (aid>=0)\n        for (int i=0;i<Count();i++)\n          if (aid==Get(i)->attr_id) return Get(i)->attr_val;\n      return NULL;\n      }\n    char* getAttr(int aid) {\n      if (aid>=0)\n        for (int i=0;i<Count();i++)\n          if (aid==Get(i)->attr_id) return Get(i)->attr_val;\n      return NULL;\n      }\n};\n\n\nclass GffExon : public GSeg {\n public:\n  void* uptr; //for later extensions\n  GffAttrs* attrs; //other attributes kept for this exon\n  double score; // gff score column\n  char phase; //GFF phase column - for CDS segments only\n             // '.' = undefined (UTR), '0','1','2' for CDS exons\n  char exontype; // 1=\"exon\" 2=\"cds\" 3=\"utr\" 4=\"stop_codon\"\n  int qstart; // for mRNA/protein exon mappings: coordinates on query\n  int qend;\n  GffExon(int s=0, int e=0, double sc=0, char fr=0, int qs=0, int qe=0, char et=0) {\n    uptr=NULL;\n    attrs=NULL;\n    if (s<e) {\n      start=s;\n      end=e;\n      }\n   else {\n     start=e;\n     end=s;\n    }\n   if (qs<qe) {\n     qstart=qs;\n     qend=qe;\n     } else {\n     qstart=qe;\n     qend=qs;\n     }\n   score=sc;\n   phase=fr;\n   exontype=et;\n   } //constructor\n\n char* getAttr(GffNames* names, const char* atrname) {\n   if (attrs==NULL || names==NULL || atrname==NULL) return NULL;\n   return attrs->getAttr(names, atrname);\n   }\n\n char* getAttr(int aid) {\n   if (attrs==NULL) return NULL;\n   return attrs->getAttr(aid);\n   }\n\n ~GffExon() { //destructor\n   if (attrs!=NULL) delete attrs;\n   }\n};\n\n\nclass GffCDSeg:public GSeg {\n public:\n  char phase;\n  int exonidx;\n};\n//one GFF mRNA object -- e.g. a mRNA with its exons and/or CDS segments\nclass GffObj:public GSeg {\n  //utility segment-merging function for addExon() \n  void expandExon(int xovl, uint segstart, uint segend,\n       char exontype, double sc, char fr, int qs, int qe);\n protected:\n   //coordinate transformation data:\n   uint xstart; //absolute genomic coordinates of reference region\n   uint xend;\n   char xstatus; //coordinate transform status:\n            //0 : (start,end) coordinates are absolute\n            //'+' : (start,end) coords are relative to xstart..xend region\n            //'-' : (start,end) are relative to the reverse complement of xstart..xend region\n   //--\n   char* gffID; // ID name for mRNA (parent) feature\n   char* gene_name; //value of gene_name attribute (GTF) if present or Name attribute of the parent gene feature (GFF3)\n   char* geneID; //value of gene_id attribute (GTF) if present or ID attribute of a parent gene feature (GFF3)\n   unsigned int flags;\n   //-- friends:\n   friend class GffReader;\n   friend class GffExon;\npublic:\n  static GffNames* names; // dictionary storage that holds the various attribute names etc.\n  int track_id; // index of track name in names->tracks\n  int gseq_id; // index of genomic sequence name in names->gseqs\n  int ftype_id; // index of this record's feature name in names->feats, or the special gff_fid_mRNA value\n  int exon_ftype_id; //index of child subfeature name in names->feats (that subfeature stored in \"exons\")\n                   //if ftype_id==gff_fid_mRNA then this value is ignored\n  GList<GffExon> exons; //for non-mRNA entries, these can be any subfeature of type subftype_id\n  GPVec<GffObj> children;\n  GffObj* parent;\n  int udata; //user data, flags etc.\n  void* uptr; //user pointer (to a parent object, cluster, locus etc.)\n  GffObj* ulink; //link to another GffObj (user controlled field)\n  // mRNA specific fields:\n  bool isCDS; //just a CDS, no UTRs\n  bool partial; //partial CDS\n  uint CDstart; //CDS start coord\n  uint CDend;   //CDS end coord\n  char CDphase; //initial phase for CDS start\n  bool hasErrors() { return ((flags & gfo_flag_HAS_ERRORS)!=0); }\n  void hasErrors(bool v) {\n      if (v) flags |= gfo_flag_HAS_ERRORS;\n        else flags &= ~gfo_flag_HAS_ERRORS;\n      }\n  bool hasGffID() { return ((flags & gfo_flag_HAS_GFF_ID)!=0); }\n  void hasGffID(bool v) {\n      if (v) flags |= gfo_flag_HAS_GFF_ID;\n        else flags &= ~gfo_flag_HAS_GFF_ID;\n      }\n  bool createdByExon() { return ((flags & gfo_flag_BY_EXON)!=0); }\n  void createdByExon(bool v) {\n      if (v) flags |= gfo_flag_BY_EXON;\n        else flags &= ~gfo_flag_BY_EXON;\n      }\n  bool isGene() { return ((flags & gfo_flag_IS_GENE)!=0); }\n  void isGene(bool v) {\n      if (v) flags |= gfo_flag_IS_GENE;\n        else flags &= ~gfo_flag_IS_GENE;\n      }\n  bool isDiscarded() { return ((flags & gfo_flag_DISCARDED)!=0); }\n  void isDiscarded(bool v) {\n      if (v) flags |= gfo_flag_DISCARDED;\n        else flags &= ~gfo_flag_DISCARDED;\n      }\n      \n  bool isUsed() { return ((flags & gfo_flag_LST_KEEP)!=0); }\n  void isUsed(bool v) {\n      if (v) flags |= gfo_flag_LST_KEEP;\n        else flags &= ~gfo_flag_LST_KEEP;\n      }\n  bool isTranscript() { return ((flags & gfo_flag_IS_TRANSCRIPT)!=0); }\n  void isTranscript(bool v) {\n      if (v) flags |= gfo_flag_IS_TRANSCRIPT;\n        else flags &= ~gfo_flag_IS_TRANSCRIPT;\n      }\n  bool promotedChildren() { return ((flags & gfo_flag_CHILDREN_PROMOTED)!=0); }\n  void promotedChildren(bool v) {\n    if (v) flags |= gfo_flag_CHILDREN_PROMOTED;\n      else flags &= ~gfo_flag_CHILDREN_PROMOTED;\n     }\n  void setLevel(byte v) {\n    if (v==0) flags &= ~gfo_flag_LEVEL_MSK;\n         else flags &= ~(((uint)v) << gfo_flagShift_LEVEL);\n    }\n  byte incLevel() {\n    uint v=((flags & gfo_flag_LEVEL_MSK) >> gfo_flagShift_LEVEL);\n    v++;\n    flags &= ~(v << gfo_flagShift_LEVEL);\n    return v;\n    }\n  byte getLevel() {\n    return ((byte)((flags & gfo_flag_LEVEL_MSK) >> gfo_flagShift_LEVEL));\n    }\n\n  bool isValidTranscript() { \n    //return (ftype_id==gff_fid_mRNA && exons.Count()>0);\n    return (isTranscript() && exons.Count()>0);\n    }\n  \n\n  int addExon(uint segstart, uint segend, double sc=0, char fr='.',\n             int qs=0, int qe=0, bool iscds=false, char exontype=0);\n\n  int addExon(GffReader* reader, GffLine* gl, bool keepAttr=false, bool noExonAttr=true);\n\n  void removeExon(int idx);\n  void removeExon(GffExon* p);\n  char  strand; //true if features are on the reverse complement strand\n  double gscore;\n  double uscore; //custom, user-computed score, if needed\n  int covlen; //total coverage of  reference genomic sequence (sum of maxcf segment lengths)\n  \n   //--------- optional data:\n  int qlen; //query length, start, end - if available\n  int qstart;\n  int qend;\n  int qcov; //query coverage - percent\n  GffAttrs* attrs; //other gff3 attributes found for the main mRNA feature\n   //constructor by gff line parsing:\n  GffObj(GffReader* gfrd, GffLine* gffline, bool keepAttrs=false, bool noExonAttr=true);\n   //if gfline->Parent!=NULL then this will also add the first sub-feature\n   // otherwise, only the main feature is created\n  void copyAttrs(GffObj* from);\n  void clearAttrs() {\n    if (attrs!=NULL) {\n      bool sharedattrs=(exons.Count()>0 && exons[0]->attrs==attrs);\n      delete attrs; attrs=NULL;\n      if (sharedattrs) exons[0]->attrs=NULL;\n      }\n    }\n  GffObj(char* anid=NULL):GSeg(0,0), exons(true,true,false), children(1,false) {\n                                   //exons: sorted, free, non-unique\n       gffID=NULL;\n       uptr=NULL;\n       ulink=NULL;\n       flags=0;\n       udata=0;\n       parent=NULL;\n       ftype_id=-1;\n       exon_ftype_id=-1;\n       if (anid!=NULL) gffID=Gstrdup(anid);\n       gffnames_ref(names);\n       qlen=0;\n       qstart=0;\n       qend=0;\n       qcov=0;\n       partial=true;\n       isCDS=false;\n       CDstart=0; // hasCDS <=> CDstart>0\n       CDend=0;\n       CDphase=0;\n       gseq_id=-1;\n       track_id=-1;\n       xstart=0;\n       xend=0;\n       xstatus=0;\n       strand='.';\n       gscore=0;\n       uscore=0;\n       attrs=NULL;\n       covlen=0;\n       gene_name=NULL;\n       geneID=NULL;\n       }\n   ~GffObj() {\n       GFREE(gffID);\n       GFREE(gene_name);\n       GFREE(geneID);\n       clearAttrs();\n       gffnames_unref(names);\n       }\n   //--------------\n   GffObj* finalize(GffReader* gfr, bool mergeCloseExons=false, \n               bool keepAttrs=false, bool noExonAttr=true); \n               //complete parsing: must be called in order to merge adjacent/close proximity subfeatures\n   void parseAttrs(GffAttrs*& atrlist, char* info, bool isExon=false);\n   const char* getSubfName() { //returns the generic feature type of the entries in exons array\n     //int sid=exon_ftype_id;\n     //if (sid==gff_fid_exon && isCDS) sid=gff_fid_CDS;\n     return names->feats.getName(exon_ftype_id);\n     }\n   void addCDS(uint cd_start, uint cd_end, char phase=0);\n   \n   bool monoFeature() {\n     return (exons.Count()==0 || \n          (exons.Count()==1 &&  //exon_ftype_id==ftype_id && \n              exons[0]->end==this->end && exons[0]->start==this->start));\n     }\n\n   bool hasCDS() { return (CDstart>0); }\n\n   const char* getFeatureName() {\n     return names->feats.getName(ftype_id);\n     }\n   void setFeatureName(const char* feature);\n   \n   void addAttr(const char* attrname, const char* attrvalue);\n   int removeAttr(const char* attrname, const char* attrval=NULL);\n   int removeAttr(int aid, const char* attrval=NULL);\n   int removeExonAttr(GffExon& exon, const char* attrname, const char* attrval=NULL);\n   int removeExonAttr(GffExon& exon, int aid, const char* attrval=NULL);\n   const char* getAttrName(int i) {\n     if (attrs==NULL) return NULL;\n     return names->attrs.getName(attrs->Get(i)->attr_id);\n     }\n   char* getAttr(const char* attrname, bool checkFirstExon=false) {\n     if (names==NULL || attrname==NULL) return NULL;\n     char* r=NULL;\n     if (attrs==NULL) {\n         if (!checkFirstExon) return NULL;\n         }\n       else r=attrs->getAttr(names, attrname);\n     if (r!=NULL) return r;\n     if (checkFirstExon && exons.Count()>0) {\n        r=exons[0]->getAttr(names, attrname);\n        }\n     return r; \n     }\n\n   char* getExonAttr(GffExon* exon, const char* attrname) {\n      if (exon==NULL || attrname==NULL) return NULL;\n      return exon->getAttr(names, attrname);\n      }\n\n   char* getExonAttr(int exonidx, const char* attrname) {\n      if (exonidx<0 || exonidx>=exons.Count() || attrname==NULL) return NULL;\n      return exons[exonidx]->getAttr(names, attrname);\n      }\n\n   char* getAttrValue(int i) {\n     if (attrs==NULL) return NULL;\n     return attrs->Get(i)->attr_val;\n     }\n   const char* getGSeqName() {\n     return names->gseqs.getName(gseq_id);\n     }\n\n   const char* getRefName() {\n     return names->gseqs.getName(gseq_id);\n     }\n   void setRefName(const char* newname);\n   \n   const char* getTrackName() {\n     return names->tracks.getName(track_id);\n     }\n   bool exonOverlap(uint s, uint e) {//check if ANY exon overlaps given segment\n      //ignores strand!\n      if (s>e) Gswap(s,e);\n      for (int i=0;i<exons.Count();i++) {\n         if (exons[i]->overlap(s,e)) return true;\n         }\n      return false;\n      }\n    bool exonOverlap(GffObj& m) {//check if ANY exon overlaps given segment\n      //if (gseq_id!=m.gseq_id) return false;\n      // ignores strand and gseq_id, must check in advance\n      for (int i=0;i<exons.Count();i++) {\n         for (int j=0;j<m.exons.Count();j++) {\n            if (exons[i]->start>m.exons[j]->end) continue;\n            if (m.exons[j]->start>exons[i]->end) break;\n            //-- overlap if we are here:\n            return true;\n            }\n         }\n      return false;\n      }\n    \n    int exonOverlapIdx(uint s, uint e, int* ovlen=NULL) {\n      //return the exons' index for the overlapping OR ADJACENT exon\n      //ovlen, if given, will return the overlap length\n      if (s>e) Gswap(s,e);\n      s--;e++; //to also catch adjacent exons\n      for (int i=0;i<exons.Count();i++) {\n            if (exons[i]->start>e) break;\n            if (s>exons[i]->end) continue;\n            //-- overlap if we are here:\n            if (ovlen!=NULL) {\n              s++;e--;\n              int ovlend= (exons[i]->end>e) ? e : exons[i]->end;\n              *ovlen= ovlend - ((s>exons[i]->start)? s : exons[i]->start)+1;\n              }\n            return i;\n            } //for each exon\n      *ovlen=0;\n      return -1;\n      }\n     \n    int exonOverlapLen(GffObj& m) {\n      if (start>m.end || m.start>end) return 0;\n      int i=0;\n      int j=0;\n      int ovlen=0;\n      while (i<exons.Count() && j<m.exons.Count()) {\n        uint istart=exons[i]->start;\n        uint iend=exons[i]->end;\n        uint jstart=m.exons[j]->start;\n        uint jend=m.exons[j]->end;\n        if (istart>jend) { j++; continue; }\n        if (jstart>iend) { i++; continue; }\n        //exon overlap\n        uint ovstart=GMAX(istart,jstart);\n        if (iend<jend) {\n           ovlen+=iend-ovstart+1;\n           i++;\n           }\n        else {\n           ovlen+=jend-ovstart+1;\n           j++;\n           }\n        }//while comparing exons\n      return ovlen;\n      }\n\n    bool exonOverlap(GffObj* m) {\n      return exonOverlap(*m);\n      }\n   //---------- coordinate transformation\n   void xcoord(uint grstart, uint grend, char xstrand='+') {\n     //relative coordinate transform, and reverse-complement transform if xstrand is '-'\n     //does nothing if xstatus is the same already\n     if (xstatus) {\n          if (xstatus==xstrand && grstart==xstart && grend==xend) return;\n          unxcoord();//restore original coordinates\n          }\n     xstatus=xstrand;\n     xstart=grstart;\n     xend=grend;\n     if (CDstart>0) xcoordseg(CDstart, CDend);\n     for (int i=0;i<exons.Count();i++) {\n         xcoordseg(exons[i]->start, exons[i]->end);\n         }\n     if (xstatus=='-') {\n       exons.Reverse();\n       int flen=end-start;\n       start=xend-end+1;\n       end=start+flen;\n       }\n      else {\n       start=start-xstart+1;\n       end=end-xstart+1;\n       }\n     }\n\n   //transform an arbitrary segment based on current xstatus/xstart-xend\n   void xcoordseg(uint& segstart, uint &segend) {\n     if (xstatus==0) return;\n     if (xstatus=='-') {\n       int flen=segend-segstart;\n       segstart=xend-segend+1;\n       segend=segstart+flen;\n       return;\n       }\n     else {\n       segstart=segstart-xstart+1;\n       segend=segend-xstart+1;\n       }\n     }\n\n   void unxcoord() { //revert back to absolute genomic/gff coordinates if xstatus==true\n     if (xstatus==0) return; //nothing to do, no transformation appplied\n     if (CDstart>0) unxcoordseg(CDstart, CDend);\n     //restore all GffExon intervals too\n     for (int i=0;i<exons.Count();i++) {\n         unxcoordseg(exons[i]->start, exons[i]->end);\n         }\n     if (xstatus=='-') {\n        exons.Reverse();\n        int flen=end-start;\n        start=xend-end+1;\n        end=start+flen;\n        }\n      else {\n        start=start+xstart-1;\n        end=end+xstart-1;\n        }\n     xstatus=0;\n     }\n   void unxcoordseg(uint& astart, uint &aend) {\n     //restore an arbitrary interval -- does NOT change the transform state!\n     if (xstatus==0) return;\n     if (xstatus=='-') {\n        int flen=aend-astart;\n        astart=xend-aend+1;\n        aend=astart+flen;\n        }\n      else {\n        astart=astart+xstart-1;\n        aend=aend+xstart-1;\n        }\n     }\n   //---------------------\n   bool operator==(GffObj& d){\n       return (gseq_id==d.gseq_id && start==d.start && end==d.end && strcmp(gffID, d.gffID)==0);\n       }\n   bool operator>(GffObj& d){\n      if (gseq_id!=d.gseq_id) return (gseq_id>d.gseq_id);\n      if (start==d.start) {\n         if (getLevel()==d.getLevel()) {\n             if (end==d.end) return (strcmp(gffID, d.gffID)>0);\n                        else return (end>d.end);\n             } else return (getLevel()>d.getLevel());\n         } else return (start>d.start);\n      }\n   bool operator<(GffObj& d){\n     if (gseq_id!=d.gseq_id) return (gseq_id<d.gseq_id);\n     if (start==d.start) {\n         if (getLevel()==d.getLevel()) {\n            if (end==d.end) return strcmp(gffID, d.gffID)<0;\n                     else return end<d.end;\n            } else return (getLevel()<d.getLevel());\n        } else return (start<d.start);\n     }\n   char* getID() { return gffID; }\n   char* getGeneID() { return geneID; }\n   char* getGeneName() { return gene_name; }\n   void setGeneName(const char* gname) {\n        GFREE(gene_name);\n        if (gname) gene_name=Gstrdup(gname);\n        }\n   void setGeneID(const char* gene_id) {\n        GFREE(geneID);\n        if (gene_id) geneID=Gstrdup(gene_id);\n        }\n   int addSeg(GffLine* gfline);\n   int addSeg(int fnid, GffLine* gfline);\n   void getCDSegs(GArray<GffCDSeg>& cds);\n\n   void updateExonPhase(); //for CDS-only features, updates GExon::phase\n\n   void printGxfLine(FILE* fout, const char* tlabel, const char* gseqname, \n          bool iscds, uint segstart, uint segend, int exidx, char phase, bool gff3, bool cvtChars=false);\n   void printGxf(FILE* fout, GffPrintMode gffp=pgffExon, \n             const char* tlabel=NULL, const char* gfparent=NULL, bool cvtChars=false);\n   void printGtf(FILE* fout, const char* tlabel=NULL, bool cvtChars=false) {\n      printGxf(fout, pgtfAny, tlabel, NULL, cvtChars);\n      }\n   void printGff(FILE* fout, const char* tlabel=NULL,\n                                const char* gfparent=NULL, bool cvtChars=false) {\n      printGxf(fout, pgffAny, tlabel, gfparent, cvtChars);\n      }\n   void printTranscriptGff(FILE* fout, char* tlabel=NULL,\n                            bool showCDS=false, const char* gfparent=NULL, bool cvtChars=false) {\n      if (isValidTranscript())\n         printGxf(fout, showCDS ? pgffBoth : pgffExon, tlabel, gfparent, cvtChars);\n      }\n   void printSummary(FILE* fout=NULL);\n   void getCDS_ends(uint& cds_start, uint& cds_end);\n   void mRNA_CDS_coords(uint& cds_start, uint& cds_end);\n   char* getSpliced(GFaSeqGet* faseq, bool CDSonly=false, int* rlen=NULL,\n           uint* cds_start=NULL, uint* cds_end=NULL, GList<GSeg>* seglst=NULL);\n    char* getUnspliced(GFaSeqGet* faseq, int* rlen, GList<GSeg>* seglst);\n   char* getSplicedTr(GFaSeqGet* faseq, bool CDSonly=true, int* rlen=NULL);\n   //bool validCDS(GFaSeqGet* faseq); //has In-Frame Stop Codon ?\n   bool empty() { return (start==0); }\n};\n\ntypedef bool GffRecFunc(GffObj* gobj, void* usrptr1, void* usrptr2);\n//user callback after parsing a mapping object:\n// Returns: \"done with it\" status:\n//   TRUE if gobj is no longer needed so it's FREEd upon return\n//   FALSE if the user needs the gobj pointer and is responsible for\n//             collecting and freeing all GffObj objects\n\n\n//GSeqStat: collect basic stats about a common underlying genomic sequence\n//          for multiple GffObj\nclass GSeqStat {\n public:\n   int gseqid; //gseq id in the global static pool of gseqs\n   char* gseqname; //just a pointer to the name of gseq\n   int fcount;//number of features on this gseq\n   uint mincoord;\n   uint maxcoord;\n   uint maxfeat_len; //maximum feature length on this genomic sequence\n   GffObj* maxfeat; \n   GSeqStat(int id=-1, char* name=NULL) {\n     gseqid=id;\n     gseqname=name;\n     fcount=0;\n     mincoord=MAXUINT;\n     maxcoord=0;\n     maxfeat_len=0;\n     maxfeat=NULL;\n     }\n   bool operator>(GSeqStat& g) {\n    return (gseqid>g.gseqid);\n    }\n   bool operator<(GSeqStat& g) {\n    return (gseqid<g.gseqid);\n    }\n   bool operator==(GSeqStat& g) {\n    return (gseqid==g.gseqid);\n    }\n};\n\n\nint gfo_cmpByLoc(const pointer p1, const pointer p2);\n\nclass GfList: public GList<GffObj> {\n  //just adding the option to sort by genomic sequence and coordinate\n   bool mustSort;\n public:\n   GfList(bool sortbyloc=false):GList<GffObj>(false,false,false) {\n     //GffObjs in this list are NOT deleted when the list is cleared\n     //-- for deallocation of these objects, call freeAll() or freeUnused() as needed\n     mustSort=sortbyloc;\n     }\n   void sortedByLoc(bool v=true) {\n     bool prev=mustSort;\n     mustSort=v;\n     if (fCount>0 && mustSort && !prev) {\n       this->setSorted((GCompareProc*)gfo_cmpByLoc);\n       }\n     }\n   void finalize(GffReader* gfr, bool mergeCloseExons, \n                bool keepAttrs=false, bool noExonAttr=true);\n\n   void freeAll() {\n     for (int i=0;i<fCount;i++) {\n       delete fList[i];\n       fList[i]=NULL;\n       }\n     Clear();\n     }\n   void freeUnused() {\n     for (int i=0;i<fCount;i++) {\n       if (fList[i]->isUsed()) continue;\n       //inform the children\n       for (int c=0;c<fList[i]->children.Count();c++) {\n          fList[i]->children[c]->parent=NULL;\n          }\n       delete fList[i];\n       fList[i]=NULL;\n       }\n     Clear();\n     }\n\n};\n/*\nstruct GfoHolder {\n   //int idx; //position in GffReader::gflst array\n   GffObj* gffobj;\n   GfoHolder(GffObj* gfo=NULL) { //, int i=0) {\n     //idx=i;\n     gffobj=gfo;\n     }\n};\n*/\nclass CNonExon { //utility class used in subfeature promotion\n public:\n   //int idx;\n   GffObj* parent;\n   GffExon* exon;\n   GffLine* gffline;\n   //CNonExon(int i, GffObj* p, GffExon* e, GffLine* gl) {\n   CNonExon(GffObj* p, GffExon* e, GffLine* gl) {\n     parent=p;\n     exon=e;\n     //idx=i;\n     gffline=new GffLine(gl);\n     }\n  ~CNonExon() {\n     delete gffline;\n     }\n };\n\n\nclass GffReader {\n  friend class GffObj;\n  friend class GffLine;\n  char* linebuf;\n  off_t fpos;\n  int buflen;\n protected:\n  bool gff_warns; //warn about duplicate IDs, etc. even when they are on different chromosomes\n  FILE* fh;\n  char* fname;  //optional fasta file with the underlying genomic sequence to be attached to this reader\n  GffLine* gffline;\n  bool transcriptsOnly; //keep only transcripts w/ their exon/CDS features\n  GHash<int> discarded_ids; //for transcriptsOnly mode, keep track\n                            // of discarded parent IDs\n  GHash< GPVec<GffObj> > phash; //transcript_id+contig (Parent~Contig) => [gflst index, GffObj]\n  //GHash<int> tids; //just for transcript_id uniqueness\n  char* gfoBuildId(const char* id, const char* ctg);\n  //void gfoRemove(const char* id, const char* ctg);\n  GffObj* gfoAdd(GffObj* gfo);\n  GffObj* gfoAdd(GPVec<GffObj>& glst, GffObj* gfo);\n  // const char* id, const char* ctg, char strand, GVec<GfoHolder>** glst, uint start, uint end\n  bool pFind(const char* id, GPVec<GffObj>*& glst);\n  GffObj* gfoFind(const char* id, GPVec<GffObj>* & glst, const char* ctg=NULL,\n\t                                         char strand=0, uint start=0, uint end=0);\n  CNonExon* subfPoolCheck(GffLine* gffline, GHash<CNonExon>& pex, char*& subp_name);\n  void subfPoolAdd(GHash<CNonExon>& pex, GffObj* newgfo);\n  GffObj* promoteFeature(CNonExon* subp, char*& subp_name, GHash<CNonExon>& pex,\n                                  bool keepAttr, bool noExonAttr);\n  GList<GSeqStat> gseqstats; //list of all genomic sequences seen by this reader, accumulates stats\n#ifdef CUFFLINKS\n     boost::crc_32_type  _crc_result;\n#endif\n public:\n  GffNames* names; //just a pointer to the global static Gff names repository in GffObj\n  GfList gflst; //accumulate GffObjs being read\n  GffObj* newGffRec(GffLine* gffline, bool keepAttr, bool noExonAttr,\n                               GffObj* parent=NULL, GffExon* pexon=NULL, GPVec<GffObj>* glst=NULL);\n  //GffObj* replaceGffRec(GffLine* gffline, bool keepAttr, bool noExonAttr, int replaceidx);\n  GffObj* updateGffRec(GffObj* prevgfo, GffLine* gffline,\n                                         bool keepAttr);\n  GffObj* updateParent(GffObj* newgfh, GffObj* parent);\n  bool addExonFeature(GffObj* prevgfo, GffLine* gffline, GHash<CNonExon>& pex, bool noExonAttr);\n  GPVec<GSeqStat> gseqStats; //only populated after finalize()\n  GffReader(FILE* f=NULL, bool t_only=false, bool sortbyloc=false):discarded_ids(true),\n                       phash(true), gseqstats(true,true,true), gflst(sortbyloc), gseqStats(1, false) {\n      gff_warns=gff_show_warnings;\n      names=NULL;\n      gffline=NULL;\n      transcriptsOnly=t_only;\n      fpos=0;\n      fname=NULL;\n      fh=f;\n      GMALLOC(linebuf, GFF_LINELEN);\n      buflen=GFF_LINELEN-1;\n      }\n  void init(FILE *f, bool t_only=false, bool sortbyloc=false) {\n      fname=NULL;\n      fh=f;\n      if (fh!=NULL) rewind(fh);\n      fpos=0;\n      transcriptsOnly=t_only;\n      gflst.sortedByLoc(sortbyloc);\n      }\n  GffReader(char* fn, bool t_only=false, bool sort=false):discarded_ids(true), phash(true),\n            gseqstats(true,true,true), gflst(sort), gseqStats(1,false) {\n      gff_warns=gff_show_warnings;\n      names=NULL;\n      fname=Gstrdup(fn);\n      transcriptsOnly=t_only;\n      fh=fopen(fname, \"rb\");\n      fpos=0;\n      gffline=NULL;\n      GMALLOC(linebuf, GFF_LINELEN);\n      buflen=GFF_LINELEN-1;\n      }\n\n ~GffReader() {\n      delete gffline;\n      gffline=NULL;\n      fpos=0;\n      gflst.freeUnused();\n      gflst.Clear();\n      discarded_ids.Clear();\n      phash.Clear();\n      gseqstats.Clear();\n      GFREE(fname);\n      GFREE(linebuf);\n      }\n\n  void showWarnings(bool v=true) {\n      gff_warns=v;\n      gff_show_warnings=v;\n      }\n\n  GffLine* nextGffLine();\n\n  // load all subfeatures, re-group them:\n  void readAll(bool keepAttr=false, bool mergeCloseExons=false, bool noExonAttr=true);\n#ifdef CUFFLINKS\n    boost::crc_32_type current_crc_result() const { return _crc_result; }\n#endif\n}; // end of GffReader\n\n#endif\n"
  },
  {
    "path": "src/gff_utils.cpp",
    "content": "#include \"gff_utils.h\"\n\nextern bool verbose;\nextern bool debugMode;\n\n//bool debugState=false;\n\nvoid printFasta(FILE* f, GStr& defline, char* seq, int seqlen) {\n if (seq==NULL) return;\n int len=(seqlen>0)?seqlen:strlen(seq);\n if (len<=0) return;\n if (!defline.is_empty())\n     fprintf(f, \">%s\\n\",defline.chars());\n int ilen=0;\n for (int i=0; i < len; i++, ilen++) {\n   if (ilen == 70) {\n     fputc('\\n', f);\n     ilen = 0;\n     }\n   putc(seq[i], f);\n   } //for\n fputc('\\n', f);\n}\n\nint qsearch_gloci(uint x, GList<GffLocus>& loci) {\n  //binary search\n  //do the simplest tests first:\n  if (loci[0]->start>x) return 0;\n  if (loci.Last()->start<x) return -1;\n  uint istart=0;\n  int i=0;\n  int idx=-1;\n  int maxh=loci.Count()-1;\n  int l=0;\n  int h = maxh;\n  while (l <= h) {\n     i = (l+h)>>1;\n     istart=loci[i]->start;\n     if (istart < x)  l = i + 1;\n          else {\n             if (istart == x) { //found matching coordinate here\n                  idx=i;\n                  while (idx<=maxh && loci[idx]->start==x) {\n                     idx++;\n                     }\n                  return (idx>maxh) ? -1 : idx;\n                  }\n             h = i - 1;\n             }\n     } //while\n idx = l;\n while (idx<=maxh && loci[idx]->start<=x) {\n    idx++;\n    }\n return (idx>maxh) ? -1 : idx;\n}\n\nint qsearch_rnas(uint x, GList<GffObj>& rnas) {\n  //binary search\n  //do the simplest tests first:\n  if (rnas[0]->start>x) return 0;\n  if (rnas.Last()->start<x) return -1;\n  uint istart=0;\n  int i=0;\n  int idx=-1;\n  int maxh=rnas.Count()-1;\n  int l=0;\n  int h = maxh;\n  while (l <= h) {\n     i = (l+h)>>1;\n     istart=rnas[i]->start;\n     if (istart < x)  l = i + 1;\n          else {\n             if (istart == x) { //found matching coordinate here\n                  idx=i;\n                  while (idx<=maxh && rnas[idx]->start==x) {\n                     idx++;\n                     }\n                  return (idx>maxh) ? -1 : idx;\n                  }\n             h = i - 1;\n             }\n     } //while\n idx = l;\n while (idx<=maxh && rnas[idx]->start<=x) {\n    idx++;\n    }\n return (idx>maxh) ? -1 : idx;\n}\n\nint cmpRedundant(GffObj& a, GffObj& b) {\n  if (a.exons.Count()==b.exons.Count()) {\n     if (a.covlen==b.covlen) {\n       return strcmp(a.getID(), b.getID());\n       }\n     else return (a.covlen>b.covlen)? 1 : -1;\n     }\n   else return (a.exons.Count()>b.exons.Count())? 1: -1;\n}\n\n\nbool tMatch(GffObj& a, GffObj& b) {\n  //strict intron chain match, or single-exon perfect match\n  int imax=a.exons.Count()-1;\n  int jmax=b.exons.Count()-1;\n  int ovlen=0;\n  if (imax!=jmax) return false; //different number of introns\n\n  if (imax==0) { //single-exon mRNAs\n    //if (equnspl) {\n      //fuzz match for single-exon transfrags: \n      // it's a match if they overlap at least 80% of max len\n      ovlen=a.exons[0]->overlapLen(b.exons[0]);\n      int maxlen=GMAX(a.covlen,b.covlen);\n      return (ovlen>=maxlen*0.8);\n    /*}\n    else {\n      //only exact match\n      ovlen=a.covlen;\n      return (a.exons[0]->start==b.exons[0]->start &&\n          a.exons[0]->end==b.exons[0]->end);\n      \n       }*/\n     }\n  //check intron overlaps\n  ovlen=a.exons[0]->end-(GMAX(a.start,b.start))+1;\n  ovlen+=(GMIN(a.end,b.end))-a.exons.Last()->start;\n  for (int i=1;i<=imax;i++) {\n    if (i<imax) ovlen+=a.exons[i]->len();\n    if ((a.exons[i-1]->end!=b.exons[i-1]->end) ||\n      (a.exons[i]->start!=b.exons[i]->start)) {\n            return false; //intron mismatch\n    }\n  }\n  return true;\n}\n\n\nbool unsplContained(GffObj& ti, GffObj&  tj, bool fuzzSpan) {\n //returns true only if ti (which MUST be single-exon) is \"almost\" contained in any of tj's exons\n //but it does not cross any intron-exon boundary of tj\n  int imax=ti.exons.Count()-1;\n  int jmax=tj.exons.Count()-1;\n  if (imax>0) GError(\"Error: bad unsplContained() call, 1st param must be single-exon transcript!\\n\");\n  int minovl = (int)(0.8 * ti.len()); //minimum overlap for fuzzSpan\n  if (fuzzSpan) {\n    for (int j=0;j<=jmax;j++) {\n       //must NOT overlap the introns\n       if ((j>0 && ti.start<tj.exons[j]->start) \n          || (j<jmax && ti.end>tj.exons[j]->end))\n         return false;\n       if (ti.exons[0]->overlapLen(tj.exons[j])>=minovl)\n              return true;\n       }\n      } else {\n    for (int j=0;j<=jmax;j++) {\n       //must NOT overlap the introns\n       if ((j>0 && ti.start<tj.exons[j]->start) \n          || (j<jmax && ti.end>tj.exons[j]->end))\n         return false;\n         //strict containment\n       if (ti.end<=tj.exons[j]->end && ti.start>=tj.exons[j]->start) \n            return true;\n       }\n      }\n return false;\n}\n\nGffObj* redundantTranscripts(GffObj& ti, GffObj&  tj, bool matchAllIntrons, bool fuzzSpan) {\n  // matchAllIntrons==true:  transcripts are considered \"redundant\" only if\n  //                   they have the exact same number of introns and same splice sites (or none)\n  //                 (single-exon transcripts can be also fully contained to be considered matching)\n  // matchAllIntrons==false: an intron chain could be a subset of a \"container\" chain, \n  //                   as long as no intron-exon boundaries are violated; also, a single-exon \n  //                   transcript will be collapsed if it's contained in one of the exons of the other\n  // fuzzSpan==false: the genomic span of one transcript must be contained in or equal with the genomic \n  //                  span of the other \n  // \n  // fuzzSpan==true: then genomic spans of transcripts are no longer required to be fully contained \n  //                 (i.e. they may extend each-other in opposite directions)\n  \n  //if redundancy is detected, the \"bigger\" transcript is returned (otherwise NULL is returned)\n if (ti.start>=tj.end || tj.start>=ti.end || tj.strand!=ti.strand) return NULL; //no span overlap at all\n int imax=ti.exons.Count()-1;\n int jmax=tj.exons.Count()-1;\n GffObj* bigger=NULL;\n GffObj* smaller=NULL;\n if (matchAllIntrons) {\n   if (imax!=jmax) return NULL;\n   if (ti.covlen>tj.covlen) {\n       bigger=&ti;\n       if (!fuzzSpan && (ti.start>tj.start || ti.end<tj.end)) return NULL;\n       }\n     else { //ti.covlen<=tj.covlen\n       bigger=&tj;\n       if (!fuzzSpan && (tj.start>ti.start || tj.end<ti.end)) return NULL;\n       }\n   //check that all introns really match\n   for (int i=0;i<imax;i++) {\n     if (ti.exons[i]->end!=tj.exons[i]->end || \n         ti.exons[i+1]->start!=tj.exons[i+1]->start) return NULL;\n     }\n   return bigger;\n   }\n //--- matchAllIntrons==false: intron-chain containment is also considered redundancy\n //int maxlen=0;\n int minlen=0;\n if (ti.covlen>tj.covlen) {\n      if (tj.exons.Count()>ti.exons.Count()) {\n          //exon count override\n          bigger=&tj;\n          smaller=&ti;\n          }\n        else {\n          bigger=&ti;\n          smaller=&tj;\n          }\n      //maxlen=ti.covlen;\n      minlen=tj.covlen;\n      }\n   else { //tj has more bases\n      if (ti.exons.Count()>tj.exons.Count()) {\n          //exon count override\n          bigger=&ti;\n          smaller=&tj;\n          }\n        else {\n          bigger=&tj;\n          smaller=&ti;\n          }\n      //maxlen=tj.covlen;\n      minlen=ti.covlen;\n      }\n if (imax==0 && jmax==0) {\n     //single-exon transcripts: if fuzzSpan, at least 80% of the shortest one must be overlapped by the other\n     if (fuzzSpan) {\n         return (ti.exons[0]->overlapLen(tj.exons[0])>=minlen*0.8) ? bigger : NULL;\n         }\n       else {\n         return (smaller->start>=bigger->start && smaller->end<=bigger->end) ? bigger : NULL;\n         }\n     }\n //containment is also considered redundancy\n if (smaller->exons.Count()==1) {\n   //check if this single exon is contained in any of tj exons\n   //without violating any intron-exon boundaries\n   return (unsplContained(*smaller, *bigger, fuzzSpan) ? bigger : NULL);\n   }\n\n //--from here on: both are multi-exon transcripts, imax>0 && jmax>0\n  if (ti.exons[imax]->start<tj.exons[0]->end ||\n     tj.exons[jmax]->start<ti.exons[0]->end )\n         return NULL; //intron chains do not overlap at all\n \n \n //checking full intron chain containment\n uint eistart=0, eiend=0, ejstart=0, ejend=0; //exon boundaries\n int i=1; //exon idx to the right of the current intron of ti\n int j=1; //exon idx to the right of the current intron of tj\n //find the first intron overlap:\n while (i<=imax && j<=jmax) {\n    eistart=ti.exons[i-1]->end;\n    eiend=ti.exons[i]->start;\n    ejstart=tj.exons[j-1]->end;\n    ejend=tj.exons[j]->start;\n    if (ejend<eistart) { j++; continue; }\n    if (eiend<ejstart) { i++; continue; }\n    //we found an intron overlap\n    break;\n    }\n if (!fuzzSpan && (bigger->start>smaller->start || bigger->end < smaller->end)) return NULL;\n if ((i>1 && j>1) || i>imax || j>jmax) {\n     return NULL; //either no intron overlaps found at all\n                  //or it's not the first intron for at least one of the transcripts\n     }\n if (eistart!=ejstart || eiend!=ejend) return NULL; //not an exact intron match\n if (j>i) {\n   //i==1, ti's start must not conflict with the previous intron of tj\n   if (ti.start<tj.exons[j-1]->start) return NULL;\n   //so i's first intron starts AFTER j's first intron\n   // then j must contain i, so i's last intron must end with or before j's last intron\n   if (ti.exons[imax]->start>tj.exons[jmax]->start) return NULL;\n      //comment out the line above if you just want \"intron compatibility\" (i.e. extension of intron chains )\n   }\n  else if (i>j) {\n     //j==1, tj's start must not conflict with the previous intron of ti\n     if (tj.start<ti.exons[i-1]->start) return NULL;\n     //so j's intron chain starts AFTER i's\n     // then i must contain j, so j's last intron must end with or before j's last intron\n     if (tj.exons[jmax]->start>ti.exons[imax]->start) return NULL;\n        //comment out the line above for just \"intronCompatible()\" check (allowing extension of intron chain)\n     }\n //now check if the rest of the introns overlap, in the same sequence\n i++;\n j++;\n while (i<=imax && j<=jmax) {\n  if (ti.exons[i-1]->end!=tj.exons[j-1]->end ||\n      ti.exons[i]->start!=tj.exons[j]->start) return NULL;\n  i++;\n  j++;\n  }\n i--;\n j--;\n if (i==imax && j<jmax) {\n   // tj has more introns to the right, check if ti's end doesn't conflict with the current tj exon boundary\n   if (ti.end>tj.exons[j]->end) return NULL;\n   }\n else if (j==jmax && i<imax) {\n   if (tj.end>ti.exons[i]->end) return NULL;\n   }\n return bigger;\n}\n\n\nint gseqCmpName(const pointer p1, const pointer p2) {\n return strcmp(((GenomicSeqData*)p1)->gseq_name, ((GenomicSeqData*)p2)->gseq_name);\n}\n\n\nvoid printLocus(GffLocus* loc, const char* pre) {\n  if (pre!=NULL) fprintf(stderr, \"%s\", pre);\n  GMessage(\" [%d-%d] : \", loc->start, loc->end);\n  GMessage(\"%s\",loc->rnas[0]->getID());\n  for (int i=1;i<loc->rnas.Count();i++) {\n    GMessage(\",%s\",loc->rnas[i]->getID());\n    }\n  GMessage(\"\\n\");\n}\n\nvoid preserveContainedCDS(GffObj* t, GffObj* tfrom) {\n //transfer CDS info to the container t if it's a larger protein\n if (tfrom->CDstart==0) return;\n if (t->CDstart) {\n   if (tfrom->CDstart<t->CDstart && tfrom->CDstart>=t->start)\n      t->CDstart=tfrom->CDstart;\n   if (tfrom->CDend>t->CDend && tfrom->CDend<=t->end)\n      t->CDend=tfrom->CDend;\n   }\n  else { //no CDS info on container, just copy it from the contained\n   t->addCDS(tfrom->CDstart, tfrom->CDend, tfrom->CDphase);\n   }\n}\n\nbool exonOverlap2Gene(GffObj* t, GffObj& g) {\n\tif (t->exons.Count()>0) {\n\t\treturn t->exonOverlap(g.start, g.end);\n\t}\n\telse return g.overlap(*t);\n}\nvoid GffLoader::placeGf(GffObj* t, GenomicSeqData* gdata, bool doCluster, bool collapseRedundant,\n                                               bool matchAllIntrons, bool fuzzSpan) {\n  GTData* tdata=new GTData(t); //additional transcript data\n  gdata->tdata.Add(tdata);\n  //int tidx=-1;\n  /*\n  if (debug) {\n     GMessage(\">>Placing transcript %s\\n\", t->getID());\n     debugState=true;\n     }\n    else debugState=false; \n   */\n  //dumb TRNA case for RefSeq: gene parent link missing\n  //try to restore it here; BUT this only works if gene feature comes first\n  if (t->parent==NULL && t->isTranscript()) {\n  \tint gidx=gdata->gfs.Count()-1;\n  \twhile (gidx>=0 && gdata->gfs[gidx]->end>=t->start) {\n  \t\tGffObj& g = *(gdata->gfs[gidx]);\n  \t\tif (g.isGene() && t->strand==g.strand && exonOverlap2Gene(t, g)) {\n  \t\t\tg.children.Add(t);\n  \t\t\tt->parent=&g;\n  \t\t\t//disable printing of gene if transcriptsOnly\n  \t\t\tif (transcriptsOnly) {\n  \t\t\t\tg.udata|=4; //tag it as non-printable\n  \t\t\t}\n  \t\t\tconst char* geneName=g.getAttr(\"Name\");\n  \t\t\tif (t->getAttr(\"Name\")==NULL && geneName) {\n  \t\t\t\tt->addAttr(\"Name\", geneName);\n  \t\t\t\tt->addAttr(\"gene_name\", geneName);\n  \t\t\t}\n  \t\t\tt->addAttr(\"geneID\", g.getID());\n  \t\t\tbreak;\n  \t\t}\n  \t\tgidx--;\n  \t}\n  }\n\n  /*\n\tif (t->exons.Count()==0  && t->children.Count()==0 && forceExons) {\n\t\t//a non-mRNA feature with no subfeatures\n\t\t//just so we get some sequence functions working, add a dummy \"exon\"-like subfeature here\n\t\t//--this could be a single \"pseudogene\" entry or another genomic region without exons\n\t\t//\n\t\tt->addExon(t->start,t->end);\n\t}\n  */\n  if (t->exons.Count()>0) {\n              //tidx=\n              gdata->rnas.Add(t); //added it in sorted order\n              }\n            else {\n              if (t->isGene() || !this->transcriptsOnly)\n              \t  gdata->gfs.Add(t);\n              return; //nothing to do with these non-transcript objects\n              }\n  if (!doCluster) return;\n  if (gdata->loci.Count()==0) {\n       gdata->loci.Add(new GffLocus(t));\n       //GMessage(\"  <<make it first locus %d-%d \\n\",t->start, t->end);\n       return;\n       }\n   /*    \n  //DEBUG: show available loci:\n   if (debug) {\n    GMessage(\"  [%d loci already:\\n\", gdata->loci.Count());\n    for (int l=0;l<gdata->loci.Count();l++) {\n       printLocus(gdata->loci[l]);\n       }\n    }\n  */\n  int nidx=qsearch_gloci(t->end, gdata->loci); //get index of nearest locus starting just ABOVE t->end\n  //GMessage(\"\\tlooking up end coord %d in gdata->loci.. (qsearch got nidx=%d)\\n\", t->end, nidx);\n  if (nidx==0) {\n     //cannot have any overlapping loci\n     //if (debug) GMessage(\"  <<no ovls possible, create locus %d-%d \\n\",t->start, t->end);\n     gdata->loci.Add(new GffLocus(t));\n     return;\n     }\n  if (nidx==-1) nidx=gdata->loci.Count();//all loci start below t->end\n  int lfound=0; //count of parent loci\n  GArray<int> mrgloci(false);\n  GList<GffLocus> tloci(true); //candidate parent loci to adopt this\n  //if (debug) GMessage(\"\\tchecking all loci from %d to 0\\n\",nidx-1);\n  for (int l=nidx-1;l>=0;l--) {\n      GffLocus& loc=*(gdata->loci[l]);\n      if (loc.strand!='.' && t->strand!='.'&& loc.strand!=t->strand) continue;\n      if (t->start>loc.end) {\n           if (t->start-loc.start>GFF_MAX_LOCUS) break; //give up already\n           continue;\n           }\n      if (loc.start>t->end) {\n               //this should never be the case if nidx was found correctly\n               GMessage(\"Warning: qsearch_gloci found loc.start>t.end!(t=%s)\\n\", t->getID());\n               continue;\n               }\n      /*\n      if (debug) {\n          GMessage(\" !range overlap found with locus \");\n          printLocus(&loc);\n          }\n      */\n      if (loc.add_RNA(t)) {\n         //will add this transcript to loc\n         lfound++;\n         mrgloci.Add(l);\n         if (collapseRedundant) {\n           //compare to every single transcript in this locus\n           for (int ti=0;ti<loc.rnas.Count();ti++) {\n                 if (loc.rnas[ti]==t) continue;\n                 GTData* odata=(GTData*)(loc.rnas[ti]->uptr);\n                 //GMessage(\"  ..redundant check vs overlapping transcript %s\\n\",loc.rnas[ti]->getID());\n                 GffObj* container=NULL;\n                 if (odata->replaced_by==NULL && \n                      (container=redundantTranscripts(*t, *(loc.rnas[ti]), matchAllIntrons, fuzzSpan))!=NULL) {\n                     if (container==t) {\n                        odata->replaced_by=t;\n                        preserveContainedCDS(t, loc.rnas[ti]);\n                        }\n                     else {\n                        tdata->replaced_by=loc.rnas[ti];\n                        preserveContainedCDS(loc.rnas[ti], t);\n                        }\n                     }\n              }//for each transcript in the exon-overlapping locus\n          } //if doCollapseRedundant\n         } //overlapping locus\n      } //for each existing locus\n  if (lfound==0) {\n      //overlapping loci not found, create a locus with only this mRNA\n      /* if (debug) {\n        GMessage(\"  overlapping locus not found, create locus %d-%d \\n\",t->start, t->end);\n        }\n      */\n      int addidx=gdata->loci.Add(new GffLocus(t));\n      if (addidx<0) {\n         //should never be the case!\n         GMessage(\"  WARNING: new GffLocus(%s:%d-%d) not added!\\n\",t->getID(), t->start, t->end);\n         }\n      }\n   else { //found at least one overlapping locus\n     lfound--;\n     int locidx=mrgloci[lfound];\n     GffLocus& loc=*(gdata->loci[locidx]);\n     //last locus index found is also the smallest index\n     if (lfound>0) {\n       //more than one loci found parenting this mRNA, merge loci\n       /* if (debug)\n          GMessage(\" merging %d loci \\n\",lfound);\n       */\n       for (int l=0;l<lfound;l++) {\n          int mlidx=mrgloci[l]; \n          loc.addMerge(*(gdata->loci[mlidx]), t);\n          gdata->loci.Delete(mlidx); //highest indices first, so it's safe to remove\n          }\n       }\n     int i=locidx;  \n     while (i>0 && loc<*(gdata->loci[i-1])) {\n       //bubble down until it's in the proper order\n       i--;\n       gdata->loci.Swap(i,i+1);\n       }\n     }//found at least one overlapping locus\n}\n\nvoid collectLocusData(GList<GenomicSeqData>& ref_data) {\n  int locus_num=0;\n  for (int g=0;g<ref_data.Count();g++) {\n    GenomicSeqData* gdata=ref_data[g];\n    for (int l=0;l<gdata->loci.Count();l++) {\n      GffLocus& loc=*(gdata->loci[l]);\n      GHash<int> gnames(true); //gene names in this locus\n      GHash<int> geneids(true); //Entrez GeneID: numbers\n      for (int i=0;i<loc.rnas.Count();i++) {\n        GffObj& t=*(loc.rnas[i]);\n        GStr gname(t.getGeneName());\n        if (!gname.is_empty()) {\n           gname.upper();\n           int* prevg=gnames.Find(gname.chars());\n           if (prevg!=NULL) (*prevg)++;\n                  else gnames.Add(gname, new int(1));\n           }\n        //parse GeneID xrefs, if any:\n        GStr xrefs(t.getAttr(\"xrefs\"));\n        if (!xrefs.is_empty()) {\n          xrefs.startTokenize(\",\");\n          GStr token;\n          while (xrefs.nextToken(token)) {\n            token.upper();\n            if (token.startsWith(\"GENEID:\")) {\n              token.cut(0,token.index(':')+1);\n              int* prevg=geneids.Find(token.chars());\n              if (prevg!=NULL) (*prevg)++;\n                     else geneids.Add(token, new int(1));\n              }\n            } //for each xref\n          } //xrefs parsing\n        }//for each transcript\n      locus_num++;\n      loc.locus_num=locus_num;\n      if (gnames.Count()>0) { //collect all gene names associated to this locus\n         gnames.startIterate();\n         int* gfreq=NULL;\n         char* key=NULL;\n         while ((gfreq=gnames.NextData(key))!=NULL) {\n            loc.gene_names.AddIfNew(new CGeneSym(key,*gfreq));\n            }\n         } //added collected gene_names\n      if (loc.gene_ids.Count()>0) { //collect all GeneIDs names associated to this locus\n         geneids.startIterate();\n         int* gfreq=NULL;\n         char* key=NULL;\n         while ((gfreq=geneids.NextData(key))!=NULL) {\n           loc.gene_ids.AddIfNew(new CGeneSym(key,*gfreq));\n            }\n          }\n      } //for each locus\n  }//for each genomic sequence\n}\n\n\nvoid GffLoader::load(GList<GenomicSeqData>& seqdata, GFValidateFunc* gf_validate, \n                          bool doCluster, bool doCollapseRedundant, \n                          bool matchAllIntrons, bool fuzzSpan, bool forceExons) {\n   GffReader* gffr=new GffReader(f, this->transcriptsOnly, false); //not only mRNA features, not sorted\n   gffr->showWarnings(this->showWarnings);\n   //           keepAttrs   mergeCloseExons  noExonAttr\n   gffr->readAll(this->fullAttributes,    this->mergeCloseExons,  this->noExonAttrs);\n   GVec<int> pseudoAttrIds;\n   GVec<int> pseudoFeatureIds;\n   if (this->noPseudo) {\n   \t GffNameList& fnames = gffr->names->feats;\n   \t for (int i=0;i<fnames.Count();i++) {\n   \t\tchar* n=fnames[i]->name;\n   \t\tif (startsWith(n, \"pseudo\")) {\n   \t\t\tpseudoFeatureIds.Add(fnames[i]->idx);\n   \t\t}\n   \t }\n  \t GffNameList& attrnames = gffr->names->attrs;\n  \t for (int i=0;i<attrnames.Count();i++) {\n  \t\tchar* n=attrnames[i]->name;\n  \t\tchar* p=strifind(n, \"pseudo\");\n  \t\tif (p==n || (p==n+2 && tolower(n[0])=='i' && tolower(n[1])=='s')) {\n  \t\t\tpseudoAttrIds.Add(attrnames[i]->idx);\n  \t\t}\n  \t}\n   }\n\n  //int redundant=0; //redundant annotation discarded\n  if (verbose) GMessage(\"   .. loaded %d genomic features from %s\\n\", gffr->gflst.Count(), fname.chars());\n  //int rna_deleted=0;\n  //add to GenomicSeqData, adding to existing loci and identifying intron-chain duplicates\n  for (int k=0;k<gffr->gflst.Count();k++) {\n     GffObj* m=gffr->gflst[k];\n     if (strcmp(m->getFeatureName(), \"locus\")==0 && \n          m->getAttr(\"transcripts\")!=NULL) {\n        continue; //discard locus meta-features\n        }\n     if (this->noPseudo) {\n    \t bool is_pseudo=false;\n    \t for (int i=0;i<pseudoFeatureIds.Count();++i) {\n    \t\t if (pseudoFeatureIds[i]==m->ftype_id) {\n    \t\t\t is_pseudo=true;\n    \t\t\t break;\n    \t\t }\n    \t }\n    \t if (is_pseudo) continue;\n    \t for (int i=0;i<pseudoAttrIds.Count();++i) {\n    \t\t char* attrv=NULL;\n    \t\t if (m->attrs!=NULL) attrv=m->attrs->getAttr(pseudoAttrIds[i]);\n    \t\t if (attrv!=NULL) {\n    \t\t\t char fc=tolower(attrv[0]);\n    \t\t\t if (fc=='t' || fc=='y' || fc=='1') {\n    \t\t\t\t is_pseudo=true;\n    \t\t\t\t break;\n    \t\t\t }\n    \t\t }\n    \t }\n    \t if (is_pseudo) continue;\n    \t //last resort:\n    \t //  scan all the attribute values for \"pseudogene\" keyword (NCBI does that for \"product\" attr)\n    \t if (m->attrs!=NULL) {\n    \t\t for (int i=0;i<m->attrs->Count();++i) {\n    \t\t\t GffAttr& a=*(m->attrs->Get(i));\n    \t\t\t if (strifind(a.attr_val, \"pseudogene\")) {\n    \t\t\t\t is_pseudo=true;\n    \t\t\t\t break;\n    \t\t\t }\n    \t\t }\n    \t }\n         if (is_pseudo) continue;\n     } //pseudogene detection requested\n     char* rloc=m->getAttr(\"locus\");\n     if (rloc!=NULL && startsWith(rloc, \"RLOC_\")) {\n        m->removeAttr(\"locus\", rloc);\n        }\n    /*\n     if (m->exons.Count()==0 && m->children.Count()==0) {\n       //a non-mRNA feature with no subfeatures\n       //add a dummy exon just to have the generic exon checking work\n       m->addExon(m->start,m->end);\n       }\n     */\n     if (forceExons) {  // && m->children.Count()==0) {\n       m->exon_ftype_id=gff_fid_exon;\n       }\n     GList<GffObj> gfadd(false,false);\n     if (gf_validate!=NULL && !(*gf_validate)(m, &gfadd)) {\n       continue;\n       }\n     m->isUsed(true); //so the gffreader won't destroy it\n     int i=-1;\n     GenomicSeqData f(m->gseq_id);\n     GenomicSeqData* gdata=NULL;\n     if (seqdata.Found(&f,i)) gdata=seqdata[i];\n         else { //entry not created yet for this genomic seq\n           gdata=new GenomicSeqData(m->gseq_id);\n           seqdata.Add(gdata);\n           }\n    for (int k=0;k<gfadd.Count();k++) {\n      placeGf(gfadd[k], gdata, doCluster, doCollapseRedundant, matchAllIntrons, fuzzSpan);\n      }\n    placeGf(m, gdata, doCluster, doCollapseRedundant, matchAllIntrons, fuzzSpan);\n    } //for each read gffObj\n   //if (verbose) GMessage(\"  .. %d records from %s clustered into loci.\\n\", gffr->gflst.Count(), fname.chars());\n   if (f!=stdin) { fclose(f); f=NULL; }\n   delete gffr;\n}\n"
  },
  {
    "path": "src/gff_utils.h",
    "content": "#ifndef GFF_UTILS_H\n#define GFF_UTILS_H\n#include \"gff.h\"\n#include \"GStr.h\"\n#include \"GFastaIndex.h\"\n#include \"GFaSeqGet.h\"\n\ntypedef bool GFValidateFunc(GffObj* gf, GList<GffObj>* gfadd);\n\nclass GeneInfo { //for Ensembl GTF conversion\n public:\n   int flag;\n   GffObj* gf;\n   GList<GStr> gene_names;\n   GList<GStr> transcripts; //list of transcript IDs\n   GeneInfo():gene_names(true, true, true), transcripts(true,true,true) {\n     gf=NULL;\n     flag=0;\n     }\n   GeneInfo(GffObj* gfrec, bool ensembl_convert=false):gene_names(true, true, true), \n                    transcripts(true,true,true) {\n     flag=0;\n     if (gfrec->getGeneName())\n        gene_names.Add(new GStr(gfrec->getGeneName()));\n     transcripts.Add(new GStr(gfrec->getID()));\n     create_gf(gfrec, ensembl_convert);\n     }\n     \n   void create_gf(GffObj* gfrec, bool ensembl_convert) {\n     gf=new GffObj(gfrec->getGeneID());\n     gf->gseq_id=gfrec->gseq_id;\n     gf->track_id=gfrec->track_id;\n     gf->start=gfrec->start;\n     gf->end=gfrec->end;\n     gf->strand=gfrec->strand;\n     gf->setFeatureName(\"gene\");\n     gf->isGene(true);\n     gf->isUsed(true);\n     gf->uptr=this;\n     gfrec->incLevel();\n     gfrec->parent=gf;\n     gf->children.Add(gfrec);\n     if (ensembl_convert) {\n       //gf->addAttr(\"type\", gf->getTrackName());\n       const char* biotype=gfrec->getAttr(\"type\");\n       if (biotype) gf->addAttr(\"type\", biotype);\n       }\n     //gf->children.Add(gfrec);\n     }\n   //~GeneInfo() {\n   //  }\n   void update(GffObj* gfrec) {\n     if (transcripts.AddedIfNew(new GStr(gfrec->getID()))<0)\n       return;\n     gene_names.AddedIfNew(new GStr(gfrec->getGeneName()));\n     if (gf==NULL) {\n        GError(\"GeneInfo::update() called on uninitialized gf!\\n\");\n        //create_gf(gfrec);\n        //return;\n        }\n     gfrec->parent=gf;\n     gf->children.Add(gfrec);\n     gfrec->incLevel();\n     if (gf->start>gfrec->start) \n           gf->start=gfrec->start;\n     if (gf->end<gfrec->end) \n           gf->end=gfrec->end;\n     }\n    void finalize() {\n     //prepare attributes for printing\n     //must be called right before printing\n     if (gf==NULL || transcripts.Count()==0) return;\n     if (gene_names.Count()>0) {\n       gf->addAttr(\"Name\", gene_names[0]->chars());\n       /*\n       GStr s(gene_names[0]->chars());\n       for (int i=1;i<gene_names.Count();i++) {\n          s.append(\",\");\n          s.append(gene_names[i]->chars());\n          }\n       gf->addAttr(\"genes\", s.chars());\n       */\n       } //has gene names\n       GStr t(transcripts[0]->chars());\n       for (int i=1;i<transcripts.Count();i++) {\n          t.append(\",\");\n          t.append(transcripts[i]->chars());\n          }\n       gf->addAttr(\"transcripts\", t.chars());\n     }\n};\n\n//genomic fasta sequence handling\nclass GFastaDb {\n public:\n  char* fastaPath;\n  GFastaIndex* faIdx; //could be a cdb .cidx file\n  int last_fetchid;\n  GFaSeqGet* faseq;\n  //GCdbYank* gcdb;\n  char* getFastaFile(int gseq_id) {\n     if (fastaPath==NULL) return NULL;\n     GStr s(fastaPath);\n     s.trimR('/');\n     s.appendfmt(\"/%s\",GffObj::names->gseqs.getName(gseq_id));\n     GStr sbase(s);\n     if (!fileExists(s.chars())) s.append(\".fa\");\n     if (!fileExists(s.chars())) s.append(\"sta\");\n     if (fileExists(s.chars())) return Gstrdup(s.chars());\n         else {\n             GMessage(\"Warning: cannot find genomic sequence file %s{.fa,.fasta}\\n\",sbase.chars());\n             return NULL;\n             }\n     }\n\n   GFastaDb(const char* fpath=NULL) {\n     //gcdb=NULL;\n     fastaPath=NULL;\n     faseq=NULL;\n     faIdx=NULL;\n     init(fpath);\n     }\n\n   void init(const char* fpath) {\n     if (fpath==NULL || fpath[0]==0) return;\n     last_fetchid=-1;\n     if (!fileExists(fpath))\n       GError(\"Error: file/directory %s does not exist!\\n\",fpath);\n     fastaPath=Gstrdup(fpath);\n     GStr gseqpath(fpath);\n     if (fileExists(fastaPath)>1) { //exists and it's not a directory\n            GStr fainame(fastaPath);\n            if (fainame.rindex(\".fai\")==fainame.length()-4) {\n               //.fai index file given directly\n               fastaPath[fainame.length()-4]=0;\n               if (!fileExists(fastaPath))\n                  GError(\"Error: cannot find fasta file for index %s !\\n\", fastaPath);\n               }\n              else fainame.append(\".fai\");\n            //GMessage(\"creating GFastaIndex with fastaPath=%s, fainame=%s\\n\", fastaPath, fainame.chars());\n            faIdx=new GFastaIndex(fastaPath,fainame.chars());\n            GStr fainamecwd(fainame);\n            int ip=-1;\n            if ((ip=fainamecwd.rindex(CHPATHSEP))>=0)\n               fainamecwd.cut(0,ip+1);\n            if (!faIdx->hasIndex()) { //could not load index\n               //try current directory\n                  if (fainame!=fainamecwd) {\n                    if (fileExists(fainamecwd.chars())>1) {\n                       faIdx->loadIndex(fainamecwd.chars());\n                       }\n                    }\n                  } //tried to load index\n            if (!faIdx->hasIndex()) {\n                 GMessage(\"No fasta index found for %s. Rebuilding, please wait..\\n\",fastaPath);\n                 faIdx->buildIndex();\n                 if (faIdx->getCount()==0) GError(\"Error: no fasta records found!\\n\");\n                 GMessage(\"Fasta index rebuilt.\\n\");\n                 FILE* fcreate=fopen(fainame.chars(), \"w\");\n                 if (fcreate==NULL) {\n                   GMessage(\"Warning: cannot create fasta index %s! (permissions?)\\n\", fainame.chars());\n                   if (fainame!=fainamecwd) fcreate=fopen(fainamecwd.chars(), \"w\");\n                   if (fcreate==NULL)\n                      GError(\"Error: cannot create fasta index %s!\\n\", fainamecwd.chars());\n                   }\n                 if (faIdx->storeIndex(fcreate)<faIdx->getCount())\n                     GMessage(\"Warning: error writing the index file!\\n\");\n                 } //index created and attempted to store it\n            } //multi-fasta\n     }\n   GFaSeqGet* fetch(int gseq_id, bool checkFasta=false) {\n     if (fastaPath==NULL) return NULL;\n     if (gseq_id==last_fetchid && faseq!=NULL) return faseq;\n     delete faseq;\n     faseq=NULL;\n     last_fetchid=-1;\n     char* gseqname=GffObj::names->gseqs.getName(gseq_id);\n     if (faIdx!=NULL) { //fastaPath was the multi-fasta file name\n        GFastaRec* farec=faIdx->getRecord(gseqname);\n        if (farec!=NULL) {\n             faseq=new GFaSeqGet(fastaPath,farec->seqlen, farec->fpos,\n                               farec->line_len, farec->line_blen);\n             faseq->loadall(); //just cache the whole sequence, it's faster\n             last_fetchid=gseq_id;\n             }\n        else {\n          GMessage(\"Warning: couldn't find fasta record for '%s'!\\n\",gseqname);\n          return NULL;\n          }\n        }\n     else {\n         char* sfile=getFastaFile(gseq_id);\n         if (sfile!=NULL) {\n            faseq=new GFaSeqGet(sfile,checkFasta);\n            faseq->loadall();\n            last_fetchid=gseq_id;\n            GFREE(sfile);\n            }\n         } //one fasta file per contig\n       return faseq;\n     }\n\n   ~GFastaDb() {\n     GFREE(fastaPath);\n     //delete gcdb;\n     delete faIdx;\n     delete faseq;\n     }\n};\n\nclass GffLocus;\n\nclass GTData { //transcript associated data\n public:\n    GffObj* rna;\n    GffLocus* locus;\n    GffObj* replaced_by;\n    GeneInfo* geneinfo;\n    int flag;\n    GTData(GffObj* t=NULL) {\n        rna=t;\n        flag=0;\n        locus=NULL;\n        replaced_by=NULL;\n        geneinfo=NULL;\n        if (rna!=NULL) {\n            geneinfo=(GeneInfo*)rna->uptr; //take over geneinfo, if there\n            rna->uptr=this;\n            }\n        }\n   bool operator<(GTData& b) { return (rna < b.rna); }\n   bool operator==(GTData& b) { return (rna==b.rna); }\n};\n\nclass CGeneSym {\n public:\n  GStr name;\n  int freq;\n  CGeneSym(const char* n=NULL, int f=0):name(n) {\n    freq=f;\n    }\n  bool operator<(CGeneSym& b) {\n     return (freq==b.freq)? ( (name.length()==b.name.length()) ? (name<b.name) :\n         (name.length()<b.name.length()) ) : ( freq>b.freq );\n     }\n  bool operator==(CGeneSym& b) { return name==b.name; }\n};\n\nconst char* getGeneDescr(const char* gsym);\n\nvoid printLocus(GffLocus* loc, const char* pre=NULL);\n\nclass GffLocus:public GSeg {\npublic:\n    int gseq_id; //id of underlying genomic sequence\n    int locus_num;\n    bool is_mrna;\n    char strand;\n    GffObj* t_maxcov;  //transcript with maximum coverage (for main \"ref\" transcript)\n    GList<GffObj> rnas; //list of transcripts (isoforms) for this locus\n    GArray<GSeg> mexons; //list of merged exons in this region\n    GList<CGeneSym> gene_names;\n    GList<CGeneSym> gene_ids;\n    int v; //user flag/data\n   /*\n   bool operator==(GffLocus& d){\n       return (gseq_id==d.gseq_id && strand==d.strand && start==d.start && end==d.end);\n       }\n   bool operator<(GffLocus& d){\n     if (gseq_id!=d.gseq_id) return (gseq_id<d.gseq_id);\n     if (start==d.start) {\n        if (end==d.end) return strand<d.strand;\n                     else return end<d.end;\n        } else return (start<d.start);\n     }\n    */\n    const char* getGeneName() {\n         if (gene_names.Count()==0) return NULL;\n         return gene_names.First()->name.chars();\n         }\n    const char* get_tmax_id() {\n         return t_maxcov->getID();\n         }\n    const char* get_descr() {\n       if (gene_names.Count()>0) {\n          for (int i=0;i<gene_names.Count();i++) {\n            const char* gn=getGeneDescr(gene_names.First()->name.chars());\n            if (gn!=NULL) return gn;\n            }\n          }\n       char* s=t_maxcov->getAttr(\"product\");\n       if (s!=NULL) return s;\n       s=t_maxcov->getAttr(\"descr\");\n       if (s!=NULL) return s;\n       s=t_maxcov->getAttr(\"description\");\n       if (s!=NULL) return s;\n       s=t_maxcov->getAttr(\"info\");\n       if (s!=NULL) return s;\n       return NULL;\n       }\n\n    GffLocus(GffObj* t=NULL):rnas(true,false,false),mexons(true,true),\n           gene_names(true,true,false), gene_ids(true,true,false) {\n        //this will NOT free rnas!\n        t_maxcov=NULL;\n        gseq_id=-1;\n        v=0;\n        locus_num=0;\n        start=0;\n        end=0;\n        strand=0;\n        is_mrna=false;\n        if (t!=NULL) {\n           start=t->exons.First()->start;\n           end=t->exons.Last()->end;;\n           gseq_id=t->gseq_id;\n           GSeg seg;\n           for (int i=0;i<t->exons.Count();i++) {\n                seg.start=t->exons[i]->start;\n                seg.end=t->exons[i]->end;\n                mexons.Add(seg);\n                }\n           rnas.Add(t);\n           ((GTData*)(t->uptr))->locus=this;\n           t_maxcov=t;\n           strand=t->strand;\n           if (t->ftype_id==gff_fid_mRNA) {\n              is_mrna=true;\n              }\n           }\n    }\n\n   void addMerge(GffLocus& locus, GffObj* lnkrna) {\n     //add all the elements of the other locus (merging)\n     //-- merge mexons\n     GArray<int> ovlexons(true,true); //list of locus.mexons indexes overlapping existing mexons\n     int i=0; //index of first mexons with a merge\n     int j=0; //index current mrna exon\n     while (i<mexons.Count() && j<locus.mexons.Count()) {\n            uint istart=mexons[i].start;\n            uint iend=mexons[i].end;\n            uint jstart=locus.mexons[j].start;\n            uint jend=locus.mexons[j].end;\n            if (iend<jstart) { i++; continue; }\n            if (jend<istart) { j++; continue; }\n            ovlexons.Add(j);\n            //extend mexons[i] as needed\n            if (jstart<istart) mexons[i].start=jstart;\n            if (jend>iend) { //mexons[i] end extend\n                mexons[i].end=jend;\n                //now this could overlap the next mexon(s), so we have to merge them all\n                while (i<mexons.Count()-1 && mexons[i].end>mexons[i+1].start) {\n                    uint nextend=mexons[i+1].end;\n                    mexons.Delete(i+1);\n                    if (nextend>mexons[i].end) {\n                        mexons[i].end=nextend;\n                        break; //no need to check next mexons\n                    }\n                } //while next mexons merge\n            } // mexons[i] end extend\n            j++; //check the next locus.mexon\n        }\n        //-- add the rest of the non-overlapping mexons:\n        GSeg seg;\n        for (int i=0;i<locus.mexons.Count();i++) {\n            seg.start=locus.mexons[i].start;\n            seg.end=locus.mexons[i].end;\n            if (!ovlexons.Exists(i)) mexons.Add(seg);\n        }\n     // -- add locus.rnas\n     for (int i=0;i<locus.rnas.Count();i++) {\n          ((GTData*)(locus.rnas[i]->uptr))->locus=this;\n          if (locus.rnas[i]!=lnkrna) rnas.Add(locus.rnas[i]);\n          }\n        // -- adjust start/end as needed\n     if (start>locus.start) start=locus.start;\n     if (end<locus.end) end=locus.end;\n     if (locus.is_mrna) is_mrna=true;\n     if (t_maxcov->covlen<locus.t_maxcov->covlen)\n            t_maxcov=locus.t_maxcov;\n     }\n\n    bool exonOverlap(GffLocus& loc) {\n        //check if any mexons overlap!\n        if (strand!=loc.strand || loc.start>end || start>loc.end) return false;\n        int i=0;\n        int j=0;\n        while (i<mexons.Count() && j<loc.mexons.Count()) {\n            uint istart=mexons[i].start;\n            uint iend=mexons[i].end;\n            uint jstart=loc.mexons[j].start;\n            uint jend=loc.mexons[j].end;\n            if (iend<jstart) { i++; continue; }\n            if (jend<istart) { j++; continue; }\n            //exon overlap found if we're here:\n            return true;\n        }\n        return false;\n    }\n\n    bool add_RNA(GffObj* t) {\n        //if (rnas.Count()==0) return true; //? should never be called on an empty locus\n        if (t->gseq_id!=gseq_id || t->strand!=strand || t->start>end || start>t->end)\n              return false; //rna must be on the same genomic seq\n        //check for exon overlap with existing mexons\n        //also update mexons accordingly if t is to be added\n        bool hasovl=false;\n        int i=0; //index of first mexons with a merge\n        int j=0; //index current t exon\n        GArray<int> ovlexons(true,true); //list of mrna exon indexes overlapping mexons\n        while (i<mexons.Count() && j<t->exons.Count()) {\n            uint istart=mexons[i].start;\n            uint iend=mexons[i].end;\n            uint jstart=t->exons[j]->start;\n            uint jend=t->exons[j]->end;\n            if (iend<jstart) { i++; continue; }\n            if (jend<istart) { j++; continue; }\n            //exon overlap found if we're here:\n            ovlexons.Add(j);\n            hasovl=true;\n            //extend mexons[i] as needed\n            if (jstart<istart) mexons[i].start=jstart;\n            if (jend>iend) { //mexon stretch up\n                mexons[i].end=jend;\n                //now this could overlap the next mexon(s), so we have to merge them all\n                while (i<mexons.Count()-1 && mexons[i].end>mexons[i+1].start) {\n                    uint nextend=mexons[i+1].end;\n                    mexons.Delete(i+1);\n                    if (nextend>mexons[i].end) {\n                        mexons[i].end=nextend;\n                        break; //no need to check next mexons\n                    }\n                } //while next mexons merge\n            } //possible mexons merge\n\n            j++; //check the next t exon\n        }//all vs all exon check loop\n        if (hasovl) {\n            GSeg seg;\n             //add the rest of the non-overlapping exons\n            for (int i=0;i<t->exons.Count();i++) {\n                seg.start=t->exons[i]->start;\n                seg.end=t->exons[i]->end;\n                if (!ovlexons.Exists(i)) mexons.Add(seg);\n                }\n            rnas_add(t);\n            // add to rnas\n            ((GTData*)t->uptr)->locus=this;\n            gseq_id=t->gseq_id;\n            }\n        return hasovl;\n    }\n\n    //simpler,basic adding of a mrna\n    void rnas_add(GffObj* t) {\n      rnas.Add(t);\n      // adjust start/end\n      //if (start==0 || start>t->start) start=t->start;\n      if (start==0) start=t->start;\n        else if (start>t->start) {\n          start=t->start;\n          }\n      if (end<t->end) end=t->end;\n      if (t_maxcov->covlen<t->covlen) t_maxcov=t;\n      if (strand==0) strand=t->strand;\n      if (t->ftype_id==gff_fid_mRNA) is_mrna=true;\n      }\n};\n\nclass GenomicSeqData {\n  int gseq_id;\n public:\n  const char* gseq_name;\n  GList<GffObj> gfs; //all non-transcript features -> usually gene features\n  GList<GffObj> rnas; //all transcripts on this genomic sequence\n  GList<GffLocus> loci; //all loci clusters\n  GList<GTData> tdata; //transcript data (uptr holder for all rnas loaded here)\n  //GenomicSeqData(int gid=-1):rnas(true,true,false),loci(true,true,true),\n  GenomicSeqData(int gid=-1):gfs(true, true, false),rnas((GCompareProc*)gfo_cmpByLoc),loci(true,true,false),\n       tdata(false,true,false) {\n  gseq_id=gid;\n  if (gseq_id>=0) \n    gseq_name=GffObj::names->gseqs.getName(gseq_id);\n  \n  }\n  bool operator==(GenomicSeqData& d){\n    return gseq_id==d.gseq_id;\n  }\n  bool operator<(GenomicSeqData& d){\n    return (gseq_id<d.gseq_id);\n  }\n};\n\nint gseqCmpName(const pointer p1, const pointer p2);\n\nclass GSpliceSite {\n public:\n  char nt[3];\n  GSpliceSite(const char* c, bool revc=false) {\n    nt[2]=0;\n    if (c==NULL) {\n      nt[0]=0;\n      nt[1]=0;\n      return;\n      }\n    if (revc) {\n      nt[0]=toupper(ntComplement(c[1]));\n      nt[1]=toupper(ntComplement(c[0]));\n      }\n    else {\n      nt[0]=toupper(c[0]);\n      nt[1]=toupper(c[1]);\n      }\n    }\n\n  GSpliceSite(const char* intron, int intronlen, bool getAcceptor, bool revc=false) {\n    nt[2]=0;\n    if (intron==NULL || intronlen==0)\n       GError(\"Error: invalid intron or intron len for GSpliceSite()!\\n\");\n    const char* c=intron;\n    if (revc) {\n      if (!getAcceptor) c+=intronlen-2;\n      nt[0]=toupper(ntComplement(c[1]));\n      nt[1]=toupper(ntComplement(c[0]));\n      }\n    else { //on forward strand\n      if (getAcceptor) c+=intronlen-2;\n      nt[0]=toupper(c[0]);\n      nt[1]=toupper(c[1]);\n      }//forward strand\n    }\n\n  GSpliceSite(const char n1, const char n2) {\n    nt[2]=0;\n    nt[0]=toupper(n1);\n    nt[1]=toupper(n2);\n    }\n  bool canonicalDonor() {\n    return (nt[0]=='G' && (nt[1]=='C' || nt[1]=='T'));\n    }\n  bool operator==(GSpliceSite& c) {\n    return (c.nt[0]==nt[0] && c.nt[1]==nt[1]);\n    }\n  bool operator==(GSpliceSite* c) {\n    return (c->nt[0]==nt[0] && c->nt[1]==nt[1]);\n    }\n  bool operator==(const char* c) {\n    //return (nt[0]==toupper(c[0]) && nt[1]==toupper(c[1]));\n    //assumes given const nucleotides are uppercase already!\n    return (nt[0]==c[0] && nt[1]==c[1]);\n    }\n  bool operator!=(const char* c) {\n    //assumes given const nucleotides are uppercase already!\n    return (nt[0]!=c[0] || nt[1]!=c[1]);\n    }\n};\n\nstruct GffLoader {\n  GStr fname;\n  FILE* f;\n  bool transcriptsOnly;\n  bool fullAttributes;\n  bool noExonAttrs;\n  bool mergeCloseExons;\n  bool showWarnings;\n  bool noPseudo;\n  void placeGf(GffObj* t, GenomicSeqData* gdata, bool doCluster=true, bool collapseRedundant=true,\n                                    bool matchAllIntrons=true, bool fuzzSpan=false);\n  void load(GList<GenomicSeqData>&seqdata, GFValidateFunc* gf_validate=NULL, \n                      bool doCluster=true, bool doCollapseRedundant=true, \n                      bool matchAllIntrons=true, bool fuzzSpan=false, bool forceExons=false);\n  GffLoader(const char* filename):fname(filename) {\n      f=NULL;\n      transcriptsOnly=true;\n      fullAttributes=false;\n      noExonAttrs=false;\n      mergeCloseExons=false;\n      showWarnings=false;\n      noPseudo=false;\n      if (fname==\"-\" || fname==\"stdin\") {\n         f=stdin;\n         fname=\"stdin\";\n         }\n        else {\n          if ((f=fopen(fname.chars(), \"r\"))==NULL) {\n            GError(\"Error: cannot open gff file %s!\\n\",fname.chars());\n            }\n          }\n      }\n  ~GffLoader() {\n      if (f!=NULL && f!=stdin) fclose(f);\n      }\n};\n\nvoid printFasta(FILE* f, GStr& defline, char* seq, int seqlen=-1);\n\n//\"position\" a given coordinate x within a list of transcripts sorted by their start (lowest)\n//coordinate, using quick-search; the returned int is the list index of the closest *higher*\n//GffObj - i.e. starting right *ABOVE* the given coordinate\n//Convention: returns -1 if there is no such GffObj (i.e. last GffObj starts below x)\nint qsearch_rnas(uint x, GList<GffObj>& rnas);\nint qsearch_gloci(uint x, GList<GffLocus>& loci);\n\nGffObj* redundantTranscripts(GffObj& ti, GffObj&  tj, bool matchAllIntrons=true, bool fuzzSpan=false);\n\n//void loadGFF(FILE* f, GList<GenomicSeqData>& seqdata, const char* fname);\n\nvoid collectLocusData(GList<GenomicSeqData>& ref_data);\n\n#endif\n"
  },
  {
    "path": "src/gffread.cpp",
    "content": "#include \"GArgs.h\"\n#include \"gff_utils.h\"\n#include <ctype.h>\n// don't care about cdb compression\n//#ifdef ENABLE_COMPRESSION\n//#undef ENABLE_COMPRESSION\n//#endif\n//#include \"GCdbYank.h\"\n\n#define USAGE \"Usage:\\n\\\ngffread <input_gff> [-g <genomic_seqs_fasta> | <dir>][-s <seq_info.fsize>] \\n\\\n [-o <outfile.gff>] [-t <tname>] [-r [[<strand>]<chr>:]<start>..<end> [-R]]\\n\\\n [-CTVNJMKQAFGUBHZWTOLE] [-w <exons.fa>] [-x <cds.fa>] [-y <tr_cds.fa>]\\n\\\n [-i <maxintron>] \\n\\\n Filters and/or converts GFF3/GTF2 records.\\n\\\n <input_gff> is a GFF file, use '-' if the GFF records will be given at stdin\\n\\\n \\n\\\n Options:\\n\\\n  -g  full path to a multi-fasta file with the genomic sequences\\n\\\n      for all input mappings, OR a directory with single-fasta files\\n\\\n      (one per genomic sequence, with file names matching sequence names)\\n\\\n  -s  <seq_info.fsize> is a tab-delimited file providing this info\\n\\\n      for each of the mapped sequences:\\n\\\n      <seq-name> <seq-length> <seq-description>\\n\\\n      (useful for -A option with mRNA/EST/protein mappings)\\n\\\n  -i  discard transcripts having an intron larger than <maxintron>\\n\\\n  -r  only show transcripts overlapping coordinate range <start>..<end>\\n\\\n      (on chromosome/contig <chr>, strand <strand> if provided)\\n\\\n  -R  for -r option, discard all transcripts that are not fully \\n\\\n      contained within the given range\\n\\\n  -U  discard single-exon transcripts\\n\\\n  -C  coding only: discard mRNAs that have no CDS feature\\n\\\n  -F  full GFF attribute preservation (all attributes are shown)\\n\\\n  -G  only parse additional exon attributes from the first exon\\n\\\n      and move them to the mRNA level (useful for GTF input)\\n\\\n  -A  use the description field from <seq_info.fsize> and add it\\n\\\n      as the value for a 'descr' attribute to the GFF record\\n\\\n  \\n\\\n  -O  process also non-transcript GFF records (by default non-transcript\\n\\\n      records are ignored)\\n\\\n  -V  discard any mRNAs with CDS having in-frame stop codons\\n\\\n  -H  for -V option, check and adjust the starting CDS phase\\n\\\n      if the original phase leads to a translation with an \\n\\\n      in-frame stop codon\\n\\\n  -B  for -V option, single-exon transcripts are also checked on the\\n\\\n      opposite strand\\n\\\n  -N  discard multi-exon mRNAs that have any intron with a non-canonical\\n\\\n      splice site consensus (i.e. not GT-AG, GC-AG or AT-AC)\\n\\\n  -J  discard any mRNAs that either lack initial START codon\\n\\\n      or the terminal STOP codon, or have an in-frame stop codon\\n\\\n      (only print mRNAs with a fulll, valid CDS)\\n\\\n  --no-pseudo: filter out records matching the 'pseudo' keyword\\n\\\n \\n\\\n  -M/--merge : cluster the input transcripts into loci, collapsing matching\\n\\\n       transcripts (those with the same exact introns and fully contained)\\n\\\n  -d <dupinfo> : for -M option, write collapsing info to file <dupinfo>\\n\\\n  --cluster-only: same as --merge but without collapsing matching transcripts\\n\\\n  -K  for -M option: also collapse shorter, fully contained transcripts\\n\\\n      with fewer introns than the container\\n\\\n  -Q  for -M option, remove the containment restriction:\\n\\\n      (multi-exon transcripts will be collapsed if just their introns match,\\n\\\n      while single-exon transcripts can partially overlap (80%))\\n\\\n \\n\\\n  --force-exons: make sure that the lowest level GFF features are printed as \\n\\\n      \\\"exon\\\" features\\n\\\n  -E  expose (warn about) duplicate transcript IDs and other potential \\n\\\n      problems with the given GFF/GTF records\\n\\\n  -D  decode url encoded characters within attributes\\n\\\n  -Z  merge close exons into a single exon (for intron size<4)\\n\\\n  -w  write a fasta file with spliced exons for each GFF transcript\\n\\\n  -x  write a fasta file with spliced CDS for each GFF transcript\\n\\\n  -W  for -w and -x options, also write for each fasta record the exon\\n\\\n      coordinates projected onto the spliced sequence\\n\\\n  -y  write a protein fasta file with the translation of CDS for each record\\n\\\n  -L  Ensembl GTF to GFF3 conversion (implies -F; should be used with -m)\\n\\\n  -m  <chr_replace> is a reference (genomic) sequence replacement table with\\n\\\n      this format:\\n\\\n      <original_ref_ID> <new_ref_ID>\\n\\\n      GFF records on reference sequences that are not found among the\\n\\\n      <original_ref_ID> entries in this file will be filtered out\\n\\\n  -o  the \\\"filtered\\\" GFF records will be written to <outfile.gff>\\n\\\n      (use -o- for printing to stdout)\\n\\\n  -t  use <trackname> in the second column of each GFF output line\\n\\\n  -T  -o option will output GTF format instead of GFF3\\n\\\n \"\n\n\nclass SeqInfo { //populated from the -s option of gffread\n public:\n  int len;\n  char* descr;\n  SeqInfo( int l, char* s) {\n   len=l;\n   if (s==NULL) {\n     descr=NULL;\n     }   else {\n     descr=Gstrdup(s);\n     }\n   }\n  ~SeqInfo() {\n   GFREE(descr);\n   }\n};\n\nclass RefTran {\n public:\n   char* new_name;\n   RefTran(char *ns) {\n      new_name=NULL;\n      if (ns!=NULL)\n         new_name=Gstrdup(ns);\n      }\n   ~RefTran() {\n      GFREE(new_name);\n      }\n};\n\nFILE* ffasta=NULL;\nFILE* f_in=NULL;\nFILE* f_out=NULL;\nFILE* f_w=NULL; //fasta with spliced exons (transcripts)\nFILE* f_x=NULL; //fasta with spliced CDS\nFILE* f_y=NULL; //fasta with translated CDS\nbool wCDSonly=false;\n\nbool validCDSonly=false; // translation with no in-frame STOP\nbool bothStrands=false; //for single-exon mRNA validation, check the other strand too\nbool altPhases=false; //if original phase fails translation validation,\n                     //try the other 2 phases until one makes it\nbool mRNAOnly=true;\nbool NoPseudo=false;\nbool forceExons=false;\nbool spliceCheck=false; //only known splice-sites\nbool decodeChars=false; //decode url-encoded chars in attrs (-D)\nbool fullCDSonly=false; // starts with START, ends with STOP codon\nbool fullattr=false;\n//bool sortByLoc=false; // if the GFF output should be sorted by location\nbool ensembl_convert=false; //-L, assist in converting Ensembl GTF to GFF3\n\n\n//GStr gseqpath;\n//GStr gcdbfa;\n//bool multiGSeq=false; //if a directory or a .cidx file was given to -g option\n//GFaSeqGet* faseq=NULL;\n//GCdbYank* gcdb=NULL;\n//int gseq_id=-1; //current genome sequence ID -- the current GffObj::gseq_id\nbool fmtGTF=false;\nbool addDescr=false;\n//bool protmap=false;\nbool multiExon=false;\nbool writeExonSegs=false;\nchar* tracklabel=NULL;\nint maxintron=999000000;\nbool mergeCloseExons=false;\n//range filter:\nchar* rfltGSeq=NULL;\nchar rfltStrand=0;\nuint rfltStart=0;\nuint rfltEnd=MAX_UINT;\nbool rfltWithin=false; //check for full containment within given range\nbool noExonAttr=false;\n\nbool doCluster=false;\nbool doCollapseRedundant=false;\n\nGList<GenomicSeqData> g_data(true,true,true); //list of GFF records by genomic seq\n\n//hash with sequence info\nGHash<SeqInfo> seqinfo;\nGHash<int> isoCounter; //counts the valid isoforms\nGHash<RefTran> reftbl;\nGHash<GeneInfo> gene_ids; \n  //min-max gene span associated to chr|gene_id (mostly for Ensembl conversion)\n\nbool debugMode=false;\nbool verbose=false;\n\nvoid loadSeqInfo(FILE* f, GHash<SeqInfo> &si) {\n  GLineReader fr(f);\n  while (!fr.isEof()) {\n      char* line=fr.getLine();\n      if (line==NULL) break;\n      char* id=line;\n      char* lenstr=NULL;\n      char* text=NULL;\n      char* p=line;\n      while (*p!=0 && !isspace(*p)) p++;\n      if (*p==0) continue;\n      *p=0;p++;\n      while (*p==' ' || *p=='\\t') p++;\n      if (*p==0) continue;\n      lenstr=p;\n      while (*p!=0 && !isspace(*p)) p++;\n      if (*p!=0) { *p=0;p++; }\n      while (*p==' ' || *p=='\\t') p++;\n      if (*p!=0) text=p; //else text remains NULL\n      int len=0;\n      if (!parseInt(lenstr,len)) {\n         GMessage(\"Warning: could not parse sequence length: %s %s\\n\",\n                  id, lenstr);\n         continue;\n         }\n      // --- here we have finished parsing the line\n      si.Add(id, new SeqInfo(len,text));\n      } //while lines\n}\n\nvoid loadRefTable(FILE* f, GHash<RefTran>& rt) {\n  GLineReader fr(f);\n  char* line=NULL;\n  while ((line=fr.getLine())) {\n      char* orig_id=line;\n      char* p=line;\n      while (*p!=0 && !isspace(*p)) p++;\n      if (*p==0) continue;\n      *p=0;p++;//split the line here\n      while (*p==' ' || *p=='\\t') p++;\n      if (*p==0) continue;\n      rt.Add(orig_id, new RefTran(p));\n      } //while lines\n}\n\nchar* getSeqDescr(char* seqid) {\n static char charbuf[128];\n if (seqinfo.Count()==0) return NULL;\n char* suf=rstrchr(seqid, '.');\n if (suf!=NULL) *suf=0;\n SeqInfo* seqd=seqinfo.Find(seqid);\n if (suf!=NULL) *suf='.';\n if (seqd!=NULL) {\n  GStr s(seqd->descr);\n  //cleanup some Uniref gunk\n  if (s[0]=='[') {\n    int r=s.index(']');\n    if (r>=0 && r<8 && isdigit(s[1]))\n       s.remove(0,r+1);\n    }\n  if (s.length()>80) {\n    int r=s.index(';');\n    if (r>5) s.cut(r);\n    }\n  if (s.length()>127) {\n   s.cut(127);\n   int r=s.rindex(' ');\n   if (r>0) s.cut(r);\n   }\n  strcpy(charbuf, s.chars());\n  return charbuf;\n  }\n else return NULL;\n}\n\nchar* getSeqName(char* seqid) {\n  static char charbuf[128];\n  char* suf=rstrchr(seqid, '.');\n  if (suf!=NULL) *suf=0;\n  strcpy(charbuf, seqid);\n  if (suf!=NULL) *suf='.';\n  return charbuf;\n}\n\nGFaSeqGet* fastaSeqGet(GFastaDb& gfasta, GffObj& gffrec) {\n  if (gfasta.fastaPath==NULL) return NULL;\n  return gfasta.fetch(gffrec.gseq_id);\n}\n\n\nint adjust_stopcodon(GffObj& gffrec, int adj, GList<GSeg>* seglst=NULL) {\n //adj>0 => extedn CDS,  adj<0 => shrink CDS\n //when CDS is expanded, exons have to be checked too and \n // expanded accordingly if they had the same boundary\n  int realadj=0;\n  if (gffrec.strand=='-') {\n       if ((int)gffrec.CDstart>adj) {\n\n           gffrec.CDstart-=adj;\n           realadj=adj;\n           if (adj<0) { //restore\n              if (gffrec.exons.First()->start==gffrec.CDstart+adj) {\n                 gffrec.exons.First()->start-=adj;\n                 gffrec.start=gffrec.exons.First()->start;\n                 gffrec.covlen+=adj;\n                 }\n              }\n           else if (gffrec.exons.First()->start>=gffrec.CDstart) {\n                 gffrec.exons.First()->start-=adj;\n                 gffrec.start=gffrec.exons.First()->start;\n                 gffrec.covlen+=adj;\n                 }\n             }\n          }\n        else {\n         realadj=adj;\n         gffrec.CDend+=adj;\n         if (adj<0) {//restore\n           if (gffrec.exons.Last()->end==gffrec.CDend-adj) {\n                        gffrec.exons.Last()->end+=adj;\n                        gffrec.end=gffrec.exons.Last()->end;\n                        gffrec.covlen+=adj;\n                        }\n          }\n         else if (gffrec.exons.Last()->end<=gffrec.CDend) {\n             gffrec.exons.Last()->end+=adj;\n             gffrec.end=gffrec.exons.Last()->end;\n             gffrec.covlen+=adj;\n             }\n         }\n  if (seglst!=NULL) seglst->Last()->end+=adj;\n  return realadj;\n }\n\nbool process_transcript(GFastaDb& gfasta, GffObj& gffrec) {\n //returns true if the transcript passed the filter\n char* gname=gffrec.getGeneName();\n if (gname==NULL) gname=gffrec.getGeneID();\n GStr defline(gffrec.getID());\n if (f_out && !fmtGTF) {\n     const char* tname=NULL;\n     if ((tname=gffrec.getAttr(\"transcript_name\"))!=NULL) {\n        gffrec.addAttr(\"Name\", tname);\n        gffrec.removeAttr(\"transcript_name\");\n        }\n     }\n if (ensembl_convert && startsWith(gffrec.getID(), \"ENS\")) {\n      const char* biotype=gffrec.getAttr(\"gene_biotype\");\n      if (biotype) {\n         gffrec.addAttr(\"type\", biotype);\n         gffrec.removeAttr(\"gene_biotype\");\n         }\n       else { //old Ensembl files lacking gene_biotype\n         gffrec.addAttr(\"type\", gffrec.getTrackName());\n         }\n\n      //bool is_gene=false;\n      bool is_pseudo=false;\n      if (strcmp(biotype, \"protein_coding\")==0 || gffrec.hasCDS())\n                gffrec.setFeatureName(\"mRNA\");\n       else {\n          if (strcmp(biotype, \"processed_transcript\")==0) \n              gffrec.setFeatureName(\"proc_RNA\");\n            else {\n              //is_gene=endsWith(biotype, \"gene\");\n              is_pseudo=strifind(biotype, \"pseudo\");\n              if (is_pseudo) {\n                   gffrec.setFeatureName(\"pseudo_RNA\");\n                   }\n                else if (endsWith(biotype, \"RNA\")) {\n                   gffrec.setFeatureName(biotype);\n                   } else gffrec.setFeatureName(\"misc_RNA\");\n              }\n          }\n      }\n if (gname && strcmp(gname, gffrec.getID())!=0) {\n   int* isonum=isoCounter.Find(gname);\n   if  (isonum==NULL) {\n       isonum=new int(1);\n       isoCounter.Add(gname,isonum);\n       }\n      else (*isonum)++;\n   defline.appendfmt(\" gene=%s\", gname);\n   }\n  int seqlen=0;\n\n  const char* tlabel=tracklabel;\n  if (tlabel==NULL) tlabel=gffrec.getTrackName();\n  //defline.appendfmt(\" track:%s\",tlabel);\n  char* cdsnt = NULL;\n  char* cdsaa = NULL;\n  int aalen=0;\n  for (int i=1;i<gffrec.exons.Count();i++) {\n     int ilen=gffrec.exons[i]->start-gffrec.exons[i-1]->end-1;\n     if (ilen>4000000) \n            GMessage(\"Warning: very large intron (%d) for transcript %s\\n\",\n                           ilen, gffrec.getID());\n     if (ilen>maxintron) {\n         return false;\n         }\n     }\n  GList<GSeg> seglst(false,true);\n  GFaSeqGet* faseq=fastaSeqGet(gfasta, gffrec);\n  if (spliceCheck && gffrec.exons.Count()>1) {\n    //check introns for splice site consensi ( GT-AG, GC-AG or AT-AC )\n    if (faseq==NULL) GError(\"Error: no genomic sequence available!\\n\");\n    int glen=gffrec.end-gffrec.start+1;\n    const char* gseq=faseq->subseq(gffrec.start, glen);\n    bool revcompl=(gffrec.strand=='-');\n    bool ssValid=true;\n    for (int e=1;e<gffrec.exons.Count();e++) {\n      const char* intron=gseq+gffrec.exons[e-1]->end+1-gffrec.start;\n      int intronlen=gffrec.exons[e]->start-gffrec.exons[e-1]->end-1;\n      GSpliceSite acceptorSite(intron,intronlen,true, revcompl);\n      GSpliceSite    donorSite(intron,intronlen, false, revcompl);\n      //GMessage(\"%c intron %d-%d : %s .. %s\\n\",\n      //           gffrec.strand, istart, iend, donorSite.nt, acceptorSite.nt);\n      if (acceptorSite==\"AG\") { // GT-AG or GC-AG\n         if (!donorSite.canonicalDonor()) {\n            ssValid=false;break;\n            }\n         }\n      else if (acceptorSite==\"AC\") { //\n         if (donorSite!=\"AT\") { ssValid=false; break; }\n         }\n      else { ssValid=false; break; }\n      }\n    //GFREE(gseq);\n    if (!ssValid) {\n      if (verbose)\n         GMessage(\"Invalid splice sites found for '%s'\\n\",gffrec.getID());\n      return false; //don't print this one!\n      }\n    }\n\n  bool trprint=true;\n  int stopCodonAdjust=0;\n  int mCDphase=0;\n  bool hasStop=false;\n  if (gffrec.CDphase=='1' || gffrec.CDphase=='2')\n      mCDphase = gffrec.CDphase-'0';\n  if (f_y!=NULL || f_x!=NULL || validCDSonly) {\n    if (faseq==NULL) GError(\"Error: no genomic sequence provided!\\n\");\n    //if (protmap && fullCDSonly) {\n    //if (protmap && (fullCDSonly ||  (gffrec.qlen>0 && gffrec.qend==gffrec.qlen))) {\n    \n    if (validCDSonly) { //make sure the stop codon is always included \n      //adjust_stopcodon(gffrec,3);\n      stopCodonAdjust=adjust_stopcodon(gffrec,3);\n      }\n    int strandNum=0;\n    int phaseNum=0;\n  CDS_CHECK:\n    cdsnt=gffrec.getSpliced(faseq, true, &seqlen, NULL, NULL, &seglst);\n    if (cdsnt==NULL) trprint=false;\n    else { //has CDS\n      if (validCDSonly) {\n         cdsaa=translateDNA(cdsnt, aalen, seqlen);\n         char* p=strchr(cdsaa,'.');\n         hasStop=false;\n         if (p!=NULL) {\n              if (p-cdsaa>=aalen-2) { //stop found as the last codon\n                      *p='0';//remove it\n                      hasStop=true;\n                      if (aalen-2==p-cdsaa) {\n                        //previous to last codon is the stop codon\n                        //so correct the CDS stop accordingly\n                        adjust_stopcodon(gffrec,-3, &seglst);\n                        stopCodonAdjust=0; //clear artificial stop adjustment\n                        seqlen-=3;\n                        cdsnt[seqlen]=0;\n                        }\n                      aalen=p-cdsaa;\n                      }\n                   else {//stop found before the last codon\n                      trprint=false;\n                      }\n              }//stop codon found\n         if (trprint==false) { //failed CDS validity check\n           //in-frame stop codon found\n           if (altPhases && phaseNum<3) {\n              phaseNum++;\n              gffrec.CDphase = '0'+((mCDphase+phaseNum)%3);\n              GFREE(cdsaa);\n              goto CDS_CHECK;\n              }\n           if (gffrec.exons.Count()==1 && bothStrands) {\n              strandNum++;\n              phaseNum=0;\n              if (strandNum<2) {\n                 GFREE(cdsaa);\n                 gffrec.strand = (gffrec.strand=='-') ? '+':'-';\n                 goto CDS_CHECK; //repeat the CDS check for a different frame\n                 }\n              }\n           if (verbose) GMessage(\"In-frame STOP found for '%s'\\n\",gffrec.getID());\n           } //has in-frame STOP\n         if (fullCDSonly) {\n             if (!hasStop || cdsaa[0]!='M') trprint=false;\n             }\n         } // CDS check requested\n      } //has CDS\n    } //translation or codon check/output was requested\n  if (!trprint) {\n    GFREE(cdsnt);\n    GFREE(cdsaa);\n    return false;\n    }\n  if (stopCodonAdjust>0 && !hasStop) {\n          //restore stop codon location\n          adjust_stopcodon(gffrec, -stopCodonAdjust, &seglst);\n          if (cdsnt!=NULL && seqlen>0) {\n             seqlen-=stopCodonAdjust;\n             cdsnt[seqlen]=0;\n             }\n          if (cdsaa!=NULL) aalen--;\n          }\n\n  if (f_y!=NULL) { //CDS translation fasta output requested\n         //char* \n         if (cdsaa==NULL) { //translate now if not done before\n           cdsaa=translateDNA(cdsnt, aalen, seqlen);\n           }\n         if (fullattr && gffrec.attrs!=NULL) {\n             //append all attributes found for each transcripts\n              for (int i=0;i<gffrec.attrs->Count();i++) {\n                defline.append(\" \");\n                defline.append(gffrec.getAttrName(i));\n                defline.append(\"=\");\n                defline.append(gffrec.getAttrValue(i));\n                }\n              }\n         printFasta(f_y, defline, cdsaa, aalen);\n         }\n   if (f_x!=NULL) { //CDS only\n         if (writeExonSegs) {\n              defline.append(\" loc:\");\n              defline.append(gffrec.getGSeqName());\n              defline.appendfmt(\"(%c)\",gffrec.strand);\n              //warning: not CDS coordinates are written here, but the exon ones\n              defline+=(int)gffrec.start;\n              defline+=(char)'-';\n              defline+=(int)gffrec.end;\n              // -- here these are CDS substring coordinates on the spliced sequence:\n              defline.append(\" segs:\");\n              for (int i=0;i<seglst.Count();i++) {\n                  if (i>0) defline.append(\",\");\n                  defline+=(int)seglst[i]->start;\n                  defline.append(\"-\");\n                  defline+=(int)seglst[i]->end;\n                  }\n              }\n         if (fullattr && gffrec.attrs!=NULL) {\n             //append all attributes found for each transcript\n              for (int i=0;i<gffrec.attrs->Count();i++) {\n                defline.append(\" \");\n                defline.append(gffrec.getAttrName(i));\n                defline.append(\"=\");\n                defline.append(gffrec.getAttrValue(i));\n                }\n              }\n         printFasta(f_x, defline, cdsnt, seqlen);\n         }\n GFREE(cdsnt);\n GFREE(cdsaa);\n if (f_w!=NULL) { //write spliced exons\n    uint cds_start=0;\n    uint cds_end=0;\n    seglst.Clear();\n    char* exont=gffrec.getSpliced(faseq, false, &seqlen, &cds_start, &cds_end, &seglst);\n    if (exont!=NULL) {\n    if (gffrec.CDstart>0) {\n        defline.appendfmt(\" CDS=%d-%d\", cds_start, cds_end);\n        }\n      if (writeExonSegs) {\n        defline.append(\" loc:\");\n        defline.append(gffrec.getGSeqName());\n        defline+=(char)'|';\n        defline+=(int)gffrec.start;\n        defline+=(char)'-';\n        defline+=(int)gffrec.end;\n        defline+=(char)'|';\n        defline+=(char)gffrec.strand;\n        defline.append(\" exons:\");\n        for (int i=0;i<gffrec.exons.Count();i++) {\n                if (i>0) defline.append(\",\");\n                defline+=(int)gffrec.exons[i]->start;\n                defline.append(\"-\");\n                defline+=(int)gffrec.exons[i]->end;\n                }\n        defline.append(\" segs:\");\n        for (int i=0;i<seglst.Count();i++) {\n            if (i>0) defline.append(\",\");\n            defline+=(int)seglst[i]->start;\n            defline.append(\"-\");\n            defline+=(int)seglst[i]->end;\n            }\n        }\n      if (fullattr && gffrec.attrs!=NULL) {\n       //append all attributes found for each transcripts\n        for (int i=0;i<gffrec.attrs->Count();i++) {\n          defline.append(\" \");\n          defline.append(gffrec.getAttrName(i));\n          defline.append(\"=\");\n          defline.append(gffrec.getAttrValue(i));\n          }\n        }\n      printFasta(f_w, defline, exont, seqlen);\n      GFREE(exont);\n      }\n    } //writing f_w (spliced exons)\n return true;\n}\n\nvoid openfw(FILE* &f, GArgs& args, char opt) {\n  GStr s=args.getOpt(opt);\n  if (!s.is_empty()) {\n      if (s=='-')\n       f=stdout;\n      else {\n       f=fopen(s,\"w\");\n       if (f==NULL) GError(\"Error creating file: %s\\n\", s.chars());\n       }\n     }\n}\n\n#define FWCLOSE(fh) if (fh!=NULL && fh!=stdout) fclose(fh)\n#define FRCLOSE(fh) if (fh!=NULL && fh!=stdin) fclose(fh)\n\nvoid printGff3Header(FILE* f, GArgs& args) {\n  fprintf(f, \"# \");\n  args.printCmdLine(f);\n  fprintf(f, \"##gff-version 3\\n\");\n  //for (int i=0;i<gseqdata.Count();i++) {\n  //\n  //}\n  }\n\nbool validateGffRec(GffObj* gffrec, GList<GffObj>* gfnew) {\n\tif (reftbl.Count()>0) {\n\t\tGStr refname(gffrec->getRefName());\n\t\tRefTran* rt=reftbl.Find(refname.chars());\n\t\tif (rt==NULL && refname.length()>2 && refname[-2]=='.' && isdigit(refname[-1])) {\n\t\t\t//try removing the version suffix\n\t\t\trefname.cut(-2);\n\t\t\t//GMessage(\"[DEBUG] Trying ref name '%s'...\\n\", refname.chars());\n\t\t\trt=reftbl.Find(refname.chars());\n\t\t}\n\t\tif (rt) {\n\t\t\tgffrec->setRefName(rt->new_name);\n\t\t}\n\t\telse return false; //discard, ref seq not in the given translation table\n\t}\n\tif (mRNAOnly && gffrec->isDiscarded()) {\n\t\t//discard generic \"locus\" features with no other detailed subfeatures\n\t\t//GMessage(\"Warning: discarding %s GFF generic gene/locus container %s\\n\",gffrec->getID());\n\t\treturn false;\n\t}\n\n\tif (rfltGSeq!=NULL) { //filter by gseqName\n\t\tif (strcmp(gffrec->getGSeqName(),rfltGSeq)!=0) {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (rfltStrand>0 && gffrec->strand !=rfltStrand) {\n\t\treturn false;\n\t}\n\t//check coordinates\n\tif (rfltStart!=0 || rfltEnd!=MAX_UINT) {\n\t\tif (rfltWithin) {\n\t\t\tif (gffrec->start<rfltStart || gffrec->end>rfltEnd) {\n\t\t\t\treturn false; //not within query range\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (gffrec->start>rfltEnd || gffrec->end<rfltStart) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\tif (multiExon && gffrec->exons.Count()<=1) {\n\t\treturn false;\n\t}\n\tif (wCDSonly && gffrec->CDstart==0) {\n\t\treturn false;\n\t}\n\tif (ensembl_convert && startsWith(gffrec->getID(), \"ENS\")) {\n\t\t//keep track of chr|gene_id data -- coordinate range\n\t\tchar* geneid=gffrec->getGeneID();\n\t\tif (geneid!=NULL) {\n\t\t\tGeneInfo* ginfo=gene_ids.Find(geneid);\n\t\t\tif (ginfo==NULL) {//first time seeing this gene ID\n\t\t\t\tGeneInfo* geneinfo=new GeneInfo(gffrec, ensembl_convert);\n\t\t\t\tgene_ids.Add(geneid, geneinfo);\n\t\t\t\tif (gfnew!=NULL) gfnew->Add(geneinfo->gf);\n\t\t\t}\n\t\t\telse ginfo->update(gffrec);\n\t\t}\n\t}\n\treturn true;\n}\n\n\nint main(int argc, char * const argv[]) {\n GArgs args(argc, argv, \n   \"debug;merge;cluster-only;help;force-exons;no-pseudo;MINCOV=MINPID=hvOUNHWCVJMKQNSXTDAPRZFGLEm:g:i:r:s:t:a:b:o:w:x:y:d:\");\n args.printError(USAGE, true);\n if (args.getOpt('h') || args.getOpt(\"help\")) {\n    GMessage(\"%s\",USAGE);\n    exit(1);\n    }\n debugMode=(args.getOpt(\"debug\")!=NULL);\n decodeChars=(args.getOpt('D')!=NULL);\n forceExons=(args.getOpt(\"force-exons\")!=NULL);\n NoPseudo=(args.getOpt(\"no-pseudo\")!=NULL);\n mRNAOnly=(args.getOpt('O')==NULL);\n //sortByLoc=(args.getOpt('S')!=NULL);\n addDescr=(args.getOpt('A')!=NULL);\n verbose=(args.getOpt('v')!=NULL);\n wCDSonly=(args.getOpt('C')!=NULL);\n validCDSonly=(args.getOpt('V')!=NULL);\n altPhases=(args.getOpt('H')!=NULL);\n fmtGTF=(args.getOpt('T')!=NULL); //switch output format to GTF\n bothStrands=(args.getOpt('B')!=NULL);\n fullCDSonly=(args.getOpt('J')!=NULL);\n spliceCheck=(args.getOpt('N')!=NULL);\n bool matchAllIntrons=(args.getOpt('K')==NULL);\n bool fuzzSpan=(args.getOpt('Q')!=NULL);\n if (args.getOpt('M') || args.getOpt(\"merge\")) {\n    doCluster=true;\n    doCollapseRedundant=true;\n    }\n   else {\n    if (!matchAllIntrons || fuzzSpan) {\n      GMessage(\"%s\",USAGE);\n      GMessage(\"Error: -K or -Q options require -M/--merge option!\\n\");\n      exit(1);\n      }\n    }\n if (args.getOpt(\"cluster-only\")) {\n    doCluster=true;\n    doCollapseRedundant=false;\n    if (!matchAllIntrons || fuzzSpan) {\n      GMessage(\"%s\",USAGE);\n      GMessage(\"Error: -K or -Q options have no effect with --cluster-only.\\n\");\n      exit(1);\n      }\n    }\n if (fullCDSonly) validCDSonly=true;\n if (verbose) { \n     fprintf(stderr, \"Command line was:\\n\");\n     args.printCmdLine(stderr);\n     }\n\n fullattr=(args.getOpt('F')!=NULL);\n if (args.getOpt('G')==NULL) \n    noExonAttr=!fullattr;\n   else {\n     noExonAttr=true;\n     fullattr=true;\n     }\n if (NoPseudo && !fullattr) {\n\t noExonAttr=true;\n\t fullattr=true;\n }\n ensembl_convert=(args.getOpt('L')!=NULL);\n if (ensembl_convert) {\n    fullattr=true;\n    noExonAttr=false;\n    //sortByLoc=true;\n    }\n    \n mergeCloseExons=(args.getOpt('Z')!=NULL);\n multiExon=(args.getOpt('U')!=NULL);\n writeExonSegs=(args.getOpt('W')!=NULL);\n tracklabel=args.getOpt('t');\n GFastaDb gfasta(args.getOpt('g'));\n //if (gfasta.fastaPath!=NULL)\n //    sortByLoc=true; //enforce sorting by chromosome/contig\n GStr s=args.getOpt('i');\n if (!s.is_empty()) maxintron=s.asInt();\n \n FILE* f_repl=NULL;\n s=args.getOpt('d');\n if (!s.is_empty()) {\n   if (s==\"-\") f_repl=stdout;\n     else {\n       f_repl=fopen(s.chars(), \"w\");\n       if (f_repl==NULL) GError(\"Error creating file %s\\n\", s.chars());\n       }\n   }\n \n rfltWithin=(args.getOpt('R')!=NULL);\n s=args.getOpt('r');\n if (!s.is_empty()) {\n   s.trim();\n   if (s[0]=='+' || s[0]=='-') {\n     rfltStrand=s[0];\n     s.cut(0,1);\n     }\n   int isep=s.index(':');\n   if (isep>0) { //gseq name given\n      if (rfltStrand==0 && (s[isep-1]=='+' || s[isep-1]=='-')) {\n        isep--;\n        rfltStrand=s[isep];\n        s.cut(isep,1);\n        }\n      if (isep>0) \n          rfltGSeq=Gstrdup((s.substr(0,isep)).chars());\n      s.cut(0,isep+1);\n      }\n   GStr gsend;\n   char slast=s[s.length()-1];\n   if (rfltStrand==0 && (slast=='+' || slast=='-')) {\n      s.chomp(slast);\n      rfltStrand=slast;\n      }\n   if (s.index(\"..\")>=0) gsend=s.split(\"..\");\n                    else gsend=s.split('-');\n   if (!s.is_empty()) rfltStart=(uint)s.asInt();\n   if (!gsend.is_empty()) {\n      rfltEnd=(uint)gsend.asInt();\n      if (rfltEnd==0) rfltEnd=MAX_UINT;\n      }\n   } //gseq/range filtering\n else {\n   if (rfltWithin)\n     GError(\"Error: option -R requires -r!\\n\");\n   //if (rfltWholeTranscript)\n   //  GError(\"Error: option -P requires -r!\\n\");\n   }\n s=args.getOpt('m');\n if (!s.is_empty()) {\n   FILE* ft=fopen(s,\"r\");\n   if (ft==NULL) GError(\"Error opening reference table: %s\\n\",s.chars());\n   loadRefTable(ft, reftbl);\n   fclose(ft);\n   }\n s=args.getOpt('s');\n if (!s.is_empty()) {\n   FILE* fsize=fopen(s,\"r\");\n   if (fsize==NULL) GError(\"Error opening info file: %s\\n\",s.chars());\n   loadSeqInfo(fsize, seqinfo);\n   fclose(fsize);\n   }\n\n openfw(f_out, args, 'o');\n //if (f_out==NULL) f_out=stdout;\n if (gfasta.fastaPath==NULL && (validCDSonly || spliceCheck || args.getOpt('w')!=NULL || args.getOpt('x')!=NULL || args.getOpt('y')!=NULL))\n  GError(\"Error: -g option is required for options -w, -x, -y, -V, -N, -M !\\n\");\n\n openfw(f_w, args, 'w');\n openfw(f_x, args, 'x');\n openfw(f_y, args, 'y');\n if (f_y!=NULL || f_x!=NULL) wCDSonly=true;\n //useBadCDS=useBadCDS || (fgtfok==NULL && fgtfbad==NULL && f_y==NULL && f_x==NULL);\n \n int numfiles = args.startNonOpt();\n //GList<GffObj> gfkept(false,true); //unsorted, free items on delete\n int out_counter=0; //number of records printed\n while (true) {\n   GStr infile;\n   if (numfiles) {\n          infile=args.nextNonOpt();\n          if (infile.is_empty()) break;\n          if (infile==\"-\") { f_in=stdin; infile=\"stdin\"; }\n               else \n                 if ((f_in=fopen(infile, \"r\"))==NULL)\n                    GError(\"Error: cannot open input file %s!\\n\",infile.chars());\n          }\n        else \n          infile=\"-\";\n   GffLoader gffloader(infile.chars());\n   gffloader.transcriptsOnly=mRNAOnly;\n   gffloader.fullAttributes=fullattr;\n   gffloader.noExonAttrs=noExonAttr;\n   gffloader.mergeCloseExons=mergeCloseExons;\n   gffloader.showWarnings=(args.getOpt('E')!=NULL);\n   gffloader.noPseudo=NoPseudo;\n   gffloader.load(g_data, &validateGffRec, doCluster, doCollapseRedundant, \n                             matchAllIntrons, fuzzSpan, forceExons);\n   if (doCluster) \n     collectLocusData(g_data);\n   if (numfiles==0) break;\n   }\n   \n GStr loctrack(\"gffcl\");\n if (tracklabel) loctrack=tracklabel;\n g_data.setSorted(&gseqCmpName);\n GffPrintMode exonPrinting;\n if (fmtGTF) {\n\t exonPrinting = pgtfAny;\n } else {\n\t exonPrinting = forceExons ? pgffBoth : pgffAny;\n }\n bool firstGff3Print=!fmtGTF;\n if (doCluster) {\n   //grouped in loci\n   for (int g=0;g<g_data.Count();g++) {\n     GenomicSeqData* gdata=g_data[g];\n     int gfs_i=0;\n     for (int l=0;l<gdata->loci.Count();l++) {\n       GffLocus& loc=*(gdata->loci[l]);\n       //check all non-replaced transcripts in this locus:\n       int numvalid=0;\n       int idxfirstvalid=-1;\n       for (int i=0;i<loc.rnas.Count();i++) {\n         GffObj& t=*(loc.rnas[i]);\n         if (f_out) {\n          while (gfs_i<gdata->gfs.Count() && gdata->gfs[gfs_i]->start<=t.start) {\n             GffObj& gfst=*(gdata->gfs[gfs_i]);\n             if ((gfst.udata&4)==0) { //never printed\n               gfst.udata|=4;\n               if (firstGff3Print) { printGff3Header(f_out, args);firstGff3Print=false; }\n               if (gfst.exons.Count()==0 && gfst.children.Count()==0 && forceExons)\n                gfst.addExon(gfst.start,gfst.end);\n               gfst.printGxf(f_out, exonPrinting, tracklabel, NULL, decodeChars);\n               }\n             ++gfs_i;\n          }\n         }\n         GTData* tdata=(GTData*)(t.uptr);\n         if (tdata->replaced_by!=NULL) {\n            if (f_repl && (t.udata & 8)==0) {\n               //t.udata|=8;\n               fprintf(f_repl, \"%s\", t.getID());\n               GTData* rby=tdata;\n               while (rby->replaced_by!=NULL) {\n                  fprintf(f_repl,\" => %s\", rby->replaced_by->getID());\n                  rby->rna->udata|=8;\n                  rby=(GTData*)(rby->replaced_by->uptr);\n                  }\n               fprintf(f_repl, \"\\n\");\n               }\n            continue;\n            }\n         if (process_transcript(gfasta, t)) {\n             t.udata|=4; //tag it as valid\n             numvalid++;\n             if (idxfirstvalid<0) idxfirstvalid=i;\n             }\n         }\n       if (f_out && numvalid>0) {\n         GStr locname(\"RLOC_\");\n         locname.appendfmt(\"%08d\",loc.locus_num);\n         if (!fmtGTF) {\n           if (firstGff3Print) { printGff3Header(f_out, args);firstGff3Print=false; }\n           fprintf(f_out,\"%s\\t%s\\tlocus\\t%d\\t%d\\t.\\t%c\\t.\\tID=%s;locus=%s\",\n                    loc.rnas[0]->getGSeqName(), loctrack.chars(), loc.start, loc.end, loc.strand,\n                     locname.chars(), locname.chars());\n           //const char* loc_gname=loc.getGeneName();\n           if (loc.gene_names.Count()>0) { //print all gene names associated to this locus\n              fprintf(f_out, \";genes=%s\",loc.gene_names.First()->name.chars());\n              for (int i=1;i<loc.gene_names.Count();i++) {\n                fprintf(f_out, \",%s\",loc.gene_names[i]->name.chars());\n                }\n              }\n           if (loc.gene_ids.Count()>0) { //print all GeneIDs names associated to this locus\n              fprintf(f_out, \";geneIDs=%s\",loc.gene_ids.First()->name.chars());\n              for (int i=1;i<loc.gene_ids.Count();i++) {\n                fprintf(f_out, \",%s\",loc.gene_ids[i]->name.chars());\n                }\n              }\n           fprintf(f_out, \";transcripts=%s\",loc.rnas[idxfirstvalid]->getID());\n           for (int i=idxfirstvalid+1;i<loc.rnas.Count();i++) {\n              fprintf(f_out, \",%s\",loc.rnas[i]->getID());\n              }\n           fprintf(f_out, \"\\n\");\n           }\n         //now print all valid, non-replaced transcripts in this locus:\n         for (int i=0;i<loc.rnas.Count();i++) {\n           GffObj& t=*(loc.rnas[i]);\n           GTData* tdata=(GTData*)(t.uptr);\n           if (tdata->replaced_by!=NULL || ((t.udata & 4)==0)) continue;\n           t.addAttr(\"locus\", locname.chars());\n           out_counter++;\n           if (fmtGTF) t.printGxf(f_out, exonPrinting, tracklabel, NULL, decodeChars);\n               else {\n                if (firstGff3Print) { printGff3Header(f_out, args);firstGff3Print=false; }\n                //print the parent first, if any\n                if (t.parent!=NULL && ((t.parent->udata & 4)==0)) {\n                    GTData* pdata=(GTData*)(t.parent->uptr);\n                    if (pdata && pdata->geneinfo!=NULL) \n                         pdata->geneinfo->finalize();\n                    t.parent->addAttr(\"locus\", locname.chars());\n                    t.parent->printGxf(f_out, exonPrinting, tracklabel, NULL, decodeChars);\n                    t.parent->udata|=4;\n                    }\n                t.printGxf(f_out, exonPrinting, tracklabel, NULL, decodeChars);\n                }\n            }\n          } //have valid transcripts to print\n       }//for each locus\n     //print the rest of the isolated pseudo/gene/region features not printed yet\n     if (f_out) {\n      while (gfs_i<gdata->gfs.Count()) {\n         GffObj& gfst=*(gdata->gfs[gfs_i]);\n         if ((gfst.udata&4)==0) { //never printed\n           gfst.udata|=4;\n           if (firstGff3Print) { printGff3Header(f_out, args);firstGff3Print=false; }\n           if (gfst.exons.Count()==0 && gfst.children.Count()==0 && forceExons)\n             gfst.addExon(gfst.start,gfst.end);\n           gfst.printGxf(f_out, exonPrinting, tracklabel, NULL, decodeChars);\n           }\n         ++gfs_i;\n      }\n     }\n    } //for each genomic sequence\n   }\n  else {\n   //not grouped into loci, print the rnas with their parents, if any\n   int numvalid=0;\n   for (int g=0;g<g_data.Count();g++) {\n     GenomicSeqData* gdata=g_data[g];\n     int gfs_i=0;\n     for (int m=0;m<gdata->rnas.Count();m++) {\n        GffObj& t=*(gdata->rnas[m]);\n        if (f_out) {\n         while (gfs_i<gdata->gfs.Count() && gdata->gfs[gfs_i]->start<=t.start) {\n            GffObj& gfst=*(gdata->gfs[gfs_i]);\n            if ((gfst.udata&4)==0) { //never printed\n              gfst.udata|=4;\n              if (firstGff3Print) { printGff3Header(f_out, args);firstGff3Print=false; }\n              if (gfst.exons.Count()==0 && gfst.children.Count()==0 && forceExons)\n               gfst.addExon(gfst.start,gfst.end);\n              gfst.printGxf(f_out, exonPrinting, tracklabel, NULL, decodeChars);\n              }\n            ++gfs_i;\n         }\n        }\n        GTData* tdata=(GTData*)(t.uptr);\n        if (tdata->replaced_by!=NULL) continue;\n        if (process_transcript(gfasta, t)) {\n           t.udata|=4; //tag it as valid\n           numvalid++;\n           if (f_out) {\n             if (tdata->geneinfo) tdata->geneinfo->finalize();\n             out_counter++;\n             if (fmtGTF) t.printGxf(f_out, exonPrinting, tracklabel, NULL, decodeChars);\n               else {\n                if (firstGff3Print) { printGff3Header(f_out, args);firstGff3Print=false; }\n                //print the parent first, if any\n                if (t.parent!=NULL && ((t.parent->udata & 4)==0)) {\n                    GTData* pdata=(GTData*)(t.parent->uptr);\n                    if (pdata && pdata->geneinfo!=NULL) \n                         pdata->geneinfo->finalize();\n                    t.parent->printGxf(f_out, exonPrinting, tracklabel, NULL, decodeChars);\n                    t.parent->udata|=4;\n                    }\n                t.printGxf(f_out, exonPrinting, tracklabel, NULL, decodeChars);\n                }\n             }//GFF/GTF output requested\n           } //valid transcript\n        } //for each rna\n     //print the rest of the isolated pseudo/gene/region features not printed yet\n     if (f_out) {\n      while (gfs_i<gdata->gfs.Count()) {\n         GffObj& gfst=*(gdata->gfs[gfs_i]);\n         if ((gfst.udata&4)==0) { //never printed\n           gfst.udata|=4;\n           if (firstGff3Print) { printGff3Header(f_out, args);firstGff3Print=false; }\n           if (gfst.exons.Count()==0 && gfst.children.Count()==0 && forceExons)\n            gfst.addExon(gfst.start,gfst.end);\n           gfst.printGxf(f_out, exonPrinting, tracklabel, NULL, decodeChars);\n           }\n         ++gfs_i;\n      }\n     }\n    } //for each genomic seq\n   } //not clustered\n if (f_repl && f_repl!=stdout) fclose(f_repl);\n seqinfo.Clear();\n //if (faseq!=NULL) delete faseq;\n //if (gcdb!=NULL) delete gcdb;\n GFREE(rfltGSeq);\n FRCLOSE(f_in);\n FWCLOSE(f_out);\n FWCLOSE(f_w);\n FWCLOSE(f_x);\n FWCLOSE(f_y);\n }\n\n\n"
  },
  {
    "path": "src/graph_optimize.cpp",
    "content": "/*\n *  graph_optimize.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 6/1/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <vector>\n#include <algorithm>\n\n#include \"graph_optimize.h\"\n// for graph optimization only\n\n#include <lemon/topology.h>\n#include <lemon/smart_graph.h>\n#include <lemon/bipartite_matching.h>\n\n#include \"scaffold_graph.h\"\n#include \"scaffolds.h\"\n#include \"filters.h\"\n#include \"matching_merge.h\"\n\nusing namespace std;\nusing namespace boost;\n\nnamespace ublas = boost::numeric::ublas;\n\nvoid fill_gaps(vector<Scaffold>& scaffolds, int fill_size)\n{\n\tfor (size_t i = 0; i < scaffolds.size(); ++i)\n\t\tscaffolds[i].fill_gaps(fill_size);\n}\n\nenum ConflictState { UNKNOWN_CONFLICTS = 0, SAME_CONFLICTS, DIFF_CONFLICTS };\n\nbool scaff_left_lt_right_gt(const Scaffold& lhs, const Scaffold& rhs)\n{\n    if (lhs.left() != rhs.left())\n        return lhs.left() < rhs.left();\n    return lhs.right() > rhs.right();\n}\n\nbool op_left_lt_right_lt(const AugmentedCuffOp& lhs, const AugmentedCuffOp& rhs)\n{\n\tif (lhs.genomic_offset != rhs.genomic_offset)\n\t{\n\t\treturn lhs.genomic_offset < rhs.genomic_offset;\n\t}\n\tif (lhs.genomic_length != rhs.genomic_length)\n\t{\n\t\treturn lhs.genomic_length < rhs.genomic_length;\n\t}\n\treturn false;\n}\n\nvoid extract_conflicting_ops(const vector<AugmentedCuffOp>& ops,\n                                       vector<AugmentedCuffOp>& conflict_ops)\n{\t\n\tfor (size_t i = 0; i < ops.size(); ++i)\n\t{\n\t\tfor (size_t j = i+1; j < ops.size(); ++j)\n\t\t{\n\t\t\tif (AugmentedCuffOp::overlap_in_genome(ops[i], ops[j]))\n\t\t\t{\n\t\t\t\tif (!AugmentedCuffOp::compatible(ops[i], ops[j]))\n\t\t\t\t{\n\t\t\t\t\tif (!binary_search(conflict_ops.begin(), conflict_ops.end(), ops[i]))\n\t\t\t\t\t{\n\t\t\t\t\t\tconflict_ops.push_back(ops[i]);\n\t\t\t\t\t\tsort(conflict_ops.begin(), conflict_ops.end());\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (!binary_search(conflict_ops.begin(), conflict_ops.end(), ops[j]))\n\t\t\t\t\t{\n\t\t\t\t\t\tconflict_ops.push_back(ops[j]);\n\t\t\t\t\t\tsort(conflict_ops.begin(), conflict_ops.end());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n            \n\t\t}\n\t}    \n}\n\nvoid collect_non_redundant_ops(const vector<Scaffold>& scaffolds,\n                               vector<AugmentedCuffOp>& ops)\n{\n\n\tfor (size_t i = 0; i < scaffolds.size(); ++i)\n\t{\n\t\tops.insert(ops.end(), \n\t\t\t\t   scaffolds[i].augmented_ops().begin(), \n\t\t\t\t   scaffolds[i].augmented_ops().end());\n\t}\n    sort(ops.begin(), ops.end());\n    vector<AugmentedCuffOp>::iterator new_end = unique(ops.begin(), ops.end());\n\tops.erase(new_end, ops.end());\n\t\n\tsort (ops.begin(), ops.end(), op_left_lt_right_lt);   \n}\n\nvoid fill_unambiguous_unknowns(vector<Scaffold>& to_fill, \n                               const vector<Scaffold>& constitutive)\n{\n//    vector<AugmentedCuffOp> conflict_ops;\n//    vector<AugmentedCuffOp> ops;\n\n    for (size_t i = 0; i < to_fill.size(); ++i)\n    {\n        if (to_fill[i].has_unknown())\n        {\n            for( size_t j = 0; j < constitutive.size(); ++j)\n            {\n                const Scaffold& cons = constitutive[j];\n                if (Scaffold::overlap_in_genome(to_fill[i], cons, 0) &&\n                    Scaffold::compatible(to_fill[i], cons))\n                {\n                    if (cons.strand() != CUFF_STRAND_UNKNOWN)\n                        to_fill[i].strand(cons.strand());\n\n                    to_fill[i].fill_gaps(cons.augmented_ops());\n                    if (!to_fill[i].has_unknown())\n                    {\n                        break;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// WARNING: scaffolds MUST be sorted by scaff_lt_rt() in order for this routine\n// to work correctly.\nvoid add_non_constitutive_to_scaffold_mask(const vector<Scaffold>& scaffolds,\n\t\t\t\t\t\t\t\t\t\t   vector<bool>& scaffold_mask)\n{\t\n\t\n\t// First, we filter out all fragments that are entirely contained in a \n\t// constitutive exon of the \"gene\".  If such fragments were non-constitutive,\n\t// neither would that exon.  Also, we can examine all fragments at most\n\t// once here, because if we don't look at them here, we'll look hard in the\n\t// next loop\n\tScaffold smashed_gene;\n\t\n\t// setting introns_overwrite_matches in a gene smash takes only it's\n\t// constitutive regions\n\tScaffold::merge(scaffolds, smashed_gene, true); \n\t\n\tvector<bool> smash_filter(scaffolds.size(), false);\n\t\n\tconst vector<AugmentedCuffOp>& cig = smashed_gene.augmented_ops();\n\tsize_t next_frag = 0; \n\t\n\tsize_t num_filtered = 0;\n\tfor (size_t j = 0; j < cig.size(); ++j)\n\t{\n\t\tif (cig[j].opcode == CUFF_MATCH)\n\t\t{\n\t\t\tfor (;next_frag < scaffolds.size(); ++next_frag)\n\t\t\t{\n\t\t\t\tconst Scaffold& frag = scaffolds[next_frag];\n\t\t\t\t\n\t\t\t\tif (frag.left() >= cig[j].g_left() && \n\t\t\t\t\tfrag.right() <= cig[j].g_right())\n\t\t\t\t{\n\t\t\t\t\tsmash_filter[next_frag] = true;\n\t\t\t\t\t//scaffold_mask[next_frag] = true;\n\t\t\t\t\tnum_filtered++;\n\t\t\t\t}\n\t\t\t\tif (frag.left() >= cig[j].g_right())\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n    \n\tverbose_msg(\"%lu constitutive reads of %lu smash-filtered from further consideration\\n\", num_filtered, smash_filter.size());\n    \n    vector<AugmentedCuffOp> ops;\n    collect_non_redundant_ops(scaffolds, ops);\n\t\n    vector<AugmentedCuffOp> conflict_ops;\n    extract_conflicting_ops(ops, conflict_ops);\n\t\n\tfor (size_t i = 0; i < scaffolds.size(); ++i)\n\t{\n\t\tif (smash_filter[i])\n\t\t\tcontinue;\n\t\tconst vector<AugmentedCuffOp>& s_ops = scaffolds[i].augmented_ops();\n\t\tfor (size_t j = 0; j < s_ops.size(); ++j)\n\t\t{\n\t\t\tif (binary_search(conflict_ops.begin(), conflict_ops.end(), s_ops[j]))\n\t\t\t{\n\t\t\t\tscaffold_mask[i] = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n\nbool collapse_contained_transfrags(vector<Scaffold>& scaffolds, \n                                   uint32_t max_rounds)\n{\n\t// The containment graph is a bipartite graph with an edge (u,v) when\n\t// u is (not necessarily properly) contained in v and is the two are\n\t// compatible.\n\ttypedef lemon::SmartBpUGraph ContainmentGraph;\n\tnormal norm(0, 0.1);\n\tbool performed_collapse = false;\n    \n\twhile (max_rounds--)\n\t{\n\t\t\n\t\tverbose_msg(\"%s\\tStarting new collapse round\\n\", bundle_label->c_str());\n        \n\t\tContainmentGraph containment;\n\t\t\n\t\t\n\t\ttypedef pair<ContainmentGraph::ANode, ContainmentGraph::BNode> NodePair;\n\t\tvector<NodePair> node_ids;\n\t\tvector<size_t> A_to_scaff(scaffolds.size());\n\t\tvector<size_t> B_to_scaff(scaffolds.size());\n\t\t\n\t\tfor (size_t n = 0; n < scaffolds.size(); ++n)\n\t\t{\n\t\t\tNodePair p = make_pair(containment.addANode(),\n\t\t\t\t\t\t\t\t   containment.addBNode());\n\t\t\tnode_ids.push_back(p);\n\t\t\tA_to_scaff[containment.aNodeId(p.first)] = n;\n\t\t\tB_to_scaff[containment.bNodeId(p.second)] = n;\n\t\t}\n\t\t\n\t\tbool will_perform_collapse = false;\n\t\tfor (size_t i = 0; i < scaffolds.size(); ++i)\n\t\t{\n\t\t\tfor (size_t j = 0; j < scaffolds.size(); ++j)\n\t\t\t{\n\t\t\t\tif (i == j)\n\t\t\t\t\tcontinue;\n                \n\t\t\t\tif (scaffolds[i].contains(scaffolds[j]) &&\n                    Scaffold::compatible(scaffolds[i], scaffolds[j]))\n\t\t\t\t{\n                    // To gaurd against the identity collapse, which won't \n\t\t\t\t\t// necessary reduce the total number of scaffolds.\n\t\t\t\t\tif (scaffolds[j].contains(scaffolds[i]) && i < j)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tconst NodePair& nj = node_ids[j];\n\t\t\t\t\tconst NodePair& ni = node_ids[i];\n\t\t\t\t\tassert (nj.first != ni.second);\n                    \n\t\t\t\t\twill_perform_collapse = true;\n\t\t\t\t\tContainmentGraph::UEdge e = containment.addEdge(nj.first,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tni.second);\t\t\t\t\t\t\n                    \n                }\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (will_perform_collapse == false)\n\t\t\treturn performed_collapse;\n\t\t\n\t\tlemon::MaxBipartiteMatching<ContainmentGraph>  matcher(containment);\n        \n\t\tverbose_msg(\"%s\\tContainment graph has %d nodes, %d edges\\n\", bundle_label->c_str(), containment.aNodeNum(), containment.uEdgeNum());\n\t\tverbose_msg(\"%s\\tFinding a maximum matching to collapse scaffolds\\n\", bundle_label->c_str());\n        \n\t\tmatcher.run();\n        \n\t\tverbose_msg( \"%s\\tWill collapse %d scaffolds\\n\", bundle_label->c_str(), matcher.matchingSize());\n\t\t\n\t\tContainmentGraph::UEdgeMap<bool> matched_edges(containment);\n\t\t\n\t\tmatcher.matching(matched_edges);\n\t\t\n        merge_from_matching(containment, matcher, scaffolds);\n        \n\t\tperformed_collapse = true;\n\t}\n\treturn performed_collapse;\n}\n\nbool scaff_smaller_lt_rt(const Scaffold& lhs, const Scaffold& rhs)\n{\n\tsize_t lhs_len = lhs.right() - lhs.left();\n\tsize_t rhs_len = rhs.right() - rhs.left();\n\t\n\tif (lhs_len != rhs_len)\n\t{\n\t\treturn lhs_len < rhs_len;\n\t}\n\telse \n\t{\n\t\treturn scaff_lt_rt(lhs, rhs);\n\t}\n\treturn false;\n}\n\nstruct FragIndexSortSmallerLR\n{\n\tFragIndexSortSmallerLR(const vector<Scaffold>& frags) : fragments(frags) {}\n\t\n\tconst vector<Scaffold>& fragments;\n\t\n\tbool operator()(size_t lhs_frag_idx, size_t rhs_frag_idx)\n\t{\n\t\tconst Scaffold& lhs = fragments[lhs_frag_idx];\n\t\tconst Scaffold& rhs = fragments[rhs_frag_idx];\n\t\t\n\t\tsize_t lhs_len = lhs.right() - lhs.left();\n\t\tsize_t rhs_len = rhs.right() - rhs.left();\n\t\t\n\t\tif (lhs_len != rhs_len)\n\t\t{\n\t\t\treturn lhs_len > rhs_len;\n\t\t}\n\t\telse \n\t\t{\n\t\t\treturn scaff_lt_rt(lhs, rhs);\n\t\t}\n\t\treturn false;\n\t}\n};\n\nbool collapse_equivalent_transfrags(vector<Scaffold>& fragments, \n                                    uint32_t max_rounds)\n{\n\t// The containment graph is a bipartite graph with an edge (u,v) when\n\t// u is (not necessarily properly) contained in v and is the two are\n\t// compatible.\n\ttypedef lemon::SmartBpUGraph ContainmentGraph;\n\tnormal norm(0, 0.1);\n\tbool performed_collapse = false;\n\t\n\t//double last_size = -1;\n    //long leftmost = 9999999999;\n    long leftmost = LONG_MAX-1;\n    long rightmost = -1;\n    \n    for (size_t i = 0; i < fragments.size(); ++i)\n    {\n        leftmost = std::min((long)fragments[i].left(), leftmost);\n        rightmost = std::max((long)fragments[i].right(), rightmost);\n    }\n    \n    //long bundle_length = rightmost - leftmost;\n    \n\twhile (max_rounds--)\n\t{\n\t\t\n\t\tsort (fragments.begin(), fragments.end(), scaff_lt_rt);\n\t\t\n\t\t\n\t\tvector<size_t> smaller_idx_array;\n\t\tfor (size_t i = 0; i < fragments.size(); ++i)\n        {\n            smaller_idx_array.push_back(i);\n        }\n\t\t\n\t\tsort(smaller_idx_array.begin(), \n\t\t\t smaller_idx_array.end(), \n\t\t\t FragIndexSortSmallerLR(fragments));\n\t\t\n\t\tverbose_msg(\"%s\\tStarting new collapse round\\n\", bundle_label->c_str());\n        verbose_msg(\"%s\\tFinding fragment-level conflicts\\n\", bundle_label->c_str());\n\n        bool will_perform_collapse = false;\n\t\t\n        verbose_msg( \"%s\\tAssessing overlaps between %lu fragments for identical conflict sets\\n\", \n                bundle_label->c_str(), \n                fragments.size());\n        vector<size_t> replacements;\n        for (size_t i = 0; i < fragments.size(); ++i)\n        {\n            replacements.push_back(i);\n        }\n\t\t\n\t\tsize_t curr_frag = 0;\n\t\tvector<int> curr_conflicts;\n\t\t\n//\t\tfor (int i = 0; i < fragments.size(); ++i)\n//\t\t{\n//\t\t\tif (Scaffold::overlap_in_genome(fragments[0], fragments[i], 0))\n//\t\t\t{\n//\t\t\t\tif (!Scaffold::compatible(fragments[0], fragments[i]))\n//\t\t\t\t{\n//\t\t\t\t\tcurr_conflicts.push_back(i);\n//\t\t\t\t}\n//\t\t\t}\n//\t\t}\n\t\t\n        double mean_length = 0;\n        for (size_t i = 0; i < fragments.size(); ++i)\n        {\n            mean_length += fragments[i].length();\n        }\n        \n        mean_length /= fragments.size();\n        \n        double variance = 0.0;\n        for (size_t i = 0; i < fragments.size(); ++i)\n        {\n            double v = fragments[i].length() - mean_length;\n            v *= v;\n            variance += v;\n        }\n        \n        variance /= fragments.size();\n        double frag_len_std_dev = sqrt(variance);\n        \n\t\tint num_merges = 0;\n\t\t\n\t\twhile (curr_frag < smaller_idx_array.size())\n\t\t{\t\n\t\t\tsize_t curr_frag_native_idx = smaller_idx_array[curr_frag];\n\t\t\tif (replacements[curr_frag_native_idx] == curr_frag_native_idx)\n\t\t\t{\n\t\t\t\tsize_t lhs = curr_frag;\n\t\t\t\t\n\t\t\t\tsize_t lhs_native_idx = smaller_idx_array[lhs];\n\t\t\t\t\n\t\t\t\tconst Scaffold& lhs_scaff = fragments[lhs_native_idx];\n\t\t\t\tcurr_conflicts.clear();\n\t\t\t\t\n\t\t\t\tdouble lhs_len = lhs_scaff.right() - lhs_scaff.left();\n\t\t\t\t\n\t\t\t\tfor (size_t i = 0; i < smaller_idx_array.size(); ++i)\n\t\t\t\t{\n\t\t\t\t\tsize_t j_scaff_idx = smaller_idx_array[i];\n                    if (replacements[j_scaff_idx] == j_scaff_idx)\n                    {\n                        if (Scaffold::overlap_in_genome(lhs_scaff, fragments[j_scaff_idx], 0))\n                        {\n                            if (!Scaffold::compatible(lhs_scaff, fragments[j_scaff_idx]))\n                            {\n                                curr_conflicts.push_back(j_scaff_idx);\n                            }\n                        }\n                    }\n\t\t\t\t}\n\t\t\t\tsort(curr_conflicts.begin(), curr_conflicts.end());\n\t\t\t\t\n\t\t\t\t//bool advanced_curr = false;\n\t\t\t\tfor (size_t c = lhs + 1; c < smaller_idx_array.size(); ++c)\n\t\t\t\t{\n\t\t\t\t\tsize_t c_native_idx = smaller_idx_array[c];\n\t\t\t\t\tconst Scaffold& c_scaff = fragments[c_native_idx];\n\t\t\t\t\tif (replacements[c_native_idx] == c_native_idx &&\n\t\t\t\t\t\tlhs_scaff.contains(c_scaff))\n\t\t\t\t\t{\n\t\t\t\t\t\tdouble c_len = c_scaff.right() - c_scaff.left();\n\n\t\t\t\t\t\tif (lhs_len - c_len > frag_len_std_dev)\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tif (c_scaff.augmented_ops() == lhs_scaff.augmented_ops())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (num_merges % 100 == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tverbose_msg(\"%s\\tCollapsing frag # %d\\n\", \n\t\t\t\t\t\t\t\t\t\tbundle_label->c_str(), \n\t\t\t\t\t\t\t\t\t\tnum_merges);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvector<Scaffold> s;\n\t\t\t\t\t\t\ts.push_back(c_scaff);\n\t\t\t\t\t\t\ts.push_back(lhs_scaff);\n\t\t\t\t\t\t\tfragments[lhs_native_idx] = Scaffold(s);\n\t\t\t\t\t\t\treplacements[c_native_idx] = lhs_native_idx;\n\t\t\t\t\t\t\t//fragments[c_native_idx] = Scaffold();\n\t\t\t\t\t\t\t//curr_conflicts = c_conflicts;\n\t\t\t\t\t\t\tfragments[c_native_idx].clear_hits();\n\t\t\t\t\t\t\t///lhs = c;\n\t\t\t\t\t\t\t//advanced_curr = true;\n\t\t\t\t\t\t\twill_perform_collapse = true;\n\t\t\t\t\t\t\tnum_merges++;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!Scaffold::compatible(lhs_scaff, c_scaff))\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tvector<int> c_conflicts;\n\t\t\t\t\t\t// Find c's conflicts\n\t\t\t\t\t\t\n\t\t\t\t\t\t// If c fails to overlap lhs's conflicts, or if it's\n\t\t\t\t\t\t// compatible with any of them, they aren't equivalent\n\t\t\t\t\t\tbool not_equivalent = false;\n\t\t\t\t\t\tfor (size_t j = 0; j < curr_conflicts.size(); ++j)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!Scaffold::overlap_in_genome(fragments[curr_conflicts[j]], c_scaff, 0) ||\n\t\t\t\t\t\t\t\t Scaffold::compatible(fragments[curr_conflicts[j]], c_scaff))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tnot_equivalent = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (not_equivalent)\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\n\t\t\t\t\t\t// If we get here, then c disagrees with at least all \n\t\t\t\t\t\t// the guys lhs does.\n\t\t\t\t\t\n\t\t\t\t\t\t// Now check that c doesn't have any additional conflicts\n\t\t\t\t\t\t// of it's own\n\t\t\t\t\t\tfor (size_t i = lhs_native_idx + 1; i < fragments.size(); ++i)\n\t\t\t\t\t\t{\n                            if (replacements[i] == i)\n                            {\n                                if (Scaffold::overlap_in_genome(fragments[i], lhs_scaff, 0))\n                                {\n                                    if (Scaffold::overlap_in_genome(fragments[i], c_scaff, 0))\n                                    {\n                                        if (!Scaffold::compatible(fragments[i], c_scaff))\n                                        {\n                                            //c_conflicts.push_back(i);\n                                            if (!binary_search(curr_conflicts.begin(), curr_conflicts.end(), i))\n                                            {\n                                                not_equivalent = true;\n                                                break;\n                                            }\n                                        }\n                                    }\n                                }\n                                else\n                                {\n                                    break;\n                                }\n                            }\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (not_equivalent)\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\n\t\t\t\t\t\t// merge\n\t\t\t\t\t\tif (num_merges % 100 == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tverbose_msg(\"%s\\tCollapsing frag # %d\\n\", \n\t\t\t\t\t\t\t\t\tbundle_label->c_str(), \n\t\t\t\t\t\t\t\t\tnum_merges);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tvector<Scaffold> s;\n\t\t\t\t\t\ts.push_back(c_scaff);\n\t\t\t\t\t\ts.push_back(lhs_scaff);\n\t\t\t\t\t\tfragments[lhs_native_idx] = Scaffold(s);\n\t\t\t\t\t\treplacements[c_native_idx] = lhs_native_idx;\n\t\t\t\t\t\t//fragments[c_native_idx] = Scaffold();\n\t\t\t\t\t\tfragments[c_native_idx].clear_hits();\n\t\t\t\t\t\t//curr_conflicts = c_conflicts;\n\t\t\t\t\t\t//advanced_curr = true;\n\t\t\t\t\t\twill_perform_collapse = true;\n\t\t\t\t\t\tnum_merges++;\n\t\t\t\t\t\t//break;\n\t\t\t\t\t}\n\t\t\t\t\telse \n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t//if (!advanced_curr)\n\t\t\t{\n\t\t\t\t++curr_frag;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (will_perform_collapse == false)\n\t\t\treturn performed_collapse;\n\t\t\n\t\t\n        vector<Scaffold> replaced;\n        for (size_t i = 0; i < fragments.size(); ++i)\n        {\n            if (replacements[i] == i)\n            {\n                replaced.push_back(fragments[i]);\n            }\n        }\n        \n        fragments = replaced;\n        sort(fragments.begin(), fragments.end(), scaff_lt_rt);\n\t\tperformed_collapse = true;\n\t}\n\treturn performed_collapse;\n}\n\nvoid compress_consitutive(vector<Scaffold>& hits)\n{\n    vector<bool> scaffold_mask;\n    \n    verbose_msg(\"%s\\tBuilding constitutivity mask\\n\", bundle_label->c_str()); \n    \n    scaffold_mask = vector<bool>(hits.size(), false);\n    add_non_constitutive_to_scaffold_mask(hits, scaffold_mask);\n    \n    vector<Scaffold> constitutive;\n    vector<Scaffold> non_constitutive;\n    \n    for (size_t i = 0; i < scaffold_mask.size(); ++i)\n    {\n        if (!scaffold_mask[i])\n            constitutive.push_back(hits[i]);\n        else\n            non_constitutive.push_back(hits[i]);\n    }\n    \n    size_t pre_compress = hits.size();\n    hits.clear();\n    if (!constitutive.empty())\n    {\n        Scaffold compressed = Scaffold(constitutive); \n        vector<Scaffold> completes; \n        compressed.fill_gaps(2 * olap_radius);\n        compressed.get_complete_subscaffolds(completes);\n        \n        hits.insert(hits.end(), completes.begin(), completes.end()); \n    }\n    \n    fill_unambiguous_unknowns(non_constitutive, hits);\n    \n    hits.insert(hits.end(), non_constitutive.begin(), non_constitutive.end());\n    sort(hits.begin(), hits.end(), scaff_lt);\n    \n    \n    size_t post_compress = hits.size();\n    size_t delta = pre_compress - post_compress;\n    double collapse_ratio = delta / (double) pre_compress; \n    verbose_msg(\"%s\\tCompressed %lu of %lu constitutive fragments (%lf percent)\\n\", \n            bundle_label->c_str(),\n            delta, \n            pre_compress, \n            collapse_ratio);\n}\n\n\nvoid compress_redundant(vector<Scaffold>& fragments)\n{\n    double last_size = -1;\n    //long leftmost = 9999999999;\n    long leftmost = LONG_MAX-1;\n    long rightmost = -1;\n    \n    for (size_t i = 0; i < fragments.size(); ++i)\n    {\n        leftmost = std::min((long)fragments[i].left(), leftmost);\n        rightmost = std::max((long)fragments[i].right(), rightmost);\n    }\n    \n    size_t pre_compress = fragments.size();\n    \n    while (true)\n    {\n        if (last_size == -1 || 0.9 * last_size > fragments.size())\n        {\n            last_size = fragments.size();\n            if (!collapse_equivalent_transfrags(fragments, 1))\n            {\n                break;\n            }\n        }\n        else\n        {\n            break;\n        }\n    }\n    \n    size_t post_compress = fragments.size();\n    size_t delta = pre_compress - post_compress;\n    double collapse_ratio = delta / (double) pre_compress; \n    verbose_msg(\"%s\\tCompressed %lu of %lu redundant fragments (%lf percent)\\n\", \n                bundle_label->c_str(),\n                delta, \n                pre_compress, \n                collapse_ratio);\n}\n\nvoid compress_fragments(vector<Scaffold>& fragments)\n{\n    verbose_msg(\"%s\\tPerforming preliminary containment collapse on %lu fragments\\n\", bundle_label->c_str(), fragments.size());\n    size_t pre_hit_collapse_size = fragments.size();\n    sort(fragments.begin(), fragments.end(), scaff_lt_rt);\n    \n\tcompress_consitutive(fragments);\n\t\n\tcompress_redundant(fragments);\n    \n    size_t post_hit_collapse_size = fragments.size();\n    verbose_msg(\"%s\\tIgnoring %lu strictly contained fragments\\n\", bundle_label->c_str(), pre_hit_collapse_size - post_hit_collapse_size);\n}\n\nvoid compress_overlap_dag_paths(DAG& bundle_dag,\n                                vector<Scaffold>& hits)\n{\n    HitsForNodeMap hits_for_node = get(vertex_name, bundle_dag);\n    \n    vector_property_map<size_t> path_for_scaff;\n    path_compress_visitor<vector_property_map<DAGNode>,\n    vector_property_map<size_t> > vis(path_for_scaff);\n    depth_first_search(bundle_dag,\n                       visitor(vis));\n    \n    vector<vector<Scaffold> > compressed_paths(hits.size()+1);\n\n    vector<Scaffold> new_scaffs;\n    \n    for (size_t i = 0; i < num_vertices(bundle_dag); ++i)\n    {\n        size_t path_id = path_for_scaff[i];\n        assert (path_id < compressed_paths.size());\n        const Scaffold* h = hits_for_node[i];\n        if (h)\n        {\n            compressed_paths[path_id].push_back(*h);\n        }\n    }\n    for (size_t i = 0; i < compressed_paths.size(); ++i)\n    {\n        if (!compressed_paths[i].empty())\n        {\n            Scaffold s(compressed_paths[i]);\n            verbose_msg(\"Path over %d-%d has %lu fragments in it\\n\", s.left(), s.right(), compressed_paths[i].size());\n            new_scaffs.push_back(s);\n        }\n    }\n    //hits = new_scaffs;\n\t\n    verbose_msg(\"%s\\tCompressed overlap graph from %lu to %lu fragments (%f percent)\\n\",\n            bundle_label->c_str(), \n            hits.size(), \n            new_scaffs.size(), \n            (hits.size() - new_scaffs.size())/(double)hits.size());\n\n    hits = new_scaffs;\n    sort(hits.begin(), hits.end(), scaff_lt);\n    create_overlap_dag(hits, bundle_dag);\n}\n\n"
  },
  {
    "path": "src/graph_optimize.h",
    "content": "#ifndef GRAPH_OPTIMIZE_H\n#define GRAPH_OPTIMIZE_H\n/*\n *  graph_optimize.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 6/1/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <vector>\n\n#include <boost/graph/depth_first_search.hpp>\n#include <boost/graph/visitors.hpp>\n\n#include \"bundles.h\"\n#include \"scaffold_graph.h\"\n#include \"scaffolds.h\"\n\nusing namespace std;\n\nusing namespace boost;\n\ntemplate < typename PredecessorMap, \n           typename PathIDMap > \nclass path_compress_visitor : public default_dfs_visitor \n{    \npublic:\n    path_compress_visitor(PathIDMap pm) : curr_path_id(0), path_map(pm) {}\n    \n    template < typename Vertex, typename Graph >\n    void initialize_vertex(Vertex u, const Graph & g) const\n    {\n        put(predecessor, u, u);\n        put(path_map, u, u);\n    }\n    \n    template < typename Vertex, typename Graph >\n    void discover_vertex(Vertex u, const Graph & g)\n    {\n        //fprintf(stderr, \"node %d has indegree %d, outdegree %d\\n\",u,in_degree(u, g),out_degree(u, g)); \n        if (in_degree(u, g) == 1)\n        {\n            \n            Vertex v = get(predecessor, u);\n            \n            assert(v != u);\n            \n            if (out_degree(v, g) == 1)\n            {\n                // compress into predecessor's path \n                typename PathIDMap::value_type path = get(path_map, v);\n                put(path_map, u, path);\n                //fprintf(stderr, \"\\told path for node %d = %d\\n\", u, path);\n                \n                return;\n            }\n        }\n        // start a new path\n        curr_path_id++;\n        put(path_map, u, curr_path_id);\n        //fprintf(stderr, \"\\tnew path for node %d = %d\\n\", u, curr_path_id);\n        \n    }\n    \n    template < typename Edge, typename Graph >\n    void tree_edge(Edge e, const Graph & g) const\n    {\n        put(predecessor, target(e, g), source(e, g));\n    }\n    \n    size_t last_path_id() const { return curr_path_id; }\n    \n    PredecessorMap predecessor;\n    \n    size_t curr_path_id;\n\tPathIDMap path_map;\n};\n\nvoid fill_gaps(vector<Scaffold>& scaffolds, int fill_size);\n\nvoid compress_fragments(vector<Scaffold>& hits);\n\nbool collapse_equivalent_transfrags(vector<Scaffold>& scaffolds, \n                                    uint32_t max_rounds = 0xFFFFFFFF);\n\nbool collapse_contained_transfrags(vector<Scaffold>& scaffolds, \n                                   uint32_t max_rounds = 0xFFFFFFFF);\n\nvoid compress_overlap_dag_paths(DAG& bundle_dag,\n                                vector<Scaffold>& hits);\n\n#endif\n"
  },
  {
    "path": "src/gtf_reads.cpp",
    "content": "/*\n *  reads_of_interest.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 11/29/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdlib.h>\n#include <getopt.h>\n#include <string>\n#include <numeric>\n#include <cfloat>\n#include <iostream>\n\n#include \"common.h\"\n#include \"hits.h\"\n#include \"bundles.h\"\n#include \"abundances.h\"\n\n#if ENABLE_THREADS\nconst char *short_options = \"\";\n#else\nconst char *short_options = \"\";\n#endif\n\nstatic struct option long_options[] = {\n{0, 0, 0, 0} // terminator\n};\n\nvoid print_usage()\n{\n\t//NOTE: SPACES ONLY, bozo\n    fprintf(stderr, \"Usage:   cuffdiff <transcripts.gtf> <sample_hits.sam>\\n\");\n}\n\nint parse_options(int argc, char** argv)\n{\n    int option_index = 0;\n    int next_option;\n    do {\n        next_option = getopt_long(argc, argv, short_options, long_options, &option_index);\n        switch (next_option) {\n\t\t\tcase -1:     /* Done with options. */\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tprint_usage();\n\t\t\t\treturn 1;\n        }\n    } while(next_option != -1);\n\t\n\treturn 0;\n}\n\nvoid driver(FILE* ref_gtf, FILE* sam_hit_file)\n{\n\tReadTable it;\n\tRefSequenceTable rt(true, false);\n\t\n\tvector<Scaffold> ref_mRNAs;\n\t\n\tSAMHitFactory hs(it, rt);\n    \n\tboost::shared_ptr<HitFactory> hit_factory(createSamHitFactory(hit_file_name, it, rt));\n\tBundleFactory& bundle_factory = *(new BundleFactory(hit_factory, bundle_mode));\n    \n    boost::crc_32_type ref_gtf_crc_result;\n    vector<boost::shared_ptr<Scaffold> > ref_mRNAs;\n    if (ref_gtf)\n    {\n        ::load_ref_rnas(ref_gtf, bundle_factory.ref_table(), ref_mRNAs, ref_gtf_crc_result, false, false);\n        bundle_factory.set_ref_rnas(ref_mRNAs);\n    }\n    rt.print_rec_ordering();\n    vector<boost::shared_ptr<Scaffold> > mask_rnas;\n    boost::crc_32_type mask_gtf_crc_result;\n    if (mask_gtf)\n    {\n        ::load_ref_rnas(mask_gtf, bundle_factory.ref_table(), mask_rnas, mask_gtf_crc_result, false, false);\n        bundle_factory.set_mask_rnas(mask_rnas);\n    }\n    \n\tlong num_fragments = 0;\n\tlong num_reads = 0;\n\t\n    const vector<MateHit>& hits = bundle.hits();\n    for (size_t i = 0; i < bundle.hits().size(); ++i)\n    {\n        bool compatible = false;\n        for (vector<Scaffold>::iterator ri = ref_mrnas.begin();\n             ri != ref_mrnas.end();\n             ++ri)\n        {\n            if (Scaffold::overlap_in_genome(*ri, hits[i], 0) &&\n                Scaffold::compatible(*ri,hits[i]))\n            {\n                compatible = true;\n                break;\n            }\n        }\n        if (!compatible)\n            continue;\n        \n        if (hits[i].left_alignment() || hits[i].right_alignment())\n            num_fragments++;\n        if (hits[i].left_alignment())\n        {\n            printf(\"%s\\n\", hits[i].left_alignment()->hitfile_rec().c_str());\n            num_reads++;\n        }\n        if (hits[i].right_alignment())\n        {\n            printf(\"%s\\n\", hits[i].right_alignment()->hitfile_rec().c_str());\n            num_reads++;\n        }\n    }\n\t\n\tfprintf(stderr, \"Extracted %ld fragments, %ld reads\\n\", num_fragments, num_reads); \n}\t\n\nint main(int argc, char** argv)\n{\n\tint parse_ret = parse_options(argc,argv);\n    if (parse_ret)\n        return parse_ret;\n\t\n\tif(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n\t\n    string ref_gtf_filename = argv[optind++];\n\n\tstring sam_hits_file_name = argv[optind++];\n\t// Open the approppriate files\n\tFILE* sam_hits_file = fopen(sam_hits_file_name.c_str(), \"r\");\n\tif (sam_hits_file == NULL)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open SAM file %s for reading\\n\",\n\t\t\t\tsam_hits_file_name.c_str());\n\t\texit(1);\n\t}\n\t\n\tFILE* ref_gtf = NULL;\n\tif (ref_gtf_filename != \"\")\n\t{\n\t\tref_gtf = fopen(ref_gtf_filename.c_str(), \"r\");\n\t\tif (!ref_gtf)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open GTF file %s for reading\\n\",\n\t\t\t\t\tref_gtf_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n\t\n    driver(ref_gtf, sam_hits_file);\n\t\n\treturn 0;\n}\n"
  },
  {
    "path": "src/gtf_to_sam.cpp",
    "content": "/*\n *  gtf_to_sam.cpp\n *  Cufflinks\n *\n *  Created by Cole Trapnell on 8/1/10.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <stdlib.h>\n#include <getopt.h>\n#include <string>\n\n#include <boost/version.hpp>\n#include <boost/graph/adjacency_list.hpp>\n#include <boost/graph/depth_first_search.hpp>\n#include <boost/graph/visitors.hpp>\n#include <boost/graph/graph_traits.hpp>\n#include <boost/graph/connected_components.hpp>\n\n#include \"common.h\"\n#include \"hits.h\"\n#include \"bundles.h\"\n\n#include \"scaffolds.h\"\n#include \"tokenize.h\"\n\nusing namespace boost;\nusing namespace std;\n\n#if ENABLE_THREADS\nconst char *short_options = \"r:F\";\n#else\nconst char *short_options = \"r:F\";\n#endif\n\nbool raw_fpkm = false;\n\nstatic struct option long_options[] = {\n{\"reference-seq\",\t\trequired_argument,\t\t 0,\t\t\t 'r'},\n{\"raw-fpkm\",            no_argument,             0,\t\t\t 'F'},\n{0, 0, 0, 0} // terminator\n};\n\nvoid print_usage()\n{\n\t//NOTE: SPACES ONLY, bozo\n\tfprintf(stderr, \"gtf_to_sam v%s\\n\", PACKAGE_VERSION);\n\tfprintf(stderr, \"linked against Boost version %d\\n\", BOOST_VERSION);\n\tfprintf(stderr, \"-----------------------------\\n\"); \n\tfprintf(stderr, \"Usage:   cufflinks [options] <transcripts1.gtf,...,transcriptsN.gtf> <out.sam>\\n\");\n\tfprintf(stderr, \"Options:\\n\\n\");\n\tfprintf(stderr, \"-r/--reference-seq\t\t\t  reference fasta file                     [ default:   NULL ]\\n\");\n    fprintf(stderr, \"-F/--raw-fpkm\t\t\t      use FPKM instead of isoform fraction                        \\n\");\n}\n\nint parse_options(int argc, char** argv)\n{\n    int option_index = 0;\n    int next_option;\n    do {\n        next_option = getopt_long(argc, argv, short_options, long_options, &option_index);\n        switch (next_option) {\n\t\t\tcase -1:     /* Done with options. */\n\t\t\t\tbreak;\n            case 'r':\n\t\t\t{\n\t\t\t\tfasta_dir = optarg;\n\t\t\t\tbreak;\n            }    \n            case 'F':\n\t\t\t{\n\t\t\t\traw_fpkm = true;\n\t\t\t\tbreak;\n            }   \n\t\t\tdefault:\n\t\t\t\tprint_usage();\n\t\t\t\treturn 1;\n        }\n    } while(next_option != -1);\n\n\treturn 0;\n}\n\nvoid print_scaff_as_sam(FILE* sam_out,\n                        const RefSequenceTable& rt, \n                        const Scaffold& scaff)\n{\n\tstring seq;\n\tstring quals;\n\n    seq = \"*\";\n    quals = \"*\";\t\n\n\tuint32_t sam_flag = 0;\n\tif (scaff.strand() == CUFF_REV)\n\t{\n\t\tsam_flag |= 0x0010; // BAM_FREVERSE\n//\t\tif (sequence)\n//\t\t{\n//\t\t\treverse_complement(seq);\n//\t\t\treverse(quals.begin(), quals.end());\n//\t\t}\n\t}\n\t\n\tuint32_t sam_pos = scaff.left() + 1;\n\tuint32_t map_quality = 255;\n\tchar cigar[8192];\n\tcigar[0] = 0;\n\tstring mate_ref_name = \"*\";\n\tuint32_t mate_pos = 0;\n\tuint32_t insert_size = 0;\n\t\n\tconst vector<AugmentedCuffOp>& ops = scaff.augmented_ops();\n\tfor (size_t c = 0; c < ops.size(); ++c)\n\t{\n\t\tchar ibuf[64];\n\t\tsprintf(ibuf, \"%d\", ops[c].genomic_length);\n\t\tswitch(ops[c].opcode)\n\t\t{\n\t\t\tcase CUFF_MATCH:\n\t\t\t\tstrcat(cigar, ibuf);\n\t\t\t\tstrcat(cigar, \"M\");\n\t\t\t\tbreak;\n\t\t\tcase CUFF_INTRON:\n\t\t\t\tstrcat(cigar, ibuf);\n\t\t\t\tstrcat(cigar, \"N\");\n\t\t\t\tbreak;\n\t\t\tdefault:\n                fprintf(stderr, \"Warning: Transcript %s contains an unconvertible alignment operator, skipping\\n\", scaff.annotated_trans_id().c_str());\n                return;\n                break;\n\t\t}\n\t}\n\t\n\t//string q = string(bh.read_len(), '!');\n\t//string s = string(bh.read_len(), 'N');\n\t\n    const char* ref_name = rt.get_name(scaff.ref_id());\n    if (!ref_name)\n    {\n        fprintf(stderr, \"Warning: Could not find contig name for ID %d, skipping\\n\", scaff.ref_id());\n        return;\n    }\n    \n    if (scaff.annotated_trans_id() == \"\")\n    {\n        fprintf(stderr, \"Warning: transcript_id attribute is empty, skipping\\n\");\n        return;\n    }\n    \n\tfprintf(sam_out,\n\t\t\t\"%s\\t%d\\t%s\\t%d\\t%d\\t%s\\t%s\\t%d\\t%d\\t%s\\t%s\",\n\t\t\tscaff.annotated_trans_id().c_str(),\n\t\t\tsam_flag,\n\t\t\tref_name,\n\t\t\tsam_pos,\n\t\t\tmap_quality,\n\t\t\tcigar,\n\t\t\tmate_ref_name.c_str(),\n\t\t\tmate_pos,\n\t\t\tinsert_size,\n\t\t\tseq.c_str(),\n\t\t\tquals.c_str());\n\t\n\tif (scaff.strand() != CUFF_STRAND_UNKNOWN)\n\t{\n\t\tfprintf(sam_out,\n\t\t\t\t\"\\tXS:A:%c\",\n\t\t\t\tscaff.strand() == CUFF_REV ? '-' : '+');\n\t}\n    \n    if (scaff.fpkm() != 0)\n\t{\n\t\tfprintf(sam_out,\n\t\t\t\t\"\\tZF:f:%f\",\n\t\t\t\tscaff.fpkm());\n\t}\n\t\n\tfprintf(sam_out, \"\\n\");\n    \n}\n\t\nvoid set_relative_fpkms(vector<boost::shared_ptr<Scaffold> >& ref_mRNAs)\n{\n    adjacency_list <vecS, vecS, undirectedS> G;\n\t\n\tfor (size_t i = 0; i < ref_mRNAs.size(); ++i)\n\t{\n\t\tadd_vertex(G);\n\t}\n\t\n    map<string, vector<int> > gene_id_idxs;\n    \n    for (size_t i = 0; i < ref_mRNAs.size(); ++i)\n    {\n        pair<map<string, vector<int> >::iterator, bool> inserted;\n        inserted = gene_id_idxs.insert(make_pair(ref_mRNAs[i]->annotated_gene_id(), vector<int>()));\n        inserted.first->second.push_back(i);\n    }\n    \n    for (map<string, vector<int> >::iterator itr = gene_id_idxs.begin();\n         itr != gene_id_idxs.end();\n         ++itr)\n    {\n        vector<int>& gene = itr->second;\n        for (size_t i = 0; i < gene.size(); ++i)\n        {\n            for (size_t j = 0; j < gene.size(); ++j)\n            {\n                {\n                    add_edge(gene[i], gene[j], G);\n                }\n            }\n        }\n    }\n    \n    std::vector<int> component(num_vertices(G));\n\tconnected_components(G, &component[0]);\n\t\n\tvector<vector<bool> > clusters(ref_mRNAs.size(), \n\t\t\t\t\t\t\t\t   vector<bool>(ref_mRNAs.size(), false));\n\t\n\t//vector<vector<size_t> > cluster_indices(three_prime_ends.size());\n    \n    vector<vector<boost::shared_ptr<Scaffold> > > grouped_scaffolds(ref_mRNAs.size());\n\tfor (size_t i = 0; i < ref_mRNAs.size(); ++i)\n\t{\n\t\tclusters[component[i]][i] = true;\n\t\tgrouped_scaffolds[component[i]].push_back(ref_mRNAs[i]);\n\t}\n    \n    for (size_t i = 0; i < grouped_scaffolds.size(); ++i)\n    {\n        vector<boost::shared_ptr<Scaffold> >& gene = grouped_scaffolds[i];\n        \n        double total_fpkm = 0.0;\n        BOOST_FOREACH(boost::shared_ptr<Scaffold> scaff, gene)\n        {\n            total_fpkm += scaff->fpkm();\n        }\n        if (total_fpkm > 0)\n        {\n            BOOST_FOREACH (boost::shared_ptr<Scaffold> scaff, gene)\n            {\n                scaff->fpkm(scaff->fpkm() / total_fpkm);\n            }\n        }\n    }\n}\n\nvoid driver(vector<FILE*> ref_gtf_files, FILE* sam_out)\n{\n\tReadTable it;\n\tRefSequenceTable rt(true, false);\n\t\n\tvector<vector<boost::shared_ptr<Scaffold> > > ref_mRNA_table;\n\tvector<pair<string, vector<double> > > sample_count_table;\n    \n    BOOST_FOREACH (FILE* ref_gtf, ref_gtf_files)\n    {\n        vector<boost::shared_ptr<Scaffold> > ref_mRNAs;\n        boost::crc_32_type ref_gtf_crc_result;\n        ::load_ref_rnas(ref_gtf, rt, ref_mRNAs, ref_gtf_crc_result, false, true);\n        ref_mRNA_table.push_back(ref_mRNAs);\n    }\n    \n    for (size_t j = 0; j < ref_mRNA_table.size(); ++j)\n    {\n        vector<boost::shared_ptr<Scaffold> > ref_mRNAs = ref_mRNA_table[j];\n        \n        if (!raw_fpkm)\n            set_relative_fpkms(ref_mRNAs);\n        \n        for (size_t i = 0; i < ref_mRNAs.size(); ++i)\n        {\n            print_scaff_as_sam(sam_out, rt, *ref_mRNA_table[j][i]);\n        }\n    }\n}\n\nint main(int argc, char** argv)\n{\n    init_library_table();\n    \n\tint parse_ret = parse_options(argc,argv);\n    if (parse_ret)\n        return parse_ret;\n\t\n    \n    if(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n\t\n    string ref_gtf_in_filenames = argv[optind++];\n    \n    if(optind >= argc)\n    {\n        print_usage();\n        return 1;\n    }\n\t\n    string sam_out_filename = argv[optind++];\n    \n    vector<string> ref_gtf_filenames;\n    tokenize(ref_gtf_in_filenames, \",\", ref_gtf_filenames);\n    \n    vector<FILE*> ref_gtf_files;\n    \n    BOOST_FOREACH (const string& ref_gtf_in_filename, ref_gtf_filenames)\n    {\n        FILE* ref_gtf = NULL;\n        if (ref_gtf_in_filename != \"\")\n        {\n            ref_gtf = fopen(ref_gtf_in_filename.c_str(), \"r\");\n            if (!ref_gtf)\n            {\n                fprintf(stderr, \"Error: cannot open GTF file %s for reading\\n\",\n                        ref_gtf_in_filename.c_str());\n                exit(1);\n            }\n            ref_gtf_files.push_back(ref_gtf);\n        }\n    }\n    \n    FILE* sam_out = NULL;\n\tif (sam_out_filename != \"\")\n\t{\n\t\tsam_out = fopen(sam_out_filename.c_str(), \"w\");\n\t\tif (!sam_out)\n\t\t{\n\t\t\tfprintf(stderr, \"Error: cannot open SAM file %s for writing\\n\",\n\t\t\t\t\tsam_out_filename.c_str());\n\t\t\texit(1);\n\t\t}\n\t}\n    \n    driver(ref_gtf_files, sam_out);\n\t\n\treturn 0;\n}\n"
  },
  {
    "path": "src/gtf_tracking.cpp",
    "content": "/*\n *  gtf_tracking.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 9/5/09.\n *  Copyright 2009 Geo Pertea. All rights reserved.\n *\n */\n\n#include \"gtf_tracking.h\"\n\nbool gtf_tracking_verbose = false;\nbool gtf_tracking_largeScale=false; //many input Cufflinks files processed at once by cuffcompare, discard exon attributes\n\nint GXConsensus::count=0;\n\nchar* getGSeqName(int gseq_id) {\n return GffObj::names->gseqs.getName(gseq_id);\n}\n\nint cmpByPtr(const pointer p1, const pointer p2) {\n  return (p1>p2) ? 1: ((p1==p2)? 0 : -1);\n  }\n\nbool betterRef(GffObj* a, GffObj* b) {\n if (a==NULL || b==NULL) return (a!=NULL);\n if (a->exons.Count()!=b->exons.Count()) return (a->exons.Count()>b->exons.Count());\n if (a->hasCDS() && !b->hasCDS())\n        return true;\n   else {\n     if (b->hasCDS() && !a->hasCDS()) return false;\n     return (a->covlen>b->covlen);\n     }\n }\n\nGffObj* is_RefDup(GffObj* m, GList<GffObj>& mrnas, int& dupidx) {\n //mrnas MUST be sorted by start coordinate\n  int ovlen=0;\n  dupidx=-1;\n  if (mrnas.Count()==0) return NULL;\n  int nidx=qsearch_mrnas(m->end, mrnas);\n  if (nidx==0) return NULL;\n  if (nidx==-1) nidx=mrnas.Count();//all can overlap\n  for (int i=nidx-1;i>=0;i--) {\n      GffObj& omrna=*mrnas[i];\n      if (m->start>omrna.end) {\n           if (m->start-omrna.start>GFF_MAX_EXON) break; //give up already\n           continue;\n           }\n      if (omrna.start>m->end) continue; //this should never be the case if nidx was found correctly\n      //locus overlap here:\n      if (tMatch(*m, omrna, ovlen, false, true)) {\n             dupidx=i;\n             return mrnas[i];\n             }\n      }\n  return NULL;\n}\n\n\nbool intronRedundant(GffObj& ti, GffObj&  tj, bool no5share=false) {\n //two transcripts are \"intron redundant\" iff one transcript's intron chain\n  // is a sub-chain of the other's\n int imax=ti.exons.Count()-1;\n int jmax=tj.exons.Count()-1;\n if (imax==0 || jmax==0) return false; //don't deal with single-exon transcripts here\n if (ti.exons[imax]->start<tj.exons[0]->end ||\n     tj.exons[jmax]->start<ti.exons[0]->end )\n         return false; //intron chains do not overlap at all\n \n uint eistart=0, eiend=0, ejstart=0, ejend=0; //exon boundaries\n int i=1; //exon idx to the right of the current intron of ti\n int j=1; //exon idx to the right of the current intron of tj\n //find the first intron overlap:\n while (i<=imax && j<=jmax) {\n    eistart=ti.exons[i-1]->end;\n    eiend=ti.exons[i]->start;\n    ejstart=tj.exons[j-1]->end;\n    ejend=tj.exons[j]->start;\n    if (ejend<eistart) { j++; continue; }\n    if (eiend<ejstart) { i++; continue; }\n    //we found an intron overlap\n    break;\n    }\n if ((i>1 && j>1) || i>imax || j>jmax) {\n     return false; //either no intron overlaps found at all\n                  //or it's not the first intron for at least one of the transcripts\n     }\n if (eistart!=ejstart || eiend!=ejend) return false; //not an exact intron match\n //we have the first matching intron on the left\n\n if (j>i) {\n   //i==1, ti's start must not conflict with the previous intron of tj\n   if (ti.start<tj.exons[j-1]->start) return false;\n   //so i's first intron starts AFTER j's first intron\n   // then j must contain i, so i's last intron must end with or before j's last intron\n   if (ti.exons[imax]->start>tj.exons[jmax]->start) return false;\n      //comment out the line above if you just want \"intron compatibility\" (i.e. extension of intron chains )\n   }\n  else if (i>j) {\n   //j==1, tj's start must not conflict with the previous intron of ti\n   if (tj.start<ti.exons[i-1]->start) return false;\n   //so j's intron chain starts AFTER i's\n   // then i must contain j, so j's last intron must end with or before j's last intron\n   if (tj.exons[jmax]->start>ti.exons[imax]->start) return false;\n      //comment out the line above for just \"intronCompatible()\" check\n   }\n //now check if the rest of the introns overlap, in the same sequence\n int i_start=i; //first (leftmost) matching intron of ti (1-based index)\n int j_start=j; //first (leftmost) matching intron of tj\n i++;\n j++;\n while (i<=imax && j<=jmax) {\n  if (ti.exons[i-1]->end!=tj.exons[j-1]->end ||\n      ti.exons[i]->start!=tj.exons[j]->start) return false;\n  i++;\n  j++;\n  }\n i--;\n j--;\n if (i==imax && j<jmax) {\n   // tj has more introns to the right, check if ti's end doesn't conflict with the current tj exon boundary\n   if (ti.end>tj.exons[j]->end) return false;\n   }\n else if (j==jmax && i<imax) {\n   if (tj.end>ti.exons[i]->end) return false;\n   }\n if (no5share && imax!=jmax) {\n\t //if they share the 5' intron, they are NOT to be considered redundant\n\t if (ti.strand=='+') {\n\t\t\t if (i_start==1 && j_start==1) return false;\n\t }\n\t else { //reverse strand\n\t\t if (i==imax && j==jmax) return false;\n\t }\n }\n return true; //they are intron-redundant\n}\n\nbool t_contains(GffObj& a, GffObj& b) {\n //returns true if b's intron chain (or single exon) is included in a\n if (b.exons.Count()>=a.exons.Count()) return false;\n if (b.exons.Count()==1) {\n    //check if b is contained in any of a's exons:\n    for (int i=0;i<a.exons.Count();i++) {\n       if (b.start>=a.exons[i]->start && b.end<=a.exons[i]->end) return true;\n       }\n    return false;\n    }\n if (intronRedundant(a,b)) {\n    //intronRedudant allows b's initial/terminal exons to extend beyond a's boundaries\n    //but we don't allow this kind of behavior here\n    return (b.start>=a.start && b.end<=a.end);\n    }\n  else return false;\n }\n\nint is_Redundant(GffObj*m, GList<GffObj>* mrnas, bool no5share=false) {\n //first locate the list index of the mrna starting just ABOVE\n //the end of this mrna\n if (mrnas->Count()==0) return -1;\n int nidx=qsearch_mrnas(m->end, *mrnas);\n if (nidx==0) return -1;\n if (nidx==-1) nidx=mrnas->Count();//all can overlap\n for (int i=nidx-1;i>=0;i--) {\n     GffObj& omrna=*mrnas->Get(i);\n     if (m->start>omrna.end) {\n          if (m->start-omrna.start>GFF_MAX_EXON) break; //give up already\n          continue;\n          }\n     if (omrna.start>m->end) continue; //this should never be the case if nidx was found correctly\n     \n     if (intronRedundant(*m, omrna, no5share)) return i;\n     }\n return -1;\n}\n\nbool t_dominates(GffObj* a, GffObj* b) {\n // for redundant / intron compatible transfrags:\n // returns true if a \"dominates\" b, i.e. a has more exons or is longer\n if (a->exons.Count()==b->exons.Count())\n         return (a->covlen>b->covlen);\n    else return (a->exons.Count()>b->exons.Count());\n}\n\nbool betterDupRef(GffObj* a, GffObj* b) {\n  if (a->exons.Count()!=b->exons.Count())\n    return (a->exons.Count()>b->exons.Count());\n  if (a->hasCDS()!=b->hasCDS())\n     return (a->hasCDS()>b->hasCDS());\n   //for annotation purposes, it's more important to keep the \n   //longer transcript, instead of the one that was loaded first\n  if (a->covlen != b->covlen)\n         return (a->covlen > b->covlen);\n    else return (a->track_id < b->track_id);\n}\n\nint parse_mRNAs(GfList& mrnas,\n\t\t\t\t GList<GSeqData>& glstdata,\n\t\t\t\t bool is_ref_set,\n\t\t\t\t int check_for_dups,\n\t\t\t\t int qfidx, bool only_multiexon) {\n\tint tredundant=0; //redundant transcripts discarded\n\tint total_kept=0;\n\tint total_seen=mrnas.Count();\n\tfor (int k=0;k<mrnas.Count();k++) {\n\t\tGffObj* m=mrnas[k];\n\t\tint i=-1;\n\t\tGSeqData f(m->gseq_id);\n\t\tGSeqData* gdata=NULL;\n\t\tuint tlen=m->len();\n\t\tif (m->hasErrors() || (tlen+500>GFF_MAX_LOCUS)) { //should probably report these in a file too..\n\t\t\tif (gtf_tracking_verbose) \n\t\t\t      GMessage(\"Warning: transcript %s discarded (structural errors found, length=%d).\\n\", m->getID(), tlen);\n\t\t\tcontinue;\n\t\t\t}\n\t\tif (only_multiexon && m->exons.Count()<2) {\n\t\t\tcontinue;\n\t\t\t}\n\t\t//GStr feature(m->getFeatureName());\n\t\t//feature.lower();\n\t\t//bool gene_or_locus=(feature.endsWith(\"gene\") ||feature.index(\"loc\")>=0);\n\t\t//if (m->exons.Count()==0 && gene_or_locus) {\n\t\tif (m->isDiscarded()) {\n\t\t\t//discard generic \"gene\" or \"locus\" features with no other detailed subfeatures\n\t\t\tif (!is_ref_set && gtf_tracking_verbose)\n\t\t\t   GMessage(\"Warning: discarding non-transfrag (GFF generic gene/locus container?) %s\\n\",m->getID());\n\t\t\tcontinue;\n\t\t\t}\n\n\t\tif (m->exons.Count()==0) {\n\t\t\t\tif (gtf_tracking_verbose && !is_ref_set)\n\t\t\t\t GMessage(\"Warning: %s %s found without exon segments (adding default exon).\\n\",m->getFeatureName(), m->getID());\n\t\t\t\tm->addExon(m->start,m->end);\n\t\t\t\t}\n\t\tif (glstdata.Found(&f,i)) gdata=glstdata[i];\n\t\telse {\n\t\t\tgdata=new GSeqData(m->gseq_id);\n\t\t\tglstdata.Add(gdata);\n\t\t\t}\n\t\t\n\t\tdouble fpkm=0;\n\t\tdouble cov=0;\n\t\tdouble conf_hi=0;\n\t\tdouble conf_lo=0;\n\n\t\tGList<GffObj>* target_mrnas=NULL;\n\t\tif (is_ref_set) { //-- ref transcripts\n\t\t   if (m->strand=='.') {\n\t\t     //unknown strand - discard from reference set (!)\n\t\t     continue;\n\t\t     }\n\t\t   total_kept++;\n\t\t   target_mrnas=(m->strand=='+') ? &(gdata->mrnas_f) : &(gdata->mrnas_r);\n\t\t   if (check_for_dups) {\n\t\t     //check all gdata->mrnas_r (ref_data) for duplicate ref transcripts\n\t\t     int rpidx=-1;\n\t\t     GffObj* rp= is_RefDup(m, *target_mrnas, rpidx);\n\t\t     if (rp!=NULL) { //duplicate found\n\t\t      //discard one of them\n\t\t      //but let's keep the gene_name if present\n\t\t      //DEBUG:\n\t\t      //GMessage(\"Ref duplicates: %s = %s\\n\", rp->getID(), m->getID());\n\t\t      tredundant++;\n\t\t      total_kept--;\n\t\t      if (betterDupRef(rp, m)) {\n\t\t           if (rp->getGeneName()==NULL && m->getGeneName()!=NULL) {\n\t\t                  rp->setGeneName(m->getGeneName());\n\t\t                  }\n\t\t           continue;\n\t\t           }\n\t\t         else {\n\t\t           if (m->getGeneName()==NULL && rp->getGeneName()!=NULL) {\n\t\t                  m->setGeneName(rp->getGeneName());\n\t\t                  }\n\t\t           ((CTData*)(rp->uptr))->mrna=NULL;\n\t\t           rp->isUsed(false);\n\t\t           target_mrnas->Forget(rpidx);\n\t\t           target_mrnas->Delete(rpidx);\n\t\t           }\n\t\t       }\n\t\t     } //check for duplicate ref transcripts\n\t\t   } //ref transcripts\n\t\telse { //-- query transfrags\n\t\t   if (m->strand=='+') { target_mrnas = &(gdata->mrnas_f); }\n\t\t     else if (m->strand=='-') { target_mrnas=&(gdata->mrnas_r); }\n\t\t        else { m->strand='.'; target_mrnas=&(gdata->umrnas); }\n\t\t   total_kept++;\n\t\t   if (check_for_dups) { //check for redundancy\n\t\t     // check if there is a redundancy between this and another already loaded Cufflinks transcript\n\t\t     int cidx =  is_Redundant(m, target_mrnas, (check_for_dups>1));\n\t\t     if (cidx>=0) {\n\t\t        //always discard the redundant transcript with the fewer exons OR shorter\n\t\t\t     tredundant++;\n\t\t         total_kept--;\n\t\t    \t if (t_dominates(target_mrnas->Get(cidx),m)) {\n\t\t            //new transcript is shorter, discard it\n\t\t        \tif (gtf_tracking_verbose) {\n\t\t        \t\tGMessage(\" transfrag %s discarded (made redundant by %s)\\n\", m->getID(), target_mrnas->Get(cidx)->getID());\n\t\t        \t}\n\t\t            continue;\n\t\t        }\n\t\t        else {\n\t\t            //discard the older transfrag\n\t\t        \tif (gtf_tracking_verbose) {\n\t\t        \t\tGMessage(\" transfrag %s discarded (made redundant by %s)\\n\", target_mrnas->Get(cidx)->getID(), m->getID());\n\t\t        \t}\n\t\t            ((CTData*)(target_mrnas->Get(cidx)->uptr))->mrna=NULL;\n\t\t            target_mrnas->Get(cidx)->isUsed(false);\n\t\t            target_mrnas->Forget(cidx);\n\t\t            target_mrnas->Delete(cidx);\n\t\t            //the uptr (CTData) pointer will still be kept in gdata->ctdata and deallocated eventually\n\t\t        }\n\t\t     }\n\t\t   }// redundant transfrag check\n\t\t   if (m->gscore==0.0)   \n\t\t     m->gscore=m->exons[0]->score; //Cufflinks exon score = isoform abundance\n\t\t   //const char* expr = (gtf_tracking_largeScale) ? m->getAttr(\"FPKM\") : m->exons[0]->getAttr(m->names,\"FPKM\");\n\t\t   const char* expr = m->getAttr(\"FPKM\");\n\t\t   if (expr!=NULL) {\n\t\t       if (expr[0]=='\"') expr++;\n\t\t       fpkm=strtod(expr, NULL);\n\t\t       } else { //backward compatibility: read RPKM if FPKM not found\n\t\t       //expr=(gtf_tracking_largeScale) ? m->getAttr(\"RPKM\") : m->exons[0]->getAttr(m->names,\"RPKM\");\n\t\t       expr=m->getAttr(\"RPKM\");\n\t\t       if (expr!=NULL) {\n\t\t           if (expr[0]=='\"') expr++;\n\t\t           fpkm=strtod(expr, NULL);\n\t\t           }\n\t\t       }\n\t\t   //const char* scov=(gtf_tracking_largeScale) ? m->getAttr(\"cov\") : m->exons[0]->getAttr(m->names,\"cov\");\n\t\t   const char* scov=m->getAttr(\"cov\");\n\t\t   if (scov!=NULL) {\n\t\t       if (scov[0]=='\"') scov++; \n\t\t       cov=strtod(scov, NULL);\n\t\t       }\n\t\t   //const char* sconf_hi=(gtf_tracking_largeScale) ? m->getAttr(\"conf_hi\") : m->exons[0]->getAttr(m->names,\"conf_hi\");\n\t\t   const char* sconf_hi=m->getAttr(\"conf_hi\");\n\t\t   if (sconf_hi!=NULL){\n\t\t       if (sconf_hi[0]=='\"') sconf_hi++;\n\t\t       conf_hi=strtod(sconf_hi, NULL);\n\t\t       }\n\t\t   //const char* sconf_lo=(gtf_tracking_largeScale) ? m->getAttr(\"conf_lo\") : m->exons[0]->getAttr(m->names,\"conf_lo\");\n\t\t   const char* sconf_lo=m->getAttr(\"conf_lo\");\n\t\t   if (sconf_lo!=NULL) {\n\t\t       if (sconf_lo[0]=='\"') sconf_lo++;\n\t\t       conf_lo=strtod(sconf_lo, NULL);\n\t\t       }\n\t\t   } //Cufflinks transfrags\n\t\ttarget_mrnas->Add(m);\n\t\tm->isUsed(true);\n\t\tCTData* mdata=new CTData(m);\n\t\tmdata->qset=qfidx;\n\t\tgdata->tdata.Add(mdata);\n\t\tif (!is_ref_set) {\n\t\t// Cufflinks - attributes parsing\n\t\t   mdata->FPKM=fpkm;\n\t\t   mdata->cov=cov;\n\t\t   mdata->conf_hi=conf_hi;\n\t\t   mdata->conf_lo=conf_lo;\n\t\t   }\n\t}//for each mrna read\n\tif (gtf_tracking_verbose) {\n\t\tif (is_ref_set)\n       GMessage(\" Kept %d ref transcripts out of %d\\n\", total_kept, total_seen);\n\t\telse\n\t   GMessage(\" Kept %d transfrags out of %d\\n\", total_kept, total_seen);\n\t}\n //if (mrna_deleted>0)\n //  mrnas.Pack();\n \n //return (is_ref_set ? refdiscarded : tredundant);\n\treturn tredundant;\n}\n\nbool singleExonTMatch(GffObj& m, GffObj& r, int& ovlen) {\n //if (m.exons.Count()>1 || r.exons.Count()>1..)\n GSeg mseg(m.start, m.end);\n ovlen=mseg.overlapLen(r.start,r.end);\n int lmax=GMAX(r.covlen, m.covlen);\n return ((ovlen >= lmax*0.8) // fuzz matching for single-exon transcripts: 80% of the longer one\n             || (ovlen >= r.covlen*0.9)); // fuzzy reverse-containment - the reference transcript is shorter\n}\n\nbool tMatch(GffObj& a, GffObj& b, int& ovlen, bool fuzzunspl, bool contain_only) {\n\t//strict intron chain match, or single-exon match\n\tint imax=a.exons.Count()-1;\n\tint jmax=b.exons.Count()-1;\n\tovlen=0;\n\tif (imax!=jmax) return false; //different number of exons\n\tif (imax==0) { //single-exon mRNAs\n\t\tif (contain_only) {\n\t\t   return ((a.start>=b.start && a.end<=b.end) || \n\t\t           (b.start>=a.start && b.end<=a.end));\n\t\t}\n\t\tif (fuzzunspl) {\n\t\t\t//fuzz match for single-exon transfrags: \n\t\t\t// it's a match if they overlap at least 80% of longest one\n\t\t\t//ovlen=a.exons[0]->overlapLen(b.exons[0]);\n\t\t\t//int maxlen=GMAX(a.covlen,b.covlen);\n\t\t\t//return (ovlen>=maxlen*0.8);\n\t\t\treturn (singleExonTMatch(a,b,ovlen));\n\t\t}\n\t  else {\n\t\t\t//only exact match\n\t\t\tovlen=a.covlen;\n\t\t\treturn (a.exons[0]->start==b.exons[0]->start &&\n\t\t\t\t\ta.exons[0]->end==b.exons[0]->end);\n\t\t}\n\t}\n\tif ( a.exons[imax]->start<b.exons[0]->end ||\n\t\tb.exons[jmax]->start<a.exons[0]->end )\n\t\treturn false; //intron chains do not overlap at all\n\t//check intron overlaps\n\tovlen=a.exons[0]->end-(GMAX(a.start,b.start))+1;\n\tovlen+=(GMIN(a.end,b.end))-a.exons.Last()->start;\n\tfor (int i=1;i<=imax;i++) {\n\t\tif (i<imax) ovlen+=a.exons[i]->len();\n\t\tif ((a.exons[i-1]->end!=b.exons[i-1]->end) ||\n\t\t\t(a.exons[i]->start!=b.exons[i]->start)) {\n\t\t\treturn false; //intron mismatch\n\t\t}\n\t}\n\tif (contain_only) \n\t\t     return ((a.start>=b.start && a.end<=b.end) || \n\t\t           (b.start>=a.start && b.end<=a.end));\n\t\telse return true;\n}\n\n\nvoid cluster_mRNAs(GList<GffObj> & mrnas, GList<GLocus> & loci, int qfidx) {\n\t//mrnas sorted by start coordinate\n\t//and so are the loci\n\t//int rdisc=0;\n\t\tfor (int t=0;t<mrnas.Count();t++) {\n\t\tGArray<int> mrgloci(false);\n\t\tGffObj* mrna=mrnas[t];\n\t\tint lfound=0; //count of parent loci\n\t\t/*for (int l=0;l<loci.Count();l++) {\n\t\t\tif (loci[l]->end<mrna->exons.First()->start) continue;\n\t\t\tif (loci[l]->start>mrna->exons.Last()->end) break; */\n\t\t for (int l=loci.Count()-1;l>=0;l--) {\n\t\t   if (loci[l]->end<mrna->exons.First()->start) {\n\t\t       if (mrna->exons.First()->start-loci[l]->start > GFF_MAX_LOCUS) break;\n\t\t       continue;\n\t\t       }\n\t\t   if (loci[l]->start>mrna->exons.Last()->end) continue;\n\t\t\t//here we have mrna overlapping loci[l]\n\t\t\tif (loci[l]->add_mRNA(mrna)) {\n\t\t\t\t//a parent locus was found\n\t\t\t\tlfound++;\n\t\t\t\tmrgloci.Add(l); //locus indices added here, in decreasing order\n\t\t\t}\n\t\t}//loci loop\n\t\t//if (lfound<0) continue; //mrna was a ref duplicate, skip it\n\t\tif (lfound==0) {\n\t\t\t//create a locus with only this mRNA\n \t\t\t loci.Add(new GLocus(mrna, qfidx));\n\t\t    }\n\t\t else if (lfound>1) {\n\t\t\t//more than one locus found parenting this mRNA, merge loci\n\t\t     lfound--;\n\t\t\t for (int l=0;l<lfound;l++) {\n\t\t\t\t  int mlidx=mrgloci[l]; //largest indices first, so it's safe to remove\n\t\t\t\t  loci[mrgloci[lfound]]->addMerge(*loci[mlidx], mrna);\n\t\t\t\t  loci.Delete(mlidx);\n\t\t\t    }\n\t\t    }\n\t}//mrnas loop\n\t//if (rdisc>0) mrnas.Pack();\n\t//return rdisc;\n}\n\nint fix_umrnas(GSeqData& seqdata, GSeqData* rdata, FILE* fdis=NULL) {\n\t//attempt to find the strand for seqdata.umrnas\n\t//based on a) overlaps with oriented reference mRNAs if present\n\t//         b) overlaps with oriented mRNAs from the same input set\n\t//int incount=seqdata.umrnas.Count();\n\tif (rdata!=NULL) { //we have reference mrnas\n\t\tfor (int i=0;i<rdata->mrnas_f.Count();i++) {\n\t\t\tfor (int j=0;j<seqdata.umrnas.Count();j++) {\n\t\t\t\tif (rdata->mrnas_f[i]->gseq_id!=seqdata.umrnas[j]->gseq_id) continue;\n\t\t\t\tif (seqdata.umrnas[j]->strand!='.') continue;\n\t\t\t\tuint ustart=seqdata.umrnas[j]->exons.First()->start;\n\t\t\t\tuint uend=seqdata.umrnas[j]->exons.Last()->end;\n\t\t\t\tuint rstart=rdata->mrnas_f[i]->exons.First()->start;\n\t\t\t\tuint rend=rdata->mrnas_f[i]->exons.Last()->end;\n\t\t\t\tif (ustart>rend) break;\n\t\t\t\tif (rstart>uend) continue;\n\t\t\t\tif (rdata->mrnas_f[i]->exonOverlap(ustart,uend)) {\n\t\t\t\t\tseqdata.umrnas[j]->strand='+';\n\t\t\t\t}\n\t\t\t\telse { //within intron\n\t\t\t\t\t//if (seqdata.umrnas[j]->ulink==NULL ||\n\t\t\t\t\t//     seqdata.umrnas[j]->ulink->covlen<rdata->mrnas_f[i]->covlen) {\n\t\t\t\t\tCTData* mdata=(CTData*)seqdata.umrnas[j]->uptr;\n\t\t\t\t\tmdata->addOvl('i',rdata->mrnas_f[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (int i=0;i<rdata->mrnas_r.Count();i++) {\n\t\t\tfor (int j=0;j<seqdata.umrnas.Count();j++) {\n\t\t\t\tif (seqdata.umrnas[j]->strand!='.') continue;\n\t\t\t\tuint ustart=seqdata.umrnas[j]->exons.First()->start;\n\t\t\t\tuint uend=seqdata.umrnas[j]->exons.Last()->end;\n\t\t\t\tuint rstart=rdata->mrnas_r[i]->exons.First()->start;\n\t\t\t\tuint rend=rdata->mrnas_r[i]->exons.Last()->end;\n\t\t\t\tif (ustart>rend) break;\n\t\t\t\tif (rstart>uend) continue;\n\t\t\t\tif (rdata->mrnas_r[i]->exonOverlap(ustart,uend)) {\n\t\t\t\t\tseqdata.umrnas[j]->strand='-';\n\t\t\t\t}\n\t\t\t\telse { //within intron\n\t\t\t\t\tCTData* mdata=(CTData*)seqdata.umrnas[j]->uptr;\n\t\t\t\t\tmdata->addOvl('i',rdata->mrnas_r[i]);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\t}//we have reference transcripts\n\t//---- now compare to other qry transcripts\n\tfor (int i=0;i<seqdata.mrnas_f.Count();i++) {\n\t\tfor (int j=0;j<seqdata.umrnas.Count();j++) {\n\t\t\tif (seqdata.umrnas[j]->strand!='.') continue;\n\t\t\tuint ustart=seqdata.umrnas[j]->exons.First()->start;\n\t\t\tuint uend=seqdata.umrnas[j]->exons.Last()->end;\n\t\t\tuint rstart=seqdata.mrnas_f[i]->exons.First()->start;\n\t\t\tuint rend=seqdata.mrnas_f[i]->exons.Last()->end;\n\t\t\tif (ustart>rend) break;\n\t\t\tif (rstart>uend) continue;\n\t\t\tif (seqdata.mrnas_f[i]->exonOverlap(ustart,uend)) {\n\t\t\t\tseqdata.umrnas[j]->strand='+';\n\t\t\t}\n\t\t}\n\t}\n\tfor (int i=0;i<seqdata.mrnas_r.Count();i++) {\n\t\tfor (int j=0;j<seqdata.umrnas.Count();j++) {\n\t\t\tif (seqdata.umrnas[j]->strand!='.') continue;\n\t\t\tuint ustart=seqdata.umrnas[j]->exons.First()->start;\n\t\t\tuint uend=seqdata.umrnas[j]->exons.Last()->end;\n\t\t\tuint rstart=seqdata.mrnas_r[i]->exons.First()->start;\n\t\t\tuint rend=seqdata.mrnas_r[i]->exons.Last()->end;\n\t\t\tif (ustart>rend) break;\n\t\t\tif (rstart>uend) continue;\n\t\t\t//overlap\n\t\t\tif (seqdata.mrnas_r[i]->exonOverlap(ustart,uend)) {\n\t\t\t\tseqdata.umrnas[j]->strand='-';\n\t\t\t}\n\t\t}\n    }\n\tint fcount=0;\n\tint fixed=0;\n\tfor (int i=0;i<seqdata.umrnas.Count();i++) {\n\t\tif (seqdata.umrnas[i]->strand=='+') {\n\t\t\tseqdata.mrnas_f.Add(seqdata.umrnas[i]);\n\t\t\tfixed++;\n\t\t\tseqdata.umrnas.Forget(i);\n\t\t}\n\t\telse if (seqdata.umrnas[i]->strand=='-') {\n\t\t    seqdata.mrnas_r.Add(seqdata.umrnas[i]);\n\t\t    seqdata.umrnas.Forget(i);\n\t\t    fixed++;\n\t\t}\n\t\telse {  //discard mRNAs not settled\n\t\t\t//seqdata.umrnas[i]->strand='.'; ?\n\t\t\tif (fdis!=NULL) {\n\t\t\t\tseqdata.umrnas[i]->printGtf(fdis);\n\t\t\t\t}\n\t\t\tfcount++;\n\t\t}\n\t}\n\n\tseqdata.umrnas.Pack();\n\t//if (gtf_tracking_verbose) {\n\t//\tGMessage(\" %d out of %d (%d left, %d) unoriented transfrags were assigned a strand based on overlaps.\\n\", fixed, incount, seqdata.umrnas.Count(), fcount);\n\t//}\n\treturn fixed;\n}\n\n//retrieve ref_data for a specific genomic sequence\nGSeqData* getRefData(int gid, GList<GSeqData>& ref_data) {\n\tint ri=-1;\n\tGSeqData f(gid);\n\tGSeqData* r=NULL;\n\tif (ref_data.Found(&f,ri))\n\t\tr=ref_data[ri];\n\treturn r;\n}\n\nvoid read_transcripts(FILE* f, GList<GSeqData>& seqdata, \n#ifdef CUFFLINKS\n  boost::crc_32_type& crc_result,\n#endif\n   bool keepAttrs) {\n\trewind(f);\n\tGffReader gffr(f, true); //loading only recognizable transcript features\n\tgffr.showWarnings(gtf_tracking_verbose);\n\n\t//          keepAttrs    mergeCloseExons   noExonAttrs\n\tgffr.readAll(keepAttrs,          true,        true);\n#ifdef CUFFLINKS\n     crc_result = gffr.current_crc_result();\n#endif\n\t//                               is_ref?    check_for_dups,\n\tparse_mRNAs(gffr.gflst, seqdata, false,       0);\n}\n\nint cmpGSeqByName(const pointer p1, const pointer p2) {\n return strcmp(((GSeqData*)p1)->gseq_name, ((GSeqData*)p2)->gseq_name);\n}\n\nvoid sort_GSeqs_byName(GList<GSeqData>& seqdata) {\n  seqdata.setSorted(&cmpGSeqByName);\n}\n\nvoid read_mRNAs(FILE* f, GList<GSeqData>& seqdata, GList<GSeqData>* ref_data,\n\t         int check_for_dups, int qfidx, const char* fname, bool only_multiexon) {\n\t//>>>>> read all transcripts/features from a GTF/GFF3 file\n\t//int imrna_counter=0;\n#ifdef HEAPROFILE\n    if (IsHeapProfilerRunning())\n      HeapProfilerDump(\"00\");\n#endif\n\tint loci_counter=0;\n\tif (ref_data==NULL) ref_data=&seqdata;\n\tbool isRefData=(&seqdata==ref_data);\n\t                          //(f, transcripts_only)\n\tGffReader* gffr=new GffReader(f, true); //load only transcript annotations\n\tgffr->showWarnings(gtf_tracking_verbose);\n\t//            keepAttrs   mergeCloseExons   noExonAttrs\n\tgffr->readAll(!isRefData,          true,        isRefData || gtf_tracking_largeScale);\n\t//so it will read exon attributes only for low number of Cufflinks files\n#ifdef HEAPROFILE\n    if (IsHeapProfilerRunning())\n      HeapProfilerDump(\"post_readAll\");\n#endif\n\n\tint d=parse_mRNAs(gffr->gflst, seqdata, isRefData, check_for_dups, qfidx,only_multiexon);\n#ifdef HEAPROFILE\n    if (IsHeapProfilerRunning())\n      HeapProfilerDump(\"post_parse_mRNAs\");\n#endif\n\tif (gtf_tracking_verbose && d>0) {\n\t  if (isRefData) GMessage(\" %d duplicate reference transcripts discarded.\\n\",d);\n\t            else GMessage(\" %d redundant cufflinks transfrags discarded.\\n\",d);\n\t  }\n\t//imrna_counter=gffr->mrnas.Count();\n\tdelete gffr; //free the extra memory and unused GffObjs\n#ifdef HEAPROFILE\n    if (IsHeapProfilerRunning())\n      HeapProfilerDump(\"post_del_gffr\");\n#endif\n\t\n\t//for each genomic sequence, cluster transcripts\n\tint oriented_by_overlap=0;\n\tint initial_unoriented=0;\n\tint final_unoriented=0;\n\tGStr bname(fname);\n\tGStr s;\n\tif (!bname.is_empty()) {\n\t\tint di=bname.rindex('.');\n\t\tif (di>0) bname.cut(di);\n\t\tint p=bname.rindex('/');\n\t\tif (p<0) p=bname.rindex('\\\\');\n\t\tif (p>=0) bname.remove(0,p);\n\t}\n\tFILE* fdis=NULL;\n\tFILE* frloci=NULL;\n\n\tfor (int g=0;g<seqdata.Count();g++) {\n\t\t//find the corresponding refseqdata with the same gseq_id\n\t\tint gseq_id=seqdata[g]->get_gseqid();\n\t\tif (!isRefData) { //cufflinks data, find corresponding ref data\n\t\t\tGSeqData* rdata=getRefData(gseq_id, *ref_data);\n\t\t\tinitial_unoriented+=seqdata[g]->umrnas.Count();\n\t\t\tif (seqdata[g]->umrnas.Count()>0) {\n\t\t\t    oriented_by_overlap+=fix_umrnas(*seqdata[g], rdata, fdis);\n\t\t\t    final_unoriented+=seqdata[g]->umrnas.Count();\n\t\t\t    }\n\t\t\t}\n\t\t//>>>>> group mRNAs into locus-clusters (based on exon overlap)\n\t\tcluster_mRNAs(seqdata[g]->mrnas_f, seqdata[g]->loci_f, qfidx);\n\t\tcluster_mRNAs(seqdata[g]->mrnas_r, seqdata[g]->loci_r, qfidx);\n\t\tif (!isRefData) {\n\t\t\tcluster_mRNAs(seqdata[g]->umrnas, seqdata[g]->nloci_u, qfidx);\n\t\t\t}\n\t\tloci_counter+=seqdata[g]->loci_f.Count();\n\t\tloci_counter+=seqdata[g]->loci_r.Count();\n//\t\tif (refData) {\n//\t\t\tif (frloci==NULL) {\n//\t\t\t\ts=bname;\n//\t\t\t\ts.append(\".loci.lst\");\n//\t\t\t\tfrloci=fopen(s.chars(), \"w\");\n//\t\t\t}\n//\t\t\twriteLoci(frloci, seqdata[g]->loci_f);\n//\t\t\twriteLoci(frloci, seqdata[g]->loci_r);\n//\t\t}//write ref loci\n\t}//for each genomic sequence\n\tif (fdis!=NULL) fclose(fdis);\n\tif (frloci!=NULL) fclose(frloci);\n\tif (initial_unoriented || final_unoriented) {\n\t  if (gtf_tracking_verbose) GMessage(\" Found %d transfrags with undetermined strand (%d out of initial %d were fixed by overlaps)\\n\",\n\t\t\t    final_unoriented, oriented_by_overlap, initial_unoriented);\n\t}\n\t//if (fdis!=NULL) remove(s.chars()); remove 0-length file\n#ifdef HEAPROFILE\n    if (IsHeapProfilerRunning())\n      HeapProfilerDump(\"post_cluster\");\n#endif\n}\n\nint qsearch_mrnas(uint x, GList<GffObj>& mrnas) {\n  //binary search\n  //do the simplest tests first:\n  if (mrnas[0]->start>x) return 0;\n  if (mrnas.Last()->start<x) return -1;\n  uint istart=0;\n  int i=0;\n  int idx=-1;\n  int maxh=mrnas.Count()-1;\n  int l=0;\n  int h = maxh;\n  while (l <= h) {\n     i = (l+h)>>1;\n     istart=mrnas[i]->start;\n     if (istart < x)  l = i + 1;\n          else {\n             if (istart == x) { //found matching coordinate here\n                  idx=i;\n                  while (idx<=maxh && mrnas[idx]->start==x) {\n                     idx++;\n                     }\n                  return (idx>maxh) ? -1 : idx;\n                  }\n             h = i - 1;\n             }\n     } //while\n idx = l;\n while (idx<=maxh && mrnas[idx]->start<=x) {\n    idx++;\n    }\n return (idx>maxh) ? -1 : idx;\n}\n\nint qsearch_loci(uint x, GList<GLocus>& loci) {\n // same as above, but for GSeg lists\n  //binary search\n  //do the simplest tests first:\n  if (loci[0]->start>x) return 0;\n  if (loci.Last()->start<x) return -1;\n  uint istart=0;\n  int i=0;\n  int idx=-1;\n  int maxh=loci.Count()-1;\n  int l=0;\n  int h = maxh;\n  while (l <= h) {\n     i = (l + h) >> 1;\n     istart=loci[i]->start;\n     if (istart < x) l=i+1;\n                else {\n                   if (istart == x) { //found matching coordinate here\n                        idx=i;\n                        while (idx<=maxh && loci[idx]->start==x) {\n                           idx++;\n                           }\n                        return (idx>maxh) ? -1 : idx;\n                        }\n                   h=i-1;\n                   }\n     } //while\n idx = l;\n while (idx<=maxh && loci[idx]->start<=x) {\n    idx++;\n    }\n return (idx>maxh) ? -1 : idx;\n}\n\n"
  },
  {
    "path": "src/gtf_tracking.h",
    "content": "#ifndef GTF_TRACKING_H\n#define GTF_TRACKING_H\n/*\n *  gtf_tracking.h\n *\n */\n\n#ifdef HEAPROFILE\n#include \"gperftools/heap-profiler.h\"\n#endif\n\n#include \"gff.h\"\n#include \"GFaSeqGet.h\"\n#include \"GFastaIndex.h\"\n#include \"GStr.h\"\n\n#define MAX_QFILES 500\n\nextern bool gtf_tracking_verbose;\n\nextern bool gtf_tracking_largeScale;\n//many input files, no accuracy stats are generated, no *.tmap\n// and exon attributes are discarded\n\nint cmpByPtr(const pointer p1, const pointer p2);\n\nbool t_contains(GffObj& a, GffObj& b); \n//returns true only IF b has fewer exons than a AND a \"contains\" b\n\nchar* getGSeqName(int gseq_id);\n\n//genomic fasta sequence handling\nclass GFastaHandler {\n public:\n  char* fastaPath;\n  GFastaIndex* faIdx;\n  char* getFastaFile(int gseq_id) {\n     if (fastaPath==NULL) return NULL;\n     GStr s(fastaPath);\n     s.trimR('/');\n     s.appendfmt(\"/%s\",getGSeqName(gseq_id));\n     GStr sbase(s);\n     if (!fileExists(s.chars())) s.append(\".fa\");\n     if (!fileExists(s.chars())) s.append(\"sta\");\n     if (fileExists(s.chars())) return Gstrdup(s.chars());\n         else {\n             GMessage(\"Warning: cannot find genomic sequence file %s{.fa,.fasta}\\n\",sbase.chars());\n             return NULL;\n             }\n     }\n     \n   GFastaHandler(const char* fpath=NULL) {\n     fastaPath=NULL;\n     faIdx=NULL;\n     if (fpath!=NULL && fpath[0]!=0) init(fpath);\n     }\n     \n   void init(const char* fpath) {\n     if (fpath==NULL || fpath[0]==0) return;\n     if (!fileExists(fpath))\n       GError(\"Error: file/directory %s does not exist!\\n\",fpath);\n     fastaPath=Gstrdup(fpath);\n     if (fastaPath!=NULL) {\n         if (fileExists(fastaPath)>1) { //exists and it's not a directory\n            GStr fainame(fastaPath);\n            //the .fai name might have been given directly\n            if (fainame.rindex(\".fai\")==fainame.length()-4) {\n               //.fai index file given directly\n               fastaPath[fainame.length()-4]=0;\n               if (!fileExists(fastaPath))\n                  GError(\"Error: cannot find fasta file for index %s !\\n\", fastaPath);\n               }\n              else fainame.append(\".fai\");\n            //fainame.append(\".fai\");\n            faIdx=new GFastaIndex(fastaPath,fainame.chars());\n            GStr fainamecwd(fainame);\n            int ip=-1;\n            if ((ip=fainamecwd.rindex('/'))>=0)\n               fainamecwd.cut(0,ip+1);\n            if (!faIdx->hasIndex()) { //could not load index\n               //try current directory\n                  if (fainame!=fainamecwd) {\n                    if (fileExists(fainamecwd.chars())>1) {\n                       faIdx->loadIndex(fainamecwd.chars());\n                       }\n                    }\n                  } //tried to load index\n            if (!faIdx->hasIndex()) {\n                 GMessage(\"No fasta index found for %s. Rebuilding, please wait..\\n\",fastaPath);\n                 faIdx->buildIndex();\n                 if (faIdx->getCount()==0) GError(\"Error: no fasta records found!\\n\");\n                 GMessage(\"Fasta index rebuilt.\\n\");\n                 FILE* fcreate=fopen(fainame.chars(), \"w\");\n                 if (fcreate==NULL) {\n                   GMessage(\"Warning: cannot create fasta index %s! (permissions?)\\n\", fainame.chars());\n                   if (fainame!=fainamecwd) fcreate=fopen(fainamecwd.chars(), \"w\");\n                   if (fcreate==NULL)\n                      GError(\"Error: cannot create fasta index %s!\\n\", fainamecwd.chars());\n                   }\n                 if (faIdx->storeIndex(fcreate)<faIdx->getCount())\n                     GMessage(\"Warning: error writing the index file!\\n\");\n                 } //index created and attempted to store it\n            } //multi-fasta\n         } //genomic sequence given\n     }\n   GFaSeqGet* fetch(int gseq_id, bool checkFasta=false) {\n     if (fastaPath==NULL) return NULL;\n     //genomic sequence given\n     GFaSeqGet* faseq=NULL;\n     if (faIdx!=NULL) { //fastaPath was the multi-fasta file name\n        char* gseqname=getGSeqName(gseq_id);\n        GFastaRec* farec=faIdx->getRecord(gseqname);\n        if (farec!=NULL) {\n             faseq=new GFaSeqGet(fastaPath,farec->seqlen, farec->fpos,\n                               farec->line_len, farec->line_blen);\n             faseq->loadall(); //just cache the whole sequence, it's faster\n             }\n        else {\n          GMessage(\"Warning: couldn't find fasta record for '%s'!\\n\",gseqname);\n          return NULL;\n          }\n        }\n     else //if (fileExists(fastaPath)==1)\n        {\n         char* sfile=getFastaFile(gseq_id);\n         if (sfile!=NULL) {\n            //if (gtf_tracking_verbose)\n            //   GMessage(\"Processing sequence from fasta file '%s'\\n\",sfile);\n            faseq=new GFaSeqGet(sfile,checkFasta);\n            faseq->loadall();\n            GFREE(sfile);\n            }\n         } //one fasta file per contig\n       return faseq;\n     }\n\n   ~GFastaHandler() {\n     GFREE(fastaPath);\n     delete faIdx;\n     }\n};\n\n\n\nbool betterRef(GffObj* a, GffObj* b); //for better CovLink reference ranking\n\nclass GLocus;\n\nclass COvLink {\npublic:\n\tstatic int coderank(char c) {\n\t\tswitch (c) {\n\t\t\tcase '=': return 0; //ichain match\n\t\t\tcase 'c': return 2; //containment (ichain fragment)\n\t\t\tcase 'j': return 4; // overlap with at least a junction match\n\t\t\tcase 'e': return 6; // single exon transfrag overlapping an intron of reference (possible pre-mRNA)\n\t\t\tcase 'o': return 8; // generic exon overlap\n\t\t\tcase 's': return 16; //\"shadow\" - an intron overlaps with a ref intron on the opposite strand\n\t\t\tcase 'x': return 18; // exon overlap on opposite strand (usually wrong strand mapping)\n\t\t\tcase 'i': return 20; // intra-intron\n\t\t\tcase 'p': return 90; //polymerase run\n\t\t\tcase 'r': return 92; //repeats\n\t\t\tcase 'u': return 94; //intergenic\n\t\t\tcase  0 : return 100;\n\t\t\tdefault: return 96;\n\t\t\t}\n\t}\n    char code;\n    int rank;\n    GffObj* mrna;\n    int ovlen;\n    COvLink(char c=0,GffObj* m=NULL, int ovl=0) {\n\t\tcode=c;\n\t\tmrna=m;\n\t\tovlen=ovl;\n\t\trank=coderank(c);\n\t}\n    bool operator<(COvLink& b) {\n\t\tif (rank==b.rank)\n\t\t\treturn (ovlen==b.ovlen)? betterRef(mrna, b.mrna) : (ovlen>b.ovlen);\n\t\telse return rank<b.rank;\n\t}\n    bool operator==(COvLink& b) {\n\t\treturn (rank==b.rank && mrna==b.mrna);\n\t}\n};\n\nclass GISeg: public GSeg {\n public:\n   GffObj* t; //pointer to the largest transcript with a segment this exact exon coordinates\n   GISeg(uint s=0,uint e=0, GffObj* ot=NULL):GSeg(s,e) { t=ot; }\n};\n\nclass GIArray:public GArray<GISeg> {\n  public:\n   GIArray(bool uniq=true):GArray<GISeg>(true,uniq) { }\n   int IAdd(GISeg* item) {\n     if (item==NULL) return -1;\n     int result=-1;\n     if (Found(*item, result)) {\n         if (fUnique) {\n           //cannot add a duplicate, return index of existing item\n           if (item->t!=NULL && fArray[result].t!=NULL &&\n                  item->t->covlen>fArray[result].t->covlen)\n               fArray[result].t=item->t;\n           return result;\n           }\n         }\n     //Found sets result to the position where the item should be\n     idxInsert(result, *item);\n     return result;\n     }\n\n};\n\nclass CEqList: public GList<GffObj> {\n  public:\n    GffObj* head;\n    CEqList():GList<GffObj>((GCompareProc*)cmpByPtr, (GFreeProc*)NULL, true) {\n      head=NULL;\n      }\n};\n\nclass CTData { //transcript associated data\npublic:\n\tGffObj* mrna; //owner transcript\n\tGLocus* locus;\n\tGList<COvLink> ovls; //overlaps with other transcripts (ref vs query)\n\t//-- just for ichain match tracking:\n\tGffObj* eqref; //ref transcript having an ichain match\n\tint qset; //qry set index (qfidx), -1 means reference dataset\n\t//GffObj* eqnext; //next GffObj in the linked list of matching transfrags\n\tbool eqhead;\n\tCEqList* eqlist; //keep track of matching transfrags\n\t//int eqdata; // flags for EQ list (is it a list head?)\n\t// Cufflinks specific data:\n\tdouble FPKM;\n\tdouble conf_hi;\n\tdouble conf_lo;\n\tdouble cov;\n\tchar classcode; //the best/final classcode\n\tCTData(GffObj* m=NULL, GLocus* l=NULL):ovls(true,true,true) {\n\t\tmrna=m;\n\t\tif (mrna!=NULL) mrna->uptr=this;\n\t\tlocus=l;\n\t\tclasscode=0;\n\t\teqref=NULL;\n\t\teqhead=false;\n\t\teqlist=NULL;\n\t\tqset=-2;\n\t\tFPKM=0;\n\t\tconf_lo=0;\n\t\tconf_hi=0;\n\t\tcov=0;\n\t}\n\n\t~CTData() {\n\t\tovls.Clear();\n\t\t//if ((eqdata & EQHEAD_TAG)!=0) delete eqlist;\n\t\t//if (isEqHead()) delete eqlist;\n\t\tif (eqhead) delete eqlist;\n\t}\n\n  //inline bool eqHead() { return ((eqdata & EQHEAD_TAG)!=0); }\n /*  bool isEqHead() {\n      if (eqlist==NULL) return false;\n      return (eqlist->head==this->mrna);\n      }\n  */\n  void joinEqList(GffObj* m) { //add list from m\n   //list head is set to the transfrag with the lower qset#\n  CTData* md=(CTData*)(m->uptr);\n  //ASSERT(md);\n  if (eqlist==NULL) { //no eqlist yet for this node\n     if (md->eqlist!=NULL) { //m in an eqlist already\n          eqlist=md->eqlist;\n          eqlist->Add(this->mrna);\n          CTData* md_head_d=(CTData*)(md->eqlist->head->uptr);\n          if (this->qset < md_head_d->qset) {\n               eqlist->head=this->mrna;\n               eqhead=true;\n               md_head_d->eqhead=false;\n               }\n        }\n        else { //m was not in an EQ list either\n          eqlist=new CEqList();\n          eqlist->Add(this->mrna);\n          eqlist->Add(m);\n          md->eqlist=eqlist;\n          if (qset<md->qset) {\n        \teqlist->head=this->mrna;\n        \teqhead=true;\n          }\n          else  {\n        \teqlist->head=m;\n        \tmd->eqhead=true;\n          }\n        }\n      }//no eqlist before\n     else { //merge two eqlists\n      if (eqlist==md->eqlist) //already in the same eqlist, nothing to do\n         return;\n      if (md->eqlist!=NULL) {\n        //copy the smaller list into the larger one\n        CEqList* srclst, *destlst;\n        if (md->eqlist->Count()<eqlist->Count()) {\n           srclst=md->eqlist;\n           destlst=eqlist;\n           }\n         else {\n           srclst=eqlist;\n           destlst=md->eqlist;\n           }\n         for (int i=0;i<srclst->Count();i++) {\n           destlst->Add(srclst->Get(i));\n           CTData* od=(CTData*)((*srclst)[i]->uptr);\n           od->eqlist=destlst;\n           }\n        this->eqlist=destlst;\n        CTData* s_head_d=(CTData*)(srclst->head->uptr);\n        CTData* d_head_d=(CTData*)(destlst->head->uptr);\n        if (s_head_d->qset < d_head_d->qset ) {\n             this->eqlist->head=srclst->head;\n             s_head_d->eqhead=true;\n             d_head_d->eqhead=false;\n        }\n        else {\n          s_head_d->eqhead=false;\n          d_head_d->eqhead=true;\n        }\n        delete srclst;\n      }\n      else { //md->eqlist==NULL\n        eqlist->Add(m);\n        md->eqlist=eqlist;\n        CTData* head_d=(CTData*)(eqlist->head->uptr);\n        if (md->qset<head_d->qset) {\n          eqlist->head=m;\n          md->eqhead=true;\n        }\n      }\n    }\n  }\n\n\tvoid addOvl(char code,GffObj* target=NULL, int ovlen=0) {\n\t\tovls.AddIfNew(new COvLink(code, target, ovlen));\n\t}\n\tchar getBestCode() {\n\t\treturn (ovls.Count()>0) ? ovls[0]->code : 0 ;\n    }\n\tbool operator<(CTData& b) { return (mrna < b.mrna); }\n\tbool operator==(CTData& b) { return (mrna==b.mrna); }\n};\n\nclass GSuperLocus;\nclass GTrackLocus;\nclass GXLocus;\n\nclass GXSeg : public GSeg {\npublic:\n\tint flags;\n\tGXSeg(uint s=0, uint e=0, int f=0):GSeg(s,e),flags(f) { }\n};\n\n//Data structure holding a query locus data (overlapping mRNAs on the same strand)\n// and also the accuracy data of all mRNAs of a query locus\n// (against all reference loci overlapping the same region)\nclass GLocus:public GSeg {\npublic:\n    int gseq_id; //id of underlying genomic sequence\n    int qfidx; // for locus tracking\n    GTrackLocus* t_ptr; //for locus tracking cluster\n    GffObj* mrna_maxcov;  //transcript with maximum coverage (for main \"ref\" transcript)\n    GffObj* mrna_maxscore; //transcript with maximum gscore (for major isoform)\n    GList<GffObj> mrnas; //list of transcripts (isoforms) for this locus\n\tGArray<GXSeg> uexons; //list of unique exons (covered segments) in this region\n\tGArray<GSeg> mexons; //list of merged exons in this region\n\tGIArray introns;\n\tGList<GLocus> cmpovl; //temp list of overlapping qry/ref loci to compare to (while forming superloci)\n\t\n\t//only for reference loci --> keep track of all superloci found for each qry dataset\n\t//                           which contain this reference locus\n\tGList<GSuperLocus>* superlst;\n\tGXLocus* xlocus; //superlocus formed by exon overlaps across all qry datasets\n\t// -- if genomic sequence was given:\n\tint spl_major; // number of GT-AG splice site consensi\n\tint spl_rare; // number of GC-AG, AT-AC and other rare splice site consensi\n\tint spl_wrong; //number of \"wrong\" (unrecognized) splice site consensi\n\tint ichains; //number of multi-exon mrnas\n\tint ichainTP; //number of intron chains fully matching reference introns\n\t//int ichainATP;\n\tint mrnaTP;\n\t//int mrnaATP;\n\tint v; //user flag/data\n\tGLocus(GffObj* mrna=NULL, int qidx=-1):mrnas(true,false,false),uexons(true,true),mexons(true,true),\n\t  introns(), cmpovl(true,false,true) {\n\t\t//this will NOT free mrnas!\n\t\tichains=0;\n\t\tgseq_id=-1;\n\t\tqfidx=qidx;\n\t\tt_ptr=NULL;\n\t\tcreset();\n\t\txlocus=NULL;\n\t\tmrna_maxcov=NULL;\n\t\tmrna_maxscore=NULL;\n\t\tsuperlst=new GList<GSuperLocus>(true,false,false);\n\t\tif (mrna!=NULL) {\n\t\t\tstart=mrna->exons.First()->start;\n\t\t\tend=mrna->exons.Last()->end;;\n\t\t\tgseq_id=mrna->gseq_id;\n\t\t\tGISeg seg;\n\t\t\tfor (int i=0;i<mrna->exons.Count();i++) {\n\t\t\t\tseg.start=mrna->exons[i]->start;\n\t\t\t\tseg.end=mrna->exons[i]->end;\n\t\t\t\tint flags=0; //terminal exon flags (1=left end, 2=right end)\n\t\t\t\tif (i==0) flags|=1;\n\t\t\t\tif (i==mrna->exons.Count()-1) flags|=2;\n\t\t\t\tGXSeg xseg(seg.start, seg.end, flags);\n\t\t\t\tuexons.Add(xseg);\n\t\t\t\tmexons.Add(seg);\n\t\t\t\tif (i>0) {\n\t\t\t\t\tseg.start=mrna->exons[i-1]->end+1;\n\t\t\t\t\tseg.end=mrna->exons[i]->start-1;\n\t\t\t\t\tseg.t=mrna;\n\t\t\t\t\tintrons.Add(seg);\n\t\t\t\t}\n\t\t\t}\n\t\t\tmrnas.Add(mrna);\n\t\t\tif (mrna->exons.Count()>1) ichains++;\n\t\t\t((CTData*)(mrna->uptr))->locus=this;\n\t\t\tmrna_maxscore=mrna;\n\t\t\tmrna_maxcov=mrna;\n\t\t}\n\t}\n\t~GLocus() {\n\t\tdelete superlst;\n\t}\n\tvoid creset() {\n\t\tspl_major=0;spl_rare=0;spl_wrong=0;\n\t\tv=0; //visited/other data\n\t\tichainTP=0;\n\t\t//ichainATP=0;\n\t\tmrnaTP=0;\n\t\t//mrnaATP=0;\n\t\tcmpovl.Clear();\n\t}\n\t\n\tvoid addMerge(GLocus& locus, GffObj* lnkmrna) {\n\t\t//add all the elements of the other locus (merging)\n\t\t//-- merge mexons\n\t\tGArray<int> ovlexons(true,true); //list of locus.mexons indexes overlapping existing mexons\n\t\tint i=0; //index of first mexons with a merge\n\t\tint j=0; //index current mrna exon\n\t\twhile (i<mexons.Count() && j<locus.mexons.Count()) {\n\t\t\tuint istart=mexons[i].start;\n\t\t\tuint iend=mexons[i].end;\n\t\t\tuint jstart=locus.mexons[j].start;\n\t\t\tuint jend=locus.mexons[j].end;\n\t\t\tif (iend<jstart) { i++; continue; }\n\t\t\tif (jend<istart) { j++; continue; }\n\t\t\t//if (mexons[i].overlap(jstart, jend)) {\n\t\t\t//exon overlap was found :\n\t\t\tovlexons.Add(j);\n\t\t\t//extend mexons[i] as needed\n\t\t\tif (jstart<istart) mexons[i].start=jstart;\n\t\t\tif (jend>iend) { //mexons[i] end extend\n\t\t\t\tmexons[i].end=jend;\n\t\t\t\t//now this could overlap the next mexon(s), so we have to merge them all\n\t\t\t\twhile (i<mexons.Count()-1 && mexons[i].end>mexons[i+1].start) {\n\t\t\t\t\tuint nextend=mexons[i+1].end;\n\t\t\t\t\tmexons.Delete(i+1);\n\t\t\t\t\tif (nextend>mexons[i].end) {\n\t\t\t\t\t\tmexons[i].end=nextend;\n\t\t\t\t\t\tbreak; //no need to check next mexons\n\t\t\t\t\t}\n                } //while next mexons merge\n            } // mexons[i] end extend\n\t\t\t//  } //exon overlap\n\t\t\tj++; //check the next locus.mexon\n\t\t}\n\t\t//-- add the rest of the non-overlapping mexons:\n\t\tGSeg seg;\n\t\tfor (int i=0;i<locus.mexons.Count();i++) {\n\t\t\tseg.start=locus.mexons[i].start;\n\t\t\tseg.end=locus.mexons[i].end;\n\t\t\tif (!ovlexons.Exists(i)) mexons.Add(seg);\n\t\t}\n        // -- merge uexons\n        //add to uexons:\n\t\tfor (int i=0;i<locus.uexons.Count();i++) {\n\t\t\tuexons.Add(locus.uexons[i]);\n\t\t}\n\t\tfor (int i=0;i<locus.introns.Count();i++) {\n\t\t\tintrons.IAdd(&(locus.introns[i]));\n            }\n\t\t\n\t\t// -- add locus.mrnas\n\t\tfor (int i=0;i<locus.mrnas.Count();i++) {\n\t\t\t((CTData*)(locus.mrnas[i]->uptr))->locus=this;\n\t\t\tif (locus.mrnas[i]!=lnkmrna) {\n\t\t\t\tmrnas.Add(locus.mrnas[i]);\n\t\t\t\tif (locus.mrnas[i]->exons.Count()>1) ichains++;\n            }\n\t\t  }\n\t\t// -- adjust start/end as needed\n\t\tif (start>locus.start) start=locus.start;\n\t\tif (end<locus.end) end=locus.end;\n\t\tif (mrna_maxcov->covlen<locus.mrna_maxcov->covlen)\n\t\t\tmrna_maxcov=locus.mrna_maxcov;\n\t\tif (mrna_maxscore->gscore<locus.mrna_maxscore->gscore)\n\t\t\tmrna_maxscore=locus.mrna_maxscore;\n     }\n\t\n\n\tbool exonOverlap(GLocus& loc) {\n\t\t//check if any mexons overlap!\n\t\tint i=0;\n\t\tint j=0;\n\t\twhile (i<mexons.Count() && j<loc.mexons.Count()) {\n\t\t\tuint istart=mexons[i].start;\n\t\t\tuint iend=mexons[i].end;\n\t\t\tuint jstart=loc.mexons[j].start;\n\t\t\tuint jend=loc.mexons[j].end;\n\t\t\tif (iend<jstart) { i++; continue; }\n\t\t\tif (jend<istart) { j++; continue; }\n\t\t\t//exon overlap found if we're here:\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n    }\n\t\n\tbool add_mRNA(GffObj* mrna) {\n\t\tif (mrnas.Count()>0 && mrna->gseq_id!=gseq_id) return false; //mrna must be on the same genomic seq\n\t\t//check for exon overlap with existing mexons\n\t\t//also update uexons and mexons accordingly, if mrna is added\n\t\tuint mrna_start=mrna->exons.First()->start;\n\t\tuint mrna_end=mrna->exons.Last()->end;\n\t\tif (mrna_start>end || start>mrna_end) return false;\n\t\tbool hasovl=false;\n\t\tint i=0; //index of first mexons with a merge\n\t\tint j=0; //index current mrna exon\n\t\tGArray<int> ovlexons(true,true); //list of mrna exon indexes overlapping mexons\n\t\twhile (i<mexons.Count() && j<mrna->exons.Count()) {\n\t\t\tuint istart=mexons[i].start;\n\t\t\tuint iend=mexons[i].end;\n\t\t\tuint jstart=mrna->exons[j]->start;\n\t\t\tuint jend=mrna->exons[j]->end;\n\t\t\tif (iend<jstart) { i++; continue; }\n\t\t\tif (jend<istart) { j++; continue; }\n\t\t\t//exon overlap found if we're here:\n\t\t\tovlexons.Add(j);\n\t\t\thasovl=true;\n\t\t\t//extend mexons[i] as needed\n\t\t\tif (jstart<istart) mexons[i].start=jstart;\n\t\t\tif (jend>iend) { //mexon stretch up\n\t\t\t\tmexons[i].end=jend;\n\t\t\t\t//now this could overlap the next mexon(s), so we have to merge them all\n\t\t\t\twhile (i<mexons.Count()-1 && mexons[i].end>mexons[i+1].start) {\n\t\t\t\t\tuint nextend=mexons[i+1].end;\n\t\t\t\t\tmexons.Delete(i+1);\n\t\t\t\t\tif (nextend>mexons[i].end) {\n\t\t\t\t\t\tmexons[i].end=nextend;\n\t\t\t\t\t\tbreak; //no need to check next mexons\n\t\t\t\t\t}\n\t\t\t\t} //while next mexons merge\n\t\t\t} //possible mexons merge\n\t\t\t\n\t\t\tj++; //check the next mrna exon\n\t\t}//all vs all exon check loop\n\t\tif (hasovl) {\n\t\t\tGSeg seg;\n\t         //add the rest of the non-overlapping exons,\n\t\t\t // and also to uexons etc.\n\t\t\tfor (int i=0;i<mrna->exons.Count();i++) {\n\t\t\t\tseg.start=mrna->exons[i]->start;\n\t\t\t\tseg.end=mrna->exons[i]->end;\n\t\t\t\tif (!ovlexons.Exists(i)) mexons.Add(seg);\n\t\t\t\tint xterm=0;\n\t\t\t\tif (i==0) xterm|=1;\n\t\t\t\tif (i==mrna->exons.Count()-1) xterm|=2;\n\t\t\t\tGXSeg xseg(seg.start, seg.end, xterm);\n\t\t\t\tuexons.Add(xseg);\n\t\t\t\tGISeg iseg;\n\t\t\t\tif (i>0) {\n\t\t\t\t\tiseg.start=mrna->exons[i-1]->end+1;\n\t\t\t\t\tiseg.end=mrna->exons[i]->start-1;\n\t\t\t\t\tiseg.t=mrna;\n\t\t\t\t\tintrons.Add(iseg);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tmrnas_add(mrna);\n\t\t\t// add to mrnas\n\t\t\t((CTData*)mrna->uptr)->locus=this;\n\t\t\tgseq_id=mrna->gseq_id;\n\t\t\tif (mrna->exons.Count()>1) ichains++;\n\t\t}\n\t\treturn hasovl;\n\t}\n\t\n\t//simpler,basic adding of a mrna\n\tvoid mrnas_add(GffObj* mrna) {\n\t\tmrnas.Add(mrna);\n\t\t// adjust start/end\n\t\tif (start>mrna->start) start=mrna->start;\n\t\tif (end<mrna->end) end=mrna->end;\n\t\tif (mrna_maxcov->covlen<mrna->covlen) mrna_maxcov=mrna;\n\t\tif (mrna_maxscore->gscore<mrna->gscore) mrna_maxscore=mrna;\n    }\n};\n\nclass GSuperLocus;\nclass GTrackLocus;\n\nclass GSuperLocus : public GSeg {\npublic:\n    int qfidx; //index of query dataset/file for which this superlocus was created\n    GList<GLocus> qloci;\n    GList<GLocus> rloci;\n    GList<GffObj> qmrnas; //list of transcripts (isoforms) for this locus\n    GArray<GSeg> qmexons; //list of merged exons in this region\n    GArray<GXSeg> quexons; //list of unique exons (covered segments) in this region\n    GIArray qintrons; //list of unique introns in this region\n    //same lists for reference:\n    GList<GffObj> rmrnas; //list of ref transcripts (isoforms) for this locus\n    GArray<GSeg> rmexons; //list of ref merged exons in this region\n    GArray<GXSeg> ruexons; //list of ref unique exons (covered segments) in this region\n    GArray<GISeg> rintrons; //list of unique introns in this region\n    // store problematic introns for printing:\n    GIArray i_missed; //missed reference introns (not overlapped by any qry intron)\n    GIArray i_notp;  //wrong ref introns (one or both ends not matching any qry intron)\n    //\n    GIArray i_qwrong; //totally wrong qry introns (not overlapped by any ref intron)\n    GIArray i_qnotp;  //imperfect qry introns (may overlap but has no \"perfect\" match)\n\t\n\t\n    int qbases_all;\n    int rbases_all; //in fact, it's all ref bases overlapping any query loci\n    int in_rmrnas; //count of ALL ref mrnas and loci given for this region\n    int in_rloci; //not just those overlapping qry data\n    // this will keep track of total qry loci, mrnas and exons in an area\n    int total_superloci;\n    int total_qloci;\n    int total_qloci_alt; //total qloci with multiple transcripts\n\n    int total_qmrnas;\n    int total_qexons; //unique exons\n    int total_qmexons;\n    int total_qintrons; //unique introns\n    int total_qichains; //total multi-exon transfrags predicted (incl. duplicates if -G)\n\n    // NOTE: these ref totals are only limited to data from loci overlapping any qry loci\n    int total_rmexons;\n    int total_rloci;\n    int total_rmrnas;\n    int total_richains; //total multi-exon reference transcripts\n    int total_rexons;\n    int total_rintrons; //unique introns\n\t\n    //--- accuracy data after compared to ref loci:\n  int locusQTP;\n  int locusTP; // +1 if ichainTP+mrnaTP > 0\n  //int locusAQTP;\n\t//int locusATP; // 1 if ichainATP + mrnaATP > 0\n\tint locusFP;\n\t//int locusAFP;\n\t//int locusAFN;\n\tint locusFN;\n\t//---transcript level accuracy -- all exon coordinates should match (most stringent)\n\tint mrnaTP; // number of qry mRNAs with perfect match with ref transcripts\n\t//int mrnaATP;\n\t//---intron level accuracy (comparing the ordered set of splice sites):\n\tint ichainTP; // number of fully matched ref intron chains (# correctly predicted ichains)\n\t\n\t//int ichainFP; // number of qry intron chains not matching a reference intron chain\n\t//int ichainFN; // number of ref intron chains in this region not being covered by a reference intron chain\n\t/*\n\t// same as above, but Approximate -- allowing a 5bp distance around splice site coordinates\n\tint ichainATP; //as opposed to ichainTP, this also includes ref intron chains which are \n                   //sub-chains of qry intron chains (rare cases)\n     */\n\t//---projected features ---\n\t//---exon level accuracy:\n\tint exonTP;  //number of matched reference exons (true positives)\n\tint exonQTP; //number of query exons matching reference exons\n\t//int exonFP; //number of exons of query with no perfect match with a reference exon\n\t//int exonFN; //number of exons of reference with no perfect match with a query exon\n\t// same as the above but with acceptable approximation (10bp error window):\n\t/*int exonATP;\n\tint exonAFP;\n\tint exonAFN;*/\n\t\n\tint intronTP;  //number of perfectly overlapping introns (true positives)\n\tint intronFP; //number of introns of query with no perfect match with a reference intron\n\tint intronFN; //number of introns of reference with no perfect match with a query intron\n\t/*\n\t// same as the above but with acceptable approximation (10bp error window):\n\tint intronATP;\n\tint intronAFP;\n\tint intronAFN;\n\t*/\n\t//-- EGASP added these too:\n\tint m_exons; //number of exons totally missed (not overlapped *at all* by any query exon)\n\tint w_exons; //numer of totally wrong exons (query exons not overlapping *at all* any reference exon)\n\tint m_introns; //number of introns totally missed (not overlapped *at all* by any query intron)\n\tint w_introns; //numer of totally wrong introns (query introns not overlapping *at all* any reference intron)\n\tint m_loci; //missed loci\n\tint w_loci; //novel/wrong loci\n\t//---base level accuracy\n\tint baseTP; //number of overlapping bases\n\tint baseFP; //number of qry bases not overlapping reference\n\tint baseFN; //number of ref bases not overlapping qry\n\t//            sorted,free,unique       sorted,unique\n    GSuperLocus(uint lstart=0,uint lend=0):qloci(true,false,false),rloci(true,false,false),\n\tqmrnas(true,false,false), qmexons(true,false), quexons(true,false), qintrons(false),\n\trmrnas(true,false,false), rmexons(true,false), ruexons(true,false), rintrons(false),\n\ti_missed(false),i_notp(false), i_qwrong(false), i_qnotp(false){\n\t\tqfidx=-1;\n\t\tstart=lstart;\n\t\tend=lend;\n\t\tqbases_all=0;\n\t\trbases_all=0;\n\t\tbaseTP=0;baseFP=0;baseFN=0;\n\t\tlocusTP=0;locusQTP=0; //locusAQTP=0; locusATP=0;\n\t\tlocusFP=0;// locusAFP=0;locusAFN=0;\n\t\tlocusFN=0;\n\t\tin_rmrnas=0;\n\t\tin_rloci=0;\n\t\tw_loci=0;\n\t\tm_loci=0;\n\t\ttotal_superloci=0;\n\t\tmrnaTP=0;//mrnaFP=0;mrnaFN=0;\n\t\tichainTP=0;//ichainFP=0;ichainFN=0;\n\t\texonTP=0;exonQTP=0;\n\t\t//exonFP=0;exonFN=0;\n\t\tintronTP=0;intronFP=0;intronFN=0;\n\t\t/* mrnaATP=0;//mrnaAFP=0;mrnaAFN=0;\n\t\tichainATP=0;//ichainAFP=0;ichainAFN=0;\n\t\texonATP=0;exonAFP=0;exonAFN=0;\n\t\tintronATP=0;intronAFP=0;intronAFN=0; */\n\t\ttotal_rmexons=0;\n\t\ttotal_qmexons=0;\n\t\ttotal_qexons=0;total_qloci=0;total_qmrnas=0;\n\t\ttotal_qloci_alt=0;\n\t\ttotal_qintrons=0;total_qichains=0;\n\t\ttotal_rexons=0;total_rloci=0;total_rmrnas=0;\n\t\ttotal_rintrons=0;total_richains=0;\n\t\tw_exons=0;\n\t\tm_exons=0;\n\t\tw_introns=0;\n\t\tm_introns=0;\n\t}\n    void addQlocus(GLocus& loc) {\n\t\tif (start==0 || start>loc.start) start=loc.start;\n\t\tif (end<loc.end) end=loc.end;\n\t\tqloci.Add(&loc);\n\t\ttotal_qloci++;\n\t\tif (loc.ichains>0 && loc.mrnas.Count()>1)\n\t\t    total_qloci_alt++;\n\t\tqmrnas.Add(loc.mrnas);\n\t\ttotal_qmrnas+=loc.mrnas.Count();\n\t\ttotal_qichains+=loc.ichains;\n\t\tqmexons.Add(loc.mexons);\n\t\ttotal_qmexons+=loc.mexons.Count();\n\t\tquexons.Add(loc.uexons);\n\t\ttotal_qexons+=loc.uexons.Count();\n\t\tqintrons.Add(loc.introns);\n\t\ttotal_qintrons+=loc.introns.Count();\n\t}\n    void addRlocus(GLocus& loc) {\n\t\tif (start==0 || start>loc.start) start=loc.start;\n\t\tif (end<loc.end) end=loc.end;\n\t\trloci.Add(&loc);\n\t\ttotal_rloci++;\n\t\trmrnas.Add(loc.mrnas);\n\t\ttotal_rmrnas+=loc.mrnas.Count();\n\t\ttotal_richains+=loc.ichains;\n\t\trmexons.Add(loc.mexons);\n\t\ttotal_rmexons+=loc.mexons.Count();\n\t\truexons.Add(loc.uexons);\n\t\ttotal_rexons+=loc.uexons.Count();\n\t\trintrons.Add(loc.introns);\n\t\ttotal_rintrons+=loc.introns.Count();\n\t}\n\t\n    void calcF() {\n\t\t// base level\n\t\tbaseFP=qbases_all-baseTP;\n\t\tbaseFN=rbases_all-baseTP;\n\t\t//exon level:\n\t\t//exonFP=total_qexons-exonTP;\n\t\t//exonFN=total_rexons-exonTP;\n\t\t//intron stats\n\t\tintronFP=total_qintrons-intronTP;\n\t\tintronFN=total_rintrons-intronTP;\n\t\t/* intronAFN=total_rintrons-intronATP;\n\t\tintronAFP=total_qintrons-intronATP;\n\t\texonAFP=total_qexons-exonATP;\n\t\texonAFN=total_rexons-exonATP; */\n\t\t\n\t\t// ichain and transcript levels:\n\t\t//ichainAFP=total_qichains-ichainATP;\n\t\t//ichainFP=total_qichains-ichainTP;\n\t\t//ichainAFN=total_richains-ichainATP;\n\t\t//ichainFN=total_richains-ichainTP;\n\t\t//mrnaFP=total_qmrnas-mrnaTP;\n\t\t//mrnaFN=total_rmrnas-mrnaTP;\n\t\t//mrnaAFP=total_qmrnas-mrnaATP;\n\t\t//mrnaAFN=total_rmrnas-mrnaATP;\n\t\t// locus/gene level:\n\t\tlocusFP=total_qloci-locusQTP;\n\t\t/*locusAFN=total_rloci-locusATP;\n\t\tlocusAFP=total_qloci-locusAQTP;*/\n\t\tlocusFN=total_rloci-locusTP;\n\t}\n\t\n    void addStats(GSuperLocus& s) {\n\t\tin_rmrnas+=s.in_rmrnas;\n\t\tin_rloci+=s.in_rloci;\n\t\tbaseTP+=s.baseTP;\n\t\texonTP+=s.exonTP;\n\t\texonQTP+=s.exonQTP;\n\t\tintronTP+=s.intronTP;\n\t\tichainTP+=s.ichainTP;\n\t\tmrnaTP+=s.mrnaTP;\n\t\tlocusTP+=s.locusTP;\n\t\tlocusQTP+=s.locusQTP;\n\t\t/*\n\t\tmrnaATP+=s.mrnaATP;\n\t\texonATP+=s.exonATP;\n\t\tintronATP+=s.intronATP;\n\t\tichainATP+=s.ichainATP;\n\t\tlocusATP+=s.locusATP;\n\t\tlocusAQTP+=s.locusAQTP;\n\t\t*/\n\t\tm_exons+=s.m_exons;\n\t\tw_exons+=s.w_exons;\n\t\tm_introns+=s.m_introns;\n\t\tw_introns+=s.w_introns;\n\t\tif (s.total_superloci==0 && s.qloci.Count()>0) s.total_superloci=1;\n\t\ttotal_superloci+=s.total_superloci;\n\t\tqbases_all+=s.qbases_all;\n\t\trbases_all+=s.rbases_all;\n\t\tm_loci+=s.m_loci;\n\t\tw_loci+=s.w_loci;\n\t\ttotal_qexons+=s.total_qexons;\n\t\ttotal_qintrons+=s.total_qintrons;\n\t\ttotal_qmexons+=s.total_qmexons;\n\t\ttotal_rexons+=s.total_rexons;\n\t\ttotal_rintrons+=s.total_rintrons;\n\t\ttotal_rmexons+=s.total_rmexons;\n\t\ttotal_qmrnas+=s.total_qmrnas;\n\t\ttotal_qichains+=s.total_qichains;\n\t\ttotal_rmrnas+=s.total_rmrnas;\n\t\ttotal_richains+=s.total_richains;\n\t\ttotal_qloci+=s.total_qloci;\n\t\ttotal_qloci_alt+=s.total_qloci_alt;\n\t\ttotal_rloci+=s.total_rloci;\n    }\n};\n\nclass GSeqData {\n\tint gseq_id;\npublic:\n    const char* gseq_name;\n    GList<GffObj> refs_f; //forward strand mRNAs\n    GList<GffObj> refs_r; //reverse strand mRNAs\n\tGList<GffObj> mrnas_f; //forward strand mRNAs\n\tGList<GffObj> mrnas_r; //reverse strand mRNAs\n\tGList<GLocus> loci_f; //forward strand loci\n\tGList<GLocus> loci_r; //reverse strand loci\n\t//--> the fields below are not used by reference data --\n\tGList<GSuperLocus> gstats_f; //stats for forward strand superloci\n\tGList<GSuperLocus> gstats_r; //stats for reverse strand superloci\n\tGList<GLocus> nloci_f; //\"novel\" loci on forward strand\n\tGList<GLocus> nloci_r; //\"novel\" loci on reverse strand\n\tGList<GffObj> umrnas; //unknown orientation mrnas\n\tGList<GLocus> nloci_u; //\"novel\" loci with no orientation found\n\t\n\tGList<CTData> tdata; //transcript data (uptr holder for all mrnas here)\n\n\tint get_gseqid() { return gseq_id; }\n\n\t//--<\n\tGSeqData(int gid=-1):mrnas_f(true,true,false),mrnas_r(true,true,false),\n\tloci_f(true,true,true),loci_r(true,true,true),\n\tgstats_f(true,true,false),gstats_r(true,true,false),\n\tnloci_f(true,false,true), nloci_r(true,false,true),\n\tumrnas(true,true,false), nloci_u(true,true,true), tdata(false,true,false) {\n\t\tgseq_id=gid;\n\t\tif (gseq_id>=0) \n\t\t  gseq_name=GffObj::names->gseqs.getName(gseq_id);\n\t}\n\tbool operator==(GSeqData& d){\n\t\treturn (gseq_id==d.gseq_id);\n\t}\n\tbool operator>(GSeqData& d){\n\t\treturn (gseq_id>d.gseq_id);\n\t}\n\tbool operator<(GSeqData& d){\n\t\treturn (gseq_id<d.gseq_id);\n\t}\n};\n\n\n// a group of qry loci and a transcript cluster for a single qry dataset\nclass GQCluster : public GList<GffObj> {\n public:\n   GffObj* mrna_maxcov;  //transcript with maximum coverage (for largest transcript)\n   GffObj* mrna_maxscore; //transcript with maximum gscore ( = major isoform for Cufflinks)\n   uint start;\n   uint end;\n   GList<GLocus> qloci;\n   //GCluster cl; //just a more compact way of keeping all transcripts in these loci\n   GQCluster(GList<GLocus>* loci=NULL):GList<GffObj>(true,false,false),\n                                    qloci(true,false,false) {\n     mrna_maxcov=NULL;\n     mrna_maxscore=NULL;\n     start=0;\n     end=0;\n     if (loci!=NULL)  {\n          qloci.Add(*loci);\n          for (int i=0;i<loci->Count();i++) {\n             addLocus(loci->Get(i),false);\n             }\n          }\n      }\n   void addLocus(GLocus* loc, bool toLoci=true) {\n     //check so we don't add locus duplicates\n     if (toLoci) {\n        for (int i=0;i<qloci.Count();i++) {\n           if (loc==qloci[i]) return;\n           }\n        qloci.Add(loc);\n        }\n     for (int m=0;m<loc->mrnas.Count();m++) {\n        GffObj* mrna=loc->mrnas[m];\n        Add(mrna);\n        if (start==0 || start>mrna->start) start=mrna->start;\n        if (end<mrna->end) end=mrna->end;\n        if (mrna_maxcov==NULL || mrna_maxcov->covlen<mrna->covlen) mrna_maxcov=mrna;\n        if (mrna_maxscore==NULL || mrna_maxscore->gscore<mrna->gscore) mrna_maxscore=mrna;\n        }\n     }\n};\n\n//track a set of clustered qloci across multiple qry datasets\n// the qloci in qcls[] overlap but not necessarily at exon level\n// (so there can be multiple genes here in fact)\nclass GTrackLocus:public GSeg {\n  public:\n    char strand;\n    bool hasQloci;\n    //GLocus* rloc; //corresponding reference locus, if available\n    GList<GLocus> rloci; //ref loci found overlapping this region\n    GQCluster* qcls[MAX_QFILES]; //all qloci for this superlocus, grouped by dataset\n    GTrackLocus(GLocus* qloc=NULL, int q=-1):GSeg(0,0),rloci(true,false,true) {\n      strand='.';\n      for (int i=0;i<MAX_QFILES;i++) qcls[i]=NULL;\n      if (qloc!=NULL) addQLocus(qloc,q);\n      }\n\n    void addRLocus(GLocus* rl) {\n      if (rl==NULL) return;\n      if (rl->qfidx>=0)\n          GError(\"Error: GTrackLocus::addRLocus called with a query locus (set# %d)\\n\",\n                        rl->qfidx+1);\n      if (strand=='.') strand=rl->mrna_maxcov->strand;\n      if (start==0 || start>rl->start) start=rl->start;\n      if (end==0 || end<rl->end) end=rl->end;\n      rl->t_ptr=this;\n      rloci.Add(rl);\n      }\n\n    void addQLocus(GLocus* loc, int q=-1) { //adding qry locus\n      if (loc==NULL) return;\n      if (strand=='.' && loc->mrna_maxcov->strand!='.')\n           strand=loc->mrna_maxcov->strand;\n      if (loc->qfidx<0 && q<0)\n         GError(\"Error at GTrackLocus::addQLocus(): locus.qfidx not set and index not given!\\n\");\n      if (q>=0) loc->qfidx=q;\n           else q=loc->qfidx;\n      if (start==0 || start>loc->start) start=loc->start;\n      if (end==0 || end<loc->end) end=loc->end;\n      if (qcls[q]==NULL) qcls[q]=new GQCluster();\n      hasQloci=true;\n      loc->t_ptr = this;\n      qcls[q]->addLocus(loc);\n      }\n\n    bool add_Locus(GLocus* loc) {\n      if (start==0 || overlap(*loc)) { //simple range overlap, not exon overlap\n         if (loc->qfidx<0) addRLocus(loc);\n                      else addQLocus(loc);\n         return true;\n         }\n      return false;\n      }\n\n\n   void addQCl(int q, GQCluster* qcl, GLocus* lnkloc) {\n      for (int i=0;i<qcl->qloci.Count();i++) {\n         GLocus* loc=qcl->qloci[i];\n         if (loc==lnkloc) continue; // or if loc->t_ptr==this ?\n         hasQloci=true;\n         loc->t_ptr=this;\n         qcls[q]->addLocus(loc);\n         }\n     }\n\n   void addMerge(GTrackLocus* loctrack, int qcount, GLocus* lnkloc) {\n      if (loctrack==NULL) return;\n      //merge qloci\n      for (int q=0; q < qcount; q++) {\n          if (qcls[q]==NULL) {\n             if (loctrack->qcls[q]!=NULL) {\n                 qcls[q]=loctrack->qcls[q];\n                 loctrack->qcls[q]=NULL; //just move pointer here\n                 //set all t_ptr pointers for moved loci\n                 for (int ql = 0; ql < qcls[q]->qloci.Count(); ql++) {\n                    qcls[q]->qloci[ql]->t_ptr=this;\n                    }\n                 hasQloci=true;\n                 }\n             }\n           else //existing qloci at q\n             if (loctrack->qcls[q]!=NULL) { //merge elements\n                addQCl(q, loctrack->qcls[q], lnkloc);\n              }\n          }//for each qset\n      //merge rloci, if any\n      if (loctrack->rloci.Count()>0) {\n         for (int l=0;l<loctrack->rloci.Count();l++) {\n           if (loctrack->rloci[l]!=lnkloc && loctrack->rloci[l]->t_ptr!=this) {\n              rloci.Add(loctrack->rloci[l]);\n              loctrack->rloci[l]->t_ptr=this;\n              }\n           }\n         }\n      if (loctrack->start<start) start=loctrack->start;\n      if (loctrack->end>end) end=loctrack->end;\n      if (strand=='.' && loctrack->strand!='.') strand=loctrack->strand;\n      }\n\n    /*\n    void add_QLoci(GList<GLocus>* loci, int q, GLocus& r) {\n      // only add loci overlapping given refloc\n      //rloc=&r;\n      if (loci==NULL) return;\n      for (int i=0;i<loci->Count();i++) {\n         GLocus* loc=loci->Get(i);\n         // if (!loc->exonOverlap(r)) continue;  //do we really needed exon overlap?\n         if (!loc->overlap(r)) continue;\n         if (start==0 || start>loc->start) start=loc->start;\n         if (end==0 || end<loc->end) end=loc->end;\n         loc->t_ptr=this;\n         loc->qfidx=q;\n         if (qcls[q]==NULL) qcls[q]=new GQCluster();\n         qcls[q]->addLocus(loc);\n         }\n      strand=r.mrnas[0]->strand;\n      }\n     */\n    ~GTrackLocus() {\n      for (int q=0;q<MAX_QFILES;q++)\n           if (qcls[q]!=NULL) { delete qcls[q]; qcls[q]=NULL; }\n      }\n\n    GQCluster* operator[](int q) {\n      if (q<0 || q>=MAX_QFILES)\n          GError(\"Error: qfidx index out of bounds (%d) for GTrackLocus!\\n\",q);\n      return qcls[q];\n      }\n};\n\nclass GXConsensus:public GSeg {\n public:\n   static int count;\n   int id; //XConsensus ID\n   int tss_id; //group id for those xconsensi with shared first exon\n   int p_id; //group id for those xconsensi with \"similar\" protein\n   GffObj* tcons; //longest transcript to represent the combined \"consensus\" structure\n   GffObj* ref; //overlapping reference transcript \n   char refcode; // the code for ref relationship (like in the tracking file)\n   char* aa;\n   int aalen;\n   GXConsensus* contained; //if contained into another GXConsensus \n   //list of ichain-matching query (cufflinks) transcripts that contributed to this consensus\n   GList<GffObj> qchain;\n   GXConsensus(GffObj* c, CEqList* qlst, GffObj* r=NULL, char rcode=0)\n                   :qchain(false,false,false) {\n      ref=r;\n      refcode=rcode;\n      tcons=c;\n      if (qlst!=NULL) qchain.Add(*((GList<GffObj>*)qlst));\n                 else qchain.Add(c);\n      count++;\n      tss_id=0;\n      p_id=0;\n      aalen=0;\n      id=count;\n      aa=NULL;\n      start=tcons->start;\n      end=tcons->end;\n      contained=NULL;\n      }\n   ~GXConsensus() {\n     if (aa!=NULL) GFREE(aa);\n     }\n};\n\nclass GXLocus:public GSeg {\n public:\n    int id;\n    int num_mtcons; //number of multi-exon \"consensus\" transcripts in this locus\n    char strand;\n    GList<GLocus> rloci; //list of ref loci overlapping any of the mexons\n    GList<GLocus> qloci; //loci from all qry datasets that have overlapping exons with this region\n    GArray<GSeg> mexons; //list of merged exonic regions for this locus\n    GList<GXConsensus> tcons;\n    GXLocus(GLocus* lfirst=NULL):GSeg(0,0),\n        rloci((GCompareProc*)cmpByPtr, (GFreeProc*)NULL, true),\n        qloci((GCompareProc*)cmpByPtr, (GFreeProc*)NULL, true),\n        mexons(true,true), tcons(true,true,false) {\n      strand='.';\n      num_mtcons=0;\n      if (lfirst!=NULL) {\n         add_Locus(lfirst);\n         }\n      id=0;\n      }\n\n    bool add_Locus(GLocus* loc) {\n      if (mexons.Count()>0 && (end<loc->start || start > loc->end))\n              return false; //no chance for overlapping exons\n      if (mexons.Count()==0) {\n          mexons.Add(loc->mexons);\n          start=loc->start;\n          end=loc->end;\n          if (loc->qfidx<0) rloci.Add(loc);\n                      else  qloci.Add(loc);\n          strand=loc->mrna_maxcov->strand;\n          loc->xlocus=this;\n          return true;\n          }\n      int f=0;\n      if (loc->qfidx<0) {\n        if (rloci.Found(loc,f)) return false;\n        }\n      else if (qloci.Found(loc,f)) return false;\n\n      // -- merge mexons\n      GArray<int> ovlexons(true,true); //list of locus.mexons indexes overlapping existing mexons\n      int i=0; //index of first mexons with a merge\n      int j=0; //index current mrna exon\n      while (i<mexons.Count() && j<loc->mexons.Count()) {\n          uint istart=mexons[i].start;\n          uint iend=mexons[i].end;\n          uint jstart=loc->mexons[j].start;\n          uint jend=loc->mexons[j].end;\n          if (iend<jstart) { i++; continue; }\n          if (jend<istart) { j++; continue; }\n          //if (mexons[i].overlap(jstart, jend)) {\n          //exon overlap was found :\n          ovlexons.Add(j);\n          //extend mexons[i] as needed\n          if (jstart<istart) mexons[i].start=jstart;\n          if (jend>iend) { //mexons[i] end extend\n              mexons[i].end=jend;\n              //now this could overlap the next mexon(s), so we have to merge them all\n              while (i<mexons.Count()-1 && mexons[i].end>mexons[i+1].start) {\n                  uint nextend=mexons[i+1].end;\n                  mexons.Delete(i+1);\n                  if (nextend>mexons[i].end) {\n                      mexons[i].end=nextend;\n                      break; //no need to check next mexons\n                  }\n              } //while next mexons merge\n          } // mexons[i] end extend\n          //  } //exon overlap\n          j++; //check the next locus.mexon\n        }//while mexons\n      if (ovlexons.Count()==0) return false;\n      if (strand=='.' && loc->mrna_maxcov->strand!='.')\n             strand=loc->mrna_maxcov->strand;\n      //have exon overlap:\n      //-- add the rest of the non-overlapping mexons:\n       GSeg seg;\n       for (int i=0;i<loc->mexons.Count();i++) {\n            seg.start=loc->mexons[i].start;\n            seg.end=loc->mexons[i].end;\n            if (!ovlexons.Exists(i)) mexons.Add(seg);\n            }\n      // -- adjust start/end as needed\n      if (start>loc->start) start=loc->start;\n      if (end<loc->end) end=loc->end;\n      loc->xlocus=this;\n      if (loc->qfidx<0) rloci.Add(loc);\n                  else  qloci.Add(loc);\n      return true;\n      }\n\n  void addMerge(GXLocus& oxloc) {\n    GArray<int> ovlexons(true,true); //list of oxloc.mexons indexes overlapping existing mexons\n    int i=0; //index of first mexons with a merge\n    int j=0; //index current mrna exon\n    while (i<mexons.Count() && j<oxloc.mexons.Count()) {\n        uint istart=mexons[i].start;\n        uint iend=mexons[i].end;\n        uint jstart=oxloc.mexons[j].start;\n        uint jend=oxloc.mexons[j].end;\n        if (iend<jstart) { i++; continue; }\n        if (jend<istart) { j++; continue; }\n        //if (mexons[i].overlap(jstart, jend)) {\n        //exon overlap was found :\n        ovlexons.Add(j);\n        //extend mexons[i] as needed\n        if (jstart<istart) mexons[i].start=jstart;\n        if (jend>iend) { //mexons[i] end extend\n            mexons[i].end=jend;\n            //now this could overlap the next mexon(s), so we have to merge them all\n            while (i<mexons.Count()-1 && mexons[i].end>mexons[i+1].start) {\n                uint nextend=mexons[i+1].end;\n                mexons.Delete(i+1);\n                if (nextend>mexons[i].end) {\n                    mexons[i].end=nextend;\n                    break; //no need to check next mexons\n                }\n            } //while next mexons merge\n        } // mexons[i] end extend\n        //  } //exon overlap\n        j++; //check the next oxloc.mexon\n    }\n    if (ovlexons.Count()==0) {\n      GError(\"Error: attempt to merge GXLoci with non-overlapping exons!\\n\");\n      }\n    //-- add the rest of the non-overlapping mexons:\n    GSeg seg;\n    for (int i=0;i<oxloc.mexons.Count();i++) {\n        seg.start=oxloc.mexons[i].start;\n        seg.end=oxloc.mexons[i].end;\n        if (!ovlexons.Exists(i)) mexons.Add(seg);\n        }\n   if (start>oxloc.start) start=oxloc.start;\n   if (end<oxloc.end) end=oxloc.end;\n   if (strand=='.') strand=oxloc.strand;\n    //-- steal all qloci and rloci\n    for (int i=0;i<oxloc.qloci.Count();i++) {\n         if (oxloc.qloci[i]->xlocus==this) continue;\n         qloci.Add(oxloc.qloci[i]);\n         oxloc.qloci[i]->xlocus=this;\n         }\n    for (int i=0;i<oxloc.rloci.Count();i++) {\n         if (oxloc.rloci[i]->xlocus==this) continue;\n         rloci.Add(oxloc.rloci[i]);\n         oxloc.rloci[i]->xlocus=this;\n         }\n  } //::addMerge()\n\n\n void checkContainment() {\n   //checking containment\n  for (int j=0;j<tcons.Count()-1;j++) {\n    GXConsensus* t=tcons[j];\n    for (int i=j+1;i<tcons.Count();i++) {\n       if (tcons[i]->contained!=NULL && t->tcons->exons.Count()>1) continue; //will check the container later anyway\n       int c_status=checkXConsContain(t->tcons, tcons[i]->tcons);\n       if (c_status==0) continue; //no containment relationship between t and tcons[i]\n       if (c_status>0) { //t is a container for tcons[i]\n            tcons[i]->contained=t;\n            }\n         else { //contained into exising XCons\n            t->contained=tcons[i];\n            break;\n            }\n       }\n   }\n  }\n \n int checkXConsContain(GffObj* a, GffObj* b) {\n  // returns  1 if a is the container of b\n  //         -1 if a is contained in b\n  //          0 if no \n  if (a->end<b->start || b->end<a->start) return 0;\n  if (a->exons.Count()==b->exons.Count()) {\n     if (a->exons.Count()>1) return 0; //same number of exons - no containment possible\n                                       //because equivalence was already tested\n           else { //single exon containment testing\n             //this is fuzzy and messy (end result may vary depending on the testing order)\n             int ovlen=a->exons[0]->overlapLen(b->exons[0]);\n             int minlen=GMIN(a->covlen, b->covlen);\n             if (ovlen>=minlen*0.8) { //if at least 80% of the shorter one is covered, it is contained\n                return ((a->covlen>b->covlen) ? 1 : -1);\n                }\n              else return 0;\n             //if (a->start<=b->start+10 && a->end+10>=b->end) return 1;\n             //  else { if (b->start<=a->start+10 && b->end+10>=a->end) return -1;\n             //          else return 0; \n             //}\n             }\n     }\n   //different number of exons:\n   if (a->exons.Count()>b->exons.Count()) return t_contains(*a, *b) ? 1:0;\n                     else return t_contains(*b, *a) ? -1 : 0;\n  }\n  \n void addXCons(GXConsensus* t) {\n  tcons.Add(t);\n  }\n  \n}; //GXLocus\n\n\n\nint parse_mRNAs(GfList& mrnas,\n\t\t\t\t GList<GSeqData>& glstdata,\n\t\t\t\t bool is_ref_set=true,\n\t\t\t\t int check_for_dups=0,\n\t\t\t\t int qfidx=-1, bool only_multiexon=false);\n\n//reading a mRNAs from a gff file and grouping them into loci\nvoid read_mRNAs(FILE* f, GList<GSeqData>& seqdata, GList<GSeqData>* ref_data=NULL, \n              int check_for_dups=0, int qfidx=-1, const char* fname=NULL,\n              bool only_multiexon=false);\n\nvoid read_transcripts(FILE* f, GList<GSeqData>& seqdata, \n#ifdef CUFFLINKS\n  boost::crc_32_type& crc_result, \n#endif\n  bool keepAttrs=true);\n\nvoid sort_GSeqs_byName(GList<GSeqData>& seqdata);\n\nbool singleExonTMatch(GffObj& m, GffObj& r, int& ovlen);\n\n//strict intron chain match, or single-exon match\nbool tMatch(GffObj& a, GffObj& b, int& ovlen, bool fuzzunspl=false, \n           bool contain_only=false);\n\n//use qsearch to \"position\" a given coordinate x within a list of transcripts sorted \n//by their start (lowest) coordinate; the returned int is the list index of the \n//closest GffObj starting just *ABOVE* coordinate x\n//Convention: returns -1 if there is no such GffObj (i.e. last GffObj start <= x)\nint qsearch_mrnas(uint x, GList<GffObj>& mrnas);\nint qsearch_loci(uint x, GList<GLocus>& segs); // same as above, but for GSeg lists\n\nGSeqData* getRefData(int gid, GList<GSeqData>& ref_data); //returns reference GSeqData for a specific genomic sequence\n\n#endif\n"
  },
  {
    "path": "src/hits.cpp",
    "content": "/*\n *  hits.cpp\n *  Cufflinks\n *\n *  Created by Cole Trapnell on 3/23/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <cassert>\n#include <cstdlib>\n#include <cstring>\n#include <iostream>\n#include <set>\n#include <vector>\n\n#include \"common.h\"\n#include \"hits.h\"\n#include \"tokenize.h\"\n\n#include \"abundances.h\"\n\nusing namespace std;\n\n#if ENABLE_THREADS\nboost::mutex RefSequenceTable::table_lock;\n#endif\n\nint num_deleted = 0;\n\nvoid ReadHit::trim(int trimmed_length)\n{\n    bool antisense_aln = _sam_flag & 0x10;\n    \n    vector<CigarOp> new_cigar;\n    int new_left = 0;\n    \n    if (!antisense_aln)\n    {\n        int pos = _left;\n        new_left = _left;\n        int length = 0;\n\t\tfor (vector<CigarOp>::iterator i = _cigar.begin(); i < _cigar.end(); ++i)\n\t\t{\n\t\t\tconst CigarOp& op = *i;\n            \n            if (length < trimmed_length)\n            {\n                switch(op.opcode)\n                {\n                    case REF_SKIP:\n                        //gaps_out.push_back(make_pair(pos, pos + op.length - 1));\n                        pos += op.length;\n                        new_cigar.push_back(op);\n                        break;\n                    case SOFT_CLIP:\n                        assert(false); // not sure if this case is right\n                        pos += op.length;\n                        length += op.length;\n                        new_cigar.push_back(op);\n                        break;\n                    case HARD_CLIP:\n                        new_cigar.push_back(op);\n                        break;\n                    case MATCH:\n                        if (length + op.length < trimmed_length)\n                        {\n                            pos += op.length;\n                            length += op.length;\n                            new_cigar.push_back(op);\n                        }\n                        else\n                        {\n                            new_cigar.push_back(CigarOp(MATCH, trimmed_length - length));\n                            pos += trimmed_length - length;\n                            length += trimmed_length - length;\n                        }\n                        break;\n                    case INS:\n                        assert(false); // not sure if this case is right\n                        pos -= op.length;\n                        length -= op.length;\n                        new_cigar.push_back(op);\n                        break;\n                    case DEL:\n                        assert(false); // not sure if this case is right\n                        pos += op.length;\n                        length += op.length;\n                        new_cigar.push_back(op);\n                        break;\n                    default:\n                        break;\n                }\n            }\n\t\t}\n    }\n    else\n    {\n        int pos = _right;\n        int length = 0;\n\t\tfor (vector<CigarOp>::reverse_iterator i = _cigar.rbegin(); i < _cigar.rend(); ++i)\n\t\t{\n\t\t\tconst CigarOp& op = *i;\n            \n            if (length < trimmed_length)\n            {\n                switch(op.opcode)\n                {\n                    case REF_SKIP:\n                        //gaps_out.push_back(make_pair(pos, pos + op.length - 1));\n                        pos -= op.length;\n                        new_cigar.push_back(op);\n                        break;\n                    case SOFT_CLIP:\n                        assert(false); // not sure if this case is right\n                        pos -= op.length;\n                        length += op.length;\n                        new_cigar.push_back(op);\n                        break;\n                    case HARD_CLIP:\n                        new_cigar.push_back(op);\n                        break;\n                    case MATCH:\n                        if (length + op.length < trimmed_length)\n                        {\n                            pos -= op.length;\n                            length += op.length;\n                            new_cigar.push_back(op);\n                        }\n                        else\n                        {\n                            new_cigar.push_back(CigarOp(MATCH, trimmed_length - length));\n                            pos -= trimmed_length - length;\n                            length += trimmed_length - length;\n                        }\n                        break;\n                    case INS:\n                        assert(false); // not sure if this case is right\n                        pos += op.length;\n                        length -= op.length;\n                        new_cigar.push_back(op);\n                        break;\n                    case DEL:\n                        assert(false); // not sure if this case is right\n                        pos -= op.length;\n                        length += op.length;\n                        new_cigar.push_back(op);\n                        break;\n                    default:\n                        break;\n                }\n            }\n\t\t}\n        _left = pos;\n    }\n    _cigar = new_cigar;\n    _right = get_right();\n    assert (trimmed_length == read_len());\n}\n\n//static const int max_read_length = 1024;\n\nbool hit_insert_id_lt(const ReadHit& h1, const ReadHit& h2)\n{\n\treturn h1.insert_id() < h2.insert_id();\n}\n\nbool hits_eq_mod_id(const ReadHit& lhs, const ReadHit& rhs)\n{\n\treturn (lhs.ref_id() == rhs.ref_id() &&\n\t\t\tlhs.antisense_align() == rhs.antisense_align() &&\n\t\t\tlhs.left() == rhs.left() && \n\t\t\tlhs.source_strand() == rhs.source_strand() &&\n\t\t\tlhs.cigar() == rhs.cigar());\n}\n\n// Compares for structural equality, but won't declare multihits equal to one another\nbool hits_eq_non_multi(const MateHit& lhs, const MateHit& rhs)\n{\n\tif ((lhs.is_multi() || rhs.is_multi() ) && lhs.insert_id() != rhs.insert_id())\n\t\treturn false;\n\treturn hits_equals(lhs, rhs);\n}\n\n// Compares for structural equality, but won't declare multihits equal to one another\n// and won't return true for hits from different read groups (e.g. replicate samples)\nbool hits_eq_non_multi_non_replicate(const MateHit& lhs, const MateHit& rhs)\n{\n\tif (((lhs.is_multi() || rhs.is_multi()) && lhs.insert_id() != rhs.insert_id()) || lhs.read_group_props() != rhs.read_group_props())\n\t\treturn false;\n\treturn hits_equals(lhs, rhs);\n}\n    \n// Does NOT care about the read group this hit came from.\nbool hits_equals(const MateHit& lhs, const MateHit& rhs) \n{\n\tif (lhs.ref_id() != rhs.ref_id())\n\t\treturn false;\n\t\n\tif ((lhs.left_alignment() == NULL) != (rhs.left_alignment() == NULL))\n\t\treturn false;\n\tif ((lhs.right_alignment() == NULL) != (rhs.right_alignment() == NULL))\n\t\treturn false;\n\tif (lhs.left_alignment())\n\t{\n\t\tif (!(hits_eq_mod_id(*lhs.left_alignment(),*(rhs.left_alignment()))))\n\t\t\treturn false;\n\t}\n\tif (lhs.right_alignment())\n\t{\n\t\tif (!(hits_eq_mod_id(*lhs.right_alignment(),*(rhs.right_alignment()))))\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\nbool has_no_collapse_mass(const MateHit& hit)\n{\n\treturn hit.collapse_mass() == 0;\n}\n\n// Assumes hits are sorted by mate_hit_lt\n// Does not collapse hits that are multi-reads\nvoid collapse_hits(const vector<MateHit>& hits,\n\t\t\t\t   vector<MateHit>& non_redundant)\n{\n\tcopy(hits.begin(), hits.end(), back_inserter(non_redundant));\n\tvector<MateHit>::iterator new_end = unique(non_redundant.begin(), \n\t\t\t\t\t\t\t\t\t\t\t   non_redundant.end(), \n\t\t\t\t\t\t\t\t\t\t\t   hits_eq_non_multi_non_replicate);\n\tnon_redundant.erase(new_end, non_redundant.end());\n    non_redundant.resize(non_redundant.size());\n\t\n\tBOOST_FOREACH(MateHit& hit, non_redundant)\n\t\thit.collapse_mass(0);\n\t\n\tsize_t curr_aln = 0;\n\tsize_t curr_unique_aln = 0;\n\twhile (curr_aln < hits.size())\n\t{\n\t\tif (hits_eq_non_multi_non_replicate(non_redundant[curr_unique_aln], hits[curr_aln]) || hits_eq_non_multi_non_replicate(non_redundant[++curr_unique_aln], hits[curr_aln]))\n\t\t{\n            double more_mass = hits[curr_aln].internal_scale_mass();\n\t\t\t//assert(non_redundant[curr_unique_aln].collapse_mass() == 0 || !non_redundant[curr_unique_aln].is_multi());\n\t\t\tnon_redundant[curr_unique_aln].incr_collapse_mass(more_mass);\n\t\t}\n\t\telse\n\t\t\tassert(false);\n\t\t\n\t\t++curr_aln;\n\t}\n\t\n\t//BOOST_FOREACH(MateHit& hit, non_redundant)\n\t\t//assert(hit.collapse_mass() <= 1 || !hit.is_multi());\n\t\n\t//non_redundant.erase(remove_if(non_redundant.begin(),non_redundant.end(),has_no_collapse_mass), non_redundant.end()); \n\t\n}\n\n// Places multi-reads to the right of reads they match\nbool mate_hit_lt(const MateHit& lhs, const MateHit& rhs)\n{\n\tif (lhs.left() != rhs.left())\n\t\treturn lhs.left() < rhs.left();\n\tif (lhs.right() != rhs.right())\n\t\treturn lhs.right() > rhs.right();\n\t\n\tif ((lhs.left_alignment() == NULL) != (rhs.left_alignment() == NULL))\n\t\treturn (lhs.left_alignment() == NULL) < (rhs.left_alignment() == NULL);\n\t\n\tif ((lhs.right_alignment() == NULL) != (rhs.right_alignment() == NULL))\n\t\treturn (lhs.right_alignment() == NULL) < (rhs.right_alignment() == NULL);\n\t\n\tassert ((lhs.right_alignment() == NULL) == (rhs.right_alignment() == NULL));\n\tassert ((lhs.left_alignment() == NULL) == (rhs.left_alignment() == NULL));\n\t\n\tconst ReadHit* lhs_l = lhs.left_alignment();\n\tconst ReadHit* lhs_r = lhs.right_alignment();\n\t\n\tconst ReadHit* rhs_l = rhs.left_alignment();\n\tconst ReadHit* rhs_r = rhs.right_alignment();\n\t\n\tif (lhs_l && rhs_l)\n\t{\n\t\tif (lhs_l->cigar().size() != rhs_l->cigar().size())\n\t\t\treturn lhs_l->cigar().size() < rhs_l->cigar().size(); \n\t\tfor (size_t i = 0; i < lhs_l->cigar().size(); ++i)\n\t\t{\n\t\t\tif (lhs_l->cigar()[i].opcode != rhs_l->cigar()[i].opcode)\n\t\t\t\treturn lhs_l->cigar()[i].opcode < rhs_l->cigar()[i].opcode;\n\t\t\tif (lhs_l->cigar()[i].length != rhs_l->cigar()[i].length)\n\t\t\t\treturn lhs_l->cigar()[i].length < rhs_l->cigar()[i].length;\n\t\t}\n\t}\n\t\n\tif (lhs_r && rhs_r)\n\t{\n\t\tif (lhs_r->cigar().size() != rhs_r->cigar().size())\n\t\t\treturn lhs_r->cigar().size() < rhs_r->cigar().size(); \n\t\tfor (size_t i = 0; i < lhs_r->cigar().size(); ++i)\n\t\t{\n\t\t\tif (lhs_r->cigar()[i].opcode != rhs_r->cigar()[i].opcode)\n\t\t\t\treturn lhs_r->cigar()[i].opcode < rhs_r->cigar()[i].opcode;\n\t\t\tif (lhs_r->cigar()[i].length != rhs_r->cigar()[i].length)\n\t\t\t\treturn lhs_r->cigar()[i].length < rhs_r->cigar()[i].length;\n\t\t}\n\t}\n\t\n\tif (lhs.is_multi() != rhs.is_multi())\n\t{\n\t\treturn rhs.is_multi();\n\t}\n    \n    if (lhs.read_group_props() != rhs.read_group_props())\n\t{\n\t\treturn lhs.read_group_props() < rhs.read_group_props();\n\t}\n\t\n\treturn false;\n}\n\n\nReadHit HitFactory::create_hit(const string& insert_name, \n\t\t\t\t\t\t\t   const string& ref_name,\n\t\t\t\t\t\t\t   int left,\n\t\t\t\t\t\t\t   const vector<CigarOp>& cigar,\n\t\t\t\t\t\t\t   CuffStrand source_strand,\n\t\t\t\t\t\t\t   const string& partner_ref,\n\t\t\t\t\t\t\t   int partner_pos, \n\t\t\t\t\t\t\t   unsigned int edit_dist,\n\t\t\t\t\t\t\t   int num_hits,\n                               float base_mass,\n                               uint32_t sam_flag)\n{\n\tInsertID insert_id = _insert_table.get_id(insert_name);\n\tRefID reference_id = _ref_table.get_id(ref_name, NULL);\n\tRefID partner_ref_id = _ref_table.get_id(partner_ref, NULL);\n\t\n\treturn ReadHit(reference_id,\n\t\t\t\t   insert_id,\n\t\t\t\t   left, \n\t\t\t\t   cigar, \n\t\t\t\t   source_strand,\n\t\t\t\t   partner_ref_id,\n\t\t\t\t   partner_pos,\n\t\t\t\t   edit_dist,\n\t\t\t\t   num_hits,\n                   base_mass,\n                   sam_flag);\t\n}\n\nReadHit HitFactory::create_hit(const string& insert_name, \n\t\t\t\t\t\t\t   const string& ref_name,\n\t\t\t\t\t\t\t   uint32_t left,\n\t\t\t\t\t\t\t   uint32_t read_len,\n\t\t\t\t\t\t\t   CuffStrand source_strand,\n\t\t\t\t\t\t\t   const string& partner_ref,\n\t\t\t\t\t\t\t   int partner_pos,\n\t\t\t\t\t\t\t   unsigned int edit_dist,\n\t\t\t\t\t\t\t   int num_hits,\n                               float base_mass,\n                               uint32_t sam_flag)\n{\n\tInsertID insert_id = _insert_table.get_id(insert_name);\n\tRefID reference_id = _ref_table.get_id(ref_name, NULL);\n\tRefID partner_ref_id = _ref_table.get_id(partner_ref, NULL);\n\t\n\treturn ReadHit(reference_id,\n\t\t\t\t   insert_id, \n\t\t\t\t   left,\n\t\t\t\t   read_len,\n\t\t\t\t   source_strand,\n\t\t\t\t   partner_ref_id,\n\t\t\t\t   partner_pos,\n\t\t\t\t   edit_dist,\n\t\t\t\t   num_hits,\n                   base_mass,\n                   sam_flag);\t\n}\n\nCuffStrand use_stranded_protocol(uint32_t sam_flag,  MateStrandMapping msm)\n{\n    bool antisense_aln = sam_flag & 0x10;\n\tif (((sam_flag & BAM_FPAIRED) && (sam_flag & BAM_FREAD1)) || !(sam_flag & BAM_FPAIRED)) // first-in-pair or single-end\n\t{\n\t\tswitch(msm)\n\t\t{\n\t\t\tcase FF:\n\t\t\tcase FR:\n\t\t\t\treturn (antisense_aln) ? CUFF_REV : CUFF_FWD;\n\t\t\t\tbreak;\n\t\t\tcase RF:\n\t\t\tcase RR:\n\t\t\t\treturn (antisense_aln) ? CUFF_FWD : CUFF_REV;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\telse // second-in-pair read\n\t{\n\t\tswitch (msm)\n\t\t{\n\t\t\tcase FF:\n\t\t\tcase RF:\n\t\t\t\treturn (antisense_aln) ? CUFF_REV : CUFF_FWD;\n\t\t\t\tbreak;\n\t\t\tcase FR:\n\t\t\tcase RR:\n\t\t\t\treturn (antisense_aln) ? CUFF_FWD : CUFF_REV;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tassert(false);\n    return CUFF_STRAND_UNKNOWN;\n}\n\nbool BAMHitFactory::get_hit_from_bam1t(const bam1_t* hit_buf,\n\t\t\t\t\t\t\t\t\t   const bam_hdr_t* header,\n\t\t\t\t\t\t\t\t\t   ReadHit& bh)\n{\n\tuint32_t sam_flag = hit_buf->core.flag;\n\t\n\tint text_offset = hit_buf->core.pos;\n\tint text_mate_pos = hit_buf->core.mpos;\n\tint target_id = hit_buf->core.tid;\n\tint mate_target_id = hit_buf->core.mtid;\n\t\n\tvector<CigarOp> cigar;\n\tbool spliced_alignment = false;\n\tint num_hits = 1;\n\t\n\t//header->target_name[c->tid]\n\t\n\tif (sam_flag & 0x4 || target_id < 0)\n\t{\n\t\t//assert(cigar.size() == 1 && cigar[0].opcode == MATCH);\n\t\tbh = create_hit(bam_get_qname(hit_buf),\n\t\t\t\t\t\t\"*\",\n\t\t\t\t\t\t0, // SAM files are 1-indexed\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tCUFF_STRAND_UNKNOWN,\n\t\t\t\t\t\t\"*\",\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t1,\n                        1.0,\n                        sam_flag);\n\t\treturn true;\n\t}\n\tif (target_id >= header->n_targets)\n    {\n        fprintf (stderr, \"BAM error: file contains hits to sequences not in header SQ records (%s)\\n\", bam_get_qname(hit_buf));\n        return false;\n    }\n    \n\tstring text_name = header->target_name[target_id];\n\t\n\tfor (int i = 0; i < hit_buf->core.n_cigar; ++i) \n\t{\n\t\t//char* t;\n\n\t\tint length = bam_get_cigar(hit_buf)[i] >> BAM_CIGAR_SHIFT;\n\t\tif (length <= 0)\n\t\t{\n\t\t  fprintf (stderr, \"BAM error: CIGAR op has zero length (%s)\\n\", bam_get_qname(hit_buf));\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\tCigarOpCode opcode;\n\t\tswitch(bam_get_cigar(hit_buf)[i] & BAM_CIGAR_MASK)\n\t\t{\n\t\t\tcase BAM_CMATCH: opcode  = MATCH; break; \n\t\t\tcase BAM_CINS: opcode  = INS; break;\n\t\t\tcase BAM_CDEL: opcode  = DEL; break; \n\t\t\tcase BAM_CSOFT_CLIP: opcode  = SOFT_CLIP; break;\n\t\t\tcase BAM_CHARD_CLIP: opcode  = HARD_CLIP; break;\n\t\t\tcase BAM_CPAD: opcode  = PAD; break; \n\t\t\tcase BAM_CREF_SKIP:\n                opcode = REF_SKIP;\n\t\t\t\tspliced_alignment = true;\n\t\t\t\tif (length > (int)max_intron_length)\n\t\t\t\t{\n\t\t\t\t\t//fprintf(stderr, \"Encounter REF_SKIP > max_gene_length, skipping\\n\");\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t//fprintf (stderr, \"SAM error on line %d: invalid CIGAR operation\\n\", _line_num);\n\t\t\t\treturn false;\n\t\t}\n\t\tif (opcode != HARD_CLIP)\n\t\t\tcigar.push_back(CigarOp(opcode, length));\n\t}\n\t\n\tstring mrnm;\n\tif (mate_target_id >= 0)\n\t{\n\t\tif (mate_target_id == target_id)\n\t\t{\n\t\t\tmrnm = header->target_name[mate_target_id];\n//\t\t\tif (abs((int)text_mate_pos - (int)text_offset) > (int)max_intron_length)\n//\t\t\t{\n//\t\t\t\t//fprintf (stderr, \"Mates are too distant, skipping\\n\");\n//\t\t\t\treturn false;\n//\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//fprintf(stderr, \"Trans-spliced mates are not currently supported, skipping\\n\");\n\t\t\treturn false;\n\t\t}\n\t}\n\telse\n\t{\n\t\ttext_mate_pos = 0;\n\t}\n\t\n\tCuffStrand source_strand = CUFF_STRAND_UNKNOWN;\n\tunsigned char num_mismatches = 0;\n\n\tuint8_t* ptr = bam_aux_get(hit_buf, \"XS\");\n\tif (ptr)\n\t{\n\t\tchar src_strand_char = bam_aux2A(ptr);\n\t\tif (src_strand_char == '-')\n\t\t\tsource_strand = CUFF_REV;\n\t\telse if (src_strand_char == '+')\n\t\t\tsource_strand = CUFF_FWD;\n\t}\n\t\n\tptr = bam_aux_get(hit_buf, \"NM\");\n\tif (ptr)\n\t{\n\t\tnum_mismatches = bam_aux2i(ptr);\n\t}\n\n\tptr = bam_aux_get(hit_buf, \"NH\");\n\tif (ptr)\n\t{\n\t\tnum_hits = bam_aux2i(ptr);\n\t}\n    \n    double mass = 1.0;\n    ptr = bam_aux_get(hit_buf, \"ZF\");\n\tif (ptr)\n\t{\n\t\tmass = bam_aux2i(ptr);\n        if (mass <= 0.0)\n            mass = 1.0;\n\t}\n\t    \n    if (_rg_props.strandedness() == STRANDED_PROTOCOL && source_strand == CUFF_STRAND_UNKNOWN)\n\t\tsource_strand = use_stranded_protocol(sam_flag, _rg_props.mate_strand_mapping());\n    \n\tif (!spliced_alignment)\n\t{\n\t\t//assert(_rg_props.strandedness() == STRANDED_PROTOCOL || source_strand == CUFF_STRAND_UNKNOWN);\n\n\t\t//assert(cigar.size() == 1 && cigar[0].opcode == MATCH);\n\t\tbh = create_hit(bam_get_qname(hit_buf),\n\t\t\t\t\t\ttext_name,\n\t\t\t\t\t\ttext_offset,  // BAM files are 0-indexed\n\t\t\t\t\t\tcigar,\n\t\t\t\t\t\tsource_strand,\n\t\t\t\t\t\tmrnm,\n\t\t\t\t\t\ttext_mate_pos,\n\t\t\t\t\t\tnum_mismatches,\n\t\t\t\t\t\tnum_hits,\n                        mass,\n                        sam_flag);\n\t\treturn true;\n\t\t\n\t}\n\telse\n\t{\t\n\t\tif (source_strand == CUFF_STRAND_UNKNOWN)\n\t\t{\n\t\t\tfprintf(stderr, \"BAM record error: found spliced alignment without XS attribute\\n\");\n\t\t}\n\t\t\n\t\tbh = create_hit(bam_get_qname(hit_buf),\n\t\t\t\t\t\ttext_name,\n\t\t\t\t\t\ttext_offset,  // BAM files are 0-indexed\n\t\t\t\t\t\tcigar,\n\t\t\t\t\t\tsource_strand,\n\t\t\t\t\t\tmrnm,\n\t\t\t\t\t\ttext_mate_pos,\n\t\t\t\t\t\tnum_mismatches,\n\t\t\t\t\t\tnum_hits,\n                        mass,\n                        sam_flag);\n\t\treturn true;\n\t}\n\t\n\t\n\treturn true;\n}\n\n\n\nPlatform str_to_platform(const string pl_str)\n{\n    if (pl_str == \"SOLiD\")\n    {\n        return SOLID;\n    }\n    else if (pl_str == \"Illumina\") \n    {\n        return ILLUMINA;\n    }\n    else \n    {\n        return UNKNOWN_PLATFORM;\n    }\n}\n\n// Parses the header to determine platform and other properties\nbool HitFactory::parse_header_string(const string& header_rec,\n                                     ReadGroupProperties& rg_props)\n{\n    vector<string> columns;\n    tokenize(header_rec, \"\\t\", columns); \n    \n    if (columns[0] == \"@RG\")\n    {\n        for (size_t i = 1; i < columns.size(); ++i)\n        {\n            vector<string> fields;\n            tokenize(columns[i], \":\", fields);\n            if (fields[0] == \"PL\")\n            {\n                if (rg_props.platform() == UNKNOWN_PLATFORM)\n                {\n                    Platform p = str_to_platform(fields[1]);\n                    rg_props.platform(p);\n                }\n                else \n                {\n                    Platform p = str_to_platform(fields[1]);\n                    if (p != rg_props.platform())\n                    {\n                        fprintf(stderr, \"Error: Processing reads from different platforms is not currently supported\\n\");\n                        return false;\n                    }\n                }\n\n            }\n        }\n    }\n    else if (columns[0] == \"@SQ\")\n    {\n        _num_seq_header_recs++;\n        for (size_t i = 1; i < columns.size(); ++i)\n        {\n            vector<string> fields;\n            tokenize(columns[i], \":\", fields);\n            if (fields[0] == \"SN\")\n            {\n                // Populate the RefSequenceTable with the sequence dictionary, \n                // to ensure that (for example) downstream GTF files are sorted\n                // in an order consistent with the header, and to enforce that\n                // BAM records appear in the order implied by the header\n                RefID _id = _ref_table.get_id(fields[1], NULL);\n\n                const RefSequenceTable::SequenceInfo* info = _ref_table.get_info(_id);\n\t\t\t\t\n                if (info->observation_order != _num_seq_header_recs)\n                {\n                    if (info->name != fields[1])\n                    {\n                        fprintf(stderr, \"Error: Hash collision between references '%s' and '%s'.\\n\", info->name, fields[1].c_str());\n                    }\n                    else\n                    {\n                        fprintf(stderr, \"Error: sort order of reads in BAMs must be the same\\n\");\n\t\t\t\t\t}\n                    exit(1);\n                }\n            }\n        }\n    }\n\n    return true;\n}\n\n// Parses multiple header lines to determine platform and other properties\nvoid HitFactory::parse_header_lines(const string& h_text,\n\t\t\t\t\t\t\t\t\tReadGroupProperties& _rg_props)\n{\n\tsize_t offset = 0;\n\twhile(offset < h_text.size())\n\t{\n\t\tsize_t next_newline = h_text.find('\\n', offset);\n\t\tsize_t line_length = next_newline == string::npos ? string::npos : next_newline - offset;\n\t\tstd::string this_line = h_text.substr(offset, line_length);\n\t\tparse_header_string(this_line, _rg_props);\n\n\t\tif(next_newline == string::npos)\n\t\t\tbreak;\n\t\toffset = next_newline + 1;\n\t}\n}\n\nvoid HitFactory::finalize_rg_props()\n{\n    if (_rg_props.platform() == SOLID)\n    {\n        _rg_props.strandedness(STRANDED_PROTOCOL);\n        _rg_props.std_mate_orientation(MATES_POINT_TOWARD);\n    }\n    else\n    {\n        // Default to Illumina's unstranded protocol params for strandedness and\n        // mate orientation\n        _rg_props.strandedness(UNSTRANDED_PROTOCOL);\n        _rg_props.std_mate_orientation(MATES_POINT_TOWARD);\n    }\n}\n\nstatic const unsigned MAX_HEADER_LEN = 64 * 1024 * 1024; // 4 MB\n\nbool SAMHitFactory::read_next_hit(ReadHit& bh)\n{\n\tbool new_rec = fgets(_hit_buf,  _hit_buf_max_sz - 1, _hit_file);\n\tif (!new_rec)\n\t\treturn false;\n\t++_line_num;\n\tchar* nl = strrchr(_hit_buf, '\\n');\n\tif (nl) *nl = 0;\n\n\tconst char* buf = _hit_buf;\n\n\t// Are we still in the header region?\n\tif (buf[0] == '@')\n\t\treturn false;\n\t\n\tconst char* _name = strsep((char**)&buf,\"\\t\");\n\tif (!_name)\n\t\treturn false;\n\tchar name[2048];\n\tstrncpy(name, _name, 2047); \n    \n\tconst char* sam_flag_str = strsep((char**)&buf,\"\\t\");\n\tif (!sam_flag_str)\n\t\treturn false;\n\t\n\tconst char* text_name = strsep((char**)&buf,\"\\t\");\n\tif (!text_name)\n\t\treturn false;\n\t\n\tconst char* text_offset_str = strsep((char**)&buf,\"\\t\");\n\tif (!text_offset_str)\n\t\treturn false;\n\t\n\tconst char* map_qual_str =  strsep((char**)&buf,\"\\t\");\n\tif (!map_qual_str)\n\t\treturn false;\n\t\n\tconst char* cigar_str = strsep((char**)&buf,\"\\t\");\n\tif (!cigar_str)\n\t\treturn false;\n\t\n\tconst char* mate_ref_name =  strsep((char**)&buf,\"\\t\");\n\tif (!mate_ref_name)\n\t\treturn false;\n\t\n\tconst char* mate_pos_str =  strsep((char**)&buf,\"\\t\");\n\tif (!mate_pos_str)\n\t\treturn false;\n\t\n\tconst char* inferred_insert_sz_str =  strsep((char**)&buf,\"\\t\");\n\tif (!inferred_insert_sz_str)\n\t\treturn false;\n\t\n\tconst char* seq_str =  strsep((char**)&buf,\"\\t\");\n\tif (!seq_str)\n\t\treturn false;\n\t\n\tconst char* qual_str =  strsep((char**)&buf,\"\\t\");\n\tif (!qual_str)\n\t\treturn false;\n\t\n\t\n\tint sam_flag = atoi(sam_flag_str);\n\tint text_offset = atoi(text_offset_str);\n\tint text_mate_pos = atoi(mate_pos_str);\n\t\n\tconst char* p_cig = cigar_str;\n\t//int len = strlen(sequence);\n\tvector<CigarOp> cigar;\n\tbool spliced_alignment = false;\n\tint num_hits = 1;\n\t    \n    if ((sam_flag & 0x4) ||!strcmp(text_name, \"*\"))\n\t{\n\t\t//assert(cigar.size() == 1 && cigar[0].opcode == MATCH);\n\t\tbh = create_hit(name,\n\t\t\t\t\t\t\"*\",\n\t\t\t\t\t\t0, // SAM files are 1-indexed\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tCUFF_STRAND_UNKNOWN,\n\t\t\t\t\t\t\"*\",\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t1,\n                        1.0,\n                        sam_flag);\n\t\treturn true;\n\t}\n\t// Mostly pilfered direct from the SAM tools:\n\twhile (*p_cig) \n\t{\n\t\tchar* t;\n\t\tint length = (int)strtol(p_cig, &t, 10);\n\t\tif (length <= 0)\n\t\t{\n\t\t\tfprintf (stderr, \"SAM error on line %d: CIGAR op has zero length\\n\", _line_num);\n            fprintf (stderr,\"%s\\n\", _hit_buf);\n\t\t\treturn false;\n\t\t}\n\t\tchar op_char = toupper(*t);\n\t\tCigarOpCode opcode;\n\t\tif (op_char == 'M') \n\t\t{\n\t\t\t/*if (length > max_read_length)\n\t\t\t {\n\t\t\t fprintf(stderr, \"SAM error on line %d:  %s: MATCH op has length > %d\\n\", line_num, name, max_read_length);\n\t\t\t return false;\n\t\t\t }*/\n\t\t\topcode = MATCH;\n\t\t}\n\t\telse if (op_char == 'I') opcode = INS;\n\t\telse if (op_char == 'D') \n        {\n            opcode = DEL;\n        }\n\t\telse if (op_char == 'N')\n\t\t{\n\t\t\topcode = REF_SKIP;\n\t\t\tspliced_alignment = true;\n\t\t\tif (length > (int)max_intron_length)\n\t\t\t{\n\t\t\t\t//fprintf(stderr, \"Encounter REF_SKIP > max_gene_length, skipping\\n\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\telse if (op_char == 'S') opcode = SOFT_CLIP;\n\t\telse if (op_char == 'H') opcode = HARD_CLIP;\n\t\telse if (op_char == 'P') opcode = PAD;\n\t\telse\n\t\t{\n\t\t\tfprintf (stderr, \"SAM error on line %d: invalid CIGAR operation\\n\", _line_num);\n\t\t\treturn false;\n\t\t}\n\t\tp_cig = t + 1;\n\t\t//i += length;\n\t\tif (opcode != HARD_CLIP)\n\t\t\tcigar.push_back(CigarOp(opcode, length));\n\t}\n\tif (*p_cig)\n\t{\n\t\tfprintf (stderr, \"SAM error on line %d: unmatched CIGAR operation\\n\", _line_num);\n\t\treturn false;\n\t}\n    \n\tstring mrnm;\n\tif (strcmp(mate_ref_name, \"*\"))\n\t{\n\t\tif (!strcmp(mate_ref_name, \"=\") || !strcmp(mate_ref_name, text_name))\n\t\t{\n\t\t\tmrnm = text_name;\n//\t\t\tif (abs((int)text_mate_pos - (int)text_offset) > (int)max_intron_length)\n//\t\t\t{\n//\t\t\t\t//fprintf (stderr, \"Mates are too distant, skipping\\n\");\n//\t\t\t\treturn false;\n//\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//fprintf(stderr, \"Trans-spliced mates are not currently supported, skipping\\n\");\n\t\t\treturn false;\n\t\t}\n\t}\n\telse\n\t{\n\t\ttext_mate_pos = 0;\n\t}\n\t\n\tCuffStrand source_strand = CUFF_STRAND_UNKNOWN;\n\tunsigned char num_mismatches = 0;\n\t\n\tconst char* tag_buf = buf;\n\t\n    double mass = 1.0;\n    \n\twhile((tag_buf = strsep((char**)&buf,\"\\t\")))\n\t{\n\t\t\n\t\tchar* first_colon = (char*)strchr(tag_buf, ':');\n\t\tif (first_colon)\n\t\t{\n\t\t\t*first_colon = 0;\n\t\t\t++first_colon;\n\t\t\tchar* second_colon = strchr(first_colon, ':');\n\t\t\tif (second_colon)\n\t\t\t{\n\t\t\t\t*second_colon = 0;\n\t\t\t\t++second_colon;\n\t\t\t\tconst char* first_token = tag_buf;\n\t\t\t\t//const char* second_token = first_colon;\n\t\t\t\tconst char* third_token = second_colon;\n\t\t\t\tif (!strcmp(first_token, \"XS\"))\n\t\t\t\t{\t\t\t\t\n\t\t\t\t\tif (*third_token == '-')\n\t\t\t\t\t\tsource_strand = CUFF_REV;\n\t\t\t\t\telse if (*third_token == '+')\n\t\t\t\t\t\tsource_strand = CUFF_FWD;\n\t\t\t\t}\n\t\t\t\telse if (!strcmp(first_token, \"NM\"))\n\t\t\t\t{\n\t\t\t\t\tnum_mismatches = atoi(third_token);\n\t\t\t\t}\n\t\t\t\telse if (!strcmp(first_token, \"NH\"))\n\t\t\t\t{\n                    num_hits = atoi(third_token);\n\t\t\t\t}\n                else if (!strcmp(first_token, \"ZF\"))\n\t\t\t\t{\n\t\t\t\t\tmass = atof(third_token);\n                    if (mass <= 0.0)\n                        mass = 1.0;\n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t{\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n        \n    // Don't let the protocol setting override explicit XS tags\n\tif (_rg_props.strandedness() == STRANDED_PROTOCOL && source_strand == CUFF_STRAND_UNKNOWN)\n\t\tsource_strand = use_stranded_protocol(sam_flag, _rg_props.mate_strand_mapping());\n\t\n\tif (!spliced_alignment)\n\t{\t\t\n\t\t//assert(cigar.size() == 1 && cigar[0].opcode == MATCH);\n\t\tbh = create_hit(name,\n\t\t\t\t\t\ttext_name,\n\t\t\t\t\t\ttext_offset - 1,\n\t\t\t\t\t\tcigar,\n\t\t\t\t\t\tsource_strand,\n\t\t\t\t\t\tmrnm,\n\t\t\t\t\t\ttext_mate_pos - 1,\n\t\t\t\t\t\tnum_mismatches,\n\t\t\t\t\t\tnum_hits,\n                        mass,\n                        sam_flag);\n\t\treturn true;\n\t\t\n\t}\n\telse\n\t{\t\n\t\tif (source_strand == CUFF_STRAND_UNKNOWN)\n\t\t{\n\t\t\tfprintf(stderr, \"SAM error on line %d: found spliced alignment without XS attribute\\n\", _line_num);\n\t\t}\n\t\t\n\t\tbh = create_hit(name,\n\t\t\t\t\t\ttext_name,\n\t\t\t\t\t\ttext_offset - 1,\n\t\t\t\t\t\tcigar,\n\t\t\t\t\t\tsource_strand,\n\t\t\t\t\t\tmrnm,\n\t\t\t\t\t\ttext_mate_pos - 1,\n\t\t\t\t\t\tnum_mismatches,\n\t\t\t\t\t\tnum_hits,\n                        mass,\n                        sam_flag);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool SAMHitFactory::inspect_header()\n{\n    char pBuf[10 * 1024];\n    \n    off_t curr_pos = ftello(_hit_file);\n    rewind(_hit_file);\n    \n    while (fgets(pBuf, 10*1024, _hit_file))\n    {\n        if (pBuf[0] != '@')\n        {\n            break; // done with the header.\n        }\n        char* nl = strchr(pBuf, '\\n');\n        if (nl) \n        {\n            *nl = 0; \n            parse_header_string(pBuf, _rg_props);\n        }\n    }\n    \n    fseek(_hit_file, curr_pos, SEEK_SET);\n    \n    finalize_rg_props();\n    return true;\n}\n\n//////////////////////////////////////////\n\nvoid PrecomputedExpressionHitFactory::load_count_tables(const string& expression_file_name)\n{\n    //map<int, AbundanceGroup > ab_groups;\n    \n    \n    std::ifstream ifs(expression_file_name.c_str());\n    boost::archive::binary_iarchive ia(ifs);\n    \n    //map<string, AbundanceGroup> single_sample_tracking;\n    \n    size_t num_loci = 0;\n    ia >> num_loci;\n    \n    if (num_loci > 0)\n    {\n        pair<int, AbundanceGroup> first_locus;\n        ia >> first_locus;\n        boost::shared_ptr<AbundanceGroup> ab = boost::shared_ptr<AbundanceGroup>(new AbundanceGroup(first_locus.second));\n        \n        // populate the cached count tables so we can make convincing fake bundles later on.\n        ReadGroupProperties rg_props = **(ab->rg_props().begin());\n\n        int i = 0;\n        BOOST_FOREACH(const LocusCount& c, rg_props.raw_compatible_counts())\n        {\n            compat_mass[i++] = c.count;\n            //compat_mass[c.locus_desc] = c.count;\n        }\n\n        i = 0;\n        BOOST_FOREACH(const LocusCount& c, rg_props.raw_total_counts())\n        {\n            total_mass[i++] = c.count;\n            //total_mass[c.locus_desc] = c.count;\n        }\n    }\n}\n\nvoid PrecomputedExpressionHitFactory::load_checked_parameters(const string& expression_file_name)\n{\n    std::ifstream ifs(expression_file_name.c_str());\n    boost::archive::binary_iarchive ia(ifs);\n    \n    //map<string, AbundanceGroup> single_sample_tracking;\n    \n    size_t num_loci = 0;\n    ia >> num_loci;\n    \n    if (num_loci > 0)\n    {\n        pair<int, AbundanceGroup> first_locus;\n        ia >> first_locus;\n        boost::shared_ptr<AbundanceGroup> ab = boost::shared_ptr<AbundanceGroup>(new AbundanceGroup(first_locus.second));\n        \n        // populate the cached count tables so we can make convincing fake bundles later on.\n        ReadGroupProperties rg_props = **(ab->rg_props().begin());\n        _rg_props.checked_parameters(rg_props.checked_parameters());\n    }\n}\n\nbool PrecomputedExpressionHitFactory::read_next_hit(ReadHit& buf)\n{\n\treturn false;\n}\n\nbool PrecomputedExpressionHitFactory::inspect_header()\n{\n    \n    std::ifstream ifs(_expression_file_name.c_str());\n    boost::archive::binary_iarchive ia(ifs);\n\n    RefSequenceTable& rt = ref_table();\n    \n    size_t num_loci = 0;\n    ia >> num_loci;\n    \n    for (size_t i = 0; i < num_loci; ++i)\n    {\n        pair<int, AbundanceGroup> locus;\n\n        ia >> locus;\n        boost::shared_ptr<AbundanceGroup> ab = boost::shared_ptr<AbundanceGroup>(new AbundanceGroup(locus.second));\n        \n        const string locus_tag = ab->locus_tag();\n        \n        string::size_type idx = locus_tag.find(':');\n        if (idx != string::npos)\n        {\n            string chrom_name = locus_tag.substr(0, idx);\n            rt.get_id(chrom_name.c_str(), NULL); // make sure the chromosome names are added to the RefSequenceTable in the order that they occur in the expression files.\n        }\n    }\n    \n    return true;\n}\n\nboost::shared_ptr<const AbundanceGroup> PrecomputedExpressionHitFactory::get_abundance_for_locus(int locus_id)\n{\n#if ENABLE_THREADS\n    boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n    map<int, boost::shared_ptr<const AbundanceGroup> >::const_iterator itr = _curr_ab_groups.find(locus_id);\n    if (itr != _curr_ab_groups.end())\n        return itr->second;\n    else\n        return boost::shared_ptr<const AbundanceGroup>();\n}\n\nvoid PrecomputedExpressionHitFactory::clear_abundance_for_locus(int locus_id)\n{\n#if ENABLE_THREADS\n    boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n\n    map<int, boost::shared_ptr<const AbundanceGroup> >::iterator itr = _curr_ab_groups.find(locus_id);\n    \n    if (itr != _curr_ab_groups.end())\n        _curr_ab_groups.erase(itr);\n}\n\nboost::shared_ptr<const AbundanceGroup> PrecomputedExpressionHitFactory::next_locus(int locus_id, bool cache_locus)\n{\n#if ENABLE_THREADS\n    boost::mutex::scoped_lock lock(_factory_lock);\n#endif\n//    if (locus_id == 7130)\n//    {\n//        fprintf(stderr, \"Trying to get a chr13_random\\n\");\n//    }\n    \n    if (_last_locus_id >= locus_id)\n        return boost::shared_ptr<const AbundanceGroup>(); // we already processed this one\n    \n    boost::shared_ptr<const AbundanceGroup> sought_group;\n    \n    map<int, boost::shared_ptr<const AbundanceGroup> >::iterator itr = _curr_ab_groups.find(locus_id);\n    \n    if (itr != _curr_ab_groups.end())\n        return itr->second;\n    \n    for (;_curr_locus_idx < _num_loci; ++_curr_locus_idx)\n    {\n        pair<int, AbundanceGroup> p;\n        *_ia >> p;\n        _last_locus_id = p.first;\n        boost::shared_ptr<AbundanceGroup> ab = boost::shared_ptr<AbundanceGroup>(new AbundanceGroup(p.second));\n        if (_last_locus_id == locus_id)\n        {\n            sought_group = ab;\n            break;\n        }\n        else // we don't want to lose this one...\n        {\n            if (cache_locus)\n                _curr_ab_groups[_last_locus_id] = ab;\n        }\n    }\n    if (cache_locus)\n        _curr_ab_groups[locus_id] = sought_group;\n    \n    return sought_group;\n}\n\n#ifdef HAVE_HTSLIB\n\nbool HTSHitFactory::read_next_hit(ReadHit& bh)\n{\n\tif(!records_remain())\n\t\treturn false;\n\n\tint read_ret = sam_read1(_hit_file, _file_header, _next_hit);\n\tif(read_ret < 0)\n\t{\n\t\t_eof_encountered = true;\n\t\treturn false;\n\t}\n\n\treturn get_hit_from_bam1t(_next_hit, _file_header, bh);\n}\n\nbool HTSHitFactory::inspect_header()\n{\n\tif (_file_header->text == NULL || _file_header->l_text == 0)\n\t{\n\t\tthrow std::runtime_error(\"Warning: SAM/BAM/CRAM header has 0 length or is corrupted.  Try using 'samtools reheader'\");\n\t}\n\n\tparse_header_lines(_file_header->text, _rg_props);\n\n    finalize_rg_props();\n    return true;\n}\n\nHitFactory* createSamHitFactory(const string& hit_file_name, ReadTable& it, RefSequenceTable& rt)\n{\n\ttry {\n\t\treturn new HTSHitFactory(hit_file_name, it, rt);\n\t}\n\tcatch (std::runtime_error& e)\n\t{\n\t\tfprintf(stderr, \"Error: cannot open alignment file %s for reading\\n\",\n\t\t\t\thit_file_name.c_str());\n\t\tfprintf(stderr, \"Cause: %s\\n\", e.what());\n\t\texit(1);\n\t}\n}\n\n#else // ndef HAVE_HTSLIB\n\nbool SamtoolsHitFactory::inspect_header()\n{\n    bam_header_t* header = _hit_file->header;\n\n    if (header == NULL)\n    {\n        fprintf(stderr, \"Warning: No BAM header\\n\");\n        return false;\n    }\n\n//    if (header->l_text >= MAX_HEADER_LEN)\n//    {\n//        fprintf(stderr, \"Warning: BAM header too large\\n\");\n//        return false;\n//    }\n\n\tif (header->l_text == 0 || header->text == NULL)\n\t{\n\t\tfprintf(stderr, \"Warning: BAM header has 0 length or is corrupted.  Try using 'samtools reheader'.\\n\");\n        return false;\n\t}\n\n\tparse_header_lines(header->text, _rg_props);\n\n    finalize_rg_props();\n    return true;\n}\n\n// populate a bam_t This will\nbool SamtoolsHitFactory::read_next_hit(ReadHit& bh)\n{\n    if (_next_hit.data)\n    {\n        free(_next_hit.data);\n        _next_hit.data = NULL;\n    }\n\n    if (records_remain() == false)\n        return false;\n\n    memset(&_next_hit, 0, sizeof(_next_hit));\n\n\tint bytes_read = samread(_hit_file, &_next_hit);\n\tif (bytes_read < 0)\n    {\n        _eof_encountered = true;\n\t\treturn false;\n    }\n\n\treturn get_hit_from_bam1t(&_next_hit, _hit_file->header, bh);\n}\n\nHitFactory* createSamHitFactory(const string& hit_file_name, ReadTable& it, RefSequenceTable& rt)\n{\n\ttry\n\t{\n\t\treturn new SamtoolsHitFactory(hit_file_name, it, rt);\n\t}\n\tcatch (std::runtime_error& e)\n\t{\n\t\tfprintf(stderr, \"File %s doesn't appear to be a valid BAM file, trying SAM...\\n\",\n\t\t\t\thit_file_name.c_str());\n        try\n        {\n            return new SAMHitFactory(hit_file_name, it, rt);\n        }\n        catch (std::runtime_error& e)\n        {\n            fprintf(stderr, \"Error: cannot open alignment file %s for reading\\n\",\n                    hit_file_name.c_str());\n            exit(1);\n        }\n\t}\n}\n\n#endif\n"
  },
  {
    "path": "src/hits.h",
    "content": "#ifndef BWT_MAP_H\n#define BWT_MAP_H\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <iostream>\n#include <fstream>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <cstring>\n#include <map>\n#include <vector>\n#include <cassert>\n\n#include <boost/shared_ptr.hpp>\n\n#ifdef HAVE_HTSLIB\n#include <htslib/hts.h>\n#include <htslib/hfile.h>\n#include <htslib/cram.h>\n#include <htslib/bgzf.h>\n#include <htslib/sam.h>\n#else\n#include <bam/sam.h>\n#endif\n\n#include \"common.h\"\n#include \"multireads.h\"\n\nusing namespace std;\n\n/*\n *  hits.h\n *  Cufflinks\n *\n *  Created by Cole Trapnell on 3/23/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\nenum CuffStrand { CUFF_STRAND_UNKNOWN = 0, CUFF_FWD = 1, CUFF_REV = 2, CUFF_BOTH = 3 };\n\n\nenum CigarOpCode \n{ \n\tMATCH = BAM_CMATCH, \n\tINS = BAM_CINS, \n\tDEL = BAM_CDEL, \n\tREF_SKIP = BAM_CREF_SKIP,\n\tSOFT_CLIP = BAM_CSOFT_CLIP, \n\tHARD_CLIP = BAM_CHARD_CLIP, \n\tPAD = BAM_CPAD\n};\n\nstruct CigarOp\n{\n\tCigarOp(CigarOpCode o, uint32_t l) : opcode(o), length(l) {}\n\tCigarOpCode opcode : 3;\n\tuint32_t length : 29;\n\t\n\tbool operator==(const CigarOp& rhs) const { return opcode == rhs.opcode && length == rhs.length; }\n\t\n};\n\ntypedef uint64_t InsertID;\ntypedef uint64_t RefID;\n\nextern int num_deleted;\n\n/*  Stores the information from a single record of the bowtie map. A given read\n    may have many of these.\n*/\nstruct ReadHit\n{\n\tReadHit() : \n\t\t_ref_id(0),\n\t\t_insert_id(0),\n        _base_mass(1.0),\n        _edit_dist(0xFFFFFFFF),\n\t\t_num_hits(1)\n    {\n        num_deleted++;\n    }\n\t\n\tReadHit(RefID ref_id,\n\t\t\tInsertID insert_id, \n\t\t\tint left, \n\t\t\tint read_len, \n\t\t\tCuffStrand source_strand,\n\t\t\tRefID partner_ref,\n\t\t\tint partner_pos,\n\t\t\tunsigned int edit_dist,\n\t\t\tint num_hits,\n            float base_mass,\n            uint32_t sam_flag) :\n\t\t_ref_id(ref_id),\n\t\t_insert_id(insert_id), \n\t\t_left(left), \n\t\t_partner_ref_id(partner_ref),\n\t\t_partner_pos(partner_pos),\n\t\t_cigar(vector<CigarOp>(1,CigarOp(MATCH,read_len))),\n\t\t_source_strand(source_strand),\n        _base_mass(base_mass),\n        _edit_dist(edit_dist),\n\t\t_num_hits(num_hits),\n        _sam_flag(sam_flag)\n\t{\n\t\tassert(_cigar.capacity() == _cigar.size());\n\t\t_right = get_right();\n        num_deleted++;\n\t}\n    \n\tReadHit(RefID ref_id,\n\t\t\tInsertID insert_id, \n\t\t\tint left,  \n\t\t\tconst vector<CigarOp>& cigar,\n\t\t\tCuffStrand source_strand,\n\t\t\tRefID partner_ref,\n\t\t\tint partner_pos, \n\t\t\tunsigned int  edit_dist,\n\t\t\tint num_hits,\n            float base_mass,\n            uint32_t sam_flag) : \n\t\t_ref_id(ref_id),\n\t\t_insert_id(insert_id), \t\n\t\t_left(left),\n\t\t_partner_ref_id(partner_ref),\n\t\t_partner_pos(partner_pos),\n\t\t_cigar(cigar),\n\t\t_source_strand(source_strand),\n        _base_mass(base_mass),\n        _edit_dist(edit_dist),\n\t\t_num_hits(num_hits),\n        _sam_flag(sam_flag)\n\t{\n\t\tassert(_cigar.capacity() == _cigar.size());\n\t\t_right = get_right();\n        num_deleted++;\n\t}\n    \n    ReadHit(const ReadHit& other)\n    {\n        _ref_id = other._ref_id;\n\t\t_insert_id = other._insert_id;\n\t\t_left = other._left;\n\t\t_partner_ref_id = other._partner_ref_id;\n\t\t_partner_pos = other._partner_pos;\n\t\t_cigar = other._cigar;\n\t\t_source_strand = other._source_strand;\n\t\t_num_hits = other._num_hits;\n        _base_mass = other._base_mass;\n        _edit_dist = other._edit_dist;\n        _right = get_right();\n        _sam_flag = other._sam_flag;\n        num_deleted++;\n    }\n    \n    ~ReadHit()\n    {\n        --num_deleted;\n    }\n\n\tint read_len() const\n\t{\n\t\tint len = 0;\n\t\tfor (size_t i = 0; i < _cigar.size(); ++i)\n\t\t{\n\t\t\tconst CigarOp& op = _cigar[i];\n\t\t\tswitch(op.opcode)\n\t\t\t{\n\t\t\t\tcase MATCH:\n\t\t\t\tcase INS:\n\t\t\t\tcase SOFT_CLIP:\n\t\t\t\t\tlen += op.length;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn len;\n\t}\n\t\n\tbool contains_splice() const\n\t{\n\t\tfor (size_t i = 0; i < _cigar.size(); ++i)\n\t\t{\n\t\t\t\tif (_cigar[i].opcode == REF_SKIP)\n\t\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\tbool is_singleton() const\n\t{ \n\t\treturn (partner_ref_id() == 0 ||\n\t\t\t\tpartner_ref_id() != ref_id() ||\n\t\t\t\tabs(partner_pos() - left()) > max_partner_dist);\n\t}\n\t\n\tbool operator==(const ReadHit& rhs) const\n\t{\n\t    return (_insert_id == rhs._insert_id &&\n\t            _ref_id == rhs._ref_id &&\n\t            antisense_align() == rhs.antisense_align() &&\n\t            _left == rhs._left && \n\t            _source_strand == rhs._source_strand &&\n\t            /* DO NOT USE ACCEPTED IN COMPARISON */\n\t            _cigar == rhs._cigar);\n    }\n\t\n\tRefID ref_id() const\t\t\t\t{ return _ref_id;\t\t\t}\n\tInsertID insert_id() const\t\t\t{ return _insert_id;\t\t}\n\t\n\tRefID partner_ref_id() const\t\t{ return _partner_ref_id;\t}\n\tint\t  partner_pos()\tconst\t\t\t{ return _partner_pos;\t\t}\n\t\n\tint left() const\t\t\t\t\t{ return _left;\t\t\t\t}\n\tint right() const\t\t\t\t\t{ return _right;\t\t\t}\n\tCuffStrand source_strand()\tconst\t{ return _source_strand; }\n\tbool antisense_align() const\t\t{ return _sam_flag & 0x10;\t}\n    bool is_first() const               { return _sam_flag & 0x40;  }\t\n\t\n\t// Number of multi-hits for this read\n\tint num_hits() const\t\t\t\t{ return _num_hits;\t\t\t}\n\t\n    // We are ignoring the _base_mass and re-calculating based on multi-hits\n\tdouble mass() const \n\t{\n\t\tif (is_singleton())\n\t\t\treturn 1.0/_num_hits;\n\t\treturn 0.5 / _num_hits;\n\t}\n\t\n\t// For convenience, if you just want a copy of the gap intervals\n\t// for this hit.\n\tvoid gaps(vector<pair<int,int> >& gaps_out) const\n\t{\n\t\tgaps_out.clear();\n\t\tint pos = _left;\n\t\tfor (size_t i = 0; i < _cigar.size(); ++i)\n\t\t{\n\t\t\tconst CigarOp& op = _cigar[i];\n\t\t\t\n\t\t\tswitch(op.opcode)\n\t\t\t{\n\t\t\t\tcase REF_SKIP:\n\t\t\t\t\tgaps_out.push_back(make_pair(pos, pos + op.length - 1));\n\t\t\t\t\tpos += op.length;\n\t\t\t\t\tbreak;\n                case SOFT_CLIP:\n                    pos += op.length;\n                    break;\n                case HARD_CLIP:\n                    break;\n\t\t\t\tcase MATCH:\n\t\t\t\t\tpos += op.length;\n\t\t\t\t\tbreak;\n                case INS:\n                    pos -= op.length;\n\t\t\t\t\tbreak;\n                case DEL:\n                    pos += op.length;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tconst vector<CigarOp>& cigar() const { return _cigar; }\n\t\n\tbool contiguous() const \n\t{ \n\t\treturn _cigar.size() == 1 && _cigar[0].opcode == MATCH;\n\t}\n\t\n    unsigned int  edit_dist() const { return _edit_dist; }\n    \n    void trim(int trimmed_length);\n    \n\t//const string& hitfile_rec() const { return _hitfile_rec; }\n\t//void hitfile_rec(const string& rec) { _hitfile_rec = rec; }\n\t\nprivate:\n\t\n\tint get_right() const\t\n\t{\n\t\tint r = _left;\n\t\tfor (size_t i = 0; i < _cigar.size(); ++i)\n\t\t{\n\t\t\tconst CigarOp& op = _cigar[i];\n\t\t\t\n\t\t\tswitch(op.opcode)\n\t\t\t{\n\t\t\t\tcase MATCH:\n\t\t\t\tcase REF_SKIP:\n                case SOFT_CLIP:\n\t\t\t\tcase DEL:\n\t\t\t\t\tr += op.length;\n\t\t\t\t\tbreak;\n                case INS:\n                case HARD_CLIP:\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn r;\t\t\t\n\t}\n\t\n\tRefID _ref_id;\n\tInsertID _insert_id;   // Id of the sequencing insert\n\tint _left;        // Position in the reference of the left side of the alignment\n\tint _right;\n\t\n\tRefID _partner_ref_id;  // Reference contig on which we expect the mate \n\tint _partner_pos;     // Position at which we expect the mate of this hit\n\t\n\t\n\tvector<CigarOp> _cigar;\n\t\n\tCuffStrand _source_strand;    // Which strand the read really came from, if known\n    float _base_mass;\n    unsigned int  _edit_dist;            // Number of mismatches\n\tint _num_hits; // Number of multi-hits (1 by default)\n    uint32_t _sam_flag;\n\t//string _hitfile_rec; // Points to the buffer for the record from which this hit came\n};\n\nclass ReadTable\n{\npublic:\n\t\n\tReadTable() {}\n\t\n\t// This function should NEVER return zero\n\tInsertID get_id(const string& name)\n\t{\n\t\tuint64_t _id = hash_string(name.c_str());\n\t\tassert(_id);\n\t\treturn _id;\n\t}\n    \n    // Calculate checksum\n\tInsertID get_cs(const string& name)\n\t{\n        return string_checksum(name.c_str());\n    }\n    \nprivate:\n\t\n\t// This is FNV-1, see http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash\n\tinline uint64_t hash_string(const char* __s)\n\t{\n\t\tuint64_t hash = 0xcbf29ce484222325ull;\n\t\tfor ( ; *__s; ++__s)\n\t\t{\n\t\t\thash *= 1099511628211ull;\n\t\t\thash ^= *__s;\n\t\t}\n\t\treturn hash;\n\t}\n    \n    \n    inline uint64_t string_checksum(const char * s)\n    {\n        uint64_t c = 0;\n        for ( ; *s; ++s)       \n        {\n            c += *s;\n        }\n        return c;\n    }\n};\n\nclass RefSequenceTable\n{\npublic:\n\t\n\ttypedef std::string Sequence;\n\t\n\tstruct SequenceInfo\n\t{\n\t\tSequenceInfo(uint32_t _order, \n\t\t\t\t\t char* _name, \n\t\t\t\t\t Sequence* _seq) :\n\t\tobservation_order(_order),\n\t\tname(_name),\n\t\tseq(_seq) {}\n\t\tuint32_t observation_order;\n\t\tchar* name;\n\t\tSequence* seq;\n\t};\n\t\n\ttypedef map<string, RefID> IDTable;\n\ttypedef map<RefID, SequenceInfo> InvertedIDTable;\n\ttypedef InvertedIDTable::iterator iterator;\n\ttypedef InvertedIDTable::const_iterator const_iterator;\n\t\n\tRefSequenceTable(bool keep_names, bool keep_seqs = false) : \n\t_next_id(1), \n\t_keep_names(keep_names) {}\n\t\n\t~RefSequenceTable()\n\t{\n\t\tfor (InvertedIDTable::iterator itr = _by_id.begin();\n\t\t\t itr != _by_id.end();\n\t\t\t ++itr)\n\t\t{\n\t\t\tfree(itr->second.name);\n\t\t}\n\t}\n\t\n\tRefID get_id(const string& name,\n\t\t\t\t Sequence* seq)\n\t{\n\t\tif (name.empty())\n\t\t\treturn 0;\n#if ENABLE_THREADS\n        table_lock.lock();\n#endif\n\t\tuint64_t _id = hash_string(name.c_str());\n\t\tpair<InvertedIDTable::iterator, bool> ret = \n\t\t_by_id.insert(make_pair(_id, SequenceInfo(_next_id, NULL, NULL)));\n\t\tif (ret.second == true)\n\t\t{\t\t\t\n\t\t\tchar* _name = NULL;\n\t\t\tif (_keep_names)\n\t\t\t\t_name = strdup(name.c_str());\n\t\t\tret.first->second.name = _name;\n\t\t\tret.first->second.seq\t= seq;\n\t\t\t++_next_id;\n\t\t}\n\t\tassert (_id);\n#if ENABLE_THREADS\n        table_lock.unlock();\n#endif\n\t\treturn _id;\n\t}\n\t\n\t// You must call invert() before using this function\n\tconst char* get_name(RefID ID) const\n\t{\n\t\tInvertedIDTable::const_iterator itr = _by_id.find(ID);\n\t\tif (itr != _by_id.end())\n        {\n            //const SequenceInfo& info = itr->second;\n\t\t\treturn itr->second.name;\n        }\n\t\telse\n        {\n\t\t\treturn NULL;\n        }\n\t}\n\t\n\tSequence* get_seq(RefID ID) const\n\t{\n\t\tInvertedIDTable::const_iterator itr = _by_id.find(ID);\n\t\tif (itr != _by_id.end())\n\t\t\treturn itr->second.seq;\n\t\telse\n\t\t\treturn NULL;\n\t}\n\t\n\tconst SequenceInfo* get_info(RefID ID) const\n\t{\n\t\t\n\t\tInvertedIDTable::const_iterator itr = _by_id.find(ID);\n\t\tif (itr != _by_id.end())\n\t\t{\n\t\t\treturn &(itr->second);\n\t\t}\n\t\telse\n\t\t\treturn NULL;\n\t}\n\t\n\tint observation_order(RefID ID) const\n\t{\n\t\tInvertedIDTable::const_iterator itr = _by_id.find(ID);\n\t\tif (itr != _by_id.end())\n\t\t{\n\t\t\treturn itr->second.observation_order;\n\t\t}\n\t\telse\n\t\t\treturn -1;\n\t}\n    \n    void order_recs_lexicographically() \n    {\n        map<string, RefID> str_to_id;\n        \n        for (InvertedIDTable::iterator i = _by_id.begin(); i != _by_id.end(); ++i)\n        {\n            str_to_id[i->second.name] = i->first;\n            //fprintf(stderr, \"%d: %s\\n\", i->second.observation_order, i->second.name);\n        }\n        \n        size_t new_order = 1;\n        for (map<string, RefID>::iterator i = str_to_id.begin(); i != str_to_id.end(); ++i, ++new_order)\n        {\n            _by_id.find(get_id(i->first, NULL))->second.observation_order = new_order;\n            verbose_msg( \"%lu: %s\\n\", new_order, i->first.c_str());\n        }\n    }\n    \n    void print_rec_ordering()\n    {\n        for (InvertedIDTable::iterator i = _by_id.begin(); i != _by_id.end(); ++i)\n        {\n            verbose_msg( \"%lu: %s\\n\", i->second.observation_order, i->second.name);\n        }\n    }\n\t\n\titerator begin() { return _by_id.begin(); }\n\titerator end() { return _by_id.end(); }\n\t\n\tconst_iterator begin() const { return _by_id.begin(); }\n\tconst_iterator end() const { return _by_id.end(); }\n\t\n\tsize_t size() const { return _by_id.size(); }\n\t\n\tvoid clear()\n\t{\n\t\t//_by_name.clear();\n\t\t_by_id.clear();\n\t}\n\t\nprivate:\n\t\n\t// This is FNV-1, see http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash\n\tinline uint64_t hash_string(const char* __s)\n\t{\n\t\tuint64_t hash = 0xcbf29ce484222325ull;\n\t\tfor ( ; *__s; ++__s)\n\t\t{\n\t\t\thash *= 1099511628211ull;\n\t\t\thash ^= *__s;\n\t\t}\n\t\treturn hash;\n\t}\n\t\n\t//IDTable _by_name;\n\tRefID _next_id;\n\tbool _keep_names;\n\tInvertedIDTable _by_id;\n#if ENABLE_THREADS\n    static boost::mutex table_lock;\n#endif\n};\n\n\nbool hit_insert_id_lt(const ReadHit& h1, const ReadHit& h2);\n\n/******************************************************************************\n The HitFactory abstract class is responsible for returning a single ReadHit \n from an alignment file.\n*******************************************************************************/\nclass HitFactory\n{\npublic:\n    \n\tHitFactory(ReadTable& insert_table, \n\t\t\t   RefSequenceTable& reference_table) : \n\t\t_insert_table(insert_table), \n\t\t_ref_table(reference_table),\n\t\t_num_seq_header_recs(0),\n\t\t_undone_hit_present(false) {}\n\t\n\tHitFactory& operator=(const HitFactory& rhs) \n\t{\n\t\tif (this != &rhs)\n\t\t{\n\t\t\t//_hit_file = rhs._hit_file;\n\t\t\t_insert_table = rhs._insert_table;\n\t\t\t_ref_table = rhs._ref_table;\n\t\t}\n\t\treturn *this;\n\t}\n\tvirtual ~HitFactory() {}\n\t\n\tReadHit create_hit(const string& insert_name, \n\t\t\t\t\t   const string& ref_name,\n\t\t\t\t\t   int left,\n\t\t\t\t\t   const vector<CigarOp>& cigar,\n\t\t\t\t\t   CuffStrand source_strand,\n\t\t\t\t\t   const string& partner_ref,\n\t\t\t\t\t   int partner_pos,\n\t\t\t\t\t   unsigned int  edit_dist,\n\t\t\t\t\t   int num_hits,\n                       float base_mass,\n                       uint32_t sam_flag);\n\t\n\tReadHit create_hit(const string& insert_name, \n\t\t\t\t\t   const string& ref_name,\n\t\t\t\t\t   uint32_t left,\n\t\t\t\t\t   uint32_t read_len,\n\t\t\t\t\t   CuffStrand source_strand,\n\t\t\t\t\t   const string& partner_ref,\n\t\t\t\t\t   int partner_pos,\n\t\t\t\t\t   unsigned int  edit_dist,\n\t\t\t\t\t   int num_hits,\n                       float base_mass,\n                       uint32_t sam_flag);\n\t\n\tvirtual void reset() = 0;\n\t\n\tvoid undo_hit()\n\t{\n\t\tif(_undone_hit_present)\n\t\t\tthrow \"undo_hit can only back up one hit\";\n\t\t_undone_hit_present=true;\n\t}\n\t\n\tbool next_hit(ReadHit &result)\n\t{\n\t\tif(_undone_hit_present)\n\t\t{\n\t\t\t_undone_hit_present=false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(!read_next_hit(_last_hit))\n\t\t\t\treturn false;\n\t\t}\n\t\tresult=_last_hit;\n\t\treturn true;\n\t}\n\t\n\tvirtual bool records_remain() const = 0;\n\t\n\tRefSequenceTable& ref_table() { return _ref_table; }\n\t\n\t//FILE* hit_file() { return _hit_file; }\n\t\n    virtual bool inspect_header() = 0;\n    \n    const ReadGroupProperties& read_group_properties()\n    {\n        return _rg_props;\n    }\n    \nprotected:\n    \n\tvirtual bool read_next_hit(ReadHit &result) = 0;\n\n    bool parse_header_string(const string& header_rec,\n                             ReadGroupProperties& rg_props);\n    \n\tvoid parse_header_lines(const string& headers,\n\t\t\t\t\t\t\tReadGroupProperties& rg_props);\n\n    void finalize_rg_props();\n    \n    // TODO: We want to keep a collection of these, indexed by RG ID.  See #180\n    ReadGroupProperties _rg_props; \n    \nprivate:\n\n    \n\tReadTable& _insert_table;\n\tRefSequenceTable& _ref_table;\n    uint32_t _num_seq_header_recs;\n\tbool _undone_hit_present;\n\tReadHit _last_hit;\n};\n\n/******************************************************************************\n SAMHitFactory turns SAM alignments into ReadHits\n*******************************************************************************/\nclass SAMHitFactory : public HitFactory\n{\npublic:\n\tSAMHitFactory(const string& hit_file_name, \n\t\t\t\t  ReadTable& insert_table, \n\t\t\t\t  RefSequenceTable& reference_table) : \n\t\tHitFactory(insert_table, reference_table), \n\t\t_line_num(0)\n\t{\n\t\t_hit_file = fopen(hit_file_name.c_str(), \"r\");\n\t\tif (_hit_file == NULL)\n\t\t{\n\t\t\tthrow std::runtime_error(\"Error: could not open file for reading\");\n\t\t}\n        \n        if (inspect_header() == false)\n        {\n            throw std::runtime_error(\"Error: could not parse SAM header\");\n        }\n        \n        // Override header-inferred read group properities with whatever\n        // the user supplied.\n        if (global_read_properties != NULL)\n        {\n            _rg_props = *global_read_properties;\n        }\n\t}\n\t\n\t~SAMHitFactory() \n\t{\n\t\tif (_hit_file)\n\t\t{\n\t\t\tfclose(_hit_file);\n\t\t}\n\t}\n\t\n\tvoid reset() { rewind(_hit_file); }\n\t\n\tbool records_remain() const { return !feof(_hit_file); }\n\t\n\tbool read_next_hit(ReadHit& buf);\n    \n    bool inspect_header();\n    \nprivate:\n\tstatic const size_t _hit_buf_max_sz = 10 * 1024;\n\tchar _hit_buf[_hit_buf_max_sz];\n\tint _line_num;\n\t\n\tFILE* _hit_file;\n};\n\nclass BAMHitFactory : public HitFactory\n{\npublic:\n\tBAMHitFactory(ReadTable& insert_table,\n\t\t\t\t  RefSequenceTable& reference_table) :\n\tHitFactory(insert_table, reference_table)\n\t{}\n\n\tbool get_hit_from_bam1t(const bam1_t* hit_buf,\n\t\t\t\t\t\t\tconst bam_hdr_t* header,\n\t\t\t\t\t\t\tReadHit& bh);\n\n\tbool records_remain() const\n\t{\n\t\treturn !_eof_encountered;\n\t}\n\n protected:\n\tint64_t _beginning;\n    bool _eof_encountered;\n};\n\n#ifndef HAVE_HTSLIB\n\n/******************************************************************************\n SamtoolsHitFactory turns SAM alignments into ReadHits\n *******************************************************************************/\nclass SamtoolsHitFactory : public BAMHitFactory\n{\npublic:\n    SamtoolsHitFactory(const string& hit_file_name,\n\t\t\t\t  ReadTable& insert_table, \n\t\t\t\t  RefSequenceTable& reference_table) : \n\tBAMHitFactory(insert_table, reference_table)\n\t{\n\t\t_hit_file = samopen(hit_file_name.c_str(), \"rb\", 0);\n        \n        memset(&_next_hit, 0, sizeof(_next_hit));\n        \n\t\tif (_hit_file == NULL || _hit_file->header == NULL) \n\t\t{\n\t\t\tthrow std::runtime_error(\"Fail to open BAM file\");\n\t\t}\n\t\t\n\t\t_beginning = bgzf_tell(_hit_file->x.bam);\n        _eof_encountered = false;\n        \n        if (inspect_header() == false)\n        {\n            throw std::runtime_error(\"Error: could not parse BAM header\");\n        }\n        \n        // Override header-inferred read group properities with whatever\n        // the user supplied.\n        if (global_read_properties != NULL)\n        {\n            _rg_props = *global_read_properties;\n        }\n\t}\t\n\t\n\t~SamtoolsHitFactory()\n\t{\n\t\tif (_hit_file)\n\t\t{\n\t\t\tsamclose(_hit_file);\n\t\t}\n\t}\n\t\n\tvoid reset() \n\t{ \n\t\tif (_hit_file && _hit_file->x.bam)\n\t\t{\n\t\t\tbgzf_seek(_hit_file->x.bam, _beginning, SEEK_SET);\n            _eof_encountered = false;\n\t\t}\n\t}\n\t\n\t\n\tbool read_next_hit(ReadHit& bh);\n    \n    bool inspect_header();\n\t\nprivate:\n\tsamfile_t* _hit_file; \n\tbam1_t _next_hit; \n};\n\n#else\n\n/******************************************************************************\n HTSHitFactory uses htslib to turn SAM/BAM/CRAM alignments into ReadHits\n *******************************************************************************/\n\nclass HTSHitFactory : public BAMHitFactory\n{\npublic:\n    HTSHitFactory(const string& hit_file_name,\n\t\t\t\t  ReadTable& insert_table,\n\t\t\t\t  RefSequenceTable& reference_table) :\n\tBAMHitFactory(insert_table, reference_table),\n\t_hit_file_name(hit_file_name)\n\t{\n\t\t_hit_file = hts_open(hit_file_name.c_str(), \"r\");\n\t\tif(!_hit_file)\n\t\t\tthrow std::runtime_error(\"Failed to open SAM/BAM/CRAM file \" + hit_file_name);\n\t\t_file_header = sam_hdr_read(_hit_file);\n\t\tif(!_file_header)\n\t\t{\n\t\t\thts_close(_hit_file);\n\t\t\tthrow std::runtime_error(\"Failed to read header from \" + hit_file_name);\n\t\t}\n\t\t_next_hit = bam_init1();\n\t\tif(!_next_hit)\n\t\t\tthrow std::runtime_error(\"Failed to allocate SAM record\");\n\t\t_eof_encountered = false;\n\n\t\tif (inspect_header() == false)\n        {\n            throw std::runtime_error(\"Error: could not parse BAM header\");\n        }\n\n        // Override header-inferred read group properities with whatever\n        // the user supplied.\n        if (global_read_properties != NULL)\n        {\n            _rg_props = *global_read_properties;\n        }\n\t}\n\n\t~HTSHitFactory()\n\t{\n\t\tif(_next_hit)\n\t\t\tbam_destroy1(_next_hit);\n\t\tif(_file_header)\n\t\t\tbam_hdr_destroy(_file_header);\n\t\tif(_hit_file)\n\t\t\thts_close(_hit_file);\n\t}\n\n\tvoid reset()\n\t{\n\t\tif(_hit_file)\n\t\t{\n\t\t\thts_close(_hit_file);\n\t\t\t_hit_file = hts_open(_hit_file_name.c_str(), \"r\");\n\t\t\tif(!_hit_file)\n\t\t\t\tthrow std::runtime_error(\"Failed to reopen SAM/BAM/CRAM file \" + _hit_file_name);\n\t\t\tbam_hdr_t* reread_header = sam_hdr_read(_hit_file);\n\t\t\tif(!reread_header)\n\t\t\t\tthrow std::runtime_error(\"Failed to re-read header from \" + _hit_file_name);\n\t\t\t// Keep the old header:\n\t\t\tbam_hdr_destroy(reread_header);\n\t\t\t_eof_encountered = false;\n\t\t}\n\t}\n\n\tbool read_next_hit(ReadHit& buf);\n\n\tbool inspect_header();\n\n private:\n\thtsFile* _hit_file;\n\tbam_hdr_t* _file_header;\n\tbam1_t* _next_hit;\n\tstd::string _hit_file_name;\n};\n\n#endif\n\nclass AbundanceGroup;\n    \n/******************************************************************************\n BAMHitFactory turns SAM alignments into ReadHits\n *******************************************************************************/\nclass PrecomputedExpressionHitFactory : public HitFactory\n{\npublic:\n    PrecomputedExpressionHitFactory(const string& expression_file_name,\n                                    ReadTable& insert_table,\n                                    RefSequenceTable& reference_table) :\n    HitFactory(insert_table, reference_table), _expression_file_name(expression_file_name), _ifs(expression_file_name.c_str()),\n    _ia(boost::shared_ptr<boost::archive::binary_iarchive>(new boost::archive::binary_iarchive(_ifs)))\n    {\n        load_count_tables(expression_file_name);\n        \n        if (inspect_header() == false)\n        {\n            throw std::runtime_error(\"Error: could not parse CXB header\");\n        }\n        \n        // Override header-inferred read group properities with whatever\n        // the user supplied.\n        if (global_read_properties != NULL)\n        {\n            _rg_props = *global_read_properties;\n        }\n        \n        load_checked_parameters(expression_file_name);\n        \n        //map<string, AbundanceGroup> single_sample_tracking;\n        \n        _num_loci = 0;\n        *_ia >> _num_loci;\n        \n        _curr_locus_idx = 0;\n        _last_locus_id = -1;\n    }\n    \n    ~PrecomputedExpressionHitFactory()\n    {\n        \n    }\n    \n    bool records_remain() const\n    {\n        return false;\n    }\n    \n    void reset()\n    {\n        _ifs.clear() ;\n        _ifs.seekg(0, ios::beg);\n        _ia = boost::shared_ptr<boost::archive::binary_iarchive>(new boost::archive::binary_iarchive(_ifs));\n        size_t num_loci = 0;\n        *_ia >> num_loci;\n        _last_locus_id = -1;\n        _curr_locus_idx = 0;\n        _curr_ab_groups.clear();\n    }\n    \n\tbool read_next_hit(ReadHit& buf);\n    \n    bool inspect_header();\n    \n    boost::shared_ptr<const AbundanceGroup> next_locus(int locus_id, bool cache_locus);\n    \n    boost::shared_ptr<const AbundanceGroup> get_abundance_for_locus(int locus_id);\n    void clear_abundance_for_locus(int locus_id);\n    \n    double get_compat_mass(int locus_id)\n    {\n       map<int, double >::iterator i = compat_mass.find(locus_id);\n       if (i != compat_mass.end())\n       {\n           return i->second;\n       }\n       else\n       {\n           return 0;\n       }\n    }\n\n    double get_total_mass(int locus_id)\n    {\n        map<int, double >::iterator i = total_mass.find(locus_id);\n        if (i != total_mass.end())\n        {\n            return i->second;\n        }\n        else\n        {\n            return 0;\n        }\n    }\n\n    \nprivate:\n    \n    void load_count_tables(const string& expression_file_name);\n    void load_checked_parameters(const string& expression_file_name);\n    \n    //map<int, boost::shared_ptr<const AbundanceGroup> > ab_group_table;\n    size_t _num_loci;\n    size_t _curr_locus_idx;\n    int _last_locus_id;\n    std::ifstream _ifs;\n    string _expression_file_name;\n    boost::shared_ptr<boost::archive::binary_iarchive> _ia;\n    map<int, double> compat_mass;\n    map<int, double> total_mass;\n    map<int, boost::shared_ptr<const AbundanceGroup> > _curr_ab_groups;\n    \n    boost::shared_ptr<ReadGroupProperties> _cached_rg_props;\n    \n#if ENABLE_THREADS\n    boost::mutex _factory_lock;\n#endif\n};\n    \n    \n// Forward declaration of BundleFactory, because MateHit will need a pointer\n// back to the Factory that created.  Ultimately, we should replace this\n// with a pointer back to the ReadGroupProperty object corresponding to each \n// MateHit.  That, however, requires that we link fragment length distributions\n// and bias models, etc, with each read group, and that's more than we can \n// afford to implement right now.\n\n/*******************************************************************************\n MateHit is a class that encapsulates a paired-end alignment as a single object.\n MateHits can be \"open\" when one hit has been read from a stream of individual\n read alignments, but the other hasn't.  A \"closed\" MateHit is one where either\n both read alignments have been installed in the MateHit, or one read hit has,\n but the other will never come (i.e. singletons)\n*******************************************************************************/\nclass MateHit\n{\npublic:\n    MateHit() : \n    _refid(0), \n    _left_alignment(NULL),\n    _right_alignment(NULL),\n    _collapse_mass(0.0),\n    _is_mapped(false){}\n    \n\tMateHit(boost::shared_ptr<ReadGroupProperties const> rg_props,\n            RefID refid, \n\t\t\tconst ReadHit* left_alignment, \n\t\t\tconst ReadHit* right_alignment) : \n    _rg_props(rg_props),\n\t_refid(refid), \n\t_left_alignment(left_alignment),\n\t_right_alignment(right_alignment),\n\t_collapse_mass(0.0),\n\t_is_mapped(false)\n\t{\n\t\t//_expected_inner_dist = min(genomic_inner_dist(), _expected_inner_dist);\n\t}\n\t~MateHit()\n\t{\n\t\t//fprintf(stderr, \"Killing hit %lx\\n\",this);\n\t}\n\n\t//bool closed() {return _closed;}\n\t\n    boost::shared_ptr<ReadGroupProperties const> read_group_props() const { return _rg_props; }\n    \n\tconst ReadHit* left_alignment() const {return _left_alignment;}\n\tvoid left_alignment(const ReadHit* left_alignment) \n\t{\n\t\t_left_alignment = left_alignment;\n\t}\n\t\n\tconst ReadHit* right_alignment() const {return _right_alignment;}\t\t\t\t\t\n\tvoid right_alignment(const ReadHit* right_alignment)  \n\t{\n\t\t_right_alignment = right_alignment;\n\t}\n\t\n\tbool is_mapped() const {return _is_mapped;}\t\t\t\t\t\n\tvoid is_mapped(bool mapped) \n\t{ \n\t\t_is_mapped = mapped; \n\t}\n\t\n\tint num_hits() const \n\t{\n\t\tassert(_left_alignment);\n\t\treturn _left_alignment->num_hits();\n\t}\n\t\n\tbool is_multi() const \n\t{\n\t\treturn num_hits() > 1;\n\t}\n\t\t\n\tbool is_pair() const\n\t{\n\t\treturn (_left_alignment && _right_alignment);\n\t}\n\n\tint left() const \n\t{\n\t\tif (_right_alignment && _left_alignment)\n\t\t{\n\t\t\treturn min(_right_alignment->left(),_left_alignment->left());\n\t\t}\n\t\tif (_left_alignment)\n\t\t\treturn _left_alignment->left();\n\t\telse if (_right_alignment)\n\t\t\treturn _right_alignment->left(); \n\t\treturn -1;\n\t}\n\t\n\tint right() const \n\t{\n\t\tif (_right_alignment && _left_alignment)\n\t\t{\n\t\t\treturn max(_right_alignment->right(),_left_alignment->right());\n\t\t}\n\t\tif (_right_alignment)\n\t\t\treturn _right_alignment->right();\n\t\telse if (_left_alignment)\n\t\t\treturn _left_alignment->right(); \n\t\treturn -1;\n\t}\n\t\n\tCuffStrand strand() const \n\t{\n\t\tCuffStrand left_strand = CUFF_STRAND_UNKNOWN;\n\t\tCuffStrand right_strand = CUFF_STRAND_UNKNOWN;\n\t\tif (_left_alignment)\n\t\t{\n\t\t\tleft_strand = _left_alignment->source_strand();\n\t\t}\n\t\tif (_right_alignment)\n\t\t{\n\t\t\tright_strand = _right_alignment->source_strand();\n\t\t\t//assert ( s != CUFF_STRAND_UNKNOWN ? s == r : true);\n\t\t}\n\t\tassert (left_strand == right_strand || \n\t\t\t\tleft_strand == CUFF_STRAND_UNKNOWN || \n\t\t\t\tright_strand == CUFF_STRAND_UNKNOWN);\n\t\t\n\t\treturn max(left_strand, right_strand);\n\t}\n\t\n\t\n\tbool contains_splice() const\n\t{\n\t\tif (_right_alignment)\n\t\t\treturn (_left_alignment->contains_splice() || _right_alignment->contains_splice());\n\t\treturn (_left_alignment->contains_splice());\n\t}\n\t\n\tInsertID insert_id() const\n\t{\n\t\tif (_left_alignment) return _left_alignment->insert_id();\n\t\tif (_right_alignment) return _right_alignment->insert_id();\n\t\treturn 0;\n\t}\n\t\n\tRefID ref_id() const { return _refid; }\n\t\n\tint genomic_inner_dist() const \n\t{\n\t\tif (_left_alignment && _right_alignment)\n\t\t{\n\t\t\treturn _right_alignment->left() - _left_alignment->right();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\t\treturn -1;\n\t}\n\t\n\tpair<int,int> genomic_outer_span() const\n\t{\n\t\tif (_left_alignment && _right_alignment)\n\t\t{\n\t\t\treturn make_pair(left(),\n\t\t\t\t\t\t\t right() - 1);\n\t\t}\n\n\t\treturn make_pair(-1,-1);\n\t}\t\n\t\n\tpair<int,int> genomic_inner_span() const \n\t{\n\t\tif (_left_alignment && _right_alignment)\n\t\t{\n\t\t\treturn make_pair(_left_alignment->right(),\n\t\t\t\t\t\t\t _right_alignment->left() - 1);\n\t\t}\n\n\t\treturn make_pair(-1,-1);\n\t}\n\t\n\t// MRT is incorrect and not added to rg_props until after inspect_map\n    // We are ignoring the mass reported by the ReadHits and re-calculating based on multi-hits\n\tdouble mass() const\n\t{\n        double base_mass = 1.0;\n\n        if (is_multi())\n\t\t{\n\t\t\tboost::shared_ptr<MultiReadTable> mrt = _rg_props->multi_read_table();\n\t\t\tif (mrt)\n\t\t\t\treturn mrt->get_mass(*this);\n\t\t\telse\n\t\t\t\treturn base_mass/num_hits();\n\t\t}\n\t\treturn base_mass;\n\t}\n    \n\tdouble internal_scale_mass() const\n\t{\n       \tdouble m = mass();\n        m *= 1.0 / _rg_props->internal_scale_factor();\n        \n        return m;\n\t}\n\t\n\tunsigned int  edit_dist() const\n\t{\n\t\tunsigned int edits = 0;\n\t\tif (_left_alignment)\n\t\t\tedits += _left_alignment->edit_dist();\n\t\tif (_right_alignment)\n\t\t\tedits += _right_alignment->edit_dist();\n\t\treturn edits;\n\t}\n\t\n\tdouble collapse_mass() const { return _collapse_mass; }\n\tvoid collapse_mass(double m) { _collapse_mass = m; }\n\tvoid incr_collapse_mass(double incr) { _collapse_mass += incr; }\n\t\nprivate:\n\t\n    boost::shared_ptr<ReadGroupProperties const> _rg_props;\n\tRefID _refid;\n\tconst ReadHit* _left_alignment;\n\tconst ReadHit* _right_alignment;\n\tdouble _collapse_mass;\n\tbool _is_mapped;\n\t//bool _closed;\n};\n\nbool mate_hit_lt(const MateHit& lhs, const MateHit& rhs);\n\nbool hits_eq_mod_id(const ReadHit& lhs, const ReadHit& rhs);\n\nbool hits_eq_non_multi(const MateHit& lhs, const MateHit& rhs);\nbool hits_eq_non_multi_non_replicate(const MateHit& lhs, const MateHit& rhs);\n\nbool hits_equals(const MateHit& lhs, const MateHit& rhs);\n\nbool has_no_collapse_mass(const MateHit& hit);\n\n// Assumes hits are sorted by mate_hit_lt\nvoid collapse_hits(const vector<MateHit>& hits,\n\t\t\t\t   vector<MateHit>& non_redundant);\n\nvoid normalize_counts(std::vector<boost::shared_ptr<ReadGroupProperties> > & all_read_groups);\n\nHitFactory* createSamHitFactory(const string& hit_file_name, ReadTable& it, RefSequenceTable& rt);\n\n#endif\n"
  },
  {
    "path": "src/jensen_shannon.cpp",
    "content": "/*\n *  jensen_shannon.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 8/30/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <numeric>\n\n#include \"jensen_shannon.h\"\n\nusing namespace std;\nusing namespace boost;\n\n\ndouble entropy(const Eigen::VectorXd& p)\n{\n\tdouble e = 0;  \n\tfor (size_t i = 0; i < p.size(); ++i)\n\t{\n\t\tdouble P = p[i];\n        if (P != 0.0)\n        {\n            e -= (P * log(P));\n        }\n\t}\n    if (e < 0)\n        e = 0;\n\treturn e;\n}\n\ndouble jensen_shannon_distance(std::vector<Eigen::VectorXd>& sample_kappas)\n{\n\tassert (sample_kappas.size() > 1);\n\t\n\tsize_t kappa_length = 0;\n\tfor (size_t i = 1; i < sample_kappas.size(); ++i)\n\t{\n\t\tassert (sample_kappas[i].size() == sample_kappas[i-1].size());\n\t\tkappa_length = sample_kappas[i].size();\n\t}\n\t\n    Eigen::VectorXd avg_kappas = Eigen::VectorXd::Zero(kappa_length);\n\tfor (size_t i = 0; i < sample_kappas.size(); ++i)\n\t{\n\t\t//cout << \"kappa \" << i<< \" \"<< sample_kappas[i] << endl;\n\t\tavg_kappas += sample_kappas[i];\n\t}\n\tavg_kappas /= sample_kappas.size();\n\t//cout << avg_kappas << endl;\n\t\n\tdouble avg_entropy = 0.0;\n\tfor (size_t i = 0; i < sample_kappas.size(); ++i)\n\t{\n\t\tavg_entropy += entropy(sample_kappas[i]);\n\t}\n\tavg_entropy /= sample_kappas.size();\n\t//cout << avg_entropy << endl;\n\t\n\tdouble entropy_avg = entropy(avg_kappas);\n\t\n\tdouble js = entropy_avg - avg_entropy;\n    if (js < 0) // can happen due to underflow or rounding errors.\n        return 0;\n\treturn sqrt(js);\n}\n\nvoid jensen_shannon_gradient(vector<Eigen::VectorXd>& sample_kappas,\n\t\t\t\t\t\t\t double js,\n\t\t\t\t\t\t\t ublas::vector<double>& gradient)\n{\n\tassert (sample_kappas.size() > 1);\n\tsize_t kappa_length = sample_kappas.front().size();\n\tfor (size_t i = 1; i < sample_kappas.size(); ++i)\n\t{\n\t\tassert (sample_kappas[i].size() == sample_kappas[i-1].size());\n\t\tkappa_length = sample_kappas[i].size();\n\t}\n\t\n\tif (kappa_length == 0)\n\t\treturn;\n\t\n\tgradient = ublas::zero_vector<double>(sample_kappas.size() * kappa_length);\n\tfor (size_t i = 0; i < sample_kappas.size(); ++i)\n\t{\n\t\tfor (size_t k = 0; k < kappa_length; ++k)\n\t\t{\n            assert (!isinf(sample_kappas[i](k)) && !isnan(sample_kappas[i](k)));\n\t\t\tgradient(i*kappa_length + k) = sample_kappas[i](k);\n\t\t}\n\t}\n\t\n\t//cout << \"t1: \" << gradient<< endl;\n\t\n    ublas::vector<double> p_bar = ublas::zero_vector<double>(kappa_length);\n\tfor (size_t i = 0; i < sample_kappas.size(); ++i)\n\t{\n\t\tfor (size_t j = 0; j < sample_kappas[i].size(); ++j)\n        {\n            p_bar[j] += sample_kappas[i](j);   \n        }\n\t}\n\tp_bar /= sample_kappas.size();\n\t\n\t\n\t//cout << \"t2 \" << denoms << endl;\n\t\n\tfor (size_t i = 0; i < sample_kappas.size(); ++i)\n\t{\n\t\tfor (size_t k = 0; k < kappa_length; ++k)\n\t\t{\n\t\t\tif (p_bar(k) == 0.0 || gradient(i*kappa_length + k) == 0.0 || js == 0.0)\n\t\t\t{\n\t\t\t\tgradient(i*kappa_length + k) = 0.0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n                double alt_grad = 0.0;\n                double m = 2.0;\n                alt_grad = js / (2.0 * m);\n                double A = log(gradient(i*kappa_length + k)) + (1.0 / gradient(i*kappa_length + k));\n                double B = log(p_bar[k]) + (1.0 / p_bar[k]);\n                alt_grad *= (A - B);\n                \n\t\t\t\tgradient(i*kappa_length + k) /= p_bar(k);\n\t\t\t\tgradient(i*kappa_length + k) = log(gradient(i*kappa_length + k));\n\t\t\t\tgradient(i*kappa_length + k) /= sample_kappas.size(); // m in paper notation\n\t\t\t\tgradient(i*kappa_length + k) *= (1.0/(2.0 * js)); // This is supposed to use the square root of the distance (it's not a typo)\n\t\t\t\t\n                double curr_grad = gradient(i*kappa_length + k);\n                \n                assert (!isinf(curr_grad) && !isnan(curr_grad));\n                //fprintf(stderr, \"Curr gradient: %lg, alternate gradient %lg\\n\", curr_grad, alt_grad);\n            \n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid make_js_covariance_matrix(vector<ublas::matrix<double> >& kappa_covariances,\n\t\t\t\t\t\t\t   ublas::matrix<double>& js_covariance)\n{\n\tsize_t kappa_length = 0;\n\tfor (size_t i = 1; i < kappa_covariances.size(); ++i)\n\t{\n\t\tassert (kappa_covariances[i].size1() == kappa_covariances[i-1].size1());\n\t\tassert (kappa_covariances[i].size2() == kappa_covariances[i-1].size2());\n\t\t\n\t\tkappa_length = kappa_covariances[i].size1();\n\t}\n\t\n\tif (kappa_length == 0)\n\t\treturn;\n\t\n\tjs_covariance = ublas::zero_matrix<double>(kappa_covariances.size() * kappa_length,\n\t\t\t\t\t\t\t\t\t\t\t   kappa_covariances.size() * kappa_length);\n\tfor (size_t i = 0; i < kappa_covariances.size(); ++i)\n\t{\n\t\tfor (size_t j = 0; j < kappa_length; ++j)\n\t\t{\n\t\t\tfor (size_t k = 0; k < kappa_length; ++k)\n\t\t\t{\n\t\t\t\tjs_covariance(i*kappa_length + j, i*kappa_length + k) = \n\t\t\t\tkappa_covariances[i](j,k);\n                assert (!isinf(js_covariance(i*kappa_length + j, i*kappa_length + k) && ! isnan(js_covariance(i*kappa_length + j, i*kappa_length + k))));\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/jensen_shannon.h",
    "content": "/*\n *  jensen_shannon.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 8/30/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/matrix_proxy.hpp>\n#include <boost/numeric/ublas/vector.hpp>\n#include <boost/numeric/ublas/vector_proxy.hpp>\n#include <boost/numeric/ublas/io.hpp>\n\n#include <vector>\n#include <Eigen/Dense>\n\nnamespace ublas = boost::numeric::ublas;\n\ndouble entropy(const ublas::vector<double>& p);\n\ndouble jensen_shannon_distance(std::vector<Eigen::VectorXd>& sample_kappas);\n\nvoid jensen_shannon_gradient(std::vector<Eigen::VectorXd>& sample_kappas,\n\t\t\t\t\t\t\t double js,\n\t\t\t\t\t\t\t ublas::vector<double>& gradient);\n\nvoid make_js_covariance_matrix(std::vector<ublas::matrix<double> >& kappa_covariances,\n\t\t\t\t\t\t\t   ublas::matrix<double>& js_covariance);\n"
  },
  {
    "path": "src/lemon/bfs.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BFS_H\n#define LEMON_BFS_H\n\n///\\ingroup search\n///\\file\n///\\brief Bfs algorithm.\n\n#include <lemon/list_graph.h>\n#include <lemon/graph_utils.h>\n#include <lemon/bits/path_dump.h>\n#include <lemon/bits/invalid.h>\n#include <lemon/error.h>\n#include <lemon/maps.h>\n\nnamespace lemon {\n\n\n  \n  ///Default traits class of Bfs class.\n\n  ///Default traits class of Bfs class.\n  ///\\param GR Graph type.\n  template<class GR>\n  struct BfsDefaultTraits\n  {\n    ///The graph type the algorithm runs on. \n    typedef GR Graph;\n    ///\\brief The type of the map that stores the last\n    ///edges of the shortest paths.\n    /// \n    ///The type of the map that stores the last\n    ///edges of the shortest paths.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\n    typedef typename Graph::template NodeMap<typename GR::Edge> PredMap;\n    ///Instantiates a PredMap.\n \n    ///This function instantiates a \\ref PredMap. \n    ///\\param G is the graph, to which we would like to define the PredMap.\n    ///\\todo The graph alone may be insufficient to initialize\n    static PredMap *createPredMap(const GR &G) \n    {\n      return new PredMap(G);\n    }\n    ///The type of the map that indicates which nodes are processed.\n \n    ///The type of the map that indicates which nodes are processed.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\\todo named parameter to set this type, function to read and write.\n    typedef NullMap<typename Graph::Node,bool> ProcessedMap;\n    ///Instantiates a ProcessedMap.\n \n    ///This function instantiates a \\ref ProcessedMap. \n    ///\\param g is the graph, to which\n    ///we would like to define the \\ref ProcessedMap\n#ifdef DOXYGEN\n    static ProcessedMap *createProcessedMap(const GR &g)\n#else\n    static ProcessedMap *createProcessedMap(const GR &)\n#endif\n    {\n      return new ProcessedMap();\n    }\n    ///The type of the map that indicates which nodes are reached.\n \n    ///The type of the map that indicates which nodes are reached.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\\todo named parameter to set this type, function to read and write.\n    typedef typename Graph::template NodeMap<bool> ReachedMap;\n    ///Instantiates a ReachedMap.\n \n    ///This function instantiates a \\ref ReachedMap. \n    ///\\param G is the graph, to which\n    ///we would like to define the \\ref ReachedMap.\n    static ReachedMap *createReachedMap(const GR &G)\n    {\n      return new ReachedMap(G);\n    }\n    ///The type of the map that stores the dists of the nodes.\n \n    ///The type of the map that stores the dists of the nodes.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\n    typedef typename Graph::template NodeMap<int> DistMap;\n    ///Instantiates a DistMap.\n \n    ///This function instantiates a \\ref DistMap. \n    ///\\param G is the graph, to which we would like to define the \\ref DistMap\n    static DistMap *createDistMap(const GR &G)\n    {\n      return new DistMap(G);\n    }\n  };\n  \n  ///%BFS algorithm class.\n  \n  ///\\ingroup search\n  ///This class provides an efficient implementation of the %BFS algorithm.\n  ///\n  ///\\param GR The graph type the algorithm runs on. The default value is\n  ///\\ref ListGraph. The value of GR is not used directly by Bfs, it\n  ///is only passed to \\ref BfsDefaultTraits.\n  ///\\param TR Traits class to set various data types used by the algorithm.\n  ///The default traits class is\n  ///\\ref BfsDefaultTraits \"BfsDefaultTraits<GR>\".\n  ///See \\ref BfsDefaultTraits for the documentation of\n  ///a Bfs traits class.\n  ///\n  ///\\author Alpar Juttner\n\n#ifdef DOXYGEN\n  template <typename GR,\n\t    typename TR>\n#else\n  template <typename GR=ListGraph,\n\t    typename TR=BfsDefaultTraits<GR> >\n#endif\n  class Bfs {\n  public:\n    /**\n     * \\brief \\ref Exception for uninitialized parameters.\n     *\n     * This error represents problems in the initialization\n     * of the parameters of the algorithms.\n     */\n    class UninitializedParameter : public lemon::UninitializedParameter {\n    public:\n      virtual const char* what() const throw() {\n\treturn \"lemon::Bfs::UninitializedParameter\";\n      }\n    };\n\n    typedef TR Traits;\n    ///The type of the underlying graph.\n    typedef typename TR::Graph Graph;\n    \n    ///\\brief The type of the map that stores the last\n    ///edges of the shortest paths.\n    typedef typename TR::PredMap PredMap;\n    ///The type of the map indicating which nodes are reached.\n    typedef typename TR::ReachedMap ReachedMap;\n    ///The type of the map indicating which nodes are processed.\n    typedef typename TR::ProcessedMap ProcessedMap;\n    ///The type of the map that stores the dists of the nodes.\n    typedef typename TR::DistMap DistMap;\n  private:\n\n    typedef typename Graph::Node Node;\n    typedef typename Graph::NodeIt NodeIt;\n    typedef typename Graph::Edge Edge;\n    typedef typename Graph::OutEdgeIt OutEdgeIt;\n\n    /// Pointer to the underlying graph.\n    const Graph *G;\n    ///Pointer to the map of predecessors edges.\n    PredMap *_pred;\n    ///Indicates if \\ref _pred is locally allocated (\\c true) or not.\n    bool local_pred;\n    ///Pointer to the map of distances.\n    DistMap *_dist;\n    ///Indicates if \\ref _dist is locally allocated (\\c true) or not.\n    bool local_dist;\n    ///Pointer to the map of reached status of the nodes.\n    ReachedMap *_reached;\n    ///Indicates if \\ref _reached is locally allocated (\\c true) or not.\n    bool local_reached;\n    ///Pointer to the map of processed status of the nodes.\n    ProcessedMap *_processed;\n    ///Indicates if \\ref _processed is locally allocated (\\c true) or not.\n    bool local_processed;\n\n    std::vector<typename Graph::Node> _queue;\n    int _queue_head,_queue_tail,_queue_next_dist;\n    int _curr_dist;\n\n    ///Creates the maps if necessary.\n    \n    ///\\todo Better memory allocation (instead of new).\n    void create_maps() \n    {\n      if(!_pred) {\n\tlocal_pred = true;\n\t_pred = Traits::createPredMap(*G);\n      }\n      if(!_dist) {\n\tlocal_dist = true;\n\t_dist = Traits::createDistMap(*G);\n      }\n      if(!_reached) {\n\tlocal_reached = true;\n\t_reached = Traits::createReachedMap(*G);\n      }\n      if(!_processed) {\n\tlocal_processed = true;\n\t_processed = Traits::createProcessedMap(*G);\n      }\n    }\n\n  protected:\n    \n    Bfs() {}\n    \n  public:\n \n    typedef Bfs Create;\n\n    ///\\name Named template parameters\n\n    ///@{\n\n    template <class T>\n    struct DefPredMapTraits : public Traits {\n      typedef T PredMap;\n      static PredMap *createPredMap(const Graph &) \n      {\n\tthrow UninitializedParameter();\n      }\n    };\n    ///\\brief \\ref named-templ-param \"Named parameter\" for setting\n    ///PredMap type\n    ///\n    ///\\ref named-templ-param \"Named parameter\" for setting PredMap type\n    ///\n    template <class T>\n    struct DefPredMap : public Bfs< Graph, DefPredMapTraits<T> > { \n      typedef Bfs< Graph, DefPredMapTraits<T> > Create;\n    };\n    \n    template <class T>\n    struct DefDistMapTraits : public Traits {\n      typedef T DistMap;\n      static DistMap *createDistMap(const Graph &) \n      {\n\tthrow UninitializedParameter();\n      }\n    };\n    ///\\brief \\ref named-templ-param \"Named parameter\" for setting\n    ///DistMap type\n    ///\n    ///\\ref named-templ-param \"Named parameter\" for setting DistMap type\n    ///\n    template <class T>\n    struct DefDistMap : public Bfs< Graph, DefDistMapTraits<T> > { \n      typedef Bfs< Graph, DefDistMapTraits<T> > Create;\n    };\n    \n    template <class T>\n    struct DefReachedMapTraits : public Traits {\n      typedef T ReachedMap;\n      static ReachedMap *createReachedMap(const Graph &) \n      {\n\tthrow UninitializedParameter();\n      }\n    };\n    ///\\brief \\ref named-templ-param \"Named parameter\" for setting\n    ///ReachedMap type\n    ///\n    ///\\ref named-templ-param \"Named parameter\" for setting ReachedMap type\n    ///\n    template <class T>\n    struct DefReachedMap : public Bfs< Graph, DefReachedMapTraits<T> > { \n      typedef Bfs< Graph, DefReachedMapTraits<T> > Create;\n    };\n    \n    template <class T>\n    struct DefProcessedMapTraits : public Traits {\n      typedef T ProcessedMap;\n      static ProcessedMap *createProcessedMap(const Graph &) \n      {\n\tthrow UninitializedParameter();\n      }\n    };\n    ///\\brief \\ref named-templ-param \"Named parameter\" for setting\n    ///ProcessedMap type\n    ///\n    ///\\ref named-templ-param \"Named parameter\" for setting ProcessedMap type\n    ///\n    template <class T>\n    struct DefProcessedMap : public Bfs< Graph, DefProcessedMapTraits<T> > {\n      typedef Bfs< Graph, DefProcessedMapTraits<T> > Create;\n    };\n    \n    struct DefGraphProcessedMapTraits : public Traits {\n      typedef typename Graph::template NodeMap<bool> ProcessedMap;\n      static ProcessedMap *createProcessedMap(const Graph &G) \n      {\n\treturn new ProcessedMap(G);\n      }\n    };\n    ///\\brief \\ref named-templ-param \"Named parameter\"\n    ///for setting the ProcessedMap type to be Graph::NodeMap<bool>.\n    ///\n    ///\\ref named-templ-param \"Named parameter\"\n    ///for setting the ProcessedMap type to be Graph::NodeMap<bool>.\n    ///If you don't set it explicitly, it will be automatically allocated.\n    template <class T>\n    struct DefProcessedMapToBeDefaultMap :\n      public Bfs< Graph, DefGraphProcessedMapTraits> { \n      typedef Bfs< Graph, DefGraphProcessedMapTraits> Create;\n    };\n    \n    ///@}\n\n  public:      \n    \n    ///Constructor.\n    \n    ///\\param _G the graph the algorithm will run on.\n    ///\n    Bfs(const Graph& _G) :\n      G(&_G),\n      _pred(NULL), local_pred(false),\n      _dist(NULL), local_dist(false),\n      _reached(NULL), local_reached(false),\n      _processed(NULL), local_processed(false)\n    { }\n    \n    ///Destructor.\n    ~Bfs() \n    {\n      if(local_pred) delete _pred;\n      if(local_dist) delete _dist;\n      if(local_reached) delete _reached;\n      if(local_processed) delete _processed;\n    }\n\n    ///Sets the map storing the predecessor edges.\n\n    ///Sets the map storing the predecessor edges.\n    ///If you don't use this function before calling \\ref run(),\n    ///it will allocate one. The destructor deallocates this\n    ///automatically allocated map, of course.\n    ///\\return <tt> (*this) </tt>\n    Bfs &predMap(PredMap &m) \n    {\n      if(local_pred) {\n\tdelete _pred;\n\tlocal_pred=false;\n      }\n      _pred = &m;\n      return *this;\n    }\n\n    ///Sets the map indicating the reached nodes.\n\n    ///Sets the map indicating the reached nodes.\n    ///If you don't use this function before calling \\ref run(),\n    ///it will allocate one. The destructor deallocates this\n    ///automatically allocated map, of course.\n    ///\\return <tt> (*this) </tt>\n    Bfs &reachedMap(ReachedMap &m) \n    {\n      if(local_reached) {\n\tdelete _reached;\n\tlocal_reached=false;\n      }\n      _reached = &m;\n      return *this;\n    }\n\n    ///Sets the map indicating the processed nodes.\n\n    ///Sets the map indicating the processed nodes.\n    ///If you don't use this function before calling \\ref run(),\n    ///it will allocate one. The destructor deallocates this\n    ///automatically allocated map, of course.\n    ///\\return <tt> (*this) </tt>\n    Bfs &processedMap(ProcessedMap &m) \n    {\n      if(local_processed) {\n\tdelete _processed;\n\tlocal_processed=false;\n      }\n      _processed = &m;\n      return *this;\n    }\n\n    ///Sets the map storing the distances calculated by the algorithm.\n\n    ///Sets the map storing the distances calculated by the algorithm.\n    ///If you don't use this function before calling \\ref run(),\n    ///it will allocate one. The destructor deallocates this\n    ///automatically allocated map, of course.\n    ///\\return <tt> (*this) </tt>\n    Bfs &distMap(DistMap &m) \n    {\n      if(local_dist) {\n\tdelete _dist;\n\tlocal_dist=false;\n      }\n      _dist = &m;\n      return *this;\n    }\n\n  public:\n    ///\\name Execution control\n    ///The simplest way to execute the algorithm is to use\n    ///one of the member functions called \\c run(...).\n    ///\\n\n    ///If you need more control on the execution,\n    ///first you must call \\ref init(), then you can add several source nodes\n    ///with \\ref addSource().\n    ///Finally \\ref start() will perform the actual path\n    ///computation.\n\n    ///@{\n\n    ///\\brief Initializes the internal data structures.\n    ///\n    ///Initializes the internal data structures.\n    ///\n    void init()\n    {\n      create_maps();\n      _queue.resize(countNodes(*G));\n      _queue_head=_queue_tail=0;\n      _curr_dist=1;\n      for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {\n\t_pred->set(u,INVALID);\n\t_reached->set(u,false);\n\t_processed->set(u,false);\n      }\n    }\n    \n    ///Adds a new source node.\n\n    ///Adds a new source node to the set of nodes to be processed.\n    ///\n    void addSource(Node s)\n    {\n      if(!(*_reached)[s])\n\t{\n\t  _reached->set(s,true);\n\t  _pred->set(s,INVALID);\n\t  _dist->set(s,0);\n\t  _queue[_queue_head++]=s;\n\t  _queue_next_dist=_queue_head;\n\t}\n    }\n    \n    ///Processes the next node.\n\n    ///Processes the next node.\n    ///\n    ///\\return The processed node.\n    ///\n    ///\\warning The queue must not be empty!\n    Node processNextNode()\n    {\n      if(_queue_tail==_queue_next_dist) {\n\t_curr_dist++;\n\t_queue_next_dist=_queue_head;\n      }\n      Node n=_queue[_queue_tail++];\n      _processed->set(n,true);\n      Node m;\n      for(OutEdgeIt e(*G,n);e!=INVALID;++e)\n\tif(!(*_reached)[m=G->target(e)]) {\n\t  _queue[_queue_head++]=m;\n\t  _reached->set(m,true);\n\t  _pred->set(m,e);\n\t  _dist->set(m,_curr_dist);\n\t}\n      return n;\n    }\n\n    ///Processes the next node.\n\n    ///Processes the next node. And checks that the given target node\n    ///is reached. If the target node is reachable from the processed\n    ///node then the reached parameter will be set true. The reached\n    ///parameter should be initially false.\n    ///\n    ///\\param target The target node.\n    ///\\retval reach Indicates that the target node is reached.\n    ///\\return The processed node.\n    ///\n    ///\\warning The queue must not be empty!\n    Node processNextNode(Node target, bool& reach)\n    {\n      if(_queue_tail==_queue_next_dist) {\n\t_curr_dist++;\n\t_queue_next_dist=_queue_head;\n      }\n      Node n=_queue[_queue_tail++];\n      _processed->set(n,true);\n      Node m;\n      for(OutEdgeIt e(*G,n);e!=INVALID;++e)\n\tif(!(*_reached)[m=G->target(e)]) {\n\t  _queue[_queue_head++]=m;\n\t  _reached->set(m,true);\n\t  _pred->set(m,e);\n\t  _dist->set(m,_curr_dist);\n          reach = reach || (target == m);\n\t}\n      return n;\n    }\n\n    ///Processes the next node.\n\n    ///Processes the next node. And checks that at least one of\n    ///reached node has true value in the \\c nm node map. If one node\n    ///with true value is reachable from the processed node then the\n    ///rnode parameter will be set to the first of such nodes.\n    ///\n    ///\\param nm The node map of possible targets.\n    ///\\retval rnode The reached target node.\n    ///\\return The processed node.\n    ///\n    ///\\warning The queue must not be empty!\n    template<class NM>\n    Node processNextNode(const NM& nm, Node& rnode)\n    {\n      if(_queue_tail==_queue_next_dist) {\n\t_curr_dist++;\n\t_queue_next_dist=_queue_head;\n      }\n      Node n=_queue[_queue_tail++];\n      _processed->set(n,true);\n      Node m;\n      for(OutEdgeIt e(*G,n);e!=INVALID;++e)\n\tif(!(*_reached)[m=G->target(e)]) {\n\t  _queue[_queue_head++]=m;\n\t  _reached->set(m,true);\n\t  _pred->set(m,e);\n\t  _dist->set(m,_curr_dist);\n\t  if (nm[m] && rnode == INVALID) rnode = m;\n\t}\n      return n;\n    }\n      \n    ///Next node to be processed.\n\n    ///Next node to be processed.\n    ///\n    ///\\return The next node to be processed or INVALID if the queue is\n    /// empty.\n    Node nextNode()\n    { \n      return _queue_tail<_queue_head?_queue[_queue_tail]:INVALID;\n    }\n \n    ///\\brief Returns \\c false if there are nodes\n    ///to be processed in the queue\n    ///\n    ///Returns \\c false if there are nodes\n    ///to be processed in the queue\n    bool emptyQueue() { return _queue_tail==_queue_head; }\n    ///Returns the number of the nodes to be processed.\n    \n    ///Returns the number of the nodes to be processed in the queue.\n    int queueSize() { return _queue_head-_queue_tail; }\n    \n    ///Executes the algorithm.\n\n    ///Executes the algorithm.\n    ///\n    ///\\pre init() must be called and at least one node should be added\n    ///with addSource() before using this function.\n    ///\n    ///This method runs the %BFS algorithm from the root node(s)\n    ///in order to\n    ///compute the\n    ///shortest path to each node. The algorithm computes\n    ///- The shortest path tree.\n    ///- The distance of each node from the root(s).\n    void start()\n    {\n      while ( !emptyQueue() ) processNextNode();\n    }\n    \n    ///Executes the algorithm until \\c dest is reached.\n\n    ///Executes the algorithm until \\c dest is reached.\n    ///\n    ///\\pre init() must be called and at least one node should be added\n    ///with addSource() before using this function.\n    ///\n    ///This method runs the %BFS algorithm from the root node(s)\n    ///in order to compute the shortest path to \\c dest.\n    ///The algorithm computes\n    ///- The shortest path to \\c  dest.\n    ///- The distance of \\c dest from the root(s).\n    void start(Node dest)\n    {\n      bool reach = false;\n      while ( !emptyQueue() && !reach ) processNextNode(dest, reach);\n    }\n    \n    ///Executes the algorithm until a condition is met.\n\n    ///Executes the algorithm until a condition is met.\n    ///\n    ///\\pre init() must be called and at least one node should be added\n    ///with addSource() before using this function.\n    ///\n    ///\\param nm must be a bool (or convertible) node map. The\n    ///algorithm will stop when it reaches a node \\c v with\n    /// <tt>nm[v]</tt> true.\n    ///\n    ///\\return The reached node \\c v with <tt>nm[v]</tt> true or\n    ///\\c INVALID if no such node was found.\n    template<class NM>\n    Node start(const NM &nm)\n    {\n      Node rnode = INVALID;\n      while ( !emptyQueue() && rnode == INVALID ) {\n\tprocessNextNode(nm, rnode);\n      }\n      return rnode;\n    }\n    \n    ///Runs %BFS algorithm from node \\c s.\n    \n    ///This method runs the %BFS algorithm from a root node \\c s\n    ///in order to\n    ///compute the\n    ///shortest path to each node. The algorithm computes\n    ///- The shortest path tree.\n    ///- The distance of each node from the root.\n    ///\n    ///\\note b.run(s) is just a shortcut of the following code.\n    ///\\code\n    ///  b.init();\n    ///  b.addSource(s);\n    ///  b.start();\n    ///\\endcode\n    void run(Node s) {\n      init();\n      addSource(s);\n      start();\n    }\n    \n    ///Finds the shortest path between \\c s and \\c t.\n    \n    ///Finds the shortest path between \\c s and \\c t.\n    ///\n    ///\\return The length of the shortest s---t path if there exists one,\n    ///0 otherwise.\n    ///\\note Apart from the return value, b.run(s) is\n    ///just a shortcut of the following code.\n    ///\\code\n    ///  b.init();\n    ///  b.addSource(s);\n    ///  b.start(t);\n    ///\\endcode\n    int run(Node s,Node t) {\n      init();\n      addSource(s);\n      start(t);\n      return reached(t) ? _curr_dist : 0;\n    }\n    \n    ///@}\n\n    ///\\name Query Functions\n    ///The result of the %BFS algorithm can be obtained using these\n    ///functions.\\n\n    ///Before the use of these functions,\n    ///either run() or start() must be calleb.\n    \n    ///@{\n\n    typedef PredMapPath<Graph, PredMap> Path;\n\n    ///Gives back the shortest path.\n    \n    ///Gives back the shortest path.\n    ///\\pre The \\c t should be reachable from the source.\n    Path path(Node t) \n    {\n      return Path(*G, *_pred, t);\n    }\n\n    ///The distance of a node from the root(s).\n\n    ///Returns the distance of a node from the root(s).\n    ///\\pre \\ref run() must be called before using this function.\n    ///\\warning If node \\c v in unreachable from the root(s) the return value\n    ///of this function is undefined.\n    int dist(Node v) const { return (*_dist)[v]; }\n\n    ///Returns the 'previous edge' of the shortest path tree.\n\n    ///For a node \\c v it returns the 'previous edge'\n    ///of the shortest path tree,\n    ///i.e. it returns the last edge of a shortest path from the root(s) to \\c\n    ///v. It is \\ref INVALID\n    ///if \\c v is unreachable from the root(s) or \\c v is a root. The\n    ///shortest path tree used here is equal to the shortest path tree used in\n    ///\\ref predNode().\n    ///\\pre Either \\ref run() or \\ref start() must be called before using\n    ///this function.\n    Edge predEdge(Node v) const { return (*_pred)[v];}\n\n    ///Returns the 'previous node' of the shortest path tree.\n\n    ///For a node \\c v it returns the 'previous node'\n    ///of the shortest path tree,\n    ///i.e. it returns the last but one node from a shortest path from the\n    ///root(a) to \\c /v.\n    ///It is INVALID if \\c v is unreachable from the root(s) or\n    ///if \\c v itself a root.\n    ///The shortest path tree used here is equal to the shortest path\n    ///tree used in \\ref predEdge().\n    ///\\pre Either \\ref run() or \\ref start() must be called before\n    ///using this function.\n    Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID:\n\t\t\t\t  G->source((*_pred)[v]); }\n    \n    ///Returns a reference to the NodeMap of distances.\n\n    ///Returns a reference to the NodeMap of distances.\n    ///\\pre Either \\ref run() or \\ref init() must\n    ///be called before using this function.\n    const DistMap &distMap() const { return *_dist;}\n \n    ///Returns a reference to the shortest path tree map.\n\n    ///Returns a reference to the NodeMap of the edges of the\n    ///shortest path tree.\n    ///\\pre Either \\ref run() or \\ref init()\n    ///must be called before using this function.\n    const PredMap &predMap() const { return *_pred;}\n \n    ///Checks if a node is reachable from the root.\n\n    ///Returns \\c true if \\c v is reachable from the root.\n    ///\\warning The source nodes are indicated as unreached.\n    ///\\pre Either \\ref run() or \\ref start()\n    ///must be called before using this function.\n    ///\n    bool reached(Node v) { return (*_reached)[v]; }\n    \n    ///@}\n  };\n\n  ///Default traits class of Bfs function.\n\n  ///Default traits class of Bfs function.\n  ///\\param GR Graph type.\n  template<class GR>\n  struct BfsWizardDefaultTraits\n  {\n    ///The graph type the algorithm runs on. \n    typedef GR Graph;\n    ///\\brief The type of the map that stores the last\n    ///edges of the shortest paths.\n    /// \n    ///The type of the map that stores the last\n    ///edges of the shortest paths.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\n    typedef NullMap<typename Graph::Node,typename GR::Edge> PredMap;\n    ///Instantiates a PredMap.\n \n    ///This function instantiates a \\ref PredMap. \n    ///\\param g is the graph, to which we would like to define the PredMap.\n    ///\\todo The graph alone may be insufficient to initialize\n#ifdef DOXYGEN\n    static PredMap *createPredMap(const GR &g) \n#else\n    static PredMap *createPredMap(const GR &) \n#endif\n    {\n      return new PredMap();\n    }\n\n    ///The type of the map that indicates which nodes are processed.\n \n    ///The type of the map that indicates which nodes are processed.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\\todo named parameter to set this type, function to read and write.\n    typedef NullMap<typename Graph::Node,bool> ProcessedMap;\n    ///Instantiates a ProcessedMap.\n \n    ///This function instantiates a \\ref ProcessedMap. \n    ///\\param g is the graph, to which\n    ///we would like to define the \\ref ProcessedMap\n#ifdef DOXYGEN\n    static ProcessedMap *createProcessedMap(const GR &g)\n#else\n    static ProcessedMap *createProcessedMap(const GR &)\n#endif\n    {\n      return new ProcessedMap();\n    }\n    ///The type of the map that indicates which nodes are reached.\n \n    ///The type of the map that indicates which nodes are reached.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\\todo named parameter to set this type, function to read and write.\n    typedef typename Graph::template NodeMap<bool> ReachedMap;\n    ///Instantiates a ReachedMap.\n \n    ///This function instantiates a \\ref ReachedMap. \n    ///\\param G is the graph, to which\n    ///we would like to define the \\ref ReachedMap.\n    static ReachedMap *createReachedMap(const GR &G)\n    {\n      return new ReachedMap(G);\n    }\n    ///The type of the map that stores the dists of the nodes.\n \n    ///The type of the map that stores the dists of the nodes.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\n    typedef NullMap<typename Graph::Node,int> DistMap;\n    ///Instantiates a DistMap.\n \n    ///This function instantiates a \\ref DistMap. \n    ///\\param g is the graph, to which we would like to define the \\ref DistMap\n#ifdef DOXYGEN\n    static DistMap *createDistMap(const GR &g)\n#else\n    static DistMap *createDistMap(const GR &)\n#endif\n    {\n      return new DistMap();\n    }\n  };\n  \n  /// Default traits used by \\ref BfsWizard\n\n  /// To make it easier to use Bfs algorithm\n  ///we have created a wizard class.\n  /// This \\ref BfsWizard class needs default traits,\n  ///as well as the \\ref Bfs class.\n  /// The \\ref BfsWizardBase is a class to be the default traits of the\n  /// \\ref BfsWizard class.\n  template<class GR>\n  class BfsWizardBase : public BfsWizardDefaultTraits<GR>\n  {\n\n    typedef BfsWizardDefaultTraits<GR> Base;\n  protected:\n    /// Type of the nodes in the graph.\n    typedef typename Base::Graph::Node Node;\n\n    /// Pointer to the underlying graph.\n    void *_g;\n    ///Pointer to the map of reached nodes.\n    void *_reached;\n    ///Pointer to the map of processed nodes.\n    void *_processed;\n    ///Pointer to the map of predecessors edges.\n    void *_pred;\n    ///Pointer to the map of distances.\n    void *_dist;\n    ///Pointer to the source node.\n    Node _source;\n    \n    public:\n    /// Constructor.\n    \n    /// This constructor does not require parameters, therefore it initiates\n    /// all of the attributes to default values (0, INVALID).\n    BfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0),\n\t\t\t   _dist(0), _source(INVALID) {}\n\n    /// Constructor.\n    \n    /// This constructor requires some parameters,\n    /// listed in the parameters list.\n    /// Others are initiated to 0.\n    /// \\param g is the initial value of  \\ref _g\n    /// \\param s is the initial value of  \\ref _source\n    BfsWizardBase(const GR &g, Node s=INVALID) :\n      _g(reinterpret_cast<void*>(const_cast<GR*>(&g))), \n      _reached(0), _processed(0), _pred(0), _dist(0), _source(s) {}\n\n  };\n  \n  /// A class to make the usage of Bfs algorithm easier\n\n  /// This class is created to make it easier to use Bfs algorithm.\n  /// It uses the functions and features of the plain \\ref Bfs,\n  /// but it is much simpler to use it.\n  ///\n  /// Simplicity means that the way to change the types defined\n  /// in the traits class is based on functions that returns the new class\n  /// and not on templatable built-in classes.\n  /// When using the plain \\ref Bfs\n  /// the new class with the modified type comes from\n  /// the original class by using the ::\n  /// operator. In the case of \\ref BfsWizard only\n  /// a function have to be called and it will\n  /// return the needed class.\n  ///\n  /// It does not have own \\ref run method. When its \\ref run method is called\n  /// it initiates a plain \\ref Bfs class, and calls the \\ref Bfs::run\n  /// method of it.\n  template<class TR>\n  class BfsWizard : public TR\n  {\n    typedef TR Base;\n\n    ///The type of the underlying graph.\n    typedef typename TR::Graph Graph;\n    //\\e\n    typedef typename Graph::Node Node;\n    //\\e\n    typedef typename Graph::NodeIt NodeIt;\n    //\\e\n    typedef typename Graph::Edge Edge;\n    //\\e\n    typedef typename Graph::OutEdgeIt OutEdgeIt;\n    \n    ///\\brief The type of the map that stores\n    ///the reached nodes\n    typedef typename TR::ReachedMap ReachedMap;\n    ///\\brief The type of the map that stores\n    ///the processed nodes\n    typedef typename TR::ProcessedMap ProcessedMap;\n    ///\\brief The type of the map that stores the last\n    ///edges of the shortest paths.\n    typedef typename TR::PredMap PredMap;\n    ///The type of the map that stores the dists of the nodes.\n    typedef typename TR::DistMap DistMap;\n\n  public:\n    /// Constructor.\n    BfsWizard() : TR() {}\n\n    /// Constructor that requires parameters.\n\n    /// Constructor that requires parameters.\n    /// These parameters will be the default values for the traits class.\n    BfsWizard(const Graph &g, Node s=INVALID) :\n      TR(g,s) {}\n\n    ///Copy constructor\n    BfsWizard(const TR &b) : TR(b) {}\n\n    ~BfsWizard() {}\n\n    ///Runs Bfs algorithm from a given node.\n    \n    ///Runs Bfs algorithm from a given node.\n    ///The node can be given by the \\ref source function.\n    void run()\n    {\n      if(Base::_source==INVALID) throw UninitializedParameter();\n      Bfs<Graph,TR> alg(*reinterpret_cast<const Graph*>(Base::_g));\n      if(Base::_reached)\n\talg.reachedMap(*reinterpret_cast<ReachedMap*>(Base::_reached));\n      if(Base::_processed) \n        alg.processedMap(*reinterpret_cast<ProcessedMap*>(Base::_processed));\n      if(Base::_pred) \n        alg.predMap(*reinterpret_cast<PredMap*>(Base::_pred));\n      if(Base::_dist) \n        alg.distMap(*reinterpret_cast<DistMap*>(Base::_dist));\n      alg.run(Base::_source);\n    }\n\n    ///Runs Bfs algorithm from the given node.\n\n    ///Runs Bfs algorithm from the given node.\n    ///\\param s is the given source.\n    void run(Node s)\n    {\n      Base::_source=s;\n      run();\n    }\n\n    template<class T>\n    struct DefPredMapBase : public Base {\n      typedef T PredMap;\n      static PredMap *createPredMap(const Graph &) { return 0; };\n      DefPredMapBase(const TR &b) : TR(b) {}\n    };\n    \n    ///\\brief \\ref named-templ-param \"Named parameter\"\n    ///function for setting PredMap\n    ///\n    /// \\ref named-templ-param \"Named parameter\"\n    ///function for setting PredMap\n    ///\n    template<class T>\n    BfsWizard<DefPredMapBase<T> > predMap(const T &t) \n    {\n      Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));\n      return BfsWizard<DefPredMapBase<T> >(*this);\n    }\n    \n \n    template<class T>\n    struct DefReachedMapBase : public Base {\n      typedef T ReachedMap;\n      static ReachedMap *createReachedMap(const Graph &) { return 0; };\n      DefReachedMapBase(const TR &b) : TR(b) {}\n    };\n    \n    ///\\brief \\ref named-templ-param \"Named parameter\"\n    ///function for setting ReachedMap\n    ///\n    /// \\ref named-templ-param \"Named parameter\"\n    ///function for setting ReachedMap\n    ///\n    template<class T>\n    BfsWizard<DefReachedMapBase<T> > reachedMap(const T &t) \n    {\n      Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));\n      return BfsWizard<DefReachedMapBase<T> >(*this);\n    }\n    \n\n    template<class T>\n    struct DefProcessedMapBase : public Base {\n      typedef T ProcessedMap;\n      static ProcessedMap *createProcessedMap(const Graph &) { return 0; };\n      DefProcessedMapBase(const TR &b) : TR(b) {}\n    };\n    \n    ///\\brief \\ref named-templ-param \"Named parameter\"\n    ///function for setting ProcessedMap\n    ///\n    /// \\ref named-templ-param \"Named parameter\"\n    ///function for setting ProcessedMap\n    ///\n    template<class T>\n    BfsWizard<DefProcessedMapBase<T> > processedMap(const T &t) \n    {\n      Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));\n      return BfsWizard<DefProcessedMapBase<T> >(*this);\n    }\n    \n   \n    template<class T>\n    struct DefDistMapBase : public Base {\n      typedef T DistMap;\n      static DistMap *createDistMap(const Graph &) { return 0; };\n      DefDistMapBase(const TR &b) : TR(b) {}\n    };\n    \n    ///\\brief \\ref named-templ-param \"Named parameter\"\n    ///function for setting DistMap type\n    ///\n    /// \\ref named-templ-param \"Named parameter\"\n    ///function for setting DistMap type\n    ///\n    template<class T>\n    BfsWizard<DefDistMapBase<T> > distMap(const T &t) \n    {\n      Base::_dist=reinterpret_cast<void*>(const_cast<T*>(&t));\n      return BfsWizard<DefDistMapBase<T> >(*this);\n    }\n    \n    /// Sets the source node, from which the Bfs algorithm runs.\n\n    /// Sets the source node, from which the Bfs algorithm runs.\n    /// \\param s is the source node.\n    BfsWizard<TR> &source(Node s) \n    {\n      Base::_source=s;\n      return *this;\n    }\n    \n  };\n  \n  ///Function type interface for Bfs algorithm.\n\n  /// \\ingroup search\n  ///Function type interface for Bfs algorithm.\n  ///\n  ///This function also has several\n  ///\\ref named-templ-func-param \"named parameters\",\n  ///they are declared as the members of class \\ref BfsWizard.\n  ///The following\n  ///example shows how to use these parameters.\n  ///\\code\n  ///  bfs(g,source).predMap(preds).run();\n  ///\\endcode\n  ///\\warning Don't forget to put the \\ref BfsWizard::run() \"run()\"\n  ///to the end of the parameter list.\n  ///\\sa BfsWizard\n  ///\\sa Bfs\n  template<class GR>\n  BfsWizard<BfsWizardBase<GR> >\n  bfs(const GR &g,typename GR::Node s=INVALID)\n  {\n    return BfsWizard<BfsWizardBase<GR> >(g,s);\n  }\n\n#ifdef DOXYGEN\n  /// \\brief Visitor class for bfs.\n  ///  \n  /// This class defines the interface of the BfsVisit events, and\n  /// it could be the base of a real Visitor class.\n  template <typename _Graph>\n  struct BfsVisitor {\n    typedef _Graph Graph;\n    typedef typename Graph::Edge Edge;\n    typedef typename Graph::Node Node;\n    /// \\brief Called when the edge reach a node.\n    /// \n    /// It is called when the bfs find an edge which target is not\n    /// reached yet.\n    void discover(const Edge& edge) {}\n    /// \\brief Called when the node reached first time.\n    /// \n    /// It is Called when the node reached first time.\n    void reach(const Node& node) {}\n    /// \\brief Called when the edge examined but target of the edge \n    /// already discovered.\n    /// \n    /// It called when the edge examined but the target of the edge \n    /// already discovered.\n    void examine(const Edge& edge) {}\n    /// \\brief Called for the source node of the bfs.\n    /// \n    /// It is called for the source node of the bfs.\n    void start(const Node& node) {}\n    /// \\brief Called when the node processed.\n    /// \n    /// It is Called when the node processed.\n    void process(const Node& node) {}\n  };\n#else\n  template <typename _Graph>\n  struct BfsVisitor {\n    typedef _Graph Graph;\n    typedef typename Graph::Edge Edge;\n    typedef typename Graph::Node Node;\n    void discover(const Edge&) {}\n    void reach(const Node&) {}\n    void examine(const Edge&) {}\n    void start(const Node&) {}\n    void process(const Node&) {}\n\n    template <typename _Visitor>\n    struct Constraints {\n      void constraints() {\n\tEdge edge;\n\tNode node;\n\tvisitor.discover(edge);\n\tvisitor.reach(node);\n\tvisitor.examine(edge);\n\tvisitor.start(node);\n        visitor.process(node);\n      }\n      _Visitor& visitor;\n    };\n  };\n#endif\n\n  /// \\brief Default traits class of BfsVisit class.\n  ///\n  /// Default traits class of BfsVisit class.\n  /// \\param _Graph Graph type.\n  template<class _Graph>\n  struct BfsVisitDefaultTraits {\n\n    /// \\brief The graph type the algorithm runs on. \n    typedef _Graph Graph;\n\n    /// \\brief The type of the map that indicates which nodes are reached.\n    /// \n    /// The type of the map that indicates which nodes are reached.\n    /// It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    /// \\todo named parameter to set this type, function to read and write.\n    typedef typename Graph::template NodeMap<bool> ReachedMap;\n\n    /// \\brief Instantiates a ReachedMap.\n    ///\n    /// This function instantiates a \\ref ReachedMap. \n    /// \\param graph is the graph, to which\n    /// we would like to define the \\ref ReachedMap.\n    static ReachedMap *createReachedMap(const Graph &graph) {\n      return new ReachedMap(graph);\n    }\n\n  };\n\n  /// \\ingroup search\n  ///  \n  /// \\brief %BFS Visit algorithm class.\n  ///  \n  /// This class provides an efficient implementation of the %BFS algorithm\n  /// with visitor interface.\n  ///\n  /// The %BfsVisit class provides an alternative interface to the Bfs\n  /// class. It works with callback mechanism, the BfsVisit object calls\n  /// on every bfs event the \\c Visitor class member functions. \n  ///\n  /// \\param _Graph The graph type the algorithm runs on. The default value is\n  /// \\ref ListGraph. The value of _Graph is not used directly by Bfs, it\n  /// is only passed to \\ref BfsDefaultTraits.\n  /// \\param _Visitor The Visitor object for the algorithm. The \n  /// \\ref BfsVisitor \"BfsVisitor<_Graph>\" is an empty Visitor which\n  /// does not observe the Bfs events. If you want to observe the bfs\n  /// events you should implement your own Visitor class.\n  /// \\param _Traits Traits class to set various data types used by the \n  /// algorithm. The default traits class is\n  /// \\ref BfsVisitDefaultTraits \"BfsVisitDefaultTraits<_Graph>\".\n  /// See \\ref BfsVisitDefaultTraits for the documentation of\n  /// a Bfs visit traits class.\n  ///\n  /// \\author Jacint Szabo, Alpar Juttner and Balazs Dezso\n#ifdef DOXYGEN\n  template <typename _Graph, typename _Visitor, typename _Traits>\n#else\n  template <typename _Graph = ListGraph,\n\t    typename _Visitor = BfsVisitor<_Graph>,\n\t    typename _Traits = BfsDefaultTraits<_Graph> >\n#endif\n  class BfsVisit {\n  public:\n    \n    /// \\brief \\ref Exception for uninitialized parameters.\n    ///\n    /// This error represents problems in the initialization\n    /// of the parameters of the algorithms.\n    class UninitializedParameter : public lemon::UninitializedParameter {\n    public:\n      virtual const char* what() const throw() \n      {\n\treturn \"lemon::BfsVisit::UninitializedParameter\";\n      }\n    };\n\n    typedef _Traits Traits;\n\n    typedef typename Traits::Graph Graph;\n\n    typedef _Visitor Visitor;\n\n    ///The type of the map indicating which nodes are reached.\n    typedef typename Traits::ReachedMap ReachedMap;\n\n  private:\n\n    typedef typename Graph::Node Node;\n    typedef typename Graph::NodeIt NodeIt;\n    typedef typename Graph::Edge Edge;\n    typedef typename Graph::OutEdgeIt OutEdgeIt;\n\n    /// Pointer to the underlying graph.\n    const Graph *_graph;\n    /// Pointer to the visitor object.\n    Visitor *_visitor;\n    ///Pointer to the map of reached status of the nodes.\n    ReachedMap *_reached;\n    ///Indicates if \\ref _reached is locally allocated (\\c true) or not.\n    bool local_reached;\n\n    std::vector<typename Graph::Node> _list;\n    int _list_front, _list_back;\n\n    /// \\brief Creates the maps if necessary.\n    ///\n    /// Creates the maps if necessary.\n    void create_maps() {\n      if(!_reached) {\n\tlocal_reached = true;\n\t_reached = Traits::createReachedMap(*_graph);\n      }\n    }\n\n  protected:\n\n    BfsVisit() {}\n    \n  public:\n\n    typedef BfsVisit Create;\n\n    /// \\name Named template parameters\n\n    ///@{\n    template <class T>\n    struct DefReachedMapTraits : public Traits {\n      typedef T ReachedMap;\n      static ReachedMap *createReachedMap(const Graph &graph) {\n\tthrow UninitializedParameter();\n      }\n    };\n    /// \\brief \\ref named-templ-param \"Named parameter\" for setting \n    /// ReachedMap type\n    ///\n    /// \\ref named-templ-param \"Named parameter\" for setting ReachedMap type\n    template <class T>\n    struct DefReachedMap : public BfsVisit< Graph, Visitor,\n\t\t\t\t\t    DefReachedMapTraits<T> > {\n      typedef BfsVisit< Graph, Visitor, DefReachedMapTraits<T> > Create;\n    };\n    ///@}\n\n  public:      \n    \n    /// \\brief Constructor.\n    ///\n    /// Constructor.\n    ///\n    /// \\param graph the graph the algorithm will run on.\n    /// \\param visitor The visitor of the algorithm.\n    ///\n    BfsVisit(const Graph& graph, Visitor& visitor) \n      : _graph(&graph), _visitor(&visitor),\n\t_reached(0), local_reached(false) {}\n    \n    /// \\brief Destructor.\n    ///\n    /// Destructor.\n    ~BfsVisit() {\n      if(local_reached) delete _reached;\n    }\n\n    /// \\brief Sets the map indicating if a node is reached.\n    ///\n    /// Sets the map indicating if a node is reached.\n    /// If you don't use this function before calling \\ref run(),\n    /// it will allocate one. The destuctor deallocates this\n    /// automatically allocated map, of course.\n    /// \\return <tt> (*this) </tt>\n    BfsVisit &reachedMap(ReachedMap &m) {\n      if(local_reached) {\n\tdelete _reached;\n\tlocal_reached = false;\n      }\n      _reached = &m;\n      return *this;\n    }\n\n  public:\n    /// \\name Execution control\n    /// The simplest way to execute the algorithm is to use\n    /// one of the member functions called \\c run(...).\n    /// \\n\n    /// If you need more control on the execution,\n    /// first you must call \\ref init(), then you can adda source node\n    /// with \\ref addSource().\n    /// Finally \\ref start() will perform the actual path\n    /// computation.\n\n    /// @{\n    /// \\brief Initializes the internal data structures.\n    ///\n    /// Initializes the internal data structures.\n    ///\n    void init() {\n      create_maps();\n      _list.resize(countNodes(*_graph));\n      _list_front = _list_back = -1;\n      for (NodeIt u(*_graph) ; u != INVALID ; ++u) {\n\t_reached->set(u, false);\n      }\n    }\n    \n    /// \\brief Adds a new source node.\n    ///\n    /// Adds a new source node to the set of nodes to be processed.\n    void addSource(Node s) {\n      if(!(*_reached)[s]) {\n\t  _reached->set(s,true);\n\t  _visitor->start(s);\n\t  _visitor->reach(s);\n          _list[++_list_back] = s;\n\t}\n    }\n    \n    /// \\brief Processes the next node.\n    ///\n    /// Processes the next node.\n    ///\n    /// \\return The processed node.\n    ///\n    /// \\pre The queue must not be empty!\n    Node processNextNode() { \n      Node n = _list[++_list_front];\n      _visitor->process(n);\n      Edge e;\n      for (_graph->firstOut(e, n); e != INVALID; _graph->nextOut(e)) {\n        Node m = _graph->target(e);\n        if (!(*_reached)[m]) {\n          _visitor->discover(e);\n          _visitor->reach(m);\n          _reached->set(m, true);\n          _list[++_list_back] = m;\n        } else {\n          _visitor->examine(e);\n        }\n      }\n      return n;\n    }\n\n    /// \\brief Processes the next node.\n    ///\n    /// Processes the next node. And checks that the given target node\n    /// is reached. If the target node is reachable from the processed\n    /// node then the reached parameter will be set true. The reached\n    /// parameter should be initially false.\n    ///\n    /// \\param target The target node.\n    /// \\retval reach Indicates that the target node is reached.\n    /// \\return The processed node.\n    ///\n    /// \\warning The queue must not be empty!\n    Node processNextNode(Node target, bool& reach) {\n      Node n = _list[++_list_front];\n      _visitor->process(n);\n      Edge e;\n      for (_graph->firstOut(e, n); e != INVALID; _graph->nextOut(e)) {\n        Node m = _graph->target(e);\n        if (!(*_reached)[m]) {\n          _visitor->discover(e);\n          _visitor->reach(m);\n          _reached->set(m, true);\n          _list[++_list_back] = m;\n          reach = reach || (target == m);\n        } else {\n          _visitor->examine(e);\n        }\n      }\n      return n;\n    }\n\n    /// \\brief Processes the next node.\n    ///\n    /// Processes the next node. And checks that at least one of\n    /// reached node has true value in the \\c nm node map. If one node\n    /// with true value is reachable from the processed node then the\n    /// rnode parameter will be set to the first of such nodes.\n    ///\n    /// \\param nm The node map of possible targets.\n    /// \\retval rnode The reached target node.\n    /// \\return The processed node.\n    ///\n    /// \\warning The queue must not be empty!\n    template <typename NM>\n    Node processNextNode(const NM& nm, Node& rnode) {\n      Node n = _list[++_list_front];\n      _visitor->process(n);\n      Edge e;\n      for (_graph->firstOut(e, n); e != INVALID; _graph->nextOut(e)) {\n        Node m = _graph->target(e);\n        if (!(*_reached)[m]) {\n          _visitor->discover(e);\n          _visitor->reach(m);\n          _reached->set(m, true);\n          _list[++_list_back] = m;\n          if (nm[m] && rnode == INVALID) rnode = m;\n        } else {\n          _visitor->examine(e);\n        }\n      }\n      return n;\n    }\n\n    /// \\brief Next node to be processed.\n    ///\n    /// Next node to be processed.\n    ///\n    /// \\return The next node to be processed or INVALID if the stack is\n    /// empty.\n    Node nextNode() { \n      return _list_front != _list_back ? _list[_list_front + 1] : INVALID;\n    }\n\n    /// \\brief Returns \\c false if there are nodes\n    /// to be processed in the queue\n    ///\n    /// Returns \\c false if there are nodes\n    /// to be processed in the queue\n    bool emptyQueue() { return _list_front == _list_back; }\n\n    /// \\brief Returns the number of the nodes to be processed.\n    ///\n    /// Returns the number of the nodes to be processed in the queue.\n    int queueSize() { return _list_back - _list_front; }\n    \n    /// \\brief Executes the algorithm.\n    ///\n    /// Executes the algorithm.\n    ///\n    /// \\pre init() must be called and at least one node should be added\n    /// with addSource() before using this function.\n    void start() {\n      while ( !emptyQueue() ) processNextNode();\n    }\n    \n    /// \\brief Executes the algorithm until \\c dest is reached.\n    ///\n    /// Executes the algorithm until \\c dest is reached.\n    ///\n    /// \\pre init() must be called and at least one node should be added\n    /// with addSource() before using this function.\n    void start(Node dest) {\n      bool reach = false;\n      while ( !emptyQueue() && !reach ) processNextNode(dest, reach);\n    }\n    \n    /// \\brief Executes the algorithm until a condition is met.\n    ///\n    /// Executes the algorithm until a condition is met.\n    ///\n    /// \\pre init() must be called and at least one node should be added\n    /// with addSource() before using this function.\n    ///\n    ///\\param nm must be a bool (or convertible) node map. The\n    ///algorithm will stop when it reaches a node \\c v with\n    /// <tt>nm[v]</tt> true.\n    ///\n    ///\\return The reached node \\c v with <tt>nm[v]</tt> true or\n    ///\\c INVALID if no such node was found.\n    template <typename NM>\n    Node start(const NM &nm) {\n      Node rnode = INVALID;\n      while ( !emptyQueue() && rnode == INVALID ) {\n\tprocessNextNode(nm, rnode);\n      }\n      return rnode;\n    }\n\n    /// \\brief Runs %BFSVisit algorithm from node \\c s.\n    ///\n    /// This method runs the %BFS algorithm from a root node \\c s.\n    /// \\note b.run(s) is just a shortcut of the following code.\n    ///\\code\n    ///   b.init();\n    ///   b.addSource(s);\n    ///   b.start();\n    ///\\endcode\n    void run(Node s) {\n      init();\n      addSource(s);\n      start();\n    }\n\n    /// \\brief Runs %BFSVisit algorithm to visit all nodes in the graph.\n    ///    \n    /// This method runs the %BFS algorithm in order to\n    /// compute the %BFS path to each node. The algorithm computes\n    /// - The %BFS tree.\n    /// - The distance of each node from the root in the %BFS tree.\n    ///\n    ///\\note b.run() is just a shortcut of the following code.\n    ///\\code\n    ///  b.init();\n    ///  for (NodeIt it(graph); it != INVALID; ++it) {\n    ///    if (!b.reached(it)) {\n    ///      b.addSource(it);\n    ///      b.start();\n    ///    }\n    ///  }\n    ///\\endcode\n    void run() {\n      init();\n      for (NodeIt it(*_graph); it != INVALID; ++it) {\n        if (!reached(it)) {\n          addSource(it);\n          start();\n        }\n      }\n    }\n    ///@}\n\n    /// \\name Query Functions\n    /// The result of the %BFS algorithm can be obtained using these\n    /// functions.\\n\n    /// Before the use of these functions,\n    /// either run() or start() must be called.\n    ///@{\n\n    /// \\brief Checks if a node is reachable from the root.\n    ///\n    /// Returns \\c true if \\c v is reachable from the root(s).\n    /// \\warning The source nodes are inditated as unreachable.\n    /// \\pre Either \\ref run() or \\ref start()\n    /// must be called before using this function.\n    ///\n    bool reached(Node v) { return (*_reached)[v]; }\n    ///@}\n  };\n\n} //END OF NAMESPACE LEMON\n\n#endif\n\n"
  },
  {
    "path": "src/lemon/bin_heap.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BIN_HEAP_H\n#define LEMON_BIN_HEAP_H\n\n///\\ingroup auxdat\n///\\file\n///\\brief Binary Heap implementation.\n\n#include <vector>\n#include <utility>\n#include <functional>\n\nnamespace lemon {\n\n  ///\\ingroup auxdat\n  ///\n  ///\\brief A Binary Heap implementation.\n  ///\n  ///This class implements the \\e binary \\e heap data structure. A \\e heap\n  ///is a data structure for storing items with specified values called \\e\n  ///priorities in such a way that finding the item with minimum priority is\n  ///efficient. \\c Compare specifies the ordering of the priorities. In a heap\n  ///one can change the priority of an item, add or erase an item, etc.\n  ///\n  ///\\param _Prio Type of the priority of the items.\n  ///\\param _ItemIntMap A read and writable Item int map, used internally\n  ///to handle the cross references.\n  ///\\param _Compare A class for the ordering of the priorities. The\n  ///default is \\c std::less<_Prio>.\n  ///\n  ///\\sa FibHeap\n  ///\\sa Dijkstra\n  template <typename _Prio, typename _ItemIntMap,\n\t    typename _Compare = std::less<_Prio> >\n  class BinHeap {\n\n  public:\n    ///\\e\n    typedef _ItemIntMap ItemIntMap;\n    ///\\e\n    typedef _Prio Prio;\n    ///\\e\n    typedef typename ItemIntMap::Key Item;\n    ///\\e\n    typedef std::pair<Item,Prio> Pair;\n    ///\\e\n    typedef _Compare Compare;\n\n    /// \\brief Type to represent the items states.\n    ///\n    /// Each Item element have a state associated to it. It may be \"in heap\",\n    /// \"pre heap\" or \"post heap\". The latter two are indifferent from the\n    /// heap's point of view, but may be useful to the user.\n    ///\n    /// The ItemIntMap \\e should be initialized in such way that it maps\n    /// PRE_HEAP (-1) to any element to be put in the heap...\n    enum State {\n      IN_HEAP = 0,\n      PRE_HEAP = -1,\n      POST_HEAP = -2\n    };\n\n  private:\n    std::vector<Pair> data;\n    Compare comp;\n    ItemIntMap &iim;\n\n  public:\n    /// \\brief The constructor.\n    ///\n    /// The constructor.\n    /// \\param _iim should be given to the constructor, since it is used\n    /// internally to handle the cross references. The value of the map\n    /// should be PRE_HEAP (-1) for each element.\n    explicit BinHeap(ItemIntMap &_iim) : iim(_iim) {}\n    \n    /// \\brief The constructor.\n    ///\n    /// The constructor.\n    /// \\param _iim should be given to the constructor, since it is used\n    /// internally to handle the cross references. The value of the map\n    /// should be PRE_HEAP (-1) for each element.\n    ///\n    /// \\param _comp The comparator function object.\n    BinHeap(ItemIntMap &_iim, const Compare &_comp) \n      : iim(_iim), comp(_comp) {}\n\n\n    /// The number of items stored in the heap.\n    ///\n    /// \\brief Returns the number of items stored in the heap.\n    int size() const { return data.size(); }\n    \n    /// \\brief Checks if the heap stores no items.\n    ///\n    /// Returns \\c true if and only if the heap stores no items.\n    bool empty() const { return data.empty(); }\n\n    /// \\brief Make empty this heap.\n    /// \n    /// Make empty this heap. It does not change the cross reference map.\n    /// If you want to reuse what is not surely empty you should first clear\n    /// the heap and after that you should set the cross reference map for\n    /// each item to \\c PRE_HEAP.\n    void clear() { \n      data.clear(); \n    }\n\n  private:\n    static int parent(int i) { return (i-1)/2; }\n\n    static int second_child(int i) { return 2*i+2; }\n    bool less(const Pair &p1, const Pair &p2) const {\n      return comp(p1.second, p2.second);\n    }\n\n    int bubble_up(int hole, Pair p) {\n      int par = parent(hole);\n      while( hole>0 && less(p,data[par]) ) {\n\tmove(data[par],hole);\n\thole = par;\n\tpar = parent(hole);\n      }\n      move(p, hole);\n      return hole;\n    }\n\n    int bubble_down(int hole, Pair p, int length) {\n      int child = second_child(hole);\n      while(child < length) {\n\tif( less(data[child-1], data[child]) ) {\n\t  --child;\n\t}\n\tif( !less(data[child], p) )\n\t  goto ok;\n\tmove(data[child], hole);\n\thole = child;\n\tchild = second_child(hole);\n      }\n      child--;\n      if( child<length && less(data[child], p) ) {\n\tmove(data[child], hole);\n\thole=child;\n      }\n    ok:\n      move(p, hole);\n      return hole;\n    }\n\n    void move(const Pair &p, int i) {\n      data[i] = p;\n      iim.set(p.first, i);\n    }\n\n  public:\n    /// \\brief Insert a pair of item and priority into the heap.\n    ///\n    /// Adds \\c p.first to the heap with priority \\c p.second.\n    /// \\param p The pair to insert.\n    void push(const Pair &p) {\n      int n = data.size();\n      data.resize(n+1);\n      bubble_up(n, p);\n    }\n\n    /// \\brief Insert an item into the heap with the given heap.\n    ///    \n    /// Adds \\c i to the heap with priority \\c p. \n    /// \\param i The item to insert.\n    /// \\param p The priority of the item.\n    void push(const Item &i, const Prio &p) { push(Pair(i,p)); }\n\n    /// \\brief Returns the item with minimum priority relative to \\c Compare.\n    ///\n    /// This method returns the item with minimum priority relative to \\c\n    /// Compare.  \n    /// \\pre The heap must be nonempty.  \n    Item top() const {\n      return data[0].first;\n    }\n\n    /// \\brief Returns the minimum priority relative to \\c Compare.\n    ///\n    /// It returns the minimum priority relative to \\c Compare.\n    /// \\pre The heap must be nonempty.\n    Prio prio() const {\n      return data[0].second;\n    }\n\n    /// \\brief Deletes the item with minimum priority relative to \\c Compare.\n    ///\n    /// This method deletes the item with minimum priority relative to \\c\n    /// Compare from the heap.  \n    /// \\pre The heap must be non-empty.  \n    void pop() {\n      int n = data.size()-1;\n      iim.set(data[0].first, POST_HEAP);\n      if (n > 0) {\n\tbubble_down(0, data[n], n);\n      }\n      data.pop_back();\n    }\n\n    /// \\brief Deletes \\c i from the heap.\n    ///\n    /// This method deletes item \\c i from the heap.\n    /// \\param i The item to erase.\n    /// \\pre The item should be in the heap.\n    void erase(const Item &i) {\n      int h = iim[i];\n      int n = data.size()-1;\n      iim.set(data[h].first, POST_HEAP);\n      if( h < n ) {\n\tif ( bubble_up(h, data[n]) == h) {\n\t  bubble_down(h, data[n], n);\n\t}\n      }\n      data.pop_back();\n    }\n\n    \n    /// \\brief Returns the priority of \\c i.\n    ///\n    /// This function returns the priority of item \\c i.  \n    /// \\pre \\c i must be in the heap.\n    /// \\param i The item.\n    Prio operator[](const Item &i) const {\n      int idx = iim[i];\n      return data[idx].second;\n    }\n\n    /// \\brief \\c i gets to the heap with priority \\c p independently \n    /// if \\c i was already there.\n    ///\n    /// This method calls \\ref push(\\c i, \\c p) if \\c i is not stored\n    /// in the heap and sets the priority of \\c i to \\c p otherwise.\n    /// \\param i The item.\n    /// \\param p The priority.\n    void set(const Item &i, const Prio &p) {\n      int idx = iim[i];\n      if( idx < 0 ) {\n\tpush(i,p);\n      }\n      else if( comp(p, data[idx].second) ) {\n\tbubble_up(idx, Pair(i,p));\n      }\n      else {\n\tbubble_down(idx, Pair(i,p), data.size());\n      }\n    }\n\n    /// \\brief Decreases the priority of \\c i to \\c p.\n    ///\n    /// This method decreases the priority of item \\c i to \\c p.\n    /// \\pre \\c i must be stored in the heap with priority at least \\c\n    /// p relative to \\c Compare.\n    /// \\param i The item.\n    /// \\param p The priority.\n    void decrease(const Item &i, const Prio &p) {\n      int idx = iim[i];\n      bubble_up(idx, Pair(i,p));\n    }\n    \n    /// \\brief Increases the priority of \\c i to \\c p.\n    ///\n    /// This method sets the priority of item \\c i to \\c p. \n    /// \\pre \\c i must be stored in the heap with priority at most \\c\n    /// p relative to \\c Compare.\n    /// \\param i The item.\n    /// \\param p The priority.\n    void increase(const Item &i, const Prio &p) {\n      int idx = iim[i];\n      bubble_down(idx, Pair(i,p), data.size());\n    }\n\n    /// \\brief Returns if \\c item is in, has already been in, or has \n    /// never been in the heap.\n    ///\n    /// This method returns PRE_HEAP if \\c item has never been in the\n    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP\n    /// otherwise. In the latter case it is possible that \\c item will\n    /// get back to the heap again.\n    /// \\param i The item.\n    State state(const Item &i) const {\n      int s = iim[i];\n      if( s>=0 )\n\ts=0;\n      return State(s);\n    }\n\n    /// \\brief Sets the state of the \\c item in the heap.\n    ///\n    /// Sets the state of the \\c item in the heap. It can be used to\n    /// manually clear the heap when it is important to achive the\n    /// better time complexity.\n    /// \\param i The item.\n    /// \\param st The state. It should not be \\c IN_HEAP. \n    void state(const Item& i, State st) {\n      switch (st) {\n      case POST_HEAP:\n      case PRE_HEAP:\n        if (state(i) == IN_HEAP) {\n          erase(i);\n        }\n        iim[i] = st;\n        break;\n      case IN_HEAP:\n        break;\n      }\n    }\n\n    /// \\brief Replaces an item in the heap.\n    ///\n    /// The \\c i item is replaced with \\c j item. The \\c i item should\n    /// be in the heap, while the \\c j should be out of the heap. The\n    /// \\c i item will out of the heap and \\c j will be in the heap\n    /// with the same prioriority as prevoiusly the \\c i item.\n    void replace(const Item& i, const Item& j) {\n      int idx = iim[i];\n      iim.set(i, iim[j]);\n      iim.set(j, idx);\n      data[idx].first = j;\n    }\n\n  }; // class BinHeap\n  \n} // namespace lemon\n\n#endif // LEMON_BIN_HEAP_H\n"
  },
  {
    "path": "src/lemon/bipartite_matching.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BIPARTITE_MATCHING\n#define LEMON_BIPARTITE_MATCHING\n\n#include <functional>\n\n#include <lemon/bin_heap.h>\n#include <lemon/fib_heap.h>\n#include <lemon/maps.h>\n\n#include <iostream>\n\n///\\ingroup matching\n///\\file\n///\\brief Maximum matching algorithms in bipartite graphs.\n///\n///\\note The pr_bipartite_matching.h file also contains algorithms to\n///solve maximum cardinality bipartite matching problems.\n\nnamespace lemon {\n\t\n\t/// \\ingroup matching\n\t///\n\t/// \\brief Bipartite Max Cardinality Matching algorithm\n\t///\n\t/// Bipartite Max Cardinality Matching algorithm. This class implements\n\t/// the Hopcroft-Karp algorithm which has \\f$ O(e\\sqrt{n}) \\f$ time\n\t/// complexity.\n\t///\n\t/// \\note In several cases the push-relabel based algorithms have\n\t/// better runtime performance than the augmenting path based ones. \n\t///\n\t/// \\see PrBipartiteMatching\n\ttemplate <typename BpUGraph>\n\tclass MaxBipartiteMatching {\n\tprotected:\n\t\t\n\t\ttypedef BpUGraph Graph;\n\t\t\n\t\ttypedef typename Graph::Node Node;\n\t\ttypedef typename Graph::ANodeIt ANodeIt;\n\t\ttypedef typename Graph::BNodeIt BNodeIt;\n\t\ttypedef typename Graph::UEdge UEdge;\n\t\ttypedef typename Graph::UEdgeIt UEdgeIt;\n\t\ttypedef typename Graph::IncEdgeIt IncEdgeIt;\n\t\t\n\t\ttypedef typename BpUGraph::template ANodeMap<UEdge> ANodeMatchingMap;\n\t\ttypedef typename BpUGraph::template BNodeMap<UEdge> BNodeMatchingMap;\n\t\t\n\t\t\n\tpublic:\n\t\t\n\t\t/// \\brief Constructor.\n\t\t///\n\t\t/// Constructor of the algorithm. \n\t\tMaxBipartiteMatching(const BpUGraph& graph) \n\t\t: _matching(graph), _rmatching(graph), _reached(graph), _graph(&graph) {}\n\t\t\n\t\t/// \\name Execution control\n\t\t/// The simplest way to execute the algorithm is to use\n\t\t/// one of the member functions called \\c run().\n\t\t/// \\n\n\t\t/// If you need more control on the execution,\n\t\t/// first you must call \\ref init() or one alternative for it.\n\t\t/// Finally \\ref start() will perform the matching computation or\n\t\t/// with step-by-step execution you can augment the solution.\n\t\t\n\t\t/// @{\n\t\t\n\t\t/// \\brief Initalize the data structures.\n\t\t///\n\t\t/// It initalizes the data structures and creates an empty matching.\n\t\tvoid init() {\n\t\t\tfor (ANodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\t_matching.set(it, INVALID);\n\t\t\t}\n\t\t\tfor (BNodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\t_rmatching.set(it, INVALID);\n\t\t\t\t_reached.set(it, -1);\n\t\t\t}\n\t\t\t_size = 0;\n\t\t\t_phase = -1;\n\t\t}\n\t\t\n\t\t/// \\brief Initalize the data structures.\n\t\t///\n\t\t/// It initalizes the data structures and creates a greedy\n\t\t/// matching.  From this matching sometimes it is faster to get\n\t\t/// the matching than from the initial empty matching.\n\t\tvoid greedyInit() {\n\t\t\t_size = 0;\n\t\t\tfor (BNodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\t_rmatching.set(it, INVALID);\n\t\t\t\t_reached.set(it, 0);\n\t\t\t}\n\t\t\tfor (ANodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\t_matching[it] = INVALID;\n\t\t\t\tfor (IncEdgeIt jt(*_graph, it); jt != INVALID; ++jt) {\n\t\t\t\t\tif (_rmatching[_graph->bNode(jt)] == INVALID) {\n\t\t\t\t\t\t_matching.set(it, jt);\n\t\t\t\t\t\t_rmatching.set(_graph->bNode(jt), jt);\n\t\t\t\t\t\t_reached.set(_graph->bNode(jt), -1);\n\t\t\t\t\t\t++_size;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t_phase = 0;\n\t\t}\n\t\t\n\t\t/// \\brief Initalize the data structures with an initial matching.\n\t\t///\n\t\t/// It initalizes the data structures with an initial matching.\n\t\ttemplate <typename MatchingMap>\n\t\tvoid matchingInit(const MatchingMap& mm) {\n\t\t\tfor (ANodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\t_matching.set(it, INVALID);\n\t\t\t}\n\t\t\tfor (BNodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\t_rmatching.set(it, INVALID);\n\t\t\t\t_reached.set(it, 0);\n\t\t\t}\n\t\t\t_size = 0;\n\t\t\tfor (UEdgeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tif (mm[it]) {\n\t\t\t\t\t++_size;\n\t\t\t\t\t_matching.set(_graph->aNode(it), it);\n\t\t\t\t\t_rmatching.set(_graph->bNode(it), it);\n\t\t\t\t\t_reached.set(_graph->bNode(it), 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\t_phase = 0;\n\t\t}\n\t\t\n\t\t/// \\brief Initalize the data structures with an initial matching.\n\t\t///\n\t\t/// It initalizes the data structures with an initial matching.\n\t\t/// \\return %True when the given map contains really a matching.\n\t\ttemplate <typename MatchingMap>\n\t\tbool checkedMatchingInit(const MatchingMap& mm) {\n\t\t\tfor (ANodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\t_matching.set(it, INVALID);\n\t\t\t}\n\t\t\tfor (BNodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\t_rmatching.set(it, INVALID);\n\t\t\t\t_reached.set(it, 0);\n\t\t\t}\n\t\t\t_size = 0;\n\t\t\tfor (UEdgeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tif (mm[it]) {\n\t\t\t\t\t++_size;\n\t\t\t\t\tif (_matching[_graph->aNode(it)] != INVALID) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t_matching.set(_graph->aNode(it), it);\n\t\t\t\t\tif (_matching[_graph->bNode(it)] != INVALID) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t_matching.set(_graph->bNode(it), it);\n\t\t\t\t\t_reached.set(_graph->bNode(it), -1);\n\t\t\t\t}\n\t\t\t}\n\t\t\t_phase = 0;\n\t\t\treturn true;\n\t\t}\n\t\t\n\tprivate:\n\t\t\n\t\tbool _find_path(Node anode, int maxlevel,\n\t\t\t\t\t\ttypename Graph::template BNodeMap<int>& level) {\n\t\t\tfor (IncEdgeIt it(*_graph, anode); it != INVALID; ++it) {\n\t\t\t\tNode bnode = _graph->bNode(it); \n\t\t\t\tif (level[bnode] == maxlevel) {\n\t\t\t\t\tlevel.set(bnode, -1);\n\t\t\t\t\tif (maxlevel == 0) {\n\t\t\t\t\t\t_matching.set(anode, it);\n\t\t\t\t\t\t_rmatching.set(bnode, it);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tNode nnode = _graph->aNode(_rmatching[bnode]);\n\t\t\t\t\t\tif (_find_path(nnode, maxlevel - 1, level)) {\n\t\t\t\t\t\t\t_matching.set(anode, it);\n\t\t\t\t\t\t\t_rmatching.set(bnode, it);\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\t\n\tpublic:\n\t\t\n\t\t/// \\brief An augmenting phase of the Hopcroft-Karp algorithm\n\t\t///\n\t\t/// It runs an augmenting phase of the Hopcroft-Karp\n\t\t/// algorithm. This phase finds maximal edge disjoint augmenting\n\t\t/// paths and augments on these paths. The algorithm consists at\n\t\t/// most of \\f$ O(\\sqrt{n}) \\f$ phase and one phase is \\f$ O(e)\n\t\t/// \\f$ long.\n\t\tbool augment() {\n\t\t\t\n\t\t\t++_phase;\n\t\t\t\n\t\t\ttypename Graph::template BNodeMap<int> _level(*_graph, -1);\n\t\t\t//typename Graph::template ANodeMap<int> _found(*_graph, false);\n\t\t\ttypename Graph::template ANodeMap<bool> _found(*_graph, false);\n\t\t\tstd::vector<Node> queue, aqueue;\n\t\t\tfor (BNodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tif (_rmatching[it] == INVALID) {\n\t\t\t\t\tqueue.push_back(it);\n\t\t\t\t\t_reached.set(it, _phase);\n\t\t\t\t\t_level.set(it, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tbool success = false;\n\t\t\t\n\t\t\tint level = 0;\n\t\t\t//std::vector<Node> nqueue;\n\t\t\twhile (!success && !queue.empty()) {\n\t\t\t\t//nqueue.clear();\n\t\t\t\tstd::vector<Node> nqueue;\n\t\t\t\tfor (int i = 0; i < int(queue.size()); ++i) {\n\t\t\t\t\tNode bnode = queue[i];\n\t\t\t\t\tfor (IncEdgeIt jt(*_graph, bnode); jt != INVALID; ++jt) {\n\t\t\t\t\t\tNode anode = _graph->aNode(jt);\n\t\t\t\t\t\tif (_matching[anode] == INVALID) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (!_found[anode]) {\n\t\t\t\t\t\t\t\tif (_find_path(anode, level, _level)) {\n\t\t\t\t\t\t\t\t\t++_size;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t_found.set(anode, true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsuccess = true;\n\t\t\t\t\t\t} else {           \n\t\t\t\t\t\t\tNode nnode = _graph->bNode(_matching[anode]);\n\t\t\t\t\t\t\tif (_reached[nnode] != _phase) {\n\t\t\t\t\t\t\t\t_reached.set(nnode, _phase);\n\t\t\t\t\t\t\t\tnqueue.push_back(nnode);\n\t\t\t\t\t\t\t\t_level.set(nnode, level + 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t++level;\n\t\t\t\tqueue.swap(nqueue);\n\t\t\t}\n\t\t\t\n\t\t\treturn success;\n\t\t}\n\tprivate:\n\t\t\n\t\tvoid _find_path_bfs(Node anode,\n\t\t\t\t\t\t\ttypename Graph::template ANodeMap<UEdge>& pred) {\n\t\t\twhile (true) {\n\t\t\t\tUEdge uedge = pred[anode];\n\t\t\t\tNode bnode = _graph->bNode(uedge);\n\t\t\t\t\n\t\t\t\tUEdge nedge = _rmatching[bnode];\n\t\t\t\t\n\t\t\t\t_matching.set(anode, uedge);\n\t\t\t\t_rmatching.set(bnode, uedge);\n\t\t\t\t\n\t\t\t\tif (nedge == INVALID) break;\n\t\t\t\tanode = _graph->aNode(nedge);\n\t\t\t}\n\t\t}\n\t\t\n\tpublic:\n\t\t\n\t\t/// \\brief An augmenting phase with single path augementing\n\t\t///\n\t\t/// This phase finds only one augmenting paths and augments on\n\t\t/// these paths. The algorithm consists at most of \\f$ O(n) \\f$\n\t\t/// phase and one phase is \\f$ O(e) \\f$ long.\n\t\tbool simpleAugment() { \n\t\t\t++_phase;\n\t\t\t\n\t\t\ttypename Graph::template ANodeMap<UEdge> _pred(*_graph);\n\t\t\t\n\t\t\tstd::vector<Node> queue, aqueue;\n\t\t\tfor (BNodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tif (_rmatching[it] == INVALID) {\n\t\t\t\t\tqueue.push_back(it);\n\t\t\t\t\t_reached.set(it, _phase);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tbool success = false;\n\t\t\t\n\t\t\tint level = 0;\n\t\t\twhile (!success && !queue.empty()) {\n\t\t\t\tstd::vector<Node> nqueue;\n\t\t\t\tfor (int i = 0; i < int(queue.size()); ++i) {\n\t\t\t\t\tNode bnode = queue[i];\n\t\t\t\t\tfor (IncEdgeIt jt(*_graph, bnode); jt != INVALID; ++jt) {\n\t\t\t\t\t\tNode anode = _graph->aNode(jt);\n\t\t\t\t\t\tif (_matching[anode] == INVALID) {\n\t\t\t\t\t\t\t_pred.set(anode, jt);\n\t\t\t\t\t\t\t_find_path_bfs(anode, _pred);\n\t\t\t\t\t\t\t++_size;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t} else {           \n\t\t\t\t\t\t\tNode nnode = _graph->bNode(_matching[anode]);\n\t\t\t\t\t\t\tif (_reached[nnode] != _phase) {\n\t\t\t\t\t\t\t\t_pred.set(anode, jt);\n\t\t\t\t\t\t\t\t_reached.set(nnode, _phase);\n\t\t\t\t\t\t\t\tnqueue.push_back(nnode);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t++level;\n\t\t\t\tqueue.swap(nqueue);\n\t\t\t}\n\t\t\t\n\t\t\treturn success;\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t/// \\brief Starts the algorithm.\n\t\t///\n\t\t/// Starts the algorithm. It runs augmenting phases until the optimal\n\t\t/// solution reached.\n\t\tvoid start() {\n\t\t\twhile (augment()) {}\n\t\t}\n\t\t\n\t\t/// \\brief Runs the algorithm.\n\t\t///\n\t\t/// It just initalize the algorithm and then start it.\n\t\tvoid run() {\n\t\t\tgreedyInit();\n\t\t\tstart();\n\t\t}\n\t\t\n\t\t/// @}\n\t\t\n\t\t/// \\name Query Functions\n\t\t/// The result of the %Matching algorithm can be obtained using these\n\t\t/// functions.\\n\n\t\t/// Before the use of these functions,\n\t\t/// either run() or start() must be called.\n\t\t\n\t\t///@{\n\t\t\n\t\t/// \\brief Return true if the given uedge is in the matching.\n\t\t/// \n\t\t/// It returns true if the given uedge is in the matching.\n\t\tbool matchingEdge(const UEdge& edge) const {\n\t\t\treturn _matching[_graph->aNode(edge)] == edge;\n\t\t}\n\t\t\n\t\t/// \\brief Returns the matching edge from the node.\n\t\t/// \n\t\t/// Returns the matching edge from the node. If there is not such\n\t\t/// edge it gives back \\c INVALID.\n\t\t/// \\note If the parameter node is a B-node then the running time is\n\t\t/// propotional to the degree of the node.\n\t\tUEdge matchingEdge(const Node& node) const {\n\t\t\tif (_graph->aNode(node)) {\n\t\t\t\treturn _matching[node];\n\t\t\t} else {\n\t\t\t\treturn _rmatching[node];\n\t\t\t}\n\t\t}\n\t\t\n\t\t/// \\brief Set true all matching uedge in the map.\n\t\t/// \n\t\t/// Set true all matching uedge in the map. It does not change the\n\t\t/// value mapped to the other uedges.\n\t\t/// \\return The number of the matching edges.\n\t\ttemplate <typename MatchingMap>\n\t\tint quickMatching(MatchingMap& mm) const {\n\t\t\tfor (ANodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tif (_matching[it] != INVALID) {\n\t\t\t\t\tmm.set(_matching[it], true);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn _size;\n\t\t}\n\t\t\n\t\t/// \\brief Set true all matching uedge in the map and the others to false.\n\t\t/// \n\t\t/// Set true all matching uedge in the map and the others to false.\n\t\t/// \\return The number of the matching edges.\n\t\ttemplate <typename MatchingMap>\n\t\tint matching(MatchingMap& mm) const {\n\t\t\tfor (UEdgeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tmm.set(it, it == _matching[_graph->aNode(it)]);\n\t\t\t}\n\t\t\treturn _size;\n\t\t}\n\t\t\n\t\t///Gives back the matching in an ANodeMap.\n\t\t\n\t\t///Gives back the matching in an ANodeMap. The parameter should\n\t\t///be a write ANodeMap of UEdge values.\n\t\t///\\return The number of the matching edges.\n\t\ttemplate<class MatchingMap>\n\t\tint aMatching(MatchingMap& mm) const {\n\t\t\tfor (ANodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tmm.set(it, _matching[it]);\n\t\t\t}\n\t\t\treturn _size;\n\t\t}\n\t\t\n\t\t///Gives back the matching in a BNodeMap.\n\t\t\n\t\t///Gives back the matching in a BNodeMap. The parameter should\n\t\t///be a write BNodeMap of UEdge values.\n\t\t///\\return The number of the matching edges.\n\t\ttemplate<class MatchingMap>\n\t\tint bMatching(MatchingMap& mm) const {\n\t\t\tfor (BNodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tmm.set(it, _rmatching[it]);\n\t\t\t}\n\t\t\treturn _size;\n\t\t}\n\t\t\n\t\t/// \\brief Returns a minimum covering of the nodes.\n\t\t///\n\t\t/// The minimum covering set problem is the dual solution of the\n\t\t/// maximum bipartite matching. It provides a solution for this\n\t\t/// problem what is proof of the optimality of the matching.\n\t\t/// \\return The size of the cover set.\n\t\ttemplate <typename CoverMap>\n\t\tint coverSet(CoverMap& covering) const {\n\t\t\t\n\t\t\tint size = 0;\n\t\t\tfor (ANodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tbool cn = _matching[it] != INVALID && \n\t\t\t\t_reached[_graph->bNode(_matching[it])] == _phase;\n\t\t\t\tcovering.set(it, cn);\n\t\t\t\tif (cn) ++size;\n\t\t\t}\n\t\t\tfor (BNodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tbool cn = _reached[it] != _phase;\n\t\t\t\tcovering.set(it, cn);\n\t\t\t\tif (cn) ++size;\n\t\t\t}\n\t\t\treturn size;\n\t\t}\n\t\t\n\t\t/// \\brief Gives back a barrier on the A-nodes\n\t\t///    \n\t\t/// The barrier is s subset of the nodes on the same side of the\n\t\t/// graph, which size minus its neighbours is exactly the\n\t\t/// unmatched nodes on the A-side.  \n\t\t/// \\retval barrier A WriteMap on the ANodes with bool value.\n\t\ttemplate <typename BarrierMap>\n\t\tvoid aBarrier(BarrierMap& barrier) const {\n\t\t\t\n\t\t\tfor (ANodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tbarrier.set(it, _matching[it] == INVALID || \n\t\t\t\t\t\t\t_reached[_graph->bNode(_matching[it])] != _phase);\n\t\t\t}\n\t\t}\n\t\t\n\t\t/// \\brief Gives back a barrier on the B-nodes\n\t\t///    \n\t\t/// The barrier is s subset of the nodes on the same side of the\n\t\t/// graph, which size minus its neighbours is exactly the\n\t\t/// unmatched nodes on the B-side.  \n\t\t/// \\retval barrier A WriteMap on the BNodes with bool value.\n\t\ttemplate <typename BarrierMap>\n\t\tvoid bBarrier(BarrierMap& barrier) const {\n\t\t\t\n\t\t\tfor (BNodeIt it(*_graph); it != INVALID; ++it) {\n\t\t\t\tbarrier.set(it, _reached[it] == _phase);\n\t\t\t}\n\t\t}\n\t\t\n\t\t/// \\brief Gives back the number of the matching edges.\n\t\t///\n\t\t/// Gives back the number of the matching edges.\n\t\tint matchingSize() const {\n\t\t\treturn _size;\n\t\t}\n\t\t\n\t\t/// @}\n\t\t\n\tprivate:\n\t\t\n\t\ttypename BpUGraph::template ANodeMap<UEdge> _matching;\n\t\ttypename BpUGraph::template BNodeMap<UEdge> _rmatching;\n\t\t\n\t\ttypename BpUGraph::template BNodeMap<int> _reached;\n\t\t\n\t\tint _phase;\n\t\tconst Graph *_graph;\n\t\t\n\t\tint _size;\n\t\t\n\t};\n\t\n\t/// \\ingroup matching\n\t///\n\t/// \\brief Maximum cardinality bipartite matching\n\t///\n\t/// This function calculates the maximum cardinality matching\n\t/// in a bipartite graph. It gives back the matching in an undirected\n\t/// edge map.\n\t///\n\t/// \\param graph The bipartite graph.\n\t/// \\return The size of the matching.\n\ttemplate <typename BpUGraph>\n\tint maxBipartiteMatching(const BpUGraph& graph) {\n\t\tMaxBipartiteMatching<BpUGraph> bpmatching(graph);\n\t\tbpmatching.run();\n\t\treturn bpmatching.matchingSize();\n\t}\n\t\n\t/// \\ingroup matching\n\t///\n\t/// \\brief Maximum cardinality bipartite matching\n\t///\n\t/// This function calculates the maximum cardinality matching\n\t/// in a bipartite graph. It gives back the matching in an undirected\n\t/// edge map.\n\t///\n\t/// \\param graph The bipartite graph.\n\t/// \\retval matching The ANodeMap of UEdges which will be set to covered\n\t/// matching undirected edge.\n\t/// \\return The size of the matching.\n\ttemplate <typename BpUGraph, typename MatchingMap>\n\tint maxBipartiteMatching(const BpUGraph& graph, MatchingMap& matching) {\n\t\tMaxBipartiteMatching<BpUGraph> bpmatching(graph);\n\t\tbpmatching.run();\n\t\tbpmatching.aMatching(matching);\n\t\treturn bpmatching.matchingSize();\n\t}\n\t\n\t/// \\ingroup matching\n\t///\n\t/// \\brief Maximum cardinality bipartite matching\n\t///\n\t/// This function calculates the maximum cardinality matching\n\t/// in a bipartite graph. It gives back the matching in an undirected\n\t/// edge map.\n\t///\n\t/// \\param graph The bipartite graph.\n\t/// \\retval matching The ANodeMap of UEdges which will be set to covered\n\t/// matching undirected edge.\n\t/// \\retval barrier The BNodeMap of bools which will be set to a barrier\n\t/// of the BNode-set.\n\t/// \\return The size of the matching.\n\ttemplate <typename BpUGraph, typename MatchingMap, typename BarrierMap>\n\tint maxBipartiteMatching(const BpUGraph& graph, \n\t\t\t\t\t\t\t MatchingMap& matching, BarrierMap& barrier) {\n\t\tMaxBipartiteMatching<BpUGraph> bpmatching(graph);\n\t\tbpmatching.run();\n\t\tbpmatching.aMatching(matching);\n\t\tbpmatching.bBarrier(barrier);\n\t\treturn bpmatching.matchingSize();\n\t}\n\t\n\t/// \\brief Default traits class for weighted bipartite matching algoritms.\n\t///\n\t/// Default traits class for weighted bipartite matching algoritms.\n\t/// \\param _BpUGraph The bipartite undirected graph type.\n\t/// \\param _WeightMap Type of weight map.\n\ttemplate <typename _BpUGraph, typename _WeightMap>\n\tstruct MaxWeightedBipartiteMatchingDefaultTraits {\n\t\t/// \\brief The type of the weight of the undirected edges.\n\t\ttypedef typename _WeightMap::Value Value;\n\t\t\n\t\t/// The undirected bipartite graph type the algorithm runs on. \n\t\ttypedef _BpUGraph BpUGraph;\n\t\t\n\t\t/// The map of the edges weights\n\t\ttypedef _WeightMap WeightMap;\n\t\t\n\t\t/// \\brief The cross reference type used by heap.\n\t\t///\n\t\t/// The cross reference type used by heap.\n\t\t/// Usually it is \\c Graph::ANodeMap<int>.\n\t\ttypedef typename BpUGraph::template ANodeMap<int> HeapCrossRef;\n\t\t\n\t\t/// \\brief Instantiates a HeapCrossRef.\n\t\t///\n\t\t/// This function instantiates a \\ref HeapCrossRef. \n\t\t/// \\param graph is the graph, to which we would like to define the \n\t\t/// HeapCrossRef.\n\t\tstatic HeapCrossRef *createHeapCrossRef(const BpUGraph &graph) {\n\t\t\treturn new HeapCrossRef(graph);\n\t\t}\n\t\t\n\t\t/// \\brief The heap type used by weighted matching algorithms.\n\t\t///\n\t\t/// The heap type used by weighted matching algorithms. It should\n\t\t/// minimize the priorities and the heap's key type is the graph's\n\t\t/// anode graph's node.\n\t\t///\n\t\t/// \\sa BinHeap\n\t\t//typedef BinHeap<Value, HeapCrossRef> Heap;\n\t\ttypedef FibHeap<Value, HeapCrossRef> Heap;\n\n\t\t/// \\brief Instantiates a Heap.\n\t\t///\n\t\t/// This function instantiates a \\ref Heap. \n\t\t/// \\param crossref The cross reference of the heap.\n\t\tstatic Heap *createHeap(HeapCrossRef& crossref) {\n\t\t\treturn new Heap(crossref);\n\t\t}\n\t\t\n\t};\n\t\n\t\n\t/// \\ingroup matching\n\t///\n\t/// \\brief Bipartite Max Weighted Matching algorithm\n\t///\n\t/// This class implements the bipartite Max Weighted Matching\n\t/// algorithm.  It uses the successive shortest path algorithm to\n\t/// calculate the maximum weighted matching in the bipartite\n\t/// graph. The algorithm can be used also to calculate the maximum\n\t/// cardinality maximum weighted matching. The time complexity\n\t/// of the algorithm is \\f$ O(ne\\log(n)) \\f$ with the default binary\n\t/// heap implementation but this can be improved to \n\t/// \\f$ O(n^2\\log(n)+ne) \\f$ if we use fibonacci heaps.\n\t///\n\t/// The algorithm also provides a potential function on the nodes\n\t/// which a dual solution of the matching algorithm and it can be\n\t/// used to proof the optimality of the given pimal solution.\n#ifdef DOXYGEN\n\ttemplate <typename _BpUGraph, typename _WeightMap, typename _Traits>\n#else\n\ttemplate <typename _BpUGraph, \n\ttypename _WeightMap = typename _BpUGraph::template UEdgeMap<int>,\n\ttypename _Traits = \n\tMaxWeightedBipartiteMatchingDefaultTraits<_BpUGraph, _WeightMap> >\n#endif\n\tclass MaxWeightedBipartiteMatching {\npublic:\n\t\n    typedef _Traits Traits;\n    typedef typename Traits::BpUGraph BpUGraph;\n    typedef typename Traits::WeightMap WeightMap;\n    typedef typename Traits::Value Value;\n\t\nprotected:\n\t\n    typedef typename Traits::HeapCrossRef HeapCrossRef;\n    typedef typename Traits::Heap Heap; \n\t\n    \n    typedef typename BpUGraph::Node Node;\n    typedef typename BpUGraph::ANodeIt ANodeIt;\n    typedef typename BpUGraph::BNodeIt BNodeIt;\n    typedef typename BpUGraph::UEdge UEdge;\n    typedef typename BpUGraph::UEdgeIt UEdgeIt;\n    typedef typename BpUGraph::IncEdgeIt IncEdgeIt;\n\t\n    typedef typename BpUGraph::template ANodeMap<UEdge> ANodeMatchingMap;\n    typedef typename BpUGraph::template BNodeMap<UEdge> BNodeMatchingMap;\n\t\n    typedef typename BpUGraph::template ANodeMap<Value> ANodePotentialMap;\n    typedef typename BpUGraph::template BNodeMap<Value> BNodePotentialMap;\n\t\n\t\npublic:\n\t\n    /// \\brief \\ref Exception for uninitialized parameters.\n    ///\n    /// This error represents problems in the initialization\n    /// of the parameters of the algorithms.\n    class UninitializedParameter : public lemon::UninitializedParameter {\n    public:\n\t\tvirtual const char* what() const throw() {\n\t\t\treturn \"lemon::MaxWeightedBipartiteMatching::UninitializedParameter\";\n\t\t}\n    };\n\t\n    ///\\name Named template parameters\n\t\n    ///@{\n\t\n    template <class H, class CR>\n    struct DefHeapTraits : public Traits {\n\t\ttypedef CR HeapCrossRef;\n\t\ttypedef H Heap;\n\t\tstatic HeapCrossRef *createHeapCrossRef(const BpUGraph &) {\n\t\t\tthrow UninitializedParameter();\n\t\t}\n\t\tstatic Heap *createHeap(HeapCrossRef &) {\n\t\t\tthrow UninitializedParameter();\n\t\t}\n    };\n\t\n    /// \\brief \\ref named-templ-param \"Named parameter\" for setting heap \n    /// and cross reference type\n    ///\n    /// \\ref named-templ-param \"Named parameter\" for setting heap and cross \n    /// reference type\n    template <class H, class CR = typename BpUGraph::template NodeMap<int> >\n    struct DefHeap\n\t: public MaxWeightedBipartiteMatching<BpUGraph, WeightMap, \n\tDefHeapTraits<H, CR> > { \n\ttypedef MaxWeightedBipartiteMatching<BpUGraph, WeightMap, \n\tDefHeapTraits<H, CR> > Create;\n};\n\ntemplate <class H, class CR>\nstruct DefStandardHeapTraits : public Traits {\n\ttypedef CR HeapCrossRef;\n\ttypedef H Heap;\n\tstatic HeapCrossRef *createHeapCrossRef(const BpUGraph &graph) {\n\t\treturn new HeapCrossRef(graph);\n\t}\n\tstatic Heap *createHeap(HeapCrossRef &crossref) {\n\t\treturn new Heap(crossref);\n\t}\n};\n\n/// \\brief \\ref named-templ-param \"Named parameter\" for setting heap and \n/// cross reference type with automatic allocation\n///\n/// \\ref named-templ-param \"Named parameter\" for setting heap and cross \n/// reference type. It can allocate the heap and the cross reference \n/// object if the cross reference's constructor waits for the graph as \n/// parameter and the heap's constructor waits for the cross reference.\ntemplate <class H, class CR = typename BpUGraph::template NodeMap<int> >\nstruct DefStandardHeap\n: public MaxWeightedBipartiteMatching<BpUGraph, WeightMap, \nDefStandardHeapTraits<H, CR> > { \ntypedef MaxWeightedBipartiteMatching<BpUGraph, WeightMap, \nDefStandardHeapTraits<H, CR> > \nCreate;\n};\n\n///@}\n\n\n/// \\brief Constructor.\n///\n/// Constructor of the algorithm. \nMaxWeightedBipartiteMatching(const BpUGraph& _graph, \n\t\t\t\t\t\t\t const WeightMap& _weight) \n: graph(&_graph), weight(&_weight),\nanode_matching(_graph), bnode_matching(_graph),\nanode_potential(_graph), bnode_potential(_graph),\n_heap_cross_ref(0), local_heap_cross_ref(false),\n_heap(0), local_heap(0) {}\n\n/// \\brief Destructor.\n///\n/// Destructor of the algorithm.\n~MaxWeightedBipartiteMatching() {\n\tdestroyStructures();\n}\n\n/// \\brief Sets the heap and the cross reference used by algorithm.\n///\n/// Sets the heap and the cross reference used by algorithm.\n/// If you don't use this function before calling \\ref run(),\n/// it will allocate one. The destuctor deallocates this\n/// automatically allocated map, of course.\n/// \\return \\c (*this)\nMaxWeightedBipartiteMatching& heap(Heap& hp, HeapCrossRef &cr) {\n\tif(local_heap_cross_ref) {\n\t\tdelete _heap_cross_ref;\n\t\tlocal_heap_cross_ref = false;\n\t}\n\t_heap_cross_ref = &cr;\n\tif(local_heap) {\n\t\tdelete _heap;\n\t\tlocal_heap = false;\n\t}\n\t_heap = &hp;\n\treturn *this;\n}\n\n/// \\name Execution control\n/// The simplest way to execute the algorithm is to use\n/// one of the member functions called \\c run().\n/// \\n\n/// If you need more control on the execution,\n/// first you must call \\ref init() or one alternative for it.\n/// Finally \\ref start() will perform the matching computation or\n/// with step-by-step execution you can augment the solution.\n\n/// @{\n\n/// \\brief Initalize the data structures.\n///\n/// It initalizes the data structures and creates an empty matching.\nvoid init() {\n\tinitStructures();\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        anode_matching[it] = INVALID;\n        anode_potential[it] = 0;\n\t}\n\tfor (BNodeIt it(*graph); it != INVALID; ++it) {\n        bnode_matching[it] = INVALID;\n        bnode_potential[it] = 0;\n        for (IncEdgeIt jt(*graph, it); jt != INVALID; ++jt) {\n\t\t\tif ((*weight)[jt] > bnode_potential[it]) {\n\t\t\t\tbnode_potential[it] = (*weight)[jt];\n\t\t\t}\n        }\n\t}\n\tmatching_value = 0;\n\tmatching_size = 0;\n}\n\n\n/// \\brief An augmenting phase of the weighted matching algorithm\n///\n/// It runs an augmenting phase of the weighted matching \n/// algorithm. This phase finds the best augmenting path and \n/// augments only on this paths. \n///\n/// The algorithm consists at most \n/// of \\f$ O(n) \\f$ phase and one phase is \\f$ O(n\\log(n)+e) \\f$ \n/// long with Fibonacci heap or \\f$ O((n+e)\\log(n)) \\f$ long \n/// with binary heap.\n/// \\param decrease If the given parameter true the matching value\n/// can be decreased in the augmenting phase. If we would like\n/// to calculate the maximum cardinality maximum weighted matching\n/// then we should let the algorithm to decrease the matching\n/// value in order to increase the number of the matching edges.\nbool augment(bool decrease = false) {\n\t\n\ttypename BpUGraph::template BNodeMap<Value> bdist(*graph);\n\ttypename BpUGraph::template BNodeMap<UEdge> bpred(*graph, INVALID);\n\t\n\tNode bestNode = INVALID;\n\tValue bestValue = 0;\n\t\n\t_heap->clear();\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        (*_heap_cross_ref)[it] = Heap::PRE_HEAP;\n\t}\n\t\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        if (anode_matching[it] == INVALID) {\n\t\t\t_heap->push(it, 0);\n        }\n\t}\n\t\n\tValue bdistMax = 0;\n\twhile (!_heap->empty()) {\n        Node anode = _heap->top();\n        Value avalue = _heap->prio();\n        _heap->pop();\n        for (IncEdgeIt jt(*graph, anode); jt != INVALID; ++jt) {\n\t\t\tif (jt == anode_matching[anode]) continue;\n\t\t\tNode bnode = graph->bNode(jt);\n\t\t\tValue bvalue = avalue  - (*weight)[jt] +\n            anode_potential[anode] + bnode_potential[bnode];\n\t\t\tif (bvalue > bdistMax) {\n\t\t\t\tbdistMax = bvalue;\n\t\t\t}\n\t\t\tif (bpred[bnode] == INVALID || bvalue < bdist[bnode]) {\n\t\t\t\tbdist[bnode] = bvalue;\n\t\t\t\tbpred[bnode] = jt;\n\t\t\t} else continue;\n\t\t\tif (bnode_matching[bnode] != INVALID) {\n\t\t\t\tNode newanode = graph->aNode(bnode_matching[bnode]);\n\t\t\t\tswitch (_heap->state(newanode)) {\n\t\t\t\t\tcase Heap::PRE_HEAP:\n\t\t\t\t\t\t_heap->push(newanode, bvalue);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Heap::IN_HEAP:\n\t\t\t\t\t\tif (bvalue < (*_heap)[newanode]) {\n\t\t\t\t\t\t\t_heap->decrease(newanode, bvalue);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Heap::POST_HEAP:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (bestNode == INVALID || \n\t\t\t\t\tbnode_potential[bnode] - bvalue > bestValue) {\n\t\t\t\t\tbestValue = bnode_potential[bnode] - bvalue;\n\t\t\t\t\tbestNode = bnode;\n\t\t\t\t}\n\t\t\t}\n        }\n\t}\n\t\n\tif (bestNode == INVALID || (!decrease && bestValue < 0)) {\n        return false;\n\t}\n\t\n\tmatching_value += bestValue;\n\t++matching_size;\n\t\n\tfor (BNodeIt it(*graph); it != INVALID; ++it) {\n        if (bpred[it] != INVALID) {\n\t\t\tbnode_potential[it] -= bdist[it];\n        } else {\n\t\t\tbnode_potential[it] -= bdistMax;\n        }\n\t}\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        if (anode_matching[it] != INVALID) {\n\t\t\tNode bnode = graph->bNode(anode_matching[it]);\n\t\t\tif (bpred[bnode] != INVALID) {\n\t\t\t\tanode_potential[it] += bdist[bnode];\n\t\t\t} else {\n\t\t\t\tanode_potential[it] += bdistMax;\n\t\t\t}\n        }\n\t}\n\t\n\twhile (bestNode != INVALID) {\n        UEdge uedge = bpred[bestNode];\n        Node anode = graph->aNode(uedge);\n        \n        bnode_matching[bestNode] = uedge;\n        if (anode_matching[anode] != INVALID) {\n\t\t\tbestNode = graph->bNode(anode_matching[anode]);\n        } else {\n\t\t\tbestNode = INVALID;\n        }\n        anode_matching[anode] = uedge;\n\t}\n\t\n\t\n\treturn true;\n}\n\n/// \\brief Starts the algorithm.\n///\n/// Starts the algorithm. It runs augmenting phases until the\n/// optimal solution reached.\n///\n/// \\param maxCardinality If the given value is true it will\n/// calculate the maximum cardinality maximum matching instead of\n/// the maximum matching.\nvoid start(bool maxCardinality = false) {\n\twhile (augment(maxCardinality)) {}\n}\n\n/// \\brief Runs the algorithm.\n///\n/// It just initalize the algorithm and then start it.\n///\n/// \\param maxCardinality If the given value is true it will\n/// calculate the maximum cardinality maximum matching instead of\n/// the maximum matching.\nvoid run(bool maxCardinality = false) {\n\tinit();\n\tstart(maxCardinality);\n}\n\n/// @}\n\n/// \\name Query Functions\n/// The result of the %Matching algorithm can be obtained using these\n/// functions.\\n\n/// Before the use of these functions,\n/// either run() or start() must be called.\n\n///@{\n\n/// \\brief Gives back the potential in the NodeMap\n///\n/// Gives back the potential in the NodeMap. The matching is optimal\n/// with the current number of edges if \\f$ \\pi(a) + \\pi(b) - w(ab) = 0 \\f$\n/// for each matching edges and \\f$ \\pi(a) + \\pi(b) - w(ab) \\ge 0 \\f$\n/// for each edges. \ntemplate <typename PotentialMap>\nvoid potential(PotentialMap& pt) const {\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        pt.set(it, anode_potential[it]);\n\t}\n\tfor (BNodeIt it(*graph); it != INVALID; ++it) {\n        pt.set(it, bnode_potential[it]);\n\t}\n}\n\n/// \\brief Set true all matching uedge in the map.\n/// \n/// Set true all matching uedge in the map. It does not change the\n/// value mapped to the other uedges.\n/// \\return The number of the matching edges.\ntemplate <typename MatchingMap>\nint quickMatching(MatchingMap& mm) const {\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        if (anode_matching[it] != INVALID) {\n\t\t\tmm.set(anode_matching[it], true);\n        }\n\t}\n\treturn matching_size;\n}\n\n/// \\brief Set true all matching uedge in the map and the others to false.\n/// \n/// Set true all matching uedge in the map and the others to false.\n/// \\return The number of the matching edges.\ntemplate <typename MatchingMap>\nint matching(MatchingMap& mm) const {\n\tfor (UEdgeIt it(*graph); it != INVALID; ++it) {\n        mm.set(it, it == anode_matching[graph->aNode(it)]);\n\t}\n\treturn matching_size;\n}\n\n///Gives back the matching in an ANodeMap.\n\n///Gives back the matching in an ANodeMap. The parameter should\n///be a write ANodeMap of UEdge values.\n///\\return The number of the matching edges.\ntemplate<class MatchingMap>\nint aMatching(MatchingMap& mm) const {\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        mm.set(it, anode_matching[it]);\n\t}\n\treturn matching_size;\n}\n\n///Gives back the matching in a BNodeMap.\n\n///Gives back the matching in a BNodeMap. The parameter should\n///be a write BNodeMap of UEdge values.\n///\\return The number of the matching edges.\ntemplate<class MatchingMap>\nint bMatching(MatchingMap& mm) const {\n\tfor (BNodeIt it(*graph); it != INVALID; ++it) {\n        mm.set(it, bnode_matching[it]);\n\t}\n\treturn matching_size;\n}\n\n\n/// \\brief Return true if the given uedge is in the matching.\n/// \n/// It returns true if the given uedge is in the matching.\nbool matchingEdge(const UEdge& edge) const {\n\treturn anode_matching[graph->aNode(edge)] == edge;\n}\n\n/// \\brief Returns the matching edge from the node.\n/// \n/// Returns the matching edge from the node. If there is not such\n/// edge it gives back \\c INVALID.\nUEdge matchingEdge(const Node& node) const {\n\tif (graph->aNode(node)) {\n        return anode_matching[node];\n\t} else {\n        return bnode_matching[node];\n\t}\n}\n\n/// \\brief Gives back the sum of weights of the matching edges.\n///\n/// Gives back the sum of weights of the matching edges.\nValue matchingValue() const {\n\treturn matching_value;\n}\n\n/// \\brief Gives back the number of the matching edges.\n///\n/// Gives back the number of the matching edges.\nint matchingSize() const {\n\treturn matching_size;\n}\n\n/// @}\n\nprivate:\n\nvoid initStructures() {\n\tif (!_heap_cross_ref) {\n\t\tlocal_heap_cross_ref = true;\n\t\t_heap_cross_ref = Traits::createHeapCrossRef(*graph);\n\t}\n\tif (!_heap) {\n\t\tlocal_heap = true;\n\t\t_heap = Traits::createHeap(*_heap_cross_ref);\n\t}\n}\n\nvoid destroyStructures() {\n\tif (local_heap_cross_ref) delete _heap_cross_ref;\n\tif (local_heap) delete _heap;\n}\n\n\nprivate:\n\nconst BpUGraph *graph;\nconst WeightMap* weight;\n\nANodeMatchingMap anode_matching;\nBNodeMatchingMap bnode_matching;\n\nANodePotentialMap anode_potential;\nBNodePotentialMap bnode_potential;\n\nValue matching_value;\nint matching_size;\n\nHeapCrossRef *_heap_cross_ref;\nbool local_heap_cross_ref;\n\nHeap *_heap;\nbool local_heap;\n\n};\n\n/// \\ingroup matching\n///\n/// \\brief Maximum weighted bipartite matching\n///\n/// This function calculates the maximum weighted matching\n/// in a bipartite graph. It gives back the matching in an undirected\n/// edge map.\n///\n/// \\param graph The bipartite graph.\n/// \\param weight The undirected edge map which contains the weights.\n/// \\retval matching The undirected edge map which will be set to \n/// the matching.\n/// \\return The value of the matching.\ntemplate <typename BpUGraph, typename WeightMap, typename MatchingMap>\ntypename WeightMap::Value \nmaxWeightedBipartiteMatching(const BpUGraph& graph, const WeightMap& weight,\n\t\t\t\t\t\t\t MatchingMap& matching) {\n    MaxWeightedBipartiteMatching<BpUGraph, WeightMap> \n\tbpmatching(graph, weight);\n    bpmatching.run();\n    bpmatching.matching(matching);\n    return bpmatching.matchingValue();\n}\n\n/// \\ingroup matching\n///\n/// \\brief Maximum weighted maximum cardinality bipartite matching\n///\n/// This function calculates the maximum weighted of the maximum cardinality\n/// matchings of a bipartite graph. It gives back the matching in an \n/// undirected edge map.\n///\n/// \\param graph The bipartite graph.\n/// \\param weight The undirected edge map which contains the weights.\n/// \\retval matching The undirected edge map which will be set to \n/// the matching.\n/// \\return The value of the matching.\ntemplate <typename BpUGraph, typename WeightMap, typename MatchingMap>\ntypename WeightMap::Value \nmaxWeightedMaxBipartiteMatching(const BpUGraph& graph, \n\t\t\t\t\t\t\t\tconst WeightMap& weight,\n\t\t\t\t\t\t\t\tMatchingMap& matching) {\n    MaxWeightedBipartiteMatching<BpUGraph, WeightMap> \n\tbpmatching(graph, weight);\n    bpmatching.run(true);\n    bpmatching.matching(matching);\n    return bpmatching.matchingValue();\n}\n\n/// \\brief Default traits class for minimum cost bipartite matching\n/// algoritms.\n///\n/// Default traits class for minimum cost bipartite matching\n/// algoritms.  \n///\n/// \\param _BpUGraph The bipartite undirected graph\n/// type.  \n///\n/// \\param _CostMap Type of cost map.\ntemplate <typename _BpUGraph, typename _CostMap>\nstruct MinCostMaxBipartiteMatchingDefaultTraits {\n    /// \\brief The type of the cost of the undirected edges.\n    typedef typename _CostMap::Value Value;\n\t\n    /// The undirected bipartite graph type the algorithm runs on. \n    typedef _BpUGraph BpUGraph;\n\t\n    /// The map of the edges costs\n    typedef _CostMap CostMap;\n\t\n    /// \\brief The cross reference type used by heap.\n    ///\n    /// The cross reference type used by heap.\n    /// Usually it is \\c Graph::NodeMap<int>.\n    typedef typename BpUGraph::template NodeMap<int> HeapCrossRef;\n\t\n    /// \\brief Instantiates a HeapCrossRef.\n    ///\n    /// This function instantiates a \\ref HeapCrossRef. \n    /// \\param graph is the graph, to which we would like to define the \n    /// HeapCrossRef.\n    static HeapCrossRef *createHeapCrossRef(const BpUGraph &graph) {\n\t\treturn new HeapCrossRef(graph);\n    }\n    \n    /// \\brief The heap type used by costed matching algorithms.\n    ///\n    /// The heap type used by costed matching algorithms. It should\n    /// minimize the priorities and the heap's key type is the graph's\n    /// anode graph's node.\n    ///\n    /// \\sa BinHeap\n    //typedef BinHeap<Value, HeapCrossRef> Heap;\n\ttypedef FibHeap<Value, HeapCrossRef> Heap;\n    \n    /// \\brief Instantiates a Heap.\n    ///\n    /// This function instantiates a \\ref Heap. \n    /// \\param crossref The cross reference of the heap.\n    static Heap *createHeap(HeapCrossRef& crossref) {\n\t\treturn new Heap(crossref);\n    }\n\t\n};\n\n\n/// \\ingroup matching\n///\n/// \\brief Bipartite Min Cost Matching algorithm\n///\n/// This class implements the bipartite Min Cost Matching algorithm.\n/// It uses the successive shortest path algorithm to calculate the\n/// minimum cost maximum matching in the bipartite graph. The time\n/// complexity of the algorithm is \\f$ O(ne\\log(n)) \\f$ with the\n/// default binary heap implementation but this can be improved to\n/// \\f$ O(n^2\\log(n)+ne) \\f$ if we use fibonacci heaps.\n///\n/// The algorithm also provides a potential function on the nodes\n/// which a dual solution of the matching algorithm and it can be\n/// used to proof the optimality of the given pimal solution.\n#ifdef DOXYGEN\ntemplate <typename _BpUGraph, typename _CostMap, typename _Traits>\n#else\ntemplate <typename _BpUGraph, \ntypename _CostMap = typename _BpUGraph::template UEdgeMap<int>,\ntypename _Traits = \nMinCostMaxBipartiteMatchingDefaultTraits<_BpUGraph, _CostMap> >\n#endif\nclass MinCostMaxBipartiteMatching {\npublic:\n\ntypedef _Traits Traits;\ntypedef typename Traits::BpUGraph BpUGraph;\ntypedef typename Traits::CostMap CostMap;\ntypedef typename Traits::Value Value;\n\nprotected:\n\ntypedef typename Traits::HeapCrossRef HeapCrossRef;\ntypedef typename Traits::Heap Heap; \n\n\ntypedef typename BpUGraph::Node Node;\ntypedef typename BpUGraph::ANodeIt ANodeIt;\ntypedef typename BpUGraph::BNodeIt BNodeIt;\ntypedef typename BpUGraph::UEdge UEdge;\ntypedef typename BpUGraph::UEdgeIt UEdgeIt;\ntypedef typename BpUGraph::IncEdgeIt IncEdgeIt;\n\ntypedef typename BpUGraph::template ANodeMap<UEdge> ANodeMatchingMap;\ntypedef typename BpUGraph::template BNodeMap<UEdge> BNodeMatchingMap;\n\ntypedef typename BpUGraph::template ANodeMap<Value> ANodePotentialMap;\ntypedef typename BpUGraph::template BNodeMap<Value> BNodePotentialMap;\n\n\npublic:\n\n/// \\brief \\ref Exception for uninitialized parameters.\n///\n/// This error represents problems in the initialization\n/// of the parameters of the algorithms.\nclass UninitializedParameter : public lemon::UninitializedParameter {\npublic:\n\tvirtual const char* what() const throw() {\n\t\treturn \"lemon::MinCostMaxBipartiteMatching::UninitializedParameter\";\n\t}\n};\n\n///\\name Named template parameters\n\n///@{\n\ntemplate <class H, class CR>\nstruct DefHeapTraits : public Traits {\n\ttypedef CR HeapCrossRef;\n\ttypedef H Heap;\n\tstatic HeapCrossRef *createHeapCrossRef(const BpUGraph &) {\n\t\tthrow UninitializedParameter();\n\t}\n\tstatic Heap *createHeap(HeapCrossRef &) {\n\t\tthrow UninitializedParameter();\n\t}\n};\n\n/// \\brief \\ref named-templ-param \"Named parameter\" for setting heap \n/// and cross reference type\n///\n/// \\ref named-templ-param \"Named parameter\" for setting heap and cross \n/// reference type\ntemplate <class H, class CR = typename BpUGraph::template NodeMap<int> >\nstruct DefHeap\n: public MinCostMaxBipartiteMatching<BpUGraph, CostMap, \nDefHeapTraits<H, CR> > { \ntypedef MinCostMaxBipartiteMatching<BpUGraph, CostMap, \nDefHeapTraits<H, CR> > Create;\n};\n\ntemplate <class H, class CR>\nstruct DefStandardHeapTraits : public Traits {\n\ttypedef CR HeapCrossRef;\n\ttypedef H Heap;\n\tstatic HeapCrossRef *createHeapCrossRef(const BpUGraph &graph) {\n\t\treturn new HeapCrossRef(graph);\n\t}\n\tstatic Heap *createHeap(HeapCrossRef &crossref) {\n\t\treturn new Heap(crossref);\n\t}\n};\n\n/// \\brief \\ref named-templ-param \"Named parameter\" for setting heap and \n/// cross reference type with automatic allocation\n///\n/// \\ref named-templ-param \"Named parameter\" for setting heap and cross \n/// reference type. It can allocate the heap and the cross reference \n/// object if the cross reference's constructor waits for the graph as \n/// parameter and the heap's constructor waits for the cross reference.\ntemplate <class H, class CR = typename BpUGraph::template NodeMap<int> >\nstruct DefStandardHeap\n: public MinCostMaxBipartiteMatching<BpUGraph, CostMap, \nDefStandardHeapTraits<H, CR> > { \ntypedef MinCostMaxBipartiteMatching<BpUGraph, CostMap, \nDefStandardHeapTraits<H, CR> > \nCreate;\n};\n\n///@}\n\n\n/// \\brief Constructor.\n///\n/// Constructor of the algorithm. \nMinCostMaxBipartiteMatching(const BpUGraph& _graph, \n\t\t\t\t\t\t\tconst CostMap& _cost) \n: graph(&_graph), cost(&_cost),\nanode_matching(_graph), bnode_matching(_graph),\nanode_potential(_graph), bnode_potential(_graph),\n_heap_cross_ref(0), local_heap_cross_ref(false),\n_heap(0), local_heap(0) {}\n\n/// \\brief Destructor.\n///\n/// Destructor of the algorithm.\n~MinCostMaxBipartiteMatching() {\n\tdestroyStructures();\n}\n\n/// \\brief Sets the heap and the cross reference used by algorithm.\n///\n/// Sets the heap and the cross reference used by algorithm.\n/// If you don't use this function before calling \\ref run(),\n/// it will allocate one. The destuctor deallocates this\n/// automatically allocated map, of course.\n/// \\return \\c (*this)\nMinCostMaxBipartiteMatching& heap(Heap& hp, HeapCrossRef &cr) {\n\tif(local_heap_cross_ref) {\n\t\tdelete _heap_cross_ref;\n\t\tlocal_heap_cross_ref = false;\n\t}\n\t_heap_cross_ref = &cr;\n\tif(local_heap) {\n\t\tdelete _heap;\n\t\tlocal_heap = false;\n\t}\n\t_heap = &hp;\n\treturn *this;\n}\n\n/// \\name Execution control\n/// The simplest way to execute the algorithm is to use\n/// one of the member functions called \\c run().\n/// \\n\n/// If you need more control on the execution,\n/// first you must call \\ref init() or one alternative for it.\n/// Finally \\ref start() will perform the matching computation or\n/// with step-by-step execution you can augment the solution.\n\n/// @{\n\n/// \\brief Initalize the data structures.\n///\n/// It initalizes the data structures and creates an empty matching.\nvoid init() {\n\tinitStructures();\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        anode_matching[it] = INVALID;\n        anode_potential[it] = 0;\n\t}\n\tfor (BNodeIt it(*graph); it != INVALID; ++it) {\n        bnode_matching[it] = INVALID;\n        bnode_potential[it] = 0;\n\t}\n\tmatching_cost = 0;\n\tmatching_size = 0;\n}\n\n\n/// \\brief An augmenting phase of the costed matching algorithm\n///\n/// It runs an augmenting phase of the matching algorithm. The\n/// phase finds the best augmenting path and augments only on this\n/// paths.\n///\n/// The algorithm consists at most \n/// of \\f$ O(n) \\f$ phase and one phase is \\f$ O(n\\log(n)+e) \\f$ \n/// long with Fibonacci heap or \\f$ O((n+e)\\log(n)) \\f$ long \n/// with binary heap.\nbool augment() {\n\t\n\ttypename BpUGraph::template BNodeMap<Value> bdist(*graph);\n\ttypename BpUGraph::template BNodeMap<UEdge> bpred(*graph, INVALID);\n\t\n\tNode bestNode = INVALID;\n\tValue bestValue = 0;\n\t\n\t_heap->clear();\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        (*_heap_cross_ref)[it] = Heap::PRE_HEAP;\n\t}\n\t\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        if (anode_matching[it] == INVALID) {\n\t\t\t_heap->push(it, 0);\n        }\n\t}\n\tValue bdistMax = 0;\n\t\n\twhile (!_heap->empty()) {\n        Node anode = _heap->top();\n        Value avalue = _heap->prio();\n        _heap->pop();\n        for (IncEdgeIt jt(*graph, anode); jt != INVALID; ++jt) {\n\t\t\tif (jt == anode_matching[anode]) continue;\n\t\t\tNode bnode = graph->bNode(jt);\n\t\t\tValue bvalue = avalue + (*cost)[jt] + \n            anode_potential[anode] - bnode_potential[bnode];\n\t\t\tif (bvalue > bdistMax) {\n\t\t\t\tbdistMax = bvalue;\n\t\t\t}\n\t\t\tif (bpred[bnode] == INVALID || bvalue < bdist[bnode]) {\n\t\t\t\tbdist[bnode] = bvalue;\n\t\t\t\tbpred[bnode] = jt;\n\t\t\t} else continue;\n\t\t\tif (bnode_matching[bnode] != INVALID) {\n\t\t\t\tNode newanode = graph->aNode(bnode_matching[bnode]);\n\t\t\t\tswitch (_heap->state(newanode)) {\n\t\t\t\t\tcase Heap::PRE_HEAP:\n\t\t\t\t\t\t_heap->push(newanode, bvalue);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Heap::IN_HEAP:\n\t\t\t\t\t\tif (bvalue < (*_heap)[newanode]) {\n\t\t\t\t\t\t\t_heap->decrease(newanode, bvalue);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Heap::POST_HEAP:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (bestNode == INVALID || \n\t\t\t\t\tbvalue + bnode_potential[bnode] < bestValue) {\n\t\t\t\t\tbestValue = bvalue + bnode_potential[bnode];\n\t\t\t\t\tbestNode = bnode;\n\t\t\t\t}\n\t\t\t}\n        }\n\t}\n\t\n\tif (bestNode == INVALID) {\n        return false;\n\t}\n\t\n\tmatching_cost += bestValue;\n\t++matching_size;\n\t\n\tfor (BNodeIt it(*graph); it != INVALID; ++it) {\n        if (bpred[it] != INVALID) {\n\t\t\tbnode_potential[it] += bdist[it];\n        } else {\n\t\t\tbnode_potential[it] += bdistMax;\n        }\n\t}\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        if (anode_matching[it] != INVALID) {\n\t\t\tNode bnode = graph->bNode(anode_matching[it]);\n\t\t\tif (bpred[bnode] != INVALID) {\n\t\t\t\tanode_potential[it] += bdist[bnode];\n\t\t\t} else {\n\t\t\t\tanode_potential[it] += bdistMax;\n\t\t\t}\n        }\n\t}\n\t\n\twhile (bestNode != INVALID) {\n        UEdge uedge = bpred[bestNode];\n        Node anode = graph->aNode(uedge);\n        \n        bnode_matching[bestNode] = uedge;\n        if (anode_matching[anode] != INVALID) {\n\t\t\tbestNode = graph->bNode(anode_matching[anode]);\n        } else {\n\t\t\tbestNode = INVALID;\n        }\n        anode_matching[anode] = uedge;\n\t}\n\t\n\t\n\treturn true;\n}\n\n/// \\brief Starts the algorithm.\n///\n/// Starts the algorithm. It runs augmenting phases until the\n/// optimal solution reached.\nvoid start() {\n\twhile (augment()) {}\n}\n\n/// \\brief Runs the algorithm.\n///\n/// It just initalize the algorithm and then start it.\nvoid run() {\n\tinit();\n\tstart();\n}\n\n/// @}\n\n/// \\name Query Functions\n/// The result of the %Matching algorithm can be obtained using these\n/// functions.\\n\n/// Before the use of these functions,\n/// either run() or start() must be called.\n\n///@{\n\n/// \\brief Gives back the potential in the NodeMap\n///\n/// Gives back the potential in the NodeMap. The matching is optimal\n/// with the current number of edges if \\f$ \\pi(a) + \\pi(b) - w(ab) = 0 \\f$\n/// for each matching edges and \\f$ \\pi(a) + \\pi(b) - w(ab) \\ge 0 \\f$\n/// for each edges. \ntemplate <typename PotentialMap>\nvoid potential(PotentialMap& pt) const {\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        pt.set(it, anode_potential[it]);\n\t}\n\tfor (BNodeIt it(*graph); it != INVALID; ++it) {\n        pt.set(it, bnode_potential[it]);\n\t}\n}\n\n/// \\brief Set true all matching uedge in the map.\n/// \n/// Set true all matching uedge in the map. It does not change the\n/// value mapped to the other uedges.\n/// \\return The number of the matching edges.\ntemplate <typename MatchingMap>\nint quickMatching(MatchingMap& mm) const {\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        if (anode_matching[it] != INVALID) {\n\t\t\tmm.set(anode_matching[it], true);\n        }\n\t}\n\treturn matching_size;\n}\n\n/// \\brief Set true all matching uedge in the map and the others to false.\n/// \n/// Set true all matching uedge in the map and the others to false.\n/// \\return The number of the matching edges.\ntemplate <typename MatchingMap>\nint matching(MatchingMap& mm) const {\n\tfor (UEdgeIt it(*graph); it != INVALID; ++it) {\n        mm.set(it, it == anode_matching[graph->aNode(it)]);\n\t}\n\treturn matching_size;\n}\n\n/// \\brief Gives back the matching in an ANodeMap.\n///\n/// Gives back the matching in an ANodeMap. The parameter should\n/// be a write ANodeMap of UEdge values.\n/// \\return The number of the matching edges.\ntemplate<class MatchingMap>\nint aMatching(MatchingMap& mm) const {\n\tfor (ANodeIt it(*graph); it != INVALID; ++it) {\n        mm.set(it, anode_matching[it]);\n\t}\n\treturn matching_size;\n}\n\n/// \\brief Gives back the matching in a BNodeMap.\n///\n/// Gives back the matching in a BNodeMap. The parameter should\n/// be a write BNodeMap of UEdge values.\n/// \\return The number of the matching edges.\ntemplate<class MatchingMap>\nint bMatching(MatchingMap& mm) const {\n\tfor (BNodeIt it(*graph); it != INVALID; ++it) {\n        mm.set(it, bnode_matching[it]);\n\t}\n\treturn matching_size;\n}\n\n/// \\brief Return true if the given uedge is in the matching.\n/// \n/// It returns true if the given uedge is in the matching.\nbool matchingEdge(const UEdge& edge) const {\n\treturn anode_matching[graph->aNode(edge)] == edge;\n}\n\n/// \\brief Returns the matching edge from the node.\n/// \n/// Returns the matching edge from the node. If there is not such\n/// edge it gives back \\c INVALID.\nUEdge matchingEdge(const Node& node) const {\n\tif (graph->aNode(node)) {\n        return anode_matching[node];\n\t} else {\n        return bnode_matching[node];\n\t}\n}\n\n/// \\brief Gives back the sum of costs of the matching edges.\n///\n/// Gives back the sum of costs of the matching edges.\nValue matchingCost() const {\n\treturn matching_cost;\n}\n\n/// \\brief Gives back the number of the matching edges.\n///\n/// Gives back the number of the matching edges.\nint matchingSize() const {\n\treturn matching_size;\n}\n\n/// @}\n\nprivate:\n\nvoid initStructures() {\n\tif (!_heap_cross_ref) {\n\t\tlocal_heap_cross_ref = true;\n\t\t_heap_cross_ref = Traits::createHeapCrossRef(*graph);\n\t}\n\tif (!_heap) {\n\t\tlocal_heap = true;\n\t\t_heap = Traits::createHeap(*_heap_cross_ref);\n\t}\n}\n\nvoid destroyStructures() {\n\tif (local_heap_cross_ref) delete _heap_cross_ref;\n\tif (local_heap) delete _heap;\n}\n\n\nprivate:\n\nconst BpUGraph *graph;\nconst CostMap* cost;\n\nANodeMatchingMap anode_matching;\nBNodeMatchingMap bnode_matching;\n\nANodePotentialMap anode_potential;\nBNodePotentialMap bnode_potential;\n\nValue matching_cost;\nint matching_size;\n\nHeapCrossRef *_heap_cross_ref;\nbool local_heap_cross_ref;\n\nHeap *_heap;\nbool local_heap;\n\n};\n\n/// \\ingroup matching\n///\n/// \\brief Minimum cost maximum cardinality bipartite matching\n///\n/// This function calculates the maximum cardinality matching with\n/// minimum cost of a bipartite graph. It gives back the matching in\n/// an undirected edge map.\n///\n/// \\param graph The bipartite graph.\n/// \\param cost The undirected edge map which contains the costs.\n/// \\retval matching The undirected edge map which will be set to \n/// the matching.\n/// \\return The cost of the matching.\ntemplate <typename BpUGraph, typename CostMap, typename MatchingMap>\ntypename CostMap::Value \nminCostMaxBipartiteMatching(const BpUGraph& graph, \n\t\t\t\t\t\t\tconst CostMap& cost,\n\t\t\t\t\t\t\tMatchingMap& matching) {\n    MinCostMaxBipartiteMatching<BpUGraph, CostMap> \n\tbpmatching(graph, cost);\n    bpmatching.run();\n    bpmatching.matching(matching);\n    return bpmatching.matchingCost();\n}\n\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/alteration_notifier.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_ALTERATION_NOTIFIER_H\n#define LEMON_BITS_ALTERATION_NOTIFIER_H\n\n#include <vector>\n#include <list>\n\n#include <lemon/bits/utility.h>\n\n///\\ingroup graphbits\n///\\file\n///\\brief Observer notifier for graph alteration observers.\n\nnamespace lemon {\n\n  /// \\ingroup graphbits\n  ///\n  /// \\brief Notifier class to notify observes about alterations in \n  /// a container.\n  ///\n  /// The simple graph's can be refered as two containers, one node container\n  /// and one edge container. But they are not standard containers they\n  /// does not store values directly they are just key continars for more\n  /// value containers which are the node and edge maps.\n  ///\n  /// The graph's node and edge sets can be changed as we add or erase\n  /// nodes and edges in the graph. Lemon would like to handle easily\n  /// that the node and edge maps should contain values for all nodes or\n  /// edges. If we want to check on every indicing if the map contains\n  /// the current indicing key that cause a drawback in the performance\n  /// in the library. We use another solution we notify all maps about\n  /// an alteration in the graph, which cause only drawback on the\n  /// alteration of the graph.\n  ///\n  /// This class provides an interface to the container. The \\e first() and \\e \n  /// next() member functions make possible to iterate on the keys of the\n  /// container. The \\e id() function returns an integer id for each key.\n  /// The \\e maxId() function gives back an upper bound of the ids.\n  ///\n  /// For the proper functonality of this class, we should notify it\n  /// about each alteration in the container. The alterations have four type\n  /// as \\e add(), \\e erase(), \\e build() and \\e clear(). The \\e add() and\n  /// \\e erase() signals that only one or few items added or erased to or\n  /// from the graph. If all items are erased from the graph or from an empty\n  /// graph a new graph is builded then it can be signaled with the\n  /// clear() and build() members. Important rule that if we erase items \n  /// from graph we should first signal the alteration and after that erase\n  /// them from the container, on the other way on item addition we should\n  /// first extend the container and just after that signal the alteration.\n  ///\n  /// The alteration can be observed with a class inherited from the\n  /// \\e ObserverBase nested class. The signals can be handled with\n  /// overriding the virtual functions defined in the base class.  The\n  /// observer base can be attached to the notifier with the \n  /// \\e attach() member and can be detached with detach() function. The\n  /// alteration handlers should not call any function which signals\n  /// an other alteration in the same notifier and should not\n  /// detach any observer from the notifier.\n  ///\n  /// Alteration observers try to be exception safe. If an \\e add() or\n  /// a \\e clear() function throws an exception then the remaining\n  /// observeres will not be notified and the fulfilled additions will\n  /// be rolled back by calling the \\e erase() or \\e clear()\n  /// functions. Thence the \\e erase() and \\e clear() should not throw\n  /// exception. Actullay, it can be throw only \n  /// \\ref AlterationObserver::ImmediateDetach ImmediateDetach\n  /// exception which detach the observer from the notifier.\n  ///\n  /// There are some place when the alteration observing is not completly\n  /// reliable. If we want to carry out the node degree in the graph\n  /// as in the \\ref InDegMap and we use the reverseEdge that cause \n  /// unreliable functionality. Because the alteration observing signals\n  /// only erasing and adding but not the reversing it will stores bad\n  /// degrees. The sub graph adaptors cannot signal the alterations because\n  /// just a setting in the filter map can modify the graph and this cannot\n  /// be watched in any way.\n  ///\n  /// \\param _Container The container which is observed.\n  /// \\param _Item The item type which is obserbved.\n  ///\n  /// \\author Balazs Dezso\n\n  template <typename _Container, typename _Item>\n  class AlterationNotifier {\n  public:\n\n    typedef True Notifier;\n\n    typedef _Container Container;\n    typedef _Item Item;\n\n    /// \\brief Exception which can be called from \\e clear() and \n    /// \\e erase().\n    ///\n    /// From the \\e clear() and \\e erase() function only this\n    /// exception is allowed to throw. The exception immediatly\n    /// detaches the current observer from the notifier. Because the\n    /// \\e clear() and \\e erase() should not throw other exceptions\n    /// it can be used to invalidate the observer.\n    struct ImmediateDetach {};\n\n    /// \\brief ObserverBase is the base class for the observers.\n    ///\n    /// ObserverBase is the abstract base class for the observers.\n    /// It will be notified about an item was inserted into or\n    /// erased from the graph.\n    ///\n    /// The observer interface contains some pure virtual functions\n    /// to override. The add() and erase() functions are\n    /// to notify the oberver when one item is added or\n    /// erased.\n    ///\n    /// The build() and clear() members are to notify the observer\n    /// about the container is built from an empty container or\n    /// is cleared to an empty container. \n    /// \n    /// \\author Balazs Dezso\n\n    class ObserverBase {\n    protected:\n      typedef AlterationNotifier Notifier;\n\n      friend class AlterationNotifier;\n\n      /// \\brief Default constructor.\n      ///\n      /// Default constructor for ObserverBase.\n      /// \n      ObserverBase() : _notifier(0) {}\n\n      /// \\brief Constructor which attach the observer into notifier.\n      ///\n      /// Constructor which attach the observer into notifier.\n      ObserverBase(AlterationNotifier& nf) {\n        attach(nf);\n      }\n\n      /// \\brief Constructor which attach the obserever to the same notifier.\n      ///\n      /// Constructor which attach the obserever to the same notifier as\n      /// the other observer is attached to. \n      ObserverBase(const ObserverBase& copy) {\n\tif (copy.attached()) {\n          attach(*copy.notifier());\n\t}\n      }\n\t\n      /// \\brief Destructor\n      virtual ~ObserverBase() {\n        if (attached()) {\n          detach();\n        }\n      }\n\n      /// \\brief Attaches the observer into an AlterationNotifier.\n      ///\n      /// This member attaches the observer into an AlterationNotifier.\n      ///\n      void attach(AlterationNotifier& nf) {\n\tnf.attach(*this);\n      }\n      \n      /// \\brief Detaches the observer into an AlterationNotifier.\n      ///\n      /// This member detaches the observer from an AlterationNotifier.\n      ///\n      void detach() {\n        _notifier->detach(*this);\n      }\n      \n      /// \\brief Gives back a pointer to the notifier which the map \n      /// attached into.\n      ///\n      /// This function gives back a pointer to the notifier which the map\n      /// attached into.\n      ///\n      Notifier* notifier() const { return const_cast<Notifier*>(_notifier); }\n      \n      /// Gives back true when the observer is attached into a notifier.\n      bool attached() const { return _notifier != 0; }\n\n    private:\n\n      ObserverBase& operator=(const ObserverBase& copy);\n\n    protected:\n      \n      Notifier* _notifier;\n      typename std::list<ObserverBase*>::iterator _index;\n\n      /// \\brief The member function to notificate the observer about an\n      /// item is added to the container.\n      ///\n      /// The add() member function notificates the observer about an item\n      /// is added to the container. It have to be overrided in the\n      /// subclasses.\n      virtual void add(const Item&) = 0;\n\n      /// \\brief The member function to notificate the observer about \n      /// more item is added to the container.\n      ///\n      /// The add() member function notificates the observer about more item\n      /// is added to the container. It have to be overrided in the\n      /// subclasses.\n      virtual void add(const std::vector<Item>& items) = 0;\n\n      /// \\brief The member function to notificate the observer about an\n      /// item is erased from the container.\n      ///\n      /// The erase() member function notificates the observer about an\n      /// item is erased from the container. It have to be overrided in\n      /// the subclasses.\t\n      virtual void erase(const Item&) = 0;\n\n      /// \\brief The member function to notificate the observer about \n      /// more item is erased from the container.\n      ///\n      /// The erase() member function notificates the observer about more item\n      /// is erased from the container. It have to be overrided in the\n      /// subclasses.\n      virtual void erase(const std::vector<Item>& items) = 0;\n\n      /// \\brief The member function to notificate the observer about the\n      /// container is built.\n      ///\n      /// The build() member function notificates the observer about the\n      /// container is built from an empty container. It have to be\n      /// overrided in the subclasses.\n\n      virtual void build() = 0;\n\n      /// \\brief The member function to notificate the observer about all\n      /// items are erased from the container.\n      ///\n      /// The clear() member function notificates the observer about all\n      /// items are erased from the container. It have to be overrided in\n      /// the subclasses.      \n      virtual void clear() = 0;\n\n    };\n\t\n  protected:\n\n    const Container* container;\n\n    typedef std::list<ObserverBase*> Observers; \n    Observers _observers;\n\n\t\t\n  public:\n\n    /// \\brief Default constructor.\n    ///\n    /// The default constructor of the AlterationNotifier. \n    /// It creates an empty notifier.\n    AlterationNotifier() \n      : container(0) {}\n\n    /// \\brief Constructor.\n    ///\n    /// Constructor with the observed container parameter.\n    AlterationNotifier(const Container& _container) \n      : container(&_container) {}\n\n    /// \\brief Copy Constructor of the AlterationNotifier. \n    ///\n    /// Copy constructor of the AlterationNotifier. \n    /// It creates only an empty notifier because the copiable\n    /// notifier's observers have to be registered still into that notifier.\n    AlterationNotifier(const AlterationNotifier& _notifier) \n      : container(_notifier.container) {}\n\n    /// \\brief Destructor.\n    ///\t\t\n    /// Destructor of the AlterationNotifier.\n    ///\n    ~AlterationNotifier() {\n      typename Observers::iterator it;\n      for (it = _observers.begin(); it != _observers.end(); ++it) {\n\t(*it)->_notifier = 0;\n      }\n    }\n\n    /// \\brief Sets the container.\n    ///\n    /// Sets the container.\n    void setContainer(const Container& _container) {\n      container = &_container;\n    }\n\n  protected:\n\n    AlterationNotifier& operator=(const AlterationNotifier&);\n\n  public:\n\n\n\n    /// \\brief First item in the container.\n    ///\n    /// Returns the first item in the container. It is\n    /// for start the iteration on the container.\n    void first(Item& item) const {\n      container->first(item);\n    }\n\n    /// \\brief Next item in the container.\n    ///\n    /// Returns the next item in the container. It is\n    /// for iterate on the container.\n    void next(Item& item) const {\n      container->next(item);\n    }\n\n    /// \\brief Returns the id of the item.\n    ///\n    /// Returns the id of the item provided by the container.\n    int id(const Item& item) const {\n      return container->id(item);\n    }\n\n    /// \\brief Returns the maximum id of the container.\n    ///\n    /// Returns the maximum id of the container.\n    int maxId() const {\n      return container->maxId(Item());\n    }\n\t\t\n  protected:\n\n    void attach(ObserverBase& observer) {\n      observer._index = _observers.insert(_observers.begin(), &observer);\n      observer._notifier = this;\n    } \n\n    void detach(ObserverBase& observer) {\n      _observers.erase(observer._index);\n      observer._index = _observers.end();\n      observer._notifier = 0;\n    }\n\n  public:\n\t\n    /// \\brief Notifies all the registed observers about an item added to \n    /// the container.\n    ///\n    /// It notifies all the registed observers about an item added to \n    /// the container.\n    /// \n    void add(const Item& item) {\n      typename Observers::reverse_iterator it;\n      try {\n        for (it = _observers.rbegin(); it != _observers.rend(); ++it) {\n          (*it)->add(item);\n        }\n      } catch (...) {\n        typename Observers::iterator jt;\n        for (jt = it.base(); jt != _observers.end(); ++jt) {\n          (*jt)->erase(item);\n        }\n        throw;\n      }\n    }\t\n\n    /// \\brief Notifies all the registed observers about more item added to \n    /// the container.\n    ///\n    /// It notifies all the registed observers about more item added to \n    /// the container.\n    /// \n    void add(const std::vector<Item>& items) {\n      typename Observers::reverse_iterator it;\n      try {\n        for (it = _observers.rbegin(); it != _observers.rend(); ++it) {\n          (*it)->add(items);\n        }\n      } catch (...) {\n        typename Observers::iterator jt;\n        for (jt = it.base(); jt != _observers.end(); ++jt) {\n          (*jt)->erase(items);\n        }\n        throw;\n      }\n    }\t\n\n    /// \\brief Notifies all the registed observers about an item erased from \n    /// the container.\n    ///\t\n    /// It notifies all the registed observers about an item erased from \n    /// the container.\n    /// \n    void erase(const Item& item) throw() {\n      typename Observers::iterator it = _observers.begin();\n      while (it != _observers.end()) {\n        try {\n          (*it)->erase(item);\n          ++it;\n        } catch (const ImmediateDetach&) {\n          it = _observers.erase(it);\n          (*it)->_index = _observers.end();\n          (*it)->_notifier = 0;\n        }\n      }\n    }\n\n    /// \\brief Notifies all the registed observers about more item erased  \n    /// from the container.\n    ///\t\n    /// It notifies all the registed observers about more item erased from \n    /// the container.\n    /// \n    void erase(const std::vector<Item>& items) {\n      typename Observers::iterator it = _observers.begin();\n      while (it != _observers.end()) {\n        try {\n          (*it)->erase(items);\n          ++it;\n        } catch (const ImmediateDetach&) {\n          it = _observers.erase(it);\n          (*it)->_index = _observers.end();\n          (*it)->_notifier = 0;\n        }\n      }\n    }\n\n    /// \\brief Notifies all the registed observers about the container is \n    /// built.\n    ///\t\t\n    /// Notifies all the registed observers about the container is built\n    /// from an empty container.\n    void build() {\n      typename Observers::reverse_iterator it;\n      try {\n        for (it = _observers.rbegin(); it != _observers.rend(); ++it) {\n          (*it)->build();\n        }\n      } catch (...) {\n        typename Observers::iterator jt;\n        for (jt = it.base(); jt != _observers.end(); ++jt) {\n          (*jt)->clear();\n        }\n        throw;\n      }\n    }\n\n    /// \\brief Notifies all the registed observers about all items are \n    /// erased.\n    ///\n    /// Notifies all the registed observers about all items are erased\n    /// from the container.\n    void clear() {\n      typename Observers::iterator it = _observers.begin();\n      while (it != _observers.end()) {\n        try {\n          (*it)->clear();\n          ++it;\n        } catch (const ImmediateDetach&) {\n          it = _observers.erase(it);\n          (*it)->_index = _observers.end();\n          (*it)->_notifier = 0;\n        }\n      }\n    }\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/array_map.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_ARRAY_MAP_H\n#define LEMON_BITS_ARRAY_MAP_H\n\n#include <memory>\n\n#include <lemon/bits/traits.h>\n#include <lemon/bits/alteration_notifier.h>\n#include <lemon/concept_check.h>\n#include <lemon/concepts/maps.h>\n\n/// \\ingroup graphbits\n/// \\file\n/// \\brief Graph map based on the array storage.\n\nnamespace lemon {\n\t\n\t/// \\ingroup graphbits\n\t///\n\t/// \\brief Graph map based on the array storage.\n\t///\n\t/// The ArrayMap template class is graph map structure what\n\t/// automatically updates the map when a key is added to or erased from\n\t/// the map. This map uses the allocators to implement \n\t/// the container functionality.\n\t///\n\t/// The template parameters are the Graph the current Item type and\n\t/// the Value type of the map.\n\ttemplate <typename _Graph, typename _Item, typename _Value>\n\tclass ArrayMap \n    : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {\n\tpublic:\n\t\t/// The graph type of the maps. \n\t\ttypedef _Graph Graph;\n\t\t/// The item type of the map.\n\t\ttypedef _Item Item;\n\t\t/// The reference map tag.\n\t\ttypedef True ReferenceMapTag;\n\t\t\n\t\t/// The key type of the maps.\n\t\ttypedef _Item Key;\n\t\t/// The value type of the map.\n\t\ttypedef _Value Value;\n\t\t\n\t\t/// The const reference type of the map.\n\t\ttypedef const _Value& ConstReference;\n\t\t/// The reference type of the map.\n\t\ttypedef _Value& Reference;\n\t\t\n\t\t/// The notifier type.\n\t\ttypedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;\n\t\t\n\t\t/// The MapBase of the Map which imlements the core regisitry function.\n\t\ttypedef typename Notifier::ObserverBase Parent;\n\t\t\n\tprivate:\n\t\ttypedef std::allocator<Value> Allocator;\n\t\t\n\tpublic:\n\t\t\n\t\t/// \\brief Graph initialized map constructor.\n\t\t///\n\t\t/// Graph initialized map constructor.\n\t\texplicit ArrayMap(const Graph& graph) {\n\t\t\tParent::attach(graph.notifier(Item()));\n\t\t\tallocate_memory();\n\t\t\tNotifier* nf = Parent::notifier();\n\t\t\tItem it;\n\t\t\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t\t\t\tint id = nf->id(it);;\n\t\t\t\tallocator.construct(&(values[id]), Value());\n\t\t\t}\t\t\t\t\t\t\t\t\n\t\t}\n\t\t\n\t\t/// \\brief Constructor to use default value to initialize the map. \n\t\t///\n\t\t/// It constructs a map and initialize all of the the map. \n\t\tArrayMap(const Graph& graph, const Value& value) {\n\t\t\tParent::attach(graph.notifier(Item()));\n\t\t\tallocate_memory();\n\t\t\tNotifier* nf = Parent::notifier();\n\t\t\tItem it;\n\t\t\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t\t\t\tint id = nf->id(it);;\n\t\t\t\tallocator.construct(&(values[id]), value);\n\t\t\t}\t\t\t\t\t\t\t\t\n\t\t}\n\t\t\n\t\t/// \\brief Constructor to copy a map of the same map type.\n\t\t///\n\t\t/// Constructor to copy a map of the same map type.     \n\t\tArrayMap(const ArrayMap& copy) : Parent() {\n\t\t\tif (copy.attached()) {\n\t\t\t\tattach(*copy.notifier());\n\t\t\t}\n\t\t\tcapacity = copy.capacity;\n\t\t\tif (capacity == 0) return;\n\t\t\tvalues = allocator.allocate(capacity);\n\t\t\tNotifier* nf = Parent::notifier();\n\t\t\tItem it;\n\t\t\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t\t\t\tint id = nf->id(it);;\n\t\t\t\tallocator.construct(&(values[id]), copy.values[id]);\n\t\t\t}\n\t\t}\n\t\t\n\t\t/// \\brief Assign operator.\n\t\t///\n\t\t/// This operator assigns for each item in the map the\n\t\t/// value mapped to the same item in the copied map.  \n\t\t/// The parameter map should be indiced with the same\n\t\t/// itemset because this assign operator does not change\n\t\t/// the container of the map. \n\t\tArrayMap& operator=(const ArrayMap& cmap) {\n\t\t\treturn operator=<ArrayMap>(cmap);\n\t\t}\n\t\t\n\t\t\n\t\t/// \\brief Template assign operator.\n\t\t///\n\t\t/// The given parameter should be conform to the ReadMap\n\t\t/// concecpt and could be indiced by the current item set of\n\t\t/// the NodeMap. In this case the value for each item\n\t\t/// is assigned by the value of the given ReadMap. \n\t\ttemplate <typename CMap>\n\t\tArrayMap& operator=(const CMap& cmap) {\n\t\t\tcheckConcept<concepts::ReadMap<Key, _Value>, CMap>();\n\t\t\tconst typename Parent::Notifier* nf = Parent::notifier();\n\t\t\tItem it;\n\t\t\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t\t\t\tset(it, cmap[it]);\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\t\t\n\t\t/// \\brief The destructor of the map.\n\t\t///     \n\t\t/// The destructor of the map.\n\t\tvirtual ~ArrayMap() {      \n\t\t\tif (attached()) {\n\t\t\t\tclear();\n\t\t\t\tdetach();\n\t\t\t}\n\t\t}\n\t\t\n\tprotected:\n\t\t\n\t\tusing Parent::attach;\n\t\tusing Parent::detach;\n\t\tusing Parent::attached;\n\t\t\n\tpublic:\n\t\t\n\t\t/// \\brief The subscript operator. \n\t\t///\n\t\t/// The subscript operator. The map can be subscripted by the\n\t\t/// actual keys of the graph. \n\t\tValue& operator[](const Key& key) {\n\t\t\tint id = Parent::notifier()->id(key);\n\t\t\treturn values[id];\n\t\t} \n\t\t\n\t\t/// \\brief The const subscript operator.\n\t\t///\n\t\t/// The const subscript operator. The map can be subscripted by the\n\t\t/// actual keys of the graph. \n\t\tconst Value& operator[](const Key& key) const {\n\t\t\tint id = Parent::notifier()->id(key);\n\t\t\treturn values[id];\n\t\t}\n\t\t\n\t\t/// \\brief Setter function of the map.\n\t\t///\t\n\t\t/// Setter function of the map. Equivalent with map[key] = val.\n\t\t/// This is a compatibility feature with the not dereferable maps.\n\t\tvoid set(const Key& key, const Value& val) {\n\t\t\t(*this)[key] = val;\n\t\t}\n\t\t\n\tprotected:\n\t\t\n\t\t/// \\brief Adds a new key to the map.\n\t\t///\t\t\n\t\t/// It adds a new key to the map. It called by the observer notifier\n\t\t/// and it overrides the add() member function of the observer base.     \n\t\tvirtual void add(const Key& key) {\n\t\t\tNotifier* nf = Parent::notifier();\n\t\t\tint id = nf->id(key);\n\t\t\tif (id >= capacity) {\n\t\t\t\tint new_capacity = (capacity == 0 ? 1 : capacity);\n\t\t\t\twhile (new_capacity <= id) {\n\t\t\t\t\tnew_capacity <<= 1;\n\t\t\t\t}\n\t\t\t\tValue* new_values = allocator.allocate(new_capacity);\n\t\t\t\tItem it;\n\t\t\t\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t\t\t\t\tint jd = nf->id(it);;\n\t\t\t\t\tif (id != jd) {\n\t\t\t\t\t\tallocator.construct(&(new_values[jd]), values[jd]);\n\t\t\t\t\t\tallocator.destroy(&(values[jd]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (capacity != 0) allocator.deallocate(values, capacity);\n\t\t\t\tvalues = new_values;\n\t\t\t\tcapacity = new_capacity;\n\t\t\t}\n\t\t\tallocator.construct(&(values[id]), Value());\n\t\t}\n\t\t\n\t\t/// \\brief Adds more new keys to the map.\n\t\t///\t\t\n\t\t/// It adds more new keys to the map. It called by the observer notifier\n\t\t/// and it overrides the add() member function of the observer base.     \n\t\tvirtual void add(const std::vector<Key>& keys) {\n\t\t\tNotifier* nf = Parent::notifier();\n\t\t\tint max_id = -1;\n\t\t\tfor (int i = 0; i < int(keys.size()); ++i) {\n\t\t\t\tint id = nf->id(keys[i]);\n\t\t\t\tif (id > max_id) {\n\t\t\t\t\tmax_id = id;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (max_id >= capacity) {\n\t\t\t\tint new_capacity = (capacity == 0 ? 1 : capacity);\n\t\t\t\twhile (new_capacity <= max_id) {\n\t\t\t\t\tnew_capacity <<= 1;\n\t\t\t\t}\n\t\t\t\tValue* new_values = allocator.allocate(new_capacity);\n\t\t\t\tItem it;\n\t\t\t\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t\t\t\t\tint id = nf->id(it);\n\t\t\t\t\tbool found = false;\n\t\t\t\t\tfor (int i = 0; i < int(keys.size()); ++i) {\n\t\t\t\t\t\tint jd = nf->id(keys[i]);\n\t\t\t\t\t\tif (id == jd) {\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (found) continue;\n\t\t\t\t\tallocator.construct(&(new_values[id]), values[id]);\n\t\t\t\t\tallocator.destroy(&(values[id]));\n\t\t\t\t}\n\t\t\t\tif (capacity != 0) allocator.deallocate(values, capacity);\n\t\t\t\tvalues = new_values;\n\t\t\t\tcapacity = new_capacity;\n\t\t\t}\n\t\t\tfor (int i = 0; i < int(keys.size()); ++i) {\n\t\t\t\tint id = nf->id(keys[i]);\n\t\t\t\tallocator.construct(&(values[id]), Value());\n\t\t\t}\n\t\t}\n\t\t\n\t\t/// \\brief Erase a key from the map.\n\t\t///\n\t\t/// Erase a key from the map. It called by the observer notifier\n\t\t/// and it overrides the erase() member function of the observer base.     \n\t\tvirtual void erase(const Key& key) {\n\t\t\tint id = Parent::notifier()->id(key);\n\t\t\tallocator.destroy(&(values[id]));\n\t\t}\n\t\t\n\t\t/// \\brief Erase more keys from the map.\n\t\t///\n\t\t/// Erase more keys from the map. It called by the observer notifier\n\t\t/// and it overrides the erase() member function of the observer base.     \n\t\tvirtual void erase(const std::vector<Key>& keys) {\n\t\t\tfor (int i = 0; i < int(keys.size()); ++i) {\n\t\t\t\tint id = Parent::notifier()->id(keys[i]);\n\t\t\t\tallocator.destroy(&(values[id]));\n\t\t\t}\n\t\t}\n\t\t\n\t\t/// \\brief Buildes the map.\n\t\t///\t\n\t\t/// It buildes the map. It called by the observer notifier\n\t\t/// and it overrides the build() member function of the observer base. \n\t\tvirtual void build() {\n\t\t\tNotifier* nf = Parent::notifier();\n\t\t\tallocate_memory();\n\t\t\tItem it;\n\t\t\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t\t\t\tint id = nf->id(it);;\n\t\t\t\tallocator.construct(&(values[id]), Value());\n\t\t\t}\t\t\t\t\t\t\t\t\n\t\t}\n\t\t\n\t\t/// \\brief Clear the map.\n\t\t///\n\t\t/// It erase all items from the map. It called by the observer notifier\n\t\t/// and it overrides the clear() member function of the observer base.     \n\t\tvirtual void clear() {\t\n\t\t\tNotifier* nf = Parent::notifier();\n\t\t\tif (capacity != 0) {\n\t\t\t\tItem it;\n\t\t\t\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t\t\t\t\tint id = nf->id(it);\n\t\t\t\t\tallocator.destroy(&(values[id]));\n\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t\tallocator.deallocate(values, capacity);\n\t\t\t\tcapacity = 0;\n\t\t\t}\n\t\t}\n\t\t\n\tprivate:\n\t\t\n\t\tvoid allocate_memory() {\n\t\t\tint max_id = Parent::notifier()->maxId();\n\t\t\tif (max_id == -1) {\n\t\t\t\tcapacity = 0;\n\t\t\t\tvalues = 0;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcapacity = 1;\n\t\t\twhile (capacity <= max_id) {\n\t\t\t\tcapacity <<= 1;\n\t\t\t}\n\t\t\tvalues = allocator.allocate(capacity);\t\n\t\t}      \n\t\t\n\t\tint capacity;\n\t\tValue* values;\n\t\tAllocator allocator;\n\t\t\n\t};\t\t\n\t\n}\n\n#endif \n"
  },
  {
    "path": "src/lemon/bits/base_extender.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_BASE_EXTENDER_H\n#define LEMON_BITS_BASE_EXTENDER_H\n\n#include <lemon/bits/invalid.h>\n#include <lemon/error.h>\n\n#include <lemon/bits/map_extender.h>\n#include <lemon/bits/default_map.h>\n\n#include <lemon/concept_check.h>\n#include <lemon/concepts/maps.h>\n\n///\\ingroup graphbits\n///\\file\n///\\brief Extenders for the graph types\nnamespace lemon {\n\t\n\t/// \\ingroup graphbits\n\t///\n\t/// \\brief BaseGraph to BaseUGraph extender\n\ttemplate <typename Base>\n\tclass UndirGraphExtender : public Base {\n\t\t\n\tpublic:\n\t\t\n\t\ttypedef Base Parent;\n\t\ttypedef typename Parent::Edge UEdge;\n\t\ttypedef typename Parent::Node Node;\n\t\t\n\t\ttypedef True UndirectedTag;\n\t\t\n\t\tclass Edge : public UEdge {\n\t\t\tfriend class UndirGraphExtender;\n\t\t\t\n\t\tprotected:\n\t\t\tbool forward;\n\t\t\t\n\t\t\tEdge(const UEdge &ue, bool _forward) :\n\t\t\tUEdge(ue), forward(_forward) {}\n\t\t\t\n\t\tpublic:\n\t\t\tEdge() {}\n\t\t\t\n\t\t\t/// Invalid edge constructor\n\t\t\tEdge(Invalid i) : UEdge(i), forward(true) {}\n\t\t\t\n\t\t\tbool operator==(const Edge &that) const {\n\t\t\t\treturn forward==that.forward && UEdge(*this)==UEdge(that);\n\t\t\t}\n\t\t\tbool operator!=(const Edge &that) const {\n\t\t\t\treturn forward!=that.forward || UEdge(*this)!=UEdge(that);\n\t\t\t}\n\t\t\tbool operator<(const Edge &that) const {\n\t\t\t\treturn forward<that.forward ||\n\t\t\t\t(!(that.forward<forward) && UEdge(*this)<UEdge(that));\n\t\t\t}\n\t\t};\n\t\t\n\t\t\n\t\t\n\t\tusing Parent::source;\n\t\t\n\t\t/// Source of the given Edge.\n\t\tNode source(const Edge &e) const {\n\t\t\treturn e.forward ? Parent::source(e) : Parent::target(e);\n\t\t}\n\t\t\n\t\tusing Parent::target;\n\t\t\n\t\t/// Target of the given Edge.\n\t\tNode target(const Edge &e) const {\n\t\t\treturn e.forward ? Parent::target(e) : Parent::source(e);\n\t\t}\n\t\t\n\t\t/// \\brief Directed edge from an undirected edge.\n\t\t///\n\t\t/// Returns a directed edge corresponding to the specified UEdge.\n\t\t/// If the given bool is true the given undirected edge and the\n\t\t/// returned edge have the same source node.\n\t\tstatic Edge direct(const UEdge &ue, bool d) {\n\t\t\treturn Edge(ue, d);\n\t\t}\n\t\t\n\t\t/// Returns whether the given directed edge is same orientation as the\n\t\t/// corresponding undirected edge.\n\t\t///\n\t\t/// \\todo reference to the corresponding point of the undirected graph\n\t\t/// concept. \"What does the direction of an undirected edge mean?\"\n\t\tstatic bool direction(const Edge &e) { return e.forward; }\n\t\t\n\t\t\n\t\tusing Parent::first;\n\t\tusing Parent::next;\n\t\t\n\t\tvoid first(Edge &e) const {\n\t\t\tParent::first(e);\n\t\t\te.forward=true;\n\t\t}\n\t\t\n\t\tvoid next(Edge &e) const {\n\t\t\tif( e.forward ) {\n\t\t\t\te.forward = false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tParent::next(e);\n\t\t\t\te.forward = true;\n\t\t\t}\n\t\t}\n\t\t\n\t\tvoid firstOut(Edge &e, const Node &n) const {\n\t\t\tParent::firstIn(e,n);\n\t\t\tif( UEdge(e) != INVALID ) {\n\t\t\t\te.forward = false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tParent::firstOut(e,n);\n\t\t\t\te.forward = true;\n\t\t\t}\n\t\t}\n\t\tvoid nextOut(Edge &e) const {\n\t\t\tif( ! e.forward ) {\n\t\t\t\tNode n = Parent::target(e);\n\t\t\t\tParent::nextIn(e);\n\t\t\t\tif( UEdge(e) == INVALID ) {\n\t\t\t\t\tParent::firstOut(e, n);\n\t\t\t\t\te.forward = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tParent::nextOut(e);\n\t\t\t}\n\t\t}\n\t\t\n\t\tvoid firstIn(Edge &e, const Node &n) const {\n\t\t\tParent::firstOut(e,n);\n\t\t\tif( UEdge(e) != INVALID ) {\n\t\t\t\te.forward = false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tParent::firstIn(e,n);\n\t\t\t\te.forward = true;\n\t\t\t}\n\t\t}\n\t\tvoid nextIn(Edge &e) const {\n\t\t\tif( ! e.forward ) {\n\t\t\t\tNode n = Parent::source(e);\n\t\t\t\tParent::nextOut(e);\n\t\t\t\tif( UEdge(e) == INVALID ) {\n\t\t\t\t\tParent::firstIn(e, n);\n\t\t\t\t\te.forward = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tParent::nextIn(e);\n\t\t\t}\n\t\t}\n\t\t\n\t\tvoid firstInc(UEdge &e, bool &d, const Node &n) const {\n\t\t\td = true;\n\t\t\tParent::firstOut(e, n);\n\t\t\tif (e != INVALID) return;\n\t\t\td = false;\n\t\t\tParent::firstIn(e, n);\n\t\t}\n\t\t\n\t\tvoid nextInc(UEdge &e, bool &d) const {\n\t\t\tif (d) {\n\t\t\t\tNode s = Parent::source(e);\n\t\t\t\tParent::nextOut(e);\n\t\t\t\tif (e != INVALID) return;\n\t\t\t\td = false;\n\t\t\t\tParent::firstIn(e, s);\n\t\t\t} else {\n\t\t\t\tParent::nextIn(e);\n\t\t\t}\n\t\t}\n\t\t\n\t\tNode nodeFromId(int ix) const {\n\t\t\treturn Parent::nodeFromId(ix);\n\t\t}\n\t\t\n\t\tEdge edgeFromId(int ix) const {\n\t\t\treturn direct(Parent::edgeFromId(ix >> 1), bool(ix & 1));\n\t\t}\n\t\t\n\t\tUEdge uEdgeFromId(int ix) const {\n\t\t\treturn Parent::edgeFromId(ix);\n\t\t}\n\t\t\n\t\tint id(const Node &n) const {\n\t\t\treturn Parent::id(n);\n\t\t}\n\t\t\n\t\tint id(const UEdge &e) const {\n\t\t\treturn Parent::id(e);\n\t\t}\n\t\t\n\t\tint id(const Edge &e) const {\n\t\t\treturn 2 * Parent::id(e) + int(e.forward);\n\t\t}\n\t\t\n\t\tint maxNodeId() const {\n\t\t\treturn Parent::maxNodeId();\n\t\t}\n\t\t\n\t\tint maxEdgeId() const {\n\t\t\treturn 2 * Parent::maxEdgeId() + 1;\n\t\t}\n\t\t\n\t\tint maxUEdgeId() const {\n\t\t\treturn Parent::maxEdgeId();\n\t\t}\n\t\t\n\t\t\n\t\tint edgeNum() const {\n\t\t\treturn 2 * Parent::edgeNum();\n\t\t}\n\t\t\n\t\tint uEdgeNum() const {\n\t\t\treturn Parent::edgeNum();\n\t\t}\n\t\t\n\t\tEdge findEdge(Node s, Node t, Edge p = INVALID) const {\n\t\t\tif (p == INVALID) {\n\t\t\t\tUEdge edge = Parent::findEdge(s, t);\n\t\t\t\tif (edge != INVALID) return direct(edge, true);\n\t\t\t\tedge = Parent::findEdge(t, s);\n\t\t\t\tif (edge != INVALID) return direct(edge, false);\n\t\t\t} else if (direction(p)) {\n\t\t\t\tUEdge edge = Parent::findEdge(s, t, p);\n\t\t\t\tif (edge != INVALID) return direct(edge, true);\n\t\t\t\tedge = Parent::findEdge(t, s);\n\t\t\t\tif (edge != INVALID) return direct(edge, false);\t\n\t\t\t} else {\n\t\t\t\tUEdge edge = Parent::findEdge(t, s, p);\n\t\t\t\tif (edge != INVALID) return direct(edge, false);\t      \n\t\t\t}\n\t\t\treturn INVALID;\n\t\t}\n\t\t\n\t\tUEdge findUEdge(Node s, Node t, UEdge p = INVALID) const {\n\t\t\tif (s != t) {\n\t\t\t\tif (p == INVALID) {\n\t\t\t\t\tUEdge edge = Parent::findEdge(s, t);\n\t\t\t\t\tif (edge != INVALID) return edge;\n\t\t\t\t\tedge = Parent::findEdge(t, s);\n\t\t\t\t\tif (edge != INVALID) return edge;\n\t\t\t\t} else if (Parent::s(p) == s) {\n\t\t\t\t\tUEdge edge = Parent::findEdge(s, t, p);\n\t\t\t\t\tif (edge != INVALID) return edge;\n\t\t\t\t\tedge = Parent::findEdge(t, s);\n\t\t\t\t\tif (edge != INVALID) return edge;\t\n\t\t\t\t} else {\n\t\t\t\t\tUEdge edge = Parent::findEdge(t, s, p);\n\t\t\t\t\tif (edge != INVALID) return edge;\t      \n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn Parent::findEdge(s, t, p);\n\t\t\t}\n\t\t\treturn INVALID;\n\t\t}\n\t};\n\t\n\ttemplate <typename Base>\n\tclass BidirBpUGraphExtender : public Base {\n\tpublic:\n\t\ttypedef Base Parent;\n\t\ttypedef BidirBpUGraphExtender Graph;\n\t\t\n\t\ttypedef typename Parent::Node Node;\n\t\ttypedef typename Parent::UEdge UEdge;\n\t\t\n\t\t\n\t\tusing Parent::first;\n\t\tusing Parent::next;\n\t\t\n\t\tusing Parent::id;\n\t\t\n\t\tclass ANode : public Node {\n\t\t\tfriend class BidirBpUGraphExtender;\n\t\tpublic:\n\t\t\tANode() {}\n\t\t\tANode(const Node& node) : Node(node) {\n\t\t\t\tLEMON_ASSERT(Parent::aNode(node) || node == INVALID, \n\t\t\t\t\t\t\t typename Parent::NodeSetError());\n\t\t\t}\n\t\t\tANode& operator=(const Node& node) {\n\t\t\t\tLEMON_ASSERT(Parent::aNode(node) || node == INVALID, \n\t\t\t\t\t\t\t typename Parent::NodeSetError());\n\t\t\t\tNode::operator=(node);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t\tANode(Invalid) : Node(INVALID) {}\n\t\t\tANode& operator=(Invalid) {\n\t\t\t\tNode::operator=(INVALID);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t};\n\t\t\n\t\tvoid first(ANode& node) const {\n\t\t\tParent::firstANode(static_cast<Node&>(node));\n\t\t}\n\t\tvoid next(ANode& node) const {\n\t\t\tParent::nextANode(static_cast<Node&>(node));\n\t\t}\n\t\t\n\t\tint id(const ANode& node) const {\n\t\t\treturn Parent::aNodeId(node);\n\t\t}\n\t\t\n\t\tclass BNode : public Node {\n\t\t\tfriend class BidirBpUGraphExtender;\n\t\tpublic:\n\t\t\tBNode() {}\n\t\t\tBNode(const Node& node) : Node(node) {\n\t\t\t\tLEMON_ASSERT(Parent::bNode(node) || node == INVALID,\n\t\t\t\t\t\t\t typename Parent::NodeSetError());\n\t\t\t}\n\t\t\tBNode& operator=(const Node& node) {\n\t\t\t\tLEMON_ASSERT(Parent::bNode(node) || node == INVALID, \n\t\t\t\t\t\t\t typename Parent::NodeSetError());\n\t\t\t\tNode::operator=(node);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t\tBNode(Invalid) : Node(INVALID) {}\n\t\t\tBNode& operator=(Invalid) {\n\t\t\t\tNode::operator=(INVALID);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t};\n\t\t\n\t\tvoid first(BNode& node) const {\n\t\t\tParent::firstBNode(static_cast<Node&>(node));\n\t\t}\n\t\tvoid next(BNode& node) const {\n\t\t\tParent::nextBNode(static_cast<Node&>(node));\n\t\t}\n\t\t\n\t\tint id(const BNode& node) const {\n\t\t\treturn Parent::aNodeId(node);\n\t\t}\n\t\t\n\t\tNode source(const UEdge& edge) const {\n\t\t\treturn this->aNode(edge);\n\t\t}\n\t\tNode target(const UEdge& edge) const {\n\t\t\treturn this->bNode(edge);\n\t\t}\n\t\t\n\t\tvoid firstInc(UEdge& edge, bool& dir, const Node& node) const {\n\t\t\tif (Parent::aNode(node)) {\n\t\t\t\tParent::firstFromANode(edge, node);\n\t\t\t\tdir = true;\n\t\t\t} else {\n\t\t\t\tParent::firstFromBNode(edge, node);\n\t\t\t\tdir = static_cast<UEdge&>(edge) == INVALID;\n\t\t\t}\n\t\t}\n\t\tvoid nextInc(UEdge& edge, bool& dir) const {\n\t\t\tif (dir) {\n\t\t\t\tParent::nextFromANode(edge);\n\t\t\t} else {\n\t\t\t\tParent::nextFromBNode(edge);\n\t\t\t\tif (edge == INVALID) dir = true;\n\t\t\t}\n\t\t}\n\t\t\n\t\tclass Edge : public UEdge {\n\t\t\tfriend class BidirBpUGraphExtender;\n\t\tprotected:\n\t\t\tbool forward;\n\t\t\t\n\t\t\tEdge(const UEdge& edge, bool _forward)\n\t\t\t: UEdge(edge), forward(_forward) {}\n\t\t\t\n\t\tpublic:\n\t\t\tEdge() {}\n\t\t\tEdge (Invalid) : UEdge(INVALID), forward(true) {}\n\t\t\tbool operator==(const Edge& i) const {\n\t\t\t\treturn UEdge::operator==(i) && forward == i.forward;\n\t\t\t}\n\t\t\tbool operator!=(const Edge& i) const {\n\t\t\t\treturn UEdge::operator!=(i) || forward != i.forward;\n\t\t\t}\n\t\t\tbool operator<(const Edge& i) const {\n\t\t\t\treturn UEdge::operator<(i) || \n\t\t\t\t(!(i.forward<forward) && UEdge(*this)<UEdge(i));\n\t\t\t}\n\t\t};\n\t\t\n\t\tvoid first(Edge& edge) const {\n\t\t\tParent::first(static_cast<UEdge&>(edge));\n\t\t\tedge.forward = true;\n\t\t}\n\t\t\n\t\tvoid next(Edge& edge) const {\n\t\t\tif (!edge.forward) {\n\t\t\t\tParent::next(static_cast<UEdge&>(edge));\n\t\t\t}\n\t\t\tedge.forward = !edge.forward;\n\t\t}\n\t\t\n\t\tvoid firstOut(Edge& edge, const Node& node) const {\n\t\t\tif (Parent::aNode(node)) {\n\t\t\t\tParent::firstFromANode(edge, node);\n\t\t\t\tedge.forward = true;\n\t\t\t} else {\n\t\t\t\tParent::firstFromBNode(edge, node);\n\t\t\t\tedge.forward = static_cast<UEdge&>(edge) == INVALID;\n\t\t\t}\n\t\t}\n\t\tvoid nextOut(Edge& edge) const {\n\t\t\tif (edge.forward) {\n\t\t\t\tParent::nextFromANode(edge);\n\t\t\t} else {\n\t\t\t\tParent::nextFromBNode(edge);\n\t\t\t\tedge.forward = static_cast<UEdge&>(edge) == INVALID;\n\t\t\t}\n\t\t}\n\t\t\n\t\tvoid firstIn(Edge& edge, const Node& node) const {\n\t\t\tif (Parent::bNode(node)) {\n\t\t\t\tParent::firstFromBNode(edge, node);\n\t\t\t\tedge.forward = true;\t\n\t\t\t} else {\n\t\t\t\tParent::firstFromANode(edge, node);\n\t\t\t\tedge.forward = static_cast<UEdge&>(edge) == INVALID;\n\t\t\t}\n\t\t}\n\t\tvoid nextIn(Edge& edge) const {\n\t\t\tif (edge.forward) {\n\t\t\t\tParent::nextFromBNode(edge);\n\t\t\t} else {\n\t\t\t\tParent::nextFromANode(edge);\n\t\t\t\tedge.forward = static_cast<UEdge&>(edge) == INVALID;\n\t\t\t}\n\t\t}\n\t\t\n\t\tNode source(const Edge& edge) const {\n\t\t\treturn edge.forward ? Parent::aNode(edge) : Parent::bNode(edge);\n\t\t}\n\t\tNode target(const Edge& edge) const {\n\t\t\treturn edge.forward ? Parent::bNode(edge) : Parent::aNode(edge);\n\t\t}\n\t\t\n\t\tint id(const Edge& edge) const {\n\t\t\treturn (Parent::id(static_cast<const UEdge&>(edge)) << 1) + \n\t\t\t(edge.forward ? 0 : 1);\n\t\t}\n\t\tEdge edgeFromId(int ix) const {\n\t\t\treturn Edge(Parent::fromUEdgeId(ix >> 1), (ix & 1) == 0);\n\t\t}\n\t\tint maxEdgeId() const {\n\t\t\treturn (Parent::maxUEdgeId() << 1) + 1;\n\t\t}\n\t\t\n\t\tbool direction(const Edge& edge) const {\n\t\t\treturn edge.forward;\n\t\t}\n\t\t\n\t\tEdge direct(const UEdge& edge, bool dir) const {\n\t\t\treturn Edge(edge, dir);\n\t\t}\n\t\t\n\t\tint edgeNum() const {\n\t\t\treturn 2 * Parent::uEdgeNum();\n\t\t}\n\t\t\n\t\tint uEdgeNum() const {\n\t\t\treturn Parent::uEdgeNum();\n\t\t}\n\t\t\n\t\t\n\t};\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/debug_map.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_DEBUG_MAP_H\n#define LEMON_BITS_DEBUG_MAP_H\n\n#include <vector>\n#include <algorithm>\n\n#include <lemon/bits/traits.h>\n#include <lemon/bits/utility.h>\n#include <lemon/error.h>\n\n#include <lemon/bits/alteration_notifier.h>\n\n#include <lemon/concept_check.h>\n#include <lemon/concepts/maps.h>\n\n///\\ingroup graphbits\n///\n///\\file\n///\\brief Vector based graph maps for debugging.\nnamespace lemon {\n\n#ifndef LEMON_STRICT_DEBUG_MAP\n#define LEMON_STRICT_DEBUG_MAP false\n#endif\n\n  /// \\ingroup graphbits\n  ///\n  /// \\brief Graph map based on the std::vector storage.\n  ///\n  /// The DebugMap template class is graph map structure what\n  /// automatically updates the map when a key is added to or erased from\n  /// the map. This map also checks some programming failures by example\n  /// multiple addition of items, erasing of not existing item or\n  /// not erased items at the destruction of the map. It helps the\n  /// programmer to avoid segmentation faults and memory leaks.\n  ///\n  /// \\param Notifier The AlterationNotifier that will notify this map.\n  /// \\param Item The item type of the graph items.\n  /// \\param Value The value type of the map.\n  /// \n  /// \\author Balazs Dezso  \t\n  template <typename _Graph, typename _Item, typename _Value>\n  class DebugMap \n    : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {\n  private:\n\t\t\n    /// The container type of the map.\n    typedef std::vector<_Value> Container;\t\n\n    /// The container type of the debug flags.\n    typedef std::vector<bool> Flag;\t\n\n  public:\n\n    static const bool strictCheck = LEMON_STRICT_DEBUG_MAP;\n\n    struct MapError {\n    public:\n      virtual ~MapError() {}\n      virtual const char* what() const throw() {\n        return \"lemon::DebugMap::MapError\";\n      }\n    };\n\n    /// The graph type of the map. \n    typedef _Graph Graph;\n    /// The item type of the map.\n    typedef _Item Item;\n    /// The reference map tag.\n    typedef True ReferenceMapTag;\n\n    /// The key type of the map.\n    typedef _Item Key;\n    /// The value type of the map.\n    typedef _Value Value;\n\n    /// The notifier type.\n    typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;\n\n    /// The map type.\n    typedef DebugMap Map;\n    /// The base class of the map.\n    typedef typename Notifier::ObserverBase Parent;\n\n    /// The reference type of the map;\n    typedef typename Container::reference Reference;\n    /// The const reference type of the map;\n    typedef typename Container::const_reference ConstReference;\n\n\n    /// \\brief Constructor to attach the new map into the notifier.\n    ///\n    /// It constructs a map and attachs it into the notifier.\n    /// It adds all the items of the graph to the map.\n    DebugMap(const Graph& graph) {\n      Parent::attach(graph.notifier(Item()));\n      container.resize(Parent::notifier()->maxId() + 1);\n      flag.resize(Parent::notifier()->maxId() + 1, false);\n      const typename Parent::Notifier* notifier = Parent::notifier();\n      Item it;\n      for (notifier->first(it); it != INVALID; notifier->next(it)) {\n        flag[Parent::notifier()->id(it)] = true;\n      }\n    }\n\n    /// \\brief Constructor uses given value to initialize the map. \n    ///\n    /// It constructs a map uses a given value to initialize the map. \n    /// It adds all the items of the graph to the map.\n    DebugMap(const Graph& graph, const Value& value) {\n      Parent::attach(graph.notifier(Item()));\n      container.resize(Parent::notifier()->maxId() + 1, value);\n      flag.resize(Parent::notifier()->maxId() + 1, false);\n      const typename Parent::Notifier* notifier = Parent::notifier();\n      Item it;\n      for (notifier->first(it); it != INVALID; notifier->next(it)) {\n        flag[Parent::notifier()->id(it)] = true;\n      }\n    }\n\n    /// \\brief Copy constructor\n    ///\n    /// Copy constructor.\n    DebugMap(const DebugMap& _copy) : Parent() {\n      if (_copy.attached()) {\n\tParent::attach(*_copy.notifier());\n\tcontainer = _copy.container;\n      }\n      flag.resize(Parent::notifier()->maxId() + 1, false);\n      const typename Parent::Notifier* notifier = Parent::notifier();\n      Item it;\n      for (notifier->first(it); it != INVALID; notifier->next(it)) {\n        flag[Parent::notifier()->id(it)] = true;\n        LEMON_ASSERT(_copy.flag[Parent::notifier()->id(it)], MapError());\n      }\n    }\n\n    /// \\brief Destructor\n    ///\n    /// Destructor.\n    ~DebugMap() {\n      const typename Parent::Notifier* notifier = Parent::notifier();\n      if (notifier != 0) {\n        Item it;\n        for (notifier->first(it); it != INVALID; notifier->next(it)) {\n          LEMON_ASSERT(flag[Parent::notifier()->id(it)], MapError());\n          flag[Parent::notifier()->id(it)] = false;\n        }\n      }\n      for (int i = 0; i < int(flag.size()); ++i) {\n        LEMON_ASSERT(!flag[i], MapError());\n      }\n    }\n\n    /// \\brief Assign operator.\n    ///\n    /// This operator assigns for each item in the map the\n    /// value mapped to the same item in the copied map.  \n    /// The parameter map should be indiced with the same\n    /// itemset because this assign operator does not change\n    /// the container of the map. \n    DebugMap& operator=(const DebugMap& cmap) {\n      return operator=<DebugMap>(cmap);\n    }\n\n\n    /// \\brief Template assign operator.\n    ///\n    /// The given parameter should be conform to the ReadMap\n    /// concecpt and could be indiced by the current item set of\n    /// the NodeMap. In this case the value for each item\n    /// is assigned by the value of the given ReadMap. \n    template <typename CMap>\n    DebugMap& operator=(const CMap& cmap) {\n      checkConcept<concepts::ReadMap<Key, _Value>, CMap>();\n      const typename Parent::Notifier* notifier = Parent::notifier();\n      Item it;\n      for (notifier->first(it); it != INVALID; notifier->next(it)) {\n        set(it, cmap[it]);\n      }\n      return *this;\n    }\n    \n  public:\n\n    /// \\brief The subcript operator.\n    ///\n    /// The subscript operator. The map can be subscripted by the\n    /// actual items of the graph.      \n    Reference operator[](const Key& key) {\n      LEMON_ASSERT(flag[Parent::notifier()->id(key)], MapError());\n      return container[Parent::notifier()->id(key)];\n    } \n\t\t\n    /// \\brief The const subcript operator.\n    ///\n    /// The const subscript operator. The map can be subscripted by the\n    /// actual items of the graph. \n    ConstReference operator[](const Key& key) const {\n      LEMON_ASSERT(flag[Parent::notifier()->id(key)], MapError());\n      return container[Parent::notifier()->id(key)];\n    }\n\n\n    /// \\brief The setter function of the map.\n    ///\n    /// It the same as operator[](key) = value expression.\n    void set(const Key& key, const Value& value) {\n      (*this)[key] = value;\n    }\n\n  protected:\n\n    /// \\brief Adds a new key to the map.\n    ///\t\t\n    /// It adds a new key to the map. It called by the observer notifier\n    /// and it overrides the add() member function of the observer base.     \n    virtual void add(const Key& key) {\n      int id = Parent::notifier()->id(key);\n      if (id >= int(container.size())) {\n\tcontainer.resize(id + 1);\n        flag.resize(id + 1, false);\n      }\n      LEMON_ASSERT(!flag[Parent::notifier()->id(key)], MapError());\n      flag[Parent::notifier()->id(key)] = true;\n      if (strictCheck) {\n        std::vector<bool> fl(flag.size(), false);\n        const typename Parent::Notifier* notifier = Parent::notifier();\n        Item it;\n        for (notifier->first(it); it != INVALID; notifier->next(it)) {\n          int jd = Parent::notifier()->id(it);\n          fl[jd] = true;\n        }\n        LEMON_ASSERT(fl == flag, MapError());\n      }\n    }\n\n    /// \\brief Adds more new keys to the map.\n    ///\t\t\n    /// It adds more new keys to the map. It called by the observer notifier\n    /// and it overrides the add() member function of the observer base.     \n    virtual void add(const std::vector<Key>& keys) {\n      int max = container.size() - 1;\n      for (int i = 0; i < int(keys.size()); ++i) {\n        int id = Parent::notifier()->id(keys[i]);\n        if (id >= max) {\n          max = id;\n        }\n      }\n      container.resize(max + 1);\n      flag.resize(max + 1, false);\n      for (int i = 0; i < int(keys.size()); ++i) {\n        LEMON_ASSERT(!flag[Parent::notifier()->id(keys[i])], MapError());\n        flag[Parent::notifier()->id(keys[i])] = true;\n      }\n      if (strictCheck) {\n        std::vector<bool> fl(flag.size(), false);\n        const typename Parent::Notifier* notifier = Parent::notifier();\n        Item it;\n        for (notifier->first(it); it != INVALID; notifier->next(it)) {\n          int id = Parent::notifier()->id(it);\n          fl[id] = true;\n        }\n        LEMON_ASSERT(fl == flag, MapError());\n      }\n    }\n\n    /// \\brief Erase a key from the map.\n    ///\n    /// Erase a key from the map. It called by the observer notifier\n    /// and it overrides the erase() member function of the observer base.     \n    virtual void erase(const Key& key) {\n      if (strictCheck) {\n        std::vector<bool> fl(flag.size(), false);\n        const typename Parent::Notifier* notifier = Parent::notifier();\n        Item it;\n        for (notifier->first(it); it != INVALID; notifier->next(it)) {\n          int id = Parent::notifier()->id(it);\n          fl[id] = true;\n        }\n        LEMON_ASSERT(fl == flag, MapError());\n      }\n      container[Parent::notifier()->id(key)] = Value();\n      LEMON_ASSERT(flag[Parent::notifier()->id(key)], MapError());\n      flag[Parent::notifier()->id(key)] = false;\n    }\n\n    /// \\brief Erase more keys from the map.\n    ///\n    /// Erase more keys from the map. It called by the observer notifier\n    /// and it overrides the erase() member function of the observer base.     \n    virtual void erase(const std::vector<Key>& keys) {\n      if (strictCheck) {\n        std::vector<bool> fl(flag.size(), false);\n        const typename Parent::Notifier* notifier = Parent::notifier();\n        Item it;\n        for (notifier->first(it); it != INVALID; notifier->next(it)) {\n          int id = Parent::notifier()->id(it);\n          fl[id] = true;\n        }\n        LEMON_ASSERT(fl == flag, MapError());\n      }\n      for (int i = 0; i < int(keys.size()); ++i) {\n\tcontainer[Parent::notifier()->id(keys[i])] = Value();\n        LEMON_ASSERT(flag[Parent::notifier()->id(keys[i])], MapError());\n        flag[Parent::notifier()->id(keys[i])] = false;\n      }\n    }\n    \n    /// \\brief Buildes the map.\n    ///\t\n    /// It buildes the map. It called by the observer notifier\n    /// and it overrides the build() member function of the observer base.\n    virtual void build() { \n      if (strictCheck) {\n        for (int i = 0; i < int(flag.size()); ++i) {\n          LEMON_ASSERT(flag[i], MapError());\n        }\n      }\n      int size = Parent::notifier()->maxId() + 1;\n      container.reserve(size);\n      container.resize(size);\n      flag.reserve(size);\n      flag.resize(size, false);\n      const typename Parent::Notifier* notifier = Parent::notifier();\n      Item it;\n      for (notifier->first(it); it != INVALID; notifier->next(it)) {\n        int id = Parent::notifier()->id(it);\n        LEMON_ASSERT(!flag[id], MapError());\n        flag[id] = true;\n      }\n    }\n\n    /// \\brief Clear the map.\n    ///\n    /// It erase all items from the map. It called by the observer notifier\n    /// and it overrides the clear() member function of the observer base.     \n    virtual void clear() { \n      const typename Parent::Notifier* notifier = Parent::notifier();\n      Item it;\n      for (notifier->first(it); it != INVALID; notifier->next(it)) {\n        int id = Parent::notifier()->id(it);\n        LEMON_ASSERT(flag[id], MapError());\n        flag[id] = false;\n      }\n      if (strictCheck) {\n        for (int i = 0; i < int(flag.size()); ++i) {\n          LEMON_ASSERT(!flag[i], MapError());\n        }\n      }\n      container.clear();\n      flag.clear();\n    }\n    \n  private:\n\t\t\n    Container container;\n    Flag flag;\n\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/default_map.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_DEFAULT_MAP_H\n#define LEMON_BITS_DEFAULT_MAP_H\n\n\n#include <lemon/bits/array_map.h>\n#include <lemon/bits/vector_map.h>\n#include <lemon/bits/debug_map.h>\n\n///\\ingroup graphbits\n///\\file\n///\\brief Graph maps that construct and destruct their elements dynamically.\n\nnamespace lemon {\n\t\n\t\n#ifndef LEMON_USE_DEBUG_MAP\n\t\n\ttemplate <typename _Graph, typename _Item, typename _Value>\n\tstruct DefaultMapSelector {\n\t\ttypedef ArrayMap<_Graph, _Item, _Value> Map;\n\t};\n\t\n\t// bool\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, bool> {\n\t\ttypedef VectorMap<_Graph, _Item, bool> Map;\n\t};\n\t\n\t// char\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, char> {\n\t\ttypedef VectorMap<_Graph, _Item, char> Map;\n\t};\n\t\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, signed char> {\n\t\ttypedef VectorMap<_Graph, _Item, signed char> Map;\n\t};\n\t\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, unsigned char> {\n\t\ttypedef VectorMap<_Graph, _Item, unsigned char> Map;\n\t};\n\t\n\t\n\t// int\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, signed int> {\n\t\ttypedef VectorMap<_Graph, _Item, signed int> Map;\n\t};\n\t\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, unsigned int> {\n\t\ttypedef VectorMap<_Graph, _Item, unsigned int> Map;\n\t};\n\t\n\t\n\t// short\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, signed short> {\n\t\ttypedef VectorMap<_Graph, _Item, signed short> Map;\n\t};\n\t\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, unsigned short> {\n\t\ttypedef VectorMap<_Graph, _Item, unsigned short> Map;\n\t};\n\t\n\t\n\t// long\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, signed long> {\n\t\ttypedef VectorMap<_Graph, _Item, signed long> Map;\n\t};\n\t\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, unsigned long> {\n\t\ttypedef VectorMap<_Graph, _Item, unsigned long> Map;\n\t};\n\t\n\t\n#if defined __GNUC__ && !defined __STRICT_ANSI__\n\t\n\t// long long\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, signed long long> {\n\t\ttypedef VectorMap<_Graph, _Item, signed long long> Map;\n\t};\n\t\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, unsigned long long> {\n\t\ttypedef VectorMap<_Graph, _Item, unsigned long long> Map;\n\t};\n\t\n#endif\n\t\n\t\n\t// float\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, float> {\n\t\ttypedef VectorMap<_Graph, _Item, float> Map;\n\t};\n\t\n\t\n\t// double\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, double> {\n\t\ttypedef VectorMap<_Graph, _Item,  double> Map;\n\t};\n\t\n\t\n\t// long double\n\ttemplate <typename _Graph, typename _Item>\n\tstruct DefaultMapSelector<_Graph, _Item, long double> {\n\t\ttypedef VectorMap<_Graph, _Item, long double> Map;\n\t};\n\t\n\t\n\t// pointer\n\ttemplate <typename _Graph, typename _Item, typename _Ptr>\n\tstruct DefaultMapSelector<_Graph, _Item, _Ptr*> {\n\t\ttypedef VectorMap<_Graph, _Item, _Ptr*> Map;\n\t};\n\t\n#else \n\t\n\ttemplate <typename _Graph, typename _Item, typename _Value>\n\tstruct DefaultMapSelector {\n\t\ttypedef DebugMap<_Graph, _Item, _Value> Map;\n\t};\n\t\n#endif  \n\t\n\t/// \\e\n\ttemplate <typename _Graph, typename _Item, typename _Value>\n\tclass DefaultMap \n    : public DefaultMapSelector<_Graph, _Item, _Value>::Map {\n\tpublic:\n\t\ttypedef typename DefaultMapSelector<_Graph, _Item, _Value>::Map Parent;\n\t\ttypedef DefaultMap<_Graph, _Item, _Value> Map;\n\t\t\n\t\ttypedef typename Parent::Graph Graph;\n\t\ttypedef typename Parent::Value Value;\n\t\t\n\t\texplicit DefaultMap(const Graph& graph) : Parent(graph) {}\n\t\tDefaultMap(const Graph& graph, const Value& value) \n\t\t: Parent(graph, value) {}\n\t\t\n\t\tDefaultMap& operator=(const DefaultMap& cmap) {\n\t\t\treturn operator=<DefaultMap>(cmap);\n\t\t}\n\t\t\n\t\ttemplate <typename CMap>\n\t\tDefaultMap& operator=(const CMap& cmap) {\n\t\t\tParent::operator=(cmap);\n\t\t\treturn *this;\n\t\t}\n\t\t\n\t};\n\t\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/graph_adaptor_extender.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_GRAPH_ADAPTOR_EXTENDER_H\n#define LEMON_BITS_GRAPH_ADAPTOR_EXTENDER_H\n\n#include <lemon/bits/invalid.h>\n#include <lemon/error.h>\n\n#include <lemon/bits/default_map.h>\n\n\n///\\ingroup graphbits\n///\\file\n///\\brief Extenders for the graph adaptor types\nnamespace lemon {\n\n  /// \\ingroup graphbits\n  ///\n  /// \\brief Extender for the GraphAdaptors\n  template <typename _Graph>\n  class GraphAdaptorExtender : public _Graph {\n  public:\n\n    typedef _Graph Parent;\n    typedef _Graph Graph;\n    typedef GraphAdaptorExtender Adaptor;\n\n    // Base extensions\n\n    typedef typename Parent::Node Node;\n    typedef typename Parent::Edge Edge;\n\n    int maxId(Node) const {\n      return Parent::maxNodeId();\n    }\n\n    int maxId(Edge) const {\n      return Parent::maxEdgeId();\n    }\n\n    Node fromId(int id, Node) const {\n      return Parent::nodeFromId(id);\n    }\n\n    Edge fromId(int id, Edge) const {\n      return Parent::edgeFromId(id);\n    }\n\n    Node oppositeNode(const Node &n, const Edge &e) const {\n      if (n == Parent::source(e))\n\treturn Parent::target(e);\n      else if(n==Parent::target(e))\n\treturn Parent::source(e);\n      else\n\treturn INVALID;\n    }\n\n    class NodeIt : public Node { \n      const Adaptor* graph;\n    public:\n\n      NodeIt() {}\n\n      NodeIt(Invalid i) : Node(i) { }\n\n      explicit NodeIt(const Adaptor& _graph) : graph(&_graph) {\n\t_graph.first(static_cast<Node&>(*this));\n      }\n\n      NodeIt(const Adaptor& _graph, const Node& node) \n\t: Node(node), graph(&_graph) {}\n\n      NodeIt& operator++() { \n\tgraph->next(*this);\n\treturn *this; \n      }\n\n    };\n\n\n    class EdgeIt : public Edge { \n      const Adaptor* graph;\n    public:\n\n      EdgeIt() { }\n\n      EdgeIt(Invalid i) : Edge(i) { }\n\n      explicit EdgeIt(const Adaptor& _graph) : graph(&_graph) {\n\t_graph.first(static_cast<Edge&>(*this));\n      }\n\n      EdgeIt(const Adaptor& _graph, const Edge& e) : \n\tEdge(e), graph(&_graph) { }\n\n      EdgeIt& operator++() { \n\tgraph->next(*this);\n\treturn *this; \n      }\n\n    };\n\n\n    class OutEdgeIt : public Edge { \n      const Adaptor* graph;\n    public:\n\n      OutEdgeIt() { }\n\n      OutEdgeIt(Invalid i) : Edge(i) { }\n\n      OutEdgeIt(const Adaptor& _graph, const Node& node) \n\t: graph(&_graph) {\n\t_graph.firstOut(*this, node);\n      }\n\n      OutEdgeIt(const Adaptor& _graph, const Edge& edge) \n\t: Edge(edge), graph(&_graph) {}\n\n      OutEdgeIt& operator++() { \n\tgraph->nextOut(*this);\n\treturn *this; \n      }\n\n    };\n\n\n    class InEdgeIt : public Edge { \n      const Adaptor* graph;\n    public:\n\n      InEdgeIt() { }\n\n      InEdgeIt(Invalid i) : Edge(i) { }\n\n      InEdgeIt(const Adaptor& _graph, const Node& node) \n\t: graph(&_graph) {\n\t_graph.firstIn(*this, node);\n      }\n\n      InEdgeIt(const Adaptor& _graph, const Edge& edge) : \n\tEdge(edge), graph(&_graph) {}\n\n      InEdgeIt& operator++() { \n\tgraph->nextIn(*this);\n\treturn *this; \n      }\n\n    };\n\n    /// \\brief Base node of the iterator\n    ///\n    /// Returns the base node (ie. the source in this case) of the iterator\n    Node baseNode(const OutEdgeIt &e) const {\n      return Parent::source(e);\n    }\n    /// \\brief Running node of the iterator\n    ///\n    /// Returns the running node (ie. the target in this case) of the\n    /// iterator\n    Node runningNode(const OutEdgeIt &e) const {\n      return Parent::target(e);\n    }\n\n    /// \\brief Base node of the iterator\n    ///\n    /// Returns the base node (ie. the target in this case) of the iterator\n    Node baseNode(const InEdgeIt &e) const {\n      return Parent::target(e);\n    }\n    /// \\brief Running node of the iterator\n    ///\n    /// Returns the running node (ie. the source in this case) of the\n    /// iterator\n    Node runningNode(const InEdgeIt &e) const {\n      return Parent::source(e);\n    }\n\n  };\n\n\n  /// \\ingroup graphbits\n  ///\n  /// \\brief Extender for the UGraphAdaptors\n  template <typename _UGraph> \n  class UGraphAdaptorExtender : public _UGraph {\n  public:\n    \n    typedef _UGraph Parent;\n    typedef _UGraph UGraph;\n    typedef UGraphAdaptorExtender Adaptor;\n\n    typedef typename Parent::Node Node;\n    typedef typename Parent::Edge Edge;\n    typedef typename Parent::UEdge UEdge;\n\n    // UGraph extension    \n\n    int maxId(Node) const {\n      return Parent::maxNodeId();\n    }\n\n    int maxId(Edge) const {\n      return Parent::maxEdgeId();\n    }\n\n    int maxId(UEdge) const {\n      return Parent::maxUEdgeId();\n    }\n\n    Node fromId(int id, Node) const {\n      return Parent::nodeFromId(id);\n    }\n\n    Edge fromId(int id, Edge) const {\n      return Parent::edgeFromId(id);\n    }\n\n    UEdge fromId(int id, UEdge) const {\n      return Parent::uEdgeFromId(id);\n    }\n\n    Node oppositeNode(const Node &n, const UEdge &e) const {\n      if( n == Parent::source(e))\n\treturn Parent::target(e);\n      else if( n == Parent::target(e))\n\treturn Parent::source(e);\n      else\n\treturn INVALID;\n    }\n\n    Edge oppositeEdge(const Edge &e) const {\n      return Parent::direct(e, !Parent::direction(e));\n    }\n\n    using Parent::direct;\n    Edge direct(const UEdge &ue, const Node &s) const {\n      return Parent::direct(ue, Parent::source(ue) == s);\n    }\n\n\n    class NodeIt : public Node { \n      const Adaptor* graph;\n    public:\n\n      NodeIt() {}\n\n      NodeIt(Invalid i) : Node(i) { }\n\n      explicit NodeIt(const Adaptor& _graph) : graph(&_graph) {\n\t_graph.first(static_cast<Node&>(*this));\n      }\n\n      NodeIt(const Adaptor& _graph, const Node& node) \n\t: Node(node), graph(&_graph) {}\n\n      NodeIt& operator++() { \n\tgraph->next(*this);\n\treturn *this; \n      }\n\n    };\n\n\n    class EdgeIt : public Edge { \n      const Adaptor* graph;\n    public:\n\n      EdgeIt() { }\n\n      EdgeIt(Invalid i) : Edge(i) { }\n\n      explicit EdgeIt(const Adaptor& _graph) : graph(&_graph) {\n\t_graph.first(static_cast<Edge&>(*this));\n      }\n\n      EdgeIt(const Adaptor& _graph, const Edge& e) : \n\tEdge(e), graph(&_graph) { }\n\n      EdgeIt& operator++() { \n\tgraph->next(*this);\n\treturn *this; \n      }\n\n    };\n\n\n    class OutEdgeIt : public Edge { \n      const Adaptor* graph;\n    public:\n\n      OutEdgeIt() { }\n\n      OutEdgeIt(Invalid i) : Edge(i) { }\n\n      OutEdgeIt(const Adaptor& _graph, const Node& node) \n\t: graph(&_graph) {\n\t_graph.firstOut(*this, node);\n      }\n\n      OutEdgeIt(const Adaptor& _graph, const Edge& edge) \n\t: Edge(edge), graph(&_graph) {}\n\n      OutEdgeIt& operator++() { \n\tgraph->nextOut(*this);\n\treturn *this; \n      }\n\n    };\n\n\n    class InEdgeIt : public Edge { \n      const Adaptor* graph;\n    public:\n\n      InEdgeIt() { }\n\n      InEdgeIt(Invalid i) : Edge(i) { }\n\n      InEdgeIt(const Adaptor& _graph, const Node& node) \n\t: graph(&_graph) {\n\t_graph.firstIn(*this, node);\n      }\n\n      InEdgeIt(const Adaptor& _graph, const Edge& edge) : \n\tEdge(edge), graph(&_graph) {}\n\n      InEdgeIt& operator++() { \n\tgraph->nextIn(*this);\n\treturn *this; \n      }\n\n    };\n\n    class UEdgeIt : public Parent::UEdge { \n      const Adaptor* graph;\n    public:\n\n      UEdgeIt() { }\n\n      UEdgeIt(Invalid i) : UEdge(i) { }\n\n      explicit UEdgeIt(const Adaptor& _graph) : graph(&_graph) {\n\t_graph.first(static_cast<UEdge&>(*this));\n      }\n\n      UEdgeIt(const Adaptor& _graph, const UEdge& e) : \n\tUEdge(e), graph(&_graph) { }\n\n      UEdgeIt& operator++() { \n\tgraph->next(*this);\n\treturn *this; \n      }\n\n    };\n\n    class IncEdgeIt : public Parent::UEdge { \n      friend class UGraphAdaptorExtender;\n      const Adaptor* graph;\n      bool direction;\n    public:\n\n      IncEdgeIt() { }\n\n      IncEdgeIt(Invalid i) : UEdge(i), direction(false) { }\n\n      IncEdgeIt(const Adaptor& _graph, const Node &n) : graph(&_graph) {\n\t_graph.firstInc(static_cast<UEdge&>(*this), direction, n);\n      }\n\n      IncEdgeIt(const Adaptor& _graph, const UEdge &ue, const Node &n)\n\t: graph(&_graph), UEdge(ue) {\n\tdirection = (_graph.source(ue) == n);\n      }\n\n      IncEdgeIt& operator++() {\n\tgraph->nextInc(*this, direction);\n\treturn *this; \n      }\n    };\n\n    /// \\brief Base node of the iterator\n    ///\n    /// Returns the base node (ie. the source in this case) of the iterator\n    Node baseNode(const OutEdgeIt &e) const {\n      return Parent::source(static_cast<const Edge&>(e));\n    }\n    /// \\brief Running node of the iterator\n    ///\n    /// Returns the running node (ie. the target in this case) of the\n    /// iterator\n    Node runningNode(const OutEdgeIt &e) const {\n      return Parent::target(static_cast<const Edge&>(e));\n    }\n\n    /// \\brief Base node of the iterator\n    ///\n    /// Returns the base node (ie. the target in this case) of the iterator\n    Node baseNode(const InEdgeIt &e) const {\n      return Parent::target(static_cast<const Edge&>(e));\n    }\n    /// \\brief Running node of the iterator\n    ///\n    /// Returns the running node (ie. the source in this case) of the\n    /// iterator\n    Node runningNode(const InEdgeIt &e) const {\n      return Parent::source(static_cast<const Edge&>(e));\n    }\n\n    /// Base node of the iterator\n    ///\n    /// Returns the base node of the iterator\n    Node baseNode(const IncEdgeIt &e) const {\n      return e.direction ? source(e) : target(e);\n    }\n    /// Running node of the iterator\n    ///\n    /// Returns the running node of the iterator\n    Node runningNode(const IncEdgeIt &e) const {\n      return e.direction ? target(e) : source(e);\n    }\n\n  };\n\n  /// \\ingroup graphbits\n  ///\n  /// \\brief Extender for the BpUGraphAdaptors\n  template <typename Base>\n  class BpUGraphAdaptorExtender : public Base {\n  public:\n    typedef Base Parent;\n    typedef BpUGraphAdaptorExtender Graph;\n\n    typedef typename Parent::Node Node;\n    typedef typename Parent::BNode BNode;\n    typedef typename Parent::ANode ANode;\n    typedef typename Parent::Edge Edge;\n    typedef typename Parent::UEdge UEdge;\n\n\n    int maxId(Node) const {\n      return Parent::maxNodeId();\n    }\n    int maxId(BNode) const {\n      return Parent::maxBNodeId();\n    }\n    int maxId(ANode) const {\n      return Parent::maxANodeId();\n    }\n    int maxId(Edge) const {\n      return Parent::maxEdgeId();\n    }\n    int maxId(UEdge) const {\n      return Parent::maxUEdgeId();\n    }\n\n\n    Node fromId(int id, Node) const {\n      return Parent::nodeFromId(id);\n    }\n    ANode fromId(int id, ANode) const {\n      return Parent::nodeFromANodeId(id);\n    }\n    BNode fromId(int id, BNode) const {\n      return Parent::nodeFromBNodeId(id);\n    }\n    Edge fromId(int id, Edge) const {\n      return Parent::edgeFromId(id);\n    }\n    UEdge fromId(int id, UEdge) const {\n      return Parent::uEdgeFromId(id);\n    }  \n  \n    class NodeIt : public Node { \n      const Graph* graph;\n    public:\n    \n      NodeIt() { }\n    \n      NodeIt(Invalid i) : Node(INVALID) { }\n    \n      explicit NodeIt(const Graph& _graph) : graph(&_graph) {\n\tgraph->first(static_cast<Node&>(*this));\n      }\n\n      NodeIt(const Graph& _graph, const Node& node) \n\t: Node(node), graph(&_graph) { }\n    \n      NodeIt& operator++() { \n\tgraph->next(*this);\n\treturn *this; \n      }\n\n    };\n\n    class ANodeIt : public Node { \n      friend class BpUGraphAdaptorExtender;\n      const Graph* graph;\n    public:\n    \n      ANodeIt() { }\n    \n      ANodeIt(Invalid i) : Node(INVALID) { }\n    \n      explicit ANodeIt(const Graph& _graph) : graph(&_graph) {\n\tgraph->firstANode(static_cast<Node&>(*this));\n      }\n\n      ANodeIt(const Graph& _graph, const Node& node) \n\t: Node(node), graph(&_graph) {}\n    \n      ANodeIt& operator++() { \n\tgraph->nextANode(*this);\n\treturn *this; \n      }\n    };\n\n    class BNodeIt : public Node { \n      friend class BpUGraphAdaptorExtender;\n      const Graph* graph;\n    public:\n    \n      BNodeIt() { }\n    \n      BNodeIt(Invalid i) : Node(INVALID) { }\n    \n      explicit BNodeIt(const Graph& _graph) : graph(&_graph) {\n\tgraph->firstBNode(static_cast<Node&>(*this));\n      }\n\n      BNodeIt(const Graph& _graph, const Node& node) \n\t: Node(node), graph(&_graph) {}\n    \n      BNodeIt& operator++() { \n\tgraph->nextBNode(*this);\n\treturn *this; \n      }\n    };\n\n    class EdgeIt : public Edge { \n      friend class BpUGraphAdaptorExtender;\n      const Graph* graph;\n    public:\n    \n      EdgeIt() { }\n    \n      EdgeIt(Invalid i) : Edge(INVALID) { }\n    \n      explicit EdgeIt(const Graph& _graph) : graph(&_graph) {\n\tgraph->first(static_cast<Edge&>(*this));\n      }\n\n      EdgeIt(const Graph& _graph, const Edge& edge) \n\t: Edge(edge), graph(&_graph) { }\n    \n      EdgeIt& operator++() { \n\tgraph->next(*this);\n\treturn *this; \n      }\n\n    };\n\n    class UEdgeIt : public UEdge { \n      friend class BpUGraphAdaptorExtender;\n      const Graph* graph;\n    public:\n    \n      UEdgeIt() { }\n    \n      UEdgeIt(Invalid i) : UEdge(INVALID) { }\n    \n      explicit UEdgeIt(const Graph& _graph) : graph(&_graph) {\n\tgraph->first(static_cast<UEdge&>(*this));\n      }\n\n      UEdgeIt(const Graph& _graph, const UEdge& edge) \n\t: UEdge(edge), graph(&_graph) { }\n    \n      UEdgeIt& operator++() { \n\tgraph->next(*this);\n\treturn *this; \n      }\n    };\n\n    class OutEdgeIt : public Edge { \n      friend class BpUGraphAdaptorExtender;\n      const Graph* graph;\n    public:\n    \n      OutEdgeIt() { }\n    \n      OutEdgeIt(Invalid i) : Edge(i) { }\n    \n      OutEdgeIt(const Graph& _graph, const Node& node) \n\t: graph(&_graph) {\n\tgraph->firstOut(*this, node);\n      }\n    \n      OutEdgeIt(const Graph& _graph, const Edge& edge) \n\t: Edge(edge), graph(&_graph) {}\n    \n      OutEdgeIt& operator++() { \n\tgraph->nextOut(*this);\n\treturn *this; \n      }\n\n    };\n\n\n    class InEdgeIt : public Edge { \n      friend class BpUGraphAdaptorExtender;\n      const Graph* graph;\n    public:\n    \n      InEdgeIt() { }\n    \n      InEdgeIt(Invalid i) : Edge(i) { }\n    \n      InEdgeIt(const Graph& _graph, const Node& node) \n\t: graph(&_graph) {\n\tgraph->firstIn(*this, node);\n      }\n    \n      InEdgeIt(const Graph& _graph, const Edge& edge) : \n\tEdge(edge), graph(&_graph) {}\n    \n      InEdgeIt& operator++() { \n\tgraph->nextIn(*this);\n\treturn *this; \n      }\n\n    };\n  \n    /// \\brief Base node of the iterator\n    ///\n    /// Returns the base node (ie. the source in this case) of the iterator\n    Node baseNode(const OutEdgeIt &e) const {\n      return Parent::source(static_cast<const Edge&>(e));\n    }\n    /// \\brief Running node of the iterator\n    ///\n    /// Returns the running node (ie. the target in this case) of the\n    /// iterator\n    Node runningNode(const OutEdgeIt &e) const {\n      return Parent::target(static_cast<const Edge&>(e));\n    }\n  \n    /// \\brief Base node of the iterator\n    ///\n    /// Returns the base node (ie. the target in this case) of the iterator\n    Node baseNode(const InEdgeIt &e) const {\n      return Parent::target(static_cast<const Edge&>(e));\n    }\n    /// \\brief Running node of the iterator\n    ///\n    /// Returns the running node (ie. the source in this case) of the\n    /// iterator\n    Node runningNode(const InEdgeIt &e) const {\n      return Parent::source(static_cast<const Edge&>(e));\n    }\n  \n    class IncEdgeIt : public Parent::UEdge { \n      friend class BpUGraphAdaptorExtender;\n      const Graph* graph;\n      bool direction;\n    public:\n    \n      IncEdgeIt() { }\n    \n      IncEdgeIt(Invalid i) : UEdge(i), direction(true) { }\n    \n      IncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) {\n\tgraph->firstInc(*this, direction, n);\n      }\n\n      IncEdgeIt(const Graph& _graph, const UEdge &ue, const Node &n)\n\t: graph(&_graph), UEdge(ue) {\n\tdirection = (graph->source(ue) == n);\n      }\n\n      IncEdgeIt& operator++() {\n\tgraph->nextInc(*this, direction);\n\treturn *this; \n      }\n    };\n  \n\n    /// Base node of the iterator\n    ///\n    /// Returns the base node of the iterator\n    Node baseNode(const IncEdgeIt &e) const {\n      return e.direction ? source(e) : target(e);\n    }\n\n    /// Running node of the iterator\n    ///\n    /// Returns the running node of the iterator\n    Node runningNode(const IncEdgeIt &e) const {\n      return e.direction ? target(e) : source(e);\n    }\n\n    Node oppositeNode(const Node &n, const UEdge &e) const {\n      if( n == Parent::source(e))\n\treturn Parent::target(e);\n      else if( n == Parent::target(e))\n\treturn Parent::source(e);\n      else\n\treturn INVALID;\n    }\n\n    Edge oppositeEdge(const Edge &e) const {\n      return Parent::direct(e, !Parent::direction(e));\n    }\n\n    using Parent::direct;\n    Edge direct(const UEdge &ue, const Node &s) const {\n      return Parent::direct(ue, Parent::source(ue) == s);\n    }\n\n  };\n\n\n}\n\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/graph_extender.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_GRAPH_EXTENDER_H\n#define LEMON_BITS_GRAPH_EXTENDER_H\n\n#include <lemon/bits/invalid.h>\n#include <lemon/bits/utility.h>\n#include <lemon/error.h>\n\n#include <lemon/bits/map_extender.h>\n#include <lemon/bits/default_map.h>\n\n#include <lemon/concept_check.h>\n#include <lemon/concepts/maps.h>\n\n///\\ingroup graphbits\n///\\file\n///\\brief Extenders for the graph types\nnamespace lemon {\n\t\n\t/// \\ingroup graphbits\n\t///\n\t/// \\brief Extender for the Graphs\n\ttemplate <typename Base>\n\tclass GraphExtender : public Base {\n\tpublic:\n\t\t\n\t\ttypedef Base Parent;\n\t\ttypedef GraphExtender Graph;\n\t\t\n\t\t// Base extensions\n\t\t\n\t\ttypedef typename Parent::Node Node;\n\t\ttypedef typename Parent::Edge Edge;\n\t\t\n\t\tint maxId(Node) const {\n\t\t\treturn Parent::maxNodeId();\n\t\t}\n\t\t\n\t\tint maxId(Edge) const {\n\t\t\treturn Parent::maxEdgeId();\n\t\t}\n\t\t\n\t\tNode fromId(int id, Node) const {\n\t\t\treturn Parent::nodeFromId(id);\n\t\t}\n\t\t\n\t\tEdge fromId(int id, Edge) const {\n\t\t\treturn Parent::edgeFromId(id);\n\t\t}\n\t\t\n\t\tNode oppositeNode(const Node &n, const Edge &e) const {\n\t\t\tif (n == Parent::source(e))\n\t\t\t\treturn Parent::target(e);\n\t\t\telse if(n==Parent::target(e))\n\t\t\t\treturn Parent::source(e);\n\t\t\telse\n\t\t\t\treturn INVALID;\n\t\t}\n\t\t\n\t\t// Alterable extension\n\t\t\n\t\ttypedef AlterationNotifier<GraphExtender, Node> NodeNotifier;\n\t\ttypedef AlterationNotifier<GraphExtender, Edge> EdgeNotifier;\n\t\t\n\t\t\n\tprotected:\n\t\t\n\t\tmutable NodeNotifier node_notifier;\n\t\tmutable EdgeNotifier edge_notifier;\n\t\t\n\tpublic:\n\t\t\n\t\tNodeNotifier& notifier(Node) const {\n\t\t\treturn node_notifier;\n\t\t}\n\t\t\n\t\tEdgeNotifier& notifier(Edge) const {\n\t\t\treturn edge_notifier;\n\t\t}\n\t\t\n\t\tclass NodeIt : public Node { \n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tNodeIt() {}\n\t\t\t\n\t\t\tNodeIt(Invalid i) : Node(i) { }\n\t\t\t\n\t\t\texplicit NodeIt(const Graph& _graph) : graph(&_graph) {\n\t\t\t\t_graph.first(static_cast<Node&>(*this));\n\t\t\t}\n\t\t\t\n\t\t\tNodeIt(const Graph& _graph, const Node& node) \n\t\t\t: Node(node), graph(&_graph) {}\n\t\t\t\n\t\t\tNodeIt& operator++() { \n\t\t\t\tgraph->next(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t\n\t\tclass EdgeIt : public Edge { \n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tEdgeIt() { }\n\t\t\t\n\t\t\tEdgeIt(Invalid i) : Edge(i) { }\n\t\t\t\n\t\t\texplicit EdgeIt(const Graph& _graph) : graph(&_graph) {\n\t\t\t\t_graph.first(static_cast<Edge&>(*this));\n\t\t\t}\n\t\t\t\n\t\t\tEdgeIt(const Graph& _graph, const Edge& e) : \n\t\t\tEdge(e), graph(&_graph) { }\n\t\t\t\n\t\t\tEdgeIt& operator++() { \n\t\t\t\tgraph->next(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t\n\t\tclass OutEdgeIt : public Edge { \n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tOutEdgeIt() { }\n\t\t\t\n\t\t\tOutEdgeIt(Invalid i) : Edge(i) { }\n\t\t\t\n\t\t\tOutEdgeIt(const Graph& _graph, const Node& node) \n\t\t\t: graph(&_graph) {\n\t\t\t\t_graph.firstOut(*this, node);\n\t\t\t}\n\t\t\t\n\t\t\tOutEdgeIt(const Graph& _graph, const Edge& edge) \n\t\t\t: Edge(edge), graph(&_graph) {}\n\t\t\t\n\t\t\tOutEdgeIt& operator++() { \n\t\t\t\tgraph->nextOut(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t\n\t\tclass InEdgeIt : public Edge { \n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tInEdgeIt() { }\n\t\t\t\n\t\t\tInEdgeIt(Invalid i) : Edge(i) { }\n\t\t\t\n\t\t\tInEdgeIt(const Graph& _graph, const Node& node) \n\t\t\t: graph(&_graph) {\n\t\t\t\t_graph.firstIn(*this, node);\n\t\t\t}\n\t\t\t\n\t\t\tInEdgeIt(const Graph& _graph, const Edge& edge) : \n\t\t\tEdge(edge), graph(&_graph) {}\n\t\t\t\n\t\t\tInEdgeIt& operator++() { \n\t\t\t\tgraph->nextIn(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t/// \\brief Base node of the iterator\n\t\t///\n\t\t/// Returns the base node (i.e. the source in this case) of the iterator\n\t\tNode baseNode(const OutEdgeIt &e) const {\n\t\t\treturn Parent::source(e);\n\t\t}\n\t\t/// \\brief Running node of the iterator\n\t\t///\n\t\t/// Returns the running node (i.e. the target in this case) of the\n\t\t/// iterator\n\t\tNode runningNode(const OutEdgeIt &e) const {\n\t\t\treturn Parent::target(e);\n\t\t}\n\t\t\n\t\t/// \\brief Base node of the iterator\n\t\t///\n\t\t/// Returns the base node (i.e. the target in this case) of the iterator\n\t\tNode baseNode(const InEdgeIt &e) const {\n\t\t\treturn Parent::target(e);\n\t\t}\n\t\t/// \\brief Running node of the iterator\n\t\t///\n\t\t/// Returns the running node (i.e. the source in this case) of the\n\t\t/// iterator\n\t\tNode runningNode(const InEdgeIt &e) const {\n\t\t\treturn Parent::source(e);\n\t\t}\n\t\t\n\t\t\n\t\ttemplate <typename _Value>\n\t\tclass NodeMap \n\t\t: public MapExtender<DefaultMap<Graph, Node, _Value> > {\n\t\tpublic:\n\t\t\ttypedef GraphExtender Graph;\n\t\t\ttypedef MapExtender<DefaultMap<Graph, Node, _Value> > Parent;\n\t\t\t\n\t\t\texplicit NodeMap(const Graph& graph) \n\t\t\t: Parent(graph) {}\n\t\t\tNodeMap(const Graph& graph, const _Value& value) \n\t\t\t: Parent(graph, value) {}\n\t\t\t\n\t\t\tNodeMap& operator=(const NodeMap& cmap) {\n\t\t\t\treturn operator=<NodeMap>(cmap);\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename CMap>\n\t\t\tNodeMap& operator=(const CMap& cmap) {\n\t\t\t\tParent::operator=(cmap);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\ttemplate <typename _Value>\n\t\tclass EdgeMap \n\t\t: public MapExtender<DefaultMap<Graph, Edge, _Value> > {\n\t\tpublic:\n\t\t\ttypedef GraphExtender Graph;\n\t\t\ttypedef MapExtender<DefaultMap<Graph, Edge, _Value> > Parent;\n\t\t\t\n\t\t\texplicit EdgeMap(const Graph& graph) \n\t\t\t: Parent(graph) {}\n\t\t\tEdgeMap(const Graph& graph, const _Value& value) \n\t\t\t: Parent(graph, value) {}\n\t\t\t\n\t\t\tEdgeMap& operator=(const EdgeMap& cmap) {\n\t\t\t\treturn operator=<EdgeMap>(cmap);\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename CMap>\n\t\t\tEdgeMap& operator=(const CMap& cmap) {\n\t\t\t\tParent::operator=(cmap);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t};\n\t\t\n\t\t\n\t\tNode addNode() {\n\t\t\tNode node = Parent::addNode();\n\t\t\tnotifier(Node()).add(node);\n\t\t\treturn node;\n\t\t}\n\t\t\n\t\tEdge addEdge(const Node& from, const Node& to) {\n\t\t\tEdge edge = Parent::addEdge(from, to);\n\t\t\tnotifier(Edge()).add(edge);\n\t\t\treturn edge;\n\t\t}\n\t\t\n\t\tvoid clear() {\n\t\t\tnotifier(Edge()).clear();\n\t\t\tnotifier(Node()).clear();\n\t\t\tParent::clear();\n\t\t}\n\t\t\n\t\ttemplate <typename Graph, typename NodeRefMap, typename EdgeRefMap>\n\t\tvoid build(const Graph& graph, NodeRefMap& nodeRef, EdgeRefMap& edgeRef) {\n\t\t\tParent::build(graph, nodeRef, edgeRef);\n\t\t\tnotifier(Node()).build();\n\t\t\tnotifier(Edge()).build();\n\t\t}\n\t\t\n\t\tvoid erase(const Node& node) {\n\t\t\tEdge edge;\n\t\t\tParent::firstOut(edge, node);\n\t\t\twhile (edge != INVALID ) {\n\t\t\t\terase(edge);\n\t\t\t\tParent::firstOut(edge, node);\n\t\t\t} \n\t\t\t\n\t\t\tParent::firstIn(edge, node);\n\t\t\twhile (edge != INVALID ) {\n\t\t\t\terase(edge);\n\t\t\t\tParent::firstIn(edge, node);\n\t\t\t}\n\t\t\t\n\t\t\tnotifier(Node()).erase(node);\n\t\t\tParent::erase(node);\n\t\t}\n\t\t\n\t\tvoid erase(const Edge& edge) {\n\t\t\tnotifier(Edge()).erase(edge);\n\t\t\tParent::erase(edge);\n\t\t}\n\t\t\n\t\tGraphExtender() {\n\t\t\tnode_notifier.setContainer(*this);\n\t\t\tedge_notifier.setContainer(*this);\n\t\t} \n\t\t\n\t\t\n\t\t~GraphExtender() {\n\t\t\tedge_notifier.clear();\n\t\t\tnode_notifier.clear();\n\t\t}\n\t};\n\t\n\t/// \\ingroup graphbits\n\t///\n\t/// \\brief Extender for the UGraphs\n\ttemplate <typename Base> \n\tclass UGraphExtender : public Base {\n\tpublic:\n\t\t\n\t\ttypedef Base Parent;\n\t\ttypedef UGraphExtender Graph;\n\t\t\n\t\ttypedef True UndirectedTag;\n\t\t\n\t\ttypedef typename Parent::Node Node;\n\t\ttypedef typename Parent::Edge Edge;\n\t\ttypedef typename Parent::UEdge UEdge;\n\t\t\n\t\t// UGraph extension    \n\t\t\n\t\tint maxId(Node) const {\n\t\t\treturn Parent::maxNodeId();\n\t\t}\n\t\t\n\t\tint maxId(Edge) const {\n\t\t\treturn Parent::maxEdgeId();\n\t\t}\n\t\t\n\t\tint maxId(UEdge) const {\n\t\t\treturn Parent::maxUEdgeId();\n\t\t}\n\t\t\n\t\tNode fromId(int id, Node) const {\n\t\t\treturn Parent::nodeFromId(id);\n\t\t}\n\t\t\n\t\tEdge fromId(int id, Edge) const {\n\t\t\treturn Parent::edgeFromId(id);\n\t\t}\n\t\t\n\t\tUEdge fromId(int id, UEdge) const {\n\t\t\treturn Parent::uEdgeFromId(id);\n\t\t}\n\t\t\n\t\tNode oppositeNode(const Node &n, const UEdge &e) const {\n\t\t\tif( n == Parent::source(e))\n\t\t\t\treturn Parent::target(e);\n\t\t\telse if( n == Parent::target(e))\n\t\t\t\treturn Parent::source(e);\n\t\t\telse\n\t\t\t\treturn INVALID;\n\t\t}\n\t\t\n\t\tEdge oppositeEdge(const Edge &e) const {\n\t\t\treturn Parent::direct(e, !Parent::direction(e));\n\t\t}\n\t\t\n\t\tusing Parent::direct;\n\t\tEdge direct(const UEdge &ue, const Node &s) const {\n\t\t\treturn Parent::direct(ue, Parent::source(ue) == s);\n\t\t}\n\t\t\n\t\t// Alterable extension\n\t\t\n\t\ttypedef AlterationNotifier<UGraphExtender, Node> NodeNotifier;\n\t\ttypedef AlterationNotifier<UGraphExtender, Edge> EdgeNotifier;\n\t\ttypedef AlterationNotifier<UGraphExtender, UEdge> UEdgeNotifier;\n\t\t\n\t\t\n\tprotected:\n\t\t\n\t\tmutable NodeNotifier node_notifier;\n\t\tmutable EdgeNotifier edge_notifier;\n\t\tmutable UEdgeNotifier uedge_notifier;\n\t\t\n\tpublic:\n\t\t\n\t\tNodeNotifier& notifier(Node) const {\n\t\t\treturn node_notifier;\n\t\t}\n\t\t\n\t\tEdgeNotifier& notifier(Edge) const {\n\t\t\treturn edge_notifier;\n\t\t}\n\t\t\n\t\tUEdgeNotifier& notifier(UEdge) const {\n\t\t\treturn uedge_notifier;\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\tclass NodeIt : public Node { \n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tNodeIt() {}\n\t\t\t\n\t\t\tNodeIt(Invalid i) : Node(i) { }\n\t\t\t\n\t\t\texplicit NodeIt(const Graph& _graph) : graph(&_graph) {\n\t\t\t\t_graph.first(static_cast<Node&>(*this));\n\t\t\t}\n\t\t\t\n\t\t\tNodeIt(const Graph& _graph, const Node& node) \n\t\t\t: Node(node), graph(&_graph) {}\n\t\t\t\n\t\t\tNodeIt& operator++() { \n\t\t\t\tgraph->next(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t\n\t\tclass EdgeIt : public Edge { \n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tEdgeIt() { }\n\t\t\t\n\t\t\tEdgeIt(Invalid i) : Edge(i) { }\n\t\t\t\n\t\t\texplicit EdgeIt(const Graph& _graph) : graph(&_graph) {\n\t\t\t\t_graph.first(static_cast<Edge&>(*this));\n\t\t\t}\n\t\t\t\n\t\t\tEdgeIt(const Graph& _graph, const Edge& e) : \n\t\t\tEdge(e), graph(&_graph) { }\n\t\t\t\n\t\t\tEdgeIt& operator++() { \n\t\t\t\tgraph->next(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t\n\t\tclass OutEdgeIt : public Edge { \n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tOutEdgeIt() { }\n\t\t\t\n\t\t\tOutEdgeIt(Invalid i) : Edge(i) { }\n\t\t\t\n\t\t\tOutEdgeIt(const Graph& _graph, const Node& node) \n\t\t\t: graph(&_graph) {\n\t\t\t\t_graph.firstOut(*this, node);\n\t\t\t}\n\t\t\t\n\t\t\tOutEdgeIt(const Graph& _graph, const Edge& edge) \n\t\t\t: Edge(edge), graph(&_graph) {}\n\t\t\t\n\t\t\tOutEdgeIt& operator++() { \n\t\t\t\tgraph->nextOut(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t\n\t\tclass InEdgeIt : public Edge { \n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tInEdgeIt() { }\n\t\t\t\n\t\t\tInEdgeIt(Invalid i) : Edge(i) { }\n\t\t\t\n\t\t\tInEdgeIt(const Graph& _graph, const Node& node) \n\t\t\t: graph(&_graph) {\n\t\t\t\t_graph.firstIn(*this, node);\n\t\t\t}\n\t\t\t\n\t\t\tInEdgeIt(const Graph& _graph, const Edge& edge) : \n\t\t\tEdge(edge), graph(&_graph) {}\n\t\t\t\n\t\t\tInEdgeIt& operator++() { \n\t\t\t\tgraph->nextIn(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t\n\t\tclass UEdgeIt : public Parent::UEdge { \n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tUEdgeIt() { }\n\t\t\t\n\t\t\tUEdgeIt(Invalid i) : UEdge(i) { }\n\t\t\t\n\t\t\texplicit UEdgeIt(const Graph& _graph) : graph(&_graph) {\n\t\t\t\t_graph.first(static_cast<UEdge&>(*this));\n\t\t\t}\n\t\t\t\n\t\t\tUEdgeIt(const Graph& _graph, const UEdge& e) : \n\t\t\tUEdge(e), graph(&_graph) { }\n\t\t\t\n\t\t\tUEdgeIt& operator++() { \n\t\t\t\tgraph->next(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\tclass IncEdgeIt : public Parent::UEdge {\n\t\t\tfriend class UGraphExtender;\n\t\t\tconst Graph* graph;\n\t\t\tbool direction;\n\t\tpublic:\n\t\t\t\n\t\t\tIncEdgeIt() { }\n\t\t\t\n\t\t\tIncEdgeIt(Invalid i) : UEdge(i), direction(false) { }\n\t\t\t\n\t\t\tIncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) {\n\t\t\t\t_graph.firstInc(*this, direction, n);\n\t\t\t}\n\t\t\t\n\t\t\tIncEdgeIt(const Graph& _graph, const UEdge &ue, const Node &n)\n\t\t\t: graph(&_graph), UEdge(ue) {\n\t\t\t\tdirection = (_graph.source(ue) == n);\n\t\t\t}\n\t\t\t\n\t\t\tIncEdgeIt& operator++() {\n\t\t\t\tgraph->nextInc(*this, direction);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t};\n\t\t\n\t\t/// \\brief Base node of the iterator\n\t\t///\n\t\t/// Returns the base node (ie. the source in this case) of the iterator\n\t\tNode baseNode(const OutEdgeIt &e) const {\n\t\t\treturn Parent::source(static_cast<const Edge&>(e));\n\t\t}\n\t\t/// \\brief Running node of the iterator\n\t\t///\n\t\t/// Returns the running node (ie. the target in this case) of the\n\t\t/// iterator\n\t\tNode runningNode(const OutEdgeIt &e) const {\n\t\t\treturn Parent::target(static_cast<const Edge&>(e));\n\t\t}\n\t\t\n\t\t/// \\brief Base node of the iterator\n\t\t///\n\t\t/// Returns the base node (ie. the target in this case) of the iterator\n\t\tNode baseNode(const InEdgeIt &e) const {\n\t\t\treturn Parent::target(static_cast<const Edge&>(e));\n\t\t}\n\t\t/// \\brief Running node of the iterator\n\t\t///\n\t\t/// Returns the running node (ie. the source in this case) of the\n\t\t/// iterator\n\t\tNode runningNode(const InEdgeIt &e) const {\n\t\t\treturn Parent::source(static_cast<const Edge&>(e));\n\t\t}\n\t\t\n\t\t/// Base node of the iterator\n\t\t///\n\t\t/// Returns the base node of the iterator\n\t\tNode baseNode(const IncEdgeIt &e) const {\n\t\t\treturn e.direction ? source(e) : target(e);\n\t\t}\n\t\t/// Running node of the iterator\n\t\t///\n\t\t/// Returns the running node of the iterator\n\t\tNode runningNode(const IncEdgeIt &e) const {\n\t\t\treturn e.direction ? target(e) : source(e);\n\t\t}\n\t\t\n\t\t// Mappable extension\n\t\t\n\t\ttemplate <typename _Value>\n\t\tclass NodeMap \n\t\t: public MapExtender<DefaultMap<Graph, Node, _Value> > {\n\t\tpublic:\n\t\t\ttypedef UGraphExtender Graph;\n\t\t\ttypedef MapExtender<DefaultMap<Graph, Node, _Value> > Parent;\n\t\t\t\n\t\t\tNodeMap(const Graph& graph) \n\t\t\t: Parent(graph) {}\n\t\t\tNodeMap(const Graph& graph, const _Value& value) \n\t\t\t: Parent(graph, value) {}\n\t\t\t\n\t\t\tNodeMap& operator=(const NodeMap& cmap) {\n\t\t\t\treturn operator=<NodeMap>(cmap);\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename CMap>\n\t\t\tNodeMap& operator=(const CMap& cmap) {\n\t\t\t\tParent::operator=(cmap);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\ttemplate <typename _Value>\n\t\tclass EdgeMap \n\t\t: public MapExtender<DefaultMap<Graph, Edge, _Value> > {\n\t\tpublic:\n\t\t\ttypedef UGraphExtender Graph;\n\t\t\ttypedef MapExtender<DefaultMap<Graph, Edge, _Value> > Parent;\n\t\t\t\n\t\t\tEdgeMap(const Graph& graph) \n\t\t\t: Parent(graph) {}\n\t\t\tEdgeMap(const Graph& graph, const _Value& value) \n\t\t\t: Parent(graph, value) {}\n\t\t\t\n\t\t\tEdgeMap& operator=(const EdgeMap& cmap) {\n\t\t\t\treturn operator=<EdgeMap>(cmap);\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename CMap>\n\t\t\tEdgeMap& operator=(const CMap& cmap) {\n\t\t\t\tParent::operator=(cmap);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t};\n\t\t\n\t\t\n\t\ttemplate <typename _Value>\n\t\tclass UEdgeMap \n\t\t: public MapExtender<DefaultMap<Graph, UEdge, _Value> > {\n\t\tpublic:\n\t\t\ttypedef UGraphExtender Graph;\n\t\t\ttypedef MapExtender<DefaultMap<Graph, UEdge, _Value> > Parent;\n\t\t\t\n\t\t\tUEdgeMap(const Graph& graph) \n\t\t\t: Parent(graph) {}\n\t\t\t\n\t\t\tUEdgeMap(const Graph& graph, const _Value& value) \n\t\t\t: Parent(graph, value) {}\n\t\t\t\n\t\t\tUEdgeMap& operator=(const UEdgeMap& cmap) {\n\t\t\t\treturn operator=<UEdgeMap>(cmap);\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename CMap>\n\t\t\tUEdgeMap& operator=(const CMap& cmap) {\n\t\t\t\tParent::operator=(cmap);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t// Alteration extension\n\t\t\n\t\tNode addNode() {\n\t\t\tNode node = Parent::addNode();\n\t\t\tnotifier(Node()).add(node);\n\t\t\treturn node;\n\t\t}\n\t\t\n\t\tUEdge addEdge(const Node& from, const Node& to) {\n\t\t\tUEdge uedge = Parent::addEdge(from, to);\n\t\t\tnotifier(UEdge()).add(uedge);\n\t\t\tstd::vector<Edge> ev;\n\t\t\tev.push_back(Parent::direct(uedge, true));\n\t\t\tev.push_back(Parent::direct(uedge, false));      \n\t\t\tnotifier(Edge()).add(ev);\n\t\t\treturn uedge;\n\t\t}\n\t\t\n\t\tvoid clear() {\n\t\t\tnotifier(Edge()).clear();\n\t\t\tnotifier(UEdge()).clear();\n\t\t\tnotifier(Node()).clear();\n\t\t\tParent::clear();\n\t\t}\n\t\t\n\t\ttemplate <typename Graph, typename NodeRefMap, typename UEdgeRefMap>\n\t\tvoid build(const Graph& graph, NodeRefMap& nodeRef, \n\t\t\t\t   UEdgeRefMap& uEdgeRef) {\n\t\t\tParent::build(graph, nodeRef, uEdgeRef);\n\t\t\tnotifier(Node()).build();\n\t\t\tnotifier(UEdge()).build();\n\t\t\tnotifier(Edge()).build();\n\t\t}\n\t\t\n\t\tvoid erase(const Node& node) {\n\t\t\tEdge edge;\n\t\t\tParent::firstOut(edge, node);\n\t\t\twhile (edge != INVALID ) {\n\t\t\t\terase(edge);\n\t\t\t\tParent::firstOut(edge, node);\n\t\t\t} \n\t\t\t\n\t\t\tParent::firstIn(edge, node);\n\t\t\twhile (edge != INVALID ) {\n\t\t\t\terase(edge);\n\t\t\t\tParent::firstIn(edge, node);\n\t\t\t}\n\t\t\t\n\t\t\tnotifier(Node()).erase(node);\n\t\t\tParent::erase(node);\n\t\t}\n\t\t\n\t\tvoid erase(const UEdge& uedge) {\n\t\t\tstd::vector<Edge> ev;\n\t\t\tev.push_back(Parent::direct(uedge, true));\n\t\t\tev.push_back(Parent::direct(uedge, false));      \n\t\t\tnotifier(Edge()).erase(ev);\n\t\t\tnotifier(UEdge()).erase(uedge);\n\t\t\tParent::erase(uedge);\n\t\t}\n\t\t\n\t\tUGraphExtender() {\n\t\t\tnode_notifier.setContainer(*this); \n\t\t\tedge_notifier.setContainer(*this);\n\t\t\tuedge_notifier.setContainer(*this);\n\t\t} \n\t\t\n\t\t~UGraphExtender() {\n\t\t\tuedge_notifier.clear();\n\t\t\tedge_notifier.clear();\n\t\t\tnode_notifier.clear(); \n\t\t} \n\t\t\n\t};\n\t\n\t/// \\ingroup graphbits\n\t///\n\t/// \\brief Extender for the BpUGraphs\n\ttemplate <typename Base>\n\tclass BpUGraphExtender : public Base {\n\tpublic:\n\t\t\n\t\ttypedef Base Parent;\n\t\ttypedef BpUGraphExtender Graph;\n\t\t\n\t\ttypedef True UndirectedTag;\n\t\t\n\t\ttypedef typename Parent::Node Node;\n\t\ttypedef typename Parent::ANode ANode;\n\t\ttypedef typename Parent::BNode BNode;\n\t\ttypedef typename Parent::Edge Edge;\n\t\ttypedef typename Parent::UEdge UEdge;\n\t\t\n\t\t\n\t\tNode oppositeNode(const Node& node, const UEdge& edge) const {\n\t\t\treturn Parent::aNode(edge) == node ? \n\t\t\tParent::bNode(edge) : Parent::aNode(edge);\n\t\t}\n\t\t\n\t\tusing Parent::direct;\n\t\tEdge direct(const UEdge& edge, const Node& node) const {\n\t\t\treturn Parent::direct(edge, node == Parent::source(edge));\n\t\t}\n\t\t\n\t\tEdge oppositeEdge(const Edge& edge) const {\n\t\t\treturn direct(edge, !Parent::direction(edge));\n\t\t}\n\t\t\n\t\tint maxId(Node) const {\n\t\t\treturn Parent::maxNodeId();\n\t\t}\n\t\tint maxId(BNode) const {\n\t\t\treturn Parent::maxBNodeId();\n\t\t}\n\t\tint maxId(ANode) const {\n\t\t\treturn Parent::maxANodeId();\n\t\t}\n\t\tint maxId(Edge) const {\n\t\t\treturn Parent::maxEdgeId();\n\t\t}\n\t\tint maxId(UEdge) const {\n\t\t\treturn Parent::maxUEdgeId();\n\t\t}\n\t\t\n\t\t\n\t\tNode fromId(int id, Node) const {\n\t\t\treturn Parent::nodeFromId(id);\n\t\t}\n\t\tANode fromId(int id, ANode) const {\n\t\t\treturn Parent::nodeFromANodeId(id);\n\t\t}\n\t\tBNode fromId(int id, BNode) const {\n\t\t\treturn Parent::nodeFromBNodeId(id);\n\t\t}\n\t\tEdge fromId(int id, Edge) const {\n\t\t\treturn Parent::edgeFromId(id);\n\t\t}\n\t\tUEdge fromId(int id, UEdge) const {\n\t\t\treturn Parent::uEdgeFromId(id);\n\t\t}  \n\t\t\n\t\ttypedef AlterationNotifier<BpUGraphExtender, ANode> ANodeNotifier;\n\t\ttypedef AlterationNotifier<BpUGraphExtender, BNode> BNodeNotifier;\n\t\ttypedef AlterationNotifier<BpUGraphExtender, Node> NodeNotifier;\n\t\ttypedef AlterationNotifier<BpUGraphExtender, Edge> EdgeNotifier;\n\t\ttypedef AlterationNotifier<BpUGraphExtender, UEdge> UEdgeNotifier;\n\t\t\n\tprotected:\n\t\t\n\t\tmutable ANodeNotifier anode_notifier;\n\t\tmutable BNodeNotifier bnode_notifier;\n\t\tmutable NodeNotifier node_notifier;\n\t\tmutable EdgeNotifier edge_notifier;\n\t\tmutable UEdgeNotifier uedge_notifier;\n\t\t\n\tpublic:\n\t\t\n\t\tNodeNotifier& notifier(Node) const {\n\t\t\treturn node_notifier;\n\t\t}\n\t\t\n\t\tANodeNotifier& notifier(ANode) const {\n\t\t\treturn anode_notifier;\n\t\t}\n\t\t\n\t\tBNodeNotifier& notifier(BNode) const {\n\t\t\treturn bnode_notifier;\n\t\t}\n\t\t\n\t\tEdgeNotifier& notifier(Edge) const {\n\t\t\treturn edge_notifier;\n\t\t}\n\t\t\n\t\tUEdgeNotifier& notifier(UEdge) const {\n\t\t\treturn uedge_notifier;\n\t\t}\n\t\t\n\t\tclass NodeIt : public Node { \n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tNodeIt() { }\n\t\t\t\n\t\t\tNodeIt(Invalid i) : Node(INVALID) { }\n\t\t\t\n\t\t\texplicit NodeIt(const Graph& _graph) : graph(&_graph) {\n\t\t\t\tgraph->first(static_cast<Node&>(*this));\n\t\t\t}\n\t\t\t\n\t\t\tNodeIt(const Graph& _graph, const Node& node) \n\t\t\t: Node(node), graph(&_graph) { }\n\t\t\t\n\t\t\tNodeIt& operator++() { \n\t\t\t\tgraph->next(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\tclass ANodeIt : public Node { \n\t\t\tfriend class BpUGraphExtender;\n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tANodeIt() { }\n\t\t\t\n\t\t\tANodeIt(Invalid i) : Node(INVALID) { }\n\t\t\t\n\t\t\texplicit ANodeIt(const Graph& _graph) : graph(&_graph) {\n\t\t\t\tgraph->firstANode(static_cast<Node&>(*this));\n\t\t\t}\n\t\t\t\n\t\t\tANodeIt(const Graph& _graph, const Node& node) \n\t\t\t: Node(node), graph(&_graph) {}\n\t\t\t\n\t\t\tANodeIt& operator++() { \n\t\t\t\tgraph->nextANode(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t};\n\t\t\n\t\tclass BNodeIt : public Node { \n\t\t\tfriend class BpUGraphExtender;\n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tBNodeIt() { }\n\t\t\t\n\t\t\tBNodeIt(Invalid i) : Node(INVALID) { }\n\t\t\t\n\t\t\texplicit BNodeIt(const Graph& _graph) : graph(&_graph) {\n\t\t\t\tgraph->firstBNode(static_cast<Node&>(*this));\n\t\t\t}\n\t\t\t\n\t\t\tBNodeIt(const Graph& _graph, const Node& node) \n\t\t\t: Node(node), graph(&_graph) {}\n\t\t\t\n\t\t\tBNodeIt& operator++() { \n\t\t\t\tgraph->nextBNode(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t};\n\t\t\n\t\tclass EdgeIt : public Edge { \n\t\t\tfriend class BpUGraphExtender;\n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tEdgeIt() { }\n\t\t\t\n\t\t\tEdgeIt(Invalid i) : Edge(INVALID) { }\n\t\t\t\n\t\t\texplicit EdgeIt(const Graph& _graph) : graph(&_graph) {\n\t\t\t\tgraph->first(static_cast<Edge&>(*this));\n\t\t\t}\n\t\t\t\n\t\t\tEdgeIt(const Graph& _graph, const Edge& edge) \n\t\t\t: Edge(edge), graph(&_graph) { }\n\t\t\t\n\t\t\tEdgeIt& operator++() { \n\t\t\t\tgraph->next(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\tclass UEdgeIt : public UEdge { \n\t\t\tfriend class BpUGraphExtender;\n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tUEdgeIt() { }\n\t\t\t\n\t\t\tUEdgeIt(Invalid i) : UEdge(INVALID) { }\n\t\t\t\n\t\t\texplicit UEdgeIt(const Graph& _graph) : graph(&_graph) {\n\t\t\t\tgraph->first(static_cast<UEdge&>(*this));\n\t\t\t}\n\t\t\t\n\t\t\tUEdgeIt(const Graph& _graph, const UEdge& edge) \n\t\t\t: UEdge(edge), graph(&_graph) { }\n\t\t\t\n\t\t\tUEdgeIt& operator++() { \n\t\t\t\tgraph->next(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t};\n\t\t\n\t\tclass OutEdgeIt : public Edge { \n\t\t\tfriend class BpUGraphExtender;\n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tOutEdgeIt() { }\n\t\t\t\n\t\t\tOutEdgeIt(Invalid i) : Edge(i) { }\n\t\t\t\n\t\t\tOutEdgeIt(const Graph& _graph, const Node& node) \n\t\t\t: graph(&_graph) {\n\t\t\t\tgraph->firstOut(*this, node);\n\t\t\t}\n\t\t\t\n\t\t\tOutEdgeIt(const Graph& _graph, const Edge& edge) \n\t\t\t: Edge(edge), graph(&_graph) {}\n\t\t\t\n\t\t\tOutEdgeIt& operator++() { \n\t\t\t\tgraph->nextOut(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t\n\t\tclass InEdgeIt : public Edge { \n\t\t\tfriend class BpUGraphExtender;\n\t\t\tconst Graph* graph;\n\t\tpublic:\n\t\t\t\n\t\t\tInEdgeIt() { }\n\t\t\t\n\t\t\tInEdgeIt(Invalid i) : Edge(i) { }\n\t\t\t\n\t\t\tInEdgeIt(const Graph& _graph, const Node& node) \n\t\t\t: graph(&_graph) {\n\t\t\t\tgraph->firstIn(*this, node);\n\t\t\t}\n\t\t\t\n\t\t\tInEdgeIt(const Graph& _graph, const Edge& edge) : \n\t\t\tEdge(edge), graph(&_graph) {}\n\t\t\t\n\t\t\tInEdgeIt& operator++() { \n\t\t\t\tgraph->nextIn(*this);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\t/// \\brief Base node of the iterator\n\t\t///\n\t\t/// Returns the base node (ie. the source in this case) of the iterator\n\t\tNode baseNode(const OutEdgeIt &e) const {\n\t\t\treturn Parent::source(static_cast<const Edge&>(e));\n\t\t}\n\t\t/// \\brief Running node of the iterator\n\t\t///\n\t\t/// Returns the running node (ie. the target in this case) of the\n\t\t/// iterator\n\t\tNode runningNode(const OutEdgeIt &e) const {\n\t\t\treturn Parent::target(static_cast<const Edge&>(e));\n\t\t}\n\t\t\n\t\t/// \\brief Base node of the iterator\n\t\t///\n\t\t/// Returns the base node (ie. the target in this case) of the iterator\n\t\tNode baseNode(const InEdgeIt &e) const {\n\t\t\treturn Parent::target(static_cast<const Edge&>(e));\n\t\t}\n\t\t/// \\brief Running node of the iterator\n\t\t///\n\t\t/// Returns the running node (ie. the source in this case) of the\n\t\t/// iterator\n\t\tNode runningNode(const InEdgeIt &e) const {\n\t\t\treturn Parent::source(static_cast<const Edge&>(e));\n\t\t}\n\t\t\n\t\tclass IncEdgeIt : public Parent::UEdge { \n\t\t\tfriend class BpUGraphExtender;\n\t\t\tconst Graph* graph;\n\t\t\tbool direction;\n\t\tpublic:\n\t\t\t\n\t\t\tIncEdgeIt() { }\n\t\t\t\n\t\t\tIncEdgeIt(Invalid i) : UEdge(i), direction(true) { }\n\t\t\t\n\t\t\tIncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) {\n\t\t\t\tgraph->firstInc(*this, direction, n);\n\t\t\t}\n\t\t\t\n\t\t\tIncEdgeIt(const Graph& _graph, const UEdge &ue, const Node &n)\n\t\t\t: graph(&_graph), UEdge(ue) {\n\t\t\t\tdirection = (graph->source(ue) == n);\n\t\t\t}\n\t\t\t\n\t\t\tIncEdgeIt& operator++() {\n\t\t\t\tgraph->nextInc(*this, direction);\n\t\t\t\treturn *this; \n\t\t\t}\n\t\t};\n\t\t\n\t\t\n\t\t/// Base node of the iterator\n\t\t///\n\t\t/// Returns the base node of the iterator\n\t\tNode baseNode(const IncEdgeIt &e) const {\n\t\t\treturn e.direction ? source(e) : target(e);\n\t\t}\n\t\t\n\t\t/// Running node of the iterator\n\t\t///\n\t\t/// Returns the running node of the iterator\n\t\tNode runningNode(const IncEdgeIt &e) const {\n\t\t\treturn e.direction ? target(e) : source(e);\n\t\t}\n\t\t\n\t\ttemplate <typename _Value>\n\t\tclass ANodeMap \n\t\t: public MapExtender<DefaultMap<Graph, ANode, _Value> > {\n\t\tpublic:\n\t\t\ttypedef BpUGraphExtender Graph;\n\t\t\ttypedef MapExtender<DefaultMap<Graph, ANode, _Value> > Parent;\n\t\t\t\n\t\t\tANodeMap(const Graph& graph) \n\t\t\t: Parent(graph) {}\n\t\t\tANodeMap(const Graph& graph, const _Value& value) \n\t\t\t: Parent(graph, value) {}\n\t\t\t\n\t\t\tANodeMap& operator=(const ANodeMap& cmap) {\n\t\t\t\treturn operator=<ANodeMap>(cmap);\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename CMap>\n\t\t\tANodeMap& operator=(const CMap& cmap) {\n\t\t\t\tParent::operator=(cmap);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\t\ttemplate <typename _Value>\n\t\tclass BNodeMap \n\t\t: public MapExtender<DefaultMap<Graph, BNode, _Value> > {\n\t\tpublic:\n\t\t\ttypedef BpUGraphExtender Graph;\n\t\t\ttypedef MapExtender<DefaultMap<Graph, BNode, _Value> > Parent;\n\t\t\t\n\t\t\tBNodeMap(const Graph& graph) \n\t\t\t: Parent(graph) {}\n\t\t\tBNodeMap(const Graph& graph, const _Value& value) \n\t\t\t: Parent(graph, value) {}\n\t\t\t\n\t\t\tBNodeMap& operator=(const BNodeMap& cmap) {\n\t\t\t\treturn operator=<BNodeMap>(cmap);\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename CMap>\n\t\t\tBNodeMap& operator=(const CMap& cmap) {\n\t\t\t\tParent::operator=(cmap);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t\t\n\t\t};\n\t\t\n\tpublic:\n\t\t\n\t\ttemplate <typename _Value>\n\t\tclass NodeMap {\n\t\tpublic:\n\t\t\ttypedef BpUGraphExtender Graph;\n\t\t\t\n\t\t\ttypedef Node Key;\n\t\t\ttypedef _Value Value;\n\t\t\t\n\t\t\t/// The reference type of the map;\n\t\t\ttypedef typename ANodeMap<_Value>::Reference Reference;\n\t\t\t/// The const reference type of the map;\n\t\t\ttypedef typename ANodeMap<_Value>::ConstReference ConstReference;\n\t\t\t\n\t\t\ttypedef True ReferenceMapTag;\n\t\t\t\n\t\t\tNodeMap(const Graph& _graph) \n\t\t\t: graph(_graph), aNodeMap(_graph), bNodeMap(_graph) {}\n\t\t\tNodeMap(const Graph& _graph, const _Value& _value) \n\t\t\t: graph(_graph), aNodeMap(_graph, _value), bNodeMap(_graph, _value) {}\n\t\t\t\n\t\t\tNodeMap& operator=(const NodeMap& cmap) {\n\t\t\t\treturn operator=<NodeMap>(cmap);\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename CMap>\n\t\t\tNodeMap& operator=(const CMap& cmap) {\n\t\t\t\tcheckConcept<concepts::ReadMap<Node, _Value>, CMap>();\n\t\t\t\taNodeMap = cmap;\n\t\t\t\tbNodeMap = cmap;\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t\t\n\t\t\tConstReference operator[](const Key& node) const {\n\t\t\t\tif (Parent::aNode(node)) {\n\t\t\t\t\treturn aNodeMap[node];\n\t\t\t\t} else {\n\t\t\t\t\treturn bNodeMap[node];\n\t\t\t\t}\n\t\t\t} \n\t\t\t\n\t\t\tReference operator[](const Key& node) {\n\t\t\t\tif (Parent::aNode(node)) {\n\t\t\t\t\treturn aNodeMap[node];\n\t\t\t\t} else {\n\t\t\t\t\treturn bNodeMap[node];\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvoid set(const Key& node, const Value& value) {\n\t\t\t\tif (Parent::aNode(node)) {\n\t\t\t\t\taNodeMap.set(node, value);\n\t\t\t\t} else {\n\t\t\t\t\tbNodeMap.set(node, value);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tclass MapIt : public NodeIt {\n\t\t\tpublic:\n\t\t\t\t\n\t\t\t\ttypedef NodeIt Parent;\n\t\t\t\t\n\t\t\t\texplicit MapIt(NodeMap& _map) \n\t\t\t\t: Parent(_map.graph), map(_map) {}\n\t\t\t\t\n\t\t\t\ttypename MapTraits<NodeMap>::ConstReturnValue operator*() const {\n\t\t\t\t\treturn map[*this];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\ttypename MapTraits<NodeMap>::ReturnValue operator*() {\n\t\t\t\t\treturn map[*this];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvoid set(const Value& value) {\n\t\t\t\t\tmap.set(*this, value);\n\t\t\t\t}\n\t\t\t\t\n\t\t\tprivate:\n\t\t\t\tNodeMap& map;\n\t\t\t};\n\t\t\t\n\t\t\tclass ConstMapIt : public NodeIt {\n\t\t\tpublic:\n\t\t\t\t\n\t\t\t\ttypedef NodeIt Parent;\n\t\t\t\t\n\t\t\t\texplicit ConstMapIt(const NodeMap& _map) \n\t\t\t\t: Parent(_map.graph), map(_map) {}\n\t\t\t\t\n\t\t\t\ttypename MapTraits<NodeMap>::ConstReturnValue operator*() const {\n\t\t\t\t\treturn map[*this];\n\t\t\t\t}\n\t\t\t\t\n\t\t\tprivate:\n\t\t\t\tconst NodeMap& map;\n\t\t\t};\n\t\t\t\n\t\t\tclass ItemIt : public NodeIt {\n\t\t\tpublic:\n\t\t\t\t\n\t\t\t\ttypedef NodeIt Parent;\n\t\t\t\t\n\t\t\t\texplicit ItemIt(const NodeMap& _map)\n\t\t\t\t: Parent(_map.graph) {}\n\t\t\t\t\n\t\t\t};\n\t\t\t\n\t\tprivate:\n\t\t\tconst Graph& graph;\n\t\t\tANodeMap<_Value> aNodeMap;\n\t\t\tBNodeMap<_Value> bNodeMap;\n\t\t};\n\t\t\n\t\t\n\t\ttemplate <typename _Value>\n\t\tclass EdgeMap \n\t\t: public MapExtender<DefaultMap<Graph, Edge, _Value> > {\n\t\tpublic:\n\t\t\ttypedef BpUGraphExtender Graph;\n\t\t\ttypedef MapExtender<DefaultMap<Graph, Edge, _Value> > Parent;\n\t\t\t\n\t\t\tEdgeMap(const Graph& graph) \n\t\t\t: Parent(graph) {}\n\t\t\tEdgeMap(const Graph& graph, const _Value& value) \n\t\t\t: Parent(graph, value) {}\n\t\t\t\n\t\t\tEdgeMap& operator=(const EdgeMap& cmap) {\n\t\t\t\treturn operator=<EdgeMap>(cmap);\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename CMap>\n\t\t\tEdgeMap& operator=(const CMap& cmap) {\n\t\t\t\tParent::operator=(cmap);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t};\n\t\t\n\t\ttemplate <typename _Value>\n\t\tclass UEdgeMap \n\t\t: public MapExtender<DefaultMap<Graph, UEdge, _Value> > {\n\t\tpublic:\n\t\t\ttypedef BpUGraphExtender Graph;\n\t\t\ttypedef MapExtender<DefaultMap<Graph, UEdge, _Value> > Parent;\n\t\t\t\n\t\t\tUEdgeMap(const Graph& graph) \n\t\t\t: Parent(graph) {}\n\t\t\tUEdgeMap(const Graph& graph, const _Value& value) \n\t\t\t: Parent(graph, value) {}\n\t\t\t\n\t\t\tUEdgeMap& operator=(const UEdgeMap& cmap) {\n\t\t\t\treturn operator=<UEdgeMap>(cmap);\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename CMap>\n\t\t\tUEdgeMap& operator=(const CMap& cmap) {\n\t\t\t\tParent::operator=(cmap);\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t};\n\t\t\n\t\t\n\t\tNode addANode() {\n\t\t\tNode node = Parent::addANode();\n\t\t\tnotifier(ANode()).add(node);\n\t\t\tnotifier(Node()).add(node);\n\t\t\treturn node;\n\t\t}\n\t\t\n\t\tNode addBNode() {\n\t\t\tNode node = Parent::addBNode();\n\t\t\tnotifier(BNode()).add(node);\n\t\t\tnotifier(Node()).add(node);\n\t\t\treturn node;\n\t\t}\n\t\t\n\t\tUEdge addEdge(const Node& s, const Node& t) {\n\t\t\tUEdge uedge = Parent::addEdge(s, t);\n\t\t\tnotifier(UEdge()).add(uedge);\n\t\t\t\n\t\t\tstd::vector<Edge> ev;\n\t\t\tev.push_back(Parent::direct(uedge, true));\n\t\t\tev.push_back(Parent::direct(uedge, false));\n\t\t\tnotifier(Edge()).add(ev);\n\t\t\t\n\t\t\treturn uedge;\n\t\t}\n\t\t\n\t\tvoid clear() {\n\t\t\tnotifier(Edge()).clear();\n\t\t\tnotifier(UEdge()).clear();\n\t\t\tnotifier(Node()).clear();\n\t\t\tnotifier(BNode()).clear();\n\t\t\tnotifier(ANode()).clear();\n\t\t\tParent::clear();\n\t\t}\n\t\t\n\t\ttemplate <typename Graph, typename ANodeRefMap, \n\t\ttypename BNodeRefMap, typename UEdgeRefMap>\n\t\tvoid build(const Graph& graph, ANodeRefMap& aNodeRef, \n\t\t\t\t   BNodeRefMap& bNodeRef, UEdgeRefMap& uEdgeRef) {\n\t\t\tParent::build(graph, aNodeRef, bNodeRef, uEdgeRef);\n\t\t\tnotifier(ANode()).build();\n\t\t\tnotifier(BNode()).build();\n\t\t\tnotifier(Node()).build();\n\t\t\tnotifier(UEdge()).build();\n\t\t\tnotifier(Edge()).build();\n\t\t}\n\t\t\n\t\tvoid erase(const Node& node) {\n\t\t\tUEdge uedge;\n\t\t\tif (Parent::aNode(node)) {\n\t\t\t\tParent::firstFromANode(uedge, node);\n\t\t\t\twhile (uedge != INVALID) {\n\t\t\t\t\terase(uedge);\n\t\t\t\t\tParent::firstFromANode(uedge, node);\n\t\t\t\t}\n\t\t\t\tnotifier(ANode()).erase(node);\n\t\t\t} else {\n\t\t\t\tParent::firstFromBNode(uedge, node);\n\t\t\t\twhile (uedge != INVALID) {\n\t\t\t\t\terase(uedge);\n\t\t\t\t\tParent::firstFromBNode(uedge, node);\n\t\t\t\t}\n\t\t\t\tnotifier(BNode()).erase(node);\n\t\t\t}\n\t\t\t\n\t\t\tnotifier(Node()).erase(node);\n\t\t\tParent::erase(node);\n\t\t}\n\t\t\n\t\tvoid erase(const UEdge& uedge) {\n\t\t\tstd::vector<Edge> ev;\n\t\t\tev.push_back(Parent::direct(uedge, true));\n\t\t\tev.push_back(Parent::direct(uedge, false));\n\t\t\tnotifier(Edge()).erase(ev);\n\t\t\tnotifier(UEdge()).erase(uedge);\n\t\t\tParent::erase(uedge);\n\t\t}\n\t\t\n\t\t\n\t\tBpUGraphExtender() {\n\t\t\tanode_notifier.setContainer(*this); \n\t\t\tbnode_notifier.setContainer(*this); \n\t\t\tnode_notifier.setContainer(*this); \n\t\t\tedge_notifier.setContainer(*this); \n\t\t\tuedge_notifier.setContainer(*this);\n\t\t} \n\t\t\n\t\t~BpUGraphExtender() {\n\t\t\tuedge_notifier.clear();\n\t\t\tedge_notifier.clear(); \n\t\t\tnode_notifier.clear(); \n\t\t\tanode_notifier.clear(); \n\t\t\tbnode_notifier.clear(); \n\t\t}\n\t\t\n\t\tEdge findEdge(Node u, Node v, Edge prev = INVALID) const {\n\t\t\tUEdge uedge = Parent::findUEdge(u, v, prev);\n\t\t\tif (uedge != INVALID) {\n\t\t\t\treturn Parent::direct(uedge, Parent::aNode(u));\n\t\t\t} else {\n\t\t\t\treturn INVALID;\n\t\t\t}\n\t\t}\n\t\t\n\t};\n\t\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/invalid.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_INVALID_H\n#define LEMON_BITS_INVALID_H\n\n///\\file\n///\\brief Definition of INVALID.\n\nnamespace lemon {\n\n  /// \\brief Dummy type to make it easier to make invalid iterators.\n  ///\n  /// See \\ref INVALID for the usage.\n  struct Invalid {\n  public:\n    bool operator==(Invalid) { return true;  }\n    bool operator!=(Invalid) { return false; }\n    bool operator< (Invalid) { return false; }\n  };\n  \n  /// Invalid iterators.\n  \n  /// \\ref Invalid is a global type that converts to each iterator\n  /// in such a way that the value of the target iterator will be invalid.\n\n  //Some people didn't like this:\n  //const Invalid &INVALID = *(Invalid *)0;\n\n#ifdef LEMON_ONLY_TEMPLATES\n  const Invalid INVALID = Invalid();\n#else\n  extern const Invalid INVALID;\n#endif\n\n} //namespace lemon\n\n#endif\n  \n"
  },
  {
    "path": "src/lemon/bits/map_extender.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_MAP_EXTENDER_H\n#define LEMON_BITS_MAP_EXTENDER_H\n\n#include <iterator>\n\n#include <lemon/bits/traits.h>\n\n#include <lemon/concept_check.h>\n#include <lemon/concepts/maps.h>\n\n///\\file\n///\\brief Extenders for iterable maps.\n\nnamespace lemon {\n\n  /// \\ingroup graphbits\n  /// \n  /// \\brief Extender for maps\n  template <typename _Map>\n  class MapExtender : public _Map {\n  public:\n\n    typedef _Map Parent;\n    typedef MapExtender Map;\n\n\n    typedef typename Parent::Graph Graph;\n    typedef typename Parent::Key Item;\n\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    class MapIt;\n    class ConstMapIt;\n\n    friend class MapIt;\n    friend class ConstMapIt;\n\n  public:\n\n    MapExtender(const Graph& graph) \n      : Parent(graph) {}\n\n    MapExtender(const Graph& graph, const Value& value) \n      : Parent(graph, value) {}\n\n    MapExtender& operator=(const MapExtender& cmap) {\n      return operator=<MapExtender>(cmap);\n    }\n\n    template <typename CMap>\n    MapExtender& operator=(const CMap& cmap) {\n      Parent::operator=(cmap);\n      return *this;\n    } \n\n    class MapIt : public Item {\n    public:\n      \n      typedef Item Parent;\n      typedef typename Map::Value Value;\n      \n      MapIt() {}\n\n      MapIt(Invalid i) : Parent(i) { }\n\n      explicit MapIt(Map& _map) : map(_map) {\n        map.notifier()->first(*this);\n      }\n\n      MapIt(const Map& _map, const Item& item) \n\t: Parent(item), map(_map) {}\n\n      MapIt& operator++() { \n\tmap.notifier()->next(*this);\n\treturn *this; \n      }\n      \n      typename MapTraits<Map>::ConstReturnValue operator*() const {\n\treturn map[*this];\n      }\n\n      typename MapTraits<Map>::ReturnValue operator*() {\n\treturn map[*this];\n      }\n      \n      void set(const Value& value) {\n\tmap.set(*this, value);\n      }\n      \n    protected:\n      Map& map;\n      \n    };\n\n    class ConstMapIt : public Item {\n    public:\n\n      typedef Item Parent;\n\n      typedef typename Map::Value Value;\n      \n      ConstMapIt() {}\n\n      ConstMapIt(Invalid i) : Parent(i) { }\n\n      explicit ConstMapIt(Map& _map) : map(_map) {\n        map.notifier()->first(*this);\n      }\n\n      ConstMapIt(const Map& _map, const Item& item) \n\t: Parent(item), map(_map) {}\n\n      ConstMapIt& operator++() { \n\tmap.notifier()->next(*this);\n\treturn *this; \n      }\n\n      typename MapTraits<Map>::ConstReturnValue operator*() const {\n\treturn map[*this];\n      }\n\n    protected:\n      const Map& map;\n    };\n\n    class ItemIt : public Item {\n    public:\n      \n      typedef Item Parent;\n      \n      ItemIt() {}\n\n      ItemIt(Invalid i) : Parent(i) { }\n\n      explicit ItemIt(Map& _map) : map(_map) {\n        map.notifier()->first(*this);\n      }\n\n      ItemIt(const Map& _map, const Item& item) \n\t: Parent(item), map(_map) {}\n\n      ItemIt& operator++() { \n\tmap.notifier()->next(*this);\n\treturn *this; \n      }\n\n    protected:\n      const Map& map;\n      \n    };\n  };\n\n  /// \\ingroup graphbits\n  /// \n  /// \\brief Extender for maps which use a subset of the items.\n  template <typename _Graph, typename _Map>\n  class SubMapExtender : public _Map {\n  public:\n\n    typedef _Map Parent;\n    typedef SubMapExtender Map;\n\n    typedef _Graph Graph;\n\n    typedef typename Parent::Key Item;\n\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    class MapIt;\n    class ConstMapIt;\n\n    friend class MapIt;\n    friend class ConstMapIt;\n\n  public:\n\n    SubMapExtender(const Graph& _graph) \n      : Parent(_graph), graph(_graph) {}\n\n    SubMapExtender(const Graph& _graph, const Value& _value) \n      : Parent(_graph, _value), graph(_graph) {}\n\n    SubMapExtender& operator=(const SubMapExtender& cmap) {\n      return operator=<MapExtender>(cmap);\n    }\n\n    template <typename CMap>\n    SubMapExtender& operator=(const CMap& cmap) {\n      checkConcept<concepts::ReadMap<Key, Value>, CMap>();\n      Item it;\n      for (graph.first(it); it != INVALID; graph.next(it)) {\n        Parent::set(it, cmap[it]);\n      }\n      return *this;\n    } \n\n    class MapIt : public Item {\n    public:\n      \n      typedef Item Parent;\n      typedef typename Map::Value Value;\n      \n      MapIt() {}\n\n      MapIt(Invalid i) : Parent(i) { }\n\n      explicit MapIt(Map& _map) : map(_map) {\n        map.graph.first(*this);\n      }\n\n      MapIt(const Map& _map, const Item& item) \n\t: Parent(item), map(_map) {}\n\n      MapIt& operator++() { \n\tmap.graph.next(*this);\n\treturn *this; \n      }\n      \n      typename MapTraits<Map>::ConstReturnValue operator*() const {\n\treturn map[*this];\n      }\n\n      typename MapTraits<Map>::ReturnValue operator*() {\n\treturn map[*this];\n      }\n      \n      void set(const Value& value) {\n\tmap.set(*this, value);\n      }\n      \n    protected:\n      Map& map;\n      \n    };\n\n    class ConstMapIt : public Item {\n    public:\n\n      typedef Item Parent;\n\n      typedef typename Map::Value Value;\n      \n      ConstMapIt() {}\n\n      ConstMapIt(Invalid i) : Parent(i) { }\n\n      explicit ConstMapIt(Map& _map) : map(_map) {\n        map.graph.first(*this);\n      }\n\n      ConstMapIt(const Map& _map, const Item& item) \n\t: Parent(item), map(_map) {}\n\n      ConstMapIt& operator++() { \n\tmap.graph.next(*this);\n\treturn *this; \n      }\n\n      typename MapTraits<Map>::ConstReturnValue operator*() const {\n\treturn map[*this];\n      }\n\n    protected:\n      const Map& map;\n    };\n\n    class ItemIt : public Item {\n    public:\n      \n      typedef Item Parent;\n      \n      ItemIt() {}\n\n      ItemIt(Invalid i) : Parent(i) { }\n\n      explicit ItemIt(Map& _map) : map(_map) {\n        map.graph.first(*this);\n      }\n\n      ItemIt(const Map& _map, const Item& item) \n\t: Parent(item), map(_map) {}\n\n      ItemIt& operator++() { \n\tmap.graph.next(*this);\n\treturn *this; \n      }\n\n    protected:\n      const Map& map;\n      \n    };\n    \n  private:\n\n    const Graph& graph;\n    \n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/path_dump.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_PRED_MAP_PATH_H\n#define LEMON_BITS_PRED_MAP_PATH_H\n\nnamespace lemon {\n\n  template <typename _Graph, typename _PredMap>\n  class PredMapPath {\n  public:\n    typedef True RevPathTag;\n\n    typedef _Graph Graph;\n    typedef typename Graph::Edge Edge;\n    typedef _PredMap PredMap;\n\n    PredMapPath(const Graph& _graph, const PredMap& _predMap,\n                typename Graph::Node _target)\n      : graph(_graph), predMap(_predMap), target(_target) {}\n\n    int length() const {\n      int len = 0;\n      typename Graph::Node node = target;\n      typename Graph::Edge edge;\n      while ((edge = predMap[node]) != INVALID) {\n        node = graph.source(edge);\n        ++len;\n      }\n      return len;\n    }\n\n    bool empty() const {\n      return predMap[target] != INVALID;\n    }\n\n    class RevEdgeIt {\n    public:\n      RevEdgeIt() {}\n      RevEdgeIt(Invalid) : path(0), current(INVALID) {}\n      RevEdgeIt(const PredMapPath& _path) \n        : path(&_path), current(_path.target) {\n        if (path->predMap[current] == INVALID) current = INVALID;\n      }\n\n      operator const typename Graph::Edge() const {\n        return path->predMap[current];\n      }\n\n      RevEdgeIt& operator++() {\n        current = path->graph.source(path->predMap[current]);\n        if (path->predMap[current] == INVALID) current = INVALID;\n        return *this;\n      }\n\n      bool operator==(const RevEdgeIt& e) const { \n        return current == e.current; \n      }\n\n      bool operator!=(const RevEdgeIt& e) const {\n        return current != e.current; \n      }\n\n      bool operator<(const RevEdgeIt& e) const { \n        return current < e.current; \n      }\n      \n    private:\n      const PredMapPath* path;\n      typename Graph::Node current;\n    };\n\n  private:\n    const Graph& graph;\n    const PredMap& predMap;\n    typename Graph::Node target;\n  };\n\n\n  template <typename _Graph, typename _PredMatrixMap>\n  class PredMatrixMapPath {\n  public:\n    typedef True RevPathTag;\n\n    typedef _Graph Graph;\n    typedef typename Graph::Edge Edge;\n    typedef _PredMatrixMap PredMatrixMap;\n\n    PredMatrixMapPath(const Graph& _graph, \n                      const PredMatrixMap& _predMatrixMap,\n                      typename Graph::Node _source, \n                      typename Graph::Node _target)\n      : graph(_graph), predMatrixMap(_predMatrixMap), \n        source(_source), target(_target) {}\n\n    int length() const {\n      int len = 0;\n      typename Graph::Node node = target;\n      typename Graph::Edge edge;\n      while ((edge = predMatrixMap(source, node)) != INVALID) {\n        node = graph.source(edge);\n        ++len;\n      }\n      return len;\n    }\n\n    bool empty() const {\n      return source != target;\n    }\n\n    class RevEdgeIt {\n    public:\n      RevEdgeIt() {}\n      RevEdgeIt(Invalid) : path(0), current(INVALID) {}\n      RevEdgeIt(const PredMatrixMapPath& _path) \n        : path(&_path), current(_path.target) {\n        if (path->predMatrixMap(path->source, current) == INVALID) \n          current = INVALID;\n      }\n\n      operator const typename Graph::Edge() const {\n        return path->predMatrixMap(path->source, current);\n      }\n\n      RevEdgeIt& operator++() {\n        current = \n          path->graph.source(path->predMatrixMap(path->source, current));\n        if (path->predMatrixMap(path->source, current) == INVALID) \n          current = INVALID;\n        return *this;\n      }\n\n      bool operator==(const RevEdgeIt& e) const { \n        return current == e.current; \n      }\n\n      bool operator!=(const RevEdgeIt& e) const {\n        return current != e.current; \n      }\n\n      bool operator<(const RevEdgeIt& e) const { \n        return current < e.current; \n      }\n      \n    private:\n      const PredMatrixMapPath* path;\n      typename Graph::Node current;\n    };\n\n  private:\n    const Graph& graph;\n    const PredMatrixMap& predMatrixMap;\n    typename Graph::Node source;\n    typename Graph::Node target;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/traits.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_TRAITS_H\n#define LEMON_BITS_TRAITS_H\n\n#include <lemon/bits/utility.h>\n\n///\\file\n///\\brief Traits for graphs and maps\n///\n\nnamespace lemon {\n  template <typename _Graph, typename _Item>\n  class ItemSetTraits {};\n  \n\n  template <typename Graph, typename Enable = void>\n  struct NodeNotifierIndicator {\n    typedef InvalidType Type;\n  };\n  template <typename Graph>\n  struct NodeNotifierIndicator<\n    Graph, \n    typename enable_if<typename Graph::NodeNotifier::Notifier, void>::type\n  > { \n    typedef typename Graph::NodeNotifier Type;\n  };\n\n  template <typename _Graph>\n  class ItemSetTraits<_Graph, typename _Graph::Node> {\n  public:\n    \n    typedef _Graph Graph;\n\n    typedef typename Graph::Node Item;\n    typedef typename Graph::NodeIt ItemIt;\n\n    typedef typename NodeNotifierIndicator<Graph>::Type ItemNotifier;\n\n    template <typename _Value>\n    class Map : public Graph::template NodeMap<_Value> {\n    public:\n      typedef typename Graph::template NodeMap<_Value> Parent; \n      typedef typename Graph::template NodeMap<_Value> Type; \n      typedef typename Parent::Value Value;\n\n      Map(const Graph& _graph) : Parent(_graph) {}\n      Map(const Graph& _graph, const Value& _value) \n\t: Parent(_graph, _value) {}\n\n     };\n\n  };\n\n  template <typename Graph, typename Enable = void>\n  struct EdgeNotifierIndicator {\n    typedef InvalidType Type;\n  };\n  template <typename Graph>\n  struct EdgeNotifierIndicator<\n    Graph, \n    typename enable_if<typename Graph::EdgeNotifier::Notifier, void>::type\n  > { \n    typedef typename Graph::EdgeNotifier Type;\n  };\n\n  template <typename _Graph>\n  class ItemSetTraits<_Graph, typename _Graph::Edge> {\n  public:\n    \n    typedef _Graph Graph;\n\n    typedef typename Graph::Edge Item;\n    typedef typename Graph::EdgeIt ItemIt;\n\n    typedef typename EdgeNotifierIndicator<Graph>::Type ItemNotifier;\n\n    template <typename _Value>\n    class Map : public Graph::template EdgeMap<_Value> {\n    public:\n      typedef typename Graph::template EdgeMap<_Value> Parent; \n      typedef typename Graph::template EdgeMap<_Value> Type; \n      typedef typename Parent::Value Value;\n\n      Map(const Graph& _graph) : Parent(_graph) {}\n      Map(const Graph& _graph, const Value& _value) \n\t: Parent(_graph, _value) {}\n    };\n\n  };\n\n  template <typename Graph, typename Enable = void>\n  struct UEdgeNotifierIndicator {\n    typedef InvalidType Type;\n  };\n  template <typename Graph>\n  struct UEdgeNotifierIndicator<\n    Graph, \n    typename enable_if<typename Graph::UEdgeNotifier::Notifier, void>::type\n  > { \n    typedef typename Graph::UEdgeNotifier Type;\n  };\n\n  template <typename _Graph>\n  class ItemSetTraits<_Graph, typename _Graph::UEdge> {\n  public:\n    \n    typedef _Graph Graph;\n\n    typedef typename Graph::UEdge Item;\n    typedef typename Graph::UEdgeIt ItemIt;\n\n    typedef typename UEdgeNotifierIndicator<Graph>::Type ItemNotifier;\n\n    template <typename _Value>\n    class Map : public Graph::template UEdgeMap<_Value> {\n    public:\n      typedef typename Graph::template UEdgeMap<_Value> Parent; \n      typedef typename Graph::template UEdgeMap<_Value> Type; \n      typedef typename Parent::Value Value;\n\n      Map(const Graph& _graph) : Parent(_graph) {}\n      Map(const Graph& _graph, const Value& _value) \n\t: Parent(_graph, _value) {}\n    };\n\n  };\n\n  template <typename Graph, typename Enable = void>\n  struct ANodeNotifierIndicator {\n    typedef InvalidType Type;\n  };\n  template <typename Graph>\n  struct ANodeNotifierIndicator<\n    Graph, \n    typename enable_if<typename Graph::ANodeNotifier::Notifier, void>::type\n  > { \n    typedef typename Graph::ANodeNotifier Type;\n  };\n\n  template <typename _Graph>\n  class ItemSetTraits<_Graph, typename _Graph::ANode> {\n  public:\n    \n    typedef _Graph Graph;\n\n    typedef typename Graph::ANode Item;\n    typedef typename Graph::ANodeIt ItemIt;\n\n    typedef typename ANodeNotifierIndicator<Graph>::Type ItemNotifier;\n\n    template <typename _Value>\n    class Map : public Graph::template ANodeMap<_Value> {\n    public:\n      typedef typename Graph::template ANodeMap<_Value> Parent; \n      typedef typename Graph::template ANodeMap<_Value> Type; \n      typedef typename Parent::Value Value;\n\n      Map(const Graph& _graph) : Parent(_graph) {}\n      Map(const Graph& _graph, const Value& _value) \n\t: Parent(_graph, _value) {}\n    };\n\n  };\n\n  template <typename Graph, typename Enable = void>\n  struct BNodeNotifierIndicator {\n    typedef InvalidType Type;\n  };\n  template <typename Graph>\n  struct BNodeNotifierIndicator<\n    Graph, \n    typename enable_if<typename Graph::BNodeNotifier::Notifier, void>::type\n  > { \n    typedef typename Graph::BNodeNotifier Type;\n  };\n\n  template <typename _Graph>\n  class ItemSetTraits<_Graph, typename _Graph::BNode> {\n  public:\n    \n    typedef _Graph Graph;\n\n    typedef typename Graph::BNode Item;\n    typedef typename Graph::BNodeIt ItemIt;\n\n    typedef typename BNodeNotifierIndicator<Graph>::Type ItemNotifier;\n\n    template <typename _Value>\n    class Map : public Graph::template BNodeMap<_Value> {\n    public:\n      typedef typename Graph::template BNodeMap<_Value> Parent; \n      typedef typename Graph::template BNodeMap<_Value> Type; \n      typedef typename Parent::Value Value;\n\n      Map(const Graph& _graph) : Parent(_graph) {}\n      Map(const Graph& _graph, const Value& _value) \n\t: Parent(_graph, _value) {}\n    };\n\n  };\n\n\n  template <typename Map, typename Enable = void>\n  struct MapTraits {\n    typedef False ReferenceMapTag;\n\n    typedef typename Map::Key Key;\n    typedef typename Map::Value Value;\n\n    typedef const Value ConstReturnValue;\n    typedef const Value ReturnValue;\n  };\n\n  template <typename Map>\n  struct MapTraits<\n    Map, typename enable_if<typename Map::ReferenceMapTag, void>::type > \n  {\n    typedef True ReferenceMapTag;\n    \n    typedef typename Map::Key Key;\n    typedef typename Map::Value Value;\n\n    typedef typename Map::ConstReference ConstReturnValue;\n    typedef typename Map::Reference ReturnValue;\n\n    typedef typename Map::ConstReference ConstReference; \n    typedef typename Map::Reference Reference;\n };\n\n  template <typename MatrixMap, typename Enable = void>\n  struct MatrixMapTraits {\n    typedef False ReferenceMapTag;\n\n    typedef typename MatrixMap::FirstKey FirstKey;\n    typedef typename MatrixMap::SecondKey SecondKey;\n    typedef typename MatrixMap::Value Value;\n\n    typedef const Value ConstReturnValue;\n    typedef const Value ReturnValue;\n  };\n\n  template <typename MatrixMap>\n  struct MatrixMapTraits<\n    MatrixMap, typename enable_if<typename MatrixMap::ReferenceMapTag, \n                                  void>::type > \n  {\n    typedef True ReferenceMapTag;\n    \n    typedef typename MatrixMap::FirstKey FirstKey;\n    typedef typename MatrixMap::SecondKey SecondKey;\n    typedef typename MatrixMap::Value Value;\n\n    typedef typename MatrixMap::ConstReference ConstReturnValue;\n    typedef typename MatrixMap::Reference ReturnValue;\n\n    typedef typename MatrixMap::ConstReference ConstReference; \n    typedef typename MatrixMap::Reference Reference;\n };\n\n  // Indicators for the tags\n\n  template <typename Graph, typename Enable = void>\n  struct NodeNumTagIndicator {\n    static const bool value = false;\n  };\n\n  template <typename Graph>\n  struct NodeNumTagIndicator<\n    Graph, \n    typename enable_if<typename Graph::NodeNumTag, void>::type\n  > {\n    static const bool value = true;\n  };\n\n  template <typename Graph, typename Enable = void>\n  struct EdgeNumTagIndicator {\n    static const bool value = false;\n  };\n\n  template <typename Graph>\n  struct EdgeNumTagIndicator<\n    Graph, \n    typename enable_if<typename Graph::EdgeNumTag, void>::type\n  > {\n    static const bool value = true;\n  };\n\n  template <typename Graph, typename Enable = void>\n  struct FindEdgeTagIndicator {\n    static const bool value = false;\n  };\n\n  template <typename Graph>\n  struct FindEdgeTagIndicator<\n    Graph, \n    typename enable_if<typename Graph::FindEdgeTag, void>::type\n  > {\n    static const bool value = true;\n  };\n\n  template <typename Graph, typename Enable = void>\n  struct UndirectedTagIndicator {\n    static const bool value = false;\n  };\n\n  template <typename Graph>\n  struct UndirectedTagIndicator<\n    Graph, \n    typename enable_if<typename Graph::UndirectedTag, void>::type\n  > {\n    static const bool value = true;\n  };\n\n  template <typename Graph, typename Enable = void>\n  struct BuildTagIndicator {\n    static const bool value = false;\n  };\n\n  template <typename Graph>\n  struct BuildTagIndicator<\n    Graph, \n    typename enable_if<typename Graph::BuildTag, void>::type\n  > {\n    static const bool value = true;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/utility.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n// This file contains a modified version of the enable_if library from BOOST.\n// See the appropriate copyright notice below.\n\n// Boost enable_if library\n\n// Copyright 2003  The Trustees of Indiana University.\n\n// Use, modification, and distribution is subject to the Boost Software\n// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\n// http://www.boost.org/LICENSE_1_0.txt)\n\n//    Authors: Jaakko Jrvi (jajarvi at osl.iu.edu)\n//             Jeremiah Willcock (jewillco at osl.iu.edu)\n//             Andrew Lumsdaine (lums at osl.iu.edu)\n\n\n#ifndef LEMON_BITS_UTILITY_H\n#define LEMON_BITS_UTILITY_H\n\n///\\file\n///\\brief Miscellaneous basic utilities\n///\n///\\todo Please rethink the organisation of the basic files like this.\n///E.g. this file might be merged with invalid.h.\n\n\nnamespace lemon\n{\n\n  /// Basic type for defining \"tags\". A \"YES\" condition for \\c enable_if.\n\n  /// Basic type for defining \"tags\". A \"YES\" condition for \\c enable_if.\n  ///\n  ///\\sa False\n  ///\n  /// \\todo This should go to a separate \"basic_types.h\" (or something)\n  /// file.\n  struct True {\n    ///\\e\n    static const bool value = true;\n  };\n\n  /// Basic type for defining \"tags\". A \"NO\" condition for \\c enable_if.\n\n  /// Basic type for defining \"tags\". A \"NO\" condition for \\c enable_if.\n  ///\n  ///\\sa True\n  struct False {\n    ///\\e\n    static const bool value = false;\n  };\n\n\n  struct InvalidType {\n  };\n\n  template <typename T>\n  struct Wrap {\n    const T &value;\n    Wrap(const T &t) : value(t) {}\n  };\n\n  /**************** dummy class to avoid ambiguity ****************/\n\n  template<int T> struct dummy { dummy(int) {} };\n\n  /**************** enable_if from BOOST ****************/\n  \n  template <typename Type, typename T = void>\n  struct exists {\n    typedef T type;\n  };\n\n \n  template <bool B, class T = void>\n  struct enable_if_c {\n    typedef T type;\n  };\n\n  template <class T>\n  struct enable_if_c<false, T> {};\n\n  template <class Cond, class T = void> \n  struct enable_if : public enable_if_c<Cond::value, T> {};\n\n  template <bool B, class T>\n  struct lazy_enable_if_c {\n    typedef typename T::type type;\n  };\n\n  template <class T>\n  struct lazy_enable_if_c<false, T> {};\n\n  template <class Cond, class T> \n  struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};\n\n\n  template <bool B, class T = void>\n  struct disable_if_c {\n    typedef T type;\n  };\n\n  template <class T>\n  struct disable_if_c<true, T> {};\n\n  template <class Cond, class T = void> \n  struct disable_if : public disable_if_c<Cond::value, T> {};\n\n  template <bool B, class T>\n  struct lazy_disable_if_c {\n    typedef typename T::type type;\n  };\n\n  template <class T>\n  struct lazy_disable_if_c<true, T> {};\n\n  template <class Cond, class T> \n  struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};\n\n} // namespace lemon\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/variant.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_VARIANT_H\n#define LEMON_BITS_VARIANT_H\n\n#include <lemon/error.h>\n\n/// \\file\n/// \\brief Variant types\n\nnamespace lemon {\n\n  namespace _variant_bits {\n  \n    template <int left, int right>\n    struct CTMax {\n      static const int value = left < right ? right : left;\n    };\n\n  }\n\n\n  /// \\brief Simple Variant type for two types\n  ///\n  /// Simple Variant type for two types. The Variant type is a type\n  /// safe union. The C++ has strong limitations for using unions, by\n  /// example we can not store type with non default constructor or\n  /// destructor in an union. This class always knowns the current\n  /// state of the variant and it cares for the proper construction\n  /// and destruction.\n  template <typename _First, typename _Second>\n  class BiVariant {\n  public:\n\n    /// \\brief The \\c First type.\n    typedef _First First;\n    /// \\brief The \\c Second type.\n    typedef _Second Second;\n\n    struct WrongStateError : public lemon::LogicError {\n    public:\n      virtual const char* what() const throw() {\n        return \"lemon::BiVariant::WrongStateError\";\n      }\n    };\n\n    /// \\brief Constructor\n    ///\n    /// This constructor initalizes to the default value of the \\c First\n    /// type.\n    BiVariant() {\n      flag = true;\n      new(reinterpret_cast<First*>(data)) First();\n    }\n\n    /// \\brief Constructor\n    ///\n    /// This constructor initalizes to the given value of the \\c First\n    /// type.\n    BiVariant(const First& f) {\n      flag = true;\n      new(reinterpret_cast<First*>(data)) First(f);\n    }\n\n    /// \\brief Constructor\n    ///\n    /// This constructor initalizes to the given value of the \\c\n    /// Second type.\n    BiVariant(const Second& s) {\n      flag = false;\n      new(reinterpret_cast<Second*>(data)) Second(s);\n    }\n\n    /// \\brief Copy constructor\n    ///\n    /// Copy constructor\n    BiVariant(const BiVariant& bivariant) {\n      flag = bivariant.flag;\n      if (flag) {\n        new(reinterpret_cast<First*>(data)) First(bivariant.first());      \n      } else {\n        new(reinterpret_cast<Second*>(data)) Second(bivariant.second());      \n      }\n    }\n\n    /// \\brief Destrcutor\n    ///\n    /// Destructor\n    ~BiVariant() {\n      destroy();\n    }\n\n    /// \\brief Set to the default value of the \\c First type.\n    ///\n    /// This function sets the variant to the default value of the \\c\n    /// First type.\n    BiVariant& setFirst() {\n      destroy();\n      flag = true;\n      new(reinterpret_cast<First*>(data)) First();   \n      return *this;\n    }\n\n    /// \\brief Set to the given value of the \\c First type.\n    ///\n    /// This function sets the variant to the given value of the \\c\n    /// First type.\n    BiVariant& setFirst(const First& f) {\n      destroy();\n      flag = true;\n      new(reinterpret_cast<First*>(data)) First(f);   \n      return *this;\n    }\n\n    /// \\brief Set to the default value of the \\c Second type.\n    ///\n    /// This function sets the variant to the default value of the \\c\n    /// Second type.\n    BiVariant& setSecond() {\n      destroy();\n      flag = false;\n      new(reinterpret_cast<Second*>(data)) Second();   \n      return *this;\n    }\n\n    /// \\brief Set to the given value of the \\c Second type.\n    ///\n    /// This function sets the variant to the given value of the \\c\n    /// Second type.\n    BiVariant& setSecond(const Second& s) {\n      destroy();\n      flag = false;\n      new(reinterpret_cast<Second*>(data)) Second(s);   \n      return *this;\n    }\n\n    /// \\brief Operator form of the \\c setFirst()\n    BiVariant& operator=(const First& f) {\n      return setFirst(f);\n    }\n\n    /// \\brief Operator form of the \\c setSecond()\n    BiVariant& operator=(const Second& s) {\n      return setSecond(s);\n    }\n\n    /// \\brief Assign operator\n    BiVariant& operator=(const BiVariant& bivariant) {\n      if (this == &bivariant) return *this;\n      destroy();\n      flag = bivariant.flag;\n      if (flag) {\n        new(reinterpret_cast<First*>(data)) First(bivariant.first());      \n      } else {\n        new(reinterpret_cast<Second*>(data)) Second(bivariant.second());      \n      }\n      return *this;\n    }\n\n    /// \\brief Reference to the value\n    ///\n    /// Reference to the value of the \\c First type.\n    /// \\pre The BiVariant should store value of \\c First type.\n    First& first() {\n      LEMON_ASSERT(flag, WrongStateError());\n      return *reinterpret_cast<First*>(data); \n    }\n\n    /// \\brief Const reference to the value\n    ///\n    /// Const reference to the value of the \\c First type.\n    /// \\pre The BiVariant should store value of \\c First type.\n    const First& first() const { \n      LEMON_ASSERT(flag, WrongStateError());\n      return *reinterpret_cast<const First*>(data); \n    }\n\n    /// \\brief Operator form of the \\c first()\n    operator First&() { return first(); }\n    /// \\brief Operator form of the const \\c first()\n    operator const First&() const { return first(); }\n\n    /// \\brief Reference to the value\n    ///\n    /// Reference to the value of the \\c Second type.\n    /// \\pre The BiVariant should store value of \\c Second type.\n    Second& second() { \n      LEMON_ASSERT(!flag, WrongStateError());\n      return *reinterpret_cast<Second*>(data); \n    }\n\n    /// \\brief Const reference to the value\n    ///\n    /// Const reference to the value of the \\c Second type.\n    /// \\pre The BiVariant should store value of \\c Second type.\n    const Second& second() const { \n      LEMON_ASSERT(!flag, WrongStateError());\n      return *reinterpret_cast<const Second*>(data); \n    }\n\n    /// \\brief Operator form of the \\c second()\n    operator Second&() { return second(); }\n    /// \\brief Operator form of the const \\c second()\n    operator const Second&() const { return second(); }\n\n    /// \\brief %True when the variant is in the first state\n    ///\n    /// %True when the variant stores value of the \\c First type.\n    bool firstState() const { return flag; }\n\n    /// \\brief %True when the variant is in the second state\n    ///\n    /// %True when the variant stores value of the \\c Second type.\n    bool secondState() const { return !flag; }\n\n  private:\n\n    void destroy() {\n      if (flag) {\n        reinterpret_cast<First*>(data)->~First();\n      } else {\n        reinterpret_cast<Second*>(data)->~Second();\n      }\n    }\n    \n    char data[_variant_bits::CTMax<sizeof(First), sizeof(Second)>::value];\n    bool flag;\n  };\n\n  namespace _variant_bits {\n    \n    template <int _idx, typename _TypeMap>\n    struct Memory {\n\n      typedef typename _TypeMap::template Map<_idx>::Type Current;\n\n      static void destroy(int index, char* place) {\n        if (index == _idx) {\n          reinterpret_cast<Current*>(place)->~Current();\n        } else {\n          Memory<_idx - 1, _TypeMap>::destroy(index, place);\n        }\n      }\n\n      static void copy(int index, char* to, const char* from) {\n        if (index == _idx) {\n          new (reinterpret_cast<Current*>(to))\n            Current(reinterpret_cast<const Current*>(from));\n        } else {\n          Memory<_idx - 1, _TypeMap>::copy(index, to, from);\n        }\n      }\n\n    };\n\n    template <typename _TypeMap>\n    struct Memory<-1, _TypeMap> {\n\n      static void destroy(int, char*) {\n        LEMON_ASSERT(false, \"Wrong Variant Index.\");\n      }\n\n      static void copy(int, char*, const char*) {\n        LEMON_ASSERT(false, \"Wrong Variant Index.\");\n      }\n    };\n\n    template <int _idx, typename _TypeMap>\n    struct Size {\n      static const int value = \n      CTMax<sizeof(typename _TypeMap::template Map<_idx>::Type), \n            Size<_idx - 1, _TypeMap>::value>::value;\n    };\n\n    template <typename _TypeMap>\n    struct Size<0, _TypeMap> {\n      static const int value = \n      sizeof(typename _TypeMap::template Map<0>::Type);\n    };\n\n  }\n\n  /// \\brief Variant type\n  ///\n  /// Simple Variant type. The Variant type is a type safe union. The\n  /// C++ has strong limitations for using unions, by example we\n  /// cannot store type with non default constructor or destructor in\n  /// a union. This class always knowns the current state of the\n  /// variant and it cares for the proper construction and\n  /// destruction.\n  ///\n  /// \\param _num The number of the types which can be stored in the\n  /// variant type.\n  /// \\param _TypeMap This class describes the types of the Variant. The\n  /// _TypeMap::Map<index>::Type should be a valid type for each index \n  /// in the range {0, 1, ..., _num - 1}. The \\c VariantTypeMap is helper\n  /// class to define such type mappings up to 10 types.\n  ///\n  /// And the usage of the class:\n  ///\\code\n  /// typedef Variant<3, VariantTypeMap<int, std::string, double> > MyVariant;\n  /// MyVariant var;\n  /// var.set<0>(12);\n  /// std::cout << var.get<0>() << std::endl;\n  /// var.set<1>(\"alpha\");\n  /// std::cout << var.get<1>() << std::endl;\n  /// var.set<2>(0.75);\n  /// std::cout << var.get<2>() << std::endl;\n  ///\\endcode\n  ///\n  /// The result of course:\n  ///\\code\n  /// 12\n  /// alpha\n  /// 0.75\n  ///\\endcode\n  template <int _num, typename _TypeMap>\n  class Variant {\n  public:\n\n    static const int num = _num;\n\n    typedef _TypeMap TypeMap;\n\n    struct WrongStateError : public lemon::LogicError {\n    public:\n      virtual const char* what() const throw() {\n        return \"lemon::Variant::WrongStateError\";\n      }\n    };\n\n    /// \\brief Constructor\n    ///\n    /// This constructor initalizes to the default value of the \\c type\n    /// with 0 index.\n    Variant() {\n      flag = 0;\n      new(reinterpret_cast<typename TypeMap::template Map<0>::Type*>(data)) \n        typename TypeMap::template Map<0>::Type();\n    }\n\n\n    /// \\brief Copy constructor\n    ///\n    /// Copy constructor\n    Variant(const Variant& variant) {\n      flag = variant.flag;\n      _variant_bits::Memory<num - 1, TypeMap>::copy(flag, data, variant.data);\n    }\n\n    /// \\brief Assign operator\n    ///\n    /// Assign operator\n    Variant& operator=(const Variant& variant) {\n      if (this == &variant) return *this;\n      _variant_bits::Memory<num - 1, TypeMap>::\n        destroy(flag, data);\n      flag = variant.flag;\n      _variant_bits::Memory<num - 1, TypeMap>::\n        copy(flag, data, variant.data);\n      return *this;\n    }\n\n    /// \\brief Destrcutor\n    ///\n    /// Destructor\n    ~Variant() {\n      _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);\n    }\n\n    /// \\brief Set to the default value of the type with \\c _idx index.\n    ///\n    /// This function sets the variant to the default value of the\n    /// type with \\c _idx index.\n    template <int _idx>\n    Variant& set() {\n      _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);\n      flag = _idx;\n      new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data)) \n        typename TypeMap::template Map<_idx>::Type();\n      return *this;\n    }\n\n    /// \\brief Set to the given value of the type with \\c _idx index.\n    ///\n    /// This function sets the variant to the given value of the type\n    /// with \\c _idx index.\n    template <int _idx>\n    Variant& set(const typename _TypeMap::template Map<_idx>::Type& init) {\n      _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);\n      flag = _idx;\n      new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data)) \n        typename TypeMap::template Map<_idx>::Type(init);\n      return *this;\n    }\n\n    /// \\brief Gets the current value of the type with \\c _idx index.\n    ///\n    /// Gets the current value of the type with \\c _idx index.\n    template <int _idx>\n    const typename TypeMap::template Map<_idx>::Type& get() const {\n      LEMON_ASSERT(_idx == flag, \"Wrong Variant Index.\");\n      return *reinterpret_cast<const typename TypeMap::\n        template Map<_idx>::Type*>(data); \n    }\n\n    /// \\brief Gets the current value of the type with \\c _idx index.\n    ///\n    /// Gets the current value of the type with \\c _idx index.\n    template <int _idx>\n    typename _TypeMap::template Map<_idx>::Type& get() {\n      LEMON_ASSERT(_idx == flag, \"Wrong Variant Index.\");\n      return *reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>\n        (data); \n    }\n\n    /// \\brief Returns the current state of the variant.\n    ///\n    /// Returns the current state of the variant.\n    int state() const {\n      return flag;\n    }\n\n  private:\n    \n    char data[_variant_bits::Size<num - 1, TypeMap>::value];\n    int flag;\n  };\n\n  namespace _variant_bits {\n\n    template <int _index, typename _List>\n    struct Get {\n      typedef typename Get<_index - 1, typename _List::Next>::Type Type;\n    };\n\n    template <typename _List>\n    struct Get<0, _List> {\n      typedef typename _List::Type Type;\n    };\n\n    struct List {};\n    \n    template <typename _Type, typename _List>\n    struct Insert {\n      typedef _List Next;\n      typedef _Type Type;\n    };\n\n    template <int _idx, typename _T0, typename _T1, typename _T2, \n              typename _T3, typename _T5, typename _T4, typename _T6,\n              typename _T7, typename _T8, typename _T9>\n    struct Mapper {\n      typedef List L10;\n      typedef Insert<_T9, L10> L9;\n      typedef Insert<_T8, L9> L8;\n      typedef Insert<_T7, L8> L7;\n      typedef Insert<_T6, L7> L6;\n      typedef Insert<_T5, L6> L5;\n      typedef Insert<_T4, L5> L4;\n      typedef Insert<_T3, L4> L3;\n      typedef Insert<_T2, L3> L2;\n      typedef Insert<_T1, L2> L1;\n      typedef Insert<_T0, L1> L0;\n      typedef typename Get<_idx, L0>::Type Type;\n    };\n    \n  }\n\n  /// \\brief Helper class for Variant\n  ///\n  /// Helper class to define type mappings for Variant. This class\n  /// converts the template parameters to be mappable by integer.\n  /// \\see Variant\n  template <\n    typename _T0, \n    typename _T1 = void, typename _T2 = void, typename _T3 = void,\n    typename _T5 = void, typename _T4 = void, typename _T6 = void,\n    typename _T7 = void, typename _T8 = void, typename _T9 = void>\n  struct VariantTypeMap {\n    template <int _idx>\n    struct Map {\n      typedef typename _variant_bits::\n      Mapper<_idx, _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, _T8, _T9>::Type\n      Type;\n    };\n  };\n  \n}\n\n\n#endif\n"
  },
  {
    "path": "src/lemon/bits/vector_map.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BITS_VECTOR_MAP_H\n#define LEMON_BITS_VECTOR_MAP_H\n\n#include <vector>\n#include <algorithm>\n\n#include <lemon/bits/traits.h>\n#include <lemon/bits/utility.h>\n\n#include <lemon/bits/alteration_notifier.h>\n\n#include <lemon/concept_check.h>\n#include <lemon/concepts/maps.h>\n\n///\\ingroup graphbits\n///\n///\\file\n///\\brief Vector based graph maps.\nnamespace lemon {\n\n  /// \\ingroup graphbits\n  ///\n  /// \\brief Graph map based on the std::vector storage.\n  ///\n  /// The VectorMap template class is graph map structure what\n  /// automatically updates the map when a key is added to or erased from\n  /// the map. This map type uses the std::vector to store the values.\n  ///\n  /// \\param Notifier The AlterationNotifier that will notify this map.\n  /// \\param Item The item type of the graph items.\n  /// \\param Value The value type of the map.\n  /// \n  /// \\author Balazs Dezso  \t\n  template <typename _Graph, typename _Item, typename _Value>\n  class VectorMap \n    : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {\n  private:\n\t\t\n    /// The container type of the map.\n    typedef std::vector<_Value> Container;\t\n\n  public:\n\n    /// The graph type of the map. \n    typedef _Graph Graph;\n    /// The item type of the map.\n    typedef _Item Item;\n    /// The reference map tag.\n    typedef True ReferenceMapTag;\n\n    /// The key type of the map.\n    typedef _Item Key;\n    /// The value type of the map.\n    typedef _Value Value;\n\n    /// The notifier type.\n    typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;\n\n    /// The map type.\n    typedef VectorMap Map;\n    /// The base class of the map.\n    typedef typename Notifier::ObserverBase Parent;\n\n    /// The reference type of the map;\n    typedef typename Container::reference Reference;\n    /// The const reference type of the map;\n    typedef typename Container::const_reference ConstReference;\n\n\n    /// \\brief Constructor to attach the new map into the notifier.\n    ///\n    /// It constructs a map and attachs it into the notifier.\n    /// It adds all the items of the graph to the map.\n    VectorMap(const Graph& graph) {\n      Parent::attach(graph.notifier(Item()));\n      container.resize(Parent::notifier()->maxId() + 1);\n    }\n\n    /// \\brief Constructor uses given value to initialize the map. \n    ///\n    /// It constructs a map uses a given value to initialize the map. \n    /// It adds all the items of the graph to the map.\n    VectorMap(const Graph& graph, const Value& value) {\n      Parent::attach(graph.notifier(Item()));\n      container.resize(Parent::notifier()->maxId() + 1, value);\n    }\n\n    /// \\brief Copy constructor\n    ///\n    /// Copy constructor.\n    VectorMap(const VectorMap& _copy) : Parent() {\n      if (_copy.attached()) {\n\tParent::attach(*_copy.notifier());\n\tcontainer = _copy.container;\n      }\n    }\n\n    /// \\brief Assign operator.\n    ///\n    /// This operator assigns for each item in the map the\n    /// value mapped to the same item in the copied map.  \n    /// The parameter map should be indiced with the same\n    /// itemset because this assign operator does not change\n    /// the container of the map. \n    VectorMap& operator=(const VectorMap& cmap) {\n      return operator=<VectorMap>(cmap);\n    }\n\n\n    /// \\brief Template assign operator.\n    ///\n    /// The given parameter should be conform to the ReadMap\n    /// concecpt and could be indiced by the current item set of\n    /// the NodeMap. In this case the value for each item\n    /// is assigned by the value of the given ReadMap. \n    template <typename CMap>\n    VectorMap& operator=(const CMap& cmap) {\n      checkConcept<concepts::ReadMap<Key, _Value>, CMap>();\n      const typename Parent::Notifier* nf = Parent::notifier();\n      Item it;\n      for (nf->first(it); it != INVALID; nf->next(it)) {\n        set(it, cmap[it]);\n      }\n      return *this;\n    }\n    \n  public:\n\n    /// \\brief The subcript operator.\n    ///\n    /// The subscript operator. The map can be subscripted by the\n    /// actual items of the graph.      \n    Reference operator[](const Key& key) {\n      return container[Parent::notifier()->id(key)];\n    } \n\t\t\n    /// \\brief The const subcript operator.\n    ///\n    /// The const subscript operator. The map can be subscripted by the\n    /// actual items of the graph. \n    ConstReference operator[](const Key& key) const {\n      return container[Parent::notifier()->id(key)];\n    }\n\n\n    /// \\brief The setter function of the map.\n    ///\n    /// It the same as operator[](key) = value expression.\n    void set(const Key& key, const Value& value) {\n      (*this)[key] = value;\n    }\n\n  protected:\n\n    /// \\brief Adds a new key to the map.\n    ///\t\t\n    /// It adds a new key to the map. It called by the observer notifier\n    /// and it overrides the add() member function of the observer base.     \n    virtual void add(const Key& key) {\n      int id = Parent::notifier()->id(key);\n      if (id >= int(container.size())) {\n\tcontainer.resize(id + 1);\n      }\n    }\n\n    /// \\brief Adds more new keys to the map.\n    ///\t\t\n    /// It adds more new keys to the map. It called by the observer notifier\n    /// and it overrides the add() member function of the observer base.     \n    virtual void add(const std::vector<Key>& keys) {\n      int max = container.size() - 1;\n      for (int i = 0; i < int(keys.size()); ++i) {\n        int id = Parent::notifier()->id(keys[i]);\n        if (id >= max) {\n          max = id;\n        }\n      }\n      container.resize(max + 1);\n    }\n\n    /// \\brief Erase a key from the map.\n    ///\n    /// Erase a key from the map. It called by the observer notifier\n    /// and it overrides the erase() member function of the observer base.     \n    virtual void erase(const Key& key) {\n      container[Parent::notifier()->id(key)] = Value();\n    }\n\n    /// \\brief Erase more keys from the map.\n    ///\n    /// Erase more keys from the map. It called by the observer notifier\n    /// and it overrides the erase() member function of the observer base.     \n    virtual void erase(const std::vector<Key>& keys) {\n      for (int i = 0; i < int(keys.size()); ++i) {\n\tcontainer[Parent::notifier()->id(keys[i])] = Value();\n      }\n    }\n    \n    /// \\brief Buildes the map.\n    ///\t\n    /// It buildes the map. It called by the observer notifier\n    /// and it overrides the build() member function of the observer base.\n    virtual void build() { \n      int size = Parent::notifier()->maxId() + 1;\n      container.reserve(size);\n      container.resize(size);\n    }\n\n    /// \\brief Clear the map.\n    ///\n    /// It erase all items from the map. It called by the observer notifier\n    /// and it overrides the clear() member function of the observer base.     \n    virtual void clear() { \n      container.clear();\n    }\n    \n  private:\n\t\t\n    Container container;\n\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/bucket_heap.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_BUCKET_HEAP_H\n#define LEMON_BUCKET_HEAP_H\n\n///\\ingroup auxdat\n///\\file\n///\\brief Bucket Heap implementation.\n\n#include <vector>\n#include <utility>\n#include <functional>\n\nnamespace lemon {\n\n  /// \\ingroup auxdat\n  ///\n  /// \\brief A Bucket Heap implementation.\n  ///\n  /// This class implements the \\e bucket \\e heap data structure. A \\e heap\n  /// is a data structure for storing items with specified values called \\e\n  /// priorities in such a way that finding the item with minimum priority is\n  /// efficient. The bucket heap is very simple implementation, it can store\n  /// only integer priorities and it stores for each priority in the \n  /// \\f$ [0..C) \\f$ range a list of items. So it should be used only when \n  /// the priorities are small. It is not intended to use as dijkstra heap.\n  ///\n  /// \\param _ItemIntMap A read and writable Item int map, used internally\n  /// to handle the cross references.\n  /// \\param minimize If the given parameter is true then the heap gives back\n  /// the lowest priority. \n  template <typename _ItemIntMap, bool minimize = true >\n  class BucketHeap {\n\n  public:\n    /// \\e\n    typedef typename _ItemIntMap::Key Item;\n    /// \\e\n    typedef int Prio;\n    /// \\e\n    typedef std::pair<Item, Prio> Pair;\n    /// \\e\n    typedef _ItemIntMap ItemIntMap;\n\n    /// \\brief Type to represent the items states.\n    ///\n    /// Each Item element have a state associated to it. It may be \"in heap\",\n    /// \"pre heap\" or \"post heap\". The latter two are indifferent from the\n    /// heap's point of view, but may be useful to the user.\n    ///\n    /// The ItemIntMap \\e should be initialized in such way that it maps\n    /// PRE_HEAP (-1) to any element to be put in the heap...\n    enum State {\n      IN_HEAP = 0,\n      PRE_HEAP = -1,\n      POST_HEAP = -2\n    };\n\n  public:\n    /// \\brief The constructor.\n    ///\n    /// The constructor.\n    /// \\param _index should be given to the constructor, since it is used\n    /// internally to handle the cross references. The value of the map\n    /// should be PRE_HEAP (-1) for each element.\n    explicit BucketHeap(ItemIntMap &_index) : index(_index), minimal(0) {}\n    \n    /// The number of items stored in the heap.\n    ///\n    /// \\brief Returns the number of items stored in the heap.\n    int size() const { return data.size(); }\n    \n    /// \\brief Checks if the heap stores no items.\n    ///\n    /// Returns \\c true if and only if the heap stores no items.\n    bool empty() const { return data.empty(); }\n\n    /// \\brief Make empty this heap.\n    /// \n    /// Make empty this heap. It does not change the cross reference\n    /// map.  If you want to reuse a heap what is not surely empty you\n    /// should first clear the heap and after that you should set the\n    /// cross reference map for each item to \\c PRE_HEAP.\n    void clear() { \n      data.clear(); first.clear(); minimal = 0;\n    }\n\n  private:\n\n    void relocate_last(int idx) {\n      if (idx + 1 < int(data.size())) {\n\tdata[idx] = data.back();\n\tif (data[idx].prev != -1) {\n\t  data[data[idx].prev].next = idx;\n\t} else {\n\t  first[data[idx].value] = idx;\n\t}\n\tif (data[idx].next != -1) {\n\t  data[data[idx].next].prev = idx;\n\t}\n\tindex[data[idx].item] = idx;\n      }\n      data.pop_back();\n    }\n\n    void unlace(int idx) {\n      if (data[idx].prev != -1) {\n\tdata[data[idx].prev].next = data[idx].next;\n      } else {\n\tfirst[data[idx].value] = data[idx].next;\n      }\n      if (data[idx].next != -1) {\n\tdata[data[idx].next].prev = data[idx].prev;\n      }\n    }\n\n    void lace(int idx) {\n      if (int(first.size()) <= data[idx].value) {\n\tfirst.resize(data[idx].value + 1, -1);\n      }\n      data[idx].next = first[data[idx].value];\n      if (data[idx].next != -1) {\n\tdata[data[idx].next].prev = idx;\n      }\n      first[data[idx].value] = idx;\n      data[idx].prev = -1;\n    }\n\n  public:\n    /// \\brief Insert a pair of item and priority into the heap.\n    ///\n    /// Adds \\c p.first to the heap with priority \\c p.second.\n    /// \\param p The pair to insert.\n    void push(const Pair& p) {\n      push(p.first, p.second);\n    }\n\n    /// \\brief Insert an item into the heap with the given priority.\n    ///    \n    /// Adds \\c i to the heap with priority \\c p. \n    /// \\param i The item to insert.\n    /// \\param p The priority of the item.\n    void push(const Item &i, const Prio &p) { \n      int idx = data.size();\n      index[i] = idx;\n      data.push_back(BucketItem(i, p));\n      lace(idx);\n      if (p < minimal) {\n\tminimal = p;\n      }\n    }\n\n    /// \\brief Returns the item with minimum priority.\n    ///\n    /// This method returns the item with minimum priority.\n    /// \\pre The heap must be nonempty.  \n    Item top() const {\n      while (first[minimal] == -1) {\n\t++minimal;\n      }\n      return data[first[minimal]].item;\n    }\n\n    /// \\brief Returns the minimum priority.\n    ///\n    /// It returns the minimum priority.\n    /// \\pre The heap must be nonempty.\n    Prio prio() const {\n      while (first[minimal] == -1) {\n\t++minimal;\n      }\n      return minimal;\n    }\n\n    /// \\brief Deletes the item with minimum priority.\n    ///\n    /// This method deletes the item with minimum priority from the heap.  \n    /// \\pre The heap must be non-empty.  \n    void pop() {\n      while (first[minimal] == -1) {\n\t++minimal;\n      }\n      int idx = first[minimal];\n      index[data[idx].item] = -2;\n      unlace(idx);\n      relocate_last(idx);\n    }\n\n    /// \\brief Deletes \\c i from the heap.\n    ///\n    /// This method deletes item \\c i from the heap, if \\c i was\n    /// already stored in the heap.\n    /// \\param i The item to erase. \n    void erase(const Item &i) {\n      int idx = index[i];\n      index[data[idx].item] = -2;\n      unlace(idx);\n      relocate_last(idx);\n    }\n\n    \n    /// \\brief Returns the priority of \\c i.\n    ///\n    /// This function returns the priority of item \\c i.  \n    /// \\pre \\c i must be in the heap.\n    /// \\param i The item.\n    Prio operator[](const Item &i) const {\n      int idx = index[i];\n      return data[idx].value;\n    }\n\n    /// \\brief \\c i gets to the heap with priority \\c p independently \n    /// if \\c i was already there.\n    ///\n    /// This method calls \\ref push(\\c i, \\c p) if \\c i is not stored\n    /// in the heap and sets the priority of \\c i to \\c p otherwise.\n    /// \\param i The item.\n    /// \\param p The priority.\n    void set(const Item &i, const Prio &p) {\n      int idx = index[i];\n      if (idx < 0) {\n\tpush(i,p);\n      } else if (p > data[idx].value) {\n\tincrease(i, p);\n      } else {\n\tdecrease(i, p);\n      }\n    }\n\n    /// \\brief Decreases the priority of \\c i to \\c p.\n    ///\n    /// This method decreases the priority of item \\c i to \\c p.\n    /// \\pre \\c i must be stored in the heap with priority at least \\c\n    /// p relative to \\c Compare.\n    /// \\param i The item.\n    /// \\param p The priority.\n    void decrease(const Item &i, const Prio &p) {\n      int idx = index[i];\n      unlace(idx);\n      data[idx].value = p;\n      if (p < minimal) {\n\tminimal = p;\n      }\n      lace(idx);\n    }\n    \n    /// \\brief Increases the priority of \\c i to \\c p.\n    ///\n    /// This method sets the priority of item \\c i to \\c p. \n    /// \\pre \\c i must be stored in the heap with priority at most \\c\n    /// p relative to \\c Compare.\n    /// \\param i The item.\n    /// \\param p The priority.\n    void increase(const Item &i, const Prio &p) {\n      int idx = index[i];\n      unlace(idx);\n      data[idx].value = p;\n      lace(idx);\n    }\n\n    /// \\brief Returns if \\c item is in, has already been in, or has \n    /// never been in the heap.\n    ///\n    /// This method returns PRE_HEAP if \\c item has never been in the\n    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP\n    /// otherwise. In the latter case it is possible that \\c item will\n    /// get back to the heap again.\n    /// \\param i The item.\n    State state(const Item &i) const {\n      int idx = index[i];\n      if (idx >= 0) idx = 0;\n      return State(idx);\n    }\n\n    /// \\brief Sets the state of the \\c item in the heap.\n    ///\n    /// Sets the state of the \\c item in the heap. It can be used to\n    /// manually clear the heap when it is important to achive the\n    /// better time complexity.\n    /// \\param i The item.\n    /// \\param st The state. It should not be \\c IN_HEAP. \n    void state(const Item& i, State st) {\n      switch (st) {\n      case POST_HEAP:\n      case PRE_HEAP:\n        if (state(i) == IN_HEAP) {\n          erase(i);\n        }\n        index[i] = st;\n        break;\n      case IN_HEAP:\n        break;\n      }\n    }\n\n  private:\n\n    struct BucketItem {\n      BucketItem(const Item& _item, int _value) \n\t: item(_item), value(_value) {}\n\n      Item item;\n      int value;\n\n      int prev, next;\n    };\n\n    ItemIntMap& index;\n    std::vector<int> first;\n    std::vector<BucketItem> data;\n    mutable int minimal;\n\n  }; // class BucketHeap\n\n\n  template <typename _ItemIntMap>\n  class BucketHeap<_ItemIntMap, false> {\n\n  public:\n    typedef typename _ItemIntMap::Key Item;\n    typedef int Prio;\n    typedef std::pair<Item, Prio> Pair;\n    typedef _ItemIntMap ItemIntMap;\n\n    enum State {\n      IN_HEAP = 0,\n      PRE_HEAP = -1,\n      POST_HEAP = -2\n    };\n\n  public:\n\n    explicit BucketHeap(ItemIntMap &_index) : index(_index), maximal(-1) {}\n\n    int size() const { return data.size(); }\n    bool empty() const { return data.empty(); }\n\n    void clear() { \n      data.clear(); first.clear(); maximal = -1; \n    }\n\n  private:\n\n    void relocate_last(int idx) {\n      if (idx + 1 != int(data.size())) {\n\tdata[idx] = data.back();\n\tif (data[idx].prev != -1) {\n\t  data[data[idx].prev].next = idx;\n\t} else {\n\t  first[data[idx].value] = idx;\n\t}\n\tif (data[idx].next != -1) {\n\t  data[data[idx].next].prev = idx;\n\t}\n\tindex[data[idx].item] = idx;\n      }\n      data.pop_back();\n    }\n\n    void unlace(int idx) {\n      if (data[idx].prev != -1) {\n\tdata[data[idx].prev].next = data[idx].next;\n      } else {\n\tfirst[data[idx].value] = data[idx].next;\n      }\n      if (data[idx].next != -1) {\n\tdata[data[idx].next].prev = data[idx].prev;\n      }\n    }\n\n    void lace(int idx) {\n      if (int(first.size()) <= data[idx].value) {\n\tfirst.resize(data[idx].value + 1, -1);\n      }\n      data[idx].next = first[data[idx].value];\n      if (data[idx].next != -1) {\n\tdata[data[idx].next].prev = idx;\n      }\n      first[data[idx].value] = idx;\n      data[idx].prev = -1;\n    }\n\n  public:\n\n    void push(const Pair& p) {\n      push(p.first, p.second);\n    }\n\n    void push(const Item &i, const Prio &p) { \n      int idx = data.size();\n      index[i] = idx;\n      data.push_back(BucketItem(i, p));\n      lace(idx);\n      if (data[idx].value > maximal) {\n\tmaximal = data[idx].value;\n      }\n    }\n\n    Item top() const {\n      while (first[maximal] == -1) {\n\t--maximal;\n      }\n      return data[first[maximal]].item;\n    }\n\n    Prio prio() const {\n      while (first[maximal] == -1) {\n\t--maximal;\n      }\n      return maximal;\n    }\n\n    void pop() {\n      while (first[maximal] == -1) {\n\t--maximal;\n      }\n      int idx = first[maximal];\n      index[data[idx].item] = -2;\n      unlace(idx);\n      relocate_last(idx);\n    }\n\n    void erase(const Item &i) {\n      int idx = index[i];\n      index[data[idx].item] = -2;\n      unlace(idx);\n      relocate_last(idx);\n    }\n\n    Prio operator[](const Item &i) const {\n      int idx = index[i];\n      return data[idx].value;\n    }\n\n    void set(const Item &i, const Prio &p) {\n      int idx = index[i];\n      if (idx < 0) {\n\tpush(i,p);\n      } else if (p > data[idx].value) {\n\tdecrease(i, p);\n      } else {\n\tincrease(i, p);\n      }\n    }\n\n    void decrease(const Item &i, const Prio &p) {\n      int idx = index[i];\n      unlace(idx);\n      data[idx].value = p;\n      if (p > maximal) {\n\tmaximal = p;\n      }\n      lace(idx);\n    }\n    \n    void increase(const Item &i, const Prio &p) {\n      int idx = index[i];\n      unlace(idx);\n      data[idx].value = p;\n      lace(idx);\n    }\n\n    State state(const Item &i) const {\n      int idx = index[i];\n      if (idx >= 0) idx = 0;\n      return State(idx);\n    }\n\n    void state(const Item& i, State st) {\n      switch (st) {\n      case POST_HEAP:\n      case PRE_HEAP:\n        if (state(i) == IN_HEAP) {\n          erase(i);\n        }\n        index[i] = st;\n        break;\n      case IN_HEAP:\n        break;\n      }\n    }\n\n  private:\n\n    struct BucketItem {\n      BucketItem(const Item& _item, int _value) \n\t: item(_item), value(_value) {}\n\n      Item item;\n      int value;\n\n      int prev, next;\n    };\n\n    ItemIntMap& index;\n    std::vector<int> first;\n    std::vector<BucketItem> data;\n    mutable int maximal;\n\n  }; // class BucketHeap\n\n  /// \\ingroup auxdat\n  ///\n  /// \\brief A Simplified Bucket Heap implementation.\n  ///\n  /// This class implements a simplified \\e bucket \\e heap data\n  /// structure.  It does not provide some functionality but it faster\n  /// and simplier data structure than the BucketHeap. The main\n  /// difference is that the BucketHeap stores for every key a double\n  /// linked list while this class stores just simple lists. In the\n  /// other way it does not supports erasing each elements just the\n  /// minimal and it does not supports key increasing, decreasing.\n  ///\n  /// \\param _ItemIntMap A read and writable Item int map, used internally\n  /// to handle the cross references.\n  /// \\param minimize If the given parameter is true then the heap gives back\n  /// the lowest priority.\n  ///\n  /// \\sa BucketHeap \n  template <typename _ItemIntMap, bool minimize = true >\n  class SimpleBucketHeap {\n\n  public:\n    typedef typename _ItemIntMap::Key Item;\n    typedef int Prio;\n    typedef std::pair<Item, Prio> Pair;\n    typedef _ItemIntMap ItemIntMap;\n\n    /// \\brief Type to represent the items states.\n    ///\n    /// Each Item element have a state associated to it. It may be \"in heap\",\n    /// \"pre heap\" or \"post heap\". The latter two are indifferent from the\n    /// heap's point of view, but may be useful to the user.\n    ///\n    /// The ItemIntMap \\e should be initialized in such way that it maps\n    /// PRE_HEAP (-1) to any element to be put in the heap...\n    enum State {\n      IN_HEAP = 0,\n      PRE_HEAP = -1,\n      POST_HEAP = -2\n    };\n\n  public:\n\n    /// \\brief The constructor.\n    ///\n    /// The constructor.\n    /// \\param _index should be given to the constructor, since it is used\n    /// internally to handle the cross references. The value of the map\n    /// should be PRE_HEAP (-1) for each element.\n    explicit SimpleBucketHeap(ItemIntMap &_index) \n      : index(_index), free(-1), num(0), minimal(0) {}\n    \n    /// \\brief Returns the number of items stored in the heap.\n    ///\n    /// The number of items stored in the heap.\n    int size() const { return num; }\n    \n    /// \\brief Checks if the heap stores no items.\n    ///\n    /// Returns \\c true if and only if the heap stores no items.\n    bool empty() const { return num == 0; }\n\n    /// \\brief Make empty this heap.\n    /// \n    /// Make empty this heap. It does not change the cross reference\n    /// map.  If you want to reuse a heap what is not surely empty you\n    /// should first clear the heap and after that you should set the\n    /// cross reference map for each item to \\c PRE_HEAP.\n    void clear() { \n      data.clear(); first.clear(); free = -1; num = 0; minimal = 0;\n    }\n\n    /// \\brief Insert a pair of item and priority into the heap.\n    ///\n    /// Adds \\c p.first to the heap with priority \\c p.second.\n    /// \\param p The pair to insert.\n    void push(const Pair& p) {\n      push(p.first, p.second);\n    }\n\n    /// \\brief Insert an item into the heap with the given priority.\n    ///    \n    /// Adds \\c i to the heap with priority \\c p. \n    /// \\param i The item to insert.\n    /// \\param p The priority of the item.\n    void push(const Item &i, const Prio &p) {\n      int idx;\n      if (free == -1) {\n        idx = data.size();\n        data.push_back(BucketItem(i));\n      } else {\n        idx = free;\n        free = data[idx].next;\n        data[idx].item = i;\n      }\n      index[i] = idx;\n      if (p >= int(first.size())) first.resize(p + 1, -1);\n      data[idx].next = first[p];\n      first[p] = idx;\n      if (p < minimal) {\n\tminimal = p;\n      }\n      ++num;\n    }\n\n    /// \\brief Returns the item with minimum priority.\n    ///\n    /// This method returns the item with minimum priority.\n    /// \\pre The heap must be nonempty.  \n    Item top() const {\n      while (first[minimal] == -1) {\n\t++minimal;\n      }\n      return data[first[minimal]].item;\n    }\n\n    /// \\brief Returns the minimum priority.\n    ///\n    /// It returns the minimum priority.\n    /// \\pre The heap must be nonempty.\n    Prio prio() const {\n      while (first[minimal] == -1) {\n\t++minimal;\n      }\n      return minimal;\n    }\n\n    /// \\brief Deletes the item with minimum priority.\n    ///\n    /// This method deletes the item with minimum priority from the heap.  \n    /// \\pre The heap must be non-empty.  \n    void pop() {\n      while (first[minimal] == -1) {\n\t++minimal;\n      }\n      int idx = first[minimal];\n      index[data[idx].item] = -2;\n      first[minimal] = data[idx].next;\n      data[idx].next = free;\n      free = idx;\n      --num;\n    }\n    \n    /// \\brief Returns the priority of \\c i.\n    ///\n    /// This function returns the priority of item \\c i.\n    /// \\warning This operator is not a constant time function\n    /// because it scans the whole data structure to find the proper\n    /// value.  \n    /// \\pre \\c i must be in the heap.\n    /// \\param i The item.\n    Prio operator[](const Item &i) const {\n      for (int k = 0; k < first.size(); ++k) {\n        int idx = first[k];\n        while (idx != -1) {\n          if (data[idx].item == i) {\n            return k;\n          }\n          idx = data[idx].next;\n        }\n      }\n      return -1;\n    }\n\n    /// \\brief Returns if \\c item is in, has already been in, or has \n    /// never been in the heap.\n    ///\n    /// This method returns PRE_HEAP if \\c item has never been in the\n    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP\n    /// otherwise. In the latter case it is possible that \\c item will\n    /// get back to the heap again.\n    /// \\param i The item.\n    State state(const Item &i) const {\n      int idx = index[i];\n      if (idx >= 0) idx = 0;\n      return State(idx);\n    }\n\n  private:\n\n    struct BucketItem {\n      BucketItem(const Item& _item) \n\t: item(_item) {}\n\n      Item item;\n      int next;\n    };\n\n    ItemIntMap& index;\n    std::vector<int> first;\n    std::vector<BucketItem> data;\n    int free, num;\n    mutable int minimal;\n\n  }; // class SimpleBucketHeap\n\n  template <typename _ItemIntMap>\n  class SimpleBucketHeap<_ItemIntMap, false> {\n\n  public:\n    typedef typename _ItemIntMap::Key Item;\n    typedef int Prio;\n    typedef std::pair<Item, Prio> Pair;\n    typedef _ItemIntMap ItemIntMap;\n\n    enum State {\n      IN_HEAP = 0,\n      PRE_HEAP = -1,\n      POST_HEAP = -2\n    };\n\n  public:\n\n    explicit SimpleBucketHeap(ItemIntMap &_index) \n      : index(_index), free(-1), num(0), maximal(0) {}\n    \n    int size() const { return num; }\n    \n    bool empty() const { return num == 0; }\n\n    void clear() { \n      data.clear(); first.clear(); free = -1; num = 0; maximal = 0;\n    }\n\n    void push(const Pair& p) {\n      push(p.first, p.second);\n    }\n\n    void push(const Item &i, const Prio &p) {\n      int idx;\n      if (free == -1) {\n        idx = data.size();\n        data.push_back(BucketItem(i));\n      } else {\n        idx = free;\n        free = data[idx].next;\n        data[idx].item = i;\n      }\n      index[i] = idx;\n      if (p >= int(first.size())) first.resize(p + 1, -1);\n      data[idx].next = first[p];\n      first[p] = idx;\n      if (p > maximal) {\n\tmaximal = p;\n      }\n      ++num;\n    }\n\n    Item top() const {\n      while (first[maximal] == -1) {\n\t--maximal;\n      }\n      return data[first[maximal]].item;\n    }\n\n    Prio prio() const {\n      while (first[maximal] == -1) {\n\t--maximal;\n      }\n      return maximal;\n    }\n\n    void pop() {\n      while (first[maximal] == -1) {\n\t--maximal;\n      }\n      int idx = first[maximal];\n      index[data[idx].item] = -2;\n      first[maximal] = data[idx].next;\n      data[idx].next = free;\n      free = idx;\n      --num;\n    }\n    \n    Prio operator[](const Item &i) const {\n      for (int k = 0; k < first.size(); ++k) {\n        int idx = first[k];\n        while (idx != -1) {\n          if (data[idx].item == i) {\n            return k;\n          }\n          idx = data[idx].next;\n        }\n      }\n      return -1;\n    }\n\n    State state(const Item &i) const {\n      int idx = index[i];\n      if (idx >= 0) idx = 0;\n      return State(idx);\n    }\n\n  private:\n\n    struct BucketItem {\n      BucketItem(const Item& _item) : item(_item) {}\n\n      Item item;\n\n      int next;\n    };\n\n    ItemIntMap& index;\n    std::vector<int> first;\n    std::vector<BucketItem> data;\n    int free, num;\n    mutable int maximal;\n\n  };\n\n}\n  \n#endif\n"
  },
  {
    "path": "src/lemon/concept_check.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n// Modified for use in LEMON.\n// We should really consider using Boost...\n\n//\n// (C) Copyright Jeremy Siek 2000.\n// Distributed under the Boost Software License, Version 1.0. (See\n// accompanying file LICENSE_1_0.txt or copy at\n// http://www.boost.org/LICENSE_1_0.txt)\n//\n// Revision History:\n//   05 May   2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek)\n//   02 April 2001: Removed limits header altogether. (Jeremy Siek)\n//   01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock)\n//\n\n// See http://www.boost.org/libs/concept_check for documentation.\n\n#ifndef LEMON_BOOST_CONCEPT_CHECKS_HPP\n#define LEMON_BOOST_CONCEPT_CHECKS_HPP\n\nnamespace lemon {\n\n  /*\n    \"inline\" is used for ignore_unused_variable_warning()\n    and function_requires() to make sure there is no\n    overtarget with g++.\n  */\n\n  template <class T> inline void ignore_unused_variable_warning(const T&) { }\n\n  template <class Concept>\n  inline void function_requires()\n  {\n#if !defined(NDEBUG)\n    void (Concept::*x)() = & Concept::constraints;\n    ignore_unused_variable_warning(x);\n#endif\n  }\n\n  template <typename Concept, typename Type>\n  inline void checkConcept() {\n#if !defined(NDEBUG)\n    typedef typename Concept::template Constraints<Type> ConceptCheck;\n    void (ConceptCheck::*x)() = & ConceptCheck::constraints;\n    ignore_unused_variable_warning(x);\n#endif\n  }\n#if 0\n#define BOOST_CLASS_REQUIRE(type_var, ns, concept) \\\n  typedef void (ns::concept <type_var>::* func##type_var##concept)(); \\\n  template <func##type_var##concept Tp1_> \\\n  struct concept_checking_##type_var##concept { }; \\\n  typedef concept_checking_##type_var##concept< \\\n    BOOST_FPTR ns::concept<type_var>::constraints> \\\n    concept_checking_typedef_##type_var##concept\n\n#define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \\\n  typedef void (ns::concept <type_var1,type_var2>::* \\\n     func##type_var1##type_var2##concept)(); \\\n  template <func##type_var1##type_var2##concept Tp1_> \\\n  struct concept_checking_##type_var1##type_var2##concept { }; \\\n  typedef concept_checking_##type_var1##type_var2##concept< \\\n    BOOST_FPTR ns::concept<type_var1,type_var2>::constraints> \\\n    concept_checking_typedef_##type_var1##type_var2##concept\n\n#define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \\\n  typedef void (ns::concept <tv1,tv2,tv3>::* \\\n     func##tv1##tv2##tv3##concept)(); \\\n  template <func##tv1##tv2##tv3##concept Tp1_> \\\n  struct concept_checking_##tv1##tv2##tv3##concept { }; \\\n  typedef concept_checking_##tv1##tv2##tv3##concept< \\\n    BOOST_FPTR ns::concept<tv1,tv2,tv3>::constraints> \\\n    concept_checking_typedef_##tv1##tv2##tv3##concept\n\n#define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \\\n  typedef void (ns::concept <tv1,tv2,tv3,tv4>::* \\\n     func##tv1##tv2##tv3##tv4##concept)(); \\\n  template <func##tv1##tv2##tv3##tv4##concept Tp1_> \\\n  struct concept_checking_##tv1##tv2##tv3##tv4##concept { }; \\\n  typedef concept_checking_##tv1##tv2##tv3##tv4##concept< \\\n    BOOST_FPTR ns::concept<tv1,tv2,tv3,tv4>::constraints> \\\n    concept_checking_typedef_##tv1##tv2##tv3##tv4##concept\n#endif\n\n} // namespace lemon\n\n#endif // LEMON_BOOST_CONCEPT_CHECKS_HPP\n"
  },
  {
    "path": "src/lemon/concepts/bpugraph.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n/// \\ingroup graph_concepts\n/// \\file\n/// \\brief The concept of Bipartite Undirected Graphs.\n\n#ifndef LEMON_CONCEPT_BPUGRAPH_H\n#define LEMON_CONCEPT_BPUGRAPH_H\n\n#include <lemon/concepts/graph_components.h>\n\n#include <lemon/concepts/graph.h>\n#include <lemon/concepts/ugraph.h>\n\n#include <lemon/bits/utility.h>\n\nnamespace lemon {\n  namespace concepts {\n\n    /// \\ingroup graph_concepts\n    ///\n    /// \\brief Class describing the concept of Bipartite Undirected Graphs.\n    ///\n    /// This class describes the common interface of all \n    /// Undirected Bipartite Graphs.\n    ///\n    /// As all concept describing classes it provides only interface\n    /// without any sensible implementation. So any algorithm for\n    /// bipartite undirected graph should compile with this class, but it \n    /// will not run properly, of course.\n    ///\n    /// In LEMON bipartite undirected graphs also fulfill the concept of \n    /// the undirected graphs (\\ref lemon::concepts::UGraph \"UGraph Concept\"). \n    ///\n    /// You can assume that all undirected bipartite graph can be handled\n    /// as an undirected graph and consequently as a static graph.\n    ///\n    /// The bipartite graph stores two types of nodes which are named\n    /// ANode and BNode. The graph type contains two types ANode and\n    /// BNode which are inherited from Node type. Moreover they have\n    /// constructor which converts Node to either ANode or BNode when\n    /// it is possible. Therefor everywhere the Node type can be used\n    /// instead of ANode and BNode. So the usage of the ANode and\n    /// BNode is not suggested.\n    ///\n    /// The iteration on the partition can be done with the ANodeIt and \n    /// BNodeIt classes. The node map can be used to map values to the nodes\n    /// and similarly we can use to map values for just the ANodes and\n    /// BNodes the ANodeMap and BNodeMap template classes.\n\n    class BpUGraph {\n    public:\n      /// \\brief The undirected graph should be tagged by the\n      /// UndirectedTag.\n      ///\n      /// The undirected graph should be tagged by the UndirectedTag. This\n      /// tag helps the enable_if technics to make compile time \n      /// specializations for undirected graphs.  \n      typedef True UndirectedTag;\n\n      /// \\brief The base type of node iterators, \n      /// or in other words, the trivial node iterator.\n      ///\n      /// This is the base type of each node iterator,\n      /// thus each kind of node iterator converts to this.\n      /// More precisely each kind of node iterator should be inherited \n      /// from the trivial node iterator. The Node class represents\n      /// both of two types of nodes. \n      class Node {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        Node() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        Node(const Node&) { }\n\n        /// Invalid constructor \\& conversion.\n\n        /// This constructor initializes the iterator to be invalid.\n        /// \\sa Invalid for more details.\n        Node(Invalid) { }\n        /// Equality operator\n\n        /// Two iterators are equal if and only if they point to the\n        /// same object or both are invalid.\n        bool operator==(Node) const { return true; }\n\n        /// Inequality operator\n        \n        /// \\sa operator==(Node n)\n        ///\n        bool operator!=(Node) const { return true; }\n\n\t/// Artificial ordering operator.\n\t\n\t/// To allow the use of graph descriptors as key type in std::map or\n\t/// similar associative container we require this.\n\t///\n\t/// \\note This operator only have to define some strict ordering of\n\t/// the items; this order has nothing to do with the iteration\n\t/// ordering of the items.\n\tbool operator<(Node) const { return false; }\n\n      };\n\n      /// \\brief Helper class for ANodes.\n      ///\n      /// This class is just a helper class for ANodes, it is not\n      /// suggested to use it directly. It can be converted easily to\n      /// node and vice versa. The usage of this class is limited\n      /// to use just as template parameters for special map types. \n      class ANode : public Node {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        ANode() : Node() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        ANode(const ANode&) : Node() { }\n\n        /// Construct the same node as ANode.\n\n        /// Construct the same node as ANode. It may throws assertion\n        /// when the given node is from the BNode set.\n        ANode(const Node&) : Node() { }\n\n        /// Assign node to A-node.\n\n        /// Besides the core graph item functionality each node should\n        /// be convertible to the represented A-node if it is it possible. \n        ANode& operator=(const Node&) { return *this; }\n\n        /// Invalid constructor \\& conversion.\n\n        /// This constructor initializes the iterator to be invalid.\n        /// \\sa Invalid for more details.\n        ANode(Invalid) { }\n        /// Equality operator\n\n        /// Two iterators are equal if and only if they point to the\n        /// same object or both are invalid.\n        bool operator==(ANode) const { return true; }\n\n        /// Inequality operator\n        \n        /// \\sa operator==(ANode n)\n        ///\n        bool operator!=(ANode) const { return true; }\n\n\t/// Artificial ordering operator.\n\t\n\t/// To allow the use of graph descriptors as key type in std::map or\n\t/// similar associative container we require this.\n\t///\n\t/// \\note This operator only have to define some strict ordering of\n\t/// the items; this order has nothing to do with the iteration\n\t/// ordering of the items.\n\tbool operator<(ANode) const { return false; }\n\n      };\n\n      /// \\brief Helper class for BNodes.\n      ///\n      /// This class is just a helper class for BNodes, it is not\n      /// suggested to use it directly. It can be converted easily to\n      /// node and vice versa. The usage of this class is limited\n      /// to use just as template parameters for special map types. \n      class BNode : public Node {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        BNode() : Node() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        BNode(const BNode&) : Node() { }\n\n        /// Construct the same node as BNode.\n\n        /// Construct the same node as BNode. It may throws assertion\n        /// when the given node is from the ANode set.\n        BNode(const Node&) : Node() { }\n\n        /// Assign node to B-node.\n\n        /// Besides the core graph item functionality each node should\n        /// be convertible to the represented B-node if it is it possible. \n        BNode& operator=(const Node&) { return *this; }\n\n        /// Invalid constructor \\& conversion.\n\n        /// This constructor initializes the iterator to be invalid.\n        /// \\sa Invalid for more details.\n        BNode(Invalid) { }\n        /// Equality operator\n\n        /// Two iterators are equal if and only if they point to the\n        /// same object or both are invalid.\n        bool operator==(BNode) const { return true; }\n\n        /// Inequality operator\n        \n        /// \\sa operator==(BNode n)\n        ///\n        bool operator!=(BNode) const { return true; }\n\n\t/// Artificial ordering operator.\n\t\n\t/// To allow the use of graph descriptors as key type in std::map or\n\t/// similar associative container we require this.\n\t///\n\t/// \\note This operator only have to define some strict ordering of\n\t/// the items; this order has nothing to do with the iteration\n\t/// ordering of the items.\n\tbool operator<(BNode) const { return false; }\n\n      };\n    \n      /// This iterator goes through each node.\n\n      /// This iterator goes through each node.\n      /// Its usage is quite simple, for example you can count the number\n      /// of nodes in graph \\c g of type \\c Graph like this:\n      ///\\code\n      /// int count=0;\n      /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count;\n      ///\\endcode\n      class NodeIt : public Node {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        NodeIt() { }\n        /// Copy constructor.\n        \n        /// Copy constructor.\n        ///\n        NodeIt(const NodeIt& n) : Node(n) { }\n        /// Invalid constructor \\& conversion.\n\n        /// Initialize the iterator to be invalid.\n        /// \\sa Invalid for more details.\n        NodeIt(Invalid) { }\n        /// Sets the iterator to the first node.\n\n        /// Sets the iterator to the first node of \\c g.\n        ///\n        NodeIt(const BpUGraph&) { }\n        /// Node -> NodeIt conversion.\n\n        /// Sets the iterator to the node of \\c the graph pointed by \n\t/// the trivial iterator.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        NodeIt(const BpUGraph&, const Node&) { }\n        /// Next node.\n\n        /// Assign the iterator to the next node.\n        ///\n        NodeIt& operator++() { return *this; }\n      };\n\n      /// This iterator goes through each ANode.\n\n      /// This iterator goes through each ANode.\n      /// Its usage is quite simple, for example you can count the number\n      /// of nodes in graph \\c g of type \\c Graph like this:\n      ///\\code\n      /// int count=0;\n      /// for (Graph::ANodeIt n(g); n!=INVALID; ++n) ++count;\n      ///\\endcode\n      class ANodeIt : public Node {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        ANodeIt() { }\n        /// Copy constructor.\n        \n        /// Copy constructor.\n        ///\n        ANodeIt(const ANodeIt& n) : Node(n) { }\n        /// Invalid constructor \\& conversion.\n\n        /// Initialize the iterator to be invalid.\n        /// \\sa Invalid for more details.\n        ANodeIt(Invalid) { }\n        /// Sets the iterator to the first node.\n\n        /// Sets the iterator to the first node of \\c g.\n        ///\n        ANodeIt(const BpUGraph&) { }\n        /// Node -> ANodeIt conversion.\n\n        /// Sets the iterator to the node of \\c the graph pointed by \n\t/// the trivial iterator.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        ANodeIt(const BpUGraph&, const Node&) { }\n        /// Next node.\n\n        /// Assign the iterator to the next node.\n        ///\n        ANodeIt& operator++() { return *this; }\n      };\n\n      /// This iterator goes through each BNode.\n\n      /// This iterator goes through each BNode.\n      /// Its usage is quite simple, for example you can count the number\n      /// of nodes in graph \\c g of type \\c Graph like this:\n      ///\\code\n      /// int count=0;\n      /// for (Graph::BNodeIt n(g); n!=INVALID; ++n) ++count;\n      ///\\endcode\n      class BNodeIt : public Node {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        BNodeIt() { }\n        /// Copy constructor.\n        \n        /// Copy constructor.\n        ///\n        BNodeIt(const BNodeIt& n) : Node(n) { }\n        /// Invalid constructor \\& conversion.\n\n        /// Initialize the iterator to be invalid.\n        /// \\sa Invalid for more details.\n        BNodeIt(Invalid) { }\n        /// Sets the iterator to the first node.\n\n        /// Sets the iterator to the first node of \\c g.\n        ///\n        BNodeIt(const BpUGraph&) { }\n        /// Node -> BNodeIt conversion.\n\n        /// Sets the iterator to the node of \\c the graph pointed by \n\t/// the trivial iterator.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        BNodeIt(const BpUGraph&, const Node&) { }\n        /// Next node.\n\n        /// Assign the iterator to the next node.\n        ///\n        BNodeIt& operator++() { return *this; }\n      };\n    \n    \n      /// The base type of the undirected edge iterators.\n\n      /// The base type of the undirected edge iterators.\n      ///\n      class UEdge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        UEdge() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        UEdge(const UEdge&) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        UEdge(Invalid) { }\n        /// Equality operator\n\n        /// Two iterators are equal if and only if they point to the\n        /// same object or both are invalid.\n        bool operator==(UEdge) const { return true; }\n        /// Inequality operator\n\n        /// \\sa operator==(UEdge n)\n        ///\n        bool operator!=(UEdge) const { return true; }\n\n\t/// Artificial ordering operator.\n\t\n\t/// To allow the use of graph descriptors as key type in std::map or\n\t/// similar associative container we require this.\n\t///\n\t/// \\note This operator only have to define some strict ordering of\n\t/// the items; this order has nothing to do with the iteration\n\t/// ordering of the items.\n\tbool operator<(UEdge) const { return false; }\n      };\n\n      /// This iterator goes through each undirected edge.\n\n      /// This iterator goes through each undirected edge of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of undirected edges in a graph \\c g of type \\c Graph as follows:\n      ///\\code\n      /// int count=0;\n      /// for(Graph::UEdgeIt e(g); e!=INVALID; ++e) ++count;\n      ///\\endcode\n      class UEdgeIt : public UEdge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        UEdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        UEdgeIt(const UEdgeIt& e) : UEdge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        UEdgeIt(Invalid) { }\n        /// This constructor sets the iterator to the first undirected edge.\n    \n        /// This constructor sets the iterator to the first undirected edge.\n        UEdgeIt(const BpUGraph&) { }\n        /// UEdge -> UEdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator.\n        /// This feature necessitates that each time we\n        /// iterate the undirected edge-set, the iteration order is the \n\t/// same.\n        UEdgeIt(const BpUGraph&, const UEdge&) { } \n        /// Next undirected edge\n        \n        /// Assign the iterator to the next undirected edge.\n        UEdgeIt& operator++() { return *this; }\n      };\n\n      /// \\brief This iterator goes trough the incident undirected \n      /// edges of a node.\n      ///\n      /// This iterator goes trough the incident undirected edges\n      /// of a certain node\n      /// of a graph.\n      /// Its usage is quite simple, for example you can compute the\n      /// degree (i.e. count the number\n      /// of incident edges of a node \\c n\n      /// in graph \\c g of type \\c Graph as follows.\n      ///\\code\n      /// int count=0;\n      /// for(Graph::IncEdgeIt e(g, n); e!=INVALID; ++e) ++count;\n      ///\\endcode\n      class IncEdgeIt : public UEdge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        IncEdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        IncEdgeIt(const IncEdgeIt& e) : UEdge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        IncEdgeIt(Invalid) { }\n        /// This constructor sets the iterator to first incident edge.\n    \n        /// This constructor set the iterator to the first incident edge of\n        /// the node.\n        IncEdgeIt(const BpUGraph&, const Node&) { }\n        /// UEdge -> IncEdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator \\c e.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        IncEdgeIt(const BpUGraph&, const UEdge&) { }\n        /// Next incident edge\n\n        /// Assign the iterator to the next incident edge\n\t/// of the corresponding node.\n        IncEdgeIt& operator++() { return *this; }\n      };\n\n      /// The directed edge type.\n\n      /// The directed edge type. It can be converted to the\n      /// undirected edge.\n      class Edge : public UEdge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        Edge() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        Edge(const Edge& e) : UEdge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        Edge(Invalid) { }\n        /// Equality operator\n\n        /// Two iterators are equal if and only if they point to the\n        /// same object or both are invalid.\n        bool operator==(Edge) const { return true; }\n        /// Inequality operator\n\n        /// \\sa operator==(Edge n)\n        ///\n        bool operator!=(Edge) const { return true; }\n\n\t/// Artificial ordering operator.\n\t\n\t/// To allow the use of graph descriptors as key type in std::map or\n\t/// similar associative container we require this.\n\t///\n\t/// \\note This operator only have to define some strict ordering of\n\t/// the items; this order has nothing to do with the iteration\n\t/// ordering of the items.\n\tbool operator<(Edge) const { return false; }\n\t\n      }; \n      /// This iterator goes through each directed edge.\n\n      /// This iterator goes through each edge of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of edges in a graph \\c g of type \\c Graph as follows:\n      ///\\code\n      /// int count=0;\n      /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count;\n      ///\\endcode\n      class EdgeIt : public Edge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        EdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        EdgeIt(const EdgeIt& e) : Edge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        EdgeIt(Invalid) { }\n        /// This constructor sets the iterator to the first edge.\n    \n        /// This constructor sets the iterator to the first edge of \\c g.\n        ///@param g the graph\n        EdgeIt(const BpUGraph &g) { ignore_unused_variable_warning(g); }\n        /// Edge -> EdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator \\c e.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        EdgeIt(const BpUGraph&, const Edge&) { } \n        ///Next edge\n        \n        /// Assign the iterator to the next edge.\n        EdgeIt& operator++() { return *this; }\n      };\n   \n      /// This iterator goes trough the outgoing directed edges of a node.\n\n      /// This iterator goes trough the \\e outgoing edges of a certain node\n      /// of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of outgoing edges of a node \\c n\n      /// in graph \\c g of type \\c Graph as follows.\n      ///\\code\n      /// int count=0;\n      /// for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) ++count;\n      ///\\endcode\n    \n      class OutEdgeIt : public Edge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        OutEdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        OutEdgeIt(const OutEdgeIt& e) : Edge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        OutEdgeIt(Invalid) { }\n        /// This constructor sets the iterator to the first outgoing edge.\n    \n        /// This constructor sets the iterator to the first outgoing edge of\n        /// the node.\n        ///@param n the node\n        ///@param g the graph\n        OutEdgeIt(const BpUGraph& n, const Node& g) {\n\t  ignore_unused_variable_warning(n);\n\t  ignore_unused_variable_warning(g);\n\t}\n        /// Edge -> OutEdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator.\n\t/// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        OutEdgeIt(const BpUGraph&, const Edge&) { }\n        ///Next outgoing edge\n        \n        /// Assign the iterator to the next \n        /// outgoing edge of the corresponding node.\n        OutEdgeIt& operator++() { return *this; }\n      };\n\n      /// This iterator goes trough the incoming directed edges of a node.\n\n      /// This iterator goes trough the \\e incoming edges of a certain node\n      /// of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of outgoing edges of a node \\c n\n      /// in graph \\c g of type \\c Graph as follows.\n      ///\\code\n      /// int count=0;\n      /// for(Graph::InEdgeIt e(g, n); e!=INVALID; ++e) ++count;\n      ///\\endcode\n\n      class InEdgeIt : public Edge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        InEdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        InEdgeIt(const InEdgeIt& e) : Edge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        InEdgeIt(Invalid) { }\n        /// This constructor sets the iterator to first incoming edge.\n    \n        /// This constructor set the iterator to the first incoming edge of\n        /// the node.\n        ///@param n the node\n        ///@param g the graph\n        InEdgeIt(const BpUGraph& g, const Node& n) { \n\t  ignore_unused_variable_warning(n);\n\t  ignore_unused_variable_warning(g);\n\t}\n        /// Edge -> InEdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator \\c e.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        InEdgeIt(const BpUGraph&, const Edge&) { }\n        /// Next incoming edge\n\n        /// Assign the iterator to the next inedge of the corresponding node.\n        ///\n        InEdgeIt& operator++() { return *this; }\n      };\n\n      /// \\brief Read write map of the nodes to type \\c T.\n      /// \n      /// ReadWrite map of the nodes to type \\c T.\n      /// \\sa Reference\n      /// \\todo Wrong documentation\n      template<class T> \n      class NodeMap : public ReadWriteMap< Node, T >\n      {\n      public:\n\n        ///\\e\n        NodeMap(const BpUGraph&) { }\n        ///\\e\n        NodeMap(const BpUGraph&, T) { }\n\n        ///Copy constructor\n        NodeMap(const NodeMap& nm) : ReadWriteMap< Node, T >(nm) { }\n        ///Assignment operator\n        NodeMap& operator=(const NodeMap&) { return *this; }\n        ///Assignment operator\n        template <typename CMap>\n        NodeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Node, T>, CMap>();\n          return *this; \n        }\n      };\n\n      /// \\brief Read write map of the ANodes to type \\c T.\n      /// \n      /// ReadWrite map of the ANodes to type \\c T.\n      /// \\sa Reference\n      /// \\todo Wrong documentation\n      template<class T> \n      class ANodeMap : public ReadWriteMap< Node, T >\n      {\n      public:\n\n        ///\\e\n        ANodeMap(const BpUGraph&) { }\n        ///\\e\n        ANodeMap(const BpUGraph&, T) { }\n\n        ///Copy constructor\n        ANodeMap(const ANodeMap& nm) : ReadWriteMap< Node, T >(nm) { }\n        ///Assignment operator\n        ANodeMap& operator=(const ANodeMap&) { return *this; }\n        ///Assignment operator\n        template <typename CMap>\n        ANodeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Node, T>, CMap>();\n          return *this; \n        }\n      };\n\n      /// \\brief Read write map of the BNodes to type \\c T.\n      /// \n      /// ReadWrite map of the BNodes to type \\c T.\n      /// \\sa Reference\n      /// \\todo Wrong documentation\n      template<class T> \n      class BNodeMap : public ReadWriteMap< Node, T >\n      {\n      public:\n\n        ///\\e\n        BNodeMap(const BpUGraph&) { }\n        ///\\e\n        BNodeMap(const BpUGraph&, T) { }\n\n        ///Copy constructor\n        BNodeMap(const BNodeMap& nm) : ReadWriteMap< Node, T >(nm) { }\n        ///Assignment operator\n        BNodeMap& operator=(const BNodeMap&) { return *this; }\n        ///Assignment operator\n        template <typename CMap>\n        BNodeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Node, T>, CMap>();\n          return *this; \n        }\n      };\n\n      /// \\brief Read write map of the directed edges to type \\c T.\n      ///\n      /// Reference map of the directed edges to type \\c T.\n      /// \\sa Reference\n      /// \\todo Wrong documentation\n      template<class T> \n      class EdgeMap : public ReadWriteMap<Edge,T>\n      {\n      public:\n\n        ///\\e\n        EdgeMap(const BpUGraph&) { }\n        ///\\e\n        EdgeMap(const BpUGraph&, T) { }\n        ///Copy constructor\n        EdgeMap(const EdgeMap& em) : ReadWriteMap<Edge,T>(em) { }\n        ///Assignment operator\n        EdgeMap& operator=(const EdgeMap&) { return *this; }\n        ///Assignment operator\n        template <typename CMap>\n        EdgeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Edge, T>, CMap>();\n          return *this; \n        }\n      };\n\n      /// Read write map of the undirected edges to type \\c T.\n\n      /// Reference map of the edges to type \\c T.\n      /// \\sa Reference\n      /// \\todo Wrong documentation\n      template<class T> \n      class UEdgeMap : public ReadWriteMap<UEdge,T>\n      {\n      public:\n\n        ///\\e\n        UEdgeMap(const BpUGraph&) { }\n        ///\\e\n        UEdgeMap(const BpUGraph&, T) { }\n        ///Copy constructor\n        UEdgeMap(const UEdgeMap& em) : ReadWriteMap<UEdge,T>(em) {}\n        ///Assignment operator\n        UEdgeMap &operator=(const UEdgeMap&) { return *this; }\n        ///Assignment operator\n        template <typename CMap>\n        UEdgeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<UEdge, T>, CMap>();\n          return *this; \n        }\n      };\n\n      /// \\brief Direct the given undirected edge.\n      ///\n      /// Direct the given undirected edge. The returned edge source\n      /// will be the given node.\n      Edge direct(const UEdge&, const Node&) const {\n\treturn INVALID;\n      }\n\n      /// \\brief Direct the given undirected edge.\n      ///\n      /// Direct the given undirected edge. The returned edge\n      /// represents the given undirected edge and the direction comes\n      /// from the given bool.  The source of the undirected edge and\n      /// the directed edge is the same when the given bool is true.\n      Edge direct(const UEdge&, bool) const {\n\treturn INVALID;\n      }\n\n      /// \\brief Returns true when the given node is an ANode.\n      ///\n      /// Returns true when the given node is an ANode.\n      bool aNode(Node) const { return true;}\n\n      /// \\brief Returns true when the given node is an BNode.\n      ///\n      /// Returns true when the given node is an BNode.\n      bool bNode(Node) const { return true;}\n\n      /// \\brief Returns the edge's end node which is in the ANode set.\n      ///\n      /// Returns the edge's end node which is in the ANode set.\n      Node aNode(UEdge) const { return INVALID;}\n\n      /// \\brief Returns the edge's end node which is in the BNode set.\n      ///\n      /// Returns the edge's end node which is in the BNode set.\n      Node bNode(UEdge) const { return INVALID;}\n\n      /// \\brief Returns true if the edge has default orientation.\n      ///\n      /// Returns whether the given directed edge is same orientation as\n      /// the corresponding undirected edge's default orientation.\n      bool direction(Edge) const { return true; }\n\n      /// \\brief Returns the opposite directed edge.\n      ///\n      /// Returns the opposite directed edge.\n      Edge oppositeEdge(Edge) const { return INVALID; }\n\n      /// \\brief Opposite node on an edge\n      ///\n      /// \\return the opposite of the given Node on the given UEdge\n      Node oppositeNode(Node, UEdge) const { return INVALID; }\n\n      /// \\brief First node of the undirected edge.\n      ///\n      /// \\return the first node of the given UEdge.\n      ///\n      /// Naturally undirected edges don't have direction and thus\n      /// don't have source and target node. But we use these two methods\n      /// to query the two endnodes of the edge. The direction of the edge\n      /// which arises this way is called the inherent direction of the\n      /// undirected edge, and is used to define the \"default\" direction\n      /// of the directed versions of the edges.\n      /// \\sa direction\n      Node source(UEdge) const { return INVALID; }\n\n      /// \\brief Second node of the undirected edge.\n      Node target(UEdge) const { return INVALID; }\n\n      /// \\brief Source node of the directed edge.\n      Node source(Edge) const { return INVALID; }\n\n      /// \\brief Target node of the directed edge.\n      Node target(Edge) const { return INVALID; }\n\n      /// \\brief Base node of the iterator\n      ///\n      /// Returns the base node (the source in this case) of the iterator\n      Node baseNode(OutEdgeIt e) const {\n\treturn source(e);\n      }\n\n      /// \\brief Running node of the iterator\n      ///\n      /// Returns the running node (the target in this case) of the\n      /// iterator\n      Node runningNode(OutEdgeIt e) const {\n\treturn target(e);\n      }\n\n      /// \\brief Base node of the iterator\n      ///\n      /// Returns the base node (the target in this case) of the iterator\n      Node baseNode(InEdgeIt e) const {\n\treturn target(e);\n      }\n      /// \\brief Running node of the iterator\n      ///\n      /// Returns the running node (the source in this case) of the\n      /// iterator\n      Node runningNode(InEdgeIt e) const {\n\treturn source(e);\n      }\n\n      /// \\brief Base node of the iterator\n      ///\n      /// Returns the base node of the iterator\n      Node baseNode(IncEdgeIt) const {\n\treturn INVALID;\n      }\n      \n      /// \\brief Running node of the iterator\n      ///\n      /// Returns the running node of the iterator\n      Node runningNode(IncEdgeIt) const {\n\treturn INVALID;\n      }\n\n      void first(Node&) const {}\n      void next(Node&) const {}\n\n      void first(Edge&) const {}\n      void next(Edge&) const {}\n\n      void first(UEdge&) const {}\n      void next(UEdge&) const {}\n\n      void firstANode(Node&) const {}\n      void nextANode(Node&) const {}\n\n      void firstBNode(Node&) const {}\n      void nextBNode(Node&) const {}\n\n      void firstIn(Edge&, const Node&) const {}\n      void nextIn(Edge&) const {}\n\n      void firstOut(Edge&, const Node&) const {}\n      void nextOut(Edge&) const {}\n\n      void firstInc(UEdge &, bool &, const Node &) const {}\n      void nextInc(UEdge &, bool &) const {}\n\n      void firstFromANode(UEdge&, const Node&) const {}\n      void nextFromANode(UEdge&) const {}\n\n      void firstFromBNode(UEdge&, const Node&) const {}\n      void nextFromBNode(UEdge&) const {}\n\n      template <typename Graph>\n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<IterableBpUGraphComponent<>, Graph>();\n\t  checkConcept<MappableBpUGraphComponent<>, Graph>();\n\t}\n      };\n\n    };\n\n  }\n\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/concepts/graph.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_CONCEPT_GRAPH_H\n#define LEMON_CONCEPT_GRAPH_H\n\n///\\ingroup graph_concepts\n///\\file\n///\\brief The concept of Directed Graphs.\n\n#include <lemon/bits/invalid.h>\n#include <lemon/bits/utility.h>\n#include <lemon/concepts/maps.h>\n#include <lemon/concept_check.h>\n#include <lemon/concepts/graph_components.h>\n\nnamespace lemon {\n  namespace concepts {\n\n    /// \\ingroup graph_concepts\n    ///\n    /// \\brief Class describing the concept of Directed Graphs.\n    ///\n    /// This class describes the \\ref concept \"concept\" of the\n    /// immutable directed graphs.\n    ///\n    /// Note that actual graph implementation like @ref ListGraph or\n    /// @ref SmartGraph may have several additional functionality.\n    ///\n    /// \\sa concept\n    class Graph {\n    private:\n      ///Graphs are \\e not copy constructible. Use GraphCopy() instead.\n      \n      ///Graphs are \\e not copy constructible. Use GraphCopy() instead.\n      ///\n      Graph(const Graph &) {};\n      ///\\brief Assignment of \\ref Graph \"Graph\"s to another ones are\n      ///\\e not allowed. Use GraphCopy() instead.\n      \n      ///Assignment of \\ref Graph \"Graph\"s to another ones are\n      ///\\e not allowed.  Use GraphCopy() instead.\n\n      void operator=(const Graph &) {}\n    public:\n      ///\\e\n\n      /// Defalult constructor.\n\n      /// Defalult constructor.\n      ///\n      Graph() { }\n      /// Class for identifying a node of the graph\n\n      /// This class identifies a node of the graph. It also serves\n      /// as a base class of the node iterators,\n      /// thus they will convert to this type.\n      class Node {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        Node() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        Node(const Node&) { }\n\n        /// Invalid constructor \\& conversion.\n\n        /// This constructor initializes the iterator to be invalid.\n        /// \\sa Invalid for more details.\n        Node(Invalid) { }\n        /// Equality operator\n\n        /// Two iterators are equal if and only if they point to the\n        /// same object or both are invalid.\n        bool operator==(Node) const { return true; }\n\n        /// Inequality operator\n        \n        /// \\sa operator==(Node n)\n        ///\n        bool operator!=(Node) const { return true; }\n\n\t/// Artificial ordering operator.\n\t\n\t/// To allow the use of graph descriptors as key type in std::map or\n\t/// similar associative container we require this.\n\t///\n\t/// \\note This operator only have to define some strict ordering of\n\t/// the items; this order has nothing to do with the iteration\n\t/// ordering of the items.\n\tbool operator<(Node) const { return false; }\n\n      };\n    \n      /// This iterator goes through each node.\n\n      /// This iterator goes through each node.\n      /// Its usage is quite simple, for example you can count the number\n      /// of nodes in graph \\c g of type \\c Graph like this:\n      ///\\code\n      /// int count=0;\n      /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count;\n      ///\\endcode\n      class NodeIt : public Node {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        NodeIt() { }\n        /// Copy constructor.\n        \n        /// Copy constructor.\n        ///\n        NodeIt(const NodeIt& n) : Node(n) { }\n        /// Invalid constructor \\& conversion.\n\n        /// Initialize the iterator to be invalid.\n        /// \\sa Invalid for more details.\n        NodeIt(Invalid) { }\n        /// Sets the iterator to the first node.\n\n        /// Sets the iterator to the first node of \\c g.\n        ///\n        NodeIt(const Graph&) { }\n        /// Node -> NodeIt conversion.\n\n        /// Sets the iterator to the node of \\c the graph pointed by \n\t/// the trivial iterator.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        NodeIt(const Graph&, const Node&) { }\n        /// Next node.\n\n        /// Assign the iterator to the next node.\n        ///\n        NodeIt& operator++() { return *this; }\n      };\n    \n    \n      /// Class for identifying an edge of the graph\n\n      /// This class identifies an edge of the graph. It also serves\n      /// as a base class of the edge iterators,\n      /// thus they will convert to this type.\n      class Edge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        Edge() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        Edge(const Edge&) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        Edge(Invalid) { }\n        /// Equality operator\n\n        /// Two iterators are equal if and only if they point to the\n        /// same object or both are invalid.\n        bool operator==(Edge) const { return true; }\n        /// Inequality operator\n\n        /// \\sa operator==(Edge n)\n        ///\n        bool operator!=(Edge) const { return true; }\n\n\t/// Artificial ordering operator.\n\t\n\t/// To allow the use of graph descriptors as key type in std::map or\n\t/// similar associative container we require this.\n\t///\n\t/// \\note This operator only have to define some strict ordering of\n\t/// the items; this order has nothing to do with the iteration\n\t/// ordering of the items.\n\tbool operator<(Edge) const { return false; }\n      };\n    \n      /// This iterator goes trough the outgoing edges of a node.\n\n      /// This iterator goes trough the \\e outgoing edges of a certain node\n      /// of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of outgoing edges of a node \\c n\n      /// in graph \\c g of type \\c Graph as follows.\n      ///\\code\n      /// int count=0;\n      /// for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) ++count;\n      ///\\endcode\n    \n      class OutEdgeIt : public Edge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        OutEdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        OutEdgeIt(const OutEdgeIt& e) : Edge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        OutEdgeIt(Invalid) { }\n        /// This constructor sets the iterator to the first outgoing edge.\n    \n        /// This constructor sets the iterator to the first outgoing edge of\n        /// the node.\n        OutEdgeIt(const Graph&, const Node&) { }\n        /// Edge -> OutEdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator.\n\t/// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        OutEdgeIt(const Graph&, const Edge&) { }\n        ///Next outgoing edge\n        \n        /// Assign the iterator to the next \n        /// outgoing edge of the corresponding node.\n        OutEdgeIt& operator++() { return *this; }\n      };\n\n      /// This iterator goes trough the incoming edges of a node.\n\n      /// This iterator goes trough the \\e incoming edges of a certain node\n      /// of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of outgoing edges of a node \\c n\n      /// in graph \\c g of type \\c Graph as follows.\n      ///\\code\n      /// int count=0;\n      /// for(Graph::InEdgeIt e(g, n); e!=INVALID; ++e) ++count;\n      ///\\endcode\n\n      class InEdgeIt : public Edge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        InEdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        InEdgeIt(const InEdgeIt& e) : Edge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        InEdgeIt(Invalid) { }\n        /// This constructor sets the iterator to first incoming edge.\n    \n        /// This constructor set the iterator to the first incoming edge of\n        /// the node.\n        InEdgeIt(const Graph&, const Node&) { }\n        /// Edge -> InEdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator \\c e.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        InEdgeIt(const Graph&, const Edge&) { }\n        /// Next incoming edge\n\n        /// Assign the iterator to the next inedge of the corresponding node.\n        ///\n        InEdgeIt& operator++() { return *this; }\n      };\n      /// This iterator goes through each edge.\n\n      /// This iterator goes through each edge of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of edges in a graph \\c g of type \\c Graph as follows:\n      ///\\code\n      /// int count=0;\n      /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count;\n      ///\\endcode\n      class EdgeIt : public Edge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        EdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        EdgeIt(const EdgeIt& e) : Edge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        EdgeIt(Invalid) { }\n        /// This constructor sets the iterator to the first edge.\n    \n        /// This constructor sets the iterator to the first edge of \\c g.\n        ///@param g the graph\n        EdgeIt(const Graph& g) { ignore_unused_variable_warning(g); }\n        /// Edge -> EdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator \\c e.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        EdgeIt(const Graph&, const Edge&) { } \n        ///Next edge\n        \n        /// Assign the iterator to the next edge.\n        EdgeIt& operator++() { return *this; }\n      };\n      ///Gives back the target node of an edge.\n\n      ///Gives back the target node of an edge.\n      ///\n      Node target(Edge) const { return INVALID; }\n      ///Gives back the source node of an edge.\n\n      ///Gives back the source node of an edge.\n      ///\n      Node source(Edge) const { return INVALID; }\n\n      void first(Node&) const {}\n      void next(Node&) const {}\n\n      void first(Edge&) const {}\n      void next(Edge&) const {}\n\n\n      void firstIn(Edge&, const Node&) const {}\n      void nextIn(Edge&) const {}\n\n      void firstOut(Edge&, const Node&) const {}\n      void nextOut(Edge&) const {}\n\n      /// \\brief The base node of the iterator.\n      ///\n      /// Gives back the base node of the iterator.\n      /// It is always the target of the pointed edge.\n      Node baseNode(const InEdgeIt&) const { return INVALID; }\n\n      /// \\brief The running node of the iterator.\n      ///\n      /// Gives back the running node of the iterator.\n      /// It is always the source of the pointed edge.\n      Node runningNode(const InEdgeIt&) const { return INVALID; }\n\n      /// \\brief The base node of the iterator.\n      ///\n      /// Gives back the base node of the iterator.\n      /// It is always the source of the pointed edge.\n      Node baseNode(const OutEdgeIt&) const { return INVALID; }\n\n      /// \\brief The running node of the iterator.\n      ///\n      /// Gives back the running node of the iterator.\n      /// It is always the target of the pointed edge.\n      Node runningNode(const OutEdgeIt&) const { return INVALID; }\n\n      /// \\brief The opposite node on the given edge.\n      ///\n      /// Gives back the opposite node on the given edge.\n      Node oppositeNode(const Node&, const Edge&) const { return INVALID; }\n\n      /// \\brief Read write map of the nodes to type \\c T.\n      /// \n      /// ReadWrite map of the nodes to type \\c T.\n      /// \\sa Reference\n      template<class T> \n      class NodeMap : public ReadWriteMap< Node, T > {\n      public:\n\n        ///\\e\n        NodeMap(const Graph&) { }\n        ///\\e\n        NodeMap(const Graph&, T) { }\n\n        ///Copy constructor\n        NodeMap(const NodeMap& nm) : ReadWriteMap< Node, T >(nm) { }\n        ///Assignment operator\n        template <typename CMap>\n        NodeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Node, T>, CMap>();\n          return *this; \n        }\n      };\n\n      /// \\brief Read write map of the edges to type \\c T.\n      ///\n      /// Reference map of the edges to type \\c T.\n      /// \\sa Reference\n      template<class T> \n      class EdgeMap : public ReadWriteMap<Edge,T> {\n      public:\n\n        ///\\e\n        EdgeMap(const Graph&) { }\n        ///\\e\n        EdgeMap(const Graph&, T) { }\n        ///Copy constructor\n        EdgeMap(const EdgeMap& em) : ReadWriteMap<Edge,T>(em) { }\n        ///Assignment operator\n        template <typename CMap>\n        EdgeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Edge, T>, CMap>();\n          return *this; \n        }\n      };\n\n      template <typename RGraph>\n      struct Constraints {\n        void constraints() {\n          checkConcept<IterableGraphComponent<>, Graph>();\n          checkConcept<MappableGraphComponent<>, Graph>();\n        }\n      };\n\n    };\n    \n  } //namespace concepts  \n} //namespace lemon\n\n\n\n#endif // LEMON_CONCEPT_GRAPH_H\n"
  },
  {
    "path": "src/lemon/concepts/graph_components.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n///\\ingroup graph_concepts\n///\\file\n///\\brief The concept of graph components.\n\n\n#ifndef LEMON_CONCEPT_GRAPH_COMPONENTS_H\n#define LEMON_CONCEPT_GRAPH_COMPONENTS_H\n\n#include <lemon/bits/invalid.h>\n#include <lemon/concepts/maps.h>\n\n#include <lemon/bits/alteration_notifier.h>\n\nnamespace lemon {\n  namespace concepts {\n\n    /// \\brief Skeleton class for graph Node and Edge types\n    ///\n    /// This class describes the interface of Node and Edge (and UEdge\n    /// in undirected graphs) subtypes of graph types.\n    ///\n    /// \\note This class is a template class so that we can use it to\n    /// create graph skeleton classes. The reason for this is than Node\n    /// and Edge types should \\em not derive from the same base class.\n    /// For Node you should instantiate it with character 'n' and for Edge\n    /// with 'e'.\n\n#ifndef DOXYGEN\n    template <char _selector = '0'>\n#endif\n    class GraphItem {\n    public:\n      /// \\brief Default constructor.\n      ///      \n      /// \\warning The default constructor is not required to set\n      /// the item to some well-defined value. So you should consider it\n      /// as uninitialized.\n      GraphItem() {}\n      /// \\brief Copy constructor.\n      ///\n      /// Copy constructor.\n      ///\n      GraphItem(const GraphItem &) {}\n      /// \\brief Invalid constructor \\& conversion.\n      ///\n      /// This constructor initializes the item to be invalid.\n      /// \\sa Invalid for more details.\n      GraphItem(Invalid) {}\n      /// \\brief Assign operator for nodes.\n      ///\n      /// The nodes are assignable. \n      ///\n      GraphItem& operator=(GraphItem const&) { return *this; }\n      /// \\brief Equality operator.\n      ///\n      /// Two iterators are equal if and only if they represents the\n      /// same node in the graph or both are invalid.\n      bool operator==(GraphItem) const { return false; }\n      /// \\brief Inequality operator.\n      ///\n      /// \\sa operator==(const Node& n)\n      ///\n      bool operator!=(GraphItem) const { return false; }\n\n      /// \\brief Artificial ordering operator.\n      ///\n      /// To allow the use of graph descriptors as key type in std::map or\n      /// similar associative container we require this.\n      ///\n      /// \\note This operator only have to define some strict ordering of\n      /// the items; this order has nothing to do with the iteration\n      /// ordering of the items.\n      bool operator<(GraphItem) const { return false; }\n\n      template<typename _GraphItem>\n      struct Constraints {\n\tvoid constraints() {\n\t  _GraphItem i1;\n\t  _GraphItem i2 = i1;\n\t  _GraphItem i3 = INVALID;\n\t  \n\t  i1 = i2 = i3;\n\n\t  bool b;\n\t  //\t  b = (ia == ib) && (ia != ib) && (ia < ib);\n\t  b = (ia == ib) && (ia != ib);\n\t  b = (ia == INVALID) && (ib != INVALID);\n          b = (ia < ib);\n\t}\n\n\tconst _GraphItem &ia;\n\tconst _GraphItem &ib;\n      };\n    };\n\n    /// \\brief An empty base graph class.\n    ///  \n    /// This class provides the minimal set of features needed for a graph\n    /// structure. All graph concepts have to be conform to this base\n    /// graph. It just provides types for nodes and edges and functions to\n    /// get the source and the target of the edges.\n    class BaseGraphComponent {\n    public:\n\n      typedef BaseGraphComponent Graph;\n      \n      /// \\brief Node class of the graph.\n      ///\n      /// This class represents the Nodes of the graph. \n      ///\n      typedef GraphItem<'n'> Node;\n\n      /// \\brief Edge class of the graph.\n      ///\n      /// This class represents the Edges of the graph. \n      ///\n      typedef GraphItem<'e'> Edge;\n\n      /// \\brief Gives back the target node of an edge.\n      ///\n      /// Gives back the target node of an edge.\n      ///\n      Node target(const Edge&) const { return INVALID;}\n\n      /// \\brief Gives back the source node of an edge.\n      ///\n      /// Gives back the source node of an edge.\n      ///\n      Node source(const Edge&) const { return INVALID;}\n\n      /// \\brief Gives back the opposite node on the given edge.\n      ///\n      /// Gives back the opposite node on the given edge.\n      Node oppositeNode(const Node&, const Edge&) const {\n        return INVALID;\n      }\n\n      template <typename _Graph>\n      struct Constraints {\n\ttypedef typename _Graph::Node Node;\n\ttypedef typename _Graph::Edge Edge;\n      \n\tvoid constraints() {\n\t  checkConcept<GraphItem<'n'>, Node>();\n\t  checkConcept<GraphItem<'e'>, Edge>();\n\t  {\n\t    Node n;\n\t    Edge e(INVALID);\n\t    n = graph.source(e);\n\t    n = graph.target(e);\n            n = graph.oppositeNode(n, e);\n\t  }      \n\t}\n      \n\tconst _Graph& graph;\n      };\n    };\n\n    /// \\brief An empty base undirected graph class.\n    ///  \n    /// This class provides the minimal set of features needed for an\n    /// undirected graph structure. All undirected graph concepts have\n    /// to be conform to this base graph. It just provides types for\n    /// nodes, edges and undirected edges and functions to get the\n    /// source and the target of the edges and undirected edges,\n    /// conversion from edges to undirected edges and function to get\n    /// both direction of the undirected edges.\n    class BaseUGraphComponent : public BaseGraphComponent {\n    public:\n      typedef BaseGraphComponent::Node Node;\n      typedef BaseGraphComponent::Edge Edge;\n      /// \\brief Undirected edge class of the graph.\n      ///\n      /// This class represents the undirected edges of the graph.\n      /// The undirected graphs can be used as a directed graph which\n      /// for each edge contains the opposite edge too so the graph is\n      /// bidirected. The undirected edge represents two opposite\n      /// directed edges.\n      class UEdge : public GraphItem<'u'> {\n      public:\n        typedef GraphItem<'u'> Parent;\n        /// \\brief Default constructor.\n        ///      \n        /// \\warning The default constructor is not required to set\n        /// the item to some well-defined value. So you should consider it\n        /// as uninitialized.\n        UEdge() {}\n        /// \\brief Copy constructor.\n        ///\n        /// Copy constructor.\n        ///\n        UEdge(const UEdge &) : Parent() {}\n        /// \\brief Invalid constructor \\& conversion.\n        ///\n        /// This constructor initializes the item to be invalid.\n        /// \\sa Invalid for more details.\n        UEdge(Invalid) {}\n        /// \\brief Converter from edge to undirected edge.\n        ///\n        /// Besides the core graph item functionality each edge should\n        /// be convertible to the represented undirected edge. \n        UEdge(const Edge&) {}\n        /// \\brief Assign edge to undirected edge.\n        ///\n        /// Besides the core graph item functionality each edge should\n        /// be convertible to the represented undirected edge. \n        UEdge& operator=(const Edge&) { return *this; }\n      };\n\n      /// \\brief Returns the direction of the edge.\n      ///\n      /// Returns the direction of the edge. Each edge represents an\n      /// undirected edge with a direction. It gives back the\n      /// direction.\n      bool direction(const Edge&) const { return true; }\n\n      /// \\brief Returns the directed edge.\n      ///\n      /// Returns the directed edge from its direction and the\n      /// represented undirected edge.\n      Edge direct(const UEdge&, bool) const { return INVALID;} \n\n      /// \\brief Returns the directed edge.\n      ///\n      /// Returns the directed edge from its source and the\n      /// represented undirected edge.\n      Edge direct(const UEdge&, const Node&) const { return INVALID;} \n\n      /// \\brief Returns the opposite edge.\n      ///\n      /// Returns the opposite edge. It is the edge representing the\n      /// same undirected edge and has opposite direction.\n      Edge oppositeEdge(const Edge&) const { return INVALID;}\n\n      /// \\brief Gives back the target node of an undirected edge.\n      ///\n      /// Gives back the target node of an undirected edge. The name\n      /// target is a little confusing because the undirected edge\n      /// does not have target but it just means that one of the end \n      /// node.\n      Node target(const UEdge&) const { return INVALID;}\n\n      /// \\brief Gives back the source node of an undirected edge.\n      ///\n      /// Gives back the source node of an undirected edge. The name\n      /// source is a little confusing because the undirected edge\n      /// does not have source but it just means that one of the end \n      /// node.\n      Node source(const UEdge&) const { return INVALID;}\n      \n      template <typename _Graph>\n      struct Constraints {\n\ttypedef typename _Graph::Node Node;\n\ttypedef typename _Graph::Edge Edge;\n\ttypedef typename _Graph::UEdge UEdge;\n      \n\tvoid constraints() {\n          checkConcept<BaseGraphComponent, _Graph>();\n\t  checkConcept<GraphItem<'u'>, UEdge>();\n\t  {\n\t    Node n;\n\t    UEdge ue(INVALID);\n            Edge e;\n\t    n = graph.source(ue);\n\t    n = graph.target(ue);\n            e = graph.direct(ue, true);\n            e = graph.direct(ue, n);\n            e = graph.oppositeEdge(e);\n            ue = e;\n            bool d = graph.direction(e);\n            ignore_unused_variable_warning(d);\n\t  }      \n\t}\n      \n\tconst _Graph& graph;\n      };\n\n    };\n\n    /// \\brief An empty base bipartite undirected graph class.\n    ///  \n    /// This class provides the minimal set of features needed for an\n    /// bipartite undirected graph structure. All bipartite undirected\n    /// graph concepts have to be conform to this base graph. It just\n    /// provides types for nodes, A-nodes, B-nodes, edges and\n    /// undirected edges and functions to get the source and the\n    /// target of the edges and undirected edges, conversion from\n    /// edges to undirected edges and function to get both direction\n    /// of the undirected edges.\n    class BaseBpUGraphComponent : public BaseUGraphComponent {\n    public:\n      typedef BaseUGraphComponent::Node Node;\n      typedef BaseUGraphComponent::Edge Edge;\n      typedef BaseUGraphComponent::UEdge UEdge;\n\n      /// \\brief Helper class for A-nodes.\n      ///\n      /// This class is just a helper class for A-nodes, it is not\n      /// suggested to use it directly. It can be converted easily to\n      /// node and vice versa. The usage of this class is limited\n      /// to use just as template parameters for special map types. \n      class ANode : public Node {\n      public:\n        typedef Node Parent;\n\n        /// \\brief Default constructor.\n        ///      \n        /// \\warning The default constructor is not required to set\n        /// the item to some well-defined value. So you should consider it\n        /// as uninitialized.\n        ANode() {}\n        /// \\brief Copy constructor.\n        ///\n        /// Copy constructor.\n        ///\n        ANode(const ANode &) : Parent() {}\n        /// \\brief Invalid constructor \\& conversion.\n        ///\n        /// This constructor initializes the item to be invalid.\n        /// \\sa Invalid for more details.\n        ANode(Invalid) {}\n        /// \\brief Converter from node to A-node.\n        ///\n        /// Besides the core graph item functionality each node should\n        /// be convertible to the represented A-node if it is it possible. \n        ANode(const Node&) {}\n        /// \\brief Assign node to A-node.\n        ///\n        /// Besides the core graph item functionality each node should\n        /// be convertible to the represented A-node if it is it possible. \n        ANode& operator=(const Node&) { return *this; }\n      };\n\n      /// \\brief Helper class for B-nodes.\n      ///\n      /// This class is just a helper class for B-nodes, it is not\n      /// suggested to use it directly. It can be converted easily to\n      /// node and vice versa. The usage of this class is limited\n      /// to use just as template parameters for special map types. \n      class BNode : public Node {\n      public:\n        typedef Node Parent;\n\n        /// \\brief Default constructor.\n        ///      \n        /// \\warning The default constructor is not required to set\n        /// the item to some well-defined value. So you should consider it\n        /// as uninitialized.\n        BNode() {}\n        /// \\brief Copy constructor.\n        ///\n        /// Copy constructor.\n        ///\n        BNode(const BNode &) : Parent() {}\n        /// \\brief Invalid constructor \\& conversion.\n        ///\n        /// This constructor initializes the item to be invalid.\n        /// \\sa Invalid for more details.\n        BNode(Invalid) {}\n        /// \\brief Converter from node to B-node.\n        ///\n        /// Besides the core graph item functionality each node should\n        /// be convertible to the represented B-node if it is it possible. \n        BNode(const Node&) {}\n        /// \\brief Assign node to B-node.\n        ///\n        /// Besides the core graph item functionality each node should\n        /// be convertible to the represented B-node if it is it possible. \n        BNode& operator=(const Node&) { return *this; }\n      };\n      \n      /// \\brief Gives back %true when the node is A-node.\n      ///\n      /// Gives back %true when the node is A-node.\n      bool aNode(const Node&) const { return false; }\n\n      /// \\brief Gives back %true when the node is B-node.\n      ///\n      /// Gives back %true when the node is B-node.\n      bool bNode(const Node&) const { return false; }\n\n      /// \\brief Gives back the A-node of the undirected edge.\n      ///\n      /// Gives back the A-node of the undirected edge.\n      Node aNode(const UEdge&) const { return INVALID; }\n\n      /// \\brief Gives back the B-node of the undirected edge.\n      ///\n      /// Gives back the B-node of the undirected edge.\n      Node bNode(const UEdge&) const { return INVALID; }\n      \n      template <typename _Graph>\n      struct Constraints {\n\ttypedef typename _Graph::Node Node;\n\ttypedef typename _Graph::ANode ANode;\n\ttypedef typename _Graph::BNode BNode;\n\ttypedef typename _Graph::Edge Edge;\n\ttypedef typename _Graph::UEdge UEdge;\n      \n\tvoid constraints() {\n          checkConcept<BaseUGraphComponent, _Graph>();\n\t  checkConcept<GraphItem<'a'>, ANode>();\n\t  checkConcept<GraphItem<'b'>, BNode>();\n\t  {\n\t    Node n;\n\t    UEdge ue(INVALID);\n            bool b;\n\t    n = graph.aNode(ue);\n\t    n = graph.bNode(ue);\n            b = graph.aNode(n);\n            b = graph.bNode(n);\n            ANode an;\n            an = n; n = an;\n            BNode bn;\n            bn = n; n = bn;            \n            ignore_unused_variable_warning(b);\n\t  }      \n\t}\n      \n\tconst _Graph& graph;\n      };\n\n    };\n\n    /// \\brief An empty idable base graph class.\n    ///  \n    /// This class provides beside the core graph features\n    /// core id functions for the graph structure.\n    /// The most of the base graphs should be conform to this concept.\n    /// The id's are unique and immutable.\n    template <typename _Base = BaseGraphComponent>\n    class IDableGraphComponent : public _Base {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::Node Node;\n      typedef typename Base::Edge Edge;\n\n      /// \\brief Gives back an unique integer id for the Node. \n      ///\n      /// Gives back an unique integer id for the Node. \n      ///\n      int id(const Node&) const { return -1;}\n\n      /// \\brief Gives back the node by the unique id.\n      ///\n      /// Gives back the node by the unique id.\n      /// If the graph does not contain node with the given id\n      /// then the result of the function is undetermined. \n      Node nodeFromId(int) const { return INVALID;}\n\n      /// \\brief Gives back an unique integer id for the Edge. \n      ///\n      /// Gives back an unique integer id for the Edge. \n      ///\n      int id(const Edge&) const { return -1;}\n\n      /// \\brief Gives back the edge by the unique id.\n      ///\n      /// Gives back the edge by the unique id.\n      /// If the graph does not contain edge with the given id\n      /// then the result of the function is undetermined. \n      Edge edgeFromId(int) const { return INVALID;}\n\n      /// \\brief Gives back an integer greater or equal to the maximum\n      /// Node id.\n      ///\n      /// Gives back an integer greater or equal to the maximum Node\n      /// id.\n      int maxNodeId() const { return -1;}\n\n      /// \\brief Gives back an integer greater or equal to the maximum\n      /// Edge id.\n      ///\n      /// Gives back an integer greater or equal to the maximum Edge\n      /// id.\n      int maxEdgeId() const { return -1;}\n\n      template <typename _Graph>\n      struct Constraints {\n\n\tvoid constraints() {\n\t  checkConcept<Base, _Graph >();\n\t  typename _Graph::Node node;\n\t  int nid = graph.id(node);\n\t  nid = graph.id(node);\n\t  node = graph.nodeFromId(nid);\n\t  typename _Graph::Edge edge;\n\t  int eid = graph.id(edge);\n\t  eid = graph.id(edge);\n\t  edge = graph.edgeFromId(eid);\n\n\t  nid = graph.maxNodeId();\n\t  ignore_unused_variable_warning(nid);\n\t  eid = graph.maxEdgeId();\n\t  ignore_unused_variable_warning(eid);\n\t}\n\n\tconst _Graph& graph;\n      };\n    };\n\n    /// \\brief An empty idable base undirected graph class.\n    ///  \n    /// This class provides beside the core undirected graph features\n    /// core id functions for the undirected graph structure.  The\n    /// most of the base undirected graphs should be conform to this\n    /// concept.  The id's are unique and immutable.\n    template <typename _Base = BaseUGraphComponent>\n    class IDableUGraphComponent : public IDableGraphComponent<_Base> {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::UEdge UEdge;\n\n      using IDableGraphComponent<_Base>::id;\n\n      /// \\brief Gives back an unique integer id for the UEdge. \n      ///\n      /// Gives back an unique integer id for the UEdge. \n      ///\n      int id(const UEdge&) const { return -1;}\n\n      /// \\brief Gives back the undirected edge by the unique id.\n      ///\n      /// Gives back the undirected edge by the unique id.  If the\n      /// graph does not contain edge with the given id then the\n      /// result of the function is undetermined.\n      UEdge uEdgeFromId(int) const { return INVALID;}\n\n      /// \\brief Gives back an integer greater or equal to the maximum\n      /// UEdge id.\n      ///\n      /// Gives back an integer greater or equal to the maximum UEdge\n      /// id.\n      int maxUEdgeId() const { return -1;}\n\n      template <typename _Graph>\n      struct Constraints {\n\n\tvoid constraints() {\n\t  checkConcept<Base, _Graph >();\n\t  checkConcept<IDableGraphComponent<Base>, _Graph >();\n\t  typename _Graph::UEdge uedge;\n\t  int ueid = graph.id(uedge);\n\t  ueid = graph.id(uedge);\n\t  uedge = graph.uEdgeFromId(ueid);\n\t  ueid = graph.maxUEdgeId();\n\t  ignore_unused_variable_warning(ueid);\n\t}\n\n\tconst _Graph& graph;\n      };\n    };\n\n    /// \\brief An empty idable base bipartite undirected graph class.\n    ///  \n    /// This class provides beside the core bipartite undirected graph\n    /// features core id functions for the bipartite undirected graph\n    /// structure.  The most of the base undirected graphs should be\n    /// conform to this concept.\n    template <typename _Base = BaseBpUGraphComponent>\n    class IDableBpUGraphComponent : public IDableUGraphComponent<_Base> {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::Node Node;\n\n      using IDableUGraphComponent<_Base>::id;\n\n      /// \\brief Gives back an unique integer id for the ANode. \n      ///\n      /// Gives back an unique integer id for the ANode. \n      ///\n      int aNodeId(const Node&) const { return -1;}\n\n      /// \\brief Gives back the undirected edge by the unique id.\n      ///\n      /// Gives back the undirected edge by the unique id.  If the\n      /// graph does not contain edge with the given id then the\n      /// result of the function is undetermined.\n      Node nodeFromANodeId(int) const { return INVALID;}\n\n      /// \\brief Gives back an integer greater or equal to the maximum\n      /// ANode id.\n      ///\n      /// Gives back an integer greater or equal to the maximum ANode\n      /// id.\n      int maxANodeId() const { return -1;}\n\n      /// \\brief Gives back an unique integer id for the BNode. \n      ///\n      /// Gives back an unique integer id for the BNode. \n      ///\n      int bNodeId(const Node&) const { return -1;}\n\n      /// \\brief Gives back the undirected edge by the unique id.\n      ///\n      /// Gives back the undirected edge by the unique id.  If the\n      /// graph does not contain edge with the given id then the\n      /// result of the function is undetermined.\n      Node nodeFromBNodeId(int) const { return INVALID;}\n\n      /// \\brief Gives back an integer greater or equal to the maximum\n      /// BNode id.\n      ///\n      /// Gives back an integer greater or equal to the maximum BNode\n      /// id.\n      int maxBNodeId() const { return -1;}\n\n      template <typename _Graph>\n      struct Constraints {\n\n\tvoid constraints() {\n\t  checkConcept<Base, _Graph >();\n\t  checkConcept<IDableGraphComponent<Base>, _Graph >();\n\t  typename _Graph::Node node(INVALID);\n\t  int id;\n          id = graph.aNodeId(node);\n          id = graph.bNodeId(node);\n          node = graph.nodeFromANodeId(id);\n          node = graph.nodeFromBNodeId(id);\n          id = graph.maxANodeId();\n          id = graph.maxBNodeId();\n\t}\n\n\tconst _Graph& graph;\n      };\n    };\n\n    /// \\brief Skeleton class for graph NodeIt and EdgeIt\n    ///\n    /// Skeleton class for graph NodeIt and EdgeIt.\n    ///\n    template <typename _Graph, typename _Item>\n    class GraphItemIt : public _Item {\n    public:\n      /// \\brief Default constructor.\n      ///\n      /// @warning The default constructor sets the iterator\n      /// to an undefined value.\n      GraphItemIt() {}\n      /// \\brief Copy constructor.\n      ///\n      /// Copy constructor.\n      ///\n      GraphItemIt(const GraphItemIt& ) {}\n      /// \\brief Sets the iterator to the first item.\n      ///\n      /// Sets the iterator to the first item of \\c the graph.\n      ///\n      explicit GraphItemIt(const _Graph&) {}\n      /// \\brief Invalid constructor \\& conversion.\n      ///\n      /// This constructor initializes the item to be invalid.\n      /// \\sa Invalid for more details.\n      GraphItemIt(Invalid) {}\n      /// \\brief Assign operator for items.\n      ///\n      /// The items are assignable. \n      ///\n      GraphItemIt& operator=(const GraphItemIt&) { return *this; }      \n      /// \\brief Next item.\n      /// \n      /// Assign the iterator to the next item.\n      ///\n      GraphItemIt& operator++() { return *this; }\n      /// \\brief Equality operator\n      /// \n      /// Two iterators are equal if and only if they point to the\n      /// same object or both are invalid.\n      bool operator==(const GraphItemIt&) const { return true;}\n      /// \\brief Inequality operator\n      ///\t\n      /// \\sa operator==(Node n)\n      ///\n      bool operator!=(const GraphItemIt&) const { return true;}\n      \n      template<typename _GraphItemIt>\n      struct Constraints {\n\tvoid constraints() {\n\t  _GraphItemIt it1(g);\t\n\t  _GraphItemIt it2;\n\n\t  it2 = ++it1;\n\t  ++it2 = it1;\n\t  ++(++it1);\n\n\t  _Item bi = it1;\n\t  bi = it2;\n\t}\n\t_Graph& g;\n      };\n    };\n\n    /// \\brief Skeleton class for graph InEdgeIt and OutEdgeIt\n    ///\n    /// \\note Because InEdgeIt and OutEdgeIt may not inherit from the same\n    /// base class, the _selector is a additional template parameter. For \n    /// InEdgeIt you should instantiate it with character 'i' and for \n    /// OutEdgeIt with 'o'.\n    template <typename _Graph,\n\t      typename _Item = typename _Graph::Edge,\n              typename _Base = typename _Graph::Node, \n\t      char _selector = '0'>\n    class GraphIncIt : public _Item {\n    public:\n      /// \\brief Default constructor.\n      ///\n      /// @warning The default constructor sets the iterator\n      /// to an undefined value.\n      GraphIncIt() {}\n      /// \\brief Copy constructor.\n      ///\n      /// Copy constructor.\n      ///\n      GraphIncIt(GraphIncIt const& gi) : _Item(gi) {}\n      /// \\brief Sets the iterator to the first edge incoming into or outgoing \n      /// from the node.\n      ///\n      /// Sets the iterator to the first edge incoming into or outgoing \n      /// from the node.\n      ///\n      explicit GraphIncIt(const _Graph&, const _Base&) {}\n      /// \\brief Invalid constructor \\& conversion.\n      ///\n      /// This constructor initializes the item to be invalid.\n      /// \\sa Invalid for more details.\n      GraphIncIt(Invalid) {}\n      /// \\brief Assign operator for iterators.\n      ///\n      /// The iterators are assignable. \n      ///\n      GraphIncIt& operator=(GraphIncIt const&) { return *this; }      \n      /// \\brief Next item.\n      ///\n      /// Assign the iterator to the next item.\n      ///\n      GraphIncIt& operator++() { return *this; }\n\n      /// \\brief Equality operator\n      ///\n      /// Two iterators are equal if and only if they point to the\n      /// same object or both are invalid.\n      bool operator==(const GraphIncIt&) const { return true;}\n\n      /// \\brief Inequality operator\n      ///\n      /// \\sa operator==(Node n)\n      ///\n      bool operator!=(const GraphIncIt&) const { return true;}\n\n      template <typename _GraphIncIt>\n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<GraphItem<_selector>, _GraphIncIt>();\n\t  _GraphIncIt it1(graph, node);\n\t  _GraphIncIt it2;\n\n\t  it2 = ++it1;\n\t  ++it2 = it1;\n\t  ++(++it1);\n\t  _Item e = it1;\n\t  e = it2;\n\n\t}\n\n\t_Item edge;\n\t_Base node;\n\t_Graph graph;\n\t_GraphIncIt it;\n      };\n    };\n\n\n    /// \\brief An empty iterable graph class.\n    ///\n    /// This class provides beside the core graph features\n    /// iterator based iterable interface for the graph structure.\n    /// This concept is part of the Graph concept.\n    template <typename _Base = BaseGraphComponent>\n    class IterableGraphComponent : public _Base {\n\n    public:\n    \n      typedef _Base Base;\n      typedef typename Base::Node Node;\n      typedef typename Base::Edge Edge;\n\n      typedef IterableGraphComponent Graph;\n\n      /// \\name Base iteration\n      /// \n      /// This interface provides functions for iteration on graph items\n      ///\n      /// @{  \n\n      /// \\brief Gives back the first node in the iterating order.\n      ///      \n      /// Gives back the first node in the iterating order.\n      ///     \n      void first(Node&) const {}\n\n      /// \\brief Gives back the next node in the iterating order.\n      ///\n      /// Gives back the next node in the iterating order.\n      ///     \n      void next(Node&) const {}\n\n      /// \\brief Gives back the first edge in the iterating order.\n      ///\n      /// Gives back the first edge in the iterating order.\n      ///     \n      void first(Edge&) const {}\n\n      /// \\brief Gives back the next edge in the iterating order.\n      ///\n      /// Gives back the next edge in the iterating order.\n      ///     \n      void next(Edge&) const {}\n\n\n      /// \\brief Gives back the first of the edges point to the given\n      /// node.\n      ///\n      /// Gives back the first of the edges point to the given node.\n      ///     \n      void firstIn(Edge&, const Node&) const {}\n\n      /// \\brief Gives back the next of the edges points to the given\n      /// node.\n      ///\n      /// Gives back the next of the edges points to the given node.\n      ///\n      void nextIn(Edge&) const {}\n\n      /// \\brief Gives back the first of the edges start from the\n      /// given node.\n      ///      \n      /// Gives back the first of the edges start from the given node.\n      ///     \n      void firstOut(Edge&, const Node&) const {}\n\n      /// \\brief Gives back the next of the edges start from the given\n      /// node.\n      ///\n      /// Gives back the next of the edges start from the given node.\n      ///     \n      void nextOut(Edge&) const {}\n\n      /// @}\n\n      /// \\name Class based iteration\n      /// \n      /// This interface provides functions for iteration on graph items\n      ///\n      /// @{\n\n      /// \\brief This iterator goes through each node.\n      ///\n      /// This iterator goes through each node.\n      ///\n      typedef GraphItemIt<Graph, Node> NodeIt;\n\n      /// \\brief This iterator goes through each node.\n      ///\n      /// This iterator goes through each node.\n      ///\n      typedef GraphItemIt<Graph, Edge> EdgeIt;\n\n      /// \\brief This iterator goes trough the incoming edges of a node.\n      ///\n      /// This iterator goes trough the \\e inccoming edges of a certain node\n      /// of a graph.\n      typedef GraphIncIt<Graph, Edge, Node, 'i'> InEdgeIt;\n\n      /// \\brief This iterator goes trough the outgoing edges of a node.\n      ///\n      /// This iterator goes trough the \\e outgoing edges of a certain node\n      /// of a graph.\n      typedef GraphIncIt<Graph, Edge, Node, 'o'> OutEdgeIt;\n\n      /// \\brief The base node of the iterator.\n      ///\n      /// Gives back the base node of the iterator.\n      /// It is always the target of the pointed edge.\n      Node baseNode(const InEdgeIt&) const { return INVALID; }\n\n      /// \\brief The running node of the iterator.\n      ///\n      /// Gives back the running node of the iterator.\n      /// It is always the source of the pointed edge.\n      Node runningNode(const InEdgeIt&) const { return INVALID; }\n\n      /// \\brief The base node of the iterator.\n      ///\n      /// Gives back the base node of the iterator.\n      /// It is always the source of the pointed edge.\n      Node baseNode(const OutEdgeIt&) const { return INVALID; }\n\n      /// \\brief The running node of the iterator.\n      ///\n      /// Gives back the running node of the iterator.\n      /// It is always the target of the pointed edge.\n      Node runningNode(const OutEdgeIt&) const { return INVALID; }\n\n      /// @}\n\n      template <typename _Graph> \n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<Base, _Graph>();\n\n          {\n            typename _Graph::Node node(INVALID);      \n            typename _Graph::Edge edge(INVALID);\n            {\n              graph.first(node);\n              graph.next(node);\n            }\n            {\n              graph.first(edge);\n              graph.next(edge);\n            }\n            {\n              graph.firstIn(edge, node);\n              graph.nextIn(edge);\n            }\n            {\n              graph.firstOut(edge, node);\n              graph.nextOut(edge);\n            }\n          }           \n\n          {\n            checkConcept<GraphItemIt<_Graph, typename _Graph::Edge>,\n              typename _Graph::EdgeIt >();\n            checkConcept<GraphItemIt<_Graph, typename _Graph::Node>,\n              typename _Graph::NodeIt >();\n            checkConcept<GraphIncIt<_Graph, typename _Graph::Edge, \n              typename _Graph::Node, 'i'>, typename _Graph::InEdgeIt>();\n            checkConcept<GraphIncIt<_Graph, typename _Graph::Edge, \n              typename _Graph::Node, 'o'>, typename _Graph::OutEdgeIt>();\n\n            typename _Graph::Node n;\n            typename _Graph::InEdgeIt ieit(INVALID);\n            typename _Graph::OutEdgeIt oeit(INVALID);\n            n = graph.baseNode(ieit);\n            n = graph.runningNode(ieit);\n            n = graph.baseNode(oeit);\n            n = graph.runningNode(oeit);\n            ignore_unused_variable_warning(n);\n          }\n        }\n\t\n\tconst _Graph& graph;\n\t\n      };\n    };\n\n    /// \\brief An empty iterable undirected graph class.\n    ///\n    /// This class provides beside the core graph features iterator\n    /// based iterable interface for the undirected graph structure.\n    /// This concept is part of the UGraph concept.\n    template <typename _Base = BaseUGraphComponent>\n    class IterableUGraphComponent : public IterableGraphComponent<_Base> {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::Node Node;\n      typedef typename Base::Edge Edge;\n      typedef typename Base::UEdge UEdge;\n\n    \n      typedef IterableUGraphComponent Graph;\n\n      /// \\name Base iteration\n      /// \n      /// This interface provides functions for iteration on graph items\n      /// @{  \n\n      using IterableGraphComponent<_Base>::first;\n      using IterableGraphComponent<_Base>::next;\n\n      /// \\brief Gives back the first undirected edge in the iterating\n      /// order.\n      ///\n      /// Gives back the first undirected edge in the iterating order.\n      ///     \n      void first(UEdge&) const {}\n\n      /// \\brief Gives back the next undirected edge in the iterating\n      /// order.\n      ///\n      /// Gives back the next undirected edge in the iterating order.\n      ///     \n      void next(UEdge&) const {}\n\n\n      /// \\brief Gives back the first of the undirected edges from the\n      /// given node.\n      ///\n      /// Gives back the first of the undirected edges from the given\n      /// node. The bool parameter gives back that direction which\n      /// gives a good direction of the uedge so the source of the\n      /// directed edge is the given node.\n      void firstInc(UEdge&, bool&, const Node&) const {}\n\n      /// \\brief Gives back the next of the undirected edges from the\n      /// given node.\n      ///\n      /// Gives back the next of the undirected edges from the given\n      /// node. The bool parameter should be used as the \\c firstInc()\n      /// use it.\n      void nextInc(UEdge&, bool&) const {}\n\n      using IterableGraphComponent<_Base>::baseNode;\n      using IterableGraphComponent<_Base>::runningNode;\n\n      /// @}\n\n      /// \\name Class based iteration\n      /// \n      /// This interface provides functions for iteration on graph items\n      ///\n      /// @{\n\n      /// \\brief This iterator goes through each node.\n      ///\n      /// This iterator goes through each node.\n      typedef GraphItemIt<Graph, UEdge> UEdgeIt;\n      /// \\brief This iterator goes trough the incident edges of a\n      /// node.\n      ///\n      /// This iterator goes trough the incident edges of a certain\n      /// node of a graph.\n      typedef GraphIncIt<Graph, UEdge, Node, 'u'> IncEdgeIt;\n      /// \\brief The base node of the iterator.\n      ///\n      /// Gives back the base node of the iterator.\n      Node baseNode(const IncEdgeIt&) const { return INVALID; }\n\n      /// \\brief The running node of the iterator.\n      ///\n      /// Gives back the running node of the iterator.\n      Node runningNode(const IncEdgeIt&) const { return INVALID; }\n\n      /// @}\n\n      template <typename _Graph> \n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<IterableGraphComponent<Base>, _Graph>();\n\n          {\n            typename _Graph::Node node(INVALID);\n            typename _Graph::UEdge uedge(INVALID);\n            bool dir;\n            {\n              graph.first(uedge);\n              graph.next(uedge);\n            }\n            {\n              graph.firstInc(uedge, dir, node);\n              graph.nextInc(uedge, dir);\n            }\n            \n          }\t\n  \n          {\n            checkConcept<GraphItemIt<_Graph, typename _Graph::UEdge>,\n              typename _Graph::UEdgeIt >();\n            checkConcept<GraphIncIt<_Graph, typename _Graph::UEdge, \n              typename _Graph::Node, 'u'>, typename _Graph::IncEdgeIt>();\n            \n            typename _Graph::Node n;\n            typename _Graph::IncEdgeIt ueit(INVALID);\n            n = graph.baseNode(ueit);\n            n = graph.runningNode(ueit);\n          }\n        }\n\t\n\tconst _Graph& graph;\n\t\n      };\n    };\n\n    /// \\brief An empty iterable bipartite undirected graph class.\n    ///\n    /// This class provides beside the core graph features iterator\n    /// based iterable interface for the bipartite undirected graph\n    /// structure. This concept is part of the BpUGraph concept.\n    template <typename _Base = BaseUGraphComponent>\n    class IterableBpUGraphComponent : public IterableUGraphComponent<_Base> {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::Node Node;\n      typedef typename Base::UEdge UEdge;\n    \n      typedef IterableBpUGraphComponent Graph;\n\n      /// \\name Base iteration\n      /// \n      /// This interface provides functions for iteration on graph items\n      /// @{  \n\n      using IterableUGraphComponent<_Base>::first;\n      using IterableUGraphComponent<_Base>::next;\n\n      /// \\brief Gives back the first A-node in the iterating order.\n      ///\n      /// Gives back the first undirected A-node in the iterating\n      /// order.\n      ///     \n      void firstANode(Node&) const {}\n\n      /// \\brief Gives back the next A-node in the iterating order.\n      ///\n      /// Gives back the next A-node in the iterating order.\n      ///     \n      void nextANode(Node&) const {}\n\n      /// \\brief Gives back the first B-node in the iterating order.\n      ///\n      /// Gives back the first undirected B-node in the iterating\n      /// order.\n      ///     \n      void firstBNode(Node&) const {}\n\n      /// \\brief Gives back the next B-node in the iterating order.\n      ///\n      /// Gives back the next B-node in the iterating order.\n      ///     \n      void nextBNode(Node&) const {}\n\n\n      /// \\brief Gives back the first of the undirected edges start\n      /// from the given A-node.\n      ///      \n      /// Gives back the first of the undirected edges start from the\n      /// given A-node.\n      void firstFromANode(UEdge&, const Node&) const {}\n\n      /// \\brief Gives back the next of the undirected edges start\n      /// from the given A-node.\n      ///      \n      /// Gives back the next of the undirected edges start from the\n      /// given A-node.\n      void nextFromANode(UEdge&) const {}\n\n      /// \\brief Gives back the first of the undirected edges start\n      /// from the given B-node.\n      ///      \n      /// Gives back the first of the undirected edges start from the\n      /// given B-node.\n      void firstFromBNode(UEdge&, const Node&) const {}\n\n      /// \\brief Gives back the next of the undirected edges start\n      /// from the given B-node.\n      ///      \n      /// Gives back the next of the undirected edges start from the\n      /// given B-node.\n      void nextFromBNode(UEdge&) const {}\n\n\n      /// @}\n\n      /// \\name Class based iteration\n      /// \n      /// This interface provides functions for iteration on graph items\n      ///\n      /// @{\n\n      /// \\brief This iterator goes through each A-node.\n      ///\n      /// This iterator goes through each A-node.\n      typedef GraphItemIt<Graph, Node> ANodeIt;\n\n      /// \\brief This iterator goes through each B-node.\n      ///\n      /// This iterator goes through each B-node.\n      typedef GraphItemIt<Graph, Node> BNodeIt;\n\n      /// @}\n\n      template <typename _Graph> \n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<IterableUGraphComponent<Base>, _Graph>();\n\n          {\n            typename _Graph::Node node(INVALID);\n            typename _Graph::UEdge uedge(INVALID);\n            graph.firstANode(node);\n            graph.nextANode(node);\n            graph.firstBNode(node);\n            graph.nextBNode(node);\n\n            graph.firstFromANode(uedge, node);\n            graph.nextFromANode(uedge);\n            graph.firstFromBNode(uedge, node);\n            graph.nextFromBNode(uedge);\n          }\n          {\n            checkConcept<GraphItemIt<_Graph, typename _Graph::Node>,\n              typename _Graph::ANodeIt >();\n            checkConcept<GraphItemIt<_Graph, typename _Graph::Node>,\n              typename _Graph::BNodeIt >();\n          }\n\n\t}\n\t\n\tconst _Graph& graph;\n\t\n      };\n    };\n\n    /// \\brief An empty alteration notifier graph class.\n    ///  \n    /// This class provides beside the core graph features alteration\n    /// notifier interface for the graph structure.  This implements\n    /// an observer-notifier pattern for each graph item. More\n    /// obsevers can be registered into the notifier and whenever an\n    /// alteration occured in the graph all the observers will\n    /// notified about it.\n    template <typename _Base = BaseGraphComponent>\n    class AlterableGraphComponent : public _Base {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::Node Node;\n      typedef typename Base::Edge Edge;\n\n\n      /// The node observer registry.\n      typedef AlterationNotifier<AlterableGraphComponent, Node> \n      NodeNotifier;\n      /// The edge observer registry.\n      typedef AlterationNotifier<AlterableGraphComponent, Edge> \n      EdgeNotifier;\n      \n      /// \\brief Gives back the node alteration notifier.\n      ///\n      /// Gives back the node alteration notifier.\n      NodeNotifier& notifier(Node) const {\n\treturn NodeNotifier();\n      }\n      \n      /// \\brief Gives back the edge alteration notifier.\n      ///\n      /// Gives back the edge alteration notifier.\n      EdgeNotifier& notifier(Edge) const {\n\treturn EdgeNotifier();\n      }\n\n      template <typename _Graph> \n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<Base, _Graph>();\n          typename _Graph::NodeNotifier& nn \n            = graph.notifier(typename _Graph::Node());\n\n          typename _Graph::EdgeNotifier& en \n            = graph.notifier(typename _Graph::Edge());\n          \n          ignore_unused_variable_warning(nn);\n          ignore_unused_variable_warning(en);\n\t}\n\t\n\tconst _Graph& graph;\n\t\n      };\n      \n    };\n\n    /// \\brief An empty alteration notifier undirected graph class.\n    ///  \n    /// This class provides beside the core graph features alteration\n    /// notifier interface for the graph structure.  This implements\n    /// an observer-notifier pattern for each graph item. More\n    /// obsevers can be registered into the notifier and whenever an\n    /// alteration occured in the graph all the observers will\n    /// notified about it.\n    template <typename _Base = BaseUGraphComponent>\n    class AlterableUGraphComponent : public AlterableGraphComponent<_Base> {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::UEdge UEdge;\n\n\n      /// The edge observer registry.\n      typedef AlterationNotifier<AlterableUGraphComponent, UEdge> \n      UEdgeNotifier;\n      \n      /// \\brief Gives back the edge alteration notifier.\n      ///\n      /// Gives back the edge alteration notifier.\n      UEdgeNotifier& notifier(UEdge) const {\n\treturn UEdgeNotifier();\n      }\n\n      template <typename _Graph> \n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<AlterableGraphComponent<Base>, _Graph>();\n          typename _Graph::UEdgeNotifier& uen \n            = graph.notifier(typename _Graph::UEdge());\n          ignore_unused_variable_warning(uen);\n\t}\n\t\n\tconst _Graph& graph;\n\t\n      };\n      \n    };\n\n    /// \\brief An empty alteration notifier bipartite undirected graph\n    /// class.\n    ///  \n    /// This class provides beside the core graph features alteration\n    /// notifier interface for the graph structure.  This implements\n    /// an observer-notifier pattern for each graph item. More\n    /// obsevers can be registered into the notifier and whenever an\n    /// alteration occured in the graph all the observers will\n    /// notified about it.\n    template <typename _Base = BaseUGraphComponent>\n    class AlterableBpUGraphComponent : public AlterableUGraphComponent<_Base> {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::ANode ANode;\n      typedef typename Base::BNode BNode;\n\n\n      /// The A-node observer registry.\n      typedef AlterationNotifier<AlterableBpUGraphComponent, ANode> \n      ANodeNotifier;\n\n      /// The B-node observer registry.\n      typedef AlterationNotifier<AlterableBpUGraphComponent, BNode> \n      BNodeNotifier;\n      \n      /// \\brief Gives back the A-node alteration notifier.\n      ///\n      /// Gives back the A-node alteration notifier.\n      ANodeNotifier& notifier(ANode) const {\n\treturn ANodeNotifier();\n      }\n\n      /// \\brief Gives back the B-node alteration notifier.\n      ///\n      /// Gives back the B-node alteration notifier.\n      BNodeNotifier& notifier(BNode) const {\n\treturn BNodeNotifier();\n      }\n\n      template <typename _Graph> \n      struct Constraints {\n\tvoid constraints() {\n          checkConcept<AlterableUGraphComponent<Base>, _Graph>();\n          typename _Graph::ANodeNotifier& ann \n            = graph.notifier(typename _Graph::ANode());\n          typename _Graph::BNodeNotifier& bnn \n            = graph.notifier(typename _Graph::BNode());\n          ignore_unused_variable_warning(ann);\n          ignore_unused_variable_warning(bnn);\n\t}\n\t\n\tconst _Graph& graph;\n\t\n      };\n      \n    };\n\n\n    /// \\brief Class describing the concept of graph maps\n    /// \n    /// This class describes the common interface of the graph maps\n    /// (NodeMap, EdgeMap), that is \\ref maps-page \"maps\" which can be used to\n    /// associate data to graph descriptors (nodes or edges).\n    template <typename _Graph, typename _Item, typename _Value>\n    class GraphMap : public ReadWriteMap<_Item, _Value> {\n    public:\n\n      typedef ReadWriteMap<_Item, _Value> Parent;\n\n      /// The graph type of the map.\n      typedef _Graph Graph;\n      /// The key type of the map.\n      typedef _Item Key;\n      /// The value type of the map.\n      typedef _Value Value;\n\n      /// \\brief Construct a new map.\n      ///\n      /// Construct a new map for the graph.\n      explicit GraphMap(const Graph&) {}\n      /// \\brief Construct a new map with default value.\n      ///\n      /// Construct a new map for the graph and initalise the values.\n      GraphMap(const Graph&, const Value&) {}\n      /// \\brief Copy constructor.\n      ///\n      /// Copy Constructor.\n      GraphMap(const GraphMap&) : Parent() {}\n      \n      /// \\brief Assign operator.\n      ///\n      /// Assign operator. It does not mofify the underlying graph,\n      /// it just iterates on the current item set and set the  map\n      /// with the value returned by the assigned map. \n      template <typename CMap>\n      GraphMap& operator=(const CMap&) { \n        checkConcept<ReadMap<Key, Value>, CMap>();\n        return *this;\n      }\n\n      template<typename _Map>\n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<ReadWriteMap<Key, Value>, _Map >();\n\t  // Construction with a graph parameter\n\t  _Map a(g);\n\t  // Constructor with a graph and a default value parameter\n\t  _Map a2(g,t);\n\t  // Copy constructor.\n\t  _Map b(c);\n          \n          ReadMap<Key, Value> cmap;\n          b = cmap;\n\n\t  ignore_unused_variable_warning(a2);\n\t  ignore_unused_variable_warning(b);\n\t}\n\n\tconst _Map &c;\n\tconst Graph &g;\n\tconst typename GraphMap::Value &t;\n      };\n\n    };\n\n    /// \\brief An empty mappable graph class.\n    ///\n    /// This class provides beside the core graph features\n    /// map interface for the graph structure.\n    /// This concept is part of the Graph concept.\n    template <typename _Base = BaseGraphComponent>\n    class MappableGraphComponent : public _Base  {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::Node Node;\n      typedef typename Base::Edge Edge;\n\n      typedef MappableGraphComponent Graph;\n\n      /// \\brief ReadWrite map of the nodes.\n      ///\n      /// ReadWrite map of the nodes.\n      ///\n      template <typename _Value>\n      class NodeMap : public GraphMap<Graph, Node, _Value> {\n      public:\n        typedef GraphMap<MappableGraphComponent, Node, _Value> Parent;\n\n\t/// \\brief Construct a new map.\n\t///\n\t/// Construct a new map for the graph.\n\texplicit NodeMap(const MappableGraphComponent& graph) \n          : Parent(graph) {}\n\n\t/// \\brief Construct a new map with default value.\n\t///\n\t/// Construct a new map for the graph and initalise the values.\n\tNodeMap(const MappableGraphComponent& graph, const _Value& value)\n          : Parent(graph, value) {}\n\n\t/// \\brief Copy constructor.\n\t///\n\t/// Copy Constructor.\n\tNodeMap(const NodeMap& nm) : Parent(nm) {}\n\n\t/// \\brief Assign operator.\n\t///\n\t/// Assign operator.\n        template <typename CMap>\n        NodeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Node, _Value>, CMap>();\n          return *this;\n        }\n\n      };\n\n      /// \\brief ReadWrite map of the edges.\n      ///\n      /// ReadWrite map of the edges.\n      ///\n      template <typename _Value>\n      class EdgeMap : public GraphMap<Graph, Edge, _Value> {\n      public:\n        typedef GraphMap<MappableGraphComponent, Edge, _Value> Parent;\n\n\t/// \\brief Construct a new map.\n\t///\n\t/// Construct a new map for the graph.\n\texplicit EdgeMap(const MappableGraphComponent& graph) \n          : Parent(graph) {}\n\n\t/// \\brief Construct a new map with default value.\n\t///\n\t/// Construct a new map for the graph and initalise the values.\n\tEdgeMap(const MappableGraphComponent& graph, const _Value& value)\n          : Parent(graph, value) {}\n\n\t/// \\brief Copy constructor.\n\t///\n\t/// Copy Constructor.\n\tEdgeMap(const EdgeMap& nm) : Parent(nm) {}\n\n\t/// \\brief Assign operator.\n\t///\n\t/// Assign operator.\n        template <typename CMap>\n        EdgeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Edge, _Value>, CMap>();\n          return *this;\n        }\n\n      };\n\n\n      template <typename _Graph>\n      struct Constraints {\n\n\tstruct Dummy {\n\t  int value;\n\t  Dummy() : value(0) {}\n\t  Dummy(int _v) : value(_v) {}\n\t};\n\n\tvoid constraints() {\n\t  checkConcept<Base, _Graph>();\n\t  { // int map test\n\t    typedef typename _Graph::template NodeMap<int> IntNodeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::Node, int>, \n\t      IntNodeMap >();\n\t  } { // bool map test\n\t    typedef typename _Graph::template NodeMap<bool> BoolNodeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::Node, bool>,\n\t      BoolNodeMap >();\n\t  } { // Dummy map test\n\t    typedef typename _Graph::template NodeMap<Dummy> DummyNodeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::Node, Dummy>,\n\t      DummyNodeMap >();\n\t  } \n\n\t  { // int map test\n\t    typedef typename _Graph::template EdgeMap<int> IntEdgeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::Edge, int>,\n\t      IntEdgeMap >();\n\t  } { // bool map test\n\t    typedef typename _Graph::template EdgeMap<bool> BoolEdgeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::Edge, bool>,\n\t      BoolEdgeMap >();\n\t  } { // Dummy map test\n\t    typedef typename _Graph::template EdgeMap<Dummy> DummyEdgeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::Edge, Dummy>, \n\t      DummyEdgeMap >();\n\t  } \n\t}\n\n\t_Graph& graph;\n      };\n    };\n\n    /// \\brief An empty mappable base bipartite undirected graph class.\n    ///\n    /// This class provides beside the core graph features\n    /// map interface for the graph structure.\n    /// This concept is part of the UGraph concept.\n    template <typename _Base = BaseUGraphComponent>\n    class MappableUGraphComponent : public MappableGraphComponent<_Base>  {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::UEdge UEdge;\n\n      typedef MappableUGraphComponent Graph;\n\n      /// \\brief ReadWrite map of the uedges.\n      ///\n      /// ReadWrite map of the uedges.\n      ///\n      template <typename _Value>\n      class UEdgeMap : public GraphMap<Graph, UEdge, _Value> {  \n      public:\n        typedef GraphMap<MappableUGraphComponent, UEdge, _Value> Parent;\n\n\t/// \\brief Construct a new map.\n\t///\n\t/// Construct a new map for the graph.\n\texplicit UEdgeMap(const MappableUGraphComponent& graph) \n          : Parent(graph) {}\n\n\t/// \\brief Construct a new map with default value.\n\t///\n\t/// Construct a new map for the graph and initalise the values.\n\tUEdgeMap(const MappableUGraphComponent& graph, const _Value& value)\n          : Parent(graph, value) {}\n\n\t/// \\brief Copy constructor.\n\t///\n\t/// Copy Constructor.\n\tUEdgeMap(const UEdgeMap& nm) : Parent(nm) {}\n\n\t/// \\brief Assign operator.\n\t///\n\t/// Assign operator.\n        template <typename CMap>\n        UEdgeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<UEdge, _Value>, CMap>();\n          return *this;\n        }\n\n      };\n\n\n      template <typename _Graph>\n      struct Constraints {\n\n\tstruct Dummy {\n\t  int value;\n\t  Dummy() : value(0) {}\n\t  Dummy(int _v) : value(_v) {}\n\t};\n\n\tvoid constraints() {\n\t  checkConcept<MappableGraphComponent<Base>, _Graph>();\n\n\t  { // int map test\n\t    typedef typename _Graph::template UEdgeMap<int> IntUEdgeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::UEdge, int>,\n\t      IntUEdgeMap >();\n\t  } { // bool map test\n\t    typedef typename _Graph::template UEdgeMap<bool> BoolUEdgeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::UEdge, bool>,\n\t      BoolUEdgeMap >();\n\t  } { // Dummy map test\n\t    typedef typename _Graph::template UEdgeMap<Dummy> DummyUEdgeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::UEdge, Dummy>, \n\t      DummyUEdgeMap >();\n\t  } \n\t}\n\n\t_Graph& graph;\n      };\n    };\n\n    /// \\brief An empty mappable base bipartite undirected graph\n    /// class.\n    ///\n    /// This class provides beside the core graph features\n    /// map interface for the graph structure.\n    /// This concept is part of the BpUGraph concept.\n    template <typename _Base = BaseBpUGraphComponent>\n    class MappableBpUGraphComponent : public MappableUGraphComponent<_Base>  {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::Node Node;\n\n      typedef MappableBpUGraphComponent Graph;\n\n      /// \\brief ReadWrite map of the A-nodes.\n      ///\n      /// ReadWrite map of the A-nodes.\n      ///\n      template <typename _Value>\n      class ANodeMap : public GraphMap<Graph, Node, _Value> {  \n      public:\n        typedef GraphMap<MappableBpUGraphComponent, Node, _Value> Parent;\n\n\t/// \\brief Construct a new map.\n\t///\n\t/// Construct a new map for the graph.\n\texplicit ANodeMap(const MappableBpUGraphComponent& graph) \n          : Parent(graph) {}\n\n\t/// \\brief Construct a new map with default value.\n\t///\n\t/// Construct a new map for the graph and initalise the values.\n\tANodeMap(const MappableBpUGraphComponent& graph, const _Value& value)\n          : Parent(graph, value) {}\n\n\t/// \\brief Copy constructor.\n\t///\n\t/// Copy Constructor.\n\tANodeMap(const ANodeMap& nm) : Parent(nm) {}\n\n\t/// \\brief Assign operator.\n\t///\n\t/// Assign operator.\n        template <typename CMap>\n        ANodeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Node, _Value>, CMap>();\n          return *this;\n        }\n\n      };\n\n      /// \\brief ReadWrite map of the B-nodes.\n      ///\n      /// ReadWrite map of the A-nodes.\n      ///\n      template <typename _Value>\n      class BNodeMap : public GraphMap<Graph, Node, _Value> {  \n      public:\n        typedef GraphMap<MappableBpUGraphComponent, Node, _Value> Parent;\n\n\t/// \\brief Construct a new map.\n\t///\n\t/// Construct a new map for the graph.\n\texplicit BNodeMap(const MappableBpUGraphComponent& graph) \n          : Parent(graph) {}\n\n\t/// \\brief Construct a new map with default value.\n\t///\n\t/// Construct a new map for the graph and initalise the values.\n\tBNodeMap(const MappableBpUGraphComponent& graph, const _Value& value)\n          : Parent(graph, value) {}\n\n\t/// \\brief Copy constructor.\n\t///\n\t/// Copy Constructor.\n\tBNodeMap(const BNodeMap& nm) : Parent(nm) {}\n\n\t/// \\brief Assign operator.\n\t///\n\t/// Assign operator.\n        template <typename CMap>\n        BNodeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Node, _Value>, CMap>();\n          return *this;\n        }\n\n      };\n\n\n      template <typename _Graph>\n      struct Constraints {\n\n\tstruct Dummy {\n\t  int value;\n\t  Dummy() : value(0) {}\n\t  Dummy(int _v) : value(_v) {}\n\t};\n\n\tvoid constraints() {\n\t  checkConcept<MappableUGraphComponent<Base>, _Graph>();\n\n\t  { // int map test\n\t    typedef typename _Graph::template ANodeMap<int> IntANodeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::ANode, int>,\n\t      IntANodeMap >();\n\t  } { // bool map test\n\t    typedef typename _Graph::template ANodeMap<bool> BoolANodeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::ANode, bool>,\n\t      BoolANodeMap >();\n\t  } { // Dummy map test\n\t    typedef typename _Graph::template ANodeMap<Dummy> DummyANodeMap;\n\t    checkConcept<GraphMap<_Graph, typename _Graph::ANode, Dummy>, \n\t      DummyANodeMap >();\n\t  } \n\t}\n\n\t_Graph& graph;\n      };\n    };\n\n\n    /// \\brief An empty extendable graph class.\n    ///\n    /// This class provides beside the core graph features graph\n    /// extendable interface for the graph structure.  The main\n    /// difference between the base and this interface is that the\n    /// graph alterations should handled already on this level.\n    template <typename _Base = BaseGraphComponent>\n    class ExtendableGraphComponent : public _Base {\n    public:\n      typedef _Base Base;\n\n      typedef typename _Base::Node Node;\n      typedef typename _Base::Edge Edge;\n\n      /// \\brief Adds a new node to the graph.\n      ///\n      /// Adds a new node to the graph.\n      ///\n      Node addNode() {\n\treturn INVALID;\n      }\n    \n      /// \\brief Adds a new edge connects the given two nodes.\n      ///\n      /// Adds a new edge connects the the given two nodes.\n      Edge addEdge(const Node&, const Node&) {\n\treturn INVALID;\n      }\n\n      template <typename _Graph>\n      struct Constraints {\n\tvoid constraints() {\n          checkConcept<Base, _Graph>();\n\t  typename _Graph::Node node_a, node_b;\n\t  node_a = graph.addNode();\n\t  node_b = graph.addNode();\n\t  typename _Graph::Edge edge;\n\t  edge = graph.addEdge(node_a, node_b);\n\t}\n\n\t_Graph& graph;\n      };\n    };\n\n    /// \\brief An empty extendable base undirected graph class.\n    ///\n    /// This class provides beside the core undirected graph features\n    /// core undircted graph extend interface for the graph structure.\n    /// The main difference between the base and this interface is\n    /// that the graph alterations should handled already on this\n    /// level.\n    template <typename _Base = BaseUGraphComponent>\n    class ExtendableUGraphComponent : public _Base {\n    public:\n\n      typedef _Base Base;\n      typedef typename _Base::Node Node;\n      typedef typename _Base::UEdge UEdge;\n\n      /// \\brief Adds a new node to the graph.\n      ///\n      /// Adds a new node to the graph.\n      ///\n      Node addNode() {\n\treturn INVALID;\n      }\n    \n      /// \\brief Adds a new edge connects the given two nodes.\n      ///\n      /// Adds a new edge connects the the given two nodes.\n      UEdge addEdge(const Node&, const Node&) {\n\treturn INVALID;\n      }\n\n      template <typename _Graph>\n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<Base, _Graph>();\n\t  typename _Graph::Node node_a, node_b;\n\t  node_a = graph.addNode();\n\t  node_b = graph.addNode();\n\t  typename _Graph::UEdge uedge;\n\t  uedge = graph.addUEdge(node_a, node_b);\n\t}\n\n\t_Graph& graph;\n      };\n    };\n\n    /// \\brief An empty extendable base undirected graph class.\n    ///\n    /// This class provides beside the core bipartite undirected graph\n    /// features core undircted graph extend interface for the graph\n    /// structure.  The main difference between the base and this\n    /// interface is that the graph alterations should handled already\n    /// on this level.\n    template <typename _Base = BaseBpUGraphComponent>\n    class ExtendableBpUGraphComponent \n      : public ExtendableUGraphComponent<_Base> {\n\n      typedef _Base Base;\n\n      template <typename _Graph>\n      struct Constraints {\n\tvoid constraints() {\n          checkConcept<ExtendableUGraphComponent<Base>, _Graph>();\n\t}\n      };\n    };\n\n    /// \\brief An empty erasable graph class.\n    ///  \n    /// This class provides beside the core graph features core erase\n    /// functions for the graph structure. The main difference between\n    /// the base and this interface is that the graph alterations\n    /// should handled already on this level.\n    template <typename _Base = BaseGraphComponent>\n    class ErasableGraphComponent : public _Base {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::Node Node;\n      typedef typename Base::Edge Edge;\n\n      /// \\brief Erase a node from the graph.\n      ///\n      /// Erase a node from the graph. This function should \n      /// erase all edges connecting to the node.\n      void erase(const Node&) {}    \n\n      /// \\brief Erase an edge from the graph.\n      ///\n      /// Erase an edge from the graph.\n      ///\n      void erase(const Edge&) {}\n\n      template <typename _Graph>\n      struct Constraints {\n\tvoid constraints() {\n          checkConcept<Base, _Graph>();\n\t  typename _Graph::Node node;\n\t  graph.erase(node);\n\t  typename _Graph::Edge edge;\n\t  graph.erase(edge);\n\t}\n\n\t_Graph& graph;\n      };\n    };\n\n    /// \\brief An empty erasable base undirected graph class.\n    ///  \n    /// This class provides beside the core undirected graph features\n    /// core erase functions for the undirceted graph structure. The\n    /// main difference between the base and this interface is that\n    /// the graph alterations should handled already on this level.\n    template <typename _Base = BaseUGraphComponent>\n    class ErasableUGraphComponent : public _Base {\n    public:\n\n      typedef _Base Base;\n      typedef typename Base::Node Node;\n      typedef typename Base::UEdge UEdge;\n\n      /// \\brief Erase a node from the graph.\n      ///\n      /// Erase a node from the graph. This function should erase\n      /// edges connecting to the node.\n      void erase(const Node&) {}    \n\n      /// \\brief Erase an edge from the graph.\n      ///\n      /// Erase an edge from the graph.\n      ///\n      void erase(const UEdge&) {}\n\n      template <typename _Graph>\n      struct Constraints {\n\tvoid constraints() {\n          checkConcept<Base, _Graph>();\n\t  typename _Graph::Node node;\n\t  graph.erase(node);\n\t  typename _Graph::Edge edge;\n\t  graph.erase(edge);\n\t}\n\n\t_Graph& graph;\n      };\n    };\n\n    /// \\brief An empty erasable base bipartite undirected graph class.\n    ///  \n    /// This class provides beside the core bipartite undirected graph\n    /// features core erase functions for the undirceted graph\n    /// structure. The main difference between the base and this\n    /// interface is that the graph alterations should handled already\n    /// on this level.\n    template <typename _Base = BaseBpUGraphComponent>\n    class ErasableBpUGraphComponent : public ErasableUGraphComponent<_Base> {\n    public:\n\n      typedef _Base Base;\n\n      template <typename _Graph>\n      struct Constraints {\n\tvoid constraints() {\n          checkConcept<ErasableUGraphComponent<Base>, _Graph>();\n\t}\n      };\n    };\n\n    /// \\brief An empty clearable base graph class.\n    ///\n    /// This class provides beside the core graph features core clear\n    /// functions for the graph structure. The main difference between\n    /// the base and this interface is that the graph alterations\n    /// should handled already on this level.\n    template <typename _Base = BaseGraphComponent>\n    class ClearableGraphComponent : public _Base {\n    public:\n\n      typedef _Base Base;\n\n      /// \\brief Erase all nodes and edges from the graph.\n      ///\n      /// Erase all nodes and edges from the graph.\n      ///\n      void clear() {}    \n\n      template <typename _Graph>\n      struct Constraints {\n\tvoid constraints() {\n          checkConcept<Base, _Graph>();\n\t  graph.clear();\n\t}\n\n\t_Graph graph;\n      };\n    };\n\n    /// \\brief An empty clearable base undirected graph class.\n    ///\n    /// This class provides beside the core undirected graph features\n    /// core clear functions for the undirected graph structure. The\n    /// main difference between the base and this interface is that\n    /// the graph alterations should handled already on this level.\n    template <typename _Base = BaseUGraphComponent>\n    class ClearableUGraphComponent : public ClearableGraphComponent<_Base> {\n    public:\n\n      typedef _Base Base;\n\n      template <typename _Graph>\n      struct Constraints {\n\tvoid constraints() {\n          checkConcept<ClearableUGraphComponent<Base>, _Graph>();\n\t}\n\n\t_Graph graph;\n      };\n    };\n\n    /// \\brief An empty clearable base bipartite undirected graph\n    /// class.\n    ///\n    /// This class provides beside the core bipartite undirected graph\n    /// features core clear functions for the undirected graph\n    /// structure. The main difference between the base and this\n    /// interface is that the graph alterations should handled already\n    /// on this level.\n    template <typename _Base = BaseUGraphComponent>\n    class ClearableBpUGraphComponent : public ClearableUGraphComponent<_Base> {\n    public:\n\n      typedef _Base Base;\n\n      template <typename _Graph>\n      struct Constraints {\n\tvoid constraints() {\n          checkConcept<ClearableBpUGraphComponent<Base>, _Graph>();\n\t}\n\n      };\n\n    };\n\n  }\n\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/concepts/heap.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n///\\ingroup concept\n///\\file\n///\\brief Classes for representing heaps.\n///\n\n#ifndef LEMON_CONCEPT_HEAP_H\n#define LEMON_CONCEPT_HEAP_H\n\n#include <lemon/bits/invalid.h>\n\nnamespace lemon {\n  namespace concepts {\n    /// \\addtogroup concept\n    /// @{\n\n\n    /// \\brief A concept structure describes the main interface of heaps.\n    ///\n    /// A concept structure describes the main interface of heaps.\n    ///\n    template <typename Prio, typename ItemIntMap>\n    class Heap {\n    public:\n\n      ///\\brief Type of the items stored in the heap.\n      typedef typename ItemIntMap::Key  Item;\n  \n\n      /// \\brief Type to represent the items states.\n      ///\n      /// Each Item element have a state associated to it. It may be \"in heap\",\n      /// \"pre heap\" or \"post heap\". The later two are indifferent from the\n      /// heap's point of view, but may be useful to the user.\n      ///\n      /// The ItemIntMap _should_ be initialized in such way, that it maps\n      /// PRE_HEAP (-1) to any element to be put in the heap...\n      enum State {\n\tIN_HEAP = 0,\n\tPRE_HEAP = -1,\n\tPOST_HEAP = -2\n      };\n      \n      /// \\brief The constructor.\n      ///\n      /// The constructor.\n      /// \\param _iim should be given to the constructor, since it is used\n      /// internally to handle the cross references. The value of the map\n      /// should be PRE_HEAP (-1) for each element.\n      explicit Heap(ItemIntMap &_iim) {}\n\n      /// \\brief The number of items stored in the heap.\n      ///\n      /// Returns the number of items stored in the heap.\n      int size() const { return 0; }\n\n      /// \\brief Checks if the heap stores no items.\n      ///\n      /// Returns \\c true if and only if the heap stores no items.\n      bool empty() const { return false; }\n\n      /// \\brief Makes empty this heap.\n      ///\n      /// Makes this heap empty.\n      void clear();\n\n      /// \\brief Insert an item into the heap with the given heap.\n      ///    \n      /// Adds \\c i to the heap with priority \\c p. \n      /// \\param i The item to insert.\n      /// \\param p The priority of the item.\n      void push(const Item &i, const Prio &p) {}\n\n      /// \\brief Returns the item with minimum priority.\n      ///\n      /// This method returns the item with minimum priority.  \n      /// \\pre The heap must be nonempty.  \n      Item top() const {}\n\n      /// \\brief Returns the minimum priority.\n      ///\n      /// It returns the minimum priority.\n      /// \\pre The heap must be nonempty.\n      Prio prio() const {}\n\n      /// \\brief Deletes the item with minimum priority.\n      ///\n      /// This method deletes the item with minimum priority.\n      /// \\pre The heap must be non-empty.  \n      void pop() {}\n\n      /// \\brief Deletes \\c i from the heap.\n      ///\n      /// This method deletes item \\c i from the heap, if \\c i was\n      /// already stored in the heap.\n      /// \\param i The item to erase. \n      void erase(const Item &i) {}\n\n      /// \\brief Returns the priority of \\c i.\n      ///\n      /// This function returns the priority of item \\c i.  \n      /// \\pre \\c i must be in the heap.\n      /// \\param i The item.\n      Prio operator[](const Item &i) const {}\n\n      /// \\brief \\c i gets to the heap with priority \\c p independently \n      /// if \\c i was already there.\n      ///\n      /// This method calls \\ref push(\\c i, \\c p) if \\c i is not stored\n      /// in the heap and sets the priority of \\c i to \\c p otherwise.\n      /// It may throw an \\e UnderFlowPriorityException. \n      /// \\param i The item.\n      /// \\param p The priority.\n      void set(const Item &i, const Prio &p) {}\n      \n      /// \\brief Decreases the priority of \\c i to \\c p.\n      ///\n      /// This method decreases the priority of item \\c i to \\c p.\n      /// \\pre \\c i must be stored in the heap with priority at least \\c p.\n      /// \\param i The item.\n      /// \\param p The priority.\n      void decrease(const Item &i, const Prio &p) {}\n\n      /// \\brief Increases the priority of \\c i to \\c p.\n      ///\n      /// This method sets the priority of item \\c i to \\c p. \n      /// \\pre \\c i must be stored in the heap with priority at most \\c\n      /// p relative to \\c Compare.\n      /// \\param i The item.\n      /// \\param p The priority.\n      void increase(const Item &i, const Prio &p) {}\n\n      /// \\brief Returns if \\c item is in, has already been in, or has \n      /// never been in the heap.\n      ///\n      /// This method returns PRE_HEAP if \\c item has never been in the\n      /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP\n      /// otherwise. In the latter case it is possible that \\c item will\n      /// get back to the heap again.\n      /// \\param i The item.\n      State state(const Item &i) const {}\n\n      /// \\brief Sets the state of the \\c item in the heap.\n      ///\n      /// Sets the state of the \\c item in the heap. It can be used to\n      /// manually clear the heap when it is important to achive the\n      /// better time complexity.\n      /// \\param i The item.\n      /// \\param st The state. It should not be \\c IN_HEAP. \n      void state(const Item& i, State st) {}\n\n\n      template <typename _Heap>\n      struct Constraints {\n      public:\n    \n\tvoid constraints() {\n\t  Item item;\n\t  Prio prio;\n\n\t  item=Item();\n\t  prio=Prio();\n\n\t  ignore_unused_variable_warning(item);\n\t  ignore_unused_variable_warning(prio);\n\n\t  typedef typename _Heap::State State;\n\t  State state;\n\n\t  ignore_unused_variable_warning(state);\n      \n\t  _Heap heap1 = _Heap(map);\n\n\t  ignore_unused_variable_warning(heap1);\n      \n\t  heap.push(item, prio);\n\n\t  prio = heap.prio();\n\t  item = heap.top();\n\n\t  heap.pop();\n\n\t  heap.set(item, prio);\n\t  heap.decrease(item, prio);\n\t  heap.increase(item, prio);\n\t  prio = heap[item];\n\n\t  heap.erase(item);\n\n\t  state = heap.state(item);\n\n\t  state = _Heap::PRE_HEAP;\n\t  state = _Heap::IN_HEAP;\n\t  state = _Heap::POST_HEAP;\n\n\t  heap.clear();\n\t}\n    \n\t_Heap& heap;\n\tItemIntMap& map;\n\n\tConstraints() : heap(0), map(0) {}\n      };\n    };\n\n    /// @}\n  } // namespace lemon\n}\n#endif // LEMON_CONCEPT_PATH_H\n"
  },
  {
    "path": "src/lemon/concepts/maps.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_CONCEPT_MAPS_H\n#define LEMON_CONCEPT_MAPS_H\n\n#include <lemon/bits/utility.h>\n#include <lemon/concept_check.h>\n\n///\\ingroup concept\n///\\file\n///\\brief Map concepts checking classes for testing and documenting.\n\nnamespace lemon {\n\t\n\tnamespace concepts {\n\t\t\n\t\t/// \\addtogroup concept\n\t\t/// @{\n\t\t\n\t\t/// Readable map concept\n\t\t\n\t\t/// Readable map concept.\n\t\t///\n\t\ttemplate<typename K, typename T>\n\t\tclass ReadMap\n\t\t\t{\n\t\t\tpublic:\n\t\t\t\t/// The key type of the map.\n\t\t\t\ttypedef K Key;    \n\t\t\t\t/// The value type of the map. (The type of objects associated with the keys).\n\t\t\t\ttypedef T Value;\n\t\t\t\t\n\t\t\t\t/// Returns the value associated with a key.\n\t\t\t\t\n\t\t\t\t/// Returns the value associated with a key.\n\t\t\t\t/// \\bug Value shouldn't need to be default constructible.\n\t\t\t\t///\n\t\t\t\tValue operator[](const Key &) const {return Value();}\n\t\t\t\t\n\t\t\t\ttemplate<typename _ReadMap>\n\t\t\t\tstruct Constraints {\n\t\t\t\t\t\n\t\t\t\t\tvoid constraints() {\n\t\t\t\t\t\tValue val = m[key];\n\t\t\t\t\t\tval = m[key];\n\t\t\t\t\t\ttypename _ReadMap::Value own_val = m[own_key]; \n\t\t\t\t\t\town_val = m[own_key]; \n\t\t\t\t\t\t\n\t\t\t\t\t\tignore_unused_variable_warning(val);\n\t\t\t\t\t\tignore_unused_variable_warning(own_val);\n\t\t\t\t\t\tignore_unused_variable_warning(key);\n\t\t\t\t\t}\n\t\t\t\t\tKey& key;\n\t\t\t\t\ttypename _ReadMap::Key& own_key;\n\t\t\t\t\t_ReadMap& m;\n\t\t\t\t};\n\t\t\t\t\n\t\t\t};\n\t\t\n\t\t\n\t\t/// Writable map concept\n\t\t\n\t\t/// Writable map concept.\n\t\t///\n\t\ttemplate<typename K, typename T>\n\t\tclass WriteMap\n\t\t\t{\n\t\t\tpublic:\n\t\t\t\t/// The key type of the map.\n\t\t\t\ttypedef K Key;    \n\t\t\t\t/// The value type of the map. (The type of objects associated with the keys).\n\t\t\t\ttypedef T Value;\n\t\t\t\t\n\t\t\t\t/// Sets the value associated with a key.\n\t\t\t\tvoid set(const Key &,const Value &) {}\n\t\t\t\t\n\t\t\t\t///Default constructor\n\t\t\t\tWriteMap() {}\n\t\t\t\t\n\t\t\t\ttemplate <typename _WriteMap>\n\t\t\t\tstruct Constraints {\n\t\t\t\t\tvoid constraints() {\n\t\t\t\t\t\t// No constraints for constructor.\n\t\t\t\t\t\tm.set(key, val);\n\t\t\t\t\t\tm.set(own_key, own_val);\n\t\t\t\t\t\tignore_unused_variable_warning(key);\n\t\t\t\t\t\tignore_unused_variable_warning(val);\n\t\t\t\t\t\tignore_unused_variable_warning(own_key);\n\t\t\t\t\t\tignore_unused_variable_warning(own_val);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tValue& val;\n\t\t\t\t\ttypename _WriteMap::Value own_val;\n\t\t\t\t\tKey& key;\n\t\t\t\t\ttypename _WriteMap::Key& own_key;\n\t\t\t\t\t_WriteMap& m;\n\t\t\t\t\t\n\t\t\t\t};\n\t\t\t};\n\t\t\n\t\t/// Read/writable map concept\n\t\t\n\t\t/// Read/writable map concept.\n\t\t///\n\t\ttemplate<typename K, typename T>\n\t\tclass ReadWriteMap : public ReadMap<K,T>,\n\t\tpublic WriteMap<K,T>\n\t\t{\n\t\tpublic:\n\t\t\t/// The key type of the map.\n\t\t\ttypedef K Key;    \n\t\t\t/// The value type of the map. (The type of objects associated with the keys).\n\t\t\ttypedef T Value;\n\t\t\t\n\t\t\t/// Returns the value associated with a key.\n\t\t\tValue operator[](const Key &) const {return Value();}\n\t\t\t/// Sets the value associated with a key.\n\t\t\tvoid set(const Key & ,const Value &) {}\n\t\t\t\n\t\t\ttemplate<typename _ReadWriteMap>\n\t\t\tstruct Constraints {\n\t\t\t\tvoid constraints() {\n\t\t\t\t\tcheckConcept<ReadMap<K, T>, _ReadWriteMap >();\n\t\t\t\t\tcheckConcept<WriteMap<K, T>, _ReadWriteMap >();\n\t\t\t\t}\n\t\t\t};\n\t\t};\n\t\t\n\t\t\n\t\t///Dereferable map concept\n\t\t\n\t\t/// Dereferable map concept.\n\t\t///\n\t\t/// \\todo Rethink this concept.\n\t\ttemplate<typename K, typename T, typename R, typename CR>\n\t\tclass ReferenceMap : public ReadWriteMap<K,T>\n\t\t{\n\t\tpublic:\n\t\t\t/// Tag for reference maps.\n\t\t\ttypedef True ReferenceMapTag;\n\t\t\t/// The key type of the map.\n\t\t\ttypedef K Key;    \n\t\t\t/// The value type of the map. (The type of objects associated with the keys).\n\t\t\ttypedef T Value;\n\t\t\t/// The reference type of the map.\n\t\t\ttypedef R Reference;\n\t\t\t/// The const reference type of the map.\n\t\t\ttypedef CR ConstReference;\n\t\t\t\n\t\tprotected:\n\t\t\tValue tmp;\n\t\tpublic:\n\t\t\t\n\t\t\t///Returns a reference to the value associated with a key.\n\t\t\tReference operator[](const Key &) { return tmp; }\n\t\t\t///Returns a const reference to the value associated with a key.\n\t\t\tConstReference operator[](const Key &) const { return tmp; }\n\t\t\t/// Sets the value associated with a key.\n\t\t\tvoid set(const Key &k,const Value &t) { operator[](k)=t; }\n\t\t\t\n\t\t\ttemplate<typename _ReferenceMap>\n\t\t\tstruct Constraints {\n\t\t\t\t\n\t\t\t\tvoid constraints() {\n\t\t\t\t\tcheckConcept<ReadWriteMap<K, T>, _ReferenceMap >();\n\t\t\t\t\tm[key] = val;\n\t\t\t\t\tval  = m[key];\n\t\t\t\t\tm[key] = ref;\n\t\t\t\t\tref = m[key];\n\t\t\t\t\tm[own_key] = own_val;\n\t\t\t\t\town_val  = m[own_key];\n\t\t\t\t\tm[own_key] = own_ref;\n\t\t\t\t\town_ref = m[own_key];\t  \t  \n\t\t\t\t}\n\t\t\t\t\n\t\t\t\ttypename _ReferenceMap::Key& own_key;\n\t\t\t\ttypename _ReferenceMap::Value& own_val;\n\t\t\t\ttypename _ReferenceMap::Reference own_ref;\n\t\t\t\tKey& key;\n\t\t\t\tValue& val;\n\t\t\t\tReference ref;\n\t\t\t\t_ReferenceMap& m;\n\t\t\t};\n\t\t};\n\t\t\n\t\t// @}\n\t\t\n\t} //namespace concepts\n\t\n} //namespace lemon\n\n#endif // LEMON_CONCEPT_MAPS_H\n"
  },
  {
    "path": "src/lemon/concepts/matrix_maps.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_CONCEPT_MATRIX_MAPS_H\n#define LEMON_CONCEPT_MATRIX_MAPS_H\n\n#include <lemon/bits/utility.h>\n#include <lemon/concept_check.h>\n\n///\\ingroup concept\n///\\file\n///\\brief MatrixMap concepts checking classes for testing and documenting.\n\nnamespace lemon {\n\n  namespace concepts {\n  \n    /// \\addtogroup concept\n    /// @{\n\n    /// Readable matrix map concept\n    template <typename K1, typename K2, typename V>\n    class ReadMatrixMap\n    {\n    public:\n      /// Map's first key type.\n      typedef K1 FirstKey;    \n      /// Map's second key type.\n      typedef K2 SecondKey;    \n      /// \\brief Map's value type. \n      /// (The type of objects associated with the pairs of keys).\n      typedef V Value;\n\n      // \\bug Value don't need to be default constructible.\n      /// Returns the value associated with a key.\n      Value operator()(const FirstKey&, const SecondKey&) const {\n\treturn Value();\n      }\n\n      template <typename _ReadMatrixMap>\n      struct Constraints {\n\n\tvoid constraints() {\n\t  Value val = m(first_key, second_key);\n\t  val = m(first_key, second_key);\n\t  typename _ReadMatrixMap::Value own_val = \n\t    m(own_first_key, own_second_key); \n\t  own_val = m(own_first_key, own_second_key);\n\t  ignore_unused_variable_warning(val);\n\t  ignore_unused_variable_warning(own_val);\n\t}\n\n\tFirstKey& first_key;\n\tSecondKey& second_key;\t\n\ttypename _ReadMatrixMap::FirstKey& own_first_key;\n\ttypename _ReadMatrixMap::SecondKey& own_second_key;\n\t_ReadMatrixMap& m;\n      };\n      \n    };\n\n\n    /// Writable map concept\n    template <typename K1, typename K2, typename V>\n    class WriteMatrixMap {\n    public:\n      /// Map's first key type.\n      typedef K1 FirstKey;    \n      /// Map's second key type.\n      typedef K2 SecondKey;    \n      /// \\brief Map's value type. \n      /// (The type of objects associated with the pairs of keys).\n      typedef V Value;\n\n      /// Sets the value associated with the pair of keys.\n      void set(const FirstKey&, const SecondKey& ,const Value&) {}\n\n      template <typename _WriteMatrixMap>\n      struct Constraints {\n\tvoid constraints() {\n\t  // No constraints for constructor.\n\t  m.set(first_key, second_key, val);\n\t  m.set(own_first_key, own_second_key, own_val);\n\t}\n\n\tValue& val;\n\ttypename _WriteMatrixMap::Value own_val;\n\tFirstKey& first_key;\n\tSecondKey& second_key;\n\ttypename _WriteMatrixMap::FirstKey& own_first_key;\n\ttypename _WriteMatrixMap::SecondKey& own_second_key;\n\t_WriteMatrixMap& m;\n\n      };\n    };\n\n    ///Read/Writable map concept\n    template<typename K1, typename K2, typename V>\n    class ReadWriteMatrixMap \n      : public ReadMatrixMap<K1, K2, V>, public WriteMatrixMap<K1, K2, V> {\n    public:\n      /// Map's first key type.\n      typedef K1 FirstKey;    \n      /// Map's second key type.\n      typedef K2 SecondKey;    \n      /// \\brief Map's value type. \n      /// (The type of objects associated with the pairs of keys).\n      typedef V Value;\n\n      /// Returns the value associated with a pair of keys.\n      Value operator()(const FirstKey&, const SecondKey&) const { \n\treturn Value(); \n      }\n      /// Sets the value associated with the pair of keys.\n      void set(const FirstKey&, const SecondKey& ,const Value&) {}\n\n      template<typename _ReadWriteMatrixMap>\n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<ReadMatrixMap<K1, K2, V>, _ReadWriteMatrixMap >();\n\t  checkConcept<WriteMatrixMap<K1, K2, V>, _ReadWriteMatrixMap >();\n\t}\n      };\n    };\n  \n  \n    ///Dereferable matrix map concept\n    template<typename K1, typename K2, typename V, typename R, typename CR>\n    class ReferenceMatrixMap : public ReadWriteMatrixMap<K1, K2, V>\n    {\n    public:\n      /// Tag for reference maps.\n      typedef True ReferenceMapTag;\n      /// Map's first key type.\n      typedef K1 FirstKey;    \n      /// Map's second key type.\n      typedef K1 SecondKey;    \n      /// Map's value type. (The type of objects associated with the keys).\n      typedef V Value;\n      /// Map's reference type.\n      typedef R Reference;\n      /// Map's const reference type.\n      typedef CR ConstReference;\n\n    protected:\n      Value tmp;\n    public:\n\n      ///Returns a reference to the value associated to a pair of keys.\n      Reference operator()(const FirstKey&, const SecondKey&) { \n\treturn tmp; \n      }\n      ///Returns a const reference to the value associated to a pair of keys.\n      ConstReference operator()(const FirstKey&, const SecondKey&) const { \n\treturn tmp; \n      }\n      /// Sets the value associated with the pair of keys.\n      void set(const FirstKey&, const SecondKey& ,const Value&) {}\n\n      // \\todo rethink this concept\n      template<typename _ReferenceMatrixMap>\n      struct ReferenceMapConcept {\n\n\tvoid constraints() {\n\t  checkConcept<ReadWriteMatrixMap, _ReferenceMatrixMap >();\n\t  m(first_key, second_key) = val;\n\t  val  = m(first_key, second_key);\n\t  m(first_key, second_key) = ref;\n\t  ref = m(first_key, second_key);\n\t  m(own_first_key, own_second_key) = own_val;\n\t  own_val  = m(own_first_key, own_second_key);\n\t  m(own_first_key, own_second_key) = own_ref;\n\t  own_ref = m(own_first_key, own_second_key); \n\t}\n\n\ttypename _ReferenceMatrixMap::Key& own_first_key;\n\ttypename _ReferenceMatrixMap::Key& own_second_key;\n\ttypename _ReferenceMatrixMap::Value& own_val;\n\ttypename _ReferenceMatrixMap::Reference& own_ref;\n\tFirstKey& first_key;\n\tSecondKey& second_key;\n\tValue& val;\n\tReference& ref;\n\t_ReferenceMatrixMap& m;\n      };\n    };\n\n    // @}\n\n  } //namespace concepts\n} //namespace lemon\n#endif // LEMON_CONCEPT_MATRIX_MAPS_H\n"
  },
  {
    "path": "src/lemon/concepts/path.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n///\\ingroup concept\n///\\file\n///\\brief Classes for representing paths in graphs.\n///\n///\\todo Iterators have obsolete style\n\n#ifndef LEMON_CONCEPT_PATH_H\n#define LEMON_CONCEPT_PATH_H\n\n#include <lemon/bits/invalid.h>\n#include <lemon/bits/utility.h>\n#include <lemon/concept_check.h>\n\nnamespace lemon {\n  namespace concepts {\n\n    /// \\addtogroup concept\n    /// @{\n\n    /// \\brief A skeleton structure for representing directed paths in\n    /// a graph.\n    ///\n    /// A skeleton structure for representing directed paths in a\n    /// graph.  \n    /// \\param _Graph The graph type in which the path is.\n    ///\n    /// In a sense, the path can be treated as a list of edges. The\n    /// lemon path type stores just this list. As a consequence it\n    /// cannot enumerate the nodes in the path and the zero length\n    /// paths cannot store the source.\n    ///\n    template <typename _Graph>\n    class Path {\n    public:\n\n      /// Type of the underlying graph.\n      typedef _Graph Graph;\n      /// Edge type of the underlying graph.\n      typedef typename Graph::Edge Edge;\n\n      class EdgeIt;\n\n      /// \\brief Default constructor\n      Path() {}\n\n      /// \\brief Template constructor\n      template <typename CPath>\n      Path(const CPath& cpath) {}\n\n      /// \\brief Template assigment\n      template <typename CPath>\n      Path& operator=(const CPath& cpath) {}\n\n      /// Length of the path ie. the number of edges in the path.\n      int length() const { return 0;}\n\n      /// Returns whether the path is empty.\n      bool empty() const { return true;}\n\n      /// Resets the path to an empty path.\n      void clear() {}\n\n      /// \\brief Lemon style iterator for path edges\n      ///\n      /// This class is used to iterate on the edges of the paths.\n      class EdgeIt {\n      public:\n\t/// Default constructor\n\tEdgeIt() {}\n\t/// Invalid constructor\n\tEdgeIt(Invalid) {}\n\t/// Constructor for first edge\n\tEdgeIt(const Path &) {}\n\n        /// Conversion to Edge\n\toperator Edge() const { return INVALID; }\n\n\t/// Next edge\n\tEdgeIt& operator++() {return *this;}\n\n\t/// Comparison operator\n\tbool operator==(const EdgeIt&) const {return true;}\n\t/// Comparison operator\n\tbool operator!=(const EdgeIt&) const {return true;}\n \t/// Comparison operator\n \tbool operator<(const EdgeIt&) const {return false;}\n\n      };\n\n      template <typename _Path>\n      struct Constraints {\n        void constraints() {\n          Path<Graph> pc;\n          _Path p, pp(pc);\n          int l = p.length();\n          int e = p.empty();\n          p.clear();\n\n          p = pc;\n\n          typename _Path::EdgeIt id, ii(INVALID), i(p);\n\n          ++i;\n          typename Graph::Edge ed = i;\n\n          e = (i == ii);\n          e = (i != ii);\n          e = (i < ii);\n\n          ignore_unused_variable_warning(l);\n          ignore_unused_variable_warning(pp);\n          ignore_unused_variable_warning(e);\n          ignore_unused_variable_warning(id);\n          ignore_unused_variable_warning(ii);\n          ignore_unused_variable_warning(ed);\n        }\n      };\n\n    };\n\n    namespace _path_bits {\n      \n      template <typename _Graph, typename _Path, typename RevPathTag = void>\n      struct PathDumperConstraints {\n        void constraints() {\n          int l = p.length();\n          int e = p.empty();\n\n          typename _Path::EdgeIt id, i(p);\n\n          ++i;\n          typename _Graph::Edge ed = i;\n\n          e = (i == INVALID);\n          e = (i != INVALID);\n\n          ignore_unused_variable_warning(l);\n          ignore_unused_variable_warning(e);\n          ignore_unused_variable_warning(id);\n          ignore_unused_variable_warning(ed);\n        }\n        _Path& p;\n      };\n\n      template <typename _Graph, typename _Path>\n      struct PathDumperConstraints<\n        _Graph, _Path, \n        typename enable_if<typename _Path::RevPathTag, void>::type\n      > {\n        void constraints() {\n          int l = p.length();\n          int e = p.empty();\n\n          typename _Path::RevEdgeIt id, i(p);\n\n          ++i;\n          typename _Graph::Edge ed = i;\n\n          e = (i == INVALID);\n          e = (i != INVALID);\n\n          ignore_unused_variable_warning(l);\n          ignore_unused_variable_warning(e);\n          ignore_unused_variable_warning(id);\n          ignore_unused_variable_warning(ed);\n        }\n        _Path& p;\n      };\n    \n    }\n\n\n    /// \\brief A skeleton structure for path dumpers.\n    ///\n    /// A skeleton structure for path dumpers. The path dumpers are\n    /// the generalization of the paths. The path dumpers can\n    /// enumerate the edges of the path wheter in forward or in\n    /// backward order.  In most time these classes are not used\n    /// directly rather it used to assign a dumped class to a real\n    /// path type.\n    ///\n    /// The main purpose of this concept is that the shortest path\n    /// algorithms can enumerate easily the edges in reverse order.\n    /// If we would like to give back a real path from these\n    /// algorithms then we should create a temporarly path object. In\n    /// Lemon such algorithms gives back a path dumper what can\n    /// assigned to a real path and the dumpers can be implemented as\n    /// an adaptor class to the predecessor map.\n\n    /// \\param _Graph  The graph type in which the path is.\n    ///\n    /// The paths can be constructed from any path type by a\n    /// template constructor or a template assignment operator.\n    /// \n    template <typename _Graph>\n    class PathDumper {\n    public:\n\n      /// Type of the underlying graph.\n      typedef _Graph Graph;\n      /// Edge type of the underlying graph.\n      typedef typename Graph::Edge Edge;\n\n      /// Length of the path ie. the number of edges in the path.\n      int length() const { return 0;}\n\n      /// Returns whether the path is empty.\n      bool empty() const { return true;}\n\n      /// \\brief Forward or reverse dumping\n      ///\n      /// If the RevPathTag is defined and true then reverse dumping\n      /// is provided in the path dumper. In this case instead of the\n      /// EdgeIt the RevEdgeIt iterator should be implemented in the\n      /// dumper.\n      typedef False RevPathTag;\n\n      /// \\brief Lemon style iterator for path edges\n      ///\n      /// This class is used to iterate on the edges of the paths.\n      class EdgeIt {\n      public:\n\t/// Default constructor\n\tEdgeIt() {}\n\t/// Invalid constructor\n\tEdgeIt(Invalid) {}\n\t/// Constructor for first edge\n\tEdgeIt(const PathDumper&) {}\n\n        /// Conversion to Edge\n\toperator Edge() const { return INVALID; }\n\n\t/// Next edge\n\tEdgeIt& operator++() {return *this;}\n\n\t/// Comparison operator\n\tbool operator==(const EdgeIt&) const {return true;}\n\t/// Comparison operator\n\tbool operator!=(const EdgeIt&) const {return true;}\n \t/// Comparison operator\n \tbool operator<(const EdgeIt&) const {return false;}\n\n      };\n\n      /// \\brief Lemon style iterator for path edges\n      ///\n      /// This class is used to iterate on the edges of the paths in\n      /// reverse direction.\n      class RevEdgeIt {\n      public:\n\t/// Default constructor\n\tRevEdgeIt() {}\n\t/// Invalid constructor\n\tRevEdgeIt(Invalid) {}\n\t/// Constructor for first edge\n\tRevEdgeIt(const PathDumper &) {}\n\n        /// Conversion to Edge\n\toperator Edge() const { return INVALID; }\n\n\t/// Next edge\n\tRevEdgeIt& operator++() {return *this;}\n\n\t/// Comparison operator\n\tbool operator==(const RevEdgeIt&) const {return true;}\n\t/// Comparison operator\n\tbool operator!=(const RevEdgeIt&) const {return true;}\n \t/// Comparison operator\n \tbool operator<(const RevEdgeIt&) const {return false;}\n\n      };\n\n      template <typename _Path>\n      struct Constraints {\n        void constraints() {\n          function_requires<_path_bits::\n            PathDumperConstraints<Graph, _Path> >();\n        }\n      };\n\n    };\n\n\n    ///@}\n  }\n\n} // namespace lemon\n\n#endif // LEMON_CONCEPT_PATH_H\n"
  },
  {
    "path": "src/lemon/concepts/ugraph.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n///\\ingroup graph_concepts\n///\\file\n///\\brief The concept of Undirected Graphs.\n\n#ifndef LEMON_CONCEPT_UGRAPH_H\n#define LEMON_CONCEPT_UGRAPH_H\n\n#include <lemon/concepts/graph_components.h>\n#include <lemon/concepts/graph.h>\n#include <lemon/bits/utility.h>\n\nnamespace lemon {\n  namespace concepts {\n\n    /// \\ingroup graph_concepts\n    ///\n    /// \\brief Class describing the concept of Undirected Graphs.\n    ///\n    /// This class describes the common interface of all Undirected\n    /// Graphs.\n    ///\n    /// As all concept describing classes it provides only interface\n    /// without any sensible implementation. So any algorithm for\n    /// undirected graph should compile with this class, but it will not\n    /// run properly, of course.\n    ///\n    /// The LEMON undirected graphs also fulfill the concept of\n    /// directed graphs (\\ref lemon::concepts::Graph \"Graph\n    /// Concept\"). Each undirected edges can be seen as two opposite\n    /// directed edge and consequently the undirected graph can be\n    /// seen as the direceted graph of these directed edges. The\n    /// UGraph has the UEdge inner class for the undirected edges and\n    /// the Edge type for the directed edges. The Edge type is\n    /// convertible to UEdge or inherited from it so from a directed\n    /// edge we can get the represented undirected edge.\n    ///\n    /// In the sense of the LEMON each undirected edge has a default\n    /// direction (it should be in every computer implementation,\n    /// because the order of undirected edge's nodes defines an\n    /// orientation). With the default orientation we can define that\n    /// the directed edge is forward or backward directed. With the \\c\n    /// direction() and \\c direct() function we can get the direction\n    /// of the directed edge and we can direct an undirected edge.\n    ///\n    /// The UEdgeIt is an iterator for the undirected edges. We can use\n    /// the UEdgeMap to map values for the undirected edges. The InEdgeIt and\n    /// OutEdgeIt iterates on the same undirected edges but with opposite\n    /// direction. The IncEdgeIt iterates also on the same undirected edges\n    /// as the OutEdgeIt and InEdgeIt but it is not convertible to Edge just\n    /// to UEdge.  \n    class UGraph {\n    public:\n      /// \\brief The undirected graph should be tagged by the\n      /// UndirectedTag.\n      ///\n      /// The undirected graph should be tagged by the UndirectedTag. This\n      /// tag helps the enable_if technics to make compile time \n      /// specializations for undirected graphs.  \n      typedef True UndirectedTag;\n\n      /// \\brief The base type of node iterators, \n      /// or in other words, the trivial node iterator.\n      ///\n      /// This is the base type of each node iterator,\n      /// thus each kind of node iterator converts to this.\n      /// More precisely each kind of node iterator should be inherited \n      /// from the trivial node iterator.\n      class Node {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        Node() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        Node(const Node&) { }\n\n        /// Invalid constructor \\& conversion.\n\n        /// This constructor initializes the iterator to be invalid.\n        /// \\sa Invalid for more details.\n        Node(Invalid) { }\n        /// Equality operator\n\n        /// Two iterators are equal if and only if they point to the\n        /// same object or both are invalid.\n        bool operator==(Node) const { return true; }\n\n        /// Inequality operator\n        \n        /// \\sa operator==(Node n)\n        ///\n        bool operator!=(Node) const { return true; }\n\n\t/// Artificial ordering operator.\n\t\n\t/// To allow the use of graph descriptors as key type in std::map or\n\t/// similar associative container we require this.\n\t///\n\t/// \\note This operator only have to define some strict ordering of\n\t/// the items; this order has nothing to do with the iteration\n\t/// ordering of the items.\n\tbool operator<(Node) const { return false; }\n\n      };\n    \n      /// This iterator goes through each node.\n\n      /// This iterator goes through each node.\n      /// Its usage is quite simple, for example you can count the number\n      /// of nodes in graph \\c g of type \\c Graph like this:\n      ///\\code\n      /// int count=0;\n      /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count;\n      ///\\endcode\n      class NodeIt : public Node {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        NodeIt() { }\n        /// Copy constructor.\n        \n        /// Copy constructor.\n        ///\n        NodeIt(const NodeIt& n) : Node(n) { }\n        /// Invalid constructor \\& conversion.\n\n        /// Initialize the iterator to be invalid.\n        /// \\sa Invalid for more details.\n        NodeIt(Invalid) { }\n        /// Sets the iterator to the first node.\n\n        /// Sets the iterator to the first node of \\c g.\n        ///\n        NodeIt(const UGraph&) { }\n        /// Node -> NodeIt conversion.\n\n        /// Sets the iterator to the node of \\c the graph pointed by \n\t/// the trivial iterator.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        NodeIt(const UGraph&, const Node&) { }\n        /// Next node.\n\n        /// Assign the iterator to the next node.\n        ///\n        NodeIt& operator++() { return *this; }\n      };\n    \n    \n      /// The base type of the undirected edge iterators.\n\n      /// The base type of the undirected edge iterators.\n      ///\n      class UEdge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        UEdge() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        UEdge(const UEdge&) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        UEdge(Invalid) { }\n        /// Equality operator\n\n        /// Two iterators are equal if and only if they point to the\n        /// same object or both are invalid.\n        bool operator==(UEdge) const { return true; }\n        /// Inequality operator\n\n        /// \\sa operator==(UEdge n)\n        ///\n        bool operator!=(UEdge) const { return true; }\n\n\t/// Artificial ordering operator.\n\t\n\t/// To allow the use of graph descriptors as key type in std::map or\n\t/// similar associative container we require this.\n\t///\n\t/// \\note This operator only have to define some strict ordering of\n\t/// the items; this order has nothing to do with the iteration\n\t/// ordering of the items.\n\tbool operator<(UEdge) const { return false; }\n      };\n\n      /// This iterator goes through each undirected edge.\n\n      /// This iterator goes through each undirected edge of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of undirected edges in a graph \\c g of type \\c Graph as follows:\n      ///\\code\n      /// int count=0;\n      /// for(Graph::UEdgeIt e(g); e!=INVALID; ++e) ++count;\n      ///\\endcode\n      class UEdgeIt : public UEdge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        UEdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        UEdgeIt(const UEdgeIt& e) : UEdge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        UEdgeIt(Invalid) { }\n        /// This constructor sets the iterator to the first undirected edge.\n    \n        /// This constructor sets the iterator to the first undirected edge.\n        UEdgeIt(const UGraph&) { }\n        /// UEdge -> UEdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator.\n        /// This feature necessitates that each time we\n        /// iterate the undirected edge-set, the iteration order is the \n\t/// same.\n        UEdgeIt(const UGraph&, const UEdge&) { } \n        /// Next undirected edge\n        \n        /// Assign the iterator to the next undirected edge.\n        UEdgeIt& operator++() { return *this; }\n      };\n\n      /// \\brief This iterator goes trough the incident undirected \n      /// edges of a node.\n      ///\n      /// This iterator goes trough the incident undirected edges\n      /// of a certain node of a graph. You should assume that the \n      /// loop edges will be iterated twice.\n      /// \n      /// Its usage is quite simple, for example you can compute the\n      /// degree (i.e. count the number of incident edges of a node \\c n\n      /// in graph \\c g of type \\c Graph as follows. \n      ///\n      ///\\code\n      /// int count=0;\n      /// for(Graph::IncEdgeIt e(g, n); e!=INVALID; ++e) ++count;\n      ///\\endcode\n      class IncEdgeIt : public UEdge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        IncEdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        IncEdgeIt(const IncEdgeIt& e) : UEdge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        IncEdgeIt(Invalid) { }\n        /// This constructor sets the iterator to first incident edge.\n    \n        /// This constructor set the iterator to the first incident edge of\n        /// the node.\n        IncEdgeIt(const UGraph&, const Node&) { }\n        /// UEdge -> IncEdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator \\c e.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        IncEdgeIt(const UGraph&, const UEdge&) { }\n        /// Next incident edge\n\n        /// Assign the iterator to the next incident edge\n\t/// of the corresponding node.\n        IncEdgeIt& operator++() { return *this; }\n      };\n\n      /// The directed edge type.\n\n      /// The directed edge type. It can be converted to the\n      /// undirected edge or it should be inherited from the undirected\n      /// edge.\n      class Edge : public UEdge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        Edge() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        Edge(const Edge& e) : UEdge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        Edge(Invalid) { }\n        /// Equality operator\n\n        /// Two iterators are equal if and only if they point to the\n        /// same object or both are invalid.\n        bool operator==(Edge) const { return true; }\n        /// Inequality operator\n\n        /// \\sa operator==(Edge n)\n        ///\n        bool operator!=(Edge) const { return true; }\n\n\t/// Artificial ordering operator.\n\t\n\t/// To allow the use of graph descriptors as key type in std::map or\n\t/// similar associative container we require this.\n\t///\n\t/// \\note This operator only have to define some strict ordering of\n\t/// the items; this order has nothing to do with the iteration\n\t/// ordering of the items.\n\tbool operator<(Edge) const { return false; }\n\t\n      }; \n      /// This iterator goes through each directed edge.\n\n      /// This iterator goes through each edge of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of edges in a graph \\c g of type \\c Graph as follows:\n      ///\\code\n      /// int count=0;\n      /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count;\n      ///\\endcode\n      class EdgeIt : public Edge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        EdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        EdgeIt(const EdgeIt& e) : Edge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        EdgeIt(Invalid) { }\n        /// This constructor sets the iterator to the first edge.\n    \n        /// This constructor sets the iterator to the first edge of \\c g.\n        ///@param g the graph\n        EdgeIt(const UGraph &g) { ignore_unused_variable_warning(g); }\n        /// Edge -> EdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator \\c e.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        EdgeIt(const UGraph&, const Edge&) { } \n        ///Next edge\n        \n        /// Assign the iterator to the next edge.\n        EdgeIt& operator++() { return *this; }\n      };\n   \n      /// This iterator goes trough the outgoing directed edges of a node.\n\n      /// This iterator goes trough the \\e outgoing edges of a certain node\n      /// of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of outgoing edges of a node \\c n\n      /// in graph \\c g of type \\c Graph as follows.\n      ///\\code\n      /// int count=0;\n      /// for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) ++count;\n      ///\\endcode\n    \n      class OutEdgeIt : public Edge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        OutEdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        OutEdgeIt(const OutEdgeIt& e) : Edge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        OutEdgeIt(Invalid) { }\n        /// This constructor sets the iterator to the first outgoing edge.\n    \n        /// This constructor sets the iterator to the first outgoing edge of\n        /// the node.\n        ///@param n the node\n        ///@param g the graph\n        OutEdgeIt(const UGraph& n, const Node& g) {\n\t  ignore_unused_variable_warning(n);\n\t  ignore_unused_variable_warning(g);\n\t}\n        /// Edge -> OutEdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator.\n\t/// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        OutEdgeIt(const UGraph&, const Edge&) { }\n        ///Next outgoing edge\n        \n        /// Assign the iterator to the next \n        /// outgoing edge of the corresponding node.\n        OutEdgeIt& operator++() { return *this; }\n      };\n\n      /// This iterator goes trough the incoming directed edges of a node.\n\n      /// This iterator goes trough the \\e incoming edges of a certain node\n      /// of a graph.\n      /// Its usage is quite simple, for example you can count the number\n      /// of outgoing edges of a node \\c n\n      /// in graph \\c g of type \\c Graph as follows.\n      ///\\code\n      /// int count=0;\n      /// for(Graph::InEdgeIt e(g, n); e!=INVALID; ++e) ++count;\n      ///\\endcode\n\n      class InEdgeIt : public Edge {\n      public:\n        /// Default constructor\n\n        /// @warning The default constructor sets the iterator\n        /// to an undefined value.\n        InEdgeIt() { }\n        /// Copy constructor.\n\n        /// Copy constructor.\n        ///\n        InEdgeIt(const InEdgeIt& e) : Edge(e) { }\n        /// Initialize the iterator to be invalid.\n\n        /// Initialize the iterator to be invalid.\n        ///\n        InEdgeIt(Invalid) { }\n        /// This constructor sets the iterator to first incoming edge.\n    \n        /// This constructor set the iterator to the first incoming edge of\n        /// the node.\n        ///@param n the node\n        ///@param g the graph\n        InEdgeIt(const UGraph& g, const Node& n) { \n\t  ignore_unused_variable_warning(n);\n\t  ignore_unused_variable_warning(g);\n\t}\n        /// Edge -> InEdgeIt conversion\n\n        /// Sets the iterator to the value of the trivial iterator \\c e.\n        /// This feature necessitates that each time we \n        /// iterate the edge-set, the iteration order is the same.\n        InEdgeIt(const UGraph&, const Edge&) { }\n        /// Next incoming edge\n\n        /// Assign the iterator to the next inedge of the corresponding node.\n        ///\n        InEdgeIt& operator++() { return *this; }\n      };\n\n      /// \\brief Read write map of the nodes to type \\c T.\n      /// \n      /// ReadWrite map of the nodes to type \\c T.\n      /// \\sa Reference\n      template<class T> \n      class NodeMap : public ReadWriteMap< Node, T >\n      {\n      public:\n\n        ///\\e\n        NodeMap(const UGraph&) { }\n        ///\\e\n        NodeMap(const UGraph&, T) { }\n\n        ///Copy constructor\n        NodeMap(const NodeMap& nm) : ReadWriteMap< Node, T >(nm) { }\n        ///Assignment operator\n        template <typename CMap>\n        NodeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Node, T>, CMap>();\n          return *this; \n        }\n      };\n\n      /// \\brief Read write map of the directed edges to type \\c T.\n      ///\n      /// Reference map of the directed edges to type \\c T.\n      /// \\sa Reference\n      template<class T> \n      class EdgeMap : public ReadWriteMap<Edge,T>\n      {\n      public:\n\n        ///\\e\n        EdgeMap(const UGraph&) { }\n        ///\\e\n        EdgeMap(const UGraph&, T) { }\n        ///Copy constructor\n        EdgeMap(const EdgeMap& em) : ReadWriteMap<Edge,T>(em) { }\n        ///Assignment operator\n        template <typename CMap>\n        EdgeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<Edge, T>, CMap>();\n          return *this; \n        }\n      };\n\n      /// Read write map of the undirected edges to type \\c T.\n\n      /// Reference map of the edges to type \\c T.\n      /// \\sa Reference\n      template<class T> \n      class UEdgeMap : public ReadWriteMap<UEdge,T>\n      {\n      public:\n\n        ///\\e\n        UEdgeMap(const UGraph&) { }\n        ///\\e\n        UEdgeMap(const UGraph&, T) { }\n        ///Copy constructor\n        UEdgeMap(const UEdgeMap& em) : ReadWriteMap<UEdge,T>(em) {}\n        ///Assignment operator\n        template <typename CMap>\n        UEdgeMap& operator=(const CMap&) { \n          checkConcept<ReadMap<UEdge, T>, CMap>();\n          return *this; \n        }\n      };\n\n      /// \\brief Direct the given undirected edge.\n      ///\n      /// Direct the given undirected edge. The returned edge source\n      /// will be the given node.\n      Edge direct(const UEdge&, const Node&) const {\n\treturn INVALID;\n      }\n\n      /// \\brief Direct the given undirected edge.\n      ///\n      /// Direct the given undirected edge. The returned edge\n      /// represents the given undirected edge and the direction comes\n      /// from the given bool.  The source of the undirected edge and\n      /// the directed edge is the same when the given bool is true.\n      Edge direct(const UEdge&, bool) const {\n\treturn INVALID;\n      }\n\n      /// \\brief Returns true if the edge has default orientation.\n      ///\n      /// Returns whether the given directed edge is same orientation as\n      /// the corresponding undirected edge's default orientation.\n      bool direction(Edge) const { return true; }\n\n      /// \\brief Returns the opposite directed edge.\n      ///\n      /// Returns the opposite directed edge.\n      Edge oppositeEdge(Edge) const { return INVALID; }\n\n      /// \\brief Opposite node on an edge\n      ///\n      /// \\return the opposite of the given Node on the given UEdge\n      Node oppositeNode(Node, UEdge) const { return INVALID; }\n\n      /// \\brief First node of the undirected edge.\n      ///\n      /// \\return the first node of the given UEdge.\n      ///\n      /// Naturally undirected edges don't have direction and thus\n      /// don't have source and target node. But we use these two methods\n      /// to query the two nodes of the edge. The direction of the edge\n      /// which arises this way is called the inherent direction of the\n      /// undirected edge, and is used to define the \"default\" direction\n      /// of the directed versions of the edges.\n      /// \\sa direction\n      Node source(UEdge) const { return INVALID; }\n\n      /// \\brief Second node of the undirected edge.\n      Node target(UEdge) const { return INVALID; }\n\n      /// \\brief Source node of the directed edge.\n      Node source(Edge) const { return INVALID; }\n\n      /// \\brief Target node of the directed edge.\n      Node target(Edge) const { return INVALID; }\n\n      void first(Node&) const {}\n      void next(Node&) const {}\n\n      void first(UEdge&) const {}\n      void next(UEdge&) const {}\n\n      void first(Edge&) const {}\n      void next(Edge&) const {}\n\n      void firstOut(Edge&, Node) const {}\n      void nextOut(Edge&) const {}\n\n      void firstIn(Edge&, Node) const {}\n      void nextIn(Edge&) const {}\n\n\n      void firstInc(UEdge &, bool &, const Node &) const {}\n      void nextInc(UEdge &, bool &) const {}\n\n      /// \\brief Base node of the iterator\n      ///\n      /// Returns the base node (the source in this case) of the iterator\n      Node baseNode(OutEdgeIt e) const {\n\treturn source(e);\n      }\n      /// \\brief Running node of the iterator\n      ///\n      /// Returns the running node (the target in this case) of the\n      /// iterator\n      Node runningNode(OutEdgeIt e) const {\n\treturn target(e);\n      }\n\n      /// \\brief Base node of the iterator\n      ///\n      /// Returns the base node (the target in this case) of the iterator\n      Node baseNode(InEdgeIt e) const {\n\treturn target(e);\n      }\n      /// \\brief Running node of the iterator\n      ///\n      /// Returns the running node (the source in this case) of the\n      /// iterator\n      Node runningNode(InEdgeIt e) const {\n\treturn source(e);\n      }\n\n      /// \\brief Base node of the iterator\n      ///\n      /// Returns the base node of the iterator\n      Node baseNode(IncEdgeIt) const {\n\treturn INVALID;\n      }\n      \n      /// \\brief Running node of the iterator\n      ///\n      /// Returns the running node of the iterator\n      Node runningNode(IncEdgeIt) const {\n\treturn INVALID;\n      }\n\n      template <typename Graph>\n      struct Constraints {\n\tvoid constraints() {\n\t  checkConcept<IterableUGraphComponent<>, Graph>();\n\t  checkConcept<MappableUGraphComponent<>, Graph>();\n\t}\n      };\n\n    };\n\n  }\n\n}\n\n#endif\n"
  },
  {
    "path": "src/lemon/dfs.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_DFS_H\n#define LEMON_DFS_H\n\n///\\ingroup search\n///\\file\n///\\brief Dfs algorithm.\n\n#include <lemon/list_graph.h>\n#include <lemon/graph_utils.h>\n#include <lemon/bits/path_dump.h>\n#include <lemon/bits/invalid.h>\n#include <lemon/error.h>\n#include <lemon/maps.h>\n\n#include <lemon/concept_check.h>\n\nnamespace lemon {\n\n  \n  ///Default traits class of Dfs class.\n\n  ///Default traits class of Dfs class.\n  ///\\param GR Graph type.\n  template<class GR>\n  struct DfsDefaultTraits\n  {\n    ///The graph type the algorithm runs on. \n    typedef GR Graph;\n    ///\\brief The type of the map that stores the last\n    ///edges of the %DFS paths.\n    /// \n    ///The type of the map that stores the last\n    ///edges of the %DFS paths.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\n    typedef typename Graph::template NodeMap<typename GR::Edge> PredMap;\n    ///Instantiates a PredMap.\n \n    ///This function instantiates a \\ref PredMap. \n    ///\\param G is the graph, to which we would like to define the PredMap.\n    ///\\todo The graph alone may be insufficient to initialize\n    static PredMap *createPredMap(const GR &G) \n    {\n      return new PredMap(G);\n    }\n\n    ///The type of the map that indicates which nodes are processed.\n \n    ///The type of the map that indicates which nodes are processed.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\\todo named parameter to set this type, function to read and write.\n    typedef NullMap<typename Graph::Node,bool> ProcessedMap;\n    ///Instantiates a ProcessedMap.\n \n    ///This function instantiates a \\ref ProcessedMap. \n    ///\\param g is the graph, to which\n    ///we would like to define the \\ref ProcessedMap\n#ifdef DOXYGEN\n    static ProcessedMap *createProcessedMap(const GR &g)\n#else\n    static ProcessedMap *createProcessedMap(const GR &)\n#endif\n    {\n      return new ProcessedMap();\n    }\n    ///The type of the map that indicates which nodes are reached.\n \n    ///The type of the map that indicates which nodes are reached.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\\todo named parameter to set this type, function to read and write.\n    typedef typename Graph::template NodeMap<bool> ReachedMap;\n    ///Instantiates a ReachedMap.\n \n    ///This function instantiates a \\ref ReachedMap. \n    ///\\param G is the graph, to which\n    ///we would like to define the \\ref ReachedMap.\n    static ReachedMap *createReachedMap(const GR &G)\n    {\n      return new ReachedMap(G);\n    }\n    ///The type of the map that stores the dists of the nodes.\n \n    ///The type of the map that stores the dists of the nodes.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\n    typedef typename Graph::template NodeMap<int> DistMap;\n    ///Instantiates a DistMap.\n \n    ///This function instantiates a \\ref DistMap. \n    ///\\param G is the graph, to which we would like to define the \\ref DistMap\n    static DistMap *createDistMap(const GR &G)\n    {\n      return new DistMap(G);\n    }\n  };\n  \n  ///%DFS algorithm class.\n  \n  ///\\ingroup search\n  ///This class provides an efficient implementation of the %DFS algorithm.\n  ///\n  ///\\param GR The graph type the algorithm runs on. The default value is\n  ///\\ref ListGraph. The value of GR is not used directly by Dfs, it\n  ///is only passed to \\ref DfsDefaultTraits.\n  ///\\param TR Traits class to set various data types used by the algorithm.\n  ///The default traits class is\n  ///\\ref DfsDefaultTraits \"DfsDefaultTraits<GR>\".\n  ///See \\ref DfsDefaultTraits for the documentation of\n  ///a Dfs traits class.\n  ///\n  ///\\author Jacint Szabo and Alpar Juttner\n#ifdef DOXYGEN\n  template <typename GR,\n\t    typename TR>\n#else\n  template <typename GR=ListGraph,\n\t    typename TR=DfsDefaultTraits<GR> >\n#endif\n  class Dfs {\n  public:\n    /**\n     * \\brief \\ref Exception for uninitialized parameters.\n     *\n     * This error represents problems in the initialization\n     * of the parameters of the algorithms.\n     */\n    class UninitializedParameter : public lemon::UninitializedParameter {\n    public:\n      virtual const char* what() const throw() {\n\treturn \"lemon::Dfs::UninitializedParameter\";\n      }\n    };\n\n    typedef TR Traits;\n    ///The type of the underlying graph.\n    typedef typename TR::Graph Graph;\n    ///\\e\n    typedef typename Graph::Node Node;\n    ///\\e\n    typedef typename Graph::NodeIt NodeIt;\n    ///\\e\n    typedef typename Graph::Edge Edge;\n    ///\\e\n    typedef typename Graph::OutEdgeIt OutEdgeIt;\n    \n    ///\\brief The type of the map that stores the last\n    ///edges of the %DFS paths.\n    typedef typename TR::PredMap PredMap;\n    ///The type of the map indicating which nodes are reached.\n    typedef typename TR::ReachedMap ReachedMap;\n    ///The type of the map indicating which nodes are processed.\n    typedef typename TR::ProcessedMap ProcessedMap;\n    ///The type of the map that stores the dists of the nodes.\n    typedef typename TR::DistMap DistMap;\n  private:\n    /// Pointer to the underlying graph.\n    const Graph *G;\n    ///Pointer to the map of predecessors edges.\n    PredMap *_pred;\n    ///Indicates if \\ref _pred is locally allocated (\\c true) or not.\n    bool local_pred;\n    ///Pointer to the map of distances.\n    DistMap *_dist;\n    ///Indicates if \\ref _dist is locally allocated (\\c true) or not.\n    bool local_dist;\n    ///Pointer to the map of reached status of the nodes.\n    ReachedMap *_reached;\n    ///Indicates if \\ref _reached is locally allocated (\\c true) or not.\n    bool local_reached;\n    ///Pointer to the map of processed status of the nodes.\n    ProcessedMap *_processed;\n    ///Indicates if \\ref _processed is locally allocated (\\c true) or not.\n    bool local_processed;\n\n    std::vector<typename Graph::OutEdgeIt> _stack;\n    int _stack_head;\n\n    ///Creates the maps if necessary.\n    \n    ///\\todo Better memory allocation (instead of new).\n    void create_maps() \n    {\n      if(!_pred) {\n\tlocal_pred = true;\n\t_pred = Traits::createPredMap(*G);\n      }\n      if(!_dist) {\n\tlocal_dist = true;\n\t_dist = Traits::createDistMap(*G);\n      }\n      if(!_reached) {\n\tlocal_reached = true;\n\t_reached = Traits::createReachedMap(*G);\n      }\n      if(!_processed) {\n\tlocal_processed = true;\n\t_processed = Traits::createProcessedMap(*G);\n      }\n    }\n\n  protected:\n\n    Dfs() {}\n    \n  public:\n\n    typedef Dfs Create;\n\n    ///\\name Named template parameters\n\n    ///@{\n\n    template <class T>\n    struct DefPredMapTraits : public Traits {\n      typedef T PredMap;\n      static PredMap *createPredMap(const Graph &G) \n      {\n\tthrow UninitializedParameter();\n      }\n    };\n    ///\\brief \\ref named-templ-param \"Named parameter\" for setting\n    ///PredMap type\n    ///\n    ///\\ref named-templ-param \"Named parameter\" for setting PredMap type\n    ///\n    template <class T>\n    struct DefPredMap : public Dfs<Graph, DefPredMapTraits<T> > {\n      typedef Dfs<Graph, DefPredMapTraits<T> > Create;\n    };\n    \n    \n    template <class T>\n    struct DefDistMapTraits : public Traits {\n      typedef T DistMap;\n      static DistMap *createDistMap(const Graph &) \n      {\n\tthrow UninitializedParameter();\n      }\n    };\n    ///\\brief \\ref named-templ-param \"Named parameter\" for setting\n    ///DistMap type\n    ///\n    ///\\ref named-templ-param \"Named parameter\" for setting DistMap\n    ///type\n    template <class T>\n    struct DefDistMap {\n      typedef Dfs<Graph, DefDistMapTraits<T> > Create;\n    };\n    \n    template <class T>\n    struct DefReachedMapTraits : public Traits {\n      typedef T ReachedMap;\n      static ReachedMap *createReachedMap(const Graph &) \n      {\n\tthrow UninitializedParameter();\n      }\n    };\n    ///\\brief \\ref named-templ-param \"Named parameter\" for setting\n    ///ReachedMap type\n    ///\n    ///\\ref named-templ-param \"Named parameter\" for setting ReachedMap type\n    ///\n    template <class T>\n    struct DefReachedMap : public Dfs< Graph, DefReachedMapTraits<T> > {\n      typedef Dfs< Graph, DefReachedMapTraits<T> > Create;\n    };\n\n    template <class T>\n    struct DefProcessedMapTraits : public Traits {\n      typedef T ProcessedMap;\n      static ProcessedMap *createProcessedMap(const Graph &) \n      {\n\tthrow UninitializedParameter();\n      }\n    };\n    ///\\brief \\ref named-templ-param \"Named parameter\" for setting\n    ///ProcessedMap type\n    ///\n    ///\\ref named-templ-param \"Named parameter\" for setting ProcessedMap type\n    ///\n    template <class T>\n    struct DefProcessedMap : public Dfs< Graph, DefProcessedMapTraits<T> > { \n      typedef Dfs< Graph, DefProcessedMapTraits<T> > Create;\n    };\n    \n    struct DefGraphProcessedMapTraits : public Traits {\n      typedef typename Graph::template NodeMap<bool> ProcessedMap;\n      static ProcessedMap *createProcessedMap(const Graph &G) \n      {\n\treturn new ProcessedMap(G);\n      }\n    };\n    ///\\brief \\ref named-templ-param \"Named parameter\"\n    ///for setting the ProcessedMap type to be Graph::NodeMap<bool>.\n    ///\n    ///\\ref named-templ-param \"Named parameter\"\n    ///for setting the ProcessedMap type to be Graph::NodeMap<bool>.\n    ///If you don't set it explicitely, it will be automatically allocated.\n    template <class T>\n    class DefProcessedMapToBeDefaultMap :\n      public Dfs< Graph, DefGraphProcessedMapTraits> { \n      typedef Dfs< Graph, DefGraphProcessedMapTraits> Create;\n    };\n    \n    ///@}\n\n  public:      \n    \n    ///Constructor.\n    \n    ///\\param _G the graph the algorithm will run on.\n    ///\n    Dfs(const Graph& _G) :\n      G(&_G),\n      _pred(NULL), local_pred(false),\n      _dist(NULL), local_dist(false),\n      _reached(NULL), local_reached(false),\n      _processed(NULL), local_processed(false)\n    { }\n    \n    ///Destructor.\n    ~Dfs() \n    {\n      if(local_pred) delete _pred;\n      if(local_dist) delete _dist;\n      if(local_reached) delete _reached;\n      if(local_processed) delete _processed;\n    }\n\n    ///Sets the map storing the predecessor edges.\n\n    ///Sets the map storing the predecessor edges.\n    ///If you don't use this function before calling \\ref run(),\n    ///it will allocate one. The destuctor deallocates this\n    ///automatically allocated map, of course.\n    ///\\return <tt> (*this) </tt>\n    Dfs &predMap(PredMap &m) \n    {\n      if(local_pred) {\n\tdelete _pred;\n\tlocal_pred=false;\n      }\n      _pred = &m;\n      return *this;\n    }\n\n    ///Sets the map storing the distances calculated by the algorithm.\n\n    ///Sets the map storing the distances calculated by the algorithm.\n    ///If you don't use this function before calling \\ref run(),\n    ///it will allocate one. The destuctor deallocates this\n    ///automatically allocated map, of course.\n    ///\\return <tt> (*this) </tt>\n    Dfs &distMap(DistMap &m) \n    {\n      if(local_dist) {\n\tdelete _dist;\n\tlocal_dist=false;\n      }\n      _dist = &m;\n      return *this;\n    }\n\n    ///Sets the map indicating if a node is reached.\n\n    ///Sets the map indicating if a node is reached.\n    ///If you don't use this function before calling \\ref run(),\n    ///it will allocate one. The destuctor deallocates this\n    ///automatically allocated map, of course.\n    ///\\return <tt> (*this) </tt>\n    Dfs &reachedMap(ReachedMap &m) \n    {\n      if(local_reached) {\n\tdelete _reached;\n\tlocal_reached=false;\n      }\n      _reached = &m;\n      return *this;\n    }\n\n    ///Sets the map indicating if a node is processed.\n\n    ///Sets the map indicating if a node is processed.\n    ///If you don't use this function before calling \\ref run(),\n    ///it will allocate one. The destuctor deallocates this\n    ///automatically allocated map, of course.\n    ///\\return <tt> (*this) </tt>\n    Dfs &processedMap(ProcessedMap &m) \n    {\n      if(local_processed) {\n\tdelete _processed;\n\tlocal_processed=false;\n      }\n      _processed = &m;\n      return *this;\n    }\n\n  public:\n    ///\\name Execution control\n    ///The simplest way to execute the algorithm is to use\n    ///one of the member functions called \\c run(...).\n    ///\\n\n    ///If you need more control on the execution,\n    ///first you must call \\ref init(), then you can add a source node\n    ///with \\ref addSource().\n    ///Finally \\ref start() will perform the actual path\n    ///computation.\n\n    ///@{\n\n    ///Initializes the internal data structures.\n\n    ///Initializes the internal data structures.\n    ///\n    void init()\n    {\n      create_maps();\n      _stack.resize(countNodes(*G));\n      _stack_head=-1;\n      for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {\n\t_pred->set(u,INVALID);\n\t// _predNode->set(u,INVALID);\n\t_reached->set(u,false);\n\t_processed->set(u,false);\n      }\n    }\n    \n    ///Adds a new source node.\n\n    ///Adds a new source node to the set of nodes to be processed.\n    ///\n    ///\\warning dists are wrong (or at least strange)\n    ///in case of multiple sources.\n    void addSource(Node s)\n    {\n      if(!(*_reached)[s])\n\t{\n\t  _reached->set(s,true);\n\t  _pred->set(s,INVALID);\n\t  OutEdgeIt e(*G,s);\n\t  if(e!=INVALID) {\n\t    _stack[++_stack_head]=e;\n\t    _dist->set(s,_stack_head);\n\t  }\n\t  else {\n\t    _processed->set(s,true);\n\t    _dist->set(s,0);\n\t  }\n\t}\n    }\n    \n    ///Processes the next edge.\n\n    ///Processes the next edge.\n    ///\n    ///\\return The processed edge.\n    ///\n    ///\\pre The stack must not be empty!\n    Edge processNextEdge()\n    { \n      Node m;\n      Edge e=_stack[_stack_head];\n      if(!(*_reached)[m=G->target(e)]) {\n\t_pred->set(m,e);\n\t_reached->set(m,true);\n\t++_stack_head;\n\t_stack[_stack_head] = OutEdgeIt(*G, m);\n\t_dist->set(m,_stack_head);\n      }\n      else {\n\tm=G->source(e);\n\t++_stack[_stack_head];\n      }\n      while(_stack_head>=0 && _stack[_stack_head]==INVALID) {\n\t_processed->set(m,true);\n\t--_stack_head;\n\tif(_stack_head>=0) {\n\t  m=G->source(_stack[_stack_head]);\n\t  ++_stack[_stack_head];\n\t}\n      }\n      return e;\n    }\n    ///Next edge to be processed.\n\n    ///Next edge to be processed.\n    ///\n    ///\\return The next edge to be processed or INVALID if the stack is\n    /// empty.\n    OutEdgeIt nextEdge()\n    { \n      return _stack_head>=0?_stack[_stack_head]:INVALID;\n    }\n\n    ///\\brief Returns \\c false if there are nodes\n    ///to be processed in the queue\n    ///\n    ///Returns \\c false if there are nodes\n    ///to be processed in the queue\n    bool emptyQueue() { return _stack_head<0; }\n    ///Returns the number of the nodes to be processed.\n    \n    ///Returns the number of the nodes to be processed in the queue.\n    int queueSize() { return _stack_head+1; }\n    \n    ///Executes the algorithm.\n\n    ///Executes the algorithm.\n    ///\n    ///\\pre init() must be called and at least one node should be added\n    ///with addSource() before using this function.\n    ///\n    ///This method runs the %DFS algorithm from the root node(s)\n    ///in order to\n    ///compute the\n    ///%DFS path to each node. The algorithm computes\n    ///- The %DFS tree.\n    ///- The distance of each node from the root(s) in the %DFS tree.\n    ///\n    void start()\n    {\n      while ( !emptyQueue() ) processNextEdge();\n    }\n    \n    ///Executes the algorithm until \\c dest is reached.\n\n    ///Executes the algorithm until \\c dest is reached.\n    ///\n    ///\\pre init() must be called and at least one node should be added\n    ///with addSource() before using this function.\n    ///\n    ///This method runs the %DFS algorithm from the root node(s)\n    ///in order to\n    ///compute the\n    ///%DFS path to \\c dest. The algorithm computes\n    ///- The %DFS path to \\c  dest.\n    ///- The distance of \\c dest from the root(s) in the %DFS tree.\n    ///\n    void start(Node dest)\n    {\n      while ( !emptyQueue() && G->target(_stack[_stack_head])!=dest ) \n\tprocessNextEdge();\n    }\n    \n    ///Executes the algorithm until a condition is met.\n\n    ///Executes the algorithm until a condition is met.\n    ///\n    ///\\pre init() must be called and at least one node should be added\n    ///with addSource() before using this function.\n    ///\n    ///\\param em must be a bool (or convertible) edge map. The algorithm\n    ///will stop when it reaches an edge \\c e with <tt>em[e]</tt> true.\n    ///\n    ///\\return The reached edge \\c e with <tt>em[e]</tt> true or\n    ///\\c INVALID if no such edge was found.\n    ///\n    ///\\warning Contrary to \\ref Bfs and \\ref Dijkstra, \\c em is an edge map,\n    ///not a node map.\n    template<class EM>\n    Edge start(const EM &em)\n    {\n      while ( !emptyQueue() && !em[_stack[_stack_head]] )\n        processNextEdge();\n      return emptyQueue() ? INVALID : _stack[_stack_head];\n    }\n\n    ///Runs %DFS algorithm to visit all nodes in the graph.\n    \n    ///This method runs the %DFS algorithm in order to\n    ///compute the\n    ///%DFS path to each node. The algorithm computes\n    ///- The %DFS tree.\n    ///- The distance of each node from the root in the %DFS tree.\n    ///\n    ///\\note d.run() is just a shortcut of the following code.\n    ///\\code\n    ///  d.init();\n    ///  for (NodeIt it(graph); it != INVALID; ++it) {\n    ///    if (!d.reached(it)) {\n    ///      d.addSource(it);\n    ///      d.start();\n    ///    }\n    ///  }\n    ///\\endcode\n    void run() {\n      init();\n      for (NodeIt it(*G); it != INVALID; ++it) {\n        if (!reached(it)) {\n          addSource(it);\n          start();\n        }\n      }\n    }\n\n    ///Runs %DFS algorithm from node \\c s.\n    \n    ///This method runs the %DFS algorithm from a root node \\c s\n    ///in order to\n    ///compute the\n    ///%DFS path to each node. The algorithm computes\n    ///- The %DFS tree.\n    ///- The distance of each node from the root in the %DFS tree.\n    ///\n    ///\\note d.run(s) is just a shortcut of the following code.\n    ///\\code\n    ///  d.init();\n    ///  d.addSource(s);\n    ///  d.start();\n    ///\\endcode\n    void run(Node s) {\n      init();\n      addSource(s);\n      start();\n    }\n    \n    ///Finds the %DFS path between \\c s and \\c t.\n    \n    ///Finds the %DFS path between \\c s and \\c t.\n    ///\n    ///\\return The length of the %DFS s---t path if there exists one,\n    ///0 otherwise.\n    ///\\note Apart from the return value, d.run(s,t) is\n    ///just a shortcut of the following code.\n    ///\\code\n    ///  d.init();\n    ///  d.addSource(s);\n    ///  d.start(t);\n    ///\\endcode\n    int run(Node s,Node t) {\n      init();\n      addSource(s);\n      start(t);\n      return reached(t)?_stack_head+1:0;\n    }\n    \n    ///@}\n\n    ///\\name Query Functions\n    ///The result of the %DFS algorithm can be obtained using these\n    ///functions.\\n\n    ///Before the use of these functions,\n    ///either run() or start() must be called.\n    \n    ///@{\n\n    typedef PredMapPath<Graph, PredMap> Path;\n\n    ///Gives back the shortest path.\n    \n    ///Gives back the shortest path.\n    ///\\pre The \\c t should be reachable from the source.\n    Path path(Node t) \n    {\n      return Path(*G, *_pred, t);\n    }\n\n    ///The distance of a node from the root(s).\n\n    ///Returns the distance of a node from the root(s).\n    ///\\pre \\ref run() must be called before using this function.\n    ///\\warning If node \\c v is unreachable from the root(s) then the return \n    ///value of this funcion is undefined.\n    int dist(Node v) const { return (*_dist)[v]; }\n\n    ///Returns the 'previous edge' of the %DFS tree.\n\n    ///For a node \\c v it returns the 'previous edge'\n    ///of the %DFS path,\n    ///i.e. it returns the last edge of a %DFS path from the root(s) to \\c\n    ///v. It is \\ref INVALID\n    ///if \\c v is unreachable from the root(s) or \\c v is a root. The\n    ///%DFS tree used here is equal to the %DFS tree used in\n    ///\\ref predNode().\n    ///\\pre Either \\ref run() or \\ref start() must be called before using\n    ///this function.\n    Edge predEdge(Node v) const { return (*_pred)[v];}\n\n    ///Returns the 'previous node' of the %DFS tree.\n\n    ///For a node \\c v it returns the 'previous node'\n    ///of the %DFS tree,\n    ///i.e. it returns the last but one node from a %DFS path from the\n    ///root(s) to \\c v.\n    ///It is INVALID if \\c v is unreachable from the root(s) or\n    ///if \\c v itself a root.\n    ///The %DFS tree used here is equal to the %DFS\n    ///tree used in \\ref predEdge().\n    ///\\pre Either \\ref run() or \\ref start() must be called before\n    ///using this function.\n    Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID:\n\t\t\t\t  G->source((*_pred)[v]); }\n    \n    ///Returns a reference to the NodeMap of distances.\n\n    ///Returns a reference to the NodeMap of distances.\n    ///\\pre Either \\ref run() or \\ref init() must\n    ///be called before using this function.\n    const DistMap &distMap() const { return *_dist;}\n \n    ///Returns a reference to the %DFS edge-tree map.\n\n    ///Returns a reference to the NodeMap of the edges of the\n    ///%DFS tree.\n    ///\\pre Either \\ref run() or \\ref init()\n    ///must be called before using this function.\n    const PredMap &predMap() const { return *_pred;}\n \n    ///Checks if a node is reachable from the root.\n\n    ///Returns \\c true if \\c v is reachable from the root(s).\n    ///\\warning The source nodes are inditated as unreachable.\n    ///\\pre Either \\ref run() or \\ref start()\n    ///must be called before using this function.\n    ///\n    bool reached(Node v) { return (*_reached)[v]; }\n    \n    ///@}\n  };\n\n  ///Default traits class of Dfs function.\n\n  ///Default traits class of Dfs function.\n  ///\\param GR Graph type.\n  template<class GR>\n  struct DfsWizardDefaultTraits\n  {\n    ///The graph type the algorithm runs on. \n    typedef GR Graph;\n    ///\\brief The type of the map that stores the last\n    ///edges of the %DFS paths.\n    /// \n    ///The type of the map that stores the last\n    ///edges of the %DFS paths.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\n    typedef NullMap<typename Graph::Node,typename GR::Edge> PredMap;\n    ///Instantiates a PredMap.\n \n    ///This function instantiates a \\ref PredMap. \n    ///\\param g is the graph, to which we would like to define the PredMap.\n    ///\\todo The graph alone may be insufficient to initialize\n#ifdef DOXYGEN\n    static PredMap *createPredMap(const GR &g) \n#else\n    static PredMap *createPredMap(const GR &) \n#endif\n    {\n      return new PredMap();\n    }\n\n    ///The type of the map that indicates which nodes are processed.\n \n    ///The type of the map that indicates which nodes are processed.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\\todo named parameter to set this type, function to read and write.\n    typedef NullMap<typename Graph::Node,bool> ProcessedMap;\n    ///Instantiates a ProcessedMap.\n \n    ///This function instantiates a \\ref ProcessedMap. \n    ///\\param g is the graph, to which\n    ///we would like to define the \\ref ProcessedMap\n#ifdef DOXYGEN\n    static ProcessedMap *createProcessedMap(const GR &g)\n#else\n    static ProcessedMap *createProcessedMap(const GR &)\n#endif\n    {\n      return new ProcessedMap();\n    }\n    ///The type of the map that indicates which nodes are reached.\n \n    ///The type of the map that indicates which nodes are reached.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\\todo named parameter to set this type, function to read and write.\n    typedef typename Graph::template NodeMap<bool> ReachedMap;\n    ///Instantiates a ReachedMap.\n \n    ///This function instantiates a \\ref ReachedMap. \n    ///\\param G is the graph, to which\n    ///we would like to define the \\ref ReachedMap.\n    static ReachedMap *createReachedMap(const GR &G)\n    {\n      return new ReachedMap(G);\n    }\n    ///The type of the map that stores the dists of the nodes.\n \n    ///The type of the map that stores the dists of the nodes.\n    ///It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    ///\n    typedef NullMap<typename Graph::Node,int> DistMap;\n    ///Instantiates a DistMap.\n \n    ///This function instantiates a \\ref DistMap. \n    ///\\param g is the graph, to which we would like to define the \\ref DistMap\n#ifdef DOXYGEN\n    static DistMap *createDistMap(const GR &g)\n#else\n    static DistMap *createDistMap(const GR &)\n#endif\n    {\n      return new DistMap();\n    }\n  };\n  \n  /// Default traits used by \\ref DfsWizard\n\n  /// To make it easier to use Dfs algorithm\n  ///we have created a wizard class.\n  /// This \\ref DfsWizard class needs default traits,\n  ///as well as the \\ref Dfs class.\n  /// The \\ref DfsWizardBase is a class to be the default traits of the\n  /// \\ref DfsWizard class.\n  template<class GR>\n  class DfsWizardBase : public DfsWizardDefaultTraits<GR>\n  {\n\n    typedef DfsWizardDefaultTraits<GR> Base;\n  protected:\n    /// Type of the nodes in the graph.\n    typedef typename Base::Graph::Node Node;\n\n    /// Pointer to the underlying graph.\n    void *_g;\n    ///Pointer to the map of reached nodes.\n    void *_reached;\n    ///Pointer to the map of processed nodes.\n    void *_processed;\n    ///Pointer to the map of predecessors edges.\n    void *_pred;\n    ///Pointer to the map of distances.\n    void *_dist;\n    ///Pointer to the source node.\n    Node _source;\n    \n    public:\n    /// Constructor.\n    \n    /// This constructor does not require parameters, therefore it initiates\n    /// all of the attributes to default values (0, INVALID).\n    DfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0),\n\t\t\t   _dist(0), _source(INVALID) {}\n\n    /// Constructor.\n    \n    /// This constructor requires some parameters,\n    /// listed in the parameters list.\n    /// Others are initiated to 0.\n    /// \\param g is the initial value of  \\ref _g\n    /// \\param s is the initial value of  \\ref _source\n    DfsWizardBase(const GR &g, Node s=INVALID) :\n      _g(reinterpret_cast<void*>(const_cast<GR*>(&g))), \n      _reached(0), _processed(0), _pred(0), _dist(0), _source(s) {}\n\n  };\n  \n  /// A class to make the usage of the Dfs algorithm easier\n\n  /// This class is created to make it easier to use the Dfs algorithm.\n  /// It uses the functions and features of the plain \\ref Dfs,\n  /// but it is much simpler to use it.\n  ///\n  /// Simplicity means that the way to change the types defined\n  /// in the traits class is based on functions that returns the new class\n  /// and not on templatable built-in classes.\n  /// When using the plain \\ref Dfs\n  /// the new class with the modified type comes from\n  /// the original class by using the ::\n  /// operator. In the case of \\ref DfsWizard only\n  /// a function have to be called and it will\n  /// return the needed class.\n  ///\n  /// It does not have own \\ref run method. When its \\ref run method is called\n  /// it initiates a plain \\ref Dfs object, and calls the \\ref Dfs::run\n  /// method of it.\n  template<class TR>\n  class DfsWizard : public TR\n  {\n    typedef TR Base;\n\n    ///The type of the underlying graph.\n    typedef typename TR::Graph Graph;\n    //\\e\n    typedef typename Graph::Node Node;\n    //\\e\n    typedef typename Graph::NodeIt NodeIt;\n    //\\e\n    typedef typename Graph::Edge Edge;\n    //\\e\n    typedef typename Graph::OutEdgeIt OutEdgeIt;\n    \n    ///\\brief The type of the map that stores\n    ///the reached nodes\n    typedef typename TR::ReachedMap ReachedMap;\n    ///\\brief The type of the map that stores\n    ///the processed nodes\n    typedef typename TR::ProcessedMap ProcessedMap;\n    ///\\brief The type of the map that stores the last\n    ///edges of the %DFS paths.\n    typedef typename TR::PredMap PredMap;\n    ///The type of the map that stores the distances of the nodes.\n    typedef typename TR::DistMap DistMap;\n\n  public:\n    /// Constructor.\n    DfsWizard() : TR() {}\n\n    /// Constructor that requires parameters.\n\n    /// Constructor that requires parameters.\n    /// These parameters will be the default values for the traits class.\n    DfsWizard(const Graph &g, Node s=INVALID) :\n      TR(g,s) {}\n\n    ///Copy constructor\n    DfsWizard(const TR &b) : TR(b) {}\n\n    ~DfsWizard() {}\n\n    ///Runs Dfs algorithm from a given node.\n    \n    ///Runs Dfs algorithm from a given node.\n    ///The node can be given by the \\ref source function.\n    void run()\n    {\n      if(Base::_source==INVALID) throw UninitializedParameter();\n      Dfs<Graph,TR> alg(*reinterpret_cast<const Graph*>(Base::_g));\n      if(Base::_reached) \n        alg.reachedMap(*reinterpret_cast<ReachedMap*>(Base::_reached));\n      if(Base::_processed) \n        alg.processedMap(*reinterpret_cast<ProcessedMap*>(Base::_processed));\n      if(Base::_pred) \n        alg.predMap(*reinterpret_cast<PredMap*>(Base::_pred));\n      if(Base::_dist) \n        alg.distMap(*reinterpret_cast<DistMap*>(Base::_dist));\n      alg.run(Base::_source);\n    }\n\n    ///Runs Dfs algorithm from the given node.\n\n    ///Runs Dfs algorithm from the given node.\n    ///\\param s is the given source.\n    void run(Node s)\n    {\n      Base::_source=s;\n      run();\n    }\n\n    template<class T>\n    struct DefPredMapBase : public Base {\n      typedef T PredMap;\n      static PredMap *createPredMap(const Graph &) { return 0; };\n      DefPredMapBase(const TR &b) : TR(b) {}\n    };\n    \n    ///\\brief \\ref named-templ-param \"Named parameter\"\n    ///function for setting PredMap type\n    ///\n    /// \\ref named-templ-param \"Named parameter\"\n    ///function for setting PredMap type\n    ///\n    template<class T>\n    DfsWizard<DefPredMapBase<T> > predMap(const T &t) \n    {\n      Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));\n      return DfsWizard<DefPredMapBase<T> >(*this);\n    }\n    \n \n    template<class T>\n    struct DefReachedMapBase : public Base {\n      typedef T ReachedMap;\n      static ReachedMap *createReachedMap(const Graph &) { return 0; };\n      DefReachedMapBase(const TR &b) : TR(b) {}\n    };\n    \n    ///\\brief \\ref named-templ-param \"Named parameter\"\n    ///function for setting ReachedMap\n    ///\n    /// \\ref named-templ-param \"Named parameter\"\n    ///function for setting ReachedMap\n    ///\n    template<class T>\n    DfsWizard<DefReachedMapBase<T> > reachedMap(const T &t) \n    {\n      Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));\n      return DfsWizard<DefReachedMapBase<T> >(*this);\n    }\n    \n\n    template<class T>\n    struct DefProcessedMapBase : public Base {\n      typedef T ProcessedMap;\n      static ProcessedMap *createProcessedMap(const Graph &) { return 0; };\n      DefProcessedMapBase(const TR &b) : TR(b) {}\n    };\n    \n    ///\\brief \\ref named-templ-param \"Named parameter\"\n    ///function for setting ProcessedMap\n    ///\n    /// \\ref named-templ-param \"Named parameter\"\n    ///function for setting ProcessedMap\n    ///\n    template<class T>\n    DfsWizard<DefProcessedMapBase<T> > processedMap(const T &t) \n    {\n      Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));\n      return DfsWizard<DefProcessedMapBase<T> >(*this);\n    }\n    \n    template<class T>\n    struct DefDistMapBase : public Base {\n      typedef T DistMap;\n      static DistMap *createDistMap(const Graph &) { return 0; };\n      DefDistMapBase(const TR &b) : TR(b) {}\n    };\n    \n    ///\\brief \\ref named-templ-param \"Named parameter\"\n    ///function for setting DistMap type\n    ///\n    /// \\ref named-templ-param \"Named parameter\"\n    ///function for setting DistMap type\n    ///\n    template<class T>\n    DfsWizard<DefDistMapBase<T> > distMap(const T &t) \n    {\n      Base::_dist=reinterpret_cast<void*>(const_cast<T*>(&t));\n      return DfsWizard<DefDistMapBase<T> >(*this);\n    }\n    \n    /// Sets the source node, from which the Dfs algorithm runs.\n\n    /// Sets the source node, from which the Dfs algorithm runs.\n    /// \\param s is the source node.\n    DfsWizard<TR> &source(Node s) \n    {\n      Base::_source=s;\n      return *this;\n    }\n    \n  };\n  \n  ///Function type interface for Dfs algorithm.\n\n  ///\\ingroup search\n  ///Function type interface for Dfs algorithm.\n  ///\n  ///This function also has several\n  ///\\ref named-templ-func-param \"named parameters\",\n  ///they are declared as the members of class \\ref DfsWizard.\n  ///The following\n  ///example shows how to use these parameters.\n  ///\\code\n  ///  dfs(g,source).predMap(preds).run();\n  ///\\endcode\n  ///\\warning Don't forget to put the \\ref DfsWizard::run() \"run()\"\n  ///to the end of the parameter list.\n  ///\\sa DfsWizard\n  ///\\sa Dfs\n  template<class GR>\n  DfsWizard<DfsWizardBase<GR> >\n  dfs(const GR &g,typename GR::Node s=INVALID)\n  {\n    return DfsWizard<DfsWizardBase<GR> >(g,s);\n  }\n\n#ifdef DOXYGEN\n  /// \\brief Visitor class for dfs.\n  ///  \n  /// It gives a simple interface for a functional interface for dfs \n  /// traversal. The traversal on a linear data structure. \n  template <typename _Graph>\n  struct DfsVisitor {\n    typedef _Graph Graph;\n    typedef typename Graph::Edge Edge;\n    typedef typename Graph::Node Node;\n    /// \\brief Called when the edge reach a node.\n    /// \n    /// It is called when the dfs find an edge which target is not\n    /// reached yet.\n    void discover(const Edge& edge) {}\n    /// \\brief Called when the node reached first time.\n    /// \n    /// It is Called when the node reached first time.\n    void reach(const Node& node) {}\n    /// \\brief Called when we step back on an edge.\n    /// \n    /// It is called when the dfs should step back on the edge.\n    void backtrack(const Edge& edge) {}\n    /// \\brief Called when we step back from the node.\n    /// \n    /// It is called when we step back from the node.\n    void leave(const Node& node) {}\n    /// \\brief Called when the edge examined but target of the edge \n    /// already discovered.\n    /// \n    /// It called when the edge examined but the target of the edge \n    /// already discovered.\n    void examine(const Edge& edge) {}\n    /// \\brief Called for the source node of the dfs.\n    /// \n    /// It is called for the source node of the dfs.\n    void start(const Node& node) {}\n    /// \\brief Called when we leave the source node of the dfs.\n    /// \n    /// It is called when we leave the source node of the dfs.\n    void stop(const Node& node) {}\n\n  };\n#else\n  template <typename _Graph>\n  struct DfsVisitor {\n    typedef _Graph Graph;\n    typedef typename Graph::Edge Edge;\n    typedef typename Graph::Node Node;\n    void discover(const Edge&) {}\n    void reach(const Node&) {}\n    void backtrack(const Edge&) {}\n    void leave(const Node&) {}\n    void examine(const Edge&) {}\n    void start(const Node&) {}\n    void stop(const Node&) {}\n\n    template <typename _Visitor>\n    struct Constraints {\n      void constraints() {\n\tEdge edge;\n\tNode node;\n\tvisitor.discover(edge);\n\tvisitor.reach(node);\n\tvisitor.backtrack(edge);\n\tvisitor.leave(node);\n\tvisitor.examine(edge);\n\tvisitor.start(node);\n\tvisitor.stop(edge);\n      }\n      _Visitor& visitor;\n    };\n  };\n#endif\n\n  /// \\brief Default traits class of DfsVisit class.\n  ///\n  /// Default traits class of DfsVisit class.\n  /// \\param _Graph Graph type.\n  template<class _Graph>\n  struct DfsVisitDefaultTraits {\n\n    /// \\brief The graph type the algorithm runs on. \n    typedef _Graph Graph;\n\n    /// \\brief The type of the map that indicates which nodes are reached.\n    /// \n    /// The type of the map that indicates which nodes are reached.\n    /// It must meet the \\ref concepts::WriteMap \"WriteMap\" concept.\n    /// \\todo named parameter to set this type, function to read and write.\n    typedef typename Graph::template NodeMap<bool> ReachedMap;\n\n    /// \\brief Instantiates a ReachedMap.\n    ///\n    /// This function instantiates a \\ref ReachedMap. \n    /// \\param graph is the graph, to which\n    /// we would like to define the \\ref ReachedMap.\n    static ReachedMap *createReachedMap(const Graph &graph) {\n      return new ReachedMap(graph);\n    }\n\n  };\n  \n  /// %DFS Visit algorithm class.\n  \n  /// \\ingroup search\n  /// This class provides an efficient implementation of the %DFS algorithm\n  /// with visitor interface.\n  ///\n  /// The %DfsVisit class provides an alternative interface to the Dfs\n  /// class. It works with callback mechanism, the DfsVisit object calls\n  /// on every dfs event the \\c Visitor class member functions. \n  ///\n  /// \\param _Graph The graph type the algorithm runs on. The default value is\n  /// \\ref ListGraph. The value of _Graph is not used directly by Dfs, it\n  /// is only passed to \\ref DfsDefaultTraits.\n  /// \\param _Visitor The Visitor object for the algorithm. The \n  /// \\ref DfsVisitor \"DfsVisitor<_Graph>\" is an empty Visitor which\n  /// does not observe the Dfs events. If you want to observe the dfs\n  /// events you should implement your own Visitor class.\n  /// \\param _Traits Traits class to set various data types used by the \n  /// algorithm. The default traits class is\n  /// \\ref DfsVisitDefaultTraits \"DfsVisitDefaultTraits<_Graph>\".\n  /// See \\ref DfsVisitDefaultTraits for the documentation of\n  /// a Dfs visit traits class.\n  ///\n  /// \\author Jacint Szabo, Alpar Juttner and Balazs Dezso\n#ifdef DOXYGEN\n  template <typename _Graph, typename _Visitor, typename _Traits>\n#else\n  template <typename _Graph = ListGraph,\n\t    typename _Visitor = DfsVisitor<_Graph>,\n\t    typename _Traits = DfsDefaultTraits<_Graph> >\n#endif\n  class DfsVisit {\n  public:\n    \n    /// \\brief \\ref Exception for uninitialized parameters.\n    ///\n    /// This error represents problems in the initialization\n    /// of the parameters of the algorithms.\n    class UninitializedParameter : public lemon::UninitializedParameter {\n    public:\n      virtual const char* what() const throw() \n      {\n\treturn \"lemon::DfsVisit::UninitializedParameter\";\n      }\n    };\n\n    typedef _Traits Traits;\n\n    typedef typename Traits::Graph Graph;\n\n    typedef _Visitor Visitor;\n\n    ///The type of the map indicating which nodes are reached.\n    typedef typename Traits::ReachedMap ReachedMap;\n\n  private:\n\n    typedef typename Graph::Node Node;\n    typedef typename Graph::NodeIt NodeIt;\n    typedef typename Graph::Edge Edge;\n    typedef typename Graph::OutEdgeIt OutEdgeIt;\n\n    /// Pointer to the underlying graph.\n    const Graph *_graph;\n    /// Pointer to the visitor object.\n    Visitor *_visitor;\n    ///Pointer to the map of reached status of the nodes.\n    ReachedMap *_reached;\n    ///Indicates if \\ref _reached is locally allocated (\\c true) or not.\n    bool local_reached;\n\n    std::vector<typename Graph::Edge> _stack;\n    int _stack_head;\n\n    /// \\brief Creates the maps if necessary.\n    ///\n    /// Creates the maps if necessary.\n    void create_maps() {\n      if(!_reached) {\n\tlocal_reached = true;\n\t_reached = Traits::createReachedMap(*_graph);\n      }\n    }\n\n  protected:\n\n    DfsVisit() {}\n    \n  public:\n\n    typedef DfsVisit Create;\n\n    /// \\name Named template parameters\n\n    ///@{\n    template <class T>\n    struct DefReachedMapTraits : public Traits {\n      typedef T ReachedMap;\n      static ReachedMap *createReachedMap(const Graph &graph) {\n\tthrow UninitializedParameter();\n      }\n    };\n    /// \\brief \\ref named-templ-param \"Named parameter\" for setting \n    /// ReachedMap type\n    ///\n    /// \\ref named-templ-param \"Named parameter\" for setting ReachedMap type\n    template <class T>\n    struct DefReachedMap : public DfsVisit< Graph, Visitor,\n\t\t\t\t\t    DefReachedMapTraits<T> > {\n      typedef DfsVisit< Graph, Visitor, DefReachedMapTraits<T> > Create;\n    };\n    ///@}\n\n  public:      \n    \n    /// \\brief Constructor.\n    ///\n    /// Constructor.\n    ///\n    /// \\param graph the graph the algorithm will run on.\n    /// \\param visitor The visitor of the algorithm.\n    ///\n    DfsVisit(const Graph& graph, Visitor& visitor) \n      : _graph(&graph), _visitor(&visitor),\n\t_reached(0), local_reached(false) {}\n    \n    /// \\brief Destructor.\n    ///\n    /// Destructor.\n    ~DfsVisit() {\n      if(local_reached) delete _reached;\n    }\n\n    /// \\brief Sets the map indicating if a node is reached.\n    ///\n    /// Sets the map indicating if a node is reached.\n    /// If you don't use this function before calling \\ref run(),\n    /// it will allocate one. The destuctor deallocates this\n    /// automatically allocated map, of course.\n    /// \\return <tt> (*this) </tt>\n    DfsVisit &reachedMap(ReachedMap &m) {\n      if(local_reached) {\n\tdelete _reached;\n\tlocal_reached=false;\n      }\n      _reached = &m;\n      return *this;\n    }\n\n  public:\n    /// \\name Execution control\n    /// The simplest way to execute the algorithm is to use\n    /// one of the member functions called \\c run(...).\n    /// \\n\n    /// If you need more control on the execution,\n    /// first you must call \\ref init(), then you can adda source node\n    /// with \\ref addSource().\n    /// Finally \\ref start() will perform the actual path\n    /// computation.\n\n    /// @{\n    /// \\brief Initializes the internal data structures.\n    ///\n    /// Initializes the internal data structures.\n    ///\n    void init() {\n      create_maps();\n      _stack.resize(countNodes(*_graph));\n      _stack_head = -1;\n      for (NodeIt u(*_graph) ; u != INVALID ; ++u) {\n\t_reached->set(u, false);\n      }\n    }\n    \n    /// \\brief Adds a new source node.\n    ///\n    /// Adds a new source node to the set of nodes to be processed.\n    void addSource(Node s) {\n      if(!(*_reached)[s]) {\n\t  _reached->set(s,true);\n\t  _visitor->start(s);\n\t  _visitor->reach(s);\n\t  Edge e; \n\t  _graph->firstOut(e, s);\n\t  if (e != INVALID) {\n\t    _stack[++_stack_head] = e;\n\t  } else {\n\t    _visitor->leave(s);\n\t  }\n\t}\n    }\n    \n    /// \\brief Processes the next edge.\n    ///\n    /// Processes the next edge.\n    ///\n    /// \\return The processed edge.\n    ///\n    /// \\pre The stack must not be empty!\n    Edge processNextEdge() { \n      Edge e = _stack[_stack_head];\n      Node m = _graph->target(e);\n      if(!(*_reached)[m]) {\n\t_visitor->discover(e);\n\t_visitor->reach(m);\n\t_reached->set(m, true);\n\t_graph->firstOut(_stack[++_stack_head], m);\n      } else {\n\t_visitor->examine(e);\n\tm = _graph->source(e);\n\t_graph->nextOut(_stack[_stack_head]);\n      }\n      while (_stack_head>=0 && _stack[_stack_head] == INVALID) {\n\t_visitor->leave(m);\n\t--_stack_head;\n\tif (_stack_head >= 0) {\n\t  _visitor->backtrack(_stack[_stack_head]);\n\t  m = _graph->source(_stack[_stack_head]);\n\t  _graph->nextOut(_stack[_stack_head]);\n\t} else {\n\t  _visitor->stop(m);\t  \n\t}\n      }\n      return e;\n    }\n\n    /// \\brief Next edge to be processed.\n    ///\n    /// Next edge to be processed.\n    ///\n    /// \\return The next edge to be processed or INVALID if the stack is\n    /// empty.\n    Edge nextEdge() { \n      return _stack_head >= 0 ? _stack[_stack_head] : INVALID;\n    }\n\n    /// \\brief Returns \\c false if there are nodes\n    /// to be processed in the queue\n    ///\n    /// Returns \\c false if there are nodes\n    /// to be processed in the queue\n    bool emptyQueue() { return _stack_head < 0; }\n\n    /// \\brief Returns the number of the nodes to be processed.\n    ///\n    /// Returns the number of the nodes to be processed in the queue.\n    int queueSize() { return _stack_head + 1; }\n    \n    /// \\brief Executes the algorithm.\n    ///\n    /// Executes the algorithm.\n    ///\n    /// \\pre init() must be called and at least one node should be added\n    /// with addSource() before using this function.\n    void start() {\n      while ( !emptyQueue() ) processNextEdge();\n    }\n    \n    /// \\brief Executes the algorithm until \\c dest is reached.\n    ///\n    /// Executes the algorithm until \\c dest is reached.\n    ///\n    /// \\pre init() must be called and at least one node should be added\n    /// with addSource() before using this function.\n    void start(Node dest) {\n      while ( !emptyQueue() && _graph->target(_stack[_stack_head]) != dest ) \n\tprocessNextEdge();\n    }\n    \n    /// \\brief Executes the algorithm until a condition is met.\n    ///\n    /// Executes the algorithm until a condition is met.\n    ///\n    /// \\pre init() must be called and at least one node should be added\n    /// with addSource() before using this function.\n    ///\n    /// \\param em must be a bool (or convertible) edge map. The algorithm\n    /// will stop when it reaches an edge \\c e with <tt>em[e]</tt> true.\n    ///\n    ///\\return The reached edge \\c e with <tt>em[e]</tt> true or\n    ///\\c INVALID if no such edge was found.\n    ///\n    /// \\warning Contrary to \\ref Bfs and \\ref Dijkstra, \\c em is an edge map,\n    /// not a node map.\n    template <typename EM>\n    Edge start(const EM &em) {\n      while ( !emptyQueue() && !em[_stack[_stack_head]] )\n        processNextEdge();\n      return emptyQueue() ? INVALID : _stack[_stack_head];\n    }\n\n    /// \\brief Runs %DFSVisit algorithm from node \\c s.\n    ///\n    /// This method runs the %DFS algorithm from a root node \\c s.\n    /// \\note d.run(s) is just a shortcut of the following code.\n    ///\\code\n    ///   d.init();\n    ///   d.addSource(s);\n    ///   d.start();\n    ///\\endcode\n    void run(Node s) {\n      init();\n      addSource(s);\n      start();\n    }\n\n    /// \\brief Runs %DFSVisit algorithm to visit all nodes in the graph.\n    \n    /// This method runs the %DFS algorithm in order to\n    /// compute the %DFS path to each node. The algorithm computes\n    /// - The %DFS tree.\n    /// - The distance of each node from the root in the %DFS tree.\n    ///\n    ///\\note d.run() is just a shortcut of the following code.\n    ///\\code\n    ///  d.init();\n    ///  for (NodeIt it(graph); it != INVALID; ++it) {\n    ///    if (!d.reached(it)) {\n    ///      d.addSource(it);\n    ///      d.start();\n    ///    }\n    ///  }\n    ///\\endcode\n    void run() {\n      init();\n      for (NodeIt it(*_graph); it != INVALID; ++it) {\n        if (!reached(it)) {\n          addSource(it);\n          start();\n        }\n      }\n    }\n    ///@}\n\n    /// \\name Query Functions\n    /// The result of the %DFS algorithm can be obtained using these\n    /// functions.\\n\n    /// Before the use of these functions,\n    /// either run() or start() must be called.\n    ///@{\n    /// \\brief Checks if a node is reachable from the root.\n    ///\n    /// Returns \\c true if \\c v is reachable from the root(s).\n    /// \\warning The source nodes are inditated as unreachable.\n    /// \\pre Either \\ref run() or \\ref start()\n    /// must be called before using this function.\n    ///\n    bool reached(Node v) { return (*_reached)[v]; }\n    ///@}\n  };\n\n\n} //END OF NAMESPACE LEMON\n\n#endif\n\n"
  },
  {
    "path": "src/lemon/error.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_ERROR_H\n#define LEMON_ERROR_H\n\n//! \\ingroup exceptions\n//! \\file\n//! \\brief Basic exception classes and error handling.\n\n#include <exception>\n#include <string>\n#include <sstream>\n#include <iostream>\n#include <cstdlib>\n#include <memory>\n\nnamespace lemon {\n\n  /// \\addtogroup exceptions\n  /// @{\n  \n  /// \\brief Exception safe wrapper class.\n  ///\n  /// Exception safe wrapper class to implement the members of exceptions.\n  template <typename _Type>\n  class ExceptionMember {\n  public:\n    typedef _Type Type;\n\n    ExceptionMember() throw () {\n      try {\n\tptr.reset(new Type());\n      } catch (...) {}\n    }\n\n    ExceptionMember(const Type& type) throw () {\n      try {\n\tptr.reset(new Type());\n\tif (ptr.get() == 0) return;\n\t*ptr = type;\n      } catch (...) {}\n    }\n\n    ExceptionMember(const ExceptionMember& copy) throw() {\n      try {\n\tif (!copy.valid()) return;\n\tptr.reset(new Type());\n\tif (ptr.get() == 0) return;\n\t*ptr = copy.get();\n      } catch (...) {}\n    }\n\n    ExceptionMember& operator=(const ExceptionMember& copy) {\n      if (ptr.get() == 0) return *this;\n      try {\n\tif (!copy.valid()) return *this;\n \t*ptr = copy.get();\n      } catch (...) {}\n    }\n\n    void set(const Type& type) {\n      if (ptr.get() == 0) return;\n      try {\n\t*ptr = type;\n      } catch (...) {}\n    }\n\n    const Type& get() const {\n      return *ptr;\n    }\n\n    bool valid() const {\n      return ptr.get() != 0;\n    }\n    \n  private:\n    std::auto_ptr<_Type> ptr;\n  };\n\n  /// Exception-safe convenient \"error message\" class.\n\n  /// Helper class which provides a convenient ostream-like (operator <<\n  /// based) interface to create a string message. Mostly useful in\n  /// exception classes (therefore the name).\n  class ErrorMessage {\n  protected:\n    ///\\e \n\n    ///\\todo The good solution is boost::shared_ptr...\n    ///\n    mutable\n    std::auto_ptr<std::ostringstream> buf;\n    \n    ///\\e \n    bool init() throw() {\n      try {\n\tbuf.reset(new std::ostringstream);\n      }\n      catch(...) {\n\tbuf.reset();\n      }\n      return buf.get();\n    }\n\n  public:\n\n    ///\\e \n    ErrorMessage() throw() { init(); }\n\n    ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }\n\n    ///\\e \n    ErrorMessage(const char *msg) throw() {\n      init();\n      *this << msg;\n    }\n\n    ///\\e \n    ErrorMessage(const std::string &msg) throw() {\n      init();\n      *this << msg;\n    }\n\n    ///\\e \n    template <typename T>\n    ErrorMessage& operator<<(const T &t) throw() {\n      if( ! buf.get() ) return *this;\n\n      try {\n\t*buf << t;\n      }\n      catch(...) {\n\tbuf.reset();\n      }\n      return *this;\n    }\n\n    ///\\e \n    const char* message() throw() {\n      if( ! buf.get() ) return 0;\n\n      const char* mes = 0;\n      try {\n\tmes = buf->str().c_str();\n      }\n      catch(...) {}\n      return mes;\n    }\n    \n  };\n\n  /**\n   * \\brief Generic exception class.\n   *\n   * Base class for exceptions used in LEMON.\n   */\n  class Exception : public std::exception {\n  public:\n    ///\\e \n    Exception() {}\n    ///\\e \n    virtual ~Exception() throw() {}\n    ///\\e \n    virtual const char* what() const throw() {\n      return \"lemon::Exception\";\n    }\n  };\n\n  /**\n   * \\brief One of the two main subclasses of \\ref Exception.\n   *\n   * Logic errors represent problems in the internal logic of a program;\n   * in theory, these are preventable, and even detectable before the\n   * program runs (e.g., violations of class invariants).\n   *\n   * A typical example for this is \\ref UninitializedParameter.\n   */\n  class LogicError : public Exception {\n  public:\n    virtual const char* what() const throw() {\n      return \"lemon::LogicError\";\n    }\n  };\n\n  /**\n   * \\brief \\ref Exception for uninitialized parameters.\n   *\n   * This error represents problems in the initialization\n   * of the parameters of the algorithms.\n   */\n  class UninitializedParameter : public LogicError {\n  public:\n    virtual const char* what() const throw() {\n      return \"lemon::UninitializedParameter\";\n    }\n  };\n\n  \n  /**\n   * \\brief One of the two main subclasses of \\ref Exception.\n   *\n   * Runtime errors represent problems outside the scope of a program;\n   * they cannot be easily predicted and can generally only be caught as\n   * the program executes.\n   */\n  class RuntimeError : public Exception {\n  public:\n    virtual const char* what() const throw() {\n      return \"lemon::RuntimeError\";\n    }\n  };\n\n  ///\\e\n  class RangeError : public RuntimeError {\n  public:\n    virtual const char* what() const throw() {\n      return \"lemon::RangeError\";\n    }\n  };\n\n  ///\\e \n  class IoError : public RuntimeError {\n  public:\n    virtual const char* what() const throw() {\n      return \"lemon::IoError\";\n    }\n  };\n\n  ///\\e \n  class DataFormatError : public IoError {\n  protected:\n    ExceptionMember<std::string> _message;\n    ExceptionMember<std::string> _file;\n    int _line;\n\n    mutable ExceptionMember<std::string> _message_holder;\n  public:\n\n    DataFormatError(const DataFormatError &dfe) : \n      IoError(dfe), _message(dfe._message), _file(dfe._file),\n      _line(dfe._line) {}\n\n    ///\\e \n    explicit DataFormatError(const char *the_message)\n      : _message(the_message), _line(0) {}\n\n    ///\\e \n    DataFormatError(const std::string &file_name, int line_num,\n\t\t    const char *the_message)\n      : _message(the_message), _line(line_num) { file(file_name); }\n\n    ///\\e \n    void line(int ln) { _line = ln; }\n    ///\\e \n    void message(const std::string& msg) { _message.set(msg); }\n    ///\\e \n    void file(const std::string &fl) { _file.set(fl); }\n \n    ///\\e\n    int line() const { return _line; }\n    ///\\e\n    const char* message() const { \n      if (_message.valid() && !_message.get().empty()) {\n\treturn _message.get().c_str();\n      } else {\n\treturn 0;\n      }\n    }\n\n    /// \\brief Returns the filename.\n    ///\n    /// Returns \\e null if the filename was not specified.\n    const char* file() const {\n      if (_file.valid() && !_file.get().empty()) {\n\treturn _file.get().c_str();\n      } else {\n\treturn 0;\n      }\n    }\n\n    ///\\e \n    virtual const char* what() const throw() {\n      try {\n\tstd::ostringstream ostr;\n\tostr << \"lemon:DataFormatError\" << \": \";\n\tif (message()) ostr << message();\n\tif( file() || line() != 0 ) {\n\t  ostr << \" (\";\n\t  if( file() ) ostr << \"in file '\" << file() << \"'\";\n\t  if( file() && line() != 0 ) ostr << \" \";\n\t  if( line() != 0 ) ostr << \"at line \" << line();\n\t  ostr << \")\";\n\t}\n\t_message_holder.set(ostr.str());\n      }\n      catch (...) {}\n      if( _message_holder.valid()) return _message_holder.get().c_str();\n      return \"lemon:DataFormatError\";\n    }\n\n    virtual ~DataFormatError() throw() {}\n  };\n\n  ///\\e \n  class FileOpenError : public IoError {\n  protected:\n    ExceptionMember<std::string> _file;\n\n    mutable ExceptionMember<std::string> _message_holder;\n  public:\n\n    FileOpenError(const FileOpenError &foe) : \n      IoError(foe), _file(foe._file) {}\n\n    ///\\e \n    explicit FileOpenError(const std::string& fl)\n      : _file(fl) {}\n\n\n    ///\\e \n    void file(const std::string &fl) { _file.set(fl); }\n \n    /// \\brief Returns the filename.\n    ///\n    /// Returns \\e null if the filename was not specified.\n    const char* file() const {\n      if (_file.valid() && !_file.get().empty()) {\n\treturn _file.get().c_str();\n      } else {\n\treturn 0;\n      }\n    }\n\n    ///\\e \n    virtual const char* what() const throw() {\n      try {\n\tstd::ostringstream ostr;\n\tostr << \"lemon::FileOpenError\" << \": \";\n\tostr << \"Cannot open file - \" << file();\n\t_message_holder.set(ostr.str());\n      }\n      catch (...) {}\n      if( _message_holder.valid()) return _message_holder.get().c_str();\n      return \"lemon::FileOpenError\";\n    }\n    virtual ~FileOpenError() throw() {}\n  };\n\n  class IoParameterError : public IoError {\n  protected:\n    ExceptionMember<std::string> _message;\n    ExceptionMember<std::string> _file;\n\n    mutable ExceptionMember<std::string> _message_holder;\n  public:\n\n    IoParameterError(const IoParameterError &ile) : \n      IoError(ile), _message(ile._message), _file(ile._file) {}\n\n    ///\\e \n    explicit IoParameterError(const char *the_message)\n      : _message(the_message) {}\n\n    ///\\e \n    IoParameterError(const char *file_name, const char *the_message)\n      : _message(the_message), _file(file_name) {}\n\n     ///\\e \n    void message(const std::string& msg) { _message.set(msg); }\n    ///\\e \n    void file(const std::string &fl) { _file.set(fl); }\n \n     ///\\e\n    const char* message() const { \n      if (_message.valid()) {\n\treturn _message.get().c_str();\n      } else {\n\treturn 0;\n      }\n    }\n\n    /// \\brief Returns the filename.\n    ///\n    /// Returns \\e null if the filename was not specified.\n    const char* file() const {\n      if (_file.valid()) {\n\treturn _file.get().c_str();\n      } else {\n\treturn 0;\n      }\n    }\n\n    ///\\e \n    virtual const char* what() const throw() {\n      try {\n\tstd::ostringstream ostr;\n\tif (message()) ostr << message();\n\tif (file()) ostr << \"(when reading file '\" << file() << \"')\";\n\t_message_holder.set(ostr.str());\n      }\n      catch (...) {}\n      if( _message_holder.valid() ) return _message_holder.get().c_str();\n      return \"lemon:IoParameterError\";\n    }\n    virtual ~IoParameterError() throw() {}\n  };\n\n\n  ///\\e\n  class AssertionFailedError : public LogicError {\n  protected:\n    const char *assertion;\n    const char *file;\n    int line;\n    const char *function;\n    const char *message;\n\n    mutable ExceptionMember<std::string> _message_holder;\n  public:\n    ///\\e\n    AssertionFailedError(const char *_file, int _line, const char *func,\n\t\t\t const char *msg, const char *_assertion = 0) :\n      assertion(_assertion), file(_file), line(_line), function(func),\n      message(msg) {}\n\n    ///\\e\n    const char* get_assertion() const { return assertion; }\n    ///\\e\n    const char* get_message() const { return message; }\n    ///\\e\n    const char* get_file() const { return file; }\n    ///\\e\n    const char* get_function() const { return function; }\n    ///\\e\n    int get_line() const { return line; }\n\n\n    virtual const char* what() const throw() {\n      try {\n\tstd::ostringstream ostr;\n\tostr << file << \":\" << line << \": \";\n\tif( function )\n\t  ostr << function << \": \";\n\tostr << message;\n\tif( assertion )\n\t   ostr << \" (assertion '\" << assertion << \"' failed)\";\n\t_message_holder.set(ostr.str());\n\treturn ostr.str().c_str();\n      }\n      catch(...) {}\n      if( _message_holder.valid() ) return _message_holder.get().c_str();\n      return \"lemon::AssertionFailedError\";\n    }\n   virtual ~AssertionFailedError() throw() {}\n  };\n\n\n  /****************  Macros  ****************/\n\n\n  template <typename Exception>\n  inline void assert_fail(const char *file, int line, \n                          const char *func,\n                          Exception exception, \n                          const char *assertion = 0,\n                          bool do_abort=true)\n  {\n    using namespace std;\n    cerr << file << \":\" << line << \": \";\n    if( func )\n      cerr << func << \": \";\n    cerr << exception.what();\n    if( assertion )\n      cerr << \" (assertion '\" << assertion << \"' failed)\";\n    cerr << endl;\n    if(do_abort)\n      abort();\n  }\n\n  template <>\n  inline void assert_fail<const char *>(const char *file, int line, \n                                        const char *func,\n                                        const char *message, \n                                        const char *assertion,\n                                        bool do_abort)\n  {\n    using namespace std;\n    cerr << file << \":\" << line << \": \";\n    if( func )\n      cerr << func << \": \";\n    cerr << message;\n    if( assertion )\n      cerr << \" (assertion '\" << assertion << \"' failed)\";\n    cerr << endl;\n    if(do_abort)\n      abort();\n  }\n\n  template <>\n  inline void assert_fail<std::string>(const char *file, int line, \n                                       const char *func,\n                                       std::string message, \n                                       const char *assertion,\n                                       bool do_abort)\n  {\n    assert_fail(file, line, func, message.c_str(), assertion, do_abort);\n  }\n\n  template <typename Exception>\n  inline void assert_fail_failure(const char *file, int line, const char *func,\n\t\t\t   Exception exception, \n\t\t\t   const char *assertion = 0,\n\t\t\t   bool = true)\n  {\n    throw AssertionFailedError(file, line, func, exception.what(), assertion);\n  }\n\n  template <>\n  inline void assert_fail_failure<const char *>(const char *file, int line, \n                                                const char *func,\n                                                const char *message, \n                                                const char *assertion,\n                                                bool)\n  {\n    throw AssertionFailedError(file, line, func, message, assertion);\n  }\n\n  template <>\n  inline void assert_fail_failure<std::string>(const char *file, int line, \n                                               const char *func,\n                                               std::string message, \n                                               const char *assertion,\n                                               bool)\n  {\n    assert_fail_failure(file, line, func, message.c_str(), assertion, true);\n  }\n\n  template <typename Exception> \n  inline void assert_fail_exception(const char *file, int line, const char *func,\n\t\t\t     Exception exception, \n\t\t\t     const char *assertion = 0, bool = true)\n  {\n    throw exception;\n  }\n\n  template <> \n  inline void assert_fail_exception<const char *>(const char *file, int line, \n\t\t\t\t\t   const char *func,\n\t\t\t\t\t   const char *message, \n\t\t\t\t\t   const char *assertion,\n\t\t\t\t\t   bool)\n  {\n    throw AssertionFailedError(file, line, func, message, assertion);\n  }\n\n  template <>\n  inline void assert_fail_exception<std::string>(const char *file, int line, \n                                                 const char *func,\n                                                 std::string message, \n                                                 const char *assertion,\n                                                 bool)\n  {\n    assert_fail_exception(file, line, func, message.c_str(), assertion, true);    \n  }\n\n/// @}\n\n}\n#endif // LEMON_ERROR_H\n\n#undef LEMON_ASSERT\n#undef LEMON_FIXME\n\n#ifdef LEMON_ENABLE_ASSERTS\n#  define LEMON_ASSERT_ABORT\n#endif\n\n#ifndef LEMON_ASSERT_DO_ABORT\n#  define LEMON_ASSERT_DO_ABORT 1\n#endif\n\n#ifndef LEMON_ASSERT_HANDLER\n#  if defined LEMON_ASSERT_EXCEPTION\n#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception\n#  elif defined LEMON_ASSERT_FAILURE\n#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure\n#  elif defined LEMON_ASSERT_ABORT\n#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail\n#  else\n#    define LEMON_DISABLE_ASSERTS\n#  endif\n#endif\n\n#ifdef DOXYGEN\n\n/// \\brief Macro for assertions with customizable message\n///\n/// Macro for assertions with customizable message.\n///\n/// The assertions are disabled in the default behaviour. You can\n/// enable the assertions with the\n/// \\code\n/// #define LEMON_ENABLE_ASSERTS\n/// \\endcode\n/// Then an assert\n/// provides a log on the standard error about the assertion and aborts\n/// the program if LEMON_ASSERT_DO_ABORT is also defined (otherwise the\n/// program keeps on running).\n/// By defining LEMON_ASSERT_FAILURE or\n/// LEMON_ASSERT_EXCEPTION, you can set other behaviour to the\n/// assertions. In case LEMON_ASSERT_FAILURE is given, LEMON_ASSERT\n/// will always throw an \\c AssertionFailedError exception with\n/// the \\c msg error message. By using\n/// LEMON_ASSERT_EXCEPTION, one can define an arbitrary exception to be thrown.\n///\n/// The LEMON_ASSERT macro should be called with the \\c exp parameter\n/// which should be an expression convertible to bool. If the given\n/// parameter is false the assertion is raised and one of the assertion\n/// behaviour will be activated. The \\c msg should be either a const\n/// char* message or an exception. When the \\c msg is an exception the\n/// \\ref lemon::Exception::what() \"what()\" function is called to retrieve and\n/// display the error message.\n///\n/// \\todo We should provide some way to reset to the default behaviour,\n/// shouldn't we?\n///\n/// \\todo This whole 'assert' business should be placed in a separate\n/// include file. The boost assert is not guarded by header sentries\n/// which may help to change the behaviour of the assertions in \n/// the files.\n///\n/// \\todo __PRETTY_FUNCTION__ should be replaced by something\n/// compiler-independent, like BOOST_CURRENT_FUNCTION\n\n#  define LEMON_ASSERT(exp, msg)                 \\\n     (static_cast<void> (!!(exp) ? 0 : (         \\\n       LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \\\n                            __PRETTY_FUNCTION__, \\\n                            msg, #exp, LEMON_ASSERT_DO_ABORT), 0)))\n\n#else \n#  if defined LEMON_DISABLE_ASSERTS\n\n#    define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))\n\n#  else\n#    define LEMON_ASSERT(exp, msg)                 \\\n       (static_cast<void> (!!(exp) ? 0 : (         \\\n         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \\\n                              __PRETTY_FUNCTION__, \\\n                              msg, #exp, LEMON_ASSERT_DO_ABORT), 0)))\n#  endif\n#endif\n\n/**\n * \\brief Macro for mark not yet implemented features.\n *\n * \\todo Is this the right place for this? It should be used only in\n * modules under development.\n *\n * \\todo __PRETTY_FUNCTION__ should be replaced by something\n * compiler-independent, like BOOST_CURRENT_FUNCTION\n */\n\n# define LEMON_FIXME(msg) \\\n    (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \\\n\t\t\t  \"FIXME: \" msg))\n"
  },
  {
    "path": "src/lemon/fib_heap.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_FIB_HEAP_H\n#define LEMON_FIB_HEAP_H\n\n///\\file\n///\\ingroup auxdat\n///\\brief Fibonacci Heap implementation.\n\n#include <vector>\n#include <functional>\n#include <lemon/math.h>\n\nnamespace lemon {\n  \n  /// \\ingroup auxdat\n  ///\n  ///\\brief Fibonacci Heap.\n  ///\n  ///This class implements the \\e Fibonacci \\e heap data structure. A \\e heap\n  ///is a data structure for storing items with specified values called \\e\n  ///priorities in such a way that finding the item with minimum priority is\n  ///efficient. \\c Compare specifies the ordering of the priorities. In a heap\n  ///one can change the priority of an item, add or erase an item, etc.\n  ///\n  ///The methods \\ref increase and \\ref erase are not efficient in a Fibonacci\n  ///heap. In case of many calls to these operations, it is better to use a\n  ///\\ref BinHeap \"binary heap\".\n  ///\n  ///\\param _Prio Type of the priority of the items.\n  ///\\param _ItemIntMap A read and writable Item int map, used internally\n  ///to handle the cross references.\n  ///\\param _Compare A class for the ordering of the priorities. The\n  ///default is \\c std::less<_Prio>.\n  ///\n  ///\\sa BinHeap\n  ///\\sa Dijkstra\n  ///\\author Jacint Szabo \n \n#ifdef DOXYGEN\n  template <typename _Prio, \n\t    typename _ItemIntMap, \n\t    typename _Compare>\n#else\n  template <typename _Prio, \n\t    typename _ItemIntMap, \n\t    typename _Compare = std::less<_Prio> >\n#endif\n  class FibHeap {\n  public:\n    typedef _ItemIntMap ItemIntMap;\n    typedef _Prio Prio;\n    typedef typename ItemIntMap::Key Item;\n    typedef std::pair<Item,Prio> Pair;\n    typedef _Compare Compare;\n    \n  private:\n    class store;\n    \n    std::vector<store> container;\n    int minimum;\n    ItemIntMap &iimap;\n    Compare comp;\n    int num_items;\n    \n  public:\n    ///Status of the nodes\n    enum State {\n      ///The node is in the heap\n      IN_HEAP = 0,\n      ///The node has never been in the heap\n      PRE_HEAP = -1,\n      ///The node was in the heap but it got out of it\n      POST_HEAP = -2\n    };\n    \n    /// \\brief The constructor\n    ///\n    /// \\c _iimap should be given to the constructor, since it is\n    ///   used internally to handle the cross references.\n    explicit FibHeap(ItemIntMap &_iimap) \n      : minimum(0), iimap(_iimap), num_items() {} \n \n    /// \\brief The constructor\n    ///\n    /// \\c _iimap should be given to the constructor, since it is used\n    /// internally to handle the cross references. \\c _comp is an\n    /// object for ordering of the priorities. \n    FibHeap(ItemIntMap &_iimap, const Compare &_comp) \n      : minimum(0), iimap(_iimap), comp(_comp), num_items() {}\n    \n    /// \\brief The number of items stored in the heap.\n    ///\n    /// Returns the number of items stored in the heap.\n    int size() const { return num_items; }\n\n    /// \\brief Checks if the heap stores no items.\n    ///\n    ///   Returns \\c true if and only if the heap stores no items.\n    bool empty() const { return num_items==0; }\n\n    /// \\brief Make empty this heap.\n    /// \n    /// Make empty this heap. It does not change the cross reference\n    /// map.  If you want to reuse a heap what is not surely empty you\n    /// should first clear the heap and after that you should set the\n    /// cross reference map for each item to \\c PRE_HEAP.\n    void clear() {\n      container.clear(); minimum = 0; num_items = 0;\n    }\n\n    /// \\brief \\c item gets to the heap with priority \\c value independently \n    /// if \\c item was already there.\n    ///\n    /// This method calls \\ref push(\\c item, \\c value) if \\c item is not\n    /// stored in the heap and it calls \\ref decrease(\\c item, \\c value) or\n    /// \\ref increase(\\c item, \\c value) otherwise.\n    void set (const Item& item, const Prio& value) {\n      int i=iimap[item];\n      if ( i >= 0 && container[i].in ) {\n\tif ( comp(value, container[i].prio) ) decrease(item, value); \n\tif ( comp(container[i].prio, value) ) increase(item, value); \n      } else push(item, value);\n    }\n    \n    /// \\brief Adds \\c item to the heap with priority \\c value. \n    ///    \n    /// Adds \\c item to the heap with priority \\c value. \n    /// \\pre \\c item must not be stored in the heap. \n    void push (const Item& item, const Prio& value) {\n      int i=iimap[item];      \n      if ( i < 0 ) {\n\tint s=container.size();\n\tiimap.set( item, s );\t\n\tstore st;\n\tst.name=item;\n\tcontainer.push_back(st);\n\ti=s;\n      } else {\n\tcontainer[i].parent=container[i].child=-1;\n\tcontainer[i].degree=0;\n\tcontainer[i].in=true;\n\tcontainer[i].marked=false;\n      }\n\n      if ( num_items ) {\n\tcontainer[container[minimum].right_neighbor].left_neighbor=i;\n\tcontainer[i].right_neighbor=container[minimum].right_neighbor;\n\tcontainer[minimum].right_neighbor=i;\n\tcontainer[i].left_neighbor=minimum;\n\tif ( comp( value, container[minimum].prio) ) minimum=i; \n      } else {\n\tcontainer[i].right_neighbor=container[i].left_neighbor=i;\n\tminimum=i;\t\n      }\n      container[i].prio=value;\n      ++num_items;\n    }\n    \n    /// \\brief Returns the item with minimum priority relative to \\c Compare.\n    ///\n    /// This method returns the item with minimum priority relative to \\c\n    /// Compare.  \n    /// \\pre The heap must be nonempty.  \n    Item top() const { return container[minimum].name; }\n\n    /// \\brief Returns the minimum priority relative to \\c Compare.\n    ///\n    /// It returns the minimum priority relative to \\c Compare.\n    /// \\pre The heap must be nonempty.\n    const Prio& prio() const { return container[minimum].prio; }\n        \n    /// \\brief Returns the priority of \\c item.\n    ///\n    /// It returns the priority of \\c item.\n    /// \\pre \\c item must be in the heap.\n    const Prio& operator[](const Item& item) const { \n      return container[iimap[item]].prio; \n    }\n\n    /// \\brief Deletes the item with minimum priority relative to \\c Compare.\n    ///\n    /// This method deletes the item with minimum priority relative to \\c\n    /// Compare from the heap.  \n    /// \\pre The heap must be non-empty.  \n    void pop() {\n      /*The first case is that there are only one root.*/\n      if ( container[minimum].left_neighbor==minimum ) {\n\tcontainer[minimum].in=false;\n\tif ( container[minimum].degree!=0 ) { \n\t  makeroot(container[minimum].child);\n\t  minimum=container[minimum].child;\n\t  balance();\n\t}\n      } else {\n\tint right=container[minimum].right_neighbor;\n\tunlace(minimum);\n\tcontainer[minimum].in=false;\n\tif ( container[minimum].degree > 0 ) {\n\t  int left=container[minimum].left_neighbor;\n\t  int child=container[minimum].child;\n\t  int last_child=container[child].left_neighbor;\n\t  \n\t  makeroot(child);\n\t  \n\t  container[left].right_neighbor=child;\n\t  container[child].left_neighbor=left;\n\t  container[right].left_neighbor=last_child;\n\t  container[last_child].right_neighbor=right;\n\t}\n\tminimum=right;\n\tbalance();\n      } // the case where there are more roots\n      --num_items;   \n    }\n\n    /// \\brief Deletes \\c item from the heap.\n    ///\n    /// This method deletes \\c item from the heap, if \\c item was already\n    /// stored in the heap. It is quite inefficient in Fibonacci heaps.\n    void erase (const Item& item) {\n      int i=iimap[item];\n      \n      if ( i >= 0 && container[i].in ) { \t\n\tif ( container[i].parent!=-1 ) {\n\t  int p=container[i].parent;\n\t  cut(i,p);\t    \n\t  cascade(p);\n\t}\n\tminimum=i;     //As if its prio would be -infinity\n\tpop();\n      }\n    }\n\n    /// \\brief Decreases the priority of \\c item to \\c value.\n    ///\n    /// This method decreases the priority of \\c item to \\c value.\n    /// \\pre \\c item must be stored in the heap with priority at least \\c\n    ///   value relative to \\c Compare.\n    void decrease (Item item, const Prio& value) {\n      int i=iimap[item];\n      container[i].prio=value;\n      int p=container[i].parent;\n      \n      if ( p!=-1 && comp(value, container[p].prio) ) {\n\tcut(i,p);\t    \n\tcascade(p);\n      }      \n      if ( comp(value, container[minimum].prio) ) minimum=i; \n    }\n\n    /// \\brief Increases the priority of \\c item to \\c value.\n    ///\n    /// This method sets the priority of \\c item to \\c value. Though\n    /// there is no precondition on the priority of \\c item, this\n    /// method should be used only if it is indeed necessary to increase\n    /// (relative to \\c Compare) the priority of \\c item, because this\n    /// method is inefficient.\n    void increase (Item item, const Prio& value) {\n      erase(item);\n      push(item, value);\n    }\n\n\n    /// \\brief Returns if \\c item is in, has already been in, or has never \n    /// been in the heap.\n    ///\n    /// This method returns PRE_HEAP if \\c item has never been in the\n    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP\n    /// otherwise. In the latter case it is possible that \\c item will\n    /// get back to the heap again.\n    State state(const Item &item) const {\n      int i=iimap[item];\n      if( i>=0 ) {\n\tif ( container[i].in ) i=0;\n\telse i=-2; \n      }\n      return State(i);\n    }    \n\n    /// \\brief Sets the state of the \\c item in the heap.\n    ///\n    /// Sets the state of the \\c item in the heap. It can be used to\n    /// manually clear the heap when it is important to achive the\n    /// better time complexity.\n    /// \\param i The item.\n    /// \\param st The state. It should not be \\c IN_HEAP. \n    void state(const Item& i, State st) {\n      switch (st) {\n      case POST_HEAP:\n      case PRE_HEAP:\n        if (state(i) == IN_HEAP) {\n          erase(i);\n        }\n        iimap[i] = st;\n        break;\n      case IN_HEAP:\n        break;\n      }\n    }\n    \n  private:\n    \n    void balance() {\n\n      int maxdeg=int( std::floor( 2.08*log(double(container.size()))))+1;\n  \n      std::vector<int> A(maxdeg,-1); \n    \n      /*\n       *Recall that now minimum does not point to the minimum prio element.\n       *We set minimum to this during balance().\n       */\n      int anchor=container[minimum].left_neighbor; \n      int next=minimum; \n      bool end=false; \n    \t\n      do {\n\tint active=next;\n\tif ( anchor==active ) end=true;\n\tint d=container[active].degree;\n\tnext=container[active].right_neighbor;\n\n\twhile (A[d]!=-1) {\t  \n\t  if( comp(container[active].prio, container[A[d]].prio) ) {\n\t    fuse(active,A[d]); \n\t  } else { \n\t    fuse(A[d],active);\n\t    active=A[d];\n\t  } \n\t  A[d]=-1;\n\t  ++d;\n\t}\t\n\tA[d]=active;\n      } while ( !end );\n\n\n      while ( container[minimum].parent >=0 ) \n\tminimum=container[minimum].parent;\n      int s=minimum;\n      int m=minimum;\n      do {  \n\tif ( comp(container[s].prio, container[minimum].prio) ) minimum=s;\n\ts=container[s].right_neighbor;\n      } while ( s != m );\n    }\n\n    void makeroot(int c) {\n      int s=c;\n      do {  \n\tcontainer[s].parent=-1;\n\ts=container[s].right_neighbor;\n      } while ( s != c );\n    }\n\n    void cut(int a, int b) {\n      /*\n       *Replacing a from the children of b.\n       */\n      --container[b].degree;\n    \n      if ( container[b].degree !=0 ) {\n\tint child=container[b].child;\n\tif ( child==a ) \n\t  container[b].child=container[child].right_neighbor;\n\tunlace(a);\n      }\n    \n    \n      /*Lacing a to the roots.*/\n      int right=container[minimum].right_neighbor;\n      container[minimum].right_neighbor=a;\n      container[a].left_neighbor=minimum;\n      container[a].right_neighbor=right;\n      container[right].left_neighbor=a;\n    \n      container[a].parent=-1;\n      container[a].marked=false;\n    }\n\n    void cascade(int a) {\n      if ( container[a].parent!=-1 ) {\n\tint p=container[a].parent;\n\t\n\tif ( container[a].marked==false ) container[a].marked=true;\n\telse {\n\t  cut(a,p);\n\t  cascade(p);\n\t}\n      }\n    }\n\n    void fuse(int a, int b) {\n      unlace(b);\n      \n      /*Lacing b under a.*/\n      container[b].parent=a;\n\n      if (container[a].degree==0) {\n\tcontainer[b].left_neighbor=b;\n\tcontainer[b].right_neighbor=b;\n\tcontainer[a].child=b;\t\n      } else {\n\tint child=container[a].child;\n\tint last_child=container[child].left_neighbor;\n\tcontainer[child].left_neighbor=b;\n\tcontainer[b].right_neighbor=child;\n\tcontainer[last_child].right_neighbor=b;\n\tcontainer[b].left_neighbor=last_child;\n      }\n\n      ++container[a].degree;\n      \n      container[b].marked=false;\n    }\n\n    /*\n     *It is invoked only if a has siblings.\n     */\n    void unlace(int a) {\n      int leftn=container[a].left_neighbor;\n      int rightn=container[a].right_neighbor;\n      container[leftn].right_neighbor=rightn;\n      container[rightn].left_neighbor=leftn;\n    }\n\n\n    class store {\n      friend class FibHeap;\n      \n      Item name;\n      int parent;\n      int left_neighbor;\n      int right_neighbor;\n      int child;\n      int degree;  \n      bool marked;\n      bool in;\n      Prio prio;\n      \n      store() : parent(-1), child(-1), degree(), marked(false), in(true) {} \n    };\n  };    \n\n} //namespace lemon\n\n#endif //LEMON_FIB_HEAP_H\n\n"
  },
  {
    "path": "src/lemon/graph_adaptor.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_GRAPH_ADAPTOR_H\n#define LEMON_GRAPH_ADAPTOR_H\n\n///\\ingroup graph_adaptors\n///\\file\n///\\brief Several graph adaptors.\n///\n///This file contains several useful graph adaptor functions.\n///\n///\\author Marton Makai and Balazs Dezso\n\n#include <lemon/bits/invalid.h>\n#include <lemon/bits/variant.h>\n#include <lemon/maps.h>\n\n#include <lemon/bits/base_extender.h>\n#include <lemon/bits/graph_adaptor_extender.h>\n#include <lemon/bits/graph_extender.h>\n#include <lemon/tolerance.h>\n\n#include <algorithm>\n\nnamespace lemon {\n\n  ///\\brief Base type for the Graph Adaptors\n  ///\n  ///Base type for the Graph Adaptors\n  ///\n  ///This is the base type for most of LEMON graph adaptors. \n  ///This class implements a trivial graph adaptor i.e. it only wraps the \n  ///functions and types of the graph. The purpose of this class is to \n  ///make easier implementing graph adaptors. E.g. if an adaptor is \n  ///considered which differs from the wrapped graph only in some of its \n  ///functions or types, then it can be derived from GraphAdaptor,\n  ///and only the \n  ///differences should be implemented.\n  ///\n  ///author Marton Makai \n  template<typename _Graph>\n  class GraphAdaptorBase {\n  public:\n    typedef _Graph Graph;\n    typedef GraphAdaptorBase Adaptor;\n    typedef Graph ParentGraph;\n\n  protected:\n    Graph* graph;\n    GraphAdaptorBase() : graph(0) { }\n    void setGraph(Graph& _graph) { graph=&_graph; }\n\n  public:\n    GraphAdaptorBase(Graph& _graph) : graph(&_graph) { }\n\n    typedef typename Graph::Node Node;\n    typedef typename Graph::Edge Edge;\n   \n    void first(Node& i) const { graph->first(i); }\n    void first(Edge& i) const { graph->first(i); }\n    void firstIn(Edge& i, const Node& n) const { graph->firstIn(i, n); }\n    void firstOut(Edge& i, const Node& n ) const { graph->firstOut(i, n); }\n\n    void next(Node& i) const { graph->next(i); }\n    void next(Edge& i) const { graph->next(i); }\n    void nextIn(Edge& i) const { graph->nextIn(i); }\n    void nextOut(Edge& i) const { graph->nextOut(i); }\n\n    Node source(const Edge& e) const { return graph->source(e); }\n    Node target(const Edge& e) const { return graph->target(e); }\n\n    typedef NodeNumTagIndicator<Graph> NodeNumTag;\n    int nodeNum() const { return graph->nodeNum(); }\n    \n    typedef EdgeNumTagIndicator<Graph> EdgeNumTag;\n    int edgeNum() const { return graph->edgeNum(); }\n\n    typedef FindEdgeTagIndicator<Graph> FindEdgeTag;\n    Edge findEdge(const Node& u, const Node& v, \n\t\t  const Edge& prev = INVALID) {\n      return graph->findEdge(u, v, prev);\n    }\n  \n    Node addNode() const { \n      return Node(graph->addNode()); \n    }\n\n    Edge addEdge(const Node& u, const Node& v) const { \n      return Edge(graph->addEdge(u, v)); \n    }\n\n    void erase(const Node& i) const { graph->erase(i); }\n    void erase(const Edge& i) const { graph->erase(i); }\n  \n    void clear() const { graph->clear(); }\n    \n    int id(const Node& v) const { return graph->id(v); }\n    int id(const Edge& e) const { return graph->id(e); }\n\n    Node fromNodeId(int ix) const {\n      return graph->fromNodeId(ix);\n    }\n\n    Edge fromEdgeId(int ix) const {\n      return graph->fromEdgeId(ix);\n    }\n\n    int maxNodeId() const {\n      return graph->maxNodeId();\n    }\n\n    int maxEdgeId() const {\n      return graph->maxEdgeId();\n    }\n\n    typedef typename ItemSetTraits<Graph, Node>::ItemNotifier NodeNotifier;\n\n    NodeNotifier& notifier(Node) const {\n      return graph->notifier(Node());\n    } \n\n    typedef typename ItemSetTraits<Graph, Edge>::ItemNotifier EdgeNotifier;\n\n    EdgeNotifier& notifier(Edge) const {\n      return graph->notifier(Edge());\n    } \n    \n    template <typename _Value>\n    class NodeMap : public Graph::template NodeMap<_Value> {\n    public:\n\n      typedef typename Graph::template NodeMap<_Value> Parent;\n\n      explicit NodeMap(const Adaptor& ga) \n\t: Parent(*ga.graph) {}\n\n      NodeMap(const Adaptor& ga, const _Value& value)\n\t: Parent(*ga.graph, value) { }\n\n      NodeMap& operator=(const NodeMap& cmap) {\n        return operator=<NodeMap>(cmap);\n      }\n\n      template <typename CMap>\n      NodeMap& operator=(const CMap& cmap) {\n        Parent::operator=(cmap);\n        return *this;\n      }\n      \n    };\n\n    template <typename _Value>\n    class EdgeMap : public Graph::template EdgeMap<_Value> {\n    public:\n      \n      typedef typename Graph::template EdgeMap<_Value> Parent;\n      \n      explicit EdgeMap(const Adaptor& ga) \n\t: Parent(*ga.graph) {}\n\n      EdgeMap(const Adaptor& ga, const _Value& value)\n\t: Parent(*ga.graph, value) {}\n\n      EdgeMap& operator=(const EdgeMap& cmap) {\n        return operator=<EdgeMap>(cmap);\n      }\n\n      template <typename CMap>\n      EdgeMap& operator=(const CMap& cmap) {\n        Parent::operator=(cmap);\n        return *this;\n      }\n\n    };\n\n  };\n\n  ///\\ingroup graph_adaptors\n  ///\n  ///\\brief Trivial Graph Adaptor\n  /// \n  /// This class is an adaptor which does not change the adapted graph.\n  /// It can be used only to test the graph adaptors.\n  template <typename _Graph>\n  class GraphAdaptor :\n    public GraphAdaptorExtender<GraphAdaptorBase<_Graph> > { \n  public:\n    typedef _Graph Graph;\n    typedef GraphAdaptorExtender<GraphAdaptorBase<_Graph> > Parent;\n  protected:\n    GraphAdaptor() : Parent() { }\n\n  public:\n    explicit GraphAdaptor(Graph& _graph) { setGraph(_graph); }\n  };\n\n  /// \\brief Just gives back a graph adaptor\n  ///\n  /// Just gives back a graph adaptor which \n  /// should be provide original graph\n  template<typename Graph>\n  GraphAdaptor<const Graph>\n  graphAdaptor(const Graph& graph) {\n    return GraphAdaptor<const Graph>(graph);\n  }\n\n\n  template <typename _Graph>\n  class RevGraphAdaptorBase : public GraphAdaptorBase<_Graph> {\n  public:\n    typedef _Graph Graph;\n    typedef GraphAdaptorBase<_Graph> Parent;\n  protected:\n    RevGraphAdaptorBase() : Parent() { }\n  public:\n    typedef typename Parent::Node Node;\n    typedef typename Parent::Edge Edge;\n\n    void firstIn(Edge& i, const Node& n) const { Parent::firstOut(i, n); }\n    void firstOut(Edge& i, const Node& n ) const { Parent::firstIn(i, n); }\n\n    void nextIn(Edge& i) const { Parent::nextOut(i); }\n    void nextOut(Edge& i) const { Parent::nextIn(i); }\n\n    Node source(const Edge& e) const { return Parent::target(e); }\n    Node target(const Edge& e) const { return Parent::source(e); }\n\n    typedef FindEdgeTagIndicator<Graph> FindEdgeTag;\n    Edge findEdge(const Node& u, const Node& v, \n\t\t  const Edge& prev = INVALID) {\n      return Parent::findEdge(v, u, prev);\n    }\n\n  };\n    \n\n  ///\\ingroup graph_adaptors\n  ///\n  ///\\brief A graph adaptor which reverses the orientation of the edges.\n  ///\n  /// If \\c g is defined as\n  ///\\code\n  /// ListGraph g;\n  ///\\endcode\n  /// then\n  ///\\code\n  /// RevGraphAdaptor<ListGraph> ga(g);\n  ///\\endcode\n  /// implements the graph obtained from \\c g by \n  /// reversing the orientation of its edges.\n  ///\n  /// A good example of using RevGraphAdaptor is to decide that the\n  /// directed graph is wheter strongly connected or not. If from one\n  /// node each node is reachable and from each node is reachable this\n  /// node then and just then the graph is strongly connected. Instead of\n  /// this condition we use a little bit different. From one node each node\n  /// ahould be reachable in the graph and in the reversed graph. Now this\n  /// condition can be checked with the Dfs algorithm class and the\n  /// RevGraphAdaptor algorithm class.\n  ///\n  /// And look at the code:\n  ///\n  ///\\code\n  /// bool stronglyConnected(const Graph& graph) {\n  ///   if (NodeIt(graph) == INVALID) return true;\n  ///   Dfs<Graph> dfs(graph);\n  ///   dfs.run(NodeIt(graph));\n  ///   for (NodeIt it(graph); it != INVALID; ++it) {\n  ///     if (!dfs.reached(it)) {\n  ///       return false;\n  ///     }\n  ///   }\n  ///   typedef RevGraphAdaptor<const Graph> RGraph;\n  ///   RGraph rgraph(graph);\n  ///   DfsVisit<RGraph> rdfs(rgraph);\n  ///   rdfs.run(NodeIt(graph));\n  ///   for (NodeIt it(graph); it != INVALID; ++it) {\n  ///     if (!rdfs.reached(it)) {\n  ///       return false;\n  ///     }\n  ///   }\n  ///   return true;\n  /// }\n  ///\\endcode\n  template<typename _Graph>\n  class RevGraphAdaptor : \n    public GraphAdaptorExtender<RevGraphAdaptorBase<_Graph> > {\n  public:\n    typedef _Graph Graph;\n    typedef GraphAdaptorExtender<\n      RevGraphAdaptorBase<_Graph> > Parent;\n  protected:\n    RevGraphAdaptor() { }\n  public:\n    explicit RevGraphAdaptor(_Graph& _graph) { setGraph(_graph); }\n  };\n\n  /// \\brief Just gives back a reverse graph adaptor\n  ///\n  /// Just gives back a reverse graph adaptor\n  template<typename Graph>\n  RevGraphAdaptor<const Graph>\n  revGraphAdaptor(const Graph& graph) {\n    return RevGraphAdaptor<const Graph>(graph);\n  }\n\n  template <typename _Graph, typename NodeFilterMap, \n\t    typename EdgeFilterMap, bool checked = true>\n  class SubGraphAdaptorBase : public GraphAdaptorBase<_Graph> {\n  public:\n    typedef _Graph Graph;\n    typedef SubGraphAdaptorBase Adaptor;\n    typedef GraphAdaptorBase<_Graph> Parent;\n  protected:\n    NodeFilterMap* node_filter_map;\n    EdgeFilterMap* edge_filter_map;\n    SubGraphAdaptorBase() : Parent(), \n\t\t\t    node_filter_map(0), edge_filter_map(0) { }\n\n    void setNodeFilterMap(NodeFilterMap& _node_filter_map) {\n      node_filter_map=&_node_filter_map;\n    }\n    void setEdgeFilterMap(EdgeFilterMap& _edge_filter_map) {\n      edge_filter_map=&_edge_filter_map;\n    }\n\n  public:\n\n    typedef typename Parent::Node Node;\n    typedef typename Parent::Edge Edge;\n\n    void first(Node& i) const { \n      Parent::first(i); \n      while (i!=INVALID && !(*node_filter_map)[i]) Parent::next(i); \n    }\n\n    void first(Edge& i) const { \n      Parent::first(i); \n      while (i!=INVALID && (!(*edge_filter_map)[i] \n\t     || !(*node_filter_map)[Parent::source(i)]\n\t     || !(*node_filter_map)[Parent::target(i)])) Parent::next(i); \n    }\n\n    void firstIn(Edge& i, const Node& n) const { \n      Parent::firstIn(i, n); \n      while (i!=INVALID && (!(*edge_filter_map)[i] \n\t     || !(*node_filter_map)[Parent::source(i)])) Parent::nextIn(i); \n    }\n\n    void firstOut(Edge& i, const Node& n) const { \n      Parent::firstOut(i, n); \n      while (i!=INVALID && (!(*edge_filter_map)[i] \n\t     || !(*node_filter_map)[Parent::target(i)])) Parent::nextOut(i); \n    }\n\n    void next(Node& i) const { \n      Parent::next(i); \n      while (i!=INVALID && !(*node_filter_map)[i]) Parent::next(i); \n    }\n\n    void next(Edge& i) const { \n      Parent::next(i); \n      while (i!=INVALID && (!(*edge_filter_map)[i] \n\t     || !(*node_filter_map)[Parent::source(i)]\n\t     || !(*node_filter_map)[Parent::target(i)])) Parent::next(i); \n    }\n\n    void nextIn(Edge& i) const { \n      Parent::nextIn(i); \n      while (i!=INVALID && (!(*edge_filter_map)[i] \n\t     || !(*node_filter_map)[Parent::source(i)])) Parent::nextIn(i); \n    }\n\n    void nextOut(Edge& i) const { \n      Parent::nextOut(i); \n      while (i!=INVALID && (!(*edge_filter_map)[i] \n\t     || !(*node_filter_map)[Parent::target(i)])) Parent::nextOut(i); \n    }\n\n    ///\\e\n\n    /// This function hides \\c n in the graph, i.e. the iteration \n    /// jumps over it. This is done by simply setting the value of \\c n  \n    /// to be false in the corresponding node-map.\n    void hide(const Node& n) const { node_filter_map->set(n, false); }\n\n    ///\\e\n\n    /// This function hides \\c e in the graph, i.e. the iteration \n    /// jumps over it. This is done by simply setting the value of \\c e  \n    /// to be false in the corresponding edge-map.\n    void hide(const Edge& e) const { edge_filter_map->set(e, false); }\n\n    ///\\e\n\n    /// The value of \\c n is set to be true in the node-map which stores \n    /// hide information. If \\c n was hidden previuosly, then it is shown \n    /// again\n     void unHide(const Node& n) const { node_filter_map->set(n, true); }\n\n    ///\\e\n\n    /// The value of \\c e is set to be true in the edge-map which stores \n    /// hide information. If \\c e was hidden previuosly, then it is shown \n    /// again\n    void unHide(const Edge& e) const { edge_filter_map->set(e, true); }\n\n    /// Returns true if \\c n is hidden.\n    \n    ///\\e\n    ///\n    bool hidden(const Node& n) const { return !(*node_filter_map)[n]; }\n\n    /// Returns true if \\c n is hidden.\n    \n    ///\\e\n    ///\n    bool hidden(const Edge& e) const { return !(*edge_filter_map)[e]; }\n\n    typedef False NodeNumTag;\n    typedef False EdgeNumTag;\n\n    typedef FindEdgeTagIndicator<Graph> FindEdgeTag;\n    Edge findEdge(const Node& source, const Node& target, \n\t\t  const Edge& prev = INVALID) {\n      if (!(*node_filter_map)[source] || !(*node_filter_map)[target]) {\n        return INVALID;\n      }\n      Edge edge = Parent::findEdge(source, target, prev);\n      while (edge != INVALID && !(*edge_filter_map)[edge]) {\n        edge = Parent::findEdge(source, target, edge);\n      }\n      return edge;\n    }\n\n    template <typename _Value>\n    class NodeMap \n      : public SubMapExtender<Adaptor, \n                              typename Parent::template NodeMap<_Value> > \n    {\n    public:\n      typedef Adaptor Graph;\n      //typedef SubMapExtender<Adaptor, typename Parent::\n      //                       template NodeMap<_Value> > Parent;\n    \n      NodeMap(const Graph& g) \n\t: Parent(g) {}\n      NodeMap(const Graph& g, const _Value& v) \n\t: Parent(g, v) {}\n    \n      NodeMap& operator=(const NodeMap& cmap) {\n\treturn operator=<NodeMap>(cmap);\n      }\n    \n      template <typename CMap>\n      NodeMap& operator=(const CMap& cmap) {\n        Parent::operator=(cmap);\n\treturn *this;\n      }\n    };\n\n    template <typename _Value>\n    class EdgeMap \n      : public SubMapExtender<Adaptor, \n                              typename Parent::template EdgeMap<_Value> > \n    {\n    public:\n      typedef Adaptor Graph;\n      //typedef SubMapExtender<Adaptor, typename Parent::\n      //                       template EdgeMap<_Value> > Parent;\n    \n      EdgeMap(const Graph& g) \n\t: Parent(g) {}\n      EdgeMap(const Graph& g, const _Value& v) \n\t: Parent(g, v) {}\n    \n      EdgeMap& operator=(const EdgeMap& cmap) {\n\treturn operator=<EdgeMap>(cmap);\n      }\n    \n      template <typename CMap>\n      EdgeMap& operator=(const CMap& cmap) {\n        Parent::operator=(cmap);\n\treturn *this;\n      }\n    };\n\n  };\n\n  template <typename _Graph, typename NodeFilterMap, typename EdgeFilterMap>\n  class SubGraphAdaptorBase<_Graph, NodeFilterMap, EdgeFilterMap, false> \n    : public GraphAdaptorBase<_Graph> {\n  public:\n    typedef _Graph Graph;\n    typedef SubGraphAdaptorBase Adaptor;\n    typedef GraphAdaptorBase<_Graph> Parent;\n  protected:\n    NodeFilterMap* node_filter_map;\n    EdgeFilterMap* edge_filter_map;\n    SubGraphAdaptorBase() : Parent(), \n\t\t\t    node_filter_map(0), edge_filter_map(0) { }\n\n    void setNodeFilterMap(NodeFilterMap& _node_filter_map) {\n      node_filter_map=&_node_filter_map;\n    }\n    void setEdgeFilterMap(EdgeFilterMap& _edge_filter_map) {\n      edge_filter_map=&_edge_filter_map;\n    }\n\n  public:\n\n    typedef typename Parent::Node Node;\n    typedef typename Parent::Edge Edge;\n\n    void first(Node& i) const { \n      Parent::first(i); \n      while (i!=INVALID && !(*node_filter_map)[i]) Parent::next(i); \n    }\n\n    void first(Edge& i) const { \n      Parent::first(i); \n      while (i!=INVALID && !(*edge_filter_map)[i]) Parent::next(i); \n    }\n\n    void firstIn(Edge& i, const Node& n) const { \n      Parent::firstIn(i, n); \n      while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextIn(i); \n    }\n\n    void firstOut(Edge& i, const Node& n) const { \n      Parent::firstOut(i, n); \n      while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextOut(i); \n    }\n\n    void next(Node& i) const { \n      Parent::next(i); \n      while (i!=INVALID && !(*node_filter_map)[i]) Parent::next(i); \n    }\n    void next(Edge& i) const { \n      Parent::next(i); \n      while (i!=INVALID && !(*edge_filter_map)[i]) Parent::next(i); \n    }\n    void nextIn(Edge& i) const { \n      Parent::nextIn(i); \n      while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextIn(i); \n    }\n\n    void nextOut(Edge& i) const { \n      Parent::nextOut(i); \n      while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextOut(i); \n    }\n\n    ///\\e\n\n    /// This function hides \\c n in the graph, i.e. the iteration \n    /// jumps over it. This is done by simply setting the value of \\c n  \n    /// to be false in the corresponding node-map.\n    void hide(const Node& n) const { node_filter_map->set(n, false); }\n\n    ///\\e\n\n    /// This function hides \\c e in the graph, i.e. the iteration \n    /// jumps over it. This is done by simply setting the value of \\c e  \n    /// to be false in the corresponding edge-map.\n    void hide(const Edge& e) const { edge_filter_map->set(e, false); }\n\n    ///\\e\n\n    /// The value of \\c n is set to be true in the node-map which stores \n    /// hide information. If \\c n was hidden previuosly, then it is shown \n    /// again\n     void unHide(const Node& n) const { node_filter_map->set(n, true); }\n\n    ///\\e\n\n    /// The value of \\c e is set to be true in the edge-map which stores \n    /// hide information. If \\c e was hidden previuosly, then it is shown \n    /// again\n    void unHide(const Edge& e) const { edge_filter_map->set(e, true); }\n\n    /// Returns true if \\c n is hidden.\n    \n    ///\\e\n    ///\n    bool hidden(const Node& n) const { return !(*node_filter_map)[n]; }\n\n    /// Returns true if \\c n is hidden.\n    \n    ///\\e\n    ///\n    bool hidden(const Edge& e) const { return !(*edge_filter_map)[e]; }\n\n    typedef False NodeNumTag;\n    typedef False EdgeNumTag;\n\n    typedef FindEdgeTagIndicator<Graph> FindEdgeTag;\n    Edge findEdge(const Node& source, const Node& target, \n\t\t  const Edge& prev = INVALID) {\n      if (!(*node_filter_map)[source] || !(*node_filter_map)[target]) {\n        return INVALID;\n      }\n      Edge edge = Parent::findEdge(source, target, prev);\n      while (edge != INVALID && !(*edge_filter_map)[edge]) {\n        edge = Parent::findEdge(source, target, edge);\n      }\n      return edge;\n    }\n\n    template <typename _Value>\n    class NodeMap \n      : public SubMapExtender<Adaptor, \n                              typename Parent::template NodeMap<_Value> > \n    {\n    public:\n      typedef Adaptor Graph;\n      //typedef SubMapExtender<Adaptor, typename Parent::\n      //                       template NodeMap<_Value> > Parent;\n    \n      NodeMap(const Graph& g) \n\t: Parent(g) {}\n      NodeMap(const Graph& g, const _Value& v) \n\t: Parent(g, v) {}\n    \n      NodeMap& operator=(const NodeMap& cmap) {\n\treturn operator=<NodeMap>(cmap);\n      }\n    \n      template <typename CMap>\n      NodeMap& operator=(const CMap& cmap) {\n        Parent::operator=(cmap);\n\treturn *this;\n      }\n    };\n\n    template <typename _Value>\n    class EdgeMap \n      : public SubMapExtender<Adaptor, \n                              typename Parent::template EdgeMap<_Value> > \n    {\n    public:\n      typedef Adaptor Graph;\n      //typedef SubMapExtender<Adaptor, typename Parent::\n      //                       template EdgeMap<_Value> > Parent;\n    \n      EdgeMap(const Graph& g) \n\t: Parent(g) {}\n      EdgeMap(const Graph& g, const _Value& v) \n\t: Parent(g, v) {}\n    \n      EdgeMap& operator=(const EdgeMap& cmap) {\n\treturn operator=<EdgeMap>(cmap);\n      }\n    \n      template <typename CMap>\n      EdgeMap& operator=(const CMap& cmap) {\n        Parent::operator=(cmap);\n\treturn *this;\n      }\n    };\n\n  };\n\n  /// \\ingroup graph_adaptors\n  ///\n  /// \\brief A graph adaptor for hiding nodes and edges from a graph.\n  /// \n  /// SubGraphAdaptor shows the graph with filtered node-set and \n  /// edge-set. If the \\c checked parameter is true then it filters the edgeset\n  /// to do not get invalid edges without source or target.\n  /// Let \\f$ G=(V, A) \\f$ be a directed graph\n  /// and suppose that the graph instance \\c g of type ListGraph\n  /// implements \\f$ G \\f$.\n  /// Let moreover \\f$ b_V \\f$ and \\f$ b_A \\f$ be bool-valued functions resp.\n  /// on the node-set and edge-set.\n  /// SubGraphAdaptor<...>::NodeIt iterates \n  /// on the node-set \\f$ \\{v\\in V : b_V(v)=true\\} \\f$ and \n  /// SubGraphAdaptor<...>::EdgeIt iterates \n  /// on the edge-set \\f$ \\{e\\in A : b_A(e)=true\\} \\f$. Similarly, \n  /// SubGraphAdaptor<...>::OutEdgeIt and\n  /// SubGraphAdaptor<...>::InEdgeIt iterates \n  /// only on edges leaving and entering a specific node which have true value.\n  /// \n  /// If the \\c checked template parameter is false then we have to note that \n  /// the node-iterator cares only the filter on the node-set, and the \n  /// edge-iterator cares only the filter on the edge-set.\n  /// This way the edge-map\n  /// should filter all edges which's source or target is filtered by the \n  /// node-filter.\n  ///\\code\n  /// typedef ListGraph Graph;\n  /// Graph g;\n  /// typedef Graph::Node Node;\n  /// typedef Graph::Edge Edge;\n  /// Node u=g.addNode(); //node of id 0\n  /// Node v=g.addNode(); //node of id 1\n  /// Node e=g.addEdge(u, v); //edge of id 0\n  /// Node f=g.addEdge(v, u); //edge of id 1\n  /// Graph::NodeMap<bool> nm(g, true);\n  /// nm.set(u, false);\n  /// Graph::EdgeMap<bool> em(g, true);\n  /// em.set(e, false);\n  /// typedef SubGraphAdaptor<Graph, Graph::NodeMap<bool>, Graph::EdgeMap<bool> > SubGA;\n  /// SubGA ga(g, nm, em);\n  /// for (SubGA::NodeIt n(ga); n!=INVALID; ++n) std::cout << g.id(n) << std::endl;\n  /// std::cout << \":-)\" << std::endl;\n  /// for (SubGA::EdgeIt e(ga); e!=INVALID; ++e) std::cout << g.id(e) << std::endl;\n  ///\\endcode\n  /// The output of the above code is the following.\n  ///\\code\n  /// 1\n  /// :-)\n  /// 1\n  ///\\endcode\n  /// Note that \\c n is of type \\c SubGA::NodeIt, but it can be converted to\n  /// \\c Graph::Node that is why \\c g.id(n) can be applied.\n  /// \n  /// For other examples see also the documentation of NodeSubGraphAdaptor and \n  /// EdgeSubGraphAdaptor.\n  /// \n  /// \\author Marton Makai\n\n  template<typename _Graph, typename NodeFilterMap, \n\t   typename EdgeFilterMap, bool checked = true>\n  class SubGraphAdaptor : \n    public GraphAdaptorExtender<\n    SubGraphAdaptorBase<_Graph, NodeFilterMap, EdgeFilterMap, checked> > {\n  public:\n    typedef _Graph Graph;\n    typedef GraphAdaptorExtender< SubGraphAdaptorBase<_Graph, NodeFilterMap, \n                                                      EdgeFilterMap, checked> >\n    Parent;\n\n  protected:\n    SubGraphAdaptor() { }\n  public:\n\n    SubGraphAdaptor(_Graph& _graph, NodeFilterMap& _node_filter_map, \n\t\t    EdgeFilterMap& _edge_filter_map) { \n      setGraph(_graph);\n      setNodeFilterMap(_node_filter_map);\n      setEdgeFilterMap(_edge_filter_map);\n    }\n\n  };\n\n  /// \\brief Just gives back a sub graph adaptor\n  ///\n  /// Just gives back a sub graph adaptor\n  template<typename Graph, typename NodeFilterMap, typename EdgeFilterMap>\n  SubGraphAdaptor<const Graph, NodeFilterMap, EdgeFilterMap>\n  subGraphAdaptor(const Graph& graph, \n                   NodeFilterMap& nfm, EdgeFilterMap& efm) {\n    return SubGraphAdaptor<const Graph, NodeFilterMap, EdgeFilterMap>\n      (graph, nfm, efm);\n  }\n\n  template<typename Graph, typename NodeFilterMap, typename EdgeFilterMap>\n  SubGraphAdaptor<const Graph, const NodeFilterMap, EdgeFilterMap>\n  subGraphAdaptor(const Graph& graph, \n                   NodeFilterMap& nfm, EdgeFilterMap& efm) {\n    return SubGraphAdaptor<const Graph, const NodeFilterMap, EdgeFilterMap>\n      (graph, nfm, efm);\n  }\n\n  template<typename Graph, typename NodeFilterMap, typename EdgeFilterMap>\n  SubGraphAdaptor<const Graph, NodeFilterMap, const EdgeFilterMap>\n  subGraphAdaptor(const Graph& graph, \n                   NodeFilterMap& nfm, EdgeFilterMap& efm) {\n    return SubGraphAdaptor<const Graph, NodeFilterMap, const EdgeFilterMap>\n      (graph, nfm, efm);\n  }\n\n  template<typename Graph, typename NodeFilterMap, typename EdgeFilterMap>\n  SubGraphAdaptor<const Graph, const NodeFilterMap, const EdgeFilterMap>\n  subGraphAdaptor(const Graph& graph, \n                   NodeFilterMap& nfm, EdgeFilterMap& efm) {\n    return SubGraphAdaptor<const Graph, const NodeFilterMap, \n      const EdgeFilterMap>(graph, nfm, efm);\n  }\n\n\n\n  ///\\ingroup graph_adaptors\n  ///\n  ///\\brief An adaptor for hiding nodes from a graph.\n  ///\n  ///An adaptor for hiding nodes from a graph.\n  ///This adaptor specializes SubGraphAdaptor in the way that only\n  ///the node-set \n  ///can be filtered. In usual case the checked parameter is true, we get the\n  ///induced subgraph. But if the checked parameter is false then we can\n  ///filter only isolated nodes.\n  ///\\author Marton Makai\n  template<typename Graph, typename NodeFilterMap, bool checked = true>\n  class NodeSubGraphAdaptor : \n    public SubGraphAdaptor<Graph, NodeFilterMap, \n\t\t\t   ConstMap<typename Graph::Edge,bool>, checked> {\n  public:\n\n    typedef SubGraphAdaptor<Graph, NodeFilterMap, \n\t\t\t    ConstMap<typename Graph::Edge,bool>, checked > \n    Parent;\n\n  protected:\n    ConstMap<typename Graph::Edge, bool> const_true_map;\n\n    NodeSubGraphAdaptor() : const_true_map(true) {\n      Parent::setEdgeFilterMap(const_true_map);\n    }\n\n  public:\n\n    NodeSubGraphAdaptor(Graph& _graph, NodeFilterMap& _node_filter_map) : \n      Parent(), const_true_map(true) { \n      Parent::setGraph(_graph);\n      Parent::setNodeFilterMap(_node_filter_map);\n      Parent::setEdgeFilterMap(const_true_map);\n    }\n\n  };\n\n\n  /// \\brief Just gives back a node sub graph adaptor\n  ///\n  /// Just gives back a node sub graph adaptor\n  template<typename Graph, typename NodeFilterMap>\n  NodeSubGraphAdaptor<const Graph, NodeFilterMap>\n  nodeSubGraphAdaptor(const Graph& graph, NodeFilterMap& nfm) {\n    return NodeSubGraphAdaptor<const Graph, NodeFilterMap>(graph, nfm);\n  }\n\n  template<typename Graph, typename NodeFilterMap>\n  NodeSubGraphAdaptor<const Graph, const NodeFilterMap>\n  nodeSubGraphAdaptor(const Graph& graph, const NodeFilterMap& nfm) {\n    return NodeSubGraphAdaptor<const Graph, const NodeFilterMap>(graph, nfm);\n  }\n\n  ///\\ingroup graph_adaptors\n  ///\n  ///\\brief An adaptor for hiding edges from a graph.\n  ///\n  ///An adaptor for hiding edges from a graph.\n  ///This adaptor specializes SubGraphAdaptor in the way that\n  ///only the edge-set \n  ///can be filtered. The usefulness of this adaptor is demonstrated in the \n  ///problem of searching a maximum number of edge-disjoint shortest paths \n  ///between \n  ///two nodes \\c s and \\c t. Shortest here means being shortest w.r.t. \n  ///non-negative edge-lengths. Note that \n  ///the comprehension of the presented solution \n  ///need's some elementary knowledge from combinatorial optimization. \n  ///\n  ///If a single shortest path is to be \n  ///searched between \\c s and \\c t, then this can be done easily by \n  ///applying the Dijkstra algorithm. What happens, if a maximum number of \n  ///edge-disjoint shortest paths is to be computed. It can be proved that an \n  ///edge can be in a shortest path if and only\n  ///if it is tight with respect to \n  ///the potential function computed by Dijkstra.\n  ///Moreover, any path containing \n  ///only such edges is a shortest one.\n  ///Thus we have to compute a maximum number \n  ///of edge-disjoint paths between \\c s and \\c t in\n  ///the graph which has edge-set \n  ///all the tight edges. The computation will be demonstrated\n  ///on the following \n  ///graph, which is read from the dimacs file \\c sub_graph_adaptor_demo.dim. \n  ///The full source code is available in \\ref sub_graph_adaptor_demo.cc. \n  ///If you are interested in more demo programs, you can use \n  ///\\ref dim_to_dot.cc to generate .dot files from dimacs files. \n  ///The .dot file of the following figure was generated by  \n  ///the demo program \\ref dim_to_dot.cc.\n  ///\n  ///\\dot\n  ///digraph lemon_dot_example {\n  ///node [ shape=ellipse, fontname=Helvetica, fontsize=10 ];\n  ///n0 [ label=\"0 (s)\" ];\n  ///n1 [ label=\"1\" ];\n  ///n2 [ label=\"2\" ];\n  ///n3 [ label=\"3\" ];\n  ///n4 [ label=\"4\" ];\n  ///n5 [ label=\"5\" ];\n  ///n6 [ label=\"6 (t)\" ];\n  ///edge [ shape=ellipse, fontname=Helvetica, fontsize=10 ];\n  ///n5 ->  n6 [ label=\"9, length:4\" ];\n  ///n4 ->  n6 [ label=\"8, length:2\" ];\n  ///n3 ->  n5 [ label=\"7, length:1\" ];\n  ///n2 ->  n5 [ label=\"6, length:3\" ];\n  ///n2 ->  n6 [ label=\"5, length:5\" ];\n  ///n2 ->  n4 [ label=\"4, length:2\" ];\n  ///n1 ->  n4 [ label=\"3, length:3\" ];\n  ///n0 ->  n3 [ label=\"2, length:1\" ];\n  ///n0 ->  n2 [ label=\"1, length:2\" ];\n  ///n0 ->  n1 [ label=\"0, length:3\" ];\n  ///}\n  ///\\enddot\n  ///\n  ///\\code\n  ///Graph g;\n  ///Node s, t;\n  ///LengthMap length(g);\n  ///\n  ///readDimacs(std::cin, g, length, s, t);\n  ///\n  ///cout << \"edges with lengths (of form id, source--length->target): \" << endl;\n  ///for(EdgeIt e(g); e!=INVALID; ++e) \n  ///  cout << g.id(e) << \", \" << g.id(g.source(e)) << \"--\" \n  ///       << length[e] << \"->\" << g.id(g.target(e)) << endl;\n  ///\n  ///cout << \"s: \" << g.id(s) << \" t: \" << g.id(t) << endl;\n  ///\\endcode\n  ///Next, the potential function is computed with Dijkstra.\n  ///\\code\n  ///typedef Dijkstra<Graph, LengthMap> Dijkstra;\n  ///Dijkstra dijkstra(g, length);\n  ///dijkstra.run(s);\n  ///\\endcode\n  ///Next, we consrtruct a map which filters the edge-set to the tight edges.\n  ///\\code\n  ///typedef TightEdgeFilterMap<Graph, const Dijkstra::DistMap, LengthMap> \n  ///  TightEdgeFilter;\n  ///TightEdgeFilter tight_edge_filter(g, dijkstra.distMap(), length);\n  ///\n  ///typedef EdgeSubGraphAdaptor<Graph, TightEdgeFilter> SubGA;\n  ///SubGA ga(g, tight_edge_filter);\n  ///\\endcode\n  ///Then, the maximum nimber of edge-disjoint \\c s-\\c t paths are computed \n  ///with a max flow algorithm Preflow.\n  ///\\code\n  ///ConstMap<Edge, int> const_1_map(1);\n  ///Graph::EdgeMap<int> flow(g, 0);\n  ///\n  ///Preflow<SubGA, ConstMap<Edge, int>, Graph::EdgeMap<int> > \n  ///  preflow(ga, const_1_map, s, t);\n  ///preflow.run();\n  ///\\endcode\n  ///Last, the output is:\n  ///\\code  \n  ///cout << \"maximum number of edge-disjoint shortest path: \" \n  ///     << preflow.flowValue() << endl;\n  ///cout << \"edges of the maximum number of edge-disjoint shortest s-t paths: \" \n  ///     << endl;\n  ///for(EdgeIt e(g); e!=INVALID; ++e) \n  ///  if (preflow.flow(e))\n  ///    cout << \" \" << g.id(g.source(e)) << \"--\"\n  ///         << length[e] << \"->\" << g.id(g.target(e)) << endl;\n  ///\\endcode\n  ///The program has the following (expected :-)) output:\n  ///\\code\n  ///edges with lengths (of form id, source--length->target):\n  /// 9, 5--4->6\n  /// 8, 4--2->6\n  /// 7, 3--1->5\n  /// 6, 2--3->5\n  /// 5, 2--5->6\n  /// 4, 2--2->4\n  /// 3, 1--3->4\n  /// 2, 0--1->3\n  /// 1, 0--2->2\n  /// 0, 0--3->1\n  ///s: 0 t: 6\n  ///maximum number of edge-disjoint shortest path: 2\n  ///edges of the maximum number of edge-disjoint shortest s-t paths:\n  /// 9, 5--4->6\n  /// 8, 4--2->6\n  /// 7, 3--1->5\n  /// 4, 2--2->4\n  /// 2, 0--1->3\n  /// 1, 0--2->2\n  ///\\endcode\n  ///\n  ///\\author Marton Makai\n  template<typename Graph, typename EdgeFilterMap>\n  class EdgeSubGraphAdaptor : \n    public SubGraphAdaptor<Graph, ConstMap<typename Graph::Node,bool>, \n\t\t\t   EdgeFilterMap, false> {\n  public:\n    typedef SubGraphAdaptor<Graph, ConstMap<typename Graph::Node,bool>, \n\t\t\t    EdgeFilterMap, false> Parent;\n  protected:\n    ConstMap<typename Graph::Node, bool> const_true_map;\n\n    EdgeSubGraphAdaptor() : const_true_map(true) {\n      Parent::setNodeFilterMap(const_true_map);\n    }\n\n  public:\n\n    EdgeSubGraphAdaptor(Graph& _graph, EdgeFilterMap& _edge_filter_map) : \n      Parent(), const_true_map(true) { \n      Parent::setGraph(_graph);\n      Parent::setNodeFilterMap(const_true_map);\n      Parent::setEdgeFilterMap(_edge_filter_map);\n    }\n\n  };\n\n  /// \\brief Just gives back an edge sub graph adaptor\n  ///\n  /// Just gives back an edge sub graph adaptor\n  template<typename Graph, typename EdgeFilterMap>\n  EdgeSubGraphAdaptor<const Graph, EdgeFilterMap>\n  edgeSubGraphAdaptor(const Graph& graph, EdgeFilterMap& efm) {\n    return EdgeSubGraphAdaptor<const Graph, EdgeFilterMap>(graph, efm);\n  }\n\n  template<typename Graph, typename EdgeFilterMap>\n  EdgeSubGraphAdaptor<const Graph, const EdgeFilterMap>\n  edgeSubGraphAdaptor(const Graph& graph, const EdgeFilterMap& efm) {\n    return EdgeSubGraphAdaptor<const Graph, const EdgeFilterMap>(graph, efm);\n  }\n\n  template <typename _Graph>\n  class UndirGraphAdaptorBase : \n    public UndirGraphExtender<GraphAdaptorBase<_Graph> > {\n  public:\n    typedef _Graph Graph;\n    typedef UndirGraphAdaptorBase Adaptor;\n    typedef UndirGraphExtender<GraphAdaptorBase<_Graph> > Parent;\n\n  protected:\n\n    UndirGraphAdaptorBase() : Parent() {}\n\n  public:\n\n    typedef typename Parent::UEdge UEdge;\n    typedef typename Parent::Edge Edge;\n\n  private:\n    \n    template <typename _Value>\n    class EdgeMapBase {\n    private:\n      \n      typedef typename _Graph::template EdgeMap<_Value> MapImpl;\n      \n    public:\n\n      typedef typename MapTraits<MapImpl>::ReferenceMapTag ReferenceMapTag;\n\n      typedef _Value Value;\n      typedef Edge Key;\n      \n      EdgeMapBase(const Adaptor& adaptor) :\n\tforward_map(*adaptor.graph), backward_map(*adaptor.graph) {}\n\n      EdgeMapBase(const Adaptor& adaptor, const Value& v) \n        : forward_map(*adaptor.graph, v), backward_map(*adaptor.graph, v) {}\n      \n      void set(const Edge& e, const Value& a) { \n\tif (Parent::direction(e)) {\n\t  forward_map.set(e, a); \n        } else { \n\t  backward_map.set(e, a);\n        } \n      }\n\n      typename MapTraits<MapImpl>::ConstReturnValue operator[](Edge e) const { \n\tif (Parent::direction(e)) {\n\t  return forward_map[e]; \n\t} else { \n\t  return backward_map[e]; \n        }\n      }\n\n      typename MapTraits<MapImpl>::ReturnValue operator[](Edge e) { \n\tif (Parent::direction(e)) {\n\t  return forward_map[e]; \n\t} else { \n\t  return backward_map[e]; \n        }\n      }\n\n    protected:\n\n      MapImpl forward_map, backward_map; \n\n    };\n\n  public:\n\n    template <typename _Value>\n    class EdgeMap \n      : public SubMapExtender<Adaptor, EdgeMapBase<_Value> > \n    {\n    public:\n      typedef Adaptor Graph;\n      typedef SubMapExtender<Adaptor, EdgeMapBase<_Value> > Parent;\n    \n      EdgeMap(const Graph& g) \n\t: Parent(g) {}\n      EdgeMap(const Graph& g, const _Value& v) \n\t: Parent(g, v) {}\n    \n      EdgeMap& operator=(const EdgeMap& cmap) {\n\treturn operator=<EdgeMap>(cmap);\n      }\n    \n      template <typename CMap>\n      EdgeMap& operator=(const CMap& cmap) {\n        Parent::operator=(cmap);\n\treturn *this;\n      }\n    };\n        \n    template <typename _Value>\n    class UEdgeMap : public Graph::template EdgeMap<_Value> {\n    public:\n      \n      typedef typename Graph::template EdgeMap<_Value> Parent;\n      \n      explicit UEdgeMap(const Adaptor& ga) \n\t: Parent(*ga.graph) {}\n\n      UEdgeMap(const Adaptor& ga, const _Value& value)\n\t: Parent(*ga.graph, value) {}\n\n      UEdgeMap& operator=(const UEdgeMap& cmap) {\n        return operator=<UEdgeMap>(cmap);\n      }\n\n      template <typename CMap>\n      UEdgeMap& operator=(const CMap& cmap) {\n        Parent::operator=(cmap);\n        return *this;\n      }\n\n    };\n      \n  };\n\n  template <typename _Graph, typename Enable = void>\n  class AlterableUndirGraphAdaptor \n    : public UGraphAdaptorExtender<UndirGraphAdaptorBase<_Graph> > {\n  public:\n    typedef UGraphAdaptorExtender<UndirGraphAdaptorBase<_Graph> > Parent;\n    \n  protected:\n\n    AlterableUndirGraphAdaptor() : Parent() {}\n\n  public:\n\n    typedef typename Parent::EdgeNotifier UEdgeNotifier;\n    typedef InvalidType EdgeNotifier;\n\n  };\n\n  template <typename _Graph>\n  class AlterableUndirGraphAdaptor<\n    _Graph, \n    typename enable_if<typename _Graph::EdgeNotifier::Notifier>::type > \n    : public UGraphAdaptorExtender<UndirGraphAdaptorBase<_Graph> > {\n  public:\n\n    typedef UGraphAdaptorExtender<UndirGraphAdaptorBase<_Graph> > Parent;\n    typedef _Graph Graph;\n    typedef typename _Graph::Edge GraphEdge;\n    \n  protected:\n\n    AlterableUndirGraphAdaptor() \n      : Parent(), edge_notifier(*this), edge_notifier_proxy(*this) {}\n\n    void setGraph(_Graph& g) {\n      Parent::setGraph(g);\n      edge_notifier_proxy.setNotifier(g.notifier(GraphEdge()));\n    }\n\n  public:\n\n    ~AlterableUndirGraphAdaptor() {\n      edge_notifier.clear();\n    }\n\n    typedef typename Parent::UEdge UEdge;\n    typedef typename Parent::Edge Edge;\n\n    typedef typename Parent::EdgeNotifier UEdgeNotifier;\n\n    using Parent::notifier;\n\n    typedef AlterationNotifier<AlterableUndirGraphAdaptor, \n                               Edge> EdgeNotifier;\n    EdgeNotifier& notifier(Edge) const { return edge_notifier; }\n\n  protected:\n\n    class NotifierProxy : public Graph::EdgeNotifier::ObserverBase {\n    public:\n\n      typedef typename Graph::EdgeNotifier::ObserverBase Parent;\n      typedef AlterableUndirGraphAdaptor AdaptorBase;\n      \n      NotifierProxy(const AdaptorBase& _adaptor)\n        : Parent(), adaptor(&_adaptor) {\n      }\n\n      virtual ~NotifierProxy() {\n        if (Parent::attached()) {\n          Parent::detach();\n        }\n      }\n\n      void setNotifier(typename Graph::EdgeNotifier& nf) {\n        Parent::attach(nf);\n      }\n\n      \n    protected:\n\n      virtual void add(const GraphEdge& ge) {\n        std::vector<Edge> edges;\n        edges.push_back(AdaptorBase::Parent::direct(ge, true));\n        edges.push_back(AdaptorBase::Parent::direct(ge, false));\n        adaptor->notifier(Edge()).add(edges);\n      }\n      virtual void add(const std::vector<GraphEdge>& ge) {\n        std::vector<Edge> edges;\n        for (int i = 0; i < int(ge.size()); ++i) { \n          edges.push_back(AdaptorBase::Parent::direct(ge[i], true));\n          edges.push_back(AdaptorBase::Parent::direct(ge[i], false));\n        }\n        adaptor->notifier(Edge()).add(edges);\n      }\n      virtual void erase(const GraphEdge& ge) {\n        std::vector<Edge> edges;\n        edges.push_back(AdaptorBase::Parent::direct(ge, true));\n        edges.push_back(AdaptorBase::Parent::direct(ge, false));\n        adaptor->notifier(Edge()).erase(edges);\n      }\n      virtual void erase(const std::vector<GraphEdge>& ge) {\n        std::vector<Edge> edges;\n        for (int i = 0; i < int(ge.size()); ++i) { \n          edges.push_back(AdaptorBase::Parent::direct(ge[i], true));\n          edges.push_back(AdaptorBase::Parent::direct(ge[i], false));\n        }\n        adaptor->notifier(Edge()).erase(edges);\n      }\n      virtual void build() {\n        adaptor->notifier(Edge()).build();\n      }\n      virtual void clear() {\n        adaptor->notifier(Edge()).clear();\n      }\n\n      const AdaptorBase* adaptor;\n    };\n\n\n    mutable EdgeNotifier edge_notifier;\n    NotifierProxy edge_notifier_proxy;\n\n  };\n\n\n  ///\\ingroup graph_adaptors\n  ///\n  /// \\brief An undirected graph is made from a directed graph by an adaptor\n  ///\n  /// This adaptor makes an undirected graph from a directed\n  /// graph. All edge of the underlying will be showed in the adaptor\n  /// as an undirected edge. Let's see an informal example about using\n  /// this adaptor:\n  ///\n  /// There is a network of the streets of a town. Of course there are\n  /// some one-way street in the town hence the network is a directed\n  /// one. There is a crazy driver who go oppositely in the one-way\n  /// street without moral sense. Of course he can pass this streets\n  /// slower than the regular way, in fact his speed is half of the\n  /// normal speed. How long should he drive to get from a source\n  /// point to the target? Let see the example code which calculate it:\n  ///\n  ///\\code\n  /// typedef UndirGraphAdaptor<Graph> UGraph;\n  /// UGraph ugraph(graph);\n  ///\n  /// typedef SimpleMap<LengthMap> FLengthMap;\n  /// FLengthMap flength(length);\n  ///\n  /// typedef ScaleMap<LengthMap> RLengthMap;\n  /// RLengthMap rlength(length, 2.0);\n  ///\n  /// typedef UGraph::CombinedEdgeMap<FLengthMap, RLengthMap > ULengthMap;\n  /// ULengthMap ulength(flength, rlength);\n  /// \n  /// Dijkstra<UGraph, ULengthMap> dijkstra(ugraph, ulength);\n  /// std::cout << \"Driving time : \" << dijkstra.run(src, trg) << std::endl;\n  ///\\endcode\n  ///\n  /// The combined edge map makes the length map for the undirected\n  /// graph. It is created from a forward and reverse map. The forward\n  /// map is created from the original length map with a SimpleMap\n  /// adaptor which just makes a read-write map from the reference map\n  /// i.e. it forgets that it can be return reference to values. The\n  /// reverse map is just the scaled original map with the ScaleMap\n  /// adaptor. The combination solves that passing the reverse way\n  /// takes double time than the original. To get the driving time we\n  /// run the dijkstra algorithm on the undirected graph.\n  ///\n  /// \\author Marton Makai and Balazs Dezso\n  template<typename _Graph>\n  class UndirGraphAdaptor : public AlterableUndirGraphAdaptor<_Graph> {\n  public:\n    typedef _Graph Graph;\n    typedef AlterableUndirGraphAdaptor<_Graph> Parent;\n  protected:\n    UndirGraphAdaptor() { }\n  public:\n\n    /// \\brief Constructor\n    ///\n    /// Constructor\n    UndirGraphAdaptor(_Graph& _graph) { \n      setGraph(_graph);\n    }\n\n    /// \\brief EdgeMap combined from two original EdgeMap\n    ///\n    /// This class adapts two original graph EdgeMap to\n    /// get an edge map on the adaptor.\n    template <typename _ForwardMap, typename _BackwardMap>\n    class CombinedEdgeMap {\n    public:\n      \n      typedef _ForwardMap ForwardMap;\n      typedef _BackwardMap BackwardMap;\n\n      typedef typename MapTraits<ForwardMap>::ReferenceMapTag ReferenceMapTag;\n\n      typedef typename ForwardMap::Value Value;\n      typedef typename Parent::Edge Key;\n\n      /// \\brief Constructor      \n      ///\n      /// Constructor      \n      CombinedEdgeMap() : forward_map(0), backward_map(0) {}\n\n      /// \\brief Constructor      \n      ///\n      /// Constructor      \n      CombinedEdgeMap(ForwardMap& _forward_map, BackwardMap& _backward_map) \n        : forward_map(&_forward_map), backward_map(&_backward_map) {}\n      \n\n      /// \\brief Sets the value associated with a key.\n      ///\n      /// Sets the value associated with a key.\n      void set(const Key& e, const Value& a) { \n\tif (Parent::direction(e)) {\n\t  forward_map->set(e, a); \n        } else { \n\t  backward_map->set(e, a);\n        } \n      }\n\n      /// \\brief Returns the value associated with a key.\n      ///\n      /// Returns the value associated with a key.\n      typename MapTraits<ForwardMap>::ConstReturnValue \n      operator[](const Key& e) const { \n\tif (Parent::direction(e)) {\n\t  return (*forward_map)[e]; \n\t} else { \n\t  return (*backward_map)[e]; \n        }\n      }\n\n      /// \\brief Returns the value associated with a key.\n      ///\n      /// Returns the value associated with a key.\n      typename MapTraits<ForwardMap>::ReturnValue \n      operator[](const Key& e) { \n\tif (Parent::direction(e)) {\n\t  return (*forward_map)[e]; \n\t} else { \n\t  return (*backward_map)[e]; \n        }\n      }\n\n      /// \\brief Sets the forward map\n      ///\n      /// Sets the forward map\n      void setForwardMap(ForwardMap& _forward_map) {\n        forward_map = &_forward_map;\n      }\n\n      /// \\brief Sets the backward map\n      ///\n      /// Sets the backward map\n      void setBackwardMap(BackwardMap& _backward_map) {\n        backward_map = &_backward_map;\n      }\n\n    protected:\n\n      ForwardMap* forward_map;\n      BackwardMap* backward_map; \n\n    };\n\n  };\n\n  /// \\brief Just gives back an undir graph adaptor\n  ///\n  /// Just gives back an undir graph adaptor\n  template<typename Graph>\n  UndirGraphAdaptor<const Graph>\n  undirGraphAdaptor(const Graph& graph) {\n    return UndirGraphAdaptor<const Graph>(graph);\n  }\n\n  template<typename Graph, typename Number,  \n           typename CapacityMap, typename FlowMap, \n           typename Tol = Tolerance<Number> >\n  class ResForwardFilter {\n    const CapacityMap* capacity;\n    const FlowMap* flow;\n    Tol tolerance;\n  public:\n    typedef typename Graph::Edge Key;\n    typedef bool Value;\n\n    ResForwardFilter(const CapacityMap& _capacity, const FlowMap& _flow,\n                     const Tol& _tolerance = Tol()) \n      : capacity(&_capacity), flow(&_flow), tolerance(_tolerance) { }\n\n    ResForwardFilter(const Tol& _tolerance) \n      : capacity(0), flow(0), tolerance(_tolerance)  { }\n\n    void setCapacity(const CapacityMap& _capacity) { capacity = &_capacity; }\n    void setFlow(const FlowMap& _flow) { flow = &_flow; }\n\n    bool operator[](const typename Graph::Edge& e) const {\n      return tolerance.positive((*capacity)[e] - (*flow)[e]);\n    }\n  };\n\n  template<typename Graph, typename Number,\n\t   typename CapacityMap, typename FlowMap,\n           typename Tol = Tolerance<Number> >\n  class ResBackwardFilter {\n    const CapacityMap* capacity;\n    const FlowMap* flow;\n    Tol tolerance;\n  public:\n    typedef typename Graph::Edge Key;\n    typedef bool Value;\n\n    ResBackwardFilter(const CapacityMap& _capacity, const FlowMap& _flow,\n                      const Tol& _tolerance = Tol())\n      : capacity(&_capacity), flow(&_flow), tolerance(_tolerance) { }\n    ResBackwardFilter(const Tol& _tolerance = Tol())\n      : capacity(0), flow(0), tolerance(_tolerance) { }\n    void setCapacity(const CapacityMap& _capacity) { capacity = &_capacity; }\n    void setFlow(const FlowMap& _flow) { flow = &_flow; }\n    bool operator[](const typename Graph::Edge& e) const {\n      return tolerance.positive((*flow)[e]);\n    }\n  };\n\n  \n  ///\\ingroup graph_adaptors\n  ///\n  ///\\brief An adaptor for composing the residual\n  ///graph for directed flow and circulation problems.\n  ///\n  ///An adaptor for composing the residual graph for directed flow and\n  ///circulation problems.  Let \\f$ G=(V, A) \\f$ be a directed graph\n  ///and let \\f$ F \\f$ be a number type. Let moreover \\f$ f,c:A\\to F \\f$,\n  ///be functions on the edge-set.\n  ///\n  ///In the appications of ResGraphAdaptor, \\f$ f \\f$ usually stands\n  ///for a flow and \\f$ c \\f$ for a capacity function.  Suppose that a\n  ///graph instange \\c g of type \\c ListGraph implements \\f$ G \\f$.\n  ///\n  ///\\code \n  ///  ListGraph g;\n  ///\\endcode \n  ///\n  ///Then ResGraphAdaptor implements the graph structure with node-set\n  /// \\f$ V \\f$ and edge-set \\f$ A_{forward}\\cup A_{backward} \\f$,\n  ///where \\f$ A_{forward}=\\{uv : uv\\in A, f(uv)<c(uv)\\} \\f$ and \n  /// \\f$ A_{backward}=\\{vu : uv\\in A, f(uv)>0\\} \\f$, i.e. the so called\n  ///residual graph.  When we take the union \n  /// \\f$ A_{forward}\\cup A_{backward} \\f$, multilicities are counted, i.e. \n  ///if an edge is in both \\f$ A_{forward} \\f$ and \\f$ A_{backward} \\f$, \n  ///then in the adaptor it appears twice. The following code shows how \n  ///such an instance can be constructed.\n  ///\n  ///\\code \n  ///  typedef ListGraph Graph; \n  ///  Graph::EdgeMap<int> f(g);\n  ///  Graph::EdgeMap<int> c(g); \n  ///  ResGraphAdaptor<Graph, int, Graph::EdgeMap<int>, Graph::EdgeMap<int> > ga(g); \n  ///\\endcode\n  ///\\author Marton Makai\n  ///\n  template<typename Graph, typename Number, \n\t   typename CapacityMap, typename FlowMap,\n           typename Tol = Tolerance<Number> >\n  class ResGraphAdaptor : \n    public EdgeSubGraphAdaptor< \n    UndirGraphAdaptor<const Graph>, \n    typename UndirGraphAdaptor<const Graph>::template CombinedEdgeMap<\n    ResForwardFilter<const Graph, Number, CapacityMap, FlowMap>,  \n    ResBackwardFilter<const Graph, Number, CapacityMap, FlowMap> > > {\n  public:\n\n    typedef UndirGraphAdaptor<const Graph> UGraph;\n\n    typedef ResForwardFilter<const Graph, Number, CapacityMap, FlowMap> \n    ForwardFilter;\n\n    typedef ResBackwardFilter<const Graph, Number, CapacityMap, FlowMap> \n    BackwardFilter;\n\n    typedef typename UGraph::\n    template CombinedEdgeMap<ForwardFilter, BackwardFilter>\n    EdgeFilter;\n\n    typedef EdgeSubGraphAdaptor<UGraph, EdgeFilter> Parent;\n\n  protected:\n\n    const CapacityMap* capacity;\n    FlowMap* flow;\n\n    UGraph ugraph;\n    ForwardFilter forward_filter;\n    BackwardFilter backward_filter;\n    EdgeFilter edge_filter;\n\n    void setCapacityMap(const CapacityMap& _capacity) {\n      capacity=&_capacity;\n      forward_filter.setCapacity(_capacity);\n      backward_filter.setCapacity(_capacity);\n    }\n\n    void setFlowMap(FlowMap& _flow) {\n      flow=&_flow;\n      forward_filter.setFlow(_flow);\n      backward_filter.setFlow(_flow);\n    }\n\n  public:\n\n    /// \\brief Constructor of the residual graph.\n    ///\n    /// Constructor of the residual graph. The parameters are the graph type,\n    /// the flow map, the capacity map and a tolerance object.\n    ResGraphAdaptor(const Graph& _graph, const CapacityMap& _capacity, \n                    FlowMap& _flow, const Tol& _tolerance = Tol()) \n      : Parent(), capacity(&_capacity), flow(&_flow), ugraph(_graph),\n        forward_filter(_capacity, _flow, _tolerance), \n        backward_filter(_capacity, _flow, _tolerance),\n        edge_filter(forward_filter, backward_filter)\n    {\n      Parent::setGraph(ugraph);\n      Parent::setEdgeFilterMap(edge_filter);\n    }\n\n    typedef typename Parent::Edge Edge;\n\n    /// \\brief Gives back the residual capacity of the edge.\n    ///\n    /// Gives back the residual capacity of the edge.\n    Number rescap(const Edge& edge) const {\n      if (UGraph::direction(edge)) {\n        return (*capacity)[edge]-(*flow)[edge]; \n      } else {\n        return (*flow)[edge];\n      }\n    } \n\n    /// \\brief Augment on the given edge in the residual graph.\n    ///\n    /// Augment on the given edge in the residual graph. It increase\n    /// or decrease the flow on the original edge depend on the direction\n    /// of the residual edge.\n    void augment(const Edge& e, Number a) const {\n      if (UGraph::direction(e)) {\n        flow->set(e, (*flow)[e] + a);\n      } else {  \n        flow->set(e, (*flow)[e] - a);\n      }\n    }\n\n    /// \\brief Returns the direction of the edge.\n    ///\n    /// Returns true when the edge is same oriented as the original edge.\n    static bool forward(const Edge& e) {\n      return UGraph::direction(e);\n    }\n\n    /// \\brief Returns the direction of the edge.\n    ///\n    /// Returns true when the edge is opposite oriented as the original edge.\n    static bool backward(const Edge& e) {\n      return !UGraph::direction(e);\n    }\n\n    /// \\brief Gives back the forward oriented residual edge.\n    ///\n    /// Gives back the forward oriented residual edge.\n    static Edge forward(const typename Graph::Edge& e) {\n      return UGraph::direct(e, true);\n    }\n\n    /// \\brief Gives back the backward oriented residual edge.\n    ///\n    /// Gives back the backward oriented residual edge.\n    static Edge backward(const typename Graph::Edge& e) {\n      return UGraph::direct(e, false);\n    }\n\n    /// \\brief Residual capacity map.\n    ///\n    /// In generic residual graphs the residual capacity can be obtained \n    /// as a map. \n    class ResCap {\n    protected:\n      const ResGraphAdaptor* res_graph;\n    public:\n      typedef Number Value;\n      typedef Edge Key;\n      ResCap(const ResGraphAdaptor& _res_graph) \n        : res_graph(&_res_graph) {}\n      \n      Number operator[](const Edge& e) const {\n        return res_graph->rescap(e);\n      }\n      \n    };\n\n  };\n\n\n\n  template <typename _Graph, typename FirstOutEdgesMap>\n  class ErasingFirstGraphAdaptorBase : public GraphAdaptorBase<_Graph> {\n  public:\n    typedef _Graph Graph;\n    typedef GraphAdaptorBase<_Graph> Parent;\n  protected:\n    FirstOutEdgesMap* first_out_edges;\n    ErasingFirstGraphAdaptorBase() : Parent(), \n\t\t\t\t     first_out_edges(0) { }\n\n    void setFirstOutEdgesMap(FirstOutEdgesMap& _first_out_edges) {\n      first_out_edges=&_first_out_edges;\n    }\n\n  public:\n\n    typedef typename Parent::Node Node;\n    typedef typename Parent::Edge Edge;\n\n    void firstOut(Edge& i, const Node& n) const { \n      i=(*first_out_edges)[n];\n    }\n\n    void erase(const Edge& e) const {\n      Node n=source(e);\n      Edge f=e;\n      Parent::nextOut(f);\n      first_out_edges->set(n, f);\n    }    \n  };\n\n\n  ///\\ingroup graph_adaptors\n  ///\n  ///\\brief For blocking flows.\n  ///\n  ///This graph adaptor is used for on-the-fly \n  ///Dinits blocking flow computations.\n  ///For each node, an out-edge is stored which is used when the \n  ///\\code\n  ///OutEdgeIt& first(OutEdgeIt&, const Node&)\n  ///\\endcode\n  ///is called. \n  ///\n  ///\\author Marton Makai\n  ///\n  template <typename _Graph, typename FirstOutEdgesMap>\n  class ErasingFirstGraphAdaptor : \n    public GraphAdaptorExtender<\n    ErasingFirstGraphAdaptorBase<_Graph, FirstOutEdgesMap> > {\n  public:\n    typedef _Graph Graph;\n    typedef GraphAdaptorExtender<\n      ErasingFirstGraphAdaptorBase<_Graph, FirstOutEdgesMap> > Parent;\n    ErasingFirstGraphAdaptor(Graph& _graph, \n\t\t\t     FirstOutEdgesMap& _first_out_edges) { \n      setGraph(_graph);\n      setFirstOutEdgesMap(_first_out_edges);\n    } \n\n  };\n\n  /// \\brief Base class for split graph adaptor\n  ///\n  /// Base class of split graph adaptor. In most case you do not need to\n  /// use it directly but the documented member functions of this class can \n  /// be used with the SplitGraphAdaptor class.\n  /// \\sa SplitGraphAdaptor\n  template <typename _Graph>\n  class SplitGraphAdaptorBase \n    : public GraphAdaptorBase<const _Graph> {\n  public:\n\n    typedef _Graph Graph;\n\n    typedef GraphAdaptorBase<const _Graph> Parent;\n\n    typedef typename Graph::Node GraphNode;\n    typedef typename Graph::Edge GraphEdge;\n\n    class Node;\n    class Edge;\n\n    template <typename T> class NodeMap;\n    template <typename T> class EdgeMap;\n    \n\n    class Node : public GraphNode {\n      friend class SplitGraphAdaptorBase;\n      template <typename T> friend class NodeMap;\n    private:\n\n      bool in_node;\n      Node(GraphNode _node, bool _in_node)\n\t: GraphNode(_node), in_node(_in_node) {}\n      \n    public:\n\n      Node() {}\n      Node(Invalid) : GraphNode(INVALID), in_node(true) {}\n\n      bool operator==(const Node& node) const {\n\treturn GraphNode::operator==(node) && in_node == node.in_node;\n      }\n      \n      bool operator!=(const Node& node) const {\n\treturn !(*this == node);\n      }\n      \n      bool operator<(const Node& node) const {\n\treturn GraphNode::operator<(node) || \n\t  (GraphNode::operator==(node) && in_node < node.in_node);\n      }\n    };\n\n    class Edge {\n      friend class SplitGraphAdaptorBase;\n      template <typename T> friend class EdgeMap;\n    private:\n      typedef BiVariant<GraphEdge, GraphNode> EdgeImpl;\n\n      explicit Edge(const GraphEdge& edge) : item(edge) {}\n      explicit Edge(const GraphNode& node) : item(node) {}\n      \n      EdgeImpl item;\n\n    public:\n      Edge() {}\n      Edge(Invalid) : item(GraphEdge(INVALID)) {}\n\n      bool operator==(const Edge& edge) const {\n        if (item.firstState()) {\n          if (edge.item.firstState()) {\n            return item.first() == edge.item.first();\n          }\n        } else {\n          if (edge.item.secondState()) {\n            return item.second() == edge.item.second();\n          }\n        }\n        return false;\n      }\n      \n      bool operator!=(const Edge& edge) const {\n\treturn !(*this == edge);\n      }\n      \n      bool operator<(const Edge& edge) const {\n        if (item.firstState()) {\n          if (edge.item.firstState()) {\n            return item.first() < edge.item.first();\n          }\n          return false;\n        } else {\n          if (edge.item.secondState()) {\n            return item.second() < edge.item.second();\n          }\n          return true;\n        }\n      }\n\n      operator GraphEdge() const { return item.first(); }\n      operator GraphNode() const { return item.second(); }\n\n    };\n\n    void first(Node& n) const {\n      Parent::first(n);\n      n.in_node = true;\n    }\n\n    void next(Node& n) const {\n      if (n.in_node) {\n\tn.in_node = false;\n      } else {\n\tn.in_node = true;\n\tParent::next(n);\n      }\n    }\n\n    void first(Edge& e) const {\n      e.item.setSecond();\n      Parent::first(e.item.second());\n      if (e.item.second() == INVALID) {\n        e.item.setFirst();\n\tParent::first(e.item.first());\n      }\n    }\n\n    void next(Edge& e) const {\n      if (e.item.secondState()) {\n\tParent::next(e.item.second());\n        if (e.item.second() == INVALID) {\n          e.item.setFirst();\n          Parent::first(e.item.first());\n        }\n      } else {\n\tParent::next(e.item.first());\n      }      \n    }\n\n    void firstOut(Edge& e, const Node& n) const {\n      if (n.in_node) {\n        e.item.setSecond(n);\n      } else {\n        e.item.setFirst();\n\tParent::firstOut(e.item.first(), n);\n      }\n    }\n\n    void nextOut(Edge& e) const {\n      if (!e.item.firstState()) {\n\te.item.setFirst(INVALID);\n      } else {\n\tParent::nextOut(e.item.first());\n      }      \n    }\n\n    void firstIn(Edge& e, const Node& n) const {\n      if (!n.in_node) {\n        e.item.setSecond(n);        \n      } else {\n        e.item.setFirst();\n\tParent::firstIn(e.item.first(), n);\n      }\n    }\n\n    void nextIn(Edge& e) const {\n      if (!e.item.firstState()) {\n\te.item.setFirst(INVALID);\n      } else {\n\tParent::nextIn(e.item.first());\n      }\n    }\n\n    Node source(const Edge& e) const {\n      if (e.item.firstState()) {\n\treturn Node(Parent::source(e.item.first()), false);\n      } else {\n\treturn Node(e.item.second(), true);\n      }\n    }\n\n    Node target(const Edge& e) const {\n      if (e.item.firstState()) {\n\treturn Node(Parent::target(e.item.first()), true);\n      } else {\n\treturn Node(e.item.second(), false);\n      }\n    }\n\n    int id(const Node& n) const {\n      return (Parent::id(n) << 1) | (n.in_node ? 0 : 1);\n    }\n    Node nodeFromId(int ix) const {\n      return Node(Parent::nodeFromId(ix >> 1), (ix & 1) == 0);\n    }\n    int maxNodeId() const {\n      return 2 * Parent::maxNodeId() + 1;\n    }\n\n    int id(const Edge& e) const {\n      if (e.item.firstState()) {\n        return Parent::id(e.item.first()) << 1;\n      } else {\n        return (Parent::id(e.item.second()) << 1) | 1;\n      }\n    }\n    Edge edgeFromId(int ix) const {\n      if ((ix & 1) == 0) {\n        return Edge(Parent::edgeFromId(ix >> 1));\n      } else {\n        return Edge(Parent::nodeFromId(ix >> 1));\n      }\n    }\n    int maxEdgeId() const {\n      return std::max(Parent::maxNodeId() << 1, \n                      (Parent::maxEdgeId() << 1) | 1);\n    }\n\n    /// \\brief Returns true when the node is in-node.\n    ///\n    /// Returns true when the node is in-node.\n    static bool inNode(const Node& n) {\n      return n.in_node;\n    }\n\n    /// \\brief Returns true when the node is out-node.\n    ///\n    /// Returns true when the node is out-node.\n    static bool outNode(const Node& n) {\n      return !n.in_node;\n    }\n\n    /// \\brief Returns true when the edge is edge in the original graph.\n    ///\n    /// Returns true when the edge is edge in the original graph.\n    static bool origEdge(const Edge& e) {\n      return e.item.firstState();\n    }\n\n    /// \\brief Returns true when the edge binds an in-node and an out-node.\n    ///\n    /// Returns true when the edge binds an in-node and an out-node.\n    static bool bindEdge(const Edge& e) {\n      return e.item.secondState();\n    }\n\n    /// \\brief Gives back the in-node created from the \\c node.\n    ///\n    /// Gives back the in-node created from the \\c node.\n    static Node inNode(const GraphNode& n) {\n      return Node(n, true);\n    }\n\n    /// \\brief Gives back the out-node created from the \\c node.\n    ///\n    /// Gives back the out-node created from the \\c node.\n    static Node outNode(const GraphNode& n) {\n      return Node(n, false);\n    }\n\n    /// \\brief Gives back the edge binds the two part of the node.\n    /// \n    /// Gives back the edge binds the two part of the node.\n    static Edge edge(const GraphNode& n) {\n      return Edge(n);\n    }\n\n    /// \\brief Gives back the edge of the original edge.\n    /// \n    /// Gives back the edge of the original edge.\n    static Edge edge(const GraphEdge& e) {\n      return Edge(e);\n    }\n\n    typedef True NodeNumTag;\n\n    int nodeNum() const {\n      return  2 * countNodes(*Parent::graph);\n    }\n\n    typedef True EdgeNumTag;\n    \n    int edgeNum() const {\n      return countEdges(*Parent::graph) + countNodes(*Parent::graph);\n    }\n\n    typedef True FindEdgeTag;\n\n    Edge findEdge(const Node& u, const Node& v, \n\t\t  const Edge& prev = INVALID) const {\n      if (inNode(u)) {\n        if (outNode(v)) {\n          if (static_cast<const GraphNode&>(u) == \n              static_cast<const GraphNode&>(v) && prev == INVALID) {\n            return Edge(u);\n          }\n        }\n      } else {\n        if (inNode(v)) {\n          return Edge(findEdge(*Parent::graph, u, v, prev));\n        }\n      }\n      return INVALID;\n    }\n\n    \n    template <typename T>\n    class NodeMap : public MapBase<Node, T> {\n      typedef typename Parent::template NodeMap<T> NodeImpl;\n    public:\n      NodeMap(const SplitGraphAdaptorBase& _graph) \n\t: inNodeMap(_graph), outNodeMap(_graph) {}\n      NodeMap(const SplitGraphAdaptorBase& _graph, const T& t) \n\t: inNodeMap(_graph, t), outNodeMap(_graph, t) {}\n      NodeMap& operator=(const NodeMap& cmap) {\n        return operator=<NodeMap>(cmap);\n      }\n      template <typename CMap>\n      NodeMap& operator=(const CMap& cmap) {\n        Parent::operator=(cmap);\n        return *this;\n      }\n\n      void set(const Node& key, const T& val) {\n\tif (SplitGraphAdaptorBase::inNode(key)) { inNodeMap.set(key, val); }\n\telse {outNodeMap.set(key, val); }\n      }\n      \n      typename MapTraits<NodeImpl>::ReturnValue \n      operator[](const Node& key) {\n\tif (SplitGraphAdaptorBase::inNode(key)) { return inNodeMap[key]; }\n\telse { return outNodeMap[key]; }\n      }\n\n      typename MapTraits<NodeImpl>::ConstReturnValue\n      operator[](const Node& key) const {\n\tif (SplitGraphAdaptorBase::inNode(key)) { return inNodeMap[key]; }\n\telse { return outNodeMap[key]; }\n      }\n\n    private:\n      NodeImpl inNodeMap, outNodeMap;\n    };\n\n    template <typename T>\n    class EdgeMap : public MapBase<Edge, T> {\n      typedef typename Parent::template EdgeMap<T> EdgeMapImpl;\n      typedef typename Parent::template NodeMap<T> NodeMapImpl;\n    public:\n\n      EdgeMap(const SplitGraphAdaptorBase& _graph) \n\t: edge_map(_graph), node_map(_graph) {}\n      EdgeMap(const SplitGraphAdaptorBase& _graph, const T& t) \n\t: edge_map(_graph, t), node_map(_graph, t) {}\n      EdgeMap& operator=(const EdgeMap& cmap) {\n        return operator=<EdgeMap>(cmap);\n      }\n      template <typename CMap>\n      EdgeMap& operator=(const CMap& cmap) {\n        Parent::operator=(cmap);\n        return *this;\n      }\n      \n      void set(const Edge& key, const T& val) {\n\tif (SplitGraphAdaptorBase::origEdge(key)) { \n          edge_map.set(key.item.first(), val); \n        } else {\n          node_map.set(key.item.second(), val); \n        }\n      }\n      \n      typename MapTraits<EdgeMapImpl>::ReturnValue\n      operator[](const Edge& key) {\n\tif (SplitGraphAdaptorBase::origEdge(key)) { \n          return edge_map[key.item.first()];\n        } else {\n          return node_map[key.item.second()];\n        }\n      }\n\n      typename MapTraits<EdgeMapImpl>::ConstReturnValue\n      operator[](const Edge& key) const {\n\tif (SplitGraphAdaptorBase::origEdge(key)) { \n          return edge_map[key.item.first()];\n        } else {\n          return node_map[key.item.second()];\n        }\n      }\n\n    private:\n      typename Parent::template EdgeMap<T> edge_map;\n      typename Parent::template NodeMap<T> node_map;\n    };\n\n\n  };\n\n  template <typename _Graph, typename NodeEnable = void, \n            typename EdgeEnable = void>\n  class AlterableSplitGraphAdaptor \n    : public GraphAdaptorExtender<SplitGraphAdaptorBase<_Graph> > {\n  public:\n\n    typedef GraphAdaptorExtender<SplitGraphAdaptorBase<_Graph> > Parent;\n    typedef _Graph Graph;\n\n    typedef typename Graph::Node GraphNode;\n    typedef typename Graph::Node GraphEdge;\n\n  protected:\n\n    AlterableSplitGraphAdaptor() : Parent() {}\n\n  public:\n    \n    typedef InvalidType NodeNotifier;\n    typedef InvalidType EdgeNotifier;\n\n  };\n\n  template <typename _Graph, typename EdgeEnable>\n  class AlterableSplitGraphAdaptor<\n    _Graph,\n    typename enable_if<typename _Graph::NodeNotifier::Notifier>::type,\n    EdgeEnable> \n      : public GraphAdaptorExtender<SplitGraphAdaptorBase<_Graph> > {\n  public:\n\n    typedef GraphAdaptorExtender<SplitGraphAdaptorBase<_Graph> > Parent;\n    typedef _Graph Graph;\n\n    typedef typename Graph::Node GraphNode;\n    typedef typename Graph::Edge GraphEdge;\n\n    typedef typename Parent::Node Node;\n    typedef typename Parent::Edge Edge;\n \n  protected:\n\n    AlterableSplitGraphAdaptor() \n      : Parent(), node_notifier(*this), node_notifier_proxy(*this) {}\n\n    void setGraph(_Graph& graph) {\n      Parent::setGraph(graph);\n      node_notifier_proxy.setNotifier(graph.notifier(GraphNode()));\n    }\n\n  public:\n\n    ~AlterableSplitGraphAdaptor() {\n      node_notifier.clear();\n    }\n\n    typedef AlterationNotifier<AlterableSplitGraphAdaptor, Node> NodeNotifier;\n    typedef InvalidType EdgeNotifier;\n\n    NodeNotifier& notifier(Node) const { return node_notifier; }\n\n  protected:\n\n    class NodeNotifierProxy : public Graph::NodeNotifier::ObserverBase {\n    public:\n\n      typedef typename Graph::NodeNotifier::ObserverBase Parent;\n      typedef AlterableSplitGraphAdaptor AdaptorBase;\n      \n      NodeNotifierProxy(const AdaptorBase& _adaptor)\n        : Parent(), adaptor(&_adaptor) {\n      }\n\n      virtual ~NodeNotifierProxy() {\n        if (Parent::attached()) {\n          Parent::detach();\n        }\n      }\n\n      void setNotifier(typename Graph::NodeNotifier& graph_notifier) {\n        Parent::attach(graph_notifier);\n      }\n\n      \n    protected:\n\n      virtual void add(const GraphNode& gn) {\n        std::vector<Node> nodes;\n        nodes.push_back(AdaptorBase::Parent::inNode(gn));\n        nodes.push_back(AdaptorBase::Parent::outNode(gn));\n        adaptor->notifier(Node()).add(nodes);\n      }\n\n      virtual void add(const std::vector<GraphNode>& gn) {\n        std::vector<Node> nodes;\n        for (int i = 0; i < int(gn.size()); ++i) {\n          nodes.push_back(AdaptorBase::Parent::inNode(gn[i]));\n          nodes.push_back(AdaptorBase::Parent::outNode(gn[i]));\n        }\n        adaptor->notifier(Node()).add(nodes);\n      }\n\n      virtual void erase(const GraphNode& gn) {\n        std::vector<Node> nodes;\n        nodes.push_back(AdaptorBase::Parent::inNode(gn));\n        nodes.push_back(AdaptorBase::Parent::outNode(gn));\n        adaptor->notifier(Node()).erase(nodes);\n      }\n\n      virtual void erase(const std::vector<GraphNode>& gn) {\n        std::vector<Node> nodes;\n        for (int i = 0; i < int(gn.size()); ++i) {\n          nodes.push_back(AdaptorBase::Parent::inNode(gn[i]));\n          nodes.push_back(AdaptorBase::Parent::outNode(gn[i]));\n        }\n        adaptor->notifier(Node()).erase(nodes);\n      }\n      virtual void build() {\n        adaptor->notifier(Node()).build();\n      }\n      virtual void clear() {\n        adaptor->notifier(Node()).clear();\n      }\n\n      const AdaptorBase* adaptor;\n    };\n\n\n    mutable NodeNotifier node_notifier;\n\n    NodeNotifierProxy node_notifier_proxy;\n\n  };\n\n  template <typename _Graph>\n  class AlterableSplitGraphAdaptor<\n    _Graph,\n    typename enable_if<typename _Graph::NodeNotifier::Notifier>::type,\n    typename enable_if<typename _Graph::EdgeNotifier::Notifier>::type> \n      : public GraphAdaptorExtender<SplitGraphAdaptorBase<_Graph> > {\n  public:\n\n    typedef GraphAdaptorExtender<SplitGraphAdaptorBase<_Graph> > Parent;\n    typedef _Graph Graph;\n\n    typedef typename Graph::Node GraphNode;\n    typedef typename Graph::Edge GraphEdge;\n\n    typedef typename Parent::Node Node;\n    typedef typename Parent::Edge Edge;\n \n  protected:\n    \n    AlterableSplitGraphAdaptor() \n      : Parent(), node_notifier(*this), edge_notifier(*this), \n        node_notifier_proxy(*this), edge_notifier_proxy(*this) {}\n    \n    void setGraph(_Graph& g) {\n      Parent::setGraph(g);\n      node_notifier_proxy.setNotifier(g.notifier(GraphNode()));\n      edge_notifier_proxy.setNotifier(g.notifier(GraphEdge()));\n    }\n\n  public:\n\n    ~AlterableSplitGraphAdaptor() {\n      node_notifier.clear();\n      edge_notifier.clear();\n    }\n\n    typedef AlterationNotifier<AlterableSplitGraphAdaptor, Node> NodeNotifier;\n    typedef AlterationNotifier<AlterableSplitGraphAdaptor, Edge> EdgeNotifier;\n\n    NodeNotifier& notifier(Node) const { return node_notifier; }\n    EdgeNotifier& notifier(Edge) const { return edge_notifier; }\n\n  protected:\n\n    class NodeNotifierProxy : public Graph::NodeNotifier::ObserverBase {\n    public:\n      \n      typedef typename Graph::NodeNotifier::ObserverBase Parent;\n      typedef AlterableSplitGraphAdaptor AdaptorBase;\n      \n      NodeNotifierProxy(const AdaptorBase& _adaptor)\n        : Parent(), adaptor(&_adaptor) {\n      }\n\n      virtual ~NodeNotifierProxy() {\n        if (Parent::attached()) {\n          Parent::detach();\n        }\n      }\n\n      void setNotifier(typename Graph::NodeNotifier& graph_notifier) {\n        Parent::attach(graph_notifier);\n      }\n\n      \n    protected:\n\n      virtual void add(const GraphNode& gn) {\n        std::vector<Node> nodes;\n        nodes.push_back(AdaptorBase::Parent::inNode(gn));\n        nodes.push_back(AdaptorBase::Parent::outNode(gn));\n        adaptor->notifier(Node()).add(nodes);\n        adaptor->notifier(Edge()).add(AdaptorBase::Parent::edge(gn));\n      }\n      virtual void add(const std::vector<GraphNode>& gn) {\n        std::vector<Node> nodes;\n        std::vector<Edge> edges;\n        for (int i = 0; i < int(gn.size()); ++i) {\n          edges.push_back(AdaptorBase::Parent::edge(gn[i]));\n          nodes.push_back(AdaptorBase::Parent::inNode(gn[i]));\n          nodes.push_back(AdaptorBase::Parent::outNode(gn[i]));\n        }\n        adaptor->notifier(Node()).add(nodes);\n        adaptor->notifier(Edge()).add(edges);\n      }\n      virtual void erase(const GraphNode& gn) {\n        adaptor->notifier(Edge()).erase(AdaptorBase::Parent::edge(gn));\n        std::vector<Node> nodes;\n        nodes.push_back(AdaptorBase::Parent::inNode(gn));\n        nodes.push_back(AdaptorBase::Parent::outNode(gn));\n        adaptor->notifier(Node()).erase(nodes);\n      }\n      virtual void erase(const std::vector<GraphNode>& gn) {\n        std::vector<Node> nodes;\n        std::vector<Edge> edges;\n        for (int i = 0; i < int(gn.size()); ++i) {\n          edges.push_back(AdaptorBase::Parent::edge(gn[i]));\n          nodes.push_back(AdaptorBase::Parent::inNode(gn[i]));\n          nodes.push_back(AdaptorBase::Parent::outNode(gn[i]));\n        }\n        adaptor->notifier(Edge()).erase(edges);\n        adaptor->notifier(Node()).erase(nodes);\n      }\n      virtual void build() {\n        std::vector<Edge> edges;\n        const typename Parent::Notifier* nf = Parent::notifier();\n        GraphNode it;\n        for (nf->first(it); it != INVALID; nf->next(it)) {\n          edges.push_back(AdaptorBase::Parent::edge(it));\n        }\n        adaptor->notifier(Node()).build();\n        adaptor->notifier(Edge()).add(edges);        \n      }\n      virtual void clear() {\n        std::vector<Edge> edges;\n        const typename Parent::Notifier* nf = Parent::notifier();\n        GraphNode it;\n        for (nf->first(it); it != INVALID; nf->next(it)) {\n          edges.push_back(AdaptorBase::Parent::edge(it));\n        }\n        adaptor->notifier(Edge()).erase(edges);        \n        adaptor->notifier(Node()).clear();\n      }\n\n      const AdaptorBase* adaptor;\n    };\n\n    class EdgeNotifierProxy : public Graph::EdgeNotifier::ObserverBase {\n    public:\n\n      typedef typename Graph::EdgeNotifier::ObserverBase Parent;\n      typedef AlterableSplitGraphAdaptor AdaptorBase;\n      \n      EdgeNotifierProxy(const AdaptorBase& _adaptor)\n        : Parent(), adaptor(&_adaptor) {\n      }\n\n      virtual ~EdgeNotifierProxy() {\n        if (Parent::attached()) {\n          Parent::detach();\n        }\n      }\n\n      void setNotifier(typename Graph::EdgeNotifier& graph_notifier) {\n        Parent::attach(graph_notifier);\n      }\n\n      \n    protected:\n\n      virtual void add(const GraphEdge& ge) {\n        adaptor->notifier(Edge()).add(AdaptorBase::edge(ge));\n      }\n      virtual void add(const std::vector<GraphEdge>& ge) {\n        std::vector<Edge> edges;\n        for (int i = 0; i < int(ge.size()); ++i) {\n          edges.push_back(AdaptorBase::edge(ge[i]));\n        }\n        adaptor->notifier(Edge()).add(edges);\n      }\n      virtual void erase(const GraphEdge& ge) {\n        adaptor->notifier(Edge()).erase(AdaptorBase::edge(ge));\n      }\n      virtual void erase(const std::vector<GraphEdge>& ge) {\n        std::vector<Edge> edges;\n        for (int i = 0; i < int(ge.size()); ++i) {\n          edges.push_back(AdaptorBase::edge(ge[i]));\n        }\n        adaptor->notifier(Edge()).erase(edges);\n      }\n      virtual void build() {\n        std::vector<Edge> edges;\n        const typename Parent::Notifier* nf = Parent::notifier();\n        GraphEdge it;\n        for (nf->first(it); it != INVALID; nf->next(it)) {\n          edges.push_back(AdaptorBase::Parent::edge(it));\n        }\n        adaptor->notifier(Edge()).add(edges);\n      }\n      virtual void clear() {\n        std::vector<Edge> edges;\n        const typename Parent::Notifier* nf = Parent::notifier();\n        GraphEdge it;\n        for (nf->first(it); it != INVALID; nf->next(it)) {\n          edges.push_back(AdaptorBase::Parent::edge(it));\n        }\n        adaptor->notifier(Edge()).erase(edges);\n      }\n\n      const AdaptorBase* adaptor;\n    };\n\n\n    mutable NodeNotifier node_notifier;\n    mutable EdgeNotifier edge_notifier;\n\n    NodeNotifierProxy node_notifier_proxy;\n    EdgeNotifierProxy edge_notifier_proxy;\n\n  };\n\n  /// \\ingroup graph_adaptors\n  ///\n  /// \\brief Split graph adaptor class\n  /// \n  /// This is an graph adaptor which splits all node into an in-node\n  /// and an out-node. Formaly, the adaptor replaces each \\f$ u \\f$\n  /// node in the graph with two node, \\f$ u_{in} \\f$ node and \n  /// \\f$ u_{out} \\f$ node. If there is an \\f$ (v, u) \\f$ edge in the \n  /// original graph the new target of the edge will be \\f$ u_{in} \\f$ and\n  /// similarly the source of the original \\f$ (u, v) \\f$ edge will be\n  /// \\f$ u_{out} \\f$.  The adaptor will add for each node in the \n  /// original graph an additional edge which will connect \n  /// \\f$ (u_{in}, u_{out}) \\f$.\n  ///\n  /// The aim of this class is to run algorithm with node costs if the \n  /// algorithm can use directly just edge costs. In this case we should use\n  /// a \\c SplitGraphAdaptor and set the node cost of the graph to the\n  /// bind edge in the adapted graph.\n  /// \n  /// By example a maximum flow algoritm can compute how many edge\n  /// disjoint paths are in the graph. But we would like to know how\n  /// many node disjoint paths are in the graph. First we have to\n  /// adapt the graph with the \\c SplitGraphAdaptor. Then run the flow\n  /// algorithm on the adapted graph. The bottleneck of the flow will\n  /// be the bind edges which bounds the flow with the count of the\n  /// node disjoint paths.\n  ///\n  ///\\code\n  ///\n  /// typedef SplitGraphAdaptor<SmartGraph> SGraph;\n  ///\n  /// SGraph sgraph(graph);\n  ///\n  /// typedef ConstMap<SGraph::Edge, int> SCapacity;\n  /// SCapacity scapacity(1);\n  ///\n  /// SGraph::EdgeMap<int> sflow(sgraph);\n  ///\n  /// Preflow<SGraph, SCapacity> \n  ///   spreflow(sgraph, scapacity, \n  ///            SGraph::outNode(source), SGraph::inNode(target));\n  ///                                            \n  /// spreflow.run();\n  ///\n  ///\\endcode\n  ///\n  /// The result of the mamixum flow on the original graph\n  /// shows the next figure:\n  ///\n  /// \\image html edge_disjoint.png\n  /// \\image latex edge_disjoint.eps \"Edge disjoint paths\" width=\\textwidth\n  /// \n  /// And the maximum flow on the adapted graph:\n  ///\n  /// \\image html node_disjoint.png\n  /// \\image latex node_disjoint.eps \"Node disjoint paths\" width=\\textwidth\n  ///\n  /// The second solution contains just 3 disjoint paths while the first 4.\n  /// The full code can be found in the \\ref disjoint_paths_demo.cc demo file.\n  ///\n  /// This graph adaptor is fully conform to the \n  /// \\ref concepts::Graph \"Graph\" concept and\n  /// contains some additional member functions and types. The \n  /// documentation of some member functions may be found just in the\n  /// SplitGraphAdaptorBase class.\n  ///\n  /// \\sa SplitGraphAdaptorBase\n  template <typename _Graph>\n  class SplitGraphAdaptor : public AlterableSplitGraphAdaptor<_Graph> {\n  public:\n    typedef AlterableSplitGraphAdaptor<_Graph> Parent;\n\n    typedef typename Parent::Node Node;\n    typedef typename Parent::Edge Edge;\n\n    /// \\brief Constructor of the adaptor.\n    ///\n    /// Constructor of the adaptor.\n    SplitGraphAdaptor(_Graph& g) {\n      Parent::setGraph(g);\n    }\n\n    /// \\brief NodeMap combined from two original NodeMap\n    ///\n    /// This class adapt two of the original graph NodeMap to\n    /// get a node map on the adapted graph.\n    template <typename InNodeMap, typename OutNodeMap>\n    class CombinedNodeMap {\n    public:\n\n      typedef Node Key;\n      typedef typename InNodeMap::Value Value;\n\n      /// \\brief Constructor\n      ///\n      /// Constructor.\n      CombinedNodeMap(InNodeMap& _inNodeMap, OutNodeMap& _outNodeMap) \n\t: inNodeMap(_inNodeMap), outNodeMap(_outNodeMap) {}\n\n      /// \\brief The subscript operator.\n      ///\n      /// The subscript operator.\n      Value& operator[](const Key& key) {\n\tif (Parent::inNode(key)) {\n\t  return inNodeMap[key];\n\t} else {\n\t  return outNodeMap[key];\n\t}\n      }\n\n      /// \\brief The const subscript operator.\n      ///\n      /// The const subscript operator.\n      Value operator[](const Key& key) const {\n\tif (Parent::inNode(key)) {\n\t  return inNodeMap[key];\n\t} else {\n\t  return outNodeMap[key];\n\t}\n      }\n\n      /// \\brief The setter function of the map.\n      /// \n      /// The setter function of the map.\n      void set(const Key& key, const Value& value) {\n\tif (Parent::inNode(key)) {\n\t  inNodeMap.set(key, value);\n\t} else {\n\t  outNodeMap.set(key, value);\n\t}\n      }\n      \n    private:\n      \n      InNodeMap& inNodeMap;\n      OutNodeMap& outNodeMap;\n      \n    };\n\n\n    /// \\brief Just gives back a combined node map.\n    /// \n    /// Just gives back a combined node map.\n    template <typename InNodeMap, typename OutNodeMap>\n    static CombinedNodeMap<InNodeMap, OutNodeMap> \n    combinedNodeMap(InNodeMap& in_map, OutNodeMap& out_map) {\n      return CombinedNodeMap<InNodeMap, OutNodeMap>(in_map, out_map);\n    }\n\n    template <typename InNodeMap, typename OutNodeMap>\n    static CombinedNodeMap<const InNodeMap, OutNodeMap> \n    combinedNodeMap(const InNodeMap& in_map, OutNodeMap& out_map) {\n      return CombinedNodeMap<const InNodeMap, OutNodeMap>(in_map, out_map);\n    }\n\n    template <typename InNodeMap, typename OutNodeMap>\n    static CombinedNodeMap<InNodeMap, const OutNodeMap> \n    combinedNodeMap(InNodeMap& in_map, const OutNodeMap& out_map) {\n      return CombinedNodeMap<InNodeMap, const OutNodeMap>(in_map, out_map);\n    }\n\n    template <typename InNodeMap, typename OutNodeMap>\n    static CombinedNodeMap<const InNodeMap, const OutNodeMap> \n    combinedNodeMap(const InNodeMap& in_map, const OutNodeMap& out_map) {\n      return CombinedNodeMap<const InNodeMap, \n        const OutNodeMap>(in_map, out_map);\n    }\n\n    /// \\brief EdgeMap combined from an original EdgeMap and NodeMap\n    ///\n    /// This class adapt an original graph EdgeMap and NodeMap to\n    /// get an edge map on the adapted graph.\n    template <typename GraphEdgeMap, typename GraphNodeMap>\n    class CombinedEdgeMap {\n    public:\n      \n      typedef Edge Key;\n      typedef typename GraphEdgeMap::Value Value;\n      \n      /// \\brief Constructor\n      ///\n      /// Constructor.\n      CombinedEdgeMap(GraphEdgeMap& _edge_map, GraphNodeMap& _node_map) \n\t: edge_map(_edge_map), node_map(_node_map) {}\n\n      /// \\brief The subscript operator.\n      ///\n      /// The subscript operator.\n      void set(const Edge& edge, const Value& val) {\n\tif (Parent::origEdge(edge)) {\n\t  edge_map.set(edge, val);\n\t} else {\n\t  node_map.set(edge, val);\n\t}\n      }\n\n      /// \\brief The const subscript operator.\n      ///\n      /// The const subscript operator.\n      Value operator[](const Key& edge) const {\n\tif (Parent::origEdge(edge)) {\n\t  return edge_map[edge];\n\t} else {\n\t  return node_map[edge];\n\t}\n      }      \n\n      /// \\brief The const subscript operator.\n      ///\n      /// The const subscript operator.\n      Value& operator[](const Key& edge) {\n\tif (Parent::origEdge(edge)) {\n\t  return edge_map[edge];\n\t} else {\n\t  return node_map[edge];\n\t}\n      }      \n      \n    private:\n      GraphEdgeMap& edge_map;\n      GraphNodeMap& node_map;\n    };\n                    \n    /// \\brief Just gives back a combined edge map.\n    /// \n    /// Just gives back a combined edge map.\n    template <typename GraphEdgeMap, typename GraphNodeMap>\n    static CombinedEdgeMap<GraphEdgeMap, GraphNodeMap> \n    combinedEdgeMap(GraphEdgeMap& edge_map, GraphNodeMap& node_map) {\n      return CombinedEdgeMap<GraphEdgeMap, GraphNodeMap>(edge_map, node_map);\n    }\n\n    template <typename GraphEdgeMap, typename GraphNodeMap>\n    static CombinedEdgeMap<const GraphEdgeMap, GraphNodeMap> \n    combinedEdgeMap(const GraphEdgeMap& edge_map, GraphNodeMap& node_map) {\n      return CombinedEdgeMap<const GraphEdgeMap, \n        GraphNodeMap>(edge_map, node_map);\n    }\n\n    template <typename GraphEdgeMap, typename GraphNodeMap>\n    static CombinedEdgeMap<GraphEdgeMap, const GraphNodeMap> \n    combinedEdgeMap(GraphEdgeMap& edge_map, const GraphNodeMap& node_map) {\n      return CombinedEdgeMap<GraphEdgeMap, \n        const GraphNodeMap>(edge_map, node_map);\n    }\n\n    template <typename GraphEdgeMap, typename GraphNodeMap>\n    static CombinedEdgeMap<const GraphEdgeMap, const GraphNodeMap> \n    combinedEdgeMap(const GraphEdgeMap& edge_map, \n                    const GraphNodeMap& node_map) {\n      return CombinedEdgeMap<const GraphEdgeMap, \n        const GraphNodeMap>(edge_map, node_map);\n    }\n\n  };\n\n  /// \\brief Just gives back a split graph adaptor\n  ///\n  /// Just gives back a split graph adaptor\n  template<typename Graph>\n  SplitGraphAdaptor<Graph>\n  splitGraphAdaptor(const Graph& graph) {\n    return SplitGraphAdaptor<Graph>(graph);\n  }\n\n\n} //namespace lemon\n\n#endif //LEMON_GRAPH_ADAPTOR_H\n\n"
  },
  {
    "path": "src/lemon/graph_utils.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_GRAPH_UTILS_H\n#define LEMON_GRAPH_UTILS_H\n\n#include <iterator>\n#include <vector>\n#include <map>\n#include <lemon/math.h>\n#include <algorithm>\n\n#include <lemon/bits/invalid.h>\n#include <lemon/bits/utility.h>\n#include <lemon/maps.h>\n#include <lemon/bits/traits.h>\n\n#include <lemon/bits/alteration_notifier.h>\n#include <lemon/bits/default_map.h>\n\n///\\ingroup gutils\n///\\file\n///\\brief Graph utilities.\n\nnamespace lemon {\n\n  /// \\addtogroup gutils\n  /// @{\n\n  ///Creates convenience typedefs for the graph types and iterators\n\n  ///This \\c \\#define creates convenience typedefs for the following types\n  ///of \\c Graph: \\c Node,  \\c NodeIt, \\c Edge, \\c EdgeIt, \\c InEdgeIt,\n  ///\\c OutEdgeIt\n  ///\\note If \\c G it a template parameter, it should be used in this way.\n  ///\\code\n  ///  GRAPH_TYPEDEFS(typename G);\n  ///\\endcode\n  ///\n  ///\\warning There are no typedefs for the graph maps because of the lack of\n  ///template typedefs in C++.\n#define GRAPH_TYPEDEFS(Graph)\t\t\t\t\\\n  typedef Graph::     Node      Node;\t\t\t\\\n    typedef Graph::   NodeIt    NodeIt;\t\t\t\\\n    typedef Graph::   Edge      Edge;\t\t\t\\\n    typedef Graph::   EdgeIt    EdgeIt;\t\t\t\\\n    typedef Graph:: InEdgeIt  InEdgeIt;\t\t\t\\\n    typedef Graph::OutEdgeIt OutEdgeIt\n\n  ///Creates convenience typedefs for the undirected graph types and iterators\n\n  ///This \\c \\#define creates the same convenience typedefs as defined by\n  ///\\ref GRAPH_TYPEDEFS(Graph) and three more, namely it creates\n  ///\\c UEdge, \\c UEdgeIt, \\c IncEdgeIt,\n  ///\n  ///\\note If \\c G it a template parameter, it should be used in this way.\n  ///\\code\n  ///  UGRAPH_TYPEDEFS(typename G);\n  ///\\endcode\n  ///\n  ///\\warning There are no typedefs for the graph maps because of the lack of\n  ///template typedefs in C++.\n#define UGRAPH_TYPEDEFS(Graph)\t\t\t\t\\\n  GRAPH_TYPEDEFS(Graph);\t\t\t\t\\\n    typedef Graph:: UEdge   UEdge;\t\t\t\\\n    typedef Graph:: UEdgeIt UEdgeIt;\t\t\t\\\n    typedef Graph:: IncEdgeIt   IncEdgeIt\n\n  ///\\brief Creates convenience typedefs for the bipartite undirected graph \n  ///types and iterators\n\n  ///This \\c \\#define creates the same convenience typedefs as defined by\n  ///\\ref UGRAPH_TYPEDEFS(Graph) and two more, namely it creates\n  ///\\c ANodeIt, \\c BNodeIt, \n  ///\n  ///\\note If \\c G it a template parameter, it should be used in this way.\n  ///\\code\n  ///  BPUGRAPH_TYPEDEFS(typename G);\n  ///\\endcode\n  ///\n  ///\\warning There are no typedefs for the graph maps because of the lack of\n  ///template typedefs in C++.\n#define BPUGRAPH_TYPEDEFS(Graph)            \\\n  UGRAPH_TYPEDEFS(Graph);\t\t    \\\n    typedef Graph::ANode ANode;             \\\n    typedef Graph::BNode BNode;             \\\n    typedef Graph::ANodeIt ANodeIt;\t    \\\n    typedef Graph::BNodeIt BNodeIt\n\n  /// \\brief Function to count the items in the graph.\n  ///\n  /// This function counts the items (nodes, edges etc) in the graph.\n  /// The complexity of the function is O(n) because\n  /// it iterates on all of the items.\n\n  template <typename Graph, typename Item>\n  inline int countItems(const Graph& g) {\n    typedef typename ItemSetTraits<Graph, Item>::ItemIt ItemIt;\n    int num = 0;\n    for (ItemIt it(g); it != INVALID; ++it) {\n      ++num;\n    }\n    return num;\n  }\n\n  // Node counting:\n\n  namespace _graph_utils_bits {\n    \n    template <typename Graph, typename Enable = void>\n    struct CountNodesSelector {\n      static int count(const Graph &g) {\n        return countItems<Graph, typename Graph::Node>(g);\n      }\n    };\n\n    template <typename Graph>\n    struct CountNodesSelector<\n      Graph, typename \n      enable_if<typename Graph::NodeNumTag, void>::type> \n    {\n      static int count(const Graph &g) {\n        return g.nodeNum();\n      }\n    };    \n  }\n\n  /// \\brief Function to count the nodes in the graph.\n  ///\n  /// This function counts the nodes in the graph.\n  /// The complexity of the function is O(n) but for some\n  /// graph structures it is specialized to run in O(1).\n  ///\n  /// If the graph contains a \\e nodeNum() member function and a \n  /// \\e NodeNumTag tag then this function calls directly the member\n  /// function to query the cardinality of the node set.\n  template <typename Graph>\n  inline int countNodes(const Graph& g) {\n    return _graph_utils_bits::CountNodesSelector<Graph>::count(g);\n  }\n\n  namespace _graph_utils_bits {\n    \n    template <typename Graph, typename Enable = void>\n    struct CountANodesSelector {\n      static int count(const Graph &g) {\n        return countItems<Graph, typename Graph::ANode>(g);\n      }\n    };\n\n    template <typename Graph>\n    struct CountANodesSelector<\n      Graph, typename \n      enable_if<typename Graph::NodeNumTag, void>::type> \n    {\n      static int count(const Graph &g) {\n        return g.aNodeNum();\n      }\n    };    \n  }\n\n  /// \\brief Function to count the anodes in the graph.\n  ///\n  /// This function counts the anodes in the graph.\n  /// The complexity of the function is O(an) but for some\n  /// graph structures it is specialized to run in O(1).\n  ///\n  /// If the graph contains an \\e aNodeNum() member function and a \n  /// \\e NodeNumTag tag then this function calls directly the member\n  /// function to query the cardinality of the A-node set.\n  template <typename Graph>\n  inline int countANodes(const Graph& g) {\n    return _graph_utils_bits::CountANodesSelector<Graph>::count(g);\n  }\n\n  namespace _graph_utils_bits {\n    \n    template <typename Graph, typename Enable = void>\n    struct CountBNodesSelector {\n      static int count(const Graph &g) {\n        return countItems<Graph, typename Graph::BNode>(g);\n      }\n    };\n\n    template <typename Graph>\n    struct CountBNodesSelector<\n      Graph, typename \n      enable_if<typename Graph::NodeNumTag, void>::type> \n    {\n      static int count(const Graph &g) {\n        return g.bNodeNum();\n      }\n    };    \n  }\n\n  /// \\brief Function to count the bnodes in the graph.\n  ///\n  /// This function counts the bnodes in the graph.\n  /// The complexity of the function is O(bn) but for some\n  /// graph structures it is specialized to run in O(1).\n  ///\n  /// If the graph contains a \\e bNodeNum() member function and a \n  /// \\e NodeNumTag tag then this function calls directly the member\n  /// function to query the cardinality of the B-node set.\n  template <typename Graph>\n  inline int countBNodes(const Graph& g) {\n    return _graph_utils_bits::CountBNodesSelector<Graph>::count(g);\n  }\n\n\n  // Edge counting:\n\n  namespace _graph_utils_bits {\n    \n    template <typename Graph, typename Enable = void>\n    struct CountEdgesSelector {\n      static int count(const Graph &g) {\n        return countItems<Graph, typename Graph::Edge>(g);\n      }\n    };\n\n    template <typename Graph>\n    struct CountEdgesSelector<\n      Graph, \n      typename enable_if<typename Graph::EdgeNumTag, void>::type> \n    {\n      static int count(const Graph &g) {\n        return g.edgeNum();\n      }\n    };    \n  }\n\n  /// \\brief Function to count the edges in the graph.\n  ///\n  /// This function counts the edges in the graph.\n  /// The complexity of the function is O(e) but for some\n  /// graph structures it is specialized to run in O(1).\n  ///\n  /// If the graph contains a \\e edgeNum() member function and a \n  /// \\e EdgeNumTag tag then this function calls directly the member\n  /// function to query the cardinality of the edge set.\n  template <typename Graph>\n  inline int countEdges(const Graph& g) {\n    return _graph_utils_bits::CountEdgesSelector<Graph>::count(g);\n  }\n\n  // Undirected edge counting:\n  namespace _graph_utils_bits {\n    \n    template <typename Graph, typename Enable = void>\n    struct CountUEdgesSelector {\n      static int count(const Graph &g) {\n        return countItems<Graph, typename Graph::UEdge>(g);\n      }\n    };\n\n    template <typename Graph>\n    struct CountUEdgesSelector<\n      Graph, \n      typename enable_if<typename Graph::EdgeNumTag, void>::type> \n    {\n      static int count(const Graph &g) {\n        return g.uEdgeNum();\n      }\n    };    \n  }\n\n  /// \\brief Function to count the undirected edges in the graph.\n  ///\n  /// This function counts the undirected edges in the graph.\n  /// The complexity of the function is O(e) but for some\n  /// graph structures it is specialized to run in O(1).\n  ///\n  /// If the graph contains a \\e uEdgeNum() member function and a \n  /// \\e EdgeNumTag tag then this function calls directly the member\n  /// function to query the cardinality of the undirected edge set.\n  template <typename Graph>\n  inline int countUEdges(const Graph& g) {\n    return _graph_utils_bits::CountUEdgesSelector<Graph>::count(g);\n\n  }\n\n\n  template <typename Graph, typename DegIt>\n  inline int countNodeDegree(const Graph& _g, const typename Graph::Node& _n) {\n    int num = 0;\n    for (DegIt it(_g, _n); it != INVALID; ++it) {\n      ++num;\n    }\n    return num;\n  }\n\n  /// \\brief Function to count the number of the out-edges from node \\c n.\n  ///\n  /// This function counts the number of the out-edges from node \\c n\n  /// in the graph.  \n  template <typename Graph>\n  inline int countOutEdges(const Graph& _g,  const typename Graph::Node& _n) {\n    return countNodeDegree<Graph, typename Graph::OutEdgeIt>(_g, _n);\n  }\n\n  /// \\brief Function to count the number of the in-edges to node \\c n.\n  ///\n  /// This function counts the number of the in-edges to node \\c n\n  /// in the graph.  \n  template <typename Graph>\n  inline int countInEdges(const Graph& _g,  const typename Graph::Node& _n) {\n    return countNodeDegree<Graph, typename Graph::InEdgeIt>(_g, _n);\n  }\n\n  /// \\brief Function to count the number of the inc-edges to node \\c n.\n  ///\n  /// This function counts the number of the inc-edges to node \\c n\n  /// in the graph.  \n  template <typename Graph>\n  inline int countIncEdges(const Graph& _g,  const typename Graph::Node& _n) {\n    return countNodeDegree<Graph, typename Graph::IncEdgeIt>(_g, _n);\n  }\n\n  namespace _graph_utils_bits {\n    \n    template <typename Graph, typename Enable = void>\n    struct FindEdgeSelector {\n      typedef typename Graph::Node Node;\n      typedef typename Graph::Edge Edge;\n      static Edge find(const Graph &g, Node u, Node v, Edge e) {\n        if (e == INVALID) {\n          g.firstOut(e, u);\n        } else {\n          g.nextOut(e);\n        }\n        while (e != INVALID && g.target(e) != v) {\n          g.nextOut(e);\n        }\n        return e;\n      }\n    };\n\n    template <typename Graph>\n    struct FindEdgeSelector<\n      Graph, \n      typename enable_if<typename Graph::FindEdgeTag, void>::type> \n    {\n      typedef typename Graph::Node Node;\n      typedef typename Graph::Edge Edge;\n      static Edge find(const Graph &g, Node u, Node v, Edge prev) {\n        return g.findEdge(u, v, prev);\n      }\n    };    \n  }\n\n  /// \\brief Finds an edge between two nodes of a graph.\n  ///\n  /// Finds an edge from node \\c u to node \\c v in graph \\c g.\n  ///\n  /// If \\c prev is \\ref INVALID (this is the default value), then\n  /// it finds the first edge from \\c u to \\c v. Otherwise it looks for\n  /// the next edge from \\c u to \\c v after \\c prev.\n  /// \\return The found edge or \\ref INVALID if there is no such an edge.\n  ///\n  /// Thus you can iterate through each edge from \\c u to \\c v as it follows.\n  ///\\code\n  /// for(Edge e=findEdge(g,u,v);e!=INVALID;e=findEdge(g,u,v,e)) {\n  ///   ...\n  /// }\n  ///\\endcode\n  ///\n  ///\\sa EdgeLookUp\n  ///\\sa AllEdgeLookUp\n  ///\\sa DynEdgeLookUp\n  ///\\sa ConEdgeIt\n  template <typename Graph>\n  inline typename Graph::Edge \n  findEdge(const Graph &g, typename Graph::Node u, typename Graph::Node v,\n           typename Graph::Edge prev = INVALID) {\n    return _graph_utils_bits::FindEdgeSelector<Graph>::find(g, u, v, prev);\n  }\n\n  /// \\brief Iterator for iterating on edges connected the same nodes.\n  ///\n  /// Iterator for iterating on edges connected the same nodes. It is \n  /// higher level interface for the findEdge() function. You can\n  /// use it the following way:\n  ///\\code\n  /// for (ConEdgeIt<Graph> it(g, src, trg); it != INVALID; ++it) {\n  ///   ...\n  /// }\n  ///\\endcode\n  /// \n  ///\\sa findEdge()\n  ///\\sa EdgeLookUp\n  ///\\sa AllEdgeLookUp\n  ///\\sa DynEdgeLookUp\n  ///\n  /// \\author Balazs Dezso \n  template <typename _Graph>\n  class ConEdgeIt : public _Graph::Edge {\n  public:\n\n    typedef _Graph Graph;\n    typedef typename Graph::Edge Parent;\n\n    typedef typename Graph::Edge Edge;\n    typedef typename Graph::Node Node;\n\n    /// \\brief Constructor.\n    ///\n    /// Construct a new ConEdgeIt iterating on the edges which\n    /// connects the \\c u and \\c v node.\n    ConEdgeIt(const Graph& g, Node u, Node v) : graph(g) {\n      Parent::operator=(findEdge(graph, u, v));\n    }\n\n    /// \\brief Constructor.\n    ///\n    /// Construct a new ConEdgeIt which continues the iterating from \n    /// the \\c e edge.\n    ConEdgeIt(const Graph& g, Edge e) : Parent(e), graph(g) {}\n    \n    /// \\brief Increment operator.\n    ///\n    /// It increments the iterator and gives back the next edge.\n    ConEdgeIt& operator++() {\n      Parent::operator=(findEdge(graph, graph.source(*this), \n\t\t\t\t graph.target(*this), *this));\n      return *this;\n    }\n  private:\n    const Graph& graph;\n  };\n\n  namespace _graph_utils_bits {\n    \n    template <typename Graph, typename Enable = void>\n    struct FindUEdgeSelector {\n      typedef typename Graph::Node Node;\n      typedef typename Graph::UEdge UEdge;\n      static UEdge find(const Graph &g, Node u, Node v, UEdge e) {\n        bool b;\n        if (u != v) {\n          if (e == INVALID) {\n            g.firstInc(e, b, u);\n          } else {\n            b = g.source(e) == u;\n            g.nextInc(e, b);\n          }\n          while (e != INVALID && (b ? g.target(e) : g.source(e)) != v) {\n            g.nextInc(e, b);\n          }\n        } else {\n          if (e == INVALID) {\n            g.firstInc(e, b, u);\n          } else {\n            b = true;\n            g.nextInc(e, b);\n          }\n          while (e != INVALID && (!b || g.target(e) != v)) {\n            g.nextInc(e, b);\n          }\n        }\n        return e;\n      }\n    };\n\n    template <typename Graph>\n    struct FindUEdgeSelector<\n      Graph, \n      typename enable_if<typename Graph::FindEdgeTag, void>::type> \n    {\n      typedef typename Graph::Node Node;\n      typedef typename Graph::UEdge UEdge;\n      static UEdge find(const Graph &g, Node u, Node v, UEdge prev) {\n        return g.findUEdge(u, v, prev);\n      }\n    };    \n  }\n\n  /// \\brief Finds an uedge between two nodes of a graph.\n  ///\n  /// Finds an uedge from node \\c u to node \\c v in graph \\c g.\n  /// If the node \\c u and node \\c v is equal then each loop edge\n  /// will be enumerated.\n  ///\n  /// If \\c prev is \\ref INVALID (this is the default value), then\n  /// it finds the first edge from \\c u to \\c v. Otherwise it looks for\n  /// the next edge from \\c u to \\c v after \\c prev.\n  /// \\return The found edge or \\ref INVALID if there is no such an edge.\n  ///\n  /// Thus you can iterate through each edge from \\c u to \\c v as it follows.\n  ///\\code\n  /// for(UEdge e = findUEdge(g,u,v); e != INVALID; \n  ///     e = findUEdge(g,u,v,e)) {\n  ///   ...\n  /// }\n  ///\\endcode\n  ///\n  ///\\sa ConEdgeIt\n\n  template <typename Graph>\n  inline typename Graph::UEdge \n  findUEdge(const Graph &g, typename Graph::Node u, typename Graph::Node v,\n            typename Graph::UEdge p = INVALID) {\n    return _graph_utils_bits::FindUEdgeSelector<Graph>::find(g, u, v, p);\n  }\n\n  /// \\brief Iterator for iterating on uedges connected the same nodes.\n  ///\n  /// Iterator for iterating on uedges connected the same nodes. It is \n  /// higher level interface for the findUEdge() function. You can\n  /// use it the following way:\n  ///\\code\n  /// for (ConUEdgeIt<Graph> it(g, src, trg); it != INVALID; ++it) {\n  ///   ...\n  /// }\n  ///\\endcode\n  ///\n  ///\\sa findUEdge()\n  ///\n  /// \\author Balazs Dezso \n  template <typename _Graph>\n  class ConUEdgeIt : public _Graph::UEdge {\n  public:\n\n    typedef _Graph Graph;\n    typedef typename Graph::UEdge Parent;\n\n    typedef typename Graph::UEdge UEdge;\n    typedef typename Graph::Node Node;\n\n    /// \\brief Constructor.\n    ///\n    /// Construct a new ConUEdgeIt iterating on the edges which\n    /// connects the \\c u and \\c v node.\n    ConUEdgeIt(const Graph& g, Node u, Node v) : graph(g) {\n      Parent::operator=(findUEdge(graph, u, v));\n    }\n\n    /// \\brief Constructor.\n    ///\n    /// Construct a new ConUEdgeIt which continues the iterating from \n    /// the \\c e edge.\n    ConUEdgeIt(const Graph& g, UEdge e) : Parent(e), graph(g) {}\n    \n    /// \\brief Increment operator.\n    ///\n    /// It increments the iterator and gives back the next edge.\n    ConUEdgeIt& operator++() {\n      Parent::operator=(findUEdge(graph, graph.source(*this), \n\t\t\t\t      graph.target(*this), *this));\n      return *this;\n    }\n  private:\n    const Graph& graph;\n  };\n\n  /// \\brief Copy a map.\n  ///\n  /// This function copies the \\c from map to the \\c to map. It uses the\n  /// given iterator to iterate on the data structure and it uses the \\c ref\n  /// mapping to convert the from's keys to the to's keys.\n  template <typename To, typename From, \n\t    typename ItemIt, typename Ref>\t    \n  void copyMap(To& to, const From& from, \n\t       ItemIt it, const Ref& ref) {\n    for (; it != INVALID; ++it) {\n      to[ref[it]] = from[it];\n    }\n  }\n\n  /// \\brief Copy the from map to the to map.\n  ///\n  /// Copy the \\c from map to the \\c to map. It uses the given iterator\n  /// to iterate on the data structure.\n  template <typename To, typename From, typename ItemIt>\t    \n  void copyMap(To& to, const From& from, ItemIt it) {\n    for (; it != INVALID; ++it) {\n      to[it] = from[it];\n    }\n  }\n\n  namespace _graph_utils_bits {\n\n    template <typename Graph, typename Item, typename RefMap>\n    class MapCopyBase {\n    public:\n      virtual void copy(const Graph& from, const RefMap& refMap) = 0;\n      \n      virtual ~MapCopyBase() {}\n    };\n\n    template <typename Graph, typename Item, typename RefMap, \n              typename ToMap, typename FromMap>\n    class MapCopy : public MapCopyBase<Graph, Item, RefMap> {\n    public:\n\n      MapCopy(ToMap& tmap, const FromMap& map) \n        : _tmap(tmap), _map(map) {}\n      \n      virtual void copy(const Graph& graph, const RefMap& refMap) {\n        typedef typename ItemSetTraits<Graph, Item>::ItemIt ItemIt;\n        for (ItemIt it(graph); it != INVALID; ++it) {\n          _tmap.set(refMap[it], _map[it]);\n        }\n      }\n\n    private:\n      ToMap& _tmap;\n      const FromMap& _map;\n    };\n\n    template <typename Graph, typename Item, typename RefMap, typename It>\n    class ItemCopy : public MapCopyBase<Graph, Item, RefMap> {\n    public:\n\n      ItemCopy(It& it, const Item& item) : _it(it), _item(item) {}\n      \n      virtual void copy(const Graph&, const RefMap& refMap) {\n        _it = refMap[_item];\n      }\n\n    private:\n      It& _it;\n      Item _item;\n    };\n\n    template <typename Graph, typename Item, typename RefMap, typename Ref>\n    class RefCopy : public MapCopyBase<Graph, Item, RefMap> {\n    public:\n\n      RefCopy(Ref& map) : _map(map) {}\n      \n      virtual void copy(const Graph& graph, const RefMap& refMap) {\n        typedef typename ItemSetTraits<Graph, Item>::ItemIt ItemIt;\n        for (ItemIt it(graph); it != INVALID; ++it) {\n          _map.set(it, refMap[it]);\n        }\n      }\n\n    private:\n      Ref& _map;\n    };\n\n    template <typename Graph, typename Item, typename RefMap, \n              typename CrossRef>\n    class CrossRefCopy : public MapCopyBase<Graph, Item, RefMap> {\n    public:\n\n      CrossRefCopy(CrossRef& cmap) : _cmap(cmap) {}\n      \n      virtual void copy(const Graph& graph, const RefMap& refMap) {\n        typedef typename ItemSetTraits<Graph, Item>::ItemIt ItemIt;\n        for (ItemIt it(graph); it != INVALID; ++it) {\n          _cmap.set(refMap[it], it);\n        }\n      }\n\n    private:\n      CrossRef& _cmap;\n    };\n\n    template <typename Graph, typename Enable = void>\n    struct GraphCopySelector {\n      template <typename From, typename NodeRefMap, typename EdgeRefMap>\n      static void copy(Graph &to, const From& from,\n                       NodeRefMap& nodeRefMap, EdgeRefMap& edgeRefMap) {\n        for (typename From::NodeIt it(from); it != INVALID; ++it) {\n          nodeRefMap[it] = to.addNode();\n        }\n        for (typename From::EdgeIt it(from); it != INVALID; ++it) {\n          edgeRefMap[it] = to.addEdge(nodeRefMap[from.source(it)], \n                                          nodeRefMap[from.target(it)]);\n        }\n      }\n    };\n\n    template <typename Graph>\n    struct GraphCopySelector<\n      Graph, \n      typename enable_if<typename Graph::BuildTag, void>::type> \n    {\n      template <typename From, typename NodeRefMap, typename EdgeRefMap>\n      static void copy(Graph &to, const From& from,\n                       NodeRefMap& nodeRefMap, EdgeRefMap& edgeRefMap) {\n        to.build(from, nodeRefMap, edgeRefMap);\n      }\n    };\n\n    template <typename UGraph, typename Enable = void>\n    struct UGraphCopySelector {\n      template <typename From, typename NodeRefMap, typename UEdgeRefMap>\n      static void copy(UGraph &to, const From& from,\n                       NodeRefMap& nodeRefMap, UEdgeRefMap& uEdgeRefMap) {\n        for (typename From::NodeIt it(from); it != INVALID; ++it) {\n          nodeRefMap[it] = to.addNode();\n        }\n        for (typename From::UEdgeIt it(from); it != INVALID; ++it) {\n          uEdgeRefMap[it] = to.addEdge(nodeRefMap[from.source(it)], \n\t\t\t\t       nodeRefMap[from.target(it)]);\n        }\n      }\n    };\n\n    template <typename UGraph>\n    struct UGraphCopySelector<\n      UGraph, \n      typename enable_if<typename UGraph::BuildTag, void>::type> \n    {\n      template <typename From, typename NodeRefMap, typename UEdgeRefMap>\n      static void copy(UGraph &to, const From& from,\n                       NodeRefMap& nodeRefMap, UEdgeRefMap& uEdgeRefMap) {\n        to.build(from, nodeRefMap, uEdgeRefMap);\n      }\n    };\n\n    template <typename BpUGraph, typename Enable = void>\n    struct BpUGraphCopySelector {\n      template <typename From, typename ANodeRefMap, \n                typename BNodeRefMap, typename UEdgeRefMap>\n      static void copy(BpUGraph &to, const From& from,\n                       ANodeRefMap& aNodeRefMap, BNodeRefMap& bNodeRefMap,\n                       UEdgeRefMap& uEdgeRefMap) {\n        for (typename From::ANodeIt it(from); it != INVALID; ++it) {\n          aNodeRefMap[it] = to.addANode();\n        }\n        for (typename From::BNodeIt it(from); it != INVALID; ++it) {\n          bNodeRefMap[it] = to.addBNode();\n        }\n        for (typename From::UEdgeIt it(from); it != INVALID; ++it) {\n          uEdgeRefMap[it] = to.addEdge(aNodeRefMap[from.aNode(it)], \n                                           bNodeRefMap[from.bNode(it)]);\n        }\n      }\n    };\n\n    template <typename BpUGraph>\n    struct BpUGraphCopySelector<\n      BpUGraph, \n      typename enable_if<typename BpUGraph::BuildTag, void>::type> \n    {\n      template <typename From, typename ANodeRefMap, \n                typename BNodeRefMap, typename UEdgeRefMap>\n      static void copy(BpUGraph &to, const From& from,\n                       ANodeRefMap& aNodeRefMap, BNodeRefMap& bNodeRefMap,\n                       UEdgeRefMap& uEdgeRefMap) {\n        to.build(from, aNodeRefMap, bNodeRefMap, uEdgeRefMap);\n      }\n    };\n    \n\n  }\n\n  /// \\brief Class to copy a graph.\n  ///\n  /// Class to copy a graph to another graph (duplicate a graph). The\n  /// simplest way of using it is through the \\c copyGraph() function.\n  template <typename To, typename From>\n  class GraphCopy {\n  private:\n\n    typedef typename From::Node Node;\n    typedef typename From::NodeIt NodeIt;\n    typedef typename From::Edge Edge;\n    typedef typename From::EdgeIt EdgeIt;\n\n    typedef typename To::Node TNode;\n    typedef typename To::Edge TEdge;\n\n    typedef typename From::template NodeMap<TNode> NodeRefMap;\n    typedef typename From::template EdgeMap<TEdge> EdgeRefMap;\n    \n    \n  public: \n\n\n    /// \\brief Constructor for the GraphCopy.\n    ///\n    /// It copies the content of the \\c _from graph into the\n    /// \\c _to graph.\n    GraphCopy(To& _to, const From& _from) \n      : from(_from), to(_to) {}\n\n    /// \\brief Destructor of the GraphCopy\n    ///\n    /// Destructor of the GraphCopy\n    ~GraphCopy() {\n      for (int i = 0; i < int(nodeMapCopies.size()); ++i) {\n        delete nodeMapCopies[i];\n      }\n      for (int i = 0; i < int(edgeMapCopies.size()); ++i) {\n        delete edgeMapCopies[i];\n      }\n\n    }\n\n    /// \\brief Copies the node references into the given map.\n    ///\n    /// Copies the node references into the given map.\n    template <typename NodeRef>\n    GraphCopy& nodeRef(NodeRef& map) {\n      nodeMapCopies.push_back(new _graph_utils_bits::RefCopy<From, Node, \n                              NodeRefMap, NodeRef>(map));\n      return *this;\n    }\n\n    /// \\brief Copies the node cross references into the given map.\n    ///\n    ///  Copies the node cross references (reverse references) into\n    ///  the given map.\n    template <typename NodeCrossRef>\n    GraphCopy& nodeCrossRef(NodeCrossRef& map) {\n      nodeMapCopies.push_back(new _graph_utils_bits::CrossRefCopy<From, Node,\n                              NodeRefMap, NodeCrossRef>(map));\n      return *this;\n    }\n\n    /// \\brief Make copy of the given map.\n    ///\n    /// Makes copy of the given map for the newly created graph. \n    /// The new map's key type is the to graph's node type,\n    /// and the copied map's key type is the from graph's node\n    /// type.  \n    template <typename ToMap, typename FromMap>\n    GraphCopy& nodeMap(ToMap& tmap, const FromMap& map) {\n      nodeMapCopies.push_back(new _graph_utils_bits::MapCopy<From, Node, \n                              NodeRefMap, ToMap, FromMap>(tmap, map));\n      return *this;\n    }\n\n    /// \\brief Make a copy of the given node.\n    ///\n    /// Make a copy of the given node.\n    GraphCopy& node(TNode& tnode, const Node& snode) {\n      nodeMapCopies.push_back(new _graph_utils_bits::ItemCopy<From, Node, \n                              NodeRefMap, TNode>(tnode, snode));\n      return *this;\n    }\n\n    /// \\brief Copies the edge references into the given map.\n    ///\n    /// Copies the edge references into the given map.\n    template <typename EdgeRef>\n    GraphCopy& edgeRef(EdgeRef& map) {\n      edgeMapCopies.push_back(new _graph_utils_bits::RefCopy<From, Edge, \n                              EdgeRefMap, EdgeRef>(map));\n      return *this;\n    }\n\n    /// \\brief Copies the edge cross references into the given map.\n    ///\n    ///  Copies the edge cross references (reverse references) into\n    ///  the given map.\n    template <typename EdgeCrossRef>\n    GraphCopy& edgeCrossRef(EdgeCrossRef& map) {\n      edgeMapCopies.push_back(new _graph_utils_bits::CrossRefCopy<From, Edge,\n                              EdgeRefMap, EdgeCrossRef>(map));\n      return *this;\n    }\n\n    /// \\brief Make copy of the given map.\n    ///\n    /// Makes copy of the given map for the newly created graph. \n    /// The new map's key type is the to graph's edge type,\n    /// and the copied map's key type is the from graph's edge\n    /// type.  \n    template <typename ToMap, typename FromMap>\n    GraphCopy& edgeMap(ToMap& tmap, const FromMap& map) {\n      edgeMapCopies.push_back(new _graph_utils_bits::MapCopy<From, Edge, \n                              EdgeRefMap, ToMap, FromMap>(tmap, map));\n      return *this;\n    }\n\n    /// \\brief Make a copy of the given edge.\n    ///\n    /// Make a copy of the given edge.\n    GraphCopy& edge(TEdge& tedge, const Edge& sedge) {\n      edgeMapCopies.push_back(new _graph_utils_bits::ItemCopy<From, Edge, \n                              EdgeRefMap, TEdge>(tedge, sedge));\n      return *this;\n    }\n\n    /// \\brief Executes the copies.\n    ///\n    /// Executes the copies.\n    void run() {\n      NodeRefMap nodeRefMap(from);\n      EdgeRefMap edgeRefMap(from);\n      _graph_utils_bits::GraphCopySelector<To>::\n        copy(to, from, nodeRefMap, edgeRefMap);\n      for (int i = 0; i < int(nodeMapCopies.size()); ++i) {\n        nodeMapCopies[i]->copy(from, nodeRefMap);\n      }\n      for (int i = 0; i < int(edgeMapCopies.size()); ++i) {\n        edgeMapCopies[i]->copy(from, edgeRefMap);\n      }      \n    }\n\n  protected:\n\n\n    const From& from;\n    To& to;\n\n    std::vector<_graph_utils_bits::MapCopyBase<From, Node, NodeRefMap>* > \n    nodeMapCopies;\n\n    std::vector<_graph_utils_bits::MapCopyBase<From, Edge, EdgeRefMap>* > \n    edgeMapCopies;\n\n  };\n\n  /// \\brief Copy a graph to another graph.\n  ///\n  /// Copy a graph to another graph.\n  /// The usage of the function:\n  /// \n  ///\\code\n  /// copyGraph(trg, src).nodeRef(nr).edgeCrossRef(ecr).run();\n  ///\\endcode\n  /// \n  /// After the copy the \\c nr map will contain the mapping from the\n  /// nodes of the \\c from graph to the nodes of the \\c to graph and\n  /// \\c ecr will contain the mapping from the edges of the \\c to graph\n  /// to the edges of the \\c from graph.\n  ///\n  /// \\see GraphCopy \n  template <typename To, typename From>\n  GraphCopy<To, From> copyGraph(To& to, const From& from) {\n    return GraphCopy<To, From>(to, from);\n  }\n\n  /// \\brief Class to copy an undirected graph.\n  ///\n  /// Class to copy an undirected graph to another graph (duplicate a graph).\n  /// The simplest way of using it is through the \\c copyUGraph() function.\n  template <typename To, typename From>\n  class UGraphCopy {\n  private:\n\n    typedef typename From::Node Node;\n    typedef typename From::NodeIt NodeIt;\n    typedef typename From::Edge Edge;\n    typedef typename From::EdgeIt EdgeIt;\n    typedef typename From::UEdge UEdge;\n    typedef typename From::UEdgeIt UEdgeIt;\n\n    typedef typename To::Node TNode;\n    typedef typename To::Edge TEdge;\n    typedef typename To::UEdge TUEdge;\n\n    typedef typename From::template NodeMap<TNode> NodeRefMap;\n    typedef typename From::template UEdgeMap<TUEdge> UEdgeRefMap;\n\n    struct EdgeRefMap {\n      EdgeRefMap(const To& _to, const From& _from,\n                 const UEdgeRefMap& _uedge_ref, const NodeRefMap& _node_ref) \n        : to(_to), from(_from), \n          uedge_ref(_uedge_ref), node_ref(_node_ref) {}\n\n      typedef typename From::Edge Key;\n      typedef typename To::Edge Value;\n\n      Value operator[](const Key& key) const {\n        bool forward = \n          (from.direction(key) == \n           (node_ref[from.source(static_cast<const UEdge&>(key))] == \n            to.source(uedge_ref[static_cast<const UEdge&>(key)])));\n\treturn to.direct(uedge_ref[key], forward); \n      }\n      \n      const To& to;\n      const From& from;\n      const UEdgeRefMap& uedge_ref;\n      const NodeRefMap& node_ref;\n    };\n\n    \n  public: \n\n\n    /// \\brief Constructor for the GraphCopy.\n    ///\n    /// It copies the content of the \\c _from graph into the\n    /// \\c _to graph.\n    UGraphCopy(To& _to, const From& _from) \n      : from(_from), to(_to) {}\n\n    /// \\brief Destructor of the GraphCopy\n    ///\n    /// Destructor of the GraphCopy\n    ~UGraphCopy() {\n      for (int i = 0; i < int(nodeMapCopies.size()); ++i) {\n        delete nodeMapCopies[i];\n      }\n      for (int i = 0; i < int(edgeMapCopies.size()); ++i) {\n        delete edgeMapCopies[i];\n      }\n      for (int i = 0; i < int(uEdgeMapCopies.size()); ++i) {\n        delete uEdgeMapCopies[i];\n      }\n\n    }\n\n    /// \\brief Copies the node references into the given map.\n    ///\n    /// Copies the node references into the given map.\n    template <typename NodeRef>\n    UGraphCopy& nodeRef(NodeRef& map) {\n      nodeMapCopies.push_back(new _graph_utils_bits::RefCopy<From, Node, \n                              NodeRefMap, NodeRef>(map));\n      return *this;\n    }\n\n    /// \\brief Copies the node cross references into the given map.\n    ///\n    ///  Copies the node cross references (reverse references) into\n    ///  the given map.\n    template <typename NodeCrossRef>\n    UGraphCopy& nodeCrossRef(NodeCrossRef& map) {\n      nodeMapCopies.push_back(new _graph_utils_bits::CrossRefCopy<From, Node,\n                              NodeRefMap, NodeCrossRef>(map));\n      return *this;\n    }\n\n    /// \\brief Make copy of the given map.\n    ///\n    /// Makes copy of the given map for the newly created graph. \n    /// The new map's key type is the to graph's node type,\n    /// and the copied map's key type is the from graph's node\n    /// type.  \n    template <typename ToMap, typename FromMap>\n    UGraphCopy& nodeMap(ToMap& tmap, const FromMap& map) {\n      nodeMapCopies.push_back(new _graph_utils_bits::MapCopy<From, Node, \n                              NodeRefMap, ToMap, FromMap>(tmap, map));\n      return *this;\n    }\n\n    /// \\brief Make a copy of the given node.\n    ///\n    /// Make a copy of the given node.\n    UGraphCopy& node(TNode& tnode, const Node& snode) {\n      nodeMapCopies.push_back(new _graph_utils_bits::ItemCopy<From, Node, \n                              NodeRefMap, TNode>(tnode, snode));\n      return *this;\n    }\n\n    /// \\brief Copies the edge references into the given map.\n    ///\n    /// Copies the edge references into the given map.\n    template <typename EdgeRef>\n    UGraphCopy& edgeRef(EdgeRef& map) {\n      edgeMapCopies.push_back(new _graph_utils_bits::RefCopy<From, Edge, \n                              EdgeRefMap, EdgeRef>(map));\n      return *this;\n    }\n\n    /// \\brief Copies the edge cross references into the given map.\n    ///\n    ///  Copies the edge cross references (reverse references) into\n    ///  the given map.\n    template <typename EdgeCrossRef>\n    UGraphCopy& edgeCrossRef(EdgeCrossRef& map) {\n      edgeMapCopies.push_back(new _graph_utils_bits::CrossRefCopy<From, Edge,\n                              EdgeRefMap, EdgeCrossRef>(map));\n      return *this;\n    }\n\n    /// \\brief Make copy of the given map.\n    ///\n    /// Makes copy of the given map for the newly created graph. \n    /// The new map's key type is the to graph's edge type,\n    /// and the copied map's key type is the from graph's edge\n    /// type.  \n    template <typename ToMap, typename FromMap>\n    UGraphCopy& edgeMap(ToMap& tmap, const FromMap& map) {\n      edgeMapCopies.push_back(new _graph_utils_bits::MapCopy<From, Edge, \n                              EdgeRefMap, ToMap, FromMap>(tmap, map));\n      return *this;\n    }\n\n    /// \\brief Make a copy of the given edge.\n    ///\n    /// Make a copy of the given edge.\n    UGraphCopy& edge(TEdge& tedge, const Edge& sedge) {\n      edgeMapCopies.push_back(new _graph_utils_bits::ItemCopy<From, Edge, \n                              EdgeRefMap, TEdge>(tedge, sedge));\n      return *this;\n    }\n\n    /// \\brief Copies the undirected edge references into the given map.\n    ///\n    /// Copies the undirected edge references into the given map.\n    template <typename UEdgeRef>\n    UGraphCopy& uEdgeRef(UEdgeRef& map) {\n      uEdgeMapCopies.push_back(new _graph_utils_bits::RefCopy<From, UEdge, \n                               UEdgeRefMap, UEdgeRef>(map));\n      return *this;\n    }\n\n    /// \\brief Copies the undirected edge cross references into the given map.\n    ///\n    /// Copies the undirected edge cross references (reverse\n    /// references) into the given map.\n    template <typename UEdgeCrossRef>\n    UGraphCopy& uEdgeCrossRef(UEdgeCrossRef& map) {\n      uEdgeMapCopies.push_back(new _graph_utils_bits::CrossRefCopy<From, \n                               UEdge, UEdgeRefMap, UEdgeCrossRef>(map));\n      return *this;\n    }\n\n    /// \\brief Make copy of the given map.\n    ///\n    /// Makes copy of the given map for the newly created graph. \n    /// The new map's key type is the to graph's undirected edge type,\n    /// and the copied map's key type is the from graph's undirected edge\n    /// type.  \n    template <typename ToMap, typename FromMap>\n    UGraphCopy& uEdgeMap(ToMap& tmap, const FromMap& map) {\n      uEdgeMapCopies.push_back(new _graph_utils_bits::MapCopy<From, UEdge, \n                               UEdgeRefMap, ToMap, FromMap>(tmap, map));\n      return *this;\n    }\n\n    /// \\brief Make a copy of the given undirected edge.\n    ///\n    /// Make a copy of the given undirected edge.\n    UGraphCopy& uEdge(TUEdge& tuedge, const UEdge& suedge) {\n      uEdgeMapCopies.push_back(new _graph_utils_bits::ItemCopy<From, UEdge, \n                               UEdgeRefMap, TUEdge>(tuedge, suedge));\n      return *this;\n    }\n\n    /// \\brief Executes the copies.\n    ///\n    /// Executes the copies.\n    void run() {\n      NodeRefMap nodeRefMap(from);\n      UEdgeRefMap uEdgeRefMap(from);\n      EdgeRefMap edgeRefMap(to, from, uEdgeRefMap, nodeRefMap);\n      _graph_utils_bits::UGraphCopySelector<To>::\n        copy(to, from, nodeRefMap, uEdgeRefMap);\n      for (int i = 0; i < int(nodeMapCopies.size()); ++i) {\n        nodeMapCopies[i]->copy(from, nodeRefMap);\n      }\n      for (int i = 0; i < int(uEdgeMapCopies.size()); ++i) {\n        uEdgeMapCopies[i]->copy(from, uEdgeRefMap);\n      }\n      for (int i = 0; i < int(edgeMapCopies.size()); ++i) {\n        edgeMapCopies[i]->copy(from, edgeRefMap);\n      }\n    }\n\n  private:\n    \n    const From& from;\n    To& to;\n\n    std::vector<_graph_utils_bits::MapCopyBase<From, Node, NodeRefMap>* > \n    nodeMapCopies;\n\n    std::vector<_graph_utils_bits::MapCopyBase<From, Edge, EdgeRefMap>* > \n    edgeMapCopies;\n\n    std::vector<_graph_utils_bits::MapCopyBase<From, UEdge, UEdgeRefMap>* > \n    uEdgeMapCopies;\n\n  };\n\n  /// \\brief Copy an undirected graph to another graph.\n  ///\n  /// Copy an undirected graph to another graph.\n  /// The usage of the function:\n  /// \n  ///\\code\n  /// copyUGraph(trg, src).nodeRef(nr).edgeCrossRef(ecr).run();\n  ///\\endcode\n  /// \n  /// After the copy the \\c nr map will contain the mapping from the\n  /// nodes of the \\c from graph to the nodes of the \\c to graph and\n  /// \\c ecr will contain the mapping from the edges of the \\c to graph\n  /// to the edges of the \\c from graph.\n  ///\n  /// \\see UGraphCopy \n  template <typename To, typename From>\n  UGraphCopy<To, From> \n  copyUGraph(To& to, const From& from) {\n    return UGraphCopy<To, From>(to, from);\n  }\n\n  /// \\brief Class to copy a bipartite undirected graph.\n  ///\n  /// Class to copy a bipartite undirected graph to another graph\n  /// (duplicate a graph).  The simplest way of using it is through\n  /// the \\c copyBpUGraph() function.\n  template <typename To, typename From>\n  class BpUGraphCopy {\n  private:\n\n    typedef typename From::Node Node;\n    typedef typename From::ANode ANode;\n    typedef typename From::BNode BNode;\n    typedef typename From::NodeIt NodeIt;\n    typedef typename From::Edge Edge;\n    typedef typename From::EdgeIt EdgeIt;\n    typedef typename From::UEdge UEdge;\n    typedef typename From::UEdgeIt UEdgeIt;\n\n    typedef typename To::Node TNode;\n    typedef typename To::Edge TEdge;\n    typedef typename To::UEdge TUEdge;\n\n    typedef typename From::template ANodeMap<TNode> ANodeRefMap;\n    typedef typename From::template BNodeMap<TNode> BNodeRefMap;\n    typedef typename From::template UEdgeMap<TUEdge> UEdgeRefMap;\n\n    struct NodeRefMap {\n      NodeRefMap(const From& _from, const ANodeRefMap& _anode_ref,\n                 const BNodeRefMap& _bnode_ref)\n        : from(_from), anode_ref(_anode_ref), bnode_ref(_bnode_ref) {}\n\n      typedef typename From::Node Key;\n      typedef typename To::Node Value;\n\n      Value operator[](const Key& key) const {\n\treturn from.aNode(key) ? anode_ref[key] : bnode_ref[key]; \n      }\n      \n      const From& from;\n      const ANodeRefMap& anode_ref;\n      const BNodeRefMap& bnode_ref;\n    };\n\n    struct EdgeRefMap {\n      EdgeRefMap(const To& _to, const From& _from,\n                 const UEdgeRefMap& _uedge_ref, const NodeRefMap& _node_ref) \n        : to(_to), from(_from), \n          uedge_ref(_uedge_ref), node_ref(_node_ref) {}\n\n      typedef typename From::Edge Key;\n      typedef typename To::Edge Value;\n\n      Value operator[](const Key& key) const {\n        bool forward = \n          (from.direction(key) == \n           (node_ref[from.source(static_cast<const UEdge&>(key))] == \n            to.source(uedge_ref[static_cast<const UEdge&>(key)])));\n\treturn to.direct(uedge_ref[key], forward); \n      }\n      \n      const To& to;\n      const From& from;\n      const UEdgeRefMap& uedge_ref;\n      const NodeRefMap& node_ref;\n    };\n    \n  public: \n\n\n    /// \\brief Constructor for the GraphCopy.\n    ///\n    /// It copies the content of the \\c _from graph into the\n    /// \\c _to graph.\n    BpUGraphCopy(To& _to, const From& _from) \n      : from(_from), to(_to) {}\n\n    /// \\brief Destructor of the GraphCopy\n    ///\n    /// Destructor of the GraphCopy\n    ~BpUGraphCopy() {\n      for (int i = 0; i < int(aNodeMapCopies.size()); ++i) {\n        delete aNodeMapCopies[i];\n      }\n      for (int i = 0; i < int(bNodeMapCopies.size()); ++i) {\n        delete bNodeMapCopies[i];\n      }\n      for (int i = 0; i < int(nodeMapCopies.size()); ++i) {\n        delete nodeMapCopies[i];\n      }\n      for (int i = 0; i < int(edgeMapCopies.size()); ++i) {\n        delete edgeMapCopies[i];\n      }\n      for (int i = 0; i < int(uEdgeMapCopies.size()); ++i) {\n        delete uEdgeMapCopies[i];\n      }\n\n    }\n\n    /// \\brief Copies the A-node references into the given map.\n    ///\n    /// Copies the A-node references into the given map.\n    template <typename ANodeRef>\n    BpUGraphCopy& aNodeRef(ANodeRef& map) {\n      aNodeMapCopies.push_back(new _graph_utils_bits::RefCopy<From, ANode, \n                               ANodeRefMap, ANodeRef>(map));\n      return *this;\n    }\n\n    /// \\brief Copies the A-node cross references into the given map.\n    ///\n    /// Copies the A-node cross references (reverse references) into\n    /// the given map.\n    template <typename ANodeCrossRef>\n    BpUGraphCopy& aNodeCrossRef(ANodeCrossRef& map) {\n      aNodeMapCopies.push_back(new _graph_utils_bits::CrossRefCopy<From, \n                               ANode, ANodeRefMap, ANodeCrossRef>(map));\n      return *this;\n    }\n\n    /// \\brief Make copy of the given A-node map.\n    ///\n    /// Makes copy of the given map for the newly created graph. \n    /// The new map's key type is the to graph's node type,\n    /// and the copied map's key type is the from graph's node\n    /// type.  \n    template <typename ToMap, typename FromMap>\n    BpUGraphCopy& aNodeMap(ToMap& tmap, const FromMap& map) {\n      aNodeMapCopies.push_back(new _graph_utils_bits::MapCopy<From, ANode, \n                               ANodeRefMap, ToMap, FromMap>(tmap, map));\n      return *this;\n    }\n\n    /// \\brief Copies the B-node references into the given map.\n    ///\n    /// Copies the B-node references into the given map.\n    template <typename BNodeRef>\n    BpUGraphCopy& bNodeRef(BNodeRef& map) {\n      bNodeMapCopies.push_back(new _graph_utils_bits::RefCopy<From, BNode, \n                               BNodeRefMap, BNodeRef>(map));\n      return *this;\n    }\n\n    /// \\brief Copies the B-node cross references into the given map.\n    ///\n    ///  Copies the B-node cross references (reverse references) into\n    ///  the given map.\n    template <typename BNodeCrossRef>\n    BpUGraphCopy& bNodeCrossRef(BNodeCrossRef& map) {\n      bNodeMapCopies.push_back(new _graph_utils_bits::CrossRefCopy<From, \n                              BNode, BNodeRefMap, BNodeCrossRef>(map));\n      return *this;\n    }\n\n    /// \\brief Make copy of the given B-node map.\n    ///\n    /// Makes copy of the given map for the newly created graph. \n    /// The new map's key type is the to graph's node type,\n    /// and the copied map's key type is the from graph's node\n    /// type.  \n    template <typename ToMap, typename FromMap>\n    BpUGraphCopy& bNodeMap(ToMap& tmap, const FromMap& map) {\n      bNodeMapCopies.push_back(new _graph_utils_bits::MapCopy<From, BNode, \n                               BNodeRefMap, ToMap, FromMap>(tmap, map));\n      return *this;\n    }\n    /// \\brief Copies the node references into the given map.\n    ///\n    /// Copies the node references into the given map.\n    template <typename NodeRef>\n    BpUGraphCopy& nodeRef(NodeRef& map) {\n      nodeMapCopies.push_back(new _graph_utils_bits::RefCopy<From, Node, \n                              NodeRefMap, NodeRef>(map));\n      return *this;\n    }\n\n    /// \\brief Copies the node cross references into the given map.\n    ///\n    ///  Copies the node cross references (reverse references) into\n    ///  the given map.\n    template <typename NodeCrossRef>\n    BpUGraphCopy& nodeCrossRef(NodeCrossRef& map) {\n      nodeMapCopies.push_back(new _graph_utils_bits::CrossRefCopy<From, Node,\n                              NodeRefMap, NodeCrossRef>(map));\n      return *this;\n    }\n\n    /// \\brief Make copy of the given map.\n    ///\n    /// Makes copy of the given map for the newly created graph. \n    /// The new map's key type is the to graph's node type,\n    /// and the copied map's key type is the from graph's node\n    /// type.  \n    template <typename ToMap, typename FromMap>\n    BpUGraphCopy& nodeMap(ToMap& tmap, const FromMap& map) {\n      nodeMapCopies.push_back(new _graph_utils_bits::MapCopy<From, Node, \n                              NodeRefMap, ToMap, FromMap>(tmap, map));\n      return *this;\n    }\n\n    /// \\brief Make a copy of the given node.\n    ///\n    /// Make a copy of the given node.\n    BpUGraphCopy& node(TNode& tnode, const Node& snode) {\n      nodeMapCopies.push_back(new _graph_utils_bits::ItemCopy<From, Node, \n                              NodeRefMap, TNode>(tnode, snode));\n      return *this;\n    }\n\n    /// \\brief Copies the edge references into the given map.\n    ///\n    /// Copies the edge references into the given map.\n    template <typename EdgeRef>\n    BpUGraphCopy& edgeRef(EdgeRef& map) {\n      edgeMapCopies.push_back(new _graph_utils_bits::RefCopy<From, Edge, \n                              EdgeRefMap, EdgeRef>(map));\n      return *this;\n    }\n\n    /// \\brief Copies the edge cross references into the given map.\n    ///\n    ///  Copies the edge cross references (reverse references) into\n    ///  the given map.\n    template <typename EdgeCrossRef>\n    BpUGraphCopy& edgeCrossRef(EdgeCrossRef& map) {\n      edgeMapCopies.push_back(new _graph_utils_bits::CrossRefCopy<From, Edge,\n                              EdgeRefMap, EdgeCrossRef>(map));\n      return *this;\n    }\n\n    /// \\brief Make copy of the given map.\n    ///\n    /// Makes copy of the given map for the newly created graph. \n    /// The new map's key type is the to graph's edge type,\n    /// and the copied map's key type is the from graph's edge\n    /// type.  \n    template <typename ToMap, typename FromMap>\n    BpUGraphCopy& edgeMap(ToMap& tmap, const FromMap& map) {\n      edgeMapCopies.push_back(new _graph_utils_bits::MapCopy<From, Edge, \n                              EdgeRefMap, ToMap, FromMap>(tmap, map));\n      return *this;\n    }\n\n    /// \\brief Make a copy of the given edge.\n    ///\n    /// Make a copy of the given edge.\n    BpUGraphCopy& edge(TEdge& tedge, const Edge& sedge) {\n      edgeMapCopies.push_back(new _graph_utils_bits::ItemCopy<From, Edge, \n                              EdgeRefMap, TEdge>(tedge, sedge));\n      return *this;\n    }\n\n    /// \\brief Copies the undirected edge references into the given map.\n    ///\n    /// Copies the undirected edge references into the given map.\n    template <typename UEdgeRef>\n    BpUGraphCopy& uEdgeRef(UEdgeRef& map) {\n      uEdgeMapCopies.push_back(new _graph_utils_bits::RefCopy<From, UEdge, \n                               UEdgeRefMap, UEdgeRef>(map));\n      return *this;\n    }\n\n    /// \\brief Copies the undirected edge cross references into the given map.\n    ///\n    /// Copies the undirected edge cross references (reverse\n    /// references) into the given map.\n    template <typename UEdgeCrossRef>\n    BpUGraphCopy& uEdgeCrossRef(UEdgeCrossRef& map) {\n      uEdgeMapCopies.push_back(new _graph_utils_bits::CrossRefCopy<From, \n                               UEdge, UEdgeRefMap, UEdgeCrossRef>(map));\n      return *this;\n    }\n\n    /// \\brief Make copy of the given map.\n    ///\n    /// Makes copy of the given map for the newly created graph. \n    /// The new map's key type is the to graph's undirected edge type,\n    /// and the copied map's key type is the from graph's undirected edge\n    /// type.  \n    template <typename ToMap, typename FromMap>\n    BpUGraphCopy& uEdgeMap(ToMap& tmap, const FromMap& map) {\n      uEdgeMapCopies.push_back(new _graph_utils_bits::MapCopy<From, UEdge, \n                               UEdgeRefMap, ToMap, FromMap>(tmap, map));\n      return *this;\n    }\n\n    /// \\brief Make a copy of the given undirected edge.\n    ///\n    /// Make a copy of the given undirected edge.\n    BpUGraphCopy& uEdge(TUEdge& tuedge, const UEdge& suedge) {\n      uEdgeMapCopies.push_back(new _graph_utils_bits::ItemCopy<From, UEdge, \n                               UEdgeRefMap, TUEdge>(tuedge, suedge));\n      return *this;\n    }\n\n    /// \\brief Executes the copies.\n    ///\n    /// Executes the copies.\n    void run() {\n      ANodeRefMap aNodeRefMap(from);\n      BNodeRefMap bNodeRefMap(from);\n      NodeRefMap nodeRefMap(from, aNodeRefMap, bNodeRefMap);\n      UEdgeRefMap uEdgeRefMap(from);\n      EdgeRefMap edgeRefMap(to, from, uEdgeRefMap, nodeRefMap);\n      _graph_utils_bits::BpUGraphCopySelector<To>::\n        copy(to, from, aNodeRefMap, bNodeRefMap, uEdgeRefMap);\n      for (int i = 0; i < int(aNodeMapCopies.size()); ++i) {\n        aNodeMapCopies[i]->copy(from, aNodeRefMap);\n      }\n      for (int i = 0; i < int(bNodeMapCopies.size()); ++i) {\n        bNodeMapCopies[i]->copy(from, bNodeRefMap);\n      }\n      for (int i = 0; i < int(nodeMapCopies.size()); ++i) {\n        nodeMapCopies[i]->copy(from, nodeRefMap);\n      }\n      for (int i = 0; i < int(uEdgeMapCopies.size()); ++i) {\n        uEdgeMapCopies[i]->copy(from, uEdgeRefMap);\n      }\n      for (int i = 0; i < int(edgeMapCopies.size()); ++i) {\n        edgeMapCopies[i]->copy(from, edgeRefMap);\n      }\n    }\n\n  private:\n    \n    const From& from;\n    To& to;\n\n    std::vector<_graph_utils_bits::MapCopyBase<From, ANode, ANodeRefMap>* > \n    aNodeMapCopies;\n\n    std::vector<_graph_utils_bits::MapCopyBase<From, BNode, BNodeRefMap>* > \n    bNodeMapCopies;\n\n    std::vector<_graph_utils_bits::MapCopyBase<From, Node, NodeRefMap>* > \n    nodeMapCopies;\n\n    std::vector<_graph_utils_bits::MapCopyBase<From, Edge, EdgeRefMap>* > \n    edgeMapCopies;\n\n    std::vector<_graph_utils_bits::MapCopyBase<From, UEdge, UEdgeRefMap>* > \n    uEdgeMapCopies;\n\n  };\n\n  /// \\brief Copy a bipartite undirected graph to another graph.\n  ///\n  /// Copy a bipartite undirected graph to another graph.\n  /// The usage of the function:\n  /// \n  ///\\code\n  /// copyBpUGraph(trg, src).aNodeRef(anr).edgeCrossRef(ecr).run();\n  ///\\endcode\n  /// \n  /// After the copy the \\c nr map will contain the mapping from the\n  /// nodes of the \\c from graph to the nodes of the \\c to graph and\n  /// \\c ecr will contain the mapping from the edges of the \\c to graph\n  /// to the edges of the \\c from graph.\n  ///\n  /// \\see BpUGraphCopy\n  template <typename To, typename From>\n  BpUGraphCopy<To, From> \n  copyBpUGraph(To& to, const From& from) {\n    return BpUGraphCopy<To, From>(to, from);\n  }\n\n\n  /// @}\n\n  /// \\addtogroup graph_maps\n  /// @{\n\n  /// Provides an immutable and unique id for each item in the graph.\n\n  /// The IdMap class provides a unique and immutable id for each item of the\n  /// same type (e.g. node) in the graph. This id is <ul><li>\\b unique:\n  /// different items (nodes) get different ids <li>\\b immutable: the id of an\n  /// item (node) does not change (even if you delete other nodes).  </ul>\n  /// Through this map you get access (i.e. can read) the inner id values of\n  /// the items stored in the graph. This map can be inverted with its member\n  /// class \\c InverseMap.\n  ///\n  template <typename _Graph, typename _Item>\n  class IdMap {\n  public:\n    typedef _Graph Graph;\n    typedef int Value;\n    typedef _Item Item;\n    typedef _Item Key;\n\n    /// \\brief Constructor.\n    ///\n    /// Constructor of the map.\n    explicit IdMap(const Graph& _graph) : graph(&_graph) {}\n\n    /// \\brief Gives back the \\e id of the item.\n    ///\n    /// Gives back the immutable and unique \\e id of the item.\n    int operator[](const Item& item) const { return graph->id(item);}\n\n    /// \\brief Gives back the item by its id.\n    ///\n    /// Gives back the item by its id.\n    Item operator()(int id) { return graph->fromId(id, Item()); }\n\n  private:\n    const Graph* graph;\n\n  public:\n\n    /// \\brief The class represents the inverse of its owner (IdMap).\n    ///\n    /// The class represents the inverse of its owner (IdMap).\n    /// \\see inverse()\n    class InverseMap {\n    public:\n\n      /// \\brief Constructor.\n      ///\n      /// Constructor for creating an id-to-item map.\n      explicit InverseMap(const Graph& _graph) : graph(&_graph) {}\n\n      /// \\brief Constructor.\n      ///\n      /// Constructor for creating an id-to-item map.\n      explicit InverseMap(const IdMap& idMap) : graph(idMap.graph) {}\n\n      /// \\brief Gives back the given item from its id.\n      ///\n      /// Gives back the given item from its id.\n      /// \n      Item operator[](int id) const { return graph->fromId(id, Item());}\n\n    private:\n      const Graph* graph;\n    };\n\n    /// \\brief Gives back the inverse of the map.\n    ///\n    /// Gives back the inverse of the IdMap.\n    InverseMap inverse() const { return InverseMap(*graph);} \n\n  };\n\n  \n  /// \\brief General invertable graph-map type.\n\n  /// This type provides simple invertable graph-maps. \n  /// The InvertableMap wraps an arbitrary ReadWriteMap \n  /// and if a key is set to a new value then store it\n  /// in the inverse map.\n  ///\n  /// The values of the map can be accessed\n  /// with stl compatible forward iterator.\n  ///\n  /// \\param _Graph The graph type.\n  /// \\param _Item The item type of the graph.\n  /// \\param _Value The value type of the map.\n  ///\n  /// \\see IterableValueMap\n  template <typename _Graph, typename _Item, typename _Value>\n  class InvertableMap : protected DefaultMap<_Graph, _Item, _Value> {\n  private:\n    \n    typedef DefaultMap<_Graph, _Item, _Value> Map;\n    typedef _Graph Graph;\n\n    typedef std::map<_Value, _Item> Container;\n    Container invMap;    \n\n  public:\n \n    /// The key type of InvertableMap (Node, Edge, UEdge).\n    typedef typename Map::Key Key;\n    /// The value type of the InvertableMap.\n    typedef typename Map::Value Value;\n\n\n\n    /// \\brief Constructor.\n    ///\n    /// Construct a new InvertableMap for the graph.\n    ///\n    explicit InvertableMap(const Graph& graph) : Map(graph) {} \n\n    /// \\brief Forward iterator for values.\n    ///\n    /// This iterator is an stl compatible forward\n    /// iterator on the values of the map. The values can\n    /// be accessed in the [beginValue, endValue) range.\n    ///\n    class ValueIterator \n      : public std::iterator<std::forward_iterator_tag, Value> {\n      friend class InvertableMap;\n    private:\n      ValueIterator(typename Container::const_iterator _it) \n        : it(_it) {}\n    public:\n      \n      ValueIterator() {}\n\n      ValueIterator& operator++() { ++it; return *this; }\n      ValueIterator operator++(int) { \n        ValueIterator tmp(*this); \n        operator++();\n        return tmp; \n      }\n\n      const Value& operator*() const { return it->first; }\n      const Value* operator->() const { return &(it->first); }\n\n      bool operator==(ValueIterator jt) const { return it == jt.it; }\n      bool operator!=(ValueIterator jt) const { return it != jt.it; }\n      \n    private:\n      typename Container::const_iterator it;\n    };\n\n    /// \\brief Returns an iterator to the first value.\n    ///\n    /// Returns an stl compatible iterator to the \n    /// first value of the map. The values of the\n    /// map can be accessed in the [beginValue, endValue)\n    /// range.\n    ValueIterator beginValue() const {\n      return ValueIterator(invMap.begin());\n    }\n\n    /// \\brief Returns an iterator after the last value.\n    ///\n    /// Returns an stl compatible iterator after the \n    /// last value of the map. The values of the\n    /// map can be accessed in the [beginValue, endValue)\n    /// range.\n    ValueIterator endValue() const {\n      return ValueIterator(invMap.end());\n    }\n    \n    /// \\brief The setter function of the map.\n    ///\n    /// Sets the mapped value.\n    void set(const Key& key, const Value& val) {\n      Value oldval = Map::operator[](key);\n      typename Container::iterator it = invMap.find(oldval);\n      if (it != invMap.end() && it->second == key) {\n\tinvMap.erase(it);\n      }      \n      invMap.insert(make_pair(val, key));\n      Map::set(key, val);\n    }\n\n    /// \\brief The getter function of the map.\n    ///\n    /// It gives back the value associated with the key.\n    typename MapTraits<Map>::ConstReturnValue \n    operator[](const Key& key) const {\n      return Map::operator[](key);\n    }\n\n    /// \\brief Gives back the item by its value.\n    ///\n    /// Gives back the item by its value.\n    Key operator()(const Value& key) const {\n      typename Container::const_iterator it = invMap.find(key);\n      return it != invMap.end() ? it->second : INVALID;\n    }\n\n  protected:\n\n    /// \\brief Erase the key from the map.\n    ///\n    /// Erase the key to the map. It is called by the\n    /// \\c AlterationNotifier.\n    virtual void erase(const Key& key) {\n      Value val = Map::operator[](key);\n      typename Container::iterator it = invMap.find(val);\n      if (it != invMap.end() && it->second == key) {\n\tinvMap.erase(it);\n      }\n      Map::erase(key);\n    }\n\n    /// \\brief Erase more keys from the map.\n    ///\n    /// Erase more keys from the map. It is called by the\n    /// \\c AlterationNotifier.\n    virtual void erase(const std::vector<Key>& keys) {\n      for (int i = 0; i < int(keys.size()); ++i) {\n\tValue val = Map::operator[](keys[i]);\n\ttypename Container::iterator it = invMap.find(val);\n\tif (it != invMap.end() && it->second == keys[i]) {\n\t  invMap.erase(it);\n\t}\n      }\n      Map::erase(keys);\n    }\n\n    /// \\brief Clear the keys from the map and inverse map.\n    ///\n    /// Clear the keys from the map and inverse map. It is called by the\n    /// \\c AlterationNotifier.\n    virtual void clear() {\n      invMap.clear();\n      Map::clear();\n    }\n\n  public:\n\n    /// \\brief The inverse map type.\n    ///\n    /// The inverse of this map. The subscript operator of the map\n    /// gives back always the item what was last assigned to the value. \n    class InverseMap {\n    public:\n      /// \\brief Constructor of the InverseMap.\n      ///\n      /// Constructor of the InverseMap.\n      explicit InverseMap(const InvertableMap& _inverted) \n        : inverted(_inverted) {}\n\n      /// The value type of the InverseMap.\n      typedef typename InvertableMap::Key Value;\n      /// The key type of the InverseMap.\n      typedef typename InvertableMap::Value Key; \n\n      /// \\brief Subscript operator. \n      ///\n      /// Subscript operator. It gives back always the item \n      /// what was last assigned to the value.\n      Value operator[](const Key& key) const {\n\treturn inverted(key);\n      }\n      \n    private:\n      const InvertableMap& inverted;\n    };\n\n    /// \\brief It gives back the just readable inverse map.\n    ///\n    /// It gives back the just readable inverse map.\n    InverseMap inverse() const {\n      return InverseMap(*this);\n    } \n\n\n    \n  };\n\n  /// \\brief Provides a mutable, continuous and unique descriptor for each \n  /// item in the graph.\n  ///\n  /// The DescriptorMap class provides a unique and continuous (but mutable)\n  /// descriptor (id) for each item of the same type (e.g. node) in the\n  /// graph. This id is <ul><li>\\b unique: different items (nodes) get\n  /// different ids <li>\\b continuous: the range of the ids is the set of\n  /// integers between 0 and \\c n-1, where \\c n is the number of the items of\n  /// this type (e.g. nodes) (so the id of a node can change if you delete an\n  /// other node, i.e. this id is mutable).  </ul> This map can be inverted\n  /// with its member class \\c InverseMap.\n  ///\n  /// \\param _Graph The graph class the \\c DescriptorMap belongs to.\n  /// \\param _Item The Item is the Key of the Map. It may be Node, Edge or \n  /// UEdge.\n  template <typename _Graph, typename _Item>\n  class DescriptorMap : protected DefaultMap<_Graph, _Item, int> {\n\n    typedef _Item Item;\n    typedef DefaultMap<_Graph, _Item, int> Map;\n\n  public:\n    /// The graph class of DescriptorMap.\n    typedef _Graph Graph;\n\n    /// The key type of DescriptorMap (Node, Edge, UEdge).\n    typedef typename Map::Key Key;\n    /// The value type of DescriptorMap.\n    typedef typename Map::Value Value;\n\n    /// \\brief Constructor.\n    ///\n    /// Constructor for descriptor map.\n    explicit DescriptorMap(const Graph& _graph) : Map(_graph) {\n      Item it;\n      const typename Map::Notifier* nf = Map::notifier(); \n      for (nf->first(it); it != INVALID; nf->next(it)) {\n\tMap::set(it, invMap.size());\n\tinvMap.push_back(it);\t\n      }      \n    }\n\n  protected:\n\n    /// \\brief Add a new key to the map.\n    ///\n    /// Add a new key to the map. It is called by the\n    /// \\c AlterationNotifier.\n    virtual void add(const Item& item) {\n      Map::add(item);\n      Map::set(item, invMap.size());\n      invMap.push_back(item);\n    }\n\n    /// \\brief Add more new keys to the map.\n    ///\n    /// Add more new keys to the map. It is called by the\n    /// \\c AlterationNotifier.\n    virtual void add(const std::vector<Item>& items) {\n      Map::add(items);\n      for (int i = 0; i < int(items.size()); ++i) {\n\tMap::set(items[i], invMap.size());\n\tinvMap.push_back(items[i]);\n      }\n    }\n\n    /// \\brief Erase the key from the map.\n    ///\n    /// Erase the key from the map. It is called by the\n    /// \\c AlterationNotifier.\n    virtual void erase(const Item& item) {\n      Map::set(invMap.back(), Map::operator[](item));\n      invMap[Map::operator[](item)] = invMap.back();\n      invMap.pop_back();\n      Map::erase(item);\n    }\n\n    /// \\brief Erase more keys from the map.\n    ///\n    /// Erase more keys from the map. It is called by the\n    /// \\c AlterationNotifier.\n    virtual void erase(const std::vector<Item>& items) {\n      for (int i = 0; i < int(items.size()); ++i) {\n\tMap::set(invMap.back(), Map::operator[](items[i]));\n\tinvMap[Map::operator[](items[i])] = invMap.back();\n\tinvMap.pop_back();\n      }\n      Map::erase(items);\n    }\n\n    /// \\brief Build the unique map.\n    ///\n    /// Build the unique map. It is called by the\n    /// \\c AlterationNotifier.\n    virtual void build() {\n      Map::build();\n      Item it;\n      const typename Map::Notifier* nf = Map::notifier(); \n      for (nf->first(it); it != INVALID; nf->next(it)) {\n\tMap::set(it, invMap.size());\n\tinvMap.push_back(it);\t\n      }      \n    }\n    \n    /// \\brief Clear the keys from the map.\n    ///\n    /// Clear the keys from the map. It is called by the\n    /// \\c AlterationNotifier.\n    virtual void clear() {\n      invMap.clear();\n      Map::clear();\n    }\n\n  public:\n\n    /// \\brief Returns the maximal value plus one.\n    ///\n    /// Returns the maximal value plus one in the map.\n    unsigned int size() const {\n      return invMap.size();\n    }\n\n    /// \\brief Swaps the position of the two items in the map.\n    ///\n    /// Swaps the position of the two items in the map.\n    void swap(const Item& p, const Item& q) {\n      int pi = Map::operator[](p);\n      int qi = Map::operator[](q);\n      Map::set(p, qi);\n      invMap[qi] = p;\n      Map::set(q, pi);\n      invMap[pi] = q;\n    }\n\n    /// \\brief Gives back the \\e descriptor of the item.\n    ///\n    /// Gives back the mutable and unique \\e descriptor of the map.\n    int operator[](const Item& item) const {\n      return Map::operator[](item);\n    }\n\n    /// \\brief Gives back the item by its descriptor.\n    ///\n    /// Gives back th item by its descriptor.\n    Item operator()(int id) const {\n      return invMap[id];\n    }\n    \n  private:\n\n    typedef std::vector<Item> Container;\n    Container invMap;\n\n  public:\n    /// \\brief The inverse map type of DescriptorMap.\n    ///\n    /// The inverse map type of DescriptorMap.\n    class InverseMap {\n    public:\n      /// \\brief Constructor of the InverseMap.\n      ///\n      /// Constructor of the InverseMap.\n      explicit InverseMap(const DescriptorMap& _inverted) \n\t: inverted(_inverted) {}\n\n\n      /// The value type of the InverseMap.\n      typedef typename DescriptorMap::Key Value;\n      /// The key type of the InverseMap.\n      typedef typename DescriptorMap::Value Key; \n\n      /// \\brief Subscript operator. \n      ///\n      /// Subscript operator. It gives back the item \n      /// that the descriptor belongs to currently.\n      Value operator[](const Key& key) const {\n\treturn inverted(key);\n      }\n\n      /// \\brief Size of the map.\n      ///\n      /// Returns the size of the map.\n      unsigned int size() const {\n\treturn inverted.size();\n      }\n      \n    private:\n      const DescriptorMap& inverted;\n    };\n\n    /// \\brief Gives back the inverse of the map.\n    ///\n    /// Gives back the inverse of the map.\n    const InverseMap inverse() const {\n      return InverseMap(*this);\n    }\n  };\n\n  /// \\brief Returns the source of the given edge.\n  ///\n  /// The SourceMap gives back the source Node of the given edge. \n  /// \\see TargetMap\n  /// \\author Balazs Dezso\n  template <typename Graph>\n  class SourceMap {\n  public:\n\n    typedef typename Graph::Node Value;\n    typedef typename Graph::Edge Key;\n\n    /// \\brief Constructor\n    ///\n    /// Constructor\n    /// \\param _graph The graph that the map belongs to.\n    explicit SourceMap(const Graph& _graph) : graph(_graph) {}\n\n    /// \\brief The subscript operator.\n    ///\n    /// The subscript operator.\n    /// \\param edge The edge \n    /// \\return The source of the edge \n    Value operator[](const Key& edge) const {\n      return graph.source(edge);\n    }\n\n  private:\n    const Graph& graph;\n  };\n\n  /// \\brief Returns a \\ref SourceMap class.\n  ///\n  /// This function just returns an \\ref SourceMap class.\n  /// \\relates SourceMap\n  template <typename Graph>\n  inline SourceMap<Graph> sourceMap(const Graph& graph) {\n    return SourceMap<Graph>(graph);\n  } \n\n  /// \\brief Returns the target of the given edge.\n  ///\n  /// The TargetMap gives back the target Node of the given edge. \n  /// \\see SourceMap\n  /// \\author Balazs Dezso\n  template <typename Graph>\n  class TargetMap {\n  public:\n\n    typedef typename Graph::Node Value;\n    typedef typename Graph::Edge Key;\n\n    /// \\brief Constructor\n    ///\n    /// Constructor\n    /// \\param _graph The graph that the map belongs to.\n    explicit TargetMap(const Graph& _graph) : graph(_graph) {}\n\n    /// \\brief The subscript operator.\n    ///\n    /// The subscript operator.\n    /// \\param e The edge \n    /// \\return The target of the edge \n    Value operator[](const Key& e) const {\n      return graph.target(e);\n    }\n\n  private:\n    const Graph& graph;\n  };\n\n  /// \\brief Returns a \\ref TargetMap class.\n  ///\n  /// This function just returns a \\ref TargetMap class.\n  /// \\relates TargetMap\n  template <typename Graph>\n  inline TargetMap<Graph> targetMap(const Graph& graph) {\n    return TargetMap<Graph>(graph);\n  }\n\n  /// \\brief Returns the \"forward\" directed edge view of an undirected edge.\n  ///\n  /// Returns the \"forward\" directed edge view of an undirected edge.\n  /// \\see BackwardMap\n  /// \\author Balazs Dezso\n  template <typename Graph>\n  class ForwardMap {\n  public:\n\n    typedef typename Graph::Edge Value;\n    typedef typename Graph::UEdge Key;\n\n    /// \\brief Constructor\n    ///\n    /// Constructor\n    /// \\param _graph The graph that the map belongs to.\n    explicit ForwardMap(const Graph& _graph) : graph(_graph) {}\n\n    /// \\brief The subscript operator.\n    ///\n    /// The subscript operator.\n    /// \\param key An undirected edge \n    /// \\return The \"forward\" directed edge view of undirected edge \n    Value operator[](const Key& key) const {\n      return graph.direct(key, true);\n    }\n\n  private:\n    const Graph& graph;\n  };\n\n  /// \\brief Returns a \\ref ForwardMap class.\n  ///\n  /// This function just returns an \\ref ForwardMap class.\n  /// \\relates ForwardMap\n  template <typename Graph>\n  inline ForwardMap<Graph> forwardMap(const Graph& graph) {\n    return ForwardMap<Graph>(graph);\n  }\n\n  /// \\brief Returns the \"backward\" directed edge view of an undirected edge.\n  ///\n  /// Returns the \"backward\" directed edge view of an undirected edge.\n  /// \\see ForwardMap\n  /// \\author Balazs Dezso\n  template <typename Graph>\n  class BackwardMap {\n  public:\n\n    typedef typename Graph::Edge Value;\n    typedef typename Graph::UEdge Key;\n\n    /// \\brief Constructor\n    ///\n    /// Constructor\n    /// \\param _graph The graph that the map belongs to.\n    explicit BackwardMap(const Graph& _graph) : graph(_graph) {}\n\n    /// \\brief The subscript operator.\n    ///\n    /// The subscript operator.\n    /// \\param key An undirected edge \n    /// \\return The \"backward\" directed edge view of undirected edge \n    Value operator[](const Key& key) const {\n      return graph.direct(key, false);\n    }\n\n  private:\n    const Graph& graph;\n  };\n\n  /// \\brief Returns a \\ref BackwardMap class\n\n  /// This function just returns a \\ref BackwardMap class.\n  /// \\relates BackwardMap\n  template <typename Graph>\n  inline BackwardMap<Graph> backwardMap(const Graph& graph) {\n    return BackwardMap<Graph>(graph);\n  }\n\n  /// \\brief Potential difference map\n  ///\n  /// If there is an potential map on the nodes then we\n  /// can get an edge map as we get the substraction of the\n  /// values of the target and source.\n  template <typename Graph, typename NodeMap>\n  class PotentialDifferenceMap {\n  public:\n    typedef typename Graph::Edge Key;\n    typedef typename NodeMap::Value Value;\n\n    /// \\brief Constructor\n    ///\n    /// Contructor of the map\n    explicit PotentialDifferenceMap(const Graph& _graph, \n                                    const NodeMap& _potential) \n      : graph(_graph), potential(_potential) {}\n\n    /// \\brief Const subscription operator\n    ///\n    /// Const subscription operator\n    Value operator[](const Key& edge) const {\n      return potential[graph.target(edge)] - potential[graph.source(edge)];\n    }\n\n  private:\n    const Graph& graph;\n    const NodeMap& potential;\n  };\n\n  /// \\brief Returns a PotentialDifferenceMap.\n  ///\n  /// This function just returns a PotentialDifferenceMap.\n  /// \\relates PotentialDifferenceMap\n  template <typename Graph, typename NodeMap>\n  PotentialDifferenceMap<Graph, NodeMap> \n  potentialDifferenceMap(const Graph& graph, const NodeMap& potential) {\n    return PotentialDifferenceMap<Graph, NodeMap>(graph, potential);\n  }\n\n  /// \\brief Map of the node in-degrees.\n  ///\n  /// This map returns the in-degree of a node. Once it is constructed,\n  /// the degrees are stored in a standard NodeMap, so each query is done\n  /// in constant time. On the other hand, the values are updated automatically\n  /// whenever the graph changes.\n  ///\n  /// \\warning Besides addNode() and addEdge(), a graph structure may provide\n  /// alternative ways to modify the graph. The correct behavior of InDegMap\n  /// is not guarantied if these additional features are used. For example\n  /// the functions \\ref ListGraph::changeSource() \"changeSource()\",\n  /// \\ref ListGraph::changeTarget() \"changeTarget()\" and\n  /// \\ref ListGraph::reverseEdge() \"reverseEdge()\"\n  /// of \\ref ListGraph will \\e not update the degree values correctly.\n  ///\n  /// \\sa OutDegMap\n\n  template <typename _Graph>\n  class InDegMap  \n    : protected ItemSetTraits<_Graph, typename _Graph::Edge>\n      ::ItemNotifier::ObserverBase {\n\n  public:\n    \n    typedef _Graph Graph;\n    typedef int Value;\n    typedef typename Graph::Node Key;\n\n    typedef typename ItemSetTraits<_Graph, typename _Graph::Edge>\n    ::ItemNotifier::ObserverBase Parent;\n\n  private:\n\n    class AutoNodeMap : public DefaultMap<_Graph, Key, int> {\n    public:\n\n      typedef DefaultMap<_Graph, Key, int> Parent;\n      typedef typename Parent::Graph Graph;\n\n      AutoNodeMap(const Graph& graph) : Parent(graph, 0) {}\n      \n      virtual void add(const Key& key) {\n\tParent::add(key);\n\tParent::set(key, 0);\n      }\n\n      virtual void add(const std::vector<Key>& keys) {\n\tParent::add(keys);\n\tfor (int i = 0; i < int(keys.size()); ++i) {\n\t  Parent::set(keys[i], 0);\n\t}\n      }\n\n      virtual void build() {\n\tParent::build();\n\tKey it;\n\ttypename Parent::Notifier* nf = Parent::notifier();\n\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t  Parent::set(it, 0);\n\t}\n      }\n    };\n\n  public:\n\n    /// \\brief Constructor.\n    ///\n    /// Constructor for creating in-degree map.\n    explicit InDegMap(const Graph& _graph) : graph(_graph), deg(_graph) {\n      Parent::attach(graph.notifier(typename _Graph::Edge()));\n      \n      for(typename _Graph::NodeIt it(graph); it != INVALID; ++it) {\n\tdeg[it] = countInEdges(graph, it);\n      }\n    }\n    \n    /// Gives back the in-degree of a Node.\n    int operator[](const Key& key) const {\n      return deg[key];\n    }\n\n  protected:\n    \n    typedef typename Graph::Edge Edge;\n\n    virtual void add(const Edge& edge) {\n      ++deg[graph.target(edge)];\n    }\n\n    virtual void add(const std::vector<Edge>& edges) {\n      for (int i = 0; i < int(edges.size()); ++i) {\n        ++deg[graph.target(edges[i])];\n      }\n    }\n\n    virtual void erase(const Edge& edge) {\n      --deg[graph.target(edge)];\n    }\n\n    virtual void erase(const std::vector<Edge>& edges) {\n      for (int i = 0; i < int(edges.size()); ++i) {\n        --deg[graph.target(edges[i])];\n      }\n    }\n\n    virtual void build() {\n      for(typename _Graph::NodeIt it(graph); it != INVALID; ++it) {\n\tdeg[it] = countInEdges(graph, it);\n      }      \n    }\n\n    virtual void clear() {\n      for(typename _Graph::NodeIt it(graph); it != INVALID; ++it) {\n\tdeg[it] = 0;\n      }\n    }\n  private:\n    \n    const _Graph& graph;\n    AutoNodeMap deg;\n  };\n\n  /// \\brief Map of the node out-degrees.\n  ///\n  /// This map returns the out-degree of a node. Once it is constructed,\n  /// the degrees are stored in a standard NodeMap, so each query is done\n  /// in constant time. On the other hand, the values are updated automatically\n  /// whenever the graph changes.\n  ///\n  /// \\warning Besides addNode() and addEdge(), a graph structure may provide\n  /// alternative ways to modify the graph. The correct behavior of OutDegMap\n  /// is not guarantied if these additional features are used. For example\n  /// the functions \\ref ListGraph::changeSource() \"changeSource()\",\n  /// \\ref ListGraph::changeTarget() \"changeTarget()\" and\n  /// \\ref ListGraph::reverseEdge() \"reverseEdge()\"\n  /// of \\ref ListGraph will \\e not update the degree values correctly.\n  ///\n  /// \\sa InDegMap\n\n  template <typename _Graph>\n  class OutDegMap  \n    : protected ItemSetTraits<_Graph, typename _Graph::Edge>\n      ::ItemNotifier::ObserverBase {\n\n  public:\n\n    typedef typename ItemSetTraits<_Graph, typename _Graph::Edge>\n    ::ItemNotifier::ObserverBase Parent;\n    \n    typedef _Graph Graph;\n    typedef int Value;\n    typedef typename Graph::Node Key;\n\n  private:\n\n    class AutoNodeMap : public DefaultMap<_Graph, Key, int> {\n    public:\n\n      typedef DefaultMap<_Graph, Key, int> Parent;\n      typedef typename Parent::Graph Graph;\n\n      AutoNodeMap(const Graph& graph) : Parent(graph, 0) {}\n      \n      virtual void add(const Key& key) {\n\tParent::add(key);\n\tParent::set(key, 0);\n      }\n      virtual void add(const std::vector<Key>& keys) {\n\tParent::add(keys);\n\tfor (int i = 0; i < int(keys.size()); ++i) {\n\t  Parent::set(keys[i], 0);\n\t}\n      }\n      virtual void build() {\n\tParent::build();\n\tKey it;\n\ttypename Parent::Notifier* nf = Parent::notifier();\n\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t  Parent::set(it, 0);\n\t}\n      }\n    };\n\n  public:\n\n    /// \\brief Constructor.\n    ///\n    /// Constructor for creating out-degree map.\n    explicit OutDegMap(const Graph& _graph) : graph(_graph), deg(_graph) {\n      Parent::attach(graph.notifier(typename _Graph::Edge()));\n      \n      for(typename _Graph::NodeIt it(graph); it != INVALID; ++it) {\n\tdeg[it] = countOutEdges(graph, it);\n      }\n    }\n\n    /// Gives back the out-degree of a Node.\n    int operator[](const Key& key) const {\n      return deg[key];\n    }\n\n  protected:\n    \n    typedef typename Graph::Edge Edge;\n\n    virtual void add(const Edge& edge) {\n      ++deg[graph.source(edge)];\n    }\n\n    virtual void add(const std::vector<Edge>& edges) {\n      for (int i = 0; i < int(edges.size()); ++i) {\n        ++deg[graph.source(edges[i])];\n      }\n    }\n\n    virtual void erase(const Edge& edge) {\n      --deg[graph.source(edge)];\n    }\n\n    virtual void erase(const std::vector<Edge>& edges) {\n      for (int i = 0; i < int(edges.size()); ++i) {\n        --deg[graph.source(edges[i])];\n      }\n    }\n\n    virtual void build() {\n      for(typename _Graph::NodeIt it(graph); it != INVALID; ++it) {\n\tdeg[it] = countOutEdges(graph, it);\n      }      \n    }\n\n    virtual void clear() {\n      for(typename _Graph::NodeIt it(graph); it != INVALID; ++it) {\n\tdeg[it] = 0;\n      }\n    }\n  private:\n    \n    const _Graph& graph;\n    AutoNodeMap deg;\n  };\n\n\n  ///Dynamic edge look up between given endpoints.\n  \n  ///\\ingroup gutils\n  ///Using this class, you can find an edge in a graph from a given\n  ///source to a given target in amortized time <em>O(log d)</em>,\n  ///where <em>d</em> is the out-degree of the source node.\n  ///\n  ///It is possible to find \\e all parallel edges between two nodes with\n  ///the \\c findFirst() and \\c findNext() members.\n  ///\n  ///See the \\ref EdgeLookUp and \\ref AllEdgeLookUp classes if your\n  ///graph do not changed so frequently.\n  ///\n  ///This class uses a self-adjusting binary search tree, Sleator's\n  ///and Tarjan's Splay tree for guarantee the logarithmic amortized\n  ///time bound for edge lookups. This class also guarantees the\n  ///optimal time bound in a constant factor for any distribution of\n  ///queries.\n  ///\n  ///\\param G The type of the underlying graph.  \n  ///\n  ///\\sa EdgeLookUp  \n  ///\\sa AllEdgeLookUp  \n  template<class G>\n  class DynEdgeLookUp \n    : protected ItemSetTraits<G, typename G::Edge>::ItemNotifier::ObserverBase\n  {\n  public:\n    typedef typename ItemSetTraits<G, typename G::Edge>\n    ::ItemNotifier::ObserverBase Parent;\n\n    GRAPH_TYPEDEFS(typename G);\n    typedef G Graph;\n\n  protected:\n\n    class AutoNodeMap : public DefaultMap<G, Node, Edge> {\n    public:\n\n      typedef DefaultMap<G, Node, Edge> Parent;\n\n      AutoNodeMap(const G& graph) : Parent(graph, INVALID) {}\n      \n      virtual void add(const Node& node) {\n\tParent::add(node);\n\tParent::set(node, INVALID);\n      }\n\n      virtual void add(const std::vector<Node>& nodes) {\n\tParent::add(nodes);\n\tfor (int i = 0; i < int(nodes.size()); ++i) {\n\t  Parent::set(nodes[i], INVALID);\n\t}\n      }\n\n      virtual void build() {\n\tParent::build();\n\tNode it;\n\ttypename Parent::Notifier* nf = Parent::notifier();\n\tfor (nf->first(it); it != INVALID; nf->next(it)) {\n\t  Parent::set(it, INVALID);\n\t}\n      }\n    };\n\n    const Graph &_g;\n    AutoNodeMap _head;\n    typename Graph::template EdgeMap<Edge> _parent;\n    typename Graph::template EdgeMap<Edge> _left;\n    typename Graph::template EdgeMap<Edge> _right;\n    \n    class EdgeLess {\n      const Graph &g;\n    public:\n      EdgeLess(const Graph &_g) : g(_g) {}\n      bool operator()(Edge a,Edge b) const \n      {\n\treturn g.target(a)<g.target(b);\n      }\n    };\n    \n  public:\n    \n    ///Constructor\n\n    ///Constructor.\n    ///\n    ///It builds up the search database.\n    DynEdgeLookUp(const Graph &g) \n      : _g(g),_head(g),_parent(g),_left(g),_right(g) \n    { \n      Parent::attach(_g.notifier(typename Graph::Edge()));\n      refresh(); \n    }\n    \n  protected:\n\n    virtual void add(const Edge& edge) {\n      insert(edge);\n    }\n\n    virtual void add(const std::vector<Edge>& edges) {\n      for (int i = 0; i < int(edges.size()); ++i) {\n\tinsert(edges[i]);\n      }\n    }\n\n    virtual void erase(const Edge& edge) {\n      remove(edge);\n    }\n\n    virtual void erase(const std::vector<Edge>& edges) {\n      for (int i = 0; i < int(edges.size()); ++i) {\n\tremove(edges[i]);\n      }     \n    }\n\n    virtual void build() {\n      refresh();\n    }\n\n    virtual void clear() {\n      for(NodeIt n(_g);n!=INVALID;++n) {\n\t_head.set(n, INVALID);\n      }\n    }\n\n    void insert(Edge edge) {\n      Node s = _g.source(edge);\n      Node t = _g.target(edge);\n      _left.set(edge, INVALID);\n      _right.set(edge, INVALID);\n      \n      Edge e = _head[s];\n      if (e == INVALID) {\n\t_head.set(s, edge);\n\t_parent.set(edge, INVALID);\n\treturn;\n      }\n      while (true) {\n\tif (t < _g.target(e)) {\n\t  if (_left[e] == INVALID) {\n\t    _left.set(e, edge);\n\t    _parent.set(edge, e);\n\t    splay(edge);\n\t    return;\n\t  } else {\n\t    e = _left[e];\n\t  }\n\t} else {\n\t  if (_right[e] == INVALID) {\n\t    _right.set(e, edge);\n\t    _parent.set(edge, e);\n\t    splay(edge);\n\t    return;\n\t  } else {\n\t    e = _right[e];\n\t  }\n\t}\n      }\n    }\n\n    void remove(Edge edge) {\n      if (_left[edge] == INVALID) {\n\tif (_right[edge] != INVALID) {\n\t  _parent.set(_right[edge], _parent[edge]);\n\t}\n\tif (_parent[edge] != INVALID) {\n\t  if (_left[_parent[edge]] == edge) {\n\t    _left.set(_parent[edge], _right[edge]);\n\t  } else {\n\t    _right.set(_parent[edge], _right[edge]);\n\t  }\n\t} else {\n\t  _head.set(_g.source(edge), _right[edge]);\n\t}\n      } else if (_right[edge] == INVALID) {\n\t_parent.set(_left[edge], _parent[edge]);\n\tif (_parent[edge] != INVALID) {\n\t  if (_left[_parent[edge]] == edge) {\n\t    _left.set(_parent[edge], _left[edge]);\n\t  } else {\n\t    _right.set(_parent[edge], _left[edge]);\n\t  }\n\t} else {\n\t  _head.set(_g.source(edge), _left[edge]);\n\t}\n      } else {\n\tEdge e = _left[edge];\n\tif (_right[e] != INVALID) {\n\t  e = _right[e];\t  \n\t  while (_right[e] != INVALID) {\n\t    e = _right[e];\n\t  }\n\t  Edge s = _parent[e];\n\t  _right.set(_parent[e], _left[e]);\n\t  if (_left[e] != INVALID) {\n\t    _parent.set(_left[e], _parent[e]);\n\t  }\n\t  \n\t  _left.set(e, _left[edge]);\n\t  _parent.set(_left[edge], e);\n\t  _right.set(e, _right[edge]);\n\t  _parent.set(_right[edge], e);\n\n\t  _parent.set(e, _parent[edge]);\n\t  if (_parent[edge] != INVALID) {\n\t    if (_left[_parent[edge]] == edge) {\n\t      _left.set(_parent[edge], e);\n\t    } else {\n\t      _right.set(_parent[edge], e);\n\t    }\n\t  }\n\t  splay(s);\n\t} else {\n\t  _right.set(e, _right[edge]);\n\t  _parent.set(_right[edge], e);\n\n\t  if (_parent[edge] != INVALID) {\n\t    if (_left[_parent[edge]] == edge) {\n\t      _left.set(_parent[edge], e);\n\t    } else {\n\t      _right.set(_parent[edge], e);\n\t    }\n\t  } else {\n\t    _head.set(_g.source(edge), e);\n\t  }\n\t}\n      }\n    }\n\n    Edge refreshRec(std::vector<Edge> &v,int a,int b) \n    {\n      int m=(a+b)/2;\n      Edge me=v[m];\n      if (a < m) {\n\tEdge left = refreshRec(v,a,m-1);\n\t_left.set(me, left);\n\t_parent.set(left, me);\n      } else {\n\t_left.set(me, INVALID);\n      }\n      if (m < b) {\n\tEdge right = refreshRec(v,m+1,b);\n\t_right.set(me, right);\n\t_parent.set(right, me);\n      } else {\n\t_right.set(me, INVALID);\n      }\n      return me;\n    }\n\n    void refresh() {\n      for(NodeIt n(_g);n!=INVALID;++n) {\n\tstd::vector<Edge> v;\n\tfor(OutEdgeIt e(_g,n);e!=INVALID;++e) v.push_back(e);\n\tif(v.size()) {\n\t  std::sort(v.begin(),v.end(),EdgeLess(_g));\n\t  Edge head = refreshRec(v,0,v.size()-1);\n\t  _head.set(n, head);\n\t  _parent.set(head, INVALID);\n\t}\n\telse _head.set(n, INVALID);\n      }\n    }\n\n    void zig(Edge v) {        \n      Edge w = _parent[v];\n      _parent.set(v, _parent[w]);\n      _parent.set(w, v);\n      _left.set(w, _right[v]);\n      _right.set(v, w);\n      if (_parent[v] != INVALID) {\n\tif (_right[_parent[v]] == w) {\n\t  _right.set(_parent[v], v);\n\t} else {\n\t  _left.set(_parent[v], v);\n\t}\n      }\n      if (_left[w] != INVALID){\n\t_parent.set(_left[w], w);\n      }\n    }\n\n    void zag(Edge v) {        \n      Edge w = _parent[v];\n      _parent.set(v, _parent[w]);\n      _parent.set(w, v);\n      _right.set(w, _left[v]);\n      _left.set(v, w);\n      if (_parent[v] != INVALID){\n\tif (_left[_parent[v]] == w) {\n\t  _left.set(_parent[v], v);\n\t} else {\n\t  _right.set(_parent[v], v);\n\t}\n      }\n      if (_right[w] != INVALID){\n\t_parent.set(_right[w], w);\n      }\n    }\n\n    void splay(Edge v) {\n      while (_parent[v] != INVALID) {\n\tif (v == _left[_parent[v]]) {\n\t  if (_parent[_parent[v]] == INVALID) {\n\t    zig(v);\n\t  } else {\n\t    if (_parent[v] == _left[_parent[_parent[v]]]) {\n\t      zig(_parent[v]);\n\t      zig(v);\n\t    } else {\n\t      zig(v);\n\t      zag(v);\n\t    }\n\t  }\n\t} else {\n\t  if (_parent[_parent[v]] == INVALID) {\n\t    zag(v);\n\t  } else {\n\t    if (_parent[v] == _left[_parent[_parent[v]]]) {\n\t      zag(v);\n\t      zig(v);\n\t    } else {\n\t      zag(_parent[v]);\n\t      zag(v);\n\t    }\n\t  }\n\t}\n      }\n      _head[_g.source(v)] = v;\n    }\n\n\n  public:\n    \n    ///Find an edge between two nodes.\n    \n    ///Find an edge between two nodes in time <em>O(</em>log<em>d)</em>, where\n    /// <em>d</em> is the number of outgoing edges of \\c s.\n    ///\\param s The source node\n    ///\\param t The target node\n    ///\\return An edge from \\c s to \\c t if there exists,\n    ///\\ref INVALID otherwise.\n    Edge operator()(Node s, Node t) const\n    {\n      Edge e = _head[s];\n      while (true) {\n\tif (_g.target(e) == t) {\n\t  const_cast<DynEdgeLookUp&>(*this).splay(e);\n\t  return e;\n\t} else if (t < _g.target(e)) {\n\t  if (_left[e] == INVALID) {\n\t    const_cast<DynEdgeLookUp&>(*this).splay(e);\n\t    return INVALID;\n\t  } else {\n\t    e = _left[e];\n\t  }\n\t} else  {\n\t  if (_right[e] == INVALID) {\n\t    const_cast<DynEdgeLookUp&>(*this).splay(e);\n\t    return INVALID;\n\t  } else {\n\t    e = _right[e];\n\t  }\n\t}\n      }\n    }\n\n    ///Find the first edge between two nodes.\n    \n    ///Find the first edge between two nodes in time\n    /// <em>O(</em>log<em>d)</em>, where <em>d</em> is the number of\n    /// outgoing edges of \\c s.  \n    ///\\param s The source node \n    ///\\param t The target node\n    ///\\return An edge from \\c s to \\c t if there exists, \\ref INVALID\n    /// otherwise.\n    Edge findFirst(Node s, Node t) const\n    {\n      Edge e = _head[s];\n      Edge r = INVALID;\n      while (true) {\n\tif (_g.target(e) < t) {\n\t  if (_right[e] == INVALID) {\n\t    const_cast<DynEdgeLookUp&>(*this).splay(e);\n\t    return r;\n\t  } else {\n\t    e = _right[e];\n\t  }\n\t} else {\n\t  if (_g.target(e) == t) {\n\t    r = e;\n\t  }\n\t  if (_left[e] == INVALID) {\n\t    const_cast<DynEdgeLookUp&>(*this).splay(e);\n\t    return r;\n\t  } else {\n\t    e = _left[e];\n\t  }\n\t}\n      }\n    }\n\n    ///Find the next edge between two nodes.\n    \n    ///Find the next edge between two nodes in time\n    /// <em>O(</em>log<em>d)</em>, where <em>d</em> is the number of\n    /// outgoing edges of \\c s.  \n    ///\\param s The source node \n    ///\\param t The target node\n    ///\\return An edge from \\c s to \\c t if there exists, \\ref INVALID\n    /// otherwise.\n\n    ///\\note If \\c e is not the result of the previous \\c findFirst()\n    ///operation then the amorized time bound can not be guaranteed.\n#ifdef DOXYGEN\n    Edge findNext(Node s, Node t, Edge e) const\n#else\n    Edge findNext(Node, Node t, Edge e) const\n#endif\n    {\n      if (_right[e] != INVALID) {\n\te = _right[e];\n\twhile (_left[e] != INVALID) {\n\t  e = _left[e];\n\t}\n\tconst_cast<DynEdgeLookUp&>(*this).splay(e);\n      } else {\n\twhile (_parent[e] != INVALID && _right[_parent[e]] ==  e) {\n\t  e = _parent[e];\n\t}\n\tif (_parent[e] == INVALID) {\n\t  return INVALID;\n\t} else {\n\t  e = _parent[e];\n\t  const_cast<DynEdgeLookUp&>(*this).splay(e);\n\t}\n      }\n      if (_g.target(e) == t) return e;\n      else return INVALID;    \n    }\n\n  };\n\n  ///Fast edge look up between given endpoints.\n  \n  ///\\ingroup gutils\n  ///Using this class, you can find an edge in a graph from a given\n  ///source to a given target in time <em>O(log d)</em>,\n  ///where <em>d</em> is the out-degree of the source node.\n  ///\n  ///It is not possible to find \\e all parallel edges between two nodes.\n  ///Use \\ref AllEdgeLookUp for this purpose.\n  ///\n  ///\\warning This class is static, so you should refresh() (or at least\n  ///refresh(Node)) this data structure\n  ///whenever the graph changes. This is a time consuming (superlinearly\n  ///proportional (<em>O(m</em>log<em>m)</em>) to the number of edges).\n  ///\n  ///\\param G The type of the underlying graph.\n  ///\n  ///\\sa DynEdgeLookUp\n  ///\\sa AllEdgeLookUp  \n  template<class G>\n  class EdgeLookUp \n  {\n  public:\n    GRAPH_TYPEDEFS(typename G);\n    typedef G Graph;\n\n  protected:\n    const Graph &_g;\n    typename Graph::template NodeMap<Edge> _head;\n    typename Graph::template EdgeMap<Edge> _left;\n    typename Graph::template EdgeMap<Edge> _right;\n    \n    class EdgeLess {\n      const Graph &g;\n    public:\n      EdgeLess(const Graph &_g) : g(_g) {}\n      bool operator()(Edge a,Edge b) const \n      {\n\treturn g.target(a)<g.target(b);\n      }\n    };\n    \n  public:\n    \n    ///Constructor\n\n    ///Constructor.\n    ///\n    ///It builds up the search database, which remains valid until the graph\n    ///changes.\n    EdgeLookUp(const Graph &g) :_g(g),_head(g),_left(g),_right(g) {refresh();}\n    \n  private:\n    Edge refreshRec(std::vector<Edge> &v,int a,int b) \n    {\n      int m=(a+b)/2;\n      Edge me=v[m];\n      _left[me] = a<m?refreshRec(v,a,m-1):INVALID;\n      _right[me] = m<b?refreshRec(v,m+1,b):INVALID;\n      return me;\n    }\n  public:\n    ///Refresh the data structure at a node.\n\n    ///Build up the search database of node \\c n.\n    ///\n    ///It runs in time <em>O(d</em>log<em>d)</em>, where <em>d</em> is\n    ///the number of the outgoing edges of \\c n.\n    void refresh(Node n) \n    {\n      std::vector<Edge> v;\n      for(OutEdgeIt e(_g,n);e!=INVALID;++e) v.push_back(e);\n      if(v.size()) {\n\tstd::sort(v.begin(),v.end(),EdgeLess(_g));\n\t_head[n]=refreshRec(v,0,v.size()-1);\n      }\n      else _head[n]=INVALID;\n    }\n    ///Refresh the full data structure.\n\n    ///Build up the full search database. In fact, it simply calls\n    ///\\ref refresh(Node) \"refresh(n)\" for each node \\c n.\n    ///\n    ///It runs in time <em>O(m</em>log<em>D)</em>, where <em>m</em> is\n    ///the number of the edges of \\c n and <em>D</em> is the maximum\n    ///out-degree of the graph.\n\n    void refresh() \n    {\n      for(NodeIt n(_g);n!=INVALID;++n) refresh(n);\n    }\n    \n    ///Find an edge between two nodes.\n    \n    ///Find an edge between two nodes in time <em>O(</em>log<em>d)</em>, where\n    /// <em>d</em> is the number of outgoing edges of \\c s.\n    ///\\param s The source node\n    ///\\param t The target node\n    ///\\return An edge from \\c s to \\c t if there exists,\n    ///\\ref INVALID otherwise.\n    ///\n    ///\\warning If you change the graph, refresh() must be called before using\n    ///this operator. If you change the outgoing edges of\n    ///a single node \\c n, then\n    ///\\ref refresh(Node) \"refresh(n)\" is enough.\n    ///\n    Edge operator()(Node s, Node t) const\n    {\n      Edge e;\n      for(e=_head[s];\n\t  e!=INVALID&&_g.target(e)!=t;\n\t  e = t < _g.target(e)?_left[e]:_right[e]) ;\n      return e;\n    }\n\n  };\n\n  ///Fast look up of all edges between given endpoints.\n  \n  ///\\ingroup gutils\n  ///This class is the same as \\ref EdgeLookUp, with the addition\n  ///that it makes it possible to find all edges between given endpoints.\n  ///\n  ///\\warning This class is static, so you should refresh() (or at least\n  ///refresh(Node)) this data structure\n  ///whenever the graph changes. This is a time consuming (superlinearly\n  ///proportional (<em>O(m</em>log<em>m)</em>) to the number of edges).\n  ///\n  ///\\param G The type of the underlying graph.\n  ///\n  ///\\sa DynEdgeLookUp\n  ///\\sa EdgeLookUp  \n  template<class G>\n  class AllEdgeLookUp : public EdgeLookUp<G>\n  {\n    using EdgeLookUp<G>::_g;\n    using EdgeLookUp<G>::_right;\n    using EdgeLookUp<G>::_left;\n    using EdgeLookUp<G>::_head;\n\n    GRAPH_TYPEDEFS(typename G);\n    typedef G Graph;\n    \n    typename Graph::template EdgeMap<Edge> _next;\n    \n    Edge refreshNext(Edge head,Edge next=INVALID)\n    {\n      if(head==INVALID) return next;\n      else {\n\tnext=refreshNext(_right[head],next);\n// \t_next[head]=next;\n\t_next[head]=( next!=INVALID && _g.target(next)==_g.target(head))\n\t  ? next : INVALID;\n\treturn refreshNext(_left[head],head);\n      }\n    }\n    \n    void refreshNext()\n    {\n      for(NodeIt n(_g);n!=INVALID;++n) refreshNext(_head[n]);\n    }\n    \n  public:\n    ///Constructor\n\n    ///Constructor.\n    ///\n    ///It builds up the search database, which remains valid until the graph\n    ///changes.\n    AllEdgeLookUp(const Graph &g) : EdgeLookUp<G>(g), _next(g) {refreshNext();}\n\n    ///Refresh the data structure at a node.\n\n    ///Build up the search database of node \\c n.\n    ///\n    ///It runs in time <em>O(d</em>log<em>d)</em>, where <em>d</em> is\n    ///the number of the outgoing edges of \\c n.\n    \n    void refresh(Node n) \n    {\n      EdgeLookUp<G>::refresh(n);\n      refreshNext(_head[n]);\n    }\n    \n    ///Refresh the full data structure.\n\n    ///Build up the full search database. In fact, it simply calls\n    ///\\ref refresh(Node) \"refresh(n)\" for each node \\c n.\n    ///\n    ///It runs in time <em>O(m</em>log<em>D)</em>, where <em>m</em> is\n    ///the number of the edges of \\c n and <em>D</em> is the maximum\n    ///out-degree of the graph.\n\n    void refresh() \n    {\n      for(NodeIt n(_g);n!=INVALID;++n) refresh(_head[n]);\n    }\n    \n    ///Find an edge between two nodes.\n    \n    ///Find an edge between two nodes.\n    ///\\param s The source node\n    ///\\param t The target node\n    ///\\param prev The previous edge between \\c s and \\c t. It it is INVALID or\n    ///not given, the operator finds the first appropriate edge.\n    ///\\return An edge from \\c s to \\c t after \\c prev or\n    ///\\ref INVALID if there is no more.\n    ///\n    ///For example, you can count the number of edges from \\c u to \\c v in the\n    ///following way.\n    ///\\code\n    ///AllEdgeLookUp<ListGraph> ae(g);\n    ///...\n    ///int n=0;\n    ///for(Edge e=ae(u,v);e!=INVALID;e=ae(u,v,e)) n++;\n    ///\\endcode\n    ///\n    ///Finding the first edge take <em>O(</em>log<em>d)</em> time, where\n    /// <em>d</em> is the number of outgoing edges of \\c s. Then, the\n    ///consecutive edges are found in constant time.\n    ///\n    ///\\warning If you change the graph, refresh() must be called before using\n    ///this operator. If you change the outgoing edges of\n    ///a single node \\c n, then\n    ///\\ref refresh(Node) \"refresh(n)\" is enough.\n    ///\n#ifdef DOXYGEN\n    Edge operator()(Node s, Node t, Edge prev=INVALID) const {}\n#else\n    using EdgeLookUp<G>::operator() ;\n    Edge operator()(Node s, Node t, Edge prev) const\n    {\n      return prev==INVALID?(*this)(s,t):_next[prev];\n    }\n#endif\n      \n  };\n\n  /// @}\n\n} //END OF NAMESPACE LEMON\n\n#endif\n"
  },
  {
    "path": "src/lemon/list_graph.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_LIST_GRAPH_H\n#define LEMON_LIST_GRAPH_H\n\n///\\ingroup graphs\n///\\file\n///\\brief ListGraph, ListUGraph classes.\n\n#include <lemon/bits/base_extender.h>\n#include <lemon/bits/graph_extender.h>\n\n#include <lemon/error.h>\n\n#include <vector>\n#include <list>\n\nnamespace lemon {\n\n  class ListGraphBase {\n\n  protected:\n    struct NodeT {\n      int first_in, first_out;\n      int prev, next;\n    };\n \n    struct EdgeT {\n      int target, source;\n      int prev_in, prev_out;\n      int next_in, next_out;\n    };\n\n    std::vector<NodeT> nodes;\n\n    int first_node;\n\n    int first_free_node;\n\n    std::vector<EdgeT> edges;\n\n    int first_free_edge;\n    \n  public:\n    \n    typedef ListGraphBase Graph;\n    \n    class Node {\n      friend class ListGraphBase;\n    protected:\n\n      int id;\n      explicit Node(int pid) { id = pid;}\n\n    public:\n      Node() {}\n      Node (Invalid) { id = -1; }\n      bool operator==(const Node& node) const {return id == node.id;}\n      bool operator!=(const Node& node) const {return id != node.id;}\n      bool operator<(const Node& node) const {return id < node.id;}\n    };\n\n    class Edge {\n      friend class ListGraphBase;\n    protected:\n\n      int id;\n      explicit Edge(int pid) { id = pid;}\n\n    public:\n      Edge() {}\n      Edge (Invalid) { id = -1; }\n      bool operator==(const Edge& edge) const {return id == edge.id;}\n      bool operator!=(const Edge& edge) const {return id != edge.id;}\n      bool operator<(const Edge& edge) const {return id < edge.id;}\n    };\n\n\n\n    ListGraphBase()\n      : nodes(), first_node(-1),\n\tfirst_free_node(-1), edges(), first_free_edge(-1) {}\n\n    \n    int maxNodeId() const { return nodes.size()-1; } \n    int maxEdgeId() const { return edges.size()-1; }\n\n    Node source(Edge e) const { return Node(edges[e.id].source); }\n    Node target(Edge e) const { return Node(edges[e.id].target); }\n\n\n    void first(Node& node) const { \n      node.id = first_node;\n    }\n\n    void next(Node& node) const {\n      node.id = nodes[node.id].next;\n    }\n\n\n    void first(Edge& e) const { \n      int n;\n      for(n = first_node; \n\t  n!=-1 && nodes[n].first_in == -1; \n\t  n = nodes[n].next);\n      e.id = (n == -1) ? -1 : nodes[n].first_in;\n    }\n\n    void next(Edge& edge) const {\n      if (edges[edge.id].next_in != -1) {\n\tedge.id = edges[edge.id].next_in;\n      } else {\n\tint n;\n\tfor(n = nodes[edges[edge.id].target].next;\n\t  n!=-1 && nodes[n].first_in == -1; \n\t  n = nodes[n].next);\n\tedge.id = (n == -1) ? -1 : nodes[n].first_in;\n      }      \n    }\n\n    void firstOut(Edge &e, const Node& v) const {\n      e.id = nodes[v.id].first_out;\n    }\n    void nextOut(Edge &e) const {\n      e.id=edges[e.id].next_out;\n    }\n\n    void firstIn(Edge &e, const Node& v) const {\n      e.id = nodes[v.id].first_in;\n    }\n    void nextIn(Edge &e) const {\n      e.id=edges[e.id].next_in;\n    }\n\n    \n    static int id(Node v) { return v.id; }\n    static int id(Edge e) { return e.id; }\n\n    static Node nodeFromId(int id) { return Node(id);}\n    static Edge edgeFromId(int id) { return Edge(id);}\n\n    Node addNode() {     \n      int n;\n      \n      if(first_free_node==-1) {\n\tn = nodes.size();\n\tnodes.push_back(NodeT());\n      } else {\n\tn = first_free_node;\n\tfirst_free_node = nodes[n].next;\n      }\n      \n      nodes[n].next = first_node;\n      if(first_node != -1) nodes[first_node].prev = n;\n      first_node = n;\n      nodes[n].prev = -1;\n      \n      nodes[n].first_in = nodes[n].first_out = -1;\n      \n      return Node(n);\n    }\n    \n    Edge addEdge(Node u, Node v) {\n      int n;      \n\n      if (first_free_edge == -1) {\n\tn = edges.size();\n\tedges.push_back(EdgeT());\n      } else {\n\tn = first_free_edge;\n\tfirst_free_edge = edges[n].next_in;\n      }\n      \n      edges[n].source = u.id; \n      edges[n].target = v.id;\n\n      edges[n].next_out = nodes[u.id].first_out;\n      if(nodes[u.id].first_out != -1) {\n\tedges[nodes[u.id].first_out].prev_out = n;\n      }\n      \n      edges[n].next_in = nodes[v.id].first_in;\n      if(nodes[v.id].first_in != -1) {\n\tedges[nodes[v.id].first_in].prev_in = n;\n      }\n      \n      edges[n].prev_in = edges[n].prev_out = -1;\n\t\n      nodes[u.id].first_out = nodes[v.id].first_in = n;\n\n      return Edge(n);\n    }\n    \n    void erase(const Node& node) {\n      int n = node.id;\n      \n      if(nodes[n].next != -1) {\n\tnodes[nodes[n].next].prev = nodes[n].prev;\n      }\n      \n      if(nodes[n].prev != -1) {\n\tnodes[nodes[n].prev].next = nodes[n].next;\n      } else {\n\tfirst_node = nodes[n].next;\n      }\n      \n      nodes[n].next = first_free_node;\n      first_free_node = n;\n\n    }\n    \n    void erase(const Edge& edge) {\n      int n = edge.id;\n      \n      if(edges[n].next_in!=-1) {\n\tedges[edges[n].next_in].prev_in = edges[n].prev_in;\n      }\n\n      if(edges[n].prev_in!=-1) {\n\tedges[edges[n].prev_in].next_in = edges[n].next_in;\n      } else {\n\tnodes[edges[n].target].first_in = edges[n].next_in;\n      }\n\n      \n      if(edges[n].next_out!=-1) {\n\tedges[edges[n].next_out].prev_out = edges[n].prev_out;\n      } \n\n      if(edges[n].prev_out!=-1) {\n\tedges[edges[n].prev_out].next_out = edges[n].next_out;\n      } else {\n\tnodes[edges[n].source].first_out = edges[n].next_out;\n      }\n      \n      edges[n].next_in = first_free_edge;\n      first_free_edge = n;      \n\n    }\n\n    void clear() {\n      edges.clear();\n      nodes.clear();\n      first_node = first_free_node = first_free_edge = -1;\n    }\n\n  protected:\n    void changeTarget(Edge e, Node n) \n    {\n      if(edges[e.id].next_in != -1)\n\tedges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;\n      if(edges[e.id].prev_in != -1)\n\tedges[edges[e.id].prev_in].next_in = edges[e.id].next_in;\n      else nodes[edges[e.id].target].first_in = edges[e.id].next_in;\n      if (nodes[n.id].first_in != -1) {\n\tedges[nodes[n.id].first_in].prev_in = e.id;\n      }\n      edges[e.id].target = n.id;\n      edges[e.id].prev_in = -1;\n      edges[e.id].next_in = nodes[n.id].first_in;\n      nodes[n.id].first_in = e.id;\n    }\n    void changeSource(Edge e, Node n) \n    {\n      if(edges[e.id].next_out != -1)\n\tedges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;\n      if(edges[e.id].prev_out != -1)\n\tedges[edges[e.id].prev_out].next_out = edges[e.id].next_out;\n      else nodes[edges[e.id].source].first_out = edges[e.id].next_out;\n      if (nodes[n.id].first_out != -1) {\n\tedges[nodes[n.id].first_out].prev_out = e.id;\n      }\n      edges[e.id].source = n.id;\n      edges[e.id].prev_out = -1;\n      edges[e.id].next_out = nodes[n.id].first_out;\n      nodes[n.id].first_out = e.id;\n    }\n\n  };\n\n  typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;\n\n  /// \\addtogroup graphs\n  /// @{\n\n  ///A list graph class.\n\n  ///This is a simple and fast graph implementation.\n  ///\n  ///It conforms to the \\ref concepts::Graph \"Graph concept\" and it\n  ///also provides several additional useful extra functionalities.\n  ///The most of the member functions and nested classes are\n  ///documented only in the concept class.\n  ///\n  ///An important extra feature of this graph implementation is that\n  ///its maps are real \\ref concepts::ReferenceMap \"reference map\"s.\n  ///\n  ///\\sa concepts::Graph.\n\n  class ListGraph : public ExtendedListGraphBase {\n  private:\n    ///ListGraph is \\e not copy constructible. Use GraphCopy() instead.\n    \n    ///ListGraph is \\e not copy constructible. Use GraphCopy() instead.\n    ///\n    ListGraph(const ListGraph &) :ExtendedListGraphBase() {};\n    ///\\brief Assignment of ListGraph to another one is \\e not allowed.\n    ///Use GraphCopy() instead.\n\n    ///Assignment of ListGraph to another one is \\e not allowed.\n    ///Use GraphCopy() instead.\n    void operator=(const ListGraph &) {}\n  public:\n\n    typedef ExtendedListGraphBase Parent;\n\n    /// Constructor\n    \n    /// Constructor.\n    ///\n    ListGraph() {}\n\n    ///Add a new node to the graph.\n    \n    /// \\return the new node.\n    ///\n    Node addNode() { return Parent::addNode(); }\n\n    ///Add a new edge to the graph.\n    \n    ///Add a new edge to the graph with source node \\c s\n    ///and target node \\c t.\n    ///\\return the new edge.\n    Edge addEdge(const Node& s, const Node& t) { \n      return Parent::addEdge(s, t); \n    }\n\n    /// Changes the target of \\c e to \\c n\n\n    /// Changes the target of \\c e to \\c n\n    ///\n    ///\\note The <tt>EdgeIt</tt>s and <tt>OutEdgeIt</tt>s referencing\n    ///the changed edge remain valid. However <tt>InEdgeIt</tt>s are\n    ///invalidated.\n    ///\\warning This functionality cannot be used together with the Snapshot\n    ///feature.\n    void changeTarget(Edge e, Node n) { \n      Parent::changeTarget(e,n); \n    }\n    /// Changes the source of \\c e to \\c n\n\n    /// Changes the source of \\c e to \\c n\n    ///\n    ///\\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s referencing\n    ///the changed edge remain valid. However <tt>OutEdgeIt</tt>s are\n    ///invalidated.\n    ///\\warning This functionality cannot be used together with the Snapshot\n    ///feature.\n    void changeSource(Edge e, Node n) { \n      Parent::changeSource(e,n);\n    }\n\n    /// Invert the direction of an edge.\n\n    ///\\note The <tt>EdgeIt</tt>s referencing the changed edge remain\n    ///valid. However <tt>OutEdgeIt</tt>s and <tt>InEdgeIt</tt>s are\n    ///invalidated.\n    ///\\warning This functionality cannot be used together with the Snapshot\n    ///feature.\n    void reverseEdge(Edge e) {\n      Node t=target(e);\n      changeTarget(e,source(e));\n      changeSource(e,t);\n    }\n\n    /// Using this it is possible to avoid the superfluous memory\n    /// allocation: if you know that the graph you want to build will\n    /// be very large (e.g. it will contain millions of nodes and/or edges)\n    /// then it is worth reserving space for this amount before starting\n    /// to build the graph.\n    /// \\sa reserveEdge\n    void reserveNode(int n) { nodes.reserve(n); };\n\n    /// \\brief Using this it is possible to avoid the superfluous memory\n    /// allocation.\n\n    /// Using this it is possible to avoid the superfluous memory\n    /// allocation: if you know that the graph you want to build will\n    /// be very large (e.g. it will contain millions of nodes and/or edges)\n    /// then it is worth reserving space for this amount before starting\n    /// to build the graph.\n    /// \\sa reserveNode\n    void reserveEdge(int m) { edges.reserve(m); };\n\n    ///Contract two nodes.\n\n    ///This function contracts two nodes.\n    ///\n    ///Node \\p b will be removed but instead of deleting\n    ///incident edges, they will be joined to \\p a.\n    ///The last parameter \\p r controls whether to remove loops. \\c true\n    ///means that loops will be removed.\n    ///\n    ///\\note The <tt>EdgeIt</tt>s\n    ///referencing a moved edge remain\n    ///valid. However <tt>InEdgeIt</tt>s and <tt>OutEdgeIt</tt>s\n    ///may be invalidated.\n    ///\\warning This functionality cannot be used together with the Snapshot\n    ///feature.\n    void contract(Node a, Node b, bool r = true) \n    {\n      for(OutEdgeIt e(*this,b);e!=INVALID;) {\n\tOutEdgeIt f=e;\n\t++f;\n\tif(r && target(e)==a) erase(e);\n\telse changeSource(e,a);\n\te=f;\n      }\n      for(InEdgeIt e(*this,b);e!=INVALID;) {\n\tInEdgeIt f=e;\n\t++f;\n\tif(r && source(e)==a) erase(e);\n\telse changeTarget(e,a);\n\te=f;\n      }\n      erase(b);\n    }\n\n    ///Split a node.\n\n    ///This function splits a node. First a new node is added to the graph,\n    ///then the source of each outgoing edge of \\c n is moved to this new node.\n    ///If \\c connect is \\c true (this is the default value), then a new edge\n    ///from \\c n to the newly created node is also added.\n    ///\\return The newly created node.\n    ///\n    ///\\note The <tt>EdgeIt</tt>s referencing a moved edge remain\n    ///valid. However <tt>InEdgeIt</tt>s and <tt>OutEdgeIt</tt>s may\n    ///be invalidated.  \n    ///\n    ///\\warning This functionality cannot be used together with the\n    ///Snapshot feature.  \\todo It could be implemented in a bit\n    ///faster way.\n    Node split(Node n, bool connect = true) {\n      Node b = addNode();\n      for(OutEdgeIt e(*this,n);e!=INVALID;) {\n \tOutEdgeIt f=e;\n\t++f;\n\tchangeSource(e,b);\n\te=f;\n      }\n      if (connect) addEdge(n,b);\n      return b;\n    }\n      \n    ///Split an edge.\n\n    ///This function splits an edge. First a new node \\c b is added to\n    ///the graph, then the original edge is re-targeted to \\c\n    ///b. Finally an edge from \\c b to the original target is added.\n    ///\\return The newly created node.  \n    ///\\warning This functionality\n    ///cannot be used together with the Snapshot feature.\n    Node split(Edge e) {\n      Node b = addNode();\n      addEdge(b,target(e));\n      changeTarget(e,b);\n      return b;\n    }\n      \n    /// \\brief Class to make a snapshot of the graph and restore\n    /// to it later.\n    ///\n    /// Class to make a snapshot of the graph and to restore it\n    /// later.\n    ///\n    /// The newly added nodes and edges can be removed using the\n    /// restore() function.\n    ///\n    /// \\warning Edge and node deletions cannot be restored. This\n    /// events invalidate the snapshot. \n    class Snapshot {\n    protected:\n\n      typedef Parent::NodeNotifier NodeNotifier;\n\n      class NodeObserverProxy : public NodeNotifier::ObserverBase {\n      public:\n\n        NodeObserverProxy(Snapshot& _snapshot)\n          : snapshot(_snapshot) {}\n\n        using NodeNotifier::ObserverBase::attach;\n        using NodeNotifier::ObserverBase::detach;\n        using NodeNotifier::ObserverBase::attached;\n        \n      protected:\n        \n        virtual void add(const Node& node) {\n          snapshot.addNode(node);\n        }\n        virtual void add(const std::vector<Node>& nodes) {\n          for (int i = nodes.size() - 1; i >= 0; ++i) {\n            snapshot.addNode(nodes[i]);\n          }\n        }\n        virtual void erase(const Node& node) {\n          snapshot.eraseNode(node);\n        }\n        virtual void erase(const std::vector<Node>& nodes) {\n          for (int i = 0; i < int(nodes.size()); ++i) {\n            snapshot.eraseNode(nodes[i]);\n          }\n        }\n        virtual void build() {\n          Node node;\n          std::vector<Node> nodes;\n          for (notifier()->first(node); node != INVALID; \n               notifier()->next(node)) {\n            nodes.push_back(node);\n          }\n          for (int i = nodes.size() - 1; i >= 0; --i) {\n            snapshot.addNode(nodes[i]);\n          }\n        }\n        virtual void clear() {\n          Node node;\n          for (notifier()->first(node); node != INVALID; \n               notifier()->next(node)) {\n            snapshot.eraseNode(node);\n          }\n        }\n\n        Snapshot& snapshot;\n      };\n\n      class EdgeObserverProxy : public EdgeNotifier::ObserverBase {\n      public:\n\n        EdgeObserverProxy(Snapshot& _snapshot)\n          : snapshot(_snapshot) {}\n\n        using EdgeNotifier::ObserverBase::attach;\n        using EdgeNotifier::ObserverBase::detach;\n        using EdgeNotifier::ObserverBase::attached;\n        \n      protected:\n\n        virtual void add(const Edge& edge) {\n          snapshot.addEdge(edge);\n        }\n        virtual void add(const std::vector<Edge>& edges) {\n          for (int i = edges.size() - 1; i >= 0; ++i) {\n            snapshot.addEdge(edges[i]);\n          }\n        }\n        virtual void erase(const Edge& edge) {\n          snapshot.eraseEdge(edge);\n        }\n        virtual void erase(const std::vector<Edge>& edges) {\n          for (int i = 0; i < int(edges.size()); ++i) {\n            snapshot.eraseEdge(edges[i]);\n          }\n        }\n        virtual void build() {\n          Edge edge;\n          std::vector<Edge> edges;\n          for (notifier()->first(edge); edge != INVALID; \n               notifier()->next(edge)) {\n            edges.push_back(edge);\n          }\n          for (int i = edges.size() - 1; i >= 0; --i) {\n            snapshot.addEdge(edges[i]);\n          }\n        }\n        virtual void clear() {\n          Edge edge;\n          for (notifier()->first(edge); edge != INVALID; \n               notifier()->next(edge)) {\n            snapshot.eraseEdge(edge);\n          }\n        }\n\n        Snapshot& snapshot;\n      };\n      \n      ListGraph *graph;\n\n      NodeObserverProxy node_observer_proxy;\n      EdgeObserverProxy edge_observer_proxy;\n\n      std::list<Node> added_nodes;\n      std::list<Edge> added_edges;\n\n\n      void addNode(const Node& node) {\n        added_nodes.push_front(node);        \n      }\n      void eraseNode(const Node& node) {\n        std::list<Node>::iterator it = \n          std::find(added_nodes.begin(), added_nodes.end(), node);\n        if (it == added_nodes.end()) {\n          clear();\n          edge_observer_proxy.detach();\n          throw NodeNotifier::ImmediateDetach();\n        } else {\n          added_nodes.erase(it);\n        }\n      }\n\n      void addEdge(const Edge& edge) {\n        added_edges.push_front(edge);        \n      }\n      void eraseEdge(const Edge& edge) {\n        std::list<Edge>::iterator it = \n          std::find(added_edges.begin(), added_edges.end(), edge);\n        if (it == added_edges.end()) {\n          clear();\n          node_observer_proxy.detach(); \n          throw EdgeNotifier::ImmediateDetach();\n        } else {\n          added_edges.erase(it);\n        }        \n      }\n\n      void attach(ListGraph &_graph) {\n\tgraph = &_graph;\n\tnode_observer_proxy.attach(graph->notifier(Node()));\n        edge_observer_proxy.attach(graph->notifier(Edge()));\n      }\n            \n      void detach() {\n\tnode_observer_proxy.detach();\n\tedge_observer_proxy.detach();\n      }\n\n      bool attached() const {\n        return node_observer_proxy.attached();\n      }\n\n      void clear() {\n        added_nodes.clear();\n        added_edges.clear();        \n      }\n\n    public:\n\n      /// \\brief Default constructor.\n      ///\n      /// Default constructor.\n      /// To actually make a snapshot you must call save().\n      Snapshot() \n        : graph(0), node_observer_proxy(*this), \n          edge_observer_proxy(*this) {}\n      \n      /// \\brief Constructor that immediately makes a snapshot.\n      ///      \n      /// This constructor immediately makes a snapshot of the graph.\n      /// \\param _graph The graph we make a snapshot of.\n      Snapshot(ListGraph &_graph) \n        : node_observer_proxy(*this), \n          edge_observer_proxy(*this) {\n\tattach(_graph);\n      }\n      \n      /// \\brief Make a snapshot.\n      ///\n      /// Make a snapshot of the graph.\n      ///\n      /// This function can be called more than once. In case of a repeated\n      /// call, the previous snapshot gets lost.\n      /// \\param _graph The graph we make the snapshot of.\n      void save(ListGraph &_graph) {\n        if (attached()) {\n          detach();\n          clear();\n        }\n        attach(_graph);\n      }\n      \n      /// \\brief Undo the changes until the last snapshot.\n      // \n      /// Undo the changes until the last snapshot created by save().\n      void restore() {\n\tdetach();\n\tfor(std::list<Edge>::iterator it = added_edges.begin(); \n            it != added_edges.end(); ++it) {\n\t  graph->erase(*it);\n\t}\n\tfor(std::list<Node>::iterator it = added_nodes.begin(); \n            it != added_nodes.end(); ++it) {\n\t  graph->erase(*it);\n\t}\n        clear();\n      }\n\n      /// \\brief Gives back true when the snapshot is valid.\n      ///\n      /// Gives back true when the snapshot is valid.\n      bool valid() const {\n        return attached();\n      }\n    };\n    \n  };\n\n  ///@}\n\n  class ListUGraphBase {\n\n  protected:\n\n    struct NodeT {\n      int first_out;\n      int prev, next;\n    };\n \n    struct EdgeT {\n      int target;\n      int prev_out, next_out;\n    };\n\n    std::vector<NodeT> nodes;\n\n    int first_node;\n\n    int first_free_node;\n\n    std::vector<EdgeT> edges;\n\n    int first_free_edge;\n    \n  public:\n    \n    typedef ListUGraphBase Graph;\n\n    class Node;\n    class Edge;\n    class UEdge;\n    \n    class Node {\n      friend class ListUGraphBase;\n    protected:\n\n      int id;\n      explicit Node(int pid) { id = pid;}\n\n    public:\n      Node() {}\n      Node (Invalid) { id = -1; }\n      bool operator==(const Node& node) const {return id == node.id;}\n      bool operator!=(const Node& node) const {return id != node.id;}\n      bool operator<(const Node& node) const {return id < node.id;}\n    };\n\n    class UEdge {\n      friend class ListUGraphBase;\n    protected:\n\n      int id;\n      explicit UEdge(int pid) { id = pid;}\n\n    public:\n      UEdge() {}\n      UEdge (Invalid) { id = -1; }\n      bool operator==(const UEdge& edge) const {return id == edge.id;}\n      bool operator!=(const UEdge& edge) const {return id != edge.id;}\n      bool operator<(const UEdge& edge) const {return id < edge.id;}\n    };\n\n    class Edge {\n      friend class ListUGraphBase;\n    protected:\n\n      int id;\n      explicit Edge(int pid) { id = pid;}\n\n    public:\n      operator UEdge() const { return uEdgeFromId(id / 2); }\n\n      Edge() {}\n      Edge (Invalid) { id = -1; }\n      bool operator==(const Edge& edge) const {return id == edge.id;}\n      bool operator!=(const Edge& edge) const {return id != edge.id;}\n      bool operator<(const Edge& edge) const {return id < edge.id;}\n    };\n\n\n\n    ListUGraphBase()\n      : nodes(), first_node(-1),\n\tfirst_free_node(-1), edges(), first_free_edge(-1) {}\n\n    \n    int maxNodeId() const { return nodes.size()-1; } \n    int maxUEdgeId() const { return edges.size() / 2 - 1; }\n    int maxEdgeId() const { return edges.size()-1; }\n\n    Node source(Edge e) const { return Node(edges[e.id ^ 1].target); }\n    Node target(Edge e) const { return Node(edges[e.id].target); }\n\n    Node source(UEdge e) const { return Node(edges[2 * e.id].target); }\n    Node target(UEdge e) const { return Node(edges[2 * e.id + 1].target); }\n\n    static bool direction(Edge e) {\n      return (e.id & 1) == 1;\n    }\n\n    static Edge direct(UEdge e, bool d) {\n      return Edge(e.id * 2 + (d ? 1 : 0));\n    }\n\n    void first(Node& node) const { \n      node.id = first_node;\n    }\n\n    void next(Node& node) const {\n      node.id = nodes[node.id].next;\n    }\n\n    void first(Edge& e) const { \n      int n = first_node;\n      while (n != -1 && nodes[n].first_out == -1) {\n        n = nodes[n].next;\n      }\n      e.id = (n == -1) ? -1 : nodes[n].first_out;\n    }\n\n    void next(Edge& e) const {\n      if (edges[e.id].next_out != -1) {\n\te.id = edges[e.id].next_out;\n      } else {\n\tint n = nodes[edges[e.id ^ 1].target].next;\n        while(n != -1 && nodes[n].first_out == -1) {\n          n = nodes[n].next;\n        }\n\te.id = (n == -1) ? -1 : nodes[n].first_out;\n      }      \n    }\n\n    void first(UEdge& e) const { \n      int n = first_node;\n      while (n != -1) {\n        e.id = nodes[n].first_out;\n        while ((e.id & 1) != 1) {\n          e.id = edges[e.id].next_out;\n        }\n        if (e.id != -1) {\n          e.id /= 2;\n          return;\n        } \n        n = nodes[n].next;\n      }\n      e.id = -1;\n    }\n\n    void next(UEdge& e) const {\n      int n = edges[e.id * 2].target;\n      e.id = edges[(e.id * 2) | 1].next_out;\n      while ((e.id & 1) != 1) {\n        e.id = edges[e.id].next_out;\n      }\n      if (e.id != -1) {\n        e.id /= 2;\n        return;\n      } \n      n = nodes[n].next;\n      while (n != -1) {\n        e.id = nodes[n].first_out;\n        while ((e.id & 1) != 1) {\n          e.id = edges[e.id].next_out;\n        }\n        if (e.id != -1) {\n          e.id /= 2;\n          return;\n        } \n        n = nodes[n].next;\n      }\n      e.id = -1;\n    }\n\n    void firstOut(Edge &e, const Node& v) const {\n      e.id = nodes[v.id].first_out;\n    }\n    void nextOut(Edge &e) const {\n      e.id = edges[e.id].next_out;\n    }\n\n    void firstIn(Edge &e, const Node& v) const {\n      e.id = ((nodes[v.id].first_out) ^ 1);\n      if (e.id == -2) e.id = -1;\n    }\n    void nextIn(Edge &e) const {\n      e.id = ((edges[e.id ^ 1].next_out) ^ 1);\n      if (e.id == -2) e.id = -1;\n    }\n\n    void firstInc(UEdge &e, bool& d, const Node& v) const {\n      int de = nodes[v.id].first_out;\n      if (de != -1 ) {\n        e.id = de / 2;\n        d = ((de & 1) == 1);\n      } else {\n        e.id = -1;\n        d = true;\n      }\n    }\n    void nextInc(UEdge &e, bool& d) const {\n      int de = (edges[(e.id * 2) | (d ? 1 : 0)].next_out);\n      if (de != -1 ) {\n        e.id = de / 2;\n        d = ((de & 1) == 1);\n      } else {\n        e.id = -1;\n        d = true;\n      }\n    }\n    \n    static int id(Node v) { return v.id; }\n    static int id(Edge e) { return e.id; }\n    static int id(UEdge e) { return e.id; }\n\n    static Node nodeFromId(int id) { return Node(id);}\n    static Edge edgeFromId(int id) { return Edge(id);}\n    static UEdge uEdgeFromId(int id) { return UEdge(id);}\n\n    Node addNode() {     \n      int n;\n      \n      if(first_free_node==-1) {\n\tn = nodes.size();\n\tnodes.push_back(NodeT());\n      } else {\n\tn = first_free_node;\n\tfirst_free_node = nodes[n].next;\n      }\n      \n      nodes[n].next = first_node;\n      if (first_node != -1) nodes[first_node].prev = n;\n      first_node = n;\n      nodes[n].prev = -1;\n      \n      nodes[n].first_out = -1;\n      \n      return Node(n);\n    }\n    \n    UEdge addEdge(Node u, Node v) {\n      int n;      \n\n      if (first_free_edge == -1) {\n\tn = edges.size();\n\tedges.push_back(EdgeT());\n\tedges.push_back(EdgeT());\n      } else {\n\tn = first_free_edge;\n\tfirst_free_edge = edges[n].next_out;\n      }\n      \n      edges[n].target = u.id;\n      edges[n | 1].target = v.id;\n\n      edges[n].next_out = nodes[v.id].first_out;\n      if (nodes[v.id].first_out != -1) {\n\tedges[nodes[v.id].first_out].prev_out = n;\n      }      \n      edges[n].prev_out = -1;\n      nodes[v.id].first_out = n;\n      \n      edges[n | 1].next_out = nodes[u.id].first_out;\n      if (nodes[u.id].first_out != -1) {\n\tedges[nodes[u.id].first_out].prev_out = (n | 1);\n      }\n      edges[n | 1].prev_out = -1;      \n      nodes[u.id].first_out = (n | 1);\n\n      return UEdge(n / 2);\n    }\n    \n    void erase(const Node& node) {\n      int n = node.id;\n      \n      if(nodes[n].next != -1) {\n\tnodes[nodes[n].next].prev = nodes[n].prev;\n      }\n      \n      if(nodes[n].prev != -1) {\n\tnodes[nodes[n].prev].next = nodes[n].next;\n      } else {\n\tfirst_node = nodes[n].next;\n      }\n      \n      nodes[n].next = first_free_node;\n      first_free_node = n;\n\n    }\n    \n    void erase(const UEdge& edge) {\n      int n = edge.id * 2;\n      \n      if (edges[n].next_out != -1) {\n\tedges[edges[n].next_out].prev_out = edges[n].prev_out;\n      } \n\n      if (edges[n].prev_out != -1) {\n\tedges[edges[n].prev_out].next_out = edges[n].next_out;\n      } else {\n\tnodes[edges[n | 1].target].first_out = edges[n].next_out;\n      }\n\n      if (edges[n | 1].next_out != -1) {\n\tedges[edges[n | 1].next_out].prev_out = edges[n | 1].prev_out;\n      } \n\n      if (edges[n | 1].prev_out != -1) {\n\tedges[edges[n | 1].prev_out].next_out = edges[n | 1].next_out;\n      } else {\n\tnodes[edges[n].target].first_out = edges[n | 1].next_out;\n      }\n      \n      edges[n].next_out = first_free_edge;\n      first_free_edge = n;      \n\n    }\n\n    void clear() {\n      edges.clear();\n      nodes.clear();\n      first_node = first_free_node = first_free_edge = -1;\n    }\n\n  protected:\n\n    void changeTarget(UEdge e, Node n) {\n      if(edges[2 * e.id].next_out != -1) {\n\tedges[edges[2 * e.id].next_out].prev_out = edges[2 * e.id].prev_out;\n      }\n      if(edges[2 * e.id].prev_out != -1) {\n\tedges[edges[2 * e.id].prev_out].next_out = \n          edges[2 * e.id].next_out;\n      } else {\n        nodes[edges[(2 * e.id) | 1].target].first_out = \n          edges[2 * e.id].next_out;\n      }\n\n      if (nodes[n.id].first_out != -1) {\n\tedges[nodes[n.id].first_out].prev_out = 2 * e.id;\n      }\n      edges[(2 * e.id) | 1].target = n.id;\n      edges[2 * e.id].prev_out = -1;\n      edges[2 * e.id].next_out = nodes[n.id].first_out;\n      nodes[n.id].first_out = 2 * e.id;\n    }\n\n    void changeSource(UEdge e, Node n) {\n      if(edges[(2 * e.id) | 1].next_out != -1) {\n\tedges[edges[(2 * e.id) | 1].next_out].prev_out = \n          edges[(2 * e.id) | 1].prev_out;\n      }\n      if(edges[(2 * e.id) | 1].prev_out != -1) {\n\tedges[edges[(2 * e.id) | 1].prev_out].next_out = \n          edges[(2 * e.id) | 1].next_out;\n      } else {\n        nodes[edges[2 * e.id].target].first_out = \n          edges[(2 * e.id) | 1].next_out;\n      }\n\n      if (nodes[n.id].first_out != -1) {\n\tedges[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1);\n      }\n      edges[2 * e.id].target = n.id;\n      edges[(2 * e.id) | 1].prev_out = -1;\n      edges[(2 * e.id) | 1].next_out = nodes[n.id].first_out;\n      nodes[n.id].first_out = ((2 * e.id) | 1);\n    }\n\n  };\n\n//   typedef UGraphExtender<UndirGraphExtender<ListGraphBase> > \n//   ExtendedListUGraphBase;\n\n  typedef UGraphExtender<ListUGraphBase> ExtendedListUGraphBase;\n\n\n\n  /// \\addtogroup graphs\n  /// @{\n\n  ///An undirected list graph class.\n\n  ///This is a simple and fast undirected graph implementation.\n  ///\n  ///An important extra feature of this graph implementation is that\n  ///its maps are real \\ref concepts::ReferenceMap \"reference map\"s.\n  ///\n  ///It conforms to the\n  ///\\ref concepts::UGraph \"UGraph concept\".\n  ///\n  ///\\sa concepts::UGraph.\n  ///\n  class ListUGraph : public ExtendedListUGraphBase {\n  private:\n    ///ListUGraph is \\e not copy constructible. Use UGraphCopy() instead.\n\n    ///ListUGraph is \\e not copy constructible. Use UGraphCopy() instead.\n    ///\n    ListUGraph(const ListUGraph &) :ExtendedListUGraphBase()  {};\n    ///\\brief Assignment of ListUGraph to another one is \\e not allowed.\n    ///Use UGraphCopy() instead.\n\n    ///Assignment of ListUGraph to another one is \\e not allowed.\n    ///Use UGraphCopy() instead.\n    void operator=(const ListUGraph &) {}\n  public:\n    /// Constructor\n    \n    /// Constructor.\n    ///\n    ListUGraph() {}\n\n    typedef ExtendedListUGraphBase Parent;\n\n    typedef Parent::OutEdgeIt IncEdgeIt;\n\n    /// \\brief Add a new node to the graph.\n    ///\n    /// \\return the new node.\n    ///\n    Node addNode() { return Parent::addNode(); }\n\n    /// \\brief Add a new edge to the graph.\n    ///\n    /// Add a new edge to the graph with source node \\c s\n    /// and target node \\c t.\n    /// \\return the new undirected edge.\n    UEdge addEdge(const Node& s, const Node& t) { \n      return Parent::addEdge(s, t); \n    }\n    /// \\brief Changes the source of \\c e to \\c n\n    ///\n    /// Changes the source of \\c e to \\c n\n    ///\n    ///\\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s\n    ///referencing the changed edge remain\n    ///valid. However <tt>OutEdgeIt</tt>s are invalidated.\n    void changeSource(UEdge e, Node n) { \n      Parent::changeSource(e,n); \n    }    \n    /// \\brief Changes the target of \\c e to \\c n\n    ///\n    /// Changes the target of \\c e to \\c n\n    ///\n    /// \\note The <tt>EdgeIt</tt>s referencing the changed edge remain\n    /// valid. However the other iterators may be invalidated.\n    void changeTarget(UEdge e, Node n) { \n      Parent::changeTarget(e,n); \n    }\n    /// \\brief Changes the source of \\c e to \\c n\n    ///\n    /// Changes the source of \\c e to \\c n. It changes the proper\n    /// node of the represented undirected edge.\n    ///\n    ///\\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s\n    ///referencing the changed edge remain\n    ///valid. However <tt>OutEdgeIt</tt>s are invalidated.\n    void changeSource(Edge e, Node n) { \n      if (Parent::direction(e)) {\n        Parent::changeSource(e,n);\n      } else {\n        Parent::changeTarget(e,n);\n      } \n    }\n    /// \\brief Changes the target of \\c e to \\c n\n    ///\n    /// Changes the target of \\c e to \\c n. It changes the proper\n    /// node of the represented undirected edge.\n    ///\n    ///\\note The <tt>EdgeIt</tt>s and <tt>OutEdgeIt</tt>s\n    ///referencing the changed edge remain\n    ///valid. However <tt>InEdgeIt</tt>s are invalidated.\n    void changeTarget(Edge e, Node n) { \n      if (Parent::direction(e)) {\n        Parent::changeTarget(e,n);\n      } else {\n        Parent::changeSource(e,n);\n      } \n    }\n    /// \\brief Contract two nodes.\n    ///\n    /// This function contracts two nodes.\n    ///\n    /// Node \\p b will be removed but instead of deleting\n    /// its neighboring edges, they will be joined to \\p a.\n    /// The last parameter \\p r controls whether to remove loops. \\c true\n    /// means that loops will be removed.\n    ///\n    /// \\note The <tt>EdgeIt</tt>s referencing a moved edge remain\n    /// valid.\n    void contract(Node a, Node b, bool r = true) {\n      for(IncEdgeIt e(*this, b); e!=INVALID;) {\n\tIncEdgeIt f = e; ++f;\n\tif (r && runningNode(e) == a) {\n\t  erase(e);\n\t} else if (source(e) == b) {\n\t  changeSource(e, a);\n\t} else {\n\t  changeTarget(e, a);\n\t}\n\te = f;\n      }\n      erase(b);\n    }\n\n\n    /// \\brief Class to make a snapshot of the graph and restore\n    /// to it later.\n    ///\n    /// Class to make a snapshot of the graph and to restore it\n    /// later.\n    ///\n    /// The newly added nodes and undirected edges can be removed\n    /// using the restore() function.\n    ///\n    /// \\warning Edge and node deletions cannot be restored. This\n    /// events invalidate the snapshot. \n    class Snapshot {\n    protected:\n\n      typedef Parent::NodeNotifier NodeNotifier;\n\n      class NodeObserverProxy : public NodeNotifier::ObserverBase {\n      public:\n\n        NodeObserverProxy(Snapshot& _snapshot)\n          : snapshot(_snapshot) {}\n\n        using NodeNotifier::ObserverBase::attach;\n        using NodeNotifier::ObserverBase::detach;\n        using NodeNotifier::ObserverBase::attached;\n        \n      protected:\n        \n        virtual void add(const Node& node) {\n          snapshot.addNode(node);\n        }\n        virtual void add(const std::vector<Node>& nodes) {\n          for (int i = nodes.size() - 1; i >= 0; ++i) {\n            snapshot.addNode(nodes[i]);\n          }\n        }\n        virtual void erase(const Node& node) {\n          snapshot.eraseNode(node);\n        }\n        virtual void erase(const std::vector<Node>& nodes) {\n          for (int i = 0; i < int(nodes.size()); ++i) {\n            snapshot.eraseNode(nodes[i]);\n          }\n        }\n        virtual void build() {\n          Node node;\n          std::vector<Node> nodes;\n          for (notifier()->first(node); node != INVALID; \n               notifier()->next(node)) {\n            nodes.push_back(node);\n          }\n          for (int i = nodes.size() - 1; i >= 0; --i) {\n            snapshot.addNode(nodes[i]);\n          }\n        }\n        virtual void clear() {\n          Node node;\n          for (notifier()->first(node); node != INVALID; \n               notifier()->next(node)) {\n            snapshot.eraseNode(node);\n          }\n        }\n\n        Snapshot& snapshot;\n      };\n\n      class UEdgeObserverProxy : public UEdgeNotifier::ObserverBase {\n      public:\n\n        UEdgeObserverProxy(Snapshot& _snapshot)\n          : snapshot(_snapshot) {}\n\n        using UEdgeNotifier::ObserverBase::attach;\n        using UEdgeNotifier::ObserverBase::detach;\n        using UEdgeNotifier::ObserverBase::attached;\n        \n      protected:\n\n        virtual void add(const UEdge& edge) {\n          snapshot.addUEdge(edge);\n        }\n        virtual void add(const std::vector<UEdge>& edges) {\n          for (int i = edges.size() - 1; i >= 0; ++i) {\n            snapshot.addUEdge(edges[i]);\n          }\n        }\n        virtual void erase(const UEdge& edge) {\n          snapshot.eraseUEdge(edge);\n        }\n        virtual void erase(const std::vector<UEdge>& edges) {\n          for (int i = 0; i < int(edges.size()); ++i) {\n            snapshot.eraseUEdge(edges[i]);\n          }\n        }\n        virtual void build() {\n          UEdge edge;\n          std::vector<UEdge> edges;\n          for (notifier()->first(edge); edge != INVALID; \n               notifier()->next(edge)) {\n            edges.push_back(edge);\n          }\n          for (int i = edges.size() - 1; i >= 0; --i) {\n            snapshot.addUEdge(edges[i]);\n          }\n        }\n        virtual void clear() {\n          UEdge edge;\n          for (notifier()->first(edge); edge != INVALID; \n               notifier()->next(edge)) {\n            snapshot.eraseUEdge(edge);\n          }\n        }\n\n        Snapshot& snapshot;\n      };\n      \n      ListUGraph *graph;\n\n      NodeObserverProxy node_observer_proxy;\n      UEdgeObserverProxy edge_observer_proxy;\n\n      std::list<Node> added_nodes;\n      std::list<UEdge> added_edges;\n\n\n      void addNode(const Node& node) {\n        added_nodes.push_front(node);        \n      }\n      void eraseNode(const Node& node) {\n        std::list<Node>::iterator it = \n          std::find(added_nodes.begin(), added_nodes.end(), node);\n        if (it == added_nodes.end()) {\n          clear();\n          edge_observer_proxy.detach();\n          throw NodeNotifier::ImmediateDetach();\n        } else {\n          added_nodes.erase(it);\n        }\n      }\n\n      void addUEdge(const UEdge& edge) {\n        added_edges.push_front(edge);        \n      }\n      void eraseUEdge(const UEdge& edge) {\n        std::list<UEdge>::iterator it = \n          std::find(added_edges.begin(), added_edges.end(), edge);\n        if (it == added_edges.end()) {\n          clear();\n          node_observer_proxy.detach();\n          throw UEdgeNotifier::ImmediateDetach();\n        } else {\n          added_edges.erase(it);\n        }        \n      }\n\n      void attach(ListUGraph &_graph) {\n\tgraph = &_graph;\n\tnode_observer_proxy.attach(graph->notifier(Node()));\n        edge_observer_proxy.attach(graph->notifier(UEdge()));\n      }\n            \n      void detach() {\n\tnode_observer_proxy.detach();\n\tedge_observer_proxy.detach();\n      }\n\n      bool attached() const {\n        return node_observer_proxy.attached();\n      }\n\n      void clear() {\n        added_nodes.clear();\n        added_edges.clear();        \n      }\n\n    public:\n\n      /// \\brief Default constructor.\n      ///\n      /// Default constructor.\n      /// To actually make a snapshot you must call save().\n      Snapshot() \n        : graph(0), node_observer_proxy(*this), \n          edge_observer_proxy(*this) {}\n      \n      /// \\brief Constructor that immediately makes a snapshot.\n      ///      \n      /// This constructor immediately makes a snapshot of the graph.\n      /// \\param _graph The graph we make a snapshot of.\n      Snapshot(ListUGraph &_graph) \n        : node_observer_proxy(*this), \n          edge_observer_proxy(*this) {\n\tattach(_graph);\n      }\n      \n      /// \\brief Make a snapshot.\n      ///\n      /// Make a snapshot of the graph.\n      ///\n      /// This function can be called more than once. In case of a repeated\n      /// call, the previous snapshot gets lost.\n      /// \\param _graph The graph we make the snapshot of.\n      void save(ListUGraph &_graph) {\n        if (attached()) {\n          detach();\n          clear();\n        }\n        attach(_graph);\n      }\n      \n      /// \\brief Undo the changes until the last snapshot.\n      // \n      /// Undo the changes until the last snapshot created by save().\n      void restore() {\n\tdetach();\n\tfor(std::list<UEdge>::iterator it = added_edges.begin(); \n            it != added_edges.end(); ++it) {\n\t  graph->erase(*it);\n\t}\n\tfor(std::list<Node>::iterator it = added_nodes.begin(); \n            it != added_nodes.end(); ++it) {\n\t  graph->erase(*it);\n\t}\n        clear();\n      }\n\n      /// \\brief Gives back true when the snapshot is valid.\n      ///\n      /// Gives back true when the snapshot is valid.\n      bool valid() const {\n        return attached();\n      }\n    };\n  };\n\n\n  class ListBpUGraphBase {\n  public:\n\n    class NodeSetError : public LogicError {\n    public:\n      virtual const char* what() const throw() { \n\treturn \"lemon::ListBpUGraph::NodeSetError\";\n      }\n    };\n\n  protected:\n\n    struct NodeT {\n      int first_edge, prev, next;\n    };\n\n    struct UEdgeT {\n      int aNode, prev_out, next_out;\n      int bNode, prev_in, next_in;\n    };\n\n    std::vector<NodeT> aNodes;\n    std::vector<NodeT> bNodes;\n\n    std::vector<UEdgeT> edges;\n\n    int first_anode;\n    int first_free_anode;\n\n    int first_bnode;\n    int first_free_bnode;\n\n    int first_free_edge;\n\n  public:\n  \n    class Node {\n      friend class ListBpUGraphBase;\n    protected:\n      int id;\n\n      explicit Node(int _id) : id(_id) {}\n    public:\n      Node() {}\n      Node(Invalid) { id = -1; }\n      bool operator==(const Node i) const {return id==i.id;}\n      bool operator!=(const Node i) const {return id!=i.id;}\n      bool operator<(const Node i) const {return id<i.id;}\n    };\n\n    class UEdge {\n      friend class ListBpUGraphBase;\n    protected:\n      int id;\n\n      explicit UEdge(int _id) { id = _id;}\n    public:\n      UEdge() {}\n      UEdge (Invalid) { id = -1; }\n      bool operator==(const UEdge i) const {return id==i.id;}\n      bool operator!=(const UEdge i) const {return id!=i.id;}\n      bool operator<(const UEdge i) const {return id<i.id;}\n    };\n\n    ListBpUGraphBase()\n      : first_anode(-1), first_free_anode(-1),\n        first_bnode(-1), first_free_bnode(-1),\n        first_free_edge(-1) {}\n\n    void firstANode(Node& node) const {\n      node.id = first_anode != -1 ? (first_anode << 1) : -1;\n    }\n    void nextANode(Node& node) const {\n      node.id = aNodes[node.id >> 1].next;\n    }\n\n    void firstBNode(Node& node) const {\n      node.id = first_bnode != -1 ? (first_bnode << 1) + 1 : -1;\n    }\n    void nextBNode(Node& node) const {\n      node.id = bNodes[node.id >> 1].next;\n    }\n\n    void first(Node& node) const {\n      if (first_anode != -1) {\n        node.id = (first_anode << 1);\n      } else if (first_bnode != -1) {\n        node.id = (first_bnode << 1) + 1;\n      } else {\n        node.id = -1;\n      }\n    }\n    void next(Node& node) const {\n      if (aNode(node)) {\n        node.id = aNodes[node.id >> 1].next;\n        if (node.id == -1) {\n          if (first_bnode != -1) {\n            node.id = (first_bnode << 1) + 1;\n          }\n        }\n      } else {\n        node.id = bNodes[node.id >> 1].next;\n      }\n    }\n  \n    void first(UEdge& edge) const {\n      int aid = first_anode;\n      while (aid != -1 && aNodes[aid].first_edge == -1) {\n        aid = aNodes[aid].next != -1 ? \n          aNodes[aid].next >> 1 : -1;\n      }\n      if (aid != -1) {\n        edge.id = aNodes[aid].first_edge;\n      } else {\n        edge.id = -1;\n      }\n    }\n    void next(UEdge& edge) const {\n      int aid = edges[edge.id].aNode >> 1;\n      edge.id = edges[edge.id].next_out;\n      if (edge.id == -1) {\n        aid = aNodes[aid].next != -1 ? \n          aNodes[aid].next >> 1 : -1;\n        while (aid != -1 && aNodes[aid].first_edge == -1) {\n          aid = aNodes[aid].next != -1 ? \n          aNodes[aid].next >> 1 : -1;\n        }\n        if (aid != -1) {\n          edge.id = aNodes[aid].first_edge;\n        } else {\n          edge.id = -1;\n        }\n      }\n    }\n\n    void firstFromANode(UEdge& edge, const Node& node) const {\n      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());\n      edge.id = aNodes[node.id >> 1].first_edge;\n    }\n    void nextFromANode(UEdge& edge) const {\n      edge.id = edges[edge.id].next_out;\n    }\n\n    void firstFromBNode(UEdge& edge, const Node& node) const {\n      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());\n      edge.id = bNodes[node.id >> 1].first_edge;\n    }\n    void nextFromBNode(UEdge& edge) const {\n      edge.id = edges[edge.id].next_in;\n    }\n\n    static int id(const Node& node) {\n      return node.id;\n    }\n    static Node nodeFromId(int id) {\n      return Node(id);\n    }\n    int maxNodeId() const {\n      return aNodes.size() > bNodes.size() ?\n\taNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;\n    }\n  \n    static int id(const UEdge& edge) {\n      return edge.id;\n    }\n    static UEdge uEdgeFromId(int id) {\n      return UEdge(id);\n    }\n    int maxUEdgeId() const {\n      return edges.size();\n    }\n  \n    static int aNodeId(const Node& node) {\n      return node.id >> 1;\n    }\n    static Node nodeFromANodeId(int id) {\n      return Node(id << 1);\n    }\n    int maxANodeId() const {\n      return aNodes.size();\n    }\n\n    static int bNodeId(const Node& node) {\n      return node.id >> 1;\n    }\n    static Node nodeFromBNodeId(int id) {\n      return Node((id << 1) + 1);\n    }\n    int maxBNodeId() const {\n      return bNodes.size();\n    }\n\n    Node aNode(const UEdge& edge) const {\n      return Node(edges[edge.id].aNode);\n    }\n    Node bNode(const UEdge& edge) const {\n      return Node(edges[edge.id].bNode);\n    }\n\n    static bool aNode(const Node& node) {\n      return (node.id & 1) == 0;\n    }\n\n    static bool bNode(const Node& node) {\n      return (node.id & 1) == 1;\n    }\n\n    Node addANode() {\n      int aid;\n      if (first_free_anode == -1) {\n        aid = aNodes.size();\n        aNodes.push_back(NodeT());\n      } else {\n        aid = first_free_anode;\n        first_free_anode = aNodes[first_free_anode].next;\n      }\n      if (first_anode != -1) {\n        aNodes[aid].next = first_anode << 1;\n        aNodes[first_anode].prev = aid << 1;\n      } else {\n        aNodes[aid].next = -1;\n      }\n      aNodes[aid].prev = -1;\n      first_anode = aid;\n      aNodes[aid].first_edge = -1;\n      return Node(aid << 1);\n    }\n\n    Node addBNode() {\n      int bid;\n      if (first_free_bnode == -1) {\n        bid = bNodes.size();\n        bNodes.push_back(NodeT());\n      } else {\n        bid = first_free_bnode;\n        first_free_bnode = bNodes[first_free_bnode].next;\n      }\n      if (first_bnode != -1) {\n        bNodes[bid].next = (first_bnode << 1) + 1;\n        bNodes[first_bnode].prev = (bid << 1) + 1;\n      } else {\n        bNodes[bid].next = -1;\n      }\n      bNodes[bid].prev = -1;\n      first_bnode = bid;\n      bNodes[bid].first_edge = -1;\n      return Node((bid << 1) + 1);\n    }\n\n    UEdge addEdge(const Node& source, const Node& target) {\n      LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());\n      int edgeId;\n      if (first_free_edge != -1) {\n        edgeId = first_free_edge;\n        first_free_edge = edges[edgeId].next_out;\n      } else {\n        edgeId = edges.size();\n        edges.push_back(UEdgeT());\n      }\n      if ((source.id & 1) == 0) {\n\tedges[edgeId].aNode = source.id;\n\tedges[edgeId].bNode = target.id;\n      } else {\n\tedges[edgeId].aNode = target.id;\n\tedges[edgeId].bNode = source.id;\n      }\n      edges[edgeId].next_out = aNodes[edges[edgeId].aNode >> 1].first_edge;\n      edges[edgeId].prev_out = -1;\n      if (aNodes[edges[edgeId].aNode >> 1].first_edge != -1) {\n        edges[aNodes[edges[edgeId].aNode >> 1].first_edge].prev_out = edgeId;\n      }\n      aNodes[edges[edgeId].aNode >> 1].first_edge = edgeId;\n      edges[edgeId].next_in = bNodes[edges[edgeId].bNode >> 1].first_edge;\n      edges[edgeId].prev_in = -1;\n      if (bNodes[edges[edgeId].bNode >> 1].first_edge != -1) {\n        edges[bNodes[edges[edgeId].bNode >> 1].first_edge].prev_in = edgeId;\n      }\n      bNodes[edges[edgeId].bNode >> 1].first_edge = edgeId;\n      return UEdge(edgeId);\n    }\n\n    void erase(const Node& node) {\n      if (aNode(node)) {\n        int aid = node.id >> 1;\n        if (aNodes[aid].prev != -1) {\n          aNodes[aNodes[aid].prev >> 1].next = aNodes[aid].next;\n        } else {\n          first_anode = \n            aNodes[aid].next != -1 ? aNodes[aid].next >> 1 : -1;\n        }\n        if (aNodes[aid].next != -1) {\n          aNodes[aNodes[aid].next >> 1].prev = aNodes[aid].prev;\n        }\n        aNodes[aid].next = first_free_anode;\n        first_free_anode = aid;\n      } else {\n        int bid = node.id >> 1;\n        if (bNodes[bid].prev != -1) {\n          bNodes[bNodes[bid].prev >> 1].next = bNodes[bid].next;\n        } else {\n          first_bnode = \n            bNodes[bid].next != -1 ? bNodes[bid].next >> 1 : -1;\n        }\n        if (bNodes[bid].next != -1) {\n          bNodes[bNodes[bid].next >> 1].prev = bNodes[bid].prev;\n        }\n        bNodes[bid].next = first_free_bnode;\n        first_free_bnode = bid;\n      }\n    }\n\n    void erase(const UEdge& edge) {\n\n      if (edges[edge.id].prev_out != -1) {\n        edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out;\n      } else {\n        aNodes[edges[edge.id].aNode >> 1].first_edge = edges[edge.id].next_out;\n      }\n      if (edges[edge.id].next_out != -1) {\n        edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out;\n      }\n\n      if (edges[edge.id].prev_in != -1) {\n        edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in;\n      } else {\n        bNodes[edges[edge.id].bNode >> 1].first_edge = edges[edge.id].next_in;\n      }\n      if (edges[edge.id].next_in != -1) {\n        edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in;\n      }\n\n      edges[edge.id].next_out = first_free_edge;\n      first_free_edge = edge.id;\n    }\n \n    void clear() {\n      aNodes.clear();\n      bNodes.clear();\n      edges.clear();\n      first_anode = -1;\n      first_free_anode = -1;\n      first_bnode = -1;\n      first_free_bnode = -1;\n      first_free_edge = -1;\n    }\n\n    void changeANode(const UEdge& edge, const Node& node) {\n      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());\n      if (edges[edge.id].prev_out != -1) {\n        edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out;\n      } else {\n        aNodes[edges[edge.id].aNode >> 1].first_edge = edges[edge.id].next_out;\n      }\n      if (edges[edge.id].next_out != -1) {\n        edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out;  \n      }\n      if (aNodes[node.id >> 1].first_edge != -1) {\n        edges[aNodes[node.id >> 1].first_edge].prev_out = edge.id;\n      }\n      edges[edge.id].prev_out = -1;\n      edges[edge.id].next_out = aNodes[node.id >> 1].first_edge;\n      aNodes[node.id >> 1].first_edge = edge.id;\n      edges[edge.id].aNode = node.id;\n    } \n\n    void changeBNode(const UEdge& edge, const Node& node) {\n      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());\n      if (edges[edge.id].prev_in != -1) {\n        edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in;\n      } else {\n        bNodes[edges[edge.id].bNode >> 1].first_edge = edges[edge.id].next_in;\n      }\n      if (edges[edge.id].next_in != -1) {\n        edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in;  \n      }\n      if (bNodes[node.id >> 1].first_edge != -1) {\n        edges[bNodes[node.id >> 1].first_edge].prev_in = edge.id;\n      }\n      edges[edge.id].prev_in = -1;\n      edges[edge.id].next_in = bNodes[node.id >> 1].first_edge;\n      bNodes[node.id >> 1].first_edge = edge.id;\n      edges[edge.id].bNode = node.id;\n    } \n\n  };\n\n\n  typedef BpUGraphExtender<BidirBpUGraphExtender<ListBpUGraphBase> > \n  ExtendedListBpUGraphBase;\n\n  /// \\ingroup graphs\n  ///\n  /// \\brief A smart bipartite undirected graph class.\n  ///\n  /// This is a bipartite undirected graph implementation.\n  /// It is conforms to the \\ref concepts::BpUGraph \"BpUGraph concept\".\n  ///\n  ///An important extra feature of this graph implementation is that\n  ///its maps are real \\ref concepts::ReferenceMap \"reference map\"s.\n  ///\n  /// \\sa concepts::BpUGraph.\n  ///\n  class ListBpUGraph : public ExtendedListBpUGraphBase {\n    /// \\brief ListBpUGraph is \\e not copy constructible.\n    ///\n    ///ListBpUGraph is \\e not copy constructible.\n    ListBpUGraph(const ListBpUGraph &) :ExtendedListBpUGraphBase()  {};\n    /// \\brief Assignment of ListBpUGraph to another one is \\e not\n    /// allowed.\n    ///\n    /// Assignment of ListBpUGraph to another one is \\e not allowed.\n    void operator=(const ListBpUGraph &) {}\n  public:\n    /// \\brief Constructor\n    ///    \n    /// Constructor.\n    ///\n    ListBpUGraph() {}\n\n    typedef ExtendedListBpUGraphBase Parent;\n    /// \\brief Add a new ANode to the graph.\n    ///\n    /// \\return the new node.\n    ///\n    Node addANode() { return Parent::addANode(); }\n\n    /// \\brief Add a new BNode to the graph.\n    ///\n    /// \\return the new node.\n    ///\n    Node addBNode() { return Parent::addBNode(); }\n\n    /// \\brief Add a new edge to the graph.\n    ///\n    /// Add a new edge to the graph with an ANode and a BNode.\n    /// \\return the new undirected edge.\n    UEdge addEdge(const Node& s, const Node& t) { \n      return Parent::addEdge(s, t); \n    }\n\n    /// \\brief Changes the ANode of \\c e to \\c n\n    ///\n    /// Changes the ANode of \\c e to \\c n\n    ///\n    ///\\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s referencing\n    ///the changed edge remain valid. However <tt>OutEdgeIt</tt>s are\n    ///invalidated.\n    void changeANode(UEdge e, Node n) { \n      Parent::changeANode(e,n); \n    }\n\n    /// \\brief Changes the BNode of \\c e to \\c n\n    ///\n    /// Changes the BNode of \\c e to \\c n\n    ///\n    /// \\note The <tt>EdgeIt</tt>s and <tt>OutEdgeIt</tt>s\n    /// referencing the changed edge remain\n    /// valid. However <tt>InEdgeIt</tt>s are invalidated.\n    void changeBNode(UEdge e, Node n) { \n      Parent::changeBNode(e,n); \n    }\n\n    /// \\brief Changes the source(ANode) of \\c e to \\c n\n    ///\n    /// Changes the source(ANode) of \\c e to \\c n\n    ///\n    ///\\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s referencing\n    ///the changed edge remain valid. However <tt>OutEdgeIt</tt>s are\n    ///invalidated.\n    void changeSource(UEdge e, Node n) { \n      Parent::changeANode(e,n); \n    }\n\n    /// \\brief Changes the target(BNode) of \\c e to \\c n\n    ///\n    /// Changes the target(BNode) of \\c e to \\c n\n    ///\n    /// \\note The <tt>EdgeIt</tt>s and <tt>OutEdgeIt</tt>s\n    /// referencing the changed edge remain\n    /// valid. However <tt>InEdgeIt</tt>s are invalidated.\n    void changeTarget(UEdge e, Node n) { \n      Parent::changeBNode(e,n); \n    }\n\n    /// \\brief Changes the source of \\c e to \\c n\n    ///\n    /// Changes the source of \\c e to \\c n. It changes the proper\n    /// node of the represented undirected edge.\n    ///\n    ///\\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s\n    ///referencing the changed edge remain\n    ///valid. However <tt>OutEdgeIt</tt>s are invalidated.\n    void changeSource(Edge e, Node n) { \n      if (Parent::direction(e)) {\n        Parent::changeANode(e,n);\n      } else {\n        Parent::changeBNode(e,n);\n      } \n    }\n    /// \\brief Changes the target of \\c e to \\c n\n    ///\n    /// Changes the target of \\c e to \\c n. It changes the proper\n    /// node of the represented undirected edge.\n    ///\n    ///\\note The <tt>EdgeIt</tt>s and <tt>OutEdgeIt</tt>s\n    ///referencing the changed edge remain\n    ///valid. However <tt>InEdgeIt</tt>s are invalidated.\n    void changeTarget(Edge e, Node n) { \n      if (Parent::direction(e)) {\n        Parent::changeBNode(e,n);\n      } else {\n        Parent::changeANode(e,n);\n      } \n    }\n    /// \\brief Contract two nodes.\n    ///\n    /// This function contracts two nodes.\n    ///\n    /// Node \\p b will be removed but instead of deleting its\n    /// neighboring edges, they will be joined to \\p a.  The two nodes\n    /// should be from the same nodeset, of course.\n    ///\n    /// \\note The <tt>EdgeIt</tt>s referencing a moved edge remain\n    /// valid.\n    void contract(const Node& a, const Node& b) {\n      LEMON_ASSERT(Parent::aNode(a) == Parent::aNode(b), NodeSetError());\n      if (Parent::aNode(a)) {\n        for (IncEdgeIt e(*this, b); e!=INVALID;) {\n          IncEdgeIt f = e; ++f;\n          changeSource(e, a);\n          e = f;\n        }\n      } else {\n        for (IncEdgeIt e(*this, b); e!=INVALID;) {\n          IncEdgeIt f = e; ++f;\n          changeTarget(e, a);\n          e = f;\n        }\n      }\n      erase(b);\n    }\n\n    /// \\brief Class to make a snapshot of the graph and restore\n    /// to it later.\n    ///\n    /// Class to make a snapshot of the graph and to restore it\n    /// later.\n    ///\n    /// The newly added nodes and undirected edges can be removed\n    /// using the restore() function.\n    ///\n    /// \\warning Edge and node deletions cannot be restored. This\n    /// events invalidate the snapshot. \n    class Snapshot {\n    protected:\n\n      typedef Parent::NodeNotifier NodeNotifier;\n\n      class NodeObserverProxy : public NodeNotifier::ObserverBase {\n      public:\n\n        NodeObserverProxy(Snapshot& _snapshot)\n          : snapshot(_snapshot) {}\n\n        using NodeNotifier::ObserverBase::attach;\n        using NodeNotifier::ObserverBase::detach;\n        using NodeNotifier::ObserverBase::attached;\n        \n      protected:\n        \n        virtual void add(const Node& node) {\n          snapshot.addNode(node);\n        }\n        virtual void add(const std::vector<Node>& nodes) {\n          for (int i = nodes.size() - 1; i >= 0; ++i) {\n            snapshot.addNode(nodes[i]);\n          }\n        }\n        virtual void erase(const Node& node) {\n          snapshot.eraseNode(node);\n        }\n        virtual void erase(const std::vector<Node>& nodes) {\n          for (int i = 0; i < int(nodes.size()); ++i) {\n            snapshot.eraseNode(nodes[i]);\n          }\n        }\n        virtual void build() {\n          Node node;\n          std::vector<Node> nodes;\n          for (notifier()->first(node); node != INVALID; \n               notifier()->next(node)) {\n            nodes.push_back(node);\n          }\n          for (int i = nodes.size() - 1; i >= 0; --i) {\n            snapshot.addNode(nodes[i]);\n          }\n        }\n        virtual void clear() {\n          Node node;\n          for (notifier()->first(node); node != INVALID; \n               notifier()->next(node)) {\n            snapshot.eraseNode(node);\n          }\n        }\n\n        Snapshot& snapshot;\n      };\n\n      class UEdgeObserverProxy : public UEdgeNotifier::ObserverBase {\n      public:\n\n        UEdgeObserverProxy(Snapshot& _snapshot)\n          : snapshot(_snapshot) {}\n\n        using UEdgeNotifier::ObserverBase::attach;\n        using UEdgeNotifier::ObserverBase::detach;\n        using UEdgeNotifier::ObserverBase::attached;\n        \n      protected:\n\n        virtual void add(const UEdge& edge) {\n          snapshot.addUEdge(edge);\n        }\n        virtual void add(const std::vector<UEdge>& edges) {\n          for (int i = edges.size() - 1; i >= 0; ++i) {\n            snapshot.addUEdge(edges[i]);\n          }\n        }\n        virtual void erase(const UEdge& edge) {\n          snapshot.eraseUEdge(edge);\n        }\n        virtual void erase(const std::vector<UEdge>& edges) {\n          for (int i = 0; i < int(edges.size()); ++i) {\n            snapshot.eraseUEdge(edges[i]);\n          }\n        }\n        virtual void build() {\n          UEdge edge;\n          std::vector<UEdge> edges;\n          for (notifier()->first(edge); edge != INVALID; \n               notifier()->next(edge)) {\n            edges.push_back(edge);\n          }\n          for (int i = edges.size() - 1; i >= 0; --i) {\n            snapshot.addUEdge(edges[i]);\n          }\n        }\n        virtual void clear() {\n          UEdge edge;\n          for (notifier()->first(edge); edge != INVALID; \n               notifier()->next(edge)) {\n            snapshot.eraseUEdge(edge);\n          }\n        }\n\n        Snapshot& snapshot;\n      };\n      \n      ListBpUGraph *graph;\n\n      NodeObserverProxy node_observer_proxy;\n      UEdgeObserverProxy edge_observer_proxy;\n\n      std::list<Node> added_nodes;\n      std::list<UEdge> added_edges;\n\n\n      void addNode(const Node& node) {\n        added_nodes.push_front(node);        \n      }\n      void eraseNode(const Node& node) {\n        std::list<Node>::iterator it = \n          std::find(added_nodes.begin(), added_nodes.end(), node);\n        if (it == added_nodes.end()) {\n          clear();\n          edge_observer_proxy.detach();\n          throw NodeNotifier::ImmediateDetach();\n        } else {\n          added_nodes.erase(it);\n        }\n      }\n\n      void addUEdge(const UEdge& edge) {\n        added_edges.push_front(edge);        \n      }\n      void eraseUEdge(const UEdge& edge) {\n        std::list<UEdge>::iterator it = \n          std::find(added_edges.begin(), added_edges.end(), edge);\n        if (it == added_edges.end()) {\n          clear();\n          node_observer_proxy.detach();\n          throw UEdgeNotifier::ImmediateDetach();\n        } else {\n          added_edges.erase(it);\n        }        \n      }\n\n      void attach(ListBpUGraph &_graph) {\n\tgraph = &_graph;\n\tnode_observer_proxy.attach(graph->notifier(Node()));\n        edge_observer_proxy.attach(graph->notifier(UEdge()));\n      }\n            \n      void detach() {\n\tnode_observer_proxy.detach();\n\tedge_observer_proxy.detach();\n      }\n\n      bool attached() const {\n        return node_observer_proxy.attached();\n      }\n\n      void clear() {\n        added_nodes.clear();\n        added_edges.clear();        \n      }\n\n    public:\n\n      /// \\brief Default constructor.\n      ///\n      /// Default constructor.\n      /// To actually make a snapshot you must call save().\n      Snapshot() \n        : graph(0), node_observer_proxy(*this), \n          edge_observer_proxy(*this) {}\n      \n      /// \\brief Constructor that immediately makes a snapshot.\n      ///      \n      /// This constructor immediately makes a snapshot of the graph.\n      /// \\param _graph The graph we make a snapshot of.\n      Snapshot(ListBpUGraph &_graph) \n        : node_observer_proxy(*this), \n          edge_observer_proxy(*this) {\n\tattach(_graph);\n      }\n      \n      /// \\brief Make a snapshot.\n      ///\n      /// Make a snapshot of the graph.\n      ///\n      /// This function can be called more than once. In case of a repeated\n      /// call, the previous snapshot gets lost.\n      /// \\param _graph The graph we make the snapshot of.\n      void save(ListBpUGraph &_graph) {\n        if (attached()) {\n          detach();\n          clear();\n        }\n        attach(_graph);\n      }\n      \n      /// \\brief Undo the changes until the last snapshot.\n      // \n      /// Undo the changes until the last snapshot created by save().\n      void restore() {\n\tdetach();\n\tfor(std::list<UEdge>::iterator it = added_edges.begin(); \n            it != added_edges.end(); ++it) {\n\t  graph->erase(*it);\n\t}\n\tfor(std::list<Node>::iterator it = added_nodes.begin(); \n            it != added_nodes.end(); ++it) {\n\t  graph->erase(*it);\n\t}\n        clear();\n      }\n\n      /// \\brief Gives back true when the snapshot is valid.\n      ///\n      /// Gives back true when the snapshot is valid.\n      bool valid() const {\n        return attached();\n      }\n    };\n  };\n\n  \n  /// @}  \n} //namespace lemon\n  \n\n#endif\n"
  },
  {
    "path": "src/lemon/maps.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_MAPS_H\n#define LEMON_MAPS_H\n\n#include <iterator>\n#include <functional>\n#include <vector>\n\n#include <lemon/bits/utility.h>\n#include <lemon/bits/traits.h>\n\n///\\file\n///\\ingroup maps\n///\\brief Miscellaneous property maps\n///\n#include <map>\n\nnamespace lemon {\n\n  /// \\addtogroup maps\n  /// @{\n\n  /// Base class of maps.\n\n  /// Base class of maps.\n  /// It provides the necessary <tt>typedef</tt>s required by the map concept.\n  template<typename K, typename T>\n  class MapBase {\n  public:\n    /// The key type of the map.\n    typedef K Key;\n    /// The value type of the map. (The type of objects associated with the keys).\n    typedef T Value;\n  };\n\n  /// Null map. (a.k.a. DoNothingMap)\n\n  /// This map can be used if you have to provide a map only for\n  /// its type definitions, or if you have to provide a writable map, \n  /// but data written to it is not required (i.e. it will be sent to \n  /// <tt>/dev/null</tt>).\n  template<typename K, typename T>\n  class NullMap : public MapBase<K, T> {\n  public:\n    typedef MapBase<K, T> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n    \n    /// Gives back a default constructed element.\n    T operator[](const K&) const { return T(); }\n    /// Absorbs the value.\n    void set(const K&, const T&) {}\n  };\n\n  ///Returns a \\c NullMap class\n\n  ///This function just returns a \\c NullMap class.\n  ///\\relates NullMap\n  template <typename K, typename V> \n  NullMap<K, V> nullMap() {\n    return NullMap<K, V>();\n  }\n\n\n  /// Constant map.\n\n  /// This is a \\ref concepts::ReadMap \"readable\" map which assigns a \n  /// specified value to each key.\n  /// In other aspects it is equivalent to \\c NullMap.\n  template<typename K, typename T>\n  class ConstMap : public MapBase<K, T> {\n  private:\n    T v;\n  public:\n\n    typedef MapBase<K, T> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    /// Default constructor\n\n    /// Default constructor.\n    /// The value of the map will be uninitialized. \n    /// (More exactly it will be default constructed.)\n    ConstMap() {}\n    \n    /// Constructor with specified initial value\n\n    /// Constructor with specified initial value.\n    /// \\param _v is the initial value of the map.\n    ConstMap(const T &_v) : v(_v) {}\n    \n    ///\\e\n    T operator[](const K&) const { return v; }\n\n    ///\\e\n    void setAll(const T &t) {\n      v = t;\n    }    \n\n    template<typename T1>\n    struct rebind {\n      typedef ConstMap<K, T1> other;\n    };\n\n    template<typename T1>\n    ConstMap(const ConstMap<K, T1> &, const T &_v) : v(_v) {}\n  };\n\n  ///Returns a \\c ConstMap class\n\n  ///This function just returns a \\c ConstMap class.\n  ///\\relates ConstMap\n  template<typename K, typename V> \n  inline ConstMap<K, V> constMap(const V &v) {\n    return ConstMap<K, V>(v);\n  }\n\n\n  template<typename T, T v>\n  struct Const { };\n\n  /// Constant map with inlined constant value.\n\n  /// This is a \\ref concepts::ReadMap \"readable\" map which assigns a \n  /// specified value to each key.\n  /// In other aspects it is equivalent to \\c NullMap.\n  template<typename K, typename V, V v>\n  class ConstMap<K, Const<V, v> > : public MapBase<K, V> {\n  public:\n    typedef MapBase<K, V> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ConstMap() { }\n    ///\\e\n    V operator[](const K&) const { return v; }\n    ///\\e\n    void set(const K&, const V&) { }\n  };\n\n  ///Returns a \\c ConstMap class with inlined value\n\n  ///This function just returns a \\c ConstMap class with inlined value.\n  ///\\relates ConstMap\n  template<typename K, typename V, V v> \n  inline ConstMap<K, Const<V, v> > constMap() {\n    return ConstMap<K, Const<V, v> >();\n  }\n\n  ///Map based on \\c std::map\n\n  ///This is essentially a wrapper for \\c std::map with addition that\n  ///you can specify a default value different from \\c Value() .\n  ///It meets the \\ref concepts::ReferenceMap \"ReferenceMap\" concept.\n  template <typename K, typename T, typename Compare = std::less<K> >\n  class StdMap : public MapBase<K, T> {\n    template <typename K1, typename T1, typename C1>\n    friend class StdMap;\n  public:\n\n    typedef MapBase<K, T> Parent;\n    ///Key type\n    typedef typename Parent::Key Key;\n    ///Value type\n    typedef typename Parent::Value Value;\n    ///Reference Type\n    typedef T& Reference;\n    ///Const reference type\n    typedef const T& ConstReference;\n\n    typedef True ReferenceMapTag;\n\n  private:\n    \n    typedef std::map<K, T, Compare> Map;\n    Value _value;\n    Map _map;\n\n  public:\n\n    /// Constructor with specified default value\n    StdMap(const T& value = T()) : _value(value) {}\n    /// \\brief Constructs the map from an appropriate \\c std::map, and \n    /// explicitly specifies a default value.\n    template <typename T1, typename Comp1>\n    StdMap(const std::map<Key, T1, Comp1> &map, const T& value = T()) \n      : _map(map.begin(), map.end()), _value(value) {}\n    \n    /// \\brief Constructs a map from an other \\ref StdMap.\n    template<typename T1, typename Comp1>\n    StdMap(const StdMap<Key, T1, Comp1> &c) \n      : _map(c._map.begin(), c._map.end()), _value(c._value) {}\n\n  private:\n\n    StdMap& operator=(const StdMap&);\n\n  public:\n\n    ///\\e\n    Reference operator[](const Key &k) {\n      typename Map::iterator it = _map.lower_bound(k);\n      if (it != _map.end() && !_map.key_comp()(k, it->first))\n\treturn it->second;\n      else\n\treturn _map.insert(it, std::make_pair(k, _value))->second;\n    }\n\n    /// \\e \n    ConstReference operator[](const Key &k) const {\n      typename Map::const_iterator it = _map.find(k);\n      if (it != _map.end())\n\treturn it->second;\n      else\n\treturn _value;\n    }\n\n    /// \\e \n    void set(const Key &k, const T &t) {\n      typename Map::iterator it = _map.lower_bound(k);\n      if (it != _map.end() && !_map.key_comp()(k, it->first))\n\tit->second = t;\n      else\n\t_map.insert(it, std::make_pair(k, t));\n    }\n\n    /// \\e\n    void setAll(const T &t) {\n      _value = t;\n      _map.clear();\n    }    \n\n    template <typename T1, typename C1 = std::less<T1> >\n    struct rebind {\n      typedef StdMap<Key, T1, C1> other;\n    };\n  };\n\n  ///Returns a \\c StdMap class\n\n  ///This function just returns a \\c StdMap class with specified \n  ///default value.\n  ///\\relates StdMap\n  template<typename K, typename V, typename Compare> \n  inline StdMap<K, V, Compare> stdMap(const V& value = V()) {\n    return StdMap<K, V, Compare>(value);\n  }\n  \n  template<typename K, typename V> \n  inline StdMap<K, V, std::less<K> > stdMap(const V& value = V()) {\n    return StdMap<K, V, std::less<K> >(value);\n  }\n  \n  ///Returns a \\c StdMap class created from an appropriate \\c std::map\n\n  ///This function just returns a \\c StdMap class created from an \n  ///appropriate \\c std::map.\n  ///\\relates StdMap\n  template<typename K, typename V, typename Compare> \n  inline StdMap<K, V, Compare> stdMap( const std::map<K, V, Compare> &map, \n                                       const V& value = V() ) {\n    return StdMap<K, V, Compare>(map, value);\n  }\n\n  /// \\brief Map for storing values for keys from the range <tt>[0..size-1]</tt>\n  ///\n  /// This map has the <tt>[0..size-1]</tt> keyset and the values\n  /// are stored in a \\c std::vector<T>  container. It can be used with\n  /// some data structures, for example \\c UnionFind, \\c BinHeap, when \n  /// the used items are small integer numbers.\n  template <typename T>\n  class IntegerMap : public MapBase<int, T> {\n\n    template <typename T1>\n    friend class IntegerMap;\n\n  public:\n\n    typedef MapBase<int, T> Parent;\n    ///\\e\n    typedef typename Parent::Key Key;\n    ///\\e\n    typedef typename Parent::Value Value;\n    ///\\e\n    typedef T& Reference;\n    ///\\e\n    typedef const T& ConstReference;\n\n    typedef True ReferenceMapTag;\n\n  private:\n    \n    typedef std::vector<T> Vector;\n    Vector _vector;\n\n  public:\n\n    /// Constructor with specified default value\n    IntegerMap(int size = 0, const T& value = T()) : _vector(size, value) {}\n\n    /// \\brief Constructs the map from an appropriate \\c std::vector.\n    template <typename T1>\n    IntegerMap(const std::vector<T1>& vector) \n      : _vector(vector.begin(), vector.end()) {}\n    \n    /// \\brief Constructs a map from an other \\ref IntegerMap.\n    template <typename T1>\n    IntegerMap(const IntegerMap<T1> &c) \n      : _vector(c._vector.begin(), c._vector.end()) {}\n\n    /// \\brief Resize the container\n    void resize(int size, const T& value = T()) {\n      _vector.resize(size, value);\n    }\n\n  private:\n\n    IntegerMap& operator=(const IntegerMap&);\n\n  public:\n\n    ///\\e\n    Reference operator[](Key k) {\n      return _vector[k];\n    }\n\n    /// \\e \n    ConstReference operator[](Key k) const {\n      return _vector[k];\n    }\n\n    /// \\e \n    void set(const Key &k, const T& t) {\n      _vector[k] = t;\n    }\n\n  };\n\n  ///Returns an \\c IntegerMap class\n\n  ///This function just returns an \\c IntegerMap class.\n  ///\\relates IntegerMap\n  template<typename T>\n  inline IntegerMap<T> integerMap(int size = 0, const T& value = T()) {\n    return IntegerMap<T>(size, value);\n  }\n\n  /// @}\n\n  /// \\addtogroup map_adaptors\n  /// @{\n\n  /// \\brief Identity map.\n  ///\n  /// This map gives back the given key as value without any\n  /// modification. \n  template <typename T>\n  class IdentityMap : public MapBase<T, T> {\n  public:\n    typedef MapBase<T, T> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    /// \\e\n    const T& operator[](const T& t) const {\n      return t;\n    }\n  };\n\n  ///Returns an \\c IdentityMap class\n\n  ///This function just returns an \\c IdentityMap class.\n  ///\\relates IdentityMap\n  template<typename T>\n  inline IdentityMap<T> identityMap() {\n    return IdentityMap<T>();\n  }\n  \n\n  ///\\brief Convert the \\c Value of a map to another type using\n  ///the default conversion.\n  ///\n  ///This \\ref concepts::ReadMap \"read only map\"\n  ///converts the \\c Value of a map to type \\c T.\n  ///Its \\c Key is inherited from \\c M.\n  template <typename M, typename T> \n  class ConvertMap : public MapBase<typename M::Key, T> {\n    const M& m;\n  public:\n    typedef MapBase<typename M::Key, T> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n\n    ///Constructor\n    ///\\param _m is the underlying map\n    ConvertMap(const M &_m) : m(_m) {};\n\n    ///\\e\n    Value operator[](const Key& k) const {return m[k];}\n  };\n  \n  ///Returns a \\c ConvertMap class\n\n  ///This function just returns a \\c ConvertMap class.\n  ///\\relates ConvertMap\n  template<typename T, typename M>\n  inline ConvertMap<M, T> convertMap(const M &m) {\n    return ConvertMap<M, T>(m);\n  }\n\n  ///Simple wrapping of a map\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the simple\n  ///wrapping of the given map. Sometimes the reference maps cannot be\n  ///combined with simple read maps. This map adaptor wraps the given\n  ///map to simple read map.\n  ///\n  ///\\sa SimpleWriteMap\n  ///\n  /// \\todo Revise the misleading name \n  template<typename M> \n  class SimpleMap : public MapBase<typename M::Key, typename M::Value> {\n    const M& m;\n\n  public:\n    typedef MapBase<typename M::Key, typename M::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    SimpleMap(const M &_m) : m(_m) {};\n    ///\\e\n    Value operator[](Key k) const {return m[k];}\n  };\n\n  ///Returns a \\c SimpleMap class\n\n  ///This function just returns a \\c SimpleMap class.\n  ///\\relates SimpleMap\n  template<typename M>\n  inline SimpleMap<M> simpleMap(const M &m) {\n    return SimpleMap<M>(m);\n  }\n\n  ///Simple writable wrapping of a map\n\n  ///This \\ref concepts::ReadWriteMap \"read-write map\" returns the simple\n  ///wrapping of the given map. Sometimes the reference maps cannot be\n  ///combined with simple read-write maps. This map adaptor wraps the\n  ///given map to simple read-write map.\n  ///\n  ///\\sa SimpleMap\n  ///\n  /// \\todo Revise the misleading name\n  template<typename M> \n  class SimpleWriteMap : public MapBase<typename M::Key, typename M::Value> {\n    M& m;\n\n  public:\n    typedef MapBase<typename M::Key, typename M::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    SimpleWriteMap(M &_m) : m(_m) {};\n    ///\\e\n    Value operator[](Key k) const {return m[k];}\n    ///\\e\n    void set(Key k, const Value& c) { m.set(k, c); }\n  };\n\n  ///Returns a \\c SimpleWriteMap class\n\n  ///This function just returns a \\c SimpleWriteMap class.\n  ///\\relates SimpleWriteMap\n  template<typename M>\n  inline SimpleWriteMap<M> simpleWriteMap(M &m) {\n    return SimpleWriteMap<M>(m);\n  }\n\n  ///Sum of two maps\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the sum of the two\n  ///given maps.\n  ///Its \\c Key and \\c Value are inherited from \\c M1.\n  ///The \\c Key and \\c Value of \\c M2 must be convertible to those of \\c M1.\n  template<typename M1, typename M2> \n  class AddMap : public MapBase<typename M1::Key, typename M1::Value> {\n    const M1& m1;\n    const M2& m2;\n\n  public:\n    typedef MapBase<typename M1::Key, typename M1::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    AddMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {};\n    ///\\e\n    Value operator[](Key k) const {return m1[k]+m2[k];}\n  };\n  \n  ///Returns an \\c AddMap class\n\n  ///This function just returns an \\c AddMap class.\n  ///\\todo How to call these type of functions?\n  ///\n  ///\\relates AddMap\n  template<typename M1, typename M2> \n  inline AddMap<M1, M2> addMap(const M1 &m1,const M2 &m2) {\n    return AddMap<M1, M2>(m1,m2);\n  }\n\n  ///Shift a map with a constant.\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the sum of the\n  ///given map and a constant value.\n  ///Its \\c Key and \\c Value is inherited from \\c M.\n  ///\n  ///Actually,\n  ///\\code\n  ///  ShiftMap<X> sh(x,v);\n  ///\\endcode\n  ///is equivalent to\n  ///\\code\n  ///  ConstMap<X::Key, X::Value> c_tmp(v);\n  ///  AddMap<X, ConstMap<X::Key, X::Value> > sh(x,v);\n  ///\\endcode\n  ///\n  ///\\sa ShiftWriteMap\n  template<typename M, typename C = typename M::Value> \n  class ShiftMap : public MapBase<typename M::Key, typename M::Value> {\n    const M& m;\n    C v;\n  public:\n    typedef MapBase<typename M::Key, typename M::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n\n    ///Constructor\n    ///\\param _m is the undelying map\n    ///\\param _v is the shift value\n    ShiftMap(const M &_m, const C &_v ) : m(_m), v(_v) {};\n    ///\\e\n    Value operator[](Key k) const {return m[k] + v;}\n  };\n\n  ///Shift a map with a constant (ReadWrite version).\n\n  ///This \\ref concepts::ReadWriteMap \"read-write map\" returns the sum of the\n  ///given map and a constant value. It makes also possible to write the map.\n  ///Its \\c Key and \\c Value are inherited from \\c M.\n  ///\n  ///\\sa ShiftMap\n  template<typename M, typename C = typename M::Value> \n  class ShiftWriteMap : public MapBase<typename M::Key, typename M::Value> {\n    M& m;\n    C v;\n  public:\n    typedef MapBase<typename M::Key, typename M::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n\n    ///Constructor\n    ///\\param _m is the undelying map\n    ///\\param _v is the shift value\n    ShiftWriteMap(M &_m, const C &_v ) : m(_m), v(_v) {};\n    /// \\e\n    Value operator[](Key k) const {return m[k] + v;}\n    /// \\e\n    void set(Key k, const Value& c) { m.set(k, c - v); }\n  };\n  \n  ///Returns a \\c ShiftMap class\n\n  ///This function just returns an \\c ShiftMap class.\n  ///\\relates ShiftMap\n  template<typename M, typename C> \n  inline ShiftMap<M, C> shiftMap(const M &m,const C &v) {\n    return ShiftMap<M, C>(m,v);\n  }\n\n  ///Returns a \\c ShiftWriteMap class\n\n  ///This function just returns a \\c ShiftWriteMap class.\n  ///\\relates ShiftWriteMap\n  template<typename M, typename C> \n  inline ShiftWriteMap<M, C> shiftMap(M &m,const C &v) {\n    return ShiftWriteMap<M, C>(m,v);\n  }\n\n  ///Difference of two maps\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the difference\n  ///of the values of the two given maps.\n  ///Its \\c Key and \\c Value are inherited from \\c M1.\n  ///The \\c Key and \\c Value of \\c M2 must be convertible to those of \\c M1.\n\n  template<typename M1, typename M2> \n  class SubMap : public MapBase<typename M1::Key, typename M1::Value> {\n    const M1& m1;\n    const M2& m2;\n  public:\n    typedef MapBase<typename M1::Key, typename M1::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    SubMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {};\n    /// \\e\n    Value operator[](Key k) const {return m1[k]-m2[k];}\n  };\n  \n  ///Returns a \\c SubMap class\n\n  ///This function just returns a \\c SubMap class.\n  ///\n  ///\\relates SubMap\n  template<typename M1, typename M2> \n  inline SubMap<M1, M2> subMap(const M1 &m1, const M2 &m2) {\n    return SubMap<M1, M2>(m1, m2);\n  }\n\n  ///Product of two maps\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the product of the\n  ///values of the two given maps.\n  ///Its \\c Key and \\c Value are inherited from \\c M1.\n  ///The \\c Key and \\c Value of \\c M2 must be convertible to those of \\c M1.\n  template<typename M1, typename M2> \n  class MulMap : public MapBase<typename M1::Key, typename M1::Value> {\n    const M1& m1;\n    const M2& m2;\n  public:\n    typedef MapBase<typename M1::Key, typename M1::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    MulMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {};\n    /// \\e\n    Value operator[](Key k) const {return m1[k]*m2[k];}\n  };\n  \n  ///Returns a \\c MulMap class\n\n  ///This function just returns a \\c MulMap class.\n  ///\\relates MulMap\n  template<typename M1, typename M2> \n  inline MulMap<M1, M2> mulMap(const M1 &m1,const M2 &m2) {\n    return MulMap<M1, M2>(m1,m2);\n  }\n \n  ///Scales a map with a constant.\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the value of the\n  ///given map multiplied from the left side with a constant value.\n  ///Its \\c Key and \\c Value are inherited from \\c M.\n  ///\n  ///Actually,\n  ///\\code\n  ///  ScaleMap<X> sc(x,v);\n  ///\\endcode\n  ///is equivalent to\n  ///\\code\n  ///  ConstMap<X::Key, X::Value> c_tmp(v);\n  ///  MulMap<X, ConstMap<X::Key, X::Value> > sc(x,v);\n  ///\\endcode\n  ///\n  ///\\sa ScaleWriteMap\n  template<typename M, typename C = typename M::Value> \n  class ScaleMap : public MapBase<typename M::Key, typename M::Value> {\n    const M& m;\n    C v;\n  public:\n    typedef MapBase<typename M::Key, typename M::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n\n    ///Constructor\n    ///\\param _m is the undelying map\n    ///\\param _v is the scaling value\n    ScaleMap(const M &_m, const C &_v ) : m(_m), v(_v) {};\n    /// \\e\n    Value operator[](Key k) const {return v * m[k];}\n  };\n\n  ///Scales a map with a constant (ReadWrite version).\n\n  ///This \\ref concepts::ReadWriteMap \"read-write map\" returns the value of the\n  ///given map multiplied from the left side with a constant value. It can\n  ///also be used as write map if the \\c / operator is defined between\n  ///\\c Value and \\c C and the given multiplier is not zero.\n  ///Its \\c Key and \\c Value are inherited from \\c M.\n  ///\n  ///\\sa ScaleMap\n  template<typename M, typename C = typename M::Value> \n  class ScaleWriteMap : public MapBase<typename M::Key, typename M::Value> {\n    M& m;\n    C v;\n  public:\n    typedef MapBase<typename M::Key, typename M::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n\n    ///Constructor\n    ///\\param _m is the undelying map\n    ///\\param _v is the scaling value\n    ScaleWriteMap(M &_m, const C &_v ) : m(_m), v(_v) {};\n    /// \\e\n    Value operator[](Key k) const {return v * m[k];}\n    /// \\e\n    void set(Key k, const Value& c) { m.set(k, c / v);}\n  };\n  \n  ///Returns a \\c ScaleMap class\n\n  ///This function just returns a \\c ScaleMap class.\n  ///\\relates ScaleMap\n  template<typename M, typename C> \n  inline ScaleMap<M, C> scaleMap(const M &m,const C &v) {\n    return ScaleMap<M, C>(m,v);\n  }\n\n  ///Returns a \\c ScaleWriteMap class\n\n  ///This function just returns a \\c ScaleWriteMap class.\n  ///\\relates ScaleWriteMap\n  template<typename M, typename C> \n  inline ScaleWriteMap<M, C> scaleMap(M &m,const C &v) {\n    return ScaleWriteMap<M, C>(m,v);\n  }\n\n  ///Quotient of two maps\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the quotient of the\n  ///values of the two given maps.\n  ///Its \\c Key and \\c Value are inherited from \\c M1.\n  ///The \\c Key and \\c Value of \\c M2 must be convertible to those of \\c M1.\n  template<typename M1, typename M2> \n  class DivMap : public MapBase<typename M1::Key, typename M1::Value> {\n    const M1& m1;\n    const M2& m2;\n  public:\n    typedef MapBase<typename M1::Key, typename M1::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    DivMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {};\n    /// \\e\n    Value operator[](Key k) const {return m1[k]/m2[k];}\n  };\n  \n  ///Returns a \\c DivMap class\n\n  ///This function just returns a \\c DivMap class.\n  ///\\relates DivMap\n  template<typename M1, typename M2> \n  inline DivMap<M1, M2> divMap(const M1 &m1,const M2 &m2) {\n    return DivMap<M1, M2>(m1,m2);\n  }\n  \n  ///Composition of two maps\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the composition of\n  ///two given maps.\n  ///That is to say, if \\c m1 is of type \\c M1 and \\c m2 is of \\c M2,\n  ///then for\n  ///\\code\n  ///  ComposeMap<M1, M2> cm(m1,m2);\n  ///\\endcode\n  /// <tt>cm[x]</tt> will be equal to <tt>m1[m2[x]]</tt>.\n  ///\n  ///Its \\c Key is inherited from \\c M2 and its \\c Value is from \\c M1.\n  ///\\c M2::Value must be convertible to \\c M1::Key.\n  ///\n  ///\\sa CombineMap\n  ///\n  ///\\todo Check the requirements.\n  template <typename M1, typename M2> \n  class ComposeMap : public MapBase<typename M2::Key, typename M1::Value> {\n    const M1& m1;\n    const M2& m2;\n  public:\n    typedef MapBase<typename M2::Key, typename M1::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    ComposeMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {};\n    \n    typename MapTraits<M1>::ConstReturnValue\n    /// \\e\n    operator[](Key k) const {return m1[m2[k]];}\n  };\n  ///Returns a \\c ComposeMap class\n\n  ///This function just returns a \\c ComposeMap class.\n  ///\n  ///\\relates ComposeMap\n  template <typename M1, typename M2> \n  inline ComposeMap<M1, M2> composeMap(const M1 &m1,const M2 &m2) {\n    return ComposeMap<M1, M2>(m1,m2);\n  }\n  \n  ///Combine of two maps using an STL (binary) functor.\n\n  ///Combine of two maps using an STL (binary) functor.\n  ///\n  ///This \\ref concepts::ReadMap \"read only map\" takes two maps and a\n  ///binary functor and returns the composition of the two\n  ///given maps unsing the functor. \n  ///That is to say, if \\c m1 and \\c m2 is of type \\c M1 and \\c M2\n  ///and \\c f is of \\c F, then for\n  ///\\code\n  ///  CombineMap<M1, M2,F,V> cm(m1,m2,f);\n  ///\\endcode\n  /// <tt>cm[x]</tt> will be equal to <tt>f(m1[x],m2[x])</tt>\n  ///\n  ///Its \\c Key is inherited from \\c M1 and its \\c Value is \\c V.\n  ///\\c M2::Value and \\c M1::Value must be convertible to the corresponding\n  ///input parameter of \\c F and the return type of \\c F must be convertible\n  ///to \\c V.\n  ///\n  ///\\sa ComposeMap\n  ///\n  ///\\todo Check the requirements.\n  template<typename M1, typename M2, typename F,\n\t   typename V = typename F::result_type> \n  class CombineMap : public MapBase<typename M1::Key, V> {\n    const M1& m1;\n    const M2& m2;\n    F f;\n  public:\n    typedef MapBase<typename M1::Key, V> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    CombineMap(const M1 &_m1,const M2 &_m2,const F &_f = F())\n      : m1(_m1), m2(_m2), f(_f) {};\n    /// \\e\n    Value operator[](Key k) const {return f(m1[k],m2[k]);}\n  };\n  \n  ///Returns a \\c CombineMap class\n\n  ///This function just returns a \\c CombineMap class.\n  ///\n  ///For example if \\c m1 and \\c m2 are both \\c double valued maps, then \n  ///\\code\n  ///combineMap(m1,m2,std::plus<double>())\n  ///\\endcode\n  ///is equivalent to\n  ///\\code\n  ///addMap(m1,m2)\n  ///\\endcode\n  ///\n  ///This function is specialized for adaptable binary function\n  ///classes and C++ functions.\n  ///\n  ///\\relates CombineMap\n  template<typename M1, typename M2, typename F, typename V> \n  inline CombineMap<M1, M2, F, V> \n  combineMap(const M1& m1,const M2& m2, const F& f) {\n    return CombineMap<M1, M2, F, V>(m1,m2,f);\n  }\n\n  template<typename M1, typename M2, typename F> \n  inline CombineMap<M1, M2, F, typename F::result_type> \n  combineMap(const M1& m1, const M2& m2, const F& f) {\n    return combineMap<M1, M2, F, typename F::result_type>(m1,m2,f);\n  }\n\n  template<typename M1, typename M2, typename K1, typename K2, typename V> \n  inline CombineMap<M1, M2, V (*)(K1, K2), V> \n  combineMap(const M1 &m1, const M2 &m2, V (*f)(K1, K2)) {\n    return combineMap<M1, M2, V (*)(K1, K2), V>(m1,m2,f);\n  }\n\n  ///Negative value of a map\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the negative\n  ///value of the value returned by the given map.\n  ///Its \\c Key and \\c Value are inherited from \\c M.\n  ///The unary \\c - operator must be defined for \\c Value, of course.\n  ///\n  ///\\sa NegWriteMap\n  template<typename M> \n  class NegMap : public MapBase<typename M::Key, typename M::Value> {\n    const M& m;\n  public:\n    typedef MapBase<typename M::Key, typename M::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    NegMap(const M &_m) : m(_m) {};\n    /// \\e\n    Value operator[](Key k) const {return -m[k];}\n  };\n  \n  ///Negative value of a map (ReadWrite version)\n\n  ///This \\ref concepts::ReadWriteMap \"read-write map\" returns the negative\n  ///value of the value returned by the given map.\n  ///Its \\c Key and \\c Value are inherited from \\c M.\n  ///The unary \\c - operator must be defined for \\c Value, of course.\n  ///\n  /// \\sa NegMap\n  template<typename M> \n  class NegWriteMap : public MapBase<typename M::Key, typename M::Value> {\n    M& m;\n  public:\n    typedef MapBase<typename M::Key, typename M::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    NegWriteMap(M &_m) : m(_m) {};\n    /// \\e\n    Value operator[](Key k) const {return -m[k];}\n    /// \\e\n    void set(Key k, const Value& v) { m.set(k, -v); }\n  };\n\n  ///Returns a \\c NegMap class\n\n  ///This function just returns a \\c NegMap class.\n  ///\\relates NegMap\n  template <typename M> \n  inline NegMap<M> negMap(const M &m) {\n    return NegMap<M>(m);\n  }\n\n  ///Returns a \\c NegWriteMap class\n\n  ///This function just returns a \\c NegWriteMap class.\n  ///\\relates NegWriteMap\n  template <typename M> \n  inline NegWriteMap<M> negMap(M &m) {\n    return NegWriteMap<M>(m);\n  }\n\n  ///Absolute value of a map\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the absolute value\n  ///of the value returned by the given map.\n  ///Its \\c Key and \\c Value are inherited from \\c M. \n  ///\\c Value must be comparable to \\c 0 and the unary \\c -\n  ///operator must be defined for it, of course.\n  ///\n  ///\\bug We need a unified way to handle the situation below:\n  ///\\code\n  ///  struct _UnConvertible {};\n  ///  template<class A> inline A t_abs(A a) {return _UnConvertible();}\n  ///  template<> inline int t_abs<>(int n) {return abs(n);}\n  ///  template<> inline long int t_abs<>(long int n) {return labs(n);}\n  ///  template<> inline long long int t_abs<>(long long int n) {return ::llabs(n);}\n  ///  template<> inline float t_abs<>(float n) {return fabsf(n);}\n  ///  template<> inline double t_abs<>(double n) {return fabs(n);}\n  ///  template<> inline long double t_abs<>(long double n) {return fabsl(n);}\n  ///\\endcode\n  \n\n  template<typename M> \n  class AbsMap : public MapBase<typename M::Key, typename M::Value> {\n    const M& m;\n  public:\n    typedef MapBase<typename M::Key, typename M::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    AbsMap(const M &_m) : m(_m) {};\n    /// \\e\n    Value operator[](Key k) const {\n      Value tmp = m[k]; \n      return tmp >= 0 ? tmp : -tmp;\n    }\n\n  };\n  \n  ///Returns an \\c AbsMap class\n\n  ///This function just returns an \\c AbsMap class.\n  ///\\relates AbsMap\n  template<typename M> \n  inline AbsMap<M> absMap(const M &m) {\n    return AbsMap<M>(m);\n  }\n\n  ///Converts an STL style functor to a map\n\n  ///This \\ref concepts::ReadMap \"read only map\" returns the value\n  ///of a given functor.\n  ///\n  ///Template parameters \\c K and \\c V will become its\n  ///\\c Key and \\c Value. \n  ///In most cases they have to be given explicitly because a \n  ///functor typically does not provide \\c argument_type and \n  ///\\c result_type typedefs.\n  ///\n  ///Parameter \\c F is the type of the used functor.\n  ///\n  ///\\sa MapFunctor\n  template<typename F, \n\t   typename K = typename F::argument_type, \n\t   typename V = typename F::result_type> \n  class FunctorMap : public MapBase<K, V> {\n    F f;\n  public:\n    typedef MapBase<K, V> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    FunctorMap(const F &_f = F()) : f(_f) {}\n    /// \\e\n    Value operator[](Key k) const { return f(k);}\n  };\n  \n  ///Returns a \\c FunctorMap class\n\n  ///This function just returns a \\c FunctorMap class.\n  ///\n  ///This function is specialized for adaptable binary function\n  ///classes and C++ functions.\n  ///\n  ///\\relates FunctorMap\n  template<typename K, typename V, typename F> inline \n  FunctorMap<F, K, V> functorMap(const F &f) {\n    return FunctorMap<F, K, V>(f);\n  }\n\n  template <typename F> inline \n  FunctorMap<F, typename F::argument_type, typename F::result_type> \n  functorMap(const F &f) {\n    return FunctorMap<F, typename F::argument_type, \n      typename F::result_type>(f);\n  }\n\n  template <typename K, typename V> inline \n  FunctorMap<V (*)(K), K, V> functorMap(V (*f)(K)) {\n    return FunctorMap<V (*)(K), K, V>(f);\n  }\n\n\n  ///Converts a map to an STL style (unary) functor\n\n  ///This class Converts a map to an STL style (unary) functor.\n  ///That is it provides an <tt>operator()</tt> to read its values.\n  ///\n  ///For the sake of convenience it also works as\n  ///a ususal \\ref concepts::ReadMap \"readable map\",\n  ///i.e. <tt>operator[]</tt> and the \\c Key and \\c Value typedefs also exist.\n  ///\n  ///\\sa FunctorMap\n  template <typename M> \n  class MapFunctor : public MapBase<typename M::Key, typename M::Value> {\n    const M& m;\n  public:\n    typedef MapBase<typename M::Key, typename M::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    typedef typename M::Key argument_type;\n    typedef typename M::Value result_type;\n\n    ///Constructor\n    MapFunctor(const M &_m) : m(_m) {};\n    ///\\e\n    Value operator()(Key k) const {return m[k];}\n    ///\\e\n    Value operator[](Key k) const {return m[k];}\n  };\n  \n  ///Returns a \\c MapFunctor class\n\n  ///This function just returns a \\c MapFunctor class.\n  ///\\relates MapFunctor\n  template<typename M> \n  inline MapFunctor<M> mapFunctor(const M &m) {\n    return MapFunctor<M>(m);\n  }\n\n  ///Just readable version of \\ref ForkWriteMap\n\n  ///This map has two \\ref concepts::ReadMap \"readable map\"\n  ///parameters and each read request will be passed just to the\n  ///first map. This class is the just readable map type of \\c ForkWriteMap.\n  ///\n  ///The \\c Key and \\c Value are inherited from \\c M1.\n  ///The \\c Key and \\c Value of \\c M2 must be convertible from those of \\c M1.\n  ///\n  ///\\sa ForkWriteMap\n\n  template<typename  M1, typename M2> \n  class ForkMap : public MapBase<typename M1::Key, typename M1::Value> {\n    const M1& m1;\n    const M2& m2;\n  public:\n    typedef MapBase<typename M1::Key, typename M1::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    ForkMap(const M1 &_m1, const M2 &_m2) : m1(_m1), m2(_m2) {};\n    /// \\e\n    Value operator[](Key k) const {return m1[k];}\n  };\n\n\n  ///Applies all map setting operations to two maps\n\n  ///This map has two \\ref concepts::WriteMap \"writable map\"\n  ///parameters and each write request will be passed to both of them.\n  ///If \\c M1 is also \\ref concepts::ReadMap \"readable\",\n  ///then the read operations will return the\n  ///corresponding values of \\c M1.\n  ///\n  ///The \\c Key and \\c Value are inherited from \\c M1.\n  ///The \\c Key and \\c Value of \\c M2 must be convertible from those of \\c M1.\n  ///\n  ///\\sa ForkMap\n  template<typename  M1, typename M2> \n  class ForkWriteMap : public MapBase<typename M1::Key, typename M1::Value> {\n    M1& m1;\n    M2& m2;\n  public:\n    typedef MapBase<typename M1::Key, typename M1::Value> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    ///Constructor\n    ForkWriteMap(M1 &_m1, M2 &_m2) : m1(_m1), m2(_m2) {};\n    ///\\e\n    Value operator[](Key k) const {return m1[k];}\n    ///\\e\n    void set(Key k, const Value &v) {m1.set(k,v); m2.set(k,v);}\n  };\n  \n  ///Returns a \\c ForkMap class\n\n  ///This function just returns a \\c ForkMap class.\n  ///\\relates ForkMap\n  template <typename M1, typename M2> \n  inline ForkMap<M1, M2> forkMap(const M1 &m1, const M2 &m2) {\n    return ForkMap<M1, M2>(m1,m2);\n  }\n\n  ///Returns a \\c ForkWriteMap class\n\n  ///This function just returns a \\c ForkWriteMap class.\n  ///\\relates ForkWriteMap\n  template <typename M1, typename M2> \n  inline ForkWriteMap<M1, M2> forkMap(M1 &m1, M2 &m2) {\n    return ForkWriteMap<M1, M2>(m1,m2);\n  }\n\n\n  \n  /* ************* BOOL MAPS ******************* */\n  \n  ///Logical 'not' of a map\n  \n  ///This bool \\ref concepts::ReadMap \"read only map\" returns the \n  ///logical negation of the value returned by the given map.\n  ///Its \\c Key is inherited from \\c M, its \\c Value is \\c bool.\n  ///\n  ///\\sa NotWriteMap\n  template <typename M> \n  class NotMap : public MapBase<typename M::Key, bool> {\n    const M& m;\n  public:\n    typedef MapBase<typename M::Key, bool> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    /// Constructor\n    NotMap(const M &_m) : m(_m) {};\n    ///\\e\n    Value operator[](Key k) const {return !m[k];}\n  };\n\n  ///Logical 'not' of a map (ReadWrie version)\n  \n  ///This bool \\ref concepts::ReadWriteMap \"read-write map\" returns the \n  ///logical negation of the value returned by the given map. When it is set,\n  ///the opposite value is set to the original map.\n  ///Its \\c Key is inherited from \\c M, its \\c Value is \\c bool.\n  ///\n  ///\\sa NotMap\n  template <typename M> \n  class NotWriteMap : public MapBase<typename M::Key, bool> {\n    M& m;\n  public:\n    typedef MapBase<typename M::Key, bool> Parent;\n    typedef typename Parent::Key Key;\n    typedef typename Parent::Value Value;\n\n    /// Constructor\n    NotWriteMap(M &_m) : m(_m) {};\n    ///\\e\n    Value operator[](Key k) const {return !m[k];}\n    ///\\e\n    void set(Key k, bool v) { m.set(k, !v); }\n  };\n  \n  ///Returns a \\c NotMap class\n  \n  ///This function just returns a \\c NotMap class.\n  ///\\relates NotMap\n  template <typename M> \n  inline NotMap<M> notMap(const M &m) {\n    return NotMap<M>(m);\n  }\n  \n  ///Returns a \\c NotWriteMap class\n  \n  ///This function just returns a \\c NotWriteMap class.\n  ///\\relates NotWriteMap\n  template <typename M> \n  inline NotWriteMap<M> notMap(M &m) {\n    return NotWriteMap<M>(m);\n  }\n\n  namespace _maps_bits {\n\n    template <typename Value>\n    struct Identity {\n      typedef Value argument_type;\n      typedef Value result_type;\n      Value operator()(const Value& val) const {\n\treturn val;\n      }\n    };\n\n    template <typename _Iterator, typename Enable = void>\n    struct IteratorTraits {\n      typedef typename std::iterator_traits<_Iterator>::value_type Value;\n    };\n\n    template <typename _Iterator>\n    struct IteratorTraits<_Iterator,\n      typename exists<typename _Iterator::container_type>::type> \n    {\n      typedef typename _Iterator::container_type::value_type Value;\n    };\n\n  }\n  \n\n  /// \\brief Writable bool map for logging each \\c true assigned element\n  ///\n  /// A \\ref concepts::ReadWriteMap \"read-write\" bool map for logging \n  /// each \\c true assigned element, i.e it copies all the keys set \n  /// to \\c true to the given iterator.\n  ///\n  /// \\note The container of the iterator should contain space \n  /// for each element.\n  ///\n  /// The following example shows how you can write the edges found by \n  /// the \\ref Prim algorithm directly to the standard output.\n  ///\\code\n  /// typedef IdMap<UGraph, UEdge> UEdgeIdMap;\n  /// UEdgeIdMap uedgeId(ugraph);\n  ///\n  /// typedef MapFunctor<UEdgeIdMap> UEdgeIdFunctor;\n  /// UEdgeIdFunctor uedgeIdFunctor(uedgeId);\n  ///\n  /// StoreBoolMap<ostream_iterator<int>, UEdgeIdFunctor> \n  ///   writerMap(ostream_iterator<int>(cout, \" \"), uedgeIdFunctor);\n  ///\n  /// prim(ugraph, cost, writerMap);\n  ///\\endcode\n  ///\n  ///\\sa BackInserterBoolMap \n  ///\\sa FrontInserterBoolMap \n  ///\\sa InserterBoolMap \n  template <typename _Iterator, \n            typename _Functor =\n            _maps_bits::Identity<typename _maps_bits::\n                                 IteratorTraits<_Iterator>::Value> >\n  class StoreBoolMap {\n  public:\n    typedef _Iterator Iterator;\n\n    typedef typename _Functor::argument_type Key;\n    typedef bool Value;\n\n    typedef _Functor Functor;\n\n    /// Constructor\n    StoreBoolMap(Iterator it, const Functor& functor = Functor()) \n      : _begin(it), _end(it), _functor(functor) {}\n\n    /// Gives back the given iterator set for the first key\n    Iterator begin() const {\n      return _begin;\n    }\n \n    /// Gives back the the 'after the last' iterator\n    Iterator end() const {\n      return _end;\n    }\n\n    /// The \\c set function of the map\n    void set(const Key& key, Value value) const {\n      if (value) {\n\t*_end++ = _functor(key);\n      }\n    }\n    \n  private:\n    Iterator _begin;\n    mutable Iterator _end;\n    Functor _functor;\n  };\n\n  /// \\brief Writable bool map for logging each \\c true assigned element in \n  /// a back insertable container.\n  ///\n  /// Writable bool map for logging each \\c true assigned element by pushing\n  /// them into a back insertable container.\n  /// It can be used to retrieve the items into a standard\n  /// container. The next example shows how you can store the\n  /// edges found by the Prim algorithm in a vector.\n  ///\n  ///\\code\n  /// vector<UEdge> span_tree_uedges;\n  /// BackInserterBoolMap<vector<UEdge> > inserter_map(span_tree_uedges);\n  /// prim(ugraph, cost, inserter_map);\n  ///\\endcode\n  ///\n  ///\\sa StoreBoolMap\n  ///\\sa FrontInserterBoolMap\n  ///\\sa InserterBoolMap\n  template <typename Container,\n            typename Functor =\n            _maps_bits::Identity<typename Container::value_type> >\n  class BackInserterBoolMap {\n  public:\n    typedef typename Functor::argument_type Key;\n    typedef bool Value;\n\n    /// Constructor\n    BackInserterBoolMap(Container& _container, \n                        const Functor& _functor = Functor()) \n      : container(_container), functor(_functor) {}\n\n    /// The \\c set function of the map\n    void set(const Key& key, Value value) {\n      if (value) {\n\tcontainer.push_back(functor(key));\n      }\n    }\n    \n  private:\n    Container& container;\n    Functor functor;\n  };\n\n  /// \\brief Writable bool map for logging each \\c true assigned element in \n  /// a front insertable container.\n  ///\n  /// Writable bool map for logging each \\c true assigned element by pushing\n  /// them into a front insertable container.\n  /// It can be used to retrieve the items into a standard\n  /// container. For example see \\ref BackInserterBoolMap.\n  ///\n  ///\\sa BackInserterBoolMap\n  ///\\sa InserterBoolMap\n  template <typename Container,\n            typename Functor =\n            _maps_bits::Identity<typename Container::value_type> >\n  class FrontInserterBoolMap {\n  public:\n    typedef typename Functor::argument_type Key;\n    typedef bool Value;\n\n    /// Constructor\n    FrontInserterBoolMap(Container& _container,\n                         const Functor& _functor = Functor()) \n      : container(_container), functor(_functor) {}\n\n    /// The \\c set function of the map\n    void set(const Key& key, Value value) {\n      if (value) {\n\tcontainer.push_front(functor(key));\n      }\n    }\n    \n  private:\n    Container& container;    \n    Functor functor;\n  };\n\n  /// \\brief Writable bool map for storing each \\c true assigned element in \n  /// an insertable container.\n  ///\n  /// Writable bool map for storing each \\c true assigned element in an \n  /// insertable container. It will insert all the keys set to \\c true into\n  /// the container.\n  ///\n  /// For example, if you want to store the cut arcs of the strongly\n  /// connected components in a set you can use the next code:\n  ///\n  ///\\code\n  /// set<Edge> cut_edges;\n  /// InserterBoolMap<set<Edge> > inserter_map(cut_edges);\n  /// stronglyConnectedCutEdges(graph, cost, inserter_map);\n  ///\\endcode\n  ///\n  ///\\sa BackInserterBoolMap\n  ///\\sa FrontInserterBoolMap\n  template <typename Container,\n            typename Functor =\n            _maps_bits::Identity<typename Container::value_type> >\n  class InserterBoolMap {\n  public:\n    typedef typename Container::value_type Key;\n    typedef bool Value;\n\n    /// Constructor with specified iterator\n    \n    /// Constructor with specified iterator.\n    /// \\param _container The container for storing the elements.\n    /// \\param _it The elements will be inserted before this iterator.\n    /// \\param _functor The functor that is used when an element is stored.\n    InserterBoolMap(Container& _container, typename Container::iterator _it,\n                    const Functor& _functor = Functor()) \n      : container(_container), it(_it), functor(_functor) {}\n\n    /// Constructor\n\n    /// Constructor without specified iterator.\n    /// The elements will be inserted before <tt>_container.end()</tt>.\n    /// \\param _container The container for storing the elements.\n    /// \\param _functor The functor that is used when an element is stored.\n    InserterBoolMap(Container& _container, const Functor& _functor = Functor())\n      : container(_container), it(_container.end()), functor(_functor) {}\n\n    /// The \\c set function of the map\n    void set(const Key& key, Value value) {\n      if (value) {\n\tit = container.insert(it, functor(key));\n        ++it;\n      }\n    }\n    \n  private:\n    Container& container;\n    typename Container::iterator it;\n    Functor functor;\n  };\n\n  /// \\brief Writable bool map for filling each \\c true assigned element with a \n  /// given value.\n  ///\n  /// Writable bool map for filling each \\c true assigned element with a \n  /// given value. The value can set the container.\n  ///\n  /// The following code finds the connected components of a graph\n  /// and stores it in the \\c comp map:\n  ///\\code\n  /// typedef UGraph::NodeMap<int> ComponentMap;\n  /// ComponentMap comp(ugraph);\n  /// typedef FillBoolMap<UGraph::NodeMap<int> > ComponentFillerMap;\n  /// ComponentFillerMap filler(comp, 0);\n  ///\n  /// Dfs<UGraph>::DefProcessedMap<ComponentFillerMap>::Create dfs(ugraph);\n  /// dfs.processedMap(filler);\n  /// dfs.init();\n  /// for (NodeIt it(ugraph); it != INVALID; ++it) {\n  ///   if (!dfs.reached(it)) {\n  ///     dfs.addSource(it);\n  ///     dfs.start();\n  ///     ++filler.fillValue();\n  ///   }\n  /// }\n  ///\\endcode\n  template <typename Map>\n  class FillBoolMap {\n  public:\n    typedef typename Map::Key Key;\n    typedef bool Value;\n\n    /// Constructor\n    FillBoolMap(Map& _map, const typename Map::Value& _fill) \n      : map(_map), fill(_fill) {}\n\n    /// Constructor\n    FillBoolMap(Map& _map) \n      : map(_map), fill() {}\n\n    /// Gives back the current fill value\n    const typename Map::Value& fillValue() const {\n      return fill;\n    } \n\n    /// Gives back the current fill value\n    typename Map::Value& fillValue() {\n      return fill;\n    } \n\n    /// Sets the current fill value\n    void fillValue(const typename Map::Value& _fill) {\n      fill = _fill;\n    } \n\n    /// The \\c set function of the map\n    void set(const Key& key, Value value) {\n      if (value) {\n\tmap.set(key, fill);\n      }\n    }\n    \n  private:\n    Map& map;\n    typename Map::Value fill;\n  };\n\n\n  /// \\brief Writable bool map for storing the sequence number of \n  /// \\c true assignments.  \n  ///\n  /// Writable bool map that stores for each \\c true assigned elements  \n  /// the sequence number of this setting.\n  /// It makes it easy to calculate the leaving\n  /// order of the nodes in the \\c Dfs algorithm.\n  ///\n  ///\\code\n  /// typedef Graph::NodeMap<int> OrderMap;\n  /// OrderMap order(graph);\n  /// typedef SettingOrderBoolMap<OrderMap> OrderSetterMap;\n  /// OrderSetterMap setter(order);\n  /// Dfs<Graph>::DefProcessedMap<OrderSetterMap>::Create dfs(graph);\n  /// dfs.processedMap(setter);\n  /// dfs.init();\n  /// for (NodeIt it(graph); it != INVALID; ++it) {\n  ///   if (!dfs.reached(it)) {\n  ///     dfs.addSource(it);\n  ///     dfs.start();\n  ///   }\n  /// }\n  ///\\endcode\n  ///\n  /// The storing of the discovering order is more difficult because the\n  /// ReachedMap should be readable in the dfs algorithm but the setting\n  /// order map is not readable. Thus we must use the fork map:\n  ///\n  ///\\code\n  /// typedef Graph::NodeMap<int> OrderMap;\n  /// OrderMap order(graph);\n  /// typedef SettingOrderBoolMap<OrderMap> OrderSetterMap;\n  /// OrderSetterMap setter(order);\n  /// typedef Graph::NodeMap<bool> StoreMap;\n  /// StoreMap store(graph);\n  ///\n  /// typedef ForkWriteMap<StoreMap, OrderSetterMap> ReachedMap;\n  /// ReachedMap reached(store, setter);\n  ///\n  /// Dfs<Graph>::DefReachedMap<ReachedMap>::Create dfs(graph);\n  /// dfs.reachedMap(reached);\n  /// dfs.init();\n  /// for (NodeIt it(graph); it != INVALID; ++it) {\n  ///   if (!dfs.reached(it)) {\n  ///     dfs.addSource(it);\n  ///     dfs.start();\n  ///   }\n  /// }\n  ///\\endcode\n  template <typename Map>\n  class SettingOrderBoolMap {\n  public:\n    typedef typename Map::Key Key;\n    typedef bool Value;\n\n    /// Constructor\n    SettingOrderBoolMap(Map& _map) \n      : map(_map), counter(0) {}\n\n    /// Number of set operations.\n    int num() const {\n      return counter;\n    }\n\n    /// The \\c set function of the map\n    void set(const Key& key, Value value) {\n      if (value) {\n\tmap.set(key, counter++);\n      }\n    }\n    \n  private:\n    Map& map;\n    int counter;\n  };\n\n  /// @}\n}\n\n#endif // LEMON_MAPS_H\n"
  },
  {
    "path": "src/lemon/math.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_MATH_H\n#define LEMON_MATH_H\n\n///\\ingroup misc\n///\\file\n///\\brief Some extensions to the standard \\c cmath library.\n///\n///Some extensions to the standard \\c cmath library.\n///\n///This file includes the standard math library (cmath).\n\n#include<cmath>\n\nnamespace lemon {\n\n  /// \\addtogroup misc\n  /// @{\n  \n  /// The Euler constant\n  const long double E       = 2.7182818284590452353602874713526625L;\n  /// log_2(e)\n  const long double LOG2E   = 1.4426950408889634073599246810018921L;\n  /// log_10(e)\n  const long double LOG10E  = 0.4342944819032518276511289189166051L;\n  /// ln(2)\n  const long double LN2     = 0.6931471805599453094172321214581766L;\n  /// ln(10)\n  const long double LN10    = 2.3025850929940456840179914546843642L;\n  /// pi\n  const long double PI      = 3.1415926535897932384626433832795029L;\n  /// pi/2\n  const long double PI_2    = 1.5707963267948966192313216916397514L;\n  /// pi/4\n  const long double PI_4    = 0.7853981633974483096156608458198757L;\n  /// sqrt(2)\n  const long double SQRT2   = 1.4142135623730950488016887242096981L;\n  /// 1/sqrt(2)\n  const long double SQRT1_2 = 0.7071067811865475244008443621048490L;\n  \n\n  /// @}\n\n} //namespace lemon\n\n#endif //LEMON_TOLERANCE_H\n"
  },
  {
    "path": "src/lemon/smart_graph.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_SMART_GRAPH_H\n#define LEMON_SMART_GRAPH_H\n\n///\\ingroup graphs\n///\\file\n///\\brief SmartGraph and SmartUGraph classes.\n\n#include <vector>\n\n#include <lemon/bits/invalid.h>\n\n#include <lemon/bits/base_extender.h>\n#include <lemon/bits/graph_extender.h>\n\n#include <lemon/bits/utility.h>\n#include <lemon/error.h>\n\n#include <lemon/bits/graph_extender.h>\n\nnamespace lemon {\n\t\n\tclass SmartGraph;\n\t///Base of SmartGraph\n\t\n\t///Base of SmartGraph\n\t///\n\tclass SmartGraphBase {\n\tprotected:\n\t\t\n\t\tstruct NodeT \n\t\t{\n\t\t\tint first_in, first_out;      \n\t\t\tNodeT() {}\n\t\t};\n\t\tstruct EdgeT \n\t\t{\n\t\t\tint target, source, next_in, next_out;      \n\t\t\tEdgeT() {}  \n\t\t};\n\t\t\n\t\tstd::vector<NodeT> nodes;\n\t\t\n\t\tstd::vector<EdgeT> edges;\n\t\t\n\t\t\n\tpublic:\n\t\t\n\t\ttypedef SmartGraphBase Graph;\n\t\t\n\t\tclass Node;\n\t\tclass Edge;\n\t\t\n\t\t\n\tpublic:\n\t\t\n\t\tSmartGraphBase() : nodes(), edges() { }\n\t\tSmartGraphBase(const SmartGraphBase &_g) \n\t\t: nodes(_g.nodes), edges(_g.edges) { }\n\t\t\n\t\ttypedef True NodeNumTag;\n\t\ttypedef True EdgeNumTag;\n\t\t\n\t\tint nodeNum() const { return nodes.size(); }\n\t\tint edgeNum() const { return edges.size(); }\n\t\t\n\t\tint maxNodeId() const { return nodes.size()-1; }\n\t\tint maxEdgeId() const { return edges.size()-1; }\n\t\t\n\t\tNode addNode() {\n\t\t\tint n = nodes.size();     \n\t\t\tnodes.push_back(NodeT());\n\t\t\tnodes[n].first_in = -1;\n\t\t\tnodes[n].first_out = -1;\n\t\t\treturn Node(n);\n\t\t}\n\t\t\n\t\tEdge addEdge(Node u, Node v) {\n\t\t\tint n = edges.size(); \n\t\t\tedges.push_back(EdgeT());\n\t\t\tedges[n].source = u.id; \n\t\t\tedges[n].target = v.id;\n\t\t\tedges[n].next_out = nodes[u.id].first_out;\n\t\t\tedges[n].next_in = nodes[v.id].first_in;\n\t\t\tnodes[u.id].first_out = nodes[v.id].first_in = n;\n\t\t\t\n\t\t\treturn Edge(n);\n\t\t}\n\t\t\n\t\tvoid clear() {\n\t\t\tedges.clear();\n\t\t\tnodes.clear();\n\t\t}\n\t\t\n\t\tNode source(Edge e) const { return Node(edges[e.id].source); }\n\t\tNode target(Edge e) const { return Node(edges[e.id].target); }\n\t\t\n\t\tstatic int id(Node v) { return v.id; }\n\t\tstatic int id(Edge e) { return e.id; }\n\t\t\n\t\tstatic Node nodeFromId(int id) { return Node(id);}\n\t\tstatic Edge edgeFromId(int id) { return Edge(id);}\n\t\t\n\t\tclass Node {\n\t\t\tfriend class SmartGraphBase;\n\t\t\tfriend class SmartGraph;\n\t\t\t\n\t\tprotected:\n\t\t\tint id;\n\t\t\texplicit Node(int _id) : id(_id) {}\n\t\tpublic:\n\t\t\tNode() {}\n\t\t\tNode (Invalid) : id(-1) {}\n\t\t\tbool operator==(const Node i) const {return id == i.id;}\n\t\t\tbool operator!=(const Node i) const {return id != i.id;}\n\t\t\tbool operator<(const Node i) const {return id < i.id;}\n\t\t};\n\t\t\n\t\t\n\t\tclass Edge {\n\t\t\tfriend class SmartGraphBase;\n\t\t\tfriend class SmartGraph;\n\t\t\t\n\t\tprotected:\n\t\t\tint id;\n\t\t\texplicit Edge(int _id) : id(_id) {}\n\t\tpublic:\n\t\t\tEdge() { }\n\t\t\tEdge (Invalid) : id(-1) {}\n\t\t\tbool operator==(const Edge i) const {return id == i.id;}\n\t\t\tbool operator!=(const Edge i) const {return id != i.id;}\n\t\t\tbool operator<(const Edge i) const {return id < i.id;}\n\t\t};\n\t\t\n\t\tvoid first(Node& node) const {\n\t\t\tnode.id = nodes.size() - 1;\n\t\t}\n\t\t\n\t\tstatic void next(Node& node) {\n\t\t\t--node.id;\n\t\t}\n\t\t\n\t\tvoid first(Edge& edge) const {\n\t\t\tedge.id = edges.size() - 1;\n\t\t}\n\t\t\n\t\tstatic void next(Edge& edge) {\n\t\t\t--edge.id;\n\t\t}\n\t\t\n\t\tvoid firstOut(Edge& edge, const Node& node) const {\n\t\t\tedge.id = nodes[node.id].first_out;\n\t\t}\n\t\t\n\t\tvoid nextOut(Edge& edge) const {\n\t\t\tedge.id = edges[edge.id].next_out;\n\t\t}\n\t\t\n\t\tvoid firstIn(Edge& edge, const Node& node) const {\n\t\t\tedge.id = nodes[node.id].first_in;\n\t\t}\n\t\t\n\t\tvoid nextIn(Edge& edge) const {\n\t\t\tedge.id = edges[edge.id].next_in;\n\t\t}\n\t\t\n\t};\n\t\n\ttypedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;\n\t\n\t///\\ingroup graphs\n\t///\n\t///\\brief A smart graph class.\n\t///\n\t///This is a simple and fast graph implementation.\n\t///It is also quite memory efficient, but at the price\n\t///that <b> it does support only limited (only stack-like)\n\t///node and edge deletions</b>.\n\t///It conforms to \n\t///the \\ref concepts::Graph \"Graph concept\" with an\n\t///important extra feature that\n\t///its maps are real \\ref concepts::ReferenceMap \"reference map\"s.\n\t///\n\t///\\sa concepts::Graph.\n\t///\n\t///\\author Alpar Juttner\n\tclass SmartGraph : public ExtendedSmartGraphBase {\n\tpublic:\n\t\t\n\t\ttypedef ExtendedSmartGraphBase Parent;\n\t\t\n\tprivate:\n\t\t\n\t\t///SmartGraph is \\e not copy constructible. Use GraphCopy() instead.\n\t\t\n\t\t///SmartGraph is \\e not copy constructible. Use GraphCopy() instead.\n\t\t///\n\t\tSmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};\n\t\t///\\brief Assignment of SmartGraph to another one is \\e not allowed.\n\t\t///Use GraphCopy() instead.\n\t\t\n\t\t///Assignment of SmartGraph to another one is \\e not allowed.\n\t\t///Use GraphCopy() instead.\n\t\tvoid operator=(const SmartGraph &) {}\n\t\t\n\tpublic:\n\t\t\n\t\t/// Constructor\n\t\t\n\t\t/// Constructor.\n\t\t///\n\t\tSmartGraph() {};\n\t\t\n\t\t///Add a new node to the graph.\n\t\t\n\t\t/// \\return the new node.\n\t\t///\n\t\tNode addNode() { return Parent::addNode(); }\n\t\t\n\t\t///Add a new edge to the graph.\n\t\t\n\t\t///Add a new edge to the graph with source node \\c s\n\t\t///and target node \\c t.\n\t\t///\\return the new edge.\n\t\tEdge addEdge(const Node& s, const Node& t) { \n\t\t\treturn Parent::addEdge(s, t); \n\t\t}\n\t\t\n\t\t/// \\brief Using this it is possible to avoid the superfluous memory\n\t\t/// allocation.\n\t\t\n\t\t/// Using this it is possible to avoid the superfluous memory\n\t\t/// allocation: if you know that the graph you want to build will\n\t\t/// be very large (e.g. it will contain millions of nodes and/or edges)\n\t\t/// then it is worth reserving space for this amount before starting\n\t\t/// to build the graph.\n\t\t/// \\sa reserveEdge\n\t\tvoid reserveNode(int n) { nodes.reserve(n); };\n\t\t\n\t\t/// \\brief Using this it is possible to avoid the superfluous memory\n\t\t/// allocation.\n\t\t\n\t\t/// Using this it is possible to avoid the superfluous memory\n\t\t/// allocation: if you know that the graph you want to build will\n\t\t/// be very large (e.g. it will contain millions of nodes and/or edges)\n\t\t/// then it is worth reserving space for this amount before starting\n\t\t/// to build the graph.\n\t\t/// \\sa reserveNode\n\t\tvoid reserveEdge(int m) { edges.reserve(m); };\n\t\t\n\t\t///Clear the graph.\n\t\t\n\t\t///Erase all the nodes and edges from the graph.\n\t\t///\n\t\tvoid clear() {\n\t\t\tParent::clear();\n\t\t}\n\t\t\n\t\t///Split a node.\n\t\t\n\t\t///This function splits a node. First a new node is added to the graph,\n\t\t///then the source of each outgoing edge of \\c n is moved to this new node.\n\t\t///If \\c connect is \\c true (this is the default value), then a new edge\n\t\t///from \\c n to the newly created node is also added.\n\t\t///\\return The newly created node.\n\t\t///\n\t\t///\\note The <tt>Edge</tt>s\n\t\t///referencing a moved edge remain\n\t\t///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s\n\t\t///may be invalidated.\n\t\t///\\warning This functionality cannot be used together with the Snapshot\n\t\t///feature.\n\t\t///\\todo It could be implemented in a bit faster way.\n\t\tNode split(Node n, bool connect = true)\n\t\t{\n\t\t\tNode b = addNode();\n\t\t\tnodes[b.id].first_out=nodes[n.id].first_out;\n\t\t\tnodes[n.id].first_out=-1;\n\t\t\tfor(int i=nodes[b.id].first_out;i!=-1;i++) edges[i].source=b.id;\n\t\t\tif(connect) addEdge(n,b);\n\t\t\treturn b;\n\t\t}\n\t\t\n\tpublic:\n\t\t\n\t\tclass Snapshot;\n\t\t\n\tprotected:\n\t\t\n\t\tvoid restoreSnapshot(const Snapshot &s)\n\t\t{\n\t\t\twhile(s.edge_num<edges.size()) {\n\t\t\t\tEdge edge = edgeFromId(edges.size()-1);\n\t\t\t\tParent::notifier(Edge()).erase(edge);\n\t\t\t\tnodes[edges.back().source].first_out=edges.back().next_out;\n\t\t\t\tnodes[edges.back().target].first_in=edges.back().next_in;\n\t\t\t\tedges.pop_back();\n\t\t\t}\n\t\t\twhile(s.node_num<nodes.size()) {\n\t\t\t\tNode node = nodeFromId(nodes.size()-1);\n\t\t\t\tParent::notifier(Node()).erase(node);\n\t\t\t\tnodes.pop_back();\n\t\t\t}\n\t\t}    \n\t\t\n\tpublic:\n\t\t\n\t\t///Class to make a snapshot of the graph and to restrore to it later.\n\t\t\n\t\t///Class to make a snapshot of the graph and to restrore to it later.\n\t\t///\n\t\t///The newly added nodes and edges can be removed using the\n\t\t///restore() function.\n\t\t///\\note After you restore a state, you cannot restore\n\t\t///a later state, in other word you cannot add again the edges deleted\n\t\t///by restore() using another one Snapshot instance.\n\t\t///\n\t\t///\\warning If you do not use correctly the snapshot that can cause\n\t\t///either broken program, invalid state of the graph, valid but\n\t\t///not the restored graph or no change. Because the runtime performance\n\t\t///the validity of the snapshot is not stored.\n\t\tclass Snapshot \n\t\t{\n\t\t\tSmartGraph *g;\n\t\tprotected:\n\t\t\tfriend class SmartGraph;\n\t\t\tunsigned int node_num;\n\t\t\tunsigned int edge_num;\n\t\tpublic:\n\t\t\t///Default constructor.\n\t\t\t\n\t\t\t///Default constructor.\n\t\t\t///To actually make a snapshot you must call save().\n\t\t\t///\n\t\t\tSnapshot() : g(0) {}\n\t\t\t///Constructor that immediately makes a snapshot\n\t\t\t\n\t\t\t///This constructor immediately makes a snapshot of the graph.\n\t\t\t///\\param _g The graph we make a snapshot of.\n\t\t\tSnapshot(SmartGraph &_g) :g(&_g) {\n\t\t\t\tnode_num=g->nodes.size();\n\t\t\t\tedge_num=g->edges.size();\n\t\t\t}\n\t\t\t\n\t\t\t///Make a snapshot.\n\t\t\t\n\t\t\t///Make a snapshot of the graph.\n\t\t\t///\n\t\t\t///This function can be called more than once. In case of a repeated\n\t\t\t///call, the previous snapshot gets lost.\n\t\t\t///\\param _g The graph we make the snapshot of.\n\t\t\tvoid save(SmartGraph &_g) \n\t\t\t{\n\t\t\t\tg=&_g;\n\t\t\t\tnode_num=g->nodes.size();\n\t\t\t\tedge_num=g->edges.size();\n\t\t\t}\n\t\t\t\n\t\t\t///Undo the changes until a snapshot.\n\t\t\t\n\t\t\t///Undo the changes until a snapshot created by save().\n\t\t\t///\n\t\t\t///\\note After you restored a state, you cannot restore\n\t\t\t///a later state, in other word you cannot add again the edges deleted\n\t\t\t///by restore().\n\t\t\tvoid restore()\n\t\t\t{\n\t\t\t\tg->restoreSnapshot(*this);\n\t\t\t}\n\t\t};\n\t};\n\t\n\t\n\tclass SmartUGraphBase {\n\t\t\n\tprotected:\n\t\t\n\t\tstruct NodeT {\n\t\t\tint first_out;\n\t\t};\n\t\t\n\t\tstruct EdgeT {\n\t\t\tint target;\n\t\t\tint next_out;\n\t\t};\n\t\t\n\t\tstd::vector<NodeT> nodes;\n\t\tstd::vector<EdgeT> edges;\n\t\t\n\t\tint first_free_edge;\n\t\t\n\tpublic:\n\t\t\n\t\ttypedef SmartUGraphBase Graph;\n\t\t\n\t\tclass Node;\n\t\tclass Edge;\n\t\tclass UEdge;\n\t\t\n\t\tclass Node {\n\t\t\tfriend class SmartUGraphBase;\n\t\tprotected:\n\t\t\t\n\t\t\tint id;\n\t\t\texplicit Node(int pid) { id = pid;}\n\t\t\t\n\t\tpublic:\n\t\t\tNode() {}\n\t\t\tNode (Invalid) { id = -1; }\n\t\t\tbool operator==(const Node& node) const {return id == node.id;}\n\t\t\tbool operator!=(const Node& node) const {return id != node.id;}\n\t\t\tbool operator<(const Node& node) const {return id < node.id;}\n\t\t};\n\t\t\n\t\tclass UEdge {\n\t\t\tfriend class SmartUGraphBase;\n\t\tprotected:\n\t\t\t\n\t\t\tint id;\n\t\t\texplicit UEdge(int pid) { id = pid;}\n\t\t\t\n\t\tpublic:\n\t\t\tUEdge() {}\n\t\t\tUEdge (Invalid) { id = -1; }\n\t\t\tbool operator==(const UEdge& edge) const {return id == edge.id;}\n\t\t\tbool operator!=(const UEdge& edge) const {return id != edge.id;}\n\t\t\tbool operator<(const UEdge& edge) const {return id < edge.id;}\n\t\t};\n\t\t\n\t\tclass Edge {\n\t\t\tfriend class SmartUGraphBase;\n\t\tprotected:\n\t\t\t\n\t\t\tint id;\n\t\t\texplicit Edge(int pid) { id = pid;}\n\t\t\t\n\t\tpublic:\n\t\t\toperator UEdge() const { return uEdgeFromId(id / 2); }\n\t\t\t\n\t\t\tEdge() {}\n\t\t\tEdge (Invalid) { id = -1; }\n\t\t\tbool operator==(const Edge& edge) const {return id == edge.id;}\n\t\t\tbool operator!=(const Edge& edge) const {return id != edge.id;}\n\t\t\tbool operator<(const Edge& edge) const {return id < edge.id;}\n\t\t};\n\t\t\n\t\t\n\t\t\n\t\tSmartUGraphBase()\n\t\t: nodes(), edges() {}\n\t\t\n\t\t\n\t\tint maxNodeId() const { return nodes.size()-1; } \n\t\tint maxUEdgeId() const { return edges.size() / 2 - 1; }\n\t\tint maxEdgeId() const { return edges.size()-1; }\n\t\t\n\t\tNode source(Edge e) const { return Node(edges[e.id ^ 1].target); }\n\t\tNode target(Edge e) const { return Node(edges[e.id].target); }\n\t\t\n\t\tNode source(UEdge e) const { return Node(edges[2 * e.id].target); }\n\t\tNode target(UEdge e) const { return Node(edges[2 * e.id + 1].target); }\n\t\t\n\t\tstatic bool direction(Edge e) {\n\t\t\treturn (e.id & 1) == 1;\n\t\t}\n\t\t\n\t\tstatic Edge direct(UEdge e, bool d) {\n\t\t\treturn Edge(e.id * 2 + (d ? 1 : 0));\n\t\t}\n\t\t\n\t\tvoid first(Node& node) const { \n\t\t\tnode.id = nodes.size() - 1;\n\t\t}\n\t\t\n\t\tvoid next(Node& node) const {\n\t\t\t--node.id;\n\t\t}\n\t\t\n\t\tvoid first(Edge& edge) const { \n\t\t\tedge.id = edges.size() - 1;\n\t\t}\n\t\t\n\t\tvoid next(Edge& edge) const {\n\t\t\t--edge.id;\n\t\t}\n\t\t\n\t\tvoid first(UEdge& edge) const { \n\t\t\tedge.id = edges.size() / 2 - 1;\n\t\t}\n\t\t\n\t\tvoid next(UEdge& edge) const {\n\t\t\t--edge.id;\n\t\t}\n\t\t\n\t\tvoid firstOut(Edge &edge, const Node& v) const {\n\t\t\tedge.id = nodes[v.id].first_out;\n\t\t}\n\t\tvoid nextOut(Edge &edge) const {\n\t\t\tedge.id = edges[edge.id].next_out;\n\t\t}\n\t\t\n\t\tvoid firstIn(Edge &edge, const Node& v) const {\n\t\t\tedge.id = ((nodes[v.id].first_out) ^ 1);\n\t\t\tif (edge.id == -2) edge.id = -1;\n\t\t}\n\t\tvoid nextIn(Edge &edge) const {\n\t\t\tedge.id = ((edges[edge.id ^ 1].next_out) ^ 1);\n\t\t\tif (edge.id == -2) edge.id = -1;\n\t\t}\n\t\t\n\t\tvoid firstInc(UEdge &edge, bool& d, const Node& v) const {\n\t\t\tint de = nodes[v.id].first_out;\n\t\t\tif (de != -1) {\n\t\t\t\tedge.id = de / 2;\n\t\t\t\td = ((de & 1) == 1);\n\t\t\t} else {\n\t\t\t\tedge.id = -1;\n\t\t\t\td = true;\n\t\t\t}\n\t\t}\n\t\tvoid nextInc(UEdge &edge, bool& d) const {\n\t\t\tint de = (edges[(edge.id * 2) | (d ? 1 : 0)].next_out);\n\t\t\tif (de != -1) {\n\t\t\t\tedge.id = de / 2;\n\t\t\t\td = ((de & 1) == 1);\n\t\t\t} else {\n\t\t\t\tedge.id = -1;\n\t\t\t\td = true;      \n\t\t\t}\n\t\t}\n\t\t\n\t\tstatic int id(Node v) { return v.id; }\n\t\tstatic int id(Edge e) { return e.id; }\n\t\tstatic int id(UEdge e) { return e.id; }\n\t\t\n\t\tstatic Node nodeFromId(int id) { return Node(id);}\n\t\tstatic Edge edgeFromId(int id) { return Edge(id);}\n\t\tstatic UEdge uEdgeFromId(int id) { return UEdge(id);}\n\t\t\n\t\tNode addNode() {     \n\t\t\tint n = nodes.size();\n\t\t\tnodes.push_back(NodeT());\n\t\t\tnodes[n].first_out = -1;\n\t\t\t\n\t\t\treturn Node(n);\n\t\t}\n\t\t\n\t\tUEdge addEdge(Node u, Node v) {\n\t\t\tint n = edges.size();\n\t\t\tedges.push_back(EdgeT());\n\t\t\tedges.push_back(EdgeT());\n\t\t\t\n\t\t\tedges[n].target = u.id;\n\t\t\tedges[n | 1].target = v.id;\n\t\t\t\n\t\t\tedges[n].next_out = nodes[v.id].first_out;\n\t\t\tnodes[v.id].first_out = n;\n\t\t\t\n\t\t\tedges[n | 1].next_out = nodes[u.id].first_out;\t\n\t\t\tnodes[u.id].first_out = (n | 1);\n\t\t\t\n\t\t\treturn UEdge(n / 2);\n\t\t}\n\t\t\n\t\tvoid clear() {\n\t\t\tedges.clear();\n\t\t\tnodes.clear();\n\t\t}\n\t\t\n\t};\n\t\n\ttypedef UGraphExtender<SmartUGraphBase> ExtendedSmartUGraphBase;\n\t\n\t/// \\ingroup graphs\n\t///\n\t/// \\brief A smart undirected graph class.\n\t///\n\t/// This is a simple and fast undirected graph implementation.\n\t/// It is also quite memory efficient, but at the price\n\t/// that <b> it does support only limited (only stack-like)\n\t/// node and edge deletions</b>.\n\t/// Except from this it conforms to \n\t/// the \\ref concepts::UGraph \"UGraph concept\".\n\t///\n\t///It also has an\n\t///important extra feature that\n\t///its maps are real \\ref concepts::ReferenceMap \"reference map\"s.\n\t///\n\t/// \\sa concepts::UGraph.\n\t///\n\tclass SmartUGraph : public ExtendedSmartUGraphBase {\n\tprivate:\n\t\t\n\t\t///SmartUGraph is \\e not copy constructible. Use UGraphCopy() instead.\n\t\t\n\t\t///SmartUGraph is \\e not copy constructible. Use UGraphCopy() instead.\n\t\t///\n\t\tSmartUGraph(const SmartUGraph &) : ExtendedSmartUGraphBase() {};\n\t\t\n\t\t///\\brief Assignment of SmartUGraph to another one is \\e not allowed.\n\t\t///Use UGraphCopy() instead.\n\t\t\n\t\t///Assignment of SmartUGraph to another one is \\e not allowed.\n\t\t///Use UGraphCopy() instead.\n\t\tvoid operator=(const SmartUGraph &) {}\n\t\t\n\tpublic:\n\t\t\n\t\ttypedef ExtendedSmartUGraphBase Parent;\n\t\ttypedef Parent::OutEdgeIt IncEdgeIt;\n\t\t\n\t\t/// Constructor\n\t\t\n\t\t/// Constructor.\n\t\t///\n\t\tSmartUGraph() {}\n\t\t\n\t\t///Add a new node to the graph.\n\t\t\n\t\t/// \\return the new node.\n\t\t///\n\t\tNode addNode() { return Parent::addNode(); }\n\t\t\n\t\t///Add a new undirected edge to the graph.\n\t\t\n\t\t///Add a new undirected edge to the graph with node \\c s\n\t\t///and \\c t.\n\t\t///\\return the new undirected edge.\n\t\tUEdge addEdge(const Node& s, const Node& t) { \n\t\t\treturn Parent::addEdge(s, t); \n\t\t}\n\t\t\n\t\t///Clear the graph.\n\t\t\n\t\t///Erase all the nodes and edges from the graph.\n\t\t///\n\t\tvoid clear() {\n\t\t\tParent::clear();\n\t\t}\n\t\t\n\tpublic:\n\t\t\n\t\tclass Snapshot;\n\t\t\n\tprotected:\n\t\t\n\t\tvoid saveSnapshot(Snapshot &s)\n\t\t{\n\t\t\ts.graph = this;\n\t\t\ts.node_num = nodes.size();\n\t\t\ts.edge_num = edges.size();\n\t\t}\n\t\t\n\t\tvoid restoreSnapshot(const Snapshot &s)\n\t\t{\n\t\t\twhile(s.edge_num<edges.size()) {\n\t\t\t\tint n=edges.size()-1;\n\t\t\t\tUEdge edge=uEdgeFromId(n/2);\n\t\t\t\tParent::notifier(UEdge()).erase(edge);\n\t\t\t\tstd::vector<Edge> dir;\n\t\t\t\tdir.push_back(edgeFromId(n));\n\t\t\t\tdir.push_back(edgeFromId(n-1));\n\t\t\t\tParent::notifier(Edge()).erase(dir);\n\t\t\t\tnodes[edges[n].target].first_out=edges[n].next_out;\n\t\t\t\tnodes[edges[n-1].target].first_out=edges[n-1].next_out;\n\t\t\t\tedges.pop_back();\n\t\t\t\tedges.pop_back();\n\t\t\t}\n\t\t\twhile(s.node_num<nodes.size()) {\n\t\t\t\tint n=nodes.size()-1;\n\t\t\t\tNode node = nodeFromId(n);\n\t\t\t\tParent::notifier(Node()).erase(node);\n\t\t\t\tnodes.pop_back();\n\t\t\t}\n\t\t}    \n\t\t\n\tpublic:\n\t\t\n\t\t///Class to make a snapshot of the graph and to restrore to it later.\n\t\t\n\t\t///Class to make a snapshot of the graph and to restrore to it later.\n\t\t///\n\t\t///The newly added nodes and edges can be removed using the\n\t\t///restore() function.\n\t\t///\n\t\t///\\note After you restore a state, you cannot restore\n\t\t///a later state, in other word you cannot add again the edges deleted\n\t\t///by restore() using another one Snapshot instance.\n\t\t///\n\t\t///\\warning If you do not use correctly the snapshot that can cause\n\t\t///either broken program, invalid state of the graph, valid but\n\t\t///not the restored graph or no change. Because the runtime performance\n\t\t///the validity of the snapshot is not stored.\n\t\tclass Snapshot \n\t\t{\n\t\t\tSmartUGraph *graph;\n\t\tprotected:\n\t\t\tfriend class SmartUGraph;\n\t\t\tunsigned int node_num;\n\t\t\tunsigned int edge_num;\n\t\tpublic:\n\t\t\t///Default constructor.\n\t\t\t\n\t\t\t///Default constructor.\n\t\t\t///To actually make a snapshot you must call save().\n\t\t\t///\n\t\t\tSnapshot() : graph(0) {}\n\t\t\t///Constructor that immediately makes a snapshot\n\t\t\t\n\t\t\t///This constructor immediately makes a snapshot of the graph.\n\t\t\t///\\param g The graph we make a snapshot of.\n\t\t\tSnapshot(SmartUGraph &g) {\n\t\t\t\tg.saveSnapshot(*this);\n\t\t\t}\n\t\t\t\n\t\t\t///Make a snapshot.\n\t\t\t\n\t\t\t///Make a snapshot of the graph.\n\t\t\t///\n\t\t\t///This function can be called more than once. In case of a repeated\n\t\t\t///call, the previous snapshot gets lost.\n\t\t\t///\\param g The graph we make the snapshot of.\n\t\t\tvoid save(SmartUGraph &g) \n\t\t\t{\n\t\t\t\tg.saveSnapshot(*this);\n\t\t\t}\n\t\t\t\n\t\t\t///Undo the changes until a snapshot.\n\t\t\t\n\t\t\t///Undo the changes until a snapshot created by save().\n\t\t\t///\n\t\t\t///\\note After you restored a state, you cannot restore\n\t\t\t///a later state, in other word you cannot add again the edges deleted\n\t\t\t///by restore().\n\t\t\tvoid restore()\n\t\t\t{\n\t\t\t\tgraph->restoreSnapshot(*this);\n\t\t\t}\n\t\t};\n\t};\n\t\n\t\n\tclass SmartBpUGraphBase {\n\tpublic:\n\t\t\n\t\tclass NodeSetError : public LogicError {\n\t\tpublic:\n\t\t\tvirtual const char* what() const throw() { \n\t\t\t\treturn \"lemon::SmartBpUGraph::NodeSetError\";\n\t\t\t}\n\t\t};\n\t\t\n\tprotected:\n\t\t\n\t\tstruct NodeT {\n\t\t\tint first;\n\t\t\tNodeT() {}\n\t\t\tNodeT(int _first) : first(_first) {}\n\t\t};\n\t\t\n\t\tstruct UEdgeT {\n\t\t\tint aNode, next_out;\n\t\t\tint bNode, next_in;\n\t\t};\n\t\t\n\t\tstd::vector<NodeT> aNodes;\n\t\tstd::vector<NodeT> bNodes;\n\t\t\n\t\tstd::vector<UEdgeT> edges;\n\t\t\n\tpublic:\n\t\t\n\t\tclass Node {\n\t\t\tfriend class SmartBpUGraphBase;\n\t\tprotected:\n\t\t\tint id;\n\t\t\t\n\t\t\texplicit Node(int _id) : id(_id) {}\n\t\tpublic:\n\t\t\tNode() {}\n\t\t\tNode(Invalid) : id(-1) {}\n\t\t\tbool operator==(const Node i) const {return id==i.id;}\n\t\t\tbool operator!=(const Node i) const {return id!=i.id;}\n\t\t\tbool operator<(const Node i) const {return id<i.id;}\n\t\t};\n\t\t\n\t\tclass UEdge {\n\t\t\tfriend class SmartBpUGraphBase;\n\t\tprotected:\n\t\t\tint id;\n\t\t\t\n\t\t\tUEdge(int _id) : id(_id) {}\n\t\tpublic:\n\t\t\tUEdge() {}\n\t\t\tUEdge(Invalid) : id(-1) {}\n\t\t\tbool operator==(const UEdge i) const {return id==i.id;}\n\t\t\tbool operator!=(const UEdge i) const {return id!=i.id;}\n\t\t\tbool operator<(const UEdge i) const {return id<i.id;}\n\t\t};\n\t\t\n\t\tvoid firstANode(Node& node) const {\n\t\t\tnode.id = 2 * aNodes.size() - 2;\n\t\t\tif (node.id < 0) node.id = -1; \n\t\t}\n\t\tvoid nextANode(Node& node) const {\n\t\t\tnode.id -= 2;\n\t\t\tif (node.id < 0) node.id = -1; \n\t\t}\n\t\t\n\t\tvoid firstBNode(Node& node) const {\n\t\t\tnode.id = 2 * bNodes.size() - 1;\n\t\t}\n\t\tvoid nextBNode(Node& node) const {\n\t\t\tnode.id -= 2;\n\t\t}\n\t\t\n\t\tvoid first(Node& node) const {\n\t\t\tif (aNodes.size() > 0) {\n\t\t\t\tnode.id = 2 * aNodes.size() - 2;\n\t\t\t} else {\n\t\t\t\tnode.id = 2 * bNodes.size() - 1;\n\t\t\t}\n\t\t}\n\t\tvoid next(Node& node) const {\n\t\t\tnode.id -= 2;\n\t\t\tif (node.id == -2) {\n\t\t\t\tnode.id = 2 * bNodes.size() - 1;\n\t\t\t}\n\t\t}\n\t\t\n\t\tvoid first(UEdge& edge) const {\n\t\t\tedge.id = edges.size() - 1;\n\t\t}\n\t\tvoid next(UEdge& edge) const {\n\t\t\t--edge.id;\n\t\t}\n\t\t\n\t\tvoid firstFromANode(UEdge& edge, const Node& node) const {\n\t\t\tLEMON_ASSERT((node.id & 1) == 0, NodeSetError());\n\t\t\tedge.id = aNodes[node.id >> 1].first;\n\t\t}\n\t\tvoid nextFromANode(UEdge& edge) const {\n\t\t\tedge.id = edges[edge.id].next_out;\n\t\t}\n\t\t\n\t\tvoid firstFromBNode(UEdge& edge, const Node& node) const {\n\t\t\tLEMON_ASSERT((node.id & 1) == 1, NodeSetError());\n\t\t\tedge.id = bNodes[node.id >> 1].first;\n\t\t}\n\t\tvoid nextFromBNode(UEdge& edge) const {\n\t\t\tedge.id = edges[edge.id].next_in;\n\t\t}\n\t\t\n\t\tstatic int id(const Node& node) {\n\t\t\treturn node.id;\n\t\t}\n\t\tstatic Node nodeFromId(int id) {\n\t\t\treturn Node(id);\n\t\t}\n\t\tint maxNodeId() const {\n\t\t\treturn aNodes.size() > bNodes.size() ?\n\t\t\taNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;\n\t\t}\n\t\t\n\t\tstatic int id(const UEdge& edge) {\n\t\t\treturn edge.id;\n\t\t}\n\t\tstatic UEdge uEdgeFromId(int id) {\n\t\t\treturn UEdge(id);\n\t\t}\n\t\tint maxUEdgeId() const {\n\t\t\treturn edges.size();\n\t\t}\n\t\t\n\t\tstatic int aNodeId(const Node& node) {\n\t\t\treturn node.id >> 1;\n\t\t}\n\t\tstatic Node nodeFromANodeId(int id) {\n\t\t\treturn Node(id << 1);\n\t\t}\n\t\tint maxANodeId() const {\n\t\t\treturn aNodes.size();\n\t\t}\n\t\t\n\t\tstatic int bNodeId(const Node& node) {\n\t\t\treturn node.id >> 1;\n\t\t}\n\t\tstatic Node nodeFromBNodeId(int id) {\n\t\t\treturn Node((id << 1) + 1);\n\t\t}\n\t\tint maxBNodeId() const {\n\t\t\treturn bNodes.size();\n\t\t}\n\t\t\n\t\tNode aNode(const UEdge& edge) const {\n\t\t\treturn Node(edges[edge.id].aNode);\n\t\t}\n\t\tNode bNode(const UEdge& edge) const {\n\t\t\treturn Node(edges[edge.id].bNode);\n\t\t}\n\t\t\n\t\tstatic bool aNode(const Node& node) {\n\t\t\treturn (node.id & 1) == 0;\n\t\t}\n\t\t\n\t\tstatic bool bNode(const Node& node) {\n\t\t\treturn (node.id & 1) == 1;\n\t\t}\n\t\t\n\t\tNode addANode() {\n\t\t\tNodeT nodeT;\n\t\t\tnodeT.first = -1;\n\t\t\taNodes.push_back(nodeT);\n\t\t\treturn Node(aNodes.size() * 2 - 2);\n\t\t}\n\t\t\n\t\tNode addBNode() {\n\t\t\tNodeT nodeT;\n\t\t\tnodeT.first = -1;\n\t\t\tbNodes.push_back(nodeT);\n\t\t\treturn Node(bNodes.size() * 2 - 1);\n\t\t}\n\t\t\n\t\tUEdge addEdge(const Node& source, const Node& target) {\n\t\t\tLEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());\n\t\t\tUEdgeT edgeT;\n\t\t\tif ((source.id & 1) == 0) {\n\t\t\t\tedgeT.aNode = source.id;\n\t\t\t\tedgeT.bNode = target.id;\n\t\t\t} else {\n\t\t\t\tedgeT.aNode = target.id;\n\t\t\t\tedgeT.bNode = source.id;\n\t\t\t}\n\t\t\tedgeT.next_out = aNodes[edgeT.aNode >> 1].first;\n\t\t\taNodes[edgeT.aNode >> 1].first = edges.size();\n\t\t\tedgeT.next_in = bNodes[edgeT.bNode >> 1].first;\n\t\t\tbNodes[edgeT.bNode >> 1].first = edges.size();\n\t\t\tedges.push_back(edgeT);\n\t\t\treturn UEdge(edges.size() - 1);\n\t\t}\n\t\t\n\t\tvoid reserveANode(int n) { aNodes.reserve(n); };\n\t\tvoid reserveBNode(int n) { bNodes.reserve(n); };\n\t\t\n\t\tvoid reserveEdge(int m) { edges.reserve(m); };\n\t\t\n\t\tvoid clear() {\n\t\t\taNodes.clear();\n\t\t\tbNodes.clear();\n\t\t\tedges.clear();\n\t\t}\n\t\t\n\t\ttypedef True NodeNumTag;\n\t\tint nodeNum() const { return aNodes.size() + bNodes.size(); }\n\t\tint aNodeNum() const { return aNodes.size(); }\n\t\tint bNodeNum() const { return bNodes.size(); }\n\t\t\n\t\ttypedef True EdgeNumTag;\n\t\tint uEdgeNum() const { return edges.size(); }\n\t\t\n\t};\n\t\n\t\n\ttypedef BpUGraphExtender<BidirBpUGraphExtender<SmartBpUGraphBase> >\n\t\tExtendedSmartBpUGraphBase;\n\t\n\t/// \\ingroup graphs\n\t///\n\t/// \\brief A smart bipartite undirected graph class.\n\t///\n\t/// This is a simple and fast bipartite undirected graph implementation.\n\t/// It is also quite memory efficient, but at the price\n\t/// that <b> it does not support node and edge deletions</b>.\n\t/// Except from this it conforms to \n\t/// the \\ref concepts::BpUGraph \"BpUGraph concept\".\n\t///\n\t///It also has an\n\t///important extra feature that\n\t///its maps are real \\ref concepts::ReferenceMap \"reference map\"s.\n\t///\n\t/// \\sa concepts::BpUGraph.\n\t///\n\tclass SmartBpUGraph : public ExtendedSmartBpUGraphBase {\n\tprivate:\n\t\t\n\t\t/// \\brief SmartBpUGraph is \\e not copy constructible.\n\t\t///\n\t\t///SmartBpUGraph is \\e not copy constructible.\n\t\tSmartBpUGraph(const SmartBpUGraph &) : ExtendedSmartBpUGraphBase() {};\n\t\t\n\t\t/// \\brief Assignment of SmartBpUGraph to another one is \\e not\n\t\t/// allowed.\n\t\t///\n\t\t/// Assignment of SmartBpUGraph to another one is \\e not allowed.\n\t\tvoid operator=(const SmartBpUGraph &) {}\n\t\t\n\tpublic:\n\t\t\n\t\ttypedef ExtendedSmartBpUGraphBase Parent;\n\t\t\n\t\t///Constructor\n\t\t\n\t\t///Constructor.\n\t\t///\n\t\tSmartBpUGraph() : ExtendedSmartBpUGraphBase() {}\n\t\t\n\t\t///Add a new ANode to the graph.\n\t\t\n\t\t/// \\return the new node.\n\t\t///\n\t\tNode addANode() { return Parent::addANode(); }\n\t\t\n\t\t///Add a new BNode to the graph.\n\t\t\n\t\t/// \\return the new node.\n\t\t///\n\t\tNode addBNode() { return Parent::addBNode(); }\n\t\t\n\t\t///Add a new undirected edge to the graph.\n\t\t\n\t\t///Add a new undirected edge to the graph with node \\c s\n\t\t///and \\c t.\n\t\t///\\return the new undirected edge.\n\t\tUEdge addEdge(const Node& s, const Node& t) { \n\t\t\treturn Parent::addEdge(s, t); \n\t\t}\n\t\t\n\t\t///Clear the graph.\n\t\t\n\t\t///Erase all the nodes and edges from the graph.\n\t\t///\n\t\tvoid clear() {\n\t\t\tParent::clear();\n\t\t}\n\t\t\n\tpublic:\n\t\t\n\t\tclass Snapshot;\n\t\t\n\tprotected:\n\t\t\n\t\tvoid restoreSnapshot(const Snapshot &s)\n\t\t{\n\t\t\twhile(s.edge_num<edges.size()) {\n\t\t\t\tUEdge edge = uEdgeFromId(edges.size()-1);\n\t\t\t\tParent::notifier(UEdge()).erase(edge);\n\t\t\t\tstd::vector<Edge> dir;\n\t\t\t\tdir.push_back(Parent::direct(edge, true));\n\t\t\t\tdir.push_back(Parent::direct(edge, false));\n\t\t\t\tParent::notifier(Edge()).erase(dir);\n\t\t\t\taNodes[edges.back().aNode >> 1].first=edges.back().next_out;\n\t\t\t\tbNodes[edges.back().bNode >> 1].first=edges.back().next_in;\n\t\t\t\tedges.pop_back();\n\t\t\t}\n\t\t\twhile(s.anode_num<aNodes.size()) {\n\t\t\t\tNode node = nodeFromANodeId(aNodes.size() - 1);\n\t\t\t\tParent::notifier(ANode()).erase(node);\n\t\t\t\tParent::notifier(Node()).erase(node);\n\t\t\t\taNodes.pop_back();\n\t\t\t}\n\t\t\twhile(s.bnode_num<bNodes.size()) {\n\t\t\t\tNode node = nodeFromBNodeId(bNodes.size() - 1);\n\t\t\t\tParent::notifier(BNode()).erase(node);\n\t\t\t\tParent::notifier(Node()).erase(node);\n\t\t\t\tbNodes.pop_back();\n\t\t\t}\n\t\t}    \n\t\t\n\tpublic:\n\t\t\n\t\t///Class to make a snapshot of the graph and to restrore to it later.\n\t\t\n\t\t///Class to make a snapshot of the graph and to restrore to it later.\n\t\t///\n\t\t///The newly added nodes and edges can be removed using the\n\t\t///restore() function.\n\t\t///\n\t\t///\\note After you restore a state, you cannot restore\n\t\t///a later state, in other word you cannot add again the edges deleted\n\t\t///by restore() using another one Snapshot instance.\n\t\t///\n\t\t///\\warning If you do not use correctly the snapshot that can cause\n\t\t///either broken program, invalid state of the graph, valid but\n\t\t///not the restored graph or no change. Because the runtime performance\n\t\t///the validity of the snapshot is not stored.\n\t\tclass Snapshot \n\t\t{\n\t\t\tSmartBpUGraph *g;\n\t\tprotected:\n\t\t\tfriend class SmartBpUGraph;\n\t\t\tunsigned int anode_num;\n\t\t\tunsigned int bnode_num;\n\t\t\tunsigned int edge_num;\n\t\tpublic:\n\t\t\t///Default constructor.\n\t\t\t\n\t\t\t///Default constructor.\n\t\t\t///To actually make a snapshot you must call save().\n\t\t\t///\n\t\t\tSnapshot() : g(0) {}\n\t\t\t\n\t\t\t///Constructor that immediately makes a snapshot\n\t\t\t\n\t\t\t///This constructor immediately makes a snapshot of the graph.\n\t\t\t///\\param _g The graph we make a snapshot of.\n\t\t\tSnapshot(SmartBpUGraph &_g) : g(&_g) {\n\t\t\t\tanode_num=g->aNodes.size();\n\t\t\t\tbnode_num=g->bNodes.size();\n\t\t\t\tedge_num=g->edges.size();\n\t\t\t}\n\t\t\t\n\t\t\t///Make a snapshot.\n\t\t\t\n\t\t\t///Make a snapshot of the graph.\n\t\t\t///\n\t\t\t///This function can be called more than once. In case of a repeated\n\t\t\t///call, the previous snapshot gets lost.\n\t\t\t///\\param _g The graph we make the snapshot of.\n\t\t\tvoid save(SmartBpUGraph &_g) \n\t\t\t{\n\t\t\t\tg=&_g;\n\t\t\t\tanode_num=g->aNodes.size();\n\t\t\t\tbnode_num=g->bNodes.size();\n\t\t\t\tedge_num=g->edges.size();\n\t\t\t}\n\t\t\t\n\t\t\t///Undo the changes until a snapshot.\n\t\t\t\n\t\t\t///Undo the changes until a snapshot created by save().\n\t\t\t///\n\t\t\t///\\note After you restored a state, you cannot restore\n\t\t\t///a later state, in other word you cannot add again the edges deleted\n\t\t\t///by restore().\n\t\t\tvoid restore()\n\t\t\t{\n\t\t\t\tg->restoreSnapshot(*this);\n\t\t\t}\n\t\t};\n\t};\n\t\n\t\n\t/// @}  \n} //namespace lemon\n\n\n#endif //LEMON_SMART_GRAPH_H\n"
  },
  {
    "path": "src/lemon/tolerance.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_TOLERANCE_H\n#define LEMON_TOLERANCE_H\n\n///\\ingroup misc\n///\\file\n///\\brief A basic tool to handle the anomalies of calculation with\n///floating point numbers.\n///\n///\\todo It should be in a module like \"Basic tools\"\n\n\nnamespace lemon {\n\n  /// \\addtogroup misc\n  /// @{\n  \n  ///\\brief A class to provide a basic way to\n  ///handle the comparison of numbers that are obtained\n  ///as a result of a probably inexact computation.\n  ///\n  ///Tolerance is a class to provide a basic way to\n  ///handle the comparison of numbers that are obtained\n  ///as a result of a probably inexact computation.\n  ///\n  ///This is an abstract class, it should be specialized for all numerical\n  ///data types. These specialized classes like \\ref Tolerance\\<double\\>\n  ///may offer additional tuning parameters.\n  ///\n  ///\\sa Tolerance<float>\n  ///\\sa Tolerance<double>\n  ///\\sa Tolerance<long double>\n  ///\\sa Tolerance<int>\n  ///\\sa Tolerance<long long int>\n  ///\\sa Tolerance<unsigned int>\n  ///\\sa Tolerance<unsigned long long int>\n\n  template<class T>\n  class Tolerance\n  {\n  public:\n    typedef T Value;\n\n    ///\\name Comparisons\n    ///The concept is that these bool functions return with \\c true only if\n    ///the related comparisons hold even if some numerical error appeared\n    ///during the computations.\n\n    ///@{\n\n    ///Returns \\c true if \\c a is \\e surely strictly less than \\c b\n    static bool less(Value a,Value b) {return false;}\n    ///Returns \\c true if \\c a is \\e surely different from \\c b\n    static bool different(Value a,Value b) {return false;}\n    ///Returns \\c true if \\c a is \\e surely positive\n    static bool positive(Value a) {return false;}\n    ///Returns \\c true if \\c a is \\e surely negative\n    static bool negative(Value a) {return false;}\n    ///Returns \\c true if \\c a is \\e surely non-zero\n    static bool nonZero(Value a) {return false;}\n\n    ///@}\n\n    ///Returns the zero value.\n    static Value zero() {return T();}\n\n    //   static bool finite(Value a) {}\n    //   static Value big() {}\n    //   static Value negativeBig() {}\n  };\n\n\n  ///Float specialization of \\ref Tolerance.\n\n  ///Float specialization of \\ref Tolerance.\n  ///\\sa Tolerance\n  ///\\relates Tolerance\n  template<>\n  class Tolerance<float>\n  {\n    static float def_epsilon;\n    float _epsilon;\n  public:\n    ///\\e\n    typedef float Value;\n\n    ///Constructor setting the epsilon tolerance to the default value.\n    Tolerance() : _epsilon(def_epsilon) {}\n    ///Constructor setting the epsilon tolerance.\n    Tolerance(float e) : _epsilon(e) {}\n\n    ///Return the epsilon value.\n    Value epsilon() const {return _epsilon;}\n    ///Set the epsilon value.\n    void epsilon(Value e) {_epsilon=e;}\n\n    ///Return the default epsilon value.\n    static Value defaultEpsilon() {return def_epsilon;}\n    ///Set the default epsilon value.\n    static void defaultEpsilon(Value e) {def_epsilon=e;}\n\n    ///\\name Comparisons\n    ///See class Tolerance for more details.\n\n    ///@{\n\n    ///Returns \\c true if \\c a is \\e surely strictly less than \\c b\n    bool less(Value a,Value b) const {return a+_epsilon<b;}\n    ///Returns \\c true if \\c a is \\e surely different from \\c b\n    bool different(Value a,Value b) const { return less(a,b)||less(b,a); }\n    ///Returns \\c true if \\c a is \\e surely positive\n    bool positive(Value a) const { return _epsilon<a; }\n    ///Returns \\c true if \\c a is \\e surely negative\n    bool negative(Value a) const { return -_epsilon>a; }\n    ///Returns \\c true if \\c a is \\e surely non-zero\n    bool nonZero(Value a) const { return positive(a)||negative(a); };\n\n    ///@}\n\n    ///Returns zero\n    static Value zero() {return 0;}\n  };\n\n  ///Double specialization of \\ref Tolerance.\n\n  ///Double specialization of \\ref Tolerance.\n  ///\\sa Tolerance\n  ///\\relates Tolerance\n  template<>\n  class Tolerance<double>\n  {\n    static double def_epsilon;\n    double _epsilon;\n  public:\n    ///\\e\n    typedef double Value;\n\n    ///Constructor setting the epsilon tolerance to the default value.\n    Tolerance() : _epsilon(def_epsilon) {}\n    ///Constructor setting the epsilon tolerance.\n    Tolerance(double e) : _epsilon(e) {}\n\n    ///Return the epsilon value.\n    Value epsilon() const {return _epsilon;}\n    ///Set the epsilon value.\n    void epsilon(Value e) {_epsilon=e;}\n\n    ///Return the default epsilon value.\n    static Value defaultEpsilon() {return def_epsilon;}\n    ///Set the default epsilon value.\n    static void defaultEpsilon(Value e) {def_epsilon=e;}\n\n    ///\\name Comparisons\n    ///See class Tolerance for more details.\n\n    ///@{\n\n    ///Returns \\c true if \\c a is \\e surely strictly less than \\c b\n    bool less(Value a,Value b) const {return a+_epsilon<b;}\n    ///Returns \\c true if \\c a is \\e surely different from \\c b\n    bool different(Value a,Value b) const { return less(a,b)||less(b,a); }\n    ///Returns \\c true if \\c a is \\e surely positive\n    bool positive(Value a) const { return _epsilon<a; }\n    ///Returns \\c true if \\c a is \\e surely negative\n    bool negative(Value a) const { return -_epsilon>a; }\n    ///Returns \\c true if \\c a is \\e surely non-zero\n    bool nonZero(Value a) const { return positive(a)||negative(a); };\n\n    ///@}\n\n    ///Returns zero\n    static Value zero() {return 0;}\n  };\n\n  ///Long double specialization of \\ref Tolerance.\n\n  ///Long double specialization of \\ref Tolerance.\n  ///\\sa Tolerance\n  ///\\relates Tolerance\n  template<>\n  class Tolerance<long double>\n  {\n    static long double def_epsilon;\n    long double _epsilon;\n  public:\n    ///\\e\n    typedef long double Value;\n\n    ///Constructor setting the epsilon tolerance to the default value.\n    Tolerance() : _epsilon(def_epsilon) {}\n    ///Constructor setting the epsilon tolerance.\n    Tolerance(long double e) : _epsilon(e) {}\n\n    ///Return the epsilon value.\n    Value epsilon() const {return _epsilon;}\n    ///Set the epsilon value.\n    void epsilon(Value e) {_epsilon=e;}\n\n    ///Return the default epsilon value.\n    static Value defaultEpsilon() {return def_epsilon;}\n    ///Set the default epsilon value.\n    static void defaultEpsilon(Value e) {def_epsilon=e;}\n\n    ///\\name Comparisons\n    ///See class Tolerance for more details.\n\n    ///@{\n\n    ///Returns \\c true if \\c a is \\e surely strictly less than \\c b\n    bool less(Value a,Value b) const {return a+_epsilon<b;}\n    ///Returns \\c true if \\c a is \\e surely different from \\c b\n    bool different(Value a,Value b) const { return less(a,b)||less(b,a); }\n    ///Returns \\c true if \\c a is \\e surely positive\n    bool positive(Value a) const { return _epsilon<a; }\n    ///Returns \\c true if \\c a is \\e surely negative\n    bool negative(Value a) const { return -_epsilon>a; }\n    ///Returns \\c true if \\c a is \\e surely non-zero\n    bool nonZero(Value a) const { return positive(a)||negative(a); };\n\n    ///@}\n\n    ///Returns zero\n    static Value zero() {return 0;}\n  };\n\n  ///Integer specialization of \\ref Tolerance.\n\n  ///Integer specialization of \\ref Tolerance.\n  ///\\sa Tolerance\n  template<>\n  class Tolerance<int>\n  {\n  public:\n    ///\\e\n    typedef int Value;\n\n    ///\\name Comparisons\n    ///See \\ref Tolerance for more details.\n\n    ///@{\n\n    ///Returns \\c true if \\c a is \\e surely strictly less than \\c b\n    static bool less(Value a,Value b) { return a<b;}\n    ///Returns \\c true if \\c a is \\e surely different from \\c b\n    static bool different(Value a,Value b) { return a!=b; }\n    ///Returns \\c true if \\c a is \\e surely positive\n    static bool positive(Value a) { return 0<a; }\n    ///Returns \\c true if \\c a is \\e surely negative\n    static bool negative(Value a) { return 0>a; }\n    ///Returns \\c true if \\c a is \\e surely non-zero\n    static bool nonZero(Value a) { return a!=0; };\n\n    ///@}\n\n    ///Returns zero\n    static Value zero() {return 0;}\n  };\n\n  ///Unsigned integer specialization of \\ref Tolerance.\n\n  ///Unsigned integer specialization of \\ref Tolerance.\n  ///\\sa Tolerance\n  template<>\n  class Tolerance<unsigned int>\n  {\n  public:\n    ///\\e\n    typedef unsigned int Value;\n\n    ///\\name Comparisons\n    ///See \\ref Tolerance for more details.\n\n    ///@{\n\n    ///Returns \\c true if \\c a is \\e surely strictly less than \\c b\n    static bool less(Value a,Value b) { return a<b;}\n    ///Returns \\c true if \\c a is \\e surely different from \\c b\n    static bool different(Value a,Value b) { return a!=b; }\n    ///Returns \\c true if \\c a is \\e surely positive\n    static bool positive(Value a) { return 0<a; }\n    ///Returns \\c true if \\c a is \\e surely negative\n    static bool negative(Value) { return false; }\n    ///Returns \\c true if \\c a is \\e surely non-zero\n    static bool nonZero(Value a) { return a!=0; };\n\n    ///@}\n\n    ///Returns zero\n    static Value zero() {return 0;}\n  };\n  \n\n  ///Long integer specialization of \\ref Tolerance.\n\n  ///Long integer specialization of \\ref Tolerance.\n  ///\\sa Tolerance\n  template<>\n  class Tolerance<long int>\n  {\n  public:\n    ///\\e\n    typedef long int Value;\n\n    ///\\name Comparisons\n    ///See \\ref Tolerance for more details.\n\n    ///@{\n\n    ///Returns \\c true if \\c a is \\e surely strictly less than \\c b\n    static bool less(Value a,Value b) { return a<b;}\n    ///Returns \\c true if \\c a is \\e surely different from \\c b\n    static bool different(Value a,Value b) { return a!=b; }\n    ///Returns \\c true if \\c a is \\e surely positive\n    static bool positive(Value a) { return 0<a; }\n    ///Returns \\c true if \\c a is \\e surely negative\n    static bool negative(Value a) { return 0>a; }\n    ///Returns \\c true if \\c a is \\e surely non-zero\n    static bool nonZero(Value a) { return a!=0;};\n\n    ///@}\n\n    ///Returns zero\n    static Value zero() {return 0;}\n  };\n\n  ///Unsigned long integer specialization of \\ref Tolerance.\n\n  ///Unsigned long integer specialization of \\ref Tolerance.\n  ///\\sa Tolerance\n  template<>\n  class Tolerance<unsigned long int>\n  {\n  public:\n    ///\\e\n    typedef unsigned long int Value;\n\n    ///\\name Comparisons\n    ///See \\ref Tolerance for more details.\n\n    ///@{\n\n    ///Returns \\c true if \\c a is \\e surely strictly less than \\c b\n    static bool less(Value a,Value b) { return a<b;}\n    ///Returns \\c true if \\c a is \\e surely different from \\c b\n    static bool different(Value a,Value b) { return a!=b; }\n    ///Returns \\c true if \\c a is \\e surely positive\n    static bool positive(Value a) { return 0<a; }\n    ///Returns \\c true if \\c a is \\e surely negative\n    static bool negative(Value) { return false; }\n    ///Returns \\c true if \\c a is \\e surely non-zero\n    static bool nonZero(Value a) { return a!=0;};\n\n    ///@}\n\n    ///Returns zero\n    static Value zero() {return 0;}\n  };\n\n#if defined __GNUC__ && !defined __STRICT_ANSI__\n\n  ///Long long integer specialization of \\ref Tolerance.\n\n  ///Long long integer specialization of \\ref Tolerance.\n  ///\\warning This class (more exactly, type <tt>long long</tt>)\n  ///is not ansi compatible.\n  ///\\sa Tolerance\n  template<>\n  class Tolerance<long long int>\n  {\n  public:\n    ///\\e\n    typedef long long int Value;\n\n    ///\\name Comparisons\n    ///See \\ref Tolerance for more details.\n\n    ///@{\n\n    ///Returns \\c true if \\c a is \\e surely strictly less than \\c b\n    static bool less(Value a,Value b) { return a<b;}\n    ///Returns \\c true if \\c a is \\e surely different from \\c b\n    static bool different(Value a,Value b) { return a!=b; }\n    ///Returns \\c true if \\c a is \\e surely positive\n    static bool positive(Value a) { return 0<a; }\n    ///Returns \\c true if \\c a is \\e surely negative\n    static bool negative(Value a) { return 0>a; }\n    ///Returns \\c true if \\c a is \\e surely non-zero\n    static bool nonZero(Value a) { return a!=0;};\n\n    ///@}\n\n    ///Returns zero\n    static Value zero() {return 0;}\n  };\n\n  ///Unsigned long long integer specialization of \\ref Tolerance.\n\n  ///Unsigned long long integer specialization of \\ref Tolerance.\n  ///\\warning This class (more exactly, type <tt>unsigned long long</tt>)\n  ///is not ansi compatible.\n  ///\\sa Tolerance\n  template<>\n  class Tolerance<unsigned long long int>\n  {\n  public:\n    ///\\e\n    typedef unsigned long long int Value;\n\n    ///\\name Comparisons\n    ///See \\ref Tolerance for more details.\n\n    ///@{\n\n    ///Returns \\c true if \\c a is \\e surely strictly less than \\c b\n    static bool less(Value a,Value b) { return a<b;}\n    ///Returns \\c true if \\c a is \\e surely different from \\c b\n    static bool different(Value a,Value b) { return a!=b; }\n    ///Returns \\c true if \\c a is \\e surely positive\n    static bool positive(Value a) { return 0<a; }\n    ///Returns \\c true if \\c a is \\e surely negative\n    static bool negative(Value) { return false; }\n    ///Returns \\c true if \\c a is \\e surely non-zero\n    static bool nonZero(Value a) { return a!=0;};\n\n    ///@}\n\n    ///Returns zero\n    static Value zero() {return 0;}\n  };\n\n#endif\n\n  /// @}\n\n} //namespace lemon\n\n#endif //LEMON_TOLERANCE_H\n"
  },
  {
    "path": "src/lemon/topology.h",
    "content": "/* -*- C++ -*-\n *\n * This file is a part of LEMON, a generic C++ optimization library\n *\n * Copyright (C) 2003-2008\n * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport\n * (Egervary Research Group on Combinatorial Optimization, EGRES).\n *\n * Permission to use, modify and distribute this software is granted\n * provided that this copyright notice appears in all copies. For\n * precise terms see the accompanying LICENSE file.\n *\n * This software is provided \"AS IS\" with no warranty of any kind,\n * express or implied, and with no claim as to its suitability for any\n * purpose.\n *\n */\n\n#ifndef LEMON_TOPOLOGY_H\n#define LEMON_TOPOLOGY_H\n\n#include <lemon/dfs.h>\n#include <lemon/bfs.h>\n#include <lemon/graph_utils.h>\n#include <lemon/graph_adaptor.h>\n#include <lemon/maps.h>\n\n#include <lemon/concepts/graph.h>\n#include <lemon/concepts/ugraph.h>\n#include <lemon/concept_check.h>\n\n#include <lemon/bin_heap.h>\n#include <lemon/bucket_heap.h>\n\n#include <stack>\n#include <functional>\n\n/// \\ingroup graph_prop\n/// \\file\n/// \\brief Topology related algorithms\n///\n/// Topology related algorithms\n\nnamespace lemon {\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Check that the given undirected graph is connected.\n  ///\n  /// Check that the given undirected graph connected.\n  /// \\param graph The undirected graph.\n  /// \\return %True when there is path between any two nodes in the graph.\n  /// \\note By definition, the empty graph is connected.\n  template <typename UGraph>\n  bool connected(const UGraph& graph) {\n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::NodeIt NodeIt;\n    if (NodeIt(graph) == INVALID) return true;\n    Dfs<UGraph> dfs(graph);\n    dfs.run(NodeIt(graph));\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\treturn false;\n      }\n    }\n    return true;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Count the number of connected components of an undirected graph\n  ///\n  /// Count the number of connected components of an undirected graph\n  ///\n  /// \\param graph The graph. It should be undirected.\n  /// \\return The number of components\n  /// \\note By definition, the empty graph consists\n  /// of zero connected components.\n  template <typename UGraph>\n  int countConnectedComponents(const UGraph &graph) {\n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::Node Node;\n    typedef typename UGraph::Edge Edge;\n\n    typedef NullMap<Node, Edge> PredMap;\n    typedef NullMap<Node, int> DistMap;\n\n    int compNum = 0;\n    typename Bfs<UGraph>::\n      template DefPredMap<PredMap>::\n      template DefDistMap<DistMap>::\n      Create bfs(graph);\n\n    PredMap predMap;\n    bfs.predMap(predMap);\n\n    DistMap distMap;\n    bfs.distMap(distMap);\n\n    bfs.init();\n    for(typename UGraph::NodeIt n(graph); n != INVALID; ++n) {\n      if (!bfs.reached(n)) {\n\tbfs.addSource(n);\n\tbfs.start();\n\t++compNum;\n      }\n    }\n    return compNum;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Find the connected components of an undirected graph\n  ///\n  /// Find the connected components of an undirected graph.\n  ///\n  /// \\image html connected_components.png\n  /// \\image latex connected_components.eps \"Connected components\" width=\\textwidth\n  ///\n  /// \\param graph The graph. It should be undirected.\n  /// \\retval compMap A writable node map. The values will be set from 0 to\n  /// the number of the connected components minus one. Each values of the map\n  /// will be set exactly once, the values of a certain component will be\n  /// set continuously.\n  /// \\return The number of components\n  ///\n  template <class UGraph, class NodeMap>\n  int connectedComponents(const UGraph &graph, NodeMap &compMap) {\n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::Node Node;\n    typedef typename UGraph::Edge Edge;\n    checkConcept<concepts::WriteMap<Node, int>, NodeMap>();\n\n    typedef NullMap<Node, Edge> PredMap;\n    typedef NullMap<Node, int> DistMap;\n\n    int compNum = 0;\n    typename Bfs<UGraph>::\n      template DefPredMap<PredMap>::\n      template DefDistMap<DistMap>::\n      Create bfs(graph);\n\n    PredMap predMap;\n    bfs.predMap(predMap);\n\n    DistMap distMap;\n    bfs.distMap(distMap);\n    \n    bfs.init();\n    for(typename UGraph::NodeIt n(graph); n != INVALID; ++n) {\n      if(!bfs.reached(n)) {\n\tbfs.addSource(n);\n\twhile (!bfs.emptyQueue()) {\n\t  compMap.set(bfs.nextNode(), compNum);\n\t  bfs.processNextNode();\n\t}\n\t++compNum;\n      }\n    }\n    return compNum;\n  }\n\n  namespace _topology_bits {\n\n    template <typename Graph, typename Iterator >\n    struct LeaveOrderVisitor : public DfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Node Node;\n      LeaveOrderVisitor(Iterator it) : _it(it) {}\n\n      void leave(const Node& node) {\n\t*(_it++) = node;\n      }\n\n    private:\n      Iterator _it;\n    };\n\n    template <typename Graph, typename Map>\n    struct FillMapVisitor : public DfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Node Node;\n      typedef typename Map::Value Value;\n\n      FillMapVisitor(Map& map, Value& value) \n\t: _map(map), _value(value) {}\n\n      void reach(const Node& node) {\n\t_map.set(node, _value);\n      }\n    private:\n      Map& _map;\n      Value& _value;\n    };\n\n    template <typename Graph, typename EdgeMap>\n    struct StronglyConnectedCutEdgesVisitor : public DfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Node Node;\n      typedef typename Graph::Edge Edge;\n\n      StronglyConnectedCutEdgesVisitor(const Graph& graph, EdgeMap& cutMap, \n\t\t\t\t       int& cutNum) \n\t: _graph(graph), _cutMap(cutMap), _cutNum(cutNum), \n\t  _compMap(graph), _num(0) {\n      }\n\n      void stop(const Node&) {\n\t++_num;\n      }\n\n      void reach(const Node& node) {\n\t_compMap.set(node, _num);\n      }\n\n      void examine(const Edge& edge) {\n \tif (_compMap[_graph.source(edge)] != _compMap[_graph.target(edge)]) {\n \t  _cutMap.set(edge, true);\n \t  ++_cutNum;\n \t}\n      }\n    private:\n      const Graph& _graph;\n      EdgeMap& _cutMap;\n      int& _cutNum;\n\n      typename Graph::template NodeMap<int> _compMap;\n      int _num;\n    };\n\n  }\n\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Check that the given directed graph is strongly connected.\n  ///\n  /// Check that the given directed graph is strongly connected. The\n  /// graph is strongly connected when any two nodes of the graph are\n  /// connected with directed paths in both direction.\n  /// \\return %False when the graph is not strongly connected.\n  /// \\see connected\n  ///\n  /// \\note By definition, the empty graph is strongly connected.\n  template <typename Graph>\n  bool stronglyConnected(const Graph& graph) {\n    checkConcept<concepts::Graph, Graph>();\n\n    typedef typename Graph::Node Node;\n    typedef typename Graph::NodeIt NodeIt;\n\n    if (NodeIt(graph) == INVALID) return true;\n\n    using namespace _topology_bits;\n\n    typedef DfsVisitor<Graph> Visitor;\n    Visitor visitor;\n\n    DfsVisit<Graph, Visitor> dfs(graph, visitor);\n    dfs.init();\n    dfs.addSource(NodeIt(graph));\n    dfs.start();\n\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\treturn false;\n      }\n    }\n\n    typedef RevGraphAdaptor<const Graph> RGraph;\n    RGraph rgraph(graph);\n\n    typedef DfsVisitor<Graph> RVisitor;\n    RVisitor rvisitor;\n\n    DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);\n    rdfs.init();    \n    rdfs.addSource(NodeIt(graph));\n    rdfs.start();\n\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!rdfs.reached(it)) {\n\treturn false;\n      }\n    }\n\n    return true;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Count the strongly connected components of a directed graph\n  ///\n  /// Count the strongly connected components of a directed graph.\n  /// The strongly connected components are the classes of an\n  /// equivalence relation on the nodes of the graph. Two nodes are in\n  /// the same class if they are connected with directed paths in both\n  /// direction. \n  ///\n  /// \\param graph The graph.\n  /// \\return The number of components\n  /// \\note By definition, the empty graph has zero\n  /// strongly connected components.\n  template <typename Graph>\n  int countStronglyConnectedComponents(const Graph& graph) {\n    checkConcept<concepts::Graph, Graph>();\n\n    using namespace _topology_bits;\n\n    typedef typename Graph::Node Node;\n    typedef typename Graph::Edge Edge;\n    typedef typename Graph::NodeIt NodeIt;\n    typedef typename Graph::EdgeIt EdgeIt;\n    \n    typedef std::vector<Node> Container;\n    typedef typename Container::iterator Iterator;\n\n    Container nodes(countNodes(graph));\n    typedef LeaveOrderVisitor<Graph, Iterator> Visitor;\n    Visitor visitor(nodes.begin());\n      \n    DfsVisit<Graph, Visitor> dfs(graph, visitor);\n    dfs.init();\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\tdfs.start();\n      }\n    }\n\n    typedef typename Container::reverse_iterator RIterator;\n    typedef RevGraphAdaptor<const Graph> RGraph;\n\n    RGraph rgraph(graph);\n\n    typedef DfsVisitor<Graph> RVisitor;\n    RVisitor rvisitor;\n\n    DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);\n\n    int compNum = 0;\n\n    rdfs.init();\n    for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {\n      if (!rdfs.reached(*it)) {\n\trdfs.addSource(*it);\n\trdfs.start();\n\t++compNum;\n      }\n    }\n    return compNum;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Find the strongly connected components of a directed graph\n  ///\n  /// Find the strongly connected components of a directed graph.  The\n  /// strongly connected components are the classes of an equivalence\n  /// relation on the nodes of the graph. Two nodes are in\n  /// relationship when there are directed paths between them in both\n  /// direction. In addition, the numbering of components will satisfy\n  /// that there is no edge going from a higher numbered component to\n  /// a lower.\n  ///\n  /// \\image html strongly_connected_components.png\n  /// \\image latex strongly_connected_components.eps \"Strongly connected components\" width=\\textwidth\n  ///\n  /// \\param graph The graph.\n  /// \\retval compMap A writable node map. The values will be set from 0 to\n  /// the number of the strongly connected components minus one. Each value \n  /// of the map will be set exactly once, the values of a certain component \n  /// will be set continuously.\n  /// \\return The number of components\n  ///\n  template <typename Graph, typename NodeMap>\n  int stronglyConnectedComponents(const Graph& graph, NodeMap& compMap) {\n    checkConcept<concepts::Graph, Graph>();\n    typedef typename Graph::Node Node;\n    typedef typename Graph::NodeIt NodeIt;\n    checkConcept<concepts::WriteMap<Node, int>, NodeMap>();\n\n    using namespace _topology_bits;\n    \n    typedef std::vector<Node> Container;\n    typedef typename Container::iterator Iterator;\n\n    Container nodes(countNodes(graph));\n    typedef LeaveOrderVisitor<Graph, Iterator> Visitor;\n    Visitor visitor(nodes.begin());\n      \n    DfsVisit<Graph, Visitor> dfs(graph, visitor);\n    dfs.init();\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\tdfs.start();\n      }\n    }\n\n    typedef typename Container::reverse_iterator RIterator;\n    typedef RevGraphAdaptor<const Graph> RGraph;\n\n    RGraph rgraph(graph);\n\n    int compNum = 0;\n\n    typedef FillMapVisitor<RGraph, NodeMap> RVisitor;\n    RVisitor rvisitor(compMap, compNum);\n\n    DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);\n\n    rdfs.init();\n    for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {\n      if (!rdfs.reached(*it)) {\n\trdfs.addSource(*it);\n\trdfs.start();\n\t++compNum;\n      }\n    }\n    return compNum;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Find the cut edges of the strongly connected components.\n  ///\n  /// Find the cut edges of the strongly connected components.\n  /// The strongly connected components are the classes of an equivalence\n  /// relation on the nodes of the graph. Two nodes are in relationship\n  /// when there are directed paths between them in both direction.\n  /// The strongly connected components are separated by the cut edges.\n  ///\n  /// \\param graph The graph.\n  /// \\retval cutMap A writable node map. The values will be set true when the\n  /// edge is a cut edge.\n  ///\n  /// \\return The number of cut edges\n  template <typename Graph, typename EdgeMap>\n  int stronglyConnectedCutEdges(const Graph& graph, EdgeMap& cutMap) {\n    checkConcept<concepts::Graph, Graph>();\n    typedef typename Graph::Node Node;\n    typedef typename Graph::Edge Edge;\n    typedef typename Graph::NodeIt NodeIt;\n    checkConcept<concepts::WriteMap<Edge, bool>, EdgeMap>();\n\n    using namespace _topology_bits;\n    \n    typedef std::vector<Node> Container;\n    typedef typename Container::iterator Iterator;\n\n    Container nodes(countNodes(graph));\n    typedef LeaveOrderVisitor<Graph, Iterator> Visitor;\n    Visitor visitor(nodes.begin());\n      \n    DfsVisit<Graph, Visitor> dfs(graph, visitor);\n    dfs.init();\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\tdfs.start();\n      }\n    }\n\n    typedef typename Container::reverse_iterator RIterator;\n    typedef RevGraphAdaptor<const Graph> RGraph;\n\n    RGraph rgraph(graph);\n\n    int cutNum = 0;\n\n    typedef StronglyConnectedCutEdgesVisitor<RGraph, EdgeMap> RVisitor;\n    RVisitor rvisitor(rgraph, cutMap, cutNum);\n\n    DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);\n\n    rdfs.init();\n    for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {\n      if (!rdfs.reached(*it)) {\n\trdfs.addSource(*it);\n\trdfs.start();\n      }\n    }\n    return cutNum;\n  }\n\n  namespace _topology_bits {\n    \n    template <typename Graph>\n    class CountBiNodeConnectedComponentsVisitor : public DfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Node Node;\n      typedef typename Graph::Edge Edge;\n      typedef typename Graph::UEdge UEdge;\n\n      CountBiNodeConnectedComponentsVisitor(const Graph& graph, int &compNum) \n\t: _graph(graph), _compNum(compNum), \n\t  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}\n\n      void start(const Node& node) {\n\t_predMap.set(node, INVALID);\n      }\n      \n      void reach(const Node& node) {\n\t_numMap.set(node, _num);\n\t_retMap.set(node, _num);\n\t++_num;\n      }\n\n      void discover(const Edge& edge) {\n\t_predMap.set(_graph.target(edge), _graph.source(edge));\n      }\n\n      void examine(const Edge& edge) {\n\tif (_graph.source(edge) == _graph.target(edge) && \n\t    _graph.direction(edge)) {\n\t  ++_compNum;\n\t  return;\n\t}\n\tif (_predMap[_graph.source(edge)] == _graph.target(edge)) {\n\t  return;\n\t}\n\tif (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {\n\t  _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);\n\t}\n      }\n\n      void backtrack(const Edge& edge) {\n\tif (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {\n\t  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);\n\t}  \n\tif (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {\n\t  ++_compNum;\n\t}\n      }\n      \n    private:\n      const Graph& _graph;\n      int& _compNum; \n\n      typename Graph::template NodeMap<int> _numMap;\n      typename Graph::template NodeMap<int> _retMap;\n      typename Graph::template NodeMap<Node> _predMap;\n      int _num;\n    };\n\n    template <typename Graph, typename EdgeMap>\n    class BiNodeConnectedComponentsVisitor : public DfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Node Node;\n      typedef typename Graph::Edge Edge;\n      typedef typename Graph::UEdge UEdge;\n\n      BiNodeConnectedComponentsVisitor(const Graph& graph, \n\t\t\t\t       EdgeMap& compMap, int &compNum) \n\t: _graph(graph), _compMap(compMap), _compNum(compNum), \n\t  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}\n\n      void start(const Node& node) {\n\t_predMap.set(node, INVALID);\n      }\n      \n      void reach(const Node& node) {\n\t_numMap.set(node, _num);\n\t_retMap.set(node, _num);\n\t++_num;\n      }\n\n      void discover(const Edge& edge) {\n\tNode target = _graph.target(edge);\n\t_predMap.set(target, edge);\n\t_edgeStack.push(edge);\n      }\n\n      void examine(const Edge& edge) {\n\tNode source = _graph.source(edge);\n\tNode target = _graph.target(edge);\n\tif (source == target && _graph.direction(edge)) {\n\t  _compMap.set(edge, _compNum);\n\t  ++_compNum;\n\t  return;\n\t}\n\tif (_numMap[target] < _numMap[source]) {\n\t  if (_predMap[source] != _graph.oppositeEdge(edge)) {\n\t    _edgeStack.push(edge);\n\t  }\n\t}\n\tif (_predMap[source] != INVALID && \n\t    target == _graph.source(_predMap[source])) {\n\t  return;\n\t}\n\tif (_retMap[source] > _numMap[target]) {\n\t  _retMap.set(source, _numMap[target]);\n\t}\n      }\n\n      void backtrack(const Edge& edge) {\n\tNode source = _graph.source(edge);\n\tNode target = _graph.target(edge);\n\tif (_retMap[source] > _retMap[target]) {\n\t  _retMap.set(source, _retMap[target]);\n\t}  \n\tif (_numMap[source] <= _retMap[target]) {\n\t  while (_edgeStack.top() != edge) {\n\t    _compMap.set(_edgeStack.top(), _compNum);\n\t    _edgeStack.pop();\n\t  }\n\t  _compMap.set(edge, _compNum);\n\t  _edgeStack.pop();\n\t  ++_compNum;\n\t}\n      }\n      \n    private:\n      const Graph& _graph;\n      EdgeMap& _compMap;\n      int& _compNum; \n\n      typename Graph::template NodeMap<int> _numMap;\n      typename Graph::template NodeMap<int> _retMap;\n      typename Graph::template NodeMap<Edge> _predMap;\n      std::stack<UEdge> _edgeStack;\n      int _num;\n    };\n\n\n    template <typename Graph, typename NodeMap>\n    class BiNodeConnectedCutNodesVisitor : public DfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Node Node;\n      typedef typename Graph::Edge Edge;\n      typedef typename Graph::UEdge UEdge;\n\n      BiNodeConnectedCutNodesVisitor(const Graph& graph, NodeMap& cutMap,\n\t\t\t\t     int& cutNum) \n\t: _graph(graph), _cutMap(cutMap), _cutNum(cutNum),\n\t  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}\n\n      void start(const Node& node) {\n\t_predMap.set(node, INVALID);\n\trootCut = false;\n      }\n      \n      void reach(const Node& node) {\n\t_numMap.set(node, _num);\n\t_retMap.set(node, _num);\n\t++_num;\n      }\n\n      void discover(const Edge& edge) {\n\t_predMap.set(_graph.target(edge), _graph.source(edge));\n      }\n\n      void examine(const Edge& edge) {\n\tif (_graph.source(edge) == _graph.target(edge) && \n\t    _graph.direction(edge)) {\n\t  if (!_cutMap[_graph.source(edge)]) {\n\t    _cutMap.set(_graph.source(edge), true);\n\t    ++_cutNum;\n\t  }\n\t  return;\n\t}\n\tif (_predMap[_graph.source(edge)] == _graph.target(edge)) return;\n\tif (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {\n\t  _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);\n\t}\n      }\n\n      void backtrack(const Edge& edge) {\n\tif (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {\n\t  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);\n\t}  \n\tif (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {\n\t  if (_predMap[_graph.source(edge)] != INVALID) {\n\t    if (!_cutMap[_graph.source(edge)]) {\n\t      _cutMap.set(_graph.source(edge), true);\n\t      ++_cutNum;\n\t    }\n\t  } else if (rootCut) {\n\t    if (!_cutMap[_graph.source(edge)]) {\n\t      _cutMap.set(_graph.source(edge), true);\n\t      ++_cutNum;\n\t    }\n\t  } else {\n\t    rootCut = true;\n\t  }\n\t}\n      }\n      \n    private:\n      const Graph& _graph;\n      NodeMap& _cutMap;\n      int& _cutNum; \n\n      typename Graph::template NodeMap<int> _numMap;\n      typename Graph::template NodeMap<int> _retMap;\n      typename Graph::template NodeMap<Node> _predMap;\n      std::stack<UEdge> _edgeStack;\n      int _num;\n      bool rootCut;\n    };\n\n  }\n\n  template <typename UGraph>\n  int countBiNodeConnectedComponents(const UGraph& graph);\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Checks the graph is bi-node-connected.\n  ///\n  /// This function checks that the undirected graph is bi-node-connected  \n  /// graph. The graph is bi-node-connected if any two undirected edge is \n  /// on same circle.\n  ///\n  /// \\param graph The graph.\n  /// \\return %True when the graph bi-node-connected.\n  template <typename UGraph>\n  bool biNodeConnected(const UGraph& graph) {\n    return countBiNodeConnectedComponents(graph) == 1;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Count the biconnected components.\n  ///\n  /// This function finds the bi-node-connected components in an undirected \n  /// graph. The biconnected components are the classes of an equivalence \n  /// relation on the undirected edges. Two undirected edge is in relationship\n  /// when they are on same circle.\n  ///\n  /// \\param graph The graph.\n  /// \\return The number of components.\n  template <typename UGraph>\n  int countBiNodeConnectedComponents(const UGraph& graph) {\n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::NodeIt NodeIt;\n\n    using namespace _topology_bits;\n\n    typedef CountBiNodeConnectedComponentsVisitor<UGraph> Visitor;\n\n    int compNum = 0;\n    Visitor visitor(graph, compNum);\n\n    DfsVisit<UGraph, Visitor> dfs(graph, visitor);\n    dfs.init();\n    \n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\tdfs.start();\n      }\n    }\n    return compNum;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Find the bi-node-connected components.\n  ///\n  /// This function finds the bi-node-connected components in an undirected \n  /// graph. The bi-node-connected components are the classes of an equivalence\n  /// relation on the undirected edges. Two undirected edge are in relationship\n  /// when they are on same circle.\n  ///\n  /// \\image html node_biconnected_components.png\n  /// \\image latex node_biconnected_components.eps \"bi-node-connected components\" width=\\textwidth\n  ///\n  /// \\param graph The graph.\n  /// \\retval compMap A writable uedge map. The values will be set from 0\n  /// to the number of the biconnected components minus one. Each values \n  /// of the map will be set exactly once, the values of a certain component \n  /// will be set continuously.\n  /// \\return The number of components.\n  ///\n  template <typename UGraph, typename UEdgeMap>\n  int biNodeConnectedComponents(const UGraph& graph, \n\t\t\t\tUEdgeMap& compMap) {\n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::NodeIt NodeIt;\n    typedef typename UGraph::UEdge UEdge;\n    checkConcept<concepts::WriteMap<UEdge, int>, UEdgeMap>();\n\n    using namespace _topology_bits;\n\n    typedef BiNodeConnectedComponentsVisitor<UGraph, UEdgeMap> Visitor;\n    \n    int compNum = 0;\n    Visitor visitor(graph, compMap, compNum);\n\n    DfsVisit<UGraph, Visitor> dfs(graph, visitor);\n    dfs.init();\n    \n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\tdfs.start();\n      }\n    }\n    return compNum;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Find the bi-node-connected cut nodes.\n  ///\n  /// This function finds the bi-node-connected cut nodes in an undirected \n  /// graph. The bi-node-connected components are the classes of an equivalence\n  /// relation on the undirected edges. Two undirected edges are in \n  /// relationship when they are on same circle. The biconnected components \n  /// are separted by nodes which are the cut nodes of the components.\n  ///\n  /// \\param graph The graph.\n  /// \\retval cutMap A writable edge map. The values will be set true when\n  /// the node separate two or more components.\n  /// \\return The number of the cut nodes.\n  template <typename UGraph, typename NodeMap>\n  int biNodeConnectedCutNodes(const UGraph& graph, NodeMap& cutMap) {\n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::Node Node;\n    typedef typename UGraph::NodeIt NodeIt;\n    checkConcept<concepts::WriteMap<Node, bool>, NodeMap>();\n\n    using namespace _topology_bits;\n\n    typedef BiNodeConnectedCutNodesVisitor<UGraph, NodeMap> Visitor;\n    \n    int cutNum = 0;\n    Visitor visitor(graph, cutMap, cutNum);\n\n    DfsVisit<UGraph, Visitor> dfs(graph, visitor);\n    dfs.init();\n    \n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\tdfs.start();\n      }\n    }\n    return cutNum;\n  }\n\n  namespace _topology_bits {\n    \n    template <typename Graph>\n    class CountBiEdgeConnectedComponentsVisitor : public DfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Node Node;\n      typedef typename Graph::Edge Edge;\n      typedef typename Graph::UEdge UEdge;\n\n      CountBiEdgeConnectedComponentsVisitor(const Graph& graph, int &compNum) \n\t: _graph(graph), _compNum(compNum), \n\t  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}\n\n      void start(const Node& node) {\n\t_predMap.set(node, INVALID);\n      }\n      \n      void reach(const Node& node) {\n\t_numMap.set(node, _num);\n\t_retMap.set(node, _num);\n\t++_num;\n      }\n      \n      void leave(const Node& node) {\n\tif (_numMap[node] <= _retMap[node]) {\n\t  ++_compNum;\n\t}\t\n      }\n\n      void discover(const Edge& edge) {\n\t_predMap.set(_graph.target(edge), edge);\n      }\n\n      void examine(const Edge& edge) {\n\tif (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {\n\t  return;\n\t}\n\tif (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {\n\t  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);\n\t}\n      }\n\n      void backtrack(const Edge& edge) {\n\tif (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {\n\t  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);\n\t}  \n      }\n      \n    private:\n      const Graph& _graph;\n      int& _compNum; \n\n      typename Graph::template NodeMap<int> _numMap;\n      typename Graph::template NodeMap<int> _retMap;\n      typename Graph::template NodeMap<Edge> _predMap;\n      int _num;\n    };\n\n    template <typename Graph, typename NodeMap>\n    class BiEdgeConnectedComponentsVisitor : public DfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Node Node;\n      typedef typename Graph::Edge Edge;\n      typedef typename Graph::UEdge UEdge;\n\n      BiEdgeConnectedComponentsVisitor(const Graph& graph, \n\t\t\t\t       NodeMap& compMap, int &compNum) \n\t: _graph(graph), _compMap(compMap), _compNum(compNum), \n\t  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}\n\n      void start(const Node& node) {\n\t_predMap.set(node, INVALID);\n      }\n      \n      void reach(const Node& node) {\n\t_numMap.set(node, _num);\n\t_retMap.set(node, _num);\n\t_nodeStack.push(node);\n\t++_num;\n      }\n      \n      void leave(const Node& node) {\n\tif (_numMap[node] <= _retMap[node]) {\n\t  while (_nodeStack.top() != node) {\n\t    _compMap.set(_nodeStack.top(), _compNum);\n\t    _nodeStack.pop();\n\t  }\n\t  _compMap.set(node, _compNum);\n\t  _nodeStack.pop();\n\t  ++_compNum;\n\t}\t\n      }\n\n      void discover(const Edge& edge) {\n\t_predMap.set(_graph.target(edge), edge);\n      }\n\n      void examine(const Edge& edge) {\n\tif (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {\n\t  return;\n\t}\n\tif (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {\n\t  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);\n\t}\n      }\n\n      void backtrack(const Edge& edge) {\n\tif (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {\n\t  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);\n\t}  \n      }\n      \n    private:\n      const Graph& _graph;\n      NodeMap& _compMap;\n      int& _compNum; \n\n      typename Graph::template NodeMap<int> _numMap;\n      typename Graph::template NodeMap<int> _retMap;\n      typename Graph::template NodeMap<Edge> _predMap;\n      std::stack<Node> _nodeStack;\n      int _num;\n    };\n\n\n    template <typename Graph, typename EdgeMap>\n    class BiEdgeConnectedCutEdgesVisitor : public DfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Node Node;\n      typedef typename Graph::Edge Edge;\n      typedef typename Graph::UEdge UEdge;\n\n      BiEdgeConnectedCutEdgesVisitor(const Graph& graph, \n\t\t\t\t     EdgeMap& cutMap, int &cutNum) \n\t: _graph(graph), _cutMap(cutMap), _cutNum(cutNum), \n\t  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}\n\n      void start(const Node& node) {\n\t_predMap[node] = INVALID;\n      }\n      \n      void reach(const Node& node) {\n\t_numMap.set(node, _num);\n\t_retMap.set(node, _num);\n\t++_num;\n      }\n      \n      void leave(const Node& node) {\n\tif (_numMap[node] <= _retMap[node]) {\n\t  if (_predMap[node] != INVALID) {\n\t    _cutMap.set(_predMap[node], true);\n\t    ++_cutNum;\n\t  }\n\t}\t\n      }\n\n      void discover(const Edge& edge) {\n\t_predMap.set(_graph.target(edge), edge);\n      }\n\n      void examine(const Edge& edge) {\n\tif (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {\n\t  return;\n\t}\n\tif (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {\n\t  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);\n\t}\n      }\n\n      void backtrack(const Edge& edge) {\n\tif (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {\n\t  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);\n\t}  \n      }\n      \n    private:\n      const Graph& _graph;\n      EdgeMap& _cutMap;\n      int& _cutNum; \n\n      typename Graph::template NodeMap<int> _numMap;\n      typename Graph::template NodeMap<int> _retMap;\n      typename Graph::template NodeMap<Edge> _predMap;\n      int _num;\n    };\n  }\n\n  template <typename UGraph>\n  int countBiEdgeConnectedComponents(const UGraph& graph);\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Checks that the graph is bi-edge-connected.\n  ///\n  /// This function checks that the graph is bi-edge-connected. The undirected\n  /// graph is bi-edge-connected when any two nodes are connected with two\n  /// edge-disjoint paths.\n  ///\n  /// \\param graph The undirected graph.\n  /// \\return The number of components.\n  template <typename UGraph>\n  bool biEdgeConnected(const UGraph& graph) { \n    return countBiEdgeConnectedComponents(graph) == 1;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Count the bi-edge-connected components.\n  ///\n  /// This function count the bi-edge-connected components in an undirected \n  /// graph. The bi-edge-connected components are the classes of an equivalence\n  /// relation on the nodes. Two nodes are in relationship when they are  \n  /// connected with at least two edge-disjoint paths.\n  ///\n  /// \\param graph The undirected graph.\n  /// \\return The number of components.\n  template <typename UGraph>\n  int countBiEdgeConnectedComponents(const UGraph& graph) { \n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::NodeIt NodeIt;\n\n    using namespace _topology_bits;\n\n    typedef CountBiEdgeConnectedComponentsVisitor<UGraph> Visitor;\n    \n    int compNum = 0;\n    Visitor visitor(graph, compNum);\n\n    DfsVisit<UGraph, Visitor> dfs(graph, visitor);\n    dfs.init();\n    \n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\tdfs.start();\n      }\n    }\n    return compNum;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Find the bi-edge-connected components.\n  ///\n  /// This function finds the bi-edge-connected components in an undirected \n  /// graph. The bi-edge-connected components are the classes of an equivalence\n  /// relation on the nodes. Two nodes are in relationship when they are  \n  /// connected at least two edge-disjoint paths.\n  ///\n  /// \\image html edge_biconnected_components.png\n  /// \\image latex edge_biconnected_components.eps \"bi-edge-connected components\" width=\\textwidth\n  ///\n  /// \\param graph The graph.\n  /// \\retval compMap A writable node map. The values will be set from 0 to\n  /// the number of the biconnected components minus one. Each values \n  /// of the map will be set exactly once, the values of a certain component \n  /// will be set continuously.\n  /// \\return The number of components.\n  ///\n  template <typename UGraph, typename NodeMap>\n  int biEdgeConnectedComponents(const UGraph& graph, NodeMap& compMap) { \n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::NodeIt NodeIt;\n    typedef typename UGraph::Node Node;\n    checkConcept<concepts::WriteMap<Node, int>, NodeMap>();\n\n    using namespace _topology_bits;\n\n    typedef BiEdgeConnectedComponentsVisitor<UGraph, NodeMap> Visitor;\n    \n    int compNum = 0;\n    Visitor visitor(graph, compMap, compNum);\n\n    DfsVisit<UGraph, Visitor> dfs(graph, visitor);\n    dfs.init();\n    \n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\tdfs.start();\n      }\n    }\n    return compNum;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Find the bi-edge-connected cut edges.\n  ///\n  /// This function finds the bi-edge-connected components in an undirected \n  /// graph. The bi-edge-connected components are the classes of an equivalence\n  /// relation on the nodes. Two nodes are in relationship when they are \n  /// connected with at least two edge-disjoint paths. The bi-edge-connected \n  /// components are separted by edges which are the cut edges of the \n  /// components.\n  ///\n  /// \\param graph The graph.\n  /// \\retval cutMap A writable node map. The values will be set true when the\n  /// edge is a cut edge.\n  /// \\return The number of cut edges.\n  template <typename UGraph, typename UEdgeMap>\n  int biEdgeConnectedCutEdges(const UGraph& graph, UEdgeMap& cutMap) { \n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::NodeIt NodeIt;\n    typedef typename UGraph::UEdge UEdge;\n    checkConcept<concepts::WriteMap<UEdge, bool>, UEdgeMap>();\n\n    using namespace _topology_bits;\n\n    typedef BiEdgeConnectedCutEdgesVisitor<UGraph, UEdgeMap> Visitor;\n    \n    int cutNum = 0;\n    Visitor visitor(graph, cutMap, cutNum);\n\n    DfsVisit<UGraph, Visitor> dfs(graph, visitor);\n    dfs.init();\n    \n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\tdfs.start();\n      }\n    }\n    return cutNum;\n  }\n\n\n  namespace _topology_bits {\n    \n    template <typename Graph, typename IntNodeMap>\n    class TopologicalSortVisitor : public DfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Node Node;\n      typedef typename Graph::Edge edge;\n\n      TopologicalSortVisitor(IntNodeMap& order, int num) \n\t: _order(order), _num(num) {}\n      \n      void leave(const Node& node) {\n\t_order.set(node, --_num);\n      }\n\n    private:\n      IntNodeMap& _order;\n      int _num;\n    };\n    \n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Sort the nodes of a DAG into topolgical order.\n  ///\n  /// Sort the nodes of a DAG into topolgical order.\n  ///\n  /// \\param graph The graph. It should be directed and acyclic.\n  /// \\retval order A writable node map. The values will be set from 0 to\n  /// the number of the nodes in the graph minus one. Each values of the map\n  /// will be set exactly once, the values  will be set descending order.\n  ///\n  /// \\see checkedTopologicalSort\n  /// \\see dag\n  template <typename Graph, typename NodeMap>\n  void topologicalSort(const Graph& graph, NodeMap& order) {\n    using namespace _topology_bits;\n\n    checkConcept<concepts::Graph, Graph>();\n    checkConcept<concepts::WriteMap<typename Graph::Node, int>, NodeMap>();\n\n    typedef typename Graph::Node Node;\n    typedef typename Graph::NodeIt NodeIt;\n    typedef typename Graph::Edge Edge;\n\n    TopologicalSortVisitor<Graph, NodeMap> \n      visitor(order, countNodes(graph)); \n\n    DfsVisit<Graph, TopologicalSortVisitor<Graph, NodeMap> >\n      dfs(graph, visitor);\n\n    dfs.init();\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\tdfs.start();\n      }\n    }    \n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Sort the nodes of a DAG into topolgical order.\n  ///\n  /// Sort the nodes of a DAG into topolgical order. It also checks\n  /// that the given graph is DAG.\n  ///\n  /// \\param graph The graph. It should be directed and acyclic.\n  /// \\retval order A readable - writable node map. The values will be set \n  /// from 0 to the number of the nodes in the graph minus one. Each values \n  /// of the map will be set exactly once, the values will be set descending \n  /// order.\n  /// \\return %False when the graph is not DAG.\n  ///\n  /// \\see topologicalSort\n  /// \\see dag\n  template <typename Graph, typename NodeMap>\n  bool checkedTopologicalSort(const Graph& graph, NodeMap& order) {\n    using namespace _topology_bits;\n\n    checkConcept<concepts::Graph, Graph>();\n    checkConcept<concepts::ReadWriteMap<typename Graph::Node, int>, NodeMap>();\n\n    typedef typename Graph::Node Node;\n    typedef typename Graph::NodeIt NodeIt;\n    typedef typename Graph::Edge Edge;\n\n    order = constMap<Node, int, -1>();\n\n    TopologicalSortVisitor<Graph, NodeMap> \n      visitor(order, countNodes(graph)); \n\n    DfsVisit<Graph, TopologicalSortVisitor<Graph, NodeMap> >\n      dfs(graph, visitor);\n\n    dfs.init();\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\twhile (!dfs.emptyQueue()) {\n \t  Edge edge = dfs.nextEdge();\n \t  Node target = graph.target(edge);\n \t  if (dfs.reached(target) && order[target] == -1) {\n \t    return false;\n \t  }\n \t  dfs.processNextEdge();\n \t}\n      }\n    }\n    return true;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Check that the given directed graph is a DAG.\n  ///\n  /// Check that the given directed graph is a DAG. The DAG is\n  /// an Directed Acyclic Graph.\n  /// \\return %False when the graph is not DAG.\n  /// \\see acyclic\n  template <typename Graph>\n  bool dag(const Graph& graph) {\n\n    checkConcept<concepts::Graph, Graph>();\n\n    typedef typename Graph::Node Node;\n    typedef typename Graph::NodeIt NodeIt;\n    typedef typename Graph::Edge Edge;\n\n    typedef typename Graph::template NodeMap<bool> ProcessedMap;\n\n    typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::\n      Create dfs(graph);\n\n    ProcessedMap processed(graph);\n    dfs.processedMap(processed);\n\n    dfs.init();\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\twhile (!dfs.emptyQueue()) {\n\t  Edge edge = dfs.nextEdge();\n\t  Node target = graph.target(edge);\n\t  if (dfs.reached(target) && !processed[target]) {\n\t    return false;\n\t  }\n\t  dfs.processNextEdge();\n\t}\n      }\n    }    \n    return true;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Check that the given undirected graph is acyclic.\n  ///\n  /// Check that the given undirected graph acyclic.\n  /// \\param graph The undirected graph.\n  /// \\return %True when there is no circle in the graph.\n  /// \\see dag\n  template <typename UGraph>\n  bool acyclic(const UGraph& graph) {\n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::Node Node;\n    typedef typename UGraph::NodeIt NodeIt;\n    typedef typename UGraph::Edge Edge;\n    Dfs<UGraph> dfs(graph);\n    dfs.init();\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\tdfs.addSource(it);\n\twhile (!dfs.emptyQueue()) {\n\t  Edge edge = dfs.nextEdge();\n\t  Node source = graph.source(edge);\n\t  Node target = graph.target(edge);\n\t  if (dfs.reached(target) && \n\t      dfs.predEdge(source) != graph.oppositeEdge(edge)) {\n\t    return false;\n\t  }\n\t  dfs.processNextEdge();\n\t}\n      }\n    }\n    return true;\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Check that the given undirected graph is tree.\n  ///\n  /// Check that the given undirected graph is tree.\n  /// \\param graph The undirected graph.\n  /// \\return %True when the graph is acyclic and connected.\n  template <typename UGraph>\n  bool tree(const UGraph& graph) {\n    checkConcept<concepts::UGraph, UGraph>();\n    typedef typename UGraph::Node Node;\n    typedef typename UGraph::NodeIt NodeIt;\n    typedef typename UGraph::Edge Edge;\n    Dfs<UGraph> dfs(graph);\n    dfs.init();\n    dfs.addSource(NodeIt(graph));\n    while (!dfs.emptyQueue()) {\n      Edge edge = dfs.nextEdge();\n      Node source = graph.source(edge);\n      Node target = graph.target(edge);\n      if (dfs.reached(target) && \n\t  dfs.predEdge(source) != graph.oppositeEdge(edge)) {\n\treturn false;\n      }\n      dfs.processNextEdge();\n    }\n    for (NodeIt it(graph); it != INVALID; ++it) {\n      if (!dfs.reached(it)) {\n\treturn false;\n      }\n    }    \n    return true;\n  }\n\n  namespace _topology_bits {\n\n    template <typename Graph>\n    class BipartiteVisitor : public BfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Edge Edge;\n      typedef typename Graph::Node Node;\n\n      BipartiteVisitor(const Graph& graph, bool& bipartite) \n        : _graph(graph), _part(graph), _bipartite(bipartite) {}\n      \n      void start(const Node& node) {\n        _part[node] = true;\n      }\n      void discover(const Edge& edge) {\n        _part.set(_graph.target(edge), !_part[_graph.source(edge)]);\n      }\n      void examine(const Edge& edge) {\n        _bipartite = _bipartite && \n          _part[_graph.target(edge)] != _part[_graph.source(edge)];\n      }\n\n    private:\n\n      const Graph& _graph;\n      typename Graph::template NodeMap<bool> _part;\n      bool& _bipartite;\n    };\n\n    template <typename Graph, typename PartMap>\n    class BipartitePartitionsVisitor : public BfsVisitor<Graph> {\n    public:\n      typedef typename Graph::Edge Edge;\n      typedef typename Graph::Node Node;\n\n      BipartitePartitionsVisitor(const Graph& graph, \n                                 PartMap& part, bool& bipartite) \n        : _graph(graph), _part(part), _bipartite(bipartite) {}\n      \n      void start(const Node& node) {\n        _part.set(node, true);\n      }\n      void discover(const Edge& edge) {\n        _part.set(_graph.target(edge), !_part[_graph.source(edge)]);\n      }\n      void examine(const Edge& edge) {\n        _bipartite = _bipartite && \n          _part[_graph.target(edge)] != _part[_graph.source(edge)];\n      }\n\n    private:\n\n      const Graph& _graph;\n      PartMap& _part;\n      bool& _bipartite;\n    };\n  }\n\n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Check if the given undirected graph is bipartite or not\n  ///\n  /// The function checks if the given undirected \\c graph graph is bipartite \n  /// or not. The \\ref Bfs algorithm is used to calculate the result.\n  /// \\param graph The undirected graph.\n  /// \\return %True if \\c graph is bipartite, %false otherwise.\n  /// \\sa bipartitePartitions\n  ///\n  /// \\author Balazs Attila Mihaly  \n  template<typename UGraph>\n  inline bool bipartite(const UGraph &graph){\n    using namespace _topology_bits;\n\n    checkConcept<concepts::UGraph, UGraph>();\n    \n    typedef typename UGraph::NodeIt NodeIt;\n    typedef typename UGraph::EdgeIt EdgeIt;\n    \n    bool bipartite = true;\n\n    BipartiteVisitor<UGraph> \n      visitor(graph, bipartite);\n    BfsVisit<UGraph, BipartiteVisitor<UGraph> > \n      bfs(graph, visitor);\n    bfs.init();\n    for(NodeIt it(graph); it != INVALID; ++it) {\n      if(!bfs.reached(it)){\n\tbfs.addSource(it);\n        while (!bfs.emptyQueue()) {\n          bfs.processNextNode();\n          if (!bipartite) return false;\n        }\n      }\n    }\n    return true;\n  }\n  \n  /// \\ingroup graph_prop\n  ///\n  /// \\brief Check if the given undirected graph is bipartite or not\n  ///\n  /// The function checks if the given undirected graph is bipartite \n  /// or not. The  \\ref  Bfs  algorithm  is   used  to  calculate the result. \n  /// During the execution, the \\c partMap will be set as the two \n  /// partitions of the graph.\n  /// \\param graph The undirected graph.\n  /// \\retval partMap A writable bool map of nodes. It will be set as the\n  /// two partitions of the graph. \n  /// \\return %True if \\c graph is bipartite, %false otherwise.\n  ///\n  /// \\author Balazs Attila Mihaly  \n  ///\n  /// \\image html bipartite_partitions.png\n  /// \\image latex bipartite_partitions.eps \"Bipartite partititions\" width=\\textwidth\n  template<typename UGraph, typename NodeMap>\n  inline bool bipartitePartitions(const UGraph &graph, NodeMap &partMap){\n    using namespace _topology_bits;\n\n    checkConcept<concepts::UGraph, UGraph>();\n    \n    typedef typename UGraph::Node Node;\n    typedef typename UGraph::NodeIt NodeIt;\n    typedef typename UGraph::EdgeIt EdgeIt;\n\n    bool bipartite = true;\n\n    BipartitePartitionsVisitor<UGraph, NodeMap> \n      visitor(graph, partMap, bipartite);\n    BfsVisit<UGraph, BipartitePartitionsVisitor<UGraph, NodeMap> > \n      bfs(graph, visitor);\n    bfs.init();\n    for(NodeIt it(graph); it != INVALID; ++it) {\n      if(!bfs.reached(it)){\n\tbfs.addSource(it);\n        while (!bfs.emptyQueue()) {\n          bfs.processNextNode();\n          if (!bipartite) return false;\n        }\n      }\n    }\n    return true;\n  }\n\n  /// \\brief Returns true when there is not loop edge in the graph.\n  ///\n  /// Returns true when there is not loop edge in the graph.\n  template <typename Graph>\n  bool loopFree(const Graph& graph) {\n    for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {\n      if (graph.source(it) == graph.target(it)) return false;\n    }\n    return true;\n  }\n\n  /// \\brief Returns true when there is not parallel edges in the graph.\n  ///\n  /// Returns true when there is not parallel edges in the graph.\n  template <typename Graph>\n  bool parallelFree(const Graph& graph) {\n    typename Graph::template NodeMap<bool> reached(graph, false);\n    for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {\n      for (typename Graph::OutEdgeIt e(graph, n); e != INVALID; ++e) {\n        if (reached[graph.target(e)]) return false;\n        reached.set(graph.target(e), true);\n      }\n      for (typename Graph::OutEdgeIt e(graph, n); e != INVALID; ++e) {\n        reached.set(graph.target(e), false);\n      }\n    }\n    return true;\n  }\n\n  /// \\brief Returns true when there is not loop edge and parallel\n  /// edges in the graph.\n  ///\n  /// Returns true when there is not loop edge and parallel edges in\n  /// the graph.\n  template <typename Graph>\n  bool simpleGraph(const Graph& graph) {\n    typename Graph::template NodeMap<bool> reached(graph, false);\n    for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {\n      reached.set(n, true);\n      for (typename Graph::OutEdgeIt e(graph, n); e != INVALID; ++e) {\n        if (reached[graph.target(e)]) return false;\n        reached.set(graph.target(e), true);\n      }\n      for (typename Graph::OutEdgeIt e(graph, n); e != INVALID; ++e) {\n        reached.set(graph.target(e), false);\n      }\n      reached.set(n, false);\n    }\n    return true;\n  }\n   \n} //namespace lemon\n\n#endif //LEMON_TOPOLOGY_H\n"
  },
  {
    "path": "src/locfit/adap.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n/*\n  Functions implementing the adaptive bandwidth selection.\n  Will make the final call to nbhd() to set smoothing weights\n  for selected bandwidth, But will **not** make the\n  final call to locfit().\n*/\n\n#include \"local.h\"\n\nstatic double hmin;\n\ndouble acri(lk,t0,t2,pen)\ndouble lk, t0, t2, pen;\n{ double y;\n/* return(-2*lk/(t0*exp(pen*log(1-t2/t0)))); */\n  /* return((-2*lk+pen*t2)/t0); */\n  y = (MAX(-2*lk,t0-t2)+pen*t2)/t0;\n  return(y);\n}\n\ndouble mmse(lf,des)\nlfit *lf;\ndesign *des;\n{ int i, ii, j, p, p1;\n  double sv, sb, *l, dp;\n  l = des->wd;\n  wdiag(lf,des,l,(INT)0,(INT)1,(INT)0);\n  sv = sb = 0;\n  p = lf->mi[MP];\n  for (i=0; i<des->n; i++)\n  { sv += l[i]*l[i];\n    ii = des->ind[i];\n    dp = des->di[ii];\n    for (j=0; j<lf->mi[MDEG]; j++) dp *= des->di[ii];\n    sb += fabs(l[i])*dp;\n  }\n  p1 = factorial((int)lf->mi[MDEG]+1);\n  return(sv+sb*sb*lf->dp[DADP]*lf->dp[DADP]/(p1*p1));\n}\n\nstatic double mcp, clo, cup;\n\n/*\n  Initial bandwidth will be (by default)\n  k-nearest neighbors for k small, just lage enough to\n  get defined estimate (unless user provided nonzero DALP\n  or DFXH components)\n*/\n\nINT ainitband(des,lf)\ndesign *des;\nlfit   *lf;\n{ INT lf_status = LF_OK, p, z, cri, noit, redo;\n  double h, ho, t[6];\n  p = des->p;\n  cri = lf->mi[MACRI];\n  noit = !((cri==AOK) | (cri==ANONE));\n  z = (INT)(lf->mi[MN]*lf->dp[DALP]);\n  if ((noit) && (z<p+2)) z = p+2;\n  redo = 0; ho = -1;\n  do\n  { h = nbhd(lf,des,z,lf->dp[DFXH],redo);\n    if (z<des->n) z = des->n;\n    if (h>ho) lf_status = locfit(lf,des,h,noit);\n    if (cri==ANONE) return(lf_status);\n    z++;\n    redo = 1;\n  } while ((z<=lf->mi[MN]) && ((h==0)||(lf_status!=LF_OK)));\n  hmin = h;\n\n  switch(lf->mi[MACRI])\n  { case ACP:\n      local_df(lf,des,t);\n      mcp = acri(des->llk,t[0],t[2],lf->dp[DADP]);\n      return(lf_status);\n    case AKAT:\n      local_df(lf,des,t);\n      clo = des->cf[0]-lf->dp[DADP]*t[5];\n      cup = des->cf[0]+lf->dp[DADP]*t[5];\n      return(lf_status);\n    case AMDI:\n      mcp = mmse(lf,des);\n      return(lf_status);\n    case AOK: return(lf_status);\n  }\n  ERROR((\"aband1: unknown criterion\"));\n  return(LF_ERR);\n}\n\n/*\n  aband2 increases the initial bandwidth until lack of fit results,\n  or the fit is close to a global fit. Increase h by 1+0.3/d at\n  each iteration.\n*/\n\ndouble aband2(des,lf,h0)\ndesign *des;\nlfit   *lf;\ndouble h0;\n{ double t[6], h, h1, nu1, cp, ncp, tlo, tup;\n  INT d, inc, n, p, done;\n  d = lf->mi[MDIM]; n = lf->mi[MN]; p = lf->mi[MP];\n  h1 = h = h0;\n  done = 0; nu1 = 0.0;\n  inc = 0; ncp = 0.0;\n  while ((!done) & (nu1<(n-p)*0.95))\n  { h = nbhd(lf,des,0,(1+0.3/d)*h,1);\n    if (locfit(lf,des,h,1)>0) WARN((\"aband2: failed fit\"));\n    local_df(lf,des,t);\n    nu1 = t[0]-t[2]; /* tr(A) */\n    switch(lf->mi[MACRI])\n    { case AKAT:\n        tlo = des->cf[0]-lf->dp[DADP]*t[5];\n        tup = des->cf[0]+lf->dp[DADP]*t[5];\n/* printf(\"h %8.5f  tlo %8.5f  tup %8.5f\\n\",h,tlo,tup); */\n        done = ((tlo>cup) | (tup<clo));\n        if (!done)\n        { clo = MAX(clo,tlo);\n          cup = MIN(cup,tup);\n          h1 = h;\n        }\n        break;\n      case ACP:\n        cp = acri(des->llk,t[0],t[2],lf->dp[DADP]);\n/* printf(\"h %8.5f  lk %8.5f  t0 %8.5f  t2 %8.5f  cp %8.5f\\n\",h,des->llk,t[0],t[2],cp); */\n        if (cp<mcp) { mcp = cp; h1 = h; }\n        if (cp>=ncp) inc++; else inc = 0;\n        ncp = cp;\n        done = (inc>=10) | ((inc>=3) & ((t[0]-t[2])>=10) & (cp>1.5*mcp));\n        break;\n      case AMDI:\n        cp = mmse(lf,des);\n        if (cp<mcp) { mcp = cp; h1 = h; }\n        if (cp>ncp) inc++; else inc = 0;\n        ncp = cp;\n        done = (inc>=3);\n        break;\n    }\n  }\n  return(h1);\n}\n\n/*\n  aband3 does a finer search around best h so far. Try\n  h*(1-0.2/d), h/(1-0.1/d), h*(1+0.1/d), h*(1+0.2/d)\n*/\ndouble aband3(des,lf,h0)\ndesign *des;\nlfit   *lf;\ndouble h0;\n{ double t[6], h, h1, cp, tlo, tup;\n  INT i, i0, d, n;\n  d = lf->mi[MDIM]; n = lf->mi[MN];\n\n  h1 = h0;\n  i0 = (lf->mi[MACRI]==AKAT) ? 1 : -2;\n  if (h0==hmin) i0 = 1;\n  for (i=i0; i<=2; i++)\n  { if (i==0) i++;\n    h = h0*(1+0.1*i/lf->mi[MDIM]);\n    h = nbhd(lf,des,0,h,1);\n    if (locfit(lf,des,h,1)>0) WARN((\"aband3: failed fit\"));\n    local_df(lf,des,t);\n    switch (lf->mi[MACRI])\n    { case AKAT:\n        tlo = des->cf[0]-lf->dp[DADP]*t[5];\n        tup = des->cf[0]+lf->dp[DADP]*t[5];\n        if ((tlo>cup) | (tup<clo)) /* done */\n          i = 2;\n        else\n        { h1 = h;\n          clo = MAX(clo,tlo);\n          cup = MIN(cup,tup);\n        }\n        break;\n      case ACP:\n        cp = acri(des->llk,t[0],t[2],lf->dp[DADP]);\n        if (cp<mcp) { mcp = cp; h1 = h; }\n        else\n        { if (i>0) i = 2; }\n        break;\n      case AMDI:\n        cp = mmse(lf,des);\n        if (cp<mcp) { mcp = cp; h1 = h; }\n        else\n        { if (i>0) i = 2; }\n    }\n  }\n  return(h1);\n}\n"
  },
  {
    "path": "src/locfit/ar_funs.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n * \n *\n *  ar_setfunction sets a function pointer on the arithmetic structure,\n *    according to the first len compnents of the string z.\n *    Also sets the rt->cmd field, and returns the required number of\n *    arguments.\n */\n\n#include \"local.h\"\n\ndouble vrexp()  { return(rexp(1.0)); }\ndouble vrnorm() { return(rnorm(0.0,1.0)); }\ndouble vpnorm(double x){ return(pnorm(x,0.0,1.0)); }\ndouble vdnorm(double x){ return(exp(-x*x/2)/S2PI); }\ndouble dummyf() { return(0.0); }\ndouble frac(double x) { return(x-floor(x)); }\n\ndouble vmin(v)\nvari *v;\n{ int i;\n  double z, x;\n  z = vitem(v,0);\n  for (i=1; i<vlength(v); i++)\n  { x = vitem(v,i);\n    if (x<z) z = x;\n  }\n  return(z);\n}\n\ndouble vmax(v)\nvari *v;\n{ int i;\n  double z, x;\n  z = vitem(v,0);\n  for (i=1; i<vlength(v); i++)\n  { x = vitem(v,i);\n    if (x>z) z = x;\n  }\n  return(z);\n}\n\ndouble vsum(v)\nvari *v;\n{ int i;\n  double z;\n  z = 0.0;\n  for (i=0; i<vlength(v); i++) z += vitem(v,i);\n  return(z);\n}\ndouble vmean(vari *v) { return(vsum(v)/vlength(v)); }\n\nint ar_setfunction(rt,z,len)\narstruct *rt;\nint z;\nint len;\n{ int rargs;\n  rt->f = NULL;\n  rt->cmd = 'f';\n  rargs = 1;\n  if (len==3)\n  { if (stm(z,\"sin\",3)) rt->f = sin;\n    if (stm(z,\"cos\",3)) rt->f = cos;\n    if (stm(z,\"tan\",3)) rt->f = tan;\n    if (stm(z,\"exp\",3)) rt->f = exp;\n    if (stm(z,\"log\",3)) rt->f = log;\n    if (stm(z,\"abs\",3)) rt->f = fabs;\n    if (stm(z,\"seq\",3)) { rt->f = dummyf; rt->cmd = 'Q'; rargs=3; }\n    if (stm(z,\"min\",3)) { rt->f = vmin; rt->cmd = 'S'; rargs=1; }\n    if (stm(z,\"max\",3)) { rt->f = vmax; rt->cmd = 'S'; rargs=1; }\n    if (stm(z,\"sum\",3)) { rt->f = vsum; rt->cmd = 'S'; rargs=1; }\n    if (stm(z,\"rep\",3)) { rt->f = dummyf; rt->cmd = 'R'; rargs=2; }\n  }\n  if (len==4)\n  { if (stm(z,\"frac\",4)) rt->f = frac;\n    if (stm(z,\"sqrt\",4)) rt->f = sqrt;\n    if (stm(z,\"rexp\",4)) { rt->f = vrexp; rt->cmd = 'G'; }\n    if (stm(z,\"mean\",4)) { rt->f = vmean; rt->cmd = 'S'; rargs=1; }\n  }\n  if (len==5)\n  { if (stm(z,\"floor\",5)) rt->f = floor;\n    if (stm(z,\"pnorm\",5)) rt->f = vpnorm;\n    if (stm(z,\"dnorm\",5)) rt->f = vdnorm;\n    if (stm(z,\"logit\",5)) rt->f = logit;\n    if (stm(z,\"expit\",5)) rt->f = expit;\n    if (stm(z,\"runif\",5)) { rt->f = runif; rt->cmd='G'; }\n    if (stm(z,\"rnorm\",5)) { rt->f = vrnorm;rt->cmd='G'; }\n    if (stm(z,\"rpois\",5)) { rt->f = rpois; rt->cmd='H'; rargs=2; }\n  }\n  if (len==6)\n  { if (stm(z,\"sample\",6)) { rt->f = dummyf;rt->cmd='M'; rargs=2; }\n    if (stm(z,\"fitted\",6)) { rt->f = dummyf; rt->cmd='Z'; rargs=0; }\n  }\n  if (len==9)\n  { if (stm(z,\"residuals\",9))\n    { rt->f= dummyf; rt->cmd='Y'; rargs=0; }\n  }\n  if (rt->f==NULL)\n  { rt->cmd = 'e';\n    ERROR((\"unknown function\"));\n  }\n  return(rargs);\n}\n"
  },
  {
    "path": "src/locfit/arith.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n */\n\n#include <ctype.h>\n#include \"local.h\"\n\n#ifdef CVERSION\n\nextern lfit lf;\nextern int ar_setfunction();\n\ndouble vadd(double e1,double e2) { return(e1+e2); }\ndouble vsub(double e1,double e2) { return(e1-e2); }\ndouble vmul(double e1,double e2) { return(e1*e2); }\ndouble vdiv(double e1,double e2) { return(e1/e2); }\ndouble vpow(double e1,double e2)\n{ if (e2==2) return(e1*e1);\n    if (e1<=0) return(0.0);\n    return(exp(e2*log(e1)));\n}\ndouble vgt(double e1,double e2) { return((double)(e1>e2)); }\ndouble vlt(double e1,double e2) { return((double)(e1<e2)); }\ndouble vge(double e1,double e2) { return((double)(e1>=e2)); }\ndouble vle(double e1,double e2) { return((double)(e1<=e2)); }\ndouble veq(double e1,double e2) { return((double)(e1==e2)); }\ndouble vne(double e1,double e2) { return((double)(e1!=e2)); }\n\narstruct art;\n\ndouble lf_exp(double x) { return (x<700.0) ? exp(x) : exp(700.0); }\n\ndouble vseq(double a,double b,int i,int n) { return(a+(b-a)*i/(n-1)); }\n\ndouble rsample(v)\nvari *v;\n{ int i;\n    i = (int)( runif() * vlength(v) );\n    return( vitem(v,i) );\n}\n\nvari *vrep(v1,v2)\nvari *v1, *v2;\n{ int i, j, k, m, n;\n    vari *v;\n    n = 0;\n    for (i=0; i<vlength(v1); i++) n += vitem(v2,i);\n    v = createvar(\"_vrep\",STHIDDEN,n,VDOUBLE);\n    k = 0;\n    if (vlength(v2)==1)\n    { m = vitem(v2,0);\n        for (i=0; i<m; i++)\n            for (j=0; j<vlength(v1); j++)\n                vassn(v,k++,vitem(v1,j));\n    }\n    else\n    { for (i=0; i<vlength(v1); i++)\n    { m = vitem(v2,i);\n        for (j=0; j<m; j++) vassn(v,k++,vitem(v1,i));\n    }\n    }\n    deleteifhidden(v1);\n    deleteifhidden(v2);\n    return(v);\n}\n\n/*\n Set the arguments on arith structures.\n Argument number p (0,1,2; max args = 3)\n n is the index of source arstruct.\n k is the index of the argument arstruct.\n */\nvoid setnext(va,n,p,k)\nvari *va;\nint n, p, k;\n{ arstruct *rt;\n    rt = viptr(va,n);\n    if (p>=3)\n    { ERROR((\"Too many function arguments\"));\n        return;\n    }\n    rt->nx[p] = k;\n}\n\nvoid prars(v,i)\nvari *v;\nint i;\n{ arstruct *ars;\n    ars = (arstruct *)viptr(v,i);\n    printf(\"%d %c\\n\",i,ars->cmd);\n}\n\narstruct *cmdptr(v,i)\nvari *v;\nint i;\n{ return((arstruct *)viptr(v,i));\n}\n\nint isstring(z,i1,i2)\nchar *z;\nint i1, i2;\n{ int i;\n    if ((z[i1] != '\"') | (z[i2] != '\"')) return(0);\n    for (i=i1+1; i<i2; i++) if (z[i]=='\"') return(0);\n    return(1);\n}\n\nint isname(z,i1,i2)\nchar *z;\nint i1, i2;\n{ int i;\n    if (!isalpha(z[i1])) return(0);\n    for (i=i1+1; i<=i2; i++)\n        if (!isalnum(z[i])) return(0);\n    return(1);\n}\n\nint isfunction(z,i1,i2)\nchar *z;\nint i1, i2;\n{ int i;\n    if (z[i2] != ')') return(0);\n    i = matchlf(z,i1,i2,'(',')');\n    if (lf_error) return(0);\n    return(isname(z,i1,i-1));\n}\n\nint issubset(z,i1,i2)\nchar *z;\nint i1, i2;\n{ int i;\n    if (z[i2] != ']') return(0);\n    i = matchlf(z,i1,i2,'[',']');\n    if (lf_error) return(0);\n    return(isname(z,i1,i-1));\n}\n\nint isNumber(z,i1,i2,val)\nchar *z;\nint i1, i2;\ndouble *val;\n{ char *end;\n    *val = strtod(&z[i1],&end);\n    return(end==&z[i2+1]);\n}\n\nint isoperator(z,i1,i2)\nchar *z;\nint i1, i2;\n{ int i;\n    \n    i = checkrtol(z,i1,i2,\",\");\n    if (i >= i1) return(i);\n    \n    i = checkrtol(z,i1,i2,\"=<>\");\n    if (i > i1) return(i);\n    \n    i = checkrtol(z,i1,i2,\"+-\");\n    while ((i>i1) && (strchr(\"+-*/:^\",z[i-1])!=NULL))\n        i = checkrtol(z,i1+1,i-1,\"+-\");\n    if (i>i1) return(i);\n    \n    i = checkrtol(z,i1,i2,\"*/\");\n    if (i >= i1) return(i);\n    \n    /* looks like a weird priority for : (sequence) but seems to match S. */\n    i = checkrtol(z,i1,i2,\":\");\n    if (i >= i1) return(i);\n    \n    i = checkrtol(z,i1,i2,\"^\");\n    if (i >= i1) return(i);\n    \n    return(-1);\n}\n\nvari *arbuild(z,i1,i2,va,k,dum) /* k=0/1 search variable names? */\nchar *z;                        /* dum: are dummies x0, x1 etc allowed? */\nINT i1, i2, k, dum;\nvari *va;\n{ INT al, ar, i, j, n, nargs, rargs, inum;\n    vari *v;\n    arstruct *rt;\n    char tmp;\n    double val;\n    \n    if (va==NULL)\n    { va = createvar(\"_varith\",STSYSTEM,10,VARC);\n        if (lf_error || va == NULL) \n        {\n            return(NULL);   \n        }\n        else\n        {\n            vlength(va) = 0;\n        }\n    }\n    \n    n = vlength(va);\n    if (vbytes(n+1,VARC)>va->bytes) /* need to grow */\n    { v = va;\n        setvarname(va,\"_ovarith\");\n        va = createvar(\"_varith\",STSYSTEM,n+5,VARC);\n        vlength(va) = n;\n        memcpy(vdptr(va),vdptr(v),vbytes(n,VARC));\n        deletevar(v);\n    }\n    inum = n;\n    vlength(va) = n+1;\n    \n    while ((z[i1]=='(') && (matchrt(z,i1,i2,'(',')')==i2)) { i1++; i2--; }\n    \n    if (isNumber(z,i1,i2,&val))\n    { rt = cmdptr(va,inum);\n        rt->cmd = 'D';\n        rt->x = val;\n        return(va);\n    }\n    \n    if (isstring(z,i1,i2))\n    { rt = cmdptr(va,inum);\n        rt->cmd = 's';\n        rt->vv = createvar(\"_string\",STHIDDEN,i2-i1,VCHAR);\n        for (i=0; i<i2-i1-1; i++) ((char *)vdptr(rt->vv))[i] = z[i1+i+1];\n        ((char *)vdptr(rt->vv))[i2-i1-1] = '\\0';\n        return(va);\n    }\n    \n    if (isname(z,i1,i2))\n    { tmp = z[i2+1]; z[i2+1] = '\\0';\n        if (dum) /* search for dummies */\n        { for (j=0; j<lf.mi[MDIM]; j++)\n            if (strcmp(&z[i1],lf.xname[j])==0)\n            { rt = cmdptr(va,inum);\n                rt->cmd = 'x';\n                rt->m = j;\n                z[i2+1] = tmp;\n                return(va);\n            }\n        }\n        n = 0;\n        v = findvar(&z[i1],1,&n);\n        z[i2+1] = tmp;\n        if (v==NULL) return(va);\n        rt = cmdptr(va,inum);\n        rt->cmd = 'v';\n        rt->vv = v;\n        return(va);\n    }\n    \n    if (isfunction(z,i1,i2))\n    {\n        /* build the argument list */\n        ar = i2;\n        al = matchlf(z,i1,i2,'(',')');\n        j = al+1;\n        nargs = 0;\n        \n        if (ar>al+1)\n        { i = al;\n            while (j<=ar)\n            { if (z[j]=='(') j = matchrt(z,j,ar-1,'(',')')+1;\n                if (z[j]=='[') j = matchrt(z,j,ar-1,'[',']')+1;\n                if (lf_error) return(va);\n                if ((z[j]==')') | (z[j]==','))\n                { setnext(va,n,nargs,vlength(va));\n                    va = arbuild(z,i+1,j-1,va,k,dum);\n                    nargs++; i = j;\n                }\n                j++;\n            }\n        }\n        rt = cmdptr(va,inum);\n        rt->m = nargs;\n        \n        rargs = ar_setfunction(rt,&z[i1],al-i1);\n        if (rargs != nargs)\n            ERROR((\"arbuild: wrong number of arguments, %s\",&z[i1]));\n        return(va);\n    }\n    \n    rt = cmdptr(va,inum);\n    \n    if (issubset(z,i1,i2))\n    { rt->cmd = 'U';\n        al = matchlf(z,i1,i2,'[',']');\n        setnext(va,n,0,vlength(va));\n        va = arbuild(z,i1,al-1,va,k,dum);\n        if (lf_error) return(va);\n        setnext(va,n,1,vlength(va));\n        va = arbuild(z,al+1,i2-1,va,k,dum);\n        return(va);\n    }\n    \n    /* that leaves operators */\n    \n    i = isoperator(z,i1,i2);\n    if (i >= i1)\n    { rt->cmd = 'O';\n        rt->f = NULL;\n        al = i-1; ar = i+1;\n        if (z[i]==',') rt->cmd = 'C';\n        if (z[i]=='>')\n        { rt->f = vgt;\n            if (z[i-1]=='<') { rt->f = vne; al--; }\n        }\n        if (z[i]=='<') rt->f = vlt;\n        if (z[i]=='=')\n        { rt->f = veq;\n            if (z[i-1]=='=') al--;\n            if (z[i-1]=='<') { rt->f = vle; al--; }\n            if (z[i-1]=='>') { rt->f = vge; al--; }\n            if (z[i-1]=='!') { rt->f = vne; al--; }\n        }\n        if (z[i]=='+') rt->f = vadd;\n        if (z[i]=='-') rt->f = vsub;\n        if (z[i]=='*') rt->f = vmul;\n        if (z[i]=='/') rt->f = vdiv;\n        if (z[i]==':') rt->cmd = ':';\n        if (z[i]=='^') rt->f = vpow;\n        \n        setnext(va,n,0,vlength(va));\n        va = arbuild(z,i1,al,va,k,dum);\n        if (lf_error) return(va);\n        setnext(va,n,1,vlength(va));\n        va = arbuild(z,ar,i2,va,k,dum);\n        return(va);\n    }\n    \n    ERROR((\"arbuild: unknown expression %s\",z));\n    return(va);\n}\n\nvari *vevop(l,r,f)\nvari *l, *r;\ndouble (*f)();\n{ INT i, n;\n    vari *v;\n    double z;\n    if ((l==NULL) | (r==NULL)) return(NULL);\n    n = vlength(l);\n    if (n<vlength(r)) n = vlength(r);\n    v = createvar(\"_vevop\",STHIDDEN,n,VDOUBLE);\n    if (lf_error) return(NULL);\n    for (i=0; i<n; i++)\n    { z = f(vitem(l,i),vitem(r,i));\n        vassn(v,i,z);\n    }\n    deleteifhidden(l);\n    deleteifhidden(r);\n    return(v);\n}\n\nvari *vcat(v1,v2)\nvari *v1, *v2;\n{ INT i, n;\n    vari *v;\n    n = vlength(v1) + vlength(v2);\n    v = createvar(\"_vcat\",STHIDDEN,n,VDOUBLE);\n    if (lf_error) return(NULL);\n    for (i=0; i<vlength(v1); i++) vassn(v,i,vitem(v1,i));\n    for (i=0; i<vlength(v2); i++) vassn(v,i+vlength(v1),vitem(v2,i));\n    deleteifhidden(v1);\n    deleteifhidden(v2);\n    return(v);\n}\n\nvari *vrvec(v1,f)\nvari *v1;\ndouble (*f)();\n{ vari *v;\n    INT i, n;\n    n = (INT)vitem(v1,0);\n    v = createvar(\"_vrvec\",STHIDDEN,n,VDOUBLE);\n    if (lf_error) return(NULL);\n    for (i=0; i<n; i++) vassn(v,i,f());\n    deleteifhidden(v1);\n    return(v);\n}\n\nvari *vrsca(v,f)\nvari *v;\ndouble (*f)();\n{ vari *z;\n    if (v==NULL) return(NULL);\n    z = createvar(\"_vrsca\",STHIDDEN,1,VDOUBLE);\n    if (lf_error) return(NULL);\n    vassn(z,(INT)0,f(v));\n    deleteifhidden(v);\n    return(z);\n}\n\nvari *vrve2(v1,a1,f)\nvari *v1, *a1;\ndouble (*f)();\n{ vari *v;\n    int i, n;\n    n = vitem(v1,0);\n    v = createvar(\"_vrvec\",STHIDDEN,n,VDOUBLE);\n    if (lf_error) return(NULL);\n    for (i=0; i<n; i++) vassn(v,i,f(vitem(a1,i)));\n    //deleteifhidden(v1,a1);\n    return(v);\n}\n\nvari *vvec1(l,f)\nvari *l;\ndouble (*f)();\n{ vari *v;\n    INT i;\n    if (l==NULL) \n    {\n        ERROR((\"vvec1 recieved NULL variable\\n\"));  \n        return NULL;\n    }\n    v = createvar(\"_vvec1\",STHIDDEN,l->n,VDOUBLE);\n    if (lf_error) return(NULL);\n    for (i=0; i<vlength(l); i++) vassn(v,i,f(vitem(l,i)));\n    deleteifhidden(l);\n    return(v);\n}\n\nvari *vrsamp(v1,v2)\nvari *v1, *v2;\n{ vari *v;\n    int i, n;\n    n = vitem(v2,0);\n    v = createvar(\"_vrsamp\",STHIDDEN,n,VDOUBLE);\n    if (lf_error) return(NULL);\n    for (i=0; i<n; i++) vassn(v,i,rsample(v1));\n    deleteifhidden(v1);\n    deleteifhidden(v2);\n    return(v);\n}\n\nvari *vrseq(v1,v2,v3)\nvari *v1, *v2, *v3;\n{ vari *v;\n    double beg, end;\n    int i, n;\n    n = vitem(v3,0);\n    v = createvar(\"_vrseq\",STHIDDEN,n,VDOUBLE);\n    if (lf_error) return(NULL);\n    beg = vitem(v1,0);\n    end = vitem(v2,0);\n    for (i=0; i<n; i++) vassn(v,i,vseq(beg,end,i,n));\n    deleteifhidden(v1);\n    deleteifhidden(v2);\n    deleteifhidden(v3);\n    return(v);\n}\n\nvari *vrse2(v1,v2)\nvari *v1, *v2;\n{ vari *v;\n    double beg, end;\n    int i, n;\n    beg = vitem(v1,0);\n    end = vitem(v2,0);\n    n = (beg<=end) ? end-beg+1 : beg-end+1;\n    v = createvar(\"_vrse2\",STHIDDEN,n,VDOUBLE);\n    if (lf_error) return(NULL);\n    if (beg<=end) for (i=0; i<n; i++) vassn(v,i,beg+i);\n    else for (i=0; i<n; i++) vassn(v,i,beg-i);\n    deleteifhidden(v1);\n    deleteifhidden(v2);\n    return(v);\n}\n\nvari *vsubset(v1,v2)\nvari *v1, *v2;\n{ vari *v;\n    int i, n;\n    n = v2->n;\n    v = createvar(\"_vsubs\",STHIDDEN,n,VDOUBLE);\n    for (i=0; i<n; i++) vassn(v,i,vitem(v1,vitem(v2,i)-1));\n    deleteifhidden(v1);\n    deleteifhidden(v2);\n    return(v);\n}\n\nvari *vareval(v,k)\nvari *v;\nINT k;\n{ INT n;\n    arstruct *rt;\n    rt = viptr(v,k);\n    switch (rt->cmd)\n    { case 'e': return(NULL);\n        case 'v': return(rt->vv);\n        case 'O': return(vevop(vareval(v,rt->nx[0]),vareval(v,rt->nx[1]),rt->f));\n        case 'C': return(vcat(vareval(v,rt->nx[0]),vareval(v,rt->nx[1])));\n        case 'D':\n            n = 1;\n            rt->vv = createvar(\"_vevcon\",STHIDDEN,n,VDOUBLE);\n            if (lf_error) return(NULL);\n            vassn(rt->vv,0,rt->x);\n            return(rt->vv);\n        case 'G': return(vrvec(vareval(v,rt->nx[0]),rt->f));\n        case 'H': return(vrve2(vareval(v,rt->nx[0]),vareval(v,rt->nx[1]),rt->f));\n        case 'f': return(vvec1(vareval(v,rt->nx[0]),rt->f));\n        case 'M': return(vrsamp(vareval(v,rt->nx[0]),vareval(v,rt->nx[1])));\n        case 'Q': return(vrseq(vareval(v,rt->nx[0]),vareval(v,rt->nx[1]),\n                               vareval(v,rt->nx[2])));\n        case ':': return(vrse2(vareval(v,rt->nx[0]),vareval(v,rt->nx[1])));\n        case 'S': return(vrsca(vareval(v,rt->nx[0]),rt->f));\n        case 'U': return(vsubset(vareval(v,rt->nx[0]),vareval(v,rt->nx[1])));\n        case 'R': return(vrep(vareval(v,rt->nx[0]),vareval(v,rt->nx[1])));\n        case 'Z': return(vfitted(RMEAN));\n        case 'Y': return(vfitted(RDEV));\n        case 's': return(rt->vv);\n        case 'x':\n            ERROR((\"Dummy in vareval\"));\n            return(NULL);\n        default : ERROR((\"vareval: unknown command %c\",rt->cmd));\n    }\n    return(NULL);\n}\n\nvari *saveresult(v,name,status)\nvari *v;\nint status;\nchar *name;\n{ vari *vr;\n    if (v==NULL) return(NULL);\n    \n    vr = v;\n    if (v->stat != STHIDDEN)\n    { vr = createvar(\"_result\",STHIDDEN,vlength(v),vmode(v));\n        memcpy(vdptr(vr),vdptr(v),vbytes(vlength(v),vmode(v)));\n    }\n    \n    if (name!=NULL)\n    { setvarname(vr,name);\n        vr->stat = status;\n    }\n    return(vr);\n}\n\nvari *varith(z,name,status)\nchar *z, *name;\nint status;\n{ vari *v, *va;\n    va = arbuild(z,0,strlen(z)-1,NULL,1,0);\n    if (lf_error) return(NULL);\n    v = vareval(va,0);\n    deletevar(va);\n    \n    v = saveresult(v,name,status);\n    return(v);\n}\n\ndouble dareval(v,k,x)\nvari *v;\nINT k;\ndouble *x;\n{ arstruct *rt;\n    rt = viptr(v,k);\n    switch (rt->cmd)\n    { case 'e': return(0.0);\n        case 'v': return(vitem(rt->vv,0));\n        case 'O': return(rt->f(dareval(v,rt->nx[0],x),dareval(v,rt->nx[1],x)));\n        case 'P': return(rt->f(0.0,dareval(v,rt->nx[1],x)));\n        case 'D': return(rt->x);\n        case 'G': return(rt->f());\n        case 'H': return(rt->f(dareval(v,rt->nx[1],x)));\n        case 'f': return(rt->f(dareval(v,rt->nx[0],x)));\n        case 'M': return(rsample(vareval(v,rt->nx[0])));\n        case 'x': return(x[rt->m]);\n        case 'U': return(vitem(vareval(v,rt->nx[0]),(int)dareval(v,rt->nx[1],x)-1));\n        case 'Q': ERROR((\"sequence in dareval\"));\n            return(0.0);\n        default : ERROR((\"dareval: unknown command %c\",rt->cmd));\n    }\n    return(0.0);\n}\n\ndouble darith(z)\nchar *z;\n{ vari *va;\n    double y;\n    va = arbuild(z,0,strlen(z)-1,NULL,1,0);\n    y = dareval(va,0,NULL);\n    deletevar(va);\n    return(y);\n}\n\nINT arvect(z,res,c,a) /* c = no of items to read */\nchar *z;\nINT c, a;\ndouble *res;\n{ INT i;\n    vari *v;\n    \n    if (z==NULL) return(0);\n    \n    v = varith(z,\"arvect\",STPLOTVAR);\n    if (v==NULL || lf_error) \n    {\n        return(0);   \n    }\n    deletevar(v);\n    \n    for (i=0; (i<c) & (i<vlength(v)); i++) res[i] = vitem(v,i);\n    if (i<c) /* insufficient items */\n    { switch(a)\n        { case 0: /* pad */\n                for (; i<c; i++) res[i] = res[0];\n                return(c);\n            case 1: return(i); /* ignore */\n            case 2:\n                ERROR((\"Insufficient items: %s\",z));\n                return(i);\n        }\n    }\n    return(i);\n}\n\n#endif\n"
  },
  {
    "path": "src/locfit/band.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\nextern lfit lf;\nextern design des;\nextern void fitoptions();\n\nstatic double hmin, gmin, sig2, pen, vr, tb;\n\n#define BGCV 1\n#define BCP  2\n#define BIND 3\n\nINT procvbind(des,lf,v)\ndesign *des;\nlfit *lf;\nINT v;\n{ double s0, s1, bi;\n    int i, ii, k;\n    k = procvraw(des,lf,v);\n    wdiag(lf,des,des->wd,0,1,0);\n    s0 = s1 = 0.0;\n    for (i=0; i<des->n; i++)\n    { ii = des->ind[i];\n        s0+= prwt(lf,ii)*des->wd[i]*des->wd[i];\n        bi = prwt(lf,ii)*fabs(des->wd[i]*ipower(des->di[ii],lf->mi[MDEG]+1));\n        s1+= bi*bi;\n    }\n    vr += s0;\n    tb += s1;\n    return(k);\n}\n\ndouble bcri(h,c,cri)\ndouble h;\nINT c, cri;\n{ double num, den;\n    INT (*pv)();\n    lf.dp[c] = h;\n    if ((cri&63)==BIND)\n    { pv = procvbind;\n        vr = tb = 0.0;\n    }\n    else pv = procv;\n    if (cri<64) startlf(&des,&lf,pv,0);\n    switch(cri&63)\n    { case BGCV:\n            ressumm(&lf,&des);\n            num = -2*lf.mi[MN]*lf.dp[DLK];\n            den = lf.mi[MN]-lf.dp[DT0];\n            return(num/(den*den));\n        case BCP:\n            ressumm(&lf,&des);\n            return(-2*lf.dp[DLK]/sig2-lf.mi[MN]+pen*lf.dp[DT0]);\n        case BIND:\n            return(vr+pen*pen*tb);\n    } \n    ERROR((\"bcri: unknown criterion\"));\n    return(0.0);\n}\n\nvoid bsel2(h0,g0,ifact,c,cri)\ndouble h0, g0, ifact;\nINT c, cri;\n{ INT done, inc;\n    double h1, g1;\n    h1 = h0; g1 = g0;\n    done = inc = 0;\n    while (!done)\n    { h1 *= 1+ifact;\n        g0 = g1;\n        g1 = bcri(h1,c,cri);\n        if (g1<gmin) { hmin = h1; gmin = g1; }\n        if (g1>g0) inc++; else inc = 0;\n        switch(cri)\n        { case BIND:\n                done = (inc>=4) & (vr<lf.nv);\n                break;\n            default:\n                done = (inc>=4);\n        }\n    }\n}\n\nvoid bsel3(h0,g0,ifact,c,cri)\ndouble h0, g0, ifact;\nINT c, cri;\n{ double h1, g1;\n    INT i;\n    hmin = h0; gmin = g0;\n    for (i=-1; i<=1; i++) if (i!=0)\n    { h1 = h0*(1+i*ifact);\n        g1 = bcri(h1,c,cri);\n        if (g1<gmin) { hmin = h1; gmin = g1; }\n    }\n    return;\n}\n\nvoid bselect(c,cri,pn)\nINT c, cri;\ndouble pn;\n{ double h0, g0, ifact;\n    INT i;\n    pen = pn;\n    if (cri==BIND) pen /= factorial((int)lf.mi[MDEG]+1);\n    hmin = h0 = lf.dp[c];\n    if (h0==0) ERROR((\"bselect: initial bandwidth is 0\"));\n    if (lf_error) return;\n    sig2 = 1.0;\n    \n    gmin = g0 = bcri(h0,c,cri);\n    if (cri==BCP)\n    { sig2 = lf.dp[DRV];\n        g0 = gmin = bcri(h0,c,cri+64);\n    }\n    \n    ifact = 0.3;\n    bsel2(h0,g0,ifact,c,cri);\n    \n    for (i=0; i<5; i++)\n    { ifact = ifact/2;\n        bsel3(hmin,gmin,ifact,c,cri);\n    }\n    lf.dp[c] = hmin;\n    startlf(&des,&lf,procv,0);\n    ressumm(&lf,&des);\n}\n\ndouble compsda(x,h,n)\ndouble *x, h;\nINT n;\n/* n/(n-1) * int( fhat''(x)^2 dx ); bandwidth h */\n{ INT i, j;\n    double ik, sd, z;\n    ik = wint(1,NULL,0,WGAUS);\n    sd = 0;\n    \n    for (i=0; i<n; i++)\n        for (j=i; j<n; j++)\n        { z = (x[i]-x[j])/h;\n            sd += (2-(i==j))*Wconv4(z,WGAUS)/(ik*ik);\n        }\n    sd = sd/(n*(n-1)*h*h*h*h*h);\n    return(sd);\n}\n\ndouble widthsj(x,lambda,n)\ndouble *x, lambda;\nINT n;\n{ double ik, a, b, td, sa, z, c, c1, c2, c3;\n    INT i, j;\n    a = GFACT*0.920*lambda*exp(-log((double)n)/7)/SQRT2;\n    b = GFACT*0.912*lambda*exp(-log((double)n)/9)/SQRT2;\n    ik = wint(1,NULL,0,WGAUS);\n    \n    td = 0;\n    for (i=0; i<n; i++)\n        for (j=i; j<n; j++)\n        { z = (x[i]-x[j])/b;\n            td += (2-(i==j))*Wconv6(z,WGAUS)/(ik*ik);\n        }\n    \n    td = -td/(n*(n-1));\n    j = 2.0;\n    c1 = Wconv4(0.0,WGAUS);\n    c2 = wint(1,&j,1,WGAUS);\n    c3 = Wconv(0.0,WGAUS);  /* (2*c1/(c2*c3))^(1/7)=1.357 */\n    sa = compsda(x,a,n);\n    c = b*exp(log(c1*ik/(c2*c3*GFACT*GFACT*GFACT*GFACT)*sa/td)/7)*SQRT2;\n    return(c);\n}\n\nvoid kdecri(x,h,res,c,k,ker,n)\ndouble *x, h, *res, c;\nINT k, ker, n;\n{ INT i, j;\n    double degfree, dfd, pen, s, r0, r1, d0, d1, ik, wij;\n    \n    if (h<=0) WARN((\"kdecri, h = %6.4f\",h));\n    \n    res[0] = res[1] = 0.0;\n    ik = wint(1,NULL,0,ker);\n    switch(k)\n    { case 1: /* aic */\n            pen = 2.0;\n            for (i=0; i<n; i++)\n            { r0 = d0 = 0.0;\n                for (j=0; j<n; j++)\n                { s = (x[i]-x[j])/h;\n                    r0 += W(s,ker);\n                    d0 += s*s*Wd(s,ker);\n                }\n                d0 = -(d0+r0)/(n*h*h*ik);  /* d0 = d/dh fhat(xi) */\n                r0 /= n*h*ik;              /* r0 = fhat(xi) */\n                res[0] += -2*log(r0)+pen*W(0.0,ker)/(n*h*ik*r0);\n                res[1] += -2*d0/r0-pen*W(0.0,ker)/(n*h*ik*r0)*(d0/r0+1.0/h);\n            }\n            return;\n        case 2: /* ocv */\n            for (i=0; i<n; i++)\n            { r0 = 0.0; d0 = 0.0;\n                for (j=0; j<n; j++) if (i!=j)\n                { s = (x[i]-x[j])/h;\n                    r0 += W(s,ker);\n                    d0 += s*s*Wd(s,ker);\n                }\n                d0 = -(d0+r0)/((n-1)*h*h);\n                r0 = r0/((n-1)*h);\n                res[0] -= log(r0);\n                res[1] -= d0/r0;\n            }\n            return;\n        case 3: /* lscv */\n            r0 = r1 = d0 = d1 = degfree = 0.0;\n            for (i=0; i<n; i++)\n            { dfd = 0.0;\n                for (j=0; j<n; j++)\n                { s = (x[i]-x[j])/h;\n                    wij = W(s,ker);\n                    dfd += wij;\n                    /* \n                     *  r0 = \\int fhat * fhat = sum_{i,j} W*W( (Xi-Xj)/h ) / n^2 h.\n                     *  d0 is it's derivative wrt h.\n                     *\n                     *  r1 = 1/n sum( f_{-i}(X_i) ).\n                     *  d1 is  it's derivative wrt h.\n                     *\n                     *  degfree = sum_i ( W_0 / sum_j W( (Xi-Xj)/h ) ) is fitted d.f.\n                     */\n                    r0 += Wconv(s,ker);\n                    d0 += -s*s*Wconv1(s,ker);\n                    if (i != j)\n                    { r1 += wij;\n                        d1 += -s*s*Wd(s,ker);\n                    }\n                }\n                degfree += 1.0/dfd;\n            }\n            d1 -= r1;\n            d0 -= r0;\n            res[0] = r0/(n*n*h*ik*ik)   - 2*r1/(n*(n-1)*h*ik);\n            res[1] = d0/(n*n*h*h*ik*ik) - 2*d1/(n*(n-1)*h*h*ik);\n            res[2] = degfree;\n            return;\n        case 4: /* bcv */\n            r0 = d0 = 0.0;\n            for (i=0; i<n; i++)\n                for (j=i+1; j<n; j++)\n                { s = (x[i]-x[j])/h;\n                    r0 += 2*Wconv4(s,ker);\n                    d0 += 2*s*Wconv5(s,ker);\n                }\n            d0 = (-d0-r0)/(n*n*h*h*ik*ik);\n            r0 = r0/(n*n*h*ik*ik);\n            j = 2.0;\n            d1 = wint(1,&j,1,ker);\n            r1 = Wconv(0.0,ker);\n            res[0] = (d1*d1*r0/4+r1/(n*h))/(ik*ik);\n            res[1] = (d1*d1*d0/4-r1/(n*h*h))/(ik*ik);\n            return;\n        case 5: /* sjpi */\n            s = c*exp(5*log(h)/7)/SQRT2;\n            d0 = compsda(x,s,n);\n            res[0] = d0; /* this is S(alpha) in SJ */\n            res[1] = exp(log(Wikk(WGAUS,0)/(d0*n))/5)-h;\n            return;\n        case 6: /* gas-k-k */\n            s = exp(log(1.0*n)/10)*h;\n            d0 = compsda(x,s,n);\n            res[0] = d0;\n            res[1] = exp(log(Wikk(WGAUS,0)/(d0*n))/5)-h;\n            return;\n    }\n    ERROR((\"kdecri: what???\"));\n    return;\n}\n\ndouble esolve(x,j,h0,h1,k,c,ker,n)\ndouble *x, h0, h1, c;\nINT j, k, ker, n;\n{ \n    double h[7], d[7], r[7], res[4], min, minh, fact;\n    INT i, nc;\n    memset(h, 0, sizeof(h));\n    memset(d, 0, sizeof(d));\n    memset(r, 0, sizeof(r));\n    \n    min = 1.0e30; minh = 0.0;\n    fact = 1.00001;\n    h[6] = h0; kdecri(x,h[6],res,c,j,ker,n);\n    r[6] = res[0]; d[6] = res[1];\n    if (lf_error) return(0.0);\n    nc = 0;\n    for (i=0; i<k; i++)\n    { h[5] = h[6]; r[5] = r[6]; d[5] = d[6];\n        h[6] = h0*exp((i+1)*log(h1/h0)/k);\n        kdecri(x,h[6],res,c,j,ker,n);\n        r[6] = res[0]; d[6] = res[1];\n        if (lf_error) return(0.0);\n        if (d[5]*d[6]<0)\n        { h[2] = h[0] = h[5]; d[2] = d[0] = d[5]; r[2] = r[0] = r[5];\n            h[3] = h[1] = h[6]; d[3] = d[1] = d[6]; r[3] = r[1] = r[6];\n            while ((h[3]>fact*h[2])|(h[2]>fact*h[3]))\n            { h[4] = h[3]-d[3]*(h[3]-h[2])/(d[3]-d[2]);\n                if ((h[4]<h[0]) | (h[4]>h[1])) h[4] = (h[0]+h[1])/2;\n                kdecri(x,h[4],res,c,j,ker,n);\n                r[4] = res[0]; d[4] = res[1];\n                if (lf_error) return(0.0);\n                h[2] = h[3]; h[3] = h[4];\n                d[2] = d[3]; d[3] = d[4];\n                r[2] = r[3]; r[3] = r[4];\n                if (d[4]*d[0]>0) { h[0] = h[4]; d[0] = d[4]; r[0] = r[4]; }\n                else { h[1] = h[4]; d[1] = d[4]; r[1] = r[4]; }\n            }\n            if (j>=4) return(h[4]); /* first min for BCV etc */\n            if (r[4]<=min) { min = r[4]; minh = h[4]; }\n            nc++;\n        }\n    }\n    if (nc==0) minh = (r[5]<r[6]) ? h0 : h1;\n    return(minh);\n}\n\nvoid kdeselect(band,x,ind,h0,h1,meth,nm,ker,n)\ndouble h0, h1, *band, *x;\nINT *ind, *meth, nm, ker, n;\n{ double scale, c;\n    INT i, k;\n    k = n/4;\n    for (i=0; i<n; i++) ind[i] = i;\n    scale = kordstat(x,n+1-k,n,ind) - kordstat(x,k,n,ind);\n    c = widthsj(x,scale,n);\n    for (k=0; k<nm; k++)\n        band[k] = esolve(x,meth[k],h0,h1,10,c,ker,n);\n}\n\n#ifdef CVERSION\nvoid band(v)\nvari *v;\n{ INT i, c, cri;\n    double pen;\n    char *z;\n    fitoptions(&lf,v,0);\n    \n    c = DALP;\n    i = getarg(v,\"comp\",1);\n    if (i>0)\n    { z = argval(v,i);\n        if (z[0]=='h') c = DFXH;\n    }\n    \n    cri = BGCV;\n    i = getarg(v,\"bcri\",1);\n    if (i>0)\n    { z = argval(v,i);\n        if (z[0]=='c') cri = BCP;\n        if (z[0]=='i') cri = BIND;\n    }\n    \n    pen = 2.0;\n    i = getarg(v,\"pen\",1);\n    if (i>0)\n        pen = darith(argval(v,i));\n    \n    bselect(c,cri,pen);\n}\n#endif\n\n#ifdef SVERSION\nvoid slscv(x,n,h,z)\ndouble *x, *h, *z;\nint *n;\n{ INT i;\n    double res[4];\n    kdecri(x,*h,res,0.0,3,WGAUS,*n);\n    z[0] = res[0];\n    z[1] = res[2];\n}\n#endif\n"
  },
  {
    "path": "src/locfit/c_args.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n *\n *   Functions for interpreting and manipulating command line\n *   arguments.\n */\n\n#include \"local.h\"\n\nchar *argval(vari *v,int i)\n{ if (i<0) return(NULL);\n  return(((carg *)viptr(v,i))->val);\n}\n\nint getarg(v,s,un) /* un=1: unnamed permitted un=2: next unused */\nvari *v;\nint un;\nchar *s;\n{ int i;\n  if (un==2)\n  { for (i=1; i<vlength(v); i++)\n    { if (!argused(v,i))\n      { setused(v,i);\n        return(i);\n      }\n    }\n    return(0);\n  }\n  for (i=1; i<vlength(v); i++)\n  { if ((!argused(v,i)) && (argarg(v,i)!=NULL))\n    { if (strcmp(argarg(v,i),s)==0)\n      { setused(v,i);\n        return(i);\n      }\n    }\n  }\n  if (!un) return(0);\n  for (i=1; i<vlength(v); i++)\n  { if ((!argused(v,i)) && (argarg(v,i)==NULL))\n    { setused(v,i);\n      return(i);\n    }\n  }\n  return(0);\n}\n\nchar *getargval(vari *v, char *s, int un)\n{ int i;\n  i = getarg(v,s,un);\n  if (i==0) return(NULL);\n  return(argval(v,i));\n}\n\nint readilist(ivec,z,n0,n1,pad)\nchar *z;\nint *ivec, n0, n1, pad;\n{ int i, n, nd;\n  n = 1;\n  for (i=0; i<strlen(z); i++)\n    if (z[i]==',') { z[i]=' '; n++; }\n  if (n>n1)\n  { WARN((\"too many items in ilist\"));\n    n = n1;\n  }\n  for (i=0; i<n; i++)\n  { nd = sscanf(z,\"%d\",&ivec[i]);\n    //if (nd!=1) WARN((\"problem scaning ilist %s\",&ivec[i]));\n    if (i<n-1) while (*z!=' ') z++;\n  }\n  if (pad)\n  { for (i=n; i<n1; i++) ivec[i] = ivec[0]; \n    n = n1;\n  }\n  if (n<n0) WARN((\"too few items in ilist\"));\n  return(n);\n}\n\nint getlogic(v,i)\nvari *v;\nint i;\n{ char *z;\n  if (argarg(v,i)==NULL) return(1);\n  z = argval(v,i);\n  if ((z[0]=='T') | (z[0]=='t') | (z[0]=='1')) return(1);\n  if ((z[0]=='F') | (z[0]=='f') | (z[0]=='0')) return(0);\n  ERROR((\"getlogic: invalid logical argument %s\",z));\n  return(0);\n}\n"
  },
  {
    "path": "src/locfit/c_plot.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\nvari *growvar(vari* vold, int n);\n\nplots *cpl, pl[MAXWIN];\nextern device devps, devwin;\nINT curwin;\nchar *psfn;\nextern lfit lf;\nextern pplot pp;\nextern char *curstr;\n\nplots *get_graphics_window(v)\nvari *v;\n{ int win_no;\n  char *w;\n\n  w = getargval(v,\"win\",0);\n  if (w != NULL)\n  { sscanf(w,\"%d\",&win_no);\n    if ((win_no<0) | (win_no>=MAXWIN))\n    { WARN((\"Invalid window %d\",win_no));\n    }\n    else\n      curwin = win_no;\n  }\n  return( &pl[curwin] );\n}\n\nchar *settype(xyz,type,def)\nplxyz *xyz;\nchar *type, def;\n{ if ((type==NULL) || (strlen(type)==0))\n  { xyz->type = def;\n    return(NULL);\n  }\n  xyz->type = type[0];\n  return(&type[1]);\n}\n\nchar *pvarname(xyz,c,vn)\nplxyz *xyz;\nchar c;\nvarname vn;\n{ sprintf(vn,\"_plv%d%c\",xyz->id,c);\n  return(vn);\n}\n\nplxyz *nextxyz(win,add,ck)\nplots *win;\nINT add, ck;\n{ plxyz *xyz;\n  vari *v;\n  varname vn;\n\n  if (!add)\n  { sprintf(vn,\"_xyz%d\",curwin);\n    v = win->xyzs = createvar(vn,STSYSTEM,5,VXYZ);\n    v->n = 0;\n    win->xlab[0] = win->ylab[0] = win->zlab[0] = '\\0';\n  }\n  else\n    v = win->xyzs = growvar(win->xyzs,vlength(win->xyzs)+ck);\n\n  xyz = (plxyz *)viptr(v,vlength(v));\n  xyz->id = (vlength(v) << 4) + win->id;\n  xyz->pch = 1;\n  v->n++;\n  return(xyz);\n}\n\nvoid plotopt(v,re)\nvari *v;\nINT re;\n{ INT i, j, h, w;\n  double z[2];\n  char *fmt, *ty;\n  plxyz *xyz;\n\n  cpl = get_graphics_window(v);\n\n  if (!re)\n  { cpl->main[0] = '\\0';\n    cpl->xl[0] = cpl->xl[1] = cpl->yl[0]\n               = cpl->yl[1] = cpl->zl[0] = cpl->zl[1] = 0.0;\n    cpl->nsl = 0;\n  }\n\n  arvect(getargval(v,\"xlim\",1), cpl->xl, 2, 2);\n  arvect(getargval(v,\"ylim\",1), cpl->yl, 2, 2);\n  arvect(getargval(v,\"zlim\",1), cpl->zl, 2, 2);\n\n  i = getarg(v,\"main\",1);\n  if (i>0) { strcpy(cpl->main,argval(v,i)); strip(cpl->main); }\n  i = getarg(v,\"xlab\",1);\n  if (i>0) { strcpy(cpl->xlab,argval(v,i)); strip(cpl->xlab); }\n  i = getarg(v,\"ylab\",1);\n  if (i>0) { strcpy(cpl->ylab,argval(v,i)); strip(cpl->ylab); }\n  i = getarg(v,\"zlab\",1);\n  if (i>0) { strcpy(cpl->zlab,argval(v,i)); strip(cpl->zlab); }\n\n  if ( arvect(getargval(v,\"view\",1), z, 2, 2) == 2 )\n  { cpl->theta=z[0];\n    cpl->phi  =z[1];\n  }\n\n  fmt = getargval(v,\"fmt\",1);\n  if (fmt==NULL) fmt = \"xwin\";\n\n  i = getarg(v,\"split\",1);\n  if (i>0)\n    cpl->nsl = arvect(argval(v,i),cpl->sl,10,1);\n  i = getarg(v,\"h\",1);\n  if (i>0) sscanf(argval(v,i),\"%d\",&h); else h = 0;\n  i = getarg(v,\"w\",1);\n  if (i>0) sscanf(argval(v,i),\"%d\",&w); else w = 0;\n\n  ty = getargval(v,\"type\",1);\n  if (ty != NULL)\n  { for (j=0; j<vlength(cpl->xyzs); j++)\n    { xyz = (plxyz *)viptr(cpl->xyzs,j);\n      ty = settype(xyz,ty,xyz->type);\n    }\n  }\n  if (stm(fmt,\"xwin\",1)) { plotxwin(cpl,&devwin,curwin,w,h,0); return; }\n  if (stm(fmt,\"win\",1))  { plotxwin(cpl,&devwin,curwin,w,h,0); return; }\n  if (stm(fmt,\"post\",1))\n  { psfn = getargval(v,\"file\",1);\n    plotxwin(cpl,&devps,curwin,w,h,0);\n    return;\n  }\n}\n\nvoid pvari(cmd,xyz,win,ax)\nchar *cmd, ax;\nplxyz *xyz;\nplots *win;\n{ vari *vv;\n  INT k;\n  varname vname;\n  vv = varith(cmd,pvarname(xyz,ax,vname),STPLOTVAR);\n  if (vv==NULL) return;\n  k = xyz->id>>4;\n  switch(ax)\n  { case 'x':\n      xyz->x = vv;\n      if (k==0) strcpy(win->xlab,cmd);\n      return;\n    case 'y':\n      xyz->y = vv;\n      if (k==0) strcpy(win->ylab,cmd);\n      return;\n    case 'z':\n      xyz->z = vv;\n      if (k==0) strcpy(win->zlab,cmd);\n      return;\n  }\n  ERROR((\"pvari: unknown axis %c\",ax));\n}\n\nvoid plotdata(v)\nvari *v;\n{ INT add, i, j, k;\n  plxyz *xyz = NULL, *xyz2 = NULL;\n  char *type;\n\n  cpl = get_graphics_window(v);\n\n  i = getarg(v,\"add\",0);\n  add = (i>0) ? getlogic(v,i) : 0;\n\n  type = getargval(v,\"type\",0);\n\n  i = getarg(v,\"data\",0);\n  if (i>0) doreaddata(argval(v,i),(INT)0);\n\n  i = getarg(v,\"pch\",0);\n  if (i>0) sscanf(argval(v,i),\"%d\",&xyz->pch);\n\n  xyz = nextxyz(cpl,add,2);\n  if (xyz==NULL) return;\n  xyz->x = xyz->y = xyz->z = NULL;\n  type = settype(xyz,type,'p');\n\n  i = getarg(v,\"x\",1);\n  j = getarg(v,\"y\",1);\n  k = getarg(v,\"z\",1);\n\n  if (!add) /* set the default view angle */\n  { cpl->theta = 45*( 1 - ((j==0)|(k==0)) - 3*(i==0) );\n    cpl->phi   = 45*( 1 + ((i==0)|(j==0)) - (k==0) );\n  }\n\n  if (i>0) pvari(argval(v,i),xyz,cpl,'x');\n  if (j>0) pvari(argval(v,j),xyz,cpl,'y');\n  if (k>0) pvari(argval(v,k),xyz,cpl,'z');\n\n  i = getarg(v,\"x2\",1);\n  j = getarg(v,\"y2\",1);\n  k = getarg(v,\"z2\",1);\n  if (i+j+k>0)\n  { xyz2= nextxyz(cpl,1,1);\n    if (xyz2==NULL) return;\n    xyz2->x = xyz->x;\n    xyz2->y = xyz->y;\n    xyz2->z = xyz->z;\n    type = settype(xyz2,type,'s');\n    if (i>0) pvari(argval(v,i),xyz2,cpl,'x');\n    if (j>0) pvari(argval(v,j),xyz2,cpl,'y');\n    if (k>0) pvari(argval(v,k),xyz2,cpl,'z');\n  }\n  if (lf_error) return;\n\n  cpl->ty |= PLDATA;\n\n  plotopt(v,add);\n}\n\nvoid plotfit(v)\nvari *v;\n{ INT add, d, dp, i = 0, j = 0, n, sef;\n  INT dt, mg[MXDIM], ix, iy;\n  double c, sd, xl[2*MXDIM], xll[2];\n  char cb;\n  varname vn;\n  plxyz *xyz, *xyzl, *xyzu, *xyzd;\n  char *type;\n\n  cpl = get_graphics_window(v);\n\n  i = getarg(v,\"fit\",1);\n  if (i>0) dosavefit(&lf,argval(v,i),\"rb\",(INT)0);\n  if (nofit()) ERROR((\"plotfit: no fit to plot.\"));\n  if (lf_error) return;\n  dp = 0;\n\n  d = lf.mi[MDIM];\n  for (i=0; i<d; i++)\n  { j = getarg(v,lf.xname[i],0);\n    if (j>0)\n    { j = arvect(argval(v,j),xll,2,1);\n      if (j==1)\n        xl[i] = xl[i+d] = xll[0];\n      else\n      { xl[i] = xll[0];\n        xl[i+d] = xll[1];\n      }\n    }\n    else\n    { xl[i] = lf.fl[i];\n      xl[i+d] = lf.fl[i+d];\n      j = 2;\n    }\n    if (j==2)\n    { if (dp==2)\n      { xl[i] = xl[i+d] = (xl[i]+xl[i+d])/2;\n        WARN((\"plotfit: fixing %s=%f\",lf.xname[i],xl[i]));\n        j = 1;\n      }\n      if (dp==1) { iy = i; dp++; }\n      if (dp==0) { ix = i; dp++; }\n    }\n    mg[i] = 2-j;\n  }\n  if (dp<=0)\n  { ERROR((\"No plot variables\"));\n    return;\n  }\n  sef = 0; dt = 0;\n  i = getarg(v,\"data\",1);  if (i>0) dt =getlogic(v,i);\n  i = getarg(v,\"band\",1);  cb = (i>0) ? *argval(v,i) : 'n';\n\n  for (i=0; i<d; i++) mg[i] = 1;\n  if (dp==1)\n    mg[ix] = 100;\n  else\n    mg[ix] = mg[iy] = 50;\n  i = getarg(v,\"m\",1);\n  if (i>0) readilist(mg,argval(v,i),1,lf.mi[MDIM],1);\n\n  i = getarg(v,\"add\",1);\n  add = (i>0) ? getlogic(v,i) : 0;\n\n  type =  getargval(v,\"type\",1);\n\n  if ((lf.mi[MEV]==EDATA) | (lf.mi[MEV]==ECROS))\n    n = setpppoints(&pp,\"fitp\",mg,xl);\n  else\n    n = setpppoints(&pp,\"grid\",mg,xl);\n  pp.fit = createvar(\"_ppfit\",STPLOTVAR,n,VDOUBLE);\n  if (cb=='n')\n    pp.se = NULL;\n  else\n    pp.se = createvar(\"_ppsef\",STPLOTVAR,n,VDOUBLE);\n  if (lf_error) return;\n  cpreplot(&pp,v,cb);\n  if (lf_error) return;\n\n  xyz = nextxyz(cpl,add,4);\n  if (xyz==NULL) return;\n  /* set up first predictor variable */\n  xyz->x = pp.data[ix];\n  setvarname(xyz->x,pvarname(xyz,'x',vn));\n  strcpy(cpl->xlab,lf.xname[ix]);\n\n  /* set up second predictor variable */\n  if (dp==2)\n  { xyz->y = pp.data[iy];\n    setvarname(xyz->y,pvarname(xyz,'y',vn));\n    strcpy(cpl->ylab,lf.xname[iy]);\n  }\n  else\n  { xyz->y = NULL;\n    cpl->ylab[0] = '\\0';\n  }\n\n  xyz->z = pp.fit;\n  setvarname(xyz->z,pvarname(xyz,'z',vn));\n  switch(lf.mi[MTG]&63)\n  { case TDEN: strcpy(cpl->zlab,\"Density\"); break;\n    case TRAT: strcpy(cpl->zlab,\"Rate\"); break;\n    case THAZ: strcpy(cpl->zlab,\"Hazard\"); break;\n    default: strcpy(cpl->zlab,lf.yname);\n  }\n  type = settype(xyz,type,(dp==1) ? 'l' : 'c');\n\n  if (pp.se!=NULL)\n  { xyzl = nextxyz(cpl,1,3); xyzu = nextxyz(cpl,1,2);\n    if ((xyzl!=NULL) & (xyzu!=NULL))\n    { sd = sqrt(lf.dp[DRV]);\n      xyzl->x = xyzu->x = xyz->x;\n      xyzl->y = xyzu->y = xyz->y;\n      xyzl->z = createvar(pvarname(xyzl,'z',vn),STPLOTVAR,n,VDOUBLE);\n      xyzu->z = createvar(pvarname(xyzu,'z',vn),STPLOTVAR,n,VDOUBLE);\n      if (lf_error) return;\n      c = docrit(v);\n      for (i=0; i<n; i++)\n      { vassn(xyzu->z,i,backtr(vitem(pp.fit,i)+c*vitem(pp.se,i),lf.mi,lf.nd));\n        vassn(xyzl->z,i,backtr(vitem(pp.fit,i)-c*vitem(pp.se,i),lf.mi,lf.nd));\n      }\n      type = settype(xyzl,type,(d==1) ? 'l' : 'c');\n      type = settype(xyzu,type,(d==1) ? 'l' : 'c');\n    }\n    deletevar(pp.se);\n  }\n  if (pp.wh==PCOEF)\n    for (i=0; i<vlength(xyz->z); i++)\n      vassn(xyz->z,i,backtr(vitem(pp.fit,i),lf.mi,lf.nd));\n  if (dt)\n  {\n    recondat(0,&n);\n    if (lf_error) return;\n    xyzd = nextxyz(cpl,1,1);\n    if (xyzd!=NULL)\n    { xyzd->x = createvar(pvarname(xyzd,'x',vn),STPLOTVAR,n,VDOUBLE);\n      for (i=0; i<n; i++) vassn(xyzd->x,i,datum(&lf,ix,i));\n      if (d==2)\n      { xyzd->y = createvar(pvarname(xyzd,'y',vn),STPLOTVAR,n,VDOUBLE);\n        for (i=0; i<n; i++) vassn(xyzd->y,i,datum(&lf,iy,i));\n      }\n      else xyzd->y = NULL;\n      xyzd->z = createvar(pvarname(xyzd,'z',vn),STPLOTVAR,n,VDOUBLE);\n      for (i=0; i<n; i++)\n        vassn(xyzd->z,i,((lf.mi[MTG]&63)==TGAUS) ? resp(&lf,i) : resp(&lf,i)/prwt(&lf,i));\n      type = settype(xyzd,type,'p');\n    }\n  }\n\n  /* now, set default view angle */\n  if (!add)\n  { if (dp==1) { cpl->theta = 0; cpl->phi = 90; } /* x-z axis */\n    else\n    { if (xyz->type=='w')\n        cpl->theta = cpl->phi = 45; /* wireframes */\n      else\n        cpl->theta = cpl->phi = 0;  /* x-y plot; e.g. for contours */\n    }\n  }\n  if (lf_error) return;\n  cpl->ty |= PLFIT;\n  if (dt) cpl->ty |= PLDATA;\n\n  plotopt(v,add);\n}\n\nvoid plottrack(v)\nvari *v;\n{ INT i, j;\n  plxyz *xyz;\n  varname vn;\n\n  cpl = get_graphics_window(v);\n\n  if ((cpl->ty & PLTRK)!=PLTRK) /* initialize */\n  { xyz = nextxyz(cpl,0,1);\n    xyz->x = createvar(pvarname(xyz,'x',vn),STPLOTVAR,100,VDOUBLE);\n    xyz->y = createvar(pvarname(xyz,'y',vn),STPLOTVAR,100,VDOUBLE);\n    xyz->z = createvar(pvarname(xyz,'z',vn),STPLOTVAR,100,VDOUBLE);\n    if (lf_error) return;\n    vlength(xyz->x) = vlength(xyz->y) = vlength(xyz->z) = 0;\n    settype(xyz,NULL,'p');\n    cpl->theta = cpl->phi = 0;\n    cpl->ty = PLTRK;\n  }\n  else\n  { vlength(cpl->xyzs) = 0;\n    xyz = nextxyz(cpl,1,1);\n  }\n  j = vlength(xyz->x);\n  i = getarg(v,\"x\",1);\n  if (i>0)\n  { vassn(xyz->x,j,darith(argval(v,i)));\n    strcpy(cpl->xlab,argval(v,i));\n    vlength(xyz->x) = j+1;\n  }\n  i = getarg(v,\"y\",1);\n  if (i>0)\n  { vassn(xyz->y,j,darith(argval(v,i)));\n    strcpy(cpl->ylab,argval(v,i));\n    vlength(xyz->y) = j+1;\n  }\n  i = getarg(v,\"z\",1);\n  if (i>0)\n  { vassn(xyz->z,j,darith(argval(v,i)));\n    strcpy(cpl->zlab,argval(v,i));\n    vlength(xyz->z) = j+1;\n  }\n  plotopt(v,0);\n}\n\nvoid setplot(v)\nvari *v;\n{ INT i, j, w;\n  carg *ct;\n  varname tname;\n  i = getarg(v,\"win\",1);\n  if (i==0)\n  { ERROR((\"setplot: no win argument\"));\n    return;\n  }\n  sscanf(argval(v,i),\"%d\",&w);\n  if ((w<0) | (w>=MAXWIN))\n  { ERROR((\"setplot: invalid win %s\",argval(v,i)));\n    return;\n  }\n  if (vlength(v)==2)\n  { deletevar(pl[w].track);\n    pl[w].track = NULL;\n    return;\n  }\n  sprintf(tname,\"=tpc%d\",w);\n  pl[w].track = createvar(tname,STSYSTEM,v->n-2,VARGL);\n  j = 0;\n  pl[w].ty = PLNONE; /* to ensure previous track is cleared */\n  for (i=1; i<vlength(v); i++)\n  { if (!argused(v,i))\n    { ct = (carg *)viptr(pl[w].track,j);\n      ct->arg = argarg(v,i);\n      ct->val = argval(v,i);\n      setused(v,i);\n      j++;\n    }\n  }\n  sprintf(tname,\"=tps%d\",w);\n  setvarname(curstr,tname);\n}\n"
  },
  {
    "path": "src/locfit/cmd.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n */\n\n#include <unistd.h>\n#ifdef DOS\n#include <dos.h>\n#endif\n\n#include \"local.h\"\n\n#ifdef CVERSION\n\n#define MAXK 20\n\nFILE *ofile;\n\ndevice devps, devwin;\ndesign des;\nlfit lf;\nvari *aru;\n\nextern plots pl[];\npplot pp;\nstruct lfcol mycol[MAXCOLOR];\nchar *lfhome;\nextern char filename[100];\n\nINT lf_error, lfcm[10];\n\nvari *curstr;\nvoid cmdint();\nvoid del_lines();\n\n/*\n INDEX  data input and output functions\n savefit:   f/end for user savefit.\n readdata:  f/end for readdata\n savedata:  f/end for savedata\n recondat:  reconnect data to fit\n */\n\nvoid savefit(v,mode)\nvari *v;\nchar *mode;\n{ INT j, fp;\n    char *filename;\n    filename = getargval(v,\"file\",1);\n    if (filename==NULL)\n    { ERROR((\"savefit: no filename\"));\n        return;\n    }\n    j = getarg(v,\"fp\",1);\n    fp = (j>0) ? getlogic(v,j) : 0;\n    dosavefit(&lf,filename,mode,fp);\n    if (mode[0]=='r') endfit();\n}\n\nvoid readdata(v)\nvari *v;\n{ INT i, fp;\n    i = getarg(v,\"data\",1);\n    if (i==0) i = getarg(v,\"file\",1);\n    if (i==0) { ERROR((\"readdata: no file name\")); return; }\n    fp = getarg(v,\"fp\",1);\n    fp = (fp>0) ? getlogic(v,fp) : 0;\n    doreaddata(argval(v,i),fp);\n}\n\nvoid savedata(v)\nvari *v;\n{ INT fp;\n    if (argarg(v,0)==NULL) { ERROR((\"savedata: no file name\")); return; }\n    fp = getarg(v,\"fp\",0);\n    fp = (fp>0) ? getlogic(v,fp) : 0;\n    dosavedata(v,fp);\n}\n\nvoid recondat(xonly,n)\nINT xonly, *n;\n{ INT i;\n    *n = -1;\n    for (i=0; i<lf.mi[MDIM]; i++) dvari(&lf,i) = vdptr(findvar(lf.xname[i],1,n));\n    if (lf_error | xonly) return;\n    lf.y = vdptr(findvar(lf.yname,1,n));\n    lf.c = vdptr(findvar(lf.cname,1,n));\n    lf.w = vdptr(findvar(lf.wname,1,n));\n    lf.base=vdptr(findvar(lf.bname,1,n));\n}\n\n/*\n INDEX  Call fitting functions e.t.c.\n ckap():       compute SCB constants.\n crband():     regression bandwidths\n ckdeb():      kde bandwidths\n */\n\nvoid ckap(v)\nvari *v;\n{ INT i, nd;\n    nd = 0;\n    if (v->n==1) /* compute for existing fit */\n    { if (nofit()) { ERROR((\"ckap: no fit, no arguments\")); }\n    else recondat(0,&lf.mi[MN]);\n    }\n    else      /* new fit specification */\n        fitoptions(&lf,v,0);\n    if (lf_error) return;\n    lf.nk = constants(&des,&lf,lf.kap);\n    if (lf_error) { lf.nk=0; return; }\n    printf(\"kappa0:\");\n    for (i=0; i<lf.nk; i++) printf(\" %8.5f\",lf.kap[i]);\n    printf(\"\\n\");\n}\n\nvoid crband(v)\nvari *v;\n{ double h[4];\n    INT i, kk, meth[4], nm;\n    meth[0] = 1; meth[1] = 2; meth[2] = 3; meth[3] = 4;\n    nm = 4;\n    fitoptions(&lf,v,0);\n    lf.mi[MDEG0] = lf.mi[MDEG]; lf.mi[MDEG] = 4;\n    rband(&des,&lf,h,meth,&nm,&kk);\n    for (i=0; i<nm; i++)\n        printf(\"%8.5f \",h[i]);\n    printf(\"\\n\");\n    return;\n}\n\nvoid ckdeb(v)\nvari *v;\n{ INT i, mm[6], nm, n;\n    double *x, band[6], h0, h1;\n    char meth[6][5];\n    strcpy(meth[0],\"AIC\");  strcpy(meth[1],\"LCV\");\n    strcpy(meth[2],\"LSCV\"); strcpy(meth[3],\"BCV\");\n    strcpy(meth[4],\"SJPI\"); strcpy(meth[5],\"GKK\");\n    n = -1;\n    i = getarg(v,\"x\",1);\n    x = vdptr(findvar(argval(v,i),1,&n));\n    if (lf_error) return;\n    h0 = 0.02; h1 = 1.0;\n    i = getarg(v,\"h0\",1); if (i>0) h0 = darith(argval(v,i));\n    i = getarg(v,\"h1\",1); if (i>0) h1 = darith(argval(v,i));\n    \n    deschk(des,n,1);\n    mm[0]=1; mm[1]=2; mm[2]=3; mm[3]=4; mm[4]=5; mm[5]=6; nm=6;\n    kdeselect(band,x,des.ind,h0,h1,mm,nm,WGAUS,n);\n    for (i=0; i<nm; i++)\n        printf(\"%s: %8.6f \",meth[mm[i]-1],band[i]);\n    printf(\"\\n\");\n}\n\n/*\n INDEX post-fitting functions\n docrit():    compute c for scb's.\n crit():      f/end to docrit();\n backtr():    back transform theta in likelihood models.\n predict():   interpolate the fit.\n printdata(): print the current dataset.\n printfit():  print the current fit.\n summdata():  summarize current dataset.\n summfit():   summarize current fit.\n */\n\ndouble docrit(v)\nvari *v;\n{ double df, al;\n    INT i;\n    df = 0; al = 0.05;\n    i = getarg(v,\"df\",1); if (i>0) sscanf(argval(v,i),\"%lf\",&df);\n    i = getarg(v,\"al\",1); if (i>0) sscanf(argval(v,i),\"%lf\",&al);\n    return(critval(lf.kap,lf.nk,lf.mi[MDIM],al,10,2,df));\n}\n\nvoid crit(v)\nvari *v;\n{ vari *vr;\n    vr = createvar(\"crit\",STHIDDEN,1,VDOUBLE);\n    if (lf_error) return;\n    vassn(vr,0,docrit(v));\n    saveresult(vr,argarg(v,0),STREGULAR);\n}\n\ndouble backtr(th,mi,nd)\ndouble th;\nINT *mi, nd;\n{ if (nd>0) return(th);\n    return(invlink(th,mi[MLINK]));\n}\n\nvoid predict(vc)\nvari *vc;\n{ \n    double *data[MXDIM];\n    varname vn;\n    INT i, k, j, gr, n, z, mg[MXDIM];\n    memset(mg, 0, sizeof(mg));\n    dosavefit(&lf,getargval(vc,\"fit\",0),\"rb\",(INT)0);\n    if (nofit()) ERROR((\"predict: no fit to interpolate\\n\"));\n    if (lf_error)  return;\n    \n    gr=0;\n    i = getarg(vc,\"grid\",0);\n    if (i>0) gr = getlogic(vc,i);\n    \n    i = getarg(vc,\"where\",0);\n    if (i>0) n = setpppoints(&pp,argval(vc,i),NULL,lf.fl);\n    else\n    { \n        for (j=0; j<lf.mi[MDIM]; j++)\n        { i = getarg(vc,lf.xname[j],1);\n            if (i==0)\n            { \n                ERROR((\"predict: missing variables\"));\n                return;\n            }\n            if (gr) n = 0;\n            sprintf(vn,\"_pred%d\",j);\n            pp.data[j] = varith(argval(vc,i),vn,STPLOTVAR);\n            if (lf_error) return;\n            if (gr) mg[j] = pp.data[j]->n;\n        }\n        n = pp.data[0]->n;\n        pp.gr = 1+gr;\n    }\n    \n    for (j=0; j<lf.mi[MDIM]; j++) data[j] = vdptr(pp.data[j]);\n    pp.d = lf.mi[MDIM];\n    \n    switch(pp.gr)\n    { case 1:\n            n = pp.data[0]->n;\n            break;\n        case 2:\n            n = 1;\n            for (i=0; i<lf.mi[MDIM]; i++)\n            {\n                mg[i] = pp.data[i]->n;\n                n *= mg[i];\n            }\n            break;\n        case 3:\n            n = lf.mi[MN];\n            break;\n        case 4:\n            n = lf.nv;\n            break;\n        default:\n            ERROR((\"cpreplot where problem\"));\n    }\n    \n    if (argarg(vc,0)==NULL)\n        pp.fit = createvar(\"predict\",STHIDDEN,n,VDOUBLE);\n    else\n        pp.fit = createvar(argarg(vc,0),STREGULAR,n,VDOUBLE);\n    if (lf_error) return;\n    pp.se = NULL;\n    cpreplot(&pp,vc,'n');\n    if (lf_error) return;\n    for (j=0; j<n; j++)\n        if (vitem(pp.fit,j)!=NOSLN)\n            vassn(pp.fit,j,backtr(vitem(pp.fit,j),lf.mi,lf.nd));\n    if (argarg(vc,0)!=NULL) return;\n    for (j=0; j<n; j++)\n    { for (i=0; i<lf.mi[MDIM]; i++)\n    { z = j;\n        if (pp.gr==2)\n        { for (k=0; k<i; k++) z /= mg[k];\n            z = z%mg[i];\n        }\n        //printf(\"%10.6f \",data[i][z]);\n    }\n        if (vitem(pp.fit,j)==NOSLN) printf(\"   Not computed\\n\");\n        else printf(\"   %10.6f\\n\",vitem(pp.fit,j));\n    }\n    deletevar(pp.fit);\n}\n\nvoid printfit(v)\nvari *v;\n{ INT d, i = 0, j, k, cs, ck, nk, wh[MAXK];\n    double rs, alp, c = 0, fh;\n    cs = ck = nk = 0; rs = 1.0;\n    \n    dosavefit(&lf,getargval(v,\"fit\",i),\"rb\",(INT)0);\n    for (i=1; i<v->n; i++) if (!argused(v,i))\n    { if (argvalis(v,i,\"x\"))     { setused(v,i); wh[nk++]=1; }\n        if (argvalis(v,i,\"fhat\"))  { setused(v,i); wh[nk++]=2; }\n        if (argvalis(v,i,\"coef\"))  { setused(v,i); wh[nk++]=2; }\n        if (argvalis(v,i,\"nlx\"))   { setused(v,i); wh[nk++]=3; }\n        if (argvalis(v,i,\"infl\"))  { setused(v,i); wh[nk++]=4; }\n        if (argvalis(v,i,\"se\"))    { setused(v,i); wh[nk++]=5; cs=1; }\n        if (argvalis(v,i,\"cband\")) { setused(v,i); wh[nk++]=7; cs=ck=1; }\n        if (argvalis(v,i,\"h\"))     { setused(v,i); wh[nk++]=8; }\n        if (argvalis(v,i,\"deg\"))   { setused(v,i); wh[nk++]=9; }\n    }\n    if (nk==0) /* default: x and fhat */\n    { wh[nk++] = 1; wh[nk++] = 2;\n    }\n    d = lf.mi[MDIM];\n    alp = 0.95;\n    \n    if (cs) rs = sqrt(lf.dp[DRV]);\n    if (ck)\n    { c = critval(lf.kap,lf.nk,lf.mi[MDIM],1-alp,10,2,0.0);\n        printf(\"using c = %8.5f\\n\",c);\n    }\n    \n    for (i=0; i<lf.nv; i++) if (!lf.s[i])\n    { fh = lf.coef[i]+addparcomp(&lf,evpt(&lf,i),PCOEF);\n        for (j=0; j<nk; j++) switch(wh[j])\n        { case 1:\n                for (k=0; k<d; k++)\n                    printf(\"%8.5f \",evptx(&lf,i,k));\n                break;\n            case 2: printf(\" %12.6f \",backtr(fh,lf.mi,0)); break;\n            case 3: printf(\" %12.6f \",lf.nlx[i]); break;\n            case 4: printf(\" %12.6f \",lf.t0[i]); break;\n            case 5: printf(\" %12.6f \",rs*lf.nlx[i]); break;\n            case 7: printf(\" (%12.6f,%12.6f) \",fh-c*rs*lf.nlx[i],fh+c*rs*lf.nlx[i]);\n                break;\n            case 8: printf(\" %12.6f \",lf.h[i]); break;\n            case 9: printf(\" %6.4f \",lf.deg[i]); break;\n            default: ERROR((\"prfit: what??\"));\n        }\n        printf(\"\\n\");\n    }\n}\n\nvari *knotsvar(name,n)\nvarname *name;\nINT n;\n{ vari *v;\n    v = createvar(\"=knotv\",STHIDDEN,n,VDOUBLE);\n    if (lf_error) return(NULL);\n    if (name!=NULL) v = saveresult(v,name,STREGULAR);\n    return(v);\n}\n\nvoid knots(v)\nvari *v;\n{ INT i, j, k, n;\n    vari *vr;\n    if (nofit()) { ERROR((\"knots: no fit\")); return; }\n    n = lf.nv; /* should delete pseudo vertices */\n    for (k=0; k<v->n; k++)\n    { vr = NULL;\n        for (j=0; j<lf.mi[MDIM]; j++)\n            if (argvalis(v,k,lf.xname[j]))\n            { vr = knotsvar(argarg(v,k),n);\n                for (i=0; i<n; i++) vassn(vr,i,evptx(&lf,i,j));\n                setused(v,k);\n            }\n        if (argvalis(v,k,\"fit\")|argvalis(v,k,\"coef\"))\n        { vr = knotsvar(argarg(v,k),n);\n            for (i=0; i<n; i++) vassn(vr,i,backtr(lf.coef[i],lf.mi,0));\n            setused(v,k);\n        }\n        if (argvalis(v,k,\"h\")|argvalis(v,k,\"band\"))\n        { vr = knotsvar(argarg(v,k),n);\n            for (i=0; i<lf.nv; i++) vassn(vr,i,lf.h[i]);\n            setused(v,k);\n        }\n        if (argvalis(v,k,\"deg\"))\n        { vr = knotsvar(argarg(v,k),n);\n            for (i=0; i<lf.nv; i++) vassn(vr,i,lf.deg[i]);\n            setused(v,k);\n        }\n        ((carg *)viptr(v,k))->result = vr;\n    }\n}\n\nvoid summfit(v)\nvari *v;\n{ int i;\n    dosavefit(&lf,getargval(v,\"fit\",1),\"rb\",0);\n    printf(\"Response variable: %s\\n\",lf.yname);\n    printf(\"Predictor variables: \");\n    for (i=0; i<lf.mi[MDIM]; i++) printf(\"%s \",lf.xname[i]);\n    printf(\"\\nDegree of fit: %d\\n\",lf.mi[MDEG]);\n    printf(\"Smoothing parameters: NN %f  fix %f  pen %f\\n\",\n           lf.dp[DALP],lf.dp[DFXH],lf.dp[DADP]);\n    printf(\"Fitting Family: \");\n    switch(lf.mi[MTG]&63)\n    { case TDEN: printf(\"Density Estimation\\n\"); break;\n        case TRAT: printf(\"Poisson Process Rate Estimation\\n\"); break;\n        case THAZ: printf(\"Hazard Rate Estimation\\n\"); break;\n        case TGAUS:printf(\"Local Regression\\n\"); break;\n        case TLOGT:printf(\"Binomial\\n\"); break;\n        case TPOIS:printf(\"Poisson\\n\"); break;\n        case TGAMM:printf(\"Exponential/Gamma\\n\"); break;\n        case TGEOM:printf(\"Geometric/Negative Binomial\\n\"); break;\n        case TCIRC:printf(\"Circular - Von Mises\\n\"); break;\n    }\n    printf(\"Fitted Degrees of Freedom: %8.5f\\n\",lf.dp[DT0]);\n    printf(\"Number of fit points: %d\\n\",lf.nv);\n    printf(\"Evaluation structure: \");\n    switch(lf.mi[MEV])\n    { case ENULL: printf(\"None\\n\"); break;\n        case ETREE: printf(\"Rectangular tree\\n\"); break;\n        case EPHULL:printf(\"Triangulation\\n\"); break;\n        case EDATA: printf(\"Data\\n\"); break;\n        case EGRID: printf(\"Grid\\n\"); break;\n        case EKDTR: printf(\"K-d Tree\\n\"); break;\n        case EKDCE: printf(\"K-d Tree (centers)\\n\"); break;\n        case ECROS: printf(\"Data, Cross-Validation\\n\"); break;\n        case EPRES: printf(\"User-provided\\n\"); break;\n        default:    printf(\"Unknown\\n\");\n    }\n}\n\nvoid AC(name,r,g,b,p)\nchar *name;\nINT r, g, b, p;\n{ devwin.AddColor(name,r,g,b,p);\n    devps.AddColor(name,r,g,b,p);\n}\n\nINT getcolidx(cname, def)\nchar *cname;\nint def;\n{ int i;\n    if (cname==NULL) return(def);\n    for (i=0; i<8; i++)\n        if (strcmp(cname,mycol[i].name)==0) return(i);\n    WARN((\"color %s not found\",cname));\n    return(def);\n}\n\nvoid greyscale(v)\nvari *v;\n{ INT i, j0, j1;\n    j0 = getcolidx(getargval(v,\"lo\",1),0);\n    j1 = getcolidx(getargval(v,\"hi\",1),1);\n    for (i=0; i<=10; i++)\n        AC(\"\",((10-i)*mycol[j0].r+i*mycol[j1].r)/11,\n           ((10-i)*mycol[j0].g+i*mycol[j1].g)/11,\n           ((10-i)*mycol[j0].b+i*mycol[j1].b)/11,8+i);\n}\n\nvoid setcolor(v)\nvari *v;\n{\n    return;\n//   int i;\n//    lfcm[CBAK] = getcolidx(getargval(v,\"back\",0),lfcm[CBAK]);\n//    \n//    i = getarg(v,\"fore\",1);\n//    if (i>0)\n//    { lfcm[CAXI] = getcolidx(argval(v,i));\n//        for (i=CTEX; i<CPA2; i++) lfcm[i] = lfcm[CAXI];\n//    }\n//    \n//    lfcm[CAXI] = getcolidx(getargval(v,\"axis\",0),lfcm[CAXI]);\n//    lfcm[CTEX] = getcolidx(getargval(v,\"text\",0),lfcm[CTEX]);\n//    lfcm[CLIN] = getcolidx(getargval(v,\"lines\",0),lfcm[CLIN]);\n//    lfcm[CPOI] = getcolidx(getargval(v,\"points\",0),lfcm[CPOI]);\n//    lfcm[CCON] = getcolidx(getargval(v,\"cont\",0),lfcm[CCON]);\n//    lfcm[CCLA] = getcolidx(getargval(v,\"clab\",0),lfcm[CCLA]);\n//    lfcm[CSEG] = getcolidx(getargval(v,\"cseg\",0),lfcm[CSEG]);\n//    lfcm[CPA1] = getcolidx(getargval(v,\"patch1\",0),lfcm[CPA1]);\n//    lfcm[CPA2] = getcolidx(getargval(v,\"patch2\",0),lfcm[CPA2]);\n//    if (lfcm[CAXI]==lfcm[0]) WARN((\"axis color = background color\"));\n//    if (lfcm[CTEX]==lfcm[0]) WARN((\"text color = background color\"));\n//    if (lfcm[CLIN]==lfcm[0]) WARN((\"lines color = background color\"));\n//    if (lfcm[CPOI]==lfcm[0]) WARN((\"points color = background color\"));\n//    if (lfcm[CCON]==lfcm[0]) WARN((\"cont color = background color\"));\n//    if (lfcm[CCLA]==lfcm[0]) WARN((\"clab color = background color\"));\n//    if (lfcm[CSEG]==lfcm[0]) WARN((\"cseg color = background color\"));\n//    if (lfcm[CPA1]==lfcm[0]) WARN((\"patch1 color = background color\"));\n//    if (lfcm[CPA2]==lfcm[0]) WARN((\"patch2 color = background color\"));\n//    if (lfcm[CPA1]==lfcm[CPA2]) WARN((\"patch1 color = patch2 color\"));\n}\n\nvoid table(v)\nvari *v;\n{ INT i = 0, j = 0, ix, iy, m, mx, my, n, nx[15], ny[15], count[100];\n    double xl[2], yl[2], xs[15], ys[15], *x, *y;\n    i = getarg(v,\"x\",1);\n    if (i==0)\n    { ERROR((\"table: no x variable\"));\n        return;\n    }\n    n = -1;\n    x = vdptr(findvar(argval(v,i),1,&n));\n    xl[0] = xl[1] = x[0];\n    for (i=1; i<n; i++)\n    { if (x[i]<xl[0]) xl[0] = x[i];\n        if (x[i]>xl[1]) xl[1] = x[i];\n    }\n    i = getarg(v,\"m\",0);\n    if (i>0) sscanf(argval(v,i),\"%d\",&m); else m = 5;\n    mx = pretty(xl,m,xs);\n    if (lf_error) return;\n    \n    i = getarg(v,\"y\",1);\n    if (i>0)\n    { y = vdptr(findvar(argval(v,i),1,&n));\n        yl[0] = yl[1] = y[0];\n        for (i=1; i<n; i++)\n        { if (y[i]<yl[0]) yl[0] = y[i];\n            if (y[i]>yl[1]) yl[1] = y[i];\n        }\n        my = pretty(yl,m,ys);\n    }\n    else { y = NULL; my = 0; }\n    if (lf_error) return;\n    \n    for (i=0; i<15; i++) nx[i] = ny[i] = 0;\n    for (i=0; i<=(mx+1)*(my+1); i++) count[i] = 0;\n    for (i=0; i<n; i++)\n    { if (x[i]<xs[0]) ix = 0;\n        if (x[i]>=xs[mx-1]) ix = mx;\n        if ((x[i]>=xs[0]) & (x[i]<xs[mx-1]))\n            for (j=1; j<mx; j++)\n                if ((x[i]>=xs[j-1]) & (x[i]<xs[j])) ix = j;\n        if (my>0)\n        { if (y[i]<ys[0]) iy = 0;\n            if (y[i]>=ys[my-1]) iy = my;\n            if ((y[i]>=ys[0]) & (y[i]<ys[my-1]))\n                for (j=1; j<my; j++)\n                    if ((y[i]>=ys[j-1]) & (y[i]<ys[j])) iy = j;\n        } else iy = 0;\n        nx[ix] = ny[iy] = 1;\n        count[ix*(my+1)+iy]++;\n    }\n    if (my>0) printf(\"          \");\n    for (i=0; i<=mx; i++) if (nx[i]>0)\n        printf(\"  %4g-\",(i==0) ? xl[0] : xs[i-1]);\n    printf(\"\\n\");\n    if (my>0) printf(\"          \");\n    for (i=0; i<=mx; i++) if (nx[i]>0)\n        printf(\"  %4g \",(i==mx) ? xl[1] : xs[i]);\n    printf(\"\\n\\n\");\n    for (j=0; j<=my; j++) if (ny[j]>0)\n    { if (my>0)\n        printf(\"%4g-%4g \",(j==0) ? yl[0] : ys[j-1],\n               (j==my) ? yl[1] : ys[j]);\n        for (i=0; i<=mx; i++)\n            if (nx[i]>0) printf(\"%6d \",count[i*(my+1)+j]);\n        printf(\"\\n\");\n    }\n}\n\n/*\n INDEX control functions:\n setout(): set output file.\n cmdint(): send off the command...\n locfit_dispatch(): called by the main program.\n */\n\nvoid setout(v)\nvari *v;\n{ INT i, i0;\n    char md;\n    i0 = getarg(v,\"file\",1);\n    if (i0==0)\n    { if (ofile!=NULL) fclose(ofile);\n        ofile = NULL;\n        printf(\"Output set to stdout\\n\");\n        return;\n    }\n    \n    md = 'w';\n    i = getarg(v,\"mode\",1);\n    if ((i>0) && (argval(v,i)[0]=='a')) md = 'a';\n    \n    setfilename(argval(v,i0),\"\",&md,0);\n    if (ofile != NULL) fclose(ofile);\n    ofile = fopen(filename,&md);\n    if (ofile == NULL)\n        ERROR((\"setout: can't open %s for writing\",filename));\n    else\n        printf(\"Output set to file %s\\n\",filename);\n}\n\nvoid dosleep(v)\nvari *v;\n{ INT i;\n    i = getarg(v,\"time\",1);\n    if (i==0) return;\n    sscanf(argval(v,i),\"%d\",&i);\n    (void)sleep(i);\n}\n\nvoid setdef(v)\nvari *v;\n{ INT i, n;\n    carg *ca;\n    vari *vd;\n    \n    if (argarg(v,0)==NULL)\n    { ERROR((\"Unnamed Defintion\"));\n        return;\n    }\n    n = vlength(v)-1;\n    vd = createvar(argarg(v,0),STSYSTEM,n,VARGL);\n    if (lf_error) return;\n    \n    for (i=0; i<n; i++)\n    { ca = (carg *)viptr(vd,i);\n        ca->arg = argarg(v,i+1);\n        ca->val = argval(v,i+1);\n        setused(v,i+1);\n    }\n    sprintf(curstr->name,\"=%s\",argarg(v,0));\n}\n\nextern void cscbsim();\n\nvoid dcmdint(v)\nvari *v;\n{ INT i;\n    if (v==NULL)\n    { ERROR((\"dcmdint received NULL\"));\n        return;\n    }\n    if (argvalis(v,0,\"band\"))  { band(v); return; }\n    if (argvalis(v,0,\"crit\"))  { crit(v); return; }\n    if (argvalis(v,0,\"def\"))   { setdef(v); return; }\n    if (argvalis(v,0,\"endfor\")) { dec_forvar(); return; }\n    if (argvalis(v,0,\"for\"))    { inc_forvar(); return; }\n    if (argvalis(v,0,\"example\")){example(v); return; }\n    if (argvalis(v,0,\"help\"))   {example(v); return; }\n    if (argvalis(v,0,\"?\"))      {example(v); return; }\n    if (argvalis(v,0,\"exit\")) exit(0);\n    if (argvalis(v,0,\"quit\")) exit(0);\n    if (argvalis(v,0,\"q()\"))  exit(0);\n    if (argvalis(v,0,\"fitted\")){ cfitted(v,RMEAN); return; }\n    if (argvalis(v,0,\"greyscale\"))   { greyscale(v); return; }\n    if (argvalis(v,0,\"kappa\")) { ckap(v); return; }\n    if (argvalis(v,0,\"kdeb\"))  { ckdeb(v); return; }\n    if (argvalis(v,0,\"knots\")) { knots(v); return; }\n    if (argvalis(v,0,\"locfit\"))   { clocfit(v,0); return; }\n    if (argvalis(v,0,\"relocfit\")) { clocfit(v,1); return; }\n    if (argvalis(v,0,\"plot\"))     { printf(\"use plotfit or plotdata\\n\"); return; }\n    if (argvalis(v,0,\"plotdata\")) { plotdata(v); return; }\n    if (argvalis(v,0,\"plotfit\"))  { plotfit(v); return; }\n    if (argvalis(v,0,\"replot\"))   { plotopt(v,1); return; }\n    if (argvalis(v,0,\"predict\"))  { predict(v); return; }\n    if (argvalis(v,0,\"prfit\"))    { printfit(v); return; }\n    if (argvalis(v,0,\"rband\"))    { crband(v); return; }\n    if (argvalis(v,0,\"readdata\")) { readdata(v); return; }\n    if (argvalis(v,0,\"readfile\")) { readfile(v); return; }\n    if (argvalis(v,0,\"readfit\"))  { savefit(v,\"rb\"); return; }\n    if (argvalis(v,0,\"residuals\")){ cfitted(v,RDEV); return; }\n    if (argvalis(v,0,\"run\"))      return;\n    if (argvalis(v,0,\"savedata\")) { savedata(v); return; }\n    if (argvalis(v,0,\"savefit\"))  { savefit(v,\"wb\"); return; }\n    if (argvalis(v,0,\"scbmax\"))   { cscbsim(v); return; }\n    if (argvalis(v,0,\"scbsim\"))   { cscbsim(v); return; }\n    if (argvalis(v,0,\"seed\"))     { rseed(argval(v,1)); setused(v,1); return; }\n    if (argvalis(v,0,\"setcolor\")) { setcolor(v); return; }\n    if (argvalis(v,0,\"setout\"))   { setout(v); return; }\n    if (argvalis(v,0,\"outf\"))     { setout(v); return; }\n    if (argvalis(v,0,\"setplot\"))  { setplot(v); return; }\n    if (argvalis(v,0,\"sleep\"))    { dosleep(v); return; }\n    if (argvalis(v,0,\"summfit\"))  { summfit(v); return; }\n    if (argvalis(v,0,\"table\"))    { table(v); return; }\n    if (argvalis(v,0,\"track\"))    { plottrack(v); return; }\n    if (argvalis(v,0,\"wdiag\"))    { cwdiag(v); return; }\n    for (i=0; i<vlength(v); i++)\n    { ((carg *)viptr(v,i))->result = varith(argval(v,i),argarg(v,i),STREGULAR);\n        setused(v,i);\n        if (lf_error) return;\n    }\n}\n\nvoid cmdint(v)\nvari *v;\n{ vari *vv, *vr;\n    INT i, j, mn, nr;\n    if (v==NULL) return;\n    \n    for (i=0; i<vlength(v); i++)\n    { setunused(v,i);\n        /* ((carg *)viptr(v,i))->used = 0; */\n        ((carg *)viptr(v,i))->result = NULL;\n    }\n    \n    setused(v,0);\n    if (vlength(v)==1)\n    { j = 0;\n        vv = findvar(argval(v,0),0,&j);\n        if ((vv!=NULL) && ((vv->mode==VARGL) & (!argvalis(v,0,\"=cline\"))))\n        { \n            cmdint(vv);\n            return;\n        }\n    }\n    \n    /* dcmdint processes command */\n    dcmdint(v);\n    \n    /* print the results of unassigned expression.\n     * First, determine mn = maximum number of rows in the\n     * output. Note that vr->stat==STHIDDEN determines whether\n     * the result was unassigned.\n     */\n    mn = 0; nr = 0;\n    for (i=0; i<vlength(v); i++)\n    { vr = ((carg *)viptr(v,i))->result;\n        if ((vr != NULL) && (vr->stat==STHIDDEN))\n            switch(vr->mode)\n        { case VCHAR: if (mn<1) mn = 1;\n                break;\n            case VINT:\n            case VDOUBLE: if (mn<vr->n) mn = vr->n;\n                break;\n        }\n    }\n    \n    /* now, print the unassigned variables.\n     \n     for (i=0; i<mn; i++)\n     { for (j=0; j<vlength(v); j++)\n     { vr = ((carg *)viptr(v,j))->result;\n     if ((vr != NULL) && (vr->stat==STHIDDEN))\n     switch(vr->mode)\n     { case VDOUBLE: printf(\"%8.5f  \",vitem(vr,i)); break;\n     case VCHAR:   printf(\"%s  \",vdptr(vr)); break;\n     case VINT:    printf(\"%4d  \", vitem(vr,i)); break;\n     }\n     }\n     printf(\"\\n\");\n     }\n     */\n    \n    for (i=0; i<vlength(v); i++)\n        deleteifhidden(((carg *)viptr(v,i))->result);\n}\n\nINT locfit_dispatch(char *z)\n\n{ vari *v;\n    \n    makecmd(z);\n    while (1)\n    { lf_error = 0;\n        v = getcmd();\n        if (v==NULL)\n        { del_lines();\n            return(0);\n        }\n        cmdint(v);\n    }\n}\n\nvoid setuplf()\n{ INT i;\n    char command[100];\n    vari *v;\n    \n    lfhome = getenv(\"LFHOME\");\n    initdb();\n    \n    ofile = NULL;\n    lf.tw = lf.xxev = lf.L = lf.iw = des.dw = lf.pc.wk = NULL;\n    des.index = NULL;\n    lf.mg = calloc(MXDIM,sizeof(INT));\n    \n    v = createvar(\"mi\",STSYSPEC,LENM,VINT); v->dpr = (double *)lf.mi;\n    v = createvar(\"dp\",STSYSPEC,LEND,VDOUBLE); v->dpr = lf.dp;\n    v = createvar(\"alpha\",STSYSPEC,1,VDOUBLE); v->dpr = &lf.dp[DALP];\n    v = createvar(\"h\",    STSYSPEC,1,VDOUBLE); v->dpr = &lf.dp[DFXH];\n    v = createvar(\"pen\",  STSYSPEC,1,VDOUBLE); v->dpr = &lf.dp[DADP];\n    v = createvar(\"infl\", STSYSPEC,1,VDOUBLE); v->dpr = &lf.dp[DT0];\n    v = createvar(\"vari\", STSYSPEC,1,VDOUBLE); v->dpr = &lf.dp[DT1];\n    v = createvar(\"like\", STSYSPEC,1,VDOUBLE); v->dpr = &lf.dp[DLK];\n    v = createvar(\"resv\", STSYSPEC,1,VDOUBLE); v->dpr = &lf.dp[DRV];\n    \n    for (i=0; i<MAXWIN; i++)\n    { pl[i].xyzs = NULL;\n        pl[i].id = i;\n        pl[i].ty = PLNONE;\n        pl[i].track = NULL;\n    }\n    //SetWinDev(&devwin);\n    //SetPSDev(&devps);\n    //  AC(\"white\",255,255,255,0);\n    //  AC(\"black\",  0,  0,  0,1);\n    //  AC(  \"red\",255,  0,  0,2);\n    //  AC(\"green\",  0,255,  0,3);\n    //  AC( \"blue\",  0,  0,255,4);\n    //  AC(\"magenta\",255,0,255,5);\n    //  AC(\"yellow\",255,255, 0,6);\n    //  AC( \"cyan\",  0,255,255,7);\n    lfcm[0] = 0;\n    for (i=CAXI; i<=CPA1; i++) lfcm[i] = 1;\n    lfcm[CPA2] = 2;\n    rseed(\"LocalFit\");\n    if (setfilename(\"LFInit\",\"cmd\",\"r\",0))\n    { sprintf(command,\"run %s\",filename);\n        locfit_dispatch(command);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "src/locfit/dens_haz.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *\n *   Integration for hazard rate estimation. The functions in this\n *   file are used to evaluate\n *      sum int_0^{Ti} W_i(t,x) A()A()' exp( P() ) dt\n *   for hazard rate models.\n *\n *   These routines assume the weight function is supported on [-1,1].\n *   hasint_sph multiplies by exp(base(lf,i)), which allows estimating\n *   the baseline in a proportional hazards model, when the covariate\n *   effect base(lf,i) is known.\n *\n *   TODO:\n *     hazint_sph, should be able to reduce mint in some cases with\n *       small integration range. onedint could be used for beta-family\n *       (RECT,EPAN,BISQ,TRWT) kernels.\n *     hazint_prod, restrict terms from the sum based on x values.\n *       I should count obs >= max, and only do that integration once.\n */\n\n#include \"local.h\"\n\nstatic double ilim[2*MXDIM], *ff, tmax;\n\n/*\n *  hrao returns 0 if integration region is empty.\n *               1 otherwise.\n */\nINT haz_sph_int(lf,dfx,cf,h,r1)\nlfit *lf;\ndouble *dfx, *cf, h, *r1;\n{ double s, t0, t1, wt, th;\n  INT dim, j, p, *mi;\n  mi = lf->mi;\n  s = 0; p = mi[MP];\n  dim = mi[MDIM];\n  for (j=1; j<dim; j++) s += SQR(dfx[j]/(h*lf->sca[j]));\n  if (s>1) return(0);\n\n  setzero(r1,p*p);\n  t1 = sqrt(1-s)*h*lf->sca[0];\n  t0 = -t1;\n  if (t0<ilim[0])   t0 = ilim[0];\n  if (t1>ilim[dim]) t1 = ilim[dim];\n  if (t1>dfx[0]) t1 = dfx[0];\n  if (t1<t0) return(0);\n\n/*  Numerical integration by Simpson's rule.\n */\n  for (j=0; j<=mi[MMINT]; j++)\n  { dfx[0] = t0+(t1-t0)*j/mi[MMINT];\n    wt = weight(lf,dfx,NULL,h,0,0.0);\n    fitfun(lf,dfx,NULL,ff,NULL,0);\n    th = innerprod(cf,ff,p);\n    if (mi[MLINK]==LLOG) th = exp(th);\n    wt *= 2+2*(j&1)-(j==0)-(j==mi[MMINT]);\n    addouter(r1,ff,ff,p,wt*th);\n  }\n  multmatscal(r1,(t1-t0)/(3*mi[MMINT]),p*p);\n\n  return(1);\n}\n\nINT hazint_sph(t,resp,r1,lf,cf,h)\nlfit *lf;\ndouble *t, *resp, *r1, *cf, h;\n{ INT i, j, p, st;\n  double dfx[MXDIM], eb, sb;\n  p = lf->mi[MP];\n  setzero(resp,p*p);\n  sb = 0.0;\n\n  for (i=0; i<=lf->mi[MN]; i++)\n  {\n    if (i==lf->mi[MN])\n    { dfx[0] = tmax-t[0];\n      for (j=1; j<lf->mi[MDIM]; j++) dfx[j] = 0.0;\n      eb = exp(sb/lf->mi[MN]);\n    }\n    else\n    { eb = exp(base(lf,i)); sb += base(lf,i);\n      for (j=0; j<lf->mi[MDIM]; j++) dfx[j] = datum(lf,j,i)-t[j];\n    }\n\n    st = haz_sph_int(lf,dfx,cf,h,r1);\n    if (st)\n      for (j=0; j<p*p; j++) resp[j] += eb*r1[j];\n  }\n  return(LF_OK);\n}\n\nINT hazint_prod(t,resp,x,lf,cf,h)\nlfit *lf;\ndouble *t, *resp, *x, *cf, h;\n{ INT d, p, deg, i, j, k, st;\n  double dfx[MXDIM], t_prev,\n         hj, hs, ncf[MXDEG], ef, il1;\n  double prod_wk[MXDIM][2*MXDEG+1], eb, sb;\n\n  p = lf->mi[MP]; d = lf->mi[MDIM];\n  deg = lf->mi[MDEG];\n  setzero(resp,p*p);\n  hj = hs = h*lf->sca[0];\n    memset(dfx, 0.0, sizeof(dfx));\n  ncf[0] = cf[0];\n  for (i=1; i<=deg; i++)\n  { ncf[i] = hj*cf[(i-1)*d+1]; hj *= hs;\n  }\n\n/*   for i=0..n....\n *     First we compute prod_wk[j], j=0..d.\n *     For j=0, this is int_0^T_i (u-t)^k W((u-t)/h) exp(b0*(u-t)) du\n *     For remaining j,   (x(i,j)-x(j))^k Wj exp(bj*(x..-x.))\n *\n *     Second, we add to the integration (exp(a) incl. in integral)\n *     with the right factorial denominators.\n */\n  t_prev = ilim[0]; sb = 0.0;\n  for (i=0; i<=lf->mi[MN]; i++)\n  { if (i==lf->mi[MN])\n    { dfx[0] = tmax-t[0];\n      for (j=1; j<d; j++) dfx[j] = 0.0;\n      eb = exp(sb/lf->mi[MN]);\n    }\n    else\n    { eb = exp(base(lf,i)); sb += base(lf,i);\n      for (j=0; j<d; j++) dfx[j] = datum(lf,j,i)-t[j];\n    }\n\n    if (dfx[0]>ilim[0]) /* else it doesn't contribute */\n    {\n/* time integral */\n      il1 = (dfx[0]>ilim[d]) ? ilim[d] : dfx[0];\n      if (il1 != t_prev) /* don't repeat! */\n      { st = onedint(ncf,lf->mi,ilim[0]/hs,il1/hs,prod_wk[0]);\n        if (st>0) return(st);\n        hj = eb;\n        for (j=0; j<=2*deg; j++)\n        { hj *= hs;\n          prod_wk[0][j] *= hj;\n        }\n        t_prev = il1;\n      }\n\n/* covariate terms */\n      for (j=1; j<d; j++)\n      {\n        ef = 0.0;\n        for (k=deg; k>0; k--) ef = (ef+dfx[j])*cf[1+(k-1)*d+j];\n        ef = exp(ef);\n        prod_wk[j][0] = ef * W(dfx[j]/(h*lf->sca[j]),lf->mi[MKER]);\n        for (k=1; k<=2*deg; k++)\n          prod_wk[j][k] = prod_wk[j][k-1] * dfx[j];\n      }\n\n/*  add to the integration.  */\n      prodint_resp(resp,prod_wk,d,deg,p);\n    } /* if dfx0 > ilim0 */\n  } /* n loop */\n\n/* symmetrize */\n  for (k=0; k<p; k++)\n    for (j=k; j<p; j++)\n      resp[j*p+k] = resp[k*p+j];\n  return(LF_OK);\n}\n\nINT hazint(t,resp,resp1,lf,cf,h)\nlfit *lf;\ndouble *t, *resp, *resp1, *cf, h;\n{ if (lf->mi[MDIM]==1) return(hazint_prod(t,resp,resp1,lf,cf,h));\n  if (lf->mi[MKT]==KPROD) return(hazint_prod(t,resp,resp1,lf,cf,h));\n\n  return(hazint_sph(t,resp,resp1,lf,cf,h));\n}\n\nvoid haz_init(lf,des,il)\nlfit *lf;\ndesign *des;\ndouble *il;\n{ int i;\n  tmax = datum(lf,0,0);\n  for (i=1; i<lf->mi[MN]; i++) tmax = MAX(tmax,datum(lf,0,i));\n  ff = des->xtwx.wk;\n  for (i=0; i<2*lf->mi[MDIM]; i++) ilim[i] = il[i];\n}\n"
  },
  {
    "path": "src/locfit/dens_int.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *   The function dens_integrate(lf,des,z) is used to integrate a density\n *   estimate (z=1) or the density squared (z=2). This is used to renormalize\n *   the estimate (function dens_renorm) or in the computation of LSCV\n *   (function dnes_lscv). The implementation is presently for d=1.\n *\n *   The computation orders the fit points selected by locfit, and\n *   integrates analytically over each interval. For the log-link,\n *   the interpolant used is peicewise quadratic (with one knot in\n *   the middle of each interval); this differs from the cubic interpolant\n *   used elsewhere in Locfit.\n *\n *   TODO: allow for xlim. What can be done simply in >=2 dimensions?\n *         fix df computation (in lscv) for link=IDENT.\n */\n\n#include \"local.h\"\n\n/*\n * Finds the order of observations in the array x, and\n * stores in integer array ind.\n * At input, lset l=0 and r=length(x)-1.\n * At output, x[ind[0]] <= x[ind[1]] <= ...\n */\nvoid lforder(ind,x,l,r)\nINT *ind, l, r;\ndouble *x;\n{ double piv;\n  INT i, i0, i1;\n  piv = (x[ind[l]]+x[ind[r]])/2;\n  i0 = l; i1 = r;\n  while (i0<=i1)\n  { while ((i0<=i1) && (x[ind[i0]]<=piv)) i0++;\n    while ((i0<=i1) && (x[ind[i1]]>piv))  i1--;\n    if (i0<i1)\n    { ISWAP(ind[i0],ind[i1]);\n      i0++; i1--;\n    }\n  }\n  /* now, x[ind[l..i1]] <= piv < x[ind[i0..r]].\n     put the ties in the middle */\n  while ((i1>=l) && (x[ind[i1]]==piv)) i1--;\n  for (i=l; i<=i1; i++)\n    if (x[ind[i]]==piv)\n    { ISWAP(ind[i],ind[i1]);\n      while (x[ind[i1]]==piv) i1--;\n    }\n\n  if (l<i1) lforder(ind,x,l,i1);\n  if (i0<r) lforder(ind,x,i0,r);\n}\n\n/*\n *  estdiv integrates the density between fit points x0 and x1.\n *  f0, f1 are function values, d0, d1 are derivatives.\n */\ndouble estdiv(x0,x1,f0,f1,d0,d1,link)\ndouble x0, x1, f0, f1, d0, d1;\nINT link;\n{ double cf[4], I[2], dlt, e0, e1;\n\n  if (x0==x1) return(0.0);\n\n  if (link==LIDENT)\n  {\n/* cf are integrals of hermite polynomials.\n * Then adjust for x1-x0.\n */\n    cf[0] = cf[1] = 0.5;\n    cf[2] = 1.0/12.0; cf[3] = -cf[2];\n    return( (cf[0]*f0+cf[1]*f1)*(x1-x0)\n          + (cf[2]*d0+cf[3]*d1)*(x1-x0)*(x1-x0) );\n  }\n\n/*\n * this is for LLOG\n */\n\n  dlt = (x1-x0)/2;\n  cf[0] = f0;\n  cf[1] = d0;\n  cf[2] = ( 2*(f1-f0) - dlt*(d1+3*d0) )/(4*dlt*dlt);\n  recurint(0.0,dlt,cf,I,0,WRECT);\n  e0 = I[0];\n\n  cf[0] = f1;\n  cf[1] = -d1;\n  cf[2] = ( 2*(f0-f1) + dlt*(d0+3*d1) )/( 4*dlt*dlt );\n  recurint(0.0,dlt,cf,I,0,WRECT);\n  e1 = I[0];\n\n  return(e0+e1);\n}\n\n/*\n *   Evaluate the integral of the density estimate to the power z.\n *   This would be severely messed up, if I ever implement parcomp\n *   for densities.\n */\ndouble dens_integrate(lf,des,z)\nlfit *lf;\ndesign *des;\nINT z;\n{ INT has_deriv, i, i0, i1, link, nv, *ind;\n  double *xev, *fit, *deriv, sum, term;\n  double d0, d1, f0, f1;\n\n  if (lf->mi[MDIM]>=2)\n  { WARN((\"dens_integrate requires d=1\"));\n    return(0.0);\n  }\n\n  link = lf->mi[MLINK];\n  has_deriv = (lf->mi[MDEG] > 0); /* not right? */\n  fit = lf->coef;\n  if (has_deriv)\n    deriv = &lf->coef[lf->nvm];\n  xev = vdptr(lf->xxev);\n\n  /*\n   * order the vertices\n   */\n  nv = lf->nv;\n  if (lf->mi[MN]<nv) return(0.0);\n  ind = des->ind;\n  for (i=0; i<nv; i++) ind[i] = i;\n  lforder(ind,xev,0,nv-1);\n  sum = 0.0;\n\n  /*\n   * Estimate the contribution of the boundaries.\n   * should really check flim here.\n   */\n  i0 = ind[0]; i1 = ind[1];\n  f1 = fit[i0];\n  d1 = (has_deriv) ? deriv[i0] :\n         (fit[i1]-fit[i0])/(xev[i1]-xev[i0]);\n  if (d1 <= 0) WARN((\"dens_integrate - ouch!\"));\n  if (z==2)\n  { if (link==LLOG)\n    { f1 *= 2; d1 *= 2; }\n    else\n    { d1 = 2*d1*f1; f1 = f1*f1; }\n  }\n  term = (link==LIDENT) ? f1*f1/(2*d1) : exp(f1)/d1;\n  sum += term;\n\n  i0 = ind[nv-2]; i1 = ind[nv-1];\n  f0 = fit[i1];\n  d0 = (has_deriv) ? deriv[i1] :\n         (fit[i1]-fit[i0])/(xev[i1]-xev[i0]);\n  if (d0 >= 0) WARN((\"dens_integrate - ouch!\"));\n  if (z==2)\n  { if (link==LLOG)\n    { f0 *= 2; d0 *= 2; }\n    else\n    { d0 = 2*d0*f0; f0 = f0*f0; }\n  }\n  term = (link==LIDENT) ? -f0*f0/(2*d0) : exp(f0)/d0;\n  sum += term;\n  \n  for (i=1; i<nv; i++)\n  { i0 = ind[i-1]; i1 = ind[i];\n    f0 = fit[i0]; f1 = fit[i1];\n    d0 = (has_deriv) ? deriv[i0] :\n              (f1-f0)/(xev[i1]-xev[i0]);\n    d1 = (has_deriv) ? deriv[i1] : d0;\n    if (z==2)\n    { if (link==LLOG)\n      { f0 *= 2; f1 *= 2; d0 *= 2; d1 *= 2; }\n      else\n      { d0 *= 2*f0; d1 *= 2*f1; f0 = f0*f0; f1 = f1*f1; }\n    }\n    term = estdiv(xev[i0],xev[i1],f0,f1,d0,d1,link);\n    sum += term;\n  }\n\n  return(sum);\n}\n\nvoid dens_renorm(lf,des)\nlfit *lf;\ndesign *des;\n{ INT i;\n  double sum;\n  sum = dens_integrate(lf,des,1);\n  if (sum==0.0) return;\n  sum = log(sum);\n  for (i=0; i<lf->nv; i++) lf->coef[i] -= sum;\n}\n\nvoid dens_lscv(des,lf)\nlfit *lf;\ndesign *des;\n{ double df, fh, fh_cv, infl, z0, z1, x[MXDIM];\n  int i, n, j, ev;\n  z1 = df = 0.0;\n  ev = lf->mi[MEV];\n  n = lf->mi[MN];\n  if ((ev==EDATA) | (ev==ECROS)) ev = EFITP;\n\n  z0 = dens_integrate(lf,des,2);\n\n  for (i=0; i<n; i++)\n  { for (j=0; j<lf->mi[MDIM]; j++) x[j] = datum(lf,j,i);\n    fh = base(lf,i)+dointpoint(lf,des,x,PCOEF,ev,i);\n    if (lf->mi[MLINK]==LLOG) fh = exp(fh);\n    infl = dointpoint(lf,des,x,PT0,ev,i);\n    infl = infl * infl;\n    if (infl>1) infl = 1;\n    fh_cv = (lf->mi[MLINK] == LIDENT) ?\n       (n*fh - infl) / (n-1.0) : fh*(1-infl)*n/(n-1.0);\n    z1 += fh_cv;\n    df += infl;\n  }\n\n  vdptr(lf->L)[0] = z0-2*z1/n;\n  vdptr(lf->L)[1] = df;\n}\n"
  },
  {
    "path": "src/locfit/dens_odi.c",
    "content": "/*\n *   Copyright (c) 1996-200 Lucent Technologies.\n *   See README file for details.\n *\n *\n *\n *  Routines for one-dimensional numerical integration\n *  in density estimation. The entry point is\n *\n *  onedint(cf,mi,l0,l1,resp)\n *\n *  which evaluates int W(u)u^j exp( P(u) ), j=0..2*deg.\n *  P(u) = cf[0] + cf[1]u + cf[2]u^2/2 + ... + cf[deg]u^deg/deg!\n *  l0 and l1 are the integration limits.\n *  The results are returned through the vector resp.\n *\n */\n\n#include \"local.h\"\n\nstatic int debug;\n\nINT exbctay(b,c,n,z) /* n-term taylor series of e^(bx+cx^2) */\ndouble b, c, *z;\nINT n;\n{ double ec[20];\n  INT i, j;\n  z[0] = 1;\n  for (i=1; i<=n; i++) z[i] = z[i-1]*b/i;\n  if (c==0.0) return(n);\n  if (n>=40)\n  { WARN((\"exbctay limit to n<40\"));\n    n = 39;\n  }\n  ec[0] = 1;\n  for (i=1; 2*i<=n; i++) ec[i] = ec[i-1]*c/i;\n  for (i=n; i>1; i--)\n    for (j=1; 2*j<=i; j++)\n      z[i] += ec[j]*z[i-2*j];\n  return(n);\n}\n\ndouble explinjtay(l0,l1,j,cf)\n/* int_l0^l1 x^j e^(a+bx+cx^2); exbctay aroud l1 */\ndouble l0, l1, *cf;\nINT j;\n{ double tc[40], f, s;\n  INT k, n;\n  if ((l0!=0.0) | (l1!=1.0)) WARN((\"explinjtay: invalid l0, l1\"));\n  n = exbctay(cf[1]+2*cf[2]*l1,cf[2],20,tc);\n  s = tc[0]/(j+1);\n  f = 1/(j+1);\n  for (k=1; k<=n; k++)\n  { f *= -k/(j+k+1.0);\n    s += tc[k]*f;\n  }\n  return(f);\n}\n\nvoid explint1(l0,l1,cf,I,p) /* int x^j exp(a+bx); j=0..p-1 */\ndouble l0, l1, *cf, *I;\nINT p;\n{ double y0, y1, f;\n  INT j, k, k1;\n  y0 = lf_exp(cf[0]+l0*cf[1]);\n  y1 = lf_exp(cf[0]+l1*cf[1]);\n  if (p<2*fabs(cf[1])) k = p; else k = (INT)fabs(cf[1]);\n\n  if (k>0)\n  { I[0] = (y1-y0)/cf[1];\n    for (j=1; j<k; j++) /* forward steps for small j */\n    { y1 *= l1; y0 *= l0;\n      I[j] = (y1-y0-j*I[j-1])/cf[1];\n    }\n    if (k==p) return;\n    y1 *= l1; y0 *= l0;\n  }\n\n  f = 1; k1 = k;\n  while ((k<50) && (f>1.0e-8)) /* initially Ik = diff(x^{k+1}e^{a+bx}) */\n  { y1 *= l1; y0 *= l0;\n    I[k] = y1-y0;\n    if (k>=p) f *= fabs(cf[1])/(k+1);\n    k++;\n  }\n  if (k==50) WARN((\"explint1: want k>50\"));\n  I[k] = 0.0;\n  for (j=k-1; j>=k1; j--) /* now do back step recursion */\n    I[j] = (I[j]-cf[1]*I[j+1])/(j+1);\n}\n\nvoid explintyl(l0,l1,cf,I,p) /* small c, use taylor series and explint1 */\ndouble l0, l1, *cf, *I;\nINT p;\n{ INT i;\n  double c;\n  explint1(l0,l1,cf,I,p+8);\n  c = cf[2];\n  for (i=0; i<p; i++)\n    I[i] = (((I[i+8]*c/4+I[i+6])*c/3+I[i+4])*c/2+I[i+2])*c+I[i];\n}\n\nvoid solvetrid(X,y,m)\ndouble *X, *y;\nINT m;\n{ INT i;\n  double s;\n  for (i=1; i<m; i++)\n  { s = X[3*i]/X[3*i-2];\n    X[3*i] = 0; X[3*i+1] -= s*X[3*i-1];\n    y[i] -= s*y[i-1];\n  }\n  for (i=m-2; i>=0; i--)\n  { s = X[3*i+2]/X[3*i+4];\n    X[3*i+2] = 0;\n    y[i] -= s*y[i+1];\n  }\n  for (i=0; i<m; i++) y[i] /= X[3*i+1];\n}\n\nvoid initi0i1(I,cf,y0,y1,l0,l1)\ndouble *I, *cf, y0, y1, l0, l1;\n{ double a0, a1, c, d, bi;\n  d = -cf[1]/(2*cf[2]); c = sqrt(2*fabs(cf[2]));\n  a0 = c*(l0-d); a1 = c*(l1-d);\n  if (cf[2]<0)\n  { bi = lf_exp(cf[0]+cf[1]*d+cf[2]*d*d)/c;\n    if (a0>0)\n    { if (a0>6) I[0] = (y0*ptail(-a0)-y1*ptail(-a1))/c;\n      else I[0] = S2PI*(pnorm(-a0,0.0,1.0)-pnorm(-a1,0.0,1.0))*bi;\n    }\n    else\n    { if (a1< -6) I[0] = (y1*ptail(a1)-y0*ptail(a0))/c;\n      else I[0] = S2PI*(pnorm(a1,0.0,1.0)-pnorm(a0,0.0,1.0))*bi;\n    }\n  }\n  else\n    I[0] = (y1*daws(a1)-y0*daws(a0))/c;\n  I[1] = (y1-y0)/(2*cf[2])+d*I[0];\n}\n\nvoid explinsid(l0,l1,cf,I,p) /* large b; don't use fwd recursion */\ndouble l0, l1, *cf, *I;\nINT p;\n{ INT k, k0, k1, k2;\n  double y0, y1, Z[150];\nif (debug) printf(\"side: %8.5f %8.5f %8.5f    limt %8.5f %8.5f  p %2d\\n\",cf[0],cf[1],cf[2],l0,l1,p);\n \n  k0 = 2;\n  k1 = (INT)(fabs(cf[1])+fabs(2*cf[2]));\n  if (k1<2) k1 = 2;\n  if (k1>p+20) k1 = p+20;\n  k2 = p+20;\n\n  if (debug) printf(\"k0 %2d  k1 %2d  k2 %2d  p %2d\\n\",k0,k1,k2,p);\n\n  y0 = lf_exp(cf[0]+l0*(cf[1]+l0*cf[2]));\n  y1 = lf_exp(cf[0]+l1*(cf[1]+l1*cf[2]));\n  initi0i1(I,cf,y0,y1,l0,l1);\nif (debug) printf(\"i0 %8.5f  i1 %8.5f\\n\",I[0],I[1]);\n\n  y1 *= l1; y0 *= l0; /* should be x^(k1)*exp(..) */\n  if (k0<k1) /* center steps; initially x^k*exp(...) */\n    for (k=k0; k<k1; k++)\n    { y1 *= l1; y0 *= l0;\n      I[k] = y1-y0;\n      Z[3*k] = k; Z[3*k+1] = cf[1]; Z[3*k+2] = 2*cf[2];\n    }\n   \n  y1 *= l1; y0 *= l0; /* should be x^(k1)*exp(..) */\nif (debug) printf(\"k1 %2d  y0 %8.5f  y1 %8.5f\\n\",k1,y0,y1);\n  for (k=k1; k<k2; k++)\n  { y1 *= l1; y0 *= l0;\n    I[k] = y1-y0;\n  }\n  I[k2] = I[k2+1] = 0.0;\n  for (k=k2-1; k>=k1; k--)\n    I[k] = (I[k]-cf[1]*I[k+1]-2*cf[2]*I[k+2])/(k+1);\n\n  if (k0<k1)\n  { I[k0] -= k0*I[k0-1];\n    I[k1-1] -= 2*cf[2]*I[k1];\n    Z[3*k0] = Z[3*k1-1] = 0;\n    solvetrid(&Z[3*k0],&I[k0],k1-k0);\n  }\nif (debug)\n{ printf(\"explinsid:\\n\");\n  for (k=0; k<p; k++) printf(\"  %8.5f\\n\",I[k]);\n}\n}\n\nvoid explinbkr(l0,l1,cf,I,p) /* small b,c; use back recursion */\ndouble l0, l1, *cf, *I;\nINT p;\n{ INT k, km;\n  double y0, y1;\n  y0 = lf_exp(cf[0]+l0*(cf[1]+cf[2]*l0));\n  y1 = lf_exp(cf[0]+l1*(cf[1]+cf[2]*l1));\n  km = p+10;\n  for (k=0; k<=km; k++)\n  { y1 *= l1; y0 *= l0;\n    I[k] = y1-y0;\n  }\n  I[km+1] = I[km+2] = 0;\n  for (k=km; k>=0; k--)\n    I[k] = (I[k]-cf[1]*I[k+1]-2*cf[2]*I[k+2])/(k+1);\n}\n\nvoid explinfbk0(l0,l1,cf,I,p) /* fwd and bac recur; b=0; c<0 */\ndouble l0, l1, *cf, *I;\nINT p;\n{ double y0, y1, f1, f2, f, ml2;\n  INT k, ks;\n\n  y0 = lf_exp(cf[0]+l0*l0*cf[2]);\n  y1 = lf_exp(cf[0]+l1*l1*cf[2]);\n  initi0i1(I,cf,y0,y1,l0,l1);\n\n  ml2 = MAX(l0*l0,l1*l1);\n  ks = 1+(INT)(2*fabs(cf[2])*ml2);\n  if (ks<2) ks = 2;\n  if (ks>p-3) ks = p;\n\n  /* forward recursion for k < ks */\n  for (k=2; k<ks; k++)\n  { y1 *= l1; y0 *= l0;\n    I[k] = (y1-y0-(k-1)*I[k-2])/(2*cf[2]);\n  }\n  if (ks==p) return;\n\n  y1 *= l1*l1; y0 *= l0*l0;\n  for (k=ks; k<p; k++) /* set I[k] = x^{k+1}e^(a+cx^2) | {l0,l1} */\n  { y1 *= l1; y0 *= l0;\n    I[k] = y1-y0;\n  }\n\n  /* initialize I[p-2] and I[p-1] */\n  f1 = 1.0/p; f2 = 1.0/(p-1);\n  I[p-1] *= f1; I[p-2] *= f2;\n  k = p; f = 1.0;\n  while (f>1.0e-8)\n  { y1 *= l1; y0 *= l0;\n    if ((k-p)%2==0) /* add to I[p-2] */\n    { f2 *= -2*cf[2]/(k+1);\n      I[p-2] += (y1-y0)*f2;\n    }\n    else /* add to I[p-1] */\n    { f1 *= -2*cf[2]/(k+1);\n      I[p-1] += (y1-y0)*f1;\n      f *= 2*fabs(cf[2])*ml2/(k+1);\n    }\n    k++;\n  }\n  \n  /* use back recursion for I[ks..(p-3)] */\n  for (k=p-3; k>=ks; k--)\n    I[k] = (I[k]-2*cf[2]*I[k+2])/(k+1);\n}\n\nvoid explinfbk(l0,l1,cf,I,p) /* fwd and bac recur; b not too large */\ndouble l0, l1, *cf, *I;\nINT p;\n{ double y0, y1;\n  INT k, ks, km;\n\n  y0 = lf_exp(cf[0]+l0*(cf[1]+l0*cf[2]));\n  y1 = lf_exp(cf[0]+l1*(cf[1]+l1*cf[2]));\n  initi0i1(I,cf,y0,y1,l0,l1);\n\n  ks = (INT)(3*fabs(cf[2]));\n  if (ks<3) ks = 3;\n  if (ks>0.75*p) ks = p; /* stretch the forward recurs as far as poss. */\n  /* forward recursion for k < ks */\n  for (k=2; k<ks; k++)\n  { y1 *= l1; y0 *= l0;\n    I[k] = (y1-y0-cf[1]*I[k-1]-(k-1)*I[k-2])/(2*cf[2]);\n  }\n  if (ks==p) return;\n\n  km = p+15;\n  y1 *= l1*l1; y0 *= l0*l0;\n  for (k=ks; k<=km; k++)\n  { y1 *= l1; y0 *= l0;\n    I[k] = y1-y0;\n  }\n  I[km+1] = I[km+2] = 0.0;\n  for (k=km; k>=ks; k--)\n    I[k] = (I[k]-cf[1]*I[k+1]-2*cf[2]*I[k+2])/(k+1);\n}\n\nvoid recent(I,resp,wt,p,s,x)\ndouble *I, *resp, *wt, x;\nINT p, s;\n{ INT i, j;\n\n  /* first, use W taylor series I -> resp */\n  for (i=0; i<=p; i++)\n  { resp[i] = 0.0;\n    for (j=0; j<s; j++) resp[i] += wt[j]*I[i+j];\n  }\n\n  /* now, recenter x -> 0 */\n  if (x==0) return;\n  for (j=0; j<=p; j++) for (i=p; i>j; i--) resp[i] += x*resp[i-1];\n}\n\nvoid recurint(l0,l2,cf,resp,p,ker)\ndouble l0, l2, *cf, *resp;\nINT p, ker;\n{ INT i, s;\n  double l1, d0, d1, d2, dl, z0, z1, z2, wt[20], ncf[3], I[50], r1[5], r2[5];\nif (debug) printf(\"\\nrecurint: %8.5f %8.5f %8.5f   %8.5f %8.5f\\n\",cf[0],cf[1],cf[2],l0,l2);\n\n  if (cf[2]==0) /* go straight to explint1 */\n  { s = wtaylor(wt,0.0,ker);\nif (debug) printf(\"case 1\\n\");\n    explint1(l0,l2,cf,I,p+s);\n    recent(I,resp,wt,p,s,0.0);\n    return;\n  }\n\n  dl = l2-l0;\n  d0 = cf[1]+2*l0*cf[2];\n  d2 = cf[1]+2*l2*cf[2];\n  z0 = cf[0]+l0*(cf[1]+l0*cf[2]);\n  z2 = cf[0]+l2*(cf[1]+l2*cf[2]);\n\n  if ((fabs(cf[1]*dl)<1) && (fabs(cf[2]*dl*dl)<1))\n  { ncf[0] = z0; ncf[1] = d0; ncf[2] = cf[2];\nif (debug) printf(\"case 2\\n\");\n    s = wtaylor(wt,l0,ker);\n    explinbkr(0.0,dl,ncf,I,p+s);\n    recent(I,resp,wt,p,s,l0);\n    return;\n  }\n\n  if (fabs(cf[2]*dl*dl)<0.001) /* small c, use explint1+tay.ser */\n  { ncf[0] = z0; ncf[1] = d0; ncf[2] = cf[2];\nif (debug) printf(\"case small c\\n\");\n    s = wtaylor(wt,l0,ker);\n    explintyl(0.0,l2-l0,ncf,I,p+s);\n    recent(I,resp,wt,p,s,l0);\n    return;\n  }\n\n  if (d0*d2<=0) /* max/min in [l0,l2] */\n  { l1 = -cf[1]/(2*cf[2]);\n    z1 = cf[0]+l1*(cf[1]+l1*cf[2]);\n    d1 = 0.0;\n    if (cf[2]<0) /* peak, integrate around l1 */\n    { s = wtaylor(wt,l1,ker);\n      ncf[0] = z1; ncf[1] = 0.0; ncf[2] = cf[2];\nif (debug) printf(\"case peak  p %2d  s %2d\\n\",p,s);\n      explinfbk0(l0-l1,l2-l1,ncf,I,p+s);\n      recent(I,resp,wt,p,s,l1);\n      return;\n    }\n  }\n\n  if ((d0-2*cf[2]*dl)*(d2+2*cf[2]*dl)<0) /* max/min is close to [l0,l2] */\n  { l1 = -cf[1]/(2*cf[2]);\n    z1 = cf[0]+l1*(cf[1]+l1*cf[2]);\n    if (l1<l0) { l1 = l0; z1 = z0; }\n    if (l1>l2) { l1 = l2; z1 = z2; }\n\n    if ((z1>=z0) & (z1>=z2)) /* peak; integrate around l1 */\n    { s = wtaylor(wt,l1,ker);\nif (debug) printf(\"case 4\\n\");\n      d1 = cf[1]+2*l1*cf[2];\n      ncf[0] = z1; ncf[1] = d1; ncf[2] = cf[2];\n      explinfbk(l0-l1,l2-l1,ncf,I,p+s);\n      recent(I,resp,wt,p,s,l1);\n      return;\n    }\n\n    /* trough; integrate [l0,l1] and [l1,l2] */\n    for (i=0; i<=p; i++) r1[i] = r2[i] = 0.0;\n    if (l0<l1)\n    { s = wtaylor(wt,l0,ker);\nif (debug) printf(\"case 5\\n\");\n      ncf[0] = z0; ncf[1] = d0; ncf[2] = cf[2];\n      explinfbk(0.0,l1-l0,ncf,I,p+s);\n      recent(I,r1,wt,p,s,l0);\n    }\n    if (l1<l2)\n    { s = wtaylor(wt,l2,ker);\nif (debug) printf(\"case 6\\n\");\n      ncf[0] = z2; ncf[1] = d2; ncf[2] = cf[2];\n      explinfbk(l1-l2,0.0,ncf,I,p+s);\n      recent(I,r2,wt,p,s,l2);\n    }\n    for (i=0; i<=p; i++) resp[i] = r1[i]+r2[i];\n    return;\n  }\n\n  /* Now, quadratic is monotone on [l0,l2]; big b; moderate c */\n  if (z2>z0+3) /* steep increase, expand around l2 */\n  { s = wtaylor(wt,l2,ker);\nif (debug) printf(\"case 7\\n\");\n\n\n    ncf[0] = z2; ncf[1] = d2; ncf[2] = cf[2];\n    explinsid(l0-l2,0.0,ncf,I,p+s);\n    recent(I,resp,wt,p,s,l2);\nif (debug) printf(\"7 resp: %8.5f %8.5f %8.5f %8.5f\\n\",resp[0],resp[1],resp[2],resp[3]);\n    return;\n  }\n\n  /* bias towards expansion around l0, because it's often 0 */\nif (debug) printf(\"case 8\\n\");\n  s = wtaylor(wt,l0,ker);\n  ncf[0] = z0; ncf[1] = d0; ncf[2] = cf[2];\n  explinsid(0.0,l2-l0,ncf,I,p+s);\n  recent(I,resp,wt,p,s,l0);\n  return;\n}\n\nINT onedexpl(cf,mi,resp)\ndouble *cf, *resp;\nINT *mi;\n{ INT i;\n  double f0, fr, fl;\n  if (mi[MDEG]>=2) ERROR((\"onedexpl only valid for deg=0,1\"));\n  if (fabs(cf[1])>=EFACT) return(LF_BADP);\n\n  f0 = exp(cf[0]); fl = fr = 1.0;\n  for (i=0; i<=2*mi[MDEG]; i++)\n  { f0 *= i+1;\n    fl /=-(EFACT+cf[1]);\n    fr /=  EFACT-cf[1];\n    resp[i] = f0*(fr-fl);\n  }\n  return(LF_OK);\n}\n\nINT onedgaus(cf,mi,resp)\ndouble *cf, *resp;\nINT *mi;\n{ INT i;\n  double f0, mu, s2;\n  if (mi[MDEG]>=3)\n  { ERROR((\"onedgaus only valid for deg=0,1,2\"));\n    return(LF_ERR);\n  }\n  if (2*cf[2]>=GFACT*GFACT) return(LF_BADP);\n\n  s2 = 1/(GFACT*GFACT-2*cf[2]);\n  mu = cf[1]*s2;\n  resp[0] = 1.0;\n  if (mi[MDEG]>=1)\n  { resp[1] = mu;\n    resp[2] = s2+mu*mu;\n    if (mi[MDEG]==2)\n    { resp[3] = mu*(3*s2+mu*mu);\n      resp[4] = 3*s2*s2 + mu*mu*(6*s2+mu*mu);\n    }\n  }\n  f0 = S2PI * exp(cf[0]+mu*mu/(2*s2))*sqrt(s2);\n  for (i=0; i<=2*mi[MDEG]; i++) resp[i] *= f0;\n  return(LF_OK);\n}\n\nINT onedint(cf,mi,l0,l1,resp) /* int W(u)u^j exp(..), j=0..2*deg */\ndouble *cf, l0, l1, *resp;\nINT *mi;\n{ double u, uj, y, ncf[4], rr[5];\n  INT deg, i, j;\n    memset(rr, 0, sizeof(rr));\nif (debug) printf(\"onedint: %f %f %f   %f %f\\n\",cf[0],cf[1],cf[2],l0,l1);\n  deg = mi[MDEG];\n\n  if (deg<=2)\n  { for (i=0; i<3; i++) ncf[i] = (i>deg) ? 0.0 : cf[i];\n    ncf[2] /= 2;\n\n    if (mi[MKER]==WEXPL) return(onedexpl(ncf,mi,resp));\n    if (mi[MKER]==WGAUS) return(onedgaus(ncf,mi,resp));\n\n    if (l1>0)\n      recurint(MAX(l0,0.0),l1,ncf,resp,2*deg,mi[MKER]);\n    else for (i=0; i<=2*deg; i++) resp[i] = 0;\n\n    if (l0<0)\n    { ncf[1] = -ncf[1];\n      l0 = -l0; l1 = -l1;\n      recurint(MAX(l1,0.0),l0,ncf,rr,2*deg,mi[MKER]);\n    }\n    else for (i=0; i<=2*deg; i++) rr[i] = 0.0;\n\n    for (i=0; i<=2*deg; i++)\n      resp[i] += (i%2==0) ? rr[i] : -rr[i];\n\n    return(LF_OK);\n  }\n\n  /* For degree >= 3, we use Simpson's rule. */\n  for (j=0; j<=2*deg; j++) resp[j] = 0.0;\n  for (i=0; i<=mi[MMINT]; i++)\n  { u = l0+(l1-l0)*i/mi[MMINT];\n    y = cf[0]; uj = 1;\n    for (j=1; j<=deg; j++)\n    { uj *= u;\n      y += cf[j]*uj/fact[j];\n    }\n    y = (4-2*(i%2==0)-(i==0)-(i==mi[MMINT])) *\n          W(fabs(u),mi[MKER])*exp(MIN(y,300.0));\n    for (j=0; j<=2*deg; j++)\n    { resp[j] += y;\n      y *= u;\n    }\n  }\n  for (j=0; j<=2*deg; j++) resp[j] = resp[j]*(l1-l0)/(3*mi[MMINT]);\n  return(LF_OK);\n}\n\n"
  },
  {
    "path": "src/locfit/density.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\nextern int lf_status;\nstatic double u[MXDIM], ilim[2*MXDIM], *ff;\nstatic lfit   *den_lf;\nstatic design *den_des;\nINT fact[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800};\n\nINT multint(), prodint(), gausint(), mlinint();\n\nvoid prresp(coef,resp,p)\ndouble *coef, *resp;\nINT p;\n{ INT i, j;\n  printf(\"Coefficients:\\n\");\n  for (i=0; i<p; i++) printf(\"%8.5f \",coef[i]);\n  printf(\"\\n\");\n  printf(\"Response matrix:\\n\");\n  for (i=0; i<p; i++)\n  { for (j=0; j<p; j++) printf(\"%9.6f, \",resp[i+j*p]);\n    printf(\"\\n\");\n  }\n}\n\nINT multint(t,resp1,resp2,lf,cf,h)\nlfit *lf;\ndouble *t, *resp1, *resp2, *cf, h;\n{ INT d, p, i, j, k, m, m1, w, z, z1;\n  double th, wt, dj[MXDIM];\n  d = lf->mi[MDIM]; p = lf->mi[MP];\n  setzero(resp1,p*p);\n  m = 1; m1 = lf->mi[MMINT]+1;\n  for (i=0; i<d; i++)\n  { m *= m1;\n    dj[i] = (ilim[i+d]-ilim[i])/lf->mi[MMINT];\n  }\n  for (i=0; i<m; i++)\n  { z = i; w = 1;\n    for (j=d-1; j>=0; j--)\n    { z1 = z%m1;\n      u[j] = t[j]+ilim[j]+dj[j]*z1;\n      w *= (4-2*(z1%2==0)-(z1==0)-(z1==lf->mi[MMINT]));\n      z /= m1;\n    }\n    wt = w*weight(lf,u,t,h,0,0.0);\n    if (wt>0)\n    { fitfun(lf,u,t,ff,NULL,0);\n      th = innerprod(ff,cf,p);\n      switch(lf->mi[MLINK])\n      { case LLOG:\n          addouter(resp1,ff,ff,p,wt*lf_exp(th));\n          break;\n        case LIDENT:\n          addouter(resp1,ff,ff,p,wt);\n          break;\n        default:\n          ERROR((\"multint: Invalid link\"));\n          return(LF_LNK);\n      }\n    }\n  }\n  wt = 1;\n  for (j=0; j<d; j++) wt *= dj[j]/3;\n  for (j=0; j<p; j++)\n    for (k=j; k<p; k++)\n      resp1[p*k+j] = resp1[p*j+k] = resp1[p*j+k]*wt;\n  return(LF_OK);\n}\n\nINT mlinint(t,resp1,resp2,lf,cf,h)\nlfit *lf;\ndouble *t, *resp1, *resp2, *cf, h;\n{\n  double hd, nb, wt, wu, g[4], w0, w1, v, *sca;\n  INT d, p, i, j, jmax, k, l, z, jj[2];\n  d = lf->mi[MDIM]; p = lf->mi[MP]; sca = lf->sca;\n  hd = 1;\n  for (i=0; i<d; i++) hd *= h*sca[i];\n\n  if (lf->mi[MLINK]==LIDENT)\n  { setzero(resp1,p*p);\n    resp1[0] = wint(d,NULL,0,lf->mi[MKER])*hd;\n    if (lf->mi[MDEG]==0) return(LF_OK);\n    jj[0] = 2; w0 = wint(d,jj,1,lf->mi[MKER])*hd*h*h;\n    for (i=0; i<d; i++) resp1[(i+1)*p+i+1] = w0*sca[i]*sca[i];\n    if (lf->mi[MDEG]==1) return(LF_OK);\n    for (i=0; i<d; i++)\n    { j = p-(d-i)*(d-i+1)/2;\n      resp1[j] = resp1[p*j] = w0*sca[i]*sca[i]/2;\n    }\n    if (d>1) { jj[1] = 2; w0 = wint(d,jj,2,lf->mi[MKER])*hd*h*h*h*h; }\n    jj[0] = 4; w1 = wint(d,jj,1,lf->mi[MKER])*hd*h*h*h*h/4;\n    z = d+1;\n    for (i=0; i<d; i++)\n    { k = p-(d-i)*(d-i+1)/2;\n      for (j=i; j<d; j++)\n      { l = p-(d-j)*(d-j+1)/2;\n        if (i==j) resp1[z*p+z] = w1*SQR(sca[i])*SQR(sca[i]);\n        else\n        { resp1[z*p+z] = w0*SQR(sca[i])*SQR(sca[j]);\n          resp1[k*p+l] = resp1[k+p*l] = w0/4*SQR(sca[i])*SQR(sca[j]);\n        }\n        z++;\n    } }\n    return(LF_OK);\n  }\n  switch(lf->mi[MDEG])\n  { case 0:\n      resp1[0] = lf_exp(cf[0])*wint(d,NULL,0,lf->mi[MKER])*hd;\n      return(LF_OK);\n    case 1:\n      nb = 0.0;\n      for (i=1; i<=d; i++)\n      { v = h*cf[i]*sca[i-1];\n        nb += v*v;\n      }\n      if (lf->mi[MKER]==WGAUS)\n      { w0 = 1/(GFACT*GFACT);\n        g[0] = lf_exp(cf[0]+w0*nb/2+d*log(S2PI/2.5));\n        g[1] = g[3] = g[0]*w0;\n        g[2] = g[0]*w0*w0;\n      }\n      else\n      { wt = wu = lf_exp(cf[0]);\n        w0 = wint(d,NULL,0,lf->mi[MKER]); g[0] = wt*w0;\n        g[1] = g[2] = g[3] = 0.0;\n        j = 0; jmax = (d+2)*lf->mi[MMINT];\n        while ((j<jmax) && (wt*w0/g[0]>1.0e-8))\n        { j++;\n          jj[0] = 2*j; w0 = wint(d,jj,1,lf->mi[MKER]);\n          if (d==1) g[3] += wt * w0;\n          else\n          { jj[0] = 2; jj[1] = 2*j-2; w1 = wint(d,jj,2,lf->mi[MKER]);\n            g[3] += wt*w1;\n            g[2] += wu*(w0-w1);\n          }\n          wt /= (2*j-1.0); g[1] += wt*w0;\n          wt *= nb/(2*j); g[0] += wt*w0;\n          wu /= (2*j-1.0)*(2*j);\n          if (j>1) wu *= nb;\n        }\n        if (j==jmax) WARN((\"mlinint: series not converged\"));\n      }\n      g[0] *= hd; g[1] *= hd;\n      g[2] *= hd; g[3] *= hd;\n      resp1[0] = g[0];\n      for (i=1; i<=d; i++)\n      { resp1[i] = resp1[(d+1)*i] = cf[i]*SQR(h*sca[i-1])*g[1];\n        for (j=1; j<=d; j++)\n        { resp1[(d+1)*i+j] = (i==j) ? g[3]*SQR(h*sca[i-1]) : 0;\n          resp1[(d+1)*i+j] += g[2]*SQR(h*h*sca[i-1]*sca[j-1])*cf[i]*cf[j];\n        }\n      }\n      return(LF_OK);\n  }\n  ERROR((\"mlinint: deg=0,1 only\"));\n  return(LF_ERR);\n}\n\nvoid prodint_resp(resp,prod_wk,dim,deg,p)\ndouble *resp, prod_wk[MXDIM][2*MXDEG+1];\nint dim, deg, p;\n{ double prod;\n  int i, j, k, j1, k1;\n\n  prod = 1.0;\n  for (i=0; i<dim; i++) prod *= prod_wk[i][0];\n  resp[0] += prod;\n  if (deg==0) return;\n\n  for (j1=1; j1<=deg; j1++)\n  { for (j=0; j<dim; j++)\n    { prod = 1.0;\n      for (i=0; i<dim; i++) prod *= prod_wk[i][j1*(j==i)];\n      prod /= fact[j1];\n      resp[1 + (j1-1)*dim +j] += prod;\n    }\n  }\n\n  for (k1=1; k1<=deg; k1++)\n    for (j1=k1; j1<=deg; j1++)\n    { for (k=0; k<dim; k++)\n        for (j=0; j<dim; j++)\n        { prod = 1.0;\n          for (i=0; i<dim; i++) prod *= prod_wk[i][k1*(k==i) + j1*(j==i)];\n          prod /= fact[k1]*fact[j1];\n          resp[ (1+(k1-1)*dim+k)*p + 1+(j1-1)*dim+j] += prod;\n        }\n    }\n}\n\nINT prodint(t,resp,resp2,lf,coef,h)\nlfit *lf;\ndouble *t, *resp, *resp2, *coef, h;\n{ INT dim, deg, p, i, j, k, st;\n  double cf[MXDEG+1], hj, hs, prod_wk[MXDIM][2*MXDEG+1];\n\n    st = 0;\n  dim = lf->mi[MDIM];\n  deg = lf->mi[MDEG];\n  p = lf->mi[MP];\n  for (i=0; i<p*p; i++) resp[i] = 0.0;\n  cf[0] = coef[0];\n\n/*  compute the one dimensional terms\n */\n  for (i=0; i<dim; i++)\n  { hj = 1; hs = h*lf->sca[i];\n    for (j=0; j<deg; j++)\n    { hj *= hs;\n      cf[j+1] = hj*coef[ j*dim+i+1 ];\n    }\n    st = onedint(cf,lf->mi,ilim[i]/hs,ilim[i+dim]/hs,prod_wk[i]);\n    if (st==LF_BADP) return(st);\n    hj = 1;\n    for (j=0; j<=2*deg; j++)\n    { hj *= hs;\n      prod_wk[i][j] *= hj;\n    }\n    cf[0] = 0.0; /* so we only include it once, when d>=2 */\n  }\n\n/*  transfer to the resp array\n */\n  prodint_resp(resp,prod_wk,dim,deg,p);\n\n/* Symmetrize.\n*/\n  for (k=0; k<p; k++)\n    for (j=k; j<p; j++)\n      resp[j*p+k] = resp[k*p+j];\n\n  return(st);\n}\n\nINT gausint(t,resp,C,cf,h,mi,sca)\ndouble *t, *resp, *C, *cf, h, *sca;\nINT *mi;\n{ double nb, det, z, *P;\n  INT d, p, i, j, k, l, m1, m2, f;\n  d = mi[MDIM]; p = mi[MP];\n  m1 = d+1; nb = 0;\n  P = &C[d*d];\n  resp[0] = 1;\n  for (i=0; i<d; i++)\n  { C[i*d+i] = SQR(GFACT/(h*sca[i]))-cf[m1++];\n    for (j=i+1; j<d; j++) C[i*d+j] = C[j*d+i] = -cf[m1++];\n  }\n  eig_dec(C,P,d);\n  det = 1;\n  for (i=1; i<=d; i++)\n  { det *= C[(i-1)*(d+1)];\n    if (det <= 0) return(LF_BADP);\n    resp[i] = cf[i];\n    for (j=1; j<=d; j++) resp[j+i*p] = 0;\n    resp[i+i*p] = 1;\n    svdsolve(&resp[i*p+1],u,P,C,P,d,0.0);\n  }\n  svdsolve(&resp[1],u,P,C,P,d,0.0);\n  det = sqrt(det);\n  for (i=1; i<=d; i++)\n  { nb += cf[i]*resp[i];\n    resp[i*p] = resp[i];\n    for (j=1; j<=d; j++)\n      resp[i+p*j] += resp[i]*resp[j];\n  }\n  m1 = d;\n  for (i=1; i<=d; i++)\n    for (j=i; j<=d; j++)\n    { m1++; f = 1+(i==j);\n      resp[m1] = resp[m1*p] = resp[i*p+j]/f;\n      m2 = d;\n      for (k=1; k<=d; k++)\n      { resp[m1+k*p] = resp[k+m1*p] =\n        ( resp[i]*resp[j*p+k] + resp[j]*resp[i*p+k]\n        + resp[k]*resp[i*p+j] - 2*resp[i]*resp[j]*resp[k] )/f;\n        for (l=k; l<=d; l++)\n        { m2++; f = (1+(i==j))*(1+(k==l));\n          resp[m1+m2*p] = resp[m2+m1*p] = ( resp[i+j*p]*resp[k+l*p]\n            + resp[i+k*p]*resp[j+l*p] + resp[i+l*p]*resp[j+k*p]\n            - 2*resp[i]*resp[j]*resp[k]*resp[l] )/f;\n    } } }\n  z = lf_exp(d*0.918938533+cf[0]+nb/2)/det;\n  multmatscal(resp,z,p*p);\n  return(LF_OK);\n}\n\nint likeden(coef, lk0, f1, A)\ndouble *coef, *lk0, *f1, *A;\n{ double lk, r;\n  int i, j, p, rstat;\n\n    lk = 0;\n  lf_status = LF_OK;\n  p = den_des->p;\n  if ((den_lf->mi[MLINK]==LIDENT) && (coef[0] != 0.0)) return(NR_BREAK);\n  lf_status = (den_des->itype)(den_des->xev,A,den_des->xtwx.Q,den_lf,coef,den_des->h);\n  if (lf_error) lf_status = LF_ERR;\n  if (lf_status==LF_BADP)\n  { *lk0 = -1.0e300;\n    return(NR_REDUCE);\n  }\n  if (lf_status!=LF_OK) return(NR_BREAK);\n  if (den_lf->mi[MDEB]>2) prresp(coef,A,(INT)p);\n\n  den_des->xtwx.p = p;\n  rstat = NR_OK;\n  switch(den_lf->mi[MLINK])\n  { case LLOG:\n      r = den_des->ss[0]/A[0];\n      coef[0] += log(r);\n      multmatscal(A,r,(INT)p*p);\n      A[0] = den_des->ss[0];\n      lk = -A[0];\n      if (fabs(coef[0]) > 700)\n      { lf_status = LF_OOB;\n        rstat = NR_REDUCE;\n      }\n      for (i=0; i<p; i++)\n      { lk += coef[i]*den_des->ss[i];\n        f1[i] = den_des->ss[i]-A[i];\n      }\n      break;\n    case LIDENT:\n      lk = 0.0;\n      for (i=0; i<p; i++)\n      { f1[i] = den_des->ss[i];\n        for (j=0; j<p; j++)\n          den_des->res[i] -= A[i*p+j]*coef[j];\n      }\n      break;\n  }\n  *lk0 = den_des->llk = lk;\n\n  return(rstat);\n}\n\nINT inre(x,bound,d)\ndouble *x, *bound;\nINT d;\n{ INT i, z;\n  z = 1;\n  for (i=0; i<d; i++)\n    if (bound[i]<bound[i+d])\n      z &= (x[i]>=bound[i]) & (x[i]<=bound[i+d]);\n  return(z);\n}\n\nINT setintlimits(lf, x, h, ang, lset)\nlfit *lf;\nINT *ang, *lset;\ndouble *x, h;\n{ INT d, i;\n  d = lf->mi[MDIM];\n  *ang = *lset = 0;\n  for (i=0; i<d; i++)\n  { if (lf->sty[i]==STANGL)\n    { ilim[i+d] = ((h<2) ? 2*asin(h/2) : PI)*lf->sca[i];\n      ilim[i] = -ilim[i+d];\n      *ang = 1;\n    }\n    else\n    { ilim[i+d] = h*lf->sca[i];\n      ilim[i] = -ilim[i+d];\n\n      if (lf->sty[i]==STLEFT) { ilim[i+d] = 0; *lset = 1; }\n      if (lf->sty[i]==STRIGH) { ilim[i] = 0;   *lset = 1; }\n\n      if (lf->xl[i]<lf->xl[i+d]) /* user limits for this variable */\n      { if (lf->xl[i]-x[i]> ilim[i])\n        { ilim[i] = lf->xl[i]-x[i]; *lset=1; }\n        if (lf->xl[i+d]-x[i]< ilim[i+d])\n        { ilim[i+d] = lf->xl[i+d]-x[i]; *lset=1; }\n      }\n    }\n    if (ilim[i]==ilim[i+d]) return(LF_DEMP); /* empty integration */\n  }\n  return(LF_OK);\n}\n\nINT selectintmeth(mi,lset,ang)\nINT *mi, lset, ang;\n{\n  if (mi[MIT]==IDEFA) /* select the default method */\n  { if (mi[MTG]==THAZ)\n    { if (ang) return(IDEFA);\n      return( IHAZD );\n    }\n\n    if (mi[MUBAS]) return(IMULT);\n\n    if (ang) return(IMULT);\n\n    if (iscompact(mi[MKER]))\n    { if (mi[MKT]==KPROD) return(IPROD);\n      if (lset)\n        return( (mi[MDIM]==1) ? IPROD : IMULT );\n      if (mi[MDEG]<=1) return(IMLIN);\n      if (mi[MDIM]==1) return(IPROD);\n      return(IMULT);\n    }\n\n    if (mi[MKER]==WGAUS)\n    { if (lset) WARN((\"Integration for Gaussian weights ignores limits\"));\n      if ((mi[MDIM]==1)|(mi[MKT]==KPROD)) return(IPROD);\n      return(IMLIN);\n    }\n\n    return(IDEFA);\n  }\n\n  /* user provided an integration method, check it is valid */\n\n  if (mi[MTG]==THAZ)\n  { if (ang) return(INVLD);\n    if (!iscompact(mi[MKER])) return(INVLD);\n    return( ((mi[MKT]==KPROD) | (mi[MKT]==KSPH)) ? IHAZD : INVLD );\n  }\n\n  if ((ang) && (mi[MIT] != IMULT)) return(INVLD);\n\n  switch(mi[MIT])\n  { case IMULT: return( iscompact(mi[MKER]) ? IMULT : INVLD );\n    case IPROD: return( ((mi[MDIM]==1) | (mi[MKT]==KPROD)) ? IPROD : INVLD );\n    case IMLIN: return( ((mi[MKT]==KSPH) && (!lset) &&\n      (mi[MDEG]<=1)) ? IMLIN : INVLD );\n  }\n\n  return(INVLD);\n}\n\nINT densinit(lf,des,h,cf,m)\nlfit *lf;\ndesign *des;\ndouble h, *cf;\nINT m;\n{ INT deg, p, i, ii, j, nnz, rnz, lset, ang, status;\n  double w;\n\n  den_lf  = lf;\n  den_des = des;\n\n  p = des->p; deg = lf->mi[MDEG];\n  ff = des->xtwx.wk;\n  cf[0] = NOSLN;\n  for (i=1; i<p; i++) cf[i] = 0.0;\n\n  if (!inre(des->xev,lf->xl,lf->mi[MDIM])) return(LF_XOOR);\n\n  status = setintlimits(lf,des->xev,h,&ang,&lset);\n  if (status != LF_OK) return(status);\n\n  switch(selectintmeth(lf->mi,lset,ang))\n  { case IMULT: des->itype = multint; break;\n    case IPROD: des->itype = prodint; break;\n    case IMLIN: des->itype = mlinint; break;\n    case IHAZD: des->itype = hazint; break;\n    case INVLD: ERROR((\"Invalid integration method %d\",lf->mi[MIT]));\n                break;\n    case IDEFA: ERROR((\"No integration type available for this model\"));\n                break;\n    default: ERROR((\"densinit: unknown integral type\"));\n  }\n\n  switch(deg)\n  { case 0: rnz = 1; break;\n    case 1: rnz = 1; break;\n    case 2: rnz = lf->mi[MDIM]+1; break;\n    case 3: rnz = lf->mi[MDIM]+2; break;\n    default: ERROR((\"densinit: invalid degree %d\",deg));\n  }\n  if (lf_error) return(LF_ERR);\n\n  setzero(des->ss,p);\n  nnz = 0;\n  for (i=0; i<m; i++)\n  { ii = des->ind[i];\n    if (!cens(lf,ii))\n    { w = des->w[i]*prwt(lf,ii);\n      for (j=0; j<p; j++) des->ss[j] += d_xij(des,i,j)*w;\n      if (des->w[i]>0.00001) nnz++;\n  } }\n\n  if (lf->mi[MTG]==THAZ) haz_init(lf,des,ilim);\n\n  if (lf->mi[MDEB]>2)\n  { printf(\"    LHS: \");\n    for (i=0; i<p; i++) printf(\" %8.5f\",des->ss[i]);\n    printf(\"\\n\");\n  }\n\n  switch(lf->mi[MLINK])\n  { case LIDENT:\n      cf[0] = 0.0;\n      return(LF_OK);\n    case LLOG:\n      if (nnz<rnz) { cf[0] = -1000; return(LF_DNOP); }\n      cf[0] = 0.0;\n      return(LF_OK);\n    default:\n      ERROR((\"unknown link in densinit\"));\n      return(LF_ERR);\n  }\n}\n"
  },
  {
    "path": "src/locfit/design.h",
    "content": "/*\n *   Copyright (c) 1998-2000 Lucent Technologies.\n *   See README file for details.\n *\n *\n *   The design structure used in Locfit, and associated macro definitions.\n */\n\ntypedef struct {\n  vari *dw, *index;\n  double *xev;       /* fit point length p               */\n  double *X;         /* design matrix, length n*p        */\n  double *w, *di, *res, *th, *wd, h, xb[MXDIM];\n  double *V, *P, *f1, *ss, *oc, *cf, llk;\n  jacobian xtwx;     /* to store X'WVX and decomposition */\n  int cfn[1+MXDIM], ncoef;\n  int *fix;          /* indicator vector, showing fixed variables. */\n  INT *ind, n, p, pref, (*itype)();\n  INT (*vfun)();     /* pointer to the vertex processing function. */\n} design;\n\n#define cfn(des,i) (des->cfn[i])\n#define d_x(des) ((des)->X)\n#define d_xi(des,i) (&(des)->X[i*((des)->p)])\n#define d_xij(des,i,j) ((des)->X[i*((des)->p)+j])\n#define is_fixed(des,i) ((des)->fix[i]==1)\n\nextern int des_reqd(), des_reqi();\n"
  },
  {
    "path": "src/locfit/dist.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\n#define LOG_2           0.6931471805599453094172321214581765680755\n#define IBETA_LARGE     1.0e30\n#define IBETA_SMALL     1.0e-30\n#define IGAMMA_LARGE    1.0e30\n#define DOUBLE_EP     2.2204460492503131E-16\n\ndouble dchisq(x, df)\ndouble x, df;\n{ return(exp(log(x/2)*(df/2-1) - x/2 - LGAMMA(df/2) - LOG_2));\n}\n\ndouble df(x, df1, df2)\ndouble x, df1, df2;\n{ double p;\n  p = exp(LGAMMA((df1+df2)/2) + df1/2*log(df1/df2) + (df1/2-1)*log(x)\n               - LGAMMA(df1/2) - LGAMMA(df2/2) - (df1+df2)/2*log(1+x*df1/df2));\n  return(p);\n}\n\ndouble ibeta(x, a, b)\ndouble x, a, b;\n{ int flipped = 0, i, k, count;\n  double I = 0, temp, pn[6], ak, bk, next, prev, factor, val;\n  if (x <= 0) return(0);\n  if (x >= 1) return(1);\n/* use ibeta(x,a,b) = 1-ibeta(1-x,b,z) */\n  if ((a+b+1)*x > (a+1))\n  { flipped = 1;\n    temp = a;\n    a = b;\n    b = temp;\n    x = 1 - x;\n  }\n  pn[0] = 0.0;\n  pn[2] = pn[3] = pn[1] = 1.0;\n  count = 1;\n  val = x/(1.0-x);\n  bk = 1.0;\n  next = 1.0;\n  do\n  { count++;\n    k = count/2;\n    prev = next;\n    if (count%2 == 0)\n      ak = -((a+k-1.0)*(b-k)*val)/((a+2.0*k-2.0)*(a+2.0*k-1.0));\n    else\n      ak = ((a+b+k-1.0)*k*val)/((a+2.0*k)*(a+2.0*k-1.0));\n    pn[4] = bk*pn[2] + ak*pn[0];\n    pn[5] = bk*pn[3] + ak*pn[1];\n    next = pn[4] / pn[5];\n    for (i=0; i<=3; i++)\n      pn[i] = pn[i+2];\n    if (fabs(pn[4]) >= IBETA_LARGE)\n      for (i=0; i<=3; i++)\n        pn[i] /= IBETA_LARGE;\n    if (fabs(pn[4]) <= IBETA_SMALL)\n      for (i=0; i<=3; i++)\n        pn[i] /= IBETA_SMALL;\n  } while (fabs(next-prev) > DOUBLE_EP*prev);\n  factor = a*log(x) + (b-1)*log(1-x);\n  factor -= LGAMMA(a+1) + LGAMMA(b) - LGAMMA(a+b);\n  I = exp(factor) * next;\n  return(flipped ? 1-I : I);\n}\n\n/*\n * Incomplete gamma function.\n * int_0^x u^{df-1} e^{-u} du / Gamma(df).\n */\ndouble igamma(x, df)\ndouble x, df;\n{ double factor, term, gintegral, pn[6], rn, ak, bk;\n  int i, count, k;\n  if (x <= 0.0) return(0.0);\n\n  if (df < 1.0)\n    return( exp(df*log(x)-x-LGAMMA(df+1.0)) + igamma(x,df+1.0) );\n\n/* \n * this is unstable for large df\n */\n  factor = exp(df*log(x) - x - LGAMMA(df));\n\n  if (x > 1.0 && x >= df)\n  {\n    pn[0] = 0.0;\n    pn[2] = pn[1] = 1.0;\n    pn[3] = x;\n    count = 1;\n    rn = 1.0 / x;\n    do\n    { count++;\n      k = count / 2;\n      gintegral = rn;\n      if (count%2 == 0)\n      { bk = 1.0;\n        ak = (double)k - df;\n      } else\n      { bk = x;\n        ak = (double)k;\n      }\n      pn[4] = bk*pn[2] + ak*pn[0];\n      pn[5] = bk*pn[3] + ak*pn[1];\n      rn = pn[4] / pn[5];\n      for (i=0; i<4; i++)\n        pn[i] = pn[i+2];\n      if (pn[4] > IGAMMA_LARGE)\n        for (i=0; i<4; i++)\n          pn[i] /= IGAMMA_LARGE;\n    } while (fabs(gintegral-rn) > DOUBLE_EP*rn);\n    gintegral = 1.0 - factor*rn;\n  }\n  else\n  { /*   For x<df, use the series\n     *   dpois(df,x)*( 1 + x/(df+1) + x^2/((df+1)(df+2)) + ... )\n     *   This could be slow if df large and x/df is close to 1.\n     */\n    gintegral = term = 1.0;\n    rn = df;\n    do\n    { rn += 1.0;\n      term *= x/rn;\n      gintegral += term;\n    } while (term > DOUBLE_EP*gintegral);\n    gintegral *= factor/df;\n  }\n  return(gintegral);\n}\n\ndouble pf(q, df1, df2)\ndouble q, df1, df2;\n{ return(ibeta(q*df1/(df2+q*df1), df1/2, df2/2));\n}\n\ndouble pchisq(q, df)\ndouble q, df;\n{ return(igamma(q/2, df/2));\n}\n\n#ifdef RVERSION\nextern double Rf_pnorm5();\ndouble pnorm(x,mu,s)\ndouble x, mu, s;\n{ return(Rf_pnorm5(x, mu, s, 1L, 0L));\n}\n#else\ndouble pnorm(x,mu,s)\ndouble x, mu, s;\n{ if(x == mu)\n    return(0.5);\n  x = (x-mu)/s;\n  if(x > 0) return((1 + erf(x/SQRT2))/2);\n  return(erfc(-x/SQRT2)/2);\n}\n#endif\n"
  },
  {
    "path": "src/locfit/ev_atree.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *   This file contains functions for constructing and\n *   interpolating the adaptive tree structure. This is\n *   the default evaluation structure used by Locfit.\n */\n\n#include \"local.h\"\n\n/*\n  Guess the number of fitting points.\n  Needs improving!\n*/\nvoid atree_guessnv(nvm,ncm,vc,dp,mi)\ndouble *dp;\nINT *nvm, *ncm, *vc, *mi;\n{ double a0, cu, ifl;\n  int i, nv, nc;\n\n  *ncm = 1<<30; *nvm = 1<<30;\n  *vc = 1 << mi[MDIM];\n\n  if (dp[DALP]>0)\n  { a0 = (dp[DALP] > 1) ? 1 : 1/dp[DALP];\n    if (dp[DCUT]<0.01)\n    { WARN((\"guessnv: cut too small.\"));\n      dp[DCUT] = 0.01;\n    }\n    cu = 1;\n    for (i=0; i<mi[MDIM]; i++) cu *= MIN(1.0,dp[DCUT]);\n    nv = (int)((5*a0/cu+1)**vc);  /* this allows 10*a0/cu splits */\n    nc = (int)(10*a0/cu+1);      /* and 10*a0/cu cells */\n    if (nv<*nvm) *nvm = nv;\n    if (nc<*ncm) *ncm = nc;\n  }\n\n  if (*nvm == 1<<30) /* by default, allow 100 splits */\n  { *nvm = 102**vc;\n    *ncm = 201;\n  }\n\n  /* inflation based on mi[MK] */\n  ifl = mi[MK]/100.0;\n  *nvm = (int)(ifl**nvm);\n  *ncm = (int)(ifl**ncm);\n  \n}\n\n/*\n  Determine whether a cell in the tree needs splitting.\n  If so, return the split variable (0..d-1).\n  Otherwise, return -1.\n*/\nINT atree_split(lf,ce,le,ll,ur)\nlfit *lf;\nINT *ce;\ndouble *le, *ll, *ur;\n{ INT d, vc, i, is;\n  double h, hmin, score[MXDIM];\n    memset(score, 0, sizeof(score));\n  d = lf->mi[MDIM]; vc = 1<<d;\n\n  hmin = 0.0;\n  for (i=0; i<vc; i++)\n  { h = lf->h[ce[i]];\n    if ((h>0) && ((hmin==0)|(h<hmin))) hmin = h;\n  }\n\n  is = 0;\n  for (i=0; i<d; i++)\n  { le[i] = (ur[i]-ll[i])/lf->sca[i];\n    if ((lf->sty[i]==STCPAR) || (hmin==0))\n      score[i] = 2*(ur[i]-ll[i])/(lf->fl[i+d]-lf->fl[i]);\n    else\n      score[i] = le[i]/hmin;\n    if (score[i]>score[is]) is = i;\n  }\n  if (lf->dp[DCUT]<score[is]) return(is);\n  return(-1);\n}\n\n/*\n  recursively grow the tree structure, begining with the parent cell.\n*/\nvoid atree_grow(des,lf,ce,ct,term,ll,ur)\ndesign *des;\nlfit *lf;\nINT *ce, *ct, *term;\ndouble *ll, *ur;\n{ INT i, i0, i1, d, vc, ns, tk, nce[1024], pv;\n  double le[MXDIM], z;\n  d = lf->mi[MDIM]; vc = 1<<d;\n\n  /* does this cell need splitting?\n     If not, wrap up and return.\n  */\n  ns = atree_split(lf,ce,le,ll,ur);\n  if (ns==-1)\n  { if (ct != NULL) /* reconstructing terminal cells */\n    { for (i=0; i<vc; i++) term[*ct*vc+i] = ce[i];\n      (*ct)++;\n    }\n    return;\n  }\n\n  /* split the cell at the midpoint on side ns */\n  tk = 1<<ns;\n  for (i=0; i<vc; i++)\n  { if ((i&tk)==0) nce[i] = ce[i];\n    else\n    { i0 = ce[i];\n      i1 = ce[i-tk];\n      pv = (lf->sty[i]!=STCPAR) &&\n           (le[ns] < (lf->dp[DCUT]*MIN(lf->h[i0],lf->h[i1])));\n      nce[i] = newsplit(des,lf,i0,i1,pv);\n      if (lf_error) return;\n    }\n  }\n  z = ur[ns]; ur[ns] = (z+ll[ns])/2;\n  atree_grow(des,lf,nce,ct,term,ll,ur);\n  if (lf_error) return;\n  ur[ns] = z;\n  for (i=0; i<vc; i++)\n    nce[i] = ((i&tk)== 0) ? nce[i+tk] : ce[i];\n  z = ll[ns]; ll[ns] = (z+ur[ns])/2;\n  atree_grow(des,lf,nce,ct,term,ll,ur);\n  ll[ns] = z;\n}\n\nvoid atree_start(des,lf)\ndesign *des;\nlfit *lf;\n{ INT i, j, vc, d, ncm, nvm, k;\n  double ll[MXDIM], ur[MXDIM];\n\n  d = lf->mi[MDIM];\n  atree_guessnv(&nvm,&ncm,&vc,lf->dp,lf->mi);\n  trchck(lf,nvm,ncm,d,des->p,vc);\n\n  /* Set the lower left, upper right limits. */\n  for (j=0; j<d; j++)\n  { ll[j] = lf->fl[j];\n    ur[j] = lf->fl[j+d];\n  }\n\n  /* Set the initial cell; fit at the vertices. */\n  for (i=0; i<vc; i++)\n  { j = i;\n    for (k=0; k<d; ++k)\n    { evptx(lf,i,k) = (j%2) ? ur[k] : ll[k];\n      j >>= 1;\n    }\n    lf->ce[i] = i;\n    des->vfun(des,lf,i);\n    if (lf_error) return;\n    lf->s[i] = 0;\n  }\n  lf->nv = vc;\n\n  /* build the tree */\n  atree_grow(des,lf,lf->ce,NULL,NULL,ll,ur);\n  lf->nce = 1;\n}\n\ndouble atree_int(tr,x,what)\nlfit *tr;\ndouble *x;\nINT what;\n{ double vv[64][64], *ll, *ur, h, xx[MXDIM];\n  INT d, i, lo, tk, ns, nv, nc, vc, ce[64];\n  d = tr->mi[MDIM];\n  vc = 1<<tr->mi[MDIM];\n  for (i=0; i<vc; i++)\n  { setzero(vv[i],vc);\n    nc = exvval(tr,vv[i],i,d,what,1);\n    ce[i] = tr->ce[i];\n  }\n  ns = 0;\n  while(ns!=-1)\n  { ll = evpt(tr,ce[0]); ur = evpt(tr,ce[vc-1]);\n    ns = atree_split(tr,ce,xx,ll,ur);\n    if (ns!=-1)\n    { tk = 1<<ns;\n      h = ur[ns]-ll[ns];\n      lo = (2*(x[ns]-ll[ns])) < h;\n      for (i=0; i<vc; i++) if ((tk&i)==0)\n      { nv = newsplit((design *)NULL,tr,ce[i],ce[i+tk],0);\n        if (lf_error) return(0.0);\n        if (lo)\n        { ce[i+tk] = nv;\n          if (tr->s[nv]) exvvalpv(vv[i+tk],vv[i],vv[i+tk],d,ns,h,nc);\n                    else exvval(tr,vv[i+tk],nv,d,what,1);\n        }\n        else\n        { ce[i] = nv;\n          if (tr->s[nv]) exvvalpv(vv[i],vv[i],vv[i+tk],d,ns,h,nc);\n                    else exvval(tr,vv[i],nv,d,what,1);\n      } }\n  } }\n  ll = evpt(tr,ce[0]); ur = evpt(tr,ce[vc-1]);\n  return(rectcell_interp(x,vdptr(tr->xxev),vv,ll,ur,d,nc));\n}\n"
  },
  {
    "path": "src/locfit/ev_interp.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\ndouble linear_interp(h,d,f0,f1)\ndouble h, d, f0, f1;\n{ if (d==0) return(f0);\n  return( ( (d-h)*f0 + h*f1 ) / d );\n}\n\nvoid hermite2(x,z,phi)\ndouble x, z, *phi;\n{ double h;\n  if (z==0)\n  { phi[0] = 1.0; phi[1] = phi[2] = phi[3] = 0.0;\n    return;\n  }\n  h = x/z;\n  if (h<0)\n  { phi[0] = 1; phi[1] = 0;\n    phi[2] = h; phi[3] = 0;\n    return;\n  }\n  if (h>1)\n  { phi[0] = 0; phi[1] = 1;\n    phi[2] = 0; phi[3] = h-1;\n    return;\n  }\n  phi[1] = h*h*(3-2*h);\n  phi[0] = 1-phi[1];\n  phi[2] = h*(1-h)*(1-h);\n  phi[3] = h*h*(h - 1);\n}\n\ndouble cubic_interp(h,f0,f1,d0,d1)\ndouble h, f0, f1, d0, d1;\n{ double phi[4];\n  hermite2(h,1.0,phi);\n  return(phi[0]*f0+phi[1]*f1+phi[2]*d0+phi[3]*d1);\n}\n\ndouble cubintd(h,f0,f1,d0,d1)\ndouble h, f0, f1, d0, d1;\n{ double phi[4];\n  phi[1] = 6*h*(1-h);\n  phi[0] = -phi[1];\n  phi[2] = (1-h)*(1-3*h);\n  phi[3] = h*(3*h-2);\n  return(phi[0]*f0+phi[1]*f1+phi[2]*d0+phi[3]*d1);\n}\n\n/*\n  interpolate over a rectangular cell.\n    x = interpolation point. \n    xev = evaluation points (do I need this?)\n    vv = array of vertex values.\n    ll = lower left corner.\n    ur = upper right corner.\n    d = dimension.\n    nc = no of coefficients.\n*/\ndouble rectcell_interp(x,xev,vv,ll,ur,d,nc)\ndouble *x, *xev, vv[64][64], *ll, *ur;\nINT d, nc;\n{ double phi[4];\n  INT i, j, k, tk;\n\n  tk = 1<<d;\n  for (i=0; i<tk; i++) if (vv[i][0]==NOSLN) return(NOSLN);\n\n  /* no derivatives - use multilinear interpolation */\n  if (nc==1)\n  { for (i=d-1; i>=0; i--)\n    { tk = 1<<i;\n      for (j=0; j<tk; j++)\n        vv[j][0] = linear_interp(x[i]-ll[i],ur[i]-ll[i],vv[j][0],vv[j+tk][0]);\n    }\n    return(vv[0][0]);\n  }\n\n  /* with derivatives -- use cubic */\n  if (nc==d+1)\n  { for (i=d-1; i>=0; i--)\n    { hermite2(x[i]-ll[i],ur[i]-ll[i],phi);\n      tk = 1<<i;\n      phi[2] *= ur[i]-ll[i];\n      phi[3] *= ur[i]-ll[i];\n      for (j=0; j<tk; j++)\n      { vv[j][0] = phi[0]*vv[j][0] + phi[1]*vv[j+tk][0]\n                 + phi[2]*vv[j][i+1] + phi[3]*vv[j+tk][i+1];\n        for (k=1; k<=i; k++)\n          vv[j][k] = phi[0]*vv[j][k] + phi[1]*vv[j+tk][k];\n      }\n    }\n    return(vv[0][0]); \n  }\n\n  /* with all coefs -- use multicubic */\n  for (i=d-1; i>=0; i--)\n  { hermite2(x[i]-ll[i],ur[i]-ll[i],phi);\n    tk = 1<<i;\n    phi[2] *= ur[i]-ll[i];\n    phi[3] *= ur[i]-ll[i];\n    for (j=0; j<tk; j++)\n      for (k=0; k<tk; k++)\n        vv[j][k] = phi[0]*vv[j][k] + phi[1]*vv[j+tk][k]\n                 + phi[2]*vv[j][k+tk] + phi[3]*vv[j+tk][k+tk];\n  }\n  return(vv[0][0]);\n}\n\nINT exvval(lf,vv,nv,d,what,z)\nlfit *lf;\ndouble *vv;\nINT nv, d, what, z;\n{ INT i, k;\n  double *values;\n  k = (z) ? 1<<d : d+1;\n  for (i=1; i<k; i++) vv[i] = 0.0;\n  switch(what)\n  { case PCOEF:\n      values = lf->coef;\n      break;\n    case PVARI:\n    case PNLX:\n      values = lf->nlx;\n      break;\n    case PT0:\n      values = lf->t0;\n      break;\n    case PBAND:\n      vv[0] = lf->h[nv];\n      return(1);\n    case PDEGR:\n      vv[0] = lf->deg[nv];\n      return(1);\n    case PLIK:\n      vv[0] = lf->lik[nv];\n      return(1);\n    case PRDF:\n      vv[0] = lf->lik[2*lf->nvm+nv];\n      return(1);\n    default:\n      ERROR((\"Invalid what in exvval\"));\n      return(0);\n  }\n  vv[0] = values[nv];\n  if ((lf->mi[MDEG]==0) && (lf->mi[MDC]==0))return(1);\n  if (z)\n  { for (i=0; i<d; i++) vv[1<<i] = values[(i+1)*lf->nvm+nv];\n    return(1<<d);\n  }\n  else\n  { for (i=1;i<=d; i++) vv[i] = values[i*lf->nvm+nv];\n    return(d+1);\n  }\n}\n\nvoid exvvalpv(vv,vl,vr,d,k,dl,nc)\ndouble *vv, *vl, *vr, dl;\nINT d, k, nc;\n{ INT i, tk, td;\n  double f0, f1;\n  if (nc==1)\n  { vv[0] = (vl[0]+vr[0])/2;\n    return;\n  }\n  tk = 1<<k;\n  td = 1<<d;\n  for (i=0; i<td; i++) if ((i&tk)==0)\n  { f0 = (vl[i]+vr[i])/2 + dl*(vl[i+tk]-vr[i+tk])/8;\n    f1 = 1.5*(vr[i]-vl[i])/dl - (vl[i+tk]+vr[i+tk])/4;\n    vv[i] = f0;\n    vv[i+tk] = f1;\n  }\n} \n\ndouble gridint(tr,x,what)\nlfit *tr;\ndouble *x;\nINT what;\n{ INT d, i, j, jj, v[MXDIM], vc, z0, sk, nce[1024], nc;\n  double *ll, *ur, vv[64][64];\n  d = tr->mi[MDIM];\n  ll = evpt(tr,0); ur = evpt(tr,tr->nv-1);\n  z0 = 0; vc = 1<<d;\n  for (j=d-1; j>=0; j--)\n  { v[j] = (INT)((tr->mg[j]-1)*(x[j]-ll[j])/(ur[j]-ll[j]));\n    if (v[j]<0) v[j]=0;\n    if (v[j]>=tr->mg[j]-1) v[j] = tr->mg[j]-2;\n    z0 = z0*tr->mg[j]+v[j];\n  }\n  nce[0] = z0; nce[1] = z0+1; sk = jj = 1; \n    memset(nce, 0, sizeof(nce));\n  for (i=1; i<d; i++)\n  { sk *= tr->mg[i-1];\n    jj<<=1;\n    for (j=0; j<jj; j++)\n      nce[j+jj] = nce[j]+sk;\n  }\n    nc = 0;\n  for (i=0; i<vc; i++)\n    nc = exvval(tr,vv[i],nce[i],d,what,1);\n  ll = evpt(tr,nce[0]);\n  ur = evpt(tr,nce[vc-1]);\n  return(rectcell_interp(x,vdptr(tr->xxev),vv,ll,ur,d,nc));\n}\n\ndouble fitpint(lf,x,what,i)\nlfit *lf;\ndouble *x;\nINT what, i;\n{ double vv[1+MXDIM];\n  exvval(lf,vv,i,lf->mi[MDIM],what,0);\n  return(vv[0]);\n}\n\ndouble dointpointpf(lf,des,x,what)\nlfit *lf;\ndesign *des;\ndouble *x;\nINT what;\n{ locfit(lf,des,0.0,0);\n  if (what==PCOEF) return(des->cf[0]);\n  if ((what==PNLX)|(what==PT0)) return(sqrt(comp_infl(lf,des)));\n  ERROR((\"dointpointpf: invalid what\"));\n  return(0.0);\n}\n\ndouble xbarint(lf,x,what)\nlfit *lf;\ndouble *x;\nINT what;\n{ INT i, nc;\n  double vv[1+MXDIM], f;\n  nc = exvval(lf,vv,0,lf->mi[MDIM],what,0);\n  f = vv[0];\n  if (nc>1)\n    for (i=0; i<lf->mi[MDIM]; i++)\n      f += vv[i+1]*(x[i]-evptx(lf,0,i));\n  return(f);\n}\n\ndouble dointpoint(lf,des,x,what,ev,j)\nlfit *lf;\ndesign *des;\ndouble *x;\nINT what, ev, j;\n{ double xf, f;\n  INT i;\n  for (i=0; i<lf->mi[MDIM]; i++) if (lf->sty[i]==STANGL)\n  { xf = floor(x[i]/(2*PI*lf->sca[i]));\n    x[i] -= xf*2*PI*lf->sca[i];\n  }\n    f = 0;\n  if (ident==1) return(dointpointpf(lf,des,x,what));\n  switch(ev)\n  { case EGRID: f = gridint(lf,x,what); break;\n    case EKDTR: f = kdtre_int(lf,x,what); break;\n    case ETREE: f = atree_int(lf,x,what); break;\n    case EPHULL: f = triang_int(lf,x,what); break;\n    case EFITP: f = fitpint(lf,x,what,j); break;\n    case EXBAR: f = xbarint(lf,x,what); break;\n    case ENONE: f = 0; break;\n    default: ERROR((\"dointpoint: cannot interpolate this structure\"));\n  }\n  if (((what==PT0)|(what==PNLX)) && (f<0)) f = 0.0;\n  f += addparcomp(lf,x,what);\n  return(f);\n}\n"
  },
  {
    "path": "src/locfit/ev_kdtre.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *   Routines for building and interpolating the kd tree.\n *   Initially, this started from the loess code.\n *\n *   Todo: EKDCE isn't working.\n */\n\n#include \"local.h\"\n\nvoid newcell();\nstatic INT nterm;\n\nvoid kdtre_guessnv(nvm,ncm,vc,dp,mi)\ndouble *dp;\nINT *nvm, *ncm, *vc, *mi;\n{ int k;\n  if (mi[MEV] == EKDTR)\n  { nterm = (INT) (dp[DCUT]/4 * mi[MN] * MIN(dp[DALP],1.0) );\n    k = 2*mi[MN]/nterm;\n    *vc = 1<<mi[MDIM];\n    *ncm = 2*k+1;\n    *nvm = (k+2)**vc/2;\n    return;\n  }\n  if (mi[MEV] == EKDCE)\n  { nterm = (INT) (mi[MN] * dp[DALP]);\n    *vc = 1;\n    *nvm = 1+(INT)(2*mi[MN]/nterm);\n    *ncm = 2**nvm+1;\n    return;\n  }\n  *nvm = *ncm = *vc = 0;\n  return;\n}\n\n/*\n  Split x[pi[l..r]] into two equal sized sets.\n\n  Let m=(l+r)/2.\n  At return,\n    x[pi[l..m]] < x[pi[m+1..r]].\n    Assuming no ties:\n      If l+r is odd, the sets have the same size.\n      If l+r is even, the low set is larger by 1.\n    If there are ties, all ties go in the low set.\n*/      \nint ksmall(l, r, m, x, pi)\nINT l, r, m, *pi;\ndouble *x;\n{\n  int il, ir, jl, jr;\n  double t;\n\n\n  while(l<r)\n  { t = x[pi[m]];\n\n    /*\n      permute the observations so that\n        x[pi[l..il]] < t <= x[pi[ir..r]].\n    */\n    ir = l; il = r;\n    while (ir<il)\n    { while ((ir<=r) && (x[pi[ir]] < t)) ir++;\n      while ((il>=l) && (x[pi[il]]>= t)) il--;\n      if (ir<il) ISWAP(pi[ir],pi[il]);\n    }\n\n    /*\n      move  = t to the middle:\n        x[pi[l..il]]  < t\n        x[pi[jl..jr]] = t\n        x[pi[ir..r]] > t\n    */\n    jl = ir; jr = r;\n    while (ir<jr)\n    { while ((ir<=r)  && (x[pi[ir]]== t)) ir++;\n      while ((jr>=jl) && (x[pi[jr]] > t)) jr--;\n      if (ir<jr) ISWAP(pi[ir],pi[jr]);\n    }\n\n    /*\n      we're done if m is in the middle, jl <= m <= jr.\n    */\n    if ((jl<=m) & (jr>=m)) return(jr);\n\n    /*\n      update l or r.\n    */\n    if (m>=ir) l = ir;\n    if (m<=il) r = il;\n  }\n  if (l==r) return(l);\n  ERROR((\"ksmall failure\"));\n  return(0);\n}\n\nINT terminal(tr,p,pi,fc,d,m,split_val)\nlfit *tr;\nINT p, *pi, d, fc, *m;\ndouble *split_val;\n{ INT i, k, lo, hi, split_var;\n  double max, min, score, max_score, t;\n\n  /*\n    if there are fewer than fc points in the cell, this cell\n    is terminal.\n  */\n  lo = tr->lo[p]; hi = tr->hi[p];\n  if (hi-lo < fc) return(-1);\n\n  /* determine the split variable */\n  max_score = 0.0; split_var = 0;\n  for (k=0; k<d; k++)\n  { max = min = datum(tr, k, pi[lo]);\n    for (i=lo+1; i<=hi; i++)\n    { t = datum(tr,k,pi[i]);\n      if (t<min) min = t;\n      if (t>max) max = t;\n    }\n    score = (max-min) / tr->sca[k];\n    if (score > max_score)\n    { max_score = score;\n      split_var = k;\n    }\n  }\n  if (max_score==0) /* all points in the cell are equal */\n    return(-1);\n\n  *m = ksmall(lo,hi,(lo+hi)/2, dvari(tr,split_var), pi);\n  *split_val = datum(tr, split_var, pi[*m]);\n\n  if (*m==hi) /* all observations go lo */\n    return(-1);\n  return(split_var);\n}\n\nvoid kdtre_start(des,tr)\ndesign *des;\nlfit *tr;\n{ INT i, j, vc, d, nc, nv, ncm, nvm, k, m, n, p, *pi;\n  double sv;\n  d = tr->mi[MDIM]; n = tr->mi[MN]; pi = des->ind;\n  kdtre_guessnv(&nvm,&ncm,&vc,tr->dp,tr->mi);\n  trchck(tr,nvm,ncm,d,des->p,vc);\n\n  nv = 0;\n  if (tr->mi[MEV] != EKDCE)\n  { for (i=0; i<vc; i++)\n    { j = i;\n      for (k=0; k<d; ++k)\n      { evptx(tr,i,k) = tr->fl[d*(j%2)+k];\n        j >>= 1;\n      }\n    }\n    nv = vc;\n    for (j=0; j<vc; j++) tr->ce[j] = j;\n  }\n\n  for (i=0; i<n; i++) pi[i] = i;\n  p = 0; nc = 1;\n  tr->lo[p] = 0; tr->hi[p] = n-1;\n  tr->s[p] = -1;\n  while (p<nc)\n  { k = terminal(tr,p,pi,nterm,d,&m,&sv);\n    if (k>=0)\n    {\n      if ((ncm<nc+2) | (2*nvm<2*nv+vc))\n      { WARN((\"Insufficient space for full tree\"));\n        tr->nce = nc; tr->nv = nv;\n        return;\n      }\n\n      /* new lo cell has obsn's tr->lo[p]..m */\n      tr->lo[nc] = tr->lo[p];\n      tr->hi[nc] = m;\n      tr->s[nc] = -1;\n\n      /* new hi cell has obsn's m+1..tr->hi[p] */\n      tr->lo[nc+1] = m+1;\n      tr->hi[nc+1] = tr->hi[p];\n      tr->s[nc+1] = -1;\n\n      /* cell p is split on variable k, value sv */\n      tr->s[p] = k;\n      tr->sv[p] = sv;\n      tr->lo[p] = nc; tr->hi[p] = nc+1;\n\n      nc=nc+2; i = nv;\n\n      /* now compute the new vertices. */\n      if (tr->mi[MEV] != EKDCE)\n        newcell(&nv,vc,vdptr(tr->xxev), d, k, sv,\n             &tr->ce[p*vc], &tr->ce[(nc-2)*vc], &tr->ce[(nc-1)*vc]);\n\n    }\n    else if (tr->mi[MEV]==EKDCE) /* new vertex at cell center */\n    { sv = 0;\n      for (i=0; i<d; i++) evptx(tr,nv,i) = 0;\n      for (j=tr->lo[p]; j<=tr->hi[p]; j++)\n      { sv += prwt(tr,pi[j]);\n        for (i=0; i<d; i++)\n          evptx(tr,nv,i) += datum(tr,i,pi[j])*prwt(tr,pi[j]);\n      }\n      for (i=0; i<d; i++) evptx(tr,nv,i) /= sv;\n      tr->mi[MN] = tr->hi[p]-tr->lo[p]+1;\n      des->ind = &pi[tr->lo[p]];\n      des->vfun(des,tr,nv);\n      tr->mi[MN] = n; des->ind = pi;\n      nv++;\n    }\n    p++;\n  }\n\n  /* We've built the tree. Now do the fitting. */\n  if (tr->mi[MEV]==EKDTR)\n    for (i=0; i<nv; i++) des->vfun(des,tr,i);\n\n  tr->nce = nc; tr->nv = nv;\n  return;\n}\n\nvoid newcell(nv,vc,xev, d, k, split_val, cpar, clef, crig)\ndouble *xev, split_val;\nINT *nv, vc, d, k, *cpar, *clef, *crig;\n{ INT i, ii, j, j2, tk, match;\n  tk = 1<<k;\n  for (i=0; i<vc; i++)\n  { if ((i&tk) == 0)\n    { for (j=0; j<d; j++) xev[*nv*d+j] = xev[d*cpar[i]+j];\n      xev[*nv*d+k] = split_val;\n      match = 0; j = vc; /* no matches in first vc points */\n      while ((j<*nv) && (!match))\n      { j2 = 0;\n        while ((j2<d) && (xev[*nv*d+j2] == xev[j*d+j2])) j2++;\n        match = (j2==d);\n        if (!match) j++;\n      }\n      ii = i+tk;\n      clef[i] = cpar[i];\n      clef[ii]= crig[i] = j;\n      crig[ii]= cpar[ii];\n      if (!match) (*nv)++;\n    }\n  }\n  return;\n}\n\nextern void hermite2();\n\ndouble blend(lf,s,x,ll,ur,j,nt,t,what)\nlfit *lf;\ndouble s, *x, *ll, *ur;\nINT j, nt, *t, what;\n{ INT k, k1, m, nc, j0, j1, *ce;\n  double v0, v1, xibar, g0[3], g1[3], gg[4], gp[4], phi[4];\n  ce = lf->ce;\n  for (k=0; k<4; k++)  /* North South East West */\n  { k1 = (k>1);\n    v0 = ll[k1]; v1 = ur[k1];\n    j0 = ce[j+2*(k==0)+(k==2)];\n    j1 = ce[j+3-2*(k==1)-(k==3)];\n    xibar = (k%2==0) ? ur[k<2] : ll[k<2];\n    m = nt;\n    while ((m>=0) && ((lf->s[t[m]] != (k<=1)) | (lf->sv[t[m]] != xibar))) m--;\n    if (m >= 0)\n    { m = (k%2==1) ? lf->lo[t[m]] : lf->hi[t[m]];\n      while (lf->s[m] != -1)\n        m = (x[lf->s[m]] < lf->sv[m]) ? lf->lo[m] : lf->hi[m];\n      if (v0 < evptx(lf,ce[4*m+2*(k==1)+(k==3)],k1))\n      { j0 = ce[4*m+2*(k==1)+(k==3)];\n        v0 = evptx(lf,j0,k1);\n      }\n      if (evptx(lf,ce[4*m+3-2*(k==0)-(k==2)],k1) < v1)\n      { j1 = ce[4*m+3-2*(k==0)-(k==2)];\n        v1 = evptx(lf,j1,k1);\n      }\n    }\n    nc = exvval(lf,g0,j0,2,what,0);\n    nc = exvval(lf,g1,j1,2,what,0);\n    if (nc==1)\n      gg[k] = linear_interp((x[(k>1)]-v0),v1-v0,g0[0],g1[0]);\n    else\n    { hermite2(x[(k>1)]-v0,v1-v0,phi);\n      gg[k] = phi[0]*g0[0]+phi[1]*g1[0]+(phi[2]*g0[1+k1]+phi[3]*g1[1+k1])*(v1-v0);\n      gp[k] = phi[0]*g0[2-k1] + phi[1]*g1[2-k1];\n    }\n  }\n  s = -s;\n  if (nc==1)\n    for (k=0; k<2; k++)\n      s += linear_interp(x[k]-ll[k],ur[k]-ll[k],gg[3-2*k],gg[2-2*k]);\n    else\n    for (k=0; k<2; k++) /* EW NS */\n    { hermite2(x[k]-ll[k],ur[k]-ll[k],phi);\n      s += phi[0]*gg[3-2*k] + phi[1]*gg[2-2*k]\n          +(phi[2]*gp[3-2*k] + phi[3]*gp[2-2*k]) * (ur[k]-ll[k]);\n    }\n  return(s);\n}\n\ndouble kdtre_int(lf,x,what)\nlfit *lf;\ndouble *x;\nINT what;\n{ INT d, vc, k, t[20], nt, nc, *ce, j;\n  double *ll, *ur, ff, vv[64][64];\n  d = lf->mi[MDIM];\n  vc = lf->vc;\n  if (d > 6) ERROR((\"d too large in kdint\"));\n\n  /* descend the tree to find the terminal cell */\n  nt = 0; t[nt] = 0; k = 0;\n  while (lf->s[k] != -1)\n  { nt++;\n    if (nt>=20) { ERROR((\"Too many levels in kdint\")); return(NOSLN); }\n    k = t[nt] = (x[lf->s[k]] < lf->sv[k]) ? lf->lo[k] : lf->hi[k];\n  }\n\n  ce = &lf->ce[k*vc];\n  ll = evpt(lf,ce[0]);\n  ur = evpt(lf,ce[vc-1]);\n  nc = 0;\n  for (j=0; j<vc; j++) nc = exvval(lf,vv[j],ce[j],d,what,0);\n  ff = rectcell_interp(x,NULL,vv,ll,ur,d,nc);\n\n  if (d==2) ff = blend(lf,ff,x,ll,ur,k*vc,nt,t,what);\n  return(ff);\n}\n"
  },
  {
    "path": "src/locfit/ev_main.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\nvoid kdtre_guessnv(int* nvm, int* ncm, int* vc, double* dp, int* mi);\n\nINT cvi=-1;\n\n/*\n * the C version has its own createvar, file src-c/vari.c.\n * For other versions, use the simple function here.\n */\n#ifndef CVERSION\nvari *createvar(name,type,n,mode)\nvarname name;\nINT type, n, mode;\n{ vari *v;\nprintf(\"creating variable\\n\");\n  v = (vari *)malloc(sizeof(vari));\n  vdptr(v) = (double *)calloc( vlength(v)=n ,\n              (mode==VDOUBLE) ? sizeof(double) : sizeof(INT));\n  return(v);\n}\n#endif\n\n/*\n *  guessnv is used to guess the number of vertices etc in the\n *  evaluation structure.\n */\nvoid guessnv(nvm,ncm,vc,dp,mi)\ndouble *dp;\nint *nvm, *ncm, *vc, *mi;\n{ switch(mi[MEV])\n  { case ETREE:\n      atree_guessnv(nvm,ncm,vc,dp,mi);\n      return;\n    case EPHULL:\n      *nvm = *ncm = mi[MK]*mi[MDIM];\n      *vc = mi[MDIM]+1;\n      return;\n    case EDATA:\n    case ECROS:\n      *nvm = mi[MN];\n      *ncm = *vc = 0;\n      return;\n    case EKDTR:\n    case EKDCE:\n      kdtre_guessnv(nvm,ncm,vc,dp,mi);\n      return;\n    case EXBAR:\n    case ENONE:\n      *nvm = 1;\n      *ncm = *vc = 0;\n      return;\n    case EPRES:\n      /* preset -- leave everything unchanged. */\n      return;\n    default:\n      ERROR((\"guessnv: I don't know this evaluation structure.\"));\n  }\n  return;\n}\n\n/*\n * trchck checks the working space on the lfit structure \n * has space for nvm vertices and ncm cells.\n */\nint lfit_reqd(d,nvm,ncm)\nINT d, nvm, ncm;\n{ return(nvm*(3*d+8)+ncm);\n}\nint lfit_reqi(nvm,ncm,vc)\nINT nvm, ncm, vc;\n{ return(ncm*vc+3*MAX(ncm,nvm));\n}\n\nvoid trchck(tr,nvm,ncm,d,p,vc)\nlfit *tr;\nINT nvm, ncm, d, p, vc;\n{ INT rw, *k;\n  double *z;\n\n  tr->xxev = checkvarlen(tr->xxev,d*nvm,\"_lfxev\",VDOUBLE);\n\n  rw = nvm*(3*d+8)+ncm;\n  tr->tw = checkvarlen(tr->tw,lfit_reqd(d,nvm,ncm),\"_lfwork\",VDOUBLE);\n  z = (double *)vdptr(tr->tw);\n  tr->coef= z; z += nvm*(d+1);\n  tr->nlx = z; z += nvm*(d+1);\n  tr->t0  = z; z += nvm*(d+1);\n  tr->lik = z; z += 3*nvm;\n  tr->h   = z; z += nvm;\n  tr->deg = z; z += nvm;\n  tr->sv  = z; z += ncm;\n  if (z != (double *)vdptr(tr->tw)+rw)\n    WARN((\"trchck: double assign problem\"));\n\n  rw = lfit_reqi(nvm,ncm,vc);\n  tr->iw = checkvarlen(tr->iw,rw,\"_lfiwork\",VINT);\n  k = (INT *)vdptr(tr->iw);\n  tr->ce = k; k += vc*ncm;\n  tr->s  = k; k += MAX(ncm,nvm);\n  tr->lo = k; k += MAX(ncm,nvm);\n  tr->hi = k; k += MAX(ncm,nvm);\n  if (k != (INT *)vdptr(tr->iw)+rw)\n    WARN((\"trchck: int assign problem\"));\n\n  tr->nvm = nvm; tr->ncm = ncm; tr->mi[MDIM] = d; tr->mi[MP] = p; tr->vc = vc;\n}\n\n#ifdef CVERSION\nvoid reassign(lf)\nlfit *lf;\n{ INT i, nvm, ncm, vc, d, k, p, *iw;\n  double *tw, *ntw;\n  setvarname(lf->tw,\"__lfwork\"); /* prevent overwrite */\n  setvarname(lf->iw,\"__lfiwork\");\n  nvm = lf->nvm; ncm = lf->ncm; vc = lf->vc;\n  tw = (double *)vdptr(lf->tw);\n  iw = (INT *)vdptr(lf->iw);\n  d = lf->mi[MDIM];\n  p = lf->mi[MP];\n  trchck(lf,2*nvm,ncm,d,p,vc);\n  ntw = vdptr(lf->tw);\n/*\n  xev is stored in blocks of d. other matrices by blocks on nvm\n*/\n  k = nvm*d;\n  memcpy(vdptr(lf->xxev),tw,k*sizeof(double));\n  tw += k; ntw += 2*k;\n  for (i=0; i<2*p+2*d+6; i++)\n  { memcpy(ntw,tw,nvm*sizeof(double));\n    tw += nvm; ntw += 2*nvm;\n  }\n  k = ncm;       memcpy(lf->sv,tw,k*sizeof(double));   tw += k;\n\n  k = vc*ncm;       memcpy(lf->ce,iw,k*sizeof(INT)); iw += k;\n  k = MAX(ncm,nvm); memcpy(lf->s,iw,k*sizeof(INT));  iw += k;\n  k = MAX(ncm,nvm); memcpy(lf->lo,iw,k*sizeof(INT)); iw += k;\n  k = MAX(ncm,nvm); memcpy(lf->hi,iw,k*sizeof(INT)); iw += k;\n  deletename(\"__lfwork\");\n  deletename(\"__lfiwork\");\n}\n#endif\n\nvoid dataf(des,lf)\ndesign *des;\nlfit *lf;\n{ INT d, i, j, ncm, nv, vc;\n\n  d = lf->mi[MDIM];\n  guessnv(&nv,&ncm,&vc,lf->dp,lf->mi);\n  trchck(lf,nv,0,d,des->p,0);\n\n  for (i=0; i<nv; i++)\n    for (j=0; j<d; j++) evptx(lf,i,j) = datum(lf,j,i);\n  for (i=0; i<nv; i++)\n  { des->vfun(des,lf,i);\n    lf->s[i] = 0;\n  }\n  lf->nv = lf->nvm = nv; lf->nce = 0;\n}\n\nvoid xbarf(des,lf)\ndesign *des;\nlfit *lf;\n{ int i, d, nvm, ncm, vc;\n  d = lf->mi[MDIM];\n  guessnv(&nvm,&ncm,&vc,lf->dp,lf->mi);\n  trchck(lf,1,0,d,des->p,0);\n  for (i=0; i<d; i++) evptx(lf,0,i) = lf->pc.xbar[i];\n  des->vfun(des,lf,0);\n  lf->s[0] = 0;\n  lf->nv = 1; lf->nce = 0;\n}\n\n#ifndef GR\nvoid preset(des,lf)\ndesign *des;\nlfit *lf;\n{ INT i, nv;\n  double *tmp;\n  nv = lf->nvm;\n  tmp = vdptr(lf->xxev);\n  trchck(lf,nv,0,lf->mi[MDIM],des->p,0);\n  lf->xxev->dpr = tmp;\n  for (i=0; i<nv; i++)\n  { \n    des->vfun(des,lf,i);\n    lf->s[i] = 0;\n  }\n  lf->nv = nv; lf->nce = 0;\n}\n#endif\n\nvoid crossf(des,lf)\ndesign *des;\nlfit *lf;\n{ INT d, i, j, n, nv, ncm, vc;\n\n  n = lf->mi[MN]; d = lf->mi[MDIM];\n  guessnv(&nv,&ncm,&vc,lf->dp,lf->mi);\n  trchck(lf,n,0,d,des->p,0);\n\n  for (i=0; i<n; i++)\n    for (j=0; j<d; j++) evptx(lf,i,j) = datum(lf,j,i);\n  for (cvi=0; cvi<n; cvi++)\n  { lf->s[cvi] = 0;\n    des->vfun(des,lf,cvi);\n  }\n  cvi = -1;\n  lf->nv = n; lf->nce = 0; lf->mi[MN] = n;\n}\n\nvoid gridf(des,tr)\ndesign *des;\nlfit *tr;\n{ INT d, i, j, nv, u0, u1, z;\n  nv = 1; d = tr->mi[MDIM];\n  for (i=0; i<d; i++)\n  { if (tr->mg[i]==0)\n      tr->mg[i] = 2+(INT)((tr->fl[i+d]-tr->fl[i])/(tr->sca[i]*tr->dp[DCUT]));\n    nv *= tr->mg[i];\n  }\n  trchck(tr,nv,0,d,des->p,1<<d);\n  for (i=0; i<nv; i++)\n  { z = i;\n    for (j=0; j<d; j++)\n    { u0 = z%tr->mg[j];\n      u1 = tr->mg[j]-1-u0;\n      evptx(tr,i,j) = (tr->mg[j]==1) ? tr->fl[j] :\n                      (u1*tr->fl[j]+u0*tr->fl[j+d])/(tr->mg[j]-1);\n      z = z/tr->mg[j];\n    }\n    tr->s[i] = 0;\n    des->vfun(des,tr,i);\n  }\n  tr->nv = nv; tr->nce = 0;\n}\n\n/*\n  add a new vertex at the midpoint of (x[i0],x[i1]).\n  return the vertex number.\n*/\nINT newsplit(des,lf,i0,i1,pv)\ndesign *des;\nlfit *lf;\nINT i0, i1, pv;\n{ INT i, nv;\n\n  /* first, check to see if the new point already exists */\n  if (i0>i1) ISWAP(i0,i1);\n  nv = lf->nv;\n  for (i=i1+1; i<nv; i++)\n    if ((lf->lo[i]==i0) && (lf->hi[i]==i1)) return(i);\n  \n  /* the point is new. Now check we have space for the new point. */\n  if (nv==lf->nvm)\n  {\n#ifdef CVERSION\n    reassign(lf);\n#else\n    ERROR((\"newsplit: out of vertex space\"));\n    return(-1);\n#endif\n  }\n\n  /* compute the new point, and evaluate the fit */\n  lf->lo[nv] = i0;\n  lf->hi[nv] = i1;\n  for (i=0; i<lf->mi[MDIM]; i++)\n    evptx(lf,nv,i) = (evptx(lf,i0,i)+evptx(lf,i1,i))/2;\n  if (pv) /* pseudo vertex */\n  { lf->h[nv] = (lf->h[i0]+lf->h[i1])/2;\n    lf->s[nv] = 1; /* pseudo-vertex */\n  }\n  else /* real vertex */\n  { des->vfun(des,lf,nv);\n    lf->s[nv] = 0;\n  }\n  lf->nv++;\n\n  return(nv);\n}\n"
  },
  {
    "path": "src/locfit/ev_trian.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\nINT triang_split(tr,ce,le)\nlfit *tr;\ndouble *le;\nINT *ce;\n{ INT d, i, j, k, nts, vc;\n  double di, dfx[MXDIM];\n  nts = 0; d = tr->mi[MDIM]; vc = d+1;\n  for (i=0; i<d; i++)\n    for (j=i+1; j<=d; j++)\n    { for (k=0; k<d; k++)\n        dfx[k] = evptx(tr,ce[i],k)-evptx(tr,ce[j],k);\n      di = rho(dfx,tr->sca,d,KSPH,NULL);\n      le[i*vc+j] = le[j*vc+i] = di/MIN(tr->h[ce[i]],tr->h[ce[j]]);\n      nts = nts || le[i*vc+j]>tr->dp[DCUT];\n    }\n  return(nts);\n}\n\nvoid resort(pv,xev,dig)\ndouble *xev;\nINT *pv, *dig;\n{ double d0, d1, d2;\n  INT i;\n  d0 = d1 = d2 = 0;\n  for (i=0; i<3; i++)\n  { d0 += (xev[3*pv[11]+i]-xev[3*pv[1]+i])*(xev[3*pv[11]+i]-xev[3*pv[1]+i]);\n    d1 += (xev[3*pv[ 7]+i]-xev[3*pv[2]+i])*(xev[3*pv[ 7]+i]-xev[3*pv[2]+i]);\n    d2 += (xev[3*pv[ 6]+i]-xev[3*pv[3]+i])*(xev[3*pv[ 6]+i]-xev[3*pv[3]+i]);\n  }\n  if ((d0<=d1) & (d0<=d2))\n  { dig[0] = pv[1]; dig[1] = pv[11];\n    dig[2] = pv[2]; dig[3] = pv[7];\n    dig[4] = pv[3]; dig[5] = pv[6];\n  }\n  else if (d1<=d2)\n  { dig[0] = pv[2]; dig[1] = pv[7];\n    dig[2] = pv[1]; dig[3] = pv[11];\n    dig[4] = pv[3]; dig[5] = pv[6];\n  }\n  else\n  { dig[0] = pv[3]; dig[1] = pv[6];\n    dig[2] = pv[2]; dig[3] = pv[7];\n    dig[4] = pv[1]; dig[5] = pv[11];\n  }\n}\n\nvoid triang_grow(des,tr,ce,ct,term)\ndesign *des;\nlfit *tr;\nINT *ce, *ct, *term;\n{ double le[(1+MXDIM)*(1+MXDIM)], ml;\n  INT pv[(1+MXDIM)*(1+MXDIM)], nce[1+MXDIM], d, i, j, im, jm, vc, dig[6];\n  if (lf_error) return;\n  d = tr->mi[MDIM]; vc = d+1;\n  if (!triang_split(tr,ce,le))\n  { if (ct != NULL)\n    { for (i=0; i<vc; i++) term[*ct*vc+i] = ce[i];\n      (*ct)++;\n    }\n    return;\n  }\n  if (d>3)\n  { ml = 0;\n    for (i=0; i<d; i++)\n      for (j=i+1; j<vc; j++)\n        if (le[i*vc+j]>ml) { ml = le[i*vc+j]; im = i; jm = j; }\n    pv[0] = newsplit(des,tr,ce[im],ce[jm],0);\n    for (i=0; i<vc; i++) nce[i] = ce[i];\n    nce[im] = pv[0]; triang_grow(des,tr,nce,ct,term); nce[im] = ce[im];\n    nce[jm] = pv[0]; triang_grow(des,tr,nce,ct,term);\n    return;\n  }\n\n  for (i=0; i<d; i++)\n    for (j=i+1; j<=d; j++)\n      pv[i*vc+j] = pv[j*vc+i]\n        = newsplit(des,tr,ce[i],ce[j],le[i*vc+j]<=tr->dp[DCUT]);\n  for (i=0; i<=d; i++) /* corners */\n  { for (j=0; j<=d; j++) nce[j] = (j==i) ? ce[i] : pv[i*vc+j];\n    triang_grow(des,tr,nce,ct,term);\n  }\n  \n  if (d==2) /* center for d=2 */\n  { nce[0] = pv[5]; nce[1] = pv[2]; nce[2] = pv[1];\n    triang_grow(des,tr,nce,ct,term);\n  }\n  if (d==3) /* center for d=3 */\n  { resort(pv,vdptr(tr->xxev),dig);\n    nce[0] = dig[0]; nce[1] = dig[1];\n    nce[2] = dig[2]; nce[3] = dig[4]; triang_grow(des,tr,nce,ct,term);\n    nce[2] = dig[5]; nce[3] = dig[3]; triang_grow(des,tr,nce,ct,term);\n    nce[2] = dig[2]; nce[3] = dig[5]; triang_grow(des,tr,nce,ct,term);\n    nce[2] = dig[4]; nce[3] = dig[3]; triang_grow(des,tr,nce,ct,term);\n  }\n  if (d==1) return;\n}\n\nvoid triang_descend(tr,xa,ce)\nlfit *tr;\ndouble *xa;\nINT *ce;\n{ double le[(1+MXDIM)*(1+MXDIM)], ml;\n  INT d, vc, i, j, pv[(1+MXDIM)*(1+MXDIM)], im = 0, jm = 0;\n  design *des;\n  des = NULL;\n  if (!triang_split(tr,ce,le)) return;\n  d = tr->mi[MDIM]; vc = d+1;\n\n  if (d>3) /* split longest edge */\n  { ml = 0;\n    for (i=0; i<d; i++)\n      for (j=i+1; j<vc; j++)\n        if (le[i*vc+j]>ml) { ml = le[i*vc+j]; im = i; jm = j; }\n    pv[0] = newsplit(des,tr,ce[im],ce[jm],0);\n    if (xa[im]>xa[jm])\n    { xa[im] -= xa[jm]; xa[jm] *= 2; ce[jm] = pv[0]; }\n    else\n    { xa[jm] -= xa[im]; xa[im] *= 2; ce[im] = pv[0]; }\n    triang_descend(tr,xa,ce);\n    return;\n  }\n\n  for (i=0; i<d; i++)\n    for (j=i+1; j<=d; j++)\n      pv[i*vc+j] = pv[j*vc+i]\n        = newsplit(des,tr,ce[i],ce[j],le[i*d+j]<=tr->dp[DCUT]);\n  for (i=0; i<=d; i++) if (xa[i]>=0.5) /* in corner */\n  { for (j=0; j<=d; j++)\n    { if (i!=j) ce[j] = pv[i*vc+j];\n      xa[j] = 2*xa[j];\n    }\n    xa[i] -= 1;\n    triang_descend(tr,xa,ce);\n    return;\n  }\n  if (d==1) { ERROR((\"weights sum to < 1\")); }\n  if (d==2) /* center */\n  { ce[0] = pv[5]; xa[0] = 1-2*xa[0];\n    ce[1] = pv[2]; xa[1] = 1-2*xa[1];\n    ce[2] = pv[1]; xa[2] = 1-2*xa[2];\n    triang_descend(tr,xa,ce);\n  }\n  if (d==3) /* center */\n  { double z; INT dig[6];\n    resort(pv,vdptr(tr->xxev),dig);\n    ce[0] = dig[0]; ce[1] = dig[1];\n    xa[0] *= 2; xa[1] *= 2; xa[2] *= 2; xa[3] *= 2;\n    if (xa[0]+xa[2]>=1)\n    { if (xa[0]+xa[3]>=1)\n      { ce[2] = dig[2]; ce[3] = dig[4];\n        z = xa[0];\n        xa[3] += z-1; xa[2] += z-1; xa[0] = xa[1]; xa[1] = 1-z;\n      }\n      else\n      { ce[2] = dig[2]; ce[3] = dig[5];\n        z = xa[3]; xa[3] = xa[1]+xa[2]-1; xa[1] = z;\n        z = xa[2]; xa[2] += xa[0]-1; xa[0] = 1-z;\n    } }\n    else\n    { if (xa[1]+xa[2]>=1)\n      { ce[2] = dig[5]; ce[3] = dig[3];\n        xa[1] = 1-xa[1]; xa[2] -= xa[1]; xa[3] -= xa[1];\n      }\n      else\n      { ce[2] = dig[4]; ce[3] = dig[3];\n        z = xa[3]; xa[3] += xa[1]-1; xa[1] = xa[2];\n        xa[2] = z+xa[0]-1; xa[0] = 1-z;\n    } }\n    triang_descend(tr,xa,ce);\n} }\n\nvoid covrofdata(lf,V,mn) /* covar of data; mean in mn */\nlfit *lf;\ndouble *V, *mn;\n{ INT d, i, j, k;\n  double s;\n  s = 0; d = lf->mi[MDIM];\n  for (i=0; i<d*d; i++) V[i] = 0;\n  for (i=0; i<lf->mi[MN]; i++)\n  { s += prwt(lf,i);\n    for (j=0; j<d; j++)\n      for (k=0; k<d; k++)\n        V[j*d+k] += prwt(lf,i)*(datum(lf,j,i)-mn[j])*(datum(lf,k,i)-mn[k]);\n  }\n  for (i=0; i<d*d; i++) V[i] /= s;\n}\n\nINT intri(x,w,xev,xa,d) /* is x in triangle bounded by xd[0..d-1]? */\ndouble *x, *xev, *xa;\nINT d, *w;\n{ INT i, j;\n  double eps, *r, xd[MXDIM*MXDIM];\n  eps = 1.0e-10;\n  r = &xev[w[d]*d];\n  for (i=0; i<d; i++)\n  { xa[i] = x[i]-r[i];\n    for (j=0; j<d; j++) xd[i*d+j] = xev[w[i]*d+j]-r[j];\n  }\n  solve(xd,xa,d);\n  xa[d] = 1.0;\n  for (i=0; i<d; i++) xa[d] -= xa[i];\n  for (i=0; i<=d; i++) if ((xa[i]<-eps) | (xa[i]>1+eps)) return(0);\n  return(1);\n}\n\nvoid triang_start(des,tr) /* Triangulation with polyhedral start */\ndesign *des;\nlfit *tr;\n{ INT i, j, k, n, d, nc, nvm, ncm, vc, *ce, ed[1+MXDIM];\n  double V[MXDIM*MXDIM], P[MXDIM*MXDIM], sigma, z[MXDIM], xa[1+MXDIM], *xev;\n  xev = vdptr(tr->xxev);\n  d = tr->mi[MDIM]; n = tr->mi[MN]; tr->nv = nc = 0;\n\n  guessnv(&nvm,&ncm,&vc,tr->dp,tr->mi);\n  trchck(tr,nvm,ncm,d,des->p,vc);\n\n  ce = tr->ce;\n  for (j=0; j<d; j++) xev[j] = tr->pc.xbar[j];\n  tr->nv = 1;\n  covrofdata(tr,V,tr->pc.xbar); /* fix this with scaling */\n  eig_dec(V,P,d);\n\n  for (i=0; i<d; i++) /* add vertices +- 2sigma*eigenvect */\n  { sigma = sqrt(V[i*(d+1)]);\n    for (j=0; j<d; j++)\n      xev[tr->nv*d+j] = xev[j]-2*sigma*P[j*d+i];\n    tr->nv++;\n    for (j=0; j<d; j++)\n      xev[tr->nv*d+j] = xev[j]+2*sigma*P[j*d+i];\n    tr->nv++;\n  }\n\n  for (i=0; i<n; i++) /* is point i inside? */\n  { ed[0] = 0;\n    for (j=0; j<d; j++)\n    { z[j] = 0;\n      for (k=0; k<d; k++) z[j] += P[k*d+j]*(datum(tr,k,i)-xev[k]);\n      ed[j+1] = 2*j+1+(z[j]>0);\n      for (k=0; k<d; k++) z[j] = datum(tr,j,i);\n    }\n    k = intri(z,ed,xev,xa,d);\n    if (xa[0]<0)\n    { for (j=1; j<=d; j++)\n        for (k=0; k<d; k++)\n          xev[ed[j]*d+k] = xa[0]*xev[k]+(1-xa[0])*xev[ed[j]*d+k];\n    }\n  }\n\n  nc = 1<<d; /* create initial cells */\n  for (i=0; i<nc; i++)\n  { ce[i*vc] = 0; k = i;\n    for (j=0; j<d; j++)\n    { ce[i*vc+j+1] = 2*j+(k%2)+1;\n      k>>=1;\n    }\n  }\n\n  for (i=0; i<tr->nv; i++)\n  { des->vfun(des,tr,i);\n    if (lf_error) return;\n    tr->s[i] = 0;\n  }\n  for (i=0; i<nc; i++)\n  { for (j=0; j<=d; j++) ed[j] = tr->ce[i*vc+j];\n    triang_grow(des,tr,&tr->ce[i*vc],(INT *)NULL,(INT *)NULL);\n  }\n  tr->nce = nc;\n}\n\ndouble triang_cubicint(v,vv,w,d,nc,xxa)\ndouble *v, *vv, *xxa;\nINT d, *w, nc;\n{ double sa, lb, *vert0, *vert1, *vals0, *vals1, deriv0, deriv1;\n  INT i, j, k;\n  if (nc==1) /* linear interpolate */\n  { sa = 0;\n    for (i=0; i<=d; i++) sa += xxa[i]*vv[i];\n    return(sa);\n  }\n  sa = 1.0;\n    vals0 = NULL;\n  for (j=d; j>0; j--)  /* eliminate v[w[j]] */\n  { lb = xxa[j]/sa;\n    for (k=0; k<j; k++) /* Interpolate edge v[w[k]],v[w[j]] */\n    { vert0 = &v[w[k]*d];\n      vert1 = &v[w[j]*d];\n      vals0 = &vv[k*nc];\n      vals1 = &vv[j*nc];\n      deriv0 = deriv1 = 0;\n      for (i=0; i<d; i++)\n      { deriv0 += (vert1[i]-vert0[i])*vals0[i+1];\n        deriv1 += (vert1[i]-vert0[i])*vals1[i+1];\n      }\n      vals0[0] = cubic_interp(lb,vals0[0],vals1[0],deriv0,deriv1);\n      for (i=1; i<=d; i++)\n        vals0[i] = (1-lb)*((1-lb)*vals0[i]+lb*vals1[i]);\n    }\n    sa -= xxa[j];\n    if (sa<=0) j = 0;\n  }\n    if (vals0)\n      return(vals0[0]);\n    else\n    {\n        fprintf(stderr, \"Warning: vals0 is undefined!\\n\");\n        return 0.0;\n    }\n}\n\ndouble triang_clotoch(xev,vv,ce,p,xxa)\ndouble *xev, *vv, *xxa;\nINT *ce, p;\n{ double cfo[3], cfe[3], cg[9], *va, *vb, *vc,\n    l0, nm[3], na, nb, nc, *xl, *xr, *xz, d0, d1, lb, dlt, gam;\n  INT i, w[3], cfl, cfr;\n  if (p==1)\n    return(xxa[0]*vv[0]+xxa[1]*vv[1]+xxa[2]*vv[2]);\n  if (xxa[2]<=MIN(xxa[0],xxa[1]))\n  { va = &xev[2*ce[0]]; vb = &xev[2*ce[1]]; vc = &xev[2*ce[2]];\n    w[0] = 0; w[1] = 3; w[2] = 6;\n  }\n  else\n  if (xxa[1]<xxa[0])\n  { w[0] = 0; w[1] = 6; w[2] = 3;\n    va = &xev[2*ce[0]]; vb = &xev[2*ce[2]]; vc = &xev[2*ce[1]];\n    lb = xxa[1]; xxa[1] = xxa[2]; xxa[2] = lb;\n  }\n  else\n  { w[0] = 6; w[1] = 3; w[2] = 0;\n    va = &xev[2*ce[2]]; vb = &xev[2*ce[1]]; vc = &xev[2*ce[0]];\n    lb = xxa[0]; xxa[0] = xxa[2]; xxa[2] = lb;\n  }\n  \n/* set cg to values and derivatives on standard triangle */\n  for (i=0; i<3; i++)\n  { cg[3*i] = vv[w[i]];\n    cg[3*i+1] = ((vb[0]-va[0])*vv[w[i]+1]\n                +(vb[1]-va[1])*vv[w[i]+2])/2;  /* df/dx */\n    cg[3*i+2] = ((2*vc[0]-vb[0]-va[0])*vv[w[i]+1]\n                +(2*vc[1]-vb[1]-va[1])*vv[w[i]+2])/2.0; /* sqrt{3} df/dy */\n  }\n  dlt = (vb[0]-va[0])*(vc[1]-va[1])-(vc[0]-va[0])*(vb[1]-va[1]);\n  /* Twice area; +ve if abc antic.wise  -ve is abc c.wise */\n  cfo[0] = (cg[0]+cg[3]+cg[6])/3;\n  cfo[1] = (2*cg[0]-cg[3]-cg[6])/4;\n  cfo[2] = (2*cg[3]-cg[0]-cg[6])/4;\n  na = -cg[1]+cg[2];  /* perp. deriv, rel. length 2 */\n  nb = -cg[4]-cg[5];\n  nc = 2*cg[7];\n  cfo[1] += (nb-nc)/16;\n  cfo[2] += (nc-na)/16;\n  na = -cg[1]-cg[2]/3.0;  /* derivatives back to origin */\n  nb =  cg[4]-cg[5]/3.0;\n  nc =        cg[8]/1.5;\n  cfo[0] -= (na+nb+nc)*7/54;\n  cfo[1] += 13*(nb+nc-2*na)/144;\n  cfo[2] += 13*(na+nc-2*nb)/144;\n  for (i=0; i<3; i++)\n  { /* Outward normals by linear interpolation on original triangle.\n       Convert to outward normals on standard triangle.\n       Actually, computed to opposite corner */\n    switch(i)\n    { case 0: xl = vc; xr = vb; xz = va; cfl = w[2]; cfr = w[1];\n              break;\n      case 1: xl = va; xr = vc; xz = vb; cfl = w[0]; cfr = w[2];\n              break;\n      case 2: xl = vb; xr = va; xz = vc; cfl = w[1]; cfr = w[0];\n              break;\n    }\n    na = xr[0]-xl[0]; nb = xr[1]-xl[1];\n    lb = na*na+nb*nb;\n    d0 = 1.5*(vv[cfr]-vv[cfl]) - 0.25*(na*(vv[cfl+1]+vv[cfr+1])\n         +nb*(vv[cfl+2]+vv[cfr+2]));\n    d1 = 0.5*( na*(vv[cfl+2]+vv[cfr+2])-nb*(vv[cfl+1]+vv[cfr+1]) );\n    l0 = (xz[0]-xl[0])*na+(xz[1]-xl[1])*nb-lb/2;\n    nm[i] = (d1*dlt-l0*d0)/lb;\n  }\n  cfo[0] -= (nm[0]+nm[1]+nm[2])*4/81;\n  cfo[1] += (2*nm[0]-nm[1]-nm[2])/27;\n  cfo[2] += (2*nm[1]-nm[0]-nm[2])/27;\n\n  gam = xxa[0]+xxa[1]-2*xxa[2];\n  if (gam==0) return(cfo[0]);\n  lb = (xxa[0]-xxa[2])/gam;\n  d0 = -2*cg[4]; d1 = -2*cg[1];\n  cfe[0] = cubic_interp(lb,cg[3],cg[0],d0,d1);\n  cfe[1] = cubintd(lb,cg[3],cg[0],d0,d1);\n  cfe[2] = -(1-lb)*(1-2*lb)*cg[5] + 4*lb*(1-lb)*nm[2] - lb*(2*lb-1)*cg[2];\n  d0 = 2*(lb*cfo[1]+(1-lb)*cfo[2]);\n  d1 = (lb-0.5)*cfe[1]+cfe[2]/3.0;\n  return(cubic_interp(gam,cfo[0],cfe[0],d0,d1));\n}\n\nINT triang_getvertexvals(lf,vv,i,what)\nlfit *lf;\ndouble *vv;\nINT i, what;\n{ double dx, P, le, vl[1+MXDIM], vh[1+MXDIM];\n  INT d, il, ih, j, nc;\n  d = lf->mi[MDIM];\n  if (lf->s[i]==0) return(exvval(lf,vv,i,d,what,0));\n\n  il = lf->lo[i]; nc = triang_getvertexvals(lf,vl,il,what);\n  ih = lf->hi[i]; nc = triang_getvertexvals(lf,vh,ih,what);\n  vv[0] = (vl[0]+vh[0])/2;\n  if (nc==1) return(nc);\n  P = 1.5*(vh[0]-vl[0]);\n  le = 0.0;\n  for (j=0; j<d; j++)\n  { dx = evptx(lf,ih,j)-evptx(lf,il,j);\n    vv[0] += dx*(vl[j+1]-vh[j+1])/8;\n    vv[j+1] = (vl[j+1]+vh[j+1])/2;\n    P -= 1.5*dx*vv[j+1];\n    le += dx*dx;\n  }\n  for (j=0; j<d; j++)\n    vv[j+1] += P*(evptx(lf,ih,j)-evptx(lf,il,j))/le;\n  return(nc);\n}\n\ndouble triang_int(tr,x,what)\nlfit *tr;\ndouble *x;\nINT what;\n{ INT d, vc, i, j, k, *ce, nc, nce[1+MXDIM];\n  double xa[1+MXDIM], vv[(1+MXDIM)*(1+MXDIM)], lb;\n  d = tr->mi[MDIM]; vc = d+1;\n  ce = tr->ce;\n  i = 0;\n  while ((i<tr->nce) && (!intri(x,&ce[i*vc],vdptr(tr->xxev),xa,d))) i++;\n  if (i==tr->nce) return(NOSLN);\n  i *= vc;\n  for (j=0; j<vc; j++) nce[j] = ce[i+j];\n  triang_descend(tr,xa,nce);\n\n  /* order the vertices -- needed for asymmetric interptr */\n  do\n  { k=0;\n    for (i=0; i<d; i++)\n      if (nce[i]>nce[i+1])\n      { j=nce[i]; nce[i]=nce[i+1]; nce[i+1]=j; k=1;\n        lb = xa[i]; xa[i] = xa[i+1]; xa[i+1] = lb;\n      }\n  } while(k);\n  nc = 0;\n  for (i=0; i<vc; i++)\n    nc =  triang_getvertexvals(tr,&vv[i*nc],nce[i],what);\n  return((d==2) ? triang_clotoch(vdptr(tr->xxev),vv,nce,nc,xa) :\n                 triang_cubicint(vdptr(tr->xxev),vv,nce,d,nc,xa));\n}\n"
  },
  {
    "path": "src/locfit/family.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\n#define HUBERC 2.0\n\nextern double rs, log();\n\nINT defaultlink(link,family)\nINT link, family;\n{ if (link==LDEFAU)\n    switch(family&63)\n    { case TDEN:\n      case TRAT:\n      case THAZ:\n      case TGAMM:\n      case TGEOM:\n      case TPROB:\n      case TPOIS: return(LLOG);\n      case TCIRC:\n      case TGAUS:\n      case TCAUC:\n      case TROBT: return(LIDENT);\n      case TRBIN:\n      case TLOGT: return(LLOGIT);\n    }\n  if (link==LCANON)\n    switch(family&63)\n    { case TDEN:\n      case TRAT:\n      case THAZ:\n      case TPROB:\n      case TPOIS: return(LLOG);\n      case TGEOM:\n        WARN((\"Canonical link unavaialable for geometric family; using inverse\"));\n      case TGAMM: return(LINVER);\n      case TCIRC:\n      case TGAUS:\n      case TCAUC:\n      case TROBT: return(LIDENT);\n      case TRBIN:\n      case TLOGT: return(LLOGIT);\n    }\n  return(link);\n}\n\nINT validlinks(link,family)\nINT link, family;\n{ switch(family&63)\n  { case TDEN:\n    case TRAT:\n    case THAZ:\n      return((link==LLOG) | (link==LIDENT));\n    case TGAUS:\n      return((link==LIDENT) | (link==LLOG) | (link==LLOGIT));\n    case TROBT:\n    case TCAUC:\n    case TCIRC:\n      return(link==LIDENT);\n    case TLOGT:\n      return((link==LLOGIT) | (link==LIDENT) | (link==LASIN));\n    case TRBIN:\n      return(link==LLOGIT);\n    case TGAMM:\n      return((link==LLOG) | (link==LINVER) | (link==LIDENT));\n    case TGEOM:\n      return((link==LLOG) | (link==LIDENT));\n    case TPOIS:\n    case TPROB:\n      return((link==LLOG) | (link==LSQRT) | (link==LIDENT));\n  }\n  ERROR((\"Unknown family %d in validlinks\",family));\n  return(0);\n}\n\nINT famdens(mean,th,link,res,cens,w)\ndouble mean, th, *res, w;\nINT link, cens;\n{ if (cens)\n    res[ZLIK] = res[ZDLL] = res[ZDDLL] = 0.0;\n  else\n  { res[ZLIK] = w*th;\n    res[ZDLL] = res[ZDDLL] = w;\n  }\n  return(LF_OK);\n}\n\nINT famgaus(y,mean,th,link,res,cens,w)\ndouble y, mean, th, *res, w;\nINT link, cens;\n{ double z, pz, dp;\n  if (link==LINIT)\n  { res[ZDLL] = w*y;\n    return(LF_OK);\n  }\n  z = y-mean;\n  if (cens)\n  { if (link!=LIDENT)\n    { ERROR((\"Link invalid for censored Gaussian family\"));\n      return(LF_LNK);\n    }\n    pz = pnorm(-z,0.0,1.0);\n    dp = ((z>6) ? ptail(-z) : exp(-z*z/2)/pz)/2.5066283;\n    res[ZLIK] = w*log(pz);\n    res[ZDLL] = w*dp;\n    res[ZDDLL]= w*dp*(dp-z);\n    return(LF_OK);\n  }\n  res[ZLIK] = -w*z*z/2; \n  switch(link)\n  { case LIDENT:\n      res[ZDLL] = w*z;\n      res[ZDDLL]= w;\n      break;\n    case LLOG:\n      res[ZDLL] = w*z*mean;\n      res[ZDDLL]= w*mean*mean;\n      break;\n    case LLOGIT:\n      res[ZDLL] = w*z*mean*(1-mean);\n      res[ZDDLL]= w*mean*mean*(1-mean)*(1-mean);\n      break;\n    default:\n      ERROR((\"Invalid link for Gaussian family\"));\n      return(LF_LNK);\n  }\n  return(LF_OK);\n}\n\nINT famrobu(y,mean,th,link,res,cens,w,rs)\ndouble y, mean, th, *res, w, rs;\nINT link, cens;\n{ double z, sw;\n  if (link==LINIT)\n  { res[ZDLL] = w*y;\n    return(LF_OK);\n  }\n  sw = (w==1.0) ? 1.0 : sqrt(w); /* don't want unnecess. sqrt! */\n  z = sw*(y-mean)/rs;\n  res[ZLIK] = (fabs(z)<HUBERC) ? -z*z/2 : HUBERC*(HUBERC/2.0-fabs(z));\n  if (z< -HUBERC)\n  { res[ZDLL] = -sw*HUBERC/rs;\n    res[ZDDLL]= 0.0;\n    return(LF_OK);\n  }\n  if (z> HUBERC)\n  { res[ZDLL] = sw*HUBERC/rs;\n    res[ZDDLL]= 0.0;\n    return(LF_OK);\n  }\n  res[ZDLL] =  sw*z/rs;\n  res[ZDDLL] = w/(rs*rs);\n  return(LF_OK);\n}\n\nINT famcauc(y,p,th,link,res,cens,w,rs)\ndouble y, p, th, *res, w, rs;\nINT link, cens;\n{ double z;\n  if (link!=LIDENT)\n  { ERROR((\"Invalid link in famcauc\"));\n    return(LF_LNK);\n  }\n  z = w*(y-th)/rs;\n  res[ZLIK] = -log(1+z*z);\n  res[ZDLL] = 2*w*z/(rs*(1+z*z));\n  res[ZDDLL] = 2*w*w*(1-z*z)/(rs*rs*(1+z*z)*(1+z*z));\n  return(LF_OK);\n}\n\nINT famrbin(y,p,th,link,res,cens,w)\ndouble y, p, th, *res, w;\nINT link, cens;\n{ double s2y;\n  if (link==LINIT)\n  { res[ZDLL] = y;\n    return(LF_OK);\n  }\n  if ((y<0) | (y>w)) /* goon observation; delete it */\n  { res[ZLIK] = res[ZDLL] = res[ZDDLL] = 0.0;\n    return(LF_OK);\n  }\n  res[ZLIK] = (th<0) ? th*y-w*log(1+exp(th)) : th*(y-w)-w*log(1+exp(-th));\n  if (y>0) res[ZLIK] -= y*log(y/w);\n  if (y<w) res[ZLIK] -= (w-y)*log(1-y/w);\n  res[ZDLL] = (y-w*p);\n  res[ZDDLL]= w*p*(1-p);\n  if (-res[ZLIK]>HUBERC*HUBERC/2.0)\n  { s2y = sqrt(-2*res[ZLIK]);\n    res[ZLIK] = HUBERC*(HUBERC/2.0-s2y);\n    res[ZDLL] *= HUBERC/s2y;\n    res[ZDDLL] = HUBERC/s2y*(res[ZDDLL]-1/(s2y*s2y)*w*p*(1-p));\n  }\n  return(LF_OK);\n}\n\nINT fambino(y,p,th,link,res,cens,w)\ndouble y, p, th, *res, w;\nINT link, cens;\n{ double wp;\n  if (link==LINIT)\n  { if (y<0) y = 0;\n    if (y>w) y = w;\n    res[ZDLL] = y;\n    return(LF_OK);\n  }\n  wp = w*p;\n  if (link==LIDENT)\n  { if ((p<=0) && (y>0)) return(LF_BADP);\n    if ((p>=1) && (y<w)) return(LF_BADP);\n    res[ZLIK] = res[ZDLL] = res[ZDDLL] = 0.0;\n    if (y>0)\n    { res[ZLIK] += y*log(wp/y);\n      res[ZDLL] += y/p;\n      res[ZDDLL]+= y/(p*p);\n    }\n    if (y<w)\n    { res[ZLIK] += (w-y)*log((w-wp)/(w-y));\n      res[ZDLL] -= (w-y)/(1-p);\n      res[ZDDLL]+= (w-y)/SQR(1-p);\n    }\n    return(LF_OK);\n  }\n  if (link==LLOGIT)\n  { if ((y<0) | (y>w)) /* goon observation; delete it */\n    { res[ZLIK] = res[ZDLL] = res[ZDDLL] = 0.0;\n      return(LF_OK);\n    }\n    res[ZLIK] = (th<0) ? th*y-w*log(1+exp(th)) : th*(y-w)-w*log(1+exp(-th));\n    if (y>0) res[ZLIK] -= y*log(y/w);\n    if (y<w) res[ZLIK] -= (w-y)*log(1-y/w);\n    res[ZDLL] = (y-wp);\n    res[ZDDLL]= wp*(1-p);\n    return(LF_OK);\n  }\n  if (link==LASIN)\n  { if ((p<=0) && (y>0)) return(LF_BADP);\n    if ((p>=1) && (y<w)) return(LF_BADP);\n    if ((th<0) | (th>PI/2)) return(LF_BADP);\n    res[ZDLL] = res[ZDDLL] = res[ZLIK] = 0;\n    if (y>0)\n    { res[ZDLL] += 2*y*sqrt((1-p)/p);\n      res[ZLIK] += y*log(wp/y);\n    }\n    if (y<w)\n    { res[ZDLL] -= 2*(w-y)*sqrt(p/(1-p));\n      res[ZLIK] += (w-y)*log((w-wp)/(w-y));\n    }\n    res[ZDDLL] = 4*w;\n    return(LF_OK);\n  }\n  ERROR((\"link %d invalid for binomial family\",link));\n  return(LF_LNK);\n}\n\nINT fampois(y,mean,th,link,res,cens,w)\ndouble y, mean, th, *res, w;\nINT link, cens;\n{ double wmu, pt, dp, dq;\n  if (link==LINIT)\n  { res[ZDLL] = MAX(y,0.0);\n    return(LF_OK);\n  }\n  wmu = w*mean;\n  if (cens)\n  { if (y<=0)\n    { res[ZLIK] = res[ZDLL] = res[ZDDLL] = 0.0;\n      return(LF_OK);\n    }\n    pt = igamma(wmu,y);\n    dp = exp((y-1)*log(wmu)-wmu-LGAMMA(y))/pt;\n    dq = dp*((y-1)/wmu-1);\n    res[ZLIK] = log(pt);\n    if (link==LLOG)\n    { res[ZDLL] = dp*wmu;\n      res[ZDDLL]= -(dq-dp*dp)*wmu*wmu-dp*wmu;\n      return(LF_OK);\n    }\n    if (link==LIDENT)\n    { res[ZDLL] = dp*w;\n      res[ZDDLL]= -(dq-dp*dp)*w*w;\n      return(LF_OK);\n    }\n    if (link==LSQRT)\n    { res[ZDLL] = dp*2*w*th;\n      res[ZDDLL]= -(dq-dp*dp)*(4*w*w*mean)-2*dp*w;\n      return(LF_OK);\n  } }\n  if (link==LLOG)\n  { if (y<0) /* goon observation - delete it */\n    { res[ZLIK] = res[ZDLL] = res[ZDDLL] = 0;\n      return(LF_OK);\n    }\n    res[ZLIK] = res[ZDLL] = y-wmu;\n    if (y>0) res[ZLIK] += y*(th-log(y/w));\n    res[ZDDLL] = wmu;\n    return(LF_OK);\n  }\n  if (link==LIDENT)\n  { if ((mean<=0) && (y>0)) return(LF_BADP);\n    res[ZLIK] = y-wmu;\n    res[ZDLL] = -w;\n    res[ZDDLL] = 0;\n    if (y>0)\n    { res[ZLIK] += y*log(wmu/y);\n      res[ZDLL] += y/mean;\n      res[ZDDLL]= y/(mean*mean);\n    }\n    return(LF_OK);\n  }\n  if (link==LSQRT)\n  { if ((mean<=0) && (y>0)) return(LF_BADP);\n    res[ZLIK] = y-wmu;\n    res[ZDLL] = -2*w*th;\n    res[ZDDLL]= 2*w;\n    if (y>0)\n    { res[ZLIK] += y*log(wmu/y);\n      res[ZDLL] += 2*y/th;\n      res[ZDDLL]+= 2*y/mean;\n    }\n    return(LF_OK);\n  }\n  ERROR((\"link %d invalid for Poisson family\",link));\n  return(LF_LNK);\n}\n\nINT famgamm(y,mean,th,link,res,cens,w)\ndouble y, mean, th, *res, w;\nINT link, cens;\n{ double pt, dg;\n  if (link==LINIT)\n  { res[ZDLL] = MAX(y,0.0);\n    return(LF_OK);\n  }\n  if ((mean<=0) & (y>0)) return(LF_BADP);\n  if (cens)\n  { if (y<=0)\n    { res[ZLIK] = res[ZDLL] = res[ZDDLL] = 0.0;\n      return(LF_OK);\n    }\n    if (link==LLOG)\n    { pt = 1-igamma(y/mean,w);\n      dg = exp((w-1)*log(y/mean)-y/mean-LGAMMA(w));\n      res[ZLIK] = log(pt);\n      res[ZDLL] = y*dg/(mean*pt);\n      res[ZDDLL]= dg*(w*y/mean-y*y/(mean*mean))/pt+SQR(res[ZDLL]);\n      return(LF_OK);\n    }\n    if (link==LINVER)\n    { pt = 1-igamma(th*y,w);\n      dg = exp((w-1)*log(th*y)-th*y-LGAMMA(w));\n      res[ZLIK] = log(pt);\n      res[ZDLL] = -y*dg/pt;\n      res[ZDDLL]= dg*y*((w-1)*mean-y)/pt+SQR(res[ZDLL]);\n      return(LF_OK);\n    }\n  }\n  else\n  { if (y<0) WARN((\"Negative Gamma observation\"));\n    if (link==LLOG)\n    { res[ZLIK] = -y/mean+w*(1-th);\n      if (y>0) res[ZLIK] += w*log(y/w);\n      res[ZDLL] = y/mean-w;\n      res[ZDDLL]= y/mean;\n      return(LF_OK);\n    }\n    if (link==LINVER)\n    { res[ZLIK] = -y/mean+w-w*log(mean);\n      if (y>0) res[ZLIK] += w*log(y/w);\n      res[ZDLL] = -y+w*mean;\n      res[ZDDLL]= w*mean*mean;\n      return(LF_OK);\n    }\n    if (link==LIDENT)\n    { res[ZLIK] = -y/mean+w-w*log(mean);\n      if (y>0) res[ZLIK] += w*log(y/w);\n      res[ZDLL] = (y-mean)/(mean*mean);\n      res[ZDDLL]= w/(mean*mean);\n      return(LF_OK);\n    }\n  }\n  ERROR((\"link %d invalid for Gamma family\",link));\n  return(LF_LNK);\n}\n\nINT famgeom(y,mean,th,link,res,cens,w)\ndouble y, mean, th, *res, w;\nINT link, cens;\n{ double p, pt, dp, dq;\n  if (link==LINIT)\n  { res[ZDLL] = MAX(y,0.0);\n    return(LF_OK);\n  }\n  p = 1/(1+mean);\n  if (cens) /* censored observation */\n  { if (y<=0)\n    { res[ZLIK] = res[ZDLL] = res[ZDDLL] = 0;\n      return(LF_OK);\n    }\n    pt = 1-ibeta(p,w,y);\n    dp = -exp(LGAMMA(w+y)-LGAMMA(w)-LGAMMA(y)+(y-1)*th+(w+y-2)*log(p))/pt;\n    dq = ((w-1)/p-(y-1)/(1-p))*dp;\n    res[ZLIK] = log(pt);\n    res[ZDLL] = -dp*p*(1-p);\n    res[ZDDLL]= (dq-dp*dp)*p*p*(1-p)*(1-p)+dp*(1-2*p)*p*(1-p);\n    res[ZDDLL]= -res[ZDDLL];\n    return(LF_OK);\n  }\n  else\n  { res[ZLIK] = (y+w)*log((y/w+1)/(mean+1));\n    if (y>0) res[ZLIK] += y*log(w*mean/y);\n    if (link==LLOG)\n    { res[ZDLL] = (y-w*mean)*p;\n      res[ZDDLL]= (y+w)*p*(1-p);\n      return(LF_OK);\n    }\n    if (link==LIDENT)\n    { res[ZDLL] = (y-w*mean)/(mean*(1+mean));\n      res[ZDDLL]= w/(mean*(1+mean));\n      return(LF_OK);\n    }\n  }\n  ERROR((\"link %d invalid for geometric family\",link));\n  return(LF_LNK);\n}\n\nINT famweib(y,mean,th,link,res,cens,w)\ndouble y, mean, th, *res, w;\nINT link, cens;\n{ double yy;\n  yy = pow(y,w);\n  if (link==LINIT)\n  { res[ZDLL] = MAX(yy,0.0);\n    return(LF_OK);\n  }\n  if (cens)\n  { res[ZLIK] = -yy/mean;\n    res[ZDLL] = res[ZDDLL] = yy/mean;\n    return(LF_OK);\n  }\n  res[ZLIK] = 1-yy/mean-th;\n  if (yy>0) res[ZLIK] += log(w*yy);\n  res[ZDLL] = -1+yy/mean;\n  res[ZDDLL]= yy/mean;\n  return(LF_OK);\n}\n\nINT famcirc(y,mean,th,link,res,cens,w)\ndouble y, mean, th, *res, w;\nINT link, cens;\n{ if (link==LINIT)\n  { res[ZDLL] = w*sin(y);\n    res[ZLIK] = w*cos(y);\n    return(LF_OK);\n  }\n  res[ZDLL] = w*sin(y-mean);\n  res[ZDDLL]= w*cos(y-mean);\n  res[ZLIK] = res[ZDDLL]-w;\n  return(LF_OK);\n}\n\nvoid robustify(res,rs)\ndouble *res, rs;\n{ double sc, z;\n  sc = rs*HUBERC;\n  if (res[ZLIK] > -sc*sc/2) return;\n  z = sqrt(-2*res[ZLIK]);\n  res[ZDDLL]= -sc*res[ZDLL]*res[ZDLL]/(z*z*z)+sc*res[ZDDLL]/z;\n  res[ZDLL]*= sc/z;\n  res[ZLIK] = sc*sc/2-sc*z;\n}\n\ndouble lf_link(y,lin)\ndouble y;\nINT lin;\n{ switch(lin)\n  { case LIDENT: return(y);\n    case LLOG:   return(log(y));\n    case LLOGIT: return(logit(y));\n    case LINVER: return(1/y);\n    case LSQRT:  return(sqrt(fabs(y)));\n    case LASIN:  return(asin(sqrt(y)));\n  }\n  ERROR((\"link: unknown link %d\",lin));\n  return(0.0);\n}\n\ndouble invlink(th,lin)\ndouble th;\nINT lin;\n{ switch(lin)\n  { case LIDENT: return(th);\n    case LLOG:   return(lf_exp(th));\n    case LLOGIT: return(expit(th));\n    case LINVER: return(1/th);\n    case LSQRT:  return(th*fabs(th));\n    case LASIN:  return(sin(th)*sin(th));\n    case LINIT:  return(0.0);\n  }\n  ERROR((\"invlink: unknown link %d\",lin));\n  return(0.0);\n}\n\nINT links(th,y,fam,lin,res,cd,w,rs) /* the link and various related functions */\ndouble th, y, *res, w, cd, rs;\nINT fam, lin;\n{ double mean;\n  INT c, link, st;\n  c = (INT)cd; link = (INT)lin;\n\n  mean = res[ZMEAN] = invlink(th,lin);\n  if (lf_error) return(LF_LNK);\n\n  switch(fam&63)\n  { case THAZ:\n    case TDEN:\n    case TRAT: return(famdens(mean,th,link,res,c,w));\n    case TGAUS: st = famgaus(y,mean,th,link,res,c,w);\n                break;\n    case TLOGT: st = fambino(y,mean,th,link,res,c,w);\n                break;\n    case TRBIN: return(famrbin(y,mean,th,link,res,c,w));\n    case TPROB:\n    case TPOIS: st = fampois(y,mean,th,link,res,c,w);\n                break;\n    case TGAMM: st = famgamm(y,mean,th,link,res,c,w);\n                break;\n    case TGEOM: st = famgeom(y,mean,th,link,res,c,w);\n                break;\n    case TWEIB: return(famweib(y,mean,th,link,res,c,w));\n    case TCIRC: st = famcirc(y,mean,th,link,res,c,w);\n                break;\n    case TROBT: return(famrobu(y,mean,th,link,res,c,w,rs));\n    case TCAUC: return(famcauc(y,mean,th,link,res,c,w,rs));\n    default:\n      ERROR((\"links: invalid family %d\",fam));\n      return(LF_FAM);\n  }\n  if (st!=LF_OK) return(st);\n  if (link==LINIT) return(st);\n  if ((fam&128)==128) robustify(res,rs);\n  return(st);\n}\n\n/*\n  stdlinks is a version of links when family, link, response e.t.c\n  all come from the standard places.\n*/\nINT stdlinks(res,lf,i,th,rs)\nlfit *lf;\ndouble th, rs, *res;\nINT i;\n{ return(links(th,resp(lf,i),lf->mi[MTG],lf->mi[MLINK],res,cens(lf,i),prwt(lf,i),rs));\n}\n\n/*\n *  functions used in variance, skewness, kurtosis calculations\n *  in scb corrections.\n */\n\ndouble b2(th,tg,w)\ndouble th, w;\nINT tg;\n{ double y;\n  switch(tg&63)\n  { case TGAUS: return(w);\n    case TPOIS: return(w*lf_exp(th));\n    case TLOGT:\n      y = expit(th);\n      return(w*y*(1-y));\n  }\n  ERROR((\"b2: invalid family %d\",tg));\n  return(0.0);\n}\n\ndouble b3(th,tg,w)\ndouble th, w;\nINT tg;\n{ double y;\n  switch(tg&63)\n  { case TGAUS: return(0.0);\n    case TPOIS: return(w*lf_exp(th));\n    case TLOGT:\n      y = expit(th);\n      return(w*y*(1-y)*(1-2*y));\n  }\n  ERROR((\"b3: invalid family %d\",tg));\n  return(0.0);\n}\n\ndouble b4(th,tg,w)\ndouble th, w;\nINT tg;\n{ double y;\n  switch(tg&63)\n  { case TGAUS: return(0.0);\n    case TPOIS: return(w*lf_exp(th));\n    case TLOGT:\n      y = expit(th); y = y*(1-y);\n      return(w*y*(1-6*y));\n  }\n  ERROR((\"b4: invalid family %d\",tg));\n  return(0.0);\n}\n"
  },
  {
    "path": "src/locfit/fitted.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n/*\n  Functions for computing residuals and fitted values from\n  the locfit object.\n\n  fitted(lf,des,fit,what,cv,ty) computes fitted values from the\n    fit structure in lf. \n  resid(y,c,w,th,mi,ty) converts fitted values to residuals\n  cfitted(v,ty) is CVERSION front end, interpreting command\n    line arguments and computing th.\n  vfitted(ty) for use by arithmetic interpreter.\n*/\n\n#include \"local.h\"\n\ndouble resid(y,w,th,mi,ty,res)\nINT *mi, ty;\ndouble y, w, th, *res;\n{ double raw;\n  INT tg;\n\n  tg = mi[MTG] & 63;\n  if ((tg==TGAUS) | (tg==TROBT) | (tg==TCAUC))\n    raw = y-res[ZMEAN];\n  else\n    raw = y-w*res[ZMEAN];\n  switch(ty)\n  { case RDEV:\n      if (res[ZDLL]>0) return(sqrt(-2*res[ZLIK]));\n            else return(-sqrt(-2*res[ZLIK]));\n    case RPEAR:\n      if (res[ZDDLL]<=0)\n      { if (res[ZDLL]==0) return(0);\n        return(NOSLN);\n      }\n      return(res[ZDLL]/sqrt(res[ZDDLL]));\n    case RRAW:  return(raw);\n    case RLDOT: return(res[ZDLL]);\n    case RDEV2: return(-2*res[ZLIK]);\n    case RLDDT: return(res[ZDDLL]);\n    case RFIT:  return(th);\n    case RMEAN: return(res[ZMEAN]);\n    default: ERROR((\"resid: unknown residual type %d\",ty));\n  }\n  return(0.0);\n}\n\ndouble studentize(res,inl,var,ty,link)\ndouble res, inl, var, *link;\nint ty;\n{ double den;\n  inl *= link[ZDDLL];\n  var = var*var*link[ZDDLL];\n  if (inl>1) inl = 1;\n  if (var>inl) var = inl;\n  den = 1-2*inl+var;\n  if (den<0) return(0.0);\n  switch(ty)\n  { case RDEV:\n    case RPEAR:\n    case RRAW:\n    case RLDOT:\n      return(res/sqrt(den));\n    case RDEV2:\n      return(res/den);\n    default: return(res);\n  }\n}\n\nvoid fitted(lf,des,fit,what,cv,st,ty)\nlfit *lf;\ndesign *des;\ndouble *fit;\nINT what, cv, st, ty;\n{ INT i, j, d, n, ev;\n  double xx[MXDIM], th, inl, var, link[LLEN];\n    inl = 0.0;\n    var = 0.0;\n  n = lf->mi[MN];\n  d = lf->mi[MDIM];\n  ev = lf->mi[MEV];\n  cv &= (ev!=ECROS);\n  if ((lf->mi[MEV]==EDATA)|(lf->mi[MEV]==ECROS)) ev = EFITP;\n  for (i=0; i<n; i++)\n  { for (j=0; j<d; j++) xx[j] = datum(lf,j,i);\n    th = dointpoint(lf,des,xx,what,ev,i);\n    if ((what==PT0)|(what==PVARI)) th = th*th;\n    if (what==PCOEF)\n    { th += base(lf,i);\n      stdlinks(link,lf,i,th,lf->dp[DRSC]);\n      if ((cv)|(st))\n      { inl = dointpoint(lf,des,xx,PT0,ev,i);\n        inl = inl*inl;\n        if (cv)\n        { th -= inl*link[ZDLL];\n          stdlinks(link,lf,i,th,lf->dp[DRSC]);\n        }\n        if (st) var = dointpoint(lf,des,xx,PNLX,ev,i);\n      }\n      fit[i] = resid(resp(lf,i),prwt(lf,i),th,lf->mi,ty,link);\n      if (st) fit[i] = studentize(fit[i],inl,var,ty,link);\n    } else fit[i] = th;\n    if (lf_error) return;\n  }\n}\n\n#ifdef CVERSION\nextern lfit lf;\nextern design des;\n\nvari *vfitted(type)\nINT type;\n{ vari *v;\n  INT n;\n  n = lf.mi[MN];\n  v = createvar(\"vfitted\",STHIDDEN,n,VDOUBLE);\n  recondat(1,&n);\n  if (lf_error) return(NULL);\n\n  fitted(&lf,&des,vdptr(v),PCOEF,0,0,type);\n  return(v);\n}\n\nvoid cfitted(v,ty)\nvari *v;\nINT ty;\n{ double *f;\n  vari *vr;\n  INT i, n, cv, st, wh;\n\n  i = getarg(v,\"type\",1);\n  if (i>0) ty = restyp(argval(v,i));\n\n  i = getarg(v,\"cv\",1); cv = (i>0) ? getlogic(v,i) : 0;\n  i = getarg(v,\"studentize\",1); st = (i>0) ? getlogic(v,i) : 0;\n\n  wh = PCOEF;\n  i = getarg(v,\"what\",1);\n  if (i>0) wh = ppwhat(argval(v,i));\n\n  recondat(ty==5,&n);\n  if (lf_error) return;\n\n  vr = createvar(\"fitted\",STHIDDEN,n,VDOUBLE);\n  f = vdptr(vr);\n  fitted(&lf,&des,f,wh,cv,st,ty);\n\n  saveresult(vr,argarg(v,0),STREGULAR);\n}\n#endif\n"
  },
  {
    "path": "src/locfit/frend.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\nextern INT cvi;\nextern double robscale;\n\ndouble resp(lf,i)\nlfit *lf;\nINT i;\n{ if (lf->y==NULL) return(0.0);\n    return(lf->y[i]);\n}\n\ndouble prwt(lf,i)\nlfit *lf;\nINT i;\n{ if (i==cvi) return(0.0);\n    if (lf->w==NULL) return(1.0);\n    return(lf->w[i]);\n}\n\ndouble base(lf,i)\nlfit *lf;\nINT i;\n{ if (lf->base==NULL) return(0.0);\n    return(lf->base[i]);\n}\n\ndouble cens(lf,i)\nlfit *lf;\nINT i;\n{ if (lf->c==NULL) return(0.0);\n    return(lf->c[i]);\n}\n\ndouble vocri(lk,t0,t2,pen)\ndouble lk, t0, t2, pen;\n{ if (pen==0) return(-2*t0*lk/((t0-t2)*(t0-t2)));\n    return((-2*lk+pen*t2)/t0);\n}\n\nINT procvraw(des,lf,v)\ndesign *des;\nlfit *lf;\nINT v;\n{ INT lf_status;\n    int i;\n    double h, coef[1+MXDIM];\n    des->xev = evpt(lf,v);\n    \n    lf_status = ainitband(des,lf);\n    \n    if (!lf_error) switch(lf->mi[MACRI])\n    { case AKAT:\n        case ACP:\n        case AMDI:\n            h = aband2(des,lf,des->h);\n            h = aband3(des,lf,h);\n            h = nbhd(lf,des,0,h,1);\n            lf_status = locfit(lf,des,h,0);\n            break;\n        case ANONE:\n        case AOK:\n            break;\n    }\n    \n    lf->h[v] = des->h;\n    for (i=0; i<des->ncoef; i++) coef[i] = des->cf[cfn(des,i)];\n    \n    if (!lf_error)\n    { if (lf->mi[MDC]) dercor(des,lf,coef);\n        subparcomp(des,lf,coef);\n        for (i=0; i<des->ncoef; i++) lf->coef[i*lf->nvm+v] =  coef[i];\n    }\n    \n    lf->deg[v] = lf->mi[MDEG];\n    \n    return(lf_status);\n}\n\n/*\n * Set default values for the likelihood e.t.c. This\n * is called in cases where the optimization for the fit\n * has failed.\n */\n\nvoid set_default_like(lf,nvm,v,d)\nlfit *lf;\nINT nvm, v;\nint d;\n{ INT i;\n    lf->lik[v] = lf->lik[nvm+v] = 0;\n    lf->lik[2*nvm+v] = 0; /* should use sum of weights here? */\n    for (i=0; i<=d; i++)\n        lf->t0[i*nvm+v] = lf->nlx[i*nvm+v] = 0.0;\n}\n\nINT procv(des,lf,v)\ndesign *des;\nlfit *lf;\nINT v;\n{ INT d, p, nvm, i, k;\n    double trc[6], t0[1+MXDIM], vari[1+MXDIM];\n    memset(vari, 0, sizeof(vari));\n    k = procvraw(des,lf,v);\n    if (lf_error) return(k);\n    \n    d = lf->mi[MDIM]; p = lf->mi[MP];\n    nvm = lf->nvm;\n    \n    switch(k)\n    { case LF_OK: break;\n        case LF_NCON:\n            WARN((\"procv: locfit did not converge\"));\n            break;\n        case LF_OOB:\n            WARN((\"procv: parameters out of bounds\"));\n            break;\n        case LF_PF:\n            if (lf->mi[MDEB]>1) WARN((\"procv: perfect fit\"));\n            set_default_like(lf,nvm,v,d);\n            return(k);\n        case LF_NOPT:\n            WARN((\"procv: no points with non-zero weight\"));\n            set_default_like(lf,nvm,v,d);\n            return(k);\n        case LF_INFA:\n            if (lf->mi[MDEB]>1) WARN((\"procv: initial value problem\"));\n            set_default_like(lf,nvm,v,d);\n            return(k);\n        case LF_DEMP:\n            WARN((\"procv: density estimate, empty integration region\"));\n            set_default_like(lf,nvm,v,d);\n            return(k);\n        case LF_XOOR:\n            WARN((\"procv: fit point outside xlim region\"));\n            set_default_like(lf,nvm,v,d);\n            return(k);\n        case LF_DNOP:\n            if (lf->mi[MDEB]>1)\n                WARN((\"density estimation -- insufficient points in smoothing window\"));\n            set_default_like(lf,nvm,v,d);\n            return(k);\n        case LF_FPROB:\n            WARN((\"procv: f problem; likelihood failure\"));\n            set_default_like(lf,nvm,v,d);\n            return(k);\n        default:\n            WARN((\"procv: unknown return code %d\",k));\n            set_default_like(lf,nvm,v,d);\n            return(k);\n    }\n    \n    comp_vari(lf,des,trc,t0);\n    lf->lik[v] = des->llk;\n    lf->lik[nvm+v] = trc[2];\n    lf->lik[2*nvm+v] = trc[0]-trc[2];\n    lf->nlx[v] = sqrt(des->V[0]);\n    \n    for (i=0; i<des->ncoef; i++)\n        vari[i] = des->V[p*cfn(des,0) + cfn(des,i)];\n    vari[0] = sqrt(vari[0]);\n    if (vari[0]>0) for (i=1; i<des->ncoef; i++) vari[i] /= vari[0];\n    t0[0] = sqrt(t0[0]);\n    if (t0[0]>0) for (i=1; i<des->ncoef; i++) t0[i] /= t0[0];\n    \n    subparcomp2(des,lf,vari,t0);\n    for (i=0; i<des->ncoef; i++)\n    { lf->nlx[i*lf->nvm+v] = vari[i];\n        lf->t0[i*lf->nvm+v]  = t0[i];\n    }\n    \n    return(k);\n}\n\ndouble intvo(des,lf,c0,c1,a,p,t0,t20,t21)\ndesign *des;\nlfit *lf;\ndouble *c0, *c1, a, t0, t20, t21;\nINT p;\n{ double th, lk, link[LLEN];\n    INT i;\n    lk = 0;\n    for (i=0; i<des->n; i++)\n    { th = (1-a)*innerprod(c0,&des->X[i*p],p) + a*innerprod(c1,&des->X[i*p],p);\n        stdlinks(link,lf,des->ind[i],th,robscale);\n        lk += des->w[i]*link[ZLIK];\n    }\n    des->llk = lk;\n    return(vocri(des->llk,t0,(1-a)*t20+a*t21,lf->dp[DADP]));\n}\n\nINT procvvord(des,lf,v)\ndesign *des;\nlfit *lf;\nINT v;\n{ \n    static const int x_1 = 4;\n    static const int y_1 = 10;\n    double tr[6], gcv, g0, ap, coef[x_1][y_1], t2[4], th, md = 0.0;\n    INT i, j, k = 0, d1, *mi, i0, p1, ip;\n    mi = lf->mi;\n    des->xev = evpt(lf,v);\n    \n    for (i = 0; i < x_1; ++i)\n    {\n        for (j = 0; j < y_1; ++j)\n        {\n            coef[i][j] = 0;\n        }\n    }\n    \n    lf->h[v] = nbhd(lf,des,(INT)(mi[MN]*lf->dp[DALP]),lf->dp[DFXH],0);\n    if (lf->h[v]<=0) WARN((\"zero bandwidth in procvvord\"));\n    \n    ap = lf->dp[DADP];\n    if ((ap==0) & ((mi[MTG]&63)!=TGAUS)) ap = 2.0;\n    d1 = mi[MDEG]; p1 = mi[MP];\n    for (i=0; i<p1; i++) coef[0][i] = coef[1][i] = coef[2][i] = coef[3][i] = 0.0;\n    i0 = 0; g0 = 0;\n    ip = 1;\n    for (i=mi[MDEG0]; i<=d1; i++)\n    { mi[MDEG] = i; des->p = mi[MP] = calcp(mi,i);\n        k = locfit(lf,des,lf->h[v],0);\n        \n        local_df(lf,des,tr);\n        gcv = vocri(des->llk,tr[0],tr[2],ap);\n        if ((i==mi[MDEG0]) || (gcv<g0)) { i0 = i; g0 = gcv; md = i; }\n        \n        for (j=0; j<des->p; j++) coef[i][j] = des->cf[j];\n        t2[i] = tr[2];\n        \n#ifdef RESEARCH\n        printf(\"variable order\\n\");\n        if ((ip) && (i>mi[MDEG0]))\n        { for (j=1; j<10; j++)\n        { gcv = intvo(des,lf,coef[i-1],coef[i],j/10.0,des->p,tr[0],t2[i-1],t2[i]);\n            if (gcv<g0) { g0 = gcv; md = i-1+j/10.0; }\n        }\n        }\n#endif\n    }\n    \n    if (i0<d1) /* recompute the best fit */\n    { mi[MDEG] = i0; des->p = mi[MP] = calcp(mi,i0);\n        k = locfit(lf,des,lf->h[v],0);\n        for (i=mi[MP]; i<p1; i++) des->cf[i] = 0.0;\n        i0 = (INT)md; if (i0==d1) i0--;\n        th = md-i0;\n        for (i=0; i<p1; i++) des->cf[i] = (1-th)*coef[i0][i]+th*coef[i0+1][i];\n        mi[MDEG] = d1; mi[MP] = p1;\n    }\n    \n    for (i=0; i<p1; i++) lf->coef[i*lf->nvm+v] = des->cf[i];\n    lf->deg[v] = md;\n    return(k);\n}\n\n/* special version of ressumm to estimate sigma^2, with derivative estimation */\nvoid ressummd(lf,des)\nlfit *lf;\ndesign *des;\n{ INT i;\n    double s0, s1;\n    s0 = s1 = 0.0;\n    if ((lf->mi[MTG]&64)==0)\n    { lf->dp[DRV] = 1.0;\n        return;\n    }\n    for (i=0; i<lf->nv; i++)\n    { s0 += lf->lik[2*lf->nvm+i];\n        s1 += lf->lik[i];\n    }\n    if (s0==0.0)\n        lf->dp[DRV] = 0.0;\n    else\n        lf->dp[DRV] = -2*s1/s0;\n}\n\nvoid ressumm(lf,des)\nlfit *lf;\ndesign *des;\n{ INT i, j, ev, tg, orth;\n    double *dp, *oy, pw, r1, r2, rdf, t0, t1, u[MXDIM], link[LLEN];\n    dp = lf->dp;\n    dp[DLK] = dp[DT0] = dp[DT1] = 0;\n    if ((lf->mi[MEV]==EKDCE) | (lf->mi[MEV]==EPRES))\n    { dp[DRV] = 1.0;\n        return;\n    }\n    if (lf->nd>0)\n    { ressummd(lf,des);\n        return;\n    }\n    r1 = r2 = 0.0;\n    ev = lf->mi[MEV];\n    if ((ev==EDATA) | (ev==ECROS)) ev = EFITP;\n    orth = (lf->mi[MGETH]==4) | (lf->mi[MGETH]==5);\n    for (i=0; i<lf->mi[MN]; i++)\n    { for (j=0; j<lf->mi[MDIM]; j++) u[j] = datum(lf,j,i);\n        des->th[i] = base(lf,i)+dointpoint(lf,des,u,PCOEF,ev,i);\n        des->wd[i] = resp(lf,i) - des->th[i];\n        des->w[i] = 1.0;\n        des->ind[i] = i;\n    }\n    \n    tg = lf->mi[MTG];\n    lf->dp[DRSC] = 1.0;\n    if ((tg==TROBT+64) | (tg==TCAUC+64)) /* global robust scale */\n    { oy = lf->y; lf->y = des->wd;\n        des->xev = lf->pc.xbar;\n        locfit(lf,des,0.0,1);\n        lf->y = oy;\n        lf->dp[DRSC] = robscale;\n    }\n    \n    if (orth) /* orthog. residuals */\n    { int od, op;\n        des->n = lf->mi[MN];\n        od = lf->mi[MDEG]; op = lf->mi[MP];\n        lf->mi[MDEG] = 1;\n        lf->mi[MP] = des->p = 1+lf->mi[MDIM];\n        oy = lf->y; lf->y = des->wd;\n        des->xev = lf->pc.xbar;\n        locfit(lf,des,0.0,1);\n        for (i=0; i<lf->mi[MN]; i++) oy[i] = resp(lf,i) - des->th[i];\n        lf->y = oy;\n        lf->mi[MDEG] = od; lf->mi[MP] = op;\n    }\n    \n    for (i=0; i<lf->mi[MN]; i++)\n    { for (j=0; j<lf->mi[MDIM]; j++) u[j] = datum(lf,j,i);\n        t0 = dointpoint(lf,des,u,PT0,ev,i);\n        t1 = dointpoint(lf,des,u,PNLX,ev,i);\n        stdlinks(link,lf,i,des->th[i],lf->dp[DRSC]);\n        t1 = t1*t1*link[ZDDLL];\n        t0 = t0*t0*link[ZDDLL];\n        if (t1>1) t1 = 1;\n        if (t0>1) t0 = 1; /* no observation gives >1 deg.free */\n        dp[DLK] += link[ZLIK];\n        dp[DT0] += t0;\n        dp[DT1] += t1;\n        pw = prwt(lf,i);\n        if (pw>0)\n        { r1 += link[ZDLL]*link[ZDLL]/pw;\n            r2 += link[ZDDLL]/pw;\n        }\n        if (orth) des->di[i]  = t1;\n    }\n    \n    if (orth) return;\n    \n    dp[DRV] = 1.0;\n    if ((lf->mi[MTG]&64)==64) /* quasi family */\n    { rdf = lf->mi[MN]-2*dp[DT0]+dp[DT1];\n        if (rdf<1.0)\n        { WARN((\"Estimated rdf < 1.0; not estimating variance\"));\n        }\n        else\n            dp[DRV] = r1/r2 * lf->mi[MN] / rdf;\n    }\n    \n    /* try to ensure consistency for family=\"circ\"! */\n    if (((lf->mi[MTG]&63)==TCIRC) & (lf->mi[MDIM]==1))\n    { INT *ind, nv;\n        double dlt, th0, th1;\n        ind = des->ind;\n        nv = lf->nv;\n        for (i=0; i<nv; i++) ind[i] = i;\n        lforder(ind,vdptr(lf->xxev),0,nv-1);\n        for (i=1; i<nv; i++)\n        { dlt = evptx(lf,ind[i],0)-evptx(lf,ind[i-1],0);\n            th0 = lf->coef[ind[i]]-dlt*lf->coef[ind[i]+nv]-lf->coef[ind[i-1]];\n            th1 = lf->coef[ind[i]]-dlt*lf->coef[ind[i-1]+nv]-lf->coef[ind[i-1]];\n            if ((th0>PI)&(th1>PI))\n            { for (j=0; j<i; j++)\n                lf->coef[ind[j]] += 2*PI;\n                i--;\n            }\n            if ((th0<(-PI))&(th1<(-PI)))\n            { for (j=0; j<i; j++)\n                lf->coef[ind[j]] -= 2*PI;\n                i--;\n            }\n        }\n    }\n}\n\ndouble rss(lf,des,df)\nlfit *lf;\ndesign *des;\ndouble *df;\n{ double ss;\n    INT i;\n    ss = 0;\n    if (ident==1)\n    { for (i=0; i<lf->mi[MN]; i++)\n        ss += SQR(resp(lf,i)-lf->coef[i]);\n        *df = lf->mi[MN]-lf->mi[MP];\n        return(ss);\n    }\n    ressumm(lf,des);\n    *df = lf->mi[MN] - 2*lf->dp[DT0] + lf->dp[DT1];\n    return(-2*lf->dp[DLK]);\n}\n"
  },
  {
    "path": "src/locfit/help.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n *\n *\n *\n *   The example() function is used to tnterpreting examples\n *   in the locfit.ceg file.\n */\n\n#include \"local.h\"\n\n#ifdef CVERSION\n\nstatic FILE *help;\nextern char *lfhome;\n\nvoid example(v)\nvari *v;\n{ int i, j, run, ti;\n  char *z, elin[10], helpfile[100], line[200];\n\n  run = 0;\n  i = getarg(v,\"ex\",1);\n  ti = (i==0);\n  if (!ti)\n  { z = strchr(argval(v,i),'.');\n    if (z==NULL)\n    { ERROR((\"example: invalid number %s\",argval(v,i)));\n      return;\n    }\n    j = getarg(v,\"run\",1);\n    if (j>0) run = getlogic(v,j);\n  }\n\n  if (lfhome!=NULL)\n    sprintf(helpfile,\"%s/locfit.ceg\",lfhome);\n  else\n    sprintf(helpfile,\"locfit.ceg\");\n\n  help = fopen(helpfile,\"r\");\n  if (help==NULL)\n  { ERROR((\"Can't find locfit.ceg file -- is LFHOME set?\"));\n    return;\n  }\n\n  do\n  { z = fgets(line,190,help);\n    if (z==NULL) /* reached end of file */\n    { if (!ti) ERROR((\"No example %s in help file\",argval(v,i)));\n      fclose(help);\n      return;\n    }\n    if (line[0]=='e')\n    { sscanf(&line[2],\"%s\",elin);\n      if (ti) printf(\"Example %s. \",elin);\n    }\n    else elin[0] = 0;\n    if ((ti) && (line[0]=='t'))\n      printf(\"%s\",&line[2]);\n  }  while ((ti) || (strcmp(elin,argval(v,i))!=0));\n\n  while(1)\n  { z = fgets(line,190,help);\n    switch(z[0])\n    { case 'f': /* end example */\n        fclose(help);\n        printf(\"\\n\");\n        return;\n      case 't': /* title */\n        printf(\"\\nExample %s. %s\\n\",argval(v,i),&line[2]);\n        break;\n      case 'c': /* code */\n        printf(\"  %s\",&line[2]);\n      case 'h': /* hidden code, usually sleep */\n        if (run) makecmd(&line[2]);\n        break;\n      case 'd': /* discussion */\n        printf(\"%s\",&line[2]);\n        break;\n      case 'n': /* no code */\n        printf(\"There is no code for this example.\\n\");\n        break;\n    }\n  }\n}\n\n#endif\n"
  },
  {
    "path": "src/locfit/imatlb.h",
    "content": "typedef struct {\n  int n;\n  double *dpr;\n} vari;    \n\ntypedef struct {\n  double *Z, *Q, *dg, *f2;\n  int p, sm; } xtwxstruc;\n\ntypedef struct {\n  vari *wk;\n  double *coef, *xbar, *f;\n  xtwxstruc xtwx; } paramcomp;\n\ntypedef struct {\n  vari *dw, *index;\n  double *xev, *X, *w, *di, *res, *th, *wd, h, xb[15];\n  double *V, *P, *f1, *ss, *oc, *cf, llk;\n  xtwxstruc xtwx;\n  int *ind, n, p, pref, (*itype)();\n  int (*vfun)(); } design;\n\ntypedef struct {\n  vari *tw, *L, *iw, *xxev;\n  double *x[15], *y, *w, *base, *c, *xl;\n  double *coef, *nlx, *t0, *lik, *h, *deg;\n  double *sv, *fl, *sca, *dp, kap[3];\n  int *ce, *s, *lo, *hi, sty[15];\n  int *mg, nvm, ncm, vc;\n  int nl, nv, nnl, nce, nk, nn, *mi, ord, deriv[9], nd;\n  paramcomp pc;\n  varname yname, xname[15], wname, bname, cname; } lfit;\n\nextern void mlbcall(\n             double *x, double *y,\n             double *xx, double *ff, int n);\n"
  },
  {
    "path": "src/locfit/lf_dercor.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *   Derivative corrections. The local slopes are not the derivatives\n *   of the local likelihood estimate; the function dercor() computes\n *   the adjustment to get the correct derivatives under the assumption\n *   that h is constant.\n *\n *   By differentiating the local likelihood equations, one obtains\n *\n *     d ^      ^       T      -1   T  d    .       ^\n *    -- a   =  a  -  (X W V X)    X  -- W  l( Y, X a)\n *    dx  0      1                    dx\n */\n\n#include \"local.h\"\nextern double robscale;\n\nvoid dercor(des,lf,coef)\ndesign *des;\nlfit *lf;\ndouble *coef;\n{ double s1, dc[MXDIM], wd, link[LLEN];\n  INT i, ii, j, m, p, d, *mi; \n  mi = lf->mi;\n  if (mi[MTG]<=THAZ) return;\n  if (mi[MKER]==WPARM) return;\n\n  d = mi[MDIM];\n  p = des->p; m = des->n;\n\n  if (mi[MDEB]>1) printf(\"  Correcting derivatives\\n\");\n  fitfun(lf,des->xev,des->xev,des->f1,NULL,0);\n  jacob_solve(&des->xtwx,des->f1);\n  setzero(dc,d);\n\n  /* correction term is e1^T (XTWVX)^{-1} XTW' ldot. */\n  for (i=0; i<m; i++)\n  { s1 = innerprod(des->f1,&des->X[i*p],p);\n    ii = des->ind[i];\n    stdlinks(link,lf,ii,des->th[i],robscale);\n    for (j=0; j<d; j++)\n    { wd = des->w[i]*weightd(datum(lf,j,ii)-des->xev[j],lf->sca[j],d,mi[MKER],mi[MKT],des->h,lf->sty[j],des->di[ii]);\n      dc[j] += s1*wd*link[ZDLL];\n    }\n\n  }\n  for (j=0; j<d; j++) coef[j+1] += dc[j];\n}\n"
  },
  {
    "path": "src/locfit/lf_fitfun.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *   Evaluate the locfit fitting functions.\n *     calcp(mi,deg)\n *       calculates the number of fitting functions.\n *     makecfn(des,lf)\n *       makes the coef.number vector.\n *     fitfun(lf,x,t,f,der,nd)\n *       lf is the local fit structure.\n *       x is the data point.\n *       t is the fitting point.\n *       f is a vector to return the results.\n *       deriv is a vector of derivative variables.\n *       nd is the number of derivatives.\n *     designmatrix(lf, des)\n *       is a wrapper for fitfun to build the design matrix.\n *\n */\n\n#include \"local.h\"\n\nINT calcp(mi,deg)\nINT *mi, deg;\n{ INT i, k;\n    \n    if (mi[MUBAS]) return(mi[MP]);\n    \n    switch (mi[MKT])\n    { case KSPH:\n        case KCE:\n            k = 1;\n            for (i=1; i<=deg; i++) k = k*(mi[MDIM]+i)/i;\n            return(k);\n        case KPROD: return(mi[MDIM]*deg+1);\n        case KLM: return(mi[MDIM]);\n    }\n    ERROR((\"calcp: invalid kt %d\",mi[MKT]));\n    return(0);\n}\n\nINT coefnumber(deriv,nd,kt,d,deg)\nINT *deriv, nd, kt, d, deg;\n{ INT d0, d1, t;\n    \n    if (d==1)\n    { if (nd<=deg) return(nd);\n        return(-1);\n    }\n    \n    if (nd==0) return(0);\n    if (deg==0) return(-1);\n    if (nd==1) return(1+deriv[0]);\n    if (deg==1) return(-1);\n    if (kt==KPROD) return(-1);\n    \n    if (nd==2)\n    { d0 = deriv[0]; d1 = deriv[1];\n        if (d0<d1) { t = d0; d0 = d1; d1 = t; }\n        return((d+1)*(d0+1)-d0*(d0+3)/2+d1);\n    }\n    if (deg==2) return(-1);\n    \n    ERROR((\"coefnumber not programmed for nd>=3\"));\n    return(-1);\n}\n\nvoid makecfn(des,lf)\ndesign *des;\nlfit *lf;\n{ int i;\n    INT *mi, nd;\n    \n    nd = lf->nd;\n    mi = lf->mi;\n    \n    des->cfn[0] = coefnumber(lf->deriv,nd,mi[MKT],mi[MDIM],mi[MDEG]);\n    des->ncoef = 1;\n    if (nd >= mi[MDEG]) return;\n    if (mi[MDIM]>1)\n    { if (nd>=2) return;\n        if ((nd>=1) && (mi[MKT]==KPROD)) return;\n    }\n    \n    for (i=0; i<mi[MDIM]; i++)\n    { lf->deriv[nd] = i;\n        des->cfn[i+1] = coefnumber(lf->deriv,nd+1,mi[MKT],mi[MDIM],mi[MDEG]);\n    }\n    des->ncoef = 1+mi[MDIM];\n}\n\nvoid fitfunangl(dx,ff,sca,cd,deg)\ndouble dx, *ff, sca;\nINT deg, cd;\n{\n    if (deg>=3) WARN((\"Can't handle angular model with deg>=3\"));\n    \n    switch(cd)\n    { case 0:\n            ff[0] = 1;\n            ff[1] = sin(dx/sca)*sca;\n            ff[2] = (1-cos(dx/sca))*sca*sca;\n            return;\n        case 1:\n            ff[0] = 0;\n            ff[1] = cos(dx/sca);\n            ff[2] = sin(dx/sca)*sca;\n            return;\n        case 2:\n            ff[0] = 0;\n            ff[1] = -sin(dx/sca)/sca;\n            ff[2] = cos(dx/sca);\n            return;\n        default: WARN((\"Can't handle angular model with >2 derivs\"));\n    }\n}\n\nvoid fitfun(lf,x,t,f,deriv,nd)\nlfit *lf;\ndouble *x, *t, *f;\nINT *deriv, nd;\n{ \n    INT d, deg, m, i, j, k, ct_deriv[MXDIM];\n    double ff[MXDIM][1+MXDEG], dx[MXDIM];\n    \n#ifdef SVERSION\n    if (lf->mi[MUBAS])\n    { if (nd>0) WARN((\"User basis does not take derivatives\"));\n        basis(x,t,f,lf->mi[MDIM],lf->mi[MP]);\n        return;\n    }\n#endif\n    \n    d = lf->mi[MDIM];\n    deg = lf->mi[MDEG];\n    m = 0;\n    \n    if (lf->mi[MKT]==KLM)\n    { for (i=0; i<d; i++) f[m++] = x[i];\n        return;\n    }\n    memset(ct_deriv, 0, sizeof(ct_deriv));\n    for (i = 0; i < MXDIM; ++i)\n    {\n        for (j = 0; j < 1 + MXDEG; ++j)\n        {\n            ff[i][j] = 0;\n        }\n    }\n    \n    f[m++] = (nd==0);\n    if (deg==0) return;\n    \n    for (i=0; i<d; i++)\n    { ct_deriv[i] = 0;\n        dx[i] = (t==NULL) ? x[i] : x[i]-t[i];\n    }\n    for (i=0; i<nd; i++) ct_deriv[deriv[i]]++;\n    \n    for (i=0; i<d; i++)\n    { switch(lf->sty[i])\n        {\n            case STANGL:\n                fitfunangl(dx[i],ff[i],lf->sca[i],ct_deriv[i],lf->mi[MDEG]);\n                break;\n            default:\n                for (j=0; j<ct_deriv[i]; j++) ff[i][j] = 0.0;\n                ff[i][ct_deriv[i]] = 1.0;\n                for (j=ct_deriv[i]+1; j<=deg; j++)\n                    ff[i][j] = ff[i][j-1]*dx[i]/(j-ct_deriv[i]);\n        }\n    }\n    \n    /*\n     *  Product kernels. Note that if ct_deriv[i] != nd, that implies\n     *  there is differentiation wrt another variable, and all components\n     *  involving x[i] are 0.\n     */\n    if ((d==1) || (lf->mi[MKT]==KPROD))\n    { for (j=1; j<=deg; j++)\n        for (i=0; i<d; i++)\n            f[m++] = (ct_deriv[i]==nd) ? ff[i][j] : 0.0;\n        return;\n    }\n    \n    /*\n     *  Spherical kernels with the full polynomial basis.\n     *  Presently implemented up to deg=3.\n     */\n    for (i=0; i<d; i++)\n        f[m++] = (ct_deriv[i]==nd) ? ff[i][1] : 0.0;\n    if (deg==1) return;\n    \n    for (i=0; i<d; i++)\n    {\n        /* xi^2/2 terms. */\n        f[m++] = (ct_deriv[i]==nd) ? ff[i][2] : 0.0;\n        \n        /* xi xj terms */\n        for (j=i+1; j<d; j++)\n            f[m++] = (ct_deriv[i]+ct_deriv[j]==nd) ? ff[i][1]*ff[j][1] : 0.0;\n    }\n    if (deg==2) return;\n    \n    for (i=0; i<d; i++)\n    { \n        /* xi^3/6 terms */\n        f[m++] = (ct_deriv[i]==nd) ? ff[i][3] : 0.0;\n        \n        /* xi^2/2 xk terms */\n        for (k=i+1; k<d; k++)\n            f[m++] = (ct_deriv[i]+ct_deriv[k]==nd) ? ff[i][2]*ff[k][1] : 0.0;\n        \n        /* xi xj xk terms */\n        for (j=i+1; j<d; j++)\n        { f[m++] = (ct_deriv[i]+ct_deriv[j]==nd) ? ff[i][1]*ff[j][2] : 0.0;\n            for (k=j+1; k<d; k++)\n                f[m++] = (ct_deriv[i]+ct_deriv[j]+ct_deriv[k]==nd) ?\n                ff[i][1]*ff[j][1]*ff[k][1] : 0.0;\n        }\n    }\n    if (deg==3) return;\n    \n    ERROR((\"fitfun: can't handle deg=%d for spherical kernels\",deg));\n}\n\n/*\n *  Build the design matrix. Assumes des->ind contains the indices of\n *  the required data points; des->n the number of points; des->xev\n *  the fitting point.\n */\nvoid designmatrix(lf,des)\nlfit *lf;\ndesign *des;\n{ int i, ii, j, p;\n    double *X, u[MXDIM];\n    \n    X = d_x(des);\n    p = des->p;\n    \n    if (lf->mi[MUBAS])\n    {\n#ifdef SVERSION\n        vbasis(lf->x,des->xev,lf->mi[MN],lf->mi[MDIM],des->ind,des->n,p,X);\n#else\n        ERROR((\"user basis in S version only\\n\"));\n#endif\n        return;\n    }\n    \n    for (i=0; i<des->n; i++)\n    { ii = des->ind[i];\n        for (j=0; j<lf->mi[MDIM]; j++) u[j] = datum(lf,j,ii);\n        fitfun(lf,u,des->xev,&X[i*p],NULL,(INT)0);\n    }\n}\n"
  },
  {
    "path": "src/locfit/lf_robust.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *   This file includes functions to solve for the scale estimate in\n *   local robust regression and likelihood. The main entry point is\n *   lf_robust(lf,des,noit),\n *   called from the locfit() function.\n *\n *   The update_rs(x) accepts a residual scale x as the argument (actually,\n *   it works on the log-scale). The function computes the local fit\n *   assuming this residual scale, and re-estimates the scale from this\n *   new fit. The final solution satisfies the fixed point equation\n *   update_rs(x)=x. The function lf_robust() automatically calls\n *   update_rs() through the fixed point iterations.\n *\n *   The estimation of the scale from the fit is based on the sqrt of\n *   the median deviance of observations with non-zero weights (in the\n *   gaussian case, this is the median absolute residual).\n *\n *   TODO:\n *     Should use smoothing weights in the median.\n */\n\n#include \"local.h\"\n\nvoid lfiter(lfit* lf, design* des);\n\nextern int lf_status;\ndouble robscale;\n\nstatic lfit *rob_lf;\nstatic design *rob_des;\n\ndouble median(x,n)\ndouble *x;\nINT n;\n{ INT i, j, lt, eq, gt;\n  double lo, hi, s;\n  lo = hi = x[0];\n  for (i=0; i<n; i++)\n  { lo = MIN(lo,x[i]);\n    hi = MAX(hi,x[i]);\n  }\n  if (lo==hi) return(lo);\n  lo -= (hi-lo);\n  hi += (hi-lo);\n  for (i=0; i<n; i++)\n  { if ((x[i]>lo) & (x[i]<hi))\n    { s = x[i]; lt = eq = gt = 0;\n      for (j=0; j<n; j++)\n      { lt += (x[j]<s);\n        eq += (x[j]==s);\n        gt += (x[j]>s);\n      }\n      if ((2*(lt+eq)>n) && (2*(gt+eq)>n)) return(s);\n      if (2*(lt+eq)<=n) lo = s;\n      if (2*(gt+eq)<=n) hi = s;\n    }\n  }\n  return((hi+lo)/2);\n}\n\ndouble nrobustscale(lf,des,rs)\nlfit *lf;\ndesign *des;\ndouble rs;\n{ int i, ii, p;\n  double link[LLEN], sc, sd, sw, e;\n  p = des->p; sc = sd = sw = 0.0;\n  for (i=0; i<des->n; i++)\n  { ii = des->ind[i];\n    des->th[i] = base(lf,ii)+innerprod(des->cf,d_xi(des,i),p);\n    e = resp(lf,ii)-des->th[i];\n    stdlinks(link,lf,ii,des->th[i],rs);\n    sc += des->w[i]*e*link[ZDLL];\n    sd += des->w[i]*e*e*link[ZDDLL];\n    sw += des->w[i];\n  }\n\n  /* newton-raphson iteration for log(s)\n     -psi(ei/s) - log(s); s = e^{-th}\n  */\n  rs *= exp((sc-sw)/(sd+sc));\n  return(rs);\n}\n\ndouble robustscale(lf,des)\nlfit *lf;\ndesign *des;\n{ INT i, ii, p;\n  double rs, link[LLEN];\n  p = des->p;\n  for (i=0; i<des->n; i++)\n  { ii = des->ind[i];\n    des->th[i] = base(lf,ii) + innerprod(des->cf,d_xi(des,i),p);\n    links(des->th[i],resp(lf,ii),lf->mi[MTG]&127,lf->mi[MLINK],link,cens(lf,ii),prwt(lf,ii),1.0);\n    des->res[i] = -2*link[ZLIK];\n  }\n  rs = sqrt(median(des->res,des->n));\n  if (rs==0.0) rs = 1.0;\n  return(rs);\n}\n\ndouble update_rs(x)\ndouble x;\n{\n  if (lf_status != LF_OK) return(x);\n  robscale = exp(x);\n  lfiter(rob_lf,rob_des);\n  if (lf_status != LF_OK) return(x);\n\n  return(log(robustscale(rob_lf,rob_des)));\n}\n\nvoid lf_robust(lf,des)\nlfit *lf;\ndesign *des;\n{ double x;\n  rob_lf = lf;\n  rob_des = des;\n  lf_status = LF_OK;\n\n  x = log(robustscale(lf,des));\n  solve_fp(update_rs, x, 1.0e-6, (int)lf->mi[MMXIT]);\n}\n"
  },
  {
    "path": "src/locfit/lf_vari.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *   Post-fitting functions to compute the local variance and\n *   influence functions. Also the local degrees of freedom\n *   calculations for adaptive smoothing.\n */\n\n#include \"local.h\"\n\nextern double robscale;\n\n/*\n  vmat() computes (after the local fit..) the matrix \n  M2  = X^T W^2 V X.\n  M12 = (X^T W V X)^{-1} M2\n  Also, for convenience, tr[0] = sum(wi) tr[1] = sum(wi^2).\n*/\nvoid vmat(lf, des, M12, M2, tr)\nlfit *lf;\ndesign *des;\ndouble *M12, *M2, *tr;\n{ INT i, p, nk, ok;\n  double link[LLEN], h, ww;\n  p = des->p;\n  setzero(M2,p*p);\n\n  nk = -1;\n\n  /* for density estimation, use integral rather than\n     sum form, if W^2 is programmed...\n  */\n  if ((lf->mi[MTG]<=THAZ) && (lf->mi[MLINK]==LLOG))\n  { switch(lf->mi[MKER])\n    { case WGAUS: nk = WGAUS; h = des->h/SQRT2; break;\n      case WRECT: nk = WRECT; h = des->h; break;\n      case WEPAN: nk = WBISQ; h = des->h; break;\n      case WBISQ: nk = WQUQU; h = des->h; break;\n      case WTCUB: nk = W6CUB; h = des->h; break;\n      case WEXPL: nk = WEXPL; h = des->h/2; break;\n    }\n  }\n\n  tr[0] = tr[1] = 0.0;\n  if (nk != -1)\n  { ok = lf->mi[MKER]; lf->mi[MKER] = nk;\n/* compute M2 using integration. Use M12 as work matrix. */\n    (des->itype)(des->xev, M2, M12, lf, des->cf, h);\n    lf->mi[MKER] = ok;\n    if (lf->mi[MTG]==TDEN) multmatscal(M2,lf->dp[DSWT],p*p);\n    tr[0] = des->ss[0];\n    tr[1] = M2[0]; /* n int W e^<a,A> */\n  }\n  else\n  { for (i=0; i<des->n; i++)\n    { stdlinks(link,lf,des->ind[i],des->th[i],robscale);\n      ww = SQR(des->w[i])*link[ZDDLL];\n      tr[0] += des->w[i];\n      tr[1] += SQR(des->w[i]);\n      addouter(M2,d_xi(des,i),d_xi(des,i),p,ww);\n    }\n  }\n\n  memcpy(M12,M2,p*p*sizeof(double));\n  for (i=0; i<p; i++)\n    jacob_solve(&des->xtwx,&M12[i*p]);\n}\n\n/* Compute influence function and estimated derivatives.\n * Results stored in des->f1.\n * This assumes weight function is scaled so that W(0)=1.0.\n */\ndouble comp_infl(lf,des)\nlfit *lf;\ndesign *des;\n{ unitvec(des->f1,0,des->p);\n  jacob_solve(&des->xtwx,des->f1);\n  return(des->f1[0]);\n}\n\nvoid comp_vari(lf,des,tr,t0)\nlfit *lf;\ndesign *des;\ndouble *tr, *t0;\n{ int i, j, k, p;\n  double *M12, *M2;\n  M12 = des->V; M2 = des->P; p = des->p;\n  vmat(lf,des,M12,M2,tr); /* M2 = X^T W^2 V X  tr0=sum(W) tr1=sum(W*W) */\n  tr[2] = m_trace(M12,p);   /* tr (XTWVX)^{-1}(XTW^2VX) */\n\n  comp_infl(lf,des);\n  for (i=0; i<=lf->mi[MDIM]; i++) t0[i] = des->f1[i];\n\n/*\n * Covariance matrix is M1^{-1} * M2 * M1^{-1}\n * We compute this using the cholesky decomposition of\n * M2; premultiplying by M1^{-1} and squaring. This\n * is more stable than direct computation in near-singular cases.\n */\n  chol_dec(M2,p);\n  for (i=0; i<p; i++) jacob_solve(&des->xtwx,&M2[i*p]);\n  for (i=0; i<p; i++)\n  { for (j=0; j<p; j++)\n    { M12[i*p+j] = 0;\n      for (k=0; k<p; k++)\n        M12[i*p+j] += M2[k*p+i]*M2[k*p+j]; /* ith column of covariance */\n    }\n  }\n  if ((lf->mi[MTG]==TDEN) && (lf->mi[MLINK]==LIDENT))\n    multmatscal(M12,1/SQR(lf->dp[DSWT]),p*p);\n}\n\n/* local_df computes:\n *   tr[0] = trace(W)\n *   tr[1] = trace(W*W)\n *   tr[2] = trace( M1^{-1} M2 )\n *   tr[3] = trace( M1^{-1} M3 )\n *   tr[4] = trace( (M1^{-1} M2)^2 )\n *   tr[5] = var(theta-hat).\n */\nvoid local_df(lf,des,tr)\nlfit *lf;\ndesign *des;\ndouble *tr;\n{ int i, j, p;\n  double *m2, *V, ww, link[LLEN];\n\n  tr[0] = tr[1] = tr[2] = tr[3] = tr[4] = tr[5] = 0.0;\n  m2 = des->V; V = des->P; p = des->p;\n\n  vmat(lf,des,m2,V,tr);  /* M = X^T W^2 V X  tr0=sum(W) tr1=sum(W*W) */\n  tr[2] = m_trace(m2,p);   /* tr (XTWVX)^{-1}(XTW^2VX) */\n\n  unitvec(des->f1,0,p);\n  jacob_solve(&des->xtwx,des->f1);\n  for (i=0; i<p; i++)\n    for (j=0; j<p; j++)\n    { tr[4] += m2[i*p+j]*m2[j*p+i];  /* tr(M^2) */\n      tr[5] += des->f1[i]*V[i*p+j]*des->f1[j]; /* var(thetahat) */\n  }\n  tr[5] = sqrt(tr[5]);\n\n  setzero(m2,p*p);\n  for (i=0; i<des->n; i++)\n  { stdlinks(link,lf,des->ind[i],des->th[i],robscale);\n    ww = SQR(des->w[i])*des->w[i]*link[ZDDLL];\n    addouter(m2,d_xi(des,i),d_xi(des,i),p,ww);\n  }\n  for (i=0; i<p; i++)\n  { jacob_solve(&des->xtwx,&m2[i*p]);\n    tr[3] += m2[i*(p+1)];\n  }\n\n  return;\n}\n"
  },
  {
    "path": "src/locfit/lfcons.h",
    "content": "/*\n *   Copyright (c) 1998 Lucent Technologies.\n *   See README file for details.\n */\n\n/*\n  Numeric values for constants used in locfit\n*/\n\n/*\n  MXDIM and MXDEG are maximum dimension and local polynomial\n  degree for Locfit. Note that some parts of the code may be\n  more restrictive.\n*/\n#define MXDIM 15\n#define MXDEG 7\n\n/*\n  floating point constants\n*/\n#ifndef PI\n#define PI    3.141592653589793238462643\n#endif\n#define S2PI  2.506628274631000502415765\n#define SQRT2 1.4142135623730950488\n#define SQRPI 1.77245385090552\n#define LOGPI 1.144729885849400174143427\n#define GOLDEN 0.61803398874989484820\n#define HL2PI 0.91893853320467267 /* log(2pi)/2 */\n#define SQRPI 1.77245385090552    /* sqrt(pi)   */\n\n/*\n  Criteria for adaptive local fitting  mi[MACRI]\n  1: localized CP;  2: ICI (katkovnik);  3: curvature model index\n  4: Increase bandwidth until locfit returns LF_OK\n*/\n#define ANONE 0\n#define ACP  1\n#define AKAT 2\n#define AMDI 3\n#define AOK  4\n\n/*\n  vector of double precision parameters.\n  0, 1, 2 are the three components of the smoothing parameter.\n  3 cut parameter for adaptive evaluation structures.\n  4-8 are likelihood, degrees of freedom and residual variance,\n  computed as part of the fit.\n  Stored as the lf.dp vector.\n*/\n#define DALP 0\n#define DFXH 1\n#define DADP 2\n#define DCUT 3\n#define DLK  4\n#define DT0  5\n#define DT1  6\n#define DRV  7\n#define DSWT 8\n#define DRSC 9\n#define LEND 10\n\n/*\n  Evaluation structures mi[MEV]\n  EFITP special for `interpolation' at fit points\n*/\n#define ENULL  0\n#define ETREE  1\n#define EPHULL 2\n#define EDATA  3\n#define EGRID  4\n#define EKDTR  5\n#define EKDCE  6\n#define ECROS  7\n#define EPRES  8\n#define EXBAR  9\n#define ENONE  10\n#define EFITP  50\n\n/*\n  integer parameters: sample size; dimension; number of local parameters etc.\n  stored as the lf.mi vector.\n*/\n#define MN     0\n#define MP     1\n#define MDEG0  2\n#define MDEG   3\n#define MDIM   4\n#define MACRI  5\n#define MKER   6\n#define MKT    7\n#define MIT    8\n#define MMINT  9\n#define MMXIT 10\n#define MREN  11\n#define MEV   12\n#define MTG   13\n#define MLINK 14\n#define MDC   15\n#define MK    16\n#define MDEB  17\n#define MGETH 18\n#define MPC   19\n#define MUBAS 20\n#define LENM  21\n\n/*\n  Link functions mi[MLINK].\n  Mostly as in table 4.1 of the book.\n  LDEFAU and LCANON are used to select default and canonical\n  links respectively. LINIT shouldn't be selected by user...\n*/\n#define LINIT  0\n#define LDEFAU 1\n#define LCANON 2\n#define LIDENT 3\n#define LLOG   4\n#define LLOGIT 5\n#define LINVER 6\n#define LSQRT  7\n#define LASIN  8\n\n/*\n  components of vector returned by the links() function\n  in family.c. ZLIK the likelihood; ZMEAN = estimated mean;\n  ZDLL = derivative of log-likelihood; ZDDLL = - second derivative\n*/\n#define LLEN  4\n#define ZLIK  0\n#define ZMEAN 1\n#define ZDLL  2\n#define ZDDLL 3\n\n/*\n  weight functions mi[MKER].\n  see Table 3.1 or the function W() in weights.c for definitions.\n*/\n#define WRECT 1\n#define WEPAN 2\n#define WBISQ 3\n#define WTCUB 4\n#define WTRWT 5\n#define WGAUS 6\n#define WTRIA 7\n#define WQUQU 8\n#define W6CUB 9\n#define WMINM 10\n#define WEXPL 11\n#define WMACL 12\n#define WPARM 13\n\n/*\n  type of multivariate weight function mi[MKT]\n  KSPH (spherical)  KPROD (product)\n  others shouldn't be used at present.\n*/\n#define KSPH   1\n#define KPROD  2\n#define KCE    3\n#define KLM    4\n\n#define STANGL 4\n#define STLEFT 5\n#define STRIGH 6\n#define STCPAR 7\n\n/*\n  Local likelihood family mi[MTG]\n  for quasi-likelihood, add 64.\n*/\n#define TNUL 0\n#define TDEN 1\n#define TRAT 2\n#define THAZ 3\n#define TGAUS 4\n#define TLOGT 5\n#define TPOIS 6\n#define TGAMM 7\n#define TGEOM 8\n#define TCIRC 9\n#define TROBT 10\n#define TRBIN 11\n#define TWEIB 12\n#define TCAUC 13\n#define TPROB 14\n\n/*\n  Integration type mi[MIT] for integration in\n  density estimation.\n*/\n#define INVLD 0\n#define IDEFA 1\n#define IMULT 2\n#define IPROD 3\n#define IMLIN 4\n#define IHAZD 5\n#define IMONT 7\n\n/*\n  For prediction functions, what to predict?\n  PCOEF -- coefficients        PT0   -- influence function\n  PNLX  -- ||l(x)||            PBAND -- bandwidth h(x)\n  PDEGR -- local poly. degree  PLIK  -- max. local likelihood\n  PRDF  -- local res. d.f.     PVARI -- ||l(x)||^2\n*/\n#define PCOEF 1\n#define PT0   2\n#define PNLX  3\n#define PBAND 4\n#define PDEGR 5\n#define PLIK  6\n#define PRDF  7\n#define PVARI 8\n\n/*\n  Residual Types\n*/\n#define RDEV  1\n#define RPEAR 2\n#define RRAW  3\n#define RLDOT 4\n#define RDEV2 5\n#define RLDDT 6\n#define RFIT  7\n#define RMEAN 8\n\n/*\n  components of the colour vector\n*/\n#define CBAK 0\n#define CAXI 1\n#define CTEX 2\n#define CLIN 3\n#define CPOI 4\n#define CCON 5\n#define CCLA 6\n#define CSEG 7\n#define CPA1 8\n#define CPA2 9\n\n/*\n  variable types: double, INT, char, argument list\n*/\n#define VDOUBLE 0\n#define VINT    1\n#define VCHAR   2\n#define VARGL   3\n#define VPREP   4\n#define VARC    5\n#define VVARI   6\n#define VXYZ    7\n\n/*\n  variable status\n*/\n#define STEMPTY   0\n#define STREGULAR 1\n#define STHIDDEN  3\n#define STPLOTVAR 4\n#define STSYSTEM  5\n#define STSYSPEC  6\n#define STREADFI  7\n\n/*\n  return status for the locfit() function\n*/\n#define LF_OK   0\n#define LF_OOB  2   /* out of bounds, or large unstable parameter */\n#define LF_PF   3   /* perfect fit; interpolation; deviance=0 */\n#define LF_NCON 4   /* not converged */\n#define LF_NOPT 6   /* no or insufficient points with non-zero wt */\n#define LF_INFA 7   /* initial failure e.g. log(0) */\n#define LF_DEMP 10  /* density -- empty integration region */\n#define LF_XOOR 11  /* density -- fit point outside xlim region */\n#define LF_DNOP 12  /* density version of 6 */\n#define LF_FPROB 80\n#define LF_BADP 81  /* bad parameters e.g. neg prob for binomial */\n#define LF_LNK  82  /* invalid link */\n#define LF_FAM  83  /* invalid family */\n#define LF_ERR  99  /* error */\n"
  },
  {
    "path": "src/locfit/lfd.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n */\n\n\n/* Functions for reading/writing to LFData directory */\n\n#include <unistd.h>\n#include \"local.h\"\n\n#ifdef CVERSION\n\nFILE *lfd=NULL;\nextern char *lfhome;\nchar filename[100];\n\nvoid closefile()\n{ fclose(lfd);\n  lfd = NULL;\n}\n\nvoid openfile(mode)\nchar *mode;\n{ if (lfd!=NULL) closefile();\n  lfd = fopen(filename,mode);\n}\n\n/*\n *  setfilename() places name[] in the filename[] array.\n *    -- quotes are stripped from name.\n *    -- ext is the default extension; .ext is added as an extension.\n *       (unless fp=1).\n *       If ext = \"lfd\" or \"fit\", the LFData (and paths) are used.\n *    -- mode is a standard unix mode (\"r\", \"w\" etc)\n *    -- fp indicates the full path is given (used by Windoze GUI).\n *    -- checks for validity of filename and mode.\n *    -- returns 0 for successful, 1 for unsuccessful.\n */\nINT setfilename(name,ext,mode,fp)\nchar *name, *ext, *mode;\nINT fp;\n{ char subp[20];\n  int n, quote, use_lfd;\n\n  n = strlen(name);\n  quote = ((name[0]=='\"') && (name[n-1]=='\"'));\n  if (quote)\n  { name++;\n    name[n-2] = '\\0';\n  }\n\n  use_lfd = (strcmp(ext,\"lfd\")==0) | (strcmp(ext,\"fit\")==0);\n  if (fp)\n    sprintf(filename,\"%s\",name);\n  else\n  { if (use_lfd)\n      sprintf(subp,\"LFData%c\",DIRSEP);\n    else\n      sprintf(subp,\"\");\n    if (strlen(ext)==0)\n      sprintf(filename,\"%s%s\",subp,name);\n    else\n      sprintf(filename,\"%s%s.%s\",subp,name,ext);\n  }\n  if (quote) name[n-2] = '\"';\n\n/*\n * If we are writing, check the file is writeable and that the\n * LFData directory exists.\n */\n  if ((mode[0]=='w') | (mode[0]=='a'))\n  { if (use_lfd)\n    { if (access(\"LFData\",F_OK)==-1)\n      { if (access(\".\",W_OK)==0)\n        { printf(\"Creating LFData Directory...\\n\");\n          system(\"mkdir LFData\");\n        }\n      }\n      if (access(\"LFData\",W_OK)==-1)\n      { ERROR((\"LFData directory not writeable\"));\n        return(0);\n      }\n    }\n    return(1);  /* definitive test is whether fopen works. */\n  }\n\n/*\n *  If we are reading, check the file exists.\n *  If it doesn't and use_lfd is true, also check a defined lfhome.\n */\n  if (mode[0]=='r')\n  { if (access(filename,R_OK)==0) return(1);\n\n    if ((use_lfd) && (lfhome!=NULL)) /* search system lfhome */\n    { if (quote) name[n-2] = '\\0';\n      sprintf(filename,\"%s/%s%s.%s\",lfhome,subp,name,ext);\n      if (quote) name[n-2] = '\"';\n      return(access(filename,R_OK)==0);\n    }\n\n    return(0);\n  }\n  ERROR((\"setfilename: invalid mode %s\",mode));\n  return(0);\n}\n\nvoid readchar(c,n)\nchar *c;\nINT n;\n{ fread(c,1,n,lfd);\n}\n\nvoid readstr(z)\nchar *z;\n{ while(1)\n  { readchar(z,1);\n    if (*z=='\\0') return;\n    z++;\n  }\n}\n\nvoid dumpchar(c,n)\nchar *c;\nINT n;\n{ fwrite(c,1,n,lfd);\n}\n\nvoid dumpstr(z)\nchar *z;\n{ dumpchar(z,strlen(z)+1);\n}\n\n#define LFDATAID -281\n\nvoid dosavedata(v,fp)\nvari *v;\nint fp;\n{ void (*fn)(), (*fs)();\n  INT i, n;\n  char *name;\n  vari *v1;\n  if (argarg(v,0)==NULL)\n  { ERROR((\"savedata: no filename\"));\n    return;\n  }\n  name = argarg(v,0);\n\n  if (setfilename(name,\"lfd\",\"wb\",fp)==0)\n  { ERROR((\"savedata: cannot access file %s\",filename));\n    return;\n  }\n  openfile(\"wb\");\n  if (lf_error) return;\n  fn = dumpchar;\n  fs = dumpstr;\n\n  i = LFDATAID;\n  (*fn)(&i, sizeof(INT));\n  n = 0;\n  for (i=1; i<v->n; i++) if (!argused(v,i))\n  { v1 = findvar(argval(v,i),0,&n);\n    if (v==NULL)\n    { WARN((\"variable %s not found; skipping\",argval(v,i)));\n    }\n    else\n    { (*fs)(v1->name);\n      (*fn)(&v1->n,sizeof(INT));\n      (*fn)(&v1->mode,sizeof(INT)); /* mode indicator for later */\n      (*fn)(v1->dpr,v1->n*sizeof(double));\n    }\n    setused(v,i);\n  }\n  (*fs)(\"__end__\");\n  closefile();\n}\n\nvoid doreaddata(name,fp)\nchar *name;\nint fp;\n{ void (*fn)(), (*fs)();\n  INT i, k, md, n, of;\n  varname vn;\n  vari *v;\n\n  if (setfilename(name,\"lfd\",\"rb\",fp)==0)\n  { ERROR((\"readdata: cannot access file %s\",filename));\n    return;\n  }\n  openfile(\"rb\");\n  if (lf_error) return;\n  fn = readchar;\n  fs = readstr;\n\n  of = 0;\n  (*fn)(&i, sizeof(INT));\n  if (i!=LFDATAID) /* wrong or old format */\n  { if (i==-367)\n    { printf(\"Old format LFData file\\n\");\n      of = 1;\n    }\n    else\n    { ERROR((\"not a Locfit data file: %s\",name));\n    }\n  }\n  if (lf_error) { closefile(); return; }\n\n  if (of) /* old format: n nv name (10 char) data */\n  { (*fn)(&n,sizeof(INT));\n    (*fn)(&k,sizeof(INT));\n    for (i=0; i<k; i++)\n    { (*fn)(vn,10);\n      v = createvar(vn,STREGULAR,n,VDOUBLE);\n      (*fn)(v->dpr,n*sizeof(double));\n    }\n  }\n  else /* new format: name (str) n mode data __end__ */\n  { k = 999999;\n    for (i=0; i<k; i++)\n    { (*fs)(vn);\n      if (strcmp(vn,\"__end__\")==0) i=999999;\n      else\n      { (*fn)(&n,sizeof(INT));\n        (*fn)(&md,sizeof(INT));\n        v = createvar(vn,STREGULAR,n,md);\n        (*fn)(v->dpr,n*sizeof(double));\n  } } }\n  closefile();\n}\n\n#define FITID 4395943.3249934\n\nvoid dosavefit(lf,fi,mode,fp)\nlfit *lf;\nchar *fi, *mode;\nint fp;\n{ void (*fn)();\n  double z;\n  INT d = 0, i, k, lm, ld;\n\n  if (fi==NULL) return;\n  if (setfilename(fi,\"fit\",mode,fp)==0)\n  { ERROR((\"savefit: cannot access file %s.\",fi));\n    return;\n  }\n\n  if (mode[0]=='r')\n    fn = readchar;\n  else\n  { if (lf->mi[MEV]==ENULL) ERROR((\"savefit: No fit to save.\"));\n    if (lf_error) return;\n    fn = dumpchar;\n    z = FITID;\n    lm = LENM; ld = LEND;\n    d = lf->mi[MDIM];\n  }\n\n  openfile(mode);\n  (*fn)(&z,sizeof(double));\n\n  if ((mode[0]=='r') && (z!=FITID))\n  { ERROR((\"readfit: file %s is not an evaluation structure\",filename));\n    closefile();\n    return;\n  }\n\n  /* if reading, ensure lf.mi etc are assigned */\n  if (mode[0]=='r') fitdefault(lf,0,1);\n\n  (*fn)(&lm,sizeof(INT));\n  (*fn)(lf->mi,lm*sizeof(INT));\n  (*fn)(&ld,sizeof(INT));\n  (*fn)(lf->dp,LEND*sizeof(double));\n  (*fn)(&lf->nv,sizeof(INT));\n  (*fn)(&lf->nce,sizeof(INT));\n  (*fn)(&lf->vc,sizeof(INT));\n  (*fn)(&lf->nnl,sizeof(INT)); /* no longer used -- delete sometime! */\n\n  if (mode[0]=='r')\n  { d = lf->mi[MDIM];\n    trchck(lf,lf->nv,lf->nce,d,lf->mi[MP],lf->vc);\n    pcchk(&lf->pc,d,lf->mi[MP],1);\n    if ((mode[0]=='r') && (lm<20)) lf->mi[MPC] = 1-noparcomp(lf);\n  }\n  (*fn)(vdptr(lf->xxev),d*lf->nv*sizeof(double));\n  for (i=0; i<3*lf->mi[MDIM]+8; i++)\n    (*fn)(&lf->coef[i*lf->nvm],lf->nv*sizeof(double));\n\n  for (i=0; i<d; i++) (*fn)(lf->xname[i],10);\n  (*fn)(lf->yname,10);\n  (*fn)(lf->bname,10);\n  (*fn)(lf->cname,10);\n  (*fn)(lf->wname,10);\n\n  (*fn)(lf->sv,lf->nce*sizeof(double));\n  (*fn)(lf->fl,2*d*sizeof(double));\n  (*fn)(lf->sca,d*sizeof(double));\n  (*fn)(lf->ce,lf->nce*lf->vc*sizeof(INT));\n  (*fn)(lf->s,lf->nce*sizeof(INT));\n  k = 0;\n  if ((lf->mi[MEV]==EPHULL) | (lf->mi[MEV]==ETREE)) k = lf->nv;\n  if (lf->mi[MEV]==EKDTR) k = lf->nce;\n  (*fn)(lf->lo,k*sizeof(INT));\n  (*fn)(lf->hi,k*sizeof(INT));\n  (*fn)(lf->sty,d*sizeof(INT));\n  if (lf->mi[MEV]==EGRID)\n    (*fn)(lf->mg,d*sizeof(INT));\n  (*fn)(&lf->nd,sizeof(INT));\n  (*fn)(lf->deriv,lf->nd*sizeof(INT));\n\n  (*fn)(vdptr(lf->pc.wk),pc_reqd(d,lf->mi[MP])*sizeof(double));\n  lf->pc.xtwx.p = lf->mi[MP];\n/* MUST save lf->pc.xtwx.sm here */\n  lf->pc.xtwx.sm = lf->pc.xtwx.st = JAC_EIGD;\n\n  closefile();\n}\n\n#endif\n"
  },
  {
    "path": "src/locfit/lffuns.h",
    "content": "\n\n\n/* FILES IN THE src DIRECTORY */\n\n/* adap.c */\nextern double afit(), aband2(), aband3();\nextern INT ainitband();\n\n/* band.c */\nextern void band(), kdeselect();\n\n/* density.c */\nextern INT densinit();\nextern INT fact[];\nextern int likeden();\nextern void prodint_resp(), prresp();\n\n/* dens_haz.c */\nextern void haz_init();\nextern INT hazint();\n\n/* dens_int.c */\nextern double dens_integrate();\nextern void dens_renorm(), dens_lscv(), lforder();\n\n/* dist.c */\nextern double igamma(), ibeta();\nextern double pf(), pchisq(), pnorm();\nextern double df(), dchisq();\n\n/* ev_atree.c */\nextern void atree_start(), atree_grow(), atree_guessnv();\nextern double atree_int();\n\n/* ev_interp.c */\nextern double dointpoint(), cubintd();\nextern double linear_interp(), cubic_interp(), rectcell_interp();\nextern INT exvval();\nextern void exvvalpv(), hermite2();\n\n/* ev_kdtre.c */\nextern void kdtre_start();\nextern double kdtre_int();\n\n/* ev_main.c */\nextern void trchck(), guessnv();\nextern void dataf(), gridf(), crossf(), xbarf(), preset();\nextern INT newsplit();\nextern int lfit_reqd(), lfit_reqi();\n#ifndef CVERSION\nextern vari *createvar();\n#endif\n\n/* ev_trian.c */\nextern void triang_start(), triang_grow();\nextern double triang_int();\n\n/* family.c */\nextern INT links(), stdlinks(), defaultlink(), validlinks();\nextern double b2(), b3(), b4(), lf_link(), invlink();\n\n/* frend.c */\nextern void fitfun(), degfree(), ressumm(), makecfn();\nextern INT procv(), procvraw(), procvvord();\nextern double base(), cens(), prwt(), resp(), getxi(), rss();\nextern INT calcp();\n\n/* kappa0.c */\nextern double critval(), critvalc(), tailp(), taild();\nextern INT constants();\n\n/* lf_dercor.c */\nextern void dercor();\n\n/* lf_fitfun.c */\nextern void fitfun(), designmatrix();\nextern INT calcp(), coefnumber();\n\n/* lf_robust.c */\nextern double median();\nextern void lf_robust();\n\n/* lfstr.c */\nextern void setstrval();\nextern INT ppwhat(), restyp();\n\n/* lf_vari.c */\nextern void comp_vari(), local_df();\nextern double comp_infl();\n\n/* linalg.c */\nextern void svd(), hsvdsolve();\nextern void addouter(), multmatscal();\nextern void QRupd(), QR1(), bacK(), bacT(), solve(), grsc();\nextern void setzero(), unitvec();\nextern void transpose();\nextern double innerprod(), m_trace();\nextern INT svdsolve();\n\n/* locfit.c or parfit.c (most) */\nextern int ident, locfit(), lf_iter();\n\n/* math.c */\nextern double lflgamma(), lferf(), lferfc(), lfdaws();\nextern double ptail(), logit(), expit();\n//extern double lgamma(), erf(), erfc();\nextern int factorial();\n\n/* minmax.c */\nextern double ipower(), minmax();\n\n/* nbhd.c */\nextern double kordstat(), nbhd(), rho();\n\n/* odint.c */\nextern INT onedint();\nextern void recurint();\n\n/* pcomp.c */\nextern double addparcomp();\nextern void compparcomp(), subparcomp(), subparcomp2(), pcchk();\nextern int pc_reqd();\nextern INT noparcomp(), hasparcomp();\n\n/* preplot.c */\nextern void preplot(), cpreplot();\nextern INT setpppoints();\n\n/* resid.c */\nextern double resid();\nextern void cfitted();\nextern vari *vfitted(), *vresid();\n\n/* scb.c */\nextern void scb(), cscbsim();\n\n/* simul.c */\nextern void liksim(), scbsim(), scbmax(), regband(), rband();\n\n/* startlf.c */\nextern void bbox(), deschk(), startlf(), preproc(), fitdefault();\nextern void fitoptions(), clocfit(), endfit();\nextern INT nofit();\n\n/* strings.c */\nextern int stm(), pmatch(), matchlf(), matchrt(), checkltor(), checkrtol();\nextern void strip();\n\n/* wdiag.c */\nextern INT wdiag(), procvhatm();\nextern void cwdiag();\n\n/* weight.c */\nextern double W(), weight(), weightd(), Wd(), Wdd(), wint();\nextern double Wconv(), Wconv1(), Wconv4(), Wconv5(), Wconv6(), Wikk();\nextern INT iscompact(), wtaylor();\n\n/* arith.c */\nextern INT arvect(), intitem();\nextern double areval(), arith(), darith(), dareval();\nextern vari *varith(), *saveresult(), *arbuild();\n\n/* c_args.c */\n#define argused(v,i) (((carg *)viptr(v,i))->used)\n#define setused(v,i) { ((carg *)viptr(v,i))->used = 1; }\n#define setunused(v,i) { ((carg *)viptr(v,i))->used = 0; }\n#define argarg(v,i) (((carg *)viptr(v,i))->arg)\n#define argvalis(v,i,z) (strcmp(argval(v,i),z)==0)\nextern char *argval(), *getargval();\nextern int getarg(), readilist(), getlogic();\n\n/* cmd.c */\nextern int locfit_dispatch(char*);\nextern void setuplf(), recondat(), cmdint();\nextern double backtr(), docrit();\n\n/* c_plot.c */\nextern void plotdata(), plotfit(), plottrack(), plotopt(), setplot();\n\n/* help.c */\nextern void example();\n\n/* lfd.c */\nextern void doreaddata(), dosavedata(), dosavefit();\nextern INT  setfilename();\n\n/* main.c */\nextern void SetWinDev();\n\n/* makecmd.c */\nextern vari *getcmd();\nextern void makecmd(), del_clines(), inc_forvar(), dec_forvar();\n\n/* post.c */\nextern void SetPSDev();\n\n/* pout.c */\nextern INT pretty();\nextern void displayplot();\nextern void plotmaple(), plotmathe(), plotmatlb(), plotgnup(), plotxwin();\n\n/* random.c */\nextern double rnorm(), rexp(), runif(), rpois();\nextern void rseed();\n\n/* readfile.c */\nextern void readfile();\n\n/* scbmax.c */\nextern void cscbmax();\n\n/* vari.c */\n#include \"vari.hpp\"\n\n"
  },
  {
    "path": "src/locfit/lfstr.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *\n *  setstrval() is a  function for converting string arguments to Locfit's\n *    numeric values.  A typical call will be setstrval(lf.mi,MKER,\"gauss\").\n *\n *  components that can be set in this manner are\n *    MKER  (weight function)\n *    MKT   (kernel type -- spherical or product)\n *    MTG   (local likelihood family)\n *    MLINK (link function)\n *    MIT   (integration type for density estimation)\n *    MEV   (evaluation structure)\n *    MACRI (adaptive criterion)\n *\n *  INT ppwhat(str) interprets the preplot what argument.\n *  INT restyp(str) interprets the residual type argument.\n *\n */\n\n#include \"local.h\"\n\nstatic char *famil[17] =\n  { \"density\", \"ate\",   \"hazard\",    \"gaussian\", \"binomial\",\n    \"poisson\", \"gamma\", \"geometric\", \"circular\", \"obust\", \"huber\",\n    \"weibull\", \"cauchy\",\"probab\",    \"logistic\", \"nbinomial\", \"vonmises\" };\nstatic int   fvals[17] = \n  { TDEN,  TRAT,  THAZ,  TGAUS, TLOGT,\n    TPOIS, TGAMM, TGEOM, TCIRC, TROBT, TROBT,\n    TWEIB, TCAUC, TPROB, TLOGT, TGEOM, TCIRC };\n\nINT lffamily(z)\nchar *z;\n{ INT quasi, robu, f;\n  quasi = robu = 0;\n  while ((z[0]=='q') | (z[0]=='r'))\n  { quasi |= (z[0]=='q');\n    robu  |= (z[0]=='r');\n    z++;\n  }\n  f = pmatch(z,famil,fvals,16,-1);\n  if ((z[0]=='o') | (z[0]=='a')) robu = 0;\n  if (f==-1)\n  { WARN((\"unknown family %s\",z));\n    f = TGAUS;\n  }\n  if (quasi) f += 64;\n  if (robu)  f += 128;\n  return(f);\n}\n\nvoid getlffam(z,x)\nchar **z;\nINT *x;\n{ *x = lffamily(z[0]);\n}\n\nstatic char *wfuns[13] = {\n  \"rectangular\", \"epanechnikov\", \"bisquare\",    \"tricube\",\n  \"triweight\",   \"gaussian\",     \"triangular\",  \"ququ\",\n  \"6cub\",        \"minimax\",      \"exponential\", \"maclean\", \"parametric\" };\nstatic int wvals[13] = { WRECT, WEPAN, WBISQ, WTCUB,\n  WTRWT, WGAUS, WTRIA, WQUQU, W6CUB, WMINM, WEXPL, WMACL, WPARM };\n\nstatic char *ktype[3] = { \"spherical\", \"product\", \"center\" };\nstatic int   kvals[3] = { KSPH, KPROD, KCE };\n\nstatic char *ltype[8] = { \"default\", \"canonical\", \"identity\", \"log\",\n                          \"logi\",    \"inverse\",   \"sqrt\",     \"arcsin\" };\nstatic int   lvals[8] = { LDEFAU, LCANON, LIDENT, LLOG,\n                          LLOGIT, LINVER, LSQRT,  LASIN };\n\nstatic char *etype[9] = { \"tree\",     \"phull\", \"data\", \"grid\", \"kdtree\",\n                          \"kdcenter\", \"cross\", \"xbar\", \"none\" };\nstatic int   evals[9] = { ETREE, EPHULL, EDATA, EGRID, EKDTR,\n                          EKDCE, ECROS,  EXBAR, ENONE };\n\nstatic char *itype[6] = { \"default\", \"multi\", \"product\", \"mlinear\",\n                          \"hazard\",  \"monte\" };\nstatic int   ivals[6] = { IDEFA, IMULT, IPROD, IMLIN, IHAZD, IMONT };\n\nstatic char *atype[5] = { \"none\", \"cp\", \"ici\", \"mindex\", \"ok\" };\nstatic int   avals[5] = { ANONE, ACP, AKAT, AMDI, AOK };\n\nvoid setstrval(mi,v,z)\nINT *mi, v;\nchar *z;\n{ \n  switch(v)\n  { case MKER:\n      mi[v] = pmatch(z, wfuns, wvals, 13, WTCUB);\n      return;\n\n    case MKT:\n      mi[v] = pmatch(z, ktype, kvals, 3, KSPH);\n      return;\n\n    case MTG:\n      mi[v] = lffamily(z);\n      return;\n\n    case MLINK:\n      mi[v] = pmatch(z, ltype, lvals, 8, LDEFAU);\n      return;\n\n    case MIT:\n      mi[v] = pmatch(z, itype, ivals, 6, IDEFA);\n      return;\n\n    case MEV:\n      mi[v] = pmatch(z, etype, evals, 9, ETREE);\n      return;\n\n    case MACRI:\n      mi[v] = pmatch(z, atype, avals, 5, ANONE);\n      return;\n  }\n\n  WARN((\"setstrval: invalid value %d\",v));\n  return;\n}\n\nstatic char *rtype[8] = { \"deviance\", \"d2\",    \"pearson\", \"raw\",\n                          \"ldot\",     \"lddot\", \"fit\",     \"mean\" };\nstatic int   rvals[8] = { RDEV, RDEV2, RPEAR, RRAW, RLDOT, RLDDT, RFIT, RMEAN};\n\nstatic char *whtyp[8] = { \"coef\", \"nlx\", \"infl\", \"band\",\n                          \"degr\", \"like\", \"rdf\", \"vari\" };\nstatic int   whval[8] = { PCOEF, PNLX, PT0, PBAND, PDEGR, PLIK, PRDF, PVARI };\n\nINT restyp(z)\nchar *z;\n{ int val;\n  \n  val = pmatch(z, rtype, rvals, 8, -1);\n  if (val==-1) ERROR((\"Unknown type = %s\",z));\n  return((INT)val);\n}\n\nINT ppwhat(z)\nchar *z;\n{ int val;\n  \n  val = pmatch(z, whtyp, whval, 8, -1);\n  if (val==-1) ERROR((\"Unknown what = %s\",z));\n  return((INT)val);\n}\n"
  },
  {
    "path": "src/locfit/lfstruc.h",
    "content": "/*\n *   Copyright (c) 1998-2000 Lucent Technologies.\n *   See README file for details.\n *\n *\n *\n *   Structures, typedefs etc used in Locfit\n */\n\ntypedef char varname[64];\n\n/*\n *  Define the vari type for locfit variables and related macros.\n *  For the C version, an enhanced vari type is needed;\n *  for other versions a simple structure suffices.\n */\n#ifdef CVERSION\n\ntypedef struct {\n  varname name;\n  INT n, bytes, mode, stat;\n  double *dpr; } vari;\n#define checkvarlen(v,n,name,mode) (createvar(name,STSYSTEM,n,mode))\n#define vmode(v) ((v)->mode)\n\n#else\n\ntypedef struct {\n  INT n;\n  double *dpr;\n} vari;\n#define viptr(v,i) (&(v)->dpr[i])\n#define checkvarlen(v,len,name,mode) \\\n   ((((v)!=NULL) && (vlength(v) >= (len))) ? (v) : createvar((name),0,(len),(mode)))\n#endif\n\n#define vlength(v) ((v)->n)\n\ntypedef struct {\n  char *arg, *val;\n  vari *result;\n  INT used; } carg;\n\ntypedef struct {\n  void (*AddColor)(), (*SetColor)(), (*ClearScreen)(), (*TextDim)(), (*DoText)();\n  void (*DrawPoint)(), (*DrawLine)(), (*DrawPatch)(), (*wrapup)();\n  INT (*makewin)(), ticklength, defth, deftw;\n} device;\n\ntypedef struct {\n  vari *wk;\n  double *coef, *xbar, *f;\n  jacobian xtwx; } paramcomp;\n\ntypedef struct {\n  vari *tw, *L, *iw, *xxev;\n  double *x[MXDIM], *y, *w, *base, *c;\n  double *coef, *nlx, *t0, *lik, *h, *deg;\n  double *sv, dp[LEND], kap[3];\n  double sca[MXDIM], fl[2*MXDIM], xl[2*MXDIM];\n  INT *ce, *s, *lo, *hi, sty[MXDIM];\n  INT *mg, nvm, ncm, vc;\n  INT nl, nv, nnl, nce, nk, nn, mi[LENM], ord, deriv[MXDEG+2], nd;\n  paramcomp pc;\n  varname yname, xname[MXDIM], wname, bname, cname; } lfit;\n\n#define datum(lf,i,j) (lf)->x[i][j]\n#define dvari(lf,i)   (lf)->x[i]\n#define evpt(lf,i) (&(lf)->xxev->dpr[(i)*(lf)->mi[MDIM]])\n#define evptx(lf,i,k) ((lf)->xxev->dpr[(i)*(lf)->mi[MDIM]+(k)])\n\ntypedef struct {\n  vari *data[MXDIM], *fit, *se;\n  INT d, wh, gr;\n} pplot;\n\ntypedef struct {\n  char cmd;\n  double x, *v, (*f)();\n  INT m, nx[3];\n  vari *vv; } arstruct;\n\ntypedef struct {\n  vari *x, *y, *z;\n  char type;\n  INT id, t, n, nx, ny, pch; } plxyz;\n\ntypedef struct {\n  double theta, phi, xl[2], yl[2], zl[2], sl[10];\n  INT id, ty, nsl;\n  char main[50], xlab[50], ylab[50], zlab[50];\n  vari *track, *xyzs; } plots;\n\n#define PLNONE 0\n#define PLDATA 1\n#define PLFIT  2\n#define PLTRK  4\n\nstruct lfcol {\n  char name[10];\n  INT n, r, g, b;\n};\n"
  },
  {
    "path": "src/locfit/lfwin.h",
    "content": "#define LFM_EXIT   0\r\n#define LFM_COPY   1\r\n#define LFM_PASTE  2\r\n#define LFM_RUN    3\r\n\r\n#define LFM_READA 10\r\n#define LFM_SAVED 11\r\n#define LFM_READD 12\r\n#define LFM_SUMD  13\r\n#define LFM_PLOTD 18\r\n\r\n#define LFM_LOCF  20\r\n#define LFM_READF 22\r\n#define LFM_SUMF  23\r\n#define LFM_PRFIT 24\r\n\r\n#define LFM_ALPH  70\r\n#define LFM_FIXH  71\r\n#define LFM_APEN  72\r\n#define LFM_DEG0  75\r\n#define LFM_DEG1  76\r\n#define LFM_DEG2  77\r\n#define LFM_DEG3  78\r\n\r\n#define LFM_ABOUT 81\r\n#define LFM_INDEX 82\r\n#define LFM_READM 83\r\n#define LFM_WWW   84\r\n\r\n#define LFP_ROT   10\r\n#define LFP_STY   11\r\n#define LFP_PS    42\r\n#define LFP_COL   13\r\n\r\n#define LFP_XLAB  20\r\n#define LFP_YLAB  21\r\n#define LFP_ZLAB  22\r\n#define LFP_MAIN  23\r\n\r\n#define AB_WWW 10\r\n\r\n#define CM_LINE 1\r\n#define CM_OK   99\r\n\r\n#define RL_ALP  0\r\n#define RL_ALPV 1\r\n#define RL_H    2\r\n#define RL_HV   3\r\n#define RL_PEN  4\r\n#define RL_PENV 5\r\n#define RL_DEG  10\r\n#define RL_FORM 20\r\n#define RL_FAMY 21\r\n#define RL_QUAS 22\r\n#define RL_ROBU 23\r\n#define RL_FIT  98\r\n#define RL_OK   99\r\n\r\n#define RP_VS 1\r\n#define RP_HS 2\r\n#define RP_AUT  3\r\n#define RP_DRAW 98\r\n#define RP_OK   99\r\n\r\n#define PD_X 1\r\n#define PD_Y 2\r\n#define PD_Z 3\r\n#define PD_DRAW 10\r\n#define PD_ADD  11\r\n#define PD_WIN  12\r\n\r\n#define PS_FIL 1\r\n#define PS_DR  8\r\n#define PS_CA  9\r\n#define PS_H 10\r\n#define PS_W 11\r\n\r\n#define SC_COL 1\r\n#define SC_SCO 2\r\n#define SC_DR  8\r\n#define SC_OK  9\r\n\r\n#define VN_VN 1\r\n#define VN_SA 2\r\n#define VN_RF 98\r\n#define VN_CA 99\r\n\r\n#define BP_ALP 1\r\n#define BP_ALV 2\r\n#define BP_AUT 3\r\n#define BP_FIT 4\r\n#define BP_EX 99\r\n\r\n#define GR_CM 10\r\n#define GR_ST 11\r\n\r\n#define LB_LAB  10\r\n#define LB_DRAW 11\r\n\r\n#define LD_QUIT 99\r\n\r\n/* about.c */\r\nextern void AboutDlg();\r\n\r\n/* devwin.c */\r\nextern void getwinsize(), GetFontInfo();\r\n\r\n/* dlgraph.c */\r\nextern void GStyleDlg(), LabelDlg(), PostDlg(), RotateDlg(), SetColDlg();\r\n\r\n/* winfile.c */\r\nextern void ReadFileDlg(), ReadDataDlg(), SaveDataDlg(), RunDlg();\r\nextern void ReadFitDlg();\r\n\r\n/* windlg.c */\r\nextern void BandDlg(), LocfitDlg(), PlotDataDlg(), wlocfit_dispatch();\r\nextern int LFDefDlgProc();\r\n"
  },
  {
    "path": "src/locfit/linalg.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\nvoid svd(x,p,q,d,mxit)  /* svd of square matrix */\ndouble *x, *p, *q;\nINT d, mxit;\n{ INT i, j, k, iter, ms, zer;\n  double r, u, v, cp, cm, sp, sm, c1, c2, s1, s2, mx;\n  for (i=0; i<d; i++)\n    for (j=0; j<d; j++) p[i*d+j] = q[i*d+j] = (i==j);\n  for (iter=0; iter<mxit; iter++)\n  { ms = 0;\n    for (i=0; i<d; i++)\n      for (j=i+1; j<d; j++)\n      { mx = MAX(fabs(x[i*d+j]),fabs(x[j*d+i]));\n        zer = 1;\n        if (mx*mx>1.0e-15*fabs(x[i*d+i]*x[j*d+j]))\n        { if (fabs(x[i*(d+1)])<fabs(x[j*(d+1)]))\n          { for (k=0; k<d; k++)\n            { u = x[i*d+k]; x[i*d+k] = x[j*d+k]; x[j*d+k] = u;\n              u = p[k*d+i]; p[k*d+i] = p[k*d+j]; p[k*d+j] = u;\n            }\n            for (k=0; k<d; k++)\n            { u = x[k*d+i]; x[k*d+i] = x[k*d+j]; x[k*d+j] = u;\n              u = q[k*d+i]; q[k*d+i] = q[k*d+j]; q[k*d+j] = u;\n            }\n          }\n          cp = x[i*(d+1)]+x[j*(d+1)];\n          sp = x[j*d+i]-x[i*d+j];\n          r = sqrt(cp*cp+sp*sp);\n          if (r>0) { cp /= r; sp /= r; }\n              else { cp = 1.0; zer = 0;}\n          cm = x[i*(d+1)]-x[j*(d+1)];\n          sm = x[i*d+j]+x[j*d+i];\n          r = sqrt(cm*cm+sm*sm);\n          if (r>0) { cm /= r; sm /= r; }\n              else { cm = 1.0; zer = 0;}\n          c1 = cm+cp;\n          s1 = sm+sp;\n          r = sqrt(c1*c1+s1*s1);\n          if (r>0) { c1 /= r; s1 /= r; }\n              else { c1 = 1.0; zer = 0;}\n          if (fabs(s1)>ms) ms = fabs(s1);\n          c2 = cm+cp;\n          s2 = sp-sm;\n          r = sqrt(c2*c2+s2*s2);\n          if (r>0) { c2 /= r; s2 /= r; }\n              else { c2 = 1.0; zer = 0;}\n          for (k=0; k<d; k++)\n          { u = x[i*d+k]; v = x[j*d+k];\n            x[i*d+k] = c1*u+s1*v;\n            x[j*d+k] = c1*v-s1*u;\n            u = p[k*d+i]; v = p[k*d+j];\n            p[k*d+i] = c1*u+s1*v;\n            p[k*d+j] = c1*v-s1*u;\n          }\n          for (k=0; k<d; k++)\n          { u = x[k*d+i]; v = x[k*d+j];\n            x[k*d+i] = c2*u-s2*v;\n            x[k*d+j] = s2*u+c2*v;\n            u = q[k*d+i]; v = q[k*d+j];\n            q[k*d+i] = c2*u-s2*v;\n            q[k*d+j] = s2*u+c2*v;\n          }\n          if (zer) x[i*d+j] = x[j*d+i] = 0.0;\n          ms = 1;\n        }\n      }\n    if (ms==0) iter=mxit+10;\n  }\n  if (iter==mxit) WARN((\"svd not converged\"));\n  for (i=0; i<d; i++)\n    if (x[i*d+i]<0)\n    { x[i*d+i] = -x[i*d+i];\n      for (j=0; j<d; j++) p[j*d+i] = -p[j*d+i];\n    }\n}\n\nINT svdsolve(x,w,P,D,Q,d,tol) /* original X = PDQ^T; comp. QD^{-1}P^T x */\ndouble *x, *w, *P, *D, *Q, tol;\nINT d;\n{ INT i, j, rank;\n  double mx;\n  if (tol>0)\n  { mx = D[0];\n    for (i=1; i<d; i++) if (D[i*(d+1)]>mx) mx = D[i*(d+1)];\n    tol *= mx;\n  }\n  rank = 0;\n  for (i=0; i<d; i++)\n  { w[i] = 0.0;\n    for (j=0; j<d; j++) w[i] += P[j*d+i]*x[j];\n  }\n  for (i=0; i<d; i++)\n    if (D[i*d+i]>tol)\n    { w[i] /= D[i*(d+1)];\n      rank++;\n    }\n  for (i=0; i<d; i++)\n  { x[i] = 0.0;\n    for (j=0; j<d; j++) x[i] += Q[i*d+j]*w[j];\n  }\n  return(rank);\n}\n\nvoid hsvdsolve(x,w,P,D,Q,d,tol) /* original X = PDQ^T; comp. D^{-1/2}P^T x */\ndouble *x, *w, *P, *D, *Q, tol;\nINT d;\n{ INT i, j;\n  double mx;\n  if (tol>0)\n  { mx = D[0];\n    for (i=1; i<d; i++) if (D[i*(d+1)]>mx) mx = D[i*(d+1)];\n    tol *= mx;\n  }\n  for (i=0; i<d; i++)\n  { w[i] = 0.0;\n    for (j=0; j<d; j++) w[i] += P[j*d+i]*x[j];\n  }\n  for (i=0; i<d; i++) if (D[i*d+i]>tol) w[i] /= sqrt(D[i*(d+1)]);\n  for (i=0; i<d; i++) x[i] = w[i];\n}\n\nvoid QRupd(X,u,p,w,y)\ndouble *X, *u, *w, y;\nINT p;\n{ INT i, j;\n  double s, c, r, t;\n  for (i=0; i<p; i++)\n  { c = X[i*p+i]; s = u[i];\n    if (s!=0)\n    { r = sqrt(c*c+s*s);\n      c = c/r; s = s/r;\n      for (j=i; j<p; j++)\n      { t = c*X[i*p+j]+s*u[j];\n        u[j] = c*u[j]-s*X[i*p+j];\n        X[i*p+j] = t;\n      }\n      if (w!=NULL)\n      { t = c*w[i]+s*y;\n        y = c*y-s*w[i];\n        w[i] = t;\n      }\n    }\n  }\n}\n\nvoid QR1(X,n,p,w)   /* QR of X (n*p); take w for the ride, if not NULL */\ndouble *X, *w;\nINT n, p;\n{ INT i, j, k, mi;\n  double c, s, mx, nx, t;\n  for (j=0; j<p; j++)\n  { mi = j; mx = fabs(X[(p+1)*j]); nx = mx*mx;\n    for (i=j+1; i<n; i++)\n    { nx += X[p*i+j]*X[p*i+j];\n      if (fabs(X[p*i+j])>mx) { mi = i; mx = fabs(X[p*i+j]); }\n    }\n    for (i=0; i<p; i++)\n    { t = X[p*j+i]; X[p*j+i] = X[p*mi+i]; X[p*mi+i] = t; }\n    if (w != NULL)\n    { t = w[j]; w[j] = w[mi]; w[mi] = t; }\n    if (X[(p+1)*j]>0)\n    { for (i=j; i<p; i++) X[p*j+i] = -X[p*j+i];\n      if (w != NULL) w[j] = -w[j];\n    }\n    nx = sqrt(nx);\n    c = nx*(nx-X[(p+1)*j]);\n    if (c!=0)\n    { for (i=j+1; i<p; i++)\n      { s = 0;\n        for (k=j; k<n; k++)\n          s += X[p*k+i]*X[p*k+j];\n        s = (s-nx*X[p*j+i])/c;\n        for (k=j; k<n; k++)\n          X[p*k+i] -= s*X[p*k+j];\n        X[p*j+i] += s*nx;\n      }\n      if (w != NULL)\n      { s = 0;\n        for (k=j; k<n; k++)\n          s += w[k]*X[p*k+j];\n        s = (s-nx*w[j])/c;\n        for (k=j; k<n; k++)\n          w[k] -= s*X[p*k+j];\n        w[j] += s*nx;\n      }\n      X[p*j+j] = nx;\n   }\n} }\n\nvoid bacK(R,f,p)   /* R^{-1} f */\ndouble *R, *f;\nINT p;\n{ INT i, j;\n  for (i=p-1; i>=0; i--)\n  { for (j=i+1; j<p; j++)\n      f[i] -= R[i*p+j]*f[j];\n    f[i] /= R[i*(p+1)];\n  }\n}\n\nvoid bacT(R,f,p,i0,i1)   /* R^{-1} (R^T)^{-1} f; p columns; use i0-(i1-1) */\ndouble *R, *f;\nINT p;\nint i0;\nint i1;\n{ INT i, j;\n  for (i=i0; i<i1; i++)\n  { for (j=i0; j<i; j++)\n      f[i-i0] -= R[j*p+i]*f[j-i0];\n    f[i-i0] /= R[i*(p+1)];\n  }\n  for (i=i1-1; i>=i0; i--)\n  { for (j=i+1; j<i1; j++)\n      f[i-i0] -= R[i*p+j]*f[j-i0];\n    f[i-i0] /= R[i*(p+1)];\n  }\n}\n\nvoid solve(A,b,d) /* this is crude! A organized by column. */\ndouble *A, *b;\nINT d;\n{ INT i, j, k;\n  double piv;\n  for (i=0; i<d; i++)\n  { piv = A[(d+1)*i];\n    for (j=i; j<d; j++) A[j*d+i] /= piv;\n    b[i] /= piv;\n    for (j=0; j<d; j++) if (j != i)\n    { piv = A[i*d+j];\n      A[i*d+j] = 0;\n      for (k=i+1; k<d; k++)\n        A[k*d+j] -= piv*A[k*d+i];\n      b[j] -= piv*b[i];\n    }\n  }\n}\n\nvoid grsc(X,d)\ndouble *X;\nINT d;\n{ INT i, j, k;\n  double nx;\n  for (i=0; i<d; i++)\n  { nx = 0;\n    for (j=0; j<d; j++) nx += X[i*d+j]*X[i*d+j];\n    nx = sqrt(nx);\n    for (j=0; j<d; j++) X[i*d+j] /= nx;\n    for (j=i+1; j<d; j++)\n    { nx = 0;\n      for (k=0; k<d; k++) nx += X[i*d+k]*X[j*d+k];\n      for (k=0; k<d; k++) X[j*d+k] -= nx*X[i*d+k];\n    }\n  }\n}\n\nvoid setzero(v,p)\ndouble *v;\nINT p;\n{ int i;\n  for (i=0; i<p; i++) v[i] = 0.0;\n}\n\nvoid unitvec(x,k,p)\ndouble *x;\nINT k, p;\n{ setzero(x,p);\n  x[k] = 1.0;\n}\n\ndouble innerprod(v1,v2,p)\ndouble *v1, *v2;\nINT p;\n{ int i;\n  double s;\n  s = 0;\n  for (i=0; i<p; i++) s += v1[i]*v2[i];\n  return(s);\n}\n\nvoid addouter(re,v1,v2,p,c)\ndouble *re, *v1, *v2, c;\nINT p;\n{ int i, j;\n  for (i=0; i<p; i++)\n    for (j=0; j<p; j++)\n      re[i*p+j] += c*v1[i]*v2[j];\n}\n\nvoid multmatscal(A,z,n)\ndouble *A, z;\nINT n;\n{ INT i;\n  for (i=0; i<n; i++) A[i] *= z;\n}\n\n/*\n *  transpose() transposes an m*n matrix in place.\n *  At input, the matrix has n rows, m columns and\n *    x[0..n-1] is the is the first column.\n *  At output, the matrix has m rows, n columns and\n *    x[0..m-1] is the first column.\n */\nvoid transpose(x,m,n)\ndouble *x;\nINT m, n;\n{ INT t0, t, ti, tj;\n  double z;\n  for (t0=1; t0<m*n-2; t0++)\n    { ti = t0%m; tj = t0/m;\n      do\n      { t = ti*n+tj;\n        ti= t%m;\n        tj= t/m;\n      } while (t<t0);\n      z = x[t];\n      x[t] = x[t0];\n      x[t0] = z;\n    }\n}\n\n/* trace of an n*n square matrix. */\ndouble m_trace(x,n)\ndouble *x;\nint n;\n{ int i;\n  double sum;\n  sum = 0;\n  for (i=0; i<n; i++)\n    sum += x[i*(n+1)];\n  return(sum);\n}\n"
  },
  {
    "path": "src/locfit/local.h",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n * \n *\n *  Most of the changes formerly needed here are handled through\n *  the Makefiles and #ifdef's.\n *\n *\n */\n\n#define CVERSION 1\n\n#ifndef I_LF_H\n#define I_LF_H\n\n/*RVERSION*/\n\n/*\n *   DIRSEP: '/' for unix; '\\\\' for DOS\n */\n#ifdef DOS\n#define DIRSEP '\\\\'\n#else\n#define DIRSEP '/'\n#endif\n\n\n/*\n   Some older math libraries have no lgamma() function, and gamma(arg)\n   actually returns log(gamma(arg)). If so, you need to change\n   LGAMMA macro below.\n\n   If all else fails, you can also use lflgamma().\n\n   Use the definitions for erf, erfc and daws only if your\n   math libraries don't include these functions.\n */\n#ifdef DOS\n#define LGAMMA(arg) lflgamma(arg)\n#define erf(x) lferf(x)\n#define erfc(x) lferfc(x)\n#else\n#define LGAMMA(arg) lgamma(arg)\n#endif\n#define daws(x) lfdaws(x)\n\n\n/*\n   Does your system support popen() and pclose()\n   for pipes? For most flavours of unix, yes.\n   For other OS's, usually not, and you'll need to\n   uncomment the following line.\n\n   (This is only relevant if making the C version).\n*/\n/* #define NOPIPES */\n\n\n/*\n   (the #ifdef's below should now take care of this).\n   the INT type is used for all integers provided in .C() calls from S.\n   For the S version, this should be long int.\n   For the R version, should be int.\n   For the C version, either is adequate.\n   Usually this only makes a difference on 64 bit systems.\n*/\n\n//#ifndef SWINVERSION\n\n//#ifdef RVERSION\n//typedef int INT;\n//#else\n//#ifdef SVERSION\n//typedef long int INT;\n//#else\ntypedef int INT;\n//#endif /* SVERSION */\n//#endif /* RVERSION */\n\n//#endif /* SWINVERSION */\n\n/******** NOTHING BELOW HERE NEEDS CHANGING **********/\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <math.h>\n\n#ifdef RVERSION\n#undef LGAMMA\n#define LGAMMA(arg) Rf_lgammafn(arg)\nextern double Rf_lgammafn();\n#define SVERSION\n#endif\n\n#ifdef SWINVERSION\n#define SVERSION\n#include \"newredef.h\"\n#endif\n\n#include \"mutil.h\"\n#include \"lfcons.h\"\n#include \"lfstruc.h\"\n#include \"design.h\"\n#include \"lffuns.h\"\n\n#ifdef CVERSION\n//#undef printf\n//#define printf lfprintf\n//extern int lfprintf(const char *format, ...);\n//extern int printf(const char *format, ...);\n#endif\n\n#ifdef SVERSION\n#define printf printf\n#endif\n\n#ifdef INTERFACE\n#define printf printf\n#endif\n\n#define ERROR(args) printf(\"Error: \"), printf args , printf(\"\\n\"), lf_error=1\n#define WARN(args)  printf(\"Warning: \"),printf args, printf(\"\\n\")\n\n#define MAX(a,b) (((a)>(b)) ? (a) : (b))\n#define MIN(a,b) (((a)<(b)) ? (a) : (b))\n#define SGN(x) (((x)>0) ? 1 : -1)\n#define SQR(x) ((x)*(x))\n#define NOSLN 0.1278433\n#define GFACT 2.5\n#define EFACT 3.0\n\n#define MAXCOLOR 20\n#define MAXWIN 5\n\n#ifdef SWINVERSION\n#define ISWAP(a,b) { int zz; zz = a; a = b; b = zz; }\n#else\n#define ISWAP(a,b) { INT zz; zz = a; a = b; b = zz; }\nextern INT lf_error;\n#endif\n\nextern INT lf_error;\n\ndouble lf_exp(double x);\n\n#endif /* I_LF_H */\n"
  },
  {
    "path": "src/locfit/locfit.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\nstatic double s0, s1, tol;\nstatic lfit   *lf_lf;\nstatic design *lf_des;\nint lf_status;\nint ident=0;\nint (*like)();\nextern double robscale;\n\nint likereg(coef, lk0, f1, Z)\ndouble *coef, *lk0, *f1, *Z;\n{ INT i, ii, j, p, *mi;\n    double lk, ww, link[LLEN], *X;\n    lf_status = LF_OK;\n    lk = 0.0; p = lf_des->p;\n    mi = lf_lf->mi;\n    setzero(Z,p*p);\n    setzero(f1,p);\n    for (i=0; i<lf_des->n; i++)\n    { ii = lf_des->ind[i];\n        X = d_xi(lf_des,i);\n        lf_des->th[i] = base(lf_lf,ii)+innerprod(coef,X,p);\n        lf_status = stdlinks(link,lf_lf,ii,lf_des->th[i],robscale);\n        if (lf_status == LF_BADP)\n        { *lk0 = -1.0e300;\n            return(NR_REDUCE);\n        }\n        if (lf_error) lf_status = LF_ERR;\n        if (lf_status != LF_OK) return(NR_BREAK);\n        \n        ww = lf_des->w[i];\n        lk += ww*link[ZLIK];\n        for (j=0; j<p; j++)\n            f1[j] += X[j]*ww*link[ZDLL];\n        addouter(Z, X, X, p, ww*link[ZDDLL]);\n    }\n    if (mi[MDEB]>2) prresp(coef,Z,p);\n    if (mi[MDEB]>1) printf(\"  likelihood: %8.5f\\n\",lk);\n    *lk0 = lf_des->llk = lk;\n    \n    switch (lf_lf->mi[MTG]&63) /* parameter checks */\n    { case TGAUS: /* prevent iterations! */\n            if ((mi[MLINK]==LIDENT)&((mi[MTG]&128)==0)) return(NR_BREAK);\n            break;\n        case TPOIS:\n        case TGEOM:\n        case TWEIB:\n        case TGAMM:\n            if ((mi[MLINK]==LLOG) && (fabs(coef[0])>700))\n            { lf_status = LF_OOB;\n                return(NR_REDUCE);\n            }\n            if (lk > -1.0e-5*s0)\n            { lf_status = LF_PF;\n                return(NR_REDUCE);\n            }\n            break;\n        case TRBIN:\n        case TLOGT:\n            if (lk > -1.0e-5*s0)\n            { lf_status = LF_PF;\n                return(NR_REDUCE);\n            }\n            if (fabs(coef[0])>700)\n            { lf_status = LF_OOB;\n                return(NR_REDUCE);\n            }\n            break;\n    }\n    return(NR_OK);\n}\n\nINT robustinit(lf,des)\nlfit *lf;\ndesign *des;\n{ int i;\n    for (i=0; i<des->n; i++)\n        des->res[i] = resp(lf,des->ind[i])-base(lf,des->ind[i]);\n    des->cf[0] = median(des->res,des->n);\n    for (i=1; i<des->p; i++) des->cf[i] = 0.0;\n    tol = 1.0e-6;\n    return(LF_OK);\n}\n\nINT circinit(lf,des)\nlfit *lf;\ndesign *des;\n{ int i, ii;\n    double s0, s1;\n    s0 = s1 = 0.0;\n    for (i=0; i<des->n; i++)\n    { ii = des->ind[i];\n        s0 += des->w[i]*prwt(lf,ii)*sin(resp(lf,ii)-base(lf,ii));\n        s1 += des->w[i]*prwt(lf,ii)*cos(resp(lf,ii)-base(lf,ii));\n    }\n    des->cf[0] = atan2(s0,s1);\n    for (i=1; i<des->p; i++) des->cf[i] = 0.0;\n    tol = 1.0e-6;\n    return(LF_OK);\n}\n\nINT reginit(lf,des)\nlfit *lf;\ndesign *des;\n{ int i, ii;\n    double sb, link[LLEN];\n    s0 = s1 = sb = 0;\n    for (i=0; i<des->n; i++)\n    { ii = des->ind[i];\n        links(base(lf,ii),resp(lf,ii),lf->mi[MTG],LINIT,link,cens(lf,ii),prwt(lf,ii),1.0);\n        s1 += des->w[i]*link[ZDLL];\n        s0 += des->w[i]*prwt(lf,ii);\n        sb += des->w[i]*prwt(lf,ii)*base(lf,ii);\n    }\n    if (s0==0) return(LF_NOPT); /* no observations with W>0 */\n    setzero(des->cf,des->p);\n    tol = 1.0e-6*s0;\n    switch(lf->mi[MLINK])\n    { case LIDENT:\n            des->cf[0] = (s1-sb)/s0;\n            return(LF_OK);\n        case LLOG:\n            if (s1<=0.0)\n            { des->cf[0] = -1000;\n                return(LF_INFA);\n            }\n            des->cf[0] = log(s1/s0) - sb/s0;\n            return(LF_OK);\n        case LLOGIT:\n            if (s1<=0.0)\n            { des->cf[0] = -1000;\n                return(LF_INFA);\n            }\n            if (s1>=s0)\n            { des->cf[0] = +1000;\n                return(LF_INFA);\n            }\n            des->cf[0] = logit(s1/s0)-sb/s0;\n            return(LF_OK);\n        case LINVER:\n            if (s1<=0.0)\n            { des->cf[0] = 1000;\n                return(LF_INFA);\n            }\n            des->cf[0] = s0/s1-sb/s0;\n            return(LF_OK);\n        case LSQRT:\n            des->cf[0] = sqrt(s1/s0)-sb/s0;\n            return(LF_OK);\n        case LASIN:\n            des->cf[0] = asin(sqrt(s1/s0))-sb/s0;\n            return(LF_OK);\n        default:\n            ERROR((\"reginit: invalid link %d\",lf->mi[MLINK]));\n            return(LF_ERR);\n    }\n}\n\nint lfinit(lf,des)\nlfit *lf;\ndesign *des;\n{ \n    //double u[MXDIM];\n    INT *mi;\n    \n    mi = lf->mi;\n    des->xtwx.sm = (mi[MDEG0]<mi[MDEG]) ? JAC_CHOL : JAC_EIGD;\n    \n    designmatrix(lf,des);\n    \n    like = likereg;\n    switch(mi[MTG]&63)\n    { case TDEN:\n        case TRAT:\n        case THAZ:\n            like = likeden;\n            tol = (mi[MLINK]==LLOG) ? 1.0e-6 : 0.0;\n            return(densinit(lf,des,des->h,des->cf,des->n));\n        case TCAUC:\n        case TROBT:\n            return(robustinit(lf,des));\n        case TCIRC:\n            return(circinit(lf,des));\n        default:\n            return(reginit(lf,des));\n    }\n}\n\nvoid lfiter(lf,des)\nlfit *lf;\ndesign *des;\n{ int err;\n    max_nr(like, des->cf, des->oc, des->res, des->f1,\n           &des->xtwx, (int)des->p, (int)lf->mi[MMXIT], tol, &err);\n    switch(err)\n    { case NR_OK: return;\n        case NR_NCON:\n            WARN((\"max_nr not converged\"));\n            return;\n        case NR_NDIV:\n            WARN((\"max_nr reduction problem\"));\n            return;\n    }\n    WARN((\"max_nr return status %d\",err));\n}\n\nint use_robust_scale(int tg)\n{ if ((tg&64)==0) return(0); /* not quasi - no scale */\n    if (((tg&128)==0) & (((tg&63)!=TROBT) & ((tg&63)!=TCAUC))) return(0);\n    return(1);\n}\n\nint locfit(lf,des,h,noit)\nlfit *lf;\ndesign *des;\ndouble h;\nint noit;\n{ int i, p;\n    \n    if (lf->mi[MDEB]>0)\n    { printf(\"locfit: \");\n        for (i=0; i<lf->mi[MDIM]; i++) printf(\" %10.6f\",des->xev[i]);\n        printf(\"  h = %8.5f\\n\",h);\n    }\n    \n    lf_lf  = lf;\n    lf_des = des;\n    des->h = h;\n    p = des->p;\n    \n    lf_status = lfinit(lf,des);\n    if (lf_status != LF_OK) return(lf_status);\n    \n    if (use_robust_scale((int)lf->mi[MTG]))\n        lf_robust(lf,des);\n    else\n    { robscale = 1.0;\n        lfiter(lf,des);\n    }\n    \n    if (lf_status == LF_OOB)\n        for (i=1; i<p; i++) des->cf[i] = 0.0;\n    \n    if ((lf->mi[MTG]&63)==TDEN) /* convert from rate to density */\n    { switch(lf->mi[MLINK])\n        { case LLOG:\n                des->cf[0] -= log(lf->dp[DSWT]);\n                break;\n            case LIDENT:\n                multmatscal(des->cf,1.0/lf->dp[DSWT],des->p);\n                break;\n            default: ERROR((\"Density adjustment; invalid link\"));\n        }\n    }\n    \n    return(lf_status);\n}\n"
  },
  {
    "path": "src/locfit/m_chol.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include <math.h>\n#include \"mutil.h\"\n\nvoid chol_dec(A,n)\ndouble *A;\nint n;\n{ int i, j, k;\n  for (j=0; j<n; j++)\n  { k = n*j+j;\n    for (i=0; i<j; i++) A[k] -= A[n*i+j]*A[n*i+j];\n    if (A[k]<=0)\n    { for (i=j; i<n; i++) A[n*j+i] = 0.0; }\n    else\n    { A[k] = sqrt(A[k]);\n      for (i=j+1; i<n; i++)\n      { for (k=0; k<j; k++)\n          A[n*j+i] -= A[n*k+i]*A[n*k+j];\n        A[n*j+i] /= A[n*j+j];\n      }\n    }\n  }\n  for (j=0; j<n; j++)\n    for (i=j+1; i<n; i++) A[n*i+j] = 0.0;\n}\n\nint chol_solve(A,v,p)\ndouble *A, *v;\nint p;\n{ int i, j;\n\n  for (i=0; i<p; i++)\n  { for (j=0; j<i; j++) v[i] -= A[j*p+i]*v[j];\n    v[i] /= A[i*p+i];\n  }\n  for (i=p-1; i>=0; i--)\n  { for (j=i+1; j<p; j++) v[i] -= A[i*p+j]*v[j];\n    v[i] /= A[i*p+i];\n  }\n  return(p);\n}\n\nint chol_hsolve(A,v,p)\ndouble *A, *v;\nint p;\n{ int i, j;\n\n  for (i=0; i<p; i++)\n  { for (j=0; j<i; j++) v[i] -= A[j*p+i]*v[j];\n    v[i] /= A[i*p+i];\n  }\n  return(p);\n}\n\ndouble chol_qf(A,v,p)\ndouble *A, *v;\nint p;\n{ int i, j;\n  double sum;\n \n  sum = 0.0;\n  for (i=0; i<p; i++)\n  { for (j=0; j<i; j++) v[i] -= A[j*p+i]*v[j];\n    v[i] /= A[i*p+i];\n    sum += v[i]*v[i];\n  }\n  return(sum);\n}\n"
  },
  {
    "path": "src/locfit/m_eigen.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include <math.h>\n#include \"mutil.h\"\n#define E_MAXIT 20\n#define E_TOL 1.0e-8\n#define SQR(x) ((x)*(x))\n\ndouble e_tol(D,p)\ndouble *D;\nint p;\n{ double mx;\n  int i;\n  if (E_TOL <= 0.0) return(0.0);\n  mx = D[0];\n  for (i=1; i<p; i++) if (D[i*(p+1)]>mx) mx = D[i*(p+1)];\n  return(E_TOL*mx);\n}\n\nvoid eig_dec(X,P,d)\ndouble *X, *P;\nint d;\n{ int i, j, k, iter, ms;\n  double c, s, r, u, v;\n\n  for (i=0; i<d; i++)\n    for (j=0; j<d; j++) P[i*d+j] = (i==j);\n\n  for (iter=0; iter<E_MAXIT; iter++)\n  { ms = 0;\n    for (i=0; i<d; i++)\n      for (j=i+1; j<d; j++)\n        if (SQR(X[i*d+j]) > 1.0e-15*fabs(X[i*d+i]*X[j*d+j]))\n        { c = (X[j*d+j]-X[i*d+i])/2;\n          s = -X[i*d+j];\n          r = sqrt(c*c+s*s);\n          c /= r;\n          s = sqrt((1-c)/2)*(2*(s>0)-1);\n          c = sqrt((1+c)/2);\n          for (k=0; k<d; k++)\n          { u = X[i*d+k]; v = X[j*d+k];\n            X[i*d+k] = u*c+v*s;\n            X[j*d+k] = v*c-u*s;\n          }\n          for (k=0; k<d; k++)\n          { u = X[k*d+i]; v = X[k*d+j];\n            X[k*d+i] = u*c+v*s;\n            X[k*d+j] = v*c-u*s;\n          }\n          X[i*d+j] = X[j*d+i] = 0.0;\n          for (k=0; k<d; k++)\n          { u = P[k*d+i]; v = P[k*d+j];\n            P[k*d+i] = u*c+v*s;\n            P[k*d+j] = v*c-u*s;\n          }\n          ms = 1;\n        }\n    if (ms==0) return;\n  }\n  //printf(\"eig_dec not converged\\n\");\n}\n\nint eig_solve(J,x)\njacobian *J;\ndouble *x;\n{ int d, i, j, rank;\n  double  *D, *P, *Q, *w;\n  double tol;\n\n  D = J->Z;\n  P = Q = J->Q;\n  d = J->p;\n  w = J->wk;\n\n  tol = e_tol(D,d);\n\n  rank = 0;\n  for (i=0; i<d; i++)\n  { w[i] = 0.0;\n    for (j=0; j<d; j++) w[i] += P[j*d+i]*x[j];\n  }\n  for (i=0; i<d; i++)\n    if (D[i*d+i]>tol)\n    { w[i] /= D[i*(d+1)];\n      rank++;\n    }\n  for (i=0; i<d; i++)\n  { x[i] = 0.0;\n    for (j=0; j<d; j++) x[i] += Q[i*d+j]*w[j];\n  }\n  return(rank);\n}\n\nint eig_hsolve(J,v)\njacobian *J;\ndouble *v;\n{ int i, j, p, rank;\n  double *D, *Q, *w;\n  double tol;\n\n    rank = 0;\n  D = J->Z;\n  Q = J->Q;\n  p = J->p;\n  w = J->wk;\n\n  tol = e_tol(D,p);\n\n  for (i=0; i<p; i++)\n  { w[i] = 0.0;\n    for (j=0; j<p; j++) w[i] += Q[j*p+i]*v[j];\n  }\n  for (i=0; i<p; i++)\n    if (D[i*p+i]>tol)\n    { w[i] /= sqrt(D[i*(p+1)]);\n      rank++;\n    }\n  return(rank);\n}\n\ndouble eig_qf(J,v)\njacobian *J;\ndouble *v;\n{ int i, j, p;\n  double sum, tol;\n\n  p = J->p;\n  sum = 0.0;\n  tol = e_tol(J->Z,p);\n\n  for (i=0; i<p; i++)\n    if (J->Z[i*p+i]>tol)\n    { J->wk[i] = 0.0;\n      for (j=0; j<p; j++) J->wk[i] += J->Q[j*p+i]*v[j];\n      sum += J->wk[i]*J->wk[i]/J->Z[i*p+i];\n    }\n  return(sum);\n}\n"
  },
  {
    "path": "src/locfit/m_jacob.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include <stdlib.h>\n#include \"math.h\"\n#include \"stdio.h\"\n#include \"mutil.h\"\n\n#define DEF_METH JAC_EIGD\n\nint jac_reqd(int p) { return(2*p*(p+1)); }\n\ndouble *jac_alloc(J,p,wk)\njacobian *J;\nint p;\ndouble *wk;\n{ if (wk==NULL)\n    wk = (double *)calloc(2*p*(p+1),sizeof(double));\n  J->Z = wk; wk += p*p;\n  J->Q = wk; wk += p*p;\n  J->wk= wk; wk += p;\n  J->dg= wk; wk += p;\n  return(wk);\n}\n\nvoid jacob_dec(J, meth)\njacobian *J;\nint meth;\n{ int i, j, p;\n\n  if (J->st != JAC_RAW) return;\n\n  J->sm = J->st = meth;\n  switch(meth)\n  { case JAC_EIG:\n      eig_dec(J->Z,J->Q,J->p);\n      return;\n    case JAC_EIGD:\n      p = J->p;\n      for (i=0; i<p; i++)\n        J->dg[i] = (J->Z[i*(p+1)]<=0) ? 0.0 : 1/sqrt(J->Z[i*(p+1)]);\n      for (i=0; i<p; i++)\n        for (j=0; j<p; j++)\n          J->Z[i*p+j] *= J->dg[i]*J->dg[j];\n      eig_dec(J->Z,J->Q,J->p);\n      J->st = JAC_EIGD;\n      return;\n    case JAC_CHOL:\n      chol_dec(J->Z,J->p);\n      return;\n    default: printf(\"jacob_dec: unknown method %d\",meth);\n  }\n}\n\nint jacob_solve(J,v) /* (X^T W X)^{-1} v */\njacobian *J;\ndouble *v;\n{ int i, rank;\n\n  if (J->st == JAC_RAW) jacob_dec(J,DEF_METH);\n\n  switch(J->st)\n  { case JAC_EIG:\n      return(eig_solve(J,v));\n    case JAC_EIGD:\n      for (i=0; i<J->p; i++) v[i] *= J->dg[i];\n      rank = eig_solve(J,v);\n      for (i=0; i<J->p; i++) v[i] *= J->dg[i];\n      return(rank);\n    case JAC_CHOL:\n      return(chol_solve(J->Z,v,J->p));\n  }\n  printf(\"jacob_solve: unknown method %d\",J->st);\n  return(0);\n}\n\nint jacob_hsolve(J,v) /*  J^{-1/2} v */\njacobian *J;\ndouble *v;\n{ int i;\n\n  if (J->st == JAC_RAW) jacob_dec(J,DEF_METH);\n\n  switch(J->st)\n  { case JAC_EIG:\n      return(eig_hsolve(J,v));\n    case JAC_EIGD: /* eigenvalues on corr matrix */\n      for (i=0; i<J->p; i++) v[i] *= J->dg[i];\n      return(eig_hsolve(J,v));\n    case JAC_CHOL:\n      return(chol_hsolve(J->Z,v,J->p));\n  }\n  printf(\"jacob_hsolve: unknown method %d\",J->st);\n  return(0);\n}\n\ndouble jacob_qf(J,v)  /* vT J^{-1} v */\njacobian *J;\ndouble *v;\n{ int i;\n\n  if (J->st == JAC_RAW) jacob_dec(J,DEF_METH);\n\n  switch (J->st)\n  { case JAC_EIG:\n      return(eig_qf(J,v));\n    case JAC_EIGD:\n      for (i=0; i<J->p; i++) v[i] *= J->dg[i];\n      return(eig_qf(J,v));\n    case JAC_CHOL:\n      return(chol_qf(J->Z,v,J->p));\n    default:\n      printf(\"jacob_qf: invalid method\\n\");\n      return(0.0);\n  }\n}\n"
  },
  {
    "path": "src/locfit/m_max.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *  Routines for maximization of a one dimensional function f()\n *    over an interval [xlo,xhi]. In all cases. the flag argument\n *    controls the return:\n *      flag='x', the maximizer xmax is returned.\n *                otherwise, maximum f(xmax) is returned.\n *\n *  max_grid(f,xlo,xhi,n,flag)\n *    grid maximization of f() over [xlo,xhi] with n intervals.\n *\n *  max_golden(f,xlo,xhi,n,tol,err,flag)\n *    golden section maximization.\n *    If n>2, an initial grid search is performed with n intervals\n *      (this helps deal with local maxima).\n *    convergence criterion is |x-xmax| < tol.\n *    err is an error flag.\n *    if flag='x', return value is xmax.\n *       otherwise, return value is f(xmax).\n *\n *  max_quad(f,xlo,xhi,n,tol,err,flag)\n *    quadratic maximization.\n *\n *  max_nr()\n *    newton-raphson, handles multivariate case.\n *\n *  TODO: additional error checking, non-convergence stop.\n */\n\n#include <math.h>\n#include <string.h>\n#include \"mutil.h\"\nextern double innerprod();\n\n#define gold_rat 0.6180339887498948482045870\n#define max_val(x,y) ((flag=='x') ? x : y)\n\ndouble max_grid(f,xlo,xhi,n,flag)\ndouble (*f)(), xlo, xhi;\nint n;\nchar flag;\n{ int i, mi;\n    mi = 0;\n    double x, y, mx, my;\n    my = 0.0;\n    for (i=0; i<=n; i++)\n    { x = xlo + (xhi-xlo)*i/n;\n        y = f(x);\n        if ((i==0) || (y>my))\n        { mx = x;\n            my = y;\n            mi = i;\n        }\n    }\n    if (mi==0) return(max_val(xlo,my));\n    if (mi==n) return(max_val(xhi,my));\n    return(max_val(mx,my));\n}\n\ndouble max_golden(f,xlo,xhi,n,tol,err,flag)\ndouble (*f)(), xhi, xlo, tol;\nint n, *err;\nchar flag;\n{ double x0, x1, x2, x3, y0, y1, y2, y3;\n    *err = 0;\n    \n    if (n>2)\n    { x0 = max_grid(f,xlo,xhi,n,'x');\n        if (xlo<x0) xlo = x0-1.0/n;\n        if (xhi>x0) xhi = x0+1.0/n;\n    }\n    \n    x0 = xlo; y0 = f(xlo);\n    x3 = xhi; y3 = f(xhi);\n    x1 = gold_rat*x0 + (1-gold_rat)*x3; y1 = f(x1);\n    x2 = gold_rat*x3 + (1-gold_rat)*x1; y2 = f(x2);\n    \n    while (fabs(x3-x0)>tol)\n    { if ((y1>=y0) && (y1>=y2))\n    { x3 = x2; y3 = y2;\n        x2 = x1; y2 = y1;\n        x1 = gold_rat*x0 + (1-gold_rat)*x3; y1 = f(x1);\n    }\n    else if ((y2>=y3) && (y2>=y1))\n    { x0 = x1; y0 = y1;\n        x1 = x2; y1 = y2;\n        x2 = gold_rat*x3 + (1-gold_rat)*x1; y2 = f(x2);\n    }\n    else\n    { if (y3>y0) { x0 = x2; y0 = y2; }\n    else { x3 = x1; y3 = y1; }\n        x1 = gold_rat*x0 + (1-gold_rat)*x3; y1 = f(x1);\n        x2 = gold_rat*x3 + (1-gold_rat)*x1; y2 = f(x2);\n    }\n    }\n    if (y0>=y1) return(max_val(x0,y0));\n    if (y3>=y2) return(max_val(x3,y3));\n    return((y1>y2) ? max_val(x1,y1) : max_val(x2,y2));\n}\n\ndouble max_quad(f,xlo,xhi,n,tol,err,flag)\ndouble (*f)(), xhi, xlo, tol;\nint n, *err;\nchar flag;\n{ double x0, x1, x2, xnew, y0, y1, y2, ynew, a, b;\n    *err = 0;\n    \n    if (n>2)\n    { x0 = max_grid(f,xlo,xhi,n,'x');\n        if (xlo<x0) xlo = x0-1.0/n;\n        if (xhi>x0) xhi = x0+1.0/n;\n    }\n    \n    x0 = xlo; y0 = f(x0);\n    x2 = xhi; y2 = f(x2);\n    x1 = (x0+x2)/2; y1 = f(x1);\n    \n    while (x2-x0>tol)\n    {\n        /* first, check (y0,y1,y2) is a peak. If not,\n         * next interval is the halve with larger of (y0,y2).\n         */\n        if ((y0>y1) | (y2>y1))\n        { \n            if (y0>y2) { x2 = x1; y2 = y1; }\n            else { x0 = x1; y0 = y1; }\n            x1 = (x0+x2)/2;\n            y1 = f(x1);\n        }\n        else /* peak */\n        { a = (y1-y0)*(x2-x1) + (y1-y2)*(x1-x0);\n            b = ((y1-y0)*(x2-x1)*(x2+x1) + (y1-y2)*(x1-x0)*(x1+x0))/2;\n            /* quadratic maximizer is b/a. But first check if a's too\n             * small, since we may be close to constant.\n             */\n            if ((a<=0) | (b<x0*a) | (b>x2*a))\n            { /* split the larger halve */\n                xnew = ((x2-x1) > (x1-x0)) ? (x1+x2)/2 : (x0+x1)/2;\n            }\n            else\n            { xnew = b/a;\n                if (10*xnew < (9*x0+x1)) xnew = (9*x0+x1)/10;\n                if (10*xnew > (9*x2+x1)) xnew = (9*x2+x1)/10;\n                if (fabs(xnew-x1) < 0.001*(x2-x0))\n                {\n                    if ((x2-x1) > (x1-x0))\n                        xnew = (99*x1+x2)/100;\n                    else\n                        xnew = (99*x1+x0)/100;\n                }\n            }\n            ynew = f(xnew);\n            if (xnew>x1)\n            { if (ynew >= y1) { x0 = x1; y0 = y1; x1 = xnew; y1 = ynew; }\n            else { x2 = xnew; y2 = ynew; }\n            }\n            else\n            { if (ynew >= y1) { x2 = x1; y2 = y1; x1 = xnew; y1 = ynew; }\n            else { x0 = xnew; y0 = ynew; }\n            }\n        }\n    }\n    return(max_val(x1,y1));\n}\n\ndouble max_nr(F, coef, old_coef, f1, delta, J, p, maxit, tol, err)\ndouble *coef, *old_coef, *f1, *delta, tol;\nint (*F)(), p, maxit, *err;\njacobian *J;\n{ double old_f, f, lambda;\n    int i, j, fr;\n    double nc, nd, cut;\n    int rank;\n    \n    *err = NR_OK;\n    J->p = p;\n    fr = F(coef, &f, f1, J->Z); J->st = JAC_RAW;\n    \n    for (i=0; i<maxit; i++)\n    { memcpy(old_coef,coef,p*sizeof(double));\n        old_f = f;\n        rank = jacob_solve(J,f1);\n        memcpy(delta,f1,p*sizeof(double));\n        \n        \n        if (rank==0) /* NR won't move! */\n            delta[0] = -f/f1[0];\n        \n        lambda = 1.0;\n        \n        nc = innerprod(old_coef,old_coef,p);\n        nd = innerprod(delta, delta, p);\n        cut = sqrt(nc/nd);\n        if (cut>1.0) cut = 1.0;\n        cut *= 0.0001;\n        do\n        { for (j=0; j<p; j++) coef[j] = old_coef[j] + lambda*delta[j];\n            fr = F(coef, &f, f1, J->Z); J->st = JAC_RAW;\n            if (fr==NR_BREAK) return(f);\n            \n            lambda = (fr==NR_REDUCE) ? lambda/2 : lambda/10.0;\n        } while ((lambda>cut) & (f <= old_f - 1.0e-3));\n        \n        if (f < old_f - 1.0e-3) { *err = NR_NDIV; return(f); }\n        if (fr==NR_REDUCE) return(f);\n        \n        if (fabs(f-old_f) < tol) return(f);\n        \n    }\n    *err = NR_NCON;\n    return(f);\n}\n"
  },
  {
    "path": "src/locfit/makecmd.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n *\n *\n *   The makecmd() function converts a command line string\n *   into a locfit command variable. If the line has no\n *   commands (for example, a blank line or a comment)\n *   it returns NULL; otherwise, it returns the pointer to\n *   the command variable.\n *\n *   The command line is split into arguments, with arguments\n *   separated by spaces. Exception: A space in a quoted\n *   \"str ing\" is not split into separate fields.\n *\n *   getcmd() returns a pointer to the next line for processing.\n *     If no lines are ready for processing, it returns NULL.\n *\n *   del_lines()  frees the work space used by processed command lines.\n *\n *   set_forvar(), inc_forvar(), dec_forvar() are used in the\n *     control of for loops.\n */\n\n#include \"local.h\"\n\n#define isterminator(c) (((c)=='\\0') | ((c)=='\\n') | ((c)=='#'))\nstatic int clcount = 0;\nstatic int proc_to = 0;\nstatic int del_to = 0;\nextern vari *curstr;\nextern char filename[];\n\ntypedef struct {\n  vari *v;\n  char *name;\n  int line_no;\n  int index; } forvar;\nstatic forvar fv[10];\nstatic int for_level = 0, proc_level = 0;\n\nint countfields(z)\nchar *z;\n{ int n, instr;\n\n  n = 0;\n  instr = 0;\n\n  while (1)\n  { while (*z==' ') z++;\n    if (isterminator(*z)) return(n);\n\n    n++;\n\n    while ((instr) || (*z!=' '))\n    { if (isterminator(*z))\n      {  if (instr) ERROR((\"Unterminated String\"));\n         return(n);\n      }\n      if (*z=='\"') instr = !instr;\n      z++;\n    }\n  }\n}\n\nvoid makefields(z, va, n)\nchar *z;\nvari *va;\nint n;\n{ int i, instr;\n  char *st, *eq;\n  carg *curr_arg;\n\n  instr = 0;\n  for (i=0; i<n; i++)\n  { while (*z==' ') z++;\n\n    curr_arg = (carg *)viptr(va,i);\n    curr_arg->val = st = z;\n    curr_arg->arg = NULL;\n    curr_arg->result = NULL;\n\n    eq = NULL;\n    do\n    { if (*z=='\"') instr = !instr;\n      if ((eq==NULL) && (!instr) && (*z=='=')) eq = z;\n      z++;\n    } while ((instr) || (*z !=' ') && (!isterminator(*z)));\n    *z = '\\0';\n\n    if (eq != NULL)\n    { if (eq==st)\n      { ERROR((\"command line argument begins with =\"));\n        return;\n      }\n      if ((eq[1]!='=') & (strchr(\"<>!\",eq[-1])==NULL))\n      { curr_arg->arg = st;\n        curr_arg->val = &eq[1];\n        *eq = '\\0';\n      }\n    } /* eq != */\n    z++;\n\n  }   /* for i */\n}\n\n/*\n *  set_forvar and inc_forvar are used to control for loops.\n *  set_forvar is called when the for cmd is built, making the\n *    variable to loop through.\n *  inc_forvar is called when the for is processed, to update\n *    the value of the variable.\n *  dec_forvar is called when the endfor is processed. This\n *    resets the proc_to line count to the beginning of the for loop.\n */\nvoid set_forvar(v,ct)\nvari *v;\nint ct;\n{ \n  varname vn;\n\n  if (vlength(v)<2)\n  { ERROR((\"for: missing variable\"));\n    return;\n  }\n\n  sprintf(vn,\"=forv%d\",for_level);\n  fv[for_level].v = varith(argval(v,1),vn,STHIDDEN);\n  fv[for_level].line_no = ct;\n  fv[for_level].index = 0;\n  fv[for_level].name = argarg(v,1);\n  for_level++;\n}\n\nvoid inc_forvar()\n{ varname vn;\n  vari *v, *va;\n  double x;\n  \n  if (fv[proc_level].name == NULL)\n  { sprintf(vn,\"=fv%d\",proc_level);\n    v = createvar(vn,STHIDDEN,1,VDOUBLE);\n  }\n  else\n    v = createvar(fv[proc_level].name,STREGULAR,1,VDOUBLE);\n\n  va = fv[proc_level].v;\n  x = vitem(va, fv[proc_level].index);\n  vassn(v,0,x);\n  fv[proc_level].index++;\n  proc_level++;\n}\n\nvoid dec_forvar()\n{ proc_level--;\n  if (fv[proc_level].index < vlength(fv[proc_level].v))\n    proc_to = fv[proc_level].line_no - 1;\n  else\n    fv[proc_level].index = 0;\n}\n\nvoid run(va)\nvari *va;\n{ FILE *runf;\n  char cline[256], *z;\n\n  if (vlength(va)<2)\n  { ERROR((\"run: no command file\"));\n    return;\n  }\n\n  if (!setfilename(argval(va,1),\"\",\"r\",0))\n  { ERROR((\"run: cannot read file %s\",argval(va,1)));\n    return;\n  }\n\n  runf = fopen(filename,\"r\");\n  while (1)\n  { z = fgets(cline,256,runf);\n    if (z==NULL)\n    { fclose(runf);\n      return;\n    }\n    makecmd(cline);\n  }\n}\n\nvoid makecmd(cmdline)\nchar *cmdline;\n{ \n  varname vn;\n  vari *va, *vs;\n  int n;\n\n  n = countfields(cmdline);\n  if (lf_error) return;\n  if (n==0) return;\n  clcount++;\n\n  /* vs is used to store the command line string. */\n  sprintf(vn,\"=clstr%d\",clcount);\n  vs = createvar(vn,STSYSTEM,1+strlen(cmdline),VCHAR);\n  sprintf((char *)vdptr(vs),cmdline);\n\n  /* va is used to store pointers to the command line fields. */\n  sprintf(vn,\"=cline%d\",clcount);\n  va = createvar(vn,STSYSTEM,(INT)n,VARGL);\n  makefields((char *)vdptr(vs), va, n);\n\n  if (argvalis(va,0,\"for\")) set_forvar(va,clcount);\n  if (argvalis(va,0,\"endfor\")) for_level--;\n\n/* we want to read in run files here, not when commands are executed.\n * otherwise, we would have problems with run commands in a for loop.\n */\n  if (argvalis(va,0,\"run\")) run(va);\n\n  return;\n}\n\nvoid del_lines()\n{ int i;\n  varname vn;\n  for (i=proc_to; i>del_to; i--)\n  { sprintf(vn,\"=cline%d\",i);\n    deletename(vn);\n    sprintf(vn,\"=clstr%d\",i);\n    deletename(vn);\n  }\n  del_to = proc_to;\n}\n\nvari *getcmd()\n{\n  varname vn;\n  vari *v;\n\n  if (for_level > 0) return(NULL);\n\n  if (proc_to < clcount)\n  { \n    sprintf(vn,\"=cline%d\",++proc_to);\n    v = findvar(vn,1,NULL);\n    if (v==NULL) return(v);\n\n/* this nonsense is req'd by setplot and setdef.\n * get rid of it, I hope.\n */\nsprintf(vn,\"=clstr%d\",proc_to);\ncurstr = findvar(vn,1,NULL);\n\n    return(v);\n  }\n\n  return(NULL);\n}\n"
  },
  {
    "path": "src/locfit/math.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n  miscellaneous functions that may not be defined in the math\n  libraries. The implementations are crude.\n  lflgamma(x) -- log(gamma(x))\n  lferf(x)    -- erf(x)\n  lferfc(x)   -- erfc(x)\n  lfdaws(x)   -- dawson's function\n\n  where required, these must be #define'd in local.h.\n\n  also includes\n  ptail(x)    -- exp(x*x/2)*int_{-\\infty}^x exp(-u^2/2)du for x < -6.\n  logit(x)    -- logistic function.\n  expit(x)    -- inverse of logit.\n */\n\n#include \"local.h\"\n\ndouble lferfc();\n\ndouble lferf(x)\ndouble x;\n{ static double val[] = { 0.0, 0.52049987781304674,\n    0.84270079294971501, 0.96610514647531076, 0.99532226501895282,\n    0.99959304798255499, 0.99997790950300125 };\n  double h, xx, y, z, f0, f1, f2;\n  int m, j;\n  if (x<0) return(-lferf(-x));\n  if (x>3.2) return(1-lferfc(x));\n  m = (int) (2*x+0.5);\n  xx= ((double)m)/2;\n  h = x-xx; y = h;\n  f0 = val[m];\n  f1 = 2*exp(-xx*xx)/SQRPI;\n  z = f0+h*f1;\n  j = 0;\n  while (fabs(y)>1.0e-12)\n  { f2 = -2*j*f0-2*xx*f1;\n    f0 = f1; f1 = f2;\n    y *= h/(j+2);\n    z += y*f2;\n    j++;\n  }\n  return(z);\n}\n\ndouble lferfc(x)\ndouble x;\n{ if (x<0) return(1+lferf(-x));\n  if (x<2.5) return(1-lferf(x));\n  return(exp(-x*x)/(x*SQRPI));\n}\n\ndouble lflgamma(x)\ndouble x;\n{ double x1;\n  static double ilg[] = { 0.0, 0.0, 0.69314718055994529,\n    1.791759469228055, 3.1780538303479458, 4.7874917427820458, 6.5792512120101012,\n    8.5251613610654147, 10.604602902745251, 12.801827480081469 };\n  static double hlg[] = { 0.57236494292470008, -0.12078223763524520,\n    0.28468287047291918, 1.20097360234707430,  2.45373657084244230,\n    3.95781396761871650, 5.66256205985714270,  7.53436423675873360,\n    9.54926725730099870, 11.68933342079726900 };\n\n  if (x<=0.0) return(0.0);\n  if (x<10)\n  { if (x==(int)x) return(ilg[(int)x-1]);\n    if ((x-0.5)==(int)(x-0.5)) return(hlg[(int)(x-0.5)]);\n  }\n  if (x<3) return(lflgamma(x+1)-log(x));\n\n  x1 = x-1;\n  return(HL2PI+(x1+0.5)*log(x1)-x1+1/(12*x1));\n}\n\ndouble lfdaws(x)\ndouble x;\n{ static double val[] = {\n  0,  0.24485619356002, 0.46034428261948, 0.62399959848185, 0.72477845900708,\n      0.76388186132749, 0.75213621001998, 0.70541701910853, 0.63998807456541,\n      0.56917098836654, 0.50187821196415, 0.44274283060424, 0.39316687916687,\n      0.35260646480842, 0.31964847250685, 0.29271122077502, 0.27039629581340,\n      0.25160207761769, 0.23551176224443, 0.22153505358518, 0.20924575719548,\n      0.19833146819662, 0.18855782729305, 0.17974461154688, 0.17175005072385 };\n  double h, f0, f1, f2, y, z, xx;\n  int j, m;\n  if (x<0) return(-daws(-x));\n  if (x>6)\n  { /* Tail series: 1/x + 1/x^3 + 1.3/x^5 + 1.3.5/x^7 + ...  */\n    y = z = 1/x;\n    j = 0;\n    while (((f0=(2*j+1)/(x*x))<1) && (y>1.0e-10*z))\n    { y *= f0;\n      z += y;\n      j++;\n    }\n    return(z);\n  }\n  m = (int) (4*x);\n  h = x-0.25*m;\n  if (h>0.125)\n  { m++;\n    h = h-0.25;\n  }\n  xx = 0.25*m;\n  f0 = val[m];\n  f1 = 1-xx*f0;\n  z = f0+h*f1;\n  y = h;\n  j = 2;\n  while (fabs(y)>z*1.0e-10)\n  { f2 = -(j-1)*f0-xx*f1;\n    y *= h/j;\n    z += y*f2;\n    f0 = f1; f1 = f2;\n    j++;\n  }\n  return(z);\n}\n\ndouble ptail(x) /* exp(x*x/2)*int_{-\\infty}^x exp(-u^2/2)du for x < -6 */\ndouble x;\n{ double y, z, f0;\n  int j;\n  y = z = -1.0/x;\n  j = 0;\n  while ((fabs(f0= -(2*j+1)/(x*x))<1) && (fabs(y)>1.0e-10*z))\n  { y *= f0;\n    z += y;\n    j++;\n  }\n  return(z);\n}\n\ndouble logit(x)\ndouble x;\n{ return(log(x/(1-x)));\n}\n\ndouble expit(x)\ndouble x;\n{ double u;\n  if (x<0)\n  { u = exp(x);\n    return(u/(1+u));\n  }\n  return(1/(1+exp(-x)));\n}\n\nint factorial(n)\nint n;\n{ if (n<=1) return(1.0);\n  return(n*factorial(n-1));\n}\n"
  },
  {
    "path": "src/locfit/minmax.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *   Compute minimax weights for local regression.\n */\n\n#include \"local.h\"\n\nint mmsm_ct;\n\nstatic int debug=0;\n#define CONVTOL 1.0e-8\n#define SINGTOL 1.0e-10\n#define NR_SINGULAR 100\n\nstatic lfit *mm_lf;\nstatic design *mm_des;\nstatic double mm_gam;\n\ndouble ipower(x,n) /* use for n not too large!! */\ndouble x;\nint n;\n{ if (n==0) return(1.0);\n    if (n<0) return(1/ipower(x,-n));\n    return(x*ipower(x,n-1));\n}\n\ndouble setmmwt(des,lf,a,gam)\ndesign *des;\nlfit *lf;\ndouble *a, gam;\n{ double ip, w0, w1, sw, wt;\n    INT i, p;\n    sw = 0.0;\n    p = lf->mi[MP];\n    for (i=0; i<lf->mi[MN]; i++)\n    { ip = innerprod(a,d_xi(des,i),p);\n        wt = prwt(lf,i);\n        w0 = ip - gam*des->wd[i];\n        w1 = ip + gam*des->wd[i];\n        des->w[i] = 0.0;\n        if (w0>0) { des->w[i] = w0; sw += wt*w0*w0; }\n        if (w1<0) { des->w[i] = w1; sw += wt*w1*w1; }\n    }\n    return(sw/2-a[0]);\n}\n\n/* compute sum_{w!=0} AA^T; e1-sum wA  */\nint mmsums(coef,f,z,J)\ndouble *coef, *f, *z;\njacobian *J;\n{ int i, j, p, sing;\n    double *A;\n    \n    mmsm_ct++;\n    A = J->Z;\n    *f = setmmwt(mm_des,mm_lf,coef,mm_gam);\n    \n    p = mm_lf->mi[MP];\n    setzero(A,p*p);\n    setzero(z,p);\n    z[0] = 1.0;\n    \n    for (i=0; i<mm_lf->mi[MN]; i++)\n        if (mm_des->w[i]!=0.0)\n        { addouter(A,d_xi(mm_des,i),d_xi(mm_des,i),p,prwt(mm_lf,i));\n            for (j=0; j<p; j++) z[j] -= prwt(mm_lf,i)*mm_des->w[i]*mm_des->X[i*p+j];\n        }\n    \n    J->st = JAC_RAW;\n    jacob_dec(J,JAC_EIGD);\n    \n    sing = 0;\n    for (i=0; i<p; i++) sing |= (J->Z[i*p+i]<SINGTOL);\n    if ((debug) & (sing)) printf(\"SINGULAR!!!!\\n\");\n    \n    /* printf(\"%8.5f %8.5f  %8.5f   f %8.5f  z %8.5f %8.5f\\n\",\n     coef[0],coef[1],mm_gam,*f,z[0],z[1]); */\n    return((sing) ? NR_SINGULAR : NR_OK);\n}\n\ndouble updatesd(des,lf,z,p,a,a0,sw0,gam)\ndesign *des;\nlfit *lf;\nint p;\ndouble *z, *a, *a0, sw0, gam;\n{ double f, sw, c0, c1, tmp[10];\n    INT i, j, sd;\n    \n    if (debug) printf(\"updatesd\\n\");\n    for (i=0; i<p; i++) if (des->xtwx.Z[i*p+i]<SINGTOL) sd = i;\n    if (des->xtwx.dg[sd]>0)\n        for (i=0; i<p; i++) tmp[i] = des->xtwx.Q[p*i+sd]*des->xtwx.dg[i];\n    else\n    { for (i=0; i<p; i++) tmp[i] = 0.0;\n        tmp[sd] = 1.0;\n    }\n    \n    mmsums(a0,&sw,z,&des->xtwx);\n    \n    c0 = c1 = 0.0;\n    for (i=0; i<p; i++)\n    { c0 += tmp[i]*z[i];\n        for (j=0; j<p; j++)\n            c1 += tmp[i]*des->xtwx.Z[i*p+j]*tmp[j];\n    }\n    if (debug) printf(\"sdir: c0 %8.5f  c1 %8.5f  z %8.5f %8.5f  tmp %8.5f %8.5f\\n\",c0,c1,z[0],z[1],tmp[0],tmp[1]);\n    if (c0<0) for (i=0; i<p; i++) tmp[i] = -tmp[i];\n    \n    f = 1.0;\n    for (i=0; i<p; i++) a[i] = a0[i]+tmp[i];\n    sw = setmmwt(des,lf,a,gam);\n    \n    if (sw<sw0) /* double till we drop */\n    { while(1)\n    { f *= 2;\n        sw0 = sw;\n        for (i=0; i<p; i++) a[i] = a0[i]+f*tmp[i];\n        sw = setmmwt(des,lf,a,gam);\n        if (sw>sw0-CONVTOL) /* go back one step */\n        { f /= 2;\n            for (i=0; i<p; i++) a[i] = a0[i]+f*tmp[i];\n            sw0 = setmmwt(des,lf,a,gam);\n            return(sw0);\n        }\n    }\n    }\n    \n    /* halve till success */\n    while (1)\n    { f *= 0.5;\n        for (i=0; i<p; i++) a[i] = a0[i]+f*tmp[i];\n        sw = setmmwt(des,lf,a,gam);\n        if (sw<sw0+CONVTOL) return(sw);\n    }\n}\n\nint mm_initial(des,lf,z,p,coef)\ndesign *des;\nlfit *lf;\nint p;\ndouble *z, *coef;\n{ int st;\n    double f;\n    \n    setzero(coef,p);\n    coef[0] = 1;\n    while (1)\n    {\n        st = mmsums(coef,&f,z,&des->xtwx);\n        if (st==NR_OK) return(0);\n        coef[0] *= 2;\n        if (coef[0]>1e8) return(1);\n    } \n}\n\nint mmax(coef, old_coef, f1, delta, J, p, maxit, tol, err)\ndouble *coef, *old_coef, *f1, *delta, tol;\nint p, maxit, *err;\njacobian *J;\n{ double f, old_f, lambda;\n    int i, j, fr, sing;\n    \n    *err = NR_OK;\n    J->p = p;\n    J->st = JAC_RAW;\n    fr = mmsums(coef,&f,f1,J);\n    \n    for (j=0; j<maxit; j++)\n    { memcpy(old_coef,coef,p*sizeof(double));\n        old_f = f;\n        \n        /* compute delta = Newton-Raphson increment */\n        /* jacob_dec(J,JAC_EIGD); */\n        \n        sing = (fr==NR_SINGULAR);\n        \n        if (fr == NR_SINGULAR)\n        { J->st = JAC_RAW;\n            if (j==0) printf(\"init singular\\n\");\n            f = updatesd(mm_des,mm_lf,delta,p,coef,old_coef,f,mm_gam);\n            fr = mmsums(coef,&f,f1,J);\n        }\n        else\n        { \n            jacob_solve(J,f1);\n            memcpy(delta,f1,p*sizeof(double));\n            /* printf(\"delta %8.5f %8.5f\\n\",f1[0],f1[1]); */\n            lambda = 1.0;\n            do\n            {\n                for (i=0; i<p; i++) coef[i] = old_coef[i] + lambda*delta[i];\n                J->st = JAC_RAW;\n                fr = mmsums(coef,&f,f1,J);\n                \n                lambda = lambda/2.0;\n                /* if (fr==NR_SINGULAR) printf(\"singular\\n\"); */\n            } while (((lambda>0.000000001) & (f > old_f+0.001)) /* | (fr==NR_SINGULAR) */ );\n            \n            if (f>old_f+0.001) { printf(\"lambda prob\\n\"); *err = NR_NDIV; return(f); }\n            \n        }\n        if (f==0.0)\n        { if (sing) printf(\"final singular - conv\\n\");\n            return(f);\n        }\n        \n        if (debug)\n        { for (i=0; i<p; i++) printf(\"%8.5f \",coef[i]);\n            printf(\" f %8.5f\\n\",f);\n        }\n        \n        if ((j>0) & (fabs(f-old_f)<tol)) return(f);\n    }\n    if (sing) printf(\"final singular\\n\");\n    WARN((\"findab not converged\"));\n    *err = NR_NCON;\n    return(f);\n}\n\ndouble findab(double gam)\n{ double *coef, sl;\n    int i, p, nr_stat;\n    \n    mm_gam = gam;\n    p = mm_lf->mi[MP];\n    \n    /* starting values for nr iteration */\n    coef = mm_des->cf;\n    for (i=0; i<p; i++) coef[i] = 0.0;\n    if (mm_initial(mm_des, mm_lf, mm_des->f1, p, coef))\n    { WARN((\"findab: initial value divergence\"));\n        return(0.0);\n    }\n    else\n        mmax(coef, mm_des->oc, mm_des->res, mm_des->f1,\n             &mm_des->xtwx, p, mm_lf->mi[MMXIT], CONVTOL, &nr_stat);\n    \n    if (nr_stat != NR_OK) return(0.0);\n    \n    sl = 0.0;\n    for (i=0; i<mm_lf->mi[MN]; i++) sl += fabs(mm_des->w[i])*mm_des->wd[i];\n    \n    return(sl-gam);\n}\n\ndouble weightmm(coef,di,ff,mi,gam)\ndouble *coef, di, *ff, gam;\nINT *mi;\n{ double y1, y2, ip;\n    ip = innerprod(ff,coef,mi[MP]);\n    y1 = ip-gam*di; if (y1>0) return(y1/ip);\n    y2 = ip+gam*di; if (y2<0) return(y2/ip);\n    return(0.0);\n}\n\ndouble minmax(lf,des)\nlfit *lf;\ndesign *des;\n{ double h, u[MXDIM], gam;\n    int i, j, m, d1, p1, err_flag;\n    \n    mmsm_ct = 0;\n    d1 = lf->mi[MDEG]+1;\n    p1 = factorial(d1);\n    for (i=0; i<lf->mi[MN]; i++)\n    { for (j=0; j<lf->mi[MDIM]; j++) u[j] = datum(lf,j,i);\n        des->wd[i] = lf->dp[DALP]/p1*ipower(des->di[i],d1);\n        des->ind[i] = i;\n        fitfun(lf,u,des->xev,d_xi(des,i),NULL,(INT)0);\n    }\n    /* designmatrix(lf,des); */\n    \n    /* find gamma (i.e. solve eqn 13.17 from book), using the secant method.\n     * As a side effect, this finds the other minimax coefficients.\n     * First, set some global pointers a, mm_lf, mm_des.\n     * Note that 13.17 is rewritten as\n     *   g2 = sum |l_i(x)| (||xi-x||^(p+1) M/(s*(p+1)!))\n     * where g2 = gamma * s * (p+1)! / M. The gam variable below is g2.\n     * The smoothing parameter is lf->dp[DALP] == M/s.\n     */\n    mm_lf = lf;\n    mm_des = des;\n    gam = solve_secant(findab, 0.0, 0.0,1.0, 0.0000001, BDF_EXPRIGHT, &err_flag);\n    \n    /*\n     * Set the smoothing weights, in preparation for the actual fit.\n     */\n    h = 0.0; m = 0;\n    for (i=0; i<lf->mi[MN]; i++)\n    { des->w[m] = weightmm(des->cf, des->wd[i],&des->X[i*lf->mi[MP]],lf->mi,gam);\n        if (des->w[m]>0)\n        { if (des->di[i]>h) h = des->di[i];\n            des->ind[m] = i;\n            m++;\n        }\n    }\n    des->n = m;\n    return(h);\n}\n"
  },
  {
    "path": "src/locfit/mutil.h",
    "content": "/*\n *   Copyright (c) 1998-2000 Lucent Technologies.\n *   See README file for details.\n *\n *\n *   Headers for math utility functions.\n */\n\n#ifndef I_MUT_H\n#define I_MUT_H\n\ntypedef struct {\n  double *Z;   /* jacobian matrix, length p*p          */\n  double *Q;   /* eigenvalue matrix, length p*p        */\n  double *wk;  /* work vector in eig_solve, length p   */\n  double *dg;  /* diag vector in eigd, length p        */\n  int p;       /* dimension */\n  int st;      /* status    */\n  int sm;      /* requested decomposition */\n} jacobian;\n\n/* m_jacob.c */\nextern int jac_reqd();\nextern double *jac_alloc();\nextern void jacob_dec(),   chol_dec(),   eig_dec();\nextern int  jacob_solve(), chol_solve(), eig_solve();\nextern int  jacob_hsolve(),chol_hsolve(),eig_hsolve();\nextern double jacob_qf(),  chol_qf(),    eig_qf();\n\n/* m_max.c */\nextern double max_grid(), max_golden(), max_quad(), max_nr();\n\n/* solve.c */\nextern double solve_secant(), solve_nr(), solve_fp();\n\n#define BDF_NONE  0\n#define BDF_EXPLEFT  1\n#define BDF_EXPRIGHT 2\n\n/* return codes for functions optimized by max_nr */\n#define NR_OK 0\n#define NR_INVALID 1\n#define NR_BREAK   2\n#define NR_REDUCE  3\n#define NR_NCON  10\n#define NR_NDIV  11\n\n\n/* jacobian status definitions */\n#define JAC_RAW 0\n#define JAC_CHOL 1\n#define JAC_EIG  2\n#define JAC_EIGD 3\n\n\n#endif  /* define I_MUT_H */\n"
  },
  {
    "path": "src/locfit/nbhd.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *\n *  Functions for determining bandwidth; smoothing neighborhood\n *  and smoothing weights.\n */\n\n#include \"local.h\"\n\nextern vari *vb;\n\ndouble rho(x,sc,d,kt,sty) /* ||x|| for appropriate distance metric */\ndouble *x, *sc;\nINT d, kt, *sty;\n{ double rhoi[MXDIM], s;\n  INT i;\n  for (i=0; i<d; i++)\n  { if (sty!=NULL)\n    { switch(sty[i])\n      { case STANGL:  rhoi[i] = 2*sin(x[i]/(2*sc[i])); break;\n        case STCPAR: rhoi[i] = 0; break;\n        default: rhoi[i] = x[i]/sc[i];\n    } }\n    else rhoi[i] = x[i]/sc[i];\n  }\n\n  if (d==1) return(fabs(rhoi[0]));\n\n  s = 0;\n  if (kt==KPROD)\n  { for (i=0; i<d; i++)\n    { rhoi[i] = fabs(rhoi[i]);\n      if (rhoi[i]>s) s = rhoi[i];\n    }\n    return(s);\n  }\n\n  if (kt==KSPH)\n  { for (i=0; i<d; i++)\n      s += rhoi[i]*rhoi[i];\n    return(sqrt(s));\n  }\n\n  ERROR((\"rho: invalid kt\"));\n  return(0.0);\n}\n\ndouble kordstat(x,k,n,ind)\ndouble *x;\nINT k, n, *ind;\n{ INT i, i0, i1, l, r;\n  double piv;\n  if (k<1) return(0.0);\n  i0 = 0; i1 = n-1;\n  while (1)\n  { piv = x[ind[(i0+i1)/2]];\n    l = i0; r = i1;\n    while (l<=r)\n    { while ((l<=i1) && (x[ind[l]]<=piv)) l++;\n      while ((r>=i0) && (x[ind[r]]>piv)) r--;\n      if (l<=r) ISWAP(ind[l],ind[r]);\n    } /* now, x[ind[i0..r]] <= piv < x[ind[l..i1]] */\n    if (r<k-1) i0 = l;  /* go right */\n    else /* put pivots in middle */\n    { for (i=i0; i<=r; )\n        if (x[ind[i]]==piv) { ISWAP(ind[i],ind[r]); r--; }\n        else i++;\n      if (r<k-1) return(piv);\n      i1 = r;\n    }\n  }\n}\n\n/* check if i'th data point is in limits */\nINT inlim(lf,xlim,i,d)\nlfit *lf;\ndouble *xlim;\nINT i, d;\n{ INT j, k;\n  k = 1;\n  for (j=0; j<d; j++)\n  { if (xlim[j]<xlim[j+d])\n      k &= ((datum(lf,j,i)>=xlim[j]) & (datum(lf,j,i)<=xlim[j+d]));\n  }\n  return(k);\n}\n\ndouble compbandwid(di,ind,x,n,d,nn,fxh)\ndouble *di, *x, fxh;\nINT n, d, *ind, nn;\n{ INT i;\n  double nnh;\n\n#ifdef CVERSION\n  if (nn<0)\n    return(dareval(vb,0,x));\n#endif\n\n  if (nn<=0) return(fxh);\n\n  if (nn<n)\n    nnh = kordstat(di,nn,n,ind);\n  else\n  { nnh = 0;\n    for (i=0; i<n; i++) nnh = MAX(nnh,di[i]);\n    nnh = nnh*exp(log(1.0*nn/n)/d);\n  }\n  return(MAX(fxh,nnh));\n}\n\n/*\n  fast version of nbhd for ordered 1-d data\n*/\ndouble nbhd1(lf,des,k,fxh)\nlfit *lf;\ndesign *des;\nINT k;\ndouble fxh;\n{ double x, h, *xd;\n  INT i, l, r, m, n, z;\n  n = lf->mi[MN];\n  x = des->xev[0];\n  xd = dvari(lf,0);\n\n  /* find closest data point to x */\n  if (x<=xd[0]) z = 0;\n  else\n  if (x>=xd[n-1]) z = n-1;\n  else\n  { l = 0; r = n-1;\n    while (r-l>1)\n    { z = (r+l)/2;\n      if (xd[z]>x) r = z;\n              else l = z;\n    }\n    /* now, xd[0..l] <= x < x[r..n-1] */\n    if ((x-xd[l])>(xd[r]-x)) z = r; else z = l;\n  }\n  /* closest point to x is xd[z] */\n\n  if (k>0) /* set h to nearest neighbor bandwidth */\n  { l = r = z;\n    if (l==0) r = k-1;\n    if (r==n-1) l = n-k;\n    while (r-l<k-1)\n    { if ((x-xd[l-1])<(xd[r+1]-x)) l--; else r++;\n      if (l==0) r = k-1;\n      if (r==n-1) l = n-k;\n    }\n    h = x-xd[l];\n    if (h<xd[r]-x) h = xd[r]-x;\n  } else h = 0;\n\n  if (h<fxh) h = fxh;\n\n  m = 0;\n  if (xd[z]>x) z--; /* so xd[z]<=x */\n  /* look left */\n  for (i=z; i>=0; i--) if (inlim(lf,lf->xl,i,1))\n  { des->di[i] = x-xd[i];\n    des->w[m] = weight(lf,&xd[i],&x,h,1,des->di[i]);\n    if (des->w[m]>0)\n    { des->ind[m] = i;\n      m++; \n    } else i = 0;\n  }\n  /* look right */\n  for (i=z+1; i<n; i++) if (inlim(lf,lf->xl,i,1))\n  { des->di[i] = xd[i]-x;\n    des->w[m] = weight(lf,&xd[i],&x,h,1,des->di[i]);\n    if (des->w[m]>0)\n    { des->ind[m] = i;\n      m++; \n    } else i = n;\n  }\n\n  des->n = m;\n  return(h);\n}\n\ndouble nbhd(lf,des,nn,fxh,redo)\nlfit *lf;\ndesign *des;\ndouble fxh;\nINT redo, nn;\n{ INT d, i, j, m, n, *mi;\n  double h, u[MXDIM];\n\n  mi = lf->mi;\n\n  if (mi[MKT]==KCE) return(0.0);\n  d = mi[MDIM]; n = mi[MN];\n\n  /* ordered 1-dim; use fast searches */\n  if ((nn<=n) & (lf->ord) & (mi[MKER]!=WMINM) & (lf->sty[0]!=STANGL))\n    return(nbhd1(lf,des,nn,fxh));\n\n  if (!redo)\n  { for (i=0; i<n; i++)\n    { for (j=0; j<d; j++) u[j] = datum(lf,j,i)-des->xev[j];\n      des->di[i] = rho(u,lf->sca,d,mi[MKT],lf->sty);\n      des->ind[i] = i;\n    }\n  }\n  else\n    for (i=0; i<n; i++) des->ind[i] = i;\n\n  if (mi[MKER]==WMINM) return(minmax(lf,des));\n\n  h = compbandwid(des->di,des->ind,des->xev,n,mi[MDIM],nn,fxh);\n\n  m = 0;\n  for (i=0; i<n; i++) if (inlim(lf,lf->xl,i,d))\n  { for (j=0; j<d; j++) u[j] = datum(lf,j,i);\n    des->w[m] = weight(lf,u,des->xev,h,1,des->di[i]);\n    if (des->w[m]>0)\n    { des->ind[m] = i;\n      m++;\n    }\n  }\n  des->n = m;\n  return(h);\n}\n"
  },
  {
    "path": "src/locfit/pcomp.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n * \n *\n * functions for computing and subtracting, adding the\n * parametric component\n */\n\n#include \"local.h\"\n\nINT noparcomp(lf)\nlfit *lf;\n{ \n    INT tg;\n    if (lf->mi[MDEG0]<lf->mi[MDEG]) return(1);\n    if (lf->mi[MUBAS]) return(1);\n    tg = lf->mi[MTG] & 63;\n    if (tg<=THAZ) return(1);\n    if (tg==TROBT) return(1);\n    if (tg==TCAUC) return(1);\n    return(0);\n}\n\nINT hasparcomp(lf)\nlfit *lf;\n{ \n    return(lf->mi[MPC]);\n}\n\nint pc_reqd(d,p)\nINT d, p;\n{ \n    return(d + 2*p + jac_reqd(p));\n}\n\nvoid pcchk(pc,d,p,lc)\nparamcomp *pc;\nINT d, p, lc;\n{ \n    //INT k;\n    double *z;\n    pc->wk = checkvarlen(pc->wk,pc_reqd(d,p),\"_pcwork\",VDOUBLE);\n    z = vdptr(pc->wk);\n    //k = 0;\n    \n    pc->xbar = z; z += d;\n    pc->coef = z; z += p;\n    pc->f    = z; z += p;\n    \n    z = jac_alloc(&pc->xtwx,p,z);\n    pc->xtwx.p = p;\n}\n\nvoid compparcomp(des,lf,nopc)\ndesign *des;\nlfit *lf;\nINT nopc;\n{ \n    INT i, j, k;\n    double wt, sw;\n    paramcomp *pc;\n    pc = &lf->pc;\n    pcchk(pc,lf->mi[MDIM],lf->mi[MP],1);\n    \n    if (pc == NULL)\n    {\n        fprintf(stderr, \"Error: locfit cannot allocate pc working memory\\n\");\n        pcchk(pc,lf->mi[MDIM],lf->mi[MP],1);\n        return;\n    }\n    \n    for (i=0; i<lf->mi[MDIM]; i++) pc->xbar[i] = 0.0;\n    sw = 0.0;\n    for (i=0; i<lf->mi[MN]; i++)\n    { \n        wt = prwt(lf,i);\n        sw += wt;\n        for (j=0; j<lf->mi[MDIM]; j++)\n            pc->xbar[j] += datum(lf,j,i)*wt;\n        des->ind[i] = i;\n        des->w[i] = 1.0;\n    }\n    for (i=0; i<lf->mi[MDIM]; i++) pc->xbar[i] /= sw;\n    if ((nopc) || noparcomp(lf))\n    { lf->mi[MPC] = 0;\n        return;\n    }\n    lf->mi[MPC] = 1;\n    des->xev = pc->xbar;\n    k = locfit(lf,des,0.0,0);\n\n    if (lf_error) return;\n    switch(k)\n    { case LF_NOPT:\n            ERROR((\"compparcomp: no points in dataset?\"));\n            return;\n        case LF_INFA:\n            ERROR((\"compparcomp: infinite parameters in param. component\"));\n            return;\n        case LF_NCON:\n            ERROR((\"compparcom: not converged\"));\n            return;\n        case LF_OOB:\n            ERROR((\"compparcomp: parameters out of bounds\"));\n            return;\n        case LF_PF:\n            WARN((\"compparcomp: perfect fit\"));\n        case LF_OK:\n            for (i=0; i<lf->mi[MP]; i++)\n            { pc->coef[i] = des->cf[i];\n                pc->xtwx.dg[i] = des->xtwx.dg[i];\n                pc->xtwx.wk[i] = des->xtwx.wk[i];\n            }\n            for (i=0; i<lf->mi[MP]*lf->mi[MP]; i++)\n            { pc->xtwx.Z[i] = des->xtwx.Z[i];\n                pc->xtwx.Q[i] = des->xtwx.Q[i];\n            }\n            pc->xtwx.sm = des->xtwx.sm;\n            pc->xtwx.st = des->xtwx.st;\n            return;\n        default:\n            ERROR((\"compparcomp: locfit unknown return status %d\",k));\n            return;\n    }\n}\n\nvoid subparcomp(des,lf,coef)\ndesign *des;\nlfit *lf;\ndouble *coef;\n{ INT i, *deriv, nd;\n    \n    if (!hasparcomp(lf)) return;\n    \n    deriv = lf->deriv;\n    nd = lf->nd;\n    fitfun(lf,des->xev,lf->pc.xbar,des->f1,deriv,nd);\n    coef[0] -= innerprod(lf->pc.coef,des->f1,lf->mi[MP]);\n    if (des->ncoef == 1) return;\n    \n    for (i=0; i<lf->mi[MDIM]; i++)\n    { deriv[nd] = i;\n        fitfun(lf,des->xev,lf->pc.xbar,des->f1,deriv,nd+1);\n        coef[i+1] -= innerprod(lf->pc.coef,des->f1,lf->mi[MP]);\n    }\n}\n\nvoid subparcomp2(des,lf,vr,il)\ndesign *des;\nlfit *lf;\ndouble *vr, *il;\n{ double t0, t1;\n    INT i, *deriv, nd, *mi;\n    \n    if (!hasparcomp(lf)) return;\n    \n    mi = lf->mi;\n    deriv = lf->deriv;\n    nd = lf->nd;\n    fitfun(lf,des->xev,lf->pc.xbar,des->f1,deriv,nd);\n    for (i=0; i<mi[MP]; i++) lf->pc.f[i] = des->f1[i];\n    jacob_solve(&lf->pc.xtwx,des->f1);\n    t0 = sqrt(innerprod(lf->pc.f,des->f1,mi[MP]));\n    vr[0] -= t0;\n    il[0] -= t0;\n    if ((t0==0) | (des->ncoef==1)) return;\n    \n    for (i=0; i<mi[MDIM]; i++)\n    { deriv[nd] = i;\n        fitfun(lf,des->xev,lf->pc.xbar,lf->pc.f,deriv,nd+1);\n        t1 = innerprod(lf->pc.f,des->f1,mi[MP])/t0;\n        vr[i+1] -= t1;\n        il[i+1] -= t1;\n    }\n}\n\ndouble addparcomp(lf,x,c)\nlfit *lf;\ndouble *x;\nint c;\n{ double y;\n    if (!hasparcomp(lf)) return(0.0);\n    fitfun(lf,x,lf->pc.xbar,lf->pc.f,lf->deriv,lf->nd);\n    if (c==PCOEF) return(innerprod(lf->pc.coef,lf->pc.f,lf->mi[MP]));\n    if ((c==PNLX)|(c==PT0)|(c==PVARI))\n    { y = sqrt(jacob_qf(&lf->pc.xtwx,lf->pc.f));\n        return(y);\n    }\n    return(0.0);\n}\n"
  },
  {
    "path": "src/locfit/pout.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n *\n *\n * print a plot structure in the format of various graph packages\n */\n\n#include \"local.h\"\n\n#ifdef CVERSION\n\n#define XCON(x) (INT)(i0+(i1-i0)*(x-px[0])/(px[1]-px[0]))\n#define YCON(y) (INT)(k0+(k1-k0)*(y-py[0])/(py[1]-py[0]))\n\nextern double sin(), cos(), sqrt(), atan2(), ceil(), floor(), log10(), pow();\nstatic INT i0, i1, k0, k1, cw, ch;\n#ifdef YAWN\nstatic FILE *plf;\n#endif\nextern INT curwin, lfcm[10];\n\n#ifdef NOPIPES\nFILE *popen(const char *cmd,const char *mode) { return(NULL); }\nint pclose(FILE *file) { return(0); }\n#endif\n\nextern device devps, devwin;\n\nchar f2(fmt)\nchar *fmt;\n{ char *z;\n  z = strchr(fmt,',');\n  if (z==NULL) return('d');\n  z++;\n  return(*z);\n}\n\nINT pretty(xl,k,z)\ndouble *xl, *z;\nINT k;\n{ double dlt, m;\n  INT i, j, u;\n  if (k<=0) return(0);\n  dlt = (xl[1]-xl[0])/k;\n  m = floor(log10(dlt));\n  dlt *= pow(10.0,-m);\n  if (dlt<2) u = 2;\n    else if (dlt<5) u = 5;\n      else { u = 1; m++; } /* increments should be u*10^m; */\n  dlt = u*pow(10.0,m);\n  i = (INT)ceil(xl[0]/dlt);\n  j = 0;\n  while ((j<k) && ((i+j)*dlt<=xl[1]))\n  { z[j] = (i+j)*dlt;\n    j++;\n  }\n  return(j);\n}\n\nvoid isgrid(xyz)\nplxyz *xyz;\n{ INT i, n;\n  vari *x, *y, *z;\n  x = xyz->x; y = xyz->y; z = xyz->z;\n  if ((x!=NULL) & (y!=NULL) & (z!=NULL))\n  { if ((x->n*y->n)==z->n)\n    { xyz->nx = x->n;\n      xyz->ny = y->n;\n      xyz->n = z->n;\n      xyz->t = 1;\n      return;\n    }\n    if ((x->n>1) & (y->n>1))\n    { i = 0; n = z->n;\n      while ((i<y->n) && (vitem(y,0)==vitem(y,i))) i++;\n      if ((i>1) && (i*(n/i)==n))\n      { xyz->nx = n/i;\n        xyz->ny = i;\n        xyz->n = n;\n        xyz->t = 1;\n        return;\n      }\n    }\n  }\n  xyz->t = 0;\n  xyz->n = 0;\n  if ((x!=NULL) && (x->n>xyz->n)) xyz->n = x->n;\n  if ((y!=NULL) && (y->n>xyz->n)) xyz->n = y->n;\n  if ((z!=NULL) && (z->n>xyz->n)) xyz->n = z->n;\n}\n\nvoid getxyzitem(x,xyz,i)\nplxyz *x;\ndouble xyz[3];\nint i;\n{ xyz[0] = vitem(x->x,i);\n  if (x->t==1)\n    xyz[1] = vitem(x->y,i/x->x->n);\n  else\n    xyz[1] = vitem(x->y,i);\n  xyz[2] = vitem(x->z,i);\n}\n\nstatic double xl[2], yl[2], zl[2], px[2], py[2];\n\nvoid project(z,x,theta,phi)\ndouble *z, *x, theta, phi;\n{ double z0, z1, z2;\n  z0 = (z[0]-xl[0])/(xl[1]-xl[0]);\n  z1 = (z[1]-yl[0])/(yl[1]-yl[0]);\n  z2 = (z[2]-zl[0])/(zl[1]-zl[0]);\n  x[0] = cos(theta)*z0-sin(theta)*z1;\n  x[1] = (sin(theta)*z0+cos(theta)*z1)*cos(phi)+sin(phi)*z2;\n}\n\nvoid iproject(z,i,theta,phi)\ndouble *z, theta, phi;\nINT *i;\n{ double x[2];\n  project(z,x,theta,phi);\n  i[0] = XCON(x[0]); i[1] = YCON(x[1]);\n}\n\nvoid line3d(z1,z2,theta,phi,dev,col)\ndouble *z1, *z2, theta, phi;\ndevice *dev;\nINT col;\n{ INT x1[2], x2[2];\n  iproject(z1,x1,theta,phi);\n  iproject(z2,x2,theta,phi);\n  dev->SetColor(lfcm[col]);\n  dev->DrawLine(x1[0],x1[1],x2[0],x2[1]);\n}\n\nvoid xyztext(tx,x,ah,av,theta,phi,dev,col)\ndouble *x, theta, phi;\nINT ah, av, col;\nchar *tx;\ndevice *dev;\n{ INT xy[2];\n  iproject(x,xy,theta,phi);\n  dev->SetColor(lfcm[col]);\n  dev->DoText(0,xy[0],xy[1],tx,ah,av);\n}\n\nint getgreylevel(z)\ndouble z;\n{ int c;\n  c = 8+11*(z-zl[0])/(zl[1]-zl[0]);\n  if (c<8) return(8);\n  if (c>18)return(18);\n  return(c);\n}\n\nvoid points3d(x,theta,phi,dev,type)\nplxyz *x;\ndouble theta, phi;\nchar type;\ndevice *dev;\n{ INT i, xy[2];\n  double xyz[3];\n  for (i=0; i<x->n; i++)\n  {\n    getxyzitem(x,xyz,i);\n    iproject(xyz,xy,theta,phi);\n    if (type=='q') \n      dev->SetColor(getgreylevel(xyz[2]));\n    else\n      dev->SetColor(lfcm[CPOI]);\n    dev->DrawPoint(xy[0],xy[1],x->pch);\n  }\n}\n\nvoid lines3d(xyz,theta,phi,dev)\nplxyz *xyz;\ndouble theta, phi;\ndevice *dev;\n{ INT i;\n  double x0[3], x1[3];\n  getxyzitem(xyz,x0,0);\n  for (i=1; i<xyz->n; i++)\n  { if (i&1)\n    { getxyzitem(xyz,x1,i);\n      line3d(x0,x1,theta,phi,dev,CLIN);\n    }\n    else \n    { getxyzitem(xyz,x0,i);\n      line3d(x1,x0,theta,phi,dev,CLIN);\n    }\n  }\n}\n\nvoid segments(xyz0,xyz1,theta,phi,dev)\nplxyz *xyz0, *xyz1;\ndouble theta, phi;\ndevice *dev;\n{ INT i, n;\n  double x0[3], x1[3];\n  n = xyz0->n;\n  if (xyz1->n>n) n = xyz1->n;\n  for (i=0; i<n; i++)\n  { getxyzitem(xyz0,x0,i);\n    getxyzitem(xyz1,x1,i);\n    line3d(x0,x1,theta,phi,dev,CSEG);\n  }\n}\n\ndouble spl(z0,z1)\ndouble z0, z1;\n{ if (z0-z1==0.0) return(0.5);\n  return(z0/(z0-z1));\n}\n\nvoid contour3d(x,theta,phi,dev,sl,nsl)\nplxyz *x;\ndouble theta, phi, *sl;\nINT nsl;\ndevice *dev;\n{ INT i, j, k, nx, ny, s;\n  double xyz[4][3], u[4], x0[3], x1[3], x2[3], x3[3], r;\n  char lb[20];\n  if (x->t==0) ERROR((\"Contour: not a grid\"));\n  if (lf_error) return;\n  if (nsl==0) nsl = pretty(zl,10,sl);\n  nx = x->nx; ny = x->ny;\n  for (k=0; k<nsl; k++)\n  { x0[2] = x1[2] = x2[2] = x3[2] = sl[k];\n    for (i=0; i<nx-1; i++)\n      for (j=0; j<ny-1; j++)\n      { sprintf(lb,\"%g\",sl[k]);\n        getxyzitem(x,xyz[0],i+j*nx);\n        getxyzitem(x,xyz[1],(i+1)+j*nx);\n        getxyzitem(x,xyz[2],i+(j+1)*nx);\n        getxyzitem(x,xyz[3],i+1+(j+1)*nx);\n        u[0] = xyz[0][2]-sl[k];\n        u[1] = xyz[1][2]-sl[k];\n        u[2] = xyz[2][2]-sl[k];\n        u[3] = xyz[3][2]-sl[k];\n        if (u[0]*u[1]<=0) /* bottom of cell */\n        { r = spl(u[0],u[1]);\n          x0[0] = (1-r)*xyz[0][0]+r*xyz[1][0];\n          x0[1] = xyz[0][1];\n          if (j==0) xyztext(lb,x0,-1,-1,theta,phi,dev,CCLA);\n        }\n        if (u[1]*u[3]<=0) /* right of cell */\n        { r = spl(u[1],u[3]);\n          x1[0] = xyz[1][0];\n          x1[1] = (1-r)*xyz[1][1]+r*xyz[3][1];\n          if (i==nx-2) xyztext(lb,x1,-1,0,theta,phi,dev,CCLA);\n        }\n        if (u[2]*u[3]<=0) /* top of cell */\n        { r = spl(u[2],u[3]);\n          x2[0] = (1-r)*xyz[2][0]+r*xyz[3][0];\n          x2[1] = xyz[2][1];\n          if (j==ny-2) xyztext(lb,x2,-1,1,theta,phi,dev,CCLA);\n        }\n        if (u[0]*u[2]<=0) /* left of cell */\n        { r = spl(u[0],u[2]);\n          x3[0] = xyz[0][0];\n          x3[1] = (1-r)*xyz[0][1]+r*xyz[2][1];\n          if (i==0) xyztext(lb,x3,-1,0,theta,phi,dev,CCLA);\n        }\n\n        s = 8*(u[3]>0)+4*(u[2]>0)+2*(u[1]>0)+(u[0]>0);\n        switch(s)\n        { case 0:\n          case 15: break;\n          case 1:\n          case 14:\n            line3d(x0,x3,theta,phi,dev,CCON);\n            break;\n          case 2:\n          case 13:\n            line3d(x0,x1,theta,phi,dev,CCON);\n            break;\n          case 3:\n          case 12:\n            line3d(x3,x1,theta,phi,dev,CCON);\n            break;\n          case 4:\n          case 11:\n            line3d(x3,x2,theta,phi,dev,CCON);\n            break;\n          case 5:\n          case 10:\n            line3d(x0,x2,theta,phi,dev,CCON);\n            break;\n          case 6:\n          case 9:\n            line3d(x0,x1,theta,phi,dev,CCON);\n            break;\n          case 7:\n          case 8:\n            line3d(x1,x2,theta,phi,dev,CCON);\n            break;\n          default: ERROR((\"severe contouring error...\"));\n        }\n      }\n  }\n}\n\ndouble angle(x0,x1,x2) /* rotation angle from (x0,x1) to (x0,x2) */\ndouble *x0, *x1, *x2;\n/* If x0=0, ||x1=1|| then express\n   x2 = u x1 + v y1       where y1=(-x11,x10) = 90 deg anticlk rot.\n      i.e. u = <x1,x2>  v = <y1,x2>\n   tan(theta) = v/u\n   atan2(v,u) returns positive for anticlkws rot;\n                      negative for clockwise rot.\n*/\n{ double u, v;\n  u =  (x1[0]-x0[0])*(x2[0]-x0[0]) + (x1[1]-x0[1])*(x2[1]-x0[1]);\n  v = -(x1[1]-x0[1])*(x2[0]-x0[0]) + (x1[0]-x0[0])*(x2[1]-x0[1]);\n  return(atan2(v,u));\n}\n\nvoid persp3d(xyz,theta,phi,DP,sl,nsl)\nplxyz *xyz;\ndouble theta, phi, *sl;\nvoid (*DP)();\nINT nsl;\n{ INT i, j, k, m, nx, ny, ii, jj, cb, cp, cx[4], cy[4], xhi, yhi;\n  double u[4][3], w[4][2], r;\n  if (xyz->t==0) ERROR((\"persp3d: not a grid\"));\n  if (lf_error) return;\n  /* theta=135 --- 225\n            |       |\n            45 --- 315;\n     i.e start at top right for theta=45 e.t.c. Reverse if sin(phi)<0.\n     x starts hi if cos(theta)>0\n     y starts hi if sin(theta)>0\n  */\n  xhi = (cos(theta)*sin(phi)) > 0;\n  yhi = (sin(theta)*sin(phi)) > 0;\n  nx = xyz->nx; ny = xyz->ny;\n  for (i=0; i<nx-1; i++)\n    for (j=0; j<ny-1; j++)\n    { for (k=0; k<4; k++)\n      {  /*     1 -- 2\n                |    |\n                0 -- 3   */\n        ii = (xhi) ? nx-2-i : i;\n        jj = (yhi) ? ny-2-j : j;\n        ii += (k>1);\n        jj += (k==1)+(k==2);\n        m = jj*nx+ii;\n        getxyzitem(xyz,u[k],m);\n        project(u[k],w[k],theta,phi);\n        cx[k] = XCON(w[k][0]); cy[k] = YCON(w[k][1]);\n      }\n\n      switch(xyz->type)\n      { case 'w':\n          /* wireframe:\n             from top, use color CPA1 for border, CPA2 for patch\n             angles are anti-clock from top; r approx 2pi\n                             clock from bot; r approx -2pi\n          */\n          r = angle(w[0],w[3],w[1])+angle(w[1],w[0],w[2])\n             +angle(w[2],w[1],w[3])+angle(w[3],w[2],w[0]);\n          if (r>0) { cb = lfcm[CPA1]; cp = lfcm[CPA2]; }\n              else { cp = lfcm[CPA1]; cb = lfcm[CPA2]; }\n          DP(cx,cy,cp,cb);\n          break;\n        case 'i': /* image */\n          if (nsl==0) nsl = pretty(zl,10,sl);\n          r = u[0][2] + u[1][2] + u[2][2] + u[3][2];\n          cb = cp = getgreylevel(r/4);\n          DP(cx,cy,cp,cb);\n          break;\n      }\n    }\n}\n\nvoid updatelim(v,xl)\nvari *v;\ndouble *xl;\n{ INT i;\n  if ((v==NULL) || (vlength(v)==0)) return;\n  if (xl[0]==xl[1])\n    xl[0] = xl[1] = vitem(v,0);\n  for (i=0; i<vlength(v); i++)\n  { if (vitem(v,i)<xl[0]) xl[0] = vitem(v,i);\n    if (vitem(v,i)>xl[1]) xl[1] = vitem(v,i);\n  }\n}\n\nvoid axis(z1,z2,zl,lab,theta,phi,a,s,dev)\ndouble *z1, *z2, *zl, theta, phi;\nchar *lab;\nINT a, s;\ndevice *dev;\n{ double x1[3], x2[3], z[50];\n  INT i, u0, u1, v0, v1, n, horiz;\n  char lb[20];\n  dev->SetColor(lfcm[CAXI]);\n  project(z1,x1,theta,phi);\n  project(z2,x2,theta,phi);\n  u0 = XCON(x1[0]); v0 = XCON(x2[0]);\n  u1 = YCON(x1[1]); v1 = YCON(x2[1]);\n  horiz = abs(v0-u0)>abs(v1-u1);\n  dev->DrawLine(u0,u1,v0,v1);\n  n = (INT)sqrt((double)((v0-u0)*(v0-u0)+(v1-u1)*(v1-u1)))/((horiz) ? 5*cw : 2*ch);\n  if (n>50) n = 50;\n  n = pretty(zl,n,z);\n  if (n==0) return;\n  x1[0] = z1[0];  x1[1] = z1[1]; x1[2] = z1[2];\n  if (abs(v0-u0)>abs(v1-u1)) /* horizontal axis */\n  { dev->SetColor(lfcm[CTEX]);\n    if (lab!=NULL)\n      dev->DoText(0,(u0+v0)/2,(u1+v1)/2+s*(dev->ticklength+ch),lab,0,s);\n    for (i=0; i<n; i++)\n    { x1[a] = z[i];\n      project(x1,x2,theta,phi);\n      u0 = XCON(x2[0]); u1 = YCON(x2[1]);\n      v0 = u0; v1 = u1+s*dev->ticklength;\n      sprintf(lb,\"%g\",z[i]);\n      dev->SetColor(lfcm[CAXI]);\n      dev->DrawLine(u0,u1,v0,v1);\n      dev->SetColor(lfcm[CTEX]);\n      dev->DoText(0,v0,v1,lb,0,s);\n  } }\n  else /* vertical axis */\n  { s = 2*((2*v0)>(i0+i1))-1;\n    dev->SetColor(lfcm[CTEX]);\n    if (lab!=NULL)\n      dev->DoText(0,v0,v1-ch,lab,-s,-1);\n    for (i=0; i<n; i++)\n    { x1[a] = z[i];\n      project(x1,x2,theta,phi);\n      u0 = XCON(x2[0]); u1 = YCON(x2[1]);\n      v0 = u0+s*dev->ticklength; v1 = u1;\n      sprintf(lb,\"%g\",z[i]);\n      dev->SetColor(lfcm[CAXI]);\n      dev->DrawLine(u0,u1,v0,v1);\n      dev->SetColor(lfcm[CTEX]);\n      dev->DoText(0,v0,v1,lb,-s,0);\n  } }\n}\n\nvoid plotxwin(pl,dev,wn,w,h,rd)\nplots *pl;\ndevice *dev;\nINT wn, w, h, rd;\n{ INT i, j, k, s;\n  double z[3], z2[3], xx[2], vx, vy, vz;\n  static double theta, phi;\n  plxyz *xyz;\n  if (pl->ty==PLNONE) return;\n  if (h<=0) h = dev->defth;\n  if (w<=0) w = dev->deftw;\n  if (!dev->makewin(&w,&h,wn,rd)) return;\n  dev->TextDim(0,\"0\",&cw,&ch);\n  i0 = 4*cw+dev->ticklength;   i1 = w-2*cw;\n  k0 = h-3*ch-dev->ticklength; k1 = 3*ch;\n  dev->ClearScreen(lfcm[CBAK]);\n  if (pl->xl[0]<pl->xl[1])\n  { xl[0] = pl->xl[0]; xl[1] = pl->xl[1]; }\n  else\n  { xl[0] = xl[1] = 0.0;\n    for (i=0; i<pl->xyzs->n; i++)\n    { xyz = (plxyz *)viptr(pl->xyzs,i);\n      updatelim(xyz->x,xl);\n    }\n    if (xl[0]==xl[1]) { xl[0] -= 0.5; xl[1] += 0.5; }\n  }\n  if (pl->yl[0]<pl->yl[1])\n  { yl[0] = pl->yl[0]; yl[1] = pl->yl[1]; }\n  else\n  { yl[0] = yl[1] = 0.0;\n    for (i=0; i<pl->xyzs->n; i++)\n    { xyz = (plxyz *)viptr(pl->xyzs,i);\n      updatelim(xyz->y,yl);\n    }\n    if (yl[0]==yl[1]) { yl[0] -= 0.5; yl[1] += 0.5; }\n  }\n  if (pl->zl[0]<pl->zl[1])\n  { zl[0] = pl->zl[0]; zl[1] = pl->zl[1]; }\n  else\n  { zl[0] = zl[1] = 0.0;\n    for (i=0; i<pl->xyzs->n; i++)\n    { xyz = (plxyz *)viptr(pl->xyzs,i);\n      updatelim(xyz->z,zl);\n    }\n    if (zl[0]==zl[1]) { zl[0] -= 0.5; zl[1] += 0.5; }\n  }\n  theta = pl->theta*PI/180; phi = pl->phi*PI/180;\n  vx = -sin(theta)*sin(phi);\n  vy = -cos(theta)*sin(phi);\n  vz = cos(phi);\n\n  for (i=0; i<2; i++)\n    for (j=0; j<2; j++)\n      for (k=0; k<2; k++)\n      { z[0] = xl[i]; z[1] = yl[j]; z[2] = zl[k];\n        project(z,xx,theta,phi);\n        if ((i+j+k==0) | (xx[0]<px[0])) px[0]=xx[0];\n        if ((i+j+k==0) | (xx[0]>px[1])) px[1]=xx[0];\n        if ((i+j+k==0) | (xx[1]<py[0])) py[0]=xx[1];\n        if ((i+j+k==0) | (xx[1]>py[1])) py[1]=xx[1];\n      }\n  s = 1-2*((cos(phi)<0)^(sin(phi)<0));\n  z[0] = xl[0]; z2[0] = xl[1];\n  z[1] = z2[1] = yl[(cos(theta)<0)^(sin(phi)<0)];\n  z[2] = z2[2] = zl[cos(phi)<0];\n  axis(z,z2,xl,pl->xlab,theta,phi,0,s,dev);\n  z[0] = z2[0] = xl[(sin(theta)<0)^(sin(phi)<0)];\n  z[1] = yl[0]; z2[1] = yl[1];\n  z[2] = z2[2] = zl[cos(phi)<0];\n  axis(z,z2,yl,pl->ylab,theta,phi,1,s,dev);\n  z[0] = z2[0] = xl[cos(theta)<0];\n  z[1] = z2[1] = yl[sin(theta)>0];\n  z[2] = zl[0]; z2[2] = zl[1];\n  axis(z,z2,zl,pl->zlab,theta,phi,2,s,dev);\n  if (strlen(pl->main)>0) dev->DoText(1,(i0+i1)/2,2*ch,pl->main,0,-1);\n \n  for (i=0; i<pl->xyzs->n; i++)\n  { xyz = viptr(pl->xyzs,i);\n    isgrid(xyz);\n    switch (xyz->type)\n    { case 'c':\n        contour3d(xyz,theta,phi,dev,pl->sl,pl->nsl);\n        break;\n      case 'i':\n        persp3d(xyz,theta,phi,dev->DrawPatch,pl->sl,pl->nsl);\n        break;\n      case 'b':\n        points3d(xyz,theta,phi,dev,'p');\n      case 'l':\n        lines3d(xyz,theta,phi,dev);\n        break;\n      case 'p':\n        points3d(xyz,theta,phi,dev,'p');\n        break;\n      case 'q':\n        points3d(xyz,theta,phi,dev,'q');\n        break;\n      case 's':\n        if (i==0) { ERROR((\"invalid segements\")); }\n        else\n        segments(viptr(pl->xyzs,i-1),xyz,theta,phi,dev);\n        break;\n      case 'w':\n        persp3d(xyz,theta,phi,dev->DrawPatch,pl->sl,pl->nsl);\n        break;\n  } }\n\n  dev->wrapup(rd);\n}\n\n#ifdef YAWN\nvoid plotmaple(pl)\nplots *pl;\n{ INT i, j;\n  plf = fopen(\"lfplot\",\"w\");\n  switch(pl->d)\n  { case 1:\n      fprintf(plf,\"PLOT(\\n\");\n      for (j=0; j<pl->r; j++)\n      { fprintf(plf,\"CURVES([\\n\");\n        for (i=0; i<pl->mx[j]; i++)\n        { if (i>0) fprintf(plf,\",\\n\");\n          fprintf(plf,\"[%f,%f]\",pl->x[j][i],pl->y[j][i]);\n        }\n        fprintf(plf,\"],\\nCOLOUR(RGB,0,0,0)),\\n\");\n      }\n      if (pl->type[0]=='p') fprintf(plf,\"STYLE(POINT),\");\n      if (pl->main!=NULL) fprintf(plf,\"TITLE(%s),\",pl->main);\n      fprintf(plf,\"AXESLABELS(%s,%s)\",pl->xlab,pl->ylab);\n      fprintf(plf,\");\\n\");\n      \n      break;\n    case 2:\n      fprintf(plf,\"PLOT3D(GRID(%f..%f,%f..%f,[[\\n\",pl->x[0][0],pl->x[0][pl->mx[0]-1],pl->y[0][0],pl->y[0][pl->my[0]-1]);\n      for (i=0; i<pl->mx[0]; i++)\n      { if (i>0) fprintf(plf,\"],\\n[\");\n        for (j=0; j<pl->my[0]; j++)\n        { if (j>0) fprintf(plf,\",\\n\");\n          fprintf(plf,\"%f\",pl->z[0][i*pl->my[0]+j]);\n        }\n      }\n      fprintf(plf,\"]]),\\nAXESLABELS(%s,%s,%s),AXESSTYLE(FRAME)\",pl->xlab,pl->ylab,pl->zlab);\n      if (pl->type[0]=='c') fprintf(plf,\",STYLE(CONTOUR),CONTOURS(DEFAULT),ORIENTATION(-90,0.1),COLOUR(ZSHADING)\");\n      if (pl->main!=NULL) fprintf(plf,\",\\nTITLE(%s)\\n\",pl->main);\n      fprintf(plf,\");\\n\");\n      break;\n  }\n  fclose(plf);\n  printf(\"Created lfplot file; Maple format.\\n\");\n}\n\nvoid plotmathe(pl,fmt)\nplots *pl;\nchar *fmt;\n{ INT i, j, aut;\n  static FILE *plm=NULL;\n  aut = f2(fmt)!='m';\n#ifdef NOPIPES\n  aut = 0;\n#endif\n  if (aut)\n  { if (plm==NULL) plm = (FILE *)popen(\"math >/dev/null\",\"w\");\n    plf = plm;\n  }\n  else\n    plf = fopen(\"lfplot\",\"w\");\n  switch(pl->d)\n  { case 1:\n      fprintf(plf,\"ListPlot[{{\\n\");\n      for (i=0; i<pl->mx[0]; i++)\n      { if (i>0) fprintf(plf,\"},\\n{\");\n        fprintf(plf,\"%f,%f\",pl->x[0][i],pl->y[0][i]);\n      }\n      fprintf(plf,\"}}\");\n      fprintf(plf,\",AxesLabel->{%s,%s}\",pl->xlab,pl->ylab);\n      if (pl->type[0]=='l') fprintf(plf,\",PlotJoined->True\");\n      break;\n    case 2:\n      if (pl->type[0]=='c') fprintf(plf,\"ListContourPlot[{{\");\n                    else fprintf(plf,\"ListPlot3D[{{\");\n      for (j=0; j<pl->my[0]; j++)\n      { if (j>0) fprintf(plf,\"},\\n{\");\n        for (i=0; i<pl->mx[0]; i++)\n        { if (i>0) fprintf(plf,\",\\n\");\n          fprintf(plf,\"%f\",pl->z[0][i*pl->my[0]+j]);\n        }\n      }\n      fprintf(plf,\"}},\\nMeshRange->{{\");\n      fprintf(plf,\"%f,%f},{%f,%f}}\\n\",pl->x[0][0],pl->x[0][pl->mx[0]-1],pl->y[0][0],pl->y[0][pl->my[0]-1]);\n      if (pl->type[0]=='c') fprintf(plf,\",FrameLabel->{%s,%s}\",pl->xlab,pl->ylab);\n                    else fprintf(plf,\",AxesLabel->{%s,%s,%s}\",pl->xlab,pl->ylab,pl->zlab);\n      break;\n  }\n  if (pl->main!=NULL) fprintf(plf,\",PlotLabel->%s\\n\",pl->main);\n  fprintf(plf,\"];\\n\");\n  if (aut)\n    fflush(plf);\n  else\n  { fclose(plf);\n    printf(\"Created lfplot file; Mathematica format.\\n\");\n  }\n}\n\nvoid plotmatlb(pl) /* Matlab */\nplots *pl;\n{ INT i, j;\n  plf = fopen(\"lfplot.m\",\"w\");\n  switch(pl->d)\n  { case 1:\n      fprintf(plf,\"plot([\");\n      for (i=0; i<pl->mx[0]; i++)\n      { if (i>0) putc(',',plf);\n        fprintf(plf,\"%f\",pl->x[0][i]);\n      } \n      fprintf(plf,\"],[\");\n      for (i=0; i<pl->mx[0]; i++)\n      { if (i>0) putc(',',plf);\n        fprintf(plf,\"%f\",pl->y[0][i]);\n      }\n      fprintf(plf,\"])\\n\");\n      break;\n    case 2:\n      if (pl->type[0]=='c') fprintf(plf,\"contour([\");\n                    else fprintf(plf,\"mesh([\");\n      for (i=0; i<pl->my[0]; i++) fprintf(plf,\"%f \",pl->y[0][i]); \n      fprintf(plf,\"],[\");\n      for (i=0; i<pl->mx[0]; i++) fprintf(plf,\"%f \",pl->x[0][i]); \n      fprintf(plf,\"],[\\n\");\n      for (j=0; j<pl->my[0]; j++)\n      { fprintf(plf,\"[\");\n        for (i=0; i<pl->mx[0]; i++)\n          fprintf(plf,\"%f \",pl->z[0][i*pl->my[0]+j]);\n        fprintf(plf,\"]\\n\");\n      }\n      fprintf(plf,\"])\\n\");\n      fprintf(plf,\"xlabel('%s')\\n\",pl->xlab);\n      fprintf(plf,\"ylabel('%s')\\n\",pl->ylab);\n      break;\n    default: ERROR((\"plotmatlb: invalid dimension %d\",pl->d));\n  }\n  if (pl->main!=NULL) fprintf(plf,\"title('%s')\\n\",pl->main);\n  fclose(plf);\n  printf(\"Created lfplot.m file; matlab format.\\n\");\n}\n\nvoid plotgnup(pl,fmt)\nplots *pl;\nchar *fmt;\n{ INT i, j, z, aut;\n  char m;\n  static FILE *plc=NULL;\n\n  /* first, the data file */\n  plf=fopen(\"lfplot.dat\",\"w\");\n  switch(pl->d)\n  { case 1:\n      z = pl->mx[0];\n      for (j=0; j<pl->r; j++) if (pl->mx[j]>z) z = pl->mx[j];\n      for (i=0; i<z; i++)\n      { for (j=0; j<pl->r; j++)\n          if (i<pl->mx[j])\n            fprintf(plf,\"%f %f \",pl->x[j][i],pl->y[j][i]);\n          else\n            fprintf(plf,\"%f %f \",pl->x[j][pl->mx[j]-1],pl->y[j][pl->mx[j]-1]);\n        fprintf(plf,\"\\n\");\n      }\n      break;\n    case 2:\n      for (j=0; j<pl->my[0]; j++)\n      { for (i=0; i<pl->mx[0]; i++)\n          fprintf(plf,\"%f %f %f\\n\",pl->x[0][i],pl->y[0][j],pl->z[0][i*pl->my[0]+j]);\n        fprintf(plf,\"\\n\");\n      }\n  }\n  fclose(plf);\n\n  /* second, the command file */\n  m = f2(fmt);\n  aut = (m!='m');\n#ifdef NOPIPES\n  aut = 0;\n#endif\n  if (aut)\n  { if ((m=='s') && (plc!=NULL)) pclose(plc);\n    if ((m=='s') || (plc==NULL))\n      plc = (FILE *)popen(\"gnuplot\",\"w\");\n    plf = plc;\n  }\n  else plf = fopen(\"lfplot\",\"w\");\n  switch(pl->d)\n  { case 1:\n      fprintf(plf,\"set nokey\\n\");\n      fprintf(plf,\"set xlab \\\"%s\\\"\\n\",pl->xlab);\n      fprintf(plf,\"set ylab \\\"%s\\\"\\n\",pl->ylab);\n      if (pl->main != NULL)\n        fprintf(plf,\"set title \\\"%s\\\"\\n\",pl->main);\n      fprintf(plf,\"plot \");\n      for (i=0; i<pl->r; i++)\n      { if (i>0) fprintf(plf,\", \");\n        fprintf(plf,\"\\\"lfplot.dat\\\" using %d:%d \",2*i+1,2*i+2);\n        switch(pl->type[i])\n        { case 'l': fprintf(plf,\"with lines\"); break;\n          case 'p': fprintf(plf,\"with points\"); break;\n          case 'b': fprintf(plf,\"with linespoints\"); break;\n        }\n      }\n      fprintf(plf,\"\\n\");\n      break;\n    case 2:\n      fprintf(plf,\"set xlab \\\"%s\\\"\\n\",pl->xlab);\n      fprintf(plf,\"set ylab \\\"%s\\\"\\n\",pl->ylab);\n      fprintf(plf,\"set zlab \\\"%s\\\"\\n\",pl->zlab);\n      if (pl->type[0]=='c')\n      { fprintf(plf,\"set contour\\n\");\n        fprintf(plf,\"set nosurface\\n\");\n        fprintf(plf,\"set key\\n\");\n      }\n      else\n      { fprintf(plf,\"set nocontour\\n\");\n        fprintf(plf,\"set surface\\n\");\n        fprintf(plf,\"set nokey\\n\");\n      }\n      fprintf(plf,\"set view %g,%g\\n\",pl->phi,pl->theta);\n      fprintf(plf,\"set parametric\\n\");\n      if (pl->main != NULL)\n        fprintf(plf,\"set title \\\"%s\\\"\\n\",pl->main);\n      fprintf(plf,\"splot \\\"lfplot.dat\\\" with lines\\n\");\n      break;\n  }\n  if (aut)\n    fflush(plf);\n  else\n  { fclose(plf);\n    printf(\"Created lfplot, lfplot.dat files; gnuplot format.\\n\");\n  }\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/locfit/preplot.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\n/*\n preplot():  interpolates the fit to a new set of points.\n lf  -- the fit structure.\n des -- design structure; really only needed for parfit.\n x   -- the points to predict at.\n f   -- vector to return the predictions.\n se  -- vector to return std errors (NULL if not req'd)\n band-- char for conf band type. ('n'=none, 'g'=global etc.)\n n   -- no of predictions (or vector of margin lengths for grid)\n where -- where to predict:\n 1 = points in the array x.\n 2 = grid defined by margins in x.\n 3 = data points from lf (ignore x).\n 4 = fit points from lf (ignore x).\n what -- what to predict.\n (PCOEF etc; see lfcons.h file)\n \n cpreplot(): C version front end.\n setpppoints(): (C version) used to set preplot points.\n */\n\nstatic char cb;\ndouble *sef, *fit, sigmahat;\n\nvoid predptall(lf,des,x,what,ev,i)\nlfit *lf;\ndesign *des;\ndouble *x;\nINT what, ev, i;\n{ double lik, rdf;\n    fit[i] = dointpoint(lf,des,x,what,ev,i);\n    if (cb=='n') return;\n    sef[i] = dointpoint(lf,des,x,PNLX,ev,i);\n    if (cb=='g')\n    { sef[i] *= sigmahat;\n        return;\n    }\n    if (cb=='l')\n    { lik = dointpoint(lf,des,x,PLIK,ev,i);\n        rdf = dointpoint(lf,des,x,PRDF,ev,i);\n        sef[i] *= sqrt(-2*lik/rdf);\n        return;\n    }\n    if (cb=='p')\n    { sef[i] = sigmahat*sqrt(1+sef[i]*sef[i]);\n        return;\n    }\n}\n\nvoid prepvector(lf,des,x,n,what) /* interpolate a vector */\nlfit *lf;\ndesign *des;\ndouble **x;\nINT n, what;\n{ INT i, j;\n    double xx[MXDIM];\n    for (i=0; i<n; i++)\n    { for (j=0; j<lf->mi[MDIM]; j++) xx[j] = x[j][i];\n        predptall(lf,des,xx,what,lf->mi[MEV],i);\n        if (lf_error) return;\n    }\n}\n\nvoid prepfitp(lf,des,what)\nlfit *lf;\ndesign *des;\nINT what;\n{ \n    INT i;\n    //d = lf->mi[MDIM];\n    for (i=0; i<lf->nv; i++)\n    { predptall(lf,des,evpt(lf,i),what,EFITP,i);\n        if (lf_error) return;\n    }\n}\n\nvoid prepgrid(lf,des,x,mg,n,what) /* interpolate a grid given margins */\ndesign *des;\nlfit *lf;\ndouble **x;\nINT *mg, n, what;\n{ INT i, ii, j, d;\n    double xv[MXDIM];\n    d = lf->mi[MDIM];\n    for (i=0; i<n; i++)\n    { ii = i;\n        for (j=0; j<d; j++)\n        { xv[j] = x[j][ii%mg[j]];\n            ii /= mg[j];\n        }\n        predptall(lf,des,xv,what,lf->mi[MEV],i);\n        if (lf_error) return;\n    }\n}\n\nvoid preplot(lf,des,x,f,se,band,mg,where,what)\nlfit *lf;\ndesign *des;\ndouble **x, *f, *se;\nINT *mg, where, what;\nchar band;\n{ INT d = 0, i, n;\n    double *xx[MXDIM];\n    d = lf->mi[MDIM];\n    fit = f;\n    sef = se;\n    cb = band;\n    if (cb!='n') sigmahat = sqrt(lf->dp[DRV]);\n    \n    switch(where)\n    { case 1: /* vector */\n            n = mg[0];\n            prepvector(lf,des,x,n,what);\n            break;\n        case 2: /* grid */\n            n = 1;\n            for (i=0; i<d; i++) n *= mg[i];\n            prepgrid(lf,des,x,mg,n,what);\n            break;\n        case 3: /* data */\n            n = lf->mi[MN];\n            if ((lf->mi[MEV]==EDATA) | (lf->mi[MEV]==ECROS))\n                prepfitp(lf,des,what);\n            else\n            { for (i=0; i<d; i++) xx[i] = dvari(lf,i);\n                prepvector(lf,des,xx,n,what);\n            }\n            break;\n        case 4: /* fit points */\n            n = lf->nv;\n            prepfitp(lf,des,what);\n            break;\n        default:\n            ERROR((\"unknown where in preplot\"));\n            return;\n    }\n    \n    if ((what==PT0)|(what==PVARI))\n        for (i=0; i<n; i++) f[i] = f[i]*f[i];\n}\n\n#ifdef CVERSION\nextern lfit lf;\nextern design des;\n\nvoid cpreplot(pp,vc,band)\npplot *pp;\nvari *vc;\nchar band;\n{ double *data[MXDIM];\n    INT j, mg[MXDIM];\n    for (j=0; j<pp->d; j++)\n    { data[j] = vdptr(pp->data[j]);\n        mg[j] = pp->data[j]->n;\n    }\n    j = getarg(vc,\"what\",0);\n    pp->wh = (j>0) ? ppwhat(argval(vc,j)) : PCOEF;\n    \n    preplot(&lf,&des,data,vdptr(pp->fit),vdptr(pp->se),band,mg,pp->gr,pp->wh);\n}\n\nINT setpppoints(pp,where,mg,xl)\npplot *pp;\nchar *where;\nINT *mg;\ndouble *xl;\n{ INT d, i, j, n, m;\n    varname vn;\n    d = pp->d = lf.mi[MDIM];\n    if (strcmp(where,\"fitp\")==0)\n    { n = lf.nv;\n        for (j=0; j<d; j++)\n        { sprintf(vn,\"_pred%d\",j);\n            pp->data[j] = createvar(vn,STPLOTVAR,n,VDOUBLE);\n            if (lf_error) return(0);\n            for (i=0; i<n; i++)\n                vassn(pp->data[j],i,evptx(&lf,i,j));\n        }\n        pp->gr = 4;\n        return(n);\n    }\n    if (strcmp(where,\"data\")==0)\n    { recondat(1,&n);\n        for (j=0; j<d; j++)\n        { sprintf(vn,\"_pred%d\",j);\n            pp->data[j] = createvar(vn,STPLOTVAR,n,VDOUBLE);\n            if (lf_error) return(0);\n            for (i=0; i<n; i++)\n                vassn(pp->data[j],i,datum(&lf,j,i));\n        }\n        pp->gr = 3;\n        return(n);\n    }\n    if (strcmp(where,\"grid\")==0)\n    { n = 1;\n        for (j=0; j<d; j++)\n        { sprintf(vn,\"_pred%d\",j);\n            m = (mg==NULL) ? 40 : mg[j];\n            pp->data[j] = createvar(vn,STPLOTVAR,m,VDOUBLE);\n            if (lf_error) return(0);\n            if (m==1)\n                vassn(pp->data[j],0,(xl[d+j]+xl[j])/2);\n            else\n                for (i=0; i<m; i++)\n                    vassn(pp->data[j],i,xl[j]+i*(xl[d+j]-xl[j])/(m-1));\n            n *= m;\n            pp->gr = 2;\n        }\n        return(n);\n    }\n    ERROR((\"setpppoints: invalid where=%s\",where));\n    return(0);\n}\n\n#endif\n"
  },
  {
    "path": "src/locfit/random.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\n#define PI_HALF         1.5707963267948966192313216916397514420986 /*pi/2*/\n#define PI_QUARTER      0.7853981633974483096156608458198757210493 /*pi/4*/\n#define EXP78           1.0129030479320018583185514777512982888868 /*e^(1/78)*/\n#define PI128          40.7436654315252059568342434233636766808217 /*128/pi*/\n\nstatic unsigned long cc, tv, ss=1;\n\ndouble runif()\n{\tif (ss)\n\t{ WARN((\"runif: No seed set.\"));\n          return(0.0);\n\t}\n        cc = cc * 69069;    /* congruential part */\n        tv ^= tv >> 15;       /* tausworthe part */\n        tv ^= tv << 17;\n\treturn(((tv ^ cc) >> 1) / 2147483648.0);\n}\n\nvoid rseed(seed)\n/*\n  Seed should be string of at least 8 characters.\n*/\nchar *seed;\n{\tss = 0;\n\ttv = seed[0];\n        tv = (tv<<8) | seed[1];\n        tv = (tv<<8) | seed[2];\n        tv = (tv<<8) | seed[3];\n \tcc = seed[4];\n        cc = (cc<<8) | seed[5];\n        cc = (cc<<8) | seed[6];\n        cc = (cc<<8) | seed[7];\n        if(cc % 2 == 0)\n             cc++;\n}\n\n/*\n * Gaussian random variable.\n * Reference: Kinderman & Monahan, Proceedings of\n * the ASA, Statistical Computing Section, 1975, 128-131.\n */\ndouble rnorm(mu,s)\ndouble mu, s;\n{\n\tdouble rnormk, u, x2;\n\n\tdo {\n\t\tu = runif();\n\t\trnormk = 1.715527769 * (runif()-0.5) / u;\n\t\tx2 = rnormk * rnormk / 4;\n\t} while((x2>1-u) || (x2 > -log(u)));\n\treturn(mu+s*rnormk);\n}\n\ndouble rexp(lb)\ndouble lb;\n{ return(-log(runif())/lb);\n}\n\n/*\n * Poisson random variable.\n * Simple algorithm for small lambda, else complex algorithm.\n * Crossover point must be at least 5 for the complex algorithm\n * to work correctly.\n * Reference: Devroye, pages 504, 511 and 516 (with corrections!)\n */\ndouble rpois(lambda)\ndouble lambda;\n{\n\tstatic double olambda = -1, a, mu, delta, d, c1, c2, c3, c4, c5;\n\tdouble u, e, n, x, y, w, t, p, q;\n\tint new = lambda != olambda;\n\n\tolambda = lambda;\n\tif(lambda < 8) {\n\t\tif(new)\n\t\t\ta = exp(-lambda);\n\t\tq = 1;\n\t\tx = -1;\n\t\tdo {\n\t\t\tq *= runif();\n\t\t\tx++;\n\t\t} while(q >= a);\n\t\treturn(x);\n\t}\n\n\tif(new) {\n\t\tmu = floor(lambda);\n\t\tdelta = sqrt(2 * mu * log(mu * PI128));\n\t\tdelta = MAX(6.0, MIN(mu, floor(delta)));\n\t\td = 2*mu + delta;\n\t\tc1 = sqrt(mu * PI_HALF);\n\t\tc2 = c1 + sqrt(d * PI_QUARTER) * exp(1/d);\n\t\tc3 = c2 + 1;\n\t\tc4 = c3 + EXP78;\n\t\tc5 = c4 + 2 * d * exp(-delta*(1+delta/2)/d) / delta;\n\t}\n\twhile(1) {\n\t\tu = c5 * runif();\n\t\te = -log(runif());\n\t\tif(u <= c1) {\n\t\t\tn = rnorm(0.0,1.0);\n\t\t\tx = floor(-fabs(n) * sqrt(mu));\n\t\t\tif(x < -mu)\n\t\t\t\tcontinue;\n\t\t\tw = n*n/2 + e + x*log(lambda/mu);\n\t\t} else if(u <= c2) {\n\t\t\ty = 1 + fabs(rnorm(0.0,1.0)) * sqrt(d/2);\n\t\t\tx = ceil(y);\n\t\t\tif(x > delta)\n\t\t\t\tcontinue;\n\t\t\tw = y*(y-2)/d + e + x*log(lambda/mu);\n\t\t} else if(u <= c3) {\n\t\t\tx = 0;\n\t\t\tw = e;\n\t\t} else if(u <= c4) {\n\t\t\tx = 1;\n\t\t\tw = e + log(lambda/mu);\n\t\t} else {\n\t\t\ty = delta - 2*d*log(runif())/delta;\n\t\t\tx = ceil(y);\n\t\t\tw = delta*(1+y/2)/d + e + x*log(lambda/mu);\n\t\t}\n\t\tw = -w;\n\t\tt = x*(x+1) / (2*mu);\n\t\tif(x >= 0 && w <= -t)\n\t\t\treturn(x+mu);\n\t\tif(x < 0 && w > -t)\n\t\t\tcontinue;\n\t\tq = t * ((2*x+1)/(6*mu) - 1);\n\t\tif(w > q)\n\t\t\tcontinue;\n\t\tp = x+1 <= 0 ? x+1 : 0;\n\t\tp = q - t*t/(3*(mu+p));\n\t\tif(w <= p)\n\t\t\treturn(x+mu);\n\t\tif(w <= x*log(mu) - LGAMMA(mu+x+1) + LGAMMA(mu+1))\n\t\t\treturn(x+mu);\n\t}\n}\n"
  },
  {
    "path": "src/locfit/readfile.c",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n *\n *\n *\n *   Function to read and create Locfit variables from an ASCII file.\n *\n *   Command syntax:\n *     locfit> readfile filename v1 v2 v3\n *   filename is the file to be read (no default extension or path is added).\n *   v1 v2 v3  etc are the names of the variables to create.\n *\n *   File format: The file should be a plain ASCII file organized\n *     in matrix format, with one variable per column and one observation\n *     per row. Fields are separated by spaces.\n *     \n */\n\n#include \"local.h\"\n\nextern char filename[];\nstatic FILE *aaa;\n\nvoid readfile(vc)\nvari *vc;\n{ int i, j, k, n, nv;\n  char wc[50], *fn;\n  double *dpr;\n  vari *v;\n\n  i = getarg(vc,\"file\",1);\n  if (i==0)\n  { ERROR((\"readfile: no file\"));\n    return;\n  }\n\n  fn = argval(vc,i);\n  setfilename(fn,\"\",\"r\",0);\n  if (lf_error) return;\n\n  i = getarg(vc,\"arith\",0); /* now automatic - leave for backward compat. */\n\n  aaa = fopen(filename,\"r\");\n  v = createvar(\"readfile\",STREADFI,0,VDOUBLE);\n\n  n = 0;\n  do\n  { k = fscanf(aaa,\"%s\",wc);\n    if (k==1)\n    { vassn(v,n,darith(wc));\n      n++;\n    }\n  } while (k==1);\n  fclose(aaa);\n  dpr = vdptr(v);\n  deletevar(v);\n\n  nv = 0;\n  for (i=1; i<vlength(vc); i++)\n    if (!argused(vc,i)) nv++;\n  if (nv==0) { ERROR((\"readfile: no variables specified\")); return; }\n  if (n%nv != 0)\n    WARN((\"number of items not multiple of number of variables\"));\n\n  n /= nv;\n  transpose(dpr,n,nv);\n  nv = 0;\n  for (i=1; i<vlength(vc); i++)\n    if (!argused(vc,i))\n    { v = createvar(argval(vc,i),STREGULAR,n,VDOUBLE);\n      if (v==NULL) return;\n      for (j=0; j<n; j++) vassn(v,j,dpr[nv*n+j]);\n      nv++;\n      if (lf_error) return;\n    }\n  if (argarg(vc,0)!=NULL)\n    dosavedata(vc,0);\n  else\n    for (i=1; i<vlength(vc); i++) setused(vc,i);\n}\n"
  },
  {
    "path": "src/locfit/scb.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Jiayang Sun, Catherine Loader.\n *   This file is used by the simultaneous confidence band\n *   additions to Locfit.\n *\n */\n\n#include \"local.h\"\nextern int cvi;\nstatic double scb_crit, *x, c[10], kap[5], kaq[5], max_p2;\nstatic int type, side;\n\ndouble covar_par(lf,des,x1,x2)\nlfit *lf;\ndesign *des;\ndouble x1, x2;\n{ double *v1, *v2, *wk;\n  paramcomp *pc;\n  int i, j, p, ispar;\n\n  v1 = des->f1; v2 = des->ss; wk = des->oc;\n  ispar = (lf->mi[MKER]==WPARM) && (hasparcomp(lf));\n  p = lf->mi[MP];\n\n/*  for parametric models, the covariance is\n *  A(x1)^T (X^T W V X)^{-1} A(x2)\n *  which we can find easily from the parametric component.\n */\n  if (ispar)\n  { pc = &lf->pc;\n    fitfun(lf,&x1,pc->xbar,v1,NULL,0);\n    fitfun(lf,&x2,pc->xbar,v2,NULL,0);\n    jacob_hsolve(&lf->pc.xtwx,v1);\n    jacob_hsolve(&lf->pc.xtwx,v2);\n  }\n\n/*  for non-parametric models, we must use the cholseky decomposition\n *  of M2 = X^T W^2 V X. Courtesy of comp_vari, we already have\n *  des->P = M2^{1/2} M1^{-1}.\n */\n  if (!ispar)\n  { fitfun(lf,&x1,des->xev,wk,NULL,0);\n    for (i=0; i<p; i++)\n    { v1[i] = 0;\n      for (j=0; j<p; j++) v1[i] += des->P[i*p+j]*wk[j];\n    }\n    fitfun(lf,&x2,des->xev,wk,NULL,0);\n    for (i=0; i<p; i++)\n    { v2[i] = 0;\n      for (j=0; j<p; j++) v2[i] += des->P[i*p+j]*wk[j];\n    }\n  }\n\n  return(innerprod(v1,v2,p));\n}\n\nvoid cumulant(lf,des,sd)\nlfit *lf;\ndesign *des;\ndouble sd;\n{ double b2i, b3i, b3j, b4i;\n  double ss, si, sj, uii, uij, ujj, k1;\n  INT ii, i, j, jj, *mi;\n  for (i=1; i<10; i++) c[i] = 0.0;\n  k1 = 0;\n  mi = lf->mi;\n\n  /* ss = sd*sd; */\n  ss = covar_par(lf,des,des->xev[0],des->xev[0]);\n\n/*\n * this isn't valid for nonparametric models. At a minimum,\n * the sums would have to include weights. Still have to work\n * out the right way.\n */\n  for (i=0; i<mi[MN]; i++)\n  { ii = des->ind[i];\n    b2i = b2(des->th[i],mi[MTG],prwt(lf,ii));\n    b3i = b3(des->th[i],mi[MTG],prwt(lf,ii));\n    b4i = b4(des->th[i],mi[MTG],prwt(lf,ii));\n    si = covar_par(lf,des,des->xev[0],datum(lf,0,ii));\n    uii= covar_par(lf,des,datum(lf,0,ii),datum(lf,0,ii));\n    if (lf_error) return;\n\n    c[2] += b4i*si*si*uii;\n    c[6] += b4i*si*si*si*si;\n    c[7] += b3i*si*uii;\n    c[8] += b3i*si*si*si;\n    /* c[9] += b2i*si*si*si*si;\n       c[9] += b2i*b2i*si*si*si*si; */\n    k1 += b3i*si*(si*si/ss-uii);\n\n    /* i=j components */\n    c[1] += b3i*b3i*si*si*uii*uii;\n    c[3] += b3i*b3i*si*si*si*si*uii;\n    c[4] += b3i*b3i*si*si*uii*uii;\n\n    for (j=i+1; j<mi[MN]; j++)\n    { jj = des->ind[j];\n      b3j = b3(des->th[j],mi[MTG],prwt(lf,jj));\n      sj = covar_par(lf,des,des->xev[0],datum(lf,0,jj));\n      uij= covar_par(lf,des,datum(lf,0,ii),datum(lf,0,jj));\n      ujj= covar_par(lf,des,datum(lf,0,jj),datum(lf,0,jj));\n\n      c[1] += 2*b3i*b3j*si*sj*uij*uij;\n      c[3] += 2*b3i*b3j*si*si*sj*sj*uij;\n      c[4] += b3i*b3j*uij*(si*si*ujj+sj*sj*uii);\n      if (lf_error) return;\n    }\n  }\n  c[5] = c[1];\n  c[7] = c[7]*c[8];\n  c[8] = c[8]*c[8];\n\n  c[1] /= ss; c[2] /= ss; c[3] /= ss*ss; c[4] /= ss;\n  c[5] /= ss; c[6] /= ss*ss; c[7] /= ss*ss;\n  c[8] /= ss*ss*ss; c[9] /= ss*ss;\n\n/* constants used in p(x,z) computation */\n  kap[1] = k1/(2*sqrt(ss));\n  kap[2] = 1 + 0.5*(c[1]-c[2]+c[4]-c[7]) - 3*c[3] + c[6] + 1.75*c[8];\n  kap[4] = -9*c[3] + 3*c[6] + 6*c[8] + 3*c[9];\n\n/* constants used in q(x,u) computation */\n  kaq[2] = c[3] - 1.5*c[8] - c[5] - c[4] + 0.5*c[7] + c[6] - c[2];\n  kaq[4] = -3*c[3] - 6*c[4] - 6*c[5] + 3*c[6] + 3*c[7] - 3*c[8] + 3*c[9];\n}\n\n/* q2(u) := u+q2(x,u) in paper */\ndouble q2(u)\ndouble u;\n{ return(u-u*(36.0*kaq[2] + 3*kaq[4]*(u*u-3) + c[8]*((u*u-10)*u*u+15))/72.0);\n}\n\n/*  p2(u) := p2(x,u) in paper */\ndouble p2(u)\ndouble u;\n{ return( -u*( 36*(kap[2]-1+kap[1]*kap[1])\n     + 3*(kap[4]+4*kap[1]*sqrt(kap[3]))*(u*u-3)\n     + c[8]*((u*u-10)*u*u+15) ) / 72 );\n}\n\nvoid procvscb2(des,lf,v)\ndesign *des;\nlfit *lf;\nINT v;\n{ double thhat, sd, *lo, *hi, u;\n  int err, tmp;\n  x = des->xev = evpt(lf,v);\n  tmp = lf->mi[MPC];\n  if ((lf->mi[MKER]==WPARM) && (hasparcomp(lf)))\n  { lf->coef[v] = thhat = addparcomp(lf,des->xev,PCOEF);\n    lf->nlx[v] = sd = addparcomp(lf,des->xev,PNLX);\n  }\n  else\n  { lf->mi[MPC] = 0;\n    procv(des,lf,v);\n    thhat = lf->coef[v];\n    sd = lf->nlx[v];\n  }\n  if (type >= 2)\n  { if (lf->mi[MKER] != WPARM)\n      WARN((\"nonparametric fit; correction is invalid\"));\n    cumulant(lf,des,sd);\n  }\n  lf->mi[MPC] = tmp;\n  lo = vdptr(lf->L);\n  hi = &lo[lf->nvm];\n  switch(type)\n  { case 0:\n    case 1: /* basic scr */\n      lo[v] = thhat - scb_crit * sd;\n      hi[v] = thhat + scb_crit * sd;\n      return;\n    case 2: /* centered scr */\n      lo[v] = thhat - kap[1]*sd - scb_crit*sd*sqrt(kap[2]);\n      hi[v] = thhat - kap[1]*sd + scb_crit*sd*sqrt(kap[2]);\n      return;\n    case 3: /* corrected 2 */\n      u = solve_secant(q2,scb_crit,0.0,2*scb_crit,0.000001,BDF_NONE,&err);\n      lo[v] = thhat - u*sd;\n      hi[v] = thhat + u*sd;\n      return;\n    case 4: /* corrected 2' */\n      u = fabs(p2(scb_crit));\n      max_p2 = MAX(max_p2,u);\n      lo[v] = thhat;\n      hi[v] = thhat;\n      return;\n  }\n  ERROR((\"procvscb2: invalid type\"));\n}\n\nvoid scb(des,lf)\ndesign *des;\nlfit *lf;\n{ double kap[10], *lo, *hi;\n  INT i, *mi, nterms;\n  mi = lf->mi;\n  mi[MP] = calcp(mi,mi[MDEG]);\n  type = mi[MGETH] - 70;\n  deschk(des,mi[MN],mi[MP]);\n  des->pref = 0;\n  cvi = -1; /* inhibit cross validation */\n  mi[MLINK] = defaultlink(mi[MLINK],mi[MTG]);\n\n  if (type==0)\n  { kap[0] = 1;\n    scb_crit = critval(kap,1,0,0.05,10,2,0.0);\n  }\n  else\n  { compparcomp(des,lf,0);\n    nterms = constants(des,lf,kap);\n    scb_crit = critval(kap,nterms,mi[MDIM],0.05,10,2,0.0);\n  }\n\n  max_p2 = 0.0;\n  startlf(des,lf,procvscb2,0);\n  if (type==4)\n  { lo = vdptr(lf->L);\n    hi = &lo[lf->nvm];\n    for (i=0; i<lf->nv; i++)\n    {\n      lo[i] -= (scb_crit-max_p2)*lf->nlx[i];\n      hi[i] += (scb_crit-max_p2)*lf->nlx[i];\n    }\n  }\n}\n\n#ifdef CVERSION\nextern lfit lf;\nextern design des;\nextern vari *aru;\n\nlfit *lf_sim;\ndesign *des_sim;\n\ndouble scbsim_fun(x)\ndouble x;\n{ double y;\n  evptx(lf_sim,0,0) = x;\n  procv(des_sim,lf_sim,0);\n\n  if (type>=2)\n  { if (lf_sim->mi[MKER] != WPARM)\n      WARN((\"nonparametric fit; correction is invalid\"));\n    cumulant(lf_sim,des_sim,lf_sim->nlx[0]);\n  }\n\n  y = lf_link(dareval(aru,0,&x),lf_sim->mi[MLINK]);\n  y = (lf_sim->coef[0] - y) / lf_sim->nlx[0];\n\n  switch(type)\n  {\n    case 2:\n      y = (y-kap[1]) / sqrt(kap[2]);\n      break;\n    case 3:\n      y = (y-kap[1])/sqrt(kap[2]);\n      y = (y>0) ? y+q2(y) : y - q2(y);\n      break;\n  }\n\n  switch(side)\n  { case -1: return(-y);\n    case  1: return(y);\n    default: return(fabs(y));\n  }\n}\n\nstatic double max;\n\nvoid do_scbsim(des,lf)\ndesign *des;\nlfit *lf;\n{ double y;\n  int err;\n\n  lf_sim = lf;\n  des_sim = des;\n\n  trchck(lf,1,1,lf->mi[MDIM],lf->mi[MP],1);\n  y = max_quad(scbsim_fun,lf->fl[0],lf->fl[1],10,0.00001,&err,'y');\n  max = y;\n}\n\nvoid scbsim(lf,des)\nlfit *lf;\ndesign *des;\n{ double kap[5];\n  int nterms;\n\n  lf->mi[MEV] = 100;\n  startlf(des,lf,scbsim_fun,1);\n\n  nterms = constants(des,lf,kap);\n  printf(\"xmx: %10.6f  max: %10.6f  k0 %10.6f %10.6f  pr %10.6f\\n\",0.0,max,kap[0],kap[1],tailp(max,kap,nterms,lf->mi[MDIM],0.0));\n}\n\nvoid cscbsim(v)\nvari *v;\n{ int i;\n  side = 0; type = 1;\n  fitoptions(&lf,v,0);\n\n  i = getarg(v,\"mean\",1);\n  if (i==0)\n  { WARN((\"cscbsim: no mean function; setting = 0\"));\n    aru = arbuild(\"0\",0,0,NULL,0,1);\n  }\n  else\n  { aru = arbuild(argval(v,i),0,strlen(argval(v,i))-1,NULL,0,1);\n    setvarname(aru,\"_aru\");\n  }\n\n  i = getarg(v,\"corr\",1);\n  if (i>0) type = getlogic(v,i);\n  if (lf_error) return;\n\n  i = getarg(v,\"side\",1);\n  if (i>0) sscanf(argval(v,i),\"%d\",&side);\n  if (lf_error) return;\n\n  scbsim(&lf,&des);\n}\n#endif\n"
  },
  {
    "path": "src/locfit/scb_cons.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Jiayang Sun, Catherine Loader.\n *   This file is used by the simultaneous confidence band\n *   additions to Locfit.\n *\n */\n\n#include \"local.h\"\n\nextern INT cvi;\n\nstatic double *fd, *ft, *lij, *d1a;\nstatic INT par;\n\nvoid assignk0(z,d,n) /* z should be n*(2*d*d+2*d+2); */\ndouble *z;\nINT d, n;\n{ d1a= z; z += d*d*n;\n  ft = z; z += n*(d*(d+1)+1);\n  fd = z; z += n*(d+1);\n}\n\nvoid christ(d,nn,nl)  /* lij[i][j] = res proj. of Tij to (T1...Td) */\ndouble nl;\nINT d, nn;\n{ INT i, j, k, l;\n  double p4, *ll, v[1+MXDIM];\n  for (i=0; i<d; i++)\n    for (j=i; j<d; j++)\n    { ll = &lij[(i*d+j)*nn];\n      for (k=0; k<=d; k++) v[k] = innerprod(&ft[k*nn],ll,nn);\n      bacT(fd,v,d+1,0,d+1);\n      for (k=0; k<nn; k++)\n        for (l=0; l<=d; l++)\n          ll[k] -= ft[l*nn+k]*v[l];\n      p4 = 0;\n      for (k=0; k<=i+1; k++)\n        p4 += fd[k*(d+1)+i+1]*fd[k*(d+1)+j+1];\n      p4 = (fd[i+1]*fd[j+1]-p4)/(nl*nl);\n      for (k=0; k<nn; k++)\n        ll[k] = lij[(j*d+i)*nn+k] = ll[k] + p4*ft[k];\n    }\n}\n\nvoid d1(n,d)   /* d1[i][j] = e_i^T (A^T A)^{-1} B_j^T */\nINT n, d;\n{ INT a, b, i, j;\n  double *dd, v[MXDIM];\n  for (i=0; i<d; i++)\n  { for (j=0; j<d; j++) v[j] = 0;\n    v[i] = 1;\n    bacT(fd,v,d+1,1,d+1);\n    for (j=0; j<d; j++)\n    { dd = &d1a[(i*d+j)*n];\n      for (a=0; a<n; a++)\n      { dd[a] = 0;\n        for (b=0; b<d; b++)\n          dd[a] += v[b] * lij[(j*d+b)*n+a]; \n} } } }\n\nvoid k2x(lf,des,kap)\nlfit *lf;\ndesign *des;\ndouble *kap;\n{ double det, s;\n  INT i, j, k, l, d, m;\n  d = lf->mi[MDIM];\n  m = wdiag(lf,des,ft,1+(d>1),2,0);\n  lij = &ft[(d+1)*m];\n  for (i=0; i<m; i++)\n    for (j=0; j<=d; j++)\n      fd[i*(d+1)+j] = ft[j*m+i];\n  QR1(fd,m,d+1,NULL);\n  s = 0;\n  if (d>1)\n  { christ(d,m,fd[0]);\n    d1(m,d);\n    for (j=0; j<d; j++)\n      for (k=0; k<j; k++)\n        for (l=0; l<m; l++)\n          s += d1a[(j*d+k)*m+l]*d1a[(k*d+j)*m+l]\n             - d1a[(j*d+j)*m+l]*d1a[(k*d+k)*m+l];\n  }\n  det = 1;\n  for (j=1; j<=d; j++)\n    det *= fd[j*(d+2)]/fd[0];\n  kap[0] = det;\n  kap[2] = s*det*fd[0]*fd[0];\n}\n\nvoid l1x(lf,des,lap,re)\nlfit *lf;\ndesign *des;\ndouble *lap;\nINT re;\n{ double det, t, sumcj, nu, *u, v[MXDIM];\n  INT i, j, j1, d, m;\n  d = lf->mi[MDIM]; u = des->res;\n  m = wdiag(lf,des,ft,2,2,0);\n  lij = &ft[(d+1)*m];\n  for (i=0; i<m; i++)\n  { t = ft[(re+1)*m+i];\n    ft[(re+1)*m+i] = ft[d*m+i];\n    ft[d*m+i] = t;\n    for (j=0; j<d; j++) /* don't copy last column */\n      fd[i*d+j] = ft[j*m+i];\n    u[i] = ft[d*m+i];\n  }\n  QR1(fd,m,d,&ft[d*m]);\n  bacK(fd,&ft[d*m],d);\n  nu = 0;\n  for (i=0; i<m; i++)\n  { for (j=0; j<d; j++)\n      u[i] -= ft[j*m+i]*ft[d*m+j];\n    nu += u[i]*u[i];\n  }    /* now u is outward vector, nu = ||u|| */\n  sumcj = 0;\n  for (i=0; i<d; i++) /* copy l(d-1,i) to l(re,i) */\n    for (j=0; j<m; j++)\n      lij[(re*d+i)*m+j] = lij[((d-1)*d+i)*m+j];\n  for (j=0; j<d; j++)\n  { if (j != re)\n    { j1 = (j==(d-1)) ? re : j;\n      for (i=0; i<d-1; i++)\n        v[i] = innerprod(&lij[(i*d+j)*m],u,m);\n      bacT(fd,v,d,1,d);\n      sumcj += -v[j1];\n    }\n  }                                   /* stage 3,4 now complete */\n  det = 1;\n  for (j=1; j<d; j++)\n    det *= fd[j*(d+1)]/fd[0];\n  lap[0] = det;\n  lap[1] = sumcj*det*fd[0]/sqrt(nu);\n}\n\nvoid m0x(lf,des,m0,re,rg)\nlfit *lf;\ndesign *des;\ndouble *m0;\nINT re, rg;\n{ double det, t;\n  INT d, m, i, j;\n  d = lf->mi[MDIM];\n  m = wdiag(lf,des,ft,1,2,0);\n  for (i=0; i<m; i++)\n  { t=ft[(rg+1)*m+i]; ft[(rg+1)*m+i]=ft[d*m+i]; ft[d*m+i]=t;\n    t=ft[(re+1)*m+i]; ft[(re+1)*m+i]=ft[(d-1)*m+i]; ft[(d-1)*m+i]=t;\n    for (j=0; j<=d; j++)\n      fd[i*(d+1)+j] = ft[j*m+i];\n  }\n  det = 1;\n  QR1(fd,m,d+1,NULL);\n  for (j=1; j<d-1; j++)\n    det *= fd[j*(d+2)]/fd[0];\n  m0[0] = det*atan2(fd[d*(d+2)],-par*fd[d*(d+1)-1]);\n}\n\nINT constants(des,lf,kap)\ndesign *des;\nlfit *lf;\ndouble *kap;\n{ double h, k0[3], k1[3], l0[2], l1[2], m0[1], m1[1];\n  double z[MXDIM], delt[MXDIM], mk, ml, mm;\n  INT d, i, j, nnn, wt, index[MXDIM], *mi, pe, re, rg;\n  cvi = -1; /* avoid cross valid */\n  mi = lf->mi;\n  d = mi[MDIM];\n  if (lf_error) return(0);\n  if ((lf->mi[MKER] != WPARM) && (lf->dp[DALP]>0))\n    WARN((\"constants are approximate for varying h\"));\n  mi[MP] = calcp(mi,mi[MDEG]);\n  deschk(des,mi[MN],mi[MP]);\n  preproc(des,lf,mi[MKER]!=WPARM);\n  nnn = (ident==1) ? lf->mi[MP] : lf->mi[MN];\n  lf->L = checkvarlen(lf->L,2*nnn*(d*d+d+1),\"_hatmat\",VDOUBLE);\n  assignk0(vdptr(lf->L),d,nnn);\n  mi[MDC] = 1;\n  des->xev = z;\n\n  mk = 1.0;\n  for (i=0; i<d; i++)\n  { index[i] = 0;\n    z[i] = lf->fl[i];\n    delt[i] = (lf->fl[i+d]-z[i])/(3*mi[MMINT]);\n    mk *= delt[i];\n  }\n  i = 0;\n  \n  k0[0] = k0[1] = k0[2] = 0.0;\n  l0[0] = l0[1] = 0.0;\n  m0[0] = 0.0;\n\n#ifdef CVERSION\n  if (mi[MIT]==IMONT)\n  { for (i=0; i<mi[MMINT]; i++)\n    { for (j=0; j<d; j++) z[j] = lf->fl[j]+(lf->fl[j+d]-lf->fl[j])*runif();\n      if ((mi[MKER]!=WPARM) | (!hasparcomp(lf)))\n      { h = nbhd(lf,des,(INT)(mi[MN]*lf->dp[DALP]),lf->dp[DFXH],0);\n        locfit(lf,des,h,1);\n      }\n      k2x(lf,des,k1);\n      k0[0] += k1[0];\n    }\n    for (j=0; j<d; j++) k0[0] *= lf->fl[j+d]-lf->fl[j];\n    kap[0] = k0[0]/mi[MMINT];\n    return(1);\n  }\n#endif\n\n  while(1)\n  {\n    wt = 1;\n    for (i=0; i<d; i++)\n      wt *= (4-2*(index[i]%2==0)-(index[i]==0)-(index[i]==mi[MMINT]));\n    if ((mi[MKER]!=WPARM) | (!hasparcomp(lf)))\n    { h = nbhd(lf,des,(INT)(mi[MN]*lf->dp[DALP]),lf->dp[DFXH],0);\n      locfit(lf,des,h,1);\n    }\n    k2x(lf,des,k1);\n    k0[0] += wt*mk*k1[0];\n    k0[2] += wt*mk*k1[2];\n\n    for (re=0; re<d; re++) if ((index[re]==0) | (index[re]==mi[MMINT]))\n    { l1x(lf,des,l1,re);\n      ml = 1;\n      for (i=0; i<d; i++) if (i!=re) ml *= delt[i];\n      pe = 1-2*(index[re]==0);\n      l0[0] += wt*ml*l1[0];\n      l0[1] += wt*ml*pe*l1[1];\n\n      for (rg=re+1; rg<d; rg++) if ((index[rg]==0) | (index[rg]==mi[MMINT]))\n      { par = pe*(1-2*(index[rg]==0));\n        m0x(lf,des,m1,re,rg);\n        mm = 1;\n        for (i=0; i<d; i++) if ((i!=re) & (i!=rg)) mm *= delt[i];\n        m0[0] += wt*mm*m1[0];\n      }\n    }\n\n    /* compute next grid point */\n    for (i=0; i<d; i++)\n    { index[i]++;\n      z[i] = lf->fl[i]+3*delt[i]*index[i];\n      if (index[i]>mi[MMINT])\n      { index[i] = 0;\n        z[i] = lf->fl[i];\n        if (i==d-1) /* done */\n        { kap[0] = k0[0];\n          kap[1] = l0[0]/2;\n          if (d==1) return(2);\n          k0[2] = -k0[2] - d*(d-1)*k0[0]/2;\n          if (mi[MDEB]>0)\n          { printf(\"constants:\\n\");\n            printf(\"  k0: %8.5f  k2: %8.5f\\n\",k0[0],k0[2]);\n            printf(\"  l0: %8.5f  l1: %8.5f\\n\",l0[0],l1[1]);\n            printf(\"  m0: %8.5f\\n\",m0[0]);\n            printf(\"  check: %8.5f\\n\",(k0[0]+k0[2]+l0[1]+m0[0])/(2*PI));\n          }\n          kap[2] = (k0[2]+l0[1]+m0[0])/(2*PI);\n          return(3);\n        }\n      }\n      else i = d;\n    }\n\n  }\n}\n\ndouble tailp(c,k0,m,d,nu)\ndouble c, *k0, nu;\nINT m, d;\n{ INT i;\n  double p;\n  p = 0;\n  if (nu==0)\n  { for (i=0; i<m; i++) if (k0[i]>0)\n      p += k0[i]*exp(LGAMMA((d+1-i)/2.0)-(d+1-i)*LOGPI/2)\n          *(1-pchisq(c*c,(double) d+1-i));\n  }\n  else\n  { for (i=0; i<m; i++) if (k0[i]>0)\n      p += k0[i]*exp(LGAMMA((d+1-i)/2.0)-(d+1-i)*LOGPI/2)\n          *(1-pf(c*c/(d+1-i),(double) (d+1-i), nu));\n  }\n  return(p);\n}\n\ndouble taild(c,k0,m,d,nu)\ndouble c, *k0, nu;\nINT m, d;\n{ double p;\n  INT i;\n  p = 0;\n  if (nu==0)\n  { for (i=0; i<m; i++) if (k0[i]>0)\n      p += k0[i]*exp(LGAMMA((d+1-i)/2.0)-(d+1-i)*LOGPI/2)\n          *2*c*dchisq(c*c,(double) (d+1-i));\n  }\n  else\n  { for (i=0; i<m; i++) if (k0[i]>0)\n      p += k0[i]*exp(LGAMMA((d+1-i)/2.0)-(d+1-i)*LOGPI/2)\n          *2*c*df(c*c/(d+1-i),(double) (d+1-i), nu)/(d+1-i);\n  }\n  return(-p);\n}\n\ndouble critval(k0,m,d,al,it,s,nu)\ndouble *k0, al, nu;\nINT m, d, it, s;\n{ double c, cn, c0, c1, tp, td;\n  INT j;\n  if (m<0) ERROR((\"critval: no terms?\"));\n  if (m>d+1) m = d+1;\n  if ((al<=0) | (al>=1)) ERROR((\"critval: invalid alpha %8.5f\",al));\n  if (lf_error) return(0.0);\n  if (al>0.5) WARN((\"critval: A mighty large tail probability al=%8.5f\",al));\n  if (s==1) al = 2*al;\n  if (m==0) { d = 0; k0[0] = 1; m = 1; }\n  c = 2.0; c0 = 0.0; c1 = 0.0;\n  for (j=0; j<it; j++)\n  { tp = tailp(c,k0,m,d,nu)-al;\n    td = taild(c,k0,m,d,nu);\n    if (tp>0) c0 = c;\n    if (tp<0) c1 = c;\n    cn = c - tp/td;\n    if (cn<c0) cn = (c+c0)/2;\n    if ((c1>0.0) && (cn>c1)) cn = (c+c1)/2;\n    c = cn;\n    if (fabs(tp/al)<1.0e-10) return(c);\n  }\n  return(c);\n}\n\n#ifdef SVERSION\nvoid scritval(k0,d,cov,m,rdf,z)\ndouble *k0, *z, *cov, *rdf;\nINT *d, *m;\n{ lf_error = 0;\n  *z = critval(k0,*m,*d,1-*cov,10,2,*rdf);\n}\n#endif\n"
  },
  {
    "path": "src/locfit/simul.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n */\n\n#include \"local.h\"\n\nstatic double pen, sig2;\n\nvoid goldensec(f,des,tr,eps,xm,ym,meth)\ndouble (*f)(), eps, *xm, *ym;\nINT meth;\ndesign *des;\nlfit *tr;\n{ double x[4], y[4], xx[11], yy[11];\n  INT i, im;\n  xx[0] = tr->dp[DFXH];\n  if (xx[0]<=0)\n  { ERROR((\"regband: initialize h>0\"));\n    return;\n  }\n  for (i=0; i<=10; i++)\n  { if (i>0) xx[i] = (1+GOLDEN)*xx[i-1];\n    yy[i] = f(xx[i],des,tr,meth);\n    if ((i==0) || (yy[i]<yy[im])) im = i;\n  }\n  if (im==0) im = 1;\n  if (im==10)im = 9;\n  x[0] = xx[im-1]; y[0] = yy[im-1];\n  x[1] = xx[im];   y[1] = yy[im];\n  x[3] = xx[im+1]; y[3] = yy[im+1];\n  x[2] = GOLDEN*x[3]+(1-GOLDEN)*x[0];\n  y[2] = f(x[2],des,tr,meth);\n  while (x[3]-x[0]>eps)\n  { if (y[1]<y[2])\n    { x[3] = x[2]; y[3] = y[2];\n      x[2] = x[1]; y[2] = y[1];\n      x[1] = GOLDEN*x[0]+(1-GOLDEN)*x[3];\n      y[1] = f(x[1],des,tr,meth);\n    }\n    else\n    { x[0] = x[1]; y[0] = y[1];\n      x[1] = x[2]; y[1] = y[2];\n      x[2] = GOLDEN*x[3]+(1-GOLDEN)*x[0];\n      y[2] = f(x[2],des,tr,meth);\n    }\n  }\n  im = 0;\n  for (i=1; i<4; i++) if (y[i]<y[im]) im = i;\n  *xm = x[im]; *ym = y[im];\n}\n\ndouble dnk(x,k)\ndouble x;\nINT k;\n{ double f;\n  switch(k)\n  { case 0: f = 1; break;\n    case 1: f = -x; break;\n    case 2: f = x*x-1; break;\n    case 3: f = x*(x*x-3); break;\n    case 4: f = 3-x*x*(6-x*x); break;\n    case 5: f = -x*(15-x*x*(10-x*x)); break;\n    case 6: f = -15+x*x*(45-x*x*(15-x*x)); break;\n    default: ERROR((\"dnk: k=%d too large\",k)); return(0.0);\n  }\n  return(f*exp(-x*x/2)/S2PI);\n}\n\ndouble locai(h,des,tr)\ndouble h;\ndesign *des;\nlfit *tr;\n{ double cp;\n  tr->dp[DALP] = h;\n  startlf(des,tr,procv,0);\n  ressumm(tr,des);\n  cp = -2*tr->dp[DLK]+pen*tr->dp[DT0];\n  return(cp);\n}\n\ndouble loccp(h,des,tr,m) /* m=1: cp    m=2: gcv */\ndouble h;\ndesign *des;\nlfit *tr;\nint m;\n{ double cp;\n  INT dg;\n  tr->dp[DALP] = 0;\n  tr->dp[DFXH] = h;\n  dg = tr->mi[MDEG]; tr->mi[MDEG] = tr->mi[MDEG0];\n  startlf(des,tr,procv,0);\n  ressumm(tr,des);\n  if (m==1)\n    cp = -2*tr->dp[DLK]/sig2 - tr->mi[MN] + 2*tr->dp[DT0];\n  else cp = -2*tr->mi[MN]*tr->dp[DLK]/((tr->mi[MN]-tr->dp[DT0])*(tr->mi[MN]-tr->dp[DT0]));\n  printf(\"h %8.5f  deg %2d  rss %8.5f  trl %8.5f  cp: %8.5f\\n\",h,tr->mi[MDEG],-2*tr->dp[DLK],tr->dp[DT0],cp);\n  tr->mi[MDEG0] = tr->mi[MDEG]; tr->mi[MDEG] = dg;\n  return(cp);\n}\n\ndouble cp(des,tr,meth)\ndesign *des;\nlfit *tr;\nINT meth;\n{ double hm, ym;\n  goldensec(loccp,des,tr,0.001,&hm,&ym,meth);\n  return(hm);\n}\n\ndouble gkk(des,tr)\ndesign *des;\nlfit *tr;\n{ double h, h5, nf, th;\n  INT i, j, n, dg0, dg1;\n  tr->mi[MEV]=EDATA;\n  tr->dp[DALP] = 0;\n  n = tr->mi[MN];\n  dg0 = tr->mi[MDEG0];     /* target degree */\n  dg1 = dg0+1+(dg0%2==0);  /* pilot degree */\n  nf = exp(log(1.0*n)/10); /* bandwidth inflation factor */\n  h = tr->dp[DFXH];        /* start bandwidth */\n  for (i=0; i<=10; i++)\n  { tr->mi[MDEG] = dg1;\n    tr->dp[DFXH] = h*nf;\n    startlf(des,tr,procv,0);\n    th = 0;\n    for (j=10; j<n-10; j++)\n      th += tr->coef[dg1*n+j]*tr->coef[dg1*n+j];\nth *= n/(n-20.0);\n    h5 = sig2*Wikk(tr->mi[MKER],dg0)/th;\n    h = exp(log(h5)/(2*dg1+1));\n/* printf(\"pilot %8.5f  sel %8.5f\\n\",tr->dp[DFXH],h); */\n  }\n  return(h);\n}\n\ndouble rsw(des,tr,kk)\ndesign *des;\nlfit *tr;\nINT *kk;\n{ INT i, j, k, nmax, nvm, n, mk, ev, dg0, dg1;\n  double rss[6], cp[6], th22, dx, d2, hh;\n  nmax = 5;\n  ev = tr->mi[MEV];  tr->mi[MEV] = EGRID;\n  mk = tr->mi[MKER]; tr->mi[MKER]= WRECT;\n  dg0 = tr->mi[MDEG0];\n  dg1 = 1 + dg0 + (dg0%2==0);\n  tr->mi[MDEG]= 4;\n  for (k=nmax; k>0; k--)\n  { tr->mg[0] = k;\n    tr->fl[0] = 1.0/(2*k); tr->fl[1] = 1-1.0/(2*k);\n    tr->dp[DALP] = 0; tr->dp[DFXH] = 1.0/(2*k);\n    startlf(des,tr,procv,0);\n    nvm = tr->nvm;\n    rss[k] = 0;\n    for (i=0; i<k; i++) rss[k] += -2*tr->lik[i];\n  }\n  n = tr->mi[MN]; k = 1;\n  for (i=1; i<=nmax; i++)\n  { /* cp[i] = (n-5*nmax)*rss[i]/rss[nmax]-(n-10*i); */\n    cp[i] = rss[i]/sig2-(n-10*i);\n    if (cp[i]<cp[k]) k = i;\n  }\n  *kk = k;\n  tr->mg[0] = k;\n  tr->fl[0] = 1.0/(2*k); tr->fl[1] = 1-1.0/(2*k);\n  tr->dp[DALP] = 0; tr->dp[DFXH] = 1.0/(2*k);\n  startlf(des,tr,procv,0);\n  tr->mi[MKER] = mk; tr->mi[MEV] = ev;\n  nvm = tr->nvm;\n  th22 = 0;\n  for (i=10; i<n-10; i++)\n  { j = floor(k*datum(tr,0,i));\n    if (j>=k) j = k-1;\n    dx = datum(tr,0,i)-evptx(tr,0,j);\n    if (dg1==2)\n      d2 = tr->coef[2*nvm+j]+dx*tr->coef[3*nvm+j]+dx*dx*tr->coef[4*nvm+j]/2;\n    else d2 = tr->coef[4*nvm+j];\n    th22 += d2*d2;\n  }\n  hh = Wikk(mk,dg0)*sig2/th22*(n-20.0)/n;\n  return(exp(log(hh)/(2*dg1+1)));\n}\n\nvoid rband(des,tr,hhat,meth,nmeth,kk)\ndesign *des;\nlfit *tr;\ndouble *hhat;\nINT *meth, *nmeth, *kk;\n{ INT i, deg;\n  double h0;\n\n  /* first, estimate sigma^2 */\n  deg = tr->mi[MDEG]; tr->mi[MDEG] = 2;\n  h0 = tr->dp[DFXH];  tr->dp[DFXH] = 0.05;\nprintf(\"alp: %8.5f  h: %8.5f  deg %2d  ev %2d\\n\",tr->dp[DALP],tr->dp[DFXH],tr->mi[MDEG],tr->mi[MEV]);\n  startlf(des,tr,procv,0);\n  ressumm(tr,des);\n  tr->mi[MDEG] = deg; tr->dp[DFXH] = h0;\n  sig2 = tr->dp[DRV]; \n  printf(\"sd est: %8.5f\\n\",sqrt(tr->dp[DRV]));\n\n  for (i=0; i<*nmeth; i++)\n  { switch(meth[i])\n    { case 1: hhat[i] = cp(des,tr,1);\n              break;\n      case 2: hhat[i] = cp(des,tr,2);\n              break;\n      case 3: hhat[i] = gkk(des,tr);\n              break;\n      case 4: hhat[i] = rsw(des,tr,kk);\n              break;\n      default: hhat[i] = 0;\n    }\n    tr->dp[DFXH] = h0;\n    tr->mi[MDEG] = deg;\n  }\n}\n"
  },
  {
    "path": "src/locfit/solve.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *  solve f(x)=c by various methods, with varying stability etc...\n *    xlo and xhi should be initial bounds for the solution.\n *    convergence criterion is |f(x)-c| < tol.\n *\n *  double solve_secant(f,c,xlo,xhi,tol,bd_flag,err)\n *    secant method solution of f(x)=c.\n *    xlo and xhi are starting values and bound for solution.\n *    tol = convergence criterion, |f(x)-c| < tol.\n *    bd_flag = if (xlo,xhi) doesn't bound a solution, what action to take?\n *      BDF_NONE returns error.\n *      BDF_EXPRIGHT increases xhi.\n *      BDF_EXPLEFT  decreases xlo.\n *    err = error flag.\n *    The (xlo,xhi) bound is not formally necessary for the secant method.\n *    But having such a bound vastly improves stability; the code performs\n *    a bisection step whenever the iterations run outside the bounds.\n *\n *  double solve_nr(f,f1,c,x0,tol,err)\n *    Newton-Raphson solution of f(x)=c.\n *    f1 = f'(x).\n *    x0 = starting value.\n *    tol = convergence criteria, |f(x)-c| < tol.\n *    err = error flag.\n *    No stability checks at present.\n *\n *  double solve_fp(f,x0,tol)\n *    fixed-point iteration to solve f(x)=x.\n *    x0 = starting value.\n *    tol = convergence criteria, stops when |f(x)-x| < tol.\n *    Convergence requires |f'(x)|<1 in neighborhood of true solution;\n *      f'(x) \\approx 0 gives the fastest convergence.\n *    No stability checks at present.\n *\n *  TODO: additional error checking, non-convergence stop.\n */\n\n#include <math.h>\n#include <stdlib.h>\n\n#include \"mutil.h\"\n\ndouble solve_secant(f,c,xlo,xhi,tol,bd_flag,err)\ndouble (*f)(), c, xhi, xlo, tol;\nint bd_flag, *err;\n{ double ylo, yhi, x1, x2, x, y1, y2, y;\n  *err = 0;\n  ylo = f(xlo)-c;\n  yhi = f(xhi)-c;\n\n  switch(bd_flag)\n  { case BDF_EXPRIGHT:\n      while (yhi*ylo > 0)\n      { xhi += xhi-xlo;\n        yhi = f(xhi)-c;\n      }\n      break;\n    case BDF_EXPLEFT:\n      while (yhi*ylo > 0)\n      { xlo -= xhi-xlo;\n        ylo = f(xlo)-c;\n      }\n      break;\n    case BDF_NONE:\n    default:\n      if (yhi*ylo > 0)\n      { *err = 1;\n        return((xlo+xhi)/2);\n      }\n      break;\n  }\n\n  x1 = xlo; y1 = ylo;\n  x2 = xhi; y2 = yhi;\n\n  while (1)\n  { x = x2 + (x1-x2)*y2/(y2-y1);\n    if ((x<=xlo) | (x>=xhi)) x = (xlo+xhi)/2;\n    y = f(x)-c;\n    if (fabs(y) < tol) return(x);\n    if (y*ylo>0) { xlo = x; ylo = y; }\n            else { xhi = x; yhi = y; }\nif (y2==y)\n{ //printf(\"secant: y2 %12.9f\\n\",y2);\n  return(x);\n}\n    x1 = x2; y1 = y2;\n    x2 = x;  y2 = y;\n  }\n}\n\ndouble solve_nr(f,f1,c,x0,tol,err)\ndouble (*f)(), (*f1)(), c, x0, tol;\nint *err;\n{ double y;\n  do\n  { y = f(x0)-c;\n    x0 -= y/f1(x0);\n  } while (fabs(y)>tol);\n  return(x0);\n}\n\ndouble solve_fp(f,x0,tol,maxit)\ndouble (*f)(), x0, tol;\nint maxit;\n{ double x1;\n  int i;\n    x1 = 0;\n  for (i=0; i<maxit; i++)\n  { x1 = f(x0);\n    if (fabs(x1-x0)<tol) return(x1);\n    x0 = x1;\n  }\n  return(x1); /* although it hasn't converged */\n}\n"
  },
  {
    "path": "src/locfit/startlf.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *\n startlf(des,lf,vfun,nopc) -- starting point for locfit.\n des and lf are pointers to the design and fit structures.\n vfun is the vertex processing function.\n nopc=1 inhibits computation of parametric component.\n fitdefault(lf,n,d) -- fit default parameters.\n lf is pointer to fit; n and d are sample size and dimension.\n deschk()  -- assignment function for the design structure.\n preproc() -- fit preprocessing (limits, scales, paramcomp etc.)\n bbox()    -- compute bounding box.\n \n fitoptions()\n clocfit()  -- start point for CLocfit - interpret cmd line etc.\n */\n\n#include \"local.h\"\n\nextern INT cvi;\n\nvoid fitdefault(lf,n,d)\nlfit *lf;\nINT n, d;\n{ INT i, *mi;\n    double *dp;\n    \n    dp = lf->dp;\n    mi = lf->mi;\n    \n    mi[MTG] = TNUL;\n    mi[MTG] = (lf->y==NULL) ? TDEN : (64+TGAUS);\n    mi[MLINK] = LDEFAU;\n    mi[MACRI] = ANONE;\n    mi[MDEG] = mi[MDEG0] = 2;\n    mi[MEV] = (ident==1) ? EDATA : ETREE;\n    mi[MKT] = KSPH; mi[MKER] = WTCUB;\n    mi[MIT] = IDEFA; mi[MDC] = mi[MREN] = 0;\n    mi[MK] = 100; mi[MMINT] = 20;\n    mi[MMXIT] = 20;\n    mi[MN] = n; mi[MDIM] = d;\n    mi[MDEB] = 0;\n    mi[MUBAS] = 0;\n    \n    \n    dp[DALP] = 0.7; dp[DFXH] = dp[DADP] = 0.0;\n    dp[DCUT] = 0.8;\n    \n    if (d<=0)\n        ERROR((\"must set MDIM before calling fitdefault\"));\n    for (i=0; i<d; i++)\n    { lf->sca[i] = 1.0;\n        lf->xl[i] = lf->xl[i+d] = 0.0;\n        lf->fl[i] = lf->fl[i+d] = 0.0;\n    }\n}\n\nint des_reqd(n,p)\nINT n, p;\n{ \n    return (n*(p+5)+2*p*p+4*p + jac_reqd(p));\n}\nint des_reqi(INT n) { return(n); }\n\nvoid deschk(des,n,p)\ndesign *des;\nINT n, p;\n{ \n    double *z;\n    des->dw = checkvarlen(des->dw,des_reqd(n,p),\"_deswork\",VDOUBLE);\n    z = vdptr(des->dw);\n    des->X = z; z += n*p;\n    setzero(des->X, n*p);\n    \n    des->w = z; z += n;\n    setzero(des->w, n);\n    \n    des->res=z; z += n;\n    setzero(des->res, n);\n    \n    des->di =z; z += n;\n    setzero(des->di, n);\n    \n    des->th =z; z += n;\n    setzero(des->th, n);\n    \n    des->wd =z; z += n;\n    setzero(des->wd, n);\n    \n    des->V  =z; z += p*p;\n    setzero(des->V, p*p);\n    \n    des->P  =z; z += p*p;\n    setzero(des->P, p*p);\n    \n    des->f1 =z; z += p;\n    setzero(des->f1, p);\n    \n    des->ss =z; z += p;\n    setzero(des->ss, p);\n    \n    des->oc =z; z += p;\n    setzero(des->oc, p);\n    \n    des->cf =z; z += p;\n    setzero(des->cf, p);\n    \n    z = jac_alloc(&des->xtwx,p,z);\n    \n    des->index = checkvarlen(des->index,des_reqi(n),\"_desidx\",VINT);\n    des->ind = (INT *)vdptr(des->index);\n    des->n = n; \n    des->p = p;\n    des->xtwx.p = p;\n}\n\nvoid bbox(lf,bx)\nlfit *lf;\ndouble *bx;\n{ INT i, j, d, n;\n    double z, mx, mn;\n    d = lf->mi[MDIM]; n = lf->mi[MN];\n    for (i=0; i<d; i++)\n        if (bx[i]==bx[i+d])\n        { if (lf->sty[i]==STANGL)\n        { bx[i] = 0.0; bx[i+d] = 2*PI*lf->sca[i];\n        }\n        else\n        { mx = mn = datum(lf,i,0);\n            for (j=1; j<n; j++)\n            { mx = MAX(mx,datum(lf,i,j));\n                mn = MIN(mn,datum(lf,i,j));\n            }\n            if (lf->xl[i]<lf->xl[i+d]) /* user set xlim; maybe use them. */\n            { z = mx-mn;\n                if (mn-0.2*z < lf->xl[i]) mn = lf->xl[i];\n                if (mx+0.2*z > lf->xl[i+d]) mx = lf->xl[i+d];\n            }\n            bx[i] = mn;\n            bx[i+d] = mx;\n        }\n        }\n}\n\nvoid preproc(des,lf,nopc)\ndesign *des;\nlfit *lf;\nINT nopc;\n{ INT d, i, j, n;\n    double xb;\n    d = lf->mi[MDIM]; n = lf->mi[MN];\n    lf->mi[MLINK] = defaultlink(lf->mi[MLINK],lf->mi[MTG]);\n    if (!validlinks(lf->mi[MLINK],lf->mi[MTG]))\n    { ERROR((\"Invalid family/link combination\"));\n        return;\n    }\n    compparcomp(des,lf,nopc);\n    if (lf->w==NULL)\n        lf->dp[DSWT] = lf->mi[MN];\n    else\n    { lf->dp[DSWT] = 0;\n        for (i=0; i<lf->mi[MN]; i++) lf->dp[DSWT] += prwt(lf,i);\n    }\n    for (i=0; i<d; i++)\n        if (lf->sca[i]<=0) /* set automatic scales */\n        { if (lf->sty[i]==STANGL) lf->sca[i] = 1.0;\n        else\n        { xb = lf->sca[i] = 0.0;\n            for (j=0; j<n; j++) xb += datum(lf,i,j);\n            xb /= n;\n            for (j=0; j<n; j++) lf->sca[i] += SQR(datum(lf,i,j)-xb);\n            lf->sca[i] = sqrt(lf->sca[i]/(n-1));\n        }\n        }\n    bbox(lf,lf->fl);\n}\n\n#ifdef CVERSION\nextern void do_scbsim();\n#endif\n\nvoid startlf(des,lf,vfun,nopc)\ndesign *des;\nlfit *lf;\nINT (*vfun)(), nopc;\n{ \n    INT i, *mi;\n    des->vfun = vfun;\n    mi = lf->mi;\n    mi[MP] = calcp(mi,mi[MDEG]);\n    des->pref = 0;\n    cvi = -1; /* inhibit cross validation */\n    deschk(des,mi[MN],mi[MP]);\n    if (mi[MDEB]>0) printf(\"preprocess\\n\");\n        preproc(des,lf,nopc);\n        if (mi[MDEB]>0) printf(\"preprocess ok\\n\");\n            if (lf_error) return;\n    lf->ord = 0;\n    makecfn(des,lf);\n    if ((mi[MDIM]==1) && (lf->sty[0]!=STANGL))\n    { i = 1;\n        while ((i<mi[MN]) && (datum(lf,0,i)>=datum(lf,0,i-1))) i++;\n        lf->ord = (i==mi[MN]);\n    }\n    \n    if (mi[MDEB]>0) printf(\"call eval structure\\n\");\n        switch(mi[MEV])\n    { case EPHULL: triang_start(des,lf); break;\n        case EDATA:  dataf(des,lf); break;\n        case ECROS:  crossf(des,lf); break;\n        case EGRID:  gridf(des,lf); break;\n        case ETREE:  atree_start(des,lf); break;\n        case EKDCE:  mi[MKT] = KCE;\n        case EKDTR:  kdtre_start(des,lf); break;\n        case EPRES:  preset(des,lf); break;\n        case EXBAR:  xbarf(des,lf); break;\n        case ENONE:  lf->nv = lf->nce = 0;\n            return;\n#ifdef CVERSION\n        case 100: do_scbsim(des,lf); break;\n#endif\n        default: ERROR((\"startlf: Invalid evaluation structure\"));\n    }\n    \n    /* renormalize for family=density */\n    if ((mi[MREN]) && (mi[MTG]==TDEN)) dens_renorm(lf,des);\n        }\n\n#ifdef CVERSION\nextern lfit lf;\nextern design des;\nextern plots pl[];\nint curwin;\nvari *vb;\n\nINT nofit()\n{ if (lf.mi==NULL) return(1);\n    return(lf.mi[MEV]==ENULL);\n}\n\nvoid endfit()\n{ INT i;\n    for (i=0; i<MAXWIN; i++)\n        if (pl[i].track != NULL)\n        { curwin = i;\n            cmdint(pl[i].track);\n        }\n}\n\nINT drl(key,dv,mi)\nchar *key;\nINT *dv, *mi;\n{ INT i, nd;\n    nd = readilist(dv,key,0,mi[MDEG],0);\n    for (i=0; i<nd; i++)\n    { if ((dv[i]<1) | (dv[i]>mi[MDIM]))\n        ERROR((\"drl: Invalid derivatives %s\",key));\n        dv[i]--;\n    }\n    return(nd);\n}\n\nvoid fitoptions(lf,vc,re)\nlfit *lf;\nvari *vc;\nINT re;\n{ \n    INT d = 0, n, i, i0, i1, *mi;\n    char kc, *key;\n    vari *v;\n    \n    re &= (!nofit());\n    i0 = getarg(vc,\"formula\",1);\n    if ((!re) && (i0==0)) { ERROR((\"no formula\")); return; }\n    i1 = getarg(vc,\"data\",1);\n    if (i1>0) doreaddata(argval(vc,i1),(INT)0);\n    if (re)\n        recondat(0,&lf->mi[MN]);\n    else\n    { lf->base = lf->y = lf->c = lf->w = NULL;\n        lf->nd = 0;\n        strcpy(lf->yname,\"_NuLl\");\n        strcpy(lf->wname,\"_NuLl\");\n        strcpy(lf->bname,\"_NuLl\");\n        strcpy(lf->cname,\"_NuLl\");\n    }\n    if (i0>0) /* interpret formula */\n    { key = argval(vc,i0);\n        n = -1;\n        i0 = i1 = 0; d = 0;\n        while ((i0<strlen(key)) && (key[i0]!='~')) i0++;\n        if (key[i0] != '~') { ERROR((\"invalid formula %s\",key)); return; }\n        if (i0>0)\n        { key[i0] = '\\0';\n            lf->y = vdptr(findvar(key,1,&n));\n            strcpy(lf->yname,key);\n            key[i0] = '~';\n        }\n        i1 = i0 = i0+1;\n        while (i1<strlen(key))\n        { while ((i1<strlen(key)) && (key[i1]!='+')) i1++;\n            kc = key[i1]; key[i1] = '\\0';\n            lf->sty[d] = KPROD;\n            if (stm(&key[i0],\"left(\",5))\n            { lf->sty[d] = STLEFT;\n                i0 = i0+5; key[i1-1] = '\\0';\n            }\n            else if (stm(&key[i0],\"right(\",6))\n            { lf->sty[d] = STRIGH;\n                i0 = i0+6; key[i1-1] = '\\0';\n            }\n            else if (stm(&key[i0],\"ang(\",4))\n            { lf->sty[d] = STANGL;\n                i0 = i0+4; key[i1-1] = '\\0';\n            }\n            else if (stm(&key[i0],\"cpar(\",5))\n            { lf->sty[d] = STCPAR;\n                i0 = i0+5; key[i1-1] = '\\0';\n            }\n            dvari(lf,d) = vdptr(findvar(&key[i0],1,&n));\n            strcpy(lf->xname[d],&key[i0]);\n            if (lf->sty[d]!=KPROD) key[i1-1] = ')';\n            d++; key[i1] = kc;\n            i0 = i1 = i1+1;\n        }\n        fitdefault(lf,n,d);\n    }\n    mi = lf->mi;\n    \n    i = getarg(vc,\"weights\",1);\n    if (i>0)\n    { lf->w = vdptr(findvar(argval(vc,i),1,&mi[MN]));\n        strcpy(lf->wname,argval(vc,i));\n    }\n    i = getarg(vc,\"cens\",1);\n    if (i>0)\n    { lf->c = vdptr(findvar(argval(vc,i),1,&mi[MN]));\n        strcpy(lf->cname,argval(vc,i));\n    }\n    i = getarg(vc,\"base\",1);\n    if (i>0)\n    { lf->base = vdptr(findvar(argval(vc,i),1,&mi[MN]));\n        strcpy(lf->bname,argval(vc,i));\n    }\n    \n    i = getarg(vc,\"scale\",1);\n    if (i>0)\n    { if (argvalis(vc,i,\"T\"))\n        for (i=0; i<d; i++) lf->sca[i] = 0;\n    else if (argvalis(vc,i,\"F\"))\n        for (i=0; i<d; i++) lf->sca[i] = 1;\n    else\n        arvect(argval(vc,i),lf->sca,d,0);\n    }\n    \n    i = getarg(vc,\"vb\",0);\n    if (i>0)\n    { lf->dp[DALP] = -1;\n        vb = arbuild(argval(vc,i),0,strlen(argval(vc,i))-1,NULL,0,1);\n        setvarname(vb,\"_varband\");\n    }\n    else\n    { i = getarg(vc,\"alpha\",1);\n        if (i>0) arvect(argval(vc,i),&lf->dp[DALP],3,1);\n    }\n    \n    i = getarg(vc,\"deg\",1);\n    if (i>0)\n    { i =  readilist(&mi[MDEG0],argval(vc,i),1,2,0);\n        if (i==1) mi[MDEG] = mi[MDEG0];\n    }\n    \n    i = getarg(vc,\"family\",1);if (i>0) setstrval(mi,MTG,argval(vc,i));\n    i = getarg(vc,\"link\",1);  if (i>0) setstrval(mi,MLINK,argval(vc,i));\n    i = getarg(vc,\"ev\",1); \n    if (i>0)\n    { v = findvar(argval(vc,i),0,NULL);\n        if (v!=NULL)\n        { mi[MEV] = EPRES;\n            lf->xxev= v;\n            lf->nvm = v->n;\n        }\n        else\n            setstrval(mi,MEV,argval(vc,i));\n    }\n    i = getarg(vc,\"acri\",1);  if (i>0) setstrval(mi,MACRI,argval(vc,i));\n    \n    i = getarg(vc,\"mg\",1);\n    if (i>0) readilist(lf->mg,argval(vc,i),1,MXDIM,1);\n    \n    i = getarg(vc,\"kt\",1);   if (i>0) setstrval(mi,MKT, argval(vc,i));\n    i = getarg(vc,\"kern\",1); if (i>0) setstrval(mi,MKER,argval(vc,i));\n    i = getarg(vc,\"itype\",1);if (i>0) setstrval(mi,MIT, argval(vc,i));\n    \n    i = getarg(vc,\"cut\",1);\n    if (i>0) lf->dp[DCUT] = darith(argval(vc,i));\n    \n    i = getarg(vc,\"flim\",1);\n    if (i>0) arvect(argval(vc,i),lf->fl,2*d,2);\n    \n    i = getarg(vc,\"xlim\",1);\n    if (i>0) arvect(argval(vc,i),lf->xl,2*d,2);\n    \n    i = getarg(vc,\"deriv\",0);\n    if (i>0) lf->nd = drl(argval(vc,i),lf->deriv,lf->mi);\n    i = getarg(vc,\"dc\",1); if (i>0) mi[MDC] = getlogic(vc,i);\n    i = getarg(vc,\"maxk\",1); if (i>0) readilist(&mi[MK],argval(vc,i),1,1,0);\n    i = getarg(vc,\"mint\",1); if (i>0) readilist(&mi[MMINT],argval(vc,i),1,1,0);\n    i = getarg(vc,\"maxit\",1); if (i>0) readilist(&mi[MMXIT],argval(vc,i),1,1,0);\n    i = getarg(vc,\"renorm\",1);if (i>0) mi[MREN] = getlogic(vc,i);\n    i = getarg(vc,\"debug\",1); if (i>0) readilist(&mi[MDEB],argval(vc,i),1,1,0);\n}\n\nvoid clocfit(v,re)\nINT re;\nvari *v;\n{\n    lf.ord = 0;\n    lf.kap[0] = lf.kap[1] = lf.kap[2] = 0.0; lf.nk = 0;\n    fitoptions(&lf,v,re);\n    if (lf_error)\n    { if (lf.mi!=NULL) lf.mi[MEV] = ENULL;\n        return;\n    }\n    \n    \n    lf.nv = 0;\n    if (lf.mi[MDEG0]==lf.mi[MDEG])\n    { startlf(&des,&lf,procv,0);\n        if (!lf_error) ressumm(&lf,&des);\n    }\n    else\n        startlf(&des,&lf,procvvord,0);\n    if (lf_error)\n    { if (!re) lf.mi[MEV] = ENULL;\n        return;\n    }\n    \n    //printf(\"Evaluation structure %d, %d points.\\n\",lf.mi[MEV],lf.nv);\n    if (argarg(v,0) != NULL) dosavefit(&lf,argarg(v,0),\"wb\",(INT)0);\n    endfit();\n}\n\n#endif\n"
  },
  {
    "path": "src/locfit/strings.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *\n *  miscellaneous string handling functions.\n *  used mostly in arith (C version) and lfstr.c\n *\n *  stm(u,v,k)        do the first k components of u, v match?\n *  ct_match(z1,z2)   counts number of matching components.\n *  pmatch(z,strings,vals,n,def)\n *                    finds the best match for z among the strings;\n *                    returns corresponding component of vals.\n *                    n = no of strings; def = value if no match.\n *  matchrt(z,i,i2,op,cl)\n *  matchlf(z,i1,i,op,cl)\n *                    Parenthesis matching. If op='(' and cl=')', matchrt\n *                    searches z, starting at z[i]='(' and ending and z[i2],\n *                    for the closing ')', taking care of nesting.\n *                    matchlf does the reverse.\n *\n *  checkltor(z,i1,i2,c)\n *                    Checks the string z, left to right from z[i1] to z[i2]\n *                    but skipping parenthesized () and [] parts, for the\n *                    occurence of any character from c. If a match is found,\n *                    the index is returned. If no match is found, return -1.\n *\n *  checkrtol(z,i1,i2,c) Same as checkltor(), but searches right to left.\n *  strip(z)          replaces underscores in z by spaces.\n */\n\n#include \"local.h\"\n\n/* do the first k components of u, v match? */\nint stm(char *u, char *v, int k) { return((strncmp(u,v,k)==0)); }\n\nint ct_match(z1, z2)\nchar *z1, *z2;\n{ int ct = 0;\n  while (z1[ct]==z2[ct])\n  { if (z1[ct]=='\\0') return(ct+1);\n    ct++;\n  }\n  return(ct);\n}\n\nint pmatch(z, strings, vals, n, def)\nchar *z, **strings;\nint *vals, n, def;\n{ int i, ct, best, best_ct;\n  best = -1;\n  best_ct = 0;\n\n  for (i=0; i<n; i++)\n  { ct = ct_match(z,strings[i]);\n    if (ct==strlen(z)+1) return(vals[i]);\n    if (ct>best_ct) { best = i; best_ct = ct; }\n  }\n  if (best==-1) return(def);\n  return(vals[best]);\n}\n\nint matchrt(z,i,i2,op,cl)\nchar *z, op, cl;\nint i, i2;\n{ int k;\n  if (z[i] != op)\n  { ERROR((\"matchrt: wrong start character\"));\n    return(i);\n  }\n  k = 0;\n  while (1)\n  { if (z[i]==op) k++;\n    if (z[i]==cl) k--;\n    if (k==0) return(i);\n    i++;\n    if (i>i2)\n    { ERROR((\"matchrt: unbalanced %c%c: %s\",op,cl,z));\n      return(i);\n    }\n  }\n}\n\nint matchlf(z,i1,i,op,cl)\nchar *z, op, cl;\nint i, i1;\n{ int k;\n  if (z[i] != cl)\n  { ERROR((\"matchlf: wrong end character\"));\n    return(i);\n  }\n  k = 0;\n  while (1)\n  { if (z[i]==op) k--;\n    if (z[i]==cl) k++;\n    if (k==0) return(i);\n    i--;\n    if (i<i1)\n    { ERROR((\"matchlf: unbalanced %c%c: %s\",op,cl,z));\n      return(i);\n    }\n  }\n}\n\nint checkltor(z,i1,i2,c)\nchar *z, *c;\nint i1, i2;\n{ int i;\n  i = i1;\n  while (i<=i2)\n  {\n    if (strchr(c,z[i]) != NULL) return(i);\n    if (z[i]=='(') i = matchrt(z,i,i2,'(',')');\n    if (z[i]=='[') i = matchrt(z,i,i2,'[',']');\n    i++;\n    if (lf_error) return(-1);\n  }\n  return(-1);\n}\n\nint checkrtol(z,i1,i2,c)\nchar *z, *c;\nint i1, i2;\n{ int i;\n  i = i2;\n  while (i >= i1)\n  { if (strchr(c,z[i]) != NULL) return(i);\n    if (z[i]==')') i = matchlf(z,i1,i,'(',')');\n    if (z[i]==']') i = matchlf(z,i1,i,'[',']');\n    i--;\n    if (lf_error) return(-1);\n  }\n  return(-1);\n}\n\nvoid strip(z)\nchar *z;\n{ do { if (*z=='_') *z=' '; } while (*(++z)!='\\0');\n}\n"
  },
  {
    "path": "src/locfit/vari.cpp",
    "content": "/*\n *   Copyright (c) 1996-2000 Lucent Technologies.\n *   See README file for details.\n *\n *  Functions for handling locfit variables in the C version.\n */\n\nextern \"C\" \n{\n#include \"local.h\"\n}\n\n#include <errno.h>\n\n#include \"vari.hpp\"\n//#define MAXV 1000\n//#define LF_WORK 102400\n\n//static char *db = NULL;\n//static INT lfwptr, lf_work;\n//vari root;\n\n\n\n#include <map>\n#include <string>\n\nusing namespace std;\n\n\ntypedef map<string, vari*> VarTable;\nVarTable var_table;\n\nvoid cleardb()\n{\n    for (VarTable::iterator i = var_table.begin(); i != var_table.end(); ++i)\n    {\n        if (i->second && i->second->stat != STSYSPEC)\n        {\n            free(i->second->dpr);\n        }\n        free(i->second);\n    }\n    var_table.clear();\n}\n\nvoid initdb() /* initialize locfit's work space */\n{ \n    cleardb();\n    \n//    char *z = NULL;\n//    z = getenv(\"LFWORK\");\n//    if (z==NULL) lf_work = LF_WORK;\n//    else sscanf(z,\"%d\",&lf_work);\n//    lf_work <<= 10;\n//    if (db != NULL)\n//    {\n//        free(db);\n//        lfwptr = 0;\n//    }\n//    db = (char *)calloc(lf_work, 1);\n//    if (db == NULL)\n//    {\n//        fprintf(stderr, \"Error: Locfit working space could not be allocated!\\n\");\n//        fprintf(stderr, \"Error code %d\\n\", errno);\n//    }\n//    \n//    root.stat = STSYSTEM;\n//    root.mode = VVARI;\n//    root.dpr = (double *)db;\n//    lfwptr = root.bytes = MAXV*sizeof(vari);\n//    root.n = 0;\n}\n\n\nINT vbytes(int n, int mode)\n{ \n    switch(mode)\n    { \n        case VDOUBLE: return(n*sizeof(double));\n        case VINT:    return(n*sizeof(INT));\n        case VCHAR:   return(n);\n        case VARGL:   return(n*sizeof(carg));\n        case VPREP:   return(sizeof(pplot));\n        case VARC:    return(n*sizeof(arstruct));\n        case VVARI:   return(n*sizeof(vari));\n        case VXYZ:    return(n*sizeof(plxyz));\n    }\n    ERROR((\"unknown mode %d in vbytes\",mode));\n    return(0);\n}\n\n/* vdptr with NULL check */\ndouble *vdptr(vari* v)\n\n{\n    if (v==NULL) \n        return(NULL);\n    return(v->dpr);\n}\n\n/* return the i'th data item. Cyclic. */\ndouble vitem(vari* v, int i)\n{ \n    int index;\n    if ((v==NULL) || (vlength(v)==0)) \n        return(0.0);\n    index = i % vlength(v);\n    switch(v->mode)\n    { case VDOUBLE: return( vdptr(v)[index] );\n        case VINT:\n        { INT *z;\n            z = (INT *)vdptr(v);\n            return(z[index]);\n        }\n        case VCHAR:\n        { char *z;\n            z = (char *)vdptr(v);\n            return(z[index]);\n        }\n    }\n    ERROR((\"Invalid mode in vitem()\"));\n    return(0.0);\n}\n\nvoid vassn(vari* v, int i, double x)\n{ \n    vdptr(v)[i] = x;\n}\n\nvari *growvar(vari* vold, int n)\n{ \n    fprintf(stderr, \"Error: attempting to grow variable not supported\\n\");\n    return NULL;\n//    vari *vnew;\n//    int reqd_bytes;\n//    \n//    if (vold==NULL)\n//    { \n//        ERROR((\"growvar: NULL old\"));\n//        return(NULL);\n//    }\n//    \n//    reqd_bytes = vbytes(n, vmode(vold));\n//    if (reqd_bytes <= vold->bytes) \n//        return(vold);\n//    \n//    vnew = createvar(\"_grow\",vold->stat,n,vmode(vold));\n//    memcpy(vdptr(vnew),vdptr(vold),vbytes(vlength(vold),vmode(vold)));\n//    setvarname(vnew,vold->name);\n//    vlength(vnew) = vlength(vold);\n//    deletevar(vold);\n//    return(vnew);\n}\n\nvoid *viptr(vari* v, int i) /* return pointer to ith data item, take account of mode */\n{ switch(vmode(v))\n    { case VDOUBLE: return(&v->dpr[i]);\n        case VCHAR: return(&((char *)v->dpr)[i]);\n        case VARGL: return(&((carg *)v->dpr)[i]);\n        case VARC:  return(&((arstruct *)v->dpr)[i]);\n        case VVARI: return(&((vari *)v->dpr)[i]);\n        case VXYZ:  return(&((plxyz *)v->dpr)[i]);\n    }\n    ERROR((\"Unknown mode %d in viptr\",vmode(v)));\n    return(NULL);\n}\n\nvoid setvarname(vari* v, varname name)\n{ \n    if (strcmp(v->name,name)==0) \n        return;\n    deletename(name);\n    strcpy(v->name,name);\n}\n\n/*\n findvar finds the variable name.\n err=0, keep quiet if not found; 1 produce error message.\n *n returns length of variable (if initially>0, checks length)\n */\n\nvari *findvar(varname name, int err, int* n)\n{ \n    INT status;\n    vari *v;\n    \n    if (strcmp(name,\"_NuLl\")==0) return(NULL);\n    \n    VarTable::iterator i = var_table.find(name);\n    \n    if (i != var_table.end())\n    {\n        v = i->second;\n        if (v == NULL)\n        {\n            fprintf(stderr, \"Found variable named %s, but data is NULL\\n\", name);\n            return NULL;\n        }\n        status = v->stat;\n        if (status != STHIDDEN && status != STEMPTY)\n        {\n            if (n == NULL)\n                return v;\n            if (*n==-1) \n                *n = vlength(v);\n            if (*n==0 || *n==vlength(v)) \n                return(v);\n            if (err) \n                ERROR((\"Variable %s has wrong length\",name));\n        }\n    }\n\n    if (err) \n        ERROR((\"Variable %s not found\",name));\n    return NULL;\n}\n\nvoid deletevar(vari* v) /* delete variable, or top variable if NULL */\n{ \n    if (v == NULL)\n    {\n        fprintf(stderr, \"Error: attempting to clear entire table through NULL delete\\n\");\n        return;\n    }\n    \n    VarTable::iterator i = var_table.find(v->name);\n    if (i != var_table.end())\n    {   \n        if (i->second && i->second->stat != STSYSPEC)\n        {\n            free(i->second->dpr);\n        }\n        free(i->second);\n        var_table.erase(i);\n    }\n}\n\nvoid deleteifhidden(vari* v)\n{ \n    if (v==NULL) \n        return;\n    if (v->stat == STHIDDEN) deletevar(v);\n}\n\nvoid deletename(varname name) /* delete variable name, or top variable if NULL */\n{ \n    vari *v;\n    v = findvar(name,0,NULL);\n    if (v!=NULL) \n        deletevar(v);\n}\n\nvari *createvar(varname name, int status, int n, int mode)\n{\n    int bytes;\n    vari *v;\n    \n    /*\n     compute the length of the variable in bytes. some systems\n     mess up is this is not a multiple of 8.\n     */\n    bytes = vbytes(n,mode);\n    while ( (bytes & 8) > 0 ) bytes++;\n    \n    if (lf_error) \n        return(NULL);\n    \n    // Don't delete the hidden vars\n    if (status==STSYSTEM || status==STREGULAR || status==STPLOTVAR)\n        deletename(name);\n    \n    v = findvar(name,0,NULL);\n    if (v != NULL)\n    {\n        fprintf(stderr, \"Error: attempting to re-initialize still-live variable %s\\n\", name);\n    }\n    \n    pair<map<string, vari*>::iterator, bool> inserted;\n    string str_name = name;\n    pair<string, vari*> p;\n    p.first = str_name;\n    p.second = (vari*)calloc(1, sizeof(vari));\n    inserted = var_table.insert(p);\n    \n    v = inserted.first->second;\n    \n    strcpy(v->name,name);\n    vlength(v) = n;\n    v->stat = status;\n    v->bytes = bytes;\n    v->mode = mode;\n    if (status!=STSYSPEC)\n    { \n        v->dpr = (double*)calloc(bytes, 1);\n    }\n\n    return(v);\n}\n"
  },
  {
    "path": "src/locfit/vari.hpp",
    "content": "//\n//  vari.hpp\n//  cufflinks\n//\n//  Created by Cole Trapnell on 3/22/11.\n//  Copyright 2011 Cole Trapnell. All rights reserved.\n//\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n    void cleardb();\n    void initdb();\n    INT vbytes(int n, int mode);\n    void setvarname(vari* v, varname name);\n    double *vdptr(vari* v);\n    double vitem(vari* v, int i);\n    void vassn(vari* v, int i, double x);\n    vari *findvar(varname name, int err, int* n);\n    vari *growvar(vari* vold, int n);\n    void *viptr(vari* v, int i);\n    void setvarname(vari* v, varname name);\n    vari *findvar(varname name, int err, int* n);\n    \n    void deletevar(vari* v); /* delete variable, or top variable if NULL */\n    void deleteifhidden(vari* v);\n    vari *createvar(varname name, int status, int n, int mode);\n    void deletename(varname name);\n    \n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "src/locfit/wdiag.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n  Routines for computing weight diagrams.\n  wdiag(lf,des,lx,deg,ty,exp)\n  Must locfit() first, unless ker==WPARM and has par. comp.\n \n  also, vertex processing function procvhatm().\n\n  cwdiag() entry for CLOCFIT.\n */\n\n#include \"local.h\"\n\nstatic double *wd;\nextern double robscale;\nextern void unitvec();\n\nvoid nnresproj(lf,des,u,m,p,mi)\nlfit *lf;\ndesign *des;\ndouble *u;\nINT m, p, *mi;\n{ INT i, j;\n  double link[LLEN];\n  setzero(des->f1,p);\n  for (j=0; j<m; j++)\n  { stdlinks(link,lf,des->ind[j],des->th[j],robscale);\n    for (i=0; i<p; i++) des->f1[i] += link[ZDDLL]*d_xij(des,j,i)*u[j];\n  }\n  jacob_solve(&des->xtwx,des->f1);\n  for (i=0; i<m; i++)\n    u[i] -= innerprod(des->f1,d_xi(des,i),p)*des->w[i];\n}\n\nvoid wdexpand(l,n,ind,m)\ndouble *l;\nINT n, m, *ind;\n{ INT i, j, t;\n  double z;\n  for (j=m; j<n; j++) { l[j] = 0.0; ind[j] = -1; }\n  j = m-1;\n  while (j>=0)\n  { if (ind[j]==j) j--;\n    else\n    { i = ind[j];\n      z = l[j]; l[j] = l[i]; l[i] = z;\n      t = ind[j]; ind[j] = ind[i]; ind[i] = t;\n      if (ind[j]==-1) j--;\n    }\n  }\n\n/*  for (i=n-1; i>=0; i--)\n  { l[i] = ((j>=0) && (ind[j]==i)) ? l[j--] : 0.0; } */\n}\n\nINT wdiagp(lf,des,lx,deg,ty,exp)\nlfit *lf;\ndesign *des;\ndouble *lx;\nINT deg, ty, exp;\n{ INT i, j, p, *mi, *deriv, nd;\n  double *l1;\n  mi = lf->mi; p = des->p;\n  deriv = lf->deriv; nd = lf->nd;\n  fitfun(lf,des->xev,lf->pc.xbar,des->f1,deriv,nd);\n  if (exp)\n  { jacob_solve(&lf->pc.xtwx,des->f1);\n    for (i=0; i<mi[MN]; i++)\n      lx[i] = innerprod(des->f1,d_xi(des,i),p);\n    return(mi[MN]);\n  }\n  jacob_hsolve(&lf->pc.xtwx,des->f1);\n  for (i=0; i<p; i++) lx[i] = des->f1[i];\n\n  if (deg>=1)\n    for (i=0; i<mi[MDIM]; i++)\n    { deriv[nd] = i;\n      l1 = &lx[(i+1)*p];\n      fitfun(lf,des->xev,lf->pc.xbar,l1,deriv,nd+1);\n      jacob_hsolve(&lf->pc.xtwx,l1);\n    }\n\n  if (deg>=2)\n    for (i=0; i<mi[MDIM]; i++)\n    { deriv[nd] = i;\n      for (j=0; j<mi[MDIM]; j++)\n      { deriv[nd+1] = j;\n        l1 = &lx[(i*mi[MDIM]+j+mi[MDIM]+1)*p];\n        fitfun(lf,des->xev,lf->pc.xbar,l1,deriv,nd+2);\n        jacob_hsolve(&lf->pc.xtwx,l1);\n    } }\n  return(p);\n}\n\nINT wdiag(lf,des,lx,deg,ty,exp)\nlfit *lf;\ndesign *des;\ndouble *lx;\nINT deg, ty, exp;\n/* deg=0: l(x) only.\n   deg=1: l(x), l'(x) (approx/exact ? mi[MDC] );\n   deg=2: l(x), l'(x), l''(x);\n   ty = 1: e1 (X^T WVX)^{-1} X^T W        -- hat matrix\n   ty = 2: e1 (X^T WVX)^{-1} X^T WV^{1/2} -- scb's\n*/\n{ double w, *X, *lxd, *lxdd, wdd, wdw, *ulx, link[LLEN], h;\n  double dfx[MXDIM], hs[MXDIM];\n  INT i, ii, j, k, l, m, d, p, *mi, *deriv, nd;\n  if ((lf->mi[MKER]==WPARM) && (hasparcomp(lf)))\n    return(wdiagp(lf,des,lx,deg,ty,exp));\n  mi = lf->mi; h = des->h;\n  deriv = lf->deriv; nd = lf->nd;\n  wd = des->wd;\n  d = mi[MDIM]; p = des->p; X = d_x(des);\n  ulx = des->res;\n  m = des->n;\n  for (i=0; i<d; i++) hs[i] = h*lf->sca[i];\n  if (deg>0)\n  { lxd = &lx[m];\n    setzero(lxd,m*d);\n    if (deg>1)\n    { lxdd = &lxd[d*m];\n      setzero(lxdd,m*d*d);\n  } }\n  if (nd>0) fitfun(lf,des->xev,des->xev,des->f1,deriv,nd); /* c(0) */\n    else unitvec(des->f1,0,p);\n  jacob_solve(&des->xtwx,des->f1);   /* c(0) (X^TWX)^{-1} */\n  for (i=0; i<m; i++)\n  { ii = des->ind[i];\n    lx[i] = innerprod(des->f1,&X[i*p],p); /* c(0)(XTWX)^{-1}X^T */\n    if ((deg>0) && (mi[MDC]))\n    { wd[i] = Wd(des->di[ii]/h,mi[MKER]);\n      for (j=0; j<d; j++)\n      { dfx[j] = datum(lf,j,ii)-des->xev[j];\n        lxd[j*m+i] = lx[i]*des->w[i]*weightd(dfx[j],lf->sca[j],\n          d,mi[MKER],mi[MKT],h,lf->sty[j],des->di[ii]);\n             /* c(0) (XTWX)^{-1}XTW' */\n      }\n      if (deg>1)\n      { wdd = Wdd(des->di[ii]/h,mi[MKER]);\n        for (j=0; j<d; j++)\n          for (k=0; k<d; k++)\n          { w = (des->di[ii]==0) ? 0 : h/des->di[ii];\n            w = wdd * (des->xev[k]-datum(lf,k,ii)) * (des->xev[j]-datum(lf,j,ii))\n                  * w*w / (hs[k]*hs[k]*hs[j]*hs[j]);\n            if (j==k) w += wd[i]/(hs[j]*hs[j]);\n            lxdd[(j*d+k)*m+i] = lx[i]*w;\n              /* c(0)(XTWX)^{-1}XTW'' */\n          }\n      }\n    }\n    lx[i] *= des->w[i];\n  }\n  if ((deg==2) && (mi[MDC]))\n  { for (i=0; i<d; i++)\n    { deriv[nd] = i;\n      fitfun(lf,des->xev,des->xev,des->f1,deriv,nd+1);\n      for (k=0; k<m; k++)\n      { stdlinks(link,lf,des->ind[k],des->th[k],robscale);\n        for (j=0; j<p; j++)\n          des->f1[j] -= link[ZDDLL]*lxd[i*m+k]*X[k*p+j];\n        /* c'(x)-c(x)(XTWX)^{-1}XTW'X */\n      }\n      jacob_solve(&des->xtwx,des->f1); /* (...)(XTWX)^{-1} */\n      for (j=0; j<m; j++)\n        ulx[j] = innerprod(des->f1,&X[j*p],p); /* (...)XT */\n      for (j=0; j<d; j++)\n        for (k=0; k<m; k++)\n        { ii = des->ind[k];\n          dfx[j] = datum(lf,j,ii)-des->xev[j];\n          wdw = des->w[k]*weightd(dfx[j],lf->sca[j],d,mi[MKER],mi[MKT],h,\n            lf->sty[j],des->di[ii]);\n          lxdd[(i*d+j)*m+k] += ulx[k]*wdw;\n          lxdd[(j*d+i)*m+k] += ulx[k]*wdw;\n        }\n        /* + 2(c'-c(XTWX)^{-1}XTW'X)(XTWX)^{-1}XTW' */\n    }\n    for (j=0; j<d*d; j++) nnresproj(lf,des,&lxdd[j*m],m,p,mi);\n        /* * (I-X(XTWX)^{-1} XTW */\n  }\n  if (deg>0)\n  { if (mi[MDC]) for (j=0; j<d; j++) nnresproj(lf,des,&lxd[j*m],m,p,mi);\n             /* c(0)(XTWX)^{-1}XTW'(I-X(XTWX)^{-1}XTW) */\n    for (i=0; i<d; i++)\n    { deriv[nd]=i;\n      fitfun(lf,des->xev,des->xev,des->f1,deriv,nd+1);\n      jacob_solve(&des->xtwx,des->f1);\n      for (k=0; k<m; k++)\n        for (l=0; l<p; l++)\n          lxd[i*m+k] += des->f1[l]*X[k*p+l]*des->w[k];\n            /* add c'(0)(XTWX)^{-1}XTW */\n    }\n  }\n  if (deg==2)\n  { for (i=0; i<d; i++)\n    { deriv[nd]=i;\n      for (j=0; j<d; j++)\n      { deriv[nd+1]=j;\n        fitfun(lf,des->xev,des->xev,des->f1,deriv,nd+2);\n        jacob_solve(&des->xtwx,des->f1);\n        for (k=0; k<m; k++)\n          for (l=0; l<p; l++)\n            lxdd[(i*d+j)*m+k] += des->f1[l]*X[k*p+l]*des->w[k];\n        /* + c''(x)(XTWX)^{-1}XTW */\n      }\n    }\n  }\n  k = 1+d*(deg>0)+d*d*(deg==2);\n\n  if (exp) wdexpand(lx,mi[MN],des->ind,m);\n \n  if (ty==1) return(m);\n  for (i=0; i<m; i++)\n  { stdlinks(link,lf,des->ind[i],des->th[i],robscale);\n    link[ZDDLL] = sqrt(fabs(link[ZDDLL]));\n    for (j=0; j<k; j++) lx[j*m+i] *= link[ZDDLL];\n  }\n  return(m);\n}\n\nINT procvhatm(des,lf,v)\ndesign *des;\nlfit *lf;\nINT v;\n{ INT k = 0, n;\n  double *l;\n  n = (ident==0) ? lf->mi[MN] : des->p;\n  if ((lf->mi[MKER]!=WPARM) | (!hasparcomp(lf))) k = procvraw(des,lf,v);\n  l = (double *)viptr(lf->L,v*n);\n  wdiag(lf,des,l,(INT)0,(INT)1,1);\n  return(k);\n}\n\n#ifdef CVERSION\nextern lfit lf;\nextern design des;\n\nvoid cwdiag(v)\nvari *v;\n{ INT i;\n  vari *ve, *vr;\n  i = getarg(v,\"ev\",0);\n  if (i==0) ERROR((\"wdiag: no ev point\"));\n  fitoptions(&lf,v,0);\n  if (lf_error) return;\n  ve = varith(argval(v,i),\"wdev\",STPLOTVAR);\n  vr = createvar(\"wdres\",STHIDDEN,lf.mi[MN],VDOUBLE);\n  lf.xxev = ve;\n  lf.nv = lf.nvm = 1;\n  lf.L = vr;\n  lf.mi[MEV] = EPRES;\n  startlf(&des,&lf,procvhatm,1);\n  deletevar(ve);\n  saveresult(vr,argarg(v,0),STREGULAR);\n}\n\n#endif\n"
  },
  {
    "path": "src/locfit/weight.c",
    "content": "/*\n *   Copyright (c) 1996-2001 Lucent Technologies.\n *   See README file for details.\n *\n *\n *  Defines the weight functions and related quantities used\n *  in LOCFIT.\n */\n\n#include \"local.h\"\n\n\n/* The weight functions themselves.  Used everywhere. */\ndouble W(u,ker)\ndouble u;\nINT ker;\n{ u = fabs(u);\n  switch(ker)\n  { case WRECT: return((u>1) ? 0.0 : 1.0);\n    case WEPAN: return((u>1) ? 0.0 : 1-u*u);\n    case WBISQ: if (u>1) return(0.0);\n                u = 1-u*u; return(u*u);\n    case WTCUB: if (u>1) return(0.0);\n                u = 1-u*u*u; return(u*u*u);\n    case WTRWT: if (u>1) return(0.0);\n                u = 1-u*u; return(u*u*u);\n    case WQUQU: if (u>1) return(0.0);\n                u = 1-u*u; return(u*u*u*u);\n    case WTRIA: if (u>1) return(0.0);\n                return(1-u);\n    case W6CUB: if (u>1) return(0.0);\n                u = 1-u*u*u; u = u*u*u; return(u*u);\n    case WGAUS: return(exp(-SQR(GFACT*u)/2.0));\n    case WEXPL: return(exp(-EFACT*u));\n    case WMACL: return(1/((u+1.0e-100)*(u+1.0e-100)));\n    case WMINM: ERROR((\"WMINM in W\"));\n                return(0.0);\n    case WPARM: return(1.0);\n  }\n  return(0.0);\n}\n\nINT iscompact(ker)\nINT ker;\n{ if ((ker==WEXPL) | (ker==WGAUS) | (ker==WMACL) | (ker==WPARM)) return(0);\n  return(1);\n}\n\ndouble weightprod(lf,u,h)\nlfit *lf;\ndouble *u, h;\n{ INT i, ker;\n  double sc, w;\n  w = 1.0;\n  ker = lf->mi[MKER];\n  for (i=0; i<lf->mi[MDIM]; i++)\n  { sc = lf->sca[i];\n    switch(lf->sty[i])\n    { case STLEFT:\n        if (u[i]>0) return(0.0);\n        w *= W(-u[i]/(h*sc),ker);\n        break;\n      case STRIGH:\n        if (u[i]<0) return(0.0);\n        w *= W(u[i]/(h*sc),ker);\n        break;\n      case STANGL:\n        w *= W(2*fabs(sin(u[i]/(2*sc)))/h,ker);\n        break;\n      case STCPAR:\n        break;\n      default:\n        w *= W(fabs(u[i])/(h*sc),ker);\n    }\n    if (w==0.0) return(w);\n  }\n  return(w);\n}\n\ndouble weightsph(lf,u,h,hasdi,di)\nlfit *lf;\ndouble *u, h, di;\nINT hasdi;\n{ INT i;\n\n  if (!hasdi) di = rho(u,lf->sca,lf->mi[MDIM],lf->mi[MKT],lf->sty);\n\n  for (i=0; i<lf->mi[MDIM]; i++)\n  { if ((lf->sty[i]==STLEFT) && (u[i]>0.0)) return(0.0);\n    if ((lf->sty[i]==STRIGH) && (u[i]<0.0)) return(0.0);\n  }\n  if (h==0) return((di==0.0) ? 1.0 : 0.0);\n\n  return(W(di/h,lf->mi[MKER]));\n}\n\ndouble weight(lf,x,t,h,hasdi,di)\nlfit *lf;\ndouble *x, *t, h, di;\nINT hasdi;\n{ double u[MXDIM];\n  INT i;\n  for (i=0; i<lf->mi[MDIM]; i++) u[i] = (t==NULL) ? x[i] : x[i]-t[i];\n  switch(lf->mi[MKT])\n  { case KPROD: return(weightprod(lf,u,h));\n    case KSPH:  return(weightsph(lf,u,h,hasdi,di));\n  }\n  ERROR((\"weight: unknown kernel type %d\",lf->mi[MKT]));\n  return(1.0);\n}\n\ndouble sgn(x)\ndouble x;\n{ if (x>0) return(1.0);\n  if (x<0) return(-1.0);\n  return(0.0);\n}\n\ndouble WdW(u,ker) /* W'(u)/W(u) */\ndouble u;\nINT ker;\n{ double eps=1.0e-10;\n  if (ker==WGAUS) return(-GFACT*GFACT*u);\n  if (ker==WPARM) return(0.0);\n  if (fabs(u)>=1) return(0.0);\n  switch(ker)\n  { case WRECT: return(0.0);\n    case WTRIA: return(-sgn(u)/(1-fabs(u)+eps));\n    case WEPAN: return(-2*u/(1-u*u+eps));\n    case WBISQ: return(-4*u/(1-u*u+eps));\n    case WTRWT: return(-6*u/(1-u*u+eps));\n    case WTCUB: return(-9*sgn(u)*u*u/(1-u*u*fabs(u)+eps));\n    case WEXPL: return((u>0) ? -EFACT : EFACT);\n  }\n  ERROR((\"WdW: invalid kernel\"));\n  return(0.0);\n}\n\n/* deriv. weights .. spherical, product etc\n   u, sc, sty needed only in relevant direction\n   Acutally, returns (d/dx W(||x||/h) ) / W(.)\n*/\ndouble weightd(u,sc,d,ker,kt,h,sty,di)\ndouble u, sc, h, di;\nINT d, ker, kt, sty;\n{ if (sty==STANGL)\n  { if (kt==KPROD)\n      return(-WdW(2*sin(u/(2*sc)),ker)*cos(u/(2*sc))/(h*sc));\n    if (di==0.0) return(0.0);\n    return(-WdW(di/h,ker)*sin(u/sc)/(h*sc*di));\n  }\n  if (sty==STCPAR) return(0.0);\n  if (kt==KPROD)\n    return(-WdW(u/(h*sc),ker)/(h*sc));\n  if (di==0.0) return(0.0);\n  return(-WdW(di/h,ker)*u/(h*di*sc*sc));\n}\n\ndouble weightdd(u,sc,d,ker,kt,h,sty,di,i0,i1)\ndouble *u, *sc, h, di;\nINT d, ker, kt, *sty, i0, i1;\n{ double w;\n  w = 1;\n  if (kt==KPROD)\n  {\n    w = WdW(u[i0]/(h*sc[i0]),ker)*WdW(u[i1]/(h*sc[i1]),ker)/(h*h*sc[i0]*sc[i1]);\n  }\n  return(0.0);\n}\n\n/* Derivatives W'(u)/u.\n   Used in simult. conf. band computations,\n   and kernel density bandwidth selectors. */\ndouble Wd(u,ker)\ndouble u;\nINT ker;\n{ double v;\n  if (ker==WGAUS) return(-SQR(GFACT)*exp(-SQR(GFACT*u)/2));\n  if (ker==WPARM) return(0.0);\n  if (fabs(u)>1) return(0.0);\n  switch(ker)\n  { case WEPAN: return(-2.0);\n    case WBISQ: return(-4*(1-u*u));\n    case WTCUB: v = 1-u*u*u;\n                return(-9*v*v*u);\n    case WTRWT: v = 1-u*u;\n                return(-6*v*v);\n    default: ERROR((\"Invalid kernel %d in Wd\",ker));\n  }\n  return(0.0);\n}\n\n/* Second derivatives W''(u)-W'(u)/u.\n   used in simult. conf. band computations in >1 dimension. */\ndouble Wdd(u,ker)\ndouble u;\nINT ker;\n{ double v;\n  if (ker==WGAUS) return(SQR(u*GFACT*GFACT)*exp(-SQR(u*GFACT)/2));\n  if (ker==WPARM) return(0.0);\n  if (u>1) return(0.0);\n  switch(ker)\n  { case WBISQ: return(12*u*u);\n    case WTCUB: v = 1-u*u*u;\n                return(-9*u*v*v+54*u*u*u*u*v);\n    case WTRWT: return(24*u*u*(1-u*u));\n    default: ERROR((\"Invalid kernel %d in Wdd\",ker));\n  }\n  return(0.0);\n}\n\n/* int u1^j1..ud^jd W(u) du.\n   Used for local log-linear density estimation.\n   Assume all j_i are even.\n   Also in some bandwidth selection.\n*/\ndouble wint(d,j,nj,ker)\nINT d, *j, nj, ker;\n{ double I, z;\n  int k, dj;\n  dj = d;\n    I = 0.0;\n  for (k=0; k<nj; k++) dj += j[k];\n  switch(ker) /* int_0^1 u^(dj-1) W(u)du  */\n  { case WRECT: I = 1.0/dj; break;\n    case WEPAN: I = 2.0/(dj*(dj+2)); break;\n    case WBISQ: I = 8.0/(dj*(dj+2)*(dj+4)); break;\n    case WTCUB: I = 162.0/(dj*(dj+3)*(dj+6)*(dj+9)); break;\n    case WTRWT: I = 48.0/(dj*(dj+2)*(dj+4)*(dj+6)); break;\n    case WTRIA: I = 1.0/(dj*(dj+1)); break;\n    case WQUQU: I = 384.0/(dj*(dj+2)*(dj+4)*(dj+6)*(dj+8)); break;\n    case W6CUB: I = 524880.0/(dj*(dj+3)*(dj+6)*(dj+9)*(dj+12)*(dj+15)*(dj+18)); break;\n    case WGAUS: switch(d)\n                { case 1: I = S2PI/GFACT; break;\n                  case 2: I = 2*PI/(GFACT*GFACT); break;\n                  default: I = exp(d*log(S2PI/GFACT)); /* for nj=0 */\n                }\n                for (k=0; k<nj; k++) /* deliberate drop */\n                  switch(j[k])\n                  { case 4: I *= 3.0/(GFACT*GFACT);\n                    case 2: I /= GFACT*GFACT;\n                  }\n                return(I);\n    case WEXPL: I = factorial(dj-1)/ipower(EFACT,dj); break;\n    default: ERROR((\"Unknown kernel %d in exacint\",ker));\n  }\n  if ((d==1) && (nj==0)) return(2*I); /* common case quick */\n  z = (d-nj)*LOGPI/2-LGAMMA(dj/2.0);\n  for (k=0; k<nj; k++) z += LGAMMA((j[k]+1)/2.0);\n  return(2*I*exp(z));\n}\n\n/* taylor series expansion of weight function around x.\n   0 and 1 are common arguments, so are worth programming\n   as special cases.\n   Used in density estimation.\n*/\nINT wtaylor(f,x,ker)\ndouble *f, x;\nINT ker;\n{ double v;\n  switch(ker)\n  { case WRECT:\n      f[0] = 1.0;\n      return(1);\n    case WEPAN:\n      f[0] = 1-x*x; f[1] = -2*x; f[2] = -1;\n      return(3);\n    case WBISQ:\n      v = 1-x*x;\n      f[0] = v*v;   f[1] = -4*x*v; f[2] = 4-6*v;\n      f[3] = 4*x;   f[4] = 1;\n      return(5);\n    case WTCUB:\n      if (x==1.0)\n      { f[0] = f[1] = f[2] = 0; f[3] = -27; f[4] = -81; f[5] = -108;\n        f[6] = -81; f[7] = -36; f[8] = -9; f[9] = -1; return(10); }\n      if (x==0.0)\n      { f[1] = f[2] = f[4] = f[5] = f[7] = f[8] = 0;\n        f[0] = 1; f[3] = -3; f[6] = 3; f[9] = -1; return(10); }\n      v = 1-x*x*x;\n      f[0] = v*v*v; f[1] = -9*v*v*x*x; f[2] = x*v*(27-36*v);\n      f[3] = -27+v*(108-84*v);         f[4] = -3*x*x*(27-42*v);\n      f[5] = x*(-108+126*v);           f[6] = -81+84*v;\n      f[7] = -36*x*x; f[8] = -9*x;     f[9] = -1;\n      return(10);\n    case WTRWT:\n      v = 1-x*x;\n      f[0] = v*v*v; f[1] = -6*x*v*v; f[2] = v*(12-15*v);\n      f[3] = x*(20*v-8); f[4] = 15*v-12; f[5] = -6; f[6] = -1;\n      return(7);\n    case WTRIA:\n      f[0] = 1-x; f[1] = -1;\n      return(2);\n    case WQUQU:\n      v = 1-x*x;\n      f[0] = v*v*v*v; f[1] = -8*x*v*v*v; f[2] = v*v*(24-28*v);\n      f[3] = v*x*(56*v-32); f[4] = (70*v-80)*v+16; f[5] = x*(32-56*v);\n      f[6] = 24-28*v; f[7] = 8*x; f[8] = 1;\n      return(9);\n    case W6CUB:\n      v = 1-x*x*x;\n      f[0] = v*v*v*v*v*v;\n      f[1] = -18*x*x*v*v*v*v*v;\n      f[2] = x*v*v*v*v*(135-153*v);\n      f[3] = v*v*v*(-540+v*(1350-816*v));\n      f[4] = x*x*v*v*(1215-v*(4050-v*3060));\n      f[5] = x*v*(-1458+v*(9234+v*(-16254+v*8568)));\n      f[6] = 729-v*(10206-v*(35154-v*(44226-v*18564)));\n      f[7] = x*x*(4374-v*(30132-v*(56862-v*31824)));\n      f[8] = x*(12393-v*(61479-v*(92664-v*43758)));\n      f[9] = 21870-v*(89100-v*(115830-v*48620));\n      f[10]= x*x*(26730-v*(69498-v*43758));\n      f[11]= x*(23814-v*(55458-v*31824));\n      f[12]= 15849-v*(34398-v*18564);\n      f[13]= x*x*(7938-8568*v);\n      f[14]= x*(2970-3060*v);\n      f[15]= 810-816*v;\n      f[16]= 153*x*x;\n      f[17]= 18*x;\n      f[18]= 1;\n      return(19);\n  }\n  ERROR((\"Invalid kernel %d in wtaylor\",ker));\n  return(0);\n}\n\n/* convolution int W(x)W(x+v)dx.\n   used in kde bandwidth selection.\n*/\ndouble Wconv(v,ker)\ndouble v;\nINT ker;\n{ double v2;\n  switch(ker)\n  { case WGAUS: return(SQRPI/GFACT*exp(-SQR(GFACT*v)/4));\n    case WRECT:\n      v = fabs(v);\n      if (v>2) return(0.0);\n      return(2-v);\n    case WEPAN:\n      v = fabs(v);\n      if (v>2) return(0.0);\n      return((2-v)*(16+v*(8-v*(16-v*(2+v))))/30);\n    case WBISQ:\n      v = fabs(v);\n      if (v>2) return(0.0);\n      v2 = 2-v;\n      return(v2*v2*v2*v2*v2*(16+v*(40+v*(36+v*(10+v))))/630);\n  }\n  ERROR((\"Wconv not implemented for kernel %d\",ker));\n  return(0.0);\n}\n\n/* derivative of Wconv.\n   1/v d/dv int W(x)W(x+v)dx\n   used in kde bandwidth selection.\n*/\ndouble Wconv1(v,ker)\ndouble v;\nINT ker;\n{ double v2;\n  v = fabs(v);\n  switch(ker)\n  { case WGAUS: return(-0.5*SQRPI*GFACT*exp(-SQR(GFACT*v)/4));\n    case WRECT:\n      if (v>2) return(0.0);\n      return(1.0);\n    case WEPAN:\n      if (v>2) return(0.0);\n      return((-16+v*(12-v*v))/6);\n    case WBISQ:\n      if (v>2) return(0.0);\n      v2 = 2-v;\n      return(-v2*v2*v2*v2*(32+v*(64+v*(24+v*3)))/210);\n  }\n  ERROR((\"Wconv1 not implemented for kernel %d\",ker));\n  return(0.0);\n}\n\n/* 4th derivative of Wconv.\n   used in kde bandwidth selection (BCV, SJPI, GKK)\n*/\ndouble Wconv4(v,ker)\ndouble v;\nINT ker;\n{ double gv;\n  switch(ker)\n  { case WGAUS:\n      gv = GFACT*v;\n      return(exp(-SQR(gv)/4)*GFACT*GFACT*GFACT*(12-gv*gv*(12-gv*gv))*SQRPI/16);\n  }\n  ERROR((\"Wconv4 not implemented for kernel %d\",ker));\n  return(0.0);\n}\n\n/* 5th derivative of Wconv.\n   used in kde bandwidth selection (BCV method only)\n*/\ndouble Wconv5(v,ker) /* (d/dv)^5 int W(x)W(x+v)dx */\ndouble v;\nINT ker;\n{ double gv;\n  switch(ker)\n  { case WGAUS:\n      gv = GFACT*v;\n      return(-exp(-SQR(gv)/4)*GFACT*GFACT*GFACT*GFACT*gv*(60-gv*gv*(20-gv*gv))*SQRPI/32);\n  }\n  ERROR((\"Wconv5 not implemented for kernel %d\",ker));\n  return(0.0);\n}\n\n/* 6th derivative of Wconv.\n   used in kde bandwidth selection (SJPI)\n*/\ndouble Wconv6(v,ker)\ndouble v;\nINT ker;\n{ double gv, z;\n  switch(ker)\n  { case WGAUS:\n      gv = GFACT*v;\n      gv = gv*gv;\n      z = exp(-gv/4)*(-120+gv*(180-gv*(30-gv)))*0.02769459142;\n      gv = GFACT*GFACT;\n      return(z*gv*gv*GFACT);\n  }\n  ERROR((\"Wconv6 not implemented for kernel %d\",ker));\n  return(0.0);\n}\n\n/* int W(v)^2 dv / (int v^2 W(v) dv)^2\n   used in some bandwidth selectors\n*/\ndouble Wikk(ker,deg)\nINT ker, deg;\n{ switch(deg)\n  { case 0:\n    case 1: /* int W(v)^2 dv / (int v^2 W(v) dv)^2 */\n      switch(ker)\n      { case WRECT: return(4.5);\n        case WEPAN: return(15.0);\n        case WBISQ: return(35.0);\n        case WGAUS: return(0.2820947918*GFACT*GFACT*GFACT*GFACT*GFACT);\n        case WTCUB: return(34.15211105);\n        case WTRWT: return(66.08391608);\n      }\n    case 2:\n    case 3: /* 4!^2/8*int(W1^2)/int(v^4W1)^2\n               W1=W*(n4-v^2n2)/(n0n4-n2n2) */\n      switch(ker)\n      { case WRECT: return(11025.0);\n        case WEPAN: return(39690.0);\n        case WBISQ: return(110346.9231);\n        case WGAUS: return(14527.43412);\n        case WTCUB: return(126500.5904);\n        case WTRWT: return(254371.7647);\n      }\n  }\n  ERROR((\"Wikk not implemented for kernel %d\",ker));\n  return(0.0);\n}\n"
  },
  {
    "path": "src/matching_merge.cpp",
    "content": "/*\n *  matching_merge.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 6/1/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include \"matching_merge.h\"\n\nusing namespace std;\nusing namespace boost;\n\nvoid find_path(const DAG& bundle_dag,\n\t\t\t   const adjacency_list<>& TC,\n\t\t\t   const DAGNode& source,\n\t\t\t   const DAGNode& target,\n\t\t\t   vector<DAGNode>& path)\n{\n\tif (source == target)\n\t\treturn;\n\tbool done = false;\n\tDAGNode curr = source;\n\twhile(!done)\n\t{\n\t\tgraph_traits<DAG>::adjacency_iterator i, iend;\n\t\tfor (tie(i,iend) = adjacent_vertices(curr, bundle_dag); i != iend; ++i)\n\t\t{\n\t\t\tDAGNode I = *i;\n\t\t\tpair<adjacency_list<>::edge_descriptor, bool> p;\n\t\t\tp = edge(I, target, TC);\n\t\t\tif (p.second)\n\t\t\t{\n\t\t\t\tpath.push_back(*i);\n\t\t\t\tcurr = *i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (*i == target)\n\t\t\t{\n\t\t\t\tpath.push_back(*i);\n\t\t\t\tdone = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid extend_chains_to_paths(const DAG& bundle_dag,\n\t\t\t\t\t\t\tvector<vector<DAGNode> >& chains,\n\t\t\t\t\t\t\tadjacency_list<>& TC,\n\t\t\t\t\t\t\tDAGNode source,\n\t\t\t\t\t\t\tDAGNode sink,\n\t\t\t\t\t\t\tvector<vector<DAGNode> >& paths)\n{\t\n\t//Extend each chain to a path\n\tfor(size_t c = 0; c < chains.size(); ++c)\n\t{\n\t\tvector<DAGNode>& chain = chains[c];\n\t\tassert (!chain.empty());\n\t\treverse(chain.begin(), chain.end());\n\t\tvector<DAGNode> path;\n\t\tfind_path(bundle_dag, TC, source, chain[0], path);\n\t\tfor (size_t n = 1; n < chain.size(); ++n)\n\t\t{\n\t\t\tassert (path.back() == chain[n - 1]);\n\t\t\tDAGNode last = chain[n-1];\n\t\t\tDAGNode next = chain[n];\n\t\t\tfind_path(bundle_dag, TC, last, next, path);\n\t\t}\n\t\tfind_path(bundle_dag, TC, chain.back(), sink, path);\n\t\tassert (path.back() == sink);\n\t\tpath.pop_back();\n\t\tpaths.push_back(path);\n\t}\n}\n\nvoid make_scaffolds_from_paths(DAG& bundle_dag,\n\t\t\t\t\t\t\t   const vector<vector<DAGNode> >& paths,\n\t\t\t\t\t\t\t   vector<Scaffold>& scaffolds)\n{\n\tHitsForNodeMap hits_for_node = get(vertex_name, bundle_dag);\n\tfor (size_t p = 0; p < paths.size(); ++p)\n\t{\n\t\tconst vector<DAGNode>& path = paths[p];\n\t\t\n\t\tvector<Scaffold> path_alignments;\n\t\tfor (size_t m = 0; m < path.size(); ++m)\n\t\t{\n\t\t\t//fprintf(stderr, \"%d \", scaff_id);\n\t\t\tpath_alignments.push_back(*(hits_for_node[path[m]]));\n\t\t}\n\t\t//fprintf(stderr,\"\\n\");\n\t\t//fprintf(stderr, \"\\tMerging path %d into scaffold\\n\", p);\n\t\tScaffold s(path_alignments);\n\t\t\n\t\t//fprintf(stderr, \"PATH %d\\n-------------------------------------\\n\",s.get_id());\n\t\tscaffolds.push_back(s);\n\t}\n\tsort(scaffolds.begin(), scaffolds.end(), scaff_lt);\n}\n\n\n"
  },
  {
    "path": "src/matching_merge.h",
    "content": "#ifndef MATCHING_MERGE_H\n#define MATCHING_MERGE_H\n\n/*\n *  matching_merge.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 6/1/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <vector>\n\n//#include <lemon/topology.h>\n#include <lemon/smart_graph.h>\n#include <lemon/bipartite_matching.h>\n\n#include \"scaffold_graph.h\"\n#include \"scaffolds.h\"\n\nusing namespace std;\n\ntypedef lemon::SmartBpUGraph ReachGraph;\n\ntemplate<class Matcher>\nvoid make_chains_from_matching(const ReachGraph& bp, \n\t\t\t\t\t\t\t   const Matcher& matcher,\n\t\t\t\t\t\t\t   vector<vector<DAGNode> >& chains)\n{\n\t// Make chains out of the matching\n\tReachGraph::ANodeMap<ReachGraph::UEdge> matched_a_nodes(bp);\n\tmatcher.aMatching(matched_a_nodes);\n\t\n\tReachGraph::BNodeMap<ReachGraph::UEdge> matched_b_nodes(bp);\n\tmatcher.bMatching(matched_b_nodes);\n\t\n\tset<ReachGraph::ANode> chain_heads;\n\t\n\tfor (ReachGraph::ANodeIt i(bp); i!=lemon::INVALID; ++i)\n\t{\n\t\tint a_id = bp.aNodeId(i);\n\t\tReachGraph::ANode a = bp.nodeFromANodeId(a_id);\n\t\tif (matched_a_nodes[a] == lemon::INVALID)\n\t\t\tchain_heads.insert(bp.nodeFromANodeId(bp.aNodeId(i)));\n\t}\n\t\n\tfor (set<ReachGraph::ANode>::iterator i = chain_heads.begin();\n\t\t i != chain_heads.end();\n\t\t ++i)\n\t{\n\t\tvector<DAGNode> chain;\n\t\tReachGraph::ANode n = *i;\n\t\tchain.push_back(bp.aNodeId(*i));\n\t\twhile(true)\n\t\t{\n\t\t\t//int a_id = bp.aNodeId(n);\n\t\t\tint b_id = bp.bNodeId(n);\n\t\t\t\n\t\t\tReachGraph::BNode b = bp.nodeFromBNodeId(b_id);\n\t\t\t\n\t\t\tif (matched_b_nodes[b] == lemon::INVALID)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tReachGraph::ANode a_match_to_b = bp.source(matched_b_nodes[b]);\n\t\t\t\tchain.push_back(bp.aNodeId(a_match_to_b));\n\t\t\t\tn = a_match_to_b;\n\t\t\t}\n\t\t}\n\t\tchains.push_back(chain);\n\t}\n\tassert (chains.size() == chain_heads.size());\n}\n\ntemplate<class Matcher>\nvoid merge_from_matching(const ReachGraph& bp_graph,\n                         const Matcher& matcher,\n                         vector<Scaffold>& scaffolds)\n{\n    vector<Scaffold> merged_scaffolds;\n    \n    vector<vector<DAGNode> > chains;\n    \n    make_chains_from_matching(bp_graph, matcher, chains);\n    for (size_t i = 0; i < chains.size(); ++i)\n    {\n        vector<Scaffold> chain;\n        for (size_t j = 0; j < chains[i].size(); ++j)\n        {\n            chain.push_back(scaffolds[chains[i][j]]);\n        }\n        merged_scaffolds.push_back(Scaffold(chain));\n    }\n    \n    sort (merged_scaffolds.begin(), merged_scaffolds.end(), scaff_lt);\n    \n    scaffolds = merged_scaffolds;   \n}\n\nvoid extend_chains_to_paths(const DAG& bundle_dag,\n\t\t\t\t\t\t\tvector<vector<DAGNode> >& chains,\n\t\t\t\t\t\t\tboost::adjacency_list<>& TC,\n\t\t\t\t\t\t\tDAGNode source,\n\t\t\t\t\t\t\tDAGNode sink,\n\t\t\t\t\t\t\tvector<vector<DAGNode> >& paths);\n\nvoid make_scaffolds_from_paths(DAG& bundle_dag,\n\t\t\t\t\t\t\t   const vector<vector<DAGNode> >& paths,\n\t\t\t\t\t\t\t   vector<Scaffold>& scaffolds);\n#endif\n"
  },
  {
    "path": "src/multireads.cpp",
    "content": "/*\n *  multireads.cpp\n *  cufflinks\n *\n *  Created by Adam Roberts on 3/6/11.\n *  Copyright 2011 Adam Roberts. All rights reserved.\n *\n */\n\n\n#include \"hits.h\"\n#include \"multireads.h\"\n\nvoid MultiRead::add_hit(RefID r_id, int left, int right)\n{\n\t_hits.push_back(MultiHit(r_id, left, right));\n}\n\nMultiHit* MultiRead::get_hit(RefID r_id, int left, int right)\n{\n    for (size_t i = 0; i < num_hits(); ++i)\n\t{\n\t\tMultiHit& hit = _hits[_curr_index];\n\t\tif (hit.r_id == r_id && hit.left == left && hit.right == right)\n\t\t{\n\t\t\treturn &hit;\n        }\n\t\t_curr_index = (_curr_index + 1) % num_hits();\n\t}  \n    fprintf(stderr, \"\\nWARNING: Multi-Hit not found (%d,%d).\\n\", left, right); \n    return NULL;\n}\n\nvoid MultiRead::add_expr(RefID r_id, int left, int right, double expr)\n{\n\tMultiHit* hit = get_hit(r_id, left, right);\n    if (hit)\n    {\n        hit->expr += expr;\n        _tot_expr += expr;\n    }\n}\n\ndouble MultiRead::get_mass(RefID r_id, int left, int right, bool valid_mass)\n{\n\tif (!valid_mass)\n\t{\n\t\treturn 1.0/num_hits();\n\t}\n\t\n\tif (_tot_expr == 0.0)\n\t\treturn 0.0;\n\t\n\tMultiHit* hit = get_hit(r_id, left, right);\n    if (hit)\n        return hit->expr/_tot_expr;\n    else\n        return 1.0/num_hits();\n}\n\nMultiRead* MultiReadTable::get_read(InsertID mr_id)\n{\n\tMultiReadMap::iterator it;\n\tit = _read_map.find(mr_id);\n\tif (it == _read_map.end())\n\t{\n\t\treturn NULL;\n\t}\n\telse \n\t{\n\t\treturn &(it->second);\n\t}\n}\n\nvoid MultiReadTable::add_hit(const MateHit& hit)\n{\n\tadd_hit(hit.ref_id(), hit.left(), hit.right(), hit.insert_id(), hit.num_hits());\n}\n\nvoid MultiReadTable::add_hit(RefID r_id, int left, int right, InsertID mr_id, int exp_num_hits)\n{\n#if ENABLE_THREADS\n\tboost::mutex::scoped_lock lock(_lock);\n#endif\n\tMultiRead* mr = get_read(mr_id);\n\tif (!mr)\n\t{\n\t\tmr = &((_read_map.insert(std::make_pair(mr_id, MultiRead(mr_id, exp_num_hits)))).first->second); \n\t}\n\tmr->add_hit(r_id, left, right);\n}\n\nvoid MultiReadTable::add_expr(const MateHit& hit, double expr)\n{\n\tadd_expr(hit.ref_id(), hit.left(), hit.right(), hit.insert_id(), expr);\n}\n\nvoid MultiReadTable::add_expr(RefID r_id, int left, int right, InsertID mr_id, double expr)\n{\n#if ENABLE_THREADS\n\tboost::mutex::scoped_lock lock(_lock);\n#endif\n\tMultiRead* mr = get_read(mr_id);\n    if (mr)\n        mr->add_expr(r_id, left, right, expr);\n}\n\ndouble MultiReadTable::get_mass(const MateHit& hit)\n{\n#if ENABLE_THREADS\n\tboost::mutex::scoped_lock lock(_lock);\n#endif\t\n\tMultiRead* mr = get_read(hit.insert_id());\n\tif(!mr)\n\t\treturn 1.0;\n\treturn mr->get_mass(hit.ref_id(), hit.left(), hit.right(), _valid_mass);\n}\n\nsize_t MultiReadTable::num_multireads()\n{\n\treturn (int)_read_map.size();\n}\n\nsize_t MultiReadTable::num_multihits()\n{\n\tsize_t count = 0;\n\tfor (MultiReadMap::iterator it=_read_map.begin() ; it != _read_map.end(); it++ )\n\t{\n\t\tcount += it->second.num_hits();\n\t}\n\treturn count;\n}\n"
  },
  {
    "path": "src/multireads.h",
    "content": "#ifndef MULTIREADS_H\n#define MULTIREADS_H\n\n#include <boost/thread.hpp>\n\ntypedef uint64_t RefID;\ntypedef uint64_t InsertID;\n\nstruct MultiHit\n{\n    MultiHit(RefID id, int l, int r)\n    :   r_id(id),\n        left(l),\n        right(r),\n        expr(0) {}\n    RefID r_id;\n    int left;\n    int right;\n    double expr;\n};\n\nclass MultiRead\n{\n\tsize_t _curr_index;\n\tstd::vector<MultiHit> _hits;\n\tdouble _tot_expr;\n\tInsertID _id;\n    \n    MultiHit* get_hit(RefID r_id, int left, int right);\n\t\npublic:\n\t\n\tMultiRead(InsertID id, int exp_num_hits)\n\t:\t_curr_index(0),\n\t\t_tot_expr(0.0),\n\t\t_id(id)\n\t{\n\t\t_hits.reserve(exp_num_hits);\n\t}\n\t\n\tsize_t num_hits() { return (int)_hits.size(); }\n\tvoid add_hit(RefID r_id, int left, int right);\n\tvoid add_expr(RefID r_id, int left, int right, double expr);\n\tdouble get_mass(RefID r_id, int left, int right, bool valid_mass);\n};\n\nclass MateHit;\n\nclass MultiReadTable\n{\n\ttypedef std::map<InsertID, MultiRead> MultiReadMap;\n\tMultiReadMap _read_map;\n\tbool _valid_mass;\n\tMultiRead* get_read(InsertID mr_id);\n#if ENABLE_THREADS\n\tboost::mutex _lock;\n#endif\npublic:\n\tMultiReadTable(): _valid_mass(false) {}\n\t\n\tvoid valid_mass(bool vm) { _valid_mass = vm; }\n\tvoid add_hit(const MateHit& hit);\n\tvoid add_hit(RefID r_id, int left, int right, InsertID mr_id, int exp_num_hits);\n\tvoid add_expr(const MateHit& hit, double expr);\n\tvoid add_expr(RefID r_id, int left, int right, InsertID mr_id, double expr);\n\tdouble get_mass(const MateHit& hit);\n\tsize_t num_multireads();\n\tsize_t num_multihits();\n\t\n};\n\n#endif\n"
  },
  {
    "path": "src/negative_binomial_distribution.h",
    "content": "/* boost random/negative_binomial_distribution.hpp header file\n *\n * Copyright Steven Watanabe 2010\n * Distributed under the Boost Software License, Version 1.0. (See\n * accompanying file LICENSE_1_0.txt or copy at\n * http://www.boost.org/LICENSE_1_0.txt)\n *\n * See http://www.boost.org for most recent version including documentation.\n *\n * $Id: negative_binomial_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $\n */\n\n#ifndef NEGATIVE_BINOMIAL_DIST_H\n#define NEGATIVE_BINOMIAL_DIST_H\n\n#include <iosfwd>\n\n#include <boost/limits.hpp>\n#include <boost/random/detail/config.hpp>\n#include <boost/random/gamma_distribution.hpp>\n#include <boost/random/poisson_distribution.hpp>\n//\n//namespace boost {\n//namespace random {\n\n/**\n * The negative binomial distribution is an integer valued\n * distribution with two parameters, @c k and @c p.  The\n * distribution produces non-negative values.\n *\n * The distribution function is\n * \\f$\\displaystyle P(i) = {k+i-1\\choose i}p^k(1-p)^i\\f$.\n *\n * This implementation uses a gamma-poisson mixture.\n */\ntemplate<class IntType = int, class RealType = double>\nclass negative_binomial_distribution {\npublic:\n    typedef IntType result_type;\n    typedef RealType input_type;\n\n    class param_type {\n    public:\n        typedef negative_binomial_distribution distribution_type;\n        /**\n         * Construct a param_type object.  @c k and @c p\n         * are the parameters of the distribution.\n         *\n         * Requires: k >=0 && 0 <= p <= 1\n         */\n        explicit param_type(RealType k_arg = 1, RealType p_arg = RealType (0.5))\n          : _k(k_arg), _p(p_arg)\n        {}\n        /** Returns the @c k parameter of the distribution. */\n        RealType k() const { return _k; }\n        /** Returns the @c p parameter of the distribution. */\n        RealType p() const { return _p; }\n#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS\n        /** Writes the parameters of the distribution to a @c std::ostream. */\n        template<class CharT, class Traits>\n        friend std::basic_ostream<CharT,Traits>&\n        operator<<(std::basic_ostream<CharT,Traits>& os,\n                   const param_type& parm)\n        {\n            os << parm._p << \" \" << parm._k;\n            return os;\n        }\n    \n        /** Reads the parameters of the distribution from a @c std::istream. */\n        template<class CharT, class Traits>\n        friend std::basic_istream<CharT,Traits>&\n        operator>>(std::basic_istream<CharT,Traits>& is, param_type& parm)\n        {\n            is >> parm._p >> std::ws >> parm._k;\n            return is;\n        }\n#endif\n        /** Returns true if the parameters have the same values. */\n        friend bool operator==(const param_type& lhs, const param_type& rhs)\n        {\n            return lhs._k == rhs._k && lhs._p == rhs._p;\n        }\n        /** Returns true if the parameters have different values. */\n        friend bool operator!=(const param_type& lhs, const param_type& rhs)\n        {\n            return !(lhs == rhs);\n        }\n    private:\n        RealType _k;\n        RealType _p;\n    };\n    \n    /**\n     * Construct a @c negative_binomial_distribution object. @c k and @c p\n     * are the parameters of the distribution.\n     *\n     * Requires: k >=0 && 0 <= p <= 1\n     */\n    explicit negative_binomial_distribution(RealType k_arg = 1,\n                                            RealType p_arg = RealType(0.5))\n      : _k(k_arg), _p(p_arg)\n    {}\n    \n    /**\n     * Construct an @c negative_binomial_distribution object from the\n     * parameters.\n     */\n    explicit negative_binomial_distribution(const param_type& parm)\n      : _k(parm.k()), _p(parm.p())\n    {}\n    \n    /**\n     * Returns a random variate distributed according to the\n     * negative binomial distribution.\n     */\n    template<class URNG>\n    IntType operator()(URNG& urng) const\n    {\n        boost::random::gamma_distribution<RealType> gamma(_k, (1-_p)/_p);\n        double lambda = gamma(urng);\n        if (lambda <= 0)\n            return 0;\n        boost::random::poisson_distribution<IntType, RealType> poisson(lambda);\n        return poisson(urng);\n    }\n    \n    /**\n     * Returns a random variate distributed according to the negative\n     * binomial distribution with parameters specified by @c param.\n     */\n    template<class URNG>\n    IntType operator()(URNG& urng, const param_type& parm) const\n    {\n        return negative_binomial_distribution(parm)(urng);\n    }\n\n    /** Returns the @c k parameter of the distribution. */\n    RealType k() const { return _k; }\n    /** Returns the @c p parameter of the distribution. */\n    RealType p() const { return _p; }\n\n    /** Returns the smallest value that the distribution can produce. */\n    IntType min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return 0; }\n    /** Returns the largest value that the distribution can produce. */\n    IntType max BOOST_PREVENT_MACRO_SUBSTITUTION() const\n    { return (std::numeric_limits<IntType>::max)(); }\n\n    /** Returns the parameters of the distribution. */\n    param_type param() const { return param_type(_k, _p); }\n    /** Sets parameters of the distribution. */\n    void param(const param_type& parm)\n    {\n        _k = parm.k();\n        _p = parm.p();\n    }\n\n    /**\n     * Effects: Subsequent uses of the distribution do not depend\n     * on values produced by any engine prior to invoking reset.\n     */\n    void reset() { }\n\n#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS\n    /** Writes the parameters of the distribution to a @c std::ostream. */\n    template<class CharT, class Traits>\n    friend std::basic_ostream<CharT,Traits>&\n    operator<<(std::basic_ostream<CharT,Traits>& os,\n               const negative_binomial_distribution& bd)\n    {\n        os << bd.param();\n        return os;\n    }\n    \n    /** Reads the parameters of the distribution from a @c std::istream. */\n    template<class CharT, class Traits>\n    friend std::basic_istream<CharT,Traits>&\n    operator>>(std::basic_istream<CharT,Traits>& is,\n               negative_binomial_distribution& bd)\n    {\n        bd.read(is);\n        return is;\n    }\n#endif\n\n    /** Returns true if the two distributions will produce the same\n        sequence of values, given equal generators. */\n    friend bool operator==(const negative_binomial_distribution& lhs,\n                           const negative_binomial_distribution& rhs)\n    {\n        return lhs._k == rhs._k && lhs._p == rhs._p;\n    }\n    /** Returns true if the two distributions could produce different\n        sequences of values, given equal generators. */\n    friend bool operator!=(const negative_binomial_distribution& lhs,\n                           const negative_binomial_distribution& rhs)\n    {\n        return !(lhs == rhs);\n    }\n\nprivate:\n\n    /// @cond \\show_private\n\n    template<class CharT, class Traits>\n    void read(std::basic_istream<CharT, Traits>& is) {\n        param_type parm;\n        if(is >> parm) {\n            param(parm);\n        }\n    }\n\n    // parameters\n    RealType _k;\n    RealType _p;\n\n    /// @endcond\n};\n\n//}\n//\n//}\n\n#endif\n"
  },
  {
    "path": "src/progressbar.h",
    "content": "#ifndef PROGRESS_H\n#define PROGRESS_H\n\n#include \"time.h\"\n\nusing namespace std;\n\nconst int BAR_BUF_SIZE = 28;\nconst char SYMBOL = '*';\n\nclass ProgressBar\n{\n\tchar _bar_buf[BAR_BUF_SIZE];\n\tstring _process;\n\tlong double _num_complete;\n\tlong double _tot_num;\n\tint _num_updates;\n\tint _num_remaining;\n\t\npublic:\n\tProgressBar() {}\n\t\n\tProgressBar(string process, double tot_num) \n\t{ \n\t\t_tot_num = tot_num;\n\t\t_process = process;\n\t\t_num_complete = -1.0;\n\t\t_num_remaining = -1.0;\n\t\t_num_updates = 0;\n\t\t\n\t\tfor(int i=0; i < BAR_BUF_SIZE; ++i) _bar_buf[i] = ' ';\n\t\t_bar_buf[0] = '[';\n\t\t_bar_buf[BAR_BUF_SIZE-2] = ']';\n\t\t_bar_buf[BAR_BUF_SIZE-1] = '\\0';\n\t\t\n\t\t\n\t\ttime_t rawtime;\n  \t\tstruct tm * timeinfo;\n  \t\tchar time_buf [80];\n\n  \t\ttime ( &rawtime );\n  \t\ttimeinfo = localtime ( &rawtime );\n\t\t\n\t\tstrftime (time_buf,80,\"%H:%M:%S\",timeinfo);\n\n\t\tfprintf(stderr, \"[%s] %s\\n\", time_buf, _process.c_str());\n\t}\n\t\n\tvoid update(const char* bundle_label_buf, double inc_amt)\n\t{\n\t\t\n\t\t_num_complete += inc_amt;\n\t\t_num_updates ++;\n\t\t\n\t\tif (cuff_verbose||cuff_quiet||_tot_num==0) return;\n\n\t\tchar bundle_buf[28];\n\t\tbundle_buf[27] = '\\0';\n\t\tstrncpy(bundle_buf, bundle_label_buf, 27);\n\t\t\n\t\tint percent = (_num_complete * 100)/_tot_num;\n\n\t\tpercent = min(percent, 99);\n\t\t\n\t\tint last_bar = percent/(100/(BAR_BUF_SIZE-3));\n\t\tfor (int i=1; i <= last_bar; ++i)\n\t\t\t_bar_buf[i] = SYMBOL;\n\t\t\n\t\tchar line_buf[82];\n\t\tsnprintf(line_buf, 82, \"\\r> Processing Locus %-27s %s %3d%%\", bundle_buf, _bar_buf, percent);\n\t\t\n\t\tfprintf(stderr,\"%s\",line_buf);\n\t}\n\t\n\tvoid remaining(int num_remaining)\n\t{\n\t\tif (cuff_verbose||cuff_quiet||_tot_num==0||num_remaining==_num_remaining) return;\n\t\t\n\t\t_num_remaining = num_remaining;\n\t\t\n\t\tint percent = (_num_complete * 100)/_tot_num;\n\t\tpercent = min(percent, 99);\n\t\t\n\t\tchar msg_buff[45];\n\t\tsprintf(msg_buff, \"Waiting for %d threads to complete.\", num_remaining);\n\t\t\n\t\tint last_bar = percent/(100/(BAR_BUF_SIZE-3));\n\t\tfor (int i=1; i <= last_bar; ++i)\n\t\t\t_bar_buf[i] = SYMBOL;\n\t\t\n\t\tchar line_buf[82];\n\t\tsnprintf(line_buf, 81, \"\\r> %-44s %s %3d%%\", msg_buff, _bar_buf, percent);\n\t\t\n\t\tfprintf(stderr,\"%s\",line_buf);\n\t}\n\t\n\tvoid complete()\n\t{\n\t\tfor (int i=1; i < BAR_BUF_SIZE-2; ++i)\n\t\t\t_bar_buf[i] = SYMBOL;\n\t\tchar complete_buf[45];\n\t\tsnprintf(complete_buf, 44, \"Processed %d loci.\", _num_updates); \n\t\tif (cuff_verbose||cuff_quiet)\n\t\t\tfprintf(stderr, \"%-44s\\n\", complete_buf);\n\t\telse\n\t\t\tfprintf(stderr, \"\\r> %-44s %s %3d%%\\n\", complete_buf, _bar_buf, 100);\n\t}\n};\n\n#endif\n"
  },
  {
    "path": "src/replicates.cpp",
    "content": "//\n//  replicates.cpp\n//  cufflinks\n//\n//  Created by Cole Trapnell on 3/11/11.\n//  Copyright 2011 Cole Trapnell. All rights reserved.\n//\n\n#include <boost/thread.hpp>\n\nextern \"C\" {\n#include \"locfit/local.h\"\n}\n\n#include <boost/random/gamma_distribution.hpp>\n#include <boost/random/poisson_distribution.hpp>\n\n#include \"replicates.h\"\n//#include \"rounding.h\"\n\n#if ENABLE_THREADS\t\nboost::mutex _locfit_lock;\n#endif\n\nMassDispersionModel::MassDispersionModel(const std::string& name,\n                                         const std::vector<double>& scaled_compatible_mass_means, \n                                         const std::vector<double>& scaled_compatible_variances,\n                                         const std::vector<double>& scaled_mass_variances) \n{\n    _name = name;\n    \n    if (scaled_compatible_mass_means.size() != scaled_mass_variances.size())\n    {\n        fprintf (stderr, \"Error: dispersion model table is malformed\\n\");\n    }\n    \n    double last_val = 0;\n    for (size_t i = 0; i < scaled_compatible_mass_means.size(); i++)\n    {\n        \n        if (last_val > scaled_compatible_mass_means[i])\n        {\n            fprintf (stderr, \"Error: DispersionModel input is malformed\\n\");\n        }\n        \n        if ( i == 0 || last_val < scaled_compatible_mass_means[i])\n        {\n            _scaled_compatible_mass_means.push_back(scaled_compatible_mass_means[i]);\n            _scaled_compatible_variances.push_back(scaled_compatible_variances[i]);\n            _scaled_mass_variances.push_back(scaled_mass_variances[i]);\n        }\n        else\n        {\n            // skip this element if it's equal to what we've already seen\n        }\n        \n        last_val = scaled_compatible_mass_means[i];\n    }\n}\n\ndouble MassDispersionModel::scale_mass_variance(double scaled_mass) const \n{\n    if (scaled_mass <= 0)\n        return 0.0;\n    \n    if (_scaled_compatible_mass_means.size() < 2 || _scaled_mass_variances.size() < 2)\n    {\n        return scaled_mass; // revert to poisson.\n    }\n    if (scaled_mass > _scaled_compatible_mass_means.back())\n    {\n        // extrapolate to the right\n        // off the right end\n        double x1_mean = _scaled_compatible_mass_means[_scaled_compatible_mass_means.size()-2];\n        double x2_mean = _scaled_compatible_mass_means[_scaled_compatible_mass_means.size()-1];\n        \n        double y1_var = _scaled_mass_variances[_scaled_compatible_mass_means.size()-2];\n        double y2_var = _scaled_mass_variances[_scaled_compatible_mass_means.size()-1];\n        double slope = 0.0;                \n        if (x2_mean != x1_mean)\n        {\n            slope = (y2_var - y1_var) / (x2_mean-x1_mean);\n        }\n        else if (y1_var == y2_var)\n        {\n            assert (false); // should have a unique'd table\n        }\n        double mean_interp = _scaled_mass_variances[_scaled_compatible_mass_means.size()-1] -\n        slope*(scaled_mass - _scaled_compatible_mass_means.size()-1);\n        if (mean_interp < scaled_mass)\n            mean_interp = scaled_mass;\n        assert (!isnan(mean_interp) && !isinf(mean_interp));\n        return mean_interp;\n    }\n    else if (scaled_mass < _scaled_compatible_mass_means.front())\n    {\n        // extrapolate to the left\n        // off the left end?\n        double x1_mean = _scaled_compatible_mass_means[0];\n        double x2_mean = _scaled_compatible_mass_means[1];\n        \n        double y1_var = _scaled_mass_variances[0];\n        double y2_var = _scaled_mass_variances[1];\n        double slope = 0.0;                \n        if (x2_mean != x1_mean)\n        {\n            slope = (y2_var - y1_var) / (x2_mean-x1_mean);\n        }\n        else if (y1_var == y2_var)\n        {\n            assert (false); // should have a unique'd table\n        }\n        double mean_interp = _scaled_mass_variances[0] - slope*(_scaled_compatible_mass_means[0] - scaled_mass);\n        if (mean_interp < scaled_mass)\n            mean_interp = scaled_mass;\n\n        assert (!isnan(mean_interp) && !isinf(mean_interp));\n        return mean_interp;\n    }\n    \n    vector<double>::const_iterator lb;\n    lb = lower_bound(_scaled_compatible_mass_means.begin(), \n                     _scaled_compatible_mass_means.end(), \n                     scaled_mass);\n    if (lb < _scaled_compatible_mass_means.end())\n    {\n        int d = lb - _scaled_compatible_mass_means.begin();\n        if (*lb == scaled_mass || lb == _scaled_compatible_mass_means.begin())\n        {\n            double var = _scaled_mass_variances[d];\n            if (var < scaled_mass) // revert to poisson if underdispersed\n                var = scaled_mass;\n            assert (!isnan(var) && !isinf(var));\n            return var;\n        }\n        \n        \n        //in between two points on the scale.\n        d--;\n        \n        if (d < 0)\n        {\n            fprintf(stderr, \"ARG d < 0, d = %d \\n\", d);\n        }\n        \n        if (d >= _scaled_compatible_mass_means.size())\n        {\n            fprintf(stderr, \"ARG d >= _scaled_compatible_mass_means.size(), d = %d\\n\", d);\n        }\n        if (d >= _scaled_mass_variances.size())\n        {\n            fprintf(stderr, \"ARG d >= _scaled_mass_variances.size(), d = %d\\n\", d);\n        }\n        \n        double x1_mean = _scaled_compatible_mass_means[d];\n        double x2_mean = _scaled_compatible_mass_means[d + 1];\n        \n        double y1_var = _scaled_mass_variances[d];\n        double y2_var = _scaled_mass_variances[d + 1];\n        double slope = 0.0;                \n        if (x2_mean != x1_mean)\n        {\n            slope = (y2_var - y1_var) / (x2_mean-x1_mean);\n        }\n        else if (y1_var == y2_var)\n        {\n            assert (false); // should have a unique'd table\n        }\n        double mean_interp = _scaled_mass_variances[d] + slope*(scaled_mass - _scaled_compatible_mass_means[d]);\n        if (mean_interp < scaled_mass) // revert to poisson if underdispersed\n            mean_interp = scaled_mass;\n \n        assert (!isnan(mean_interp) && !isinf(mean_interp));\n        return mean_interp;\n    }\n    else\n    {\n        assert (!isnan(scaled_mass) && !isinf(scaled_mass));\n        return scaled_mass; // revert to poisson assumption\n    }\n}\n\n\nMleErrorModel::MleErrorModel(const std::string& name,\n                             const std::vector<double>& scaled_compatible_mass_means,\n                             const std::vector<double>& scaled_mle_variances)\n{\n    _name = name;\n    \n    if (scaled_compatible_mass_means.size() != scaled_mle_variances.size())\n    {\n        fprintf (stderr, \"Error: dispersion model table is malformed\\n\");\n    }\n    \n    double last_val = 0;\n    for (size_t i = 0; i < scaled_compatible_mass_means.size(); i++)\n    {\n        \n        if (last_val > scaled_compatible_mass_means[i])\n        {\n            fprintf (stderr, \"Error: MLEError input is malformed\\n\");\n        }\n        \n        if ( i == 0 || last_val < scaled_compatible_mass_means[i])\n        {\n            _scaled_compatible_mass_means.push_back(scaled_compatible_mass_means[i]);\n            _scaled_mle_variances.push_back(scaled_mle_variances[i]);\n        }\n        else\n        {\n            // skip this element if it's equal to what we've already seen\n        }\n        \n        last_val = scaled_compatible_mass_means[i];\n    }\n}\n\ndouble MleErrorModel::scale_mle_variance(double scaled_mass) const\n{\n    if (scaled_mass <= 0)\n        return 0.0;\n    \n    if (_scaled_compatible_mass_means.size() < 2 || _scaled_mle_variances.size() < 2)\n    {\n        return 0; // revert to poisson.\n    }\n    if (scaled_mass > _scaled_compatible_mass_means.back())\n    {\n        return 0;\n    }\n    else if (scaled_mass < _scaled_compatible_mass_means.front())\n    {\n        return 0; // we won't add anything if we're out of the range of the table\n    }\n    \n    vector<double>::const_iterator lb;\n    lb = lower_bound(_scaled_compatible_mass_means.begin(),\n                     _scaled_compatible_mass_means.end(),\n                     scaled_mass);\n    if (lb < _scaled_compatible_mass_means.end())\n    {\n        int d = lb - _scaled_compatible_mass_means.begin();\n        if (*lb == scaled_mass || lb == _scaled_compatible_mass_means.begin())\n        {\n            double var = _scaled_mle_variances[d];\n            assert (!isnan(var) && !isinf(var));\n            if (var < 0)\n                var = 0;\n            return var;\n        }\n        \n        //in between two points on the scale.\n        d--;\n        \n        if (d < 0)\n        {\n            fprintf(stderr, \"ARG d < 0, d = %d \\n\", d);\n        }\n        \n        if (d >= _scaled_compatible_mass_means.size())\n        {\n            fprintf(stderr, \"ARG d >= _scaled_compatible_mass_means.size(), d = %d\\n\", d);\n        }\n        if (d >= _scaled_mle_variances.size())\n        {\n            fprintf(stderr, \"ARG d >= _scaled_mass_variances.size(), d = %d\\n\", d);\n        }\n        \n        double x1_mean = _scaled_compatible_mass_means[d];\n        double x2_mean = _scaled_compatible_mass_means[d + 1];\n        \n        double y1_var = _scaled_mle_variances[d];\n        double y2_var = _scaled_mle_variances[d + 1];\n        double slope = 0.0;\n        if (x2_mean != x1_mean)\n        {\n            slope = (y2_var - y1_var) / (x2_mean-x1_mean);\n        }\n        else if (y1_var == y2_var)\n        {\n            assert (false); // should have a unique'd table\n        }\n        double mean_interp = _scaled_mle_variances[d] + slope*(scaled_mass - _scaled_compatible_mass_means[d]);\n        if (mean_interp < 0)\n            mean_interp = 0;\n        \n        assert (!isnan(mean_interp) && !isinf(mean_interp));\n        return mean_interp;\n    }\n    else\n    {\n        assert (!isnan(scaled_mass) && !isinf(scaled_mass));\n        return 0; // revert to poisson assumption\n    }\n}\n\nvoid transform_counts_to_common_scale(const vector<double>& scale_factors,\n                                      vector<LocusCountList>& sample_compatible_count_table)\n{\n    // Transform raw counts to the common scale\n    for (size_t i = 0; i < sample_compatible_count_table.size(); ++i)\n    {\n        LocusCountList& p = sample_compatible_count_table[i];\n        for (size_t j = 0; j < p.counts.size(); ++j)\n        {\n            assert (scale_factors.size() > j);\n            p.counts[j] *= (1.0 / scale_factors[j]);\n        }\n    }\n}\n\nvoid calc_geometric_scaling_factors(const vector<LocusCountList>& sample_compatible_count_table,\n                                    vector<double>& scale_factors)\n{\n    \n    vector<double> log_geom_means(sample_compatible_count_table.size(), 0.0);\n    \n    for (size_t i = 0; i < sample_compatible_count_table.size(); ++i)\n    {\n        const LocusCountList& p = sample_compatible_count_table[i];\n        \n        for (size_t j = 0; j < p.counts.size(); ++j)\n        {\n            //assert (log_geom_means.size() > j);\n            //if (floor(p.counts[j]) > 0)\n            //{\n                log_geom_means[i] += (1.0/p.counts.size()) * log(floor(p.counts[j]));\n            //}\n            \n        }\n        //log_geom_means[i] = pow(log_geom_means[i], 1.0/(double)p.counts.size());\n    }\n    \n    for (size_t j = 0; j < scale_factors.size(); ++j)\n    {\n        vector<double> tmp_counts;\n        for (size_t i = 0; i < sample_compatible_count_table.size(); ++i)\n        {\n            if (log_geom_means[i] && !isinf(log_geom_means[i]) && !isnan(log_geom_means[i]) && floor(sample_compatible_count_table[i].counts[j]))\n            {\n                double gm = (double)log(floor(sample_compatible_count_table[i].counts[j])) - log_geom_means[i];\n                assert (!isinf(gm));\n                tmp_counts.push_back(gm);\n            }\n        }\n        sort(tmp_counts.begin(), tmp_counts.end());\n        if (!tmp_counts.empty())\n            scale_factors[j] = exp(tmp_counts[tmp_counts.size()/2]);\n        else\n            scale_factors[j] = 1.0;\n    }\n}\n\nvoid calc_classic_fpkm_scaling_factors(const vector<LocusCountList>& sample_compatible_count_table,\n                                       vector<double>& scale_factors)\n{\n    vector<double> total_counts(sample_compatible_count_table.size(), 0.0);\n    \n    for (size_t i = 0; i < sample_compatible_count_table.size(); ++i)\n    {\n        const LocusCountList& p = sample_compatible_count_table[i];\n        \n        for (size_t j = 0; j < p.counts.size(); ++j)\n        {\n            total_counts[j] += floor(p.counts[j]);\n        }\n    }\n    \n    double all_library_counts = accumulate(total_counts.begin(), total_counts.end(), 0.0);\n    if (all_library_counts == 0.0)\n    {\n        for (size_t i = 0; i < scale_factors.size(); ++i)\n        {\n            scale_factors[i] = 1.0;\n        }\n        return;\n    }\n    for (size_t i = 0; i < scale_factors.size(); ++i)\n    {\n        scale_factors[i] = total_counts[i] / all_library_counts;\n    }\n    \n    double avg_scaling_factor = accumulate(scale_factors.begin(), scale_factors.end(), 0.0);\n    avg_scaling_factor /= scale_factors.size();\n    \n    for (size_t i = 0; i < scale_factors.size(); ++i)\n    {\n        scale_factors[i] = scale_factors[i] / avg_scaling_factor;\n    }\n}\n\nvoid calc_quartile_scaling_factors(const vector<LocusCountList>& sample_compatible_count_table,\n                                   vector<double>& scale_factors)\n{\n    \n    if (sample_compatible_count_table.empty())\n        return;\n    \n    vector<double> upper_quartiles(sample_compatible_count_table.front().counts.size(), 0.0);\n    vector<double> total_common_masses(sample_compatible_count_table.front().counts.size(), 0.0);\n    \n    for (size_t i = 0; i < sample_compatible_count_table.front().counts.size(); ++i)\n    {\n        vector<double> common_scaled_counts;\n        double total_common = 0.0;\n\n        for (size_t j = 0; j < sample_compatible_count_table.size(); ++j)\n        {\n        \n            //boost::shared_ptr<ReadGroupProperties> rg = bundle_factories[fac_idx];\n            //double scaled_mass = scale_factors[fac_idx] * rg->total_map_mass();\n            \n            total_common += sample_compatible_count_table[j].counts[i];\n            common_scaled_counts.push_back(sample_compatible_count_table[j].counts[i]);\n        }\n    \n        sort(common_scaled_counts.begin(), common_scaled_counts.end());\n        if (common_scaled_counts.empty())\n            continue;\n        \n        int upper_quart_index = common_scaled_counts.size() * 0.75;\n        double upper_quart_count = common_scaled_counts[upper_quart_index];\n        upper_quartiles[i] = upper_quart_count;\n        total_common_masses[i] = total_common;\n    }\n    \n    long double total_mass = accumulate(total_common_masses.begin(), total_common_masses.end(), 0.0);\n    long double total_norm_mass = accumulate(upper_quartiles.begin(), upper_quartiles.end(), 0.0);\n    \n    for (size_t i = 0; i < sample_compatible_count_table.front().counts.size(); ++i)\n    {\n        if (total_mass > 0)\n        {\n            double scaling_factor = upper_quartiles[i];\n            scaling_factor /= (total_norm_mass / upper_quartiles.size());\n            scale_factors[i] = scaling_factor;\n        }\n        else\n        {\n            scale_factors[i] = 1.0;\n        }\n    }\n}\n\nvoid calc_tmm_scaling_factors(const vector<LocusCountList>& sample_compatible_count_table,\n                              vector<double>& scale_factors)\n{\n    scale_factors = vector<double>(sample_compatible_count_table.size(), 1.0);\n}\n\nstatic const int min_loci_for_fitting = 30;\n\nstruct SCVInterpolator\n{\n    void add_scv_pair(double est_scv, double true_scv)\n    {\n        true_scvs.push_back(true_scv);\n        est_scvs.push_back(est_scv);\n    }\n    \n    void finalize() \n    {\n        vector<pair<double, double> > pv;\n        for (size_t i =0; i < true_scvs.size(); ++i)\n        {\n            pv.push_back(make_pair(est_scvs[i], true_scvs[i]));\n        }\n        sort(pv.begin(), pv.end());\n    }\n    \n    // This was built from the dispersion model interpolator - we should refactor these \n    // into a single routine.\n    double interpolate_scv(double est_scv)\n    {\n//        if (est_scv <= 0)\n//            return 0.0;\n        \n        if (est_scvs.size() < 2 || true_scvs.size() < 2)\n        {\n            return est_scv; // revert to poisson.\n        }\n        if (est_scv > est_scvs.back())\n        {\n            //fprintf(stderr, \"Warning: extrapolating to the right\\n\");\n            // extrapolate to the right\n            // off the right end\n            double x1_mean = est_scvs[est_scvs.size()-2];\n            double x2_mean = est_scvs[est_scvs.size()-1];\n            \n            double y1_var = true_scvs[est_scvs.size()-2];\n            double y2_var = true_scvs[est_scvs.size()-1];\n            double slope = 0.0;                \n            if (x2_mean != x1_mean)\n            {\n                slope = (y2_var - y1_var) / (x2_mean-x1_mean);\n            }\n            else if (y1_var == y2_var)\n            {\n                assert (false); // should have a unique'd table\n            }\n            double mean_interp = true_scvs[est_scvs.size()-1] -\n                slope*(est_scv - est_scvs.size()-1);\n//            if (mean_interp < est_scv)\n//                mean_interp = est_scv;\n            assert (!isnan(mean_interp) && !isinf(mean_interp));\n            return mean_interp;\n        }\n        else if (est_scv < est_scvs.front())\n        {\n            //fprintf(stderr, \"Warning: extrapolating to the left\\n\");\n            \n            // If we're extrapolating to the left, our fit is too coarse, but\n            // that probably means we don't need SCV bias correction at all.\n            return est_scv;\n        }\n        \n        vector<double>::const_iterator lb;\n        lb = lower_bound(est_scvs.begin(), \n                         est_scvs.end(), \n                         est_scv);\n        if (lb < est_scvs.end())\n        {\n            int d = lb - est_scvs.begin();\n            if (*lb == est_scv || lb == est_scvs.begin())\n            {\n                double var = true_scvs[d];\n//                if (var < est_scv) // revert to poisson if underdispersed\n//                    var = est_scv;\n                assert (!isnan(var) && !isinf(var));\n                return var;\n            }\n            \n            \n            //in between two points on the scale.\n            d--;\n            \n            if (d < 0)\n            {\n                fprintf(stderr, \"ARG d < 0, d = %d \\n\", d);\n            }\n            \n            if (d >= est_scvs.size())\n            {\n                fprintf(stderr, \"ARG d >= est_scvs.size(), d = %d\\n\", d);\n            }\n            if (d >= true_scvs.size())\n            {\n                fprintf(stderr, \"ARG d >= true_scvs.size(), d = %d\\n\", d);\n            }\n            \n            double x1_mean = est_scvs[d];\n            double x2_mean = est_scvs[d + 1];\n            \n            double y1_var = true_scvs[d];\n            double y2_var = true_scvs[d + 1];\n            double slope = 0.0;                \n            if (x2_mean != x1_mean)\n            {\n                slope = (y2_var - y1_var) / (x2_mean-x1_mean);\n            }\n            else if (y1_var == y2_var)\n            {\n                fprintf(stderr, \"Warning: SCV table does not have unique keys\\n!\");\n                assert (false); // should have a unique'd table\n            }\n            double mean_interp = true_scvs[d] + slope*(est_scv - est_scvs[d]);\n//            if (mean_interp < est_scv) // revert to poisson if underdispersed\n//                mean_interp = est_scv;\n            \n            assert (!isnan(mean_interp) && !isinf(mean_interp));\n            return mean_interp;\n        }\n        else\n        {\n            assert (!isnan(est_scv) && !isinf(est_scv));\n            return est_scv; // revert to poisson assumption\n        }\n        \n        return est_scv;\n    }\n    \nprivate:\n    vector<double> true_scvs;\n    vector<double> est_scvs;\n};\n\nvoid build_scv_correction_fit(int nreps, int ngenes, int mean_count, SCVInterpolator& true_to_est_scv_table)\n{    \n    setuplf();  \n    \n    vector<pair<double, double> > alpha_vs_scv;\n   \n    boost::mt19937 rng(random_seed);\n    vector<boost::random::negative_binomial_distribution<int, double> > nb_gens;\n    \n    vector<double> alpha_range;\n    for(double a = 0.0002; a < 2.0; a += 0.0002)\n    {\n        alpha_range.push_back(a);\n    }\n    \n    for (double a = 2; a < 100.0; a += 1)\n    {\n        alpha_range.push_back(a);\n    }\n    \n    BOOST_FOREACH (double alpha, alpha_range)\n    {\n        double k = 1.0/alpha;\n        double p = k / (k + mean_count);\n        double r = (mean_count * p) / (1-p);\n\n        //boost::random::negative_binomial_distribution<int, double> nb(r, p);\n        \n        boost::random::gamma_distribution<double> gamma(r, (1-p)/p);\n        \n        \n        vector<double> scvs_for_alpha;\n        vector<double> draws;\n        for (size_t i = 0; i < ngenes; ++i)\n        {\n            LocusCountList locus_count(\"\", nreps, 1, vector<string>(), vector<string>());\n            for (size_t rep_idx = 0; rep_idx < nreps; ++rep_idx)\n            {\n                double gamma_draw = gamma(rng);\n                if (gamma_draw == 0)\n                {\n                    locus_count.counts[rep_idx] = 0;\n                    draws.push_back(0);\n                }\n                else\n                {\n                    boost::random::poisson_distribution<long, double> poisson(gamma_draw);\n                    locus_count.counts[rep_idx] = poisson(rng);\n                    draws.push_back(locus_count.counts[rep_idx]);\n                    //fprintf(stderr, \"%lg\\t\", locus_count.counts[rep_idx]);\n                }\n            }\n            \n            double mean = accumulate(locus_count.counts.begin(), locus_count.counts.end(), 0.0);\n            if (mean == 0)\n                continue;\n            mean /= locus_count.counts.size();\n            double var = 0.0;\n            BOOST_FOREACH(double c,  locus_count.counts)\n            {\n                var += (c-mean)*(c-mean);\n            }\n            var /= locus_count.counts.size();\n            var *= locus_count.counts.size() / (locus_count.counts.size() - 1);\n            \n            double scv = var / (mean*mean);\n            scvs_for_alpha.push_back(scv);\n            //fprintf(stderr, \" : mean = %lg, var = %lg, scv = %lg\\n\", mean, var, scv);\n            \n            //fprintf(stderr, \"\\n\");\n        }\n        \n        double mean = accumulate(draws.begin(), draws.end(), 0.0);\n        mean /= draws.size();\n        double var = 0.0;\n        BOOST_FOREACH(int c,  draws)\n        {\n            var += (c - mean)*(c-mean);\n        }\n        var /= draws.size();\n        var *= draws.size() / (draws.size() - 1);\n        \n       \n        \n        //fprintf(stderr, \"##########\\n\");\n        //fprintf(stderr, \"mean = %lf, var = %lg\\n\", mean, var);\n        if (scvs_for_alpha.size() > 0)\n        {\n            double mean_scv = accumulate(scvs_for_alpha.begin(),scvs_for_alpha.end(), 0.0);\n            mean_scv /= scvs_for_alpha.size();\n            //fprintf(stderr, \"alpha = %lg scv = %lg\\n\", alpha, mean_scv);\n            alpha_vs_scv.push_back(make_pair(alpha, mean_scv));\n        }\n    }\n    \n    //fprintf(stderr, \"$$$$$$$$$\\n\");\n    \n    //sort (alpha_range.begin(), alpha_range.end());\n    \n    char namebuf[256];\n    sprintf(namebuf, \"trueSCV\");\n    vari* cm = createvar(namebuf,STREGULAR,alpha_vs_scv.size(),VDOUBLE);\n    for (size_t i = 0; i < alpha_vs_scv.size(); ++i)\n    {\n        cm->dpr[i] = alpha_vs_scv[i].first;\n    }\n    \n    sprintf(namebuf, \"estSCV\");\n    vari* cv = createvar(namebuf,STREGULAR,alpha_vs_scv.size(),VDOUBLE);\n    for (size_t i = 0; i < alpha_vs_scv.size(); ++i)\n    {\n        cv->dpr[i] = alpha_vs_scv[i].second;\n    }\n    \n    char locfit_cmd[2048];\n    sprintf(locfit_cmd, \"locfit trueSCV~estSCV\");\n    \n    locfit_dispatch(locfit_cmd);\n    \n    sprintf(namebuf, \"domainSCV\");\n    vari* cd = createvar(namebuf,STREGULAR,alpha_vs_scv.size(),VDOUBLE);\n    for (size_t i = 0; i < alpha_vs_scv.size(); ++i)\n    {\n        cd->dpr[i] = alpha_vs_scv[i].second;\n    }\n    \n    sprintf(locfit_cmd, \"fittedSCV=predict domainSCV\");\n    locfit_dispatch(locfit_cmd);\n    \n    int n = 0;\n    sprintf(namebuf, \"fittedSCV\");\n    vari* cp = findvar(namebuf, 1, &n);\n    assert(cp != NULL);\n    \n    for (size_t i = 0; i < cp->n; ++i)\n    {\n        //fprintf(stderr, \"%lg\\t%lg\\n\",alpha_range[i], cp->dpr[i]);\n        true_to_est_scv_table.add_scv_pair(alpha_range[i], cp->dpr[i]);\n    }\n    true_to_est_scv_table.finalize();\n}\n\nvoid calculate_count_means_and_vars(const vector<LocusCountList>& sample_compatible_count_table,\n                                    vector<pair<double, double> >& means_and_vars)\n{\n    \n    for (size_t i = 0; i < sample_compatible_count_table.size(); ++i)\n    {\n        const LocusCountList& p = sample_compatible_count_table[i];\n        double mean = accumulate(p.counts.begin(), p.counts.end(), 0.0);\n        if (mean > 0.0 && p.counts.size() > 0)\n            mean /= p.counts.size();\n        \n        double var = 0.0;\n        double num_non_zero = 0;\n        BOOST_FOREACH (double d, p.counts)\n        {\n            if (d > 0)\n                num_non_zero++;\n            var += (d - mean) * (d - mean);\n        }\n        if (var > 0.0 && p.counts.size())\n        {\n            var /= p.counts.size();\n            var *= p.counts.size() / (p.counts.size() - 1);\n        }\n        means_and_vars.push_back(make_pair(mean, var));\n    }\n}\n                              \nboost::shared_ptr<MassDispersionModel>\nfit_dispersion_model_helper(const string& condition_name,\n                            const vector<double>& scale_factors,\n                            const vector<LocusCountList>& sample_compatible_count_table)\n{\n    vector<pair<double, double> > compatible_means_and_vars;\n    \n    SCVInterpolator true_to_est_scv_table;\n    \n    int num_samples = sample_compatible_count_table.front().counts.size();\n    if (no_scv_correction == false)\n    {\n        build_scv_correction_fit(num_samples, 10000, 100000, true_to_est_scv_table);\n    }\n    \n    setuplf();  \n    \n    calculate_count_means_and_vars(sample_compatible_count_table, compatible_means_and_vars);\n\n    sort(compatible_means_and_vars.begin(), compatible_means_and_vars.end());\n    \n    vector<double> compatible_count_means;\n    vector<double> raw_variances;\n    \n    for(size_t i = 0; i < compatible_means_and_vars.size(); ++i)\n    {\n        if (compatible_means_and_vars[i].first > 0 && compatible_means_and_vars[i].second > 0.0)\n        {\n            compatible_count_means.push_back(compatible_means_and_vars[i].first);\n            raw_variances.push_back(compatible_means_and_vars[i].second);\n        }\n    }\n    \n    if (compatible_count_means.size() < min_loci_for_fitting)\n    {\n        boost::shared_ptr<MassDispersionModel> disperser;\n        disperser = boost::shared_ptr<MassDispersionModel>(new PoissonDispersionModel(condition_name));\n        \n        return disperser;\n    }\n    \n    \n    vector<double> fitted_values;\n    \n    // WARNING: locfit doesn't like undescores - need camel case for \n    // variable names\n    \n    char namebuf[256];\n    sprintf(namebuf, \"countMeans\");\n    vari* cm = createvar(namebuf,STREGULAR,compatible_count_means.size(),VDOUBLE);\n    for (size_t i = 0; i < compatible_count_means.size(); ++i)\n    {\n        cm->dpr[i] = log(compatible_count_means[i]);\n    }\n    \n    //sprintf(namebuf, \"countSCV\");\n    sprintf(namebuf, \"countVariances\");\n    vari* cv = createvar(namebuf,STREGULAR,raw_variances.size(),VDOUBLE);\n    for (size_t i = 0; i < raw_variances.size(); ++i)\n    {\n        cv->dpr[i] = raw_variances[i]; \n        //cv->dpr[i] = raw_scvs[i];\n    }\n    \n    char locfit_cmd[2048];\n    //sprintf(locfit_cmd, \"locfit countVariances~countMeans family=gamma\");\n    sprintf(locfit_cmd, \"locfit countVariances~countMeans family=gamma\");\n    \n    locfit_dispatch(locfit_cmd);\n    \n    sprintf(locfit_cmd, \"fittedVars=predict countMeans\");\n    locfit_dispatch(locfit_cmd);\n    \n    //sprintf(locfit_cmd, \"prfit x fhat h nlx\");\n    //locfit_dispatch(locfit_cmd);\n    \n    double xim = 0;\n    BOOST_FOREACH(double s, scale_factors)\n    {\n        if (s)\n            xim += 1.0 / s;\n    }\n    xim /= scale_factors.size();\n    \n    int n = 0;\n    sprintf(namebuf, \"fittedVars\");\n    vari* cp = findvar(namebuf, 1, &n);\n    assert(cp != NULL);\n    for (size_t i = 0; i < cp->n; ++i)\n    {\n//        if (cp->dpr[i] >= 0)\n//        {\n            double mean = exp(cm->dpr[i]);\n            double fitted_scv = (cp->dpr[i] - mean) / (mean * mean);\n            double corrected_scv = true_to_est_scv_table.interpolate_scv(fitted_scv);\n            double corrected_variance = mean + (corrected_scv * (mean * mean));\n            double uncorrected_variance = mean + (fitted_scv * (mean * mean));\n            //fitted_values.push_back(mean + (cp->dpr[i] - xim * mean));\n            if (no_scv_correction == false && corrected_variance > uncorrected_variance)\n                fitted_values.push_back(corrected_variance);\n            else if (uncorrected_variance > 0)\n                fitted_values.push_back(uncorrected_variance);\n            else\n                fitted_values.push_back(compatible_count_means[i]);\n        \n            \n//        }\n//        else\n//        {\n//            fitted_values.push_back(compatible_count_means[i]);\n//        }\n    }\n    \n    boost::shared_ptr<MassDispersionModel> disperser;\n    disperser = boost::shared_ptr<MassDispersionModel>(new MassDispersionModel(condition_name, compatible_count_means, raw_variances, fitted_values));\n    if (dispersion_method == POISSON)\n        disperser = boost::shared_ptr<MassDispersionModel>(new PoissonDispersionModel(condition_name));\n    \n//    for (map<string, pair<double, double> >::iterator itr = labeled_mv_table.begin();\n//         itr != labeled_mv_table.end();\n//         ++itr)\n//    {\n//        string label = itr->first;\n//        disperser->set_compatible_mean_and_var(itr->first, itr->second);\n//    }\n    \n    return disperser;\n}\n\nboost::shared_ptr<MassDispersionModel>\nfit_dispersion_model(const string& condition_name,\n                     const vector<double>& scale_factors,\n                     const vector<LocusCountList>& sample_compatible_count_table)\n{\n//    \n//#if ENABLE_THREADS\n//\tboost::mutex::scoped_lock lock(_locfit_lock);\n//#endif\n    for (size_t i = 0; i < sample_compatible_count_table.size(); ++i)\n    {\n        if (sample_compatible_count_table[i].counts.size() <= 1)\n        {\n            // only one replicate - no point in fitting variance\n            return boost::shared_ptr<MassDispersionModel>(new PoissonDispersionModel(condition_name));\n        }\n    }\n#if ENABLE_THREADS\n    _locfit_lock.lock();\n#endif\n    \n    ProgressBar p_bar(\"Modeling fragment count overdispersion.\",0);\n    \n    int max_transcripts = 0;\n    BOOST_FOREACH(const LocusCountList& L, sample_compatible_count_table)\n    {\n        if (L.num_transcripts > max_transcripts)\n        {\n            max_transcripts = L.num_transcripts;\n        }\n    }\n    \n    boost::shared_ptr<MassDispersionModel>  model = fit_dispersion_model_helper(condition_name, scale_factors, sample_compatible_count_table);\n\n#if ENABLE_THREADS\n    _locfit_lock.unlock();\n#endif\n    return model;\n}\n\nvoid build_norm_table(const vector<LocusCountList>& full_count_table,\n                      boost::shared_ptr<const map<string, LibNormStandards> > normalizing_standards,\n                      vector<LocusCountList>& norm_table)\n{\n    // If we're using housekeeping genes or spike-in controls, select the rows we'll be using from the full count table.\n    if (normalizing_standards)\n    {\n        for (size_t i = 0; i < full_count_table.size(); ++i)\n        {\n            const vector<string>& gene_ids = full_count_table[i].gene_ids;\n            const vector<string>& gene_short_names = full_count_table[i].gene_short_names;\n            \n            // If the row has an ID that's in the table, take it.\n            map<string, LibNormStandards>::const_iterator g_id_itr = normalizing_standards->end();\n            map<string, LibNormStandards>::const_iterator g_name_itr = normalizing_standards->end();\n            \n            for (size_t j = 0; j < gene_ids.size(); ++j)\n            {\n                g_id_itr = normalizing_standards->find(gene_ids[j]);\n                if (g_id_itr != normalizing_standards->end())\n                {\n                    break;\n                }\n            }\n            \n            if (g_id_itr != normalizing_standards->end())\n            {\n                norm_table.push_back(full_count_table[i]);\n                continue;\n            }\n\n            for (size_t j = 0; j < gene_short_names.size(); ++j)\n            {\n                g_name_itr = normalizing_standards->find(gene_short_names[j]);\n                if (g_name_itr != normalizing_standards->end())\n                {\n                    break;\n                }\n            }\n            \n            if (g_name_itr != normalizing_standards->end())\n            {\n                norm_table.push_back(full_count_table[i]);\n                continue;\n            }\n\n        }\n    }\n    else // otherwise, just take all rows.\n    {\n        norm_table = full_count_table;\n    }\n}\n\nvoid normalize_counts(vector<boost::shared_ptr<ReadGroupProperties> > & all_read_groups)\n{\n    vector<LocusCountList> sample_compatible_count_table;\n    vector<LocusCountList> sample_total_count_table;\n    \n    for (size_t i = 0; i < all_read_groups.size(); ++i)\n    {\n        boost::shared_ptr<ReadGroupProperties> rg_props = all_read_groups[i];\n        const vector<LocusCount>& raw_compatible_counts = rg_props->raw_compatible_counts();\n        const vector<LocusCount>& raw_total_counts = rg_props->raw_total_counts();\n        \n        for (size_t j = 0; j < raw_compatible_counts.size(); ++j)\n        {\n            if (sample_compatible_count_table.size() == j)\n            {\n                const string& locus_id = raw_compatible_counts[j].locus_desc;\n                int num_transcripts = raw_compatible_counts[j].num_transcripts;\n                \n                const vector<string>& gene_ids = raw_compatible_counts[j].gene_ids;\n                const vector<string>& gene_short_names = raw_compatible_counts[j].gene_short_names;\n                \n                sample_compatible_count_table.push_back(LocusCountList(locus_id,all_read_groups.size(), num_transcripts, gene_ids, gene_short_names));\n                sample_total_count_table.push_back(LocusCountList(locus_id,all_read_groups.size(), num_transcripts, gene_ids, gene_short_names));\n            }\n            double scaled = raw_compatible_counts[j].count;\n            //sample_compatible_count_table[j].counts[i] = scaled * unscaling_factor;\n            sample_compatible_count_table[j].counts[i] = floor(scaled);\n            sample_total_count_table[j].counts[i] = floor(raw_total_counts[j].count);\n            \n            assert(sample_compatible_count_table[j].counts[i] >= 0 && !isinf(sample_compatible_count_table[j].counts[i]));\n        }\n    }\n    \n    vector<double> scale_factors(all_read_groups.size(), 0.0);\n    \n    vector<LocusCountList> norm_table;\n    \n    if (use_compat_mass)\n    {\n        build_norm_table(sample_compatible_count_table, lib_norm_standards, norm_table);\n    }\n    else // use_total_mass\n    {\n        assert(use_total_mass);\n        build_norm_table(sample_total_count_table, lib_norm_standards, norm_table);\n    }\n    \n    if (lib_norm_method == GEOMETRIC)\n    {\n        calc_geometric_scaling_factors(norm_table, scale_factors);\n    }\n    else if (lib_norm_method == CLASSIC_FPKM)\n    {\n        calc_classic_fpkm_scaling_factors(norm_table, scale_factors);\n    }\n    else if (lib_norm_method == QUARTILE)\n    {\n        calc_quartile_scaling_factors(norm_table, scale_factors);\n    }\n    else if (lib_norm_method == TMM)\n    {\n        calc_tmm_scaling_factors(norm_table, scale_factors);\n    }\n    else\n    {\n        assert (false);\n    }\n    \n    for (size_t i = 0; i < all_read_groups.size(); ++i)\n    {\n        boost::shared_ptr<ReadGroupProperties> rg_props = all_read_groups[i];\n        rg_props->internal_scale_factor(scale_factors[i]);\n    }\n    \n    assert(sample_compatible_count_table.size() == sample_total_count_table.size());\n    \n    // Transform raw counts to the common scale\n    for (size_t i = 0; i < sample_compatible_count_table.size(); ++i)\n    {\n        LocusCountList& p = sample_compatible_count_table[i];\n        for (size_t j = 0; j < p.counts.size(); ++j)\n        {\n            assert (scale_factors.size() > j);\n            p.counts[j] *= (1.0 / scale_factors[j]);\n        }\n        \n        LocusCountList& t = sample_total_count_table[i];\n        for (size_t j = 0; j < t.counts.size(); ++j)\n        {\n            assert (scale_factors.size() > j);\n            t.counts[j] *= (1.0 / scale_factors[j]);\n        }\n    }\n    \n    for (size_t i = 0; i < all_read_groups.size(); ++i)\n    {\n        boost::shared_ptr<ReadGroupProperties> rg_props = all_read_groups[i];\n        vector<LocusCount> scaled_compatible_counts;\n        for (size_t j = 0; j < sample_compatible_count_table.size(); ++j)\n        {\n            string& locus_id = sample_compatible_count_table[j].locus_desc;\n            double count = sample_compatible_count_table[j].counts[i];\n            int num_transcripts = sample_compatible_count_table[j].num_transcripts;\n            \n            const vector<string>& gids = sample_compatible_count_table[j].gene_ids;\n            const vector<string>& gnms = sample_compatible_count_table[j].gene_short_names;\n            \n            LocusCount locus_count(locus_id, count, num_transcripts, gids, gnms);\n            scaled_compatible_counts.push_back(locus_count);\n        }\n        rg_props->common_scale_compatible_counts(scaled_compatible_counts);\n    }\n    \n    for (size_t i = 0; i < all_read_groups.size(); ++i)\n    {\n        boost::shared_ptr<ReadGroupProperties> rg_props = all_read_groups[i];\n        vector<LocusCount> scaled_total_counts;\n        for (size_t j = 0; j < sample_total_count_table.size(); ++j)\n        {\n            string& locus_id = sample_total_count_table[j].locus_desc;\n            double count = sample_total_count_table[j].counts[i];\n            int num_transcripts = sample_total_count_table[j].num_transcripts;\n            \n            const vector<string>& gids = sample_total_count_table[j].gene_ids;\n            const vector<string>& gnms = sample_total_count_table[j].gene_short_names;\n            \n            LocusCount locus_count(locus_id, count, num_transcripts, gids, gnms);\n            scaled_total_counts.push_back(locus_count);\n        }\n        rg_props->common_scale_total_counts(scaled_total_counts);\n    }\n    \n    double avg_total_common_scaled_count = 0.0;\n    \n    for (size_t fac_idx = 0; fac_idx < all_read_groups.size(); ++fac_idx)\n    {\n        double total_common = 0.0;\n        if (use_compat_mass)\n        {\n            for (size_t j = 0; j < sample_compatible_count_table.size(); ++j)\n            {\n                total_common += sample_compatible_count_table[j].counts[fac_idx];\n            }\n        }\n        else\n        {\n            for (size_t j = 0; j < sample_compatible_count_table.size(); ++j)\n            {\n                total_common += sample_total_count_table[j].counts[fac_idx];\n            }\n\n        }\n        \n        avg_total_common_scaled_count += (1.0/all_read_groups.size()) * total_common;\n    }\n    \n    BOOST_FOREACH(boost::shared_ptr<ReadGroupProperties> rg, all_read_groups)\n    {\n        rg->normalized_map_mass(avg_total_common_scaled_count);\n    }\n}\n\n"
  },
  {
    "path": "src/replicates.h",
    "content": "//\n//  replicates.h\n//  cufflinks\n//\n//  Created by Cole Trapnell on 3/11/11.\n//  Copyright 2011 Cole Trapnell. All rights reserved.\n//\n\n#include \"common.h\"\n#include \"bundles.h\"\n#include <vector>\n#include <algorithm>\n#include <map>\n\nclass MassDispersionModel\n{\npublic:\n    MassDispersionModel() {}\n    MassDispersionModel(const std::string& name,\n                        const std::vector<double>& scaled_compatible_mass_means, \n                        const std::vector<double>& scaled_compatible_variances,\n                        const std::vector<double>& scaled_mass_variances);\n\n    virtual const std::string& name() const { return _name; }\n    \n    virtual double scale_mass_variance(double scaled_mass) const;\n    \n    const vector<double>& scaled_compatible_mass_means() const { return _scaled_compatible_mass_means; }\n    const vector<double>& scaled_compatible_variances() const { return _scaled_compatible_variances; }\n    const vector<double>& scaled_mass_variances() const { return _scaled_mass_variances; }\n    \n    std::pair<double, double> get_compatible_mean_and_var(const std::string& locus_desc) const\n    {\n        std::map<std::string, std::pair<double, double> >::const_iterator itr;\n        itr = _compatible_mv_by_locus.find(locus_desc);\n        std::pair<double, double> p = make_pair<double, double>(0.0,0.0);\n        if (itr != _compatible_mv_by_locus.end())\n        {\n            p = itr->second;\n        }\n        return p;\n    }\n    \n    std::pair<double, double> get_total_mean_and_var(const std::string& locus_desc) const\n    {\n        std::map<std::string, std::pair<double, double> >::const_iterator itr;\n        itr = _total_mv_by_locus.find(locus_desc);\n        std::pair<double, double> p = make_pair<double, double>(0.0,0.0);\n        if (itr != _total_mv_by_locus.end())\n        {\n            p = itr->second;\n        }\n        return p;\n    }\n    \n    void set_compatible_mean_and_var(const std::string& locus_desc, const std::pair<double, double>& p)\n    {\n        _compatible_mv_by_locus[locus_desc] = p;\n    }\n    \n    void set_total_mean_and_var(const std::string& locus_desc, const std::pair<double, double>& p)\n    {\n        _total_mv_by_locus[locus_desc] = p;\n    }\n    \n    const std::map<std::string, std::pair<double, double> >& total_mv_by_locus() const { return _total_mv_by_locus; }\n    const std::map<std::string, std::pair<double, double> >& compatible_mv_by_locus() const { return _compatible_mv_by_locus; }\n    \nprivate:\n    std::string         _name;\n    std::vector<double> _scaled_compatible_mass_means;\n    std::vector<double> _scaled_compatible_variances;\n    std::vector<double> _scaled_mass_variances;\n    \n    std::map<std::string, std::pair<double, double> > _compatible_mv_by_locus;\n    std::map<std::string, std::pair<double, double> > _total_mv_by_locus;\n};\n\nclass PoissonDispersionModel : public MassDispersionModel\n{\n    std::string         _name;\n    \npublic:\n    PoissonDispersionModel(const std::string& name) : _name(name) {}\n        \n        virtual const std::string& name() const { return _name; }\n    virtual double scale_mass_variance(double scaled_mass) const \n    { \n        return scaled_mass; \n    }\n};\n\n\n\nclass MleErrorModel\n{\npublic:\n    MleErrorModel() {}\n    MleErrorModel(const std::string& name,\n                        const std::vector<double>& scaled_compatible_mass_means,\n                        const std::vector<double>& scaled_mle_variances);\n    \n    virtual const std::string& name() const { return _name; }\n    \n    virtual double scale_mle_variance(double scaled_mass) const;\n    \n//    const vector<double>& scaled_compatible_mass_means() const { return _scaled_compatible_mass_means; }\n//    const vector<double>& scaled_compatible_variances() const { return _scaled_compatible_variances; }\n//    const vector<double>& scaled_mass_variances() const { return _scaled_mass_variances; }\n    \nprivate:\n    std::string         _name;\n    std::vector<double> _scaled_compatible_mass_means;\n    std::vector<double> _scaled_mle_variances;\n};\n\nstruct LocusCountList\n{\n    LocusCountList(std::string ld, int num_reps, int nt, const std::vector<std::string>& gids, const std::vector<std::string>& gnms) :\n    locus_desc(ld), counts(std::vector<double>(num_reps, 0)), num_transcripts(nt), gene_ids(gids), gene_short_names(gnms) {}\n    std::string locus_desc;\n    std::vector<double> counts;\n    int num_transcripts;\n    vector<std::string> gene_ids;\n    vector<std::string> gene_short_names;\n};\n\nvoid transform_counts_to_common_scale(const vector<double>& scale_factors,\n                                      vector<LocusCountList>& sample_count_table);\n\nvoid calc_geometric_scaling_factors(const std::vector<LocusCountList>& sample_count_table,\n                                    std::vector<double>& scale_factors);\n\nvoid calc_classic_fpkm_scaling_factors(const std::vector<LocusCountList>& sample_count_table,\n                                       std::vector<double>& scale_factors);\n\nvoid calc_quartile_scaling_factors(const std::vector<LocusCountList>& sample_count_table,\n                                        std::vector<double>& scale_factors);\n\nvoid calc_tmm_scaling_factors(const std::vector<LocusCountList>& sample_count_table,\n                                        std::vector<double>& scale_factors);\n\n\nboost::shared_ptr<MassDispersionModel>\nfit_dispersion_model(const string& condition_name,\n                     const std::vector<double>& scale_factors,\n                     const std::vector<LocusCountList>& sample_count_table);\n\nvoid calculate_count_means_and_vars(const vector<LocusCountList>& sample_compatible_count_table,\n                                    vector<pair<double, double> >& means_and_vars);\n\n// This factory merges bundles in a requested locus from several replicates\nclass ReplicatedBundleFactory\n{\npublic:\n\tReplicatedBundleFactory(const std::vector<boost::shared_ptr<BundleFactory> >& factories, \n                            const string& condition_name)\n    : _factories(factories), _condition_name(condition_name) {}\n\t\n\tint num_bundles() { return _factories[0]->num_bundles(); }\n    std::vector<boost::shared_ptr<BundleFactory> > factories() { return _factories; }\n\t\n    const string& condition_name() const { return _condition_name; }\n    void condition_name(const string& cn) { _condition_name = cn; }\n    \n    bool bundles_remain() \n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_rep_factory_lock);\n#endif\n        BOOST_FOREACH (boost::shared_ptr<BundleFactory> fac, _factories)\n        {\n            if (fac->bundles_remain())\n                return true;\n        }\n        return false;\n    }\n    \n\tbool next_bundle(HitBundle& bundle_out, bool cache_bundle)\n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_rep_factory_lock);\n#endif\n        std::vector<HitBundle*> bundles;\n        \n        bool non_empty_bundle = false;\n        BOOST_FOREACH (boost::shared_ptr<BundleFactory> fac, _factories)\n        {\n            bundles.push_back(new HitBundle());\n            if (fac->next_bundle(*(bundles.back()), cache_bundle))\n            {\n                non_empty_bundle = true;\n            }\n        }\n        \n        int locus_id = -1;\n        for (size_t i = 0; i < bundles.size(); ++i)\n        {\n            if (locus_id == -1)\n                locus_id = bundles[i]->id();\n            if (locus_id != bundles[i]->id())\n            {\n                fprintf(stderr, \"Error: locus id mismatch!\\n\");\n                exit(1);\n            }\n        }\n        \n        \n//        if (non_empty_bundle == false)\n//        {\n//            bundle_out.id(locus_id);\n//            BOOST_FOREACH (HitBundle* in_bundle, bundles)\n//            {\n//                in_bundle->ref_scaffolds().clear();\n//                in_bundle->clear_hits();\n//                delete in_bundle;\n//            }\n//            return false;\n//        }\n        \n        for (size_t i = 1; i < bundles.size(); ++i)\n        {\n            const vector<boost::shared_ptr<Scaffold> >& s1 = bundles[i]->ref_scaffolds();\n            const vector<boost::shared_ptr<Scaffold> >& s2 =  bundles[i-1]->ref_scaffolds();\n            assert (s1.size() == s2.size());\n            for (size_t j = 0; j < s1.size(); ++j)\n            {\n                assert (s1[j]->annotated_trans_id() == s2[j]->annotated_trans_id());\n            }\n        }\n        \n        double total_compatible_mass = 0.0;\n        double total_raw_mass = 0.0;\n        \n        for (size_t i = 0; i < bundles.size(); ++i)\n        {\n            total_compatible_mass += bundles[i]->compatible_mass();\n            total_raw_mass += bundles[i]->raw_mass();\n        }\n        \n        // Merge the replicates into a combined bundle of hits.\n        HitBundle::combine(bundles, bundle_out);\n        \n        bundle_out.compatible_mass(total_compatible_mass);\n        bundle_out.add_raw_mass(total_raw_mass);\n        \n        bundle_out.id(locus_id);\n        \n        BOOST_FOREACH (HitBundle* in_bundle, bundles)\n        {\n            in_bundle->ref_scaffolds().clear();\n            in_bundle->clear_hits();\n            delete in_bundle;\n        }\n        return non_empty_bundle;\n    }\n\t\n\tvoid reset() \n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_rep_factory_lock);\n#endif\n        BOOST_FOREACH (boost::shared_ptr<BundleFactory> fac, _factories)\n        {\n            fac->reset();\n        }\n    }\n    \n    void inspect_replicate_maps(int& min_len, int& max_len, IdToLocusMap& id_to_locus_map)\n    {\n        vector<LocusCountList> sample_compatible_count_table;\n        vector<LocusCountList> sample_total_count_table;\n        \n        vector<double> sample_masses;\n        \n        for (size_t fac_idx = 0; fac_idx < _factories.size(); ++fac_idx)\n        {\n            boost::shared_ptr<BundleFactory> fac = _factories[fac_idx];        \n            BadIntronTable bad_introns;\n            \n            vector<LocusCount> compatible_count_table;\n            vector<LocusCount> total_count_table;\n            \n            inspect_map(fac, NULL, compatible_count_table, total_count_table, id_to_locus_map, false, false);\n            \n            boost::shared_ptr<ReadGroupProperties> rg_props = fac->read_group_properties();\n            \n            assert (compatible_count_table.size() == total_count_table.size());\n            \n            for (size_t i = 0; i < compatible_count_table.size(); ++i)\n            {\n                LocusCount& c = compatible_count_table[i];\n                double raw_count = c.count;\n                \n                if (i >= sample_compatible_count_table.size())\n                {\n                    LocusCountList locus_count(c.locus_desc, _factories.size(), c.num_transcripts, c.gene_ids, c.gene_short_names);\n                    sample_compatible_count_table.push_back(locus_count);\n                    sample_compatible_count_table.back().counts[0] = raw_count;\n                    sample_total_count_table.push_back(locus_count);\n                    sample_total_count_table.back().counts[0] = total_count_table[i].count;\n                }\n                else\n                {\n                    if (sample_compatible_count_table[i].locus_desc != c.locus_desc)\n                    {\n                        fprintf (stderr, \"Error: bundle boundaries don't match across replicates!\\n\");\n                        exit(1);\n                    }\n                    sample_compatible_count_table[i].counts[fac_idx] = raw_count;\n                    sample_total_count_table[i].counts[fac_idx] = total_count_table[i].count;\n                }\n            }\n            \n            rg_props->raw_compatible_counts(compatible_count_table);\n            rg_props->raw_total_counts(total_count_table);\n            \n            sample_masses.push_back(rg_props->total_map_mass());\n\t\t\tmin_len = min(min_len, rg_props->frag_len_dist()->min());\n\t\t\tmax_len = max(max_len, rg_props->frag_len_dist()->max());\n        }\n        \n        /*\n        vector<double> scale_factors(_factories.size(), 0.0);\n        \n        calc_scaling_factors(sample_compatible_count_table, scale_factors);\n        \n        for (size_t i = 0; i < scale_factors.size(); ++i)\n        {\n            boost::shared_ptr<ReadGroupProperties> rg_props = _factories[i]->read_group_properties();\n            assert (scale_factors[i] != 0);\n            rg_props->internal_scale_factor(scale_factors[i]);\n        }\n        \n        transform_counts_to_common_scale(scale_factors, sample_compatible_count_table);\n        transform_counts_to_common_scale(scale_factors, sample_total_count_table);\n        \n        for (size_t fac_idx = 0; fac_idx < _factories.size(); ++fac_idx)\n        {\n            boost::shared_ptr<ReadGroupProperties> rg_props = _factories[fac_idx]->read_group_properties();\n            assert (scale_factors[fac_idx] != 0);\n            vector<LocusCount> common_scaled_compatible_counts;\n            vector<LocusCount> common_scaled_total_counts;\n            for (size_t j = 0; j < sample_compatible_count_table.size(); ++j)\n            {\n                common_scaled_compatible_counts.push_back(LocusCount(sample_compatible_count_table[j].locus_desc, sample_compatible_count_table[j].counts[fac_idx], sample_compatible_count_table[j].num_transcripts));\n            }\n            for (size_t j = 0; j < sample_total_count_table.size(); ++j)\n            {\n                common_scaled_total_counts.push_back(LocusCount(sample_total_count_table[j].locus_desc, sample_total_count_table[j].counts[fac_idx], sample_total_count_table[j].num_transcripts));\n            }\n            rg_props->common_scale_compatible_counts(common_scaled_compatible_counts);\n            rg_props->common_scale_total_counts(common_scaled_total_counts);\n        }\n        fit_dispersion_model();\n        */\n        \n    }\n\n    void fit_dispersion_model()\n    {\n        vector<LocusCountList> sample_compatible_count_table;\n        vector<LocusCountList> sample_total_count_table;\n        \n        vector<double> scale_factors;\n        \n        for (size_t fac_idx = 0; fac_idx < _factories.size(); ++fac_idx)\n        {\n            boost::shared_ptr<BundleFactory> fac = _factories[fac_idx];        \n            \n            boost::shared_ptr<ReadGroupProperties> rg_props = fac->read_group_properties();\n            const vector<LocusCount>& compatible_count_table = rg_props->common_scale_compatible_counts();\n            const vector<LocusCount>& total_count_table = rg_props->common_scale_total_counts();\n            \n            assert(compatible_count_table.size() == compatible_count_table.size());\n            \n            for (size_t i = 0; i < compatible_count_table.size(); ++i)\n            {\n                const LocusCount& c = compatible_count_table[i];\n                double common_scale_compatible_count = c.count;\n                double common_scale_total_count = total_count_table[i].count;\n                \n                if (i >= sample_compatible_count_table.size())\n                {\n                    LocusCountList locus_count(c.locus_desc, _factories.size(), c.num_transcripts, c.gene_ids, c.gene_short_names);\n                    sample_compatible_count_table.push_back(locus_count);\n                    sample_compatible_count_table.back().counts[0] = common_scale_compatible_count;\n                    sample_total_count_table.push_back(locus_count);\n                    sample_total_count_table.back().counts[0] = common_scale_total_count;\n                }\n                else\n                {\n                    if (sample_compatible_count_table[i].locus_desc != c.locus_desc)\n                    {\n                        fprintf (stderr, \"Error: bundle boundaries don't match across replicates!\\n\");\n                        exit(1);\n                    }\n                    sample_compatible_count_table[i].counts[fac_idx] = common_scale_compatible_count;\n                    sample_total_count_table[i].counts[fac_idx] = common_scale_total_count;\n                }\n            }\n            scale_factors.push_back(rg_props->internal_scale_factor());\n        }\n        \n        boost::shared_ptr<MassDispersionModel> disperser;\n        disperser = ::fit_dispersion_model(_condition_name, scale_factors, sample_compatible_count_table);\n        \n        vector<pair<double, double> > compatible_means_and_vars;\n        calculate_count_means_and_vars(sample_compatible_count_table,\n                                       compatible_means_and_vars);\n        \n        for (size_t i = 0; i < sample_compatible_count_table.size(); ++i)\n        {\n            const LocusCountList& p = sample_compatible_count_table[i];\n            double mean = compatible_means_and_vars[i].first;\n            double var = compatible_means_and_vars[i].second;\n            disperser->set_compatible_mean_and_var(p.locus_desc, make_pair(mean, var));\n            //labeled_mv_table[p.locus_desc] = make_pair(mean, var);\n        }\n        \n        vector<pair<double, double> > total_means_and_vars;\n        calculate_count_means_and_vars(sample_total_count_table,\n                                       total_means_and_vars);\n        \n        for (size_t i = 0; i < sample_total_count_table.size(); ++i)\n        {\n            const LocusCountList& p = sample_total_count_table[i];\n            double mean = total_means_and_vars[i].first;\n            double var = total_means_and_vars[i].second;\n            disperser->set_total_mean_and_var(p.locus_desc, make_pair(mean, var));\n            //labeled_mv_table[p.locus_desc] = make_pair(mean, var);\n        }\n\n        \n        BOOST_FOREACH (boost::shared_ptr<BundleFactory> fac, _factories)\n        {\n            boost::shared_ptr<ReadGroupProperties> rg_props = fac->read_group_properties();\n            rg_props->mass_dispersion_model(disperser);\n        }\n    }\n    \n    \n    // This function NEEDS to deep copy the ref_mRNAs, otherwise cuffdiff'd\n    // samples will clobber each other\n    void set_ref_rnas(const vector<boost::shared_ptr<Scaffold> >& mRNAs, bool deep_copy = true)\n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_rep_factory_lock);\n#endif\n        BOOST_FOREACH(boost::shared_ptr<BundleFactory> fac, _factories)\n        {\n            fac->set_ref_rnas(mRNAs, deep_copy);\n        }\n    }\n    \n    void set_mask_rnas(const vector<boost::shared_ptr<Scaffold> >& mRNAs)\n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_rep_factory_lock);\n#endif\n        BOOST_FOREACH(boost::shared_ptr<BundleFactory> fac, _factories)\n        {\n            fac->set_mask_rnas(mRNAs);\n        }\n    }\n    \n    int num_replicates() const { return _factories.size(); }\n    \n    void mass_dispersion_model(boost::shared_ptr<MassDispersionModel const> disperser)\n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_rep_factory_lock);\n#endif\n        BOOST_FOREACH(boost::shared_ptr<BundleFactory>& fac, _factories)\n        {\n            fac->read_group_properties()->mass_dispersion_model(disperser);\n        }\n    }\n    \n    boost::shared_ptr<MassDispersionModel const> mass_dispersion_model() const\n    {\n        return _factories.front()->read_group_properties()->mass_dispersion_model();\n    }\n    \n    void mle_error_model(boost::shared_ptr<MleErrorModel const> mle_model)\n    {\n#if ENABLE_THREADS\n        boost::mutex::scoped_lock lock(_rep_factory_lock);\n#endif\n        BOOST_FOREACH(boost::shared_ptr<BundleFactory>& fac, _factories)\n        {\n            fac->read_group_properties()->mle_error_model(mle_model);\n        }\n    }\n    \n    boost::shared_ptr<MleErrorModel const> mle_error_model() const\n    {\n        return _factories.front()->read_group_properties()->mle_error_model();\n    }\n    \nprivate:\n\tvector<boost::shared_ptr<BundleFactory> > _factories;\n#if ENABLE_THREADS\n    boost::mutex _rep_factory_lock;\n#endif\n    string _condition_name; \n};\n\nvoid normalize_counts(std::vector<boost::shared_ptr<ReadGroupProperties> > & all_read_groups);\n"
  },
  {
    "path": "src/rounding.h",
    "content": "// rounding-algorithms.hpp\n//\n// General Rounding Algorithms\n// Copyright (c) 2008 Michael Thomas Greer\n// Boost Software License - Version 1.0 - August 17th, 2003\n//\n// Permission is hereby granted, free of charge, to any person or organization\n// obtaining a copy of the software and accompanying documentation covered by\n// this license (the \"Software\") to use, reproduce, display, distribute,\n// execute, and transmit the Software, and to prepare derivative works of the\n// Software, and to permit third-parties to whom the Software is furnished to\n// do so, all subject to the following:\n//\n// The copyright notices in the Software and this entire statement, including\n// the above license grant, this restriction and the following disclaimer,\n// must be included in all copies of the Software, in whole or in part, and\n// all derivative works of the Software, unless such copies or derivative\n// works are solely in the form of machine-executable object code generated by\n// a source language processor.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n// DEALINGS IN THE SOFTWARE.\n//\n//----------------------------------------------------------------------------\n// Reference\n// <http://www.pldesignline.com/howto/showArticle.jhtml;?articleID=175801189>\n//\n//----------------------------------------------------------------------------\n// In this library, symmetric functions are indicated by a zero at the end\n// of the function name.\n//\n// If you want a different default epsilon make sure to change\n//\n//   #define ROUNDING_EPSILON 0.001\n//\n// to whatever you want it to be. (I wanted to make it so that you could \n// define a different default epsilon each time you #included the file, but\n// I haven't figured out how to get around the template restrictions yet.)\n//\n\n#ifndef ROUNDING_ALGORITHMS_HPP\n#define ROUNDING_ALGORITHMS_HPP\n\n#ifndef ROUNDING_EPSILON\n#define ROUNDING_EPSILON 0.0000001\n#endif\n\n#include <cmath>\n#include <cstdlib>\n#include <ciso646>\n\nnamespace rounding\n{\n    \n    //--------------------------------------------------------------------------\n    // round down\n    // Bias: -Infinity\n    using std::floor;\n    \n    //--------------------------------------------------------------------------\n    // round up\n    // Bias: +Infinity\n    using std::ceil;\n    \n    //--------------------------------------------------------------------------\n    // symmetric round down\n    // Bias: towards zero\n    template <typename FloatType>\n    FloatType floor0( const FloatType& value )\n    {\n        FloatType result = std::floor( std::fabs( value ) );\n        return (value < 0.0) ? -result : result;\n    }\n    \n    //--------------------------------------------------------------------------\n    // A common alias for floor0()\n    // (notwithstanding hardware quirks)\n    template <typename FloatType>\n    inline\n    FloatType trunc( const FloatType& value )\n    {\n        return floor0( value );\n    }\n    \n    //--------------------------------------------------------------------------\n    // symmetric round up\n    // Bias: away from zero\n    template <typename FloatType>\n    FloatType ceil0( const FloatType& value )\n    {\n        FloatType result = std::ceil( std::fabs( value ) );\n        return (value < 0.0) ? -result : result;\n    }\n    \n    //--------------------------------------------------------------------------\n    // Common rounding: round half up\n    // Bias: +Infinity\n    template <typename FloatType>\n    FloatType roundhalfup( const FloatType& value )\n    {\n        return std::floor( value +0.5 );\n    }\n    \n    //--------------------------------------------------------------------------\n    // Round half down\n    // Bias: -Infinity\n    template <typename FloatType>\n    FloatType roundhalfdown( const FloatType& value )\n    {\n        return std::ceil( value -0.5 );\n    }\n    \n    //--------------------------------------------------------------------------\n    // symmetric round half down\n    // Bias: towards zero\n    template <typename FloatType>\n    FloatType roundhalfdown0( const FloatType& value )\n    {\n        FloatType result = roundhalfdown( std::fabs( value ) );\n        return (value < 0.0) ? -result : result;\n    }\n    \n    //--------------------------------------------------------------------------\n    // symmetric round half up\n    // Bias: away from zero\n    template <typename FloatType>\n    FloatType roundhalfup0( const FloatType& value )\n    {\n        FloatType result = roundhalfup( std::fabs( value ) );\n        return (value < 0.0) ? -result : result;\n    }\n    \n    //--------------------------------------------------------------------------\n    // round half even (banker's rounding)\n    // Bias: none\n    template <typename FloatType>\n    FloatType roundhalfeven(\n                            const FloatType& value,\n                            const FloatType& epsilon = ROUNDING_EPSILON\n                            ) {\n        if (value < 0.0) return -roundhalfeven <FloatType> ( -value, epsilon );\n        \n        FloatType ipart;\n        std::modf( value, &ipart );\n        \n        // If 'value' is exctly halfway between two integers\n        if ((value -(ipart +0.5)) < epsilon)\n        {\n            // If 'ipart' is even then return 'ipart'\n            if (std::fmod( ipart, 2.0 ) < epsilon)\n                return ipart;\n            \n            // Else return the nearest even integer\n            return ceil0( ipart +0.5 );\n        }\n        \n        // Otherwise use the usual round to closest\n        // (Either symmetric half-up or half-down will do0\n        return roundhalfup0( value );\n    }\n        \n    //--------------------------------------------------------------------------\n    // round random\n    // Bias: generator's bias\n    template <typename FloatType, typename RandValue, typename RandomGenerator>\n    FloatType roundrandom(\n                          const FloatType& value,\n                          const RandValue& mid,\n                          RandomGenerator& g\n                          ) {\n        if (g() < mid)\n            return roundhalfup0( value );\n        return roundhalfdown0( value );\n    }\n    \n    //--------------------------------------------------------------------------\n    // default round random\n    // Bias: rand()\n    template <typename FloatType>\n    FloatType roundrandom( const FloatType& value )\n    {\n        return roundrandom <FloatType, int, int(*)()> ( value, RAND_MAX /2, &rand );\n    }\n}\n\n#endif \n"
  },
  {
    "path": "src/sampling.cpp",
    "content": "//\n//  sampling.cpp\n//  cufflinks\n//\n//  Created by Cole Trapnell on 12/19/11.\n//  Copyright 2011 __MyCompanyName__. All rights reserved.\n//\n\n#include \"sampling.h\"\n#include <limits>\n\nusing namespace std;\n\nvoid generate_importance_samples(multinormal_generator<double>& generator,\n                                 std::vector<Eigen::VectorXd>& samples, \n                                 int num_samples,\n                                 bool no_zeros)\n{\n\tfor (int i = 0; i < num_samples; ++i)\n\t{\n        // TODO: we should switch the multinormal generator over to Eigen for\n        // consistency as part of the push to drop uBLAS.\n\t\tboost::numeric::ublas::vector<double> r = generator.next_rand();\n        \n        Eigen::VectorXd scaled_sample = Eigen::VectorXd::Zero(r.size());\n\t\t\n\t\tfor (int j = 0; j < scaled_sample.size(); ++j) \n        {\n            scaled_sample(j) = r(j);\n            \n            if (scaled_sample(j) < 0)\n            {\n                scaled_sample(j) = 0.0;\n                //scaled_sample(j) = -scaled_sample(j);\n            }\n\t\t}\n\t\t\n\t\tdouble m = scaled_sample.sum();\n\t\tif (m && !isnan(m))\n\t\t{\n\t\t\tfor (int j = 0; j < scaled_sample.size(); ++j) \n            {\n\t\t\t\tscaled_sample(j) = scaled_sample(j) / m;\n\t\t\t}\n\t\t\tif (no_zeros)\n            {\n                bool has_zero = false;\n                for (int j = 0; j < scaled_sample.size(); ++j)\n                {\n                    if (scaled_sample[j] == 0)\n                    {\n                        has_zero = true;\n                        break;\n                    }\n                }\n                \n                if (has_zero)\n                    continue;\n            }\n\t\t\tsamples.push_back(scaled_sample);\n\t\t}\n\t\telse\n\t\t{\n            samples.push_back(Eigen::VectorXd::Zero(scaled_sample.size()));\n\t\t\t//cerr << r << endl;\n\t\t\t//cerr << scaled_sample << endl;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/sampling.h",
    "content": "#ifndef SAMPLING_H\n#define SAMPLING_H\n//\n//  sampling.h\n//  cufflinks\n//\n//  Created by Cole Trapnell on 12/19/11.\n//  Copyright 2011 Cole Trapnell. All rights reserved.\n//\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include \"common.h\"\n\n#include <stdint.h>\n#include <vector>\n#include <iostream>\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/vector.hpp>\n\n#include <boost/numeric/ublas/vector_proxy.hpp>\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/triangular.hpp>\n\n//#define BOOST_UBLAS_TYPE_CHECK 0\n#include <boost/numeric/ublas/lu.hpp>\n\n#include <boost/numeric/ublas/io.hpp>\n\n#include <boost/random/mersenne_twister.hpp>\n#include <boost/random/normal_distribution.hpp>\n#include <boost/random/uniform_int.hpp>\n#include <boost/random/variate_generator.hpp>\n#include <boost/math/constants/constants.hpp>\n\n#include <Eigen/Dense>\n\n// Boost Cholesky factorizations in the spirit of lu.hpp\n// Written by Robbie Vogt, found at: \n// http://lists.boost.org/MailArchives/ublas/2005/07/0568.php\n\nnamespace boost { namespace numeric { namespace ublas {\n\t\n\t// Cholesky factorization\n\ttemplate<class M>\n\tdouble cholesky_factorize (M &m) \n\t{\n\t\ttypedef M matrix_type;\n\t\ttypedef typename M::size_type size_type;\n\t\ttypedef typename M::value_type value_type;\n\t\t\n\t\tBOOST_UBLAS_CHECK (m.size1() == m.size2(), external_logic(\"Cholesky decomposition is only valid for a square, positive definite matrix.\"));\n\t\t\n\t\tsize_type size = m.size1();\n\t\tvector<value_type> d(size);\n\t\t//bool positive_definite = true;\n\t\tfor (size_type i = 0; i < size; ++ i) {\n\t\t\tmatrix_row<M> mri (row (m, i));\n\t\t\tfor (size_type j = i; j < size; ++ j) {\n\t\t\t\tmatrix_row<M> mrj (row (m, j));\n\t\t\t\t\n\t\t\t\tvalue_type elem = m(i,j) - inner_prod(project(mri,range(0,i)), project(mrj,range(0,i)));\n\t\t\t\t\n\t\t\t\tif (i == j) {\n\t\t\t\t\tif (elem <= 0.0) {\n//                        std::cerr << \"intermediate: \" << std::endl;\n//                        for (unsigned k = 0; k < m.size1 (); ++k) \n//                        {\n//                            ublas::matrix_row<ublas::matrix<double> > mr (m, k);\n//                            std::cerr << k << \" : \" << mr << std::endl;\n//                        }\n//                        std::cerr << \"======\" << std::endl;\n//                        std::cerr << i << \" , \" << j << \" = \" << m(i,j) << std::endl; \n//                        std::cerr << project(mri,range(0,i)) << std::endl;\n//                        std::cerr << project(mrj,range(0,i)) << std::endl;\n//                        std::cerr << inner_prod(project(mri,range(0,i)), project(mrj,range(0,i))) << std::endl;\n\t\t\t\t\t\t// matrix after rounding errors is not positive definite\n\t\t\t\t\t\treturn elem;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\td(i) = sqrtl(elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tm(j,i) = elem / d(i);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// put the diagonal back in\n\t\tfor (size_type i = 0; i < size; ++ i) {\n\t\t\tm(i,i) = d(i);\n\t\t}\n\t\t\n\t\t//cerr << m << endl;\n\t\tfor (size_type i = 0; i < size; ++i) {\n\t\t\tfor (size_type j = 0; j < i; ++j)\n\t\t\t{\n\t\t\t\tm(j,i) = 0;\n\t\t\t}\n\t\t}\n\t\t//cerr << m << endl;\n\t\t// decomposition succeeded\n\t\treturn 0.0;\n\t}\n\t\n\t\n\t// Cholesky substitution \n\ttemplate<class M, class E> \n\tvoid cholesky_substitute (const M &m, vector_expression<E> &e) { \n\t\ttypedef const M const_matrix_type; \n\t\ttypedef vector<typename E::value_type> vector_type; \n\t\tinplace_solve (m, e, lower_tag ()); \n\t\tinplace_solve (trans(m), e, upper_tag ()); \n\t} \n\ttemplate<class M, class E> \n\tvoid cholesky_substitute (const M &m, matrix_expression<E> &e) { \n\t\ttypedef const M const_matrix_type; \n\t\ttypedef matrix<typename E::value_type> matrix_type; \n\t\tinplace_solve (m, e, lower_tag ()); \n\t\tinplace_solve (trans(m), e, upper_tag ()); \n\t} \n\ttemplate<class E, class M> \n\tvoid cholesky_substitute_left (vector_expression<E> &e, const M &m) { \n\t\ttypedef const M const_matrix_type; \n\t\ttypedef vector<typename E::value_type> vector_type; \n\t\tinplace_solve (trans(m), e, upper_tag ()); \n\t\tinplace_solve (m, e, lower_tag ()); \n\t} \n\ttemplate<class E, class M> \n\tvoid cholesky_substitute_left (matrix_expression<E> &e, const M &m) { \n\t\ttypedef const M const_matrix_type; \n\t\ttypedef matrix<typename E::value_type> matrix_type; \n\t\tinplace_solve (trans(m), e, upper_tag ()); \n\t\tinplace_solve (m, e, lower_tag ()); \n\t} \n\t// Cholesky matrix inversion \n\ttemplate<class M> \n\tvoid cholesky_invert (M &m) \n\t{ \n\t\ttypedef typename M::size_type size_type; \n\t\ttypedef typename M::value_type value_type; \n\t\tsize_type size = m.size1(); \n\t\t// determine the inverse of the lower traingular matrix \n\t\tfor (size_type i = 0; i < size; ++ i) { \n\t\t\tm(i,i) = 1 / m(i,i); \n\t\t\tfor (size_type j = i+1; j < size; ++ j) { \n\t\t\t\tvalue_type elem(0); \n\t\t\t\tfor (size_type k = i; k < j; ++ k) { \n\t\t\t\t\telem -= m(j,k)*m(k,i); \n\t\t\t\t} \n\t\t\t\tm(j,i) = elem / m(j,j); \n\t\t\t} \n\t\t} \n\t\t// multiply the upper and lower inverses together \n\t\tm = prod(trans(triangular_adaptor<M,lower>(m)), triangular_adaptor<M,lower>(m)); \n\t} \n\t\n\t\n}}}\n\n/* Matrix inversion routine.\n Uses lu_factorize and lu_substitute in uBLAS to invert a matrix */\ntemplate<class T>\nbool lu_invert_matrix (const boost::numeric::ublas::matrix<T>& input, boost::numeric::ublas::matrix<T>& inverse) {\n \tusing namespace boost::numeric::ublas;\n    typedef permutation_matrix<std::size_t> pmatrix;\n \t// create a working copy of the input\n \tmatrix<T> A(input);\n \t// create a permutation matrix for the LU-factorization\n \tpmatrix pm(A.size1());\n\t\n \t// perform LU-factorization\n \tint res = lu_factorize(A,pm);\n\tif( res != 0 ) return false;\n\t\n \t// create identity matrix of \"inverse\"\n \tinverse.assign(boost::numeric::ublas::identity_matrix<T>(A.size1()));\n\t\n \t// backsubstitute to get the inverse\n \tlu_substitute(A, pm, inverse);\n\t\n \treturn true;\n}\n\n///* Matrix inversion routine.\n// Expects input to be PRE-FACTORIZED */\ntemplate<class T>\nbool chol_invert_matrix (const boost::numeric::ublas::matrix<T>& input, boost::numeric::ublas::matrix<T>& inverse) {\n\t\n \tusing namespace boost::numeric::ublas;\n\tinverse = input;\n\t\n\tcholesky_invert(inverse);\n\t\n \treturn true;\n}\n\n\n// Adapted for Boost from Numerical Recipes\ntemplate<typename ValueType>\nclass multinormal_generator\n{\n\ttypedef boost::mt19937 base_generator_type;\n\ttypedef boost::normal_distribution<> distribution_type;\n    \npublic:\n\t// expects the mean vector and the *CHOLESKY* factorization of the covariance\n\tmultinormal_generator(const boost::numeric::ublas::vector<ValueType>& mean,\n\t\t\t\t\t\t  const boost::numeric::ublas::matrix<ValueType>& chol_cov)\n    :\t\n    _engine(random_seed),\n    _distribution(),\n    _generator(boost::variate_generator<base_generator_type&, \n               distribution_type >(_engine, \n                                   _distribution))\n\t{\n\t\t_rand = boost::numeric::ublas::zero_vector<ValueType>(mean.size());\n\t\t_mean = mean; \n\t\t_cholesky = chol_cov;\n\t}\n\t\n\tconst boost::numeric::ublas::vector<ValueType>& next_rand()\n\t{\n\t\tboost::numeric::ublas::vector<ValueType> temp(_mean.size());\n\t\tfor (size_t i = 0; i < _mean.size(); ++i)\n\t\t{\n\t\t\tdouble r = _generator();\n\t\t\ttemp(i) = r;\n\t\t\t_rand(i) = 0.0;\n\t\t}\n\t\t\n\t\t//cerr << \"rand =\"<<temp << endl;\n\t\t//_rand = prod(ublas::triangular_adaptor<ublas::matrix<ValueType>,ublas::lower>(_cholesky), temp);\n\t\tfor (size_t i = 0; i < _cholesky.size1(); ++i)\n\t\t{\n\t\t\tfor (size_t j = 0; j <= i; ++j)\n\t\t\t{\n\t\t\t\t_rand(i) += _cholesky(i,j) * temp(j);\n\t\t\t}\n\t\t}\n\t\t//cerr <<_rand << \" + \" << _mean << \"=\";\n\t\t_rand = _rand + _mean;\n\t\t//cerr <<_rand <<endl;\n\t\t\n\t\treturn _rand;\n\t}\n    \n    void set_parameters(const boost::numeric::ublas::vector<ValueType>& mean,\n                        const boost::numeric::ublas::matrix<ValueType>& chol_cov)\n    {\n        _rand = boost::numeric::ublas::zero_vector<ValueType>(mean.size());\n\t\t_mean = mean; \n\t\t_cholesky = chol_cov;\n    }\n\t\nprivate:\n\tboost::numeric::ublas::vector<ValueType>\t\t_rand;\n\tboost::numeric::ublas::vector<ValueType>\t\t_mean;\n\tboost::numeric::ublas::matrix<ValueType>\t\t_cholesky;\n\t\n\tbase_generator_type\t\t\t\t\t\t\t\t_engine;\n\tdistribution_type\t\t\t\t\t\t\t\t_distribution;\n\tboost::variate_generator<base_generator_type&, \n    distribution_type>\t\t_generator;\n};\n\n// expects a cholesky factorized covariance matrix\ntemplate<class matrix_T>\ndouble determinant(boost::numeric::ublas::matrix_expression<matrix_T> const& mat_r)\n{\n\tdouble det = 1.0;\n\t\n\tmatrix_T chol(mat_r());\n\t\n\tfor (size_t i = 0; i < chol.size1(); ++i)\n\t{\n\t\tdet *= chol(i,i);\n\t}\n\t\n\treturn det * det;\n}\n\n\n// Given log(p) and log(q) returns log(p+q)double\ntemplate<class float_type>\nfloat_type log_space_add(float_type log_p, float_type log_q)\n{\n\tif (log_p < log_q)\n\t{\n\t\tfloat_type tmp = log_p;\n\t\tlog_p = log_q;\n\t\tlog_q = tmp;\n\t}\n    \n\tassert (log_p >= log_q);\n\treturn log (1.0 + exp(log_q - log_p)) + log_p;\n}\n\nvoid generate_importance_samples(multinormal_generator<double>& generator,\n                                 std::vector<Eigen::VectorXd>& samples, \n                                 int num_samples,\n                                 bool no_zeros = true);\n\n#endif\n"
  },
  {
    "path": "src/scaffold_graph.cpp",
    "content": "/*\n *  scaffold_graph.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 6/2/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <vector>\n#include \"scaffold_graph.h\"\n#include \"scaffolds.h\"\n\n#include <boost/graph/depth_first_search.hpp>\n#include <boost/graph/visitors.hpp>\n\n#ifndef NDEBUG\n#include \"transitive_reduction.h\"\n#endif\n\nusing namespace std;\nusing namespace boost;\n\nstruct HitBufBasket\n{\n\tHitBufBasket(int coord, Scaffold* h, DAGNode d)\n    : expiration_coord(coord), hit(h), node(d) {}\n\tint expiration_coord;\n\tScaffold* hit;\n\tDAGNode node;\n};\n\n\n\nbool right_lt (const HitBufBasket& lhs, \n\t\t\t   const HitBufBasket& rhs)\n{\n\treturn lhs.expiration_coord < rhs.expiration_coord;\n}\n\nstruct Expired\n{\n\tExpired(int ec) : expiration_coord(ec) {}\n\tbool operator()(const HitBufBasket& lhs)\n\t{\n\t\treturn lhs.expiration_coord <= expiration_coord;\n\t}\n\t\n\tint expiration_coord;\n};\n\nenum ConnectState { UNKNOWN, CONNECT, DONT_CONNECT };\n\ntemplate <class CompatibilityMap, class ConnectMap,  class Tag>\nstruct connect_visitor\n: public base_visitor<connect_visitor<CompatibilityMap, ConnectMap,  Tag> >\n{\n    typedef Tag event_filter;\n    connect_visitor(CompatibilityMap compatibility, ConnectMap connect, DAGNode t) \n    : _connect(connect),_compatibility(compatibility), _target(t) { }\n\t\n    template <class Vertex, class Graph>\n    void operator()(Vertex u, const Graph& g)\n\t{\n\t\ttypedef graph_traits<Graph> GraphTraits;\n\t\t\n\t\ttypename GraphTraits::adjacency_iterator v, vend;\n\t\t\n\t\tif (_compatibility[u] == true)\n\t\t{\n\t\t\tfor (tie(v,vend) = adjacent_vertices(u, g); v != vend; ++v)\n\t\t\t{\n\t\t\t\tif (_compatibility[*v])\n\t\t\t\t{\n\t\t\t\t\t//fprintf(stderr, \"Avoiding a redundant edge from %d to %d\\n\", u, *v);\n\t\t\t\t\t_connect[u] = DONT_CONNECT;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// If we get here, u is compatible with the target, but has no\n\t\t\t// compatible successors, so it's safe to add the edge after the DFS\n\t\t\t_connect[u] = CONNECT;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_connect[u] = DONT_CONNECT;\n\t\t}\n\t\t//put(_compat, v, compatible);\n    }\n\t\n    ConnectMap _connect;\n\tCompatibilityMap _compatibility;\n\tDAGNode _target;\n};\n\ntemplate <class CompatibilityMap, class ConnectMap, class Tag>\nconnect_visitor<CompatibilityMap, ConnectMap, Tag>\nrecord_connections(CompatibilityMap compatibility, \n\t\t\t\t   ConnectMap connect, \n\t\t\t\t   DAGNode target, \n\t\t\t\t   Tag) \n{\n    return connect_visitor<CompatibilityMap, ConnectMap, Tag> (compatibility, connect, target);\n}\n\n\nbool create_overlap_dag(vector<Scaffold>& hits,\n                        DAG& bundle_dag)\n{\n    bundle_dag = DAG();\n\tvector<Scaffold>::iterator hi =  hits.begin();\n\tbool found_compatible_scaffolds = false;\n\t\n\ttypedef list<HitBufBasket> HitBuf;\n\tHitBuf hit_buf;\n\t\n\tHitsForNodeMap hits_for_node = get(vertex_name, bundle_dag);\n\t\n\twhile (hi != hits.end())\n\t{\n\t\tint new_left = hi->left();\n\t\tint new_right = hi->right();\n        \n        //fprintf(stderr, \"Adding to hit buffer: [%d, %d)\\n\", new_left, new_right);\n        \n\t\tHitBufBasket new_basket(new_right, &(*hi), add_vertex(bundle_dag));\n\t\thits_for_node[new_basket.node] = new_basket.hit;\n\t\t\n\t\tHitBuf::iterator new_end = remove_if(hit_buf.begin(), \n\t\t\t\t\t\t\t\t\t\t\t hit_buf.end(), \n\t\t\t\t\t\t\t\t\t\t\t Expired(new_left));\n\t\t\n\t\thit_buf.erase(new_end, hit_buf.end());\n        \n\t\t// Now check the each hit in the buffer for compatibility with this\n\t\t// new one\n\t\t\n\t\tvector<const Scaffold*> containing_hits;\n\t\t\n\t\tboost::vector_property_map<bool> c(num_vertices(bundle_dag));\n\t\tboost::vector_property_map<ConnectState> connected(num_vertices(bundle_dag));\n        \n\t\tfor (HitBuf::iterator bi = hit_buf.begin();\n\t\t\t bi != hit_buf.end();\n\t\t\t ++bi)\n\t\t\t\n\t\t{\n\t\t\tconst Scaffold& lhs = *(bi->hit);\n\t\t\tconst Scaffold& rhs = *(new_basket.hit);\n            \n\t\t\tassert (lhs.left() <= rhs.left());\n\t\t\tif (!lhs.contains(rhs))\n\t\t\t{\n                //fprintf(stderr, \"Checking [%d, %d) and [%d, %d)\\n\", lhs.left(), lhs.right(), rhs.left(), rhs.right());\n\t\t\t\tif (Scaffold::compatible(lhs, rhs))\n\t\t\t\t{\n\t\t\t\t\tc[bi->node] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tfor (HitBuf::iterator bi = hit_buf.begin();\n\t\t\t bi != hit_buf.end();\n\t\t\t ++bi)\n\t\t\t\n\t\t{\n\t\t\tif (connected[bi->node] == UNKNOWN)\n\t\t\t{\n\t\t\t\tdepth_first_search(bundle_dag,\n\t\t\t\t\t\t\t\t   root_vertex(bi->node).\n\t\t\t\t\t\t\t\t   visitor(make_dfs_visitor(make_pair(record_connections(c, connected, new_basket.node, on_finish_vertex()), null_visitor()))));\n\t\t\t}\n\t\t}\n\t\t\n\t\tfor (HitBuf::iterator bi = hit_buf.begin();\n\t\t\t bi != hit_buf.end();\n\t\t\t ++bi)\n\t\t{\n\t\t\tif (connected[bi->node] == CONNECT)\n\t\t\t{ \n\t\t\t\tadd_edge(bi->node, new_basket.node, bundle_dag);\n\t\t\t\tfound_compatible_scaffolds = true;\n\t\t\t}\n\t\t}\n\t\t\n\t\thit_buf.push_back(new_basket);\n\t\t\n\t\t++hi;\n\t}\n\t\n\tvector<bool> has_parent(num_vertices(bundle_dag), false);\n\tvector<bool> has_child (num_vertices(bundle_dag), false);\n\t\n\tgraph_traits < DAG >::vertex_iterator u, uend;\n\tfor (tie(u, uend) = vertices(bundle_dag); u != uend; ++u)\n\t{\n\t\tgraph_traits < DAG >::adjacency_iterator v, vend;\n\t\tfor (tie(v,vend) = adjacent_vertices(*u, bundle_dag); v != vend; ++v)\n\t\t{\n\t\t\tDAGNode U = *u;\n\t\t\tDAGNode V = *v;\n\t\t\thas_parent[V] = true;\n\t\t\thas_child[U] = true;\n\t\t}\n\t}\n\t\n#ifdef DEBUG\n\tset<const Scaffold*> introns;\n#endif\n\tfor (size_t i = 0; i < num_vertices(bundle_dag); ++i)\n\t{\n\t\tif (has_child[i])\n\t\t\tcontinue;\n\t\tconst Scaffold* hit_i = hits_for_node[i];\n        \n\t\tfor (size_t j = 0; j < num_vertices(bundle_dag); ++j)\n\t\t{\n\t\t\tif (has_parent[j])\n\t\t\t\tcontinue;\n\t\t\tconst Scaffold* hit_j = hits_for_node[j];\n\t\t\tif (hit_i->right() < hit_j->left() &&\n\t\t\t\thit_j->left() - hit_i->right() < olap_radius)\n\t\t\t{\n\t\t\t\tadd_edge(i, j, bundle_dag);\n\t\t\t}\n\t\t}\n\t}\n    \n#ifndef NDEBUG\n    DAG tr;\n    boost::vector_property_map<DAGNode> G_to_TR;\n    property_map<DAG, vertex_index_t>::type w = get(vertex_index, bundle_dag);\n    transitive_reduction(bundle_dag, \n                         tr, \n                         G_to_TR,\n                         w);\n    verbose_msg(\"dag has %lu edges, tr has %lu edges\\n\", num_edges(bundle_dag), num_edges(tr));\n    \n\t//assert (num_edges(bundle_dag) == num_edges(tr));\n#endif\n    \n\treturn found_compatible_scaffolds;\n}\n\npair<DAGNode, DAGNode> add_terminal_nodes(DAG& bundle_dag)\n{\n    vector<char> has_parent(num_vertices(bundle_dag) + 2, false);\n    vector<char> has_child (num_vertices(bundle_dag) + 2, false);\n    \n    graph_traits < DAG >::vertex_iterator u, uend;\n    for (tie(u, uend) = vertices(bundle_dag); u != uend; ++u)\n    {\n        graph_traits < DAG >::adjacency_iterator v, vend;\n        for (tie(v,vend) = adjacent_vertices(*u, bundle_dag); v != vend; ++v)\n        {\n            DAGNode U = *u;\n            DAGNode V = *v;\n            has_parent[V] = true;\n            has_child[U] = true;\n        }\n    }\n    \n    DAGNode source = add_vertex(bundle_dag);\n    DAGNode sink = add_vertex(bundle_dag);\n    \n    int num_attached_to_source = 0;\n    int num_attached_to_sink = 0;\n    \n    for (size_t i = 0; i < num_vertices(bundle_dag); ++i)\n    {\n        if (!has_parent[i] && i != sink && i != source)\n        {\n            num_attached_to_source++;\n            add_edge(source, i, bundle_dag);\n        }\n        if (!has_child[i] && i != source && i != sink)\n        {\n            num_attached_to_sink++;\n            add_edge(i, sink, bundle_dag);\n        }\n    }\n    \n#if verbose_msg\n    HitsForNodeMap hits_for_node = get(vertex_name, bundle_dag);\n    DAG::vertex_iterator ki, ke;\n\tfor (tie(ki, ke) = vertices(bundle_dag); ki != ke; ++ki)\n\t{\n        if (edge(source, *ki, bundle_dag).second)\n        {\n            const Scaffold* pS = hits_for_node[*ki];\n            fprintf(stderr, \"%d-%d has edge from source\\n\", pS->left(), pS->right());\n        }\n        \n        if (edge(*ki, sink, bundle_dag).second)\n        {\n            const Scaffold* pS = hits_for_node[*ki];\n            fprintf(stderr, \"%d-%d has edge to sink\\n\", pS->left(), pS->right());\n        }\n    }\n    verbose_msg(\"%d source nodes, %d sink nodes\\n\", num_attached_to_source, num_attached_to_sink);\n#endif\n    return make_pair(source, sink);\n}\n"
  },
  {
    "path": "src/scaffold_graph.h",
    "content": "#ifndef SCAFFOLD_GRAPH_H\n#define SCAFFOLD_GRAPH_H\n/*\n *  scaffold_graph.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 6/2/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <vector>\n#include <utility>\n#include <boost/graph/adjacency_list.hpp>\n#include <boost/graph/graph_traits.hpp>\n\n#include <boost/version.hpp>\n\n#if (BOOST_VERSION < 103800)\n#include <boost/vector_property_map.hpp>\n#else\n#include <boost/property_map/vector_property_map.hpp>\n#endif\n\nclass Scaffold;\n\ntypedef boost::adjacency_list<boost::vecS, \n                              boost::vecS, \n                              boost::bidirectionalS, \n                              boost::property<boost::vertex_name_t, Scaffold*> > DAG;\n\ntypedef boost::graph_traits<DAG>::vertex_descriptor DAGNode;\n\ntypedef boost::property_map<DAG, boost::vertex_name_t>::type HitsForNodeMap;\n\nbool create_overlap_dag(std::vector<Scaffold>& hits, DAG& bundle_dag);\nstd::pair<DAGNode, DAGNode> add_terminal_nodes(DAG& bundle_dag);\n\n#endif\n"
  },
  {
    "path": "src/scaffolds.cpp",
    "content": "/*\n *  scaffolds.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/30/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <list>\n#include <algorithm>\n#include <numeric>\n#include \"common.h\"\n#include \"scaffolds.h\"\n\nusing namespace std;\n\nbool AugmentedCuffOp::compatible(const AugmentedCuffOp& lhs,\n\t\t\t\t\t\t\t\t const AugmentedCuffOp& rhs,\n\t\t\t\t\t\t\t\t int overhang_tolerance)\n{\n\tif (rhs.opcode == CUFF_INTRON)\n\t{\n\t\tif (lhs.opcode == CUFF_INTRON)\n\t\t{ \n\t\t\tif (lhs != rhs /*&& !(lhs.genomic_length == rhs.genomic_length && \n\t\t\t\t\t\t\t   abs(lhs.genomic_offset - rhs.genomic_offset) < 2)*/)\n\t\t\t\treturn false;\n\t\t}\n\t\telse if (lhs.opcode == CUFF_UNKNOWN)\n\t\t{\n            //int left_diff = abs(lhs.g_left() - rhs.g_left());\n            //int right_diff = abs(lhs.g_right() - rhs.g_right());\n\t\t\t//if (left_diff + right_diff > max_frag_len)\n            //    return false;\n        }\n        else\n        {\n            int l_match = match_length(lhs, rhs.g_left(), rhs.g_right());\n            if (l_match > overhang_tolerance)\n            {\n                return false;\n            }\n        }\n\t}\n\telse if (rhs.opcode == CUFF_UNKNOWN)\n\t{\n        int l_match = match_length(lhs, rhs.g_left(), rhs.g_right());\n\t\tif (l_match > max_frag_len)\n\t\t\treturn false;\n\t}\n\n\tif (lhs.opcode == CUFF_INTRON)\n\t{\n\t\tif (rhs.opcode == CUFF_INTRON)\n\t\t{\n\t\t\tif (lhs != rhs /*&& !(lhs.genomic_length == rhs.genomic_length && \n\t\t\t\t\t\t\t  abs(lhs.genomic_offset - rhs.genomic_offset) < 2)*/)\n\t\t\t\treturn false;\n\t\t}\n\t\telse if (lhs.opcode == CUFF_UNKNOWN)\n\t\t{\n            //int left_diff = abs(lhs.g_left() - rhs.g_left());\n            //int right_diff = abs(lhs.g_right() - rhs.g_right());\n            //if (left_diff + right_diff > max_frag_len)\n            //    return false;\n\t\t}\n\t\telse \n        {\n            int r_match = match_length(rhs, lhs.g_left(), lhs.g_right());\n            if (r_match > overhang_tolerance)\n            {\n                return false;\n            }\n        }\n\t}\t\n\telse if (lhs.opcode == CUFF_UNKNOWN)\n\t{\n        int r_match = match_length(rhs, lhs.g_left(), lhs.g_right());\n\t\tif (r_match > max_frag_len)\n\t\t\treturn false;\n\t}\n\t\n\treturn true;\n}\n\nbool AugmentedCuffOp::g_left_lt(const AugmentedCuffOp& lhs,\n                                const AugmentedCuffOp& rhs)\n{\n\treturn lhs.g_left() < rhs.g_left();\n}\n\nvoid disjoint_ops(vector<AugmentedCuffOp>& to_reduce)\n{\n\tif (to_reduce.empty())\n\t\treturn;\n\t\n\tvector<AugmentedCuffOp> reduced;\n\treduced.push_back(to_reduce.front());\n\tfor (int i = 1; i < (int)to_reduce.size(); ++i)\n\t{\n\t\tassert (to_reduce[i].opcode == to_reduce[i - 1].opcode);\n\t\tif (reduced.back().g_right() >= to_reduce[i].g_left())\n\t\t{\n\t\t\tint delta = to_reduce[i].g_right() - reduced.back().g_right();\n\t\t\tif (delta > 0)\n\t\t\t\treduced.back().genomic_length += delta; \n\t\t}\n\t\telse\n\t\t{\n\t\t\treduced.push_back(to_reduce[i]);\n\t\t}\n\t}\n\t\n\tto_reduce = reduced;\n}\n\n// Adds open intervals not covered in the genomic coordinate covered by to_fill\n// to the vector gaps.  DOES NOT CLEAR gaps.\nvoid record_gaps(const vector<AugmentedCuffOp>& to_fill, \n\t\t\t\t vector<pair<int, int> >& gaps)\n{\n\tfor (size_t i = 1; i < to_fill.size(); ++i)\n\t{\n\t\tif (to_fill[i].g_left() - to_fill[i-1].g_right() > 0)\n\t\t{\n\t\t\tgaps.push_back(make_pair(to_fill[i-1].g_right(), to_fill[i].g_left()));\n\t\t}\n\t}\t\n}\n\n// This function \"fills\" the gaps in to_fill with \n// AugmentedCuffOps from filler. The intersection of the gaps in both vectors\n// remains as gaps in the modified to_fill.\n\n// IMPORTANT: both vectors MUST be disjoint (see disjoint_matches) before calling\n// this function\nvoid AugmentedCuffOp::fill_interstices(vector<AugmentedCuffOp>& to_fill,\n                                       const vector<AugmentedCuffOp>& filler,\n                                       bool allow_flank_fill,\n                                       bool allow_flanking_introns)\n{\n\tvector<AugmentedCuffOp> filled = to_fill;\n\tvector<pair<int, int> > gaps;\n\t\n\t\n\tsize_t j = 0;\n\t\n\tif (to_fill.empty())\n\t{\n\t\tto_fill = filler;\n\t\tsort(to_fill.begin(), to_fill.end(), g_left_lt);\n\t\treturn;\n\t}\n\t\n\t// This first loop could scan from either end and bail on hitting\n\t// the first gap, but this is straightforward, and probably just as\n\t// fast in practice, since these arrays are generally tiny\n\tif (allow_flank_fill)\n\t{\n\t\tgaps.push_back(make_pair(0, to_fill.front().g_left()));\n\t\trecord_gaps(to_fill, gaps);\n\t\tgaps.push_back(make_pair(to_fill.back().g_right(), INT_MAX));\n\t}\n\telse\n\t{\n\t\trecord_gaps(to_fill, gaps);\n\t}\n\t\n\tsize_t i = 0; \n\t\n\twhile (i < gaps.size())\n\t{\n\t\tpair<int, int>& gap = gaps[i];\n\t\t\n\t\t// a break in this loop will advance the gap index\n\t\twhile (j < filler.size())\n\t\t{\n\t\t\tconst AugmentedCuffOp& op = filler[j];\n\t\t\t\n\t\t\tif (op.g_left() == gap.first && op.g_right() == gap.second)\n\t\t\t{\n                // CASE 1\n\t\t\t\t//  gap     [     )\n\t\t\t\t//  op      [     ) \n\t\t\t\tfilled.push_back(op);\n\t\t\t\t\n\t\t\t\t// advance both indexes (i is advanced after the break);\n\t\t\t\t++j;\n                //fprintf (stderr, \"CASE 1: advancing both indexes\\n\"); \n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\telse if (op.g_right() <= gap.first)\n\t\t\t{\n                // CASE 2\n\t\t\t\t//  gap   [     )\n\t\t\t\t//  op  [ ) \n\t\t\t\t\n                //fprintf (stderr, \"CASE 2: skipping op %d:%d-%d due to gap %d-%d\\n\", op.opcode, op.g_left(), op.g_right(), gap.first, gap.second);\n\t\t\t\t// now just move to the next op, we can't add this one\n\t\t\t}\n\t\t\telse if (op.g_left() >= gap.second)\n\t\t\t{\n                // CASE 3\n\t\t\t\t//  gap     [     )\n\t\t\t\t//  op            [ ) \n                //fprintf (stderr, \"CASE 3: advancing gap from %d-%d due to op %d:%d-%d\\n\", gap.first, gap.second, op.opcode, op.g_left(), op.g_right());\n\t\t\t\tbreak; // not safe to add yet, we've gone beyond the current gap\n\t\t\t\t//  advance the gap index\n\t\t\t}\n\t\t\telse if (op.g_left() < gap.first && op.g_right() > gap.second)\n\t\t\t{\n                // CASE 4\n\t\t\t\t//  gap     [     )\n\t\t\t\t//  op    [         ) \n\t\t\t\t\n\t\t\t\t// create a new op to fill the gap\n\t\t\t\tAugmentedCuffOp gap_op(op.opcode, \n\t\t\t\t\t\t\t\t\t   gap.first, \n\t\t\t\t\t\t\t\t\t   gap.second - gap.first);\n\t\t\t\tassert (gap_op.genomic_length > 0);\n\t\t\t\t\n\t\t\t\tfilled.push_back(gap_op);\n                \n                //fprintf (stderr, \"CASE 4: advancing gap from %d-%d due to op %d:%d-%d\\n\", gap.first, gap.second, op.opcode, op.g_left(), op.g_right());\n\t\t\t\t// advance the gap index\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (op.g_left() > gap.first && op.g_right() < gap.second)\n\t\t\t{\n                // CASE 5\n\t\t\t\t//  gap     [     )\n\t\t\t\t//  op        [ ) \n\t\t\t\t\n\t\t\t\t//  just add this op\n\t\t\t\tfilled.push_back(op);\n\t\t\t\t//  advance the op index\n                //fprintf (stderr, \"CASE 5: adding %d:%d-%d, advancing op index\\n\", op.opcode, op.g_left(), op.g_right());\n\t\t\t}\n\t\t\telse if (op.g_right() >= gap.second && op.g_left() >= gap.first)\n\t\t\t{\n                // CASE 6\n\t\t\t\t//  gap     [     )\n\t\t\t\t//  op           [ ) \n\t\t\t\t\n\t\t\t\t//  create a new op from the left part of this one and add it\n\t\t\t\tAugmentedCuffOp gap_op(op.opcode, \n\t\t\t\t\t\t\t\t\t   op.g_left(), \n\t\t\t\t\t\t\t\t\t   gap.second - op.g_left());\n\t\t\t\tassert (gap_op.genomic_length > 0);\n\t\t\t\tfilled.push_back(gap_op);\n                \n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (op.g_left() <= gap.first && op.g_right() >= gap.first)\n\t\t\t{\n                // CASE 7\n\t\t\t\t//  gap     [     )\n\t\t\t\t//  op     [ ) \n\t\t\t\t\n\t\t\t\t//  create a new op from the right part of this one and add it\n\t\t\t\tAugmentedCuffOp gap_op(op.opcode, \n\t\t\t\t\t\t\t\t\t   gap.first, \n\t\t\t\t\t\t\t\t\t   op.g_right() - gap.first);\n\t\t\t\tassert (gap_op.genomic_length > 0);\n\t\t\t\t\n\t\t\t\tfilled.push_back(gap_op);\n\t\t\t\t\n\t\t\t\t//  advance the op index\n                //fprintf (stderr, \"CASE 7: advancing op\\n\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tassert(false);\n\t\t\t}\n            \n\t\t\t++j;\n\t\t}\n\t\t\n\t\t++i;\n\t}\n    \n\tsort(filled.begin(), filled.end(), g_left_lt);\n    if (!allow_flanking_introns)\n    {\n        for (size_t i = 0; i < filled.size(); ++i)\n        {\n            if (filled[i].opcode == CUFF_INTRON)\n            {\n                assert (i > 0);\n                assert (i < filled.size() -1);\n                assert (filled[i-1].opcode == CUFF_MATCH);\n                assert (filled[i+1].opcode == CUFF_MATCH);\n                assert (filled[i-1].g_right() == filled[i].g_left());\n                assert (filled[i+1].g_left() == filled[i].g_right());\n            }\n        }\n    }\n\tto_fill = filled;\n}\n\n\n\n// ops is assumed to be sorted\nvoid AugmentedCuffOp::merge_ops(const vector<AugmentedCuffOp>& ops, \n                                vector<AugmentedCuffOp>& merged,\n                                bool introns_overwrite_matches,\n                                bool allow_flank_introns)\n{\t\n#if DEBUG\n\t//assert(std::adjacent_find(ops.begin(), ops.end(), g_left_lt) == ops.end());\n#endif\n\t\n\tif (ops.size() < 2)\n\t{\n\t\tmerged = ops;\n\t\treturn;\n\t}\n\t\n\tsize_t g_max = 0;\n\tsize_t g_min = 0xFFFFFFFF;\n\t\n\tvector<AugmentedCuffOp> matches;\n\tvector<AugmentedCuffOp> introns;\n\t\n\tvector<AugmentedCuffOp> unknowns;\n\t\n\tfor (size_t i = 0; i < ops.size(); ++i)\n\t{\n\t\t//if (ops[i].opcode == CUFF_INTRON)\n\t\t//\tfprintf (stderr, \"[%d] %d, %d (%d)\\n\", i, ops[i].g_left(),ops[i].g_right(), ops[i].g_right() - ops[i].g_left() );\n\t\tassert (ops[i].g_left() < ops[i].g_right());\n\t\t\n\t\tif ((size_t)ops[i].g_left() < g_min)\n\t\t\tg_min = ops[i].g_left();\n\t\tif ((size_t)ops[i].g_right() > g_max)\n\t\t\tg_max = ops[i].g_right();\n\n\t\tswitch(ops[i].opcode)\n\t\t{\n\t\t\tcase CUFF_MATCH:\n\t\t\t{\n\t\t\t\tmatches.push_back(ops[i]);\n\t\t\t}break;\n                \n\t\t\tcase CUFF_INTRON:\n\t\t\t{\n\t\t\t\tintrons.push_back(ops[i]);\n\t\t\t}break;\n                \n\t\t\tcase CUFF_UNKNOWN:\n\t\t\t{\n                \n\t\t\t}break;\n                \n\t\t\tdefault:\n\t\t\t\tfprintf(stderr, \"Unknown opcode, exiting\\n\");\n\t\t\t\texit(1);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tint merged_length = (int)g_max - (int)g_min + 1;\n\tif (merged_length < 0)\n    {\n        fprintf(stderr, \"Error: nonsense gene merge - negative length product\\n\");\n\t\texit(1);\n    }\n    if (gaurd_assembly() && merged_length > (int)max_gene_length)\n\t{\n\t\tfprintf(stderr, \"Error: nonsense gene merge - product > max_gene_length\\n\");\n\t\texit(1);\n\t}\n\t\n\tunknowns.push_back(AugmentedCuffOp(CUFF_UNKNOWN, g_min, g_max - g_min + 1));\n\t\n    vector<AugmentedCuffOp> pre_merge = matches;\n\t\n\tdisjoint_ops(matches);\n\tdisjoint_ops(introns);\n\t\n\t// below, the flank fill flag is set to preserve the invariant that \n\t// all scaffolds must start with CUFF_MATCH\n\tif (introns_overwrite_matches)\n\t{\n\t\tmerged = introns;\n\t\tfill_interstices(merged, matches, true, allow_flank_introns);\n\t\tvector<pair<int, int> > gaps;\n\t\trecord_gaps(merged, gaps);\n\t\tif (!gaps.empty())\n\t\t\tfill_interstices(merged, unknowns, false, allow_flank_introns); \n\t}\n\telse\n\t{\n\t\tmerged = matches;\n\t\tfill_interstices(merged, introns, false, allow_flank_introns);\n\t\tvector<pair<int, int> > gaps;\n\t\trecord_gaps(merged, gaps);\n\t\tif (!gaps.empty())\n\t\t\tfill_interstices(merged, unknowns, false, allow_flank_introns); \n\t}\n\n    if (!allow_flank_introns)\n    {\n        assert (merged.front().opcode == CUFF_MATCH);\n        assert (merged.back().opcode == CUFF_MATCH);\n    }\n    for (size_t i = 1; i < merged.size(); ++i)\n    {\n\t\tassert(merged[i-1].g_right() == merged[i].g_left());\n        if (merged[i].opcode == CUFF_INTRON)\n        {\n            assert (merged[i-1].opcode == CUFF_MATCH);\n        }\n        else if (merged[i].opcode == CUFF_UNKNOWN)\n        {\n            assert (merged[i-1].opcode != CUFF_INTRON);\n        }\n    }\n}\n    \n\nbool is_known(const AugmentedCuffOp& op)\n{\n\treturn op.opcode != CUFF_UNKNOWN;\n}\n\n// verifies that no matter how the merge goes, the result wont be an insanely \n// long gene.\nbool check_merge_length(const vector<AugmentedCuffOp>& ops)\n{\n\tsize_t g_max = 0;\n\tsize_t g_min = 0xFFFFFFFF;\n\t\n\tfor (size_t i = 0; i < ops.size(); ++i)\n\t{\n\t\t//if (ops[i].opcode == CUFF_INTRON)\n\t\t//\tfprintf (stderr, \"[%d] %d, %d (%d)\\n\", i, ops[i].g_left(),ops[i].g_right(), ops[i].g_right() - ops[i].g_left() );\n\t\tassert (ops[i].g_left() < ops[i].g_right());\n\t\t\n\t\tif ((size_t)ops[i].g_left() < g_min)\n\t\t\tg_min = ops[i].g_left();\n\t\tif ((size_t)ops[i].g_right() > g_max)\n\t\t\tg_max = ops[i].g_right();\n\t}\t\n\tint merged_length = (int)g_max - (int)g_min + 1;\n\tif (merged_length < 0 || merged_length > (int)max_gene_length)\n\t{\n\t\treturn false;\n\t\t\t}\n\treturn true;\n\t\t}\n\ninline bool has_intron(const Scaffold& scaff)\n{\n\t\t\t\n\tconst vector<AugmentedCuffOp>& ops = scaff.augmented_ops();\n\tfor (size_t j = 0; j < ops.size(); ++j)\n\t{\n\t\tif (ops[j].opcode == CUFF_INTRON)\n\t\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\n//inline bool has_intron(const Scaffold& scaff)\n//{\n//\t\n//\tconst vector<AugmentedCuffOp>& ops = scaff.augmented_ops();\n//\tfor (size_t j = 0; j < ops.size(); ++j)\n//\t{\n//\t\tif (ops[j].opcode == CUFF_INTRON)\n//\t\t\treturn true;\n//\t}\n//\t\n//\treturn false;\n//}\n\nvoid Scaffold::extend_5(const Scaffold& other)\n{\n\tassert(Scaffold::compatible(*this, other, ref_merge_overhang_tolerance));\n\t\n\tif (strand() == CUFF_FWD)\n\t{\n\t\tAugmentedCuffOp& my_first_op = _augmented_ops.front();\n\t\tconst AugmentedCuffOp& other_first_op = other.augmented_ops().front();\n\n\t\tmy_first_op.g_left(other_first_op.g_left());\n\t}\n\telse if (strand() == CUFF_REV)\n\t{\n\t\tAugmentedCuffOp& my_last_op = _augmented_ops.back();\n\t\tconst AugmentedCuffOp& other_last_op = other.augmented_ops().back();\n\t\t\n\t\tmy_last_op.g_right(other_last_op.g_right());\n\t}\n\telse \n\t{\n\t\tassert(false);\n\t}\n\t\n\tint id_length = annotated_trans_id().length();\n\tif (id_length < 4 || _annotated_trans_id.substr(id_length-4)!=\"_ext\")\n\t\t_annotated_trans_id += \"_ext\";\n}\n\n// Clip final 3' exon by given amount\nvoid Scaffold::trim_3(int to_remove)\n{\n\tif(strand() == CUFF_FWD)\n\t{\n\t\tAugmentedCuffOp& exon_3 = _augmented_ops.back();\n\t\tassert (exon_3.genomic_length > to_remove);\n\t\texon_3.genomic_length -= to_remove;\n\t}\n\telse if(strand() == CUFF_REV)\n\t{\n\t\tAugmentedCuffOp& exon_3 = _augmented_ops.front();\n\t\tassert (exon_3.genomic_length > to_remove);\n\t\texon_3.genomic_offset += to_remove;\n\t\texon_3.genomic_length -= to_remove;\n\n\t}\n\telse\n\t{\n\t\tassert(false);\n\t}\n}\n\n// Clip final 3' exon by given amount\nvoid Scaffold::extend_3(int to_add)\n{\n\tif(strand() == CUFF_FWD)\n\t{\n\t\tAugmentedCuffOp& exon_3 = _augmented_ops.back();\n\t\t//assert (exon_3.genomic_length > to_remove);\n\t\texon_3.genomic_length += to_add;\n\t}\n\telse if(strand() == CUFF_REV)\n\t{\n\t\tAugmentedCuffOp& exon_3 = _augmented_ops.front();\n\t\t//assert (exon_3.genomic_length > to_remove);\n\t\texon_3.genomic_offset -= to_add;\n\t\texon_3.genomic_length += to_add;\n        \n\t}\n\telse\n\t{\n\t\tassert(false);\n\t}\n}\n\nvoid Scaffold::tile_with_scaffs(vector<Scaffold>& tile_scaffs, int max_len, int tile_offset) const\n{\n    int min_len = tile_offset;\n\tassert(min_len % tile_offset == 0 && max_len % tile_offset == 0);\n\t\n\tif (length() < max_len)\n\t\treturn;\n\t\n\tsize_t l = 0;\n\tsize_t r = 0;\n\tint l_off = 0;\n\tint r_off = min_len; // One past end\n\tint curr_len = min_len;\n\tint remaining_len = length();\n\t\n    const vector<AugmentedCuffOp>& orig_ops = augmented_ops();\n    \n\twhile(true)\n\t{\n\t\twhile (l < orig_ops.size() && (orig_ops[l].opcode != CUFF_MATCH || l_off >= orig_ops[l].genomic_length))\n\t\t{\n\t\t\tif (orig_ops[l].opcode == CUFF_MATCH)\n\t\t\t\tl_off -= orig_ops[l].genomic_length;\n            ++l;\n\t\t\t//if(++l == augmented_ops().size())\n\t\t\t//\tassert(false);\n\t\t}\n\t\twhile (r < orig_ops.size() && (orig_ops[r].opcode != CUFF_MATCH || r_off > orig_ops[r].genomic_length)) // Strictly > because r_off is one past\n\t\t{\n\t\t\tif (orig_ops[r].opcode == CUFF_MATCH)\n\t\t\t\tr_off -= orig_ops[r].genomic_length;\n            ++r;\n\t\t\t//if(++r == augmented_ops().size())\n\t\t\t//\tassert(false);\n\t\t}\n\t\t\n\t\tvector<AugmentedCuffOp> ops;\n\t\t\n        //if (l >= orig_ops.size() && r >= orig_ops.size())\n        //    break;\n        \n\t\tif (l==r)\n\t\t{\n            assert (l < orig_ops.size());\n\t\t\tops.push_back(AugmentedCuffOp(CUFF_MATCH, orig_ops[l].g_left() + l_off, r_off - l_off));\n\t\t}\n\t\telse\n\t\t{\n            assert(orig_ops.size());\n            //assert(orig_ops[l].genomic_offset != 0);\n            \n\t\t\tops.push_back(AugmentedCuffOp(CUFF_MATCH, orig_ops[l].g_left() + l_off, orig_ops[l].genomic_length - l_off));\n\t\t\tassert(ops.back().g_right() > ops.back().g_left());\n\t\t\tfor(size_t i = l+1; i < r; i++)\n\t\t\t{\n\t\t\t\tops.push_back(orig_ops[i]);\n\t\t\t}\n\t\t\tif (r_off > 0 && r < orig_ops.size())\n            {\n                assert (r < orig_ops.size());\n                //assert (orig_ops[r].genomic_offset != 0);\n\t\t\t\tops.push_back(AugmentedCuffOp(CUFF_MATCH, orig_ops[r].g_left(), r_off));\n            }\n\t\t}\n\t\tassert(ops.back().g_right() > ops.back().g_left());\n\n        // genomic_offset actually could be zero - from an exon starting at coord\n        // 1 in some chromosome of the ref.\n//\t\tBOOST_FOREACH(const AugmentedCuffOp& op, ops)\n//        {\n//            assert (op.genomic_offset != 0);\n//        }\n        \n\t\ttile_scaffs.push_back(Scaffold(this->ref_id(), this->strand(), ops, true)); \n\t\tassert(tile_scaffs.back().length() == curr_len );\n\t\tassert(tile_scaffs.back().left() >= left() &&\n\t\t\t   tile_scaffs.back().right() <= right());\n\t\t\n\t\tif (l==0 && l_off == 0 && curr_len < max_len) // On left end, not yet full length\n\t\t{\n\t\t\tcurr_len += tile_offset;\n\t\t\tr_off += tile_offset;\n\t\t}\n\t\telse if(remaining_len - tile_offset < max_len) // On the right end of transcript, decreasing in length\n\t\t{\n\t\t\tcurr_len += augmented_ops().back().genomic_length - r_off - tile_offset; \n\t\t\tr_off = augmented_ops().back().genomic_length;\n\t\t\tl_off += tile_offset;\n\t\t\tremaining_len -= tile_offset;\n\t\t\tif (curr_len < min_len)\n\t\t\t\treturn;\n\t\t}\n\t\telse // In the middle of the transcript, full length\n\t\t{\n\t\t\tl_off += tile_offset;\n\t\t\tr_off += tile_offset;\n\t\t\tremaining_len -= tile_offset;\n\t\t}\n\t\t\t\n\t}\n\t\n}\n\nbool Scaffold::sub_scaffold(Scaffold& sub_scaff, int g_left, int match_length) const\t\n{\n\tsize_t i;\n\tfor(i = 0; i < augmented_ops().size(); ++i)\n\t{\n\t\tif (augmented_ops()[i].g_right() > g_left)\n\t\t\tbreak;\n\t}\n\tconst AugmentedCuffOp& l_op = augmented_ops()[i++];\n\t\n\tassert(l_op.opcode == CUFF_MATCH);\n\t\n\tvector<AugmentedCuffOp> sub_ops;\n\tsub_ops.push_back(AugmentedCuffOp(CUFF_MATCH, g_left, min(match_length, l_op.g_right()-g_left)));\t\t\t\t\t \n\tint len_so_far = sub_ops.back().genomic_length;\n\t\t\t\t\t\t \n\twhile(len_so_far < match_length && i < augmented_ops().size())\n\t{\n\t\tconst AugmentedCuffOp& op = augmented_ops()[i++];\n\t\tif(op.opcode==CUFF_MATCH)\n\t\t{\n\t\t\tsub_ops.push_back(AugmentedCuffOp(CUFF_MATCH, op.g_left(), min(match_length-len_so_far, op.genomic_length)));\n\t\t\tlen_so_far += sub_ops.back().genomic_length;\n\t\t\tif (len_so_far >= match_length)\n\t\t\t\tbreak;\n\t\t}\n\t\telse \n\t\t{\n\t\t\tsub_ops.push_back(op);\n\t\t}\n\t}\n\t\n\t//assert(len_so_far == match_length);\n\tsub_scaff = Scaffold(this->ref_id(), this->strand(), sub_ops, true);\n\treturn (len_so_far == match_length);\n}\n\nvoid Scaffold::merge(const Scaffold& lhs, \n\t\t\t\t\t const Scaffold& rhs, \n\t\t\t\t\t Scaffold& merged,\n\t\t\t\t\t bool introns_overwrite_matches)\n{\n\tOpList ops;\n\t\n\tassert (merged.ref_id() == 0);\n\tassert (lhs.ref_id() == rhs.ref_id());\n\t\n\tops.insert(ops.end(), lhs._augmented_ops.begin(), lhs._augmented_ops.end());\n\tops.insert(ops.end(), rhs._augmented_ops.begin(), rhs._augmented_ops.end());\n\t\n\tsort(ops.begin(), ops.end(), AugmentedCuffOp::g_left_lt);\n\t\n\tAugmentedCuffOp::merge_ops(ops, merged._augmented_ops, introns_overwrite_matches);\n\t\n\tassert (ops.empty() || !(merged._augmented_ops.empty()));\n\t\n\tmerged._ref_id = lhs.ref_id();\n\tmerged._mates_in_scaff.insert(merged._mates_in_scaff.end(),\n\t\t\t\t\t\t\t\t  lhs._mates_in_scaff.begin(), \n\t\t\t\t\t\t\t\t  lhs._mates_in_scaff.end());\n\tmerged._mates_in_scaff.insert(merged._mates_in_scaff.end(),\n\t\t\t\t\t\t\t\t  rhs._mates_in_scaff.begin(), \n\t\t\t\t\t\t\t\t  rhs._mates_in_scaff.end());\n\t\n\tsort(merged._mates_in_scaff.begin(),\n\t\t merged._mates_in_scaff.end());\n\tvector<const MateHit*>::iterator new_end = unique(merged._mates_in_scaff.begin(), \n\t\t\t\t\t\t\t\t\t\t\t\t\t  merged._mates_in_scaff.end());\n\tmerged._mates_in_scaff.erase(new_end, merged._mates_in_scaff.end());\n\t\n\t\n\tint r_check = merged.left();\n\tfor (size_t i = 0; i < merged._augmented_ops.size(); ++i)\n\t\tr_check += merged._augmented_ops[i].genomic_length;\n\t\n\tassert(r_check == merged.right());\n\t\n\tif (lhs.strand() != CUFF_STRAND_UNKNOWN)\n\t\tmerged._strand = lhs.strand();\n\tif (rhs.strand() != CUFF_STRAND_UNKNOWN)\n\t\tmerged._strand = rhs.strand();\n\t\n\tmerged._has_intron = has_intron(merged);\n\tassert(merged._strand != CUFF_STRAND_UNKNOWN || !merged.has_intron() );\n\tassert(!merged.is_ref());\n    \n    if (library_type == \"transfrags\")\n    {\n        double avg_fpkm = lhs.fpkm() + rhs.fpkm();\n        avg_fpkm /= 2;\n        merged.fpkm(avg_fpkm);\n    }\n}\n\n\n\nvoid Scaffold::merge(const vector<Scaffold>& s, \n\t\t\t\t\t Scaffold& merged, \n\t\t\t\t\t bool introns_overwrite_matches)\n{\n\tOpList ops;\n\t\n\tCuffStrand strand = CUFF_STRAND_UNKNOWN;\n\t\n\tfor (size_t i = 0; i < s.size(); ++i)\n\t{\n\t\tops.insert(ops.end(), s[i]._augmented_ops.begin(), s[i]._augmented_ops.end());\n\t\tmerged._mates_in_scaff.insert(merged._mates_in_scaff.end(),\n\t\t\t\t\t\t\t\t\t  s[i]._mates_in_scaff.begin(), \n\t\t\t\t\t\t\t\t\t  s[i]._mates_in_scaff.end());\n\n\t\tif (s[i].strand() != CUFF_STRAND_UNKNOWN)\n\t\t{\n\t\t\t//assert (strand == CUFF_STRAND_UNKNOWN || strand == s[i].strand());\n\t\t\tstrand = s[i].strand();\n\t\t}\n\t}\n\t\n\tsort(merged._mates_in_scaff.begin(),merged._mates_in_scaff.end());\n\tvector<const MateHit*>::iterator new_end = unique(merged._mates_in_scaff.begin(), \n\t\t\t\t\t\t\t\t\t\t\t\t\t  merged._mates_in_scaff.end());\n\tmerged._mates_in_scaff.erase(new_end, merged._mates_in_scaff.end());\n\t\n\tsort(ops.begin(), ops.end(), AugmentedCuffOp::g_left_lt);\n\t//merged._contigs.push_back(CuffAlign(ops.front().g_left(), vector<CuffOp>()));\n\t\n\tif (ops.empty())\n\t\treturn;\n\t\n\tAugmentedCuffOp::merge_ops(ops, merged._augmented_ops, introns_overwrite_matches);\n\t\n\t\n\t//assert (ops.empty() || !(merged._augmented_ops.empty()));\n#ifdef DEBUG\n\tif (merged._augmented_ops.empty() || \n\t\tmerged._augmented_ops.front().opcode != CUFF_MATCH ||\n\t\tmerged._augmented_ops.back().opcode != CUFF_MATCH)\n\t{\n\t\tAugmentedCuffOp::merge_ops(ops, merged._augmented_ops, introns_overwrite_matches);\n\t}\n#endif\n\t\n\tmerged._ref_id = s.front().ref_id();\n\tmerged._strand = strand;\n\t\t\n\tint r_check = merged.left();\n\tfor (size_t i = 0; i < merged._augmented_ops.size(); ++i)\n\t\tr_check += merged._augmented_ops[i].genomic_length;\n\t\n#ifdef DEBUG\n\tif (r_check != merged.right())\n\t{\n\t\tAugmentedCuffOp::merge_ops(ops, merged._augmented_ops, introns_overwrite_matches);\n\t}\n#endif\n\t\n\tassert (r_check == merged.right());\n\tmerged._has_intron = has_intron(merged);\n\n\tassert(merged._strand != CUFF_STRAND_UNKNOWN || !merged.has_strand_support());\n    \n    if (library_type == \"transfrags\")\n    {\n        double avg_fpkm = 0.0;\n        BOOST_FOREACH (const Scaffold& sc, s)\n        {\n            avg_fpkm += sc.fpkm();\n        }\n        avg_fpkm /= s.size();\n        merged.fpkm(avg_fpkm);\n    }\n}\n\nvoid Scaffold::fill_gaps(int filled_gap_size)\n{\n\tOpList ops;\n\t\n    if (filled_gap_size <= 0)\n        return;\n    \n\tconst vector<AugmentedCuffOp>& orig_ops = augmented_ops();\n\tfor (size_t i = 0; i < orig_ops.size(); ++i)\n\t{\n\t\tif (orig_ops[i].opcode == CUFF_UNKNOWN && \n\t\t\torig_ops[i].genomic_length < filled_gap_size)\n\t\t{\n\t\t\tops.push_back(AugmentedCuffOp(CUFF_MATCH, \n\t\t\t\t\t\t\t\t\t\t  orig_ops[i].genomic_offset, \n\t\t\t\t\t\t\t\t\t\t  orig_ops[i].genomic_length)); \n\t\t}\n\t\telse\n\t\t{\n\t\t\tops.push_back(orig_ops[i]);\n\t\t}\n\t}\n\t\n\tsort(ops.begin(), ops.end(), AugmentedCuffOp::g_left_lt);\n\t\n\tAugmentedCuffOp::merge_ops(ops, _augmented_ops, false);\n\t_has_intron = has_intron(*this);\n\tassert(!has_strand_support() || _strand != CUFF_STRAND_UNKNOWN);\n\n}\n\nvoid Scaffold::fill_gaps(const vector<AugmentedCuffOp>& filler)\n{\n\tOpList ops;\n\t\n\tconst vector<AugmentedCuffOp>& orig_ops = augmented_ops();\n    \n\tconst vector<AugmentedCuffOp> og_ops = augmented_ops();\n\t\n    vector<AugmentedCuffOp> unknowns;\n\t\n    size_t g_max = 0;\n\tsize_t g_min = 0xFFFFFFFF;\n    \n    vector<AugmentedCuffOp> tmp_filler = filler;\n    \n    BOOST_FOREACH(const AugmentedCuffOp& op, orig_ops)\n    {\n\t\tassert (op.g_left() < op.g_right());\n\t\t\n\t\tif ((size_t)op.g_left() < g_min)\n\t\t\tg_min = op.g_left();\n\t\tif ((size_t)op.g_right() > g_max)\n\t\t\tg_max = op.g_right();\n\t}\n\n\ttmp_filler.push_back(AugmentedCuffOp(CUFF_UNKNOWN, g_min, g_max - g_min + 1));\n    sort(tmp_filler.begin(), tmp_filler.end(), AugmentedCuffOp::g_left_lt);\n    \n    vector<AugmentedCuffOp> padded_filler;\n    AugmentedCuffOp::merge_ops(tmp_filler, padded_filler, false);\n    \t\n    vector<AugmentedCuffOp> overlapping;\n    BOOST_FOREACH (const AugmentedCuffOp& op, padded_filler)\n    {\n\t\t//if (left() <= op.g_left() && right() >= op.g_right()\n\t\tif(::overlap_in_genome(op.g_left(),op.g_right(), left(), right())\n            && (op.opcode != CUFF_UNKNOWN || !overlapping.empty()))\n        {\n            overlapping.push_back(op);\n        }\n    }\n    \n    overlapping.insert(overlapping.end(), _augmented_ops.begin(),_augmented_ops.end()); \n    sort(overlapping.begin(), overlapping.end(), AugmentedCuffOp::g_left_lt);\n\t\n\t// Trim first in last in case they hang over the scaffold boundaries\n\tif (overlapping.front().g_left() < left())\n\t{\n\t\tAugmentedCuffOp& first_op = overlapping.front();\n\t\tfirst_op.genomic_length -= (left() - first_op.g_left());\n\t\tfirst_op.genomic_offset = left();\n\t}\n\tif (overlapping.back().g_right() > right())\n\t{\n\t\tAugmentedCuffOp& last_op = overlapping.back();\n\t\tlast_op.genomic_length -= (last_op.g_right() - right());\n\t}\n\tif (overlapping.back().opcode == CUFF_INTRON && overlapping.back().genomic_length <= bowtie_overhang_tolerance)\n\t{\n\t\toverlapping.pop_back();\n\t}\n\tif (overlapping.front().opcode == CUFF_INTRON && overlapping.front().genomic_length <= bowtie_overhang_tolerance)\n\t{\n\t\toverlapping.erase(overlapping.begin(), overlapping.begin()+1);\n\t}\n\t\n    // we don't want either the terminal ops in the filler to be unknowns,\n    // because they'll just propogate to the scaffold we're trying to fill.\n    if (!overlapping.empty() && overlapping.back().opcode == CUFF_UNKNOWN)\n        overlapping.pop_back();\n    \n    if (overlapping.empty())\n        return;\n    \n\tAugmentedCuffOp::merge_ops(overlapping, _augmented_ops, true);\n\t_has_intron = has_intron(*this);\n\tassert(!has_strand_support() || _strand != CUFF_STRAND_UNKNOWN);\n}\n\nbool Scaffold::overlap_in_genome(const Scaffold& lhs, \n\t\t\t\t\t\t\t\t const Scaffold& rhs, \n\t\t\t\t\t\t\t\t int overlap_radius)\n{\n\tint ll = lhs.left() - overlap_radius;\n\tint rr = rhs.right() + overlap_radius;\n\tint lr = lhs.right() + overlap_radius;\n\tint rl = rhs.left() - overlap_radius;\n\t\n\tif (ll >= rl && ll < rr)\n\t\treturn true;\n\tif (lr >rl && lr < rr)\n\t\treturn true;\n\tif (rl >= ll && rl < lr)\n\t\treturn true;\n\tif (rr > ll && rr < lr)\n\t\treturn true;\n\t\n\treturn false;\n}\n\nbool intron_op(const AugmentedCuffOp& op)\n{\n\treturn op.opcode == CUFF_INTRON;\n}\n\nbool Scaffold::strand_agree(const Scaffold& lhs, \n\t\t\t\t\t\t\tconst Scaffold& rhs)\n{\n\tbool strand = (lhs.strand() == CUFF_STRAND_UNKNOWN || \n\t\t\t\t   rhs.strand() == CUFF_STRAND_UNKNOWN ||\n\t\t\t\t   lhs.strand() == rhs.strand());\n\treturn strand;\n}\n\nbool Scaffold::exons_overlap(const Scaffold& lhs, \n\t\t\t\t\t\t\t const Scaffold& rhs)\n{\n\tconst vector<AugmentedCuffOp>& lhs_ops = lhs.augmented_ops();\n\tconst vector<AugmentedCuffOp>& rhs_ops = rhs.augmented_ops();\n\n\tfor (size_t l = 0; l < lhs_ops.size(); l++)\n\t{\n\t\tif (lhs_ops[l].opcode != CUFF_MATCH)\n\t\t\tcontinue;\n\t\t\n\t\tfor (size_t r = 0; r < rhs_ops.size(); r++)\n\t\t{\n\t\t\tif (rhs_ops[r].opcode == CUFF_MATCH &&\n\t\t\t\tAugmentedCuffOp::overlap_in_genome(lhs_ops[l], rhs_ops[r]))\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nbool Scaffold::compatible(const Scaffold& lhs, \n\t\t\t\t\t\t  const Scaffold& rhs,\n\t\t\t\t\t\t  int overhang_tolerance)\n{\t\n\tif (!strand_agree(lhs, rhs))\n\t\treturn false;\n\t\n\tif (lhs.left() <= rhs.left())\n\t{\n\t\tif (overlap_in_genome(lhs, rhs, olap_radius))\n\t\t{\n\t\t\t// check compatibility\n\t\t\tif (!compatible_contigs(lhs, rhs, overhang_tolerance))\n\t\t\t\treturn false;\n\t\t}\n\t}\n\telse if (rhs.left() < lhs.left())\n\t{\n\t\tif (overlap_in_genome(rhs, lhs, olap_radius))\n\t\t{\n\t\t\t// check compatibility\n\t\t\tif (!compatible_contigs(rhs, lhs, overhang_tolerance))\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\t\n\treturn true;\n}\n\nbool Scaffold::compatible_contigs(const Scaffold& lhs, \n\t\t\t\t\t\t\t\t  const Scaffold& rhs,\n\t\t\t\t\t\t\t\t  int overhang_tolerance)\n{\n\tconst vector<AugmentedCuffOp>& l_aug = lhs._augmented_ops;\n\tconst vector<AugmentedCuffOp>& r_aug = rhs._augmented_ops;\n\t\n\tsize_t curr_l_op = 0;\n\tsize_t curr_r_op = 0;\n\t\n\twhile (curr_l_op != l_aug.size() &&\n\t\t   curr_r_op != r_aug.size())\n\t{\n\t\tconst AugmentedCuffOp& l_op = l_aug[curr_l_op];\n\t\tconst AugmentedCuffOp& r_op = r_aug[curr_r_op];\n\t\t\n\t\tif (l_op.g_left() <= r_op.g_left())\n\t\t{\n\t\t\tif (AugmentedCuffOp::overlap_in_genome(l_op, r_op))\n\t\t\t{\n\t\t\t\t// check compatibility\n\t\t\t\tif (!AugmentedCuffOp::compatible(l_op, r_op, overhang_tolerance))\n\t\t\t\t\treturn false;\n//\t\t\t\tif (l_op.opcode == CUFF_UNKNOWN && \n//\t\t\t\t\tr_op.opcode == CUFF_MATCH)\n//\t\t\t\t{\n//\t\t\t\t\t//int m_len = AugmentedCuffOp::match_length(r_op, l_op.g_left(), l_op.g_right());\n//\t\t\t\t\tif (l_op.properly_contains(r_op))\n//\t\t\t\t\t\treturn false;\n//\t\t\t\t}\n\t\t\t}\n\t\t\tif (l_op.g_right() < r_op.g_right())\n\t\t\t\t++curr_l_op;\n\t\t\telse if (r_op.g_right() < l_op.g_right())\n\t\t\t\t++curr_r_op;\n\t\t\telse // Indentical boundaries, advance both\n\t\t\t{\n\t\t\t\t++curr_l_op;\n\t\t\t\t++curr_r_op;\n\t\t\t}\n\t\t}\n\t\telse if (r_op.g_left() < l_op.g_left())\n\t\t{\n\t\t\tif (AugmentedCuffOp::overlap_in_genome(r_op, l_op))\n\t\t\t{\n\t\t\t\t// check compatibility\n\t\t\t\tif (!AugmentedCuffOp::compatible(r_op, l_op, overhang_tolerance))\n\t\t\t\t\t\treturn false;\n//\t\t\t\tif (r_op.opcode == CUFF_UNKNOWN && \n//\t\t\t\t\tl_op.opcode == CUFF_MATCH)\n//\t\t\t\t{\n//\t\t\t\t\t//int m_len = AugmentedCuffOp::match_length(l_op, r_op.g_left(), r_op.g_right());\n//\t\t\t\t\tif (r_op.properly_contains(l_op))\n//\t\t\t\t\t\treturn false;\n//\t\t\t\t}\n\t\t\t}\n\t\t\tif (r_op.g_right() < l_op.g_right())\n\t\t\t\t++curr_r_op;\n\t\t\telse if (l_op.g_right() < r_op.g_right())\n\t\t\t\t++curr_l_op;\n\t\t\telse // Indentical boundaries, advance both\n\t\t\t{\n\t\t\t\t++curr_l_op;\n\t\t\t\t++curr_r_op;\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\treturn true;\n\t\n}\n\nbool overlap_in_genome(int ll, int lr, int rl, int rr)\n{\n\tif (ll >= rl && ll < rr)\n\t\treturn true;\n\tif (lr > rl && lr < rr)\n\t\treturn true;\n\tif (rl >= ll && rl < lr)\n\t\treturn true;\n\tif (rr > ll && rr < lr)\n\t\treturn true;\n\treturn false;\n}\n\ndouble Scaffold::score_overlap(const AugmentedCuffOp& op, \n\t\t\t\t\t\t\t   int inner_left_edge, \n\t\t\t\t\t\t\t   int inner_right_edge)\n{\n\tassert(false);\n\treturn 0; \n\t/*\n     assert (op.opcode == CUFF_MATCH);\n     int mlen = AugmentedCuffOp::match_length(op, \n     inner_left_edge, \n     inner_right_edge);\n     if (mlen > inner_dist_mean)\n     {\n     double c = cdf(inner_dist_norm, mlen) - 0.5;\n     //\tif (c == 1.0)\n     //\t\treturn -1000.0;\n     double weight = log(1 - c);\n     assert (weight <= 0.0);\n     return weight;\n     }\n     else\n     {\n     return 0;\n     }\n\t */\n}\n\ndouble Scaffold::min_score(const Scaffold& contig, \n\t\t\t\t\t\t   const vector<pair<int, int> >& inners)\n{\n\tdouble score = 0.0;\n\t\n\tsize_t curr_inner = 0;\n\tsize_t curr_op = 0;\n\t\n\twhile (curr_op != contig._augmented_ops.size() &&\n\t\t   curr_inner != inners.size())\n\t{\n\t\tconst pair<int, int>   inner = inners[curr_inner];\n\t\tconst AugmentedCuffOp&  op = contig._augmented_ops[curr_op];\n\t\t\n\t\tif (inner.first <= op.g_left())\n\t\t{\n\t\t\tif (op.opcode == CUFF_MATCH &&\n\t\t\t\t::overlap_in_genome(inner.first, \n\t\t\t\t\t\t\t\t\tinner.second, \n\t\t\t\t\t\t\t\t\top.g_left(), \n\t\t\t\t\t\t\t\t\top.g_right()))\n\t\t\t{\n\t\t\t\tscore = min(score, score_overlap(op, inner.first, inner.second));\n\t\t\t}\n\t\t\tif (inner.second < op.g_right())\n\t\t\t\t++curr_inner;\n\t\t\telse if (op.g_right() < inner.second)\n\t\t\t\t++curr_op;\n\t\t\telse // Indentical boundaries, advance both\n\t\t\t{\n\t\t\t\t++curr_inner;\n\t\t\t\t++curr_op;\n\t\t\t}\n\t\t}\n\t\telse if (op.g_left() < inner.first)\n\t\t{\n\t\t\tif (op.opcode == CUFF_MATCH &&\n\t\t\t\t::overlap_in_genome(op.g_left(), \n\t\t\t\t\t\t\t\t\top.g_right(), \n\t\t\t\t\t\t\t\t\tinner.first, \n\t\t\t\t\t\t\t\t\tinner.second))\n\t\t\t{\n\t\t\t\tscore = min(score, score_overlap(op, inner.first, inner.second));\n\t\t\t}\n\t\t\tif (op.g_right() < inner.second)\n\t\t\t\t++curr_op;\n\t\t\telse if (inner.second < op.g_right())\n\t\t\t\t++curr_inner;\n\t\t\telse // Indentical boundaries, advance both\n\t\t\t{\n\t\t\t\t++curr_inner;\n\t\t\t\t++curr_op;\n\t\t\t}\n\t\t}\n\t}\n\treturn score;\n}\n\ndouble Scaffold::score_contigs(const Scaffold& contig, \n\t\t\t\t\t\t\t   const vector<pair<int, int> >& inners)\n{\n\tdouble score = 0.0;\n\t\n\tsize_t curr_inner = 0;\n\tsize_t curr_op = 0;\n\t\n\twhile (curr_op != contig._augmented_ops.size() &&\n\t\t   curr_inner != inners.size())\n\t{\n\t\tconst pair<int, int>   inner = inners[curr_inner];\n\t\tconst AugmentedCuffOp&  op = contig._augmented_ops[curr_op];\n\t\t\n\t\tif (inner.first <= op.g_left())\n\t\t{\n\t\t\tif (op.opcode == CUFF_MATCH &&\n\t\t\t\t::overlap_in_genome(inner.first, \n\t\t\t\t\t\t\t\t  inner.second, \n\t\t\t\t\t\t\t\t  op.g_left(), \n\t\t\t\t\t\t\t\t  op.g_right()))\n\t\t\t{\n\t\t\t\tscore += score_overlap(op, inner.first, inner.second);\n\t\t\t}\n\t\t\tif (inner.second < op.g_right())\n\t\t\t\t++curr_inner;\n\t\t\telse if (op.g_right() < inner.second)\n\t\t\t\t++curr_op;\n\t\t\telse // Indentical boundaries, advance both\n\t\t\t{\n\t\t\t\t++curr_inner;\n\t\t\t\t++curr_op;\n\t\t\t}\n\t\t}\n\t\telse if (op.g_left() < inner.first)\n\t\t{\n\t\t\tif (op.opcode == CUFF_MATCH &&\n\t\t\t\t::overlap_in_genome(op.g_left(), \n\t\t\t\t\t\t\t\t  op.g_right(), \n\t\t\t\t\t\t\t\t  inner.first, \n\t\t\t\t\t\t\t\t  inner.second))\n\t\t\t{\n\t\t\t\tscore += score_overlap(op, inner.first, inner.second);\n\t\t\t}\n\t\t\tif (op.g_right() < inner.second)\n\t\t\t\t++curr_op;\n\t\t\telse if (inner.second < op.g_right())\n\t\t\t\t++curr_inner;\n\t\t\telse // Indentical boundaries, advance both\n\t\t\t{\n\t\t\t\t++curr_inner;\n\t\t\t\t++curr_op;\n\t\t\t}\n\t\t}\n\t}\n\treturn score;\n}\n\ndouble Scaffold::score_merge(const Scaffold& lhs, const Scaffold& rhs)\n{\n\tdouble score = 0.0;\n\t\t\n\tvector<pair<int, int> > l_inners, r_inners;\n\t\n\tvector<const MateHit*> lhs_but_not_rhs;\n\tvector<const MateHit*> rhs_but_not_lhs;\n\t\n\tset_difference(lhs.mate_hits().begin(),\n\t\t\t\t   lhs.mate_hits().end(),\n\t\t\t\t   rhs.mate_hits().begin(),\n\t\t\t\t   rhs.mate_hits().end(),\n\t\t\t\t   back_inserter(lhs_but_not_rhs));\n\t\n\tset_difference(rhs.mate_hits().begin(),\n\t\t\t\t   rhs.mate_hits().end(),\n\t\t\t\t   lhs.mate_hits().begin(),\n\t\t\t\t   lhs.mate_hits().end(),\n\t\t\t\t   back_inserter(rhs_but_not_lhs));\n\t\n\tfor (vector<const MateHit*>::iterator i = lhs_but_not_rhs.begin();\n\t\t i != lhs_but_not_rhs.end();\n\t\t ++i)\n\t{\n\t\tpair<int,int> p = (*i)->genomic_inner_span();\n\t\tif (p.first != -1 && p.second != -1)\n\t\t\tl_inners.push_back(p);\n\t}\n\t\n\tfor (vector<const MateHit*>::iterator i = rhs_but_not_lhs.begin();\n\t\t i != rhs_but_not_lhs.end();\n\t\t ++i)\n\t{\n\t\tpair<int,int> p = (*i)->genomic_inner_span();\n\t\tif (p.first != -1 && p.second != -1)\n\t\t\tr_inners.push_back(p);\n\t}\n\t\n\tscore += Scaffold::score_contigs(lhs, r_inners);\n\tscore += Scaffold::score_contigs(rhs, l_inners);\n\t\t\n\treturn score;\n}\n\ndouble Scaffold::score() const\n{\t\n\tdouble score = 0.0;\n\t\n\tvector<pair<int, int> > inners;\n\t\n\tfor (vector<const MateHit*>::const_iterator i = mate_hits().begin();\n\t\t i != mate_hits().end();\n\t\t ++i)\n\t{\n\t\tpair<int,int> p = (*i)->genomic_inner_span();\n\t\tif (p.first != -1 && p.second != -1)\n\t\t\tinners.push_back(p);\n\t}\n\n\tdouble contig_score = Scaffold::score_contigs(*this, inners);\n\tscore += contig_score;\n\n\treturn score;\t\n}\n\ndouble Scaffold::worst_mate_score() const\n{\n\tdouble min_score = 0.0;\n\t\n\tvector<pair<int, int> > inners;\n\t\n\tfor (vector<const MateHit*>::const_iterator i = mate_hits().begin();\n\t\t i != mate_hits().end();\n\t\t ++i)\n\t{\n\t\tpair<int,int> p = (*i)->genomic_inner_span();\n\t\tif (p.first != -1 && p.second != -1)\n\t\t\tinners.push_back(p);\n\t}\n\t\n\t//return overlap_in_genome(lhs._contigs[0], rhs._contigs[0]);\n\t\n\t\n\tmin_score = Scaffold::min_score(*this, inners);\n\t\n\treturn min_score;\t\n}\n\n\nint Scaffold::genomic_to_transcript_coord(int g_coord) const\n{\n\tint s_coord = 0;\n\tsize_t curr_op = 0;\n\tconst AugmentedCuffOp* op=NULL;\n\n\twhile (curr_op != _augmented_ops.size())\n\t{\n\t\top = &_augmented_ops[curr_op];\n\t\t\n\t\tif (op->g_right() > g_coord)\n\t\t\tbreak;\n\t\tif (op->opcode == CUFF_MATCH)\n\t\t\ts_coord += op->genomic_length;\n\t\t\n\t\t++curr_op;\n\t}\n\t\n\tint remainder = g_coord - (*op).g_left();\n\t\n\tif (remainder <= bowtie_overhang_tolerance || op->opcode == CUFF_MATCH)\n\t\ts_coord += remainder; \n\telse\n\t\ts_coord -= (op->genomic_length-remainder);\n\t\n\tif(strand()==CUFF_REV)\n\t\ts_coord = length() - 1 - s_coord;\n\t\n\treturn s_coord;\n}\n\n// start and end (first and second) are the first and final coordinates of the span\n// Does not handle overhangs (can return negative values)\npair <int,int> Scaffold::genomic_to_transcript_span(pair<int,int> g_span) const\n{\n\tint s_start;\n\tint s_end;\n\t\n\tint s_coord = 0;\n\tsize_t curr_op = 0;\n\tconst AugmentedCuffOp* op = NULL;\n\t// First, find start\n\twhile (curr_op != _augmented_ops.size())\n\t{\n\t\top = &_augmented_ops[curr_op];\n\t\t\n\t\tif (op->g_right() > g_span.first)\n\t\t\tbreak;\n\t\tif (op->opcode == CUFF_MATCH)\n\t\t\ts_coord += op->genomic_length;\n\t\t\n\t\t++curr_op;\n\t}\n\n\tint remainder = g_span.first - (*op).g_left();\n\t\n\tif (remainder <= bowtie_overhang_tolerance || op->opcode == CUFF_MATCH)\n\t\ts_start = s_coord + remainder; \n\telse\n\t\ts_start = s_coord - (op->genomic_length-remainder);\n\n\t\n\t// Now, find end\n\twhile (curr_op != _augmented_ops.size())\n\t{\n\t\top = &_augmented_ops[curr_op];\n\t\t\n\t\tif (op->g_right() > g_span.second)\n\t\t\tbreak;\n\t\tif (op->opcode == CUFF_MATCH)\n\t\t\ts_coord += op->genomic_length;\n\t\t++curr_op;\n\t}\n\t\n\tremainder = g_span.second - op->g_left();\n\t\n\tif (remainder < bowtie_overhang_tolerance || op->opcode == CUFF_MATCH)\n\t\ts_end = s_coord + remainder; \n\telse\n\t\ts_end = s_coord - (op->genomic_length-remainder);\n\t\n\tif(strand()==CUFF_REV)\n\t{\n\t\tint scaff_len = length();\n\t\ts_start = scaff_len - 1 - s_start;\n\t\ts_end = scaff_len - 1 - s_end;\n\t\tswap(s_start, s_end);\n\t}\n\t\n\treturn make_pair(s_start, s_end);\n}\n\n// Returns true only when both the start and end are found (ie, frag_len is known), which\n// can only happen if the read is paired.  Returned values that are equal to the trans_len \n// should be ignored, as they are invalid.\n// We can't use EmpDist unless it is unpaired since we call this function in inspect_bundle\n// End is inclusive\n// Returned indices are oriented with the transript!\nbool Scaffold::map_frag(const MateHit& hit, int& start, int& end, int& frag_len) const\n{\n\t\n\tint trans_len = length();\n    \n//    if (Scaffold(hit).augmented_ops() == augmented_ops())\n//    {\n//        int a = 4;\n//    }\n    \n\tstart = trans_len;\n\tend = trans_len;\n\t\n    Scaffold h(hit);\n    if(!(contains(h) && Scaffold::compatible(*this, h)))\n       return false;\n    \n    if (hit.read_group_props()->complete_fragments())\n    {\n        pair<int,int> g_span = make_pair(hit.left(), hit.right() - 1);\n\t\tpair<int,int> t_span = genomic_to_transcript_span(g_span);\n\t\tstart = t_span.first;\n\t\tend = t_span.second;\n\t\tfrag_len = abs(end-start)+1;\n    }\n\telse if (hit.is_pair())\n\t{\n\t\tpair<int,int> g_span = hit.genomic_outer_span();\n\t\tpair<int,int> t_span = genomic_to_transcript_span(g_span);\n\t\tstart = t_span.first;\n\t\tend = t_span.second;\n\t\tfrag_len = abs(end-start)+1;\t\t\n\t}\n\telse if (hit.read_group_props()->mate_strand_mapping()==FF)\n\t{\n\t\tboost::shared_ptr<const EmpDist> frag_len_dist = hit.read_group_props()->frag_len_dist();\n\t\tfrag_len = min(frag_len_dist->mode(), trans_len);\n\t}\n\telse\n\t{\n\t\tboost::shared_ptr<const EmpDist> frag_len_dist = hit.read_group_props()->frag_len_dist();\n\n\t\tif ((hit.left_alignment()->antisense_align() && strand() != CUFF_REV) \n\t\t\t|| (!hit.left_alignment()->antisense_align() && strand() == CUFF_REV))\n\t\t{\n\t\t\tint g_end  = (strand()!=CUFF_REV) ? hit.right()-1:hit.left();\n\t\t\tend = genomic_to_transcript_coord(g_end);\n\t\t\tfrag_len = min(frag_len_dist->mode(), end);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint g_start = (strand()!=CUFF_REV) ? hit.left():hit.right()-1;\n\t\t\tstart = genomic_to_transcript_coord(g_start);\n\t\t\tif (start == trans_len) // Overhang\n\t\t\t\tfrag_len = min(frag_len_dist->mode(), trans_len);\n\t\t\telse\n\t\t\t\tfrag_len = min(frag_len_dist->mode(), trans_len-start);\n\t\t}\n\t}\n\n    if (start <= 0 || start > trans_len)\n\t\tstart = trans_len;\n\tif (end <= 0 || end > trans_len)\n\t\tend = trans_len;\n\t\t\n\treturn (start != trans_len && end != trans_len);\n}\n\nint Scaffold::match_length(int left, int right) const\n{\n\tint len = 0;\n\n\t\n\tsize_t curr_op = 0;\n\t\n\twhile (curr_op != _augmented_ops.size())\n\t{\n\t\tconst AugmentedCuffOp&  op = _augmented_ops[curr_op];\n\t\t\n\t\tif (op.opcode == CUFF_MATCH &&\n\t\t\t::overlap_in_genome(left, \n\t\t\t\t\t\t\t\tright, \n\t\t\t\t\t\t\t\top.g_left(), \n\t\t\t\t\t\t\t\top.g_right()))\n\t\t{\n\t\t\tlen += AugmentedCuffOp::match_length(op, left, right);\n\t\t}\n\t\tif (op.g_left() >= right)\n\t\t\tbreak;\n\t\t++curr_op;\n\t}\n\t\n\treturn len;\n}\n\n\nvoid Scaffold::clear_hits()\n{\n    _mates_in_scaff.clear();\n\tvector<const MateHit*>(_mates_in_scaff).swap(_mates_in_scaff);\n    //_mates_in_scaff.clear();\n}\n\nbool Scaffold::add_hit(const MateHit* hit)\n{\n\tScaffold hs(*hit);\n\tif (contains(hs) &&\n\t\tScaffold::compatible(*this, hs))\n\t{\n\t\tif (!binary_search(_mates_in_scaff.begin(),\n\t\t\t\t\t\t  _mates_in_scaff.end(),\n\t\t\t\t\t\t  hit))\n\t\t{\n\t\t\t_mates_in_scaff.push_back(hit);\n\t\t}\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n\nvoid Scaffold::get_complete_subscaffolds(vector<Scaffold>& complete)\n{\n\tif (!has_unknown())\n\t{\n\t\tcomplete.push_back(*this);\n\t}\n\telse\n\t{\n\t\tint last_unknown = -1;\n        int leftmost_known_op = -1;\n        int rightmost_known_op = -1;\n\t\tfor (size_t i = 0; i < _augmented_ops.size(); ++i)\n\t\t{\n\t\t\tconst AugmentedCuffOp& op = _augmented_ops[i]; \n            if (op.opcode != CUFF_UNKNOWN)\n            {\n                if (leftmost_known_op == -1)\n                {\n                    leftmost_known_op = i;\n                    assert (_augmented_ops[leftmost_known_op].opcode != CUFF_INTRON);\n                }\n                rightmost_known_op = i;\n            }\n\t\t\tif (op.opcode == CUFF_UNKNOWN || i == _augmented_ops.size() - 1)\n\t\t\t{\n\t\t\t\tint left_known;\n\t\t\t\tint right_known;\n\t\t\t\t\n\t\t\t\tif (i == _augmented_ops.size() - 1)\n\t\t\t\t\tright_known = right();\n\t\t\t\telse\n\t\t\t\t\tright_known = op.g_left() - 1;\n\t\t\t\t\n\t\t\t\tif (last_unknown == -1)\n\t\t\t\t\tleft_known = left();\n\t\t\t\telse\n\t\t\t\t\tleft_known = _augmented_ops[last_unknown].g_right();\n\t\t\t\t\n                //fprintf(stderr, \"excluding unknown region between %d-%d\\n\", left_known, right_known);\n                if (leftmost_known_op != -1 && rightmost_known_op != -1)\n                {\n                    \n                    vector<AugmentedCuffOp> known_ops;\n                    known_ops.insert(known_ops.end(), \n                                     &_augmented_ops[leftmost_known_op],\n                                     &_augmented_ops[rightmost_known_op] + 1);\n                    Scaffold known(ref_id(), strand(), known_ops);\n                    \n                    for (vector<const MateHit*>::iterator mitr = _mates_in_scaff.begin();\n                         mitr != _mates_in_scaff.end();\n                         ++mitr)\n                    {\n\n                        const MateHit& m = **mitr;\n                        if (left_known <= m.left() && m.right() <= right_known)\n                        {\n                            known.add_hit(&m);\n                        }\n                    }\n                    \n                   // if (known.has_intron())\n                        known.strand(_strand);\n                    \n                    //assert (!known.mate_hits().empty());\n                    //assert(!known.has_intron()|| known.strand() != CUFF_STRAND_UNKNOWN);\n                    \n                   // const vector<const MateHit*>& hits = known.mate_hits();\n                   // bool contains_spliced_hit = false;\n                   // BOOST_FOREACH (const MateHit* h, hits)\n                   // {\n                   //     const ReadHit* left = h->left_alignment();\n                   //     const ReadHit* right = h->right_alignment();\n                   //     if (left && left->contains_splice())\n                   //     {\n                   //         contains_spliced_hit = true;\n                   //         break;\n                   //     }\n                   //     if (right && right->contains_splice())\n                   //     {\n                   //         contains_spliced_hit = true;\n                   //         break;\n                   //     }\n\t\t\t\t   // }\n                    \n                   // if (!hits.empty() && !contains_spliced_hit && !known.is_ref())\n                   // {\n                   //     known.strand(CUFF_STRAND_UNKNOWN);\n                   // }\n                    \n                    complete.push_back(known);\n                }\n                    \n\t\t\t\tlast_unknown = i;\n                leftmost_known_op = -1;\n\t\t\t}\n\t\t}\n\t}\n}\n\ndouble Scaffold::internal_exon_coverage() const\n{\n    // First check if there are internal exons\n    if (augmented_ops().size() < 5) \n        return 0.0;\n    \n    int left = augmented_ops()[2].g_left();\n    int right = augmented_ops()[augmented_ops().size() - 3].g_right();\n    vector<bool> covered(right-left, 0);\n    BOOST_FOREACH(const MateHit* h, mate_hits())\n    {\n        if (::overlap_in_genome(h->left(),h->right(), left, right))\n        {\n            for (int i = max(h->left()-left, 0); i < min(h->right()-left, right-left); ++i)\n            {\n                assert(i < covered.size());\n                covered[i] = 1;\n            }\n        }\n    }\n    double percent_covered = accumulate(covered.begin(),covered.end(),0.0)/(right-left);\n    return percent_covered;\n}\n\nbool Scaffold::has_strand_support(vector<boost::shared_ptr<Scaffold> >* ref_scaffs) const\n{\n\tif (strand() == CUFF_STRAND_UNKNOWN)\n\t\treturn false;\n\t\n\t// FIXME:  This is not true for non-canonical splicing\n\tif (has_intron())\n\t\treturn true;\n\t\n\tBOOST_FOREACH (const MateHit* h, mate_hits())\n\t{\n\t\tif (h->strand() == strand())\n\t\t\treturn true;\n\t\tassert(h->strand() == CUFF_STRAND_UNKNOWN && !h->contains_splice());\n\t}\n\t\n\tif (ref_scaffs == NULL)\n\t\treturn false;\n\t\n\tBOOST_FOREACH (boost::shared_ptr<Scaffold const> ref_scaff, *ref_scaffs)\n\t{\n\t\tif (ref_scaff->strand() == strand() && exons_overlap(*this, *ref_scaff))\n\t\t\treturn true;\n\t}\n\t\t\n\treturn false;\n}\n\nbool Scaffold::has_struct_support(set<AugmentedCuffOp>& hit_introns) const\n{\n    if(augmented_ops().size() == 1)\n        return mate_hits().size() > 0;\n\n    if(augmented_ops().size() == 3)\n        return hits_support_introns(hit_introns);\n    \n    return (hits_support_introns(hit_introns) && internal_exon_coverage() == 1.0);\n}\n\n\nbool Scaffold::hits_support_introns() const\n{\n    set<AugmentedCuffOp> hit_introns;\n    set<AugmentedCuffOp> scaffold_introns;\n    BOOST_FOREACH(const MateHit* h, _mates_in_scaff)\n    {\n        Scaffold s(*h);\n        BOOST_FOREACH (AugmentedCuffOp a, s.augmented_ops())\n        {\n            if (a.opcode == CUFF_INTRON)\n            {\n                hit_introns.insert(a);\n            }\n        }\n    }\n    BOOST_FOREACH (AugmentedCuffOp a, _augmented_ops)\n    {\n        if (a.opcode == CUFF_INTRON)\n        {\n            scaffold_introns.insert(a);\n        }\n    }\n    \n    if (hit_introns != scaffold_introns)\n    {\n        fprintf(stderr, \"********************\\n\");\n        BOOST_FOREACH(const AugmentedCuffOp& a, hit_introns)\n        {\n            fprintf(stderr, \"%d - %d\\n\", a.g_left(), a.g_right());\n        }\n        \n        fprintf(stderr, \"####################\\n\");    \n        BOOST_FOREACH(const AugmentedCuffOp& a, scaffold_introns)\n        {\n            fprintf(stderr, \"%d - %d\\n\", a.g_left(), a.g_right());\n        }\n    }\n    \n    return hit_introns == scaffold_introns;\n}\n\nbool Scaffold::hits_support_introns(set<AugmentedCuffOp>& hit_introns) const\n{\n    set<AugmentedCuffOp> scaffold_introns;\n\n    BOOST_FOREACH (AugmentedCuffOp a, _augmented_ops)\n    {\n        if (a.opcode == CUFF_INTRON)\n        {\n            scaffold_introns.insert(a);\n        }\n    }\n    \n    return includes(hit_introns.begin(),hit_introns.end(), scaffold_introns.begin(), scaffold_introns.end());\n}\n\nbool scaff_lt(const Scaffold& lhs, const Scaffold& rhs)\n{\n\treturn lhs.left() < rhs.left();\n}\n\nbool scaff_lt_rt(const Scaffold& lhs, const Scaffold& rhs)\n{\n    if (lhs.left() != rhs.left())\n        return lhs.left() < rhs.left();\n    return lhs.right() < rhs.right();\n}\n\nbool scaff_lt_rt_oplt(const Scaffold& lhs, const Scaffold& rhs)\n{\n    if (scaff_lt_rt(lhs, rhs))\n        return true;\n    if (scaff_lt_rt(rhs, lhs))\n        return false;\n    \n    // Now we need to actually compare the alignment ops\n    const vector<AugmentedCuffOp>& lhs_ops = lhs.augmented_ops();\n    const vector<AugmentedCuffOp>& rhs_ops = rhs.augmented_ops();\n    \n    if (lhs_ops.size() != rhs_ops.size())\n        return lhs_ops.size() < rhs_ops.size();\n    \n    for (size_t i = 0; i < lhs_ops.size(); ++i)\n    {\n        if (lhs_ops[i] != rhs_ops[i])\n        {\n            return lhs_ops[i] < rhs_ops[i];\n        }\n    }\n    \n    return false;\n}\n\nbool scaff_lt_sp(boost::shared_ptr<Scaffold> lhs, boost::shared_ptr<Scaffold> rhs)\n{\n\treturn scaff_lt(*lhs,*rhs);\n}\n\nbool scaff_lt_rt_sp(boost::shared_ptr<Scaffold> lhs, boost::shared_ptr<Scaffold> rhs)\n{\n\treturn scaff_lt_rt(*lhs,*rhs);\n}\n\nbool scaff_lt_rt_oplt_sp(boost::shared_ptr<Scaffold> lhs, boost::shared_ptr<Scaffold> rhs)\n{\n\treturn scaff_lt_rt_oplt(*lhs,*rhs);\n}\n"
  },
  {
    "path": "src/scaffolds.h",
    "content": "#ifndef SCAFFOLDS_H\n#define SCAFFOLDS_H\n/*\n *  scaffolds.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/30/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <set>\n#include <vector>\n\n#include \"common.h\"\n#include \"hits.h\"\n\n#include <boost/thread.hpp>\n\nusing namespace std;\n\nenum CuffOpCode { CUFF_MATCH, CUFF_INTRON, CUFF_UNKNOWN };\n\nstruct AugmentedCuffOp \n{\n\tAugmentedCuffOp(const CuffOpCode& O, int g_off, int g_len) \n\t: opcode(O), \n\tgenomic_offset(g_off),\n\tgenomic_length(g_len) \n\t{\n\t\tassert (genomic_length >= 0);\n\t}\n\t\n\tvoid g_left(int left) \n\t{ \n\t\tint right = genomic_offset + genomic_length;\n\t\tgenomic_offset = left;\n\t\tgenomic_length = right - left;\n\t}\n\tint g_left() const { return genomic_offset; }\n\t\n\tvoid g_right(int right) \n\t{ \n\t\tgenomic_length = right - genomic_offset;\n\t}\n\tint g_right() const { return genomic_offset + genomic_length; }\n\t\n\tstatic bool overlap_in_genome(const AugmentedCuffOp& lhs,\n\t\t\t\t\t\t\t\t  const AugmentedCuffOp& rhs)\n\t{\t\n\t\tif (lhs.g_left() >= rhs.g_left() && lhs.g_left() < rhs.g_right())\n\t\t\treturn true;\n\t\tif (lhs.g_right() > rhs.g_left() && lhs.g_right() < rhs.g_right())\n\t\t\treturn true;\n\t\tif (rhs.g_left() >= lhs.g_left() && rhs.g_left() < lhs.g_right())\n\t\t\treturn true;\n\t\tif (rhs.g_right() > lhs.g_left() && rhs.g_right() < lhs.g_right())\n\t\t\treturn true;\n\t\treturn false;\n\t}\n\t\n\tbool contains(const AugmentedCuffOp& other) const\n\t{\n\t\tif (g_left() <= other.g_left() && g_right() >= other.g_right())\n\t\t\treturn true;\n\t\treturn false;\n\t}\n\t\n\tbool properly_contains(const AugmentedCuffOp& other) const\n\t{\n\t\tif ((g_left() < other.g_left() && g_right() >= other.g_right()) ||\n\t\t\t(g_left() <= other.g_left() && g_right() > other.g_right()))\n\t\t\treturn true;\n\t\treturn false;\n\t}\n\t\n\tstatic int match_length(const AugmentedCuffOp& op, int left, int right)\n\t{\n\t\tint len = 0;\n\t\tint left_off = op.g_left();\n\t\tif (op.opcode == CUFF_MATCH)\n\t\t{\n\t\t\tif (left_off + op.genomic_length > left && left_off < right)\n\t\t\t{\n\t\t\t\tif (left_off > left)\n\t\t\t\t{\n\t\t\t\t\tif (left_off + op.genomic_length <= right + 1)\n\t\t\t\t\t\tlen += op.genomic_length;\n\t\t\t\t\telse\n\t\t\t\t\t\tlen += right - left_off;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (left_off + op.genomic_length <= right + 1)\n\t\t\t\t\t\tlen += (left_off + op.genomic_length - left);\n\t\t\t\t\telse\n\t\t\t\t\t\treturn right - left;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn len;\n\t}\n\t\n\tstatic bool compatible(const AugmentedCuffOp& lhs,\n\t\t\t\t\t\t   const AugmentedCuffOp& rhs,\n\t\t\t\t\t\t   int overhang_tolerance = bowtie_overhang_tolerance);\n\t\n\tbool operator==(const AugmentedCuffOp& rhs) const\n\t{\n\t\treturn (opcode == rhs.opcode && \n\t\t\t\tgenomic_offset == rhs.genomic_offset &&\n\t\t\t\tgenomic_length == rhs.genomic_length);\n\t}\n\t\n\tbool operator<(const AugmentedCuffOp& rhs) const\n\t{\n\t\tif (opcode != rhs.opcode)\n\t\t{\n\t\t\treturn opcode < rhs.opcode;\n\t\t}\n\t\tif (genomic_offset != rhs.genomic_offset)\n\t\t{\n\t\t\treturn genomic_offset < rhs.genomic_offset;\n\t\t}\n\t\tif (genomic_length != rhs.genomic_length)\n\t\t{\n\t\t\treturn genomic_length < rhs.genomic_length;\n\t\t}\n\t\treturn false;\n\t}\n    \n    static bool g_left_lt(const AugmentedCuffOp& lhs,\n\t\t\t\t\t\t  const AugmentedCuffOp& rhs);\n\t\n\tbool operator!=(const AugmentedCuffOp& rhs) const\n\t{\n\t\treturn !(*this == rhs);\n\t}\n    \n    static void merge_ops(const std::vector<AugmentedCuffOp>& ops, \n\t\t\t\t\t\t  vector<AugmentedCuffOp>& merged,\n\t\t\t\t\t\t  bool introns_overwrite_matches,\n                          bool allow_flank_introns = false);\n    \n    static void fill_interstices(vector<AugmentedCuffOp>& to_fill,\n\t\t\t\t\t\t\t\t const vector<AugmentedCuffOp>& filler,\n\t\t\t\t\t\t\t\t bool allow_flank_fill,\n                                 bool allow_flank_introns);\n\t\n\tCuffOpCode opcode;\n\tint genomic_offset;\n\tint genomic_length;\n};\n\nclass Scaffold\n{\n\tvoid cuff_ops_from_cigar(vector<AugmentedCuffOp>& ops,\n\t\t\t\t\t\t\t const vector<CigarOp>& cig,\n\t\t\t\t\t\t\t int& g_left)\n\t{\n\t\tfor (size_t i = 0; i < cig.size(); ++i)\n\t\t{\n\t\t\tassert(cig[i].length >= 0);\n\t\t\tswitch(cig[i].opcode)\n\t\t\t{\n\t\t\t\tcase MATCH:\n\t\t\t\t\tops.push_back(AugmentedCuffOp(CUFF_MATCH, g_left, cig[i].length));\n\t\t\t\t\tg_left += cig[i].length;\n\t\t\t\t\tbreak;\n\t\t\t\tcase REF_SKIP:\n\t\t\t\t\tops.push_back(AugmentedCuffOp(CUFF_INTRON, g_left, cig[i].length));\n\t\t\t\t\tg_left += cig[i].length;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SOFT_CLIP:\n\t\t\t\t\tg_left += cig[i].length;\n\t\t\t\t\tbreak;\n                case HARD_CLIP:\n\t\t\t\t\t//g_left += cig[i].length;\n\t\t\t\t\tbreak;\n                case INS:\n                    //ops.back().genomic_length -= cig[i].length;\n                    //g_left -= cig[i].length;\n\t\t\t\t\tbreak;\n                case DEL:\n\t\t\t\t\tif (!ops.empty())\n\t\t\t\t\t\tops.back().genomic_length += cig[i].length;\n                    g_left += cig[i].length;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tassert(false);\n\t\t\t\t\tbreak;\n\t\t\t}\n            assert (ops.empty() || ops.back().genomic_length >= 1);\n\t\t}\n\t}\n\n\tRefID _ref_id;\n\t\npublic:\n\t\n\tScaffold() :\n\t\t_ref_id(0), \n\t\t_is_ref(false),\n\t\t_strand(CUFF_STRAND_UNKNOWN), \n\t\t_classcode(0),\n        _fpkm(0.0) {}\n\t\n\tScaffold(const MateHit& mate) :\n\t\t_ref_id(mate.ref_id()),\n\t\t_is_ref(false),\n\t    _classcode(0)\n\t{\n\t\tconst ReadHit* left_hit = mate.left_alignment();\n\t\t//CuffAlign a;\n\t\t_strand = mate.strand();\n\t\t\n\t\tvector<AugmentedCuffOp> aug_ops;\n\t\t\n\t\tif (left_hit)\n\t\t{\n\t\t\tconst vector<CigarOp>& l_cig = left_hit->cigar();\n\t\t\tint g_left = left_hit->left();\n\t\t\tcuff_ops_from_cigar(aug_ops, l_cig, g_left);\n\t\t\t\n\t\t\tconst ReadHit* right_hit = mate.right_alignment();\n\t\t\tif (right_hit)\n\t\t\t{\n\t\t\t\tconst vector<CigarOp>& r_cig = right_hit->cigar();\n\t\t\t\tint gap = (right_hit->left() - g_left);\n\t\t\t\t\n\t\t\t\tif (gap < 0)\n\t\t\t\t{\n\t\t\t\t\tg_left += gap;\n\t\t\t\t\tcuff_ops_from_cigar(aug_ops, r_cig, g_left);\n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t{\n\t\t\t\t\tif (gap > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t//if (gap < (int)min_intron_length)\n\t\t\t\t\t\t//\taug_ops.push_back(AugmentedCuffOp(CUFF_MATCH, g_left, gap));\n\t\t\t\t\t\t//else\n                        aug_ops.push_back(AugmentedCuffOp(CUFF_UNKNOWN, g_left, gap));\n\t\t\t\t\t\tg_left += gap;\n\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\tcuff_ops_from_cigar(aug_ops, r_cig, g_left);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tassert(false);\n\t\t}\n\t\t_mates_in_scaff.push_back(&mate);\n\t\tsort(aug_ops.begin(), aug_ops.end(), AugmentedCuffOp::g_left_lt);\n\n        for(size_t i = 0; i < aug_ops.size(); ++i)\n        {\n            assert (aug_ops[i].genomic_length >= 1);\n        }\n        \n        AugmentedCuffOp::merge_ops(aug_ops, _augmented_ops, false);\n\t\t\n\t\tint r_check = left();\n\t\tfor (size_t i = 0; i < _augmented_ops.size(); ++i)\n\t\t\tr_check += _augmented_ops[i].genomic_length;\n\t\t\n#ifdef DEBUG\n\t\tif (r_check != right())\n\t\t{\n            AugmentedCuffOp::merge_ops(aug_ops, _augmented_ops, false);\n\t\t}\n#endif\n\t\tassert (r_check == right());\n\t\t\n\t\t_has_intron = has_intron(*this);\n\t\t\n\t\tassert(!has_strand_support() || _strand != CUFF_STRAND_UNKNOWN);\n\n        for(size_t i = 1; i < _augmented_ops.size(); ++i)\n\t\t{\n\t\t\tassert(_augmented_ops[i-1].g_right() == _augmented_ops[i].g_left());\n\t\t}\n\t\t\n\t\tassert (_augmented_ops.front().opcode == CUFF_MATCH);\n        assert (_augmented_ops.back().opcode == CUFF_MATCH);\n        \n        if (library_type == \"transfrags\")\n        {\n            double avg_fpkm = mate.mass();\n            fpkm(avg_fpkm);\n        }\n\t}\n\t\n\tScaffold(const vector<Scaffold>& hits, bool introns_overwrite_matches = true) \n\t\t:  _is_ref(false), _classcode(0)\n\t{\n\t\tassert (!hits.empty());\n\t\t_ref_id = hits[0].ref_id();\n\t\t\n\t\tScaffold::merge(hits, *this, introns_overwrite_matches);\n\t\t\n\t\tassert(!has_strand_support() || _strand != CUFF_STRAND_UNKNOWN);\n        \n        assert (_augmented_ops.front().opcode == CUFF_MATCH);\n        assert (_augmented_ops.back().opcode == CUFF_MATCH);\n        \n        if (library_type == \"transfrags\")\n        {\n            double avg_fpkm = 0.0;\n            BOOST_FOREACH (const Scaffold& sc, hits)\n            {\n                avg_fpkm += sc.fpkm();\n            }\n            avg_fpkm /= hits.size();\n            fpkm(avg_fpkm);\n        }\n\t}\n\t\n\t// For manually constructing scaffolds, for example when a reference is \n\t// available\n\tScaffold(RefID ref_id, CuffStrand strand, const vector<AugmentedCuffOp>& ops, bool is_ref = false, bool is_pseudo_primary = false)\n\t: _ref_id(ref_id), \n\t  _augmented_ops(ops), \n\t  _strand(strand),\n\t  _classcode(0)\n\t{\n\t\t_has_intron = has_intron(*this);\n\t\t_is_ref = is_ref;\n        _is_pseudo_primary = is_pseudo_primary;\n\t\t\n\t\tassert(!has_strand_support() || _strand != CUFF_STRAND_UNKNOWN);\n\n        assert (_augmented_ops.front().opcode == CUFF_MATCH);\n        assert (_augmented_ops.back().opcode == CUFF_MATCH);\n\t}\n\t\n\t//int get_id() const { return _id; }\n\t\t\n\tint left() const { return _augmented_ops.front().g_left(); }\n\tint right() const  { return _augmented_ops.back().g_right(); }\n\t\n\tconst vector<const MateHit*>& mate_hits() const { return _mates_in_scaff; }\n\t\n\tRefID ref_id() const { return _ref_id; }\n\tvoid ref_id(RefID rid) { _ref_id = rid; }\n\t\n\tconst string& annotated_trans_id() const { return _annotated_trans_id; }\n\tvoid annotated_trans_id(const string& ann_name) { _annotated_trans_id = ann_name; }\n\t\n\tconst string& annotated_gene_id() const { return _annotated_gene_id; }\n\tvoid annotated_gene_id(const string& ann_name) { _annotated_gene_id = ann_name; }\n\t\n\tconst string& annotated_gene_name() const { return _annotated_gene_name; }\n\tvoid annotated_gene_name(const string& ann_name) { _annotated_gene_name = ann_name; }\n\t\n\tconst string& annotated_protein_id() const { return _annotated_protein_id; }\n\tvoid annotated_protein_id(const string& ann_name) { _annotated_protein_id = ann_name; }\t\n\t\n\tconst string& annotated_tss_id() const { return _annotated_tss_id; }\n\tvoid annotated_tss_id(const string& ann_name) { _annotated_tss_id = ann_name; }\t\n\t\n\tconst string& nearest_ref_id() const { return _nearest_ref_id; }\n\tvoid nearest_ref_id(const string& ann_name) { _nearest_ref_id = ann_name; }\t\n\t\n    // fpkm() and num_fragments() are just used to cache values in scaffolds across\n    // multiple estimation runs (e.g. for use with bias correction\n\tdouble fpkm() const {return _fpkm; }\n\tvoid fpkm(double fpkm) { _fpkm = fpkm; }\n    \n    double num_fragments() const {return _num_fragments; }\n\tvoid num_fragments(double nf) { _num_fragments = nf; }\n \n\tconst string& seq() const { return _seq; } \n\tvoid seq(const string& s) {\t_seq = s; } \n\t\n\tdouble gc_content() const\n\t{\n\t\tif (_seq != \"\")\n\t\t{\n\t\t\tint count = 0;\n\t\t\tfor(size_t i = 0; i < _seq.length(); ++i)\n\t\t\t{\n\t\t\t\tif (_seq[i] == 'G' or _seq[i] == 'g' or _seq[i] == 'C' or _seq[i] == 'c')\n\t\t\t\t\tcount ++;\n\t\t\t}\n\t\t\treturn count/double(_seq.length());\n\t\t}\n\t\treturn -1.0;\n\t}\n\t\n\tchar nearest_ref_classcode() const { return _classcode; }\n\tvoid nearest_ref_classcode(char cc) { _classcode = cc; }\n\t\n\tbool has_intron() const { return _has_intron; }\n\tbool has_suspicious_unknown() const { return has_suspicious_unknown(*this); }\n\n    // returns the fraction coverage of internal exons, returns 0 if no internal exons\n\tdouble internal_exon_coverage() const;\n    \n    // returns true if the scaffold strand is supported with reads or exon overlap with\n    // a reference scaffold of known strand (since the scaffold may have been created with faux reads)\n    bool has_strand_support(vector<boost::shared_ptr<Scaffold> >* ref_scaffs = NULL) const;\n    \n    // returns true if all introns are supported with splice reads, false ow\n    bool hits_support_introns() const; \n    bool hits_support_introns(set<AugmentedCuffOp>& hit_introns) const; \n\n    // returns true if all internal exons are fully covered and hits support introns, false ow\n    bool has_struct_support(set<AugmentedCuffOp>& hit_introns) const;\n    \n\tbool is_ref() const { return _is_ref; }\n\tvoid is_ref(bool ir) { _is_ref = ir; }\n    \n    bool is_pseudo_primary() const { return _is_pseudo_primary; }\n\tvoid is_pseudo_primary(bool ip) { _is_pseudo_primary = ip; }\n\t\n\tCuffStrand strand() const \n    { \n        return _strand; \n    }\n    \n\tvoid strand(CuffStrand strand) \n    { \n\t\tassert(!has_strand_support() || _strand != CUFF_STRAND_UNKNOWN);\n        _strand = strand; \n    }\n\t\n\t// Could we merge lhs and rhs together?\n\tstatic bool compatible(const Scaffold& lhs, \n\t\t\t\t\t\t   const Scaffold& rhs,\n\t\t\t\t\t\t   int overhang_tolerance = bowtie_overhang_tolerance);\n\t\n\tstatic bool strand_agree(const Scaffold& lhs, \n\t\t\t\t\t\t\t const Scaffold& rhs);\n\t\n\tstatic bool exons_overlap(const Scaffold& lhs,\n\t\t\t\t\t\t\t  const Scaffold& rhs);\n\t\n\t// Incorporate Scaffold chow into this one.\n\tstatic void merge(const Scaffold& lhs, \n\t\t\t\t\t  const Scaffold& rhs, \n\t\t\t\t\t  Scaffold& merged,\n\t\t\t\t\t  bool introns_overwrite_matches);\n\t\n\tstatic void merge(const vector<Scaffold>& s, \n\t\t\t\t\t  Scaffold& merged,\n\t\t\t\t\t  bool introns_overwrite_matches);\n\n\t// Extend 5' end using beginning of other scaffold without adding new exons.\n\tvoid extend_5(const Scaffold& other);\n\t// Clip final 3' exon by given amount\n\tvoid trim_3(int to_remove);\n    \n    // Extend final 3' exon by given amount\n    void extend_3(int to_add);\n\n\tvoid tile_with_scaffs(vector<Scaffold>& tile_scaffs, int max_len, int tile_offset) const;\n\n\t// Creates a scaffold that matches this one but only covers the section from g_left for\n\t// a distance of match_length.  It is assumed that this region is contained in the scaffold.\n\t// sub_scaff should be an empty Scaffold object.\n\tbool sub_scaffold(Scaffold& sub_scaff, int g_left, int match_length) const;\n\n \t// Tests whether the other scaffold is contained allowing the given overhang\n\tbool contains(const Scaffold& other, int ohang_5 = 0, int ohang_3 = 0) const\n\t{\n\t\tif (left() <= other.left() && right()>= other.right())\n\t\t\treturn true;\n\t\t\n        if (!(ohang_5 || ohang_3))\n            return false;\n        \n\t\tint left_hang;\n\t\tint right_hang;\n\t\tswitch(strand())\n\t\t{\n\t\t\tcase CUFF_FWD:\n\t\t\t\tleft_hang = ohang_5;\n\t\t\t\tright_hang = ohang_3;\n\t\t\t\tbreak;\n\t\t\tcase CUFF_REV:\n\t\t\t\tleft_hang = ohang_3;\n\t\t\t\tright_hang = ohang_5;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tleft_hang = max(ohang_3, ohang_5);\n\t\t\t\tright_hang = left_hang;\n\t\t}\n\t\t\t\t\n\t\t// Test to see if it is contained within the relaxed boundaries\n\t\tif ((left()-left_hang) <= other.left() && (right() + right_hang) >= other.right())\n\t\t{\n\t\t\t// Ensure that there are no exons outside of the strict boundaries\n\t\t\treturn (other.augmented_ops().front().g_right() > left() && other.augmented_ops().back().g_left() < right()); \n\t\t}\n\t\t\n\t\treturn false;\n\n\t}\n\t\n\t// Tests whether the other scaffold contains the 5' end and is contained (allowing some overhang) on the 3' end\n\t// There can be no additional exons on the 5' end\n\tbool overlapped_3(const Scaffold& other, int ohang_5 = 0, int ohang_3 = 0) const\n\t{\n\t\tswitch(strand())\n\t\t{\n\t\t\tcase CUFF_FWD:\n\t\t\t\treturn((left() + ohang_5 >= other.left() && right() + ohang_3 >= other.right()) && other.augmented_ops().front().g_right() > left());\n\t\t\tcase CUFF_REV:\n\t\t\t\treturn ((right() - ohang_5 <= other.right() && left() - ohang_3 <= other.left()) && other.augmented_ops().back().g_left() < right());\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\t\n\tint match_length(int left, int right) const;\n\t\n\tint length() const\n\t{\n\t\t\n\t\tif(_seq != \"\")\n\t\t\treturn _seq.length();\n\t\t\n\t\tint len = 0;\n\t\t\n\t\t// FIXME: this estimate really should include estimates of the CUFF_UNKNOWN lengths\n\t\t// for better abundance estimation.\n\n\t\tfor (size_t j = 0; j < _augmented_ops.size(); ++j)\n\t\t{\n\t\t\tif (_augmented_ops[j].opcode == CUFF_MATCH)\n\t\t\t\tlen += _augmented_ops[j].genomic_length; \n\t\t}\n\n\t\t\n\t\treturn len;\n\t}\n\t\n\t//void augmented_ops(vector<AugmentedCuffOp>& augmented) const;\n\t\n\t// The \"score\" of a merge is the log odds of lhs and rhs coming from\n\t// different transcripts.  We want to minimize the total score of \n\t// all of our merges.\n\tstatic double score_merge(const Scaffold& lhs, const Scaffold& rhs);\n\t\n\tdouble score() const;\n\t\n\tdouble worst_mate_score() const;\n\t\n\tpair<int,int> genomic_to_transcript_span(pair<int,int> g_span) const;\n\tint genomic_to_transcript_coord(int g_coord) const;\n\tbool map_frag(const MateHit& hit, int& start, int& end, int& frag_len) const;\n\n\t\n\tstatic bool g_left_lt(const AugmentedCuffOp& lhs,\n\t\t\t\t\t\t  const AugmentedCuffOp& rhs);\n\t\n\tconst vector<AugmentedCuffOp>& augmented_ops() const { return _augmented_ops; }\n\tvoid augmented_ops(vector<AugmentedCuffOp> aug_ops) { _augmented_ops = aug_ops; }\n\n\t\n\tstatic bool overlap_in_genome(const Scaffold& lhs, \n\t\t\t\t\t\t\t\t  const Scaffold& rhs, \n\t\t\t\t\t\t\t\t  int overlap_radius);\n\t\n\tvector<pair< int, int> > gaps() const\n\t{\n\t\tvector<pair<int,int> > g;\n\t\tconst vector<AugmentedCuffOp>& ops = augmented_ops();\n\t\tfor (size_t j = 0; j < ops.size(); ++j)\n\t\t{\n\t\t\tif (ops[j].opcode == CUFF_INTRON)\n\t\t\t{\n\t\t\t\tg.push_back(make_pair(ops[j].g_left(), ops[j].g_right()));\n\t\t\t}\n\t\t}\n\t\treturn g;\n\t}\n\t\n\tinline bool has_unknown() const\n\t{\n\t\tconst vector<AugmentedCuffOp>& ops = augmented_ops();\n\t\tfor (size_t j = 0; j < ops.size(); ++j)\n\t\t{\n\t\t\tif (ops[j].opcode == CUFF_UNKNOWN)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n    // Fills in CUFF_UNKNOWNs up to filled_gap_size long\n\tvoid fill_gaps(int filled_gap_size);\n    \n    // Fills in CUFF_UNKNOWNs with the contents of filler.  Filler must be\n    // a sortted, contiguous, non-overlapping vector of AugmentedCuffOps\n    void fill_gaps(const vector<AugmentedCuffOp>& filler);\n\t\n\tvoid clear_hits();\n\tbool add_hit(const MateHit*);\n\t\n\tvoid get_complete_subscaffolds(vector<Scaffold>& complete);\nprivate: \n\t\n\tvoid initialize_exon_lists();\n\t\n\tstatic bool has_intron(const Scaffold& scaff)\n\t{\n\t\t\n\t\tconst vector<AugmentedCuffOp>& ops = scaff.augmented_ops();\n\t\tfor (size_t j = 0; j < ops.size(); ++j)\n\t\t{\n\t\t\tif (ops[j].opcode == CUFF_INTRON)\n\t\t\t\treturn true;\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\tstatic bool has_suspicious_unknown(const Scaffold& scaff)\n\t{\n\t\t\n\t\tconst vector<AugmentedCuffOp>& ops = scaff.augmented_ops();\n\t\tfor (size_t j = 0; j < ops.size(); ++j)\n\t\t{\n\t\t\tif (ops[j].opcode == CUFF_UNKNOWN && \n\t\t\t\tops[j].genomic_length > max_frag_len)\n\t\t\t\treturn true;\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\tstatic double score_overlap(const AugmentedCuffOp& op, \n\t\t\t\t\t\t\t\tint inner_left_edge, \n\t\t\t\t\t\t\t\tint inner_right_edge);\n\t\n\tstatic double score_contigs(const Scaffold& contig,\n\t\t\t\t\t\t\t\tconst vector<pair<int, int> >& inners);\n\t\n\tstatic double min_score(const Scaffold& contig, \n\t\t\t\t\t\t\tconst vector<pair<int, int> >& inners);\n\t\n\tstatic bool compatible_contigs(const Scaffold& lhs, \n\t\t\t\t\t\t\t\t\t\t\tconst Scaffold& rhs,\n\t\t\t\t\t\t\t\t\t\t\tint overhang_tolerance = bowtie_overhang_tolerance);\n\t\n\t\n\ttypedef vector<AugmentedCuffOp> OpList;\n\t\n\tbool check_merge_length(const vector<AugmentedCuffOp>& ops);\n\t\n\tstatic void fill_interstices(vector<AugmentedCuffOp>& to_fill,\n\t\t\t\t\t\t\t\t const vector<AugmentedCuffOp>& filler,\n\t\t\t\t\t\t\t\t bool allow_flank_fill);\n\t\n\tstatic void merge_ops(const std::vector<AugmentedCuffOp>& ops, \n\t\t\t\t\t\t  vector<AugmentedCuffOp>& merged,\n\t\t\t\t\t\t  bool introns_overwrite_matches);\n\t\n\tvector<const MateHit*> _mates_in_scaff;\n\t\n\tbool _has_intron; \n\tbool _is_ref;\n    bool _is_pseudo_primary;\n\t\n\tvector<AugmentedCuffOp> _augmented_ops;\n\tCuffStrand _strand;\n\t\n\tstring _annotated_trans_id;\n\tstring _annotated_gene_id;\n\tstring _annotated_gene_name;\n\tstring _annotated_protein_id;\n\tstring _annotated_tss_id;\n\tstring _nearest_ref_id;\n\tchar _classcode;\n\t\n\tstring _seq;\n\tdouble _fpkm;\n\tdouble _num_fragments;\n};\n\nbool scaff_lt(const Scaffold& lhs, const Scaffold& rhs);\nbool scaff_lt_rt(const Scaffold& lhs, const Scaffold& rhs);\nbool scaff_lt_rt_oplt(const Scaffold& lhs, const Scaffold& rhs);\nbool scaff_lt_sp(boost::shared_ptr<Scaffold> lhs, boost::shared_ptr<Scaffold> rhs);\nbool scaff_lt_rt_sp(boost::shared_ptr<Scaffold> lhs, boost::shared_ptr<Scaffold> rhs);\nbool scaff_lt_rt_oplt_sp(boost::shared_ptr<Scaffold> lhs, boost::shared_ptr<Scaffold> rhs);\n\n\nbool overlap_in_genome(int ll, int lr, int rl, int rr);\n\nstruct StructurallyEqualScaffolds\n{\n\tbool operator()(boost::shared_ptr<Scaffold> lhs, boost::shared_ptr<Scaffold> rhs)\n\t{\n\t\treturn lhs->ref_id() == rhs->ref_id() && \n\t\tlhs->augmented_ops() == rhs->augmented_ops();\n\t}\n};\n\n#endif\n"
  },
  {
    "path": "src/tokenize.cpp",
    "content": "#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string>\n#include <vector>\n#include <cassert>\n\nusing namespace std;\n\n/**\n * Split string s according to given delimiters.  Mostly borrowed\n * from C++ Programming HOWTO 7.3.\n */\nvoid tokenize(const string& s, const string& delims, vector<string>& ss) {\n\tstring::size_type lastPos = s.find_first_not_of(delims, 0);\n\tstring::size_type pos = s.find_first_of(delims, lastPos);\n\twhile (string::npos != pos || string::npos != lastPos) {\n\t\tss.push_back(s.substr(lastPos, pos - lastPos));\n        lastPos = s.find_first_not_of(delims, pos);\n        pos = s.find_first_of(delims, lastPos);\n    }\n}\n\n/**\n * Split string s according to given delimiters. If two delimiters occur in\n * succession, sticks an empty string token at that position in ss\n */\nvoid tokenize_strict(const string& s, const string& delims, vector<string>& ss) {\n\tstring::size_type lastPos = s.find_first_not_of(delims, 0);\n\tstring::size_type pos = s.find_first_of(delims, lastPos);\n\twhile (lastPos < s.length() || pos < s.length()) {\n\t\tss.push_back(s.substr(lastPos, pos - lastPos));\n\t\tif (pos == string::npos)\n\t\t\tbreak;\n        lastPos = pos + 1;\n        pos = s.find_first_of(delims, lastPos);\n    }\n}\n"
  },
  {
    "path": "src/tokenize.h",
    "content": "#ifndef TOKENIZE_H_\n#define TOKENIZE_H_\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string>\n#include <vector>\n\nvoid tokenize(const std::string& s,\n              const std::string& delims,\n              std::vector<std::string>& ss);\n\nvoid tokenize_strict(const std::string& s,\n                     const std::string& delims, \n                     std::vector<std::string>& ss);\n#endif /*TOKENIZE_H_*/\n"
  },
  {
    "path": "src/tracking.cpp",
    "content": "#include \"tracking.h\"\n\nvoid add_to_tracking_table(size_t sample_index,\n                           Abundance& ab,\n\t\t\t\t\t\t   FPKMTrackingTable& track)\n\n{\n\tpair<FPKMTrackingTable::iterator,bool> inserted;\n\tpair<string, FPKMTracking > p;\n\tp = make_pair(ab.description(), FPKMTracking());\n\tinserted = track.insert(p);\n\t\n\tFPKMTracking& fpkm_track = inserted.first->second;\n\t\n\tset<string> tss = ab.tss_id();\n    set<string> gene_ids = ab.gene_id();\n\tset<string> genes = ab.gene_name();\n\tset<string> proteins = ab.protein_id();\n\t\n\tfpkm_track.tss_ids.insert(tss.begin(), tss.end());\n    fpkm_track.gene_ids.insert(gene_ids.begin(), gene_ids.end());\n\tfpkm_track.gene_names.insert(genes.begin(), genes.end());\n\tfpkm_track.protein_ids.insert(proteins.begin(), proteins.end());\n\t\n\tif (inserted.second)\n\t{\n\t\tfpkm_track.locus_tag = ab.locus_tag();\n\t\tfpkm_track.description = ab.description();\n\t\tboost::shared_ptr<Scaffold> transfrag = ab.transfrag();\n\t\tif (transfrag && transfrag->nearest_ref_id() != \"\")\n\t\t{\n\t\t\tfpkm_track.classcode = transfrag->nearest_ref_classcode();\n\t\t\tfpkm_track.ref_match = transfrag->nearest_ref_id();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfpkm_track.classcode = 0;\n\t\t\tfpkm_track.ref_match = \"-\";\n\t\t}\n        if (transfrag)\n        {\n            fpkm_track.length = transfrag->length();\n        }\n        else\n        {\n            fpkm_track.length = 0;\n        }\n\t}\n\t\n\tFPKMContext r1 = FPKMContext(ab.num_fragments(),\n                                 ab.num_fragment_var(),\n                                 ab.num_fragment_uncertainty_var(),\n                                 ab.mass_variance(),\n                                 ab.num_fragments_by_replicate(),\n\t\t\t\t\t\t\t\t ab.FPKM(),\n\t\t\t\t\t\t\t\t ab.FPKM_by_replicate(),\n                                 ab.FPKM_variance(),\n                                 ab.FPKM_conf().low,\n                                 ab.FPKM_conf().high,\n                                 ab.status(),\n                                 ab.status_by_replicate(),\n                                 ab.fpkm_samples(),\n                                 ab.gamma());\n    \n    \n\t\n    vector<FPKMContext>& fpkms = inserted.first->second.fpkm_series;\n    if (sample_index < fpkms.size())\n    {\n        // if the fpkm series already has an entry matching this description\n        // for this sample index, then we are dealing with a group of transcripts\n        // that occupies multiple (genomically disjoint) bundles.  We need\n        // to add this bundle's contribution to the FPKM, fragments, and variance\n        // to whatever's already there.\n        \n        // NOTE: we can simply sum the FKPM_variances, because we are currently\n        // assuming that transcripts in disjoint bundles share no alignments and\n        // thus have FPKM covariance == 0;  This assumption will no longer be\n        // true if we decide to do multireads the right way.\n        \n        FPKMContext& existing = fpkms[sample_index];\n        existing.FPKM += r1.FPKM;\n        existing.count_mean += r1.count_mean;\n        existing.FPKM_variance += r1.FPKM_variance;\n        if (existing.status == NUMERIC_FAIL || r1.status == NUMERIC_FAIL)\n        {\n            existing.status = NUMERIC_FAIL;\n        }\n        else\n        {\n            existing.status = NUMERIC_OK;\n        }\n        \n    }\n    else\n    {\n        fpkms.push_back(r1);\n    }\n}\n"
  },
  {
    "path": "src/tracking.h",
    "content": "#include \"abundances.h\"\n\nstruct TrackingInfoPerRep\n{\n    boost::shared_ptr<const ReadGroupProperties> rg_props;\n    double fpkm;\n    double count;\n    AbundanceStatus status;\n};\n\nstruct FPKMContext\n{\n\tFPKMContext(double cm,\n                double cv,\n                double cuv,\n                double cdv,\n                const CountPerReplicateTable& cpr,\n                double r,\n                const FPKMPerReplicateTable& fpr,\n                double v,\n                double fcl,\n                double fch,\n                AbundanceStatus s,\n                const StatusPerReplicateTable& spr,\n                const vector<double>& fs,\n                double g)\n    : count_mean(cm),\n    count_var(cv),\n    count_uncertainty_var(cuv),\n    count_dispersion_var(cdv),\n    \n    FPKM(r),\n    FPKM_variance(v),\n    FPKM_conf_lo(fcl),\n    FPKM_conf_hi(fch),\n    status(s),\n    \n    fpkm_samples(fs),\n    gamma(g)\n    {\n        assert (fpr.size() == cpr.size());\n        assert (fpr.size() == spr.size());\n        assert (cpr.size() == spr.size());\n        \n        // TODO: should check for proper alignment of these tables...\n        for (CountPerReplicateTable::const_iterator itr = cpr.begin(); itr != cpr.end(); ++itr)\n        {\n            TrackingInfoPerRep info;\n            \n            info.rg_props = itr->first;\n            info.count = itr->second;\n            \n            FPKMPerReplicateTable::const_iterator f_itr = fpr.find(itr->first);\n            if (f_itr != fpr.end())\n                info.fpkm = f_itr->second;\n            \n            StatusPerReplicateTable::const_iterator s_itr = spr.find(itr->first);\n            if (s_itr != spr.end())\n                info.status = s_itr->second;\n            \n            tracking_info_per_rep.push_back(info);\n        }\n        \n        vector<TrackingInfoPerRep>(tracking_info_per_rep).swap(tracking_info_per_rep);\n    }\n    \n\tdouble count_mean;\n    double count_var;\n    double count_uncertainty_var;\n    double count_dispersion_var;\n    vector<TrackingInfoPerRep> tracking_info_per_rep;\n\tdouble FPKM;\n\tdouble FPKM_variance;\n    double FPKM_conf_lo;\n    double FPKM_conf_hi;\n    AbundanceStatus status;\n    vector<double> fpkm_samples;\n    double gamma;\n};\n\nstruct FPKMTracking\n{\n\tstring locus_tag;\n\tchar classcode;\n\tset<string> tss_ids; // for individual isoforms only\n    set<string> gene_ids;\n\tset<string> gene_names;\n\tset<string> protein_ids;\n\tstring description; // isoforms or tss groups (e.g.) involved in this test\n\tstring ref_match;\n    int length;\n\t\n    vector<vector<boost::shared_ptr<const ReadGroupProperties> > > rg_props;\n    \n\tvector<FPKMContext> fpkm_series;\n};\n\ntypedef map<string,  FPKMTracking> FPKMTrackingTable;\n\nstruct Tracking\n{\n\tFPKMTrackingTable isoform_fpkm_tracking;\n\tFPKMTrackingTable tss_group_fpkm_tracking;\n\tFPKMTrackingTable gene_fpkm_tracking;\n\tFPKMTrackingTable cds_fpkm_tracking;\n    \n    void clear()\n    {\n        isoform_fpkm_tracking.clear();\n        tss_group_fpkm_tracking.clear();\n        gene_fpkm_tracking.clear();\n        cds_fpkm_tracking.clear();\n    }\n};\n\nvoid add_to_tracking_table(size_t sample_index,\n                           Abundance& ab,\n\t\t\t\t\t\t   FPKMTrackingTable& track);\n"
  },
  {
    "path": "src/transitive_closure.h",
    "content": "/*\n *  transitive_closure.h\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/26/09.\n *  Copyright 2009 Cole Trapnell. All rights reserved.\n *\n */\n\n// This file was modified from transitive_closure.hpp in Boost.\n// The original copyright info is listed below\n\n// Copyright (C) 2001 Vladimir Prus <ghost@cs.msu.su>\n// Copyright (C) 2001 Jeremy Siek <jsiek@cs.indiana.edu>\n// Distributed under the Boost Software License, Version 1.0. (See\n// accompanying file LICENSE_1_0.txt or copy at\n// http://www.boost.org/LICENSE_1_0.txt)\n\n#ifndef BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP\n#define BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <vector>\n#include <algorithm> // for std::min and std::max\n#include <functional>\n#include <boost/config.hpp>\n#include <boost/bind.hpp>\n#include <boost/graph/vector_as_graph.hpp>\n#include <boost/graph/strong_components.hpp>\n#include <boost/graph/topological_sort.hpp>\n#include <boost/graph/graph_concepts.hpp>\n#include <boost/graph/named_function_params.hpp>\n\t\ntypedef uint16_t v_id_size_type;\n\ninline void\nunion_successor_sets(const std::vector < v_id_size_type > &s1,\n\t\t\t\t\t const std::vector < v_id_size_type > &s2,\n\t\t\t\t\t std::vector < v_id_size_type > &s3)\n{\n\tBOOST_USING_STD_MIN();\n\tfor (std::size_t k = 0; k < s1.size(); ++k)\n\t\ts3[k] = min BOOST_PREVENT_MACRO_SUBSTITUTION(s1[k], s2[k]);\n}\n\ntemplate < typename Container, \n\t\t   typename ST = std::size_t,\n           typename VT = typename Container::value_type >\nstruct subscript_t : public std::unary_function < ST, VT >\n{\n\ttypedef VT& result_type;\n\n\tsubscript_t(Container & c):container(&c)\n\t{\n\t}\n\tVT & operator() (const ST & i) const\n\t{\n\t\treturn (*container)[i];\n\t}\nprotected:\n\tContainer * container;\n};\n\ntemplate < typename Container >\nsubscript_t < Container > subscript(Container & c) {\n\treturn subscript_t < Container > (c);\n}\n\ntemplate < typename Graph, \n\t\t   typename GraphTC,\n           typename G_to_TC_VertexMap,\n\t\t   typename VertexIndexMap >\nvoid transitive_closure(const Graph & g, GraphTC & tc,\n\t\t\t\t\t\tG_to_TC_VertexMap g_to_tc_map,\n\t\t\t\t\t\tVertexIndexMap index_map)\n{\n    if (boost::num_vertices(g) == 0)\n\t\treturn;\n    typedef typename boost::graph_traits < Graph >::vertex_descriptor vertex;\n    typedef typename boost::graph_traits < Graph >::edge_descriptor edge;\n    typedef typename boost::graph_traits < Graph >::vertex_iterator vertex_iterator;\n    //typedef typename property_traits < VertexIndexMap >::value_type size_type;\n\n    typedef typename boost::graph_traits <\n\tGraph >::adjacency_iterator adjacency_iterator;\n\t\n    boost::function_requires < boost::VertexListGraphConcept < Graph > >();\n    boost::function_requires < boost::AdjacencyGraphConcept < Graph > >();\n    boost::function_requires < boost::VertexMutableGraphConcept < GraphTC > >();\n    boost::function_requires < boost::EdgeMutableGraphConcept < GraphTC > >();\n    boost::function_requires < boost::ReadablePropertyMapConcept < VertexIndexMap,\n\tvertex > >();\n\t\n    typedef v_id_size_type cg_vertex;\n    std::vector < cg_vertex > component_number_vec(boost::num_vertices(g));\n    boost::iterator_property_map < cg_vertex *, VertexIndexMap, cg_vertex, cg_vertex& >\n\tcomponent_number(&component_number_vec[0], index_map);\n\t\n    //int num_scc = strong_components(g, component_number,\n    //                                vertex_index_map(index_map));\n\t\n\tsize_t cn = 0;\n\tvertex_iterator cu, cu_end;\n\tfor (boost::tie(cu, cu_end) = vertices(g); cu != cu_end; ++cu) {\n\t\tcomponent_number[*cu] = cn++;\n\t\t//fprintf(stderr, \"%d\\n\", component_number[*cu]);\n\t}\n\t\n    std::vector < std::vector < vertex > >components;\n    build_component_lists(g, boost::num_vertices(g), component_number, components);\n\t\n    typedef std::vector<std::vector<cg_vertex> > CG_t;\n    CG_t CG(boost::num_vertices(g));\n\n\tfor (cg_vertex s = 0; s < components.size(); ++s) {\n\t\tstd::vector < cg_vertex > adj;\n\t\t\n\t\tvertex u = components[s][0];\n\n\t\tadjacency_iterator v, v_end;\n\t\tfor (boost::tie(v, v_end) = boost::adjacent_vertices(u, g); v != v_end; ++v) {\n\t\t\tcg_vertex t = component_number[*v];\n\t\t\tif (s != t)           // Avoid loops in the condensation graph\n\t\t\t\tadj.push_back(t);\n\t\t}\n\n\t\tstd::sort(adj.begin(), adj.end());\n\t\ttypename std::vector<cg_vertex>::iterator di =\n        std::unique(adj.begin(), adj.end());\n\t\tif (di != adj.end())\n\t\t\tadj.erase(di, adj.end());\n\t\tCG[s] = adj;\n    }\n\t\n    std::vector<cg_vertex> topo_order;\n    std::vector<cg_vertex> topo_number(boost::num_vertices(CG));\n    topological_sort(CG, std::back_inserter(topo_order),\n                     vertex_index_map(boost::identity_property_map()));\n    std::reverse(topo_order.begin(), topo_order.end());\n    v_id_size_type n = 0;\n    for (typename std::vector<cg_vertex>::iterator iter = topo_order.begin();\n         iter != topo_order.end(); ++iter)\n\t\ttopo_number[*iter] = n++;\n\t\n    for (size_t i = 0; i < boost::num_vertices(CG); ++i)\n\t\tstd::sort(CG[i].begin(), CG[i].end(),\n\t\t\t\t  boost::bind(std::less<cg_vertex>(),\n\t\t\t\t\t\t\t  boost::bind(subscript(topo_number), _1),\n\t\t\t\t\t\t\t  boost::bind(subscript(topo_number), _2)));\n\t\n    std::vector<std::vector<cg_vertex> > chains;\n    {\n\t\tstd::vector<cg_vertex> in_a_chain(boost::num_vertices(CG));\n\t\tfor (typename std::vector<cg_vertex>::iterator i = topo_order.begin();\n\t\t\t i != topo_order.end(); ++i) {\n\t\t\tcg_vertex v = *i;\n\t\t\tif (!in_a_chain[v]) {\n\t\t\t\tchains.resize(chains.size() + 1);\n\t\t\t\tstd::vector<cg_vertex>& chain = chains.back();\n\t\t\t\tfor (;;) {\n\t\t\t\t\tchain.push_back(v);\n\t\t\t\t\tin_a_chain[v] = true;\n\t\t\t\t\ttypename boost::graph_traits<CG_t>::adjacency_iterator adj_first, adj_last;\n\t\t\t\t\tboost::tie(adj_first, adj_last) = boost::adjacent_vertices(v, CG);\n\t\t\t\t\ttypename boost::graph_traits<CG_t>::adjacency_iterator next\n\t\t\t\t\t= std::find_if(adj_first, adj_last,\n\t\t\t\t\t\t\t\t   std::not1(subscript(in_a_chain)));\n\t\t\t\t\tif (next != adj_last)\n\t\t\t\t\t\tv = *next;\n\t\t\t\t\telse\n\t\t\t\t\t\tbreak;            // end of chain, dead-end\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t}\n    }\n    std::vector<v_id_size_type> chain_number(boost::num_vertices(CG));\n    std::vector<v_id_size_type> pos_in_chain(boost::num_vertices(CG));\n    for (size_t i = 0; i < chains.size(); ++i)\n\t\tfor (size_t j = 0; j < chains[i].size(); ++j) {\n\t\t\tcg_vertex v = chains[i][j];\n\t\t\tchain_number[v] = i;\n\t\t\tpos_in_chain[v] = j;\n\t\t}\n\t\n    cg_vertex inf = (std::numeric_limits< cg_vertex >::max)();\n    std::vector<std::vector<cg_vertex> > successors(boost::num_vertices(CG),\n                                                    std::vector<cg_vertex>\n                                                    (chains.size(), inf));\n    for (typename std::vector<cg_vertex>::reverse_iterator\n\t\t i = topo_order.rbegin(); i != topo_order.rend(); ++i) {\n\t\tcg_vertex u = *i;\n\t\ttypename boost::graph_traits<CG_t>::adjacency_iterator adj, adj_last;\n\t\tfor (boost::tie(adj, adj_last) = boost::adjacent_vertices(u, CG);\n\t\t\t adj != adj_last; ++adj) {\n\t\t\tcg_vertex v = *adj;\n\t\t\tif (topo_number[v] < successors[u][chain_number[v]]) {\n\t\t\t\t// Succ(u) = Succ(u) U Succ(v)\n\t\t\t\tunion_successor_sets(successors[u], successors[v],\n\t\t\t\t\t\t\t\t\t\t\t successors[u]);\n\t\t\t\t// Succ(u) = Succ(u) U {v}\n\t\t\t\tsuccessors[u][chain_number[v]] = topo_number[v];\n\t\t\t}\n\t\t}\n    }\n\t\n    for (size_t i = 0; i < CG.size(); ++i)\n\t\tCG[i].clear();\n    for (size_t i = 0; i < CG.size(); ++i)\n\t\tfor (size_t j = 0; j < chains.size(); ++j) {\n\t\t\tsize_t topo_num = successors[i][j];\n\t\t\tif (topo_num < inf) {\n\t\t\t\tcg_vertex v = topo_order[topo_num];\n\t\t\t\tfor (size_t k = pos_in_chain[v]; k < chains[j].size(); ++k)\n\t\t\t\t\tCG[i].push_back(chains[j][k]);\n\t\t\t}\n\t\t}\n\t\n\t\n    // Add vertices to the transitive closure graph\n    typedef typename boost::graph_traits < GraphTC >::vertex_descriptor tc_vertex;\n    {\n\t\tvertex_iterator i, i_end;\n\t\tfor (boost::tie(i, i_end) = boost::vertices(g); i != i_end; ++i)\n\t\t\tg_to_tc_map[*i] = add_vertex(tc);\n    }\n    // Add edges between all the vertices in two adjacent SCCs\n    typename boost::graph_traits<CG_t>::vertex_iterator si, si_end;\n    for (boost::tie(si, si_end) = boost::vertices(CG); si != si_end; ++si) {\n\t\tcg_vertex s = *si;\n\t\ttypename boost::graph_traits<CG_t>::adjacency_iterator i, i_end;\n\t\tfor (boost::tie(i, i_end) = boost::adjacent_vertices(s, CG); i != i_end; ++i) {\n\t\t\tcg_vertex t = *i;\n\t\t\tfor (size_t k = 0; k < components[s].size(); ++k)\n\t\t\t\tfor (size_t l = 0; l < components[t].size(); ++l)\n\t\t\t\t\tadd_edge(g_to_tc_map[components[s][k]],\n\t\t\t\t\t\t\t g_to_tc_map[components[t][l]], tc);\n\t\t}\n    }\n    // Add edges connecting all vertices in a SCC\n    for (size_t i = 0; i < components.size(); ++i)\n\t\tif (components[i].size() > 1)\n\t\t\tfor (size_t k = 0; k < components[i].size(); ++k)\n\t\t\t\tfor (size_t l = 0; l < components[i].size(); ++l) {\n\t\t\t\t\tvertex u = components[i][k], v = components[i][l];\n\t\t\t\t\tadd_edge(g_to_tc_map[u], g_to_tc_map[v], tc);\n\t\t\t\t}\n\t\n    // Find loopbacks in the original graph.\n    // Need to add it to transitive closure.\n    {\n\t\tvertex_iterator i, i_end;\n\t\tfor (boost::tie(i, i_end) = vertices(g); i != i_end; ++i)\n        {\n\t\t\tadjacency_iterator ab, ae;\n\t\t\tfor (boost::tie(ab, ae) = boost::adjacent_vertices(*i, g); ab != ae; ++ab)\n            {\n\t\t\t\tif (*ab == *i)\n\t\t\t\t\tif (components[component_number[*i]].size() == 1)\n\t\t\t\t\t\tadd_edge(g_to_tc_map[*i], g_to_tc_map[*i], tc);\n            }\n        }\n    }\n}\n\ntemplate <typename Graph, typename GraphTC>\nvoid transitive_closure(const Graph & g, GraphTC & tc)\n{\n    if (boost::num_vertices(g) == 0)\n\t\treturn;\n    typedef typename boost::property_map<Graph, boost::vertex_index_t>::const_type\n\tVertexIndexMap;\n    VertexIndexMap index_map = get(boost::vertex_index, g);\n\t\n    typedef typename boost::graph_traits<GraphTC>::vertex_descriptor tc_vertex;\n    std::vector<tc_vertex> to_tc_vec(boost::num_vertices(g));\n    boost::iterator_property_map < tc_vertex *, VertexIndexMap, tc_vertex, tc_vertex&>\n\tg_to_tc_map(&to_tc_vec[0], index_map);\n\t\n    transitive_closure(g, tc, g_to_tc_map, index_map);\n}\n\n\ntemplate < typename Graph, typename GraphTC, typename G_to_TC_VertexMap,\ntypename VertexIndexMap>\nvoid transitive_closure_dispatch\n(const Graph & g, GraphTC & tc,\n G_to_TC_VertexMap g_to_tc_map, VertexIndexMap index_map)\n{\n\ttypedef typename boost::graph_traits < GraphTC >::vertex_descriptor tc_vertex;\n\ttypename std::vector < tc_vertex >::size_type\n\tn = is_default_param(g_to_tc_map) ? boost::num_vertices(g) : 1;\n\tstd::vector < tc_vertex > to_tc_vec(n);\n\t\n\ttransitive_closure\n\t(g, tc,\n\t choose_param(g_to_tc_map, make_iterator_property_map\n\t\t\t\t  (to_tc_vec.begin(), index_map, to_tc_vec[0])),\n\t index_map);\n}\n\n\ntemplate < typename Graph, typename GraphTC,\ntypename P, typename T, typename R >\nvoid transitive_closure(const Graph & g, GraphTC & tc,\n\t\t\t\t\t\tconst boost::bgl_named_params < P, T, R > &params)\n{\n    if (boost::num_vertices(g) == 0)\n\t\treturn;\n    transitive_closure_dispatch\n\t(g, tc, get_param(params, boost::orig_to_copy_t()),\n\t choose_const_pmap(get_param(params, boost::vertex_index), g, boost::vertex_index) );\n}\n\n\ntemplate < typename G > void warshall_transitive_closure(G & g)\n{\n    typedef typename boost::graph_traits < G >::vertex_descriptor vertex;\n    typedef typename boost::graph_traits < G >::vertex_iterator vertex_iterator;\n\t\n    boost::function_requires < boost::AdjacencyMatrixConcept < G > >();\n    boost::function_requires < boost::EdgeMutableGraphConcept < G > >();\n\t\n    // Matrix form:\n    // for k\n    //  for i\n    //    if A[i,k]\n    //      for j\n    //        A[i,j] = A[i,j] | A[k,j]\n    vertex_iterator ki, ke, ii, ie, ji, je;\n    for (boost::tie(ki, ke) = vertices(g); ki != ke; ++ki)\n\t\tfor (boost::tie(ii, ie) = vertices(g); ii != ie; ++ii)\n\t\t\tif (edge(*ii, *ki, g).second)\n\t\t\t\tfor (boost::tie(ji, je) = vertices(g); ji != je; ++ji)\n\t\t\t\t\tif (!edge(*ii, *ji, g).second && edge(*ki, *ji, g).second) {\n\t\t\t\t\t\tadd_edge(*ii, *ji, g);\n\t\t\t\t\t}\n}\n\n\ntemplate < typename G > void warren_transitive_closure(G & g)\n{\n    using namespace boost;\n    typedef typename boost::graph_traits < G >::vertex_descriptor vertex;\n    typedef typename boost::graph_traits < G >::vertex_iterator vertex_iterator;\n\t\n    function_requires < AdjacencyMatrixConcept < G > >();\n    function_requires < EdgeMutableGraphConcept < G > >();\n\t\n    // Make sure second loop will work\n    if (boost::num_vertices(g) == 0)\n\t\treturn;\n\t\n    // for i = 2 to n\n    //    for k = 1 to i - 1\n    //      if A[i,k]\n    //        for j = 1 to n\n    //          A[i,j] = A[i,j] | A[k,j]\n\t\n    vertex_iterator ic, ie, jc, je, kc, ke;\n    for (boost::tie(ic, ie) = vertices(g), ++ic; ic != ie; ++ic)\n\t\tfor (boost::tie(kc, ke) = vertices(g); *kc != *ic; ++kc)\n\t\t\tif (edge(*ic, *kc, g).second)\n\t\t\t\tfor (boost::tie(jc, je) = vertices(g); jc != je; ++jc)\n\t\t\t\t\tif (!edge(*ic, *jc, g).second && edge(*kc, *jc, g).second) {\n\t\t\t\t\t\tadd_edge(*ic, *jc, g);\n\t\t\t\t\t}\n    //  for i = 1 to n - 1\n    //    for k = i + 1 to n\n    //      if A[i,k]\n    //        for j = 1 to n\n    //          A[i,j] = A[i,j] | A[k,j]\n\t\n    for (boost::tie(ic, ie) = vertices(g), --ie; ic != ie; ++ic)\n\t\tfor (kc = ic, ke = ie, ++kc; kc != ke; ++kc)\n\t\t\tif (edge(*ic, *kc, g).second)\n\t\t\t\tfor (boost::tie(jc, je) = vertices(g); jc != je; ++jc)\n\t\t\t\t\tif (!edge(*ic, *jc, g).second && edge(*kc, *jc, g).second) {\n\t\t\t\t\t\tadd_edge(*ic, *jc, g);\n\t\t\t\t\t}\n}\n\n\n#endif\n\n\n"
  },
  {
    "path": "src/transitive_reduction.h",
    "content": "// (C) Copyright 2009 Eric Bose-Wolf\n//\n// Use, modification and distribution are subject to the\n// Boost Software License, Version 1.0 (See accompanying file\n// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)\n\n#ifndef BOOST_GRAPH_TRANSITIVE_REDUCTION_HPP\n#define BOOST_GRAPH_TRANSITIVE_REDUCTION_HPP\n\n#include <vector>\n#include <algorithm> //std::find\n#include <boost/concept/requires.hpp>\n#include <boost/concept_check.hpp>\n\n#include <boost/graph/graph_traits.hpp>\n#include <boost/graph/topological_sort.hpp>\n\n// also I didn't got all of the concepts thin. Am I suppose to check\n// for all concepts, which are needed for functions I call? (As if I\n// wouldn't do that, the users would see the functions called by\n// complaining about missings concepts, which would be clearly an error\n// message revealing internal implementation and should therefore be avoided?)\n\n// the pseudocode which I followed implementing this algorithmn was taken\n// from the german book Algorithmische Graphentheorie by Volker Turau\n// it is proposed to be of O(n + nm_red ) where n is the number\n// of vertices and m_red is the number of edges in the transitive\n// reduction, but I think my implementation spoiled this up at some point\n// indicated below.\n\nnamespace boost {\n    \n    template <\n    typename Graph, typename GraphTR, typename G_to_TR_VertexMap,\n    typename VertexIndexMap\n    >\n    BOOST_CONCEPT_REQUIRES(\n                           ((VertexListGraphConcept< Graph >))\n                           ((IncidenceGraphConcept< Graph >))\n                           ((MutableGraphConcept< GraphTR >))\n                           ((ReadablePropertyMapConcept< VertexIndexMap,\n                             typename graph_traits<Graph>::vertex_descriptor >))\n                           ((Integer< typename\n                             property_traits< VertexIndexMap >::value_type >))\n                           ((LvaluePropertyMapConcept< G_to_TR_VertexMap,\n                             typename graph_traits<Graph>::vertex_descriptor >)),\n                           (void))\n    transitive_reduction(const Graph& g, GraphTR& tr,\n                         G_to_TR_VertexMap g_to_tr_map,\n                         VertexIndexMap g_index_map )\n    {\n        typedef typename graph_traits<Graph>::vertex_descriptor Vertex;\n        typedef typename graph_traits<Graph>::vertex_iterator VertexIterator;\n        typedef typename std::vector<Vertex>::size_type size_type;\n        \n        std::vector<Vertex> topo_order;\n        topological_sort(g, std::back_inserter(topo_order));\n        \n        std::vector<size_type> topo_number_storage(num_vertices(g));\n        \n        iterator_property_map<size_type*, VertexIndexMap,\n        size_type, size_type&> topo_number( &topo_number_storage[0], g_index_map );\n        \n        {\n            typename std::vector<Vertex>::reverse_iterator it = topo_order.rbegin();\n            size_type n = 0;\n            for(; it != topo_order.rend(); ++it,++n ) {\n                topo_number[ *it ] = n;\n            }\n        }\n        \n        std::vector< std::vector< bool > > edge_in_closure(num_vertices(g),\n                                                           std::vector<bool>( num_vertices(g), false));\n        {\n            typename std::vector<Vertex>::reverse_iterator it = topo_order.rbegin();\n            for( ; it != topo_order.rend(); ++it ) {\n                g_to_tr_map[*it] = add_vertex(tr);\n            }\n        }\n        \n        typename std::vector<Vertex>::iterator\n        it = topo_order.begin(),\n        end = topo_order.end();\n        for( ; it != end; ++it ) {\n            size_type i = topo_number[ *it ];\n            edge_in_closure[i][i] = true;\n            std::vector<Vertex> neighbors;\n            \n            //I have to collect the successors of *it and traverse them in\n            //ascending topological order. I didn't know a better way, how to\n            //do that. So what I'm doint is, collection the successors of *it here\n            {\n                typename Graph::out_edge_iterator oi,oi_end;\n                for( tie(oi, oi_end) = out_edges( *it, g ); oi != oi_end; ++oi ) {\n                    neighbors.push_back( target( *oi, g ) );\n                }\n            }\n            \n            {\n                //and run through all vertices in topological order\n                typename std::vector<Vertex>::reverse_iterator rit = topo_order.rbegin();\n                typename std::vector<Vertex>::reverse_iterator rend = topo_order.rend();\n                for(; rit != rend; ++rit ) {\n                    //looking if they are successors of *it\n                    if( std::find( neighbors.begin(), neighbors.end(), *rit) != neighbors.end() ) {\n                        size_type j = topo_number[ *rit ];\n                        if( not edge_in_closure[i][j] ) {\n                            for(size_type k = j; k < num_vertices(g); ++k) {\n                                if( not edge_in_closure[i][k] ) {\n                                    //here we need edge_in_closure to be in topological order,\n                                    edge_in_closure[i][k] = edge_in_closure[j][k];\n                                }\n                            }\n                            //therefore we only access edge_in_closure only through\n                            //topo_number property_map\n                            add_edge(g_to_tr_map[*it], g_to_tr_map[*rit], tr);\n                        } //if ( not edge_in_\n                    } //if (find (\n                } //for( typename vector<Vertex>::reverse_iterator\n            } // {\n            \n        } //for( typename vector<Vertex>::iterator\n        \n    } //void transitive_reduction\n    \n} // namespace boost\n\n#endif\n\n"
  },
  {
    "path": "src/update_check.h",
    "content": "/*\n *  update_check.h\n *  cufflinks\n *  Based on code from http://www.linuxhowtos.org/C_C++/socket.htm\n *  Modified by Adam Roberts on 1/18/11.\n *\n */\n\n#include <signal.h>\n#include <strings.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <netdb.h> \n\nint NUM_SEPS = 3;\nint CONNECT_TIMEOUT = 5;\n\nstatic int sTimeout = 0; \n\nstatic void AlarmHandler(int sig) \n{ \n\tsTimeout = 1; \n} \n\nbool error(const char *msg)\n{\n\treturn false;\n}\n\nint parse_version_str(char* version_str)\n{\n\tint version_int = 0;\n\tchar* token = strtok(version_str,\".\");\n    for(int i = 0; i < NUM_SEPS; ++i)\n    {\n\t\tversion_int += atoi(token)*pow(100.,NUM_SEPS-i);\n\t}\n\treturn version_int;\n}\n\nbool get_current_version(char* curr_version)\n{\n    int sockfd, portno, n;\n    struct sockaddr_in serv_addr;\n    struct hostent *server;\n\t\n    portno = 80;\n    sockfd = socket(AF_INET, SOCK_STREAM, 0);\n    if (sockfd < 0) \n        return error(\"ERROR opening socket\");\n\t\n    server = gethostbyname(\"cole-trapnell-lab.github.io\");\n    if (server == NULL) \n        return error(\"ERROR, no such host\");\n\n    bzero((char *) &serv_addr, sizeof(serv_addr));\n    serv_addr.sin_family = AF_INET;\n    bcopy((char *)server->h_addr, \n\t\t  (char *)&serv_addr.sin_addr.s_addr,\n\t\t  server->h_length);\n    serv_addr.sin_port = htons(portno);\n    \n\tsignal(SIGALRM, AlarmHandler); \n\tsTimeout = 0; \n\talarm(CONNECT_TIMEOUT); \n\t\n\tint ret;\n\tret = connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));\n\tif (ret < 0 || sTimeout)\n\t{\n\t\treturn error(\"ERROR connecting\");\n\t}\n\t\n\tchar buffer[1024];\n    memset(buffer, 0, sizeof(buffer));\n\tstrcpy(buffer, \"GET /cufflinks/curr_cuff_version HTTP/1.1\\nHost: cole-trapnell-lab.github.io\\n\\n\");\n\tn = write(sockfd,buffer,1024);\n\t\n    if (n < 0) \n\t\treturn error(\"ERROR writing to socket\");\n\tbzero(curr_version, sizeof(curr_version));\n    n = read(sockfd,buffer,1024);\n    if (n < 0) \n\t\treturn error(\"ERROR reading from socket\");\n\n\tchar* token;\n\ttoken = strtok(buffer, \"$\");\n\ttoken = strtok(NULL, \"$\");\n\tif (token==NULL)\n\t\treturn error(\"ERROR parsing response\");\n\t\n\tstrcpy(curr_version, token);\n\t\t\n\treturn true;\n}\n\nvoid check_version(const char* this_version)\n{\n\tchar curr_version[256];\n    memset(curr_version, 0, sizeof(curr_version));\n\tif (get_current_version(curr_version))\n\t{\n\t\tif (strcmp(curr_version, this_version)==0)\n\t\t\tfprintf(stderr, \"You are using Cufflinks v%s, which is the most recent release.\\n\", PACKAGE_VERSION);\n\t\telse\n\t\t\tfprintf(stderr, \"Warning: Your version of Cufflinks is not up-to-date. It is recommended that you upgrade to Cufflinks v%s to benefit from the most recent features and bug fixes (http://cole-trapnell-lab.github.io/cufflinks/).\\n\", curr_version);\n\t\t\n\t}\n\telse \n\t{\n\t\tfprintf(stderr, \"Warning: Could not connect to update server to verify current version. Please check at the Cufflinks website (http://cole-trapnell-lab.github.io/cufflinks/).\\n\");\n\t}\n}\n"
  },
  {
    "path": "tests/unit_tests/test_abundances.cpp",
    "content": "/*\n *  test_abundances.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/23/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <cppunit/extensions/HelperMacros.h>\n#include <cppunit/extensions/TestFactoryRegistry.h>\n#include <cppunit/ui/text/TestRunner.h>\n\n//class AutoFail : public CppUnit::TestFixture\n//{\n//\tCPPUNIT_TEST_SUITE( AutoFail );\n//\tCPPUNIT_TEST( testFalse );\n//\tCPPUNIT_TEST( testNotEqual );\n//\tCPPUNIT_TEST_SUITE_END();\n//\t\n//public:\t\n//\tvoid testFalse();\n//\tvoid testNotEqual();\n//};\n//\n//void AutoFail::testFalse()\n//{\n//\tCPPUNIT_ASSERT(false);\n//}\n//\n//void AutoFail::testNotEqual()\n//{\n//\tCPPUNIT_ASSERT_EQUAL(1, 2);\n//}\n//\n//// For testing Xcode integration and CppUnit installation\n//CPPUNIT_TEST_SUITE_REGISTRATION( AutoFail );"
  },
  {
    "path": "tests/unit_tests/test_main.cpp",
    "content": "/*\n *  test_main.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 3/23/10.\n *  Copyright 2010 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <cppunit/extensions/HelperMacros.h>\n#include <cppunit/CompilerOutputter.h>\n#include <cppunit/extensions/TestFactoryRegistry.h>\n#include <cppunit/ui/text/TestRunner.h>\n\n#include <cppunit/Portability.h>\n#include <cppunit/Outputter.h>\n#include <cppunit/portability/Stream.h>\n#include <cppunit/config/SourcePrefix.h>\n#include <cppunit/Exception.h>\n#include <cppunit/SourceLine.h>\n#include <cppunit/TestFailure.h>\n#include <cppunit/TestResultCollector.h>\n#include <cppunit/CompilerOutputter.h>\n#include <algorithm>\n#include <cppunit/tools/StringTools.h>\n\n#include <string>\n\nusing namespace std;\nusing namespace CppUnit;\n\nclass CustomFormatter : public Outputter\n{\npublic:\n\t/*! \\brief Constructs a CompilerOutputter object.\n\t * \\param result Result of the test run.\n\t * \\param stream Stream used to output test result.\n\t * \\param locationFormat Error location format used by your compiler. Default\n\t *                       to \\c CPPUNIT_COMPILER_LOCATION_FORMAT which is defined\n\t *                       in the configuration file. See setLocationFormat() for detail.\n\t * \\see setLocationFormat().\n\t */\n\tCustomFormatter( TestResultCollector *result,\n\t\t\t\t\t  OStream &stream,\n\t\t\t\t\t  const std::string &locationFormat = \"%p:%l: error: \" );\n\t\n\t/// Destructor.\n\tvirtual ~CustomFormatter();\n\t\n\t/*! \\brief Sets the error location format.\n\t * \n\t * Indicates the format used to report location of failed assertion. This format should\n\t * match the one used by your compiler.\n\t *\n\t * The location format is a string in which the occurence of the following character\n\t * sequence are replaced:\n\t *\n\t * - \"%l\" => replaced by the line number\n\t * - \"%p\" => replaced by the full path name of the file (\"G:\\prg\\vc\\cppunit\\MyTest.cpp\")\n\t * - \"%f\" => replaced by the base name of the file (\"MyTest.cpp\")\n\t *\n\t * Some examples:\n\t *\n\t * - VC++ error location format: \"%p(%l):\" => produce \"G:\\prg\\MyTest.cpp(43):\"\n\t * - GCC error location format: \"%f:%l:\" => produce \"MyTest.cpp:43:\"\n\t * \n\t * Thoses are the two compilers currently <em>supported</em> (gcc format is used if\n\t * VC++ is not detected). If you want your compiler to be automatically supported by\n\t * CppUnit, send a mail to the mailing list (preferred), or submit a feature request\n\t * that indicates how to detect your compiler with the preprocessor (\\#ifdef...) and\n\t * your compiler location format.\n\t */\n\tvoid setLocationFormat( const std::string &locationFormat );\n\t\n\t/*! \\brief Creates an instance of an outputter that matches your current compiler.\n\t * \\deprecated This class is specialized through parameterization instead of subclassing...\n\t *             Use CompilerOutputter::CompilerOutputter instead.\n\t */\n\tstatic CustomFormatter *defaultOutputter(TestResultCollector *result,\n\t\t\t\t\t\t\t\t\t\t\t OStream &stream );\n\t\n\tvoid write();\n\t\n\tvoid setNoWrap();\n\t\n\tvoid setWrapColumn( int wrapColumn );\n\t\n\tint wrapColumn() const;\n\t\n\tvirtual void printSuccess();\n\tvirtual void printFailureReport();\n\tvirtual void printFailuresList();\n\tvirtual void printStatistics();\n\tvirtual void printFailureDetail( TestFailure *failure );\n\tvirtual void printFailureLocation( SourceLine sourceLine );\n\tvirtual void printFailureType( TestFailure *failure );\n\tvirtual void printFailedTestName( TestFailure *failure );\n\tvirtual void printFailureMessage( TestFailure *failure );\n\t\nprivate:\n\t/// Prevents the use of the copy constructor.\n\tCustomFormatter( const CustomFormatter &copy );\n\t\n\t/// Prevents the use of the copy operator.\n\tvoid operator =( const CustomFormatter &copy );\n\t\n\tvirtual bool processLocationFormatCommand( char command, \n\t\t\t\t\t\t\t\t\t\t\t  const SourceLine &sourceLine );\n\t\n\tvirtual std::string extractBaseName( const std::string &fileName ) const;\n\t\nprivate:\n\tTestResultCollector *m_result;\n\tOStream &m_stream;\n\tstd::string m_locationFormat;\n\tint m_wrapColumn;\n};\n\nCustomFormatter::CustomFormatter( TestResultCollector *result,\n\t\t\t\t\t\t\t\t\t OStream &stream,\n\t\t\t\t\t\t\t\t\t const std::string &locationFormat )\n: m_result( result )\n, m_stream( stream )\n, m_locationFormat( locationFormat )\n, m_wrapColumn( CPPUNIT_WRAP_COLUMN )\n{\n}\n\n\nCustomFormatter::~CustomFormatter()\n{\n}\n\n\nvoid CustomFormatter::setLocationFormat( const std::string &locationFormat )\n{\n\tm_locationFormat = locationFormat;\n}\n\n\nCustomFormatter* CustomFormatter::defaultOutputter( TestResultCollector *result,\n\t\t\t\t\t\t\t\t\tOStream &stream )\n{\n\treturn new CustomFormatter( result, stream );\n}\n\n\nvoid CustomFormatter::write()\n{\n\tif ( m_result->wasSuccessful() )\n\t\tprintSuccess();\n\telse\n\t\tprintFailureReport();\n}\n\n\nvoid CustomFormatter::printSuccess()\n{\n\tm_stream  << \"OK (\" << m_result->runTests()  << \")\\n\";\n}\n\n\nvoid CustomFormatter::printFailureReport()\n{\n\tprintFailuresList();\n\tprintStatistics();\n}\n\n\nvoid CustomFormatter::printFailuresList()\n{\n\tfor ( int index =0; index < m_result->testFailuresTotal(); ++index)\n\t{\n\t\tprintFailureDetail( m_result->failures()[ index ] );\n\t}\n}\n\n\nvoid CustomFormatter::printFailureDetail( TestFailure *failure )\n{\n\tprintFailureLocation( failure->sourceLine() );\n\t//printFailureType( failure );\n\tprintFailedTestName( failure ); \n\tm_stream << \" \";\n\tprintFailureMessage( failure );\n\tm_stream << endl;\n}\n\n\nvoid CustomFormatter::printFailureLocation( SourceLine sourceLine )\n{\n\tif ( !sourceLine.isValid() )\n\t{\n\t\tm_stream  <<  \"##Failure Location unknown## : \";\n\t\treturn;\n\t}\n\t\n\tstd::string location;\n\tfor ( unsigned int index = 0; index < m_locationFormat.length(); ++index )\n\t{\n\t\tchar c = m_locationFormat[ index ];\n\t\tif ( c == '%'  &&  ( index+1 < m_locationFormat.length() ) )\n\t\t{\n\t\t\tchar command = m_locationFormat[index+1];\n\t\t\tif ( processLocationFormatCommand( command, sourceLine ) )\n\t\t\t{\n\t\t\t\t++index;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t\n\t\tm_stream  << c;\n\t}\n}\n\n\nbool CustomFormatter::processLocationFormatCommand( char command, \n\t\t\t\t\t\t\t\t\t\t\t\tconst SourceLine &sourceLine )\n{\n\tswitch ( command )\n\t{\n\t\tcase 'p':\n\t\t\tm_stream  <<  sourceLine.fileName();\n\t\t\treturn true;\n\t\tcase 'l':\n\t\t\tm_stream  <<  sourceLine.lineNumber();\n\t\t\treturn true;\n\t\tcase 'f':\n\t\t\tm_stream  <<  extractBaseName( sourceLine.fileName() );\n\t\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\n\nstd::string CustomFormatter::extractBaseName( const std::string &fileName ) const\n{\n\tint indexLastDirectorySeparator = fileName.find_last_of( '/' );\n\t\n\tif ( indexLastDirectorySeparator < 0 )\n\t\tindexLastDirectorySeparator = fileName.find_last_of( '\\\\' );\n\t\n\tif ( indexLastDirectorySeparator < 0 )\n\t\treturn fileName;\n\t\n\treturn fileName.substr( indexLastDirectorySeparator +1 );\n}\n\n\nvoid CustomFormatter::printFailureType( TestFailure *failure )\n{\n\tm_stream  <<  (failure->isError() ? \"Error\" : \"Assertion\");\n}\n\n\nvoid CustomFormatter::printFailedTestName( TestFailure *failure )\n{\n\tm_stream << failure->failedTestName();\n}\n\n\nvoid CustomFormatter::printFailureMessage( TestFailure *failure )\n{\n\t\n\tException *thrownException = failure->thrownException();\n\tm_stream  << thrownException->message().shortDescription()  <<  \" \";\n\t\n\tstd::string message = thrownException->message().details();\n\t//if ( m_wrapColumn > 0 )\n\t//\tmessage = StringTools::wrap( message, m_wrapColumn );\n\t\n\tm_stream  <<  message;\n}\n\n\nvoid CustomFormatter::printStatistics()\n{\n\tm_stream  <<  \"Failures !!!\\n\";\n\tm_stream  <<  \"Run: \"  <<  m_result->runTests()  << \"   \"\n\t<<  \"Failure total: \"  <<  m_result->testFailuresTotal()  << \"   \"\n\t<<  \"Failures: \"  <<  m_result->testFailures()  << \"   \"\n\t<<  \"Errors: \"  <<  m_result->testErrors()\n\t<<  \"\\n\";\n}\n\n\nvoid CustomFormatter::setWrapColumn( int wrapColumn )\n{\n\tm_wrapColumn = wrapColumn;\n}\n\n\nvoid CustomFormatter::setNoWrap()\n{\n\tm_wrapColumn = 0;\n}\n\n\nint CustomFormatter::wrapColumn() const\n{\n\treturn m_wrapColumn;\n}\n\n// Harness\nint main(int argc, char* argv[])\n{\n\t// Get the top level suite from the registry\n\tCppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();\n\t\n\t// Adds the test to the list of test to run\n\tCppUnit::TextUi::TestRunner runner;\n\trunner.addTest( suite );\n\t\n\tCustomFormatter* outputter = new CustomFormatter( &runner.result(), std::cerr );\n\t//outputter->setLocationFormat(\"%p:%l: error: \");\n\t//outputter->setNoWrap();\n\t// Change the default outputter to a compiler error format outputter\n\trunner.setOutputter( outputter );\n\t// Run the tests.\n\tbool wasSucessful = runner.run(\"\",false);\n\t\n\t// Return error code 1 if the one of test failed.\n\treturn wasSucessful ? 0 : 1;\n}\n"
  },
  {
    "path": "tests/unit_tests/test_scaffolds.cpp",
    "content": "/*\n *  test_scaffolds.cpp\n *  cufflinks\n *\n *  Created by Cole Trapnell on 1/27/11.\n *  Copyright 2011 Cole Trapnell. All rights reserved.\n *\n */\n\n#include <cppunit/extensions/HelperMacros.h>\n#include <cppunit/extensions/TestFactoryRegistry.h>\n#include <cppunit/ui/text/TestRunner.h>\n\n#include \"common.h\"\n#include \"scaffolds.h\"\n\nclass AugmentedCuffOpTests : public CppUnit::TestFixture\n{\n    // Nomenclature:\n    // I = Intron\n    // M = Match\n    // U = Unknown\n    // d = disjoint (no olap)\n    // s = olap <= bowtie_overhang_tolerance\n    // l = olap > bowtie_overhang_tolerance\n\tCPPUNIT_TEST_SUITE( AugmentedCuffOpTests );\n\n    CPPUNIT_TEST( testMMs );\n    CPPUNIT_TEST( testMMl );\n\n    CPPUNIT_TEST( testMUs );\n    CPPUNIT_TEST( testMUl );\n\n    CPPUNIT_TEST( testIMs );\n    CPPUNIT_TEST( testIMl );\n\n    CPPUNIT_TEST( testIUs );\n    CPPUNIT_TEST( testIUl );\n\n    CPPUNIT_TEST( testUUs );\n    CPPUNIT_TEST( testUUl );\n\n    CPPUNIT_TEST( testIIs );\n    CPPUNIT_TEST( testIIl );\n    \n\tCPPUNIT_TEST_SUITE_END();\n\t\npublic:\t\n    void testMMs();\n    void testMMl();\n    \n    void testMUs();\n    void testMUl();\n    \n    void testIMs();\n    void testIMl();\n    \n    void testIUs();\n    void testIUl();\n    \n    void testUUs();\n    void testUUl();\n    \n    void testIIs();\n    void testIIl(); \n};\n\nvoid AugmentedCuffOpTests::testMMs()\n{\n    AugmentedCuffOp lhs(CUFF_MATCH, 0, 50);\n    AugmentedCuffOp rhs(CUFF_MATCH, 50 - bowtie_overhang_tolerance, 50);\n\tCPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs));\n}\n\nvoid AugmentedCuffOpTests::testMMl()\n{\n    AugmentedCuffOp lhs(CUFF_MATCH, 0, 50);\n    AugmentedCuffOp rhs(CUFF_MATCH, 50 - 2 * bowtie_overhang_tolerance, 50);\n\tCPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs));\n}\n\nvoid AugmentedCuffOpTests::testMUs()\n{\n    AugmentedCuffOp lhs(CUFF_MATCH, 0, 50);\n    AugmentedCuffOp rhs(CUFF_UNKNOWN, 50 - bowtie_overhang_tolerance, 50);\n\tCPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs));\n}\n\nvoid AugmentedCuffOpTests::testMUl()\n{\n    AugmentedCuffOp lhs(CUFF_MATCH, 0, 50);\n    AugmentedCuffOp rhs(CUFF_UNKNOWN, 50 - 2 * bowtie_overhang_tolerance, 50);\n\tCPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs));\n}\n\nvoid AugmentedCuffOpTests::testIMs()\n{\n    AugmentedCuffOp lhs(CUFF_INTRON, 0, 50);\n    AugmentedCuffOp rhs(CUFF_MATCH, 50 - bowtie_overhang_tolerance, 50);\n\tCPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs));\n}\n\nvoid AugmentedCuffOpTests::testIMl()\n{\n    AugmentedCuffOp lhs(CUFF_INTRON, 0, 50);\n    AugmentedCuffOp rhs(CUFF_MATCH, 50 - 2 * bowtie_overhang_tolerance, 50);\n\tCPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs) == false);\n}\n\n// Note: the cases below will introduce transitivity hazards if unknowns overlapping\n// non-constitutive regions are not ablated before assembly.  We need this\n// compatibility rule for constitutive regions and all quantification\nvoid AugmentedCuffOpTests::testIUs()\n{\n    AugmentedCuffOp lhs(CUFF_INTRON, 0, 50);\n    AugmentedCuffOp rhs(CUFF_UNKNOWN, 50 - bowtie_overhang_tolerance, 50);\n\tCPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs));\n}\n\nvoid AugmentedCuffOpTests::testIUl()\n{\n    AugmentedCuffOp lhs(CUFF_INTRON, 0, 50);\n    AugmentedCuffOp rhs(CUFF_UNKNOWN, 50 - 2 * bowtie_overhang_tolerance, 50);\n    CPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs));\n}\n\n\nvoid AugmentedCuffOpTests::testUUs()\n{\n    AugmentedCuffOp lhs(CUFF_UNKNOWN, 0, 50);\n    AugmentedCuffOp rhs(CUFF_UNKNOWN, 50 - bowtie_overhang_tolerance, 50);\n\tCPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs));\n}\n\nvoid AugmentedCuffOpTests::testUUl()\n{\n    AugmentedCuffOp lhs(CUFF_UNKNOWN, 0, 50);\n    AugmentedCuffOp rhs(CUFF_UNKNOWN, 50 - 2 * bowtie_overhang_tolerance, 50);\n    CPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs));\n}\n\nvoid AugmentedCuffOpTests::testIIs()\n{\n    AugmentedCuffOp lhs(CUFF_INTRON, 0, 50);\n    AugmentedCuffOp rhs(CUFF_INTRON, 50 - 2 * bowtie_overhang_tolerance, 50);\n    CPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs) == false);\n}\n\nvoid AugmentedCuffOpTests::testIIl()\n{\n    AugmentedCuffOp lhs(CUFF_INTRON, 0, 50);\n    AugmentedCuffOp rhs(CUFF_INTRON, 50 - 2 * bowtie_overhang_tolerance, 50);\n    CPPUNIT_ASSERT(AugmentedCuffOp::compatible(lhs, rhs) == false);\n}\n\n\n// For testing Xcode integration and CppUnit installation\nCPPUNIT_TEST_SUITE_REGISTRATION( AugmentedCuffOpTests );\n\n//class AutoFail : public CppUnit::TestFixture\n//{\n//\tCPPUNIT_TEST_SUITE( AutoFail );\n//\tCPPUNIT_TEST( testFalse );\n//\tCPPUNIT_TEST( testNotEqual );\n//\tCPPUNIT_TEST_SUITE_END();\n//\t\n//public:\t\n//\tvoid testFalse();\n//\tvoid testNotEqual();\n//};\n//\n//void AutoFail::testFalse()\n//{\n//\tCPPUNIT_ASSERT(false);\n//}\n//\n//void AutoFail::testNotEqual()\n//{\n//\tCPPUNIT_ASSERT_EQUAL(1, 2);\n//}\n//\n//// For testing Xcode integration and CppUnit installation\n//CPPUNIT_TEST_SUITE_REGISTRATION( AutoFail );"
  },
  {
    "path": "version.m4",
    "content": "m4_define([VERSION_NUMBER], [0.0.0])\n"
  }
]