IRanges/DESCRIPTION0000644000175100017510000000436412612026576014646 0ustar00biocbuildbiocbuildPackage: IRanges Title: Infrastructure for manipulating intervals on sequences Description: The package provides efficient low-level and highly reusable S4 classes for storing ranges of integers, RLE vectors (Run-Length Encoding), and, more generally, data that can be organized sequentially (formally defined as Vector objects), as well as views on these Vector objects. Efficient list-like classes are also provided for storing big collections of instances of the basic classes. All classes in the package use consistent naming and share the same rich and consistent "Vector API" as much as possible. Version: 2.4.1 Author: H. Pages, P. Aboyoun and M. Lawrence Maintainer: Bioconductor Package Maintainer biocViews: Infrastructure, DataRepresentation Depends: R (>= 3.1.0), methods, utils, stats, BiocGenerics (>= 0.15.10), S4Vectors (>= 0.7.19) Imports: stats4 LinkingTo: S4Vectors Suggests: XVector, GenomicRanges, BSgenome.Celegans.UCSC.ce2, RUnit License: Artistic-2.0 Collate: Vector-class-leftovers.R Hits-class-leftovers.R List-class-leftovers.R List-comparison.R AtomicList-class.R Ranges-class.R Ranges-comparison.R IRanges-class.R IRanges-constructor.R IRanges-utils.R Views-class.R Grouping-class.R CompressedList-class.R Rle-class-leftovers.R RleViews-class.R RleViews-utils.R extractList.R seqapply.R multisplit.R AtomicList-impl.R DataFrame-utils.R DataFrameList-class.R DataFrameList-utils.R RangesList-class.R GappedRanges-class.R ViewsList-class.R RleViewsList-class.R RleViewsList-utils.R MaskCollection-class.R RangedData-class.R RDApplyParams-class.R RangedData-utils.R HitsList-class.R NCList-class.R IntervalTree-class.R IntervalTree-utils.R IntervalForest-class.R RangedSelection-class.R read.Mask.R intra-range-methods.R inter-range-methods.R reverse-methods.R coverage-methods.R slice-methods.R setops-methods.R findOverlaps-methods.R nearest-methods.R cbind-Rle-methods.R expand-methods.R updateObject-methods.R tile-methods.R mapCoords-methods.R subsetting-internals.R test_IRanges_package.R debug.R zzz.R NeedsCompilation: yes Packaged: 2015-10-22 00:27:42 UTC; biocbuild IRanges/NAMESPACE0000644000175100017510000002160212607265143014350 0ustar00biocbuildbiocbuilduseDynLib(IRanges) import(methods) importFrom(utils, stack, read.table) importFrom(stats, var, cov, cor, sd, median, quantile, smoothEnds, runmed, window, "window<-", aggregate, setNames) import(BiocGenerics) import(S4Vectors) importFrom(stats4, summary, update) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Export S4 classes ### exportClasses( functionORNULL, CompressedList, Ranges, RangesORmissing, IRanges, NormalIRanges, NCList, NCLists, IntervalTree, IntervalForest, Grouping, ManyToOneGrouping, H2LGrouping, Dups, Partitioning, PartitioningByEnd, PartitioningByWidth, PartitioningMap, Views, RleViews, MaskCollection, AtomicList, CompressedAtomicList, SimpleAtomicList, LogicalList, CompressedLogicalList, SimpleLogicalList, IntegerList, CompressedIntegerList, SimpleIntegerList, NumericList, CompressedNumericList, SimpleNumericList, ComplexList, CompressedComplexList, SimpleComplexList, CharacterList, CompressedCharacterList, SimpleCharacterList, RawList, CompressedRawList, SimpleRawList, RleList, CompressedRleList, SimpleRleList, FactorList, CompressedFactorList, SimpleFactorList, RangesList, SimpleRangesList, IRangesList, CompressedIRangesList, SimpleIRangesList, NormalIRangesList, CompressedNormalIRangesList, SimpleNormalIRangesList, GappedRanges, ViewsList, SimpleViewsList, RleViewsList, SimpleRleViewsList, DataFrameList, SimpleDataFrameList, SplitDataFrameList, CompressedSplitDataFrameList, SimpleSplitDataFrameList, RangedData, RangedDataList, RDApplyParams, HitsList, CompressedHitsList, RangedSelection ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Export S3 methods ### S3method(as.data.frame, GappedRanges) S3method(as.data.frame, Hits) S3method(as.data.frame, RangedData) S3method(as.data.frame, Ranges) S3method(as.list, Vector) S3method(as.list, CompressedNormalIRangesList) S3method(as.list, Hits) S3method(duplicated, Dups) S3method(duplicated, CompressedList) S3method(duplicated, CompressedIntegerList) S3method(sort, List) S3method(unique, RleList) S3method(unique, CompressedList) S3method(window, Rle) S3method(`window<-`, Vector) S3method(`window<-`, vector) S3method(`window<-`, factor) ### We also export them thru the export() directive so that (a) they can be ### called directly, (b) tab-completion on the name of the generic shows them, ### and (c) methods() doesn't asterisk them. export( as.data.frame.GappedRanges, as.data.frame.Hits, as.data.frame.RangedData, as.data.frame.Ranges, as.list.Vector, as.list.CompressedNormalIRangesList, as.list.Hits, duplicated.Dups, duplicated.CompressedList, sort.List, unique.RleList, unique.CompressedList, window.Rle, "window<-.Vector", "window<-.vector", "window<-.factor" ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Export S4 methods for generics not defined in IRanges ### exportMethods( length, "length<-", names, "names<-", nrow, NROW, ncol, NCOL, dim, rownames, "rownames<-", colnames, "colnames<-", dimnames, "dimnames<-", "[", "[<-", "[[", "[[<-", "$<-", as.vector, as.integer, as.matrix, as.data.frame, as.list, as.table, coerce, c, show, "==", "<=", match, duplicated, unique, anyDuplicated, "%in%", order, sort, rank, xtfrm, is.unsorted, Ops, Math, Math2, Summary, Complex, summary, rev, rep, drop, start, "start<-", end, "end<-", width, "width<-", min, max, range, which.max, which.min, diff, mean, var, cov, cor, sd, median, quantile, mad, IQR, smoothEnds, runmed, subset, window, "window<-", transform, nchar, chartr, tolower, toupper, sub, gsub, unlist, stack, "split<-", unsplit, relist, update, append, "!", which, merge, with, within, t, is.na, by, cbind, rbind, lapply, pmax, pmin, pmax.int, pmin.int, paste, rep.int, table, tapply, union, intersect, setdiff, updateObject, values, "values<-", classNameForDisplay, queryHits, subjectHits, queryLength, subjectLength, compare, selfmatch, runLength, "runValue<-", shiftApply, runsum, runmean, runwtsum, runq, elementLengths, isEmpty, revElements, endoapply, mendoapply, as.env, active, "active<-", filterRules ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Export non-generic functions ### export( splitAsList, multisplit, solveUserSEW0, IRanges, solveUserSEW, successiveIRanges, breakInChunks, whichAsIRanges, asNormalIRanges, rangeComparisonCodeToLetter, NCList, NCLists, IntervalTree, IntervalForest, H2LGrouping, Dups, PartitioningByEnd, PartitioningByWidth, PartitioningMap, RangedData, RangedDataList, RangedSelection, RDApplyParams, RangesList, IRangesList, RleViewsList, CompressedHitsList, "%over%", "%within%", "%outside%", MaskCollection.show_frame, Mask, read.gapMask, read.agpMask, read.liftMask, read.rmMask, read.trfMask, ##read.chain, newViews, successiveViews, LogicalList, IntegerList, NumericList, ComplexList, CharacterList, RawList, RleList, FactorList, DataFrameList, SplitDataFrameList ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Export S4 generics defined in IRanges + export corresponding methods ### export( ## Vector-class-leftovers.R: showAsCell, mstack, ## Ranges-class.R: mid, isNormal, whichFirstNotNormal, ## Views-class.R: subject, ranges, "ranges<-", Views, trim, subviews, viewApply, viewMins, viewMaxs, viewSums, viewMeans, viewWhichMins, viewWhichMaxs, viewRangeMins, viewRangeMaxs, ## Grouping-class.R: nobj, grouplength, members, vmembers, togroup, togrouplength, high2low, low2high, grouprank, togrouprank, mapOrder, ## Rle-class-leftovers.R: findRange, splitRanges, ## extractList.R: relistToClass, extractList, ## DataFrameList-class.R: columnMetadata, "columnMetadata<-", ## RangesList-class.R: universe, "universe<-", space, ## GappedRanges-class.R: ngap, ## MaskCollection-class.R: nir_list, desc, "desc<-", maskedwidth, maskedratio, collapse, ## RangedData-class.R: score, "score<-", ## RangedData-utils.R: rdapply, ## RDApplyParams-class.R: rangedData, "rangedData<-", applyFun, "applyFun<-", applyParams, "applyParams<-", ##excludePattern, "excludePattern<-", "filterRules<-", simplify, "simplify<-", reducerFun, "reducerFun<-", reducerParams, "reducerParams<-", iteratorFun, "iteratorFun<-", ## mapCoords.R: mapCoords, pmapCoords, ## intra-range-methods.R: shift, narrow, resize, flank, reflect, promoters, restrict, threebands, ## inter-range-methods.R: reduce, gaps, disjoin, isDisjoint, disjointBins, ## reverse-methods.R: reverse, ## coverage-methods.R: coverage, ## slice-methods.R: slice, ## setops-methods.R: punion, pintersect, psetdiff, pgap, ## findOverlaps-methods.R: findOverlaps, countOverlaps, overlapsAny, subsetByOverlaps, mergeByOverlaps, ## nearest-methods.R: precede, follow, nearest, distance, distanceToNearest, ## expand-methods.R: expand, ## tile-methods.R: tile ) ### Exactly the same list as above. exportMethods( runsum, runmean, runwtsum, runq, showAsCell, mstack, mid, isNormal, whichFirstNotNormal, subject, ranges, "ranges<-", Views, trim, subviews, viewApply, viewMins, viewMaxs, viewSums, viewMeans, viewWhichMins, viewWhichMaxs, viewRangeMins, viewRangeMaxs, nobj, grouplength, members, vmembers, togroup, togrouplength, high2low, low2high, grouprank, togrouprank, mapOrder, findRange, splitRanges, relistToClass, extractList, columnMetadata, "columnMetadata<-", universe, "universe<-", space, ngap, nir_list, desc, "desc<-", maskedwidth, maskedratio, collapse, score, "score<-", rdapply, rangedData, "rangedData<-", applyFun, "applyFun<-", applyParams, "applyParams<-", ##excludePattern, "excludePattern<-", "filterRules<-", simplify, "simplify<-", reducerFun, "reducerFun<-", reducerParams, "reducerParams<-", iteratorFun, "iteratorFun<-", shift, narrow, resize, flank, reflect, promoters, restrict, threebands, reduce, gaps, disjoin, isDisjoint, disjointBins, reverse, coverage, slice, punion, pintersect, psetdiff, pgap, findOverlaps, countOverlaps, overlapsAny, subsetByOverlaps, precede, follow, nearest, distance, distanceToNearest, expand, tile ) IRanges/NEWS0000644000175100017510000010302512607265143013630 0ustar00biocbuildbiocbuildCHANGES IN VERSION 2.4.0 ------------------------ NEW FEATURES o Add "cbind" methods for binding Rle or RleList objects together. o Add coercion from Ranges to RangesList. o Add "paste" method for CompressedAtomicList objects. o Add "expand" method for Vector objects for expanding a Vector object 'x' based on a column in mcols(x). o Add overlapsAny,integer,Ranges method. o coverage" methods now accept 'shift' and 'weight' supplied as an Rle. SIGNIFICANT USER-VISIBLE CHANGES o The following was moved to S4Vectors: - The FilterRules stuff. - The "aggregate" methods. - The "split" methods. o The "sum", "min", "max", "mean", "any", and "all" methods on CompressedAtomicList objects are 100X faster on lists with 500k elements, 80X faster for 50k elements. o Tweak "c" method for CompressedList objects to make sure it always returns an object of the same class as its 1st argument. o NCList() constructor now propagates the metadata columns. DEPRECATED AND DEFUNCT o RangedData/RangedDataList are not formally deprecated yet but the documentation now officially declares them as superseded by GRanges/GRangesList and discourages their use. o After being deprecated in BioC 3.1, IntervalTree and IntervalForest objects and the "intervaltree" algorithm in findOverlaps() are now defunct. o After being deprecated in BioC 3.1, mapCoords() and pmapCoords() are now defunct. o Remove seqapply(), mseqapply(), tseqapply(), seqsplit(), and seqby() (were defunct in BioC 3.1). BUG FIXES o Fix FactorList() constructor when 'compress=TRUE' (note that the levels are combined during compression). o Fix c() on CompressedFactorList objects (was returning a CompressedIntegerList object). CHANGES IN VERSION 2.2.0 ------------------------ NEW FEATURES o Add NCList() and NCLists() for preprocessing a Ranges or RangesList object into an NCList or NCLists object that can be used for fast overlap search with findOverlaps(). NCList() and NCLists() are replacements for IntervalTree() and IntervalForest() that use Nested Containment Lists instead of interval trees. For a one time use, it's not advised to explicitely preprocess the input. This is because findOverlaps() or countOverlaps() will take care of it and do a better job at it (that is, they preprocess only what's needed when it's needed and release memory as they go). o Add coercion methods from Hits to CompressedIntegerList, to PartitioningByEnd, and to Partitioning. SIGNIFICANT USER-VISIBLE CHANGES o The code behind overlap-based operations like findOverlaps(), countOverlaps(), subsetByOverlaps(), summarizeOverlaps(), nearest(), etc... was refactored and improved. Some highlights on what has changed: - The underlying code used for finding/counting overlaps is now based on the Nested Containment List algorithm by Alexander V. Alekseyenko and Christopher J. Lee. - The old algorithm based on interval trees is still available (but deprecated). The 'algorithm' argument was added to most overlap-based operations to let the user choose between the new (algorithm="nclist", the default) and the old (algorithm="intervaltree") algorithm. - With the new algorithm, the hits returned by findOverlaps() are not fully ordered (i.e. ordered by queryHits and subject Hits) anymore, but only partially ordered (i.e. ordered by queryHits only). Other than that, and except for the 3 particular situations mentioned below, choosing one or the other doesn't affect the output, only performance. - Either the query or subject can be preprocessed with NCList() for a Ranges object (replacement for IntervalTree()), NCLists() for a RangesList object (replacement for IntervalForest()), and GNCList() for a GenomicRanges object (replacement for GIntervalTree()). However, for a one time use, it's not advised to explicitely preprocess the input. This is because findOverlaps() or countOverlaps() will take care of it and do a better job at it (that is, they preprocess only what's needed when it's needed and release memory as they go). - With the new algorithm, countOverlaps() on Ranges or GenomicRanges objects doesn't call findOverlaps() to collect all the hits in a growing Hits object and count them only at the end. Instead the counting happens at the C level and the hits are not kept. This reduces memory usage considerably when there is a lot of hits. - When 'minoverlap=0', zero-width ranges are interpreted as insertion points and are considered to overlap with ranges that contain them. This is the 1st situation where using 'algorithm="nclist"' or 'algorithm="intervaltree"' produces different output. - When using 'select="arbitrary"', the new algorithm will generally not select the same hits as the old algorithm. This is the 2nd situation where using 'algorithm="nclist"' or 'algorithm="intervaltree"' produces different output. - When using the old interval tree algorithm, 'maxgap' has a special meaning if 'type' is "start", "end", or "within". This is not yet the case with the new algorithm. That feature seems somewhat useful though so maybe the new algorithm should also support it? Anyway, this is the 3rd situation where using 'algorithm="nclist"' or 'algorithm="intervaltree"' produces different output. - Objects preprocessed with NCList(), NCLists(), and GNCList() are serializable. o The RleViewsList() constructor function now reorders its 'rleList' argument so that its names match the names on the 'rangesList' argument. o Minor changes to breakInChunks(): - Add 'nchunk' arg. - Now returns a PartitioningByEnd instead of a PartitioningByWidth object. - Now accepts 'chunksize' of 0 if 'totalsize' is 0. o 300x speedup or more when doing unique() on a CompressedRleList object. o 20x speedup or more when doing unlist() on a SimpleRleList object. o Moved the RleTricks.Rnw vignette to the S4Vectors package. DEPRECATED AND DEFUNCT o Deprecated mapCoords() and pmapCoords(). They're replaced by mapToTranscripts() and pmapToTranscripts() from the GenomicFeatures package and mapToAlignments() and pmapToAlignments() from the GenomicAlignments package. o Deprecated IntervalTree and IntervalForest objects. o seqapply(), seqby(), seqsplit(), etc are now defunct (were deprecated in IRanges 2.0.0). o Removed map(), pmap(), and splitAsListReturnedClass() (were defunct in IRanges 2.0.0). o Removed 'with.mapping' argunment from reduce() methods (was defunct in IRanges 2.0.0). BUG FIXES o findOverlaps,Vector,missing method now accepts extra arguments via ... so for example one can specify 'ignore.strand=TRUE' when calling it on a GRanges object (before that, 'findOverlaps(gr, ignore.strand=TRUE)' would fail). o PartitioningByEnd() and PartitioningByWidth() constructors now check that, when 'x' is an integer vector, it cannot contain NAs or negative values. CHANGES IN VERSION 2.0.0 ------------------------ NEW FEATURES o Add mapCoords() and pmapCoords() as replacements for map() and pmap(). o Add coercion from list to RangesList. o Add slice,ANY method as a convenience for slice(as(x, "Rle"), ...). o Add mergeByOverlaps(); acts like base::merge as far as it makes sense. o Add overlapsAny,Vector,missing method. SIGNIFICANT USER-VISIBLE CHANGES o Move Annotated, DataTable, Vector, Hits, Rle, List, SimpleList, and DataFrame classes to new S4Vectors package. o Move isConstant(), classNameForDisplay(), and low-level argument checking helpers isSingleNumber(), isSingleString(), etc... to new S4Vectors package. o Rename Grouping class -> ManyToOneGrouping. Redefine Grouping class as the parent of all groupings (it formalizes the most general kind of grouping). o Change splitAsList() to a generic. o In rbind,DataFrame method, no longer coerce the combined column to the class of the column in the first argument. o Do not carry over row.names attribute from data.frame to DataFrame. o No longer make names valid in [[<-,DataFrame method. o Make the set operations dispatch on Ranges instead of IRanges; they usually return an IRanges, but the input could be any implementation. o Add '...' to splitAsList() generic. o Speed up trim() on a Views object when trimming is actually not needed (no-op). o Speed up validation of IRanges objects by 2x. o Speed up "flank" method for Ranges objects by 4x. DEPRECATED AND DEFUNCT o Defunct map() and pmap(). o reduce() argument 'with.mapping' is now defunct. o splitAsListReturnedClass() is now defunct. o Deprecate seqapply(), mseqapply(), tseqapply(), seqsplit(), and seqby(). BUG FIXES o Fix rbind,DataFrame method when first column is a matrix. o Fix a memory leak in the interval tree code. o Fix handling of minoverlap > 1 in findOverlaps(), so that it behaves more consistently and respects 'maxgap', as documented. o Fix findOverlaps,IRanges method for select="last". o Fix subset,Vector-method to handle objects with NULL mcols(x) (e.g. Rle object). o Fix internal helper rbind.mcols() for DataFrame (and potentially other tables). o ranges,SimpleRleList method now returns a SimpleRangesList (instead of CompressedRangesList). o Make flank() work on Ranges object of length 0. CHANGES IN VERSION 1.20.0 ------------------------- NEW FEATURES o Add IntervalForest class from Hector Corrada Bravo. o Add a FilterMatrix class, for holding the results of multiple filters. o Add selfmatch() as a faster equivalent of 'match(x, x)'. o Add "c" method for Views objects (only combine objects with same subject). o Add coercion from SimpleRangesList to SimpleIRangesList. o Add an `%outside%` that is the opposite of `%over%`. o Add validation of length() and names() of Vector objects. o Add "duplicated" and "table" methods for Vector objects. o Add some split methods that dispatch to splitAsList() even when only 'f' is a Vector. o Add set methods (setdiff, intersect, union) for Rle. o Add anyNA methods for Rle and Vector. o Add support for subset(), with(), etc on Vector objects, where the expressions are evaluated in the scope of the mcols and fixed columns. For symbols that should resolve in the calling frame, it is supported and encouraged to escape them with bquote-style ".(x)". o Add "tile" generic and methods for partitioning a ranges object into tiles; useful for iterating over subregions. SIGNIFICANT USER-VISIBLE CHANGES o All functionalities related to XVector objects have been moved to the new XVector package. o Refine how isDisjoint() handles empty ranges. o Remove 'keepLength' argument from "window<-" methods. o unlist( , use.names=FALSE) on a CompressedSplitDataFrameList object now preserves the rownames of the list elements, which is more consistent with what unlist() does on other CompressedList objects. o Splitting a list by a Vector just yields a list, not a List. o The rbind,DataFrame method now handles the case where Rle and vector columns need to be combined (assuming an equivalence between Rle and vector). Also the way the result DataFrame is constructed was changed (avoids undesirable coercions and should be faster). o as.data.frame.DataFrame now passes 'stringsAsFactors=FALSE' and 'check.names=!optional' to the underlying data.frame() call. as(x,"DataFrame") sets 'optional=TRUE' when delegating. Most places where we called as.data.frame(), we now call 'as(x,"data.frame")'. o The [<-,DataFrame method now coerces column sub-replacement value to class of column when the column already exists. o DataFrame() now automatically derives rownames (from the first argument that has some). This is a fairly significant change in behavior, but it probably does better match user behavior. o Make sure that SimpleList objects are coerced to a DataFrame with a single column. The automatic coecion methods created by the methods package were trying to create a DataFrame with one column per element, because DataFrame extends SimpleList. o Change default to 'compress=TRUE' for RleList() constructor. o tapply() now handles the case where only INDEX is a Vector (e.g. an Rle object). o Speedup coverage() in the "tiling case" (i.e. when 'x' is a tiling of the [1, width] interval). This makes it much faster to turn into an Rle a coverage loaded from a BigWig, WIG or BED as a GRanges object. o Allow logical Rle return values from filter rules. o FilterRules no longer requires its elements to be named. o The select,Vector method now returns a DataFrame even when a single column is selected. o Move is.unsorted() generic to BiocGenerics. DEPRECATED AND DEFUNCT o Deprecate seqselect() and subsetByRanges(). o Deprecate 'match.if.overlap' arg of "match" method for Ranges objects. o "match" and "%in%" methods that operate on Views, ViewsList, RangesList, or RangedData objects (20 methods in total) are now defunct. o Remove previously defunct tofactor(). BUG FIXES o The subsetting code for Vector derivatives was substancially refactored. As a consequence, it's now cleaner, simpler, and [ and [[ behave more consistently across Vector derivatives. Some obscure long-standing bugs have been eliminated and the code can be slightly faster in some circumstances. o Fix bug in findOverlaps(); zero-width ranges in the query no longer produce hits ever (regardless of 'maxgap' and 'minoverlap' values). o Correctly free memory allocated for linked list of results compiled for findOverlaps(select="all"). o Various fixes for AsIs and DataFrames. o Allow zero-row replacement values in [<-,DataFrame. o Fix long standing segfault in "[" method for Rle objects (when doing Rle()[0]). o "show" methods now display its most specific class when a column or slot is an S3 object for which class() returns more than one class. o "show" methods now display properly cells that are arrays. o Fix the [<-,DataFrame method for when a value DataFrame has matrix columns. o Fix ifelse() for when one or more of the arguments are Rle objects. o Fix coercion from SimpleList to CompressedList via AtomicList constructors. o Make "show" methods robust to "showHeadLines" and "showTailLines" global options set to NA, Inf or non-integer values. o Fix error condition in eval,FilterRules method. o Corrected an error formatting in eval,FilterRules,ANY method. CHANGES IN VERSION 1.18.0 ------------------------- NEW FEATURES o Add global options 'showHeadLines' and 'showTailLines' to control the number of head/tails lines displayed by "show" methods for Ranges, DataTable, and Hits objects. o "subset" method for Vector objects now considers metadata columns. o Add classNameForDisplay() generic and use it in all "show" methods defined in IRanges and GenomicRanges. o as(x, "DataFrame") now works on *any* R object. o Add findMatches(), an enhanced version of match() that returns all the matches between 'x' and 'table'. The hits are returned in a Hits object. Also add countMatches() for counting the number of matches in 'table' for each element in 'x'. o Add overlapsAny() as a replacement for %in% (now deprecated on range-based objects), and %over% and %within% as convenience wrappers for overlapsAny(). %over% is the replacement for %in%. o Add 'with.mapping' arg to "reduce" methods for IRanges, Ranges, Views, RangesList, and CompressedIRangesList objects. o Add "order" method for Rle objects. o Add subsetByRanges() generic with methods for ANY, NULL, vector, and IRanges for now. This is work-in-progress and more methods will be added soon. The long term plan is to make this a replacement for seqselect(), but with a faster and cleaner implementation. o Add promoters() generic with methods for Ranges, RangesList, Views, and CompressedIRangesList objects. o elementLengths() now works on XVectorList objects (and thus works on DNAStringSet objects and family defined in the Biostrings package). Note that this is the first step towards having relist() work on XVector objects (e.g. DNAString objects) eventhough this is not ready yet. o Add "mstack" method for DataFrame objects. o Add 'name.var' argument to "stack" method for List objects for naming the optional column formed when the elements themselves have named elements. SIGNIFICANT USER-VISIBLE CHANGES o "distanceToNearest" methods now return a Hits instead of a DataFrame object. o The behavior of distance() has changed. Adjacent and overlapping ranges now return a distance of 0L. See ?distance man page for details. A temporary warning will be emitted by distance() until the release of Bioconductor 2.13. o Change arg list of expand() generic: function(x, ...) instead of function(x, colnames, keepEmptyRows). o Dramatic duplicated() and unique() speedups on CompressedAtomicList objects. o Significant endoapply() speedup on XVectorList objects (this benefits DNAStringSet objects and family defined in the Biostrings package). o 2x speedup to "c" method for CompressedList objects. o classNameForDisplay() strips 'Simple' or 'Compressed', which affects all the "show" methods based on it. So now: > IntegerList(1:4, 2:-3) IntegerList of length 2 [[1]] 1 2 3 4 [[2]] 2 1 0 -1 -2 -3 instead of: > IntegerList(1:4, 2:-3) CompressedIntegerList of length 2 [[1]] 1 2 3 4 [[2]] 2 1 0 -1 -2 -3 o Optimization of "[<-" method for Rle objects when no indices are selected (just return self). o "stack" method for List objects now creates a factor for the optional name variable. o Evaluating FilterRules now subsets by each filter individually, rather than subsetting by all at the end. o Optimized which() on CompressedLogicalList objects. o All the binary comparison operations (==, <=, etc...) on Ranges objects are now using compare() behind the scene. This makes them slightly faster and also slightly more memory efficient. DEPRECATED AND DEFUNCT o %in% is now deprecated on range-based objects. Please use %over% instead. More precisely: - "match" and "%in%" methods that operate on Views, ViewsList, RangesList, or RangedData objects (20 methods in total) are now deprecated. - Behavior of match() and %in% on Ranges objects was changed (and will issue a warning) to use equality instead of overlap for comparing elements between Ranges objects 'x' and 'table'. The old behavior is still available for match() via new 'match.if.overlap' arg that is FALSE by default (the arg will be deprecated in BioC 2.13 and removed in BioC 2.14). o tofactor() is now defunct. o '.ignoreElementMetadata' argument of "c" method for IRanges objects is now defunct. BUG FIXES o Small fix to "unlist" method for CompressedList objects when 'use.names' is TRUE and 'x' is a zero-length named List (the zero-length vector returned in that case was not named, now it is). o "resize" method for Ranges objects now allows zero-length 'fix' when 'x' is zero-length. o Subsetting a Views object now subsets its metadata columns. o Names on the vector-like columns of a DataFrame object are now preserved when calling DataFrame(), or when coercing to DataFrame, or when combining DataFrame objects with rbind(). o relist() now propagates the names on 'skeleton' when returning a SimpleList. o Better argument checking in breakInChunks(). o Fix broken "showAsCell" method for ANY. Now tries to coerce uni-dimensional objects to vector instead of data.frame (which never worked anyway, due to a bug). o Fix long standing bug in "flank" method for Ranges objects: it no longer returns an invalid object when NAs are passed thru the 'width' arg. Now it's an error to try to do so. o Fix issue with some of the "as.env" methods not being able to find the environment of the caller. o Fix bug in "showAsCell" method for AtomicList objects: now returns character(0) instead of NULL on an object of length 0. o sort() now drops NA's when 'na.last=NA' on an Rle object (consistent with base::sort). o table() now handles NA's appropriately on an Rle object. o table() now returns all the levels on a factor-Rle object. o Fix sub-replacement of Rles when using Ranges as the index. o Fix bug in [<- method for DataFrame objects. The fix corrects the way a new column created by a subset assignment is filled. Previously, if the first row was set, say, to '1', all values in the column were set to '1' when they needed to be set to NA (for consistency with data.frame). o Fix bug in compare() (was not returning 0 when comparing a 0-width range to itself). o Fix naming of column when passing an AsIs matrix to DataFrame() -- no more .X suffix. o Fix "rbind" method for DataFrame objects when some columns are matrix objects. CHANGES IN VERSION 1.16.0 ------------------------- NEW FEATURES o as( , "SimpleList"), as( , "CompressedList"), and as( , "List") now work on atomic vectors, and each element of the vector corresponds to an element of the returned List (this is consistent with as.list). o Add as.list,Rle method. o Add as.matrix,Views method. Each view corresponds to a row in the returned matrix. Rows corresponding to views shorter than the longest view are right-padded with NAs. o Add FilterClosure closure class for functions placed into a FilterRules. Has methods for getting parameters and showing. o Support 'na.rm' argument in "runsum", "runwtsum", "runq", and "runmean" methods for Rle and RleList objects. o Add splitAsList() and splitAsListReturnedClass(). o Improve summary,FilterRules to support serial evaluation, discarded counts (instead of passed) and percentages. o Make rename work on ordinary vector (in addition to Vector). o Add coercion from RangedData to CompressedIRangesList, IRangesList, or RangesList. It propagates the data columns (aka values) of the RangedData object to the inner metadata columns of the RangesList object. o Add 'NG' arg to PartitioningByEnd() and PartitioningByWidth() constructors. o Make PartitioningByEnd() work on list-like objects (like PartitioningByWidth()). o Fast disjoin() for moderate-sized CompressedIRangesList. o Add countQueryHits() and countSubjectHits(). o coverage() now supports method="auto" and this is the new default. o Add the flippedQuery(), levels(), ngap(), Lngap(), Rngap(), Lencoding(), and Rencoding() getters for OverlapEncodings objects. o Add "encodeOverlaps" method for GRangesList objects. o Enhance "[" methods for IRanges, XVector, XVectorList, and MaskCollection objects, as well as "[<-" method for IRanges objects, by supporting the following subscript types: NULL, Rle, numeric, logical, character, and factor. (All the methods listed above already supported some of those types but no method supported them all). o Add remapHits() for remapping the query and subject hits of a Hits object. o Add match,Hits method. o Add %in%,Vector method. o Add "compare", "==", "!=", "<=", ">=", "<", ">", "is.unsorted", "order", "rank", "match", and "duplicated" methods for XRawList objects. unique() and sort() also work on these objects via the "unique" and "sort" methods for Vector objects. o Add expand() for expanding a DataFrame based on the contents of one or more designated columms. o After being deprecated (in BioC 2.9) and defunct (in BioC 2.10), the "as.vector" method for AtomicList objects is back, but now it mimics what as.vector() does on an ordinary list i.e. it's equivalent to 'as.vector(as.list(x), mode=mode)'. Also coercions from AtomicList to logical/integer/numeric/double/complex/character/raw are back and based on the "as.vector" method for AtomicList objects i.e. they work only on objects with top-level elements of length <= 1. o DataFrame constructor now supports 'check.names' argument. o Add revElements() generic with methods for List and CompressedList objects. SIGNIFICANT USER-VISIBLE CHANGES o Splitting / relisting a Hits object now returns a HitsList instead of an ordinary list. o Operations in the Ops group between a List and an atomic vector operand now coerce the atomic vector to List (SimpleList or CompressedList) before performing the operation. Also, operands are recycled and a better job is done returning zero length results of the correct type. o Change the warning for 'Integer overflow ...' thrown by sum() on integer-Rle's o DataFrame now coerces List/list value to DataFrame in [<-. o Fix as.matrix,DataFrame for zero column DataFrames. Returns an nrow()x0 logical matrix. o union,Hits method now sorts the returned hits first by query hit, then by subject hit. o Add mcols() accessor as the preferred way (over elementMetadata() and values()) to access the metadata columns of a Vector object. o By default, mcols(x) and elementMetadata(x) do NOT propagate the names of x as the row names of the returned DataTable anymore. However the user can still get the old behavior by doing mcols(x, use.names=TRUE). o [<-,XVectorList now preserves the original names instead of propagating the names of the replacement value, which is consistent with how [<- operates on an ordinary vector/list. o coverage() now returns a numeric-Rle when passed numeric weights. o When called on a List object with use.names=TRUE, unlist() no longer tries to mimic the kind of non-sense name mangling that base::unlist() does (e.g. on list(a=1:3)) in a pointless effort to return a vector with unique names. o Remove 'hits' argument from signature of encodeOverlaps() generic function. o unique,Vector now drops the names for consistency with base::unique(). o Remove make.names() coercion in colnames<-,DataFrame for consistency with data.frame. DEPRECATED AND DEFUNCT o Deprecated tofactor(). o Remove RangesMatching, RangesMatchingList, and Binning classes. o Change from deprecated to defunct: matchMatrix(), "dim" method for Hits objects, and RangesMatchingList(). BUG FIXES o Fix bug in pintersect,IRanges,IRanges when input had empty ranges (broken since 2010-03-04). o Avoid integer overflow in mean,Rle method by coercing integer-Rle to numeric-Rle internally. o Change evaluation frame of with,List to parent.frame(), and get the enclosure correct in eval,List. o Many fixes and improvements to coercion from RangesList to RangedData (see commit 68195 for the details). o Fix "runValue" and "ranges" methods for CompressedRleList objects (broken for a very long time). o shift,Ranges method now fails in case of integer overflow instead of returning an invalid Ranges object. o mstack() now works on Vector objects with NULL metadata columns. o In case of integer overflow, coverage() now puts NAs in the returned Rle and issues a warning. o Fix bug in xvcopy,XRawList objects that prevented sequences from being removed from the cache of a BSgenome object. See commit 67171 for the details. o Fix issues related to duplicate column names in DataFrame (see commit 67163 for the details). o Fix a bunch of subsetting methods that were not subsetting the metadata columns: "[", "subseq", and "seqselect" methods for XVector objects, "seqselect" and "window" methods for XVectorList objects, and "[" method for MaskCollection objects. o Fix empty replacement with [<-,Vector o Make %in% robust on an empty 'table' argument when operating on Hits objects. CHANGES IN VERSION 1.14.0 ------------------------- NEW FEATURES o The map generic and RangesMapping class for mapping ranges between sequences according to some alignment. Some useful methods are implemented in GenomicRanges. o The Hits class has experimental support for basic set operations, including setdiff, union and intersect. o Added a number of data manipulation functions and methods, including mstack, multisplit, rename, unsplit for Vector. o Added compare() generic for generalized range-wise comparison of 2 range-based objects. o Added OverlapEncodings class and encodeOverlaps() generic for dealing with "overlap encodings". o subsetByOverlaps() should now work again on an RleViews object. o DataFrame now supports storing an array (like a matrix) in a column. o Added as.matrix,DataFrame method. o Added merge,DataTable,DataTable method. o Added disjointBins,RangesList method. o Added ranges,Rle and ranges,RleList methods. o Added which.max,Rle method. o Added drop,AtomicList method. o Added tofactor() wrapper around togroup(). o Added coercions from vector to any AtomicList subtype (compressed and uncompressed). o Added AtomicList to Character/Numeric/Logical/Integer/Raw/ComplexList coercions. o Added revElements() for reversing individual elements of a List object. SIGNIFICANT USER-VISIBLE CHANGES o RangesMatching has been renamed to Hits and extends Vector, so that it supports metadata columns and other features. o RangesMatchingList has been renamed to HitsList. o The 2 columns of the matrix returned by the "as.matrix" method for Hits objects are now named queryHits/subjectHits instead of query/subject, for consistency with the queryHits() and subjectHits() getters. o queryLength()/subjectLength() are recommended alternatives to dim,Hits. o breakInChunks() returns a PartitioningByWidth object. o The 'weight' arg in "coverage" methods for IRanges, Views and MaskCollection objects now can also be a single string naming a column in elementMetadata(x). o "countOverlaps" methods now propagate the names of the query. DEPRECATED AND DEFUNCT o matchMatrix,Hits is deprecated. o Moved the following deprecated features to defunct status: - use of as.data.frame() or as( , "data.frame") on an AtomicList object; - all coercion methods from AtomicList to atomic vectors; - subsetting an IRanges by Ranges; - subsetting a RangesList or RangedData by RangesList. BUG FIXES o within,RangedData/List now support replacing columns o aggregate() override no longer breaks on . ~ x formulas o "[", "c", "rep.int" and "seqselect" methods for Rle objects are now safer and will raise an error if the object to be returned has a length > .Machine$integer.max o Avoid blowing up memory by not expanding 'logical' Rle's into logical vectors internally in "slice" method for RleList objects. CHANGES IN VERSION 1.12.0 ------------------------- NEW FEATURES o Add "relist" method that works on a List skeleton. o Add XDoubleViews class with support of most of the functionalities available for XIntegerViews. o c() now works on XInteger and XDouble objects (in addition to XRaw objects). o Add min, max, mean, sum, which.min, which.max methods as synonyms for the view* functions. SIGNIFICANT USER-VISIBLE CHANGES o Views and RleViewsList classes don't derive from IRanges and IRangesList classes anymore. o When used on a List or a list, togroup() now returns an integer vector (instead of a factor) for consistency with what it does on other objects (e.g. on a Partitioning object). o Move compact() generic from Biostrings to IRanges. o Drop deprecated 'multiple' argument from "findOverlaps" methods. o Drop deprecated 'start' and 'symmetric' arguments from "resize" method for Ranges objects. DEPRECATED AND DEFUNCT o Using as.data.frame() and or as( , "data.frame") on an AtomicList object is deprecated. o Deprecate all coercion methods from AtomicList to atomic vectors. Those methods were unlisting the object, which can still be done with unlist(). o Deprecate the Binning class. o Remove defunct overlap() and countOverlap(). BUG FIXES o togroup() on a List or a list does not look at the names anymore to infer the grouping, only at the shape of the list-like object. o Fix 'relist(IRanges(), IRangesList())'. o Fix 'rep.int(Rle(), integer(0))'. o Fix some long-standing issues with the XIntegerViews code (better handling of "out of limits" or empty views, overflows, NAs). IRanges/R/0000755000175100017510000000000012611546444013332 5ustar00biocbuildbiocbuildIRanges/R/AtomicList-class.R0000644000175100017510000000271112607265143016630 0ustar00biocbuildbiocbuild### ========================================================================= ### AtomicList objects ### ------------------------------------------------------------------------- ## A list that holds atomic objects setClass("AtomicList", representation("VIRTUAL"), prototype = prototype(elementType = "logical"), contains = "List") setClass("LogicalList", representation("VIRTUAL"), prototype = prototype(elementType = "logical"), contains = "AtomicList") setClass("IntegerList", representation("VIRTUAL"), prototype = prototype(elementType = "integer"), contains = "AtomicList") setClass("NumericList", representation("VIRTUAL"), prototype = prototype(elementType = "numeric"), contains = "AtomicList") setClass("ComplexList", representation("VIRTUAL"), prototype = prototype(elementType = "complex"), contains = "AtomicList") setClass("CharacterList", representation("VIRTUAL"), prototype = prototype(elementType = "character"), contains = "AtomicList") setClass("RawList", representation("VIRTUAL"), prototype = prototype(elementType = "raw"), contains = "AtomicList") setClass("RleList", representation("VIRTUAL"), prototype = prototype(elementType = "Rle"), contains = "AtomicList") setClass("FactorList", representation("VIRTUAL"), prototype = prototype(elementType = "factor"), contains = "IntegerList") IRanges/R/AtomicList-impl.R0000644000175100017510000012301712611546444016470 0ustar00biocbuildbiocbuild### ========================================================================= ### AtomicList object implementations ### ------------------------------------------------------------------------- ## Possible optimizations for compressed lists: ## - order/sort: unlist, order by split factor first ## - cumsum: unlist, cumsum and subtract offsets .ATOMIC_TYPES <- c("logical", "integer", "numeric", "complex", "character", "raw") setClassUnion("atomic", .ATOMIC_TYPES) ## A list that holds atomic objects setClass("CompressedAtomicList", contains = c("AtomicList", "CompressedList"), representation("VIRTUAL")) setClass("SimpleAtomicList", contains = c("AtomicList", "SimpleList"), representation("VIRTUAL")) setClass("CompressedLogicalList", prototype = prototype(elementType = "logical", unlistData = logical()), contains = c("LogicalList", "CompressedAtomicList")) setClass("SimpleLogicalList", prototype = prototype(elementType = "logical"), contains = c("LogicalList", "SimpleAtomicList")) setClass("CompressedIntegerList", prototype = prototype(elementType = "integer", unlistData = integer()), contains = c("IntegerList", "CompressedAtomicList")) setClass("SimpleIntegerList", prototype = prototype(elementType = "integer"), contains = c("IntegerList", "SimpleAtomicList")) setClass("CompressedNumericList", prototype = prototype(elementType = "numeric", unlistData = numeric()), contains = c("NumericList", "CompressedAtomicList")) setClass("SimpleNumericList", prototype = prototype(elementType = "numeric"), contains = c("NumericList", "SimpleAtomicList")) setClass("CompressedComplexList", prototype = prototype(elementType = "complex", unlistData = complex()), contains = c("ComplexList", "CompressedAtomicList")) setClass("SimpleComplexList", prototype = prototype(elementType = "complex"), contains = c("ComplexList", "SimpleAtomicList")) setClass("CompressedCharacterList", prototype = prototype(elementType = "character", unlistData = character()), contains = c("CharacterList", "CompressedAtomicList")) setClass("SimpleCharacterList", prototype = prototype(elementType = "character"), contains = c("CharacterList", "SimpleAtomicList")) setClass("CompressedRawList", prototype = prototype(elementType = "raw", unlistData = raw()), contains = c("RawList", "CompressedAtomicList")) setClass("SimpleRawList", prototype = prototype(elementType = "raw"), contains = c("RawList", "SimpleAtomicList")) setClass("CompressedRleList", prototype = prototype(elementType = "Rle", unlistData = new("Rle")), contains = c("RleList", "CompressedAtomicList")) setClass("SimpleRleList", prototype = prototype(elementType = "Rle"), contains = c("RleList", "SimpleAtomicList")) setClass("CompressedFactorList", prototype = prototype(elementType = "factor", unlistData = factor()), contains = c("FactorList", "CompressedAtomicList")) setClass("SimpleFactorList", prototype = prototype(elementType = "factor"), contains = c("FactorList", "SimpleAtomicList")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructors ### .dotargsAsList <- function(type, ...) { listData <- list(...) if (length(listData) == 1) { arg1 <- listData[[1]] if (is.list(arg1) || is(arg1, "List")) listData <- arg1 else if (type == "integer" && class(arg1) == "character") listData <- strsplitAsListOfIntegerVectors(arg1) # weird special case } listData } AtomicListConstructor <- function(type, compress.default = TRUE) { constructor <- eval(substitute(function(..., compress = compress.default) { if (!isTRUEorFALSE(compress)) stop("'compress' must be TRUE or FALSE") listData <- .dotargsAsList(type, ...) CompressedOrSimple <- if (compress) "Compressed" else "Simple" if (is(listData, S4Vectors:::listClassName(CompressedOrSimple, type))) listData else CoercerToList(type, compress)(listData) }, list(type = type))) formals(constructor)$compress <- compress.default constructor } LogicalList <- AtomicListConstructor("logical") IntegerList <- AtomicListConstructor("integer") NumericList <- AtomicListConstructor("numeric") ComplexList <- AtomicListConstructor("complex") CharacterList <- AtomicListConstructor("character") RawList <- AtomicListConstructor("raw") RleList <- AtomicListConstructor("Rle") FactorList <- AtomicListConstructor("factor") ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Iteration ### setMethod("lapply", "CompressedAtomicList", function(X, FUN, ...) { if (is(X, "CompressedRleList")) { callNextMethod(X, FUN, ...) } else { lapply(as.list(X), FUN, ...) } }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion ### setMethod("as.list", "CompressedAtomicList", function(x, use.names = TRUE) { if (is(x, "CompressedRleList")) { callNextMethod(x, use.names = use.names) } else { codes <- seq_len(length(x)) ans <- split(x@unlistData, structure(rep.int(codes, elementLengths(x)), levels = as.character(codes), class = "factor")) if (use.names) { names(ans) <- names(x) } else { names(ans) <- NULL } ans } }) setAs("CompressedAtomicList", "list", function(from) as.list(from)) ### Equivalent to 'as.vector(as.list(x), mode=mode)' but faster on ### CompressedAtomicList objects (10x, 75x, or more, depending on 'length(x)'). setMethod("as.vector", "AtomicList", function(x, mode="any") { valid_modes <- c("any", .ATOMIC_TYPES, "double", "list") mode <- match.arg(mode, valid_modes) if (mode %in% c("any", "list")) return(as.list(x)) elt_lens <- elementLengths(x) if (any(elt_lens > 1L)) stop("coercing an AtomicList object to an atomic vector ", "is supported only for\n", " objects with top-level elements of length <= 1") ans <- base::rep.int(as.vector(NA, mode=mode), length(x)) ans[elt_lens == 1L] <- as.vector(unlist(x, use.names=FALSE), mode=mode) ans } ) setMethod("drop", "AtomicList", function(x) { lens <- elementLengths(x) if (any(lens > 1)) stop("All element lengths must be <= 1") x_dropped <- rep.int(NA, sum(lens)) x_dropped[lens > 0] <- unlist(x, use.names = FALSE) names(x_dropped) <- names(x) x_dropped }) CoercerToList <- function(type, compress) { .coerceToList <- if (compress) coerceToCompressedList else S4Vectors:::coerceToSimpleList function(from) { .coerceToList(from, type) } } setListCoercions <- function(type) { CompressedClass <- S4Vectors:::listClassName("Compressed", type) SimpleClass <- S4Vectors:::listClassName("Simple", type) Class <- S4Vectors:::listClassName("", type) hasCompressedList <- CompressedClass != "CompressedList" if (hasCompressedList) { setAs("ANY", CompressedClass, CoercerToList(type, compress = TRUE)) } setAs("ANY", SimpleClass, CoercerToList(type, compress = FALSE)) setAs("ANY", Class, CoercerToList(type, compress = hasCompressedList)) setAs("SimpleList", Class, CoercerToList(type, compress = FALSE)) setAs("list", Class, CoercerToList(type, compress = FALSE)) } setListCoercions("logical") setListCoercions("integer") setListCoercions("numeric") setListCoercions("complex") setListCoercions("character") setListCoercions("raw") setListCoercions("Rle") setListCoercions("factor") ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Group generic methods ### emptyOpsReturnValue <- function(.Generic, e1, e2, compress) { dummy.vector <- do.call(.Generic, list(vector(e1@elementType), vector(e2@elementType))) CoercerToList(NULL, compress)(dummy.vector) } recycleList <- function(x, length.out) { if (length.out %% length(x) > 0L) warning("shorter object is not a multiple of longer object length") rep(x, length.out = length.out) } setMethod("Ops", signature(e1 = "SimpleAtomicList", e2 = "SimpleAtomicList"), function(e1, e2) { if (length(e1) == 0L || length(e2) == 0L) { return(emptyOpsReturnValue(.Generic, e1, e2, compress = FALSE)) } n <- max(length(e1), length(e2)) e1 <- recycleList(e1, n) e2 <- recycleList(e2, n) as(Map(.Generic, e1, e2), "List") }) repLengthOneElements <- function(x, times) { x@unlistData <- rep(x@unlistData, times) x@partitioning@end <- cumsum(times) x } recycleListElements <- function(x, newlen) { len <- elementLengths(x) if (identical(len, newlen)) { return(x) } if (all(len == 1L)) { ans <- repLengthOneElements(x, newlen) } else { ans <- rep(x, newlen / len) if (length(unlist(ans, use.names=FALSE)) != sum(newlen)) { stop("Some element lengths are not multiples of their corresponding ", "element length in ", deparse(substitute(x))) } } ans } doBinaryCompressedListOp <- function(OP, e1, e2, skeleton) { if (!missing(skeleton)) { n <- length(skeleton) } else { n <- max(length(e1), length(e2)) } e1 <- recycleList(e1, n) e2 <- recycleList(e2, n) if (missing(skeleton)) { n1 <- elementLengths(e1) n2 <- elementLengths(e2) if (any(n1 != n2)) { en <- ifelse(n1 == 0L | n2 == 0L, 0L, pmax.int(n1, n2)) } else { en <- NULL } nms <- names(e1) if (is.null(nms)) nms <- names(e2) } else { en <- elementLengths(skeleton) nms <- names(skeleton) } if (!is.null(en)) { e1 <- recycleListElements(e1, en) e2 <- recycleListElements(e2, en) } partitioning <- PartitioningByEnd(e1) names(partitioning) <- nms relist(OP(unlist(e1, use.names=FALSE), unlist(e2, use.names=FALSE)), partitioning) } setMethod("Ops", signature(e1 = "CompressedAtomicList", e2 = "CompressedAtomicList"), function(e1, e2) { if (length(e1) == 0L || length(e2) == 0L) { return(emptyOpsReturnValue(.Generic, e1, e2, compress = TRUE)) } doBinaryCompressedListOp(function(x, y) { .Generic <- .Generic callGeneric(x, y) }, e1, e2) }) setMethod("Ops", signature(e1 = "SimpleAtomicList", e2 = "CompressedAtomicList"), function(e1, e2) { if (sum(as.numeric(elementLengths(e1))) < .Machine$integer.max) e1 <- as(e1, "CompressedList") else e2 <- as(e2, "SimpleList") callGeneric(e1, e2) }) setMethod("Ops", signature(e1 = "CompressedAtomicList", e2 = "SimpleAtomicList"), function(e1, e2) { if (sum(as.numeric(elementLengths(e2))) < .Machine$integer.max) e2 <- as(e2, "CompressedList") else e1 <- as(e1, "SimpleList") callGeneric(e1, e2) }) setMethod("Ops", signature(e1 = "AtomicList", e2 = "atomic"), function(e1, e2) { e2 <- as(e2, "List") callGeneric(e1, e2) }) setMethod("Ops", signature(e1 = "atomic", e2 = "AtomicList"), function(e1, e2) { e1 <- as(e1, "List") callGeneric(e1, e2) }) setMethod("Ops", signature(e1 = "SimpleAtomicList", e2 = "atomic"), function(e1, e2) { e2 <- as(e2, "SimpleList") callGeneric(e1, e2) }) setMethod("Ops", signature(e1 = "atomic", e2 = "SimpleAtomicList"), function(e1, e2) { e1 <- as(e1, "SimpleList") callGeneric(e1, e2) }) setMethod("Ops", signature(e1 = "CompressedAtomicList", e2 = "atomic"), function(e1, e2) { if (length(e2) > 1) { e2 <- S4Vectors:::recycleVector(e2, length(e1)) e2 <- rep(e2, elementLengths(e1)) } relist(callGeneric(e1@unlistData, e2), e1) }) setMethod("Ops", signature(e1 = "atomic", e2 = "CompressedAtomicList"), function(e1, e2) { if (length(e1) > 1) { e1 <- S4Vectors:::recycleVector(e1, length(e2)) e1 <- rep(e1, elementLengths(e2)) } relist(callGeneric(e1, e2@unlistData), e2) }) setMethod("Math", "CompressedAtomicList", function(x) { relist(callGeneric(x@unlistData), x) }) setMethod("cumsum", "CompressedAtomicList", function(x) { xunlist <- unlist(x, use.names=FALSE) xcumsum <- cumsum(as.numeric(xunlist)) partition <- PartitioningByEnd(x) ans <- xcumsum - rep(xcumsum[start(partition)] - xunlist[start(partition)], width(partition)) relist(ans, x) }) setMethod("cumprod", "CompressedAtomicList", function(x) { as(lapply(x, .Generic), "CompressedList") }) setMethod("cummin", "CompressedAtomicList", function(x) { as(lapply(x, .Generic), "CompressedList") }) setMethod("cummax", "CompressedAtomicList", function(x) { as(lapply(x, .Generic), "CompressedList") }) setMethod("Math", "SimpleAtomicList", function(x) as(lapply(x@listData, .Generic), "List")) setMethod("Math2", "CompressedAtomicList", function(x, digits) { if (missing(digits)) digits <- ifelse(.Generic == "round", 0, 6) relist(callGeneric(x@unlistData, digits = digits), x) }) setMethod("Math2", "SimpleAtomicList", function(x, digits) { if (missing(digits)) digits <- ifelse(.Generic == "round", 0, 6) as(lapply(x@listData, .Generic, digits = digits), "List") }) setMethod("Summary", "AtomicList", function(x, ..., na.rm = FALSE) { sapply(x, .Generic, na.rm = na.rm) }) setMethod("any", "CompressedAtomicList", function(x, na.rm = FALSE) { stopifnot(isTRUEorFALSE(na.rm)) ans <- sum(x, na.rm=TRUE) > 0L if (!na.rm) { ans[!ans & any(is.na(x), na.rm=TRUE)] <- NA } ans }) setMethod("all", "CompressedAtomicList", function(x, na.rm = FALSE) { stopifnot(isTRUEorFALSE(na.rm)) ans <- !any(!x, na.rm=TRUE) if (!na.rm) { ans[ans & any(is.na(x), na.rm=TRUE)] <- NA } ans }) rowsumCompressedList <- function(x, ..., na.rm = FALSE) { x_flat <- unlist(x, use.names = FALSE) ans <- vector(class(x_flat), length(x)) non_empty <- elementLengths(x) > 0 if (is.logical(x_flat)) x_flat <- as.integer(x_flat) ans[non_empty] <- rowsum(x_flat, togroup(x), reorder = FALSE, na.rm = na.rm)[,1] setNames(ans, names(x)) } setCompressedListSummaryMethod <- function(fun, where=topenv(parent.frame())) { types <- c("Logical", "Integer", "Numeric") classNames <- paste0("Compressed", types, "List") lapply(classNames, function(className) { setMethod(fun, className, function(x, na.rm = FALSE) { stopifnot(isTRUEorFALSE(na.rm)) .Call(paste0(className, "_", fun), x, na.rm) }, where=where) }) } setCompressedListSummaryMethod("sum") setCompressedListSummaryMethod("min") setCompressedListSummaryMethod("max") setMethods("range", list("CompressedLogicalList", "CompressedIntegerList", "CompressedNumericList"), function(x, na.rm=FALSE) { stopifnot(isTRUEorFALSE(na.rm)) cbind(min(x, na.rm=na.rm), max(x, na.rm=na.rm)) }) setMethod("Summary", "CompressedRleList", function(x, ..., na.rm = FALSE) { toViewFun <- list(max = viewMaxs, min = viewMins, sum = viewSums) if (!is.null(viewFun <- toViewFun[[.Generic]])) { ans <- viewFun(as(x, "RleViews"), na.rm = na.rm) names(ans) <- names(x) ans } else sapply(x, .Generic, na.rm = na.rm) }) setMethod("all", "CompressedRleList", function(x, ..., na.rm = FALSE) { args <- list(...) if (length(args) > 0L) stop("Only a single argument in '...' is supported for now") if (!isTRUEorFALSE(na.rm)) stop("'na.rm' must be TRUE or FALSE") rv <- runValue(x) if (na.rm) rv <- rv[!is.na(rv)] elen <- elementLengths(rv) ans <- elen == 0L singletons <- elen == 1L ans[singletons] <- unlist(rv, use.names = FALSE)[singletons[togroup(rv)]] ans }) setMethod("Complex", "CompressedAtomicList", function(z) relist(callGeneric(z@unlistData), z)) setMethod("Complex", "SimpleAtomicList", function(z) as(lapply(z@listData, .Generic), "List")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### More list-ized methods ### setListMethod <- function(f, inputClass, outputBaseClass, whichArg = 1L, remainingSignature = character(), mapply = FALSE, endoapply = FALSE, applyToUnlist = FALSE, where = topenv(parent.frame())) { fargs <- formals(args(get(f))) args <- sapply(names(fargs), as.name) names(args) <- sub("...", "", names(args), fixed = TRUE) if (applyToUnlist) { call2 <- as.call(c(as.name("@"), args[[whichArg]], "partitioning")) args[[whichArg]] <- as.call(c(as.name("@"), args[[whichArg]], "unlistData")) call1 <- as.call(c(as.name(f), args)) call <- as.call(c(as.name("new2"), paste("Compressed", outputBaseClass, sep=""), unlistData = call1, partitioning = call2, check = FALSE)) } else { args <- c(args[[whichArg]], as.name(f), args[-whichArg]) if (endoapply) { call <- as.call(c(as.name("endoapply"), args)) } else if (missing(outputBaseClass)) { call <- as.call(c(as.name("sapply"), args, list(simplify = TRUE))) } else { if (mapply) { if (length(args) <= 3) { call <- as.call(c(as.name("mapply"), args[c(2:1,3L)], SIMPLIFY = FALSE)) } else { call <- as.call(c(as.name("mapply"), args[c(2:1,3L)], MoreArgs = as.call(c(as.name("list"), tail(args, -3))), SIMPLIFY = FALSE)) } } else { call <- as.call(c(as.name("lapply"), args)) } if (extends(inputClass, "SimpleList")) { call <- as.call(c(as.name("new2"), paste("Simple", outputBaseClass, sep=""), listData = call, check = FALSE)) } else { call <- as.call(c(as.name(outputBaseClass), call, compress = TRUE)) } } } def <- as.function(c(fargs, call)) environment(def) <- parent.frame() setMethod(f, c(rep("ANY", whichArg - 1L), inputClass, remainingSignature), def, where) } setAtomicListMethod <- function(f, inputBaseClass = "AtomicList", outputBaseClass, whichArg = 1L, remainingSignature = character(), mapply = FALSE, endoapply = FALSE, applyToUnlist = FALSE, addRleList = TRUE, rleListOutputBaseClass = "RleList", where = topenv(parent.frame())) { if (missing(outputBaseClass)) { for (i in inputBaseClass) setListMethod(f, i, whichArg = whichArg, remainingSignature = remainingSignature, endoapply = endoapply, where = where) } else if (endoapply) { setListMethod(f, "AtomicList", whichArg = whichArg, remainingSignature = remainingSignature, endoapply = TRUE, where = where) } else { setListMethod(f, paste("Simple", inputBaseClass, sep = ""), outputBaseClass = outputBaseClass, whichArg = whichArg, remainingSignature = remainingSignature, mapply = mapply, where = where) setListMethod(f, paste("Compressed", inputBaseClass, sep = ""), outputBaseClass = outputBaseClass, whichArg = whichArg, remainingSignature, mapply = mapply, applyToUnlist = applyToUnlist, where = where) if (addRleList) { setListMethod(f, "SimpleRleList", outputBaseClass = rleListOutputBaseClass, whichArg = whichArg, remainingSignature = remainingSignature, mapply = mapply, where = where) setListMethod(f, "CompressedRleList", outputBaseClass = rleListOutputBaseClass, whichArg = whichArg, remainingSignature = remainingSignature, mapply = mapply, applyToUnlist = applyToUnlist, where = where) } } } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### General methods ### ### S3/S4 combo for unique.RleList unique.RleList <- function(x, incomparables=FALSE, ...) unique(runValue(x), incomparables=incomparables, ...) setMethod("unique", "RleList", unique.RleList) ### S3/S4 combo for duplicated.CompressedIntegerList duplicated.CompressedIntegerList <- function(x, incomparables=FALSE, fromLast=FALSE, ...) { if (!identical(incomparables, FALSE)) stop("\"duplicated\" method for CompressedList objects ", "does not support the 'incomparables' argument") if (length(list(...)) > 0L) { stop("arguments in '...' are not supported") } x_unlistData <- x@unlistData x_group <- rep.int(seq_along(x), elementLengths(x)) ans_unlistData <- S4Vectors:::duplicatedIntegerPairs(x_group, x_unlistData, fromLast=fromLast) relist(ans_unlistData, x) } setMethod("duplicated", "CompressedIntegerList", duplicated.CompressedIntegerList) ### Could actually be made the "table" method for List objects. Will work on ### any List object 'x' for which 'as.factor(unlist(x))' works. setMethod("table", "AtomicList", function(...) { args <- list(...) if (length(args) != 1L) stop("\"table\" method for AtomicList objects ", "can only take one input object") x <- args[[1L]] y1 <- togroup(x) attributes(y1) <- list(levels=as.character(seq_along(x)), class="factor") y2 <- as.factor(unlist(x, use.names=FALSE)) ans <- table(y1, y2) names(dimnames(ans)) <- NULL x_names <- names(x) if (!is.null(x_names)) rownames(ans) <- x_names ans } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Logical methods ### setAtomicListMethod("which", inputBaseClass = "LogicalList", outputBaseClass = "IntegerList", rleListOutputBaseClass = "IntegerList") setMethod("which", "CompressedLogicalList", function(x) { x.flat <- unlist(x, use.names = FALSE) part <- PartitioningByEnd(x) which.global <- which(x.flat) group <- findInterval(which.global, start(part)) which.local <- which.global - start(part)[group] + 1L ans <- splitAsList(which.local, factor(group, seq_len(length(x)))) names(ans) <- names(x) ans }) ifelseReturnValue <- function(yes, no, len) { proto <- function(x) new(if (is.atomic(x)) class(x) else x@elementType) v <- logical() v[1L] <- proto(yes)[1L] v[1L] <- proto(no)[1L] v compress <- is(yes, "CompressedList") || is(no, "CompressedList") as(rep(v, length.out = len), if(compress) "CompressedList" else "SimpleList") } setMethods("ifelse", list(c("ANY", "ANY", "List"), c("ANY", "List", "List"), c("ANY", "List", "ANY")), function(test, yes, no) { ans <- ifelseReturnValue(yes, no, length(test)) ok <- !(nas <- is.na(test)) if (any(test[ok])) ans[test & ok] <- rep(yes, length.out = length(ans))[test & ok] if (any(!test[ok])) ans[!test & ok] <- rep(no, length.out = length(ans))[!test & ok] ans[nas] <- NA names(ans) <- names(test) ans }) setMethods("ifelse", list(c("CompressedLogicalList", "ANY", "ANY"), c("CompressedLogicalList", "ANY", "List"), c("CompressedLogicalList", "List", "ANY"), c("CompressedLogicalList", "List", "List")), function(test, yes, no) { doBinaryCompressedListOp(function(yes, no) { ifelse(unlist(test, use.names=FALSE), yes, no) }, as(yes, "List"), as(no, "List"), test) }) setMethods("ifelse", list(c("SimpleLogicalList", "ANY", "ANY"), c("SimpleLogicalList", "ANY", "List"), c("SimpleLogicalList", "List", "ANY"), c("SimpleLogicalList", "List", "List")), function(test, yes, no) { as(mapply(ifelse, test, yes, no, SIMPLIFY=FALSE), "List") }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Numerical methods ### for (i in c("IntegerList", "NumericList", "RleList")) { setAtomicListMethod("diff", inputBaseClass = i, endoapply = TRUE) setAtomicListMethod("which.max", inputBaseClass = i) setAtomicListMethod("which.min", inputBaseClass = i) setMethod("pmax", i, function(..., na.rm = FALSE) mendoapply(pmax, ..., MoreArgs = list(na.rm = na.rm))) setMethod("pmin", i, function(..., na.rm = FALSE) mendoapply(pmin, ..., MoreArgs = list(na.rm = na.rm))) setMethod("pmax.int", i, function(..., na.rm = FALSE) mendoapply(pmax.int, ..., MoreArgs = list(na.rm = na.rm))) setMethod("pmin.int", i, function(..., na.rm = FALSE) mendoapply(pmin.int, ..., MoreArgs = list(na.rm = na.rm))) } setMethod("mean", "AtomicList", function(x, ...) sapply(x, mean, ...) ) setMethods("mean", list("CompressedLogicalList", "CompressedIntegerList", "CompressedNumericList"), function(x, trim = 0, na.rm = FALSE) { stopifnot(isTRUEorFALSE(na.rm)) stopifnot(isSingleNumber(trim)) if (trim > 0) { return(callNextMethod()) } lens <- if (na.rm) sum(!is.na(x)) else elementLengths(x) sum(x, na.rm=na.rm) / lens }) setMethod("var", c("AtomicList", "missing"), function(x, y=NULL, na.rm=FALSE, use) { if (missing(use)) use <- ifelse(na.rm, "na.or.complete", "everything") sapply(x, var, na.rm=na.rm, use=use) } ) setMethod("var", c("AtomicList", "AtomicList"), function(x, y=NULL, na.rm=FALSE, use) { if (missing(use)) use <- ifelse(na.rm, "na.or.complete", "everything") mapply(var, x, y, MoreArgs=list(na.rm=na.rm, use=use)) } ) setMethod("cov", c("AtomicList", "AtomicList"), function(x, y=NULL, use="everything", method=c("pearson", "kendall", "spearman")) mapply(cov, x, y, MoreArgs=list(use=use, method=match.arg(method))) ) setMethod("cor", c("AtomicList", "AtomicList"), function(x, y=NULL, use="everything", method=c("pearson", "kendall", "spearman")) mapply(cor, x, y, MoreArgs=list(use=use, method=match.arg(method))) ) setMethod("sd", "AtomicList", function(x, na.rm=FALSE) sapply(x, sd, na.rm=na.rm) ) setMethod("median", "AtomicList", function(x, na.rm=FALSE) sapply(x, median, na.rm=na.rm) ) setMethod("quantile", "AtomicList", function(x, ...) sapply(x, quantile, ...) ) setMethod("mad", "AtomicList", function(x, center=median(x), constant=1.4826, na.rm=FALSE, low=FALSE, high=FALSE) { if (!missing(center)) stop("'center' argument is not supported") sapply(x, mad, constant=constant, na.rm=na.rm, low=low, high=high) } ) setMethod("IQR", "AtomicList", function(x, na.rm=FALSE, type=7) sapply(x, IQR, na.rm=na.rm, type=type) ) setMethod("which.max", "CompressedRleList", function(x) { viewWhichMaxs(as(x, "RleViews"), na.rm=TRUE) - c(0L, head(cumsum(elementLengths(x)), -1)) }) setMethod("which.min", "CompressedRleList", function(x) { viewWhichMins(as(x, "RleViews"), na.rm=TRUE) - c(0L, head(cumsum(elementLengths(x)), -1)) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Running window statistic methods ### setAtomicListMethod("smoothEnds", inputBaseClass = "IntegerList", outputBaseClass = "NumericList", addRleList = FALSE) setAtomicListMethod("smoothEnds", inputBaseClass = "NumericList", endoapply = TRUE) setAtomicListMethod("smoothEnds", inputBaseClass = "RleList", endoapply = TRUE) setMethod("runmed", "CompressedIntegerList", function(x, k, endrule = c("median", "keep", "constant"), algorithm = NULL, print.level = 0) NumericList(lapply(x, runmed, k = k, endrule = match.arg(endrule), algorithm = algorithm, print.level = print.level))) setMethod("runmed", "SimpleIntegerList", function(x, k, endrule = c("median", "keep", "constant"), algorithm = NULL, print.level = 0) NumericList(lapply(x, runmed, k = k, endrule = match.arg(endrule), algorithm = algorithm, print.level = print.level), compress = FALSE)) setMethod("runmed", "NumericList", function(x, k, endrule = c("median", "keep", "constant"), algorithm = NULL, print.level = 0) endoapply(x, runmed, k = k, endrule = match.arg(endrule), algorithm = algorithm, print.level = print.level)) setMethod("runmed", "RleList", function(x, k, endrule = c("median", "keep", "constant"), algorithm = NULL, print.level = 0) endoapply(x, runmed, k = k, endrule = match.arg(endrule))) setMethod("runmean", "RleList", function(x, k, endrule = c("drop", "constant"), na.rm = FALSE) endoapply(x, runmean, k = k, endrule = match.arg(endrule), na.rm = na.rm)) setMethod("runsum", "RleList", function(x, k, endrule = c("drop", "constant"), na.rm = FALSE) endoapply(x, runsum, k = k, endrule = match.arg(endrule), na.rm = na.rm)) setMethod("runwtsum", "RleList", function(x, k, wt, endrule = c("drop", "constant"), na.rm = FALSE) endoapply(x, runwtsum, k = k, wt = wt, endrule = match.arg(endrule), na.rm = na.rm)) setMethod("runq", "RleList", function(x, k, i, endrule = c("drop", "constant"), na.rm = FALSE) endoapply(x, runq, k = k, i = i, endrule = match.arg(endrule), na.rm = na.rm)) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Character ### nchar_CompressedList <- function(x, type="chars", allowNA=FALSE) { unlisted_x <- unlist(x, use.names=FALSE) unlisted_ans <- nchar(unlisted_x, type=type, allowNA=allowNA) relist(unlisted_ans, x) } setMethod("nchar", "CompressedCharacterList", nchar_CompressedList) setMethod("nchar", "SimpleCharacterList", nchar_CompressedList) setMethod("nchar", "CompressedRleList", nchar_CompressedList) setMethod("nchar", "SimpleRleList", nchar_CompressedList) ## need vectorized start, end ##setAtomicListMethod("substr") ##setAtomicListMethod("substring") setAtomicListMethod("chartr", inputBaseClass = "CharacterList", outputBaseClass = "CharacterList", whichArg = 3L, applyToUnlist = TRUE) setAtomicListMethod("tolower", inputBaseClass = "CharacterList", outputBaseClass = "CharacterList", applyToUnlist = TRUE) setAtomicListMethod("toupper", inputBaseClass = "CharacterList", outputBaseClass = "CharacterList", applyToUnlist = TRUE) setAtomicListMethod("sub", inputBaseClass = "CharacterList", outputBaseClass = "CharacterList", whichArg = 3L, applyToUnlist = TRUE) setAtomicListMethod("gsub", inputBaseClass = "CharacterList", outputBaseClass = "CharacterList", whichArg = 3L, applyToUnlist = TRUE) ### TODO: grep, grepl setMethod("unstrsplit", "CharacterList", function(x, sep="") unstrsplit(as.list(x), sep=sep) ) setMethod("paste", "CompressedAtomicList", function(..., sep=" ", collapse=NULL) { args <- lapply(list(...), as, "CharacterList") lens <- do.call(pmax, lapply(args, elementLengths)) args <- lapply(args, recycleListElements, lens) unlisted <- lapply(args, unlist, use.names=FALSE) ans <- relist(do.call(paste, c(unlisted, sep=sep)), PartitioningByWidth(lens)) if (!is.null(collapse)) { ans <- unstrsplit(ans, collapse) } ans }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Rle methods ### ### 'use.names' is ignored. setMethod("unlist", "SimpleRleList", function (x, recursive=TRUE, use.names=TRUE) { if (!identical(recursive, TRUE)) stop("\"unlist\" method for SimpleRleList objects ", "does not support the 'recursive' argument") ans_values <- unlist(lapply(x@listData, slot, "values"), use.names=FALSE) ans_lengths <- unlist(lapply(x@listData, slot, "lengths"), use.names=FALSE) Rle(ans_values, ans_lengths) } ) setMethod("runValue", "RleList", function(x) { as(lapply(x, runValue), "List") }) setMethod("runValue", "CompressedRleList", function(x) { rle <- unlist(x, use.names=FALSE) rlePart <- PartitioningByWidth(runLength(rle)) listPart <- PartitioningByEnd(x) ## 'rlePart' cannot contain empty ranges so using ## Using 'hit.empty.query.ranges=TRUE' won't affect the result ## (because 'rlePart' cannot contain empty ranges) but it makes ## findOverlaps_Ranges_Partitioning() just a little bit faster. hits <- findOverlaps_Ranges_Partitioning(rlePart, listPart, hit.empty.query.ranges=TRUE) ans_partitioning <- PartitioningByEnd(subjectHits(hits), NG=length(x)) ans_unlistData <- runValue(rle)[queryHits(hits)] ans <- relist(ans_unlistData, ans_partitioning) names(ans) <- names(x) ans } ) setReplaceMethod("runValue", "CompressedRleList", function(x, value) { if (!identical(elementLengths(ranges(x)), elementLengths(value))) stop("elementLengths() of 'x' and 'value' must match") runValue(x@unlistData) <- unlist(value, use.names=FALSE) x }) setReplaceMethod("runValue", "SimpleRleList", function(x, value) { if (!identical(elementLengths(ranges(x)), elementLengths(value))) stop("elementLengths() of 'x' and 'value' must match") x@listData <- mapply(function(rle, v) { runValue(rle) <- v rle }, x, value, SIMPLIFY=FALSE) x }) setMethod("runLength", "RleList", function(x) { as(lapply(x, runLength), "IntegerList") }) setMethod("runLength", "CompressedRleList", function(x) { width(ranges(x)) }) setMethod("ranges", "RleList", function(x) { as(lapply(x, ranges), "List") }) diceRangesByList <- function(x, list) { listPart <- PartitioningByEnd(list) ## 'x' cannot contain empty ranges so using ## 'hit.empty.query.ranges=TRUE' won't affect the result but ## it makes findOverlaps_Ranges_Partitioning() just a little ## bit faster. hits <- findOverlaps_Ranges_Partitioning(x, listPart, hit.empty.query.ranges=TRUE) ans_partitioning <- PartitioningByEnd(subjectHits(hits), NG=length(list)) ans_unlistData <- shift(ranges(hits, x, listPart), 1L - start(listPart)[subjectHits(hits)]) ans <- relist(ans_unlistData, ans_partitioning) names(ans) <- names(list) ans } setMethod("ranges", "CompressedRleList", function(x) { rle <- unlist(x, use.names=FALSE) rlePart <- PartitioningByWidth(runLength(rle)) diceRangesByList(rlePart, x) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Factor methods ### setMethod("levels", "FactorList", function(x) { CharacterList(lapply(x, levels)) }) setMethod("levels", "CompressedFactorList", function(x) { setNames(rep(CharacterList(levels(x@unlistData)), length(x)), names(x)) }) setMethod("unlist", "SimpleFactorList", function(x, recursive = TRUE, use.names = TRUE) { levs <- levels(x) if (length(x) > 1L && !all(vapply(levs[-1L], identical, logical(1L), levs[[1L]]))) { stop("inconsistent level sets") } structure(callNextMethod(), levels=as.character(levs[[1L]]), class="factor") }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "show" method. ### .showAtomicList <- function(object, minLines, ...) { len <- length(object) object_names <- names(object) k <- min(minLines, len) d <- len - minLines for (i in seq_len(k)) { if (is.null(object_names)) { label <- i } else { nm <- object_names[[i]] if (is.na(nm)) { label <- "NA" } else { label <- paste0("\"", nm, "\"") } } label <- paste0("[[", label, "]]") if (length(object[[i]]) == 0) { cat(label, " ", sep = "") print(object[[i]]) } else { cat(S4Vectors:::labeledLine(label, object[[i]], labelSep = "", count = FALSE)) } } if (d > 0) cat("...\n<", d, ifelse(d == 1, " more element>\n", " more elements>\n"), sep="") } setMethod("show", "AtomicList", function(object) { cat(classNameForDisplay(object), " of length ", length(object), "\n", sep = "") .showAtomicList(object, 10) } ) setMethod("show", "RleList", function(object) { lo <- length(object) k <- min(5, length(object)) diffK <- lo - 5 cat(classNameForDisplay(object), " of length ", lo, "\n", sep = "") show(as.list(head(object, k))) if (diffK > 0) cat("...\n<", diffK, ifelse(diffK == 1, " more element>\n", " more elements>\n"), sep="") }) setMethod("showAsCell", "AtomicList", function(object) { if (length(object) == 0L) return(character(0)) unlist(lapply(object, function(x) { str <- paste(as.vector(head(x, 3)), collapse = ",") if (length(x) > 3) str <- paste(str, "...", sep = ",") str }), use.names = FALSE) }) IRanges/R/CompressedList-class.R0000644000175100017510000004503412607265143017525 0ustar00biocbuildbiocbuild### ========================================================================= ### CompressedList objects ### ------------------------------------------------------------------------- setClass("CompressedList", contains="List", representation( "VIRTUAL", partitioning="PartitioningByEnd", unlistData="ANY" ) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor methods. ### setMethod("elementLengths", "CompressedList", function(x) { ans <- elementLengths(x@partitioning) names(ans) <- names(x) ans } ) setMethod("length", "CompressedList", function(x) length(x@partitioning)) setMethod("names", "CompressedList", function(x) names(x@partitioning)) setReplaceMethod("names", "CompressedList", function(x, value) { names(x@partitioning) <- value x }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor. ### ### Use ### IRanges:::newCompressedList0(getClass("MyClass"), ### unlistData, partitioning) ### when calling this from another package. ### compress_listData <- function(x, elementType = NULL) { if (length(x) > 0L) { if (identical(elementType, "factor")) { x <- unlist(x, recursive=FALSE, use.names=FALSE) } else if (length(dim(x[[1L]])) < 2L) { x <- do.call(c, unname(x)) } else { x <- do.call(rbind, unname(x)) } } else { x <- vector() } x } .reconcileMetadatacols <- function(x) { x_mcols <- mcols(x) if (is(x_mcols, "DataFrame") && nrow(x_mcols) == 0L && ncol(x_mcols) == 0L) { x_mcols <- new("DataFrame", nrows=length(x)) mcols(x) <- x_mcols } x } ### Low-level. NOT exported. newCompressedList0 <- function(Class, unlistData, partitioning) { ans <- new2(Class, unlistData=unlistData, partitioning=partitioning, check=FALSE) .reconcileMetadatacols(ans) } ### Low-level. NOT exported. ### Stuff to put in elementMetadata slot can be passed either with ### new_CompressedList_from_list(..., elementMetadata=somestuff) ### or with ### new_CompressedList_from_list(..., mcols=somestuff) ### The latter is the new recommended form. new_CompressedList_from_list <- function(Class, x, ..., mcols) { if (!extends(Class, "CompressedList")) stop("class ", Class, " must extend CompressedList") if (!is.list(x)) stop("'x' must be a list") ans_elementType <- elementType(new(Class)) if (!all(sapply(x, function(xi) extends(class(xi), ans_elementType)))) stop("all elements in 'listData' must be ", ans_elementType, " objects") ans_partitioning <- PartitioningByEnd(x) if (length(x) == 0L) { if (missing(mcols)) return(new2(Class, partitioning=ans_partitioning, ..., check=FALSE)) return(new2(Class, partitioning=ans_partitioning, ..., elementMetadata=mcols, check=FALSE)) } ans_unlistData <- compress_listData(x, ans_elementType) if (missing(mcols)) { ans <- new2(Class, unlistData=ans_unlistData, partitioning=ans_partitioning, ..., check=FALSE) } else { ans <- new2(Class, unlistData=ans_unlistData, partitioning=ans_partitioning, ..., elementMetadata=mcols, check=FALSE) } .reconcileMetadatacols(ans) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### .valid.CompressedList.partitioning <- function(x) { dataLength <- NROW(x@unlistData) if (nobj(x@partitioning) != dataLength) "improper partitioning" else NULL } .valid.CompressedList.unlistData <- function(x) { ## FIXME: workaround to support CompressedNormalIRangesList ## elementTypeX <- elementType(x) elementTypeX <- elementType(new(class(x))) if (!extends(class(x@unlistData), elementTypeX)) paste("the 'unlistData' slot must be of class", elementTypeX) else NULL } .valid.CompressedList <- function(x) { c(.valid.CompressedList.unlistData(x), .valid.CompressedList.partitioning(x)) } setValidity2("CompressedList", .valid.CompressedList) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### setUnlistDataNames <- function(unlisted_x, grouping, use.names, x_class) { ## If 'use.names' is FALSE or 'x' has no *outer* names, then we don't ## do anything to 'ans' i.e. we just keep whatever names/rownames are ## on it (which are the *inner* names/rownames of 'x'). Note that this ## behavior is NOT consistent with unlist,List or base::unlist as ## both of them will return a vector with no names/rownames when ## 'use.names' is FALSE. ## FIXME: Make unlist,CompressedList and unlist,List behave ## consistently in *any* situation. ## Otherwise (i.e. if 'use.names' is TRUE and 'x' has *outer* names), ## we make up new names/rownames for 'ans' by prepending the *outer* ## names of 'x' to its *inner* names/rownames. Note that this differs ## from what base::unlist does but THIS IS A FEATURE and is consistent ## with what unlist,List does. if (use.names && !is.null(x_names <- names(grouping))) { if (length(dim(unlisted_x)) < 2L) { ans_ROWNAMES <- names(unlisted_x) } else { ans_ROWNAMES <- rownames(unlisted_x) } nms <- rep.int(x_names, elementLengths(grouping)) ans_ROWNAMES <- S4Vectors:::make_unlist_result_names(nms, ans_ROWNAMES) if (length(dim(unlisted_x)) < 2L) { res <- try(names(unlisted_x) <- ans_ROWNAMES, silent=TRUE) what <- "names" } else { res <- try(rownames(unlisted_x) <- ans_ROWNAMES, silent=TRUE) what <- "rownames" } if (is(res, "try-error")) warning("failed to set ", what, " on the ", "unlisted ", x_class, " object") } unlisted_x } setMethod("unlist", "CompressedList", function(x, recursive=TRUE, use.names=TRUE) { if (!identical(recursive, TRUE)) stop("\"unlist\" method for CompressedList objects ", "does not support the 'recursive' argument") if (!isTRUEorFALSE(use.names)) stop("'use.names' must be TRUE or FALSE") setUnlistDataNames(x@unlistData, x@partitioning, use.names, class(x)) } ) setAs("ANY", "CompressedList", function(from) coerceToCompressedList(from)) coerceToCompressedList <- function(from, element.type = NULL, ...) { if (is(from, S4Vectors:::listClassName("Compressed", element.type))) return(from) if (is.list(from) || (is(from, "List") && !is(from, "DataFrame"))) { if (is.list(from)) { v <- compress_listData(from, element.type) } else { v <- unlist(from, use.names = FALSE) } part <- PartitioningByEnd(from) } else { v <- from part <- PartitioningByEnd(seq_len(NROW(from))) } if (!is.null(element.type)) { v <- S4Vectors:::coercerToClass(element.type)(v, ...) } to <- relist(v, part) names(to) <- names(from) to } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Subsetting. ### setMethod("extractROWS", "CompressedList", function(x, i) { i <- normalizeSingleBracketSubscript(i, x, as.NSBS=TRUE) ans_eltlens <- extractROWS(width(x@partitioning), i) ans_breakpoints <- suppressWarnings(cumsum(ans_eltlens)) nbreakpoints <- length(ans_breakpoints) if (nbreakpoints != 0L && is.na(ans_breakpoints[[nbreakpoints]])) stop(wmsg("Subsetting operation on ", class(x), " object 'x' ", "produces a result that is too big to be ", "represented as a CompressedList object. ", "Please try to coerce 'x' to a SimpleList object ", "first (with 'as(x, \"SimpleList\")').")) idx_on_unlisted_x <- IRanges(end=extractROWS(end(x@partitioning), i), width=ans_eltlens) ans_unlistData <- extractROWS(x@unlistData, idx_on_unlisted_x) ans_partitioning <- new2("PartitioningByEnd", end=ans_breakpoints, NAMES=extractROWS(names(x), i), check=FALSE) ans_elementMetadata <- extractROWS(x@elementMetadata, i) initialize(x, unlistData=ans_unlistData, partitioning=ans_partitioning, elementMetadata=ans_elementMetadata) } ) setMethod("getListElement", "CompressedList", function(x, i, exact=TRUE) { i <- normalizeDoubleBracketSubscript(i, x, exact=exact, error.if.nomatch=FALSE) if (is.na(i)) return(NULL) unlisted_x <- unlist(x, use.names=FALSE) x_partitioning <- PartitioningByEnd(x) window_start <- start(x_partitioning)[i] window_end <- end(x_partitioning)[i] window.Vector(unlisted_x, start=window_start, end=window_end) } ) setReplaceMethod("[[", "CompressedList", function(x, i, j,..., value) { nameValue <- if (is.character(i)) i else "" i <- S4Vectors:::normargSubset2_iOnly(x, i, j, ..., .conditionPrefix="[[<-,CompressedList-method: ") if (is.null(value)) { if (i <= length(x)) # if name did not exist, could be +1 x <- x[-i] } else { value <- try(as(value, elementType(x)), silent = TRUE) if (inherits(value, "try-error")) stop("cannot coerce 'value' to a ", elementType(x), " instance") listData <- as.list(x, use.names = FALSE) listData[[i]] <- value widths <- elementLengths(x) names(widths) <- NULL widths[i] <- NROW(value) if ((i == length(x) + 1L) && (!is.null(names(x)) || nchar(nameValue) > 0)) { NAMES <- names(x) if (is.null(NAMES)) NAMES <- rep.int("", length(x)) NAMES[i] <- nameValue } else { NAMES <- names(x) } slot(x, "unlistData", check=FALSE) <- compress_listData(listData, elementType(x)) slot(x, "partitioning", check=FALSE) <- new2("PartitioningByEnd", end = cumsum(widths), NAMES = NAMES, check=FALSE) if (i > length(x)) x <- S4Vectors:::rbindRowOfNAsToMetadatacols(x) x } }) setReplaceMethod("$", "CompressedList", function(x, name, value) { x[[name]] <- value x }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Combining. ### .bindROWS <- function(...) { args <- list(...) if (length(dim(args[[1L]])) >= 2L) return(rbind(...)) if (!is.factor(args[[1L]])) return(c(...)) ans_levels <- unique(unlist(lapply(args, levels))) x <- unlist(lapply(args, as.character)) factor(x, levels=ans_levels) } ### Not exported. combine_CompressedList_objects <- function(Class, objects, use.names=TRUE, ignore.mcols=FALSE) { if (!isSingleString(Class)) stop("'Class' must be a single character string") if (!extends(Class, "CompressedList")) stop("'Class' must be the name of a class that extends CompressedList") if (!is.list(objects)) stop("'objects' must be a list") if (!isTRUEorFALSE(use.names)) stop("'use.names' must be TRUE or FALSE") ### TODO: Support 'use.names=TRUE'. if (use.names) stop("'use.names=TRUE' is not supported yet") if (!isTRUEorFALSE(ignore.mcols)) stop("'ignore.mcols' must be TRUE or FALSE") if (length(objects) != 0L) { ## TODO: Implement (in C) fast 'elementIsNull(objects)' in S4Vectors ## that does 'sapply(objects, is.null, USE.NAMES=FALSE)', and use it ## here. null_idx <- which(sapply(objects, is.null, USE.NAMES=FALSE)) if (length(null_idx) != 0L) objects <- objects[-null_idx] } if (length(objects) == 0L) return(new(Class)) ## TODO: Implement (in C) fast 'elementIs(objects, class)' in S4Vectors ## that does 'sapply(objects, is, class, USE.NAMES=FALSE)', and use it ## here. 'elementIs(objects, "NULL")' should work and be equivalent to ## 'elementIsNull(objects)'. if (!all(sapply(objects, is, "CompressedList", USE.NAMES=FALSE))) stop("the objects to combine must be CompressedList objects (or NULLs)") objects_names <- names(objects) names(objects) <- NULL # so lapply(objects, ...) below returns an # unnamed list ## Combine "unlistData" slots. unlistData_slots <- lapply(objects, function(x) x@unlistData) ans_unlistData <- do.call(.bindROWS, unlistData_slots) ## Combine "partitioning" slots. ans_breakpoints <- cumsum(unlist(lapply(objects, elementLengths))) ans_partitioning <- PartitioningByEnd(ans_breakpoints) ans <- newCompressedList0(Class, ans_unlistData, ans_partitioning) ## Combine "mcols" slots. if (!ignore.mcols) { ans_mcols <- do.call(S4Vectors:::rbind_mcols, objects) rownames(ans_mcols) <- NULL mcols(ans) <- ans_mcols } ans } setMethod("c", "CompressedList", function (x, ..., ignore.mcols=FALSE, recursive=FALSE) { if (!identical(recursive, FALSE)) stop("\"c\" method for CompressedList objects ", "does not support the 'recursive' argument") if (missing(x)) { objects <- list(...) x <- objects[[1L]] } else { objects <- list(x, ...) } combine_CompressedList_objects(class(x), objects, use.names=FALSE, ignore.mcols=ignore.mcols) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Looping. ### ### Cannot really avoid the cost of extracting X[[i]] for all valid i but tries ### to minimize this cost by using 2 tricks: ### 1. Avoids looping on values of i for which X[[i]] has length 0. Instead ### FUN(X[[i]], ...) is computed only once (because it's the same for all ### these values of i) and placed at the corresponding positions in the ### returned list. ### 2. Turn off object validation during the main loop. Note that there is no ### reason to restrict this trick to CompressedList objects and the same ### trick could be used in the "lapply" method for List objects. ### Does NOT propagate the names. lapply_CompressedList <- function(X, FUN, ...) { FUN <- match.fun(FUN) ans <- vector(mode="list", length=length(X)) unlisted_X <- unlist(X, use.names=FALSE) X_partitioning <- PartitioningByEnd(X) X_elt_width <- width(X_partitioning) empty_idx <- which(X_elt_width == 0L) if (length(empty_idx) != 0L) ans[empty_idx] <- list(FUN(extractROWS(unlisted_X, integer(0)), ...)) non_empty_idx <- which(X_elt_width != 0L) if (length(non_empty_idx) == 0L) return(ans) X_elt_start <- start(X_partitioning) X_elt_end <- end(X_partitioning) old_validity_status <- S4Vectors:::disableValidity() S4Vectors:::disableValidity(TRUE) on.exit(S4Vectors:::disableValidity(old_validity_status)) ans[non_empty_idx] <- lapply(non_empty_idx, function(i) FUN(extractROWS(unlisted_X, IRanges(X_elt_start[i], X_elt_end[i])), ...)) S4Vectors:::disableValidity(old_validity_status) for (i in non_empty_idx) { obj <- ans[[i]] if (isS4(obj) && !isTRUE(validObject(obj, test=TRUE))) stop("invalid output element of class \"", class(obj), "\"") } ans } setMethod("lapply", "CompressedList", function(X, FUN, ...) { ans <- lapply_CompressedList(X, FUN, ...) names(ans) <- names(X) ans } ) .updateCompressedList <- function(X, listData) { elementTypeX <- elementType(X) if (!all(sapply(listData, function(Xi) extends(class(Xi), elementTypeX)))) stop("'FUN' must return elements of class ", elementTypeX) if (length(listData) == 0) { end <- integer(0) } else { end <- cumsum(unlist(lapply(listData, NROW), use.names = FALSE)) } initialize(X, unlistData = compress_listData(listData, elementTypeX), partitioning = new2("PartitioningByEnd", end = end, NAMES = names(X), check=FALSE)) } setMethod("endoapply", "CompressedList", function(X, FUN, ...) { .updateCompressedList(X, lapply_CompressedList(X, FUN, ...)) }) setMethod("mendoapply", "CompressedList", function(FUN, ..., MoreArgs = NULL) { .updateCompressedList(list(...)[[1L]], mapply(FUN = match.fun(FUN), ..., MoreArgs = MoreArgs, SIMPLIFY = FALSE)) }) setMethod("revElements", "CompressedList", function(x, i) { i <- normalizeSingleBracketSubscript(i, x, as.NSBS=TRUE) if (length(i) == 0L) return(x) elt_lens <- elementLengths(x) offset <- cumsum(c(0L, elt_lens[-length(elt_lens)])) rev <- logical(length(x)) rev <- replaceROWS(rev, i, TRUE) ii <- S4Vectors:::fancy_mseq(elt_lens, offset=offset, rev=rev) x@unlistData <- extractROWS(x@unlistData, ii) x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### classNameForDisplay() ### setMethod("classNameForDisplay", "CompressedList", function(x) sub("^Compressed", "", class(x)) ) IRanges/R/DataFrame-utils.R0000644000175100017510000000111112607265143016430 0ustar00biocbuildbiocbuild### ========================================================================= ### DataFrame utilities ### ------------------------------------------------------------------------- ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Splitting. ### setMethod("relistToClass", "data.frame", function(x) "CompressedSplitDataFrameList" ) setMethod("relistToClass", "DataFrame", function(x) "CompressedSplitDataFrameList" ) setMethod("mstack", "DataFrame", function(..., .index.var = "name") { stack(DataFrameList(...), index.var = .index.var) }) IRanges/R/DataFrameList-class.R0000644000175100017510000003634712607265143017254 0ustar00biocbuildbiocbuild### ========================================================================= ### DataFrameList objects ### ------------------------------------------------------------------------- setClass("DataFrameList", representation("VIRTUAL"), prototype = prototype(elementType = "DataFrame"), contains = "List") setClass("SimpleDataFrameList", contains = c("DataFrameList", "SimpleList")) setClass("CompressedDataFrameList", prototype = prototype(unlistData = new("DataFrame")), contains = c("DataFrameList", "CompressedList")) setClass("SplitDataFrameList", representation("VIRTUAL"), contains = "DataFrameList") setClass("SimpleSplitDataFrameList", contains = c("SplitDataFrameList", "SimpleDataFrameList")) setClass("CompressedSplitDataFrameList", contains = c("SplitDataFrameList", "CompressedDataFrameList")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor methods. ### setMethod("nrow", "DataFrameList", function(x) { if (length(x) == 0L) 0L else elementLengths(x) }) setMethod("ncol", "DataFrameList", function(x) { if (length(x) == 0L) 0L else unlist(lapply(x, ncol)) }) setMethod("ncol", "SimpleSplitDataFrameList", function(x) { if (length(x) == 0L) 0L else structure(rep.int(ncol(x[[1L]]), length(x)), names = names(x)) }) setMethod("ncol", "CompressedSplitDataFrameList", function(x) { if (length(x) == 0L) 0L else structure(rep.int(ncol(x@unlistData), length(x)), names = names(x)) }) setMethod("dim", "DataFrameList", function(x) { cbind(nrow(x), ncol(x)) }) setMethod("rownames", "DataFrameList", function(x, do.NULL = TRUE, prefix = "row") { CharacterList(lapply(x, rownames, do.NULL = do.NULL, prefix = prefix)) }) setMethod("colnames", "DataFrameList", function(x, do.NULL = TRUE, prefix = "col") { CharacterList(lapply(x, colnames, do.NULL = do.NULL, prefix = prefix)) }) setMethod("colnames", "SimpleSplitDataFrameList", function(x, do.NULL = TRUE, prefix = "col") { if (length(x)) { nms <- colnames(x[[1]], do.NULL = do.NULL, prefix = prefix) CharacterList(rep(list(nms), length(x))) } else NULL }) setMethod("colnames", "CompressedSplitDataFrameList", function(x, do.NULL = TRUE, prefix = "col") { if (length(x)) { nms <- colnames(x@unlistData, do.NULL = do.NULL, prefix = prefix) CharacterList(rep(list(nms), length(x))) } else NULL }) setMethod("dimnames", "DataFrameList", function(x) { list(rownames(x), colnames(x)) }) setReplaceMethod("rownames", "SimpleDataFrameList", function(x, value) { if (is.null(value) || is(value, "CharacterList")) { if (is.null(value)) value <- list(NULL) else if (length(x) != length(value)) stop("replacement value must be the same length as x") x@listData <- mapply(function(y, rn) {rownames(y) <- rn; y}, x@listData, value, SIMPLIFY=FALSE) } else { stop("replacement value must be NULL or a CharacterList") } x }) setReplaceMethod("rownames", "CompressedSplitDataFrameList", function(x, value) { if (is.null(value)) { rownames(x@unlistData) <- NULL } else if (is(value, "CharacterList")){ if (length(x) != length(value)) stop("replacement value must be the same length as x") rownames(x@unlistData) <- unlist(value, use.names=FALSE) } else { stop("replacement value must either be NULL or a CharacterList") } x }) setReplaceMethod("colnames", "SimpleDataFrameList", function(x, value) { if (is.null(value)) { x@listData <- lapply(x@listData, function(y) {colnames(y) <- NULL; y}) } else if (is.character(value)) { for (i in seq_len(length(x))) colnames(x@listData[[i]]) <- value } else if (is(value, "CharacterList")){ if (length(x) != length(value)) stop("replacement value must be the same length as x") for (i in seq_len(length(x))) colnames(x@listData[[i]]) <- value[[i]] } else { stop("replacement value must either be NULL or a CharacterList") } x }) setReplaceMethod("colnames", "CompressedSplitDataFrameList", function(x, value) { if (is.null(value)) { colnames(x@unlistData) <- NULL } else if (is.character(value)) { colnames(x@unlistData) <- value } else if (is(value, "CharacterList")){ if (length(x) != length(value)) stop("replacement value must be the same length as x") if (length(x) > 0) colnames(x@unlistData) <- unlist(value[[1L]]) } else { stop("replacement value must either be NULL or a CharacterList") } x }) setReplaceMethod("dimnames", "DataFrameList", function(x, value) { if (!is.list(value)) stop("replacement value must be a list") rownames(x) <- value[[1L]] colnames(x) <- value[[2L]] x }) setGeneric("columnMetadata", function(x, ...) standardGeneric("columnMetadata")) setMethod("columnMetadata", "SimpleSplitDataFrameList", function(x) { if (length(x)) mcols(x[[1]]) else NULL }) setMethod("columnMetadata", "CompressedSplitDataFrameList", function(x) { mcols(x@unlistData) }) setGeneric("columnMetadata<-", function(x, ..., value) standardGeneric("columnMetadata<-")) setReplaceMethod("columnMetadata", "SimpleSplitDataFrameList", function(x, value) { x@listData <- lapply(x@listData, function(xi) { mcols(xi) <- value xi }) x }) setReplaceMethod("columnMetadata", "CompressedSplitDataFrameList", function(x, value) { mcols(x@unlistData) <- value }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### .valid.SplitDataFrameList <- function(x) { if (length(x) && !is(x, "CompressedList")) { firstNames <- colnames(x[[1L]]) l <- as.list(x, use.names = FALSE) if (!all(sapply(l, function(df) identical(firstNames, colnames(df))))) return("column counts or names differ across elements") firstMetaData <- mcols(x[[1L]]) # could be NULL if (!all(sapply(l, function(df) { identical(firstMetaData, mcols(df)) }))) return("metadata columns must be identical across elements") } NULL } setValidity2("SplitDataFrameList", .valid.SplitDataFrameList) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor. ### DataFrameList <- function(...) { listData <- list(...) if (length(listData) == 1 && is.list(listData[[1L]]) && !is.data.frame(listData[[1L]])) listData <- listData[[1L]] if (length(listData) > 0 && !is(listData[[1L]], "DataFrame")) listData <- lapply(listData, as, "DataFrame") S4Vectors:::new_SimpleList_from_list("SimpleDataFrameList", listData) } SplitDataFrameList <- function(..., compress = TRUE, cbindArgs = FALSE) { if (!isTRUEorFALSE(compress)) stop("'compress' must be TRUE or FALSE") listData <- list(...) if (length(listData) == 1 && (is.list(listData[[1L]]) || is(listData[[1L]], "List")) && !(is.data.frame(listData[[1L]]) || is(listData[[1L]], "DataFrame"))) listData <- listData[[1L]] if (cbindArgs) { if (is.null(names(listData))) names(listData) <- paste("X", seq_len(length(listData)), sep = "") listData <- do.call(Map, c(list(DataFrame), listData)) } as(listData, if (compress) "CompressedSplitDataFrameList" else "SimpleSplitDataFrameList") } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Subsetting. ### setMethod("[", "SimpleSplitDataFrameList", function(x, i, j, ..., drop=TRUE) { if (!missing(j)) x@listData <- lapply(x@listData, function(y) y[,j,drop=FALSE]) if (!missing(i)) x <- callNextMethod(x, i) if (((nargs() - !missing(drop)) > 2) && (length(x@listData) > 0) && (ncol(x@listData[[1L]]) == 1) && (missing(drop) || drop)) { x <- as(lapply(x@listData, "[[", 1), "List") } x }) setMethod("[", "CompressedSplitDataFrameList", function(x, i, j, ..., drop=TRUE) { if (!missing(j)) x@unlistData <- x@unlistData[, j, drop=FALSE] if (!missing(i)) x <- callNextMethod(x, i) if (((nargs() - !missing(drop)) > 2) && (ncol(x@unlistData) == 1) && (missing(drop) || drop)) { x <- relist(x@unlistData[[1L]], x) } x }) setMethod("normalizeSingleBracketReplacementValue", "SplitDataFrameList", function(value, x) { value <- callNextMethod() # call default method rownames(value) <- NULL if (length(x) != 0L && ncol(x)[[1L]] == ncol(value)[[1L]]) colnames(value)[[1L]] <- colnames(x)[[1L]] value } ) setReplaceMethod("[", "SplitDataFrameList", function(x, i, j,..., value) { if (length(list(...)) > 0L) stop("invalid replacement") value <- normalizeSingleBracketReplacementValue(value, x) if (missing(j)) { if (missing(i)) ans <- callNextMethod(x=x, value=value) else ans <- callNextMethod(x=x, i=i, value=value) return(ans) } colind <- setNames(seq_along(commonColnames(x)), commonColnames(x)) if (missing(i) && is.character(j)) { colnames(value) <- j } j <- normalizeSingleBracketSubscript(j, colind, allow.append=missing(i)) if (missing(i)) { y <- value } else { y <- x[, j, drop=FALSE] if (is.list(i) || (is(i, "List") && !is(i, "Ranges"))) { y <- S4Vectors:::lsubset_List_by_List(y, i, value) } else { y[i] <- value } } if (length(y) < length(x)) { y <- rep(y, length.out=length(x)) } if (is(x, "CompressedList")) { xels <- elementLengths(x) yels <- elementLengths(y) if (any(xels != yels)) { indices <- IRanges(start(y@partitioning), width=yels) indices <- rep(indices, xels / yels) if (sum(width(indices)) != sum(xels)) { stop("some element lengths of 'x' are not multiples of the ", "corresponding element lengths of 'value'") } y@unlistData <- y@unlistData[indices, , drop=FALSE] } x@unlistData[, j] <- y@unlistData } else if (is(x, "SimpleList")) { indices <- structure(seq_len(length(x)), names = names(x)) x@listData <- lapply(indices, function(k) { z <- x@listData[[k]] z[j] <- y[[k]] z }) } else { stop(class(x), " objects not supported") } x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion ### ## Casting DataFrameList -> DataFrame implies cast to SplitDataFrameList setAs("DataFrameList", "DataFrame", function(from) { as(as(from, "SplitDataFrameList"), "DataFrame") }) setGeneric("commonColnames", function(x) standardGeneric("commonColnames")) setMethod("commonColnames", "CompressedSplitDataFrameList", function(x) colnames(unlist(x, use.names=FALSE))) setMethod("commonColnames", "SplitDataFrameList", function(x) colnames(as.list(x)[[1L]])) setAs("SplitDataFrameList", "DataFrame", function(from) { cols <- sapply(commonColnames(from), function(j) from[,j], simplify=FALSE) DataFrame(cols) } ) setAs("ANY", "SplitDataFrameList", function(from) as(from, "CompressedSplitDataFrameList")) setAs("list", "SplitDataFrameList", function(from) as(from, "SimpleSplitDataFrameList")) setAs("SimpleList", "SplitDataFrameList", function(from) as(from, "SimpleSplitDataFrameList")) setAs("DataFrame", "SplitDataFrameList", function(from) as(from, "CompressedSplitDataFrameList")) setAs("ANY", "SimpleSplitDataFrameList", function(from) { new("SimpleSplitDataFrameList", as(from, "SimpleDataFrameList")) }) setAs("ANY", "CompressedSplitDataFrameList", function(from) { coerceToCompressedList(from, "DataFrame") }) setListCoercions("DataFrame") ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Show ### setMethod("show", "SplitDataFrameList", function(object) { k <- length(object) cumsumN <- cumsum(elementLengths(object)) N <- tail(cumsumN, 1) cat(classNameForDisplay(object), " of length ", k, "\n", sep = "") if (k == 0L) { cat("<0 elements>\n") } else if ((k == 1L) || (N <= 20L)) { show(as.list(object)) } else { sketch <- function(x) c(head(x, 3), "...", tail(x, 3)) if (k >= 3 && cumsumN[3L] <= 20) showK <- 3 else if (k >= 2 && cumsumN[2L] <= 20) showK <- 2 else showK <- 1 diffK <- k - showK show(as.list(head(object, showK))) if (diffK > 0) cat("...\n<", k - showK, ifelse(diffK == 1, " more element>\n", " more elements>\n"), sep="") } }) IRanges/R/DataFrameList-utils.R0000644000175100017510000000324112607265143017272 0ustar00biocbuildbiocbuild### ========================================================================= ### DataFrameList utilities ### ------------------------------------------------------------------------- ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Combining. ### setMethod("cbind", "DataFrameList", function(..., deparse.level=1) mendoapply(cbind, ...)) setMethod("rbind", "DataFrameList", function(..., deparse.level=1) mendoapply(rbind, ...)) setMethod("stack", "DataFrameList", function(x, index.var = "name") { DataFrame(.stack.ind(x, index.var), unlist(x, use.names=FALSE), row.names = unlist(lapply(x, rownames))) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Transforming. ### setClass("SDFLWrapperForTransform", representation(delegate = "SplitDataFrameList"), contains="Vector") setMethod("colnames", "SDFLWrapperForTransform", function(x) { commonColnames(x@delegate) }) setMethod("[[", "SDFLWrapperForTransform", function (x, i, j, ...) { x@delegate[,i] }) setReplaceMethod("[[", "SDFLWrapperForTransform", function(x, i, j, ..., value) { x@delegate[,i] <- value x }) setMethod("as.env", "SDFLWrapperForTransform", function(x, ...) { env <- selectMethod(as.env, "DataTable")(x, ...) S4Vectors:::addSelfRef(x@delegate, env) }) transform.SplitDataFrameList <- function(`_data`, ...) { illConceivedWrapper <- new("SDFLWrapperForTransform", delegate=`_data`) S4Vectors:::transform.DataTable(illConceivedWrapper, ...)@delegate } setMethod("transform", "SplitDataFrameList", transform.SplitDataFrameList) IRanges/R/GappedRanges-class.R0000644000175100017510000001354012607265143017122 0ustar00biocbuildbiocbuild### ========================================================================= ### GappedRanges objects ### ------------------------------------------------------------------------- ### ### A GappedRanges object is a vector of gapped ranges. ### A gapped range is conceptually the union of 1 or more non-overlapping ### ranges ordered from left to right. ### More precisely, a gapped range can be represented by a normal IRanges ### object of length >= 1. In particular normality here ensures that the ### individual ranges are non-empty and are separated by non-empty gaps. ### The start of a gapped range is the start of its first range. ### The end of a gapped range is the end of its last range. ### If we ignore the gaps, then a GappedRanges object can be seen as a Ranges ### object. ### setClass("GappedRanges", contains="Ranges", representation(cnirl="CompressedNormalIRangesList"), prototype(elementType="NormalIRanges") ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor-like methods. ### setMethod("length", "GappedRanges", function(x) length(x@cnirl)) setMethod("start", "GappedRanges", function(x, ...) CompressedNormalIRangesList.min(x@cnirl, FALSE) ) setMethod("end", "GappedRanges", function(x, ...) CompressedNormalIRangesList.max(x@cnirl, FALSE) ) setGeneric("ngap", function(x) standardGeneric("ngap")) setMethod("ngap", "GappedRanges", function(x) {elementLengths(x) - 1L}) setMethod("names", "GappedRanges", function(x) names(x@cnirl)) setReplaceMethod("names", "GappedRanges", function(x, value) { names(x@cnirl) <- value x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### .valid.GappedRanges <- function(x) .Call2("valid_GappedRanges", x, 0L, PACKAGE="IRanges") setValidity2("GappedRanges", .valid.GappedRanges) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### setAs("CompressedNormalIRangesList", "GappedRanges", function(from) new("GappedRanges", cnirl=from) ) setAs("CompressedIRangesList", "GappedRanges", function(from) as(as(from, "CompressedNormalIRangesList"), "GappedRanges") ) setAs("GappedRanges", "CompressedNormalIRangesList", function(from) from@cnirl) setAs("GappedRanges", "NormalIRangesList", function(from) from@cnirl) setAs("GappedRanges", "CompressedIRangesList", function(from) from@cnirl) setAs("GappedRanges", "IRangesList", function(from) from@cnirl) setAs("GappedRanges", "RangesList", function(from) from@cnirl) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "show" method. ### ### S3/S4 combo for as.data.frame.GappedRanges as.data.frame.GappedRanges <- function(x, row.names=NULL, optional=FALSE, ...) { ans <- as.data.frame.Ranges(unname(x), row.names, optional, ...) ans$ngap <- ngap(x) ans$names <- names(x) ans } setMethod("as.data.frame", "GappedRanges", as.data.frame.GappedRanges) setMethod("show", "GappedRanges", function(object) { lo <- length(object) cat(class(object), " of length ", lo, "\n", sep="") if (lo == 0L) { return(NULL) } else if (lo < 20L) { showme <- as.data.frame(object, row.names=paste("[", seq_len(lo), "]", sep="")) } else { sketch <- function(x) c(head(x, n=9L), "...", tail(x, n=9L)) showme <- data.frame(start=sketch(start(object)), end=sketch(end(object)), width=sketch(width(object)), ngap=sketch(ngap(object)), row.names=c(paste("[", 1:9, "]", sep=""), "...", paste("[", (lo-8L):lo, "]", sep="")), check.rows=TRUE, check.names=FALSE, stringsAsFactors=FALSE) NAMES <- names(object) if (!is.null(NAMES)) showme$names <- sketch(NAMES) } show(showme) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Subsetting. ### ### WARNING: We override the *semantic* of the "[[" method for Ranges objects. setMethod("getListElement", "GappedRanges", function(x, i, exact=TRUE) { i <- normalizeDoubleBracketSubscript(i, x, exact=exact, error.if.nomatch=TRUE) newNormalIRangesFromIRanges(x@cnirl[[i]], check=FALSE) } ) ### WARNING: We override the *semantic* of the "elementLengths" method for ### Ranges objects. setMethod("elementLengths", "GappedRanges", function(x) elementLengths(x@cnirl) ) setMethod("extractROWS", "GappedRanges", function(x, i) { i <- normalizeSingleBracketSubscript(i, x, as.NSBS=TRUE) x@cnirl <- extractROWS(x@cnirl, i) x@elementMetadata <- extractROWS(x@elementMetadata, i) x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Combining. ### setMethod("c", "GappedRanges", function(x, ..., recursive=FALSE) { if (!identical(recursive, FALSE)) stop("\"c\" method for GappedRanges objects ", "does not support the 'recursive' argument") if (missing(x)) { args <- unname(list(...)) x <- args[[1L]] } else { args <- unname(list(x, ...)) } if (length(args) == 1L) return(x) arg_is_null <- sapply(args, is.null) if (any(arg_is_null)) args[arg_is_null] <- NULL # remove NULL elements by setting them to NULL! if (!all(sapply(args, is, class(x)))) stop("all arguments in '...' must be ", class(x), " objects (or NULLs)") x@cnirl <- do.call(c, lapply(args, function(xx) xx@cnirl)) x } ) IRanges/R/Grouping-class.R0000644000175100017510000007541612607265143016366 0ustar00biocbuildbiocbuild### ========================================================================= ### Grouping objects ### ------------------------------------------------------------------------- ### ### We call "grouping" an arbitrary mapping from a collection of NO objects ### to a collection of NG groups, or, more formally, a bipartite graph ### between integer sets [1, NO] and [1, NG]. Objects mapped to a given group ### are said to belong to, or to be assigned to, or to be in that group. ### Additionally, the objects in each group are ordered. So for example ### the 2 following groupings are considered different: ### ### Grouping 1: NG = 3, NO = 5 ### group objects ### 1 : 4, 2 ### 2 : ### 3 : 4 ### ### Grouping 2: NG = 3, NO = 5 ### group objects ### 1 : 2, 4 ### 2 : ### 3 : 4 ### ### There are no restriction on the mapping e.g. any object can be mapped ### to 0, 1, or more groups, and can be mapped twice to the same group. Also ### some or all the groups can be empty. ### ### The Grouping class is a virtual class that formalizes the most general ### kind of grouping. More specific groupings (e.g. many-to-one mappings) ### are formalized via specific Grouping subclasses. setClass("Grouping", contains="IntegerList", representation("VIRTUAL")) setGeneric("nobj", function(x) standardGeneric("nobj")) setGeneric("grouplength", signature="x", function(x, i=NULL) standardGeneric("grouplength") ) setMethod("grouplength", "Grouping", function(x, i=NULL) { if (is.null(i)) i <- seq_len(length(x)) sapply(i, function(ii) length(x[[i]])) } ) setMethod("show", "Grouping", function(object) { NG <- length(object) NO <- nobj(object) cat(class(object), " with ", NG, ifelse(NG == 1, " group ", " groups "), "and ", NO, ifelse(NO == 1, " object\n", " objects\n"), sep="") if (NG == 0L) return(invisible(NULL)) empty_groups <- which(grouplength(object) == 0L) cat("Nb of empty groups: ", length(empty_groups), " (", 100.00 * length(empty_groups) / NG, "%)\n", sep="") } ) ### ------------------------------------------------------------------------- ### ManyToOneGrouping objects ### ------------------------- ### A ManyToOneGrouping object represents a grouping where every object in ### the collection is mapped to one group and only one. setClass("ManyToOneGrouping", contains="Grouping", representation("VIRTUAL")) setGeneric("members", signature="x", function(x, i) standardGeneric("members") ) setMethod("members", "ManyToOneGrouping", function(x, i) { if (!is.numeric(i)) stop(wmsg("subscript 'i' must be a vector of integers")) if (!is.integer(i)) i <- as.integer(i) sort(unlist(sapply(i, function(ii) x[[ii]]))) } ) setGeneric("vmembers", signature="x", function(x, L) standardGeneric("vmembers") ) setMethod("vmembers", "ManyToOneGrouping", function(x, L) { if (!is.list(L)) stop(wmsg("'L' must be a list of integer vectors")) lapply(L, function(i) members(x, i)) } ) setGeneric("togroup", signature="x", function(x, j=NULL) standardGeneric("togroup") ) ### The default method works on any object 'x' for which 'elementLengths(x)' ### works (e.g. Partitioning, List, list). Not very efficient. setMethod("togroup", "ANY", function(x, j=NULL) { elt_len <- elementLengths(x) to_group <- rep.int(seq_len(length(elt_len)), elt_len) if (is.null(j)) return(to_group) if (!is.numeric(j)) stop(wmsg("subscript 'j' must be a vector of integers or NULL")) if (!is.integer(j)) j <- as.integer(j) bound <- length(to_group) if (S4Vectors:::anyMissingOrOutside(j, -bound, bound)) stop(wmsg("subscript 'j' contains NAs or out of bounds indices")) to_group[j] } ) setGeneric("togrouplength", signature="x", function(x, j=NULL) standardGeneric("togrouplength") ) setMethod("togrouplength", "ManyToOneGrouping", function(x, j=NULL) grouplength(x, togroup(x, j)) ) ### ------------------------------------------------------------------------- ### BiIndexGrouping objects ### ----------------------- #setClass("BiIndexGrouping", # contains="ManyToOneGrouping", # representation( # group2object="list", # object2group="integer" # ) #) #setMethod("length", "BiIndexGrouping", function(x) length(x@group2object)) #setMethod("nobj", "BiIndexGrouping", function(x) length(x@object2group)) ### ------------------------------------------------------------------------- ### H2LGrouping and Dups objects ### ---------------------------- ### ### High-to-Low Index ManyToOneGrouping objects. ### setClass("H2LGrouping", contains="ManyToOneGrouping", representation( high2low="integer", low2high="list" ) ) ### For storing the grouping implicitly defined by the "duplicated" ### relationship between elements of an arbitrary vector. setClass("Dups", contains="H2LGrouping") ### Two additional accessors for H2LGrouping objects. setGeneric("high2low", function(x) standardGeneric("high2low")) setMethod("high2low", "H2LGrouping", function(x) x@high2low) setGeneric("low2high", function(x) standardGeneric("low2high")) setMethod("low2high", "H2LGrouping", function(x) x@low2high) ### 'length(x)' and 'nobj(x)' are the same. setMethod("length", "H2LGrouping", function(x) length(x@low2high)) setMethod("nobj", "H2LGrouping", function(x) length(x@high2low)) setMethod("getListElement", "H2LGrouping", function(x, i, exact=TRUE) { i <- normalizeDoubleBracketSubscript(i, x, exact=exact, error.if.nomatch=TRUE) if (is.na(x@high2low[i])) c(i, x@low2high[[i]]) else integer() } ) ### Should be more efficient than the default method for ManyToOneGrouping ### objects. setMethod("grouplength", "H2LGrouping", function(x, i=NULL) { group_length <- elementLengths(x@low2high) + 1L group_length[!is.na(x@high2low)] <- 0L if (is.null(i)) return(group_length) if (!is.numeric(i)) stop(wmsg("subscript 'i' must be a vector of integers or NULL")) if (!is.integer(i)) i <- as.integer(i) bound <- length(group_length) if (S4Vectors:::anyMissingOrOutside(i, -bound, bound)) stop(wmsg("subscript 'i' contains NAs or out of bounds indices")) group_length[i] } ) setMethod("members", "H2LGrouping", function(x, i) { if (!is.numeric(i)) stop(wmsg("subscript 'i' must be a vector of integers")) if (!is.integer(i)) i <- as.integer(i) ## NAs and "subscript out of bounds" are checked at the C level .Call2("H2LGrouping_members", x, i, PACKAGE="IRanges") } ) setMethod("vmembers", "H2LGrouping", function(x, L) { if (!is.list(L)) stop(wmsg("'L' must be a list of integer vectors")) .Call2("H2LGrouping_vmembers", x, L, PACKAGE="IRanges") } ) setMethod("togroup", "H2LGrouping", function(x, j=NULL) { to_group <- x@high2low to_group[is.na(to_group)] <- which(is.na(to_group)) if (is.null(j)) return(to_group) if (!is.numeric(j)) stop(wmsg("subscript 'j' must be a vector of integers or NULL")) if (!is.integer(j)) j <- as.integer(j) bound <- length(to_group) if (S4Vectors:::anyMissingOrOutside(j, -bound, bound)) stop(wmsg("subscript 'j' contains NAs or out of bounds indices")) to_group[j] } ) ### The default method should be as good (if not better) as this. #setMethod("togrouplength", "H2LGrouping", # function(x) # { # ans <- rep.int(1L, length(x)) # mapped_lows <- setdiff(unique(x@high2low), NA) # for (low in mapped_lows) { # ii <- as.integer(c(low, x@low2high[[low]])) # ans[ii] <- length(ii) # } # ans # } #) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### More operations on H2LGrouping objects. These operations are NOT part of ### the core Grouping API. ### ### The rank of group G_i is the number of non-empty groups that are before ### G_i plus one. Or, equivalently, it's the number of non-empty groups with ### an index <= i. setGeneric("grouprank", signature="x", function(x, i=NULL) standardGeneric("grouprank") ) setMethod("grouprank", "H2LGrouping", function(x, i=NULL) { ans <- cumsum(is.na(high2low(x))) if (!is.null(i)) ans <- ans[i] return(ans) } ) ### togrouprank() returns the mapping from objects to group ranks. ### An important property of togrouprank() is that: ### togrouprank(x, neg_idx) ### and ### seq_len(length(neg_idx)) ### are identical, where 'neg_idx' is the vector of the indices of ### the non-empty groups i.e. ### neg_idx <- which(grouplength(x) != 0L) setGeneric("togrouprank", signature="x", function(x, j=NULL) standardGeneric("togrouprank") ) setMethod("togrouprank", "H2LGrouping", function(x, j=NULL) { to_group <- togroup(x) group_rank <- grouprank(x) ans <- group_rank[to_group] if (!is.null(j)) ans <- ans[j] return(ans) } ) setReplaceMethod("length", "H2LGrouping", function(x, value) { if (!isSingleNumber(value)) stop(wmsg("length must be a single integer")) if (!is.integer(value)) value <- as.integer(value) if (value < 0L) stop(wmsg("length cannot be negative")) if (value > length(x)) stop(wmsg("cannot make a ", class(x), " instance longer")) length(x@high2low) <- value x@low2high <- S4Vectors:::reverseSelfmatchMapping(x@high2low) x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### .valid.H2LGrouping <- function(x) { if (!is.integer(x@high2low)) return("the 'high2low' slot must contain an integer vector") if (!all(x@high2low >= 1L, na.rm=TRUE)) return("the 'high2low' slot must contain integer values >= 1") if (!all(x@high2low < seq_along(x@high2low), na.rm=TRUE)) { problem <- c("when mapped, elements in the 'high2low' slot must be mapped ", "to elements at a lower position") return(paste(problem, collapse="")) } if (!all(is.na(x@high2low[x@high2low]))) { problem <- c("when mapped, elements in the 'high2low' slot must be mapped ", "to unmapped elements") return(paste(problem, collapse="")) } if (!is.list(x@low2high)) return("the 'low2high' slot must contain a list") if (length(x@high2low) != length(x@low2high)) return("the 'high2low' and 'low2high' slots must have the same length") if (!identical(S4Vectors:::reverseSelfmatchMapping(x@high2low), x@low2high)) { problem <- c("the 'low2high' slot must contain the reverse mapping ", "of the 'high2low' slot") return(paste(problem, collapse="")) } NULL } setValidity("H2LGrouping", function(object) { problems <- .valid.H2LGrouping(object) if (is.null(problems)) TRUE else problems } ) ### For Dups objects only. .duplicated.Dups <- function(x, incomparables=FALSE) { if (!identical(incomparables, FALSE)) stop(wmsg("\"duplicated\" method for Dups objects ", "only accepts 'incomparables=FALSE'")) !is.na(high2low(x)) } ### S3/S4 combo for duplicated.Dups duplicated.Dups <- function(x, incomparables=FALSE, ...) .duplicated.Dups(x, incomparables=incomparables, ...) setMethod("duplicated", "Dups", duplicated.Dups) ### For Dups objects only. setMethod("show", "Dups", function(object) { percentage <- 100.00 * sum(duplicated(object)) / length(object) cat(class(object), " of length ", length(object), " (", percentage, "% of duplicates)\n", sep="") } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructors. ### .newH2LGrouping <- function(Class, high2low) { if (!is.numeric(high2low)) stop(wmsg("'high2low' must be a vector of integers")) if (!is.integer(high2low)) high2low <- as.integer(high2low) new2(Class, high2low=high2low, low2high=S4Vectors:::reverseSelfmatchMapping(high2low), check=FALSE) } H2LGrouping <- function(high2low=integer()) .newH2LGrouping("H2LGrouping", high2low) Dups <- function(high2low=integer()) .newH2LGrouping("Dups", high2low) ### If 'x' is a vector-like object for which "[" and "==" are defined, then ### 'high2low(x)' can be *conceptually* defined with: ### ### high2low <- function(x) ### sapply(seq_len(length(x)), ### function(i) match(x[i], x[seq_len(i-1L)])) ### ### Of course this is *very* inefficient (quadratic in time), its only value ### being to describe the semantic: ### ### > x <- as.integer(c(2,77,4,4,7,2,8,8,4,99)) ### > high2low(x) ### [1] NA NA NA 3 NA 1 NA 7 3 NA ### > bigx <- rep.int(x, 10000) ### > system.time(high2low(bigx)) ### user system elapsed ### 284.805 9.792 294.888 ### setMethod("high2low", "vector", function(x) { ## Author: Harris A. Jaffee ans <- match(x, x) ans[ans == seq_len(length(x))] <- NA_integer_ return(ans) } ) ### The "high2low" method for Vector objects uses an implementation that ### is O(n*log(n)) in time but it requires that "order" be defined for 'x' ### (in addition to "[" and "=="). setMethod("high2low", "Vector", function(x) { ## The 2 lines below are equivalent but much faster than ## ans <- rep.int(NA_integer_, length(x)) ans <- integer(length(x)) ans[] <- NA_integer_ if (length(x) <= 1L) return(ans) x_order <- order(x) low <- x_order[1L] for (i in 2:length(x)) { high <- x_order[i] if (x[high] == x[low]) ans[high] <- low else low <- high } return(ans) } ) ### ------------------------------------------------------------------------- ### Partitioning objects ### -------------------- ### ### A Partitioning container represents a block-grouping i.e. a grouping ### where each group contains objects that are neighbors in the original ### collection of objects. More formally, a grouping 'x' is a block-grouping ### iff 'togroup(x)' is sorted in increasing order (not necessarily strictly ### increasing). In addition, a Partitioning object can be seen (and ### manipulated) as a Ranges object where all the ranges are adjacent ### starting at 1 (i.e. it covers an integer interval starting at 1 ### and with no overlap between the ranges). Therefore the "start/end/width" ### API is implemented on Partitioning objects (in addition to the Grouping ### and ManyToOneGrouping APIs). ### ### The Partitioning class is virtual with 3 concrete subclasses: ### PartitioningByEnd and PartitioningByWidth and PartitioningMap. ### Note that we put Ranges before ManyToOneGrouping in order to have ### Partitioning objects inherit the "show" method for Ranges objects. setClass("Partitioning", contains=c("Ranges", "ManyToOneGrouping"), representation( "VIRTUAL", NAMES="characterORNULL" # R doesn't like @names !! ), prototype( NAMES=NULL ) ) ### The default methods below assume that the "length + start/end/width" API ### is already implemented. setMethod("getListElement", "Partitioning", function(x, i, exact=TRUE) { i <- normalizeDoubleBracketSubscript(i, x, exact=exact, error.if.nomatch=TRUE) ## The purpose of the code below is to extract 'start(x)[i] - 1' ## (stored in 'ans_shift') and 'width(x)[i]' (stored in 'ans_length') ## in the fastest possible way. Looks like a convoluted way to ## extract those 2 values but it is actually 1000x faster than the ## naive way. ans_shift <- 0L ans_length <- end(x)[i] if (i >= 2L) { ans_shift <- end(x)[i - 1L] ans_length <- ans_length - ans_shift } seq_len(ans_length) + ans_shift } ) ### Should be more efficient than the default method for ManyToOneGrouping ### objects. setMethod("grouplength", "Partitioning", function(x, i=NULL) { x_width <- width(x) if (is.null(i)) return(x_width) if (!is.numeric(i)) stop(wmsg("subscript 'i' must be a vector of integers or NULL")) if (!is.integer(i)) i <- as.integer(i) bound <- length(x_width) if (S4Vectors:::anyMissingOrOutside(i, -bound, bound)) stop(wmsg("subscript 'i' contains NAs or out of bounds indices")) x_width[i] } ) setMethod("names", "Partitioning", function(x) x@NAMES) setReplaceMethod("names", "Partitioning", set_IRanges_names) .valid.Partitioning <- function(x) { if (is.null(names(x))) return(NULL) if (!is.character(names(x))) return("the names must be a character vector or NULL") if (length(names(x)) != length(x)) return("number of names and number of elements differ") NULL } setValidity2("Partitioning", .valid.Partitioning) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### PartitioningByEnd uses a compact internal representation that allows ### fast mapping from groups to objects. However, it is not efficient for ### mapping from objects to groups. ### setClass("PartitioningByEnd", contains="Partitioning", representation( end="integer" ), prototype( end=integer() ) ) setMethod("end", "PartitioningByEnd", function(x) x@end) setMethod("length", "PartitioningByEnd", function(x) length(end(x))) setMethod("nobj", "PartitioningByEnd", function(x) { x_end <- end(x) if (length(x_end) == 0L) return(0L) x_end[length(x_end)] } ) setMethod("start", "PartitioningByEnd", function(x) { x_end <- end(x) if (length(x_end) == 0L) return(integer()) c(1L, x_end[-length(x_end)] + 1L) } ) setMethod("width", "PartitioningByEnd", function(x) S4Vectors:::diffWithInitialZero(end(x)) ) .valid.PartitioningByEnd <- function(x) { if (!is.integer(end(x))) return("the ends must be integers") if (length(x) == 0L) return(NULL) if (S4Vectors:::anyMissing(end(x))) return("the ends cannot be NAs") if (S4Vectors:::isNotSorted(end(x))) return("the ends must be sorted") if (end(x)[1L] < 0L) return("the ends cannot be negative") if (!is.null(names(end(x)))) return("the ends should not be named") NULL } setValidity2("PartitioningByEnd", .valid.PartitioningByEnd) .numeric2end <- function(x=integer(0), NG=NULL) { if (!is.integer(x)) x <- as.integer(x) if (S4Vectors:::anyMissingOrOutside(x, 0L)) stop(wmsg("when 'x' is an integer vector, ", "it cannot contain NAs or negative values")) if (S4Vectors:::isNotSorted(x)) stop(wmsg("when 'x' is an integer vector, ", "it must be sorted")) if (is.null(NG)) return(x) ## When 'NG' (number of groups) is supplied, then 'x' is considered ## to represent the group assignment of a collection of 'length(x)' ## objects. Therefore the values in 'x' must be >= 1 and <= 'NG'. ## ADDITIONALLY, 'x' must be *sorted* (not strictly) so it can be ## reconstructed from the object returned by PartitioningByEnd() ## by doing togroup() on that object. if (!isSingleNumber(NG)) stop(wmsg("'NG' must be either NULL or a single integer")) if (!is.integer(NG)) NG <- as.integer(NG) NO <- length(x) # nb of objects if (NG == 0L) { if (NO != 0L) stop(wmsg("when 'NG' is 0, 'x' must be of length 0")) } else { ## 'x' is expected to be non-decreasing and with values >= 1 ## and <= 'NG'. x <- cumsum(tabulate(x, nbins=NG)) ## 'x[NG]' is guaranteed to be <= 'NO'. if (x[NG] != NO) stop(wmsg("when 'NG' is supplied, values in 'x' must ", "be >= 1 and <= 'NG'")) } x } .prepare_Partitioning_names <- function(names, ans_len, NG, x_names) { if (!is.null(names)) { if (!is.character(names) || length(names) != ans_len) stop(wmsg("'names' must be either NULL or a character vector ", "of length 'NG' (if supplied) or 'length(x)' ", "(if 'NG' is not supplied)")) return(names) } if (is.null(NG)) return(x_names) # should be of length 'ans_len' NULL } PartitioningByEnd <- function(x=integer(0), NG=NULL, names=NULL) { if (is(x, "List") || is.list(x)) { if (!is.null(NG)) warning(wmsg("'NG' argument is ignored when 'x' ", "is a list-like object")) if (is(x, "CompressedList")) { ## Behaves like a getter for the 'partitioning' slot. ans <- x@partitioning if (!is.null(names)) names(ans) <- names return(ans) } if (is(x, "PartitioningByEnd")) { if (!is.null(names)) names(x) <- names return(x) } x_names <- names(x) ans_end <- cumsum(elementLengths(x)) } else { if (!is.numeric(x)) stop(wmsg("'x' must be either a list-like object or ", "a sorted vector of non-NA non-negative integers")) x_names <- names(x) ans_end <- .numeric2end(x, NG) } ans_names <- .prepare_Partitioning_names(names, length(ans_end), NG, x_names) new2("PartitioningByEnd", end=unname(ans_end), NAMES=ans_names, check=FALSE) } setAs("Ranges", "PartitioningByEnd", function(from) { ans <- PartitioningByEnd(end(from), names(from)) if (!identical(start(ans), start(from))) stop(wmsg("the Ranges object to coerce does not represent ", "a partitioning")) ans } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### PartitioningByWidth uses a compact internal representation too. Storing ### the widths instead of the ends would allow the total number of objects ### (nobj(x)) to be greater than 2^31-1 but note that some methods will break ### when this happens, e.g. nobj, end, etc... ### setClass("PartitioningByWidth", contains="Partitioning", representation( width="integer" ), prototype( width=integer() ) ) setMethod("width", "PartitioningByWidth", function(x) x@width) setMethod("length", "PartitioningByWidth", function(x) length(width(x))) setMethod("end", "PartitioningByWidth", function(x) cumsum(width(x))) setMethod("nobj", "PartitioningByWidth", function(x) { x_end <- end(x) if (length(x_end) == 0L) return(0L) x_end[length(x_end)] } ) setMethod("start", "PartitioningByWidth", function(x) { x_width <- width(x) if (length(x_width) == 0L) return(integer()) c(1L, cumsum(x_width[-length(x_width)]) + 1L) } ) .valid.PartitioningByWidth <- function(x) { if (!is.integer(width(x))) return("the widths must be integers") if (length(x) == 0L) return(NULL) if (S4Vectors:::anyMissingOrOutside(width(x), 0L)) return("the widths cannot be NAs or negative") if (!is.null(names(width(x)))) return("the widths should not be named") NULL } setValidity2("PartitioningByWidth", .valid.PartitioningByWidth) .numeric2width <- function(x=integer(0), NG=NULL) { if (!is.integer(x)) x <- as.integer(x) if (S4Vectors:::anyMissingOrOutside(x, 0L)) stop(wmsg("when 'x' is an integer vector, ", "it cannot contain NAs or negative values")) if (is.null(NG)) return(x) ## When 'NG' (number of groups) is supplied, then 'x' is considered ## to represent the group assignment of a collection of 'length(x)' ## objects. Therefore the values in 'x' must be >= 1 and <= 'NG'. ## ADDITIONALLY, 'x' must be *sorted* (not strictly) so it can be ## reconstructed from the object returned by PartitioningByWidth() ## by doing togroup() on that object. if (S4Vectors:::isNotSorted(x)) stop(wmsg("when 'x' is an integer vector, it must be sorted")) if (!isSingleNumber(NG)) stop(wmsg("'NG' must be either NULL or a single integer")) if (!is.integer(NG)) NG <- as.integer(NG) NO <- length(x) # nb of objects if (NG == 0L) { if (NO != 0L) stop(wmsg("when 'NG' is 0, 'x' must be of length 0")) } else { ## 'x' is expected to be non-decreasing and with values >= 1 ## and <= 'NG'. x <- tabulate(x, nbins=NG) ## 'sum(x)' is guaranteed to be <= 'NO'. if (sum(x) != NO) stop(wmsg("when 'NG' is supplied, values in 'x' must ", "be >= 1 and <= 'NG'")) } x } PartitioningByWidth <- function(x=integer(0), NG=NULL, names=NULL) { if (is(x, "List") || is.list(x)) { if (!is.null(NG)) warning(wmsg("'NG' argument is ignored when 'x' ", "is a list-like object")) if (is(x, "PartitioningByWidth")) { if (!is.null(names)) names(x) <- names return(x) } x_names <- names(x) ans_width <- elementLengths(x) } else { if (!is.numeric(x)) stop(wmsg("'x' must be either a list-like object or ", "a vector of non-NA non-negative integers")) x_names <- names(x) ans_width <- .numeric2width(x, NG) } ans_names <- .prepare_Partitioning_names(names, length(ans_width), NG, x_names) new2("PartitioningByWidth", width=unname(ans_width), NAMES=ans_names, check=FALSE) } setAs("Ranges", "PartitioningByWidth", function(from) { ans <- PartitioningByWidth(width(from), names(from)) if (!identical(start(ans), start(from))) stop(wmsg("the Ranges object to coerce does not represent ", "a partitioning")) ans } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### PartitioningMap contains PartitioningByEnd and one additional slot, ### 'mapOrder', to specify a different order. This object is used by the ### pack() function in GenomicFiles and is put in @partitioning of a ### GRangesList of pack()ed ranges. 'mapOrder' records the order of the ### unpacked() ranges. ### setClass("PartitioningMap", contains="PartitioningByEnd", representation( mapOrder="integer" ), prototype( mapOrder=integer() ) ) setGeneric("mapOrder", function(x) standardGeneric("mapOrder")) setMethod("mapOrder", "PartitioningMap", function(x) x@mapOrder) .valid.PartitioningMap <- function(x) { if (length(x) == 0L) return(NULL) if (S4Vectors:::anyMissing(mapOrder(x))) return("mapOrder cannot contain NA values") if (any(mapOrder(x) < 0L)) return("mapOrder values cannot be negative") if (!is.null(names(mapOrder(x)))) return("the mapOrder should not be named") if (length(maporder <- mapOrder(x))) { maxorder <- max(maporder) if (max(maporder) > max(end(x))) return("max mapOrder value must be == max(end(object))") } NULL } setValidity2("PartitioningMap", .valid.PartitioningMap) PartitioningMap <- function(x=integer(), mapOrder=integer(), ...) new("PartitioningMap", PartitioningByEnd(x=x), mapOrder=mapOrder, ...) setAs("PartitioningByEnd", "PartitioningMap", function(from) new("PartitioningMap", from, mapOrder=numeric()) ) setMethod("show", "PartitioningMap", function(object) { cat(class(object), " of length ", length(object), "\n") cat("mapOrder: ", mapOrder(object), "\n") print(PartitioningByEnd(object)) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### findOverlaps() ### ### A simple findOverlaps method that doesn't use IntervalTree but works only ### on a subject with *adjacent* ranges sorted non-decreasingly. ### Can be 30% faster or more than the real findOverlaps() (IntervalTree-based) ### when 'query' is such that 'start(query)' and 'end(query)' are also sorted ### non-decreasingly (which is the case if for example 'query' is a ### Partitioning object). ### TODO: Add a "findOverlaps" method for Partitioning,Partitioning in the ### findOverlaps-methods.R file that calls this. findOverlaps_Ranges_Partitioning <- function(query, subject, hit.empty.query.ranges=FALSE, hit.empty.subject.ranges=FALSE) { if (!is(query, "Ranges")) stop(wmsg("'query' must be a Ranges object")) if (!is(subject, "Partitioning")) stop(wmsg("'subject' must be a Partitioning object")) if (!isTRUEorFALSE(hit.empty.query.ranges) || !isTRUEorFALSE(hit.empty.subject.ranges)) stop(wmsg("'hit.empty.query.ranges' and 'hit.empty.subject.ranges' ", "must be TRUE or FALSE")) q_len <- length(query) q_start <- start(query) q_end <- end(query) s_len <- length(subject) s_end <- end(subject) if (!hit.empty.query.ranges) { q_idx <- which(width(query) != 0L) q_start <- q_start[q_idx] q_end <- q_end[q_idx] } if (!hit.empty.subject.ranges) { s_idx <- which(width(subject) != 0L) s_end <- s_end[s_idx] } vec <- c(0L, s_end) + 0.5 q_start2subject <- findInterval(q_start, vec) q_end2subject <- findInterval(q_end, vec) q_hits <- rep.int(seq_len(length(q_start)), q_end2subject - q_start2subject + 1L) s_hits <- S4Vectors:::mseq(q_start2subject, q_end2subject) ## If 'query' is a Partitioning object, all hits are guaranteed to be ## valid. if (!is(query, "Partitioning")) { ## Remove invalid hits. is_valid <- 1L <= s_hits & s_hits <= length(s_end) q_hits <- q_hits[is_valid] s_hits <- s_hits[is_valid] } ## Remap hits to original query/subject. if (!hit.empty.query.ranges) q_hits <- q_idx[q_hits] if (!hit.empty.subject.ranges) s_hits <- s_idx[s_hits] ## Make and return Hits object. Hits(q_hits, s_hits, q_len, s_len) } IRanges/R/Hits-class-leftovers.R0000644000175100017510000000461012607265143017476 0ustar00biocbuildbiocbuild### ========================================================================= ### IMPORTANT NOTE - 4/29/2014 ### Most of the stuff that used to be in the IRanges/R/Hits-class.R file was ### moved to the S4Vectors package (to R/Hits-class.R). ### The stuff that could not be moved there was *temporarily* kept here in ### Hits-class-leftovers.R but will need to find a new home (in S4Vectors ### or in IRanges). ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion ### setAs("Hits", "DataFrame", function(from) { DataFrame(as.matrix(from), if (!is.null(mcols(from))) mcols(from) else new("DataFrame", nrows = length(from))) }) ### S3/S4 combo for as.data.frame.Hits as.data.frame.Hits <- function(x, row.names=NULL, optional=FALSE, ...) { if (!(is.null(row.names) || is.character(row.names))) stop("'row.names' must be NULL or a character vector") if (!identical(optional, FALSE) || length(list(...))) warning("'optional' and arguments in '...' are ignored") as.data.frame(as(x, "DataFrame"), row.names = row.names) } setMethod("as.data.frame", "Hits", as.data.frame.Hits) ### Turn Hits object 'from' into a PartitioningByEnd object that describes ### the grouping of hits by query. .from_Hits_to_PartitioningByEnd <- function(from) PartitioningByEnd(queryHits(from), NG=queryLength(from)) setAs("Hits", "PartitioningByEnd", .from_Hits_to_PartitioningByEnd) setAs("Hits", "Partitioning", .from_Hits_to_PartitioningByEnd) setAs("Hits", "Ranges", .from_Hits_to_PartitioningByEnd) setAs("Hits", "IRanges", function(from) as(.from_Hits_to_PartitioningByEnd(from), "IRanges") ) ### Turn Hits object 'from' into a CompressedIntegerList object with one list ### element per element in the original query. .from_Hits_to_CompressedIntegerList <- function(from) { ans_partitioning <- .from_Hits_to_PartitioningByEnd(from) relist(subjectHits(from), ans_partitioning) } setAs("Hits", "CompressedIntegerList", .from_Hits_to_CompressedIntegerList) setAs("Hits", "IntegerList", .from_Hits_to_CompressedIntegerList) setAs("Hits", "List", .from_Hits_to_CompressedIntegerList) ### S3/S4 combo for as.list.Hits .as.list.Hits <- function(x) as.list(.from_Hits_to_CompressedIntegerList(x)) as.list.Hits <- function(x, ...) .as.list.Hits(x, ...) setMethod("as.list", "Hits", .as.list.Hits) setAs("Hits", "list", function(from) as.list(from)) IRanges/R/HitsList-class.R0000644000175100017510000001033512607265143016324 0ustar00biocbuildbiocbuild### ========================================================================= ### HitsList objects ### ------------------------------------------------------------------------- ### FIXME: Rename this class SimpleHitsList and make HitsList a virtual ### class that SimpleHitsList and CompressedHitsList extend directly. setClass("HitsList", contains="SimpleList", representation( subjectOffsets="integer" ), prototype(elementType="Hits") ) setClass("CompressedHitsList", prototype = prototype(elementType = "Hits", unlistData = new("Hits")), contains="CompressedList") ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessors ### setMethod("space", "HitsList", function(x) { space <- names(x) if (!is.null(space)) space <- rep.int(space, sapply(as.list(x, use.names = FALSE), length)) space }) setMethod("subjectHits", "HitsList", function(x) { as.matrix(x)[,2L,drop=TRUE] }) setMethod("subjectHits", "CompressedHitsList", function(x) subjectHits(x@unlistData)) setMethod("queryHits", "HitsList", function(x) { as.matrix(x)[,1L,drop=TRUE] }) setMethod("queryHits", "CompressedHitsList", function(x) queryHits(x@unlistData)) setMethod("queryLength", "CompressedHitsList", function(x) queryLength(x@unlistData)) setMethod("subjectLength", "CompressedHitsList", function(x) subjectLength(x@unlistData)) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor ### HitsList <- function(list_of_hits, subject) { subjectOffsets <- c(0L, head(cumsum(sapply(subject, length)), -1)) subjectToQuery <- seq_along(list_of_hits) if (!is.null(names(list_of_hits)) && !is.null(names(subject))) subjectToQuery <- match(names(list_of_hits), names(subject)) subjectOffsets <- subjectOffsets[subjectToQuery] S4Vectors:::new_SimpleList_from_list("HitsList", list_of_hits, subjectOffsets = subjectOffsets) } CompressedHitsList <- function(hits, query) { if (!(is(query, "CompressedIRangesList"))) stop("'query' must be a 'CompressedIRangesList' object") if (!is(hits, "Hits")) stop("'hits' must be a 'Hits' object") qspace <- space(query) hspace <- as.integer(qspace[queryHits(hits)]) partitioning <- PartitioningByEnd(hspace, names=names(query@partitioning), NG=length(names(query@partitioning))) newCompressedList0("CompressedHitsList", unlistData=hits, partitioning=partitioning) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Going from Hits to HitsList with extractList() and family. ### setMethod("relistToClass", "Hits", function(x) "HitsList") ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion ### ## return as.matrix as on Hits, with indices adjusted setMethod("as.matrix", "HitsList", function(x) { mats <- lapply(x, as.matrix) mat <- do.call(rbind, mats) rows <- c(0L, head(cumsum(sapply(x, queryLength)), -1)) nr <- sapply(mats, nrow) mat + cbind(rep.int(rows, nr), rep.int(x@subjectOffsets, nr)) }) setMethod("as.matrix", "CompressedHitsList", function(x) { cbind(queryHits=queryHits(x), subjectHits=subjectHits(x)) }) ## count up the matches for each query in every matching setMethod("as.table", "HitsList", function(x, ...) { counts <- unlist(lapply(x, as.table)) as.table(array(counts, length(counts), list(range = seq_along(counts)))) }) setMethod("t", "HitsList", function(x) { x@elements <- lapply(as.list(x, use.names = FALSE), t) x }) setMethod("ranges", "HitsList", function(x, query, subject) { if (!is(query, "RangesList") || length(query) != length(x)) stop("'query' must be a RangesList of length equal to that of 'x'") if (!is(subject, "RangesList") || length(subject) != length(x)) stop("'subject' must be a RangesList of length equal to that of 'x'") els <- as.list(x, use.names = FALSE) queries <- as.list(query, use.names = FALSE) subjects <- as.list(subject, use.names = FALSE) ans <- do.call(RangesList, lapply(seq_len(length(x)), function(i) { ranges(els[[i]], queries[[i]], subjects[[i]]) })) names(ans) <- names(x) ans }) ### TODO: many convenience methods IRanges/R/IRanges-class.R0000644000175100017510000003604212607265143016114 0ustar00biocbuildbiocbuild### ========================================================================= ### IRanges objects ### ------------------------------------------------------------------------- ### ### The IRanges class is a simple container for storing a vector of integer ### ranges. ### setClass("IRanges", contains="Ranges", representation( start="integer", width="integer", NAMES="characterORNULL" # R doesn't like @names !! ), prototype( start=integer(), width=integer(), NAMES=NULL ) ) ### A NormalIRanges object is an IRanges object where the ranges are: ### (a) not empty (i.e. they have a non-null width); ### (b) not overlapping; ### (c) ordered from left to right; ### (d) not even adjacent (i.e. there must be a non empty gap between 2 ### consecutive ranges). ### If 'x' is an IRanges object of length >= 2, then 'x' is normal iff: ### start(x)[i] <= end(x)[i] < start(x)[i+1] <= end(x)[i+1] ### for every 1 <= i < length(x). ### If length(x) == 1, then 'x' is normal iff width(x)[1] >= 1. ### If length(x) == 0, then 'x' is normal. setClass("NormalIRanges", contains="IRanges") ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor methods. ### setMethod("start", "IRanges", function(x, ...) x@start) setMethod("width", "IRanges", function(x) x@width) setMethod("names", "IRanges", function(x) x@NAMES) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### isEmpty(), isNormal(), isDisjoint() ### setMethod("isNormal", "IRanges", function(x) .Call2("IRanges_isNormal", x, PACKAGE="IRanges") ) ### Fast methods for NormalIRanges objects. setMethod("isEmpty", "NormalIRanges", function(x) length(x) == 0L) setMethod("isNormal", "NormalIRanges", function(x) TRUE) setMethod("isDisjoint", "NormalIRanges", function(x) TRUE) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "max" and "min" methods. ### ### Note: defined for NormalIRanges objects only. ### For an ordinary IRanges object 'x', it's not clear what the semantic ### should be. In particular, should empty ranges be ignored or not? If not ### then we could end up with 'min(x)' > 'max(x)' (e.g. when 'x' is made of 1 ### empty range) which is not nice. Another (and more pragmatic) reason for ### not defining these methods for IRanges objects is that I don't need them ### at the moment. ### setMethod("max", "NormalIRanges", function(x, ..., na.rm) { if (isEmpty(x)) { warning("empty ", class(x), " object; returning -Inf") -Inf } else { end(x)[length(x)] } } ) setMethod("min", "NormalIRanges", function(x, ..., na.rm) { if (isEmpty(x)) { warning("empty ", class(x), " object; returning Inf") Inf } else { start(x)[1L] } } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### ### Validity of IRanges objects is taken care of by the validity method for ### Ranges objects. ### ### NormalIRanges objects .valid.NormalIRanges <- function(x) { if (!isNormal(x)) return("object is not normal") NULL } setValidity2("NormalIRanges", .valid.NormalIRanges) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### ### Any Ranges object can be turned into an IRanges instance. setAs("Ranges", "IRanges", function(from) new2("IRanges", start=start(from), width=width(from), NAMES=names(from), check=FALSE) ) ### Helper function (not exported) used by the "coerce" methods defined in ### IRanges-utils.R. Believe it or not but the implicit "coerce" methods do ### NOT check that they return a valid object! newNormalIRangesFromIRanges <- function(x, check=TRUE) { if (!is(x, "IRanges")) stop("'x' must be an IRanges object") if (!isTRUEorFALSE(check)) stop("'check' must be TRUE or FALSE") ## Check only what needs to be checked. if (check) S4Vectors:::stopIfProblems(.valid.NormalIRanges(x)) ## Make a "hard copy" of the slots. No need to check anything! new2("NormalIRanges", start=x@start, width=x@width, NAMES=x@NAMES, check=FALSE) } ### The returned IRanges instance is guaranteed to be normal. setAs("logical", "IRanges", function(from) as(as(from, "NormalIRanges"), "IRanges") ) setAs("logical", "NormalIRanges", function(from) .Call2("NormalIRanges_from_logical", from, PACKAGE="IRanges") ) ### coersion from integer setAs("integer", "IRanges", function(from) .Call2("IRanges_from_integer", from, PACKAGE="IRanges") ) setAs("integer", "NormalIRanges", function(from) newNormalIRangesFromIRanges(as(from, "IRanges")) ) setAs("numeric", "IRanges", function(from) as(as.integer(from), "IRanges")) setAs("numeric", "NormalIRanges", function(from) newNormalIRangesFromIRanges(as(as.integer(from), "IRanges"))) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Low-level setters for IRanges objects. ### ### The choice was made to implement a "resizing" semantic: ### (1) changing the start preserves the end (so it changes the width) ### (2) changing the end preserves the start (so it changes the width) ### (3) changing the width preserves the start (so it changes the end) ### .set_IRanges_start <- function(x, value, check=TRUE) { if (!isTRUEorFALSE(check)) stop("'check' must be TRUE or FALSE") old_start <- start(x) ## Use 'x@start[]' instead of 'x@start' so the right value is recycled. x@start[] <- S4Vectors:::numeric2integer(value) x@width <- width(x) - start(x) + old_start if (check) validObject(x) x } setReplaceMethod("start", "IRanges", function(x, ..., value) .set_IRanges_start(x, value) ) .set_IRanges_end <- function(x, value, check=TRUE) { if (!isTRUEorFALSE(check)) stop("'check' must be TRUE or FALSE") ## Use 'x@width[]' instead of 'x@width' so the right value is recycled. x@width[] <- width(x) + S4Vectors:::numeric2integer(value) - end(x) if (check) validObject(x) x } setReplaceMethod("end", "IRanges", function(x, ..., value) .set_IRanges_end(x, value) ) .set_IRanges_width <- function(x, value, check=TRUE) { if (!isTRUEorFALSE(check)) stop("'check' must be TRUE or FALSE") ## Use 'x@width[]' instead of 'x@width' so the right value is recycled. x@width[] <- S4Vectors:::numeric2integer(value) if (check) validObject(x) x } setReplaceMethod("width", "IRanges", function(x, ..., value) .set_IRanges_width(x, value) ) set_IRanges_names <- function(x, value) { x@NAMES <- S4Vectors:::normalize_names_replacement_value(value, x) ## No need to validate an IRanges object after setting its names so this ## should be safe. x } setReplaceMethod("names", "IRanges", set_IRanges_names) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "update" method. ### ### This is a convenience method for combining multiple modifications in one ### single call. ### ### It must verify 2 important properties: ### (1) update(x) must be identical to x (doesn't touch x at all) ### (2) update(x, start=start(x), width=width(x), names=names(x)) ### must be identical to x too (but this time it updates x with its own ### content) ### unsafe.update <- function(object, ...) { valid_argnames <- c("start", "end", "width", "names") args <- S4Vectors:::extraArgsAsList(valid_argnames, ...) argnames <- names(args) sew <- c("start", "end", "width") narg_in_sew <- sum(sew %in% argnames) if (narg_in_sew == 3L) stop("at most 2 out of the ", paste("'", sew, "'", sep="", collapse=", "), " arguments can be supplied") do_atomic_update <- narg_in_sew == 2L && (is.null(names(object)) || ("names" %in% argnames)) if (do_atomic_update) { if ("end" %in% argnames) { if ("width" %in% argnames) { width <- args$width start <- args$end - width + 1L } else { start <- args$start width <- args$end - start + 1L } } else { start <- args$start width <- args$width } object@start <- S4Vectors:::numeric2integer(start) object@width <- S4Vectors:::numeric2integer(width) object@NAMES <- args$names return(object) } if ("start" %in% argnames) object <- .set_IRanges_start(object, args$start, check=FALSE) if ("end" %in% argnames) object <- .set_IRanges_end(object, args$end, check=FALSE) if ("width" %in% argnames) object <- .set_IRanges_width(object, args$width, check=FALSE) if ("names" %in% argnames) object <- set_IRanges_names(object, args$names) object } ### FIXME: need some way of specifying the extent of validity ### checking, like giving the class up to which the object is ### assumed valid. setMethod("update", "IRanges", function(object, ..., check = TRUE) { if (!isTRUEorFALSE(check)) stop("'check' must be TRUE or FALSE") object <- unsafe.update(object, ...) if (check) validObject(object) object } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Subsetting. ### setMethod("extractROWS", "IRanges", function(x, i) { i <- normalizeSingleBracketSubscript(i, x, as.NSBS=TRUE) if (is(x, "NormalIRanges")) { if (!isStrictlySorted(i)) stop("subscript must extract elements at strictly sorted ", "positions when\n subsetting a ", class(x), " object") } ans_start <- extractROWS(start(x), i) ans_width <- extractROWS(width(x), i) ans_names <- extractROWS(names(x), i) ans_mcols <- extractROWS(mcols(x), i) initialize(x, start=ans_start, width=ans_width, NAMES=ans_names, elementMetadata=ans_mcols) } ) setMethod("replaceROWS", "IRanges", function(x, i, value) { i <- normalizeSingleBracketSubscript(i, x, as.NSBS=TRUE) ans_start <- replaceROWS(start(x), i, start(value)) ans_width <- replaceROWS(width(x), i, width(value)) ans <- initialize(x, start=ans_start, width=ans_width) if (is(x, "NormalIRanges")) validObject(ans) ans } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Combining. ### ### The "c" method for IRanges objects is implemented to behave like an ### endomorphism i.e. to return an object of the same class as 'x'. In ### particular 'c(x)' now returns 'x' and not 'as(x, "IRanges")'. ### It's easy to implement specific "c" methods for IRanges subclasses. ### Typically they just need to do something like: ### ### old_val <- S4Vectors:::disableValidity() ### on.exit(S4Vectors:::disableValidity(old_val)) ### S4Vectors:::disableValidity(TRUE) ### ans <- callNextMethod(x, ..., recursive=FALSE) ### ... ### ### and to take care of the additional slots (aka the subclass-specific ### slots). If there aren't any additional slots (e.g. NormalIRanges), or ### if the additional slots don't need to be modified (e.g. the "subject" ### slot of the Views subclass), then no need to implement a specific method ### at all. ### ### In the case of NormalIRanges objects, 'c(x1, x2)' will fail if the result ### is not normal, but 'c(as(x1, "IRanges"), x2)' or 'c(IRanges(), x1, x2)' ### would work. Note that, in general, 'c(IRanges(), x)' is not the same as ### 'c(x, IRanges())' (the former is equivalent to 'as(x, IRanges)' and the ### latter to 'c(x)' or 'x'). ### Also note that the user needs to be carefull when passing named arguments ### to c() (there is no good reason to do this in the first place) because of ### the following pitfalls: ### (1) If all the arguments are named (e.g. 'c(a=x1, b=x2)') then the first ### argument must be an IRanges *instance* otherwise dispatch will fail. ### It's not clear why dispatch works when 'x1' is an IRanges instance ### because, in that case, formal argument 'x' is missing. It's even ### less clear why it fails when 'x1' is an IRanges object without being ### an IRanges instance. For example: ### x1 <- IRanges(1, 11) ### x2 <- IRanges(22, 33) ### ## works as expected: ### c(a=x1, b=x2) ### ## works as expected: ### c(a=x1, asNormalIRanges(x2)) ### ## dispatch fails (the default "c" method is selected) ### c(a=asNormalIRanges(x1), b=x2)) ### (2) When named and unnamed arguments are mixed and no named argument has ### name 'x' (e.g. 'c(a=x1, x2)'), then, following the standard rules of ### argument matching in R, one would expect that the first unnamed ### argument will match formal argument 'x'. This is more or less what ### happens: ### > c(a=x1, x2) ### IRanges object: ### start end width ### [1] 2 22 21 ### [2] 1 11 11 ### but there are some surprises: ### > c(a=x1, TRUE) ### Error in c(a = x1, TRUE) : ### all arguments in '...' must be logical objects (or NULLs) ### > c(a=asNormalIRanges(x1), TRUE) ### $a ### NormalIRanges object: ### start end width ### [1] 1 11 11 ### ### [[2]] ### [1] TRUE ### setMethod("c", "IRanges", function(x, ..., ignore.mcols=FALSE, recursive=FALSE) { if (!identical(recursive, FALSE)) stop("\"c\" method for IRanges objects ", "does not support the 'recursive' argument") if (!isTRUEorFALSE(ignore.mcols)) stop("'ignore.mcols' must be TRUE or FALSE") if (missing(x)) { args <- unname(list(...)) x <- args[[1L]] } else { args <- unname(list(x, ...)) } if (length(args) == 1L) return(x) arg_is_null <- sapply(args, is.null) if (any(arg_is_null)) args[arg_is_null] <- NULL # remove NULL elements by setting them to NULL! if (!all(sapply(args, is, class(x)))) stop("all arguments in '...' must be ", class(x), " objects (or NULLs)") new_start <- unlist(lapply(args, start), use.names=FALSE) new_width <- unlist(lapply(args, width), use.names=FALSE) names_list <- lapply(args, names) arg_has_no_names <- sapply(names_list, is.null) if (all(arg_has_no_names)) { new_names <- NULL } else { names_list[arg_has_no_names] <- lapply(args[arg_has_no_names], function(arg) character(length(arg))) new_names <- unlist(names_list, use.names=FALSE) } ans <- update(x, start=new_start, width=new_width, names=new_names, check=FALSE) if (ignore.mcols) { mcols(ans) <- NULL } else { mcols(ans) <- do.call(S4Vectors:::rbind_mcols, args) } validObject(ans) ans } ) IRanges/R/IRanges-constructor.R0000644000175100017510000001547612607265143017404 0ustar00biocbuildbiocbuild### ========================================================================= ### The IRanges constructor ### ------------------------------------------------------------------------- ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The SEW0 interface: start=NULL/end=NULL/width=NULL ### .normargSEW0 <- function(x, argname) { if (is.null(x)) return(integer()) if (!is.numeric(x) && !(is.atomic(x) && all(is.na(x)))) stop("'", argname, "' must be a numeric vector (or NULL)") if (!is.integer(x)) x <- as.integer(x) x } ### Some of the functions that support the SEW0 interface: IRanges(), Views(), ### etc... solveUserSEW0 <- function(start=NULL, end=NULL, width=NULL) { start <- .normargSEW0(start, "start") end <- .normargSEW0(end, "end") width <- .normargSEW0(width, "width") L1 <- length(start) L2 <- length(end) L3 <- length(width) L123 <- c(L1, L2, L3) max123 <- max(L123) ## We want IRanges(start=integer(0), width=5) and ## IRanges(end=integer(0), width=5) to work and return an empty IRanges ## object. if (max123 == 0L || L1 == 0L && L2 == 0L && L3 == 1L) return(new("IRanges")) ## Recycle start/end/width. if (L1 < max123) { if (L1 == 0L) start <- rep.int(NA_integer_, max123) else start <- S4Vectors:::recycleVector(start, max123) } if (L2 < max123) { if (L2 == 0L) end <- rep.int(NA_integer_, max123) else end <- S4Vectors:::recycleVector(end, max123) } if (L3 < max123) { if (L3 == 0L) width <- rep.int(NA_integer_, max123) else width <- S4Vectors:::recycleVector(width, max123) } .Call2("solve_user_SEW0", start, end, width, PACKAGE="IRanges") } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The safe and user-friendly "IRanges" constructor. ### IRanges <- function(start=NULL, end=NULL, width=NULL, names=NULL) { if (is(start, "Ranges")) { if (!is.null(end) || !is.null(width)) stop("'end' and 'width' must be NULLs ", "when 'start' is a Ranges object") ans <- new2("IRanges", start=start(start), width=width(start), NAMES=names, check=FALSE) return(ans) } if ((is.logical(start) && !all(is.na(start))) || is(start, "Rle")) { if (is(start, "Rle") && !is.logical(runValue(start))) stop("'start' is an Rle, but not a logical Rle object") if (!is.null(end) || !is.null(width)) stop("'end' and 'width' must be NULLs when 'start' is a logical ", "vector or logical Rle") ## The returned IRanges instance is guaranteed to be normal. ans <- as(start, "IRanges") names(ans) <- names return(ans) } ans <- solveUserSEW0(start=start, end=end, width=width) names(ans) <- names return(ans) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The SEW interface: start=NA/end=NA/width=NA ### ### Some of the functions that support the SEW interface: narrow(), ### XVector::subseq(), XVector::xvcopy(), Biostrings::BStringSet() (and ### family), BSgenome::getSeq(), etc... ### .normargSEW <- function(x, argname) { if (!S4Vectors:::isNumericOrNAs(x)) stop("'", argname, "' must be a vector of integers") if (!is.integer(x)) x <- as.integer(x) x } ### Use of 'rep.refwidths=TRUE' is supported only when 'refwidths' is of ### length 1. ### If 'rep.refwidths=FALSE' (the default) then 'start', 'end' and 'width' ### are recycled to 'length(refwidths)' (it's an error if one of them is ### longer than 'refwidths'). Otherwise, 'refwidths' is replicated L times ### where L is the length of the longest of 'start', 'end' and 'width'. ### The returned value is an IRanges object of the same length as 'refwidths' ### (after replication if 'rep.refwidths=TRUE'). solveUserSEW <- function(refwidths, start=NA, end=NA, width=NA, rep.refwidths=FALSE, translate.negative.coord=TRUE, allow.nonnarrowing=FALSE) { if (!is.numeric(refwidths)) stop("'refwidths' must be a vector of integers") if (!is.integer(refwidths)) refwidths <- as.integer(refwidths) start <- .normargSEW(start, "start") end <- .normargSEW(end, "end") width <- .normargSEW(width, "width") ## From here, 'refwidths', 'start', 'end' and 'width' are guaranteed to be ## integer vectors. NAs in 'start', 'end' and 'width' are OK but not in ## 'refwidths' so this should be checked at the C level. if (!isTRUEorFALSE(rep.refwidths)) stop("'rep.refwidths' must be TRUE or FALSE") if (!isTRUEorFALSE(translate.negative.coord)) stop("'translate.negative.coord' must be TRUE or FALSE") if (!isTRUEorFALSE(allow.nonnarrowing)) stop("'allow.nonnarrowing' must be TRUE or FALSE") Lsew <- c(length(start), length(end), length(width)) maxLsew <- max(Lsew) minLsew <- min(Lsew) if (minLsew == 0L && maxLsew > 1L) stop("'start', 'end' and 'width' cannot mix zero-length ", "and longer-than-one vectors") ## Check 'start', 'end', and 'width' *without* recycling them. Recycling ## is done at the C level. if (rep.refwidths) { if (length(refwidths) != 1L) stop("'rep.refwidths=TRUE' can be used only when 'refwidths' ", "is of length 1") ## 'ans_len' is the length of the longest of 'start', 'end' ## and 'width'. if (minLsew == 0L) { ans_len <- 0L } else { ans_len <- maxLsew } refwidths <- rep.int(refwidths, ans_len) } else { ans_len <- length(refwidths) if (ans_len == 0L) { if (maxLsew > 1L) stop("'start', 'end' or 'width' is longer than 'refwidths'") } else { if (minLsew == 0L) stop("cannot recycle empty 'start', 'end' or 'width'") if (maxLsew > ans_len) stop("'start', 'end' or 'width' is longer than 'refwidths'") } } .Call2("solve_user_SEW", refwidths, start, end, width, translate.negative.coord, allow.nonnarrowing, PACKAGE="IRanges") } ### Returns an IRanges instance of length 1. Not exported. solveUserSEWForSingleSeq <- function(x_length, start=NA, end=NA, width=NA) { solved_SEW <- try(solveUserSEW(x_length, start=start, end=end, width=width), silent = TRUE) if (is(solved_SEW, "try-error")) stop("Invalid sequence coordinates.\n", " Please make sure the supplied 'start', 'end' and 'width' arguments\n", " are defining a region that is within the limits of the sequence.") solved_SEW } IRanges/R/IRanges-utils.R0000644000175100017510000001436412607265143016152 0ustar00biocbuildbiocbuild### ========================================================================= ### Utility functions for creating or modifying IRanges objects ### ------------------------------------------------------------------------- ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "successiveIRanges" function. ### ### Note that the returned IRanges object is guaranteed to be normal in the ### following cases: ### (a) when length(width) == 0 ### (b) when length(width) == 1 and width > 0 ### (c) when length(width) >= 2 and all(width > 0) and all(gapwidth > 0) ### However, the function doesn't try to turn the result into a NormalIRanges ### object. ### successiveIRanges <- function(width, gapwidth=0, from=1) { if (!is.numeric(width)) stop("'width' must be an integer vector") if (length(width) == 0L) return(IRanges()) if (!is.integer(width)) width <- as.integer(width) # this drops the names else if (!is.null(names(width))) names(width) <- NULL # unname() used to be broken on 0-length vectors if (S4Vectors:::anyMissingOrOutside(width, 0L)) stop("'width' cannot contain NAs or negative values") if (!is.numeric(gapwidth)) stop("'gapwidth' must be an integer vector") if (!is.integer(gapwidth)) gapwidth <- as.integer(gapwidth) if (S4Vectors:::anyMissing(gapwidth)) stop("'gapwidth' cannot contain NAs") if (length(gapwidth) != length(width) - 1L) { if (length(gapwidth) != 1L) stop("'gapwidth' must a single integer or an integer vector ", "with one less element than the 'width' vector") gapwidth <- rep.int(gapwidth, length(width) - 1L) } if (!isSingleNumber(from)) stop("'from' must be a single integer") if (!is.integer(from)) from <- as.integer(from) ans_start <- cumsum(width[-length(width)] + gapwidth) ans_start <- from + c(0L, ans_start) ## 'ans_start' could contain NAs in case of an integer overflow in ## cumsum(), hence the use of 'check=TRUE' here: new2("IRanges", start=ans_start, width=width, check=TRUE) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### breakInChunks() ### ### TODO: Should not be in IRanges-utils.R because it returns a ### PartitioningByEnd object, not an IRanges object. So move it to another ### file, e.g. to Partitioning-class.R. breakInChunks() is actually a ### specialized PartitioningByEnd constructor. ### .normarg_totalsize <- function(totalsize) { if (!isSingleNumber(totalsize)) stop("'totalsize' must be a single integer") if (!is.integer(totalsize)) totalsize <- as.integer(totalsize) if (totalsize < 0L) stop("'totalsize' cannot be negative") totalsize } .normarg_chunksize_or_nchunk <- function(chunksize, totalsize, what) { if (!isSingleNumber(chunksize)) stop("'", what, "' must be a single integer") if (!is.integer(chunksize)) chunksize <- as.integer(chunksize) if (chunksize < 0L) stop("'", what, "' cannot be negative") if (chunksize == 0L && totalsize != 0L) stop("'", what, "' can be 0 only if 'totalsize' is 0") chunksize } ### TODO: Argument names and order is inconsistent with tileGenome(). ### Reconcile them! breakInChunks <- function(totalsize, chunksize, nchunk) { totalsize <- .normarg_totalsize(totalsize) if (!missing(chunksize)) { if (!missing(nchunk)) stop("only one of 'chunksize' and 'nchunk' can be specified") ## All chunks will have the requested size, except maybe the last one. chunksize <- .normarg_chunksize_or_nchunk(chunksize, totalsize, "chunksize") if (totalsize == 0L) return(PartitioningByEnd()) quot <- totalsize %/% chunksize # integer division ans_end <- cumsum(rep.int(chunksize, quot)) if (quot == 0L || ans_end[[quot]] != totalsize) ans_end <- c(ans_end, totalsize) } else { if (missing(nchunk)) stop("one of 'chunksize' and 'nchunk' must be specified") ## All chunks will have more or less the same size, with the difference ## between smallest and biggest chunks guaranteed to be <= 1. nchunk <- .normarg_chunksize_or_nchunk(nchunk, totalsize, "nchunk") if (nchunk == 0L) return(PartitioningByEnd()) chunksize <- totalsize / nchunk # floating point division ans_end <- as.integer(cumsum(rep.int(chunksize, nchunk))) ## The last value in 'ans_end' *should* be 'totalsize' but there is ## always some uncertainty about what coercing the result of a floating ## point operation to integer will produce. So we set this value ## manually to 'totalsize' just in case. ans_end[[nchunk]] <- totalsize } PartitioningByEnd(ans_end) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "centeredIRanges" function. ### centeredIRanges <- function(center, flank) { if (!is.numeric(center)) stop("'center' must be a numeric vector") if (!is.numeric(flank)) stop("'flank' must be a numeric vector") IRanges(start=center-flank, end=center+flank) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "whichAsIRanges" function. ### ### Note that unlike the standard which() function, whichAsIRanges() drops ### the names of 'x'. ### whichAsIRanges <- function(x) { if (!is.logical(x)) stop("'x' must be a logical vector") as(x, "NormalIRanges") } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercing an IRanges object to a NormalIRanges object. ### asNormalIRanges <- function(x, force=TRUE) { if (!is(x, "Ranges")) stop("'x' must be an Ranges object") else if (!is(x, "IRanges")) x <- as(x, "IRanges") if (!isTRUEorFALSE(force)) stop("'force' must be TRUE or FALSE") if (force) x <- reduce(x, drop.empty.ranges=TRUE) newNormalIRangesFromIRanges(x, check=!force) } .asNormalIRanges <- function(from) asNormalIRanges(from, force=TRUE) setAs("IRanges", "NormalIRanges", .asNormalIRanges) IRanges/R/IntervalForest-class.R0000644000175100017510000001105612607265143017531 0ustar00biocbuildbiocbuild### ========================================================================= ### IntervalForest objects ### ------------------------------------------------------------------------- setClass("IntervalForest", representation(ptr="externalptr", mode="character", partitioning="PartitioningByEnd"), contains = c("RangesList")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity ### .valid.IntervalForest.partitioning <- function(x) { dataLength <- .IntervalForestCall(x,"nobj") if (nobj(x@partitioning) != dataLength) "improper partitioning" else NULL } .valid.IntervalForest.mode <- function(x) { if (x@mode != "integer") return("mode is not 'integer'") NULL } .valid.IntervalForest <- function(x) { c(.valid.IntervalForest.partitioning(x), .valid.IntervalForest.mode(x)) } setValidity2("IntervalForest", .valid.IntervalForest) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor ### IntervalForest <- function(x) { if (!is(x, "IRangesList")) { stop("'x' must be an 'IRangesList' object") } if (elementType(x) != "IRanges") { stop("'elementType(x)' must be of class 'IRanges'") } as(x, "IntervalForest") } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion ### setAs("IntervalForest", "CompressedIRangesList", function(from) { new2("CompressedIRangesList", unlistData=.IntervalForestCall(from, "asIRanges"), partitioning=from@partitioning, elementType="IRanges", check=FALSE) }) setAs("IntervalForest", "IRanges", function(from) .IntervalForestCall(from, "asIRanges")) setAs("CompressedIRangesList", "IntervalForest", function(from) { msg <- c("IntervalForest objects and the \"intervaltree\" algorithm used ", "in findOverlaps() and family are defunct. Please use the ", "\"nclist\" algorithm instead. See the 'algorithm' argument ", "in ?findOverlaps for more information.") .Defunct(msg=wmsg(msg)) }) setAs("RangesList", "IntervalForest", function(from) as(as(from, "CompressedIRangesList"), "IntervalForest")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessors ### setMethod("start", "IntervalForest", function(x) new2("CompressedIntegerList", unlistData = .IntervalForestCall(x, "start"), partitioning = x@partitioning, check=FALSE)) setMethod("end", "IntervalForest", function(x) new2("CompressedIntegerList", unlistData = .IntervalForestCall(x, "end"), partitioning = x@partitioning, check=FALSE)) setMethod("width", "IntervalForest", function(x) new2("CompressedIntegerList", unlistData = .IntervalForestCall(x, "end") - .IntervalForestCall(x, "start") + 1L, partitioning = x@partitioning, check=FALSE)) setMethod("elementLengths", "IntervalForest", function(x) { ans <- elementLengths(x@partitioning) names(ans) <- names(x) ans } ) setMethod("length", "IntervalForest", function(x) length(x@partitioning)) setMethod("names", "IntervalForest", function(x) names(x@partitioning)) ### - - - - ### Subsetting ### setMethod("[", "IntervalForest", function(x, i, j, ..., drop=TRUE) { if (!missing(j) || length(list(...)) > 0L) stop("invalid subsetting") rl <- split(callGeneric(as(x, "IRanges"), i = i, ...), callGeneric(space(x), i = i, ...)) as(rl, "IntervalForest") } ) ### - - - - ### show ### - - - - setMethod("show", "IntervalForest", function(object) { newobj <- as(object, "CompressedIRangesList") cat("IntervalForest of length ", length(newobj), "\n", sep="") showRangesList(newobj, with.header=FALSE) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Low-level utilities ### .IntervalForestCall <- function(object, fun, ...) { # validObject(object) fun <- paste("IntervalForest", fun, sep = "_") if (object@mode == "integer") { fun <- paste("Integer", fun, sep = "") .Call2(fun, object@ptr, ..., PACKAGE="IRanges") } else stop("unknown interval forest mode: ", object@mode) } ## not for exporting, just a debugging utility IntervalForestDump <- function(object) { cat("IntervalForest, levels: ", levels(object), "\n") .IntervalForestCall(object, "dump") } IRanges/R/IntervalTree-class.R0000644000175100017510000000430312607265143017163 0ustar00biocbuildbiocbuild### ========================================================================= ### IntervalTree objects ### ------------------------------------------------------------------------- setClass("IntervalTree", representation(ptr = "externalptr", mode = "character"), contains = "Ranges") ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessors ### setMethod("length", "IntervalTree", function(x) IntervalTreeCall(x, "length")) setMethod("start", "IntervalTree", function(x) IntervalTreeCall(x, "start")) setMethod("end", "IntervalTree", function(x) IntervalTreeCall(x, "end")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor ### IntervalTree <- function(ranges) { as(ranges, "IntervalTree") } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion ### setAs("IntervalTree", "IRanges", function(from) { IntervalTreeCall(from, "asIRanges") }) setAs("IRanges", "IntervalTree", function(from) { msg <- c("IntervalTree objects and the \"intervaltree\" algorithm used ", "in findOverlaps() and family are defunct. Please use the ", "\"nclist\" algorithm instead. See the 'algorithm' argument ", "in ?findOverlaps for more information.") .Defunct(msg=wmsg(msg)) validObject(from) ptr <- .Call2("IntegerIntervalTree_new", from, PACKAGE="IRanges") new2("IntervalTree", ptr = ptr, mode = "integer", check=FALSE) }) setAs("Ranges", "IntervalTree", function(from) { as(as(from, "IRanges"), "IntervalTree") }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Low-level utilities ### IntervalTreeCall <- function(object, fun, ...) { #validObject(object) # causes an infinite recursion, because calls # .valid.Vector.length(), which calls length(), # which calls IntervalTreeCall(), which calls # validObject(), etc... fun <- paste("IntervalTree", fun, sep = "_") if (object@mode == "integer") { fun <- paste("Integer", fun, sep = "") .Call2(fun, object@ptr, ..., PACKAGE="IRanges") } else stop("unknown interval tree mode: ", object@mode) } IRanges/R/IntervalTree-utils.R0000644000175100017510000000511512607265143017220 0ustar00biocbuildbiocbuild### ========================================================================= ### IntervalTree utilities ### ------------------------------------------------------------------------- ## internal generic setGeneric("processSelfMatching", # not exported function(x, select = c("all", "first", "last", "arbitrary"), ignoreSelf = FALSE, ignoreRedundant = FALSE) standardGeneric("processSelfMatching")) setMethod("processSelfMatching", "Hits", function(x, select = c("all", "first", "last", "arbitrary"), ignoreSelf = FALSE, ignoreRedundant = FALSE) { if (ignoreSelf) { self_idx <- which(queryHits(x) == subjectHits(x)) if (length(self_idx) != 0L) x <- x[-self_idx] } if (ignoreRedundant) { redundant_idx <- which(S4Vectors:::duplicatedIntegerPairs( pmin.int(queryHits(x), subjectHits(x)), pmax.int(queryHits(x), subjectHits(x)))) if (length(redundant_idx) != 0L) x <- x[-redundant_idx] } selectHits(x, select=select) }) setMethod("processSelfMatching", "HitsList", function(x, select = c("all", "first", "last", "arbitrary"), ignoreSelf = FALSE, ignoreRedundant = FALSE) { select <- match.arg(select) ans <- lapply(x, processSelfMatching, select, ignoreSelf, ignoreRedundant) if (select != "all") IntegerList(ans) else S4Vectors:::new_SimpleList_from_list("HitsList", ans, subjectOffsets = x@subjectOffsets) }) setMethod("processSelfMatching", "CompressedHitsList", function(x, select = c("all", "first", "last", "arbitrary"), ignoreSelf = FALSE, ignoreRedundant = FALSE) { select <- match.arg(select) ans <- processSelfMatching(x@unlistData, select = select, ignoreSelf = ignoreSelf, ignoreRedundant = ignoreRedundant) if (select != "all") new2("CompressedIntegerList", unlistData=ans, partitioning=x@partitioning) else new2("CompressedHitsList", unlistData=ans, partitioning=x@partitioning) }) ## not for exporting, just a debugging utility IntervalTreeDump <- function(object) { IntervalTreeCall(object, "dump") } IRanges/R/List-class-leftovers.R0000644000175100017510000000472312607265143017507 0ustar00biocbuildbiocbuild### ========================================================================= ### IMPORTANT NOTE - 9/4/2014 ### Most of the stuff that used to be in the IRanges/R/List-class.R file ### was moved to the S4Vectors package (to R/List-class.R). ### The stuff that could not be moved there was *temporarily* kept here in ### List-class-leftovers.R but will need to find a new home (in S4Vectors ### or in IRanges). ### ## NOTE: while the 'c' function does not have an 'x', the generic does ## c() is a primitive, so 'x' can be missing; dispatch is by position, ## although sometimes this does not work so well, so it's best to keep ## names off the parameters whenever feasible. setMethod("c", "SimpleList", function(x, ..., recursive = FALSE) { slot(x, "listData") <- do.call(c, lapply(unname(list(x, ...)), as.list)) if (!is.null(mcols(x))) mcols(x) <- S4Vectors:::rbind_mcols(x, ...) x }) .stack.ind <- function(x, index.var = "name") { if (length(names(x)) > 0) { spaceLabels <- names(x) } else { spaceLabels <- seq_len(length(x)) } ind <- Rle(factor(spaceLabels, levels = unique(spaceLabels)), elementLengths(x)) do.call(DataFrame, structure(list(ind), names = index.var)) } ### FIXME: need a recursive argument, when TRUE we call stack on ### unlist result, instead of coercing to DataFrame. setMethod("stack", "List", function(x, index.var = "name", value.var = "value", name.var = NULL) { value <- unlist(x, use.names=FALSE) index <- .stack.ind(x, index.var) unlistsToList <- extends(x@elementType, "List") if (unlistsToList) { df <- cbind(S4Vectors:::ensureMcols(value), index) } else { df <- DataFrame(index, as(value, "DataFrame")) colnames(df)[2] <- value.var } if (!is.null(name.var)) { nms <- as.character(unlist(lapply(x, names))) if (length(nms) == 0L) { rngs <- IRanges(1L, width=elementLengths(x)) nms <- as.character(as.integer(rngs)) } df[[name.var]] <- factor(nms, unique(nms)) } if (!is.null(mcols(x))) { df <- cbind(df, mcols(x)) } if (unlistsToList) { mcols(value) <- df value } else { df } }) IRanges/R/List-comparison.R0000644000175100017510000002356112607265143016546 0ustar00biocbuildbiocbuild### ========================================================================= ### Comparing and ordering List objects ### ------------------------------------------------------------------------- ### ### Method signatures for binary comparison operators. .OP2_SIGNATURES <- list( c("List", "List"), c("List", "list"), c("list", "List") ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### compareRecursively() ### ### NOT exported! ### ### By default, List objects compare recursively. Exceptions to the rule ### (e.g. Ranges, XString, etc...) must define a "compareRecursively" method ### that returns FALSE. ### setGeneric("compareRecursively", function(x) standardGeneric("compareRecursively") ) setMethod("compareRecursively", "List", function(x) TRUE) setMethod("compareRecursively", "list", function(x) TRUE) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### .op1_apply() and .op2_apply() internal helpers ### ### Apply a unary operator. .op1_apply <- function(OP1, x, ..., ANS_CONSTRUCTOR) { comp_rec_x <- compareRecursively(x) if (!comp_rec_x) { OP1_Vector_method <- selectMethod(OP1, "Vector") return(OP1_Vector_method(x, ...)) } compress_ans <- !is(x, "SimpleList") ANS_CONSTRUCTOR(lapply(x, OP1, ...), compress=compress_ans) } ### Apply a binary operator. .op2_apply <- function(OP2, x, y, ..., ANS_CONSTRUCTOR) { comp_rec_x <- compareRecursively(x) comp_rec_y <- compareRecursively(y) if (!(comp_rec_x || comp_rec_y)) { OP2_Vector_method <- selectMethod(OP2, c("Vector", "Vector")) return(OP2_Vector_method(x, y, ...)) } if (!comp_rec_x) x <- list(x) if (!comp_rec_y) y <- list(y) compress_ans <- !((is(x, "SimpleList") || is.list(x)) && (is(y, "SimpleList") || is.list(y))) x_len <- length(x) y_len <- length(y) if (x_len == 0L || y_len == 0L) { ans <- ANS_CONSTRUCTOR(compress=compress_ans) } else { ans <- ANS_CONSTRUCTOR(mapply(OP2, x, y, MoreArgs=list(...), SIMPLIFY=FALSE, USE.NAMES=FALSE), compress=compress_ans) } ## 'ans' is guaranteed to have the length of 'x' or 'y'. x_names <- names(x) y_names <- names(y) if (!(is.null(x_names) && is.null(y_names))) { ans_len <- length(ans) if (x_len != y_len) { if (x_len == ans_len) { ans_names <- x_names } else { ans_names <- y_names } } else { if (is.null(x_names)) { ans_names <- y_names } else { ans_names <- x_names } } names(ans) <- ans_names } ans } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Element-wise (aka "parallel") comparison of 2 List objects. ### setMethods("compare", .OP2_SIGNATURES, function(x, y) .op2_apply(compare, x, y, ANS_CONSTRUCTOR=IntegerList) ) ### TODO: Add fast "==" and "<=" methods for CompressedList objects. setMethods("==", .OP2_SIGNATURES, function(e1, e2) .op2_apply(`==`, e1, e2, ANS_CONSTRUCTOR=LogicalList) ) setMethods("<=", .OP2_SIGNATURES, function(e1, e2) .op2_apply(`<=`, e1, e2, ANS_CONSTRUCTOR=LogicalList) ) ### The remaining comparison binary operators (!=, >=, <, >) will work ### out-of-the-box on List objects thanks to the "!" methods below and to the ### methods for Vector objects. setMethod("!", "List", function(x) { if (is(x, "RleList")) { ANS_CONSTRUCTOR <- RleList } else { ANS_CONSTRUCTOR <- LogicalList } .op1_apply(`!`, x, ANS_CONSTRUCTOR=ANS_CONSTRUCTOR) } ) setMethod("!", "CompressedList", function(x) relist(!unlist(x, use.names=FALSE), x) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### match() ### setMethods("match", c(.OP2_SIGNATURES, list(c("CompressedList", "list"))), function(x, table, nomatch=NA_integer_, incomparables=NULL, ...) { if (is(x, "RleList")) { ANS_CONSTRUCTOR <- RleList } else { ANS_CONSTRUCTOR <- IntegerList } .op2_apply(match, x, table, nomatch=nomatch, incomparables=incomparables, ..., ANS_CONSTRUCTOR=ANS_CONSTRUCTOR) } ) ### 2 of the 3 "match" methods defined above have signatures List,list and ### List,List and therefore are more specific than the 2 methods below. ### So in the methods below 'table' is guaranteed to be a vector that is not ### a list or a Vector that is not a List. setMethods("match", list(c("List", "vector"), c("List", "Vector")), function(x, table, nomatch=NA_integer_, incomparables=NULL, ...) { match(x, list(table), nomatch=nomatch, incomparables=incomparables, ...) } ) ### The first match method catches CompressedList,list; 'table' is atomic setMethod("match", c("CompressedList", "vector"), function(x, table, nomatch = NA_integer_, incomparables = NULL, ...) { m <- match(x@unlistData, table, nomatch=nomatch, incomparables=incomparables, ...) relist(m, x) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### duplicated() & unique() ### ### S3/S4 combo for duplicated.List duplicated.List <- function(x, incomparables=FALSE, fromLast=FALSE, ...) { .op1_apply(duplicated, x, incomparables=incomparables, fromLast=fromLast, ..., ANS_CONSTRUCTOR=LogicalList) } setMethod("duplicated", "List", duplicated.List) ### S3/S4 combo for duplicated.CompressedList .duplicated.CompressedList <- function(x, incomparables=FALSE, fromLast=FALSE) { if (!identical(incomparables, FALSE)) stop("\"duplicated\" method for CompressedList objects ", "does not support the 'incomparables' argument") x_unlistData <- x@unlistData sm <- match(x_unlistData, x_unlistData) # doesn't work on an Rle x_group <- rep.int(seq_along(x), elementLengths(x)) ans_unlistData <- S4Vectors:::duplicatedIntegerPairs(x_group, sm, fromLast=fromLast) relist(ans_unlistData, x) } duplicated.CompressedList <- function(x, incomparables=FALSE, fromLast=FALSE, ...) .duplicated.CompressedList(x, incomparables=incomparables, fromLast=fromLast, ...) setMethod("duplicated", "CompressedList", duplicated.CompressedList) ### S3/S4 combo for unique.List unique.List <- function(x, incomparables=FALSE, ...) { if (!compareRecursively(x)) return(unique.Vector(x, incomparables=incomparables, ...)) i <- !duplicated(x, incomparables=incomparables, ...) # LogicalList x[i] } setMethod("unique", "List", unique.List) ### S3/S4 combo for unique.SimpleList unique.SimpleList <- function(x, incomparables=FALSE, ...) { as(lapply(x, unique, incomparables=incomparables, ...), class(x)) } setMethod("unique", "SimpleList", unique.SimpleList) ### S3/S4 combo for unique.CompressedList .unique.CompressedList <- function(x, incomparables=FALSE, fromLast=FALSE) { if (!identical(incomparables, FALSE)) stop("\"unique\" method for CompressedList objects ", "does not support the 'incomparables' argument") is_dup <- duplicated(x, incomparables=incomparables, fromLast=fromLast) x_unlistData <- x@unlistData keep_idx <- which(!is_dup@unlistData) ans_unlistData <- x_unlistData[keep_idx] x_group <- rep.int(seq_along(x), elementLengths(x)) ans_group <- x_group[keep_idx] ans_partitioning <- PartitioningByEnd(ans_group, NG=length(x), names=names(x)) relist(ans_unlistData, ans_partitioning) } unique.CompressedList <- function(x, incomparables=FALSE, ...) .unique.CompressedList(x, incomparables=incomparables, ...) setMethod("unique", "CompressedList", unique.CompressedList) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### %in%() ### ### %in% will work out-of-the-box on List objects thanks to the "is.na" ### methods below and to the method for Vector objects. ### setMethod("is.na", "List", function(x) { if (is(x, "RleList")) { ANS_CONSTRUCTOR <- RleList } else { ANS_CONSTRUCTOR <- LogicalList } .op1_apply(is.na, x, ANS_CONSTRUCTOR=ANS_CONSTRUCTOR) } ) setMethod("is.na", "CompressedList", function(x) relist(is.na(unlist(x, use.names=FALSE)), x) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### order() and related methods. ### setMethod("order", "List", function(..., na.last=TRUE, decreasing=FALSE) { args <- list(...) if (length(args) != 1L) stop("\"order\" method for List objects ", "can only take one input object") .op1_apply(order, args[[1L]], na.last=na.last, decreasing=decreasing, ANS_CONSTRUCTOR=IntegerList) } ) ### S3/S4 combo for sort.List .sort.List <- function(x, decreasing=FALSE, na.last=NA) { if (!compareRecursively(x)) return(sort.Vector(x, decreasing=decreasing, na.last=na.last)) i <- order(x, na.last=na.last, decreasing=decreasing) # IntegerList x[i] } sort.List <- function(x, decreasing=FALSE, ...) .sort.List(x, decreasing=decreasing, ...) setMethod("sort", "List", sort.List) setMethod("rank", "List", function(x, na.last=TRUE, ties.method=c("average", "first", "random", "max", "min")) { .op1_apply(rank, x, na.last=na.last, ties.method=ties.method, ANS_CONSTRUCTOR=IntegerList) } ) IRanges/R/MaskCollection-class.R0000644000175100017510000003004312607265143017466 0ustar00biocbuildbiocbuild### ========================================================================= ### MaskCollection objects ### ------------------------------------------------------------------------- setClass("MaskCollection", contains="RangesList", representation( nir_list="list", # a list of NormalIRanges objects width="integer", active="logical", NAMES="character", # R doesn't like @names !! desc="character" ), prototype( nir_list=list(), width=0L, active=logical(0), NAMES=as.character(NA), desc=as.character(NA) ) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "length" and accessor methods. ### setGeneric("nir_list", function(x) standardGeneric("nir_list")) setMethod("nir_list", "MaskCollection", function(x) x@nir_list) setMethod("length", "MaskCollection", function(x) length(nir_list(x))) setMethod("width", "MaskCollection", function(x) x@width) setMethod("active", "MaskCollection", function(x) { ans <- x@active names(ans) <- names(x) ans } ) setReplaceMethod("active", "MaskCollection", function(x, value) { if (!is.logical(value) || S4Vectors:::anyMissing(value)) stop("'value' must be a logical vector with no NAs") x@active[] <- value x } ) setMethod("names", "MaskCollection", function(x) if (length(x@NAMES) == 1 && is.na(x@NAMES)) NULL else x@NAMES ) setReplaceMethod("names", "MaskCollection", function(x, value) { if (is.null(value)) { x@NAMES <- NA_character_ return(x) } value <- as.character(value) ii <- is.na(value) if (any(ii)) value[ii] <- "" if (length(value) > length(x)) stop("too many names") if (length(value) < length(x)) value <- c(value, character(length(x) - length(value))) x@NAMES <- value x } ) setGeneric("desc", function(x) standardGeneric("desc")) setMethod("desc", "MaskCollection", function(x) if (length(x@desc) == 1 && is.na(x@desc)) NULL else x@desc ) setGeneric("desc<-", signature="x", function(x, value) standardGeneric("desc<-") ) setReplaceMethod("desc", "MaskCollection", function(x, value) { if (is.null(value)) { x@desc <- as.character(NA) return(x) } if (!is.character(value)) stop("'value' must be NULL or a character vector") ii <- is.na(value) if (any(ii)) value[ii] <- "" if (length(value) > length(x)) stop("too many names") if (length(value) < length(x)) value <- c(value, character(length(x) - length(value))) x@desc <- value x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### .valid.MaskCollection.width <- function(x) { if (!isSingleInteger(width(x)) || width(x) < 0) return("the width of the collection must be a single non-negative integer") NULL } .valid.MaskCollection.nir_list <- function(x) { if (!is.list(nir_list(x)) || !all(sapply(nir_list(x), function(nir) is(nir, "NormalIRanges")))) return("the 'nir_list' slot must contain a list of NormalIRanges objects") if (!all(1 <= min(x)) || !all(max(x) <= width(x))) return("the min and max of the masks must be >= 1 and <= width of the collection") NULL } .valid.MaskCollection.active <- function(x) { if (!is.logical(active(x)) || S4Vectors:::anyMissing(active(x))) return("the 'active' slot must be a logical vector with no NAs") if (length(active(x)) != length(x)) return("the length of the 'active' slot differs from the length of the object") NULL } .valid.MaskCollection.names <- function(x) { if (S4Vectors:::anyMissing(names(x))) return("the names must be non-NA strings") NULL } .valid.MaskCollection.desc <- function(x) { if (!is.character(x@desc)) return("the 'desc' slot must contain a character vector") if (is.null(desc(x))) return(NULL) if (S4Vectors:::anyMissing(desc(x))) return("the descriptions must be non-NA strings") if (length(desc(x)) != length(x)) return("number of descriptions and number of elements differ") NULL } .valid.MaskCollection <- function(x) { ## The 'width' slot needs to be checked separately and we must return ## if it's invalid. This is because .valid.MaskCollection.nir_list() ## won't work properly if 'x@width' is NA. problems <- .valid.MaskCollection.width(x) if (!is.null(problems)) return(problems) c(.valid.MaskCollection.nir_list(x), .valid.MaskCollection.active(x), .valid.MaskCollection.names(x), .valid.MaskCollection.desc(x)) } setValidity2("MaskCollection", .valid.MaskCollection) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The safe and user-friendly "Mask" constructor. ### Mask <- function(mask.width, start=NULL, end=NULL, width=NULL) { nir <- asNormalIRanges(IRanges(start=start, end=end, width=width), force=FALSE) new2("MaskCollection", nir_list=list(nir), width=S4Vectors:::numeric2integer(mask.width), active=TRUE, check=FALSE) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "max" and "min" methods. ### setMethod("max", "MaskCollection", function(x, ..., na.rm) { if (length(x) == 0) return(integer(0)) sapply(nir_list(x), max) } ) setMethod("min", "MaskCollection", function(x, ..., na.rm) { if (length(x) == 0) return(integer(0)) sapply(nir_list(x), min) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "maskedwidth" and "maskedratio" generics and methods. ### setGeneric("maskedwidth", function(x) standardGeneric("maskedwidth")) setMethod("maskedwidth", "MaskCollection", function(x) { nir_list <- nir_list(x) if (length(nir_list) == 0) integer(0) else sapply(nir_list, function(nir) sum(width(nir))) } ) setGeneric("maskedratio", function(x) standardGeneric("maskedratio")) setMethod("maskedratio", "MaskCollection", function(x) maskedwidth(x) / width(x)) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Subsetting. ### setMethod("getListElement", "MaskCollection", function(x, i, exact=TRUE) { i <- normalizeDoubleBracketSubscript(i, x, exact=exact, error.if.nomatch=TRUE) nir_list(x)[[i]] } ) ### Always behaves like an endomorphism (i.e. ignores the 'drop' argument and ### behaves like if it was actually set to FALSE). setMethod("extractROWS", "MaskCollection", function(x, i) { i <- normalizeSingleBracketSubscript(i, x, as.NSBS=TRUE) if (anyDuplicated(i)) stop("subscript would generate duplicated elements") slot(x, "nir_list", check=FALSE) <- extractROWS(nir_list(x), i) slot(x, "active", check=FALSE) <- extractROWS(active(x), i) if (!is.null(names(x))) slot(x, "NAMES", check=FALSE) <- extractROWS(names(x), i) if (!is.null(desc(x))) slot(x, "desc", check=FALSE) <- extractROWS(desc(x), i) mcols(x) <- extractROWS(mcols(x), i) x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "append" method. ### ### TODO: Be more consistent with "[" which doesn't allow subscripts with ### duplicated positive values in order to make it harder for the user to ### produce a MaskCollection object with duplicated names. ### The "append" method below makes this too easy (with append(x, x)). ### .append.names.or.desc <- function(nm1, l1, nm2, l2, after) { if (is.null(nm1) && is.null(nm2)) return(as.character(NA)) if (is.null(nm1)) nm1 <- rep.int("", l1) if (is.null(nm2)) nm2 <- rep.int("", l2) append(nm1, nm2, after=after) } setMethod("append", c("MaskCollection", "MaskCollection"), function(x, values, after=length(x)) { if (width(values) != width(x)) stop("'x' and 'values' must have the same width") if (!isSingleNumber(after)) stop("'after' must be a single number") if (length(values) == 0) return(x) ans_nir_list <- append(nir_list(x), nir_list(values), after=after) ans_active <- append(active(x), active(values), after=after) l1 <- length(x) l2 <- length(values) ans_NAMES <- .append.names.or.desc(names(x), l1, names(values), l2, after) ans_desc <- .append.names.or.desc(desc(x), l1, desc(values), l2, after) ## This transformation must be atomic. x@nir_list <- ans_nir_list x@active <- ans_active x@NAMES <- ans_NAMES x@desc <- ans_desc x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### collapse() ### setGeneric("collapse", function(x) standardGeneric("collapse")) ### Always return a MaskCollection object of length 1 where the mask is active. setMethod("collapse", "MaskCollection", function(x) { keep_it <- active(x) if (!all(keep_it)) x <- x[keep_it] if (length(x) == 1) return(x) nir_list <- nir_list(x) if (length(nir_list) == 0) { nir1 <- new("NormalIRanges") } else { start1 <- unlist(lapply(nir_list, start)) width1 <- unlist(lapply(nir_list, width)) ranges <- new2("IRanges", start=start1, width=width1, check=FALSE) nir1 <- asNormalIRanges(ranges, force=TRUE) } ## This transformation must be atomic. x@nir_list <- list(nir1) x@active <- TRUE x@NAMES <- as.character(NA) x@desc <- as.character(NA) x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### ### From a MaskCollection object to a NormalIRanges object. setAs("MaskCollection", "NormalIRanges", function(from) collapse(from)[[1L]] ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "show" method. ### MaskCollection.show_frame <- function(x) { lx <- length(x) cat("masks:") if (lx == 0) { cat(" NONE\n") } else { cat("\n") ## Explictely specify 'row.names=NULL' otherwise data.frame() will ## try to use the names of the first component that has suitable ## names, which could be 'active(x)' (3rd component) if 'x' has names. frame <- data.frame(maskedwidth=maskedwidth(x), maskedratio=maskedratio(x), active=active(x), row.names=NULL, check.names=FALSE) frame$names <- names(x) frame$desc <- desc(x) show(frame) if (lx >= 2) { margin <- format("", width=nchar(as.character(lx))) cat("all masks together:\n") mask0 <- collapse(`active<-`(x, TRUE)) frame <- data.frame(maskedwidth=maskedwidth(mask0), maskedratio=maskedratio(mask0), check.names=FALSE) row.names(frame) <- margin show(frame) if (sum(active(x)) < lx) { cat("all active masks together:\n") mask1 <- collapse(x) frame <- data.frame(maskedwidth=maskedwidth(mask1), maskedratio=maskedratio(mask1), check.names=FALSE) row.names(frame) <- margin show(frame) } } } } setMethod("show", "MaskCollection", function(object) { lo <- length(object) cat(class(object), " of length ", lo, " and width ", width(object), "\n", sep="") MaskCollection.show_frame(object) } ) IRanges/R/NCList-class.R0000644000175100017510000003761512607265143015727 0ustar00biocbuildbiocbuild### ========================================================================= ### NCList and NCLists objects ### ------------------------------------------------------------------------- ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### An S4 implementation of Nested Containment List (NCList). ### ### We deliberately do NOT extend IRanges. setClass("NCList", contains="Ranges", representation( nclist="integer", ranges="IRanges" ) ) setMethod("ranges", "NCList", function(x, use.mcols=FALSE) { if (!isTRUEorFALSE(use.mcols)) stop("'use.mcols' must be TRUE or FALSE") ans <- x@ranges if (use.mcols) mcols(ans) <- mcols(x) ans } ) setMethod("length", "NCList", function(x) length(ranges(x))) setMethod("names", "NCList", function(x) names(ranges(x))) setMethod("start", "NCList", function(x, ...) start(ranges(x))) setMethod("end", "NCList", function(x, ...) end(ranges(x))) setMethod("width", "NCList", function(x) width(ranges(x))) setAs("NCList", "IRanges", function(from) ranges(from, use.mcols=TRUE)) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### .shift_ranges_to_first_circle() and ### .shift_ranges_in_groups_to_first_circle() ### ### TODO: Move to intra-range-methods.R, rename (e.g. shiftToFirstCircle()), ### make it a generic with methods for IRanges and IRangesList, export, and ### document. ### ### Returns a single integer. .normarg_circle.length1 <- function(circle.length) { msg <- "'circle.length' must be a single positive integer or NA" if (!isSingleNumberOrNA(circle.length)) stop(msg) if (!is.integer(circle.length)) circle.length <- as.integer(circle.length) if (!is.na(circle.length) && circle.length <= 0L) stop(msg) circle.length } ### Returns an integer vector of length 'x_len'. .normarg_circle.length2 <- function(circle.length, x_len, what) { msg <- c("'circle.length' must be an integer vector ", "with positive or NA values") if (!is.atomic(circle.length)) stop(msg) if (!(length(circle.length) == 1L || length(circle.length) == x_len)) stop("'circle.length' must have length 1 or length of ", what) all_NAs <- all(is.na(circle.length)) if (!(all_NAs || is.numeric(circle.length))) stop(msg) if (!is.integer(circle.length)) circle.length <- as.integer(circle.length) if (!all_NAs && min(circle.length, na.rm=TRUE) <= 0L) stop(msg) if (length(circle.length) == x_len) return(circle.length) rep.int(circle.length, x_len) } ### 'circle.length' assumed to have length 1 or length of 'x'. .shift_ranges_to_first_circle <- function(x, circle.length) { if (all(is.na(circle.length))) return(x) x_start0 <- start(x) - 1L # 0-based start x_shift0 <- x_start0 %% circle.length - x_start0 x_shift0[is.na(x_shift0)] <- 0L shift(x, x_shift0) } ### 'length(circle.length)' assumed to be >= 'length(x_groups)'. .shift_ranges_in_groups_to_first_circle <- function(x, x_groups, circle.length) { circle.length <- head(circle.length, n=length(x_groups)) if (all(is.na(circle.length))) return(x) unlisted_groups <- unlist(x_groups, use.names=FALSE) circle_len <- rep.int(NA_integer_, length(x)) circle_len[unlisted_groups + 1L] <- rep.int(circle.length, elementLengths(x_groups)) .shift_ranges_to_first_circle(x, circle_len) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### NCList constructor ### ### Returns an external pointer to the NCList C struct. .NCList_xp <- function(x_start, x_end, x_subset) { ans <- .Call2("NCList_new", PACKAGE="IRanges") reg.finalizer(ans, function(e) .Call("NCList_free", e, PACKAGE="IRanges") ) .Call2("NCList_build", ans, x_start, x_end, x_subset, PACKAGE="IRanges") } .nclist <- function(x_start, x_end, x_subset=NULL) { nclist_xp <- .NCList_xp(x_start, x_end, x_subset) .Call2("new_NCListSXP_from_NCList", nclist_xp, PACKAGE="IRanges") } NCList <- function(x, circle.length=NA_integer_) { if (!is(x, "Ranges")) stop("'x' must be a Ranges object") if (!is(x, "IRanges")) x <- as(x, "IRanges") ans_mcols <- mcols(x) mcols(x) <- NULL circle.length <- .normarg_circle.length1(circle.length) x <- .shift_ranges_to_first_circle(x, circle.length) x_nclist <- .nclist(start(x), end(x)) new2("NCList", nclist=x_nclist, ranges=x, elementMetadata=ans_mcols, check=FALSE) } setAs("Ranges", "NCList", function(from) NCList(from)) ### NOT exported. print_NCList <- function(x) { if (!is(x, "NCList")) stop("'x' must be an NCList object") .Call2("NCListSXP_print", x@nclist, start(x@ranges), end(x@ranges), PACKAGE="IRanges") invisible(NULL) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### findOverlaps_NCList() ### ### NOT exported. findOverlaps_NCList <- function(query, subject, min.score=1L, type=c("any", "start", "end", "within", "extend", "equal"), select=c("all", "first", "last", "arbitrary", "count"), circle.length=NA_integer_) { if (!(is(query, "Ranges") && is(subject, "Ranges"))) stop("'query' and 'subject' must be Ranges objects") if (!isSingleNumber(min.score)) stop("'min.score' must be a single integer") if (!is.integer(min.score)) min.score <- as.integer(min.score) type <- match.arg(type) select <- match.arg(select) circle.length <- .normarg_circle.length1(circle.length) if (is(subject, "NCList")) { nclist <- subject@nclist nclist_is_q <- FALSE query <- .shift_ranges_to_first_circle(query, circle.length) } else if (is(query, "NCList")) { nclist <- query@nclist nclist_is_q <- TRUE subject <- .shift_ranges_to_first_circle(subject, circle.length) } else { ## We'll do "on-the-fly preprocessing". nclist <- NULL nclist_is_q <- NA query <- .shift_ranges_to_first_circle(query, circle.length) subject <- .shift_ranges_to_first_circle(subject, circle.length) } .Call2("NCList_find_overlaps", start(query), end(query), start(subject), end(subject), nclist, nclist_is_q, min.score, type, select, circle.length, PACKAGE="IRanges") } ### NOT exported. min_overlap_score <- function(maxgap=0L, minoverlap=1L, type="any") { ## Check and normalize 'maxgap'. if (!isSingleNumber(maxgap)) stop("'maxgap' must be a single integer") if (!is.integer(maxgap)) maxgap <- as.integer(maxgap) ## Check and normalize 'minoverlap'. if (!isSingleNumber(minoverlap)) stop("'minoverlap' must be a single integer") if (!is.integer(minoverlap)) minoverlap <- as.integer(minoverlap) if (maxgap < 0L) stop("'maxgap' cannot be negative") if (minoverlap < 0L) stop("'minoverlap' cannot be negative") if (maxgap != 0L) { if (minoverlap > 1L) stop("'minoverlap' must be <= 1 when 'maxgap' is not 0") if (type %in% c("within", "equal")) { warning(wmsg( "With the new findOverlaps/countOverlaps implementation based ", "on Nested Containment Lists, 'maxgap' has no special meaning ", "when 'type' is set to \"within\" or \"equal\". Note that ", "this is a change with respect to the old implementation ", "based on Interval Trees. See ?NCList for more information ", "about this change and other differences between the new and ", "old implementations. Use the 'algorithm' argument to switch ", "between the 2 implementations." )) } } minoverlap - maxgap } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Representation of a list of NCList objects ### setClass("NCLists", contains="RangesList", representation( nclists="list", rglist="CompressedIRangesList" ), prototype( elementType="NCList" ) ) setMethod("parallelSlotNames", "NCLists", function(x) c("nclists", "rglist", callNextMethod()) ) ### TODO: Move rglist() generic from GenomicRanges to IRanges #setMethod("rglist", "NCLists", function(x, ...) x@ranges) setMethod("ranges", "NCLists", function(x, use.mcols=FALSE) { if (!isTRUEorFALSE(use.mcols)) stop("'use.mcols' must be TRUE or FALSE") ans <- x@rglist if (use.mcols) mcols(ans) <- mcols(x) ans } ) setMethod("length", "NCLists", function(x) length(ranges(x))) setMethod("names", "NCLists", function(x) names(ranges(x))) setMethod("start", "NCLists", function(x, ...) start(ranges(x))) setMethod("end", "NCLists", function(x, ...) end(ranges(x))) setMethod("width", "NCLists", function(x) width(ranges(x))) setMethod("elementLengths", "NCLists", function(x) elementLengths(ranges(x))) setMethod("getListElement", "NCLists", function (x, i, exact=TRUE) { i <- normalizeDoubleBracketSubscript(i, x, exact=exact, error.if.nomatch=TRUE) new2("NCList", nclist=x@nclists[[i]], ranges=x@rglist[[i]], check=FALSE) } ) setAs("NCLists", "CompressedIRangesList", function(from) ranges(from, use.mcols=TRUE) ) setAs("NCLists", "IRangesList", function(from) ranges(from, use.mcols=TRUE) ) .extract_groups_from_RangesList <- function(x) { x_partitioning <- PartitioningByEnd(x) relist(as.integer(x_partitioning) - 1L, x_partitioning) } .nclists <- function(x, x_groups) { x_start <- start(x) x_end <- end(x) lapply(x_groups, function(group) .nclist(x_start, x_end, x_subset=group)) } ### NCLists constructor. NCLists <- function(x, circle.length=NA_integer_) { if (!is(x, "RangesList")) stop("'x' must be a RangesList object") if (!is(x, "CompressedIRangesList")) x <- as(x, "CompressedIRangesList") ans_mcols <- mcols(x) mcols(x) <- NULL unlisted_x <- unlist(x, use.names=FALSE) x_groups <- .extract_groups_from_RangesList(x) circle.length <- .normarg_circle.length2(circle.length, length(x_groups), "'x'") unlisted_x <- .shift_ranges_in_groups_to_first_circle( unlisted_x, x_groups, circle.length) x <- relist(unlisted_x, x) x_nclists <- .nclists(unlisted_x, x_groups) new2("NCLists", nclists=x_nclists, rglist=x, elementMetadata=ans_mcols, check=FALSE) } setAs("RangesList", "NCLists", function(from) NCLists(from)) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### NCList_find_overlaps_in_groups() ### ### NOT exported. Workhorse behind findOverlaps_NCLists() below and behind ### GenomicRanges:::findOverlaps_GNCList(). NCList_find_overlaps_in_groups <- function( q, q_space, q_groups, s, s_space, s_groups, nclists, nclist_is_q, min.score, type, select, circle.length) { if (!(is(q, "Ranges") && is(s, "Ranges"))) stop("'q' and 's' must be Ranges object") if (!is(q_groups, "CompressedIntegerList")) stop("'q_groups' must be a CompressedIntegerList object") if (!is(s_groups, "CompressedIntegerList")) stop("'s_groups' must be a CompressedIntegerList object") q_circle_len <- circle.length q_circle_len[which(nclist_is_q)] <- NA_integer_ q <- .shift_ranges_in_groups_to_first_circle(q, q_groups, q_circle_len) s_circle_len <- circle.length s_circle_len[which(!nclist_is_q)] <- NA_integer_ s <- .shift_ranges_in_groups_to_first_circle(s, s_groups, s_circle_len) .Call2("NCList_find_overlaps_in_groups", start(q), end(q), q_space, q_groups, start(s), end(s), s_space, s_groups, nclists, nclist_is_q, min.score, type, select, circle.length, PACKAGE="IRanges") } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### findOverlaps_NCLists() ### .split_and_remap_hits <- function(all_hits, query, subject, select) { ## Compute list element lengths and offsets for 'query'. query_partitioning <- PartitioningByEnd(query) query_eltlens <- width(query_partitioning) query_offsets <- start(query_partitioning) - 1L ## Compute list element lengths and offsets for 'subject'. subject_partitioning <- PartitioningByEnd(subject) subject_eltlens <- width(subject_partitioning) subject_offsets <- start(subject_partitioning) - 1L if (select != "all") { ans <- head(relist(all_hits, query), n=length(subject)) if (select != "count") ans <- ans - head(subject_offsets, n=length(ans)) return(ans) } q_hits <- queryHits(all_hits) query_breakpoints <- end(query_partitioning) h_skeleton <- PartitioningByEnd(findInterval(query_breakpoints, q_hits)) lapply(seq_len(min(length(query), length(subject))), function(i) { hits <- all_hits[h_skeleton[[i]]] hits@queryHits <- hits@queryHits - query_offsets[[i]] hits@subjectHits <- hits@subjectHits - subject_offsets[[i]] hits@queryLength <- query_eltlens[[i]] hits@subjectLength <- subject_eltlens[[i]] hits }) } ### NOT exported. ### Return an ordinary list of: ### (a) Hits objects if 'select' is "all". In that case the list has the ### length of the shortest of 'query' or 'subject'. ### (b) integer vectors if 'select' is not "all". In that case the list is ### parallel to and has the same shape as 'query'. findOverlaps_NCLists <- function(query, subject, min.score=1L, type=c("any", "start", "end", "within", "extend", "equal"), select=c("all", "first", "last", "arbitrary", "count"), circle.length=NA_integer_) { if (!(is(query, "RangesList") && is(subject, "RangesList"))) stop("'query' and 'subject' must be RangesList objects") if (!isSingleNumber(min.score)) stop("'min.score' must be a single integer") if (!is.integer(min.score)) min.score <- as.integer(min.score) type <- match.arg(type) select <- match.arg(select) circle.length <- .normarg_circle.length2(circle.length, max(length(query), length(subject)), "longest of 'query' or 'subject'") if (is(subject, "NCLists")) { nclists <- subject@nclists nclist_is_q <- rep.int(FALSE, length(nclists)) subject <- subject@rglist } else if (is(query, "NCLists")) { nclists <- query@nclists nclist_is_q <- rep.int(TRUE, length(nclists)) query <- query@rglist } else { ## We'll do "on-the-fly preprocessing". NG <- min(length(query), length(subject)) nclists <- vector(mode="list", length=NG) nclist_is_q <- rep.int(NA, length(nclists)) } if (!is(query, "CompressedIRangesList")) query <- as(query, "CompressedIRangesList") q <- unlist(query, use.names=FALSE) q_groups <- .extract_groups_from_RangesList(query) if (!is(subject, "CompressedIRangesList")) subject <- as(subject, "CompressedIRangesList") s <- unlist(subject, use.names=FALSE) s_groups <- .extract_groups_from_RangesList(subject) all_hits <- NCList_find_overlaps_in_groups( q, NULL, q_groups, s, NULL, s_groups, nclists, nclist_is_q, min.score, type, select, circle.length) .split_and_remap_hits(all_hits, query, subject, select) } IRanges/R/RDApplyParams-class.R0000644000175100017510000001700312607265143017237 0ustar00biocbuildbiocbuild### ========================================================================= ### RDApplyParams objects ### ------------------------------------------------------------------------- setClassUnion("functionORNULL", c("function", "NULL")) setClass("RDApplyParams", representation(rangedData = "RangedData", applyFun = "function", applyParams = "list", ##excludePattern = "character", filterRules = "FilterRules", simplify = "logical", reducerFun = "functionORNULL", reducerParams = "list", iteratorFun = "function"), prototype(applyFun = function(rd) NULL, simplify = FALSE, iteratorFun = sapply)) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor methods. ### setGeneric("rangedData", function(x, ...) standardGeneric("rangedData")) setMethod("rangedData", "RDApplyParams", function(x) x@rangedData) setGeneric("rangedData<-", function(x, ..., value) standardGeneric("rangedData<-")) setReplaceMethod("rangedData", "RDApplyParams", function(x, value) { x@rangedData <- value validObject(x) x }) setGeneric("applyFun", function(x, ...) standardGeneric("applyFun")) setMethod("applyFun", "RDApplyParams", function(x) x@applyFun) setGeneric("applyFun<-", function(x, ..., value) standardGeneric("applyFun<-")) setReplaceMethod("applyFun", "RDApplyParams", function(x, value) { x@applyFun <- value validObject(x) x }) setGeneric("applyParams", function(x, ...) standardGeneric("applyParams")) setMethod("applyParams", "RDApplyParams", function(x) x@applyParams) setGeneric("applyParams<-", function(x, ..., value) standardGeneric("applyParams<-")) setReplaceMethod("applyParams", "RDApplyParams", function(x, value) { x@applyParams <- value validObject(x) x }) ## setGeneric("excludePattern", ## function(x, ...) standardGeneric("excludePattern")) ## setMethod("excludePattern", "RDApplyParams", function(x) x@excludePattern) ## setGeneric("excludePattern<-", ## function(x, ..., value) standardGeneric("excludePattern<-")) ## setReplaceMethod("excludePattern", "RDApplyParams", function(x, value) { ## x@excludePattern <- value ## validObject(x) ## x ## }) setMethod("filterRules", "RDApplyParams", function(x) x@filterRules) setGeneric("filterRules<-", function(x, ..., value) standardGeneric("filterRules<-")) setReplaceMethod("filterRules", "RDApplyParams", function(x, value) { x@filterRules <- value validObject(x) x }) setGeneric("simplify", function(x, ...) standardGeneric("simplify")) setMethod("simplify", "RDApplyParams", function(x) x@simplify) setGeneric("simplify<-", function(x, ..., value) standardGeneric("simplify<-")) setReplaceMethod("simplify", "RDApplyParams", function(x, value) { x@simplify <- value validObject(x) x }) setGeneric("reducerFun", function(x, ...) standardGeneric("reducerFun")) setMethod("reducerFun", "RDApplyParams", function(x) x@reducerFun) setGeneric("reducerFun<-", function(x, ..., value) standardGeneric("reducerFun<-")) setReplaceMethod("reducerFun", "RDApplyParams", function(x, value) { x@reducerFun <- value validObject(x) x }) setGeneric("reducerParams", function(x, ...) standardGeneric("reducerParams")) setMethod("reducerParams", "RDApplyParams", function(x) x@reducerParams) setGeneric("reducerParams<-", function(x, ..., value) standardGeneric("reducerParams<-")) setReplaceMethod("reducerParams", "RDApplyParams", function(x, value) { x@reducerParams <- value validObject(x) x }) setGeneric("iteratorFun", function(x, ...) standardGeneric("iteratorFun")) setMethod("iteratorFun", "RDApplyParams", function(x) x@iteratorFun) setGeneric("iteratorFun<-", function(x, ..., value) standardGeneric("iteratorFun<-")) setReplaceMethod("iteratorFun", "RDApplyParams", function(x, value) { x@iteratorFun <- value validObject(x) x }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor ### ## Simple convenience constructor around RDApplyParams's initializer RDApplyParams <- function(rangedData, applyFun, applyParams, #excludePattern, filterRules, simplify, reducerFun, reducerParams, iteratorFun) { params <- new("RDApplyParams", applyFun = applyFun, applyParams = applyParams, filterRules = filterRules, simplify = simplify, reducerFun = reducerFun, reducerParams = reducerParams, iteratorFun = iteratorFun) params@rangedData <- rangedData ## set rangedData last for efficiency params } ## get the defaults from the class prototype formals(RDApplyParams) <- structure(lapply(slotNames("RDApplyParams"), function(x) { slot(new("RDApplyParams"), x) }), names = slotNames("RDApplyParams")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### .valid.RDApplyParams.applyFun <- function(x) { formals <- formals(applyFun(x)) if (anyDuplicated(names(applyParams(x)))) "apply parameters have duplicated names" else if (!("..." %in% names(formals))) { if (length(formals) < (length(applyParams(x)) + 1)) "'applyFun' does not take enough parameters" else { nms <- names(applyParams(x)) if (!is.null(nms) && !all(nms[nchar(nms) > 0] %in% names(formals))) "mismatch between names of 'applyParams' and formals of 'applyFun'" else NULL } } else NULL } ## .valid.RDApplyParams.excludePattern <- function(x) { ## if (!isSingleString(excludePattern(x))) ## "'excludePattern' must be a single, non-missing string" ## else NULL ## } .valid.RDApplyParams.simplify <- function(x) { if (!isTRUEorFALSE(simplify(x))) "'simplify' must be TRUE or FALSE" else if (!is.null(reducerFun(x)) && simplify(x)) "'simplify' must be FALSE for there to be a 'reducerFun'" else NULL } .valid.RDApplyParams.reducerParams <- function(x) { if (length(reducerParams(x)) && is.null(reducerFun(x))) return("there must be a 'reducerFun' for there to be 'reducerParams'") else if (anyDuplicated(names(reducerParams(x)))) return("reducer parameters have duplicated names") else if (!is.null(reducerFun(x))) { formals <- formals(reducerFun(x)) if (!("..." %in% names(formals))) { if (length(formals) < (length(reducerParams(x)) + 1)) return("'reducerFun' does not take enough parameters") else { nms <- names(reducerParams(x)) if (!is.null(nms) && !all(nms[nchar(nms) > 0] %in% names(formals)) && !("..." %in% names(formals))) return("mismatch b/w 'reducerParams' names and 'reducerFun' formals") } } } NULL } .valid.RDApplyParams.iteratorFun <- function(x) { formals <- formals(iteratorFun(x)) if (length(formals) < 2) "'iteratorFun' must take at least two parameters" else if ("simplify" %in% names(formals) && length(formals) < 3) "'iteratorFun' must take at least three parameters if one is 'simplify'" else NULL } .valid.RDApplyParams <- function(x) c(##.valid.RDApplyParams.rangedData(x), .valid.RDApplyParams.applyFun(x), ##.valid.RDApplyParams.excludePattern(x), .valid.RDApplyParams.simplify(x), .valid.RDApplyParams.reducerParams(x), .valid.RDApplyParams.iteratorFun(x)) setValidity2("RDApplyParams", .valid.RDApplyParams) IRanges/R/RangedData-class.R0000644000175100017510000010336012607265143016554 0ustar00biocbuildbiocbuild### ========================================================================= ### RangedData objects ### ------------------------------------------------------------------------- ## For keeping data with your ranges ## There are two design aims: ## 1) Efficiency when data is large (i.e. apply by chromosome) ## 2) Convenience when data is not so large (i.e. unrolling the data) ## The ranges are stored in a RangesList, while the data is stored in ## a SplitDataFrameList. The RangesList is uncompressed, because ## users will likely want to apply over each Ranges separately, as ## they are usually in separate spaces. Also, it is difficult to ## compress RangesLists, as lists containing Views or IntervalTrees ## are uncompressible. The SplitDataFrameList should be compressed, ## because it's cheap to create from a split factor and, more ## importantly, cheap to get and set columns along the entire dataset, ## which is common. Usually the data columns are atomic vectors and ## thus trivially compressed. It does, however, incur a slight ## performance penalty when applying over the RangedData. setClass("RangedData", contains = c("DataTable", "List"), representation(ranges = "RangesList", values = "SplitDataFrameList"), prototype = prototype(ranges = new("SimpleRangesList"), values = new("CompressedSplitDataFrameList"))) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor methods. ### setMethod("values", "RangedData", function(x) x@values) setReplaceMethod("values", "RangedData", function(x, value) { if (extends(class(value), "SplitDataFrameList")) { if (!identical(elementLengths(values(x)), elementLengths(value))) stop("'value' must have same elementLengths as current 'values'") } else if (extends(class(value), "DataFrame")) { value <- split(value, space(x)) } else { stop("'value' must extend class SplitDataFrameList or DataFrame") } if (is.null(rownames(value)) && !is.null(rownames(x))) rownames(value) <- rownames(x) else if (!identical(rownames(value), rownames(values(x)))) stop("rownames of 'value', if non-NULL, must match the ", "rownames of 'x'") x@values <- value x }) setMethod("ranges", "RangedData", function(x) x@ranges) setReplaceMethod("ranges", "RangedData", function(x, value) { if (extends(class(value), "RangesList")) { if (!identical(lapply(ranges(x), names), lapply(value, names))) stop("'value' must have same length and names as current 'ranges'") } else if (extends(class(value), "IRanges")) { value <- split(value, space(x)) } else { stop("'value' must extend class RangesList or IRanges") } x@ranges <- value x }) ## range delegates setMethod("start", "RangedData", function(x) { start(unlist(ranges(x), use.names=FALSE)) }) setMethod("end", "RangedData", function(x) { end(unlist(ranges(x), use.names=FALSE)) }) setMethod("width", "RangedData", function(x) { width(unlist(ranges(x), use.names=FALSE)) }) setReplaceMethod("start", "RangedData", function(x, ..., value) { start(ranges(x), ...) <- value x }) setReplaceMethod("end", "RangedData", function(x, ..., value) { end(ranges(x), ...) <- value x }) setReplaceMethod("width", "RangedData", function(x, ..., value) { width(ranges(x), ...) <- value x }) setMethod("length", "RangedData", function(x) length(ranges(x))) setMethod("names", "RangedData", function(x) names(ranges(x))) setReplaceMethod("names", "RangedData", function(x, value) { if (!is.null(value) && !is.character(value)) stop("'value' must be NULL or a character vector") names(x@ranges) <- value names(x@values) <- value x }) setMethod("elementLengths", "RangedData", function(x) elementLengths(ranges(x))) setMethod("space", "RangedData", function(x) space(ranges(x))) setMethod("universe", "RangedData", function(x) universe(ranges(x))) setReplaceMethod("universe", "RangedData", function(x, value) { universe(x@ranges) <- value x }) setMethod("score", "RangedData", function(x) { score <- x[["score"]] ## if (is.null(score) && ncol(x) > 0 && is.numeric(x[[1L]])) ## score <- x[[1L]] score }) setReplaceMethod("score", "RangedData", function(x, value) { if (!is.numeric(value)) stop("score must be numeric") if (length(value) != nrow(x)) stop("number of scores must equal the number of rows") x[["score"]] <- value x }) ## values delegates setMethod("nrow", "RangedData", function(x) { sum(nrow(values(x))) }) setMethod("ncol", "RangedData", function(x) { ncol(values(x))[[1L]] }) setMethod("rownames", "RangedData", function(x, do.NULL = TRUE, prefix = "row") { rn <- unlist(rownames(values(x), do.NULL = do.NULL, prefix = prefix), use.names=FALSE) if (length(rn) == 0) rn <- NULL rn }) setMethod("colnames", "RangedData", function(x, do.NULL = TRUE, prefix = "col") { if (length(x) == 0) character() else colnames(values(x), do.NULL = do.NULL, prefix = prefix)[[1L]] }) setReplaceMethod("rownames", "RangedData", function(x, value) { if (!is.null(value)) { if (length(value) != nrow(x)) { stop("invalid 'row.names' length") } else { if (!is.character(value)) value <- as.character(value) ends <- cumsum(elementLengths(x)) value <- new("CompressedCharacterList", unlistData = value, partitioning = PartitioningByEnd(ends)) } } ranges <- ranges(x) for(i in seq_len(length(ranges))) { names(ranges[[i]]) <- value[[i]] } x@ranges <- ranges rownames(x@values) <- value x }) setReplaceMethod("colnames", "RangedData", function(x, value) { colnames(x@values) <- value x }) setMethod("columnMetadata", "RangedData", function(x) { columnMetadata(values(x)) }) setReplaceMethod("columnMetadata", "RangedData", function(x, value) { columnMetadata(values(x)) <- value x }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### .valid.RangedData.ranges <- function(x) { if (!identical(lapply(ranges(x), length), lapply(values(x), nrow))) "'ranges' and 'values' must be of the same length and have the same names" else if (!identical(unlist(lapply(ranges(x), names), use.names=FALSE), rownames(x))) "the names of the ranges must equal the rownames" else NULL } .valid.RangedData.names <- function(x) { nms <- names(x) if (length(nms) != length(x)) "length(names(x)) must equal length(x)" else if (!is.character(nms) || S4Vectors:::anyMissing(nms) || anyDuplicated(nms)) "names(x) must be a character vector without any NA's or duplicates" else NULL } .valid.RangedData <- function(x) { c(.valid.RangedData.ranges(x), .valid.RangedData.names(x)) } setValidity2("RangedData", .valid.RangedData) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor. ### ## creates a single-element RangedData (unless splitter (space) is specified) RangedData <- function(ranges = IRanges(), ..., space = NULL, universe = NULL) { hasDots <- (((nargs() - !missing(space)) - !missing(universe)) > 1) if (!is.null(universe) && !isSingleString(universe)) stop("'universe' must be a single string") if (is(ranges, "RangesList")) { if (!is.null(space)) warning("since 'class(ranges)' extends RangesList, 'space' argument is ignored") if (is.null(names(ranges))) names(ranges) <- as.character(seq_len(length(ranges))) space <- Rle(factor(names(ranges), levels = names(ranges)), elementLengths(ranges)) N <- sum(elementLengths(ranges)) NAMES <- unlist(lapply(ranges, names), use.names=FALSE) } else { if (!is(ranges, "Ranges")) { coerced <- try(as(ranges, "RangedData"), silent=TRUE) if (is(coerced, "RangedData")) return(coerced) stop("'ranges' must be a Ranges or directly coercible to RangedData") } N <- length(ranges) NAMES <- names(ranges) if (is.null(space)) { if (N == 0) space <- Rle(factor()) else space <- Rle(factor("1")) } else if (!is(space, "Rle")) { space <- Rle(space) } if (!is.factor(runValue(space))) runValue(space) <- factor(runValue(space)) if (length(space) != N) { if (length(space) == 0L) stop("'space' is a 0-length vector but length of 'ranges' is > 0") ## We make an exception to the "length(space) must be <= N" rule when ## N != 0L so we can support the direct creation of RangedData objects ## with 0 rows across 1 or more user-specified spaces like in: ## RangedData(ranges=IRanges(), space=letters) if (N != 0L && length(space) > N) stop("length of 'space' greater than length of 'ranges'") if (N %% length(space) != 0) stop("length of 'ranges' not a multiple of 'space' length") space <- rep(space, length.out = N) } if (!is(ranges, "IRanges")) ranges <- as(ranges, "IRanges") ranges <- split(ranges, space) } universe(ranges) <- universe if (hasDots) { args <- list(...) if (length(args) == 1L && is(args[[1L]], "SplitDataFrameList")) { values <- unlist(args[[1L]], use.names=FALSE) } else { values <- DataFrame(...) } } else values <- new2("DataFrame", nrows = N, check=FALSE) if (N != nrow(values)) { if (nrow(values) > N) stop("length of value(s) in '...' greater than length of 'ranges'") if (nrow(values) == 0 || N %% nrow(values) != 0) stop("length of 'ranges' not a multiple of length of value(s) in '...'") rind <- S4Vectors:::recycleVector(seq_len(nrow(values)), N) values <- values[rind,,drop=FALSE] } rownames(values) <- NAMES ## ensure these are identical values <- split(values, space) new2("RangedData", ranges = ranges, values = values, check=FALSE) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Subsetting. ### ## The extraction operator delegates to the values (extracts columns) setMethod("[[", "RangedData", function(x, i, j, ...) { dotArgs <- list(...) if (length(dotArgs) > 0) dotArgs <- dotArgs[names(dotArgs) != "exact"] if (!missing(j) || length(dotArgs) > 0) stop("invalid subsetting") if (missing(i)) stop("subscript is missing") if (!is.character(i) && !is.numeric(i)) stop("invalid subscript type") if (length(i) < 1L) stop("attempt to select less than one element") if (length(i) > 1L) stop("attempt to select more than one element") if (is.numeric(i) && !is.na(i) && (i < 1L || i > ncol(x))) stop("subscript out of bounds") if (is.na(i) || (is.character(i) && !(i %in% c("space", "ranges", colnames(x))))) NULL else if (i == "space") space(x) else if (i == "ranges") unlist(ranges(x), use.names=FALSE) else unlist(values(x), use.names=FALSE)[[i]] }) setReplaceMethod("[[", "RangedData", function(x, i, j,..., value) { if (!missing(j) || length(list(...)) > 0) stop("invalid subsetting") if (missing(i)) stop("subscript is missing") if (!is.character(i) && !is.numeric(i)) stop("invalid subscript type") if (length(i) < 1L) stop("attempt to select less than one element") if (length(i) > 1L) stop("attempt to select more than one element") if (is.numeric(i) && (i < 1L || i > ncol(x) + 1L)) stop("subscript out of bounds") if (i == "space") stop("cannot replace \"space\" information") if (i == "ranges") { ranges(x) <- value } else { nrx <- nrow(x) lv <- length(value) if (!is.null(value) && (nrx != lv)) { if ((nrx == 0) || (nrx %% lv != 0)) stop(paste(lv, "elements in value to replace", nrx, "elements")) else value <- rep(value, length.out = nrx) } nrows <- elementLengths(values(x)) inds <- seq_len(length(x)) spaces <- factor(rep.int(inds, nrows), inds) values <- unlist(values(x), use.names=FALSE) values[[i]] <- value x@values <- split(values, spaces) names(x@values) <- names(x) } x }) setReplaceMethod("$", "RangedData", function(x, name, value) { x[[name]] <- value x }) ### Supported index types: numeric, logical, character, NULL and missing. ## Two index modes: ## - list style ([i]): subsets by range space (e.g. chromosome) ## - matrix style ([i,j]): subsets the data frame setMethod("[", "RangedData", function(x, i, j, ..., drop=FALSE) { if (length(list(...)) > 0) stop("parameters in '...' not supported") if (missing(i) && missing(j)) return(x) checkIndex <- function(i, lx, nms) { if (!is.atomic(i)) return("invalid subscript type") if (is.numeric(i)) { if (!is.integer(i)) i <- as.integer(i) if (S4Vectors:::anyMissingOrOutside(i, upper = lx)) return("subscript contains NAs or out of bounds indices") if (S4Vectors:::anyMissingOrOutside(i, 0L, lx) && S4Vectors:::anyMissingOrOutside(i, upper = 0L)) return("negative and positive indices cannot be mixed") } else if (is.logical(i)) { if (S4Vectors:::anyMissing(i)) return("subscript contains NAs") if (length(i) > lx) return("subscript out of bounds") } else if ((is.character(i) || is.factor(i))) { if (S4Vectors:::anyMissing(i)) return("subscript contains NAs") if (S4Vectors:::anyMissing(match(i, nms))) return("mismatching names") } else if (!is.null(i)) { return("invalid subscript type") } NULL } mstyle <- nargs() > 2 if (mstyle) { ranges <- ranges(x) values <- values(x) if (!missing(j)) { prob <- checkIndex(j, ncol(x), colnames(x)) if (!is.null(prob)) stop("selecting cols: ", prob) values <- values[, j, drop=FALSE] } if (!missing(i)) { if (is(i, "RangesList")) stop("subsetting a RangedData object ", "by a RangesList subscript is not supported") if (is(i, "LogicalList")) { xeltlen <- elementLengths(ranges(x)) whichRep <- which(xeltlen != elementLengths(i)) for (k in whichRep) i[[k]] <- rep(i[[k]], length.out = xeltlen[k]) i <- unlist(i, use.names=FALSE) } else if (is(i, "IntegerList")) { itemp <- LogicalList(lapply(elementLengths(ranges(x)), rep, x = FALSE)) for (k in seq_len(length(itemp))) itemp[[k]][i[[k]]] <- TRUE i <- unlist(itemp, use.names=FALSE) } prob <- checkIndex(i, nrow(x), rownames(x)) if (!is.null(prob)) stop("selecting rows: ", prob) if (is.numeric(i) && any(i < 0)) i <- setdiff(seq(nrow(x)), -i) if (is.logical(i)) { igroup <- factor(rep.int(seq_len(length(x)), elementLengths(x)), levels = seq_len(length(x))) if (length(i) < nrow(x)) i <- rep(i, length.out = nrow(x)) } else { if (is.null(i)) i <- integer(0) if (is.factor(i)) i <- as.character(i) if (is.character(i)) { dummy <- seq_len(nrow(x)) names(dummy) <- rownames(x) i <- dummy[i] if (S4Vectors:::anyMissing(i)) ## cannot subset by NAs yet stop("invalid rownames specified") } starts <- cumsum(c(1L, head(elementLengths(x), -1))) igroup <- factor(findInterval(i, starts), levels = seq_len(length(x))) if (anyDuplicated(runValue(Rle(igroup)))) stop("cannot mix row indices from different spaces") i <- i - (starts - 1L)[as.integer(igroup)] } isplit <- split(i, igroup) names(isplit) <- names(x) ranges <- S4Vectors:::subset_List_by_List(ranges, isplit) values <- S4Vectors:::subset_List_by_List(values, isplit) if (drop) { ok <- (elementLengths(ranges) > 0) ranges <- ranges[ok] values <- values[ok] } } } else { if (!missing(i)) { prob <- checkIndex(i, length(x), names(x)) if (!is.null(prob)) stop("selecting spaces: ", prob) ranges <- ranges(x)[i] values <- values(x)[i] } } x@ranges <- ranges x@values <- values x }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Combining and splitting. ### setMethod("c", "RangedData", function(x, ..., recursive = FALSE) { if (!identical(recursive, FALSE)) stop("\"c\" method for RangedData objects ", "does not support the 'recursive' argument") if (missing(x)) rds <- unname(list(...)) else rds <- unname(list(x, ...)) rd <- rds[[1L]] if (!all(sapply(rds, is, "RangedData"))) stop("all arguments in '...' must be RangedData objects") nms <- lapply(rds, ## figure out names like 'c' on an ordinary vector function(rd) structure(logical(length(rd)), names = names(rd))) nms <- names(do.call(c, nms)) names(rds) <- NULL # critical for dispatch to work ranges <- do.call(c, lapply(rds, ranges)) values <- do.call(c, lapply(rds, values)) names(ranges) <- nms rd@ranges <- ranges names(values) <- nms rd@values <- values rd }) setMethod("split", "RangedData", function(x, f, drop = FALSE) { if (length(f) > nrow(x) || nrow(x) %% length(f) > 0) stop("nrow(x) is not a multiple of length(f)") splitInd <- split(seq_len(nrow(x)), f, drop) do.call(RangedDataList, lapply(splitInd, function(ind) x[ind,])) }) setMethod("rbind", "RangedData", function(..., deparse.level=1) { args <- unname(list(...)) rls <- lapply(args, ranges) if (!all(sapply(sapply(rls, universe), identical, universe(rls[[1L]])))) stop("All args in '...' must have the same universe") nms <- unique(unlist(lapply(args, names), use.names=FALSE)) rls <- lapply(rls, function(x) {y <- as.list(x)[nms];names(y) <- nms;y}) dfs <- lapply(args, function(x) {y <- as.list(values(x))[nms];names(y) <- nms;y}) safe.c <- function(...) { x <- list(...) do.call(c, x[!sapply(x, is.null)]) } rls <- IRangesList(do.call(Map, c(list(safe.c), rls))) safe.rbind <- function(...) { x <- list(...) do.call(rbind, x[!sapply(x, is.null)]) } dfs <- SplitDataFrameList(do.call(Map, c(list(safe.rbind), dfs))) for (i in seq_len(length(rls))) names(rls[[i]]) <- rownames(dfs[[i]]) initialize(args[[1L]], ranges = rls, values = dfs) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion ### ### The 2 functions, as.data.frame.RangesList() and ### as.data.frame.DataFrameList() are needed for as.data.frame.RangedData(). ### ### A new as.data.frame,List method was implemented in BioC 2.15 and ### is now used by all List classes. Because the RangedData class is being ### phased out, we want to retain the old behavior. In order to do that ### we have to keep these 2 helpers because as.data.frame.RangedData() ### uses old methods from both RangesList and DataFrameList. ### ### These helpers are not exported. .as.data.frame.RangesList <- function(x, row.names=NULL, optional=FALSE, ...) { if (!(is.null(row.names) || is.character(row.names))) stop("'row.names' must be NULL or a character vector") x <- as(x, "CompressedIRangesList") spaceLevels <- seq_len(length(x)) if (length(names(x)) > 0) { spaceLabels <- names(x) } else { spaceLabels <- as.character(spaceLevels) } data.frame(space = factor(rep.int(seq_len(length(x)), elementLengths(x)), levels = spaceLevels, labels = spaceLabels), as.data.frame(unlist(x, use.names = FALSE)), row.names = row.names, stringsAsFactors = FALSE) } .as.data.frame.DataFrameList <- function(x, row.names=NULL, optional=FALSE, ...) { if (!(is.null(row.names) || is.character(row.names))) stop("'row.names' must be NULL or a character vector") if (!missing(optional) || length(list(...))) warning("'optional' and arguments in '...' ignored") stacked <- stack(x) if (is.null(row.names)) row.names <- rownames(stacked) as.data.frame(stacked, row.names = row.names, optional = optional) } ### S3/S4 combo for as.data.frame.RangedData as.data.frame.RangedData <- function(x, row.names=NULL, optional=FALSE, ...) { if (!(is.null(row.names) || is.character(row.names))) stop("'row.names' must be NULL or a character vector") if (!missing(optional) || length(list(...))) warning("'optional' and arguments in '...' ignored") data.frame(.as.data.frame.RangesList(ranges(x)), .as.data.frame.DataFrameList(values(x))[-1L], row.names = row.names, stringsAsFactors = FALSE) } setMethod("as.data.frame", "RangedData",as.data.frame.RangedData) setAs("RangedData", "DataFrame", function(from) { DataFrame(as.data.frame(ranges(from)), unlist(values(from), use.names=FALSE)) }) setAs("Rle", "RangedData", function(from) { new2("RangedData", ranges = IRangesList("1" = successiveIRanges(runLength(from))), values = SplitDataFrameList("1" = DataFrame(score = runValue(from))), metadata = metadata(from), check = FALSE) }) setAs("RleList", "RangedData", function(from) { ranges <- IRangesList(lapply(from, function(x) successiveIRanges(runLength(x)))) values <- SplitDataFrameList(lapply(from, function(x) DataFrame(score = runValue(x)))) if (is.null(names(from))) { nms <- as.character(seq_len(length(from))) names(ranges) <- nms names(values) <- nms } new2("RangedData", ranges = ranges, values = values, metadata = metadata(from), elementMetadata = elementMetadata(from), check = FALSE) }) setAs("RleViewsList", "RangedData", function(from) { subject <- subject(from) from_ranges <- restrict(ranges(from), 1L, elementLengths(subject), keep.all.ranges = TRUE) ### FIXME: do we want to insert NAs for out of bounds views? score <- subject[from_ranges] score_part <- as(lapply(width(from_ranges), PartitioningByWidth), "RangesList") score_ranges <- ranges(score) ol <- findOverlaps(score_ranges, score_part) offind <- as(lapply(ol, subjectHits), "IntegerList") offset <- (start(from_ranges) - start(score_part))[offind] ranges <- shift(ranges(ol, score_ranges, score_part), offset) viewNames <- lapply(from_ranges, function(x) { if (is.null(names(x))) seq_len(length(x)) else names(x) }) RangedData(ranges, score = unlist(runValue(score), use.names = FALSE)[queryHits(ol)], view = unlist(viewNames, use.names = FALSE)[subjectHits(ol)]) }) setAs("Ranges", "RangedData", function(from) { RangedData(from) }) setAs("RangesList", "RangedData", function(from) { from_names <- names(from) if (is.null(from_names) || anyDuplicated(from_names)) stop("cannot coerce a RangesList object with no names ", "or duplicated names to a RangedData object") unlisted_from <- unlist(from, use.names=FALSE) unlisted_values <- mcols(unlisted_from) mcols(unlisted_from) <- NULL ans_ranges <- relist(unlisted_from, skeleton=from) metadata(ans_ranges) <- metadata(from) if (!is(unlisted_values, "DataFrame")) { if (!is.null(unlisted_values)) warning("could not propagate the inner metadata columns of ", "'from' (accessed with 'mcols(unlist(from))') ", "to the data columns (aka values) of the returned ", "RangedData object") unlisted_values <- new2("DataFrame", nrows=length(unlisted_from), check=FALSE) } ans_values <- newCompressedList0("CompressedSplitDataFrameList", unlisted_values, PartitioningByEnd(ans_ranges)) new2("RangedData", ranges=ans_ranges, values=ans_values, #metadata=metadata(from), elementMetadata=elementMetadata(from), check=FALSE) } ) .fromRangedDataToCompressedIRangesList <- function(from) { ans <- ranges(from) ## Propagate 'values(from)'. ans_unlisted_values <- unlist(values(from), use.names=FALSE) mcols(ans@unlistData) <- ans_unlisted_values ans } setAs("RangedData", "CompressedIRangesList", .fromRangedDataToCompressedIRangesList ) setAs("RangedData", "IRangesList", .fromRangedDataToCompressedIRangesList) setAs("RangedData", "RangesList", .fromRangedDataToCompressedIRangesList) setMethod("as.env", "RangedData", function(x, enclos = parent.frame(2)) { env <- callNextMethod(x, enclos) makeAccessorBinding <- function(fun, name = deparse(substitute(fun))) { makeActiveBinding(name, function() { val <- fun(x) rm(list=name, envir=env) assign(name, val, env) ## cache for further use val }, env) } makeAccessorBinding(ranges) makeAccessorBinding(space) makeAccessorBinding(start) makeAccessorBinding(width) makeAccessorBinding(end) env }) .RangedData_fromDataFrame <- function(from) { required <- c("start", "end") if (!all(required %in% colnames(from))) stop("'from' must at least include a 'start' and 'end' column") datacols <- setdiff(colnames(from), c(required, "space", "width")) RangedData(IRanges(from$start, from$end), from[,datacols,drop=FALSE], space = from$space) } setAs("data.frame", "RangedData", .RangedData_fromDataFrame) setAs("DataTable", "RangedData", .RangedData_fromDataFrame) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Show ### setMethod("show", "RangedData", function(object) { nr <- nrow(object) nc <- ncol(object) lo <- length(object) cat(class(object), " with ", nr, ifelse(nr == 1, " row and ", " rows and "), nc, ifelse(nc == 1, " value column across ", " value columns across "), lo, ifelse(lo == 1, " space\n", " spaces\n"), sep = "") if (nr > 0) { nms <- rownames(object) if (nr < 20) { ranges <- unlist(ranges(object), use.names=FALSE) values <- unlist(values(object), use.names=FALSE) out <- cbind(space = as.character(space(object)), ranges = showAsCell(ranges), "|" = rep.int("|", nr)) if (nc > 0) out <- cbind(out, as.matrix(format(do.call(data.frame, lapply(values, showAsCell))))) if (is.null(nms)) rownames(out) <- as.character(seq_len(nr)) else rownames(out) <- nms classinfo <- matrix(c("", "", "|", unlist(lapply(values, function(x) { paste("<", classNameForDisplay(x), ">", sep = "") }), use.names = FALSE)), nrow = 1, dimnames = list("", colnames(out))) } else { top <- object[1:9, ] topRanges <- unlist(ranges(top), use.names=FALSE) topValues <- unlist(values(top), use.names=FALSE) bottom <- object[(nr-8L):nr, ] bottomRanges <- unlist(ranges(bottom), use.names=FALSE) bottomValues <- unlist(values(bottom), use.names=FALSE) out <- rbind(cbind(space = as.character(space(top)), ranges = showAsCell(topRanges), "|" = rep.int("|", 9)), rbind(rep.int("...", 3)), cbind(space = as.character(space(bottom)), ranges = showAsCell(bottomRanges), "|" = rep.int("|", 9))) if (nc > 0) out <- cbind(out, rbind(as.matrix(format(do.call(data.frame, lapply(topValues, showAsCell)))), rbind(rep.int("...", nc)), rbind(as.matrix(format(do.call(data.frame, lapply(bottomValues, showAsCell))))))) if (is.null(nms)) { rownames(out) <- c(as.character(1:9), "...", as.character((nr-8L):nr)) } else { rownames(out) <- c(head(nms, 9), "...", tail(nms, 9)) } classinfo <- matrix(c("", "", "|", unlist(lapply(topValues, function(x) { paste("<", classNameForDisplay(x), ">", sep = "") }), use.names = FALSE)), nrow = 1, dimnames = list("", colnames(out))) } out <- rbind(classinfo, out) print(out, quote = FALSE, right = TRUE) } }) ### ========================================================================= ### RangedDataList objects ### ------------------------------------------------------------------------- ### Lists of RangedData objects setClass("RangedDataList", prototype = prototype(elementType = "RangedData"), contains = "SimpleList") RangedDataList <- function(...) { listData <- list(...) if (length(listData) == 1 && is.list(listData[[1L]])) listData <- listData[[1L]] S4Vectors:::new_SimpleList_from_list("RangedDataList", listData) } setMethod("unlist", "RangedDataList", function(x, recursive = TRUE, use.names = TRUE) { if (!identical(recursive, TRUE)) stop("\"unlist\" method for RangedDataList objects ", "does not support the 'recursive' argument") ans <- do.call(rbind, unname(as.list(x))) if (!use.names) rownames(ans) <- NULL ans }) setMethod("stack", "RangedDataList", function(x, index.var = "name") { rd <- do.call(rbind, unname(as.list(x))) spaces <- unlist(lapply(x, space), use.names=FALSE) ids <- names(x) if (is.null(ids)) ids <- seq_len(length(x)) spaceOrd <- order(factor(spaces, names(rd))) rd[[index.var]] <- rep(factor(ids), sapply(x, nrow))[spaceOrd] rd }) IRanges/R/RangedData-utils.R0000644000175100017510000000652112607265143016610 0ustar00biocbuildbiocbuild### ========================================================================= ### RangedData utilities ### ------------------------------------------------------------------------- ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Applying ### setMethod("lapply", "RangedData", function(X, FUN, ...) { FUN <- match.fun(FUN) inds <- structure(seq(length(X)), names = names(X)) lapply(inds, function(i) FUN(X[i], ...)) }) setMethod("endoapply", "RangedData", function(X, FUN, ...) { FUN <- match.fun(FUN) ans <- try(do.call(c, unname(lapply(X, FUN, ...))), silent = TRUE) if (inherits(ans, "try-error") || (class(ans) != class(X))) stop("'FUN' did not produce an endomorphism") ans }) setGeneric("rdapply", function(x, ...) standardGeneric("rdapply")) setMethod("rdapply", "RDApplyParams", function(x) { rd <- rangedData(x) applyFun <- applyFun(x) applyParams <- applyParams(x) rules <- filterRules(x) simplify <- simplify(x) reducerFun <- reducerFun(x) reducerParams <- reducerParams(x) enclos <- parent.frame(2) inds <- seq(length(rd)) names(inds) <- names(rd) ## if (length(excludePattern)) { ## excludePattern <- grep(excludePattern, names(rd)) ## if (length(excludePattern)) ## inds <- inds[-excludePattern] ## } forEachSpace <- function(i) { rdi <- rd[i] if (length(rules)) { filter <- eval(rules, rdi, enclos) rdi <- rdi[filter,] } do.call(applyFun, c(list(rdi), applyParams)) } iteratorFun <- iteratorFun(x) if ("simplify" %in% names(formals(iteratorFun))) ans <- iteratorFun(inds, forEachSpace, simplify = simplify) else ans <- iteratorFun(inds, forEachSpace) if (!is.null(reducerFun)) ans <- do.call(reducerFun, c(list(ans), reducerParams)) ans }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### within() ### setMethod("within", "RangedData", function(data, expr, ...) { e <- list2env(as.list(as(data, "DataFrame"))) e$ranges <- ranges(data) S4Vectors:::safeEval(substitute(expr), e, S4Vectors:::top_prenv(expr)) reserved <- c("ranges", "start", "end", "width", "space") l <- mget(setdiff(ls(e), reserved), e) l <- l[!sapply(l, is.null)] nD <- length(del <- setdiff(colnames(data), (nl <- names(l)))) for (nm in nl) data[[nm]] <- l[[nm]] for (nm in del) data[[nm]] <- NULL if (!identical(ranges(data), e$ranges)) ranges(data) <- e$ranges else { if (!identical(start(data), e$start)) start(data) <- e$start if (!identical(end(data), e$end)) end(data) <- e$end if (!identical(width(data), e$width)) width(data) <- e$width } data }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Merging (TODO) ### #setMethod("merge", "RangedData", # function(x, y, by = 1, all = FALSE, all.x = all, all.y = all, # resolver = intersect, sort = TRUE, suffixes = c(".x",".y")) # { # # }) IRanges/R/RangedSelection-class.R0000644000175100017510000000303112607265143017622 0ustar00biocbuildbiocbuild### ========================================================================= ### Selection of features and columns by intervals and column names ### ------------------------------------------------------------------------- setClass("RangedSelection", representation(ranges = "RangesList", colnames = "character")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor methods. ### setMethod("ranges", "RangedSelection", function(x) x@ranges) setReplaceMethod("ranges", "RangedSelection", function(x, value) { x@ranges <- value x }) setMethod("colnames", "RangedSelection", function(x, do.NULL = TRUE, prefix = "col") x@colnames) setReplaceMethod("colnames", "RangedSelection", function(x, value) { x@colnames <- value x }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor. ### RangedSelection <- function(ranges = RangesList(), colnames = character()) { if (!is(ranges, "RangesList")) stop("'ranges' must be a RangesList") if (!is.character(colnames) || S4Vectors:::anyMissing(colnames)) stop("'colnames' must be a character vector without missing values") new("RangedSelection", ranges = ranges, colnames = colnames) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### setAs("RangesList", "RangedSelection", function(from) RangedSelection(from)) IRanges/R/Ranges-class.R0000644000175100017510000001774112607265143016010 0ustar00biocbuildbiocbuild### ========================================================================= ### Ranges objects ### ------------------------------------------------------------------------- ### ### Ranges is a virtual class that serves as the base for all range containers ### Conceptually Ranges are closed, one-dimensional intervals with integer end ### points and on the domain of integers. ### setClass("Ranges", contains="IntegerList", representation("VIRTUAL")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Getters/setters. ### setMethod("length", "Ranges", function(x) length(start(x))) ### Without this definition, we inherit the method for Vector objects ### which is very inefficient on Ranges objects! setMethod("elementLengths", "Ranges", function(x) setNames(width(x), names(x))) ### The 3 default methods below provide a formalization of the relationship ### between the starts/widths/ends of a Ranges object. Of course Ranges ### subclasses need to implement at least 2 of them! ### Note that when width(x)[i] is 0, then end(x)[i] is start(x)[i] - 1 setMethod("start", "Ranges", function(x, ...) {1L - width(x) + end(x)}) setMethod("width", "Ranges", function(x) {end(x) - start(x) + 1L}) setMethod("end", "Ranges", function(x, ...) {width(x) - 1L + start(x)}) setGeneric("mid", function(x, ...) standardGeneric("mid")) setMethod("mid", "Ranges", function(x) start(x) + as.integer((width(x)-1) / 2)) setMethod("update", "Ranges", function(object, ...) as(update(as(object, "IRanges"), ...), class(object)) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### ### The checking of the names(x) is taken care of by the validity method for ### Vector objects. .valid.Ranges <- function(x) { x_start <- start(x) x_end <- end(x) x_width <- width(x) validity_failures <- .Call2("valid_Ranges", x_start, x_end, x_width, PACKAGE="IRanges"); if (!is.null(validity_failures)) return(validity_failures) if (!(is.null(names(x_start)) && is.null(names(x_end)) && is.null(names(x_width)))) return(paste0("'start(x)', 'end(x)', and 'width(x)' ", "cannot have names on them")) NULL } setValidity2("Ranges", .valid.Ranges) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### setMethod("as.matrix", "Ranges", function(x, ...) matrix(data=c(start(x), width(x)), ncol=2, dimnames=list(names(x), NULL)) ) ### S3/S4 combo for as.data.frame.Ranges as.data.frame.Ranges <- function(x, row.names=NULL, optional=FALSE, ...) { if (!(is.null(row.names) || is.character(row.names))) stop("'row.names' must be NULL or a character vector") ans <- data.frame(start=start(x), end=end(x), width=width(x), row.names=row.names, check.rows=TRUE, check.names=FALSE, stringsAsFactors=FALSE) ans$names <- names(x) ans } setMethod("as.data.frame", "Ranges", as.data.frame.Ranges) setMethod("as.integer", "Ranges", function(x, ...) S4Vectors:::fancy_mseq(width(x), offset=start(x)-1L) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### More stuff. ### ### TODO: Reorganize this ### setMethod("unlist", "Ranges", function(x, recursive=TRUE, use.names=TRUE) { if (!identical(recursive, TRUE)) stop("\"unlist\" method for Ranges objects ", "does not support the 'recursive' argument") if (!isTRUEorFALSE(use.names)) stop("'use.names' must be TRUE or FALSE") ans <- as.integer(x) # 'ans' should have no names stopifnot(is.null(names(ans))) # sanity check if (use.names && !is.null(names(x))) names(ans) <- rep.int(names(x), elementLengths(x)) ans } ) setMethod("getListElement", "Ranges", function(x, i, exact=TRUE) { i <- normalizeDoubleBracketSubscript(i, x, exact=exact, error.if.nomatch=TRUE) ans_shift <- start(x)[i] - 1L ans_length <- width(x)[i] seq_len(ans_length) + ans_shift } ) setMethod("show", "Ranges", function(object) { nhead <- get_showHeadLines() ntail <- get_showTailLines() lo <- length(object) cat(class(object), " of length ", lo, "\n", sep="") if (lo == 0L) return(NULL) if (lo < (nhead + ntail + 1L)) { showme <- as.data.frame(object, row.names=paste0("[", seq_len(lo), "]")) } else { showme <- data.frame(start=.sketch(start(object), nhead, ntail), end=.sketch(end(object), nhead, ntail), width=.sketch(width(object), nhead, ntail), row.names=.sketch(start(object), nhead, ntail, TRUE), check.rows=TRUE, check.names=FALSE, stringsAsFactors=FALSE) NAMES <- names(object) if (!is.null(NAMES)) showme$names <- .sketch(NAMES, nhead, ntail) } show(showme) } ) .sketch <- function(x, nhead, ntail, rownames=FALSE) { len <- length(x) p1 <- ifelse (nhead == 0, 0L, 1L) p2 <- ifelse (ntail == 0, 0L, ntail-1L) s1 <- s2 <- character(0) if (rownames) { if (nhead > 0) s1 <- paste0("[", p1:nhead, "]") if (ntail > 0) s2 <- paste0("[", (len-p2):len, "]") } else { if (nhead > 0) s1 <- paste0(as.character(x[p1:nhead])) if (ntail > 0) s2 <- paste0(as.character(x[(len-p2):len])) } c(s1, "...", s2) } setMethod("showAsCell", "Ranges", function(object) { if (length(object) == 0L) return(character(0)) paste("[", format(start(object)), ", ", format(end(object)), "]", sep = "") } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### isEmpty(), isNormal(), isDisjoint() ### ### All of them test a Ranges object as a whole and return a single TRUE or ### FALSE. ### ### A Ranges object is considered empty iff all its ranges are empty. setMethod("isEmpty", "Ranges", function(x) all(width(x) == 0L)) setGeneric("isNormal", function(x) standardGeneric("isNormal")) setMethod("isNormal", "Ranges", function(x) { all_ok <- all(width(x) >= 1L) if (length(x) >= 2) all_ok <- all_ok && all(start(x)[-1L] - end(x)[-length(x)] >= 2L) all_ok } ) setGeneric("whichFirstNotNormal", function(x) standardGeneric("whichFirstNotNormal") ) setMethod("whichFirstNotNormal", "Ranges", function(x) { is_ok <- width(x) >= 1L if (length(x) >= 2) is_ok <- is_ok & c(TRUE, start(x)[-1L] - end(x)[-length(x)] >= 2L) which(!is_ok)[1L] } ) setGeneric("isDisjoint", function(x, ...) standardGeneric("isDisjoint")) setMethod("isDisjoint", "Ranges", function(x) { x_len <- length(x) if (x_len < 2L) return(TRUE) x_start <- start(x) x_end <- end(x) oo <- order(x) start2 <- x_start[oo] end2 <- x_end[oo] all(start2[-1L] > end2[-x_len]) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Core endomorphisms. ### ### TODO: "extractROWS" and most of the Ranges endomorphisms are only ### defined for IRanges objects. Need to fix up the update mechanism, so that ### they can be defined on Ranges. "extractROWS" and other endomorphisms ### are currently implemented as wrappers that coerce to IRanges, which is not ### efficient so not a general, long-term solution. setMethod("extractROWS", "Ranges", function(x, i) { as(callGeneric(as(x, "IRanges"), i), class(x)) } ) IRanges/R/Ranges-comparison.R0000644000175100017510000000623512607265143017051 0ustar00biocbuildbiocbuild### ========================================================================= ### Comparing and ordering ranges ### ------------------------------------------------------------------------- ### setMethod("compareRecursively", "Ranges", function(x) FALSE) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### compare() ### ### Ranges are ordered by starting position first and then by width. ### This way, the space of ranges is totally ordered. ### This "compare" method returns one of the 13 predefined codes (>= -6 and ### <= 6) described in the man page. The signs of those codes reflect this ### order. ### setMethod("compare", c("Ranges", "Ranges"), function(x, y) { .Call2("Ranges_compare", start(x), width(x), start(y), width(y), PACKAGE="IRanges") } ) rangeComparisonCodeToLetter <- function(code) { if (!is.integer(code)) stop("'code' must be an integer vector") code <- code + 7L code[code < 1L | 14L < code] <- 14L levels <- c(letters[1:13], "X") structure(code, levels=levels, class="factor") } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### match() ### setMethod("match", c("Ranges", "Ranges"), function(x, table, nomatch=NA_integer_, incomparables=NULL, method=c("auto", "quick", "hash")) { if (!is.null(incomparables)) stop("\"match\" method for Ranges objects ", "only accepts 'incomparables=NULL'") ## Equivalent to (but faster than): ## findOverlaps(x, table, type="equal", select="first") ## except when 'x' or 'table' contain empty ranges. S4Vectors:::matchIntegerPairs(start(x), width(x), start(table), width(table), nomatch=nomatch, method=method) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### selfmatch() ### setMethod("selfmatch", "Ranges", function(x, method=c("auto", "quick", "hash")) S4Vectors:::selfmatchIntegerPairs(start(x), width(x), method=method) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Ordering ranges ### ### order(), sort(), rank() on Ranges objects are consistent with the order ### on ranges implied by compare(). ### ### 'na.last' is pointless (Ranges objects don't contain NAs) so is ignored. setMethod("order", "Ranges", function(..., na.last=TRUE, decreasing=FALSE) { if (!isTRUEorFALSE(decreasing)) stop("'decreasing' must be TRUE or FALSE") ## All arguments in '...' are guaranteed to be Ranges objects. args <- list(...) if (length(args) == 1L) { x <- args[[1L]] return(S4Vectors:::orderIntegerPairs(start(x), width(x), decreasing=decreasing)) } order_args <- vector("list", 2L * length(args)) idx <- 2L * seq_along(args) order_args[idx - 1L] <- lapply(args, start) order_args[idx] <- lapply(args, width) do.call(order, c(order_args, list(decreasing=decreasing))) } ) IRanges/R/RangesList-class.R0000644000175100017510000006123412607265143016640 0ustar00biocbuildbiocbuild### ========================================================================= ### RangesList objects ### ------------------------------------------------------------------------- ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### RangesList ### ### Accepts any type of Ranges object as an element. ### setClass("RangesList", representation("VIRTUAL"), prototype = prototype(elementType = "Ranges"), contains = "List") setClass("SimpleRangesList", prototype = prototype(elementType = "Ranges"), contains = c("RangesList", "SimpleList")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### IRangesList ### setClass("IRangesList", representation("VIRTUAL"), prototype = prototype(elementType = "IRanges"), contains = "RangesList") setClass("CompressedIRangesList", prototype = prototype(elementType = "IRanges", unlistData = new("IRanges")), contains = c("IRangesList", "CompressedList")) setClass("SimpleIRangesList", prototype = prototype(elementType = "IRanges"), contains = c("IRangesList", "SimpleRangesList")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### NormalIRangesList ### setClass("NormalIRangesList", representation("VIRTUAL"), prototype = prototype(elementType = "NormalIRanges"), contains = "IRangesList") ### CompressedNormalIRangesList cannot hold NormalIRanges as its elements, ### due to the compression combining everything into a single ### NormalIRanges (which could easily become non-normal). So just have it ### hold IRanges, instead. setClass("CompressedNormalIRangesList", prototype = prototype(elementType = "IRanges", unlistData = new("IRanges")), contains = c("NormalIRangesList", "CompressedIRangesList")) setClass("SimpleNormalIRangesList", prototype = prototype(elementType = "NormalIRanges"), contains = c("NormalIRangesList", "SimpleIRangesList")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### .valid.NormalIRangesList <- function(x) { if (!all(isNormal(x))) return("at least one element of object is not normal") NULL } setValidity2("NormalIRangesList", .valid.NormalIRangesList) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor methods. ### setMethod("start", "RangesList", function(x) S4Vectors:::new_SimpleList_from_list("SimpleIntegerList", lapply(x, start))) setMethod("end", "RangesList", function(x) S4Vectors:::new_SimpleList_from_list("SimpleIntegerList", lapply(x, end))) setMethod("width", "RangesList", function(x) S4Vectors:::new_SimpleList_from_list("SimpleIntegerList", lapply(x, width))) setGeneric(".replaceSEW", signature="x", # not exported function(x, FUN, ..., value) standardGeneric(".replaceSEW")) setMethod(".replaceSEW", "RangesList", function(x, FUN, ..., value) { if (extends(class(value), "IntegerList")) { if (!identical(lapply(x, names), lapply(value, names)) && !all(elementLengths(x) == elementLengths(value))) stop("'value' must have same length and names as current 'ranges'") } else if (is.numeric(value)) { lelts <- sum(elementLengths(x)) if (lelts != length(value)) value <- rep(value, length.out = lelts) if (!is.integer(value)) value <- as.integer(value) value <- split(value, factor(space(x), names(x))) } else { stop("'value' must extend class IntegerList or integer") } FUN <- match.fun(FUN) for (i in seq_len(length(x))) x[[i]] <- FUN(x[[i]], ..., value = value[[i]]) x } ) setReplaceMethod("start", "RangesList", function(x, ..., value) .replaceSEW(x, "start<-", ..., value=value) ) setReplaceMethod("end", "RangesList", function(x, ..., value) .replaceSEW(x, "end<-", ..., value=value) ) setReplaceMethod("width", "RangesList", function(x, ..., value) .replaceSEW(x, "width<-", ..., value=value) ) setMethod("start", "CompressedIRangesList", function(x) new2("CompressedIntegerList", unlistData = start(unlist(x, use.names=FALSE)), partitioning = x@partitioning, check=FALSE)) setMethod("end", "CompressedIRangesList", function(x) new2("CompressedIntegerList", unlistData = end(unlist(x, use.names=FALSE)), partitioning = x@partitioning, check=FALSE)) setMethod("width", "CompressedIRangesList", function(x) new2("CompressedIntegerList", unlistData = width(unlist(x, use.names=FALSE)), partitioning = x@partitioning, check=FALSE)) setMethod(".replaceSEW", "CompressedIRangesList", function(x, FUN, ..., value) { if (extends(class(value), "IntegerList")) { if (!identical(lapply(x, names), lapply(value, names)) && !all(elementLengths(x) == elementLengths(value))) stop("'value' must have same length and names as current 'ranges'") value <- unlist(value) } else if (is.numeric(value)) { lelts <- sum(elementLengths(x)) if (lelts != length(value)) value <- rep(value, length.out = lelts) if (!is.integer(value)) value <- as.integer(value) } else { stop("'value' must extend class IntegerList or integer") } FUN <- match.fun(FUN) slot(x, "unlistData", check=FALSE) <- FUN(x@unlistData, ..., value = value) x } ) setGeneric("space", function(x, ...) standardGeneric("space")) setMethod("space", "RangesList", function(x) { space <- names(x) if (!is.null(space)) space <- factor(rep.int(space, elementLengths(x)), space) space }) ### TODO: Why not define this at the List level? Or even at the Vector level? setGeneric("universe", function(x) standardGeneric("universe")) setMethod("universe", "RangesList", function(x) { metadata(x)$universe }) setGeneric("universe<-", function(x, value) standardGeneric("universe<-")) setReplaceMethod("universe", "RangesList", function(x, value) { if (!is.null(value) && !isSingleString(value)) stop("'value' must be a single string or NULL") metadata(x)$universe <- value x }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### isNormal(), isDisjoint() ### ### Test the list elements of a RangesList object 'x' individually and return ### a vector of TRUE's or FALSE's parallel to 'x'. More precisely, they're ### equivalent to 'sapply(x, FUN)', when FUN is 'isNormal' or 'isDisjoint'. ### setMethod("isNormal", "RangesList", function(x) unlist(lapply(x, isNormal))) setMethod("isNormal", "CompressedIRangesList", function(x) .Call2("CompressedIRangesList_isNormal", x, TRUE, PACKAGE = "IRanges")) setMethod("isNormal", "SimpleIRangesList", function(x) .Call2("SimpleIRangesList_isNormal", x, PACKAGE = "IRanges")) setMethod("whichFirstNotNormal", "RangesList", function(x) unlist(lapply(x, whichFirstNotNormal))) setMethod("isDisjoint", "RangesList", function(x) unlist(lapply(x, isDisjoint))) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor. ### RangesList <- function(..., universe = NULL) { if (!is.null(universe) && !isSingleString(universe)) stop("'universe' must be a single string or NULL") ranges <- list(...) if (length(ranges) == 1 && is.list(ranges[[1L]])) ranges <- ranges[[1L]] if (!all(sapply(ranges, is, "Ranges"))) stop("all elements in '...' must be Ranges objects") ans <- S4Vectors:::new_SimpleList_from_list("SimpleRangesList", ranges) universe(ans) <- universe ans } IRangesList <- function(..., universe = NULL, compress = TRUE) { if (!isTRUEorFALSE(compress)) stop("'compress' must be TRUE or FALSE") if (!is.null(universe) && !isSingleString(universe)) stop("'universe' must be a single string or NULL") ranges <- list(...) if (length(ranges) == 1 && (is(ranges[[1L]], "LogicalList") || is(ranges[[1L]], "RleList"))) { if (compress) ans <- as(ranges[[1L]], "CompressedIRangesList") else ans <- as(ranges[[1L]], "SimpleIRangesList") } else if (length(ranges) == 2 && setequal(names(ranges), c("start", "end")) && !is(ranges[[1L]], "Ranges") && !is(ranges[[2L]], "Ranges")) { if (!compress) stop("'compress' must be TRUE when passing the 'start' and 'end' arguments") ans_start <- IntegerList(ranges[["start"]], compress = TRUE) ans_end <- IntegerList(ranges[["end"]], compress = TRUE) if (!identical(ans_start@partitioning@end, ans_end@partitioning@end)) stop("'start' and 'end' are not compatible") ans_partitioning <- ans_start@partitioning ans_unlistData <- IRanges(start=ans_start@unlistData, end=ans_end@unlistData) ans <- new2("CompressedIRangesList", partitioning=ans_partitioning, unlistData=ans_unlistData, check=FALSE) } else { if (length(ranges) == 1 && is.list(ranges[[1L]])) ranges <- ranges[[1L]] if (!all(sapply(ranges, is, "IRanges"))) stop("all elements in '...' must be IRanges objects") if (compress) ans <- new_CompressedList_from_list("CompressedIRangesList", ranges) else ans <- S4Vectors:::new_SimpleList_from_list("SimpleIRangesList", ranges) } universe(ans) <- universe ans } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Subsetting. ### setMethod("getListElement", "CompressedNormalIRangesList", function(x, i, exact=TRUE) newNormalIRangesFromIRanges(callNextMethod()) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### merge() ### ### Merges various RangesList objects into a single RangesList object. ### The merging is either by name (if all the RangesList objects have names), ### or by position (if any RangesList object is missing names). ### When merging by name, and in case of duplicated names within a given ### RangesList, the elements corresponding to the duplicated names are ignored. ### When merging by position, all the RangesList objects must have the same ### length. ### Note that the "range" method for RangesList objects expects "merge" to ### behave like this. .RangesList.merge <- function(...) { args <- unname(list(...)) if (length(args) == 0L) stop("nothing to merge") x <- args[[1L]] if (!all(sapply(sapply(args, universe), identical, universe(x)))) stop("all RangesList objects to merge must have the same universe") spaceList <- lapply(args, names) names <- spaces <- unique(do.call(c, spaceList)) if (any(sapply(spaceList, is.null))) { ## Merging by position. if (!all(unlist(lapply(args, length)) == length(x))) stop("if any RangesList objects to merge are missing names, ", "all must have same length") names <- NULL spaces <- seq_len(length(x)) } ranges <- lapply(spaces, function(space) { r <- lapply(args, `[[`, space) do.call(c, r[!sapply(r, is.null)]) }) names(ranges) <- names if (is(x, "CompressedList")) ans <- new_CompressedList_from_list(class(x), ranges) else ans <- S4Vectors:::new_SimpleList_from_list(class(x), ranges) ans } setMethod("merge", c("RangesList", "missing"), function(x, y, ...) .RangesList.merge(x, ...) ) setMethod("merge", c("missing", "RangesList"), function(x, y, ...) .RangesList.merge(y, ...) ) setMethod("merge", c("RangesList", "RangesList"), function(x, y, ...) .RangesList.merge(x, y, ...) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "show" method. ### showRangesList <- function(x, with.header=TRUE) { x_len <- length(x) if (with.header) cat(classNameForDisplay(x), " of length ", x_len, "\n", sep = "") if (x_len == 0L) return(invisible(NULL)) cumsumN <- end(PartitioningByEnd(x)) N <- tail(cumsumN, 1) if (x_len <= 5L && N <= 20L) { show(as.list(x)) return(invisible(NULL)) } if (x_len >= 3L && cumsumN[3L] <= 20L) { showK <- 3L } else if (x_len >= 2L && cumsumN[2L] <= 20L) { showK <- 2L } else { showK <- 1L } show(as.list(x[seq_len(showK)])) diffK <- x_len - showK if (diffK > 0L) cat("...\n<", x_len - showK, ifelse(diffK == 1L, " more element>\n", " more elements>\n"), sep="") } setMethod("show", "RangesList", function(object) showRangesList(object)) setMethod("showAsCell", "RangesList", function(object) { unlist(lapply(object, function(x) { if (length(x) <= 3) paste(showAsCell(x), collapse = " ") else paste(c(showAsCell(head(x, 3)), "..."), collapse = " ") }), use.names = FALSE) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### ### S3/S4 combo for as.list.CompressedNormalIRangesList .as.list.CompressedNormalIRangesList <- function(x, use.names=TRUE) { if (!isTRUEorFALSE(use.names)) stop("'use.names' must be TRUE or FALSE") ans <- lapply_CompressedList(x, newNormalIRangesFromIRanges) if (use.names) names(ans) <- names(x) ans } as.list.CompressedNormalIRangesList <- function(x, ...) .as.list.CompressedNormalIRangesList(x, ...) setMethod("as.list", "CompressedNormalIRangesList", as.list.CompressedNormalIRangesList) setMethod("unlist", "SimpleNormalIRangesList", function(x, recursive = TRUE, use.names = TRUE) { x <- S4Vectors:::new_SimpleList_from_list("SimpleIRangesList", lapply(x, as, "IRanges")) callGeneric() }) setAs("RangesList", "IRangesList", function(from) { if (is(from, "CompressedList")) as(from, "CompressedIRangesList") else as(from, "SimpleIRangesList") }) setAs("RangesList", "CompressedIRangesList", function(from) { if (is(from, "CompressedList")) coerceToCompressedList(from, "IRanges") ## this case handles RangesList of Partitioning objects (not combinable) else new_CompressedList_from_list("CompressedIRangesList", lapply(from, as, "IRanges"), metadata = metadata(from), mcols = mcols(from)) }) .RangesListToSimpleIRangesList <- function(from) S4Vectors:::new_SimpleList_from_list("SimpleIRangesList", lapply(from, as, "IRanges"), metadata = metadata(from), mcols = mcols(from)) ## otherwise, SimpleRangesList->SimpleIRangesList uses a methods package default setAs("SimpleRangesList", "SimpleIRangesList", .RangesListToSimpleIRangesList) setAs("RangesList", "SimpleIRangesList", .RangesListToSimpleIRangesList) setAs("RangesList", "SimpleRangesList", function(from) S4Vectors:::new_SimpleList_from_list("SimpleRangesList", lapply(from, as, "Ranges"), metadata = metadata(from), mcols = mcols(from))) setAs("RangesList", "NormalIRangesList", function(from) { if (is(from, "CompressedList")) as(from, "CompressedNormalIRangesList") else as(from, "SimpleNormalIRangesList") }) setAs("RangesList", "CompressedNormalIRangesList", function(from) new_CompressedList_from_list("CompressedNormalIRangesList", lapply(from, as, "NormalIRanges"), metadata = metadata(from), mcols = mcols(from))) setAs("RangesList", "SimpleNormalIRangesList", function(from) S4Vectors:::new_SimpleList_from_list("SimpleNormalIRangesList", lapply(from, as, "NormalIRanges"), metadata = metadata(from), mcols = mcols(from))) setAs("CompressedIRangesList", "CompressedNormalIRangesList", function(from) { if (!all(isNormal(from))) from <- reduce(from, drop.empty.ranges=TRUE) new2("CompressedNormalIRangesList", from, check=FALSE) }) setAs("SimpleIRangesList", "SimpleNormalIRangesList", function(from) { if (!all(isNormal(from))) from <- reduce(from, drop.empty.ranges=TRUE) new2("SimpleNormalIRangesList", listData = lapply(from@listData, newNormalIRangesFromIRanges, check = FALSE), metadata = from@metadata, elementMetadata = from@elementMetadata, check=FALSE) }) setAs("LogicalList", "IRangesList", function(from) { if (is(from, "CompressedList")) as(from, "CompressedIRangesList") else as(from, "SimpleIRangesList") }) setAs("LogicalList", "CompressedIRangesList", function(from) new_CompressedList_from_list("CompressedIRangesList", lapply(from, as, "IRanges"), metadata = metadata(from), mcols = mcols(from))) setAs("LogicalList", "SimpleIRangesList", function(from) S4Vectors:::new_SimpleList_from_list("SimpleIRangesList", lapply(from, as, "IRanges"), metadata = metadata(from), mcols = mcols(from))) setAs("LogicalList", "NormalIRangesList", function(from) { if (is(from, "CompressedList")) as(from, "CompressedNormalIRangesList") else as(from, "SimpleNormalIRangesList") }) setAs("LogicalList", "CompressedNormalIRangesList", function(from) new_CompressedList_from_list("CompressedNormalIRangesList", lapply(from, as, "NormalIRanges"), metadata = metadata(from), mcols = mcols(from))) setAs("LogicalList", "SimpleNormalIRangesList", function(from) S4Vectors:::new_SimpleList_from_list("SimpleNormalIRangesList", lapply(from, as, "NormalIRanges"), metadata = metadata(from), mcols = mcols(from))) setAs("RleList", "IRangesList", function(from) { if (is(from, "CompressedList")) as(from, "CompressedIRangesList") else as(from, "SimpleIRangesList") }) setAs("RleList", "CompressedIRangesList", function(from) { if ((length(from) > 0) && (!is.logical(runValue(from[[1L]])) || S4Vectors:::anyMissing(runValue(from[[1L]])))) stop("cannot coerce a non-logical 'RleList' or a logical 'RleList' ", "with NAs to a CompressedIRangesList object") new_CompressedList_from_list("CompressedIRangesList", lapply(from, as, "IRanges"), metadata = metadata(from), mcols = mcols(from)) }) setAs("CompressedRleList", "CompressedIRangesList", function(from) { if ((length(from) > 0) && (!is.logical(runValue(from[[1L]])) || S4Vectors:::anyMissing(runValue(from[[1L]])))) stop("cannot coerce a non-logical 'RleList' or a logical 'RleList' ", "with NAs to a CompressedIRangesList object") ranges <- as(unlist(from, use.names = FALSE), "IRanges") to <- diceRangesByList(ranges, from) metadata(to) <- metadata(from) mcols(to) <- mcols(from) to }) setAs("RleList", "SimpleIRangesList", function(from) { if ((length(from) > 0) && (!is.logical(runValue(from[[1L]])) || S4Vectors:::anyMissing(runValue(from[[1L]])))) stop("cannot coerce a non-logical 'RleList' or a logical 'RleList' ", "with NAs to a SimpleIRangesList object") S4Vectors:::new_SimpleList_from_list("SimpleIRangesList", lapply(from, as, "IRanges"), metadata = metadata(from), mcols = mcols(from)) }) setAs("RleList", "NormalIRangesList", function(from) { if (is(from, "CompressedList")) as(from, "CompressedNormalIRangesList") else as(from, "SimpleNormalIRangesList") }) setAs("RleList", "CompressedNormalIRangesList", function(from) { if ((length(from) > 0) && (!is.logical(runValue(from[[1L]])) || S4Vectors:::anyMissing(runValue(from[[1L]])))) stop("cannot coerce a non-logical 'RleList' or a logical 'RleList' ", "with NAs to a CompressedNormalIRangesList object") new_CompressedList_from_list("CompressedNormalIRangesList", lapply(from, as, "NormalIRanges"), metadata = metadata(from), mcols = mcols(from)) }) setAs("RleList", "SimpleNormalIRangesList", function(from) { if ((length(from) > 0) && (!is.logical(runValue(from[[1L]])) || S4Vectors:::anyMissing(runValue(from[[1L]])))) stop("cannot coerce a non-logical 'RleList' or a logical 'RleList' ", "with NAs to a SimpleNormalIRangesList object") S4Vectors:::new_SimpleList_from_list("SimpleNormalIRangesList", lapply(from, as, "NormalIRanges"), metadata = metadata(from), mcols = mcols(from)) }) setAs("list", "RangesList", function(from) { S4Vectors:::coerceToSimpleList(from, "Ranges") }) setAs("Ranges", "RangesList", function(from) { relist(from, PartitioningByEnd(seq_along(from), names=names(from))) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "max" and "min" methods for NormalIRangesList objects. ### CompressedNormalIRangesList.max <- function(x, use.names) { if (!is(x, "CompressedNormalIRangesList")) stop("'x' must be a CompressedNormalIRangesList object") use.names <- S4Vectors:::normargUseNames(use.names) .Call2("CompressedNormalIRangesList_max", x, use.names, PACKAGE="IRanges") } setMethod("max", "CompressedNormalIRangesList", function(x, ..., na.rm) CompressedNormalIRangesList.max(x, TRUE)) setMethod("max", "SimpleNormalIRangesList", function(x, ..., na.rm) .Call2("SimpleNormalIRangesList_max", x, PACKAGE="IRanges")) CompressedNormalIRangesList.min <- function(x, use.names) { if (!is(x, "CompressedNormalIRangesList")) stop("'x' must be a CompressedNormalIRangesList object") use.names <- S4Vectors:::normargUseNames(use.names) .Call2("CompressedNormalIRangesList_min", x, use.names, PACKAGE="IRanges") } setMethod("min", "CompressedNormalIRangesList", function(x, ..., na.rm) CompressedNormalIRangesList.min(x, TRUE)) setMethod("min", "SimpleNormalIRangesList", function(x, ..., na.rm) .Call2("SimpleNormalIRangesList_min", x, PACKAGE="IRanges")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "summary" method. ### setMethod("summary", "CompressedIRangesList", function(object) .Call2("CompressedIRangesList_summary", object, PACKAGE="IRanges")) IRanges/R/Rle-class-leftovers.R0000644000175100017510000001014512607265143017311 0ustar00biocbuildbiocbuild### ========================================================================= ### IMPORTANT NOTE - 7/2/2014 ### Most of the stuff that used to be in the IRanges/R/Rle-class.R file was ### moved to the S4Vectors package (to R/Rle-class.R and R/Rle-utils.R). ### The stuff that could not be moved there was *temporarily* kept here in ### Rle-class-leftovers.R but will need to find a new home (in S4Vectors ### or in IRanges). ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor methods. ### setMethod("ranges", "Rle", function(x) IRanges(start(x), width = width(x))) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion ### setAs("Rle", "IRanges", function(from) { if (!is.logical(runValue(from)) || S4Vectors:::anyMissing(runValue(from))) stop("cannot coerce a non-logical 'Rle' or a logical 'Rle' ", "with NAs to an IRanges object") keep <- runValue(from) ## The returned IRanges instance is guaranteed to be normal. ans_start <- start(from)[keep] ans_width <- runLength(from)[keep] new2("IRanges", start=ans_start, width=ans_width, check=FALSE) }) setAs("Rle", "NormalIRanges", function(from) newNormalIRangesFromIRanges(as(from, "IRanges"), check=FALSE)) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### General methods ### ### S3/S4 combo for window.Rle window.Rle <- function(x, start=NA, end=NA, width=NA, frequency=NULL, delta=NULL, ...) { solved_SEW <- solveUserSEWForSingleSeq(length(x), start, end, width) if (is.null(frequency) && is.null(delta)) { info <- S4Vectors:::getStartEndRunAndOffset(x, start(solved_SEW), end(solved_SEW)) runStart <- info[["start"]][["run"]] offsetStart <- info[["start"]][["offset"]] runEnd <- info[["end"]][["run"]] offsetEnd <- info[["end"]][["offset"]] ans <- .Call2("Rle_window", x, runStart, runEnd, offsetStart, offsetEnd, new("Rle"), PACKAGE = "S4Vectors") if (is.factor(runValue(x))) attributes(runValue(ans)) <- list(levels = levels(x), class = "factor") ans } else { idx <- stats:::window.default(seq_len(length(x)), start = start(solved_SEW), end = end(solved_SEW), frequency = frequency, deltat = delta, ...) attributes(idx) <- NULL x[idx] } } setMethod("window", "Rle", window.Rle) setGeneric("findRange", signature = "vec", function(x, vec) standardGeneric("findRange")) setMethod("findRange", signature = c(vec = "Rle"), function(x, vec) { run <- findRun(x, vec) if (S4Vectors:::anyMissing(run)) stop("all 'x' values must be in [1, 'length(vec)']") IRanges(start = start(vec)[run], width = width(vec)[run], names = names(x)) }) setGeneric("orderAsRanges", signature = c("x"), # not exported function(x, na.last = TRUE, decreasing = FALSE) standardGeneric("orderAsRanges")) setMethod("orderAsRanges", "Rle", function(x, na.last = TRUE, decreasing = FALSE) { ord <- S4Vectors:::orderInteger(runValue(x), na.last = na.last, decreasing = decreasing) new2("IRanges", start = start(x)[ord], width = runLength(x)[ord], check = FALSE) }) setGeneric("splitRanges", signature = "x", function(x) standardGeneric("splitRanges")) setMethod("splitRanges", "Rle", function(x) { split(IRanges(start = start(x), width = runLength(x)), runValue(x)) }) setMethod("splitRanges", "vectorORfactor", function(x) { callGeneric(Rle(x)) }) IRanges/R/RleViews-class.R0000644000175100017510000001043612607265143016323 0ustar00biocbuildbiocbuild### ========================================================================= ### RleViews objects ### ------------------------------------------------------------------------- ### ### The RleViews class is the basic container for storing a set of views ### (start/end locations) on the same Rle object, called the "subject" ### vector. setClass("RleViews", contains=c("Views", "RleList"), representation( subject="Rle" ) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### User-friendly constructor. ### setMethod("Views", "Rle", function(subject, start=NULL, end=NULL, width=NULL, names=NULL) newViews(subject, start=start, end=end, width=width, names=names, Class="RleViews") ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### setAs("AtomicList", "RleViews", function(from) { to <- Views(as(unlist(from, use.names = FALSE), "Rle"), PartitioningByWidth(elementLengths(from))) names(to) <- names(from) to }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "show" method. ### ### The 2 helper functions below convert a given view on an Rle object ### into a character-string. ### Both assume that 'start' <= 'end' (so they don't check it) and ### padd the result with spaces to produce the "margin effect" ### if 'start' or 'end' are out of limits. RleViews.show_vframe_header <- function(iW, startW, endW, widthW) { cat(format("", width=iW+1), format("start", width=startW, justify="right"), " ", format("end", width=endW, justify="right"), " ", format("width", width=widthW, justify="right"), "\n", sep="") } RleViews.show_vframe_line <- function(x, i, iW, startW, endW, widthW) { lsx <- length(subject(x)) start <- start(x)[i] end <- end(x)[i] width <- end - start + 1 snippetWidth <- getOption("width") - 10 - iW - startW - endW - widthW if (width > 0 && lsx > 0 && start <= lsx && end >= 1) { snippetStart <- max(min(start,lsx),1) snippetEnd <- max(min(end,lsx,start + snippetWidth),1) snippet <- format(as.vector(extractROWS(subject(x), IRanges(snippetStart, snippetEnd)))) snippet <- snippet[cumsum(nchar(snippet) + 1L) < snippetWidth] if (length(snippet) < width) { snippet <- c(snippet, "...") } snippet <- paste(snippet, collapse = " ") } else { snippet <- " " } cat(format(paste("[", i,"]", sep=""), width=iW, justify="right"), " ", format(start, width=startW, justify="right"), " ", format(end, width=endW, justify="right"), " ", format(width, width=widthW, justify="right"), " ", "[", snippet, "]\n", sep="") } ### 'half_nrow' must be >= 1 RleViews.show_vframe <- function(x, half_nrow=9L) { cat("\nviews:") lx <- length(x) if (lx == 0) cat(" NONE\n") else { cat("\n") iW <- nchar(as.character(lx)) + 2 # 2 for the brackets startMax <- max(start(x)) startW <- max(nchar(startMax), nchar("start")) endMax <- max(end(x)) endW <- max(nchar(endMax), nchar("end")) widthMax <- max(width(x)) widthW <- max(nchar(widthMax), nchar("width")) RleViews.show_vframe_header(iW, startW, endW, widthW) if (lx <= 2*half_nrow+1) { for (i in seq_len(lx)) RleViews.show_vframe_line(x, i, iW, startW, endW, widthW) } else { for (i in 1:half_nrow) RleViews.show_vframe_line(x, i, iW, startW, endW, widthW) cat(format("...", width=iW, justify="right"), " ", format("...", width=startW, justify="right"), " ", format("...", width=endW, justify="right"), " ", format("...", width=widthW, justify="right"), " ...\n", sep="") for (i in (lx-half_nrow+1L):lx) RleViews.show_vframe_line(x, i, iW, startW, endW, widthW) } } } setMethod("show", "RleViews", function(object) { cat("Views on a ", length(subject(object)), "-length Rle subject\n", sep="") RleViews.show_vframe(object) } ) IRanges/R/RleViews-utils.R0000644000175100017510000000443412607265143016357 0ustar00biocbuildbiocbuild### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "viewApply", "viewMins", "viewMaxs", and "viewSums" generics and ### methods. ### setMethod("viewApply", "RleViews", function(X, FUN, ..., simplify = TRUE) { X <- trim(X) ans <- aggregate(subject(X), start = structure(start(X), names = names(X)), end = end(X), FUN = FUN, ..., simplify = simplify) if (!simplify) { ans <- S4Vectors:::new_SimpleList_from_list("SimpleList", ans, metadata=metadata(X), mcols=mcols(X)) } ans }) setMethod("viewMins", "RleViews", function(x, na.rm = FALSE) .Call2("RleViews_viewMins", trim(x), na.rm, PACKAGE="IRanges")) setMethod("viewMaxs", "RleViews", function(x, na.rm = FALSE) .Call2("RleViews_viewMaxs", trim(x), na.rm, PACKAGE="IRanges")) setMethod("viewSums", "RleViews", function(x, na.rm = FALSE) .Call2("RleViews_viewSums", trim(x), na.rm, PACKAGE="IRanges")) setMethod("viewMeans", "RleViews", function(x, na.rm = FALSE) .Call2("RleViews_viewMeans", trim(x), na.rm, PACKAGE="IRanges")) setMethod("viewWhichMins", "RleViews", function(x, na.rm = FALSE) .Call2("RleViews_viewWhichMins", trim(x), na.rm, PACKAGE="IRanges")) setMethod("viewWhichMaxs", "RleViews", function(x, na.rm = FALSE) .Call2("RleViews_viewWhichMaxs", trim(x), na.rm, PACKAGE="IRanges")) setMethod("viewRangeMaxs", "RleViews", function(x, na.rm = FALSE) { maxs <- viewWhichMaxs(trim(x), na.rm = na.rm) if (S4Vectors:::anyMissing(maxs)) stop("missing values present, set 'na.rm = TRUE'") findRange(maxs, subject(x)) }) setMethod("viewRangeMins", "RleViews", function(x, na.rm = FALSE) { mins <- viewWhichMins(trim(x), na.rm = na.rm) if (S4Vectors:::anyMissing(mins)) stop("missing values present, set 'na.rm = TRUE'") findRange(mins, subject(x)) }) IRanges/R/RleViewsList-class.R0000644000175100017510000000743312607265143017162 0ustar00biocbuildbiocbuild### ========================================================================= ### RleViewsList objects ### ------------------------------------------------------------------------- setClass("RleViewsList", representation("VIRTUAL"), prototype = prototype(elementType = "RleViews"), contains = "ViewsList") setClass("SimpleRleViewsList", prototype = prototype(elementType = "RleViews"), contains = c("RleViewsList", "SimpleViewsList")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor. ### setMethod("subject", "SimpleRleViewsList", function(x) S4Vectors:::new_SimpleList_from_list("SimpleRleList", lapply(x, slot, "subject")) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor. ### setMethod("Views", "RleList", function(subject, start=NULL, end=NULL, width=NULL, names=NULL) RleViewsList(rleList = subject, rangesList = start)) RleViewsList <- function(..., rleList, rangesList, universe = NULL) { if (!is.null(universe) && !isSingleString(universe)) stop(wmsg("'universe' must be a single string or NULL")) views <- list(...) if (!missing(rleList) && !missing(rangesList)) { if (length(views) > 0) stop(wmsg("'...' must be empty when 'rleList' and 'rangesList' ", "are specified")) if (!is(rleList, "RleList")) stop(wmsg("'rleList' must be a RleList object")) if (!is(rangesList, "RangesList")) { rangesList <- try(IRangesList(rangesList), silent = TRUE) if (inherits(rangesList, "try-error")) stop(wmsg("'rangesList' must be a RangesList object")) } if (length(rleList) != length(rangesList)) stop("'rleList' and 'rangesList' must have the same length") rleList_names <- names(rleList) rangesList_names <- names(rangesList) if (!(is.null(rleList_names) || is.null(rangesList_names) || identical(rleList_names, rangesList_names))) { if (anyDuplicated(rleList_names,) || anyDuplicated(rangesList_names)) stop(wmsg("when both 'rleList' and 'rangesList' have names, ", "the names on each object cannot have duplicates")) if (!setequal(rleList_names, rangesList_names)) stop(wmsg("when both 'rleList' and 'rangesList' have names, ", "the set of names must be the same on each object")) warning(wmsg("'rleList' was reordered so that its names ", "match the names on 'rangesList'")) rleList <- rleList[rangesList_names] } views <- Map(Views, rleList, rangesList) } else if ((length(views) > 0) && (!missing(rleList) || !missing(rangesList))) { stop(wmsg("cannot specify 'rleList' or 'rangesList' ", "when specifying '...'")) } else { if (length(views) == 1 && is.list(views[[1L]])) views <- views[[1L]] if (!all(sapply(views, is, "RleViews"))) stop(wmsg("all elements in '...' must be RleViews objects")) } ans <- S4Vectors:::new_SimpleList_from_list("SimpleRleViewsList", views) universe(ans) <- universe ans } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### setAs("RleViewsList", "IRangesList", function(from) IRangesList(lapply(from, as, "IRanges"))) setAs("RleViewsList", "CompressedIRangesList", function(from) IRangesList(lapply(from, as, "IRanges"), compress=TRUE)) setAs("RleViewsList", "SimpleIRangesList", function(from) IRangesList(lapply(from, as, "IRanges"), compress=FALSE)) IRanges/R/RleViewsList-utils.R0000644000175100017510000000737512607265143017222 0ustar00biocbuildbiocbuild### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "viewApply", "viewMins", "viewMaxs", and "viewSums" generics and ### methods. ### setMethod("viewApply", "RleViewsList", function(X, FUN, ..., simplify = TRUE) { ans_listData <- lapply(structure(seq_along(X), names=names(X)), function(i) { ans_elt <- aggregate( subject(X[[i]]), start=structure(start(X[[i]]), names=names(start(X[[i]]))), end=end(X[[i]]), FUN=FUN, ..., simplify=simplify) if (!simplify) ans_elt <- S4Vectors:::new_SimpleList_from_list("SimpleList", ans_elt, metadata=metadata(X[[i]]), mcols=mcols(X[[i]])) ans_elt }) S4Vectors:::new_SimpleList_from_list("SimpleList", ans_listData, metadata=metadata(X), mcols=mcols(X))}) .summaryRleViewsList <- function(x, FUN, na.rm = FALSE, outputListType = NULL) { FUN <- match.fun(FUN) if (length(x) == 0) { outputListType <- "SimpleList" listData <- list() } else { if (is.null(outputListType)) { valuesClass <- class(runValue(subject(x[[1L]]))) if (valuesClass == "integer" || valuesClass == "logical") outputListType <- "SimpleIntegerList" else if (valuesClass == "numeric") outputListType <- "SimpleNumericList" else stop("cannot compute numeric summary over a non-numeric Rle") } listData <- lapply(structure(seq_len(length(x)), names = names(x)), function(i) FUN(x[[i]], na.rm = na.rm)) } S4Vectors:::new_SimpleList_from_list(outputListType, listData, metadata = metadata(x), mcols = mcols(x)) } setMethod("viewMins", "RleViewsList", function(x, na.rm = FALSE) .summaryRleViewsList(x, FUN = viewMins, na.rm = na.rm)) setMethod("viewMaxs", "RleViewsList", function(x, na.rm = FALSE) .summaryRleViewsList(x, FUN = viewMaxs, na.rm = na.rm)) setMethod("viewSums", "RleViewsList", function(x, na.rm = FALSE) .summaryRleViewsList(x, FUN = viewSums, na.rm = na.rm)) setMethod("viewMeans", "RleViewsList", function(x, na.rm = FALSE) .summaryRleViewsList(x, FUN = viewMeans, na.rm = na.rm, outputListType = "SimpleNumericList")) setMethod("viewWhichMins", "RleViewsList", function(x, na.rm = FALSE) .summaryRleViewsList(x, FUN = viewWhichMins, na.rm = na.rm, outputListType = "SimpleIntegerList")) setMethod("viewWhichMaxs", "RleViewsList", function(x, na.rm = FALSE) .summaryRleViewsList(x, FUN = viewWhichMaxs, na.rm = na.rm, outputListType = "SimpleIntegerList")) setMethod("viewRangeMaxs", "RleViewsList", function(x, na.rm = FALSE) .summaryRleViewsList(x, FUN = viewRangeMaxs, na.rm = na.rm, outputListType = "SimpleIRangesList")) setMethod("viewRangeMins", "RleViewsList", function(x, na.rm = FALSE) .summaryRleViewsList(x, FUN = viewRangeMins, na.rm = na.rm, outputListType = "SimpleIRangesList")) IRanges/R/Vector-class-leftovers.R0000644000175100017510000001726412607265143020042 0ustar00biocbuildbiocbuild### ========================================================================= ### IMPORTANT NOTE - 4/29/2014 ### Most of the stuff that used to be in the IRanges/R/Vector-class.R file ### was moved to the S4Vectors package (to R/Vector-class.R). ### The stuff that could not be moved there was *temporarily* kept here in ### Vector-class-leftovers.R but will need to find a new home (in S4Vectors ### or in IRanges). ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Internal utility. ### setMethod("showAsCell", "list", function(object) rep.int("########", length(object))) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Convenience wrappers for common subsetting operations. ### ### S3/S4 combo for window<-.Vector `window<-.Vector` <- function(x, start=NA, end=NA, width=NA, ..., value) { i <- solveUserSEWForSingleSeq(NROW(x), start, end, width) li <- width(i) if (li == 0L) { ## Surprisingly, in that case, `[<-` on standard vectors does not ## even look at 'value'. So neither do we... return(x) } lv <- NROW(value) if (lv == 0L) stop("replacement has length zero") value <- normalizeSingleBracketReplacementValue(value, x) if (li != lv) { if (li %% lv != 0L) warning("number of values supplied is not a sub-multiple ", "of the number of values to be replaced") value <- extractROWS(value, rep(seq_len(lv), length.out=li)) } c(window(x, end=start(i)-1L), value, window(x, start=end(i)+1L)) } setReplaceMethod("window", "Vector", `window<-.Vector`) ### S3/S4 combo for window<-.vector `window<-.vector` <- `window<-.Vector` setReplaceMethod("window", "vector", `window<-.vector`) ### S3/S4 combo for window<-.factor `window<-.factor` <- function(x, start=NA, end=NA, width=NA, ..., value) { levels <- levels(x) x <- as.character(x) value <- as.character(value) factor(callGeneric(), levels=levels) } setReplaceMethod("window", "factor", `window<-.factor`) setMethod("rev", "Vector", function(x) { if (length(x) == 0L) return(x) x[length(x):1] } ) setMethod("rep", "Vector", function(x, ...) x[rep(seq_len(length(x)), ...)]) setMethod("rep.int", "Vector", function(x, times) x[rep.int(seq_len(length(x)), times)] ) setMethod("subset", "Vector", function(x, subset, select, drop = FALSE, ...) { i <- S4Vectors:::evalqForSubset(subset, x, ...) if (!is.null(mcols(x))) { j <- S4Vectors:::evalqForSelect(select, mcols(x), ...) mcols(x) <- mcols(x)[,j,drop=FALSE] } x[i, drop=drop] }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### ### S3/S4 combo for as.list.Vector as.list.Vector <- function(x, ...) as.list(as(x, "List"), ...) setMethod("as.list", "Vector", as.list.Vector) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### mstack() ### setGeneric("mstack", function(..., .index.var = "name") standardGeneric("mstack"), signature = "...") setMethod("mstack", "Vector", function(..., .index.var = "name") { if (!isSingleString(.index.var)) stop("'.index.var' must be a single, non-NA string") args <- list(...) combined <- compress_listData(args) df <- .stack.ind(args, .index.var) if (!is.null(mcols(combined))) df <- cbind(mcols(combined), df) mcols(combined) <- df combined }) setMethod("mstack", "vector", function(..., .index.var = "name") { if (!isSingleString(.index.var)) stop("'.index.var' must be a single, non-NA string") args <- list(...) combined <- compress_listData(args) df <- DataFrame(.stack.ind(args, .index.var), combined) if (ncol(df) == 2L) colnames(df)[2] <- "value" df }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Looping methods. ### #.tapplyDefault <- base::tapply #environment(.tapplyDefault) <- topenv() .tapplyDefault <- function(X, INDEX, FUN = NULL, ..., simplify = TRUE) { if (!is.null(FUN)) FUN <- match.fun(FUN) if (missing(INDEX)) stop("'INDEX' is missing") if (!is(INDEX, "RleList")) { if (!is.list(INDEX) && !is(INDEX, "Rle")) INDEX <- Rle(INDEX) INDEX <- RleList(INDEX) } nI <- length(INDEX) namelist <- vector("list", nI) names(namelist) <- names(INDEX) extent <- integer(nI) nx <- length(X) one <- 1L group <- Rle(one, nx) ngroup <- one for (i in seq_len(nI)) { index <- INDEX[[i]] if (!is.factor(runValue(index))) runValue(index) <- factor(runValue(index)) offset <- index runValue(offset) <- ngroup * (as.integer(runValue(index)) - one) if (length(index) != nx) stop("arguments must have same length") namelist[[i]] <- levels(index) extent[i] <- nlevels(index) group <- group + offset ngroup <- ngroup * nlevels(index) } if (is.null(FUN)) return(as.vector(group)) groupRanges <- splitRanges(group) ans <- lapply(groupRanges, function(i) FUN(extractROWS(X, i), ...)) index <- as.integer(names(ans)) if (simplify && all(unlist(lapply(ans, length), use.names=FALSE) == 1L)) { ansmat <- array(dim = extent, dimnames = namelist) ans <- unlist(ans, recursive = FALSE) } else { ansmat <- array(vector("list", prod(extent)), dim = extent, dimnames = namelist) } if (length(index) > 0) { names(ans) <- NULL ansmat[index] <- ans } ansmat } setMethod("tapply", c("Vector", "ANY"), .tapplyDefault) setMethod("tapply", c("ANY", "Vector"), .tapplyDefault) setMethod("tapply", c("Vector", "Vector"), .tapplyDefault) .shiftApplyInternal <- function(SHIFT, X, Y, FUN, ..., OFFSET = 0L, simplify = TRUE, verbose = FALSE) { FUN <- match.fun(FUN) N <- length(X) if (N != length(Y)) stop("'X' and 'Y' must be of equal length") if (!is.integer(SHIFT)) SHIFT <- as.integer(SHIFT) if (length(SHIFT) == 0 || S4Vectors:::anyMissingOrOutside(SHIFT, 0L)) stop("all 'SHIFT' values must be non-negative") if (!is.integer(OFFSET)) OFFSET <- as.integer(OFFSET) if (length(OFFSET) == 0 || S4Vectors:::anyMissingOrOutside(OFFSET, 0L)) stop("'OFFSET' must be non-negative") ## Perform X setup shiftedStartX <- rep.int(1L + OFFSET, length(SHIFT)) shiftedEndX <- N - SHIFT ## Perform Y setup shiftedStartY <- 1L + SHIFT shiftedEndY <- rep.int(N - OFFSET, length(SHIFT)) if (verbose) { maxI <- length(SHIFT) ans <- sapply(seq_len(length(SHIFT)), function(i) { cat("\r", i, "/", maxI) FUN(window(X, start = shiftedStartX[i], end = shiftedEndX[i]), window(Y, start = shiftedStartY[i], end = shiftedEndY[i]), ...) }, simplify = simplify) cat("\n") } else { ans <- sapply(seq_len(length(SHIFT)), function(i) FUN(window(X, start = shiftedStartX[i], end = shiftedEndX[i]), window(Y, start = shiftedStartY[i], end = shiftedEndY[i]), ...), simplify = simplify) } ans } setMethod("shiftApply", signature(X = "Vector", Y = "Vector"), .shiftApplyInternal) setMethod("shiftApply", signature(X = "vector", Y = "vector"), .shiftApplyInternal) IRanges/R/Views-class.R0000644000175100017510000002617712607265143015671 0ustar00biocbuildbiocbuild### ========================================================================= ### Views objects ### ------------------------------------------------------------------------- ### ### The Views virtual class is a general container for storing a set of views ### on an arbitrary Vector object, called the "subject". ### setClass("Views", contains="List", representation( "VIRTUAL", subject="Vector", ranges="IRanges" ) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor methods. ### setGeneric("subject", function(x) standardGeneric("subject")) setMethod("subject", "Views", function(x) x@subject) setGeneric("ranges", function(x, ...) standardGeneric("ranges")) setMethod("ranges", "Views", function(x) x@ranges) setGeneric("ranges<-", function(x, ..., value) standardGeneric("ranges<-")) setReplaceMethod("ranges", "Views", function(x, ..., value) { stop("ranges setter for Views objects not ready yet") } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Methods derived from the IRanges interface. ### setMethod("length", "Views", function(x) length(ranges(x))) setMethod("start", "Views", function(x, ...) start(ranges(x))) setMethod("end", "Views", function(x, ...) end(ranges(x))) setMethod("width", "Views", function(x) width(ranges(x))) setMethod("names", "Views", function(x) names(ranges(x))) setReplaceMethod("start", "Views", function(x, ..., value) { start(x@ranges, ...) <- value x } ) setReplaceMethod("end", "Views", function(x, ..., value) { end(x@ranges, ...) <- value x } ) setReplaceMethod("width", "Views", function(x, ..., value) { width(x@ranges, ...) <- value x } ) setReplaceMethod("names", "Views", function(x, value) { names(x@ranges) <- value x } ) setMethod("extractROWS", "Views", function(x, i) { i <- normalizeSingleBracketSubscript(i, x, as.NSBS=TRUE) x@ranges <- extractROWS(ranges(x), i) mcols(x) <- extractROWS(mcols(x), i) x } ) setMethod("elementLengths", "Views", function(x) width(x)) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity. ### .valid.Views.width <- function(x) { if (length(width(x)) != 0L && min(width(x)) <= 0L) return("null widths are not allowed") NULL } setValidity2("Views", .valid.Views.width) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The low-level "Views" constructor. ### ### TODO: - add a 'check.limits' arg (default to TRUE) for raising an error if ### some views are "out of limits". ### newViews <- function(subject, start=NULL, end=NULL, width=NULL, names=NULL, Class=NULL) { if (is(start, "Ranges")) { if (!is.null(end) || !is.null(width)) stop("'end' and 'width' must be NULLs when 'start' is a Ranges object") ranges <- start if (class(ranges) != "IRanges") ranges <- as(ranges, "IRanges") ## Keep the names that are already in 'ranges' unless the 'names' arg ## was specified. if (!is.null(names)) names(ranges) <- names } else { ranges <- IRanges(start=start, end=end, width=width, names=names) } if (is.null(Class)) Class <- paste(class(subject), "Views", sep="") new2(Class, subject=subject, ranges=ranges, check=FALSE) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The user-friendly "Views" constructor. ### ### TODO: Same as for the newViews() function above. ### setGeneric("Views", signature="subject", function(subject, start=NULL, end=NULL, width=NULL, names=NULL) standardGeneric("Views") ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion. ### ### Returns a single view covering the entire sequence. setAs("Vector", "Views", function(from) Views(from, start=1L, width=length(from)) ) setAs("Views", "Ranges", function(from) ranges(from)) setAs("Views", "IRanges", function(from) ranges(from)) ### Unfortunately, even if we've already defined the IRanges->NormalIRanges ### "coerce" method to override the silly implicit one, we still need to ### define the ->NormalIRanges ones for every that contains ### IRanges. Otherwise, again, 'as(x, "NormalIRanges")' would call another ### silly implicit method when 'x' is a instance. ### Yes, this is another S4 "feature": ### https://stat.ethz.ch/pipermail/r-devel/2008-April/049027.html setAs("Views", "NormalIRanges", function(from) asNormalIRanges(ranges(from), force=TRUE) ) setMethod("as.matrix", "Views", function(x, rev = FALSE, max.width = NA) { x_ranges <- restrict(ranges(x), start = 1L) if (is.na(max.width)) { max.width <- max(width(x_ranges)) } rev <- S4Vectors:::recycleVector(rev, length(x)) part <- PartitioningByWidth(x_ranges) ord <- S4Vectors:::mseq(ifelse(rev, end(part), start(part)), ifelse(rev, start(part), end(part))) v <- extractROWS(subject(x), x_ranges)[ord] v_fill <- rep.int(NA, max.width * length(x)) part <- PartitioningByWidth(rep(max.width, length(x))) i <- as.integer(IRanges(start(part), width = width(x_ranges))) v_fill[i] <- as.vector(v) matrix(v_fill, ncol = max.width, byrow = TRUE, dimnames = list(names(x), NULL)) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Extracting a view. ### setMethod("getListElement", "Views", function(x, i, exact=TRUE) { i <- normalizeDoubleBracketSubscript(i, x, exact=exact, error.if.nomatch=TRUE) start <- start(x)[i] end <- end(x)[i] if (start < 1L || end > length(subject(x))) stop("view is out of limits") extractROWS(subject(x), IRanges(start, end)) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Combining Views objects. ### setMethod("c", "Views", function(x, ..., ignore.mcols=FALSE, recursive=FALSE) { if (!identical(recursive, FALSE)) stop("\"c\" method for Views objects ", "does not support the 'recursive' argument") if (!isTRUEorFALSE(ignore.mcols)) stop("'ignore.mcols' must be TRUE or FALSE") if (missing(x)) { args <- unname(list(...)) x <- args[[1L]] } else { args <- unname(list(x, ...)) } if (length(args) == 1L) return(x) arg_is_null <- sapply(args, is.null) if (any(arg_is_null)) args[arg_is_null] <- NULL # remove NULL elements by setting them to NULL! if (!all(sapply(args, is, class(x)))) stop("all arguments in '...' must be ", class(x), " objects (or NULLs)") ok <- sapply(args, function(arg) isTRUE(all.equal(subject(arg), subject(x)))) if (!all(ok)) stop("all Views objects to combine must have the same subject") x@ranges <- do.call(c, lapply(args, ranges)) if (ignore.mcols) { mcols(x) <- NULL } else { mcols(x) <- do.call(S4Vectors:::rbind_mcols, args) } validObject(x) x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "trim" function. ### setGeneric("trim", signature="x", function(x, use.names=TRUE, ...) standardGeneric("trim") ) setMethod("trim", "Views", function(x, use.names=TRUE) { if (length(x) == 0L) return(x) if (min(start(x)) >= 1L && max(end(x)) <= length(subject(x))) return(x) x@ranges <- restrict(ranges(x), start=1L, end=length(subject(x)), keep.all.ranges=TRUE, use.names=use.names) x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "subviews" function. ### ### TODO: - add a 'check.limits' arg (default to TRUE) for raising an error if ### some views are "out of limits" setGeneric("subviews", signature="x", function(x, start=NA, end=NA, width=NA, use.names=TRUE) standardGeneric("subviews") ) setMethod("subviews", "Views", function(x, start=NA, end=NA, width=NA, use.names=TRUE) trim(narrow(x, start=start, end=end, width=width, use.names=use.names)) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "successiveViews" function. ### successiveViews <- function(subject, width, gapwidth=0, from=1) { ranges <- successiveIRanges(width, gapwidth=gapwidth, from=from) Views(subject, ranges) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "viewApply" function. ### setGeneric("viewApply", signature="X", function(X, FUN, ..., simplify = TRUE) standardGeneric("viewApply") ) setMethod("viewApply", "Views", function(X, FUN, ..., simplify = TRUE) { X <- trim(X) Xsubject <- subject(X) Xstart <- start(X) Xwidth <- width(X) ans <- sapply(structure(seq_len(length(X)), names=names(X)), function(i) FUN(extractROWS(Xsubject, IRanges(start=Xstart[i], width=Xwidth[i])), ...), simplify = simplify) if (!simplify) { ans <- S4Vectors:::new_SimpleList_from_list("SimpleList", ans, metadata = metadata(X), mcols = mcols(X)) } ans } ) setGeneric("viewMins", signature="x", function(x, na.rm = FALSE) standardGeneric("viewMins")) setGeneric("viewMaxs", signature="x", function(x, na.rm = FALSE) standardGeneric("viewMaxs")) setGeneric("viewSums", signature="x", function(x, na.rm = FALSE) standardGeneric("viewSums")) setGeneric("viewMeans", signature="x", function(x, na.rm = FALSE) standardGeneric("viewMeans")) setGeneric("viewWhichMins", signature="x", function(x, na.rm = FALSE) standardGeneric("viewWhichMins")) setGeneric("viewWhichMaxs", signature="x", function(x, na.rm = FALSE) standardGeneric("viewWhichMaxs")) setGeneric("viewRangeMaxs", function(x, na.rm = FALSE) standardGeneric("viewRangeMaxs")) setGeneric("viewRangeMins", function(x, na.rm = FALSE) standardGeneric("viewRangeMins")) setMethod("Summary", "Views", function(x, ..., na.rm = FALSE) { viewSummaryFunMap <- list(min = viewMins, max = viewMaxs, sum = viewSums) viewSummaryFun <- viewSummaryFunMap[[.Generic]] if (!is.null(viewSummaryFun)) { if (length(list(...))) stop("Passing multiple arguments to '", .Generic, "' is not supported.") viewSummaryFun(x, na.rm = na.rm) } else { Summary(ranges(x), ..., na.rm = na.rm) } }) setMethod("mean", "Views", viewMeans) setMethod("which.max", "Views", function(x) { viewWhichMaxs(x, na.rm = TRUE) }) setMethod("which.min", "Views", function(x) { viewWhichMins(x, na.rm = TRUE) }) IRanges/R/ViewsList-class.R0000644000175100017510000000524512607265143016516 0ustar00biocbuildbiocbuild### ========================================================================= ### ViewsList objects ### ------------------------------------------------------------------------- setClass("ViewsList", contains="List", representation("VIRTUAL"), prototype(elementType="Views") ) setClass("SimpleViewsList", contains=c("ViewsList", "SimpleList"), representation("VIRTUAL"), prototype(elementType="Views") ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor methods. ### setMethod("ranges", "SimpleViewsList", function(x, ...) S4Vectors:::new_SimpleList_from_list("SimpleIRangesList", lapply(x, ranges)) ) setMethod("start", "SimpleViewsList", function(x, ...) start(ranges(x))) setMethod("end", "SimpleViewsList", function(x, ...) end(ranges(x))) setMethod("width", "SimpleViewsList", function(x) width(ranges(x))) ### TODO: Why not define this at the List level? Or even at the Vector level? setMethod("universe", "ViewsList", function(x) { ### FIXME: for compatibility with older versions, eventually emit warning if (is.null(metadata(x)) || is.character(metadata(x))) metadata(x) else metadata(x)$universe }) ### TODO: Why not define this at the List level? Or even at the Vector level? setReplaceMethod("universe", "ViewsList", function(x, value) { if (!is.null(value) && !isSingleString(value)) stop("'value' must be a single string or NULL") metadata(x)$universe <- value x }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion ### setMethod("as.matrix", "ViewsList", function(x, rev = FALSE, use.names = FALSE) { if (!isTRUEorFALSE(use.names)) stop("use.names must be TRUE or FALSE") rev <- normargAtomicList1(rev, LogicalList, length(x)) max_width <- max(max(width(restrict(ranges(x), start = 1L)))) m <- do.call(rbind, mapply(as.matrix, x, rev, IntegerList(max_width), SIMPLIFY = FALSE)) nms <- names(x) if (!is.null(nms) && use.names) { nms <- rep(nms, elementLengths(x)) rownms <- rownames(m) if (is.null(rownms)) rownms <- as.integer(IRanges(1L, width = elementLengths(x))) rownames(m) <- paste(nms, rownms, sep = ".") } m }) IRanges/R/cbind-Rle-methods.R0000644000175100017510000000325412607265143016720 0ustar00biocbuildbiocbuild### ========================================================================= ### Binding Rle or RleList objects together ### ------------------------------------------------------------------------- ### Return a DataFrame object with 1 row per run. Its first column is ### "runLength" and is followed by 1 column per supplied Rle object. setMethod("cbind", "Rle", function(...) { args <- list(...) args_names <- names(args) if (is.null(args_names)) { noname_idx <- seq_along(args) } else { noname_idx <- which(args_names %in% c("", NA_character_)) } if (length(noname_idx) != 0L) names(args)[noname_idx] <- paste0("V", noname_idx) ## TODO: Add 'with.revmap' arg to disjoin method for Ranges object. ## Then use that feature to avoid the call to findOverlaps() below. ans_runs <- disjoin(do.call(c, unname(lapply(args, ranges)))) DataFrame( runLength=width(ans_runs), DataFrame( lapply(args, function(x) { run_idx <- findOverlaps(ans_runs, ranges(x), type="within", select="arbitrary") runValue(x)[run_idx] }) ) ) } ) ### The supplied RleList objects are recycled the "mapply way" if necessary. ### Return a CompressedSplitDataFrameList object parallel to the longest ### supplied RleList object. setMethod("cbind", "RleList", function(...) { args <- list(...) DF_list <- do.call(mapply, c(list(cbind), args, list(SIMPLIFY=FALSE))) as(DF_list, "CompressedSplitDataFrameList") } ) IRanges/R/coverage-methods.R0000644000175100017510000002571512607265143016722 0ustar00biocbuildbiocbuild### ========================================================================= ### coverage() ### ------------------------------------------------------------------------- ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### .IRanges.coverage() and .CompressedIRangesList.coverage() ### ### These 2 internal helpers are the workhorses behind most "coverage" ### methods. All the hard work is almost entirely performed at the C level. ### Only some argument checking/normalization plus the "folding" of the ### result are performed in R. ### .fold_and_truncate_coverage <- function(cvg, circle.length, width) { cvg <- fold(cvg, circle.length) if (is.na(width)) return(cvg) head(cvg, n=width) } ### Returns an Rle object. .IRanges.coverage <- function(x, shift=0L, width=NULL, weight=1L, circle.length=NA, method=c("auto", "sort", "hash")) { ## Check 'x'. if (!is(x, "IRanges")) stop("'x' must be an IRanges object") ## 'shift' will be checked at the C level. if (is(shift, "Rle")) shift <- S4Vectors:::decodeRle(shift) ## Check 'width'. if (is.null(width)) { width <- NA_integer_ } else if (!isSingleNumberOrNA(width)) { stop("'width' must be NULL or a single integer") } else if (!is.integer(width)) { width <- as.integer(width) } ## 'weight' will be checked at the C level. if (is(weight, "Rle")) weight <- S4Vectors:::decodeRle(weight) ## Check 'circle.length'. if (!isSingleNumberOrNA(circle.length)) stop("'circle.length' must be a single integer") if (!is.integer(circle.length)) circle.length <- as.integer(circle.length) ## Check 'method'. method <- match.arg(method) ## Ready to go... ans <- .Call2("IRanges_coverage", x, shift, width, weight, circle.length, method, PACKAGE="IRanges") if (is.na(circle.length)) return(ans) .fold_and_truncate_coverage(ans, circle.length, width) } ### Returns an ordinary list. .normarg_shift_or_weight <- function(arg, arg.label) { if (!is.list(arg)) { if (!(is.numeric(arg) || (is(arg, "Rle") && is.numeric(runValue(arg))) || is(arg, "List"))) stop("'", arg.label, "' must be a numeric vector ", "or a list-like object") arg <- as.list(arg) } if (length(arg) != 0L) { idx <- which(sapply(arg, is, "Rle")) if (length(idx) != 0L) arg[idx] <- lapply(arg[idx], S4Vectors:::decodeRle) } arg } .check_arg_names <- function(arg, arg.label, x_names, x_names.label) { arg_names <- names(arg) if (!(is.null(arg_names) || identical(arg_names, x_names))) stop("when '", arg.label, "' has names, ", "they must be identical to ", x_names.label) } ## Some packages like easyRNASeq or TEQC pass 'width' as a named list-like ## object where each list element is a single number, an NA, or a NULL, when ## calling coverage() on a RangesList or RangedData object. They do so because, ## for whatever reason, we've been supporting this for a while, and also ## because, in the case of the method for RangedData objects, the arg default ## for 'width' used to be such a list (a named list of NULLs in that case). ## However, it never really made sense to support a named list-like object for ## 'width', and it makes even less sense now that the signature of the method ## for RangedData objects has been modified (as of BioC 2.13) to use the same ## arg defaults as the coverage() generic and all other methods. ## TODO: Deprecate support for this. Preferred 'width' form: NULL or an integer ## vector. An that's it. .unlist_width <- function(width, x_names, x_names.label) { if (!identical(names(width), x_names)) stop("when 'width' is a list-like object, it must be named ", "and its names must be identical to ", x_names.label) width_eltlens <- elementLengths(width) if (!all(width_eltlens <= 1L)) stop("when 'width' is a list-like object, each list element ", "should contain at most 1 element or be NULL") width[width_eltlens == 0L] <- NA_integer_ setNames(unlist(width, use.names=FALSE), x_names) } ### Returns a SimpleRleList object of the length of 'x'. .CompressedIRangesList.coverage <- function(x, shift=0L, width=NULL, weight=1L, circle.length=NA, method=c("auto", "sort", "hash"), x_names.label="'x' names") { ## Check 'x'. if (!is(x, "CompressedIRangesList")) stop("'x' must be a CompressedIRangesList object") x_names <- names(x) ## Check and normalize 'shift'. shift <- .normarg_shift_or_weight(shift, "shift") .check_arg_names(shift, "shift", x_names, x_names.label) ## Check and normalize 'width'. if (is.null(width)) { width <- NA_integer_ } else { if (is.numeric(width)) { .check_arg_names(width, "width", x_names, x_names.label) } else if (is.list(width) || is(width, "List")) { width <- .unlist_width(width, x_names, x_names.label) } else { ## We purposedly omit to mention that 'width' can also be a named ## list-like object because this will be deprecated soon (this is ## why it's not documented in man/coverage-methods.Rd either). stop("'width' must be NULL or an integer vector") } if (!is.integer(width)) width <- setNames(as.integer(width), names(width)) } ## Check and normalize 'weight'. weight <- .normarg_shift_or_weight(weight, "weight") .check_arg_names(weight, "weight", x_names, x_names.label) ## Check and normalize 'circle.length'. if (identical(circle.length, NA)) { circle.length <- NA_integer_ } else if (!is.numeric(circle.length)) { stop("'circle.length' must be an integer vector") } else if (!is.integer(circle.length)) { circle.length <- setNames(as.integer(circle.length), names(circle.length)) } .check_arg_names(circle.length, "circle.length", x_names, x_names.label) ## Check and normalize 'method'. method <- match.arg(method) ## Ready to go... ans_listData <- .Call2("CompressedIRangesList_coverage", x, shift, width, weight, circle.length, method, PACKAGE="IRanges") ## "Fold" the coverage vectors in 'ans_listData' associated with a ## circular sequence. ## Note that the C code should have raised an error or warning already if ## the length of 'circle.length' or 'width' didn't allow proprer recycling ## to the length of 'x'. So using silent 'rep( , length.out=length(x))' is ## safe. circle.length <- rep(circle.length, length.out=length(x)) fold_idx <- which(!is.na(circle.length)) if (length(fold_idx) != 0L) { width <- rep(width, length.out=length(x)) ## Because we "fold" the coverage vectors in an lapply() loop, it will ## be inefficient if 'x' has a lot of list elements associated with a ## circular sequence. ans_listData[fold_idx] <- lapply(fold_idx, function(i) .fold_and_truncate_coverage(ans_listData[[i]], circle.length[i], width[i])) } names(ans_listData) <- names(x) S4Vectors:::new_SimpleList_from_list("SimpleRleList", ans_listData, metadata=metadata(x), mcols=mcols(x)) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### coverage() generic and methods. ### setGeneric("coverage", signature="x", function(x, shift=0L, width=NULL, weight=1L, ...) standardGeneric("coverage") ) setMethod("coverage", "Ranges", function(x, shift=0L, width=NULL, weight=1L, method=c("auto", "sort", "hash")) { if (isSingleString(weight)) { x_mcols <- mcols(x) if (!is(x_mcols, "DataTable") || sum(colnames(x_mcols) == weight) != 1L) stop("'mcols(x)' has 0 or more than 1 \"", weight, "\" columns") weight <- x_mcols[[weight]] } .IRanges.coverage(as(x, "IRanges"), shift=shift, width=width, weight=weight, method=method) } ) setMethod("coverage", "Views", function(x, shift=0L, width=NULL, weight=1L, method=c("auto", "sort", "hash")) { if (is.null(width)) width <- length(subject(x)) coverage(as(x, "IRanges"), shift=shift, width=width, weight=weight, method=method) } ) setMethod("coverage", "RangesList", function(x, shift=0L, width=NULL, weight=1L, method=c("auto", "sort", "hash")) { x_mcols <- mcols(x) x_mcolnames <- colnames(x_mcols) if (isSingleString(shift)) { if (!(shift %in% x_mcolnames)) stop("the string supplied for 'shift' (\"", shift, "\")", "is not a valid metadata column name of 'x'") shift <- x_mcols[[shift]] } if (isSingleString(width)) { if (!(width %in% x_mcolnames)) stop("the string supplied for 'width' (\"", width, "\")", "is not a valid metadata column name of 'x'") width <- x_mcols[[width]] } if (isSingleString(weight)) { if (!(weight %in% x_mcolnames)) stop("the string supplied for 'weight' (\"", weight, "\")", "is not a valid metadata column name of 'x'") weight <- x_mcols[[weight]] } .CompressedIRangesList.coverage(as(x, "CompressedIRangesList"), shift=shift, width=width, weight=weight, method=method) } ) setMethod("coverage", "RangedData", function(x, shift=0L, width=NULL, weight=1L, method=c("auto", "sort", "hash")) { x_ranges <- ranges(x) if (length(metadata(x)) > 0) metadata(x_ranges) <- metadata(x) varnames <- colnames(x) if (isSingleString(shift) && (shift %in% varnames)) shift <- values(x)[, shift] if (isSingleString(weight) && (weight %in% varnames)) weight <- values(x)[, weight] coverage(x_ranges, shift=shift, width=width, weight=weight, method=method) } ) IRanges/R/debug.R0000644000175100017510000000062112607265143014541 0ustar00biocbuildbiocbuild### debug_AEbufs <- function() invisible(.Call2("debug_AEbufs", PACKAGE="IRanges")) debug_IRanges_class <- function() invisible(.Call2("debug_IRanges_class", PACKAGE="IRanges")) debug_Grouping_class <- function() invisible(.Call2("debug_Grouping_class", PACKAGE="IRanges")) debug_inter_range_methods <- function() invisible(.Call2("debug_inter_range_methods", PACKAGE="IRanges")) IRanges/R/expand-methods.R0000644000175100017510000000513612607265143016401 0ustar00biocbuildbiocbuild### ========================================================================= ### expand methods ### ------------------------------------------------------------------------- ### setGeneric("expand", signature="x", function(x, ...) standardGeneric("expand") ) ## A helper function to do the work .expandOneCol <- function(x, colname, keepEmptyRows) { if (!is(x, "DataFrame")) stop("'x' must be a DataFrame object") if (!isSingleString(colname) && !isSingleNumber(colname)) stop("'colname' must be a single string or number") col <- x[[colname]] if (is.null(col)) stop("'colname' must be a valid colname name or index") if(keepEmptyRows){ col[elementLengths(col)==0] <- NA } idx <- rep(seq_len(nrow(x)), elementLengths(col)) ans <- x[idx, ] ans[[colname]] <- unlist(col, use.names=FALSE) ans } ## A better helper .expand <- function(x, colnames, keepEmptyRows){ for(colname in colnames) { x <- .expandOneCol(x, colname, keepEmptyRows) } x } ### FIXME: should make is.recursive a generic in base R isRecursive <- function(x) is.recursive(x) || is(x, "List") defaultIndices <- function(x) { which(vapply(x, isRecursive, logical(1L))) } setMethod("expand", "DataFrame", function(x, colnames, keepEmptyRows = FALSE){ stopifnot(isTRUEorFALSE(keepEmptyRows)) if (missing(colnames)) { colnames <- defaultIndices(x) } .expand(x, colnames, keepEmptyRows) } ) setMethod("expand", "Vector", function(x, colnames, keepEmptyRows = FALSE){ stopifnot(isTRUEorFALSE(keepEmptyRows)) if (missing(colnames)) { colnames <- defaultIndices(mcols(x)) } df <- mcols(x) df[["__index__"]] <- seq_along(x) ex <- .expand(df, colnames, keepEmptyRows) mcols(x) <- NULL ans <- x[ex[["__index__"]]] ex[["__index__"]] <- NULL mcols(ans) <- ex ans } ) ## Assume that the named columns have the same geometry and expand ## them simultaneously; this is different from the cartesian product ## expansion above. .expandByColumnSet <- function(x, colnames, keepEmptyRows) { if (length(colnames) == 0L) return(x) if(keepEmptyRows) { emptyRows <- elementLengths(col) == 0L x[emptyRows, colnames] <- rep(NA, sum(emptyRows)) } ans <- x[togroup(x[[colnames[1L]]]),,drop=FALSE] ans[colnames] <- lapply(x[colnames], unlist, use.names = FALSE) ans } IRanges/R/extractList.R0000644000175100017510000003014712607265143015767 0ustar00biocbuildbiocbuild### ========================================================================= ### Group elements of a vector-like object into a list-like object ### ------------------------------------------------------------------------- ### ### What should go in this file? ### ### - relistToClass() generic and default method. ### - All "relist" methods defined in IRanges should go here. ### - extractList() generic and default method. ### ### TODO: Maybe put the default methods for the reverse transformations here ### (unlist, unsplit, and unsplit<-). ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### relistToClass() ### setGeneric("relistToClass", function(x) standardGeneric("relistToClass")) .selectListClassName <- function(x) { cn <- S4Vectors:::listClassName("Compressed", x) if (cn == "CompressedList") cn <- S4Vectors:::listClassName("Simple", x) cn } setMethod("relistToClass", "ANY", function(x) .selectListClassName(class(x))) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### relist() ### setMethod("relist", c("ANY", "PartitioningByEnd"), function(flesh, skeleton) { ans_class <- relistToClass(flesh) skeleton_len <- length(skeleton) if (skeleton_len == 0L) { flesh_len2 <- 0L } else { flesh_len2 <- end(skeleton)[skeleton_len] } if (NROW(flesh) != flesh_len2) stop("shape of 'skeleton' is not compatible with 'NROW(flesh)'") if (extends(ans_class, "CompressedList")) return(newCompressedList0(ans_class, flesh, skeleton)) if (!extends(ans_class, "SimpleList")) stop("don't know how to split or relist a ", class(flesh), " object as a ", ans_class, " object") listData <- lapply(skeleton, function(i) extractROWS(flesh, i)) ## TODO: Once "window" methods have been revisited/tested and ## 'window(flesh, start=start, end=end)' is guaranteed to do the ## right thing for any 'flesh' object (in particular it subsets a ## data.frame-like object along the rows), then replace the line above ## by the code below (which should be more efficient): #skeleton_start <- start(skeleton) #skeleton_end <- end(skeleton) #FUN <- function(start, end) window(flesh, start=start, end=end) #names(skeleton_start) <- names(skeleton) #listData <- mapply(FUN, skeleton_start, skeleton_end) ## or, if we don't trust mapply(): #skeleton_start <- start(skeleton) #skeleton_end <- end(skeleton) #X <- seq_len(skeleton_len) #names(X) <- names(skeleton) #listData <- lapply(X, function(i) window(flesh, # start=skeleton_start[i], # end=skeleton_end[i])) S4Vectors:::new_SimpleList_from_list(ans_class, listData) } ) setMethod("relist", c("ANY", "List"), function(flesh, skeleton) { relist(flesh, PartitioningByEnd(skeleton)) } ) setMethod("relist", c("Vector", "list"), function(flesh, skeleton) { relist(flesh, PartitioningByEnd(skeleton)) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### splitAsList() ### ### 'f' is assumed to be an integer vector with no NAs. .splitAsList_by_integer <- function(x, f, drop) { if (length(f) > NROW(x)) stop("'f' cannot be longer than 'NROW(x)' when it's an integer vector") if (!identical(drop, FALSE)) warning("'drop' is ignored when 'f' is an integer vector") f_is_not_sorted <- S4Vectors:::isNotSorted(f) if (f_is_not_sorted) { idx <- S4Vectors:::orderInteger(f) f <- f[idx] x <- extractROWS(x, idx) } tmp <- Rle(f) f <- cumsum(runLength(tmp)) names(f) <- as.character(runValue(tmp)) f <- PartitioningByEnd(f) relist(x, f) } ### 'f' is assumed to be a factor with no NAs. .splitAsList_by_factor <- function(x, f, drop) { x_NROW <- NROW(x) f_len <- length(f) f_levels <- levels(f) f <- as.integer(f) if (f_len > x_NROW) f <- head(f, n=x_NROW) f_is_not_sorted <- S4Vectors:::isNotSorted(f) if (f_is_not_sorted) { idx <- S4Vectors:::orderInteger(f) x <- extractROWS(x, idx) } f <- tabulate(f, nbins=length(f_levels)) names(f) <- f_levels if (drop) f <- f[f != 0L] f <- cumsum(f) f <- PartitioningByEnd(f) relist(x, f) } ### 'f' is assumed to be an integer-Rle object with no NAs. .splitAsList_by_integer_Rle <- function(x, f, drop) { if (length(f) > NROW(x)) stop("'f' cannot be longer than data when it's an integer-Rle") if (!identical(drop, FALSE)) warning("'drop' is ignored when 'f' is an integer-Rle") f_vals <- runValue(f) f_lens <- runLength(f) f_is_not_sorted <- S4Vectors:::isNotSorted(f_vals) if (f_is_not_sorted) { idx <- S4Vectors:::orderInteger(f_vals) xranges <- successiveIRanges(f_lens)[idx] f_vals <- f_vals[idx] f_lens <- f_lens[idx] x <- extractROWS(x, xranges) } tmp <- Rle(f_vals, f_lens) f <- cumsum(runLength(tmp)) names(f) <- as.character(runValue(tmp)) f <- PartitioningByEnd(f) relist(x, f) } ### 'f' is assumed to be an Rle object with no NAs. .splitAsList_by_Rle <- function(x, f, drop) { x_NROW <- NROW(x) f_len <- length(f) f_vals <- runValue(f) if (!is.factor(f_vals)) { f_vals <- as.factor(f_vals) if (f_len > x_NROW) { runValue(f) <- f_vals f <- head(f, n=x_NROW) f_vals <- runValue(f) } } else if (f_len > x_NROW) { f <- head(f, n=x_NROW) f_vals <- runValue(f) } f_lens <- runLength(f) f_levels <- levels(f_vals) f_vals <- as.integer(f_vals) f_is_not_sorted <- S4Vectors:::isNotSorted(f_vals) if (f_is_not_sorted) { idx <- S4Vectors:::orderInteger(f_vals) xranges <- successiveIRanges(f_lens)[idx] x <- extractROWS(x, xranges) } ## Using S4Vectors:::tabulate2() is 5x faster than doing: ## f <- integer(length(f_levels)) ## tmp <- Rle(f_vals[idx], f_lens[idx]) ## f[runValue(tmp)] <- runLength(tmp) f <- S4Vectors:::tabulate2(f_vals, nbins=length(f_levels), weight=f_lens) names(f) <- f_levels if (drop) f <- f[f != 0L] f <- cumsum(f) f <- PartitioningByEnd(f) relist(x, f) } setGeneric("splitAsList", signature=c("x", "f"), function(x, f, drop=FALSE, ...) standardGeneric("splitAsList") ) ### Took this out of the still-in-incubation LazyList package factorsToTableIndices <- function(factors) { nI <- length(factors) nx <- length(factors[[1L]]) useRle <- any(vapply(factors, is, logical(1), "Rle")) if (useRle) { group <- as(factors[[1L]], "Rle") runValue(group) <- as.integer(runValue(group)) } else { group <- as.integer(factors[[1L]]) } ngroup <- nlevels(factors[[1L]]) for (i in tail(seq_len(nI), -1L)) { index <- factors[[i]] if (useRle) { offset <- as(index, "Rle") runValue(offset) <- ngroup * (as.integer(runValue(offset)) - 1L) } else { offset <- ngroup * (as.integer(index) - 1L) } group <- group + offset ngroup <- ngroup * nlevels(index) } as.vector(group) } normSplitFactor <- function(f, x_NROW) { if (is.list(f) || is(f, "List")) { f <- factorsToTableIndices(f) } f_len <- length(f) if (f_len < x_NROW) { if (f_len == 0L) stop("split factor has length 0 but 'NROW(x)' is > 0") if (x_NROW %% f_len != 0L) warning("'NROW(x)' is not a multiple of split factor length") f <- rep(f, length.out=x_NROW) } f } splitAsList_default <- function(x, f, drop=FALSE) { if (!isTRUEorFALSE(drop)) stop("'drop' must be TRUE or FALSE") x_NROW <- NROW(x) f <- normSplitFactor(f, x_NROW) is_na <- is.na(f) na_idx <- which(is_na) if (length(na_idx) != 0L) { keep_idx <- seq_len(x_NROW)[-na_idx] x <- extractROWS(x, keep_idx) f <- f[keep_idx] } if (is.integer(f)) return(.splitAsList_by_integer(x, f, drop)) if (is.vector(f) && is.atomic(f)) f <- as.factor(f) if (is.factor(f)) return(.splitAsList_by_factor(x, f, drop)) ## From now on, 'f' is guaranteed to be an Rle. f_vals <- runValue(f) if (!((is.vector(f_vals) && is.atomic(f_vals)) || is.factor(f_vals))) stop("'f' must be an atomic vector or a factor (possibly in Rle form)") if (is.integer(f_vals)) return(.splitAsList_by_integer_Rle(x, f, drop)) return(.splitAsList_by_Rle(x, f, drop)) } setMethod("splitAsList", c("ANY", "vectorORfactor"), function(x, f, drop=FALSE) splitAsList_default(x, f, drop=drop)) setMethod("splitAsList", c("ANY", "Rle"), function(x, f, drop=FALSE) splitAsList_default(x, f, drop=drop)) setMethod("splitAsList", c("ANY", "List"), function(x, f, drop=FALSE) splitAsList_default(x, f, drop=drop)) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### extractList() ### ### Would extractGroups be a better name for this? ### Or extractGroupedROWS? (analog to extractROWS, except that the ROWS are ### grouped). ### ### 'x' must be a vector-like object and 'i' a list-like object. ### Must return a list-like object parallel to 'i' and with same "shape" as ### 'i' (i.e. same elementLengths). If 'i' has names, they should be ### propagated to the returned value. The list elements of the returned value ### must have the class of 'x'. setGeneric("extractList", function(x, i) standardGeneric("extractList")) ### Default method. setMethod("extractList", c("ANY", "ANY"), function(x, i) { if (is(i, "Ranges")) return(relist(extractROWS(x, i), i)) if (is.list(i)) { unlisted_i <- unlist(i, recursive=FALSE, use.names=FALSE) } else if (is(i, "List")) { ## The various "unlist" methods for List derivatives don't know ## how to operate recursively and don't support the 'recursive' ## arg. unlisted_i <- unlist(i, use.names=FALSE) } else { stop("'i' must be a list-like object") } relist(extractROWS(x, unlisted_i), i) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### regroupBySupergroup() ### ### A very efficient way to concatenate groups of successive list elements ### in 'x'. ### 'x' must be a list-like object (typically a CompressedList object). ### 'supergroups' must be an object that defines a partitioning of ### 'seq_along(x)' (i.e. it could be used to do ### 'relist(seq_along(x), supergroups)'). It will be immediately replaced with ### 'PartitioningByEnd(supergroups)' so it should be an object that is ### accepted by the PartitioningByEnd() constructor (note that this constructor ### is a no-op if 'supergroups' is already a PartitioningByEnd object). ### Return a list-like object of the same elementType() as 'x' and parallel ### to 'supergroups'. The names on 'supergroups' are propagated but not the ### metadata columns. ### ### Some properties: ### - Behaves as an endomorphism on a CompressedList or PartitioningByEnd ### object. ### - This ### regroupBySupergroup(x, length(x))[[1L]] ### is equivalent to ### unlist(x, use.names=FALSE) ### ### Other possible names for regroupBySupergroup: regroup, ### mergeGroupsInSupergroups, combineGroupsOfListElements, ### unlistGroupsOfListElements, unlistBySupergroup. ### ### TODO: Maybe export and document this? regroupBySupergroup <- function(x, supergroups) { supergroups <- PartitioningByEnd(supergroups) x_breakpoints <- end(PartitioningByEnd(x)) ans_breakpoints <- x_breakpoints[end(supergroups)] nleading0s <- length(supergroups) - length(ans_breakpoints) if (nleading0s != 0L) ans_breakpoints <- c(rep.int(0L, nleading0s), ans_breakpoints) ans_partitioning <- PartitioningByEnd(ans_breakpoints, names=names(supergroups)) if (is(x, "PartitioningByEnd")) return(ans_partitioning) relist(unlist(x, use.names=FALSE), ans_partitioning) } IRanges/R/findOverlaps-methods.R0000644000175100017510000011324712607265143017561 0ustar00biocbuildbiocbuild### ========================================================================= ### findOverlaps (and related) methods ### ------------------------------------------------------------------------- ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### findOverlaps() ### ### Find objects in the query that overlap those in the subject. ### setGeneric("findOverlaps", signature=c("query", "subject"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), ...) standardGeneric("findOverlaps") ) ### ### The next two functions are pre/post processing functions shared ### by the IntervalTree and IntervalForest versions of findOverlaps ### ### pre-process query (sort and adjust) and partition (if not NULL) .preProcess_findOverlaps_query <- function(query, maxgap, minoverlap, partitioning=NULL) { res <- list() query <- as(query, "IRanges") query_ord <- NULL res$origQuery <- query adjust <- (maxgap - minoverlap + 1L) * (width(query) > 0L) if (sum(adjust) > 0L) query <- resize(query, width(query) + 2L * adjust, fix = "center") res$unsortedQuery <- query if (is.null(partitioning)) { if (S4Vectors:::isNotSorted(start(query))) { ## query must be sorted query_ord <- sort.list(start(query), method = "quick", na.last = NA) query <- query[query_ord] } else { query_ord <- seq_len(length(query)) } } else { if(!is(partitioning, "PartitioningByEnd")) stop("invalid partitioning") # query be sorted within partition spaces query_ord <- seq_len(length(query)) isSorted <- TRUE for (i in seq(len=length(partitioning))) { curStart <- start(partitioning)[i] curEnd <- end(partitioning)[i] cur <- IRanges(curStart, curEnd) qStarts <- extractROWS(start(query), cur) if (S4Vectors:::isNotSorted(qStarts)) { isSorted <- FALSE ind <- extractROWS(query_ord, cur) query_ord <- replaceROWS(query_ord, cur, ind[sort.list(qStarts, method="quick", na.last=NA)]) } } if (!isSorted) { query <- query[query_ord] } } res$query <- query res$query_ord <- query_ord res } ### post-process result based on overlap type and select .postProcess_findOverlaps_result <- function(result, unsortedQuery, origQuery, subject, type, minoverlap, maxgap, origSelect) { if (type != "any" || minoverlap > 1L) { if (!is(subject,"Ranges")) subject <- as(subject, "IRanges") m <- as.matrix(result) if (minoverlap > 1L) { olap <- width(pintersect(origQuery[queryHits(result)], subject[subjectHits(result)], resolve.empty = "max.start")) sep <- width(pgap(origQuery[queryHits(result)], subject[subjectHits(result)])) olap <- ifelse(olap == 0L, -sep + 1L, olap) + maxgap m <- m[olap >= minoverlap, , drop=FALSE] ## unname() required because in case 'm' has only 1 row ## 'm[ , 1L]' and 'm[ , 2L]' will return a named atomic vector result@queryHits <- unname(m[ , 1L]) result@subjectHits <- unname(m[ , 2L]) } query <- origQuery filterMatrix <- function(fun) m[abs(fun(query)[m[,1L]] - fun(subject)[m[,2L]]) <= maxgap, , drop=FALSE] if (type == "within") { r <- ranges(result, query, subject) m <- m[width(query)[m[,1L]] - width(r) <= maxgap, , drop=FALSE] } else if (type == "start") { m <- filterMatrix(start) } else if (type == "end") { m <- filterMatrix(end) } else if (type == "equal") { m <- filterMatrix(start) m <- filterMatrix(end) } if (origSelect != "all") { m <- m[!duplicated(m[,1L], fromLast = origSelect == "last"), , drop=FALSE] result <- rep.int(NA_integer_, length(query)) ## unname() required because in case 'm' has only 1 row ## 'm[,2L]' will return a named atomic vector result[m[,1L]] <- unname(m[,2L]) } else { ## unname() required because in case 'm' has only 1 row ## 'm[ , 1L]' and 'm[ , 2L]' will return a named atomic vector result@queryHits <- unname(m[ , 1L]) result@subjectHits <- unname(m[ , 2L]) } } result } ### findOverlaps method for IntervalTree setMethod("findOverlaps", c("Ranges", "IntervalTree"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), select = c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree")) { # verify inputs if (!isSingleNumber(maxgap) || maxgap < 0L) stop("'maxgap' must be a single, non-negative integer") if (!isSingleNumber(minoverlap) || minoverlap < 1L) stop("'minoverlap' must be a single, positive integer") type <- match.arg(type) select <- match.arg(select) algorithm <- match.arg(algorithm) if (algorithm != "nclist") warning("'algorithm' is ignored when 'subject' ", "is an IntervalTree object") origSelect <- select if (type != "any" || minoverlap > 1L) select <- "all" # preprocess query preprocRes <- .preProcess_findOverlaps_query(query, maxgap, minoverlap) origQuery <- preprocRes$origQuery unsortedQuery <- preprocRes$origQuery query <- preprocRes$query query_ord <- preprocRes$query_ord validObject(query) # make initial findOverlaps call fun <- paste("overlap_", select, sep = "") result <- IntervalTreeCall(subject, fun, query, query_ord) # postprocess results .postProcess_findOverlaps_result(result, unsortedQuery, origQuery, subject, type, minoverlap, maxgap, origSelect) }) findOverlaps_Ranges <- function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree")) { type <- match.arg(type) min.score <- min_overlap_score(maxgap, minoverlap, type) select <- match.arg(select) algorithm <- match.arg(algorithm) if (algorithm != "nclist") warning("'algorithm' is ignored when 'query' or 'subject' ", "is an NCList object") findOverlaps_NCList(query, subject, min.score=min.score, type=type, select=select) } setMethod("findOverlaps", c("NCList", "Ranges"), findOverlaps_Ranges) setMethod("findOverlaps", c("Ranges", "NCList"), findOverlaps_Ranges) setMethod("findOverlaps", c("Ranges", "Ranges"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree")) { type <- match.arg(type) select <- match.arg(select) algorithm <- match.arg(algorithm) if (algorithm == "intervaltree") { subject <- IntervalTree(subject) findOverlaps(query, subject, maxgap=maxgap, minoverlap=minoverlap, type=type, select=select) } else { findOverlaps_Ranges(query, subject, maxgap=maxgap, minoverlap=minoverlap, type=type, select=select) } } ) setMethod("findOverlaps", c("Vector", "missing"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), ..., ignoreSelf=FALSE, ignoreRedundant=FALSE) { select <- match.arg(select) result <- findOverlaps(query, query, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select="all", algorithm=match.arg(algorithm), ...) processSelfMatching(result, select, ignoreSelf, ignoreRedundant) } ) setMethod("findOverlaps", c("integer", "Ranges"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree")) { findOverlaps(IRanges(query, query), subject, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select=match.arg(select), algorithm=match.arg(algorithm)) } ) setMethod("findOverlaps", c("Views", "Views"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree")) { findOverlaps(ranges(query), ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select=match.arg(select), algorithm=match.arg(algorithm)) } ) setMethod("findOverlaps", c("Views", "Vector"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree")) { findOverlaps(ranges(query), subject, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select=match.arg(select), algorithm=match.arg(algorithm)) } ) setMethod("findOverlaps", c("Vector", "Views"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree")) { findOverlaps(query, ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select=match.arg(select), algorithm=match.arg(algorithm)) } ) ### findOverlaps method for IntervalForest setMethod("findOverlaps", c("RangesList", "IntervalForest"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), select = c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), drop=FALSE) { # verify inputs if (!isSingleNumber(maxgap) || maxgap < 0L) stop("'maxgap' must be a single, non-negative integer") if (!isSingleNumber(minoverlap) || minoverlap < 1L) stop("'minoverlap' must be a single, positive integer") type <- match.arg(type) select <- match.arg(select) algorithm <- match.arg(algorithm) if (algorithm != "nclist") warning("'algorithm' is ignored when 'subject' ", "is an IntervalForest object") origSelect <- select if (type != "any" || minoverlap > 1L) select <- "all" if (!is(query, "CompressedIRangesList")) query <- as(query, "CompressedIRangesList") validObject(query) queryList <- query query <- queryList@unlistData partitioning <- queryList@partitioning # preprocess query preprocRes <- .preProcess_findOverlaps_query(query, maxgap, minoverlap, partitioning) origQuery <- preprocRes$origQuery unsortedQuery <- preprocRes$unsortedQuery query <- preprocRes$query query_ord <- preprocRes$query_ord validObject(query) # match query partition to subject partition partitionIndices <- match(names(partitioning), names(subject)) # make initial findOverlaps call fun <- paste("overlap_", select, sep = "") result <- .IntervalForestCall(subject, fun, query, partitionIndices, elementLengths(partitioning), query_ord) # postprocess findOverlaps result res <- .postProcess_findOverlaps_result(result, unsortedQuery, origQuery, subject, type, minoverlap, maxgap, origSelect) # turn it into compressed list if (origSelect == "all") return(CompressedHitsList(res, queryList)) if (!drop) { return(newCompressedList0("CompressedIntegerList", unlistData=res, partitioning=partitioning)) } res }) # might consider making this the following: # setMethod("findOverlaps", c("RangesList", "RangesList"), # function(query, subject, maxgap = 0L, minoverlap = 1L, # type = c("any", "start", "end", "within", "equal"), # select = c("all", "first", "last", "arbitrary"), # drop = FALSE) # { # findOverlaps(query, as(query, "IntervalForest"), # maxgap = maxgap, minoverlap = minoverlap, # type = match.arg(type), select = match.arg(select), drop = drop) # } # ) setMethod("findOverlaps", c("RangesList", "RangesList"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), select = c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), drop = FALSE) { type <- match.arg(type) select <- match.arg(select) algorithm <- match.arg(algorithm) query <- as.list(query) subject <- as.list(subject) origSubject <- subject if (!is.null(names(subject)) && !is.null(names(query))) { subject <- subject[names(query)] names(subject) <- names(query) # get rid of NA's in names } else { subject <- subject[seq_along(query)] } ## NULL's are introduced where they do not match ## We replace those with empty IRanges subject[sapply(subject, is.null)] <- IRanges() ans <- lapply(seq_len(length(subject)), function(i) { findOverlaps(query[[i]], subject[[i]], maxgap = maxgap, minoverlap = minoverlap, type = type, select = select, algorithm = algorithm) }) names(ans) <- names(subject) if (select == "all") { ans <- HitsList(ans, origSubject) } else if (drop) { off <- head(c(0L, cumsum(sapply(origSubject, length))), -1) names(off) <- names(origSubject) if (is.null(names(ans))) off <- off[seq_along(ans)] else off <- off[names(ans)] ans <- unlist(ans, use.names=FALSE) + rep.int(unname(off), sapply(ans, length)) } else { ans <- IntegerList(ans) } ans }) setMethod("findOverlaps", c("ViewsList", "ViewsList"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), drop=FALSE) { findOverlaps(ranges(query), ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select=match.arg(select), algorithm=match.arg(algorithm), drop=drop) } ) setMethod("findOverlaps", c("ViewsList", "Vector"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), drop=FALSE) { findOverlaps(ranges(query), subject, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select=match.arg(select), algorithm=match.arg(algorithm), drop=drop) } ) setMethod("findOverlaps", c("Vector", "ViewsList"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), drop=FALSE) { findOverlaps(query, ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select=match.arg(select), algorithm=match.arg(algorithm), drop=drop) } ) setMethod("findOverlaps", c("RangedData", "RangedData"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), select = c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), drop = FALSE) { findOverlaps(ranges(query), ranges(subject), maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type), select = match.arg(select), algorithm = match.arg(algorithm), drop = drop) }) setMethod("findOverlaps", c("RangedData", "RangesList"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), select = c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), drop = FALSE) { findOverlaps(ranges(query), subject, maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type), select = match.arg(select), algorithm = match.arg(algorithm), drop = drop) }) setMethod("findOverlaps", c("RangesList", "RangedData"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), select = c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), drop = FALSE) { findOverlaps(query, ranges(subject), maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type), select = match.arg(select), algorithm = match.arg(algorithm), drop = drop) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### countOverlaps() ### setGeneric("countOverlaps", signature = c("query", "subject"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) standardGeneric("countOverlaps") ) countOverlaps_Ranges <- function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { type <- match.arg(type) min.score <- min_overlap_score(maxgap, minoverlap, type) algorithm <- match.arg(algorithm) if (algorithm != "nclist") warning("'algorithm' is ignored when 'query' or 'subject' ", "is an NCList object") ans <- findOverlaps_NCList(query, subject, min.score=min.score, type=type, select="count") names(ans) <- names(query) ans } setMethod("countOverlaps", c("NCList", "Ranges"), countOverlaps_Ranges) setMethod("countOverlaps", c("Ranges", "NCList"), countOverlaps_Ranges) setMethod("countOverlaps", c("ANY", "Vector"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { type <- match.arg(type) algorithm <- match.arg(algorithm) if (algorithm == "nclist" && is(query, "Ranges") && is(subject, "Ranges")) return(countOverlaps_Ranges(query, subject, maxgap=maxgap, minoverlap=minoverlap, type=type)) ov <- findOverlaps(query, subject, maxgap = maxgap, minoverlap = minoverlap, type = type, ...) ans <- countQueryHits(ov) names(ans) <- names(query) ans } ) setMethod("countOverlaps", c("ANY", "missing"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { countOverlaps(query, query, maxgap = maxgap, minoverlap = minoverlap, type = type, algorithm=match.arg(algorithm)) } ) setMethod("countOverlaps", c("RangesList", "IntervalForest"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), drop = FALSE, ...) { if (!is(query, "CompressedIRangesList")) query <- as("CompressedIRangesList", query) hits <- findOverlaps(query, subject, maxgap = maxgap, minoverlap = minoverlap, type = type, ...) res <- tabulate(queryHits(hits), queryLength(hits)) new2("CompressedIntegerList", unlistData=res, partitioning = query@partitioning) }) setMethod("countOverlaps", c("RangesList", "RangesList"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { IntegerList(mapply(countOverlaps, query, subject, MoreArgs = list(maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type), algorithm=match.arg(algorithm)), SIMPLIFY = FALSE)) }) setMethod("countOverlaps", c("ViewsList", "ViewsList"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { countOverlaps(ranges(query), ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=type, algorithm=match.arg(algorithm)) } ) setMethod("countOverlaps", c("ViewsList", "Vector"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { countOverlaps(ranges(query), subject, maxgap=maxgap, minoverlap=minoverlap, type=type, algorithm=match.arg(algorithm)) } ) setMethod("countOverlaps", c("Vector", "ViewsList"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { countOverlaps(query, ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=type, algorithm=match.arg(algorithm)) } ) setMethod("countOverlaps", c("RangedData", "RangedData"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { countOverlaps(ranges(query), ranges(subject), maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type), algorithm=match.arg(algorithm)) }) setMethod("countOverlaps", c("RangedData", "RangesList"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { countOverlaps(ranges(query), subject, maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type), algorithm=match.arg(algorithm)) }) setMethod("countOverlaps", c("RangesList", "RangedData"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { countOverlaps(query, ranges(subject), maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type), algorithm=match.arg(algorithm)) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### overlapsAny() ### ### Same args and signature as countOverlaps() and subsetByOverlaps(). setGeneric("overlapsAny", signature=c("query", "subject"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) standardGeneric("overlapsAny") ) setMethod("overlapsAny", c("Ranges", "Ranges"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { !is.na(findOverlaps(query, subject, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select="arbitrary", algorithm=match.arg(algorithm), ...)) } ) setMethod("overlapsAny", c("Vector", "missing"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { !is.na(findOverlaps(query, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select="arbitrary", algorithm=match.arg(algorithm), ...)) } ) setMethod("overlapsAny", c("integer", "Ranges"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { !is.na(findOverlaps(query, subject, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select="arbitrary", algorithm=match.arg(algorithm), ...)) } ) setMethod("overlapsAny", c("Views", "Views"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { overlapsAny(ranges(query), ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), algorithm=match.arg(algorithm), ...) } ) setMethod("overlapsAny", c("Views", "Vector"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { overlapsAny(ranges(query), subject, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), algorithm=match.arg(algorithm), ...) } ) setMethod("overlapsAny", c("Vector", "Views"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { overlapsAny(query, ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), algorithm=match.arg(algorithm), ...) } ) setMethod("overlapsAny", c("RangesList", "RangesList"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { query <- as.list(query) subject <- as.list(subject) type <- match.arg(type) algorithm <- match.arg(algorithm) if (!is.null(names(query)) && !is.null(names(subject))) { subject <- subject[names(query)] names(subject) <- names(query) # get rid of NA's in names } else { subject <- subject[seq_along(query)] } ## NULL's are introduced where they do not match ## We replace those with empty IRanges subject[sapply(subject, is.null)] <- IRanges() LogicalList(lapply(structure(seq_len(length(query)), names = names(query)), function(i) overlapsAny(query[[i]], subject[[i]], maxgap=maxgap, minoverlap=minoverlap, type=type, algorithm=algorithm, ...))) } ) setMethod("overlapsAny", c("RangesList", "IntervalForest"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { if (!is(query, "CompressedIRangesList")) query <- as(query, "CompressedIRangesList") !is.na(findOverlaps(query, subject, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), select="arbitrary", algorithm=match.arg(algorithm), ...)) } ) setMethod("overlapsAny", c("ViewsList", "ViewsList"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { overlapsAny(ranges(query), ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), algorithm=match.arg(algorithm), ...) } ) setMethod("overlapsAny", c("ViewsList", "Vector"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { overlapsAny(ranges(query), subject, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), algorithm=match.arg(algorithm), ...) } ) setMethod("overlapsAny", c("Vector", "ViewsList"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { overlapsAny(query, ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), algorithm=match.arg(algorithm), ...) } ) setMethod("overlapsAny", c("RangedData", "RangedData"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { overlapsAny(ranges(query), ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), algorithm=match.arg(algorithm), ...) } ) setMethod("overlapsAny", c("RangedData", "RangesList"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { overlapsAny(ranges(query), subject, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), algorithm=match.arg(algorithm), ...) } ) setMethod("overlapsAny", c("RangesList", "RangedData"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { overlapsAny(query, ranges(subject), maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), algorithm=match.arg(algorithm), ...) } ) ### Convenience wrappers for the 3 most common use cases. `%over%` <- function(query, subject) overlapsAny(query, subject) `%within%` <- function(query, subject) overlapsAny(query, subject, type="within") `%outside%` <- function(query, subject) !overlapsAny(query, subject) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### subsetByOverlaps() ### setGeneric("subsetByOverlaps", signature=c("query", "subject"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) standardGeneric("subsetByOverlaps") ) setMethod("subsetByOverlaps", c("Vector", "Vector"), function(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) { query[overlapsAny(query, subject, maxgap=maxgap, minoverlap=minoverlap, type=match.arg(type), algorithm=match.arg(algorithm), ...)] } ) setMethod("subsetByOverlaps", c("RangedData", "RangedData"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { query[unlist(!is.na(findOverlaps(ranges(query), ranges(subject), maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type), select = "arbitrary"), algorithm=match.arg(algorithm)), use.names=FALSE),] }) setMethod("subsetByOverlaps", c("RangedData", "RangesList"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { query[unlist(!is.na(findOverlaps(ranges(query), subject, maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type), select = "arbitrary"), algorithm=match.arg(algorithm)), use.names=FALSE),] }) setMethod("subsetByOverlaps", c("RangesList", "RangedData"), function(query, subject, maxgap = 0L, minoverlap = 1L, type = c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree")) { query[!is.na(findOverlaps(query, ranges(subject), maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type), select = "arbitrary"), algorithm=match.arg(algorithm))] }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Merge two sets of ranges by overlap into a DataFrame ### mergeByOverlaps <- function(query, subject, ...) { hits <- findOverlaps(query, subject, ...) query_df <- as(extractROWS(query, queryHits(hits)), "DataFrame") colnames(query_df)[1L] <- deparse(substitute(query)) subject_df <- as(extractROWS(subject, subjectHits(hits)), "DataFrame") colnames(subject_df)[1L] <- deparse(substitute(subject)) cbind(query_df, subject_df) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### "ranges" method for Hits objects ### ### Extracts the actual regions of intersection between the overlapping ranges. ### Not much value. Could be replaced by 1-liner: ### pintersect(query[queryHits(x)], subject[subjectHits(x)]) ### setMethod("ranges", "Hits", function(x, query, subject) { if (!is(query, "Ranges") || length(query) != queryLength(x)) stop("'query' must be a Ranges of length equal to number of queries") if (!is(subject, "Ranges") || length(subject) != subjectLength(x)) stop("'subject' must be a Ranges of length equal to number of subjects") m <- as.matrix(x) qstart <- start(query)[m[,1L]] qend <- end(query)[m[,1L]] sstart <- start(subject)[m[,2L]] send <- end(subject)[m[,2L]] IRanges(pmax.int(qstart, sstart), pmin.int(send, qend)) }) IRanges/R/inter-range-methods.R0000644000175100017510000004147612611546444017345 0ustar00biocbuildbiocbuild### ========================================================================= ### Inter-range methods ### ------------------------------------------------------------------------- ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### range() ### setMethod("range", "Ranges", function(x, ..., na.rm=FALSE) { if (!identical(na.rm, FALSE)) warning("'na.rm' argument is ignored") args <- unname(list(x, ...)) if (length(args) == 0L) # should never happen return(IRanges()) if (!all(sapply(args, is, "Ranges"))) stop("all arguments in '...' must be Ranges objects") xx <- do.call(c, lapply(args, as, "IRanges")) y <- .Call2("IRanges_range", xx, PACKAGE="IRanges") as(y, class(args[[1L]])) } ) setMethod("range", "RangesList", function(x, ..., na.rm=FALSE) { if (length(list(x, ...)) >= 2L) x <- merge(x, ...) endoapply(x, range) } ) ### Equivalent to, but much faster than, 'endoapply(x, range)'. .CompressedIRangesList.range <- function(x) { ## 'x_start' and 'x_end' are CompressedIntegerList objects with the ## same shape as 'x'. x_start <- start(x) x_end <- end(x) ## TEMPORARY HACK! if (!requireNamespace("XVector", quietly=TRUE)) stop("the XVector package is required by the \"range\" method ", "for CompressedIRangesList objects") ## 'sv' and 'ev' are XIntegerViews objects (see XVector package). sv <- Views(x_start@unlistData, x_start@partitioning) ev <- Views(x_end@unlistData, x_end@partitioning) is_not_empty_view <- width(sv) != 0L # same as 'width(ev) != 0L' ans_unlistData <- IRanges(viewMins(sv)[is_not_empty_view], viewMaxs(ev)[is_not_empty_view]) ans_partitioning <- new2("PartitioningByEnd", end=cumsum(is_not_empty_view), check=FALSE) ans <- new2("CompressedIRangesList", unlistData=ans_unlistData, partitioning=ans_partitioning, check=FALSE) names(ans) <- names(x) mcols(ans) <- mcols(x) ans } setMethod("range", "CompressedIRangesList", function(x, ..., na.rm=FALSE) { if (length(list(x, ...)) >= 2L) x <- merge(x, ...) .CompressedIRangesList.range(x) } ) setMethod("range", "IntervalForest", function(x, ..., na.rm=FALSE) as(range(as(x, "CompressedIRangesList"), ..., na.rm = na.rm), "IntervalForest")) setMethod("range", "RangedData", function(x, ..., na.rm) { args <- list(x, ...) rangeLists <- lapply(args, ranges) do.call(range, rangeLists) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### reduce() ### setGeneric("reduce", signature="x", function(x, ...) standardGeneric("reduce") ) setMethod("reduce", "IRanges", function(x, drop.empty.ranges=FALSE, min.gapwidth=1L, with.revmap=FALSE, with.inframe.attrib=FALSE) { if (!isTRUEorFALSE(drop.empty.ranges)) stop("'drop.empty.ranges' must be TRUE or FALSE") if (!isSingleNumber(min.gapwidth)) stop("'min.gapwidth' must be a single integer") if (!is.integer(min.gapwidth)) min.gapwidth <- as.integer(min.gapwidth) if (min.gapwidth < 0L) stop("'min.gapwidth' must be non-negative") if (!isTRUEorFALSE(with.revmap)) stop("'with.revmap' must be TRUE or FALSE") if (!isTRUEorFALSE(with.inframe.attrib)) stop("'with.inframe.attrib' must be TRUE or FALSE") C_ans <- .Call2("Ranges_reduce", start(x), width(x), drop.empty.ranges, min.gapwidth, with.revmap, with.inframe.attrib, PACKAGE="IRanges") ans <- unsafe.update(x, start=C_ans$start, width=C_ans$width, names=NULL) if (with.revmap) { revmap <- IntegerList(C_ans$revmap) mcols(ans) <- DataFrame(revmap=revmap) } if (with.inframe.attrib) { inframe <- new2("IRanges", start=C_ans$inframe.start, width=width(x), check=FALSE) attr(ans, "inframe") <- inframe } ans } ) setMethod("reduce", "Ranges", function(x, drop.empty.ranges=FALSE, min.gapwidth=1L, with.revmap=FALSE, with.inframe.attrib=FALSE) { ir <- as(x, "IRanges") y <- reduce(ir, drop.empty.ranges=drop.empty.ranges, min.gapwidth=min.gapwidth, with.revmap=with.revmap, with.inframe.attrib=with.inframe.attrib) as(y, class(x)) } ) setMethod("reduce", "Views", function(x, drop.empty.ranges=FALSE, min.gapwidth=1L, with.revmap=FALSE, with.inframe.attrib=FALSE) { x@ranges <- reduce(ranges(x), drop.empty.ranges=drop.empty.ranges, min.gapwidth=min.gapwidth, with.revmap=with.revmap, with.inframe.attrib=with.inframe.attrib) x } ) setMethod("reduce", "RangesList", function(x, drop.empty.ranges=FALSE, min.gapwidth=1L, with.revmap=FALSE, with.inframe.attrib=FALSE) endoapply(x, reduce, drop.empty.ranges = drop.empty.ranges, min.gapwidth = min.gapwidth, with.revmap=with.revmap, with.inframe.attrib = with.inframe.attrib)) ### 'with.inframe.attrib' is ignored for now. ### TODO: Support 'with.inframe.attrib=TRUE'. setMethod("reduce", "CompressedIRangesList", function(x, drop.empty.ranges=FALSE, min.gapwidth=1L, with.revmap=FALSE, with.inframe.attrib=FALSE) { if (!isTRUEorFALSE(drop.empty.ranges)) stop("'drop.empty.ranges' must be TRUE or FALSE") if (!isSingleNumber(min.gapwidth)) stop("'min.gapwidth' must be a single integer") if (!is.integer(min.gapwidth)) min.gapwidth <- as.integer(min.gapwidth) if (min.gapwidth < 0L) stop("'min.gapwidth' must be non-negative") if (!isTRUEorFALSE(with.revmap)) stop("'with.revmap' must be TRUE or FALSE") if (!identical(with.inframe.attrib, FALSE)) stop("'with.inframe.attrib' argument not yet supported ", "when reducing a CompressedIRangesList object") C_ans <- .Call2("CompressedIRangesList_reduce", x, drop.empty.ranges, min.gapwidth, with.revmap, PACKAGE="IRanges") ans_unlistData <- new2("IRanges", start=C_ans$start, width=C_ans$width, check=FALSE) if (with.revmap) { revmap <- IntegerList(C_ans$revmap) mcols(ans_unlistData) <- DataFrame(revmap=revmap) } ans_partitioning <- PartitioningByEnd(C_ans$partitioning_by_end) names(ans_partitioning) <- names(x) relist(ans_unlistData, ans_partitioning) } ) setMethod("reduce", "IntervalForest", function(x, drop.empty.ranges=FALSE, min.gapwidth=1L, with.inframe.attrib=FALSE) { if (!drop.empty.ranges) stop("'drop.empty.ranges' must be TRUE in ", "'reduce,IntervalForest'") as(reduce(as(x, "CompressedIRangesList"), min.gapwidth = min.gapwidth, with.inframe.attrib = with.inframe.attrib), "IntervalForest") }) setMethod("reduce", "RangedData", function(x, by = character(), drop.empty.ranges=FALSE, min.gapwidth=1L, with.inframe.attrib=FALSE) { if (!isTRUEorFALSE(drop.empty.ranges)) stop("'drop.empty.ranges' must be TRUE or FALSE") if (!isSingleNumber(min.gapwidth)) stop("'min.gapwidth' must be a single integer") if (!is.integer(min.gapwidth)) min.gapwidth <- as.integer(min.gapwidth) if (min.gapwidth < 0L) stop("'min.gapwidth' must be non-negative") FUN <- function(y) { name <- names(y) ranges <- ranges(y)[[1L]] values <- values(y)[[1L]] inds <- unname(split(seq_len(nrow(values)), lapply(values, as.vector))) rlist <- lapply(inds, function(i) { rngs <- reduce(ranges[i], drop.empty.ranges=drop.empty.ranges, min.gapwidth=min.gapwidth, with.inframe.attrib=with.inframe.attrib) list(ranges = rngs, values = values[rep(i, length.out = length(rngs)), , drop=FALSE]) }) ranges <- IRangesList(do.call(c, lapply(rlist, "[[", "ranges"))) names(ranges) <- name values <- SplitDataFrameList(do.call(rbind, lapply(rlist, "[[", "values"))) names(values) <- name new2(class(y), ranges = ranges, values = values, check = FALSE) } if (ncol(x) == 0 || length(by) == 0) { ranges <- reduce(ranges(x), drop.empty.ranges = drop.empty.ranges, min.gapwidth = min.gapwidth, with.inframe.attrib = with.inframe.attrib) listData <- new2("DataFrame", nrows=sum(elementLengths(ranges)), check=FALSE) end <- cumsum(elementLengths(ranges)) names(end) <- names(ranges) partitioning <- PartitioningByEnd(end) initialize(x, ranges = ranges, values = relist(listData, partitioning)) } else { endoapply(x[,by], FUN) } }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### gaps() ### setGeneric("gaps", signature="x", function(x, start=NA, end=NA) standardGeneric("gaps") ) setMethod("gaps", "IRanges", function(x, start=NA, end=NA) { start <- S4Vectors:::normargSingleStartOrNA(start) end <- S4Vectors:::normargSingleEndOrNA(end) C_ans <- .Call2("IRanges_gaps", start(x), width(x), start, end, PACKAGE="IRanges") initialize(x, start=C_ans$start, width=C_ans$width, NAMES=NULL, elementMetadata=NULL) } ) setMethod("gaps", "Ranges", function(x, start=NA, end=NA) { ir <- as(x, "IRanges") y <- gaps(ir, start=start, end=end) as(y, class(x)) } ) setMethod("gaps", "Views", function(x, start=NA, end=NA) { if (!isSingleNumberOrNA(start)) stop("'start' must be a single integer") if (!is.integer(start)) start <- as.integer(start) if (!isSingleNumberOrNA(end)) stop("'end' must be a single integer") if (!is.integer(end)) end <- as.integer(end) if (is.na(start)) start <- 1L if (is.na(end)) end <- length(subject(x)) x@ranges <- gaps(ranges(x), start=start, end=end) x } ) setMethod("gaps", "RangesList", function(x, start = NA, end = NA) { lx <- length(x) if (!S4Vectors:::isNumericOrNAs(start)) stop("'start' must be an integer vector or NA") if (!is.integer(start)) start <- as.integer(start) if (!S4Vectors:::isNumericOrNAs(end)) stop("'end' must be an integer vector or NA") if (!is.integer(end)) end <- as.integer(end) start <- IntegerList(as.list(S4Vectors:::recycleVector(start, lx))) end <- IntegerList(as.list(S4Vectors:::recycleVector(end, lx))) mendoapply(gaps, x, start = start, end = end) }) setMethod("gaps", "CompressedIRangesList", function(x, start = NA, end = NA) { lx <- length(x) if (!S4Vectors:::isNumericOrNAs(start)) stop("'start' must be an integer vector or NA") if (!is.integer(start)) start <- as.integer(start) if (!S4Vectors:::isNumericOrNAs(end)) stop("'end' must be an integer vector or NA") if (!is.integer(end)) end <- as.integer(end) if ((length(start) != 1) || (length(end) != 1)) { start <- S4Vectors:::recycleVector(start, lx) end <- S4Vectors:::recycleVector(end, lx) } .Call2("CompressedIRangesList_gaps", x, start, end, PACKAGE="IRanges") }) setMethod("gaps", "IntervalForest", function(x, start = NA, end = NA) as(gaps(as(x, "CompressedIRangesList"), start = start, end = end), "IntervalForest")) ### 'start' and 'end' are ignored. setMethod("gaps", "MaskCollection", function(x, start=NA, end=NA) { start <- 1L end <- width(x) x@nir_list <- lapply(nir_list(x), function(nir) gaps(nir, start=start, end=end) ) x@NAMES <- as.character(NA) x@desc <- as.character(NA) x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### disjoin() ### setGeneric("disjoin", function(x, ...) standardGeneric("disjoin")) setMethod("disjoin", "Ranges", function(x) { ## starts: original starts and end+1 when inside another interval ## ends: original ends and start-1 when inside another interval starts <- unique(start(x)) ends <- unique(end(x)) adj_start <- sort(unique(c(starts, ends + 1L))) adj_end <- sort(unique(c(ends, starts - 1L))) adj <- update(x, start=head(adj_start, -1L), end=tail(adj_end, -1L), names=NULL, check=FALSE) subsetByOverlaps(adj, x) } ) setMethod("disjoin", "RangesList", function(x) endoapply(x, disjoin)) setMethod("disjoin", "CompressedIRangesList", function(x, ...) { .wunlist <- function(x) ## unlist CompressedIntegerList, with integer(0) as 0 { w <- integer(length(x)) w[elementLengths(x) != 0L] <- unlist(x, use.names=FALSE) w } rng <- range(x) if (sum(.wunlist(width(rng) + 1)) > .Machine$integer.max) return(endoapply(x, disjoin, ...)) ## localize coordinates off0 <- head(.wunlist(width(rng) + 1L), -1L) offset <- c(1L, cumsum(off0)) - .wunlist(start(rng)) local <- unlist(shift(x, offset), use.names=FALSE) ## disjoin lvls <- names(x) if (is.null(lvls)) lvls <- seq_along(x) d <- disjoin(local, ...) vec <- unlist(start(shift(rng, offset)), use.names=FALSE) lvls0 <- lvls[elementLengths(rng) != 0] f <- lvls0[findInterval(start(d), vec)] d <- split(d, factor(f, levels=lvls)) if (is.null(names(x))) names(d) <- NULL ## globalize coordinates shift(d, -offset) }) setMethod("disjoin", "IntervalForest", function(x, ...) as(disjoin(as(x, "CompressedIRangesList"), ...), "IntervalForest")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### disjointBins() ### ## make intervals disjoint by segregating them into separate Ranges setGeneric("disjointBins", function(x, ...) standardGeneric("disjointBins")) setMethod("disjointBins", "Ranges", function(x) { x_ord <- NULL if (S4Vectors:::isNotSorted(start(x))) { # minimize work for sorted ranges (common) x_ord <- order(x) x <- x[x_ord] } bins <- .Call2("Ranges_disjointBins", start(x), width(x), PACKAGE="IRanges") if (!is.null(x_ord)) { rev_ord <- integer(length(x_ord)) rev_ord[x_ord] <- seq_along(rev_ord) bins <- bins[rev_ord] } names(bins) <- names(x) bins } ) setMethod("disjointBins", "RangesList", function(x) as(lapply(x, disjointBins), "IntegerList")) IRanges/R/intra-range-methods.R0000644000175100017510000006205612607265143017335 0ustar00biocbuildbiocbuild### ========================================================================= ### Intra-range methods ### ------------------------------------------------------------------------- ### normargAtomicList1 <- function(arg, List, lx, argname = deparse(substitute(arg))) { if (is.vector(arg)) arg <- List(as.list(S4Vectors:::recycleVector(arg, lx))) else if (!is(arg, "AtomicList")) stop("'", argname,"' must be a vector or AtomicList object") arg } normargAtomicList2 <- function(arg, List, lx, eln, argname = deparse(substitute(arg))) { if (!(is.vector(arg) && length(arg) == 1L)) { if (is.vector(arg)) arg <- as(rep(S4Vectors:::recycleVector(arg, lx), eln), class(unlist(List()))) else { if (!is(arg, "AtomicList")) stop("'arg' must be a vector or AtomicList object") if (!isTRUE(all.equal(elementLengths(arg), eln, check.attributes=FALSE))) arg <- mapply(S4Vectors:::recycleVector, arg, List(as.list(eln))) arg <- unlist(arg, use.names=FALSE) } } else if (is.list(arg)){ arg <- unlist(arg, use.names=FALSE) } arg } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### shift() ### setGeneric("shift", signature="x", function(x, shift=0L, use.names=TRUE) standardGeneric("shift") ) setMethod("shift", "Ranges", function(x, shift=0L, use.names=TRUE) { if (is(x, "NormalIRanges") && !isSingleNumber(shift)) stop("'shift' must be a single number when shifting ", "a NormalIRanges object") shift <- recycleIntegerArg(shift, "shift", length(x)) new_start <- start(x) + shift if (is(x, "IRanges")) { x@start <- new_start } else { x <- update(x, start=new_start, width=width(x), check=FALSE) } if (!S4Vectors:::normargUseNames(use.names)) names(x) <- NULL validObject(x) x } ) setMethod("shift", "Views", function(x, shift=0L, use.names=TRUE) { x@ranges <- shift(ranges(x), shift=shift, use.names=use.names) x } ) setMethod("shift", "RangesList", function(x, shift=0L, use.names = TRUE) { lx <- length(x) shift <- normargAtomicList1(shift, IntegerList, lx) mendoapply("shift", x = x, shift = shift, MoreArgs = list(use.names = use.names)) }) setMethod("shift", "CompressedIRangesList", function(x, shift=0L, use.names = TRUE) { lx <- length(x) eln <- elementLengths(x) shift <- normargAtomicList2(shift, IntegerList, lx, eln) slot(x, "unlistData", check=FALSE) <- shift(x@unlistData, shift = shift, use.names = use.names) x }) setMethod("shift", "IntervalForest", function(x, shift=0L, use.names = TRUE) as(shift(as(x, "CompressedIRangesList"), shift = shift, use.names = use.names), "IntervalForest")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### narrow() ### setGeneric("narrow", signature="x", function(x, start=NA, end=NA, width=NA, use.names=TRUE) standardGeneric("narrow") ) setMethod("narrow", "Ranges", function(x, start=NA, end=NA, width=NA, use.names=TRUE) { if (is(x, "NormalIRanges")) stop("narrowing a NormalIRanges object is not supported") solved_SEW <- solveUserSEW(width(x), start=start, end=end, width=width) ans_start <- start(x) + start(solved_SEW) - 1L ans_width <- width(solved_SEW) x <- update(x, start=ans_start, width=ans_width, check=FALSE) if (!S4Vectors:::normargUseNames(use.names)) names(x) <- NULL x } ) setMethod("narrow", "Views", function(x, start=NA, end=NA, width=NA, use.names=TRUE) { x@ranges <- narrow(ranges(x), start=start, end=end, width=width, use.names=use.names) x } ) setMethod("narrow", "RangesList", function(x, start = NA, end = NA, width = NA, use.names = TRUE) { lx <- length(x) start <- normargAtomicList1(start, IntegerList, lx) end <- normargAtomicList1(end, IntegerList, lx) width <- normargAtomicList1(width, IntegerList, lx) mendoapply(narrow, x = x, start = start, end = end, width = width, MoreArgs = list(use.names = use.names)) }) setMethod("narrow", "CompressedIRangesList", function(x, start = NA, end = NA, width = NA, use.names = TRUE) { lx <- length(x) eln <- elementLengths(x) start <- normargAtomicList2(start, IntegerList, lx, eln) end <- normargAtomicList2(end, IntegerList, lx, eln) width <- normargAtomicList2(width, IntegerList, lx, eln) slot(x, "unlistData", check=FALSE) <- narrow(x@unlistData, start = start, end = end, width = width, use.names = use.names) x }) setMethod("narrow", "IntervalForest", function(x, start = NA, end = NA, width = NA, use.names = TRUE) as(narrow(as(x, "CompressedIRangesList"), start = start, end = end, width = width, use.names = use.names), "IntervalForest")) ### FIXME: This is a quick and dirty implementation that is TOTALLY ### inefficient. It needs to be improved a lot! ### FIXME: It's also broken because it can return a GappedRanges object with ### empty elements (not allowed). #setMethod("narrow", "GappedRanges", # function(x, start=NA, end=NA, width=NA, use.names=TRUE) # { # solved_SEW <- solveUserSEW(width(x), start=start, end=end, width=width) # start2 <- start(x) + start(solved_SEW) - 1L # end2 <- start2 + width(solved_SEW) - 1L # for (i in seq_len(length(x))) { # x@cnirl[[i]] <- restrict(x[[i]], start=start2[i], end=end2[i]) # } # if (!S4Vectors:::normargUseNames(use.names)) # names(x) <- NULL # x # } #) setMethod("narrow", "MaskCollection", function(x, start=NA, end=NA, width=NA, use.names=TRUE) { solved_SEW <- solveUserSEWForSingleSeq(width(x), start, end, width) solved_start <- start(solved_SEW) solved_end <- end(solved_SEW) solved_width <- width(solved_SEW) x@nir_list <- lapply(nir_list(x), function(nir) shift(restrict(nir, start=solved_start, end=solved_end), 1L - solved_start) ) x@width <- solved_width if (!S4Vectors:::normargUseNames(use.names)) names(x) <- NULL x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### resize() ### setGeneric("resize", signature="x", function(x, width, fix="start", use.names=TRUE, ...) standardGeneric("resize") ) setMethod("resize", "Ranges", function(x, width, fix="start", use.names=TRUE) { if (is(x, "NormalIRanges")) stop("resizing a NormalIRanges object is not supported") lx <- length(x) if (!is.numeric(width) || S4Vectors:::anyMissing(width)) stop("'width' must be a numeric vector without NA's") if (!is.integer(width)) width <- as.integer(width) if (S4Vectors:::anyMissingOrOutside(width, 0L)) stop("'width' values must be non-negative") if (!(is.character(fix) || (is(fix, "Rle") && is.character(runValue(fix)))) || (length(fix) == 0L && length(x) > 0L) || (length(setdiff(unique(fix), c("start", "end", "center"))) > 0)) { stop("'fix' must be a character vector or character Rle ", "with values in \"start\", \"end\", and \"center\"") } if (!is(fix, "Rle")) fix <- Rle(fix) if (length(fix) != lx) fix <- rep(fix, length.out = lx) ans_width <- S4Vectors:::recycleVector(width, lx) ans_start <- start(x) if (!identical(runValue(fix), "start")) { fixEnd <- as(fix == "end", "IRanges") if (length(fixEnd) > 0) { value <- extractROWS(ans_start, fixEnd) + (extractROWS(width(x), fixEnd) - extractROWS(ans_width, fixEnd)) ans_start <- replaceROWS(ans_start, fixEnd, value) } fixCenter <- as(fix == "center", "IRanges") if (length(fixCenter) > 0) { value <- extractROWS(ans_start, fixCenter) + (extractROWS(width(x), fixCenter) - extractROWS(ans_width, fixCenter)) %/% 2L ans_start <- replaceROWS(ans_start, fixCenter, value) } } x <- update(x, start=ans_start, width=ans_width, check=FALSE) if (!S4Vectors:::normargUseNames(use.names)) names(x) <- NULL x } ) setMethod("resize", "RangesList", function(x, width, fix = "start", use.names = TRUE) { lx <- length(x) width <- normargAtomicList1(width, IntegerList, lx) fix <- normargAtomicList1(fix, CharacterList, lx) mendoapply(resize, x = x, width = width, fix = fix, MoreArgs = list(use.names = use.names)) }) setMethod("resize", "CompressedIRangesList", function(x, width, fix = "start", use.names = TRUE) { lx <- length(x) eln <- elementLengths(x) width <- normargAtomicList2(width, IntegerList, lx, eln) fix <- normargAtomicList2(fix, CharacterList, lx, eln) slot(x, "unlistData", check=FALSE) <- resize(x@unlistData, width = width, fix = fix, use.names = use.names) x }) setMethod("resize", "IntervalForest", function(x, width, fix = "start", use.names = TRUE) as(resize(as(x, "CompressedIRangesList"), width = width, fix = fix, use.names = use.names), "IntervalForest")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### flank() ### setGeneric("flank", signature="x", function(x, width, start=TRUE, both=FALSE, use.names=TRUE, ...) standardGeneric("flank") ) setMethod("flank", "Ranges", function(x, width, start=TRUE, both=FALSE, use.names=TRUE) { if (is(x, "NormalIRanges")) stop("flanking a NormalIRanges object is not supported") width <- recycleIntegerArg(width, "width", length(x)) if (!is.logical(start) || S4Vectors:::anyMissing(start)) stop("'start' must be logical without NA's") start <- S4Vectors:::recycleVector(unname(start), length(x)) if (!isTRUEorFALSE(both)) stop("'both' must be TRUE or FALSE") ans_start <- integer(length(x)) if (both) { idx1 <- which(start) idx2 <- which(!start) width <- abs(width) ans_width <- 2L * width ans_start[idx1] <- start(x)[idx1] - width[idx1] ans_start[idx2] <- end(x)[idx2] - width[idx2] + 1L } else { idx1a <- which(start & width >= 0L) idx1b <- which(start & width < 0L) idx2a <- which(!start & width >= 0L) idx2b <- which(!start & width < 0L) ans_width <- abs(width) ans_start[idx1a] <- start(x)[idx1a] - width[idx1a] ans_start[idx1b] <- start(x)[idx1b] ans_start[idx2a] <- end(x)[idx2a] + 1L ans_start[idx2b] <- end(x)[idx2b] + width[idx2b] + 1L } x <- update(x, start=ans_start, width=ans_width, check=FALSE) if (!S4Vectors:::normargUseNames(use.names)) names(x) <- NULL x } ) setMethod("flank", "RangesList", function(x, width, start = TRUE, both = FALSE, use.names = TRUE) { lx <- length(x) width <- normargAtomicList1(width, IntegerList, lx) start <- normargAtomicList1(start, LogicalList, lx) mendoapply(flank, x = x, width = width, start = start, MoreArgs = list(both = both, use.names = use.names)) }) setMethod("flank", "CompressedIRangesList", function(x, width, start = TRUE, both = FALSE, use.names = TRUE) { lx <- length(x) eln <- elementLengths(x) width <- normargAtomicList2(width, IntegerList, lx, eln) start <- normargAtomicList2(start, LogicalList, lx, eln) slot(x, "unlistData", check=FALSE) <- flank(x@unlistData, width = width, start = start, both = both, use.names = use.names) x }) setMethod("flank", "IntervalForest", function(x, width, start = TRUE, both = FALSE, use.names = TRUE) as(flank(as(x, "CompressedIRangesList"), width = width, start = start, both = both, use.names = use.names), "IntervalForest")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### promoters() ### setGeneric("promoters", signature="x", function(x, upstream=2000, downstream=200, ...) standardGeneric("promoters") ) setMethod("promoters", "Ranges", function(x, upstream=2000, downstream=200, ...) { if (is(x, "NormalIRanges")) stop("promoters on a NormalIRanges object is not supported") if (!isSingleNumber(upstream)) stop("'upstream' must be a single integer") if (!is.integer(upstream)) upstream <- as.numeric(upstream) if (!isSingleNumber(downstream)) stop("'downstream' must be a single integer") if (!is.integer(downstream)) downstream <- as.numeric(downstream) if (upstream < 0 | downstream < 0) stop("'upstream' and 'downstream' must be integers >= 0") st <- start(x) start(x) <- st - upstream end(x) <- st + downstream - 1L x } ) setMethod("promoters", "Views", function(x, upstream=2000, downstream=200, ...) { x@ranges <- promoters(ranges(x), upstream, downstream) x } ) setMethod("promoters", "RangesList", function(x, upstream=2000, downstream=200, ...) { endoapply(x, promoters, upstream = upstream, downstream = downstream) } ) setMethod("promoters", "CompressedIRangesList", function(x, upstream=2000, downstream=200, ...) { slot(x, "unlistData", check=FALSE) <- promoters(x@unlistData, upstream = upstream, downstream = downstream, ...) x } ) setMethod("promoters", "IntervalForest", function(x, upstream=2000, downstream=200, ...) as(promoters(as(x, "CompressedIRangesList"), upstream = upstream, downstream = downstream), "IntervalForest")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### reflect() ### setGeneric("reflect", signature="x", function(x, bounds, use.names=TRUE) standardGeneric("reflect") ) setMethod("reflect", "Ranges", function(x, bounds, use.names=TRUE) { if (is(x, "NormalIRanges")) stop("reflecting a NormalIRanges object is not supported") if (!is(bounds, "Ranges")) stop("'bounds' must be a Ranges object") if (length(x) > 1 && length(bounds) == 0) stop("'bounds' is an empty Ranges object") if (length(x) < length(bounds)) bounds <- head(bounds, length(x)) ans_start <- (2L * start(bounds) + width(bounds) - 1L) - end(x) x <- update(x, start=ans_start, width=width(x), check=FALSE) if (!S4Vectors:::normargUseNames(use.names)) names(x) <- NULL x } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### restrict() ### setGeneric("restrict", signature="x", function(x, start=NA, end=NA, keep.all.ranges=FALSE, use.names=TRUE) standardGeneric("restrict") ) ### We distinguish 4 exclusive types of relationship between a range in 'x' ### and its corresponding restriction interval (specified by 'start' and ### 'end'): ### - Type 1: They have a non-empty intersection. ### - Type 2: The restriction interval is empty but its bounds are within ### the range in 'x'. ### - Type 3: The restriction interval is not empty and is adjacent to the ### range in 'x' i.e. the range in 'x' ends at start - 1 or starts ### at end - 1. ### drop.ranges.mode: ### 0L: Ranges in 'x' that are empty after restriction are dropped. ### 1L: Ranges in 'x' that are not overlapping and not even adjacent ### with the region of restriction are dropped. ### "Not overlapping and not adjacent" means that they end strictly ### before start - 1 or start strictly after end + 1. ### Those that are not overlapping but are however adjacent are kept ### (and are empty after restriction). ### 2L: All ranges in 'x' are kept after restriction. ### Ranges ### Note that the only mode compatible with a NormalIRanges object is 0L. Ranges.restrict <- function(x, start, end, drop.ranges.mode, use.names) { if (!S4Vectors:::isNumericOrNAs(start)) stop("'start' must be a vector of integers") if (!is.integer(start)) start <- as.integer(start) if (!S4Vectors:::isNumericOrNAs(end)) stop("'end' must be a vector of integers") if (!is.integer(end)) end <- as.integer(end) if (length(x) != 0L) { if (length(start) == 0L || length(start) > length(x)) stop("invalid 'start' length") if (length(end) == 0L || length(end) > length(x)) stop("invalid 'end' length") } start <- S4Vectors:::recycleVector(start, length(x)) end <- S4Vectors:::recycleVector(end, length(x)) use.names <- S4Vectors:::normargUseNames(use.names) ans_start <- start(x) ans_end <- end(x) if (use.names) ans_names <- names(x) else ans_names <- NULL ## Compare ranges in 'x' with 'start'. if (drop.ranges.mode == 0L) far_too_left <- !is.na(start) & (ans_end < start) else far_too_left <- !is.na(start) & (ans_end < start - 1L) if (drop.ranges.mode == 2L) { ans_end[far_too_left] <- start[far_too_left] - 1L } else { ## Drop the ranges that are far too left with respect to the ## region of restriction. keep_it <- !far_too_left ans_start <- ans_start[keep_it] ans_end <- ans_end[keep_it] if (!is.null(ans_names)) ans_names <- ans_names[keep_it] start <- start[keep_it] end <- end[keep_it] } ## Fix 'ans_start'. too_left <- !is.na(start) & (ans_start < start) ans_start[too_left] <- start[too_left] ## Compare ranges in 'x' with 'end'. if (drop.ranges.mode == 0L) far_too_right <- !is.na(end) & (ans_start > end) else far_too_right <- !is.na(end) & (ans_start > end + 1L) if (drop.ranges.mode == 2L) { ans_start[far_too_right] <- end[far_too_right] + 1L } else { ## Drop the ranges that are far too right with respect to the ## region of restriction. keep_it <- !far_too_right ans_start <- ans_start[keep_it] ans_end <- ans_end[keep_it] if (!is.null(ans_names)) ans_names <- ans_names[keep_it] start <- start[keep_it] end <- end[keep_it] } ## Fix 'ans_end'. too_right <- !is.na(end) & (ans_end > end) ans_end[too_right] <- end[too_right] ans_width <- ans_end - ans_start + 1L unsafe.update(x, start=ans_start, width=ans_width, names=ans_names) } setMethod("restrict", "Ranges", function(x, start=NA, end=NA, keep.all.ranges=FALSE, use.names=TRUE) { if (!isTRUEorFALSE(keep.all.ranges)) stop("'keep.all.ranges' must be TRUE or FALSE") use.names <- S4Vectors:::normargUseNames(use.names) if (is(x, "NormalIRanges")) { if (keep.all.ranges) stop("'keep.all.ranges=TRUE' is not supported ", "when 'x' is a NormalIRanges object") drop.ranges.mode <- 0L } else { if (keep.all.ranges) drop.ranges.mode <- 2L else drop.ranges.mode <- 1L } Ranges.restrict(x, start, end, drop.ranges.mode, use.names) } ) setMethod("restrict", "RangesList", function(x, start = NA, end = NA, keep.all.ranges = FALSE, use.names = TRUE) { lx <- length(x) start <- normargAtomicList1(start, IntegerList, lx) end <- normargAtomicList1(end, IntegerList, lx) mendoapply(restrict, x, start = start, end = end, MoreArgs = list(keep.all.ranges = keep.all.ranges, use.names = use.names)) }) setMethod("restrict", "CompressedIRangesList", function(x, start = NA, end = NA, keep.all.ranges = FALSE, use.names = TRUE) { if (!isTRUEorFALSE(keep.all.ranges)) stop("'keep.all.ranges' must be TRUE or FALSE") if (keep.all.ranges) { lx <- length(x) eln <- elementLengths(x) start <- normargAtomicList2(start, IntegerList, lx, eln) end <- normargAtomicList2(end, IntegerList, lx, eln) slot(x, "unlistData", check=FALSE) <- restrict(x@unlistData, start = start, end = end, keep.all.ranges = keep.all.ranges, use.names = use.names) } else x <- callNextMethod() x }) setMethod("restrict", "IntervalForest", function(x, start = NA, end = NA, keep.all.ranges = FALSE, use.names = TRUE) { if (keep.all.ranges) stop("'keep.all.ranges' must be FALSE in ", "'restrict,IntervalForest'") as(restrict(as(x, "CompressedIRangesList"), start = start, end = end, keep.all.ranges = keep.all.ranges, use.names = use.names), "IntervalForest") }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### threebands() ### setGeneric("threebands", signature="x", function(x, start=NA, end=NA, width=NA) standardGeneric("threebands") ) ### Method for IRanges only! setMethod("threebands", "IRanges", function(x, start=NA, end=NA, width=NA) { middle <- narrow(x, start=start, end=end, width=width, use.names=FALSE) left <- right <- middle left@start <- start(x) left@width <- start(middle) - start(x) right@start <- end(middle) + 1L right@width <- end(x) - end(middle) list(left=left, middle=middle, right=right) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Zooming (symmetrically scales the width). ### ### TODO: Implement a zoom() generic and methods and make the "Ops" method ### below a simple convenience wrapper for zoom(). Recommend the use of zoom() ### over "Ops" methods in packages and scripts. Reserve "Ops" methods as a ### convenience when working interactively. ### setMethod("Ops", c("Ranges", "numeric"), function(e1, e2) { if (S4Vectors:::anyMissing(e2)) stop("NA not allowed as zoom factor") if ((length(e1) < length(e2) && length(e1)) || (length(e1) && !length(e2)) || (length(e1) %% length(e2) != 0)) stop("zoom factor length not a multiple of number of ranges") if (.Generic == "*") { e2 <- ifelse(e2 < 0, abs(1/e2), e2) r <- e1 mid <- (start(r)+end(r))/2 w <- width(r)/e2 update(r, start = ceiling(mid - w/2), width = floor(w), check = FALSE) } else { if (.Generic == "-") { e2 <- -e2 .Generic <- "+" } if (.Generic == "+") { if (any(-e2*2 > width(e1))) stop("adjustment would result in ranges with negative widths") update(e1, start = start(e1) - e2, end = end(e1) + e2, check = FALSE) } } } ) setMethod("Ops", c("RangesList", "numeric"), function(e1, e2) { for (i in seq_len(length(e1))) e1[[i]] <- callGeneric(e1[[i]], e2) e1 }) setMethod("Ops", c("CompressedIRangesList", "numeric"), function(e1, e2) { relist(callGeneric(unlist(e1, use.names = FALSE), e2), e1) }) IRanges/R/mapCoords-methods.R0000644000175100017510000000065612607265143017053 0ustar00biocbuildbiocbuild### ========================================================================= ### 'mapCoords' and 'pmapCoords' generics ### ------------------------------------------------------------------------- ### ### setGeneric("mapCoords", signature=c("from", "to"), function(from, to, ...) standardGeneric("mapCoords") ) setGeneric("pmapCoords", signature=c("from", "to"), function(from, to, ...) standardGeneric("pmapCoords") ) IRanges/R/multisplit.R0000644000175100017510000000066112607265143015665 0ustar00biocbuildbiocbuild### ========================================================================= ### multisplit() ### ------------------------------------------------------------------------- ### multisplit <- function(x, f) { if (!is.list(f) && !is(f, "List")) stop("'f' must be a list") if (length(x) != length(f)) stop("Length of 'f' must equal length of 'x'") splitAsList(rep(x, elementLengths(f)), unlist(f, use.names = FALSE)) } IRanges/R/nearest-methods.R0000644000175100017510000001471012607265143016561 0ustar00biocbuildbiocbuild### ========================================================================= ### nearest (and related) methods ### ------------------------------------------------------------------------- ### setClassUnion("RangesORmissing", c("Ranges", "missing")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### precede() and follow() ### setGeneric("precede", function(x, subject = x, ...) standardGeneric("precede")) setMethod("precede", c("Ranges", "RangesORmissing"), function(x, subject, select = c("first", "all")) { select <- match.arg(select) s <- start(subject) ord <- NULL if (S4Vectors:::isNotSorted(s)) { ord <- S4Vectors:::orderInteger(s) s <- s[ord] } if (select == "all") { srle <- Rle(s) s <- runValue(srle) } i <- findInterval(end(x), s) + 1L i[i > length(s)] <- NA if (select == "all") { vectorToHits(i, srle, ord) } else { if (!is.null(ord)) i <- ord[i] i } } ) setGeneric("follow", function(x, subject = x, ...) standardGeneric("follow")) setMethod("follow", c("Ranges", "RangesORmissing"), function(x, subject, select = c("last", "all")) { select <- match.arg(select) e <- end(subject) ord <- NULL if (S4Vectors:::isNotSorted(e)) { ord <- S4Vectors:::orderInteger(e) e <- e[ord] } if (select == "all") { srle <- Rle(e) e <- runValue(srle) } i <- findInterval(start(x) - 1L, e) i[i == 0] <- NA if (select == "all") { vectorToHits(i, srle, ord) } else { if (!is.null(ord)) i <- ord[i] i } } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### nearest() ### ### Used in GenomicRanges. ### TODO: Move to Hits-class.R vectorToHits <- function(i, srle, ord) { lx <- length(i) v <- !is.na(i) i <- i[v] w <- width(srle)[i] subj <- as.integer(IRanges(start(srle)[i], width=w)) m <- cbind(queryHits = rep(seq(lx)[v], w), subjectHits = if (!is.null(ord)) ord[subj] else subj) if (!is.null(ord)) m <- m[S4Vectors:::orderIntegerPairs(m[,1L], m[,2L]),,drop=FALSE] Hits(m[ , 1L], m[ , 2L], lx, length(srle)) } setGeneric("nearest", function(x, subject, ...) standardGeneric("nearest")) setMethod("nearest", c("Ranges", "RangesORmissing"), function(x, subject, select = c("arbitrary", "all"), algorithm = c("nclist", "intervaltree")) { select <- match.arg(select) if (!missing(subject)) { ol <- findOverlaps(x, subject, select = select, algorithm = match.arg(algorithm)) } else { subject <- x ol <- findOverlaps(x, select = select, algorithm = match.arg(algorithm), ignoreSelf = TRUE) } if (select == "all") { olv <- selectHits(ol, select="first") } else olv <- ol x <- x[is.na(olv)] before <- precede(x, subject, if (select == "all") "all" else "first") after <- follow(x, subject, if (select == "all") "all" else "last") if (select == "all") { before0 <- before before <- selectHits(before, select="first") after0 <- after after <- selectHits(after, select="first") } leftdist <- (start(subject)[before] - end(x)) rightdist <- (start(x) - end(subject)[after]) left <- leftdist < rightdist left[is.na(left)] <- is.na(after)[is.na(left)] if (select == "all") { filterHits <- function(hits, i) { m <- as.matrix(hits[as(hits, "IRanges")[i]]) m[,1L] <- map[m[,1L]] m } map <- which(is.na(olv)) right <- !left left[leftdist == rightdist] <- TRUE m <- rbind(as.matrix(ol), filterHits(before0, left), filterHits(after0, right)) m <- m[S4Vectors:::orderIntegerPairs(m[,1L], m[,2L]),, drop=FALSE] ## unname() required because in case 'm' has only 1 row ## 'm[ , 1L]' and 'm[ , 2L]' will return a named atomic vector ol@queryHits <- unname(m[ , 1L]) ol@subjectHits <- unname(m[ , 2L]) } else { olv[is.na(olv)] <- ifelse(left, before, after) ol <- olv } ol }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### distance() ### setGeneric("distance", function(x, y, ...) standardGeneric("distance")) setMethod("distance", c("Ranges", "Ranges"), function(x, y) { max_start <- pmax.int(start(x), start(y)) min_end <- pmin.int(end(x), end(y)) pmax.int(max_start - min_end - 1L, 0L) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### distanceToNearest() ### setGeneric("distanceToNearest", function(x, subject = x, ...) standardGeneric("distanceToNearest")) setMethod("distanceToNearest", c("Ranges", "RangesORmissing"), function(x, subject, select = c("arbitrary", "all"), algorithm = c("nclist", "intervaltree")) { select <- match.arg(select) if (missing(subject)) { subject <- x x_nearest <- nearest(x, select = select, algorithm = match.arg(algorithm)) } else { x_nearest <- nearest(x, subject, select = select, algorithm = match.arg(algorithm)) } if (select == "arbitrary") { queryHits <- seq_along(x)[!is.na(x_nearest)] subjectHits <- x_nearest[!is.na(x_nearest)] } else { queryHits <- queryHits(x_nearest) subjectHits <- subjectHits(x_nearest) } if (!length(subjectHits) || all(is.na(subjectHits))) { Hits(queryLength=length(x), subjectLength=length(subject), distance=integer(0)) } else { distance = distance(x[queryHits], subject[subjectHits]) Hits(queryHits, subjectHits, length(x), length(subject), distance) } } ) IRanges/R/read.Mask.R0000644000175100017510000003375212607265143015273 0ustar00biocbuildbiocbuild### ========================================================================= ### Read a mask from a file ### ----------------------- ### ### From an NCBI "agp" file (for chrY in hs b36v3): ### library(BSgenome.Hsapiens.NCBI.b36v3) ### file1 <- system.file("extdata", "hs_b36v3_chrY.agp", package="IRanges") ### mask1 <- read.agpMask(file1, seqname="chrY", mask.width=length(Hsapiens$chrY)) ### ### From an UCSC "gap" file (for chrY in hg18): ### library(BSgenome.Hsapiens.UCSC.hg18) ### file2 <- system.file("extdata", "chrY_gap.txt", package="IRanges") ### mask2 <- read.gapMask(file2, seqname="chrY", mask.width=length(Hsapiens$chrY)) ### ### From an UCSC "lift" file (for hg18): ### file3 <- system.file("extdata", "hg18liftAll.lft", package="IRanges") ### mask3 <- read.liftMask(file3, seqname="chr1") ### ### From a RepeatMasker .out file (for chrM in ce2): ### library(BSgenome.Celegans.UCSC.ce2) ### file4 <- system.file("extdata", "ce2chrM.fa.out", package="IRanges") ### mask4 <- read.rmMask(file4, seqname="chrM", mask.width=length(Celegans$chrM)) ### ### From a Tandem Repeats Finder .bed file (for chrM in ce2): ### file5 <- system.file("extdata", "ce2chrM.bed", package="IRanges") ### mask5 <- read.trfMask(file5, seqname="chrM", mask.width=length(Celegans$chrM)) ### ### ------------------------------------------------------------------------- .showDistinctSeqnamesAndStop <- function(seqnames) { distinct_seqnames <- paste("\"", unique(seqnames), "\"", sep="") distinct_seqnames <- paste(distinct_seqnames, collapse=", ") stop(length(distinct_seqnames), " distinct seqnames found in this file: ", distinct_seqnames) } .newEmptyMask <- function(seqname, mask.width, mask.name, mask.desc, nofound_what="information") { msg <- paste("No ", nofound_what, " found for sequence \"", seqname, "\" in this file. ", sep="") if (is.na(mask.width)) stop(msg, "Please use the\n", " 'mask.width' argument to specify the width of the empty mask to\n", " return (i.e. the length of the sequence this mask will be put on).") warning(msg, "returning empty mask") ans <- Mask(mask.width) # empty mask names(ans) <- mask.name desc(ans) <- paste(mask.desc, "(empty)") ans } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### read.agpMask() and read.gapMask() extract the AGAPS mask from an NCBI ### "agp" file or a UCSC "gap" file, respectively. ### .guessGapFileCOL2CLASS <- function(file) { ## UCSC "gap" files generally have the 9 columns below except for some ## organisms like Rhesus that have only 8 columns (no 'bin' column). COL2CLASS <- c( `bin`="integer", `chrom`="character", `chr_start`="integer", `chr_stop`="integer", `part_no`="integer", `part_type`="character", `gap_len`="integer", `gap_type`="character", `bridge`="character" ) line1 <- try(read.table(file, sep="\t", col.names=names(COL2CLASS), colClasses=COL2CLASS, nrows=1L, check.names=FALSE), silent=TRUE) if (!inherits(line1, "try-error")) return(COL2CLASS) COL2CLASS <- COL2CLASS[-1L] line1 <- try(read.table(file, sep="\t", col.names=names(COL2CLASS), colClasses=COL2CLASS, nrows=1L, check.names=FALSE), silent=TRUE) if (!inherits(line1, "try-error")) return(COL2CLASS) stop("unable to guess the column names in \"gap\" file '", file, "', sorry") } .read.agpORgapFile <- function(agp_or_gap, file) { if (agp_or_gap == "agp") { COL2CLASS <- c( `chrom`="character", `chr_start`="integer", `chr_stop`="integer", `part_no`="integer", `part_type`="character", `gap_len`="character", `gap_type`="character", `linkage`="character", `empty`="character" ) } else if (agp_or_gap == "gap") { COL2CLASS <- .guessGapFileCOL2CLASS(file) } else { stop("read.Mask internal error: please report") } COLS <- c( "chrom", "chr_start", "chr_stop", "part_type", "gap_len", "gap_type" ) COL2CLASS[!(names(COL2CLASS) %in% COLS)] <- "NULL" data <- read.table(file, sep="\t", col.names=names(COL2CLASS), colClasses=COL2CLASS, check.names=FALSE, fill=TRUE) } .read.agpORgapMask <- function(agp_or_gap, file, seqname, mask.width, gap.types, use.gap.types) { if (!isSingleString(seqname)) stop("'seqname' must be a single string") if (!isSingleNumberOrNA(mask.width)) stop("'mask.width' must be a single integer or 'NA'") if (!is.integer(mask.width)) mask.width <- as.integer(mask.width) if (!is.null(gap.types) && (!is.character(gap.types) || S4Vectors:::anyMissing(gap.types) || anyDuplicated(gap.types))) stop("'gap.types' must be 'NULL' or a character vector ", "with no NAs and no duplicated") if (!isTRUEorFALSE(use.gap.types)) stop("'use.gap.types' must be TRUE or FALSE") data <- .read.agpORgapFile(agp_or_gap, file) if (seqname == "?") .showDistinctSeqnamesAndStop(data$chrom) data <- data[data$chrom == seqname, ] ii <- data$part_type == "N" if (agp_or_gap == "agp") { data <- data[ii, ] } else if (!all(ii)) { warning("gap file contains gaps with a part_type that is not N") } if (length(gap.types) == 1 && gap.types == "?") { found_types <- paste("\"", unique(data$gap_type), "\"", sep="") found_types <- paste(found_types, collapse=", ") stop("gap types found in this file for sequence \"", seqname, "\": ", found_types) } mask.name <- "AGAPS" mask.desc <- "assembly gaps" if (!is.null(gap.types)) { data <- data[data$gap_type %in% gap.types, ] mask.desc <- paste(mask.desc, " [type=", paste(gap.types, collapse="|"), "]", sep="") } if (nrow(data) == 0) return(.newEmptyMask(seqname, mask.width, mask.name, mask.desc, mask.desc)) if (agp_or_gap == "agp") ranges_start <- data$chr_start else ranges_start <- data$chr_start + 1L ranges <- IRanges(start=ranges_start, width=as.integer(data$gap_len)) ## Sanity check if (!identical(end(ranges), data$chr_stop)) stop("broken \"", agp_or_gap, "\" file: contains inconsistent ", "chr_start/chr_stop/gap_len values ", "for assembly gaps in sequence \"", seqname, "\"") if (use.gap.types) { names(ranges) <- data$gap_type if (S4Vectors:::isNotStrictlySorted(start(ranges))) ranges <- ranges[S4Vectors:::orderInteger(start(ranges))] if (!isNormal(ranges)) stop("cannot use the gap types when some gaps are adjacent or overlap") nir1 <- asNormalIRanges(ranges, force=FALSE) } else { nir1 <- asNormalIRanges(ranges, force=TRUE) } ## Don't use new2(): the validity of the new mask needs to be checked! new2("MaskCollection", nir_list=list(nir1), width=mask.width, active=TRUE, NAMES=mask.name, desc=mask.desc, check=FALSE) } read.agpMask <- function(file, seqname="?", mask.width=NA, gap.types=NULL, use.gap.types=FALSE) .read.agpORgapMask("agp", file, seqname, mask.width, gap.types, use.gap.types) read.gapMask <- function(file, seqname="?", mask.width=NA, gap.types=NULL, use.gap.types=FALSE) .read.agpORgapMask("gap", file, seqname, mask.width, gap.types, use.gap.types) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### read.liftMask() extracts the AGAPS mask from a UCSC "lift" file. ### .read.liftFile <- function(file) { COL2CLASS <- c( `offset`="integer", `xxxx`="NULL", # not sure how to call this `width`="integer", `seqname`="character", `seqlen`="integer" ) read.table(file, col.names=names(COL2CLASS), colClasses=COL2CLASS, check.names=FALSE) } read.liftMask <- function(file, seqname="?", mask.width=NA) { if (!isSingleString(seqname)) stop("'seqname' must be a single string") if (!isSingleNumberOrNA(mask.width)) stop("'mask.width' must be a single integer or 'NA'") if (!is.integer(mask.width)) mask.width <- as.integer(mask.width) data <- .read.liftFile(file) if (seqname == "?") .showDistinctSeqnamesAndStop(data$seqname) data <- data[data$seqname == seqname, ] if (nrow(data) == 0) return(.newEmptyMask(seqname, mask.width, "AGAPS", "assembly gaps")) ## Sanity checks seqlen0 <- unique(data$seqlen) if (length(seqlen0) != 1) stop("broken \"lift\" file: contains different lengths ", "for sequence \"", seqname, "\"") if (!is.na(mask.width) && mask.width != seqlen0) stop("when supplied, 'mask.width' must match the length found ", "in the file for sequence \"", seqname, "\"") contigs0 <- IRanges(start=data$offset+1, width=data$width) contigs1 <- asNormalIRanges(contigs0, force=TRUE) if (length(contigs1) != length(contigs0)) warning("some contigs are adjacent or overlapping") contigs <- Mask(seqlen0, start=start(contigs1), width=width(contigs1)) ans <- gaps(contigs) names(ans) <- "AGAPS" desc(ans) <- "assembly gaps" ans } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### read.rmMask() extracts the RM mask from a RepeatMasker .out file. ### ### See http://www.repeatmasker.org/webrepeatmaskerhelp.html for a ### description of the RepeatMasker output format. ### .read.rmFile <- function(file) { COL2CLASS <- c( `SW_score`="integer", `perc_div`="numeric", `perc_del`="numeric", `perc_ins`="numeric", `query_sequence`="character", `begin_in_query`="integer", `end_in_query`="integer", `left_in_query`="character", `C`="character", `matching_repeat`="character", `repeat_class_or_family`="character", `begin_in_repeat`="integer", `end_in_repeat`="integer", `left_in_repeat`="character", `ID`="character" ) COLS <- c("query_sequence", "begin_in_query", "end_in_query", "ID") COL2CLASS[!(names(COL2CLASS) %in% COLS)] <- "NULL" read.table(file, col.names=names(COL2CLASS), colClasses=COL2CLASS, skip=3, check.names=FALSE) } read.rmMask <- function(file, seqname="?", mask.width=NA, use.IDs=FALSE) { if (!isSingleString(seqname)) stop("'seqname' must be a single string") if (!isSingleNumberOrNA(mask.width)) stop("'mask.width' must be a single integer or 'NA'") if (!is.integer(mask.width)) mask.width <- as.integer(mask.width) if (!isTRUEorFALSE(use.IDs)) stop("'use.IDs' must be TRUE or FALSE") data <- .read.rmFile(file) if (seqname == "?") .showDistinctSeqnamesAndStop(data$query_sequence) data <- data[data$query_sequence == seqname, ] if (nrow(data) == 0) return(.newEmptyMask(seqname, mask.width, "RM", "RepeatMasker")) ranges <- IRanges(start=data$begin_in_query, end=data$end_in_query) if (use.IDs) { names(ranges) <- data$ID if (S4Vectors:::isNotStrictlySorted(start(ranges))) ranges <- ranges[S4Vectors:::orderInteger(start(ranges))] if (!isNormal(ranges)) stop("cannot use the repeat IDs when some repeats are adjacent or overlap") nir1 <- asNormalIRanges(ranges, force=FALSE) } else { nir1 <- asNormalIRanges(ranges, force=TRUE) } ## Don't use new2(): the validity of the new mask needs to be checked! new2("MaskCollection", nir_list=list(nir1), width=mask.width, active=TRUE, NAMES="RM", desc="RepeatMasker", check=FALSE) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### read.trfMask() extracts the TRF mask from a Tandem Repeats Finder .bed ### file. ### .read.trfFile <- function(file) { COL2CLASS <- c( `chrom`="character", `chromStart`="integer", `chromEnd`="integer", `name`="character", `period`="integer", `copyNum`="numeric", `consensusSize`="integer", `perMatch`="integer", `perIndel`="integer", `score`="integer", `A`="integer", `C`="integer", `G`="integer", `T`="integer", `entropy`="numeric", `sequence`="character" ) COLS <- c("chrom", "chromStart", "chromEnd") COL2CLASS[!(names(COL2CLASS) %in% COLS)] <- "NULL" read.table(file, col.names=names(COL2CLASS), colClasses=COL2CLASS, check.names=FALSE) } read.trfMask <- function(file, seqname="?", mask.width=NA) { if (!isSingleString(seqname)) stop("'seqname' must be a single string") if (!isSingleNumberOrNA(mask.width)) stop("'mask.width' must be a single integer or 'NA'") if (!is.integer(mask.width)) mask.width <- as.integer(mask.width) data <- .read.trfFile(file) if (seqname == "?") .showDistinctSeqnamesAndStop(data$chrom) data <- data[data$chrom == seqname, ] if (nrow(data) == 0) return(.newEmptyMask(seqname, mask.width, "TRF", "Tandem Repeats Finder")) ranges <- IRanges(start=data$chromStart+1, end=data$chromEnd) nir1 <- asNormalIRanges(ranges, force=TRUE) ## Don't use new2(): the validity of the new mask needs to be checked! new2("MaskCollection", nir_list=list(nir1), width=mask.width, active=TRUE, NAMES="TRF", desc="Tandem Repeats Finder", check=FALSE) } IRanges/R/reverse-methods.R0000644000175100017510000000534212607265143016574 0ustar00biocbuildbiocbuild### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### The "reverse" generic and methods. ### setGeneric("reverse", function(x, ...) standardGeneric("reverse")) setMethod("reverse", "character", function(x, ...) { if (length(x) == 0) return(x) sapply(strsplit(x, NULL, fixed=TRUE), function(xx) paste(rev(xx), collapse="")) } ) ### This method does NOT preserve normality. .IRanges.reverse <- function(x, ...) { if (length(x) == 0L) return(x) args <- S4Vectors:::extraArgsAsList(NULL, ...) argnames <- names(args) n2p <- match(c("start", "end", "use.names"), argnames) if (is.na(n2p[1L])) { start <- min(start(x)) } else { start <- args[[n2p[1L]]] if (!is.numeric(start)) stop("'start' must be a vector of integers") if (!is.integer(start)) start <- as.integer(start) if (S4Vectors:::anyMissing(start)) stop("'start' contains NAs") } if (is.na(n2p[2L])) { end <- max(end(x)) } else { end <- args[[n2p[2L]]] if (!is.numeric(end)) stop("'end' must be a vector of integers") if (!is.integer(end)) end <- as.integer(end) if (S4Vectors:::anyMissing(end)) stop("'end' contains NAs") } if (!is.na(n2p[3L]) && !S4Vectors:::normargUseNames(args[[n2p[3L]]])) x <- set_IRanges_names(x, NULL) ## WARNING: -end(x) *must* appear first in this expression if we want ## the supplied 'start' and 'end' to be recycled properly. ## Remember that in R, because of the recycling, addition of numeric ## vectors of different lengths is not associative i.e. in general ## '(x + y) + z' is not the same as 'x + (y + z)'. For example: ## (integer(6) + 1:2) + 1:3 and integer(6) + (1:2 + 1:3) ## are not the same. x@start[] <- -end(x) + start + end x } setMethod("reverse", "IRanges", .IRanges.reverse) setMethod("reverse", "NormalIRanges", function(x, ...) { ## callNextMethod() temporarily breaks 'x' as a NormalIRanges object ## because the returned ranges are ordered from right to left. x <- callNextMethod() unsafe.update(x, start=rev(start(x)), width=rev(width(x)), names=rev(names(x))) } ) setMethod("reverse", "Views", function(x, ...) { x@subject <- rev(subject(x)) x@ranges <- reverse(ranges(x), start=1L, end=length(subject(x))) x } ) setMethod("reverse", "MaskCollection", function(x, ...) { start <- 1L end <- width(x) x@nir_list <- lapply(nir_list(x), function(nir) reverse(nir, start=start, end=end) ) x } ) IRanges/R/seqapply.R0000644000175100017510000000221612607265143015313 0ustar00biocbuildbiocbuild### ========================================================================= ### The stuff in this file should go somewhere else, probably close to ### splitAsList() (currently extractList.R) ### ------------------------------------------------------------------------- ### ## NOT exported. `splitAsList<-` <- function(x, f, drop = FALSE, ..., value) { if (!isTRUEorFALSE(drop)) stop("'drop' must be TRUE or FALSE") if (length(x) != length(f)) stop("Length of 'f' must equal the length of 'x'") ind <- splitAsList(seq_len(length(x)), f, drop = drop) if (length(ind) != length(value)) stop("Length of 'value' must equal the length of a split on 'f'") x[unlist(ind, use.names=FALSE)] <- unlist(value, use.names = FALSE) x } setMethod("unsplit", "List", function(value, f, drop = FALSE) { value_flat <- unlist(value, use.names = FALSE) if (length(value_flat) != length(f)) stop("Length of 'unlist(value)' must equal length of 'f'") splitAsList(value_flat, f, drop = drop) <- value value_flat }) setReplaceMethod("split", "Vector", function(x, f, drop = FALSE, ..., value) { splitAsList(x, f, drop = drop, ...) <- value x }) IRanges/R/setops-methods.R0000644000175100017510000002274612607265143016445 0ustar00biocbuildbiocbuild### ========================================================================= ### Set operations ### ------------------------------------------------------------------------- ### ### I. Vector-wise set operations: union, intersect, setdiff ### ### All the functions in that group are implemented to behave like ### endomorphisms with respect to their first argument 'x'. ### ### On IRanges objects, the functions in that group interpret each supplied ### object ('x' or 'y') as a set of integer values. Therefore, if 2 IRanges ### objects 'x1' and 'x2' represent the same set of integers, then each of ### these functions will return the same result when 'x1' is replaced by 'x2' ### in the input. The returned IRanges object is guaranteed to be normal ### (note that if 'x' is an IRanges *instance* then the returned object is ### still an IRanges *instance*, that is, it is *not* promoted to ### NormalIRanges). ### ### II. Element-wise (aka "parallel") set operations: punion, pintersect, ### psetdiff, pgap ### ### The functions in that group take 2 *objects* of the same length and ### return an object of the same class and length as the first argument. ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### union() ### setMethod("union", c("Ranges", "Ranges"), function(x, y, ...) { ## We need to downgrade 'x' to an IRanges instance 'x0' so 'c(x0, y)' ## is guaranteed to work (even e.g. if 'x' is a NormalIRanges object). x0 <- as(x, "IRanges") # downgrade x to IRanges x0 <- reduce(c(x0, y), drop.empty.ranges=TRUE) ## Maybe the call to update() below could be replaced by ## 'as(x, "IRanges") <- x0' but I was not lucky with my first ## attempt to use this construct: ## > v <- Views(XInteger(18), 2:5, 13:10) ## > as(v, "IRanges") <- IRanges(3, 8) ## Error: evaluation nested too deeply: infinite recursion / options(expressions=)? initialize(x, start=start(x0), width=width(x0), NAMES=names(x0), elementMetadata=NULL) } ) setMethod("union", c("RangesList", "RangesList"), function(x, y) mendoapply(union, x, y)) setMethod("union", c("CompressedIRangesList", "CompressedIRangesList"), function(x, y) { len <- max(length(x), length(y)) if (length(x) != len) x <- x[S4Vectors:::recycleVector(seq_len(length(x)), len)] if (length(y) != len) y <- y[S4Vectors:::recycleVector(seq_len(length(y)), len)] xy <- c(unlist(x, use.names = FALSE), unlist(y, use.names = FALSE)) xy_list <- split(xy, factor(c(togroup(x), togroup(y)), seq_len(length(x)))) names(xy_list) <- names(x) reduce(xy_list, drop.empty.ranges=TRUE) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### intersect() ### setMethod("intersect", c("Ranges", "Ranges"), function(x, y, ...) { if (length(x) == 0L) return(x) start <- min(c(start(x), start(y))) end <- max(c(end(x), end(y))) setdiff(x, gaps(y, start=start, end=end)) } ) setMethod("intersect", c("RangesList", "RangesList"), function(x, y) mendoapply(intersect, x, y)) setMethod("intersect", c("CompressedIRangesList", "CompressedIRangesList"), function(x, y) { nonempty <- elementLengths(x) != 0L rx <- unlist(range(x), use.names = FALSE) startx <- integer() startx[nonempty] <- start(rx) endx <- integer() endx[nonempty] <- end(rx) setdiff(x, gaps(y, start = startx, end = endx)) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### setdiff() ### setMethod("setdiff", c("Ranges", "Ranges"), function(x, y, ...) { if (length(x) == 0L) return(x) start <- min(c(start(x), start(y))) end <- max(c(end(x), end(y))) gaps(union(gaps(x, start=start, end=end), y), start=start, end=end) } ) setMethod("setdiff", c("RangesList", "RangesList"), function(x, y) mendoapply(setdiff, x, y)) setMethod("setdiff", c("CompressedIRangesList", "CompressedIRangesList"), function(x, y) { nonempty <- elementLengths(x) != 0L rx <- unlist(range(x), use.names = FALSE) startx <- integer() startx[nonempty] <- start(rx) endx <- integer() endx[nonempty] <- end(rx) gaps(union(gaps(x), y), start = startx, end = endx) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### punion() ### setGeneric("punion", signature=c("x", "y"), function(x, y, ...) standardGeneric("punion") ) setMethod("punion", c("Ranges", "Ranges"), function(x, y, fill.gap=FALSE, ...) { if (length(x) != length(y)) stop("'x' and 'y' must have the same length") if (!isTRUEorFALSE(fill.gap)) stop("'fill.gap' must be TRUE or FALSE") if (!fill.gap) { gap <- pmax.int(start(x), start(y)) - pmin.int(end(x), end(y)) - 1L if (any(gap > 0L)) stop("some pair of ranges have a gap within ", "the 2 members of the pair.\n", " Use 'fill.gap=TRUE' to enforce their ", "union by filling the gap.") } ans_start <- pmin.int(start(x), start(y)) ans_end <- pmax.int(end(x), end(y)) ans_names <- names(x) if (is.null(ans_names)) ans_names <- names(y) IRanges(start=ans_start, end=ans_end, names=ans_names) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### pintersect() ### setGeneric("pintersect", signature=c("x", "y"), function(x, y, ...) standardGeneric("pintersect") ) setMethod("pintersect", c("Ranges", "Ranges"), function(x, y, resolve.empty=c("none", "max.start", "start.x"), ...) { if (length(x) != length(y)) stop("'x' and 'y' must have the same length") ans_start <- pmax.int(start(x), start(y)) ans_end <- pmin.int(end(x), end(y)) ans_width <- ans_end - ans_start + 1L keep_empty_x <- width(x) == 0L if (any(keep_empty_x)) { keep_empty_x <- keep_empty_x & ((start(x) >= start(y) & start(x) <= end(y)) | (start(x) == start(y) & width(y) == 0L)) } if (any(keep_empty_x)) { ans_start[keep_empty_x] <- start(x)[keep_empty_x] ans_width[keep_empty_x] <- 0L } keep_empty_y <- width(y) == 0L if (any(keep_empty_y)) { keep_empty_y <- keep_empty_y & start(y) >= start(x) & start(y) <= end(x) } if (any(keep_empty_y)) { ans_start[keep_empty_y] <- start(y)[keep_empty_y] ans_width[keep_empty_y] <- 0L } check_empty <- ans_width < 0L check_empty[keep_empty_x | keep_empty_y] <- FALSE if (any(check_empty)) { resolve.empty <- match.arg(resolve.empty) if (resolve.empty == "none") { stop("some intersections produce ambiguous empty ranges.\n", " Use argument 'resolve.empty' to resolve them.") } else { ans_width[check_empty] <- 0L if (resolve.empty == "start.x") ans_start[check_empty] <- start(x)[check_empty] } } ans_names <- names(x) if (is.null(ans_names)) ans_names <- names(y) IRanges(start=ans_start, width=ans_width, names=ans_names) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### psetdiff() ### setGeneric("psetdiff", signature=c("x", "y"), function(x, y, ...) standardGeneric("psetdiff") ) setMethod("psetdiff", c("Ranges", "Ranges"), function(x, y, ...) { if (length(x) != length(y)) stop("'x' and 'y' must have the same length") ans_start <- start(x) ans_end <- end(x) if (any((start(y) > ans_start) & (end(y) < ans_end))) stop("some ranges in 'y' have their end points strictly inside\n", " the range in 'x' that they need to be subtracted from.\n", " Cannot subtract them.") start2 <- pmax.int(ans_start, start(y)) end2 <- pmin.int(ans_end, end(y)) ii <- start2 <= end2 jj <- end2 == ans_end kk <- ii & jj ans_end[kk] <- start2[kk] - 1L kk <- ii & (!jj) ans_start[kk] <- end2[kk] + 1L ans_names <- names(x) if (is.null(ans_names)) ans_names <- names(y) IRanges(start=ans_start, end=ans_end, names=ans_names) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### pgap() ### setGeneric("pgap", signature=c("x", "y"), function(x, y, ...) standardGeneric("pgap") ) setMethod("pgap", c("Ranges", "Ranges"), function(x, y, ...) { if (length(x) != length(y)) stop("'x' and 'y' must have the same length") ans_end_plus1 <- pmax.int(start(x), start(y)) ans_start <- pmin.int(end(x), end(y)) + 1L ans_width <- ans_end_plus1 - ans_start ans_width[ans_width < 0L] <- 0L ans_names <- names(x) if (is.null(ans_names)) ans_names <- names(y) IRanges(start=ans_start, width=ans_width, names=ans_names) } ) IRanges/R/slice-methods.R0000644000175100017510000000662412607265143016224 0ustar00biocbuildbiocbuild### ========================================================================= ### Slice the bread ### ------------------------------------------------------------------------- setGeneric("slice", signature="x", function(x, lower=-Inf, upper=Inf, ...) standardGeneric("slice")) setMethod("slice", "Rle", function(x, lower = -Inf, upper = Inf, includeLower = TRUE, includeUpper = TRUE, rangesOnly = FALSE) { if (!isSingleNumber(lower)) { stop("'lower' must be a single number") } if (!isSingleNumber(upper)) { stop("'upper' must be a single number") } if (!isTRUEorFALSE(includeLower)) { stop("'includeLower' must be TRUE or FALSE") } if (!isTRUEorFALSE(includeUpper)) { stop("'includeUpper' must be TRUE or FALSE") } if (!isTRUEorFALSE(rangesOnly)) { stop("'rangesOnly' must be TRUE or FALSE") } if (lower == -Inf) { ranges <- Rle(TRUE, length(x)) } else if (includeLower) { ranges <- (x >= lower) } else { ranges <- (x > lower) } if (upper < Inf) { if (includeUpper) { ranges <- ranges & (x <= upper) } else { ranges <- ranges & (x < upper) } } if (rangesOnly) { as(ranges, "IRanges") } else { Views(x, ranges) } }) setMethod("slice", "RleList", function(x, lower = -Inf, upper = Inf, includeLower = TRUE, includeUpper = TRUE, rangesOnly = FALSE) { if (!isSingleNumber(lower)) stop("'lower' must be a single number") if (!isSingleNumber(upper)) stop("'upper' must be a single number") if (!isTRUEorFALSE(includeLower)) stop("'includeLower' must be TRUE or FALSE") if (!isTRUEorFALSE(includeUpper)) stop("'includeUpper' must be TRUE or FALSE") if (!isTRUEorFALSE(rangesOnly)) stop("'rangesOnly' must be TRUE or FALSE") if (lower == -Inf) { ranges <- RleList(lapply(elementLengths(x), function(len) Rle(TRUE, len)), compress=FALSE) } else if (includeLower) { ranges <- (x >= lower) } else { ranges <- (x > lower) } if (upper < Inf) { if (includeUpper) { ranges <- ranges & (x <= upper) } else { ranges <- ranges & (x < upper) } } if (rangesOnly) { as(ranges, "CompressedIRangesList") } else { RleViewsList(rleList = x, rangesList = as(ranges, "SimpleIRangesList")) } }) setMethod("slice", "ANY", function(x, lower=-Inf, upper=Inf, ...) { slice(as(x, "Rle"), lower=lower, upper=upper, ...) }) IRanges/R/subsetting-internals.R0000644000175100017510000001031512607265143017640 0ustar00biocbuildbiocbuild### ========================================================================= ### Subsetting utility functions ### ------------------------------------------------------------------------- ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### RleNSBS objects. ### setClass("RleNSBS", # not exported contains="NSBS", representation( subscript="Rle" ) #prototype( # subscript=Rle(integer(0)) #) ) ### Construction methods. ### Supplied arguments are trusted so we don't check them! setMethod("NSBS", "Rle", function(i, x, exact=TRUE, upperBoundIsStrict=TRUE) { x_NROW <- NROW(x) i_vals <- runValue(i) if (is.logical(i_vals) && length(i_vals) != 0L) { if (S4Vectors:::anyMissing(i_vals)) stop("subscript contains NAs") if (length(i) < x_NROW) i <- rep(i, length.out=x_NROW) i <- as(i, "NormalIRanges") return(callGeneric()) } i_vals <- as.integer(NSBS(i_vals, x, exact=exact, upperBoundIsStrict=upperBoundIsStrict)) runValue(i) <- i_vals new("RleNSBS", subscript=i, upper_bound=x_NROW, upper_bound_is_strict=upperBoundIsStrict) } ) ### Other methods. setMethod("as.integer", "RleNSBS", function(x) S4Vectors:::decodeRle(x@subscript)) setMethod("length", "RleNSBS", function(x) length(x@subscript)) setMethod("anyDuplicated", "RleNSBS", function(x, incomparables=FALSE, ...) anyDuplicated(x@subscript) ) setMethod("isStrictlySorted", "RleNSBS", function(x) isStrictlySorted(x@subscript) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### RangesNSBS objects. ### setClass("RangesNSBS", # not exported contains="NSBS", representation( subscript="Ranges" ) #prototype( # subscript=IRanges() #) ) ### Construction methods. ### Supplied arguments are trusted so we don't check them! setMethod("NSBS", "Ranges", function(i, x, exact=TRUE, upperBoundIsStrict=TRUE) { i_len <- length(i) if (i_len == 0L) { i <- NULL return(callGeneric()) } x_NROW <- NROW(x) if (min(start(i)) < 1L || upperBoundIsStrict && max(end(i)) > x_NROW) stop("subscript contains out-of-bounds ranges") if (i_len == 1L) { ans <- new("WindowNSBS", subscript=c(start(i), end(i)), upper_bound=x_NROW, upper_bound_is_strict=upperBoundIsStrict) return(ans) } new("RangesNSBS", subscript=i, upper_bound=x_NROW, upper_bound_is_strict=upperBoundIsStrict) } ) ### Other methods. setMethod("as.integer", "RangesNSBS", function(x) as.integer(x@subscript)) setMethod("length", "RangesNSBS", function(x) sum(width(x@subscript))) setMethod("anyDuplicated", "RangesNSBS", function(x, incomparables=FALSE, ...) !isDisjoint(x@subscript) ) setMethod("isStrictlySorted", "RangesNSBS", function(x) isNormal(x@subscript)) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### "extractROWS" methods for vectorORfactor objects. ### setMethod("extractROWS", c("vectorORfactor", "Rle"), function(x, i) { i <- normalizeSingleBracketSubscript(i, x, as.NSBS=TRUE) callGeneric() } ) setMethod("extractROWS", c("vectorORfactor", "RangesNSBS"), function(x, i) { i <- i@subscript callGeneric() } ) setMethod("extractROWS", c("vectorORfactor", "Ranges"), function(x, i) { ## Which one is faster, vector_seqselect or vector_subsetByRanges? ans <- .Call2("vector_seqselect", x, start(i), width(i), PACKAGE="S4Vectors") #ans <- .Call2("vector_subsetByRanges", x, start(i), width(i), # PACKAGE="S4Vectors") if (is.factor(x)) attributes(ans) <- list(levels=levels(x), class="factor") ans } ) setMethod("extractROWS", c("matrix", "Ranges"), S4Vectors:::extractROWSWithBracket ) IRanges/R/test_IRanges_package.R0000644000175100017510000000007212607265143017515 0ustar00biocbuildbiocbuild.test <- function() BiocGenerics:::testPackage("IRanges") IRanges/R/tile-methods.R0000644000175100017510000000251712607265143016057 0ustar00biocbuildbiocbuild### ========================================================================= ### "tile" methods ### ------------------------------------------------------------------------- ### setGeneric("tile", function(x, n, width, ...) standardGeneric("tile"), signature="x") setMethod("tile", "Ranges", function(x, n, width, ...) { if (!missing(n)) { if (!missing(width)) stop("only one of 'n' and 'width' can be specified") if (any(IRanges::width(x) < n)) stop("some width(x) are less than 'n'") if (any(n < 0L)) stop("some 'n' are negative") n <- S4Vectors:::recycleVector(n, length(x)) } if (!missing(width)) { if (!missing(n)) stop("only one of 'n' and 'width' can be specified") if (any(width < 0L)) stop("some 'width' are negative") n <- ceiling(width(x) / width) } width <- IRanges::width(x) / n ## The floor() is intentional for compatibility with Jim Kent's BigWig code ## tileGenome() uses ceiling() instead tile.end <- floor(as.integer(IRanges(rep(1L, length(n)), width=n)) * rep(width, n)) tile.end.abs <- tile.end + rep(start(x), n) - 1L tile.width <- S4Vectors:::diffWithInitialZero(as.integer(tile.end.abs)) p <- PartitioningByWidth(n) tile.width[start(p)] <- tile.end[start(p)] relist(IRanges(width=tile.width, end=tile.end.abs), p) }) IRanges/R/updateObject-methods.R0000644000175100017510000003242512607265143017534 0ustar00biocbuildbiocbuild## Functions for updating old TypedList to new infrastructure toSimpleList <- function(object, newclass, newtype, ...) { annotation <- tryCatch(slot(object, "annotation"), error = function(e) list()) if (!is.list(annotation)) { if (is.null(annotation)) annotation <- list() else annotation <- list(annotation) } new(newclass, listData = lapply(structure(slot(object, "elements"), names = slot(object, "NAMES")), updateObject), elementMetadata = updateObject(tryCatch(slot(object, "elementMetadata"), error = function(e) NULL)), elementType = newtype, metadata = annotation, ...) } toCompressedList <- function(object, newclass, newtype, ...) { annotation <- tryCatch(slot(object, "annotation"), error = function(e) list()) if (!is.list(annotation)) { if (is.null(annotation)) annotation <- list() else annotation <- list(annotation) } new(newclass, partitioning = new("PartitioningByEnd", end = cumsum(slot(object, "elementLengths")), NAMES = slot(object, "NAMES")), unlistData = updateObject(slot(object, "elements")[[1L]]), elementMetadata = updateObject(tryCatch(slot(object, "elementMetadata"), error = function(e) NULL)), elementType = newtype, metadata = annotation, ...) } toNewTypeList <- function(object, simpleclass, compressedclass, newtype) { if (slot(object, "compress")) toCompressedList(object, compressedclass, newtype) else toSimpleList(object, simpleclass, newtype) } ### ################################################################### ### Update methods ### ################################################################### ## "LogicalList" -> "SimpleLogicalList" or "CompressedLogicalList" setMethod("updateObject", signature(object="LogicalList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'LogicalList')") if (!("metadata" %in% names(attributes(object)))) { object <- toNewTypeList(asS4(object), "SimpleLogicalList", "CompressedLogicalList", "logical") } object }) ## "IntegerList" -> "SimpleIntegerList" or "CompressedIntegerList" setMethod("updateObject", signature(object="IntegerList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'IntegerList')") if (!("metadata" %in% names(attributes(object)))) { object <- toNewTypeList(asS4(object), "SimpleIntegerList", "CompressedIntegerList", "integer") } object }) ## "NumericList" -> "SimpleNumericList" or "CompressedNumericList" setMethod("updateObject", signature(object="NumericList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'NumericList')") if (!("metadata" %in% names(attributes(object)))) { object <- toNewTypeList(asS4(object), "SimpleNumericList", "CompressedNumericList", "numeric") } object }) ## "ComplexList" -> "SimpleComplexList" or "CompressedComplexList" setMethod("updateObject", signature(object="ComplexList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'ComplexList')") if (!("metadata" %in% names(attributes(object)))) { object <- toNewTypeList(asS4(object), "SimpleComplexList", "CompressedComplexList", "complex") } object }) ## "CharacterList" -> "SimpleCharacterList" or "CompressedCharacterList" setMethod("updateObject", signature(object="CharacterList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'CharacterList')") if (!("metadata" %in% names(attributes(object)))) { object <- toNewTypeList(asS4(object), "SimpleCharacterList", "CompressedCharacterList", "character") } object }) ## "RawList" -> "SimpleRawList" or "CompressedRawList" setMethod("updateObject", signature(object="RawList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'RawList')") if (!("metadata" %in% names(attributes(object)))) { object <- toNewTypeList(asS4(object), "SimpleRawList", "CompressedRawList", "raw") } object }) ## "RleList" -> "SimpleRleList" or "CompressedRleList" setMethod("updateObject", signature(object="RleList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'RleList')") if (!("metadata" %in% names(attributes(object)))) { object <- toNewTypeList(asS4(object), "SimpleRleList", "CompressedRleList", "Rle") } object }) ## "IRanges" -> "IRanges" setMethod("updateObject", signature(object="IRanges"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'IRanges')") if (!("metadata" %in% names(attributes(object)))) { object <- new("IRanges", start = slot(object, "start"), width = slot(object, "width"), NAMES = slot(object, "NAMES")) } object }) ## "NormalIRanges" -> "NormalIRanges" setMethod("updateObject", signature(object="NormalIRanges"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'NormalIRanges')") if (!("metadata" %in% names(attributes(object)))) { object <- new("NormalIRanges", start = slot(object, "start"), width = slot(object, "width"), NAMES = slot(object, "NAMES")) } object }) ## "IntervalTree" -> "IntervalTree" setMethod("updateObject", signature(object="IntervalTree"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'IntervalTree')") if (!("metadata" %in% names(attributes(object)))) { object <- new("IntervalTree", ptr = slot(object, "ptr"), mode = slot(object, "mode")) } object }) ## "MaskCollection" -> "MaskCollection" setMethod("updateObject", signature(object="MaskCollection"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'MaskCollection')") if (!("metadata" %in% names(attributes(object)))) { object <- new("MaskCollection", nir_list = lapply(slot(object, "nir_list"), updateObject), width = slot(object, "width"), active = slot(object, "active"), NAMES = slot(object, "NAMES"), desc = slot(object, "desc")) } object }) ## "RDApplyParams" -> "RDApplyParams" setMethod("updateObject", signature(object="RDApplyParams"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'RDApplyParams')") if (!("metadata" %in% names(attributes(object)))) { object <- new("RDApplyParams", rangedData = updateObject(slot(object, "rangedData")), applyFun = slot(object, "applyFun"), applyParams = slot(object, "applyParams"), filterRules = updateObject(slot(object, "filterRules")), simplify = slot(object, "simplify"), reducerFun = slot(object, "reducerFun"), reducerParams = slot(object, "reducerParams")) } object }) ## "RangedData" -> "RangedData" setMethod("updateObject", signature(object="RangedData"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'RangedData')") if (!("metadata" %in% names(attributes(object)))) { ranges <- updateObject(slot(object, "ranges")) values <- updateObject(slot(object, "values")) if (is.null(names(ranges))) { names(ranges) <- as.character(seq_len(length(ranges))) } if (is.null(names(values))) { names(values) <- as.character(seq_len(length(values))) } object <- new("RangedData", ranges = ranges, values = values) } object }) ## "RangedDataList" -> "RangedDataList" setMethod("updateObject", signature(object="RangedDataList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'RangedDataList')") if (!("metadata" %in% names(attributes(object)))) { object <- toSimpleList(asS4(object), "RangedDataList", "RangedData") } object }) ## "RangesList" -> "SimpleRangesList" setMethod("updateObject", signature(object="RangesList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'RangesListList')") if (!("metadata" %in% names(attributes(object)))) { object <- toSimpleList(asS4(object), "SimpleRangesList", "Ranges") } object }) ## "IRangesList" -> "SimpleIRangesList" or "CompressedIRangesList" setMethod("updateObject", signature(object="IRangesList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'IRangesList')") if (!("metadata" %in% names(attributes(object)))) { object <- toNewTypeList(asS4(object), "SimpleIRangesList", "CompressedIRangesList", "IRanges") } object }) ## "Rle" -> "Rle" setMethod("updateObject", signature(object="Rle"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'Rle')") if (!("metadata" %in% names(attributes(object)))) { object <- new("Rle", values = slot(object, "values"), lengths = slot(object, "lengths")) } object }) ## "RleViews" -> "RleViews" setMethod("updateObject", signature(object="RleViews"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'RleViews')") if (!("metadata" %in% names(attributes(object)))) { object <- new("RleViews", subject = updateObject(slot(object, "subject")), start = slot(object, "start"), width = slot(object, "width"), NAMES = slot(object, "NAMES")) } object }) ## "XDataFrame" -> "DataFrame" setClass("XDataFrame", representation("VIRTUAL")) setMethod("updateObject", signature(object="XDataFrame"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'XDataFrame')") toSimpleList(asS4(object), "DataFrame", "ANY", rownames = slot(object, "rownames"), nrows = slot(object, "nrows")) }) ## "XDataFrameList" -> "SimpleDataFrameList" setClass("XDataFrameList", representation("VIRTUAL")) setMethod("updateObject", signature(object="XDataFrameList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'XDataFrameList')") toSimpleList(asS4(object), "SimpleDataFrameList", "DataFrame") }) ## "SplitXDataFrameList" -> "SimpleSplitDataFrameList" or "CompressedSplitDataFrameList" setClass("SplitXDataFrameList", representation("VIRTUAL")) setMethod("updateObject", signature(object="SplitXDataFrameList"), function(object, ..., verbose=FALSE) { if (verbose) message("updateObject(object = 'SplitXDataFrameList')") toNewTypeList(asS4(object), "SimpleSplitDataFrameList", "CompressedSplitDataFrameList", "DataFrame") }) IRanges/R/zzz.R0000644000175100017510000000262112607265143014312 0ustar00biocbuildbiocbuild### .onLoad <- function(libname, pkgname) { ## -- HACK! -- ## Not loading the methods package can cause some strange 'R CMD check' ## WARNINGs. For example, on a BSgenome data package (with R 2.14.0): ## ## * checking whether the namespace can be loaded with stated dependencies ... WARNING ## Error: .onLoad failed in loadNamespace() for ‘BSgenome.Celegans.UCSC.ce2’, details: ## call: length(x) ## error: could not find function "loadMethod" ## Execution halted ## ## A namespace must be able to be loaded with just the base namespace ## loaded: otherwise if the namespace gets loaded by a saved object, the ## session will be unable to start. ## ## Probably some imports need to be declared in the NAMESPACE file. ## ## However, loading the methods package with library(methods) produces the ## following 'R CMD check' NOTE (with R 2.14.0): ## ## * checking R code for possible problems ... NOTE ## File ‘IRanges/R/zzz.R’: ## .onLoad calls: ## library(methods) ## ## Package startup functions should not change the search path. ## See section ‘Good practice’ in ?.onAttach. ## ## So we cheat on codetools to avoid this NOTE. sillyname <- library sillyname(methods) } .onUnload <- function(libpath) { library.dynam.unload("IRanges", libpath) } IRanges/TODO0000644000175100017510000001212512607265143013621 0ustar00biocbuildbiocbuildImmediate TODO list ------------------- - Bug fix: Combining RangedData objects is currently broken (IRanges 1.9.20): library(IRanges) ranges <- IRanges(c(1,2,3),c(4,5,6)) rd1 <- RangedData(ranges) rd2 <- RangedData(shift(ranges, 100)) rd <- c(rd1, rd2) # Seems to work (with some warnings)... validObject(rd) # but returns an invalid object! - Herve: Make the MaskCollection class a derivative of the SimpleIRangesList class. - Herve: Use a different name for "reverse" method for IRanges and MaskCollection objects. Seems like, for IRanges objects, reverse() and reflect() are doing the same thing, so I should just keep (and eventually adapt) the latter. Also, I should add a "reflect" method for SimpleIRangesList objects that would do what the current "reverse" method for MaskCollection objects does. Once this is done, adapt R/reverse.R file in Biostrings to use reflect() instead of reverse() wherever needed. - Clean up endomorphisms. Long term TODO list ------------------- o RangesList: - parallel rbind - binary ops: "nearest", "intersect", "setdiff", "union" - 'y' omitted: become n-ary ops on items in collection - 'y' specified: performed element-wise - unary ops: "coverage" etc are vectorized o DataTable: - group generics (Math, Ops, Summary) o SplitDataFrameList: - rbind o IO: - xscan() - read data directly into XVector objects ------------------------------------- Conceptual framework (by Michael) ------------------------------------- Basic problem: We have lots of (long) data series and need a way to efficiently represent and manipulate them. A series is a vector, except that the positions of the elements are meaningful. That is, we often expect strong auto-correlation. We have an abstraction called "Vector" for representing these series. There are currently two optimized means of storing long series: 1) Externally, currently only in memory, in XVector derivatives. The main benefit here is avoiding unnecessary copying, though there is potential for vectors stored in databases and flat files on disk (but this is outside our use case). 2) Run-length encoding (Rle class). This is a classic means of compressing discrete-valued series. It is very efficient, as long as there are long runs of equal value. Rle, so far, is far ahead of XVector in terms of direct usefulness. If XVector were implemented with an environment, rather than an external pointer, adding functionality would be easier. Could carry some things over from externalVector. As the sequence of observations in a series is important, we often want to manipulate specific regions of the series. We can use the window() function to select a particular region from a Vector, and a logical Rle can represent a selection of multiple regions. A slightly more general representation, that supports overlapping regions, is the Ranges class. A Ranges object holds any number of start,width pairs that describe closed intervals representing the set of integers that fall within the endpoints. The primary implementation is IRanges, which stores the information as two integer vectors. Often the endpoints of the intervals are interesting independent of the underlying sequence. Many utilities are implemented for manipulating and analyzing Ranges. These include: 1) overlap detection 2) nearest neighbors: precede, follow, nearest 3) set operations: (p)union, (p)intersect, (p)setdiff, gaps 4) coverage, too bio specific? rename to 'table'? 5) resolving overlap: reduce and (soon) collapse 6) transformations: flank, reflect, restrict, narrow... 7) (soon) mapping/alignment There are two ways to explicitly pair a Ranges object with a Vector: 1) Masking, as in MaskedXString, where only the elements outside of the Ranges are considered by an operation. 2) Views, which are essentially lists of subsequences. This relies in the fly-weight pattern for efficiency. Several fast paths, like viewSums and viewMaxs, are implemented. There is an RleViews and an XIntegerViews (is this one currently used at all?). Views are limited to subsequences derived from a single sequence. For more general lists of sequences, we have a separate framework, based on the List class. The List optionally ensures that all of its elements are derived from a specified type, and it also aims to efficiently represent a major use case of lists: splitting a vector by a factor. The indices of the elements with each factor level are stored, but there is no physical split of the vector into separate list elements. A special case that often occurs in data analysis is a list containing a set of variables in the same dataset. This problem is solved by 'data.frame' in base R, and we have an equivalent DataFrame class that can hold any type of R object, as long as it has a vector semantic. Many of the important data structures have List analogs. These include all atomic types, as well as: * SplitDataFrameList: a list of DataFrames that have the same columns (usually the result of a split) * RangesList: Essentially just a list of Ranges objects, but often used for splitting Ranges by their "space" (e.g. chromosome) IRanges/build/0000755000175100017510000000000012612026576014230 5ustar00biocbuildbiocbuildIRanges/build/vignette.rds0000644000175100017510000000034112612026576016565 0ustar00biocbuildbiocbuild‹‹àb```b`fbb`b2™… 1# 'ö JÌKO-ö/K-*ËL-× Ê+GS"嘧à™WR”ŸRš\’™Ÿ§P’¯ÕEȰ‚”44%‚öÝ( VQ,LHXós1,bwI-HÍK ÿCÓSÂs!È4Æÿh²Þ©•åùE0PÔ°AÕ°¸eæ¤Â\’Yç0¸¸A™ŒAè.Â0Å7œEùåz0ñ‚â§Hüto'ç$£{›+%±$Q/­¨änË{õ7áIRanges/inst/0000755000175100017510000000000012612026576014106 5ustar00biocbuildbiocbuildIRanges/inst/CITATION0000644000175100017510000000165412607265143015250 0ustar00biocbuildbiocbuildcitEntry(entry="article", title = "Software for Computing and Annotating Genomic Ranges", author = personList( as.person("Michael Lawrence" ), as.person("Wolfgang Huber" ), as.person("Herv\\'e Pag\\`es" ), as.person("Patrick Aboyoun" ), as.person("Marc Carlson" ), as.person("Robert Gentleman" ), as.person("Martin Morgan" ), as.person("Vincent Carey" )), year = 2013, journal = "{PLoS} Computational Biology", volume = "9", issue = "8", doi = "10.1371/journal.pcbi.1003118", url = "http://www.ploscompbiol.org/article/info%3Adoi%2F10.1371%2Fjournal.pcbi.1003118", textVersion = "Lawrence M, Huber W, Pag\\`es H, Aboyoun P, Carlson M, et al. (2013) Software for Computing and Annotating Genomic Ranges. PLoS Comput Biol 9(8): e1003118. doi:10.1371/journal.pcbi.1003118" ) IRanges/inst/doc/0000755000175100017510000000000012612026576014653 5ustar00biocbuildbiocbuildIRanges/inst/doc/IRangesOverview.R0000644000175100017510000003506012612026576020061 0ustar00biocbuildbiocbuild### R code from vignette source 'IRangesOverview.Rnw' ################################################### ### code chunk number 1: options ################################################### options(width=72) ################################################### ### code chunk number 2: biocLite (eval = FALSE) ################################################### ## source("http://bioconductor.org/biocLite.R") ## biocLite("IRanges") ################################################### ### code chunk number 3: initialize ################################################### library(IRanges) ################################################### ### code chunk number 4: initialize ################################################### set.seed(0) lambda <- c(rep(0.001, 4500), seq(0.001, 10, length = 500), seq(10, 0.001, length = 500)) xVector <- Rle(rpois(1e7, lambda)) yVector <- Rle(rpois(1e7, lambda[c(251:length(lambda), 1:250)])) ################################################### ### code chunk number 5: basic-ops ################################################### length(xVector) xVector[1] zVector <- c(xVector, yVector) ################################################### ### code chunk number 6: seq-extraction ################################################### xSnippet <- xVector[IRanges(4751, 4760)] xSnippet head(xSnippet) tail(xSnippet) rev(xSnippet) rep(xSnippet, 2) subset(xSnippet, xSnippet >= 5L) ################################################### ### code chunk number 7: seq-combine ################################################### c(xSnippet, rev(xSnippet)) append(xSnippet, xSnippet, after = 3) ################################################### ### code chunk number 8: aggregate ################################################### xSnippet aggregate(xSnippet, start = 1:8, width = 3, FUN = median) ################################################### ### code chunk number 9: shiftApply-cor ################################################### cor(xVector, yVector) shifts <- seq(235, 265, by=3) corrs <- shiftApply(shifts, yVector, xVector, FUN = cor) ################################################### ### code chunk number 10: figshiftcorrs ################################################### plot(shifts, corrs) ################################################### ### code chunk number 11: Rle-construction ################################################### xRle <- Rle(xVector) yRle <- Rle(yVector) xRle yRle ################################################### ### code chunk number 12: Rle-vector-compare ################################################### as.vector(object.size(xRle) / object.size(xVector)) identical(as.vector(xRle), xVector) ################################################### ### code chunk number 13: Rle-accessors ################################################### head(runValue(xRle)) head(runLength(xRle)) ################################################### ### code chunk number 14: Rle-ops ################################################### xRle > 0 xRle + yRle xRle > 0 | yRle > 0 ################################################### ### code chunk number 15: Rle-summary ################################################### range(xRle) sum(xRle > 0 | yRle > 0) ################################################### ### code chunk number 16: Rle-math ################################################### log1p(xRle) ################################################### ### code chunk number 17: Rle-cor ################################################### cor(xRle, yRle) shiftApply(249:251, yRle, xRle, FUN = function(x, y) var(x, y) / (sd(x) * sd(y))) ################################################### ### code chunk number 18: list-intro ################################################### getClassDef("RleList") ################################################### ### code chunk number 19: list-construct ################################################### args(IntegerList) cIntList1 <- IntegerList(x = xVector, y = yVector) cIntList1 sIntList2 <- IntegerList(x = xVector, y = yVector, compress = FALSE) sIntList2 ## sparse integer list xExploded <- lapply(xVector[1:5000], function(x) seq_len(x)) cIntList2 <- IntegerList(xExploded) sIntList2 <- IntegerList(xExploded, compress = FALSE) object.size(cIntList2) object.size(sIntList2) ################################################### ### code chunk number 20: list-length ################################################### length(cIntList2) Rle(elementLengths(cIntList2)) ################################################### ### code chunk number 21: list-lapply ################################################### system.time(sapply(xExploded, mean)) system.time(sapply(sIntList2, mean)) system.time(sapply(cIntList2, mean)) identical(sapply(xExploded, mean), sapply(sIntList2, mean)) identical(sapply(xExploded, mean), sapply(cIntList2, mean)) ################################################### ### code chunk number 22: list-groupgenerics ################################################### xRleList <- RleList(xRle, 2L * rev(xRle)) yRleList <- RleList(yRle, 2L * rev(yRle)) xRleList > 0 xRleList + yRleList sum(xRleList > 0 | yRleList > 0) ################################################### ### code chunk number 23: list-endoapply ################################################### safe.max <- function(x) { if(length(x)) max(x) else integer(0) } endoapply(sIntList2, safe.max) endoapply(cIntList2, safe.max) endoapply(sIntList2, safe.max)[[1]] ################################################### ### code chunk number 24: iranges-constructor ################################################### ir1 <- IRanges(start = 1:10, width = 10:1) ir2 <- IRanges(start = 1:10, end = 11) ir3 <- IRanges(end = 11, width = 10:1) identical(ir1, ir2) & identical(ir2, ir3) ir <- IRanges(c(1, 8, 14, 15, 19, 34, 40), width = c(12, 6, 6, 15, 6, 2, 7)) ################################################### ### code chunk number 25: iranges-start ################################################### start(ir) ################################################### ### code chunk number 26: iranges-end ################################################### end(ir) ################################################### ### code chunk number 27: iranges-width ################################################### width(ir) ################################################### ### code chunk number 28: iranges-subset-numeric ################################################### ir[1:4] ################################################### ### code chunk number 29: iranges-subset-logical ################################################### ir[start(ir) <= 15] ################################################### ### code chunk number 30: ranges-extraction ################################################### ir[[1]] ################################################### ### code chunk number 31: plotRanges ################################################### plotRanges <- function(x, xlim = x, main = deparse(substitute(x)), col = "black", sep = 0.5, ...) { height <- 1 if (is(xlim, "Ranges")) xlim <- c(min(start(xlim)), max(end(xlim))) bins <- disjointBins(IRanges(start(x), end(x) + 1)) plot.new() plot.window(xlim, c(0, max(bins)*(height + sep))) ybottom <- bins * (sep + height) - height rect(start(x)-0.5, ybottom, end(x)+0.5, ybottom + height, col = col, ...) title(main) axis(1) } ################################################### ### code chunk number 32: ir-plotRanges ################################################### plotRanges(ir) ################################################### ### code chunk number 33: ranges-reduce ################################################### reduce(ir) plotRanges(reduce(ir)) ################################################### ### code chunk number 34: rangeslist-contructor ################################################### rl <- RangesList(ir, rev(ir)) ################################################### ### code chunk number 35: rangeslist-start ################################################### start(rl) ################################################### ### code chunk number 36: bracket-ranges ################################################### irextract <- IRanges(start = c(4501, 4901) , width = 100) xRle[irextract] ################################################### ### code chunk number 37: overlap-ranges ################################################### ol <- findOverlaps(ir, reduce(ir)) as.matrix(ol) ################################################### ### code chunk number 38: ranges-coverage ################################################### cov <- coverage(ir) plotRanges(ir) cov <- as.vector(cov) mat <- cbind(seq_along(cov)-0.5, cov) d <- diff(cov) != 0 mat <- rbind(cbind(mat[d,1]+1, mat[d,2]), mat) mat <- mat[order(mat[,1]),] lines(mat, col="red", lwd=4) axis(2) ################################################### ### code chunk number 39: ranges-shift ################################################### shift(ir, 10) ################################################### ### code chunk number 40: ranges-narrow ################################################### narrow(ir, start=1:5, width=2) ################################################### ### code chunk number 41: ranges-restrict ################################################### restrict(ir, start=2, end=3) ################################################### ### code chunk number 42: ranges-threebands ################################################### threebands(ir, start=1:5, width=2) ################################################### ### code chunk number 43: ranges-plus ################################################### ir + seq_len(length(ir)) ################################################### ### code chunk number 44: ranges-asterisk ################################################### ir * -2 # double the width ################################################### ### code chunk number 45: ranges-disjoin ################################################### disjoin(ir) plotRanges(disjoin(ir)) ################################################### ### code chunk number 46: ranges-disjointBins ################################################### disjointBins(ir) ################################################### ### code chunk number 47: ranges-reflect ################################################### reflect(ir, IRanges(start(ir), width=width(ir)*2)) ################################################### ### code chunk number 48: ranges-flank ################################################### flank(ir, width = seq_len(length(ir))) ################################################### ### code chunk number 49: ranges-gaps ################################################### gaps(ir, start=1, end=50) plotRanges(gaps(ir, start=1, end=50), c(1,50)) ################################################### ### code chunk number 50: ranges-pgap ################################################### ################################################### ### code chunk number 51: ranges-union ################################################### ################################################### ### code chunk number 52: ranges-punion ################################################### ################################################### ### code chunk number 53: ranges-intersect ################################################### ################################################### ### code chunk number 54: ranges-pintersect ################################################### ################################################### ### code chunk number 55: ranges-setdiff ################################################### ################################################### ### code chunk number 56: ranges-psetdiff ################################################### ################################################### ### code chunk number 57: Views-constructors ################################################### xViews <- Views(xRle, xRle >= 1) xViews <- slice(xRle, 1) xViewsList <- slice(xRleList, 1) ################################################### ### code chunk number 58: views-looping ################################################### head(viewSums(xViews)) viewSums(xViewsList) head(viewMaxs(xViews)) viewMaxs(xViewsList) ################################################### ### code chunk number 59: RangedData-construct ################################################### values <- rnorm(length(ir)) rd <- RangedData(ir, name = letters[seq_len(length(ir))], values) rd ################################################### ### code chunk number 60: RangedData-construct-space ################################################### rd <- RangedData(ir, name = letters[seq_len(length(ir))], values, space = rep(c("chr1", "chr2"), c(3, length(ir) - 3))) rd ################################################### ### code chunk number 61: RangedData-ranges ################################################### ranges(rd) ################################################### ### code chunk number 62: RangedData-values ################################################### values(rd) ################################################### ### code chunk number 63: RangedData-subspace ################################################### rd["chr1"] ################################################### ### code chunk number 64: RangedData-subspace-2 ################################################### all(identical(rd["chr1"], rd[1]), identical(rd[1], rd[c(TRUE, FALSE)])) ################################################### ### code chunk number 65: RangedData-names ################################################### names(rd) ################################################### ### code chunk number 66: RangedData-length ################################################### length(rd) ################################################### ### code chunk number 67: RangedData-lapply ################################################### lapply(rd, names) ################################################### ### code chunk number 68: RangedData-extract ################################################### rd[[2]] ################################################### ### code chunk number 69: RangedData-dollar ################################################### rd$values ################################################### ### code chunk number 70: RangedData-subset-2d ################################################### rd[1:3, "name"] ################################################### ### code chunk number 71: sessionInfo ################################################### toLatex(sessionInfo()) IRanges/inst/doc/IRangesOverview.Rnw0000644000175100017510000010363712612026576020434 0ustar00biocbuildbiocbuild%\VignetteIndexEntry{An Introduction to IRanges} %\VignetteDepends{} %\VignetteKeywords{Ranges} %\VignettePackage{IRanges} \documentclass[10pt]{article} \usepackage{times} \usepackage{hyperref} \textwidth=6.5in \textheight=8.5in %\parskip=.3cm \oddsidemargin=-.1in \evensidemargin=-.1in \headheight=-.3in \newcommand{\Rfunction}[1]{{\texttt{#1}}} \newcommand{\Robject}[1]{{\texttt{#1}}} \newcommand{\Rpackage}[1]{{\textit{#1}}} \newcommand{\Rmethod}[1]{{\texttt{#1}}} \newcommand{\Rfunarg}[1]{{\texttt{#1}}} \newcommand{\Rclass}[1]{{\textit{#1}}} \newcommand{\Rcode}[1]{{\texttt{#1}}} \newcommand{\software}[1]{\textsf{#1}} \newcommand{\R}{\software{R}} \newcommand{\IRanges}{\Rpackage{IRanges}} \title{An Introduction to \IRanges{}} \author{Patrick Aboyoun, Michael Lawrence, Herv\'e Pag\`es} \date{\today} \begin{document} \maketitle <>= options(width=72) @ \section{Introduction} The \IRanges{} package is designed to represent sequences, ranges representing indices along those sequences, and data related to those ranges. In this vignette, we will rely on simple, illustrative example datasets, rather than large, real-world data, so that each data structure and algorithm can be explained in an intuitive, graphical manner. We expect that packages that apply \IRanges{} to a particular problem domain will provide vignettes with relevant, realistic examples. The \IRanges{} package is available at bioconductor.org and can be downloaded via \Rfunction{biocLite}: <>= source("http://bioconductor.org/biocLite.R") biocLite("IRanges") @ <>= library(IRanges) @ \section{Vector objects} In the context of the \IRanges{} package, a sequence is an ordered finite collection of elements. The \IRanges{} packages represents two types of objects as sequences: (1) atomic sequences and (2) lists (or non-atomic sequences). The following subsections describe each in turn. All \IRanges{}-derived sequences inherit from the \Rclass{Vector} virtual class. \subsection{Atomic Vectors} In \R{}, atomic sequences are typically stored in atomic vectors. The \IRanges{} package includes an additional atomic sequence object type, \Rclass{Rle}, which compresses an atomic sequence through run-length encoding. We begin our discussion of atomic sequences using two \Rclass{Rle} vectors. <>= set.seed(0) lambda <- c(rep(0.001, 4500), seq(0.001, 10, length = 500), seq(10, 0.001, length = 500)) xVector <- Rle(rpois(1e7, lambda)) yVector <- Rle(rpois(1e7, lambda[c(251:length(lambda), 1:250)])) @ All atomic sequences in \R{} have three main properties: (1) a notion of length or number of elements, (2) the ability to extract elements to create new atomic sequences, and (3) the ability to be combined with one or more atomic sequences to form larger atomic sequences. The main functions for these three operations are \Rfunction{length}, \Rfunction{[}, and \Rfunction{c}. <>= length(xVector) xVector[1] zVector <- c(xVector, yVector) @ While these three methods may seem trivial, they provide a great deal of power and many atomic sequence manipulations can be constructed using them. \subsubsection{Vector Subsetting} As with ordinary \R{} atomic vectors, it is often necessary to subset one sequence from another. When this subsetting does not duplicate or reorder the elements being extracted, the result is called a \textit{subsequence}. In general, the \Rfunction{[} function can be used to construct a new sequence or extract a subsequence, but its interface is often inconvenient and not amenable to optimization. To compensate for this, the \IRanges{} package supports seven additional functions for sequence extraction: \begin{enumerate} \item \Rfunction{window} - Extracts a subsequence over a specified region. \item \Rfunction{subset} - Extracts the subsequence specified by a logical vector. \item \Rfunction{head} - Extracts a consecutive subsequence containing the first n elements. \item \Rfunction{tail} - Extracts a consecutive subsequence containing the last n elements. \item \Rfunction{rev} - Creates a new sequence with the elements in the reverse order. \item \Rfunction{rep} - Creates a new sequence by repeating sequence elements. \end{enumerate} The following code illustrates how these functions are used on an ordinary \R{} \Rclass{integer} vector: <>= xSnippet <- xVector[IRanges(4751, 4760)] xSnippet head(xSnippet) tail(xSnippet) rev(xSnippet) rep(xSnippet, 2) subset(xSnippet, xSnippet >= 5L) @ \subsubsection{Combining Vectors} The \IRanges{} package uses two generic functions, \Rfunction{c} and \Rfunction{append}, for combining two \Rclass{Vector} objects. The methods for \Rclass{Vector} objects follow the definition that these two functions are given the the \Rpackage{base} package. <>= c(xSnippet, rev(xSnippet)) append(xSnippet, xSnippet, after = 3) @ \subsubsection{Looping over Vectors and Vector subsets} In \R{}, \Rfunction{for} looping can be an expensive operation. To compensate for this, \IRanges{} uses three generics, \Rfunction{endoapply}, \Rfunction{lapply}, and \Rfunction{sapply}, for looping over sequences and two generics, \Rfunction{aggregate} and \Rfunction{shiftApply}, to perform calculations over subsequences. The \Rfunction{lapply} and \Rfunction{sapply} functions are familiar to many \R{} users since they are the standard functions for looping over the elements of an \R{} \Rclass{list} object. The \Rfunction{endoapply} function performs an endomorphism equivalent to \Rfunction{lapply}, i.e. returns a \Rclass{Vector} object of the same class as the input rather than a \Rclass{list} object. More will be given on these three functions in the Lists subsection. The \Rfunction{aggregate} function combines sequence extraction functionality of the \Rfunction{window} function with looping capabilities of the \Rfunction{sapply} function. For example, here is some code to compute medians across a moving window of width 3 using the function \Rfunction{aggregate}: <>= xSnippet aggregate(xSnippet, start = 1:8, width = 3, FUN = median) @ The \Rfunction{shiftApply} function is a looping operation involving two sequences whose elements are lined up via a positional shift operation. For example, the elements of \Robject{xVector} and \Robject{yVector} were simulated from Poisson distributions with the mean of element i from \Robject{yVector} being equivalent to the mean of element i + 250 from \Robject{xVector}. If we did not know the size of the shift, we could estimate it by finding the shift that maximizes the correlation between \Robject{xVector} and \Robject{yVector}. <>= cor(xVector, yVector) shifts <- seq(235, 265, by=3) corrs <- shiftApply(shifts, yVector, xVector, FUN = cor) @ % <>= plot(shifts, corrs) @ The result is shown in Fig.~\ref{figshiftcorrs}. \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-figshiftcorrs} \caption{\label{figshiftcorrs}% Correlation between \Robject{xVector} and \Robject{yVector} for various shifts.} \end{center} \end{figure} \subsubsection{Run Length Encoding} Up until this point we have used \R{} atomic vectors to represent atomic sequences, but there are times when these object become too large to manage in memory. When there are lots of consecutive repeats in the sequence, the data can be compressed and managed in memory through a run-length encoding where a data value is paired with a run length. For example, the sequence \{1, 1, 1, 2, 3, 3\} can be represented as values = \{1, 2, 3\}, run lengths = \{3, 1, 2\}. The \Rclass{Rle} class in \IRanges{} is used to represent a run-length encoded (compressed) sequence of \Rclass{logical}, \Rclass{integer}, \Rclass{numeric}, \Rclass{complex}, \Rclass{character}, or \Rclass{raw} values. One way to construct an \Rclass{Rle} object is through the \Rclass{Rle} constructor function: <>= xRle <- Rle(xVector) yRle <- Rle(yVector) xRle yRle @ When there are lots of consecutive repeats, the memory savings through an RLE can be quite dramatic. For example, the \Robject{xRle} object occupies less than one quarter of the space of the original \Robject{xVector} object, while storing the same information: <>= as.vector(object.size(xRle) / object.size(xVector)) identical(as.vector(xRle), xVector) @ The functions \Rfunction{runValue} and \Rfunction{runLength} extract the run values and run lengths from an \Rclass{Rle} object respectively: <>= head(runValue(xRle)) head(runLength(xRle)) @ The \Rclass{Rle} class supports many of the basic methods associated with \R{} atomic vectors including the Ops, Math, Math2, Summary, and Complex group generics. Here is a example of manipulating \Rclass{Rle} objects using methods from the Ops group: <>= xRle > 0 xRle + yRle xRle > 0 | yRle > 0 @ Here are some from the Summary group: <>= range(xRle) sum(xRle > 0 | yRle > 0) @ And here is one from the Math group: <>= log1p(xRle) @ As with the atomic vectors, the \Rfunction{cor} and \Rfunction{shiftApply} functions operate on \Rclass{Rle} objects: <>= cor(xRle, yRle) shiftApply(249:251, yRle, xRle, FUN = function(x, y) var(x, y) / (sd(x) * sd(y))) @ For more information on the methods supported by the \Rclass{Rle} class, consult the \Rcode{Rle} man page. \subsection{Lists} In many data analysis situation there is a desire to organize and manipulate multiple objects simultaneously. Typically this is done in \R{} through the usage of a list. While a list serves as a generic container, it does not confer any information about the specific class of its elements, provides no infrastructure to ensure type safety, and the S3 and S4 method dispatch mechanisms do not support method selection for lists with homogeneous object types. The \Rclass{List} virtual class defined in the \IRanges{} package addresses these issues. \Rclass{List} is a direct extension of \Rclass{Vector}. \subsubsection{Lists of Atomic Vectors} The first type of lists we consider are those containing atomic sequences such as \Rclass{integer} vectors or \Rclass{Rle} objects. We may wish to define a method that retrieves the length of each atomic sequence element, without special type checking. To enable this, we define collection classes such as \Rclass{IntegerList} and \Rclass{RleList}, which inherit from the \Rclass{List} virtual class, for representing lists of \Rclass{integer} vectors and \Rclass{Rle} objects respectively. <>= getClassDef("RleList") @ As the class definition above shows, the \Rclass{RleList} class is virtual with subclasses \Rclass{SimpleRleList} and \Rclass{CompressedRleList}. A \Rclass{SimpleRleList} class uses a regular \R{} list to store the underlying elements and the \Rclass{CompressedRleList} class stores the elements in an unlisted form and keeps track of where the element breaks are. The former ``simple list" class is useful when the Rle elements are long and the latter ``compressed list" class is useful when the list is long and/or sparse (i.e. a number of the list elements have length 0). In fact, all of the atomic vector types (raw, logical, integer, numeric, complex, and character) have similar list classes that derive from the \Rclass{List} virtual class. For example, there is an \Rclass{IntegerList} virtual class with subclasses \Rclass{SimpleIntegerList} and \Rclass{CompressedIntegerList}. Each of the list classes for atomic sequences, be they stored as vectors or \Rclass{Rle} objects, have a constructor function with a name of the appropriate list virtual class, such as \Rclass{IntegerList}, and an optional argument \Rfunarg{compress} that takes an argument to specify whether or not to create the simple list object type or the compressed list object type. The default is to create the compressed list object type. <>= args(IntegerList) cIntList1 <- IntegerList(x = xVector, y = yVector) cIntList1 sIntList2 <- IntegerList(x = xVector, y = yVector, compress = FALSE) sIntList2 ## sparse integer list xExploded <- lapply(xVector[1:5000], function(x) seq_len(x)) cIntList2 <- IntegerList(xExploded) sIntList2 <- IntegerList(xExploded, compress = FALSE) object.size(cIntList2) object.size(sIntList2) @ The \Rfunction{length} function returns the number of elements in a \Rclass{Vector}-derived object and, for a \Rclass{List}-derived object like ``simple list" or ``compressed list", the \Rfunction{elementLengths} function returns an integer vector containing the lengths of each of the elements: <>= length(cIntList2) Rle(elementLengths(cIntList2)) @ Just as with ordinary \R{} \Rclass{list} objects, \Rclass{List}-derived object support the \Rfunction{[[} for element extraction, \Rfunction{c} for combining, and \Rfunction{lapply}/\Rfunction{sapply} for looping. When looping over sparse lists, the ``compressed list" classes can be much faster during computations since only the non-empty elements are looped over during the \Rfunction{lapply}/\Rfunction{sapply} computation and all the empty elements are assigned the appropriate value based on their status. <>= system.time(sapply(xExploded, mean)) system.time(sapply(sIntList2, mean)) system.time(sapply(cIntList2, mean)) identical(sapply(xExploded, mean), sapply(sIntList2, mean)) identical(sapply(xExploded, mean), sapply(cIntList2, mean)) @ Unlist ordinary \R{} \Rclass{list} objects, \Rclass{AtomicList} objects support the \Rfunction{Ops} (e.g. \Rfunction{+}, \Rfunction{==}, \Rfunction{\&}), \Rfunction{Math} (e.g. \Rfunction{log}, \Rfunction{sqrt}), \Rfunction{Math2} (e.g. \Rfunction{round}, \Rfunction{signif}), \Rfunction{Summary} (e.g. \Rfunction{min}, \Rfunction{max}, \Rfunction{sum}), and \Rfunction{Complex} (e.g. \Rfunction{Re}, \Rfunction{Im}) group generics. <>= xRleList <- RleList(xRle, 2L * rev(xRle)) yRleList <- RleList(yRle, 2L * rev(yRle)) xRleList > 0 xRleList + yRleList sum(xRleList > 0 | yRleList > 0) @ Since these atomic lists inherit from \Rclass{List}, they can also use the looping function \Rfunction{endoapply} to perform endomorphisms. <>= safe.max <- function(x) { if(length(x)) max(x) else integer(0) } endoapply(sIntList2, safe.max) endoapply(cIntList2, safe.max) endoapply(sIntList2, safe.max)[[1]] @ \section{Data Tables} To Do: \Rclass{DataTable}, \Rclass{DataFrame}, \Rclass{DataFrameList}, \Rclass{SplitDataFrameList} \section{Vector Annotations} Often when one has a collection of objects, there is a need to attach metadata that describes the collection in some way. Two kinds of metadata can be attached to a \Rclass{Vector} object: \begin{enumerate} \item Metadata about the object as a whole: this metadata is accessed via the \Rfunction{metadata} accessor and is represented as an ordinary \Rclass{list}; \item Metadata about the individual elements of the object: this metadata is accessed via the \Rfunction{mcols} accessor (\Rfunction{mcols} stands for {\it metadata columns}) and is represented as a \Rclass{DataTable} object (i.e. as an instance of a concrete subclass of \Rclass{DataTable}, e.g. a \Rclass{DataFrame} object). This \Rclass{DataTable} object can be thought of as the result of binding together one or several vector-like objects (the metadata columns) of the same length as the \Rclass{Vector} object. Each row of the \Rclass{DataTable} object annotates the corresponding element of the \Rclass{Vector} object. \end{enumerate} \section{Vector Ranges} When analyzing sequences, we are often interested in particular consecutive subsequences. For example, the \Sexpr{letters} vector could be considered a sequence of lower-case letters, in alphabetical order. We would call the first five letters (\textit{a} to \textit{e}) a consecutive subsequence, while the subsequence containing only the vowels would not be consecutive. It is not uncommon for an analysis task to focus only on the geometry of the regions, while ignoring the underlying sequence values. A list of indices would be a simple way to select a subsequence. However, a sparser representation for consecutive subsequences would be a range, a pairing of a start position and a width, as used when extracting sequences with \Rfunction{window}. When analyzing subsequences in \IRanges{}, each range is treated as an observation. The virtual \Rclass{Ranges} class represents lists of ranges, or, equivalently and as a derivative \Rclass{IntegerList}, sequences of consecutive integers. The most commonly used implementation of \Rclass{Ranges} is \Rclass{IRanges}, which stores the starts and widths as ordinary integer vectors. To construct an \Rclass{IRanges} instance, we call the \Rfunction{IRanges} constructor. Ranges are normally specified by passing two out of the three parameters: start, end and width (see \Rcode{help(IRanges)} for more information). % <>= ir1 <- IRanges(start = 1:10, width = 10:1) ir2 <- IRanges(start = 1:10, end = 11) ir3 <- IRanges(end = 11, width = 10:1) identical(ir1, ir2) & identical(ir2, ir3) ir <- IRanges(c(1, 8, 14, 15, 19, 34, 40), width = c(12, 6, 6, 15, 6, 2, 7)) @ % All of the above calls construct an \Rclass{IRanges} instance with the same ranges, using different combinations of the \Rfunarg{start}, \Rfunarg{end} and \Rfunarg{width} parameters. Accessing the starts, widths and ends is supported by every \Rclass{Ranges} implementation. <>= start(ir) @ <>= end(ir) @ <>= width(ir) @ For \Rclass{IRanges} and some other \Rclass{Ranges} derivatives, subsetting is also supported, by numeric and logical indices. <>= ir[1:4] @ <>= ir[start(ir) <= 15] @ One may think of each range as a sequence of integer ranges, and \Rclass{Ranges} is, in fact, derived from \Rclass{IntegerList}. <>= ir[[1]] @ In order to illustrate range operations, we'll create a function to plot ranges. <>= plotRanges <- function(x, xlim = x, main = deparse(substitute(x)), col = "black", sep = 0.5, ...) { height <- 1 if (is(xlim, "Ranges")) xlim <- c(min(start(xlim)), max(end(xlim))) bins <- disjointBins(IRanges(start(x), end(x) + 1)) plot.new() plot.window(xlim, c(0, max(bins)*(height + sep))) ybottom <- bins * (sep + height) - height rect(start(x)-0.5, ybottom, end(x)+0.5, ybottom + height, col = col, ...) title(main) axis(1) } @ <>= plotRanges(ir) @ \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-ir-plotRanges} \caption{\label{fig-ir-plotRanges}% Plot of original ranges.} \end{center} \end{figure} \subsection{Normality} Sometimes, it is necessary to formally represent a subsequence, where no elements are repeated and order is preserved. Also, it is occasionally useful to think of a \Rclass{Ranges} object as a set, where no elements are repeated and order does not matter. While every \Rclass{Ranges} object, as a \Rclass{Vector} derivative, has an implicit ordering, one can enforce the same ordering for all such objects, so that ordering becomes inconsequential within that context. The \Rclass{NormalIRanges} class formally represents either a subsequence encoding or a set of integers. By definition a Ranges object is said to be \textit{normal} when its ranges are: (a) not empty (i.e. they have a non-null width); (b) not overlapping; (c) ordered from left to right; (d) not even adjacent (i.e. there must be a non empty gap between 2 consecutive ranges). There are three main advantages of using a \textit{normal} \Rclass{Ranges} object: (1) it guarantees a subsequence encoding or set of integers, (2) it is compact in terms of the number of ranges, and (3) it uniquely identifies its information, which simplifies comparisons. The \Rfunction{reduce} function reduces any \Rclass{Ranges} object to a \Rclass{NormalIRanges} by merging redundant ranges. <>= reduce(ir) plotRanges(reduce(ir)) @ \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-ranges-reduce} \caption{\label{fig-ranges-reduce}% Plot of reduced ranges.} \end{center} \end{figure} \subsection{Lists of \Rclass{Ranges} objects} It is common to manipulate collections of \Rclass{Ranges} objects during an analysis. Thus, the \IRanges{} package defines some specific classes for working with multiple \Rclass{Ranges} objects. The \Rclass{RangesList} class asserts that each element is a \Rclass{Ranges} object and provides convenience methods, such as \Rfunction{start}, \Rfunction{end} and \Rfunction{width} accessors that return \Rclass{IntegerList} objects, aligning with the \Rclass{RangesList} object. To explicitly construct a \Rclass{RangesList}, use the \Rfunction{RangesList} function. <>= rl <- RangesList(ir, rev(ir)) @ % <>= start(rl) @ \subsection{Vector Extraction} As the elements of a \Rclass{Ranges} object encode consecutive subsequences, they may be used directly in sequence extraction. Note that when a \textit{normal} \Rclass{Ranges} is given as the index, the result is a subsequence, as no elements are repeated or reordered. If the sequence is a \Rclass{Vector} subclass (i.e. not an ordinary \Rclass{vector}), the canonical \Rfunction{[} function accepts a \Rclass{Ranges} instance. % <>= irextract <- IRanges(start = c(4501, 4901) , width = 100) xRle[irextract] @ % \subsection{Finding Overlapping Ranges} The function \Rfunction{findOverlaps} detects overlaps between two \Rclass{Ranges} objects. <>= ol <- findOverlaps(ir, reduce(ir)) as.matrix(ol) @ \subsection{Counting Overlapping Ranges} The function \Rfunction{coverage} counts the number of ranges over each position. <>= cov <- coverage(ir) plotRanges(ir) cov <- as.vector(cov) mat <- cbind(seq_along(cov)-0.5, cov) d <- diff(cov) != 0 mat <- rbind(cbind(mat[d,1]+1, mat[d,2]), mat) mat <- mat[order(mat[,1]),] lines(mat, col="red", lwd=4) axis(2) @ \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-ranges-coverage} \caption{\label{fig-ranges-coverage}% Plot of ranges with accumulated coverage.} \end{center} \end{figure} \subsection{Finding Neighboring Ranges} The \Rfunction{nearest} function finds the nearest neighbor ranges (overlapping is zero distance). The \Rfunction{precede} and \Rfunction{follow} functions find the non-overlapping nearest neighbors on a specific side. \subsection{Transforming Ranges} Utilities are available for transforming a \Rclass{Ranges} object in a variety of ways. Some transformations, like \Rfunction{reduce} introduced above, can be dramatic, while others are simple per-range adjustments of the starts, ends or widths. \subsubsection{Adjusting starts, ends and widths} Perhaps the simplest transformation is to adjust the start values by a scalar offset, as performed by the \Rfunction{shift} function. Below, we shift all ranges forward 10 positions. % <>= shift(ir, 10) @ There are several other ways to transform ranges. These include \Rfunction{narrow}, \Rfunction{resize}, \Rfunction{flank}, \Rfunction{reflect}, \Rfunction{restrict}, and \Rfunction{threebands}. For example \Rfunction{narrow} supports the adjustment of start, end and width values, which should be relative to each range. These adjustments are vectorized over the ranges. As its name suggests, the ranges can only be narrowed. % <>= narrow(ir, start=1:5, width=2) @ The \Rfunction{restrict} function ensures every range falls within a set of bounds. Ranges are contracted as necessary, and the ranges that fall completely outside of but not adjacent to the bounds are dropped, by default. % <>= restrict(ir, start=2, end=3) @ The \Rfunction{threebands} function extends \Rfunction{narrow} so that the remaining left and right regions adjacent to the narrowed region are also returned in separate \Rclass{Ranges} objects. % <>= threebands(ir, start=1:5, width=2) @ The arithmetic operators \Rfunction{+}, \Rfunction{-} and \Rfunction{*} change both the start and the end/width by symmetrically expanding or contracting each range. Adding or subtracting a numeric (integer) vector to a \Rclass{Ranges} causes each range to be expanded or contracted on each side by the corresponding value in the numeric vector. <>= ir + seq_len(length(ir)) @ % The \Rfunction{*} operator symmetrically magnifies a \Rclass{Ranges} object by a factor, where positive contracts (zooms in) and negative expands (zooms out). % <>= ir * -2 # double the width @ WARNING: The semantic of these arithmetic operators might be revisited at some point. Please restrict their use to the context of interactive visualization (where they arguably provide some convenience) but avoid to use them programmatically. \subsubsection{Making ranges disjoint} A more complex type of operation is making a set of ranges disjoint, \textit{i.e.} non-overlapping. For example, \Rfunction{threebands} returns a disjoint set of three ranges for each input range. The \Rfunction{disjoin} function makes a \Rclass{Ranges} object disjoint by fragmenting it into the widest ranges where the set of overlapping ranges is the same. <>= disjoin(ir) plotRanges(disjoin(ir)) @ \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-ranges-disjoin} \caption{\label{fig-ranges-disjoin}% Plot of disjoined ranges.} \end{center} \end{figure} A variant of \Rfunction{disjoin} is \Rfunction{disjointBins}, which divides the ranges into bins, such that the ranges in each bin are disjoint. The return value is an integer vector of the bins. <>= disjointBins(ir) @ \subsubsection{Other transformations} Other transformations include \Rfunction{reflect} and \Rfunction{flank}. The former ``flips'' each range within a set of common reference bounds. <>= reflect(ir, IRanges(start(ir), width=width(ir)*2)) @ % The \Rfunction{flank} returns ranges of a specified width that flank, to the left (default) or right, each input range. One use case of this is forming promoter regions for a set of genes. <>= flank(ir, width = seq_len(length(ir))) @ % \subsection{Set Operations} Sometimes, it is useful to consider a \Rclass{Ranges} object as a set of integers, although there is always an implicit ordering. This is formalized by \Rclass{NormalIRanges}, above, and we now present versions of the traditional mathematical set operations \textit{complement}, \textit{union}, \textit{intersect}, and \textit{difference} for \Rclass{Ranges} objects. There are two variants for each operation. The first treats each \Rclass{Ranges} object as a set and returns a \textit{normal} value, while the other has a ``parallel'' semantic like \Rfunction{pmin}/\Rfunction{pmax} and performs the operation for each range pairing separately. The \textit{complement} operation is implemented by the \Rfunction{gaps} and \Rfunction{pgap} functions. By default, \Rfunction{gaps} will return the ranges that fall between the ranges in the (normalized) input. It is possible to specify a set of bounds, so that flanking ranges are included. <>= gaps(ir, start=1, end=50) plotRanges(gaps(ir, start=1, end=50), c(1,50)) @ \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-ranges-gaps} \caption{\label{fig-ranges-gap}% Plot of gaps from ranges.} \end{center} \end{figure} \Rfunction{pgap} considers each parallel pairing between two \Rclass{Ranges} objects and finds the range, if any, between them. Note that the function name is singular, suggesting that only one range is returned per range in the input. <>= @ The remaining operations, \textit{union}, \textit{intersect} and \textit{difference} are implemented by the \Rfunction{[p]union}, \Rfunction{[p]intersect} and \Rfunction{[p]setdiff} functions, respectively. These are relatively self-explanatory. <>= @ <>= @ <>= @ <>= @ <>= @ <>= @ % \subsection{Mapping Ranges Between Vectors} % \Rfunction{mapCoords} \section{Vector Views} The \IRanges{} package provides the virtual \Rclass{Views} class, which stores a sequence together with an \Rclass{IRanges} object defining ranges on the sequence. Each range is said to represent a \textit{view} onto the sequence. Here, we will demonstrate the \Rclass{RleViews} class, where the sequence is of class \Rclass{Rle}. Other \Rclass{Views} implementations exist, such as \Rclass{XStringViews} in the \Rpackage{Biostrings} package. \subsection{Creating Views} There are two basic constructors for creating views: the \Rfunction{Views} function based on indicators and the \Rfunction{slice} based on numeric boundaries. <>= xViews <- Views(xRle, xRle >= 1) xViews <- slice(xRle, 1) xViewsList <- slice(xRleList, 1) @ \subsection{Aggregating Views} While \Rfunction{sapply} can be used to loop over each window, the native functions \Rfunction{viewMaxs}, \Rfunction{viewMins}, \Rfunction{viewSums}, and \Rfunction{viewMeans} provide fast looping to calculate their respective statistical summaries. <>= head(viewSums(xViews)) viewSums(xViewsList) head(viewMaxs(xViews)) viewMaxs(xViewsList) @ \section{Data on Ranges} IMPORTANT NOTE: Starting with BioC 2.12, the use of \Rclass{RangedData} and \Rclass{RangedDataList} objects is discouraged in favor of \Rclass{GRanges} and \Rclass{GRangesList} objects (those classes are defined in the \Rpackage{GenomicRanges} package). When analyzing ranges, there are often additional variables of interest, besides the geometry (starts, ends and widths). To formally represent a dataset where the ranges are the observations, \IRanges{} defines the \Rclass{RangedData} class. %\subsection{Manipulating \Rclass{RangedData}} To create a \Rclass{RangedData} instance, one needs to provide a \Rclass{Ranges} object and, optionally, any number of variables on those ranges. The variable objects need not be vectors, but they must satisfy the contract of \Rclass{DataFrame}. <>= values <- rnorm(length(ir)) rd <- RangedData(ir, name = letters[seq_len(length(ir))], values) rd @ One might notice the term ``sequence'' in the above output. This refers to an important feature of \Rclass{RangedData}: the ability to segregate ranges by their sequence (or space). For example, when analyzing genomic data, one is often working with ranges on different chromosomes. In many cases, such as when calculating overlap, one needs to separately treat ranges from different spaces, and \Rclass{RangedData} aims to facilitate this mode of operation. The segregation may be performed at construction time. <>= rd <- RangedData(ir, name = letters[seq_len(length(ir))], values, space = rep(c("chr1", "chr2"), c(3, length(ir) - 3))) rd @ With the knowledge that the data is split into spaces, it should not be surprising that the \Rfunction{ranges} accessor returns a \Rclass{RangesList} and \Rfunction{values} returns a \Rclass{SplitDataFrameList}. <>= ranges(rd) @ <>= values(rd) @ To obtain a \Rclass{RangedData} for a specific set of spaces, one should use the \Rfunction{[} function, which accepts logical, numeric and character indices. <>= rd["chr1"] @ % <>= all(identical(rd["chr1"], rd[1]), identical(rd[1], rd[c(TRUE, FALSE)])) @ The \Rfunction{names} and \Rfunction{length} functions return the names and number of spaces, respectively. <>= names(rd) @ <>= length(rd) @ The \Rfunction{lapply} function operates over the spaces. The object passed to the user function is a subset \Rclass{RangedData}. <>= lapply(rd, names) @ The above would suggest that \Rclass{RangedData} is a sequence of spaces. However, \Rclass{RangedData} also inherits from \Rclass{DataTable}, so it in some ways behaves like a sequence of columns. For example, one can extract a column via \Rfunction{\$} or \Rfunction{[[}. <>= rd[[2]] @ <>= rd$values @ Note that the extracted columns are ``unlisted'' over the spaces, which is usually much more convenient than obtaining them as lists. It is important to note that the elements have been sorted by the space factor and thus may not have the same order as the objects passed to the constructor. The two dimensional matrix-style subsetting is also supported. The rows are indexed globally, independent of space. <>= rd[1:3, "name"] @ \section{IRanges in Biological Sequence Analysis} The \IRanges{} packages was primarily designed with biological sequence analysis in mind and Table \ref{table:bioseq} shows how some biological sequence analysis concepts are represented in the \IRanges{} class system. \begin{table}[ht] \begin{center} \begin{tabular}{l|l} \hline Biological Entity & \Rclass{Vector} Subclass \\ \hline Genome browser track(s) & \Rclass{GRanges}/\Rclass{GRangesList} \\ Coverage across chromosomes/contigs & \Rclass{RleList} \\ Mapped ranges to genome & \Rclass{CompressedIRangesList} \\ Data (sans ranges) across chroms/contigs & \Rclass{SplitDataFrameList} \\ \hline \end{tabular} \end{center} \caption{\Rclass{Vector} subclasses for Biological Sequence Analysis} \label{table:bioseq} \end{table} \pagebreak[4] \section{Session Information} \begin{table*}[tbp] \begin{minipage}{\textwidth} <>= toLatex(sessionInfo()) @ \end{minipage} \caption{\label{tab:sessioninfo}% The output of \Rfunction{sessionInfo} on the build system after running this vignette.} \end{table*} \end{document} IRanges/inst/doc/IRangesOverview.pdf0000644000175100017510000071413212612026576020435 0ustar00biocbuildbiocbuild%PDF-1.5 %ÐÔÅØ 121 0 obj << /Length 2440 /Filter /FlateDecode >> stream xÚÅYKÛȾûW9QȨÍîæÓH8@q°Á.Œ÷`ûÀ9’²’8%ÏοO=ɦDÍxrÉAÙ]]]ïþªõ÷Û7oòùÌæÆÙ4™ÝÞÏ\›<ËgYR˜2)f·õìsô~?_ø8Ž>Ìm´Ÿ»<:ÚùÂ¥Q}‚‘%|Ž›–æˆìØÎ¿ÞþëíO‰ 9[Ÿoí,fžÈëã<£j¿j:^à♵¦LS‡ 6KM‘•³…+LQ:^÷+î_á–ð9lhWD¿ÃÖ.‹Þß\YÔâÐ~µ'’ËF7HFÿ†GY”Gkx@VÍ–'¦w˜x<àè^”kdí?þŽl¿ÄÎÏ“ÌE ïû+V+™r2e#RlVxSZzxãó„õø™£-‹ ¼iCöfxŽñ=ƒ‚«ã9Û§Œwn¶Hœ)Š’ùÚùÂZ—ˆ¯<Ø …wÁc}¢ÅWIJ˜•¦Ì\† cК"¯ß¢y&t.6) ŒiÑ‘´@´óö…Ém®kÐÐä‚ßçi†C3&Ž<Óñc¼:X¡š‡Ùë¨Lâ#òr¢‡Ž=82ø_'i¿T"´m’Ð" ½aÇ 6}°KÈ€z½(RMq0¨¶(œ’á2´`Û5çõÁ%aŒ,ÒҸ܂W)ØNí3_$r­:RxÒË£Þbãè㺥-‡ª¯™/rȼû€•ìøý»(̆?J®a$Y=¢M„é#’mé3ˆ…¯Oøž€1xœü¸ƒÏÃ6à4,›tšÒ•Ú›M6jþ@ñwBÝŒLÒ©˜›2#flăšiÝP°@¶%½Î`ax÷ѶB²ŠæòŒC Ú.à›ômqv[3m­ +¢Î£®=czd¦’2,«˜´Wu§ zÒHfu==£Î+’a#ëÖ;fºT°Šä¼Ø³¹ÈÖ•Fk#Âó»n I¤Ÿt“Ác«Jh®È¬k­§ ã•Y´#ÁiG¤0è)ý6/< hÚ?¸è‘æ“dì!Må¨ÅÈ{[˜eSÁ»*Fó,Ê¥ò&˜¤(£ |ìIš “OêJGQy.ÓsgF’ùW»!sé³g†÷ý™›gÕºÕÔ T#ï6âÒSõîÄæ­€ŽŸƒdo.m“X€i½=ß ÿb‘€ƒRoéP/­ê›/Rç©ü´’í…9ðù§8þ$)¦µmÿ>oås.l«G¢°ìM)ìMð¼ºÂc¬0¯ù(²€Xvª‰6/± ´ú \+‘x¿Ë&ì¦)r'ÊTòû4ìòÜÊýÊÁfÞ™ÒɉåÃ}š—P5%"<ÌB‹€-ÿƒLi¢{Çá1ï³á˜oø#ŸÐ’å?òp{N}™Ìejâôõ5µLÊëÉŒ•(Ç¦Ý }} €k®Ãc%ZQžÖž5~‰m‚ö¢@tV¼ÑhˆnZb”ôŠ7R´{8Ùñ1–ú¼^ÞÊÒ¤±{Iàdô°ªÇô¥i–Ù’1ɃB¬®é݇óÚ.|¤¦'x’“V˜ –ô q”¦Gb áS iwV‘䄟Í5Ö-4Q jwrl\]/[(®2då>£C¨H$ðuO5{1Úq÷q 5´‘À’Lý ½‘‹î‘›†—óõÃtw’´ï†Ð!¸ßñ|­ýÅòÐ×AdÐõ2,è0¶ÚBÐã1¨Â{ë=‹1ftçé+/5>î“uQ+2ð]Í"^ñW/ï:\yä5÷Ô\îU®%dT4F±þižã)šºáÄ8LhàŒKûÒ¡°ç –CäI‡3÷§k_dƒûá^1E®•ˆµe~Oí2+D¸*RŠE8ÁZKç×tµµ…ñ…í«-‘d¡öÖ™¬ìú—L2“¸~KaZhF©(02ÝA2±´øÌyÅb#bµex Ó9gVÛWKX á8¹©´az[q2…D¼]OÖ´ÉÊWE^<‹õTPTh{R€¬ú«üµvæC†rŒö>!ÙÆ]ö¨t!¢›24ÙeݤƒÉ¹ÚÞLØÅºÒØÄQàRif/¬Рȓ0`ëÇ5{EÊìJÐk7\Ytj¬=æýaåŽk)Díi´ '*·[¥^]/g(–ß÷ T8ÎýØØÐ & œE¯4þо§?Ô|!ÜOªÕHtU·©šÏÄtÃÀò>ãî~²o„j1Dä³Þ*Œ-ÝPŸ0_†zÔ£1>wyj£ã=Þý|®]ðØÈ§°fü26Þ ÝÉñUó%NýÝÊ˧Œ‡ñ6F~éØçk4\ˆ(+ ¦ä|½«ñí‡xYº$o-a‡SåŸÉ'Lñg-…µSâœíùŒtÿ“8/8q÷'á;î™Îô±¿ù9êAl†CÅFÊ|,þeü¨ OÿA?ËÖ²ÒIàYiM§ÝÓ“¿ ~ïæ'¿^Úê¢fóuHÍä Üdç'+ÞŠ^\@¼nèÇ@"NM‘¸gDiò¼GkýCã»\Ú"oµ %ºŒõWS(õíƒþ-!G©Âÿ$a@.ØTÌdßg.p¡–ÂÉgÇšG¨ŸÅ5X-O;üV¼LQ5¬æ CnÊFwòz™ïûvÄõQ¼°>6)4×£`;`-‹Þlù®ŒŽp˜Éñ,ø-´1–^y”ÑkòЬþC,ÕÊ•ö 0O·u"Á8&\ñ쿸@'O4‘Ò^ü [¯e›kÊA‹/Œ&P›;=)Ùjt™ˆ 澿›<«|OQF»Vi~Þú">W³G²@¬âµd‡ó ëJãã¶ã¤B¼ °ãVíƒVŠ:àå^ÿ%\Žû:œê/_JÆGü©‚û]¤QâHW#ÚML€ûåý ôKÙðÙty»„ÑÖxçàxɺ°¼çúù’Cjœ;žxý9q èÅ÷u9Í©ÿ»w%ý¯Ë%ó¶> stream xÚÕXKÛ6¾çWø(1+‘zE¶H=¥F{HsÐZ´ctm9–œÍæ×w^”(Y^'Ûf‹hK9~óÍCóÓòÙw¿$ù¬PEªÓÙr=Kc•ÏÒ"TYÍ–ÕìMðÃ|‘h|œGÁ0,ŒŒF ãã ŒÆÛùÛå¯ 0õ†³…i:gi[X¶—í(j#ÿ(fã5Œ[š£·âÖ|y++÷² %¼ãGÿÝÁÌvò J?Ñ^Pp…*Žg‹(RE’°Z¿M ‚Æ ' ÷†Ã}ˆH)*ŸDFÃëe[(˜ø /D&Àüé"Ìôø{‚‰.ñé_aÂßC¶yΫïXR"ÖÒW2ŠUÑ))ÖûaÙö&Òq•mFs(ÚÒDì¬[VÃDTÌ—s¸»ç›Æ¢v»^Ä_õA¬ZÞòitR°|\|Ï‹r’¥Ñ†ªW¦ä¿ éS¶ü®Ê²HzT¯yò@º‘;üab²dFÅ×»9Ý÷Š—„ænKØÒ’·¾GR«V¤ ògá`õY´#é¸ýppIä¶Þ3ŸŒÑÁ ÑÅ iie–—´À‰lkYW|~B«l™Ö0azèvŠmžŽ½5QifX1 ëz¶"¥ãhT$]yÌ4¹ ~¸¯±mK¾¾9gúP®L.æG<`wžïâ}ª\À(dnV9ö¤e…2©¡$ìõ‘Ce¢Ä-Ú ßóa®s8sŠcÃ<‹ÃX¢ ­ÚŠ%P±uÛ… š@ýìŠ|¿!Uï“Bœ –0$'ÂÆö2Év–¯ûÞÅœ]ÉôÚ1{Ç÷å¾îîH†Y¤QÊŽÉ{i™[ÃZñò욉×t#ÿleGGpÔÎe-ñ0 Pº¨Dßíl[•­œžÖGþ'¯cSŠ;ᬰ®-“k¦hç3¢:,éd?Š®(µ\9cTÏùq‡(@v!¿"Å“`+'YQpy¥âÝ¥ÄkŸbq1°cPã3Ýμ÷¢?ø:ÌØs&¡Êuá„€Ýâ$^qF‚ëH%Y1´Î†˜@fvÁÏ„Æ;ßy¶MŒJâÎÞœk‘«(s‘['"›3<r¡ AF®Å|sr ®ø^îöÔ{§uév…Á‚EÉ+è4w|= é 7õV.Ù7}QL\Š3½r ‚ä©ßC^Üô׺[íšHdå±8K©,2CsÔkW· 29G‡=›óÆœÛvá^‹ ÀYñ.T³nùºÜ9/o\J…i‡jžõÁóKŠZŸÊÞZÈ"xÅr›dé³;HŽ—MDøš–·t1kÑe‡s0Iôu^Q©– K6]ÙsF6l‹µÛs  ’¿çI”Qˆly8Í(P´}Ð2…i#CwmI‰eUyµ§MLîøl}rÜèq“”ºæ ¥/°Ó%ÞÆq, ©šÔ*ÊGuR¤&|fºCã΋µ•¤Ò» cÙNö,X§—RòùÎ!!Ó ƒàŸÙÏó œX*¥¾È!e/Û®¶TF1n–z‚ÂùƱcW Xƒ‰ (j )®ÐŒ :Ç¿`þ¯ñÐao¤Æó°A/­7œí„`ãúáXÌuXÞ %ñâ «¨(A)©þ?y1E8ÀXŒ¢ê+ô±w—޾RçM¡/€RMÕòKö½cqâ·~Hn¨¦aßOUg`|ÀVÀãÏ”o@úh|èôtÁôhÉuЎºås®Šl ØÏ”í2Ë)—ç9²NzÝ Ö??µuEÙnT‰™$¤/"5+Þxd3Ñj.<ûb™1‚äŽ0J?£ÃaäGz·Dª.ÿ;Ê\â[Ç”K¦AmÈσԵôÌ€O"nå›xø)¹’où~ƒk P;¤éªí;#¸êûR¿¿±WSvy´Þ‡­ Ôµ÷‰<þtœún4:Syœ>EO¡²¾˜&i-Õû}Óê<]Ï85¼˜j™KõËÂì«6 QýKÍÂbÜ,te¨ß0L¿ aø¸?ý¸FcÌ)ÿ%S“zp—¹•_Ô Ö'ƒäekû=Æ'7zzÑàéÿ`ð¯gÛ/2ã°Jú¶Í˜<é›ÿ¡ÿõ•Ú·`´' ¸úÑq÷QFMfœ4qû· \r endstream endobj 147 0 obj << /Length 2461 /Filter /FlateDecode >> stream xÚíZKs㸾ϯðQª¬âMnU¶*Ieª&5I¥6Î\6{ %ÚVVQ÷×§Ñ €IÉ–fvg9Фðlôóë†ÿtýæ÷ouyU±Êsu}{e+¯LU0[ñ«ëÕÕ³ïæ -äl?糞xþ]è^Ÿàù'<;xÖ¾ëÁ;Àó Í4ƒÏ¼þ+ìf’ÝŠ«‡_ÒÐVk¿ØÁ/rçßnï<ßóÁ6\¸…Ï[úÜø‘;?Ë­pßo_Ðç“'4éåðYö'|ôktŽØ+^0¥€DÎ*­‰Ä÷“¹ |ömXò²—øÜéŽä“ë9úȪ=×=é÷Ô*zzé©F‘ý²'Fž3´!Õ½Eàw¢^û:OÿguP±ó4ñô0ò|þ!ÈQÜ_QwíQ½Õ¿¤ÎŠŠ¥_«X¹JLJߘ é Í´´´‹³]æL”ÁTq®ÊÙŸï¶s)PÖ»ðçn¾¥Ê*3k–‡Ö3¿£½ÊèJ&Kïá®ïñ$b•Œœ© Fã¨w(D ÇÞÝÅ––3Z†9N¹êå\ØÙOsmfõH_Iƒë<ËÜïÃ\” e×RÃ]ãNÔì½à—Ôzë˜í:–ßÑî:Tï±zrÃYÉM d9&µbÚèÐ_»eWëˆÕXM2+ãgRD.€õ)ÑúvO'Yºï­;ðÍ:1Hàìˆc±T‚IOöanAÞs-pÑm2¦H2QÆ9í 衚ý§ ¼ìØ|aa‰^®ª¨X©¶´ .å$ô­HˆRÊp¾1½Z3iùzIMÇô &tuœÞdË7ÃÖñë‰:ÂÆ}‹ÙªA'ÆÕ.q#ëvG½ÁÔ‡d¦c¹Yß–¨gØÝ±§ªÞ÷Sï\çG7¿lØd”޹&û¹ ,¸q«»ÞRËÜPK%G­ŽMEî[b2Þ,ÏŽ-}|ýL ,¿qldØH]<ýk€"{b¤š ‹ê<44í…¿,ŠÃê9¹îCT8lö IþÜÿˆÿB ö =þLÄ/¾¼“Þ½ÇP¶ªÀÃ:ÊÑ]ëpßG÷À´È ¼‡ÍÐL@Blê²lâð2H|·ó‡Jc—ÌôHäûñ"†)az46Ë„ ýͧá 0n# ¢hïàG›òGi\pnøpØx!ÎÀÔ(QC>¡™»É¨êîük Ð4¶í;÷ˆ bxŒTrv=/âT·]»} Ð°j2n\'Â=ø>Ü{ãì¾™‚Ù•bºÒgí’ÇO€ºó»y³Ý7À!xX<ê„–LMAଂ…3KKlë­.¸K'Œç1}ʰª”§DoXn6¯[t„«¥¬N@w05YÔ±…ld)¥=¦|n"P¯Kdi²$ûopQ˜½4-UïVô1˜å(ÿ9–判dxšžÜùgŸÄ™:ÆÑy5ä7š¿˜A$SEÆË Ò!6þñeÞjõ…Êt`¨ÑL ÑÁû@egÞ¼ÜinÛ=f¾ÐTí6Y>úÝê…+;! hÄ:ÊMÈ>Q*MÀñK‚ØöuÄã«ÁWÆž«±ŠY[¾Š½½èÎX»J½ç09î¹søv#ëíÚ/ìÞµgOÂ÷­kÞ9>O:~ðì?áùÁ=•Áu3Ìk(V ¹}<êòôNíÒœ!¥O‡^yís nœÿs-Ǫ`0¢MÀu¯»Â2‘µ›IŒô“óËXh˜ª`ôÔ<Ý£onh}̆ܟq6½1ƒy›dçfEýÈ+tâ•`ÚðÏǨ&â‹êum¼H‚ (PtQ,j³ÇC/ˆ6‰04 ©³*tŠ+žžÚç>|qc&4ÇZfûËi·Ço ñwþ+ðòUõ„JF­z¾t}Ô‚ê+×XÖ¾ðâåçºo÷t¯íQPÉ´°¹ÿj‡h¸Cd%D´~ÌáCÉëæ1ƒÅ Í@˜È/Sƒ?©ý²Ýá=™ C[8£ÛÕC9IÈ=úœï >ÊŠYmúË[Ô·pÅTƒòù«öùë€ÄC›´¡ïËNù;’а€%l™‡PAo ޳B fK{ÆJ—äFL6¦+9{wK×^Áð{µîo,ví>~ò"¶2OlK ZëŸûß­_;²Ì]w$.XV*Ùœ.¼ÛÇMOAÓ%ú· …}7tíßÒ¥–>;ïð«ìÆF%£§‘¬¥c+&ù÷¶þ¨p~nú$ršãöèb7¹gëaëC>rÓeÁÍ$bÕ’•‚_"íŠõ!ñ”{’Ú^bVe"¼_B¶%@µ]ͱ¤.éºÞüåúÍÿÚ5Œö endstream endobj 153 0 obj << /Length 1656 /Filter /FlateDecode >> stream xÚ¥X[oÛ6~ϯð£ T¬x“¨`°Kt(6¬p»‡®ŠíÄl+í¦ù÷;7R²­4±Hž;?R øÓ#´ #W–ªòz4]_|¾P¥/ Mó½OšÒ²J^¾YëѯíÅŸð§ræ˜÷Xþ<¹xyFµªKSŽ&7#íœr…9ø ÖŽ&³ÑÇìj¬³%´Ûý=üŸskm¦/ǹs6û¥ÅAšXÁ¿f'Äí†é®Ç¹)³ùnlBö06¬ÒÍøÓä·—W¾ì˶Nùà@W’úè>Ò’Æ… H ª<WQxh4뻕œ¯{!%ÂÓGp ûˆaÊZù²ì*œÄ` Q4I*äW§¾‘¾•¾UÂé"£4 JÏ8ÏÉFÈöO%ð!³ cCôp#¾? F„@ÂBi«+#1,YÒ«Ua¾ðá§è§ÀÉdäwÈxS©¢þ–õnF’ÒôÝKŒEÄ@3¨è Áÿ”½®€Šs~Ü1>$†ÇЈG nÈyˆH«W TyâÙ«m*a޲p³•³ŒN/,¦ªÚ{ÚYåüy›;(~Û Êãr %ÄVwÕWTˆ¢‹!ˆ©üíYZäÎ[ޱKŠ®H³ã‹€ÉnöñæÐ=„\ž}QþJ¤E¥ã r7sÖ³À3×àÇï•õøßeÚõÜ;D¬Êv"¬ƒ TïDë–n®ô5N×9UœÂ+`ñd#’‰ØÑ*/Ï"ñABÓ;M' Oå…Ür‡µÅÛA¥ø*})oø¾XSÔd𸹡ï«U³*ý)%W]%þÇÑW¼DI‰¯:ÕP?PÝËß§s’d] ŸžÖÏõ‡T|~ùéÙéR”5¤M­B¬)=H]¼ž\ü ¿>Õ endstream endobj 150 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./IRangesOverview-figshiftcorrs.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 157 0 R /BBox [0 0 360 360] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 158 0 R/F2 159 0 R>> /ExtGState << >>/ColorSpace << /sRGB 160 0 R >>>> /Length 590 /Filter /FlateDecode >> stream xœ¥VMk1½ëW̱=t¢}_šB …Ô =”œÜ†Ä8-± ýû­Ö’lŒËn^üüôæS3k‚; ØÀ«º‡Wp µ…`ÐZà 100t »Ÿð ~©«ý×O×p³RµÖÐ?W7_ä×àà¯úþ~(‚;ùlåðY]êê–ÄÝð˜;h£œÔå‹÷HHë †x·}ÃFØa§>ÿS'B @‘s³ÕDYrÖõçd vŒ.-Kê&HÅ=Z^ —ÜsüCççËYrw|L˜ì¹äî$xg1.ž%wo\ĸ ò,¹¹5!¡¥ùr#¹‡¢æpF-3ñ¶+ïe Â4P/â-a0ÜÂê„.È71³$V¢­ô;^®›çÆØñÉ¢Õ/°ñldâbå'Øñ!`ò/°ñGéÔìŸk?o½?S¼ýZÖÉ-O­aœˆò(8¯#v\@¹9l\nOíëEq^$R®Nmõ µ•bÒ‘zŽïhѤ^íføföy—õê¾ÙK›\¯ö3|=6±WWßåí†(í.ˆet´Û}BS®~A%’àR¥'ØñN#ëÆØñ²ßeÎ+_`ã™lž?ÁŽ·>ÿ^ù;¾¤Sù–]_º®^º2Ê" 2²XÌX:¹Nûsµ¿h€ŒøvÕíÞe If06 v¶¹3y­V ñøL#¯ §|zZhhdòdQl§Ã'ðpx5n×7ïŠ:o5ŠùÏJŽwÿôüøg?#cù*á‘ÄË;`ý{·«îÕ?ú¹Ü° endstream endobj 162 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xœ–wTSهϽ7½P’Š”ÐkhRH ½H‘.*1 JÀ"6DTpDQ‘¦2(à€£C‘±"Š…Q±ëDÔqp–Id­ß¼yïÍ›ß÷~kŸ½ÏÝgï}ÖºüƒÂLX € ¡Xáçň‹g` ðlàp³³BøF™|ØŒl™ø½º ùû*Ó?ŒÁÿŸ”¹Y"1P˜ŒçòøÙ\É8=Wœ%·Oɘ¶4MÎ0JÎ"Y‚2V“sò,[|ö™e9ó2„<ËsÎâeðäÜ'ã9¾Œ‘`çø¹2¾&cƒtI†@Æoä±|N6(’Ü.æsSdl-c’(2‚-ãyàHÉ_ðÒ/XÌÏËÅÎÌZ.$§ˆ&\S†“‹áÏÏMç‹ÅÌ07#â1Ø™YárfÏüYym²";Ø8980m-m¾(Ô]ü›’÷v–^„îDøÃöW~™ °¦eµÙú‡mi]ëP»ý‡Í`/в¾u}qº|^RÄâ,g+«ÜÜ\KŸk)/èïúŸC_|ÏR¾Ýïåaxó“8’t1C^7nfz¦DÄÈÎâpù 柇øþuü$¾ˆ/”ED˦L L–µ[Ȉ™B†@øŸšøÃþ¤Ù¹–‰ÚøЖX¥!@~(* {d+Ðï} ÆGù͋љ˜ûÏ‚þ}W¸LþÈ$ŽcGD2¸QÎìšüZ4 E@ê@èÀ¶À¸àA(ˆq`1à‚D €µ ”‚­`'¨u 4ƒ6ptcà48.Ë`ÜR0ž€)ð Ì@„…ÈR‡t CȲ…XäCP”%CBH@ë R¨ª†ê¡fè[è(tº C· Qhúz#0 ¦ÁZ°l³`O8Ž„ÁÉð28.‚·À•p|î„O×àX ?§€:¢‹0ÂFB‘x$ !«¤i@Ú¤¹ŠH‘§È[EE1PL” Ê…⢖¡V¡6£ªQP¨>ÔUÔ(j õMFk¢ÍÑÎèt,:‹.FW ›Ðè³èô8úƒ¡cŒ1ŽL&³³³ÓŽ9…ÆŒa¦±X¬:ÖëŠ År°bl1¶ {{{;Ž}ƒ#âtp¶8_\¡8áú"ãEy‹.,ÖXœ¾øøÅ%œ%Gщ1‰-‰ï9¡œÎôÒ€¥µK§¸lî.îžoo’ïÊ/çO$¹&•'=JvMÞž<™âžR‘òTÀT ž§ú§Ö¥¾N MÛŸö)=&½=—‘˜qTH¦ û2µ3ó2‡³Ì³Š³¤Ëœ—í\6% 5eCÙ‹²»Å4ÙÏÔ€ÄD²^2šã–S“ó&7:÷Hžrž0o`¹ÙòMË'ò}ó¿^ZÁ]Ñ[ [°¶`t¥çÊúUЪ¥«zWë¯.Z=¾Æo͵„µik(´.,/|¹.f]O‘VÑš¢±õ~ë[‹ŠEÅ76¸l¨ÛˆÚ(Ø8¸iMKx%K­K+Jßoæn¾ø•ÍW•_}Ú’´e°Ì¡lÏVÌVáÖëÛÜ·(W.Ï/Û²½scGÉŽ—;—ì¼PaWQ·‹°K²KZ\Ù]ePµµê}uJõHWM{­fí¦Ú×»y»¯ìñØÓV§UWZ÷n¯`ïÍz¿úΣ†Š}˜}9û6F7öÍúº¹I£©´éÃ~á~éˆ}ÍŽÍÍ-š-e­p«¤uò`ÂÁËßxÓÝÆl«o§·—‡$‡›øíõÃA‡{°Ž´}gø]mµ£¤ê\Þ9Õ•Ò%íŽë>x´·Ç¥§ã{Ëï÷Ó=Vs\åx٠‰¢ŸN柜>•uêééäÓc½Kz=s­/¼oðlÐÙóç|Ïé÷ì?yÞõü± ÎŽ^d]ìºäp©sÀ~ ãû:;‡‡º/;]îž7|âŠû•ÓW½¯ž»píÒÈü‘áëQ×oÞH¸!½É»ùèVú­ç·snÏÜYs}·äžÒ½Šûš÷~4ý±]ê =>ê=:ð`Áƒ;cܱ'?eÿô~¼è!ùaÅ„ÎDó#ÛGÇ&}'/?^øxüIÖ“™§Å?+ÿ\ûÌäÙw¿xü20;5þ\ôüÓ¯›_¨¿ØÿÒîeïtØôýW¯f^—¼Qsà-ëmÿ»˜w3¹ï±ï+?˜~èùôñî§ŒOŸ~÷„óû endstream endobj 165 0 obj << /Length 1484 /Filter /FlateDecode >> stream xÚÝXKÛ6¾ï¯ðQFcFE=ö°@[ì¢(ȺÛC’ƒÖ¯u`Y®´Ï ?¾3áDYòÚÞ$H‘!rDg†ß ?é·ñÉë R‘FA4ÏQ(’A”ú"Nå`<|ðΆ#(ïi(½÷ÐVÐfÃOã?aaä,ô£@Š H̪%L[C»¥éÒ[ð³„6j©"ít离â™k^…nÌ+ ]g£)Ð]vWih’›ªÇô-ºãý*tl }†ƒ‘”"É7½FáévSÃQà§·~{a½u[ž€,…5rT%@dš÷- É‹þmRrÃg´qá ^dõ;v§2û²¿Ñ·oÜgæþån¡Ð~ØFÎßZë‘ ÔçYi°‚‚¬äzRÜ7TxÅÜÈ'%꘠§·ˆûaX %¾Ú€U1E!#¯ð2'ËóòYŽ[”OfXQaѽE÷‚w¶p@+‹»Å º6oëoÎM2lä×`Adl ¼øX–uÒxŠZ³ÜZ¹œP¼ñxG2iS>ä‹a‚ÁÃQ(Í ?âÊ|ƒçŽCp2T¾u²›Åq*‚XtHÛc7çÝà À€8±“ pG‡Þg û-ZàCZcŒ'hô݆›UÆ:›çm 1:8¦Cœ™>'+mhJÖ>o¯äÉxL›lÒvÌ+J¶h±Ä­²UO<‚T *7 Wl÷„­)èÜ»ÈöE¤ÒÁÁƒ 3 U"B%Û‡øpÆ­*ð*ÚÇš»^ T¹îàЙóÀtN«rƒ!õ”MzÊwÚ*ú—8A Ôç·ô>úÚçá5´Ï[Ó«ÀÝ¿ð;^Ò†‰¹²¼nn…è¼Úm©´½Ø®¥Ÿluß³¤34jê\6ô§þ²±G„·7V”ϸç^¯u÷º¿bÙ‚v í¼ p[~\ØŒmzÅ1\ç³k‹w¾ªÇ(Šm¢¸·q÷ÆêfY$´¬³,[Sì{ÒùŒîÛ£ÿbï죥ˆ›lž=òLÔ”Q±‹£úæ@ç›-hx?Ôòµ‹Òl=5+Kg*0YCú*3cN7Kn×±‹¡ë"œƒ ê8¾zWÝ–)”¦•ÉT¥P ™nU¥ÒÔn÷â¬OÖ\®¸ÝÓžúÒΕŽ~Æ9Ã`ûrâE€÷mš?7:´làÖ.Bù]#ZC?1¹Ef«I›ÖY¾œR³¯žÏÿ¤•ÿ=è„Û°ÁܳàL„J;s‚³²Š9ž†[¸Ùs*,!àw9$àÙšf6¨Û×$ ¯³ª.ÈfÕ̆߰•i£0«**¤Db––ƒÍ¦fƒ‡e»^D-‡u$"ßIÇŽ£Ðkˆ).rÇ,“Ru1/+³)]ì(]Ý1¸–B¯33óÝÆ°ZÊh Ã´Ño­G7Ä}}ïmfƒ°äwÉs¢^OÈ-_ÕÔw)™x¿HO7ªFº0\xÃ#ºý$[ 䢉÷GÍíaÞ’ƒÝ̘¿Œìë§nùõ]6éÂyćx¦ù~P¥Œ§˜›ÿm1ŽzˆùºwnÅ5ÂU{ªók8Koi`à»tãZŸâü¸"5ŽK‡Žû8^Íì&×czüÛ‡äCëvú¿«ÛŸªïÔnùãê6Ù>ø¶–:mÉ¿¤?gÍÞó#·!v@`ÌO[ü—UäÜ›wˆOó3ë’ÃXSÏCXШï—ÄY¸ÌÁÒ¾ÏÈ£?²üóQϯR%!@À •/bɘÑ8ïä||ò‰9š" endstream endobj 169 0 obj << /Length 2384 /Filter /FlateDecode >> stream xÚÍYKÛF¾ûW>I ‹›Í—,àÝÄ€7Žij³'ŽD=bIÔŠ’'òãSÏî¦ÈÑŒƒràPݬ®ª®ÇWÕ=ÿºyöÕë´•Q™™lt³e6*FY9‹ò2Ý,FÆÿœLS“ŒÛI<>óƒç§Y:ƒ×¯ðüÏžš©„xƯßùõù 1‹'?ßüÉEf£i\Fyž²€2†çg^hdˆ Rù]Ðoâî(¶Qim—Û«=Ð.&Ó$IÆkÔêȪáx?[üiÆÍ¾æKüÞì˜à¿×žþ{øYñWD‹¦:¼”}…êL;úØŽÑ@ <+ÙÑá![?ÕjûÀi¸ UÃýÍá™ö½‚²—^\±udƒøIí>üɽȹX•^S–üù(šîÉú°±Q<‹ÈLqT¦²·ƒJÅ›/'Ó¼HËq.‘šå,Ä?‚)~˜¬r’5ëʹE—ŠiÎ"³e>/…íÌ0²Íh'ñ8‘]YbíãRã4ºRhÒžv½Æ6Jg—QÜrÄ‘µ]6‹D.Ef³c§õ§‰)hGsú„†o_töÃ*¶³¨°%؉Ï%NÙVDeî+γ†e”¤¹’µâÇ Åûõ•ÄÿAüð¹/+M£Ôe‚ Ï{ݲjöšÊÚ‡ÉÔdœèdÉ^ aílÀ¸4‘ã'&•|Ún\:ÊæÜiÇ¿8붃d³È@¬ A€7탩ÿbUÿ$Žjü¦¯‰Ä¦‘ÇèÁ1¨ûÐmÊH””ºŽUÞ‘zÙÕš¹‡Í/ ñS‹ñF£fɪU<ܲ¶lhm²¤ÿOw±õLBräwb.­zÿ¦öÛ­ÚÎ:Šv²òQÛ˜s,6\µÀ'†—6¶Ò¡’¬EÃí·žÓؘ(ɳ®pyô6“2M¨ iÆeTÚrÓˆøŽÄ‘e…£Âþn|Q'±¡J[Þ‰gŒiy„fW©'6qíÿìjÒí$dË”BìØ u>‰j’L´rÏÀj3ëwBS{’ZxÖç,©§[hD¶C¼c=ë'6–ß& WFû®–„íüRŠ04×N’È|%HÇԦ ËýAÓ ²ƒæü­°–EœÐ4³L à]ëW7¬Fʤ¸ÃlŽ2É  ª(ª·8:Å.£€¡ÕÜé÷þH5`RÚê®Y‘ék -B¥¤V<Í6>hàSŠZPôæ¡’ˆ§€YâÄŠ>”8¼%±RjŒO:l¤‚cQJ S> Zs ŠÎAÑì¢[™Ìéö†šÄ}¸r¸ž– î$Ó5äü“"j¥Uc!éq$6­$ ©³ÖT{U[ ýº†4M²ÈfùS¬8µiAIGg¼b㛊_ÔG9xP€¿=鉙ʤ¶RzÍâ¨H5n'9„Å$5Ü7?pÜ3ЂXçgÙn–uî;¼LÂŽªYÙé8¸µŒ±ó°ï7ÒyL“ÂÝG$…£D"Zì¸:Áí¤%ç'=1=Þ±HpHÅÔc«(L¸“;\Ê”Ð4hhâž+I—‡Ú-\]€ˆ:zŒ­ŸÀ5‚Ì\¡6îvƒëŸÞÝ­ -jÑ¡ÿ§£cM­o8ìÐHz;àé$‡ógæ =É<‘«WŸ+)ä¾Oh¼CPkŽ"¾9H³E”ñSúh÷$*ò¤‹kýC5á¶p˜w%–Xv î5ŽÖ<–ºdJÓ…IÛ’{ÕÒ A¶®_s¹ 1yô\§Õl¶K.¼·ê¨ÕÉ«„…ï§ÐÙîe Îô}ÍËôP°ãë0ér^à×2¬Øyž†ªE+>—- "Ûø¢(𔫇5éúÑÅ(¶tE}+vÄÜR‘–Õ4wÌôмÁî#±˜6·CÁij°¶zÆŸw¨8(Ò´ÀT7öab8öì‚ó°Nôb?¾ ÊÉEno¸l·ÆÙÐÒuî ^î 'Ù+߯Ðö¨Gµ‘yjºn%߸cÓÆŸ6ƒl#ek@éÜD¹ÍžXàKs½ÀÓÑ×ûIÃK½ ,:¸²ê{TÚÊ+[p&ð·òƒÕ+·|!¢%°Ù!Hã;Q¹?Ý9p*ÎÿŠûAÞåQ»ˆ éWK°^rr´ZbûŠinïåÔÈïßzÖÕ.žoäûÒßC=¿¸a{«N6ÏŸ|3u«q!+ÏîbtëëCÓË'²rT®änï£ü^ùh §7­ þqP ·çtk&ðh’¨Œ¥Mx/â×ã5eHÈtþƒå%84¶‰èàÛ^xÝÈ]ÈÁëyüûÀ•t¢•Ò•~Í0ÍüEêže9ÙrÜ{VÁÝ)§éüMGo ßwÁ^~Û¿“ËÙ·ôL3Sä>µ`.}ð­\›žƒ,.}q}S.^i«¢ ¤ìi(´årwÄn˜Àý3â Ä_sGìÜÝÿ_¯øH¯Áký/ê—mãöÂÚvÿM¶“ü‰ ØËÓl5àŸ­Ù¡ù.ÐýžÏÈHû^€öNX\æyíó}m³káÚv•}.uD÷wR$”°xB X¾—Ï»àßEõ£,úm ôOxÈ„>8*Š‚í”!ݳoožýúö‡™ endstream endobj 2 0 obj << /Type /ObjStm /N 100 /First 794 /Length 1701 /Filter /FlateDecode >> stream xÚ­XÛnÛF}×WÌc\î[»n ¤qá½~ ©µÌD&]^Òäï{†¢T)ŽlÚMƒËݹž9Ë•¤”,é”K¼%™RP$5IåIüÇF©Ô’¤Œ™)EÊáõñp¤#HgŽ-š4#­ÉX—¤=™€GF$küÌ(²N²w‹5XpRAŒ/ . iM.hH“O!æÉD‘w,MY*gNQ†°œ¥ÌbÒQ–Y(!“J`Ék ˜ôH#EZ)¥ðã3<=¬H’ø7Ë»4vðÌðt!eO«(¤ Œ#$µ”`O«Œìi`Oܺ4›Éb`ñgôSØ4`ÔpÉ–ñfÜ­åìÚ€uÆÞ)À²³&^\ffÞs`ÐÊ*?4J‚èd0?¬‡Œ³(Ï J¡ŠSÖ”V° h•v W5Dì@‰J*ÃÜ0\u͉óÀ³0*ïçŠxÆö2 Ðɼ‚]x CR ìМ¦'Íò¨iÅ̳ † ´£$Ê« ŒJiçá,ÐhÁ» j:㨘a£)MÊuAFráx¨ÀIÀFFkhƒ`&4À9»@e0ÓZ7{õŠÄ;?Õç5‰#zÑÆ¢+ë*‘/é‡f/Nª®©çý0÷r¯°Z ÿ†×º¡úê=íWÄû«ÆÚÁAWß–­T÷è쨭Ggïx±ëÊj1Ew ô°¾½*+è<ů^龩ë;Ö¬?Æf­Ny5Ç4hu“,š•ų¾¢7±Zt7ôcUÔó½¹lTÇ4Þ”íG¬yª¯éQÐGÝ1壼Ëé<¿ZÆdÍNYªªîr^x@ÅåÕ">Ì»ÎämÝÜæË²ûüˆ¸ú"ñ•I µëìÇð~üÔ5ù¾}°­6q\V\I:O–ùÝÀ™I)Ú5Gûª{–·ÀÛX.n®êf²¾_éŸ7yÕ^èÇwt7ûzþ¾o‡øÛ.oºö;ŠÕ|µQþ)çÝÍ$[cù~É?°¡fU¼yÙ¾¯Ëª›b`,áiwƒÍÚ­ÚËËmål¥ú.vtz›Ç¸ìvÈò[ÿyØ[uØÄ|ÀiŠÎÈÁbÑÄÅÃj£ŽßÚÂuµ¿Ž£ø˜õɸQÊŠ^—õ²^”E¾¤wñï>VEÄîΗŸÛò;a^Ûâ•Nª î÷t.ø OéŒÄqÙ]²Ú«W3qþù.’ø5_Ä™8¬«.VØÁèPXr&Îb[÷MÛáЦ~‰ó2]¢ žàîÊu9ƒ‰º8Ãõ 7šßvûÇŸ‘ÓIÆmW‚#·ê—Ë˽‚fLvíqIëBb&ÙÔ!$JN±‰v,ÉÂ61²Çèy¤2#¢hjÐÎ/Ü¡ÛWüÐù®^Р·[ÑyHµ®ˆå&*]¿pk%Ç74„à B¿6uÁ{åE;:&q?u´‰îëÕÔî^5µyn5µXÍÁ¡FÞ'iÐ$MÐI@»9AқĠE i¦œä]ãpp“$%>/èò—ÔÁ%׉=\Ú©ø¶Ãm´Îîób‡KÏ%‰ñ÷HbìsIbÜD’ì®72Ðx\ׄïOFtŽòl;«ï!jå“C{×Â+_X8–ËÕqVW8p"½8ú^¥|óÃÍ2U^e/ᢞï];/»%VÎè§&¿»)‹–Nûî®ÇQωâ‚S«zhG_5O½Ü͘ហ\ ºá•'åL¼Íoy £×y‡’ˆ¿ò»ë#£Wy×>Á†Ú¶ñs\~ŒNÈ™X÷ïÃnäÞ…89*¯¯cÃÇ/ãn¬@_Ö·œø»¯»¸Œ×ßXż†8uÅ¢É?F‘}EQ6E{½ŒŸDW.çQÜæESW⪉J^(°˜—pƒ]$¨ï<^ îEV,—ùfò¦¯yÓß.ó¾õ¢®âQäl¯½Ë‹øý®l!ù¦¬> Ûº™Çf ™¼?‹qxÁ¥—LÌŒ–8S¾§Ø¨).ç©KRÅÇŸIœaVЗíÇu¹è›8¶V[»Ôª‰û~[Pf> ž³q‰Ï²‡…‡½›’¦{¿¦;›zÿÁº÷k:ü¬à¾þiýãt¸Ó ŽNnùô}$œ½÷‘pú¹Ÿ]g&ÀÿÔSç[]¸Ÿ±vÆÙDÂí®ú zû ’Ú„$(õ QÜé w¨·Eʇñýj…rS endstream endobj 173 0 obj << /Length 2202 /Filter /FlateDecode >> stream xÚíZÝo¹Ï_!ô^VÀ‰Y.Éý8\ ¤E¤úSï% Êjí¸‘-wWŽãþõ/rIie+N¶è=È»KÉßü83’þóòÉÓõ¬QMY”³åÙ¬jTeí¬lrU5z¶\ÏÞdφùÂu¶›ëìü:þl7ð¾àÔ¯;x›k{Ï øíä¹½bÕûù¢(³í¼¨²Oø‡zª²{¥ÒÛáÇh¬nþnù×§/œêʲb–3¶×óÂe¥³W¦†±bÆ©<×¾Ùö‹ñõ¢îþ Êm¸âÖëôA`c%ªTe-¼m¸¿ŽzšŽ\þ vv ¿ë ¶=ÊŒÞ^áðG”(jš Ä y^O Õ(¤þ‚Üâ@ ”œ-¬µ*of ­UãË\÷sWd°7P°>™Ý²P¦t~H5_8—gÏŽ@kʯ#ÁBnz&ˆfL&¾Wø¨³‹ÎoHºçNËX]ÍhVÃêh 1íaÇÝïÈ‚iÀA¬dÛwc÷H3‡ˆzìèN:»:çQ~Ù‘ X×ÎkSû9ç~¹Ó)’UWåIP~+ pªhìä¬@9·ÚöÒ‘FÄàgçǹì@íÚ«Uľd€Š<›´^³Ð uÉ’ž3¬øÈa$¯S(¿j±ö#KnÏøyKûæ>jÄ ¦fï±O,^}ZQ7ЧAKqâ«õ:•Ì0§Ù[mì@.ƒà7£hÂÁ`¬<ßqn qvô‘³êˆ YÑ+þHb½Í^‡Á+½h%ž  ßù7ºV°“˜ØÌ¦ŸŸ–µ—ÜDg³„¡hߤíD¨×šdЬÁg;7L6bðƒÂìm È›+/êws6o’íEøqEŽÝ± ΡMçDÑïießúõý‚fIšÅñ¿']+"¿ÂRpö}Ó¢òÖ”¿MEûÛÇÇ „AccxZ3¬•P´½ŽHÔ©§½H¼V3Ä2`a¬SÎêt:h…òÑÁ§FÁQQ–Jû²°fXË3¹)Y Y©…MÀ­öã /4Ú²è@|®Ò¢’gì%(xK.|§çÒmÏm‘Œía—­×fµëÆÊò>ŒQQ,š$–‚#ˆc ¯ÍÒà¼Ä¥o¼í£Q¼ÛÁþˆIKy÷Q"Åà"ÛsNIÞ0¥I(“ påt´ŽSfEÕýœÓ„m&¼¦d…QÞ“Ì™ð®%k},X¶Ðظ džd Ñ5Sô'è¨ÀŒ–‡=«”Äí¥l×v‚:ñ3Iê):ôˆ½ñÎ$PpŠO›x¯ˆXdlý~äšûýˆDþÈ%Lèìïð{ÛßbüMd^ÑïT¶Ú=jö©Ð,ö3íÞéõ ‰Dý?' aæõ«4 ™·t ìÜ% îîipŒ“Õ{pšO×—FÜR¢W¿!º’V²VaU1…ù Ô¿¡ý¤&’ðùŽ~Ô&ÿ^Ñ\¿Û¸°q÷ÇÆIÎ;<`ÝŹó~q,|%Ïê/ÄÓ9ú=üþW#Àë‡ÑÐéÔO,“·ÍTuqÔ€ƒ•&;#®ôY<´¿]{ѽp³<×Q‹»8´ ohuÖÙOðsðˣ߻1vÜŸ„%#ñ阧 ÇÄøoá${ºÁW§ß(?DýÎò?±X<Œó{Dý-|iÞ‡E¦¡d„þ/©èÏã©’FLµ¦'az/Æ¿ Š÷òêkµ¾™6…8 jÔÈ{q¯Fɱ‘œ.Ç=.ãCà2=,ÇsÐéÅóðbݨ:G—ÓÇE…• X:¿é¥S<Ù·MrIŸá*¤òçp=w@— 6ÜŽòõEtMh›pMR«ÉãN`¡—”¿Î«’O6£ ˆÃóî 'E‹ý£öšïî¤]rô@@®ÄéŠÒ…cI;‰0‡÷ñ,û¾(]©2·'áò÷¾ºTµ1©Ã2\º´¬ÂJ$·¤ ]¾t”òKôR4õá£n¾Ñ±#“Ðv¼°Ô…£³×Ü\R¤öY+7þ÷@-—‘±z;4ÞI©Êø¬üˆfRÄ@öÞ€ùV‚žãEk²Û¦:<&á–{–ËÓ•O.0“WV•nï jâ0ºÅ“«I¾24|<ÎÔ£Š½^¢;ìäJ÷§“¡Í¾¿yp÷y‰$¡ijr*ÚבåÂÇÓ—+뙄£•ÃÿÊ0µÒ®`¸Ê=y¾|òo7ù‹ endstream endobj 179 0 obj << /Length 1644 /Filter /FlateDecode >> stream xÚíYKÛ6¾çW=r³bHФ¤ ) EdÓ69hm¯ãÀ­µNvÿ}9Ã!õ0íµ7¯È–L ‡ß<8œ!?½÷à©6ƒ’•FšÁéÅÀ(V LÉY^ŠÁéxp–̆"YÚveÛĶ)=×¶¥¶½´mŽ}©–Y²²¯îuN”KÞ¹OÚ¾òаë£}u©”}•¶åî/̸!~õðíéóàL©A*+µvp_D'…"y8LW¹å'’ÂÍ,y©Aý’M?Ì+l.±u>1ÛåZè¾å °9A6òß–AEZÜüÚñHãxÏžÿ=XBç%ð$^Óü4à=xZ´B1Í­Š¥Å+r‡÷9ᬯ†©Ê,öÚ=?¶ÌÿWë1ÙtYínw£Zìç¬PV#Èù¥£Ð] –Û7¢Íjœg ª(˜(KO¹:·ºPÉ{ÐæPÕ'îYÁ¸~Ì‹yJŒ{Î Ï$´ÄÚ·¼yW§Çxµüì^m÷~‡U¾‚ q¹!Û9c¬¬É3Ui‘º÷9²Äw¯xïj{|FÐÕzf£¥×:2D/M—ä«È¸qm$÷¢¬q¥¡Ò««†Å‡¡6ئé9¯ê;/²D3ŠW6ÈÓµIÄÇM‘¶‹®qƒ,܈ßÜ.\£šý†B’ÓÎì]{Aýo¸æDºm©ð‚özúÏ+´„ ×ɉ›Ü3®È-ᑯ™1¢+ņð¸dÏeHq‘p áñðë€ kw»CtËIœÒ1A™H»ŸÄ­þ¢ÉV:–H)%ü*æ€ÏÏZéñ Pé¿ü®Í¡Ž4‡þÖæ}sä_ÚfÛ9ª÷ps½¹ÍydzVY¶L0j'_+H4ò-V_/šŸ ]qôÖñ:¥š÷5Šyè^ðý©wô¿Qo¯Ð)ûå5Ì9o°¥™P®¾ûL¬ZÇŠOeK±¯ø´‡•ž9ã™8²ô46ª„"âñPjÔëjáýb_5ª¥­[÷ÔºN ®æ„ÔÕ„‚ú÷e¤EÎT²À¿B¼Š•Ûy Sòš „ )‹ð•:¨è~D$Ö¤´±*T³2rì," ¼‰C™ü¼CX-Û\J+yð‹?ÉóR·XJŸ¸«šüâžFdu›Ò²‚ýK™rÄ$gEqˆä¶ ±µG®»©CWÑs$Y2%ÊcÔ E@¿&5øÓ¿q„¿a‚ïõÃxã×¾’œ¶Ž .n+´özD©ÜWuA­"ÅÇj®’æŽZY„RóÎÑцyýÉœê zœÓ¶.Ó,“¶žŒøXŸ‘ÍÞä‹Ö~5‰ƒF­ŠãÔ*›} ÆãbKGÏv(¡Ã•€ ˜¢‹o.éßdÙ>^Õ˜ÛEò¹ÌäÌØ}0–r\wçû8’üŠgøøº›²“y´Éh÷—8_iê'x,ºsl/E蟃7Ÿ[„›OáæN"`¢ä·çJ·0:ìîEÆÐºseŸ‰A‹5»Ñvòzç« Ñ©eúm×Õ û˜|èo.n»&ÇÝAIÕ¾'2¢ í{"ßõ_AD¤të‚ç¶e#¢ûý—Dðxj{“c¼ÂìÙ¡êfÔŸ´Ãô%&qÇÎd7ŸK!ºŽ*8jã¨çìõ2|ꎹӷ»ká‡sî:Xw݇ï²Ým§¼6;Õ¼رŒVGT÷žœÞû‡ÞW endstream endobj 183 0 obj << /Length 804 /Filter /FlateDecode >> stream xÚíXMÚ0½ï¯È¤ÅµØIV+•Zi«=µ¨—íX¤… ꢶÿ½¶gÇ!°¡%—–Ã(¶ß¼¿Þ®Þ}2HI*¹ FÓ@F$ dJIœ²`ô<ô>÷YïEY¦ì^Ù\Y¡lÓöru;…[;k©lff°Þ3 ñþãèS@ƒc$Ô¸6¦ìÑXu’„IsÜ ø ¯keeŽÞ t´GzÐÌ”ïjmUªL(‹Ñ¨¹šaÍh‹þ  £$Šü˜ïIAFoGÃ&@„‰X§SÞ÷šÑ(6¬Bj„I ᑨ[0˜%jiî+Â…Öœ6mçW50ÆÝØb˜¬»A˜JHmŸ›8FÓàvðXm[òFŠK²µÝ6¿%Š&ýXÕv®&Ì·4Ü w¿8þN¼ýó1¶‡QtU«M*­¶Ô#%ÌF0w°Pö ‡WOi­#åŸpÙ°Î8cHµz*PŸ¥kÚåVY= ¼Oú¥GÕ”°ˆ¤õ”|Ñ„µX'ªÀB–‚Í (:ýn¬_æ ØÞèxç껀wÆ,]—µe¦ºœóFUIF¢8Q€âq©Û'IC;óZ#'ŽìN?óÞd¼DÆš`‘ÃöŠY‘¹ Ô÷ò2^β-ôÉGòeÃαX’8f–•-ü' Õ²BÓÎvûa J`ŒB©5.!•:ùÚÖtÚˆ3RæWgV:^˜¹«g+ÅEaJk¿DèÁê£× sï^aÊ­éÍævZiŠÔÃÃ_úõeÔoý€Ë½àœ—­³QErĸʸpGȱ1¨‡ñ«©þñ-/A5…»Šo¿WÀ1yÝfÚ6’»#þñ·¦ðŽÒVß'gý*?ªôQÃN¸F ŠNPe'¨q'¨I'H;ájæó!»¥†Á[”]ŠF]›ÌÑEæ7Æ [KVa¥›Â°õqB œ\Zà¥^Zà¥þ¿-ðÜ_¬ù¾ãmñÄüû?YxÈÔo–4„œà?=æ««£«ßxt… endstream endobj 187 0 obj << /Length 3190 /Filter /FlateDecode >> stream xÚ½ZYãÆ~÷¯˜§€BF4»ÙÝ$ØÀ»ˆƒÖçÁñWâÌ*+‰c#¯}êꃇvv'FfD6»««ëüªÈ¿Ü}õõSÝ(“—Æé›»ûgòúÆ5E^5êæn}ócV.–Ji“}Û.Tvj˲2ÙÝ¢1Yûn CÝqñÓÝß¾~Sß4yã´C*ÅÍR«¼.j&q·¨Ë¬‡•e™} Kúox‰5ÉšÒ䦄•´gµ§önQU° ÜÐNÓ ° ŒÊªÛ²./ªjDö ’=,¬ÎÚݺuÞÄe/¦«²¿oàß%7ÝÄÙ¼.õgoòý# éžÛO6ªT¢óÒ©›e©óFWLÕˆzX4eÖ­N¨ž+ùÕ~߳Α}ØïöÏ«ûŸ0íþ$ í–)²Ë{¼Ç›²Éú}Ç£8ØùºåŸU¿õê^ù}‘'¡ÓßËï»ÅÒšì?4ï$2¾ÅgšÖÐvâæ³Òöø°[3GtlG¹Ê¶íj¡k D³w]Ó!B[ÁY“7 ׸ñ8Ô݃wx™Á)ýv+Z%gÑ¢4•ÊkYš"øž±ß!‘Rg—…ßÀµÉòÅÒtLÅOÄÝ> m<êZc$C °ëø@ 9tËW힟ãªL¶ˆ¥bù®ù‘¬mgŒXÛ*/ŠàÚ?,* -é·'qML LTÛÆ¯ñÚâ¢VWéªÁJ-S(ЦÉþ,UfF-:V¦óÐP0¾¥Ý¬ØVœ…†J¿øcÙ¢ÉX»oKW8&#††gl‡7žÒ^u¨ÔcG¢á§MœJ%ñ¶ ñ‰HÞ%È[•Cû$'{D-vþ${´ÖbG±#±å×­Ù¸I¼û8c< 4«Š$)^ §ª„S‘ü9VpÖJk±ÇÏôu Ñ•[%‚·ÄöZÜö ñç·[žÑyïÞAЃ0Â!Š¡ûšBpÆÀ£lâÚ“"~䱘Î÷&…ÃÄa;>ÉŒU5 ×&5*ŠTg¿®óÚTW ‰äoŠ:WÊMæß…-æ¶Ïkç¾d÷&w1®Ii¨³†úÃŒQ—»JOœeJøb Ƨ~‹Ý]IzU *° GR¸%¤—ýš÷ÞD6¢€f}ÄJ*´j6Š*àq<ê¼lô•8Jü¢2Õ cÔ‘‘}<Êž…ÈxÕñ0fŽ ª"í ôŒÂÔ%«q¿ò!â$‰PsB;sž\m °Ìt)”GRh Þ7öE‰@ßàYUö@i³˜•xYæ¶p_ ­ÎUÜlâØd(*“}ïÞ/T °côW䯏h\ÕUkλ¤Y²€~@±ÂÞÃ{6ONt\º\—c£ºŠ:â¸æL€t¶H¢¨rMöNŽ‚çþ†xðæñ¾#_¡'ý>îe ͤ{¸Jƒ.>æûÃ9À]>С1Îîr Ja{š}°;Ã7Š äâûHû^„Ó…g·Ýusèn˰$Îk(úLáwþG–ÑÄöوʹëv iÉ^GÔ (ƒ%\¸" óUú:cª€tm_b³N©«6[!l@!õ'U»TD"iŒÛ+ØþÉ´û¡©Áœijf,iUn†Êñ@ùêq!ÿ™ê·E¶ùléVÛÜ•õ°r³×+··-·›Ï›£rí_Þá0$Œ¥øÞ¢>þ:ðRÇèîç³·YFOUâc@â  A øBœ3‰".ÐŽ~Ê:B—R‰„R=oy[Ð6ù¹ñùàXäƒbÐ;šó³´„qŒÁ¥ÉÞPwBHv¿¯>z[•à PÓØ‡[N…²±è‘Z¬gÏBkͱª²R îAJÅæ e;€Ô´{çôK·ÑQ‰8X¿%T™»MŠ„S'`„´gM:nº}”Ó¶žWX°|Ø“7zm¢"u×°íƒÃzµ7s’†Ÿֱߞ}ÌtªÉ^ñÓmìnÒ=®A<¶Ì%‰h%J¬ a€³H11ó³´ßE^K¸§%=ÃHLM*†Ð| Oé üuháO!žrQCŠÇJÚñ¦”ŽWµìñ[¬þ[n¡îyš7M¼þdó;£WOqd"CÿÑhðFx&´ÌÀ = dãû–bB8Zq5—i‹à*†X¤/¼¹¹Oú@üsÙH¡NVz+½!éIwñ° ,ÃË_dÕ¡ boõØ#í‰SÙï¦Í]šÜU¹^ZKâ2æÄûóˆ$ ;êy PV¥Ò8ôkz„êyuãræm&A—סµ÷Ìz» BþA²ÿ ,!iuZ×EÖù>/mwðuÿC'û >ºumÚ˨¤—QI¿îûp Ç”¤ëÍÕ‡m òOòÐc¿3k~›°t?Ÿ”cÚÕÃä«W´3è>S}²cCS\æßÆOq: >Kä…¡Ü`í$Ä`wÐÇZöt(GÛmx_"»H†Aj¡ ;´²{Ë·5FJ£2ÓØ(L^©‘ìOT·x¹žyseª¼²iC8‹±‡bñ‘ù„ú`šqvî HÒ.{`¼‡¨FÉhtm³]<ñÕªÇæÌŽvÛ~ä1JßTð&&˜Q65K˜éæÛP\ÆÆü³ âK*®õ|šÜ–Õ Ü7yW¹Ô(Ñ{1žú(…‰dÚ úÚp›xî9×Ñúðz¶ý[¨T«²™é i5éó *F:}ðý­&MœcÒ-à £—&V’1»•ô«ÚÙÀؘÜÔÍŠ¶Î£™o¸,!ŽÆ·ÜE»øÂDû"iËǼú§Q¹ÒCfÄ„(\ç¨É«Øœ‚]„öÖÇ!Î! Éeé°ån‡ˆ@õa'§`ÜZhßN!Ål¤ãŠ_ *ƒk*ÙÇ‹ئaPU“ú ^®àîš•IëMsQC¬vü0´Z†Ô/ñM‰n² ²Þ[îÃux6¹¾ø‚Û7Ý`Lúœf_ŽÔ6­ýÞ (¢Gîëâò몔Öïô=B‘×up_Á…üîĺ¼¨GÁp×û·Ú€h¼”ïip7Ì©¡ÓÌgu€Ò7¦†ì«Ëpßþ.—|ùÌ©Š)xŠ D\ù'þQ¤(E¿çA«Ë€²UŒÉB/¿1¼±¯ÿoìw Ž'»åKØýôοtÝ„Ýu²ó)äft™‹vX‰º‘hôw/&­§¤Ë‡ \—ž’ÆéÂÛOLà \¾BÀßÃßëy‡! õŒ _ ¾U¼L„TÇK5Ã[;¼mâm9œlD±âÿ·s6øûÅRÙJ=c"#6¡»Ù˛ɓdiY›ˆ#Y¿òMCǯÎK7€-xë_Øc’ ½4˜¾j·I“ʹI¾ôݘ;¬…JÎ|1h@9503—M’€¦‡ò/èfTOàk *’Cæø~ $ç’É‚jY‰A<áÜ0Wˆ|ü›>KE1BtŸúr@áw!áÌÓ`:}wïÒÏ:ngH¾}‹ñnúÙ~ªp]›ÌrØä¥­Æå}´û¹¯ L`Ñ¿ò g©÷á æÜ0l¾J>†ˆíÕá +ù¤‹aKú¶=ˆ=?[:i#¥ó=¶cÄÒ?¡–×£4g£qÞ¡Q|ä‰É;Ô¹o4àÃ&~’ñ¹eNaö°‘·¸‰Îa(+ÊÜ5Í,T™ZØ$E<“ êI.PTªJ~ë4'Á-‰¿IìMâîÔŽÀ …ïî l$)šøÕ뻯þ ™Ö7£ endstream endobj 194 0 obj << /Length 1209 /Filter /FlateDecode >> stream xÚíXKÛ6¾ï¯0ö9±"%ê4=H€- (|Krm­ãƶœ•\oPô¿wÈŠÔÓÞ —9h5"çñqžô¾]Üüô^¦³Œe±ˆg‹‡Y±tgK2>[¬g¼_澡W̹w€g ÏÇ@ðÚÂóˆŸ|þiñ+¨ŠUÁÌœñ B=€“Ãó õ)RX2´d†¤h“’!ÉȘì¦ãv ÿ™+ü5<ŸÿÛsÀvhš·Ù’-Ú !7XEdL¢±÷ó4òÊGB¹Ü)K à4ß=˜úc.¹—6@ª`U} aÆd˜™ÃéG"òªr_ UçCV“24È"0O•, „Y£ftú_s)½¼n¾DêP¯ ø¨:½TZ‹š¢¶¥,Ü(°RVˆ;ß)É×y:ŸãÜ18°&|kR½T¶¾¡äAÑÊÔ¾¶"rÏN©Þè|§Ž8óy*XÀ9œe’Â¥á­í6œ¡wï' ½M±d¶Ç–äîݧwúŒ%¢“Â÷©00‰)4ú«Æ‰†xê='íUY˜ošÃÉ4\(q¸ £ÒQè¡8Î:ò/ÕzqEþ-\å9¾TvœL Ô¨¯õ¨o5®7…52êý¡‚¦H XIp¢3«vï#Ù`Ô÷{-*iFÆUH<‘ŵǥ7v‡˜ödœÊÊaZ”£ÓÙ+Z#caZ:clKk66=ʚ׫¡Vz9(d"õ1KŒ ƒë– î—âúÏ­=TÕ@wFC“-1çgÀÅú÷T™ÐÅ™¿¡î\÷BȧTlív¦Õöž gs„ÛÑ B—¸˜–w4Ô’ÅA¾²0öÎuÜIƒ‘Lt7ü­|²r?;§UMDO»wéÀî×Úq÷Ÿ”u†[æmKºt?áûë|ÓvÄÈ©íõïÎ6à+ÏÝm6ŒL(Sgkæ{Ôœ§¬iï|1_T &S`Ù÷¹:ðKË1QuwÝFðÜ|ùFÌk¢ûµ1Y/[uÜéFm¼lŠq¸”5ôGXµÓíºLô).F9’—¸gê½ÆWNJõç„]}n»×^tgÙ®=ÇÚ3ó²*“؆Î/ÌÞw_#&þÛåÞW„ÈXÀS¸ r&¢ qÍxónqó/ò)l„ endstream endobj 199 0 obj << /Length 2080 /Filter /FlateDecode >> stream xÚ¥X[Û¸~ϯ𣠬ñ*i è¢ ¢X´é }ØÝ,Ï8±¥‰eïtþ}Ï4•‘³›ƒ1)^Ïõ;‡Ô«þôJ×ZÕ« ­*K»êŽo>¿QÞéPÑ|Ö¥)-»dàíû£Yýy|óø‹S¦¸ÉHþp÷æí»zÕ¨&˜°ºÛ­Œ©” ÍÊ7Z•µ_ÝmW?ïÖºØÃÿÃå¿ýzc­-Ì÷ës¶ø; à<óø¸ÃÖã)îÚðÛxGÛᡇfRë_îþúæ/w‰CfÐÕ¥ úØÞ’øJqAà *VÎ×*4æ+Ûߘ–náçÒqoYÞ·ï\µÒZ5Þd`£|Û(o™Ë•^o´6®øq„¯Ó áÑÈØymuñÂäriJYÙZ3™"›Çþ,≋ï€1]Lº–ºw\ÒõŽ´Èû #‰»®Øa—Ù9®+Hü'ä;ÒÖ¦Šg´ÜL¿GòýgT-#} [ÏÐÄÑS/]Oîñ¸Oît]œ…é6Z Öо=Ó¸.¶²nùæ–Ná]¬P'iŒÃ|bN`–VÿŠÇ’‘8ôÿt À"ðošÕjêÕŠ]TÑ¡ í„ããë—\â!» 9 ŠÚM]Q÷Q 9|²;n[öïrǶÁ¡HkŽˆN-J™^»uÊš´e¼_o¼+>’KˆLíO$¦ÈÈIï‹gä°sàºaäVL—yEÒM›-'U?‘²°ÇÜ’aÀ¢^Ù&ÌíCUqfUØŠö€ØÄ#ƒÄ­'8õsd @¢£š÷â=ïB’¿®…§ÓË‚²uíTpÕ·)Û+ß47”Mu֑‘‡%û J ük]š×Þˆúx}¨Íb…ß“„Þ³Æù =˜°Åcâb`Ýí1Ÿ²¶§wóÐ"OE|Ç´e£,À "÷ ±[6Ä8ž`Ë#\ Ôt×1z^4µÇ럜K4<ð²ÝxâN{àТ½ŒÔ å#|ñ)D2Xšbçç·gÙ“¹œÉ§•÷ A#°,ŒG¥t$8üçËÑ„óV˜|Þ #Lž3& ¥þ?²›ÏJ;Õ87_}ÇÚ\€ É(9×$(c>ü¼ÿ€~ií¶wWFi8DöwB>VƒsѲHSlB8è\™å‘»9bà’>×JâÁ–›ÅC9Mö²ò ¶™Ÿàܘ“ÒÜxjÇ-›/ê—Òúibô¨B(~xaW×%TÖÎuM¾ùs©Òˆ"H2ÃÒ¹Ø|ÈJy…ÄM“’6L#í~Ëã1Søøà^U¥ªL2Ï›w)+„mŒðÕ‡ó•Ó+ÆÛ±pF~.}ÙÂæÍ‹±OIý錊}á\,êQHó-”SçXȲÇ}ƒÁj¦Ä!&Ù yÏEœì ¹¤Ä\âçö¡`ÛF×"Fuñ W•‘{øg ¬¯’Ø…IäïèÅO 町¥ñ”€‹ GÂ9Gþ d´“Š ¾Ïha_©Æ~$ŸÄ#BÒÝv™Ó^´…l‘ÏþØv ÑÂÜ=û¸×õÕT¡ÁºcTð$£ß1unÄ €5·=ÖÌ 9êܧJ€¦ŸI½‘s¼ƒpC ;P¸v—,®’[X;óM1í*†¥.q¾I5 öI~ú–Š63/ÞB* ˜É'Úª?`Š`ZÒVò  årWål½§Lñ»€Ø–áf™±šm­ÙeŘÓÁv—–Õ—€/ÊÓràKpM ËžD ËáV7*Ôõv¿ÄÖP)­OLc;n÷yFŽ©Ú$IŒ8¿l8_»“æÌüÔvóÙgãÍî9²#2 @ý.âø§9Ã'®éR%LƲÉ Ãv‘áKÌ)™Å+ìŒx5¯0Ãô·î39b[›ª‘äâ,#1¯°æ9VÄŠøÈ‘IÎ{|~æÇ^cÔjâzçwV"aÊø”®tìgÝu×—9+U/œ—!z|ʸx;'RvÕÄ;;úRßXe\3/óÙm¿v§ªê[e>136ž¼Tå—pOø? 1|È1qÿ}‚YKTäRè PöQ»ÃVâžïñé=ƒýYÞ3|~”˪|Æ­ l÷Œ?‚ÔÆÞ0žÎ3Í)æÅ׎€®Ü(]ÊãÆ{XùAEæW-:k¤ûu2WqéHS–ü\¬®õ<L²°¦Î¼!ÒÙò糰ʆX_dÅÁB|…ÿ_$tSàóNé*Hbºh`¬„û3÷â7ÙŒ -ôÀ¾¢æÖf›mÆ´”ÍØ²¹Z°gTº™2þ(b/Û!ö[ìž›þR¬@0y›¿‘y#ûÛ^N¤7¡ŠÀ—Hrd$ªZ•:©³kú´t¨Ãç4“‡/d]¾#ž—n£MPnþ÷£§ñ)ÿ@·1þŽ„DO ¹˜¢›@Õ|9¤‡¸1Þ˜Ò5uÏàÊóQò/(àBRÚoC.¯àF³rã=g·ß&ð-&Û!"ÕK¬x&|h±ñ è"™Ûé2æÕåÛJs5>½°|û :™5ÙRûDµÙƒT&<ʸð•‹Z–¦ñx}žf/U]Lä\x'ö+âWèPK8þ)/{0Õ^/¶´2UÖ‡˜¸(ðïë¶k™o}î«n?@I®†k¯Ò5ø³iÓj^¬M|ºÿ/©Êl endstream endobj 191 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./IRangesOverview-ir-plotRanges.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 204 0 R /BBox [0 0 432 162] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 205 0 R/F3 206 0 R>> /ExtGState << >>/ColorSpace << /sRGB 207 0 R >>>> /Length 338 /Filter /FlateDecode >> stream xœ¥“OK1Åïù益13ùmQ¡ P»àAÔÃ#4žc’¿…â²7ÊGFä¢%/ð¤C©U1ÏX endstream endobj 209 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xœ–wTSهϽ7½P’Š”ÐkhRH ½H‘.*1 JÀ"6DTpDQ‘¦2(à€£C‘±"Š…Q±ëDÔqp–Id­ß¼yïÍ›ß÷~kŸ½ÏÝgï}ÖºüƒÂLX € ¡Xáçň‹g` ðlàp³³BøF™|ØŒl™ø½º ùû*Ó?ŒÁÿŸ”¹Y"1P˜ŒçòøÙ\É8=Wœ%·Oɘ¶4MÎ0JÎ"Y‚2V“sò,[|ö™e9ó2„<ËsÎâeðäÜ'ã9¾Œ‘`çø¹2¾&cƒtI†@Æoä±|N6(’Ü.æsSdl-c’(2‚-ãyàHÉ_ðÒ/XÌÏËÅÎÌZ.$§ˆ&\S†“‹áÏÏMç‹ÅÌ07#â1Ø™YárfÏüYym²";Ø8980m-m¾(Ô]ü›’÷v–^„îDøÃöW~™ °¦eµÙú‡mi]ëP»ý‡Í`/в¾u}qº|^RÄâ,g+«ÜÜ\KŸk)/èïúŸC_|ÏR¾Ýïåaxó“8’t1C^7nfz¦DÄÈÎâpù 柇øþuü$¾ˆ/”ED˦L L–µ[Ȉ™B†@øŸšøÃþ¤Ù¹–‰ÚøЖX¥!@~(* {d+Ðï} ÆGù͋љ˜ûÏ‚þ}W¸LþÈ$ŽcGD2¸QÎìšüZ4 E@ê@èÀ¶À¸àA(ˆq`1à‚D €µ ”‚­`'¨u 4ƒ6ptcà48.Ë`ÜR0ž€)ð Ì@„…ÈR‡t CȲ…XäCP”%CBH@ë R¨ª†ê¡fè[è(tº C· Qhúz#0 ¦ÁZ°l³`O8Ž„ÁÉð28.‚·À•p|î„O×àX ?§€:¢‹0ÂFB‘x$ !«¤i@Ú¤¹ŠH‘§È[EE1PL” Ê…⢖¡V¡6£ªQP¨>ÔUÔ(j õMFk¢ÍÑÎèt,:‹.FW ›Ðè³èô8úƒ¡cŒ1ŽL&³³³ÓŽ9…ÆŒa¦±X¬:ÖëŠ År°bl1¶ {{{;Ž}ƒ#âtp¶8_\¡8áú"ãEy‹.,ÖXœ¾øøÅ%œ%Gщ1‰-‰ï9¡œÎôÒ€¥µK§¸lî.îžoo’ïÊ/çO$¹&•'=JvMÞž<™âžR‘òTÀT ž§ú§Ö¥¾N MÛŸö)=&½=—‘˜qTH¦ û2µ3ó2‡³Ì³Š³¤Ëœ—í\6% 5eCÙ‹²»Å4ÙÏÔ€ÄD²^2šã–S“ó&7:÷Hžrž0o`¹ÙòMË'ò}ó¿^ZÁ]Ñ[ [°¶`t¥çÊúUЪ¥«zWë¯.Z=¾Æo͵„µik(´.,/|¹.f]O‘VÑš¢±õ~ë[‹ŠEÅ76¸l¨ÛˆÚ(Ø8¸iMKx%K­K+Jßoæn¾ø•ÍW•_}Ú’´e°Ì¡lÏVÌVáÖëÛÜ·(W.Ï/Û²½scGÉŽ—;—ì¼PaWQ·‹°K²KZ\Ù]ePµµê}uJõHWM{­fí¦Ú×»y»¯ìñØÓV§UWZ÷n¯`ïÍz¿úΣ†Š}˜}9û6F7öÍúº¹I£©´éÃ~á~éˆ}ÍŽÍÍ-š-e­p«¤uò`ÂÁËßxÓÝÆl«o§·—‡$‡›øíõÃA‡{°Ž´}gø]mµ£¤ê\Þ9Õ•Ò%íŽë>x´·Ç¥§ã{Ëï÷Ó=Vs\åx٠‰¢ŸN柜>•uêééäÓc½Kz=s­/¼oðlÐÙóç|Ïé÷ì?yÞõü± ÎŽ^d]ìºäp©sÀ~ ãû:;‡‡º/;]îž7|âŠû•ÓW½¯ž»píÒÈü‘áëQ×oÞH¸!½É»ùèVú­ç·snÏÜYs}·äžÒ½Šûš÷~4ý±]ê =>ê=:ð`Áƒ;cܱ'?eÿô~¼è!ùaÅ„ÎDó#ÛGÇ&}'/?^øxüIÖ“™§Å?+ÿ\ûÌäÙw¿xü20;5þ\ôüÓ¯›_¨¿ØÿÒîeïtØôýW¯f^—¼Qsà-ëmÿ»˜w3¹ï±ï+?˜~èùôñî§ŒOŸ~÷„óû endstream endobj 196 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./IRangesOverview-ranges-reduce.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 210 0 R /BBox [0 0 432 162] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 211 0 R/F3 212 0 R>> /ExtGState << >>/ColorSpace << /sRGB 213 0 R >>>> /Length 316 /Filter /FlateDecode >> stream xœ¥“AO1…ïýï—±3¶»Wˆšh‚lâA<&1büûvw˲£Ûìë·¯3ûÚ2&`¬±5SláK²ŠèHN…¢@Jò‚Ý x7Wû‡Û{cÉZ‹þ¸_ðxö žïÓlôø4OϰXÆ$=kÃõ¸3¡ aŽ‚B¬’·à4ÕÔg-•’1+ñ)UGâ2Õ’\èÓôgfTýÚüKIT/õê´C«¹,ˆ,‘Ô£Ú`°[-?«ùàu7Q­ÍuÕ”ú_ J¡È;°I{(†,ß0;í ¤¥ì<‰íp–G.Ö×[zàYöxl^;ÞÊ#?i§ëîÈÿ²äå,äF&硱>ruÄök½òÏV–‚¼ëyùs™~¿°\`–®Hì™Ýf§I=³væ©ùª¼/ endstream endobj 215 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xœ–wTSهϽ7½P’Š”ÐkhRH ½H‘.*1 JÀ"6DTpDQ‘¦2(à€£C‘±"Š…Q±ëDÔqp–Id­ß¼yïÍ›ß÷~kŸ½ÏÝgï}ÖºüƒÂLX € ¡Xáçň‹g` ðlàp³³BøF™|ØŒl™ø½º ùû*Ó?ŒÁÿŸ”¹Y"1P˜ŒçòøÙ\É8=Wœ%·Oɘ¶4MÎ0JÎ"Y‚2V“sò,[|ö™e9ó2„<ËsÎâeðäÜ'ã9¾Œ‘`çø¹2¾&cƒtI†@Æoä±|N6(’Ü.æsSdl-c’(2‚-ãyàHÉ_ðÒ/XÌÏËÅÎÌZ.$§ˆ&\S†“‹áÏÏMç‹ÅÌ07#â1Ø™YárfÏüYym²";Ø8980m-m¾(Ô]ü›’÷v–^„îDøÃöW~™ °¦eµÙú‡mi]ëP»ý‡Í`/в¾u}qº|^RÄâ,g+«ÜÜ\KŸk)/èïúŸC_|ÏR¾Ýïåaxó“8’t1C^7nfz¦DÄÈÎâpù 柇øþuü$¾ˆ/”ED˦L L–µ[Ȉ™B†@øŸšøÃþ¤Ù¹–‰ÚøЖX¥!@~(* {d+Ðï} ÆGù͋љ˜ûÏ‚þ}W¸LþÈ$ŽcGD2¸QÎìšüZ4 E@ê@èÀ¶À¸àA(ˆq`1à‚D €µ ”‚­`'¨u 4ƒ6ptcà48.Ë`ÜR0ž€)ð Ì@„…ÈR‡t CȲ…XäCP”%CBH@ë R¨ª†ê¡fè[è(tº C· Qhúz#0 ¦ÁZ°l³`O8Ž„ÁÉð28.‚·À•p|î„O×àX ?§€:¢‹0ÂFB‘x$ !«¤i@Ú¤¹ŠH‘§È[EE1PL” Ê…⢖¡V¡6£ªQP¨>ÔUÔ(j õMFk¢ÍÑÎèt,:‹.FW ›Ðè³èô8úƒ¡cŒ1ŽL&³³³ÓŽ9…ÆŒa¦±X¬:ÖëŠ År°bl1¶ {{{;Ž}ƒ#âtp¶8_\¡8áú"ãEy‹.,ÖXœ¾øøÅ%œ%Gщ1‰-‰ï9¡œÎôÒ€¥µK§¸lî.îžoo’ïÊ/çO$¹&•'=JvMÞž<™âžR‘òTÀT ž§ú§Ö¥¾N MÛŸö)=&½=—‘˜qTH¦ û2µ3ó2‡³Ì³Š³¤Ëœ—í\6% 5eCÙ‹²»Å4ÙÏÔ€ÄD²^2šã–S“ó&7:÷Hžrž0o`¹ÙòMË'ò}ó¿^ZÁ]Ñ[ [°¶`t¥çÊúUЪ¥«zWë¯.Z=¾Æo͵„µik(´.,/|¹.f]O‘VÑš¢±õ~ë[‹ŠEÅ76¸l¨ÛˆÚ(Ø8¸iMKx%K­K+Jßoæn¾ø•ÍW•_}Ú’´e°Ì¡lÏVÌVáÖëÛÜ·(W.Ï/Û²½scGÉŽ—;—ì¼PaWQ·‹°K²KZ\Ù]ePµµê}uJõHWM{­fí¦Ú×»y»¯ìñØÓV§UWZ÷n¯`ïÍz¿úΣ†Š}˜}9û6F7öÍúº¹I£©´éÃ~á~éˆ}ÍŽÍÍ-š-e­p«¤uò`ÂÁËßxÓÝÆl«o§·—‡$‡›øíõÃA‡{°Ž´}gø]mµ£¤ê\Þ9Õ•Ò%íŽë>x´·Ç¥§ã{Ëï÷Ó=Vs\åx٠‰¢ŸN柜>•uêééäÓc½Kz=s­/¼oðlÐÙóç|Ïé÷ì?yÞõü± ÎŽ^d]ìºäp©sÀ~ ãû:;‡‡º/;]îž7|âŠû•ÓW½¯ž»píÒÈü‘áëQ×oÞH¸!½É»ùèVú­ç·snÏÜYs}·äžÒ½Šûš÷~4ý±]ê =>ê=:ð`Áƒ;cܱ'?eÿô~¼è!ùaÅ„ÎDó#ÛGÇ&}'/?^øxüIÖ“™§Å?+ÿ\ûÌäÙw¿xü20;5þ\ôüÓ¯›_¨¿ØÿÒîeïtØôýW¯f^—¼Qsà-ëmÿ»˜w3¹ï±ï+?˜~èùôñî§ŒOŸ~÷„óû endstream endobj 219 0 obj << /Length 1937 /Filter /FlateDecode >> stream xÚ½XIoÛF¾çW¨=Q¨Åp†3\‚¦@[4hŠ #7(hJvÈ¢£Åqþ}ß6äJv=H’oÞ¾|Ã_._¼|SÌʸÌt6»¼™åeœ3ËÊ$ÎK5»\ή¢ËOs­æ/ÿxùÆX«8)ì,a²÷s«¢j ´·D¯¢=üÞ­ñÿÀ»}IVǪ,ÝæzTÕž6-ÒÒÂz,v‡î.Q•êÀ÷ø¾ªç:‡§ü`#‚ïVÛ¹."¡[{\V([Äe‘Ÿ2c¤|jc£´ÛÒ\ÏÖDŸ‘¸¡ÄaÉë{4¤AE`µ¦ÀZtªRöÿV[! E½bŠ»¹¬oæ à‚»÷¨Õl¡ g:Ÿ-”ŠKkY¡ýw‹g€=ˆg¾iœ©3b/2*T62Å*i­¾°´q–·1E­Ù #NªˆMáè*¨Ç ¨ Û²ûêùŽSa¬ DR· VuÍno5;N]¤½1Í CÓ4%9˜÷ΤÚY€¾1†§ÙºÄÛ]ù¤:\¨I*ë†~z’a¦ˆu—L,渧­¤ÍЧ~&š$6‰çRcQZ|©1_X®ÅäJç ‹6чy 5J™q‘æ&úíÑÕaEI)9ÊbŽPZÛŸqŠ©$:|’J‚5Ïá;ö? !7ÃáUsÃ×P}—'ÒçÍaÛ¬œœÃ¨ •X77EÅšŠm¿ÂttÈ# 8­Ž×D_ðŽìá‘‚íCΪ•44àzW¡¹rsM2EÞ‘8-ùõX»«ý¦/×[¾RgÈåæ«4ŒYq/­Vmø zʨ2ú³á:‚vRô‡ Üu¦lù>Ø€!Šnni¨Þ!h@i¦0fк·'–AîPŸ 3”wÛÀi°ïk*ŠÓd¤H>rÃÒ¹v çXA2/÷%U|¡××—;Ð%<||ˆùcKbÌmŽK øÈôÃRí\Î嬨=pÊ¢UåZÚ’ßQªŒiȯK×èVK aZDoo˜Üó Þ†¬à7ûëPDu¢AWŽóTÃb¶R`\sÜ[ÐHN$“Á‹075b1Sôß6QfËW6Õ¡j÷-”v) '8”ˆÌbÙ*¹ âÔ¢ë 2±¨dK¯OÊÔ^[5äðxå ôÏq\E-LØ0o g;㚺FwÜ»–8uÔÎùN˜÷êªÅU÷Ž °P*Ãø‡p…ø„äüÞBG‹væz˜§õî|Úùš/uGhhÚáHä™|ÑMÉÒ{L±¥7B0>$ø”lM†Æ«X1ÿQŒq@âÊÃ@Ó.Áq~Ô¬O€šEOê³@³¬çB‰GËâ…÷/wнÞr_ul5 ŠÄ䈖‚×sï=:dS¿ žñ¤mç¯0¸m\×ä‚Dù¯d_2à“ Ì™z¸™UŽ˜ÉÕúéÚR÷Hz»ào!á"@#ðÍzËm÷áŸþ¢ñ íhE]sï¼ïŽZû³¨ðòSw® 6ÃÀ§ƒN”™:Z·ß”¨×ÊFÂw?3,.3B Tn®J÷¬š|“AÐÑ2½—¶ìànЈðNÝÓ&•ÊØÚgƒÙ¼(§¿„†~± šàÁðyŽ=w@\JõÔrÿ„Ãâ¸ÕV"*vhÒk­kiµÂ¸9}z”T¾3¾xõ½#”­¢ß½î¸ïN¬ŒeTôÙ!s!é“óW7'ÈúWí¨¢CÉ•¥Òϳ4Ü‚Ü)Ðß ÏmHÒsÌ`ƒ9·Á6Øs²Á†L6ôÚž—òÁ†\6¤O<ÅZéa¿6ÜZRˆÍù^ÆoÍÿÜÈjÉZ¿Æª¶Œ¿RY8·ðºnxDëÂïZî°ƒ]ŠÎ G*X0_íøµáºãƳ’ÆÖkzôd…_Ñ úŠìù„Òì]ʳ¡aø˜Àù[å¡îÓÙ=ì@§=î!ÓÍÃ}clDÛ3ô‰\§µ÷›ÕàQ4óD7ÝW´Sòº¶òÖõ g{`Ú}œøÇƒ3gþ”* 51ÄvýJ/GÊ.EÑùMI'âïàNpyêg]³›vÍ ¯ùæJ^]x_þ~èŸ8¦ÈÝç»ît9¤þÏ!Štiµô fÂßV39”Lè±ñÜ4(Ÿû =6<}rÑ1þ*_Ë zxô¾ëŠº7ñ{'}€Y‰*fÐØc£™—¢1òâ·Ëÿ‹È† endstream endobj 224 0 obj << /Length 1785 /Filter /FlateDecode >> stream xÚåXÉnÛF¾û)t¤‹á,’Z Ak =iªžÒh‘–˜H¢JÊu“§Ï¿ 5”(§éµ0d 9ÿ¾Í7R³þÔLå*ÎgN™8IÌlµ»ùë&N­ríKÚRÂ%/^¼ÙÙÙOíÍoðç·,qˆ|½¼yq—ÏŠ¸pÚÍ– ÔÆEjfi¡â$OgËjö>º›«¨Ïú±ƒÿõ|aŒ‰ìËùÂZ½…W[ø´G~ß>à·Ž´Ü¯køêyç eá³aŠrµ‚‡ÇÝ\gÑ£H)q¿®˜`ÕâÖßsG5‰[×ñüÃò—w6›)†¦^(Ä ¬^X´Ú±Õ)pÄn¾PJÛè®ÙW¨~¿ÑYýŠjȧÍܨèÞ‚ ðÜ…TïJ~Úž‡±J0¢±Éë[n(8D–º€N«X%ȉlOTà *“uO¹P`“Ø…g|À`!÷ê(ùh÷`f‘E&Ê¢¡ð©0Ö…‹ŽÉl“Ʋc/PQìQqîCtÁ}í¢¶czÎƦ4A}ãtP¾1†b´$–_PeGŒô\5ƒ¯¨³_ƒh…‰š/œqÑ«c*†Æ1$VBqb·’ïêýë1$·ª ù ›B=9È(•Õ)â­8º•õÓ¥ ccgŸÍÒÐ>SRàGv—Ö{¢[LÆþÉðš%QúÊŽªç(‚š!CRíT/Øxü؈¢Æ6bÙJ¶Äöª¦ÜLõ{½ÐYœit\&·œ&ê¨PÅmÙýçûÃGƒÒø¬Qk0\ñ´æ ¦.*‰¾¼.ÙÀRÇÅQ ‰ê¢gw(X"m)Z\.v4&MœgÊ'ýÝ<å†fW(â—e’ÆÙ‰¥…ô¤6úXs©5œbñ€¾À‡”=#WXŸq+¡9‹$Oè+9üõB#e¦ˆ~GWvõ¹—” NCyªO|{ ¤¯­¼üD8Õ(Zx=î”.hÂÇ¡)§:EåC3²»`¸·Æ<‘Œ•:çîé}Ðl¯†)¶‚ÌÓÔü€"ºrçÏ“fubxÂÁØH- m+M½èëün>4Âî°D[½N:æ®>Jz”¼«C/Eæ¿ý”Æ5Q“j"së½D• Šº#8 >Ím(T:_+>`©(þÎ;JCê|Ô°Øâ*Rظ6^¡:òFu8wr f²R3&7¡D"C–Öl2l¦»â¬Çß“oCc›[b'±ÂÇžR‚Sqœj†•RØÍg¥ÎüÍXrËË’—Ì ÒBµAŠhŸGÌöÑ!xuÏHëRذüÊ-óÒ›¦­é¹£¥õ’¨ Au\À^ñ<FA¹lÓd\"½62‰'À†.b«Šoc1b>½F­[žn¥þæÜþÙœ´ñ±Ãç(íŸa Øå±ÄÓ¬“B•ð7ŸUmï1äéd•:OóÑ”bo0¬´¯öaâj3 åN#-}Ë”LÞUÓ1h—À¹Hâßå;vÜ0þ( a-©£åVv<•`bÜʨÍÎæ¹ºLá1ÀGfðr*~|ò÷ –ÆÆ”À÷Ôó*ú‘MŠ”Ö8À¡HÃZï5‰I.è3y À`ÊT¹kÌ&`F0“ÌîÄlϘSa6Âì-J¯iOÏû-Ó]ÀlÓ-[BÌWƒ–Ì)Õ3§$˜™³ËUp5³v\t|éðÐ';^¸î±8‚ëÓ–_·ÃàÀq”¹sÁT~0fù”DT£>¦ùƒÀ%§½˜áOÕVÆjá' Ž^“|©wÏ`o`ÒÃÝêvBn@m@çá… Íúr§|ŸÔÔÅÑOÓÕ…wÀk͹neL51·‹Skž“¼°.µFl~¬xŒyE \¬3h‘ƒ~ê*®3äÑךׇŸû VÕ4,Hu¬“Ô ²J\âç¹e´“ñàûí'l§Jʹ81æ{+*…î`zõJ÷/Æ >c#€€‚ý|LCìûšÉø:XO¢Y{Ø„‚‚u¡HÊu(Î9Œ˜ &ËÇi~Ú y36|£¡°õ?¹TürÐV~¼©‡ßcšaŒðî±åïº\áÛ͉G~ðÁKˆÕ2œzá*Ǹ’â³G~‰'ÑtBÌêVBØvC³Šµ£kòpÉÙÔ¦ôbË+ÑМhåÎ\îê©IM©_¯ë>€äç—ö˹èB‚[N¶Ÿùïâ‚öEv Ÿæ÷ª)$“Lb˜éZ¾†c.¡ƒŠ~Óÿ¥œ„·×ð“êÿ ƒ!Pš1üyöדnj¿ÁhÎ0“ ˜³Iæ+°'\*ÀLúßB.2Ÿ^€¦•ªÎs©De‘ðæçåÍW¡é9¥ endstream endobj 216 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./IRangesOverview-ranges-coverage.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 227 0 R /BBox [0 0 432 162] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 228 0 R/F3 229 0 R>> /ExtGState << >>/ColorSpace << /sRGB 230 0 R >>>> /Length 651 /Filter /FlateDecode >> stream xœ¥•ÍnT1 …÷y /a‰íün§¤J ÁŒÄ±* QuÚ.x}œÜÜ$½-mG]ôj¾9ãÄõøœ!8‚K¸6Ÿá|Fë :â#gô 7?á+ü1oo¿|ØÁÅ­±h­…ùy{±ÊgûäýÙ'}7zøk¾} ? Á¹þ]*€&$d‚ÑGHC@ËÍ;C´¼0$о„fQ»N©UÞCÀ,­’¬Ç˜f5{$úŒù^©X‹™Û¹äì,:A–õÒŒ&QGiv‡'§õ^tô‡_åì&,…™µ+ýGtGxõûæ5.Í»C½àeÃveË}Ô¯:` ¯`¿‘ÒAò¢’xdÛå†Cç2fîzÃIõe×úvzwCÎh¹–7£­Ń‹e³Ë`í:×ròã¥Ä ½LµtJqVÍó Årݵ^,'‹SHS±³Ó.=Ó÷ºkôà®I¹â c'‹àh¢.KhteRõ\§ê£•r@74²Ú]¨§k—€Ø`u½"×<é(„aR%£ut5$:zÆ$÷p½hÉžŽ-m6¸Öê€s˜¨L}`B;©K4m0s±Â•ZŒ‘ò׳ÍÅ+) Ø,eý;ŠE7©Róf‹í?bçÐ۞Ї SyÑ1x “µ[ÚbtÅOs5ýŠÚ@šÔ,˜bÇ5šïâz²Øˆy,ƒGË[ìµÌ%·f$() l©ûÉÞ"§ #ʤjŒJ©¸m`B7©É£êþå‰ß,^;?6ÃçTv¹DêF%L+ µ9¸©­µ¡Ö…éê²>]]uUÛÚµöÑÕÞÕ A?eÝ›)Õ¥¢òõߤ´V3ɵ¼í‰iþ”#Õ< endstream endobj 232 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xœ–wTSهϽ7½P’Š”ÐkhRH ½H‘.*1 JÀ"6DTpDQ‘¦2(à€£C‘±"Š…Q±ëDÔqp–Id­ß¼yïÍ›ß÷~kŸ½ÏÝgï}ÖºüƒÂLX € ¡Xáçň‹g` ðlàp³³BøF™|ØŒl™ø½º ùû*Ó?ŒÁÿŸ”¹Y"1P˜ŒçòøÙ\É8=Wœ%·Oɘ¶4MÎ0JÎ"Y‚2V“sò,[|ö™e9ó2„<ËsÎâeðäÜ'ã9¾Œ‘`çø¹2¾&cƒtI†@Æoä±|N6(’Ü.æsSdl-c’(2‚-ãyàHÉ_ðÒ/XÌÏËÅÎÌZ.$§ˆ&\S†“‹áÏÏMç‹ÅÌ07#â1Ø™YárfÏüYym²";Ø8980m-m¾(Ô]ü›’÷v–^„îDøÃöW~™ °¦eµÙú‡mi]ëP»ý‡Í`/в¾u}qº|^RÄâ,g+«ÜÜ\KŸk)/èïúŸC_|ÏR¾Ýïåaxó“8’t1C^7nfz¦DÄÈÎâpù 柇øþuü$¾ˆ/”ED˦L L–µ[Ȉ™B†@øŸšøÃþ¤Ù¹–‰ÚøЖX¥!@~(* {d+Ðï} ÆGù͋љ˜ûÏ‚þ}W¸LþÈ$ŽcGD2¸QÎìšüZ4 E@ê@èÀ¶À¸àA(ˆq`1à‚D €µ ”‚­`'¨u 4ƒ6ptcà48.Ë`ÜR0ž€)ð Ì@„…ÈR‡t CȲ…XäCP”%CBH@ë R¨ª†ê¡fè[è(tº C· Qhúz#0 ¦ÁZ°l³`O8Ž„ÁÉð28.‚·À•p|î„O×àX ?§€:¢‹0ÂFB‘x$ !«¤i@Ú¤¹ŠH‘§È[EE1PL” Ê…⢖¡V¡6£ªQP¨>ÔUÔ(j õMFk¢ÍÑÎèt,:‹.FW ›Ðè³èô8úƒ¡cŒ1ŽL&³³³ÓŽ9…ÆŒa¦±X¬:ÖëŠ År°bl1¶ {{{;Ž}ƒ#âtp¶8_\¡8áú"ãEy‹.,ÖXœ¾øøÅ%œ%Gщ1‰-‰ï9¡œÎôÒ€¥µK§¸lî.îžoo’ïÊ/çO$¹&•'=JvMÞž<™âžR‘òTÀT ž§ú§Ö¥¾N MÛŸö)=&½=—‘˜qTH¦ û2µ3ó2‡³Ì³Š³¤Ëœ—í\6% 5eCÙ‹²»Å4ÙÏÔ€ÄD²^2šã–S“ó&7:÷Hžrž0o`¹ÙòMË'ò}ó¿^ZÁ]Ñ[ [°¶`t¥çÊúUЪ¥«zWë¯.Z=¾Æo͵„µik(´.,/|¹.f]O‘VÑš¢±õ~ë[‹ŠEÅ76¸l¨ÛˆÚ(Ø8¸iMKx%K­K+Jßoæn¾ø•ÍW•_}Ú’´e°Ì¡lÏVÌVáÖëÛÜ·(W.Ï/Û²½scGÉŽ—;—ì¼PaWQ·‹°K²KZ\Ù]ePµµê}uJõHWM{­fí¦Ú×»y»¯ìñØÓV§UWZ÷n¯`ïÍz¿úΣ†Š}˜}9û6F7öÍúº¹I£©´éÃ~á~éˆ}ÍŽÍÍ-š-e­p«¤uò`ÂÁËßxÓÝÆl«o§·—‡$‡›øíõÃA‡{°Ž´}gø]mµ£¤ê\Þ9Õ•Ò%íŽë>x´·Ç¥§ã{Ëï÷Ó=Vs\åx٠‰¢ŸN柜>•uêééäÓc½Kz=s­/¼oðlÐÙóç|Ïé÷ì?yÞõü± ÎŽ^d]ìºäp©sÀ~ ãû:;‡‡º/;]îž7|âŠû•ÓW½¯ž»píÒÈü‘áëQ×oÞH¸!½É»ùèVú­ç·snÏÜYs}·äžÒ½Šûš÷~4ý±]ê =>ê=:ð`Áƒ;cܱ'?eÿô~¼è!ùaÅ„ÎDó#ÛGÇ&}'/?^øxüIÖ“™§Å?+ÿ\ûÌäÙw¿xü20;5þ\ôüÓ¯›_¨¿ØÿÒîeïtØôýW¯f^—¼Qsà-ëmÿ»˜w3¹ï±ï+?˜~èùôñî§ŒOŸ~÷„óû endstream endobj 235 0 obj << /Length 1369 /Filter /FlateDecode >> stream xÚÝXKoã6¾ï¯ð¡©>õ(Ð-ÐÚc[vJ¬8^$VÛ›æßw^¤i[޽@±@{MRóæÇÑ ¿þpù1T“Vµ•­&×÷“Ê«fRµZÕ­™\Ï&7ÅMiŠ žÏåÔê6ƾœíkX¯L[Øòóõ_=™£Ú¶ÌuÆìal„Ç6g¾üØd–¯ZïA\«ß²¸ëàé™vÇl :PNT/Ddгo2Æ´fmV±;ÅÆ3hé3£ð™D╼AžLFu›GqE bsÔ!W£lÍL¿–Ó`Ý äšâ“Z–ðÕsEêN–qü ®DÒG7å•cafä(éÝ#÷'P^‰pB[2‘0¼ç᣼‰TpzEz&V«¦1»Ñ:´}Ï^š¾ŠÓ³$–ð;&ð†2 gÎ,Sjôøh¦Ñç&«tcc¢ˆxŠ{†Ïm(:¨‡ÊB­Œ7'² dÊþoñ•B‘ Û1©n”¯C”¶ÌIØ…çõÐW)ÚÈ´Xa:±¾õ<éù9ø„¢K1r9çWëkžw²gĆ„óÎB[Asq’3òŒ]2!·«ç 7­ƒ®3V÷Âþûk*¤çvµÂŠâ^”“‡Œ•aJxYJºD2ò˜‰(;?“BüYgHñ9R´QÚ¹â«2ÄOB:=‡»âá›9HOÁ_úÕX™ZTcÝX*9žßšRðdýLýDzx6·Ùç¼óCüP.‘oô~ZýWòPýòP5ž‡Œä!-s}¬\²S#LMr„Ée5–É 4sNæ÷˜CÆ\ ³;Æö˜[a¶Yuç1¿WWºÑ@UÇëJÕ•z?`‡ÙÂí)ÛÈY‚ßvá}ØÙQTã°k3èSèÙ‡^5‚ž³¡×dÌí)æz–“ çO1Ÿ–&A/Ã^,êæ’,×ÿGܹl#m¶Á'Ó^$4™7š„ªãü&ù=é Fí9¦ïã0ŒàPŸ‹Ãj‡ú\º ‡Už|Ïn­§ÊŽ.B”6ý©—w"D1l;".„†—#ª1ZÙ&6?TÄʦ¢úbDBPÞ'þé!­êH:bG£BÈ~> stream xÚÝXKÛ6¾ï¯0Ћœ®Y‘")©‡)Ð)Рè! íZö:YY®e'›þúr¤(­´ÙA=¢H΃Ùo>û§«‹^šbQŠÒ*»¸Ú,¬Å–©ÈK¹¸Z/Þ&Ï—+£²d·”É‘†ßÓ«s3µ{þrÏŸî¹ãï½{Þ¥&MmÝsrÏm¿L:ñSú×û«_K6r)]¬T*¬QäÏ+·ó{ªH/ØèÈ«Ö 74œ¶ŽK9ØY8µE!+)Ei ©ïxcžHÀëYÓçgö~Ô‚¾Õ”·nN÷~¹RV–Iº\ÉTç8—¹¹´48Ö¨"eaÛ «HØFÂ&N‘包ýFÉ *îçÕœ=£ ‹ÜW8žQ`F täAÍÛ96RB+ÐäÍטG ØmT`FGàä+&rkáêSêaŽ*)Ò¢tÛqÛ³‡ŠJ!­ñëí®3©!¿*HŸÖUVVZL¾/îiššëYvûîîpÑí3ISm÷œïR©9ýACÅÎéȶ4…(ÊÜ[³4Nݰtø›¡¥ _»´×ÉØ|s"®—ªðþTd|SݰÛíñr¹ÒRb¡Ü‚ر¦­tô¶ÛñÎÝ'ÐË7í¾ðàAŸŒ1ãoÐîtäIÛðÊ®Éu¨´06¦BÅõ›en¯·{>dTé÷‡%‡h 62¬Ç¦Ýt{>õø%8ö£’…(¥šÓgôZQ=Âð;z­ñ 29»ç:`).y­£ÿ/ˆB¹®ÿQ? Hcaûüf@ ÖóDm„LéSAÔFÖó§X·3è=¯ôœð@m„Àå‡8"µ(µ&ßK)UòâÍëW¯qR?: ®Š[Ý8'jÑT q©ÝÐöP]MÕ‘7ž`:è'0·£•„¶·d g®i+úë°U¯Ù*‹€Çmî$—øÂᡌß}%W]\4ÑÿDåà#_J8<‰ÎLrf…:£à´4}"Æq¯õ=•%LCHáÍþæ´a€Á ’yšB<ÎØšv ̨ΠnbÌüŒž½wÁ%ìfð7·=WåxúpÄS8£ÞÚštmÓŸ\l÷´ PÜ7FÜÔžQðúâ:‡*(hw}›à8Â$»šP3¬nèƒÜÜb^5MÕ§kß³ í{ƒc²–=€9f "Š”ºH~-wWY¡ÜµÈîht÷ÿ¡eóû%ø9Ih\?Ê &4/\\RÇ'°  ©¦€6ü÷4{Âvð•S˜7ð¦|§ŒñçÇ$p‹;ê*ÞJõÖù00YѶ®†dL³ ”YwôpPV—|'ƒ‹ÕïÀ~Q÷ý9‡ƒ%U^¶G¿W}ÚùSA,*à‡p®ž­)’—Ë"CúNR¸ Bô.'z1¤P™š®é#KÖÜ÷«Ð4'‰š1Â(éO€Â'f Ç=³'—¾½Ö¾n?À!£‚ÇTî4‰Ùlún1E:zv„×»7È`Ý vá®æ–6úhνbÞ† Y¸Ð “çÃhÌ3íT¤eæÏΙÁ„‰Œ>d´¥Ð¥ò‚ˆÑžèlŸ° ¹õGÄ‘Ž>§unjȧÁèc|Z ­æè4Ø™Np\º†+úBã _EµmêA{tƱ÷PƒÂ½‘‚­ûöƒrÑ q‹@øP õ¨ÂˆTIàD6µ=NÏÔgØ0½v}"G€Ï®ÂV0C½cÖñ¼§ÕÓ3ý·ÄC¥ûßðÊ ™ªoI§'Ft:“:C2kr¢’ÄOg˜ Š„ŠˆB«@«g¸w±_ñOÿ/Í?:Ç!ðøqa3ÿlx”ùÚ‘p —_³œG /¸'íúk+FÂfô·ÉCáÈr gQÀ2þÛˆ”ÎS.öŒ_G®ëèçBþäš;0±k93§Ë%Ôß¿-ѸRÍ]•"•…s©t¿( rIâÿL?_]ü*Þ¹ª endstream endobj 244 0 obj << /Length 1208 /Filter /FlateDecode >> stream xÚ½WÙnÛF}×W}¢Šˆælä°@ 4h ¤/n ½ÅAÁ˜ÔÒØ¢£%þýÞm¤‘HFÎC &93çÜeî=«$‡ŸJ”W™O e²<7ÉÃÓäË$sV%ÍG4¥%7ïŸ\òk7ù~ajÆŒ³ˆòÝ|rsë“*« ]$óE¢µÍŒs‰«T–{—Ì›äCz;Ué®åa ÛéÌ“ºŸ¦3kMú =ÂÕíy¼[à]§€vÿàäzƒÈ†§¥Þ,[œÍ¦翃kÖf…­ÊJoØî/¸¼L¿N]‘ÖÛ5¡¦Ú§{K€½¹uE€+o!^b8:ù!ïFÆ‘xÌ@õéUžåÖ]§Wà¤JßE﻾ÉBgʼnì FåÓX»BІºâPø*l %Ž'ÐÊ*lJ™nk4µle–mSÆÐ9âÿû$6ÑÿCl/ÐÖûa3ÑÆ–è±­…‰7ÖCAi *«œù°áb¨£šêÕŒ¸žq©ÍW§¥„¹\[áâJy<„e:]ïÄʆagi—í6a¨}më¶ç¥|½ Þ‡â… ‰75‡Pá _0ÔŸ§3§ÍwVŠJïs—ËЖ_Õ@5‚- iUžm}€• ®lSñM½™³Aá..¹]æË’¹nCI{¡­”õézO™ÁŒyÈ F°èÄ÷§z¿–ˆGúSæ3㛺“œ¬Zb˜™’·‹«Ž¹…XRÔm¤a%ew’Ê ¡mècSd â•Þãb³–úÝè9kóÌ(€n3d Ê|^…e·–$|îójp(×ïÊêTñ˜-IÑΤ÷ÊØû\9ÉÂ3¦æœ²öaI]ž”¹^Ö!Ç¡qaI·Š6¯Ýóu¬èžÐv·á¦ÖZÃvùó¦¦.¸àš{.üNÙA¢ovTG¯íñÍéõÉF¼‡Ç¿¢t/uÖNjAîGšîÈùÔ7d®·p ý—>½^éié»ñPÈ«ŽòB!5a;CS%m›Î3ï•lš¤¸Ÿžf,v.ƒ˜Ðõ4Hç•£g”‹Ü–¼Æ5Ñä}}A`…Ÿ+/T•c`‘(¬»k`M¶®»3‚âDà.¬;!²o[/.¬¸ðhÒÊl@`Ç;@àrP|ãoˆ(Π Ueñ=‚æ³Êè3…¾×TÁÚ[QõpjÁí ê¾îžÑyø:¯©i”•“$.!k¤Òq€ñÔ‚/¢õæ3·±®L8 !±|chéc¯=ÏI7a¸><žDB1 x§“érNb¨=Ê/®!™}ÆðÅ·(l<ÝÀÊ;IeËÍe!}ù…Äbîvr A¬w"°|R1GZ‡“™‰|¶!'w–<ú,­ß=uûð)—Cz»ä¯«¢ÌÕŒ<~)"èP¸i¯ŽÜ™Â÷«iLÙûJDÃoù¶ ü×ßÑ×bsâVÉ1É~TûÿVªÝÿ Õ(¨u®<É”º&Ϭe –§bX–Y>iz'óY¾[Û1°ûÆ×Ä Ø½F’5Ž’l®éyy¡ç&Wã’¬u•åPU³Re.ü3¬háä·ùä_Q˜Ö endstream endobj 237 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./IRangesOverview-ranges-disjoin.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 247 0 R /BBox [0 0 432 162] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 248 0 R/F3 249 0 R>> /ExtGState << >>/ColorSpace << /sRGB 250 0 R >>>> /Length 366 /Filter /FlateDecode >> stream xœ¥“ËNÃ0E÷þŠY¶›Á3~ÅÛT€T ¤ÒH,(«¤F´¨Í‚ßÇNœG£¨XÄÊÍɵGwÆs (á pãQjp µ¥{4 Ç7x†½¸©žîsXWB¢”†kµnñly/gá«3ð%^^AÂFÌÃS Š?Àƒ°2 xЕDñä\94|¨È‚2È'Ð0f*9JsÂ> stream xœ–wTSهϽ7½P’Š”ÐkhRH ½H‘.*1 JÀ"6DTpDQ‘¦2(à€£C‘±"Š…Q±ëDÔqp–Id­ß¼yïÍ›ß÷~kŸ½ÏÝgï}ÖºüƒÂLX € ¡Xáçň‹g` ðlàp³³BøF™|ØŒl™ø½º ùû*Ó?ŒÁÿŸ”¹Y"1P˜ŒçòøÙ\É8=Wœ%·Oɘ¶4MÎ0JÎ"Y‚2V“sò,[|ö™e9ó2„<ËsÎâeðäÜ'ã9¾Œ‘`çø¹2¾&cƒtI†@Æoä±|N6(’Ü.æsSdl-c’(2‚-ãyàHÉ_ðÒ/XÌÏËÅÎÌZ.$§ˆ&\S†“‹áÏÏMç‹ÅÌ07#â1Ø™YárfÏüYym²";Ø8980m-m¾(Ô]ü›’÷v–^„îDøÃöW~™ °¦eµÙú‡mi]ëP»ý‡Í`/в¾u}qº|^RÄâ,g+«ÜÜ\KŸk)/èïúŸC_|ÏR¾Ýïåaxó“8’t1C^7nfz¦DÄÈÎâpù 柇øþuü$¾ˆ/”ED˦L L–µ[Ȉ™B†@øŸšøÃþ¤Ù¹–‰ÚøЖX¥!@~(* {d+Ðï} ÆGù͋љ˜ûÏ‚þ}W¸LþÈ$ŽcGD2¸QÎìšüZ4 E@ê@èÀ¶À¸àA(ˆq`1à‚D €µ ”‚­`'¨u 4ƒ6ptcà48.Ë`ÜR0ž€)ð Ì@„…ÈR‡t CȲ…XäCP”%CBH@ë R¨ª†ê¡fè[è(tº C· Qhúz#0 ¦ÁZ°l³`O8Ž„ÁÉð28.‚·À•p|î„O×àX ?§€:¢‹0ÂFB‘x$ !«¤i@Ú¤¹ŠH‘§È[EE1PL” Ê…⢖¡V¡6£ªQP¨>ÔUÔ(j õMFk¢ÍÑÎèt,:‹.FW ›Ðè³èô8úƒ¡cŒ1ŽL&³³³ÓŽ9…ÆŒa¦±X¬:ÖëŠ År°bl1¶ {{{;Ž}ƒ#âtp¶8_\¡8áú"ãEy‹.,ÖXœ¾øøÅ%œ%Gщ1‰-‰ï9¡œÎôÒ€¥µK§¸lî.îžoo’ïÊ/çO$¹&•'=JvMÞž<™âžR‘òTÀT ž§ú§Ö¥¾N MÛŸö)=&½=—‘˜qTH¦ û2µ3ó2‡³Ì³Š³¤Ëœ—í\6% 5eCÙ‹²»Å4ÙÏÔ€ÄD²^2šã–S“ó&7:÷Hžrž0o`¹ÙòMË'ò}ó¿^ZÁ]Ñ[ [°¶`t¥çÊúUЪ¥«zWë¯.Z=¾Æo͵„µik(´.,/|¹.f]O‘VÑš¢±õ~ë[‹ŠEÅ76¸l¨ÛˆÚ(Ø8¸iMKx%K­K+Jßoæn¾ø•ÍW•_}Ú’´e°Ì¡lÏVÌVáÖëÛÜ·(W.Ï/Û²½scGÉŽ—;—ì¼PaWQ·‹°K²KZ\Ù]ePµµê}uJõHWM{­fí¦Ú×»y»¯ìñØÓV§UWZ÷n¯`ïÍz¿úΣ†Š}˜}9û6F7öÍúº¹I£©´éÃ~á~éˆ}ÍŽÍÍ-š-e­p«¤uò`ÂÁËßxÓÝÆl«o§·—‡$‡›øíõÃA‡{°Ž´}gø]mµ£¤ê\Þ9Õ•Ò%íŽë>x´·Ç¥§ã{Ëï÷Ó=Vs\åx٠‰¢ŸN柜>•uêééäÓc½Kz=s­/¼oðlÐÙóç|Ïé÷ì?yÞõü± ÎŽ^d]ìºäp©sÀ~ ãû:;‡‡º/;]îž7|âŠû•ÓW½¯ž»píÒÈü‘áëQ×oÞH¸!½É»ùèVú­ç·snÏÜYs}·äžÒ½Šûš÷~4ý±]ê =>ê=:ð`Áƒ;cܱ'?eÿô~¼è!ùaÅ„ÎDó#ÛGÇ&}'/?^øxüIÖ“™§Å?+ÿ\ûÌäÙw¿xü20;5þ\ôüÓ¯›_¨¿ØÿÒîeïtØôýW¯f^—¼Qsà-ëmÿ»˜w3¹ï±ï+?˜~èùôñî§ŒOŸ~÷„óû endstream endobj 256 0 obj << /Length 2610 /Filter /FlateDecode >> stream xÚ½ÛŽÛ¸õ}¾Âè“ ¬‘"%ª@ûvƒ¦mww,äAckfÜØò¬%g’~}Ï%sf²AQöмžûQ‹þ©…r*s‹RYž‹Íáê·«ÌUV´ iIÉ)™xõöP.þz¼ú þù¥5C\G ___½zãuV—º\\ß.´Ö™Rnak•åÎ.®·‹÷Ë7+µÜÁçî|‚ïvµ.ŠbYþqµ6¦Xþ ¦öð9<¼Å¿zy×<ÀlÏ“·0<¼rj:Ööð­>^ÿýÕS-”Êjk5"±V¶Ê ÀbmTV¹‚±°¸Ý­ÖJi³ü¥Åë*»ü'Ì>Àñ‚;øÝ#|u=C Ì‘ Yáý1?´ƒPx@ ýŒçŽ`…¡rÆa‹‰ršÄóGnpØ!m»-rëÄFÅšUæ™®Qˆ„ËÏ+«–H@w·brø8Rû#Ç›ÕÚšå¿qóFpmцÿ &­,yÙ캕v„t{GlÃMBu³Çù{¤ ¼»)¼gz‚ D\iPWº‚káë«_xݸùð Ê‚?6Ì_ DR[P·¤B^µ%üp+)M¶Z»J/¯ïån*°“¿·tàÐø þƒG·¸V.oà¯) o=CÿÁ0àC`Þ‚L„gRVYU†óÀD«à0ÈE— À‹ÏøÕ2ƒi­Û2¾¼@㎶>2²È%bsßݰ2ð¶ÏHFØŽµŽYÓóY1î òâéA@6Û·ÒS ’ •Íœþ—LË¡ @ˆ!IY¦f0ðàø@ä’n4#ð>Åo]gUáÙµAöúÃ^X|hEÖÃ%¯­"çx} ¾ÊLaüÔߎQ¹„¥MVVÕ7Ã" Za#â¾I#Z”@¤Ž””Žy‹®2W•~+‰çC® ¾ n vlxtq)33*:%Ðß”£!w:ñ3dNÏøЇÊ>ágàbUå`ˆâÔ²*4§–5ªpEVÚzjÒê/é=zKW‚BÛÎ ÕMpJ=¯¡=ÃÀ.ÛfƒK÷'m³Qú>ÐhäfôÑ®}4.¡{ÀÁ©K¥¨Ûè&CI\.‚¼ºØ¥Ð³:Äšß™½‰Ï9c¦â{¼ÛÞ#{ KëžÆ5&!DÐâ=Q  Rk»ü  ƒ®­9y÷ºo%üwôÁ׈ӓHÁx¿þ‰ý&3¡Œ™P;À9Øôƒ°€ƒÇ¥ÈÁã)¿ùUžÉj§çÐPö_’î¤JBƵe¬#×(J¸2x5EÞ¥(/ŠYÓ8VUš8­¼-·þ>˜ØÝhåìâMåÕT `špm‹<þºr†3ˆŽY=W1¯„¡@6“Ûïuí6×ü fäeÈ9ò*Ê("à¢6í–·ßp6Bã1$&TÇYÐ…;óCÚºuLÑ3Y§´q„ø Ζ¡¾‘rËÎ{ZÑv¹¦°Ë×$"â%˜¸½¡\tðæ;ÃÌ"7ßEÜãN tÏžD’ÃYüh'Þʆ¢˜ûúàÿƬŸ~úÕfàß·Á'ðoN Ú1`´,ßÉá4èÝ“?ä6ÇÅd¢‹ ·qªÚ!ÎG ¤¿Fèr+é±§\ìF8ÕŽ7cŒ³ìÕÆ˜EiïíW¾©wÿ·R? *ÎÁIÃúà›óišÖ§z#É>„>KŒùä}ÁoŒ\†ÏÞCROµ ¹—ú†Òï­Tiv^HÁ/-Òþ3pI3íRžã;Q—xW/‘­‘iÿ >jÜâ]ÅV–°úË J¨xŽ)lVC’Cؼ…?ËÓD‡€cqxËCï›ü.æ"-Äm S·yÿ gúù(„oXöà €ï…ø ô¼¶p5R»V¹©h\ ¦©zi& Ö³Ãet¸~ép60®ä0ó<:|©1ÓE|w²Órªñÿј°k3^Á³ŸÐ0 cŠ_rëPÔÚŽlØ‹{hOR´©YT7ÊùåH2íÙ²cnÒé']%.Æw"m¬K¨‚ÜïMnË1ɺ¬ ø^Ÿá“pº—ãòTù,æNªdcr’ÿmEÅ;d%²x¼éÑlb„#]>H‚Z œÉN]'þ©™]Þž¹‹«f\)IÙšƒlóaæû ŠÊ¨1æ|=µT¸õ5DbÄcs$ŽÝ^"=ýð•ó”ỏÌEÑÐú<Ô.㪉·^Àè"n´)g1F¹%‘%–“,ÒzÍYåÎD¯E¸ä=êÝMÓTI)"˜Tý?*ð!å¬õwø5¶KR)à]—i«¿·¶7™®BÚæC42mÒJkg‰/K·IÏ Æ*’éÜ­å’ÃP¹¼OüQ„Ü…6S²†ÂþlYÌy\>Åãú.Ôj9åºzŠéà ðdÖSx./F÷ßíïij³ÁOª.±úÅÔ\z§Ü´•.#4íöRYQßœ ¤»©MÔY=ùZ,Øñî¢Òm­qôÅëCÓÑJqÇJŽ[ìP£š’[ì•Ér²ÐÉ͖Ò\·ª!œn_wV0…8´éˆÀy€ËÝK¢Ê” VÃ9µ¢ž‹6 ÄIÅqò5-Ðy™\‡†)÷[C„ÅX“ݧñgŸZ ¢à¾?2kR:ˆqS&Ü)sP±¡I"èE'0fsÏÄ7°‡>ÈÇcØ0$Òß|#†bŽH'(<¾Ã‚ç(ÔŒ•àtI®‘¯ú6®C¡Yd6ŸYZêµíüØq`-Ž« Íq3~Jˆ(fT‹ü8évDOG³÷`]³“P7}!.ýtü’6㓯2$è娢öCòOÖ˪›¡‡é‹²$¡Œ0± 1 Ñ%ê)ÇÿÖúŠ=L]…7ƒ {RœÃoÅÒwGeÿ$L›‡ª1 Ô6”EϪ>D(3&SÕgdéBn F„ú nд+ ©†¿ìd{[Å)iDÀÊ Ý^ªXÚ׎Þ£æeB%\–çßì «â¤bŒÔkßZÍ¡„гǖIŸ¥B¬?í™ì‡ñ¹yríq #I)©Ñ üŠÏžÃiç3ýw˜<ýÆΠœ$JsKN¸—Uc#éµ§‡2_®`îÒ—áƒÜؾtùé'cȳ@‡kÌýAÂ>žu) já¶?^š!•Hù±øzòŠí0®fO°xC*ú×.z&ë<û4âxòù»‹z½Õr3>TÄŽv}‘ÆWøªx¶·©£fthï&-ݬAÞîÙ¤‡0¼!“¤^+üâYÝràm>žzÞÆ¦z¾ *çÆä­ßÓ–¯O™«ÝÔ²Ã4ÛÙÙ7O^F Ñòn{öå*I˜XݳŸÖÀ›œþkB™i'r¸võãõÕÌ”êÄ endstream endobj 253 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./IRangesOverview-ranges-gaps.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 259 0 R /BBox [0 0 432 162] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 260 0 R/F3 261 0 R>> /ExtGState << >>/ColorSpace << /sRGB 262 0 R >>>> /Length 353 /Filter /FlateDecode >> stream xœ¥’KK1…÷ùgÙB½æÞ> stream xœ–wTSهϽ7½P’Š”ÐkhRH ½H‘.*1 JÀ"6DTpDQ‘¦2(à€£C‘±"Š…Q±ëDÔqp–Id­ß¼yïÍ›ß÷~kŸ½ÏÝgï}ÖºüƒÂLX € ¡Xáçň‹g` ðlàp³³BøF™|ØŒl™ø½º ùû*Ó?ŒÁÿŸ”¹Y"1P˜ŒçòøÙ\É8=Wœ%·Oɘ¶4MÎ0JÎ"Y‚2V“sò,[|ö™e9ó2„<ËsÎâeðäÜ'ã9¾Œ‘`çø¹2¾&cƒtI†@Æoä±|N6(’Ü.æsSdl-c’(2‚-ãyàHÉ_ðÒ/XÌÏËÅÎÌZ.$§ˆ&\S†“‹áÏÏMç‹ÅÌ07#â1Ø™YárfÏüYym²";Ø8980m-m¾(Ô]ü›’÷v–^„îDøÃöW~™ °¦eµÙú‡mi]ëP»ý‡Í`/в¾u}qº|^RÄâ,g+«ÜÜ\KŸk)/èïúŸC_|ÏR¾Ýïåaxó“8’t1C^7nfz¦DÄÈÎâpù 柇øþuü$¾ˆ/”ED˦L L–µ[Ȉ™B†@øŸšøÃþ¤Ù¹–‰ÚøЖX¥!@~(* {d+Ðï} ÆGù͋љ˜ûÏ‚þ}W¸LþÈ$ŽcGD2¸QÎìšüZ4 E@ê@èÀ¶À¸àA(ˆq`1à‚D €µ ”‚­`'¨u 4ƒ6ptcà48.Ë`ÜR0ž€)ð Ì@„…ÈR‡t CȲ…XäCP”%CBH@ë R¨ª†ê¡fè[è(tº C· Qhúz#0 ¦ÁZ°l³`O8Ž„ÁÉð28.‚·À•p|î„O×àX ?§€:¢‹0ÂFB‘x$ !«¤i@Ú¤¹ŠH‘§È[EE1PL” Ê…⢖¡V¡6£ªQP¨>ÔUÔ(j õMFk¢ÍÑÎèt,:‹.FW ›Ðè³èô8úƒ¡cŒ1ŽL&³³³ÓŽ9…ÆŒa¦±X¬:ÖëŠ År°bl1¶ {{{;Ž}ƒ#âtp¶8_\¡8áú"ãEy‹.,ÖXœ¾øøÅ%œ%Gщ1‰-‰ï9¡œÎôÒ€¥µK§¸lî.îžoo’ïÊ/çO$¹&•'=JvMÞž<™âžR‘òTÀT ž§ú§Ö¥¾N MÛŸö)=&½=—‘˜qTH¦ û2µ3ó2‡³Ì³Š³¤Ëœ—í\6% 5eCÙ‹²»Å4ÙÏÔ€ÄD²^2šã–S“ó&7:÷Hžrž0o`¹ÙòMË'ò}ó¿^ZÁ]Ñ[ [°¶`t¥çÊúUЪ¥«zWë¯.Z=¾Æo͵„µik(´.,/|¹.f]O‘VÑš¢±õ~ë[‹ŠEÅ76¸l¨ÛˆÚ(Ø8¸iMKx%K­K+Jßoæn¾ø•ÍW•_}Ú’´e°Ì¡lÏVÌVáÖëÛÜ·(W.Ï/Û²½scGÉŽ—;—ì¼PaWQ·‹°K²KZ\Ù]ePµµê}uJõHWM{­fí¦Ú×»y»¯ìñØÓV§UWZ÷n¯`ïÍz¿úΣ†Š}˜}9û6F7öÍúº¹I£©´éÃ~á~éˆ}ÍŽÍÍ-š-e­p«¤uò`ÂÁËßxÓÝÆl«o§·—‡$‡›øíõÃA‡{°Ž´}gø]mµ£¤ê\Þ9Õ•Ò%íŽë>x´·Ç¥§ã{Ëï÷Ó=Vs\åx٠‰¢ŸN柜>•uêééäÓc½Kz=s­/¼oðlÐÙóç|Ïé÷ì?yÞõü± ÎŽ^d]ìºäp©sÀ~ ãû:;‡‡º/;]îž7|âŠû•ÓW½¯ž»píÒÈü‘áëQ×oÞH¸!½É»ùèVú­ç·snÏÜYs}·äžÒ½Šûš÷~4ý±]ê =>ê=:ð`Áƒ;cܱ'?eÿô~¼è!ùaÅ„ÎDó#ÛGÇ&}'/?^øxüIÖ“™§Å?+ÿ\ûÌäÙw¿xü20;5þ\ôüÓ¯›_¨¿ØÿÒîeïtØôýW¯f^—¼Qsà-ëmÿ»˜w3¹ï±ï+?˜~èùôñî§ŒOŸ~÷„óû endstream endobj 267 0 obj << /Length 2091 /Filter /FlateDecode >> stream xÚÍ]Û6콿"pQ-É–ì¡-°®èÐuÃ-hºbð%¹\¶^|‹s½vèIQ¶å(¹ìnöàX¦(~‰¤HåéôÁÃy1*Ei”MÏG&ÅÈ”©°¥Mç£÷É“ñ$W:ù<–É[xVð,๧qS`8qÃ] ™ü–æ)¼À)<yú¤£Û ô†ÝPºõrüaúã(M¤ežßA°†Y ÖŒ1 emŽ`-“× Ãñö>¢„„¢¢=|‘Ù‘3‹Â I•™ÔNR¨BAz•%ß/ák¹AâËŠI®ÖËñDÛ,yKZ8ˆnß-PÿBè‚}â`]¬ZA lÓá«R()a¡£øÈïŠ\õe—‰ßÓ~ͬZƒ\¹LÎÆeÐ5t®’k$µ˜»¿vððV6©¯ÜL=†OcU$‹ƒ,ªÂ.Ü× Ê¾†gN˜7'6DðÂù!E„ŠläH¹µç׸væÍW¯;‹…&0Z([z}> üä'¶Éç¸Á3)¬iq¡o„–ù!ê^Ç}Ô³;Sÿ´ÂåѲ&™É…Ê®h "Üe)tn)·`óíQ0O…N[ÿCŸÛ°O8RsÞe­“s¤ÔlñC‘gzWòö[:<ïm0œUˆ7»fW&YtX æ²q° ËÛ\9Wžmy¾u+­Û¯¶ý€_¡Ÿ7®!›_VoÄl¾¾öS  ØQåe³.zÆ›w™çð jOŽ“R°i(É{ÀDì>›ÝúR%™h˜‘ï©Æ0ß§Ï+v”-S[ò{? jž»¡Ïók^åP§òðÈCËuÖûwÜÔÐ_<—¹— ‡Ã§=‡T°JÄv“©$dÂdó˜pCàs¨Ðj r+ÇÞ‰bGÕ j:(/±0Ìv– ¤"t#ú‡sQàðµ7îîáiôß„»ùÑ>ÐîžjüoÃÝ|“pΩÛ3ÂÀ©uŸ*ø2°¨Û3ѽƒýP@eƒü&Q(ÃOw&Ó€ÀÀ*Ù9EôñÑŽu~&tf|¯•È ;¥åÿÕõ•+ékò5æÉ)KËÅÞò^IQ¤{8ÆÑ/?S3Rèd:. wx3O²Ò&o>}?ß!ÀÐK•ËfÛ«:—›*mösD~ŠßõîC ©°¥ÑÆ×MÆ»áq}ΙõKk«DÚ–¯§c¨Ê«u‰P¹ÏŸQ%UE C+ŠÂ¯ êÏ€A*ÊÂÁàuì;¬l&,Œ˜H }Lž%àPØ8W~G DV¹0Z‡nI{…fõ5'™jI+Þ`_ÆrÛÕëÆ•ŒQóÉ oÚêþ%í3©èSY¬¨g+Í­–ÃÊôiÈ’¬–C¦-Ô!«¡¶œØÉkê¦+¿gT7«Ž Tmºé¹ëµe¶ömdhÄ®Œhfó~OôÒçòúÒ×é§è8Ñe!À<ÁcwâºÓ?ÇЄÂîòñJ¥=Æ|™ §w¾ËXc¯¢ÜvPSòåoƒK7Eñ¦ ”[-Ù2D¡7®ÏýéæÉϹzXù¯™!M"±}WR}dë++‘á8#ƒŽþÔÜD|©RqŸßøÍ™ûä€cÒ¤¾Äßí†îˆ;DãËï&KÍ»@‹™”=z’ÉÔ%-Äß^ô Hô2)eÃ%]Ü.Éøî^ƒH9¯Z=ú“,-!R kN­cEîÊ37¾–X8œ632U—ˆÐ¾©b˜@¦>kü»íÙ¶ÛÖœD¼[ŽïܯŽJ b½l‚ZjŒ-T•7¯'Õ.KÈw©°:kÇÖ9ðíÙÜ•µéœƒY Ψ T:Øè)itm”&3²^Û¿¤Šš+Q(žÇ YÝ/¥ h}ºCZÐÕ8Ôš Ì´˜sªËÓî–KÆî1ˆ-3-Šrï)ßRˆ ³ïÌrœ(N¼ÔWÁ5X/ÀÆŒ Taá´á]Cù›sgäÈT‹4ÏÃ]ëå˜êÌ_<¢…¬E¯¦·Ïk5è‡ –iÖ$S¿gшyÞÏ[H–§¼æˆÜž;w»ã2…ÿ®·nÜ]TZ>…ÛS‹rf#]Þµkú"/Ð> ™åºéšöGçŒæ#1f.®9µ’Ê´WvOñ4(«Ùu_ŒÉ^x€]v`P¢´­kD¯e"­°ån§Vñ¾]·þ7¼ßpñX³&—]ïÚé¯t¦{þ3ظp?íÝ)úÁ@|Æð-¿,ùR~ͳ—ÝöoÛk7|°¼ç7Âþ‚ç÷ªw×ÞuI'‡Ì¤níˆ3Q¼ai{­¯íxÕáÿ7žæ‡ôˆ/:â2Í,á¯{Vöóþ­',{*†E–d+H¦ô¾k®OúMxÛÝ¥¬»ç¤Ütc‘w9<%uò’näò˜3«8×"äªw¹ž ¸ZÎ2WË’DCHïpu9YȶÜe;°U¬ l•”4U6ÛÃ6ïØª8Ûù€mÑ[iÙ@)‰a›ïa[†l³]¶ ^!{ÚÊkÕnoä†ÌDØêÐÈÞMlÏl½v£kf5²°Í˜À‰¿×qbØ.Ýç„ô {% kïUá¬T)RYŒ&ð. ¾­‘%">x>}ðK endstream endobj 272 0 obj << /Length 1751 /Filter /FlateDecode >> stream xÚ½XYoÛF~ϯ‚>hÄp^Eë‡"5"@Ä@£`$Jb‰Š(ÇI‘ß¹–\ò´}DîÎÌ~sîŒ~½xöò<ŸQ‘êtv±šeE”Y;K‹8Ê 5»XÎ.ƒ?Bìªpnsl7ð²¾uye õ¾6 ø2|¿öž«|mùIòà½2¶©>ÁÂ-î ÿ¢‚¯ç¸]xÀn,¥üÎuÔ!|}Æãe½F!H¸wQ8Ï‹4¸@fÖ0!"¨V -Z¢¯å9t³Ea|ØAD¼’Â:X!Ø—oÆõ*¼ºøýåyb=kΕ 0ç\©¨H6çÛ0~ÔrM쉖¯HdÉ"|$:*ŒšÅÌúS8OmÂv‘£EÓ(2ÛüíWÜ4­†ðØTk ,/H½u%6qк7„bN <ò}GËïã$ƳÕ“caG±_2›ç!ØÝQU_j»ðÕ X†¹»féDSâ)%ný[Ë¥fs±›7e­ UMº ÚKòV‰ÂÁz5Å2,»àнǞ¦Caï.tþÿˆg¢È5“Þm„ôš)Da"c‰œïce\ÐpÉØ]à ×dV„[75^Õ ™T¼!ÛrçüL%Y¿Uš[R’Ñ~)î8s0“ÐPq?dML×ÛËbV¶—d€hÐExj¦Å€ÖbQÄKÑ\³h¸·/N~Ed¾£h]•G^ØØÑ°m/7EÊVKòv:ˆŠOã@JÔ,'rÒdYd —QœŒìÞ‡“8Óı–ˆjÛˆJ5G$$P”{ö^Q*´zlmÏh& F¿e+‚†K¡€ð¤ëRÊÁÔz­ÞEˆÁ×N¦!£Hº¯=J·-¥@à ×U9h//ìŸ%À¶"K’XtÒ-j4YãIaØ?…kÇÆñGâ ßœ•pݨ‚­tB>s>-ùñgxœóãÛPjfë)EùõJÖò+Uh#À^0÷Nv·l \ú…nDÖÑå¿0¢ý.å—ê|þrUJpÈYþÒº­ #(Råçª÷YÀݸQŽ}ÑK]©n?†óÂ&Ø ãb¤•+óûÆ¢{|.¯®ø(Y<Ãm-Û‚\¨;†P ‡ò¬ <º ‡‰:Ÿ>ÁôáBla5€à´¶BnƤ#² X&¬¨3€°vu^õ á”ÏåÙ¸ˆìw\n~òjúŸýB­Ó¤ñù£ä?õ°w7®A]W)wO½wÙ–I_¤%ÃÇfß5o°`eJ¥&”›5GÄ#6è:Ë(q4xLM ÷’éer¦Ý¶ #An¶D‡ÔE7„´°KáõÇ—¡Ém¤”v ëô 0²¹1ðØu¹‹¶³n ”&×D±Výp¡žã(•÷°ëÚÙr¢ ·:J³AÞMÄ¬ï› ·˜ã6\EZ-À݉VzK“dŽìä=6PÞF©õ ö$•rÇùnßÎâ2Mœ‡Ya¾(ݵtRÁ<‰¬jeMµÎ,)hÇ ´uFSת´`i\uoÿtß5ýFl8Äñèš.ÿ{A)—Åæ‡QO:AtÎŽ7Ü9ÅQžþ9h¼9âÐiUõ›=×(.[±”=‚×ÝWRI•W޵´eü<¡ìe×`sî1»k:=Å(}A{‚õ˜‹!³†„WjÚú?óƒû!ùüà,’ˆE´X¤[ÀްðاøÃxþà{›™õTpÙõÄÌ—.3óËÌÙô|íåòÙýÓæ÷”‡wrEÝxWòp ?÷zö¶ðý;¥#}BéxÖ©)ÐûíâÙ?Ñ-˜¬ endstream endobj 276 0 obj << /Length 1541 /Filter /FlateDecode >> stream xÚ¥XßoÛ6~ï_a }±Šˆ!À†µØ†=uÞSÚEVo‰”Yɺýãww–­8s·WOFÓáór/ iä¬ãyJ '¿¤ÐFù$JOpQ|@¹ vöô6qPßÿ;¢:Ȳ7ìvtpXSY;8ZµäRç°Ç"®ûÎõ +òr˜ÊžIˆG,Í?á6Ûúº„Fˆ¢Z h_­@üäÉ/´OÚ[3pó!\ ŽÑç™p…ùÚªu‚¾Â3ì;/ÔR7t§Ý]h \ƳÌņǀ=tw •Ú ÜÄh6ë‚ì*™ŠgàŒ¥"ÃhCð`u.œàª>¤i註»Æÿ¡Ã«ðç³t^ õ÷M5zÞ2Ëüíú*Ö<· v£ñYwC¡Õ²¡¸„ $Rü €2͸ë»ú o‡ zÒ±&«²xÚ‡ªÛ4þƒÅ*µN(mã2(@Ië¨}µ@¹Ò ¹Tþçº ã€~á>¤„tfü‚ —¾"PÉó4[–JhµH–Ó‹éåPú<]~ϯÑ×±ÓµQ,wº„‰åNç~•;÷ÃÛ7|[»äE?|Ó·5÷äL–«Tg¢¡|$Áo6/þÕÎèä endstream endobj 281 0 obj << /Length 1730 /Filter /FlateDecode >> stream xÚ­XYoÛF~÷¯ ‚>P@Äp/AQ g‘¢-ÐXè‹ëZ¢eµ¢èˆvùñkÉ¥§iý°ârwvfv曃z=;{ñÞQ™”™Î¢Ùu”Ù¤ˆ²2MòRE³Etÿ0™:mâíDÅ ßÁøFc ãF £›\Î~fYÀ,¦Z%¥*˜Ó)—“©Jm§0O`X†ƒQÂÈ`äô>¦Ã5-ÏRž–xŽé´ðP=E{ûü ¡qBg„.:ðS­îuÓùóVèŒÐ:4 C1œŒ‘³1мSáïåy…Ì í“‰‹Óþµ½#wLMšÇ8½AOÝá{Ö¿Ë6:í3®¡g«ùøqÁ»s˜¶äß~6³¨¶pX*þC‹žß É ÝOç ÏBÇíDç]Äõö¨ü¦·Ê©qúV•Žw7ÂpŽçoø$ àS(´ÃŸj-|`šéïç(PN5ív6o7¸Å mDFMk¡yªÍ1_µW°‡ûÕÊÝ,á”UÃ¥~¯:~ŽìÒ‘c§6+â(ͦý•,“5·“©ÎâvKRzµD@ËS”Ý;ØË®„ah]ث׬ÔpÉ^aB¼“3}_|ÆÐ*ÍúxXÀâòzØ»ú@/þä…kz!ý·bœ q:baæ¼ïQI£ã†4|à—M{Ç“Põ‚ä3Ò^»ª^‹šPN •ð§C5ÏÁ½Sçâ?ñ˜W¹cò[ØuŒm>Ø•Jñ²éäô:—«£ïñÊÊ&¥µrïŒï=ë ˆáN;¼ùÛRº%p`»‰`èÓ¦òá‹[Ÿ§ 7r°f>¨Õ=B¸«E?å%Sôh4W]Ë/i·!6 ˆåÜÅ3oCËåB~çùle‡¢¯R±dâåšâ*äÂR°Ypˆ…“¦dÆéÈŽ‚ŸÅ(šÑ§×‚†•‰T¨½ü©àM»£µÎ¬—’€Ÿóö³ Ç"–ÀFîôŒRùWKàG9ƶ÷æPñ[Y§ðg);ñ+–Ì ^ cÇ^Ã%ÏsÁ¯Š‡uš–çrÞ/S†øÌT­d.¡ùA¾ó°öG:KTªÇ~9¤žê´t\söì r¾¸T¹oaö¼K²lOÂ÷°}H¸ÍQ‚¸I>ÀøxThOöe žûÒéËcÀ¼î™³Ni²F…UeÏeô(ÞA=š”TøËA‹çî» 1zwÚ¶¨¹5ObÚÂ$&HÔáGn_À²MAOt°Ã''øK]*à€©zÄîEšè<{»ïëÿ/^&*ï£âÅ‘À#ÊeªâŸW} H˜j“% b”lÞŒ>E¦cÉ}§ÓõÙ?i©i;ñH{!ŸàËî#gEb´z#ç@—æ¾wÔN2îW¬ ¥PÇfø¯.½¼ÿ˜!s@ýÒŒÿÜ„é²Gä黺,1™{š»B¡(ê IÆæq‹¨ûVTqx/>œW³o0Ë[þ‡„Ún¼µ&*)ÝP¼™(¸x|Ú.,6ôŸ…€ªØð'[E$ûDÀ±9ä+Îù­ÿ7âŽo[½Ÿä9( †¬š îI}ðÔJý¿Ü—•ÀCGFÁ·Bî¿Ú 0¥zy¬®–p¹>?ü—dO´{Éžú,zíÿ«ïŽª]ßUÁÆ9Zëhòê «ÂÈiè9tÚå‰Qò§ªÖÞÐÿŒâç. endstream endobj 175 0 obj << /Type /ObjStm /N 100 /First 866 /Length 1677 /Filter /FlateDecode >> stream xÚåYKSÜF¾ëWÌ1¢y¿R”«l6UIìÂTÅ ÅAhV¼+‘]­Ëù÷ùZ,Ö±\ÌVšùÔ3ýõcº%éLzâÅdR;ü¦Œb2¦µÇ½gc2(f‚Á¯aÖGüJæŽy© "0Y0‘ÍB„ÄYÔšÉ(Xô–ÿVb"&¥ÃíA9ŒX\ ™ÈˆUu4L ,k I `œt¸ÀF]¤Úað¸ -âNI,©¤Ä*©˜R†Fð§µL”„Pm1/0m==Ž'¡ºØ9ÅhÖCžµø5´Q |$™@Eš†öZÇ †Á'N3-UdŒ Šê«Õ1£é9…CÛP`ʬ¼vŠ6ižö¬%.4É·`ÓúD)‡ °™FÀ6D¤€`΀„m¤ƒ|mÀ¼Ä–aIcˆ 0a í†1Ö@q)NÇ$`Æ‚Ø"ˆ#Ùß3iS&0+,0`ÀJb7V)ȃLK²”±Ì謈 +Bˆ5«Z7²– ­§m*h[°‹p/ΜP4¢˜“°¢NÒ.¬g$á"à"Úì;=à*ÎÀÿàÎÒ6rNË1×úÈpKKiA“·AZð 8É Ó eå5¨•‘ Ž r0ì•…dø†×†À [“‚1–0ƒXò ÜxóIXÏ{2<¨õA±»›ðãÿ. ÆßeEÂ÷êª)ªfŸÕ½£„«z½Ì‹U€íÐïŬÌ^Õ_؉À¨€ÕiK< œkq/^´â÷Ù‰lãøˆñý ¢RìKØ!R­çóÓkàÖf»»Œ R@oûĘ#—½ºq¸ÑêzÆQ^ßP(¶ûcÇß-ëü}Ѱ(¶Àøqñ¥a7+mÐ85ö“5Ò¸§KWý¾Æ].¶ qÚ8L¶qPÓ5îè²Ñú“•ôC%íd%Ý%@ÓEê°÷#‘1RaÇÈ´Ñ¥™`ÿMƒ4^§>ØMf£óQùï[jû¡‰<ù­ £šjèæ¨]ßܧ[pÔ8Ì?qRþÙ[YSÖÕ~Öì§ý_P;X)pÎ $qâêÙÆ¹ã²™c戽^f—Ë|ÅÞ®›Ëu³Ó*5[çÅ’fuªRµóu­š†vúÚ ¿>kÚ[” ÿ#[МJø«lU´$ó7ÅüsÑ”y–ð_«¼ž•ÕE[-u4!Rß)òçWõ|v·Ü~¸·GÌ0ÚRÚYëú‰+©7Ïó?Ëêeµ*o§÷ËóóV { €á‹²Z¯XtüßuÝóâö1†ÏjðºZ•üb™}.x–¯›‚çå2_/ÎçÅÞ”óYÁY¾¬+~¶,€Á#YžÃÀ|Vb‰U¹âiU7³âœ/±6Ïáóyv3øq]]dËõbž­^_ÔUñ‰çÉ[]fyqú#ù‡4Oã·r»þ!ísò6I†‘]ˆò4¥RÖ ¢%ºK…©Á/jåN&S©ì$RtÔ¨ò²wž:ÃP“ijànrý‡·gÿù•ìÃzÃøx¸ ¾Ò=æPPrp(PÓ6æP ¨òQc8ʨ}`[?x“JtK÷#’©ua½Yj̓{€ÍvéØr*ÝjPhPë:î!Çjù49öVn7Ç^u9Ï(ÇÒK—qáØ*R‹¬°!Çö…¶¡kcƒ„Èhý¤Ñ6 ><<Áöb·×ÙÓL¸»cè'XC/ÍäÚ‚\ë©9U›í4úý6ãÑÝ„2b¨d˜¬dé©= yŠ6.5›ÛÉ7W=O™ÌÍ0Ë›g›åíey{g–·Ï.Ë›±Y¾ TΧQÉYÞ 2r ×K㪩ͅm?´úy—ÞÙ?®¸²nvÖ<×°súiÂîVn7ìœynagíȰ땳© fcØõ„^WDîýH¥Ý0@ïDJãS+ÌÓt¯Ã¸vŒ¾#=&®Ýà ;}Â×.~[j¸‘oØûÀ›÷æfPG‰êUªI6¿ïÞPÊN%Ñ«‰^L%ÑËí|oÛTžMVrxx3YI»¥Ê{»_ÕÔõ'´®’ñAJò—2¥[õõ;â7K¶ó“â·²ú„D^/gŲ-Où~È÷Nh/â”6ƒ€?11¤"ÐKŸ†èéÓ9SèçBêµîeKÖ{Æ_×Ç5Ï?5ÙÙ¼HåñÑa?ˆ‘qÚ¶¥Š‹)}¾ù.R‰Ð~.ÓhwÉ 7àÿóɺ‹ endstream endobj 287 0 obj << /Length 924 /Filter /FlateDecode >> stream xÚµWYoÛ0 ~ï¯ð£ ̪uX–l@Ú¥[‡^HÝÃ: nâXŽ"G±ýû‘•¸IºµI÷@È¡iòã'JdŽŠƒÃ“Ô9˵ÐAÑ ´b&йdFæAÑ ¾…ï£82œG<œ€œ” ø»ùr›¤ ,3RÍHôÉä”Ö.éèX¸_¾ŸO2YÃËUÄ‚³œgέà‰3­ÃÆ'$ΤÅRÊð!&¬¦Æ"£Z„’ÁÁ„3""ái kbb®Ô&ÕuD°Tf>&o@4ÈZººiÓóØ@Dê{KÝfò1—†©ÜÀ(Q÷ÌôÏ&Q,²°]i?ÞnID¦L(³ü¬Ž)\ ¯ W MwäiL67 × ŒžÑþ„r2›ðx¢˜J–Ѷ«Y’eÛà\Pˆs‚Ò¢b:&XÇ›á´`Êf—hy?Äóœq³[Þ¸^ÒyCiP´æ>yÇÒ&5)G*M7ÞSØ UPèUľ• Hx'Bü–\“ ª5Ýk ÓùNЮÎU­F_åÈä;™ÆZo)¥Ynä_˰L‹§ËÃ| i­mÐÿ9M:MâûÓZÁ>5“,1z¯ÂkP^7µ\ý» B·ï®ÃµœI¾ÌSÚ†:œS ç/ÌFMïI«ö¸ÿ¸½tª¨ÿ¤Ïî?G¥lÅ.X¶#èG?£T‡e¯šÙŽ+%Ã;gùÆ5æN‰3…SáÓŒô½)eV=PmWë¯Ëû¾çõ#ï§ïúa§öEe¿ú&9¤W3šmÊùÌÎNé4èA‘jAvƒ¡v¶ðçHyi÷¾$¿}5}ŠDŒI$¹1˶|¼+¬=;ö8:Ü+CñüÓV‰v¸ö·À÷Šqz5«¾DF†U›M¦uW†%ÿÊ9}ÁÄRâîTàa`gL›:-ˆµÙ´Õ£ñÍæÒY™NæÎ“ݲù’½¾ ²;‰Á¹coâv’†DKˆ@à,ƒc BjåHMyG£ä¯è¯t_'÷îÁzŸt·–pãgbyE=˜Þ¼aÀ+¼#?÷RQÙç»yå³ßÆŽõ#â¾ëSg…EµÀÀc?Ìöœ¥õ=XÑgw°7ö'Ðú`¨Êp¬— ºŠ½d¸dœ»’3#â<‚~#TxmïŠÕðž¥.sÿb:òÿEÈdƒ !r–p¡Uš1gý ‰–ÍâàˆáÑ endstream endobj 291 0 obj << /Length 149 /Filter /FlateDecode >> stream xÚ31Ô35R0P0Bc3cs…C®B.c46K$çr9yré‡+pé{E¹ô=}JŠJS¹ôœ ¹ô]¢  b¹<]ä00üÿÃÀøÿûÿÿ üÿÿÿÿÿýÿÿ@¸þÿÿ0üÿÿÿ?Ä`d=0s@f‚ÌÙ² d'Èn.WO®@.Æsud endstream endobj 307 0 obj << /Length1 1954 /Length2 14534 /Length3 0 /Length 15727 /Filter /FlateDecode >> stream xÚ÷PœÙÖ £Á݃5îîîîîNãÞ$ nÁÝ-¸Ü`Áà$8—™3gfÎ÷ÿU÷VWu¿Ïògíµö[ME¦ªÁ$fél”vv3±1³ò$”ÄuÙX¬¬̬¬ìˆTTš¶`àåˆTÚ@7­³ÿ¿,$Ü€fà7™¤øÍPÉÙ ïî`ã°qó³ñð³²ØYYùþkèìÆ4ó°µ(1ä€ D* go7[kð[žÿ>h-èl||<ŒºÄn¶fN%3° Ðñ-£…™@ÃÙÂöþŸ´‚6`° ? ‹§§'³™#ˆÙÙÍZ˜Žài ¶¨A@7 %àÊe3Gà_Ô˜©š6¶ ÿ(4œ­Àžfn@À›ÀÁÖèzsqw²ºÞ²4ä*.@§ÿ+þÇ€ðWslÌl‡ûËû@¶N:›YX8;º˜9yÛ:Y¬l€iEf°˜`ædù‡¡™ÈùÍßÌÃÌÖÁÌüÍàÏÒÍÒbj³7†ñY¸Ùº€AÌ [‡?8²üæ­ÍRN–ÎŽŽ@'0ñú$mÝ€o}÷fùëpíœ=|ÿ‹¬l,­þ aéî¢ådëꔓüËæM„øÌp±²²òpó€® —… Ë 4½]€*Ùþ¿qøàëâì°z£ü`k|ûAô™y`7wàß+þ!²±,m-Às µ­â?ÑßÄ@«ÿà·ów³õ°¾€õÏßOFoféìäàýùŸGÌ¢¦/­ 'Åðå¿•ââÎ^_&.n;+€›ÀóöðáãüÝÿ²ÿSªjfûWuÿŠ(çdå àû‰·îý—ˆÇ_“Aû×ÚÐþ7ƒ²óÛ<´ÿŒ¿!+«ÅÛÛÿç%øÓåÿßìÿåÿuüÿoEÒîêiÿcðÿ£7s´uðþËâmžÝÁo»¡äü¶!Nÿ×TøŸ…wv°ü¿:9°ÙÛ†ˆ9Y;üÝF[´­ÐRÕlaóŸ!úï)¼w°uª:ƒlÿ¸pLl¬¬ÿG÷¶söo— èí¬þTßVêSJ9Y8[þ±{ìoçnææfæøvôoˆ àËö¶¤–@¯?gÀÂìä ~s¼‘û°rvCüãD¹¹,bˆþƒx,ÿ >‹Ô߈‡À¢øz³Tú½YªüxÙ,êÿ ‹Æ?è-Šö߈ï-ŠÙ?ˆÀbþz‹iñ7âä|Co÷À?Öt‹Åò_ Àü|+ÂêoÈõV„•­Ç?z®?ÔÎînÿrx3±þ|Khó/øÖ'ÛÁ7vÿ‚o<ìÿßJwü¾í(‹Ó¿à[¡Îÿ{³}{oüKýV™Ë?ê·D.okâü/¦lo¥ý«p¶·Ò@ÿû=€ÿNøüÁ[z°ð_½x«ìéü/‡7:îÿ‚oçâñ/øV±çŸð&ÑÂÝÍíí–þó®xÓÿâ?_ @ ÐqiÁÙBà“]Ý§Ž»1BO¦½I¡Yª=T:&ß%·oî¨pÉtÕ™7ÜnÅ’GzÑWw¤hoD—IŸ}[àÂÚÕÚýžLâÕgöÚLãN‹Õ#1iŠîû=»úiÙC·BvÉSåººó¢ªæcÝyöËxÕ”¯Œ‡.ì©íWs+ =•gŠÖŠ2 *™£Ê3ÏšÇ'f"†§Ç¼ðB›»¹ÅÌ™z%•g@üpÍQä«¿És?ï³V©Éê& $ÐÇ'†¾ÁŸ¡ö?ø"·è[Zµ!´˜Í;¼ü©?a^A›€Ü_ßíS“PF bewާE†›ƒ¶Å”2€š†´Þ7„ªTÆ*ñ+ÅH©I‘mÀý3±F‚.¤%÷’î“3­.z¿„X|~¶èŸ“Ž$·BXÛYþÜO÷ïX*Ìfda“­ Ö)–•Up¿Ohä}RE7ú ¼æ1ÿf²ƒ¶ ó+;®ó÷#yñâ©N>š«6$žŸ>uÅÙŒ4Ö`ßàO£›tò…ïLƒÙ_8›x.?1ʱ㉣žVdñ˧n°Îc;‚ˆ´ t¦Õ,uOȈfDPgŸ³:OËEVÔÎ0O8OꑲÑHF³Ÿ™Ó\L¦'ˆD2ƒvyϲùù›µÞ»J&ê8¦³ ›5ήî,p¦À7:\s'Ìãîý©IuÒC*=Íø¬1Uá{\m¶ÔÓ'sq»í<¾ÎÐ…œj]ÕÉŸ§«‡B(žâ€gÝÄÍÉ÷ϰú ª²ñnÒ‚¿¥äóëÓ7g˜•ý˵gk\áåLfàíf¶Á/z Kù¤ß€†îðiŠj®1‚Ú rb !ïîùÌ:àLÖi¨¤%›ùd(´Û‹îE=ì?€[˜¥ˆü|*ºôóm3²•k‘UHYxÈ/àgÐËdÅ–y:D„É+² ²ðÀ'_F<ègö¸º¤¥QÄuvØB4HÈ^  ÙéOßÍM˜FñòëÆµýrЪx×òI.ÿZÄÀ³êýö¸µþOÓ‚™²œÎõd¥,Pº8…·…´€ò}:HÓ’oNÜl³0ýcȲA̸Y<åë:¶ö'+48Ãd8ÖCžS3õ)c Úô'E<; Š12GÏuövŠv§1·-J¿È×MÌSE¸¤D£iß ÝÓ×Îf™dO¬¦ÊÝ?Õ;vñ#ëÕÏ+sûnéšl$¤ åÊ+;KŠ8rî“ â^k¨ýXßû úûõ³Ó‚$,F µ]TöâöüÇJjšR§*CÓ:#µÈOÁü¨Ûk­½ÜN¬æ|¡ŽF—ŒÇ,Ë¥E†z”Üï ‚´¤>S ¶D)婜ТLÕ1K>m)Vo—ãÞÐo‰ÞùpДSO'sº`OY}÷¹‹ –6ù:Ý>д_rã…¥n*Ùžs$!&Ö>Ý¥lzk|(Þ÷†¿=_k(䤇er[6–Ðð‚ÿˆeAÕæO‹M¶Œ(ï±BEû:Äçºà¹?½é»“ËŠùu4™ˆ¡ô) áŽZ©ÏåãOšêÏiJÔu< ­_Àú0†nÄ~\ÉJ%-\äõé;«ÑºˆO–k¢&“%c¢êÛ¯¬ì’âOF;¿uAÞçŒd‘{±öþ¶¡€®Øp7]þ°u°D¾Œ8b)/EÀ°ëÚ7Úð`î{µÂã”!œ'ØKõè9äW° cfÊ#ý¬º‘ˆK† ("-SØÁm”D±sª–#÷ÆÖ #D^•lò»£îÈ ï»±>°Íêè]:A‡ÀÆòª‰:6ouï!,©M0¦k·‚²|º“ŸöÄ,PÚQdHf‘ó-ÊϧšH|4$d›-¡k£K¹a²¾ŒƒºI ¡V¦us‡¬ç G¿Ù'éÑ-À¸-ÝÀòÒœ· olòÈæä¶›BöÇÀuÐô7Ña¸!¶m7}©Ï‘Y¨†*ʇÖ÷Ïø™‚©Å ƒ")ѾőûaÁèô¥¿d[ +¾’ì>HâÉÀk|Âë«S¯„+E#…¦m3úµíÎ"Ë¥í}°ˆ‚éòHv^?úÒ3áë‡CkÉ®ø:´ÊDÑÂoQ ²Õ•=Ç÷çe+ŽN|ãliLa¿÷rqÊ Ð  +OPú‚íxà9”Ö¼·}Š?í3n‰è_4‹î?¨c«ŠÛ _íNŸ¬x„kKÏŠÙØ×:§6}…ÝDÏä…!}•s~Nÿ®k8BYG '”OûkçâoÇ 4€/±dÖц¹ÑÐR6Ü«àù„­õÞÍûuÚBSö”ÈÖçBüsXÖ¤±&|Míߎj„;Ùó¸Hã0ƒN –ƒøÐö6JJ ñg”òe`·û!·UX¸K˜S¡–8Í”NÃê=³qZ†ŸCq#¯`…ßX 'ä1| Á_p}]%àˆN"é›ì øÑƒWŠÖ»àg ž¾U+Ì$õ©<Ë­ùÙ Ýæ«7ÙŽ½ö˜ÆðWž09¤;M›a3ÍÄì5ç㑠ߟbh¿"ëX‚´äî„ÎfÓЕüfaÓã-åï õÊÕQ+d¼Ñš9-iÑ7”cwˆZ|Éqî ?Œì‡¿òj#¦ÝAž_ˆ Mݹݴwné÷½nh¿+‰~ ŽÖÝ¿äö‰7e›óN·Îè¢,¤)•Õ|kˆªÂüQ²i‹è³™I7äv^†œë¿»Æv•ŽÔ»›'(`ÉXm<Ë]´g•ŨÚí2YêwñÕ¾C·§ñšDØ)ü]xS-`Üõ©>3Kù{>‘h{ æA–iµ¸tXç:£"Õœ£QfÇVƒ80°ƒž²†ÔÉÙk‹C€~Ó{¥MÙioÐõ’j¥%@Àù]—M öήõ*ááS}üçwÖía¤Ö)Îë«(dTÄZï±»;l"ŠÊÚWiç²ì7­‹9õ]µÁù%Œ€­†Í´o*øÓá “&†"1:à1ÁáÖhäFò}u¢*ǵޯ9t_o˰3¤b ݆uØ{fgœ“Ц± ¼w"–èÄÇ?_vŠ.[FMÉ‹8¤\]—’>]ór/ÌŒn£uÍHæ4™=ññ ï¶tOûV”d`Vè“5˜˜2¹-;,ÅÒŸ·»B~ÌÀÏÞ%Zjûñ9Œ £(iý‘ßÉ\!üA±­ß5ö}ÒÛO;.ã~>èreuízy´ŸU<@œÍ_qNuT'[S5XzƒÉîÃà…€/$+0áxœƒ-‘;‚®ä:`qC<±Ò;X£§‚X’ºB+üOoo?Yì<ߣP-\A‡®q³¥KbØTdˆÎ@Œ3ÐÊbëM4“™ŽþÇÉyaéÉÈþ”Ï ja#vh9/fqãPe[BSù7Æ!¥|SÙ‡EB}ˆ£1[Ò`Kÿ5 ì÷J#¹£€ŒmÉñB¼<㓃ý$.Šü·ÕL; Ÿíȃ–†+ì£QÔ¸ð"2Gå‚ËíÆž¤B/Í5éÎЪÑrÉ£Cë…=×<ë·ü(ñ˜9éEgA"+ˆ¶wáS. æÛ†nÑ|¨b}›ú‚÷ å£ïª%vÛ“'J‰Wx¡b±¿Ý{G2{I|_Ì¡þØ¥UšüaÉPnï}¸iÖèÃ(ž¼5!rV÷ÿþФþû²Q@mƯ÷=Ì_Nˆ¹¢uÕ‘MYV¾•úÂñ™~åÝÄA‹Üî_–Æ”¤Vü8îg2ÿÂÊÇÛï‡9º×gò:ÀÊÅBÖÔNp÷š–£ó÷´3ø%öB ¨”tY;?}7ù 1jŸß¬|’¾'EÈuî½F/ËÞ=QDóÕ\æù%(µr¾ýÒí¡ã/Ñï¨Gp%ô¸ÃlIõ€¼Ï*üZ,°ÕÛÜL¹{i< •+̨—ÉL,ý¸šT™žC™$Ӈ׆m×ÉH q†«E=©QYΊv”FU‘ªQ5aÝi¸ÓÒûø9íxm†Á†—9 ›l¤¤A$þ•ó,ÃÀøÈu^ê¹¥ÄøBžÀí1‰LgMA`áà€>…XC~^Yýùwt «T«0T—ºb9ÂÇ—@…¢”~K’:Ui‘³×,ªÊõ“9èYnvƒûŸW›é>ÌB•?T²&ÿNÉõÀ{iÒi]!b—häaTÈÊA›ÏŸlŸœ¢ËÝOç\G~@]e£€ìun«øÒÚŒ‡#Gªk‘¥úû‡D3 àÞì×Ç]ã¢ÎgœnâÙ$:;b•âe3@¿б³÷s´qnÅwj>¬”ˆøŸCTù]‚‚žÛ¥Bö"I“Ð+/v¢•ª~Dö·¸œÒ/'¡ ôºÏ}?ŠíJÒ®,\ŒüÓx»EwâzR9š ìZ÷سÂ>R%Còñ(O^PúøÇ÷ö|†vTìSTÞáûíq\ßCz0[¤{7EªõD'É,2±±ÀבUmÅ©~Ë^~3£ÛÚ:ŽïIA‚f¢îC¯?îN纵é xÀºE½ç°ÙÑ8ÙÈø©Š³‰!9:àõŽŽ~ö¤>‘j!¥w/NÍHpιÜj:ÒÁ*CÈ5ó[3¶|E¥$™þJ缂$áÈw‹žßG´{‚ùºøCqøÌY¤Ó²‡­(²¸áC!eò±7½Ðª/ÙŽ‡K^‹×¶ dÑU ÷ÈéËÈú%!7|‰Z]‘+‡ŽàäqíKïµ.y´¸ú™ûÕcÖã™;$¶v5…ÖÝhºØ@’ÀŇò÷É-æ[  š_Èc~9ßSj€†ËËürd~jüW½uëha¾²ßÓôU· +²`þ‚EÏM'TÒe´ÖdÀ¡¨ØƒBºˆuL/Œr¼kèQ 'D/:]¬fÑ€D7æZiªºFë”Âèÿ±=gÁöªü—K‚_VŽFRZÆP“‘±Î.×è ¯Vä\¢b‘ùû—æ®ØGFD·: ôÚ*±$JUàåF kx£Æ\ÖÏ_˜dFuçï|êdüàó¬LÜŒ¤dâW6Ì\W2c¬ãJ敜 ^Sà=hk$ëX®—Í+0#-·Ï—Ô«Vd2DDÌäû´5Ѷ^¼Vª^›­ ý7ÓMëôÙ£¶¦Ãý"a§}wÅä-RÔÔï ‘],i×ÑV2½Ó~5ß:KN˜j–ËKĬ^Ɇù¨›­^Í«>Õ=,&¡/EŒz fJˆ¶¿D%*¹L ÄF³N‰”>‡ ô5®cBÊÔ òíﬦJ¢_±q‚gð’Ì`CºÈË]QkÍ.j:7–†èwž^NÜ~Ÿ,]ú}åçoF׆UŽWéÑòAY•5¿0“©–”E­>¥ä¦ä+v4¢WË›C6"vÈ)ËáK,dº6š1+¤a0V! J$x#:$ÃóÐd;Z%"Q78² l•ñ‡ìÛ¾|)ÃØs'®CqìY*OBæ¤A‰² ÄÅOpÎ>èÓæÍáªbqtC [Eì›–_;z>zCÿ¨¬Ûì2Jü È ïê¼%¿x:H»^:ß$àÜ]Ó–*Süùè5Á2)«$ 5dÝÑßíÔgž]E”ù½¶Mt|ŸÕàÞÔÄ{ˆ‚Ʊéòå‰CÒ•1q°“ún Í€C ùz ô®¼À‚5UÞÓ¢‰,ðó,á± MB'ÉHR²Öu ®y¾PíÉ@È'ðe´H5^ABË5Á>")x‡b [ä§}k  Âåé£ ‘:IÍŽ )¹ºÏE‰ÎKûêwˆÙ£…Ášãˆó´VÑÉúyÍ5eÍ!‘k¼¨Â•³ ³vù /oÿV^‚aw—Æ|?”6®ó‚WJ:г²¥`ELõôæ¡V…Ò-ï4 Iš¹T—Ú±,æÞ;t0s¯÷Ï÷' y}ZØãëåBfÆmþèø;FÏW»¥¤ìßñÈà!%JwLÂw¤åygžûžÇGØ}¯»Š ,Ð1Ø‚£p†¬ uG"Z!’1ó·|»ªä–C0¥ó‡FKYe²2»Ã·T j•‘ø[ÌçÛ>7Jp¬fg›Ðòfóó›zykëSæÄ?¾ƒYûl-=×ôs5ã㥹¬šAötÉ%YsàZ9-§ã%*ŽÀÊÕž°ÌŠÔǘÛ’l«ªl?AÁ/·ÏÄô¶!Ž;pc”éØ}¾šŠ YUô†dÁèl(LŽþ•¼fÀ L‚!M—G ÃfâëÌüùªÛpÒoVÓÂó鉻‰´hhAñ®¶²´Cä5„ùo£–äaJÈ)o¸¤n¦7Ú;£¦Œ˜¹üˉM Ãìc@¼-šè-èo¾Ù}…C{[r7SÕ÷[ò£­ÆÌç™^ŽœTÁ¾P/øÜŠ s0‡¤8–1­—@„ÊÙ˜b) VÀtÆ÷mÖ¶ÜÁí¡‡í&`ù‚´î;ÓÒ_>DûÐ<æ[2õ‹Þíš«‚J6C<4œPöžq̘¯¬0×6Iàuºñ/É%.@Y'ã-¶4›'™4…AÝ–ÅÓ®hxx–Oª©vâÒnIÕ«æaŠTeÚÇùâC·3Ô¡>Ç”ód!7MWQ…‚Sö(,F;œÂ0Å HdYg¦%Ì¡¥vµõw8È~>à;8xO]œÁŒFIdÛÕ±”˜?£Jé?;ÿøaÔ—´;ŠìpÛCÞ{ÒîŠo@±M$—>îk`÷žG®‡“þ"UñúQÐ4öÊ;|hÝNì°Ò1dþ«)‡,Ú6uÕô&†¨#¸`È¡,~iºrUÓÄ8ž.4ár1ߤ¥P°£Ë`kÜ©ó}´%á³:µ›? ßà÷>®- Ô¯›þ—"Ä3-6ûã5>/&QÙq™Æà_È r³Ž±M›«Ü^¢z>XˆPEÈ4nžæÁ •BbGîƒE¨¥“»›ÒR“ìÛ‡Tñ½„A7uÝi Dy+vwãF¶ìz¥ÀP'I%1i£1©9pöÍ0ïtÔ—‡¾%7U S[Xn:Âe¥¾³àÁ°vÇ,äòÊ¥J'‹Ë‹v-?¹Å‹a„;VF?‹˜„µ0 –•K¸2k4žgyؽÊ8Ôïñ¿}Í{RƵaûp»…½uy ÁúT)EIµ\¼&j2O ‰G‰EVkTÞµv‡ë¢Æ¨ÛÈÓËÀå'¥ï'Іºå%«ajÛ\c¿Y$ vV•G~.ï<zãsÞÖûEÉóù¥âG(~MQd$…$\\òì·Î‘yüb à<ÖÊüUüÔÛF£~o¬fNº'!Âöó´Pj›WäšûíÝëGɧ^kž¸TÐŨ'2êOà›:2q7K@õ[@™3xJ–¥WÙtØ‚ò|ä^CúÂ88™Yuäíž%äBÂFŠîl+ù …™$Èýo;§þ¶«ùºµ°ï£æ\´.{¬#Z³¶=~P &ÞØškD~ã¶ŠÚUó“a;s ý8Rš— i;dÞ)Ë Aäf‚FAN?ßoÌÄ/…b§þÇêÒ½2]¶có”=æ÷>^Ôž¥^Çžä¿ÆûšöM¡ùèJ¯Ì½távÄF`6Šé¶”˜’Ì5´€¥Åm+‹ºÂ t`¤tÇúžýoDή´:ÈD…r6ýL¢†_¸œ²ñ08wºö5¹{­¤“Ž9SHáÍÝi.öœé3¿k;ìß(dýævBF×V§ˆ¬Ó'g>"lŽ$„íX:ÁPǜРáõów|PM×ïä([x¿zÚ$¸ÛºQᦉDÛŸ?ÏN=;û+*éÌUfÃU'Öð ö#ä¿#»Œ¸%-œÂyFoßÒé¬@b™^[’\Í,æ¶8Îë¤)Ì+cµbBG=ÔS#Ô.K.ñ €¾±#|Ú%§|Њ˜Çž’÷¤sxRÉ“yüW~¸BFc!0÷$«Cm'ÉA­“N’'­¼×™&J’œ6Ôf}´˜:!«¾ðzÚÛBRSc2èí zèý~\ˆŒ „«:t¶¡²ˆ·/0Ôñ M¹¤”y69‡íÔtáY¤)ôÊÌy êî v0íÓ/ÙóªŸÒQn§ûnã¹ð“Ñb=¢í¦e®Ñ'ð^åõ›±k1~”¾|´ãÙ»rxМÃW(t—‚ÚUƧ¢äÞ ¦Ô—á¦;€©†®î\_†Â9n˜V»ñÙèNøô“f^ü1x†fT‹\®.š†)×µ§cö .÷üoÛÚ±?N1Ü´,NÃÜ]œ>Éëš±Q `³.†Ë~Ì—û”ÇßÑ‹/Í/™»ÐÖÔ®¤æ\'âM‰ÏéPØ£å›UàˆùR¶m »m¸µ3}nA£`FÈbMqju0‡˜Íî&JÕCz¬P áYz©$j®Æ½ ™œüÕðãxˆÊX½ËtÛ[ÉKáÖPâ}ÓhÖTÜçú[÷+A²zÆÔNhBøäØâŠk”™+Gǯԋ°Ÿ˜¶anŸž‹Û¹xæ‡ñZ¢šŽŸl½æš‰Â?~ôª*rGÕº»‰wÊôžã~ÌÕÃæê×V}oš~Ü)¤6œ4/ÆÝê¥Åµ—…Ðà ãwŠ‚DxiOfT±è –nÙËzOÖÅ¡–¬‹„êE"©yHäxS“ÊI{z¡¶þû¶àDqÞxhÆ,ÊRßí…]|.³Bå˜ÓÍ °#s±ÌrÒ":U¢• ÂؤÿHâ ,ïâY[Ôˆø8ÊðPÎg0ò%l==6ÑA_§R¨ò,G†M±ø¢*ÐMå€è.wÃ÷²®ºÞàRöµ¬àfYrïóGY§ ׌F8mk«ô®Ûõ9~‘q¢â!ˆ>IEû#³,Ìýp‡›6¿ÔˆzfŠ—Í9Q•Ó´B@«æ<J„aØÏKBŶXkAóFZÆ!Ý oIgäË á" Ñ0 à>N¯¦P_­°¦Âs—R}¢á‚’útO]íâOP ÅÚ{b+ÕD²è¼ ¾O^âÀÑy{ªHSä¨1×¹&Kq>ŠyìG+j2 ~|i7„ÊÝ‹arSK¥w¶æ)½0ý::fCimh‚ó¸p†ñDŒí‰ ¼õ·™híß@Jº;êé‘ Á!N"„H°«ë³ÇÓŠè· Ñ×ÎŽ§‹¡÷‚à‹Õ×EúX.ÈN+ía‰@Xª=TP[ çk ñØEm¶ükðIÅoèCM”Ì k:`M…bzÀõ=‹Vuíh«P§êò©„Y‘è¯L Ím.£Œ3‡v‡™ëiÖ¶{ÛäÑ*˜eAùæoꩃß[Ò3µ?rl½bK†|Ïý²¾ !@Á?]éWXu§ -Á:.äXv¹u†X~‚•0ð,ŒºÕɤà.§|øð+ÛÂw<9`?2SüÜý‘çÎJQŒ¯1…’1ž(‡ä¸³çö''Ôè ÷ʪdƒzo–V””²’#|™Ç¨ìrý×V–˜áÊLæq¾wn·º%e7ë:+µTHã#e×sFþ±`"ŸÜ-T¢m®²]ˆ;9ÈÚ4gE6Òå箫êµ–Or¸ ô>RgΙ¢|TO$NŠ*Ö•vU5V¾6ÕÖÉôÄØÂaØB`\Ê(\äu~¿]Gò†²¸Yý_SÂ>U?”Ä꫞­0]ó†ï›ï%À *„”hµ|ý£÷ÚmÕ ¾—J£É¨A/Z÷ŒÃÍØfœÕΚÝSE.RózÑ 2¶E0䙨ùß)ȵ?DÝïi “¯ˆ–/"ÏßL<’£xmÖØ!øä°ˆ“¬÷‰-?ÚŒ+IzFacò}º¿P•ÝëÓ)Ååg+•‚Ä…=ã"|êá’­«žÜd&É¡I5½Lâ@(Âc‹æwž´ÉR­ŸmjøC¾é”ÕñP<^Z¨yŽ‘°Ï‚êøhLÙ3^˜çŸA0‰Ö>Iìn)Ä“‹$o—Æžv–XÇ{Ïæ¡©ïzwÙ)ì„iv¥Îª&ýÎ/óô)ÁuBØÛ ó"'Oin–òqPµíUy¤‹"³$½I¯#ŽÅ‚]h ˆ{mð&ïËS~Ã(¨?žˆ8NiÈ^À²àïó‚ÌbBô <8ΉKx¦^!L© ¯q‹u¥øžÐÅ!5â—áåcv­râšásáâáï,\+–#NÌÔÂ"ë.Ì`•AÉâ&vdY£¢¾«yïº@¸qkóà¥À×~$ŸÆþ»sÖj ó º©õÑy|fp‹âÅqÆ®© Ó§Ës¼ü<ôFiô˜²-Q-ê3š¯²À ôR«—;~r;ØÍ›¬²Øc†ÃΨƒyxP˜Ôãf˜g±°)9²Qÿà`dŠz¸×Æ;môõ{®>Ík}ôâXßñµ‚õm»‹3×ÄÏ銞‚R[J˜ñ|ë-adKQ4TÍÆ~Á—ıŸ4¨å‹b¯ª!C>DÅzö¬”K¢"ÌHAàîm³O†÷aM-ù*jjr:XI”U„Sƒâ†ìáÊí¡™ç¡ªÃï1𓪷ùÑúA½"Ë«Á R5ñndáRÖS£fqµÙš•e[Ù×+,+\îMxtó–j0O$ïP Xæàº-óÁ¶UûúD8»R{[èze{AœñÖ³dÐÚJ!ê ¾É•g¬ôí°rôgž¯ƒ+…Z¥M»`·µK¤ãbUQØ× ÄX­pä}økŽ·ÜŸÂ—Æ¤Ó|O¸¯|k÷éUÔë"J€C[5Q3¦­º¿vÀì°yL&rjoäýåáë çÌ­iï²·î/׿pfãZõ€ã»ú [ l ŸoÖ »ÑŸ%«¶ÊØ? …™“šRªŸÏ« “®óøYWMìku×}ùãКún³’Éù_Rî"'\>Z‘¤—ÚÝ@Š³Ž ÷Úã_mN…Ê~—‘’*'Õkqÿ晢Bþ¬¯ÕɨÈ6Öêc·¸NÇ}I×£?N„7òi¥WE¾øØù5´áåU=J‹Ö[$—eäs¹+<&r2/1®ž¯ÁLk®ç•þi=4£Øs`Ü8Ö»KëÁg—¥q€7=¨¶ÑÎCXNS¾²yÒÚ ŠRñ€§"M4ªf&÷Tvâ›q¡é,-JÝ&µÅb¸ÜJOlSùªmÖn% {LgQÝ]ÔÎS?î1CAÈò—…ê!Qñ®ŽåØvøìVêŒÁHŽý˜‚|Šv2’'L 4®«§±R:¼«V=K–®¦­+èæb}å¥,ó¥rŒPh®¹Ïh©)jßñä©v}å_¾ HQ!`?¤›¢—R£  ±„—ékÕWÝÁg&|òOCÞ¬Šìôvé§®üèuÈ4–cÞÉ›G¹ÚôZl½ ¾¯yeQ“ˆF8Ý™·“9:öt\ƒe—E Á_œ¸“x¾¯^PÖ)Û=õêǪ²³I³lñ§8m; ½Sá5ЇMuÂ/íwY.(zOf€s¤™ÔH.t,á?N¸šZ>çe¶¶úõLuAÃN Xk+÷ÒÏío±¡ºhÔàdúVM‹TzKj8–Y_Ÿ¥Ö9 'ö{T¡öÞâ‡@«¢bÌßY~ØcØóòÕv+òëÁ¦õŽ'±2rWg6õA¼›šrKáZšÊÄ¢©ü9‹"úCIÞ\ÿ.¨F4á[íÞ,‰ÅD§R7‘ó‹®²S 4Yô¥ÇOé$k.&…5ó`Ämœ¾odʈçPréÙ­‚%‹öïÞ?…BfbHyúÁ†F~~Á/€8Ü”ñ!¾([pÞ-æõ—Øg\›OI"E§"ã*™0t“WžíqÍ!¡<Á¢®Ÿ«›äNu, óXP@y}¦kñpJòßv¹Ì«?-«»ë/÷·b`¿ófèšs]¤æÄµKç±€Ðì.ßË3¿ÞfN—íå@½¡ƒ9¬LCÕY]bè–¤ö¢Çâui ÀgE¸vªŽÆx¯crŒo§nÏà ­‘ü{>ËàB6¿§Òèâë€îNA ‰ãwqõu E&Ã#öIV—ª¤PhVÔòãu]¾j+£Gzv£Ò™éñ’l;hÊóUë§Ú^>É•Ÿ&8šN•&IÏPœj4â@ºƒãtµøÒ~{áÛs¿¬r÷—51EuÈ]HŠúNXŸ_ÁeŸWJï²çÑ©.Wª]ì^µ7¶%2=,•wm(›J†±Ä˜ü~Ú?¨¶Êeе)KU ïçiv9TUh|Š?ŠÁ¡ÜåQ¤^!ý1d¶B_¸ì>dôÊ©þªZ™tœuOšm'ˆ¶Æ«;/ÚX+äÞÔ®Ñ!·/Åg¥|¥½Î~`KBŒÕ”Ÿ¤…·4èûÖÀ&rg¼J…ý%УÙãœÍ%ÛX·*{Á|¤ÚÇmAVAÔËãÔ.Ûi#ªs·X´.TDYg£½wX¯±‰UŠE©>Oßj%q47¸D€ 3®êÁ椳ˆlQ}Zœ]·¿5á; IúˢѹœÞdêWiÕS¤v…µÀìˆIÕï«Ë”:üM¨ˆÏ´ÇÉ;–?"µ÷ï'¿NÃevÆú¨ô+‰,£¢¤Ö=M‹²Ï‰›4È'WN™¢µRÙ$¦8ˆ=»¤(-j™zÓ¸ ÙX/¦u‡«‘V0tC#öNl”¾]4šfÖFäšôÝüñ¥á§­iÊ"+Àx‘+õ ™£–SK¨;¯ÿ¾“øeüíæ²¡™È^ìÃ*­‡ÊMþV§ó¯1#K¤F „Ïþ6Éý&©3óF§îëâÛÊQ/¨s8 Hdö>\c‚uxzÃéšz]’€æèIâ3úWËqáv묙Ù³jòC.ƒ§~äs•*9–¥7]÷èÊâÕà-|±ª>› Cúè[Á(¡¯"ä²Î1E'M„”bD·!Hš#»Êx¿àÅú¼Mz1’1Šu¬­Ã{§é”êµãxΞKòOR'}ÙÛa—Ì.5ÈjC.׿ô'b¨œÇí÷]}Z™ulÑ.Ï\³XÃyeÓwÒ™ÞŸÄ)]ŠÿnX—À±(ɹº2SëG®~ÀwVó#]}Z6Úä+ÛàØZ1¦³.Æh) .V±³D«nl¤üLEˆŠ.7­'?ý³“"´S 2sÜ=ÂF%“’â Ý›hò‹%Ͱùq½¶=Yå¸ÁðT\nÝõK$hÓ¶Ë7l$•þƒ æ^*úõ4DóhbH¦žó/ÈÁßôÒè±Jäá*ˆÖ2PQܱU¤Ë¸ôYs3zËÜY¹¯/!©§ùs͇x}§ÈßÂñÖ*Û‰Ôå0@›­ƒËB¦ò„Â7Yª åaÆoô7ìÂÝùб-mÚèO‰9¬Úí7„ç¹V0ðŸVb‹ß%|f蕆ÐfÒô)QÆýzœ ªÜ”ãIr¸¤þ^Š`45(` Y‰ÂL²«“xo4ò'/)övDUc1Ë®q –L±4OÖª®q&¹Œ¯ÞûéFTm<Ž •ûÆËuL5ˆ¶"f·g컽)/D–Ùœ…JµK×+­©=åÕžÒ<ôþî’ºÁiÙ³ ÜûѰ£]ó¯õÝG%O;gÎþ7{(‚(uεÕ,Ù©úlÌ(¨·í,P«„ ØXs˜º¾n˜Å¶3=qr»WÏ5Ô¹aÊëLƒSÔ{c‹ Ñ7uT×ñásb Fë«Ëî{ö“h´ž¥¸÷÷?Œ{1Ýdßü6€Ü&½哉±‰†Q‡8µÒzé.SøJ@ï}l62H²°òhbM]üéz*ŠÏ7•N”‰ ì6¶Ç¢µ~ez§ÕÌpMßâ¼\ïW€ê]K–Ö[™‰` XúîŽ6!VêÃ…ÂI†Ð»ceÝr¨úúD–9Š¿¥§a"Îö)Ha ßX0Év:I:Dx>îËB(NeOÎ[«î¸ã‹ct›]l)rh»Ûe‡8;P‚à,ÜNÓVDût]8ˆiôÕ‡ƒçvÙ—1ÜÙÛæ:¡•ç§I™°ö´äR·H[Ä ĵ¨Õ^Û¡£êËÉl|£vÕh%:àòSÛÀ\êßÃ$À;é, Ôpy4 …ã×n2Ý·9îcàÕý+…ä0Ïùïí¿Ux„aȧb;ñvT´ôS„%ÓT\™¦{·ÀCÓqê!í¦›Œ×„Üãsz/¾ýUmbRà2ƒrÝ;ÐE@ÞmcSUÉðÇ«o'̧‹R˜¾…2%±Ó®(.ƒ¦9övs-øþr¸!×à´áFJëT3ZÇÞDò±\‘2|hþô³¢C垬w¾ìNéÒé˃ p…‘}ùJWAIÛ“—ògœ~ZßTæ‚ ªhzÝÛ1GÙfTÜgðLŠG÷àø´ªÌ8¦JqBòñFkâ3%J˜/]„s_̶’÷.åÖ` Gó¶aDbhÀ’·5g•úJ`Ô/ß YªáÐ#>‡ˆG±ŸSÔz“ •›4¢¥¿†ó£r(à˜§2yºŸŒ²v¿~ÆrDUXº±øÖP)Š"™“íj·3A}Ò‡$ÛDî°à”Å D4)ÌpÅþJA£È–[ÿÔ®€âØŠÎÂ÷5Ê+Ý‚ï·)™ëïç>Øõò«­iŽ–OÂ;ç MÖ~Ç8V-ˆ'k ˜@£òP¯ñ 0¶xÂÞ-G‹Oÿ¡í\rIw#ÝTüçÿ.©PÚo¨~ |oÔÇ;• ¯ä]ôˉˆµ•à#[7T‘4ÉI< â{“w? ìO°{|±üÌ” w¾^åYRyIR®„û? ÜßG±²bwœRgµ•(ŸœÏ`ÓEuù%Aÿœ&|Ù¦5Ï ‰®’ÿNÜíŽÝ†'¾žÂ½†Ë,2@u}<^sŸ0;µýþ$Ìw©W¬Ø3jrrMþÓdub^Š_œK+,I®ˆž$¿ÍºÙ(A®…$,Œ¼y›XÇg+u©°HŒA°µC¤ ¶3® ÛR~ºôÑ—Žœã'+Cï÷ªucÖNQd]’GÑÊ­±4޼Ü3à›k§My­(Ê µÍž‹¨êø/)ã¨ÎAªÒ…Øn`—;ìm?V÷lYœ Ë­I² u\o¢¤ÇÏ2“³CmEq0Ö‘Þx¸ÒZ¡1]:F¨,N5mSwýØ—³^CHš'sÌ-½é:ªXâ!Ýd^ÔÕ!ô–ùYaY¶\Á3Öêw{†ÅÈåZrwÇp‹a?U¾hÅý?[™œ endstream endobj 309 0 obj << /Length1 2102 /Length2 14187 /Length3 0 /Length 15444 /Filter /FlateDecode >> stream xÚõP\ÛÖ€‹âÜ]w·àÁÝ]šàÖ8Á-¸ÜÝÝ=¸»‡àw‡pÙûHöùß«º·ºª»¿9|Ì1Ö¢$URe1³7JÚÛ93²2±ðÄäEµXÙ,,ìL,,lð””j–Î6ÀÿœÃSj@–öv¼ÿÐs;¿Ÿ‰;¿+ÊÛÛd\l¬ìV.^Vn^ ÏíxâÆ®–fy&€Œ½O)fïàádùÙÂù=ÎþhLi¬<<Ü ›DlN–¦Ævycg  í{DSc€ª½©%ÐÙã\Ðð[8;;ð23»¹¹1Û‚˜ì> Ò2Ü,-*@ÐÉhø«d€‚±-ðߥ1ÁSÔ,,Aÿ¨Ú›;»;ï6–¦@;뉋Ð ð *-PtÚýKYî_ €7ÀÊÄú_wÿ¶þË‘¥ÝßÆÆ¦¦ö¶Æv–vŸæ–6@€¢¤“³»3ÀØÎì/Ecý»½±«±¥±É»Âß©$E”Æïþ»>©“¥ƒ3ˆ dióW̹yo³„™˜½­-ÐÎÿW~â–N@Ó÷¾{0ÿûr­íìÝì¼þCæ–vfæ•aæâÀ¬ngéè”ÿ·ÎûüŸ³Ï@g' 7躛Z0ÿ@ÍÃø·õ¯ã÷¼½ìæïe½-Íï?ð^ cW ÀÙÉèíõOÁÿ<++ÀÌÒÔ`üliÿÇûû1Ðü_ü~ÿN–î]–÷ñc°üõùï?ý÷ 3³·³ñø£þ÷3«É+ËÈ©Òÿ»äÿ EEíÝ^ŒœìF6NV++;€›“àý¿~þÛÿTÿ÷©’±å¿³cùãQÚÎÜÀó¯"Þ»÷ŸB\ÿ=4ÿ^ZÀÿFP°Ÿg €æÏøë±p²˜¾±þ^‚¿MþÿÍþ_^þ_Çÿÿf$ébcó·œæ_ ÿ?rc[Kk¼Ï³‹óûnÈÛ¿oˆÝÿUÕþk¡EímÌþ¯LÚÙø}CDì>Ûü·– IKw ™’¥³©Å¿†è?·ðîÜÆÒ¨d²üë`deaù?²÷3µ~¨€Þïêoð}¥þ7¤„©½Ù_»ÇÆÉ0vr2ö€gy06NN€ëû’šÝÿžm3“½ó» à½8o€¹½ü_7ÊÅ `ùëè_Ä`ýCÜf±?ôÀ,þ‡xÌÿ%n³äb0Kÿ¡wŸrèÝ‹Âz÷¢ø_úÈ`VùCï^TÿÇûØÿ¡wŸÿ%ž÷<ÿÐ{“?ôÁô¿ôW‡™Íþ¬fàñ½ÌÿºÜ? ï)™ÿQxOÉÜÒõ‰í]œþað®òùøž¶Å?ð½Û–ÿÀ÷€VÿÀ÷Ìmþï©ÛþAÖ÷ÔíþD~¯Ùî}Bþ!¯Åþ¿Èñnlÿ?â÷Tþˆß#;¼oŸý?šñþŽcvü¾§þÂXßSý ÿ]ÿHè]ôþ$ûcðâO'ß7ŸÙÙ øÞ½×ãìfÿƒ÷’\þïÝpý¾äöÙÞ­ÿŒíݽÇßø?Ûaêâäôþæøûùõ¾:ÿá¿_S@ ;Ð~eÑÞ”/Ȫ.¨ã¡F„ÀqoR`ŽrO3…–ÑkÅ©Óå 6‰¶:#à§ÓHÒHêúŽÍ­ð*É«×qklh[‚rûó—Ã8•™½vøåiìÁ©‚c‘ú¢„ŒjÂû_^¿hø[C¶‚wËPæ8º|DVÊÃxpë—r¯([YÜSÞ¯æ’Ex)›eŒRÔó/ž§Ì5É\À%ƒqf$‚£C¿pG™¿½›CÏžz#‘‰£‡÷>‰b/ôÒÙd‹~\ðüQ¡ÆêÁ£ÀÓÁ%‚¼EŸ¡òý•,ƒ³äUR#QdNd°Ø,؉bìÈQKÚ½Â_66µ5†{hè/V†²3cª¼M):rh£šÝ…‹žSÏ]<ûÊj˜Rî:xÅöŒ¨œÏp ´v>Ub MýoCtK#Óõ+ôWò×2^ÞàÏ,uCü›¯pÜ2›I®³n¯—±;Òi÷Ã¥÷Ô””\–îšö© Ú4á¹ñ(«i6ŒÑi–æð`ú›µ 8AiÔ „¬ÕxíO™nOä·ï YǦB«üûˆ›KŽj{.AËfeºÀ™è4+^™^;¨1Ùçpr6Õ¼ÝÄãLQt¡ñ yðû :îêcã‚ä°$?gÍ,g×LÈï cŸ¾î–aÂæZªš'âOQÓ9!k rÂ¥Á«PÂÊJFÜ$Olֱ꽳Èi¤OQÿíVýv¹ÿÒ@»û}z[oKSI¬FcVï\aŸ0§³¯… z^DèÊÆÔ[*¢Ô|_†Ðía®êQ²µØm²‰6ñ݈DžÈ!zðNi{8¶FÁÅi‘VNÀÅ¢4z!`vX|r%·­Wi> Ø·¹…º§g~—±dÒSnb˜½âÀçnçS¡N çž2/ÄÂl; òâÖSâ –©{[v¾+î·2|š´t~þp®å4NÙµù´zð9zÏ4©Î\pÚ_'튄pÞ¥jÌÓv©‰G{§ˆw9x,zx¯ærˆéNPË‹PIþŠýo>p«?&N£Ó+{PÀ!ùÀƒhF©W÷Iü¿õš×"½0šj~ OzÅ+ù8ú¤2H£‡RÔ6‰‘Õ¿2ÛöBáp‘@:MF´~ÍS©àÖ¹ò.ÍXÕ§?öãjÀꦎ~À‡±mdì¢û¹Ó³ÉQ„I±’¨!®ÃXÜ[•:¯¹*›ìÐXx–×Ò”ë£ær_x±¨x\ÏŠWAúèOècœNÅÍQxy¸>Û=Ë ÐF?V¦!‰cºÏ>À^3†7ôÑzÁâÄúƦë@Ä.ö§qÚ^c@óBÏÒ|7ïEn±n*ÅD¶ï´¥)ÖbªÕ«Ø³<Û®Ñ8§S•\Ì5o>în}ÁðÓfe×„ÏæoÓô%y£%›a¤æ<†‚JGÕÞp’¥w•‚ÐËû)IM)°{p D=êpô2¸§ÐxÖhxˆü‚ Ÿ|ª ʇÁÕ«}ÐÐ7|h¡xp’¥²1 ƒè§æCa¾±=tÄÚ¦Yî?Nf²‚9Õ&•žÜ ꔟoMEO|ÜVÒ·ý Cn Wº™I+ùÊÕF—øÈSä*`!Ñc¨E3è¢ðKÃ_|€cƹȟ·¡ÅQÝΉAs¨%–S#A,s]ÞÕŒª·<¯¯•‹‰Û–LÜP•þ²bC×2?NÀ«MØÈ(Hè0Â}—Ô"×öÜ0´¬“5$æS?dsûx[ŽÞn–ÊZ0ÁËìÿøLÊ€9߹¬Ië‚hîRW"‡Ã #¸ßÁS…Yóñ™ñC»‰±¡4ô~c‚­EBÐüŠº£Åï@×1½¹Ž)sQŒÅ…P=ïžè¤“ªloAdæƒ#=G=ÅF¡àlkAŠyPX–N¢C"¬ÚÊp„Q¦3qÁ„h2?4ÿZÇ,æ¢Ô"49¶."¦_Ð]á´4oÃa'Y”Ù*%ç·¢Xh!x=gu3wœS’‰ß¶*Ãw!C¯g ?IB(ƒ÷Ì…;Úg‡½hëÏC£€0ŸíÕí¼ü²àróA1åبrõNGQ+ü 7Kþ$²ôíÄ\vþ¦’•Ô¿2ª8AÕî±``LJ<Ê×.DŸ(«QÏò‚ëQfÂ2cÔq,ÅV [0ïÌùêA§úŽì}f)¥ÁåfÜ Ž³Ea[âÊê©£L` ·pÀ¢p¤â˜vGºFÇ=â"§Ø1)`â;ásöbøCæÃ«X€´?çe!4‚¢'¨¸áÔÛEÎ(Y~Ù¯¬‹Œ;K¶kòìþ ýj7äÇGE@„×ÕUlÁ—W#Zâ>&ñBBöÜ•ý$YŠ$<Ìü_R; ì¾uiɳ?@ß3ÅqÚ7çTÞ ûÔšüÆMkaËÙNâ)ý_<ÄõäÐTy>-_(Gu,d:™ßH¼èqr†&‘טּbékO5Ðb`Ëîª6øØµ¦VÊãk=3|¤Êç6F4£øýíG‚3³&ºÿ²ÇT·ow?n1ÜuG‹²¬íŠÀX°¦x‡™`»=>ðhU'Ýa% ß2ˆˆ"¬/÷fó¥âŽÜšŒ«[6 YŽDIkì§§ rQ¶Nˆéì½÷›ÿ)-%ŽÜ²¬¹"Ê*ÿíMÂ|ƒzl5cð­ÓÉ7;òÊQ¥¼Õ#RÍÚ[°z³îÓéâÏLc"íc÷³K-| =¦MƒÙí.Gãa‹g©©(4ûAMF—ºÂuÿ%x?RH3Lá!B‹® ©FÚòüLÎüÚ\rž¹X!l<ÑurÜÐx‚4gi[ôÈYÿÖ3@¯'ºb#Q…9Õ‰£àø×1¶üSI2öXú’¤›ïð9“:ZÿÊ·A§Gi‚Øa‹LIžšlµED¯Xš<ª” ŠŸÁ±¾¼c7Ýø÷o·1òoV=°%ÙˆË'”±’8Ao«_¥¶‡]›`„ŒTy7ye€*ƒãM#(¾Û<éå`‘9c?øµïu톿5UÞ m@DÃaÎmvm-~<¢xê&'ÂM  /X!]šo˜å&ÇDf!T¡—4 *¹H4òßNQ(´­òç½–¼}%³Ò‚n×A¾Ê;á/IT7œd.Ƚý"=¡3Ç¥O'W ‹›…@dbGïÙqçN¾ä"'è~3&½øºC>ŒñüŠ0’4âRˆa’לðSª»~ðIé^¯TÏÈdkgâÎI ‹vB(–¹ÿž'š?ÝCTõèx…»Š)‡³tW´iGEZ_ÈcL†«AбCEäŽÆúy¿ø¸Â1Å:I 9ä$’ ÃÚUÝñã“îyUÚ®¤1d›ª«ðl¾åa“ÛÁ¬ù«YÚDߨy*%hô§Oº$ð1ìaNŸ&ú|žwïʘ­­@hc}Ý+8goG*{1 N¸Žw0צâid¼ÿñ×J—TÛ¬F¸yû ZGîz×qá¸48¿QëY4£ÐÙ­>ãõ16Œ”·*±ñÄû-{Ä¥&kês·tÔ×êoþ`’G)Aß؈1[ú½¥é6pDŦ=„Ò GÀ¡;8¾¡¿ðn'ÕšHähè±6Íj\<š0’…ÊÚK²˜™Äã·à½go˜sHŒWXÇÓx|Ÿà]‡‡Kmü½¡Ï”i^6ÁO3õ_ªÍ~·¹Ñ£Oæù†? 6‚Ò³Uëp21;—xX‚×^ÎŒ;ýn¥l¸’dÇ{ùŒZ˜]¸A•'ï½¼V2Ìž-n=la¥—íäb&øó’ïÞ²U„À°ë, Þ^Òp&ÕÔúV!}>âÄÎ(ïÉu k–--i-5~—‚ü‰ëqÆë÷9ÜKùÁvU“ž¤ë­ú‰&B·ŸÍ<¥;´îç†yÔÓ`+.ŸBt1„y¬u²øxk±ºs”¶uJÂß$´Ó”vMš ’ŠÌ`˜ò¨©•¾#˜ó>×:ާ¥«$–ÒyÁþEÙbcjétîeúÏeÉ´7$–ÙààÎ:éÉ`óú¶{aþs`q«ŠÏ þ~U·´ŸÁ,·Â_Q2BȨæèš×¨iqÏ33ᛆbGøÃ©C}e¸·à>ÿ(ŸÇ1uDøÁóïÎxý–Õo['×Ût¥›hr$Áø8?÷«öÃûö¢1¹ï-ýÙå!e 57Sœ(3*ÂÌ^æÇÊb—Þåf£=pÃKw>Ë;Nõ‡¤Õí¯Ù3±·í‘æJùöͧ~ÝòsôÔ )Èg\†Ìkš^Ë#ç#Ìa3iGãVõªÞ³¿OeB=f@!á M»á[‹V8J6ê}<Óå¼EôÀTf-(h#x=Teä~xZdõ'Å5‚ÇÓΪMûLËê@Š`=)±@ÇÀÈ(aûÐúðlS}/ÜpíÝ6x#ƒ „î¢í Õâ< °€T˜ 0V@]®+¥Œb…Þ^t…a]ÿì*tàÇÁUÏíÿé.û˜ô÷u£ÂÍk¯UÞ¶"QI'æJ—É·½‚Ö(pç\É+«ýú½ÛKªs¯k7e]zp™ø<ÇxúÖ-a„ó[;†ŸVòvæÒˆ¶%*RDÕêP• ÚÈÕûÒ‚qJòß2eQÃy ôû DIËp„üd°ÂϨ—D˜î¬{¼ø•†û¾ íQ0›äíPšª4ø‡lÙuBÑî\¥åò`b~ 'YW@q1TËí¾±&;¿d5çËÕs˜žÁ÷Œû9] КXš¦íN1Ó‡Áa8‘B¾} f~àz|E΄j*=”˜ò{ÅO|[¦å²AÚ^aâ äâ^Æ¥zV|Ív…¨f£ÙÔ²ˆÉÔ {ˆÆsÄwë†bh8ଋfÈÈ/£/ÆÈëdÝEüºG#ÞÐÜ~Ü”Ëm©~ÖÌlÒMÖaÔ•Ån&üã¢Ièw_†ø´·ãªºmz$½–˰î2ö yà1¨mŽ óu…kŒ°Ãp1Å"jιðV¿\©ãýªÓe*õzhßÛ÷º1¬' n›ÌÝšÛ”u‰ŠàØ ªYR&çCÚŠÂXTó‹Û…ùkî$˜h›»4y·=-þ „/#Hݹ-n¸läí£¼_Ʀ;¸6r—8>=ÖÎ[;]úHIDÚÞÌ_¦¹V†U›0ô馹—øo £j 7§l:Êá4÷P?‘°ñŠp‹ÅøhÑî§t©KíŠhô;뇋o˜!u5~XdñÛ¦ówù ½æyc²‹SRCp\î¤=sZT§^“ÝDy=ƒ÷ìj_]‹Êbâ+Wì²b×ÁõÓæ¼æ$[­Á*îC,8²§Tõé ÀR!gv²üõÕüÓPõlEð™é³Ñ¾(—Ôüëð±hñ˰™ÖYl#æmt«–„7XmÆipð>P½ÝðW¶r)×+Œ¥}I¼$},>û|ê‹äïÛ ”ØÊ0n“¸?#¾{¥SITFòæY P .ÓEKj›¥¿&Ágû,¬¦W›Ë–ZZ»bÎ<{m[sìO+õ>¶§Öð*ùŒ…¾Í;NíŸjAÉ«a«/:Å{eLPú¿{õqòøI›°,hÇß¿¤›ë~Â*³Ya_óÕýê9ˆ<À €)>Ô~-nOføe6ªwÝÍe•rZ=¿Üó«_¢ï#˜Ô‚.ê,²yC±‡°·–n"j8졺&5W»ŒHɳԭ ó9…Q4iöwÒŽ”¼l=‚H³ï]^W/R\œ½7æx•¤rîo„j$vB³’…*,öäþªkëkšz¾e=øÇrÜÕó.}ƒûÄ éñï .(Áti*ü½?¯¶›ÈÎy™ }&Sà¨*ŸCVÕ>$‚É(ðÔKùÐOvç2?-…´Ó4À¿ÁwCŽÎ½9ñ”Y´L ïmçÛuÎR"Èú𯹧l»x+_*›â|œ¶{¤HÖ5, è«lûí¦®Û+ovpz¬Ü•ú{ü! vºÑ÷Çò1d*ý_òm|étÍ\q·/Ûò}³ÏRf­·r„Å\¤u”IJ›q i;v½ØÄr>šâô_@£fšR\Uu¬°&嘰ZвR…uäýgÜ3ì ŒNب¨qdvH“"É2×+è0I[$X|L>à1â² àcëö:EÓ|ùn&î×ÇØ¤/A}šÌ¶I}£Ýƒß$6;Xϱ1Åp\õáÙ#ä.è ¸î—§î-²ºHT}¥7åÔZŠpžØ<-à0`Ëæ«™ê¡¾ê›T¹:ñunq†ÝÔn·yÆÄ´*îf4¶Ú¢vL³g;ÒÐ+±!”ÜD¥.ÝЧëc>‡’#8S ÀQhåLlüÓä tm°Zü&⃿ïbwA‘Àä÷{3ï¯iáÀޏ=Úì0“‰†UyC#Ð$6©º:ï'] hˆØ–ý2Þ£¬:ׯnedÔWÆ\AÎEß!Ø |m“à·ÿzGn :™–´ÓÓ­ªt¯‡µ]}8@ £å1BÖFĸIoù®JöÍTŒ> `Œ×tWS¾j¨¨XæÉ Ò‹¬»^çÜ Õò }>Û‹ ›ŽQîÁœÔnaûîP]K¸¬W.ªŠíŸUpÈmµ0°=¤%‰Ä°‹Ò î}å²ögˆR¡ óWsG=Âíó6I+° Kµ¾9ö-¨K¹Ãá4¢æ†îÔ`C*ÑNv»gÊ­ žû~öÓiÏn™Ó ˆL×CŠ£–ÌJ 'åÛ»,ƒ”aXÇþBœÔÂÒZÉc•>„b,ï[ÀNõEd‘qD†èÆxÚÜóƒ½(íþnòyZ+žCe¦á÷›œŒ0µ(Gy©L;Мí¹Fæ×tm•Æ·ØdßÒÒF½çO‰jÃ=FCvê÷iCè¬ë°Ší:F.øÏÔ0"QFaؼ¦„ªÐÊi>ʧ3ãVî{QÙR2ùšh‰?¢°ÓÓ#~V)º [ªÛßg Ò1K¯ÙU`äË_ùKËi(-²˜PpyŽÄE×Þ!ªÅ|T^í#>šþ½öñHôØ2Ý(•`:û…sy8kn¹&p »<pS^þsQß #£¡b× =šØO½BmÍ=p`º"É+—Ç­xÄõg»Fk†ßB®¿çöùýíR²á夜gQ\š9¨A¿‚;¶ Kü¡«ÅZkü…9¿Ô$)3—Ÿ¨æXK˜?$í48 ëü&WîHàûdÊÓ"ÍýCBEk:Küõ§ IU ;–›ÍœRÜÈÐ,ûµu5îˆ<~=-i]‘¸Ñh[.T„Q¹¥iŽúžçÚZ¿KCš¨õ±Ób—­y‹ö¢’å[\@“­ó:x–õÔÀSΤŒînÉ åQ»Âƒ<4+å› ërÐZ9´6}eié%±{xPh´Z ³*b÷=ÁÃã74(ÎRå_;‰aÂTö³gjK±P‚~Ô½YÇd„)ÍýÑ?lÎÆçÖ_Yí<]!1f|êÐJ†@Ñc%kWÓ6dPz‹EíreDb³Ï?‚Ñ£]—ô&ð¯ GûLÿ>£;Æ *°ôñDÒbh<to?ïÛËfC#nø*´hL•·Îek Oõú¼çH§yx^»ÈBüÅËtl÷W^e‡ð\Uƒ‰GçÛ ÎÛ÷l¨”óv0[z_%öâÄGYíµ2NÄxN”ÔÕG¾’·<‡¯”çQÿÉ‹5ÚÛÕŸ¿_'D‘8eý`Ûúä~F´êž“6#_Ô3þ ÷¹Þ¿‹y@f+° ›SÝÚT 0áÒØøø[·ÎQ äÛêF½tx›ü)Í'/*GæÚ5(õDh,rÝŽ|ïTM‹ ŸË¡ˆSÁ&^'Z¯ÀÕÐó–òh@OE‡ Vz¡gŒüÁ¶Ã®Ù± åiº“qÏêkù—¯‰eš9›NOQ…YázŒt¬¦îé5oßïõ’«*·ô2¶\­˜æ%8t¸RÐ |W ¤ÃBc‚S)ÄÑ>®Ý½ÞšTëÊuy`@¬$zs<™ÿ˜GHÁH¤ß(×;yyZo¹N’?BçU² ³ªKlv°pœ@ïôÅÑÎE›ò‘üU6µ½"Ê,c¶jy‘þñƒK=–£vvâ’¬•n[ÞCÅ©ZÞh~® ï¼H¤“§–íñÉ;[Uºé%1î7ž¢F¯è,oËŽ²åI Þµ€4åö­gvÖ âÁó¥Ô9ʰª“Hz«VÄ (úã%1|^·‹ˆè|ñåçåÎ¥í 0¡k¥ËõÏœLMúW€´oÓȺ‚PJ?Å=Y"‚8™»P6uL+ï{ƒ;TJú‹"HO2-~tœ[pbq>ÁD^ðò´-T»Öu—½´Ïú¯ñ½¡è†#®K+£¿fÄ5ºÓ#ÀÜ£­ï ižc!ã#qóÈ3¨@*Ý–4¸=bjNf—%ÒÏÆPÕˆ´ÒÂ¬Ó Z˜áKkl5>ç¢S0åÉ.׎ß>\é{ù’:Éä¸A#ÚÀ²¤K¬h ¤&Ê¥‚íY?×-À‡ îj΄#`Êâ—ÃU,¬‰l|„©CnïóxœzTj …èC?&œü…-G1é¹4ì£2Æü…<×™…^Þ¼¼¥ ðÙ/}`aŸÊS›bØi±q|ç žÉhRG"ÿ³mNM><,’DIÂO}ÖýWJu|ìñØO'é%(ÕàJN—<í›PÐú ÈœÁ}µwùˆ%V—¤gûZùs"Fg}*zª,Â¥=¢9¥$¯7›í{!æ¤âr~™S:sF»Ã2û;ôZåÖÄÓ;´éhV’ØC½çZù­(Ïo«•/JŠDˆâP~&ÎVœpòS…Aú™0§.å°üXw!UI!ßC kç× ŽÓn/"gº¼ÜôŸƒ©ÖËËýˆzFRßâ0U yŽÅï—ßë9‚_€™ª›k’pßµ+Ê¥Ò†@I3æR‹R_øóÍ«âïû`–E£ÃžJKR¡Z"VˆO%¨àkÝöñŸˆý8x­[Æpÿ Ð-d€³Ö;«x(â²TƒžÑ¼š-ù¸ÆcÛÙÐhšÃçs?´õ“ˆr»/W3>÷÷ê§èH:äׂ¶oTJŸtCADBiižÈÉ*© #jØ"4Œ!‘ò´FY¶¶"»Ïô¡É“fyÈŽIÀ½‘e;`mÎÚ¸dô’rc×’J›éƒ%ÅðF[› îRZŸÊµ®sи§Ž“ók‡º''&` ¹”¹È§ú„Û­šÿÅBéõ’67¬›˜ÿõ%‡^´8v¦ä|°¥Ñîå 'y›ŒÉ‹ObÄÅVæK½¹±“™"Í›ñdÚ‹@‡oa?fÙ\Ò¹š|ð ¶Þ^\WfÛç¡ôï-%7ÊÖµžäZ¾éH®ö“«öwW©¡’§¹¡®iâµå¤`™8ˆ(…Ðýž £I/Н£Šfšeªwt¯Ê[ÄÝ…h¾žÑ?kËOõÐteD òY|B!—r1µÿ0AdnM+? À1žÜ=´¤”_¼Ÿ«Çle¾ì¥ÌQ™Êødç²ëw;w–H½³Sˆl´†V—Ø&Ϊ>ˆ¯R¹z~Öô2r^î$Þ›é æÇåÙ ;ªrf3¶èbбØÑY\W¹VY5=½ïé{^ž®¥Mô –ú!˜~\`ÆÌCEovéùyèZRðix¾Í‰4“:?\ƒäÙÓýë½þMýôAF`ÂÍ¿êÚ µ¬ClçXµx)ÛÓÍWž<*µÕÉ1÷%¼ã1 ^N{ m¿.¨ŸwÓ)—uŽû ¬ìgFpç{¥°ñ0F›ÖgC•ÛØVóÞ5Ž« »¦#–ÖÎtj2 T× AZ}‹cØj€ñò¨ÅÆ0âÈfìL>¦uU i‘ÐJ÷+@ |øR Gvñ¯*f‰‰&¼Eÿñ—¡_loØ ƒ9Ž„3%mLN¿výPò 2×eòu:@ýgêÝ´ —ÒU’ÕO7eÜo Ök¸B)n )S7¯ÐPµÁ±kL )僴?‚yÅG„q ,]q"†Oçu¯í1뜖°|à˱ëº#Š_ƒevòÅZ* Ë†géÑ<]G—Jú¸æd$.•5/¨ø m-\Ý˜ÝÆ’çâBRèD£Â:™ÔäÖ”LÃAûkÛ©±Bû¡‰ZÑà ç|²á!mÒ+˜êù¼T±Ä‡m0ñ•o“L°Ï¥—Qma¿3âös›¹$“êdNzšÌô;*åÙ­±.'.tZˆáFŽ\'ºzàsˆcòô4ÎHŸgúS°Ã]Í9ŠÚ sžäüpÜaàÇKÎïVÆg¦–’ÀaŠËÍ<IÌ~ß²ßt¸hD½ îš IÌüXuÃ~KP%Ÿ%‚êj‘Û°3Æn”Eµ9”†òWõAÍÚ)©sŽ«£EnV+¾K;bê5¸Œ!)Â¯ì© Š‘Vª^YŸOàéw¦IÆtÒXt— sGB¶¡&#ð°ÈBSªíq1Jžxß ]mËSÎi¥œòÍ3Û£MÀáqAŽ/Ža‡#™û•M0cè…º¬ïƒÐO6´/H¼Å¥—±‚êˆ7ÎzÊçûÁo^Ù“ZÅ•Ñáeí¼{æ0&áü­ô(w1øo.ZËÚ@"¤ióßèÕ„û¥©d,»±ÔÕ¤Ö!þ¼„PœÈëï6‰ïÀ›–n “sÛÕ?8Pˆ=ZÙε ˜vÌZؘ»JU‹óqd¿ì§ †¯J?’q¡_<Øû 3Ë»bQdL‰Ì­¾ûñŒ¤²Ô1AyAv@ªkÛYݘ7EnðDó)!’øÎ©AN0“rÙ¥bó[u1þ›Ñ~ÿ/‚54;ŠÄÅÏ*g¹Åyð,<‰2™x²ßºg<7|Ú¸ùdµ=ø³º™îÏÚžî/[)“¸ÄÁ<¼ñ;ÅÒC¢bê«Ä¡\6¬'¿œVmïaÄ[Ú#ö¦2×aâ¨PÔn¡-ßðd8ŠàŸ¿"ëÇ5z+ŠE„©§ïÖ†l¯“2}!Æ‘Žãö÷©Ç¶%3ðÁÐX µzuœ6éºíz3G’O5«§0_áhÔFÃI —¶2†Â›•ËsîÑWëô’؆Ô@e¨·ÍR|©ä-SEж;8‰<Å`à°ö$³ÏÛ½¯†›—C4L¸PÜÆH–b›7˜ëœ£ç5Sû¤v¤ÁH×¢Jj…ó¥yüêd’];ú-â€É•k™ó·—þ™n k£Y:'ƒê Vcø÷ˆ°Š¾ã‰}G8¹ÓÃñB©¿GN| Y«zÙzù'ô¯3®o—‘ªŸ¾‘·>Né½òÁöûñØŸhµ««+ØÜÜfÈWd,;Œ~`úª‚$w ¾¹v–0“áñy£×©¸ku;BTÁ[¸oŽb“Ý TFÖý¤Ýc=O€µe]á~Z}±*+nÌÝRT9Áfñˆ:Û:ïöZ©(K>8¬I¼º`ÈCmý6“Øöu5÷vɇáJÍ2_nÀwu M¥ýp nPÝ;áb6ÛÊ鸵ª×ã(ãç.’ÖÑ‘ŽíˆÖõjk¬t÷'I½ëâ–Cý9usIù˜»>YC¶&·øz'²›kT û›ökø ×YÖÃtĘΠy~ù„ß~)Øœ¹’› ÉŒl ùY?¦GËÙ»%”_´&¹uf¼®­¿IÆ­/öÚ'í2ãã&1ûÑWNn¨ÃI}O)‹­‡õÉQ[sÚ×å„ãò=´»½‹ÊÈÚ¥)›,µù®³8@MÛ¿g–ß­?‘Ï(¢¼vkà; ¾ÕB#îÀôxïµlrš?ooý8+ –J]¹ºHkˆú̦ÔW#©¥ÒÚœ¬ÎØNͰΆ=ê>óX1å’J8Ó‰?Ü3ö^(¿AÞ†ØÊ‚)"eÔ9+Õ–øÒ}LA¤’ùŽwàCùÄk{€'äSé Å<ä–»ö ß°®]¹ºœƒI¦òÚŒHË9=WZ!I­6o¯V`ÒBPÁÚÏf>®¡—èu“`j¸á´ªî¡œŠqßè‹«o 8¹ŸÖ–[Æ7à@ÈŠþ[;xoXå+“+‹³™I晿’™¥CÌx L'ndˆYkDðö5‹Ü‹~¸_–~G±(©(ÐÚ…Ë©ÛÓ +ÙÓ¢IvízBM†œ^øô±«ÖÁ·6´iXË\`½ËÕHa¬ÙƒZôÅŠÜÖȺÃÂ茖·¯\îÍð¹,3¢áî€Áü+ðãt¥Ž°zXÁï£8 ‘žÚs,{!çåc°d‹MÑ”¢åjV*= ð¹±iIÔS¥Ÿj«¾@Ô9ú¦‰œŒ\uUØ€£¡V€=Z©ê¼4Â"v˜ }quðÌ@èpî6l:Çç³8–‘[ ˆ=NµÍÒâÁµó)#}B«ëνMè9®'¨ïÞûF‰/z¸æHëým%àÂ×OoþÏS‹‰Ñ²Å}-pH SâÈêS3اyRlmݽŸØ¨ ~' RÊm„Îbžê8Š˜hFþv4B‚ µÞðˆ¾hXØêCGŒ¥™ L¯Ê+—þ¨S£ô¢ZLH6Ðg_ÓÞ¶¢GC{5Q’z“¼ªøŠíôøÜâ¯Ü?PÓ¿dª~îQ™‹¥ýþÜxp+‰Ž6®U›Fõ˜ä%œýH[Ç"B3 IÒu ,hù]ÃkÇò:µa!¼ó"j?™'½´­ÝÚ^%¬ÞTêÒλ<Ì;²³Nü£€z–DízÁg ¼€U »úcàGÆãÎßp)Ê ªl¯”ôP«ñÚ'Ó7~Ø~Tö¸âg÷P?æK´sŒÅÖ®ú¼‹ˆ¬q X¦Õ­ft!“Ù\*B Ši 7¤ÜmÂØóc”r5—>ÑW»úa)%OíFc1kBw A5Ð5Þ„®ÑÔãñ1&ñ{¶–=Ž»-7_úÐ;ç Ž¹„%#n6ܳ1mpnãï¯Ë$ À¥ űú¥É²'ºR%/Q•³>–5Þ,duÕsŒ ZÔ x‡C]’]"sv’Zì™Û»/L°|b±ÜuÇ [ÎíÛWŒ„Å4Ï žÒpËQ?š ryiÍbÒCQžKSÌøÉø”pU?ƒ  10@:[¬¼Í"º÷y½Ë±:´rÅÃþ‚,ìwæ&ˆÉc뤶´Û¹7ôÍ}i¤¬þ{S2ûèf° ÿ÷eX𞊠 ÷Û²¤McE|E „è‘“=»+TÕ[Lþ·¶6¯õOÁ£Ñ-nŒŒÌÄ“D#|ƒÒ>+gÖáïÍÙ(ƒ®¿o gÃÇ·ßV>§± åɵ*†:«b?«»´Œè<„c¤|N9žÜÞ–1põfWnÁ¬êbö 0µµnm|ý<š·³JãtÉñS‡sð|­zêC¥Z¸•×ȼž½QX’`vzŒ@õå xKFú2Fò½vm²Wíé¥}M•”5µÐÃ¹Ü û3ëýÏV †óCQ¬×«>Ð×[<8þ¨Aåws´ùßaqQ=Ñ—`"¼x|_k‘ewõÅVŒûʆñÄ^½• ¿£ L£|x ÈŽÒÍaæ­_2~0 úÁ_~™¬‘ÙŽ¨ï¢)8”³tÖ°f ·;ÔzÑŽ¡ ]#µÙgú¬ÛwUQ¨ª-`Cœã">úÆ’4?dö!ê ÇÚÚEÙrªVc D2>ôbœµg’œ¶•Vë­ÕŒ€œÜ/›.ÐÆ©*VÞÔ9Š~ü6Ÿ¹h¢wÝ\ýŒ/g@¿ ¥ïkF\É·Ü]äðÅÂYA¥|Ny¥ÂÝ–Ñwº©.EÓÑSã¦ÀêY$x€g÷ˆˆBó üTæÜˆR2/imÈ>¨µÙá¢I !uuhËøGKûTR¥çrÌçª^Ÿ-XKšV‘ó¥È>—ÐG<™w14î‰eoºR‚üRÖ¨T]@3(Q¾ñ ~4K™1°½¿úFÙêƒú|&×m÷×°½+œÆè[2¢";‚,§/­~q~“Ô Õ&ð’⬩ 69w5]2Š3ÍΊf:æd<Çü.ñÿ>‰Yf¶÷ãNi€ªv!8DyÃr½6 e»¹G?޼_rÊ7UÜw§_ÙÀ7ãk!Í+|"›’“¤É?ÔsNO\F·©©€0q¯N2z",ßÎDX¿ylbúHvoJ'´\ÐÚÓ…õûG .£Ô“nf1Kv}â¶ÖNKç8ÊäÓ$í+×.ž‡AÈt—꾘¬I¥©Ç.˜ÿþcÖí¯ì¤s£Þþäu©¸4‘ËQå3,Ü#¡½ô¼Ò˜ÙÖúeQý}m24_Nr¿Šûo#³rÎRA<ÊzÍ}®>V“C™a7ñýͤ_ûÛS¾H[u% ž•6?/_‰|L6{+H—'_ÎÝmÙýÐ×=–áÏJ±PM Sv¸…†ŒPÏ,W*u›’Ú—XS#¶²5ØA®ûDpˆËã÷âÓÓ²pÌpÇiA,÷Œ.®:~!в">媬Yý’ŒMÚ7Ê8vdJP¬¿ÕW}ž?EXuÊ}Ö;|­>p X8׫tÙl¤}Æ¥jäR«‚ÎÚO*›‹Éà¡T &Ñr†ƒ2ÔÑA·4û0zºæ²lÉá8ëZ<öÛâ>dDÓv¯2›ëʉ®rù‚ʱ›Åeªyy<ì³7|[=&°ñ¶úÜ'ìWü`¥:§¸6è(Š" i êe0Õ¤;ê@gÜÀ@c¯hÚäËÃÇj¤#ºû™½“¤¶¡Ç€à’Ÿƒ [Ð7ÇÈš*ßg÷q7èX¾‰h*gøbÖ|8Ôõ‚侑±0­ÏQaÊ+ªnò¬fèáxÎ1Ü@ô(EÔv&éU3¬ ­a4kT w¿럷àhÜ/nz7TŒ¬-ïvDo,¤±½¤6LòBE{ñ¢Ôø#¤Wø4¤méVÂqÌsX’o6‚r2,Œ}ê$¨>/(ÙŸ yYE|²¿ËÄÝb ù”ÙS˜F¼;áÅEðPø:"i€øô¢;ÿ ê*ãÀh,ÌЂ'>0ôu¬ñó¸'ÝàÃFÁ/.¢<¥¦Öº0‡3BsßêEw8Õ{È¡3’"ÿÃ+qþ2bm8ð؎Ѳˆýd‹/Ò6[Bóóêì—‰v_x ðtE?´ü?ñ¢E endstream endobj 311 0 obj << /Length1 1486 /Length2 7257 /Length3 0 /Length 8246 /Filter /FlateDecode >> stream xÚWuTÔ]×¥K.©A†N‘RºTb€Áa†¡Aº¤II éînDJRºS„oô©÷y¿ïoÍZ3¿sÎ>çÞ}ïÞ¿µ†õ¾–¬Ü¬‡!yøyyu9C]~ äXYu!H(øŸ «>áÃ$þ#›#Q¹'æHT¨:Cü‚~ ~Q  Šÿ„#$OÌ] Vu^€*v"`•‡;¸# 6¶HÔJ=Ø-9üââ¢Ü¿Û²ö`ÄÒP7GÚ‚íQ+ZšC:pKéþ¯ìR¶H¤ƒŸ««+¯¹½/a#ÍÁ p… mOÁN`„ Ø ð‹6@ÃÜü79^V€®-Äé’ÜéjŽP (Ä sB59ìÀj}€ŽŠ@Ó û¬ö€ðçñøyùÿ÷g÷¯AØïfsKK¸½ƒ9̳XC `€¦¢/Ò É 0‡YýšCà¨~ssÔÜø½ys€¢¬6ÀÅñO†N–ˆÒ‰× ýÅ’ï×ÔA+À¬äáöö`Ò‰à×þž@`KÔÉ»óý}Å/apW˜ç?±5feý‹Š•³Ÿ âè Vyò' •"ø'gF„@ ¨(?ì»YÚòýZD×Ýü»ø;âáíéwX£¨€½!Ö`Ô§“¹ €D8ƒ½=ÿ³ðŸ`±D,À6Á?ÓQi°õ1JˆÀˆ!?øëó÷“JgVpÔýøï‹æ{Šâª&Ëõ7é¿Ërrp7€'€8€G@àˆ ¼ÿ=éï3ø‹ÿﬖ9äÏýýÇD˜5 þ ÔùýEÅåO}°ÿiÀ¿WЀ£t °ÿcS 0ÐõÅÿÿ6Ãï–ÿË¿¦ü?lðß{Rt†B#Øÿ‚ü/„¹=êþ'¥lg$Ê%êp”W`ÿ 5ÿan98Ôê¿k*Hs”Wda6(½óð ñ…þÈCœ!n`+-ÒÒö=ýu¨ X îùõBuÿUCYÐò%ê-ㄺ´ß%0Êaÿ^Wf ·úeEa€9aîN€Ò*xò£Ø„Â>§ßá¿6héŒ@ ¼ü[K¨Ýÿÿ~q€Án`K‚¹i¸¥d ]U`ËE…,+Ïæ¨€Qß××gx ´.ÛÚþòR?NsÃge;¦¶Â¬í ÞÖ¿4¤¾|¶ìõ&\‚j®¦ÛÚbÛkŒìÑ従š³À¨½Ýø… ÌʆêKÃÓ×3™IjnÇ“ÍOé»JRÊÎKm¿à²ÕðbŒF†ãÒˆ‰ b¶Ê¦·–ÉUÊNNµ©°8}•=ŒgPÜýñ¦wX@x­o¾˜²ú†noÈt–¾'²Ó%rôb 0ɺѥ@sÃîÖèÇná4¢•X ÚI½êw§ú:ûFuD©6Çûy0R\Ó‚œ_c[¡R'S$¢Y›J•JØìhDt]IïT[V3¶{Ÿ…Ãz=è£9Á³¡L—¤d½ñ³è¾ÑËæ HiÃz丷Â1{®3øs¨r]!¦ËcçüCñÚÜËü^¯‚âS.š"–€rÛVCÿ°µýá¤Åo‚Gդמo[=É-éX:yAdXI¥cYZ¼¬uôf[M¤1 \5\X2T‰ÏF¸êv$ebl@LT®èãz± ‘¹kÅélõ±ÉðŽ4tÕóн/eD½¼L³>„îK?ß“ï}3ñýÎcÉßïJ=@ýbî<óÕ§[+SÍ™ã›r:åÛä;^+³w舚U?L½`H+'»Ôó‹9ÏxÙš`·I€ãwN>ñÎwZ3l²¼E!Èb\Ì\ëå,>€Þ¼m.2áTذpïëÚ;‰0§Âl«] 3´@Ó®JF‘›"Ìí‘/ÔòŠŸ‰ÎéœL^¡‰È4,y.Ñ—Õî Åóê_‰l%¼ÁùG€O‰¥Œ˜y>#fº^Øèhˆ’â–åòûŠíwÒ J3g»±ú+Lª+ÜÄÜd³ã¾4=«¶“ë§U‘Vd»d xÂÝ©Îhk¿ÈÌà§WŸHFîcÄû“óy¿‡ó¤ó üÄD£¦i·ß M—}·0©ÓùÄ5³ƒ#äAZ·‡Ü¸»èÝrÎCàv>Ÿ‘êi#¡‘•$èMÂébjX²‰h¬ ÆJ“wH¥_=_L:¸ã*Ë“›H¥ZN±7 ½ˆO7èjÃËÕ¨kV˜Ù1ÓdCû°W$‘|•ñ bÖÞ–è©ZØ2f_ªa‘²ƒÓ[ˆU5¸¯û¦ÍÎP¨ùñªò”Œï¾Õ±CêO¤;T£U–sa7¥|Èü9Ëø5îsÁDÓ1FÕF­â•øqi0iwwÜœváÉð\è‹Þu•du„mWàãýæÝTÚ½JJÚãœÎå>ÉÂØ“†ö¤jÝúwήŸf¦o ‰ýÛ_°(’»oL&¸óñÞËϸ, 1 ˜Ãln—™ÜÔ>bò ˆN̰lªål K£©ºlñÌ9Ü8X 6"fØ‚ªÈÙ%jòÉSÅÓ‰oÊhÐ}ÑvÏÊ;Eëžãµ[ÂчIBËé ’ëK¿%37¾þ¶Á‚9L±˜¬ù˜Ï–1|¡a…³‹ö'´§‚wë­ÎŒ!g¡f¤ƒ)Æ/ä#¤©¥ÉXôg[“˸ê£'ÆY)à/‚­/úئߧ¥\{^-¯¹4}d‘©øy„++cž e–ÓÚÐæÔÔæÀÆ%o–@tȤ-‹×73ÙŠFžh¹U¯Íß¡=½)›ÚÙàp ˆ|tÄéŸìáPÄâ–8ülPó Iõ[k´q|m¥ŒfB¥ØâñÈ”v³2•h‹;³&«äë|¥²µÀ[Ó¾¡–Iv„ó]ÏòC;ª¯ 8ó¬½F2‘ä´lºtÒÈ×”hœ—Æ+<áo¥b6ì)Tz”Ѻ°"Ó·Ý‚ïòi‡Ô˜XO5½¾}EÏVÁUh(‡Õ=(ï#ü@ ÊÄœ¼¢ oƶ}»êí¶ö(Ú£4p##õ§Øïž¦èi‹'àÆKà»l0 ¸¤ÔÇÊHýޝwÓoÛ âÔYLúxê‰æó°þ§%™¡Õ–æÚüTŸ ©»¡L™L‹6ù<Ïù•CœÕÒAa›I£¾|ØÛ÷¥ÃԙÔöKñs¼$ýÉ2‘ºØÔ]F»9щÒ |ì 4×Ï“ÿ 3™=´át¡ÁÌ3se˜õe}?:ïjd™?Óuø:JS8’Š@ËQG_ý|ÿ‰ÓEÛ'øyð®±þä:‡RqàCö¯Ô­[:ØŠ°­ Ù‰ w‘×AcÏÃÕB®Wѯ;ºC¾ã÷èkîS@F·dR£“|:œ&žäÓb~éŸP®Ìµ“¥%«_=}]4ÄŽ÷¨Q&&d;"ÿ™Ý=¿ÌÌßcŒî=Ì`q~Â(‡N Õ ¢q¡tRÔ”G4TÞ߬¹Î>ËA>î•o¯L)ø â&øŒ{’[8bóé(ÅMl~·ÇûÄ&uÝF_¥u€y…ƒ£ÛjÚ¶[$2íâèrúà~K¿úìý¢\¶‹{€½­Ì°L½¶ÈÄž(s&ñOºm1ÄjZšˆ‰ ðuAbÊŽ!•æ½þûʶ®Z ý´üY  ¦f¤OOjþ|I\<âPgš²Lx–“%8 àM8ç«Ñ¾¨fªpG÷”y=9ÙglÚÚýÝû}’ž(Zè°®Û›cïO—-VùÌS:l%ˆçI¦Ê‘´|W÷ÞD:ðˆvºõoµâ…'~Qñ!HÒ‚¸¸,·hVÔHááÏ_5Ôð[€6Ë&L÷1ÀŽÞþn%wçn^.ÉùyÎpŠGwšÈA*§ËNx¤Âb2|¼Ä„rBù‹z·gŒƒ;Hº·žŒL=/Êñ~)ªø™m?$#hL«ªxàV$=«î‰@¯g ”–¶§’Ô³9`µ Ø-þsp¤ü“R›ËÇ>ŽcÐ|gzуþCBWÈÒˆK,³l™žÉ軀ÆI¡kê‚wÐPï§§ jU)UèÖŸÛã×Mt Â9=·1/º‡ Ïp›bá,9;õÚl]“Y\<2ù.P(­ EðÛ ªÊ>žÚ‡¥ . l=Ê; 1Ž\d/¥{œŒ|€ÞÈ—™žR™udò,רΙœó{vwQ>Ö»»á-Úl,4ª«iÅqÉx¶: –§bÂ?¨ˆà2ø˜ ûì\·tÅ`”ž˜™ý¼$¸šLh]Gޤr;£ZBì6芭U;Å$sÏX™M³OÍëWï**Sîçš¹Ó3’Kp[ÐØSˆ??Îckéè©×Cß\‹òº¯Ù®H{?Êç²VÖÙµé¨áÐ4¸î¶cn·(î¶Êxhø5@Û&_<[ÆW£m›0ùT¼*&| ©q—GÙ)x.Y¤ŒÜ÷³€fƒû÷…è iÊ;˜×cÞWâ”#I‰WŽÆ(B‘ÂÈ!·ø„ù÷˜:ÈŠ^¨’©˜T<+%gxã-ÎÎ×¹JÓ06àùE\(ßÃ(V³ÍH””ÒGøŽ˜—ö-< 6E{Óê{„x]öÔbðÔÇ~Ëï|ê™C£céž^Y@Î&6nç(c°ñ¨§æO®O4‹T|ÌkÌgú<êÊ]âid»Çò!:úapØsG[3ßaˆÅD×v±6Ï/Éãá)ýÓ…vöù84ýM—BSkºƒ Of¼6R¼ "«IM9Xr#…ãOõ˜o,¶>â5r'Ttb“,ÅÄë¹¶lþìn¿ÿ"&¼ÿЪWo²½Fm§eßíÛ®p7M„>öžaB¬ÖýG/HîHç¤Üù,׬c4?ÏO+¯r6²°ßÊa³ªH2pR¡h»½@H³f‰©öUl8O?ñ1õHw²p?&Þ1-Óx­‚á¬Æ#th©@Á£÷õSè¦RkåAãsõág±Ü_óŠŸ^M%X?â¡•8£8#]A¬6×”Lº=?…#y@5ãëÜM‹˜’·Ô2Z9ÛÏ,Áì¹Ñ#öŒ¤m÷ïÖ©p€*‹[µÌ_ºÓ­5_;Ý¥äê̋ˤŽhì4hË¿’KÞ—;4i€@SÜ߶̧V<³ êÀSx•OFM ^Oz:ÆPèÝGEzÑàaLm¶ÿpQtÜ5 “ÉJvog¬æLÄ6Q ‡Ä©eýC½+ÏÛãÙYó¸%+¿ñ•¨)hoY¹•µ?y›/[R—Óõd™öl?ÎHsÎ\šf”„pÒ™E€VZ¨n©7¬½³µ•ŠåŽ1êDc¢Î£\ЬªÔýœÎ•Þ þÇ@îc¿ÙÂb»KÑ´¼?¡ºxâ…Áå½ñÝ„R?!tcw僑¦d}ÂÛÇ êÉÖÞ_÷Í€.ì 7‹Æ‘²‚–ãl¼Á9/¬¨›P¾¹í$™b‹ÌN‹^û/v¬ܺv¢Ïæ c'çñÒZ„º0ðçÝ+«Ré,òÌ[-¯†ýÍ9~Y_Ù±‰=yQòž¶¼ “þÔì ”Z•Ê2m{Ž”ùÌ ;ˆÇ$0^ÂñIºà^Ç‹ß;S»ý¼1/HÊc6{šÈéFœÅ Øñm€\VFèë¦j<­Þñ$Hv3ùc ÕÐè‚׿¥Ó^•tH–„ÖÔXêý3+!Îܱ€eµ‚!:‘°Ð³’ /LÉkÊ!Aç{í¹&Û‡ßÖg)Ê_²á3õå\p@k/…ƹˆX¶éê~Rf„»ùk=»»“ä튗—vÓå½y£”Ãpº<—xÌ¡ÇÃ?ï‡û˜MVd)ù: ®b÷ßîiáßVÎ-2uý1‘%#f€¹ýŒ˜s>Y-N»J]BqزdÒ ‰§šñ*ÈbDu½_n‰Ÿ ²œ>ôʱX}­´é’ªLfA&“Å­Ák§‹Î²û¤L¸*+…z'6þ“T£êÝGC…ƒF,h¥O)¼(ÆÑ^œ?ämì+ÞWøê’ÔC*°/JÒ÷àýÓù9åV?“yûÑ[hÑÔ…q ʼn‚¾ÅhW1äÊLÒ°µÞɺÅj,ëÅÖäÕØ|Èì¶0ßë¶CÚÍŽ|!UË  šáêJvj6©µÛiùl4hJ ßzw%ÅIM¾Q¯£tÎ<ô†sÍöÁ·­RÝE§­óqº|ìbHfÞV½ª‡Fì¦òz³ÐNÝëËŽ&©>5]úªÎ²×y_¯(:h­É1yòv§¥Ú™¼ÔÈ>wúÛ®øzÌd@N_–Í=Ìø¶XÅÃ$î"a¹Hú)6»Ž а³ÔöªxMpGÿŒQ,½!½¼«2¡»Àóq'±ióîZRfw]A}*†fÒ É‰|Zskd»»Awª;§‘§ª5ícôqŒ!4¼ôŒCÂKн-Êp+A‘¼Ý _/¾C]ÿÆ_©€ã"‡o–€YYöÂÊúö $SŸ«ŽšqCIF“U Þâ¢ãLÉÔ‹´C§k}ÉB“©Ø9Œ˜Ñë"è˨¯"§līԼs¼ö²¸Þ×õ/u㢠¿KÝܽÑbîg6€Ÿ^ðø‚çž^ûõ¥œ3~ó$­äüº¦7Rùë] ÁZ#±¿l%ß×kºšÙ(}×µHTQOº·þ8NXɆYl§ëëz±Êu÷-ú d‹æ1âe×cöÀñK2Ý·¡áÁݧ^z‚:;l&…!!敜ävük˜ûq`˹¼ÐyMeèÎðf澪g¯²l›8YòZhûnùg?`åýĔȂjæà*,9Ãns’T_:‚‹§åëZ•¦ =&ܼ!gœ“4úÒ8»ªåw†^e{<Ð{‡YO?ˆùlu¹¡ÊhåÑ-ftÓÕÅ'Gá[IŸðj™Lœ.ìS)þ/&iCBSí‡ç©ÞKÄÍöMždÑè6j,ý¡±?âõ¦§*ru[4F¾«TÞL¬w*k†U!"î¾`}ÖÇŸ3!v©Þ¦áÅÍzœá£J1ÇO0Ö®ˆÆ¸8FŠmÌâ3µ›A~ KbùÕ$z¡{:}žY­ËôZ i݇–$Ÿw/åÆå[ûtpHæB0ð©åGR›½_¸‹Ñmܾ¦Ï¢CßV8rÇUó+™=Ú’ácu²+4Ò”>ƒ"¶‚>ƒ2Mi« Âó“ãÈs%éÞzÖ‡-æ°S¶}…;—/–GÈìtïÞ*WM_/°w]@yU•®ýÔ¥,xÍÃ2?ã7d®VÜv·;¹É‚E{Zì 4:ù­B €¹<Ä,/¥Hké¼åüdq%f&›èç°©Cä˲2ÍÞ Rî¿§_ upŒõ"f­}­½fcÕ4‘÷µ%—ÿæ·çÍ¡ñÈàÛSER7ËÂ[Æì—‘Š\&]5_O4¾]4b&ìRI¼v§|*ÿ|.˜h¬BfUiù-Ÿ‚3Ñ`ªy„ŸÐ,'®ÑþËù[ÆôBbÆÆ²'yòÜyõ‚š$$´K,L?ß›ZKÓ ƒUçò›„Âß8^Äoª…t”l¯îBçgÞˆÝÃaÓ˜—X¬‹C–È®,tg9õ “õáà`Ê/Ÿè5|#Œ¬ nÅiË÷§ÕÏn™9A`KG;-píçóÈ~JLjêî«Ì øÎZ™Çº¦O‹WÂfþP»¯¢–'P) Ü2PÛ”Gžücè[vÉgÓö|¬›”­÷‹‹ž‹F°þ bOÛöyVÞ~饯2Wò*ÝsÏFƒ°ò}]‘K'YÿÓÔ\Äè‚Ú™m):£Øõ#æ—}ë‹ ÕÎeRú´o2i)³ÐndɇYК×ÇM¨ÞkºÜ_ú2}×—Ýôî}RŸ¥ß¹ÿòÁ…¯aõ>刿ûýsò©jšˆ#ŒàÂÇ·Ôò¼IÉìóº8ÂZk‘“mÛZg$/°Ùq×u<ߟ ÀºžêxUØ4 Èóÿ1ÿûNúà¹Ëó‚3³Ü½‡ß˜zš÷ÒSËR©¿ú ä­5WsösÙ¡#û«/<çZ„å Ͼ9íŸf DçTìeé1–]ûÛ…ûMZä;¤V¡uòlhI~#»°Œ—Iä“@×KóÈ$b¯ ‘ÁÐܵVœŠ õz¶1»ÝÎ{«èÁìç3âfüÛïõMµ¼ŸÉ´µD®ݪ†ÉUÏ e÷pžÄŠnMïRïÿ°§]·;Ivª³‹«×¾è½H“¡x]‰Œã]ß0“Ycó€.™‹âQQ´©» чÈÜå~ü›z¼æuN2«”eôšíçÐÓ 2‹‰ï2sÉì|žYêZÉ—§Óü.M'†á£ÊƹµQ4ðâvFÖøÀ3£,ï~¶f N¾ÖþSµÐ:6FÄ<ËFghÌ1l$øU³4…oë'Rì­_ƒÿ·BJÓeh)vHßÂ35Zå~šÊlø¬ ÞëçE·—÷ßèŒê•ϰñ­Ns阒E­©Ûå=¯Tí ì|?I͵ Aî‘…è[Bv¤°€VG çÊÊÜJbç, jøÒaééÑsA…&ϼo2{nr®Mµª4Y¥Ì½16\9ïÊxju0òÏQöYÀar”òŸ]õáŸpò—Û> ôú?¸ÂdÅi i؇ŒO`„ÐuU>;Šº7.í„å’·€OnóÖóež±9][Öw©’[ ï#nOÖ¥Ö´C²ð žné÷y3•´¬\qÞ°ðÓ®õ纓)™üŠ<®Þ-J˜mDÍ82Œy󉱦elϱÎÞ&¨o·)ƒˆo@0¦1ðóŸÖTþÏ ÞMA'‡Ý,Fú ´²Ù¢bï¹€¨ˆ /¯¸4ÓB l/‘Àô἟‹@Ù–Ã36çd‘Ð Ö—ø¶u#8±Ùâñq$N=šÜ˸§¼d «%æÙ¸½ÅoÝ’¿4ClK^a3OѲXD¿ðKN²¶÷!cšÈ νXÈGj°?dê˜plÊÑ9÷ÑÅDÓ£™Q¥y©^ogÜèß­Äæ¨ŒX}±÷õÃýªÎ žð’þ²ÜŽw˜q†š¾õðÉ× ãrûh^‰e Nù3Éñ4é5wSÜ.)À·ª4æ'æ»j…@Ý5Q\"­M¶¼¢Ç’Æ”d+Ž~vqO€dy¼_%íÁñIóài¾™7˜kUîögÒ ~~ÁÌ”ÏYß>ºK‰µæ7Ç=©R¸TX¾§ªçc‡­EÍur+;ÕËRæŸ(4¹ê4ä"Ù*šÑ¾¼X€‘¨UKÙ×hâ’Ú‰.4îþ¨yŠÆ¼|{NéM±Žvâ4Ž0'KBÆZf;y=†–Ý¿k5µ&¾V>@+s2«Pj1£ôÁA™Ú7ª›d–«):3ÓÎÊÓ!Û}{\À¿.¡{Æ3û;fzlÛ´Ûíª_£Jà431/2 ¨zWflÔ³+ö1!,'P½¿f¨T[J¤v©ÛË`þ }Á>‡¤Ô#D¹cGv`°ð›RMã½C¹Ë™cȤm¿û@Íœ·ovÚdWöO]¨õiÔi¼¹*m5–‡Ž8Û9¢îG[hR_FÄJ<Γçᇌ8[Z¨gάæÅ8_%j»-å›R¶Wæ¸<Õ Ì}—‘ÿDï¦þhº™×á¾àú*Ýå$ßæžL,HêG7¢mnZ™i;–xÀ Ê­5íU÷žOzœ];ÚR&_é48úÕëë¶Ðèê8ßA©´ñô’ÎÈ–#¡4‰«’×îöGÏRÞ®/Ý$ùŒ6õWŠëç-¤Ý3Œ\£hÔoó¦W:¶µ–ÕQšM7r%FÔÒí¼Í~¤LtsdËùéüUcœU4mÜeíÉ7FÑ?ì§-.*=˜»ãC੹"3ÑnV=§îë2ñð€UÒ endstream endobj 313 0 obj << /Length1 2535 /Length2 21449 /Length3 0 /Length 22889 /Filter /FlateDecode >> stream xÚŒ÷T”Ú Ó ¡t ÝÝÝÝÝÍÐ ÝÝ% "Ý-ÒÒÝ- Òyæ½uÿ¿Ö9‹µ`®»¯;ž‡¡ QVc1w0J:€\X™yb ª,Ìff6FffVD ukW;à¿bD M ³‹µˆ÷1g ‰+X&nâ ¶SpdÝì,lN^.^ff+33Ï œyâ&îÖæF€¬è‚H!æàèålmiå NóŸj3 ýßî{ ³µ™  `âj´g43±¨9˜Y]½þ'5¿•««#/“‡‡£‰½ £ƒ³¥ =ÀÃÚÕ   t:»Í(šØÿaƈHP·²vùG®æ`áêaâ €vÖf@ ØÃ dt€“ÔdäJŽ@Ð?ÆòÿÐþí €…‘å¿áþõþ+5èog33{G—5È`am(IÊ3ºzºÒL@æšØ¹8€ýMÜM¬íLLÁWnQ˜€ þKÏÅÌÙÚÑÕ…ÑÅÚî/ŠL…wYd.æ`o¹º þUŸ¸µ3Ð Üv/¦&k rðùü ,¬Aæ‘0wsdÒY;¹eÄÿ5‹Ë,®fff.6Ð ô4³bú+¼º—#ðo%Ë_b0?GG€˜ÐÏÚþƒèãbâ¸:»ý|þTü/Bda˜[›¹L–Ö ÄßÑÁb Å?<|gkO€3x÷XÌýü÷“x½Ì@v^¿Íÿž/“ªˆ‚¢ª8Ý?Œÿ«uðø0°3X9˜,-øƒßÿ†ùoþCþo©²‰õ¿ÅýQdáàù‡¸yÿááþïZPÿ{24€ÿÍ èÞe €ú÷êë3s0›±ü>€¿]þÿíý_QþßVÿÿ$éfg÷·šúoýÿÚÄÞÚÎë_ð*»¹‚ÏBÁ| ÿkªü甀æÖnöÿW+ãj>¥ÝÛhí"ií 4W¶v5³úg‡þ3px;kPÙÁÅú¯‡ €<°ÿ£œ™-øâžÕß* øžþ7¥ÈÌÁü¯Ãcåà˜8;›x!‚GFð…š=ÿ^m#ÈÁìÓóX88#þ5QN“È_¢'€Iô7â0‰ýFÜ&ñ߈À$ñ_ÄÅ `’üXLR¿+€Iú7b0ÉüFì&Ùßœ]þ7gWøÀÙ#pv¥ÿ"npvåßœOõ7çSûÀùÔ#0wßœ]ó7g×ú/â#“ß\‹éo®Å쿈¬3s°ó?vö¿$öö¿ýÿš3“ùÜ/àïà:þY²ÿöú/½“ø6~»€IZü†`‹?à_JëßÙþ‚î¿3°ü%øŒã/s7ç?¢ƒ ,ÿ€`V¿ù€»fååhýa–YÿÁlþ€àîÙþÁ-ú“ ¸öP÷æwd°+|èÁ\~vvø5˜Œão58˜#ø­²Züî';Ë¿Rçÿi3;¸jGðÉá÷hØÁp´ssù#>Xâô{öàlNn®@sS»ÿIÁÆþ[ñ¿YØxþÕü¯˜…ìñÇXÀý–ìä´·þßÍâøËèþÇ 8ÀA\Ào“ÿÖnŸ‹‰‹ÕÁ,§?™\­œ¬¸e®8€c¸ýÁÓsÿ‚+óøcóÀÞž@px¯? ¸]Þ¿‹Gò:ÿ“êjfnÎàé¸þýÚ?ñþƒÿþ×ôš!.Î9˜ñ…ÚÔ…¶Ý}!ð`ؘ¦ØÕJ§aðYtnw{x ŸBSó9xÝùF$e¸ue[‚úZx‰øÙçèk|Ä·$•ÖGß'£ÕÉÝVÄ… ì…G"õý„oÞ3¨ ïù>;ùjÙB…씥Èurã~«œqçÑ'åYß_¾<>·«²WÃ)‡ôT>Å«ñA?¨d†"Ï4k—ΕýÜóÝÌõÍ4zÎWbÙ:D¿ãX¶"Ý Ö¸ûYïÕJuV—.ËV!3³.7l/äèûSŽ\ß‹8¿ªÆsÅŽ´y;tƒ×NÅWÓδóóB<+6 ãÏáÔy™ÝQykñT*|uÀÆ™r¦ó*lFñ2/bùÄ-Ž…‹Aò"v©ÞÝùêáhý`/›{žÆSÍ*Ö*$;Ç1 cAC¢!a}<7æ[7¢†X?4ïÏ«<"E‡ã6Õ¹Bó¢:Tsº\”2¤Db Šo·g{ߘ’¨‹º“Ø7Ç¿ÓRxØë*~ò /—§ *ZTè—ûÉá»h° ^Ô‹÷%P;êº9µ®]éŽù3êjÅç½eh2£öáfÍ‹|Q5õ»|2ï ˆÞù©±m’ï“Ûä>vUú%ì}->ŽÐv ”$óÛŸ~­ Pˆ~±ˆnYÓðiXz_›93\?…%ƒogcÆ?––Q}^“/¢Ã|KʶÙòÎ~ Žo¨vѯ[üæ«ÐïÒ$_ŠÔ8|3±÷Ä™’3å)•§¬ ø·c]C1—œM2?‰(Ï S«—ý íj»(€†äƒE˜v0‚ÙZ Ä6ÿ,æP]|ê…*†2›DI(o-ÚÆË„È[Ùw5Œ°‹}ub²ã²®å”½>\p9kÉ‚4'z'ºŽfç¤g ’~Å0•¼•œ·ô •äHŽ÷¸P‹$÷­y rPáßOCBš4öoâÏ"ba.óEÈxåoýiÖÐ|¿ðymØê|-7t½êg Bcã—/™BÃxÆB¿¸R°‘ŒFsaõR:~q{*ó³³Ìþpýq' ±ô…3ãk‹Ÿ³œËO¶ÇOb°ÖŸ°¤]«ê&§ýn¼p‰æ^ü͈(ô×Îõ¿}ÛcWbw'ÑË4º•ù–ÿ嬾æ k`Ï,Ÿy°âRAö^!G‡¹r4Þ݇s7yNÿ®åœã4ü‰” Oà:9K}JGŽqE÷p˜¦›GjDÎÇ$RLWT*»‘ˆÐk™úm´Ux/«ó´fZ5§Œ29¹Ýãχʆ$œ ½.Ü£àØpÌÝ >žÜè<%+…e²iwÄ­ì(^½›ƒ¿B%k®÷š[bFnÄ 'í§VÚb”þ”ŠÉWžÎñÒu¡¾¹dl3Üï?n7õÏ-s\«(…ʶã~ô]=‚àÔ<Ú“öÚÈsÍõÅZ2 Ç—”næ~i±zp;‘È›OUo8ùï°h2}®½z8!aNìÖÉsð¾'?¹Ÿ¸ ¤è«êœÆòØ\Ûd5p(ï]T= ÉX}çv'j* ‡ÃÛÈòa!Õ¡lÈ‹ó6¸ki @(‰RŠ+âP»ô ,c8šþR“-å}WÊsˆ+0D•¸C=úÜ&ód¥øÐ0ç³£„x›Î-ïn6kkÝXÜE9Dªp|hß'ܬ5^…[Xe¿bJÁ¼˜Kû`üé¾//i=‰Éâº7Ë®BY‚5—HS„FMTži¿û”£\,[¤`ý6ËŽ¯Úç{5Ù·mX$\")B D:D(·ê‚C"ZwŸ:õŽ‘Ö9”©ÈK€œ¯ƒ’ÆÜtšÚúËû„v¯…ƒWÎÀŠÜZÃö[×lba%–£<¦,É âä&6/"²Œm³w óRýºÏ«zÐö•¯ß¼| €{ƒnW~_AÚ#+X „YÐ×}ï·¯IófEmhÙ>ï,h­äL»»¨½U2vº¼]9‹ñ ]f2Ðó¦×Ho\[3 gðוJn Šºòëµ{Hî="p„>Ññe ?Ä9À*é¡%É ûâcèc:;|„[ ÊíÜG#a N6|éue÷Io<1,£/9c˜º,D´å;ƒ±è5ñ tƒ¦Žá|>«å£o‚ªTذ45ùòÚÆ"§ß¢ W+1*eoXÓ·qsWÌ…÷†‡Yæè l“Jn<ÈIÞ©ç™>¦'thÅÙQÛYVwg-™NUÅ®’´”ϦÎ~×ß|¾7aWaÁù2ê¨àÙrÒ,j)-$ºڞ付Çe‚Þz't#ÀWìòν—ÏöÆ3ˆC;/wFŠ.Ê/qWïˆQââ!—‘·~¡LY°$ØÙqzAFȾ‰—Tj¼ä—{³{¤®Õ{ñѺU¤~Ò "ÿ >:.GýBO ,•¤qÉ"åö¾­I´òòí¤“llm·Ê<ó<Ǻ±.<TÆÛUD(ÇÎKZ÷¼ŠÉEÇC.Ó׃ÉÍÄÂp!ÈŸ µVÃ(YÙ=ÐË켑öÈgXµÎ0êx`îKm¢³ôö*u!Þ4ªõ®‰È ¿brŸiC€ƒ:üÕv=Ñ« iR@Â7[h˜ºké±Hˆpǵ+ùFGØKÍÀÿ",*£êÞÎAtîgeÒâÔ,wæûƒæhÉä`äÕõ‡Ó2‰u½È`‹;eOö@é°\,ßCx­§¾e)¢9LT R6Ñ+ŽÅ_O{w›Òú¤Ózpw,©ã'fŠw<厂¬\²­¢Ï¿]˜ O£›,©¯Ê<±Tèߺ êUoq%I¹ô·ñ«’ópbRF>Ø{UÓX7âE»ÿ´é¹Ñ*‘ïS5$T5±ë<ò¬7Ê×Éâ­ãP(©Yß;]Æ<‹†Çˆk­z×HPúÈdS¶Ñ¿˜Gâ·fœ|z$N©õ>p¨|gNEû+9œôzÉþ»QW™Âª¶7C³Œ‹:ï/„@XΩ¨FWÇ • ”¥§mWEXyPjLš¬Ñ¶¡Qز%fb£6ö@<_¬1Ñ—‰“R9шµsN`_S÷ qMB ¢`ò]§ŠcB8~E~À4MWxSÖ}cÑ%S,¼²á×kÞWÙZáCLÏŠú jf©¾ñoXË*NPqeƒÉ¶êT_ϳQù²ù?:€vÜ‚\íäÅX’´ûcøiˆN ó}NSEAB;1Þ,bjt]ï ”Yzý‰€ÃPj¬cHl²© K#¡)vÔÓäD߀Ã*»LöŽŠr\ZÏÀh_šÞå…5“héÔª ݯÓ5ìn±~ý}û½W¥p˜€I’ï©:)LJ÷$323:»¥Ó9xrfE5-ÇD™¢‹£2jp,·²_ÓßЬގꩄË[•ë0ìû«9¿x™p”u¤Êf'øˆx`bßÀ”Mâè@`Ç„ s&®®ORã#Þ}NDÊê i—¶‰ÈGÝvÁrÆ ö\IEÜcì\š˜«©Éûa›V½d×ÇG™ZCÆ¿¿ôéË%ð#Å䎤w¦qó`³Pþ¶Œ„°š4e*ÿ+l[â) ÐÁ”%ü^[³¶œ­ÿ—I•‰—WÛ6ïÅ4f¶Iç9lj°é…—¹¨M& ?¶õÔÌ£ïŃۤRe©hUûT .“ð3ÄÚZÏ~O7Í-:}±†H3ó6cƒ$Òg1JÒ¯ÃcqÄF÷M1|uã— [²-îyoë‚ VÈÉáËß-S‰Y qdð‡ªá>¶ž|ÿÒ}!œT…›õæ“IeC f†H€YtøO;-ÈêËx8gˆæ²eãù ŽÍ²1›¯”;aµñ7*»Üç€Z’݆§¼ëiåž‘cŸä|8‰šô3qG“C¤ «#%[hã¬æÓÌmÇ»ä*n7¯rçËÔÕ_)nˆ~fN½tÝ^þ$Ï«³Yw]Ço5è« ;\siö¬y¥/s;”Âú–©«€JA? %5;^œ&à°+Ý6ú¤x#7/ú¼C²Ã2¥uõ)â5Nܺ ˆP&¼· q7¾‹ÆzQ*ªoµ4± àVkmµÙcÊ&Þa3L³…ÞZoÏK ¯| ²øòlÛ¢Êx”yýìN8hψN5¦¶Ý#Þ:ºhçõDŒË•„¬s='V_Õoÿ³Ñ°©FÊÃH*þ®q‘¥øñ+Ó‡¤—ØÑ­sÄ ö¨Z–*P¤Ñ£¸ Ÿ#ÝžE¹%9áCi?¤ð™Â½ñ‚áÔW)¹>Ž ¸BÁ£V˜g§3‘R6 ‘àu4k·ÊÀžÕÞËöɳã)tgÔŸ„â×7¼ñ±KæDðªEЫ€$W4ä#†òô˜4[ßLÊ ‡¿YmýàÑ›)q{EPÛÇå‘KÄ EëS—+3Ñ&ßñ°NjR ÑÛ‚òŒ!p )ð‚‘¡N}m³Aå/)—é2kôóµ"ê"OðßÂÐøÑóÑ£U'–®ý¹R—wül¿ïGaÿg–ÎËF»€E`Á ¤±Û0¾/Lå11ÖÜJäAçÃ%N‚S¦l¯ÉGc“ó<ôâ!”h½šñhT㩎Q‰ì‚ünØc"ä<ï=ëKy“Pt?›‘/ûÃÂÑ»~ýžïöδš`á3vA.qéÌ Ú·>okì„t˼ŤŒ Ç¶ìsŸ;2ÈOR§kœüòG¾-JLœà<¦(ü•! ú˜ õ­´J„‹ô§x¸*?«ë³BÿàÕ½Ënqà£-ŒöU¢EAÙçIè­×Ït‹ÅÚÇ%©¨CŒ‡›$]½¤´²Ëj\o»–tˆjÞÀžÙ,£RN-ŠÈ"ÓUìEv~mE@_B¸NUÌÛ%çt¯SÃW×A‹"[Æ­–O{e/9ÝÊ„øAus|Û{ ‰c®)%?GO·í‚U)õR¸aÈÔRæÔÐ 3|iõ¡ÿ]åý½.Q¥w¨x™«02Û-ýSf΂°  ¿–•ñŽB[¤àë|þð«ÿ&pãDS\vÖ7íÛ7íw~“%bÎÑC8êC"CH¸ÏPé‰ÉÊ~|°Ñ¤Ómr7Ódã ê¹Ío%oô÷ñŸo g’  ñ¡‘ø2ÞtùªÄõû‚Q¤Ýf8_UúŸ'Ò©²T؆Lù<ÉZâˆÙ~«ò–Û˜¢,S´¸Ê&À3 Žä)½ž~&tÖ\ êÁó4øò®Mfë,§»Ñ Ð.ëšÃ¡Uo?oB’•^‘²” ú,Z¿VQ¥[æRzfìj‚¸KH÷DxAò g_ñ ^M»{•¹–¿’¦ÕjCk.¨Ý⫤x³Uü2ãB½:¡ì$QÈÃï™)RW±EkB òªæI)VØèÝ3ssÎÖ6¥Ø´àzòò¢³Éa#éo”éÙ­‘íC¥Ø8*%üNc•SIŸ8#tåFð‰wXÓèjXp¶˜‡V†Ù{ºQŸÔg áŒMcÉ{àbØmGò³ôèbaصòzéÄÇHîwÁOEŸkßVÒ#Âv?w®†ÄÚ'€—0§WoÞ¼ô$ûY¥›¨êý%¶ÙñnàÓý;_¸ï®6,“™"ûÎ/ÑXÕ]“Õ/x£²î=ôrľo.Â~¤h®}üø1ý)S%´Aoe_£[›÷=LðÒ²Ý ÅFí›ÅÖQ5žð»îzÈØòlÒÞ¹¾Ïõ–ê?ÛVw MË´úà–©ëhÉ<à*ïh°¢?$m‡b*’8Wõêxñ…Sâ8§ñ‰˜Ëˆ3Eù!2Ø 9½õ¿Û]¾}Žþ,ÇŽO;$Ç€7¿ªU¤¶«3V-R.E҇ݷò€S?15*qƺ0!­ÌÕSCt¢³£5ÌP'9Œ.¡0oðiH4j+‡Âà‚•‚_åëÞ–ÿ´•á&ÑöÏÑã/ƒdKƒ>æÅŽ“¡„ÖÖ‡Ä<ÎIc> ïï~œj¿”¶O°ƒ¢Õm*êŽ*EŠªz%Ñ·J…ÏZJœåŒæ›UøÂ$ûói"†øÕ8ûrHÕ+bÍ|®+£sa­L°{jt-ZÝ(z-y”#dÛqiQ2ÓifDb©{$ ¾¸r¢¡ Å´)É6¬®«s‡»{«~ñ/H±fi6ÐÖ.âhàýè[+=l1J”7Mý9Ö9¾//¿€?\×C¢ÈØbȪ#7‰j"·ÊçDcN?˶&‰¦~ /ms–~Ú8;:yónz©.• F}[ئ¥ÁØNåƒ2·V'!œÈ û‡æt(ÝÆô d..ûrÓ·¸;7²ÔyòMA_zéÆsÙ/…7I×õSšb¶‰¼ ^‰FÌ;ä±x‡1U.HÛgÉ¿’qéž…²¨¤ –µ<„H1ofKà#^ßÌÕãܙ蜤7(‚†QE"›ç·épPt}Ê[XÓ†ÇW÷”¶&®o·­íÑhˆ…à8rêÖ—üˆíÒT÷9@‡ñ-œ;{N»‘›8†©ssÁzÊ:$ÈC(÷‚>®>sEÈd‰b=¹œöVŸ"èü=DŸùïXlëZùÊdø“6´ÌÏö[^kR j™I 焊×.’S‹éöÂGV¤~Œo¶½’1;Œ!õs@ZÔË$º‡W‘â¡møF ½µHdIŠþÞ }OH¶H û·Úãžf¢aó~º¹ÑÓÇlbï‰Záž?ßKŸò+l0…OBÒ,èi[(š »uÍ2ñ2aÈ54ž@oSb%Qvßò¶\ш}­—„©]J|©ÀÂ!èqy•J6¹*\3®ö‡~BÌx@²°oÙóÌ“Ú!ÓŒd¡£:sLå2iœJ­ÉѶïi¾YTg-c^¡L¦$jïøÉœâr+3œj—ÄL¡ÃAa¯í6í3¾‰ÀЉ8H΢K´ÂU'ˆŽÎ‰¬·‰æQ|ÒÏHã½D»T•#Ùœð4gÈ¥ö|D¾Ðèš3 52jHåc+Ôã³!å#ÉÊðœþúÀuE9ŠˆÆ œÜL„HÎUNAÍ]ž3d!9µ¡Žu?úø ŸŸ!%]08ÔRVÜÓÉþè1 ¤›Í† ×¬_å;n`€Rì ÃbðÐ÷¸½N)šŒTc%:4<\fn{-(!röõòÝðé¢/Å*!4Q:›â¤Úzp7(ÚJÄéQ wj™G¤.¥µO\ †¥ß{Ó8ýYÀ¤é²øôÍDüð¼Œ÷J³¦ë(ïYF)Ðê£v,Fð5,:5ÅH+µªØZ­F"··’}ï®ëŸEsâ*oôV%2ß« k~ŽJç½J„4ºøbFÅi8‘ÁÎSâ,¬ÁûÇmAGÿ$´ÙZÓ­E½óâªH™û÷%Я™/nDþÂBFgnôW*ô ç†C~áåFí&$vª‹,¡ÒܧŸAeûì6YWÍ_Î!Ät†ªJž0š#2þŸ!ÑÓžH­,1ñ É…‚¬PõzÑ'¹Ñ©¢tÅš,Æ…w­&ÁZR ŸO˜,êO*Z'AR¼‰ÂÅ­36­7Û°[r:cEð†FIâý¸â}±‰ ÇPAOaÔK™ËÆmR0e¼9o->±“ÛdfM5KŠ(̪˫ùÆÈº}ï‰üg×dÍ’-Õ…äq˜¡ÜwÒ£Su¯ª!% ±ýÀ™cr…2ÛÕ%L4¥*>7xÚÛãôl’‚sm=¾ÄVàçxíN¡DÙéV¼ÁÈÎt ]‘Yä躤ýÙà|Š75æÓd·ÆþÆðÐRVÙ*9­ti0×åÜ…‡ ³~î! S3ÏoÄéñÁß1º7²‹óý{Ñ´(ŸNt¸ß²)nÖºñª–Gãûl–·„+Y+7Ê8µ›¾>{»¦^’QؼâÜŽŸù+OcQަ6b黥ÈKµ£Š°pE)¿KÚ­7Ïkƒg(êvüŒZɦÉU¸¸w(z¹uOm‘Î>׸£?<í¼æ µtÌsMw2|]um$d©L¡‘+¡Ö$¬Å€«ôö‘ ÍêÇÀøs§JLÇ2úý-àMa=NqÏãþ¯>k[=Xæž ‚œ¥[q83ÊFOËâx¦¯o™Ì=TQ›ït[ʾƗ¾,ù\nššô…5ºîC9ÜUVÁÚï“ ‚[C߆/4šâåõû;§È-·››}klk¾Æ·¯;-Á{s’bXwÁ¡è`x iÛ›Û‡ÌÀJ× 4r…D›;K:jEà2òÛ³Øú|ˆ&U¿ÖŒŽÍFŠ7©tøÖþ-»ýjmä"ig·¤©£ BÉ¿ _¬6†)HeÊqÆ#Îu¯Žµ>× ñVÓµ/VTŽC9ªiý0г–Û-È>ý?#LÕ‚ÿÒ”JDˆ„°v„¿‚j¬‚®¨Ù:Ìkg¹Ô$/åoqè[êL*û°š\+#{ä¼Ú$/\âè1¯˜r²Ü ®<¼©ýô„¨;'ê37FW'ŸW®ù%ÔòeY–a7‚TïÉ>þ’wôÊØÇõAä^#²ËÍ wwèö09äw›%ËmyCøVhã<ø:Kä.¡ââ^É<õZ߯öîÍš\y´¾*YM¥¿c 81yÓ4n R ÓvϬӹº_>̈«ê™”ISaÒìÏËæƒ¶Ñß.2 {ÒE†)R±[Óeÿ5–[1³y[¡°¶·ªôþÁm[ê¤smŽK=)å¶#MöÈÑÿaK‹ìGjZ>꣑طXw |ZY.]âýÓ8´2H„–X‚¸ÇPÈØÚ½òÜM›×¶ý÷ =š²ë—±¼KsúK_b•ùª©rm–…Î$˜I¿°¾H 7)ùœd}J¥7}!R–2®ËÇä¼7Sÿž¦`›ˆOŽë{玨ñÖAµíÈDó%V}b@¢Öyë’a€>]ãnnÔ0Ê!ÇüiÌšØØ8¤Åö±ŒSB‡^Џ™Yêò{” úq®Íôd£BøËGAd=„ê”"cEÂí´(`häV s/êTp•=·Œï'qÚøìCi–F¾rá3‚WG$õYî­\i€gÏú3pué€K?áqZ[ÄÝY»ž;Œ-*Žº½U1Íøù ·¢E¸Ï §à†Àº&8ÐË@ÞyŠömòx8\ B8ó˜ik bj3Í1ã­qî”ÿÝÖ¦4*9¾òú.Œõ÷!»ÉG"kLä´Lq^› ÆxX‚ IwF‹VJ#Kœ‚Äp!YJ!iJ~*#þZe…Ï‚"Kvê‘zÔ«&ï™a¼UŠÕ×m.vm¿ýøé¢‘‚‰ @¨ r̵ÞÃR‰¦»ú:}uãtÎk\(άl§XV?ˆ Á.0=3]ãøñ'Ánª>Û.ä®?¥#gʬ¸wýUñ}áƒP°¬Ú«¬TÏxG5!ûÊ]Ñ™¯'õ‡f›º›#ïk§Žì•k>nY" ëÉEuôb¢ÞÇÚ‡,/¶šînÙÂÓùб·Ëøˆ’ØF@a Áùh!ï[ÅsTIÐWÍ@Î.Uë@é«%IÞž‹ÅÞ{t¾i`@i¾¤µú˪sÓ˜L3O&#CÃÝg3–t©zƒŒ ËÆ¤kõÔÖ’àÉê.{¼Kkâ j oRÙtV¡’#;SÍ$û:,ǧ®”¸ÿDíFúnP>U”R½Ž@ºQÛëí9/CÛUG·’…:4{OqÂO„RÍ;x•tމƜyk=i,nÅ·CC zOÃxÛõÆg öûlrímNk”eå. (è§±´R«)…™–ëÕúð%ý¿b6xÄuÕ}%¶Ä ±‡G7:Ìf“u:S¿Ó¡âû"±ª¯óbŸÞ¨5€û©àËÄ 0’sUùPed“Ñ¥_8=8ÜÝOÛc„êv="Ýcá÷a>u`î°ÈËjhž>R„äwë$È—ª=óvN«<ŒMQ¯q<òŒ;´éÚ9f ̜͕£Qq#[¦o€øD§n²à:îõÀo&³éW§ÇËX ߯d­[é´dPTÍ<* .½Çô^eÈgõëd`¢Îª› ÛÕÝÂ÷³Dƒ•Û@c@‘ÂÛÕYŸªÕ©‰rQ. Ý ŽüÖ¸^´¸5&ú5-Ú“PÏ%÷ +ùñ¨ÊAÉ>¢YV‡„‹J¤ï =ý• ût»6,Ëà|\/˜ÛºãÀ Ô~Ðz-á‹Á,T¸fÅþy© %*9çÏÌgçµØyýmù ö”|å¡Þiëâ¸\ù¥Jˆ$`·É~F_ÒõgÖåí7ø²¶!Ë”+=͈6mu¦díˆö„˜¤¬KÕ8ö/,ç%6J Ñ^\Qß•ËÞðEòúÃt|©à Æ®:Ç©›HÎj 5U ùÚyÅçH^¸JЀ£}й8¨eî“'ÊÛn#ÎŒ?3"°ö!ÑùE8A]ÑèðŸ,ö£Îz\¸Ù(·V/n µ¹®°>øjFà¡ä9I ^ÃøÙ¼zΔë/{Š[°‘.Ø^ ÙÆõÝTþ5Ðßø>¨âl쿳)UºU•_É;`ˆÀYÓrIÍ”b%®€®¦}V ¼5<3éXß ¡Êð[ö#}75ж‰û¾ìó HÂ-0ªcèãS´ã)f÷`©×­ÔÒé’ØáØ9zjk*$Z£$R¬ï—Û´¦M°??ܰ2ß­×Å\O XVî CVÍÞ­@žwÑIvˆ$Å.\{â{$ ¤Â«“ëBŒ<óžß<ÏË‘ÝùE|–#ÜÉÔa靿h‘+ÔÁö,v…s€OºAµ$—ߤ"fß\´”j.AmFÛPŸÐgü™O;×›X\J ]êj³T û—â±–èº×,ÊWÞ—+|Â3 H …û¾¡æ8ÕÖ!Âíù=#Ń£Ø8"ê1y¾+©mßýúûX*Uk-gK>ÖC¦fV½…¤DåâŽz¾b?þŠ;éµ/OÉ™O<4µ¦.™† í»[[KäêyÕ¶ˆÃ»#Ñxá#õÑ©ŽmIȼ:×[¡ŽAHåéÞº„ï"lûÈ.Œqìˆ= ýîâºé³0žž :¿?]YfNj«²™Q£pîÉáwgÎ ¼¥œ–oñT×5‚!…¯Íì$"¾Èœ¨§j<ÈʶWšïÑ=%ávzç¥?W—ÉõSº¼o]§øÎe™òx O·LÙ¯½ñzRœ€…âø b ü¬éU‹»ƒþsLH½Ô¯$v0u鑇ÍI”'F.s‰Š²Ë ¬Ðn•t(KŸ\Å>]ª*‹Lê}{Z¿A˜J«ñ.d[’Âјk¬´ÒÓx7WIÅPêôj`¥¤‡-Œ[©·€*åBòBÅi¢!Λû}[Ûöׯ”“q•ÒRdä »çD³1·«&BÌ'q˜æ‚hZ!‡±)sô[ªB‘U{wÖd_Ùúšï$pcÀÏ”ªïeï©°•Ó˜Y¥ß½‰&ÍÞhœšÍbP£­´È¿›‡µÐA±Çá<‰œÒâÆ¹ ù÷õsŽÿËG>äü±nMT9_XÕÊr”küú˜Û‘%?%D&›tE¸ù,ÑÑî¾îE´ïè4å=…B¦Tí%szî)u…·’T8·Ò Gn¶•p̪QøË~é|=Îa¢Éõ mYìóùzUiQî¸ò«¬fB¾øsÜ}¨”Ñš÷ØGSºÝ["³¼ÊwQ‹¨ Áïy†²vÚ›J*yc„ò‚ǰf"–‚÷Ëâ3ì“Þ;ÑÕLŸm£N€á‡Q’Vªíå«Soû|UïvˆÃaR“Ë]|”_ý)Uv”B‚žqB³ìZœŽ§5o«L@âuZòS5x–·jêËðó¿ð¸¸Ž¿ïØÌL`)œ†¼•‚ ÅîÙÞhÙeþ.•à„±ìýÄí"²sŸõB%=>ÁÞÛøÌs¯,l‰ @>VUÍ?"þ^AÍÅ|WNØ(…§%ŒG`Ì gš§#ã‚* õ(dé×÷þÕòË83ï@l±·ÐüÕ* ÷jHÜH(Ae³‘ý}«òí~¥Ì{zdìŽ@roÏÊКáv¬˜óvš kPˆ ³ïéøhkÝ`¶atE 92M/:!…áÓœŒçbùŒ‘½9ô%ªžO#‹[Oµ9èaô\§ov¬ÖçJ³®ZåKÅÎÌ,ose‹"ntð3Ñ`€„Ã;X¦{*3çUÓ¯ºtþc0rÓô'O§2…˜É6QjDéC™B|ýƒ .< Z_YÂV‚[w!såk.””GWbñ4Ÿð¯Ô…¾-ZAßÄ.ÙGÆn[ðê…F¨•Jêe¼÷Dûêgc:è²°¬ÃgŠí2xâæ*âçˆ7ÈuI½=¨ëýÈ:”6ì±fƒ°‹þ;•½ÚŸT’\ÿ@ œw?eKJ&” h(âS/O]‘Ñ[²i{k¯Q¥•6C9Gß÷-ì4×éi5áyÇ8ƒÂ«IuÂ\ä³…{áô(sV+)y˜ñª.Þ^'ë„ù#×¾§@ÜЄçbýÊùOo€ŠÜ GX­vÞ$ùH1ÞðÂ+¢‡=g/¯SÏÜùBiÍþPR£çýN‚Øw½w~ïˆÇÒ.š L P¡c1¨Ï±¿4“*J`rí3¾é–6>½§d¸ÚçFšDor³˜-Þcÿ¹Tno!2ñD{·q¬4Ç@8’þ‰¯7+±Ê»føÓö &‡# ><’ßuÐÚÜ=HoÏ$VþºƒÕšZÆÄv&[±R¢Ó©DcC[c`Rµ…£‹é¯AHôÞÒhöÍ4Z¬DŽÜíÜ‘ÜEëà+5o¡D*ͼÐ=KVûÜó6!—·÷æÇ•´@ xü×A¾•>±ðWÍÏ"M±P µ\éãYÚøœ^Ä ķWƒ ÑôòVÓ}J²œ û6׫+‡óel  YÞiïkC6ÁN¦ÓùQÖ«'ùI<)AÞÄyÖ÷ëUMU)«5;åùË›jô¾Zã4¨YÀYz©Ýœ€äqTŽ¡ËuàýG`º@«:{úûªàg˜Q§3‰ ¸1h7eÌpü–oLƒ¥|Ež~Ó2ôdRkyC¨ÊƒdÀ('1¼Þ¨Åîš.n…身IÜbXÞû²–Ü‹ï«Ô¸pþ¦­Mu ï,ó{ŒâØÅ’,Œ_N‰ù²ÏG÷–p}¶NȲßähŠN”ø?Ç1¬\§›»yÀz|…‚²ø:Üú"п/üèWb¹<«R[ùòI‰òfá—•ˆò&ÐÊh¥[­&½Œ>—ÄÞÃ("ºyˆ•ÃÛˆ¯¥ô6?¸Ê¢W\QœÁ_©ŠÄÕ—e¿+Àªa<]Cd‡Øžn‡e˜h+žŒ˜; ~Ä:Ûsã&_Å¡CSƒšîú„‘é‘ùE?R“:6›Ù]9¢»]FÖ8úG®L­C„«r4ñ˜>š¡vä¾#¢Ê?+¢¹ð§úóG†ôœdúP'úÊ „åú#8¥â~&ñŒ8«­iuü5"’A®ƒm{·¯·¦£šÔ½±JvÌØÎ¹,ˆ?*Xü;CBð=‡R°Ñ>¥yFÊîxýÚ‰dgÒOQÀÍ^_µÎ†ƒ7^ÍÒ>ùß§ãǵ?6äÊw` ,ÓÅ{Ÿ1ub9yÝÎçñUA™"—“1ôfLÎÕ 2ÙEñe„Àˆaƒ˜¸Hó±¶óƒéЮP̈—Hw´p!h©Ëž–¡*Ó¥éÈiÏWŒ°!®ê× Ðf^ûãm0?àò“wÔÌ[óËl¼ßŒŸ¥–´A 0¤,½gˆâVž o½H‘ã«ùú¬âð'ŒYöz׫óׇûÑ_¸i—2מ/ܽÇ-8:hßÑrkÝÕ™äàˆAaNîWäTÈp$÷ÄÐaVOô% ‘|,pêÐÒ§æ¹öcÃd¡úðñêMìY¥(³¶KÓ %‘þe‡é³ùãn¾¶„(Ì5^#OÅó;ư¨sAÿ× ­°*Ï·qñ_iÜÅ”ØLRívÔ€çÏ„íòÕ]oMÞ ©Xå®[UH`ó冡„~9AÜ‚Ø<êy _m´`ϸ^E¡–€mºXŒœÉÁ L{ôù8V¦dNxx4_H³"Fÿ±Ÿ;7SZŽ(¡;iò;nyÚÉGŸþ‡Çr)Ô»<©1ð—ØÁÛv+3˜’·jÚJ¤ÂC:ʈ˜þýÈA* ï?­ÅgSâÅ•ÇámZ`4£GË€jz Ÿ¦(U®J”RÄÞ½¼—Ü_=” ›ó…j7öZ¼ªpÕ>|üF4"HB팭‘|¶c®«R­XÌ%ë%Ý"äiì,,qè*Ê6Zɹ3Жƒ¾Ãô…Ø@ ;ö×Xžf8ì^±iV•ñðúíP<$ÔŽS Ç+§^•ëÆ§8ǪeL‚bg<ܱKÜñ³‹+ýýM/õBÁk0N œ_ÃØø„@É‘øM²@ƒG\$ˆêeÜÓò–Ç>Œ¦Øº©~’‹«k“Üeeƒ»ešØO¦1î²BB±Pe° Û··_ú…"2N1vÄäŒ&_hG²¶–­ŸáMÉ{‘vÎv‘Ó=h¿a0žWÍÐH¾U¥B­¹«1»n•Õ’RLs uÉÁŸÏV»þLÛÎ’6äàfãeß­t´íyÚŒºÝ?¿<ÉE)4<2Ð#Ø…tVäPØn=—$œ²§:­ˆ…ÒŽWF¦à‚SÚ1™V¨„¸¿µ´>/ :¡´ˆìuMI¥Òñø‰¶DþE+»•r”bª°¸]tM:•2xa9±½òu°W*³PöGfÄŽØOhÂ'Œ&8¢b¦´=(4¤Èvb{¡h bÂk¦™áüÞ^ %ÐÅ2«ÐüÐX\)«»q;¼c?$(1Â[Áø!P„Ù1\ʹ5›”ê»_€>Ž‚<÷^û*uë×Ý’˜Ù¦`¹²ö‹yîy{ôà; ^\×;‹@=ÇšF=B;¼Ú/™jôjy<5ùáQ¥ÙE'+«K"\ºÎªÜx•ãÙT"KöŸ²+aVކ¿ÜÉCÚ Ž6£œËhk QšÞÃ{Öò_"^óÍ)àG W¸Ú Ú e¾]þö$ yƒÇÌ™î©Â‰]£óéŠ<{¼jS÷Š¥:)u6”.eDOU@Ò®Në†jë‹òƒ1‘ýð'Õw,B?)Ç{Y¸>à÷/î¼iÇLÑw8nb#H ï0­÷š¾ZAûÏ„cÄ!ò¸/K@…&œ»èŽ»"a¥>,á­›?Õ"ÝK^äºÐ¹¡\9Ìó©Û!¨cEmŠˆ7Ž*5ó±cò€ö¿Ç…¯QÂ|è‡c0ª…•2±!âí’ôØD±«ü4è'm1Iý!ÞӪ†Tñuó¦Z.º*'Fýþ3ÙsHëLa)íÏŠ¬Á¼Çk}¯ w–-%3=s`jÔƒÙüŸ@Ûg'ºP^¤±7´Ê ±[A›¯k˜_û%/]g©#’Q‚bÆ¿‡ÚÕ…ïóùç·…u6•À䂤ÎC¯Oô ʃgµ%¡.¿Éäo a É]#ß^ú³¨B_ñ/ÛlÝœ£š‡îî ½µu|÷mìM‘”„Ÿ¿æýTY$A‰ƒìJyƒøp ‡n3†}c}mä{5_¼œä¢ì2FMR„¸ý‚¨˜x: |»N'À¦™ ž×¯_ Ìd‡ÅÑGí“íÝÛwq«?ždZ–‡ï'a%•°u$‹uŽøJÑ #£ÔÆäÌe¾ôÜXÍR÷WßÜE”v}:úõÓÍ&åUã®ãªilÀæ–Vùdš~ ^! ÉÃû©EÖwÖ¸ûgø°·ÁàþpÂIAbÕÞþÚ{ü>â…½¯ö Ì!ƉžŽƒ 5/#…ªÅ¶8³—„‚á6™ôG½Ï99¤žº‘ÉC‚™ij¤A)µ þÝÉvy8ržë¸Œ‡É4u_:‘3%fb-q´fU›4ç&‘ºšÛÚ“a–õ?:“ ôߨ,xGlÒ´c Óís& z1ó1ßU sè¼)à –_î¤P ’ýò|Úâî|çýb†­Õabé´ŽÒúå ZÿûûÀ/aò6²PbO±øLòÒmcJÒ‚­‹b¯7|.F½™2“dÞr._JÏ +_ªU¹[–¬”ŠNššŽ{ÒšÒcûüNâ,‰"Lñ0hãe¦+<áôl-£ÎÄv³Œƒº¤“få~† ¶ØÚWèt ãzq19H%°$l‰'¦kÊÈ6¹øŸáÉ«ê¾LÅn¬1æƒäxh ´ÔRYiZ¦ž¸n{¡!”¤²°“0ݼ9é^Ø's2QxÒ*ÍtGÁçdâ½£GcG©|¢á‹V©¬;çCÕý®,Ôåäfeî¹¾³ñ}>RïmA2™xñÒ§ìœÁÑšØÀ.qm¹bëmtäØg¨á›Š˜v[f!Ì÷M¦l{0­"=›± @)ýǰ"ÆWoi¡ˆ[ù†ÏPµtp” ÛJn£Ñ¤›åwO¯b=X¾pÒ†1Jó7#ùnŠƒÂYnÜø¥†Í׸d—¢¾<áB[Ó0ŽT»FÂ+¾²¥×Œá˜DaÀr¢H òV •kÁ)Kio×Ý]o»/’#¹”§‰L'ˆÐæß‰(0š¿ûA€RåzÈT£·f üP/`Aa z·¬&%R½›à…ÞÎuùA¯ÿ‡- Ó$tEÄ»^â(!a® ÚýìmšðËuçEä*ÊúŠÎ%@çJQÙŽD{a ÔöJ<b…߆§ŠÆªÈÆ%=ÔËpøÏUkSBièöˆ5Τ^&„’WâýûßEñø ì÷°P[] ê“ÇÝÉ׸óïï¶ÔT††Åϧi½ ë,l-¦)„Ü>ë$jL ¢vž¿C{?KÙ:ídU£[Ÿ'`)*½/¬õ8¬ñx§„ږĆýVþ€g˜¸ç&ª½8’ÝNµc" Á˜HÛF)='ÇE¦À2¤>™¶!*ïîñIQa޳òrÞ£à°]Rk<Ö%ÔëÎ}\SúR-вë:{¯zéVç8ßTÎ=£“øŠÕ4e/á¹|PÚûÿ ©VèÿŽkÚCŠ9½)á~}†Ë»ÙSeÕ¾ý@Ì(hQWrW¾ÑáÕs³P¬á©I×D[<®L§ÕÖô}Fñ°9ƒïÈS…ˆÎÁ#yˆ¥°5‚ÞC4¹Í÷ý_ÆÂÑIMw6± ”ÃM°yUp«ï¿¾ôéÈÔ&D¦‹ùh/š“/·*Õ¤@¥Á˜QÙˆ#¬‹¼†©Äþ<í…ªÐ/Øš*ia¾·M7{ŒÇ;œYgÙ"ÙŽÃý™ÁÖÉ’N©| ¶9d¯É†î¬HÅϵ˜/`ÝXu¸#ï6ÞÒÈGÖõbW©Mƒ45C캙‘sÔ˜×o™=¨ÙsÓ(¢d˜iäWd¿Vµ ¼+œxþÃù8dÅaSþÚ«¥Y|ã\ÅW éÝxöl@Ðdû׆ÊÒÈ ù}š)«ßœÖã‡'aM»JàÅ-êc8)oš=ÊhƒÚ/TЩ&LØJ_¿ù‡”A¨H 9¨Ä`‰•Ú±·™eg™ì ض×ÿµwÁù\^‹G¸ GD*&páÍ 1I‰ˆE²»ÄÑ€f´ò0ýdQE'Š[©Cóµ[½Ç2‘-ù­ÎRÃdð>µí„6°Z÷EÔê‚+½*püO*ÎÄzñfB°`Xfz­àVÚ¿ÏJj£°ÑÿÇaXM/»2¿–0,`_¡zà 1L‘áÄYnXvjZ”º„æò¨èÅSŸ•=T"Ƚ%h;ýûIRFˆ¥d0Ã|xLZýµ@ðWçiŒtyjóêB‚€.yÅwœļÅü^%`Ù$B–+&:í×Ã0Sú&,ÊpûÈB`,Dê6*6¯¦+ªY;ou {‚í;"*µìYˆ»{ðFæO S w\|÷ ©š« SNè&`g´ÏDÖyŸ»¦ÓYBµ a–“—ÍwVPc|¥ ñö¯\ïÃkžHO^•öù&(XPücÙ²ÀZwUï,G½C¬(à¼÷wkDK$Ðñ<-E€Ú’ón93‹Æ¨ àZL± :½þ)0YìE’C:ï™÷¡ñÝûVÃ÷Yß<æ• †Ä û@áúO˜›˜3Rcí;º6Ç#T5!õ,˜c $mVÊH“BNŽÎzyúW¢R¸tã±D¦uC*⩸nä#QIŒ`Ÿõ|í®«–aUMmµû–„ë7% jã…û-mh`ÊmNPùå·kÒ Øˆ–åW¢kšãÙôWËxÙï_þ€‰± Eš-ýø%ÍT&Äf8W¶âÆýÍ fT äöàÀ®]J ãUg:jzì„?[:[ûÕúœ%âBp3Š/,Ðd(ÚÿnOºÎä"ÿ…9g¾áª¼ÀÒŠíàܰa û¾ÙeêWˆ\%q÷Øæ ±²ÑŸ_0¬‡Aó•4Ø2®¸Óì½…ÏÛ©ÎÆ…J¶z¼Z1Eš|™/Ó÷X©i©Lâ%ñi*× Õ4Â}? ’;-°Ùð.kj1+lÊ„cÂhÝ´òaOé=ÃÀÒÖTè(ws‰w)-CïZ[9tñˆDg¦Û&~wðS€Š=˜¾Nû»ËŠ´ÆÍìþôJ1_ÅÀ9]â¿ðüëŒQËß°”TVìÒyoÓ+×'ªîuo#ëÙ†#dQLå[#ûÀ”íœQKùû£¨Tvp*ÕíθjY´72†¹´ÏÝ˶Z¸ã ¡l”—X'9ŒlRâ×FkRb6ñµ” ž0~j¼(£6wƒØqÛõ(qxTùÅvÉDƒú€˜òwKÚ)Né±o>Èöá‚ÀƹkìZÁÁ©~°TO$•ðÕ¯K‡—c͇qg<¤Ét<Εó\=2õ<ÑÅöUu®ÿ>fé:Cë0u@îä…©¼¦ƒªðäà.o—d“@ú’K´ÿêW«}Á»6BO’u!`ôÈSù[19írN Hà¡õÏQû·ðë6^?f‡®3ç£:®¥ýŽ ŽK‘áÛ›‘ûMq†d2žX7¨^¡èRðÃ&8njZ&ËØDŽqòJNyt1­&ñ­T­¹W#÷1š¸â¡ê{ýñ<°åâ}:HÇãE<[»a–:ˆÈW„#Ü×<ÕÌäÅ<Ήìîfsžd¾×Ù[@ì'·í>KD'ÛãH‹={qöø6ÈC zî­Ë¹FHÏfû¶‰@d½9›‡PµTUür‚·‡}ƒ*4¿Ù\Œ™_Ä‹]¯ 2äžüj€^?qö¨ø-»áÖ†¦ÒÌ[yº‚“ÛîðÇЊ‡-¢†ª—x]Î8õ`ï.T[ãÂhFÁ Ý“å¦)ÃLÛÃe™-Ŧ¶é¡ÎÅ­ÍÙÜ®FUþ~Q;µp¸ËßœtT'ròVäN?Ñ,kIV()*äéN[SÍíœÊE5J¤Ú$rÙpÍ:#dàQT¥ñgh‚ašÔ ©¤sàö Æ@þ‡…Õ÷ºúá-ظ :\]æ&$½£¸$Žõ%Gšq«¢H9S"õê³0Ü&pÊ.—áÿ7ÖE•¬hÇö™÷$²¨Ujè–¼eO‹+üÆf<'Y4¿3Àb‘¼ Ë´lÊ›øÎ0•‰DìçÏæµäèqÔ‚Ï»½C§èòÚ¦OU¾UÑÆDÒ`Ǥ  'º1¯©¹$žíùBGa¾ÚQO¿c“û4ÛCç;stÞY͆ùü£c­Bšö—Äâ:2ŠòdAº8ŸÄ¼}CzàÖf¸¸Õ¥z ºé¼šËŠr}QÒÞõE¤".ÛëZ* ½+ÅFCÔcæ·Ô”Û é÷KŒ-IƒŸ2q›Š3vÖ ò‚nzm=Ë[Õÿ;JgÕxÜ`©ðµ2¾Øàá36“euÀ÷ËôzÖXûC²Þ#¥’¥\ïrá΃°£Q×Fùÿ7bÎÞ~¿Í¦} ¸ÉÄ| ­“<ôÁ²Äû=çs¥1ÂØˆ ‚áAÞú6oÆÈx3Фåg[ƒzÒÝlO=i$§N€ÆØÅvLå”~lïÙÃ&ë­sKûñ˜²´¾³Ñ×rEù¤»™\&­ÎR2…Ÿ)b?ö9K™ôÇ9ŠoØã/#ÚG‘î<ës=æ€Ï„¶í>¶^#øpÓ”x´h}C zÀÑA Ë葇Þ?Cí´xq»·ï¢Mç–º“â§GÊRüRï¬|¼w3Mº#¨]×(ï*s¸W.;ð2gfÖGfÃÒ$mÆöŒ¾ŒÎPVcXæ}K;<†—‹Nk›ip2Œ3L6ö]=²\Q”AŽÊ”Œ´ÏK6rv½Š‚+"7»il¼¥tÐϾP´PË箄Ð<°Iê8›¡mQÿBÎf¬ìV×`x[Ls?o°CÜÀ§Ê†hFœ Qò /hù EŠ¥»‚3&ïªëh¬Â¶ÞîùcpIp0NÃ2X0bdæ­¥“¬Ïº2gÅ9ŒÉêÅÒÆÀ<ì¾\‰³éúß óº§u? ‘ꈩÞa­içÐneFà˜ãº77˜‡COÿ„ÇðˆþKLÚœi®œ,rú}‘# ï qЬe)Ñ®LÓB±n¢0 ÷%—¡†Õ@öÓB2\ÀžW,öÝÇ´@˜nß[ÞöŒ®#ÔÄ=Z€.C\ ÚT³ß`8YUÙNPí?_¹ÇÍ7×áR&²½l«^J‰tLά@ …­;®#X'þ]E+KD]ÐwEà9N%‘¾4ó.%V¥|Ú8ó²¡(÷|~ ´Žpc×t‰EÚjoõ!ìïØ§ T8c¿;GÕe±ô*Ñ¡V2:Ø#X_ðl“-öYÀÂæ—ð{‘FXÓyžŽ·[¬„ËŒ¸Ât%íMýZÍ6=‚GêD%ÿF…¶© €Ís/1K'ðß¶«&~ˆ¦$ÓpHÐÿ Ù¬¿f€²4Šnx^•Õ#r§ ñ{)»5Ïá-Ö†":”ïÓO­*­huñÛbÔnèæL(u‘}d o!h¶…+„§%Õ+# ‰ÌpÓ]ÊÁì|, "Á©ˆGÿÕÁ²Ú…!ìÛÁKÒÄ-B~°ûãXžóïËF“àÑ»_¦:ûŠ[“…Yì#R`2#ɳzœ‚¸”W4¡5n‹`À/cÛo ìʬ•Ê£µë`—šÁ_’# °\´öÝj•-§}ÒÐß6]Ð#ÔÈÚ‹rþšH÷9+w –½£t(0iŽ!Èj¤Zþ€À¯ÿ-•]‘¡=¦5¿ÈDÏšì„:íD‡Ô·wlW×]0#µžö“ìqãîG±/ÖØÈ@bM ü z¶Mþ"¥Wd ‹`œ]្,Rœö« †“Âû$¢O= Ò.«²í4s×Û£a ÷˜r=;½A…Û3_£»JN|lcÿuÏÐ.iÈùO¸Òä%•ÇáO(Àj‡ED¨³²øê‡šGí:X¨6á­Øÿ*úh,eÄB3K¾Ö­ÁöCp‹_£ÇRe_ÆŸÈí S ÝÝ|yƵÛè mö[¹Ü4²5Aÿ˜WŒ¿1‚~6Õ&½bξO‘z¬ :Þa4X¿r•<Ä9Ê]'2úá€ÛDŠÐ üšRn1¤ÌžR¯(”ó"÷ ßcßlÝô¡%‹xÃñ†ƒ?Ÿu!ßÙ¯Jô(ëá&‚A•äîÖËé0ÃØ{ÎS¥l¡2i·Ë+pM±tO“)–@ÄG·ø3jÿO;w¢Švj.WÒúžÐ°!ýõvÒ þ)èœ$K#°ÿBÁ8Œ5„$=Ã{Ûõ½xŽZü7qMŽØÿ=ë:Ÿ ­&M p$ËèÝÊÃ:“÷2•,Ã2z¾”/¨cNxüëëôÝ)øéË ˆ»À ]o¥w!xÁtÀ ƒZp燕fÌÎU#AõZï& ¹‡'†/H±fôÜ5.ab‘5‰L.'èct‹mDÌ,JU݈$ÀŽóv@„S`ͦÌtéö~ÞÀ@}kÂÝ?εÓô­³C+zkˆaGRÒhÍ0ßÏï»Ó<êm±”20¥TG`áC"f>æJ0‰¡{RpOÙiò$"ˆ•Î[ø@ÇUqeé‹xj™Œ5Ü£‚Y‡?ãVü“Ħո{J£StájÓ h]uPyþ±Ò…øÅXÄÿ…&Ìú­l¡„!Cš¥Ê?¨oEÞŸ°'ÇÌÞ€ ㆡ#ô´3t+ô§¦£%WéöDp  ‘bŒ-nWD%wé›u€Êßðïõ‘zc`ið6‡ÊÒ…þ¸f‹:qEQïi¶l.÷4T‡¥D%“$°Ôn6¸sç)ÏÞÔdLšãO¶0DnCC=Áò´„æ|*ü,–É¥'!ݾ6æÜs ž#üSwâZ†ãW†áwïƒH$™«Íe¨ý$i*±:Ÿ!ƒÉ°8ª÷kÅW“ Ïâ‰Ã0±\ì|ø¾ V$å#èá€ó'äÅN…ºÀÁîÜìv~ž²l±ÛsC F™¿+Ï)ßߣŒÖÛÿcyÌþOõÿͬRZ".q„‹Lmwד5]pû¶ýï‰è,D±··ŸSzHkµ”” US¾oú,~3)âG³r ²sì·±¾&Øé®H?nãÝW«U•¬Üm‡Æåš?q ÍÜRY% /…1 .$¹¤rqºœ4G¸·ÀÎDQPü¯×aæOšuJ4g*ÆKÄ™ÀU‹P`¤ $X5QÖ1…cÆx• ¨vÇÅêÀu„S7”V¬7-m‡ˆl¯×Xcó¦äžt\O)Î"GÇw—Ð}Œ®zRÊa8ƒˆa{~—¨ãȽ}¯€#àB@W±œŒÙƒ ÈÁ µ\8øoµùË`¢²·Óçéâ…ŒÊiâðÜ}.“ ÚVžcF°!â-:@"zs™ëÎnñ!‹Ñ/tLÓ¤FìÌh_wœ%D½j»(šÌýˆ|ÝÇ“±ÕM™ÒË]»`ý/«oo€“ÓOc‹XymÇjeð†˜š ÿ!Õ I(VÔùÚA€¨©[¹(ú±KMn¸ÁÊ›f‚z§ï#wp×ߌÉgIN+Ëð•:CH±Ä®Âß×0@Á€ËAu® ÜeJÑ=ñy_æ³Ùh@ÛËðÎsu¢à5;òtQÏÍ)¡¡Ë|À¯‰q…‚œ-x ùÑoþ‹ŽÀ4:¥ýIì--È‘§Y³DܱӀÿ¡,æG½{wÄùœ”—Ì&3äÁE$c^•ÕƒØ}¶{ ,Òj·±…Ï­ ëà»WÃq±ÊóÉV(¤;踯֮ïI…?%À ÛÕ€Ñ]È´ƒàܬóÖM$…v€»ký]UÈê’öƒi‹È)N„´NÒRåîãÌlŒe¸ê[>ÖÌV°å ÙßrÎ ¿K ÏÙ†t;h>z:‹ð›ýÚ<N’%¡~-@›9È endstream endobj 315 0 obj << /Length1 1841 /Length2 11300 /Length3 0 /Length 12451 /Filter /FlateDecode >> stream xÚ¶PÚ-ŠÜÝ‚ëàîîNnƒ3Àà®ÁàîÜ-¸%‚»[x¹'çÞÿ«Þ«©bfu¯–µw÷.h(Õ4YÄ-Í@2Ž`WvV @RYƒr²È44Z6®ö ¿ÍÈ4: ˆ‹#Xà_IÈÔõÅ&eêúÂSvÜììœvv^ Àòÿ‡èH™ºÛX”Y Ž` 2¤£“ÄÆÊÚõ¥Ì~èÍìüü¼Ì†Ä@sS0@ÙÔÕäðRÑÜÔ éhnrõú¯ôBÖ®®Nll¬¦.¬Ž+f€‡«5@䂸ƒ,¨˜:€þRÆŠLв¶qùË®éhéêa ^ ö6æ °ËK„ؼhÊ+T@à¿ÈJ˜Ÿ €•ýŸtGÿ‘Èüg°©¹¹£ƒ“)ØËl°´±Te”X]=]™¦`‹?ˆ¦ö.Ž/ñ¦î¦6ö¦f/„?;7Ȉ«L_þ-ÏÅbãäêÂêbcÿ‡D¶?Ò¼œ²4ØBÒÑÁvuAþ£?)Èü娽ØþºY;°£Øço`i¶°üC„…››6ØÆÙ $/õ7åÅ„üÛfrp@^~.Èò4·fû#½–—èO'ûæ~>NŽNË ?KÐ˲‹©;à qùùüÛñß™`acî 0YÙ€‘g1ƒ,ÿÂ/—±ñè_füãóÏ/×ñ²pÛ{ý¦ÿy¿l’2šÚÒjL)þÇ'!áè ðaáä°pp³øùø¼Ü@€ßgùGÿ´ÿiU3µù»7àï„ò`KGÿ_^Îî?2Üÿž ú¿7†ðßT_F ÿ=ù@n ùËöÿçùÿ3äÿoìÿÈò›üÿmHÆÍÞþO7ýŸþÿÛÔÁÆÞëoÂË$»¹¾l…²ãËn€ÿ—úô×&+ƒ,lÜþ×+ïjú²â`+ûŽÑÆEÆÆd¡fãjný×ýç^ÒÛÛ€AjŽ.6¼5v ð|/ûfn÷òž¸¼ÜÕŸ.ÐË:ýwIi°¹£Å{ÇÁÍ0…@L½/ãÅÁÍ ðaYP 矓 `c;º¾„^äù,!ÈÜ(7€MüÓŸˆ—À&÷ñØ”~#^›òoÄ`Sýñljÿ þ¦é?ˆý…ijþr¤¿ý|6³ßèÅoþââzA/»þ¯ø—]`ûÌÍ `³´qýËÿb±ú _’[ALÿ‹ð’Óú_ðE²Í¿àK·vÿ‚/ñö¿!û‹2ð¿àK/Ž¿›}iýå¹ÿ—û¥ä_ð¥’Ë¿àËyºþò’ÙÕÃñ_î—FÜþ_qÿ|©åñr¼4âõ»‘®7òW²ÿšs7äåÝüsƒ_†ç?øÏGò™#/Í;š †Ú6„vý¬'ñ`Ùû"z›qwsÞk´8\z‰¨‰ôÉ`¯±Ç§h}$¾¥*,ø”—l@ÆÓæð»'¶Þ³Û£÷ÞSÑø 9¼0¢¥™ '"dƒÅ•ŽÙèKr(£LBàÊ9[UØð”¿àm7saVM²yVµçmäÖ@áßë»Ïkôþ†H× Ë®a—ÒHà'ƒÎk¤E(Ú³ùK°n0b¾öi ·¹ÝDš¬½;pÛ*»Á#èpM‹rlÕsT~ö\Á{:Âýp‡Ñ÷ìÊ<Ëq¸gÂÅÂÈ:…¦¹9Xø[]GJž I4~c™Û ; ‹×Vçóec#É!ÆÇݵ„oM¸áË~ÝZÇßRˆˆ{¢+¼|SÝ9ññòÔ°ˆ(ÄZi¥)ªbÿG/W5Aét¦ Ž›Äˆ¿i÷I L±ƒÞ÷‡ rpè³Ï@$`9<°r^šyƒ(÷Á¹ †@¤Ûh”æy”Ú >ôD§;pxpø.²Ë†uLÈKoLíÚµ n§_ä¹~qÕ逜=HS§Ú/~D ´w½ÒôÒh=¸à ä€0Çáq2ž—z†÷Ί{Ø68uô ù.„”„_6Ø:0Æòär–AˆSsŠíEOŒÂÔ<¹3côu É»!:ö|— K#)÷¢–˜\ÌlVÙÁ&Mp—§Þéâ$|ÖÍèdå+ †°¡±Ö˜îj3Ö¯…Øå_«﹬wŽÊÜZ¹Õ ìœà›mÚ®0¹"„ý|NN*8{@ËsP«bð¤»ß‰§åàñ1q²œ·Æˆ$¸ü…‰k÷huN¦\5iЩ‚øáýœ¼^T'³|šÀs:KôÜÄɦô“"j_Æaïj¿¨z:-~Ì Þà,CÚS1q¤ƒú ?ÏÖ¢ø€¥7à’jLV4Þ”ï°Dìë£\Ë3Ø”û)M"-ž×Vþ–1ˆ J]õÖt®NI<1À ˆ/¯þžèRh]!íÁÝWè„qVviWÌ5ÖY7,Fdk,ÞIž š¦Žž\÷Ê=åÓ>¯{?´}•x­ârM 4O Ö«ÔTÃä>L¦ÌûÍzûÄ+c¼KºT¢£¯œ«&vŒZ¨-ô5†¹<Ü‹,ú}ôÒÕÇâ ”œ.ð FñÂï«Eã¨ðzO•£Ò.M*S1Mæ_+ÏYYWîDPÃû#f.²EÔ{ÂiÛIRG¨JÕzRA|$#³±KĨ ›ß=o&Á‹‘‘NÞÁµm¦FÀBåõiZpÑ{¥’}S ÏüÊw¿,(»5P ßgDd63žç#õìòïçhÖ IYàØ-'™Q×Ý뜄U¹¦rùYsƒ×åT" ƒrÕò%̪­ˆYJ©‰Û²$·wXíl\VËF9( Æüf5Q«F“í ø`ñ½'µ×3VüÑüh(ýSÇdA᯷kô¡Œ¹?c-L" Å•ïÕÌBcÂXÀʼnᇵ®pI†¯›K"‡í­hÇf@åiÕßR͸-p¦U¥‘¸Ðêµµ¬ï‰ÖìÝ{ø;IŒ ïf‰Æ©$³2‡È0™ÆéÛ”ãæº–Õt¢“T >¸šKštÌåo³âkø¸?¼§¢;LŠ`WÈDa@%®Åy?#ü ,*í·eêŒUeP{÷Žá³1×ÙG?Å·µLÍó"Fæë:Ñ<ÃØ@i½aWæÑG\"†67° €*EcõL7«”ĆO‚û‰q84ÍsÜ-FÑ'ý#¥ö,Ò‘¢Æ•¿^96j/õ𢼭ÁûYPh÷z³ÆC´Ïi`«éy"yàq˵9Ÿl¥—Ò˜Ð53hið)ùeš´Ãœ<-vaÈ´Ø’Ø%¹‚áÝ~ Æò;jk×ô(žÇ2ÓÎ-’PÔW'¬î~-dW’¨«šÄ~­°ÛÝ|Ö{ù4pÞFæD@Ä›àB}Ñ}§€•¨È«§$EeZ”re¹/Ï^N*:kë:@7Æ'ÀF#Ÿ+[·Œˆõ©™'jŽ(<M(„© ¡rø™í™»hôY8¢) ¶“¿gÏ{@þ#%\ép  $«Ò£«â$™Ê… íbh&h•MË¢$psˆ÷a¹fÜ Çt1õ†ÀÎWvÏ»‘÷£»&‰:½)ç´ÒÒ0yA¢-昄èó?qQ%WÒF2xyXLF–¨áj«•Ý7¿“}Ç÷m|Gë2óµ†G—rÐê5Øb2\?Ùk74Lj±—æ8ëHq[füîø½#úŽÐZg%LD=éZ y¸§r‚|r÷Uµ>µ…”Öw½yÌ;ÔéÛÁÖÍàd_UÖi~3M˜—! Dï„­ùÌÑ&ÊæL«3˜âù_¸<嘛+fˆætŠö‹•Ä7ÄìèâT`ÝÂñsöfèN®wàÄ E²>UI|ñŠ-a~+ná“7FžãôðžAMƒÏ˹Òäu}Ë®|˜~*yWóòqRŸBß'¥GöTe–PôP%ŽÁ¬ÃRúA·Èàö õ&.IkápŒ:hØ!•öC8Mñ#GC”ä–ÛI#ßà;£4³ißàùèÌCÕ ¬?£U¢o–5³¥e¼1GBÛcO^äÎóJäk$aCí˜GÐ騩-»Z*k¸ ÎÁd4’ñ#¦x-ŠªF²×È‚ðëÔ?•ØaÀßöì}vÒ+wRaE¤âÙ"+&¢ÝÛ›á¸+½à¨<œX²Èˆyß}l~ZÄìî!ôuK/ÆVK z—?¸• Ä©Ž½w¦ÓMJ¨Ÿ¨ªá*#ø%²';8‰Râ u_k«ö¹–ÙöÍAÐ{|å7Þ&g´ãΟ¶öÈaQ™œy”«gDü¤Ð#âX¤CL·A>ÊnjâFs¸ò;míŒ_ªŸýýVÊ1Ú°~Zˆ„F¿ú„>žz‡FaÕñÚ^û—£{ÉcTV#•:·ð u¹6´›P+ž†lÚͧ¦Õñpw‡õÝFšë»Î¼Æi\ÃÂj’~¡¿V9VGfí¯qqh†aPAõ²¼ Ið%ò©?cºê–}l‰7HQD§Y¹ JÍm_ޏd™¯‚±ó `¼@NkYÛ„ð[»”Ìñ%e:ñè² IÒŽ e#¿{Ã0 % ·6zôÑ!ZÀœ¬#ÆéìGÍX /î7IÏaÇž•˜@E1±ô˜#Üô[ËÚÁݵ»Žõºâ~›yHï| i!ŽgÔÔW oô ßçÖ“ÐÀúðÑBn;ÿ9§î)'ª*AÛó:q¸ûj¤/&š-oáÐëY§=T6 %ëíö¼pªü×Ýä^Òó¡Oªð6Ü16Øä ÈQ¬¿%•-‰}“d8É’cC4=äÀN~RõÀÄû£+¯ë]SËâÀòlqNQé›8V Ì< tè ø½ 4xóIm_Õ‹r¦vm2ê&È”ðRxdB 8á±é€Ûd<¥ˆys‹möÌ"È-JÌÿiñ CD=[eAVÏ1äÃÆmv¢UZ˜“°OØŒ1ÆhpVnB„þs“Û›î™oß,­ñ¦yåZKÆ¢Pž~<Äqóƒše#¡´l î wÆ=eŒÅøˆ»ËTö`ÂRT›pÑÝÂ` ËwùD9Gd¥0ˆ6>»r¯›¸¬QèßAç“X ùw!ó}d™[øþ®{Wì'½ßqá¯È}|­l-å´ìPµêú`“S§ÙˆïŸ'º¬ìOÔÈS<¦Ì$äÏB?„\’øU2—úÆ7ìååÈò×\r„O]@uãÛãp7Åì _*+cêz*”ô3Zc]Í­®Åýì,ÝË%ùÖ>à„†¡¡ñk9é‰Åa…ŒÖ…æÛð:µVq´¤«+U5ò6;õ¢µâ[ˆ0hö=[‹.ë;¼s}}ìY”d†óØuôn¼Èj]}%¿í¦"!‡Aw ÝxG0¤ó¦/†R—g”©ÛyÉàçòÓk"'ó„~ÅŸ=ò¤ػ범1ˆpë¹EpPç2R$‹æaPL y¡•ÏD»Ñë IC·“?Þƒ˜i'ÞÓ÷uü‚×IòC~‘Rv‰‚D;ðúë:KÃÿ®Èá™G0$®É]m›G¶ö×Ξ! Fƒ¥!M¼ªkP@|ûÞ¡½e—¸âv¶ÈØ|Þ»­f ¿±ãÉÖ†gøŠË7¸´å ð¯ï¾,ÖeÆÌ?0P%pìÛgTHäx»ÃšJŽš3} šŠém‚g ùt×\³§Llï »-X0˜}Bp¦X¹Œ»tèÐA®`.ÑÒïºD(Zš7 =¥‚Ä-\jý"Ì”ÏzèjÜ<ÍLXگư|ùµ,Â8ƒµÅõæÓu> ©¶KLKùT°D$É% /&ŒØy9?£ÙÔDuÜ×y'Ò"¾`}ë ç!1ìÌ@õÖw¶KßieûV“’ÍZÔ Až}å{ß¡¼+ÿ‹ÀÛ··Jýzû zÇ®¥g„Ù +â {iŒcäÖ¶¾ùP¦À˜§+‹åF]{Üx)]7 ÜÂ\Y”vr3eP5Ú^$#haáç†ÆŠ®'_»ø·4i°&vŠ^B¾WšôÌFPV?lF‰íä/-~vÂSµä2HmËÒ•¡–ïà”0Ã{ór”æp]B2ì%˜z8dÚ.ë.ëi0öh6–ù[ìàÜO ñ¢y™œE»&63ƒëo îòk·ûc0­(°êØëØ—9ÐRõ³ß/ì~º¤Z‹´dš¼KÌ3­P«£÷·¥Q« kÁ@n–}cŸ¢4% “‘¾Û|vWz·–XAÛeív EÛM.F;KsÇon †J%KOµŽ:´]y÷xݶu ?ÖÛ‡›2 åýŽ4&/‰*y7¤ w¹-¤Rg[.*#éz™¨9–]v9ïVÎ3jû-FסVÃÄtÕ´KË€“f BUŸdcC¾³r0,?¿'ÈÁPcÆÇ[²6¼CÔKµCsžuŸiSëµÉ/ªE@Ò°]b¶‡x–È-iˆQÃÚ7" ï)aK¬ÈÃT†ŸV¶âkÉtžáfjBµ;%FÓqÌ3”îs{‹( ”‰õŒB5õlš 0£ý0ÂÊãü~ºdú+œ[÷âL*!GTÛîP2䉒ڋ­‚­ê®O$;9ú5Qz•ØX¶Ã™M¾oaÕ¹(F÷%…ðô@“‹?w÷î¥b>›Ó$`=.7|»ÓãH< pï…¥ÃÕ<#_3yâÔÕ?KŸwË7ÃõU‰²’ç6Ú¦J`¿ò?Œ q->Ëûi+Oۜф2a$ÞìF¬~·ffý¤$r‘!—3nîÂAõÕÚŸ¤\²3„thì=AŒÊçâqµŸ8do0.Æ´P×ÝS`Ë]cÇC*•|³MKðå¸ð·ŒÆú1rïZ?(²¾OÕ" å‡B4£‘u 6ßĹg„S!À¶½ÖxDN¡b-¶òÞ™þ~º‚‚¸ššÄ†æ×9òNfþ r=uúÀüû­$%L;²ª“tþIG· ó”Ñí<´8ì qŸô°­3ø2f¢qRmÍí7¬")DÜ~f_sÊ,Èߪ‹¬š›@P>sX5|ÔòÜ—W)¬YˆÐÉ "Îpë¸ÁxQ$]4’&6>ùnxr²_X›Ôð ëv?)ÖÆáš81¾› ˜ Ò'¬Y­Æê¡i³¡bŠ=Ó…¡NïKP³nž7¡S“¶ÍXSL'l¥"k“Jë“ߎùjþˆ–Gzcë5µ@«yN&¡N/D%•AÚÙvtÎ5¼zÜP«ä³ú­±ÙH´ó9t5S†%ô‡p(ÖʾT£7ᎃI0æšÞ ïÒ<ÖTJöV²#ý Œ>ðÕU_°\T}U+~",*œD#}uh‰Ò»ˆW¡~‡‘Ï\²ì2ˆe/†ýÝ#;8+ÿ.;G¬øbÌ,Þ‚6ÜÉ#ÿïh­ÈãiNÄ3uÔ:[jëÑB|š~s¨­ŒU`NÚ,ë!¼]00ý6í@KN©4ÒÑlëɢݕLð8) ›DÖçÕZR–¨a>÷ ¢ý üle¨ 4va©r™vGe§3ê8ÒZ£Çe¹þŠÜVéâ}úÚN¸ç|¦&Š• §Ã9²zøˆ'ߺ„;l'JÔ$ Ê~¡£ k¿ˆb„ç Ž"þØjÝÀY%9–ÀõH¶á6X÷Ñ>‹>ºŒ„9à#²UC*güò#¼Oú|ËlÌÕàþX=­p¾ŠÚÀÓÞåç‘Uì2ÔÑKøeƒÁ ÍVZdÉ…‘ˆ_ÀÅ‘ÔmˆÊD0+ZÕÀÃVçôøåmÞØ¹É<ã<Ч.èɇ·]Oe¸3nF´ç¿ª] ̉oCCÊU7ðŸöì ¡‡šq±¹v¸|Ò³s–—ƒ¼•gºö>êe‡hPN·/õ–£PRIë• vÃÛ«Á‰Í2ÖLyVÆ•Ô0PÌ>-ûá6¼ŠÍÁÙ•-Aûqs,›¨Á‚•;Þ¡j¤9VLneBڞȵŸ˜}-22‡1t:ö¸$Șh <¯  åy UóÞcªËÌÚñ—‘ÎÈ<…Qr s&0 ±=6Õb¿8øAî¼öX·ÕfïËÆÑŸðç~µdFÃÚ¿ÁhÈ”v-ƒ™{wçýX(ç_õ«K‚þ{½Pô9žxÓ¾ü ™Û"€óroH´Éû.±?­m÷”Æ^Ó×àËŸéoo1NÿI¦bŸ˜õ$KK¢Ùk©ÞrV¢Å¢1h$âbíªÒ‡ÿcÊüÖ[A¶nù æ×Ëz›‚`ƒ‰«5½û²œÐø³?övˆ‘ôO|uX&Æ{Ý‘ÍaFÝ‘³Fm†Gsªâ[HÞ#*”Ô…êʃ”¢n*`„æBE‡–K/~,Ñ‘lÏÔ(Š7&Ê_o}.‰g­ªºì1œï²ÿÌt¹?~Ì)ñ–8ÅpÙ[ù@´43s+1¡Ùn*}Pƒ> bᎇ#=Ö^KÝù: Cî³ã÷j¸J3„OƒXiNsá”ùˆóàOÖ­>TxZ+:2¿ó42èr'3¢š´ö»…¶KÏÙγM ìúþáGÉG¾¥Ãª©H“RYøŒ£WÜZ™92²‡7v+[oáQåTSI—2IØï‘…+ðYUÙ˜z7}˜œ3ÈΟ>b'€äƒ,“:ªÚG’8ù K œ”Ã0#£sµÂáÓuoîÒ[O×zP­É Û¯¤Ä¯µ mr¸] 5d?sãv|7ü•+‹Ú3þ°¡ˆZ¬©¤#>Ò¡­Mo Æ6¥Å®P1¹ T_†)À´º-d„+@è)ó@dÉGk·ÖûöÊÏN°r+ߊG=ФŠßÊzb\ZÃHX¼úè™À`§aŒ@ËåØL¾PcÿÉ87ª€BKµú.‚#R꜓â'´§w•Uˆ¨3ú½õæs ýLýZÓÀ×çdà¶·=¹©ñÄ›ÞOñÁϤ±ýeÁ›Ý¯Ì%”θae“ùúµÊ#AWõ¸öøù.%»û®è[aýϹÇl§¹,b ê[—ÂH©Fõt¨•öd:Ô<¼n‡Ùðy®¥ã ž¥{­oJ4ŠVzú÷‹4}ݲM°9Ÿ’³,pw1Å:pø*ïD® £nšû×¾ëÞh²ñ²[/ôÝkPBMŒ¨1ÝË‹ˆ[JKŠiíælÈ©úT}•ÔbèÅ9(ÜÔ´r˜yK·®-õJ*Û'&ý^8ñ];ûë¸_£doD)õòm¤nQà¤AÙ³ŒøQ{ce=‰wtèó§QgSaÎg#ù‹Ï4Q\Br?õcë*›uÅ¢ç ¬êç;X®WÌóÝ ¶_ ÑHlqŸ:2.“¤ÄÜ €eÄqŸ›c¶ÀD{†áÌDgb{Ù¡ á›èžI¹°Rœ-žvÊÁžÞîãc^ÖI½_.|(ב9<Œ8ùXhlË”Yb<Û•BL+^¡ê9h¸œÁqäÌ*øcÕ:q&pq6;Þ¥†Ë z„4 “‘²!€€;zÁR›U,¾ª¢Ã¤ž‘ñj"'Ç9d$ ‚uV;;Ç%pÁiqâ—ßÞv%~ß0£xØþÐu´ÄP@eM+èàä›m póMSá1âI9ìW³Q=† N%Ÿ•Õ(*Äå7ÅøÙ¾ç¾Ðâ®aG'6+/èli”zOÏù¶¡³´ÅÕèƒJ};ÓÝVudŠƇ=Òbb[c))…‰k)'²IÉØ×óðþè»plä¶#¨¸÷¼Ÿßš¯²Yö½Qóa ×Ê.)%¢YNç„+~`ZÒy%ñxaÜi¿ÞGô&-°)ZÊ}Ç$3¸[pâåµÍÑÛb®T?Î7Pòé~yé׆îHÒiãóígt¶}£{W.Çü|‘™1Cr±—È w…ïƒÐŸ"G_ÕãMºà1¼#ð¢ LkW*À½¦©‹“¿ºMzB²;%cxJóáB4}“šb£1ÉŠy ­îqNi'Oì”ʇæÒä·‰©&œ~øáÀsá¦Â.ëÉþ€›³,+¹âÿlÅ\•ËÜ]?Jtß%ò¦šáë wTÿ´;Îü\Þ|HoE5[‹jx›¡žA±y]×\c«v"„-‚:lâ¨þu)­ôš0ß¹S7!Ïdtƒ®hTüM`ÓÝÆ E‰p„”Âóœm~7Õ¼ä“Ë'®õïèï0QòTPÜé±S0È oFvæ¡3re0é ÷Ÿæü*sY$ ЮV?;Þ¬W¬Ûof¶GÛ¯+:Wõ°çÏûA=sb€‘´k¶õwS<˜ßõ’jSQª6µÐ5R_úén–»ÂBÑÁs~‹Üò½”?.^ꬿÕÍ&“û™uIžõG4ETÝz§¬2?$Frz¶É>ÏFH¯_—DG™iOGîuežzÙÌ®(R8¶ª¸š˜è4˜mNð•Ãë7Û⡉$ì~ñ¬¨ZÚSÖЯ´Û+¾Ì™LÌŸ^.à[`õýÀ8)kŒû¡_ŠIŽ·…Kà#Ã*:lw6ŠZÕqK3œßÍínÜÛy1Ÿ‡#Qè»~`i|¬VAvP×G6þÙ0ŽÃldùšƒ¿*PÄRn’  _â9œųK¦ {Ä€b¼¯ÓŽuZʱê׳«B$õ4 Ý(šCè(ɲwö1ž\²cûÅÑÛçزŠpZ.0x`†bÍV:Iˆð[Ô¶ð¤+µò¨ö¹êÉ™òpº`n—K÷xœÊRy,’±i )U¤Ï“²¯î²º÷â\¹ #Zéqýûo*¬»Ê»>S9.?Që? N«mÔÜÓÀIÆ:¥˜ø7ŽboE:-æ¼ÀýœÒ¡K dÖhÁ(÷šÔ­fY›Ô®‹‚úë0Ôî_ÅTC/{錄BA‡påŽQûÆÊ\…?ƒ)™=G‰k¶….u2¬ÄýÙ:šõ­H7ÞÊËzufIBdîËóu}BµôÈ™¢2Eeü¸‡¤Ç·Ï™Ù['_'{Zb|Õd"²l}²‹xdÇq!>YNöüŠêǦÍRYø åè¿7z&.4ÖJÙÚ‚‡UˆŒÚ¦­ÞªŸÏ'ü°ÿ0¼Þ'ïßÔ‹ÔŸ]N¥³²yâ[ȯWbÆÚ£fn"ý°°}×2µ«¿~Ô€1ÌÊÛiä!€¾ÃŽBŸtµÐøyµYI­Ã˜à÷á²á€ ÷y$ÑÄÑÇ6cz¤ŒñØTÏÀýY†A>Úª á•fk|}(D<ƒMò­›3Íu«¼ÃÖéí«ýÁùì­£J3uã†C7öáÂTŸa¬­|ÛKŽñôgKDçÝ“EŠ›jÇõi•·OÑÒïŠÃ8+#×´r0Pš×éÆzÎúCs /Ô¾5%XZ§u*ÖíŒöÅ̤{ž_œ.„ŒË§×ÆøI¨ Èã2²Š¶~Ç“0:à¶Ë…60á:zʱ&¼ã:І1Ÿ¿áã«‚uúÅ[1GÈ%`uɘn”Ð2ûž^7;_U¿òZ=ɇá̾ˆIè›ÚkpƲæw X{åJñœV¯¸Õeœ2ÌLéᆴuog?Ç…¯³cËÍð‡=¥=_Â8k5T™ ÷JåÙ‹á?¹ùÂÐF“»äèŠÑ<ááÎ7N¹sŸÃ¾—ÄÂÁ¸À\ùð†sÊuÉ”¢\^«f±ã]V#è oÊÇ|Òÿ¬h‰¨ëiæ8Õìל—K˜¹«/¸>¥À‹‚,j•‹©ŒlebóU•ÞÌij©:¦Ä§!LjtlU‡¢¾V]kÝp.¾è³x‡×ضymA2"IŸ,Âíö“ÑæÀY&çŒU\gä]j@åqjñc>ýE,jRåkíUF[ªÅÅYù¥M˜Q¤¦sz+ïexZõÈ.DE-s—zkz(´ iÝ9Ð6-‡.ùOp:kÿ gýt5rÉkfh_ÓEº¤¶à/!ŒØ”¥maÙyïÏaÙ£y»SÇÄsÅ-ã!õœ¥Ü¤æt‹Œ—c_¾"0Çn¥ÇÌ»nó€V§ZO Nµ÷µylˆKaEògábœ(]4±T\WÊ¿cÈz-ðq£Ý÷7‚}äM<Ô7!ÿMeX@ìl‚ƪØá¼)øp©D…oÊ;’q‡y$€|{E¥Nú8ŽÊ•ÊöÙüCÿn‰PöÔ,/á“Å÷LŽw©é·iV°ªGT‰N¨®R&Hìð;cñRêÔ_u© ê*-1ìÒõ›‡*[²öG„ŨSCBø88Ý~ùH’‘JrÖR#äãRQf]y°|5ù|d¨‡¯tÏNº¶¾ ‰%³óª!]Ýò¯Y(~Pâ˜rxÅØë‘Ñß5§ƒ÷É…v×LW¬g¾¿„»ÁxjÅ®oÒ„wqQçW¨‰È ÏF>µÍ“ú<Üš”¡¾D#n:Š-Ëv°Q5æúX{]Xò”%#Î.èyè²’7÷æŒíëöñÛc üçl€m y§ñs‰¡gÕâÜMäª@ða ‰¨óÈÌÈ€¦jDÈÂÍ'4Kóiµy{¬Á÷]øÇA…U z·ƒúuœöZ+o+ËQ’©á8 2¯ø¥ïû²ÁhñËÁð+_•²—'*˜žkÁ ›‘Åk=µÇ½­³Á˜‡h8•ËòÝó[æîn{ËÏ0‡Lürˆ9w€D¥i]À,–‚ZêÂ,‰ÎϸHȽÚA¦ÎaÚAžÏÖoqáï§šBã\ƒ ÙMVãýi†XU¨wÂF_XJÙ2„v+LðŠ -‘ý7ŸYŠQ¶§ð ááЭV2`×t].‘ðâ£P¦3öP’¬‚ŸèCï¬ì:¶„Éàëë°e¢œÂ9gü6FVÚN2lCãšÓ©5pÃó”ù,¾ÝæÃí 8UŸÑXyö5Õ…kÝèP¤"J{\a)9¨>§”½G ý–µÛ›?jÝç2ÑÚ '‡ìË"¾ûñöÑÀ7?_SMÕž}©÷øÿìCw endstream endobj 317 0 obj << /Length1 1517 /Length2 7437 /Length3 0 /Length 8439 /Filter /FlateDecode >> stream xÚ¶T”ß-Lw£„ÔPCJwwwÃÌ ÝÝ¥„ JÒ! ‚”tH—J#]rÑ_ÿ¿o­{׬5óî§ÎÙçÙÏy‡™^K—SÚa Q@ÀÝ9y¸¸E²ê:<‚nn>.nn^ff=¨»äO3³ÄÕ Š€‹ü+@Ör¿·ÉÜïãÔp€Š‡€‡ÀóT„GP„›ÀËÍ-üW ÂU ò„ÚÔ¹*8Ä ‡Yáìã µ³w¿_æ¯G+˜ À#,,Èñ; ƒ¸BÁ 8@änݯ9t`(ÄÝç?%XÅìÝÝE€@///.Ì áj'ÁÆð‚ºÛt nWOˆ àa€ùƒ3@Ïêö‡]aëîr…î NP0îvŸá·¸îè*«4!ð?‚Õþàüy6.ž¿Ëý™ý«þ;#`Î ¸n°…:Aš j\îÞîÜæW ÈÉ qŸòA@Ö÷¿w(Hk@÷ÿ¤çv…:»»q¹A~Qþ*sÊòpY »»áüÚŸÔ¾?vàu„#¼à~[(ÜÆö g >êâQ–û3äÞ„óÍâàææ@\o°=ðWy=gÈo'Ï/ó=ƒ?g„3Àöž$j ¹ÿÁñsyB;þ‹pxx6P°;Àb…ãüSýÞ ±ýß7ßê 0å¾×€û×çï'ó{yÙ àN>ÿ„ÿî/ÐHSMV[çÉŒÿöÉÈ ¼~œ||N^n€0¿@_ðß*óÿ‹ûo«úçÞ¸ÿ)¨ ·E„ÿ pvÑðüS¬N à¿+h î¥ °þ£|3nnðýÏÿ³þ§üÿÉþW•ÿ›òÿwC NN¿Ý¬¿ýÿ7uòù3à^Éî÷S¡Ž¸Ÿ øÿ†Bþ˜duˆ Ôö¿^ewÐýtHÃíœþ>F¨›Ôb£uÛÿ!¡¿ºp_Þ ‡h!Ü ¿î'7÷ÿøîç ìxŸ¸Ý÷ê· r?Nÿ]RFØüš;^§«+ȇû^^¼?žûµxÿV6ÈG¸ß§îél®8¿:úT”þeúù@å¿‘°0þýÚÐæ_ð>úä¹÷Âÿy@Ä¿ ?èú/øtÿ=~Ãÿp{¸ºÞÏüoõÝÿ ÿ¾` ogn w¨ o½¨’¦òâÜŸ`Þ4Lgãô›smó¸"ÀLe«Ì]v=“Nè&ZX—g=•š§»õÛy_‡ÕüB»åÚÿÆ2Igl³gö3YßhÑŽtm/ 65§žÔ–ÿ­‹¿Aˆ#ê{äæW.BZ¤^=ŠÞµ½e_†"§7µ·*ŸªâÞ”s>Ó7 )ždηΙ¢`Àpç¤Áb'9ô&œ<=› ɽ£SIz‚°ûŒïµŸÉ ïóË)ßÅr=^·NJ&J ÔS’¡±Ç~2ß^ªÏø•¼‰#jâä-¸UÉ1ßÁ™U¡gµØ þàç0¢Ú…)·{¶ûØÙ6¸u€uè«Ð*[‡·ea¬èÝ%Þ Ó¦F¤ sQˆLÎ:ü/¦<öTÆŠ3É ÖÁøCÜíKïcŸ?tM{€Ã*b`’[–Àáá­;[ÔÕ~hW ßãúA¨^Ƙؘ`{YkB2Uq¾àú­ ÁvÂŬ®­4 «8K¬­-”$ÏD `¡bñÓ zêk×£¯KÔ•PV7fÆ|LÛRÀGñôzUF«içvŽ.Â9J$仸dI§~·@i¿è ‰‹Hˆ½Ë/»¯NmŸò‡|;c÷^³o]檧QözéŒÿ)Y,WNhúИπü›gæÇ±w·Ê´\77ˆÏ‹Ñú5æê 8n–·?6¶Ç‡qèÕNÑYIJZâú¤g‹AõôŠ˜ÕæŠZYGIJŒ­lú¦ð'G8u§nü‹óàº'yv ‘y}†b‡0Åà¶ ê‰ÕZÂGåÝ–ÒH˜¤½Þ•òP3.y»Ýãuû_³>Åh¹}E…ÙUW¶f÷íÏ{Ëë&d¤œt0Ù%JÙ¾×€Ïd­ÞPÞswgó"ªB˜[-ºF˜”תû_é¿>(@i½Ø²ûJÛ¦µûá6×ò#VÜ·Ôœ®uqÊé8ɬ÷öõ‹$¿XÅþóO±—„âžsœøÂH>ÞJ5aƉ2̇ÍU-S >o«ÇæÇyu4ë=œ¡UÂ/>Íä%ÓèŠÊÛØDÅŸQäLÉ-a‘rúùX¤j7?HY‡QÒ{%*È­à‰´}ËÁñ$Òi±ððTÁ×RÙëÕ§YÛ`©ë­•à Šf±´ÃJ…6óHåªÑ“^ªË§Äcq#n^ô£)J$šìÂêŸÆPªó=eHãOßõ®J°Ù¿„›ØŒ%ÄÈÌ×>‚þlƒçñ¥L“*9ˆ¦Ä»{PKk„ë<܈*- °(Bn!ñJ1–[ªVYÎñIcÐ åD³Í×-žõD“K8<ׯõ?)ÊGX&|\ôðõ= Çœm£$XËÉ j ÚM´¢¦!æ}#ªu#×È—u$åï®þhœú³»ùÇ.}©Ü\A[>g3u¹},‚Qy:Ó;ÇP²jN“ØŽ¬•‚¦.yuãþ8÷ËÁùùzaiR¼5Ë™®¸¤)Eé¶³}¤Â×-©%^ņÆzÝK}aëÁûîô?ü'GìûŸ`²sŒÝÎ Ùû¼ ó1¿&¶ÏÜ£ZtàÐôžˆj<]H×óˆnšoWý ­Àrl¤¬ÿ)Á9¼?8y:µ«ô¶o¼Ñræ¼0J¥¾â™r /[è›Ú5ŒŠ²iu!«C県/Ÿ'_#ôð ÿ˜U4øâS0mD|‰rÍ~e·‚£(Þ¹Àô¼Rù73ÿÄ=Ú%æù6ÇÁ›ì}a†Ùܪƒr‘zoqkçÃ?/èM…¤m8^`Î|˜äÌó³õg½¦m– [5ªþ˜¬­¼W-¾²!·ßÒÚGÅÉ7û)ß°ëIeªÏc‡#dHu(í[1ˆ ¶;ÖT-—£N;ÔOÎæüõåb—2ÞNűï±÷ÎvkyÃÚs«\i·®Æ >éQ>lÓ —z<Àóº0â 94üdW h³8·—ƒnÿ¨ëê€dÓ鉖˜~+äi§Z—VnW}MªÍsTu¶jÝbpŠ:8 ÕY=¨ïûX88´/|ÇÈB…aVÜXšK0ë<²]ž¤" ð¶ ÃÎU01ÄNQ©"zT–5äùÜÄõ|]g¾’Ø %Ö0%aŒP‹œÊÒœ‰õlmâ¤7¹æã–}ÔЈ^ã¾uñâ¾›ém|Ì&jÈ ØBŒxá~8]ÈÕÕF|q¦ã×ÙÁõ¦ÜVîŠE~)#ñà1>ð–»E¡šÁºM,G†î ;…éW-à¤^¾mœMw©f,¨…ìI+HH:k|ׯNMX¾{ =ÓÞ îÝŽ¼S¥P¯Í¶Á±Êhë®Fnòxã¦g|c¯\¸D ‹0·Yì{‡Çÿ€„´âóiÙiBœøÏÂ÷g¹ïFÄuÇ“VŘ_—rÞ\N=zmÅD ”ðm°œË½eqøªL‰ÁÃÝD|ã¿[ïn皟â-b“2¬(dÑлÁ,ú)öx>9â ·¸<[;›VÚœi¡¸Sû´î"ÒñåG¯Ölãd²d'mÃIö[ ‰zÍ“¥†hu¤¦rmÖ†”uPµß[ ÌhÎO\‘;R˜Ò:±ÒèKœ«’F+!~²Ë,]Hp‹(Ýç†ìUOkdP˜[¡h †t…‡ÇÅ8ˆýùY1º)ðÆnQý¥MPì¢Í»a“ÐèN63¯I}?ÊHm¡S¢4}1¨êoÀT÷°4 u)Ji£»#È—:"¬›uÆZF­^¥½e 0§H¤#Nõ.êÔe™ãõÉ;xp8ó8®>Ï»éÞê€üC»Xwzo¯îˆyä@¥ZvòÃâåµÎ„]ÓöŠ+{ÕÌåo/JøYÕzhöS¶+âÒHó¸ŠËȹóœÒ F£›Çk Ê×ÞŸº4ƒ>|1H÷þN¸Ø”’1ÒﺨAXí€pD“Žnh®Ï HŒŠ]êp˜. fMäSU®š½¯ó‚÷¤{ñé½ZÕ_åU$E›ìWþJ§érj–:W±`{!J0–éô(;CðõSK^uqCòǪALþŸgX8[†çÊö%²uªîBÄØ‡Pzgô'\hÍbÕ¹í´wpf¹»O¢uÄ?((3}¯ÛåÝ(9÷Œ^&™¥ÅF~ÏPöÔ~‘AÂY`Qÿ•«“­õ…¸™VvQyJã‘Ûn=9v;^´¤i»]óç_âb~æñbF¾Tøª‘¦ˆ\»ƒÛä16ÓÄ{}pü‘Lî4)Ÿ¬¼Ú`—…dZ2æJx¤£ /Û¯– k§“äÞßá߱Ъ- ²9cêu/[”ûóë{Þ|"lx*¥«ËžPÕ-‰sÊø´G³ê&äÔØŒ HvQ 9\ËC`HÕœ’lÜ O”RRx~ÑÒ% Ý[ O»ü‰ëõمB4iûÈ pêFÓ O1jHhÁó*mža’s4‰·3ŽÍ“T&Ãsö^Íîï*ù’¡Ý]9ÚTŽ+o·#ò°‚šÏŒ}$sVJçÚÕËnPzr®Ï[T*C^sRa¢†4¦IJÖà=sz«hÊ3,+ÊÔ”_‚Q掾ËZ¯=þš'y\ !rIïíq§íèeÓI&xH.JX¹Mk¢àÜ(›tî@¢)ÉDŸ… ­¯ìDsñãø¹˜ëTˆëSM&÷Ù3ºYˆž©¥³À–w,]&I)ŽJ£½«hÀ8AÅ’®“è™JÃÑyX–Ø/Ü–)«Û¢ÞYÝ|úU8|žà:ºŠÒƒ´ýcb5õùl*Zkm„ä¨7Í´V¡]oùÖDÒ´Òú5òÓÎQxíÞ–õVèÔT;¹¼|ÔL×s.9593¹Šâ‡_¥]û‰%ò~õ{6=â³Çö;|zgKÉÜ.°§Q0öp C téÝëbo¢§I9ÈiÍôý3N$d*ˆötåü–CÅ¿ 39Ü-éï³pûü ÞCÿïô ÃÁ*ßœ†ŒÀÈ[¯g¨åÜé¦ ùÎDzFö‰UCœuÙ+Û)žgâôÆøM˜‡´ÙZ–Äڀ׋ïzCb‹÷¾Äîâk5q¥|š<¯\T”}ÕCæT˜"¨ýžÃ‰[Ý ê'Fk–œ˜ˆu¦þ6ýêÛ>ý"o­3L[íxÝfFî= W²ÜL }!Ùû Ê}¬0ôz>DÝsu$¼4¤œVÀ‘¿4C=öŽ2ò1ãÉT¬šÎ ðMqŽC×býAøÕ4®ó‡¬ïå5ï·ºÏ`^„#{%ëƒ8¦ˆìëë)=>uæ&PT5bŽ¢†R<ÂaÇ0iõnìêÙ^´mGâ¼ aµ´›-éçyRƒg*ž§€¹ÎÚq&Ë)ï÷Ïu}}L^½iòÏÊb¯8)"õí\d¤®Ù?cˆûš\ÓaðN5ÌtJ__ô´Lë)öúûÂXJϯ+ŸùS0éÚÈ2"È RŽNiðâ~3bÕ€èù³ÇO½Ï+Ïá8;f¹ë š¦u?>MO½7dëæo“ N ü¶Ø«4©N™¬_ÊfãÞˆ~’×+÷°/fù„2?3ðáJeƱèðÀ¦·œU‹¶—m‰óË6…²/M—eŒ¬*ϤXP>w‹ïËÐÒ[ݱí¶ÛÞ…h°7ž1Ç„1u5p‘Ï﹯'`óû (–|á1!²Y•#>›q’t}ºŒcØÁºÆ"ñ…Ð"%‡Qƒg½´ù¬5?® œ¢èžt8ŠÜ s f6¥t½5Îùˆ”9³­‰Îj¼°‚­–xŠSœ36Î>ËãÖB«E5 ›_É0íÅ%n£3â¨[“ê†KïŸÇ)Pq],Æ?æKF2f‘ÓÇ.ȈcTŸüì[›3'¿‰ù„®(¿ª“sIYÛÁ¸Q/$-›ÔÞU±&É|g¡—5Q÷ÁÁöÇgÈ’1Óiq Ͼ#À© 1Ë)Eº¬†ól"f87güÓWšPïükr¥öGèݱlE ¬Ûy¦Ú†!Ê%Ò°:`-èšwR.ÙÙê"É~Ðéùê ›•–û‘€þá’Ì1Ydµ1ð¼©+Ï BØÛ¥šË«Q{›©¥²3áó3@è$®ž,ñãèWi¥"ñ‘ÅÂáI; ~ëqÒ­º0ÃÚ­´`s†¸[WyϹÍhÆ+Vêyû£üì½N'="£†fáŒ6•˜À´+~™è#—þÒ'é>Ž…¶”ýóì¡{¹•.ôÚÜ]„BµZ:=ŽpOU}†·+“û»ã¡\¥û7PЇ² éØñIü'9¡Sùp!mäwB>Zè]ÃWG„LÎè¸öÍ}…/÷¡gú“‚™ÉaDNê“KQæsJ‰Lïú\äªÖSpûre1@²V[ŸZ<.|&Gq)G×è¬ZDžöŽS§ßŒÐ®BQ(ÁÒÄÜ;øl*ˆreo‡¼–~sX£‹ïbÞ’²:Lb%Üß }B§&Eõ–‘k$| ´Ý\ ¦/Fî@Ë?ä.›aNóJ"ËI§u>¾IVgØ»EÕU!u¡øK1¬JÏ–b›Múiá«õ@º -2o³Ï¼¡ Ü-ÑÕu‘t#@Ýf¸ó«ÙÙç4|õ„±Ižãf:CûÌgj8zœù&RLǼؖ^IjÏMe´cX¶ç¬ƒ®ÿõ—Ÿ/<ò/å'=N•Çhg§çÒ©FþÄ9ˆÜI~‹ÙB6Þ]ÀO>Qrÿ2Ô$û\gL‚t—¹ÅëS¢Ïµ2Éréåùý·2•­ŠÌ:dËBXdŠ#ïúUÁòú[OU¹Òãm¹ÙXÜ•—VÕtkH\ w²é( g&‘Ø©ªØ'+=º¹ª$b˜Ìòùó°Ò7k34Ýê=†qÚ0O¢Öâ Ã+ưÐEøpÉ ƒì`’ÚþñÀ–º‚ÒPªö$k¯.aVí*³îaçÇ—nw±M‚ðÉLp?W ¬õâÈaâk|lsç²Ï6Ñúµ|;Ù­•BÚK3W­……R·ÇÏêÌö:Vú½¦\þ!Œs’Ò™^2š´Y9´yœ‘;6çåß*@îdµ0al¿èż|TUë Õ™b,þˆ>;@%<|'XB ¶ã9ÐÄÍ9€ò®8‚-çÚÌù*ôsÔÖ…cÐÁÅÇóTË&B\u âù{žëb6ö/Š[Tkñ »T†(P Î'hˆ_\:Òø·™õÒÙŠì—ëfÓÍŸœ–Mû½’ÞÀVO%ä$§4L™èd`DÒÄ:c¥ÊÑ'A<ìSŒ³T°Üp¬oŒv‘lB¢4/?• \ê—ÞSv®¤¨°©ßðn+•Í6¤|“òž*z®7.B[øjs¿r£¡åk9ËÛÞži2, ˜á4Á¸é ôGÞ$šÂÜ¢Äâ}l‹ÍJ†?·9§GÍÔ|£{PÄž˜Ÿ®2G=Ì›»á›ü?ö­†ÌÓÅü>;ùNµwô?¯#SK…{‹d‡{õ¸?³½šhÚq0ÿÊöÝ!6õr€•ïêL;;˜Ã"Šÿ²Ží>qúBNêÔ¸šª#‹¤>­gMO’J±¸°`œœì8õYÞYM˜‚óKB^œÛOÚ(ÛpV Ô‰BYÝ´ŽWÍÏ 5‘Ñ×1!+Ç@‚ R&··mÚí;7C¨ Ÿ ="Æê#,TP„\àeHÕzŸkozÌ `žC‘‡†®½|v½&¥¹®s´_#>:2a¥¯2îB€uü¬ÏÖß’¹`‘ÙYyd?žÈ×~¾^*"àÙã…\ÈÄ…Q«g =À>Xû6ݹ±õþìfÿ‡ÛÞP*ÝEÒh?¤~Õ¶§ŸÖ{0áw’Fâ$‚‚*­ Ë›‡î?¬²äZ‹Ù€nûI¦”ăW»­Ð °à^³Ñ1È ª‹y¬KžÂ$ÁË…Œ™]çä¢*º–5±5}Tô™j\¨ 9•™¬õ¬ "ñ#óòb«|­¸ì •#‚ ºö¤¢½ÃWï( fêý[p§•>/â– FŠö•´ßýTD‘ |Ÿ Î$™öÔ¼ãõ«ÅÔ‹® »î7¦j‘Rû‹¤abtLÇÕhž–²^KÄJÁ$þ x{MØ’1.ƒ‡°Qé’aP¼ÞVhõb|تhtqc)€HÔù+°OÉ~¿T=QtÍuèFLr{õ€$1ÓÉ XJ˜W ©­¼d±sgLd?¨ÀœÐ,Á•©*À(dHï'ÛNX•íº9ãÒ×Õú}ð¡¢­yifT‡Å³½p*5⫌•‘S¼óÝòpÈâUJû·ëyuŸê>N4ôCû´{£P£a¾zË(ûíÞÞÇÂï,ú« «­?R(ÓJ„ÊY‹}ËFnØê¬4¡ÿ¾³µcÖAOnt+>Á×C¢º‡•”NÞѪ„‘8_pvºM ‰UkÊå»$ %™Ê¿§gë¾—´ 1Y¿ÝAÞRÚ F*}ü]$ñªo3oîÈŠáDí z3ŸVVcÙ%i#Bî{‡wãP?=¹û®[ôëCuOc‰ ¸ß™œ» )oFðèh5;u" =2ÕÑëbEw£> $•‹ª–ÀKjôÏ/Ãpã¾@°d>$á¡IRsDê]Üdˆ5BëcJ»/ã¦å±èòÐ"Z0ù£¾_IeòÀ•äU YMG i4%a•ò‹ÍH”Ž×0ʬÅÐJç} Ч«ü™æˆz"Ú:þËh$Ñ ø•ˆVë>ñÖ#*7 ×ÓÐö,<ë(Þ§›ãM•½p³C×·fèöD¬ÖqÆPWf¤•ëXÒDïç8þ,ôÉzR©(u<îàACPuj’b5c[ÅuÙܯDîÒGÍ){Ð …7bÉÖu–Ø–›ú“I†Í‰ÇñÛ®Šïv¨AÝuÃ¥ô¿r(ˆÍ°-ιŽÌVHRO³–3žÙË8þlhf<<Øxc¥>êP4-?Éüíˆø«Ügâí®-—ÙOp*Â÷#æ]‰Æè·6†¾óHõóV$£$vl}’àåd[Â(U3‰¯<Ó|AÜxöp• 4aâÜ“áfõ9»wà‘\ÒuÉ£Õš9ÀØa·bÕ[ÙR3Ê®rê”ãÙI=ê:’ÒÃg{8u „¦T äGh 1˙鞃¾ e^Èwré‘1ZÝÀ« ¬â²m4V¯üÜüÓŸmM%ÔÑç¢ :IªÏ‰Ê§…F*ˆÜÎÎx¾hOÌ–CýÉÛ‡çãâ`Œ—åÄ"ã P³ØÚׂôìCv§j®:Qç¶{Kœí]¦*ýú3UM‚(ç„ÌæœP\TB-ž¦oúpQ°Ð~o‰v–L{d9.y!:Dç`%µm—ç}ì–.ÕÌÉð˜¬æK©Uälˆ¶ç†.<â0 y4êUu©:Ô?îgEíG½ßé¸19@‡q+~*1ÝnPs´øN'i«¹„’§EÛ6Ãró"?_·±À㵊–&0ø)m1â\oBìÖ÷ž ¾å¶sO–]'2—ùi6³Âÿ-8f) endstream endobj 319 0 obj << /Length1 2648 /Length2 17008 /Length3 0 /Length 18534 /Filter /FlateDecode >> stream xÚŒ¶eTœÙÒŠOp‡&¸7îî×àÚ¸»kp î®Á]ƒkÜÝ݃C°Û3sÎ$ç»÷Ç]¬oèjhamh6ø;xC€„°Àœã2t2v´°wvbt²°þ+K¦¿hÀ…·5µ³±Ù:;!þŸ˜…#È\y¦[lekçfëõ›ZØš˜þ•Љ‹=“š­…ƒ HZì?V`âo™ÈÀ¹À9@îÆæL9Qõ°ý­dþK ÎÃÇËÞÎ` Näca ÿAôr2tœ]@>^*þ!23L,ŒF 3 [Äßì`1Èô žG w€6<„Ìà_?ÿþ§ ž3;[kßæ7šIYCDIB–îߤÿU‹ˆØ¹¼X€VV3'€ƒ›àó¿Dÿ–à¿éÿ-U4´øOxJÛšÚ¸ÿÉ\¾ÿfâúŸñ þÏöÐþ׃¼x¬Aêß[ dƒ1ÿÿÞ…¿ü­À_,ÿ?¶àÿÆ$ábmý·õMþ_†6Öÿ±¶‹3xIäìÀ«bûM5@ÿì¶ÈÄÂÅæÿj¥ ÁË"lkxnF6ŽÄNî E gcó¿‡ç¿í{°¶°)Ú9Yüu˜ÿÛ”uà 4¶_2Nà¦ý­ì½ŠÛÛ™üµ‰,ìCGGCD xÔXØÙ^Ìà•5¹ÿ=å&F[;gð8C€©#â_­å`0 ÿ%úq˜D~#N“èoÄ`û¸Lâÿ"N €Iâ7b0IÿF`NÙßÌ)÷9å#0§Â¿ˆ‹<ò¿˜Så7b0©þFàÔ~#°?õ7؟ῈìÏÐÆ<ÇÝTÿ•²=:Ûnádõû ØÔè_ÄÌöhdèø‡‘£¡1Èdêü‡˜ý?âà_6æÄV çÿ±çfýWþ€kaü/bclg ’cfûKbcó;·¿¦‡éwR¬à2˜ØY[ÿ3ø†aý&[€þÇ)Ç_zð6þËŽ<=Ö†6°€Ëeú›lajáúí_j;—?Ý‚MÌ~;ëÍþú–‚þ4§cþ;9pÍ=ìÍA¶X€e@pð–@p›­þ€àzýN‚\ë¿–è·\Ý?2_¦L¿]±ƒ¹lÁË÷»`×¶.6F]f„¾è™ì~ æ´ûã338Qûßj°{ðÙöúÏÆüéÿv|w0§ÔÂî!ÑÞÚå$Ào&‡ßA‚+èàbç 21²þÃ,ý£ÌÌàL~3°ÿ…@®T™lîþ0ýë\ 'kC'ó?(À¡ý|³39›;‚þh?8Og7»?€9\~Ï5Øçßï'c;Ç?‹î˜ë\L·?¶ Lêþ{õø‚ íù;f0“'ÈñŸþç®4vqWÚùïÏø"ý/þû ¹ƒŒçìŒy?YÖ}j¿¯&pcØcíãP»}u!aCŒ¶†Üf„ê•ǵ*%`Ë»áJÊS6¨Ò†–ƒ† ‰%æt³âé`|ƒŽŒ%ŽÂXÏ'σüžzâ؇…›’s(ê1(uNZ~«I! :Š®b‡åGt¯µà G@\^P‰ p0GÃý+ðLAÊÚW‰næ{§Ð204I¦«iòJF ©é䣲Ý`v®_…Ýo&Dѹî§f)'OçhË/óŽBÝôE¹TûWôEßïe¡ã}ÉÈù9•°¿F\z‹Å$æNGYÚn¤£tíÝÆgh?ñÌ!§Z"˜º™KÅxfs–÷瘖¢>ÏAŸê²˜1 Û…É‘äÃÉ“&]Ј7;” nm>Á»}µŽÛ•àˆÓÓoÀCÐ|šMrÞ@Eüæ¯*£^¾v ¢G‚u„Vë™6ø`¨]@xêM7A>|ðasÓW\BU›«¹ÕÐ=q›j±`–ǸÊUWëgOÅ^•GHý¸Ü$3]\éGÏ“É?b×qVÝ@áJ¼—¯äüñï„u' ÷ñfò‰]LËЀ*»HQßaY„5nõ©2Ÿž#LKAú´jõ@¼– P{´ÃT!§T Ò î=LÁ˜,SQ/hcêà›¬>‡¾û”Âe06üHPºœE»N[tsX?f$Ãö¦Š;]†,’¨†>ÏÇ®€GAmdÄ…}³7…âq¤êMZSᮓ2Ø@ÒÄ@[DÚHE¸æÝ°ûŽû]*êwEDü‰þp·QÜp&ƵˆŒ(‘â°±ÆT™¨GœíÄž‘ ¡?ûºê"úùöžt^ÝÒ´ˆ›w¤ÎÄ­áL›ú¡æÎ• XõëLEÔ‡*iÝ#;þ¤wÆÝj7LºÓ3ßñ(pUMf¬†dÉS;;ÓÙP/眤ÄåÃ4a7Å! 軞f.¬ìçíïÍØðíyãÕâ ûüoë®üvSªàJ¼ ÙqªšOž ˜$’x´´¨T)éŠÊ± æzÁe¦Á(ddrÚ[äÅ–9 ÃS·¡ÂYµãÓÈ1¢êÞ÷Ô+kêMSZ®»W¡ßé&?ÎÈ‹Þa¹n·÷ k‹8•ôÎ÷5жõ\âòW_éS°RUý“8ú-®Iû“žŒÂA³qR_Lj!£Ã5p;\ëˆðB@¢ú'Æ õòÛ¼‚¢Œ‹ûŸò>z» “þ§ÄpžOÕ æåbXQ‘ÎOaSQõJC‰ŒŸKÒTÎ÷š,OKJ_¯ä;ZÛ 3›^ÊzØá‹Ã¢œÈRù™ò uL;lFÌ#QµG§MVçmŸÞŽ„a\ÕÕ7¨£?qÓÓž“È(ÚŸûó§,åÃãB9Q|¤‡3=Lð?¾Uút9y YŒoרÅx±oµ©ŒŸýÆósKÚ³ï©È¨æõN]Dƒ¼ÒÛD&R´Š§˜«iæ·1QfnZÐú‹ŠÂJ­ºHÂiꬦ‡i•C d÷œÑ%ë†Òä‚j¢ü¡o{š`.µQ¹%e™5®ßëå—àÁ½¹e&;Òy+ø' DLÝi¿Öyr¹ôqûeý~°a3UaåkZ‰;^Z&9CÁ üð¤æÝ1£§0-þ,&T”_ìà¯WãŸÑÕÕbƉ]Uµ»÷ÎË¢7¤ó/Ö© ¢ÍH—ž¿l­šËH°Ô5¨Ã8ø §(Ý eÉ‹4ódÌ?ºO¿<6îz²Á=ßqˉä;è¡ ð}‡ÛöM~Þ¤Ó½ecÏrçÒ¦:­î-_»õ{„©:!_õžy[Ûw†ÅãzÈ.'ûö¤{¢%u¸Š¡¾ Ð2 ×=¬¤ÁKÍÁGôÃ×p è0j©Œ×(ðð5àm/ÌA¯c›¦"Aµ¯ÁËþUј ÷"‡ø~¦løèÖ!ãrµ¯Då¢fÉeö·`bÄ®‹å~ÎÀ¡ó@r ÑÂK@ÕÓ©¼h8õ´MáôÃDoz-Ðó2à¼pÒ&9b²G[Ä¢ö Qµ±®å+–~‘àA´[ƃT'É¡¸\&gTËU6EÃùì ˆõcJÏ,]3['Ì(%ÆÏ××6–îY>ÄFÂe2£á' ßsV a-ã‡Í(²ßåq|tÅS¼ G¼SÓÅŸZU‡õXæhÓ&Nô÷¦ßå‹¶ÛS`ÕŽ¾à’SÕ»º?+?°¢TÓcÂr髽kÞ±ªú…Í>¹ØŠ#“†\ÖyLÚo¸÷H³¿g(6Ò]òèá?¤-´×]1ŠYø½„æ)§`¤cƒÁ†jV´"Ët6mU™ùAO>Uaš^Å}棪)0î7p·~dǬ ᕎ‡qþ²‰ŸûkÓä†ú´¦? þ™ª*÷CZøeiQ€€êQKðUvJ)òœz¹ÝJ¸Âe1K#¼$éC¥7]¤ûC€øÕðxOeb7V½LIþ w@E8°pv©±ßñBIwïc£ç¤gfä‚Ân*ÉmöhgfVÌ•ÀûÄu)1þ*–®#n5úñÒÍn…r8å =BxŒæöYšoÅ~—¤Nm’¹ÞÚÀõ'ºd¦'þÚðÅ#ñͦ·yï>¢}ñ&ÎO0] ¯‡ÊŒ8$[ÈŒÒàÈ`Öûw*×¢*…± ŽÆE¥×ÅUyw_ö® n\€‘µ êŠ` nóí¹wë9šÁúÞ&üfé4“K&íëñsÕÐb$ŸgÏ'Ïà7DÛæ“#’ ô{¥× W”æp…Á°NÁú´Š-ÞÙ&çÖz_”šÕ;†¡¼å]gz“Î…Ø×mÑØŒ÷ß\eÌÌ~\¯›oødklËdòªŒ³>ô5éP¿iö7‰õ™®ÐÙÁú4óóó¾×;[®q ÷ËozhbÉ“š­6l©%÷Ò}5¤n6ÆFo-vrm îgAkF,¤uØ)/Œ,©Ù®$eÔ¤óašèß †¬D?› ¶#Tºx)}¶Ñòè¡:zó\‚awqCì×Hms=}*£ò®äV‰ÄëU‚Øïãl±h2o$IQ–KwÊÓŒJ•Yny³Ê{Z²èØH²ó"fWµÑ˜C˜p-ïÊmßÒlýšZPúh,猔’ -gFÀÂÉʉ¨Á• 4Ûý±_r‚rn2Í/®_ž&ž8=Æ 5`‚p$Ð4‡HZ¤»’›Ø-ÍDkÂÓ¸w2šgd_“$ üª9}ÈA£Æ°}7ÑɔܬՅ&O[ p"c­ŠqÃÛý‚¦KÉ`üýÅè¶Ä™¨5 ¹¿.È0øÃ],O¶ÄÑÉ a<ä·e€bŸN¤Q: GãzqÈdbf’z¾~¶¤#ñÖ$­w½ ›Wi¸–±¨÷-â&k!„Ö´ðÆS5º?bîG j‘ùIWªÓRò}f¤†Ä¾–K‡&ãGb&mÓâýâã<Ä´¾â‰ví$åúAÙ>Ú^Ó=ÈxÑËpvϤóbƒµž€‚ ñÊ\ÜûnG,Ô’Ì}³`óÌD Ñøo«âiw oçûha¼ÁÉË„üÄ® ¸®3½‹­ukŽT g/ØJ$†D/ò㙇^Ó]mO©o¦hÑ ”ŒÄ饑aCX½í3éÙ¶U+~…Ôg;~%øµíµªFtSåø¡ öÍôžb$Yñ"±‚ uôYë2hAȳÀÕ¤³Õt8?墔å›zdžϙ‚ÇB´ Ÿã®qéF‰ Ôëf(Æ AX $ë#:åvŠá3Œ¦eÜénA!@Ä€8WÝ%@bÁt®*™)üɨßÚMúÛ³VÑÖAÑîvÜT¬9õe©Ùšà»¦Õ@Ø1~´ÂWÇ ôÑÕ«æ‚ø+Êf»¶{‹¥ñƒêfLNÖŒõŽòYŽͳ&ÈÝxVV!lGqy<ᆹvÑ(B ÇjËZâ˜ìÜ”¦ñCãu9ƒ‹ÉæÅôV‰[ê "œKÜRÞ¶²þK'–û\öUݾv[ÜÕcöŽyvnå;®´Ÿ;ï4Cüº| £Æ±¾AûÏDP.ùÉKØgcRTש|ª/¹83 Ö/c¢¥¢ÁÝ@ÚN™kåð)ÀVº[½¿ˆú3ëäj½²†­Æ.Þ’Ëó[Ñ—ˆ÷ÇÛ$K‹ˆ|Ôeâ_L‘ç×y«Íד4A‡E1ß]6v}•c’[„ [•N.Ní8çm®Ú—¡¢çœìp¨ã×» V(= æ öÞmçzéÐ~¼àv¸ U¤Àr;"sž'ÒÉ\ðŲ©~¥{¯›wÜ£Î$Kj `7ô¤ý VÏE.lj Ñ€çøZ_Ÿgê0«°Ž%«ëÁ¡€éÔ²±øÃKÇáçÌX¼£(ƒV­k6×êEÜ-”ë‡è{Á+ak—´²õørâÚÆhGj9¥Nˆo‡€þl˜-ç©y„PZéyÍ/ˆñiV0þ0»d«ú—C}­¯Õ´¸„³óA© b “ëÓ ’#üijd0 c0a§è&Ü-õŸùú „œµ6³Q"š»4£ñêö^8“ò!¾e4³vœO2‘ˆDdÂÔã +îô8óúšèóU´wbÏž %ês6¦ˆ|øñi Q¹¤68"ñäÑÌ»F'¹Þc®Äµju“æjè:–ÅÒ1™ý}¨ L)÷â<,\EÖ¡€›—(Vó"Þy:ì—‡Q—¿¶A°~5ö|§é*5)OµHäÊ}DÇÍÉ3ÖwffÂé ʾ1k‚4æõ¿†AˆÒöÌýæô?·ÎÈ >c~JW£î“!——/ñï¸Fò~ÆßW^±Ÿ_j€3,«Ÿµ¹áâË㽇‚CÜ*j7ÿ`“.™Þ)ѯuyÄù4çÊuÌ[ënõ.Í+ú0~Ã|‚¦¶°MŠ¡ÆˆWж O«¡xŸ£9s¯œÔO mnë "×i©Æœš"Aáu&<ˆ=Å!YmàïlCôç¦T.hªˆ‹æ"î¬8<ßEM%yöæô5îW£p¤EKø0gßD¢` ÑÜZd@ŽSñ(å«-ëÓ}Uk'{Ó©|kž ÌÔiKÙqÂú¾mÍäÔOñݹ{H¬Ã:áŽc JØç‹–䄵§xøøj)ÃŽKyÍéO› O6¨C v¬yÁ!OˆÙ$ØW¯µ›7.㼕¯lï?ø¯s—CÑT¤Wô.x†‰j¶­ Þ;OdÙz .”Vã}€DnŽƒø1G1jÇ#˜ƒH’úžA<ÎR„TúŸ½lD¨›hðp¬tÔÀ}´)r‡COÏ›ëÆr7üd©"¤dÝrÕþþ=üIê„‹2`Óæ~ù\ã;šW²Ž™gyZ¿çt€Dí˜íx<#Û"âÜ7õµ½ð·jÖªI¢¤n3Ÿí°q¥êvk{<׸²™“Ó¡RˆCe+_ú`tH?s:º~1øø|ë3éÄe'uº0“=b @û¹ç/[8ñ³#‹áÓaxw×Ãtz¡»yUíäGÍT j!ü<°söÆ+V;i£@9fv}ex‰Ãi;-פƒ)ìÚ5xÍD;«ùnCÞì|²‡yé{ ÂÏ7‡‚㣵vi„nˆPƒ©;‘¾ú.¬žý|/w™ ˜8¡Ü†cU ‘*‹ß©„iö0KTljxã ÕÝÊcªáHY?öéÄd èì OÚ[ª åöâ’Èõù5°òy•“™9]ï{¸ë`À–¬ƒÚH6øuY¤´7ÊŸEèöS Ò½Ša¿ 7üM§³g£¯;Í3å ;j(Ž 6±`ë{ýr¢÷nXÂôÐÕÒµ×Kê;„@b«Ih¢7f)÷’ÁJr"HvϦ»‚”ÅI÷¼²º’~•ÌŠº$¿.çFP,m(.­ZñT‹ô&†²„˜Õh„r‰‡>m‹•µât_«‘:¦PfKÂÜÑÐبò,Éq´¾Ž²²'³.Ç$L¦†^wzÔhÛ‹8(´ Å8¬Ù嬶;÷çìÃD!ƒ;:næ^Fq­g•+‰^µ§¥¶J2Ï ß´¨tf=F)à7·¨£ø§Ì9¨(¼•ê¸;¾¾ùÚ>ÿˆEc õd+¿Ras†UF:ò1}ê9†Îž4·‘œÚˆÃ÷ ëáì$ÉE–®¬„Ëv¹†º+"Ý]âµuÛø|^uK’…¢f0Qºe¡Ïú<³oäÁµ‚)³ÞÅÛE>R¿ÈÒ hJ±Fó4]ñ~JØzùÅ€mJãÄ`ñ på§è§kÉx¢S€¢Ò#µš.AË¿Û>4M}âšóA–;¾þ´,+Eø.’¹&sÛ«ÆB·]90Pÿ’.†q“g´ÌŸôñÍ¥)|!&;;â°ç÷¢n„§·³«(W*;ˆ\ñáPçt¬õJñl£xfFµ^PŸËUæ.è…'~©# ?–ŠÞU,]N@CË?,‹íñ|3Tº“X!”_ªz²?²á¨JÌUûu®{þ­¥º=*#–íØ#q‰Çf‚—<Æ×²}'¹Ðn¢n츓›÷‹²E»$“šK-ljYï§ i¥)‹cƒ2JOŸÊ¯:/AÒú’ŒèüÓÆM,·¶Ö¶ÜÉ“ª´L¶ç¯àX¿ÂòjB!ù®,¥˜ÜØö$^¶XÎ)ý ƒ\OK$)Û2Ö”NAÕh Ëš|s¸¸¢®Ï5;,)y…RÂgÒ–P¯5Q¯fº¶ñ¾B_V#ý=-£­ÊG9MâÍjÙ&óúl<OŒ“¡K¶ÐâSRMþÅ i%׎ìf^6 ÖA ­žÎò¤ÚŶ¹ª°c˜ŽŒ7L/:²çëçèÓ6ø7õW*2*Å~¾‘Ž žÐèYÔ*“Tä¤ÔܼYüýÃd@ ³_ÇÓ`;k˜ Á¨§¬·ôãÏg8Ü6ÝQèMò^„®½(ý˜v1Y-q¿SZ…®é|Ï÷NMDö«þˆ«ôJ–¢ŠSÉíxúÚ«‹è©ôK>ü<|ß·øØ…U!-(Ni²5°[oí›F¢"¼mê=GÂÀ³’<|â æ²…a!<:wXò+¼Âê÷~—M+–5ÇÑæ¨Wlj’‰}vÔühFîð1=‘”kE7öIEŒ˜/dµÁÀ»;=•m~ôÛ¡‡z†@¶]R?Ñi½ªûí¬) W'•ù[½—dö'ùk^wI¥ÊýàNEÛ¶ÍÕCÿéêx!²W½7š™ÈŸH\àŠzÒΉ¡µ<ñI¦óBsî!] tå—º‘šCMš_s?×waeˆ|]R4Ô$z¥/vÇÚË8¼Ù>–è ƒöPfß<о938—h©p_ñ…mW^¾²95íéŽA ÇÐ#šÄ¦„Y>¨›˜Íí¯tóêpJ¹§]TVÙâdzô‘¿£ljø<óÌo[Ùñ3òçMêe BemžÜj_eXND4µŠâÕcÿÄÕD©-Ò%E¢ñ¼~æ¯ç†ÜmVŸG¬"ZçMZÇ%åæú æ<õr@ƒÇHI¹©8AТ'3¬¯h§í¢^ S6þ4Î’V2¨ðþ ’ê¨Uýù|_ù1æ ¨r¬rÆ.#U>oP¤-”äfVÉO¼ŽÕ¦´9Ò ƒ’ Vq…ž#³(=Ø€ù2~ŠYe©Œ‹9Ôbz“2nÓ^’Ú»Jú]5ªOP“_ÿ—ºq-¨R Ü‹Ã_X­­Ÿëž¼V ¸¦¯‡ ̨K í/÷ ¥Lc­×(šÉñd ƒ 4.É ±ï5±ãºóÏηÚï’ì–Yù;"]V™‚¹/©½ ä*w§¸ã?å¶Â©Ï%pgâÜ{§Ù;vŽ#€: éU)¤i¶ƒu¢À¦AË»ñ\ÏŸ¡Ïí‚ãÌî´Ø¼ûWu—ÄHšižs{ßÂÜFt¹ç$}¢®(ä2²àÒˆf‡eß×Jè_ɰ§žö a)J ÚWÙ eƒ/I;Ûm¯j¯÷‰Ì팊GÊá}‚åÊÃ7È/´Íª5:ûf›|T‹§Zx´–¸Äi/µN°÷q7«âOžZ8¼TªbKÎA‰ä†<þ ¡HmÔ„-Õvº Q C.L £=ó;)ÏGX§¤tJùÈ“*¾•ýt’çä‹N a˜>J¸,u­ò²ùr¯~®”»’Bé$Ò}}»‹[ð¢$½f>g aÉÜ2‡MÆø}Ú#¿½æäØGhíÐf:÷hc­þ!ÛŽt9ïhAŒ~)Y.ò|OÖ{wËñócJŸ¸ÈÑ)˜>ûô…ðí5¼BiZzó{%àa'9«ÿà<é^v»îg:z´oGÏ%™ÍÞ} uË>FZ}öÛBÊC ê´lø ¼÷V…QbH½ ;L<_/!¸¯qXbyyo×ò¤)é-ì 4D’žÐø¹M¾{sYÿ0bè3Ô„ù~nÂã§çã§¶˜ëÖ¦›|*ÆËœ²Ú®ô|à§1,²‘4 ™p WÖ}R>4Qò[&Ò f@vÉ6ÜÕöA7IvÔÙ¯kÁõrŸ7WIñ¢Qîª*L'’ WËO™å¾â¡×ÛØj†@Øö1Sa×Üfx¬eˆ5ë±í-t°a tb€ºÎo`µ+]Ô\{1sÅ"Îk•ýׯNHе#ÐïZƒzhŠ´òeõL^Iô½O\Pb¿hþøÐÆ‚¹üÖÉ£á3R‘ƒP=C>Óþ/æáD×LŠNuxߢÇ. _Y>ˆ ïF!5*#Ïc†#ƒ\ÑÛ/*ô>î4 X€^ØTë¨.¡‹áZ]W§ºáx:4n>MÂÉTI»<‡´\îbÓÇÑÜ ¾›Œjé¹Ï([r¼Ü-š5T¥[j5¯ Ä ×9ºñ¹¾ÃÀ™˜-./=’&ÎÕ‚ààÉL¹´ñfl´­A,æÉXo^un)”†0ô …†ñ²/Ÿ‰rïöÖZÌ·mÙdsbíT”šIW#+¸®p¨húÃŽ{ų¥áEÁUtaê‹^¡²î­3õžÄv¢†è*ÐÑ?p/MN<ØW )±9¾Ñä1g ‹íPMyÚ*j§{Pf’_€2ž¤­­È1À +Qÿ‹¸pc¥þB A0Øugî/–q-|^–[VÐÏ^ûeÊ[¢6¢ Œ5B÷é0ŠžLÔړן íIƬ¾:ÁÇ`wâN}K³OE&úú´6@ÑAû¸ Bì, óTQ.ÝëTf€c²‹ÚÓ‘í< N`HÕp˜¢ölß"¯ÑP„ Èݽ»<<Ïçb,gKŸn͘š gÀ*IøûYí(ª–kkÓÇÛÓå²ÖŸ‰µÞ"–<œOèÆÌ1¤‹ÑŠt”#,„IŸ¢¾ˆYág¼„z»1²‚Ù=Ç~ 01Ä =ž e(Cˆûº})XCÆE\y¤¾]þeHPŸuý1ɾ9õÓç*¡Ð;²_Óe{Å&LRå3CjÀ¤ó醱G’xxÓ¢Á¼÷‘IÞ7³“uÝ2ÆÖ˜ÆBÐ7†ÅÀXºx\ÎÑêЯ‡Ü³ž4Sƒ0#Ë -¤‰}HC¨ôœ 3Ö´Dµk+o*>ª¶Y¤„è<á&Dç|-3Á¡½÷ˉA°QÜ6”ï8ý­¡Ã¯+yDÁâïƒåý Z^¿‘l÷b™©³âL™Á@é¹Ë[ÁÕü6”³Q‰é;¥{禾Øјç‚јËèCÓO]Í‘ìÙ¯ «•P¨¿``‚„øYr¥â:DCGÑ i]—.ZŒZv~iÂX-ð¶ëÀlv©!öU°°…²‹Sˆä%k‘1­ «G5&äK^@©ïPœÅŒ\±&½ÛSWd©ÈEîFúÙn¢ÆÁ)a¸ðC a”ŠNQ¡—Ì›a C¸á@Ðãõ2%( fñÂS´BœDrLíç;ÀO;<"c{ÞÖkÇû7Ù³X¦è3BwvÏ4]¸úùõ„c`Jß¹ÓÉKÁuo£zi§%ÎøCEQ4 D“¼šÈMó³M·ŽÍ6F1uˤAºò ÔCBÞâ¶bbg®½B—Ö¡¡ ÿ á!aÈ#À§” ü\Ès¶æw_?|ã#^Þ„Ç­Ñ p:g"ZÅÕ‹É\tÁÚ.»ÎîÃXUï­`>Íñ430áÌh"`ŒvsKÚ¸÷ÊÐ[§ñÊ=ïº}°àÅûÙdy¨Ô±}ðˆ/º¯2µ:ôxÔ=e«‘ªa;Ò¡ùÜN±¤ƒåý>ü³„Ù‹Tù,Unß3GO.[æqçìÞDB;$,Üè­£{,;‡Š¢·D ³‰óœªåK£Þ¯¬bŠNeî×ÍR )÷ö¯b KÙräSLò¢!+”ãjÌ^¹‡Ùo™é*Ë/5ö­u‡Hž}ÞBÈPTJÍà£ã–¶ïÍÐ[j]ÌpŒë·nÒüíiR:DÉæ7¹ölŽß~Te©·®t(ôqSðÎÍxGUÏWÂc_ì×^f„q\Í Ãâ]?—ÐbÕâo£¾oFØÃì]DŽ8¤d¾¦¸¼þʇ+ë8eî4$]MÆ@3£Ø³É[îO‚’’íæ)ßMðúÖv!ÙŸ©îŸî²¼øGý¼{ð?nðI“â¶V>z¬µÛå°A…ñḭïú—±C2ȯ}B¨7=äÊE®þìõ.‹ßúZh6_ âGBz¿1XN)­ÞŠázA÷òÓ|óÌùúþyfCDÁ É0Ïßsåº|ÞžN½Ö,)Û-·…íB!ð1v*h®X?i-…tŒÊL²C ÿ YФŠÀŸù(U†BÈq·@ÈÍXîUnF€4‰ò«"túL½€®ñг[1;7Íè­“2^zÝ‚_ f.eô†yé,yKõÐÛ°jt—Æ5›vw?üî™ôE‚9Ò†²+U·VnX‘å;_ô¢~Lj%ät=4±Âä|4®Ž¼ïný?òó³¿ò£³¯ Ã6µ•FÊ®lš#dqÑ8fˆ£¨¥ÈœÀ‹l…M]a6hêà6çãÕ´àaè®FîÊÒâeŸr67|2ŸÃnª¦ÁOVˆ#Û¦#¦é™Ž žy× Uà±ó¨PÇK4- HVg·`|Èìæµäœàµ_ˆØ¨n‰Æ{«‡å:9÷Ý3SÚvb©ÂË’7¾}Ð.‡Ï»w==@yªylþÚ×·Œ¼Ì ôëèøÜ/Ô ôèŒù™ŸL.ð5¿ASÜs®Öÿçž¾-s‚X ’¶¢ Áûo†ûVæ<=NÒr+ônERĨrì¯swçxÕô)ƒ®–#)ðk?÷oTQöîU8;ü¤ýšŠ!ÕÝÜ]ép2 £ƒz¦0Q ÄpÖ"§…Ê‘w~QÛ‰œ¦¨&½- qp€!÷¿Åôž©Œé7oöÈ1{¯fÿ+7ÜQ7‰Ñ¿“=³Í»ÎòÍÎÍ>©‰O”´²ÄŠr SÏF¢½ŸZçU¢ 2Á'³¾p „¤AŃWgîRºc~hEÐbQr¹œIJÀˆó A–>sK¶ 2“„´ÿþ°êY ßÄ­¥ù )°V¨hÇ®’€•ýX¶ì© Ó²ç¼æ ýyÞpöÚ~±ãc0®ÎPôàÇÇ¡^”®^%š—î¼”JúÝq±•A7¯å]î:üŽf¿8—Wú›„±p&?v-J3ú¶:»”+ÅÞÊNÎWùyƤdÙ/Þºº$)tcbVùúØ?6 ¤/ VYÔ) ú†#ùëWD—T¦¹xš¯¨v82Îàˆ ßaýöVÃVã¹âîѾ_4ö|SºÅLykbÏíªÕç‰âM4+€+hð¡ksi~¤¿Û«µ$sJv¯6±.œŠŸv( ¾ôA­×QÞ~)ïþÊ›0T™Ý~]Ú(AÙ«qUÆ›0ãG €0¤LOh”™”‹ðvñÏù©ŸkƒmÖ‘Ú½Å9]4,Á lx‹Öžœˆn„I(¯ÌFGÛK¾ ÐÈ?Du©Yœò6µ;g©4øO•=’ýJ=&ˆýÅ‘Ñð²d½•Ci½[M´àYèŸÙBIzŠOΤGÀ™ûd˜ù¹¬³Ë°7FWî¦yeAýK´*Ä·ŸI¼ìa †Ü0ÚSGcjÙkÐôÅ ²ªz»Þ1®8ŸÚýÒ¿ «e®ƒVô3 Mq„'È+ø”öX'„§:IóúöÔIÌz+’ˉœÞ/ˆ_å£2IÌýü®ê9uÌtè ¶Õù’*ÜûQé ÌS¢s_K‹] ZlÓDž³)+g.ݯIF Pa %nWlùO"c{°"°x_¾½ ¬ äÓc†£ÉzBGʰ ÃÈ,q±ˆ\C·Q/Ã¥Ÿu‘¯©2F¿®>ÑuÏßÀ(uIÔjÞ5[Ãk?E5_èçnöºË×bø„Ì1Yµ’ZªPò© Ï`KÝd;ìÁÕVg–vXŽqfEPbî ]—ˆÑGp5G°áا`$õA¿@Eq‡_T R4ØÅqI°´4ðÅAU~Šcÿv‡×Ö3#ùåzÒIy1{ä>¥†ê±.)žË ö¬€Ô¼øž+Ào%ô²OʲÄÈa\‡—Å=癊Ǣ8ÙÇàÑlbäÍ4š/€ÃxÓô†X;™Žhæb ‚ek–D«ý“;i^NCÖ¥vÔ¢hÅ>ÏF ®IëÝ¥ü*èºÕMyY·D"þÒÂ/ˆJf2‘{–ŸÈóFïK‡¨2†‘(¢áè­ÝÛJz2—‘˜©æò­6–-ÜATý¤’Á1©Oè§²”¦QýßT~Û_дî]øà¯Î"€ŒÕ%X¤Þus” ìë—ÜÉÊÜK)‘œ ewÊv~oºdÅ›IùÆÚñø†hd—(¨/ÌBþg‘#Ë—²y`ØM7y£ÄØå°¾ÚÌzUsxS¼Ñϲ¥o4)pLô[‡¬öõ–ÜäS4PëIÜã42!6D³^‰Øn= #0–:5^F!nŠÅf’$<òPÆx ›¡ù¾ÚÎrÛ¯Žë—Î%Ùö´¿¥Ä|èaèø1h¢¥Ä:––„CÎ2{ ”(µ2XðÞàâxÌsâq­€új×ø¡€#t”H%S/׬<'_›Ð}óëÅ'ÿmã”/ç…•ÂŒ%Ò <¥ß_Gñå­¨_ ,¼| .Åœ¹¼á8•©ß"pÉ4U¾+m·Éýôi¿ê`9“;ELÝ‹$<ñÊqÔOG^¡&6j˜ús¶£´øvMå䋪ÚÄ=f0œCz0# VTÞ%žùô·3nM¬¼PwÌ\éÞŸÍ.™®—+kŠüDÚé_¾Ð‰Î#ôoCâx!Du˜KG¦¼˜à™pÌTÍ2—^ލÖ*°‹n®ba2-ë[}R‚„·»¢f§žC$Cf¯ÝMVh#P-¥¾Êov‘4?@ˆ-J¿àí¡§)Äc±²>݈#:·n‰Ì20u¿MHžB4é5òB[Á¡y¿Ÿ°æšUB¼8T'>ø®Ÿ3|"UGº/÷e;œ\ø-Ì·ôJß°Ù¬Ú ý­øŸ#ôÊ¢ þzÂs‹tòé[[¿J¤1`L)%* <•¹ìÞ}ÿ²»õýÙð¹‡2©*<ÃFgñMéŽÅE[WSæ/¯TÅ*gf³µ´k¦4x$Cw|Ò§xdÎI›ÏÁÛE¤îÕ²¨³l‹Ûêο†Ž4‡‰3 ÔòÞ+bóØÕ³í;¼s±:ô \æ§H^ DÜ&nFr”|ÅÖr&ȳêN'·V¤‹{¨þí|ˆÐ£Üž2³½"; ¶‡J·½i켜Ï]U4âB³Šž +âÞ6`oºL¼ïÕ¯ê>D÷¼½|whR±‹j¡ÖÃâì×É„Ä(Zžwv?/~/¶l’ÿP†’j ™?@‘•tâíš/lȺ‡E’ LEO•¿`çÀ >ÞÐbø0ÆÚ¬|3®7ç vEò\¯E‘˜¨H·î¯5¯…e¨rß‘×$ià×›¾QÛ¾âz—‰°h™]õ–µU …€(çèeðÝl0ëk‰,UЩ÷À¯‰©ÉH–‡}¶-=‰i‰‹i“Í®LHf·DiEB,7ܦ‹¯5¥ènfqîók‚¬i~Ï“HAæêÏ š3¶öŽö¯ <ø†D’˜†¬ «ÝjVfàqUÉÓ£HDSa Öì¸!·ÓGUMx8öåñôxÎ,]7¼¶tý‰Ðª}Œ¦Þ¦žd*|*¢íkßyA ±Ètqu¶“CÉyJ?øcqž±›´ UœÅq ñˆ9ÚƒTC¯³wuì±÷b3q¹e|ÐVf±#>ÝÃn…÷ÿŒàÄÜ þŒ2}"/tÚ€`f7ãú†œ1µUÓÈïa-O?‚ÈRâæKzr÷˜û]{-VÚÄ:ÄDBÞió¶‘6Mñ¡ƒ þw­#hÔ™iaJ,mOÁö‘.*'¬£UÀ$ÍÞ'}ÂTßÈäÂü/–,5‡»D?âïÒÑXQÅj×VçUø<œFÔrõ;ÛR…êglX§ˆáå›ö±4"s)Α ŸB†°˜Î¢L~¹6%c`òw:sr$2»A ¥|ª&®ªSV‘vñ¼¶ãF‰]–™Þl7Ñ@¤Ã%=ÉË&X{ˆøäuù3„Hú =×G¦Þ¿ŸŠ^ÂísúßC'jõ$‚'†#«Àåb(1æâ™Ì'è›W#_±bÌ8ºCݳ҇–ê7v‚_Üx‰1–˜ Ù»Z:û(mPöðOq¡’w‰ŸËú=v Dm½nû'M‘‡ý°jëô¶Îh8c·?ž¾uÈiµãûLÁœX;’™& ù´Ä© ƒ\] ùaˆ–[zKã2˜xŠ|Gg^÷M®AxÒª¬¼QæsvT2—ûZF÷R˜É|žZYû…ÝbÉÛc;ÒcMr¢èÃd‰QÊ¥“K+è~³0&4ËæA¯ì<–\~¯¹Šîˆr¹ÃL1QEH§oìöK†½P ïz¿6EX«Ý¥Äý|d…¶Xåÿ:zK™GY=ذ"A°7)x4þ\ÃýÖtîñðÍ{1˜ØùÄìÆ ](=N+õ ÔÕ&•·I2væ·Y‚þL×áøÝÐb A‚Ÿ%‰!ür\æà¾å¸¯QÀ(9@9z|‘}øLN¡œÝœðÐ…ʽ gµÁ=xñ™…H‘¡Ê4å¼}çÀ€:Ó^IvW.kĹy§Ç¾<¥nŽûë—·îyõH±ƒ§íö$8X‘¾=}ÆE7 EüÍê N.KÎiŸÔ^ê`Nå¸î½=ÇR‡}x‘ñJº“¾(˜Áïê÷ï¤Ûߘ3ZÆT¶O·•U!P(æ/c(’ìÓ›‹¼9|±†æ“ÇêK¬Fñ+\ÂÀîSÞÅÊ£w”~„:§÷q]ÎëUà*5Óo ´§¢8èüÂÛñQ5N5}Ò0®eª׆¹[¸–†©¯ÄUZ/éÚ§!DÓVëÕÑßán=² ÁpÒd¸·"ã5Ä,g R½ÀU@X²2ÍVfЭ=bÆÀº)fGô¼ˆt0mט¢89J&¾Òq#HaŽu­J<Œqö…ÚÇõCSK¿ò:“ó,¢þœùÓ†Ÿè·™‡5\_^™‡—ýKžëZ³âÚ²$Er¬Ã+­ÛÔ×þ.åQüY«ÝQäøè+Ÿé*7c¨mÕz”¸E¿šÏÜç÷¨Õ¢³HÕûÌ%Ú:£š8æCw[Ã)*P[#Ê|íÒ_2ƒ¬øL…tƜDŽôoDa)+vœáËÉ@q“ñ¬y4‚Öñ’o2‡Ä1É·?FêQ*…Ù1m“ù:Ýcw›éäøÆRL5#Þ_Ή8v²ÓúC/}þ˜çwÐ$Ç´TÁìWcæt]É–î}óÒÜÝ¡Õd^¥,m¨â«8¥Ÿ™#êk2Óß±yÔɆ„r—µwéå'ò…Të¤-òV/ˆ(Ñ7ç&ƒâUõÕ­è~ÝÃc:‡×ijñRÏ{À1ˆFÆbÙ/r†zV­©Àä¡É¨m>¯GÑ ‰œuPñ󭆆pj?gq&¡Ô8ïòE„aG}+=ßÃg ÓS±ï%xƨd‹áæ- •úÌ¢™³B¥ àÐ5$Ç}/c2JÛ”Ù÷BEìS1Ÿòj/Âtñ#G`#ûµ€Põ*åÃÙ˜üÌŒéYÇF<¤ºš® 4¯GJ[8¢¬…Ozº1úë|$K\­‚A¼òhvuB­Šo2:HmþlÁZ—82ù4¹ÚžÞ 3¥Î¯ue§'Ž )¹…= Z©Yh¥Ÿò–+ùRžº#lÍRôàç-ÅRŽ®A˜d×úßà}ªZ]ÌéQdÍw&Ÿцh ñt†¸7YË6TS+~gÕoÒ’Ö* Iz‘D¿ -¼õàL|›L0¶±ÒÑO 2ò&««S@èKž ±&¡5Ô¢£Úx¤Ý[™lÉ€þù! ðödßÇ¡‰%éP¬âɼªÖí“ëöêzHøŠEæÄ­ý{ª‰¦Ô5šcXá”_a$K]QRQ2©jlŦ¸y$/\º÷Ý|n8|À¸¹nŒ­úùŒ *·ÎËVnÅRÏ­i\v·ý|±=]L¶Š89¢H]Bkúo¥¡o¿F‘X›Ñuˆj%3À4òÁ®…ÐÅŸº.«Ë¼á(˜œF·Õy‹–bps€» ƒhM p0‹G{W$G[8ºûðs{üÀœéX¯ªËLåÿ¥µM]¤¼§ƒôxÝ $ñÇY G\ K*×ó.,ÒÐqÍ&×RœQçRJ…ýjþ“çÎñ½H„í˜ï9•ZØRýUý79í,JI=‚ãÞþžˆþQïq’û—½ú‡1g†“NW2èÅ8S²Œ å.¥]Ü¥Ð?’%fi¨h,ŠkcΆ]0´Õ#7À¿àcA`È)·"g =æl³K."Åö] ‚v‡‚ ¿ MàÅ;*x™@¥ò®¤wŠÏÚ9PI«ê]oyÒT4úÔãUâcùxA &aqóÕŸ›éJmOWµé@4£T"âk’ÐY-8…ÿK3ì“L¶§t`ý&ØVjGT+·é"ÁµKTx5NùTc…4dôØ)ÙNˆcRxA²ÜY‰Ú8kWs§³Õp®1\"F½Ë˜$ì0Ö9ÉÎp›}ÂJvÐÄèc× «>rógw²Î¹¥¶³8ÉØ(^nÏ#ž½ŽQŽƒ¦ª@H#Ê¿äxþÀYˆBgn7Ÿ¶ï¾Ý%÷£µÏ{Åd³ÃI®Ô§Û„UOÒŽðu#•JèïÅÁÿjFËêÉôPWgúýF†Ym¯¢}w]s¤ƒµ÷D¨yÿÆrÀÕKpω÷ÈX4F÷Râ+‡NÊd¬A.g<__uÂã»!ƒO‘›mØäºßv×W {ðh?;b=—OKõ_ë²\å•9ñÞfk%Më´½P˜Óâzb¯–º?bÄ@¸vµù{ÉÁ^•çlòµ “8=÷’ÍjË¢O¾ƒÁ>¥Wï‡íeC¿W–™\ÓÚ©+L(Ñ!¸t“Dƒãïåé-À’a 7bÅ}þ·}7m˜ü´IRìm.Í©Sæ_ÍÇ9v†Ãu÷36ê)… g[}ÞÊÓ·BdAÛð³Â9Ÿ ÍrÝQÊi¡Ç“Tuj) ¢ß­~ZSj˜¤\j1Z[¨b;⦧œb-µi‡ø³ÚR#׃TXöÈ þ2Ò¯B…"{=ÑWÿO‚}ùQî@ÿ0(,‰§6üÈÛËôãÛPQ‹ PΤ¾ÄÈšuõ僙'›“#Lé Ë}Û€}ê.ádT-*‘» PƒÈ¥ÙHuÐï”<šHç¼^-­« N]ýʇ³^éÉboÆ@Y%ÝRù óWxu‹˜\v‡È._Kz$O¯ônE\ÿWÆ´¿ÑB ²a53X:_7c²f º·bÖ´–z 2ßy%¸Œ.&}agOž| ºô|î¦ ¿•Ê•¤e¯A¿j•íM}Jß\×å£#‡Îôµ¼¹(Þ[µ úĉ(¼¡YÑoúíbÝšG>^ ÊvÚ“@šP]¡.$\%ûÉ÷bÎ#íÂà8„ ç›à‰·¬¡âh¾²>&l‡¸²Oì½(•«YUû>t‹ _œÛ2H°¡0K¨'³ZdÖvÎðK3z…{þZȈørGÒÁ¨8‹‹ÒÔþ’Úöñ㤘U÷6®UfîÆx㊪;±?ï8±«ô3¨èX!5ÜS‹¡y»˜”ºA0y\å`:©­ýóÝŸìH™ŸÏfxß¼mqïðñ˜s—6«šìP‰¾X˜Â“&­| Ê3jO”®bô)­°<Ä Ì5FO\‘$\ÀMÊ9Rª­P-õÔ#þ~Ü{†€âïî®Éøâ“3Gxœpƒrþíì Lî5N}<òȹ|!™ÇuaHð\ªuÎYD–Ö¥k Æ?–…íÞÕÔÛíãŒXÔM V(P‘œŒŽéä—)„' §¥œñ¹nNy^JiÏ"}’—çµE"vCÍØ “,Îùë”ÜxÑõ\\EZpcmÃ[ yÏ& µô)ì ‘I§ŗÁ_ßÛz î£yѱÅ) Ùw*^à^í¬‘Ðj“_œÜ7ä[Ë—Üâô¢Ø¦KI8ö’‚³3‹YúÓéåÚ>eNìø’2³KØÑ¦l(òh»)Ò;íá¿g,?éã¼ð#7tT›Ò°+có 7CE¾?•¦ñª°{ðàA%:Òþb ¨)÷6£ljW‘èw Ú=éèûx© ºn°W.ðm½ÑŠJ¹Ñˆ„sZj‚˜…Œ.à—G}Sbg Û3î’À Åe •èŠ6»Ç:ZØM¨0…E]ÛÓÙ dÀ€âúès!(™ôµý$LîtLëw*am½0‹év ¦Ù—Òûô1¦®FS‘ˆú¸¶¬®¿è/ŒÏ* è÷Ù¹¢’8ø¿Âý‚`ÏÆÍ F²ßÀ{ö³¾ÜGáÑ¬ÊÆ¸˜RÆ—+p¶8H¸‰î8‹yÏ’¼Üßþ%È» }?)Y™O'¯>£3 Yôçë› ðKßO–KgÁ<…Á‚WÕ’¿ï<€ʘ©s”ªí¨R+мS9Õ)×JvsÆÑ|=ÚÙ)5ùÍÀ^ñWÁ¥öUààÃVæ ½`«ðž‰ °IA 1³ýº ÕOµ?ø—hâW±RÀFÉPþ¤àî–tÐ. Ò3ö" rÛ;äç¹Ï{Q=•QÐÝr4¿%2@1â¿{­÷庣:Ò&lÚ»ŒHúE¤]: ô0D,Œ ms·BsNAq ¦Á«÷mK”þì¬i`ÇÑ;–H¿Äo”ù`DF endstream endobj 321 0 obj << /Length1 1392 /Length2 5960 /Length3 0 /Length 6901 /Filter /FlateDecode >> stream xÚwT”íÖ6R H‡ÀC7 ‚¤tK× 1ÌÐ% ‚ Ý’JI Hƒ ˆ’R"Ýâ7úúžsÞóÿk}ßšµfž{ïkï}_{ïëYkX´õxdmáÖ%8 ÉÃÏ ’ä5ôôøA$È  à±°èC‘οíx,w“ø„¼;ŒDÙÀHPT=œ~A€_D‚_T@ ñ¿pw @ì µ4xU8 ‚Àc‘‡»ú¸Cí¨:?ì6¿¸¸(÷ïp@Öâµà 0Ò₪hvôà6PÒç)Ø¥HW >>///^° ‚în/ÍÁ xA‘€.q÷„Ø¿(š`Èj¼x,€¾ñ—Cn‡ô»C”Áj!P!0[ˆ;€ª詨Z®Ø_`õ¿ÜÀŸæü¼üÿJ÷'úW"(ìw0ØÆîâ †ù@aö€Ôh)©ó"½‘Üfû vFÀQñ`O0Ôlü¾:P’ÕÀ(†ø!lÜ¡®H/êü‹#߯4¨6+Âlåá..÷ë~ Pwˆ ªï>|†ëƒ{Áüþ>ÙAa¶v¿hØz¸ò=†AÝ< * 0(Þ¿mö$ Ä@‚Ä €xÛ8ðý* ïã ùíäÿeFqðs…»v(¨õƒç‡{B¤»$Àï?ÿ<áñó¶P$` ±‡Âðþe†ØýuFÍßê ˜‚PëÇ€~}þõdŽÚ0[8ÌÙçßðß#æS”5R–5àúCù_N99¸7àÇ#Âðƒqqq@TXøgš5àoò¿­Ú`èŸËýGB˜ÿ‹ªyóðü³ìTÃü³‚&µÎ€ýßÛoÙ ¾øÿÏøòÿ[ý_Yþ×íÿï)y8;ÿö³ÿøü`¨³Ïj=(ihÀQý7Ôò—ž5 ¶P—ÿöª Á(‰ÈÂìÿÕH(B ê ±Õ†"mþÚ¢¿ç€Jï …A´áè¯7ÀÃý—%:'Ô[šÖo¥©–T„ÙÀm‰O@X»»ƒ}ð@¨ üøQ*µ…xÿ^n€G¢B½ÀîŽ÷k¦bŸî/Þ?ÒÚx¸»£4÷{ô¨šŸ ñ†ØàMOÂm$ÃkÂZÏ«ei¼xV>b/,µE'÷F #Y¿äù9¨ßÎx4ê&ge[A9˜ª=U12éOù{>ìmÖ™<Ÿ¢œ‹DSì]–Ûçɸ8ê´‡ÐÙ©í?‰¦F/ßÛKÔ¡%´2Å4eK2œ¼í\«\-üцX3ß\€âS"†dœlNÛzŒ1óòƒ±Q<±»iš‡¾ÊãO?Ðc ñgr­±T>˦ñé¾~íÏêëM<,P뮩ˆ ¡"õUeÈ|þžŠ,1KµÆ*'|*_–$¸7Þ–7ø{tûN€µN÷±Nvª'F4Æí·6FÔ[ É»ôêM±8Ôbp%¯Ö¼7„ ÎÌÒ¾éæøš”{C’BÝStlmz…¥ÖÄþOcÇÏúæ±”LÐ_ƒìæÖ#09W„+ ȯýưñÏóçSý—†X}‰üDI¾·7|XYáƖ/L‘ÿèÒñ’޹8,$õ¤2tú=‘¼áš뺸á{ÅèPyQ`£!!ó–ðµÎ-~ƒ,:èÈpÛ( ÙݾßwQ,(’F[óâÎ} …ûëíb»›eùÞâãAŠùÇH ¿-<ÿÛ®´üÍó6 ç¾O…O¨“,².•žÄ D[{“W×l½|h¹ü0Í×>œ|>dÚ|þ ÄÊ}gÄúÖ\«nåc°øÜÔ{viÊÈÕÞÁ±QZ]Ãrº°F‰µøãFÎ i±}|ùª„`*ú+ZýHdU=Ç.Í8ó·Ìïö›ùÑÁöÐã\˜“çó]žV{G¼Ê‚ïN!â ƒ'ãQX®»²É,V\ÁýI~/B#œ¦5ç-»äw-6sê âê;Z˜‹¡–4¥86;6W‡Ô}Z3yõ÷ýŽZÓ?{8V?:øÜváÊnuËÿÊóVJ°Z-õöMêàÆ¤ã'¥pÙ4® ×!ƒ)νÚN«wzáÒþ 6ÛÆä›[žw?¢?]æájóú6=³îQKÖkkʰ¬Ó8¸HJÚNðo•D+®Gk }Õå¨ZZ·î´óгÈ6XBHÏɹ1š$„[Üq‰K 9ŠûBãùaV‰uÃ`ÎXŒÖ1°Ï×Kæ¤õå&(`¯+hî˜I‘2‡©Ÿ|Ã’!™ê* #k¨æ&z*BZç˜kG5#£u›³ZÄ÷Y¤áØ%c7LG2©2"m…¦PÝQeëÔÜ®¢ëÞ •EiŠ„NÉ8M:ë‘ô±¦^M<úÓÚQ³œGÆiÜÇ/óÄÀ¡Ì´OœAsxêÃG#?^úadEŠÙ™º#ЬÐ>ôG xÞ¯1£ß9ݧ~ñ½5÷ÔºžÊ0GÃ@oáÀófqIDä@ðx_~[Š'z¾|GYK¦³r¯µŠ ©‹íªp3¿š¶°–ruÝT´ãO¾½¸Ùýã‚îÈÞîzKMX]£sÛEkÆm­h#HÂ¥’M›ŽÉÈì|´lvÕùÜHaõ±ù2¢Cþ1@vYíÓ@±ÁLL2Ô_ÚA²%B눂ˆ4 ®)æë†e_î ឯH„‘R÷Ôe³jaPH@§ÄF9q¤1)ÖüÞõøâÏò»³n½ÒD–zŒ–ŽñþãpªÎ¯jzIEÑõ®Åw¨CùNÅÄ´´^HÈ×sn™=Ž"H7h ŽáóŒô%hÍÙ÷5';¦àI%Ù?_ïs×Q,%»ËP"=³!«¨{ýú;!Ö{×ûáó¯МT6m(ˆF÷^è‘-¼ &U+›lYBšÉËà–üÊIB@û·Ã¾hð²† Ï Ò\5šãµãTìöÅQÞXæ™Eý*”ºç©‘l2'ÖWD•“øýÄ’™àä\É<57º¤´cqûݟ•8Ò2=c)!ÃH û“7¢Þéîwe–aRÂì–/qͽxUòޏ)é lsÔ P»wIR–¢s #Yh>=å–õñlmZzQŒê“ùl‡¸´v8eZŽm{Õ(Õë:¹AU§Œ/Ü? M™–ÐeIÏa;—¤ç'ÙÏ3‡Ø×>ôØÆ·ô~žmJð1Ç¢¶V'ÅØŽ¤Þ­HSš”ìÕ¢Oj†T)üÈ#Ñ7C°¶¯¡öÒôyß$¬2ƒ×]éæk¥I‹ÝÚ»å}na9׉f ZùæÔöj’OŸîš_E|<¢p.ü¦ŸHÛQÍP¯²g¯xºå†·ò=ôýmšYЃz’\øB%)Ü›¡+†«œ»ŠesÃ¥/…QÓ˜’á ’Da1Ç{8Tš¸IØu/‹I–(ä0#ÂÕ1úöËp›§: ˆî¸ìðæèl>O|ÆTÞLó*ÚdD„#Ÿ–¤‡l\!Fª‚wæbØãZ—(Tójœ ^t®•šxOÓ§êáP&¥¡©HW$Émhæöþæ3Ä£3’ŸÉáÏ‹ÈÜâå >BžºX¹KˆÑè =9ó½ÿz8Ã`›g(×âìÜ38ßýmÂv>³Xü.¥©O‚0BOû¡ÁV_PŠ© §îîâzhú‚­Ý­o;]2FqX{kqQ ãWwëÆd«7™{k>îNÅLÞí˜opv/ŸóD¼æH²Ô\ß¿¨Å樘ÐnG¨™µ‰^lVð-)@p¨²¨¼¤[¿3±Ò+tÚÊvî„ʣƭܽÊ0uÌ‚ŸK–“ý3Ç¢!>¬×hÄzJ]úhEǧ‡è‚«Ê\ÕD±´{Hì“AÜx'‚º;ž Û©Ó¨"ç’M¾6©BäØ×»ö$ìˆØÕgDé«íhnxœý€Ã /ëÜØªúë×aL÷®znqr‹¨õºÚ'ÈŒiIÄg7æÉAæ•ÆðX}’N=Œ„[´mØÈ(7ŠaÑÃó-~Ωö˜ÊžxŒMáFÎvä+U²ÓÊÂÐí£ ªwoZ¶ñ, `Xo‡ö3ãk·kX^O¢A4DhÇ’Óª `CïI¯³,_ Ø¡®—UUÂ+ ;9CÏQü˜³öt³›Z¡ËÖÔ)RŽ_w( n}^Ér ÏäÞ(Ÿ°pÖóƒäñô¤tn”â÷dõ¯ë~R(‚ŸJL¾]6"xEôÖ.ÒxÃÍqX±"@ϪªWN”Ôß>OØNóZu„%úàÚ[ ²¡€²ê ÍOI"NŽ¡7˜mã³-‹”—€ÒʰSÚd1~w[ÿ …Ñ‹Ï:/ Tf²­²(È µsk}ï•}­F'm*”_?r½¾« ]8¥ŸežË•ÒãJùÙtÕëK@Ò@B·_jð±U—›]t~¾kwÓ¾à|2ËÝp-.È® J8@ôdŽ(íuµ”Ùøi½Ê<»Å®be¦’â9¦‹/ó¼^9ǨH8<ë÷Ô¹÷jònÙyqv¼ÂÞ~í]ê¡’Üî k{ʵÑ?¢OJ\û4eB¯¦‘k›>Dƒ—ófz=> MÀ$?=s˜o¢PÓüˆ¡ºügŸe»¬I°Ck¡4“ª4P«)ew+‰ Æ»i) o¾ÈÝeâ}¯ømÂÍݘrqϬãý{ÌÚ‚®ê§¿)mÕf¤ê™Æ©r›.Íñι”q›Kò_*[˜×°&ÏGø¾åXY0’Ü1¡1c Vºa^âë!›H•¡Ž}>Oíª5ÍBß6;е‹øáâûúتÂõ²¦ŸXxÞÎ<λU¿fÐ,]–Ú–øE8k7?â×Åx_te}Éð®4ÝYzbGÌÄçÐAœ¥¥¸ƒ 䩺ÔäF,7×}ÿâÑZRºWµïâ°M?7HÈʨtÂÍ“UGß'kX§ù#×4´4qLuåˆÜƒ1Â>Ÿ ÙVßôÌkä ^¼OîW\Å 4€Z“|Æ‚¨B°ï> ¤¸N¦?p íÇ„ËQ³’rø­“êan c„ñC¾ç¡§öìB•ÅÀëLŠ@FºC%XP<ü ]¦£8·Ÿá–î×Í”@ª”ÐÄÌÃï¹›=e˜;dÌkƒ¶!w û9{—ç ˆ÷°ôb›¿Ã`ÿÝËÙ•)î$Pѽ!›s^ëâËß/Wâ,ðæÕ&þ<Ú¡üžû¾TŠy¢øê}í€u<õÈÝ< +à­ÐiNïxnò+'Kol 7¯"IwÞ™¹ÆðU¶—Ž,çwUëÈæÛÉŸRtî„|ÊÊš?Om•IzIEØæ'#ŠÏ"D”yɸü¦èžþfÉ÷G-¯%v“Ñ`S7­IòñTêSAêдںž“’ùlÉÞr^W†7y+‰{ÇQÒd¸ÎA­*Z¾ŸÑûÆ9Ô_’”'0yÍóSÓ/6u«´x¤¨¿‘œ9ÍK·‰¶<žÒogqzñ¥>$¤˜ôØÄÙÒÒ°ú šo8tGf©é¾‰ñJÚ€¢´œÂ„¹ÌÀ–xfˆÀ¼º}mªe<1ÉÝ%çö1*ƒ¸iúõü8™]c@)íµÎõéĈ¬mMÚ ~ݰzIù{ ¦ä©!CéºÙʾæK›ó¨=÷•á\_9Û}`]¿+M‡êd Rö² r Jvî‹ù>a€4§¿@”Óxâk =ƒœ’KNto2{r½BÓ­î7Æ&_oI‘O9Nï˜G•iMŸUñÝbç RÛZMïweê"m?BÀ¢¼T\ˆy\ÑëÂ}RÔ%IL±íî‘l:‹ÔUjTÇÚët„éƒmqxªF¼<Û.d¾‡ß¦^|lh/¹×þôÓá÷¬éNƒ`/zIG´…‰ùï,ÞR§*S¤ž78)Éõ±@G¯SÅÃ.Ýs»'lU­6Û»ÛÆ=[˜ßœËÑ9+¹ßü|yÜ…ƒ Ò‰Á} ˜ÛVyÂ{ó¨3y=‘`ðTˆŽÎ9ˆ,_õ¢³li¦ÒÎ0Yý‰ïó8VÓ!° cÆœž>žŒC›ç«„90`fJ¿…; åLàæ’e²Ñ;ÖÄ>Å7be×ã*Žû3zJÚB#Ì÷"erùÃ,øÕãzyánüÜU|Óˆ ùÈ®wD1^4<Ï€ëù69B®Cƒ6^Ù™Ý9MÕ>b©›O}m§‰räzÞ©ÔN´—Ôv¢ºe¬^ 3Ñ 3-á‚Á‘Š_+DüI=_æKëŽ$]ú M”ÁŸÚŸ_Ý ó:ÜPvÇWÍŽ Á¼ìY$Óú"!°œcšå 4êöh™¼oÌšš†TÞQSÑmÄA¼G‘3£Ã¥Ž=ú ÁÍPÿœ`¶j¦œAA ï±ÒnrîúYþõêêÔ×];‹ŠP·*z¾­Ì8ÞûM"Ïhà"—hû˜>¦^£›­hæ©TŒño‚:FÊ“¼Ÿ®Üf+;¾wÐZ8L ¤§NˆÍ,ËF³ü<^¯Õd)-ha¬¯¹Åv„»Ê£Ã1q5»¸0UÆ.}Ñ,­à^ÊŸ¸J좩Át„zË~9¢Ð˳Îÿ™ÔN·½U«wº6q»è'Ý„2›ºª¤ž1y†@6ã‘{U`Ûáv¹A³ïŸ¿?†W`‹Í°ù(7F5ú-+Ø×Þ©Û5†n3“â”ÊqóbV„e7q†'@-Ëg#ÔuG—0Å‚æë”Hú³ñdóùö¢3B6«ð¶Î ‰ëÍúâVšÀO¯ÞÃÜ?~ÂÝJy|ÞÑXò“^N°A9D¨ˆ~–ÙýìCÈ£ òIHe>¾ôkεº÷OóÉíς̖X?<9d纎ö^UÑ¢ÅS|§wÜEt3 4³TdÐ>{Aâ1ÌÒÈz€c3h¤v?Iç±ro§g¸Xìîabõ«ý§¯#5-ú¿ƒY¨Ò¿) žÔ@¥Ê%µJAšõ*ãw®Låä\T¤Ž›öM0—:ë.?Öv=V œ:yIÓ/ïd÷¬Í’ € & /¾ ÑÐÇAw5ÇÅgøhˆ­ð»–ЦF'º|*»¾zð–Hƒ§màixÉ‚¸°GLI÷^cÊ•ËúªÏð¸þÊU-ÃŽ¨)½%µm‘®/‰ÌšvÛ¦Rük„‰§ ¤ž;ûñ@äÔÖ6fæô.Û,·«Â¬6&êš©¼ÝïðæêÒDŽ$UV)J}Ëh¡tºŒÊ‹ÆwLG¢&õÊD~ÌXÄXmÊló0Õ:óÛÇ •bç8 VOKàŠ±^²Þ?YðxG]lïëÇ•¢p^”®¶Üv.ÖêØ1ê¶y† mÒ´½³·o·llÍ´õöu}Ù¦âqö0 4’°m‚®‚·“&ß>áü´À¦è3[Ó[e©ÑûcúMâ$ö—ÍòƒÛ›}EæîvÜÒò|þ 2˸}ðæBïÈ»ÅKù¼GDù=3,u?íMǨnxÔ‚PÙ9%ëéÜÖ'g'É%¤Ï(&ØžpÐè‘Èhm˜Íê6 bÉ}(ÚøW$ÄKW«‘˜Ú9‹ItSFÔ—w«í»ÉÖ%‰²a3?µ+}vp2-HÁq§:¿µ0,7­•w2Åÿ`´7Ú9Þ—x,øCƒEêâ\.-’§ýÛrß%þÇ“°}s3kwù•ó¥¥oA–-éSØ…ìÊû?ŸÒüèWu.CG”¾ Uâ«)“Pt«yûcáØ¯> ·× {#”n™ö/èY¾©ƒYæë®Àüï^ugŸïUtv •_õZÞßÚoÑ»1¯½oÒ9>µ~i1¨ÂJðhV #Úˆrrj:zºÄlÍD‡ì RŸqò2&\3êAªÀ©BL¹aØhô©'~’/èE³o{Aº°±‰M—-þŒÄ¶h¦×@æÌ:bøË†}ÐWœ¨sƒ8mLXx8íï0Y–:‹t¯¼vNŽßì/ÔÃä6»ÔœÇt"¶Õ´Í^œã÷péTÚ–6?ëvû,dÅÜgü,­«C_é¸#)"ãõ%”ø}˜Æ£*ñ&”¥û–ƒžsÄ—)OÇ÷ÕQ'.)ä{‰ƒNLö¸ƒ˜·ÙnË%ÿ$QÛºUP[s‹¢¼uäªO¸M*Å~“„øÍ»¥ŒØ!Rú];ïf C†PŒÊ•à˜FÄëð§hâLƒ%—I9 u[mN0ûCÇ~±GGøz¸Ž’Û©iâÁr¾cëK\«}õxð|7ày3–&Û Kí»¡¤Æ36ÖÂH B"6^-Q[„‡>€oöñ•7ÝVï FØÜŹÈ|ãd¤H¹þÏ Lé·Ns±vv¥ËéµX×Ä%+¯*ˆpMƒ Þ¶OÈqrœ äTY¾õ¢ä ‰°³ªÿ[Ù[b endstream endobj 323 0 obj << /Length1 1431 /Length2 6224 /Length3 0 /Length 7197 /Filter /FlateDecode >> stream xÚxT“ÛÒ6ÒE:ÒÒkÒ{ïDJH@H„Ò«ô&A:* E:J.¢ MºTô‹Ͻ÷Üÿ_ëûVÖJÞ=óÌÌ~ö<³“Nc3(Ú ¦‰FaE@¢@Y€š™ %D@q2s ûÛNÆc óÄ Ð(Ùÿ@¨yÂÀXœMŒÅ Ð(€®’€¤dAÒ²@ @”ùˆö”¨ƒ½P€(@‚aÈxÔÐ~žg,®Îß~ˆ$##-ü; âóD@À(€ësÇU„€‘34Ãúý#¿¼ ë!+&æãã# vLj¢=„>¬ À†yzà€_”†`wØj¢d<sæ/‡Žõ{Â8¡0¸/æ ÀU˜éèŒ<`¨¿Àú„ý+ÝŸè_‰¨ßÁ`íîFù!PÎ8 iê‹b}±Â0 ú Fbиx°7;á¿·hª˜À8†øa ž,Fƒ@þâ(ö+ î˜5PP5´»; …ÅýÚŸ:ÂÁ»ŸØŸæº¡Ð>¨€¿Wp ÿEêå!fBÜó‚é¨ÿÁàLdÿ¶9ðI Œ””$»€ùB\Ä~0÷ó€ývþ6ã8x =p XÃ}`ÀÞ0ÖÓ ðŸŽ®È@ Áœ`ÎÙ¿³ãÌ0ø_k\ÿ=¾[ N~ ð×ë_Ov8…AÑ(¤ß¿á¿[,¦e¦g¨£)ô‡ò¿œªªh_@€ˆ¸ @DF @RiiI@Ð?óüëþfÿÛj FüÙÝdÔAÁÑ™¿HàNïo"Þ”Áÿglÿ¬`ˆÆéàÿ·üï%Üèÿ<¿CþÚÿ•å•ÿïHÓ ‰üíçÿ ðÿøÁî¤ßNÏ^XÜl q‚úo¨ì¯6€A^îÿíÕÁ‚q3¢‚rÆé\tKxë/;£‰ð…AXˆË_Zú»¸H fŒÆ ~Ý;¸( ð¿|¸Ñƒ¸áî ®e¿]0Üdý³® ‚†þAqI)ØÓìG†Sn% áf óý-q€˜( Å…pƒp´'ٯƂ€â1'O0†„Á±¿|Ì̵ñ—ýu!^žž¸Ñü-ܦþ^ÿ¾`0_„ln ‘‹p}Ñ~V«Ââ#²6B¼¸Ô›lÓ#‰å}÷(ÀEŸ$Gkòžª#ôéá‡Æ³•Q3,‚_ÎF}ï¾Ê ]ÈÔ.Äâiô­¨î‹ ~;zå c‡¢™Ç¤Æ®Ð쥘°Q9ÚÚò¥YÍ\DJwK¬?û\rÙ‰Y¿#³ p”Psf²`T :·ñØpr/a‡lîR'ÒzÚfy™ëXŒ]â?@$žª¶Ç3}ó[±MÌúøñu^ßC‰Ãb½ž©§QtL×ýu9 †S˜èSòt_`ðxU%OÔ*3’¹˜JÝ£x¥¾O÷·¥ Hx5:ª…^3ºÿ¦É«-9£PнpÈê°škþMŒâFsj¬‹píCnUž(ÞÉPÖ^²°‡@\ß9ÿÓ` ]^qj£ÿ¾)žä~¸„ýçñgŽ 9) q» äíOU¥Œ‘ìÃp«÷ò:f:cCN×%¯á›Â¢_÷!ª­9ÒPÇͯۇº£÷ÑÜ_Øè'C“­;r¶{·R^èHž¼¥±ÔÂÖé½Cw9$$M›·ujÉÝQ–™çJ²” *2§yg®¿Ž—exÕF6R%dŠš’ÎíK%Û³÷O¤Þ …?£5,0~vÛ-H)MzÀö='ñÎéù‹ÑÙ©»è¶0ûwÜ/xã׎íhn#3’V_`Zx#"^‰%//Û äpš¯õ†€)Žð—ž|™¯_bí0ã*’KÚȸð²Ç3‹%S‘<Ì–RU ™/öFÍg›¯>ÍNªk犜8­¤³#  ˆ™èT.œÊzÀšƒ ¼rY z çW¦>MTQV†áí¹ð`¾UmîðZÞ-–0„­®=±|¿::ޮ̱;ÞPš&Çß=tÂ!Ó²\¨¥R~Åxw;”›n¾©—I6Øïršxœ^}•ÌrÚâ)uÚþJ®´þNæFWÿª÷,»Œ¹M"C£vªŸ‡³úà»@š+Ó.(o\vß4ÂîÉÇ\'-5%.ž°@ØÇRκÌ©„áRSã îÏ/Zdv¼ìHÔ¸9»Q å{Ò³ÖÅ"ÒÒDþZOŒ¥Às=×Å?û‘Ü}8²æÎso±>åí±—Çs á£Æ1ôõ9ü'q¹úÚ¥o[õ>5d}%¹W ônbã—Ñ7ÒVZ˜{…ŒÎÁàMü¥£ˆr= Ö’ø’…ï8o¬nü¤kV1XBUúXgMOHÇnÙ{êfhÕhórWsV~C5¨>sÓ­~¾‡dÑt—ÿýô˜½ø,5_åârÇ=¢ /~”j莞z½Sy‹Éd­•þiD‘_>]`ZÒ{oÚ=¡ûÉ%…ì½éÄ·ÏçR ú·ß‰==acØÆÎF\hÃr¢æŒÕ6½ ¿¬siI‘—íP|!),°k©0&¿ŒO \¯å_m±œ>XŒÓªx‚”Óƒ³X]÷_ð,tØUø®ÅÀWuk8ÊÚPÆßu£'£.jÉ_ìC}Óœÿ¤~ψÀ–Xõ+ìý·D¨¾-5v=šâ˜ï˜7© ,E?!©½Ä4Û¬²šÞòª‹ì¬Õ¾,²Å3õÅŒ³EÇ 6<‚Á*“Êàex>nï£o°Ÿiƒ¤I+’\ ã={aÜ@¶Ù¡ Õ=–Jˆ.ZÚXÿ£õÛý}]¥ŠÐŸ®~æ9 ¡=–îŸ.1Ý+ã¬6Ä”r”²7û²5犌?QÛšyŒÚB°X/ö~kJ_VQ9šMp÷¡L|¿çش΃"´kÅ®Þ ¯kQ«èUaâ‘3!'PíÌóò\¤ºþžÉ‰ÐÓ&cú¸ý°ƒO~ܦc‘&²;£Œ/”Ô¼ù}P‚NÌ °S«RäþA yÕß™s&Î<òAöt”a¢3q1ù£ÝÛuäú–±÷_ÿ¼8s§¸ŽRØñ\ßå*sLn«txfòÁ̼êñò¤/‘}ˆ„“Š/é'jžDÀ:9òLàà3k±yÑ.^Ù ¤WXìV]ý&Îõcpu1) èÏX¥õŒm‰ã^실mp¥•É&ÄÔ Ýç-³Ö%ÌÅÝX?`oçcQ©›±}¶i7KØÂÕoj¼ Kõð¨Ñ¬®øZ·å½çi4EI£®•ÐLÀeÂkXv¬e¿v®+´çÈ Ž,è³ÁñGè{dRyÁ©®rBlômÀè«ãïUR{jõ·B­õºñç-›øüçî½Qa{/põådìZý´y{:MOvò¼þè"¥îöÞᦽ:¢âÒ¶l_#Ÿÿ¡Y¼›óàú‚Eôy`.^æMâo’–Û𠋸­{Æ¡A§“ ?ãsp¿gº%{ˆ7092åì‰A«ki‚dlBÎ*!µ¯]«Å%iÔäs¿N“§îeÖ4>œe¥ÝÓ¬`algbMó–ZãðE¹X}`ä.ÌL]”Æ!`«3î‡_t£Ñ ʵuË™¡?ö·T&ƒ%Ê—Mè7»TÙ-ïsïËh·2$»*=°SToäøÕ8PIJœ–j~qžêª¿•¯š½±š»£RQM»ÔqïùØþ0ÇâË…‰[$qìÑ%Éã_@ÏŒá7Þ^}r$Ľ±¦·[ù•çæäøS@š;”{ yuÜ||¬hÍùÚ=v0¤<Šd ´úÉ5i©¦½q–û­ãt ‘¼ßYž¡8d«´¢£O´¬kØPÚƒNÝ즢c-ÀhpFÜdVüù§M檑9,˜8;iš·BÐ>‘m …Gµ|ã‚÷Å` üâh_ÉÃÓNö æÝZÚŸ[sUBéʧ!MòE÷ýøÜw0òÙ›¡2œøå&íï¿®ò•æj5ì-e)Râ÷UŒ¼tµk EIX+êù+Í©ï†(žE^épBQ°%Üct²áWäš»-¸ñ spÄ­ÂOâ ½w†÷r«½ÒM‘¤î³ÜrfWBÞÁ’L¿ } ‘J?TÚóÀ'tŽi)›F”›ÞriÝ…›wâïÆíæÆmwk»†žpo.:¯¡nS#´ÊT>>ú.‘òЃiRó(Íäsv,¡ÓR½˜ÇѕƣG¬æi÷:5'n:ü˜V¡IíBmÓ™¼%ùYì®—Àë/'?ÝU@ê~¸b‹~3ÆÐ°÷ø€OáòžuˆùÔ!Vže:ÞíPŒT©RÜI `x ~ÜR³›±´\|æw“¥Æ‘ç}@ u9g» {ž³èÛr _W­z2íù`OcqÏ;ñÞÙH5Áä1÷9÷s…ëÌŸÂÞå)mA•% ÔvUÌ™”[Ó¬Óx<‚AÚ¬=ÌÙ›¥rjÐÇKYDƒžLµ ë®—…š4ÌÔ]1H 6cW‹ïtYínf«‡áSây94ÅuÓü-ç¹¥× ZÉë#(îõ{ó6Õ ª-®Iâ5éßÁÔû˜{¤0`Ú[ÇjÏŒ ‰ä?­,²xð°Nó«Å™1W›ÞhT”Puû¤M'LšN XÍŸqBŠ€²°äè7È9»‘ȼ¢å·ÑIŽG:>ûúEÎqš~ý³Ê8©¶lóGK6ÚlN ´Æå6í€fŸðS{›‰&Ja²GÜšo3µÕç-™•<Iü&¶\7^àÑTh ëèW&>™;)ÒÒ›5v©¿oØ`ÛL¨3ä°¢FºoÎà¿0 ¿º~U~*3=þ"ôŠã-Ü·²hF—¯ýré#·céUbª0’÷Áw+Bh– ÅÝàÅà#´—®´D~0õVá÷ÒV×q°Þ¼U@žÁÔ‚„Ò»¤„JƒC»o²VLr×i¼9’#©³ˆ¬—åˆ"T9R¯Æ–[Ó%‰/éÈ)rš—ÄD¯½À0ìœXØ­> OU˜°Žûqí2U²áe\ˆgˆVÑO¡&Jp%ÔI ó¾=E¶Eų®É×tÖW–qqtåîñélá «~(þvx‘q¯4K…â¥å/§ç|ëýÑD»Ü /®Íz¹óf™ÝÞÃû_Õî×+u醷‰¥jrIYˆÖ׉ñ…>è™LE™¸†¦ª'¶C0› »á¾h]»¥wUœo|.¤Œ>Š=(ÁnKÒì[.WÖ =¡)}ñäéË 6é¸z LXγ™Ê~¿õµ¡Þ4óÂx5É -Oçe â^jÉ7ÜIÑãyk“»âHïg|ÔªZ½]ðp‹¢¨†ØÀ{m‘ß•[¾² 8+FìæÚÚõ™à¿±ºi4›ÂãN)ÿ8ñéþUSÛNÆñ,´¡¼ëÍϤ?øÂÖ{ÛAOéf)_ÊqPíGÞ5·ÌðËÎÂ’ê”N"£Vèîdßb׋qŽ&¬ìÛ(é®\§¢SŽÏ3’˜æŸpñôë:šè}*~½r襕—KtÄrÙ{[Fôr¦¼m݉Ù["¬Ñ%¤D>(YË”9¶n1VG9_ÕÑ\—UêÆ¦Ï&›YBú)]ÅÕÜmK?UI+†ºY»•Wvà[×ð…?ÿÂVÆGEß-oQþüáüm}4ÔuóŽR‚:Z‘<û& óAæ–Ï:J/#¤!]·o¸JLš ¿ÐgwïÞ’/Ít­ÿ€º í]"})”Ù›é ~±MæÉ´Ýñf6g¶F¯q¾´¦úÆX¯«1•ÌòáS®ÜWÎiªqùñ£}sÆ_åTíM’Œ*Ó$¾u ª^“¨÷Bµp¿XÔé§ÜúYè`D ûáø–Œ#‹ûå¢cXˆ ½‰XoéšA=,¤@iöÕÀàÖdmãvê—U»¸2§ý®«—›m[Õ[âòg#™ýB„Ô;XÖîªZÛ±¼º&Ý¢•FÊ%<):a ›زÆYoâð¨é»Ì-bN+=‡–šôC@ÉŸ£Bn:kâV2ŠðÌ Êêñ³Þ¦c ltSõÏÖ"ת¨²ž@®ò†ÏÇ_’gÈ mé§ôã\ ñmhéëfÑ’Ònô‹?Ònò“h§ÞÅ~â;xŒ©Áøî–jÈkêѬ¬FÏ캔_k¹#5~#Ï]xaÂÅLÄêm%Á¨î ¾µ§C «| ×òëÁÈ*ÙXî3#ÉEãÕŸ‡ñX `§Þ‚Dìø0—ýÚÄ7ç{?d€up~~9.…CpÈ;Ñ\7-Ìî´ÚðvèJÜU£oÛŽ´C¤å©YÍ‹:RŒj™z—jb>µùî×Iª? ™½å~fò}BMÿ¸ø(¥™Á7Ëçê§Î2¶HÍæ…\"^Šû\«iŠ#QMrŽ„T}äÞßyÎ8ÞטÛîBfˆíöÂ`øq\Z-˜]«‰#üâö±Þ¾Ó²^P“¯;~ן›C¹Òª; ­¿2в›EÖø~â“ò9\‘²~®FÝ¥®ÇnDÂô*žËï¬ìc/³Ìî¶Ý ¾¿Òü¶ÉnO¥"áýäêÀ²Q®÷d k“øor2ÿó5óæ…óaàÜÇëN7Or¯Øæúû¥NsÂ@OæÝ¦%BMUvùû"•’ˆü¬»öcVÏSjÖý”?÷ýl±X:'ýý—B¶Ü$ s_ÞOÕIºÉÉë›ÔºO¤\ýv/ƒTZD8ßᵺu¯{ÿ3WVð)Ÿ×—¡@zNÅy‰ïÀ†ÆžöÇöÓÏÒoLg‹¼0Jj©5š9§6­èn ò}½±MÊcÒGzì£ê<ž²Ü~ivÙVËõ® ™ë´â/×R—¥ã7}WãÑ«á­XÏ 7òÊÄÊÝ0Þ—$2²=C±X³ÓϽå\/ Ï_âJ¸ûi-Õv<žÅßžüÛödÛÆ‡J¼,üi{6tÕnçû\M§Vcæ”—Û^]Ë~'> }…^†¥4xÖÍÖCî¸iõÀâÍp¯ôÈvkuóåû?¸h[·V#ïåk^ üÁºË–f帣`Êðô®£‡fTM …<³Õ ³y~ä«Të=WukJFе‰Ç¾2†A2DºD ÷šŒ«<±gùÇ"”ºý}‹¾Rçì®—è9hEP˼TÓîIx&¬FÂX÷€uÐßÿfù€M™´Õ¬ÇF”)ú› P]ÕÖJÐå‚ê µ—2ÓýÙÂdŠ<¯z§éÍÝ¥¯ºš.ãND»'Ñ”¤oáwˆ …ß"DÁ$öÛÌ;Aý’<‹?Ê;;Ÿƒö V "•Y‹ÃcÚûŠÓ6“7îÔÜ¢¢v9z?L)àœl9¾ûóùÿ¡ô3 endstream endobj 325 0 obj << /Length1 1945 /Length2 14950 /Length3 0 /Length 16141 /Filter /FlateDecode >> stream xÚõtœk÷À ǶÕdbÛ¶m4N&v&¶5iã†mÛfÓØnØØ|sð<ç<ÿï[ë}׬5sÿ¶÷uí}%©Š:£¨¹£)PÊÑÄÈÊÄÂWÔee°°°3±°°!PRjXƒì€ÿ‘#Pj]\­øþe!î4½Ë$L@Ž97;+;€•‹•›…ÀÆÂÂûCG>€„‰»µ9@‘ çètE wtòr±¶´½çùÏ#€ÆŒÀÊËËÍð§;@ÔèbmfâP4Yíß3š™ØÔͬ ¯ÿ A#`9ñ13{xx0™Ø»29ºX Ñ2<¬AV5 +ÐÅhø£e€’‰=ðïÖ˜(VÖ®)Ô-@&.@À»ÀÎÚ èàúîâæ`t¼g¨Ë*”€+üeÀøûp¬L¬ÿ ÷·÷¬þt613s´w2qð²v°XXÛÊR L OÀÄÁüC;WÇwwk;Ówƒ?K7H‰ªLÞ;ü»?W3k'+“«µÝ=2ÿæý˜%ÌÅíí W„?ê“°vš½Ÿ»óß—këàèáàó²°v0·ø£ s7'fMkg7 ¬Äß6ï"„d–@€“………‡t=ͬ˜ÿH áåüSÉú‡ø½?'G'€Å{@?k àû‚«‰;rqúùü[ñ¿„ÀÊ 0·6L–ÖÿD-þâ÷ûw±ö|dy?VËŸÿ>¼O˜¹£ƒ×?æ^1³´†ª„š4ýß-ÿW)&æè ðadç0²q²XYÙ8Üï~ÿç¿'ðŸîÿ”ª˜Xÿ]Ý¿"Ê:X8xÿjâýôþÓˆûß“Aó÷ÚÐþ7ƒ’ãû<4ÿŒ¿> '‹Ùûëÿç%øÓåÿßìÿåÿuüÿoERnvvêiþ2øÿÑ›Ø[Ûyýmñ>Ïn ÷ÝPt|߇ÿkª ük¡æÖnöÿW+ 2yßQË÷9gdå`báøKní*eí 4W±™Yý5Kÿ¹Œ÷vÖ@GWë?Þ;ï^,,ÿG÷¾zf¶ïï×÷+ûS|߬ÿÍ+é`æhþÇ ²qrL\\L¼Þ'à8>¬ï»jôüsÄÌLŽ wÀ{~ G„?.–‹À,ú‡è/â0‹ýCÜfñˆÀ,ñ_âf0KýC¬ï³ù±˜eÿ¡÷˜ ÿÐ{¥ÿ€Yíz÷Sÿ‡8ÌÿÐ{­è=ŠÎ‰÷½N“è]gúñ˜ÍþKœ0³ù¿ð½nà?øNÿÒ¾×cù/|/Èê¿Èñ~pV^NVïoÏ,ÞeÖÿÂ÷Jìþ…ï¥Øÿ+Ù{)ÿòý#¹ã¿ðýdœþIöÞ½ÓûÎ8þ«ö÷&fçá{u.ÿÂ÷R\ÿ…ï@ÿÂ÷sû¾êþ/|/Ôãd{/ÔóOüŸÉ3ssqy9ÿùŠxËÿðŸÿ@ 'Ð aiÞÑŒ?Ô¦6´ý¾Z”Ѓqo’yð2êN{Wß}_5X\àáŠ=/zQ´{öWôÃ&Æ1[ñ[“­‹­á†oj4ÎR};´…éƒï ÁÇcW7¶_ò]]zÆìæ–8gÍjÃ×"3´¸ Î{s‡ÒTÍ•wVg°Ô'LH“1Ѱx<<ìH¡¢•b5¢3³²®—"“¿>H>¤Œ±qn.—2€[o¥!;É_g };èå"7þ˜¡Üí•Ä{úJ|ÝDcê:®.LΟ)»ûãRær7FVͲYfhr R|ó+Ùù&¼èwOSêmC~º.‰âÖ¨¥$ovNêÒÞ²2iLA)xÄþEx©é“ÐZ¦ïèò¾ 5#Óñ†®I™3© cé˜*êW> ¬ÓfðcÑ!.±Ö bvÔBÀ²b`mìŒÖ‚§@5šùí}¨2ˆ”¤¨QOÄÇäÁZùD¾\S§ãÒ¼Ö9Ø)ãOÌíÔÌ-ÃñÌÇ`5§øC}æÙŽó¬WƒýÚcÑFÒýó½‘Y5&Hî dN&êÉŒÅEx¹–ûá~ Ë¶-|ª¤’º37™Æ‘²!¾+¹®èÓÖ3/-;Dcáo¡uxÞÏ5'ÖoéÉv™çÚ)oa4kÆ-â¢Ëü¦rœc ÍÂDÊ“|"êÆ¸zýÏ6„£äÔ»jKûëÜo(ë®­ëÈ(.j•?#䦑|×ZR>[;€c»,+gç*uË/›4öèuóÏ«mÛ&®ØÉKæ½éÚë«!ŸP,†µ`2Ÿœ.Û!hC–&žAj:.9Ù Ê™%“'É#ÄX~ü^š 0‘MÕWª£ë<8WÍ^ùM‰Åß/ÍAƒ†…Ï¢GC1y8§ãN@§ýÙ5æXêuÉ¡ÞJçU“Ÿ €iÀ„„[gè''„?¬bª÷¾Ì b—ÆjÒMa’p nÿÓ‡­4C„9«ŠÊÂ'YŽÚà4ìUç>ƒ¨Jã=ªÚÍù‰’— WqkçÇþ¸Z”ª'™™Àç„å %«Š(J–3ãåp‰Š½MúðXçÓ‹e$þ8æ‹[†ìâ E°V0$=ójkö³^­èÔ_dô4œs(¾L‰jw§±Æ‹Ò˰=§‰y]©‡¸ñœ)áè¯)^¾£ÂyÇçɱK‰R‹|µÍŽýI²yõÓœ9¢Ì Ëòª?(˜mìv¨P@ÿ)’r#ÁaJ›&‹ÓMgƒêçºyž,|¾…vu;¨Ì åÁºóˆäÂôò°$ Z ¢aZÝ?Pù¦¤²ù€*ÑøåÐjSÇUZ”¬n‡r5np"…lÚê´Mà­!V‹›£ÒŠ<;‰œ0Vcj**„¥ Nl™9Ûª¦öž»â§hægÜ{™—ÿ”*]R¥Ïl5íàb0ïYÇKžikã÷c€âáûn?"òP×­yÉ­-ƒÊÆ’<Ýb¡sº¢Ïñ“écVÆ|–„ª–iùû&° ¥Íäa^²òp º Š¡Òö Œm//ý@1¯2X¾$šÙ×LUQkæ‹éBël†ù”Ö´<°F..N¾Xaõ@4r¶¦0ð0xôXú+ƒß£î8åŸj?o/ö÷¼j  i¢àòøOînÅ`V.ï9ÂÉ 9÷ù?\átµðÛ,îÈ…¼Òß/¶8f’Fï—ÑzÅ3 `ÂM}›5´T²Óâ»8 •A\}¤ÉÇz$™¶¡`úú‡)¾‚;"ôóÞÜe½[7Ç»—=qB‚ÀŒ„æi­Ô+¾D¸´jåѵ ì“«D(¨’ƒ˜“Vžèþ~öÙÙ¬ ·H«à[Ó±ßúP¿Êʘ,õ«š¤Õjëä1Q[ ¸©ÓižŸu[×g;gêüx¡(¶Ç”ä.¸ÚeQå)»„P¶2@U>yÂ# ÒÇ6±4×nÇ\$x°Ö' ÐåÓ¡É®ü‡ÀÉ€>¿%´^fÅ%‹ßm0:Kv—yŒR“¾‹€>]¢(ë%Þ'ÕÁ$Ôjf¶W€:öaÚ^[ɳaÊŒ¹–ÜG“ô|9ïºf™D–/n™»Ø5?Ô›V?3ëÃR[Òrb–òéW[¡~×Mt‘î MjñðÖ̹ôY›eÔ›4Xz—Vn8âO}£‰0àAÌ-ÿ®¶ß(y­r]¡mUß¶8Ñám …†-»˜Óå½RwðKaÒ—L\²ÚÃOìWÆ@GÁa%K%;•Ó•{‡*ŸÛü7ŽkzñY÷®Ûy#XV]0_ŠI²W0‰>,¾.Ïi‡Àu¯¶ç|jª Ç×|¬3¤=®×©PÐaTF‚æ)nWP¨;àpÚ>2|É;G‰ó9ƒ  åçÃ3Ùo0T¬+‹€¢ï\9$”´j”£¦kmèê¾tÂË[#ÔüjtMÛbm¶yiª½m!½•–E‰‘†e‘Âñb£Û Ôµ™7¯ð™aýŒ×s y[Íêï£ëqÆÅ{î Ü´› ‰#—Š"*Õ¤–éÓ¢ŠYs:¿„= ˆ£­[îS;h =žå®RŽ6¿ÐLwkÇᇤN0a!›°*@1Õ{4Ž[›| [—©({=¼#a4¶$À…­´X£EÐH¨•”þðŽ L—u“Ä q–"´DœáLíqå-ûRBxýCZ×¥/˜b>çàìû•Ân÷À=VO‚ß±Íkø ‰=3¢p["¦ûS»ßU½¨¾v¾èèqH%uÌe÷«iüÔ©4l*ð[w35³÷vúýâÏ‹›|yI[Ÿ3¨}g\ƒ½Â°ç9Á;cE‰$@ô'ÉÈ©‰Zö唂Â\¢¤û~–\Î$’Ö’@÷ ¡/t¤ædðg§Fz6ˆqÿͳ©.—Z~9þ–´éˆM9¶†£Ÿ^L¬p;`ÔÀÜÏÔ,ûû`úÅGŠ >¢/A–݃ƒRôöÁG.‰ìó8µ%tX Ž<¡›¤I6ô<ÚqðXqÁ€Ø,øT츊=Zf¿U$Ðn÷µëc…)ïhóúƒ’Z‰Kh%‹<ÁæÙÓN{ì‰)O¿Fnª¸Oƒ ¶Ûo^D(J2„ÎÁtVŒ‰þÅVôkÃ`yMtÙï–âïK»[µ®û8`]Ô%©RÖÒTl£¦ø:_Po~ÈLÞuAºÏÎ_" é¤p|ºÄ#˜¥Ú"¸wj²_Ž8ç´ô~ÚnêÅ›³=œ·ØËØD²ú9¿´•©°áø®™ðœŒøGŒÛÖªlÝr8>m î¡cÇÀ_¥¸§ÏÆ…_Å ]•l¬LðÜkr~l1šA9B왦=¼ÂÚn=Žó½½4³ÎÆ ™6A Kò¾àúI‡CÎwU°Ü™í7í:䪭†tËÞF8Õ{Y« {s:êÔÍ/߀×ÖQoȪ™rZ\±[ù©BŽ gN*¶‹‹ã\œö&=í)Š×.EU>•©öñnýÓîIÂÛ6æ+w›fÁÉ·M#…$‘Ow¥}J?›aBý¤VÍuøáZâF£N=¢‡~MR¶š(›õe3çž]˜šÈÓc§§³9¯—YX «dž¢õCC‘!8`) .82G}¢öˆÙG„+7¤ÓÆÌM4©-.Ȉˆtl¼xŠÚú€’”ˆjwʆO[OÄ|Ä¡_¬»ë´|ÍK@|y =ê$­µ¬G¤¶èv®óh‹-dÈçêÍ=în¨ §!²ÈÁ^h·u¿1x{ðŽþÑ û«°Š’•4)l(»±ºî“6™“ÛÔ3 ÑþÚDÍ…µxcÇåù¹SD<œÑ0³ Ô¸õ¦fÈRø)zB„qæ3×…j)V÷D6·Qtw&aqOº¹!è_¢º€¹Ã÷|‘@Óÿ1ªÏ¿X=ÆÕØ& u4Á¶LÑ’h‡ù¯Nfõêö«‘&qvcO’÷I’Æ…VÉ4/ºÍÄéŠÞFÃõ—7´o˜œÛME Ð¹1UçñÊßK©?¥mÍ&o·N}ò3á}‹ÔZ ^ÀÑp °ÜÅE­(Qi8s¼x…xŽEyxPYÇîóQªK‡##sÔG•‡‘DÝ……£S³7Úæ vZâ´l]íÜM×§òÀ!xF|k‡ûô;Œ(}Î× QQyÉÂbgÜT£h?ju¨?ZkŠÆœiåѯÍÄS KøÅ#µßHß<d-|Qô¿i7Ñ¢3 %o›J›WeÝã1v O¹Ï-ÐåÛëè]Ûr$¼³Ù\/ ‹_8è{:;#÷ø„Dœ5˜ç—š©tÞbgG ÖrV4bD4BÂø=Ê_ïJfñ¿ŸV—z·ÏmâLyçîà ×lãͽ‡ÎoLvdŒçŒ)p“o9úÑQ¦¢71d–¤ 3˜©ApÚoÚ/Ó£Ïû“nDœt¦°x¼ÏJÛ#1õT³U~ËMä™tp«óÜŸ÷Ù}Ä tØ2gÇ´qºI=DSNm‡G¨5DÔ§ƒCc*;lUx,ðËZ„„Ë®*ÂÆ{`lòÌ [û]ò]úÈBb(Rf—F¢×(¨+!söJ ®ÓF’’/ð€}G'f-k’`Œ”*çU!š1oVùrŠ3‹ 3Vô5EŸ»b¡ÍDŒpGë×*϶´Bù³×'9½A¯ŠögÉ Öƒ¯r ‹5ÇÖö=} cE9·[f…ŠMÓÙ¶Bñ2²È"W"£ª£§#Ýs0æ|¬U™sJ™)8‹Èƒ# $²°-ðyίô¼’?~b°iôÃŽ7ÿ¯?Unùø©n³ræùò'˜åƒ`¸À¹Èf›Ç adç\‘„a Ï&{X÷yÙ·íÛB¯&Ïcó½g¦ðÏW€’Mó¡ùVì=õšÌ‚oøªNÖB{êÄP¹g!8¹SPXjg“4}‘AíµÌÐóñö´ý ¨ªªÀ}|†¹Ôv)pZË1øQ€?ßy/Ówò JyxÒÌúÌa†Þ#¬#¼Uíîx’ÚgG7“=9s¬æxIÌóSõ,‹fýÀVß»|±Q6Éå/e¯±Oš #Úã,7Uµ¼ËàpGÛž—ó¿ÔwwpûF»OGm†{JÓ¿£âƨZíŒzØøbU²ÜMf0WæLapÊü z Ñïìsl=½t¹ h5¦?tÔsìŃ“öc÷¦è›ZŽ‹®I“Ôx\Wò~ÃK5œ†Ö°¤ZuE =¾ óVo·>ZM óº ÖT†×ëÏ–δ‡œ.W:}Û_¸€±S±¯ Bo„9[)uq`ð è%â˜Ç™p-åðTJoÈÄ= ‘×1a#D€‹…tyÐ4>/R¹Ã0këwÆ ¶Q„Ú—?aÞ3H­;\yXȽò+¡xÉhÆC3¯‘“ÑϽšaΘJÆKºI§Ò­="=³ñ?ø!y‰_¯!‰›úFÿèÄ«@DkjKå¯ÙIâÆ´íIHÌßÍ|“?Vg½ìø¶+gÂÛསÝíš7–8e.Q §#󈑡o¾’oÓ@Ëî¹JéðBmëÄW.z¬²WÃÒ_“åt²ÆVöçúa)¢»Â¹›DO0ÝËû²Ý¼Ð”À2R_eË#‚òY5‚v[Í€âœ,:Ò›° !qÙrÈ¡$VêwÙ½ãBýámàTÞ2\”HV›Ì$Ü;?]5˼j·úÑn*c‹#RÍÿ‹¶‡iÞuüÝ“ƒÁ ½,§‡®Œ;æjm¿&ÙÐ7’ëÍÏJøx=«Ð-ç—韦ÖèÖ`úo}ô2O4¹¾8Ò+PN¬ ¾Tß²¨ÚêÜGBÐÝüÊœ]«ƒ»‹T·«¥ª„Õ:¥íM2 »îW­7 ö²„½¼žMC<Xhâ*|ý¢®z—/‚úIs•‘«¸r¸ÔÒJ/‹S7˜:'Õ¶À÷9%-¬LÏ9ßÑ™¸½L*~c»D[y.a¯}ÂÊÍô¬„Oÿr ~žá4ØnVºŠÌÌ‘T§Yÿ²’¶øùú<„5É¡kÂôùNhc^mÄT•(Wb¢¼ž¢a²½ä´“NÖlöíN¶Á®Û\fUb{m¥þNpJv¦PÆ['^z«E©¡©¯ñÛ3QÚøˆ”ë¾ô]£Äòl¦Ï®÷lœv§/s„|眸ӎf†NŸ;HV£o·°m”nŒM·>¼A ÚD…\°kÿêVÃ…zº~•ÌF1 ³@ѧõ1nkаÀX ¸ ¢±ƒÊ‚ ËšŠ…ˆaŸ × ‰uýÈ)€}¶m{|üJŽ¥˜ZD¼"à vMܱ}æ7hN’e5˜6ößÂAÍÃg„¨¯œÖŸüJ±—Ã3Ô\î>²£E¸qÇų’z”et“QðÅ&¬jOü&”oºÒ›ùTŒÂ“ò)û¬áP6è8Þà•5òúQ·“v z̳àäY[¹£w”ýŒæ$ùÏòâ'—ß;½¦¹0Š¿ò§2¸IxMp¥àӺ㈦ýΖ¤=$‚¬OSßDŸ“¸€ ýníƒz™¿–¶ r0©ÎMÓ™×¥ªîÿÈ‹x’¦×÷i@w1{+ •+˜*ßËZNœi£$IÇ¥Ùb ÓÖ`… ätiÔ~áŒë©Ö›”J¢—ý’ÏKi–~&E°àB…Sï1þª,7ø8zó ýç 9­«Œ+Ãr]¶E™lÞúº1ôw¥¸Ì@ÆÁk…>õMIÿ &¼Ìj|N¾9&Já'ìš&`q›W¢§òyÖ15O0Ah¤¸Í’m0¢~ 7üŠhó§‡-TK~˜n’ïÙá6ZÒŒ€[Wa·©LÉW]a­”3Gˆ,`ŒÐâe|T­›/K˜Z]?»] QªP$ø ‰f3bEh‰J!“utåÎÀhïZ;5jÚq|ñW3Û`‡”ç¸ì\£¡¤â2¾hÝ¿k @m^” %¢àòhÚjSë’PàòcèmO B8¤»*ÁØ#ƪŸ•M$T&ì1¡ù½- P¡ñšnJ8W¬ƒ3>ÉââÀ©…]Q—xiÙ G§¿tHe…0õ!÷p÷¨-_Ìè}&ã(£‰Ü}H=ûS2¾Í߉<6/¦;¡»“<ëµWÛ¦clëïmhIFÄ Ô¢ÕG?vL÷’¯ŒJydh¡·–^Pï¬,S?hÝ M(SĬ]PÑ´Ÿ‹xþ"­o!ôµX&v §ñ¸}x@‹„²»ugDXo10*ö}eŽ *ò úï `÷ñã K&0`¬<ËQœŽ|L–Û(™ˆ÷"͚˗Ñ"óˆî¶ªco*†€{™²ª?S´OÉ8Ÿ¢1êÒq;Zï!‚~qA–ÇõESñ˜8Ö •vN“#güˆ2gÒØ ¸ï@jöçýÒ™wÌëOuíM¸;3ŠÈòµiµR‘ÏÝKø+¬œc>3 vI)^JöCèµHKÊËd­AlŠ­¥Ø:ha’ß·UÚÚ tÄlöÎ}–uã)1Ë µÒ«¸è¥|\ä KÛ¿‡eØ›p· Jèrc~×%ð1éõQœ~šnÉZ6÷°ï5P•Ràn¢Ân(W OùNÊ OÖiöz`é¶²Ô–¨4¬ÕUf”P¶¤Ha_3Ãûs¯fˆGÓÚÇðgSWÿ‘}Ÿ" ×eZÄX?z!ÇF þüò•[Îh§ù| †¢ïø¤s±ë<ÑdŠûmZ†YÞ¤r Ópãr˜È£Ö=î\À>ט%Ä–çÈAŠ7‰Ÿv ³Yñ~ÒÞ ¡U¤—¤ñ}2ozív<4Gøí*f¥Qž‚Á¬éª“Q. c!¦LIô^DR@EŸ½4¬VÅÞ–R¯t´Öœ ,ÎÓ€°å–öÆË{õ¢»[sÛ5cæcó¹v¾-‚4­ØØîûªd—½½Gm°án0È¿GpšxÍ7óGdñÙèBÞß2Ï ñ|yÎéVr14[5k0H9 t§R·,뮊í=åõ*ÝAê-BËñƒÔ‡•çý$ɃA6t‰[ ¼n¼"ê5ÆÊš°Ö'öÓ9*¾n:“žòMÐ(/Ž…§þ^Ä/ˆöq½;|‡ªÐÞÝa¦³|“É…ãöÎàûñ'­èÑm+ï²=¨m"ê´9’œó—ÊN ,ŒdRcfþº“ls¹º¯œŽ÷bnÒE7ó§žh&QDô Sæþ²Uå@w1µ®_bo´= ­#ÓÏ!' Õf“8rGðd’UÁ‘E£f­¯jÚ|HÍh«ÜTŽ?ª"ÓÁ:s¦¤ŽÈ„²‚Χ»Êý#üUfü¾ÆøüjHSQϯá-á}œÆ ‡>¾î›$P‚‘¯µÂèÜgögäŽ Òl^S¡{à­Cì¹+ÿ&DqüŠž¦¿Ü†È¸h¥!U$$e-òþÀ“×ÎàŸ}µÓmºIÚ°@‰6ÂË“&™÷vºëùeÞl/éëôAªü"4áR>Á6˜Aùi¤ïû·-­4ÜÙ]¨]Är;!Jðu—Û‚M[þΛ)t`T¦åâ qÄ»˜3Íî¯åÃÓúèë‚8™i-ÓÙ~QeCÅSÜB߸f.\©QÍW‡­êx¶kŽi+p9J¦&{áâürvyY:¨þÀdœŠ5„+Œ2XlLœ£ÀY|™ÕÏŸ¤ H;ë<›zαфZòÀä5†:y<;g=x¬àd‹ÃrÞ&²Ô(³4_l›ª:dO@9>Y»†ƒ…P‡ÄÃkëÝ‘ÏITGU=ì^üé´+ÍgfìK7VÇä·bK.$Ñ‹²re7>á2|ãu fnÊ:Á=îÀl?BðÞr­Ã¸øðA ³Œ ínjzj³uIÏø‘^E·R‚¿òX¬8°íU ŠN7ä&ÏZ%¯./¤'D„'ã÷¿ _sD cÁÆÝìñéQäŠ&­´ŸÝ–”pÞt<8{®(±Ìµ%µ5rûY„U숔´l5;W… ô•JtÖ½&3ûš‰~»á¼†K]VÚÌZýñ·Íí¼ÄöøFÜ£;ŸE=ø‘ÁͳOšÓ}$hP Vœ¨\ab=º¢]Üj Kb…ò~1> Møñëš‹ p9—åb¤ö¸s[ïω³²=“œ3 F1­ß¨;f2Ã{wö›œ8ؾJW Ñèh¡¨~[¤K˜\#%’ûí8•¯qalŸùŒßûaDtF÷ëpûQíµ„}©ÔœÀü‰öÍFýÉs\cN3é2ËY0ú V‹'q¿ÂÙO ¦îÖ d‰X¿V»á——ãÃ’2:=u» w~9Ÿ Î;QA0?F®|;Ѫ½ ™S×­œÍºÇ)'UÈio]ƨó­qo@ôïò#.—¯´¶ýòyY[ gÛ­ŒbBŒ×ñRÏ,†Z '.^¦r(0à¾ëà.ãÅÆ|&¨mé;Q»•ð(~¥Ïø´ÒÎ…)2>IëzÒE£ÂFé[ª–«ª©8èÞ2Ëêí ¨¸¾Æ_ìòœ6tóŽ’ßãÛK„œø¤dyZ¿3—×RnIU&?§#" ³¸ŠáüÈ(úØzGQ!ù‚wj6¸rütÙ`›žö#‡)Ýb—Ì™e§5;® ·ÐÍ Ü„Òßm¨*Þ^ŽÔö€âÓ°>vZzy#n‘çldê>ä%fõÀ¸ùG¥Gñõ§HßÖYüQ*²"ÎüGíÙ"Ú­çš¡SÜEwÖÐVâCÝŠ3¿ÈÉy¶Ãp1w²î²è§ŸtYaõ_AH&‹`4ƒrÖñë'Ûò6Ú’8fÒ×ÐrY\+ÇcƒàòèGñ; ]oç¡ZÆܸ¨ßÅRLBýwñ·½gë‚0B°xqy£Û_hÜ0p¨j²\œ,|ÄÝAwÐiK(§I—ƒÆžfv±`…>¦±ãùÏ$SÏL-1™ŒÄ¯N Ý)°$ˆ\-CÅiËŇ ¡)-ckôG¯Ë*Ñþ X±´<˜]ú’ÎæJÆÁtÖ_–WºöHXÆ*½-ÓºâèºÃÆš“¶M2õ™ÁÞÙ6n–s¡|>Ƥº#tÀGjJô¾˜@¢ã"5þk”RÙórB£ù¹ƒèï™øÓ:‘ª²ö_â[ààU‘Öø÷K6I“±¯hûqù“éÑUO0¤0/`3WEöèÃÒj„ƒÍ¥¨f¤ˆ°ÚL–ãùKG†Ø gUh5Sr¿ yC‡»8\)ï†s}ü¥)ñu©Ð½vNÂW Î3ó¾ûc&xG@Ô\ƒwÊ`ÞÚ¼=ÿc°P)INñÏxäúW*Ø;ÈiíŽÎ ±L1®îMqµ»èÀG¡XS©ª Ïïà2îØš+ÕTÄ(¦Þ?®Yó«S]¡ï`œl¬“s~N-QPµed©K“fúH½ -öwI‹Øb¸Á\°(;Ù&I?² \¹°A¸Ã’A±×„J\ uÂÛÖX ·*–3¿6e‘ãy¶ŸõÌjê)\r»m[Æ!ŒÖéj·–þ”9 ã]s‰:217]ýuè”k™À³V³WYdýIqë#üEPÀh.mô.}´èK©5;ܾªö¯~æÛDp²(Œ3e£O!†îNem÷º±Ñ[ô Æ‘¹«è¹oDvØñ3îG²/gö¦w‹{Ù‹g%J›d“ü×ucºnçéÝÐë‹’Ä~^??+ó‡V€nrÄÙ):J€jªÔIýàÅׯ»œöwÓSøÝ²)”=”†Ýö_ZkŒç­ÑmD¨ùÀ‰ >ßm‡C@Š'VÎ¥¤âBéz}ÝG}›2; écy±Kù˜B,wÈA±>5Á½dÉ}{‘|†ÓÔÞ€ÑäYÁD¤ì]¤«™-OIïa+ýŒ° %JšNÏÕ:Ol´H{2‡\vËÏÓŸb»£?xX€-Ìq~©Í›‰”Bt¬|¢Ÿ[ÙÔ‘7ž0Ì߆ >hJa]0ÀM÷‘‚.K:­ ‰EzÃ!DœDÂᡉݵÑuŸòç.˜™càð“þ“WÖˆØèíðç8kƒ·pä)*)FXôN7õrûzþ’ã÷PÃ…·.#¸IçÙãéÕÙ”E5Ôx)"Æcfê…X0e†¡z¦ÅÖcéºÄ¿žßbõP$Õ,zžº ¼‰‹ƒ>>OøeÖ7Û¦Ùéx§‰±]XÏ<Œ+! ß4˜”n¡9¿Eh4?Îjö]Þj–oÖ‡Üx%s“¨Üømá*:Ø|E‹ÄÑ£ÝòŠU~˜wæÄ©±¯°ÿ=/TÚ¾¡Šõ<¬x¨!ð1Œîã„êà Õoiõ¨ºðTÌ• ûx@´Ñ('Bô§Ûöfú2wüMÍø#ñ\¾N‘Åܞ»Þmi¥‚pa^&ëgÁa®¥½…Њôæì&É|ßwÃecب8=Ì +Ïò€Vûõƒ3› ÑËë:Š‹ž}7›À{½µ¼Àûƒ¶–Û ÿr´Kã`"¯ûhscržóïùJ£-â]fÓpÒ-žÅ;zX¡A#Þí¤˜ìC¤Â×˵“çk(õÝãŸùhšì%¸6u¿Ý²œÀxax'[Ç“o Pë˰Tšu>+.Ê­†é%}æ:¹›ˆc Mî^¥µ˜Ž:}^^–MÉ<ïr ·Ö¡ü k˜.$çÎ÷[IÌ~ írn[j^‹ª.ÛÈÕè¦ÇßÍõKrH3©¼÷QߨÃô\ü¢ û¼}œDQ»èÝ,1¾s‚#’>ÓŽp.ŽRÎz‰tË®&üÎH$fpΈ¬Êê]R¢Ò§ÕÖCÖ/áíÄï“&Kõp˜öóAò°Þ&Ñk.Ⱥy™Ã}ªÏ5£Úç‘5WBÑÌ?…‡Í™¥áYŸÛ0Í+#.û´Æ·åß#i@e슯_M±“µ²|^…-0“¸ðÙýÌÍž´Ôi÷ÙIC "1|p~eµéU‰#ÂmYǽJ«9¹Þá{Æw¾k—·¸yId®VÄŽØ—8ç¥7»ØDf{°"gäÀ8¯nx_÷ž¿ wŠC;yxHÙ”÷©±VÍÅUãã|¡Œ•‰–—ŠqY=‚Á?^Kª%eTbRV V- ç= ¬©8ÅÕ䆧K™±¢ÍwàËRç«Z‹‘ùj~8³üžé¡7<YG½¨QPi}ë¼l îá³1?éõKœDö¤“}HšOn-N¼íZË£ƪw2QGéjšŽœf´îûÊ¡ä÷p‰¢/Z2ÏË^LÈø¯Íùª«Lt݃Wq8J»Ÿ6âÀg…ü‚•7ÞT~˜ÊÀ6­ù ›NÞÕv¹­}ê5B:öeöíw׎ë¥òLuöfd‹ÄÒA䬤 Y¡Gzy!Cc^ÉñÔA°ï]%>>Y¦zŽ ®O¬Aµi¤â˜T"¼QßíÀ—lÿ”üRÃùš<úð›M€¿‰ÝZ»ÄʬT¸CQ·€W%ѳ7CÝ‚üEd4gõeQÖ0£Å‡4žÔpË<’ÑŽîÌTòš^Ÿb.ÔYé rcGùIúl>¹\"?h˜‘yîÅÎéDö¸#ªýR,Ñ;f¶°·"P.®mýÍ“¦}ØÏ°žs¿<½ûµ$™³8ëïôü¡÷S AYÛÞo#äÍß,7ÄšsñݳO4P¿\ã(Âé@cˆ~õHÛÁóCp4_½f>EÕvŸg…{í­³¹½îö‘<ã{¤/Êù³Ù\F|Y ïdElE|©~dsLãsjñ°t›Úí§Áé³G¹¢ˆØ¡':ÛàBߨ·ïýáÍ--©õ+dç{¨9¬ Å@2ìÏ<{® Ö¨ìþkõ•&Ä»øŒ¸`#¾ŒÆs«ùcï8’óÀ¤D‹²}Ç\³þ .ÏéÚÛ,m™y9³HJ•&%^=‰68—·¨d›0'!¾jëén«Ÿ"ÏnÛ" ™Á¬º!»þ3I&{[\!÷¤Üiƒø³4þI«s]p9è‹UžºØ¶ŒvS ÇAyÂ^,cgè¾ žÏëXŸððö&=lùcýØ2P¼§û–þeïW®Œv©˜Ñ¸Ï50|µÞw;Ÿf+»ã'yǺG»HA}Þì ÓÄžp-”óF ã]ØŠ/‚ÛKv™%¤™¢—³öOÝ<‰óík+ýñça&ûíÔÁÜ`Ê;¤J[R™ùáLé®¶ÂÕåØ˜ïVÒßf|ˆBë tA:†¸yQ±ÜGTÖÁgãÕX÷»ÎÁþ¹ ØC7iüãšp¥à<ÖÙÆêJS Dy’,C'ËÏ訦=IÁ+øg0ÔŽ¯”w¸Þ±F_˜3 wø¾¦:¿ùm!û—2õS}±ŠîU ]UM§¢†B€Í§d© Þ¸*Ø—yãÉÂ?l¶`ÂÏë¼èu'3Í“•K_ )a¨3ÂWj‡A-·Ê#·#ÈEþ®-ÖêÿáC"tdl‚ÃØ«9¼·B§¿H¸pºÞ53wª†Ñ`¯±šA"¤›'V„Èò…`âÇ_Éò¥Ìm?Å99¹§'{è å|C'ê˰>ˆb€Q£ýrýŽëË6 vª×²£{Ó[…K/?Ò^.âO¤kîBÅV¼ÂQ×åGŒÝ[ï#n}¥×Çb¼z/Ò#$(/%ûDjƒ+ê*ʵƘ²¼Ûè—%éƒdËóŸõÊL0/Yre&ꔯÿrÅl¶¦¦jÏã´f¿æ½=T€0)–>]6¾dÕ wx¾Ùü¶jÒ$šv\"& =¬;$uq ß%ÑœÒÀK‰®öð éž9ñzžÑ÷m ê7yätŸì““ëOY¢î; %~œúkåȇ½©Ë±•½×H¼ù‘š ÑÒd3G«²E4ò’BÒQ47»ñ^¶ózIÉzZX¥¢ÉTCþñä¨ •›ùœu ôðÃómÇ® RVâ°|o<Çç|’䨒€êRÖ²à›ú*Fã·'O›Éah,“sˆ™²]Ñ…wn³. ®mè:^rë-yÁuK¯ƒYÒ³q¼à›«›ÞgÔÌÆ1KéÏ»_$8)O=’ËmÐ+VJc¸fxõ bk;â„Nj¶ ܰثxëFÚŤkƱ¡B…MÌ”`D¼ð$%6O¶V+’£îd[bɾÞÅ]…d¥5¯ºÌ2zœïÕYd¶Sqp ‹ú‘®(W7ߘ"Ù¾ç²s(‡–BÊû• oš_}\ ^ŒT!?/8ë˜ee-ƒ£áOk, åfxá¡iA×”]—ª±Kù† ØÎO'Z&EB½"­ÜÅSç¯vÊw8u¿Ô]þ¨Ô {žFã’€VÕr>õ—X[UíOhuü)ŠHkk@(T@²i“}õt©¿0z²õ!‹6cÅe®õu˜¬´ôäáÂ!ÅjqäéóÕÚ)9ûEë-ϤÃäÚbñ©½Gœ>¿ø@ü5óüÄ¡‘y¼ p•MéèñT}YÛçt+hh6…H²–vÿøÓXä$t3å zC Ó¯ùÆ6 _ÖÝî ûùšá„ PÊ ò¨\øö /2ïx.Ü*íáŽH« Ÿ©iTÈ=LÜpBêüƒF¾{öm{ÿi¨©E)>áÉÕ éâ¥ZÖ¹\ ö3Xúé`j@ŽM:Áš-JŠÕž]<1çi¤ ÏPôðZ!É—&ƒyp…š:bËP¦dæ-%j»‰¯š¥÷x#˜%ü¡wYÉ¿ÜnN¿>g¤ì.>:Eê žÞËq¸ÛÜB<\—©*ɵ/í × –S Ï{‰J2H~.O ±êµ³É s‡Þÿ5f¹â'•õ;ƒ¤~Ÿ@ƒ2~t¿íc8ÀÈÝ c¿‚¿nž³tJuιB‡Õ·>÷—»ÊpFÜfp¼"¶6N±\%91Oµ6 XfXC¤!ËcKºðøI)ft!éfž í½Ð.™ÃfRÔâÎ[ä±-:\1ÅE,æ ×Ñb±hï"ž§võ8Ð㬘La¨¯¯NÊøÖg{!Y¥R¯t.,\„¤ )¾JÐT“œj”‰ƒÜvç·ú·Íͦô*·¢~ô³Ð¢à¹³ãÞ½ñÐ?ßPm®t¦Š¡ˆ«©TÃÖ öÄ¥Ó¾LýRÙUÓ±tÒi·¢ ùR«f7îÛTï`·"Ûn—›¹{…¹—KåXМÑüX^ëNžë>ža¾$×F/ûÇ'IPb£½… >ÏH7°ûÒí&AÉžŠϧEåöù)¼öט0¨ðŠÒl†}[PÚ·“ZÈÊ5¿‰‹¾Ī4ÞE¬\VÁq&s1¦G!Á"Li%]kO0ã¢_õÕè;#A ºú7d¸¢Ýq¥áïXMƒé¤´TÆàþûß!ö*»Ÿ¯êk‚3ﲌ·í¨© äºH»ÆÁ.h]ôïÓ?ð9ë}ƒ˜üÜÞjÁèe†Ý&<)'«Üb2q”$}Œ˜Ûl÷¨ÛtßebE¡v& E¾mx²”ï`÷šáD—¢çã7+9­K3£´Â<©Aã³1%%mjú3K¤!¹lç’ŒñR&ßp YGoÙŽÍ&ÒU5_-u¬3,éîAè¼½(G¶ûreצå~ê"ka*áhÊ\4:\Ô‡€&¯æŠ(ò=Á,sÄBØr48àS!ŸÍTí ë—u<$%ã%·Ñ³È¾¸q(ø(!ûÈä—]~çI”xC4@¼¬žS[zçJí¿À-óž2,¿ŠóžþÖÑÔ†nˆ@¾@0íeRS1§G2r’h¾ÓGhÊÞÌâ¥0<Óêò]ä,ãšúÍæ¤ ¥æ¹p²Ç w¬Â1”!„1· ÉfM¼o|»§Mì•Rvç\DI”u;ªû2±“sVDö ‘õñ“È·&€ÙÖ^5<ßqâé—mš$u+ KÖsZK@á7ÅÜ 0Ó!šØ‘0¢ÚÒ·¨Öù„©¯…Ûn5¦ª÷¼’¸£¯¼YMبû˜’Î{Á€L¹Yé¶°ðé¹–k!ÜÔS®)Rþý¯’a®üOÔÛ¡vb—Ñ?êšÎÝ+ ;€ø“}5ô‘ŒçE›³ùpùòðщÓUiÚ„9?ÆÔôL>œä!;°”}—CqíÁ s“è2ðé× G™ Ë^ÃûÐp hrxˆ–ÁsD9¢^Þ[³Ÿç’:hŸ'ð#A¨’†IU<`ªÚ“|õÀã(ñTnsŠºâI¾2ßÍl~œôÊ ÏIÕ5hF o¹U7ZHyRvR š©âpÛQUá#çj/ë"²bº¡×ëÒ-f›É™$¸¬fDç]¥fìKÇdÕ¡~ òUŸ>dû°ò¡òXñ)¼®DÐþÝ# é;uIL$M°¦ùÊçGF3¶8Å´MªÂìÖà0[UéxwoU†&‚P¨"hÈx©“·Ã9£x¡®ý\›î‡i×*ÿ­Ä@ål|¿Æ€ŽP÷b§‡y«O»K®Àį́U/˜µóÆnþjRÃÁJA–Z „\ÈÓU¨\…8>í×Ñ!Äg<‡ö „ÎÜÍ]ûÈ„ÒBn¤ ò›.J"Jc.> stream xÚvT”]×6-RÒÈP# Cww#ˆ”Ä0 0Ä Ì -Ò(%R‚(‚”´tJ—(Ýõ>õ>ïÿ¯õ}kÖš¹÷Þ×Þû\ç\ûÜÃqÇИ_ÉaUGÀÑüB i ŠÞ}-!a $" qp܇¡]¡ù‰8@‘(.ý$ŒÆøTÁh Pj{º…D€BâÒBÒ P’ú ˆ@JUÁ^0{ žP‡¢ˆ8Tî¾H˜£Óç¯G 7„($%%Á÷;¨äE `8PŒv‚ºa:BÀ®@cEûþ«·¬í.-(èíí-vC Žò<|@oÚ hEA‘^P{à/Ê@}°ôOjDÀûN0Ôc„ÚŒ„1W GaR<áöP$Óh¬¥ 4p‡Âÿëþàþ¹9@!¡¿Ëý™ý« þ; ÜÜÁp_Üès… ÔuÐ>h> nÿ vE!0ù`/0Ìl‡ü^:¨®tÆ0ü“ ‚„¹£Q(˜ë/Ž‚¿Ê`¶Y n¯‚psƒÂÑ(¢_ëS…!¡̾û þy¸.p„7Üÿ/Ë·wøEÃÞÓ]Ðóð„j©þ‰Á¸ˆþñ9BÑ@1$),„z¡>'Á_ îûºC…~¹1üÝî@ hÌŠù!òG½ @4ÒàÿŸ[DBB@{ ´ƒ:ÂàDÿTǸ¡ؘóGÂ|€– Œü„€ _Ÿ¿Ÿ¬0 ³GÀ]}ÿÿ>bAu}uUcå»Rþ;¨¬Œðúó‹ˆù…Å„€BB  „ðï:ïÀ_ì{ Á°?Wú§¢Ü”úƒf÷þ"âõ§2¸ÿà¿;è#0z†¹ÿ‘ÿC‚ùú?Áï”ÿŸöUù_åÿß+R÷tuýçþðÿÄÁn0Wß?={¢1³¡‡ÀLü¿¡¦Ð?Zjótû兀™%¸#FçüB¢ Ñ?ü0”:ÌjoCCœþÐÒ_‡éá ƒC (د{“ýW 3zÌÝ‚ÂÙï3Yÿ ì °˜8ŒD‚}‰@ ‹‰ý…0³jõù-q  Ƥ1€$ѯƒ• jýrý¶$…‚F[R@Aðß–Fœ‚Ðÿ01™Žÿ˜B   ü?L1  ê·ù¯åB<‘HÌDÿÖ†Ë_öïë õBˆ&Ç™pçêðÆ“*%oþ•~aQÒŽ½˜BÓe5z¯µ{¡*²§û"ù±J-#«±§ó”ß…‹¯ë]ÌhA.ÖßeÄJÓNÖ6â;Ø-ñ=¤”;ûŽÒõ^Õin¶°Û;Òn¿3êò>Pæ¡ãóØ]ÍÚÐå|Wq\î´}ƒ«nK€§?>öÆmIIœð&¥¬¦ å7JÃ#µØQ{Šý?R˜Ô7N3Ú{„Å;¦Jù°a  ››¤î:Y›òéë­âÛAà0Çr«Úíó'Ü¡á!Üv¨^cÙwFF‰º)Aö6½—µž„ºkŠHÞ[KÛM>± ›«,öç~ä©s?úzJÉå›Rý5ÏBïÎæþsǬ×:cUNYõßQ|!|…¼šSïÂõÅKŸ7… ê7Ì)ŒÏ¹v$JÚUºöœÝ®wÛྙ¶½)Ùü–’G{¤úÃXœëq¥:ήd³å‹p¨xž#ió×¢ÏwòT3ƒ×b3-¥SñG?ÆOãßwåË]¹¥ïQ >¿Cá’®r#_«Üø«‚S: /ãuê³Óu§þ)™›yµ÷5›¶ n<™ñvS¼ój"_;‚}S HÀj$£*³º„½ºŽkBøj(%ˆò-++e•ô°ó†{ezŒÒÜ!z_ Æxê±™J|wâ:•$< |¸;?”k]‡oj<ÊÓ¢ÇîßIÜîc6O,m“Ë&Ì!—boý Ýb9iRž»ñôå‡ A&…]œä÷Z’¢šÈuœW3ý»Ïg|Ô£ùƒ°°ã茮¡‹fNõÇKv›ƒ\ú\â’ÖˆàxÀÒoI9a÷gÃóYmð&µÄžU"´ÆÅ–ÅÙ+•"ÖqþM/šMco7Æ¿Š:E9±ê?ß ë^¦a1ýùæÔ¥–…MëÞa¤Tö¤=CÉÏìŸy÷búnsí)Ï´ßÓaPžTà×õq¯}'4Ñ£ 먎»×QÅÞ{Äæ0¹JÖ¢»ü@ö’^› ±ÇCn±y(ЂÅnRÊM^lV ÷РÁ/;¢k Î .+,±!Éa¾f€aÚÖL#*ÉÙCÞ÷îùýÔÄ{« F* ž¯¸œçg´Ò¶Þ¼U%& qäˆ&s2÷°7þ„ f²P¶ÓM*UÒÃZ9ùKÊg˜w:wnáÛ=ÜQh³©¬Ozý‘07¸Éyà;Þ­f…Í($#d•LŸF5Y¯ç4@`û¥ C6“1mœø~í§–MÀD|— ²¤îO†³r;a»E¯¥ÖÞ’ëô‚¦¾×ì2BÛ„€ü\¡š<ôÒAŠZ*ÁÈÁ{s¦‘gðGhW4ÜŽX:uiçµê÷ÉŠ<=b5ÕQlkÐ…˜è¼0ÑzÂâ¾¥-æÎp«òøZ™ ËØOéu³«Zn$Õþ“#– ýMA_\=vdy5Û±NÇX*i´!ž×¶¤ÏË$)ˆÖ†B²®‡o‡v[»ºwÐÌÅ,} SfZé³Â¡LtÓŽ‰.W—F›”Ÿp½#;r·’D1J,”oÅòÒŽ;ü²–̧é„D^Ûe­j…ÃF³XcO…”cI4ò[í<€è@5îžs‘ùô°P›\AEæ¦NTØ—"M‹ÂÄv‚ÞçŒÞ]aùªxK“áâ*)w$c­6ëù ·•&[³ó ‰?¿føèüéTA&¤V«Œ.WI£øÉ¢¹a³ŽMwÑäuCÛºòÊf9xÈTªYéq¥ª°–Ú·­KÓ#ýœ7¼"0%th(Y 1ñë†6„ÉB['¶ñ{'U,Öý×bþp@GìQq4‡Œ¿€œtôde€•RJbøÆY}¹ ŒäDîñÑe€tÈ☷þöµ81ŽlH4 üt‰:PáÁðàÝàÍ´²)ɤƒ*#â%$Neˆ KMíÅ™¥8>Ñ^ÂÖaŸ_§Ç=•¢Ø)Ӭ޿)Õ蹯4 ‘•qaY>¼`}Þ±ó>ˆ†¨šU*2wïž©²D©¿¹…g¸ü[«¹gNÓu¡o_ÐW²5ÏŒ¿MîÙÖ/>è”ë—¤wtiØ3¶^·èí³§È­öiÄ[ &L°ØgÞ!ß$!þôRžPyXî˜Y«YÂ.Ä¥ŽÇqGÖ«)Ø­Q=€Ö³þÙŸ#Á$­5™cSèj5i·ASx³¢èörpk•1Ë{ ÑžùÄË1%8ÿ"àQãØLóì+‚@)ÛÞ/›¹ã.ýá[7kÉV¯¾G+¶~Èy*C™fÒ\u…ã,Ä‘8P'«¸ŠžÀv8<€E¦u_‘˜•? ì·¯³$¸2¿ý!ëU’7.xöÔD‹O„†äùSF`hÛÏ 9:²6ûÎŒ‘þ±zP«€ÞA|…½üò¦¨õ¦ö„™Ç´ÿa{9¨Ãažµ¨Ó»ý„Ñ¥óF«aÂ3hÄ~Âþ©ŒÖÜ×ýÛ$Á~Š«Ì[Óô‘Fu …JKåcËMl9OK{M)D¶¶(bEéRªn:GÓ$Ð;½oîŸtâÂõ§]·ôÞ/ê^ “/ôxX|]{Ž:Ì`p$æ3ï?ì×¹¤5[À î[9"Œv¼“°µºaîÅf¢6DGJßÅy>Û¼I¢\ÁžUæt«~`rX=-§]”I#Õàç‚&‘ˆÃ?À‚“E êßõ¤áZ° C²ß%¨˜¡z_¡Òv’Ÿãɼ6Re™dÅú·ëœdâ é^‘J#ËÀRû³µé¾È§‡5ÛÌ&[çî,ý‡!ýdž=Äï]ZFýKñà}·¢Öõq¹iœPÀ¢}@jʉãïU º1güa‘àcgÑM÷ºh®–*Ú>á‡94,‚…þã3þb.…UK_gsÎö#XJÜË®ƒnG^Îfr(¨ öѤ3Þ”š ú¤ôàÀÝ/g¡[ƒ²M+˜Ã R¡Mô½ÉäÓAõóÜÑ\ÿåÒ¡â XL+o S.U T~YLÀɉ*œ€[¿{ëþõì{-U*Ö­KuN­‘Þ=Ÿ>&èY&Ç„¦F³´M´ñZl/ìéŽìqFk|ž H…ªò+3u—2²%µða·úë±—¯–ý>tXN½^ Å·Š`–«‹¼1ó®f›÷¬¿§/{-¾Ø\ëŽöq¡\ú¶i¾Õh{šK?\‹­5Ö™u#F9RÙ+Äkrªm°ÑSýXC_†Ÿ’|ĵW§?øŒ5ì§©Q‡Zþ¢ë·ÒùâÑòŽñ];üÐ%€*’+/Ý;ŽKG®®OÖÔmR˜Wyèæú°’Z…‹~‹Úêb¦›sxß6#æ±i(qçƒdâ½ý:—27Îù˜Õàzå¥8ÅÜàþç}œc¦IAQbskƒóØ6òæ[8ÎÇù%¸QªšM¼«8¹úÖ±9¼^äp—&Ø{6ÐÄñ¨ÅD5~¹àü)ÒbTpƒïux¾þ+!œ¥ÍÖéDÇ* ãzá<Gß~â†IàTß“¸ãðx¿Ùî2n¿ãÀ¢ÿäçØ÷¶ãº‡ÇˆþTñåf­/ÅlFÞYpT:Ÿo.zlŸ±Ø/ìœGòò¼¶Ú¶H¬Â’J©¹ŸÜ^:1%ó2G5w>3&ÃfÔQ&jú¹`¿¹_>_7Òê"lªý`¿p€hðaÌÛä fÇ“µMváŒ\ö‰s·uºâP¢D:ºíŠw¸³ùJöaùžík=bÊ»?Ú)ZÖ¢²ú:_kƒ‡xh¿6»)·lÉá@ZbðbÕê$RG±)—Ö/q0dtœ‡íÈ£¾gçC´†ˆpl—s$0Ü‘Óqê² z86Ýz„­wV §¾”ÇÓ:O{h„[úöKþóNÉÓ¸Z²ßÊSn=÷Ì ŸåB7Ƕ„—ªÙ=`¬i率#j2­ÁùÞºîÂëOY åd’Ñî$QÕ_Újšx¬Y‘›Å_|9BÛP=ÑÁw’zÆšµÅþ*æåðS.·EMÛÝRÌgKæo 6¦SpÓùaÊg1Oyï~·ÿ¸bFgÞèEjA¸WôED]½HýÊ=D…Gˆ÷tËèAQ5‘³›Ùã£-&?)N™~/}ÀýhŠî¯0wæ qZÔ]aÖ Hs—yüs:®J})rÔ‹NGŠ¾Ñ¢¡‚:+Ø7)Sœm>%bcµ·©LÅ“GL¤ç>C³¿Þ¤îü©;•; {Í“‘šc>MåëIúh™HäË[‰¯00[“¬ö5û­ M·…þZ}Ê+5klÖ†ÉûO,møöÐv^*ÖXv« ³çá€nŒe`†=>7«»€a@§ø•Î3gŠ[ÑéÏŸxô|Q²Ó/(߯íñÚ¾æŸ;æu¨¬ó<äÜàx·œdFn‹ÖÙš)a¹¾AØÄÔ桜—…7^^[ð À­&ÍÊyFdP÷åðr`+iUàüYŠ¢dlÚ67¯˜3©ÃF™ €¾ÈŽ5Ht4º‚'ñïÚ%£6yøîvû¯›¸M…p¥Ã_©ðD¹Îó}®ä¼]¦“ó‚Ø„P'oÇ?#P×ä—¶«8ZÚé½UKcŒ’<.بÁr(”N²§¹qFß;Yö^Hna+çV?12í§÷" è’üsœ÷²ê(Åôî ¥ÁVfXý¥ÜÄmî!’é`‚ FñE•Ô‰ŸÕ?áïGîi_ìï7h§„ŽÛ>Sj+*>ëSw+×81v­‹R~„MšÞP °ùå”›l_x±%wNF­Nª8-%P'9L!’½:Vh:­ CJ“Ã;ÅÝøtГֽÊé_l.D`¶Äõä¯Z^¿Üì÷¼Dj~½«ÒàzUŸ²{/‹“í¢¼Iõ³g3Jv¨šúܨÖtÉuŸ¡. RJpᣌ¿o¡  »Xvi:50#þ ³¸e®¹L¸¡qÆÿb‹ññû«Šo%A«ÂuP Ë'Y„>&—£3ßÜ<÷þ9ñš­³~{xˆÐ{ë8X&¡0a¼“‘æEâ†ø=W5”˜pp†û’eóKÈ6û–~i¼a_M{lÈGÔ©ÔÖœÐÈö=ÖïÑýëäÏíÒ˜wGŸô]©Ç%¢¼ø‡—7ŠN_—ë»òš­ÅU¾Íæ5} 賡uB8©Ó“J¥¨X™qE¹‹>tõLì–Jƒ•%Øt$bzª)àËØÇ›ÏX¿KÖwõåd¯?žá'ðÏÕ_ÚÙ£M­AÛ“Öð‚Yã¶ýna9 ƒõh® ßð(ë²}$yGâO0í¬|?I¤ZÊ$!ë{9ú½Ó[‘§…Fvï˜%m%R•€×û7X ëéUïòéHvÆ}Þ»=teü=>—°L¯Ë–KϬ¾kV_´j0ß ?ô óŽå¢úªkÀSó\eëóv*O¡”?ƒŒ¥¶,`äpä"Ký¬>抪B’Nh<ðôS²ñäÓN5©!¦¢» }³)|ùâÚ»Æm5þ¸»W1šäãS¦d~ïµÜM×<%¨ð"Ý¥Þ ß{–1[Zd¸DY*\€Çt ¯ÑZ©ÿ»7²¯/_ÿåNæÈ!ƒZ\÷\¢ïÈÉÄøî#¦ÅÕé=Ggn¦&=… ¨4^q]+R‘Xù=„Éá >ª–‚”^{IB¢ãªÕgöp€‚¯pÿé*6ûñÈÙÌOßê±ùÀ J⻤‘¡‘5€”D¾§Ô¦O<üF7Ñ;xªIÏæÔÉ\¶ÑW÷ÈöîÐt3Þû®ìz‹»ñ‹hÊŠüœt˜SȬW¹ÇÙ§c­¹†UÞ Óâée±¿"ü©=TÉÄ®Çõ áC3 /·|7ÜT}—œ[XUš›€ÃMr r¼^é³ûêÕq)à …’¸§£óQß›ÉâÈîD…u3h‡Éè[äF%Ë2X×ŰáÀ›Ó“ƒÚöwð’æ§×;/ìâÄmå:G˜‰úܤEN§’ÌSuxÈ}j ûœ¦ •n…ÎNC¸YLèøñ’¥iÔ|’ìJy$ØÁÊü¡EI§<Þå“çi  ³òwfQ••q­­‹hó»rVêfKò)ª’Ù\T¾s‹Í6ºëçò‹¨<%µ|ŒjÆl8±èŠo¸SÄ·Üþ¾ÑçØÊàxÔ e%×ÖûŠÊ'E/œ˜}cXÊív‹ W7ŸHÒ¥ißÊIþ”UÞ“}¤?÷ÖÞŒ¯ÖŸAT1ŒÓ¤D ¤SˆÆ•3Û°I‡xz¬ìž¿Û8×ÅcÈ ^h%ý‡' €¤£xÏVµ‡&'/tÔÄ‹H`ƒ_1öƒiÓn_µš½Ç{+ì¯ÒœŒÊìgß$ ‘">ô®Óq±Çgõ [´¨öºù6°ïö³³RØ QÂ7nÞºª¡åœæØ½#¢Š+B mÛÞ¼íW3_›Ûoðɽ¿ÛH>óÑóKˆ Õüä©U~Œ°“W,E ¬½C¦A»–ÕÇãô}”u'™—ùÛͲ.Vœ>Xgc:Žì•„[uK§ÑEÄ9^À™§ Áå¨mèƒßˆp—ì»W¥Šº½=bëñj¤TB§i#ùŽð$D6²íÊ̤ëYH?%ì2Ù¤bŽc2 TMþüÃÃ#îÁ6b-Ä›Q×eÎ|¯7”έý;  ÿûö8KKhPúý@Ú “ž2ÑOI³°\û{ý5¨'3:Ee«Ø,§^”ME}ëµÖéô×°Ü>Ì´¦äµï­#• gŸ­µÑ>çus?lÎéÑòó³’íç¾æ|t¸çaz%{‰mIÈ\žÃñ{Ä Ÿ„ Á œƒj&‰3X0çUMQ掠ÄýFI#Q­|öP§¸ÄuÚFóÎk™ã€ syÝg7„øéˆ²(ë×ï8,~·uTs±½Oå±W-RÍ›œ=ÿ:1I›ÆJëáp½Ä(±öX}ìÓ‡ËÄhç—ŒeÉ)Mœ®¾~é!½v”œÞk€Q«¨ŠÅîßP¢p¯†bvaȩ̈«7WÞ¼K‘I »9Äß<ââ¹”×ßò¤uÄ+] µŸí¨< £?‡¿ ºí+ÛY>ô ç×1r¯ÐXº{¼ñ'‘`q»‹o7¿hŸ®V{’»=×H7=ª»Í÷¤£ë„¢Ìf§ð‰†|Æ·’€' Ùûç„7ßç÷ÝøNó8 ÓØ±©;o6U©Æýs|·Z'RÞ¬:‘Òìàä]¤"и7Ã,ïÅLo¬Æà”Õp§?eúÁr×u…ÿâDÀ’³Ž÷Ê1ÊQL–W§^ׯš¹×Í?Õ lèaFHÊÌ~b «ŸœªÛ…ݾêCF¹ âTVöuIÅÜ¿ôÓ05LÇy÷ÅeâlË“Gú9*âú£¦_Òc[ñ†·G~_³Þ*‘NŸwõÚ·“¤¨(0_r[™¹ö"lèXtU*Y;ž`þiÇSá0ؾ4éI1 F½ë¯¾Iü³y'Õ@NêòÒH7#;/Z/Ôãâ¬L"ÈcHÙ ¦š »-`äìüîIP2>zztzáòÊ7NF€ö|7œCÝ¡èÓ¦}aÒë„ûZ­™–Ü®°óᦑ£®S*(m )Ê®Ò JȰ®äéd…ïMw©µiŸ°ãÊ&A²ˆ¬të—7ÜtœeÅàõ.Ñe 'ÑüqwW[Þ è7^ñž1E™Ìî †n úº$¸“R)?¾]$qõf€‰^G²“Cà’y­´hßÚØu3_ÿºožÎ…ÚR¥b—\óg =ÅXÚg}¯cÁaV‘ š5E¤sö…, «ñò||W]•ÝÊKF*»ÓUa±¿U}!æXÆöäkî~Æà¶p•ç†î½V³ƒZ416Îõä™—Íi_×kÀ‰qïžO°7’²ã’sŽÆ²D°9ã9—/ø™Ô»á&bÕC‚p9 ¤B'÷lDx›2Õ¶teôí:ttEf¿å…‘ŽÁ´IǧJözá=ÍlpYõè—“#ÆÊŸ×nÍÏs¤ÍbÈ~oÆjè"³Ó[y¨”Sïå”3“Ûˆ§M+Id6.8cKwD˜ÈÖ4TÕOöe/¬Ç~z+·M=áO|t‚©Óú¤=ÙÜÒDØÝ¨·—g-r w‘² RÜæ-;SWð­ uí7ÎK'ˆ[t,¼åO²©ÿ¹y°-h#“–†›e m‡­@?KIêó×™ÏEõIfÑ1½|»Az^(üF"û'Ò‹QtImž)ó…€O[Ç­tdšë<À)ŽªyBÛ*l“gk7Ouæé¨{8£u}©ãKu½ »ÙÓ¦jš ­°Åm$²¹.ã±ç7Ûð»íßÞéxó sÂ%FŸÛ÷¥´8ã>„ì*†=v’²ÚY‚‰½LïùÞ0J›¶ûD9wàX…Ç¢6¸â}5@â:ÍÓCZuk©G|øšZ¡z¯Œ(°ÿH·Gˆw%d­ l?óEuÜ^:¥èÊv\†í{—…êpà±Ãq@ìÛÇh+‰tÜQ™ÒÜq®™TÓAø±à5Ñ´•º6õåñÂQZº—Ko세ð9m}삾Q÷Y\‡€³…vn°ÄÕ2šSb¿ç=âºM±3[¾– dtýüˆ}¾SÂëº;ßo 8ã{!ÀÊV~òi¾½.ḡ}–šNú|áu0âX¿û\Î(ÀsbsÍR‘°å|ËšÂÜKÎÔ‚˜ÔϪÎöv–-n31}%‹^¡¬¥)§E­Ì$á°q§%ù2LÂvçFQ­¾„®üWK–~ÎE¯~W†ú_Ò¼juóÜÅÎäüòÆ/O/V/3±üãD·Ë[ݰ'©œ³ôpýE]”  w›ÃnAP­¥7&Zq£÷[·Z¶§÷>á¾TÝ»²ía§“é䯾Æ*볨A)V]}6–PøøA¿ÿ endstream endobj 329 0 obj << /Length1 2590 /Length2 18378 /Length3 0 /Length 19876 /Filter /FlateDecode >> stream xÚŒ÷PغŠâî¼qw—àî,8»»»»{°àîî.ÁàN nÏìÙ“ìó^Õ½ÕUt¿ëZ JReUFc[C ¤­#+ @LAM•ÀÂÂÎĆ@I©fîdü/òÐÁÑÜÖ†ï 1 ˆ&nàT°µÈ:[XÙ¬\|¬Ü|,,6Þÿ Ú:ðÄ \Ì LY[ #¥˜­»ƒ¹©™ÈÏhŒh¬¼¼Ü «D¬æF6'3 5È£‘@ÕÖÈèäþ?&hÌœœìø˜™]]]™ ¬™lLi®æNf #ÐÁh ø+e€¢5ðŸÔ˜(jfæŽÿa¨Úš8¹8 ‚•¹ÐƤâlc t€¼TeäJv@›ÿËÿG€ðOq¬L¬ÿšûGû/Cæ6+ÙZÛظ›Û˜LÌ­€%Iy&'7'€ñ_‚V޶ }s+CÀß¡$E> @þ“Ÿ£‘ƒ¹“#“£¹Õ_92ÿeTf c1[kk “#Â_ñ‰›;@uwgþ§¹–6¶®6žÿE&æ6Æ&¥aìlÇüÑÆÜÞ(#þ ˆ„ð›f tp²°°ð°³€ö ›‘ó_ÔÜí€3Yÿ"ƒrðö´³µ˜€Òz››A_žŽ.@€“ƒ3ÐÛóOÆÿ"VV€±¹‘ÀhjnƒðÛ:ˆ 4ùõßÁÜ  Í?VË_Ÿé€&ÌØÖÆÊý·øß-fý !©,NÿOÊÿ2EEmÝžŒF6vv';7€‹— àý¿VþÍÿ¿¹ÿMU60ÿ'¶?ìÉØ˜Øxÿ“¨vÿMÃ培 ùgihÿëAÑ4Í@ÍïáÿÌÂÉbúÃúÿyþVùÿ7ùYùþÿ‘¤³•Õß|šÿüÿð ¬Í­Üÿ‘M³³h3lAûaóEÕÿYg ±¹³õÿåÊ8€6DÄÆÔêßBš;Jš»•ÍŒÌþž˜ÿ¶dÝÊܨlëhþ×y`deaù?<ÐÊY‚ÎGP³þfAõ¿%lŒlÿZ=6N.€ƒƒ; h¾Ø89ž¬ 5ºý=Úf&[' ”7ÀÄÖᯖrq˜Eþ"ýqfë7â0‹ýF<fñ߈À,ñ/âf0KþF¬f©ßˆ À,ý±˜e~#w¹ßä]þ7yWø@Þ#w¥È»òoò§òü©þFfµßäýãoòþé7yÐüñ‚b1ø±ƒb1°¶mÁ_Ü© ¿Ž Á1w´ü­5ü±²ü8üfƒ*eè``d ÝJ&N¿éìÿÒÿ³@ÿ2@aý‹8AÖl­@³óoQ¬­û×P1ÿŽ’”¥±­•ÕA°‚Nfào£ àÿ8åú‹oï ZÎß* dM~«€Â51wùÃÆ_l[ç?}€DL[ñMÿº>Š€b7û ¨9fîvf@›?$@4ó? (R‹? ¨I–@Pq~G̪‚Õ_‹ô›*¥õo:G™»âÙ²-à|PlGR¶ý6(#»ßl1;Ð}kó?]å`ý‡ú¿=å¥&sÛ?f T-;+ç?¢½?˜íwT*{g[' ±áMaQÿ¨'+¨Z¿-pþ…€.”“$îºz~+€ùè°fv2sþÑUPVN®¶(€ªäü{6Aþ~S8Ù:üYP#\þ€ Ò¹þ± £ÄÀòêþ•ÕãwY@–<€ÿ‰àŽA#gP]þ¾©@gäñßÏ Ð h„°²hkÄdQÔq_#Bàʸ?õ~Žr_=–ÑsÅ¡Óù6™¶:+`Ëá—HòhÚú®Í­ð*É‹çiklh[â‡ö'¯g½x•Ùýv„圡éÂS‘úA"xBF5á¯{¯Oþ–­àݲ”yöÎ<(ʘ÷®Rnõƒek!‹ûª¹äŸË¾1FŒúì_2O™o˜½ðŽ Æ‰‘Žã‡êüí¯9ŒÜé7Ùxzï³hö"O­m¶˜‡ 56Ç< <­wD·³Tž¢G)²¸Kž¥ÅQ[ï—rXh™À¶&I¼Æ»IÏù´åe0pY¬Vx¥&(¼Ûë™ý5ú‘à³öUõíèêìNQ–ÞÑ›¸ºJJ(µèŒ„Âß…9Ð+¸ÄÂ*º{|_ºÕ<½•;=¯›ÖöÓ6ÙGØÁ^oÝ µ÷ÆR€!¼9àéñ*´ÈüJQëÙo1}f7çvà¦Ú9T.qጂ[˜œŽŠ†Y˜ÑÄM9[‹Éñ¾š·Ý þs/­ö(ÞªäÇ5&û«ƒWŽóü ­4¹'WWÂFw«¤ébNCŒf £øs-ì ”ô†DîÜÂÅÑ2¹Z¾{raÙ5ã*áÙvÉ3ðI…Ðû^½²ü'ctrSúºÇÓ÷ÍG‚§PóZÙ¡¾-ͩꄊ·XÒœšÌ«»ZuC…G…ù¡ƒ‰à8“EÚãSTyÑ2ˆ}G w¿£ö`RPß™ÙYš4‡)jWfQâˆ>Ž]WKö ™ª¤Ë}­× ŸŒPShéyC­(z[¶£=AØŸ¸¢SCî“6¡5׫µì>æ6RUZ;ì¯N%®?w –I…Ѹ߶ÀOÆKجìýàÝ¿ÕÝ?kp»hÁ¤÷2·:.MÒ¸as­{r?ä;:§Ð»® B®² ~MÍnïIE¼ÎŠJf™X‘”n5ç /ùÈùwz¡aÑSŠÃõaÚá„:¾uêÈP°WÑA©2$3€[{•Suø}{‡¢0b@÷ežâW8Q· ùz“à÷Ç3£cßÉþ&Ør0êf¬P›EÔ™ô)Ö¨ŒÃbõÍ¡òWØÒ•·OëH_ÓaèyßVQ9¸Ñ#Ý¥Pifû^·¶Ký‘ûz"È*=ÆvPl•úô’¼*Œ´^ =D …›µüDH6º¶… ¾ÝRö …âɦ°“ÁßFa5{‚//²qÃÕŠME¬ 0W¢y?¾HžÈV ‘ahÛéô!®BÙM™E-÷æMõ$”^…|„àñ›^HôÈ?Üì’ª÷{„HÄ}æ#–‹ä¯º}ÌW£œÐH º…¢XåÃ5åµÛmÔ5Î"^”U¡çÒfT£;ç ÍŠžu×Ó§Vh|¡D¬„«>SÀ,W!2‰÷S#3!Œ"ƒÞ¥¾j”P%¨t H Ÿ"ꔲÉû„ €qA!] ™ÑòPM`3‹ ™þJI$Åmc küá„Ö¬ 0 ©ÁîÑɺEÁEÝìýä¯.°Åj±o¾ÃÍuøBÑÅQ ¯i¨~•ßgp™ÊWsþpdÛÊ·qýþÊ›¨Q¢a¼”fWul|’…)±»:†u“Ñø '2üç˜ Ì$»Ÿ².FçhãU+Ž x÷kòóQr› $CÙˆPfv¢ÿ¯]CÑÜé©‘ç%¯õ5©éœÍËÏümÒH6CßaŒØÂ¶ªÝH4¦`°òXI…ø¶±¿£·¦ì£á8‘÷oãQ¶ÎÞ%›E¨vµ=2r“`ÁÞ€±-3ÚÔGñ3$H ÆÇ`¸ 3¥ .—[çÂ8aÃ@øÈAxs·£¡ }‡5 *‡žCBd™³ŒX¼ØÕV=At8dVÕUcè°wûšÁú´…}•·³ï–ø #p.º“ÑuïU0tf$eªÔ,Ý~dZ˜æH'Ã1Ñð!ôî\–g2EÍ@¤RÚÙw—ÝâøVê{¸1¬zê&Lé8dîpÙV5‡4¶ÞælV8I'ª­‹½L/’•øgìwüux(°Ü[šEÃlåý<ß›ô4UPP$ï½én)è"Q0ËŒ p2ÅÀ=ŒšÚ3Jž8¥|&}—ûZr€€¶H¢yãrB ðˆ]CGêî¾ýiu‘†²tAŽwô/ÅœÎ[ïe‰Õ®+¥Ã°ÁyJ5¿7ãØ´`ÎL{>×2ú£vÜ?Âå8½}óV~>KrÀ.(‘u«OæY™S!\û΄ûÙsLßyãM;Œ€¤±ä†ò¸•½7,ö9˜»ïó‚ƒM@ˆ¢,IãÉkäôuúKžd¥eEb=ôu—’Ewj'~ÕÖê}¬:aÆñ«Â§ÔHÚ²û´”Ÿ½Û°e²WšŸ®Æ3yÎzX{_`ŒÉeåYq„0F„0É3 K&>ô¢^vµš5ÏÌå:4tV# ˜ZùD_¦ÆsjVËM¿÷WÝ¿Ò95F+ôÓƒå\vÜxº]Ç:a¾Þi‹œ°üD¸á|`ºç›ô’¹xæMÍa•<“´/üPÝ­§$³ÕÊ—9Íì§ åáÎhì0ùÎ Ù„ ¿s‚äƒ[vkvñê>hi®ç®A5ûë.u.>‡'^ë©acÑœ‘¥²!œÏ?Ø2K~m_ÿ}ñ¤Á®Ì\%i²Z`K¤JÅCq@ésÞ‘(XáÙŽ?•D Oo}úð³¼ëÇ»¬3ŽÔåÕ†¬móâPMý­V:ಎ&}´ýB|!]s¶OAÇz›À¦»ÿDZáTÍ/!¹â:mã[ÖÎÙ!S\OÞJÇxLj†Zè ­>èzìŸ .ðò`8TŽÉb‰p ëfO~|GAAþj"›£ÞKÕÝꥮEót2#-?*|:Åm¬Ôÿå`,È^=2Ä þ¯z½7‡Ï—Ö…˜ŽLA`†8ÍýxiÇ‚WQæ3tÚg´ÙÂ*ãçĈ‡=ybÃyì^†jS%jìÑ瑲Ê*R\|‰ùj~¢×`V@ènHÖ˜/5ÞO­!€Õ!aé\Å/î²ü)C?µoÂ)d’\í¦,2±Ì4Xïêù©oKg t‹íQ¦i.ú>örJõ yÐôâ ¦t HôàSé­ÊÕÈ<‰Í¹jô\>)­á„ÀÇ™À¤æ”™n™2§»µç×(ΞÍ}dº6»Àúà_ŽEn‡à­)+§ð0ÆÐ5w'’v©¢ÕnÊÇ0º~r;›óx¸½ÛššÁâã‰d÷-IXB&ÍÜÄ©«[Þè­ ã{¶Ga‡ìÏYÔ;ôjÁ@/î[Ÿ\·{^É®„E˜±D@2–3ÂÄeZ’ù.œ¯¢:QB0o@»³¹Ñã䞬Ÿ+‚‘–WS/4…؈ö,±yÄðG â7²;°§ºí®!~|v/‘xÉïš¿Ôa—U ¥ÇÒd¿—äÓú¼aQf•jw£+ õ_ òc窸†nµKTr~"ËQß÷òã_¨’Ẉ†HÒ€ þlq$÷pãèÍ…çùA„Ö_öÄ Vc;ÛœÝ9JƒB-Óž3ÞЋØçô1Aà˜í©‡ÏPÄ;Ø?7¿H^c^‰ëð‰BŸdzþª¢¡»!¾”¸ ûŠÇ4JœâVŠ!ùmBAßÝ[ê¤8 wLˆÖ(azógJÆ÷w9DRѱÎ+ðQ¦u$Û[âiœÆç0¹æ U¡I-2¢ŽkÝ[ ˆï‹—IÈaÆ@9d]Ÿáíf?zxR”®mk©V—hwS^Á’2bÖãâóÏ•À© ™&$UGôQQµæ¨…y—kŒàQc> ¼J»¥‹…W¥ùÝ‹½ÝN„n`³¶»ÒÂêÓ]<®3ÃV®8bõK‡'€_ ïÒÚ„Ê?QW¸ýÀ&Fê£û>‰?œÞî©°/&vS^•tËòÌ!ƒÀ1sJU¬êâ}ß7÷1¤'íù§y]RÆbVŠNù¤MttFÁWœ…$™ 0ÖPcò, YÞ ªt™XÈ`òZÀô iÌV“]»(:8}i%öº¤ºqˆ‚÷´Š¦sº¡2ds@¥KÆ¡‘ž©‚%§–í€íÖain}à7“¼HÜ­s©>ÁùçåÆÓÉ0†\´¼Š´]SËQ Ìf!È´Üe}ƒ0Ef};˜Ôéc66sÈÒG§qxfíá]/~±â-0®Ý[ä õˆ±È00%œ_áÎÂ5õKõeõD«·‰ÍJæí¯Ž1yHùG™®§‡ ºéºåî*†/3 »“ŠäðR < må2elf?Ù¶¸.˜]³'ô.D{Å«tÙ ¡ÿ(§~üŠz®ú¸h+³øéó욎ù¢šéHd´¶Þ–V£Þ™EaÕ—×$ÎÂêRjEWT…0JXz >—(„ˆ1² È–¹²Ë¯¾ß ŠÝpø§5‘bôë­‘îj§†€Ñ×——_É ·ÍíðµlƈúK3Ùú¢€34Eµ¦C˶OÅØ€÷g*Ío¹¯ëÐÕ¹Ô;²|FeìÅ&lŠ |ìbbqüJhc.d¾8#õ"B¼ï»çC æÞxb=>*Œ·G4ý¢ò–?°qÎ.ö}Wı–ûI{b›ž©@/Øð¤”ÂéWyë S“÷èâð\¯Ñìsµç^¹€@¦ËÙÝzË΄ÇâM¨À#â$ØUÊÈÌ— 0Þ ˜ÍwþdY†NMéciîÇ3e‹ùŸÎ:ê)ïú¿Í ~ÙØeÌA¿õ%Q.MhV§#ÒÊŒPÊ9Qõ÷ƒ?e©?ö[0ˆÅm ˜ZìiƒÙW ªåœJ¾cô怛ÂYaìͤÃm‘«Šõdi ‰HÛҬ߃­ÂsPЧ‘‚CÄ·IÃàÚ%Áêˆ-à5ßåÜ2DQ¼«#!¦v•ïCFßgÀ¨³ K>Sw©wW˜24qÉl-| ¤bX‘†­ D›mêÒ0 >À¦JüªÜãÖÒ@%ƒñ.#ýí´0Öü= êxjÞ‘_€¶7 ƒâäQpjV§!ÿPÆÊ¥Ê]ùfåÙ8jN›2À ½ÍcÖuÖ Ì¨ˆ7¥úXI•ç Ã3;e![³B–ÃÛ±õ5…}¦SÆKè7mí–5U¤¼úćyä]yîDÚÊzÓ_~Íþ!K?ã'ã›È˜Âz:ÞLah™/t;¨5¸ c¿ø¸ «o-ð­3Ó ‘ÊH©‹¡º±Ø[ݰ´{åPáyx§6qºéŽm£|¹º© žý¼‰ƒÍX³„<³¢»N«êä§õêŽkðì Þ}hþ>:ÓŠ"/³>—1#O’í=–o³³ìöƒa”s,žÀMG¡ÇkôÆ}ñ’xÍy­9ƉŸ:j”HAÿ(éL޹Þ¢%Ó‘0&ÙLõ¼Ä2Èj}mÇ„Áxª–zT”W¤Óö¤1AúI)Ep$‹P„8ÓKÿñŒ´u…Z"N¦'cI‹zaîÓæjW§‚LÁÁMÈ7ÅÈw_S}e¾H'¢a2‘® 8ï1 }sÜbcy@‘÷?SØ ‡Ó6Yœ)LLS(S#6ë¡æNÊñȇÀé+¾ÚL»µ}ÀÂè/V§^C²ð@Sà€sÔnð÷rÂÓALõ3¥Å+¨Bàý ÓRJ@JÂþ%.òä¸MŠ„¯Ö á+C2Òïbº’îk9ÍÑÔçì‚PêZa3z•mo¥7ì¥ãm²µÇ*ÉÌ¡pÅë»ì?* Û¤ «øã£ú*GVB5ôÜñ7Íšr/Ä~Ø‘9¥_ÂǾkwA¿ÙŸ‚W˜ë¬Ygá_ΰ¹G>µv KPz„ØÚ¤Þ *X% ÈÍ Š좑±FêÀal·§QìŸ ™»Ò©ÒÿÜÚèr“çµê17JYöb£ï™¯îDtSÔØY»à+¢ÄŸ`2MFvͯÄvx×,1ŽAãeïŸ[÷}ñ#¸mdq¥ôêƒõç>5*;ÌŒ)õ¸ØœY„ée´Òë?Ä^…»U!¸²&€¡%¼‘&E2–‘ûbU×fË–ü=á·õ™½4$é—‰P„<Ÿ,Òz×i‚¡°Wª{ÅàÃÇåEZ®#( 2ÙË…æ l¼ÏîÄ…H{zû¯ç¿u4|FCݱTÒ™BêZÇ¿ÄþÞÖtxqf•W|áÂÀ;ù}µWrllùù†\ßZò¦áèâʼ9¸œ×|ÎŒëV4hqM²-íS¾¥Ó·FîR»‰ÄáŽ"´W¡÷yU»þ, ‹ÝÆBSÞ«Ï}È`+×7‘}™.†¼*ѸöGb‘jZ¼…ÒÉË´KŠˆ«{úÌjL×ð#å-bFd„ŸT°½Å*x]h>FnjùYñƒÉùK®{´†˜qŒ¿gñ{/"$QG°1~…Ü_KWT·ÓÒ[9Ù‘]ä6²\kXí”ߎüG…S >Õ¸‘²æ²™úÉ£àaùÝXÝÒ.?ó“=Ì^bRP2XÑÕZVõÂ4µ+å«OÞ;¸õ Mÿªa¼ÕIÒ›«ìéµ{Z¬ùê Ud Q£'·«HË€è³Ñ“åë’2Jh8µü qG§ŽÖ¶MlZüs¶žQ¹Klžø“Y6ÌýÔǯœ f†>òý7Y…‚ÝÝGœŽYO_~/‹dÍN¼Švz€Õž×Äó5?¯F»ÿ؇ý.k¨nk4MzϼÑ1ŹÏJ©|²¨ý<—æÔаZÜHÏʦÝ÷±UÔ¢ø=YNE—Y1Ã{A¨M­EóíYNŸž|NI¤…]í®^‰|bÁñŽ$FMUÄÌÓ¸Ük,ê·óiu'*ªLGФÚÚ2ú/”užú›­^j¢#ß jBŸšÌbKkafôõ I[—JÃl©îSߌÁe‘úH§Ò² np4é|ú V¿ÅAâ<@2Œ4b\ fT}‹/8Íkà{t5EÙ$9ެ ò=Ñ Èoƒ?}ߎýˆq㺼uÄN^ ?aËŒ@t‹²ýÐö “¤«¶ñSyaŠÛ_dH‘(‚ABhàìÝ÷h÷iH–fÒË;jû䞭᱕Á¹ÎêÝe,—Êz¶¤äüÓQHИ´ªAÖÐ4½…—®ƒ¾1žlÈ%ÛïÂâr,ÄÏéÃx„*pëgŒÂ<ü53±“vlC¾Øh&õ9ÔºðýdεÇÛÀâ°ŒfÔÒDº%a•!Rñ›S;ÀªoÄá„÷>pÇC@­BiÊÆs¶<ýeY#ž˜ÄŒÅëâ*í€J.b'ìžCìGXæmÄ*Õ+{‡I6ì­¬$³ +QeÍ}ãûl|d¤ sãöõÒª… ™ÆKøæJ¢ÁáÜìÕ)‹‡¡²žÓ&V9#Ɉ†U‰ÄÞ²áeNÌ‘/J¸ª®Ÿ£:£{éø÷w²"kXxèV"êXX¿ÈÁì“Ûé3”CxŸËNéxGÖkš‘QUKˆ”w_Š—pÅ"Ì ‡†’Ø×R.™Åµoše—l¯j?x &¯ažV/`DÏ™LÒšj£<£¤&‹î/Ýjô唋΢©y¿´¼'˜gD4¾J\Oâcê+Ö2š¡ñÓïâVxô×%áònX`(ã$ßC;3qÓ¥4¿àdGΩFê~C¦:ÄC©ÐŠ£g‘Ó 9‹‡\âs=2`ê?RhQ>ˆÑ¯u« Ð~ÓgØå0@€3w….O™0úôú+*JÏðâ¢1{‰©ÓÿTaæl¦qëpX4ã¯s…^Z;˜g…A|ü$µBáÀY¶–#ôïW~_f̈y›kaªÇX¾¥fsì̉]ú±ÐbT [ó~_¿[k8µîíŽõ£°-(wUoˆlù˜¥1Cc¢ð*'/1З»/ӜƇ|…*/ðá³ð70¸öL_I\¦PaÆŸ8‘¼“iÉCäQa ù«¬(–7?ÔN$§¦ñw?}šÈî0ÙôZA— t—¦ Öcj’0:Ê^-â(óùÆÑ„”´È„¡×¹Ô]JŠä@®,˜³nø~†!ÇvZËØq/Z‚´Çêós+NÀ}^n@Œ¦†Üõ°¯šÓ Qå èA FæÂýsyâH>RªÌ'öY%—¥Í´øOÇž3ëì2a²«¹ITc‰!k «*lþÛö´±")€Óteiúrjá`öl@#´pý*Fù¾„Á7.Þ^ë‹Ïaé Z`»ÉñCѲÝaç+¶¾—I"B 8b´KáÙúKOvEYíé`'T8âJ–w5?ÿAT%ᬱ5Ü×jnó½°kŽò_/$F?µ°ê„gÔÆË×µ·ZP“êh–ô÷œòW›_k͸·%G 3˜r÷Œ©M<†#àKüüKn¢]”.¸O·ê“n >BF¦ÇéÇR/šk%7°ò@gÏ(+ÔM¤+ˆ\Ϊ•›®°R¨ÌêZæ ¿Ææ@áä¿ãG'¤äáM4 ùÁì×KÎWá=Þ…;ôêÚÉŽÙK(»Ç•à]_yÙlXðwŸ°ŠÞ¥ZMÉNÀ]3“T¬š´GÅX;SoËLÜDrVg_Ë1µéÆ1féRÛÚçiW® Væ‰ÀˆK}Ê’‹˜¡Á.?Çß=ûÄîo»pÜÀ¾|7ŵxË‚#Q“wZ7n“£YÙõ¬„Á›™¯R$Ù³Q!K8”ÜÒ`m¶çø½ãůz½’Í%‡hrn¢½›iTV%T®áýÕÌ;£¥E²Ÿ`–†I¯í0~Ãì3x˜Ææ2(«èÇGÝÏàиßz„ªœË<+T¤“ݘļÌö¤ŽF'"ðº2ZÈiÒßwþZÌ´>ÿÈ-Ç"nùöëµ€ˆœrFÁ÷Ý‹½üÏÂâ§#=‚ñŽŠO._d»• m¡èMÉ>9×v‹1 *Aá´TÎÄìü\aš‘Œ8¢Ð„²Ö_$Ni\Y›aƒûÞ;ßÅ×ÇÝhü²:Ûr0£ë[hI!̹£ÅÛ¾æÉ®~zÓ:$1ć̕ŸPˆxŒÇ…¥Œáâ×{GÅÑQÉ_y«ö@ô^É'›·ˆ‰A !rŒsÑ@è[=Õ/Ü_áÎéÕàÓû”y4¡Å€ÓTŒÈ° l×x†Y#Ä?-?OMz‡ŒC¾ÛC¬2û¬Ý Ö¦ð‚—Ý,y¿•Aæü«M(Õ°fc¬ÜaMì•¢ßpYk¥¿u¼¦¹—GwRÛXTîJ„ï05á„®2½´·-iˆëFâÅÌפ ^éÚ,1Ê’äX'I’·ás?„}^‘§?̆S<5f8,ÕáͶ€4KzÒ2L;ÂGqU‰¤ÀŽËãÉæ~·¬Þ®ŒÉ?dÅølíõÕ^V«-çÍ̸ Öê³Õa¡ÜÄ'¢êzU¹êÞ~Å ª–m¸ŸÐ¾7Šß›’¦È>GlŸÏÕ•Øaòטˆ›•žÈ¡3—±}úH %ãJ&’@òeût Ó€9 úÓ[¡™WG3dä:²H{¦¬cnšóùÄè£ðœ“Ïò³Ó+‰]ž?xÛqÞVë+Í*kªa|ÒN ñ~ä'ƒfø†ý³†#ó6‘; )•&Eµ®î¸öXYWð0ôgfv §îÊà&· ç¨&™ÔÑDÞuÑäî€c–¸Tޝ7ªö-.û(F´ç¡CfìãQŸÎ–*‘B©Y¾ “‚!0w°™¨QtœN*x‡×F2£—§3>êÞF/uš¡ÎŽ}DÚƒéSz³g‰• £#\WÁ‡Šù˜ÅNª_RDk`$¶(w§ÅlBñA­x%wR7Û¥÷rûMKÅJÐì­5­eøH::×|cï;Y³„`bvI;|\-•\‡À‰ÒчÈïÐæÃÅD#‡í¶ÍPð J¯†m›š‚å"6lôººûð nO‹¥¾¿¼`R6¥.‰8¢gшÐO’¼®›•7Ìm¹Œ+Zª_¤ûå˜BVœÈËrŒY6QÖ«QÕ.ˆcW²+qÊóÍf‹Òp·3[Ä%œÎHÚ‚ï^ºJ`ëæ¯U2Šîi"ëÁíÄ·&† ã’(ÞÜ7?ÙÂ;H<ÝzkЕ gǨQXKvK!ž–ÀC 2â&%Fƒ.’;¦¤+GÌäi Í:Ð:âX˜ ‚¨) °¶®DF‡Šˆè䊦EÜðó}“¿ls±c«Q ÆML¸ T䌮5¡kÍ”¬kÑIÌá‰`d=ëºùIÎ}¦+\àò&~"n3Ìó¡a‘@N¹L–¥³ìóuÊñWÁéx+<§E!ûª›ÖTo ™. Ø)•§_!ãÄþ-óñþ‹"È`ÁP‰NZÞ üáéÊ^ýRrì§ÎRÒ'º§›FÅSÜ4Þ(…1ë›7gë Ä{GjR>x!ˇù\jææÝmÖR‘îj$‹ ãl&Åñ¾NåÙQ¿DJ:ú‰°£1[ƒn«W(iüæãµ®í£Bøi2wàíÉÏÚ’f>]ÔàN”ßp ÚµÇhÎ2B®¥.¾äy^£¸‰¬¿4­Yb®Yê©>HKŒŒTí(ßÖÑ.ÙÆœJFM`4¬A7å[®”\•/‹¤@Lå¥ q N3|‡D)[ÖXZ¥$Œ[³\<¡Ç`æ)âPéáÚìÜ¢ áòZ›-…äMѺ®†Ôœö|ÑÖ÷ZÇžÚ2‹isÇT·´/iòGü.Œ±Ò¦½íA ³&ë/œâ<Ücå ÎqÏp,Wo)D±ð茶N†I?Œ³5l·á¹RyòV÷šu'Ó~rØïžvc6p1Ì/vD¹]Ëñ¬™†Õ{å‹“OyIŠÔñ‡.µ¯~øÚYoFÓ’?†óÊ7mÙPÂwÈ )®ï•æK·(g­çã|0Šæš›•Uc+[óRwˆÂ·Þ® í+ïGV/z1ºhÝX‹×6|¯¾!*}_Êo°Ù!Ëðnö®þ4ðlü®mêŸ_}¥åí')~t2]´?Àé­j}ë}mÇ‘Þ;¹VßW3AÔš“ÇJpðm[d²½ýªÌË-!u _yç£bÁ&Û€àÈYpÐÏ\r™·&îCÓiîå×#•ò"iOÒ‘ «l¼IÜòú­ˆúÆÇm ?AëEEÂBô²/9…S9fí—yœr¶s¥½™˜.Ãcb…  ø#.«Í›Fþ/G×iüÃÜìZV<ͯt£™Œ³îErĪuhºÏ?›Äev½‹c©ë>Ht×=hˆ1†ºH]Ä1®zn“˜Š‰D3Ï#"žIg|¡YÇ¢Y3ïÁèÌ2:ÔãD(ƒc ^±Ç$oÖ (ÏÆ½¤ÁãL0õ¾îdW€Éõ/C¯> Ewðm1ÖUdy¹‚5 e6öL~´&Q/Ï» wì+qÉ(øQhsWu ÅàH÷ÐËÕ$§èª{O6tØžËåF×Zºyh"‘mº%€øÝ?„é´ÅÖ^ 3a‰®µSÌ`À&H»kËMY6$æ}hÎÛÝ“<ÿž\¸á+X?cÄzT k•ïS"ÂDüQ[¬Ôü«ÖjKʯ¯3I}:¢. F#ÔŠÈcÁa8Ï4ªvÅš+G9–ÞÃ[Eà³— ¢‡`òP«O‘É/])¡—§’¥®-‚˜]öÅTjÝWF&ŸIŒî Úhw†ãÚ¥N’>C3ñ7“5µeØ]ú›½qL[ ©Í—­•$HZD¿""ì…±ç·MÆ3…Yõ4Âõ¢R+U<øA3.¸çA$|Æ|;·å†FòéPû"¾ÖÊ9ž’@­¥²Óˆ*Æ«Ý e`NkvÚh2ÇDãB@zýž¼0`v‚Þ­§–ŸüûT/¶p»@›»’ÌH$˜¬š‰ÚájÙDÅWG”¾bg^½ÂŸ!±/ù5gx»úYý¼µÈ雪‹L›»J@‘ЬrN™™˜‚FŠO”Q0%ßñ£Š¥¾¼°ÜG$dË”‘X·«ª6÷9l»±9œsÌ-ÈÑÔǧÊÚÙìÄ•/·°‹ÕûÂÛ;Ϊ¥cE?l£šblü¬¿¿kÊÙB¯ö' åÛßT˜êæ‰Ïâcx¦ ÛïQ›€XÌ}òðßcmà±Z= 5 ÿœÕ¶v-`öœÙ÷ ü®wý†Þ##.žI&ªNÚé«ö®å­ÆŽ¦›5ôÖ XkžìGåÐê:Ǧò;š¢wd¥z*þ·­ê\ÌùwN„ø ½Ö,á/¡ùf÷“ÃBàÒ…wZ3¿ä%!Ÿä˜ÕäŒ0ôcñ‰Ä_¶j¹©&¬}ùꦘ„¼9¿Ìtº9J›¯rЦãxl;d›ÂÈüX-ÐÂzà/•Oi'ÙH¢Ãò>û IFR!¶P–t;œKq4u"»ü kušp;X:S’:µøøF;Íóeþ "^bTÆîEš•øê€ò2‹/ºT¡ñï'DA1ÿÖ(L'¹.3'ç‰ÇE SxYhñ°Cż©ÍÞÅ´Í&š[åN–idf*®l“ô{$óøXûð×['ÌóÒUÊ+¬ÈLOUÞ¢÷r+VÖF9O¬¡¬ãaìí¤Ía¥™¼‚%û³®FqèPž5Ñ/*¼¤PŠ·XÆ!ti%8A%Ïûi_È¥b¸‹ žV22x,™I¤T°~®ýêÚ?ȿ΀-¾Ù¦Ió‡zi4š%ïû½ãÛß>¡ÿš7‚G}$—$àÊÒ2Ñ §s¬… ²ä”¼ åÉ•ÚÜ(ÌgZrÂdö^ÿÞ‘Þ¤)Ä™ðáU§àY¢}!„³ß#¨Î2ëùÈLèPÚâB®Æ>51WpÌ5 (å ûf,¶FK*FNr¢ë¥gM\^y9{ N+ËQàf±37HØ3SêÔ’p³¯ÒÖÔ9±²L‰·:椧ÇØÛ—ZA¥¶sˆtcM6¿ÿ™ÓOÛª`‘DåÜŸ#H5Z¶nŸ¹üc7Kp`• ª)Î{†#F  UhÅ£ÚFI+·›b0üóo™ð‘¼ÃRÎïî¡CÆÄGj6­xdá `°Y‡G£sQ(Ÿ{ÈL~õ×q`Êsqz†ª$rþ8\×9!ç^ä*k {ú‘.:[/|„ÚýÅGݾ êÅIñ ƒàٮˊîã£Uo(”¾õ2ç(—Õç9÷¸i¸Œ_^a'ÑÌ÷¥-—ÝjÇn5è\ Y¬ÓòNêî’?†ìböÔb‚*š¢Ï³y‰ó°ÛóÀ6yìóž³ùº«–ËØÐ*EaÆy5¸w¬vÕHÒ®ò!Ü_¡kÑò÷)ÂÀLoØË¢µ¯r0w–¯,*N¹Sc6O"®û㲊 \9•“Ôn„™½äÉI¶á¡)#S+aàEyövm%Þí°>ŒÕ»@ÛÆItÓˆ×Ó!É‘ñ6õw(tÿ0L‚ž@K=á&¡çwóõe·R¿Õ^µçˆ¢K㑟n¡4h\Ï!ä5?¢MÜK_$ë©ÍÒ?¬ˆË‰²Õ50MSPÅ\ÓÉ8N„°«B Í-%Wüi扃 üå‡÷åÍ£Çg,ç¢Íè¦W¥\öÏí4gt£ìþ´7yÁ•QMôªÌlÁ\üTb¹ †æŠöI˜ú¡PɶÖqaÁ>5QлѪ[Ùb.ä{Õ¤õ•Ñ+ëäC ÃoÛª;³înÐö’yÖP Ÿ¶OW±Õ¾Õbù¾BzÆoL\YzÙˆiM…iX4Eµ=…ú^YËSM6_´ ÀßzpŸ~1Noa§JðÑœV•ã*ì14[Ï¢á,°¯{1YÍùÚmá(Y¦Š/M ÅÒhQ«5n#k?™cº½LÏ…ÓÑ ˜—ö€ÅˆÕs÷:cxøpçB¿@G?Ú/ú²dÖª‡ØP³Œ3R¬–V; ÍÐû¦~¸{šÔºk³ƒ•ŠýSJÇ‚ Ên¯“I)Ymön`BúÏA»C±§Zö0TZ·ÆËî¸`hy†ö0»qŸuˆÁ8§ÁÌxüæy¤§fç_V+ý@×XR“”·–ðîGÎñÞEÊÞ,™ÐO…#Ò­E9õt /ï¤ëB˜”[Šõ?ûè#v‡²•J;"†rêÂÎ E&EÁ¹ôèÚÜ’­h<_v¨“¥ÍRbu÷u©Ã4PŠ|ÁΣ…®a”7l\¼ð·"’ù¹¥?§ª›ØÁæI^uOö+üøÐé—x20·0M­îxK‚¬nåì–ßýaIÂzeßZaœ(¾D®-’»:ÞWb¤Ò_ŽDíLóáq™À×ÑÛ"ü|b·:£ÑþJ¹×„a;u‘©ôô4Ñ<]»ûr¾k|µžîðÆ’Õ80Ÿ7NùE!¿<5P=†!7/IÓ†ÊµÒøýå˜Td9N}añ*Öj¬&rœ¸cZcÁNÝÝ@8r?ÆÛè1í<ø÷j3KÊŠSî¹ã)45hU‚xcR\Ô\¥ˆ‚FŸÚkDôÜ~]1-sX–tÊ­5Ð!Éã×¥bt§P¹Èî1AÁ„æ_7 A½á~É&ùQ颼û}›ï®ŽÎQ",DÑ tÀ&ÃE^ U·âww³ÏCZÅU³R{×,ß^û&cL¸ÈK=\$d~ˆ½»:°D‚$u¤dˆï3¢Y†ÔQ¯˜jYüÀÝO—Ù-åžÿ!Ó¶ºÃEc~µx° §çô¢QföÌX’/ÒLÒ¿Jª•.ÀšÿŒëM©‰ëºûÁ™»U‘!ú”Rñ¢^BPÄz•&»b)¡Ö¹ sƒK­3«kÉ¢…¨¯û«ïS×¼ç6¥åDCzîÆõqD¬ƒ5³¸¯V®û#ÁHy#²;ñ¶kñTóIJšþúJÇËU Lü|©8¢8b§E,<ÒU0¦øKk‚]&söÜòµ¾¨Å$-!º`“Jt¦kn„óÄÚeëÊlØO*/Ó3Ù—†Eexª6‹PÅ ›æüD±=Â~¬›°$b—˜ˆha´<d7ݳìeBgS×»°ÔüŠÑ­¡¼”tÏ{)°´kÐÚ‰äS4 ›¥49ÿi%_1ï.,øUdSè½x~@í¦{eÛƒûøI‘ á|ÖÅÊSŸõf±¦ì©ìïž!bkª˜ŸÜX¼Ép$¹?Üž~¥ß×â- «úÁ0R™¤éæîyŽñüøãÉ9söžìmd•KzÙÂëZ5aòôMi¦k;®{ 4%†u§…†þÜ1AaCÝ5º¾Hý£§iù«ª„%¤1A'z?ÆÀIå WP,^o{dz릷Í|]Íó–^Iåq¨sH»bÛ&z¶¹ööêû¾õ«CÅ/çpÂm%øNÑJ$-áŸt}õ5„¹Ñì'í0à9üf.oY}Ü?œàÁò(s1‘`×a° ìq_©–kßk;š ö5úq•ùã&ˆ*oÎ÷$h½[÷»Qàw‡0;Ù°öFÉ<½Iv<-~žt[uŸÞªIW£„.^"’Ðõņ6ùø¾Åhc§CV³½ ùÎ…)ç=û€{/ª¤Ÿä´s4Z÷Ü–¥Àb>ÍU‹eTï„02ñ]œ¿J(þÓNh4ï(Щ@¢êšøÕ[¼J¼¯ z»oášÉåHÛ‚& tVÁDà ҕo!òYø¬À‰$êýÂQtˆÇX†l›CLV{¡¼#w‰èÿ]ðQNød³TL›1´z¼O®jŽõmî¦Í]T‰ú-<ÆfàÃQø§$§:'¿})£ù6~¨S;ôò‹¹à„ýëiq; Švªiv¹å»çÁw“¦²¾ƒÍ¸Î¡Žd{’v·î€ÆÖl›çÏ`꺴b‚¶,¶ÓhdÇä5k7ˆâ#Î-óÌæ’~?ÞE8à0I:éÓ·.ö|YIo»ù¶g¥·¦+kn|,qúÞ!,±*6m"dƒóyáñßu·ÃN“ #ÈÿmA"Š(a^¥´ÊM¿ÿ˜Ü3sf„½­&†³"‚/@÷<];ÚD ½¨±‚)Zå~ÍLè¨2Ððª~0%úd{@¥¹ñ3nÎ •ΔH sŒIu"Ž×xEaçwµ“‹{õ3*¯µÜÖU޾*¢Z+Î9úžá8Gp×Céß&†IC®-9x0’¨›ž›†xÿOË 4ô^~ñk‰:x4¸Nø Ilði¿a_C‡¢ü~¹ñ* _#%á!Å2‡8?êä”(ðìYó©Ç¬““{¿V\Å Fs«½aÉmdzaŒŸ”7Ç Ê*ÿw ²Çi' F8©¢éC6Q§Ñ’‰‘i¦œ¡¤lfË™ã¿éC00AcTÎøB“7–ÍSÉÚ6žÿŸs&‘dëóõI¨˜•dتFʃUGR5@¦Û÷Z2HaÂÔ„­²Ê <© Ôª_0>‚^“D‰<òé;JVÅÕö±ã­Ú•|‹¼i© 6žmO€Ùs­Y¦-Á«M§º¶•?«<ØñY*ßý0›8 '+¿õ0 ×uì­ÿƒ=e£< cª@ÉÓíàT°­’àü°Åƒ,ÑEB¨Š—~ìP=VÕ¬¯­¤v+þÙT¯QãDe!ñfacö¥šoó|¾÷O¸ýwE7–O'hƒ²ÊHZöȼš¸îvª‘:^6&»_Û• ^Ò£=ˆ¹x;ëzšm¢xæÚƒÔ׿d¿虽z.ªc‚·Ü{ñGÆödýë•¢?Þœ,í{àû,)Û ûꇌ%½ÃÎa÷sßÝïiC@ ÑbPëbÞ¼ûðÍ"9ñµP=$z4Ð9Ò„t®¹&fG¥„ˆbV¡ Šš¼Ñ “‹”˜÷m~Ö”³m¸ä½F(=§ÀË&~ý8®ýR ÇMùçëÛ/©ÇæƒSÊ÷„3²«x£¼ÿ¿û¥KƼ—™ötî~WK†%võ$ÁU}—´/»Ê`ôr²¾iÇ« ú²:"-o`=+—î)÷†œk)/åv?­¥/Vò1 %³MÓr$ÎÞѤú9¤ 71ºi[D‰|Võ aÁßžz[#:·l³¿íaÈá–IOËÜ©8méa±›y=(`é­nxÏ×C–œJ¿pu:qÑNù; S èÈxžmP §”]Ô·ø–ô=¨¢”‹«~J qàþÌØs£k ¸ŒcGbrÆ3dßl<¥Ù„zmso ㈯•§ùµf?UãßtCX³IÞ¦<¢(+ZfÙþ=kÜï“!“åòâÑPG˜JW³zëT¡ß2ŠtR˜B´¥¢4H|3&š^§Ž^¿¸x½L›9!†ãÈî‚ÏÝjWàPÚG‡‘©eÊ®â‹U6%”»XíÄÐÕL§ì\M*?¼o9_5ì"Vê r©Ÿ3IÝbó“<2&æE$ràÂ+Á>.”ŸŸéyÕÕãŒæÆëœý{ç$ËIï˲•:6볣ᄘŒÂ¹oÞÆx(, pzÏÌA÷5å¤;E©1)DÖ›-MDŒIÙ‡ÞSm>­éÉOžo—Šõl%Ï…†_·Ê¨\BŒ`g Åú^Ö<æÀEfd¥R½kjÈ£!©x'œÍÒzêHLþ®oÁ£s©àAÓÌ´‹Ýå܉ñ¹Ñ@ù\“p÷&Êö%mÜ€»0O)C˜¥µ™HhK tD»5ÔÒ“ç‚öŽ¡«(†Ëi²`}Š-l:¶/’7à@_QoGÔÄèeé`c¸jå$N]QRQŸbÇ€Á{*`]¦N0cAÃ…Fš¯û§P¡jI!¸ Êý€ñ}î[¼jÆ~Y¤Ã±ÃM¤÷Ỗlºg¬Øh"ûÍ ÜTÑ \ÍZª»¹wjÿ çlÌH@7ÃM4Š{à±Q »MÖðêÌ¡ˆ®¨i-‡_vWKõ†ì¶ƒÓÝñÀï"? hŽ$O­õªDÜnQ^Mü/&‚œK˜0îV½žæ¾ibâh #d8sºï$f é "Œ­pß@Â…eòWö"Hþ$Þ0‡sUøˆ†¾­?<0ߪ(ó'§ŽßµGd)‹‰•–Ý"6²0Xã3ž‹‚¨²{ÓíFѵòËÃ3´«lƒ²c M‹„yò‚MÙ¯DÕñCd¸2шYèƒ,‰5v^œÙvޏdã„OI(qÒ˱8¼§]^aœ½eõ2“©ô§@wî—½ÿäyÍ– VÂÏ&£´³¦7/•@Aþ¶¥(þÇkød ËéÉxè×£Óh?ª˜ò™aÀÃŽ&{"•«1z eÍî!Mä)!·8]šÃ]#íH¼˜ ‹ßѳßFžt²þ°{\òoŒjaÔ±ï•ì“öÊÏtÆ%½ž–™©.º €}Ûq…®²tµ0Ý.èF``j«òz3½: iݪ®8 ‰û´ýß'?µÍ -b¡ñ¿Žï©þ"ýêµ2æ™PÑz›ˆ[ü»€é®:Nu¨‚ â§„]6o)Êç*A¤ 2ÛG~!Œdj(ÿÚnXê) ÷áËvOÿÿ‚Håší=‘H 7)Ç›<–³®ñá7 Æ_Gõ‰ü^ïhÅõÑžÒ,¦±I÷c:Kª¼bË®zõš­òÈþt”†•sz×¾¼RߌKîÃFÐé°s8¡è+†¸¯Bˆ¤œ¢;¨…yù1š¨·Þ¤Ì¦8{£;!}Ñ!ý8ûÕÁ¹[!Ô´ šÌs¨ô¸lW/٪ܫL¯'5:À^å©ór±ýt·"¦ù$ƒ†0¨Þ$)ÏųAaè; 8—¯¹ÂFåìÆ«†ÏÄc´mX„ÈW‡àUí|U°ç– ð½Í]ïV͸·U9n/ô;mX½Û kŸÊde![L=ç%5¦Øš ¬ž½×¬Ü^¥txÈp|‚Ë¡˜lÅ_xÛù÷n“’ü’eó³p˜ŒÅkª7›FåÛôü\^¿ÁÞàJ×™w¸¹!=¹†I¶ù¬™õ:Dœ©ú3¾Ôõíèѵ>íÊË ˆ9vÉ×¾\* ”…5¾ 2MLÑ#ýž4o¸åÅ«Y0IÍS0ÓMëFÄ­ !¿n]q[Šb@ཥ‘Òr~BE²‰üà¢#‹z°yí‘¶øÍÖÂü …9“t9ÖkÈœ0d?“bÕW\ä’mS…ŠÒ¸0œ¤où;9AЂ+*äÜÚ®ð«MÍ¿@>Kíi¶.Ö%0¬:líÌâÿÐWÈ£ˆW ¾ÙÓ‰ÑIé¢j¤ÝþŽé9$þ·— ÜÞü„ù&j†Ò¸„•ô©±Ó2H»a¼M8‚]ãÉ0w7¬n0{ìî'ø+UO@<¢M% ݬTt§q–AèSAÑÑÁ>fp‹ÄÿO1¯nh“!xŒYÖ=òcþ#qÿl'º™¥ÙÁnÎÎb,Û…ÑFD½¥çߨߊír[ö«‰qìÓYª³-ÈÝ+øÛë÷xye¬½îü3}ÿ«Ðxmq±’°F à»;·Ѫ†áþZà››%k‚«üáÌEtZ .Q±·€©²8~ÿu¬Ú¨¬±ôK«–ßœõ‡Ü‹Ÿ’mø‹«¥müyâXƒE>„â,­ª­¶E“'\Ïÿw SíOO vß ZÙoê%¬B¸ÃP-—Q<Ÿ’Ùó!Ïù^õ¡áš?<’uhˆŽ}ú¢Ñ6ˆ×eØîx¾w«mÁ˜DPîÖ%,²Yp $Ç̽x_amb.—ûPÆCmP+5QÖ@Ja®~qúFL¬ÔÅ·‚±"µ‚CÔ›ö‹é†×‚¼Ëàë ÿÿqÏíÓ>H~—ÿèÙ¡L=À£õCg»Ìø/^ú}CôÒ>®‚9Jë­!A1YŧêÃìòjK¯C²oé… endstream endobj 350 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.14)/Keywords() /CreationDate (D:20151021202742-04'00') /ModDate (D:20151021202742-04'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013/Debian) kpathsea version 6.1.1) >> endobj 284 0 obj << /Type /ObjStm /N 98 /First 894 /Length 4257 /Filter /FlateDecode >> stream xÚí[ÛrÛF}çWà1©-s¿T¥¶Ê—(ÑÆvlÉIœué–`™JtH*ëì×oŸž8AÚ”Sû´åâ`ÐÓÓ—Ó==V>V¢RÁUR8º†J Y©H4£*)-Ñ<ýl¥U¤k¬Œ&ZT•sDºržæESy¥&*ÚÊÓ<] äø*Z\C%µ×Ô‰Ô ²ÒBTÒ[ uRBó¼CGWZ“t-L¥}Œ-,Ô:¢¸ÊX¨*sD–4=J«©cª¨|œH- éŠ0Ð4ˆÎ‘ß„dôÓmiñU ®I†Ž`òˆ‰¢ž"t¤Ðè.Œ#H4hp‘|Š$HŽ"Kм…Ô€ŸÂ™ ¢À<У#»ˆL:¨ƒXK2’'h“` …$Ödì¡ FBŽ:„~åÀŒp80;r ÞIOò-˜•s Ï ˜£FRP¤  HbV’8ኒ G j0kC®ƒÙ ³¡!ø¨, ×=áѽ†*ö°SRRæh ,‘ÐFáÆ(N‰X#?­ÔC‚zIéót ˆ¥’F?ш*ÚcÈq Œ˜A:L ´!&°Ú+$¥4°iH6R/ºÉ7ßLê“åí¦ú曪>±0BÒr<Ãã¬H7)ÓR)ã2ûÇ7ÿû¤~±Z^ž7›êMU¿xrRÕ¯š›êbBCÐôêÏ Ì®›Iý˜´6·›5/oš>©ÏšõònuÙ¬yµ3éYs5Ÿ=Z~¬ÞÀG€û¨.HÍlEs9Á—Å?©Þ Ž°a¯ýgåô”–’°SZ´·w‹ÅÅ>Fiå4’ÖÆ)­¦ÃÌÎT«ÜTP-êqîU'Ä {¨~.Ð7©ÏïÞnøD=©ŸÏnÖš z6Û¬æp*(×M}Eÿ"q=b+Kÿ(;)-/ÊxÀ§¡A§7ÆGÕ[{2_­7ßÏVä›ÔOgåÝ/ó«Íû5—lê··—Ë«ùí5o¦€ò×\ÇsDß9¥yQ8ÜΤ Ìß½k(`ÝÒRϨéàÁM…ÅÛŠ XS9Z6>º©¤"#¦¨©vjQ7Dî¦Ö‹0¥dÁ蔘ºÜ·QR«­e ÚD±ZMUÛƒ*TP{3™N»Ô”ö'c²qyv)UHâ0ÁMãÅä…DA1{£%ÒAOi]sßÒºþÜ_žZTØ ¬ÑÐËm¢Ž (H„@+¥òìƒWšÚ( ÙIe•6È„fR•‡OÖSÍÃ,–$Mî§r§yG0Ä›SÙfr²‚[/.YîŠþÐ+ZÉY¨•@3÷•ç8È<#Q[Øbá:J´ÐÍ3;îÄa<|7–[ã r”±¢(9c§q£möÿ¿ÿéïÿ¨ÿÑvµÈ:®ZÁ£¼,ûTIèÜL}j¯È}mÐ’ä‡Ú‰9^r­á6s¬ûHgïÀ¡R]e VrÝ’Ðï©bÈ®Ïú™Çp}Om’XŽÒ! U%K;déç´YfÑ&]%O¢xü¼à™|¦£¿ó\ƒ,<ö\sŸŒ‡\wjPˆ…$–šæg Š+#G(kHœÜÆ9%%E´ÄµD¥ô)Q3Ž[w—ñîhåPSäR„r渰<%»ˆåìÑílç`“Á6‚ÕÎ{¡M»k’«AI­ò)ª<švÑÞO*†÷a¾SŒÏÁ}䆞Š88LVE –¤fÛ+¹4oc©eñåXaÞ˜aû~jÇŠ$Õx>zø­p GݺÅû® ØÎsbñž >íü[?ž¥Ëã™Æs³ô´éçË· Nz¬ëÔ[Þ!zëè°W@ÀÂr4Š~=¦öbª¶2r(lŸ;qh>ŠèT“R@ŠÑä@ê§–5óy Çë¾´Mrrk²g2ªy*·¸&â#¼a^“(€tÆÀˆ×:²ÛGà#ÉÐk·S<¥;vC 7"— ›ûAG>Þ’*§8^æ‹éD¬r7µŽêyk5ô”h”Yã¸YƯ©†P=ñ™ÔÖ¦F´‰µÏ[Þ4n,ì0OtfËÅc ¡Ôç–âeã²§õôTn´ÅBI÷Œ¨§äo9B€¦¡DW^ñ/KWô¶š#Ú,{;FÏŒ¦ñ%mk ~Ùn§¸¢Mxé6c¼áÅK{N«)4si:ÇâYCóLÅk•2/ò,ÝÊK3³l~.²¦“ .¼ëÂu76†žÃýÞöbR8¶=EÉ_Žó ¦YªFï=Ïè¸ÒX˜›úÛ±dnês‹Åí*¼ à­ÖÓ½â%Ì%*h|ß̯ßÓmp“j0ö@bðt3[Ì/Þ^/šŠÄŸoš›Ÿñ¢sR¿Î“h;JoKð&æ«úaý¸þ¶~Z?«¬ÏêóúçzV¿­/ëËåÍͬ¾ª›ú]ýnþ]–w«úº~_ÏëÕ¿Õ7õm½¬—·Mý¡þЬæË«zU¯ëuóGs[oêÍûUÓÔ›/ë»úúß_'Oæd–¾|ãö)À^={ù§ç 0µ0 À$ÞìÆ¿0öˆ {B Ô§Üó Ü«:€ÆSG¡[0t·sBn€ßï‚ëùÇ]ëõŸ}$ã1Hž½~uúô!#ùêt_ò©˜“Oy$Ÿ¹/–s-š~/šg„YCØÇ=Ϥ<ʳ‡ÏžŸ=!ÏÎö¹eDv ï질þ¬qe†h¹/C¾«¿§,ù/0dÊ‹œ+?Q¶üÒ-µÅò¶Xp)wšßïf d’(çÑb›Jïÿüðžò$-ƱœÂëíEón“z+–™íÃânMÙöûÝrÓ\½]0W{“ù.uSNÞÌ“•Ûì\/fë÷ã9Zÿ§þO³Zöª èã“óŸ¾}ÁݳæélÀk>†ð×ÄÓˆç÷¹@¾ ˆÍ.ï6MQ"››ëúz5£+9ÒVGÀ·)àùs{ 4¯|úøåCã÷@£S®Gƒ?dÆÏ†ÆîÆêÑ‡æ” Þœý]‘§w}׎*õg¿œïË's®G”õ¹ŽÛÏ(>ìߪzž¨£6¨ïÎx~zO~=´ñFþÓ3ž½ÝºBå툊Vl¼FìÍì±ôìûwT½þîÕË'gß‘ûÚ¶§Ze¾¤bþ¹ðÉ•‹8ÒÚ3Úëâ”F{ko/]äcíàH¶i·¶>BG•í“ç'OÎ%„ömi®=Æâ)ú¯AHïEètïÙKU´½|}òg¯ý%Û¤ŠmõUìû½~=zýú©Ò}ÿ*}¯òüå5ù>ÕXí©ÆƒáG³uß&ì<¿öò‚?iâ?Çoÿš"ºýc¾ŒÅóýñê‡OƒõRì¨ï}K d§_h­~÷jh€TÏ[øoïa@ÿIg¨Ý µcIî«Â}u¼öÁ±|¨Ýíh{Á7Çkœ|‡Úw2Gúy_hw÷@~çp:0@íäžÖ=÷ËÐßcå OCCõ‡3/¨B{8^ûð3Ô¾›y¢—øBúïÿð„1Ôï>‘ù¢ˆ¾<^ýpûªßI>¯÷,{|z´úá&;P¯wS¯Wu•)Ô‹]õøœnïéî°+w߯éôýÙ¤þa~…o¤Ò馫IŸ´á£G¾:“¯ŒÆÅ½tø,˧/ÜdÈ÷ùó9™¾÷¢ëýu¨T**•θ•Ò&_“ÊdºµŸÒa÷êpÉ^åe¾&ÌTùê>%[éöY¨ÊBÓ·‹!?Þmt¦Xçt¨òÊD6ð×µés9V»™s:î F¦Ñ‡xeœº{¹¼¼X5ð§¹eåÙz;[šÝžãƒÄÖ¤¾¬üf²r±—•KI+j̬¼ÞX”ê‰j'g«ÄØdÙNÎEs87)lg<7v`ÆCXš½óSgS^Ö’ƒ÷@ ôuðÇ>ú­VçGÐØ¡µ/ #>†Û Ì…‹!ŒˆéPöaTLš9b€ï@öæ€Óª˲³ζµë®``WÆs mסíÜ1¦3’×®ƒÞ©bJèÝô®ƒÞ†ýbl7ÛÅÁˆƒ-ãàFÖ›í ¶ãóL;‚ªéP5‡ê…)aå¡¡3Ž3¡M’œ a ¬ÃÞ¨CÊJðÍø¦_‡rJßÍøº_*ÍHÞèb݇¸ Tï1Ÿso‘ѽäìKW]T? ²tH8¡:L•:0³„T@ª:HeØ/F–ù©|uºin¦’ùŒ•êküŸ”‚ AÁ€  ‚A§cOýt~3ß T¶lC³˜î0Ýò<BiS BÌ6½›_ß­¶;;Y®„ì‘4HjhY«u˵cX!WUZ439«LŸD¢TªÔÕWè¸ÈÆ)U\ê±€'Ú¡i[½ÛŽmi€½¥D8«z6ß–X¯]IñmxѲcY§µãÚcX¾‰âJç‘cºdQ„òº¤HPz<ð8¨q»Â×[®q»àé…€»$ ±­)HlW¢…Tõ%ÄHÕtÊÙ± [¦q“Ö¡”AȬ›ËÍ|y‹\Ò} áàûÒÔ®á–D¾ì.ÉVkÁµcY;D¾›ò>Ú> þ‹Ü’²Oƒg²{÷¶s…—ŠÚYØ0äÞµ·'h´ÜÑb¡ÅŽÑ‰ßÚ:jãPuz„N†:¿ãÅÀ²á”C®X€íÇL&Äý˜É„zÜåwp=Æ:Ö (|éÁœÊë‡Ø¾Ñy£^õ™ :îÓŒeº×,4?>È©¤íØ †A÷ ’AAy»c÷èäO¸ &ò*dÃ7³· Þ"TÐ%å-mrû­È¢ºæôRBç—:¿=ÑK¾ÎEWëph·­VxÂOçÓλ†Îg_ÑhcöÖ}v›l§q‡ìÚ™ý¤Y“6#´x<ÛÌËëIz³}Ô¾‰)M4Ý=ÿ³åUSÿ´n¶¯m~üÐÜ>ä࿯µêþ ‡¡@ endstream endobj 351 0 obj << /Type /XRef /Index [0 352] /Size 352 /W [1 3 1] /Root 349 0 R /Info 350 0 R /ID [<63DE43C20DA8E0AE9B73C20D9E7A027E> <63DE43C20DA8E0AE9B73C20D9E7A027E>] /Length 861 /Filter /FlateDecode >> stream xÚ%•KlNQ…÷¾¿¶ZúnU«­>´õ®RT[-UJ_ªÔ»šHÄTÌ$ωi $;F%fÌH„DD$bb"Üo™|ÙkÝsïï9kïßÌìob–˜[×u£êLëêa* è¢ʀY o* dƒmx{¨rÀl0ˆ·›*ä!¼ª9`.8ˆ·‹*€I¼T… œÀë§*%)bÞd)(ۋׇ,óð ñ¶#+À|¼¼mÈJP…׈׋\ªñãõ k@-Þ¼­È… o)^7²4àµâu!Á"¼uxÈ&Ќ׆·¹,ÁëÀë@.Ëðúð6#[Àr¼a¼MÈ`%ÞÞFä*°o¯¹¬ÅÇÛ€lëðöã­G¶ªÐÞKjq;ràŽD?¤7Ыmu³BEJo¿…uÚÄå hŸ›@ X´§ÚD>!QJzÜr¿êQ½\`O£ÎW¯D(*ʼۭè³nS&÷»Õß‘<FܪÞH<™ÝMFÁ^0öq·¦]Z|v[õNò˜ÇÜÚ~Ê;Î^Ñ8‘¶Uß4^¸Ûßú¬š£z&2nC×t•Ž Ú%²ÝÆåÑBAä#×mâ¥<º'è(p;“%ÈG±ÛÉË’%nçzT)fen§oJÑPDëy ]¥5B­AC„¢ÒíìÝ¡^ B@î£ÖíÂÇô³îÞÒűÉíê)Iªb¦¼´¸ÝвʚÂJDCÕn¬v»wAëÈPlp{”/Ùîöì‡*º"6¹=ž‘$aÁÁG§ÛÌy4q‹ Õ‚ š3èÚèu{ñ<}ñw¯µ˜ó~·Wý’ ²` 2D/˜\±Çíý­#*1æö©\rß«o#R1áöíÿD%Ò¨ü|*¨ÄqîLóò[ý“`Ê3ç¿+ YÀݳë$ 2îyùòrÀl ò€† ¦^>(xE ”€RPÊÓçýÒóæ¹÷PUá~ñ¡ªùîÓãª*Ó‚vUUž¬SµÀ“Ñ—ªª=¹s_U'3…ªj=yû@ÕBÏ”.SUç™ÖKª”¿µ@ƒQSJci/ÚX%Í¡@ª¿‰Cà08Ž‚c@»;é™sÓæ™ìÁÊ endstream endobj startxref 234493 %%EOF IRanges/inst/extdata/0000755000175100017510000000000012607265143015537 5ustar00biocbuildbiocbuildIRanges/inst/extdata/ce2chrM.bed0000644000175100017510000000027112607265143017476 0ustar00biocbuildbiocbuildchrM 13357 13651 trf 2 162.5 2 67 19 173 47 0 0 52 1.00 TA chrM 13436 13585 trf 7 23.9 7 66 28 61 46 0 0 53 1.00 ATTATAA chrM 13406 13658 trf 9 28.7 9 66 15 63 45 0 0 54 0.99 TATTATATT IRanges/inst/extdata/ce2chrM.fa.out0000644000175100017510000000714312607265143020145 0ustar00biocbuildbiocbuild SW perc perc perc query position in query matching repeat position in repeat score div. del. ins. sequence begin end (left) repeat class/family begin end (left) ID 210 19.5 0.0 7.2 chrM 433 515 (13279) + T-rich Low_complexity 2 78 (0) 1 28 6.1 0.0 0.0 chrM 543 591 (13203) + AT_rich Low_complexity 1 49 (0) 2 34 2.4 0.0 0.0 chrM 1345 1385 (12409) + AT_rich Low_complexity 1 41 (0) 3 26 8.2 0.0 0.0 chrM 2464 2524 (11270) + AT_rich Low_complexity 1 61 (0) 4 239 21.5 0.8 9.7 chrM 2566 2699 (11095) + T-rich Low_complexity 3 124 (0) 5 27 7.3 0.0 0.0 chrM 3922 3976 (9818) + AT_rich Low_complexity 1 55 (0) 6 37 5.7 0.0 3.3 chrM 4206 4296 (9498) + AT_rich Low_complexity 1 88 (0) 7 22 5.6 0.0 0.0 chrM 4759 4794 (9000) + AT_rich Low_complexity 1 36 (0) 8 28 2.9 0.0 0.0 chrM 5437 5471 (8323) + AT_rich Low_complexity 1 35 (0) 9 228 18.5 1.9 0.0 chrM 5538 5591 (8203) + T-rich Low_complexity 5 59 (0) 10 22 0.0 0.0 0.0 chrM 6584 6605 (7189) + AT_rich Low_complexity 1 22 (0) 11 36 9.7 0.0 0.0 chrM 6699 6811 (6983) + AT_rich Low_complexity 1 113 (0) 12 21 8.9 0.0 0.0 chrM 6978 7033 (6761) + AT_rich Low_complexity 1 56 (0) 13 26 8.8 0.0 0.0 chrM 7521 7588 (6206) + AT_rich Low_complexity 1 68 (0) 14 30 8.3 0.0 0.0 chrM 7794 7865 (5929) + AT_rich Low_complexity 1 72 (0) 15 21 0.0 0.0 0.0 chrM 8054 8074 (5720) + AT_rich Low_complexity 1 21 (0) 16 39 5.0 0.0 0.0 chrM 10561 10620 (3174) + AT_rich Low_complexity 1 60 (0) 17 207 16.8 6.6 4.7 chrM 10656 10761 (3033) + (TTTAA)n Simple_repeat 1 108 (0) 18 32 2.6 0.0 0.0 chrM 10947 10985 (2809) + AT_rich Low_complexity 1 39 (0) 19 25 0.0 0.0 0.0 chrM 11805 11829 (1965) + AT_rich Low_complexity 1 25 (0) 20 21 3.6 0.0 0.0 chrM 12027 12054 (1740) + AT_rich Low_complexity 1 28 (0) 21 24 3.2 0.0 0.0 chrM 12320 12350 (1444) + AT_rich Low_complexity 1 31 (0) 22 27 8.1 0.0 0.0 chrM 12727 12788 (1006) + AT_rich Low_complexity 1 62 (0) 23 22 9.9 0.0 0.0 chrM 12883 12953 (841) + AT_rich Low_complexity 1 71 (0) 24 60 7.2 0.0 1.9 chrM 13006 13161 (633) + AT_rich Low_complexity 1 153 (0) 25 28 9.1 0.0 0.0 chrM 13193 13269 (525) + AT_rich Low_complexity 1 77 (0) 26 468 6.9 9.4 0.0 chrM 13358 13516 (278) + (TA)n Simple_repeat 1 174 (0) 27 344 8.5 8.3 2.4 chrM 13491 13658 (136) + (TTATA)n Simple_repeat 2 179 (0) 28 IRanges/inst/extdata/hg18liftAll.lft0000644000175100017510000004065712607265143020341 0ustar00biocbuildbiocbuild0 1/NT_077402 167280 chr1 247249719 217280 1/NT_077911 40302 chr1 247249719 307582 1/NT_077912 153649 chr1 247249719 511231 1/NT_004350 2112849 chr1 247249719 2674080 1/NT_004321 1161048 chr1 247249719 3895128 1/NT_004547 1440092 chr1 247249719 5385220 1/NT_021937 7590365 chr1 247249719 13025585 1/NT_113791 116914 chr1 247249719 13192499 1/NT_077382 237250 chr1 247249719 13479749 1/NT_004873 3518496 chr1 247249719 17048245 1/NT_004610 12702424 chr1 247249719 29800669 1/NT_032977 73835825 chr1 247249719 103686494 1/NT_113792 157344 chr1 247249719 103893838 1/NT_019273 16604841 chr1 247249719 120548679 1/NT_086586 189539 chr1 247249719 120788218 1/NT_077389 398739 chr1 247249719 141476957 1/NT_113793 195588 chr1 247249719 141722545 1/NT_113794 186739 chr1 247249719 141959284 1/NT_113795 175055 chr1 247249719 142184339 1/NT_113796 201709 chr1 247249719 142436048 1/NT_113797 126477 chr1 247249719 142612525 1/NT_079485 194615 chr1 247249719 142857140 1/NT_079497 78698 chr1 247249719 142985838 1/NT_077932 127263 chr1 247249719 143163101 1/NT_077933 170669 chr1 247249719 143383770 1/NT_113798 38311 chr1 247249719 143522081 1/NT_004434 1022394 chr1 247249719 144594475 1/NT_034398 281532 chr1 247249719 144926007 1/NT_034400 1566655 chr1 247249719 146542662 1/NT_113799 185320 chr1 247249719 146777982 1/NT_079483 172789 chr1 247249719 147000771 1/NT_034401 220313 chr1 247249719 147271084 1/NT_034403 455185 chr1 247249719 147776269 1/NT_004487 56413061 chr1 247249719 204239330 1/NT_086602 259514 chr1 247249719 204548844 1/NT_021877 17265625 chr1 247249719 221864469 1/NT_004559 11394365 chr1 247249719 233308834 1/NT_004836 13665999 chr1 247249719 247024833 1/NT_032968 174886 chr1 247249719 50000 10/NT_077567 5577110 chr10 135374737 5677110 10/NT_077569 12337571 chr10 135374737 18064681 10/NT_008705 20794160 chr10 135374737 38908841 10/NT_024133 286100 chr10 135374737 41674941 10/NT_079540 191752 chr10 135374737 41916693 10/NT_033985 3830277 chr10 135374737 45896970 10/NT_031847 952205 chr10 135374737 46999175 10/NT_077570 263307 chr10 135374737 47412482 10/NT_077571 163231 chr10 135374737 47725713 10/NT_030772 989829 chr10 135374737 48865542 10/NT_017696 1941874 chr10 135374737 50857416 10/NT_035036 211435 chr10 135374737 51118851 10/NT_008583 30112613 chr10 135374737 81241464 10/NT_030059 44617998 chr10 135374737 125909462 10/NT_035040 2696597 chr10 135374737 128656059 10/NT_008818 4615335 chr10 135374737 133281394 10/NT_025835 246123 chr10 135374737 133577517 10/NT_017795 1797220 chr10 135374737 50000 11/NT_035113 1102759 chr11 134452384 1169335 11/NT_009237 49571094 chr11 134452384 50947429 11/NT_035158 503352 chr11 134452384 54450781 11/NT_033903 14395596 chr11 134452384 68848982 11/NT_078088 588129 chr11 134452384 69454899 11/NT_033927 17911127 chr11 134452384 87378026 11/NT_008984 8549206 chr11 134452384 95942794 11/NT_033899 38509590 chr11 134452384 16000 12/NT_009759 7043293 chr12 132349534 7132293 12/NT_009714 27615668 chr12 132349534 36142961 12/NT_029419 38648979 chr12 132349534 75041940 12/NT_019546 32815934 chr12 132349534 107914874 12/NT_009775 13091146 chr12 132349534 121156020 12/NT_009755 10116045 chr12 132349534 131317065 12/NT_024477 972469 chr12 132349534 17918000 13/NT_024524 67740325 chr13 114142980 85708325 13/NT_009952 25443670 chr13 114142980 111551995 13/NT_027140 1821999 chr13 114142980 113473994 13/NT_077627 184056 chr13 114142980 113758050 13/NT_024498 369930 chr13 114142980 18070000 14/NT_026437 88290585 chr14 106368585 18260000 15/NT_037852 1403478 chr15 100338915 19763478 15/NT_077631 334079 chr15 100338915 20197557 15/NT_078094 868737 chr15 100338915 21116294 15/NT_026446 3571299 chr15 100338915 24731593 15/NT_078095 438013 chr15 100338915 25270606 15/NT_010280 1108140 chr15 100338915 26478746 15/NT_078096 417989 chr15 100338915 26996735 15/NT_010194 53619965 chr15 100338915 80676700 15/NT_077661 2098777 chr15 100338915 82835477 15/NT_010274 13510195 chr15 100338915 96367672 15/NT_035325 3971243 chr15 100338915 0 16/NT_037887 8576922 chr16 88827254 8594422 16/NT_010393 25336229 chr16 88827254 34030651 16/NT_024773 1112651 chr16 88827254 44943302 16/NT_010498 42003582 chr16 88827254 86966884 16/NT_010542 1855370 chr16 88827254 0 17/NT_024972 296854 chr17 78774742 343376 17/NT_010718 21163833 chr17 78774742 21607209 17/NT_024862 579924 chr17 78774742 22287133 17/NT_010799 9412828 chr17 78774742 31799961 17/NT_078100 1629269 chr17 78774742 33529230 17/NT_010755 5072491 chr17 78774742 38701721 17/NT_010783 24793602 chr17 78774742 63585323 17/NT_010641 11472733 chr17 78774742 75211056 17/NT_024871 2103126 chr17 78774742 77379182 17/NT_010663 1275560 chr17 78774742 0 18/NT_010859 15400898 chr18 76117153 16764896 18/NT_010966 33548238 chr18 76117153 50360134 18/NT_025028 20074199 chr18 76117153 70462333 18/NT_025004 3388475 chr18 76117153 73872808 18/NT_010879 2244345 chr18 76117153 11000 19/NT_011255 7286004 chr19 63811651 7302004 19/NT_077812 1291194 chr19 63811651 8598198 19/NT_011295 15825424 chr19 63811651 32423622 19/NT_011109 31383029 chr19 63811651 0 2/NT_022327 1254071 chr2 242951149 1255071 2/NT_022221 2252116 chr2 242951149 3557187 2/NT_022139 1426129 chr2 242951149 5083316 2/NT_005334 11088087 chr2 242951149 16221403 2/NT_015926 4791168 chr2 242951149 21037571 2/NT_022184 68373980 chr2 242951149 89561551 2/NT_032994 397279 chr2 242951149 90958830 2/NT_034508 731068 chr2 242951149 94689898 2/NT_026970 2594449 chr2 242951149 97296847 2/NT_022171 12173457 chr2 242951149 109612304 2/NT_034485 736346 chr2 242951149 110498650 2/NT_077407 359898 chr2 242951149 111008548 2/NT_022135 38390280 chr2 242951149 149498828 2/NT_005403 84213157 chr2 242951149 233731985 2/NT_005120 5688986 chr2 242951149 239453971 2/NT_113800 12944 chr2 242951149 239496915 2/NT_022173 952154 chr2 242951149 240474069 2/NT_005416 2277080 chr2 242951149 8000 20/NT_011387 26259569 chr20 62435964 28033230 20/NT_025215 234339 chr20 62435964 29267569 20/NT_028392 5092930 chr20 62435964 34380499 20/NT_011362 26144333 chr20 62435964 60551882 20/NT_035608 71932 chr20 62435964 60733814 20/NT_011333 1702150 chr20 62435964 9719767 21/NT_029490 490233 chr21 46944323 13260000 21/NT_011512 28617429 chr21 46944323 41878628 21/NT_030188 1627105 chr21 46944323 43507092 21/NT_011515 3437231 chr21 46944323 14430000 22/NT_028395 647850 chr22 49691432 15227850 22/NT_011519 3661581 chr22 49691432 18939431 22/NT_011520 23276302 chr22 49691432 42227733 22/NT_011521 830225 chr22 49691432 43107958 22/NT_011523 4248192 chr22 49691432 47366250 22/NT_011525 1384186 chr22 49691432 48767136 22/NT_019197 320440 chr22 49691432 49089176 22/NT_113818 17927 chr22 49691432 49126803 22/NT_011526 464629 chr22 49691432 0 22_h2_hap1/NT_113959 63661 chr22_h2_hap1 63661 35000 3/NT_022517 66080833 chr3 199501827 66375833 3/NT_022459 24211711 chr3 199501827 94987544 3/NT_005612 100530253 chr3 199501827 195537797 3/NT_005535 1299866 chr3 199501827 196864663 3/NT_029928 2582164 chr3 199501827 0 4/NT_037622 1413146 chr4 191273063 1464146 4/NT_006081 2419310 chr4 191273063 3963456 4/NT_006051 4820284 chr4 191273063 8933740 4/NT_006316 22487426 chr4 191273063 31492166 4/NT_022794 976586 chr4 191273063 32527752 4/NT_016297 7445039 chr4 191273063 39992791 4/NT_006238 9040907 chr4 191273063 49183698 4/NT_037645 171176 chr4 191273063 52354874 4/NT_022853 7074452 chr4 191273063 59479326 4/NT_022778 9796115 chr4 191273063 69375441 4/NT_077444 2161413 chr4 191273063 71711854 4/NT_006216 3929449 chr4 191273063 75671303 4/NT_016354 92123751 chr4 191273063 167825054 4/NT_022792 23438009 chr4 191273063 63000 5/NT_006576 46378398 chr5 180857866 49441398 5/NT_006713 42230486 chr5 180857866 91711884 5/NT_023148 5878002 chr5 180857866 97612886 5/NT_034772 41199371 chr5 180857866 138817257 5/NT_029289 16301663 chr5 180857866 155123020 5/NT_023133 25714846 chr5 180857866 0 5_h2_hap1/NT_113801 1146088 chr5_h2_hap1 1794870 1186088 5_h2_hap1/NT_113802 608782 chr5_h2_hap1 1794870 5000 6/NT_034880 9194728 chr6 170899992 9249728 6/NT_007592 48945890 chr6 170899992 58245618 6/NT_033172 642507 chr6 170899992 61938125 6/NT_033948 248423 chr6 170899992 62236548 6/NT_007299 33500716 chr6 170899992 95937264 6/NT_025741 61645385 chr6 170899992 157632649 6/NT_007422 10134273 chr6 170899992 167784922 6/NT_007302 2236975 chr6 170899992 170171897 6/NT_007583 725095 chr6 170899992 0 6_cox_hap1/NT_113891 4731698 chr6_cox_hap1 4731698 0 6_qbl_hap2/NT_113892 475847 chr6_qbl_hap2 4565931 635157 6_qbl_hap2/NT_113893 1999704 chr6_qbl_hap2 4565931 2686011 6_qbl_hap2/NT_113894 291112 chr6_qbl_hap2 4565931 3003554 6_qbl_hap2/NT_113895 266639 chr6_qbl_hap2 4565931 3322986 6_qbl_hap2/NT_113896 623992 chr6_qbl_hap2 4565931 3973953 6_qbl_hap2/NT_113897 591978 chr6_qbl_hap2 4565931 34000 7/NT_029998 293567 chr7 158821424 477567 7/NT_007819 47690382 chr7 158821424 48207949 7/NT_030008 2130176 chr7 158821424 50378125 7/NT_033968 6577293 chr7 158821424 57005418 7/NT_023629 1052855 chr7 158821424 61058273 7/NT_023603 256182 chr7 158821424 61364455 7/NT_077528 190137 chr7 158821424 61604592 7/NT_007758 12749068 chr7 158821424 74603660 7/NT_007933 64426257 chr7 158821424 139054917 7/NT_007914 14846650 chr7 158821424 154001567 7/NT_034885 736332 chr7 158821424 154817899 7/NT_007741 4003525 chr7 158821424 0 8/NT_023736 7462059 chr8 146274826 7562059 8/NT_077531 4537293 chr8 146274826 12199352 8/NT_030737 9464880 chr8 146274826 21681632 8/NT_023666 8051036 chr8 146274826 29798768 8/NT_007995 14159284 chr8 146274826 46958052 8/NT_023678 1291149 chr8 146274826 48309201 8/NT_008183 38454502 chr8 146274826 86851003 8/NT_008046 57155273 chr8 146274826 144106276 8/NT_023684 1290020 chr8 146274826 145403396 8/NT_037704 871430 chr8 146274826 0 9/NT_008413 39653686 chr9 140273252 39703686 9/NT_086745 261110 chr9 140273252 40014796 9/NT_078049 208233 chr9 140273252 40273029 9/NT_113811 142805 chr9 140273252 40465834 9/NT_078041 464507 chr9 140273252 40980341 9/NT_078042 152873 chr9 140273252 41183214 9/NT_113812 172579 chr9 140273252 41405793 9/NT_078043 1198158 chr9 140273252 42653951 9/NT_078055 549743 chr9 140273252 43253694 9/NT_078045 632871 chr9 140273252 43936565 9/NT_079529 680077 chr9 140273252 44666642 9/NT_078077 181647 chr9 140273252 44898289 9/NT_078051 291910 chr9 140273252 45240199 9/NT_078053 465318 chr9 140273252 45755517 9/NT_113813 350909 chr9 140273252 46156426 9/NT_086759 194609 chr9 140273252 46401035 9/NT_086755 498918 chr9 140273252 46949953 9/NT_078078 157546 chr9 140273252 65207499 9/NT_078052 450681 chr9 140273252 65708180 9/NT_113814 223855 chr9 140273252 65982035 9/NT_113815 162441 chr9 140273252 66194476 9/NT_078058 159539 chr9 140273252 66404015 9/NT_078059 199148 chr9 140273252 66653163 9/NT_078065 194491 chr9 140273252 66897654 9/NT_079533 158462 chr9 140273252 67106116 9/NT_078066 471702 chr9 140273252 67627818 9/NT_078067 376183 chr9 140273252 68054001 9/NT_078068 174765 chr9 140273252 68278766 9/NT_078069 289439 chr9 140273252 68618205 9/NT_078070 682157 chr9 140273252 69350362 9/NT_078071 158187 chr9 140273252 69558549 9/NT_113816 187806 chr9 140273252 69796355 9/NT_113817 178933 chr9 140273252 70025288 9/NT_023935 21507948 chr9 140273252 91583236 9/NT_079535 85380 chr9 140273252 91718616 9/NT_008470 40394265 chr9 140273252 132212881 9/NT_035014 3818133 chr9 140273252 136231014 9/NT_019501 2075804 chr9 140273252 138336818 9/NT_024000 1936434 chr9 140273252 0 M/NC_001807 16571 chrM 16571 0 X/NT_086925 34821 chrX 154913754 84821 X/NT_078115 86563 chrX 154913754 201384 X/NT_028413 766173 chrX 154913754 1017557 X/NT_086929 36556 chrX 154913754 1104113 X/NT_086931 80121 chrX 154913754 1274234 X/NT_033330 754004 chrX 154913754 2128238 X/NT_011757 34879939 chrX 154913754 37033177 X/NT_079573 12096764 chrX 154913754 49179941 X/NT_086939 680972 chrX 154913754 50040913 X/NT_011638 2371726 chrX 154913754 52462639 X/NT_011630 6136098 chrX 154913754 61598737 X/NT_011669 14971611 chrX 154913754 76590348 X/NT_011651 36813576 chrX 154913754 113473924 X/NT_028405 2122394 chrX 154913754 115616318 X/NT_011786 27718692 chrX 154913754 143365010 X/NT_011681 5427710 chrX 154913754 148832720 X/NT_011726 6081034 chrX 154913754 0 Y/NT_113967 34821 chrY 57772954 84821 Y/NT_113968 86563 chrY 57772954 201384 Y/NT_113969 766173 chrY 57772954 1017557 Y/NT_113970 36556 chrY 57772954 1104113 Y/NT_113971 80121 chrY 57772954 1274234 Y/NT_113972 754004 chrY 57772954 2128238 Y/NT_113973 581282 chrY 57772954 2709520 Y/NT_011896 6265435 chrY 57772954 9024955 Y/NT_086998 276367 chrY 57772954 9901322 Y/NT_011878 813231 chrY 57772954 11214553 Y/NT_087001 39401 chrY 57772954 11653954 Y/NT_113819 554624 chrY 57772954 12308578 Y/NT_011875 10002238 chrY 57772954 22360816 Y/NT_011903 4867933 chrY 57772954 57228749 Y/NT_025975 98295 chrY 57772954 57377044 Y/NT_091573 66393 chrY 57772954 57443437 Y/NT_113974 329517 chrY 57772954 0 1/NT_113870 145186 chr1_random 1663265 195186 1/NT_113871 197748 chr1_random 1663265 442934 1/NT_113872 183763 chr1_random 1663265 676697 1/NT_113873 51825 chr1_random 1663265 778522 1/NT_113874 136815 chr1_random 1663265 965337 1/NT_113875 114056 chr1_random 1663265 1129393 1/NT_113876 25994 chr1_random 1663265 1205387 1/NT_113877 208942 chr1_random 1663265 1464329 1/NT_113878 106433 chr1_random 1663265 1620762 1/NT_113879 42503 chr1_random 1663265 0 10/NT_113918 113275 chr10_random 113275 0 11/NT_113919 40524 chr11_random 215294 90524 11/NT_113920 35155 chr11_random 215294 175679 11/NT_113921 39615 chr11_random 215294 0 13/NT_113923 186858 chr13_random 186858 0 15/NT_113924 139260 chr15_random 784346 189260 15/NT_113925 168820 chr15_random 784346 408080 15/NT_113926 119514 chr15_random 784346 577594 15/NT_113927 111864 chr15_random 784346 739458 15/NT_113928 44888 chr15_random 784346 0 16/NT_113929 105485 chr16_random 105485 0 17/NT_113930 174588 chr17_random 2617613 224588 17/NT_113931 186078 chr17_random 2617613 460666 17/NT_113932 104495 chr17_random 2617613 615161 17/NT_113933 142595 chr17_random 2617613 807756 17/NT_113934 120350 chr17_random 2617613 978106 17/NT_113935 185449 chr17_random 2617613 1213555 17/NT_113936 163628 chr17_random 2617613 1427183 17/NT_113937 37443 chr17_random 2617613 1514626 17/NT_113938 45226 chr17_random 2617613 1609852 17/NT_113939 147354 chr17_random 2617613 1807206 17/NT_113940 19187 chr17_random 2617613 1876393 17/NT_113941 37498 chr17_random 2617613 1963891 17/NT_113942 117663 chr17_random 2617613 2131554 17/NT_113943 81310 chr17_random 2617613 2262864 17/NT_113944 182567 chr17_random 2617613 2495431 17/NT_113945 41001 chr17_random 2617613 2586432 17/NT_113946 31181 chr17_random 2617613 0 18/NT_113947 4262 chr18_random 4262 0 19/NT_113948 92689 chr19_random 301858 142689 19/NT_113949 159169 chr19_random 301858 0 2/NT_113880 185571 chr2_random 185571 0 21/NT_113950 28709 chr21_random 1679693 78709 21/NT_113951 152296 chr21_random 1679693 281005 21/NT_113952 184355 chr21_random 1679693 515360 21/NT_113953 131056 chr21_random 1679693 696416 21/NT_113954 129889 chr21_random 1679693 876305 21/NT_113955 178865 chr21_random 1679693 1105170 21/NT_113956 150002 chr21_random 1679693 1305172 21/NT_113957 166452 chr21_random 1679693 1521624 21/NT_113958 158069 chr21_random 1679693 0 22/NT_113960 40752 chr22_random 257318 90752 22/NT_113961 166566 chr22_random 257318 0 3/NT_113881 146010 chr3_random 749256 196010 3/NT_113882 172475 chr3_random 749256 418485 3/NT_113883 137703 chr3_random 749256 606188 3/NT_113884 143068 chr3_random 749256 0 4/NT_113885 189789 chr4_random 842648 239789 4/NT_113886 96249 chr4_random 842648 386038 4/NT_113887 3994 chr4_random 842648 440032 4/NT_113888 191469 chr4_random 842648 681501 4/NT_113889 161147 chr4_random 842648 0 5/NT_113890 143687 chr5_random 143687 0 6/NT_113898 1305230 chr6_random 1875562 1355230 6/NT_113899 520332 chr6_random 1875562 0 7/NT_113900 112804 chr7_random 549659 162804 7/NT_113901 182896 chr7_random 549659 395700 7/NT_113902 153959 chr7_random 549659 0 8/NT_113903 12854 chr8_random 943810 62854 8/NT_113904 50950 chr8_random 943810 163804 8/NT_113905 183161 chr8_random 943810 396965 8/NT_113906 46082 chr8_random 943810 493047 8/NT_113907 37175 chr8_random 943810 580222 8/NT_113908 13036 chr8_random 943810 643258 8/NT_113909 38914 chr8_random 943810 732172 8/NT_113910 211638 chr8_random 943810 0 9/NT_113911 36148 chr9_random 1146434 86148 9/NT_113912 185143 chr9_random 1146434 321291 9/NT_113913 154740 chr9_random 1146434 526031 9/NT_113914 90085 chr9_random 1146434 666116 9/NT_113915 187035 chr9_random 1146434 903151 9/NT_113916 173443 chr9_random 1146434 1126594 9/NT_113917 19840 chr9_random 1146434 0 X/NT_113962 217385 chrX_random 1719168 267385 X/NT_113963 24360 chrX_random 1719168 341745 X/NT_113964 204131 chrX_random 1719168 595876 X/NT_113965 1005289 chrX_random 1719168 1651165 X/NT_113966 68003 chrX_random 1719168 IRanges/inst/extdata/hs_b36v3_chrY.agp0000644000175100017510000003070512607265143020557 0ustar00biocbuildbiocbuild# # Homo sapiens chromosome Y, reference assembly, complete sequence # # This file provides assembly instructions for sequence NC_000024 # included in reference assembly of NCBI build 36 (HGSC Finished Genome v4.0). # #chrom chr_start chr_stop part_no part_type comp_id/gap_len comp_type/gap_type comp_end/linkage orientation/empty chrY 1 34821 1 F BX640545.2 1 34821 + chrY 34822 84821 2 N 50000 contig no chrY 84822 122592 3 F AL954722.18 1 37771 + chrY 122593 157464 4 F BX537334.4 1 34872 - chrY 157465 171384 5 F BX000483.7 1999 15918 + chrY 171385 201384 6 N 30000 contig no chrY 201385 232395 7 F AL954664.17 8190 39200 - chrY 232396 265528 8 F BX000476.5 208 33340 + chrY 265529 482251 9 F AL732314.18 2001 218723 + chrY 482252 550112 10 F BX004827.18 51695 119555 + chrY 550113 723877 11 F AL683871.15 2001 175765 + chrY 723878 837875 12 F AL672311.26 2001 115998 + chrY 837876 967557 13 F AL672277.20 2001 131682 + chrY 967558 1017557 14 N 50000 contig no chrY 1017558 1054113 15 F BX908402.3 1 36556 + chrY 1054114 1104113 16 N 50000 contig no chrY 1104114 1147822 17 F BX649635.3 1 43709 + chrY 1147823 1184234 18 F BX901949.9 1685 38096 + chrY 1184235 1274234 19 N 90000 contig no chrY 1274235 1307891 20 F BX908382.8 1 33657 + chrY 1307892 1390773 21 F BX649553.6 2001 84882 + chrY 1390774 1425289 22 F BX901885.7 1 34516 + chrY 1425290 1458955 23 F BX119906.16 2001 35666 + chrY 1458956 1618348 24 F AL683870.15 1001 160393 + chrY 1618349 1661433 25 F AL691415.17 1 43085 + chrY 1661434 1849259 26 F AL683807.22 1 187826 + chrY 1849260 1966556 27 F AL672040.10 1 117297 + chrY 1966557 2028238 28 F CR381640.8 2001 63682 + chrY 2028239 2128238 29 N 100000 contig no chrY 2128239 2165561 30 F CR856018.10 1 37323 + chrY 2165562 2202890 31 F CR381696.5 2000 39328 + chrY 2202891 2280454 32 F BX649443.16 2001 79564 + chrY 2280455 2333896 33 F BX119919.5 1 53442 - chrY 2333897 2514591 34 F AC079176.15 1 180695 - chrY 2514592 2593088 35 F AC097314.27 1 78497 - chrY 2593089 2709520 36 F AC006209.25 23323 139754 - chrY 2709521 2838553 37 F AC006040.3 57272 186304 + chrY 2838554 2845472 38 F AC074181.1 1 6919 + chrY 2845473 2999955 39 F AC006157.2 1 154483 + chrY 2999956 3170037 40 F AC006032.2 1 170082 + chrY 3170038 3247254 41 F AC006152.4 1 77217 + chrY 3247255 3316539 42 F AC011305.2 1 69285 + chrY 3316540 3471638 43 F AC009479.4 1 155099 + chrY 3471639 3567129 44 F AC019058.4 1 95491 + chrY 3567130 3650550 45 F AC024038.6 1 83421 + chrY 3650551 3827222 46 F AC012078.3 1 176672 + chrY 3827223 3945458 47 F AC010094.5 1 118236 + chrY 3945459 4015462 48 F AC010737.4 1 70004 + chrY 4015463 4164401 49 F AC010084.3 1 148939 + chrY 4164402 4316800 50 F AC010905.3 1 152399 + chrY 4316801 4335619 51 F AC010106.2 1 18819 + chrY 4335620 4367320 52 F AC024703.5 1 31701 + chrY 4367321 4576407 53 F AC012077.4 1 209087 + chrY 4576408 4712669 54 F AC010142.4 1 136262 + chrY 4712670 4829264 55 F AC019060.5 1 116595 + chrY 4829265 4917080 56 F AC023423.5 1 87816 + chrY 4917081 5077603 57 F AC010722.2 1 160523 + chrY 5077604 5237705 58 F AC010685.3 1 160102 + chrY 5237706 5281650 59 F AC010129.3 1 43945 + chrY 5281651 5445957 60 F AC012067.2 1 164307 + chrY 5445958 5520761 61 F AC012667.2 1 74804 + chrY 5520762 5697342 62 F AC010081.4 1 176581 + chrY 5697343 5811187 63 F AC010874.3 1 113845 + chrY 5811188 5947272 64 F AC010977.4 1 136085 + chrY 5947273 6015798 65 F AC016681.2 1 68526 + chrY 6015799 6163940 66 F AC010140.3 1 148142 + chrY 6163941 6386252 67 F AC006335.2 1 222312 + chrY 6386253 6441403 68 F AC010154.3 1 55151 + chrY 6441404 6607550 69 F AC010144.4 1 166147 + chrY 6607551 6623520 70 F AC010728.4 1 15970 + chrY 6623521 6823534 71 F AC013412.3 1 200014 + chrY 6823535 6877729 72 F AC011297.3 1 54195 + chrY 6877730 7044045 73 F AC012068.5 1 166316 + chrY 7044046 7154095 74 F AC010104.3 1 110050 + chrY 7154096 7233943 75 F AC010143.3 1 79848 + chrY 7233944 7405192 76 F AC007284.4 1 171249 + chrY 7405193 7521780 77 F AC007247.5 1 116588 + chrY 7521781 7638889 78 F AC007274.3 1 117109 + chrY 7638890 7808593 79 F AC007275.4 1 169704 + chrY 7808594 7883829 80 F AC010678.4 1 75236 + chrY 7883830 7997798 81 F AC010902.4 1 113969 + chrY 7997799 8184715 82 F AC016749.4 1 186917 + chrY 8184716 8278929 83 F AC051663.9 1 94214 + chrY 8278930 8370383 84 F AC025731.12 1 91454 + chrY 8370384 8544585 85 F AC016991.5 1 174202 + chrY 8544586 8634069 86 F AC064829.6 1 89484 + chrY 8634070 8774803 87 F AC009491.3 1 140734 + chrY 8774804 8962150 88 F AC007967.3 1 187347 + chrY 8962151 8972934 89 F AC068719.3 1 10784 + chrY 8972935 8974955 90 F AC079126.3 1 2021 + chrY 8974956 9024955 91 N 50000 clone no chrY 9024956 9030327 92 F AC079125.4 1 5372 + chrY 9030328 9178185 93 F AC009952.4 1 147858 + chrY 9178186 9190963 94 F AC025732.9 1 12778 + chrY 9190964 9301322 95 F AC006158.6 1 110359 + chrY 9301323 9901322 96 N 600000 clone no chrY 9901323 10013703 97 F AC006156.5 1 112381 + chrY 10013704 10088698 98 F AC025819.7 1 74995 + chrY 10088699 10250877 99 F AC017019.3 1 162179 + chrY 10250878 10283186 100 F AC010891.2 1 32309 + chrY 10283187 10456943 101 F AC006986.3 1 173757 + chrY 10456944 10622784 102 F AC006987.2 1 165841 + chrY 10622785 10714553 103 F AC010970.3 1 91769 + chrY 10714554 11214553 104 N 500000 clone no chrY 11214554 11253954 105 F AC069323.5 1 39401 + chrY 11253955 11653954 106 N 400000 centromere no chrY 11653955 11738549 107 F AC140113.3 71061 155655 - chrY 11738550 11861114 108 F AC134878.3 33249 155813 - chrY 11861115 12003063 109 F AC134882.2 10706 152654 - chrY 12003064 12208578 110 F AC134879.3 1 205515 - chrY 12208579 12308578 111 N 100000 centromere no chrY 12308579 12468100 112 F AC011293.5 1 159522 + chrY 12468101 12581699 113 F AC012502.3 1 113599 + chrY 12581700 12759636 114 F AC011302.3 1 177937 + chrY 12759637 12838587 115 F AC013735.5 1 78951 + chrY 12838588 12911566 116 F AC004772.2 40021 112999 + chrY 12911567 12936024 117 F AC005942.2 1 24458 - chrY 12936025 13059669 118 F AC002992.1 2001 125645 + chrY 13059670 13234892 119 F AC004617.2 1 175223 + chrY 13234893 13319390 120 F AC004810.1 1 84498 - chrY 13319391 13515290 121 F AC002531.1 2001 197900 + chrY 13515291 13619376 122 F AC004474.1 44195 148280 + chrY 13619377 13664255 123 F AC006565.4 1 44879 - chrY 13664256 13879980 124 F AC005820.1 1 215725 - chrY 13879981 13952171 125 F AC010877.3 64839 137029 + chrY 13952172 14123978 126 F AC006376.2 1 171807 + chrY 14123979 14159738 127 F AC007004.3 1 35760 + chrY 14159739 14264748 128 F AC006383.2 1 105010 + chrY 14264749 14466902 129 F AC006371.2 1 202154 + chrY 14466903 14639848 130 F AC006370.2 1 172946 + chrY 14639849 14742756 131 F AC018677.3 1 102908 + chrY 14742757 14779500 132 F AC010720.4 1 36744 + chrY 14779501 14953720 133 F AC010723.3 1 174220 + chrY 14953721 14981864 134 F AC019191.4 1 28144 + chrY 14981865 15158188 135 F AC010726.4 1 176324 + chrY 15158189 15267382 136 F AC010979.3 1 109194 + chrY 15267383 15447103 137 F AC010879.2 1 179721 + chrY 15447104 15512578 138 F AC011903.4 1 65475 + chrY 15512579 15557501 139 F AC017032.3 1 44923 + chrY 15557502 15714967 140 F AC006989.3 1 157466 + chrY 15714968 15795304 141 F AC011289.4 1 80337 + chrY 15795305 15909741 142 F AC010972.3 1 114437 + chrY 15909742 15967360 143 F AC007007.3 1 57619 + chrY 15967361 16111420 144 F AC006998.3 1 144060 + chrY 16111421 16274030 145 F AC006382.3 1 162610 + chrY 16274031 16413824 146 F AC006462.3 1 139794 + chrY 16413825 16509580 147 F AC006336.4 1 95756 + chrY 16509581 16528817 148 F AC016671.3 1 19237 + chrY 16528818 16695020 149 F AC017020.4 1 166203 + chrY 16695021 16899873 150 F AC011749.2 1 204853 + chrY 16899874 16926987 151 F AC053516.10 1 27114 + chrY 16926988 17103738 152 F AC010135.3 1 176751 + chrY 17103739 17166324 153 F AC010128.3 1 62586 + chrY 17166325 17345839 154 F AC011751.2 1 179515 + chrY 17345840 17488621 155 F AC016678.4 1 142782 + chrY 17488622 17510633 156 F AC015979.4 1 22012 + chrY 17510634 17659631 157 F AC007034.4 1 148998 + chrY 17659632 17766833 158 F AC007043.3 1 107202 + chrY 17766834 17879511 159 F AC006999.2 1 112678 + chrY 17879512 17886218 160 F AC007042.3 1 6707 + chrY 17886219 17923463 161 F AC091329.3 1 37245 + chrY 17923464 18051552 162 F AC007972.4 1 128089 + chrY 18051553 18230132 163 F AC015978.4 1 178580 + chrY 18230133 18244934 164 F AC068704.4 1 14802 + chrY 18244935 18443908 165 F AC007742.4 1 198974 + chrY 18443909 18474219 166 F AC095381.1 1 30311 + chrY 18474220 18653273 167 F AC009976.4 1 179054 + chrY 18653274 18698502 168 F AC095380.1 1 45229 + chrY 18698503 18861991 169 F AC024183.4 1 163489 + chrY 18861992 19023659 170 F AC007241.3 1 161668 + chrY 19023660 19090333 171 F AC069130.6 1 66674 + chrY 19090334 19096847 172 F AC073962.5 1 6514 + chrY 19096848 19134213 173 F AC068541.7 1 37366 + chrY 19134214 19290370 174 F AC022486.4 1 156157 + chrY 19290371 19464252 175 F AC007379.2 1 173882 + chrY 19464253 19623962 176 F AC009235.4 1 159710 + chrY 19623963 19808739 177 F AC007244.2 1 184777 + chrY 19808740 19871998 178 F AC021210.4 1 63259 + chrY 19871999 20023872 179 F AC010133.4 1 151874 + chrY 20023873 20066067 180 F AC012062.4 1 42195 + chrY 20066068 20189568 181 F AC010137.3 1 123501 + chrY 20189569 20221039 182 F AC009977.4 1 31471 + chrY 20221040 20400963 183 F AC010889.3 1 179924 + chrY 20400964 20472584 184 F AC010151.3 1 71621 + chrY 20472585 20667823 185 F AC009233.3 1 195239 + chrY 20667824 20778857 186 F AC079157.3 1 111034 + chrY 20778858 20829067 187 F AC079261.2 1 50210 + chrY 20829068 20846452 188 F AC079156.4 1 17385 + chrY 20846453 20889975 189 F AC024250.6 1 43523 + chrY 20889976 20991065 190 F AC009240.6 1 101090 + chrY 20991066 21140390 191 F AC011745.4 1 149325 + chrY 21140391 21249363 192 F AC007678.3 1 108973 + chrY 21249364 21437477 193 F AC009494.2 1 188114 + chrY 21437478 21456819 194 F AC026061.8 1 19342 + chrY 21456820 21557572 195 F AC009489.3 1 100753 + chrY 21557573 21722251 196 F AC007876.2 1 164679 + chrY 21722252 21858422 197 F AC009239.3 1 136171 + chrY 21858423 22029157 198 F AC010086.4 1 170735 + chrY 22029158 22150215 199 F AC010141.2 1 121058 + chrY 22150216 22310816 200 F AC021107.3 1 160601 + chrY 22310817 22360816 201 N 50000 clone no chrY 22360817 22384194 202 F AC078938.3 1 23378 + chrY 22384195 22403616 203 F AC024236.5 1 19422 + chrY 22403617 22587631 204 F AC007322.4 1 184015 + chrY 22587632 22688058 205 F AC007359.3 1 100427 + chrY 22688059 22757212 206 F AC023342.3 1 69154 + chrY 22757213 22817822 207 F AC025227.6 1 60610 + chrY 22817823 23005516 208 F AC007320.3 1 187694 + chrY 23005517 23210553 209 F AC008175.2 1 205037 + chrY 23210554 23230057 210 F AC016694.2 1 19504 + chrY 23230058 23386813 211 F AC010080.2 1 156756 + chrY 23386814 23417437 212 F AC016911.6 1 30624 + chrY 23417438 23583695 213 F AC006366.4 201 166458 - chrY 23583696 23691182 214 F AC010088.4 1 107487 + chrY 23691183 23794414 215 F AC053490.2 1 103232 + chrY 23794415 23811321 216 F AC007039.6 1 16907 + chrY 23811322 23991466 217 F AC006983.4 1 180145 + chrY 23991467 24140496 218 F AC009947.2 1 149030 + chrY 24140497 24157833 219 F AC016707.2 1 17337 + chrY 24157834 24324069 220 F AC016752.2 1 166236 + chrY 24324070 24353833 221 F AC025246.6 1 29764 + chrY 24353834 24474584 222 F AC073649.3 1 120751 + chrY 24474585 24538834 223 F AC073893.4 1 64250 + chrY 24538835 24614390 224 F AC068601.8 1 75556 + chrY 24614391 24751872 225 F AC023274.2 1 137482 + chrY 24751873 24941229 226 F AC012005.4 1 189357 + chrY 24941230 24948693 227 F AC013465.4 1 7464 + chrY 24948694 25102779 228 F AC016698.3 1 154086 + chrY 25102780 25206726 229 F AC010153.3 1 103947 + chrY 25206727 25291998 230 F AC025735.4 1 85272 + chrY 25291999 25395154 231 F AC010089.4 1 103156 + chrY 25395155 25397101 232 F AC006982.3 1 1947 + chrY 25397102 25572891 233 F AC006338.6 1 175790 + chrY 25572892 25724743 234 F AC016728.4 1 151852 + chrY 25724744 25888772 235 F AC006386.4 1 164029 + chrY 25888773 26066341 236 F AC006328.5 1 177569 + chrY 26066342 26203218 237 F AC007562.4 1 136877 + chrY 26203219 26348595 238 F AC010682.3 1 145377 + chrY 26348596 26443316 239 F AC017005.7 1 94721 + chrY 26443317 26625199 240 F AC007965.3 1 181883 + chrY 26625200 26798241 241 F AC006991.3 1 173042 + chrY 26798242 26906387 242 F AC024067.4 1 108146 + chrY 26906388 27086206 243 F AC013734.4 1 179819 + chrY 27086207 27194539 244 F AC019099.6 1 108333 + chrY 27194540 27228749 245 F AC073880.5 1 34210 + chrY 27228750 57228749 246 N 30000000 heterochromatin no chrY 57228750 57327044 247 F AC068123.5 1 98295 + chrY 57327045 57377044 248 N 50000 clone no chrY 57377045 57443437 249 F AC025226.4 101674 168066 - chrY 57443438 57614293 250 F AJ271735.1 69145 240000 + chrY 57614294 57772954 251 F AJ271736.1 1 158661 + IRanges/inst/include/0000755000175100017510000000000012607265143015530 5ustar00biocbuildbiocbuildIRanges/inst/include/IRanges_defines.h0000644000175100017510000000312212607265143020724 0ustar00biocbuildbiocbuild/***************************************************************************** IRanges C interface: typedefs and defines ----------------------------------------- The IRanges C interface is split in 2 files: 1. IRanges_defines.h (this file): contains the typedefs and defines of the interface. 2. IRanges_interface.h (in this directory): contains the prototypes of the IRanges C routines that are part of the interface. Please consult IRanges_interface.h for how to use this interface in your package. *****************************************************************************/ #ifndef IRANGES_DEFINES_H #define IRANGES_DEFINES_H #include "S4Vectors_defines.h" #include #include /* * *_holder structs. */ typedef struct compressed_chars_list_holder { int length; const char *unlisted; const int *breakpoints; } CompressedCharsList_holder; typedef struct compressed_ints_list_holder { int length; const int *unlisted; const int *breakpoints; } CompressedIntsList_holder; typedef struct compressed_doubles_list_holder { int length; const double *unlisted; const int *breakpoints; } CompressedDoublesList_holder; typedef struct iranges_holder { const char *classname; int is_constant_width; int length; const int *width; const int *start; const int *end; int SEXP_offset; /* offset in 'names' member below */ SEXP names; } IRanges_holder; typedef struct compressed_iranges_list_holder { const char *classname; int length; const int *end; IRanges_holder unlistData_holder; } CompressedIRangesList_holder; #endif IRanges/inst/include/IRanges_interface.h0000644000175100017510000000624012607265143021253 0ustar00biocbuildbiocbuild/***************************************************************************** IRanges C interface: prototypes ------------------------------- The IRanges C interface is split in 2 files: 1. IRanges_defines.h (in this directory): contains the typedefs and defines of the interface. 2. IRanges_interface.h (this file): contains the prototypes of the IRanges C routines that are part of the interface. *****************************************************************************/ #include "IRanges_defines.h" /* * Comparing ranges. * (see Ranges_comparison.c) */ int overlap_code( int x_start, int x_width, int y_start, int y_width ); int invert_overlap_code(int code); /* * Low-level manipulation of IRanges objects. * (see IRanges_class.c) */ SEXP get_IRanges_start(SEXP x); SEXP get_IRanges_width(SEXP x); SEXP get_IRanges_names(SEXP x); int get_IRanges_length(SEXP x); IRanges_holder hold_IRanges(SEXP x); int get_length_from_IRanges_holder(const IRanges_holder *x_holder); int get_width_elt_from_IRanges_holder(const IRanges_holder *x_holder, int i); int get_start_elt_from_IRanges_holder(const IRanges_holder *x_holder, int i); int get_end_elt_from_IRanges_holder(const IRanges_holder *x_holder, int i); SEXP get_names_elt_from_IRanges_holder(const IRanges_holder *x_holder, int i); IRanges_holder get_linear_subset_from_IRanges_holder(const IRanges_holder *x_holder, int offset, int length); void set_IRanges_names(SEXP x, SEXP names); void copy_IRanges_slots(SEXP x, SEXP x0); SEXP new_IRanges(const char *classname, SEXP start, SEXP width, SEXP names); SEXP new_IRanges_from_IntPairAE(const char *classname, const IntPairAE *intpair_ae); SEXP new_list_of_IRanges_from_IntPairAEAE(const char *element_type, const IntPairAEAE *intpair_aeae); SEXP alloc_IRanges(const char *classname, int length); /* * Low-level manipulation of Grouping objects. * (see Grouping_class.c) */ SEXP get_H2LGrouping_high2low(SEXP x); SEXP get_H2LGrouping_low2high(SEXP x); SEXP get_Partitioning_names(SEXP x); SEXP get_PartitioningByEnd_end(SEXP x); SEXP new_PartitioningByEnd(const char *classname, SEXP end, SEXP names); /* * Low-level manipulation of CompressedList objects. * (see CompressedList_class.c) */ SEXP get_CompressedList_unlistData(SEXP x); SEXP get_CompressedList_partitioning(SEXP x); int get_CompressedList_length(SEXP x); SEXP get_CompressedList_names(SEXP x); SEXP new_CompressedList(const char *classname, SEXP unlistData, SEXP partitioning); CompressedIntsList_holder hold_CompressedIntegerList(SEXP x); int get_length_from_CompressedIntsList_holder(const CompressedIntsList_holder *x_holder); Ints_holder get_elt_from_CompressedIntsList_holder(const CompressedIntsList_holder *x_holder, int i); /* * Low-level manipulation of CompressedIRangesList objects. * (see CompressedIRangesList_class.c) */ CompressedIRangesList_holder hold_CompressedIRangesList(SEXP x); IRanges_holder get_elt_from_CompressedIRangesList_holder(const CompressedIRangesList_holder *x_holder, int i); /* * Low-level manipulation of RangedData objects. * (see RangedData_class.c) */ SEXP new_RangedData(const char *classname, SEXP ranges, SEXP values); IRanges/inst/include/_IRanges_stubs.c0000644000175100017510000001246312607265143020611 0ustar00biocbuildbiocbuild#include "IRanges_interface.h" #define DEFINE_CCALLABLE_STUB(retT, stubname, Targs, args) \ typedef retT(*__ ## stubname ## _funtype__)Targs; \ retT stubname Targs \ { \ static __ ## stubname ## _funtype__ fun = NULL; \ if (fun == NULL) \ fun = (__ ## stubname ## _funtype__) R_GetCCallable("IRanges", "_" #stubname); \ return fun args; \ } /* * Using the above macro when retT (the returned type) is void will make Sun * Studio 12 C compiler unhappy. So we need to use the following macro to * handle that case. */ #define DEFINE_NOVALUE_CCALLABLE_STUB(stubname, Targs, args) \ typedef void(*__ ## stubname ## _funtype__)Targs; \ void stubname Targs \ { \ static __ ## stubname ## _funtype__ fun = NULL; \ if (fun == NULL) \ fun = (__ ## stubname ## _funtype__) R_GetCCallable("IRanges", "_" #stubname); \ fun args; \ return; \ } /* * Stubs for callables defined in Ranges_comparison.c */ DEFINE_CCALLABLE_STUB(int, overlap_code, (int x_start, int x_width, int y_start, int y_width), ( x_start, x_width, y_start, y_width) ) DEFINE_CCALLABLE_STUB(int, invert_overlap_code, (int code), ( code) ) /* * Stubs for callables defined in IRanges_class.c */ DEFINE_CCALLABLE_STUB(SEXP, get_IRanges_start, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(SEXP, get_IRanges_width, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(SEXP, get_IRanges_names, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(int, get_IRanges_length, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(IRanges_holder, hold_IRanges, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(int, get_length_from_IRanges_holder, (const IRanges_holder *x_holder), ( x_holder) ) DEFINE_CCALLABLE_STUB(int, get_width_elt_from_IRanges_holder, (const IRanges_holder *x_holder, int i), ( x_holder, i) ) DEFINE_CCALLABLE_STUB(int, get_start_elt_from_IRanges_holder, (const IRanges_holder *x_holder, int i), ( x_holder, i) ) DEFINE_CCALLABLE_STUB(int, get_end_elt_from_IRanges_holder, (const IRanges_holder *x_holder, int i), ( x_holder, i) ) DEFINE_CCALLABLE_STUB(SEXP, get_names_elt_from_IRanges_holder, (const IRanges_holder *x_holder, int i), ( x_holder, i) ) DEFINE_CCALLABLE_STUB(IRanges_holder, get_linear_subset_from_IRanges_holder, (const IRanges_holder *x_holder, int offset, int length), ( x_holder, offset, length) ) DEFINE_NOVALUE_CCALLABLE_STUB(set_IRanges_names, (SEXP x, SEXP names), ( x, names) ) DEFINE_NOVALUE_CCALLABLE_STUB(copy_IRanges_slots, (SEXP x, SEXP x0), ( x, x0) ) DEFINE_CCALLABLE_STUB(SEXP, new_IRanges, (const char *classname, SEXP start, SEXP width, SEXP names), ( classname, start, width, names) ) DEFINE_CCALLABLE_STUB(SEXP, new_IRanges_from_IntPairAE, (const char *classname, const IntPairAE *intpair_ae), ( classname, intpair_ae) ) DEFINE_CCALLABLE_STUB(SEXP, new_list_of_IRanges_from_IntPairAEAE, (const char *element_type, const IntPairAEAE *intpair_aeae), ( element_type, intpair_aeae) ) DEFINE_CCALLABLE_STUB(SEXP, alloc_IRanges, (const char *classname, int length), ( classname, length) ) /* * Stubs for callables defined in Grouping_class.c */ DEFINE_CCALLABLE_STUB(SEXP, get_H2LGrouping_high2low, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(SEXP, get_H2LGrouping_low2high, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(SEXP, get_Partitioning_names, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(SEXP, get_PartitioningByEnd_end, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(SEXP, new_PartitioningByEnd, (const char *classname, SEXP end, SEXP names), ( classname, end, names) ) /* * Stubs for callables defined in CompressedList_class.c */ DEFINE_CCALLABLE_STUB(SEXP, get_CompressedList_unlistData, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(SEXP, get_CompressedList_partitioning, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(int, get_CompressedList_length, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(SEXP, get_CompressedList_names, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(SEXP, new_CompressedList, (const char *classname, SEXP unlistData, SEXP partitioning), ( classname, unlistData, partitioning) ) DEFINE_CCALLABLE_STUB(CompressedIntsList_holder, hold_CompressedIntegerList, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(int, get_length_from_CompressedIntsList_holder, (const CompressedIntsList_holder *x_holder), ( x_holder) ) DEFINE_CCALLABLE_STUB(Ints_holder, get_elt_from_CompressedIntsList_holder, (const CompressedIntsList_holder *x_holder, int i), ( x_holder, i) ) /* * Stubs for callables defined in CompressedIRangesList_class.c */ DEFINE_CCALLABLE_STUB(CompressedIRangesList_holder, hold_CompressedIRangesList, (SEXP x), ( x) ) DEFINE_CCALLABLE_STUB(IRanges_holder, get_elt_from_CompressedIRangesList_holder, (const CompressedIRangesList_holder *x_holder, int i), ( x_holder, i) ) /* * Stubs for callables defined in RangedData_class.c */ DEFINE_CCALLABLE_STUB(SEXP, new_RangedData, (const char *classname, SEXP ranges, SEXP values), ( classname, ranges, values) ) IRanges/inst/unitTests/0000755000175100017510000000000012607265143016107 5ustar00biocbuildbiocbuildIRanges/inst/unitTests/test_AtomicList.R0000644000175100017510000002552312607265143021350 0ustar00biocbuildbiocbuildtest_AtomicList_constructors <- function() { subclasses <- c(logical="LogicalList", integer="IntegerList", #double="NumericList", numeric="NumericList", complex="ComplexList", character="CharacterList", raw="RawList", Rle="RleList") for (elt_type in names(subclasses)) { subclass <- subclasses[[elt_type]] constructor <- get(subclass) vec1 <- get(elt_type)(6) vec2 <- get(elt_type)(8) target <- list(A=vec1, B=vec2) for (compress in c(TRUE, FALSE)) { current <- constructor(A=vec1, B=vec2, compress=compress) checkTrue(is(current, subclass)) checkIdentical(compress, is(current, "CompressedList")) checkIdentical(elt_type, elementType(current)) checkIdentical(target, as.list(current)) checkIdentical(unname(target), as.list(current, use.names=FALSE)) } } } test_AtomicList_GroupGenerics <- function() { vec1 <- c(1L,2L,3L,5L,2L,8L) vec2 <- c(15L,45L,20L,1L,15L,100L,80L,5L) for (compress in c(TRUE, FALSE)) { for (type in c("IntegerList", "RleList")) { list1 <- do.call(type, list(one = vec1, vec2, compress = compress)) checkIdentical(as.list(list1 + list1), Map("+", list1, list1)) checkIdentical(as.list(log(list1)), lapply(list1, log)) checkIdentical(as.list(round(sqrt(list1))), lapply(list1, function(x) round(sqrt(x)))) checkIdentical(sum(list1), sapply(list1, sum)) } } } test_AtomicList_general <- function() { vec1 <- c(1L,2L,NA,3L,NA,5L,2L,8L) vec2 <- c(NA,15L,45L,20L,NA,1L,15L,100L,80L,5L,NA) for (compress in c(TRUE, FALSE)) { for (type in c("IntegerList", "RleList")) { list1 <- do.call(type, list(one = vec1, vec2, compress = compress)) checkIdentical(as.list(list1 %in% c(1L, 5L)), lapply(list1, "%in%", c(1L, 5L))) checkIdentical(lapply(list1 %in% IntegerList(one = vec1, vec2, compress = compress), as.vector), mapply("%in%", lapply(list1, as.vector), list(one = vec1, vec2))) checkIdentical(as.list(is.na(list1)), lapply(list1, is.na)) checkIdentical(as.list(match(list1, c(1L, 5L))), lapply(list1, match, c(1L, 5L))) checkIdentical(lapply(match(list1, IntegerList(one = vec1, vec2, compress = compress)), as.vector), mapply(match, lapply(list1, as.vector), list(one = vec1, vec2))) checkIdentical(as.list(sort(list1)), lapply(list1, sort)) checkIdentical(as.list(unique(list1)), lapply(list1, unique)) } } } test_AtomicList_logical <- function() { vec1 <- c(TRUE,NA,FALSE, NA) vec2 <- c(TRUE,TRUE,FALSE,FALSE,TRUE,FALSE,TRUE,TRUE,TRUE) for (compress in c(TRUE, FALSE)) { for (type in c("LogicalList", "RleList")) { list1 <- do.call(type, list(one = vec1, vec2, compress = compress)) checkIdentical(as.list(!list1), lapply(list1, "!")) checkIdentical(as.list(which(list1)), lapply(list1, which)) } } } test_AtomicList_numerical <- function() { vec1 <- c(1L,2L,NA,3L,NA,5L,2L,8L) vec2 <- c(NA,15L,45L,20L,NA,1L,15L,100L,80L,5L,NA) for (compress in c(TRUE, FALSE)) { for (type in c("IntegerList", "RleList")) { list1 <- do.call(type, list(one = vec1, vec2, compress = compress)) list2 <- endoapply(list1, rev) checkIdentical(as.list(diff(list1)), lapply(list1, diff)) checkIdentical(as.list(pmax(list1, list2)), mapply(pmax, list1, list2)) checkIdentical(as.list(pmin(list1, list2)), mapply(pmin, list1, list2)) checkIdentical(as.list(pmax.int(list1, list2)), mapply(pmax.int, list1, list2)) checkIdentical(as.list(pmin.int(list1, list2)), mapply(pmin.int, list1, list2)) checkIdentical(mean(list1, na.rm=TRUE), sapply(list1, mean, na.rm=TRUE)) checkIdentical(var(list1, na.rm=TRUE), sapply(list1, var, na.rm=TRUE)) checkIdentical(cov(list1, list2, use="complete.obs"), mapply(cov, list1, list2, MoreArgs = list(use="complete.obs"))) checkIdentical(cor(list1, list2, use="complete.obs"), mapply(cor, list1, list2, MoreArgs = list(use="complete.obs"))) checkIdentical(sd(list1, na.rm=TRUE), sapply(list1, sd, na.rm=TRUE)) checkIdentical(median(list1, na.rm=TRUE), sapply(list1, median, na.rm=TRUE)) checkIdentical(quantile(list1, na.rm=TRUE), sapply(list1, quantile, na.rm=TRUE)) checkIdentical(mad(list1, na.rm=TRUE), sapply(list1, mad, na.rm=TRUE)) checkIdentical(IQR(list1, na.rm=TRUE), sapply(list1, IQR, na.rm=TRUE)) vec3 <- (-20:20)^2 vec3[c(1,10,21,41)] <- c(100L, 30L, 400L, 470L) list3 <- do.call(type, list(one = vec3, rev(vec3), compress = compress)) checkIdentical(as.list(smoothEnds(list3)), lapply(list3, smoothEnds)) checkIdentical(as.list(runmed(list3, 7)), lapply(list3, function(x) { y <- runmed(x, 7) if (type != "RleList") y <- as.vector(y) y })) } } } test_AtomicList_character <- function() { txt <- c("The", "licenses", "for", "most", "software", "are", "designed", "to", "take", "away", "your", "freedom", "to", "share", "and", "change", "it.", "", "By", "contrast,", "the", "GNU", "General", "Public", "License", "is", "intended", "to", "guarantee", "your", "freedom", "to", "share", "and", "change", "free", "software", "--", "to", "make", "sure", "the", "software", "is", "free", "for", "all", "its", "users") for (compress in c(TRUE, FALSE)) { for (type in c("CharacterList", "RleList")) { list1 <- do.call(type, list(one = txt, rev(txt), compress = compress)) checkIdentical(as.list(nchar(list1)), lapply(list1, nchar)) checkIdentical(as.list(chartr("@!*", "alo", list1)), lapply(list1, chartr, old="@!*", new="alo")) checkIdentical(as.list(tolower(list1)), lapply(list1, tolower)) checkIdentical(as.list(toupper(list1)), lapply(list1, toupper)) checkIdentical(as.list(sub("[b-e]",".", list1)), lapply(list1, sub, pattern="[b-e]", replacement=".")) checkIdentical(as.list(gsub("[b-e]",".", list1)), lapply(list1, gsub, pattern="[b-e]", replacement=".")) } } } test_RleList_methods <- function() { x1 <- RleList(11:15, 15L, integer(0), 15:16, compress=FALSE) x2 <- RleList(11:15, 15L, integer(0), 15:16, compress=TRUE) checkIdentical(as(runValue(x1), "CompressedIntegerList"), runValue(x2)) checkIdentical(as(runLength(x1), "CompressedIntegerList"), runLength(x2)) checkIdentical(as(ranges(x1), "CompressedIRangesList"), ranges(x2)) ## na.rm x <- RleList(c(NA,1,1), c(1L,NA_integer_,1L), c(1,Inf,1,-Inf),compress=TRUE) target <- RleList(c(1,2), c(1L,1L), c(Inf,Inf,-Inf)) current <- runsum(x,2, na.rm = TRUE) checkIdentical(target, current) target <- RleList(c(NA,2), c(NA_integer_,NA_integer_), c(Inf,Inf,-Inf)) current <- runsum(x,2, na.rm = FALSE) checkIdentical(target, current) target <- RleList(c(2,4), c(2,2), c(Inf, Inf, -Inf)) current <- runwtsum(x,2, c(2,2), na.rm = TRUE) checkIdentical(target, current) target <- RleList(c(NA,4), c(NA_real_,NA_real_), c(Inf,Inf,-Inf)) current <- runwtsum(x,2, c(2,2), na.rm = FALSE) checkIdentical(target, current) target <- RleList(c(1,1), c(1,1), c(Inf,Inf,-Inf)) current <- runmean(x, 2, na.rm = TRUE) checkIdentical(target, current) target <- RleList(c(NA,1), c(NA_real_, NA_real_), c(Inf, Inf, -Inf)) current <- runmean(x, 2, na.rm = FALSE) checkIdentical(target, current) x <- RleList(c(NA,1,2), c(2L,NA_integer_,1L), c(1,Inf,1,-Inf),compress=TRUE) target <- RleList(c(1,2), c(2L,1L), c(Inf,Inf,1)) current <- runq(x, 2, 2, na.rm = TRUE) checkIdentical(target, current) target <- RleList(c(NA,2), c(NA_integer_, NA_integer_), c(Inf, Inf, 1)) current <- runq(x, 2, 2, na.rm = FALSE) checkIdentical(target, current) ## Binary operations between an RleList and an atomic vector: a1 <- Rle(1, 999722111) a2 <- 20 * a1 a <- RleList(a1, a2, compress=TRUE) b1 <- c(a1, a1) b2 <- 20 * b1 b <- RleList(b1, b2, compress=FALSE) ## FIXME: 'a1 <= 19:21' is taking forever and eats up all the memory in ## BioC <= 2.12! Seems like 'a1' is expanded to integer vector first, which ## is not good :-/ #for (y in list(8L, 8, 19:21)) { for (y in list(8L, 8)) { ## With a CompressedRleList target <- RleList(a1 <= y, a2 <= y, compress=TRUE) current <- a <= y checkIdentical(target, current) target <- RleList(a1 + y, a2 + y, compress=TRUE) current <- a + y checkIdentical(target, current) target <- RleList(a1 * y, a2 * y, compress=TRUE) current <- a * y checkIdentical(target, current) target <- RleList(a1 / y, a2 / y, compress=TRUE) current <- a / y checkIdentical(target, current) ## With a SimpleRleList target <- RleList(b1 <= y, b2 <= y, compress=FALSE) current <- b <= y checkIdentical(target, current) target <- RleList(b1 + y, b2 + y, compress=FALSE) current <- b + y checkIdentical(target, current) target <- RleList(b1 * y, b2 * y, compress=FALSE) current <- b * y checkIdentical(target, current) target <- RleList(b1 / y, b2 / y, compress=FALSE) current <- b / y checkIdentical(target, current) } } IRanges/inst/unitTests/test_DataFrame-utils.R0000644000175100017510000000070312607265143022253 0ustar00biocbuildbiocbuild ## splitting test_DataFrame_splitting <- function() { data(swiss) rn <- rownames(swiss) sw <- DataFrame(swiss, row.names=rn) swisssplit <- split(swiss, swiss$Education) ## split swsplit <- split(sw, sw[["Education"]]) checkTrue(validObject(swsplit)) checkIdentical(as.list(lapply(swsplit, as.data.frame)), swisssplit) checkTrue(validObject(split(DataFrame(IRanges(1:26, 1:26), LETTERS), letters))) } IRanges/inst/unitTests/test_DataFrameList.R0000644000175100017510000001773312607265143021764 0ustar00biocbuildbiocbuildtest_DataFrameList_construction <- function() { checkDFL2dfl <- function(DFL, dfl) { checkIdentical(lapply(as.list(DFL), as.data.frame), dfl) } data(airquality) data(swiss) checkDFL2dfl(DataFrameList(swiss, airquality), list(swiss, airquality)) } test_SplitDataFrameList_construction <- function() { checkDFL2dfl <- function(DFL, dfl) { checkIdentical(lapply(as.list(DFL), as.data.frame), dfl) } striprownames <- function(x) { lapply(x, function(y) { rownames(y) <- NULL y }) } data(airquality) data(swiss) aq <- DataFrame(airquality) sw <- DataFrame(swiss, row.names=rownames(swiss)) aqsplit1 <- split(aq, aq[["Month"]]) aqsplit2 <- SplitDataFrameList(lapply(split(airquality, airquality[["Month"]]), as, "DataFrame")) checkIdentical(aqsplit1, aqsplit2) swsplit1 <- split(sw, sw[["Education"]]) swsplit2 <- SplitDataFrameList(lapply(split(swiss, swiss[["Education"]]), as, "DataFrame")) checkIdentical(swsplit1, swsplit2) for (compress in c(TRUE, FALSE)) { airqualitysplit <- striprownames(split(airquality, airquality[["Month"]])) aqsplit <- SplitDataFrameList(as.list(split(aq, aq[["Month"]])), compress = compress) checkDFL2dfl(aqsplit, airqualitysplit) swisssplit <- split(swiss, swiss[["Education"]]) swsplit <- SplitDataFrameList(as.list(split(sw, sw[["Education"]])), compress = compress) checkDFL2dfl(swsplit, swisssplit) } } test_DataFrameList_subset <- function() { checkDFL2dfl <- function(DFL, dfl) { checkIdentical(lapply(as.list(DFL), as.data.frame), dfl) } data(airquality) data(swiss) DFL1 <- DataFrameList(swiss, airquality) dfl1 <- list(swiss, airquality) checkDFL2dfl(DFL1[], dfl1[]) checkDFL2dfl(DFL1[1], dfl1[1]) checkDFL2dfl(DFL1[2:1], dfl1[2:1]) checkIdentical(as.data.frame(DFL1[[2]]), airquality) checkException(DFL1[[3]], silent = TRUE) DFL2 <- DataFrameList(s = swiss, a = airquality) dfl2 <- list(s = swiss, a = airquality) checkDFL2dfl(DFL2[], dfl2[]) checkDFL2dfl(DFL2[1], dfl2[1]) checkDFL2dfl(DFL2["a"], dfl2["a"]) checkDFL2dfl(DFL2[c("a", "s")], dfl2[c("a", "s")]) checkIdentical(as.data.frame(DFL2[["a"]]), airquality) checkIdentical(DFL2[["z"]], NULL) } test_SplitDataFrameList_subset <- function() { checkDFL2dfl <- function(DFL, dfl) { checkIdentical(lapply(as.list(DFL), as.data.frame), dfl) } data(swiss) sw <- DataFrame(swiss, row.names = rownames(swiss)) for (compress in c(TRUE, FALSE)) { swsplit <- SplitDataFrameList(as.list(split(sw, sw[["Education"]])), compress = compress) swisssplit <- split(swiss, swiss[["Education"]]) checkDFL2dfl(swsplit[], swisssplit[]) checkDFL2dfl(swsplit[1], swisssplit[1]) checkDFL2dfl(swsplit[2:1], swisssplit[2:1]) checkIdentical(as.data.frame(swsplit[[2]]), swisssplit[[2]]) checkIdentical(swsplit[["A"]], NULL) checkException(swsplit[[30]], silent = TRUE) checkIdentical(as.list(swsplit[,1]), split(swiss[[1]], swiss[["Education"]])) checkIdentical(as.list(swsplit[,"Examination"]), split(swiss[["Examination"]], swiss[["Education"]])) } } test_SplitDataFrameList_as_data.frame <- function() { checkDFL2dfl <- function(DFL, dfl, compress) { df <- data.frame(group = togroup(dfl), group_name = names(dfl)[togroup(dfl)], do.call(rbind, dfl), stringsAsFactors=FALSE, row.names=NULL) if (compress) rownames(df) <- unlist(lapply(dfl, row.names), use.names = FALSE) checkIdentical(as.data.frame(DFL), df) } data(swiss) sw <- DataFrame(swiss, row.names = rownames(swiss)) for (compress in c(TRUE, FALSE)) { swsplit <- SplitDataFrameList(as.list(split(sw, sw[["Education"]])), compress = compress) swisssplit <- split(swiss, swiss[["Education"]]) checkDFL2dfl(swsplit, swisssplit, compress) } } test_DataFrameList_replace <- function() { checkDFL2dfl <- function(DFL, dfl) { checkIdentical(lapply(as.list(DFL), as.data.frame), dfl) } data(airquality) data(swiss) DFL1 <- DataFrameList(swiss, airquality) dfl1 <- list(swiss, airquality) DFL1[] <- DFL1[1] dfl1[] <- dfl1[1] checkDFL2dfl(DFL1, dfl1) DFL1 <- DataFrameList(swiss, airquality) dfl1 <- list(swiss, airquality) DFL1[2] <- DFL1[1] dfl1[2] <- dfl1[1] checkDFL2dfl(DFL1, dfl1) DFL1 <- DataFrameList(swiss, airquality) dfl1 <- list(swiss, airquality) DFL1[[1]][[1]] <- DFL1[[1]][[1]] + 1L dfl1[[1]][[1]] <- dfl1[[1]][[1]] + 1L checkDFL2dfl(DFL1, dfl1) } test_SplitDataFrameList_replace <- function() { checkDFL2dfl <- function(DFL, dfl) { checkIdentical(lapply(as.list(DFL), as.data.frame), dfl) } striprownames <- function(x) { lapply(x, function(y) { rownames(y) <- NULL y }) } data(airquality) data(swiss) swiss2 <- swiss rownames(swiss2) <- NULL sw2 <- DataFrame(swiss2) for (compress in c(TRUE, FALSE)) { swiss2split <- striprownames(split(swiss2, swiss2[["Education"]])) sw2split <- SplitDataFrameList(as.list(split(sw2, sw2[["Education"]])), compress = compress) swiss2split[] <- swiss2split[1] sw2split[] <- sw2split[1] checkDFL2dfl(sw2split, swiss2split) swiss2split <- striprownames(split(swiss2, swiss2[["Education"]])) sw2split <- SplitDataFrameList(as.list(split(sw2, sw2[["Education"]])), compress = compress) swiss2split[c(2, 4, 5)] <- swiss2split[1] sw2split[c(2, 4, 5)] <- sw2split[1] checkDFL2dfl(sw2split, swiss2split) swiss2split <- striprownames(split(swiss2, swiss2[["Education"]])) swiss2split <- lapply(swiss2split, function(x) {x[["Examination"]] <- x[["Examination"]] + 1L; x}) sw2split <- SplitDataFrameList(as.list(split(sw2, sw2[["Education"]])), compress = compress) sw2split[,"Examination"] <- sw2split[,"Examination"] + 1L checkDFL2dfl(sw2split, swiss2split) swiss2split <- striprownames(split(swiss2, swiss2[["Education"]])) swiss2split <- lapply(swiss2split, function(x) { x[["Examination"]][x[["Examination"]] > 22] <- x[["Examination"]][x[["Examination"]] > 22] + 1L x }) sw2split <- SplitDataFrameList(as.list(split(sw2, sw2[["Education"]])), compress = compress) sw2split[sw2split[, "Examination"] > 22, "Examination"] <- sw2split[sw2split[, "Examination"] > 22,"Examination"] + 1L checkDFL2dfl(sw2split, swiss2split) } } test_DataFrameList_transform <- function() { DF <- DataFrame(state.division, state.region, state.area) DFL <- split(DF, DF$state.division) # NICER: split(DF, ~ state.devision) DFL <- transform(DFL, total.area=sum(state.area[state.region!="South"]), fraction=ifelse(total.area == 0, 0, state.area/total.area)) ANS <- DataFrame(lapply(unlist(DFL, use.names=FALSE), unname)) df <- as.data.frame(DF) df$total.area <- with(subset(df, state.region != "South"), sapply(split(state.area, state.division), sum))[df$state.division] df$fraction <- with(df, ifelse(total.area == 0, 0, state.area/total.area)) df <- df[order(df$state.division),] rownames(df) <- NULL checkIdentical(ANS, DataFrame(df)) } IRanges/inst/unitTests/test_Grouping-class.R0000644000175100017510000001316412607265143022173 0ustar00biocbuildbiocbuild### test_PartitioningByEnd <- function() { ## on a numeric vector, NG not supplied current0 <- PartitioningByEnd() checkTrue(validObject(current0)) target <- new("PartitioningByEnd") checkIdentical(target, current0) breakpoints <- c(0, 5, 5, 8) current1 <- PartitioningByEnd(breakpoints) checkTrue(validObject(current1)) checkIdentical(4L, length(current1)) checkIdentical(as.integer(breakpoints), end(current1)) checkIdentical(end(current1), cumsum(width(current1))) checkIdentical(NULL, names(current1)) checkException(PartitioningByEnd(breakpoints, names=letters), silent=TRUE) current2 <- PartitioningByEnd(breakpoints, names=letters[1:4]) checkTrue(validObject(current2)) checkIdentical(letters[1:4], names(current2)) names(breakpoints) <- names(current2) current3 <- PartitioningByEnd(breakpoints) checkIdentical(current2, current3) current4 <- PartitioningByEnd(breakpoints, names=LETTERS[4:1]) checkIdentical(LETTERS[4:1], names(current4)) breakpoints <- rep.int(0, 1000) current5 <- PartitioningByEnd(breakpoints) checkTrue(validObject(current5)) checkIdentical(as.integer(breakpoints), end(current5)) checkIdentical(end(current5), cumsum(width(current5))) ## on a PartitioningByEnd object checkIdentical(current1, PartitioningByEnd(current1)) # no-op checkIdentical(current2, PartitioningByEnd(current2)) # no-op checkException(PartitioningByEnd(current2, names=LETTERS), silent=TRUE) current6 <- PartitioningByEnd(current2, names=names(current4)) checkTrue(validObject(current6)) checkIdentical(names(current4), names(current6)) ## on CompressedList, SimpleList, IRanges, and list objects do_checks <- function(x) { checkIdentical(current1, PartitioningByEnd(x)) checkException(PartitioningByEnd(x, names=letters), silent=TRUE) checkIdentical(current2, PartitioningByEnd(x, names=names(current2))) names(x) <- names(current2) checkIdentical(current2, PartitioningByEnd(x)) checkIdentical(current4, PartitioningByEnd(x, names=names(current4))) } x <- RleList(Rle(), Rle(-3, 5), Rle(), Rle(1:0, c(2,1)), compress=TRUE) do_checks(x) do_checks(as(x, "SimpleList")) do_checks(as.list(x)) x <- IRanges(seq(148, by=-50, length.out=4), width=width(current1)) do_checks(x) do_checks(as.list(x)) do_checks(list(NULL, integer(5), complex(0), raw(3))) } test_PartitioningByWidth <- function() { ## on a numeric vector, NG not supplied current0 <- PartitioningByWidth() checkTrue(validObject(current0)) target <- new("PartitioningByWidth") checkIdentical(target, current0) widths <- c(0, 5, 0, 3) current1 <- PartitioningByWidth(widths) checkTrue(validObject(current1)) checkIdentical(4L, length(current1)) checkIdentical(as.integer(widths), width(current1)) checkIdentical(end(current1), cumsum(width(current1))) checkIdentical(NULL, names(current1)) checkException(PartitioningByWidth(widths, names=letters), silent=TRUE) current2 <- PartitioningByWidth(widths, names=letters[1:4]) checkTrue(validObject(current2)) checkIdentical(letters[1:4], names(current2)) names(widths) <- names(current2) current3 <- PartitioningByWidth(widths) checkIdentical(current2, current3) current4 <- PartitioningByWidth(widths, names=LETTERS[4:1]) checkIdentical(LETTERS[4:1], names(current4)) widths <- rep.int(0, 1000) current5 <- PartitioningByWidth(widths) checkTrue(validObject(current5)) checkIdentical(as.integer(widths), width(current5)) checkIdentical(end(current5), cumsum(width(current5))) ## on a PartitioningByWidth object checkIdentical(current1, PartitioningByWidth(current1)) # no-op checkIdentical(current2, PartitioningByWidth(current2)) # no-op checkException(PartitioningByWidth(current2, names=LETTERS), silent=TRUE) current6 <- PartitioningByWidth(current2, names=names(current4)) checkTrue(validObject(current6)) checkIdentical(names(current4), names(current6)) ## on CompressedList, SimpleList, IRanges, and list objects do_checks <- function(x) { checkIdentical(current1, PartitioningByWidth(x)) checkException(PartitioningByWidth(x, names=letters), silent=TRUE) checkIdentical(current2, PartitioningByWidth(x, names=names(current2))) names(x) <- names(current2) checkIdentical(current2, PartitioningByWidth(x)) checkIdentical(current4, PartitioningByWidth(x, names=names(current4))) } x <- RleList(Rle(), Rle(-3, 5), Rle(), Rle(1:0, c(2,1)), compress=TRUE) do_checks(x) do_checks(as(x, "SimpleList")) do_checks(as.list(x)) x <- IRanges(seq(148, by=-50, length.out=4), width=width(current1)) do_checks(x) do_checks(as.list(x)) do_checks(list(NULL, integer(5), complex(0), raw(3))) } test_PartitioningByEndOrWidth_NG_supplied <- function() { for (class in c("PartitioningByEnd", "PartitioningByWidth")) { CONSTRUCTOR <- get(class) x <- c(3, 3, 4, 6) NG <- 8 current1 <- CONSTRUCTOR(x, NG) checkTrue(is(current1, class)) checkTrue(validObject(current1)) checkIdentical(8L, length(current1)) checkIdentical(tabulate(x, nbins=NG), width(current1)) checkException(CONSTRUCTOR(x, NG, names=letters[1:4]), silent=TRUE) current2 <- CONSTRUCTOR(x, NG, names=letters[1:8]) checkTrue(validObject(current2)) checkIdentical(letters[1:8], names(current2)) names(x) <- letters[1:4] current3 <- CONSTRUCTOR(x, NG) checkIdentical(current1, current3) } } IRanges/inst/unitTests/test_HitsList.R0000644000175100017510000000043412607265143021035 0ustar00biocbuildbiocbuildtest_HitsList_as_matrix <- function() { x <- RangedData(IRanges(start=c(1,6), end=c(5,10)), space=c("chr1","chr2")) y <- RangedData(IRanges(start=8, end=10), space="chr2") checkIdentical(as.matrix(findOverlaps(x, y)), cbind(queryHits = 2L, subjectHits = 1L)) } IRanges/inst/unitTests/test_IRanges-class.R0000644000175100017510000000432412607265143021727 0ustar00biocbuildbiocbuildtest_IRanges_names <- function() { range1 <- IRanges(start=c(1,2,3), end=c(5,2,8)) checkIdentical(names(range1), NULL) nms <- c("a", NA, "b") names(range1) <- nms checkIdentical(names(range1), nms) checkTrue(validObject(nms)) names(range1) <- NULL checkTrue(validObject(nms)) checkIdentical(names(range1), NULL) names(range1) <- "a" checkTrue(validObject(range1)) checkIdentical(names(range1), c("a", NA, NA)) checkException(names(range1) <- c("a", "b", "c", "d"), silent = TRUE) } test_Ranges_isDisjoint <- function() { ir1 <- IRanges(c(2,5,1), c(3,7,3)) ir2 <- IRanges(c(2,9,5), c(3,9,6)) ir3 <- IRanges(1, 5) checkIdentical(isDisjoint(ir1), FALSE) checkIdentical(isDisjoint(ir2), TRUE) checkIdentical(isDisjoint(ir3), TRUE) ## Handling of zero-width ranges current <- sapply(11:17, function(i) isDisjoint(IRanges(c(12, i), width=c(4, 0)))) target <- rep(c(TRUE, FALSE, TRUE), c(2, 3, 2)) checkIdentical(target, current) } test_IRanges_combine <- function() { range <- IRanges(start=c(1,2,3,1), end=c(5,2,8,3)) srange <- split(range, start(range) == 1) checkIdentical(srange, as(RangesList(`FALSE` = range[2:3], `TRUE` = range[c(1,4)]), "CompressedIRangesList")) checkIdentical(do.call(c, unname(as.list(srange))), IRanges(c(2,3,1,1), c(2,8,5,3))) ir1 <- IRanges(1, 10) ir2 <- IRanges(c(1, 15), width=5) mcols(ir2) <- DataFrame(score=1:2) checkIdentical(mcols(c(ir1, ir2)), DataFrame(score = c(NA, 1L, 2L))) ## Combining multiple IRanges object with varying mcols mcols(ir1) <- DataFrame(gc=0.78) checkException(c(ir1, ir2), silent=TRUE) checkIdentical(mcols(c(ir1, ir2, ignore.mcols=TRUE)), NULL) } test_IRanges_subset <- function() { # by range query <- IRanges(c(1, 4, 9), c(5, 7, 10)) subject <- IRanges(c(6, 8, 10), c(7, 12, 14)) checkIdentical(subsetByOverlaps(query, subject), query[2:3]) } test_IRanges_annotation <- function() { range <- IRanges(c(1, 4), c(5, 7)) mcols(range) <- DataFrame(a = 1:2) checkIdentical(mcols(range)[,1], 1:2) checkIdentical(mcols(range[2:1])[,1], 2:1) checkIdentical(mcols(c(range,range))[,1], rep(1:2,2)) } IRanges/inst/unitTests/test_NCList-class.R0000644000175100017510000004065612607265143021543 0ustar00biocbuildbiocbuild### findOverlaps_NCList <- IRanges:::findOverlaps_NCList findOverlaps_NCLists <- IRanges:::findOverlaps_NCLists .transpose_hits <- function(hits) { if (is.list(hits)) return(lapply(hits, .transpose_hits)) t(hits) } ### Used in the unit tests for GNCList located in GenomicRanges. .compare_hits <- function(target, current) { if (is.list(target) || is(target, "List") && is.list(current) || is(current, "List")) return(all(mapply(.compare_hits, target, current))) identical(.transpose_hits(target), .transpose_hits(current)) } ### Used in the unit tests for GNCList located in GenomicRanges. .make_Hits_from_q2s <- function(q2s, s_len) { q_hits <- rep.int(seq_along(q2s), elementLengths(q2s)) s_hits <- as.integer(unlist(q2s, use.names=FALSE)) Hits(q_hits, s_hits, length(q2s), s_len) } .make_Hits_from_s2q <- function(s2q, q_len) .transpose_hits(.make_Hits_from_q2s(s2q, q_len)) .select_hits <- function(x, select) { if (is.list(x)) return(lapply(x, .select_hits, select)) selectHits(x, select) } ### Used in the unit tests for GNCList located in GenomicRanges. .overlap_score <- function(query, subject) { pmin(end(query), end(subject)) - pmax(start(query), start(subject)) + 1L } .get_query_overlaps <- function(query, subject, min.score, type) { ok <- .overlap_score(query, subject) >= min.score if (type %in% c("start", "end")) { if (type == "start") d <- abs(start(subject) - start(query)) if (type == "end") d <- abs(end(subject) - end(query)) if (min.score >= 1L) { dmax <- 0L } else { dmax <- 1L - min.score } ok <- ok & (d <= dmax) } else if (type != "any") { codes <- rangeComparisonCodeToLetter(compare(query, subject)) type_codes <- switch(type, #"start" = c("f", "g", "h"), #"end" = c("d", "g", "j"), "within" = c("f", "g", "i", "j"), "extend" = c("d", "e", "g", "h"), "equal" = "g" ) ok <- ok & (codes %in% type_codes) } which(ok) } .findOverlaps_naive <- function(query, subject, min.score=1L, type=c("any", "start", "end", "within", "extend", "equal"), select=c("all", "first", "last", "arbitrary", "count")) { type <- match.arg(type) select <- match.arg(select) hits_per_query <- lapply(seq_along(query), function(i) .get_query_overlaps(query[i], subject, min.score, type)) hits <- .make_Hits_from_q2s(hits_per_query, length(subject)) selectHits(hits, select=select) } test_NCList <- function() { x <- IRanges(rep.int(1:5, 5:1), c(1:5, 2:5, 3:5, 4:5, 5), names=LETTERS[1:15]) mcols(x) <- DataFrame(score=seq(0.7, by=0.045, length.out=15)) nclist <- NCList(x) checkTrue(is(nclist, "NCList")) checkTrue(validObject(nclist, complete=TRUE)) checkIdentical(x, ranges(nclist, use.mcols=TRUE)) checkIdentical(length(x), length(nclist)) checkIdentical(names(x), names(nclist)) checkIdentical(start(x), start(nclist)) checkIdentical(end(x), end(nclist)) checkIdentical(width(x), width(nclist)) checkIdentical(x, as(nclist, "IRanges")) checkIdentical(x[-6], as(nclist[-6], "IRanges")) } test_findOverlaps_NCList <- function() { query <- IRanges(-3:7, width=3) subject <- IRanges(rep.int(1:5, 5:1), c(1:5, 2:5, 3:5, 4:5, 5)) target0 <- .findOverlaps_naive(query, subject) current <- findOverlaps_NCList(query, NCList(subject)) checkTrue(.compare_hits(target0, current)) current <- findOverlaps_NCList(NCList(query), subject) checkTrue(.compare_hits(target0, current)) current <- findOverlaps_NCList(query, subject) checkTrue(.compare_hits(target0, current)) ## Shuffle query and/or subject elements. permute_input <- function(q_perm, s_perm) { q_revperm <- integer(length(q_perm)) q_revperm[q_perm] <- seq_along(q_perm) s_revperm <- integer(length(s_perm)) s_revperm[s_perm] <- seq_along(s_perm) target <- remapHits(target0, query.map=q_revperm, new.queryLength=length(q_perm), subject.map=s_revperm, new.subjectLength=length(s_perm)) current <- findOverlaps_NCList(query[q_perm], NCList(subject[s_perm])) checkTrue(.compare_hits(target, current)) current <- findOverlaps_NCList(NCList(query[q_perm]), subject[s_perm]) checkTrue(.compare_hits(target, current)) current <- findOverlaps_NCList(query[q_perm], subject[s_perm]) checkTrue(.compare_hits(target, current)) } q_perm <- rev(seq_along(query)) s_perm <- rev(seq_along(subject)) permute_input(q_perm, seq_along(subject)) # reverse query permute_input(seq_along(query), s_perm) # reverse subject permute_input(q_perm, s_perm) # reverse both set.seed(97) for (i in 1:33) { ## random permutations q_perm <- sample(length(query)) s_perm <- sample(length(subject)) permute_input(q_perm, seq_along(subject)) permute_input(seq_along(query), s_perm) permute_input(q_perm, s_perm) } } test_findOverlaps_NCList_with_filtering <- function() { query <- IRanges(-3:7, width=3) subject <- IRanges(rep.int(1:5, 5:1), c(1:5, 2:5, 3:5, 4:5, 5)) pp_query <- NCList(query) pp_subject <- NCList(subject) for (min.score in -3:4) { for (type in c("any", "start", "end", "within", "extend", "equal")) { for (select in c("all", "first", "last", "count")) { ## query - subject target <- .findOverlaps_naive(query, subject, min.score=min.score, type=type, select=select) current <- findOverlaps_NCList(query, pp_subject, min.score=min.score, type=type, select=select) checkTrue(.compare_hits(target, current)) current <- findOverlaps_NCList(pp_query, subject, min.score=min.score, type=type, select=select) checkTrue(.compare_hits(target, current)) current <- findOverlaps_NCList(query, subject, min.score=min.score, type=type, select=select) checkTrue(.compare_hits(target, current)) ## subject - query target <- .findOverlaps_naive(subject, query, min.score=min.score, type=type, select=select) current <- findOverlaps_NCList(pp_subject, query, min.score=min.score, type=type, select=select) checkTrue(.compare_hits(target, current)) current <- findOverlaps_NCList(subject, pp_query, min.score=min.score, type=type, select=select) checkTrue(.compare_hits(target, current)) current <- findOverlaps_NCList(subject, query, min.score=min.score, type=type, select=select) checkTrue(.compare_hits(target, current)) ## subject - subject target <- .findOverlaps_naive(subject, subject, min.score=min.score, type=type, select=select) current <- findOverlaps_NCList(pp_subject, subject, min.score=min.score, type=type, select=select) checkTrue(.compare_hits(target, current)) current <- findOverlaps_NCList(subject, pp_subject, min.score=min.score, type=type, select=select) checkTrue(.compare_hits(target, current)) current <- findOverlaps_NCList(subject, subject, min.score=min.score, type=type, select=select) checkTrue(.compare_hits(target, current)) } } } } .test_arbitrary_selection <- function(query, subject) { pp_query <- NCList(query) pp_subject <- NCList(subject) for (min.score in -3:4) { for (type in c("any", "start", "end", "within", "extend", "equal")) { target <- as(.findOverlaps_naive(query, subject, min.score=min.score, type=type, select="all"), "CompressedIntegerList") target_idx0 <- elementLengths(target) == 0L check_arbitrary_hits <- function(current) { current_idx0 <- is.na(current) checkIdentical(target_idx0, current_idx0) current <- as(current, "CompressedIntegerList") checkTrue(all(current_idx0 | as.logical(current %in% target))) } current <- findOverlaps_NCList(query, pp_subject, min.score=min.score, type=type, select="arbitrary") check_arbitrary_hits(current) current <- findOverlaps_NCList(pp_query, subject, min.score=min.score, type=type, select="arbitrary") check_arbitrary_hits(current) current <- findOverlaps_NCList(query, subject, min.score=min.score, type=type, select="arbitrary") check_arbitrary_hits(current) } } } test_findOverlaps_NCList_arbitrary <- function() { query <- IRanges(4:3, 6) subject <- IRanges(2:4, 10) .test_arbitrary_selection(query, subject) query <- IRanges(-3:7, width=3) subject <- IRanges(rep.int(1:5, 5:1), c(1:5, 2:5, 3:5, 4:5, 5)) .test_arbitrary_selection(query, subject) } .test_circularity <- function(query0, subject0, circle_length, target0, pp, findOverlaps_pp, type) { for (i in -2:2) { query <- shift(query0, shift=i*circle_length) pp_query <- pp(query, circle.length=circle_length) for (j in -2:2) { subject <- shift(subject0, shift=j*circle_length) pp_subject <- pp(subject, circle.length=circle_length) for (select in c("all", "first", "last", "count")) { target <- .select_hits(target0, select=select) current <- findOverlaps_pp(query, pp_subject, type=type, select=select, circle.length=circle_length) checkTrue(.compare_hits(target, current)) current <- findOverlaps_pp(pp_query, subject, type=type, select=select, circle.length=circle_length) checkTrue(.compare_hits(target, current)) current <- findOverlaps_pp(query, subject, type=type, select=select, circle.length=circle_length) checkTrue(.compare_hits(target, current)) target <- .select_hits(.transpose_hits(target0), select=select) current <- findOverlaps_pp(pp_subject, query, type=type, select=select, circle.length=circle_length) checkTrue(.compare_hits(target, current)) current <- findOverlaps_pp(subject, pp_query, type=type, select=select, circle.length=circle_length) checkTrue(.compare_hits(target, current)) current <- findOverlaps_pp(subject, query, type=type, select=select, circle.length=circle_length) checkTrue(.compare_hits(target, current)) } } } } test_findOverlaps_NCList_with_circular_space <- function() { query <- IRanges(-2:17, width=3) subject <- IRanges(c(4, -1, 599), c(7, 0, 999)) circle_length <- 10L ## type "any" s2q <- list(c(5:10, 15:20L), c(1:3, 10:13, 20L), 1:20) target <- .make_Hits_from_s2q(s2q, length(query)) .test_circularity(query, subject, circle_length, target, NCList, findOverlaps_NCList, "any") ## type "start" s2q <- lapply(start(subject), function(s) which((start(query) - s) %% circle_length == 0L)) target <- .make_Hits_from_s2q(s2q, length(query)) .test_circularity(query, subject, circle_length, target, NCList, findOverlaps_NCList, "start") ## type "end" s2q <- lapply(end(subject), function(e) which((end(query) - e) %% circle_length == 0L)) target <- .make_Hits_from_s2q(s2q, length(query)) .test_circularity(query, subject, circle_length, target, NCList, findOverlaps_NCList, "end") } test_NCLists <- function() { x1 <- IRanges(-3:7, width=3) x2 <- IRanges() x3 <- IRanges(rep.int(1:5, 5:1), c(1:5, 2:5, 3:5, 4:5, 5)) x <- IRangesList(x1=x1, x2=x2, x3=x3) mcols(x) <- DataFrame(label=c("first", "second", "third")) nclists <- NCLists(x) checkTrue(is(nclists, "NCLists")) checkTrue(validObject(nclists, complete=TRUE)) checkIdentical(x, ranges(nclists, use.mcols=TRUE)) checkIdentical(length(x), length(nclists)) checkIdentical(names(x), names(nclists)) checkIdentical(start(x), start(nclists)) checkIdentical(end(x), end(nclists)) checkIdentical(width(x), width(nclists)) checkIdentical(x, as(nclists, "IRangesList")) checkIdentical(x[-1], as(nclists[-1], "IRangesList")) checkIdentical(elementLengths(x), elementLengths(nclists)) nclist <- nclists[[3]] checkTrue(is(nclist, "NCList")) checkTrue(validObject(nclist, complete=TRUE)) checkIdentical(x3, as(nclist, "IRanges")) } test_findOverlaps_NCLists <- function() { ir1 <- IRanges(-3:7, width=3) ir2 <- IRanges(rep.int(1:5, 5:1), c(1:5, 2:5, 3:5, 4:5, 5)) target0 <- mapply(findOverlaps_NCList, list(ir1, ir2), list(ir2, ir1)) for (compress in c(TRUE, FALSE)) { query <- IRangesList(ir1, ir2, IRanges(2, 7), compress=compress) pp_query <- NCLists(query) subject <- IRangesList(ir2, ir1, compress=compress) pp_subject <- NCLists(subject) for (select in c("all", "first", "last", "count")) { target <- .select_hits(target0, select=select) current <- findOverlaps_NCLists(query, pp_subject, select=select) checkTrue(.compare_hits(target, current)) current <- findOverlaps_NCLists(pp_query, subject, select=select) checkTrue(.compare_hits(target, current)) current <- findOverlaps_NCLists(query, subject, select=select) checkTrue(.compare_hits(target, current)) } } } test_findOverlaps_NCLists_with_circular_space <- function() { query1 <- IRanges(-2:17, width=3) subject1 <- IRanges(c(4, -1, 599), c(7, 0, 999)) query <- IRangesList(query1, IRanges(), subject1) subject <- IRangesList(subject1, IRanges(), query1) circle_length <- c(10L, NA_integer_, 10L) s2q <- list(c(5:10, 15:20L), c(1:3, 10:13, 20L), 1:20) target1 <- .make_Hits_from_s2q(s2q, length(query1)) target2 <- .make_Hits_from_s2q(list(), 0) target3 <- .transpose_hits(target1) target <- list(target1, target2, target3) .test_circularity(query, subject, circle_length, target, NCLists, findOverlaps_NCLists, "any") } IRanges/inst/unitTests/test_RDApplyParams.R0000644000175100017510000001777612607265143021772 0ustar00biocbuildbiocbuildtest_RDApplyParams_construct <- function() { fun <- function(rd) NULL ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) applyParams <- list(x = 2) excludePattern <- "[XY]" rd <- RangedData(ranges, filter) ## meaningless defaults checkTrue(validObject(RDApplyParams())) checkTrue(validObject(RDApplyParams(rd))) ## finally does something params <- RDApplyParams(rd, fun) checkTrue(validObject(params)) checkIdentical(rangedData(params), rd) checkIdentical(applyFun(params), fun) ## make sure function and parameters compatible ## applyFun needs 1 param checkException(applyFun(params) <- function() NULL, silent = TRUE) checkException(RDApplyParams(rd, function() NULL), silent = TRUE) ## needs 2 params checkException(RDApplyParams(rd, fun, applyParams), silent = TRUE) checkException(applyParams(params) <- applyParams, silent = TRUE) ## parameter name mismatch checkException(RDApplyParams(rd, function(rd, y) NULL, applyParams), silent = TRUE) applyFun(params) <- function(rd, y) NULL checkTrue(validObject(params)) checkException(applyParams(params) <- applyParams, silent = TRUE) ## ok with ... applyFun(params) <- function(...) NULL checkTrue(validObject(params)) checkIdentical(applyFun(params), function(...) NULL) applyParams(params) <- applyParams checkTrue(validObject(params)) checkIdentical(applyParams(params), applyParams) params <- RDApplyParams(rd, function(...) NULL, applyParams) checkTrue(validObject(params)) checkIdentical(applyParams(params), applyParams) ## check for duplicate params checkException(applyParams(params) <- rep(applyParams,2), silent = TRUE) checkException(RDApplyParams(rd, function(...) NULL, rep(applyParams,2)), silent = TRUE) ## exclude pattern -- length 1 character vector ## excludePattern(params) <- excludePattern ## checkTrue(validObject(params)) ## checkIdentical(excludePattern(params), excludePattern) ## params <- RDApplyParams(rd, function(...) NULL, ## excludePattern = excludePattern) ## checkTrue(validObject(params)) ## checkIdentical(excludePattern(params), excludePattern) ## checkException(RDApplyParams(rd, function(...) NULL, ## excludePattern = rep(excludePattern,2))) ## checkExcpetion(excludePattern(params)) <- rep(excludePattern, 2) ## filters filterRules <- FilterRules() filterRules(params) <- filterRules checkIdentical(filterRules(params), filterRules) params <- RDApplyParams(rd, function(...) NULL, filterRules = filterRules) checkTrue(validObject(params)) checkIdentical(filterRules(params), filterRules) filterRules <- FilterRules(list(basic = "filter", advanced = function(rd) NULL)) filterRules(params) <- filterRules checkTrue(validObject(params)) ## simplify -- length 1 logical simplify(params) <- TRUE checkTrue(validObject(params)) checkIdentical(simplify(params), TRUE) params <- RDApplyParams(rd, function(...) NULL, simplify = TRUE) checkTrue(validObject(params)) checkIdentical(simplify(params), TRUE) checkException(RDApplyParams(rd, function(...) NULL, simplify = rep(TRUE,2)), silent = TRUE) checkException(simplify(params) <- rep(FALSE, 2), silent = TRUE) ## reducer reducer <- function(rd) NULL ## oops, simplify is TRUE checkException(reducerFun(params) <- reducer, silent = TRUE) checkException(RDApplyParams(rd, function(...) NULL, simplify = TRUE, reducerFun = reducer), silent = TRUE) simplify(params) <- FALSE reducerFun(params) <- reducer checkTrue(validObject(params)) checkIdentical(reducerFun(params), reducer) params <- RDApplyParams(rd, function(...) NULL, reducerFun = reducer) checkTrue(validObject(params)) checkIdentical(reducerFun(params), reducer) reducerFun(params) <- NULL ## don't reduce checkTrue(validObject(params)) checkIdentical(reducerFun(params), NULL) ## reducer params ## NOTE: for some reason, new() becomes confused if we use 'applyParams' here reducerParams <- applyParams checkException(RDApplyParams(rd, function(...) NULL, ## oops, no reducer reducerParams = reducerParams), silent = TRUE) checkException(reducerParams(params) <- reducerParams, silent = TRUE) ## conflicts between reducer and its params ## needs 1 param checkException(reducerFun(params) <- function() NULL, silent = TRUE) checkException(RDApplyParams(rd, reducerFun = function() NULL), silent = TRUE) checkException(RDApplyParams(rd, fun, reducerFun = reducer, reducerParams = reducerParams), silent = TRUE) # needs 2 params reducerFun(params) <- function(rd) NULL checkException(reducerParams(params) <- reducerParams, silent = TRUE) ## parameter name mismatch checkException(RDApplyParams(rd, function(rd) NULL, reducerFun = function(rd, y) NULL, reducerParams = reducerParams), silent = TRUE) reducerFun(params) <- function(rd, y) NULL checkTrue(validObject(params)) checkException(reducerParams(params) <- reducerParams, silent = TRUE) ## ok with ... reducerFun(params) <- function(...) NULL checkTrue(validObject(params)) checkIdentical(reducerFun(params), function(...) NULL) reducerParams(params) <- reducerParams checkTrue(validObject(params)) checkIdentical(reducerParams(params), reducerParams) params <- RDApplyParams(rd, function(rd) NULL, reducerFun = function(...) NULL, reducerParams = reducerParams) checkTrue(validObject(params)) checkIdentical(reducerParams(params), reducerParams) checkException(reducerParams(params) <- rep(reducerParams,2), silent = TRUE) checkException(reducerParams(params) <- rep(reducerParams,2), silent = TRUE) checkException(RDApplyParams(rd, function(...) NULL, reducerFun = reducer, reducerParams = rep(reducerParams,2)), silent = TRUE) ## iteratorFun params <- RDApplyParams(rd, iteratorFun = lapply) checkTrue(validObject(params)) checkIdentical(iteratorFun(params), lapply) iteratorFun(params) <- sapply checkTrue(validObject(params)) checkIdentical(iteratorFun(params), sapply) checkException(iteratorFun(params) <- function(x) NULL, silent=TRUE) checkException(iteratorFun(params) <- function(x, simplify) NULL, silent=TRUE) } test_RDApplyParams_rdapply <- function() { ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(2L, 0L, 1L) rd <- RangedData(ranges, filter, space = c("chr1","chr2","chr1")) fun <- function(rd) NULL countrows <- function(rd) nrow(rd) applyParams <- list(x = 2) excludePattern <- "[XY]" ## a single function params <- RDApplyParams(rd, fun) checkIdentical(rdapply(params), list(chr1 = NULL, chr2 = NULL)) ## with a parameter params <- RDApplyParams(rd, function(rd, x) x, list(x = 2)) checkIdentical(rdapply(params), list(chr1 = 2, chr2 = 2)) ## add a filter cutoff <- 0 cutoffFun <- function(rd) rd[["filter"]] > cutoff rules <- FilterRules(list(filter = cutoffFun)) params <- RDApplyParams(rd, countrows, filterRules = rules) checkIdentical(rdapply(params), list(chr1 = 2L, chr2 = 0L)) rules <- FilterRules(list(fun = function(rd) rd[["filter"]] < 2, filter = cutoffFun)) params <- RDApplyParams(rd, countrows, filterRules = rules) checkIdentical(rdapply(params), list(chr1 = 1L, chr2 = 0L)) active(filterRules(params))["filter"] <- FALSE checkIdentical(rdapply(params), list(chr1 = 1L, chr2 = 1L)) ## simplify params <- RDApplyParams(rd, countrows, simplify = TRUE) checkIdentical(rdapply(params), c(chr1 = 2L, chr2 = 1L)) ## reducing params <- RDApplyParams(rd, fun, reducerFun = unlist) checkIdentical(rdapply(params), NULL) params <- RDApplyParams(rd, countrows, reducerFun = unlist, reducerParams = list(use.names = FALSE)) checkIdentical(rdapply(params), c(2L, 1L)) } IRanges/inst/unitTests/test_RangedData.R0000644000175100017510000002644012607265143021271 0ustar00biocbuildbiocbuildtest_RangedData_construction <- function() { ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) checkException(RangedData(c(1,2,3)), silent = TRUE) checkException(RangedData(ranges, c(1,2,3,4,5)), silent = TRUE) rd <- RangedData() checkTrue(validObject(rd)) rd <- RangedData(IRanges()) checkTrue(validObject(rd)) rd <- RangedData(IRangesList()) checkTrue(validObject(rd)) rd <- RangedData(IRangesList(IRanges())) checkTrue(validObject(rd)) rd <- RangedData(IRangesList(IRanges(), IRanges())) checkTrue(validObject(rd)) rd <- RangedData(IRangesList(IRanges(), IRanges(1,1))) checkTrue(validObject(rd)) rd <- RangedData(ranges) checkTrue(validObject(rd)) checkIdentical(unname(ranges(rd)), IRangesList(ranges)) rd <- RangedData(ranges, score) checkTrue(validObject(rd)) checkIdentical(rd[["score"]], score) rd <- RangedData(ranges, score = score) checkTrue(validObject(rd)) checkIdentical(rd[["score"]], score) rd <- RangedData(ranges, filter, score = score) checkTrue(validObject(rd)) checkIdentical(rd[["score"]], score) checkIdentical(rd[["filter"]], filter) rd <- RangedData(ranges, filter = filter, vals = score) checkTrue(validObject(rd)) checkIdentical(rd[["vals"]], score) checkIdentical(rd[["filter"]], filter) rd <- RangedData(ranges, score + score) checkTrue(validObject(rd)) checkIdentical(rd[["score...score"]], score + score) rd <- RangedData(ranges, universe = "hg18") checkTrue(validObject(rd)) checkIdentical(universe(rd), "hg18") range2 <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) both <- c(ranges, range2) score <- c(score, c(0L, 3L, NA, 22L)) chrom <- paste("chr", rep(c(1,2), c(length(ranges), length(range2))), sep="") rd <- RangedData(both, score, space = chrom, universe = "hg18") checkTrue(validObject(rd)) checkIdentical(rd[["score"]], score) checkIdentical(rd[1][["score"]], score[1:3]) checkException(RangedData(ranges, universe = c("hg18", "mm9")), silent = TRUE) checkException(RangedData(ranges, universe = 1), silent = TRUE) checkException(RangedData(both, space = chrom[1:3]), silent = TRUE) } test_RangedData_extraction <- function() { ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) rd <- RangedData(ranges, filter, score = score, space = c(1, 1, 2)) checkException(rd[[]], silent = TRUE) checkException(rd[[1, 2]], silent = TRUE) checkException(rd[[numeric()]], silent = TRUE) checkException(rd[[NULL]], silent = TRUE) checkException(rd[[c(1,2)]], silent = TRUE) checkException(rd[[-1]], silent = TRUE) checkException(rd[[5]], silent = TRUE) checkIdentical(rd[["vals"]], NULL) checkIdentical(rd$vals, NULL) checkIdentical(rd[[NA_integer_]], NULL) checkIdentical(rd[[1]], filter) checkIdentical(rd[[2]], score) checkIdentical(rd[["filter"]], filter) checkIdentical(rd[["score"]], score) checkIdentical(rd$score, score) checkIdentical(rd[1][[1]], filter[1:2]) } test_RangedData_values_replace <- function() { ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) rd1 <- RangedData(ranges, filter, space = c(1, 2, 1)) values(rd1) <- split(DataFrame(filter=score), c(1, 2, 1)) rd2 <- RangedData(ranges, filter=score, space = c(1, 2, 1)) checkIdentical(rd1, rd2) rd1 <- RangedData(ranges, filter, space = c(1, 2, 1)) values(rd1) <- DataFrame(filter=score[c(1,3,2)]) rd2 <- RangedData(ranges, filter=score, space = c(1, 2, 1)) checkIdentical(rd1, rd2) } test_RangedData_ranges_replace <- function() { ranges1 <- IRanges(c(1,2,3),c(4,5,6)) ranges2 <- IRanges(c(3,2,1),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) rd1 <- RangedData(ranges1, filter, space = c(1, 2, 1)) ranges(rd1) <- split(ranges2, c(1, 2, 1)) rd2 <- RangedData(ranges2, filter, space = c(1, 2, 1)) checkIdentical(rd1, rd2) rd1 <- RangedData(ranges1, filter, space = c(1, 2, 1)) ranges(rd1) <- ranges2[c(1,3,2)] rd2 <- RangedData(ranges2, filter, space = c(1, 2, 1)) checkIdentical(rd1, rd2) } test_RangedData_data_column_replace <- function() { ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) rd <- RangedData(ranges, filter, space = c(1, 2, 1)) filter <- filter[c(1, 3, 2)] score <- score[c(1, 3, 2)] checkException(rd[[]] <- score, silent = TRUE) checkException(rd[[1, 2]] <- score, silent = TRUE) checkException(rd[[numeric()]] <- score, silent = TRUE) checkException(rd[[NULL]] <- score, silent = TRUE) checkException(rd[[c(1,2)]] <- score, silent = TRUE) checkException(rd[[-1]] <- score, silent = TRUE) checkException(rd[[5]] <- score, silent = TRUE) checkException(rd[["score"]] <- numeric(), silent = TRUE) checkException(rd[["score"]] <- score[1:2], silent = TRUE) rd[["score"]] <- score checkTrue(validObject(rd)) checkIdentical(rd[["score"]], score) filter2 <- c(1L, 1L, 0L) rd[["filter"]] <- filter2 checkTrue(validObject(rd)) checkIdentical(rd[["filter"]], filter2) ##rd[["score"]] <- score[1] # no recycling yet ##checkTrue(validObject(rd)) ##checkIdentical(rd[["score"]], rep(score[1], 3)) rd[[2]] <- score checkTrue(validObject(rd)) checkIdentical(rd[[2]], score) rd[[2]] <- NULL checkTrue(validObject(rd)) checkIdentical(ncol(rd), 1L) rd$score2 <- score checkIdentical(rd$score2, score) } test_RangedData_subset <- function() { ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) rd <- RangedData(ranges, filter, score = score, space = c(1, 2, 1)) filter <- filter[c(1, 3, 2)] score <- score[c(1, 3, 2)] checkException(rd[list()], silent = TRUE) checkException(rd[10], silent = TRUE) checkException(rd[c(NA, 2)], silent = TRUE) checkException(rd["one"], silent = TRUE) checkException(rd[c(TRUE, TRUE, TRUE, TRUE)], silent = TRUE) checkException(rd[c(-1,2)], silent = TRUE) erd <- new("RangedData") names(erd) <- character(0) frd <- RangedData(ranges[c(1,3)], filter = filter[1:2], score = score[1:2], space = 1) checkIdenticalRD <- function(a, b) { checkIdentical(as(ranges(a), "CompressedIRangesList"), as(ranges(b), "CompressedIRangesList")) checkIdentical(length(values(a)), length(values(b))) if (length(values(a)) > 0) checkIdentical(as.data.frame(values(a)), as.data.frame(values(b))) else TRUE } checkIdenticalRD(rd[numeric()], erd) checkIdenticalRD(rd[logical()], erd) checkIdenticalRD(rd[NULL], erd) checkIdenticalRD(rd[], rd) checkIdenticalRD(rd[FALSE], erd) checkIdenticalRD(rd[c(FALSE, FALSE)], erd) checkIdenticalRD(rd[TRUE], rd) checkIdenticalRD(rd[c(TRUE, FALSE)], frd) checkIdenticalRD(rd[1], frd) checkIdenticalRD(rd[c(1,2)], rd) checkIdenticalRD(rd[-2], frd) ## now test matrix-style checkException(rd[,100], silent = TRUE) # out of bounds col checkException(rd[1000,], silent = TRUE) # out of bounds row checkException(rd[foo = "bar"], silent = TRUE) # invalid argument checkException(rd["Sion",], silent = TRUE) # no subsetting by row name yet checkException(rd[,"Fert"], silent = TRUE) # bad column name checkIdenticalRD(rd[,], rd) # identity ## empty nocols <- RangedData(ranges, new("DataFrame", nrows=3L), space=c(1,2,1)) checkIdenticalRD(rd[,NULL], nocols) checkIdenticalRD(rd[NULL,], rd[FALSE,]) ## column subsetting onecol <- RangedData(ranges, filter=filter[c(1,3,2)], space=c(1,2,1)) checkIdenticalRD(rd[,1], onecol) checkIdenticalRD(rd[,1:2], rd) checkIdenticalRD(rd[,"filter"], rd[,1]) # by name firstrow <- RangedData(ranges[1], filter = filter[1], score = score[1], space = 1) checkIdenticalRD(rd[1,,drop=TRUE], firstrow) # row subsetting splitrow <- RangedData(ranges[1:2], filter = filter[c(1,3)], score = score[c(1,3)], space = c(1,2)) checkIdenticalRD(rd[c(1,3),], splitrow) # row subsetting checkIdenticalRD(rd[1:2, 1], onecol[1:2,]) # combined ## repeats repeated <- RangedData(ranges[c(1,3,1,2)], filter=filter[c(1:2,1,3)], space = c(1,1,1,2)) checkIdenticalRD(rd[c(1:2,1,3),1], repeated) } test_RangedData_combine <- function() { ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) rd <- RangedData(ranges, score, space = filter) ## c() checkTrue(validObject(c(rd[1], rd[2]))) checkIdentical(ranges(c(rd[1], rd[2])), ranges(rd)) checkIdentical(as.data.frame(values(c(rd[1], rd[2]))), as.data.frame(values(rd))) checkException(c(rd[1], ranges), silent = TRUE) ## split() rd2 <- RangedData(ranges, score) checkIdentical(as.data.frame(unlist(split(rd2, filter))), as.data.frame(rd2[order(filter),])) checkException(split(rd2, filter[1:2]), silent = TRUE) ## rbind() ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) rd1 <- RangedData(ranges, score, space = filter) score2 <- c(15L, 10L, 3L) space2 <- c(0L, 1L, 0L) ranges2 <- IRanges(c(2,5,1), c(8, 6, 9)) rd2 <- RangedData(ranges2, score = score2, space = space2) rd <- RangedData(c(ranges, ranges2), score=c(score,score2), space=c(filter, space2)) checkIdentical(as.data.frame(rbind(rd1, rd2)), as.data.frame(rd)) rownames(rd1) <- letters[seq_len(nrow(rd1))] rownames(rd2) <- letters[seq_len(nrow(rd2))] checkTrue(validObject(rbind(rd1, rd2))) universe(rd2) <- "foo" checkException(rbind(rd1, rd2), silent=TRUE) } test_RangedData_lapply <- function() { ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) rd <- RangedData(ranges, score, space = filter) checkIdentical(lapply(rd, `[[`, 1), list(`0` = 2L, `1` = c(10L, NA))) } test_RangedData_range <- function() { rd1 <- RangedData(IRanges(c(2,5,1), c(3,7,3))) rd2 <- RangedData(IRanges(c(5,2,0), c(6,3,1))) checkIdentical(range(rd1), IRangesList("1" = IRanges(1, 7))) checkIdentical(range(rd1, rd2), IRangesList("1" = IRanges(0, 7))) checkException(range(rd1, c(2,3)), silent = TRUE) } test_RangedData_dimnames <- function() { ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) rd <- RangedData(ranges, filter, score = score, space = c(1, 2, 1)) colnames(rd)[2] <- "foo" checkTrue(validObject(rd)) checkIdentical(colnames(rd), c("filter", "foo")) rownames(rd) <- c("a", "b", "c") checkTrue(validObject(rd)) checkIdentical(rownames(rd), c("a", "b", "c")) } test_RangedData_fromDataFrame <- function() { df <- data.frame(start = c(1, 2, 3), end = c(4, 2, 3)) rd <- RangedData(IRanges(c(1,2,3), c(4,2,3)), df[,NULL]) checkIdentical(as(df, "RangedData"), rd) checkException(as(df[,1,drop=FALSE], "RangedData"), rd, silent=TRUE) df <- data.frame(start = c(1, 2, 3), end = c(4, 2, 3), space = c(1, 1, 2), foo = c("a", "b", "c")) rd <- RangedData(IRanges(c(1,2,3), c(4,2,3)), df[,"foo",drop=FALSE], space = c(1,1,2)) checkIdentical(as(df, "RangedData"), rd) } test_RangedData_legacy_data.frame <- function() { ranges <- IRanges(c(1,2,3),c(4,5,6)) rd <- RangedData(ranges) current <- as.data.frame(rd) expected <- data.frame(space = factor(rep(1, 3)), start = 1:3, end = 4:6, width = rep(4L, 3)) checkIdentical(current, expected) } IRanges/inst/unitTests/test_Ranges-comparison.R0000644000175100017510000000364612607265143022671 0ustar00biocbuildbiocbuildtest_Ranges_compare <- function() { x1 <- IRanges(6:16, width=4) y <- IRanges(11, 14) target <- c(-6:-4, -4L, -4L, 0L, 4L, 4L, 4:6) checkIdentical(target, compare(x1, y)) checkIdentical(-target, compare(y, x1)) x2 <- IRanges(4:16, width=6) target <- c(-6:-4, -4L, -4L, -3L, -2L, 1L, 4L, 4L, 4:6) checkIdentical(target, compare(x2, y)) checkIdentical(-target, compare(y, x2)) x3 <- IRanges(8:16, width=2) target <- c(-6:-4, -1L, 2L, 3L, 4:6) checkIdentical(target, compare(x3, y)) checkIdentical(-target, compare(y, x3)) ## Moving a 0-width range over a non 0-width range. ## Note that when the end of the 0-width range is equal to the start of ## the non 0-width range minus 1, returning code -5 (which describes ## a situation of adjacent ranges) seems appropriate. ## However, one could argue that returning code -1 (which describes a ## situation where one range is inside the other) would also be ## appropriate, because, in that case, the two ranges have the same start. ## So the question really is whether the 0-width range should be considered ## *outside* or *inside* the non 0-width range. ## It's an arbitrary choice and we chose the former. x0 <- IRanges(10:16, width=0) target <- c(-6:-5, 2L, 2L, 2L, 5:6) checkIdentical(target, compare(x0, y)) checkIdentical(-target, compare(y, x0)) ## Moving a 0-width range over a 0-width range. y0 <- IRanges(13, 12) target <- c(-6L, -6L, -6L, 0L, 6L, 6L, 6L) checkIdentical(target, compare(x0, y0)) checkIdentical(-target, compare(y0, x0)) } test_Ranges_order <- function() { ir1 <- IRanges(c(2,5,1,5), c(3,7,3,6)) ir1.sort <- IRanges(c(1,2,5,5), c(3,3,6,7)) ir1.rev <- IRanges(c(5,5,2,1), c(7,6,3,3)) checkIdentical(sort(ir1), ir1.sort) checkIdentical(sort(ir1, decreasing=TRUE), ir1.rev) checkException(sort(ir1, decreasing=NA), silent = TRUE) } IRanges/inst/unitTests/test_RangesList-class.R0000644000175100017510000001104312607265143022446 0ustar00biocbuildbiocbuildtest_RangesList_construction <- function() { empty <- RangesList() checkTrue(validObject(empty)) checkIdentical(length(empty), 0L) range1 <- IRanges(start=c(1,2,3), end=c(5,2,8)) range2 <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) named <- RangesList(one = range1, two = range2) checkTrue(validObject(named)) checkIdentical(length(named), 2L) checkIdentical(start(named), IntegerList(one = start(range1), two = start(range2), compress=FALSE)) checkIdentical(end(named), IntegerList(one = end(range1), two = end(range2), compress=FALSE)) checkIdentical(width(named), IntegerList(one = width(range1), two = width(range2), compress=FALSE)) checkIdentical(names(named), c("one", "two")) checkIdentical(range1, named[[1]]) unnamed <- RangesList(range1, range2) checkTrue(validObject(unnamed)) checkIdentical(length(unnamed), 2L) checkIdentical(range2, unnamed[[2]]) checkIdentical(names(unnamed), NULL) } test_RangesList_subset <- function() { ## by RangesList range1 <- IRanges(start=c(1,2,3), end=c(5,2,8)) range2 <- IRanges(start=c(1,15,20,45), end=c(5,15,100,80)) collection <- RangesList(one = range1, range2) checkIdentical(subsetByOverlaps(collection, RangesList()), RangesList(one=IRanges(), IRanges())) checkIdentical(subsetByOverlaps(collection, RangesList(IRanges(4, 6), IRanges(50, 70))), RangesList(one=IRanges(c(1,3),c(5,8)), IRanges(c(20,45),c(100,80)))) checkIdentical(subsetByOverlaps(collection, RangesList(IRanges(50, 70), one=IRanges(4, 6))), RangesList(one=IRanges(c(1,3),c(5,8)), IRanges())) } test_RangesList_as_list <- function() { range1 <- IRanges(start=c(1,2,3), end=c(5,2,8)) range2 <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) checkIdentical(list(range1, range2), as.list(RangesList(range1, range2))) checkIdentical(list(a=range1, b=range2), as.list(RangesList(a=range1, b=range2))) } test_RangesList_as_data_frame <- function() { range1 <- IRanges(start=c(1,2,3), end=c(5,2,8)) range2 <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) rl <- RangesList(range1, range2) df <- data.frame(group=togroup(rl), group_name=NA_character_, as.data.frame(c(range1,range2)), stringsAsFactors=FALSE) checkIdentical(df, as.data.frame(rl)) names(rl) <- c("a", "b") df$group_name <- c("a", "b")[togroup(rl)] checkIdentical(df, as.data.frame(rl)) } test_IRangesList_construction <- function() { range1 <- IRanges(start=c(1,2,3), end=c(5,2,8)) range2 <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) for (compress in c(TRUE, FALSE)) { named <- IRangesList(one = range1, two = range2, compress = compress) checkIdentical(length(named), 2L) checkIdentical(names(named), c("one", "two")) checkIdentical(range1, named[[1]]) unnamed <- IRangesList(range1, range2) checkTrue(validObject(unnamed)) checkIdentical(length(unnamed), 2L) checkIdentical(range2, unnamed[[2]]) checkIdentical(names(unnamed), NULL) } } test_IRangesList_annotation <- function() { range1 <- IRanges(start=c(1,2,3), end=c(5,2,8)) range2 <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) for (compress in c(TRUE, FALSE)) { rl <- IRangesList(range1, range2, compress = compress) mcols(rl) <- DataFrame(a = 1:2) checkIdentical(mcols(rl)[,1], 1:2) checkIdentical(mcols(rl[2:1])[,1], 2:1) checkIdentical(mcols(c(rl,rl))[,1], rep(1:2,2)) checkIdentical(mcols(append(rl,rl))[,1], rep(1:2,2)) } } ## test_RangesList_overlap <- function() { ## rl1 <- RangesList(a = IRanges(c(1,2),c(4,3)), b = IRanges(c(4,6),c(10,7))) ## rl2 <- RangesList(b = IRanges(c(0,2),c(4,5)), a = IRanges(c(4,5),c(6,7))) ## overlap(rl1, rl2) ## overlap(rl1, rl2, select = "first") ## overlap(rl1, rl2, select = "first", drop = TRUE) ## names(rl2)[1] <- "c" ## overlap(rl1, rl2) ## overlap(rl1, rl2, select = "first") ## overlap(rl1, rl2, select = "first", drop = TRUE) ## names(rl2) <- NULL ## overlap(rl1, rl2) ## overlap(rl1, rl2, select = "first") ## overlap(rl1, rl2, select = "first", drop = TRUE) ## overlap(rl1, rl2[1]) ## overlap(rl1, rl2[1], select = "first") ## overlap(rl1, rl2[1], select = "first", drop = TRUE) ## overlap(rl1[1], rl2) ## overlap(rl1[1], rl2, select = "first") ## overlap(rl1[1], rl2, select = "first", drop = TRUE) ## } IRanges/inst/unitTests/test_RleViews.R0000644000175100017510000001615612607265143021042 0ustar00biocbuildbiocbuildtest_RleViews <- function() { empty <- Views(Rle(), IRanges()) checkIdentical(empty, new("RleViews")) checkIdentical(list(), viewApply(empty, min)) checkIdentical(integer(0), viewMins(empty)) checkIdentical(integer(0), viewMaxs(empty)) checkIdentical(integer(0), viewSums(empty)) checkIdentical(numeric(0), viewMeans(empty)) checkIdentical(integer(0), viewWhichMins(empty)) checkIdentical(integer(0), viewWhichMaxs(empty)) checkIdentical(IRanges(), viewRangeMins(empty)) checkIdentical(IRanges(), viewRangeMaxs(empty)) x <- rep(c(1L, 3L, NA, 7L, 9L), 1:5) xRle <- Rle(x) xRleViewsUntrimmed <- Views(xRle, IRanges(start = c(1,1), width = c(0,20))) checkIdentical(c(Inf, 1), suppressWarnings(viewApply(xRleViewsUntrimmed, min, na.rm = TRUE))) checkIdentical(c(2147483647L, 1L), viewMins(xRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(viewMins(xRleViewsUntrimmed, na.rm = TRUE), min(xRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(c(-2147483647L, 9L), viewMaxs(xRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(viewMaxs(xRleViewsUntrimmed, na.rm = TRUE), max(xRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(c(0L, 80L), viewSums(xRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(viewSums(xRleViewsUntrimmed, na.rm = TRUE), sum(xRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(c(NaN, 20/3), viewMeans(xRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(viewMeans(xRleViewsUntrimmed, na.rm = TRUE), mean(xRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(c(NA_integer_, 1L), viewWhichMins(xRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(viewWhichMins(xRleViewsUntrimmed, na.rm = TRUE), which.min(xRleViewsUntrimmed)) checkIdentical(c(NA_integer_, 11L), viewWhichMaxs(xRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(viewWhichMaxs(xRleViewsUntrimmed, na.rm = TRUE), which.max(xRleViewsUntrimmed)) checkException(max(xRleViewsUntrimmed, xRleViewsUntrimmed, na.rm = TRUE), silent = TRUE) xRleViews <- Views(xRle, start = c(1, 3, 5, 7, 9), end = c(1, 13, 11, 10, 9), names = letters[1:5]) xList <- lapply(structure(seq_len(length(xRleViews)), names = letters[1:5]), function(i) window(x, start = start(xRleViews)[i], end = end(xRleViews)[i])) checkIdentical(letters[1:5], names(viewApply(xRleViews, min))) checkIdentical(letters[1:5], names(viewMins(xRleViews))) checkIdentical(letters[1:5], names(viewMaxs(xRleViews))) checkIdentical(letters[1:5], names(viewSums(xRleViews))) checkIdentical(letters[1:5], names(viewMeans(xRleViews))) checkIdentical(letters[1:5], names(viewWhichMins(xRleViews))) checkIdentical(letters[1:5], names(viewWhichMaxs(xRleViews))) checkIdentical(letters[1:5], names(viewRangeMins(xRleViews, na.rm = TRUE))) checkIdentical(letters[1:5], names(viewRangeMaxs(xRleViews, na.rm = TRUE))) checkEqualsNumeric(sapply(xList, min), viewMins(xRleViews)) checkEqualsNumeric(sapply(xList, min), viewApply(xRleViews, min)) checkEqualsNumeric(sapply(xList, min, na.rm = TRUE), viewMins(xRleViews, na.rm = TRUE)) checkEqualsNumeric(sapply(xList, min, na.rm = TRUE), viewApply(xRleViews, min, na.rm = TRUE)) checkEqualsNumeric(sapply(xList, max), viewMaxs(xRleViews)) checkEqualsNumeric(sapply(xList, max), viewApply(xRleViews, max)) checkEqualsNumeric(sapply(xList, max, na.rm = TRUE), viewMaxs(xRleViews, na.rm = TRUE)) checkEqualsNumeric(sapply(xList, max, na.rm = TRUE), viewApply(xRleViews, max, na.rm = TRUE)) checkEqualsNumeric(sapply(xList, sum), viewSums(xRleViews)) checkEqualsNumeric(sapply(xList, mean), viewMeans(xRleViews)) checkEqualsNumeric(sapply(xList, sum), viewApply(xRleViews, sum)) checkEqualsNumeric(sapply(xList, sum, na.rm = TRUE), viewSums(xRleViews, na.rm = TRUE)) checkEqualsNumeric(sapply(xList, mean, na.rm = TRUE), viewMeans(xRleViews, na.rm = TRUE)) checkEqualsNumeric(sapply(xList, sum, na.rm = TRUE), viewApply(xRleViews, sum, na.rm = TRUE)) y <- rep(c(1.2, 3.4, NA, 7.8, 9.0), 1:5) yRle <- Rle(y) yRleViewsUntrimmed <- Views(yRle, IRanges(start = c(1,1), width = c(0,20))) checkIdentical(c(Inf, 1.2), suppressWarnings(viewApply(yRleViewsUntrimmed, min, na.rm = TRUE))) checkIdentical(c(Inf, 1.2), viewMins(yRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(c(-Inf, 9), viewMaxs(yRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(c(0, 84.2), viewSums(yRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(c(NaN, 84.2/12), viewMeans(yRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(c(NA_integer_, 1L), viewWhichMins(yRleViewsUntrimmed, na.rm = TRUE)) checkIdentical(c(NA_integer_, 11L), viewWhichMaxs(yRleViewsUntrimmed, na.rm = TRUE)) yRleViews <- Views(yRle, start = c(1, 3, 5, 7, 9), end = c(1, 13, 11, 10, 9)) yList <- lapply(seq_len(length(yRleViews)), function(i) window(y, start = start(yRleViews)[i], end = end(yRleViews)[i])) checkEqualsNumeric(sapply(yList, min), viewMins(yRleViews)) checkEqualsNumeric(sapply(yList, min), viewApply(yRleViews, min)) checkEqualsNumeric(sapply(yList, min, na.rm = TRUE), viewMins(yRleViews, na.rm = TRUE)) checkEqualsNumeric(sapply(yList, min, na.rm = TRUE), viewApply(yRleViews, min, na.rm = TRUE)) checkEqualsNumeric(sapply(yList, max), viewMaxs(yRleViews)) checkEqualsNumeric(sapply(yList, max), viewApply(yRleViews, max)) checkEqualsNumeric(sapply(yList, max, na.rm = TRUE), viewMaxs(yRleViews, na.rm = TRUE)) checkEqualsNumeric(sapply(yList, max, na.rm = TRUE), viewApply(yRleViews, max, na.rm = TRUE)) checkEqualsNumeric(sapply(yList, sum), viewSums(yRleViews)) checkEqualsNumeric(sapply(yList, mean), viewMeans(yRleViews)) checkEqualsNumeric(sapply(yList, sum), viewApply(yRleViews, sum)) checkEqualsNumeric(sapply(yList, sum, na.rm = TRUE), viewSums(yRleViews, na.rm = TRUE)) checkEqualsNumeric(sapply(yList, mean, na.rm = TRUE), viewMeans(yRleViews, na.rm = TRUE)) checkEqualsNumeric(sapply(yList, sum, na.rm = TRUE), viewApply(yRleViews, sum, na.rm = TRUE)) z <- rep(c(1+1i, 3.4-1i, NA, 7.8+3i, 9.0-2i), 1:5) zRle <- Rle(z) zRleViews <- Views(zRle, start = c(1, 3, 5, 7, 9), end = c(1, 13, 11, 10, 9)) zList <- lapply(seq_len(length(zRleViews)), function(i) window(z, start = start(zRleViews)[i], end = end(zRleViews)[i])) checkEqualsNumeric(sapply(zList, sum), viewSums(zRleViews)) checkEqualsNumeric(sapply(zList, mean), viewMeans(zRleViews)) checkEqualsNumeric(sapply(zList, sum), viewApply(zRleViews, sum)) checkEqualsNumeric(sapply(zList, sum, na.rm = TRUE), viewSums(zRleViews, na.rm = TRUE)) checkEqualsNumeric(sapply(zList, mean, na.rm = TRUE), viewMeans(zRleViews, na.rm = TRUE)) checkEqualsNumeric(sapply(zList, sum, na.rm = TRUE), viewApply(zRleViews, sum, na.rm = TRUE)) } IRanges/inst/unitTests/test_RleViewsList.R0000644000175100017510000001302712607265143021670 0ustar00biocbuildbiocbuildtest_RleViewsList <- function() { x1 <- rep(c(1L, 3L, NA, 7L, 9L), 1:5) x1Rle <- Rle(x1) x1Ranges <- IRanges(start = c(1, 3, 5, 7, 9), end = c(1, 13, 11, 10, 9)) x2 <- rev(x1) x2Rle <- Rle(x2) x2Ranges <- IRanges(start = c(2, 4, 6, 8, 10), end = c(3, 9, 11, 13, 15)) checkIdentical(RleViewsList(Views(x1Rle, x1Ranges), Views(x2Rle, x2Ranges)), RleViewsList(rleList = RleList(x1Rle, x2Rle), rangesList = IRangesList(x1Ranges, x2Ranges))) xRleViewsList <- RleViewsList(a = Views(x1Rle, x1Ranges), b = Views(x2Rle, x2Ranges)) xList <- list(a = lapply(seq_len(length(xRleViewsList[[1]])), function(i) window(x1, start = start(x1Ranges)[i], end = end(x1Ranges)[i])), b = lapply(seq_len(length(xRleViewsList[[2]])), function(i) window(x2, start = start(x2Ranges)[i], end = end(x2Ranges)[i]))) checkIdentical(c("a", "b"), names(viewApply(xRleViewsList, min))) checkIdentical(c("a", "b"), names(viewMins(xRleViewsList))) checkIdentical(c("a", "b"), names(viewMaxs(xRleViewsList))) checkIdentical(c("a", "b"), names(viewSums(xRleViewsList))) checkIdentical(c("a", "b"), names(viewMeans(xRleViewsList))) checkIdentical(c("a", "b"), names(viewWhichMins(xRleViewsList))) checkIdentical(c("a", "b"), names(viewWhichMaxs(xRleViewsList))) checkIdentical(c("a", "b"), names(viewRangeMins(xRleViewsList, na.rm = TRUE))) checkIdentical(c("a", "b"), names(viewRangeMaxs(xRleViewsList, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(xList, lapply, min)), unlist(viewMins(xRleViewsList))) checkEqualsNumeric(unlist(lapply(xList, lapply, min)), unlist(viewApply(xRleViewsList, min))) checkEqualsNumeric(unlist(lapply(xList, lapply, min, na.rm = TRUE)), unlist(viewMins(xRleViewsList, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(xList, lapply, min, na.rm = TRUE)), unlist(viewApply(xRleViewsList, min, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(xList, lapply, max)), unlist(viewMaxs(xRleViewsList))) checkEqualsNumeric(unlist(lapply(xList, lapply, max)), unlist(viewApply(xRleViewsList, max))) checkEqualsNumeric(unlist(lapply(xList, lapply, max, na.rm = TRUE)), unlist(viewMaxs(xRleViewsList, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(xList, lapply, max, na.rm = TRUE)), unlist(viewApply(xRleViewsList, max, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(xList, lapply, sum)), unlist(viewSums(xRleViewsList))) checkEqualsNumeric(unlist(lapply(xList, lapply, mean)), unlist(viewMeans(xRleViewsList))) checkEqualsNumeric(unlist(lapply(xList, lapply, sum)), unlist(viewApply(xRleViewsList, sum))) checkEqualsNumeric(unlist(lapply(xList, lapply, sum, na.rm = TRUE)), unlist(viewSums(xRleViewsList, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(xList, lapply, mean, na.rm = TRUE)), unlist(viewMeans(xRleViewsList, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(xList, lapply, sum, na.rm = TRUE)), unlist(viewApply(xRleViewsList, sum, na.rm = TRUE))) y1 <- rep(c(1.2, 3.4, NA, 7.8, 9.0), 1:5) y1Ranges <- IRanges(start = c(1, 3, 5, 7, 9), end = c(1, 13, 11, 10, 9)) y1Rle <- Rle(y1) y2 <- rev(y1) y2Rle <- Rle(y2) y2Ranges <- IRanges(start = c(2, 4, 6, 8, 10), end = c(3, 9, 11, 13, 15)) checkIdentical(RleViewsList(Views(y1Rle, y1Ranges), Views(y2Rle, y2Ranges)), RleViewsList(rleList = RleList(y1Rle, y2Rle), rangesList = IRangesList(y1Ranges, y2Ranges))) yRleViewsList <- RleViewsList(Views(y1Rle, y1Ranges), Views(y2Rle, y2Ranges)) yList <- list(lapply(seq_len(length(yRleViewsList[[1]])), function(i) window(y1, start = start(y1Ranges)[i], end = end(y1Ranges)[i])), lapply(seq_len(length(yRleViewsList[[2]])), function(i) window(y2, start = start(y2Ranges)[i], end = end(y2Ranges)[i]))) checkEqualsNumeric(unlist(lapply(yList, lapply, min)), unlist(viewMins(yRleViewsList))) checkEqualsNumeric(unlist(lapply(yList, lapply, min)), unlist(viewApply(yRleViewsList, min))) checkEqualsNumeric(unlist(lapply(yList, lapply, min, na.rm = TRUE)), unlist(viewMins(yRleViewsList, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(yList, lapply, min, na.rm = TRUE)), unlist(viewApply(yRleViewsList, min, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(yList, lapply, max)), unlist(viewMaxs(yRleViewsList))) checkEqualsNumeric(unlist(lapply(yList, lapply, max)), unlist(viewApply(yRleViewsList, max))) checkEqualsNumeric(unlist(lapply(yList, lapply, max, na.rm = TRUE)), unlist(viewMaxs(yRleViewsList, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(yList, lapply, max, na.rm = TRUE)), unlist(viewApply(yRleViewsList, max, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(yList, lapply, sum)), unlist(viewSums(yRleViewsList))) checkEqualsNumeric(unlist(lapply(yList, lapply, mean)), unlist(viewMeans(yRleViewsList))) checkEqualsNumeric(unlist(lapply(yList, lapply, sum)), unlist(viewApply(yRleViewsList, sum))) checkEqualsNumeric(unlist(lapply(yList, lapply, sum, na.rm = TRUE)), unlist(viewSums(yRleViewsList, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(yList, lapply, mean, na.rm = TRUE)), unlist(viewMeans(yRleViewsList, na.rm = TRUE))) checkEqualsNumeric(unlist(lapply(yList, lapply, sum, na.rm = TRUE)), unlist(viewApply(yRleViewsList, sum, na.rm = TRUE))) } IRanges/inst/unitTests/test_coverage-methods.R0000644000175100017510000000155712607265143022535 0ustar00biocbuildbiocbuildtest_IRanges_coverage <- function() { ir <- IRanges(c(1, 8, 14, 15, 19, 34, 40), width = c(12, 6, 6, 15, 6, 2, 7)) checkIdentical(as.vector(coverage(ir)), rep(c(1L, 2L, 1L, 2L, 3L, 2L, 1L, 0L, 1L, 0L, 1L), c(7, 5, 2, 4, 1, 5, 5, 4, 2, 4, 7))) ir <- IRanges(start=c(-2L, 6L, 9L, -4L, 1L, 0L, -6L, 10L), width=c( 5L, 0L, 6L, 1L, 4L, 3L, 2L, 3L)) checkIdentical(as.vector(coverage(ir)), rep(c(3L, 1L, 0L, 1L, 2L, 1L), c(2, 2, 4, 1, 3, 2))) checkIdentical(as.vector(coverage(ir, shift=7)), rep(c(1L, 0L, 1L, 2L, 3L, 1L, 0L, 1L, 2L, 1L), c(3, 1, 2, 1, 2, 2, 4, 1, 3, 2))) checkIdentical(as.vector(coverage(ir, shift=7, width=27)), rep(c(1L, 0L, 1L, 2L, 3L, 1L, 0L, 1L, 2L, 1L, 0L), c(3, 1, 2, 1, 2, 2, 4, 1, 3, 2, 6))) } IRanges/inst/unitTests/test_expand.R0000644000175100017510000000367012607265143020556 0ustar00biocbuildbiocbuildtest_expand <- function(){ ## setup aa <- CharacterList("a", paste0("d", 1:2), paste0("b", 1:3), c(), "c") bb <- CharacterList(paste0("sna", 1:2),"foo", paste0("bar", 1:3),c(),"hica") df <- DataFrame(aa=aa, bb=bb, cc=11:15) ## tests ## test one col without dropping res1 <- expand(df, colnames="aa", keepEmptyRows=TRUE) checkTrue(dim(res1)[1]==8) checkTrue(dim(res1)[2]==3) checkIdentical(res1$aa,c("a","d1","d2","b1","b2","b3",NA,"c")) checkIdentical(res1$bb[[4]],c("bar1","bar2","bar3")) ## test one col with dropping res2 <- expand(df, colnames="aa", keepEmptyRows=FALSE) checkTrue(dim(res2)[1]==7) checkTrue(dim(res2)[2]==3) checkIdentical(res2$aa,c("a","d1","d2","b1","b2","b3","c")) checkIdentical(res2$bb[[4]],c("bar1","bar2","bar3")) ## test two columns no dropping res3 <- expand(df, colnames=c("aa","bb"), keepEmptyRows=TRUE) checkTrue(dim(res3)[1]==15) checkTrue(dim(res3)[2]==3) checkIdentical(res3$aa, c("a","a","d1","d2","b1","b1","b1","b2","b2","b2","b3","b3","b3",NA,"c")) checkIdentical(as.character(as.data.frame(res3[14,])), c(NA, NA, "14")) ## test two columns with dropping res4 <- expand(df, colnames=c("aa","bb"), keepEmptyRows=FALSE) checkTrue(dim(res4)[1]==14) checkTrue(dim(res4)[2]==3) checkIdentical(res4$aa, c("a","a","d1","d2","b1","b1","b1","b2","b2","b2","b3","b3","b3","c")) ## inverted order (different sorting of 2 cols, no dropping res5 <- expand(df, colnames=c("bb","aa"), keepEmptyRows=TRUE) checkTrue(dim(res5)[1]==15) checkTrue(dim(res5)[2]==3) checkIdentical(res5$aa, c("a","a","d1","d2","b1","b2","b3","b1","b2","b3","b1","b2","b3",NA,"c")) ## inverted order (different sorting of 2 cols, with dropping res6 <- expand(df, colnames=c("bb","aa"), keepEmptyRows=FALSE) checkTrue(dim(res6)[1]==14) checkTrue(dim(res6)[2]==3) checkIdentical(res6$aa, c("a","a","d1","d2","b1","b2","b3","b1","b2","b3","b1","b2","b3","c")) } IRanges/inst/unitTests/test_extractList.R0000644000175100017510000001014312607265143021576 0ustar00biocbuildbiocbuild### test_relistToClass <- function() { ## TODO } test_relist <- function() { ## TODO } test_splitAsList <- function() { ## TODO } test_extractList <- function() { ## TODO } test_regroupBySupergroup <- function() { regroupBySupergroup <- IRanges:::regroupBySupergroup .do_checks <- function(x, breakpoints, target) { supergroups <- PartitioningByEnd(breakpoints) current <- regroupBySupergroup(x, supergroups) checkIdentical(target, current) checkIdentical(target, regroupBySupergroup(x, breakpoints)) x_partitioning <- PartitioningByEnd(x) current2 <- regroupBySupergroup(x_partitioning, supergroups) checkIdentical(PartitioningByEnd(target), current2) } x <- CharacterList( x1=NULL, x2=LETTERS[1:3], x3=LETTERS[4:5], x4=letters[1:5], x5=NULL, x6=letters[6:7] ) breakpoints <- c(SG1=3, SG2=6) target <- CharacterList(SG1=LETTERS[1:5], SG2=letters[1:7], compress=TRUE) .do_checks(as(x, "CompressedList"), breakpoints, target) .do_checks(as(x, "SimpleList"), breakpoints, target) breakpoints <- c(SG1=2, SG2=5, SG3=6) target <- CharacterList(SG1=LETTERS[1:3], SG2=c(LETTERS[4:5], letters[1:5]), SG3=letters[6:7], compress=TRUE) .do_checks(as(x, "CompressedList"), breakpoints, target) .do_checks(as(x, "SimpleList"), breakpoints, target) breakpoints <- c(SG1=2, 2, SG2=5, SG3=6) target <- CharacterList(SG1=LETTERS[1:3], NULL, SG2=c(LETTERS[4:5], letters[1:5]), SG3=letters[6:7], compress=TRUE) .do_checks(as(x, "CompressedList"), breakpoints, target) .do_checks(as(x, "SimpleList"), breakpoints, target) breakpoints <- 6 target <- CharacterList(unlist(x, use.names=FALSE), compress=TRUE) .do_checks(as(x, "CompressedList"), breakpoints, target) .do_checks(as(x, "SimpleList"), breakpoints, target) breakpoints <- c(SG1=6, SG2=6, SG3=6) target <- CharacterList(SG1=unlist(x, use.names=FALSE), SG2=NULL, SG3=NULL, compress=TRUE) .do_checks(as(x, "CompressedList"), breakpoints, target) .do_checks(as(x, "SimpleList"), breakpoints, target) breakpoints <- c(0, 0, 0, 6, 6) target <- CharacterList(NULL, NULL, NULL, unlist(x, use.names=FALSE), NULL, compress=TRUE) .do_checks(as(x, "CompressedList"), breakpoints, target) .do_checks(as(x, "SimpleList"), breakpoints, target) breakpoints <- seq_along(x) target <- unname(as(x, "CompressedList")) .do_checks(as(x, "CompressedList"), breakpoints, target) .do_checks(as(x, "SimpleList"), breakpoints, target) names(breakpoints) <- names(x) target <- as(x, "CompressedList") .do_checks(as(x, "CompressedList"), breakpoints, target) # no-op .do_checks(as(x, "SimpleList"), breakpoints, target) x0 <- CharacterList() breakpoints <- setNames(integer(0), character(0)) target <- setNames(CharacterList(compress=TRUE), character(0)) .do_checks(as(x0, "CompressedList"), breakpoints, target) # Fails at the moment because unlist() is doesn't work properly on # SimpleCharacterList #.do_checks(as(x0, "SimpleList"), breakpoints, target) x2 <- RleList(Rle(44:45, 2:1), Rle(45), Rle(-2, 3)) breakpoints <- c(SG1=2, SG2=3) target <- RleList(SG1=Rle(44:45, c(2,2)), SG2=Rle(-2, 3), compress=TRUE) .do_checks(as(x2, "CompressedList"), breakpoints, target) .do_checks(as(x2, "SimpleList"), breakpoints, target) x3 <- Views(unlist(x2, use.names=FALSE), start=c(3, 1, 1), end=c(6, 1, 3)) breakpoints <- c(SG1=2, SG2=3) target <- RleList(SG1=Rle(c(45,-2,44), c(2,2,1)), SG2=Rle(44:45, 2:1), compress=TRUE) .do_checks(x3, breakpoints, target) } IRanges/inst/unitTests/test_findOverlaps-methods.R0000644000175100017510000001117612607265143023374 0ustar00biocbuildbiocbuild### test_findOverlaps_Ranges <- function() { ## ..... ## .... ## .. ## x ## xx ## xxx query <- IRanges(c(1, 4, 9), c(5, 7, 10)) subject <- IRanges(c(2, 2, 10), c(2, 3, 12)) result <- findOverlaps(query, subject, select = "first") checkIdentical(result, c(1L, NA, 3L)) result <- findOverlaps(query, subject, select = "last") checkIdentical(result, c(2L, NA, 3L)) result <- findOverlaps(query, subject, select = "arbitrary") checkIdentical(result, c(2L, NA, 3L)) checkOverlap <- function(a, q, s, r, c) { target <- Hits(q, s, r, c) checkIdentical(t(a), t(target)) } result <- findOverlaps(query, subject) checkOverlap(result, c(1, 1, 3), c(1, 2, 3), 3, 3) ## with 'maxgap' result <- findOverlaps(query, subject, 1) checkOverlap(result, c(1, 1, 2, 3), c(1, 2, 2, 3), 3, 3) ## with 'minoverlap' result <- findOverlaps(query, subject, minoverlap = 3L) checkOverlap(result, integer(0), integer(0), 3, 3) result <- findOverlaps(query, subject, minoverlap = 2L) checkOverlap(result, 1, 2, 3, 3) result <- findOverlaps(query, subject, minoverlap = 2L, select = "first") checkIdentical(result, c(2L, NA, NA)) result <- findOverlaps(query, subject, minoverlap = 2L, select = "last") checkIdentical(result, c(2L, NA, NA)) result <- findOverlaps(query, subject, minoverlap = 2L, select = "arbitrary") checkIdentical(result, c(2L, NA, NA)) ## zero-width ranges query <- IRanges(9:14, 8:13) result <- findOverlaps(query, subject) checkOverlap(result, integer(0), integer(0), 6, 3) result <- findOverlaps(query, subject, minoverlap = 0L) checkOverlap(result, 2:5, c(3, 3, 3, 3), 6, 3) result <- findOverlaps(query, subject, maxgap=1L, minoverlap = 0L) checkOverlap(result, 1:6, c(3, 3, 3, 3, 3, 3), 6, 3) result <- findOverlaps(subject, query) checkOverlap(result, integer(0), integer(0), 3, 6) result <- findOverlaps(subject, query, minoverlap = 0L) checkOverlap(result, c(3, 3, 3, 3), 2:5, 3, 6) result <- findOverlaps(subject, query, maxgap=1L, minoverlap = 0L) checkOverlap(result, c(3, 3, 3, 3, 3, 3), 1:6, 3, 6) ## ..... ## .... ## .. ## xxxx ## xxx query <- IRanges(c(1, 4, 9), c(5, 7, 10)) subject <- IRanges(c(2, 2), c(5, 4)) result <- findOverlaps(query, subject) checkOverlap(result, c(1, 1, 2, 2), c(1, 2, 1, 2), 3, 2) result <- findOverlaps(subject, query) checkOverlap(result, c(1, 1, 2, 2), c(1, 2, 1, 2), 2, 3) query <- IRanges(c(1, 4, 9, 11), c(5, 7, 10, 11)) result <- findOverlaps(query) checkOverlap(result, c(1, 1, 2, 2, 3, 4), c(1, 2, 1, 2, 3, 4), 4, 4) ## check case of identical subjects ## ..... ## ..... ## .. ## xxxx ## xxxx ## xx ## xxx ## xx query <- IRanges(c(1, 4, 9), c(5, 7, 10)) subject <- IRanges(c(2, 2, 6, 6, 6), c(5, 5, 7, 8, 7)) result <- findOverlaps(query, subject) checkOverlap(result, c(1, 1, 2, 2, 2, 2, 2), c(1, 2, 1, 2, 3, 4, 5), 3, 5) subject <- IRanges(c(1, 6, 13), c(4, 9, 14)) # single points checkIdentical(findOverlaps(c(3L, 7L, 10L), subject, select = "first"), c(1L, 2L, NA)) checkIdentical(findOverlaps(c(3L, 7L, 10L), subject, select = "last"), c(1L, 2L, NA)) checkIdentical(findOverlaps(c(3L, 7L, 10L), subject, select = "arbitrary"), c(1L, 2L, NA)) checkIdentical(findOverlaps(IRanges(c(2,1),c(3,4)), subject), Hits(1:2, c(1, 1), 2, 3)) ## check other types of matching ## .. ## .. ## .... ## ...... ## xxxx ## xxxx ## xxxxx ## xxxx query <- IRanges(c(1, 5, 3, 4), width=c(2, 2, 4, 6)) subject <- IRanges(c(1, 3, 5, 6), width=c(4, 4, 5, 4)) ## 'start' result <- findOverlaps(query, subject, type = "start") checkOverlap(result, c(1, 2, 3), c(1, 3, 2), 4, 4) ## minoverlap > 1L result <- findOverlaps(query, subject, type = "start", minoverlap = 3L) checkOverlap(result, 3, 2, 4, 4) ## 'end' result <- findOverlaps(query, subject, type = "end") checkOverlap(result, c(2, 3, 4, 4), c(2, 2, 3, 4), 4, 4) result <- findOverlaps(subject, query, type = "end") checkOverlap(result, c(2, 2, 3, 4), c(2, 3, 4, 4), 4, 4) ## select = "first" result <- findOverlaps(query, subject, type = "end", select = "first") checkIdentical(result, c(NA, 2L, 2L, 3L)) ## 'within' result <- findOverlaps(query, subject, type = "within") checkOverlap(result, c(1, 2, 2, 3), c(1, 2, 3, 2), 4, 4) ## 'equal' result <- findOverlaps(query, subject, type = "equal") checkOverlap(result, 3, 2, 4, 4) checkException(findOverlaps(query, NULL), silent = TRUE) checkException(findOverlaps(NULL, query), silent = TRUE) } IRanges/inst/unitTests/test_inter-range-methods.R0000644000175100017510000002123112607265143023144 0ustar00biocbuildbiocbuildtest_Ranges_range <- function() { ir1 <- IRanges(c(2,5,1), c(3,7,3)) ir2 <- IRanges(c(5,2,0), c(6,3,1)) checkIdentical(range(ir1), IRanges(1, 7)) checkIdentical(range(ir1, ir2), IRanges(0, 7)) checkIdentical(range(IRanges()), IRanges()) checkException(range(ir1, c(2,3)), silent = TRUE) } test_RangesList_range <- function() { for (compress in c(TRUE, FALSE)) { rl1 <- IRangesList(a = IRanges(c(1,2),c(4,3)), b = IRanges(c(4,6),c(10,7)), compress = compress) rl2 <- IRangesList(c = IRanges(c(0,2),c(4,5)), a = IRanges(c(4,5),c(6,7)), compress = compress) ans <- IRangesList(a = IRanges(1,7), b = IRanges(4,10), c = IRanges(0,5), compress = compress) checkIdentical(range(rl1, rl2), ans) names(rl2) <- NULL ans <- IRangesList(IRanges(0,5), IRanges(4,10), compress = compress) checkIdentical(range(rl1, rl2), ans) ## must be same length checkException(range(rl2, rep.int(rl2, 2L)), silent=TRUE) } } test_IRanges_reduce <- function() { x <- IRanges() current <- reduce(x) checkIdentical(x, current) x <- IRanges(1:3, width=0) current <- reduce(x, with.revmap=TRUE) target <- x mcols(target) <- DataFrame(revmap=as(seq_along(target), "IntegerList")) checkIdentical(target, current) current <- reduce(x, drop.empty.ranges=TRUE, with.revmap=TRUE) target <- IRanges() mcols(target) <- DataFrame(revmap=as(seq_along(target), "IntegerList")) checkIdentical(target, current) x <- IRanges(c(1:4, 10:11, 11), width=c(0,1,1,0,0,0,1)) current <- reduce(x, with.revmap=TRUE) target <- IRanges(c(1:2, 10:11), width=c(0,2,0,1)) mcols(target) <- DataFrame(revmap=IntegerList(1,2:4,5,6:7)) checkIdentical(target, current) current <- reduce(x, drop.empty.ranges=TRUE, with.revmap=TRUE) target <- IRanges(c(2, 11), width=c(2,1)) mcols(target) <- DataFrame(revmap=IntegerList(2:3,7)) checkIdentical(target, current) x <- IRanges(start=c(1,2,3), end=c(5,2,8)) y <- reduce(x, with.revmap=TRUE) target <- IRanges(start=1, end=8) mcols(target) <- DataFrame(revmap=IntegerList(1:3)) checkIdentical(target, y) mcols(target)$revmap <- as(seq_along(target), "IntegerList") checkIdentical(target, reduce(y, with.revmap=TRUE)) x <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) y <- reduce(x, with.revmap=TRUE) target <- IRanges(start=c(1,15,20), end=c(5,15,100)) mcols(target) <- DataFrame(revmap=IntegerList(4, 1, 3:2)) checkIdentical(target, y) mcols(target)$revmap <- as(seq_along(target), "IntegerList") checkIdentical(target, reduce(y, with.revmap=TRUE)) x <- IRanges(start=c(7,3,-2,6,7,-10,-2,3), width=c(3,1,0,0,0,0,8,0)) ## Before reduction: ## start end width ==-10===-5====0===+5==+10=== ## [1] 7 9 3 ....:....:....:....:.xxx:... ## [2] 3 3 1 ....:....:....:..x.:....:... ## [3] -2 -3 0 ....:....:..[.:....:....:... ## [4] 6 5 0 ....:....:....:....:[...:... ## [5] 7 6 0 ....:....:....:....:.[..:... ## [6] -10 -11 0 ....[....:....:....:....:... ## [7] -2 5 8 ....:....:..xxxxxxxx....:... ## [8] 3 2 0 ....:....:....:..[.:....:... ## ---------------------==-10===-5====0===+5==+10=== ## After reduction: ## y1: ....[....:..xxxxxxxx.xxx:... ## y3: ....:....:..xxxxxxxx....:... y1 <- reduce(x) checkIdentical(y1, IRanges(start=c(-10,-2,7), end=c(-11,5,9))) checkIdentical(reduce(y1), y1) y2 <- reduce(x, with.inframe.attrib=TRUE) checkIdentical(start(attr(y2, "inframe")), c(9L,6L,1L,9L,9L,1L,1L,6L)) checkIdentical(width(attr(y2, "inframe")), width(x)) y3 <- reduce(x, drop.empty.ranges=TRUE) checkIdentical(y3, y1[width(y1) != 0L]) checkIdentical(reduce(y3), y3) y4 <- reduce(x, drop.empty.ranges=TRUE, with.inframe.attrib=TRUE) checkIdentical(attr(y4, "inframe"), attr(y2, "inframe")) y5 <- reduce(x, min.gapwidth=0) checkIdentical(y5, IRanges(start=c(-10,-2,-2,6,7,7), end=c(-11,-3,5,5,6,9))) y6 <- reduce(x, drop.empty.ranges=TRUE, min.gapwidth=0) checkIdentical(y6, y5[width(y5) != 0L]) y7 <- reduce(x, min.gapwidth=2) checkIdentical(y7, IRanges(start=c(-10,-2), end=c(-11,9))) y8 <- reduce(x, min.gapwidth=8) checkIdentical(y8, y7) y9 <- reduce(x, min.gapwidth=9) checkIdentical(y9, IRanges(start=-10, end=9)) } test_RangesList_reduce <- function() { range1 <- IRanges(start=c(1,2,3), end=c(5,2,8)) range2 <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) range3 <- IRanges(start=c(3,-2,6,7,-10,-2,3), width=c(1,0,0,0,0,8,0)) range4 <- IRanges() for (compress in c(TRUE, FALSE)) { collection <- IRangesList(one=range1, range2, range3, range4, compress=compress) for (with.revmap in c(FALSE, TRUE)) { for (drop.empty.ranges in c(FALSE, TRUE)) { current <- reduce(collection, drop.empty.ranges=drop.empty.ranges, with.revmap=with.revmap) target <- IRangesList(one=reduce(range1, drop.empty.ranges=drop.empty.ranges, with.revmap=with.revmap), reduce(range2, drop.empty.ranges=drop.empty.ranges, with.revmap=with.revmap), reduce(range3, drop.empty.ranges=drop.empty.ranges, with.revmap=with.revmap), reduce(range4, drop.empty.ranges=drop.empty.ranges, with.revmap=with.revmap), compress=compress) checkIdentical(target, current) } } } } test_IRanges_gaps <- function() { checkIdentical(gaps(IRanges()), IRanges()) checkIdentical(gaps(IRanges(), start=1, end=4), IRanges(start=1, end=4)) x <- IRanges(start=2, end=3) checkIdentical(gaps(x), IRanges()) checkIdentical(gaps(x, start=2), IRanges()) checkIdentical(gaps(x, start=4), IRanges()) checkIdentical(gaps(x, start=0), IRanges(start=0, end=1)) checkIdentical(gaps(x, end=3), IRanges()) checkIdentical(gaps(x, end=1), IRanges()) checkIdentical(gaps(x, end=5), IRanges(start=4, end=5)) checkIdentical(gaps(x, start=0, end=5), IRanges(start=c(0,4), end=c(1,5))) } test_RangesList_gaps <- function() { range1 <- IRanges(start=c(1,2,3), end=c(5,2,8)) range2 <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) for (compress in c(TRUE, FALSE)) { collection <- IRangesList(one = range1, range2, compress = compress) checkIdentical(gaps(collection), IRangesList(one = gaps(range1), gaps(range2), compress = compress)) } } test_Ranges_disjoin <- function() { checkIdentical(disjoin(IRanges()), IRanges()) ir <- IRanges(c(1, 1, 4, 10), c(6, 3, 8, 10)) checkIdentical(disjoin(ir), IRanges(c(1, 4, 7, 10), c(3, 6, 8, 10))) } test_CompressedIRangesList_disjoin <- function() { r0 <- IRanges(10, 20) checkTrue(validObject(disjoin(IRangesList()))) ## unnamed; incl. 0-length irl <- IRangesList(IRanges()) checkIdentical(irl, disjoin(irl)) irl <- IRangesList(r0, IRanges(), r0) checkIdentical(irl, disjoin(irl)) irl <- IRangesList(r0, IRanges(), IRanges(), r0) checkIdentical(irl, disjoin(irl)) ## named; incl. 0-length irl <- IRangesList(a=IRanges()) checkIdentical(irl, disjoin(irl)) irl <- IRangesList(a=r0, b=IRanges(), c=r0) checkIdentical(irl, disjoin(irl)) irl <- IRangesList(a=r0, b=IRanges(), c=IRanges(), d=r0) checkIdentical(irl, disjoin(irl)) ## no interference between separate elements r0 <- IRanges(10, c(15, 20)) dr0 <- disjoin(r0) irl <- IRangesList(r0, r0) checkIdentical(IRangesList(dr0, dr0), disjoin(irl)) irl <- IRangesList(r0, IRanges(), r0) checkIdentical(IRangesList(dr0, IRanges(), dr0), disjoin(irl)) ## 0-width ## 1-width r0 <- IRanges(c(1, 10), 10) irl <- IRangesList(r0, IRanges()) checkIdentical(disjoin(r0), disjoin(irl)[[1]]) irl <- IRangesList(IRanges(), r0) checkIdentical(disjoin(r0), disjoin(irl)[[2]]) } test_Ranges_disjointBins <- function() { checkIdentical(disjointBins(IRanges()), integer()) checkIdentical(disjointBins(IRanges(1, 5)), 1L) checkIdentical(disjointBins(IRanges(c(1, 3), c(5, 12))), c(1L, 2L)) checkIdentical(disjointBins(IRanges(c(1, 3, 10), c(5, 12, 13))), c(1L, 2L, 1L)) checkIdentical(disjointBins(IRanges(c(3, 1, 10), c(5, 12, 13))), c(2L, 1L, 2L)) } IRanges/inst/unitTests/test_intra-range-methods.R0000644000175100017510000002222012607265143023137 0ustar00biocbuildbiocbuildtest_shift_Ranges <- function() { ir0 <- IRanges(0, 0) ir1 <- shift(ir0, .Machine$integer.max) checkTrue(validObject(ir1)) checkIdentical(.Machine$integer.max, start(ir1)) checkIdentical(.Machine$integer.max, end(ir1)) checkIdentical(1L, width(ir1)) checkIdentical(ir1, shift(ir1)) checkIdentical(ir1, shift(shift(ir1, -10), 10)) ir2 <- shift(ir0, -.Machine$integer.max) checkTrue(validObject(ir2)) checkIdentical(-.Machine$integer.max, start(ir2)) checkIdentical(-.Machine$integer.max, end(ir2)) checkIdentical(1L, width(ir2)) checkIdentical(ir2, shift(ir2)) checkIdentical(ir2, shift(shift(ir2, 10), -10)) ## shift() would produce an object with ranges that are not within the ## [-.Machine$integer.max, .Machine$integer.max] range. checkException(suppressWarnings(shift(ir1, 1)), silent=TRUE) checkException(suppressWarnings(shift(ir2, -1)), silent=TRUE) ir3 <- IRanges(1999222000, width=1000) checkException(suppressWarnings(shift(ir3, 188222000)), silent=TRUE) ir4 <- IRanges(1:20, width=222000000) checkException(suppressWarnings(shift(ir4, 1:20 * 99000000L)), silent=TRUE) } test_narrow_Ranges <- function() { ir1 <- IRanges(c(2,5,1), c(3,7,3)) checkIdentical(narrow(ir1, start=1, end=2), IRanges(c(2, 5, 1), c(3, 6, 2))) checkException(narrow(ir1, start=10, end=20), silent = TRUE) } test_narrow_RangesList <- function() { range1 <- IRanges(start=c(2,5), end=c(3,7)) range2 <- IRanges(start=1, end=3) for (compress in c(TRUE, FALSE)) { collection <- IRangesList(range1, range2, compress = compress) checkIdentical(narrow(collection, start=1, end=2), IRangesList(IRanges(c(2, 5), c(3, 6)), IRanges(1, 2), compress = compress)) checkException(narrow(collection, start=10, end=20), silent = TRUE) } } test_resize_Ranges <- function() { ir1 <- IRanges(c(2,5,1), c(3,7,3)) checkIdentical(resize(ir1, width=10), IRanges(c(2, 5, 1), width=10)) checkIdentical(resize(ir1, width=10, fix="end"), IRanges(c(-6, -2, -6), width=10)) checkIdentical(resize(ir1, width=10, fix="center"), IRanges(c(-2, 1, -3), width=10)) checkIdentical(resize(ir1, width=10, fix=c("start", "end", "center")), IRanges(c(2, -2, -3), width=10)) checkException(resize(ir1, -1), silent = TRUE) } test_resize_RangesList <- function() { range1 <- IRanges(start=c(2,5), end=c(3,7)) range2 <- IRanges(start=1, end=3) for (compress in c(TRUE, FALSE)) { collection <- IRangesList(range1, range2, compress = compress) checkIdentical(resize(collection, width=10), IRangesList(IRanges(c(2, 5), width=10), IRanges(1, width=10), compress = compress)) checkIdentical(resize(collection, width=10, fix="end"), IRangesList(IRanges(c(-6, -2), width=10), IRanges(-6, width=10), compress = compress)) checkIdentical(resize(collection, width=10, fix="center"), IRangesList(IRanges(c(-2, 1), width=10), IRanges(-3, width=10), compress = compress)) checkIdentical(resize(collection, width=10, fix=CharacterList(c("start", "end"), "center")), IRangesList(IRanges(c(2, -2), width=10), IRanges(-3, width=10), compress = compress)) checkException(resize(collection, -1), silent = TRUE) } } test_flank_Ranges <- function() { checkIdentical(flank(IRanges(), 2), IRanges()) ir1 <- IRanges(c(2, 5, 1), c(3, 7, 3)) checkIdentical(flank(ir1, 2), IRanges(c(0, 3, -1), c(1, 4, 0))) checkIdentical(flank(ir1, 2, FALSE), IRanges(c(4, 8, 4), c(5, 9, 5))) checkIdentical(flank(ir1, 2, c(FALSE, TRUE, FALSE)), IRanges(c(4, 3, 4), c(5, 4, 5))) checkIdentical(flank(ir1, c(2, -2, 2)), IRanges(c(0, 5, -1), c(1, 6, 0))) checkIdentical(flank(ir1, 2, both = TRUE), IRanges(c(0, 3, -1), c(3, 6, 2))) checkIdentical(flank(ir1, 2, FALSE, TRUE), IRanges(c(2, 6, 2), c(5, 9, 5))) checkIdentical(flank(ir1, -2, FALSE, TRUE), IRanges(c(2, 6, 2), c(5, 9, 5))) checkException(flank(ir1, 2, both = c(TRUE, FALSE, TRUE)), silent = TRUE) # not vectorized checkException(flank(ir1, 2, c(FALSE, TRUE, NA)), silent = TRUE) checkException(flank(ir1, NA), silent = TRUE) } test_flank_RangesList <- function() { range1 <- IRanges(start=c(2,5), end=c(3,7)) range2 <- IRanges(start=1, end=3) for (compress in c(TRUE, FALSE)) { collection <- IRangesList(range1, range2, compress = compress) checkIdentical(flank(collection, 2), IRangesList(IRanges(c(0, 3), c(1, 4)), IRanges(-1, 0), compress = compress)) checkIdentical(flank(collection, 2, FALSE), IRangesList(IRanges(c(4, 8), c(5, 9)), IRanges(4, 5), compress = compress)) checkIdentical(flank(collection, 2, LogicalList(c(FALSE, TRUE), FALSE)), IRangesList(IRanges(c(4, 3), c(5, 4)), IRanges(4, 5), compress = compress)) checkIdentical(flank(collection, IntegerList(c(2, -2), 2)), IRangesList(IRanges(c(0, 5), c(1, 6)), IRanges(-1, 0), compress = compress)) checkIdentical(flank(collection, 2, both = TRUE), IRangesList(IRanges(c(0, 3), c(3, 6)), IRanges(-1, 2), compress = compress)) checkIdentical(flank(collection, 2, FALSE, TRUE), IRangesList(IRanges(c(2, 6), c(5, 9)), IRanges(2, 5), compress = compress)) checkIdentical(flank(collection, -2, FALSE, TRUE), IRangesList(IRanges(c(2, 6), c(5, 9)), IRanges(2, 5), compress = compress)) checkException(flank(collection, 2, both = c(TRUE, FALSE, TRUE)), silent = TRUE) # not vectorized checkException(flank(collection, 2, LogicalList(c(FALSE, TRUE), NA)), silent = TRUE) checkException(flank(collection, NA), silent = TRUE) } } test_promoters <- function() { ir <- IRanges(c(10, 10), width=c(0, 1)) checkIdentical(width(promoters(ir, 0, 0)), c(0L, 0L)) checkIdentical(width(promoters(ir, 1, 0)), c(1L, 1L)) checkIdentical(start(promoters(ir, 1, 0)), c(9L, 9L)) checkIdentical(width(promoters(ir, 0, 1)), c(1L, 1L)) checkIdentical(start(promoters(ir, 0, 1)), c(10L, 10L)) ir <- IRanges(c(5, 2, 20), width=1) checkIdentical(start(promoters(ir, 5, 2)), c(0L, -3L, 15L)) rl <- RangesList("A"=IRanges(5:7, width=1), "B"=IRanges(10:12, width=5)) current <- promoters(rl, 0, 0) checkIdentical(names(current), names(rl)) checkIdentical(start(current), start(rl)) current <- promoters(rl, 2, 0) checkIdentical(unique(unlist(width(current))), 2L) library(XVector) subject <- XInteger(10, 3:-6) view <- Views(subject, start=4:2, end=4:6) current <- promoters(view, 0, 0) checkIdentical(start(current), start(view)) current <- promoters(view, 2, 0) checkIdentical(unique(width(current)), 2L) cmp <- IRangesList("A"=IRanges(5:7, width=1), "B"=IRanges(10:12, width=5)) current <- promoters(rl, 0, 0) checkIdentical(names(current), names(rl)) checkIdentical(start(current), start(rl)) current <- promoters(rl, 2, 0) checkIdentical(unique(unlist(width(current))), 2L) } test_reflect_Ranges <- function() { ir1 <- IRanges(c(2,5,1), c(3,7,3)) bounds <- IRanges(c(0, 5, 3), c(10, 6, 9)) checkIdentical(reflect(ir1, bounds), IRanges(c(7, 4, 9), c(8, 6, 11))) checkException(reflect(ir1, IRanges()), silent = TRUE) } test_restrict_Ranges <- function() { ir1 <- IRanges(c(2,5,1), c(3,7,3)) checkIdentical(restrict(ir1, start=2, end=5), IRanges(c(2, 5, 2), c(3, 5, 3))) checkIdentical(restrict(ir1, start=1, end=2), IRanges(c(2, 1), c(2, 2))) checkIdentical(restrict(ir1, start=1, end=2, keep.all.ranges=TRUE), IRanges(c(2, 3, 1), c(2, 2, 2))) } test_restrict_RangesList <- function() { range1 <- IRanges(start=c(2,5), end=c(3,7)) range2 <- IRanges(start=1, end=3) for (compress in c(TRUE, FALSE)) { collection <- IRangesList(range1, range2, compress = compress) checkIdentical(restrict(collection, start=2, end=5), IRangesList(IRanges(c(2, 5), c(3, 5)), IRanges(2, 3), compress = compress)) checkIdentical(restrict(collection, start=1, end=2), IRangesList(IRanges(2, 2), IRanges(1, 2), compress = compress)) checkIdentical(restrict(collection, start=1, end=2, keep.all.ranges=TRUE), IRangesList(IRanges(c(2, 3), c(2, 2)), IRanges(1, 2), compress = compress)) } } test_zoon_Ranges <- function() { ir <- IRanges(c(1,5), c(3,10)) checkIdentical(ir*1, ir) checkIdentical(ir*c(1,2), IRanges(c(1,6), c(3, 8))) checkIdentical(ir*-2, IRanges(c(-1,2), c(4, 13))) checkException(ir*NA_integer_, silent = TRUE) checkException(ir*numeric(), silent = TRUE) checkException(ir*c(1,2,1), silent = TRUE) checkException(ir[rep(1,3)]*c(1,2), silent = TRUE) } IRanges/inst/unitTests/test_nearest-methods.R0000644000175100017510000001131012607265143022367 0ustar00biocbuildbiocbuildcheckMatching <- function(a, q, s, r, c) { mat <- cbind(queryHits = as.integer(q), subjectHits = as.integer(s)) checkIdentical(as.matrix(a), mat) checkIdentical(c(queryLength(a), subjectLength(a)), as.integer(c(r, c))) } test_Ranges_adjacency <- function() { query <- IRanges(c(1, 3, 9), c(3, 7, 10)) subject <- IRanges(c(3, 10, 2), c(3, 12, 5)) checkIdentical(precede(query, subject), c(2L, 2L, NA)) checkIdentical(precede(IRanges(), subject), integer()) checkIdentical(precede(query, IRanges()), rep(NA_integer_, 3)) checkIdentical(precede(query), c(3L, 3L, NA)) checkIdentical(follow(query, subject), c(NA, NA, 3L)) checkIdentical(follow(IRanges(), subject), integer()) checkIdentical(follow(query, IRanges()), rep(NA_integer_, 3)) checkIdentical(follow(query), c(NA, NA, 2L)) checkMatching(precede(query, subject, select="all"), c(1, 2), c(2, 2), 3, 3) ## xxxx ## xxx ## xx ## xx ## xxx ## .. ## .. ## .. ## .. ## .. subject <- IRanges(c(1, 2, 9, 15, 15), width=c(4, 3, 2, 2, 3)) query <- IRanges(c(6, 11, 1, 13, 18), width=c(2, 2, 2, 2, 2)) checkMatching(precede(query, subject, select="all"), c(1, 2, 2, 3, 4, 4), c(3, 4, 5, 3, 4, 5), 5, 5) checkMatching(precede(subject, query, select="all"), c(1, 2, 3, 4, 5), c(1, 1, 2, 5, 5), 5, 5) checkMatching(follow(query, subject, select="all"), c(1, 1, 2, 4, 5), c(1, 2, 3, 3, 5), 5, 5) checkMatching(follow(subject, query, select="all"), c(3, 4, 5), c(1, 4, 4), 5, 5) checkMatching(precede(query, select="all"), c(1, 2, 3, 4), c(2, 4, 1, 5), 5, 5) checkMatching(precede(subject, select="all"), c(1, 2, 3, 3), c(3, 3, 4, 5), 5, 5) checkMatching(follow(query, select="all"), c(1, 2, 4, 5), c(3, 1, 2, 4), 5, 5) checkMatching(follow(subject, select="all"), c(3, 3, 4, 5), c(1, 2, 3, 3), 5, 5) } test_Ranges_nearest <- function() { query <- IRanges(c(1, 3, 9), c(2, 7, 10)) subject <- IRanges(c(3, 5, 12), c(3, 6, 12)) ## 2 possible results current <- nearest(query, subject) target1 <- c(1L, 1L, 3L) target2 <- c(1L, 2L, 3L) checkTrue(identical(target1, current) || identical(target2, current)) checkIdentical(nearest(query), c(2L, 1L, 2L)) checkIdentical(nearest(query, subject[c(2,3,1)]), c(3L, 3L, 2L)) ## xxxx ## xxx ## xx ## xx ## xxx ## .. ## .. ## .. ## .. ## .. subject <- IRanges(c(1, 2, 9, 15, 15), width=c(4, 3, 2, 2, 3)) query <- IRanges(c(6, 11, 1, 13, 18), width=c(2, 2, 2, 2, 2)) checkMatching(nearest(query, subject, select = "all"), c(1, 1, 1, 2, 3, 3, 4, 4, 5), c(1, 2, 3, 3, 1, 2, 4, 5, 5), 5, 5) checkMatching(nearest(subject, query, select = "all"), c(1, 2, 3, 4, 5, 5), c(3, 3, 2, 4, 4, 5), 5, 5) checkMatching(nearest(subject, select="all"), c(1, 2, 3, 3, 3, 3, 4, 5), c(2, 1, 1, 2, 4, 5, 5, 4), 5, 5) checkMatching(nearest(query, select="all"), c(1, 1, 2, 3, 4, 5), c(2, 3, 4, 1, 2, 4), 5, 5) } quiet <- suppressWarnings test_Ranges_distance <- function() { checkIdentical(quiet(distance(IRanges(), IRanges())), integer()) ## adjacent, overlap, separated by 1 query <- IRanges(c(1, 3, 9), c(2, 7, 10)) subject <- IRanges(c(3, 5, 12), c(3, 6, 12)) checkIdentical(quiet(distance(query, subject)), c(0L, 0L, 1L)) ## recycling checkIdentical(quiet(distance(query[1:2], subject)), c(0L, 0L, 9L)) ## zero-width target <- abs(-3:3) current <- sapply(-3:3, function(i) quiet(distance(shift(IRanges(4,3), i), IRanges(4,3)))) checkIdentical(target, current) checkIdentical(quiet(distance(IRanges(4,3), IRanges(3,4))), 0L) } test_Ranges_distanceToNearest <- function() { target <- Hits() current <- quiet(distanceToNearest(IRanges(), IRanges())) checkIdentical(queryHits(current), queryHits(target)) checkIdentical(subjectHits(current), subjectHits(target)) checkIdentical(queryLength(current), queryLength(target)) query <- IRanges(5, 10) subject <- IRanges(c(1, 1, 1), c(4, 5, 6)) current <- quiet(distanceToNearest(query, subject, select="all")) checkIdentical(subjectHits(current), c(2L, 3L)) current <- quiet(distanceToNearest(query, rev(subject), select="all")) checkIdentical(subjectHits(current), c(1L, 2L)) current <- distanceToNearest(query, IRanges()) checkIdentical(length(current), 0L) checkIdentical(queryLength(current), 1L) checkIdentical(subjectLength(current), 0L) } IRanges/inst/unitTests/test_seqapply.R0000644000175100017510000000062612607265143021133 0ustar00biocbuildbiocbuildtest_unsplit <- function() { ir <- IRanges(1:5, 11:15) f <- factor(c("a", "b", "a", "b", "b"), c("b", "a", "c")) rl <- split(ir, f) checkIdentical(unsplit(rl, f), ir) rl <- split(ir, f, drop=TRUE) checkIdentical(unsplit(rl, Rle(f), drop=TRUE), ir) checkException(unsplit(rl, f, drop=FALSE), silent=TRUE) v <- 1:5 l <- splitAsList(v, f) checkIdentical(unsplit(l, Rle(f)), v) } IRanges/inst/unitTests/test_setops-methods.R0000644000175100017510000000706612607265143022260 0ustar00biocbuildbiocbuildtest_IRanges_union <- function() { x <- IRanges(c(1, 4, 9), c(5, 7, 10)) y <- IRanges(c(2, 2, 10), c(2, 3, 12)) ans <- union(x, y) ans0 <- IRanges(c(1, 9), c(7, 12)) checkIdentical(ans, ans0) } test_IRanges_intersect <- function() { x <- IRanges(c(1, 4, 9), c(5, 7, 10)) y <- IRanges(c(2, 2, 10), c(2, 3, 12)) ans <- intersect(x, y) ans0 <- IRanges(c(2,10),c(3,10)) checkIdentical(ans, ans0) } test_IRanges_setdiff <- function() { x <- IRanges(c(1, 4, 9), c(5, 7, 10)) y <- IRanges(c(2, 2, 10), c(2, 3, 12)) ans <- setdiff(x, y) ans0 <- IRanges(c(1,4,9), c(1,7,9)) checkIdentical(ans, ans0) ans <- setdiff(y, x) ans0 <- IRanges(c(11), c(12)) checkIdentical(ans, ans0) } test_IRanges_punion <- function() { x <- IRanges(start=c(1,11,21,31,41,51,61,71), end=c(5,10,25,35,40,55,65,75)) y <- IRanges(start=c(1, 8,18,35,43,48,63,78), end=c(4,15,22,36,45,50,62,79)) ans0 <- IRanges(start=c(1,8,18,31,41,48,61,71), end=c(5,15,25,36,45,55,65,79)) checkIdentical(punion(x, y, fill.gap=TRUE), ans0) checkIdentical(punion(y, x, fill.gap=TRUE), ans0) } test_IRanges_pintersect <- function() { x <- IRanges(start=c(22,22,22,22,22,22), end=c(28,28,28,28,21,21)) y <- IRanges(start=c(25,30,29,25,22,22), end=c(30,40,40,24,21,29)) ansMaxStart <- IRanges(start=c(25,30,29,25,22,22), end=c(28,29,28,24,21,21)) ansStartX <- IRanges(start=c(25,22,29,25,22,22), end=c(28,21,28,24,21,21)) ansStartY <- IRanges(start=c(25,30,29,25,22,22), end=c(28,29,28,24,21,21)) checkException(pintersect(x, y), silent = TRUE) checkException(pintersect(y, x), silent = TRUE) for (resolve.empty in c("none", "max.start", "start.x")) { checkIdentical(x, pintersect(x, x, resolve.empty = resolve.empty)) checkIdentical(y, pintersect(y, y, resolve.empty = resolve.empty)) } checkIdentical(pintersect(x[-c(2,3)], y[-c(2,3)]), ansMaxStart[-c(2,3)]) checkIdentical(pintersect(y[-c(2,3)], x[-c(2,3)]), ansMaxStart[-c(2,3)]) checkIdentical(pintersect(x, y, resolve.empty = "max.start"), ansMaxStart) checkIdentical(pintersect(y, x, resolve.empty = "max.start"), ansMaxStart) checkIdentical(pintersect(x, y, resolve.empty = "start.x"), ansStartX) checkIdentical(pintersect(y, x, resolve.empty = "start.x"), ansStartY) } test_IRanges_psetdiff <- function() { x <- IRanges(start=c(1,11,21,31,41,51,61,71), end=c(5,10,25,35,40,55,65,75)) y <- IRanges(start=c(1, 8,18,35,43,48,63,78), end=c(4,15,22,36,45,50,62,79)) ans <- psetdiff(x[-7], y[-7]) ans0 <- IRanges(start=c(5,11,23,31,41,51,71), end=c(5,10,25,34,40,55,75)) checkIdentical(ans, ans0) ans <- psetdiff(y[-2], x[-2]) ans0 <- IRanges(start=c(1,18,36,43,48,63,78), end=c(0,20,36,45,50,62,79)) checkIdentical(ans, ans0) } test_IRanges_pgap <- function() { x <- IRanges(start=c(1,11,21,31,41,51,61,71), end=c(5,10,25,35,40,55,65,75)) y <- IRanges(start=c(1, 8,18,35,43,48,63,78), end=c(4,15,22,36,45,50,62,79)) ans <- pgap(x, y) checkIdentical(width(ans), c(0L, 0L, 0L, 0L, 2L, 0L, 0L, 2L)) checkIdentical(start(ans)[width(ans) != 0L], c(41L, 76L)) } test_RangesList_setops <- function() { rl1 <- RangesList(IRanges(c(1,2),c(4,3)), IRanges(c(4,6),c(10,7))) rl2 <- RangesList(IRanges(c(0,2),c(4,5)), IRanges(c(4,5),c(6,7))) checkIdentical(union(rl1, rl2), RangesList(union(rl1[[1]], rl2[[1]]), union(rl1[[2]], rl2[[2]]))) checkIdentical(intersect(rl1, rl2), RangesList(intersect(rl1[[1]], rl2[[1]]), intersect(rl1[[2]], rl2[[2]]))) checkIdentical(setdiff(rl1, rl2), RangesList(setdiff(rl1[[1]], rl2[[1]]), setdiff(rl1[[2]], rl2[[2]]))) } IRanges/inst/unitTests/test_tile-methods.R0000644000175100017510000000234212607265143021670 0ustar00biocbuildbiocbuildtest_tile <- function() { ir <- IRanges() checkIdentical(tile(ir, n=3), IRangesList()) checkIdentical(tile(ir, width=2), IRangesList()) checkIdentical(tile(ir, n=0), IRangesList()) ir <- IRanges(1, 4) checkIdentical(tile(ir, n=2), IRangesList(IRanges(c(1, 3), c(2, 4)))) checkIdentical(tile(ir, n=2), tile(ir, width=2)) ir <- IRanges(1, 5) checkIdentical(tile(ir, n=3), IRangesList(IRanges(c(1, 2, 4), c(1, 3, 5)))) checkIdentical(tile(ir, n=3), tile(ir, width=2)) ir <- IRanges(1, 4) checkIdentical(tile(ir, n=3), IRangesList(IRanges(1:3, c(1, 2, 4)))) ir <- IRanges(1:3, width=5:3) checkIdentical(tile(ir, n=3), IRangesList(IRanges(c(1, 2, 4), c(1, 3, 5)), IRanges(c(2, 3, 4), c(2, 3, 5)), IRanges(c(3, 4, 5), c(3, 4, 5)))) checkIdentical(tile(ir, width=2), IRangesList(IRanges(c(1, 2, 4), c(1, 3, 5)), IRanges(c(2, 4), c(3, 5)), IRanges(c(3, 4), c(3, 5)))) checkIdentical(elementLengths(tile(ir, width=4)), c(2L, 1L, 1L)) checkException(tile(ir, n=4), silent=TRUE) checkException(tile(ir, width=-1), silent=TRUE) checkException(tile(ir, n=-1), silent=TRUE) } IRanges/man/0000755000175100017510000000000012607265143013703 5ustar00biocbuildbiocbuildIRanges/man/AtomicList-class.Rd0000644000175100017510000004100112607265143017341 0ustar00biocbuildbiocbuild\name{AtomicList} \docType{class} % AtomicList classes \alias{class:AtomicList} \alias{AtomicList-class} \alias{AtomicList} \alias{class:CompressedAtomicList} \alias{CompressedAtomicList-class} \alias{CompressedAtomicList} \alias{class:SimpleAtomicList} \alias{SimpleAtomicList-class} \alias{SimpleAtomicList} \alias{class:LogicalList} \alias{LogicalList-class} \alias{LogicalList} \alias{class:CompressedLogicalList} \alias{CompressedLogicalList-class} \alias{CompressedLogicalList} \alias{class:SimpleLogicalList} \alias{SimpleLogicalList-class} \alias{SimpleLogicalList} \alias{class:IntegerList} \alias{IntegerList-class} \alias{IntegerList} \alias{class:CompressedIntegerList} \alias{CompressedIntegerList-class} \alias{CompressedIntegerList} \alias{class:SimpleIntegerList} \alias{SimpleIntegerList-class} \alias{SimpleIntegerList} \alias{class:NumericList} \alias{NumericList-class} \alias{NumericList} \alias{class:CompressedNumericList} \alias{CompressedNumericList-class} \alias{CompressedNumericList} \alias{class:SimpleNumericList} \alias{SimpleNumericList-class} \alias{SimpleNumericList} \alias{class:ComplexList} \alias{ComplexList-class} \alias{ComplexList} \alias{class:CompressedComplexList} \alias{CompressedComplexList-class} \alias{CompressedComplexList} \alias{class:SimpleComplexList} \alias{SimpleComplexList-class} \alias{SimpleComplexList} \alias{class:CharacterList} \alias{CharacterList-class} \alias{CharacterList} \alias{class:CompressedCharacterList} \alias{CompressedCharacterList-class} \alias{CompressedCharacterList} \alias{class:SimpleCharacterList} \alias{SimpleCharacterList-class} \alias{SimpleCharacterList} \alias{class:RawList} \alias{RawList-class} \alias{RawList} \alias{class:CompressedRawList} \alias{CompressedRawList-class} \alias{CompressedRawList} \alias{class:SimpleRawList} \alias{SimpleRawList-class} \alias{SimpleRawList} \alias{class:RleList} \alias{RleList-class} \alias{RleList} \alias{class:CompressedRleList} \alias{CompressedRleList-class} \alias{CompressedRleList} \alias{class:SimpleRleList} \alias{SimpleRleList-class} \alias{SimpleRleList} \alias{class:FactorList} \alias{FactorList-class} \alias{FactorList} \alias{class:CompressedFactorList} \alias{CompressedFactorList-class} \alias{CompressedFactorList} \alias{class:SimpleFactorList} \alias{SimpleFactorList-class} \alias{SimpleFactorList} % coercion \alias{as.list,CompressedAtomicList-method} \alias{coerce,CompressedAtomicList,list-method} \alias{as.vector,AtomicList-method} \alias{coerce,vector,AtomicList-method} \alias{lapply,CompressedAtomicList-method} \alias{coerce,vector,CompressedLogicalList-method} \alias{coerce,vector,SimpleLogicalList-method} \alias{coerce,vector,CompressedIntegerList-method} \alias{coerce,vector,SimpleIntegerList-method} \alias{coerce,vector,CompressedNumericList-method} \alias{coerce,vector,SimpleNumericList-method} \alias{coerce,vector,CompressedComplexList-method} \alias{coerce,vector,SimpleComplexList-method} \alias{coerce,vector,CompressedCharacterList-method} \alias{coerce,vector,SimpleCharacterList-method} \alias{coerce,vector,CompressedRawList-method} \alias{coerce,vector,SimpleRawList-method} \alias{coerce,vector,CompressedRleList-method} \alias{coerce,vector,SimpleRleList-method} \alias{coerce,AtomicList,LogicalList-method} \alias{coerce,AtomicList,IntegerList-method} \alias{coerce,AtomicList,NumericList-method} \alias{coerce,AtomicList,ComplexList-method} \alias{coerce,AtomicList,CharacterList-method} \alias{coerce,AtomicList,RawList-method} \alias{coerce,AtomicList,RleList-method} \alias{RleList,AtomicList,RleList-method} \alias{coerce,CompressedRleList,CompressedIRangesList-method} \alias{unlist,SimpleFactorList} \alias{unlist,SimpleRleList} \alias{Ops,CompressedAtomicList,CompressedAtomicList-method} \alias{Ops,SimpleAtomicList,SimpleAtomicList-method} \alias{Ops,SimpleAtomicList,CompressedAtomicList-method} \alias{Ops,CompressedAtomicList,SimpleAtomicList-method} \alias{Ops,AtomicList,atomic-method} \alias{Ops,atomic,AtomicList-method} \alias{Ops,CompressedAtomicList,atomic-method} \alias{Ops,atomic,CompressedAtomicList-method} \alias{Ops,SimpleAtomicList,atomic-method} \alias{Ops,atomic,SimpleAtomicList-method} \alias{Math,CompressedAtomicList-method} \alias{Math,SimpleAtomicList-method} \alias{Math2,CompressedAtomicList-method} \alias{Math2,SimpleAtomicList-method} \alias{Summary,AtomicList-method} \alias{Summary,CompressedRleList-method} \alias{Complex,CompressedAtomicList-method} \alias{Complex,SimpleAtomicList-method} \alias{sum,CompressedIntegerList-method} \alias{sum,CompressedLogicalList-method} \alias{sum,CompressedNumericList-method} \alias{unique.RleList} \alias{unique,RleList-method} \alias{unique.CompressedList} \alias{unique,CompressedList-method} \alias{table,AtomicList-method} \alias{drop,AtomicList-method} \alias{duplicated.CompressedList} \alias{duplicated,CompressedList-method} \alias{duplicated.CompressedIntegerList} \alias{duplicated,CompressedIntegerList-method} \alias{sort,List-method} \alias{sort.List} \alias{order,List-method} \alias{rank,List-method} \alias{which,CompressedLogicalList-method} \alias{which,SimpleLogicalList-method} \alias{which,CompressedRleList-method} \alias{which,SimpleRleList-method} \alias{which.max,CompressedRleList-method} \alias{which.min,CompressedRleList-method} \alias{all,CompressedRleList-method} \alias{diff,IntegerList-method} \alias{diff,NumericList-method} \alias{diff,RleList-method} \alias{pmax,IntegerList-method} \alias{pmax,NumericList-method} \alias{pmax,RleList-method} \alias{pmin,IntegerList-method} \alias{pmin,NumericList-method} \alias{pmin,RleList-method} \alias{pmax.int,IntegerList-method} \alias{pmax.int,NumericList-method} \alias{pmax.int,RleList-method} \alias{pmin.int,IntegerList-method} \alias{pmin.int,NumericList-method} \alias{pmin.int,RleList-method} \alias{mean,AtomicList-method} \alias{var,AtomicList,missing-method} \alias{var,AtomicList,AtomicList-method} \alias{cov,AtomicList,AtomicList-method} \alias{cor,AtomicList,AtomicList-method} \alias{sd,AtomicList-method} \alias{median,AtomicList-method} \alias{quantile,AtomicList-method} \alias{mad,AtomicList-method} \alias{IQR,AtomicList-method} \alias{cumsum,CompressedAtomicList-method} \alias{cumprod,CompressedAtomicList-method} \alias{cummin,CompressedAtomicList-method} \alias{cummax,CompressedAtomicList-method} \alias{smoothEnds,CompressedIntegerList-method} \alias{smoothEnds,SimpleIntegerList-method} \alias{smoothEnds,NumericList-method} \alias{smoothEnds,RleList-method} \alias{runmed,CompressedIntegerList-method} \alias{runmed,SimpleIntegerList-method} \alias{runmed,NumericList-method} \alias{runmed,RleList-method} \alias{runmean,RleList-method} \alias{runsum,RleList-method} \alias{runwtsum,RleList-method} \alias{runq,RleList-method} \alias{nchar,CompressedCharacterList-method} \alias{nchar,SimpleCharacterList-method} \alias{nchar,CompressedRleList-method} \alias{nchar,SimpleRleList-method} \alias{chartr,ANY,ANY,CompressedCharacterList-method} \alias{chartr,ANY,ANY,SimpleCharacterList-method} \alias{chartr,ANY,ANY,CompressedRleList-method} \alias{chartr,ANY,ANY,SimpleRleList-method} \alias{tolower,CompressedCharacterList-method} \alias{tolower,SimpleCharacterList-method} \alias{tolower,CompressedRleList-method} \alias{tolower,SimpleRleList-method} \alias{toupper,CompressedCharacterList-method} \alias{toupper,SimpleCharacterList-method} \alias{toupper,CompressedRleList-method} \alias{toupper,SimpleRleList-method} \alias{sub,ANY,ANY,CompressedCharacterList-method} \alias{sub,ANY,ANY,SimpleCharacterList-method} \alias{sub,ANY,ANY,CompressedRleList-method} \alias{sub,ANY,ANY,SimpleRleList-method} \alias{gsub,ANY,ANY,CompressedCharacterList-method} \alias{gsub,ANY,ANY,SimpleCharacterList-method} \alias{gsub,ANY,ANY,CompressedRleList-method} \alias{gsub,ANY,ANY,SimpleRleList-method} \alias{unstrsplit,CharacterList-method} \alias{runLength,RleList-method} \alias{runValue,RleList-method} \alias{runLength,CompressedRleList-method} \alias{runValue,CompressedRleList-method} \alias{runValue<-,CompressedRleList-method} \alias{runValue<-,SimpleRleList-method} \alias{ranges,RleList-method} \alias{ranges,CompressedRleList-method} \alias{show,AtomicList-method} \alias{show,RleList-method} \alias{showAsCell,AtomicList-method} \title{Lists of Atomic Vectors in Natural and Rle Form} \description{An extension of \code{\linkS4class{List}} that holds only atomic vectors in either a natural or run-length encoded form.} \details{ The lists of atomic vectors are \code{LogicalList}, \code{IntegerList}, \code{NumericList}, \code{ComplexList}, \code{CharacterList}, and \code{RawList}. There is also an \code{RleList} class for run-length encoded versions of these atomic vector types. Each of the above mentioned classes is virtual with Compressed* and Simple* non-virtual representations. } \section{Constructors}{ \describe{ \item{}{\code{LogicalList(..., compress = TRUE)}: Concatenates the \code{logical} vectors in \code{...} into a new \code{LogicalList}. If \code{compress}, the internal storage of the data is compressed.} \item{}{\code{IntegerList(..., compress = TRUE)}: Concatenates the \code{integer} vectors in \code{...} into a new \code{IntegerList}. If \code{compress}, the internal storage of the data is compressed.} \item{}{\code{NumericList(..., compress = TRUE)}: Concatenates the \code{numeric} vectors in \code{...} into a new \code{NumericList}. If \code{compress}, the internal storage of the data is compressed.} \item{}{\code{ComplexList(..., compress = TRUE)}: Concatenates the \code{complex} vectors in \code{...} into a new \code{ComplexList}. If \code{compress}, the internal storage of the data is compressed.} \item{}{\code{CharacterList(..., compress = TRUE)}: Concatenates the \code{character} vectors in \code{...} into a new \code{CharacterList}. If \code{compress}, the internal storage of the data is compressed.} \item{}{\code{RawList(..., compress = TRUE)}: Concatenates the \code{raw} vectors in \code{...} into a new \code{RawList}. If \code{compress}, the internal storage of the data is compressed.} \item{}{\code{RleList(..., compress = TRUE)}: Concatenates the run-length encoded atomic vectors in \code{...} into a new \code{RleList}. If \code{compress}, the internal storage of the data is compressed.} \item{}{\code{FactorList(..., compress = TRUE)}: Concatenates the \code{factor} objects in \code{...} into a new \code{FactorList}. If \code{compress}, the internal storage of the data is compressed.} } } \section{Coercion}{ \describe{ \item{}{ \code{as(from, "CompressedSplitDataFrameList")}, \code{as(from, "SimpleSplitDataFrameList")}: Creates a \linkS4class{CompressedSplitDataFrameList}/\linkS4class{SimpleSplitDataFrameList} instance from an AtomicList instance. } \item{}{ \code{as(from, "IRangesList")}, \code{as(from, "CompressedIRangesList")}, \code{as(from, "SimpleIRangesList")}: Creates a \linkS4class{CompressedIRangesList}/\linkS4class{SimpleIRangesList} instance from a LogicalList or logical RleList instance. Note that the elements of this instance are guaranteed to be normal. } \item{}{ \code{as(from, "NormalIRangesList")}, \code{as(from, "CompressedNormalIRangesList")}, \code{as(from, "SimpleNormalIRangesList")}: Creates a \linkS4class{CompressedNormalIRangesList}/\linkS4class{SimpleNormalIRangesList} instance from a LogicalList or logical RleList instance. } \item{}{\code{as(from, "CharacterList")}, \code{as(from, "ComplexList")}, \code{as(from, "IntegerList")}, \code{as(from, "LogicalList")}, \code{as(from, "NumericList")}, \code{as(from, "RawList")}, \code{as(from, "RleList")}: Coerces an \code{AtomicList} \code{from} to another derivative of \code{AtomicList}. } \item{}{\code{as(from, "AtomicList")}: If \code{from} is a vector, converts it to an \code{AtomicList} of the appropriate type. } } } \section{Group Generics}{ AtomicList objects have support for S4 group generic functionality to operate within elements across objects: \describe{ \item{\code{Arith}}{\code{"+"}, \code{"-"}, \code{"*"}, \code{"^"}, \code{"\%\%"}, \code{"\%/\%"}, \code{"/"}} \item{\code{Compare}}{\code{"=="}, \code{">"}, \code{"<"}, \code{"!="}, \code{"<="}, \code{">="}} \item{\code{Logic}}{\code{"&"}, \code{"|"}} \item{\code{Ops}}{\code{"Arith"}, \code{"Compare"}, \code{"Logic"}} \item{\code{Math}}{\code{"abs"}, \code{"sign"}, \code{"sqrt"}, \code{"ceiling"}, \code{"floor"}, \code{"trunc"}, \code{"cummax"}, \code{"cummin"}, \code{"cumprod"}, \code{"cumsum"}, \code{"log"}, \code{"log10"}, \code{"log2"}, \code{"log1p"}, \code{"acos"}, \code{"acosh"}, \code{"asin"}, \code{"asinh"}, \code{"atan"}, \code{"atanh"}, \code{"exp"}, \code{"expm1"}, \code{"cos"}, \code{"cosh"}, \code{"sin"}, \code{"sinh"}, \code{"tan"}, \code{"tanh"}, \code{"gamma"}, \code{"lgamma"}, \code{"digamma"}, \code{"trigamma"}} \item{\code{Math2}}{\code{"round"}, \code{"signif"}} \item{\code{Summary}}{\code{"max"}, \code{"min"}, \code{"range"}, \code{"prod"}, \code{"sum"}, \code{"any"}, \code{"all"}} \item{\code{Complex}}{\code{"Arg"}, \code{"Conj"}, \code{"Im"}, \code{"Mod"}, \code{"Re"}} } See \link[methods]{S4groupGeneric} for more details. } \section{Other Basic Methods}{ The AtomicList objects also support a large number of basic methods. Like the group generics above, these methods perform the corresponding operation on each element of the list separately. The methods are: \describe{ \item{General}{\code{is.na}, \code{duplicated}, \code{unique}, \code{match}, \code{\%in\%}, \code{table}, \code{order}, \code{sort}} \item{Logical}{\code{!}, \code{which}, \code{which.max}, \code{which.min}} \item{Numeric}{\code{diff}, \code{pmax}, \code{pmax.int}, \code{pmin}, \code{pmin.int}, \code{mean}, \code{var}, \code{cov}, \code{cor}, \code{sd}, \code{median}, \code{quantile}, \code{mad}, \code{IQR}} \item{Running Window}{\code{smoothEnds}, \code{runmed}. \code{runmean}, \code{runsum}, \code{runwtsum}, \code{runq}} \item{Character}{\code{nchar}, \code{chartr}, \code{tolower}, \code{toupper}, \code{sub}, \code{gsub}} } } \section{RleList Methods}{ RleList has a number of methods that are not shared by other AtomicList derivatives. \describe{ \item{}{\code{runLength(x)}: Gets the run lengths of each element of the list, as an IntegerList. } \item{}{\code{runValue(x)}, \code{runValue(x) <- value}: Gets or sets the run values of each element of the list, as an AtomicList. } \item{}{\code{ranges(x)}: Gets the run ranges as a \code{RangesList}. } } } \section{Specialized Methods}{ \describe{ \item{}{\code{drop(x)}: Checks if every element of \code{x} is of length one, and, if so, unlists \code{x}. Otherwise, an error is thrown. } \item{}{\code{unstrsplit(x, sep="")}}: A fast \code{sapply(x, paste0, collapse=sep)}. See \code{?\link{unstrsplit}} for the details. } } \author{P. Aboyoun} \seealso{\code{\linkS4class{List}} for the applicable methods.} \examples{ int1 <- c(1L,2L,3L,5L,2L,8L) int2 <- c(15L,45L,20L,1L,15L,100L,80L,5L) collection <- IntegerList(int1, int2) ## names names(collection) <- c("one", "two") names(collection) names(collection) <- NULL # clear names names(collection) names(collection) <- "one" names(collection) # c("one", NA) ## extraction collection[[1]] # range1 collection[["1"]] # NULL, does not exist collection[["one"]] # range1 collection[[NA_integer_]] # NULL ## subsetting collection[numeric()] # empty collection[NULL] # empty collection[] # identity collection[c(TRUE, FALSE)] # first element collection[2] # second element collection[c(2,1)] # reversed collection[-1] # drop first collection$one ## replacement collection$one <- int2 collection[[2]] <- int1 ## combining col1 <- IntegerList(one = int1, int2) col2 <- IntegerList(two = int2, one = int1) col3 <- IntegerList(int2) append(col1, col2) append(col1, col2, 0) col123 <- c(col1, col2, col3) col123 ## revElements revElements(col123) revElements(col123, 4:5) ## group generics 2 * col1 col1 + col1 col1 > 2 sum(col1) # equivalent to (but faster than) 'sapply(col1, sum)' mean(col1) # equivalent to 'sapply(col1, mean)' } \keyword{methods} \keyword{classes} IRanges/man/CompressedList-class.Rd0000644000175100017510000001234712607265143020244 0ustar00biocbuildbiocbuild\name{CompressedList-class} \docType{class} \alias{class:CompressedList} \alias{CompressedList} \alias{CompressedList-class} % accessors \alias{length,CompressedList-method} \alias{names,CompressedList-method} \alias{names<-,CompressedList-method} \alias{elementLengths,CompressedList-method} \alias{$<-,CompressedList-method} \alias{[[<-,CompressedList-method} % coercion \alias{unlist,CompressedList-method} \alias{coerce,ANY,CompressedList-method} % combining \alias{c,CompressedList-method} % looping \alias{lapply,CompressedList-method} \alias{endoapply,CompressedList-method} \alias{mendoapply,CompressedList-method} \alias{revElements,CompressedList-method} % displaying \alias{classNameForDisplay,CompressedList-method} % ops \alias{!,CompressedList-method} \title{CompressedList objects} \description{ Like the \link[S4Vectors]{SimpleList} class defined in the \pkg{S4Vectors} package, the CompressedList class extends the \link[S4Vectors]{List} virtual class. } \details{ Unlike the \link[S4Vectors]{SimpleList} class, CompressedList is virtual, that is, it cannot be instantiated. Many concrete (i.e. non-virtual) CompressedList subclasses are defined and documented in this package (e.g. \link{CompressedIntegerList}, \link{CompressedCharacterList}, \link{CompressedRleList}, etc...), as well as in other packages (e.g. \link[GenomicRanges]{GRangesList} in the \pkg{GenomicRanges} package, \link[GenomicAlignments]{GAlignmentsList} in the \pkg{GenomicAlignments} package, etc...). It's easy for developers to extend CompressedList to create a new CompressedList subclass and there is generally very little work involved to make this new subclass fully operational. In a CompressedList object the list elements are concatenated together in a single vector-like object. The \emph{partitioning} of this single vector-like object (i.e. the information about where each original list element starts and ends) is also kept in the CompressedList object. This internal representation is generally more memory efficient than \link[S4Vectors]{SimpleList}, especially if the object has many list elements (e.g. thousands or millions). Also it makes it possible to implement many basic list operations very efficiently. Many objects like \link{LogicalList}, \link{IntegerList}, \link{CharacterList}, \link{RleList}, etc... exist in 2 flavors: CompressedList and \link[S4Vectors]{SimpleList}. Each flavor is incarnated by a concrete subclass: \link{CompressedLogicalList} and \link{SimpleLogicalList} for virtual class \link{LogicalList}, \link{CompressedIntegerList} and \link{SimpleIntegerList} for virtual class \link{IntegerList}, etc... It's easy to switch from one representation to the other with \code{as(x, "CompressedList")} and \code{as(x, "SimpleList")}. Also the constructor function for those virtual classes have a switch that lets the user choose the representation at construction time e.g. \code{CharacterList(..., compress=TRUE)} or \code{CharacterList(..., compress=FALSE)}. See below for more information. } \section{Constructor}{ See the \link[S4Vectors]{List} man page in the \pkg{S4Vectors} package for a quick overview of how to construct \link{List} objects in general. Unlike for \link[S4Vectors]{SimpleList} objects, there is no \code{CompressedList} constructor function. However, many constructor functions for \link[S4Vectors]{List} objects have a switch that lets the user choose between the CompressedList and \link[S4Vectors]{SimpleList} representation at construction time. For example, a \link{CompressedCharacterList} object can be constructed with \code{CharacterList(..., compress=TRUE)}. } \section{Accessors}{ Same as for \link[S4Vectors]{List} objects. See the \link[S4Vectors]{List} man page in the \pkg{S4Vectors} package for more information. } \section{Coercion}{ All the coercions documented in the \link[S4Vectors]{List} man page apply to CompressedList objects. } \section{Subsetting}{ Same as for \link[S4Vectors]{List} objects. See the \link[S4Vectors]{List} man page for more information. } \section{Looping and functional programming}{ Same as for \link[S4Vectors]{List} objects. See \code{?`\link[S4Vectors]{List-utils}`} in the \pkg{S4Vectors} package for more information. } \section{Displaying}{ When a CompressedList object is displayed, the "Compressed" prefix is removed from the real class name of the object. See \code{\link[S4Vectors]{classNameForDisplay}} in the \pkg{S4Vectors} package for more information about this. } \seealso{ \itemize{ \item The \link[S4Vectors]{List} class defined and documented in the \pkg{S4Vectors} package for the parent class. \item The \link[S4Vectors]{SimpleList} class defined and documented in the \pkg{S4Vectors} package for an alternative to CompressedList. \item The \link{CompressedIntegerList} class for a CompressedList subclass example. } } \examples{ ## Displaying a CompressedList object: x <- IntegerList(11:12, integer(0), 3:-2, compress=TRUE) class(x) ## The "Simple" prefix is removed from the real class name of the ## object: x ## This is controlled by internal helper classNameForDisplay(): classNameForDisplay(x) } \keyword{methods} \keyword{classes} IRanges/man/DataFrame-utils.Rd0000644000175100017510000000220712607265143017155 0ustar00biocbuildbiocbuild\name{DataFrame-utils} \alias{DataFrame-utils} % splitting \alias{mstack,DataFrame-method} \title{Common operations on DataFrame objects} \description{ Common operations on \link{DataFrame} objects. } \section{Splitting}{ In the following code snippets, \code{x} is a \code{DataFrame}. \describe{ \item{}{\code{split(x, f, drop = FALSE)}: Splits \code{x} into a \code{\linkS4class{CompressedSplitDataFrameList}}, according to \code{f}, dropping elements corresponding to unrepresented levels if \code{drop} is \code{TRUE}. } \item{}{ \code{mstack(..., .index.var = "name")}: Stacks the data frames passed as through \dots, using \code{.index.var} as the index column name. See \code{\link{stack}}. } } } \author{ Michael Lawrence } \seealso{ \code{\linkS4class{DataTable}}, \code{\linkS4class{Vector}}, and \code{\linkS4class{RangedData}}, which makes heavy use of this class. } \examples{ ## split sw <- DataFrame(swiss) swsplit <- split(sw, sw[["Education"]]) ## rbind do.call(rbind, as.list(swsplit)) ## cbind cbind(DataFrame(score), DataFrame(counts)) } \keyword{methods} IRanges/man/DataFrameList-class.Rd0000644000175100017510000001701512607265143017761 0ustar00biocbuildbiocbuild\name{DataFrameList-class} \docType{class} \alias{DataFrameList-class} \alias{SimpleDataFrameList-class} \alias{SplitDataFrameList-class} \alias{CompressedSplitDataFrameList-class} \alias{SimpleSplitDataFrameList-class} % accessors \alias{nrow,DataFrameList-method} \alias{ncol,DataFrameList-method} \alias{ncol,CompressedSplitDataFrameList-method} \alias{ncol,SimpleSplitDataFrameList-method} \alias{dim,DataFrameList-method} \alias{rownames,DataFrameList-method} \alias{colnames,DataFrameList-method} \alias{colnames,CompressedSplitDataFrameList-method} \alias{colnames,SimpleSplitDataFrameList-method} \alias{dimnames,DataFrameList-method} \alias{rownames<-,CompressedSplitDataFrameList-method} \alias{rownames<-,SimpleDataFrameList-method} \alias{colnames<-,CompressedSplitDataFrameList-method} \alias{colnames<-,SimpleDataFrameList-method} \alias{dimnames<-,DataFrameList-method} \alias{columnMetadata} \alias{columnMetadata<-} \alias{columnMetadata,SimpleSplitDataFrameList-method} \alias{columnMetadata<-,SimpleSplitDataFrameList-method} \alias{columnMetadata,CompressedSplitDataFrameList-method} \alias{columnMetadata<-,CompressedSplitDataFrameList-method} % constructor \alias{DataFrameList} \alias{SplitDataFrameList} % subsetting \alias{[,SimpleSplitDataFrameList-method} \alias{[,CompressedSplitDataFrameList-method} \alias{[<-,SplitDataFrameList-method} % transformation \alias{transform,SplitDataFrameList-method} % coercion \alias{coerce,DataFrameList,DataFrame-method} \alias{coerce,SplitDataFrameList,DataFrame-method} \alias{coerce,ANY,CompressedSplitDataFrameList-method} \alias{coerce,ANY,SimpleSplitDataFrameList-method} \alias{coerce,List,CompressedSplitDataFrameList-method} \alias{coerce,list,SplitDataFrameList-method} \alias{coerce,List,SimpleSplitDataFrameList-method} \alias{coerce,ANY,SplitDataFrameList-method} \alias{coerce,SimpleList,SplitDataFrameList-method} \alias{coerce,list,SplitDataFrameList-method} \alias{coerce,DataFrame,SplitDataFrameList-method} \alias{stack,DataFrameList-method} % splitting and combining \alias{cbind,DataFrameList-method} \alias{rbind,DataFrameList-method} % show \alias{show,SplitDataFrameList-method} % SDFLWrapperForTransform (internal) \alias{[[,SDFLWrapperForTransform-method} \alias{[[<-,SDFLWrapperForTransform-method} \alias{as.env,SDFLWrapperForTransform-method} \title{List of DataFrames} \description{Represents a list of \code{\linkS4class{DataFrame}} objects. The \code{SplitDataFrameList} class contains the additional restriction that all the columns be of the same name and type. Internally it is stored as a list of \code{DataFrame} objects and extends \code{\linkS4class{List}}.} \section{Accessors}{ In the following code snippets, \code{x} is a \code{DataFrameList}. \describe{ \item{}{\code{dim(x)}: Get the two element integer vector indicating the number of rows and columns over the entire dataset.} \item{}{\code{dimnames(x)}: Get the list of two character vectors, the first holding the rownames (possibly \code{NULL}) and the second the column names. } \item{}{\code{columnMetadata(x)}: Get the \code{DataFrame} of metadata along the columns, i.e., where each column in \code{x} is represented by a row in the metadata. The metadata is common across all elements of \code{x}. Note that calling \code{mcols(x)} returns the metadata on the \code{DataFrame} elements of \code{x}. } \item{}{\code{columnMetadata(x) <- value}: Set the \code{DataFrame} of metadata for the columns. } } } \section{Subsetting}{ In the following code snippets, \code{x} is a \code{SplitDataFrameList}. In general \code{x} follows the conventions of \code{SimpleList}/\code{CompressedList} with the following addition: \describe{ \item{}{ \code{x[i,j,drop]}: If matrix subsetting is used, \code{i} selects either the list elements or the rows within the list elements as determined by the \code{[} method for \code{SimpleList}/\code{CompressedList}, \code{j} selects the columns, and \code{drop} is used when one column is selected and output can be coerced into an \code{AtomicList} or \code{RangesList} subclass. } \item{}{\code{x[i,j] <- value}: If matrix subsetting is used, \code{i} selects either the list elements or the rows within the list elements as determined by the \code{[<-} method for \code{SimpleList}/\code{CompressedList}, \code{j} selects the columns and \code{value} is the replacement value for the selected region. } } } \section{Constructor}{ \describe{ \item{}{\code{DataFrameList(...)}: Concatenates the \code{DataFrame} objects in \code{...} into a new \code{DataFrameList}.} \item{}{\code{SplitDataFrameList(..., compress = TRUE, cbindArgs = FALSE)}: If \code{cbindArgs} is \code{FALSE}, the \code{...} arguments are coerced to \code{DataFrame} objects and concatenated to form the result. The arguments must have the same number and names of columns. If \code{cbindArgs} is \code{TRUE}, the arguments are combined as columns. The arguments must then be the same length, with each element of an argument mapping to an element in the result. If \code{compress = TRUE}, returns a \code{CompressedSplitDataFrameList}; else returns a \code{SimpleSplitDataFrameList}.} } } \section{Combining}{ In the following code snippets, objects in \code{...} are of class \code{DataFrameList}. \describe{ \item{}{ \code{rbind(...)}: Creates a new \code{DataFrameList} containing the element-by-element row concatenation of the objects in \code{...}. } \item{}{ \code{cbind(...)}: Creates a new \code{DataFrameList} containing the element-by-element column concatenation of the objects in \code{...}. } } } \section{Transformation}{ \describe{ \item{}{\code{transform(`_data`, ...)}: Transforms a \code{SplitDataFrame} in a manner analogous to the base \code{\link{transform}}, where the columns are \code{List} objects adhering to the structure of \code{_data}. } } } \section{Coercion}{ In the following code snippets, \code{x} is a \code{DataFrameList}. \describe{ \item{}{\code{as(from, "DataFrame")}: Coerces a \code{SplitDataFrameList} to a \code{DataFrame}, which has a column for every column in \code{from}, except each column is a \code{List} with the same structure as \code{from}. } \item{}{\code{as(from, "SplitDataFrameList")}: By default, simply calls the \code{SplitDataFrameList} constructor on \code{from}. If \code{from} is a \code{List}, each element of \code{from} is passed as an argument to \code{SplitDataFrameList}, like calling \code{as.list} on a vector. If \code{from} is a \code{DataFrame}, each row becomes an element in the list.} \item{}{\code{stack(x, index.var = "name")}: Unlists \code{x} and adds a column named \code{index.var} to the result, indicating the element of \code{x} from which each row was obtained. } \item{}{ \code{as.data.frame(x, row.names = NULL, optional = FALSE, ..., value.name = "value", use.outer.mcols = FALSE, group_name.as.factor = FALSE)}: Coerces \code{x} to a \code{data.frame}. See as.data.frame on the \code{List} man page for details (?\code{List}). } } } \author{ Michael Lawrence } \seealso{ \code{\linkS4class{DataFrame}}, \code{\linkS4class{RangedData}}, which uses a \code{DataFrameList} to split the data by the spaces. } \keyword{methods} \keyword{classes} IRanges/man/GappedRanges-class.Rd0000644000175100017510000001311712607265143017640 0ustar00biocbuildbiocbuild\name{GappedRanges-class} \docType{class} % Classes: \alias{class:GappedRanges} \alias{GappedRanges-class} \alias{GappedRanges} % Generics and methods: \alias{length,GappedRanges-method} \alias{start,GappedRanges-method} \alias{end,GappedRanges-method} \alias{ngap} \alias{ngap,GappedRanges-method} \alias{names,GappedRanges-method} \alias{names<-,GappedRanges-method} \alias{coerce,CompressedNormalIRangesList,GappedRanges-method} \alias{coerce,CompressedIRangesList,GappedRanges-method} \alias{coerce,GappedRanges,CompressedNormalIRangesList-method} \alias{coerce,GappedRanges,NormalIRangesList-method} \alias{coerce,GappedRanges,CompressedIRangesList-method} \alias{coerce,GappedRanges,IRangesList-method} \alias{coerce,GappedRanges,RangesList-method} \alias{as.data.frame.GappedRanges} \alias{as.data.frame,GappedRanges-method} \alias{show,GappedRanges-method} \alias{elementLengths,GappedRanges-method} \alias{c,GappedRanges-method} \title{GappedRanges objects} \description{ The GappedRanges class is a vector-like container for storing a set of "gapped ranges". } \details{ A "gapped range" is conceptually the union of 1 or more non-overlapping (and non-empty) ranges ordered from left to right. More precisely, a "gapped range" can be represented by a normal IRanges object of length >= 1. In particular normality here ensures that the individual ranges are non-empty and are separated by non-empty gaps. The start of a "gapped range" is the start of its first range. The end of a "gapped range" is the end of its last range. If we ignore the gaps, then a GappedRanges object can be seen as a \link{Ranges} object. } \section{Constructor}{ No constructor function is provided for GappedRanges objects. The coercion methods described below can be used to create GappedRanges objects. } \section{Coercion}{ \describe{ \item{}{ \code{as(from, "GappedRanges")}: Turns a \link{CompressedNormalIRangesList} or \link{CompressedIRangesList} object into a GappedRanges object. } \item{}{ \code{as(from, "RangesList")}: Turns a GappedRanges object into a \link{RangesList} object (more precisely the result will be a \link{CompressedNormalIRangesList} object). } } } \section{Accessor methods}{ In the code snippets below, \code{x} is a GappedRanges object. \describe{ \item{}{ \code{length(x)}: Returns the number of "gapped ranges" in \code{x}. } \item{}{ \code{start(x), end(x)}: Returns an integer vector of length \code{length(x)} containing the start and end (respectively) of each "gapped range" in \code{x}. See Details section above for the exact definitions of the start and end of a "gapped range". } \item{}{ \code{width(x)}: Defined as \code{end(x) - start(x) + 1L}. } \item{}{ \code{ngap(x)}: Returns an integer vector of length \code{length(x)} containing the number of gaps for each "gapped range" in \code{x}. Equivalent to \code{elementLengths(x) - 1L}. } \item{}{ \code{names(x)}: \code{NULL} or a character vector of length \code{length(x)}. } } } \section{Subsetting and related operations}{ In the code snippets below, \code{x} is a GappedRanges object. \describe{ \item{}{ \code{x[i]}: Returns a new GappedRanges object made of the selected "gapped ranges". \code{i} can be a numeric, character or logical vector, or any of the types supported by the \code{[} method for \link{CompressedNormalIRangesList} objects. } \item{}{ \code{x[[i]]}: Returns the \link{NormalIRanges} object representing the i-th element in \code{x}. Equivalent to \code{as(from, "RangesList")[[i]]}. \code{i} can be a single numeric value or a single character string. } \item{}{ \code{elemenType(x)}: Returns the type of \code{x[[i]]} as a single string (always \code{"NormalIRanges"}). Note that the semantic of the \code{[[} method for GappedRanges objects is different from the semantic of the method for \link{Ranges} objects (the latter returns an integer vector). } \item{}{ \code{elementLengths(x)}: Semantically equivalent to \preformatted{sapply(seq_len(length(x)), function(i) length(x[[i]]))} but much faster. Note that the semantic of the \code{elementLengths} method for GappedRanges objects is different from the semantic of the method for \link{Ranges} objects (the latter returns the \code{width} of the \link{Ranges} object). } } } \section{Combining and related operations}{ In the code snippets below, \code{x} is a GappedRanges object. \describe{ \item{}{ \code{c(x, ...)}: Combine \code{x} and the GappedRanges objects in \code{...} together. The result is an object of the same class as \code{x}. } } } \author{H. Pages} \seealso{ \link{Ranges-class}, \link{CompressedNormalIRangesList-class} } \examples{ ## The 3 following IRanges objects are normal. Each of them will be ## stored as a "gapped range" in the GappedRanges object 'gr'. ir1 <- IRanges(start=c(11, 21, 23), end=c(15, 21, 30)) ir2 <- IRanges(start=-2, end=15) ir3 <- IRanges(start=c(-2, 21), end=c(10, 22)) irl <- IRangesList(ir1, ir2, ir3) gr <- as(irl, "GappedRanges") gr length(gr) start(gr) end(gr) width(gr) ngap(gr) gr[-1] gr[ngap(gr) >= 1] gr[[1]] as.integer(gr[[1]]) gr[[2]] as.integer(gr[[2]]) as(gr, "RangesList") start(as(gr, "RangesList")) # not the same as 'start(gr)' } \keyword{methods} \keyword{classes} IRanges/man/Grouping-class.Rd0000644000175100017510000003663712607265143017106 0ustar00biocbuildbiocbuild\name{Grouping-class} \docType{class} % Grouping objects: \alias{class:Grouping} \alias{Grouping-class} \alias{Grouping} \alias{nobj} \alias{grouplength} \alias{grouplength,Grouping-method} \alias{show,Grouping-method} % ManyToOneGrouping objects: \alias{class:ManyToOneGrouping} \alias{ManyToOneGrouping-class} \alias{ManyToOneGrouping} \alias{members} \alias{members,ManyToOneGrouping-method} \alias{vmembers} \alias{vmembers,ManyToOneGrouping-method} \alias{togroup} \alias{togroup,ANY-method} \alias{togrouplength} \alias{togrouplength,ManyToOneGrouping-method} % H2LGrouping and Dups objects: \alias{class:H2LGrouping} \alias{H2LGrouping-class} \alias{H2LGrouping} \alias{high2low} \alias{high2low,H2LGrouping-method} \alias{high2low,vector-method} \alias{high2low,Vector-method} \alias{low2high} \alias{low2high,H2LGrouping-method} \alias{length,H2LGrouping-method} \alias{nobj,H2LGrouping-method} \alias{grouplength,H2LGrouping-method} \alias{members,H2LGrouping-method} \alias{vmembers,H2LGrouping-method} \alias{togroup,H2LGrouping-method} \alias{grouprank} \alias{grouprank,H2LGrouping-method} \alias{togrouprank} \alias{togrouprank,H2LGrouping-method} \alias{length<-,H2LGrouping-method} \alias{class:Dups} \alias{Dups-class} \alias{Dups} \alias{duplicated,Dups-method} \alias{duplicated.Dups} \alias{show,Dups-method} % Partitioning objects: \alias{class:Partitioning} \alias{Partitioning-class} \alias{Partitioning} \alias{grouplength,Partitioning-method} \alias{names,Partitioning-method} \alias{names<-,Partitioning-method} \alias{class:PartitioningByEnd} \alias{PartitioningByEnd-class} \alias{PartitioningByEnd} \alias{end,PartitioningByEnd-method} \alias{length,PartitioningByEnd-method} \alias{nobj,PartitioningByEnd-method} \alias{start,PartitioningByEnd-method} \alias{width,PartitioningByEnd-method} \alias{coerce,Ranges,PartitioningByEnd-method} \alias{class:PartitioningByWidth} \alias{PartitioningByWidth-class} \alias{PartitioningByWidth} \alias{width,PartitioningByWidth-method} \alias{length,PartitioningByWidth-method} \alias{end,PartitioningByWidth-method} \alias{nobj,PartitioningByWidth-method} \alias{start,PartitioningByWidth-method} \alias{coerce,Ranges,PartitioningByWidth-method} \alias{class:PartitioningMap} \alias{PartitioningMap-class} \alias{PartitioningMap} \alias{mapOrder} \alias{mapOrder,PartitioningMap-method} \alias{show,PartitioningMap-method} \title{Grouping objects} \description{ We call \emph{grouping} an arbitrary mapping from a collection of NO objects to a collection of NG groups, or, more formally, a bipartite graph between integer sets [1, NO] and [1, NG]. Objects mapped to a given group are said to belong to, or to be assigned to, or to be in that group. Additionally, the objects in each group are ordered. So for example the 2 following groupings are considered different: \preformatted{ Grouping 1: NG = 3, NO = 5 group objects 1 : 4, 2 2 : 3 : 4 Grouping 2: NG = 3, NO = 5 group objects 1 : 2, 4 2 : 3 : 4 } There are no restriction on the mapping e.g. any object can be mapped to 0, 1, or more groups, and can be mapped twice to the same group. Also some or all the groups can be empty. The Grouping class is a virtual class that formalizes the most general kind of grouping. More specific groupings (e.g. many-to-one mappings) are formalized via specific Grouping subclasses. This man page documents the core Grouping API, and 2 important Grouping subclasses: ManyToOneGrouping and Partitioning (the latter being a particular case of the former). } \section{The core Grouping API}{ Let's give a formal description of the core Grouping API: Groups G_i are indexed from 1 to NG (1 <= i <= NG). Objects O_j are indexed from 1 to NO (1 <= j <= NO). Given that empty groups are allowed, NG can be greater than NO. If \code{x} is a Grouping object: \describe{ \item{}{ \code{length(x)}: Returns the number of groups (NG). } \item{}{ \code{names(x)}: Returns the names of the groups. } \item{}{ \code{nobj(x)}: Returns the number of objects (NO). } } Going from groups to objects: \describe{ \item{}{ \code{x[[i]]}: Returns the indices of the objects (the j's) that belong to G_i. This provides the mapping from groups to objects. } \item{}{ \code{grouplength(x, i=NULL)}: Returns the number of objects in G_i. Works in a vectorized fashion (unlike \code{x[[i]]}). \code{grouplength(x)} is equivalent to \code{grouplength(x, seq_len(length(x)))}. If \code{i} is not NULL, \code{grouplength(x, i)} is equivalent to \code{sapply(i, function(ii) length(x[[ii]]))}. } } Note to developers: Given that \code{length}, \code{names} and \code{[[} are expected to work on any Grouping object, those objects can be seen as \link{List} objects. More precisely, the Grouping class actually extends the \link{IntegerList} class. In particular, many other "list" operations like \code{as.list}, \code{elementLengths}, and \code{unlist}, etc... should work out-of-the-box on any Grouping object. } \section{ManyToOneGrouping objects}{ The ManyToOneGrouping class is a virtual class for representing groupings where every object belongs to one group and only one. The grouping of an empty collection of objects in an arbitrary number of groups is a valid ManyToOneGrouping object. Note that, for a ManyToOneGrouping object, if NG is 0 then NO must also be 0. The ManyToOneGrouping API extends the core Grouping API by adding a couple more operations for going from groups to objects: \describe{ \item{}{ \code{members(x, i)}: Equivalent to \code{x[[i]]} if \code{i} is a single integer. Otherwise, if \code{i} is an integer vector of arbitrary length, it's equivalent to \code{sort(unlist(sapply(i, function(ii) x[[ii]])))}. } \item{}{ \code{vmembers(x, L)}: A version of \code{members} that works in a vectorized fashion with respect to the \code{L} argument (\code{L} must be a list of integer vectors). Returns \code{lapply(L, function(i) members(x, i))}. } } And also by adding operations for going from objects to groups: \describe{ \item{}{ \code{togroup(x, j=NULL)}: Returns the index i of the group that O_j belongs to. This provides the mapping from objects to groups (many-to-one mapping). Works in a vectorized fashion. \code{togroup(x)} is equivalent to \code{togroup(x, seq_len(nobj(x)))}: both return the entire mapping in an integer vector of length NO. If \code{j} is not NULL, \code{togroup(x, j)} is equivalent to \code{y <- togroup(x); y[j]}. } \item{}{ \code{togrouplength(x, j=NULL)}: Returns the number of objects that belong to the same group as O_j (including O_j itself). Equivalent to \code{grouplength(x, togroup(x, j))}. } } One important property of any ManyToOneGrouping object \code{x} is that \code{unlist(as.list(x))} is always a permutation of \code{seq_len(nobj(x))}. This is a direct consequence of the fact that every object in the grouping belongs to one group and only one. } \section{2 ManyToOneGrouping concrete subclasses: H2LGrouping and Dups}{ [DOCUMENT ME] Constructors: \describe{ \item{}{ \code{H2LGrouping(high2low=integer())}: [DOCUMENT ME] } \item{}{ \code{Dups(high2low=integer())}: [DOCUMENT ME] } } } \section{Partitioning objects}{ The Partitioning class is a virtual subclass of ManyToOneGrouping for representing \emph{block-groupings} i.e. groupings where each group contains objects that are neighbors in the original collection of objects. More formally, a grouping \code{x} is a block-grouping iff \code{togroup(x)} is sorted in increasing order (not necessarily strictly increasing). A Partitioning object can also be seen (and manipulated) as a \link{Ranges} object where all the ranges are adjacent starting at 1 (i.e. it covers the 1:NO interval with no overlap between the ranges). Note that a Partitioning object is both: a particular type of ManyToOneGrouping object and a particular type of \link{Ranges} object. Therefore all the methods that are defined for ManyToOneGrouping and \link{Ranges} objects can also be used on a Partitioning object. See \code{?Ranges} for a description of the \link{Ranges} API. The Partitioning virtual class has 3 concrete subclasses: PartitioningByEnd (only stores the end of the groups, allowing fast mapping from groups to objects), and PartitioningByWidth (only stores the width of the groups), and PartitioningMap which contains PartitioningByEnd and two additional slots to re-order and re-list the object to a related mapping. Constructors: \describe{ \item{}{ \code{PartitioningByEnd(x=integer(), NG=NULL, names=NULL)}: \code{x} must be either a list-like object or a sorted integer vector. \code{NG} must be either \code{NULL} or a single integer. \code{names} must be either \code{NULL} or a character vector of length \code{NG} (if supplied) or \code{length(x)} (if \code{NG} is not supplied). Returns the following PartitioningByEnd object \code{y}: \itemize{ \item If \code{x} is a list-like object, then the returned object \code{y} has the same length as \code{x} and is such that \code{width(y)} is identical to \code{elementLengths(x)}. \item If \code{x} is an integer vector and \code{NG} is not supplied, then \code{x} must be sorted (checked) and contain non-NA non-negative values (NOT checked). The returned object \code{y} has the same length as \code{x} and is such that \code{end(y)} is identical to \code{x}. \item If \code{x} is an integer vector and \code{NG} is supplied, then \code{x} must be sorted (checked) and contain values >= 1 and <= \code{NG} (checked). The returned object \code{y} is of length \code{NG} and is such that \code{togroup(y)} is identical to \code{x}. } If the \code{names} argument is supplied, it is used to name the partitions. } \item{}{ \code{PartitioningByWidth(x=integer(), NG=NULL, names=NULL)}: \code{x} must be either a list-like object or an integer vector. \code{NG} must be either \code{NULL} or a single integer. \code{names} must be either \code{NULL} or a character vector of length \code{NG} (if supplied) or \code{length(x)} (if \code{NG} is not supplied). Returns the following PartitioningByWidth object \code{y}: \itemize{ \item If \code{x} is a list-like object, then the returned object \code{y} has the same length as \code{x} and is such that \code{width(y)} is identical to \code{elementLengths(x)}. \item If \code{x} is an integer vector and \code{NG} is not supplied, then \code{x} must contain non-NA non-negative values (NOT checked). The returned object \code{y} has the same length as \code{x} and is such that \code{width(y)} is identical to \code{x}. \item If \code{x} is an integer vector and \code{NG} is supplied, then \code{x} must be sorted (checked) and contain values >= 1 and <= \code{NG} (checked). The returned object \code{y} is of length \code{NG} and is such that \code{togroup(y)} is identical to \code{x}. } If the \code{names} argument is supplied, it is used to name the partitions. } \item{}{ \code{PartitioningMap(x=integer(), mapOrder=integer())}: \code{x} is a list-like object or a sorted integer vector used to construct a PartitioningByEnd object. \code{mapOrder} numeric vector of the mapped order. Returns a PartitioningMap object. } } Note that these constructors don't recycle their \code{names} argument (to remain consistent with what \code{`names<-`} does on standard vectors). } \author{H. Pages} \seealso{ \link{IntegerList-class}, \link{Ranges-class}, \link{IRanges-class}, \link{successiveIRanges}, \link[base]{cumsum}, \link[base]{diff} } \examples{ showClass("Grouping") # shows (some of) the known subclasses ## --------------------------------------------------------------------- ## A. H2LGrouping OBJECTS ## --------------------------------------------------------------------- high2low <- c(NA, NA, 2, 2, NA, NA, NA, 6, NA, 1, 2, NA, 6, NA, NA, 2) h2l <- H2LGrouping(high2low) h2l ## The core Grouping API: length(h2l) nobj(h2l) # same as 'length(h2l)' for H2LGrouping objects h2l[[1]] h2l[[2]] h2l[[3]] h2l[[4]] h2l[[5]] grouplength(h2l) # same as 'unname(sapply(h2l, length))' grouplength(h2l, 5:2) members(h2l, 5:2) # all the members are put together and sorted togroup(h2l) togroup(h2l, 5:2) togrouplength(h2l) # same as 'grouplength(h2l, togroup(h2l))' togrouplength(h2l, 5:2) ## The List API: as.list(h2l) sapply(h2l, length) ## --------------------------------------------------------------------- ## B. Dups OBJECTS ## --------------------------------------------------------------------- dups1 <- as(h2l, "Dups") dups1 duplicated(dups1) # same as 'duplicated(togroup(dups1))' ### The purpose of a Dups object is to describe the groups of duplicated ### elements in a vector-like object: x <- c(2, 77, 4, 4, 7, 2, 8, 8, 4, 99) x_high2low <- high2low(x) x_high2low # same length as 'x' dups2 <- Dups(x_high2low) dups2 togroup(dups2) duplicated(dups2) togrouplength(dups2) # frequency for each element table(x) ## --------------------------------------------------------------------- ## C. Partitioning OBJECTS ## --------------------------------------------------------------------- pbe1 <- PartitioningByEnd(c(4, 7, 7, 8, 15), names=LETTERS[1:5]) pbe1 # the 3rd partition is empty ## The core Grouping API: length(pbe1) nobj(pbe1) pbe1[[1]] pbe1[[2]] pbe1[[3]] grouplength(pbe1) # same as 'unname(sapply(pbe1, length))' and 'width(pbe1)' togroup(pbe1) togrouplength(pbe1) # same as 'grouplength(pbe1, togroup(pbe1))' names(pbe1) ## The Ranges core API: start(pbe1) end(pbe1) width(pbe1) ## The List API: as.list(pbe1) sapply(pbe1, length) ## Replacing the names: names(pbe1)[3] <- "empty partition" pbe1 ## Coercion to an IRanges object: as(pbe1, "IRanges") ## Other examples: PartitioningByEnd(c(0, 0, 19), names=LETTERS[1:3]) PartitioningByEnd() # no partition PartitioningByEnd(integer(9)) # all partitions are empty x <- c(1L, 5L, 5L, 6L, 8L) pbe2 <- PartitioningByEnd(x, NG=10L) stopifnot(identical(togroup(pbe2), x)) pbw2 <- PartitioningByWidth(x, NG=10L) stopifnot(identical(togroup(pbw2), x)) ## --------------------------------------------------------------------- ## D. RELATIONSHIP BETWEEN Partitioning OBJECTS AND successiveIRanges() ## --------------------------------------------------------------------- mywidths <- c(4, 3, 0, 1, 7) ## The 3 following calls produce the same ranges: ir <- successiveIRanges(mywidths) # IRanges instance. pbe <- PartitioningByEnd(cumsum(mywidths)) # PartitioningByEnd instance. pbw <- PartitioningByWidth(mywidths) # PartitioningByWidth instance. stopifnot(identical(as(ir, "PartitioningByEnd"), pbe)) stopifnot(identical(as(ir, "PartitioningByWidth"), pbw)) } \keyword{methods} \keyword{classes} IRanges/man/Hits-class-leftovers.Rd0000644000175100017510000000470312607265143020217 0ustar00biocbuildbiocbuild\name{Hits-class-leftovers} \docType{class} \alias{Hits-examples} % coercion \alias{as.data.frame.Hits} \alias{as.data.frame,Hits-method} \alias{as.list,Hits-method} \alias{as.list.Hits} \alias{coerce,Hits,list-method} \alias{coerce,Hits,List-method} \alias{coerce,Hits,DataFrame-method} \title{Examples of basic manipulation of Hits objects} \description{ IMPORTANT NOTE - 4/29/2014: This man page is being refactored. Most of the things that used to be documented here have been moved to the man page for \link[S4Vectors]{Hits} objects located in the \pkg{S4Vectors} package. } \details{ The \code{as.data.frame} method coerces a \code{Hits} object to a two column \code{data.frame} with one row for each hit, where the value in the first column is the index of an element in the query and the value in the second column is the index of an element in the subject. } \section{Coercion}{ In the code snippets below, \code{x} is a \code{Hits} object. \describe{ \item{}{ \code{as(from, "DataFrame")}: Creates a \code{DataFrame} by combining the result of \code{as.matrix(from)} with \code{mcols(from)}. } \item{}{\code{as.data.frame(x)}: Attempts to coerce the result of \code{as(from, "DataFrame")} to a \code{data.frame}. } \item{}{\code{as(x, "List")}: Like \code{as.list}, above. } } } \seealso{ The \link[S4Vectors]{Hits} class defined and documented in the \pkg{S4Vectors} package. } \examples{ query <- IRanges(c(1, 4, 9), c(5, 7, 10)) subject <- IRanges(c(2, 2, 10), c(2, 3, 12)) hits <- findOverlaps(query, subject) as.matrix(hits) as.data.frame(hits) as.table(hits) # hits per query as.table(t(hits)) # hits per subject ## Turn a Hits object into an IntegerList object with one list element ## per element in the original query. as(hits, "IntegerList") as(hits, "List") # same as as(hits, "IntegerList") ## Turn a Hits object into a PartitioningByEnd object that describes ## the grouping of hits by query. as(hits, "PartitioningByEnd") as(hits, "Partitioning") # same as as(hits, "PartitioningByEnd") ## --------------------------------------------------------------------- ## remapHits() ## --------------------------------------------------------------------- hits2 <- remapHits(hits, subject.map=factor(c("e", "e", "d"), letters[1:5])) hits2 hits3 <- remapHits(hits, subject.map=c(5, 5, 4), new.subjectLength=5) hits3 stopifnot(identical(hits2, hits3)) } \keyword{methods} \keyword{classes} IRanges/man/HitsList-class.Rd0000644000175100017510000000731512607265143017046 0ustar00biocbuildbiocbuild\name{HitsList-class} \docType{class} \alias{class:HitsList} \alias{HitsList-class} \alias{HitsList} \alias{class:CompressedHitsList} \alias{CompressedHitsList-class} \alias{CompressedHitsList} % coercion \alias{as.matrix,HitsList-method} \alias{as.matrix,CompressedHitsList-method} \alias{as.table,HitsList-method} \alias{t,HitsList-method} % accessors \alias{space,HitsList-method} \alias{space,CompressedHitsList-method} \alias{ranges,HitsList-method} \alias{subjectHits,HitsList-method} \alias{subjectHits,CompressedHitsList-method} \alias{queryHits,HitsList-method} \alias{queryHits,CompressedHitsList-method} \alias{queryLength,CompressedHitsList-method} \alias{subjectLength,CompressedHitsList-method} \title{List of Hits objects} \description{The \code{HitsList} class stores a set of Hits objects. It's typically used to represent the result of \code{findOverlaps} on two \code{\linkS4class{RangesList}} objects.} \details{ Roughly the same set of utilities are provided for \code{HitsList} as for \code{Hits}: The \code{as.matrix} method coerces a \code{HitsList} in a similar way to \code{Hits}, except a column is prepended that indicates which space (or element in the query \code{RangesList}) to which the row corresponds. The \code{as.table} method flattens or unlists the list, counts the number of hits for each query range and outputs the counts as a \code{table}, which has the same shape as from a single \code{Hits} object. To transpose a \code{HitsList} \code{x}, so that the subject and query in each space are interchanged, call \code{t(x)}. This allows, for example, counting the number of hits for each subject element using \code{as.table}. When the HitsList object is the result of a call to \code{\link{findOverlaps}} on two \code{\linkS4class{RangesList}} objects, the actual regions of intersection between the overlapping ranges can be obtained with the \code{ranges} accessor. } \section{Coercion}{ In the code snippets below, \code{x} is a \code{HitsList} object. \describe{ \item{}{\code{as.matrix(x)}: calls \code{as.matrix} on each \code{Hits}, combines them row-wise and offsets the indices so that they are aligned with the result of calling \code{unlist} on the query and subject. } \item{}{\code{as.table(x)}: counts the number of hits for each query element in \code{x} and outputs the counts as a \code{table}, which is aligned with the result of calling \code{unlist} on the query. } \item{}{\code{t(x)}: Interchange the query and subject in each space of \code{x}, returns a transposed \code{HitsList}.} } } \section{Accessors}{ \describe{ \item{}{\code{queryHits(x)}: Equivalent to \code{unname(as.matrix(x)[,1])}. } \item{}{\code{subjectHits(x)}: Equivalent to \code{unname(as.matrix(x)[,2])}. } \item{}{\code{space(x)}: gets the character vector naming the space in the query \code{RangesList} for each hit, or \code{NULL} if the query did not have any names. } \item{}{\code{ranges(x, query, subject)}: returns a \code{RangesList} holding the intersection of the ranges in the \code{RangesList} objects \code{query} and \code{subject}, which should be the same subject and query used in the call to \code{findOverlaps} that generated \code{x}. Eventually, we might store the query and subject inside \code{x}, in which case the arguments would be redundant. } } } \note{This class is highly experimental. It has not been well tested and may disappear at any time.} \author{ Michael Lawrence } \seealso{ \code{\link{findOverlaps}}, which generates an instance of this class. } \keyword{methods} \keyword{classes} IRanges/man/IRanges-class.Rd0000644000175100017510000001311212607265143016623 0ustar00biocbuildbiocbuild\name{IRanges-class} \docType{class} % IRanges objects: \alias{class:IRanges} \alias{IRanges-class} \alias{start,IRanges-method} \alias{width,IRanges-method} \alias{names,IRanges-method} \alias{start<-,IRanges-method} \alias{width<-,IRanges-method} \alias{end<-,IRanges-method} \alias{names<-,IRanges-method} \alias{isNormal,IRanges-method} \alias{update,IRanges-method} \alias{c,IRanges-method} % NormalIRanges objects: \alias{class:NormalIRanges} \alias{NormalIRanges-class} \alias{NormalIRanges} \alias{isEmpty,NormalIRanges-method} \alias{isNormal,NormalIRanges-method} \alias{isDisjoint,NormalIRanges-method} \alias{max,NormalIRanges-method} \alias{min,NormalIRanges-method} % Coercion: \alias{coerce,Ranges,IRanges-method} \alias{coerce,logical,IRanges-method} \alias{coerce,logical,NormalIRanges-method} \alias{coerce,integer,IRanges-method} \alias{coerce,integer,NormalIRanges-method} \alias{coerce,numeric,IRanges-method} \alias{coerce,numeric,NormalIRanges-method} \title{IRanges and NormalIRanges objects} \description{ The IRanges class is a simple implementation of the \link{Ranges} container where 2 integer vectors of the same length are used to store the start and width values. See the \link{Ranges} virtual class for a formal definition of \link{Ranges} objects and for their methods (all of them should work for IRanges objects). Some subclasses of the IRanges class are: NormalIRanges, \link{Views}, etc... A NormalIRanges object is just an IRanges object that is guaranteed to be "normal". See the Normality section in the man page for \link{Ranges} objects for the definition and properties of "normal" \link{Ranges} objects. } \section{Constructor}{ See \code{?`\link{IRanges-constructor}`}. } \section{Coercion}{ \describe{ \item{}{ \code{as(from, "IRanges")}: Creates an IRanges instance from a Ranges object, logical vector, or integer vector. When \code{from} is a logical vector, the resulting IRanges object contains the indices for the runs of \code{TRUE} values. When \code{from} is an integer vector, the elements are either singletons or "increase by 1" sequences. } \item{}{ \code{as(from, "NormalIRanges")}: Creates a NormalIRanges instance from a logical or integer vector. When \code{from} is an integer vector, the elements must be strictly increasing. } } } \section{Combining}{ \describe{ \item{}{ \code{c(x, ..., ignore.mcols=FALSE)} Combining \code{IRanges} objects is straightforward when they do not have any metadata columns. If only one of the \code{IRanges} object has metadata columns, then the corresponding metadata columns are attached to the other \code{IRanges} object and set to \code{NA}. When multiple \code{IRanges} object have their own \code{metadata columns}, the user must ensure that each such \code{linkS4class{DataFrame}} have identical layouts to each other (same columns defined), in order for the combination to be successful, otherwise an error will be thrown. The user can call \code{c(x, ..., ignore.mcols=TRUE)} in order to combine \code{IRanges} objects with differing sets of metadata columns, which will result in the combined object having NO metadata columns. } } } \section{Methods for NormalIRanges objects}{ \describe{ \item{}{ \code{max(x)}: The maximum value in the finite set of integers represented by \code{x}. } \item{}{ \code{min(x)}: The minimum value in the finite set of integers represented by \code{x}. } } } \author{H. Pages} \seealso{ \link{Ranges-class}, \link{IRanges-constructor}, \link{IRanges-utils}, \link{intra-range-methods} for intra range transformations, \link{inter-range-methods} for inter range transformations, \link{setops-methods} } \examples{ showClass("IRanges") # shows (some of) the known subclasses ## --------------------------------------------------------------------- ## A. MANIPULATING IRanges OBJECTS ## --------------------------------------------------------------------- ## All the methods defined for Ranges objects work on IRanges objects. ## See ?Ranges for some examples. ## Also see ?`IRanges-utils` and ?`setops-methods` for additional ## operations on IRanges objects. ## Combining IRanges objects ir1 <- IRanges(c(1, 10, 20), width=5) mcols(ir1) <- DataFrame(score=runif(3)) ir2 <- IRanges(c(101, 110, 120), width=10) mcols(ir2) <- DataFrame(score=runif(3)) ir3 <- IRanges(c(1001, 1010, 1020), width=20) mcols(ir3) <- DataFrame(value=runif(3)) some.iranges <- c(ir1, ir2) ## all.iranges <- c(ir1, ir2, ir3) ## This will raise an error all.iranges <- c(ir1, ir2, ir3, ignore.mcols=TRUE) stopifnot(is.null(mcols(all.iranges))) ## --------------------------------------------------------------------- ## B. A NOTE ABOUT PERFORMANCE ## --------------------------------------------------------------------- ## Using an IRanges object for storing a big set of ranges is more ## efficient than using a standard R data frame: N <- 2000000L # nb of ranges W <- 180L # width of each range start <- 1L end <- 50000000L set.seed(777) range_starts <- sort(sample(end-W+1L, N)) range_widths <- rep.int(W, N) ## Instantiation is faster system.time(x <- IRanges(start=range_starts, width=range_widths)) system.time(y <- data.frame(start=range_starts, width=range_widths)) ## Subsetting is faster system.time(x16 <- x[c(TRUE, rep.int(FALSE, 15))]) system.time(y16 <- y[c(TRUE, rep.int(FALSE, 15)), ]) ## Internal representation is more compact object.size(x16) object.size(y16) } \keyword{methods} \keyword{classes} IRanges/man/IRanges-constructor.Rd0000644000175100017510000001554512607265143020117 0ustar00biocbuildbiocbuild\name{IRanges-constructor} \alias{IRanges-constructor} \alias{IRanges} \alias{solveUserSEW0} \alias{solveUserSEW} \title{The IRanges constructor and supporting functions} \description{ The \code{IRanges} function is a constructor that can be used to create IRanges instances. \code{solveUserSEW0} and \code{solveUserSEW} are utility functions that solve a set of user-supplied start/end/width values. } \usage{ ## IRanges constructor: IRanges(start=NULL, end=NULL, width=NULL, names=NULL) ## Supporting functions (not for the end user): solveUserSEW0(start=NULL, end=NULL, width=NULL) solveUserSEW(refwidths, start=NA, end=NA, width=NA, rep.refwidths=FALSE, translate.negative.coord=TRUE, allow.nonnarrowing=FALSE) } \arguments{ \item{start, end, width}{ For \code{IRanges} and \code{solveUserSEW0}: \code{NULL}, or vector of integers (eventually with NAs). For \code{solveUserSEW}: vector of integers (eventually with NAs). } \item{names}{ A character vector or \code{NULL}. } \item{refwidths}{ Vector of non-NA non-negative integers containing the reference widths. } \item{rep.refwidths}{ \code{TRUE} or \code{FALSE}. Use of \code{rep.refwidths=TRUE} is supported only when \code{refwidths} is of length 1. } \item{translate.negative.coord, allow.nonnarrowing}{ \code{TRUE} or \code{FALSE}. } } \section{IRanges constructor}{ Return the IRanges object containing the ranges specified by \code{start}, \code{end} and \code{width}. Input falls into one of two categories: \describe{ \item{Category 1}{ \code{start}, \code{end} and \code{width} are numeric vectors (or NULLs). If necessary they are recycled to the length of the longest (NULL arguments are filled with NAs). After this recycling, each row in the 3-column matrix obtained by binding those 3 vectors together is "solved" i.e. NAs are treated as unknown in the equation \code{end = start + width - 1}. Finally, the solved matrix is returned as an \link{IRanges} instance. } \item{Category 2}{ The \code{start} argument is a logical vector or logical Rle object and \code{IRanges(start)} produces the same result as \code{as(start, "IRanges")}. Note that, in that case, the returned IRanges instance is guaranteed to be normal. } } Note that the \code{names} argument is never recycled (to remain consistent with what \code{`names<-`} does on standard vectors). } \section{Supporting functions}{ \describe{ \item{}{ \code{solveUserSEW0(start=NULL, end=NULL, width=NULL)}: } \item{}{ \code{solveUserSEW(refwidths, start=NA, end=NA, width=NA, rep.refwidths=FALSE, translate.negative.coord=TRUE, allow.nonnarrowing=FALSE)}: Use of \code{rep.refwidths=TRUE} is supported only when \code{refwidths} is of length 1. If \code{rep.refwidths=FALSE} (the default) then \code{start}, \code{end} and \code{width} are recycled to the length of \code{refwidths} (it's an error if one of them is longer than \code{refwidths}, or is of zero length while \code{refwidths} is not). If \code{rep.refwidths=TRUE} then \code{refwidths} is first replicated L times where L is the length of the longest of \code{start}, \code{end} and \code{width}. After this replication, \code{start}, \code{end} and \code{width} are recycled to the new length of \code{refwidths} (L) (it's an error if one of them is of zero length while L is != 0). From now, \code{refwidths}, \code{start}, \code{end} and \code{width} are integer vectors of equal lengths. Each row in the 3-column matrix obtained by binding those 3 vectors together must contain at least one NA (otherwise an error is returned). Then each row is "solved" i.e. the 2 following transformations are performed (\code{i} is the indice of the row): (1) if \code{translate.negative.coord} is TRUE then a negative value of \code{start[i]} or \code{end[i]} is considered to be a \code{-refwidths[i]}-based coordinate so \code{refwidths[i]+1} is added to it to make it 1-based; (2) the NAs in the row are treated as unknowns which values are deduced from the known values in the row and from \code{refwidths[i]}. The exact rules for (2) are the following. Rule (2a): if the row contains at least 2 NAs, then \code{width[i]} must be one of them (otherwise an error is returned), and if \code{start[i]} is one of them it is replaced by 1, and if \code{end[i]} is one of them it is replaced by \code{refwidths[i]}, and finally \code{width[i]} is replaced by \code{end[i] - start[i] + 1}. Rule (2b): if the row contains only 1 NA, then it is replaced by the solution of the \code{width[i] == end[i] - start[i] + 1} equation. Finally, the set of solved rows is returned as an \link{IRanges} object of the same length as \code{refwidths} (after replication if \code{rep.refwidths=TRUE}). Note that an error is raised if either (1) the set of user-supplied start/end/width values is invalid or (2) \code{allow.nonnarrowing} is FALSE and the ranges represented by the solved start/end/width values are not narrowing the ranges represented by the user-supplied start/end/width values. } } } \author{H. Pages} \seealso{ \link{IRanges-class}, \code{\link{narrow}} } \examples{ ## --------------------------------------------------------------------- ## A. USING THE IRanges() CONSTRUCTOR ## --------------------------------------------------------------------- IRanges(start=11, end=rep.int(20, 5)) IRanges(start=11, width=rep.int(20, 5)) IRanges(-2, 20) # only one range IRanges(start=c(2, 0, NA), end=c(NA, NA, 14), width=11:0) IRanges() # IRanges instance of length zero IRanges(names=character()) ## With logical input: x <- IRanges(c(FALSE, TRUE, TRUE, FALSE, TRUE)) # logical vector input isNormal(x) # TRUE x <- IRanges(Rle(1:30) \%\% 5 <= 2) # logical Rle input isNormal(x) # TRUE ## --------------------------------------------------------------------- ## B. USING solveUserSEW() ## --------------------------------------------------------------------- refwidths <- c(5:3, 6:7) refwidths solveUserSEW(refwidths) solveUserSEW(refwidths, start=4) solveUserSEW(refwidths, end=3, width=2) solveUserSEW(refwidths, start=-3) solveUserSEW(refwidths, start=-3, width=2) solveUserSEW(refwidths, end=-4) ## The start/end/width arguments are recycled: solveUserSEW(refwidths, start=c(3, -4, NA), end=c(-2, NA)) ## Using 'rep.refwidths=TRUE': solveUserSEW(10, start=-(1:6), rep.refwidths=TRUE) solveUserSEW(10, end=-(1:6), width=3, rep.refwidths=TRUE) } \keyword{utilities} IRanges/man/IRanges-internals.Rd0000644000175100017510000000054212607265143017520 0ustar00biocbuildbiocbuild\name{IRanges internals} \alias{class:functionORNULL} \alias{functionORNULL-class} \alias{functionORNULL} \alias{coerce,ANY,vector-method} \title{IRanges internals} \description{ Objects, classes and methods defined in the \pkg{IRanges} package that are not intended to be used directly. } \keyword{internal} \keyword{classes} \keyword{methods} IRanges/man/IRanges-utils.Rd0000644000175100017510000000755412607265143016673 0ustar00biocbuildbiocbuild\name{IRanges-utils} \alias{IRanges-utils} \alias{successiveIRanges} \alias{breakInChunks} \alias{whichAsIRanges} % Coercion: \alias{asNormalIRanges} \alias{coerce,IRanges,NormalIRanges-method} \title{IRanges utility functions} \description{ Utility functions for creating or modifying \link{IRanges} objects. } \usage{ ## Create an IRanges instance: successiveIRanges(width, gapwidth=0, from=1) breakInChunks(totalsize, chunksize, nchunk) ## Turn a logical vector into a set of ranges: whichAsIRanges(x) ## Coercion: asNormalIRanges(x, force=TRUE) } \arguments{ \item{width}{ A vector of non-negative integers (with no NAs) specifying the widths of the ranges to create. } \item{gapwidth}{ A single integer or an integer vector with one less element than the \code{width} vector specifying the widths of the gaps separating one range from the next one. } \item{from}{ A single integer specifying the starting position of the first range. } \item{totalsize}{ A single non-negative integer. The total size of the object to break. } \item{chunksize}{ A single positive integer. The size of the chunks (last chunk might be smaller). } \item{nchunk}{ A single positive integer. The number of chunks. } \item{x}{ A logical vector for \code{whichAsIRanges}. An \link{IRanges} object for \code{asNormalIRanges}. } \item{force}{ \code{TRUE} or \code{FALSE}. Should \code{x} be turned into a \link{NormalIRanges} object even if \code{isNormal(x)} is \code{FALSE}? } } \details{ \code{successiveIRanges} returns an IRanges instance containing the ranges that have the widths specified in the \code{width} vector and are separated by the gaps specified in \code{gapwidth}. The first range starts at position \code{from}. When \code{gapwidth=0} and \code{from=1} (the defaults), the returned IRanges can be seen as a partitioning of the 1:sum(width) interval. See \code{?Partitioning} for more details on this. \code{whichAsIRanges} returns an \link{IRanges} instance containing all of the ranges where \code{x} is \code{TRUE}. If \code{force=TRUE} (the default), then \code{asNormalIRanges} will turn \code{x} into a \link{NormalIRanges} instance by reordering and reducing the set of ranges if necessary (i.e. only if \code{isNormal(x)} is \code{FALSE}, otherwise the set of ranges will be untouched). If \code{force=FALSE}, then \code{asNormalIRanges} will turn \code{x} into a \link{NormalIRanges} instance only if \code{isNormal(x)} is \code{TRUE}, otherwise it will raise an error. Note that when \code{force=FALSE}, the returned object is guaranteed to contain exactly the same set of ranges than \code{x}. \code{as(x, "NormalIRanges")} is equivalent to \code{asNormalIRanges(x, force=TRUE)}. } \author{H. Pages} \seealso{ \link{Ranges-class}, \link{IRanges-class}, \link{intra-range-methods} for intra range transformations, \link{inter-range-methods} for inter range transformations, \link{setops-methods}, \code{\link{solveUserSEW}}, \code{\link{successiveViews}} } \examples{ vec <- as.integer(c(19, 5, 0, 8, 5)) successiveIRanges(vec) breakInChunks(600999, 50000) # 13 chunks of size 50000 (last chunk is # smaller). whichAsIRanges(vec >= 5) x <- IRanges(start=c(-2L, 6L, 9L, -4L, 1L, 0L, -6L, 10L), width=c( 5L, 0L, 6L, 1L, 4L, 3L, 2L, 3L)) asNormalIRanges(x) # 3 non-empty ranges ordered from left to right and # separated by gaps of width >= 1. ## More on normality: example(`IRanges-class`) isNormal(x16) # FALSE if (interactive()) x16 <- asNormalIRanges(x16) # Error! whichFirstNotNormal(x16) # 57 isNormal(x16[1:56]) # TRUE xx <- asNormalIRanges(x16[1:56]) class(xx) max(xx) min(xx) } \keyword{utilities} IRanges/man/IRangesList-class.Rd0000644000175100017510000000741712607265143017472 0ustar00biocbuildbiocbuild\name{IRangesList-class} \docType{class} % IRangesList objects: \alias{class:IRangesList} \alias{class:CompressedIRangesList} \alias{class:SimpleIRangesList} \alias{IRangesList-class} \alias{CompressedIRangesList-class} \alias{SimpleIRangesList-class} \alias{IRangesList} \alias{CompressedIRangesList} \alias{SimpleIRangesList} % accessors \alias{end,CompressedIRangesList-method} \alias{width,CompressedIRangesList-method} \alias{start,CompressedIRangesList-method} % coercion \alias{unlist,IRangesList-method} % general \alias{max,CompressedNormalIRangesList-method} \alias{max,SimpleNormalIRangesList-method} \alias{min,CompressedNormalIRangesList-method} \alias{min,SimpleNormalIRangesList-method} \alias{summary,CompressedIRangesList-method} % NormalIRangesList objects: \alias{class:NormalIRangesList} \alias{class:CompressedNormalIRangesList} \alias{class:SimpleNormalIRangesList} \alias{NormalIRangesList-class} \alias{CompressedNormalIRangesList-class} \alias{SimpleNormalIRangesList-class} \alias{NormalIRangesList} \alias{CompressedNormalIRangesList} \alias{SimpleNormalIRangesList} \alias{isNormal,CompressedIRangesList-method} \alias{isNormal,SimpleIRangesList-method} \alias{unlist,SimpleNormalIRangesList-method} % coercion \alias{coerce,CompressedIRangesList,CompressedNormalIRangesList-method} \alias{coerce,SimpleIRangesList,SimpleNormalIRangesList-method} \alias{as.list,CompressedNormalIRangesList-method} \alias{as.list.CompressedNormalIRangesList} \title{List of IRanges and NormalIRanges} \description{\code{\linkS4class{IRangesList}} and \code{\linkS4class{NormalIRangesList}} objects for storing \code{\linkS4class{IRanges}} and \code{\linkS4class{NormalIRanges}} objects respectively.} \section{Constructor}{ \describe{ \item{}{\code{IRangesList(..., universe = NULL, compress = TRUE)}: The \code{...} argument accepts either a comma-separated list of \code{IRanges} objects, or a single \code{LogicalList} / logical \code{RleList} object, or 2 elements named \code{start} and \code{end} each of them being either a list of integer vectors or an IntegerList object. When \code{IRanges} objects are supplied, each of them becomes an element in the new \code{IRangesList}, in the same order, which is analogous to the \code{\link{list}} constructor. If \code{compress}, the internal storage of the data is compressed. } } } \section{Coercion}{ \describe{ \item{}{\code{unlist(x)}: Unlists \code{x}, an \code{IRangesList}, by concatenating all of the ranges into a single \code{IRanges} instance. If the length of \code{x} is zero, an empty \code{IRanges} is returned. } } } \section{Methods for NormalIRangesList objects}{ \describe{ \item{}{ \code{max(x)}: An integer vector containing the maximum values of each of the elements of \code{x}. } \item{}{ \code{min(x)}: An integer vector containing the minimum values of each of the elements of \code{x}. } } } \author{ Michael Lawrence } \seealso{ \code{\linkS4class{RangesList}}, the parent of this class, for more functionality. \link{intra-range-methods} and \link{inter-range-methods} for intra and inter range transformations of IRangesList objects. \link{setops-methods} for set operations on IRangesList objects. } \examples{ range1 <- IRanges(start=c(1,2,3), end=c(5,2,8)) range2 <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) named <- IRangesList(one = range1, two = range2) length(named) # 2 names(named) # "one" and "two" named[[1]] # range1 unnamed <- IRangesList(range1, range2) names(unnamed) # NULL x <- IRangesList(start=list(c(1,2,3), c(15,45,20,1)), end=list(c(5,2,8), c(15,100,80,5))) as.list(x) } \keyword{classes} \keyword{methods} IRanges/man/IntervalForest-class.Rd0000644000175100017510000000662712607265143020257 0ustar00biocbuildbiocbuild\name{IntervalForest-class} \docType{class} \alias{IntervalForest-class} % constructor \alias{IntervalForest} % coercion \alias{coerce,CompressedIRangesList,IntervalForest-method} \alias{coerce,IntervalForest,CompressedIRangesList-method} \alias{coerce,IntervalForest,IRanges-method} \alias{coerce,RangesList,IntervalForest-method} % accessors \alias{length,IntervalForest-method} \alias{start,IntervalForest-method} \alias{end,IntervalForest-method} \alias{width,IntervalForest-method} \alias{elementLengths,IntervalForest-method} \alias{names,IntervalForest-method} % methods \alias{[,IntervalForest-method} \alias{show,IntervalForest-method} \title{Interval Search Forests} \description{ Efficiently perform overlap queries with a set of interval trees. WARNING: IntervalForest objects are defunct. Please use \link{NCLists} objects instead. See \code{?\link{NCLists}} for more information. } \details{ A common type of query that arises when working with intervals is finding which intervals in one set overlap those in another. An efficient family of algorithms for answering such queries is known as the Interval Tree. The \code{IntervalForest} class stores a set of Interval Trees corresponding to intervals that are partitioned into disjoint sets. The most efficient way to construct \code{IntervalForest} objects is to call the constructor below on a \link{CompressedIRangesList} object. See the \link{IntervalTree} class for the underlying Interval Tree data structure. A canonical example of a compressed ranges list are \code{\link[GenomicRanges]{GenomicRanges}} objects, where intervals are partitioned by their \code{seqnames}. See the \link[GenomicRanges]{GIntervalTree} class to see the use of \code{IntervalForest} objects in this case. The simplest approach for finding overlaps is to call the \code{\link{findOverlaps}} function on a \link{RangesList} object. See the man page of \code{\link{findOverlaps-methods}} for how to use this and other related functions. } \section{Constructor}{ \describe{ \item{}{IntervalForest(rangesList): Creates an \code{IntervalForest} from the ranges list in \code{rangesList}, an object coercible to \code{CompressedIRangesList}. } } } \section{Accessors}{ \describe{ \item{}{\code{length(x)}: Gets the number of ranges stored in the forest. This is a fast operation that does not bring the ranges into R.} \item{}{\code{start(x)}: Get the starts of the ranges as a \code{CompressedIntegerList}.} \item{}{\code{end(x)}: Get the ends of the ranges as \code{CompressedIntegerList}.} \item{}{\code{x@partitioning}: The range partitioning of class \code{PartitioningByEnd}.} \item{}{\code{names(x)}: Get the names of the range partitioning.} \item{}{\code{elementLengths(x)}: The number of ranges in each partition.} } } \author{Hector Corrada Bravo, Michael Lawrence} \seealso{ \code{\link{findOverlaps-methods}} for finding/counting interval overlaps between two compressed lists of "range-based" objects, \code{\linkS4class{RangesList}}, the parent of this class, \code{\linkS4class{CompressedHitsList}}, set of hits between 2 list-like objects, \code{\link[GenomicRanges]{GIntervalTree}}, which uses \code{IntervalForest} objects. } \examples{ ## IntervalForest objects are defunct. Please use NCLists objects ## instead. See ?NCLists for more information. } \keyword{classes} \keyword{methods} IRanges/man/IntervalTree-class.Rd0000644000175100017510000001275712607265143017715 0ustar00biocbuildbiocbuild\name{IntervalTree-class} \docType{class} \alias{IntervalTree-class} % constructor \alias{IntervalTree} % coercion \alias{coerce,IRanges,IntervalTree-method} \alias{coerce,Ranges,IntervalTree-method} \alias{coerce,IntervalTree,IRanges-method} % accessors \alias{length,IntervalTree-method} \alias{start,IntervalTree-method} \alias{end,IntervalTree-method} \title{Interval Search Trees} \description{ Efficiently perform overlap queries with an interval tree. WARNING: IntervalTree objects are defunct. Please use \link{NCList} objects instead. See \code{?\link{NCList}} for more information. } \details{ A common type of query that arises when working with intervals is finding which intervals in one set overlap those in another. An efficient family of algorithms for answering such queries is known as the Interval Tree. This implementation makes use of the augmented tree algorithm from the reference below, but heavily adapts it for the use case of large, sorted query sets. The simplest approach for finding overlaps is to call the \code{\link{findOverlaps}} function on a \link{Ranges} or other object with range information. See the man page of \code{\link{findOverlaps}} for how to use this and other related functions. An \code{IntervalTree} object is a derivative of \link{Ranges} and stores its ranges as a tree that is optimized for overlap queries. Thus, for repeated queries against the same subject, it is more efficient to create an \code{IntervalTree} once for the subject using the constructor described below and then perform the queries against the \code{IntervalTree} instance. } \section{Constructor}{ \describe{ \item{}{IntervalTree(ranges): Creates an \code{IntervalTree} from the ranges in \code{ranges}, an object coercible to \code{IntervalTree}, such as an \code{\linkS4class{IRanges}} object. } } } \section{Coercion}{ \describe{ \item{}{\code{as(from, "IRanges")}: Imports the ranges in \code{from}, an \code{IntervalTree}, to an \code{\linkS4class{IRanges}}.} \item{}{\code{as(from, "IntervalTree")}: Constructs an \code{IntervalTree} representing \code{from}, a \code{Ranges} object that is coercible to \code{IRanges}. } } } \section{Accessors}{ \describe{ \item{}{\code{length(x)}: Gets the number of ranges stored in the tree. This is a fast operation that does not bring the ranges into R.} \item{}{\code{start(x)}: Get the starts of the ranges.} \item{}{\code{end(x)}: Get the ends of the ranges.} } } \section{Notes on Time Complexity}{ The cost of constructing an instance of the interval tree is a \code{O(n*lg(n))}, which makes it about as fast as other types of overlap query algorithms based on sorting. The good news is that the tree need only be built once per subject; this is useful in situations of frequent querying. Also, in this implementation the data is stored outside of R, avoiding needless copying. Of course, external storage is not always convenient, so it is possible to coerce the tree to an instance of \code{\linkS4class{IRanges}} (see the Coercion section). For the query operation, the running time is based on the query size \code{m} and the average number of hits per query \code{k}. The output size is then \code{max(mk,m)}, but we abbreviate this as \code{mk}. Note that when the \code{multiple} parameter is set to \code{FALSE}, \code{k} is fixed to 1 and drops out of this analysis. We also assume here that the query is sorted by start position (the \code{findOverlaps} function sorts the query if it is unsorted). An upper bound for finding overlaps is \code{O(min(mk*lg(n),n+mk))}. The fastest interval tree algorithm known is bounded by \code{O(min(m*lg(n),n)+mk)} but is a lot more complicated and involves two auxillary trees. The lower bound is \code{Omega(lg(n)+mk)}, which is almost the same as for returning the answer, \code{Omega(mk)}. The average is of course somewhere in between. This analysis informs the choice of which set of ranges to process into a tree, i.e. assigning one to be the subject and the other to be the query. Note that if \code{m > n}, then the running time is \code{O(m)}, and the total operation of complexity \code{O(n*lg(n) + m)} is better than if \code{m} and \code{n} were exchanged. Thus, for once-off operations, it is often most efficient to choose the smaller set to become the tree (but \code{k} also affects this). This is reinforced by the realization that if \code{mk} is about the same in either direction, the running time depends only on \code{n}, which should be minimized. Even in cases where a tree has already been constructed for one of the sets, it can be more efficient to build a new tree when the existing tree of size \code{n} is much larger than the query set of size \code{m}, roughly when \code{n > m*lg(n)}. } \references{ Interval tree algorithm from: Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford. Introduction to Algorithms, second edition, MIT Press and McGraw-Hill. ISBN 0-262-53196-8 } \author{Michael Lawrence} \seealso{ \code{\link{findOverlaps}} for finding/counting interval overlaps between two "range-based" objects, \code{\linkS4class{Ranges}}, the parent of this class, \code{\linkS4class{Hits}}, set of hits between 2 vector-like objects. } \examples{ ## IntervalTree objects are defunct. Please use NCList objects instead. ## See ?NCList for more information. } \keyword{classes} \keyword{methods} IRanges/man/List-class-leftovers.Rd0000644000175100017510000000254112607265143020221 0ustar00biocbuildbiocbuild\name{List-class-leftovers} \docType{class} \alias{stack,List-method} \title{List objects (old man page)} \description{ IMPORTANT NOTE - 9/4/2014: This man page is being refactored. Most of the things that used to be documented here have been moved to the man page for \link[S4Vectors]{List} objects located in the \pkg{S4Vectors} package. } \details{ The only thing left here is the documentation of the \code{stack} method for \link{List} objects. In the code snippets below, \code{x} is a List object. \describe{ \item{}{ \code{stack(x, index.var = "name", value.var = "value")}: As with \code{\link[utils:stack]{stack}} on a \code{list}, constructs a \code{DataFrame} with two columns: one for the unlisted values, the other indicating the name of the element from which each value was obtained. \code{index.var} specifies the column name for the index (source name) column and \code{value.var} specifies the column name for the values. } } } \seealso{ \itemize{ \item The \link[S4Vectors]{List} class defined and documented in the \pkg{S4Vectors} package. } } \examples{ starts <- IntegerList(c(1, 5), c(2, 8)) ends <- IntegerList(c(3, 8), c(5, 9)) rgl <- IRangesList(start=starts, end=ends) rangeDataFrame <- stack(rgl, "space", "ranges") } \keyword{methods} \keyword{classes} IRanges/man/MaskCollection-class.Rd0000644000175100017510000001615312607265143020212 0ustar00biocbuildbiocbuild\name{MaskCollection-class} \docType{class} % Classes: \alias{class:MaskCollection} \alias{MaskCollection-class} \alias{MaskCollection} % Basic accessor methods: \alias{nir_list} \alias{nir_list,MaskCollection-method} \alias{length,MaskCollection-method} \alias{width,MaskCollection-method} \alias{active} \alias{active,MaskCollection-method} \alias{active<-} \alias{active<-,MaskCollection-method} \alias{names,MaskCollection-method} \alias{names<-,MaskCollection-method} \alias{desc} \alias{desc,MaskCollection-method} \alias{desc<-} \alias{desc<-,MaskCollection-method} % Constructor: \alias{Mask} % Other methods: \alias{max,MaskCollection-method} \alias{min,MaskCollection-method} \alias{maskedwidth} \alias{maskedwidth,MaskCollection-method} \alias{maskedratio} \alias{maskedratio,MaskCollection-method} % Subsetting and appending: \alias{append,MaskCollection,MaskCollection-method} % Endomorphisms: \alias{collapse} \alias{collapse,MaskCollection-method} % Coercion: \alias{coerce,MaskCollection,NormalIRanges-method} % "show" method: \alias{MaskCollection.show_frame} \alias{show,MaskCollection-method} \title{MaskCollection objects} \description{ The MaskCollection class is a container for storing a collection of masks that can be used to mask regions in a sequence. } \details{ In the context of the Biostrings package, a mask is a set of regions in a sequence that need to be excluded from some computation. For example, when calling \code{\link[Biostrings:letterFrequency]{alphabetFrequency}} or \code{\link[Biostrings]{matchPattern}} on a chromosome sequence, you might want to exclude some regions like the centromere or the repeat regions. This can be achieved by putting one or several masks on the sequence before calling \code{\link[Biostrings:letterFrequency]{alphabetFrequency}} on it. A MaskCollection object is a vector-like object that represents such set of masks. Like standard R vectors, it has a "length" which is the number of masks contained in it. But unlike standard R vectors, it also has a "width" which determines the length of the sequences it can be "put on". For example, a MaskCollection object of width 20000 can only be put on an \link[Biostrings:XString-class]{XString} object of 20000 letters. Each mask in a MaskCollection object \code{x} is just a finite set of integers that are >= 1 and <= \code{width(x)}. When "put on" a sequence, these integers indicate the positions of the letters to mask. Internally, each mask is represented by a \link{NormalIRanges} object. } \section{Basic accessor methods}{ In the code snippets below, \code{x} is a MaskCollection object. \describe{ \item{}{ \code{length(x)}: The number of masks in \code{x}. } \item{}{ \code{width(x)}: The common with of all the masks in \code{x}. This determines the length of the sequences that \code{x} can be "put on". } \item{}{ \code{active(x)}: A logical vector of the same length as \code{x} where each element indicates whether the corresponding mask is active or not. } \item{}{ \code{names(x)}: \code{NULL} or a character vector of the same length as \code{x}. } \item{}{ \code{desc(x)}: \code{NULL} or a character vector of the same length as \code{x}. } \item{}{ \code{nir_list(x)}: A list of the same length as \code{x}, where each element is a \link{NormalIRanges} object representing a mask in \code{x}. } } } \section{Constructor}{ \describe{ \item{}{ \code{Mask(mask.width, start=NULL, end=NULL, width=NULL)}: Return a single mask (i.e. a MaskCollection object of length 1) of width \code{mask.width} (a single integer >= 1) and masking the ranges of positions specified by \code{start}, \code{end} and \code{width}. See the \code{\link{IRanges}} constructor (\code{?\link{IRanges}}) for how \code{start}, \code{end} and \code{width} can be specified. Note that the returned mask is active and unnamed. } } } \section{Other methods}{ In the code snippets below, \code{x} is a MaskCollection object. \describe{ \item{}{ \code{isEmpty(x)}: Return a logical vector of the same length as \code{x}, indicating, for each mask in \code{x}, whether it's empty or not. } \item{}{ \code{max(x)}: The greatest (or last, or rightmost) masked position for each mask. This is a numeric vector of the same length as \code{x}. } \item{}{ \code{min(x)}: The smallest (or first, or leftmost) masked position for each mask. This is a numeric vector of the same length as \code{x}. } \item{}{ \code{maskedwidth(x)}: The number of masked position for each mask. This is an integer vector of the same length as \code{x} where all values are >= 0 and <= \code{width(x)}. } \item{}{ \code{maskedratio(x)}: \code{maskedwidth(x) / width(x)} } } } \section{Subsetting and appending}{ In the code snippets below, \code{x} and \code{values} are MaskCollection objects. \describe{ \item{}{ \code{x[i]}: Return a new MaskCollection object made of the selected masks. Subscript \code{i} can be a numeric, logical or character vector. } \item{}{ \code{x[[i, exact=TRUE]]}: Extract the mask selected by \code{i} as a \link{NormalIRanges} object. Subscript \code{i} can be a single integer or a character string. } \item{}{ \code{append(x, values, after=length(x))}: Add masks in \code{values} to \code{x}. } } } \section{Other methods}{ In the code snippets below, \code{x} is a MaskCollection object. \describe{ \item{}{ \code{collapse(x)}: Return a MaskCollection object of length 1 obtained by collapsing all the active masks in \code{x}. } } } \author{H. Pages} \seealso{ \link{NormalIRanges-class}, \link{read.Mask}, \link[Biostrings]{MaskedXString-class}, \code{\link{reverse}}, \code{\link[Biostrings]{alphabetFrequency}}, \code{\link[Biostrings]{matchPattern}} } \examples{ ## Making a MaskCollection object: mask1 <- Mask(mask.width=29, start=c(11, 25, 28), width=c(5, 2, 2)) mask2 <- Mask(mask.width=29, start=c(3, 10, 27), width=c(5, 8, 1)) mask3 <- Mask(mask.width=29, start=c(7, 12), width=c(2, 4)) mymasks <- append(append(mask1, mask2), mask3) mymasks length(mymasks) width(mymasks) collapse(mymasks) ## Names and descriptions: names(mymasks) <- c("A", "B", "C") # names should be short and unique... mymasks mymasks[c("C", "A")] # ...to make subsetting by names easier desc(mymasks) <- c("you can be", "more verbose", "here") mymasks[-2] ## Activate/deactivate masks: active(mymasks)["B"] <- FALSE mymasks collapse(mymasks) active(mymasks) <- FALSE # deactivate all masks mymasks active(mymasks)[-1] <- TRUE # reactivate all masks except mask 1 active(mymasks) <- !active(mymasks) # toggle all masks ## Other advanced operations: mymasks[[2]] length(mymasks[[2]]) mymasks[[2]][-3] append(mymasks[-2], gaps(mymasks[2])) } \keyword{methods} \keyword{classes} IRanges/man/NCList-class.Rd0000644000175100017510000002033212607265143016431 0ustar00biocbuildbiocbuild\name{NCList-class} \docType{class} % NCList objects: \alias{class:NCList} \alias{NCList-class} \alias{NCList} \alias{ranges,NCList-method} \alias{length,NCList-method} \alias{names,NCList-method} \alias{start,NCList-method} \alias{end,NCList-method} \alias{width,NCList-method} \alias{coerce,NCList,IRanges-method} \alias{coerce,Ranges,NCList-method} % NCLists objects: \alias{class:NCLists} \alias{NCLists-class} \alias{NCLists} \alias{ranges,NCLists-method} \alias{length,NCLists-method} \alias{names,NCLists-method} \alias{start,NCLists-method} \alias{end,NCLists-method} \alias{width,NCLists-method} \alias{elementLengths,NCLists-method} \alias{coerce,NCLists,CompressedIRangesList-method} \alias{coerce,NCLists,IRangesList-method} \alias{coerce,RangesList,NCLists-method} \title{Nested Containment List objects} \description{ The NCList class is a container for storing the Nested Containment List representation of a \link{Ranges} object. Preprocessing a \link{Ranges} object as a Nested Containment List allows efficient overlap-based operations like \code{\link{findOverlaps}}. The NCLists class is a container for storing a collection of NCList objects. An NCLists object is typically the result of preprocessing each list element of a \link{RangesList} object as a Nested Containment List. Like with NCList, the NCLists object can then be used for efficient overlap-based operations. To preprocess a \link{Ranges} or \link{RangesList} object, simply call the \code{NCList} or \code{NCLists} constructor function on it. } \usage{ NCList(x, circle.length=NA_integer_) NCLists(x, circle.length=NA_integer_) } \arguments{ \item{x}{ The \link{Ranges} or \link{RangesList} object to preprocess. } \item{circle.length}{ Use only if the space (or spaces if \code{x} is a \link{RangesList} object) on top of which the ranges in \code{x} are defined needs (need) to be considered circular. If that's the case, then use \code{circle.length} to specify the length(s) of the circular space(s). For \code{NCList}, \code{circle.length} must be a single positive integer (or NA if the space is linear). For \code{NCLists}, it must be an integer vector parallel to \code{x} (i.e. same length) and with positive or NA values (NAs indicate linear spaces). } } \details{ The \pkg{GenomicRanges} package also defines the \code{\link[GenomicRanges]{GNCList}} constructor and class for preprocessing and representing a vector of genomic ranges as a data structure based on Nested Containment Lists. Note that NCList, NCLists, and \link[GenomicRanges]{GNCList} objects, are replacements for \link{IntervalTree}, \link{IntervalForest}, and \link[GenomicRanges]{GIntervalTree} objects, respectively. The latter are defunct starting with BioC 3.2. Some important differences between the new findOverlaps/countOverlaps implementation based on Nested Containment Lists and the old implementation based on Interval Trees: \itemize{ \item With the new implementation, the hits returned by \code{\link{findOverlaps}} are not \emph{fully} ordered (i.e. ordered by queryHits and subject Hits) anymore, but only \emph{partially} ordered (i.e. ordered by queryHits only). Other than that, and except for the 3 particular situations mentioned below, the 2 implementations produce the same output. However, the new implementation is faster and more memory efficient. \item With the new implementation, either the query or the subject can be preprocessed with \code{NCList} for a \link{Ranges} object (replacement for \code{\link{IntervalTree}}), \code{NCLists} for a \link{RangesList} object (replacement for \code{\link{IntervalForest}}), and \code{\link[GenomicRanges]{GNCList}} for a \link[GenomicRanges]{GenomicRanges} object (replacement for \code{\link[GenomicRanges]{GIntervalTree}}). However, for a one time use, it is NOT advised to explicitely preprocess the input. This is because \code{\link{findOverlaps}} or \code{\link{countOverlaps}} will take care of it and do a better job at it (by preprocessing only what's needed when it's needed, and releasing memory as they go). \item With the new implementation, \code{\link{countOverlaps}} on \link{Ranges} or \link[GenomicRanges]{GenomicRanges} objects doesn't call \code{\link{findOverlaps}} in order to collect all the hits in a growing \link{Hits} object and count them only at the end. Instead, the counting happens at the C level and the hits are not kept. This reduces memory usage considerably when there is a lot of hits. \item When \code{minoverlap=0}, zero-width ranges are now interpreted as insertion points and considered to overlap with ranges that contain them. With the old alogrithm, zero-width ranges were always ignored. This is the 1st situation where the new and old implementations produce different outputs. \item When using \code{select="arbitrary"}, the new implementation will generally not select the same hits as the old implementation. This is the 2nd situation where the new and old implementations produce different outputs. \item With the old implementation, \code{maxgap} had a special meaning when \code{type} was set to \code{"start"}, \code{"end"}, \code{"within"}, or \code{"equal"}. With the new implementation, this special meaning is still being used but only when \code{type} is set to \code{"start"} or \code{"end"}. If \code{maxgap}'s special meaning when \code{type} is \code{"within"} or \code{"equal"} seems useful to you, please say hello on our support site (\url{https://support.bioconductor.org/}) or on the bioc-devel mailing list. Anyway, this is the 3rd situation where the new and old implementations produce different outputs. \item The new implementation supports preprocessing of a \link[GenomicRanges]{GenomicRanges} object with ranges defined on circular sequences (e.g. on the mitochnodrial chromosome). See \link[GenomicRanges]{GNCList} in the \pkg{GenomicRanges} package for some examples. \item Objects preprocessed with \code{NCList}, \code{NCLists}, and \code{\link[GenomicRanges]{GNCList}} are serializable (with \code{save}) for later use. Not a typical thing to do though, because preprocessing is very cheap (i.e. very fast and memory efficient). } } \value{ An NCList object for the \code{NCList} constructor and an NCLists object for the \code{NCLists} constructor. } \author{H. Pages} \references{ Alexander V. Alekseyenko and Christopher J. Lee -- Nested Containment List (NCList): a new algorithm for accelerating interval query of genome alignment and interval databases. Bioinformatics (2007) 23 (11): 1386-1393. doi: 10.1093/bioinformatics/btl647 } \seealso{ \itemize{ \item The \code{\link[GenomicRanges]{GNCList}} constructor and class defined in the \pkg{GenomicRanges} package. \item \code{\link{findOverlaps}} for finding/counting interval overlaps between two \emph{range-based} objects. \item \link{Ranges} and \link{RangesList} objects. } } \examples{ ## The example below is for illustration purpose only and does NOT ## reflect typical usage. This is because, for a one time use, it is ## NOT advised to explicitely preprocess the input for findOverlaps() ## or countOverlaps(). These functions will take care of it and do a ## better job at it (by preprocessing only what's needed when it's ## needed, and release memory as they go). query <- IRanges(c(1, 4, 9), c(5, 7, 10)) subject <- IRanges(c(2, 2, 10), c(2, 3, 12)) ## Either the query or the subject of findOverlaps() can be preprocessed: ppsubject <- NCList(subject) hits1 <- findOverlaps(query, ppsubject) hits1 ppquery <- NCList(query) hits2 <- findOverlaps(ppquery, subject) hits2 ## Note that 'hits1' and 'hits2' contain the same hits but not in the ## same order. stopifnot(identical(sort(hits1), sort(hits2))) } \keyword{classes} \keyword{methods} IRanges/man/RDApplyParams-class.Rd0000644000175100017510000002034412607265143017757 0ustar00biocbuildbiocbuild\name{rdapply} \alias{rdapply} \alias{rdapply,RDApplyParams-method} \alias{RDApplyParams-class} % constructor \alias{RDApplyParams} % accessors \alias{applyFun} \alias{applyFun,RDApplyParams-method} \alias{applyFun<-} \alias{applyFun<-,RDApplyParams-method} \alias{applyParams} \alias{applyParams,RDApplyParams-method} \alias{applyParams<-} \alias{applyParams<-,RDApplyParams-method} \alias{filterRules} \alias{filterRules,RDApplyParams-method} \alias{filterRules<-} \alias{filterRules<-,RDApplyParams-method} \alias{rangedData} \alias{rangedData,RDApplyParams-method} \alias{rangedData<-} \alias{rangedData<-,RDApplyParams-method} \alias{reducerFun} \alias{reducerFun,RDApplyParams-method} \alias{reducerFun<-} \alias{reducerFun<-,RDApplyParams-method} \alias{reducerParams} \alias{reducerParams,RDApplyParams-method} \alias{reducerParams<-} \alias{reducerParams<-,RDApplyParams-method} \alias{simplify} \alias{simplify,RDApplyParams-method} \alias{simplify<-} \alias{simplify<-,RDApplyParams-method} \alias{iteratorFun} \alias{iteratorFun,RDApplyParams-method} \alias{iteratorFun<-} \alias{iteratorFun<-,RDApplyParams-method} \title{Applying over spaces} \description{The \code{rdapply} function applies a user function over the spaces of a \code{\linkS4class{RangedData}}. The parameters to \code{rdapply} are collected into an instance of \code{RDApplyParams}, which is passed as the sole parameter to \code{rdapply}.} \usage{ rdapply(x, ...) } \arguments{ \item{x}{The \code{RDApplyParams} instance, see below for how to make one.} \item{...}{Additional arguments for methods} } \value{ By default a \code{list} holding the result of each invocation of the user function, but see details. } \details{ The \code{rdapply} function is an attempt to facilitate the common operation of performing the same operation over each space (e.g. chromosome) in a \code{RangedData}. To facilitate a wide array of such tasks, the function takes a large number of options. The \code{RDApplyParams} class is meant to help manage this complexity. In particular, it facilitates experimentation through its support for incremental changes to parameter settings. There are two \code{RangedData} settings that are required: the user \code{function} object and the \code{RangedData} over which it is applied. The rest of the settings determine what is actually passed to the user function and how the return value is processed before relaying it to the user. The following is the description and rationale for each setting. \describe{ \item{\code{rangedData}}{\strong{REQUIRED}. The \code{RangedData} instance over which \code{applyFun} is applied. } \item{\code{applyFun}}{\strong{REQUIRED}. The user \code{function} to be applied to each space in the \code{RangedData}. The function must expect the \code{RangedData} as its first parameter and also accept the parameters specified in \code{applyParams}. } \item{\code{applyParams}}{ The \code{list} of additional parameters to pass to \code{applyFun}. Usually empty. } \item{\code{filterRules}}{ The instance of \code{\linkS4class{FilterRules}} that is used to filter each subset of the \code{RangedData} passed to the user function. This is an efficient and convenient means for performing the same operation over different subsets of the data on a space-by-space basis. In particular, this avoids the need to store subsets of the entire \code{RangedData}. A common workflow is to invoke \code{rdapply} with one set of active filters, enable different filters, reinvoke \code{rdapply}, and compare the results. } \item{\code{simplify}}{ A scalar logical (\code{TRUE} or \code{FALSE}) indicating whether the \code{list} to be returned from \code{rdapply} should be simplified as by \code{\link{sapply}}. Defaults to \code{FALSE}. } \item{\code{reducerFun}}{ The \code{function} that is used to convert the \code{list} that would otherwise be returned from \code{rdapply} to something more convenient. The function should take the list as its first parameter and also accept the parameters specified in \code{reducerParams}. This is an alternative to the primitive behavior of the \code{simplify} option (so \code{simplify} must be \code{FALSE} if this option is set). The aim is to orthogonalize the \code{applyFun} operation (i.e. the statistics) from the data structure of the result. } \item{\code{reducerParams}}{ A \code{list} of additional parameters to pass to \code{reducerFun}. Can only be set if \code{reducerFun} is set. Usually empty. } \item{\code{iteratorFun}}{ The function used for applying over the \code{RangedData}. By default, this is \code{lapply}, but it could also be a specialized function, like \code{mclapply}. } } } \section{Constructing an RDApplyParams object}{ \describe{ \item{}{\code{RDApplyParams(rangedData, applyFun, applyParams, filterRules, simplify, reducerFun, reducerParams)}: Constructs a \code{RDApplyParams} object with each setting specified by the argument of the same name. See the Details section for more information. } } } \section{Accessors}{ In the following code snippets, \code{x} is an \code{RDApplyParams} object. \describe{ \item{}{\code{rangedData(x)}, \code{rangedData(x) <- value}: Get or set the \code{RangedData} instance over which \code{applyFun} is applied. } \item{}{\code{applyFun(x)}, \code{applyFun(x) <- value}: Get or set the user \code{function} to be applied to each space in the \code{RangedData}. } \item{}{\code{applyParams(x)}, \code{applyParams(x) <- value}: Get or set the \code{list} of additional parameters to pass to \code{applyFun}. } \item{}{\code{filterRules(x)}, \code{filterRules(x) <- value}: Get or set the instance of \code{\linkS4class{FilterRules}} that is used to filter each subset of the \code{RangedData} passed to the user function. } \item{}{\code{simplify(x)}, \code{simplify(x) <- value}: Get or set a a scalar logical (\code{TRUE} or \code{FALSE}) indicating whether the \code{list} to be returned from \code{rdapply} should be simplified as by \code{\link{sapply}}. } \item{}{\code{reducerFun(x)}, \code{reducerFun(x) <- value}: Get or set the \code{function} that is used to convert the \code{list} that would otherwise be returned from \code{rdapply} to something more convenient. } \item{}{\code{reducerParams(x)}, \code{reducerParams(x) <- value}: Get or set a \code{list} of additional parameters to pass to \code{reducerFun}. } \item{}{\code{iteratorFun(x)}, \code{iteratorFun(x) <- value}: Get or set the function used for applying over the \code{RangedData}. } } } \author{Michael Lawrence} \seealso{ \code{\linkS4class{RangedData}}, \code{\linkS4class{FilterRules}} } \examples{ ranges <- IRanges(c(1,2,3),c(4,5,6)) score <- c(2L, 0L, 1L) rd <- RangedData(ranges, score, space = c("chr1","chr2","chr1")) ## a single function countrows <- function(rd) nrow(rd) params <- RDApplyParams(rd, countrows) rdapply(params) # list(chr1 = 2L, chr2 = 1L) ## with a parameter params <- RDApplyParams(rd, function(rd, x) nrow(rd)*x, list(x = 2)) rdapply(params) # list(chr1 = 4L, chr2 = 2L) ## add a filter cutoff <- 0 rules <- FilterRules(filter = score > cutoff) params <- RDApplyParams(rd, countrows, filterRules = rules) rdapply(params) # list(chr1 = 2L, chr2 = 0L) rules <- FilterRules(list(fun = function(rd) rd[["score"]] < 2), filter = score > cutoff) params <- RDApplyParams(rd, countrows, filterRules = rules) rdapply(params) # list(chr1 = 1L, chr2 = 0L) active(filterRules(params))["filter"] <- FALSE rdapply(params) # list(chr1 = 1L, chr2 = 1L) ## simplify params <- RDApplyParams(rd, countrows, simplify = TRUE) rdapply(params) # c(chr1 = 2L, chr2 = 1L) ## reducing params <- RDApplyParams(rd, countrows, reducerFun = unlist, reducerParams = list(use.names = FALSE)) rdapply(params) ## c(2L, 1L) } \keyword{classes} \keyword{methods} IRanges/man/RangedData-class.Rd0000644000175100017510000004755612607265143017310 0ustar00biocbuildbiocbuild\name{RangedData-class} \docType{class} \alias{class:RangedData} \alias{RangedData-class} % Accessors: \alias{nrow,RangedData-method} \alias{ncol,RangedData-method} \alias{rownames,RangedData-method} \alias{colnames,RangedData-method} \alias{rownames<-,RangedData-method} \alias{colnames<-,RangedData-method} \alias{elementLengths,RangedData-method} \alias{end,RangedData-method} \alias{end<-,RangedData-method} \alias{length,RangedData-method} \alias{names,RangedData-method} \alias{names<-,RangedData-method} \alias{ranges,RangedData-method} \alias{ranges<-,RangedData-method} \alias{start,RangedData-method} \alias{start<-,RangedData-method} \alias{values,RangedData-method} \alias{values<-,RangedData-method} \alias{width,RangedData-method} \alias{width<-,RangedData-method} \alias{space,RangedData-method} \alias{universe,RangedData-method} \alias{universe<-,RangedData-method} \alias{score,RangedData-method} \alias{score<-,RangedData-method} \alias{columnMetadata,RangedData-method} \alias{columnMetadata<-,RangedData-method} % Constructor: \alias{RangedData} % Coercion: \alias{as.data.frame.RangedData} \alias{as.data.frame,RangedData-method} \alias{coerce,RangedData,DataFrame-method} \alias{coerce,Rle,RangedData-method} \alias{coerce,RleList,RangedData-method} \alias{coerce,RleViewsList,RangedData-method} \alias{coerce,Ranges,RangedData-method} \alias{coerce,RangesList,RangedData-method} \alias{coerce,RangedData,CompressedIRangesList-method} \alias{coerce,RangedData,IRangesList-method} \alias{coerce,RangedData,RangesList-method} \alias{as.env,RangedData-method} \alias{coerce,data.frame,RangedData-method} \alias{coerce,DataTable,RangedData-method} % Combining and splitting \alias{c,RangedData-method} \alias{rbind,RangedData-method} \alias{split,RangedData,ANY-method} % Subsetting: \alias{[,RangedData-method} \alias{[[,RangedData-method} \alias{[[<-,RangedData-method} \alias{$<-,RangedData-method} % Utilities: \alias{within,RangedData-method} % Applying: \alias{endoapply,RangedData-method} \alias{lapply,RangedData-method} % Show: \alias{show,RangedData-method} \title{Data on ranges} \description{ IMPORTANT NOTE: Starting with BioC 2.12, the use of \code{RangedData} and \code{RangedDataList} objects is discouraged in favor of \code{\link[GenomicRanges]{GRanges}} and \code{\link[GenomicRanges]{GRangesList}} objects (those classes are defined in the \pkg{GenomicRanges} package). \code{RangedData} supports storing data, i.e. a set of variables, on a set of ranges spanning multiple spaces (e.g. chromosomes). Although the data is split across spaces, it can still be treated as one cohesive dataset when desired and extends \code{\linkS4class{DataTable}}. In order to handle large datasets, the data values are stored externally to avoid copying, and the \code{\link{rdapply}} function facilitates the processing of each space separately (divide and conquer). } \details{ A \code{RangedData} object consists of two primary components: a \code{\linkS4class{RangesList}} holding the ranges over multiple spaces and a parallel \code{\linkS4class{SplitDataFrameList}}, holding the split data. There is also an \code{universe} slot for denoting the source (e.g. the genome) of the ranges and/or data. There are two different modes of interacting with a \code{RangedData}. The first mode treats the object as a contiguous "data frame" annotated with range information. The accessors \code{start}, \code{end}, and \code{width} get the corresponding fields in the ranges as atomic integer vectors, undoing the division over the spaces. The \code{[[} and matrix-style \code{[,} extraction and subsetting functions unroll the data in the same way. \code{[[<-} does the inverse. The number of rows is defined as the total number of ranges and the number of columns is the number of variables in the data. It is often convenient and natural to treat the data this way, at least when the data is small and there is no need to distinguish the ranges by their space. The other mode is to treat the \code{RangedData} as a list, with an element (a virtual \code{\linkS4class{Ranges}}/\code{\linkS4class{DataFrame}} pair) for each space. The length of the object is defined as the number of spaces and the value returned by the \code{names} accessor gives the names of the spaces. The list-style \code{[} subset function behaves analogously. The \code{rdapply} function provides a convenient and formal means of applying an operation over the spaces separately. This mode is helpful when ranges from different spaces must be treated separately or when the data is too large to process over all spaces at once. } \section{Accessor methods}{ In the code snippets below, \code{x} is a \code{RangedData} object. The following accessors treat the data as a contiguous dataset, ignoring the division into spaces: \describe{ \item{}{Array accessors: \describe{ \item{}{ \code{nrow(x)}: The number of ranges in \code{x}. } \item{}{ \code{ncol(x)}: The number of data variables in \code{x}. } \item{}{ \code{dim(x)}: An integer vector of length two, essentially \code{c(nrow(x), ncol(x))}. } \item{}{ \code{rownames(x)}, \code{rownames(x) <- value}: Gets or sets the names of the ranges in \code{x}. } \item{}{ \code{colnames(x)}, \code{colnames(x) <- value}: Gets the names of the variables in \code{x}. } \item{}{ \code{dimnames(x)}: A list with two elements, essentially \code{list(rownames(x), colnames(x))}. } \item{}{ \code{dimnames(x) <- value}: Sets the row and column names, where value is a list as described above. } \item{}{\code{columnMetadata(x)}: Get the \code{DataFrame} of metadata along the value columns, i.e., where each column in \code{x} is represented by a row in the metadata. Note that calling \code{mcols(x)} returns the metadata on each space in \code{x}. } \item{}{\code{columnMetadata(x) <- value}: Set the \code{DataFrame} of metadata for the columns. } \item{}{\code{within(data, expr, ...)}: Evaluates \code{expr} within \code{data}, a \code{RangedData}. Any values assigned in \code{expr} will be stored as value columns in \code{data}, unless they match one of the reserved names: \code{ranges}, \code{start}, \code{end}, \code{width} and \code{space}. Behavior is undefined if any of the range symbols are modified inconsistently. Modifications to \code{space} are ignored. } } } \item{}{Range accessors. The type of the return value depends on the type of \code{\linkS4class{Ranges}}. For \code{\linkS4class{IRanges}}, an integer vector. Regardless, the number of elements is always equal to \code{nrow(x)}. \describe{ \item{}{ \code{start(x), start(x) <- value}: Get or set the starts of the ranges. When setting the starts, \code{value} can be an integer vector of \code{length(sum(elementLengths(ranges(x))))} or an IntegerList object of length \code{length(ranges(x))} and names \code{names(ranges(x))}. } \item{}{ \code{end(x), end(x) <- value}: Get or set the ends of the ranges. When setting the ends, \code{value} can be an integer vector of \code{length(sum(elementLengths(ranges(x))))} or an IntegerList object of length \code{length(ranges(x))} and names \code{names(ranges(x))}. } \item{}{ \code{width(x), width(x) <- value}: Get or set the widths of the ranges. When setting the widths, \code{value} can be an integer vector of \code{length(sum(elementLengths(ranges(x))))} or an IntegerList object of length \code{length(ranges(x))} and names \code{names(ranges(x))}. } } } } These accessors make the object seem like a list along the spaces: \describe{ \item{}{ \code{length(x)}: The number of spaces (e.g. chromosomes) in \code{x}. } \item{}{ \code{names(x)}, \code{names(x) <- value}: Get or set the names of the spaces (e.g. \code{"chr1"}). \code{NULL} or a character vector of the same length as \code{x}. } } Other accessors: \describe{ \item{}{ \code{universe(x)}, \code{universe(x) <- value}: Get or set the scalar string identifying the scope of the data in some way (e.g. genome, experimental platform, etc). The universe may be \code{NULL}. } \item{}{ \code{ranges(x), ranges(x) <- value}: Gets or sets the ranges in \code{x} as a \code{\linkS4class{RangesList}}. } \item{}{ \code{space(x)}: Gets the spaces from \code{ranges(x)}. } \item{}{ \code{values(x), values(x) <- value}: Gets or sets the data values in \code{x} as a \code{\linkS4class{SplitDataFrameList}}. } \item{}{ \code{score(x), score(x) <- value}: Gets or sets the column representing a "score" in \code{x}, as a vector. This is the column named \code{score}, or, if this does not exist, the first column, if it is numeric. The get method return \code{NULL} if no suitable score column is found. The set method takes a numeric vector as its value. } } } \section{Constructor}{ \describe{ \item{}{ \code{RangedData(ranges = IRanges(), ..., space = NULL, universe = NULL)}: Creates a \code{RangedData} with the ranges in \code{ranges} and variables given by the arguments in \code{...}. See the constructor \code{\linkS4class{DataFrame}} for how the \code{...} arguments are interpreted. If \code{ranges} is a \code{\linkS4class{Ranges}} object, the \code{space} argument is used to split of the data into spaces. If \code{space} is \code{NULL}, all of the ranges and values are placed into the same space, resulting in a single-space (length one) \code{RangedData} object. Otherwise, the ranges and values are split into spaces according to \code{space}, which is treated as a factor, like the \code{f} argument in \code{\link{split}}. If \code{ranges} is a \code{\linkS4class{RangesList}} object, then the supplied \code{space} argument is ignored and its value is derived from \code{ranges}. If \code{ranges} is not a \code{\linkS4class{Ranges}} or \code{\linkS4class{RangesList}} object, this function calls \code{as(ranges, "RangedData")} and returns the result if successful. The universe may be specified as a scalar string by the \code{universe} argument. } } } \section{Coercion}{ \describe{ \item{}{ \code{as.data.frame(x, row.names=NULL, optional=FALSE, ...)}: Copy the start, end, width of the ranges and all of the variables as columns in a \code{data.frame}. This is a bridge to existing functionality in R, but of course care must be taken if the data is large. Note that \code{optional} and \code{...} are ignored. } \item{}{ \code{as(from, "DataFrame")}: Like \code{as.data.frame} above, except the result is an \code{\linkS4class{DataFrame}} and it probably involves less copying, especially if there is only a single space. } \item{}{ \code{as(from, "RangedData")}: Coerce \code{from} to a \code{RangedData}, according to the type of \code{from}: \describe{ \item{\code{\linkS4class{Rle}}, \code{\linkS4class{RleList}}}{ Converts each run to a range and stores the run values in a column named "score". } \item{\code{\linkS4class{RleViewsList}}}{ Creates a \code{RangedData} using the ranges given by the runs of \code{subject(from)} in each of the windows, with a value column \code{score} taken as the corresponding subject values. } \item{\code{\linkS4class{Ranges}}}{ Creates a \code{RangedData} with only the ranges in \code{from}; no data columns. } \item{\code{\linkS4class{RangesList}}}{ Creates a \code{RangedData} with the ranges in \code{from}. Also propagates the \emph{inner} metadata columns of the \code{RangesList} (accessed with \code{mcols(unlist(from))}) to the data columns (aka values) of the \code{RangedData}. This makes it a \emph{lossless} coercion and the exact reverse of the coercion from \code{RangedData} to \code{RangesList}. } \item{\code{data.frame} or \code{DataTable}}{Constructs a \code{RangedData}, using the columns \dQuote{start}, \dQuote{end}, and, optionally, \dQuote{space} columns in \code{from}. The other columns become data columns in the result. Any \dQuote{width} column is ignored. } } } \item{}{ \code{as(from, "RangesList")}: Creates a \code{CompressedIRangesList} (a subclass of \code{RangesList}) made of the ranges in \code{from}. Also propagates the data columns (aka values) of the \code{RangedData} to the inner metadata columns of the \code{RangesList}. This makes it a \emph{lossless} coercion and the exact reverse of the coercion from \code{RangesList} to \code{RangedData}. } \item{}{\code{as.env(x, enclos = parent.frame())}: Creates an \code{environment} with a symbol for each variable in the frame, as well as a \code{ranges} symbol for the ranges. This is efficient, as no copying is performed. } } } \section{Subsetting and Replacement}{ In the code snippets below, \code{x} is a \code{RangedData} object. \describe{ \item{}{ \code{x[i]}: Subsets \code{x} by indexing into its spaces, so the result is of the same class, with a different set of spaces. \code{i} can be numerical, logical, \code{NULL} or missing. } \item{}{ \code{x[i,j]}: Subsets \code{x} by indexing into its rows and columns. The result is of the same class, with a different set of rows and columns. The row index \code{i} can either treat \code{x} as a flat table by being a character, integer, or logical vector or treat \code{x} as a partitioned table by being a \code{\linkS4class{RangesList}}, \code{\linkS4class{LogicalList}}, or \code{\linkS4class{IntegerList}} of the same length as \code{x}. } \item{}{ \code{x[[i]]}: Extracts a variable from \code{x}, where \code{i} can be a character, numeric, or logical scalar that indexes into the columns. The variable is unlisted over the spaces. For convenience, values of \code{"space"} and \code{"ranges"} are equivalent to \code{space(x)} and \code{unlist(ranges(x))} respectively. } \item{}{ \code{x$name}: similar to above, where \code{name} is taken literally as a column name in the data. } \item{}{ \code{x[[i]] <- value}: Sets value as column \code{i} in \code{x}, where \code{i} can be a character, numeric, or logical scalar that indexes into the columns. The length of \code{value} should equal \code{nrow(x)}. \code{x[[i]]} should be identical to \code{value} after this operation. For convenience, \code{i="ranges"} is equivalent to \code{ranges(x) <- value}. } \item{}{ \code{x$name <- value}: similar to above, where \code{name} is taken literally as a column name in the data. } } } \section{Splitting and Combining}{ In the code snippets below, \code{x} is a \code{RangedData} object. \describe{ \item{}{ \code{split(x, f, drop = FALSE)}: Split \code{x} according to \code{f}, which should be of length equal to \code{nrow(x)}. Note that \code{drop} is ignored here. The result is a \code{\linkS4class{RangedDataList}} where every element has the same length (number of spaces) but different sets of ranges within each space. } \item{}{ \code{rbind(...)}: Matches the spaces from the \code{RangedData} objects in \code{...} by name and combines them row-wise. In a way, this is the reverse of the \code{split} operation described above. } \item{}{ \code{c(x, ..., recursive = FALSE)}: Combines \code{x} with arguments specified in \code{...}, which must all be \code{RangedData} objects. This combination acts as if \code{x} is a list of spaces, meaning that the result will contain the spaces of the first concatenated with the spaces of the second, and so on. This function is useful when creating \code{RangedData} objects on a space-by-space basis and then needing to combine them. } } } \section{Applying}{ There are two ways explicitly supported ways to apply a function over the spaces of a \code{RangedData}. The richest interface is \code{\link{rdapply}}, which is described in its own man page. The simpler interface is an \code{lapply} method: \describe{ \item{}{\code{lapply(X, FUN, ...)}: Applies \code{FUN} to each space in \code{X} with extra parameters in \code{...}. } } } \author{ Michael Lawrence } \seealso{ \linkS4class{DataTable}, the parent of this class, with more utilities. The \code{\link{rdapply}} function for applying a function to each space separately. } \examples{ ranges <- IRanges(c(1,2,3),c(4,5,6)) filter <- c(1L, 0L, 1L) score <- c(10L, 2L, NA) ## constructing RangedData instances ## no variables rd <- RangedData() rd <- RangedData(ranges) ranges(rd) ## one variable rd <- RangedData(ranges, score) rd[["score"]] ## multiple variables rd <- RangedData(ranges, filter, vals = score) rd[["vals"]] # same as rd[["score"]] above rd$vals rd[["filter"]] rd <- RangedData(ranges, score + score) rd[["score...score"]] # names made valid ## use a universe rd <- RangedData(ranges, universe = "hg18") universe(rd) ## split some data over chromosomes range2 <- IRanges(start=c(15,45,20,1), end=c(15,100,80,5)) both <- c(ranges, range2) score <- c(score, c(0L, 3L, NA, 22L)) filter <- c(filter, c(0L, 1L, NA, 0L)) chrom <- paste("chr", rep(c(1,2), c(length(ranges), length(range2))), sep="") rd <- RangedData(both, score, filter, space = chrom, universe = "hg18") rd[["score"]] # identical to score rd[1][["score"]] # identical to score[1:3] ## subsetting ## list style: [i] rd[numeric()] # these three are all empty rd[logical()] rd[NULL] rd[] # missing, full instance returned rd[FALSE] # logical, supports recycling rd[c(FALSE, FALSE)] # same as above rd[TRUE] # like rd[] rd[c(TRUE, FALSE)] rd[1] # numeric index rd[c(1,2)] rd[-2] ## matrix style: [i,j] rd[,NULL] # no columns rd[NULL,] # no rows rd[,1] rd[,1:2] rd[,"filter"] rd[1,] # now by the rows rd[c(1,3),] rd[1:2, 1] # row and column rd[c(1:2,1,3),1] ## repeating rows ## dimnames colnames(rd)[2] <- "foo" colnames(rd) rownames(rd) <- head(letters, nrow(rd)) rownames(rd) ## space names names(rd) names(rd)[1] <- "chr1" ## variable replacement count <- c(1L, 0L, 2L) rd <- RangedData(ranges, count, space = c(1, 2, 1)) ## adding a variable score <- c(10L, 2L, NA) rd[["score"]] <- score rd[["score"]] # same as 'score' ## replacing a variable count2 <- c(1L, 1L, 0L) rd[["count"]] <- count2 ## numeric index also supported rd[[2]] <- score rd[[2]] # gets 'score' ## removing a variable rd[[2]] <- NULL ncol(rd) # is only 1 rd$score2 <- score ## combining/splitting rd <- RangedData(ranges, score, space = c(1, 2, 1)) c(rd[1], rd[2]) # equal to 'rd' rd2 <- RangedData(ranges, score) unlist(split(rd2, c(1, 2, 1))) # same as 'rd' ## applying lapply(rd, `[[`, 1) # get first column in each space } \keyword{methods} \keyword{classes} IRanges/man/RangedDataList-class.Rd0000644000175100017510000000311412607265143020122 0ustar00biocbuildbiocbuild\name{RangedDataList-class} \docType{class} \alias{RangedDataList-class} \alias{unlist,RangedDataList-method} \alias{stack,RangedDataList-method} % Constructor \alias{RangedDataList} \title{Lists of RangedData} \description{ IMPORTANT NOTE: Starting with BioC 2.12, the use of \code{RangedData} and \code{RangedDataList} objects is discouraged in favor of \code{\link[GenomicRanges]{GRanges}} and \code{\link[GenomicRanges]{GRangesList}} objects (those classes are defined in the \pkg{GenomicRanges} package). A formal list of \code{\linkS4class{RangedData}} objects. Extends and inherits all its methods from \code{\linkS4class{List}}. One use case is to group together all of the samples from an experiment generating data on ranges. } \section{Constructor}{ \describe{ \item{}{\code{RangedDataList(...)}: Concatenates the \code{RangedData} objects in \code{...} into a new \code{RangedDataList}. } } } \section{Other methods}{ \describe{ \item{}{\code{stack(x, index.var = "name")}: Concantenates the elements of \code{x} into a \code{RangedData}, with a column named by \code{index.var} that groups the records by their original element in \code{x}. } } } \author{Michael Lawrence} \seealso{ \code{\linkS4class{RangedData}}, the element type of this \code{\linkS4class{List}}. } \examples{ ranges <- IRanges(c(1,2,3),c(4,5,6)) a <- RangedData(IRanges(c(1,2,3),c(4,5,6)), score = c(10L, 2L, NA)) b <- RangedData(IRanges(c(1,2,4),c(4,7,5)), score = c(3L, 5L, 7L)) RangedDataList(sample1 = a, sample2 = b) } \keyword{classes} IRanges/man/RangedSelection-class.Rd0000644000175100017510000000462712607265143020354 0ustar00biocbuildbiocbuild\name{RangedSelection-class} \docType{class} \alias{RangedSelection-class} % accessors \alias{ranges,RangedSelection-method} \alias{colnames,RangedSelection-method} \alias{ranges<-,RangedSelection-method} \alias{colnames<-,RangedSelection-method} % coercion \alias{coerce,RangesList,RangedSelection-method} % constructor \alias{RangedSelection} \title{Selection of ranges and columns} \description{A \code{RangedSelection} represents a query against a table of interval data in terms of ranges and column names. The ranges select any table row with an overlapping interval. Note that the intervals are always returned, even if no columns are selected.} \details{ Traditionally, tabular data structures have supported the \code{\link{subset}} function, which allows one to select a subset of the rows and columns from the table. In that case, the rows and columns are specified by two separate arguments. As querying interval data sources, especially those external to R, such as binary indexed files and databases, is increasingly common, there is a need to encapsulate the row and column specifications into a single data structure, mostly for the sake of interface cleanliness. The \code{RangedSelection} class fills that role. } \section{Constructor}{ \describe{ \item{}{\code{RangedSelection(ranges = RangesList(), colnames = character())}: Constructors a \code{RangedSelection} with the given \code{ranges} and \code{colnames}. } } } \section{Coercion}{ \describe{ \item{}{\code{as(from, "RangedSelection")}: Coerces \code{from} to a \code{RangedSelection} object. Typically, \code{from} is a \code{\linkS4class{RangesList}}, the ranges of which become the ranges in the new \code{RangedSelection}. } } } \section{Accessors}{ In the code snippets below, \code{x} is always a \code{RangedSelection}. \describe{ \item{}{\code{ranges(x), ranges(x) <- value}: Gets or sets the ranges, a \code{\linkS4class{RangesList}}, that select rows with overlapping intervals. } \item{}{\code{colnames(x), colnames(x) <- value}: Gets the names, a \code{character} vector, indicating the columns. } } } \author{ Michael Lawrence } \examples{ rl <- RangesList(chr1 = IRanges(c(1, 5), c(3, 6))) RangedSelection(rl) as(rl, "RangedSelection") # same as above RangedSelection(rl, "score") } \keyword{methods} \keyword{classes} IRanges/man/Ranges-class.Rd0000644000175100017510000003460012607265143016517 0ustar00biocbuildbiocbuild\name{Ranges-class} \docType{class} % Classes: \alias{class:Ranges} \alias{Ranges-class} \alias{Ranges} % Generics and methods: \alias{length,Ranges-method} \alias{elementLengths,Ranges-method} \alias{width} \alias{start,Ranges-method} \alias{width,Ranges-method} \alias{end,Ranges-method} \alias{mid} \alias{mid,Ranges-method} \alias{start<-} \alias{width<-} \alias{end<-} \alias{as.matrix,Ranges-method} \alias{as.data.frame.Ranges} \alias{as.data.frame,Ranges-method} \alias{as.integer,Ranges-method} \alias{unlist,Ranges-method} \alias{show,Ranges-method} \alias{showAsCell,Ranges-method} \alias{isEmpty,Ranges-method} \alias{isNormal} \alias{isNormal,Ranges-method} \alias{whichFirstNotNormal} \alias{whichFirstNotNormal,Ranges-method} \alias{isDisjoint} \alias{isDisjoint,Ranges-method} \alias{update,Ranges-method} \alias{tile} \alias{tile,Ranges-method} \title{Ranges objects} \description{ The Ranges virtual class is a general container for storing a set of integer ranges. } \details{ A Ranges object is a vector-like object where each element describes a "range of integer values". A "range of integer values" is a finite set of consecutive integer values. Each range can be fully described with exactly 2 integer values which can be arbitrarily picked up among the 3 following values: its "start" i.e. its smallest (or first, or leftmost) value; its "end" i.e. its greatest (or last, or rightmost) value; and its "width" i.e. the number of integer values in the range. For example the set of integer values that are greater than or equal to -20 and less than or equal to 400 is the range that starts at -20 and has a width of 421. In other words, a range is a closed, one-dimensional interval with integer end points and on the domain of integers. The starting point (or "start") of a range can be any integer (see \code{start} below) but its "width" must be a non-negative integer (see \code{width} below). The ending point (or "end") of a range is equal to its "start" plus its "width" minus one (see \code{end} below). An "empty" range is a range that contains no value i.e. a range that has a null width. Depending on the context, it can be interpreted either as just the empty \emph{set} of integers or, more precisely, as the position \emph{between} its "end" and its "start" (note that for an empty range, the "end" equals the "start" minus one). The length of a Ranges object is the number of ranges in it, not the number of integer values in its ranges. A Ranges object is considered empty iff all its ranges are empty. Ranges objects have a vector-like semantic i.e. they only support single subscript subsetting (unlike, for example, standard R data frames which can be subsetted by row and by column). The Ranges class itself is a virtual class. The following classes derive directly from the Ranges class: \link{IRanges}, \link{NCList}, \link{PartitioningByEnd}. } \section{Methods}{ In the code snippets below, \code{x}, \code{y} and \code{object} are Ranges objects. Not all the functions described below will necessarily work with all kinds of Ranges objects but they should work at least for \link{IRanges} objects. Note that many more operations on Ranges objects are described in other man pages of the IRanges package. See for example the man page for intra range transformations (e.g. \code{shift()}, see \code{?`\link{intra-range-methods}`}), or the man page for inter range transformations (e.g. \code{reduce()}, see \code{?`\link{inter-range-methods}`}), or the man page for \code{findOverlaps} methods (see \code{?`\link{findOverlaps-methods}`}), or the man page for \link{RangesList} objects where the \code{split} method for Ranges objects is documented. \describe{ \item{}{ \code{length(x)}: The number of ranges in \code{x}. } \item{}{ \code{start(x)}: The start values of the ranges. This is an integer vector of the same length as \code{x}. } \item{}{ \code{width(x)}: The number of integer values in each range. This is a vector of non-negative integers of the same length as \code{x}. } \item{}{ \code{end(x)}: \code{start(x) + width(x) - 1L} } \item{}{ \code{mid(x)}: returns the midpoint of the range, \code{start(x) + floor((width(x) - 1)/2)}. } \item{}{ \code{names(x)}: \code{NULL} or a character vector of the same length as \code{x}. } \item{}{ \code{update(object, ...)}: Convenience method for combining multiple modifications of \code{object} in one single call. For example \code{object <- update(object, start=start(object)-2L, end=end(object)+2L)} is equivalent to \code{start(object) <- start(object)-2L; end(object) <- end(object)+2L}. } \item{}{ \code{tile(x, n, width, ...)}: Splits each range in \code{x} into subranges as specified by \code{n} (number of ranges) or \code{width}. Only one of \code{n} or \code{width} can be specified. The return value is a \code{IRangesList} the same length as \code{x}. Ranges with a width less than the \code{width} argument are returned unchanged. } \item{}{ \code{isEmpty(x)}: Return a logical value indicating whether \code{x} is empty or not. } \item{}{ \code{as.matrix(x, ...)}: Convert \code{x} into a 2-column integer matrix containing \code{start(x)} and \code{width(x)}. Extra arguments (\code{...}) are ignored. } \item{}{ \code{as.data.frame(x, row.names=NULL, optional=FALSE, ...)}: Convert \code{x} into a standard R data frame object. \code{row.names} must be \code{NULL} or a character vector giving the row names for the data frame, and \code{optional} and any additional argument (\code{...}) is ignored. See \code{?\link{as.data.frame}} for more information about these arguments. } \item{}{ \code{as.integer(x)}: Convert \code{x} into an integer vector, by converting each range into the integer sequence formed by \code{from:to} and concatenating them together. } \item{}{ \code{unlist(x, recursive = TRUE, use.names = TRUE)}: Similar to \code{as.integer(x)} except can add names to elements. } \item{}{ \code{x[[i]]}: Return integer vector \code{start(x[i]):end(x[i])} denoted by \code{i}. Subscript \code{i} can be a single integer or a character string. } \item{}{ \code{x[i]}: Return a new Ranges object (of the same type as \code{x}) made of the selected ranges. \code{i} can be a numeric vector, a logical vector, \code{NULL} or missing. If \code{x} is a \link{NormalIRanges} object and \code{i} a positive numeric subscript (i.e. a numeric vector of positive values), then \code{i} must be strictly increasing. } \item{}{ \code{rep(x, times, length.out, each)}: Repeats the values in \code{x} through one of the following conventions: \describe{ \item{\code{times}}{Vector giving the number of times to repeat each element if of length \code{length(x)}, or to repeat the Ranges elements if of length 1.} \item{\code{length.out}}{Non-negative integer. The desired length of the output vector.} \item{\code{each}}{Non-negative integer. Each element of \code{x} is repeated \code{each} times.} } } \item{}{ \code{c(x, ...)}: Combine \code{x} and the Ranges objects in \code{...} together. Any object in \code{...} must belong to the same class as \code{x}, or to one of its subclasses, or must be \code{NULL}. The result is an object of the same class as \code{x}. NOTE: Only works for \link{IRanges} (and derived) objects for now. } \item{}{ \code{x * y}: The arithmetic operation \code{x * y} is for centered zooming. It symmetrically scales the width of \code{x} by \code{1/y}, where \code{y} is a numeric vector that is recycled as necessary. For example, \code{x * 2} results in ranges with half their previous width but with approximately the same midpoint. The ranges have been \dQuote{zoomed in}. If \code{y} is negative, it is equivalent to \code{x * (1/abs(y))}. Thus, \code{x * -2} would double the widths in \code{x}. In other words, \code{x} has been \dQuote{zoomed out}. } \item{}{ \code{x + y}: Expands the ranges in \code{x} on either side by the corresponding value in the numeric vector \code{y}. } \item{}{ \code{show(x)}: By default the \code{show} method displays 5 head and 5 tail lines. The number of lines can be altered by setting the global options \code{showHeadLines} and \code{showTailLines}. If the object length is less than the sum of the options, the full object is displayed. These options affect GRanges, GAlignments, Ranges and XString objects. } } } \section{Normality}{ A Ranges object \code{x} is implicitly representing an arbitrary finite set of integers (that are not necessarily consecutive). This set is the set obtained by taking the union of all the values in all the ranges in \code{x}. This representation is clearly not unique: many different Ranges objects can be used to represent the same set of integers. However one and only one of them is guaranteed to be "normal". By definition a Ranges object is said to be "normal" when its ranges are: (a) not empty (i.e. they have a non-null width); (b) not overlapping; (c) ordered from left to right; (d) not even adjacent (i.e. there must be a non empty gap between 2 consecutive ranges). Here is a simple algorithm to determine whether \code{x} is "normal": (1) if \code{length(x) == 0}, then \code{x} is normal; (2) if \code{length(x) == 1}, then \code{x} is normal iff \code{width(x) >= 1}; (3) if \code{length(x) >= 2}, then \code{x} is normal iff: \preformatted{ start(x)[i] <= end(x)[i] < start(x)[i+1] <= end(x)[i+1]} for every 1 <= \code{i} < \code{length(x)}. The obvious advantage of using a "normal" Ranges object to represent a given finite set of integers is that it is the smallest in terms of number of ranges and therefore in terms of storage space. Also the fact that we impose its ranges to be ordered from left to right makes it unique for this representation. A special container (\link{NormalIRanges}) is provided for holding a "normal" \link{IRanges} object: a \link{NormalIRanges} object is just an \link{IRanges} object that is guaranteed to be "normal". Here are some methods related to the notion of "normal" Ranges: \describe{ \item{}{ \code{isNormal(x)}: Return TRUE or FALSE indicating whether \code{x} is "normal" or not. } \item{}{ \code{whichFirstNotNormal(x)}: Return \code{NA} if \code{x} is normal, or the smallest valid indice \code{i} in \code{x} for which \code{x[1:i]} is not "normal". } } } \section{Disjoint ranges}{ A Ranges object \code{x} is considered to be "disjoint" if its ranges are disjoint (i.e. non-overlapping). The \code{isDisjoint} function is provided for testing whether a Ranges object is "disjoint" or not: \describe{ \item{}{ \code{isDisjoint(x)}: Return TRUE or FALSE indicating whether \code{x} is "disjoint" or not. \code{isDisjoint} handles empty ranges (a.k.a. zero-width ranges) as follow: single empty range A is considered to overlap with single range B iff it's contained in B without being on the edge of B (in which case it would be ambiguous whether A is contained in or adjacent to B). In other words, single empty range A is considered to overlap with single range B iff \preformatted{ start(B) < start(A) and end(A) < end(B)} Because A is an empty range it verifies \code{end(A) = start(A) - 1} so the above is equivalent to: \preformatted{ start(B) < start(A) <= end(B)} and also equivalent to: \preformatted{ start(B) <= end(A) < end(B)} Finally, it is also equivalent to: \preformatted{ compare(A, B) == 2} See \code{?`\link{Ranges-comparison}`} for the meaning of the codes returned by the \code{\link{compare}} function. } } Note that a "normal" Ranges object is always "disjoint" but the opposite is not true. } \author{H. Pages and M. Lawrence} \seealso{ \link{IRanges-class}, \link{Ranges-comparison}, \link{intra-range-methods}, \link{inter-range-methods}, \link{IRanges-utils}, \link{setops-methods}, \link{RangedData-class}, \link{NCList-class}, \link{PartitioningByEnd-class}, \code{\link{update}}, \code{\link{as.matrix}}, \code{\link{as.data.frame}}, \code{\link{rep}} } \examples{ ## --------------------------------------------------------------------- ## Basic manipulation ## --------------------------------------------------------------------- x <- IRanges(start=c(2:-1, 13:15), width=c(0:3, 2:0)) x length(x) start(x) width(x) end(x) isEmpty(x) as.matrix(x) as.data.frame(x) ## Subsetting: x[4:2] # 3 ranges x[-1] # 6 ranges x[FALSE] # 0 range x0 <- x[width(x) == 0] # 2 ranges isEmpty(x0) ## Use the replacement methods to resize the ranges: width(x) <- width(x) * 2 + 1 x end(x) <- start(x) # equivalent to width(x) <- 0 x width(x) <- c(2, 0, 4) x start(x)[3] <- end(x)[3] - 2 # resize the 3rd range x ## Name the elements: names(x) names(x) <- c("range1", "range2") x x[is.na(names(x))] # 5 ranges x[!is.na(names(x))] # 2 ranges ir <- IRanges(c(1,5), c(3,10)) ir*1 # no change ir*c(1,2) # zoom second range by 2X ir*-2 # zoom out 2X ## --------------------------------------------------------------------- ## isDisjoint() ## --------------------------------------------------------------------- ## On a Ranges object: isDisjoint(IRanges(c(2,5,1), c(3,7,3))) # FALSE isDisjoint(IRanges(c(2,9,5), c(3,9,6))) # TRUE isDisjoint(IRanges(1, 5)) # TRUE ## Handling of empty ranges: x <- IRanges(c(11, 16, 11, -2, 11), c(15, 29, 10, 10, 10)) stopifnot(isDisjoint(x)) ## Sliding an empty range along a non-empty range: sapply(11:17, function(i) compare(IRanges(i, width=0), IRanges(12, 15))) sapply(11:17, function(i) isDisjoint(c(IRanges(i, width=0), IRanges(12, 15)))) } \keyword{methods} \keyword{classes} IRanges/man/Ranges-comparison.Rd0000644000175100017510000002471412607265143017571 0ustar00biocbuildbiocbuild\name{Ranges-comparison} \alias{Ranges-comparison} \alias{compare} \alias{compare,Ranges,Ranges-method} \alias{rangeComparisonCodeToLetter} \alias{match,Ranges,Ranges-method} \alias{selfmatch,Ranges-method} \alias{order,Ranges-method} \title{Comparing and ordering ranges} \description{ Methods for comparing and/or ordering \link{Ranges} objects. } \usage{ ## Element-wise (aka "parallel") comparison of 2 Ranges objects ## ------------------------------------------------------------ \S4method{compare}{Ranges,Ranges}(x, y) rangeComparisonCodeToLetter(code) ## match() ## ------- \S4method{match}{Ranges,Ranges}(x, table, nomatch=NA_integer_, incomparables=NULL, method=c("auto", "quick", "hash")) ## selfmatch() ## ----------- \S4method{selfmatch}{Ranges}(x, method=c("auto", "quick", "hash")) ## order() ## ------- \S4method{order}{Ranges}(..., na.last=TRUE, decreasing=FALSE) } \arguments{ \item{x, y, table}{ \link{Ranges} objects. } \item{code}{ A vector of codes as returned by \code{compare}. } \item{nomatch}{ The value to be returned in the case when no match is found. It is coerced to an \code{integer}. } \item{incomparables}{ Not supported. } \item{method}{ Use a Quicksort-based (\code{method="quick"}) or a hash-based (\code{method="hash"}) algorithm. The latter tends to give better performance, except maybe for some pathological input that we've not been able to determine so far. When \code{method="auto"} is specified, the most efficient algorithm will be used, that is, the hash-based algorithm if \code{length(x) <= 2^29}, otherwise the Quicksort-based algorithm. } \item{...}{ One or more \link{Ranges} objects. The additional \link{Ranges} objects are used to break ties. } \item{na.last}{ Ignored. } \item{decreasing}{ \code{TRUE} or \code{FALSE}. } } \details{ Two ranges are considered equal iff they share the same start and width. Note that with this definition, 2 empty ranges are generally not equal (they need to share the same start to be considered equal). This means that, when it comes to comparing ranges, an empty range is interpreted as a position between its end and start. For example, a typical usecase is comparison of insertion points defined along a string (like a DNA sequence) and represented as empty ranges. Ranges are ordered by starting position first, and then by width. This way, the space of ranges is totally ordered. On a \link{Ranges} object, \code{order}, \code{sort}, and \code{rank} are consistent with this order. \describe{ \item{}{ \code{compare(x, y)}: Performs element-wise (aka "parallel") comparison of 2 \link{Ranges} objects of \code{x} and \code{y}, that is, returns an integer vector where the i-th element is a code describing how \code{x[i]} is qualitatively positioned with respect to \code{y[i]}. Here is a summary of the 13 predefined codes (and their letter equivalents) and their meanings: \preformatted{ -6 a: x[i]: .oooo....... 6 m: x[i]: .......oooo. y[i]: .......oooo. y[i]: .oooo....... -5 b: x[i]: ..oooo...... 5 l: x[i]: ......oooo.. y[i]: ......oooo.. y[i]: ..oooo...... -4 c: x[i]: ...oooo..... 4 k: x[i]: .....oooo... y[i]: .....oooo... y[i]: ...oooo..... -3 d: x[i]: ...oooooo... 3 j: x[i]: .....oooo... y[i]: .....oooo... y[i]: ...oooooo... -2 e: x[i]: ..oooooooo.. 2 i: x[i]: ....oooo.... y[i]: ....oooo.... y[i]: ..oooooooo.. -1 f: x[i]: ...oooo..... 1 h: x[i]: ...oooooo... y[i]: ...oooooo... y[i]: ...oooo..... 0 g: x[i]: ...oooooo... y[i]: ...oooooo... } Note that this way of comparing ranges is a refinement over the standard ranges comparison defined by the \code{==}, \code{!=}, \code{<=}, \code{>=}, \code{<} and \code{>} operators. In particular a code that is \code{< 0}, \code{= 0}, or \code{> 0}, corresponds to \code{x[i] < y[i]}, \code{x[i] == y[i]}, or \code{x[i] > y[i]}, respectively. The \code{compare} method for \link{Ranges} objects is guaranteed to return predefined codes only but methods for other objects (e.g. for \link[GenomicRanges]{GenomicRanges} objects) can return non-predefined codes. Like for the predefined codes, the sign of any non-predefined code must tell whether \code{x[i]} is less than, or greater than \code{y[i]}. } \item{}{ \code{rangeComparisonCodeToLetter(x)}: Translate the codes returned by \code{compare}. The 13 predefined codes are translated as follow: -6 -> a; -5 -> b; -4 -> c; -3 -> d; -2 -> e; -1 -> f; 0 -> g; 1 -> h; 2 -> i; 3 -> j; 4 -> k; 5-> l; 6 -> m. Any non-predefined code is translated to X. The translated codes are returned in a factor with 14 levels: a, b, ..., l, m, X. } \item{}{ \code{match(x, table, nomatch=NA_integer_, method=c("auto", "quick", "hash"))}: Returns an integer vector of the length of \code{x}, containing the index of the first matching range in \code{table} (or \code{nomatch} if there is no matching range) for each range in \code{x}. } \item{}{ \code{selfmatch(x, method=c("auto", "quick", "hash"))}: Equivalent to, but more efficient than, \code{match(x, x, method=method)}. } \item{}{ \code{duplicated(x, fromLast=FALSE, method=c("auto", "quick", "hash"))}: Determines which elements of \code{x} are equal to elements with smaller subscripts, and returns a logical vector indicating which elements are duplicates. \code{duplicated(x)} is equivalent to, but more efficient than, \code{duplicated(as.data.frame(x))} on a \link{Ranges} object. See \code{\link[base]{duplicated}} in the \pkg{base} package for more details. } \item{}{ \code{unique(x, fromLast=FALSE, method=c("auto", "quick", "hash"))}: Removes duplicate ranges from \code{x}. \code{unique(x)} is equivalent to, but more efficient than, \code{unique(as.data.frame(x))} on a \link{Ranges} object. See \code{\link[base]{unique}} in the \pkg{base} package for more details. } \item{}{ \code{x \%in\% table}: A shortcut for finding the ranges in \code{x} that match any of the ranges in \code{table}. Returns a logical vector of length equal to the number of ranges in \code{x}. } \item{}{ \code{findMatches(x, table, method=c("auto", "quick", "hash"))}: An enhanced version of \code{match} that returns all the matches in a \link{Hits} object. } \item{}{ \code{countMatches(x, table, method=c("auto", "quick", "hash"))}: Returns an integer vector of the length of \code{x} containing the number of matches in \code{table} for each element in \code{x}. } \item{}{ \code{order(...)}: Returns a permutation which rearranges its first argument (a \link{Ranges} object) into ascending order, breaking ties by further arguments (also \link{Ranges} objects). } \item{}{ \code{sort(x)}: Sorts \code{x}. See \code{\link[base]{sort}} in the \pkg{base} package for more details. } \item{}{ \code{rank(x, na.last=TRUE, ties.method=c("average", "first", "random", "max", "min"))}: Returns the sample ranks of the ranges in \code{x}. See \code{\link[base]{rank}} in the \pkg{base} package for more details. } } } \author{H. Pages} \seealso{ \itemize{ \item The \link{Ranges} class. \item \link[S4Vectors]{Vector-comparison} in the \pkg{S4Vectors} package for general information about comparing, ordering, and tabulating vector-like objects. \item \link[GenomicRanges]{GenomicRanges-comparison} in the \pkg{GenomicRanges} package for comparing and ordering genomic ranges. \item \link{intra-range-methods} and \link{inter-range-methods} for intra and inter range transformations. \item \link{setops-methods} for set operations on \link{IRanges} objects. \item \code{\link{findOverlaps}} for finding overlapping ranges. } } \examples{ ## --------------------------------------------------------------------- ## A. ELEMENT-WISE (AKA "PARALLEL") COMPARISON OF 2 Ranges OBJECTS ## --------------------------------------------------------------------- x0 <- IRanges(1:11, width=4) x0 y0 <- IRanges(6, 9) compare(x0, y0) compare(IRanges(4:6, width=6), y0) compare(IRanges(6:8, width=2), y0) compare(x0, y0) < 0 # equivalent to 'x0 < y0' compare(x0, y0) == 0 # equivalent to 'x0 == y0' compare(x0, y0) > 0 # equivalent to 'x0 > y0' rangeComparisonCodeToLetter(-10:10) rangeComparisonCodeToLetter(compare(x0, y0)) ## Handling of zero-width ranges (a.k.a. empty ranges): x1 <- IRanges(11:17, width=0) x1 compare(x1, x1[4]) compare(x1, IRanges(12, 15)) ## Note that x1[2] and x1[6] are empty ranges on the edge of non-empty ## range IRanges(12, 15). Even though -1 and 3 could also be considered ## valid codes for describing these configurations, compare() ## considers x1[2] and x1[6] to be *adjacent* to IRanges(12, 15), and ## thus returns codes -5 and 5: compare(x1[2], IRanges(12, 15)) # -5 compare(x1[6], IRanges(12, 15)) # 5 x2 <- IRanges(start=c(20L, 8L, 20L, 22L, 25L, 20L, 22L, 22L), width=c( 4L, 0L, 11L, 5L, 0L, 9L, 5L, 0L)) x2 which(width(x2) == 0) # 3 empty ranges x2[2] == x2[2] # TRUE x2[2] == x2[5] # FALSE x2 == x2[4] x2 >= x2[3] ## --------------------------------------------------------------------- ## B. match(), selfmatch(), %in%, duplicated(), unique() ## --------------------------------------------------------------------- table <- x2[c(2:4, 7:8)] match(x2, table) x2 \%in\% table duplicated(x2) unique(x2) ## --------------------------------------------------------------------- ## C. findMatches(), countMatches() ## --------------------------------------------------------------------- findMatches(x2, table) countMatches(x2, table) x2_levels <- unique(x2) countMatches(x2_levels, x2) ## --------------------------------------------------------------------- ## D. order() AND RELATED METHODS ## --------------------------------------------------------------------- order(x2) sort(x2) rank(x2, ties.method="first") } \keyword{methods} IRanges/man/RangesList-class.Rd0000644000175100017510000001734512607265143017362 0ustar00biocbuildbiocbuild\name{RangesList-class} \docType{class} \alias{class:RangesList-class} \alias{class:SimpleRangesList-class} \alias{RangesList-class} \alias{SimpleRangesList-class} \alias{RangesList} \alias{SimpleRangesList} % accessors \alias{end,RangesList-method} \alias{end<-,RangesList-method} \alias{width,RangesList-method} \alias{width<-,RangesList-method} \alias{start,RangesList-method} \alias{start<-,RangesList-method} \alias{space} \alias{space,RangesList-method} \alias{universe,RangesList-method} \alias{universe<-,RangesList-method} \alias{universe} \alias{universe<-} \alias{isNormal,RangesList-method} \alias{whichFirstNotNormal,RangesList-method} \alias{isDisjoint,RangesList-method} % coercion \alias{coerce,RangesList,IRangesList-method} \alias{coerce,RangesList,CompressedIRangesList-method} \alias{coerce,RangesList,SimpleIRangesList-method} \alias{coerce,SimpleRangesList,SimpleIRangesList-method} \alias{coerce,RangesList,SimpleRangesList-method} \alias{coerce,RangesList,NormalIRangesList-method} \alias{coerce,RangesList,CompressedNormalIRangesList-method} \alias{coerce,RangesList,SimpleNormalIRangesList-method} \alias{coerce,LogicalList,IRangesList-method} \alias{coerce,LogicalList,CompressedIRangesList-method} \alias{coerce,LogicalList,SimpleIRangesList-method} \alias{coerce,LogicalList,NormalIRangesList-method} \alias{coerce,LogicalList,CompressedNormalIRangesList-method} \alias{coerce,LogicalList,SimpleNormalIRangesList-method} \alias{coerce,RleList,IRangesList-method} \alias{coerce,RleList,CompressedIRangesList-method} \alias{coerce,RleList,SimpleIRangesList-method} \alias{coerce,RleList,NormalIRangesList-method} \alias{coerce,RleList,CompressedNormalIRangesList-method} \alias{coerce,RleList,SimpleNormalIRangesList-method} \alias{coerce,list,RangesList-method} \alias{merge,RangesList,missing-method} \alias{merge,missing,RangesList-method} \alias{merge,RangesList,RangesList-method} % show \alias{show,RangesList-method} \alias{showAsCell,RangesList-method} \title{List of Ranges} \description{An extension of \linkS4class{List} that holds only \linkS4class{Ranges} objects. Useful for storing ranges over a set of spaces (e.g. chromosomes), each of which requires a separate \code{Ranges} object. As a \code{Vector}, \code{RangesList} may be annotated with its universe identifier (e.g. a genome) in which all of its spaces exist. } \section{Accessors}{ In the code snippets below, \code{x} is a \code{RangesList} object. All of these accessors collapse over the spaces: \describe{ \item{}{\code{start(x), start(x) <- value}: Get or set the starts of the ranges. When setting the starts, \code{value} can be an integer vector of \code{length(sum(elementLengths(x)))} or an IntegerList object of length \code{length(x)} and names \code{names(x)}.} \item{}{\code{end(x), end(x) <- value}: Get or set the ends of the ranges. When setting the starts, \code{value} can be an integer vector of \code{length(sum(elementLengths(x)))} or an IntegerList object of length \code{length(x)} and names \code{names(x)}.} \item{}{\code{width(x), width(x) <- value}: Get or set the widths of the ranges. When setting the starts, \code{value} can be an integer vector of \code{length(sum(elementLengths(x)))} or an IntegerList object of length \code{length(x)} and names \code{names(x)}.} \item{}{\code{space(x)}: Gets the spaces of the ranges as a character vector. This is equivalent to \code{names(x)}, except each name is repeated according to the length of its element. } } These accessors are for the \code{universe} identifier: \describe{ \item{}{\code{universe(x)}: gets the name of the universe as a single string, if one has been specified, \code{NULL} otherwise. } \item{}{\code{universe(x) <- value}: sets the name of the universe to \code{value}, a single string or \code{NULL}. } } } \section{Constructor}{ \describe{ \item{}{\code{RangesList(..., universe = NULL)}: Each \code{Ranges} in \code{...} becomes an element in the new \code{RangesList}, in the same order. This is analogous to the \code{\link{list}} constructor, except every argument in \code{...} must be derived from \code{Ranges}. The universe is specified by the \code{universe} parameter, which should be a single string or NULL, to leave unspecified. } } } \section{Coercion}{ In the code snippets below, \code{x} and \code{from} are a \code{RangesList} object. \describe{ \item{}{ \code{as.data.frame(x, row.names = NULL, optional = FALSE, ..., value.name = "value", use.outer.mcols = FALSE, group_name.as.factor = FALSE)}: Coerces \code{x} to a \code{data.frame}. See as.data.frame on the \code{List} man page for details (?\code{List}). } \item{}{\code{as(from, "SimpleIRangesList")}: Coerces \code{from}, to a \code{\linkS4class{SimpleIRangesList}}, requiring that all \code{Ranges} elements are coerced to internal \code{IRanges} elements. This is a convenient way to ensure that all \code{Ranges} have been imported into R (and that there is no unwanted overhead when accessing them). } \item{}{\code{as(from, "CompressedIRangesList")}: Coerces \code{from}, to a \code{\linkS4class{CompressedIRangesList}}, requiring that all \code{Ranges} elements are coerced to internal \code{IRanges} elements. This is a convenient way to ensure that all \code{Ranges} have been imported into R (and that there is no unwanted overhead when accessing them). } \item{}{\code{as(from, "SimpleNormalIRangesList")}: Coerces \code{from}, to a \code{\linkS4class{SimpleNormalIRangesList}}, requiring that all \code{Ranges} elements are coerced to internal \code{NormalIRanges} elements. } \item{}{\code{as(from, "CompressedNormalIRangesList")}: Coerces \code{from}, to a \code{\linkS4class{CompressedNormalIRangesList}}, requiring that all \code{Ranges} elements are coerced to internal \code{NormalIRanges} elements. } } } \section{Arithmetic Operations}{ Any arithmetic operation, such as \code{x + y}, \code{x * y}, etc, where \code{x} is a \code{RangesList}, is performed identically on each element. Currently, \code{Ranges} supports only the \code{*} operator, which zooms the ranges by a numeric factor. } \author{ Michael Lawrence } \seealso{ \code{\linkS4class{List}}, the parent of this class, for more functionality. } \examples{ ## --------------------------------------------------------------------- ## Basic manipulation ## --------------------------------------------------------------------- range1 <- IRanges(start=c(1, 2, 3), end=c(5, 2, 8)) range2 <- IRanges(start=c(15, 45, 20, 1), end=c(15, 100, 80, 5)) named <- RangesList(one = range1, two = range2) length(named) # 2 start(named) # same as start(c(range1, range2)) names(named) # "one" and "two" named[[1]] # range1 unnamed <- RangesList(range1, range2) names(unnamed) # NULL # edit the width of the ranges in the list edited <- named width(edited) <- rep(c(3,2), elementLengths(named)) edited # same as list(range1, range2) as.list(RangesList(range1, range2)) # coerce to data.frame as.data.frame(named) # set the universe universe(named) <- "hg18" universe(named) RangesList(range1, range2, universe = "hg18") ## zoom in 2X collection <- RangesList(one = range1, range2) collection * 2 ## --------------------------------------------------------------------- ## isDisjoint() ## --------------------------------------------------------------------- range3 <- IRanges(start=c(-2, 6, 7), width=c(8, 0, 0)) # with empty ranges collection <- IRangesList(one=range1, range2, range3) isDisjoint(collection) } \keyword{methods} \keyword{classes} IRanges/man/Rle-class-leftovers.Rd0000644000175100017510000000606312607265143020033 0ustar00biocbuildbiocbuild\name{Rle-class-leftovers} \docType{class} \alias{ranges,Rle-method} \alias{coerce,Rle,IRanges-method} \alias{coerce,Rle,NormalIRanges-method} \alias{window.Rle} \alias{window,Rle-method} \alias{findRange} \alias{findRange,Rle-method} \alias{splitRanges} \alias{splitRanges,Rle-method} \alias{splitRanges,vectorORfactor-method} \title{Rle objects (old man page)} \description{ IMPORTANT NOTE - 7/3/2014: This man page is being refactored. Most of the things that used to be documented here have been moved to the man page for \link[S4Vectors]{Rle} objects located in the \pkg{S4Vectors} package. } \section{Coercion}{ In the code snippets below, \code{from} is an Rle object: \describe{ \item{}{ \code{as(from, "IRanges")}: Creates an \link{IRanges} instance from a logical Rle. Note that this instance is guaranteed to be normal. } \item{}{ \code{as(from, "NormalIRanges")}: Creates a \link{NormalIRanges} instance from a logical Rle. } } } \section{General Methods}{ In the code snippets below, \code{x} is an Rle object: \describe{ \item{}{ \code{window(x, start=NA, end=NA, width=NA)}: Extract the subsequence window from \code{x} specified by: \describe{ \item{\code{start}, \code{end}, \code{width}}{The start, end, or width of the window. Two of the three are required.} } } \item{}{ \code{window(x, start=NA, end=NA, width=NA) <- value}: Replace the subsequence window specified on the left (i.e. the subsequence in \code{x} specified by \code{start}, \code{end} and \code{width}) by \code{value}. \code{value} must either be of class Rle, belong to a subclass of Rle, or be coercible to Rle or a subclass of Rle. The elements of \code{value} are repeated to create an Rle with the same number of elements as the width of the subsequence window it is replacing. } \item{}{ \code{split(x, f, drop=FALSE)}: Splits \code{x} according to \code{f} to create a \link{CompressedRleList} object. If \code{f} is a list-like object then \code{drop} is ignored and \code{f} is treated as if it was \code{rep(seq_len(length(f)), sapply(f, length))}, so the returned object has the same shape as \code{f} (it also receives the names of \code{f}). Otherwise, if \code{f} is not a list-like object, empty list elements are removed from the returned object if \code{drop} is \code{TRUE}. } \item{}{ \code{findRange(x, vec)}: Returns an \link{IRanges} object representing the ranges in Rle \code{vec} that are referenced by the indices in the integer vector \code{x}. } \item{}{ \code{splitRanges(x)}: Returns a \linkS4class{CompressedIRangesList} object that contains the ranges for each of the unique run values. } } } \seealso{ The \link[S4Vectors]{Rle} class defined and documented in the \pkg{S4Vectors} package. } \examples{ x <- Rle(10:1, 1:10) x window(x, 4, 14) } \keyword{methods} \keyword{classes} IRanges/man/RleViews-class.Rd0000644000175100017510000000277212607265143017045 0ustar00biocbuildbiocbuild\name{RleViews-class} \docType{class} % Classes: \alias{class:RleViews} \alias{RleViews-class} \alias{RleViews} % Constructors: \alias{Views,Rle-method} % Methods: \alias{show,RleViews-method} % coercion \alias{coerce,AtomicList,RleViews-method} \title{The RleViews class} \description{ The RleViews class is the basic container for storing a set of views (start/end locations) on the same Rle object. } \details{ An RleViews object contains a set of views (start/end locations) on the same \link{Rle} object called "the subject vector" or simply "the subject". Each view is defined by its start and end locations: both are integers such that start <= end. An RleViews object is in fact a particular case of a \link{Views} object (the RleViews class contains the \link{Views} class) so it can be manipulated in a similar manner: see \code{?\link{Views}} for more information. Note that two views can overlap and that a view can be "out of limits" i.e. it can start before the first element of the subject or/and end after its last element. } \author{P. Aboyoun} \seealso{ \link{Views-class}, \link{Rle-class}, \link{view-summarization-methods} } \examples{ subject <- Rle(rep(c(3L, 2L, 18L, 0L), c(3,2,1,5))) myViews <- Views(subject, 3:0, 5:8) myViews subject(myViews) length(myViews) start(myViews) end(myViews) width(myViews) myViews[[2]] set.seed(0) vec <- Rle(sample(0:2, 20, replace = TRUE)) vec Views(vec, vec > 0) } \keyword{methods} \keyword{classes} IRanges/man/RleViewsList-class.Rd0000644000175100017510000000562612607265143017702 0ustar00biocbuildbiocbuild\name{RleViewsList-class} \docType{class} \alias{RleViewsList-class} \alias{SimpleRleViewsList-class} % accessor \alias{subject,SimpleRleViewsList-method} % constructor \alias{Views,RleList-method} \alias{RleViewsList} % coercion \alias{coerce,RleViewsList,IRangesList-method} \alias{coerce,RleViewsList,CompressedIRangesList-method} \alias{coerce,RleViewsList,SimpleIRangesList-method} \title{List of RleViews} \description{An extension of \linkS4class{ViewsList} that holds only \linkS4class{RleViews} objects. Useful for storing coverage vectors over a set of spaces (e.g. chromosomes), each of which requires a separate \linkS4class{RleViews} object. } \details{ For more information on methods available for RleViewsList objects consult the man pages for \link{ViewsList-class} and \link{view-summarization-methods}. } \section{Constructor}{ \describe{ \item{}{\code{RleViewsList(..., rleList, rangesList, universe = NULL)}: Either \code{...} or the \code{rleList}/\code{rangesList} couplet provide the RleViews for the list. If \code{...} is provided, each of these arguments must be RleViews objects. Alternatively, \code{rleList} and \code{rangesList} accept Rle and Ranges objects respectively that are meshed together for form the RleViewsList. The universe is specified by the \code{universe} parameter, which should be a single string or NULL, to leave unspecified. } \item{}{\code{Views(subject, start=NULL, end=NULL, width=NULL, names=NULL)}: Same as \code{RleViewsList(rleList = subject, rangesList = start)}. } } } \section{Coercion}{ In the code snippets below, \code{from} is an RleViewsList object: \describe{ \item{}{ \code{as(from, "IRangesList")}: Creates a \code{CompressedIRangesList} object containing the view locations in \code{from}. } \item{}{ \code{as(from, "CompressedIRangesList")}: Creates a \code{CompressedIRangesList} object containing the view locations in \code{from}. } \item{}{ \code{as(from, "SimpleIRangesList")}: Creates a \code{SimpleIRangesList} object containing the view locations in \code{from}. } } } \author{P. Aboyoun} \seealso{ \link{ViewsList-class}, \link{view-summarization-methods} } \examples{ ## Rle objects subject1 <- Rle(c(3L,2L,18L,0L), c(3,2,1,5)) set.seed(0) subject2 <- Rle(c(0L,5L,2L,0L,3L), c(8,5,2,7,4)) ## Views rleViews1 <- Views(subject1, 3:0, 5:8) rleViews2 <- Views(subject2, subject2 > 0) ## RleList and RangesList objects rleList <- RleList(subject1, subject2) rangesList <- IRangesList(IRanges(3:0, 5:8), IRanges(subject2 > 0)) ## methods for construction method1 <- RleViewsList(rleViews1, rleViews2) method2 <- RleViewsList(rleList = rleList, rangesList = rangesList) identical(method1, method2) ## calculation over the views viewSums(method1) } \keyword{methods} \keyword{classes} IRanges/man/Vector-class-leftovers.Rd0000644000175100017510000001500012607265143020542 0ustar00biocbuildbiocbuild\name{Vector-class-leftovers} \docType{class} \alias{showAsCell,list-method} \alias{window<-,Vector-method} \alias{window<-.Vector} \alias{window<-,vector-method} \alias{window<-.vector} \alias{window<-,factor-method} \alias{window<-.factor} \alias{rev,Vector-method} \alias{rep,Vector-method} \alias{rep.int,Vector-method} \alias{subset,Vector-method} \alias{mstack} \alias{mstack,Vector-method} \alias{mstack,vector-method} \alias{tapply,ANY,Vector-method} \alias{tapply,Vector,ANY-method} \alias{tapply,Vector,Vector-method} \alias{shiftApply} \alias{shiftApply,Vector,Vector-method} \alias{shiftApply,vector,vector-method} \alias{with,Vector-method} \alias{eval} \alias{eval,expression,Vector-method} \alias{eval,language,Vector-method} \alias{as.list.Vector} \alias{as.list,Vector-method} \title{Vector objects (old man page)} \description{ IMPORTANT NOTE - 4/29/2014: This man page is being refactored. Most of the things that used to be documented here have been moved to the man page for \link[S4Vectors]{Vector} objects located in the \pkg{S4Vectors} package. } \section{Evaluation}{ In the following code snippets, \code{x} is a Vector object. \describe{ \item{}{ \code{with(x, expr)}: Evaluates \code{expr} within \code{as.env(x)} via \code{eval(x)}. } \item{}{ \code{eval(expr, envir, enclos=parent.frame())}: Evaluates \code{expr} within \code{envir}, where \code{envir} is coerced to an environment with \code{as.env(envir, enclos)}. The \code{expr} is first processed with \code{\link{bquote}}, such that any escaped symbols are directly resolved in the calling frame. } } } \section{Convenience wrappers for common subsetting operations}{ In the code snippets below, \code{x} is a Vector object or regular R vector object. The R vector object methods for \code{window} are defined in this package and the remaining methods are defined in base R. \describe{ \item{}{ \code{window(x, start=NA, end=NA, width=NA)}: Extract the subsequence window from the Vector object using: \describe{ \item{\code{start}, \code{end}, \code{width}}{The start, end, or width of the window. Two of the three are required.} } } \item{}{ \code{window(x, start=NA, end=NA, width=NA) <- value}: Replace the subsequence window specified on the left (i.e. the subsequence in \code{x} specified by \code{start}, \code{end} and \code{width}) by \code{value}. \code{value} must either be of class \code{class(x)}, belong to a subclass of \code{class(x)}, or be coercible to \code{class(x)} or a subclass of \code{class(x)}. The elements of \code{value} are repeated to create a Vector with the same number of elements as the width of the subsequence window it is replacing. } \item{}{ \code{head(x, n = 6L)}: If \code{n} is non-negative, returns the first n elements of the Vector object. If \code{n} is negative, returns all but the last \code{abs(n)} elements of the Vector object. } \item{}{ \code{tail(x, n = 6L)}: If \code{n} is non-negative, returns the last n elements of the Vector object. If \code{n} is negative, returns all but the first \code{abs(n)} elements of the Vector object. } \item{}{ \code{rev(x)}: Return a new Vector object made of the original elements in the reverse order. } \item{}{ \code{rep(x, times, length.out, each)}, \code{rep.int(x, times)}: Repeats the values in \code{x} through one of the following conventions: \describe{ \item{\code{times}}{Vector giving the number of times to repeat each element if of length \code{length(x)}, or to repeat the whole vector if of length 1.} \item{\code{length.out}}{Non-negative integer. The desired length of the output vector.} \item{\code{each}}{Non-negative integer. Each element of \code{x} is repeated \code{each} times.} } } \item{}{ \code{subset(x, subset)}: Return a new Vector object made of the subset using logical vector \code{subset}, where missing values are taken as FALSE. } } } \section{Combining}{ In the code snippets below, \code{x} is a Vector object. \describe{ \item{}{\code{mstack(..., .index.var = "name")}: A variant of \code{\link{stack}}, where the list is taken as the list of arguments in \code{...}, each of which should be a \code{Vector} or \code{vector} (mixing the two will not work). } } } \section{Looping}{ In the code snippets below, \code{x} is a Vector object. \describe{ \item{}{ \code{tapply(X, INDEX, FUN = NULL, ..., simplify = TRUE)}: Like the standard \code{\link[base]{tapply}} function defined in the base package, the \code{tapply} method for Vector objects applies a function to each cell of a ragged array, that is to each (non-empty) group of values given by a unique combination of the levels of certain factors. } \item{}{ \code{shiftApply(SHIFT, X, Y, FUN, ..., OFFSET = 0L, simplify = TRUE, verbose = FALSE)}: Let \code{i} be the indices in \code{SHIFT}, \code{X_i = window(X, 1 + OFFSET, length(X) - SHIFT[i])}, and \code{Y_i = window(Y, 1 + SHIFT[i], length(Y) - OFFSET)}. Calculates the set of \code{FUN(X_i, Y_i, ...)} values and return the results in a convenient form: \describe{ \item{\code{SHIFT}}{A non-negative integer vector of shift values.} \item{\code{X}, \code{Y}}{The Vector or R vector objects to shift.} \item{\code{FUN}}{The function, found via \code{match.fun}, to be applied to each set of shifted vectors.} \item{\dots}{Further arguments for \code{FUN}.} \item{OFFSET}{A non-negative integer offset to maintain throughout the shift operations.} \item{\code{simplify}}{A logical value specifying whether or not the result should be simplified to a vector or matrix if possible.} \item{\code{verbose}}{A logical value specifying whether or not to print the \code{i} indices to track the iterations.} } } } } \section{Coercion}{ \describe{ \item{}{ \code{as.list(x)}: coerce a Vector to a list, where the \code{i}th element of the result corresponds to \code{x[i]}. } } } \seealso{ The \link[S4Vectors]{Vector} class defined and documented in the \pkg{S4Vectors} package. } \keyword{methods} \keyword{classes} IRanges/man/Views-class.Rd0000644000175100017510000001252212607265143016374 0ustar00biocbuildbiocbuild\name{Views-class} \docType{class} \alias{class:Views} \alias{Views-class} \alias{subject} \alias{subject,Views-method} \alias{ranges} \alias{ranges,Views-method} \alias{ranges<-} \alias{ranges<-,Views-method} \alias{length,Views-method} \alias{start,Views-method} \alias{end,Views-method} \alias{width,Views-method} \alias{names,Views-method} \alias{start<-,Views-method} \alias{end<-,Views-method} \alias{width<-,Views-method} \alias{names<-,Views-method} \alias{elementLengths,Views-method} \alias{newViews} \alias{Views} \alias{coerce,Vector,Views-method} \alias{coerce,Views,Ranges-method} \alias{coerce,Views,IRanges-method} \alias{coerce,Views,NormalIRanges-method} \alias{as.matrix,Views-method} \alias{c,Views-method} \alias{trim} \alias{trim,Views-method} \alias{subviews} \alias{subviews,Views-method} \alias{successiveViews} \title{Views objects} \description{ The Views virtual class is a general container for storing a set of views on an arbitrary \link{Vector} object, called the "subject". Its primary purpose is to introduce concepts and provide some facilities that can be shared by the concrete classes that derive from it. Some direct subclasses of the Views class are: \link{RleViews}, \link[XVector]{XIntegerViews} (defined in the XVector package), \link[Biostrings]{XStringViews} (defined in the Biostrings package), etc... } \section{Constructor}{ \describe{ \item{}{ \code{Views(subject, start=NULL, end=NULL, width=NULL, names=NULL)}: This constructor is a generic function with dispatch on argument \code{subject}. Specific methods must be defined for the subclasses of the Views class. For example a method for \link[Biostrings:XString-class]{XString} subjects is defined in the Biostrings package that returns an \link[Biostrings:XStringViews-class]{XStringViews} object. There is no default method. The treatment of the \code{start}, \code{end} and \code{width} arguments is the same as with the \code{\link{IRanges}} constructor, except that, in addition, \code{Views} allows \code{start} to be a \link{Ranges} object. With this feature, \code{Views(subject, IRanges(my_starts, my_ends, my_widths, my_names))} and \code{Views(subject, my_starts, my_ends, my_widths, my_names)} are equivalent (except when \code{my_starts} is itself a \link{Ranges} object). } } } \section{Coercion}{ In the code snippets below, \code{from} is a Views object: \describe{ \item{}{ \code{as(from, "IRanges")}: Creates an \code{IRanges} object containing the view locations in \code{from}. } } } \section{Accessor-like methods}{ All the accessor-like methods defined for \code{IRanges} objects work on Views objects. In addition, the following accessors are defined for Views objects: \describe{ \item{}{ \code{subject(x)}: Return the subject of the views. } } } \section{Subsetting}{ \describe{ \item{}{ \code{x[i]}: Select the views specified by \code{i}. } \item{}{ \code{x[[i]]}: Extracts the view selected by \code{i} as an object of the same class as \code{subject(x)}. Subscript \code{i} can be a single integer or a character string. The result is the subsequence of \code{subject(x)} defined by \code{window(subject(x), start=start(x)[i], end=end(x)[i])} or an error if the view is "out of limits" (i.e. \code{start(x)[i] < 1} or \code{end(x)[i] > length(subject(x))}). } } } \section{Combining}{ \describe{ \item{}{ \code{c(x, ..., ignore.mcols=FALSE)}: Combine \code{Views} objects. They must have the same subject. } } } \section{Other methods}{ \describe{ \item{}{ \code{trim(x, use.names=TRUE)}: Equivalent to \code{restrict(x, start=1L, end=length(subject(x)), keep.all.ranges=TRUE, use.names=use.names)}. } \item{}{ \code{subviews(x, start=NA, end=NA, width=NA, use.names=TRUE)}: \code{start}, \code{end}, and \code{width} arguments must be vectors of integers, eventually with NAs, that contain coordinates relative to the current ranges. Equivalent to \code{trim(narrow(x, start=start, end=end, width=width, use.names=use.names))}. } \item{}{ \code{successiveViews(subject, width, gapwidth=0, from=1)}: Equivalent to \code{Views(subject, successiveIRanges(width, gapwidth, from))}. See \code{?successiveIRanges} for a description of the \code{width}, \code{gapwidth} and \code{from} arguments. } } } \author{H. Pages} \seealso{ \link{IRanges-class}, \link{Vector-class}, \link{IRanges-utils}, \link[XVector]{XVector}. Some direct subclasses of the Views class: \link{RleViews-class}, \link[XVector]{XIntegerViews-class}, \link[XVector]{XDoubleViews-class}, \link[Biostrings]{XStringViews-class}. \code{\link{findOverlaps}}. } \examples{ showClass("Views") # shows (some of) the known subclasses ## Create a set of 4 views on an XInteger subject of length 10: subject <- Rle(3:-6) v1 <- Views(subject, start=4:1, end=4:7) ## Extract the 2nd view: v1[[2]] ## Some views can be "out of limits" v2 <- Views(subject, start=4:-1, end=6) trim(v2) subviews(v2, end=-2) ## See ?`XIntegerViews-class` in the XVector package for more examples. } \keyword{methods} \keyword{classes} IRanges/man/ViewsList-class.Rd0000644000175100017510000000267512607265143017240 0ustar00biocbuildbiocbuild\name{ViewsList-class} \docType{class} \alias{class:ViewsList} \alias{ViewsList-class} \alias{ViewsList} \alias{class:SimpleViewsList} \alias{SimpleViewsList-class} \alias{SimpleViewsList} % accessors \alias{ranges,SimpleViewsList-method} \alias{start,SimpleViewsList-method} \alias{end,SimpleViewsList-method} \alias{width,SimpleViewsList-method} \alias{universe,ViewsList-method} \alias{universe<-,ViewsList-method} % coercion \alias{as.matrix,ViewsList-method} \title{List of Views} \description{An extension of \linkS4class{List} that holds only \linkS4class{Views} objects. } \details{ ViewsList is a virtual class. Specialized subclasses like e.g. \linkS4class{RleViewsList} are useful for storing coverage vectors over a set of spaces (e.g. chromosomes), each of which requires a separate \linkS4class{RleViews} object. As a \linkS4class{Vector} subclass, ViewsList may be annotated with its universe identifier (e.g. a genome) in which all of its spaces exist. As a \linkS4class{List} subclass, ViewsList inherits all the methods available for \linkS4class{List} objects. It also presents an API that is very similar to that of \linkS4class{Views}, where operations are vectorized over the elements and generally return lists. } \author{P. Aboyoun and H. Pages} \seealso{ \link{List-class}, \link{RleViewsList-class}. \code{\link{findOverlaps}}. } \examples{ showClass("ViewsList") } \keyword{methods} \keyword{classes} IRanges/man/coverage-methods.Rd0000644000175100017510000003162212607265143017432 0ustar00biocbuildbiocbuild\name{coverage-methods} \alias{coverage-methods} \alias{coverage} \alias{coverage,Ranges-method} \alias{coverage,Views-method} \alias{coverage,RangesList-method} \alias{coverage,RangedData-method} \title{Coverage of a set of ranges} \description{ For each position in the space underlying a set of ranges, counts the number of ranges that cover it. } \usage{ coverage(x, shift=0L, width=NULL, weight=1L, ...) \S4method{coverage}{Ranges}(x, shift=0L, width=NULL, weight=1L, method=c("auto", "sort", "hash")) \S4method{coverage}{RangesList}(x, shift=0L, width=NULL, weight=1L, method=c("auto", "sort", "hash")) } \arguments{ \item{x}{ A \link{Ranges}, \link{Views}, or \link{RangesList} object. See \code{?`\link[GenomicRanges]{coverage-methods}`} in the \pkg{GenomicRanges} package for \code{coverage} methods for other objects. } \item{shift}{ Specifies how much each range in \code{x} should be shifted before the coverage is computed. \itemize{ \item If \code{x} is a \link{Ranges} or \link{Views} object: \code{shift} must be an integer or numeric vector parallel to \code{x} (will get recycled if necessary) and with no NAs. \item If \code{x} is a \link{RangesList} object: \code{shift} must be a numeric vector or list-like object of the same length as \code{x} (will get recycled if necessary). If it's a numeric vector, it's first turned into a list with \code{as.list}. After recycling, each list element \code{shift[[i]]} must be an integer or numeric vector parallel to \code{x[[i]]} (will get recycled if necessary) and with no NAs. } A positive shift value will shift the corresponding range in \code{x} to the right, and a negative value to the left. } \item{width}{ Specifies the length of the returned coverage vector(s). \itemize{ \item If \code{x} is a \link{Ranges} object: \code{width} must be \code{NULL} (the default), an NA, or a single non-negative integer. After being shifted, the ranges in \code{x} are always clipped on the left to keep only their positive portion i.e. their intersection with the [1, +inf) interval. If \code{width} is a single non-negative integer, then they're also clipped on the right to keep only their intersection with the [1, width] interval. In that case \code{coverage} returns a vector of length \code{width}. Otherwise, it returns a vector that extends to the last position in the underlying space covered by the shifted ranges. \item If \code{x} is a \link{Views} object: Same as for a \link{Ranges} object, except that, if \code{width} is \code{NULL} then it's treated as if it was \code{length(subject(x))}. \item If \code{x} is a \link{RangesList} object: \code{width} must be \code{NULL} or an integer vector parallel to \code{x} (i.e. with one element per list element in \code{x}). If not \code{NULL}, the vector must contain NAs or non-negative integers and it will get recycled to the length of \code{x} if necessary. If \code{NULL}, it is replaced with \code{NA} and recycled to the length of \code{x}. Finally \code{width[i]} is used to compute the coverage vector for \code{x[[i]]} and is therefore treated like explained above (when \code{x} is a \link{Ranges} object). } } \item{weight}{ Assigns a weight to each range in \code{x}. \itemize{ \item If \code{x} is a \link{Ranges} or \link{Views} object: \code{weight} must be an integer or numeric vector parallel to \code{x} (will get recycled if necessary). \item If \code{x} is a \link{RangesList} object: \code{weight} must be a numeric vector or list-like object of the same length as \code{x} (will get recycled if necessary). If it's a numeric vector, it's first turned into a list with \code{as.list}. After recycling, each list element \code{weight[[i]]} must be an integer or numeric vector parallel to \code{x[[i]]} (will get recycled if necessary). } If \code{weight} is an integer vector or list-like object of integer vectors, the coverage vector(s) will be returned as integer-\link{Rle} object(s). If it's a numeric vector or list-like object of numeric vectors, the coverage vector(s) will be returned as numeric-\link{Rle} object(s). Alternatively, \code{weight} can also be specified as a single string naming a metadata column in \code{x} (i.e. a column in \code{mcols(x)}) to be used as the \code{weight} vector. } \item{method}{ If \code{method} is set to \code{"sort"}, then \code{x} is sorted previous to the calculation of the coverage. If \code{method} is set to \code{hash}, then \code{x} is hashed directly to a vector of length \code{width} without previous sorting. The \code{"hash"} method is faster than the \code{"sort"} method when \code{x} is large (i.e. contains a lot of ranges). When \code{x} is small and \code{width} is big (e.g. \code{x} represents a small set of reads aligned to a big chromosome), then \code{method="sort"} is faster and uses less memory than \code{method="hash"}. Using \code{method="auto"} selects the best method based on \code{length(x)} and \code{width}. } \item{...}{ Further arguments to be passed to or from other methods. } } \value{ If \code{x} is a \link{Ranges} or \link{Views} object: An integer- or numeric-\link{Rle} object depending on whether \code{weight} is an integer or numeric vector. If \code{x} is a \link{RangesList} object: An \link{RleList} object with one coverage vector per list element in \code{x}, and with \code{x} names propagated to it. The i-th coverage vector can be either an integer- or numeric-\link{Rle} object, depending on the type of \code{weight[[i]]} (after \code{weight} has gone thru \code{as.list} and recycling, like described previously). } \author{H. Pages and P. Aboyoun} \seealso{ \itemize{ \item \link[GenomicRanges]{coverage-methods} in the \pkg{GenomicRanges} package for more \code{coverage} methods. \item The \code{\link{slice}} function for slicing the \link{Rle} or \link{RleList} object returned by \code{coverage}. \item The \link{Ranges}, \link{RangesList}, \link{Rle}, and \link{RleList} classes. } } \examples{ ## --------------------------------------------------------------------- ## A. COVERAGE OF AN IRanges OBJECT ## --------------------------------------------------------------------- x <- IRanges(start=c(-2L, 6L, 9L, -4L, 1L, 0L, -6L, 10L), width=c( 5L, 0L, 6L, 1L, 4L, 3L, 2L, 3L)) coverage(x) coverage(x, shift=7) coverage(x, shift=7, width=27) coverage(x, shift=c(-4, 2)) # 'shift' gets recycled coverage(x, shift=c(-4, 2), width=12) coverage(x, shift=-max(end(x))) coverage(restrict(x, 1, 10)) coverage(reduce(x), shift=7) coverage(gaps(shift(x, 7), start=1, end=27)) ## With weights: coverage(x, weight=as.integer(10^(0:7))) # integer-Rle coverage(x, weight=c(2.8, -10)) # numeric-Rle, 'shift' gets recycled ## --------------------------------------------------------------------- ## B. SOME MATHEMATICAL PROPERTIES OF THE coverage() FUNCTION ## --------------------------------------------------------------------- ## PROPERTY 1: The coverage vector is not affected by reordering the ## input ranges: set.seed(24) x <- IRanges(sample(1000, 40, replace=TRUE), width=17:10) cvg0 <- coverage(x) stopifnot(identical(coverage(sample(x)), cvg0)) ## Of course, if the ranges are shifted and/or assigned weights, then ## this doesn't hold anymore, unless the 'shift' and/or 'weight' ## arguments are reordered accordingly. ## PROPERTY 2: The coverage of the concatenation of 2 Ranges objects 'x' ## and 'y' is the sum of the 2 individual coverage vectors: y <- IRanges(sample(-20:280, 36, replace=TRUE), width=28) stopifnot(identical(coverage(c(x, y), width=100), coverage(x, width=100) + coverage(y, width=100))) ## Note that, because adding 2 vectors in R recycles the shortest to ## the length of the longest, the following is generally FALSE: identical(coverage(c(x, y)), coverage(x) + coverage(y)) # FALSE ## It would only be TRUE if the 2 coverage vectors we add had the same ## length, which would only happen by chance. By using the same 'width' ## value when we computed the 2 coverages previously, we made sure they ## had the same length. ## Because of properties 1 & 2, we have: x1 <- x[c(TRUE, FALSE)] # pick up 1st, 3rd, 5th, etc... ranges x2 <- x[c(FALSE, TRUE)] # pick up 2nd, 4th, 6th, etc... ranges cvg1 <- coverage(x1, width=100) cvg2 <- coverage(x2, width=100) stopifnot(identical(coverage(x, width=100), cvg1 + cvg2)) ## PROPERTY 3: Multiplying the weights by a scalar has the effect of ## multiplying the coverage vector by the same scalar: weight <- runif(40) cvg3 <- coverage(x, weight=weight) stopifnot(all.equal(coverage(x, weight=-2.68 * weight), -2.68 * cvg3)) ## Because of properties 1 & 2 & 3, we have: stopifnot(identical(coverage(x, width=100, weight=c(5L, -11L)), 5L * cvg1 - 11L * cvg2)) ## PROPERTY 4: Using the sum of 2 weight vectors produces the same ## result as using the 2 weight vectors separately and summing the ## 2 results: weight2 <- 10 * runif(40) + 3.7 stopifnot(all.equal(coverage(x, weight=weight + weight2), cvg3 + coverage(x, weight=weight2))) ## PROPERTY 5: Repeating any input range N number of times is ## equivalent to multiplying its assigned weight by N: times <- sample(0:10L, length(x), replace=TRUE) stopifnot(all.equal(coverage(rep(x, times), weight=rep(weight, times)), coverage(x, weight=weight * times))) ## In particular, if 'weight' is not supplied: stopifnot(identical(coverage(rep(x, times)), coverage(x, weight=times))) ## PROPERTY 6: If none of the input range actually gets clipped during ## the "shift and clip" process, then: ## ## sum(cvg) = sum(width(x) * weight) ## stopifnot(sum(cvg3) == sum(width(x) * weight)) ## In particular, if 'weight' is not supplied: stopifnot(sum(cvg0) == sum(width(x))) ## Note that this property is sometimes used in the context of a ## ChIP-Seq analysis to estimate "the number of reads in a peak", that ## is, the number of short reads that belong to a peak in the coverage ## vector computed from the genomic locations (a.k.a. genomic ranges) ## of the aligned reads. Because of property 6, the number of reads in ## a peak is approximately the area under the peak divided by the short ## read length. ## PROPERTY 7: If 'weight' is not supplied, then disjoining or reducing ## the ranges before calling coverage() has the effect of "shaving" the ## coverage vector at elevation 1: table(cvg0) shaved_cvg0 <- cvg0 runValue(shaved_cvg0) <- pmin(runValue(cvg0), 1L) table(shaved_cvg0) stopifnot(identical(coverage(disjoin(x)), shaved_cvg0)) stopifnot(identical(coverage(reduce(x)), shaved_cvg0)) ## --------------------------------------------------------------------- ## C. SOME SANITY CHECKS ## --------------------------------------------------------------------- dummy.coverage <- function(x, shift=0L, width=NULL) { y <- unlist(shift(x, shift)) if (is.null(width)) width <- max(c(0L, y)) Rle(tabulate(y, nbins=width)) } check_real_vs_dummy <- function(x, shift=0L, width=NULL) { res1 <- coverage(x, shift=shift, width=width) res2 <- dummy.coverage(x, shift=shift, width=width) stopifnot(identical(res1, res2)) } check_real_vs_dummy(x) check_real_vs_dummy(x, shift=7) check_real_vs_dummy(x, shift=7, width=27) check_real_vs_dummy(x, shift=c(-4, 2)) check_real_vs_dummy(x, shift=c(-4, 2), width=12) check_real_vs_dummy(x, shift=-max(end(x))) ## With a set of distinct single positions: x3 <- IRanges(sample(50000, 20000), width=1) stopifnot(identical(sort(start(x3)), which(coverage(x3) != 0L))) ## --------------------------------------------------------------------- ## D. COVERAGE OF AN IRangesList OBJECT ## --------------------------------------------------------------------- x <- IRangesList(A=IRanges(3*(4:-1), width=1:3), B=IRanges(2:10, width=5)) cvg <- coverage(x) cvg stopifnot(identical(cvg[[1]], coverage(x[[1]]))) stopifnot(identical(cvg[[2]], coverage(x[[2]]))) coverage(x, width=c(50, 9)) coverage(x, width=c(NA, 9)) coverage(x, width=9) # 'width' gets recycled ## Each list element in 'shift' and 'weight' gets recycled to the length ## of the corresponding element in 'x'. weight <- list(as.integer(10^(0:5)), -0.77) cvg2 <- coverage(x, weight=weight) cvg2 # 1st coverage vector is an integer-Rle, 2nd is a numeric-Rle identical(mapply(coverage, x=x, weight=weight), as.list(cvg2)) } \keyword{methods} \keyword{utilities} IRanges/man/expand-methods.Rd0000644000175100017510000000426612607265143017122 0ustar00biocbuildbiocbuild\name{expand} \alias{expand} \alias{expand,DataFrame-method} \alias{expand,Vector-method} \title{The expand method for uncompressing compressed data columns} \description{ Expand an object with compressed columns such that all compressed values are represented as separate rows. } \usage{ \S4method{expand}{DataFrame}(x, colnames, keepEmptyRows = FALSE) } \arguments{ \item{x}{ A \code{DataFrame} containing some columns that are compressed (e.g., \code{CompressedCharacterList}), or a \code{Vector} with compressed columns in \code{mcols(x)}. } \item{colnames}{ A \code{character} or \code{numeric} vector containing the names or indices of the compressed columns to expand. The order of expansion is controlled by the column order in this vector. This defaults to all of the recursive (list-like) columns in \code{x} (or \code{mcols(x)}). } \item{keepEmptyRows}{ A \code{logical} indicating if rows containing empty values in the specified \code{colnames} should be retained or dropped. When \code{TRUE}, empty values are set to NA and all rows are kept. When \code{FALSE}, rows with empty values in the \code{colnames} columns are dropped. } } \value{ A \code{DataFrame} that has been expanded row-wise to match the dimension of the uncompressed columns. } \author{Herve Pages and Marc Carlson} \seealso{ \link{DataFrame-class} } \examples{ aa <- CharacterList("a", paste0("d", 1:2), paste0("b", 1:3), c(), "c") bb <- CharacterList(paste0("sna", 1:2),"foo", paste0("bar",1:3),c(),"hica") df <- DataFrame(aa=aa, bb=bb, cc=11:15) ## expand by all list-like columns (aa, bb), dropping empty rows expand(df) ## expand the aa column only, and keep rows adjacent to empty values expand(df, colnames="aa", keepEmptyRows=TRUE) ## expand the aa column only but do not keep rows expand(df, colnames="aa", keepEmptyRows=FALSE) ## expand the aa and then the bb column, but ## keeping rows next to empty compressed values expand(df, colnames=c("aa","bb"), keepEmptyRows=TRUE) ## expand the bb and then the aa column, but don't keep rows adjacent to ## empty values from bb and aa expand(df, colnames=c("aa","bb"), keepEmptyRows=FALSE) } \keyword{methods} IRanges/man/extractList.Rd0000644000175100017510000001340712607265143016505 0ustar00biocbuildbiocbuild\name{extractList} \alias{relistToClass} \alias{relistToClass,ANY-method} \alias{relistToClass,DataFrame-method} \alias{relistToClass,data.frame-method} \alias{relist,ANY,PartitioningByEnd-method} \alias{relist,ANY,List-method} \alias{relist,Vector,list-method} \alias{relist,ANY,PartitioningByEnd-method} \alias{splitAsList} \alias{splitAsList,ANY,List} \alias{splitAsList,ANY,Rle} \alias{splitAsList,ANY,vectorORfactor} \alias{extractList} \alias{extractList,ANY,ANY-method} \alias{extractList,ANY-method} \title{Group elements of a vector-like object into a list-like object} \description{ \code{relist} and \code{split} are 2 common ways of grouping the elements of a vector-like object into a list-like object. The \pkg{IRanges} and \pkg{S4Vectors} packages define \code{relist} and \code{split} methods that operate on a \link{Vector} object and return a \link{List} object. Note that the \code{\link[S4Vectors]{split}} methods defined in \pkg{S4Vectors} delegate to the \code{splitAsList} function defined in \pkg{IRanges} and documented below. Because \code{relist} and \code{split} both impose restrictions on the kind of grouping that they support (e.g. every element in the input object needs to go in a group and can only go in one group), the \pkg{IRanges} package introduces the \code{extractList} generic function for performing \emph{arbitrary} groupings. } \usage{ ## relist() ## -------- \S4method{relist}{ANY,List}(flesh, skeleton) \S4method{relist}{Vector,list}(flesh, skeleton) ## splitAsList() ## ------------- splitAsList(x, f, drop=FALSE, ...) ## extractList() ## ------------- extractList(x, i) ## relistToClass() ## --------------- relistToClass(x) } \arguments{ \item{flesh, x}{ A vector-like object. } \item{skeleton}{ A list-like object. Only the "shape" (i.e. element lengths) of \code{skeleton} matters. Its exact content is ignored. } \item{f}{ An atomic vector or a factor (possibly in \link{Rle} form). } \item{drop}{ Logical indicating if levels that do not occur should be dropped (if \code{f} is a factor). } \item{i}{ A list-like object. Unlike for \code{skeleton}, the content here matters (see Details section below). Note that \code{i} can be a \link{Ranges} object (a particular type of list-like object), and, in that case, \code{extractList} is particularly fast (this is a common use case). } \item{...}{ Arguments to pass to methods. } } \details{ \code{relist}, \code{split}, and \code{extractList} have in common that they return a list-like value where each list element has the same class as the original vector-like object. Thus they need to be able to select the appropriate \link{List} concrete subclass to use for this returned value. This selection is performed by \code{relistToClass} and is based only on the class of the original object. By default, \code{extractList(x, i)} is equivalent to: \preformatted{ relist(x[unlist(i)], i) } An exception is made when \code{x} is a data-frame-like object. In that case \code{x} is subsetted along the rows, that is, \code{extractList(x, i)} is equivalent to: \preformatted{ relist(x[unlist(i), ], i) } This is more or less how the default method is implemented, except for some optimizations when \code{i} is a \link{Ranges} object. \code{relist} and \code{split} (or \code{splitAsList}) can be seen as special cases of \code{extractList}: \preformatted{ relist(flesh, skeleton) is equivalent to extractList(flesh, PartitioningByEnd(skeleton)) split(x, f) is equivalent to extractList(x, split(seq_along(f), f)) } It is good practise to use \code{extractList} only for cases not covered by \code{relist} or \code{split}. Whenever possible, using \code{relist} or \code{split} is preferred as they will always perform more efficiently. In addition their names carry meaning and are familiar to most R users/developers so they'll make your code easier to read/understand. Note that the transformation performed by \code{relist} or \code{split} is always reversible (via \code{unlist} and \code{unsplit}, respectively), but the not the transformation performed by \code{extractList} (in general). } \value{ The \code{relist} methods behave like \code{utils::relist} except that they return a \link{List} object. If \code{skeleton} has names, then they are propagated to the returned value. \code{splitAsList} behaves like \code{base::split} except that the former returns a \link{List} object instead of an ordinary list. \code{extractList} returns a list-like object parallel to \code{i} and with the same "shape" as \code{i} (i.e. same element lengths). If \code{i} has names, then they are propagated to the returned value. All these functions (except \code{relistToClass}) return a list-like object where the list elements have the same class as \code{x}. \code{relistToClass} gives the exact class of the returned object. } \author{ H. Pages } \seealso{ \itemize{ \item The \code{\link[base]{unlist}} and \code{\link[utils]{relist}} functions in the \pkg{base} and \pkg{utils} packages, respectively. \item The \code{\link[base]{split}} and \code{\link[base]{unsplit}} functions in the \pkg{base} package. \item The \code{\link[S4Vectors]{split}} methods defined in the \pkg{S4Vectors} package. \item \link[S4Vectors]{Vector}, \link[S4Vectors]{List}, \link[S4Vectors]{Rle}, and \link[S4Vectors]{DataFrame} objects in the \pkg{S4Vectors} package. \item \link{Ranges} objects. } } \examples{ ## On an Rle object: x <- Rle(101:105, 6:2) i <- IRanges(6:10, 16:12, names=letters[1:5]) extractList(x, i) ## On a DataFrame object: df <- DataFrame(X=x, Y=LETTERS[1:20]) extractList(df, i) } \keyword{manip} IRanges/man/findOverlaps-methods.Rd0000644000175100017510000003712712607265143020301 0ustar00biocbuildbiocbuild\name{findOverlaps-methods} \alias{findOverlaps-methods} \alias{findOverlaps} \alias{findOverlaps,Ranges,IntervalTree-method} \alias{findOverlaps,NCList,Ranges-method} \alias{findOverlaps,Ranges,NCList-method} \alias{findOverlaps,Ranges,Ranges-method} \alias{findOverlaps,Vector,missing-method} \alias{findOverlaps,integer,Ranges-method} \alias{findOverlaps,Views,Views-method} \alias{findOverlaps,Views,Vector-method} \alias{findOverlaps,Vector,Views-method} \alias{findOverlaps,RangesList,IntervalForest-method} \alias{findOverlaps,RangesList,RangesList-method} \alias{findOverlaps,ViewsList,ViewsList-method} \alias{findOverlaps,ViewsList,Vector-method} \alias{findOverlaps,Vector,ViewsList-method} \alias{findOverlaps,RangedData,RangedData-method} \alias{findOverlaps,RangedData,RangesList-method} \alias{findOverlaps,RangesList,RangedData-method} \alias{countOverlaps} \alias{countOverlaps,Ranges,NCList-method} \alias{countOverlaps,NCList,Ranges-method} \alias{countOverlaps,ANY,Vector-method} \alias{countOverlaps,ANY,missing-method} \alias{countOverlaps,RangesList,RangesList-method} \alias{countOverlaps,RangesList,IntervalForest-method} \alias{countOverlaps,ViewsList,ViewsList-method} \alias{countOverlaps,ViewsList,Vector-method} \alias{countOverlaps,Vector,ViewsList-method} \alias{countOverlaps,RangedData,RangedData-method} \alias{countOverlaps,RangedData,RangesList-method} \alias{countOverlaps,RangesList,RangedData-method} \alias{overlapsAny} \alias{overlapsAny,Ranges,Ranges-method} \alias{overlapsAny,Views,Views-method} \alias{overlapsAny,Views,Vector-method} \alias{overlapsAny,Vector,Views-method} \alias{overlapsAny,RangesList,RangesList-method} \alias{overlapsAny,RangesList,IntervalForest-method} \alias{overlapsAny,ViewsList,ViewsList-method} \alias{overlapsAny,ViewsList,Vector-method} \alias{overlapsAny,Vector,ViewsList-method} \alias{overlapsAny,RangedData,RangedData-method} \alias{overlapsAny,RangedData,RangesList-method} \alias{overlapsAny,RangesList,RangedData-method} \alias{overlapsAny,Vector,missing-method} \alias{\%over\%} \alias{\%within\%} \alias{\%outside\%} \alias{subsetByOverlaps} \alias{subsetByOverlaps,Vector,Vector-method} \alias{subsetByOverlaps,RangedData,RangedData-method} \alias{subsetByOverlaps,RangedData,RangesList-method} \alias{subsetByOverlaps,RangesList,RangedData-method} \alias{mergeByOverlaps} \alias{ranges,Hits-method} \title{Finding overlapping ranges} \description{ Various methods for finding/counting interval overlaps between two "range-based" objects: a query and a subject. NOTE: This man page describes the methods that operate on \link{Ranges}, \link{Views}, \link{RangesList}, or \link{ViewsList} objects. See \code{?`\link[GenomicRanges]{findOverlaps,GenomicRanges,GenomicRanges-method}`} in the \pkg{GenomicRanges} package for methods that operate on \link[GenomicRanges]{GenomicRanges} or \link[GenomicRanges]{GRangesList} objects. } \usage{ findOverlaps(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), select=c("all", "first", "last", "arbitrary"), algorithm=c("nclist", "intervaltree"), ...) countOverlaps(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) overlapsAny(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) query \%over\% subject query \%within\% subject query \%outside\% subject subsetByOverlaps(query, subject, maxgap=0L, minoverlap=1L, type=c("any", "start", "end", "within", "equal"), algorithm=c("nclist", "intervaltree"), ...) mergeByOverlaps(query, subject, ...) \S4method{ranges}{Hits}(x, query, subject) } \arguments{ \item{query, subject}{ Each of them can be a \link{Ranges}, \link{Views}, \link{RangesList}, \link{ViewsList}, or \link{RangedData} object. In addition, if \code{subject} is a \link{Ranges} object, \code{query} can be an integer vector to be converted to length-one ranges. If \code{query} is a \link{RangesList} or \link{RangedData}, \code{subject} must be a \link{RangesList} or \link{RangedData}. If both lists have names, each element from the subject is paired with the element from the query with the matching name, if any. Otherwise, elements are paired by position. The overlap is then computed between the pairs as described below. If \code{subject} is omitted, \code{query} is queried against itself. In this case, and only this case, the \code{ignoreSelf} and \code{ignoreRedundant} arguments are allowed. By default, the result will contain hits for each range against itself, and if there is a hit from A to B, there is also a hit for B to A. If \code{ignoreSelf} is \code{TRUE}, all self matches are dropped. If \code{ignoreRedundant} is \code{TRUE}, only one of A->B and B->A is returned. } \item{maxgap, minoverlap}{ Intervals with a separation of \code{maxgap} or less and a minimum of \code{minoverlap} overlapping positions, allowing for \code{maxgap}, are considered to be overlapping. \code{maxgap} should be a scalar, non-negative, integer. \code{minoverlap} should be a scalar, positive integer. } \item{type}{ By default, any overlap is accepted. By specifying the \code{type} parameter, one can select for specific types of overlap. The types correspond to operations in Allen's Interval Algebra (see references). If \code{type} is \code{start} or \code{end}, the intervals are required to have matching starts or ends, respectively. While this operation seems trivial, the naive implementation using \code{outer} would be much less efficient. Specifying \code{equal} as the type returns the intersection of the \code{start} and \code{end} matches. If \code{type} is \code{within}, the query interval must be wholly contained within the subject interval. Note that all matches must additionally satisfy the \code{minoverlap} constraint described above. With the old findOverlaps/countOverlaps implementation based on Interval Trees (\code{algorithm="intervaltree"}), the \code{maxgap} parameter has special meaning with the special overlap types. For \code{start}, \code{end}, and \code{equal}, it specifies the maximum difference in the starts, ends or both, respectively. For \code{within}, it is the maximum amount by which the query may be wider than the subject. With the new implementation based on Nested Containment Lists (\code{algorithm="nclist"}), this special meaning is still being used but only when \code{type} is set to \code{start} or \code{end}. See \code{?NCList} for more information about this change and other differences between the new and old findOverlaps/countOverlaps implementations. See the \code{algorithm} argument below for how to switch between the 2 implementations. } \item{select}{ If \code{query} is a \link{Ranges} or \link{Views} object: When \code{select} is \code{"all"} (the default), the results are returned as a \link{Hits} object. Otherwise the returned value is an integer vector parallel to \code{query} (i.e. same length) containing the first, last, or arbitrary overlapping interval in \code{subject}, with \code{NA} indicating intervals that did not overlap any intervals in \code{subject}. If \code{query} is a \link{RangesList}, \link{ViewsList}, or \link{RangedData} object: When \code{select} is \code{"all"} (the default), the results are returned as a \link{HitsList} object. Otherwise the returned value depends on the \code{drop} argument. When \code{select != "all" && !drop}, an \link{IntegerList} is returned, where each element of the result corresponds to a space in \code{query}. When \code{select != "all" && drop}, an integer vector is returned containing indices that are offset to align with the unlisted \code{query}. } \item{algorithm}{ Can be \code{"nclist"} (the default) or \code{"intervaltree"}. This argument was added in BioC 3.1 to facilitate the transition between the new findOverlaps/countOverlaps implementation based on Nested Containment Lists and the old implementation based on Interval Trees. See \code{?\link{NCList}} and \code{?\link{IntervalTree}} for more information about these implementations.. Note that the old implementation is defunct starting with BioC 3.2. The \code{algorithm} argument will be removed in BioC 3.3. } \item{...}{ Further arguments to be passed to or from other methods: \itemize{ \item \code{drop}: Supported only when \code{query} is a \link{RangesList}, \link{ViewsList}, or \link{RangedData} object. \code{FALSE} by default. See \code{select} argument above for the details. \item \code{ignoreSelf}, \code{ignoreRedundant}: When \code{subject} is omitted, the \code{ignoreSelf} and \code{ignoreRedundant} arguments (both \code{FALSE} by default) are allowed. See \code{query} and \code{subject} arguments above for the details. } } \item{x}{ \link{Hits} object returned by \code{findOverlaps}. } } \details{ A common type of query that arises when working with intervals is finding which intervals in one set overlap those in another. The simplest approach is to call the \code{findOverlaps} function on a \link{Ranges} or other object with range information (aka "range-based object"). } \value{ For \code{findOverlaps}: see \code{select} argument above. For \code{countOverlaps}: the overlap hit count for each range in \code{query} using the specified \code{findOverlaps} parameters. For \link{RangesList} objects, it returns an \link{IntegerList} object. \code{overlapsAny} finds the ranges in \code{query} that overlap any of the ranges in \code{subject}. For \link{Ranges} or \link{Views} objects, it returns a logical vector of length equal to the number of ranges in \code{query}. For \link{RangesList}, \link{RangedData}, or \link{ViewsList} objects, it returns a \link{LogicalList} object, where each element of the result corresponds to a space in \code{query}. \code{\%over\%} and \code{\%within\%} are convenience wrappers for the 2 most common use cases. Currently defined as \code{`\%over\%` <- function(query, subject) overlapsAny(query, subject)} and \code{`\%within\%` <- function(query, subject) overlapsAny(query, subject, type="within")}. \code{\%outside\%} is simply the inverse of \code{\%over\%}. \code{subsetByOverlaps} returns the subset of \code{query} that has an overlap hit with a range in \code{subject} using the specified \code{findOverlaps} parameters. \code{mergeByOverlaps} computes the overlap between query and subject according to the arguments in \code{\dots}. It then extracts the corresponding hits from each object and returns a \code{DataFrame} containing one column for the query and one for the subject, as well as any \code{mcols} that were present on either object. The query and subject columns are named by quoting and deparsing the corresponding argument. \code{ranges(x, query, subject)} returns a \code{Ranges} of the same length as \link{Hits} object \code{x} holding the regions of intersection between the overlapping ranges in objects \code{query} and \code{subject}, which should be the same query and subject used in the call to \code{findOverlaps} that generated \code{x}. } \references{ Allen's Interval Algebra: James F. Allen: Maintaining knowledge about temporal intervals. In: Communications of the ACM. 26/11/1983. ACM Press. S. 832-843, ISSN 0001-0782 } \author{Michael Lawrence and H. Pages} \seealso{ \itemize{ \item The \link{Hits} and \link{HitsList} classes for representing a set of hits between 2 vector-like objects. \item \link[GenomicRanges]{findOverlaps,GenomicRanges,GenomicRanges-method} in the \pkg{GenomicRanges} package for methods that operate on \link[GenomicRanges]{GRanges} or \link[GenomicRanges]{GRangesList} objects. \item The \link{NCList} class and constructor. \item The \link{IntervalTree} and \link{IntervalForest} classes and constructors (defunct). \item The \link{Ranges}, \link{Views}, \link{RangesList}, \link{ViewsList}, and \link{RangedData} classes. \item The \link{IntegerList} and \link{LogicalList} classes. } } \examples{ query <- IRanges(c(1, 4, 9), c(5, 7, 10)) subject <- IRanges(c(2, 2, 10), c(2, 3, 12)) ## --------------------------------------------------------------------- ## findOverlaps() ## --------------------------------------------------------------------- ## at most one hit per query findOverlaps(query, subject, select="first") findOverlaps(query, subject, select="last") findOverlaps(query, subject, select="arbitrary") ## overlap even if adjacent only ## (FIXME: the gap between 2 adjacent ranges should be still considered ## 0. So either we have an argument naming problem, or we should modify ## the handling of the 'maxgap' argument so that the user would need to ## specify maxgap=0L to obtain the result below.) findOverlaps(query, subject, maxgap=1L) ## shortcut findOverlaps(query, subject) query <- IRanges(c(1, 4, 9), c(5, 7, 10)) subject <- IRanges(c(2, 2), c(5, 4)) ## one Ranges with itself findOverlaps(query) ## single points as query subject <- IRanges(c(1, 6, 13), c(4, 9, 14)) findOverlaps(c(3L, 7L, 10L), subject, select="first") ## alternative overlap types query <- IRanges(c(1, 5, 3, 4), width=c(2, 2, 4, 6)) subject <- IRanges(c(1, 3, 5, 6), width=c(4, 4, 5, 4)) findOverlaps(query, subject, type="start") findOverlaps(query, subject, type="start", maxgap=1L) findOverlaps(query, subject, type="end", select="first") ov <- findOverlaps(query, subject, type="within", maxgap=1L) ov ## --------------------------------------------------------------------- ## overlapsAny() ## --------------------------------------------------------------------- overlapsAny(query, subject, type="start") overlapsAny(query, subject, type="end") query \%over\% subject # same as overlapsAny(query, subject) query \%within\% subject # same as overlapsAny(query, subject, # type="within") ## --------------------------------------------------------------------- ## "ranges" METHOD FOR Hits OBJECTS ## --------------------------------------------------------------------- ## extract the regions of intersection between the overlapping ranges ranges(ov, query, subject) ## --------------------------------------------------------------------- ## Using RangesList objects ## --------------------------------------------------------------------- query <- IRanges(c(1, 4, 9), c(5, 7, 10)) qpartition <- factor(c("a","a","b")) qlist <- split(query, qpartition) subject <- IRanges(c(2, 2, 10), c(2, 3, 12)) spartition <- factor(c("a","a","b")) slist <- split(subject, spartition) ## at most one hit per query findOverlaps(qlist, slist, select="first") findOverlaps(qlist, slist, select="last") findOverlaps(qlist, slist, select="arbitrary") query <- IRanges(c(1, 5, 3, 4), width=c(2, 2, 4, 6)) qpartition <- factor(c("a","a","b","b")) qlist <- split(query, qpartition) subject <- IRanges(c(1, 3, 5, 6), width=c(4, 4, 5, 4)) spartition <- factor(c("a","a","b","b")) slist <- split(subject, spartition) overlapsAny(qlist, slist, type="start") overlapsAny(qlist, slist, type="end") qlist %over% slist subsetByOverlaps(qlist, slist) countOverlaps(qlist, slist) } \keyword{methods} IRanges/man/inter-range-methods.Rd0000644000175100017510000002674312607265143020062 0ustar00biocbuildbiocbuild\name{inter-range-methods} \alias{inter-range-methods} \alias{range} \alias{range,Ranges-method} \alias{range,RangesList-method} \alias{range,CompressedIRangesList-method} \alias{range,IntervalForest-method} \alias{range,RangedData-method} \alias{reduce} \alias{reduce,IRanges-method} \alias{reduce,Ranges-method} \alias{reduce,Views-method} \alias{reduce,RangesList-method} \alias{reduce,CompressedIRangesList-method} \alias{reduce,IntervalForest-method} \alias{reduce,RangedData-method} \alias{gaps} \alias{gaps,IRanges-method} \alias{gaps,Ranges-method} \alias{gaps,Views-method} \alias{gaps,RangesList-method} \alias{gaps,IntervalForest-method} \alias{gaps,CompressedIRangesList-method} \alias{gaps,MaskCollection-method} \alias{disjoin} \alias{disjoin,Ranges-method} \alias{disjoin,RangesList-method} \alias{disjoin,IntervalForest-method} \alias{disjoin,CompressedIRangesList-method} \alias{disjointBins} \alias{disjointBins,Ranges-method} \alias{disjointBins,RangesList-method} \title{Inter range transformations of a Ranges, Views, RangesList, MaskCollection, or RangedData object} \description{ Except for \code{disjointBins()}, all the transformations described in this man page are \emph{endomorphisms} that operate on a single "range-based" object, that is, they transform the ranges contained in the input object and return them in an object of the \emph{same class} as the input object. Range-based endomorphisms are grouped in 2 categories: \enumerate{ \item Intra range transformations like \code{\link{shift}()} that transform each range individually (and independently of the other ranges) and return an object of the \emph{same length} as the input object. Those transformations are described in the \link{intra-range-methods} man page (see \code{?`\link{intra-range-methods}`}). \item Inter range transformations like \code{reduce()} that transform all the ranges together as a set to produce a new set of ranges and return an object not necessarily of the same length as the input object. Those transformations are described in this man page. } } \usage{ ## range() ## ------- \S4method{range}{Ranges}(x, ..., na.rm=FALSE) \S4method{range}{RangesList}(x, ..., na.rm=FALSE) ## reduce() ## -------- reduce(x, ...) \S4method{reduce}{Ranges}(x, drop.empty.ranges=FALSE, min.gapwidth=1L, with.revmap=FALSE, with.inframe.attrib=FALSE) \S4method{reduce}{Views}(x, drop.empty.ranges=FALSE, min.gapwidth=1L, with.revmap=FALSE, with.inframe.attrib=FALSE) \S4method{reduce}{RangesList}(x, drop.empty.ranges=FALSE, min.gapwidth=1L, with.revmap=FALSE, with.inframe.attrib=FALSE) \S4method{reduce}{RangedData}(x, by=character(), drop.empty.ranges=FALSE, min.gapwidth=1L, with.inframe.attrib=FALSE) ## gaps() ## ------ gaps(x, start=NA, end=NA) ## disjoin() ## --------- disjoin(x, ...) ## disjointBins() ## -------------- disjointBins(x, ...) } \arguments{ \item{x}{ A \link{Ranges}, \link{Views}, \link{RangesList}, \link{MaskCollection}, or \link{RangedData} object. } \item{...}{ For \code{range}, additional \code{Ranges} or \code{RangesList} to consider. } \item{na.rm}{Ignored.} \item{drop.empty.ranges}{ \code{TRUE} or \code{FALSE}. Should empty ranges be dropped? } \item{min.gapwidth}{ Ranges separated by a gap of at least \code{min.gapwidth} positions are not merged. } \item{with.revmap}{ \code{TRUE} or \code{FALSE}. Should the mapping from reduced to original ranges be stored in the returned object? If yes, then it is stored as metadata column \code{"revmap"} of type \link{IntegerList}. } \item{with.inframe.attrib}{ \code{TRUE} or \code{FALSE}. For internal use. } \item{by}{ A character vector. } \item{start, end}{ \itemize{ \item If \code{x} is a \link{Ranges} or \link{Views} object: A single integer or \code{NA}. Use these arguments to specify the interval of reference i.e. which interval the returned gaps should be relative to. \item If \code{x} is a \link{RangesList} object: Integer vectors containing the coordinate bounds for each \link{RangesList} top-level element. } } } \details{ Here we start by describing how each transformation operates on a \link{Ranges} object \code{x}. \code{range} first combines \code{x} and the arguments in \code{...}. If the combined \link{IRanges} object contains at least 1 range, then \code{range} returns an \code{IRanges} instance with a single range, from the minimum start to the maximum end of the combined object. Otherwise (i.e. if the combined object contains no range), \code{IRanges()} is returned (i.e. an \link{IRanges} instance of length 0). If \code{x} is a \link{RangedData} object, then \code{range} returns a \code{RangesList} object resulting from calling \code{range(ranges(x))}, i.e. the bounds of the ranges in each space. \code{reduce} first orders the ranges in \code{x} from left to right, then merges the overlapping or adjacent ones. If \code{x} is a \link{RangedData} object, \code{reduce} merges the ranges in each of the spaces after grouping by the \code{by} values columns and returns the result as a \code{RangedData} containing the reduced ranges and the \code{by} value columns. \code{gaps} returns the "normal" \link{Ranges} object representing the set of integers that remain after the set of integers represented by \code{x} has been removed from the interval specified by the \code{start} and \code{end} arguments. If \code{x} is a \link{Views} object, then \code{start=NA} and \code{end=NA} are interpreted as \code{start=1} and \code{end=length(subject(x))}, respectively, so, if \code{start} and \code{end} are not specified, then gaps are extracted with respect to the entire subject. \code{disjoin} returns a disjoint object, by finding the union of the end points in \code{x}. In other words, the result consists of a range for every interval, of maximal length, over which the set of overlapping ranges in \code{x} is the same and at least of size 1. \code{disjointBins} segregates \code{x} into a set of bins so that the ranges in each bin are disjoint. Lower-indexed bins are filled first. The method returns an integer vector indicating the bin index for each range. When \code{x} in a \link{RangesList} object, doing any of the transformation above is equivalent to applying the transformation to each \link{RangesList} top-level element separately. For \code{range}, if there are additional \code{RangesList} objects in \code{...}, they are merged into \code{x} by name, if all objects have names, otherwise, if they are all of the same length, by position. Else, an exception is thrown. } \author{H. Pages, M. Lawrence, P. Aboyoun} \seealso{ \itemize{ \item \link{intra-range-methods} for intra range transformations. \item The \link{Ranges}, \link{Views}, \link{RangesList}, \link{MaskCollection}, and \link{RangedData} classes. \item The \link[GenomicRanges]{inter-range-methods} man page in the GenomicRanges package for methods that operate on \link[GenomicRanges]{GenomicRanges} and other objects. \item \link{setops-methods} for set operations on \link{IRanges} objects. \item \code{\link{solveUserSEW}} for the SEW (Start/End/Width) interface. } } \examples{ ## --------------------------------------------------------------------- ## range() ## --------------------------------------------------------------------- ## On a Ranges object: x <- IRanges(start=c(-2, 6, 9, -4, 1, 0, -6, 3, 10), width=c( 5, 0, 6, 1, 4, 3, 2, 0, 3)) range(x) ## On a RangesList object (XVector package required): range1 <- IRanges(start=c(1, 2, 3), end=c(5, 2, 8)) range2 <- IRanges(start=c(15, 45, 20, 1), end=c(15, 100, 80, 5)) range3 <- IRanges(start=c(-2, 6, 7), width=c(8, 0, 0)) # with empty ranges collection <- IRangesList(one=range1, range2, range3) if (require(XVector)) { range(collection) } irl1 <- IRangesList(a=IRanges(c(1,2),c(4,3)), b=IRanges(c(4,6),c(10,7))) irl2 <- IRangesList(c=IRanges(c(0,2),c(4,5)), a=IRanges(c(4,5),c(6,7))) range(irl1, irl2) # matched by names names(irl2) <- NULL range(irl1, irl2) # now by position ## On a RangedData object: ranges <- IRanges(c(1,2,3),c(4,5,6)) score <- c(10L, 2L, NA) rd <- RangedData(ranges, score) range(rd) rd2 <- RangedData(IRanges(c(5,2,0), c(6,3,1))) range(rd, rd2) ## --------------------------------------------------------------------- ## reduce() ## --------------------------------------------------------------------- ## On a Ranges object: reduce(x) y <- reduce(x, with.revmap=TRUE) mcols(y)$revmap # an IntegerList reduce(x, drop.empty.ranges=TRUE) y <- reduce(x, drop.empty.ranges=TRUE, with.revmap=TRUE) mcols(y)$revmap ## Use the mapping from reduced to original ranges to split the DataFrame ## of original metadata columns by reduced range: ir0 <- IRanges(c(11:13, 2, 7:6), width=3) mcols(ir0) <- DataFrame(id=letters[1:6], score=1:6) ir <- reduce(ir0, with.revmap=TRUE) ir revmap <- mcols(ir)$revmap revmap relist(mcols(ir0)[unlist(revmap), ], revmap) # a SplitDataFrameList ## On a RangesList object. These 4 are the same: res1 <- reduce(collection) res2 <- IRangesList(one=reduce(range1), reduce(range2), reduce(range3)) res3 <- do.call(IRangesList, lapply(collection, reduce)) res4 <- endoapply(collection, reduce) stopifnot(identical(res2, res1)) stopifnot(identical(res3, res1)) stopifnot(identical(res4, res1)) reduce(collection, drop.empty.ranges=TRUE) ## On a RangedData object: rd <- RangedData( RangesList( chrA=IRanges(start=c(1, 4, 6), width=c(3, 2, 4)), chrB=IRanges(start=c(1, 3, 6), width=c(3, 3, 4))), score=c(2, 7, 3, 1, 1, 1)) rd reduce(rd) ## --------------------------------------------------------------------- ## gaps() ## --------------------------------------------------------------------- ## On a Ranges object: x0 <- IRanges(start=c(-2, 6, 9, -4, 1, 0, -6, 10), width=c( 5, 0, 6, 1, 4, 3, 2, 3)) gaps(x0) gaps(x0, start=-6, end=20) ## On a Views object: subject <- Rle(1:-3, 6:2) v <- Views(subject, start=c(8, 3), end=c(14, 4)) gaps(v) ## On a RangesList object. These 4 are the same: res1 <- gaps(collection) res2 <- IRangesList(one=gaps(range1), gaps(range2), gaps(range3)) res3 <- do.call(IRangesList, lapply(collection, gaps)) res4 <- endoapply(collection, gaps) stopifnot(identical(res2, res1)) stopifnot(identical(res3, res1)) stopifnot(identical(res4, res1)) ## On a MaskCollection object: mask1 <- Mask(mask.width=29, start=c(11, 25, 28), width=c(5, 2, 2)) mask2 <- Mask(mask.width=29, start=c(3, 10, 27), width=c(5, 8, 1)) mask3 <- Mask(mask.width=29, start=c(7, 12), width=c(2, 4)) mymasks <- append(append(mask1, mask2), mask3) mymasks gaps(mymasks) ## --------------------------------------------------------------------- ## disjoin() ## --------------------------------------------------------------------- ## On a Ranges object: ir <- IRanges(c(1, 1, 4, 10), c(6, 3, 8, 10)) disjoin(ir) # IRanges(c(1, 4, 7, 10), c(3, 6, 8, 10)) ## On a RangesList object: disjoin(collection) ## --------------------------------------------------------------------- ## disjointBins() ## --------------------------------------------------------------------- ## On a Ranges object: disjointBins(IRanges(1, 5)) # 1L disjointBins(IRanges(c(3, 1, 10), c(5, 12, 13))) # c(2L, 1L, 2L) ## On a RangesList object: disjointBins(collection) } \keyword{utilities} IRanges/man/intra-range-methods.Rd0000644000175100017510000004214512607265143020050 0ustar00biocbuildbiocbuild\name{intra-range-methods} \alias{intra-range-methods} \alias{shift} \alias{shift,Ranges-method} \alias{shift,Views-method} \alias{shift,RangesList-method} \alias{shift,CompressedIRangesList-method} \alias{shift,IntervalForest-method} \alias{narrow} \alias{narrow,Ranges-method} \alias{narrow,Views-method} \alias{narrow,RangesList-method} \alias{narrow,IntervalForest-method} \alias{narrow,CompressedIRangesList-method} \alias{narrow,MaskCollection-method} \alias{resize} \alias{resize,Ranges-method} \alias{resize,RangesList-method} \alias{resize,IntervalList-method} \alias{resize,CompressedIRangesList-method} \alias{resize,IntervalForest-method} \alias{flank} \alias{flank,Ranges-method} \alias{flank,RangesList-method} \alias{flank,IntervalForest-method} \alias{flank,CompressedIRangesList-method} \alias{promoters} \alias{promoters,Ranges-method} \alias{promoters,Views-method} \alias{promoters,RangesList-method} \alias{promoters,CompressedIRangesList-method} \alias{promoters,IntervalForest-method} \alias{reflect} \alias{reflect,Ranges-method} \alias{restrict} \alias{restrict,Ranges-method} \alias{restrict,RangesList-method} \alias{restrict,IntervalForest-method} \alias{restrict,CompressedIRangesList-method} \alias{threebands} \alias{threebands,IRanges-method} \alias{Ops,Ranges,numeric-method} \alias{Ops,Ranges,ANY-method} \alias{Ops,CompressedIRangesList,numeric-method} \alias{Ops,RangesList,numeric-method} \title{Intra range transformations of a Ranges, Views, RangesList, or MaskCollection object} \description{ Except for \code{threebands()}, all the transformations described in this man page are \emph{endomorphisms} that operate on a single "range-based" object, that is, they transform the ranges contained in the input object and return them in an object of the \emph{same class} as the input object. Range-based endomorphisms are grouped in 2 categories: \enumerate{ \item Intra range transformations like \code{shift()} that transform each range individually (and independently of the other ranges) and return an object of the \emph{same length} as the input object. Those transformations are described in this man page. \item Inter range transformations like \code{\link{reduce}()} that transform all the ranges together as a set to produce a new set of ranges and return an object not necessarily of the same length as the input object. Those transformations are described in the \link{inter-range-methods} man page (see \code{?`\link{inter-range-methods}`}). } } \usage{ ## shift() shift(x, shift=0L, use.names=TRUE) ## narrow() narrow(x, start=NA, end=NA, width=NA, use.names=TRUE) ## resize() resize(x, width, fix="start", use.names=TRUE, ...) ## flank() flank(x, width, start=TRUE, both=FALSE, use.names=TRUE, ...) ## promoters() promoters(x, upstream=2000, downstream=200, ...) ## reflect() reflect(x, bounds, use.names=TRUE) ## restrict() restrict(x, start=NA, end=NA, keep.all.ranges=FALSE, use.names=TRUE) ## threebands() threebands(x, start=NA, end=NA, width=NA) } \arguments{ \item{x}{ A \link{Ranges}, \link{Views}, \link{RangesList}, or \link{MaskCollection} object. } \item{shift}{ An integer vector containing the shift information. Recycled as necessary so that each element corresponds to a range in \code{x}. It can also be an \link{IntegerList} object if \code{x} is a \link{RangesList} object. } \item{use.names}{ \code{TRUE} or \code{FALSE}. Should names be preserved? } \item{start, end}{ \itemize{ \item If \code{x} is a \link{Ranges} or \link{Views} object: A vector of integers for all functions except for \code{flank}. For \code{restrict}, the supplied \code{start} and \code{end} arguments must be vectors of integers, eventually with NAs, that specify the restriction interval(s). Recycled as necessary so that each element corresponds to a range in \code{x}. Same thing for \code{narrow} and \code{threebands}, except that here \code{start} and \code{end} must contain coordinates relative to the ranges in \code{x}. See the Details section below. For \code{flank}, \code{start} is a logical indicating whether \code{x} should be flanked at the start (\code{TRUE}) or the end (\code{FALSE}). Recycled as necessary so that each element corresponds to a range in \code{x}. \item If \code{x} is a \link{RangesList} object: For \code{flank}, \code{start} must be either a logical vector or a \link{LogicalList} object indicating whether \code{x} should be flanked at the start (\code{TRUE}) or the end (\code{FALSE}). Recycled as necessary so that each element corresponds to a range in \code{x}. For \code{narrow}, \code{start} and \code{end} must be either an integer vector or an \link{IntegerList} object containing coordinates relative to the current ranges. For \code{restrict}, \code{start} and \code{end} must be either an integer vector or an \link{IntegerList} object (possibly containing NA's). } } \item{width}{ \itemize{ \item If \code{x} is a \link{Ranges} or \link{Views} object: For \code{narrow} and \code{threebands}, a vector of integers, eventually with NAs. See the SEW (Start/End/Width) interface for the details (\code{?solveUserSEW}). For \code{resize} and \code{flank}, the width of the resized or flanking regions. Note that if \code{both} is \code{TRUE}, this is effectively doubled. Recycled as necessary so that each element corresponds to a range in \code{x}. \item If \code{x} is a \link{RangesList} object: For \code{resize} and \code{flank}, either an integer vector or an \link{IntegerList} object containing the width of the flanking or resized regions. Recycled as necessary so that each element corresponds to a range in \code{x}. (Note for \code{flank}: if \code{both} is \code{TRUE}, this is effectively doubled.) For \code{narrow}, either an integer vector or a \link{IntegerList} object containing the widths to narrow to. See the SEW (Start/End/Width) interface for the details (\code{?solveUserSEW}). } } \item{both}{ If \code{TRUE}, extends the flanking region \code{width} positions \emph{into} the range. The resulting range thus straddles the end point, with \code{width} positions on either side. } \item{bounds}{ An \link{IRanges} object to serve as the reference bounds for the reflection, see below. } \item{fix}{ \itemize{ \item If \code{x} is a \link{Ranges} or \link{Views} object: A character vector or character-Rle of length 1 or \code{length(x)} containing the values \code{"start"}, \code{"end"}, and \code{"center"} denoting what to use as an anchor for each element in \code{x}. \item If \code{x} is a \link{RangesList} object: A character vector of length 1, a \link{CharacterList} object, or a character-RleList object containing the values \code{"start"}, \code{"end"}, and \code{"center"} denoting what to use as an anchor for each element in \code{x}. } } \item{upstream, downstream}{ Single \code{integer} values >= 0L. \code{upstream} defines the number of nucleotides toward the 5' end and \code{downstream} defines the number toward the 3' end, relative to the transcription start site. Promoter regions are formed by merging the upstream and downstream ranges. Default values for \code{upstream} and \code{downstream} were chosen based on our current understanding of gene regulation. On average, promoter regions in the mammalian genome are 5000 bp upstream and downstream of the transcription start site. } \item{keep.all.ranges}{ \code{TRUE} or \code{FALSE}. Should ranges that don't overlap with the restriction interval(s) be kept? Note that "don't overlap" means that they end strictly before \code{start - 1} or start strictly after \code{end + 1}. Ranges that end at \code{start - 1} or start at \code{end + 1} are always kept and their width is set to zero in the returned \link{IRanges} object. } \item{...}{ Additional arguments for methods. } } \details{ Here we start by describing how each transformation operates on a \link{Ranges} object \code{x}. \code{shift} shifts all the ranges in \code{x} by the amount specified by the \code{shift} argument. \code{narrow} narrows the ranges in \code{x} i.e. each range in the returned \link{Ranges} object is a subrange of the corresponding range in \code{x}. The supplied start/end/width values are solved by a call to \code{solveUserSEW(width(x), start=start, end=end, width=width)} and therefore must be compliant with the rules of the SEW (Start/End/Width) interface (see \code{?\link{solveUserSEW}} for the details). Then each subrange is derived from the original range according to the solved start/end/width values for this range. Note that those solved values are interpreted relatively to the original range. \code{resize} resizes the ranges to the specified width where either the start, end, or center is used as an anchor. \code{flank} generates flanking ranges for each range in \code{x}. If \code{start} is \code{TRUE} for a given range, the flanking occurs at the start, otherwise the end. The widths of the flanks are given by the \code{width} parameter. The widths can be negative, in which case the flanking region is reversed so that it represents a prefix or suffix of the range in \code{x}. The \code{flank} operation is illustrated below for a call of the form \code{flank(x, 3, TRUE)}, where \code{x} indicates a range in \code{x} and \code{-} indicates the resulting flanking region: \preformatted{ ---xxxxxxx } If \code{start} were \code{FALSE}: \preformatted{ xxxxxxx--- } For negative width, i.e. \code{flank(x, -3, FALSE)}, where \code{*} indicates the overlap between \code{x} and the result: \preformatted{ xxxx*** } If \code{both} is \code{TRUE}, then, for all ranges in \code{x}, the flanking regions are extended \emph{into} (or out of, if width is negative) the range, so that the result straddles the given endpoint and has twice the width given by \code{width}. This is illustrated below for \code{flank(x, 3, both=TRUE)}: \preformatted{ ---***xxxx } \code{promoters} generates promoter ranges for each range in \code{x} relative to the transcription start site (TSS), where TSS is \code{start(x)}. The promoter range is expanded around the TSS according to the \code{upsteam} and \code{downstream} arguments. \code{upstream} represents the number of nucleotides in the 5' direction and \code{downstream} the number in the 3' direction. The full range is defined as, (start(x) - upstream) to (start(x) + downstream - 1). For documentation for using \code{promoters} on \code{GenomicRanges} objects see ?\code{"promoters,GRanges-method"}. \code{reflect} "reflects" or reverses each range in \code{x} relative to the corresponding range in \code{bounds}, which is recycled as necessary. Reflection preserves the width of a range, but shifts it such the distance from the left bound to the start of the range becomes the distance from the end of the range to the right bound. This is illustrated below, where \code{x} represents a range in \code{x} and \code{[} and \code{]} indicate the bounds: \preformatted{ [..xxx.....] becomes [.....xxx..] } \code{restrict} restricts the ranges in \code{x} to the interval(s) specified by the \code{start} and \code{end} arguments. \code{threebands} extends the capability of \code{narrow} by returning the 3 ranges objects associated to the narrowing operation. The returned value \code{y} is a list of 3 ranges objects named \code{"left"}, \code{"middle"} and \code{"right"}. The middle component is obtained by calling \code{narrow} with the same arguments (except that names are dropped). The left and right components are also instances of the same class as \code{x} and they contain what has been removed on the left and right sides (respectively) of the original ranges during the narrowing. Note that original object \code{x} can be reconstructed from the left and right bands with \code{punion(y$left, y$right, fill.gap=TRUE)}. When \code{x} in a \link{RangesList} object, doing any of the transformation above is equivalent to applying the transformation to each \link{RangesList} top-level element separately. } \author{H. Pages, M. Lawrence, P. Aboyoun} \seealso{ \itemize{ \item \link{inter-range-methods} for inter range transformations. \item The \link{Ranges}, \link{Views}, \link{RangesList}, and \link{MaskCollection} classes. \item The \link[XVector]{intra-range-methods} man page in the XVector package for methods that operate on \link[XVector]{XVectorList} objects. \item The \link[GenomicRanges]{intra-range-methods} man page in the GenomicRanges package for methods that operate on \link[GenomicRanges]{GenomicRanges} and other objects. \item \link{setops-methods} for set operations on \link{IRanges} objects. \item \code{\link{solveUserSEW}} for the SEW (Start/End/Width) interface. } } \examples{ ## --------------------------------------------------------------------- ## shift() ## --------------------------------------------------------------------- ## On a Ranges object ir1 <- successiveIRanges(c(19, 5, 0, 8, 5)) ir1 shift(ir1, shift=-3) ## On a RangesList object range1 <- IRanges(start=c(1, 2, 3), end=c(5, 2, 8)) range2 <- IRanges(start=c(15, 45, 20, 1), end=c(15, 100, 80, 5)) range3 <- IRanges(start=c(-2, 6, 7), width=c(8, 0, 0)) # with empty ranges collection <- IRangesList(one=range1, range2, range3) shift(collection, shift=5) ## --------------------------------------------------------------------- ## narrow() ## --------------------------------------------------------------------- ## On a Ranges object ir2 <- ir1[width(ir1) != 0] narrow(ir2, start=4, end=-2) narrow(ir2, start=-4, end=-2) narrow(ir2, end=5, width=3) narrow(ir2, start=c(3, 4, 2, 3), end=c(12, 5, 7, 4)) ## On a RangesList object narrow(collection[-3], start=2) narrow(collection[-3], end=-2) ## On a MaskCollection object mask1 <- Mask(mask.width=29, start=c(11, 25, 28), width=c(5, 2, 2)) mask2 <- Mask(mask.width=29, start=c(3, 10, 27), width=c(5, 8, 1)) mask3 <- Mask(mask.width=29, start=c(7, 12), width=c(2, 4)) mymasks <- append(append(mask1, mask2), mask3) mymasks narrow(mymasks, start=8) ## --------------------------------------------------------------------- ## resize() ## --------------------------------------------------------------------- ## On a Ranges object resize(ir2, 200) resize(ir2, 2, fix="end") ## On a RangesList object resize(collection, width=200) ## --------------------------------------------------------------------- ## flank() ## --------------------------------------------------------------------- ## On a Ranges object ir3 <- IRanges(c(2,5,1), c(3,7,3)) flank(ir3, 2) flank(ir3, 2, start=FALSE) flank(ir3, 2, start=c(FALSE, TRUE, FALSE)) flank(ir3, c(2, -2, 2)) flank(ir3, 2, both = TRUE) flank(ir3, 2, start=FALSE, both=TRUE) flank(ir3, -2, start=FALSE, both=TRUE) ## On a RangesList object flank(collection, width=10) ## --------------------------------------------------------------------- ## promoters() ## --------------------------------------------------------------------- ## On a Ranges object ir4 <- IRanges(20:23, width=3) promoters(ir4, upstream=0, downstream=0) ## no change promoters(ir4, upstream=0, downstream=1) ## start value only promoters(ir4, upstream=1, downstream=0) ## single upstream nucleotide ## On a RangesList object promoters(collection, upstream=5, downstream=2) ## --------------------------------------------------------------------- ## reflect() ## --------------------------------------------------------------------- ## On a Ranges object bounds <- IRanges(c(0, 5, 3), c(10, 6, 9)) reflect(ir3, bounds) ## reflect() does not yet support RangesList objects! ## --------------------------------------------------------------------- ## restrict() ## --------------------------------------------------------------------- ## On a Ranges object restrict(ir1, start=12, end=34) restrict(ir1, start=20) restrict(ir1, start=21) restrict(ir1, start=21, keep.all.ranges=TRUE) ## On a RangesList object restrict(collection, start=2, end=8) ## --------------------------------------------------------------------- ## threebands() ## --------------------------------------------------------------------- ## On a Ranges object z <- threebands(ir2, start=4, end=-2) ir2b <- punion(z$left, z$right, fill.gap=TRUE) stopifnot(identical(ir2, ir2b)) threebands(ir2, start=-5) ## threebands() does not support RangesList objects. } \keyword{utilities} IRanges/man/mapCoords-methods.Rd0000644000175100017510000000424612607265143017570 0ustar00biocbuildbiocbuild\name{mapCoords-methods} \docType{class} \alias{mapCoords-methods} % generics \alias{mapCoords} \alias{pmapCoords} \title{Mapping of ranges to another sequence} \description{ DEFUNCT! Use \code{\link[GenomicFeatures]{mapToTranscripts}} from the \pkg{GenomicFeatures} package or \code{\link[GenomicAlignments]{mapToAlignments}} from the \pkg{GenomicAlignments} package instead. The \code{mapCoords} generic converts a set of ranges to the equivalent ranges on another sequence through some sort of alignment between sequences. The output is an object of the same class as \code{from} and in general will contain the mapped ranges with the matching data as metadata. Matching data are the result of calling \code{findOverlaps} with \code{type = "within"}. This operation matches each input range to a destination sequence (useful when the alignment is one/many to many). The \code{pmapCoords} function is simpler: it treats the two inputs as parallel vectors, maps each input range via the corresponding alignment, and returns the mapped ranges. There is one result per input element, instead of the many-to-many result from \code{mapCoords}. } \usage{ mapCoords(from, to, ...) pmapCoords(from, to, ...) } \arguments{ \item{from}{Typically an object containing ranges to map.} \item{to}{Typically an object representing an alignment.} \item{...}{Arguments to pass to methods} } \value{ An object the same class as \code{from}. In the case of \code{mapCoords}, the result of \code{findOverlaps} with type = ``within`` are included as metadata columns (`queryHits` and `subjectHits`). } \author{ Michael Lawrence } \seealso{ \itemize{ \item See \code{?`\link[GenomicRanges]{mapCoords-methods}`} in the \pkg{GenomicRanges} package for the \code{mapCoords} method on GRanges objects \item See \code{?`\link[GenomicAlignments]{mapCoords-methods}`} in the \pkg{GenomicAlignments} package for the \code{mapCoords} method on GAlignments objects } } \examples{ ## DEFUNCT! See ?mapToTranscripts in the GenomicFeatures package and ## ?mapToAlignments in the GenomicAlignments package. } \keyword{methods} \keyword{classes} IRanges/man/multisplit.Rd0000644000175100017510000000160012607265143016375 0ustar00biocbuildbiocbuild\name{multisplit} \alias{multisplit} \title{ Split elements belonging to multiple groups } \description{ This is like \code{\link{split}}, except elements can belong to multiple groups, in which case they are repeated to appear in multiple elements of the return value. } \usage{ multisplit(x, f) } \arguments{ \item{x}{ The object to split, like a vector. } \item{f}{ A list-like object of vectors, the same length as \code{x}, where each element indicates the groups to which each element of \code{x} belongs. } } \value{ A list-like object, with an element for each unique value in the unlisted \code{f}, containing the elements in \code{x} where the corresponding element in \code{f} contained that value. Just try it. } \author{ Michael Lawrence } \examples{ multisplit(1:3, list(letters[1:2], letters[2:3], letters[2:4])) } \keyword{ manip } IRanges/man/nearest-methods.Rd0000644000175100017510000001757112607265143017307 0ustar00biocbuildbiocbuild\name{nearest-methods} \alias{nearest-methods} \alias{class:RangesORmissing} \alias{RangesORmissing-class} \alias{RangesORmissing} \alias{nearest} \alias{precede} \alias{follow} \alias{distance} \alias{distanceToNearest} \alias{nearest,Ranges,RangesORmissing-method} \alias{precede,Ranges,RangesORmissing-method} \alias{follow,Ranges,RangesORmissing-method} \alias{distance,Ranges,Ranges-method} \alias{distanceToNearest,Ranges,RangesORmissing-method} \title{Finding the nearest range neighbor} \description{ The \code{nearest}, \code{precede}, \code{follow}, \code{distance} and \code{distanceToNearest} methods for \code{\linkS4class{Ranges}} objects and subclasses. } \usage{ \S4method{nearest}{Ranges,RangesORmissing}(x, subject, select = c("arbitrary", "all"), algorithm = c("nclist", "intervaltree")) \S4method{precede}{Ranges,RangesORmissing}(x, subject, select = c("first", "all")) \S4method{follow}{Ranges,RangesORmissing}(x, subject, select = c("last", "all")) \S4method{distanceToNearest}{Ranges,RangesORmissing}(x, subject, select = c("arbitrary", "all"), algorithm = c("nclist", "intervaltree")) \S4method{distance}{Ranges,Ranges}(x, y) } \arguments{ \item{x}{The query \code{\linkS4class{Ranges}} instance. } \item{subject}{The subject \code{Ranges} instance, within which the nearest neighbors are found. Can be missing, in which case \code{x} is also the subject. } \item{select}{Logic for handling ties. By default, all the methods select a single interval (arbitrary for \code{nearest},the first by order in \code{subject} for \code{precede}, and the last for \code{follow}). To get all matchings, as a \code{Hits} object, use \dQuote{all}. } \item{algorithm}{ This argument is passed to \code{\link{findOverlaps}}, which \code{nearest} and \code{distanceToNearest} use internally. See \code{?\link{findOverlaps}} for more information. Note that it will be removed in BioC 3.3 so please don't use it unless you have a good reason to do so (e.g. troubleshooting). } \item{y}{For the \code{distance} method, a \code{Ranges} instance. Cannot be missing. If \code{x} and \code{y} are not the same length, the shortest will be recycled to match the length of the longest. } \item{...}{Additional arguments for methods} } \details{ \itemize{ \item{nearest: }{ The conventional nearest neighbor finder. Returns a integer vector containing the index of the nearest neighbor range in \code{subject} for each range in \code{x}. If there is no nearest neighbor (if \code{subject} is empty), NA's are returned. Here is roughly how it proceeds, for a range \code{xi} in \code{x}: \enumerate{ \item Find the ranges in \code{subject} that overlap \code{xi}. If a single range \code{si} in \code{subject} overlaps \code{xi}, \code{si} is returned as the nearest neighbor of \code{xi}. If there are multiple overlaps, one of the overlapping ranges is chosen arbitrarily. \item If no ranges in \code{subject} overlap with \code{xi}, then the range in \code{subject} with the shortest distance from its end to the start \code{xi} or its start to the end of \code{xi} is returned. } } \item{precede: }{ For each range in \code{x}, \code{precede} returns the index of the interval in \code{subject} that is directly preceded by the query range. Overlapping ranges are excluded. \code{NA} is returned when there are no qualifying ranges in \code{subject}. } \item{follow: }{ The opposite of \code{precede}, this function returns the index of the range in \code{subject} that a query range in \code{x} directly follows. Overlapping ranges are excluded. \code{NA} is returned when there are no qualifying ranges in \code{subject}. } \item{distanceToNearest: }{ Returns the distance for each range in \code{x} to its nearest neighbor in \code{subject}. } \item{distance: }{ Returns the distance for each range in \code{x} to the range in \code{y}. The \code{distance} method differs from others documented on this page in that it is symmetric; \code{y} cannot be missing. If \code{x} and \code{y} are not the same length, the shortest will be recycled to match the length of the longest. The \code{select} argument is not available for \code{distance} because comparisons are made in a pair-wise fashion. The return value is the length of the longest of \code{x} and \code{y}. The \code{distance} calculation changed in BioC 2.12 to accommodate zero-width ranges in a consistent and intuitive manner. The new distance can be explained by a \emph{block} model where a range is represented by a series of blocks of size 1. Blocks are adjacent to each other and there is no gap between them. A visual representation of IRanges(4,7) would be \preformatted{ +-----+-----+-----+-----+ 4 5 6 7 } The distance between two consecutive blocks is 0L (prior to Bioconductor 2.12 it was 1L). The new distance calculation now returns the size of the gap between two ranges. This change to distance affects the notion of overlaps in that we no longer say: x and y overlap <=> distance(x, y) == 0 Instead we say x and y overlap => distance(x, y) == 0 or x and y overlap or are adjacent <=> distance(x, y) == 0 } } } \value{ For \code{nearest}, \code{precede} and \code{follow}, an integer vector of indices in \code{subject}, or a \code{\linkS4class{Hits}} if \code{select="all"}. For \code{distanceToNearest}, a \code{Hits} object with an elementMetadata column of the \code{distance} between the pair. Access \code{distance} with \code{mcols} accessor. For \code{distance}, an integer vector of distances between the ranges in \code{x} and \code{y}. } \author{M. Lawrence} \seealso{ \itemize{ \item The \link{Ranges} and \link{Hits} classes. \item The \link[GenomicRanges]{GenomicRanges} and \link[GenomicRanges]{GRanges} classes in the GenomicRanges package. \item \code{\link{findOverlaps}} for finding just the overlapping ranges. \item{}{ GenomicRanges methods for \itemize{ \item \code{precede} \item \code{follow} \item \code{nearest} \item \code{distance} \item \code{distanceToNearest} } are documented at ?\code{\link[GenomicRanges]{nearest-methods}} or ?\code{\link[GenomicRanges]{precede,GenomicRanges,GenomicRanges-method}} } } } \examples{ ## ------------------------------------------ ## precede() and follow() ## ------------------------------------------ query <- IRanges(c(1, 3, 9), c(3, 7, 10)) subject <- IRanges(c(3, 2, 10), c(3, 13, 12)) precede(query, subject) # c(3L, 3L, NA) precede(IRanges(), subject) # integer() precede(query, IRanges()) # rep(NA_integer_, 3) precede(query) # c(3L, 3L, NA) follow(query, subject) # c(NA, NA, 1L) follow(IRanges(), subject) # integer() follow(query, IRanges()) # rep(NA_integer_, 3) follow(query) # c(NA, NA, 2L) ## ------------------------------------------ ## nearest() ## ------------------------------------------ query <- IRanges(c(1, 3, 9), c(2, 7, 10)) subject <- IRanges(c(3, 5, 12), c(3, 6, 12)) nearest(query, subject) # c(1L, 1L, 3L) nearest(query) # c(2L, 1L, 2L) ## ------------------------------------------ ## distance() ## ------------------------------------------ ## adjacent distance(IRanges(1,5), IRanges(6,10)) # 0L ## overlap distance(IRanges(1,5), IRanges(3,7)) # 0L ## zero-width sapply(-3:3, function(i) distance(shift(IRanges(4,3), i), IRanges(4,3))) } \keyword{utilities} IRanges/man/read.Mask.Rd0000644000175100017510000001450312607265143016002 0ustar00biocbuildbiocbuild\name{read.Mask} \alias{read.Mask} \alias{read.agpMask} \alias{read.gapMask} \alias{read.liftMask} \alias{read.rmMask} \alias{read.trfMask} \title{Read a mask from a file} \description{ \code{read.agpMask} and \code{read.gapMask} extract the AGAPS mask from an NCBI "agp" file or a UCSC "gap" file, respectively. \code{read.liftMask} extracts the AGAPS mask from a UCSC "lift" file (i.e. a file containing offsets of contigs within sequences). \code{read.rmMask} extracts the RM mask from a RepeatMasker .out file. \code{read.trfMask} extracts the TRF mask from a Tandem Repeats Finder .bed file. } \usage{ read.agpMask(file, seqname="?", mask.width=NA, gap.types=NULL, use.gap.types=FALSE) read.gapMask(file, seqname="?", mask.width=NA, gap.types=NULL, use.gap.types=FALSE) read.liftMask(file, seqname="?", mask.width=NA) read.rmMask(file, seqname="?", mask.width=NA, use.IDs=FALSE) read.trfMask(file, seqname="?", mask.width=NA) } \arguments{ \item{file}{ Either a character string naming a file or a connection open for reading. } \item{seqname}{ The name of the sequence for which the mask must be extracted. If no sequence is specified (i.e. \code{seqname="?"}) then an error is raised and the sequence names found in the file are displayed. If the file doesn't contain any information for the specified sequence, then a warning is issued and an empty mask of width \code{mask.width} is returned. } \item{mask.width}{ The width of the mask to return i.e. the length of the sequence this mask will be put on. See \code{?`\link{MaskCollection-class}`} for more information about the width of a \link{MaskCollection} object. } \item{gap.types}{ \code{NULL} or a character vector containing gap types. Use this argument to filter the assembly gaps that are to be extracted from the "agp" or "gap" file based on their type. Most common gap types are \code{"contig"}, \code{"clone"}, \code{"centromere"}, \code{"telomere"}, \code{"heterochromatin"}, \code{"short_arm"} and \code{"fragment"}. With \code{gap.types=NULL}, all the assembly gaps described in the file are extracted. With \code{gap.types="?"}, an error is raised and the gap types found in the file for the specified sequence are displayed. } \item{use.gap.types}{ Whether or not the gap types provided in the "agp" or "gap" file should be used to name the ranges constituing the returned mask. See \code{?`\link{IRanges-class}`} for more information about the names of an \link{IRanges} object. } \item{use.IDs}{ Whether or not the repeat IDs provided in the RepeatMasker .out file should be used to name the ranges constituing the returned mask. See \code{?`\link{IRanges-class}`} for more information about the names of an \link{IRanges} object. } } \seealso{ \link{MaskCollection-class}, \link{IRanges-class} } \examples{ ## --------------------------------------------------------------------- ## A. Extract a mask of assembly gaps ("AGAPS" mask) with read.agpMask() ## --------------------------------------------------------------------- ## Note: The hs_b36v3_chrY.agp file was obtained by downloading, ## extracting and renaming the hs_ref_chrY.agp.gz file from ## ## ftp://ftp.ncbi.nih.gov/genomes/H_sapiens/Assembled_chromosomes/ ## hs_ref_chrY.agp.gz 5 KB 24/03/08 04:33:00 PM ## ## on May 9, 2008. chrY_length <- 57772954 file1 <- system.file("extdata", "hs_b36v3_chrY.agp", package="IRanges") mask1 <- read.agpMask(file1, seqname="chrY", mask.width=chrY_length, use.gap.types=TRUE) mask1 mask1[[1]] mask11 <- read.agpMask(file1, seqname="chrY", mask.width=chrY_length, gap.types=c("centromere", "heterochromatin")) mask11[[1]] ## --------------------------------------------------------------------- ## B. Extract a mask of assembly gaps ("AGAPS" mask) with read.liftMask() ## --------------------------------------------------------------------- ## Note: The hg18liftAll.lft file was obtained by downloading, ## extracting and renaming the liftAll.zip file from ## ## http://hgdownload.cse.ucsc.edu/goldenPath/hg18/bigZips/ ## liftAll.zip 03-Feb-2006 11:35 5.5K ## ## on May 8, 2008. file2 <- system.file("extdata", "hg18liftAll.lft", package="IRanges") mask2 <- read.liftMask(file2, seqname="chr1") mask2 if (interactive()) { ## contigs 7 and 8 for chrY are adjacent read.liftMask(file2, seqname="chrY") ## displays the sequence names found in the file read.liftMask(file2) ## specify an unknown sequence name read.liftMask(file2, seqname="chrZ", mask.width=300) } ## --------------------------------------------------------------------- ## C. Extract a RepeatMasker ("RM") or Tandem Repeats Finder ("TRF") ## mask with read.rmMask() or read.trfMask() ## --------------------------------------------------------------------- ## Note: The ce2chrM.fa.out and ce2chrM.bed files were obtained by ## downloading, extracting and renaming the chromOut.zip and ## chromTrf.zip files from ## ## http://hgdownload.cse.ucsc.edu/goldenPath/ce2/bigZips/ ## chromOut.zip 21-Apr-2004 09:05 2.6M ## chromTrf.zip 21-Apr-2004 09:07 182K ## ## on May 7, 2008. ## Before you can extract a mask with read.rmMask() or read.trfMask(), you ## need to know the length of the sequence that you're going to put the ## mask on: if (interactive()) { library(BSgenome.Celegans.UCSC.ce2) chrM_length <- seqlengths(Celegans)[["chrM"]] ## Read the RepeatMasker .out file for chrM in ce2: file3 <- system.file("extdata", "ce2chrM.fa.out", package="IRanges") RMmask <- read.rmMask(file3, seqname="chrM", mask.width=chrM_length) RMmask ## Read the Tandem Repeats Finder .bed file for chrM in ce2: file4 <- system.file("extdata", "ce2chrM.bed", package="IRanges") TRFmask <- read.trfMask(file4, seqname="chrM", mask.width=chrM_length) TRFmask desc(TRFmask) <- paste(desc(TRFmask), "[period<=12]") TRFmask ## Put the 2 masks on chrM: chrM <- Celegans$chrM masks(chrM) <- RMmask # this would drop all current masks, if any masks(chrM) <- append(masks(chrM), TRFmask) chrM } } \keyword{manip} IRanges/man/reverse-methods.Rd0000644000175100017510000000324612607265143017313 0ustar00biocbuildbiocbuild\name{reverse} \alias{reverse} \alias{reverse,character-method} \alias{reverse,IRanges-method} \alias{reverse,NormalIRanges-method} \alias{reverse,Views-method} \alias{reverse,MaskCollection-method} \title{reverse} \description{ A generic function for reversing vector-like or list-like objects. This man page describes methods for reversing a character vector, a \link{Views} object, or a \link{MaskCollection} object. Note that \code{reverse} is similar to but not the same as \code{\link[base]{rev}}. } \usage{ reverse(x, ...) } \arguments{ \item{x}{ A vector-like or list-like object. } \item{...}{ Additional arguments to be passed to or from methods. } } \details{ On a character vector or a \link{Views} object, \code{reverse} reverses each element individually, without modifying the top-level order of the elements. More precisely, each individual string of a character vector is reversed. } \value{ An object of the same class and length as the original object. } \seealso{ \link[XVector]{reverse-methods}, \link{Views-class}, \link{MaskCollection-class}, \code{\link{endoapply}}, \code{\link[base]{rev}} } \examples{ ## On a character vector: reverse(c("Hi!", "How are you?")) rev(c("Hi!", "How are you?")) ## On a Views object: v <- successiveViews(Rle(c(-0.5, 12.3, 4.88), 4:2), 1:4) v reverse(v) rev(v) ## On a MaskCollection object: mask1 <- Mask(mask.width=29, start=c(11, 25, 28), width=c(5, 2, 2)) mask2 <- Mask(mask.width=29, start=c(3, 10, 27), width=c(5, 8, 1)) mask3 <- Mask(mask.width=29, start=c(7, 12), width=c(2, 4)) mymasks <- append(append(mask1, mask2), mask3) reverse(mymasks) } \keyword{methods} \keyword{manip} IRanges/man/seqapply.Rd0000644000175100017510000000236012607265143016031 0ustar00biocbuildbiocbuild\name{seqapply} \alias{unsplit,List-method} \alias{split<-,Vector-method} \title{ 2 methods that should be documented somewhere else } \description{ \code{unsplit} method for \link{List} object and \code{split<-} method for \link{Vector} object. } \usage{ \S4method{unsplit}{List}(value, f, drop = FALSE) \S4method{split}{Vector}(x, f, drop = FALSE, ...) <- value } \arguments{ \item{value}{ The \link{List} object to unsplit. } \item{f}{ A \code{factor} or \code{list} of factors } \item{drop}{ Whether to drop empty elements from the returned list } \item{x}{ Like \code{X} } \item{\dots}{ Extra arguments to pass to \code{FUN} } } \details{ \code{unsplit} unlists \code{value}, where the order of the returned vector is as if \code{value} were originally created by splitting that vector on the factor \code{f}. \code{split(x, f, drop = FALSE) <- value}: Virtually splits \code{x} by the factor \code{f}, replaces the elements of the resulting list with the elements from the list \code{value}, and restores \code{x} to its original form. Note that this works for any \code{Vector}, even though \code{split} itself is not universally supported. } \author{ Michael Lawrence } \keyword{manip} IRanges/man/setops-methods.Rd0000644000175100017510000001244412607265143017155 0ustar00biocbuildbiocbuild\name{setops-methods} \alias{setops-methods} \alias{union,Ranges,Ranges-method} \alias{union,RangesList,RangesList-method} \alias{union,CompressedIRangesList,CompressedIRangesList-method} \alias{intersect,Ranges,Ranges-method} \alias{intersect,RangesList,RangesList-method} \alias{intersect,CompressedIRangesList,CompressedIRangesList-method} \alias{setdiff,Ranges,Ranges-method} \alias{setdiff,RangesList,RangesList-method} \alias{setdiff,CompressedIRangesList,CompressedIRangesList-method} \alias{punion} \alias{punion,Ranges,Ranges-method} \alias{pintersect} \alias{pintersect,Ranges,Ranges-method} \alias{psetdiff} \alias{psetdiff,Ranges,Ranges-method} \alias{pgap} \alias{pgap,Ranges,Ranges-method} \title{Set operations on IRanges and RangesList objects} \description{ Performs set operations on \link{IRanges} objects. } \usage{ ## Vector-wise operations: \S4method{union}{Ranges,Ranges}(x, y,...) \S4method{intersect}{Ranges,Ranges}(x, y,...) \S4method{setdiff}{Ranges,Ranges}(x, y,...) ## Element-wise (aka "parallel") operations: \S4method{punion}{Ranges,Ranges}(x, y, fill.gap=FALSE, ...) \S4method{pintersect}{Ranges,Ranges}(x, y, resolve.empty=c("none", "max.start", "start.x"), ...) \S4method{psetdiff}{Ranges,Ranges}(x, y, ...) \S4method{pgap}{Ranges,Ranges}(x, y, ...) } \arguments{ \item{x, y}{ \link{IRanges} objects. } \item{fill.gap}{ Logical indicating whether or not to force a union by using the rule \code{start = min(start(x), start(y)), end = max(end(x), end(y))}. } \item{resolve.empty}{ One of \code{"none"}, \code{"max.start"}, or \code{"start.x"} denoting how to handle ambiguous empty ranges formed by intersections. \code{"none"} - throw an error if an ambiguous empty range is formed, \code{"max.start"} - associate the maximum start value with any ambiguous empty range, and \code{"start.x"} - associate the start value of \code{x} with any ambiguous empty range. (See Details section below for the definition of an ambiguous range.) } \item{...}{ Further arguments to be passed to or from other methods. } } \details{ The \code{union}, \code{intersect} and \code{setdiff} methods for \link{IRanges} objects return a "normal" \link{IRanges} object (of the same class as \code{x}) representing the union, intersection and (asymmetric!) difference of the sets of integers represented by \code{x} and \code{y}. \code{punion}, \code{pintersect}, \code{psetdiff} and \code{pgap} are generic functions that compute the element-wise (aka "parallel") union, intersection, (asymmetric!) difference and gap between each element in \code{x} and its corresponding element in \code{y}. Methods for \link{IRanges} objects are defined. For these methods, \code{x} and \code{y} must have the same length (i.e. same number of ranges) and they return an \link{IRanges} instance of the same length as \code{x} and \code{y} where each range represents the union/intersection/difference/gap of/between the corresponding ranges in \code{x} and \code{y}. By default, \code{pintersect} will throw an error when an "ambiguous empty range" is formed. An ambiguous empty range can occur three different ways: 1) when corresponding non-empty ranges elements \code{x} and \code{y} have an empty intersection, 2) if the position of an empty range element does not fall within the corresponding limits of a non-empty range element, or 3) if two corresponding empty range elements do not have the same position. For example if empty range element [22,21] is intersected with non-empty range element [1,10], an error will be produced; but if it is intersected with the range [22,28], it will produce [22,21]. As mentioned in the Arguments section above, this behavior can be changed using the \code{resolve.empty} argument. } \author{H. Pages and M. Lawrence} \seealso{ \code{pintersect} is similar to \code{\link{narrow}}, except the end points are absolute, not relative. \code{pintersect} is also similar to \code{\link{restrict}}, except ranges outside of the restriction become empty and are not discarded. \link[BiocGenerics]{union}, \link{Ranges-class}, \link{intra-range-methods} for intra range transformations, \link{inter-range-methods} for inter range transformations, \link{IRanges-class}, \link{IRanges-utils} } \examples{ x <- IRanges(c(1, 5, -2, 0, 14), c(10, 9, 3, 11, 17)) subject <- Rle(1:-3, 6:2) y <- Views(subject, start=c(14, 0, -5, 6, 18), end=c(20, 2, 2, 8, 20)) ## Vector-wise operations: union(x, ranges(y)) union(ranges(y), x) intersect(x, ranges(y)) intersect(ranges(y), x) setdiff(x, ranges(y)) setdiff(ranges(y), x) ## Element-wise (aka "parallel") operations: try(punion(x, ranges(y))) punion(x[3:5], ranges(y)[3:5]) punion(x, ranges(y), fill.gap=TRUE) try(pintersect(x, ranges(y))) pintersect(x[3:4], ranges(y)[3:4]) pintersect(x, ranges(y), resolve.empty="max.start") psetdiff(ranges(y), x) try(psetdiff(x, ranges(y))) start(x)[4] <- -99 end(y)[4] <- 99 psetdiff(x, ranges(y)) pgap(x, ranges(y)) ## On RangesList objects: irl1 <- IRangesList(a = IRanges(c(1,2),c(4,3)), b = IRanges(c(4,6),c(10,7))) irl2 <- IRangesList(c = IRanges(c(0,2),c(4,5)), a = IRanges(c(4,5),c(6,7))) union(irl1, irl2) intersect(irl1, irl2) setdiff(irl1, irl2) } \keyword{utilities} IRanges/man/slice-methods.Rd0000644000175100017510000000464212607265143016740 0ustar00biocbuildbiocbuild\name{slice-methods} \alias{slice-methods} \alias{slice} \alias{slice,ANY-method} \alias{slice,Rle-method} \alias{slice,RleList-method} \title{Slice a vector-like or list-like object} \description{ \code{slice} is a generic function that creates views on a vector-like or list-like object that contain the elements that are within the specified bounds. } \usage{ slice(x, lower=-Inf, upper=Inf, ...) \S4method{slice}{Rle}(x, lower=-Inf, upper=Inf, includeLower=TRUE, includeUpper=TRUE, rangesOnly=FALSE) \S4method{slice}{RleList}(x, lower=-Inf, upper=Inf, includeLower=TRUE, includeUpper=TRUE, rangesOnly=FALSE) } \arguments{ \item{x}{ An \link{Rle} or \link{RleList} object, or any object coercible to an Rle object. } \item{lower, upper}{ The lower and upper bounds for the slice. } \item{includeLower, includeUpper}{ Logical indicating whether or not the specified boundary is open or closed. } \item{rangesOnly}{ A logical indicating whether or not to drop the original data from the output. } \item{...}{ Additional arguments to be passed to specific methods. } } \details{ \code{slice} is useful for finding areas of absolute maxima (peaks), absolute minima (troughs), or fluctuations within specified limits. One or more view summarization methods can be used on the result of \code{slice}. See \code{?`link{view-summarization-methods}`} } \value{ The method for \link{Rle} objects returns an \link{RleViews} object if \code{rangesOnly=FALSE} or an \link{IRanges} object if \code{rangesOnly=TRUE}. The method for \link{RleList} objects returns an \link{RleViewsList} object if \code{rangesOnly=FALSE} or an \link{IRangesList} object if \code{rangesOnly=TRUE}. } \author{P. Aboyoun} \seealso{ \itemize{ \item \link{view-summarization-methods} for summarizing the views returned by \code{slice}. \item \link[XVector]{slice-methods} in the \pkg{XVector} package for more \code{slice} methods. \item \code{\link{coverage}} for computing the coverage across a set of ranges. \item The \link{Rle}, \link{RleList}, \link{RleViews}, and \link{RleViewsList} classes. } } \examples{ ## Views derived from coverage x <- IRanges(start=c(1L, 9L, 4L, 1L, 5L, 10L), width=c(5L, 6L, 3L, 4L, 3L, 3L)) cvg <- coverage(x) slice(cvg, lower=2) slice(cvg, lower=2, rangesOnly=TRUE) } \keyword{methods} IRanges/man/updateObject-methods.Rd0000644000175100017510000000364712607265143020256 0ustar00biocbuildbiocbuild\name{updateObject-methods} \alias{updateObject-methods} \alias{updateObject,CharacterList-method} \alias{updateObject,ComplexList-method} \alias{updateObject,IntegerList-method} \alias{updateObject,IntervalTree-method} \alias{updateObject,IRanges-method} \alias{updateObject,IRangesList-method} \alias{updateObject,LogicalList-method} \alias{updateObject,MaskCollection-method} \alias{updateObject,NormalIRanges-method} \alias{updateObject,NumericList-method} \alias{updateObject,RangedData-method} \alias{updateObject,RangedDataList-method} \alias{updateObject,RangesList-method} \alias{updateObject,RawList-method} \alias{updateObject,RDApplyParams-method} \alias{updateObject,Rle-method} \alias{updateObject,RleList-method} \alias{updateObject,RleViews-method} \alias{updateObject,SplitXDataFrameList-method} \alias{updateObject,XDataFrame-method} \alias{updateObject,XDataFrameList-method} \title{Update an object of a class defined in the IRanges package to its current class definition} \description{ The IRanges package provides an extensive collection of \code{\link[BiocGenerics]{updateObject}} methods for updating almost any instance of a class defined in the package. } \usage{ ## Showing usage of method defined for IntegerList objects only (usage ## is the same for all methods). \S4method{updateObject}{IntegerList}(object, ..., verbose=FALSE) } \arguments{ \item{object}{ Object to be updated. Many (but not all) IRanges classes are supported. If no specific method is available for the object, then the default method (defined in the BiocGenerics package) is used. See \code{?\link[BiocGenerics]{updateObject}} for a description of the default method. } \item{..., verbose}{ See \code{?\link[BiocGenerics]{updateObject}}. } } \value{ Returns a valid instance of \code{object}. } \author{The Bioconductor Dev Team} \seealso{ \code{\link[BiocGenerics]{updateObject}} } \keyword{manip} IRanges/man/view-summarization-methods.Rd0000644000175100017510000001067012607265143021511 0ustar00biocbuildbiocbuild\name{view-summarization-methods} \alias{view-summarization-methods} \alias{viewApply} \alias{viewApply,Views-method} \alias{viewApply,RleViews-method} \alias{viewApply,RleViewsList-method} \alias{viewMins} \alias{viewMins,RleViews-method} \alias{viewMins,RleViewsList-method} \alias{viewMaxs} \alias{viewMaxs,RleViews-method} \alias{viewMaxs,RleViewsList-method} \alias{viewSums} \alias{viewSums,RleViews-method} \alias{viewSums,RleViewsList-method} \alias{viewMeans} \alias{viewMeans,RleViews-method} \alias{viewMeans,RleViewsList-method} \alias{viewWhichMins} \alias{viewWhichMins,RleViews-method} \alias{viewWhichMins,RleViewsList-method} \alias{viewWhichMaxs} \alias{viewWhichMaxs,RleViews-method} \alias{viewWhichMaxs,RleViewsList-method} \alias{viewRangeMins} \alias{viewRangeMins,RleViews-method} \alias{viewRangeMins,RleViewsList-method} \alias{viewRangeMaxs} \alias{viewRangeMaxs,RleViews-method} \alias{viewRangeMaxs,RleViewsList-method} \alias{Summary,Views-method} \alias{mean,Views-method} \alias{max,Views-method} \alias{min,Views-method} \alias{sum,Views-method} \alias{which.min,Views-method} \alias{which.max,Views-method} \title{Summarize views on a vector-like object with numeric values} \description{ \code{viewApply} applies a function on each view of a \link{Views} or \link{ViewsList} object. \code{viewMins}, \code{viewMaxs}, \code{viewSums}, \code{viewMeans} calculate respectively the minima, maxima, sums, and means of the views in a \link{Views} or \link{ViewsList} object. } \usage{ viewApply(X, FUN, ..., simplify = TRUE) viewMins(x, na.rm=FALSE) \S4method{min}{Views}(x, ..., na.rm = FALSE) viewMaxs(x, na.rm=FALSE) \S4method{max}{Views}(x, ..., na.rm = FALSE) viewSums(x, na.rm=FALSE) \S4method{sum}{Views}(x, ..., na.rm = FALSE) viewMeans(x, na.rm=FALSE) \S4method{mean}{Views}(x, ...) viewWhichMins(x, na.rm=FALSE) \S4method{which.min}{Views}(x) viewWhichMaxs(x, na.rm=FALSE) \S4method{which.max}{Views}(x) viewRangeMins(x, na.rm=FALSE) viewRangeMaxs(x, na.rm=FALSE) } \arguments{ \item{X}{ A Views object. } \item{FUN}{ The function to be applied to each view in \code{X}. } \item{...}{ Additional arguments to be passed on. } \item{simplify}{ A logical value specifying whether or not the result should be simplified to a vector or matrix if possible. } \item{x}{ An \link{RleViews} or \link{RleViewsList} object. } \item{na.rm}{ Logical indicating whether or not to include missing values in the results. } } \details{ The \code{viewMins}, \code{viewMaxs}, \code{viewSums}, and \code{viewMeans} functions provide efficient methods for calculating the specified numeric summary by performing the looping in compiled code. The \code{viewWhichMins}, \code{viewWhichMaxs}, \code{viewRangeMins}, and \code{viewRangeMaxs} functions provide efficient methods for finding the locations of the minima and maxima. } \value{ For all the functions in this man page (except \code{viewRangeMins} and \code{viewRangeMaxs}): A numeric vector of the length of \code{x} if \code{x} is an \link{RleViews} object, or a \link{List} object of the length of \code{x} if it's an \link{RleViewsList} object. For \code{viewRangeMins} and \code{viewRangeMaxs}: An \link{IRanges} object if \code{x} is an \link{RleViews} object, or an \link{IRangesList} object if it's an \link{RleViewsList} object. } \note{ For convenience, methods for \code{min}, \code{max}, \code{sum}, \code{mean}, \code{which.min} and \code{which.max} are provided as wrappers around the corresponding \code{view*} functions (which might be deprecated at some point). } \author{P. Aboyoun} \seealso{ \itemize{ \item The \code{\link{slice}} function for slicing an \link{Rle} or \link{RleList} object. \item \link[XVector]{view-summarization-methods} in the \pkg{XVector} package for more view summarization methods. \item The \link{RleViews} and \link{RleViewsList} classes. \item The \code{\link{which.min}} and \code{\link{colSums}} functions. } } \examples{ ## Views derived from coverage x <- IRanges(start=c(1L, 9L, 4L, 1L, 5L, 10L), width=c(5L, 6L, 3L, 4L, 3L, 3L)) cvg <- coverage(x) cvg_views <- slice(cvg, lower=2) viewApply(cvg_views, diff) viewMins(cvg_views) viewMaxs(cvg_views) viewSums(cvg_views) viewMeans(cvg_views) viewWhichMins(cvg_views) viewWhichMaxs(cvg_views) viewRangeMins(cvg_views) viewRangeMaxs(cvg_views) } \keyword{methods} \keyword{arith} IRanges/src/0000755000175100017510000000000012612026576013720 5ustar00biocbuildbiocbuildIRanges/src/CompressedAtomicList_utils.c0000644000175100017510000001067112612026576021406 0ustar00biocbuildbiocbuild/**************************************************************************** * Utilities for CompressedAtomicList objects * ****************************************************************************/ #include "IRanges.h" #define R_INT_MIN (1+INT_MIN) #define PARTITIONED_SUM(C_TYPE, ACCESSOR, ANS_TYPE, ANS_ACCESSOR, NA_CHECK) { \ PARTITIONED_AGG(C_TYPE, ACCESSOR, ANS_TYPE, ANS_ACCESSOR, NA_CHECK, 0, \ summary += val); \ } #define PARTITIONED_MIN(C_TYPE, ACCESSOR, ANS_TYPE, NA_CHECK, INIT) { \ PARTITIONED_AGG(C_TYPE, ACCESSOR, ANS_TYPE, ACCESSOR, NA_CHECK, INIT, \ if (val < summary) summary = val); \ } #define PARTITIONED_MAX(C_TYPE, ACCESSOR, ANS_TYPE, NA_CHECK, INIT) { \ PARTITIONED_AGG(C_TYPE, ACCESSOR, ANS_TYPE, ACCESSOR, NA_CHECK, INIT, \ if (val > summary) summary = val); \ } #define PARTITIONED_AGG(C_TYPE, ACCESSOR, ANS_TYPE, ANS_ACCESSOR, NA_CHECK, \ INIT, UPDATE) { \ SEXP unlistData = _get_CompressedList_unlistData(x); \ SEXP ends = \ _get_PartitioningByEnd_end(_get_CompressedList_partitioning(x)); \ Rboolean _na_rm = asLogical(na_rm); \ int prev_end = 0; \ SEXP ans = allocVector(ANS_TYPE, length(ends)); \ for (int i = 0; i < length(ends); i++) { \ int end = INTEGER(ends)[i]; \ int summary = INIT; \ for (int j = prev_end; j < end; j++) { \ C_TYPE val = ACCESSOR(unlistData)[j]; \ if (NA_CHECK) { \ if (_na_rm) { \ continue; \ } else { \ summary = NA_ ## ANS_ACCESSOR; \ break; \ } \ } \ UPDATE; \ } \ ANS_ACCESSOR(ans)[i] = summary; \ prev_end = end; \ } \ setAttrib(ans, R_NamesSymbol, _get_CompressedList_names(x)); \ return ans; \ } /* * --- .Call ENTRY POINT --- */ SEXP CompressedLogicalList_sum(SEXP x, SEXP na_rm) { PARTITIONED_SUM(Rboolean, LOGICAL, INTSXP, INTEGER, val == NA_LOGICAL); } /* * --- .Call ENTRY POINT --- */ SEXP CompressedIntegerList_sum(SEXP x, SEXP na_rm) { PARTITIONED_SUM(int, INTEGER, INTSXP, INTEGER, val == NA_INTEGER); } /* * --- .Call ENTRY POINT --- */ SEXP CompressedNumericList_sum(SEXP x, SEXP na_rm) { PARTITIONED_SUM(double, REAL, REALSXP, REAL, ISNA(val)); } /* * --- .Call ENTRY POINT --- */ SEXP CompressedLogicalList_min(SEXP x, SEXP na_rm) { PARTITIONED_MIN(Rboolean, LOGICAL, LGLSXP, val == NA_LOGICAL, TRUE); } /* * --- .Call ENTRY POINT --- */ SEXP CompressedIntegerList_min(SEXP x, SEXP na_rm) { PARTITIONED_MIN(int, INTEGER, INTSXP, val == NA_INTEGER, INT_MAX); } /* * --- .Call ENTRY POINT --- */ SEXP CompressedNumericList_min(SEXP x, SEXP na_rm) { PARTITIONED_MIN(double, REAL, REALSXP, ISNA(val), R_PosInf); } /* * --- .Call ENTRY POINT --- */ SEXP CompressedLogicalList_max(SEXP x, SEXP na_rm) { PARTITIONED_MAX(Rboolean, LOGICAL, LGLSXP, val == NA_LOGICAL, TRUE); } /* * --- .Call ENTRY POINT --- */ SEXP CompressedIntegerList_max(SEXP x, SEXP na_rm) { PARTITIONED_MAX(int, INTEGER, INTSXP, val == NA_INTEGER, R_INT_MIN); } /* * --- .Call ENTRY POINT --- */ SEXP CompressedNumericList_max(SEXP x, SEXP na_rm) { PARTITIONED_MAX(double, REAL, REALSXP, ISNA(val), R_NegInf); } IRanges/src/CompressedIRangesList_class.c0000644000175100017510000001306512612026576021467 0ustar00biocbuildbiocbuild/**************************************************************************** * Low-level manipulation of CompressedIRangesList objects * ****************************************************************************/ #include "IRanges.h" #include "S4Vectors_interface.h" #include #define R_INT_MIN (1+INT_MIN) /**************************************************************************** * C-level abstract getters. */ CompressedIRangesList_holder _hold_CompressedIRangesList(SEXP x) { CompressedIRangesList_holder x_holder; SEXP x_end; x_holder.classname = get_classname(x); x_end = _get_PartitioningByEnd_end( _get_CompressedList_partitioning(x)); x_holder.length = LENGTH(x_end); x_holder.end = INTEGER(x_end); x_holder.unlistData_holder = _hold_IRanges( _get_CompressedList_unlistData(x)); return x_holder; } int _get_length_from_CompressedIRangesList_holder( const CompressedIRangesList_holder *x_holder) { return x_holder->length; } IRanges_holder _get_elt_from_CompressedIRangesList_holder( const CompressedIRangesList_holder *x_holder, int i) { int offset, length; offset = i == 0 ? 0 : x_holder->end[i - 1]; length = x_holder->end[i] - offset; return _get_linear_subset_from_IRanges_holder( &(x_holder->unlistData_holder), offset, length); } int _get_eltlens_from_CompressedIRangesList_holder( const CompressedIRangesList_holder *x_holder, int i) { /* IRanges_holder ir_holder; ir_holder = _get_elt_from_CompressedIRangesList_holder(x_holder, i); return _get_length_from_IRanges_holder(&ir_holder); */ int offset; offset = i == 0 ? 0 : x_holder->end[i - 1]; return x_holder->end[i] - offset; /* faster than the above */ } /**************************************************************************** * CompressedIRangesList methods. */ /* --- .Call ENTRY POINT --- */ SEXP CompressedIRangesList_isNormal(SEXP x, SEXP use_names) { SEXP ans, ans_names; CompressedIRangesList_holder x_holder; IRanges_holder ir_holder; int x_len, i; x_holder = _hold_CompressedIRangesList(x); x_len = _get_length_from_CompressedIRangesList_holder(&x_holder); PROTECT(ans = NEW_LOGICAL(x_len)); for (i = 0; i < x_len; i++) { ir_holder = _get_elt_from_CompressedIRangesList_holder(&x_holder, i); LOGICAL(ans)[i] = _is_normal_IRanges_holder(&ir_holder); } if (LOGICAL(use_names)[0]) { PROTECT(ans_names = duplicate(_get_CompressedList_names(x))); SET_NAMES(ans, ans_names); UNPROTECT(1); } UNPROTECT(1); return ans; } /* --- .Call ENTRY POINT --- */ SEXP CompressedIRangesList_summary(SEXP object) { int ans_len; SEXP part_end; SEXP ans, ans_names, col_names; part_end = _get_PartitioningByEnd_end( _get_CompressedList_partitioning(object)); ans_len = LENGTH(part_end); PROTECT(ans = allocMatrix(INTSXP, ans_len, 2)); memset(INTEGER(ans), 0, 2 * ans_len * sizeof(int)); if (ans_len > 0) { int i, j, prev_end = 0; int *ans1_elt, *ans2_elt; const int *part_end_elt, *ranges_width; SEXP unlistData = _get_CompressedList_unlistData(object); ranges_width = INTEGER(_get_IRanges_width(unlistData)); for (i = 0, ans1_elt = INTEGER(ans), ans2_elt = (INTEGER(ans) + ans_len), part_end_elt = INTEGER(part_end); i < ans_len; i++, ans1_elt++, ans2_elt++, part_end_elt++) { *ans1_elt = *part_end_elt - prev_end; for (j = 0; j < *ans1_elt; j++) { *ans2_elt += *ranges_width; ranges_width++; } prev_end = *part_end_elt; } } PROTECT(ans_names = NEW_LIST(2)); PROTECT(col_names = NEW_CHARACTER(2)); SET_STRING_ELT(col_names, 0, mkChar("Length")); SET_STRING_ELT(col_names, 1, mkChar("WidthSum")); SET_VECTOR_ELT(ans_names, 0, duplicate(_get_CompressedList_names(object))); SET_VECTOR_ELT(ans_names, 1, col_names); SET_DIMNAMES(ans, ans_names); UNPROTECT(3); return ans; } /**************************************************************************** * CompressedNormalIRangesList methods. */ /* --- .Call ENTRY POINT --- */ SEXP CompressedNormalIRangesList_min(SEXP x, SEXP use_names) { SEXP ans, ans_names; CompressedIRangesList_holder x_holder; IRanges_holder ir_holder; int x_len, ir_len, i; int *ans_elt; x_holder = _hold_CompressedIRangesList(x); x_len = _get_length_from_CompressedIRangesList_holder(&x_holder); PROTECT(ans = NEW_INTEGER(x_len)); for (i = 0, ans_elt = INTEGER(ans); i < x_len; i++, ans_elt++) { ir_holder = _get_elt_from_CompressedIRangesList_holder(&x_holder, i); ir_len = _get_length_from_IRanges_holder(&ir_holder); if (ir_len == 0) { *ans_elt = INT_MAX; } else { *ans_elt = _get_start_elt_from_IRanges_holder(&ir_holder, 0); } } if (LOGICAL(use_names)[0]) { PROTECT(ans_names = duplicate(_get_CompressedList_names(x))); SET_NAMES(ans, ans_names); UNPROTECT(1); } UNPROTECT(1); return ans; } /* --- .Call ENTRY POINT --- */ SEXP CompressedNormalIRangesList_max(SEXP x, SEXP use_names) { SEXP ans, ans_names; CompressedIRangesList_holder x_holder; IRanges_holder ir_holder; int x_len, ir_len, i; int *ans_elt; x_holder = _hold_CompressedIRangesList(x); x_len = _get_length_from_CompressedIRangesList_holder(&x_holder); PROTECT(ans = NEW_INTEGER(x_len)); for (i = 0, ans_elt = INTEGER(ans); i < x_len; i++, ans_elt++) { ir_holder = _get_elt_from_CompressedIRangesList_holder(&x_holder, i); ir_len = _get_length_from_IRanges_holder(&ir_holder); if (ir_len == 0) { *ans_elt = R_INT_MIN; } else { *ans_elt = _get_end_elt_from_IRanges_holder(&ir_holder, ir_len - 1); } } if (LOGICAL(use_names)[0]) { PROTECT(ans_names = duplicate(_get_CompressedList_names(x))); SET_NAMES(ans, ans_names); UNPROTECT(1); } UNPROTECT(1); return ans; } IRanges/src/CompressedList_class.c0000644000175100017510000000625612612026576020222 0ustar00biocbuildbiocbuild/**************************************************************************** * Low-level manipulation of CompressedList objects * ****************************************************************************/ #include "IRanges.h" /**************************************************************************** * C-level slot getters. * * Be careful that these functions do NOT duplicate the returned slot. * Thus they cannot be made .Call entry points! */ static SEXP unlistData_symbol = NULL, partitioning_symbol = NULL; SEXP _get_CompressedList_unlistData(SEXP x) { INIT_STATIC_SYMBOL(unlistData) return GET_SLOT(x, unlistData_symbol); } SEXP _get_CompressedList_partitioning(SEXP x) { INIT_STATIC_SYMBOL(partitioning) return GET_SLOT(x, partitioning_symbol); } /* Not strict "slot getters" but very much like. */ int _get_CompressedList_length(SEXP x) { return LENGTH(_get_PartitioningByEnd_end( _get_CompressedList_partitioning(x))); } SEXP _get_CompressedList_names(SEXP x) { return _get_Partitioning_names( _get_CompressedList_partitioning(x)); } /**************************************************************************** * C-level slot setters. * * Be careful that these functions do NOT duplicate the assigned value! */ static void set_CompressedList_unlistData(SEXP x, SEXP value) { INIT_STATIC_SYMBOL(unlistData) SET_SLOT(x, unlistData_symbol, value); return; } static void set_CompressedList_partitioning(SEXP x, SEXP value) { INIT_STATIC_SYMBOL(partitioning) SET_SLOT(x, partitioning_symbol, value); return; } /**************************************************************************** * C-level constructor. */ /* Be careful that this constructor does NOT duplicate its arguments before putting them in the slots of the returned object. So don't try to make it a .Call entry point! */ SEXP _new_CompressedList(const char *classname, SEXP unlistData, SEXP partitioning) { SEXP classdef, ans; PROTECT(classdef = MAKE_CLASS(classname)); PROTECT(ans = NEW_OBJECT(classdef)); set_CompressedList_unlistData(ans, unlistData); set_CompressedList_partitioning(ans, partitioning); UNPROTECT(2); return ans; } /**************************************************************************** * C-level abstract getters for CompressedIntegerList objects. */ CompressedIntsList_holder _hold_CompressedIntegerList(SEXP x) { SEXP partitioning_end; CompressedIntsList_holder x_holder; partitioning_end = _get_PartitioningByEnd_end( _get_CompressedList_partitioning(x)); x_holder.length = LENGTH(partitioning_end); x_holder.breakpoints = INTEGER(partitioning_end); x_holder.unlisted = INTEGER(_get_CompressedList_unlistData(x)); return x_holder; } int _get_length_from_CompressedIntsList_holder( const CompressedIntsList_holder *x_holder) { return x_holder->length; } Ints_holder _get_elt_from_CompressedIntsList_holder( const CompressedIntsList_holder *x_holder, int i) { Ints_holder x_elt_holder; int offset; if (i == 0) { offset = 0; } else { offset = x_holder->breakpoints[i - 1]; } x_elt_holder.ptr = x_holder->unlisted + offset; x_elt_holder.length = x_holder->breakpoints[i] - offset; return x_elt_holder; } IRanges/src/GappedRanges_class.c0000644000175100017510000000432212612026576017612 0ustar00biocbuildbiocbuild/**************************************************************************** * Low-level manipulation of GappedRanges objects * ****************************************************************************/ #include "IRanges.h" static const char *is_valid_GappedRanges_elt(const IRanges_holder *ir_holder) { if (_get_length_from_IRanges_holder(ir_holder) == 0) return "IRanges object has no ranges"; if (!_is_normal_IRanges_holder(ir_holder)) return "IRanges object is not normal"; return NULL; } /* * TODO: This is not needed anymore now that the 'cirl' slot has been * replaced by the 'cnirl' slot which is guaranteed to hold a * CompressedNormalIRangesList object (instead of just a CompressedIRangesList * object for the old slot). Hence the validity method for GappedRanges * should just check that all the elements in 'x@cnirl' are of length >= 1 * (which can be done in R with elementLengths()). * * We assume that 'x@cnirl' is already a valid CompressedIRangesList object. * Here we only check that its elements are normal and of length >= 1. * ans_type: a single integer specifying the type of answer to return: * 0: 'ans' is a string describing the first validity failure or NULL; * 1: 'ans' is logical vector with TRUE values for valid elements in 'x'. */ SEXP valid_GappedRanges(SEXP x, SEXP ans_type) { SEXP cnirl, ans; CompressedIRangesList_holder cnirl_holder; int x_len, ans_type0, i; IRanges_holder ir_holder; const char *errmsg; char string_buf[80]; cnirl = GET_SLOT(x, install("cnirl")); cnirl_holder = _hold_CompressedIRangesList(cnirl); x_len = _get_length_from_CompressedIRangesList_holder(&cnirl_holder); ans_type0 = INTEGER(ans_type)[0]; if (ans_type0 == 1) PROTECT(ans = NEW_LOGICAL(x_len)); else ans = R_NilValue; for (i = 0; i < x_len; i++) { ir_holder = _get_elt_from_CompressedIRangesList_holder(&cnirl_holder, i); errmsg = is_valid_GappedRanges_elt(&ir_holder); if (ans_type0 == 1) { LOGICAL(ans)[i] = errmsg == NULL; continue; } if (errmsg != NULL) { snprintf(string_buf, sizeof(string_buf), "element %d is invalid (%s)", i + 1, errmsg); return mkString(string_buf); } } if (ans_type0 == 1) UNPROTECT(1); return ans; } IRanges/src/Grouping_class.c0000644000175100017510000001101612612026576017042 0ustar00biocbuildbiocbuild/**************************************************************************** * Low-level manipulation of Grouping objects * * Author: Herve Pages * ****************************************************************************/ #include "IRanges.h" #include "S4Vectors_interface.h" static int debug = 0; SEXP debug_Grouping_class() { #ifdef DEBUG_IRANGES debug = !debug; Rprintf("Debug mode turned %s in file %s\n", debug ? "on" : "off", __FILE__); #else Rprintf("Debug mode not available in file %s\n", __FILE__); #endif return R_NilValue; } /**************************************************************************** * C-level slot getters. * * Be careful that these functions do NOT duplicate the returned slot. * Thus they cannot be made .Call entry points! */ static SEXP high2low_symbol = NULL, low2high_symbol = NULL, end_symbol = NULL, NAMES_symbol = NULL; SEXP _get_H2LGrouping_high2low(SEXP x) { INIT_STATIC_SYMBOL(high2low) return GET_SLOT(x, high2low_symbol); } SEXP _get_H2LGrouping_low2high(SEXP x) { INIT_STATIC_SYMBOL(low2high) return GET_SLOT(x, low2high_symbol); } SEXP _get_Partitioning_names(SEXP x) { INIT_STATIC_SYMBOL(NAMES) return GET_SLOT(x, NAMES_symbol); } SEXP _get_PartitioningByEnd_end(SEXP x) { INIT_STATIC_SYMBOL(end) return GET_SLOT(x, end_symbol); } /**************************************************************************** * C-level slot setters. * * Be careful that these functions do NOT duplicate the assigned value! */ static void set_Partitioning_names(SEXP x, SEXP value) { INIT_STATIC_SYMBOL(NAMES) SET_SLOT(x, NAMES_symbol, value); return; } static void set_PartitioningByEnd_end(SEXP x, SEXP value) { INIT_STATIC_SYMBOL(end) SET_SLOT(x, end_symbol, value); return; } /**************************************************************************** * C-level constructor. */ /* Be careful that this constructor does NOT duplicate its arguments before putting them in the slots of the returned object. So don't try to make it a .Call entry point! */ SEXP _new_PartitioningByEnd(const char *classname, SEXP end, SEXP names) { SEXP classdef, ans; PROTECT(classdef = MAKE_CLASS(classname)); PROTECT(ans = NEW_OBJECT(classdef)); set_PartitioningByEnd_end(ans, end); if (names == NULL) names = R_NilValue; set_Partitioning_names(ans, names); UNPROTECT(2); return ans; } /**************************************************************************** * --- .Call ENTRY POINTS --- * ****************************************************************************/ SEXP H2LGrouping_members(SEXP x, SEXP group_ids) { SEXP ans, x_high2low, x_low2high, x_low2high_elt; int x_length, nids, ans_length, i, j, group_id, *ans_elt; if (TYPEOF(group_ids) != INTSXP) error("the group ids must be integers"); x_high2low = _get_H2LGrouping_high2low(x); x_low2high = _get_H2LGrouping_low2high(x); x_length = LENGTH(x_low2high); /* same as LENGTH(x_high2low) */ nids = LENGTH(group_ids); /* 1st pass: determine 'ans_length' */ ans_length = 0; for (j = 0; j < nids; j++) { group_id = INTEGER(group_ids)[j]; if (group_id == NA_INTEGER) error("some group ids are NAs"); i = group_id - 1; if (i < 0 || i >= x_length) error("subscript out of bounds"); if (INTEGER(x_high2low)[i] != NA_INTEGER) continue; ans_length++; x_low2high_elt = VECTOR_ELT(x_low2high, i); if (x_low2high_elt == R_NilValue) continue; ans_length += LENGTH(x_low2high_elt); } PROTECT(ans = NEW_INTEGER(ans_length)); /* 2nd pass: fill 'ans' */ ans_elt = INTEGER(ans); for (j = 0; j < nids; j++) { group_id = INTEGER(group_ids)[j]; i = group_id - 1; if (INTEGER(x_high2low)[i] != NA_INTEGER) continue; *(ans_elt++) = i + 1; x_low2high_elt = VECTOR_ELT(x_low2high, i); if (x_low2high_elt == R_NilValue) continue; memcpy(ans_elt, INTEGER(x_low2high_elt), sizeof(int) * LENGTH(x_low2high_elt)); ans_elt += LENGTH(x_low2high_elt); } sort_int_array(INTEGER(ans), ans_length, 0); UNPROTECT(1); return ans; } SEXP H2LGrouping_vmembers(SEXP x, SEXP group_ids_list) { SEXP ans, group_ids; int ans_length, i; ans_length = LENGTH(group_ids_list); PROTECT(ans = NEW_LIST(ans_length)); for (i = 0; i < ans_length; i++) { group_ids = VECTOR_ELT(group_ids_list, i); if (TYPEOF(group_ids) != INTSXP) error("'L' must be a list of integer vectors"); SET_VECTOR_ELT(ans, i, H2LGrouping_members(x, group_ids)); } UNPROTECT(1); return ans; } IRanges/src/IRanges.h0000644000175100017510000001461312612026576015426 0ustar00biocbuildbiocbuild#include "../inst/include/IRanges_defines.h" #include #define DEBUG_IRANGES 1 #define INIT_STATIC_SYMBOL(NAME) \ { \ if (NAME ## _symbol == NULL) \ NAME ## _symbol = install(# NAME); \ } /* Ranges_class.c */ SEXP valid_Ranges( SEXP x_start, SEXP x_end, SEXP x_width ); /* Ranges_comparison.c */ int _overlap_code( int x_start, int x_width, int y_start, int y_width ); int _invert_overlap_code( int code ); SEXP Ranges_compare( SEXP x_start, SEXP x_width, SEXP y_start, SEXP y_width ); /* IRanges_class.c */ SEXP debug_IRanges_class(); SEXP _get_IRanges_start(SEXP x); SEXP _get_IRanges_width(SEXP x); SEXP _get_IRanges_names(SEXP x); int _get_IRanges_length(SEXP x); IRanges_holder _hold_IRanges(SEXP x); int _get_length_from_IRanges_holder(const IRanges_holder *x_holder); int _get_width_elt_from_IRanges_holder( const IRanges_holder *x_holder, int i ); int _get_start_elt_from_IRanges_holder( const IRanges_holder *x_holder, int i ); int _get_end_elt_from_IRanges_holder( const IRanges_holder *x_holder, int i ); SEXP _get_names_elt_from_IRanges_holder( const IRanges_holder *x_holder, int i ); IRanges_holder _get_linear_subset_from_IRanges_holder( const IRanges_holder *x_holder, int offset, int length ); void _set_IRanges_names( SEXP x, SEXP names ); void _copy_IRanges_slots( SEXP x, SEXP x0 ); SEXP _new_IRanges( const char *classname, SEXP start, SEXP width, SEXP names ); SEXP _new_IRanges_from_IntPairAE( const char *classname, const IntPairAE *intpair_ae ); SEXP _new_list_of_IRanges_from_IntPairAEAE( const char *element_type, const IntPairAEAE *intpair_aeae ); SEXP _alloc_IRanges( const char *classname, int length ); int _is_normal_IRanges_holder(const IRanges_holder *x_holder); SEXP IRanges_isNormal(SEXP x); SEXP IRanges_from_integer(SEXP x); SEXP NormalIRanges_from_logical(SEXP x); /* IRanges_constructor.c */ SEXP solve_user_SEW0( SEXP start, SEXP end, SEXP width ); SEXP solve_user_SEW( SEXP refwidths, SEXP start, SEXP end, SEXP width, SEXP translate_negative_coord, SEXP allow_nonnarrowing ); /* Grouping_class.c */ SEXP debug_Grouping_class(); SEXP _get_H2LGrouping_high2low(SEXP x); SEXP _get_H2LGrouping_low2high(SEXP x); SEXP _get_Partitioning_names(SEXP x); SEXP _get_PartitioningByEnd_end(SEXP x); SEXP _new_PartitioningByEnd( const char *classname, SEXP end, SEXP names ); SEXP H2LGrouping_members( SEXP x, SEXP group_ids ); SEXP H2LGrouping_vmembers( SEXP x, SEXP group_ids_list ); /* SimpleIRangesList_class.c */ SEXP SimpleIRangesList_isNormal(SEXP x); SEXP SimpleNormalIRangesList_min(SEXP x); SEXP SimpleNormalIRangesList_max(SEXP x); /* CompressedList_class.c */ SEXP _get_CompressedList_unlistData(SEXP x); SEXP _get_CompressedList_partitioning(SEXP x); int _get_CompressedList_length(SEXP x); SEXP _get_CompressedList_names(SEXP x); SEXP _new_CompressedList( const char *classname, SEXP unlistData, SEXP partitioning ); CompressedIntsList_holder _hold_CompressedIntegerList( SEXP x ); int _get_length_from_CompressedIntsList_holder( const CompressedIntsList_holder *x_holder ); Ints_holder _get_elt_from_CompressedIntsList_holder( const CompressedIntsList_holder *x_holder, int i ); /* RleViews_utils.c */ SEXP RleViews_viewMins( SEXP x, SEXP na_rm ); SEXP RleViews_viewMaxs( SEXP x, SEXP na_rm ); SEXP RleViews_viewSums( SEXP x, SEXP na_rm ); SEXP RleViews_viewMeans( SEXP x, SEXP na_rm ); SEXP RleViews_viewWhichMins( SEXP x, SEXP na_rm ); SEXP RleViews_viewWhichMaxs( SEXP x, SEXP na_rm ); /* CompressedIRangesList_class.c */ CompressedIRangesList_holder _hold_CompressedIRangesList(SEXP x); int _get_length_from_CompressedIRangesList_holder( const CompressedIRangesList_holder *x_holder ); IRanges_holder _get_elt_from_CompressedIRangesList_holder( const CompressedIRangesList_holder *x_holder, int i ); int _get_eltlens_from_CompressedIRangesList_holder( const CompressedIRangesList_holder *x_holder, int i ); SEXP CompressedIRangesList_isNormal( SEXP x, SEXP use_names ); SEXP CompressedIRangesList_summary( SEXP object ); SEXP CompressedNormalIRangesList_min( SEXP x, SEXP use_names ); SEXP CompressedNormalIRangesList_max( SEXP x, SEXP use_names ); /* GappedRanges_class.c */ SEXP valid_GappedRanges(SEXP x, SEXP ans_type); /* RangedData_class.c */ SEXP _new_RangedData( const char *classname, SEXP ranges, SEXP values ); /* inter_range_methods.c */ SEXP debug_inter_range_methods(); SEXP IRanges_range(SEXP x); SEXP Ranges_reduce( SEXP x_start, SEXP x_width, SEXP drop_empty_ranges, SEXP min_gapwidth, SEXP with_revmap, SEXP with_inframe_start ); SEXP CompressedIRangesList_reduce( SEXP x, SEXP drop_empty_ranges, SEXP min_gapwidth, SEXP with_revmap ); SEXP IRanges_gaps( SEXP x_start, SEXP x_width, SEXP start, SEXP end ); SEXP CompressedIRangesList_gaps( SEXP x, SEXP start, SEXP end ); SEXP Ranges_disjointBins( SEXP x_start, SEXP x_width ); /* coverage_methods.c */ SEXP IRanges_coverage( SEXP x, SEXP shift, SEXP width, SEXP weight, SEXP circle_len, SEXP method ); SEXP CompressedIRangesList_coverage( SEXP x, SEXP shift, SEXP width, SEXP weight, SEXP circle_lens, SEXP method ); /* NCList.c */ SEXP NCList_new(); SEXP NCList_free(SEXP nclist_xp); SEXP NCList_build( SEXP nclist_xp, SEXP x_start, SEXP x_end, SEXP x_subset ); SEXP new_NCListSXP_from_NCList( SEXP nclist_xp ); SEXP NCListSXP_print( SEXP x_nclist, SEXP x_start, SEXP x_end ); SEXP NCList_find_overlaps( SEXP q_start, SEXP q_end, SEXP s_start, SEXP s_end, SEXP nclist, SEXP nclist_is_q, SEXP min_score, SEXP type, SEXP select, SEXP circle_length ); SEXP NCList_find_overlaps_in_groups( SEXP q_start, SEXP q_end, SEXP q_space, SEXP q_groups, SEXP s_start, SEXP s_end, SEXP s_space, SEXP s_groups, SEXP nclists, SEXP nclist_is_q, SEXP min_score, SEXP type, SEXP select, SEXP circle_length ); /* CompressedAtomicList_utils.c */ SEXP CompressedLogicalList_sum( SEXP x, SEXP na_rm); SEXP CompressedIntegerList_sum( SEXP x, SEXP na_rm); SEXP CompressedNumericList_sum( SEXP x, SEXP na_rm); SEXP CompressedLogicalList_min( SEXP x, SEXP na_rm); SEXP CompressedIntegerList_min( SEXP x, SEXP na_rm); SEXP CompressedNumericList_min( SEXP x, SEXP na_rm); SEXP CompressedLogicalList_max( SEXP x, SEXP na_rm); SEXP CompressedIntegerList_max( SEXP x, SEXP na_rm); SEXP CompressedNumericList_max( SEXP x, SEXP na_rm); IRanges/src/IRanges_class.c0000644000175100017510000002435412612026576016611 0ustar00biocbuildbiocbuild/**************************************************************************** * Low-level manipulation of IRanges objects * * Author: Herve Pages * ****************************************************************************/ #include "IRanges.h" #include "S4Vectors_interface.h" static int debug = 0; SEXP debug_IRanges_class() { #ifdef DEBUG_IRANGES debug = !debug; Rprintf("Debug mode turned %s in file %s\n", debug ? "on" : "off", __FILE__); #else Rprintf("Debug mode not available in file %s\n", __FILE__); #endif return R_NilValue; } /**************************************************************************** * C-level slot getters. * * Be careful that these functions do NOT duplicate the returned slot. * Thus they cannot be made .Call entry points! */ static SEXP start_symbol = NULL, width_symbol = NULL, NAMES_symbol = NULL; SEXP _get_IRanges_start(SEXP x) { INIT_STATIC_SYMBOL(start) return GET_SLOT(x, start_symbol); } SEXP _get_IRanges_width(SEXP x) { INIT_STATIC_SYMBOL(width) return GET_SLOT(x, width_symbol); } SEXP _get_IRanges_names(SEXP x) { INIT_STATIC_SYMBOL(NAMES) return GET_SLOT(x, NAMES_symbol); } /* Not a strict "slot getter" but very much like. */ int _get_IRanges_length(SEXP x) { return LENGTH(_get_IRanges_start(x)); } /**************************************************************************** * C-level abstract getters. */ IRanges_holder _hold_IRanges(SEXP x) { IRanges_holder x_holder; x_holder.classname = get_classname(x); x_holder.is_constant_width = 0; x_holder.length = _get_IRanges_length(x); x_holder.width = INTEGER(_get_IRanges_width(x)); x_holder.start = INTEGER(_get_IRanges_start(x)); x_holder.end = NULL; x_holder.SEXP_offset = 0; x_holder.names = _get_IRanges_names(x); return x_holder; } int _get_length_from_IRanges_holder(const IRanges_holder *x_holder) { return x_holder->length; } int _get_width_elt_from_IRanges_holder(const IRanges_holder *x_holder, int i) { return x_holder->is_constant_width ? x_holder->width[0] : x_holder->width[i]; } int _get_start_elt_from_IRanges_holder(const IRanges_holder *x_holder, int i) { if (x_holder->start) return x_holder->start[i]; return x_holder->end[i] - _get_width_elt_from_IRanges_holder(x_holder, i) + 1; } int _get_end_elt_from_IRanges_holder(const IRanges_holder *x_holder, int i) { if (x_holder->end) return x_holder->end[i]; return x_holder->start[i] + _get_width_elt_from_IRanges_holder(x_holder, i) - 1; } SEXP _get_names_elt_from_IRanges_holder(const IRanges_holder *x_holder, int i) { return STRING_ELT(x_holder->names, x_holder->SEXP_offset + i); } IRanges_holder _get_linear_subset_from_IRanges_holder( const IRanges_holder *x_holder, int offset, int length) { IRanges_holder y_holder; y_holder = *x_holder; y_holder.length = length; y_holder.start += offset; if (!y_holder.is_constant_width) y_holder.width += offset; y_holder.SEXP_offset += offset; return y_holder; } /**************************************************************************** * C-level slot setters. * * Be careful that these functions do NOT duplicate the assigned value! */ static void set_IRanges_start(SEXP x, SEXP value) { INIT_STATIC_SYMBOL(start) SET_SLOT(x, start_symbol, value); return; } static void set_IRanges_width(SEXP x, SEXP value) { INIT_STATIC_SYMBOL(width) SET_SLOT(x, width_symbol, value); /* Rprintf("set_IRanges_width(): value=%p _get_IRanges_width(x)=%p\n", value, _get_IRanges_width(x)); */ return; } static void set_IRanges_names(SEXP x, SEXP value) { INIT_STATIC_SYMBOL(NAMES) SET_SLOT(x, NAMES_symbol, value); return; } /* WARNING: Use only AFTER 'x@start' has been set! Because this setter is trying to figure out what the length of 'x' is. */ void _set_IRanges_names(SEXP x, SEXP names) { if (names == NULL) names = R_NilValue; else if (names != R_NilValue && LENGTH(names) != _get_IRanges_length(x)) error("_set_IRanges_names(): " "number of names and number of elements differ"); set_IRanges_names(x, names); return; } /* Note that 'start' and 'width' must NOT contain NAs. set_IRanges_slots() trusts the caller and does NOT check this! */ static void set_IRanges_slots(SEXP x, SEXP start, SEXP width, SEXP names) { if (LENGTH(width) != LENGTH(start)) error("set_IRanges_slots(): " "number of starts and number of widths differ"); set_IRanges_start(x, start); set_IRanges_width(x, width); _set_IRanges_names(x, names); return; } void _copy_IRanges_slots(SEXP x, SEXP x0) { SEXP slot; PROTECT(slot = duplicate(_get_IRanges_start(x0))); set_IRanges_start(x, slot); UNPROTECT(1); PROTECT(slot = duplicate(_get_IRanges_width(x0))); set_IRanges_width(x, slot); UNPROTECT(1); PROTECT(slot = duplicate(_get_IRanges_names(x0))); set_IRanges_names(x, slot); UNPROTECT(1); return; } /**************************************************************************** * C-level constructors. */ /* Be careful that this constructor does NOT duplicate its arguments before putting them in the slots of the returned object. So don't try to make it a .Call entry point! */ SEXP _new_IRanges(const char *classname, SEXP start, SEXP width, SEXP names) { SEXP classdef, ans; PROTECT(classdef = MAKE_CLASS(classname)); PROTECT(ans = NEW_OBJECT(classdef)); set_IRanges_slots(ans, start, width, names); UNPROTECT(2); return ans; } SEXP _new_IRanges_from_IntPairAE(const char *classname, const IntPairAE *intpair_ae) { SEXP ans, start, width; PROTECT(start = new_INTEGER_from_IntAE(intpair_ae->a)); PROTECT(width = new_INTEGER_from_IntAE(intpair_ae->b)); PROTECT(ans = _new_IRanges(classname, start, width, R_NilValue)); UNPROTECT(3); return ans; } /* TODO: Try to make this faster by making only 1 call to _new_IRanges() (or _alloc_IRanges()) and cloning and modifying this initial object inside the for loop. */ SEXP _new_list_of_IRanges_from_IntPairAEAE(const char *element_type, const IntPairAEAE *intpair_aeae) { SEXP ans, ans_elt; int nelt, i; const IntPairAE *ae; nelt = IntPairAEAE_get_nelt(intpair_aeae); PROTECT(ans = NEW_LIST(nelt)); for (i = 0; i < nelt; i++) { ae = intpair_aeae->elts[i]; PROTECT(ans_elt = _new_IRanges_from_IntPairAE(element_type, ae)); SET_VECTOR_ELT(ans, i, ans_elt); UNPROTECT(1); } UNPROTECT(1); return ans; } /* Allocation WITHOUT initialization. The 'start' and 'width' slots are not initialized (they contain junk). */ SEXP _alloc_IRanges(const char *classname, int length) { SEXP start, width, ans; PROTECT(start = NEW_INTEGER(length)); PROTECT(width = NEW_INTEGER(length)); PROTECT(ans = _new_IRanges(classname, start, width, R_NilValue)); UNPROTECT(3); return ans; } /**************************************************************************** * Validity functions. */ int _is_normal_IRanges_holder(const IRanges_holder *x_holder) { int x_len, i; x_len = _get_length_from_IRanges_holder(x_holder); if (x_len == 0) return 1; if (_get_width_elt_from_IRanges_holder(x_holder, 0) <= 0) return 0; for (i = 1; i < x_len; i++) { if (_get_width_elt_from_IRanges_holder(x_holder, i) <= 0) return 0; if (_get_start_elt_from_IRanges_holder(x_holder, i) <= _get_end_elt_from_IRanges_holder(x_holder, i - 1) + 1) return 0; } return 1; } /* --- .Call ENTRY POINT --- */ SEXP IRanges_isNormal(SEXP x) { IRanges_holder ir_holder; ir_holder = _hold_IRanges(x); return ScalarLogical(_is_normal_IRanges_holder(&ir_holder)); } /**************************************************************************** * Coercion functions. */ /* --- .Call ENTRY POINT --- */ SEXP IRanges_from_integer(SEXP x) { SEXP ans, ans_start, ans_width; int i, x_length, ans_length; int *start_buf, *width_buf; int *x_elt, *start_elt, *width_elt, prev_elt_plus1; x_length = LENGTH(x); if (x_length == 0) { PROTECT(ans_start = NEW_INTEGER(0)); PROTECT(ans_width = NEW_INTEGER(0)); } else { ans_length = 1; start_buf = (int *) R_alloc((long) x_length, sizeof(int)); width_buf = (int *) R_alloc((long) x_length, sizeof(int)); start_buf[0] = INTEGER(x)[0]; width_buf[0] = 1; prev_elt_plus1 = start_buf[0] + 1; start_elt = start_buf; width_elt = width_buf; for (i = 1, x_elt = (INTEGER(x)+1); i < x_length; i++, x_elt++) { if (*x_elt == NA_INTEGER) error("cannot create an IRanges object from an integer vector with missing values"); if (*x_elt == prev_elt_plus1) { *width_elt += 1; } else { ans_length++; start_elt++; width_elt++; *start_elt = *x_elt; *width_elt = 1; prev_elt_plus1 = *x_elt; } prev_elt_plus1++; } PROTECT(ans_start = NEW_INTEGER(ans_length)); PROTECT(ans_width = NEW_INTEGER(ans_length)); memcpy(INTEGER(ans_start), start_buf, sizeof(int) * ans_length); memcpy(INTEGER(ans_width), width_buf, sizeof(int) * ans_length); } PROTECT(ans = _new_IRanges("IRanges", ans_start, ans_width, R_NilValue)); UNPROTECT(3); return ans; } /* --- .Call ENTRY POINT --- */ SEXP NormalIRanges_from_logical(SEXP x) { SEXP ans, ans_start, ans_width; int i, x_length, buf_length, ans_length; int *start_buf, *width_buf; int *x_elt, *start_elt, *width_elt, prev_elt; x_length = LENGTH(x); if (x_length == 0) { PROTECT(ans_start = NEW_INTEGER(0)); PROTECT(ans_width = NEW_INTEGER(0)); } else { buf_length = x_length / 2 + 1; ans_length = 0; start_buf = (int *) R_alloc((long) buf_length, sizeof(int)); width_buf = (int *) R_alloc((long) buf_length, sizeof(int)); prev_elt = 0; start_elt = start_buf - 1; width_elt = width_buf - 1; for (i = 1, x_elt = LOGICAL(x); i <= x_length; i++, x_elt++) { if (*x_elt == NA_LOGICAL) error("cannot create an IRanges object from a logical vector with missing values"); if (*x_elt == 1) { if (prev_elt) { *width_elt += 1; } else { ans_length++; start_elt++; width_elt++; *start_elt = i; *width_elt = 1; } } prev_elt = *x_elt; } PROTECT(ans_start = NEW_INTEGER(ans_length)); PROTECT(ans_width = NEW_INTEGER(ans_length)); memcpy(INTEGER(ans_start), start_buf, sizeof(int) * ans_length); memcpy(INTEGER(ans_width), width_buf, sizeof(int) * ans_length); } PROTECT(ans = _new_IRanges("NormalIRanges", ans_start, ans_width, R_NilValue)); UNPROTECT(3); return ans; } IRanges/src/IRanges_constructor.c0000644000175100017510000001326612612026576020071 0ustar00biocbuildbiocbuild/**************************************************************************** * Support functions for the IRanges constructor * ****************************************************************************/ #include "IRanges.h" static char errmsg_buf[200]; /**************************************************************************** * solve_user_SEW0() */ static int solve_user_SEW0_row(int start, int end, int width, int *solved_start, int *solved_width) { int nb_of_unknowns; nb_of_unknowns = (start == NA_INTEGER) + (end == NA_INTEGER) + (width == NA_INTEGER); if (nb_of_unknowns >= 2) { snprintf(errmsg_buf, sizeof(errmsg_buf), "range cannot be determined from the supplied arguments (too many NAs)"); return -1; } if (start == NA_INTEGER) { start = end - width + 1; } else if (width == NA_INTEGER) { width = end - start + 1; } else if (end != NA_INTEGER && end != start + width - 1) { snprintf(errmsg_buf, sizeof(errmsg_buf), "supplied arguments are incompatible"); return -1; } if (width < 0) { snprintf(errmsg_buf, sizeof(errmsg_buf), "negative widths are not allowed"); return -1; } *solved_start = start; *solved_width = width; return 0; } SEXP solve_user_SEW0(SEXP start, SEXP end, SEXP width) { SEXP ans, ans_start, ans_width; int ans_length, i; ans_length = LENGTH(start); PROTECT(ans_start = NEW_INTEGER(ans_length)); PROTECT(ans_width = NEW_INTEGER(ans_length)); for (i = 0; i < ans_length; i++) { if (solve_user_SEW0_row(INTEGER(start)[i], INTEGER(end)[i], INTEGER(width)[i], INTEGER(ans_start) + i, INTEGER(ans_width) + i) != 0) { UNPROTECT(2); error("solving row %d: %s", i + 1, errmsg_buf); } } PROTECT(ans = _new_IRanges("IRanges", ans_start, ans_width, R_NilValue)); UNPROTECT(3); return ans; } /**************************************************************************** * solve_user_SEW() */ static int translate_negative_coord0; static int nonnarrowing_is_OK; static int translate_negative_startorend(int refwidth, int startorend) { if (startorend < 0) startorend += refwidth + 1; return startorend; } static int check_start(int refwidth, int start, const char *what) { if (nonnarrowing_is_OK) return 0; if (start < 1) { snprintf(errmsg_buf, sizeof(errmsg_buf), "'allow.nonnarrowing' is FALSE and the %s start " "(%d) is < 1", what, start); return -1; } if (start > refwidth + 1) { snprintf(errmsg_buf, sizeof(errmsg_buf), "'allow.nonnarrowing' is FALSE and the %s start " "(%d) is > refwidth + 1", what, start); return -1; } return 0; } static int check_end(int refwidth, int end, const char *what) { if (nonnarrowing_is_OK) return 0; if (end < 0) { snprintf(errmsg_buf, sizeof(errmsg_buf), "'allow.nonnarrowing' is FALSE and the %s end " "(%d) is < 0", what, end); return -1; } if (end > refwidth) { snprintf(errmsg_buf, sizeof(errmsg_buf), "'allow.nonnarrowing' is FALSE and the %s end " "(%d) is > refwidth", what, end); return -1; } return 0; } static int solve_user_SEW_row(int refwidth, int start, int end, int width, int *solved_start, int *solved_width) { if (refwidth == NA_INTEGER || refwidth < 0) { snprintf(errmsg_buf, sizeof(errmsg_buf), "negative values or NAs are not allowed in 'refwidths'"); return -1; } if (start != NA_INTEGER) { if (translate_negative_coord0) start = translate_negative_startorend(refwidth, start); if (check_start(refwidth, start, "supplied") != 0) return -1; } if (end != NA_INTEGER) { if (translate_negative_coord0) end = translate_negative_startorend(refwidth, end); if (check_end(refwidth, end, "supplied") != 0) return -1; } if (width == NA_INTEGER) { if (start == NA_INTEGER) start = 1; if (end == NA_INTEGER) end = refwidth; width = end - start + 1; if (width < 0) { snprintf(errmsg_buf, sizeof(errmsg_buf), "the supplied start/end lead to a " "negative width"); return -1; } } else if (width < 0) { snprintf(errmsg_buf, sizeof(errmsg_buf), "negative values are not allowed in 'width'"); return -1; } else if ((start == NA_INTEGER) == (end == NA_INTEGER)) { snprintf(errmsg_buf, sizeof(errmsg_buf), "either the supplied start or the supplied end " "(but not both) must be NA when the supplied width " "is not NA"); return -1; } else { // Either 'start' or 'end' is NA if (start == NA_INTEGER) { start = end - width + 1; if (check_start(refwidth, start, "solved") != 0) return -1; } else { end = start + width - 1; if (check_end(refwidth, end, "solved") != 0) return -1; } } *solved_start = start; *solved_width = width; return 0; } /* * --- .Call ENTRY POINT --- */ SEXP solve_user_SEW(SEXP refwidths, SEXP start, SEXP end, SEXP width, SEXP translate_negative_coord, SEXP allow_nonnarrowing) { SEXP ans, ans_start, ans_width; int ans_length, i0, i1, i2, i3; translate_negative_coord0 = LOGICAL(translate_negative_coord)[0]; nonnarrowing_is_OK = LOGICAL(allow_nonnarrowing)[0]; ans_length = LENGTH(refwidths); PROTECT(ans_start = NEW_INTEGER(ans_length)); PROTECT(ans_width = NEW_INTEGER(ans_length)); for (i0 = i1 = i2 = i3 = 0; i0 < ans_length; i0++, i1++, i2++, i3++) { /* recycling */ if (i1 >= LENGTH(start)) i1 = 0; if (i2 >= LENGTH(end)) i2 = 0; if (i3 >= LENGTH(width)) i3 = 0; if (solve_user_SEW_row(INTEGER(refwidths)[i0], INTEGER(start)[i1], INTEGER(end)[i2], INTEGER(width)[i3], INTEGER(ans_start) + i0, INTEGER(ans_width) + i0) != 0) { UNPROTECT(2); error("solving row %d: %s", i0 + 1, errmsg_buf); } } PROTECT(ans = _new_IRanges("IRanges", ans_start, ans_width, R_NilValue)); UNPROTECT(3); return ans; } IRanges/src/NCList.c0000644000175100017510000007477212612026576015241 0ustar00biocbuildbiocbuild/**************************************************************************** * A Nested Containment List implementation * * * * Author: Herve Pages * ****************************************************************************/ #include "IRanges.h" #include "S4Vectors_interface.h" #include /* for malloc, realloc, free, qsort */ #include /* for log10 */ /* #include static clock_t clock0; static void init_clock(const char *msg) { printf("%s", msg); clock0 = clock(); } static void print_elapsed_time() { printf("%8.6f s\n", ((double) clock() - clock0) / CLOCKS_PER_SEC); } */ typedef struct nclist_t { int buflength; /* >= 0 */ int nelt; /* >= 0 and <= buflength */ int *revmap; /* Of length 'nelt'. Reverse mapping into Ranges object 'x'. Contains 0-based indices */ struct nclist_t *contained_list; /* Of length 'nelt' */ } NCList; static void init_NCList(NCList *nclist) { nclist->buflength = nclist->nelt = 0; return; } static void free_NCList(const NCList *nclist) { int n; const NCList *contained_list_p; if (nclist->buflength == 0) return; for (n = 0, contained_list_p = nclist->contained_list; n < nclist->nelt; n++, contained_list_p++) free_NCList(contained_list_p); free(nclist->revmap); free(nclist->contained_list); return; } /**************************************************************************** * NCList_new() and NCList_free() */ /* --- .Call ENTRY POINT --- */ SEXP NCList_new() { NCList *top_nclist; //init_clock("preprocessing: T1 = "); top_nclist = (NCList *) malloc(sizeof(NCList)); if (top_nclist == NULL) error("NCList_new: memory allocation failed"); init_NCList(top_nclist); return R_MakeExternalPtr(top_nclist, R_NilValue, R_NilValue); } /* --- .Call ENTRY POINT --- */ SEXP NCList_free(SEXP nclist_xp) { NCList *top_nclist; top_nclist = (NCList *) R_ExternalPtrAddr(nclist_xp); if (top_nclist == NULL) error("NCList_free: pointer to NCList struct is NULL"); free_NCList(top_nclist); free(top_nclist); R_SetExternalPtrAddr(nclist_xp, NULL); return R_NilValue; } /**************************************************************************** * NCList_build() */ static void extend_NCList(NCList *nclist) { int old_buflength, new_buflength; int *new_revmap; NCList *new_contained_list; old_buflength = nclist->buflength; if (old_buflength == 0) { new_buflength = 4; new_revmap = (int *) malloc(sizeof(int) * new_buflength); new_contained_list = (NCList *) malloc(sizeof(NCList) * new_buflength); } else { if (old_buflength < 16384) new_buflength = 8 * old_buflength; else if (old_buflength < 4194304) new_buflength = 4 * old_buflength; else if (old_buflength < 67108864) new_buflength = 2 * old_buflength; else new_buflength = old_buflength + 33554432; new_revmap = (int *) realloc(nclist->revmap, sizeof(int) * new_buflength); new_contained_list = (NCList *) realloc(nclist->contained_list, sizeof(NCList) * new_buflength); } if (new_revmap == NULL || new_contained_list == NULL) error("extend_NCList: memory allocation failed"); nclist->buflength = new_buflength; nclist->revmap = new_revmap; nclist->contained_list = new_contained_list; return; } static const int *aa, *bb; static int qsort_compar(const void *p1, const void *p2) { int i1, i2, ret; i1 = *((const int *) p1); i2 = *((const int *) p2); ret = aa[i1] - aa[i2]; if (ret != 0) return ret; ret = bb[i2] - bb[i1]; if (ret != 0) return ret; /* Break tie by position so the ordering is "stable". */ return i1 - i2; } /* * Setting a hard limit on the max depth of NCList objects to prevent C stack * overflows when running recursive code like NCList_get_y_overlaps(). * A better solution would be to not use recursive code at all when traversing * an NCList object. Then NCList objects of arbitrary depth could be supported * and it wouldn't be necessary to set the limit below. */ #define NCLIST_MAX_DEPTH 100000 typedef struct stack_elt_t { int revidx; NCList *contained_list; } StackElt; static StackElt *stack = NULL; static int stack_length = 0; static StackElt append_NCList_elt(NCList *host, int revidx) { StackElt stack_elt; if (host->nelt == host->buflength) extend_NCList(host); stack_elt.revidx = host->revmap[host->nelt] = revidx; stack_elt.contained_list = host->contained_list + host->nelt; init_NCList(stack_elt.contained_list); host->nelt++; return stack_elt; } static void extend_stack() { int new_length; StackElt *new_stack; if (stack_length == 0) { new_length = 1000; new_stack = (StackElt *) malloc(sizeof(StackElt) * new_length); } else { if (stack_length == NCLIST_MAX_DEPTH) error("extend_stack: cannot build an NCList object " "of depth >= %d", NCLIST_MAX_DEPTH); if (stack_length <= NCLIST_MAX_DEPTH / 2) new_length = 2 * stack_length; else new_length = NCLIST_MAX_DEPTH; new_stack = (StackElt *) realloc(stack, sizeof(StackElt) * new_length); } if (new_stack == NULL) error("extend_stack: memory allocation failed"); stack_length = new_length; stack = new_stack; return; } static void build_NCList(NCList *top_nclist, const int *x_start_p, const int *x_end_p, const int *x_subset_p, int x_len) { int *oo, k, d, i, current_end; NCList *host; StackElt stack_elt; /* Determine order of 'x'. 'oo' will be such that 'x[oo]' is sorted first by ascending start then by descending end. */ oo = (int *) R_alloc(sizeof(int), x_len); if (x_subset_p == NULL) for (i = 0; i < x_len; i++) oo[i] = i; else for (i = 0; i < x_len; i++) oo[i] = x_subset_p[i]; aa = x_start_p; bb = x_end_p; qsort(oo, x_len, sizeof(int), qsort_compar); init_NCList(top_nclist); for (k = 0, d = -1; k < x_len; k++) { i = oo[k]; current_end = x_end_p[i]; while (d >= 0 && x_end_p[stack[d].revidx] < current_end) d--; // unstack host = d == -1 ? top_nclist: stack[d].contained_list; // append range i to host stack_elt = append_NCList_elt(host, i); if (++d == stack_length) extend_stack(); stack[d] = stack_elt; // stack } return; } /* --- .Call ENTRY POINT --- */ SEXP NCList_build(SEXP nclist_xp, SEXP x_start, SEXP x_end, SEXP x_subset) { NCList *top_nclist; int x_len; const int *x_start_p, *x_end_p, *x_subset_p; top_nclist = (NCList *) R_ExternalPtrAddr(nclist_xp); if (top_nclist == NULL) error("NCList_build: pointer to NCList struct is NULL"); x_len = check_integer_pairs(x_start, x_end, &x_start_p, &x_end_p, "start(x)", "end(x)"); if (x_subset == R_NilValue) { x_subset_p = NULL; } else { x_subset_p = INTEGER(x_subset); x_len = LENGTH(x_subset); } build_NCList(top_nclist, x_start_p, x_end_p, x_subset_p, x_len); return nclist_xp; } /**************************************************************************** * new_NCListSXP_from_NCList() */ #define NCListSXP_NELT(nclist) ((nclist)[0]) #define NCListSXP_REVMAP(nclist) ((nclist)+1) #define NCListSXP_OFFSETS(nclist) ((nclist)+1+NCListSXP_NELT(nclist)) static int compute_length_of_NCListSXP(const NCList *nclist) { int nelt, n; unsigned int ans_len, dump_len; const NCList *contained_list_p; nelt = nclist->nelt; if (nelt == 0) return 0; ans_len = 1U + 2U * (unsigned int) nelt; for (n = 0, contained_list_p = nclist->contained_list; n < nelt; n++, contained_list_p++) { dump_len = compute_length_of_NCListSXP(contained_list_p); ans_len += dump_len; if (dump_len > ans_len) goto too_big; } if (ans_len <= INT_MAX) return (int) ans_len; too_big: error("compute_length_of_NCListSXP: " "NCList object is too big to fit in an integer vector"); } static int dump_NCList_to_int_array(const NCList *nclist, int *out) { int nelt, offset, dump_len, n; const int *revmap_p; const NCList *contained_list_p; nelt = nclist->nelt; if (nelt == 0) return 0; offset = 1 + 2 * nelt; NCListSXP_NELT(out) = nelt; for (n = 0, revmap_p = nclist->revmap, contained_list_p = nclist->contained_list; n < nelt; n++, revmap_p++, contained_list_p++) { NCListSXP_REVMAP(out)[n] = *revmap_p; dump_len = dump_NCList_to_int_array(contained_list_p, out + offset); NCListSXP_OFFSETS(out)[n] = dump_len != 0 ? offset : -1; offset += dump_len; } return offset; } /* --- .Call ENTRY POINT --- */ SEXP new_NCListSXP_from_NCList(SEXP nclist_xp) { SEXP ans; const NCList *top_nclist; int ans_len; top_nclist = (NCList *) R_ExternalPtrAddr(nclist_xp); if (top_nclist == NULL) error("new_NCListSXP_from_NCList: " "pointer to NCList struct is NULL"); ans_len = compute_length_of_NCListSXP(top_nclist); PROTECT(ans = NEW_INTEGER(ans_len)); dump_NCList_to_int_array(top_nclist, INTEGER(ans)); UNPROTECT(1); //print_elapsed_time(); return ans; } /**************************************************************************** * NCListSXP_print() */ /* Print 1 line per range in 'nclist'. Return max depth. */ static int print_NCListSXP(const int *nclist, const int *x_start_p, const int *x_end_p, int depth, const char *format) { int max_depth, nelt, n, d, revidx, offset, tmp; max_depth = depth; nelt = NCListSXP_NELT(nclist); for (n = 0; n < nelt; n++) { for (d = 1; d < depth; d++) Rprintf("|"); revidx = NCListSXP_REVMAP(nclist)[n]; Rprintf(format, revidx + 1); Rprintf(": [%d, %d]\n", x_start_p[revidx], x_end_p[revidx]); offset = NCListSXP_OFFSETS(nclist)[n]; if (offset != -1) { tmp = print_NCListSXP(nclist + offset, x_start_p, x_end_p, depth + 1, format); if (tmp > max_depth) max_depth = tmp; } } return max_depth; } /* --- .Call ENTRY POINT --- */ SEXP NCListSXP_print(SEXP x_nclist, SEXP x_start, SEXP x_end) { const int *top_nclist; int x_len, max_digits, max_depth; const int *x_start_p, *x_end_p; char format[10]; top_nclist = INTEGER(x_nclist); x_len = check_integer_pairs(x_start, x_end, &x_start_p, &x_end_p, "start(x)", "end(x)"); if (x_len == 0) { max_depth = 0; } else { max_digits = (int) log10((double) x_len) + 1; sprintf(format, "%c0%d%c", '%', max_digits, 'd'); max_depth = print_NCListSXP(top_nclist, x_start_p, x_end_p, 1, format); } Rprintf("max depth = %d\n", max_depth); return R_NilValue; } /**************************************************************************** * pp_find_overlaps() */ /* 6 supported types of overlap. */ #define TYPE_ANY 1 #define TYPE_START 2 #define TYPE_END 3 #define TYPE_WITHIN 4 #define TYPE_EXTEND 5 #define TYPE_EQUAL 6 typedef struct backpack_t { /* Members set by prepare_backpack(). */ const int *x_start_p; const int *x_end_p; const int *x_space_p; int min_overlap_score0; int overlap_type; int select_mode; int circle_len; int pp_is_q; IntAE *hits; int *direct_out; /* Members set by update_backpack(). */ int y_idx; int y_start; int y_end; int y_space; int wide_y_start; int wide_y_end; } Backpack; static int is_hit(int revidx, const Backpack *backpack) { static int x_space, x_start, x_end, d; /* Check the space */ if (backpack->x_space_p != NULL && backpack->y_space != 0) { x_space = backpack->x_space_p[revidx]; if (x_space != 0 && x_space != backpack->y_space) return 0; } /* Check the score */ x_start = backpack->x_start_p[revidx]; x_end = backpack->x_end_p[revidx]; if (x_end - x_start < backpack->min_overlap_score0) return 0; /* Check the type */ if (backpack->overlap_type == TYPE_ANY || backpack->overlap_type == TYPE_WITHIN) return 1; if (backpack->overlap_type == TYPE_EXTEND) return backpack->y_start <= x_start && backpack->y_end >= x_end; if (backpack->overlap_type == TYPE_START) { d = backpack->y_start - x_start; if (backpack->min_overlap_score0 >= 0) return d == 0; if (d > 0) d = -d; return d >= backpack->min_overlap_score0; } if (backpack->overlap_type == TYPE_END) { d = backpack->y_end - x_end; if (backpack->circle_len != NA_INTEGER) d %= backpack->circle_len; if (backpack->min_overlap_score0 >= 0) return d == 0; if (d > 0) d = -d; return d >= backpack->min_overlap_score0; } /* TYPE_EQUAL */ return backpack->y_start == x_start && backpack->y_end == x_end; } static void report_hit(int revidx, const Backpack *backpack) { int i1, q_idx, s_idx1, *selection_p; i1 = revidx + 1; /* 1-based */ if (backpack->select_mode == ALL_HITS) { /* Report the hit. */ IntAE_insert_at(backpack->hits, IntAE_get_nelt(backpack->hits), i1); return; } /* Update current selection if necessary. */ if (backpack->pp_is_q) { q_idx = revidx; s_idx1 = backpack->y_idx + 1; } else { q_idx = backpack->y_idx; s_idx1 = i1; } selection_p = backpack->direct_out + q_idx; if (backpack->select_mode == COUNT_HITS) { (*selection_p)++; return; } if (*selection_p == NA_INTEGER || (backpack->select_mode == FIRST_HIT) == (s_idx1 < *selection_p)) *selection_p = s_idx1; return; } static Backpack prepare_backpack(const int *x_start_p, const int *x_end_p, const int *x_space_p, int min_overlap_score, int overlap_type, int select_mode, int circle_len, int pp_is_q, IntAE *hits, int *direct_out) { Backpack backpack; backpack.x_start_p = x_start_p; backpack.x_end_p = x_end_p; backpack.x_space_p = x_space_p; backpack.min_overlap_score0 = min_overlap_score - 1; backpack.overlap_type = overlap_type; backpack.select_mode = select_mode; backpack.circle_len = circle_len; backpack.pp_is_q = pp_is_q; backpack.hits = hits; backpack.direct_out = direct_out; return backpack; } static void update_backpack(Backpack *backpack, int y_idx, int y_start, int y_end, int y_space) { backpack->y_idx = y_idx; backpack->y_start = y_start; backpack->y_end = y_end; backpack->y_space = y_space; backpack->wide_y_start = y_start + backpack->min_overlap_score0; backpack->wide_y_end = y_end - backpack->min_overlap_score0; return; } static void shift_y(Backpack *backpack, int shift) { backpack->y_start += shift; backpack->y_end += shift; backpack->wide_y_start += shift; backpack->wide_y_end += shift; return; } /* TODO: Maybe move this to S4Vectors/src/AEbufs.c */ static void IntAE_delete_duplicates(IntAE *int_ae, int at1, int at2) { int d, k0, k, val; d = at2 - at1; if (d <= 1) return; if (d >= 3) sort_int_array(int_ae->elts + at1, d, 0); k0 = at1; for (k = k0 + 1; k < at2; k++) { val = int_ae->elts[k]; if (val == int_ae->elts[k0]) continue; k0++; int_ae->elts[k0] = val; } IntAE_set_nelt(int_ae, k0 + 1); return; } typedef void (*GetYOverlapsFunType)(const void *, const Backpack *); static void pp_find_overlaps( const int *q_start_p, const int *q_end_p, const int *q_space_p, const int *q_subset_p, int q_len, const int *s_start_p, const int *s_end_p, const int *s_space_p, const int *s_subset_p, int s_len, int min_overlap_score, int overlap_type, int select_mode, int circle_len, const void *pp, int pp_is_q, GetYOverlapsFunType get_y_overlaps, IntAE *qh_buf, IntAE *sh_buf, int *direct_out) { const int *x_start_p, *x_end_p, *x_space_p, *y_start_p, *y_end_p, *y_space_p, *y_subset_p; int y_len, backpack_select_mode, i, j, y_start, y_end, old_nhit, new_nhit, k; IntAE *xh_buf, *yh_buf; Backpack backpack; if (q_len == 0 || s_len == 0) return; if (pp_is_q) { x_start_p = q_start_p; x_end_p = q_end_p; x_space_p = q_space_p; xh_buf = qh_buf; y_start_p = s_start_p; y_end_p = s_end_p; y_space_p = s_space_p; y_subset_p = s_subset_p; y_len = s_len; yh_buf = sh_buf; if (overlap_type == TYPE_WITHIN) overlap_type = TYPE_EXTEND; else if (overlap_type == TYPE_EXTEND) overlap_type = TYPE_WITHIN; } else { x_start_p = s_start_p; x_end_p = s_end_p; x_space_p = s_space_p; xh_buf = sh_buf; y_start_p = q_start_p; y_end_p = q_end_p; y_space_p = q_space_p; y_subset_p = q_subset_p; y_len = q_len; yh_buf = qh_buf; } if (circle_len != NA_INTEGER && select_mode == COUNT_HITS) backpack_select_mode = ALL_HITS; else backpack_select_mode = select_mode; backpack = prepare_backpack(x_start_p, x_end_p, x_space_p, min_overlap_score, overlap_type, backpack_select_mode, circle_len, pp_is_q, xh_buf, direct_out); for (i = 0; i < y_len; i++) { j = y_subset_p == NULL ? i : y_subset_p[i]; y_start = y_start_p[j]; y_end = y_end_p[j]; if (y_end - y_start < backpack.min_overlap_score0) continue; update_backpack(&backpack, j, y_start, y_end, y_space_p == NULL ? 0 : y_space_p[j]); /* pass 0 */ get_y_overlaps(pp, &backpack); if (circle_len == NA_INTEGER) goto life_is_good; if (select_mode == ARBITRARY_HIT && !pp_is_q && direct_out[j] != NA_INTEGER) goto life_is_good; /* pass 1 */ shift_y(&backpack, - circle_len); get_y_overlaps(pp, &backpack); if (select_mode == ARBITRARY_HIT && !pp_is_q && direct_out[j] != NA_INTEGER) goto life_is_good; /* pass 2 */ shift_y(&backpack, 2 * circle_len); get_y_overlaps(pp, &backpack); life_is_good: if (backpack_select_mode != ALL_HITS) continue; old_nhit = IntAE_get_nelt(yh_buf); new_nhit = IntAE_get_nelt(xh_buf); if (circle_len != NA_INTEGER) { IntAE_delete_duplicates(xh_buf, old_nhit, new_nhit); new_nhit = IntAE_get_nelt(xh_buf); } if (select_mode != COUNT_HITS) { j++; /* 1-based */ for (k = old_nhit; k < new_nhit; k++) IntAE_insert_at(yh_buf, k, j); continue; } if (pp_is_q) { for (k = old_nhit; k < new_nhit; k++) direct_out[xh_buf->elts[k] - 1]++; } else { direct_out[j] += new_nhit - old_nhit; } IntAE_set_nelt(xh_buf, old_nhit); } return; } /**************************************************************************** * bsearch_revmap() */ /* * 'subset_len' is assumed to be > 0. * Return the first index 'n' for which 'base[subset[n]] >= min', or * 'subset_len' if there is no such index. * TODO: Maybe move this to int_utils.c or sort_utils.c in S4Vectors/src/ */ static int int_bsearch(const int *subset, int subset_len, const int *base, int min) { int n1, n2, n, b; /* Check first element. */ n1 = 0; b = base[subset[n1]]; if (b >= min) return n1; /* Check last element. */ n2 = subset_len - 1; b = base[subset[n2]]; if (b < min) return subset_len; if (b == min) return n2; /* Binary search. Seems that using >> 1 instead of / 2 is faster, even when compiling with 'gcc -O2' (one would hope that the optimizer is able to do that kind of optimization). */ while ((n = (n1 + n2) >> 1) != n1) { b = base[subset[n]]; if (b == min) return n; if (b < min) n1 = n; else n2 = n; } return n2; } static int bsearch_revmap(const int *revmap, int revmap_len, const Backpack *backpack) { const int *base; int min; if (backpack->overlap_type == TYPE_WITHIN) { base = backpack->x_end_p; min = backpack->y_end; } else { base = backpack->x_end_p; min = backpack->wide_y_start; } return int_bsearch(revmap, revmap_len, base, min); } /**************************************************************************** * NCList_get_y_overlaps() */ /* Recursive! */ static void NCList_get_y_overlaps(const NCList *x_nclist, const Backpack *backpack) { const int *revmap_p, *base; int nelt, n, revidx, max; const NCList *contained_list_p; revmap_p = x_nclist->revmap; nelt = x_nclist->nelt; n = bsearch_revmap(revmap_p, nelt, backpack); for (revmap_p = revmap_p + n, contained_list_p = x_nclist->contained_list + n; n < nelt; n++, revmap_p++, contained_list_p++) { revidx = *revmap_p; if (backpack->overlap_type == TYPE_WITHIN) { base = backpack->x_start_p; max = backpack->y_start; } else { base = backpack->x_start_p; max = backpack->wide_y_end; } if (base[revidx] > max) break; if (is_hit(revidx, backpack)) { report_hit(revidx, backpack); if (backpack->select_mode == ARBITRARY_HIT && !backpack->pp_is_q) break; } if (contained_list_p->nelt != 0) NCList_get_y_overlaps(contained_list_p, backpack); } return; } /**************************************************************************** * NCListSXP_get_y_overlaps() */ /* Recursive! */ static void NCListSXP_get_y_overlaps(const int *x_nclist, const Backpack *backpack) { const int *revmap_p, *base, *offset_p; int nelt, n, revidx, max, offset; revmap_p = NCListSXP_REVMAP(x_nclist); nelt = NCListSXP_NELT(x_nclist); n = bsearch_revmap(revmap_p, nelt, backpack); for (revmap_p = revmap_p + n, offset_p = NCListSXP_OFFSETS(x_nclist) + n; n < nelt; n++, revmap_p++, offset_p++) { revidx = *revmap_p; if (backpack->overlap_type == TYPE_WITHIN) { base = backpack->x_start_p; max = backpack->y_start; } else { base = backpack->x_start_p; max = backpack->wide_y_end; } if (base[revidx] > max) break; if (is_hit(revidx, backpack)) { report_hit(revidx, backpack); if (backpack->select_mode == ARBITRARY_HIT && !backpack->pp_is_q) break; } offset = *offset_p; if (offset != -1) NCListSXP_get_y_overlaps(x_nclist + offset, backpack); } return; } /**************************************************************************** * find_overlaps() */ static int find_overlaps( const int *q_start_p, const int *q_end_p, const int *q_space_p, const int *q_subset_p, int q_len, const int *s_start_p, const int *s_end_p, const int *s_space_p, const int *s_subset_p, int s_len, int min_overlap_score, int overlap_type, int select_mode, int circle_len, SEXP nclist_sxp, int pp_is_q, IntAE *qh_buf, IntAE *sh_buf, int *direct_out) { NCList nclist; const void *pp; GetYOverlapsFunType get_y_overlaps; if (q_len == 0 || s_len == 0) return 0; if (nclist_sxp == R_NilValue) { /* On-the-fly preprocessing. */ pp_is_q = q_len < s_len; if (pp_is_q) build_NCList(&nclist, q_start_p, q_end_p, q_subset_p, q_len); else build_NCList(&nclist, s_start_p, s_end_p, s_subset_p, s_len); pp = &nclist; get_y_overlaps = (GetYOverlapsFunType) NCList_get_y_overlaps; } else { pp = INTEGER(nclist_sxp); get_y_overlaps = (GetYOverlapsFunType) NCListSXP_get_y_overlaps; } pp_find_overlaps( q_start_p, q_end_p, q_space_p, q_subset_p, q_len, s_start_p, s_end_p, s_space_p, s_subset_p, s_len, min_overlap_score, overlap_type, select_mode, circle_len, pp, pp_is_q, get_y_overlaps, qh_buf, sh_buf, direct_out); if (nclist_sxp == R_NilValue) free_NCList(&nclist); return pp_is_q; } /**************************************************************************** * Helper functions shared by NCList_find_overlaps() and * NCList_find_overlaps_in_groups() */ static int get_min_overlap_score(SEXP min_score) { int min_overlap_score; if (!IS_INTEGER(min_score) || LENGTH(min_score) != 1) error("'min_score' must be a single integer"); min_overlap_score = INTEGER(min_score)[0]; if (min_overlap_score == NA_INTEGER) error("'min_score' cannot be NA"); return min_overlap_score; } static int get_overlap_type(SEXP type) { const char *type0; if (!IS_CHARACTER(type) || LENGTH(type) != 1) error("'type' must be a single string"); type = STRING_ELT(type, 0); if (type == NA_STRING) error("'type' cannot be NA"); type0 = CHAR(type); if (strcmp(type0, "any") == 0) return TYPE_ANY; if (strcmp(type0, "start") == 0) return TYPE_START; if (strcmp(type0, "end") == 0) return TYPE_END; if (strcmp(type0, "within") == 0) return TYPE_WITHIN; if (strcmp(type0, "extend") == 0) return TYPE_EXTEND; if (strcmp(type0, "equal") == 0) return TYPE_EQUAL; error("'type' must be \"any\", \"start\", \"end\", " "\"within\", \"extend\", or \"equal\""); return 0; } static int get_circle_length(SEXP circle_length) { int circle_len; if (!IS_INTEGER(circle_length) || LENGTH(circle_length) != 1) error("'circle_length' must be a single integer"); circle_len = INTEGER(circle_length)[0]; if (circle_len != NA_INTEGER && circle_len <= 0) error("'circle_length' must be a single " "positive integer or NA"); return circle_len; } static SEXP new_direct_out(int q_len, int select_mode) { SEXP ans; int init_val, i, *ans_elt; PROTECT(ans = NEW_INTEGER(q_len)); init_val = select_mode == COUNT_HITS ? 0 : NA_INTEGER; for (i = 0, ans_elt = INTEGER(ans); i < q_len; i++, ans_elt++) *ans_elt = init_val; UNPROTECT(1); return ans; } /**************************************************************************** * NCList_find_overlaps() * * --- .Call ENTRY POINT --- * Args: * q_start, q_end: Integer vectors of same length. * s_start, s_end: Integer vectors of same length. * nclist: An integer vector representing the Nested Containment * List for 'y'. * nclist_is_q: TRUE or FALSE. * min_score: See get_min_overlap_score() C function. * type: See get_overlap_type() C function. * select: See _get_select_mode() C function in S4Vectors. * circle_length: A single positive integer or NA_INTEGER. */ SEXP NCList_find_overlaps(SEXP q_start, SEXP q_end, SEXP s_start, SEXP s_end, SEXP nclist, SEXP nclist_is_q, SEXP min_score, SEXP type, SEXP select, SEXP circle_length) { int q_len, s_len, min_overlap_score, overlap_type, select_mode, circle_len, *direct_out, pp_is_q; const int *q_start_p, *q_end_p, *s_start_p, *s_end_p; IntAE *qh_buf, *sh_buf; SEXP ans; q_len = check_integer_pairs(q_start, q_end, &q_start_p, &q_end_p, "start(q)", "end(q)"); s_len = check_integer_pairs(s_start, s_end, &s_start_p, &s_end_p, "start(s)", "end(s)"); min_overlap_score = get_min_overlap_score(min_score); overlap_type = get_overlap_type(type); select_mode = get_select_mode(select); circle_len = get_circle_length(circle_length); qh_buf = new_IntAE(0, 0, 0); sh_buf = new_IntAE(0, 0, 0); direct_out = NULL; if (select_mode != ALL_HITS) { PROTECT(ans = new_direct_out(q_len, select_mode)); direct_out = INTEGER(ans); } //init_clock("find_overlaps: T2 = "); pp_is_q = find_overlaps( q_start_p, q_end_p, NULL, NULL, q_len, s_start_p, s_end_p, NULL, NULL, s_len, min_overlap_score, overlap_type, select_mode, circle_len, nclist, LOGICAL(nclist_is_q)[0], qh_buf, sh_buf, direct_out); //print_elapsed_time(); if (select_mode != ALL_HITS) { UNPROTECT(1); return ans; } return new_Hits(qh_buf->elts, sh_buf->elts, IntAE_get_nelt(qh_buf), q_len, s_len, !pp_is_q); } /**************************************************************************** * NCList_find_overlaps_in_groups() * * --- .Call ENTRY POINT --- * Args: * q_start, q_end, q_space: Integer vectors of same length (or NULL for * 'q_space'). * q_groups: A CompressedIntegerList object of length NG1. Each list * element (integer vector) represents a group of 0-based * indices into 'q_start', 'q_end', and 'q_space'. * s_start, s_end, s_space: Integer vectors of same length (or NULL for * 's_space'). * s_groups: A CompressedIntegerList object of length NG2. Each list * element (integer vector) represents a group of 0-based * indices into 's_start', 's_end', and 's_space'. * nclists: A list of length >= min(NG1, NG2). Each list element must * be NULL or an integer vector representing a Nested * Containment List. * nclist_is_q: A logical vector parallel to 'nclists'. * min_score: See get_min_overlap_score() C function. * type: See get_overlap_type() C function. * select: See _get_select_mode() C function in S4Vectors. * circle_length: An integer vector of length >= min(NG1, NG2) with positive * or NA values. */ SEXP NCList_find_overlaps_in_groups( SEXP q_start, SEXP q_end, SEXP q_space, SEXP q_groups, SEXP s_start, SEXP s_end, SEXP s_space, SEXP s_groups, SEXP nclists, SEXP nclist_is_q, SEXP min_score, SEXP type, SEXP select, SEXP circle_length) { int q_len, s_len, NG1, NG2, min_overlap_score, overlap_type, select_mode, NG, i, qi_len, si_len, *direct_out; const int *q_start_p, *q_end_p, *q_space_p, *s_start_p, *s_end_p, *s_space_p; CompressedIntsList_holder q_groups_holder, s_groups_holder; Ints_holder qi_group_holder, si_group_holder; IntAE *qh_buf, *sh_buf; SEXP ans; /* Check query. */ q_len = check_integer_pairs(q_start, q_end, &q_start_p, &q_end_p, "q_start", "q_end"); if (q_space == R_NilValue) { q_space_p = NULL; } else { if (LENGTH(q_space) != q_len) error("'q_space' must have the length of 'q_start'"); q_space_p = INTEGER(q_space); } q_groups_holder = _hold_CompressedIntegerList(q_groups); NG1 = _get_length_from_CompressedIntsList_holder(&q_groups_holder); /* Check subject. */ s_len = check_integer_pairs(s_start, s_end, &s_start_p, &s_end_p, "s_start", "s_end"); if (s_space == R_NilValue) { s_space_p = NULL; } else { if (LENGTH(s_space) != s_len) error("'s_space' must have the length of 's_start'"); s_space_p = INTEGER(s_space); } s_groups_holder = _hold_CompressedIntegerList(s_groups); NG2 = _get_length_from_CompressedIntsList_holder(&s_groups_holder); min_overlap_score = get_min_overlap_score(min_score); overlap_type = get_overlap_type(type); select_mode = get_select_mode(select); qh_buf = new_IntAE(0, 0, 0); sh_buf = new_IntAE(0, 0, 0); direct_out = NULL; if (select_mode != ALL_HITS) { PROTECT(ans = new_direct_out(q_len, select_mode)); direct_out = INTEGER(ans); } NG = NG1 <= NG2 ? NG1 : NG2; for (i = 0; i < NG; i++) { qi_group_holder = _get_elt_from_CompressedIntsList_holder( &q_groups_holder, i); qi_len = qi_group_holder.length; si_group_holder = _get_elt_from_CompressedIntsList_holder( &s_groups_holder, i); si_len = si_group_holder.length; find_overlaps( q_start_p, q_end_p, q_space_p, qi_group_holder.ptr, qi_len, s_start_p, s_end_p, s_space_p, si_group_holder.ptr, si_len, min_overlap_score, overlap_type, select_mode, INTEGER(circle_length)[i], VECTOR_ELT(nclists, i), LOGICAL(nclist_is_q)[i], qh_buf, sh_buf, direct_out); } if (select_mode != ALL_HITS) { UNPROTECT(1); return ans; } return new_Hits(qh_buf->elts, sh_buf->elts, IntAE_get_nelt(qh_buf), q_len, s_len, 0); } /**************************************************************************** Algorithm complexity ==================== X: length of object to preprocess Y: length of other object H: nb of hits (upper bound is X * Y) Time of preprocessing: T1 = a * X * log(X) Time of find_overlaps(..., select="all"): T2 = b * Y * log(X) + c * H Total time T is T1 + T2. ****************************************************************************/ IRanges/src/R_init_IRanges.c0000644000175100017510000001121112612026576016714 0ustar00biocbuildbiocbuild#include "IRanges.h" #define CALLMETHOD_DEF(fun, numArgs) {#fun, (DL_FUNC) &fun, numArgs} #define REGISTER_CCALLABLE(fun) \ R_RegisterCCallable("IRanges", #fun, (DL_FUNC) &fun) static const R_CallMethodDef callMethods[] = { /* Ranges_class.c */ CALLMETHOD_DEF(valid_Ranges, 3), /* Ranges_comparison.c */ CALLMETHOD_DEF(Ranges_compare, 4), /* IRanges_class.c */ CALLMETHOD_DEF(debug_IRanges_class, 0), CALLMETHOD_DEF(IRanges_isNormal, 1), CALLMETHOD_DEF(IRanges_from_integer, 1), CALLMETHOD_DEF(NormalIRanges_from_logical, 1), /* IRanges_constructor.c */ CALLMETHOD_DEF(solve_user_SEW0, 3), CALLMETHOD_DEF(solve_user_SEW, 6), /* Grouping_class.c */ CALLMETHOD_DEF(debug_Grouping_class, 0), CALLMETHOD_DEF(H2LGrouping_members, 2), CALLMETHOD_DEF(H2LGrouping_vmembers, 2), /* RleViews_utils.c */ CALLMETHOD_DEF(RleViews_viewMins, 2), CALLMETHOD_DEF(RleViews_viewMaxs, 2), CALLMETHOD_DEF(RleViews_viewSums, 2), CALLMETHOD_DEF(RleViews_viewMeans, 2), CALLMETHOD_DEF(RleViews_viewWhichMins, 2), CALLMETHOD_DEF(RleViews_viewWhichMaxs, 2), /* SimpleIRangesList_class.c */ CALLMETHOD_DEF(SimpleIRangesList_isNormal, 1), CALLMETHOD_DEF(SimpleNormalIRangesList_min, 1), CALLMETHOD_DEF(SimpleNormalIRangesList_max, 1), /* CompressedIRangesList_class.c */ CALLMETHOD_DEF(CompressedIRangesList_isNormal, 2), CALLMETHOD_DEF(CompressedIRangesList_summary, 1), CALLMETHOD_DEF(CompressedNormalIRangesList_min, 2), CALLMETHOD_DEF(CompressedNormalIRangesList_max, 2), /* GappedRanges_class.c */ CALLMETHOD_DEF(valid_GappedRanges, 2), /* inter_range_methods.c */ CALLMETHOD_DEF(debug_inter_range_methods, 0), CALLMETHOD_DEF(IRanges_range, 1), CALLMETHOD_DEF(Ranges_reduce, 6), CALLMETHOD_DEF(CompressedIRangesList_reduce, 4), CALLMETHOD_DEF(IRanges_gaps, 4), CALLMETHOD_DEF(CompressedIRangesList_gaps, 3), CALLMETHOD_DEF(Ranges_disjointBins, 2), /* coverage_methods.c */ CALLMETHOD_DEF(IRanges_coverage, 6), CALLMETHOD_DEF(CompressedIRangesList_coverage, 6), /* NCList.c */ CALLMETHOD_DEF(NCList_new, 0), CALLMETHOD_DEF(NCList_free, 1), CALLMETHOD_DEF(NCList_build, 4), CALLMETHOD_DEF(new_NCListSXP_from_NCList, 1), CALLMETHOD_DEF(NCListSXP_print, 3), CALLMETHOD_DEF(NCList_find_overlaps, 10), CALLMETHOD_DEF(NCList_find_overlaps_in_groups, 14), /* CompressedAtomicList_utils.c */ CALLMETHOD_DEF(CompressedLogicalList_sum, 2), CALLMETHOD_DEF(CompressedIntegerList_sum, 2), CALLMETHOD_DEF(CompressedNumericList_sum, 2), CALLMETHOD_DEF(CompressedLogicalList_min, 2), CALLMETHOD_DEF(CompressedIntegerList_min, 2), CALLMETHOD_DEF(CompressedNumericList_min, 2), CALLMETHOD_DEF(CompressedLogicalList_max, 2), CALLMETHOD_DEF(CompressedIntegerList_max, 2), CALLMETHOD_DEF(CompressedNumericList_max, 2), {NULL, NULL, 0} }; void R_init_IRanges(DllInfo *info) { R_registerRoutines(info, NULL, callMethods, NULL, NULL); /* Ranges_comparison.c */ REGISTER_CCALLABLE(_overlap_code); REGISTER_CCALLABLE(_invert_overlap_code); /* IRanges_class.c */ REGISTER_CCALLABLE(_get_IRanges_start); REGISTER_CCALLABLE(_get_IRanges_width); REGISTER_CCALLABLE(_get_IRanges_names); REGISTER_CCALLABLE(_get_IRanges_length); REGISTER_CCALLABLE(_hold_IRanges); REGISTER_CCALLABLE(_get_length_from_IRanges_holder); REGISTER_CCALLABLE(_get_width_elt_from_IRanges_holder); REGISTER_CCALLABLE(_get_start_elt_from_IRanges_holder); REGISTER_CCALLABLE(_get_end_elt_from_IRanges_holder); REGISTER_CCALLABLE(_get_names_elt_from_IRanges_holder); REGISTER_CCALLABLE(_get_linear_subset_from_IRanges_holder); REGISTER_CCALLABLE(_set_IRanges_names); REGISTER_CCALLABLE(_copy_IRanges_slots); REGISTER_CCALLABLE(_new_IRanges); REGISTER_CCALLABLE(_new_IRanges_from_IntPairAE); REGISTER_CCALLABLE(_new_list_of_IRanges_from_IntPairAEAE); REGISTER_CCALLABLE(_alloc_IRanges); /* Grouping_class.c */ REGISTER_CCALLABLE(_get_H2LGrouping_high2low); REGISTER_CCALLABLE(_get_H2LGrouping_low2high); REGISTER_CCALLABLE(_get_Partitioning_names); REGISTER_CCALLABLE(_get_PartitioningByEnd_end); REGISTER_CCALLABLE(_new_PartitioningByEnd); /* CompressedList_class.c */ REGISTER_CCALLABLE(_get_CompressedList_unlistData); REGISTER_CCALLABLE(_get_CompressedList_partitioning); REGISTER_CCALLABLE(_get_CompressedList_length); REGISTER_CCALLABLE(_get_CompressedList_names); REGISTER_CCALLABLE(_new_CompressedList); REGISTER_CCALLABLE(_hold_CompressedIntegerList); REGISTER_CCALLABLE(_get_length_from_CompressedIntsList_holder); REGISTER_CCALLABLE(_get_elt_from_CompressedIntsList_holder); /* CompressedIRangesList_class.c */ REGISTER_CCALLABLE(_hold_CompressedIRangesList); REGISTER_CCALLABLE(_get_elt_from_CompressedIRangesList_holder); /* RangedData_class.c */ REGISTER_CCALLABLE(_new_RangedData); return; } IRanges/src/RangedData_class.c0000644000175100017510000000150512612026576017244 0ustar00biocbuildbiocbuild/**************************************************************************** * Low-level manipulation of RangedData objects ****************************************************************************/ #include "IRanges.h" static SEXP ranges_symbol = NULL, values_symbol = NULL; static void set_RangedData_ranges(SEXP x, SEXP value) { INIT_STATIC_SYMBOL(ranges) SET_SLOT(x, ranges_symbol, value); } static void set_RangedData_values(SEXP x, SEXP value) { INIT_STATIC_SYMBOL(values) SET_SLOT(x, values_symbol, value); } SEXP _new_RangedData(const char *classname, SEXP ranges, SEXP values) { SEXP rdClass, rd; PROTECT(rdClass = MAKE_CLASS(classname)); PROTECT(rd = NEW_OBJECT(rdClass)); set_RangedData_ranges(rd, ranges); set_RangedData_values(rd, values); UNPROTECT(2); return rd; } IRanges/src/Ranges_class.c0000644000175100017510000000452212612026576016473 0ustar00biocbuildbiocbuild/**************************************************************************** * Low-level manipulation of Ranges objects * * Author: Herve Pages * ****************************************************************************/ #include "IRanges.h" #include "S4Vectors_interface.h" /* * --- .Call ENTRY POINT --- * Doesn't raise an error but returns NULL or a single string describing the * first encountered validity failure. */ SEXP valid_Ranges(SEXP x_start, SEXP x_end, SEXP x_width) { static char validity_failures[200]; int x_len, i, tmp; const int *x_start_p, *x_end_p, *x_width_p; if (!IS_INTEGER(x_start) || !IS_INTEGER(x_end) || !IS_INTEGER(x_width)) { snprintf(validity_failures, sizeof(validity_failures), "'%s', '%s', and '%s' must be integer vectors", "start(x)", "end(x)", "width(x)"); goto failure; } x_len = LENGTH(x_start); if (LENGTH(x_end) != x_len || LENGTH(x_width) != x_len) { snprintf(validity_failures, sizeof(validity_failures), "'%s', '%s', and '%s' must have the same length", "start(x)", "end(x)", "width(x)"); goto failure; } for (i = 0, x_start_p = INTEGER(x_start), x_end_p = INTEGER(x_end), x_width_p = INTEGER(x_width); i < x_len; i++, x_start_p++, x_end_p++, x_width_p++) { if (*x_start_p == NA_INTEGER || *x_end_p == NA_INTEGER || *x_width_p == NA_INTEGER) { snprintf(validity_failures, sizeof(validity_failures), "'%s', '%s', and '%s' cannot contain NAs", "start(x)", "end(x)", "width(x)"); goto failure; } if (*x_width_p < 0) { snprintf(validity_failures, sizeof(validity_failures), "'%s' cannot contain negative integers", "width(x)"); goto failure; } /* Safe because NA_INTEGER == INT_MIN (see R_ext/Arith.h) */ tmp = *x_start_p - 1; /* The purpose of the 1st part of the test (the part before ||) is to avoid an integer overflow during the 2nd part of the test (the part after ||). */ if (tmp > INT_MAX - *x_width_p || tmp + *x_width_p != *x_end_p) { snprintf(validity_failures, sizeof(validity_failures), "'%s[i] - %s[i] != %s[i] + 1' for i = %d", "end(x)", "start(x)", "width(x)", i + 1); goto failure; } } return R_NilValue; failure: return mkString(validity_failures); } IRanges/src/Ranges_comparison.c0000644000175100017510000001551612612026576017545 0ustar00biocbuildbiocbuild/**************************************************************************** * Range-wise comparison of 2 Ranges objects * * Author: Herve Pages * ****************************************************************************/ #include "IRanges.h" #include "S4Vectors_interface.h" /**************************************************************************** * Generalized comparison of 2 integer ranges. * * There are 13 different ways 2 integer ranges x and y can be positioned * with respect to each other. They are summarized in the following table * together with the codes we assign them: * * numeric code & | numeric code & * 1-letter code & | 1-letter code & * long code | long code * --------------- --------------- | --------------- --------------- * x: .oooo....... -6 'a' "x y" | x: .......oooo. 6 'm' "y x" * y: .......oooo. | y: .oooo....... * --------------- --------------- | --------------- --------------- * x: ..oooo...... -5 'b' "xy" | x: ......oooo.. 5 'l' "yx" * y: ......oooo.. | y: ..oooo...... * --------------- --------------- | --------------- --------------- * x: ...oooo..... -4 'c' "x=y" | x: .....oooo... 4 'k' "y=x" * y: .....oooo... | y: ...oooo..... * --------------- --------------- | --------------- --------------- * x: ...oooooo... -3 'd' "x=" | x: .....oooo... 3 'j' "y=" * y: .....oooo... | y: ...oooooo... * --------------- --------------- | --------------- --------------- * x: ..oooooooo.. -2 'e' "x=x" | x: ....oooo.... 2 'i' "y=y" * y: ....oooo.... | y: ..oooooooo.. * --------------- --------------- | --------------- --------------- * x: ...oooo..... -1 'f' "=y" | x: ...oooooo... 1 'h' "=x" * y: ...oooooo... | y: ...oooo..... * --------------- --------------------------------- --------------- * \ x: ...oooooo... 0 'g' "=" / * \ y: ...oooooo... / * \---------------------------------/ * Notes: * o This way of comparing ranges is a refinement over the standard ranges * comparison defined by the ==, !=, <=, >=, < and > operators. In * particular a numeric code that is < 0, = 0, or > 0 corresponds to * x < y, x == y, or x > y, respectively. * o In this file we use the term "overlap" in a loose way even when there * is actually no overlap between ranges x and y. Real overlaps correspond * to numeric codes >= -4 and <= 4, and to long codes that contain an * equal ("="). * o Long codes are designed to be user-friendly whereas numeric and * 1-letter codes are designed to be more compact and memory efficient. * Typically the formers will be exposed to the end-user and translated * internally into the latters. * o Swapping x and y changes the sign of the corresponding numeric code and * substitutes "x" by "y" and "y" by "x" in the corresponding long code. * o Reflecting ranges x and y relative to an arbitrary position (i.e. doing * a symetry with respect to a vertical axis) has the effect of reversing * the associated long code e.g. "x=y" becomes "y=x". The effect on the * numeric code is implemented by the _invert_overlap_code() function. * * 'x_start', 'x_width', 'y_start' and 'y_width' are assumed to be non NA (not * checked). 'x_start' and 'y_start' must be 1-based. 'x_width' and 'y_width' * are assumed to be >= 0 (not checked). */ int _overlap_code(int x_start, int x_width, int y_start, int y_width) { int x_end_plus1, y_end_plus1; x_end_plus1 = x_start + x_width; if (x_end_plus1 < y_start) return -6; if (x_end_plus1 == y_start) { if (x_width == 0 && y_width == 0) return 0; return -5; } y_end_plus1 = y_start + y_width; if (y_end_plus1 < x_start) return 6; if (y_end_plus1 == x_start) return 5; if (x_start < y_start) { if (x_end_plus1 < y_end_plus1) return -4; if (x_end_plus1 == y_end_plus1) return -3; return -2; } if (x_start == y_start) { if (x_end_plus1 < y_end_plus1) return -1; if (x_end_plus1 == y_end_plus1) return 0; return 1; } if (x_end_plus1 < y_end_plus1) return 2; if (x_end_plus1 == y_end_plus1) return 3; return 4; } int _invert_overlap_code(int code) { if (code == -2 || code == 0 || code == 2) return code; if (code <= -4 || code >= 4) return - code; /* Only possible values left: -3, -1, 1, 3 */ return code < 0 ? code + 4 : code - 4; } /* Vectorized comparison of 2 vectors of ranges. */ static void compare_ranges( const int *x_start, const int *x_width, int x_len, const int *y_start, const int *y_width, int y_len, int *out, int out_len, int with_warning) { int i, j, k; for (i = j = k = 0; k < out_len; i++, j++, k++) { if (i >= x_len) i = 0; /* recycle i */ if (j >= y_len) j = 0; /* recycle j */ out[k] = _overlap_code(x_start[i], x_width[i], y_start[j], y_width[j]); } /* This warning message is meaningful only when 'out_len' is 'max(x_len, y_len)' and is consistent with the warning we get from binary arithmetic/comparison operations on numeric vectors. */ if (with_warning && out_len != 0 && (i != x_len || j != y_len)) warning("longer object length is not a multiple " "of shorter object length"); return; } /* --- .Call ENTRY POINT --- * 'x_start' and 'x_width': integer vectors of the same length M. * 'y_start' and 'y_width': integer vectors of the same length N. * The 4 integer vectors are assumed to be NA free and 'x_width' and * 'y_width' are assumed to contain non-negative values. For efficiency * reasons, those assumptions are not checked. * If M != N then the shorter object is recycled to the length of the longer * object, except if M or N is 0 in which case the object with length != 0 is * truncated to length 0. */ SEXP Ranges_compare(SEXP x_start, SEXP x_width, SEXP y_start, SEXP y_width) { int x_len, y_len, ans_len; const int *x_start_p, *x_width_p, *y_start_p, *y_width_p; SEXP ans; x_len = check_integer_pairs(x_start, x_width, &x_start_p, &x_width_p, "start(x)", "width(x)"); y_len = check_integer_pairs(y_start, y_width, &y_start_p, &y_width_p, "start(y)", "width(y)"); if (x_len == 0 || y_len == 0) ans_len = 0; else ans_len = x_len >= y_len ? x_len : y_len; PROTECT(ans = NEW_INTEGER(ans_len)); compare_ranges(x_start_p, x_width_p, x_len, y_start_p, y_width_p, y_len, INTEGER(ans), ans_len, 1); UNPROTECT(1); return ans; } IRanges/src/RleViews_utils.c0000644000175100017510000005171012612026576017050 0ustar00biocbuildbiocbuild#include "IRanges.h" #include #include #include #define R_INT_MIN (1+INT_MIN) /* * --- .Call ENTRY POINT --- */ SEXP RleViews_viewMins(SEXP x, SEXP na_rm) { char type = '?'; int i, start, width, ans_len, index, lower_run, upper_run, upper_bound; int max_index, *lengths_elt; SEXP ans, subject, values, lengths, ranges, names; IRanges_holder ranges_holder; subject = GET_SLOT(x, install("subject")); values = GET_SLOT(subject, install("values")); lengths = GET_SLOT(subject, install("lengths")); ranges = GET_SLOT(x, install("ranges")); ranges_holder = _hold_IRanges(ranges); ans_len = _get_length_from_IRanges_holder(&ranges_holder); ans = R_NilValue; switch (TYPEOF(values)) { case LGLSXP: case INTSXP: type = 'i'; PROTECT(ans = NEW_INTEGER(ans_len)); break; case REALSXP: type = 'r'; PROTECT(ans = NEW_NUMERIC(ans_len)); break; default: error("Rle must contain either 'integer' or 'numeric' values"); } if (!IS_LOGICAL(na_rm) || LENGTH(na_rm) != 1 || LOGICAL(na_rm)[0] == NA_LOGICAL) error("'na.rm' must be TRUE or FALSE"); lengths_elt = INTEGER(lengths); max_index = LENGTH(lengths) - 1; index = 0; upper_run = *lengths_elt; for (i = 0; i < ans_len; i++) { if (i % 100000 == 99999) R_CheckUserInterrupt(); start = _get_start_elt_from_IRanges_holder(&ranges_holder, i); width = _get_width_elt_from_IRanges_holder(&ranges_holder, i); if (type == 'i') { INTEGER(ans)[i] = INT_MAX; } else if (type == 'r') { REAL(ans)[i] = R_PosInf; } if (width > 0) { while (index > 0 && upper_run > start) { upper_run -= *lengths_elt; lengths_elt--; index--; } while (upper_run < start) { lengths_elt++; index++; upper_run += *lengths_elt; } lower_run = upper_run - *lengths_elt + 1; upper_bound = start + width - 1; if (type == 'i') { while (lower_run <= upper_bound) { if (INTEGER(values)[index] == NA_INTEGER) { if (!LOGICAL(na_rm)[0]) { INTEGER(ans)[i] = NA_INTEGER; break; } } else if (INTEGER(values)[index] < INTEGER(ans)[i]) { INTEGER(ans)[i] = INTEGER(values)[index]; } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; upper_run += *lengths_elt; } else { break; } } } else if (type == 'r') { while (lower_run <= upper_bound) { if (ISNAN(REAL(values)[index])) { if (!LOGICAL(na_rm)[0]) { REAL(ans)[i] = NA_REAL; break; } } else if (REAL(values)[index] < REAL(ans)[i]) { REAL(ans)[i] = REAL(values)[index]; } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; upper_run += *lengths_elt; } else { break; } } } } } PROTECT(names = duplicate(_get_IRanges_names(ranges))); SET_NAMES(ans, names); UNPROTECT(2); return ans; } /* * --- .Call ENTRY POINT --- */ SEXP RleViews_viewMaxs(SEXP x, SEXP na_rm) { char type = '?'; int i, start, width, ans_len, index, lower_run, upper_run, upper_bound; int max_index, *lengths_elt; SEXP ans, subject, values, lengths, ranges, names; IRanges_holder ranges_holder; subject = GET_SLOT(x, install("subject")); values = GET_SLOT(subject, install("values")); lengths = GET_SLOT(subject, install("lengths")); ranges = GET_SLOT(x, install("ranges")); ranges_holder = _hold_IRanges(ranges); ans_len = _get_length_from_IRanges_holder(&ranges_holder); ans = R_NilValue; switch (TYPEOF(values)) { case LGLSXP: case INTSXP: type = 'i'; PROTECT(ans = NEW_INTEGER(ans_len)); break; case REALSXP: type = 'r'; PROTECT(ans = NEW_NUMERIC(ans_len)); break; default: error("Rle must contain either 'integer' or 'numeric' values"); } if (!IS_LOGICAL(na_rm) || LENGTH(na_rm) != 1 || LOGICAL(na_rm)[0] == NA_LOGICAL) error("'na.rm' must be TRUE or FALSE"); lengths_elt = INTEGER(lengths); max_index = LENGTH(lengths) - 1; index = 0; upper_run = *lengths_elt; for (i = 0; i < ans_len; i++) { if (i % 100000 == 99999) R_CheckUserInterrupt(); start = _get_start_elt_from_IRanges_holder(&ranges_holder, i); width = _get_width_elt_from_IRanges_holder(&ranges_holder, i); if (type == 'i') { INTEGER(ans)[i] = R_INT_MIN; } else if (type == 'r') { REAL(ans)[i] = R_NegInf; } if (width > 0) { while (index > 0 && upper_run > start) { upper_run -= *lengths_elt; lengths_elt--; index--; } while (upper_run < start) { lengths_elt++; index++; upper_run += *lengths_elt; } lower_run = upper_run - *lengths_elt + 1; upper_bound = start + width - 1; if (type == 'i') { while (lower_run <= upper_bound) { if (INTEGER(values)[index] == NA_INTEGER) { if (!LOGICAL(na_rm)[0]) { INTEGER(ans)[i] = NA_INTEGER; break; } } else if (INTEGER(values)[index] > INTEGER(ans)[i]) { INTEGER(ans)[i] = INTEGER(values)[index]; } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; upper_run += *lengths_elt; } else { break; } } } else if (type == 'r') { while (lower_run <= upper_bound) { if (ISNAN(REAL(values)[index])) { if (!LOGICAL(na_rm)[0]) { REAL(ans)[i] = NA_REAL; break; } } else if (REAL(values)[index] > REAL(ans)[i]) { REAL(ans)[i] = REAL(values)[index]; } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; upper_run += *lengths_elt; } else { break; } } } } } PROTECT(names = duplicate(_get_IRanges_names(ranges))); SET_NAMES(ans, names); UNPROTECT(2); return ans; } /* * --- .Call ENTRY POINT --- */ SEXP RleViews_viewSums(SEXP x, SEXP na_rm) { char type = '?'; int i, start, width, ans_len, index, lower_run, upper_run, lower_bound, upper_bound; int max_index, *lengths_elt; SEXP ans, subject, values, lengths, ranges, names; IRanges_holder ranges_holder; subject = GET_SLOT(x, install("subject")); values = GET_SLOT(subject, install("values")); lengths = GET_SLOT(subject, install("lengths")); ranges = GET_SLOT(x, install("ranges")); ranges_holder = _hold_IRanges(ranges); ans_len = _get_length_from_IRanges_holder(&ranges_holder); ans = R_NilValue; switch (TYPEOF(values)) { case LGLSXP: case INTSXP: type = 'i'; PROTECT(ans = NEW_INTEGER(ans_len)); break; case REALSXP: type = 'r'; PROTECT(ans = NEW_NUMERIC(ans_len)); break; case CPLXSXP: type = 'c'; PROTECT(ans = NEW_COMPLEX(ans_len)); break; default: error("Rle must contain either 'integer', 'numeric', or 'complex' values"); } if (!IS_LOGICAL(na_rm) || LENGTH(na_rm) != 1 || LOGICAL(na_rm)[0] == NA_LOGICAL) error("'na.rm' must be TRUE or FALSE"); lengths_elt = INTEGER(lengths); max_index = LENGTH(lengths) - 1; index = 0; upper_run = *lengths_elt; for (i = 0; i < ans_len; i++) { if (i % 100000 == 99999) R_CheckUserInterrupt(); start = _get_start_elt_from_IRanges_holder(&ranges_holder, i); width = _get_width_elt_from_IRanges_holder(&ranges_holder, i); if (type == 'i') { INTEGER(ans)[i] = 0; } else if (type == 'r') { REAL(ans)[i] = 0; } else if (type == 'c') { COMPLEX(ans)[i].r = 0; COMPLEX(ans)[i].i = 0; } if (width > 0) { while (index > 0 && upper_run > start) { upper_run -= *lengths_elt; lengths_elt--; index--; } while (upper_run < start) { lengths_elt++; index++; upper_run += *lengths_elt; } lower_run = upper_run - *lengths_elt + 1; lower_bound = start; upper_bound = start + width - 1; if (type == 'i') { while (lower_run <= upper_bound) { if (INTEGER(values)[index] == NA_INTEGER) { if (!LOGICAL(na_rm)[0]) { INTEGER(ans)[i] = NA_INTEGER; break; } } else { INTEGER(ans)[i] += INTEGER(values)[index] * (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; lower_bound = lower_run; upper_run += *lengths_elt; } else { break; } } if (INTEGER(ans)[i] != NA_INTEGER && (INTEGER(ans)[i] > INT_MAX || INTEGER(ans)[i] < R_INT_MIN)) error("Integer overflow"); } else if (type == 'r') { while (lower_run <= upper_bound) { if (ISNAN(REAL(values)[index])) { if (!LOGICAL(na_rm)[0]) { REAL(ans)[i] = NA_REAL; break; } } else { REAL(ans)[i] += REAL(values)[index] * (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; lower_bound = lower_run; upper_run += *lengths_elt; } else { break; } } } else if (type == 'c') { while (lower_run <= upper_bound) { if (ISNAN(COMPLEX(values)[index].r) || ISNAN(COMPLEX(values)[index].i)) { if (!LOGICAL(na_rm)[0]) { COMPLEX(ans)[i].r = NA_REAL; COMPLEX(ans)[i].i = NA_REAL; break; } } else { COMPLEX(ans)[i].r += COMPLEX(values)[index].r * (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); COMPLEX(ans)[i].i += COMPLEX(values)[index].i * (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; lower_bound = lower_run; upper_run += *lengths_elt; } else { break; } } } } } PROTECT(names = duplicate(_get_IRanges_names(ranges))); SET_NAMES(ans, names); UNPROTECT(2); return ans; } /* * --- .Call ENTRY POINT --- */ SEXP RleViews_viewMeans(SEXP x, SEXP na_rm) { char type = '?'; int i, n, start, width, ans_len, index, lower_run, upper_run, lower_bound, upper_bound; int max_index, *lengths_elt; SEXP ans, subject, values, lengths, ranges, names; IRanges_holder ranges_holder; subject = GET_SLOT(x, install("subject")); values = GET_SLOT(subject, install("values")); lengths = GET_SLOT(subject, install("lengths")); ranges = GET_SLOT(x, install("ranges")); ranges_holder = _hold_IRanges(ranges); ans_len = _get_length_from_IRanges_holder(&ranges_holder); ans = R_NilValue; switch (TYPEOF(values)) { case LGLSXP: case INTSXP: type = 'i'; PROTECT(ans = NEW_NUMERIC(ans_len)); break; case REALSXP: type = 'r'; PROTECT(ans = NEW_NUMERIC(ans_len)); break; case CPLXSXP: type = 'c'; PROTECT(ans = NEW_COMPLEX(ans_len)); break; default: error("Rle must contain either 'integer', 'numeric', or 'complex' values"); } if (!IS_LOGICAL(na_rm) || LENGTH(na_rm) != 1 || LOGICAL(na_rm)[0] == NA_LOGICAL) error("'na.rm' must be TRUE or FALSE"); lengths_elt = INTEGER(lengths); max_index = LENGTH(lengths) - 1; index = 0; upper_run = *lengths_elt; for (i = 0; i < ans_len; i++) { if (i % 100000 == 99999) R_CheckUserInterrupt(); start = _get_start_elt_from_IRanges_holder(&ranges_holder, i); width = _get_width_elt_from_IRanges_holder(&ranges_holder, i); if (width <= 0) { if (type == 'i') { REAL(ans)[i] = R_NaN; } else if (type == 'r') { REAL(ans)[i] = R_NaN; } else if (type == 'c') { COMPLEX(ans)[i].r = R_NaN; COMPLEX(ans)[i].i = R_NaN; } } else { n = width; if (type == 'i') { REAL(ans)[i] = 0; } else if (type == 'r') { REAL(ans)[i] = 0; } else if (type == 'c') { COMPLEX(ans)[i].r = 0; COMPLEX(ans)[i].i = 0; } while (index > 0 && upper_run > start) { upper_run -= *lengths_elt; lengths_elt--; index--; } while (upper_run < start) { lengths_elt++; index++; upper_run += *lengths_elt; } lower_run = upper_run - *lengths_elt + 1; lower_bound = start; upper_bound = start + width - 1; if (type == 'i') { while (lower_run <= upper_bound) { if (INTEGER(values)[index] == NA_INTEGER) { if (!LOGICAL(na_rm)[0]) { REAL(ans)[i] = NA_REAL; break; } n -= (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); } else { REAL(ans)[i] += INTEGER(values)[index] * (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; lower_bound = lower_run; upper_run += *lengths_elt; } else { break; } } if (n == 0) { REAL(ans)[i] = R_NaN; } else if (REAL(ans)[i] != NA_REAL) { REAL(ans)[i] /= n; } } else if (type == 'r') { while (lower_run <= upper_bound) { if (ISNAN(REAL(values)[index])) { if (!LOGICAL(na_rm)[0]) { REAL(ans)[i] = NA_REAL; break; } n -= (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); } else { REAL(ans)[i] += REAL(values)[index] * (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; lower_bound = lower_run; upper_run += *lengths_elt; } else { break; } } if (n == 0) { REAL(ans)[i] = R_NaN; } else if (REAL(ans)[i] != NA_REAL) { REAL(ans)[i] /= n; } } else if (type == 'c') { while (lower_run <= upper_bound) { if (ISNAN(COMPLEX(values)[index].r) || ISNAN(COMPLEX(values)[index].i)) { if (!LOGICAL(na_rm)[0]) { COMPLEX(ans)[i].r = NA_REAL; COMPLEX(ans)[i].i = NA_REAL; break; } n -= (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); } else { COMPLEX(ans)[i].r += COMPLEX(values)[index].r * (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); COMPLEX(ans)[i].i += COMPLEX(values)[index].i * (1 + (upper_bound < upper_run ? upper_bound : upper_run) - (lower_bound > lower_run ? lower_bound : lower_run)); } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; lower_bound = lower_run; upper_run += *lengths_elt; } else { break; } } if (n == 0) { COMPLEX(ans)[i].r = R_NaN; COMPLEX(ans)[i].i = R_NaN; } else if (COMPLEX(ans)[i].r != NA_REAL) { COMPLEX(ans)[i].r /= n; COMPLEX(ans)[i].i /= n; } } } } PROTECT(names = duplicate(_get_IRanges_names(ranges))); SET_NAMES(ans, names); UNPROTECT(2); return ans; } /* * --- .Call ENTRY POINT --- */ SEXP RleViews_viewWhichMins(SEXP x, SEXP na_rm) { char type = '?'; int i, start, width, ans_len, index, lower_run, upper_run, lower_bound, upper_bound; int max_index, *ans_elt, *lengths_elt; SEXP curr, ans, subject, values, lengths, ranges, names; IRanges_holder ranges_holder; subject = GET_SLOT(x, install("subject")); values = GET_SLOT(subject, install("values")); lengths = GET_SLOT(subject, install("lengths")); ranges = GET_SLOT(x, install("ranges")); ranges_holder = _hold_IRanges(ranges); ans_len = _get_length_from_IRanges_holder(&ranges_holder); curr = R_NilValue; switch (TYPEOF(values)) { case LGLSXP: case INTSXP: type = 'i'; PROTECT(curr = NEW_INTEGER(1)); break; case REALSXP: type = 'r'; PROTECT(curr = NEW_NUMERIC(1)); break; default: error("Rle must contain either 'integer' or 'numeric' values"); } if (!IS_LOGICAL(na_rm) || LENGTH(na_rm) != 1 || LOGICAL(na_rm)[0] == NA_LOGICAL) error("'na.rm' must be TRUE or FALSE"); PROTECT(ans = NEW_INTEGER(ans_len)); lengths_elt = INTEGER(lengths); max_index = LENGTH(lengths) - 1; index = 0; upper_run = *lengths_elt; for (i = 0, ans_elt = INTEGER(ans); i < ans_len; i++, ans_elt++) { if (i % 100000 == 99999) R_CheckUserInterrupt(); start = _get_start_elt_from_IRanges_holder(&ranges_holder, i); width = _get_width_elt_from_IRanges_holder(&ranges_holder, i); *ans_elt = NA_INTEGER; if (width > 0) { if (type == 'i') { INTEGER(curr)[0] = INT_MAX; } else if (type == 'r') { REAL(curr)[0] = R_PosInf; } while (index > 0 && upper_run > start) { upper_run -= *lengths_elt; lengths_elt--; index--; } while (upper_run < start) { lengths_elt++; index++; upper_run += *lengths_elt; } lower_run = upper_run - *lengths_elt + 1; lower_bound = start; upper_bound = start + width - 1; if (type == 'i') { while (lower_run <= upper_bound) { if (INTEGER(values)[index] == NA_INTEGER) { if (!LOGICAL(na_rm)[0]) { break; } } else if (INTEGER(values)[index] < INTEGER(curr)[0]) { *ans_elt = lower_bound; INTEGER(curr)[0] = INTEGER(values)[index]; } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; lower_bound = lower_run; upper_run += *lengths_elt; } else { break; } } } else if (type == 'r') { while (lower_run <= upper_bound) { if (ISNAN(REAL(values)[index])) { if (!LOGICAL(na_rm)[0]) { break; } } else if (REAL(values)[index] < REAL(curr)[0]) { *ans_elt = lower_bound; REAL(curr)[0] = REAL(values)[index]; } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; lower_bound = lower_run; upper_run += *lengths_elt; } else { break; } } } } } PROTECT(names = duplicate(_get_IRanges_names(ranges))); SET_NAMES(ans, names); UNPROTECT(3); return ans; } /* * --- .Call ENTRY POINT --- */ SEXP RleViews_viewWhichMaxs(SEXP x, SEXP na_rm) { char type = '?'; int i, start, width, ans_len, index, lower_run, upper_run, lower_bound, upper_bound; int max_index, *ans_elt, *lengths_elt; SEXP curr, ans, subject, values, lengths, ranges, names; IRanges_holder ranges_holder; subject = GET_SLOT(x, install("subject")); values = GET_SLOT(subject, install("values")); lengths = GET_SLOT(subject, install("lengths")); ranges = GET_SLOT(x, install("ranges")); ranges_holder = _hold_IRanges(ranges); ans_len = _get_length_from_IRanges_holder(&ranges_holder); curr = R_NilValue; switch (TYPEOF(values)) { case LGLSXP: case INTSXP: type = 'i'; PROTECT(curr = NEW_INTEGER(1)); break; case REALSXP: type = 'r'; PROTECT(curr = NEW_NUMERIC(1)); break; default: error("Rle must contain either 'integer' or 'numeric' values"); } if (!IS_LOGICAL(na_rm) || LENGTH(na_rm) != 1 || LOGICAL(na_rm)[0] == NA_LOGICAL) error("'na.rm' must be TRUE or FALSE"); PROTECT(ans = NEW_INTEGER(ans_len)); lengths_elt = INTEGER(lengths); max_index = LENGTH(lengths) - 1; index = 0; upper_run = *lengths_elt; for (i = 0, ans_elt = INTEGER(ans); i < ans_len; i++, ans_elt++) { if (i % 100000 == 99999) R_CheckUserInterrupt(); start = _get_start_elt_from_IRanges_holder(&ranges_holder, i); width = _get_width_elt_from_IRanges_holder(&ranges_holder, i); *ans_elt = NA_INTEGER; if (width > 0) { if (type == 'i') { INTEGER(curr)[0] = R_INT_MIN; } else if (type == 'r') { REAL(curr)[0] = R_NegInf; } while (index > 0 && upper_run > start) { upper_run -= *lengths_elt; lengths_elt--; index--; } while (upper_run < start) { lengths_elt++; index++; upper_run += *lengths_elt; } lower_run = upper_run - *lengths_elt + 1; lower_bound = start; upper_bound = start + width - 1; if (type == 'i') { while (lower_run <= upper_bound) { if (INTEGER(values)[index] == NA_INTEGER) { if (!LOGICAL(na_rm)[0]) { break; } } else if (INTEGER(values)[index] > INTEGER(curr)[0]) { *ans_elt = lower_bound; INTEGER(curr)[0] = INTEGER(values)[index]; } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; lower_bound = lower_run; upper_run += *lengths_elt; } else { break; } } } else if (type == 'r') { while (lower_run <= upper_bound) { if (ISNAN(REAL(values)[index])) { if (!LOGICAL(na_rm)[0]) { break; } } else if (REAL(values)[index] > REAL(curr)[0]) { *ans_elt = lower_bound; REAL(curr)[0] = REAL(values)[index]; } if (index < max_index) { lengths_elt++; index++; lower_run = upper_run + 1; lower_bound = lower_run; upper_run += *lengths_elt; } else { break; } } } } } PROTECT(names = duplicate(_get_IRanges_names(ranges))); SET_NAMES(ans, names); UNPROTECT(3); return ans; } IRanges/src/S4Vectors_stubs.c0000644000175100017510000000003612612026576017137 0ustar00biocbuildbiocbuild#include "_S4Vectors_stubs.c" IRanges/src/SimpleRangesList_class.c0000644000175100017510000000426312612026576020503 0ustar00biocbuildbiocbuild/**************************************************************************** * Low-level manipulation of SimpleRangesList objects * ****************************************************************************/ #include "IRanges.h" #include #define R_INT_MIN (1+INT_MIN) /* * --- .Call ENTRY POINT --- */ SEXP SimpleIRangesList_isNormal(SEXP x) { SEXP list_ir, ans, ans_names; IRanges_holder ir_holder; int x_len, i; list_ir = GET_SLOT(x, install("listData")); x_len = LENGTH(list_ir); PROTECT(ans = NEW_LOGICAL(x_len)); for (i = 0; i < x_len; i++) { ir_holder = _hold_IRanges(VECTOR_ELT(list_ir, i)); LOGICAL(ans)[i] = _is_normal_IRanges_holder(&ir_holder); } PROTECT(ans_names = duplicate(GET_NAMES(list_ir))); SET_NAMES(ans, ans_names); UNPROTECT(2); return ans; } /* * --- .Call ENTRY POINT --- */ SEXP SimpleNormalIRangesList_min(SEXP x) { SEXP list_ir, ans, ans_names; IRanges_holder ir_holder; int x_len, ir_len, i; int *ans_elt; list_ir = GET_SLOT(x, install("listData")); x_len = LENGTH(list_ir); PROTECT(ans = NEW_INTEGER(x_len)); for (i = 0, ans_elt = INTEGER(ans); i < x_len; i++, ans_elt++) { ir_holder = _hold_IRanges(VECTOR_ELT(list_ir, i)); ir_len = _get_length_from_IRanges_holder(&ir_holder); if (ir_len == 0) { *ans_elt = INT_MAX; } else { *ans_elt = _get_start_elt_from_IRanges_holder(&ir_holder, 0); } } PROTECT(ans_names = duplicate(GET_NAMES(list_ir))); SET_NAMES(ans, ans_names); UNPROTECT(2); return ans; } /* * --- .Call ENTRY POINT --- */ SEXP SimpleNormalIRangesList_max(SEXP x) { SEXP list_ir, ans, ans_names; IRanges_holder ir_holder; int x_len, ir_len, i; int *ans_elt; list_ir = GET_SLOT(x, install("listData")); x_len = LENGTH(list_ir); PROTECT(ans = NEW_INTEGER(x_len)); for (i = 0, ans_elt = INTEGER(ans); i < x_len; i++, ans_elt++) { ir_holder = _hold_IRanges(VECTOR_ELT(list_ir, i)); ir_len = _get_length_from_IRanges_holder(&ir_holder); if (ir_len == 0) { *ans_elt = R_INT_MIN; } else { *ans_elt = _get_end_elt_from_IRanges_holder(&ir_holder, ir_len - 1); } } PROTECT(ans_names = duplicate(GET_NAMES(list_ir))); SET_NAMES(ans, ans_names); UNPROTECT(2); return ans; } IRanges/src/coverage_methods.c0000644000175100017510000005711212612026576017410 0ustar00biocbuildbiocbuild/**************************************************************************** * * * Weighted coverage of a set of integer ranges * * -------------------------------------------- * * * * Authors: Herve Pages and Patrick Aboyoun * * Code for "sort" method based on timing enhancements * * by Charles C. Berry * * * ****************************************************************************/ #include "IRanges.h" #include "S4Vectors_interface.h" #include /* for qsort() */ #include /* for R_CheckUserInterrupt() */ static const char *x_label, *shift_label, *width_label, *weight_label; static void check_recycling_was_round(int last_pos_in_current, int current_len, const char *current_label, const char *target_label) { if (current_len >= 2 && last_pos_in_current < current_len) warning("'%s' length is not a divisor of '%s' length", current_label, target_label); return; } /**************************************************************************** * "sort" method * ****************************************************************************/ /**************************************************************************** * Basic manipulation of the SEids buffer (Start/End ids). */ #define SEid_TO_1BASED_INDEX(SEid) ((SEid) >= 0 ? (SEid) : -(SEid)) #define SEid_IS_END(SEid) ((SEid) >= 0) static const int *base_start; static const int *base_width; static int compar_SEids_for_asc_order(const void *p1, const void *p2) { int SEid1, SEid2, index1, index2, s1, s2; SEid1 = *((const int *) p1); SEid2 = *((const int *) p2); index1 = SEid_TO_1BASED_INDEX(SEid1); index2 = SEid_TO_1BASED_INDEX(SEid2); /* If SEid is a Start id, then s = start If SEid is an End id, then s = end + 1 */ s1 = base_start[index1]; if (SEid_IS_END(SEid1)) s1 += base_width[index1]; s2 = base_start[index2]; if (SEid_IS_END(SEid2)) s2 += base_width[index2]; return s1 - s2; } /* Initialize the SEids buffer (integer weights). */ static int init_SEids_int_weight(int *SEids, const int *x_width, int x_len, const int *weight, int weight_len) { int SEids_len, i, j, index; SEids_len = 0; for (i = j = 0, index = 1; i < x_len; i++, j++, index++) { if (j >= weight_len) j = 0; /* recycle j */ if (x_width[i] == 0 || weight[j] == 0) continue; *(SEids++) = index; /* Start id */ *(SEids++) = - index; /* End id */ SEids_len += 2; } check_recycling_was_round(j, weight_len, weight_label, x_label); return SEids_len; } /* Initialize the SEids buffer (numeric weights). */ static int init_SEids_double_weight(int *SEids, const int *x_width, int x_len, const double *weight, int weight_len) { int SEids_len, i, j, index; SEids_len = 0; for (i = j = 0, index = 1; i < x_len; i++, j++, index++) { if (j >= weight_len) j = 0; /* recycle j */ if (x_width[i] == 0 || weight[j] == 0.0) continue; *(SEids++) = index; /* Start id */ *(SEids++) = - index; /* End id */ SEids_len += 2; } check_recycling_was_round(j, weight_len, weight_label, x_label); return SEids_len; } /* Sort the SEids buffer. */ static void sort_SEids(int *SEids, int SEids_len, const int *x_start, const int *x_width) { base_start = x_start - 1; base_width = x_width - 1; qsort(SEids, SEids_len, sizeof(int), compar_SEids_for_asc_order); return; } /**************************************************************************** * int_coverage_sort(), double_coverage_sort() */ /* 'values_buf' and 'lengths_buf' must have a length >= SEids_len + 1 */ static void compute_int_coverage_in_bufs(const int *SEids, int SEids_len, const int *x_start, const int *x_width, const int *weight, int weight_len, int cvg_len, int *values_buf, int *lengths_buf) { int curr_val, curr_weight, curr_pos, i, prev_pos, index; *(values_buf++) = curr_val = 0; curr_pos = 1; reset_ovflow_flag(); /* we use safe_int_add() in loop below */ for (i = 0; i < SEids_len; i++, SEids++) { if (i % 500000 == 499999) R_CheckUserInterrupt(); prev_pos = curr_pos; index = SEid_TO_1BASED_INDEX(*SEids) - 1; curr_pos = x_start[index]; curr_weight = weight[index % weight_len]; if (SEid_IS_END(*SEids)) { curr_weight = - curr_weight; curr_pos += x_width[index]; } curr_val = safe_int_add(curr_val, curr_weight); *(values_buf++) = curr_val; *(lengths_buf++) = curr_pos - prev_pos; } if (get_ovflow_flag()) warning("NAs produced by integer overflow"); *lengths_buf = cvg_len + 1 - curr_pos; return; } static void compute_double_coverage_in_bufs(const int *SEids, int SEids_len, const int *x_start, const int *x_width, const double *weight, int weight_len, int cvg_len, double *values_buf, int *lengths_buf) { double curr_val, curr_weight; int curr_pos, i, prev_pos, index; *(values_buf++) = curr_val = 0.0; curr_pos = 1; for (i = 0; i < SEids_len; i++, SEids++) { if (i % 500000 == 499999) R_CheckUserInterrupt(); prev_pos = curr_pos; index = SEid_TO_1BASED_INDEX(*SEids) - 1; curr_pos = x_start[index]; curr_weight = weight[index % weight_len]; if (SEid_IS_END(*SEids)) { curr_weight = - curr_weight; curr_pos += x_width[index]; } curr_val += curr_weight; *(values_buf++) = curr_val; *(lengths_buf++) = curr_pos - prev_pos; } *lengths_buf = cvg_len + 1 - curr_pos; return; } static SEXP int_coverage_sort(const int *x_start, const int *x_width, int x_len, const int *weight, int weight_len, int cvg_len) { int *SEids, SEids_len, zero, buf_len, *values_buf, *lengths_buf; SEids = (int *) R_alloc((long) 2 * x_len, sizeof(int)); SEids_len = init_SEids_int_weight(SEids, x_width, x_len, weight, weight_len); if (SEids_len == 0) { //return an Rle with one run of 0's zero = 0; return integer_Rle_constructor(&zero, 1, &cvg_len, 0); } sort_SEids(SEids, SEids_len, x_start, x_width); buf_len = SEids_len + 1; values_buf = (int *) R_alloc((long) buf_len, sizeof(int)); lengths_buf = (int *) R_alloc((long) buf_len, sizeof(int)); compute_int_coverage_in_bufs(SEids, SEids_len, x_start, x_width, weight, weight_len, cvg_len, values_buf, lengths_buf); return integer_Rle_constructor(values_buf, buf_len, lengths_buf, 0); } static SEXP double_coverage_sort(const int *x_start, const int *x_width, int x_len, const double *weight, int weight_len, int cvg_len) { int *SEids, SEids_len, buf_len, *lengths_buf; double zero, *values_buf; SEids = (int *) R_alloc((long) 2 * x_len, sizeof(int)); SEids_len = init_SEids_double_weight(SEids, x_width, x_len, weight, weight_len); if (SEids_len == 0) { //return an Rle with one run of 0's zero = 0.0; return numeric_Rle_constructor(&zero, 1, &cvg_len, 0); } sort_SEids(SEids, SEids_len, x_start, x_width); buf_len = SEids_len + 1; values_buf = (double *) R_alloc((long) buf_len, sizeof(double)); lengths_buf = (int *) R_alloc((long) buf_len, sizeof(int)); compute_double_coverage_in_bufs(SEids, SEids_len, x_start, x_width, weight, weight_len, cvg_len, values_buf, lengths_buf); return numeric_Rle_constructor(values_buf, buf_len, lengths_buf, 0); } static SEXP coverage_sort(const int *x_start, const int *x_width, int x_len, SEXP weight, int cvg_len) { int weight_len; weight_len = LENGTH(weight); return IS_INTEGER(weight) ? int_coverage_sort(x_start, x_width, x_len, INTEGER(weight), weight_len, cvg_len) : double_coverage_sort(x_start, x_width, x_len, REAL(weight), weight_len, cvg_len); } /**************************************************************************** * "hash" method * ****************************************************************************/ static SEXP int_coverage_hash( const int *x_start, const int *x_width, int x_len, const int *weight, int weight_len, int cvg_len) { int *cvg_buf, *cvg_p, w, cumsum, i, j; cvg_buf = (int *) R_alloc((long) cvg_len + 1, sizeof(int)); memset(cvg_buf, 0, cvg_len * sizeof(int)); reset_ovflow_flag(); /* we use safe_int_add() in loop below */ for (i = j = 0; i < x_len; i++, j++, x_start++, x_width++) { if (i % 500000 == 499999) R_CheckUserInterrupt(); if (j >= weight_len) j = 0; /* recycle j */ cvg_p = cvg_buf + *x_start - 1; w = weight[j]; *cvg_p = safe_int_add(*cvg_p, w); cvg_p += *x_width; *cvg_p = safe_int_add(*cvg_p, - w); } check_recycling_was_round(j, weight_len, weight_label, x_label); cumsum = 0; for (i = 0, cvg_p = cvg_buf; i < cvg_len; i++, cvg_p++) { cumsum = safe_int_add(*cvg_p, cumsum); *cvg_p = cumsum; } if (get_ovflow_flag()) warning("NAs produced by integer overflow"); return integer_Rle_constructor(cvg_buf, cvg_len, NULL, 0); } static SEXP double_coverage_hash( const int *x_start, const int *x_width, int x_len, const double *weight, int weight_len, int cvg_len) { double *cvg_buf, *cvg_p, w, cumsum; int i, j; cvg_buf = (double *) R_alloc((long) cvg_len + 1, sizeof(double)); for (i = 0, cvg_p = cvg_buf; i < cvg_len; i++, cvg_p++) *cvg_p = 0.0; for (i = j = 0; i < x_len; i++, j++, x_start++, x_width++) { if (i % 500000 == 499999) R_CheckUserInterrupt(); if (j >= weight_len) j = 0; /* recycle j */ cvg_p = cvg_buf + *x_start - 1; w = weight[j]; *cvg_p += w; cvg_p += *x_width; *cvg_p -= w; } check_recycling_was_round(j, weight_len, weight_label, x_label); cumsum = 0.0; for (i = 0, cvg_p = cvg_buf; i < cvg_len; i++, cvg_p++) { cumsum += *cvg_p; *cvg_p = cumsum; } return numeric_Rle_constructor(cvg_buf, cvg_len, NULL, 0); } static SEXP coverage_hash(const int *x_start, const int *x_width, int x_len, SEXP weight, int cvg_len) { int weight_len; weight_len = LENGTH(weight); return IS_INTEGER(weight) ? int_coverage_hash(x_start, x_width, x_len, INTEGER(weight), weight_len, cvg_len) : double_coverage_hash(x_start, x_width, x_len, REAL(weight), weight_len, cvg_len); } /**************************************************************************** * Helper functions for checking args of type SEXP. * * They either pass (and return nothing) or raise an error with an * * informative message. * ****************************************************************************/ static void check_arg_is_integer(SEXP arg, const char *arg_label) { if (!IS_INTEGER(arg)) error("'%s' must be an integer vector", arg_label); return; } static void check_arg_is_numeric(SEXP arg, const char *arg_label) { if (!(IS_INTEGER(arg) || IS_NUMERIC(arg))) error("'%s' must be an integer or numeric vector", arg_label); return; } static void check_arg_is_list(SEXP arg, const char *arg_label) { if (!IS_LIST(arg)) error("'%s' must be a list", arg_label); return; } /* * Check that 'arg_len' is equal to 'x_len', or that it's the length of an * argument that can be recycled to the length of 'x'. * Assumes that 'arg_len' and 'x_len' are >= 0. */ static void check_arg_is_recyclable(int arg_len, int x_len, const char *arg_label, const char *x_label) { if (arg_len < x_len) { if (arg_len == 0) error("cannot recycle zero-length '%s' " "to the length of '%s'", arg_label, x_label); } else if (arg_len > x_len) { if (arg_len >= 2) error("'%s' is longer than '%s'", arg_label, x_label); } return; } /**************************************************************************** * compute_coverage_from_IRanges_holder() * ****************************************************************************/ /* * This is probably overly cautious. Could be that the cast from double to int * with (int) already does exactly this (i.e. produces an NA_INTEGER for all * the cases explicitely handled here) and is portable. */ static int double2int(double x) { if (x == R_PosInf || x == R_NegInf || ISNAN(x) /* NA or NaN */ || x >= (double) INT_MAX + 1.00 || x <= (double) INT_MIN) return NA_INTEGER; return (int) x; } /* * Args: * x_holder: A IRanges_holder struct holding the input ranges, those * ranges being those of a fictive IRanges object 'x'. * shift: A numeric (integer or double) vector parallel to 'x' (will * get recycled if necessary) with no NAs. * width: A single integer. NA or >= 0. * circle_len: A single integer. NA or > 0. * After the input ranges are shifted: * - If 'width' is a non-negative integer, then the ranges are clipped with * respect to the [1, width] interval and the function returns 'width'. * - If 'width' is NA, then the ranges are clipped with respect to the * [1, +inf) interval (i.e. they're only clipped on the left) and the * function returns 'max(end(x))' or 0 if 'x' is empty. * The shifted and clipped ranges are returned in 'out_ranges'. * Let's call 'cvg_len' the value returned by the function. If the output * ranges are in a tiling configuration with respect to the [1, cvg_len] * interval (i.e. they're non-overlapping, ordered from left to right, and * they fully cover the interval), then '*out_ranges_are_tiles' is set to 1. * Otherwise, it's set to 0. */ static int shift_and_clip_ranges(const IRanges_holder *x_holder, SEXP shift, int width, int circle_len, IntPairAE *out_ranges, int *out_ranges_are_tiles) { int x_len, shift_len, cvg_len, auto_cvg_len, prev_end, i, j, x_start, x_end, shift_elt, tmp; x_len = _get_length_from_IRanges_holder(x_holder); /* Check 'shift'. */ check_arg_is_numeric(shift, shift_label); shift_len = LENGTH(shift); check_arg_is_recyclable(shift_len, x_len, shift_label, x_label); /* Infer 'cvg_len' from 'width' and 'circle_len'. */ *out_ranges_are_tiles = 1; if (width == NA_INTEGER) { auto_cvg_len = 1; } else if (width < 0) { error("'%s' cannot be negative", width_label); } else if (width == 0) { return width; } else if (circle_len == NA_INTEGER) { auto_cvg_len = 0; } else if (circle_len <= 0) { error("length of underlying circular sequence is <= 0"); } else if (width > circle_len) { error("'%s' cannot be greater than length of " "underlying circular sequence", width_label); } else { auto_cvg_len = 1; } cvg_len = auto_cvg_len ? 0 : width; if (x_len == 0) { if (cvg_len != 0) *out_ranges_are_tiles = 0; return cvg_len; } IntPairAE_set_nelt(out_ranges, 0); prev_end = 0; for (i = j = 0; i < x_len; i++, j++) { if (j >= shift_len) j = 0; /* recycle j */ x_start = _get_start_elt_from_IRanges_holder(x_holder, i); x_end = _get_end_elt_from_IRanges_holder(x_holder, i); if (IS_INTEGER(shift)) { shift_elt = INTEGER(shift)[j]; if (shift_elt == NA_INTEGER) error("'%s' contains NAs", shift_label); } else { shift_elt = double2int(REAL(shift)[j]); if (shift_elt == NA_INTEGER) error("'%s' contains NAs, NaNs, or numbers " "that cannot be turned into integers", shift_label); } /* Risk of integer overflow! */ x_start += shift_elt; x_end += shift_elt; if (circle_len != NA_INTEGER) { tmp = x_start % circle_len; if (tmp <= 0) tmp += circle_len; x_end += tmp - x_start; x_start = tmp; } if (x_end < 0) { x_end = 0; } else if (x_end > cvg_len) { if (auto_cvg_len) cvg_len = x_end; else x_end = cvg_len; } if (x_start < 1) x_start = 1; else if (x_start > (tmp = cvg_len + 1)) x_start = tmp; if (*out_ranges_are_tiles) { if (x_start == prev_end + 1) prev_end = x_end; else *out_ranges_are_tiles = 0; } IntPairAE_insert_at(out_ranges, i, x_start, x_end - x_start + 1); } check_recycling_was_round(j, shift_len, shift_label, x_label); if (*out_ranges_are_tiles && x_end != cvg_len) *out_ranges_are_tiles = 0; return cvg_len; } /* * Args: * x_holder: A IRanges_holder struct holding the input ranges, those * ranges being those of a fictive IRanges object 'x'. * shift: A numeric (integer or double) vector parallel to 'x' (will * get recycled if necessary) with no NAs. * width: A single integer. NA or >= 0. * weight: A numeric (integer or double) vector parallel to 'x' (will * get recycled if necessary). * circle_len: A single integer. NA or > 0. * method: Either "auto", "sort", or "hash". * Returns an Rle object. */ static SEXP compute_coverage_from_IRanges_holder( const IRanges_holder *x_holder, SEXP shift, int width, SEXP weight, int circle_len, SEXP method, IntPairAE *ranges_buf) { int x_len, cvg_len, out_ranges_are_tiles, weight_len, effective_method, take_short_path; const int *x_start, *x_width; const char *method0; x_len = _get_length_from_IRanges_holder(x_holder); cvg_len = shift_and_clip_ranges(x_holder, shift, width, circle_len, ranges_buf, &out_ranges_are_tiles); x_start = ranges_buf->a->elts; x_width = ranges_buf->b->elts; /* Check 'weight'. */ check_arg_is_numeric(weight, weight_label); weight_len = LENGTH(weight); check_arg_is_recyclable(weight_len, x_len, weight_label, x_label); /* Infer 'effective_method' from 'method' and 'cvg_len'. */ if (!IS_CHARACTER(method) || LENGTH(method) != 1) error("'method' must be a single string"); method = STRING_ELT(method, 0); if (method == NA_STRING) error("'method' cannot be NA"); method0 = CHAR(method); if (strcmp(method0, "auto") == 0) { /* Based on empirical observation. */ effective_method = x_len <= 0.25 * cvg_len ? 1 : 2; } else if (strcmp(method0, "sort") == 0) { effective_method = 1; } else if (strcmp(method0, "hash") == 0) { effective_method = 2; } else { error("'method' must be \"auto\", \"sort\", or \"hash\""); } //Rprintf("out_ranges_are_tiles = %d\n", out_ranges_are_tiles); //Rprintf("x_len = %d\n", x_len); //Rprintf("cvg_len = %d\n", cvg_len); if (out_ranges_are_tiles) { if (cvg_len == 0) { take_short_path = 1; x_len = 0; } else if (weight_len == 1) { take_short_path = 1; x_len = 1; x_width = &cvg_len; } else if (weight_len == x_len) { take_short_path = 1; } else { take_short_path = 0; } if (take_short_path) { /* Short path for the tiling case. */ //Rprintf("taking short path\n"); return IS_INTEGER(weight) ? integer_Rle_constructor(INTEGER(weight), x_len, x_width, 0) : numeric_Rle_constructor(REAL(weight), x_len, x_width, 0); } } //Rprintf("taking normal path\n"); return effective_method == 1 ? coverage_sort(x_start, x_width, x_len, weight, cvg_len) : coverage_hash(x_start, x_width, x_len, weight, cvg_len); } /* --- .Call ENTRY POINT --- * Args: * x: An IRanges object. * shift: A numeric (integer or double) vector parallel to 'x' (will * get recycled if necessary) with no NAs. * width: A single integer. NA or >= 0. * weight: A numeric (integer or double) vector parallel to 'x' (will * get recycled if necessary). * circle_len: A single integer. NA or > 0. * method: Either "auto", "sort", or "hash". * Returns an Rle object. */ SEXP IRanges_coverage(SEXP x, SEXP shift, SEXP width, SEXP weight, SEXP circle_len, SEXP method) { IRanges_holder x_holder; int x_len; IntPairAE *ranges_buf; x_holder = _hold_IRanges(x); x_len = _get_length_from_IRanges_holder(&x_holder); /* Check 'width'. */ check_arg_is_integer(width, "width"); if (LENGTH(width) != 1) error("'%s' must be a single integer", "width"); /* Check 'circle_len'. */ check_arg_is_integer(circle_len, "circle.length"); if (LENGTH(circle_len) != 1) error("'%s' must be a single integer", "circle.length"); ranges_buf = new_IntPairAE(x_len, 0); x_label = "x"; shift_label = "shift"; width_label = "width"; weight_label = "weight"; return compute_coverage_from_IRanges_holder(&x_holder, shift, INTEGER(width)[0], weight, INTEGER(circle_len)[0], method, ranges_buf); } /* --- .Call ENTRY POINT --- * Args: * x: A CompressedIRangesList object of length N. * shift: A list of length N (will get recycled if necessary). After * recycling, each list element must be a numeric (integer or * double) vector parallel to x[[i]] that will itself get * recycled if necessary, and with no NAs. * width: An integer vector of length N (will get recycled if * necessary). Values must be NAs or >= 0. * or a single non-negative number. * weight: A list of length N (will get recycled if necessary). After * recycling, each list element must be a numeric (integer or * double) vector parallel to x[[i]] that will itself get * recycled if necessary. * circle_lens: An integer vector of length N (will get recycled if * necessary). Values must be NAs or > 0. * method: Either "auto", "sort", or "hash". * Returns a list of N RleList objects. */ SEXP CompressedIRangesList_coverage(SEXP x, SEXP shift, SEXP width, SEXP weight, SEXP circle_lens, SEXP method) { CompressedIRangesList_holder x_holder; int x_len, shift_len, width_len, weight_len, circle_lens_len, i, j, k, l, m; IntPairAE *ranges_buf; SEXP ans, ans_elt, shift_elt, weight_elt; IRanges_holder x_elt_holder; char x_label_buf[40], shift_label_buf[40], width_label_buf[40], weight_label_buf[40]; x_holder = _hold_CompressedIRangesList(x); x_len = _get_length_from_CompressedIRangesList_holder(&x_holder); /* Check 'shift'. */ check_arg_is_list(shift, "shift"); shift_len = LENGTH(shift); check_arg_is_recyclable(shift_len, x_len, "shift", "x"); /* Check 'width'. */ check_arg_is_integer(width, "width"); width_len = LENGTH(width); check_arg_is_recyclable(width_len, x_len, "width", "x"); /* Check 'weight'. */ check_arg_is_list(weight, "weight"); weight_len = LENGTH(weight); check_arg_is_recyclable(weight_len, x_len, "weight", "x"); /* Check 'circle_lens'. */ check_arg_is_integer(circle_lens, "circle.length"); circle_lens_len = LENGTH(circle_lens); check_arg_is_recyclable(circle_lens_len, x_len, "circle.length", "x"); ranges_buf = new_IntPairAE(0, 0); x_label = x_label_buf; shift_label = shift_label_buf; width_label = width_label_buf; weight_label = weight_label_buf; PROTECT(ans = NEW_LIST(x_len)); for (i = j = k = l = m = 0; i < x_len; i++, j++, k++, l++, m++) { if (j >= shift_len) j = 0; /* recycle j */ if (k >= width_len) k = 0; /* recycle k */ if (l >= weight_len) l = 0; /* recycle l */ if (m >= circle_lens_len) m = 0; /* recycle m */ snprintf(x_label_buf, sizeof(x_label_buf), "x[[%d]]", i + 1); snprintf(shift_label_buf, sizeof(shift_label_buf), "shift[[%d]]", j + 1); snprintf(width_label_buf, sizeof(width_label_buf), "width[%d]", k + 1); snprintf(weight_label_buf, sizeof(weight_label_buf), "weight[[%d]]", l + 1); x_elt_holder = _get_elt_from_CompressedIRangesList_holder( &x_holder, i); shift_elt = VECTOR_ELT(shift, j); weight_elt = VECTOR_ELT(weight, l); PROTECT(ans_elt = compute_coverage_from_IRanges_holder( &x_elt_holder, shift_elt, INTEGER(width)[k], weight_elt, INTEGER(circle_lens)[m], method, ranges_buf)); SET_VECTOR_ELT(ans, i, ans_elt); UNPROTECT(1); } check_recycling_was_round(j, shift_len, "shift", "x"); check_recycling_was_round(k, width_len, "width", "x"); check_recycling_was_round(l, weight_len, "weight", "x"); check_recycling_was_round(m, circle_lens_len, "circle.length", "x"); UNPROTECT(1); return ans; } IRanges/src/inter_range_methods.c0000644000175100017510000003427012612026576020112 0ustar00biocbuildbiocbuild/**************************************************************************** * Fast inter-range methods * * Author: Herve Pages * ****************************************************************************/ #include "IRanges.h" #include "S4Vectors_interface.h" #include #define R_INT_MIN (1+INT_MIN) static int debug = 0; SEXP debug_inter_range_methods() { #ifdef DEBUG_IRANGES debug = !debug; Rprintf("Debug mode turned %s in file %s\n", debug ? "on" : "off", __FILE__); #else Rprintf("Debug mode not available in file %s\n", __FILE__); #endif return R_NilValue; } /**************************************************************************** * Low-level helper functions. */ static int get_elt_from_CompressedIRangesList_holderlens_max( const CompressedIRangesList_holder *x_holder) { int x_len, ir_len_max, i, ir_len; x_len = _get_length_from_CompressedIRangesList_holder(x_holder); ir_len_max = 0; for (i = 0; i < x_len; i++) { ir_len = _get_eltlens_from_CompressedIRangesList_holder( x_holder, i); if (ir_len > ir_len_max) ir_len_max = ir_len; } return ir_len_max; } static int append_IRanges_holder_to_IntPairAE(IntPairAE *intpair_ae, const IRanges_holder *ir_holder) { int ir_len, j, start, width; ir_len = _get_length_from_IRanges_holder(ir_holder); for (j = 0; j < ir_len; j++) { start = _get_start_elt_from_IRanges_holder(ir_holder, j); width = _get_width_elt_from_IRanges_holder(ir_holder, j); IntPairAE_insert_at(intpair_ae, IntPairAE_get_nelt(intpair_ae), start, width); } return ir_len; } /**************************************************************************** * "range" method. */ /* --- .Call ENTRY POINT --- */ SEXP IRanges_range(SEXP x) { int x_len, min, max, i, end; const int *start_p, *width_p; SEXP ans, ans_start, ans_width; x_len = _get_IRanges_length(x); if (x_len == 0) { PROTECT(ans_start = NEW_INTEGER(0)); PROTECT(ans_width = NEW_INTEGER(0)); PROTECT(ans = _new_IRanges("IRanges", ans_start, ans_width, R_NilValue)); UNPROTECT(3); return ans; } start_p = INTEGER(_get_IRanges_start(x)); width_p = INTEGER(_get_IRanges_width(x)); min = *(start_p++); max = min + *(width_p++) - 1; for (i = 1; i < x_len; i++, start_p++, width_p++) { if (*start_p < min) min = *start_p; end = *start_p + *width_p - 1; if (end > max) max = end; } PROTECT(ans_start = ScalarInteger(min)); PROTECT(ans_width = ScalarInteger(max - min + 1)); PROTECT(ans = _new_IRanges("IRanges", ans_start, ans_width, R_NilValue)); UNPROTECT(3); return ans; } /**************************************************************************** * "ranges" methods. */ /* WARNING: The reduced ranges are *appended* to 'out_ranges'! Returns the number of ranges that were appended. */ static int reduce_ranges(const int *x_start, const int *x_width, int x_len, int drop_empty_ranges, int min_gapwidth, int *order_buf, IntPairAE *out_ranges, IntAEAE *revmap, int *out_inframe_start) { int out_len, out_len0, i, j, start_j, width_j, end_j, append_or_drop, max_end, gapwidth, delta, width_inc; IntAE *tmp, *revmap_elt; if (min_gapwidth < 0) error("IRanges internal error in reduce_ranges(): " "negative min_gapwidth not supported"); get_order_of_int_pairs(x_start, x_width, x_len, 0, order_buf, 0); out_len = out_len0 = IntPairAE_get_nelt(out_ranges); for (i = 0; i < x_len; i++) { j = order_buf[i]; start_j = x_start[j]; width_j = x_width[j]; end_j = start_j + width_j - 1; if (i == 0) { /* 'append_or_drop' is a toggle that indicates how the current input range should be added to 'out_ranges': 1 for appended (or dropped), 0 for merged. */ append_or_drop = 1; max_end = end_j; delta = start_j - 1; } else { /* If 'i' != 0 and 'append_or_drop' is 1 then the previous range was empty so 'gapwidth' will be >= 0. */ gapwidth = start_j - max_end - 1; if (gapwidth >= min_gapwidth) append_or_drop = 1; } if (append_or_drop) { if (width_j != 0 || (!drop_empty_ranges && (out_len == out_len0 || start_j != out_ranges->a->elts[ out_len - 1]))) { /* Append to 'out_ranges'. */ IntPairAE_insert_at(out_ranges, out_len, start_j, width_j); if (revmap != NULL) { /* Append to 'revmap'. */ tmp = new_IntAE(1, 1, j + 1); IntAEAE_insert_at(revmap, out_len, tmp); revmap_elt = revmap->elts[out_len]; } out_len++; append_or_drop = 0; } max_end = end_j; if (i != 0) delta += gapwidth; } else { width_inc = end_j - max_end; if (width_inc > 0) { /* Merge with last range in 'out_ranges'. */ out_ranges->b->elts[out_len - 1] += width_inc; max_end = end_j; } if (!(width_j == 0 && drop_empty_ranges) && revmap != NULL) { /* Append to 'revmap'. */ IntAE_insert_at(revmap_elt, IntAE_get_nelt(revmap_elt), j + 1); } } if (out_inframe_start != NULL) out_inframe_start[j] = start_j - delta; } return out_len - out_len0; } /* --- .Call ENTRY POINT --- */ SEXP Ranges_reduce(SEXP x_start, SEXP x_width, SEXP drop_empty_ranges, SEXP min_gapwidth, SEXP with_revmap, SEXP with_inframe_start) { int x_len, *inframe_start; const int *x_start_p, *x_width_p; SEXP ans, ans_names, ans_revmap, ans_inframe_start; IntPairAE *out_ranges; IntAE *order_buf; IntAEAE *revmap; x_len = check_integer_pairs(x_start, x_width, &x_start_p, &x_width_p, "start(x)", "width(x)"); if (LOGICAL(with_revmap)[0]) { revmap = new_IntAEAE(0, 0); } else { revmap = NULL; } if (LOGICAL(with_inframe_start)[0]) { PROTECT(ans_inframe_start = NEW_INTEGER(x_len)); inframe_start = INTEGER(ans_inframe_start); } else { inframe_start = NULL; } out_ranges = new_IntPairAE(0, 0); order_buf = new_IntAE(x_len, 0, 0); reduce_ranges(x_start_p, x_width_p, x_len, LOGICAL(drop_empty_ranges)[0], INTEGER(min_gapwidth)[0], order_buf->elts, out_ranges, revmap, inframe_start); /* Make 'ans' */ PROTECT(ans = NEW_LIST(4)); PROTECT(ans_names = NEW_CHARACTER(4)); SET_STRING_ELT(ans_names, 0, mkChar("start")); SET_STRING_ELT(ans_names, 1, mkChar("width")); SET_STRING_ELT(ans_names, 2, mkChar("revmap")); SET_STRING_ELT(ans_names, 3, mkChar("inframe.start")); SET_NAMES(ans, ans_names); UNPROTECT(1); SET_VECTOR_ELT(ans, 0, new_INTEGER_from_IntAE(out_ranges->a)); SET_VECTOR_ELT(ans, 1, new_INTEGER_from_IntAE(out_ranges->b)); if (revmap != NULL) { PROTECT(ans_revmap = new_LIST_from_IntAEAE(revmap, 0)); SET_VECTOR_ELT(ans, 2, ans_revmap); UNPROTECT(1); } if (inframe_start != NULL) { SET_VECTOR_ELT(ans, 3, ans_inframe_start); UNPROTECT(1); } UNPROTECT(1); return ans; } /* --- .Call ENTRY POINT --- */ SEXP CompressedIRangesList_reduce(SEXP x, SEXP drop_empty_ranges, SEXP min_gapwidth, SEXP with_revmap) { SEXP ans, ans_names, ans_revmap, ans_partitioning_end; //ans_unlistData, ans_partitioning; CompressedIRangesList_holder x_holder; IRanges_holder ir_holder; int x_len, in_len_max, i; IntAE *order_buf; IntPairAE *in_ranges, *out_ranges; IntAEAE *revmap; x_holder = _hold_CompressedIRangesList(x); x_len = _get_length_from_CompressedIRangesList_holder(&x_holder); if (LOGICAL(with_revmap)[0]) { revmap = new_IntAEAE(0, 0); } else { revmap = NULL; } in_len_max = get_elt_from_CompressedIRangesList_holderlens_max(&x_holder); order_buf = new_IntAE(in_len_max, 0, 0); in_ranges = new_IntPairAE(0, 0); out_ranges = new_IntPairAE(0, 0); PROTECT(ans_partitioning_end = NEW_INTEGER(x_len)); for (i = 0; i < x_len; i++) { ir_holder = _get_elt_from_CompressedIRangesList_holder(&x_holder, i); IntPairAE_set_nelt(in_ranges, 0); append_IRanges_holder_to_IntPairAE(in_ranges, &ir_holder); reduce_ranges(in_ranges->a->elts, in_ranges->b->elts, IntPairAE_get_nelt(in_ranges), LOGICAL(drop_empty_ranges)[0], INTEGER(min_gapwidth)[0], order_buf->elts, out_ranges, revmap, NULL); INTEGER(ans_partitioning_end)[i] = IntPairAE_get_nelt(out_ranges); } /* Make 'ans' */ PROTECT(ans = NEW_LIST(4)); PROTECT(ans_names = NEW_CHARACTER(4)); SET_STRING_ELT(ans_names, 0, mkChar("start")); SET_STRING_ELT(ans_names, 1, mkChar("width")); SET_STRING_ELT(ans_names, 2, mkChar("revmap")); SET_STRING_ELT(ans_names, 3, mkChar("partitioning_by_end")); SET_NAMES(ans, ans_names); UNPROTECT(1); SET_VECTOR_ELT(ans, 0, new_INTEGER_from_IntAE(out_ranges->a)); SET_VECTOR_ELT(ans, 1, new_INTEGER_from_IntAE(out_ranges->b)); if (revmap != NULL) { PROTECT(ans_revmap = new_LIST_from_IntAEAE(revmap, 0)); SET_VECTOR_ELT(ans, 2, ans_revmap); UNPROTECT(1); } SET_VECTOR_ELT(ans, 3, ans_partitioning_end); UNPROTECT(2); /* PROTECT(ans_unlistData = _new_IRanges_from_IntPairAE("IRanges", out_ranges)); PROTECT(ans_names = duplicate(_get_CompressedList_names(x))); PROTECT(ans_partitioning = _new_PartitioningByEnd( "PartitioningByEnd", ans_partitioning_end, ans_names)); PROTECT(ans = _new_CompressedList(get_classname(x), ans_unlistData, ans_partitioning)); UNPROTECT(5); */ return ans; } /**************************************************************************** * "gaps" methods. */ /* WARNING: The ranges representing the gaps are *appended* to 'out_ranges'! Returns the number of ranges that were appended. */ static int gaps_ranges(const int *x_start, const int *x_width, int x_len, int restrict_start, int restrict_end, int *order_buf, IntPairAE *out_ranges) { int out_len, out_len0, i, j, start_j, width_j, end_j, max_end, gapstart, gapwidth; if (restrict_start != NA_INTEGER) max_end = restrict_start - 1; else max_end = NA_INTEGER; get_order_of_int_pairs(x_start, x_width, x_len, 0, order_buf, 0); out_len = out_len0 = IntPairAE_get_nelt(out_ranges); for (i = 0; i < x_len; i++) { j = order_buf[i]; width_j = x_width[j]; if (width_j == 0) continue; start_j = x_start[j]; end_j = start_j + width_j - 1; if (max_end == NA_INTEGER) { max_end = end_j; } else { gapstart = max_end + 1; if (restrict_end != NA_INTEGER && start_j > restrict_end + 1) start_j = restrict_end + 1; gapwidth = start_j - gapstart; if (gapwidth >= 1) { /* Append to 'out_ranges'. */ IntPairAE_insert_at(out_ranges, out_len, gapstart, gapwidth); out_len++; max_end = end_j; } else if (end_j > max_end) { max_end = end_j; } } if (restrict_end != NA_INTEGER && max_end >= restrict_end) break; } if (restrict_end != NA_INTEGER && max_end != NA_INTEGER && max_end < restrict_end) { gapstart = max_end + 1; gapwidth = restrict_end - max_end; /* Append to 'out_ranges'. */ IntPairAE_insert_at(out_ranges, out_len, gapstart, gapwidth); out_len++; } return out_len - out_len0; } /* --- .Call ENTRY POINT --- */ SEXP IRanges_gaps(SEXP x_start, SEXP x_width, SEXP start, SEXP end) { int x_len; const int *x_start_p, *x_width_p; SEXP ans, ans_names; IntPairAE *out_ranges; IntAE *order_buf; x_len = check_integer_pairs(x_start, x_width, &x_start_p, &x_width_p, "start(x)", "width(x)"); out_ranges = new_IntPairAE(0, 0); order_buf = new_IntAE(x_len, 0, 0); gaps_ranges(x_start_p, x_width_p, x_len, INTEGER(start)[0], INTEGER(end)[0], order_buf->elts, out_ranges); PROTECT(ans = NEW_LIST(2)); PROTECT(ans_names = NEW_CHARACTER(2)); SET_STRING_ELT(ans_names, 0, mkChar("start")); SET_STRING_ELT(ans_names, 1, mkChar("width")); SET_NAMES(ans, ans_names); UNPROTECT(1); SET_VECTOR_ELT(ans, 0, new_INTEGER_from_IntAE(out_ranges->a)); SET_VECTOR_ELT(ans, 1, new_INTEGER_from_IntAE(out_ranges->b)); UNPROTECT(1); return ans; } /* --- .Call ENTRY POINT --- */ SEXP CompressedIRangesList_gaps(SEXP x, SEXP start, SEXP end) { SEXP ans, ans_names, ans_unlistData, ans_partitioning, ans_partitioning_end; CompressedIRangesList_holder x_holder; IRanges_holder ir_holder; int x_len, in_len_max, start_len, *start_elt, *end_elt, i; IntAE *order_buf; IntPairAE *in_ranges, *out_ranges; x_holder = _hold_CompressedIRangesList(x); x_len = _get_length_from_CompressedIRangesList_holder(&x_holder); in_len_max = get_elt_from_CompressedIRangesList_holderlens_max(&x_holder); order_buf = new_IntAE(in_len_max, 0, 0); in_ranges = new_IntPairAE(0, 0); out_ranges = new_IntPairAE(0, 0); start_len = LENGTH(start); if ((start_len != 1 && start_len != x_len) || start_len != LENGTH(end)) error("'start' and 'end' should both be integer vectors " "of length 1 or length(x)"); PROTECT(ans_partitioning_end = NEW_INTEGER(x_len)); start_elt = INTEGER(start); end_elt = INTEGER(end); for (i = 0; i < x_len; i++) { ir_holder = _get_elt_from_CompressedIRangesList_holder(&x_holder, i); IntPairAE_set_nelt(in_ranges, 0); append_IRanges_holder_to_IntPairAE(in_ranges, &ir_holder); gaps_ranges(in_ranges->a->elts, in_ranges->b->elts, IntPairAE_get_nelt(in_ranges), *start_elt, *end_elt, order_buf->elts, out_ranges); INTEGER(ans_partitioning_end)[i] = IntPairAE_get_nelt(out_ranges); if (start_len != 1) { start_elt++; end_elt++; } } PROTECT(ans_unlistData = _new_IRanges_from_IntPairAE("IRanges", out_ranges)); PROTECT(ans_names = duplicate(_get_CompressedList_names(x))); PROTECT(ans_partitioning = _new_PartitioningByEnd( "PartitioningByEnd", ans_partitioning_end, ans_names)); PROTECT(ans = _new_CompressedList(get_classname(x), ans_unlistData, ans_partitioning)); UNPROTECT(5); return ans; } /**************************************************************************** * "disjointBins" method. */ /* --- .Call ENTRY POINT --- * Worst case complexity of O(n^2) :(, but in practice very fast. */ SEXP Ranges_disjointBins(SEXP x_start, SEXP x_width) { SEXP ans; IntAE *bin_ends = new_IntAE(128, 0, 0); PROTECT(ans = NEW_INTEGER(length(x_start))); for (int i = 0; i < length(x_start); i++) { // find a bin, starting at first int j = 0, end = INTEGER(x_start)[i] + INTEGER(x_width)[i] - 1; for (; j < IntAE_get_nelt(bin_ends) && bin_ends->elts[j] >= INTEGER(x_start)[i]; j++); // remember when this bin will be open if (j == IntAE_get_nelt(bin_ends)) IntAE_append(bin_ends, &end, 1); else bin_ends->elts[j] = end; // store the bin for this range INTEGER(ans)[i] = j + 1; } UNPROTECT(1); return ans; } IRanges/tests/0000755000175100017510000000000012607265143014272 5ustar00biocbuildbiocbuildIRanges/tests/IRanges_unit_tests.R0000644000175100017510000000011712607265143020225 0ustar00biocbuildbiocbuildrequire("IRanges") || stop("unable to load IRanges package") IRanges:::.test() IRanges/vignettes/0000755000175100017510000000000012612026576015141 5ustar00biocbuildbiocbuildIRanges/vignettes/IRangesOverview.Rnw0000644000175100017510000010363712607265143020721 0ustar00biocbuildbiocbuild%\VignetteIndexEntry{An Introduction to IRanges} %\VignetteDepends{} %\VignetteKeywords{Ranges} %\VignettePackage{IRanges} \documentclass[10pt]{article} \usepackage{times} \usepackage{hyperref} \textwidth=6.5in \textheight=8.5in %\parskip=.3cm \oddsidemargin=-.1in \evensidemargin=-.1in \headheight=-.3in \newcommand{\Rfunction}[1]{{\texttt{#1}}} \newcommand{\Robject}[1]{{\texttt{#1}}} \newcommand{\Rpackage}[1]{{\textit{#1}}} \newcommand{\Rmethod}[1]{{\texttt{#1}}} \newcommand{\Rfunarg}[1]{{\texttt{#1}}} \newcommand{\Rclass}[1]{{\textit{#1}}} \newcommand{\Rcode}[1]{{\texttt{#1}}} \newcommand{\software}[1]{\textsf{#1}} \newcommand{\R}{\software{R}} \newcommand{\IRanges}{\Rpackage{IRanges}} \title{An Introduction to \IRanges{}} \author{Patrick Aboyoun, Michael Lawrence, Herv\'e Pag\`es} \date{\today} \begin{document} \maketitle <>= options(width=72) @ \section{Introduction} The \IRanges{} package is designed to represent sequences, ranges representing indices along those sequences, and data related to those ranges. In this vignette, we will rely on simple, illustrative example datasets, rather than large, real-world data, so that each data structure and algorithm can be explained in an intuitive, graphical manner. We expect that packages that apply \IRanges{} to a particular problem domain will provide vignettes with relevant, realistic examples. The \IRanges{} package is available at bioconductor.org and can be downloaded via \Rfunction{biocLite}: <>= source("http://bioconductor.org/biocLite.R") biocLite("IRanges") @ <>= library(IRanges) @ \section{Vector objects} In the context of the \IRanges{} package, a sequence is an ordered finite collection of elements. The \IRanges{} packages represents two types of objects as sequences: (1) atomic sequences and (2) lists (or non-atomic sequences). The following subsections describe each in turn. All \IRanges{}-derived sequences inherit from the \Rclass{Vector} virtual class. \subsection{Atomic Vectors} In \R{}, atomic sequences are typically stored in atomic vectors. The \IRanges{} package includes an additional atomic sequence object type, \Rclass{Rle}, which compresses an atomic sequence through run-length encoding. We begin our discussion of atomic sequences using two \Rclass{Rle} vectors. <>= set.seed(0) lambda <- c(rep(0.001, 4500), seq(0.001, 10, length = 500), seq(10, 0.001, length = 500)) xVector <- Rle(rpois(1e7, lambda)) yVector <- Rle(rpois(1e7, lambda[c(251:length(lambda), 1:250)])) @ All atomic sequences in \R{} have three main properties: (1) a notion of length or number of elements, (2) the ability to extract elements to create new atomic sequences, and (3) the ability to be combined with one or more atomic sequences to form larger atomic sequences. The main functions for these three operations are \Rfunction{length}, \Rfunction{[}, and \Rfunction{c}. <>= length(xVector) xVector[1] zVector <- c(xVector, yVector) @ While these three methods may seem trivial, they provide a great deal of power and many atomic sequence manipulations can be constructed using them. \subsubsection{Vector Subsetting} As with ordinary \R{} atomic vectors, it is often necessary to subset one sequence from another. When this subsetting does not duplicate or reorder the elements being extracted, the result is called a \textit{subsequence}. In general, the \Rfunction{[} function can be used to construct a new sequence or extract a subsequence, but its interface is often inconvenient and not amenable to optimization. To compensate for this, the \IRanges{} package supports seven additional functions for sequence extraction: \begin{enumerate} \item \Rfunction{window} - Extracts a subsequence over a specified region. \item \Rfunction{subset} - Extracts the subsequence specified by a logical vector. \item \Rfunction{head} - Extracts a consecutive subsequence containing the first n elements. \item \Rfunction{tail} - Extracts a consecutive subsequence containing the last n elements. \item \Rfunction{rev} - Creates a new sequence with the elements in the reverse order. \item \Rfunction{rep} - Creates a new sequence by repeating sequence elements. \end{enumerate} The following code illustrates how these functions are used on an ordinary \R{} \Rclass{integer} vector: <>= xSnippet <- xVector[IRanges(4751, 4760)] xSnippet head(xSnippet) tail(xSnippet) rev(xSnippet) rep(xSnippet, 2) subset(xSnippet, xSnippet >= 5L) @ \subsubsection{Combining Vectors} The \IRanges{} package uses two generic functions, \Rfunction{c} and \Rfunction{append}, for combining two \Rclass{Vector} objects. The methods for \Rclass{Vector} objects follow the definition that these two functions are given the the \Rpackage{base} package. <>= c(xSnippet, rev(xSnippet)) append(xSnippet, xSnippet, after = 3) @ \subsubsection{Looping over Vectors and Vector subsets} In \R{}, \Rfunction{for} looping can be an expensive operation. To compensate for this, \IRanges{} uses three generics, \Rfunction{endoapply}, \Rfunction{lapply}, and \Rfunction{sapply}, for looping over sequences and two generics, \Rfunction{aggregate} and \Rfunction{shiftApply}, to perform calculations over subsequences. The \Rfunction{lapply} and \Rfunction{sapply} functions are familiar to many \R{} users since they are the standard functions for looping over the elements of an \R{} \Rclass{list} object. The \Rfunction{endoapply} function performs an endomorphism equivalent to \Rfunction{lapply}, i.e. returns a \Rclass{Vector} object of the same class as the input rather than a \Rclass{list} object. More will be given on these three functions in the Lists subsection. The \Rfunction{aggregate} function combines sequence extraction functionality of the \Rfunction{window} function with looping capabilities of the \Rfunction{sapply} function. For example, here is some code to compute medians across a moving window of width 3 using the function \Rfunction{aggregate}: <>= xSnippet aggregate(xSnippet, start = 1:8, width = 3, FUN = median) @ The \Rfunction{shiftApply} function is a looping operation involving two sequences whose elements are lined up via a positional shift operation. For example, the elements of \Robject{xVector} and \Robject{yVector} were simulated from Poisson distributions with the mean of element i from \Robject{yVector} being equivalent to the mean of element i + 250 from \Robject{xVector}. If we did not know the size of the shift, we could estimate it by finding the shift that maximizes the correlation between \Robject{xVector} and \Robject{yVector}. <>= cor(xVector, yVector) shifts <- seq(235, 265, by=3) corrs <- shiftApply(shifts, yVector, xVector, FUN = cor) @ % <>= plot(shifts, corrs) @ The result is shown in Fig.~\ref{figshiftcorrs}. \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-figshiftcorrs} \caption{\label{figshiftcorrs}% Correlation between \Robject{xVector} and \Robject{yVector} for various shifts.} \end{center} \end{figure} \subsubsection{Run Length Encoding} Up until this point we have used \R{} atomic vectors to represent atomic sequences, but there are times when these object become too large to manage in memory. When there are lots of consecutive repeats in the sequence, the data can be compressed and managed in memory through a run-length encoding where a data value is paired with a run length. For example, the sequence \{1, 1, 1, 2, 3, 3\} can be represented as values = \{1, 2, 3\}, run lengths = \{3, 1, 2\}. The \Rclass{Rle} class in \IRanges{} is used to represent a run-length encoded (compressed) sequence of \Rclass{logical}, \Rclass{integer}, \Rclass{numeric}, \Rclass{complex}, \Rclass{character}, or \Rclass{raw} values. One way to construct an \Rclass{Rle} object is through the \Rclass{Rle} constructor function: <>= xRle <- Rle(xVector) yRle <- Rle(yVector) xRle yRle @ When there are lots of consecutive repeats, the memory savings through an RLE can be quite dramatic. For example, the \Robject{xRle} object occupies less than one quarter of the space of the original \Robject{xVector} object, while storing the same information: <>= as.vector(object.size(xRle) / object.size(xVector)) identical(as.vector(xRle), xVector) @ The functions \Rfunction{runValue} and \Rfunction{runLength} extract the run values and run lengths from an \Rclass{Rle} object respectively: <>= head(runValue(xRle)) head(runLength(xRle)) @ The \Rclass{Rle} class supports many of the basic methods associated with \R{} atomic vectors including the Ops, Math, Math2, Summary, and Complex group generics. Here is a example of manipulating \Rclass{Rle} objects using methods from the Ops group: <>= xRle > 0 xRle + yRle xRle > 0 | yRle > 0 @ Here are some from the Summary group: <>= range(xRle) sum(xRle > 0 | yRle > 0) @ And here is one from the Math group: <>= log1p(xRle) @ As with the atomic vectors, the \Rfunction{cor} and \Rfunction{shiftApply} functions operate on \Rclass{Rle} objects: <>= cor(xRle, yRle) shiftApply(249:251, yRle, xRle, FUN = function(x, y) var(x, y) / (sd(x) * sd(y))) @ For more information on the methods supported by the \Rclass{Rle} class, consult the \Rcode{Rle} man page. \subsection{Lists} In many data analysis situation there is a desire to organize and manipulate multiple objects simultaneously. Typically this is done in \R{} through the usage of a list. While a list serves as a generic container, it does not confer any information about the specific class of its elements, provides no infrastructure to ensure type safety, and the S3 and S4 method dispatch mechanisms do not support method selection for lists with homogeneous object types. The \Rclass{List} virtual class defined in the \IRanges{} package addresses these issues. \Rclass{List} is a direct extension of \Rclass{Vector}. \subsubsection{Lists of Atomic Vectors} The first type of lists we consider are those containing atomic sequences such as \Rclass{integer} vectors or \Rclass{Rle} objects. We may wish to define a method that retrieves the length of each atomic sequence element, without special type checking. To enable this, we define collection classes such as \Rclass{IntegerList} and \Rclass{RleList}, which inherit from the \Rclass{List} virtual class, for representing lists of \Rclass{integer} vectors and \Rclass{Rle} objects respectively. <>= getClassDef("RleList") @ As the class definition above shows, the \Rclass{RleList} class is virtual with subclasses \Rclass{SimpleRleList} and \Rclass{CompressedRleList}. A \Rclass{SimpleRleList} class uses a regular \R{} list to store the underlying elements and the \Rclass{CompressedRleList} class stores the elements in an unlisted form and keeps track of where the element breaks are. The former ``simple list" class is useful when the Rle elements are long and the latter ``compressed list" class is useful when the list is long and/or sparse (i.e. a number of the list elements have length 0). In fact, all of the atomic vector types (raw, logical, integer, numeric, complex, and character) have similar list classes that derive from the \Rclass{List} virtual class. For example, there is an \Rclass{IntegerList} virtual class with subclasses \Rclass{SimpleIntegerList} and \Rclass{CompressedIntegerList}. Each of the list classes for atomic sequences, be they stored as vectors or \Rclass{Rle} objects, have a constructor function with a name of the appropriate list virtual class, such as \Rclass{IntegerList}, and an optional argument \Rfunarg{compress} that takes an argument to specify whether or not to create the simple list object type or the compressed list object type. The default is to create the compressed list object type. <>= args(IntegerList) cIntList1 <- IntegerList(x = xVector, y = yVector) cIntList1 sIntList2 <- IntegerList(x = xVector, y = yVector, compress = FALSE) sIntList2 ## sparse integer list xExploded <- lapply(xVector[1:5000], function(x) seq_len(x)) cIntList2 <- IntegerList(xExploded) sIntList2 <- IntegerList(xExploded, compress = FALSE) object.size(cIntList2) object.size(sIntList2) @ The \Rfunction{length} function returns the number of elements in a \Rclass{Vector}-derived object and, for a \Rclass{List}-derived object like ``simple list" or ``compressed list", the \Rfunction{elementLengths} function returns an integer vector containing the lengths of each of the elements: <>= length(cIntList2) Rle(elementLengths(cIntList2)) @ Just as with ordinary \R{} \Rclass{list} objects, \Rclass{List}-derived object support the \Rfunction{[[} for element extraction, \Rfunction{c} for combining, and \Rfunction{lapply}/\Rfunction{sapply} for looping. When looping over sparse lists, the ``compressed list" classes can be much faster during computations since only the non-empty elements are looped over during the \Rfunction{lapply}/\Rfunction{sapply} computation and all the empty elements are assigned the appropriate value based on their status. <>= system.time(sapply(xExploded, mean)) system.time(sapply(sIntList2, mean)) system.time(sapply(cIntList2, mean)) identical(sapply(xExploded, mean), sapply(sIntList2, mean)) identical(sapply(xExploded, mean), sapply(cIntList2, mean)) @ Unlist ordinary \R{} \Rclass{list} objects, \Rclass{AtomicList} objects support the \Rfunction{Ops} (e.g. \Rfunction{+}, \Rfunction{==}, \Rfunction{\&}), \Rfunction{Math} (e.g. \Rfunction{log}, \Rfunction{sqrt}), \Rfunction{Math2} (e.g. \Rfunction{round}, \Rfunction{signif}), \Rfunction{Summary} (e.g. \Rfunction{min}, \Rfunction{max}, \Rfunction{sum}), and \Rfunction{Complex} (e.g. \Rfunction{Re}, \Rfunction{Im}) group generics. <>= xRleList <- RleList(xRle, 2L * rev(xRle)) yRleList <- RleList(yRle, 2L * rev(yRle)) xRleList > 0 xRleList + yRleList sum(xRleList > 0 | yRleList > 0) @ Since these atomic lists inherit from \Rclass{List}, they can also use the looping function \Rfunction{endoapply} to perform endomorphisms. <>= safe.max <- function(x) { if(length(x)) max(x) else integer(0) } endoapply(sIntList2, safe.max) endoapply(cIntList2, safe.max) endoapply(sIntList2, safe.max)[[1]] @ \section{Data Tables} To Do: \Rclass{DataTable}, \Rclass{DataFrame}, \Rclass{DataFrameList}, \Rclass{SplitDataFrameList} \section{Vector Annotations} Often when one has a collection of objects, there is a need to attach metadata that describes the collection in some way. Two kinds of metadata can be attached to a \Rclass{Vector} object: \begin{enumerate} \item Metadata about the object as a whole: this metadata is accessed via the \Rfunction{metadata} accessor and is represented as an ordinary \Rclass{list}; \item Metadata about the individual elements of the object: this metadata is accessed via the \Rfunction{mcols} accessor (\Rfunction{mcols} stands for {\it metadata columns}) and is represented as a \Rclass{DataTable} object (i.e. as an instance of a concrete subclass of \Rclass{DataTable}, e.g. a \Rclass{DataFrame} object). This \Rclass{DataTable} object can be thought of as the result of binding together one or several vector-like objects (the metadata columns) of the same length as the \Rclass{Vector} object. Each row of the \Rclass{DataTable} object annotates the corresponding element of the \Rclass{Vector} object. \end{enumerate} \section{Vector Ranges} When analyzing sequences, we are often interested in particular consecutive subsequences. For example, the \Sexpr{letters} vector could be considered a sequence of lower-case letters, in alphabetical order. We would call the first five letters (\textit{a} to \textit{e}) a consecutive subsequence, while the subsequence containing only the vowels would not be consecutive. It is not uncommon for an analysis task to focus only on the geometry of the regions, while ignoring the underlying sequence values. A list of indices would be a simple way to select a subsequence. However, a sparser representation for consecutive subsequences would be a range, a pairing of a start position and a width, as used when extracting sequences with \Rfunction{window}. When analyzing subsequences in \IRanges{}, each range is treated as an observation. The virtual \Rclass{Ranges} class represents lists of ranges, or, equivalently and as a derivative \Rclass{IntegerList}, sequences of consecutive integers. The most commonly used implementation of \Rclass{Ranges} is \Rclass{IRanges}, which stores the starts and widths as ordinary integer vectors. To construct an \Rclass{IRanges} instance, we call the \Rfunction{IRanges} constructor. Ranges are normally specified by passing two out of the three parameters: start, end and width (see \Rcode{help(IRanges)} for more information). % <>= ir1 <- IRanges(start = 1:10, width = 10:1) ir2 <- IRanges(start = 1:10, end = 11) ir3 <- IRanges(end = 11, width = 10:1) identical(ir1, ir2) & identical(ir2, ir3) ir <- IRanges(c(1, 8, 14, 15, 19, 34, 40), width = c(12, 6, 6, 15, 6, 2, 7)) @ % All of the above calls construct an \Rclass{IRanges} instance with the same ranges, using different combinations of the \Rfunarg{start}, \Rfunarg{end} and \Rfunarg{width} parameters. Accessing the starts, widths and ends is supported by every \Rclass{Ranges} implementation. <>= start(ir) @ <>= end(ir) @ <>= width(ir) @ For \Rclass{IRanges} and some other \Rclass{Ranges} derivatives, subsetting is also supported, by numeric and logical indices. <>= ir[1:4] @ <>= ir[start(ir) <= 15] @ One may think of each range as a sequence of integer ranges, and \Rclass{Ranges} is, in fact, derived from \Rclass{IntegerList}. <>= ir[[1]] @ In order to illustrate range operations, we'll create a function to plot ranges. <>= plotRanges <- function(x, xlim = x, main = deparse(substitute(x)), col = "black", sep = 0.5, ...) { height <- 1 if (is(xlim, "Ranges")) xlim <- c(min(start(xlim)), max(end(xlim))) bins <- disjointBins(IRanges(start(x), end(x) + 1)) plot.new() plot.window(xlim, c(0, max(bins)*(height + sep))) ybottom <- bins * (sep + height) - height rect(start(x)-0.5, ybottom, end(x)+0.5, ybottom + height, col = col, ...) title(main) axis(1) } @ <>= plotRanges(ir) @ \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-ir-plotRanges} \caption{\label{fig-ir-plotRanges}% Plot of original ranges.} \end{center} \end{figure} \subsection{Normality} Sometimes, it is necessary to formally represent a subsequence, where no elements are repeated and order is preserved. Also, it is occasionally useful to think of a \Rclass{Ranges} object as a set, where no elements are repeated and order does not matter. While every \Rclass{Ranges} object, as a \Rclass{Vector} derivative, has an implicit ordering, one can enforce the same ordering for all such objects, so that ordering becomes inconsequential within that context. The \Rclass{NormalIRanges} class formally represents either a subsequence encoding or a set of integers. By definition a Ranges object is said to be \textit{normal} when its ranges are: (a) not empty (i.e. they have a non-null width); (b) not overlapping; (c) ordered from left to right; (d) not even adjacent (i.e. there must be a non empty gap between 2 consecutive ranges). There are three main advantages of using a \textit{normal} \Rclass{Ranges} object: (1) it guarantees a subsequence encoding or set of integers, (2) it is compact in terms of the number of ranges, and (3) it uniquely identifies its information, which simplifies comparisons. The \Rfunction{reduce} function reduces any \Rclass{Ranges} object to a \Rclass{NormalIRanges} by merging redundant ranges. <>= reduce(ir) plotRanges(reduce(ir)) @ \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-ranges-reduce} \caption{\label{fig-ranges-reduce}% Plot of reduced ranges.} \end{center} \end{figure} \subsection{Lists of \Rclass{Ranges} objects} It is common to manipulate collections of \Rclass{Ranges} objects during an analysis. Thus, the \IRanges{} package defines some specific classes for working with multiple \Rclass{Ranges} objects. The \Rclass{RangesList} class asserts that each element is a \Rclass{Ranges} object and provides convenience methods, such as \Rfunction{start}, \Rfunction{end} and \Rfunction{width} accessors that return \Rclass{IntegerList} objects, aligning with the \Rclass{RangesList} object. To explicitly construct a \Rclass{RangesList}, use the \Rfunction{RangesList} function. <>= rl <- RangesList(ir, rev(ir)) @ % <>= start(rl) @ \subsection{Vector Extraction} As the elements of a \Rclass{Ranges} object encode consecutive subsequences, they may be used directly in sequence extraction. Note that when a \textit{normal} \Rclass{Ranges} is given as the index, the result is a subsequence, as no elements are repeated or reordered. If the sequence is a \Rclass{Vector} subclass (i.e. not an ordinary \Rclass{vector}), the canonical \Rfunction{[} function accepts a \Rclass{Ranges} instance. % <>= irextract <- IRanges(start = c(4501, 4901) , width = 100) xRle[irextract] @ % \subsection{Finding Overlapping Ranges} The function \Rfunction{findOverlaps} detects overlaps between two \Rclass{Ranges} objects. <>= ol <- findOverlaps(ir, reduce(ir)) as.matrix(ol) @ \subsection{Counting Overlapping Ranges} The function \Rfunction{coverage} counts the number of ranges over each position. <>= cov <- coverage(ir) plotRanges(ir) cov <- as.vector(cov) mat <- cbind(seq_along(cov)-0.5, cov) d <- diff(cov) != 0 mat <- rbind(cbind(mat[d,1]+1, mat[d,2]), mat) mat <- mat[order(mat[,1]),] lines(mat, col="red", lwd=4) axis(2) @ \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-ranges-coverage} \caption{\label{fig-ranges-coverage}% Plot of ranges with accumulated coverage.} \end{center} \end{figure} \subsection{Finding Neighboring Ranges} The \Rfunction{nearest} function finds the nearest neighbor ranges (overlapping is zero distance). The \Rfunction{precede} and \Rfunction{follow} functions find the non-overlapping nearest neighbors on a specific side. \subsection{Transforming Ranges} Utilities are available for transforming a \Rclass{Ranges} object in a variety of ways. Some transformations, like \Rfunction{reduce} introduced above, can be dramatic, while others are simple per-range adjustments of the starts, ends or widths. \subsubsection{Adjusting starts, ends and widths} Perhaps the simplest transformation is to adjust the start values by a scalar offset, as performed by the \Rfunction{shift} function. Below, we shift all ranges forward 10 positions. % <>= shift(ir, 10) @ There are several other ways to transform ranges. These include \Rfunction{narrow}, \Rfunction{resize}, \Rfunction{flank}, \Rfunction{reflect}, \Rfunction{restrict}, and \Rfunction{threebands}. For example \Rfunction{narrow} supports the adjustment of start, end and width values, which should be relative to each range. These adjustments are vectorized over the ranges. As its name suggests, the ranges can only be narrowed. % <>= narrow(ir, start=1:5, width=2) @ The \Rfunction{restrict} function ensures every range falls within a set of bounds. Ranges are contracted as necessary, and the ranges that fall completely outside of but not adjacent to the bounds are dropped, by default. % <>= restrict(ir, start=2, end=3) @ The \Rfunction{threebands} function extends \Rfunction{narrow} so that the remaining left and right regions adjacent to the narrowed region are also returned in separate \Rclass{Ranges} objects. % <>= threebands(ir, start=1:5, width=2) @ The arithmetic operators \Rfunction{+}, \Rfunction{-} and \Rfunction{*} change both the start and the end/width by symmetrically expanding or contracting each range. Adding or subtracting a numeric (integer) vector to a \Rclass{Ranges} causes each range to be expanded or contracted on each side by the corresponding value in the numeric vector. <>= ir + seq_len(length(ir)) @ % The \Rfunction{*} operator symmetrically magnifies a \Rclass{Ranges} object by a factor, where positive contracts (zooms in) and negative expands (zooms out). % <>= ir * -2 # double the width @ WARNING: The semantic of these arithmetic operators might be revisited at some point. Please restrict their use to the context of interactive visualization (where they arguably provide some convenience) but avoid to use them programmatically. \subsubsection{Making ranges disjoint} A more complex type of operation is making a set of ranges disjoint, \textit{i.e.} non-overlapping. For example, \Rfunction{threebands} returns a disjoint set of three ranges for each input range. The \Rfunction{disjoin} function makes a \Rclass{Ranges} object disjoint by fragmenting it into the widest ranges where the set of overlapping ranges is the same. <>= disjoin(ir) plotRanges(disjoin(ir)) @ \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-ranges-disjoin} \caption{\label{fig-ranges-disjoin}% Plot of disjoined ranges.} \end{center} \end{figure} A variant of \Rfunction{disjoin} is \Rfunction{disjointBins}, which divides the ranges into bins, such that the ranges in each bin are disjoint. The return value is an integer vector of the bins. <>= disjointBins(ir) @ \subsubsection{Other transformations} Other transformations include \Rfunction{reflect} and \Rfunction{flank}. The former ``flips'' each range within a set of common reference bounds. <>= reflect(ir, IRanges(start(ir), width=width(ir)*2)) @ % The \Rfunction{flank} returns ranges of a specified width that flank, to the left (default) or right, each input range. One use case of this is forming promoter regions for a set of genes. <>= flank(ir, width = seq_len(length(ir))) @ % \subsection{Set Operations} Sometimes, it is useful to consider a \Rclass{Ranges} object as a set of integers, although there is always an implicit ordering. This is formalized by \Rclass{NormalIRanges}, above, and we now present versions of the traditional mathematical set operations \textit{complement}, \textit{union}, \textit{intersect}, and \textit{difference} for \Rclass{Ranges} objects. There are two variants for each operation. The first treats each \Rclass{Ranges} object as a set and returns a \textit{normal} value, while the other has a ``parallel'' semantic like \Rfunction{pmin}/\Rfunction{pmax} and performs the operation for each range pairing separately. The \textit{complement} operation is implemented by the \Rfunction{gaps} and \Rfunction{pgap} functions. By default, \Rfunction{gaps} will return the ranges that fall between the ranges in the (normalized) input. It is possible to specify a set of bounds, so that flanking ranges are included. <>= gaps(ir, start=1, end=50) plotRanges(gaps(ir, start=1, end=50), c(1,50)) @ \begin{figure}[tb] \begin{center} \includegraphics[width=0.5\textwidth]{IRangesOverview-ranges-gaps} \caption{\label{fig-ranges-gap}% Plot of gaps from ranges.} \end{center} \end{figure} \Rfunction{pgap} considers each parallel pairing between two \Rclass{Ranges} objects and finds the range, if any, between them. Note that the function name is singular, suggesting that only one range is returned per range in the input. <>= @ The remaining operations, \textit{union}, \textit{intersect} and \textit{difference} are implemented by the \Rfunction{[p]union}, \Rfunction{[p]intersect} and \Rfunction{[p]setdiff} functions, respectively. These are relatively self-explanatory. <>= @ <>= @ <>= @ <>= @ <>= @ <>= @ % \subsection{Mapping Ranges Between Vectors} % \Rfunction{mapCoords} \section{Vector Views} The \IRanges{} package provides the virtual \Rclass{Views} class, which stores a sequence together with an \Rclass{IRanges} object defining ranges on the sequence. Each range is said to represent a \textit{view} onto the sequence. Here, we will demonstrate the \Rclass{RleViews} class, where the sequence is of class \Rclass{Rle}. Other \Rclass{Views} implementations exist, such as \Rclass{XStringViews} in the \Rpackage{Biostrings} package. \subsection{Creating Views} There are two basic constructors for creating views: the \Rfunction{Views} function based on indicators and the \Rfunction{slice} based on numeric boundaries. <>= xViews <- Views(xRle, xRle >= 1) xViews <- slice(xRle, 1) xViewsList <- slice(xRleList, 1) @ \subsection{Aggregating Views} While \Rfunction{sapply} can be used to loop over each window, the native functions \Rfunction{viewMaxs}, \Rfunction{viewMins}, \Rfunction{viewSums}, and \Rfunction{viewMeans} provide fast looping to calculate their respective statistical summaries. <>= head(viewSums(xViews)) viewSums(xViewsList) head(viewMaxs(xViews)) viewMaxs(xViewsList) @ \section{Data on Ranges} IMPORTANT NOTE: Starting with BioC 2.12, the use of \Rclass{RangedData} and \Rclass{RangedDataList} objects is discouraged in favor of \Rclass{GRanges} and \Rclass{GRangesList} objects (those classes are defined in the \Rpackage{GenomicRanges} package). When analyzing ranges, there are often additional variables of interest, besides the geometry (starts, ends and widths). To formally represent a dataset where the ranges are the observations, \IRanges{} defines the \Rclass{RangedData} class. %\subsection{Manipulating \Rclass{RangedData}} To create a \Rclass{RangedData} instance, one needs to provide a \Rclass{Ranges} object and, optionally, any number of variables on those ranges. The variable objects need not be vectors, but they must satisfy the contract of \Rclass{DataFrame}. <>= values <- rnorm(length(ir)) rd <- RangedData(ir, name = letters[seq_len(length(ir))], values) rd @ One might notice the term ``sequence'' in the above output. This refers to an important feature of \Rclass{RangedData}: the ability to segregate ranges by their sequence (or space). For example, when analyzing genomic data, one is often working with ranges on different chromosomes. In many cases, such as when calculating overlap, one needs to separately treat ranges from different spaces, and \Rclass{RangedData} aims to facilitate this mode of operation. The segregation may be performed at construction time. <>= rd <- RangedData(ir, name = letters[seq_len(length(ir))], values, space = rep(c("chr1", "chr2"), c(3, length(ir) - 3))) rd @ With the knowledge that the data is split into spaces, it should not be surprising that the \Rfunction{ranges} accessor returns a \Rclass{RangesList} and \Rfunction{values} returns a \Rclass{SplitDataFrameList}. <>= ranges(rd) @ <>= values(rd) @ To obtain a \Rclass{RangedData} for a specific set of spaces, one should use the \Rfunction{[} function, which accepts logical, numeric and character indices. <>= rd["chr1"] @ % <>= all(identical(rd["chr1"], rd[1]), identical(rd[1], rd[c(TRUE, FALSE)])) @ The \Rfunction{names} and \Rfunction{length} functions return the names and number of spaces, respectively. <>= names(rd) @ <>= length(rd) @ The \Rfunction{lapply} function operates over the spaces. The object passed to the user function is a subset \Rclass{RangedData}. <>= lapply(rd, names) @ The above would suggest that \Rclass{RangedData} is a sequence of spaces. However, \Rclass{RangedData} also inherits from \Rclass{DataTable}, so it in some ways behaves like a sequence of columns. For example, one can extract a column via \Rfunction{\$} or \Rfunction{[[}. <>= rd[[2]] @ <>= rd$values @ Note that the extracted columns are ``unlisted'' over the spaces, which is usually much more convenient than obtaining them as lists. It is important to note that the elements have been sorted by the space factor and thus may not have the same order as the objects passed to the constructor. The two dimensional matrix-style subsetting is also supported. The rows are indexed globally, independent of space. <>= rd[1:3, "name"] @ \section{IRanges in Biological Sequence Analysis} The \IRanges{} packages was primarily designed with biological sequence analysis in mind and Table \ref{table:bioseq} shows how some biological sequence analysis concepts are represented in the \IRanges{} class system. \begin{table}[ht] \begin{center} \begin{tabular}{l|l} \hline Biological Entity & \Rclass{Vector} Subclass \\ \hline Genome browser track(s) & \Rclass{GRanges}/\Rclass{GRangesList} \\ Coverage across chromosomes/contigs & \Rclass{RleList} \\ Mapped ranges to genome & \Rclass{CompressedIRangesList} \\ Data (sans ranges) across chroms/contigs & \Rclass{SplitDataFrameList} \\ \hline \end{tabular} \end{center} \caption{\Rclass{Vector} subclasses for Biological Sequence Analysis} \label{table:bioseq} \end{table} \pagebreak[4] \section{Session Information} \begin{table*}[tbp] \begin{minipage}{\textwidth} <>= toLatex(sessionInfo()) @ \end{minipage} \caption{\label{tab:sessioninfo}% The output of \Rfunction{sessionInfo} on the build system after running this vignette.} \end{table*} \end{document}