1// 2// BCNucleotideDNA.m 3// BioCocoa 4// 5// Created by John Timmer on 8/11/04. 6// Copyright (c) 2003-2009 The BioCocoa Project. 7// All rights reserved. 8// 9// Redistribution and use in source and binary forms, with or without 10// modification, are permitted provided that the following conditions 11// are met: 12// 1. Redistributions of source code must retain the above copyright 13// notice, this list of conditions and the following disclaimer. 14// 2. Redistributions in binary form must reproduce the above copyright 15// notice, this list of conditions and the following disclaimer in the 16// documentation and/or other materials provided with the distribution. 17// 3. The name of the author may not be used to endorse or promote products 18// derived from this software without specific prior written permission. 19// 20// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31#import "BCNucleotideDNA.h" 32#import "BCNucleotideRNA.h" 33 34 35static BCNucleotideDNA *adenosineRepresentation = nil; 36static BCNucleotideDNA *thymidineRepresentation = nil; 37static BCNucleotideDNA *cytidineRepresentation = nil; 38static BCNucleotideDNA *guanidineRepresentation = nil; 39static BCNucleotideDNA *anyBaseRepresentation = nil; 40static BCNucleotideDNA *purineRepresentation = nil; 41static BCNucleotideDNA *pyrimidineRepresentation = nil; 42static BCNucleotideDNA *strongRepresentation = nil; 43static BCNucleotideDNA *weakRepresentation = nil; 44static BCNucleotideDNA *aminoRepresentation = nil; 45static BCNucleotideDNA *ketoRepresentation = nil; 46static BCNucleotideDNA *HRepresentation = nil; 47static BCNucleotideDNA *VRepresentation = nil; 48static BCNucleotideDNA *DRepresentation = nil; 49static BCNucleotideDNA *BRepresentation = nil; 50static BCNucleotideDNA *gapRepresentation = nil; 51static BCNucleotideDNA *undefinedRepresentation = nil; 52 53static NSMutableDictionary *customBases = nil; 54 55 56@implementation BCNucleotideDNA 57 58 59#if 0 60#pragma mark � CLASS METHODS 61#endif 62//////////////////////////////////////////////////////////////////////////// 63// THIS METHOD CREATES THE SINGLETON REFERENCES TO ALL THE STANDARD BASES 64//////////////////////////////////////////////////////////////////////////// 65+ (void) initBases { 66 // FIND OUR BUNDLE AND LOAD UP THE BASE DEFINITIONS 67 NSBundle *biococoaBundle = [NSBundle bundleForClass: [BCNucleotideDNA class]]; 68 NSString *filePath = [biococoaBundle pathForResource: @"nucleotides" ofType: @"plist"]; 69 if ( filePath == nil ) 70 return; 71 72 NSMutableDictionary *baseDefinitions = [NSMutableDictionary dictionaryWithContentsOfFile: filePath]; 73 if ( baseDefinitions == nil ) 74 return; 75 76 customBases = [baseDefinitions retain]; 77 78 // GO THROUGH AND CREATE EACH SINGLETON BASE DEFINITION, USING THE DICTIONARY 79 NSDictionary *tempDict = [baseDefinitions objectForKey: @"A"]; 80 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 81 adenosineRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'A']; 82 [baseDefinitions removeObjectForKey: @"A"]; 83 } 84 85 tempDict = [baseDefinitions objectForKey: @"T"]; 86 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 87 thymidineRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'T']; 88 [baseDefinitions removeObjectForKey: @"T"]; 89 } 90 91 tempDict = [baseDefinitions objectForKey: @"C"]; 92 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 93 cytidineRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'C']; 94 [baseDefinitions removeObjectForKey: @"C"]; 95 } 96 97 tempDict = [baseDefinitions objectForKey: @"G"]; 98 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 99 guanidineRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'G']; 100 [baseDefinitions removeObjectForKey: @"G"]; 101 } 102 103 tempDict = [baseDefinitions objectForKey: @"N"]; 104 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 105 anyBaseRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'N']; 106 [baseDefinitions removeObjectForKey: @"N"]; 107 } 108 109 tempDict = [baseDefinitions objectForKey: @"R"]; 110 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 111 purineRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'R']; 112 [baseDefinitions removeObjectForKey: @"R"]; 113 } 114 115 tempDict = [baseDefinitions objectForKey: @"Y"]; 116 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 117 pyrimidineRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'Y']; 118 [baseDefinitions removeObjectForKey: @"Y"]; 119 } 120 121 tempDict = [baseDefinitions objectForKey: @"S"]; 122 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 123 strongRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'S']; 124 [baseDefinitions removeObjectForKey: @"S"]; 125 } 126 127 tempDict = [baseDefinitions objectForKey: @"W"]; 128 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 129 weakRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'W']; 130 [baseDefinitions removeObjectForKey: @"W"]; 131 } 132 133 tempDict = [baseDefinitions objectForKey: @"M"]; 134 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 135 aminoRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'M']; 136 [baseDefinitions removeObjectForKey: @"M"]; 137 } 138 139 tempDict = [baseDefinitions objectForKey: @"K"]; 140 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 141 ketoRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'K']; 142 [baseDefinitions removeObjectForKey: @"K"]; 143 } 144 145 tempDict = [baseDefinitions objectForKey: @"H"]; 146 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 147 HRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'H']; 148 [baseDefinitions removeObjectForKey: @"H"]; 149 } 150 151 tempDict = [baseDefinitions objectForKey: @"V"]; 152 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 153 VRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'V']; 154 [baseDefinitions removeObjectForKey: @"V"]; 155 } 156 157 tempDict = [baseDefinitions objectForKey: @"D"]; 158 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 159 DRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'D']; 160 [baseDefinitions removeObjectForKey: @"D"]; 161 } 162 163 tempDict = [baseDefinitions objectForKey: @"B"]; 164 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 165 BRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: 'B']; 166 [baseDefinitions removeObjectForKey: @"B"]; 167 } 168 169 tempDict = [baseDefinitions objectForKey: @"-"]; 170 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 171 gapRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: '-']; 172 [baseDefinitions removeObjectForKey: @"-"]; 173 } 174 175 tempDict = [baseDefinitions objectForKey: @"?"]; 176 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 177 undefinedRepresentation = [[BCNucleotideDNA alloc] initWithSymbolChar: '?']; 178 [baseDefinitions removeObjectForKey: @"?"]; 179 } 180 181 // hang on to the dictionary, in case there are custom bases 182 customBases = [baseDefinitions retain]; 183} 184 185 186 187+ (id) objectForSavedRepresentation: (NSString *)aSymbol { 188 return [BCNucleotideDNA symbolForChar: [aSymbol characterAtIndex: 0]]; 189} 190 191 192//////////////////////////////////////////////////////////////////////////// 193// THE FOLLOWING IS A METHOD FOR OBTAINING REFERENCES TO THE 194// INDIVIDUAL BASE REPRESENTATIONS WHEN GIVEN A SINGLE LETTER CODE 195// 196// THIS WILL NOT WORK WITH CUSTOM BASES, SINCE THEIR SYMBOLS ARE NOT KNOWN IN ADVACE 197//////////////////////////////////////////////////////////////////////////// 198+ (id) symbolForChar: (unsigned char)entry { 199 switch ( entry ) { 200 201 case 'A' : 202 case 'a' : { 203 return [BCNucleotideDNA adenosine]; 204 break; 205 } 206 207 208 case 'T' : 209 case 't' : { 210 return [BCNucleotideDNA thymidine]; 211 break; 212 } 213 214 case 'C' : 215 case 'c' : { 216 return [BCNucleotideDNA cytidine]; 217 break; 218 } 219 220 case 'G' : 221 case 'g' : { 222 return [BCNucleotideDNA guanidine]; 223 break; 224 } 225 226 case 'N' : 227 case 'n' : { 228 return [BCNucleotideDNA anyBase]; 229 break; 230 } 231 232 233 case 'R' : 234 case 'r' : { 235 return [BCNucleotideDNA purine]; 236 break; 237 } 238 239 240 case 'Y' : 241 case 'y' : { 242 return [BCNucleotideDNA pyrimidine]; 243 break; 244 } 245 246 247 case 'W' : 248 case 'w' : { 249 return [BCNucleotideDNA weak]; 250 break; 251 } 252 253 254 case 'S' : 255 case 's' : { 256 return [BCNucleotideDNA strong]; 257 break; 258 } 259 260 261 case 'M' : 262 case 'm' : { 263 return [BCNucleotideDNA amino]; 264 break; 265 } 266 267 268 case 'K' : 269 case 'k' : { 270 return [BCNucleotideDNA keto]; 271 break; 272 } 273 274 275 case 'H' : 276 case 'h' : { 277 return [BCNucleotideDNA H]; 278 break; 279 } 280 281 282 case 'V' : 283 case 'v' : { 284 return [BCNucleotideDNA V]; 285 break; 286 } 287 288 289 case 'D' : 290 case 'd' : { 291 return [BCNucleotideDNA D]; 292 break; 293 } 294 295 296 case 'B' : 297 case 'b' : { 298 return [BCNucleotideDNA B]; 299 break; 300 } 301 302 303 case '-' : { 304 return [BCNucleotideDNA gap]; 305 break; 306 } 307 308 309 default : 310 return [BCNucleotideDNA undefined]; 311 } 312} 313 314 315 316//////////////////////////////////////////////////////////////////////////// 317// THE FOLLOWING ARE METHODS FOR OBTAINING REFERENCES TO THE 318// INDIVIDUAL BASE REPRESENTATIONS 319//////////////////////////////////////////////////////////////////////////// 320 321+ (BCNucleotideDNA *) adenosine { 322 if ( adenosineRepresentation == nil ) 323 [BCNucleotideDNA initBases]; 324 return adenosineRepresentation; 325} 326 327 328+ (BCNucleotideDNA *) thymidine { 329 if ( thymidineRepresentation == nil ) 330 [BCNucleotideDNA initBases]; 331 return thymidineRepresentation; 332} 333 334 335+ (BCNucleotideDNA *) cytidine { 336 if ( cytidineRepresentation == nil ) 337 [BCNucleotideDNA initBases]; 338 return cytidineRepresentation; 339} 340 341+ (BCNucleotideDNA *) guanidine { 342 if ( guanidineRepresentation == nil ) 343 [BCNucleotideDNA initBases]; 344 return guanidineRepresentation; 345} 346 347+ (BCNucleotideDNA *) anyBase { 348 if ( anyBaseRepresentation == nil ) 349 [BCNucleotideDNA initBases]; 350 return anyBaseRepresentation; 351} 352 353 354+ (BCNucleotideDNA *) purine { 355 if ( purineRepresentation == nil ) 356 [BCNucleotideDNA initBases]; 357 return purineRepresentation; 358} 359 360 361+ (BCNucleotideDNA *) pyrimidine { 362 if ( pyrimidineRepresentation == nil ) 363 [BCNucleotideDNA initBases]; 364 return pyrimidineRepresentation; 365} 366 367 368+ (BCNucleotideDNA *) strong { 369 if ( strongRepresentation == nil ) 370 [BCNucleotideDNA initBases]; 371 return strongRepresentation; 372} 373 374 375+ (BCNucleotideDNA *) weak { 376 if ( weakRepresentation == nil ) 377 [BCNucleotideDNA initBases]; 378 return weakRepresentation; 379} 380 381 382+ (BCNucleotideDNA *) amino { 383 if ( aminoRepresentation == nil ) 384 [BCNucleotideDNA initBases]; 385 return aminoRepresentation; 386} 387 388 389+ (BCNucleotideDNA *) keto { 390 if ( ketoRepresentation == nil ) 391 [BCNucleotideDNA initBases]; 392 return ketoRepresentation; 393} 394 395+ (BCNucleotideDNA *) H { 396 if ( HRepresentation == nil ) 397 [BCNucleotideDNA initBases]; 398 return HRepresentation; 399} 400 401+ (BCNucleotideDNA *) V { 402 if ( VRepresentation == nil ) 403 [BCNucleotideDNA initBases]; 404 return VRepresentation; 405} 406 407+ (BCNucleotideDNA *) D { 408 if ( DRepresentation == nil ) 409 [BCNucleotideDNA initBases]; 410 return DRepresentation; 411} 412 413+ (BCNucleotideDNA *) B { 414 if ( BRepresentation == nil ) 415 [BCNucleotideDNA initBases]; 416 return BRepresentation; 417} 418 419+ (BCNucleotideDNA *) gap { 420 if ( gapRepresentation == nil ) 421 [BCNucleotideDNA initBases]; 422 return gapRepresentation; 423} 424 425+ (BCNucleotideDNA *) undefined { 426 if ( undefinedRepresentation == nil ) 427 [BCNucleotideDNA initBases]; 428 return undefinedRepresentation; 429} 430 431 432 433+ (BCNucleotideDNA *) customBase: (NSString *)baseName { 434 if ( customBases == nil ) 435 [BCNucleotideDNA initBases]; 436 id aBase = [customBases objectForKey: baseName]; 437 if ( aBase == nil) 438 return nil; 439 440 if ( [aBase isKindOfClass: [BCNucleotideDNA class]] ) 441 return aBase; 442 443 444 if ( [aBase isKindOfClass: [NSDictionary class]] ) { 445 aBase = [[[BCNucleotideDNA alloc] initWithDictionary: aBase] autorelease]; 446 if ( aBase != nil ) { 447 [customBases setObject: aBase forKey: baseName]; 448 return aBase; 449 } 450 } 451 return nil; 452} 453 454 455 456 457//////////////////////////////////////////////////////////////////////////// 458// OBJECT METHODS 459//////////////////////////////////////////////////////////////////////////// 460#if 0 461#pragma mark � 462#pragma mark � OBJECT METHODS 463#pragma mark � 464#pragma mark �INITIALIZATION METHODS 465#endif 466 467 468- (id) initWithSymbolChar: (unsigned char)aSymbol { 469 self = [super initWithSymbolChar: aSymbol]; 470 if ( self == nil ) 471 return nil; 472 473 // we hang onto the dictionary in order to establish complement realtionships 474 // once all the bases are generated 475 symbolInfo = [[customBases objectForKey: symbolString] copy]; 476 477 // get basic information about this base 478 name = [symbolInfo objectForKey: @"Name"]; 479 if (name == nil) 480 return nil; 481 else 482 [name retain]; 483 484 [self setMonoisotopicMass: [[symbolInfo objectForKey:@"MonoisotopicMass"] floatValue]]; 485 [self setAverageMass: [[symbolInfo objectForKey:@"AverageMass"] floatValue]]; 486 487 return self; 488} 489 490#if 0 491#pragma mark �BASE INFORMATION METHODS 492#endif 493 494- (BOOL) isBase { 495 if ( self == [BCNucleotideDNA gap] || self == [BCNucleotideDNA undefined] ) 496 return NO; 497 return YES; 498} 499 500#if 0 501#pragma mark �BASE RELATIONSHIP METHODS 502#endif 503 504- (BCNucleotideRNA *) RNABaseEquivalent { 505 if ( self != [BCNucleotideDNA thymidine] ) 506 return [BCNucleotideRNA performSelector: NSSelectorFromString( name )]; 507 return [BCNucleotideRNA uridine] ; 508} 509 510 511@end 512