1// 2// BCNucleotideRNA.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 "BCNucleotideRNA.h" 32#import "BCNucleotideDNA.h" 33 34 35static BCNucleotideRNA *adenosineRepresentation = nil; 36static BCNucleotideRNA *uridineRepresentation = nil; 37static BCNucleotideRNA *cytidineRepresentation = nil; 38static BCNucleotideRNA *guanidineRepresentation = nil; 39static BCNucleotideRNA *anyBaseRepresentation = nil; 40static BCNucleotideRNA *purineRepresentation = nil; 41static BCNucleotideRNA *pyrimidineRepresentation = nil; 42static BCNucleotideRNA *strongRepresentation = nil; 43static BCNucleotideRNA *weakRepresentation = nil; 44static BCNucleotideRNA *aminoRepresentation = nil; 45static BCNucleotideRNA *ketoRepresentation = nil; 46static BCNucleotideRNA *HRepresentation = nil; 47static BCNucleotideRNA *VRepresentation = nil; 48static BCNucleotideRNA *DRepresentation = nil; 49static BCNucleotideRNA *BRepresentation = nil; 50static BCNucleotideRNA *gapRepresentation = nil; 51static BCNucleotideRNA *undefinedRepresentation = nil; 52 53static NSMutableDictionary *customBases = nil; 54 55 56@implementation BCNucleotideRNA 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: [BCNucleotideRNA class]]; 68 NSString *filePath = [biococoaBundle pathForResource: @"nucleotides" ofType: @"plist"]; 69 if ( filePath == nil ) 70 return; 71 72 NSStringEncoding enc; 73 NSError *error; 74 NSMutableString *tempString = [NSMutableString stringWithContentsOfFile: filePath 75 usedEncoding: &enc error: &error]; 76 // we adapt the DNA setup for use as RNA by replacing the thymidines with uridines 77 [tempString replaceOccurrencesOfString: @">T<" withString: @">U<" options: NSLiteralSearch range: NSMakeRange(0, [tempString length])]; 78 [tempString replaceOccurrencesOfString: @"thymidine" withString: @"uridine" options: NSLiteralSearch range: NSMakeRange(0, [tempString length])]; 79 80 81 NSMutableDictionary *baseDefinitions = [tempString propertyList]; 82 if ( baseDefinitions == nil ) 83 return; 84 85 customBases = [baseDefinitions retain]; 86 87 // GO THROUGH AND CREATE EACH SINGLETON BASE DEFINITION, USING THE DICTIONARY 88 NSDictionary *tempDict = [baseDefinitions objectForKey: @"A"]; 89 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 90 adenosineRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'A']; 91 [baseDefinitions removeObjectForKey: @"A"]; 92 } 93 94 tempDict = [baseDefinitions objectForKey: @"U"]; 95 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 96 uridineRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'U']; 97 [baseDefinitions removeObjectForKey: @"U"]; 98 } 99 100 tempDict = [baseDefinitions objectForKey: @"C"]; 101 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 102 cytidineRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'C']; 103 [baseDefinitions removeObjectForKey: @"C"]; 104 } 105 106 tempDict = [baseDefinitions objectForKey: @"G"]; 107 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 108 guanidineRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'G']; 109 [baseDefinitions removeObjectForKey: @"G"]; 110 } 111 112 tempDict = [baseDefinitions objectForKey: @"N"]; 113 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 114 anyBaseRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'N']; 115 [baseDefinitions removeObjectForKey: @"N"]; 116 } 117 118 tempDict = [baseDefinitions objectForKey: @"R"]; 119 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 120 purineRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'R']; 121 [baseDefinitions removeObjectForKey: @"R"]; 122 } 123 124 tempDict = [baseDefinitions objectForKey: @"Y"]; 125 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 126 pyrimidineRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'Y']; 127 [baseDefinitions removeObjectForKey: @"Y"]; 128 } 129 130 tempDict = [baseDefinitions objectForKey: @"S"]; 131 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 132 strongRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'S']; 133 [baseDefinitions removeObjectForKey: @"S"]; 134 } 135 136 tempDict = [baseDefinitions objectForKey: @"W"]; 137 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 138 weakRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'W']; 139 [baseDefinitions removeObjectForKey: @"W"]; 140 } 141 142 tempDict = [baseDefinitions objectForKey: @"M"]; 143 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 144 aminoRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'M']; 145 [baseDefinitions removeObjectForKey: @"M"]; 146 } 147 148 tempDict = [baseDefinitions objectForKey: @"K"]; 149 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 150 ketoRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'K']; 151 [baseDefinitions removeObjectForKey: @"K"]; 152 } 153 154 tempDict = [baseDefinitions objectForKey: @"H"]; 155 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 156 HRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'H']; 157 [baseDefinitions removeObjectForKey: @"H"]; 158 } 159 160 tempDict = [baseDefinitions objectForKey: @"V"]; 161 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 162 VRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'V']; 163 [baseDefinitions removeObjectForKey: @"V"]; 164 } 165 166 tempDict = [baseDefinitions objectForKey: @"D"]; 167 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 168 DRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'D']; 169 [baseDefinitions removeObjectForKey: @"D"]; 170 } 171 172 tempDict = [baseDefinitions objectForKey: @"B"]; 173 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 174 BRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: 'B']; 175 [baseDefinitions removeObjectForKey: @"B"]; 176 } 177 178 tempDict = [baseDefinitions objectForKey: @"-"]; 179 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 180 gapRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: '-']; 181 [baseDefinitions removeObjectForKey: @"-"]; 182 } 183 184 tempDict = [baseDefinitions objectForKey: @"?"]; 185 if ( tempDict != nil && [tempDict isKindOfClass: [NSDictionary class]] ) { 186 undefinedRepresentation = [[BCNucleotideRNA alloc] initWithSymbolChar: '?']; 187 [baseDefinitions removeObjectForKey: @"?"]; 188 } 189 190 // hang on to the dictionary, in case there are custom bases 191 customBases = [baseDefinitions retain]; 192} 193 194 195 196+ (id) objectForSavedRepresentation: (NSString *)aSymbol { 197 return [BCNucleotideRNA symbolForChar: [aSymbol characterAtIndex: 0]]; 198} 199 200 201//////////////////////////////////////////////////////////////////////////// 202// THE FOLLOWING IS A METHOD FOR OBTAINING REFERENCES TO THE 203// INDIVIDUAL BASE REPRESENTATIONS WHEN GIVEN A SINGLE LETTER CODE 204// 205// THIS WILL NOT WORK WITH CUSTOM BASES, SINCE THEIR SYMBOLS ARE NOT KNOWN IN ADVACE 206//////////////////////////////////////////////////////////////////////////// 207+ (id) symbolForChar: (unsigned char)entry { 208 switch ( entry ) { 209 210 case 'A' : 211 case 'a' : { 212 return [BCNucleotideRNA adenosine]; 213 break; 214 } 215 216 217 case 'U' : 218 case 'u' : { 219 return [BCNucleotideRNA uridine]; 220 break; 221 } 222 223 case 'C' : 224 case 'c' : { 225 return [BCNucleotideRNA cytidine]; 226 break; 227 } 228 229 case 'G' : 230 case 'g' : { 231 return [BCNucleotideRNA guanidine]; 232 break; 233 } 234 235 case 'N' : 236 case 'n' : { 237 return [BCNucleotideRNA anyBase]; 238 break; 239 } 240 241 242 case 'R' : 243 case 'r' : { 244 return [BCNucleotideRNA purine]; 245 break; 246 } 247 248 249 case 'Y' : 250 case 'y' : { 251 return [BCNucleotideRNA pyrimidine]; 252 break; 253 } 254 255 256 case 'W' : 257 case 'w' : { 258 return [BCNucleotideRNA weak]; 259 break; 260 } 261 262 263 case 'S' : 264 case 's' : { 265 return [BCNucleotideRNA strong]; 266 break; 267 } 268 269 270 case 'M' : 271 case 'm' : { 272 return [BCNucleotideRNA amino]; 273 break; 274 } 275 276 277 case 'K' : 278 case 'k' : { 279 return [BCNucleotideRNA keto]; 280 break; 281 } 282 283 284 case 'H' : 285 case 'h' : { 286 return [BCNucleotideRNA H]; 287 break; 288 } 289 290 291 case 'V' : 292 case 'v' : { 293 return [BCNucleotideRNA V]; 294 break; 295 } 296 297 298 case 'D' : 299 case 'd' : { 300 return [BCNucleotideRNA D]; 301 break; 302 } 303 304 305 case 'B' : 306 case 'b' : { 307 return [BCNucleotideRNA B]; 308 break; 309 } 310 311 312 case '-' : { 313 return [BCNucleotideRNA gap]; 314 break; 315 } 316 317 318 default : 319 return [BCNucleotideRNA undefined]; 320 } 321} 322 323 324 325//////////////////////////////////////////////////////////////////////////// 326// THE FOLLOWING ARE METHODS FOR OBTAINING REFERENCES TO THE 327// INDIVIDUAL BASE REPRESENTATIONS 328//////////////////////////////////////////////////////////////////////////// 329 330+ (BCNucleotideRNA *) adenosine { 331 if ( adenosineRepresentation == nil ) 332 [BCNucleotideRNA initBases]; 333 return adenosineRepresentation; 334} 335 336 337+ (BCNucleotideRNA *) uridine { 338 if ( uridineRepresentation == nil ) 339 [BCNucleotideRNA initBases]; 340 return uridineRepresentation; 341} 342 343 344+ (BCNucleotideRNA *) cytidine { 345 if ( cytidineRepresentation == nil ) 346 [BCNucleotideRNA initBases]; 347 return cytidineRepresentation; 348} 349 350+ (BCNucleotideRNA *) guanidine { 351 if ( guanidineRepresentation == nil ) 352 [BCNucleotideRNA initBases]; 353 return guanidineRepresentation; 354} 355 356+ (BCNucleotideRNA *) anyBase { 357 if ( anyBaseRepresentation == nil ) 358 [BCNucleotideRNA initBases]; 359 return anyBaseRepresentation; 360} 361 362 363+ (BCNucleotideRNA *) purine { 364 if ( purineRepresentation == nil ) 365 [BCNucleotideRNA initBases]; 366 return purineRepresentation; 367} 368 369 370+ (BCNucleotideRNA *) pyrimidine { 371 if ( pyrimidineRepresentation == nil ) 372 [BCNucleotideRNA initBases]; 373 return pyrimidineRepresentation; 374} 375 376 377+ (BCNucleotideRNA *) strong { 378 if ( strongRepresentation == nil ) 379 [BCNucleotideRNA initBases]; 380 return strongRepresentation; 381} 382 383 384+ (BCNucleotideRNA *) weak { 385 if ( weakRepresentation == nil ) 386 [BCNucleotideRNA initBases]; 387 return weakRepresentation; 388} 389 390 391+ (BCNucleotideRNA *) amino { 392 if ( aminoRepresentation == nil ) 393 [BCNucleotideRNA initBases]; 394 return aminoRepresentation; 395} 396 397 398+ (BCNucleotideRNA *) keto { 399 if ( ketoRepresentation == nil ) 400 [BCNucleotideRNA initBases]; 401 return ketoRepresentation; 402} 403 404+ (BCNucleotideRNA *) H { 405 if ( HRepresentation == nil ) 406 [BCNucleotideRNA initBases]; 407 return HRepresentation; 408} 409 410+ (BCNucleotideRNA *) V { 411 if ( VRepresentation == nil ) 412 [BCNucleotideRNA initBases]; 413 return VRepresentation; 414} 415 416+ (BCNucleotideRNA *) D { 417 if ( DRepresentation == nil ) 418 [BCNucleotideRNA initBases]; 419 return DRepresentation; 420} 421 422+ (BCNucleotideRNA *) B { 423 if ( BRepresentation == nil ) 424 [BCNucleotideRNA initBases]; 425 return BRepresentation; 426} 427 428+ (BCNucleotideRNA *) gap { 429 if ( gapRepresentation == nil ) 430 [BCNucleotideRNA initBases]; 431 return gapRepresentation; 432} 433 434+ (BCNucleotideRNA *) undefined { 435 if ( undefinedRepresentation == nil ) 436 [BCNucleotideRNA initBases]; 437 return undefinedRepresentation; 438} 439 440 441 442+ (BCNucleotideRNA *) customBase: (NSString *)baseName { 443 if ( customBases == nil ) 444 [BCNucleotideRNA initBases]; 445 id aBase = [customBases objectForKey: baseName]; 446 if ( aBase == nil) 447 return nil; 448 449 if ( [aBase isKindOfClass: [BCNucleotideRNA class]] ) 450 return aBase; 451 452 453 if ( [aBase isKindOfClass: [NSDictionary class]] ) { 454 aBase = [[[BCNucleotideRNA alloc] initWithDictionary: aBase] autorelease]; 455 if ( aBase != nil ) { 456 [customBases setObject: aBase forKey: baseName]; 457 return aBase; 458 } 459 } 460 return nil; 461} 462 463 464 465 466//////////////////////////////////////////////////////////////////////////// 467// OBJECT METHODS 468//////////////////////////////////////////////////////////////////////////// 469#if 0 470#pragma mark � 471#pragma mark � OBJECT METHODS 472#pragma mark � 473#pragma mark �INITIALIZATION METHODS 474#endif 475 476 477- (id) initWithSymbolChar: (unsigned char)aSymbol { 478 self = [super initWithSymbolChar: aSymbol]; 479 if ( self == nil ) 480 return nil; 481 482 // we hang onto the dictionary in order to establish complement realtionships 483 // once all the bases are generated 484 symbolInfo = [[customBases objectForKey: symbolString] copy]; 485 486 // get basic information about this base 487 name = [symbolInfo objectForKey: @"Name"]; 488 if (name == nil) 489 return nil; 490 else 491 [name retain]; 492 493 494 [self setMonoisotopicMass: [[symbolInfo objectForKey:@"MonoisotopicMass"] floatValue]]; 495 [self setAverageMass: [[symbolInfo objectForKey:@"AverageMass"] floatValue]]; 496 497 return self; 498} 499 500#if 0 501#pragma mark �BASE INFORMATION METHODS 502#endif 503 504 505- (BOOL) isBase { 506 if ( self == [BCNucleotideRNA gap] || self == [BCNucleotideRNA undefined] ) 507 return NO; 508 return YES; 509} 510 511#if 0 512#pragma mark �BASE RELATIONSHIP METHODS 513#endif 514 515/////////////////////////////////////////////////////////// 516// BASE RELATIONSHIP METHODS 517/////////////////////////////////////////////////////////// 518 519 520- (BCNucleotideDNA *) DNABaseEquivalent { 521 if ( self != [BCNucleotideRNA uridine] ) 522 return [BCNucleotideDNA performSelector: NSSelectorFromString( name )]; 523 return [BCNucleotideDNA thymidine]; 524} 525 526 527@end 528