1 package FileIO::FingerprintsFPFileIO; 2 # 3 # $RCSfile: FingerprintsFPFileIO.pm,v $ 4 # $Date: 2015/02/28 20:48:43 $ 5 # $Revision: 1.19 $ 6 # 7 # Author: Manish Sud <msud@san.rr.com> 8 # 9 # Copyright (C) 2015 Manish Sud. All rights reserved. 10 # 11 # This file is part of MayaChemTools. 12 # 13 # MayaChemTools is free software; you can redistribute it and/or modify it under 14 # the terms of the GNU Lesser General Public License as published by the Free 15 # Software Foundation; either version 3 of the License, or (at your option) any 16 # later version. 17 # 18 # MayaChemTools is distributed in the hope that it will be useful, but without 19 # any warranty; without even the implied warranty of merchantability of fitness 20 # for a particular purpose. See the GNU Lesser General Public License for more 21 # details. 22 # 23 # You should have received a copy of the GNU Lesser General Public License 24 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or 25 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, 26 # Boston, MA, 02111-1307, USA. 27 # 28 29 use strict; 30 use Carp; 31 use Exporter; 32 use Scalar::Util (); 33 use TextUtil (); 34 use FileUtil (); 35 use TimeUtil (); 36 use Fingerprints::FingerprintsStringUtil (); 37 use PackageInfo (); 38 use FileIO::FileIO; 39 40 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 41 42 @ISA = qw(FileIO::FileIO Exporter); 43 @EXPORT = qw(); 44 @EXPORT_OK = qw(IsFingerprintsFPFile); 45 46 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); 47 48 # Setup class variables... 49 my($ClassName); 50 _InitializeClass(); 51 52 # Class constructor... 53 sub new { 54 my($Class, %NamesAndValues) = @_; 55 56 # Initialize object... 57 my $This = $Class->SUPER::new(); 58 bless $This, ref($Class) || $Class; 59 $This->_InitializeFingerprintsFPFileIO(); 60 61 $This->_InitializeFingerprintsFPFileIOProperties(%NamesAndValues); 62 63 return $This; 64 } 65 66 # Initialize object data... 67 # 68 sub _InitializeFingerprintsFPFileIO { 69 my($This) = @_; 70 71 # Fingerprints string data format during read/write... 72 # 73 # For file read: 74 # 75 # AutoDetect - automatically detect format of fingerprints string 76 # FingerprintsBitVectorString - Bit vector fingerprints string format 77 # FingerprintsVectorString - Vector fingerprints string format 78 # 79 # Default value: AutoDetect 80 # 81 # For file write: 82 # 83 # FingerprintsBitVectorString - Bit vector fingerprints string format 84 # FingerprintsVectorString - Vector fingerprints string format 85 # 86 # Default value: undef 87 # 88 $This->{FingerprintsStringMode} = undef; 89 90 # For file read: 91 # 92 # o Fingerprints bit-vector and vector object for current fingerprints string 93 # 94 # For file write: 95 # 96 # o Fingerprints bit-vector and vector object for current fingerprints string 97 # o Any supported fingerprints object: PathLengthFingerprints, ExtendedConnectivity, and so on. 98 # 99 $This->{FingerprintsObject} = undef; 100 101 # Fingeprints string for current line during read/write... 102 $This->{FingerprintsString} = undef; 103 104 # Partial fingeprints string corresponding to what's on the current line for current 105 # line during read/write... 106 $This->{PartialFingerprintsString} = undef; 107 108 # Required header data keys and values during read/write... 109 @{$This->{RequiredHeaderDataKeys}} = (); 110 %{$This->{RequiredHeaderDataKeysAndValues}} = (); 111 112 # First data line read/write... 113 $This->{FirstDataLineIO} = 1; 114 115 # Current fingerprints string data line number during read/write... 116 $This->{LineNum} = 0; 117 118 # FP line data during read/write... 119 $This->{DataLine} = undef; 120 121 # Initialize parameters for read... 122 $This->_InitializeFingerprintsFPFileIORead(); 123 124 # Initialize parameters for write... 125 $This->_InitializeFingerprintsFPFileIOWrite(); 126 127 return $This; 128 } 129 130 # Initialize class ... 131 sub _InitializeClass { 132 #Class name... 133 $ClassName = __PACKAGE__; 134 135 } 136 137 # Initialize object data for reading fingerprints FP file... 138 # 139 sub _InitializeFingerprintsFPFileIORead { 140 my($This) = @_; 141 142 # Header data keys and values... 143 # 144 @{$This->{HeaderDataKeys}} = (); 145 %{$This->{HeaderDataKeysAndValues}} = (); 146 %{$This->{CannonicalHeaderDataKeysAndValues}} = (); 147 148 # By default, the fingerprints data is assumed to be valid and no validation is 149 # performed before generating fingerprints objects... 150 # 151 $This->{ValidateData} = 1; 152 153 # Level of detail to print during validation of data for invalid or missing data... 154 $This->{DetailLevel} = 1; 155 156 # Number of missing and invalid fingerprints string data lines... 157 $This->{NumOfLinesWithMissingData} = 0; 158 $This->{NumOfLinesWithInvalidData} = 0; 159 160 # Compound ID for current fingerprints string... 161 $This->{CompoundID} = undef; 162 163 # Status of data in fingerprints FP file... 164 $This->{ValidFileData} = 0; 165 $This->{ValidRequiredHeaderDataKeys} = 0; 166 $This->{ValidFingerprintsStringMode} = 0; 167 168 return $This; 169 } 170 171 # Initialize object data for writing fingerprints FP file... 172 # 173 sub _InitializeFingerprintsFPFileIOWrite { 174 my($This) = @_; 175 176 # Fingerprints bit vector string format... 177 # 178 # Possible values: BinaryString or HexadecimalString [Default] 179 # 180 # Default BitStringFormat is set during first write using Fingerprints::FingerprintsStringUtil::GetDefaultBitStringFormat. 181 # 182 $This->{BitStringFormat} = undef; 183 184 # Bits order in fingerprints bit vector string... 185 # 186 # Ascending - First bit in each byte as the lowest bit [Default] 187 # Descending - First bit in each byte as the highest bit 188 # 189 # Default BitsOrder is set during first write using Fingerprints::FingerprintsStringUtil::GetDefaultBitsOrder. 190 # 191 $This->{BitsOrder} = undef; 192 193 # Fingerprints vector string format... 194 # 195 # Possible values: IDsAndValuesString, IDsAndValuesPairsString, ValuesAndIDsString, ValuesAndIDsPairsString, ValuesString 196 # 197 # Default VectorStringFormat is set during first write using Fingerprints::FingerprintsStringUtil::GetDefaultVectorStringFormat. 198 # For fingerprints vector object containing vector NumericalValues, it corresponds to IDsAndValuesString; otherwise, 199 # it's set to ValuesString. 200 # 201 $This->{VectorStringFormat} = undef; 202 203 # Overwriting existing file... 204 $This->{Overwrite} = 0; 205 206 return $This; 207 } 208 209 # Initialize object values... 210 sub _InitializeFingerprintsFPFileIOProperties { 211 my($This, %NamesAndValues) = @_; 212 213 # All other property names and values along with all Set/Get<PropertyName> methods 214 # are implemented on-demand using ObjectProperty class. 215 216 my($Name, $Value, $MethodName); 217 while (($Name, $Value) = each %NamesAndValues) { 218 $MethodName = "Set${Name}"; 219 $This->$MethodName($Value); 220 } 221 222 if (!exists $NamesAndValues{Name}) { 223 croak "Error: ${ClassName}->New: Object can't be instantiated without specifying file name..."; 224 } 225 226 # Make sure it's a fingerprints file... 227 $Name = $NamesAndValues{Name}; 228 if (!$This->IsFingerprintsFPFile($Name)) { 229 croak "Error: ${ClassName}->New: Object can't be instantiated: File, $Name, doesn't appear to be fingerprints format..."; 230 } 231 232 if ($This->GetMode() =~ /^Read$/i) { 233 $This->_InitializeFingerprintsFPFileIOReadProperties(%NamesAndValues); 234 } 235 elsif ($This->GetMode() =~ /^(Write|Append)$/i) { 236 $This->_InitializeFingerprintsFPFileIOWriteProperties(%NamesAndValues); 237 } 238 239 return $This; 240 } 241 242 # Initialize object properties for reading fingerprints FP file... 243 # 244 sub _InitializeFingerprintsFPFileIOReadProperties { 245 my($This, %NamesAndValues) = @_; 246 247 # Set default value for FingerprintsStringMode... 248 if (!$This->{FingerprintsStringMode}) { 249 $This->{FingerprintsStringMode} = 'AutoDetect'; 250 } 251 252 $This->_PrepareForReadingFingerprintsFPFileData(); 253 254 return $This; 255 } 256 257 # Initialize object properties for writing fingerprints FP file... 258 # 259 sub _InitializeFingerprintsFPFileIOWriteProperties { 260 my($This, %NamesAndValues) = @_; 261 262 # Check FingerprintsStringMode value... 263 if (!exists $NamesAndValues{FingerprintsStringMode}) { 264 croak "Error: ${ClassName}->New: Object can't be instantiated without specifying FingerprintsStringMode..."; 265 } 266 267 if ($This->{FingerprintsStringMode} !~ /^(FingerprintsBitVectorString|FingerprintsVectorString)$/i) { 268 croak "Error: ${ClassName}->New: Object can't be instantiated: FingerprintsStringMode value, $This->{FingerprintsStringMode}, is not valid; Supported values for write/append: FingerprintsBitVectorString or FingerprintsVectorString..."; 269 } 270 271 $This->_PrepareForWritingFingerprintsFPFileData(); 272 273 return $This; 274 } 275 276 # Set FingerprintsStringMode... 277 # 278 sub SetFingerprintsStringMode { 279 my($This, $Value) = @_; 280 281 # AutoDetect - automatically detect format of fingerprints string 282 # FingerprintsBitVectorString - Bit vector fingerprints string format 283 # FingerprintsVectorString - Vector fingerprints string format 284 285 if ($Value !~ /^(AutoDetect|FingerprintsBitVectorString|FingerprintsVectorString)$/i) { 286 croak "Error: ${ClassName}->SetFingerprintsStringMode: FingerprintsStringMode value, $Value, is not valid; Supported values: AutoDetect, FingerprintsBitVectorString or FingerprintsVectorString..."; 287 } 288 289 $This->{FingerprintsStringMode} = $Value; 290 291 return $This; 292 } 293 294 # Set DetailLevel... 295 # 296 sub SetDetailLevel { 297 my($This, $Value) = @_; 298 299 if (!TextUtil::IsPositiveInteger($Value)) { 300 croak "Error: ${ClassName}->SetDetailLevel: DetailLevel value, $Value, is not valid; Supported values: > 0..."; 301 } 302 303 $This->{DetailLevel} = $Value; 304 305 return $This; 306 } 307 308 # Set BitStringFormat... 309 # 310 sub SetBitStringFormat { 311 my($This, $Value) = @_; 312 313 if ($Value !~ /^(BinaryString|HexadecimalString)$/i) { 314 croak "Error: ${ClassName}->SetBitStringFormat: BitStringFormat value, $Value, is not valid; Supported values: BinaryString or HexadecimalString..."; 315 } 316 317 $This->{BitStringFormat} = $Value; 318 319 return $This; 320 } 321 322 # Set BitsOrder... 323 # 324 sub SetBitsOrder { 325 my($This, $Value) = @_; 326 327 # Ascending - First bit in each byte as the lowest bit 328 # Descending - First bit in each byte as the highest bit 329 # 330 if ($Value !~ /^(Ascending|Descending)$/i) { 331 croak "Error: ${ClassName}->SetBitsOrder: FingerprintsStringMode value, $Value, is not valid; Supported values: Ascending or Descending..."; 332 } 333 334 $This->{BitsOrder} = $Value; 335 336 return $This; 337 } 338 339 # Set compound ID... 340 # 341 sub SetCompoundID { 342 my($This, $Value) = @_; 343 344 if ($Value =~ / /) { 345 $Value =~ s/ //g; 346 carp "Warning: ${ClassName}->SetCompoundID: Spaces are not allowed in compound ID; They have been removed..."; 347 } 348 349 $This->{CompoundID} = $Value; 350 351 return $This; 352 } 353 354 # Set VectorStringFormat... 355 # 356 sub SetVectorStringFormat { 357 my($This, $Value) = @_; 358 359 # Possible values: IDsAndValuesString, IDsAndValuesPairsString, ValuesAndIDsString, ValuesAndIDsPairsString 360 361 if ($Value !~ /^(IDsAndValuesString|IDsAndValuesPairsString|ValuesAndIDsString|ValuesAndIDsPairsString|ValuesString)$/i) { 362 croak "Error: ${ClassName}->SetVectorStringFormat: FingerprintsStringMode value, $Value, is not valid; Supported values: IDsAndValuesString, IDsAndValuesPairsString, ValuesAndIDsString, ValuesAndIDsPairsString, or ValuesString..."; 363 } 364 365 $This->{VectorStringFormat} = $Value; 366 367 return $This; 368 } 369 370 # Get header data keys or number of header data keys in header data block... 371 # 372 sub GetHeaderDataKeys { 373 my($This) = @_; 374 375 return wantarray ? @{$This->{HeaderDataKeys}} : scalar @{$This->{HeaderDataKeys}}; 376 } 377 378 # Set header data keys... 379 # 380 sub SetHeaderDataKeys { 381 my($This, @Keys) = @_; 382 383 croak "Error: ${ClassName}->SetHeaderDataKeys: Can't set HeaderDataKeys: Not allowed..."; 384 385 return $This; 386 } 387 388 # Get header data keys and values hash... 389 # 390 sub GetHeaderDataKeysAndValues { 391 my($This) = @_; 392 393 return %{$This->{HeaderDataKeysAndValues}}; 394 } 395 396 # Set header data keys and values hash... 397 # 398 sub SetHeaderDataKeysAndValues { 399 my($This, %KeysAndValues) = @_; 400 401 croak "Error: ${ClassName}->SetHeaderDataKeysAndValues: Can't set HeaderDataKeysAndValues: Not allowed..."; 402 403 return $This; 404 } 405 406 # Get required header data keys or number of header data keys in header data block... 407 # 408 sub GetRequiredHeaderDataKeys { 409 my($This) = @_; 410 411 return wantarray ? @{$This->{RequiredHeaderDataKeys}} : scalar @{$This->{RequiredHeaderDataKeys}}; 412 } 413 414 # Set required header data keys... 415 # 416 sub SetRequiredHeaderDataKeys { 417 my($This, @Keys) = @_; 418 419 croak "Error: ${ClassName}->SetRequiredHeaderDataKeys: Can't set RequiredHeaderDataKeys: Not allowed..."; 420 421 return $This; 422 } 423 424 # Get required header data keys and values hash... 425 # 426 sub GetRequiredHeaderDataKeysAndValues { 427 my($This) = @_; 428 429 return %{$This->{RequiredHeaderDataKeysAndValues}}; 430 } 431 432 # Set required header data keys and values hash... 433 # 434 sub SetRequiredHeaderDataKeysAndValues { 435 my($This, %KeysAndValues) = @_; 436 437 croak "Error: ${ClassName}->SetRequiredHeaderDataKeysAndValues: Can't set RequiredHeaderDataKeysAndValues: Not allowed..."; 438 439 return $This; 440 } 441 442 # Get fingerprints object for current data line... 443 # 444 sub GetFingerprints { 445 my($This) = @_; 446 447 return $This->{FingerprintsObject}; 448 } 449 450 # Set fingerprints object for current data line... 451 # 452 sub SetFingerprints { 453 my($This, $FingerprintsObject) = @_; 454 455 $This->{FingerprintsObject} = $FingerprintsObject; 456 457 return $This; 458 } 459 460 # Get fingerprints string for current data line... 461 # 462 sub GetFingerprintsString { 463 my($This) = @_; 464 465 return $This->{FingerprintsString} ? $This->{FingerprintsString} : 'None'; 466 } 467 468 # Set fingerprints string for current data line... 469 # 470 sub SetFingerprintsString { 471 my($This, $FingerprintsString) = @_; 472 473 $This->{FingerprintsString} = $FingerprintsString; 474 475 return $This; 476 } 477 478 # Get partial fingerprints string for current data line... 479 # 480 sub GetPartialFingerprintsString { 481 my($This) = @_; 482 483 return $This->{PartialFingerprintsString} ? $This->{PartialFingerprintsString} : 'None'; 484 } 485 486 # Set partial fingerprints string for current data line... 487 # 488 sub SetPartialFingerprintsString { 489 my($This, $PartialFingerprintsString) = @_; 490 491 $This->{PartialFingerprintsString} = $PartialFingerprintsString; 492 493 return $This; 494 } 495 496 # Does fingerprints FP file contain valid data? 497 # 498 sub IsFingerprintsFileDataValid { 499 my($This) = @_; 500 501 return $This->{ValidFileData} ? 1 : 0; 502 } 503 504 # Does current data line contains valid fingerprints object data? 505 # 506 sub IsFingerprintsDataValid { 507 my($This) = @_; 508 509 return defined $This->{FingerprintsObject} ? 1 : 0; 510 } 511 512 # Check presence of a header data key... 513 # 514 sub IsHeaderDataKeyPresent { 515 my($This, $Key) = @_; 516 my($CannonicalKey); 517 518 $CannonicalKey = lc $Key; 519 520 return exists $This->{CannonicalHeaderDataKeysAndValues}{$CannonicalKey} ? 1 : 0; 521 } 522 523 # Get value of header data key... 524 # 525 sub GetHeaderDataKeyValue { 526 my($This, $Key) = @_; 527 my($CannonicalKey); 528 529 $CannonicalKey = lc $Key; 530 531 return exists $This->{CannonicalHeaderDataKeysAndValues}{$CannonicalKey} ? $This->{CannonicalHeaderDataKeysAndValues}{$CannonicalKey} : undef; 532 } 533 534 # 535 # Read next available fingerprints line, process it and generate appropriate fingerprints 536 # objects... 537 # 538 sub Read { 539 my($This) = @_; 540 541 # Read data line... 542 if (!$This->_ReadDataLine()) { 543 return undef; 544 } 545 546 # No need to process invalid FP file with invalid data... 547 if (!$This->{ValidFileData}) { 548 if ($This->{ValidateData}) { 549 $This->{NumOfLinesWithMissingData} += 1; 550 } 551 return $This; 552 } 553 554 # Perform data validation... 555 if ($This->{ValidateData}) { 556 if (!$This->_ValidateReadDataLine()) { 557 return $This; 558 } 559 } 560 561 # Check again to handle problematic data for non-validated data lines... 562 if (!$This->{FingerprintsString}) { 563 return $This; 564 } 565 566 # Generate fingeprints object... 567 $This->_GenerateFingerprintsObject(); 568 569 # Setup fingerprints compound ID for fingerprints string... 570 $This->_GenerateCompoundID(); 571 572 return $This; 573 } 574 575 # Read next available fingerprints line, process it and generate appropriate fingerprints 576 # objects... 577 # 578 sub Next { 579 my($This) = @_; 580 581 return $This->Read(); 582 } 583 584 # Read fingerprints data line line... 585 # 586 sub _ReadDataLine { 587 my($This) = @_; 588 589 # Initialize data for current line... 590 $This->_InitializeReadDataLine(); 591 592 if ($This->{FirstDataLineIO}) { 593 # Get first data line... 594 $This->_ProcessFirstDataLineRead(); 595 } 596 else { 597 # Get next data line... 598 $This->{LineNum} += 1; 599 $This->{DataLine} = TextUtil::GetTextLine($This->{FileHandle}); 600 } 601 602 # Is it end of file? 603 if (!$This->{DataLine}) { 604 return 0; 605 } 606 607 # Process data line to retrieve compound ID and fingerprints string information... 608 $This->_ProcessDataLineRead(); 609 610 return 1; 611 } 612 613 # Process data line to retrieve compound ID and fingerprints string information... 614 # 615 sub _ProcessDataLineRead { 616 my($This) = @_; 617 my($CompoundID, $PartialFingerprintsString); 618 619 ($CompoundID, $PartialFingerprintsString) = $This->{DataLine} =~ /^(.*?)[ ]+(.*?)$/; 620 621 if (!(defined($CompoundID) && defined($PartialFingerprintsString))) { 622 return $This; 623 } 624 625 $This->{CompoundID} = $CompoundID; 626 $This->{PartialFingerprintsString} = $PartialFingerprintsString; 627 628 # Set up fingerprints string... 629 $This->_GenerateFingerprintsStringFromPartialFingerprintsString(); 630 631 return $This; 632 } 633 634 # Initialize data line for reading... 635 # 636 sub _InitializeReadDataLine { 637 my($This) = @_; 638 639 $This->{CompoundID} = undef; 640 $This->{DataLine} = undef; 641 642 $This->{FingerprintsObject} = undef; 643 644 $This->{FingerprintsString} = undef; 645 $This->{PartialFingerprintsString} = undef; 646 647 return $This; 648 } 649 650 # Validate fingerprints string data line... 651 # 652 sub _ValidateReadDataLine { 653 my($This) = @_; 654 655 # Check for missing data... 656 if (!($This->{CompoundID} && $This->{PartialFingerprintsString})) { 657 # Missing data... 658 $This->{NumOfLinesWithMissingData} += 1; 659 if ($This->{DetailLevel} >= 3) { 660 carp "Warning: ${ClassName}->_ValidateReadDataLine: Data line number $This->{LineNum} contains no fingerprints data: $This->{DataLine}..."; 661 } 662 elsif ($This->{DetailLevel} >= 2) { 663 carp "Warning: ${ClassName}->_ValidateReadDataLine: Data line number $This->{LineNum} contains no fingerprints data..."; 664 } 665 return 0; 666 } 667 668 # Check for invalid data... 669 my($InvalidFingerprintsData); 670 671 $InvalidFingerprintsData = 0; 672 if ($This->{FingerprintsString}) { 673 $InvalidFingerprintsData = Fingerprints::FingerprintsStringUtil::AreFingerprintsStringValuesValid($This->{FingerprintsString}) ? 0 : 1; 674 } 675 else { 676 $InvalidFingerprintsData = 1; 677 } 678 679 if ($InvalidFingerprintsData) { 680 $This->{NumOfLinesWithInvalidData} += 1; 681 if ($This->{DetailLevel} >= 3) { 682 carp "Warning: ${ClassName}->_ValidateReadDataLine: Data line number $This->{LineNum} contains invalid fingerprints data: $This->{DataLine}..."; 683 } 684 elsif ($This->{DetailLevel} >= 2) { 685 carp "Warning: ${ClassName}->_ValidateReadDataLine: Data line number $This->{LineNum} contains invalid fingerprints data..."; 686 } 687 return 0; 688 } 689 690 return 1; 691 } 692 693 # Setup fingerprints compound ID for fingerprints string... 694 sub _GenerateCompoundID { 695 my($This) = @_; 696 697 # Set fingerprints ID... 698 if ($This->{FingerprintsObject}) { 699 $This->{FingerprintsObject}->SetID($This->{CompoundID}); 700 } 701 702 return $This; 703 } 704 705 # Process first read... 706 # 707 sub _ProcessFirstDataLineRead { 708 my($This) = @_; 709 my($Line); 710 711 $This->{FirstDataLineIO} = 0; 712 713 # Skip over header data lines and collect first data line... 714 715 LINE: while ($Line = TextUtil::GetTextLine($This->{FileHandle})) { 716 $This->{LineNum} += 1; 717 718 # Is it a header data line? 719 if ($Line =~ /^#/) { 720 next LINE; 721 } 722 $This->{DataLine} = $Line; 723 last LINE; 724 } 725 726 return $This; 727 } 728 729 # Get ready for reading fingerprints FP file... 730 # 731 sub _PrepareForReadingFingerprintsFPFileData { 732 my($This) = @_; 733 734 # Retrieve FP file data headers information.... 735 $This->_RetrieveFPFileDataHeaders(); 736 737 # Validate header data keys and values information... 738 $This->_ValidateReadHeaderDataKeysAndValues(); 739 740 # Validate fingeprints string mode information... 741 if ($This->{ValidRequiredHeaderDataKeys}) { 742 $This->_ValidateReadFingerprintsStringMode(); 743 } 744 745 # Set status of FP file data... 746 $This->{ValidFileData} = ($This->{ValidRequiredHeaderDataKeys} && $This->{ValidFingerprintsStringMode}) ? 1 : 0; 747 748 return $This; 749 } 750 751 # Retrieve information about fingerprints date header in FP file... 752 # 753 sub _RetrieveFPFileDataHeaders { 754 my($This) = @_; 755 my($FPFile, $Line, $Index, $KeyValuePair, $Key, $Value, $KeyValueDelimiter, $KeyValuePairDelimiter, @LineKeyValuePairs); 756 757 $FPFile = $This->{Name}; 758 759 if (!(-e $FPFile)) { 760 croak "Error: ${ClassName}->_RetrieveFPFileDataHeaders: File, $FPFile, doesn't exist..."; 761 } 762 763 if (!open FPFILE, "$FPFile") { 764 croak "Error: ${ClassName}->_RetrieveFPFileDataHeaders: Couldn't open input FP file $FPFile: $! ..."; 765 } 766 767 # Process header key/value pair data... 768 # 769 $KeyValueDelimiter = '='; 770 $KeyValuePairDelimiter = ';'; 771 772 @{$This->{HeaderDataKeys}} = (); 773 %{$This->{HeaderDataKeysAndValues}} = (); 774 %{$This->{CannonicalHeaderDataKeysAndValues}} = (); 775 776 LINE: while ($Line = TextUtil::GetTextLine(\*FPFILE)) { 777 # Is it a key/value pairs line? 778 if ($Line !~ /^#/) { 779 last LINE; 780 } 781 782 # Take out starting hash mark before processing key/value pairs... 783 $Line =~ s/^#//; 784 if (TextUtil::IsEmpty($Line)) { 785 next LINE; 786 } 787 788 @LineKeyValuePairs = (); 789 790 for $KeyValuePair (split "$KeyValuePairDelimiter", $Line) { 791 ($Key, $Value) = split "$KeyValueDelimiter", $KeyValuePair; 792 793 $Key = defined($Key) ? TextUtil::RemoveLeadingAndTrailingWhiteSpaces($Key) : ''; 794 $Value = defined($Value) ? TextUtil::RemoveLeadingAndTrailingWhiteSpaces($Value) : ''; 795 796 if (TextUtil::IsEmpty($Key) || TextUtil::IsEmpty($Value)) { 797 carp "Warning: ${ClassName}->_RetrieveFPFileDataHeaders: Data header line containing \"Key = Value\" pairs is not valid: It must contain even number of \"Key = Value\" pairs with valid values. Ignoring data header line: \"$Line\"..."; 798 next LINE; 799 } 800 push @{$This->{HeaderDataKeys}}, $Key; 801 push @LineKeyValuePairs, ($Key, $Value); 802 } 803 804 for ($Index = 0; $Index < $#LineKeyValuePairs; $Index += 2) { 805 $Key = $LineKeyValuePairs[$Index]; $Value = $LineKeyValuePairs[$Index + 1]; 806 807 $This->{HeaderDataKeysAndValues}{$Key} = $Value; 808 $This->{CannonicalHeaderDataKeysAndValues}{lc($Key)} = $Value; 809 } 810 } 811 close FPFILE; 812 813 return $This; 814 } 815 816 # Validate header data and keys... 817 # 818 sub _ValidateReadHeaderDataKeysAndValues { 819 my($This) = @_; 820 my($FingerprintsStringType, $Key, $Value, @RequiredHeaderDataKeys); 821 822 $This->{ValidRequiredHeaderDataKeys} = 0; 823 @{$This->{RequiredHeaderDataKeys}} = (); 824 825 # Is FingerprintsStringType key is present? 826 if (!$This->IsHeaderDataKeyPresent('FingerprintsStringType')) { 827 carp "carp: ${ClassName}->_ValidateReadHeaderDataKeysAndValues: FingerprintsStringType data header key is missing in fingerprints file..."; 828 return 0; 829 } 830 $FingerprintsStringType = $This->GetHeaderDataKeyValue('FingerprintsStringType'); 831 832 # Are all required data header keys present? 833 # 834 @RequiredHeaderDataKeys = (); 835 836 if ($FingerprintsStringType =~ /^(FingerprintsBitVector|FingerprintsVector)$/i) { 837 push @RequiredHeaderDataKeys, $This->_GetRequiredHeaderDataKeys($FingerprintsStringType); 838 } 839 else { 840 carp "Warning: ${ClassName}->_ValidateReadHeaderDataKeysAndValues: FingerprintsStringType data header key value, $FingerprintsStringType, is not valid. SUpported values: FingerprintsBitVector or FingerprintsVector..."; 841 return 0; 842 } 843 844 for $Key (@RequiredHeaderDataKeys) { 845 if (!$This->IsHeaderDataKeyPresent($Key)) { 846 croak "Error: ${ClassName}->_ValidateReadHeaderDataKeysAndValues: Requires data header key, $Key, is missing in fingerprints file..."; 847 } 848 } 849 850 push @{$This->{RequiredHeaderDataKeys}}, @RequiredHeaderDataKeys; 851 852 # Are all required data header key values valid? 853 # 854 if (!$This->_ValidateRequiredHeaderDataKeyValues()) { 855 return 0; 856 } 857 858 # Process required header key values... 859 # 860 $This->_ProcessRequiredHeaderDataKeyValues(); 861 862 $This->{ValidRequiredHeaderDataKeys} = 1; 863 864 return 1; 865 } 866 867 # Validate data header key values.... 868 # 869 sub _ValidateRequiredHeaderDataKeyValues { 870 my($This) = @_; 871 my($Key, $Value); 872 873 for $Key (@{$This->{RequiredHeaderDataKeys}}) { 874 $Value = $This->GetHeaderDataKeyValue($Key); 875 KEY: { 876 if ($Key =~ /^FingerprintsStringType$/i) { 877 if ($Value !~ /^(FingerprintsBitVector|FingerprintsVector)$/i) { 878 carp "Warning: ${ClassName}->_ValidateRequiredHeaderDataKeyValues: Required $Key data header key value, $Value, is not valid. Supported values: FingerprintsBitVector or FingerprintsVector..."; 879 return 0; 880 } 881 last KEY; 882 } 883 if ($Key =~ /^Size$/i) { 884 if (!TextUtil::IsPositiveInteger($Value)) { 885 carp "Warning: ${ClassName}->_ValidateRequiredHeaderDataKeyValues: Required $Key data header key value, $Value, is not valid. Supported values: > 0..."; 886 return 0; 887 } 888 last KEY; 889 } 890 if ($Key =~ /^BitStringFormat$/i) { 891 if ($Value !~ /^(BinaryString|HexadecimalString)$/i) { 892 carp "Warning: ${ClassName}->_ValidateRequiredHeaderDataKeyValues: Required $Key data header key value, $Value, is not valid. Supported values: BinaryString or HexadecimalString ..."; 893 return 0; 894 } 895 last KEY; 896 } 897 if ($Key =~ /^BitsOrder$/i) { 898 if ($Value !~ /^(Ascending|Descending)$/i) { 899 carp "Warning: ${ClassName}->_ValidateRequiredHeaderDataKeyValues: Required $Key data header key value, $Value, is not valid. Supported values: Ascending or Descending..."; 900 return 0; 901 } 902 last KEY; 903 } 904 if ($Key =~ /^VectorStringFormat$/i) { 905 if ($Value !~ /^(IDsAndValuesString|IDsAndValuesPairsString|ValuesAndIDsString|ValuesAndIDsPairsString|ValuesString)$/i) { 906 carp "Warning: ${ClassName}->_ValidateRequiredHeaderDataKeyValues: Required $Key data header key value, $Value, is not valid. Supported values: IDsAndValuesString, IDsAndValuesPairsString, ValuesAndIDsString, ValuesAndIDsPairsString, or ValuesString ..."; 907 return 0; 908 } 909 last KEY; 910 } 911 if ($Key =~ /^VectorValuesType$/i) { 912 if ($Value !~ /^(OrderedNumericalValues|NumericalValues|AlphaNumericalValues)$/i) { 913 carp "Warning: ${ClassName}->_ValidateRequiredHeaderDataKeyValues: Required $Key data header key value, $Value, is not valid. Supported values: OrderedNumericalValues, NumericalValues or AlphaNumericalValues..."; 914 return 0; 915 } 916 last KEY; 917 } 918 if ($Key =~ /^Description$/i) { 919 if (TextUtil::IsEmpty($Value)) { 920 carp "Warning: ${ClassName}->_ValidateRequiredHeaderDataKeyValues: Required $Key data header key value is not valid. Supported value: A no-empty text string..."; 921 return 0; 922 } 923 last KEY; 924 } 925 carp "Warning: ${ClassName}->_ValidateRequiredHeaderDataKeyValues: Required $Key data header key is not not supported..."; 926 return 0; 927 } 928 } 929 930 return 1; 931 } 932 933 # Process required header key valeues for access during complete fingerprints 934 # string generation from a partial fingerprints string specified on fingerprints 935 # line... 936 # 937 sub _ProcessRequiredHeaderDataKeyValues { 938 my($This) = @_; 939 my($Key, $Value, @Keys); 940 941 %{$This->{RequiredHeaderDataKeysAndValues}} = (); 942 943 for $Key (@{$This->{RequiredHeaderDataKeys}}) { 944 $Value = $This->GetHeaderDataKeyValue($Key); 945 $This->{RequiredHeaderDataKeysAndValues}{$Key} = $Value; 946 } 947 948 # Setup prefixes for generating fingerprints strings... 949 $This->{FingerprintsBitVectorStringPrefix} = ''; 950 $This->{FingerprintsVectorStringPrefix1} = ''; 951 $This->{FingerprintsVectorStringPrefix2} = ''; 952 953 if ($This->{RequiredHeaderDataKeysAndValues}{FingerprintsStringType} =~ /^FingerprintsBitVector$/i) { 954 @Keys = qw(FingerprintsStringType Description Size BitStringFormat BitsOrder); 955 $This->{FingerprintsBitVectorStringPrefix} = $This->_GenerateFingerprintsPrefixUsingKeys(@Keys); 956 } 957 elsif ($This->{RequiredHeaderDataKeysAndValues}{FingerprintsStringType} =~ /^FingerprintsVector$/i) { 958 @Keys = qw(FingerprintsStringType Description); 959 $This->{FingerprintsVectorStringPrefix1} = $This->_GenerateFingerprintsPrefixUsingKeys(@Keys); 960 961 @Keys = qw(VectorValuesType VectorStringFormat); 962 $This->{FingerprintsVectorStringPrefix2} = $This->_GenerateFingerprintsPrefixUsingKeys(@Keys); 963 } 964 965 return $This; 966 } 967 968 # Generate fingerprints prefix using header keys data... 969 # 970 sub _GenerateFingerprintsPrefixUsingKeys { 971 my($This, @Keys) = @_; 972 my($Delimiter, $Key, @Values); 973 974 $Delimiter = Fingerprints::FingerprintsStringUtil::GetFingeprintsStringDelimiter(); 975 976 @Values = (); 977 for $Key (@Keys) { 978 push @Values, $This->{RequiredHeaderDataKeysAndValues}{$Key}; 979 } 980 981 return join($Delimiter, @Values) 982 } 983 984 # Get required header data keys... 985 # 986 sub _GetRequiredHeaderDataKeys { 987 my($This, $FingerprintsStringType) = @_; 988 my(@RequiredKeys); 989 990 @RequiredKeys = (); 991 992 if ($FingerprintsStringType =~ /FingerprintsBitVector$/i) { 993 push @RequiredKeys, qw(FingerprintsStringType Description Size BitStringFormat BitsOrder); 994 } 995 elsif ($FingerprintsStringType =~ /^FingerprintsVector/i) { 996 push @RequiredKeys, qw(FingerprintsStringType Description VectorStringFormat VectorValuesType); 997 } 998 else { 999 carp "Warning: ${ClassName}->GetRequiredHeaderDataKeys: FingerprintsStringType value, $FingerprintsStringType, is not valid. Supported values: FingerprintsBitVector or FingerprintsVector..."; 1000 } 1001 1002 return @RequiredKeys; 1003 } 1004 1005 # Validate fingerprints string mode information... 1006 # 1007 sub _ValidateReadFingerprintsStringMode { 1008 my($This) = @_; 1009 my($FingerprintsStringType, $FingerprintsStringDescription, $FingerprintsBitVectorStringMode, $FingerprintsVectorStringMode, $FirstFingerprintsStringType, $FirstFingerprintsStringDescription); 1010 1011 $This->{ValidFingerprintsStringMode} = 0; 1012 $This->{FingerprintsBitVectorStringMode} = 0; 1013 $This->{FingerprintsVectorStringMode} = 0; 1014 1015 $This->{FirstFingerprintsStringType} = ''; 1016 $This->{FirstFingerprintsStringDescription} = ''; 1017 1018 $FingerprintsBitVectorStringMode = 0; 1019 $FingerprintsVectorStringMode = 0; 1020 1021 $FirstFingerprintsStringType = ''; 1022 $FirstFingerprintsStringDescription = ''; 1023 1024 $FingerprintsStringType = $This->GetHeaderDataKeyValue('FingerprintsStringType'); 1025 $FingerprintsStringDescription = $This->GetHeaderDataKeyValue('Description'); 1026 1027 if ($This->{FingerprintsStringMode} =~ /^FingerprintsBitVectorString$/i) { 1028 if ($FingerprintsStringType !~ /^FingerprintsBitVector$/i) { 1029 carp "Warning: ${ClassName}->_ValidateReadFingerprintsStringMode: Fingerprints string data type, $FingerprintsStringType, doesn't correspond to, FingerprintsBitVectorString, specified using \"FingerprintsStringMode\"..."; 1030 return 0; 1031 } 1032 $FingerprintsBitVectorStringMode = 1; 1033 $FirstFingerprintsStringType = 'FingerprintsBitVector'; 1034 $FirstFingerprintsStringDescription = $FingerprintsStringDescription; 1035 } 1036 elsif ($This->{FingerprintsStringMode} =~ /^FingerprintsVectorString$/i) { 1037 if ($FingerprintsStringType !~ /^FingerprintsVector$/i) { 1038 carp "Warning: ${ClassName}->_ValidateReadFingerprintsStringMode: Fingerprints string data type, $FingerprintsStringType, doesn't correspond to, FingerprintsVectorString, specified using \"FingerprintsStringMode\"..."; 1039 return 0; 1040 } 1041 $FingerprintsVectorStringMode = 1; 1042 $FirstFingerprintsStringType = 'FingerprintsVector'; 1043 $FirstFingerprintsStringDescription = $FingerprintsStringDescription; 1044 } 1045 else { 1046 # AutoDetect mode... 1047 if ($FingerprintsStringType =~ /^FingerprintsBitVector$/i) { 1048 $FingerprintsBitVectorStringMode = 1; 1049 } 1050 elsif ($FingerprintsStringType =~ /^FingerprintsVector$/i) { 1051 $FingerprintsVectorStringMode = 1; 1052 } 1053 else { 1054 carp "Warning: ${ClassName}->_ValidateReadFingerprintsStringMode: Fingerprints string data type, $FingerprintsStringType, identified during, AutoDetect, value of \"FingerprintsStringMode\" is not valid; Supported fingerprints types: FingerprintBitVector or FingerprintsVector..."; 1055 return 0; 1056 } 1057 $FirstFingerprintsStringType = $FingerprintsStringType; 1058 $FirstFingerprintsStringDescription = $FingerprintsStringDescription; 1059 } 1060 1061 $This->{ValidFingerprintsStringMode} = 1; 1062 1063 $This->{FingerprintsBitVectorStringMode} = $FingerprintsBitVectorStringMode; 1064 $This->{FingerprintsVectorStringMode} = $FingerprintsVectorStringMode; 1065 1066 $This->{FirstFingerprintsStringType} = $FirstFingerprintsStringType; 1067 $This->{FirstFingerprintsStringDescription} = $FirstFingerprintsStringDescription; 1068 1069 return 1; 1070 } 1071 1072 # Write fingerprints string generated from specified fingerprints - fingerprints-bit vector or 1073 # fingerprints vector - object and other data to FP file... 1074 # 1075 sub WriteFingerprints { 1076 my($This, $FingerprintsObject, $CompoundID) = @_; 1077 1078 # Initialize data for current line... 1079 $This->_InitializeWriteDataLine(); 1080 1081 # Set fingerprints object and compound ID... 1082 $This->{FingerprintsObject} = $FingerprintsObject; 1083 $This->SetCompoundID($CompoundID); 1084 1085 # Generate fingerprints string... 1086 $This->_GenerateFingerprintsString(); 1087 1088 # Generate partial fingerprints string... 1089 $This->_GeneratePartialFingerprintsStringFromFingerprintsString(); 1090 1091 # Write data line.. 1092 $This->_WriteDataLine(); 1093 1094 return $This; 1095 } 1096 1097 # Write fingerprints string and other data to FP file... 1098 # 1099 # Notes: 1100 # o FingerprintsStringMode, BitStringFormat, BitsOrder, VectorStringFormat values 1101 # are ignored during writing of fingerprints and it's written to the file as it is. 1102 # o FingerprintsString is a regular fingerprints string as oppose to a partial fingerprints 1103 # string. 1104 # 1105 sub WriteFingerprintsString { 1106 my($This, $FingerprintsString, $CompoundID) = @_; 1107 1108 # Initialize data for current line... 1109 $This->_InitializeWriteDataLine(); 1110 1111 # Set fingerprints string and compound ID... 1112 $This->{FingerprintsString} = $FingerprintsString; 1113 $This->SetCompoundID($CompoundID); 1114 1115 # Generate fingerprints object... 1116 $This->_GenerateFingerprintsObject(); 1117 1118 # Generate partial fingerprints string... 1119 $This->_GeneratePartialFingerprintsStringFromFingerprintsString(); 1120 1121 # Write data line.. 1122 $This->_WriteDataLine(); 1123 1124 return $This; 1125 } 1126 1127 # Initialize data line for reading... 1128 # 1129 sub _InitializeWriteDataLine { 1130 my($This) = @_; 1131 1132 $This->{DataLine} = undef; 1133 $This->{CompoundID} = undef; 1134 1135 $This->{FingerprintsObject} = undef; 1136 1137 $This->{FingerprintsString} = undef; 1138 $This->{PartialFingerprintsString} = undef; 1139 1140 return $This; 1141 } 1142 1143 # Write fingerprints data line line... 1144 # 1145 sub _WriteDataLine { 1146 my($This) = @_; 1147 my($FileHandle, $Line); 1148 1149 if ($This->{FirstDataLineIO}) { 1150 $This->_ProcessFirstDataLineWrite(); 1151 } 1152 1153 # Write data compound ID along with partial fingerprints string... 1154 $Line = $This->{CompoundID} . ' ' . $This->{PartialFingerprintsString}; 1155 1156 $This->{LineNum} += 1; 1157 $FileHandle = $This->{FileHandle}; 1158 print $FileHandle "$Line\n"; 1159 1160 $This->{DataLine} = $Line; 1161 1162 return $This; 1163 } 1164 1165 # Process first write... 1166 # 1167 sub _ProcessFirstDataLineWrite { 1168 my($This) = @_; 1169 my($Line, $FileHandle); 1170 1171 $This->{FirstDataLineIO} = 0; 1172 1173 if ($This->GetMode() =~ /^Write$/i) { 1174 # Skip it for append mode... 1175 $This->_WritePackageAndTimeStampHeaderKeys(); 1176 $This->_WriteRequiredHeaderDataKeys(); 1177 } 1178 1179 return $This; 1180 } 1181 1182 # Write out package and time stamp information... 1183 # 1184 sub _WritePackageAndTimeStampHeaderKeys { 1185 my($This) = @_; 1186 my($FileHandle, $Key, $Value); 1187 1188 $FileHandle = $This->{FileHandle}; 1189 1190 # Package information... 1191 $This->{LineNum} += 1; 1192 $Key = "Package"; $Value = PackageInfo::GetPackageName() . " " . PackageInfo::GetVersionNumber(); 1193 print $FileHandle "# $Key = $Value\n"; 1194 1195 $This->{LineNum} += 1; 1196 $Key = "Release Date"; $Value = PackageInfo::GetReleaseDate(); 1197 print $FileHandle "# $Key = $Value\n"; 1198 1199 # Timestamp information... 1200 $This->{LineNum} += 1; 1201 print $FileHandle "#\n"; 1202 1203 $This->{LineNum} += 1; 1204 $Key = "TimeStamp"; $Value = TimeUtil::FPFileTimeStamp(); 1205 print $FileHandle "# $Key = $Value\n"; 1206 1207 return $This; 1208 } 1209 1210 # Write out required header data keys... 1211 # 1212 sub _WriteRequiredHeaderDataKeys { 1213 my($This) = @_; 1214 my($FileHandle, $Key, $Value); 1215 1216 $FileHandle = $This->{FileHandle}; 1217 1218 $This->_GenerateWriteRequiredHeaderDataKeys(); 1219 1220 $This->{LineNum} += 1; 1221 print $FileHandle "#\n"; 1222 1223 for $Key (@{$This->{RequiredHeaderDataKeys}}) { 1224 $Value = $This->{RequiredHeaderDataKeysAndValues}{$Key}; 1225 1226 $This->{LineNum} += 1; 1227 print $FileHandle "# $Key = $Value\n"; 1228 1229 if ($Key =~ /^FingerprintsStringType$/i) { 1230 $This->{LineNum} += 1; 1231 print $FileHandle "#\n"; 1232 } 1233 } 1234 1235 $This->{LineNum} += 1; 1236 print $FileHandle "#\n"; 1237 1238 return $This; 1239 } 1240 1241 sub _GenerateWriteRequiredHeaderDataKeys { 1242 my($This) = @_; 1243 1244 if ($This->{FingerprintsBitVectorStringMode} && ($This->{FingerprintsString} =~ /^FingerprintsBitVector/i)) { 1245 $This->_GenerateWriteRequiredHeaderDataKeysForBitVectorString(); 1246 } 1247 elsif ($This->{FingerprintsVectorStringMode} && ($This->{FingerprintsString} =~ /^FingerprintsVector/i)) { 1248 $This->_GenerateWriteRequiredHeaderDataKeysForVectorString(); 1249 } 1250 else { 1251 croak "Error: ${ClassName}->_GenerateWriteRequiredHeaderDataKeys: Required header data keys can't be generated: FingerprintsStringMode value, $This->{FingerprintsStringMode}, doesn't correspond to type of first FingerprintsString: $This->{FingerprintsString}..."; 1252 } 1253 1254 return $This; 1255 } 1256 1257 # Generate required data header keys and values for writing fingerprints bit vector string... 1258 # 1259 sub _GenerateWriteRequiredHeaderDataKeysForBitVectorString { 1260 my($This) = @_; 1261 my($Key, $VectorType, $Description, $Size, $BitStringFormat, $BitsOrder); 1262 1263 @{$This->{RequiredHeaderDataKeys}} = (); 1264 push @{$This->{RequiredHeaderDataKeys}}, $This->_GetRequiredHeaderDataKeys('FingerprintsBitVector'); 1265 1266 ($VectorType, $Description, $Size, $BitStringFormat, $BitsOrder) = Fingerprints::FingerprintsStringUtil::GetFingerprintsStringValues($This->{FingerprintsString}); 1267 1268 %{$This->{RequiredHeaderDataKeysAndValues}} = (); 1269 1270 for $Key (@{$This->{RequiredHeaderDataKeys}}) { 1271 KEYTYPE: { 1272 if ($Key =~ /^FingerprintsStringType$/i) { 1273 $This->{RequiredHeaderDataKeysAndValues}{$Key} = $VectorType; 1274 last KEYTYPE; 1275 } 1276 if ($Key =~ /^Description$/i) { 1277 $This->{RequiredHeaderDataKeysAndValues}{$Key} = $Description; 1278 last KEYTYPE; 1279 } 1280 if ($Key =~ /^Size$/i) { 1281 $This->{RequiredHeaderDataKeysAndValues}{$Key} = $Size; 1282 last KEYTYPE; 1283 } 1284 if ($Key =~ /^BitStringFormat$/i) { 1285 $This->{RequiredHeaderDataKeysAndValues}{$Key} = $BitStringFormat; 1286 last KEYTYPE; 1287 } 1288 if ($Key =~ /^BitsOrder$/i) { 1289 $This->{RequiredHeaderDataKeysAndValues}{$Key} = $BitsOrder; 1290 last KEYTYPE; 1291 } 1292 croak "Error: ${ClassName}->_GenerateWriteRequiredHeaderDataKeysForBitVectorString: Required header data key, $Key, value can't be generated: It's not a known key ..."; 1293 } 1294 } 1295 1296 return $This; 1297 } 1298 1299 # Generate required data header keys and values for writing fingerprints vector string... 1300 # 1301 sub _GenerateWriteRequiredHeaderDataKeysForVectorString { 1302 my($This) = @_; 1303 my($Key, $Value, $VectorType, $Description, $NumOfValues, $VectorValuesType, $VectorStringFormat); 1304 1305 @{$This->{RequiredHeaderDataKeys}} = (); 1306 push @{$This->{RequiredHeaderDataKeys}}, $This->_GetRequiredHeaderDataKeys('FingerprintsVector'); 1307 1308 ($VectorType, $Description, $NumOfValues, $VectorValuesType, $VectorStringFormat) = Fingerprints::FingerprintsStringUtil::GetFingerprintsStringValues($This->{FingerprintsString}); 1309 1310 %{$This->{RequiredHeaderDataKeysAndValues}} = (); 1311 1312 for $Key (@{$This->{RequiredHeaderDataKeys}}) { 1313 KEYTYPE: { 1314 if ($Key =~ /^FingerprintsStringType$/i) { 1315 $This->{RequiredHeaderDataKeysAndValues}{$Key} = $VectorType; 1316 last KEYTYPE; 1317 } 1318 if ($Key =~ /^Description$/i) { 1319 $This->{RequiredHeaderDataKeysAndValues}{$Key} = $Description; 1320 last KEYTYPE; 1321 } 1322 if ($Key =~ /^VectorValuesType$/i) { 1323 $This->{RequiredHeaderDataKeysAndValues}{$Key} = $VectorValuesType; 1324 last KEYTYPE; 1325 } 1326 if ($Key =~ /^VectorStringFormat$/i) { 1327 $This->{RequiredHeaderDataKeysAndValues}{$Key} = $VectorStringFormat; 1328 last KEYTYPE; 1329 } 1330 croak "Error: ${ClassName}->_GenerateWriteRequiredHeaderDataKeysForVectorString: Required header data key, $Key, value can't be generated: It's not a known key ..."; 1331 } 1332 } 1333 1334 return $This; 1335 } 1336 1337 1338 # Get ready for writing fingerprints FP file... 1339 # 1340 sub _PrepareForWritingFingerprintsFPFileData { 1341 my($This) = @_; 1342 my($FPFile, $FileDir, $FileName, $FileExt, $OutDelim); 1343 1344 $FPFile = $This->{Name}; 1345 if (!$This->{Overwrite}) { 1346 if (-e $FPFile) { 1347 croak "Error: ${ClassName}->_PrepareForWritingFingerprintsFPFileData: File, $FPFile, already exist. Use overwrite option..."; 1348 } 1349 } 1350 1351 # Setup FingerprintsStringMode status... 1352 # 1353 $This->{FingerprintsBitVectorStringMode} = 0; 1354 $This->{FingerprintsVectorStringMode} = 0; 1355 $This->{ValidFingerprintsStringMode} = 0; 1356 1357 if ($This->{FingerprintsStringMode} =~ /^FingerprintsBitVectorString$/i) { 1358 $This->{FingerprintsBitVectorStringMode} = 1; 1359 } 1360 elsif ($This->{FingerprintsStringMode} =~ /^FingerprintsVectorString$/i) { 1361 $This->{FingerprintsVectorStringMode} = 1; 1362 } 1363 1364 $This->{ValidFingerprintsStringMode} = ($This->{FingerprintsBitVectorStringMode} || $This->{FingerprintsVectorStringMode}) ? 1 : 0; 1365 1366 if ($This->{FingerprintsBitVectorStringMode}) { 1367 $This->_SetDefaultBitStringFormat(); 1368 $This->_SetDefaultBitsOrder(); 1369 } 1370 elsif ($This->{FingerprintsVectorStringMode}) { 1371 $This->_SetDefaultVectorStringFormat(); 1372 } 1373 1374 return $This; 1375 } 1376 1377 # Set default value for bit string format... 1378 # 1379 sub _SetDefaultBitStringFormat { 1380 my($This) = @_; 1381 1382 if (!$This->{BitStringFormat}) { 1383 $This->{BitStringFormat} = Fingerprints::FingerprintsStringUtil::GetDefaultBitStringFormat(); 1384 } 1385 1386 return $This; 1387 } 1388 1389 # Set default value for bit string format... 1390 # 1391 sub _SetDefaultBitsOrder { 1392 my($This) = @_; 1393 1394 if (!$This->{BitsOrder}) { 1395 $This->{BitsOrder} = Fingerprints::FingerprintsStringUtil::GetDefaultBitsOrder(); 1396 } 1397 1398 return $This; 1399 } 1400 1401 # Set default value for vector string format... 1402 # 1403 sub _SetDefaultVectorStringFormat { 1404 my($This) = @_; 1405 1406 if (!$This->{VectorStringFormat} && $This->{FingerprintsObject}) { 1407 $This->{VectorStringFormat} = Fingerprints::FingerprintsStringUtil::GetDefaultVectorStringFormat($This->{FingerprintsObject}); 1408 } 1409 1410 return $This; 1411 } 1412 1413 # Generate fingerprints object using current fingerprints string... 1414 # 1415 sub _GenerateFingerprintsObject { 1416 my($This) = @_; 1417 1418 $This->{FingerprintsObject} = undef; 1419 1420 if (!$This->{FingerprintsString}) { 1421 return $This; 1422 } 1423 1424 if ($This->{FingerprintsBitVectorStringMode}) { 1425 $This->{FingerprintsObject} = Fingerprints::FingerprintsStringUtil::ParseFingerprintsBitVectorString($This->{FingerprintsString}); 1426 } 1427 elsif ($This->{FingerprintsVectorStringMode}) { 1428 $This->{FingerprintsObject} = Fingerprints::FingerprintsStringUtil::ParseFingerprintsVectorString($This->{FingerprintsString}); 1429 } 1430 else { 1431 return undef; 1432 } 1433 1434 return $This; 1435 } 1436 1437 # Generate fingerprints string using current fingerprints object... 1438 # 1439 sub _GenerateFingerprintsString { 1440 my($This) = @_; 1441 1442 $This->{FingerprintsString} = ''; 1443 1444 if (!$This->{FingerprintsObject}) { 1445 return $This; 1446 } 1447 1448 if ($This->{FingerprintsBitVectorStringMode}) { 1449 $This->{FingerprintsString} = Fingerprints::FingerprintsStringUtil::GenerateFingerprintsString($This->{FingerprintsObject}, $This->{BitStringFormat}, $This->{BitsOrder}); 1450 } 1451 elsif ($This->{FingerprintsVectorStringMode}) { 1452 $This->{FingerprintsString} = Fingerprints::FingerprintsStringUtil::GenerateFingerprintsString($This->{FingerprintsObject}, $This->{VectorStringFormat}); 1453 } 1454 1455 return $This; 1456 } 1457 1458 # Generate fingerprints string using partial fingerprints string and header keys data... 1459 # 1460 # Notes: 1461 # o FP file fingerprints data line only contain partial fingerprints data which 1462 # can't be used directly to create fingerprints bit-vector or vector objects 1463 # using functions available in FingerprintsStringUtil.pm module 1464 # 1465 sub _GenerateFingerprintsStringFromPartialFingerprintsString { 1466 my($This) = @_; 1467 my($FPStringDelim); 1468 1469 $This->{FingerprintsString} = ''; 1470 1471 if (!$This->{PartialFingerprintsString}) { 1472 return $This; 1473 } 1474 1475 $FPStringDelim = Fingerprints::FingerprintsStringUtil::GetFingeprintsStringDelimiter(); 1476 1477 if ($This->{FingerprintsBitVectorStringMode}) { 1478 $This->{FingerprintsString} = $This->{FingerprintsBitVectorStringPrefix} . $FPStringDelim . $This->{PartialFingerprintsString}; 1479 } 1480 elsif ($This->{FingerprintsVectorStringMode}) { 1481 my($NumOfValues, $VectorStringData); 1482 1483 ($NumOfValues, $VectorStringData) = $This->{PartialFingerprintsString} =~ /^(.*?)$FPStringDelim(.*?)$/; 1484 if (!(defined($NumOfValues) && defined($VectorStringData) && $VectorStringData)) { 1485 return $This; 1486 } 1487 1488 $This->{FingerprintsString} = $This->{FingerprintsVectorStringPrefix1} . $FPStringDelim . $NumOfValues . $FPStringDelim . $This->{FingerprintsVectorStringPrefix2} . $FPStringDelim . $VectorStringData; 1489 } 1490 1491 return $This; 1492 } 1493 1494 # Generate partial fingerprints string using fingerprints string and header keys data... 1495 # 1496 # Notes: 1497 # o FP file fingerprints data line only contain partial fingerprints data which 1498 # can't be used directly to create fingerprints bit-vector or vector objects 1499 # using functions available in FingerprintsStringUtil.pm module 1500 # 1501 sub _GeneratePartialFingerprintsStringFromFingerprintsString { 1502 my($This) = @_; 1503 1504 $This->{PartialFingerprintsString} = ''; 1505 1506 if (!$This->{FingerprintsString}) { 1507 return $This; 1508 } 1509 1510 if ($This->{FingerprintsBitVectorStringMode}) { 1511 my($VectorType, $Description, $Size, $BitStringFormat, $BitsOrder, $BitVectorString); 1512 1513 ($VectorType, $Description, $Size, $BitStringFormat, $BitsOrder, $BitVectorString) = Fingerprints::FingerprintsStringUtil::GetFingerprintsStringValues($This->{FingerprintsString}); 1514 $This->{PartialFingerprintsString} = $BitVectorString; 1515 } 1516 elsif ($This->{FingerprintsVectorStringMode}) { 1517 my($FPStringDelim, $VectorType, $Description, $NumOfValues, $VectorValuesType, $VectorStringFormat, $VectorString1, $VectorString2, $VectorString); 1518 1519 $FPStringDelim = Fingerprints::FingerprintsStringUtil::GetFingeprintsStringDelimiter(); 1520 1521 ($VectorType, $Description, $NumOfValues, $VectorValuesType, $VectorStringFormat, $VectorString1, $VectorString2) = Fingerprints::FingerprintsStringUtil::GetFingerprintsStringValues($This->{FingerprintsString}); 1522 $VectorString = TextUtil::IsEmpty($VectorString2) ? $VectorString1 : "${VectorString1}${FPStringDelim}${VectorString2}"; 1523 1524 $This->{PartialFingerprintsString} = $NumOfValues . $FPStringDelim . $VectorString; 1525 } 1526 1527 return $This; 1528 } 1529 1530 # Is it a fingerprints file? 1531 sub IsFingerprintsFPFile ($;$) { 1532 my($FirstParameter, $SecondParameter) = @_; 1533 my($This, $FileName, $Status); 1534 1535 if ((@_ == 2) && (_IsFingerprintsFPFileIO($FirstParameter))) { 1536 ($This, $FileName) = ($FirstParameter, $SecondParameter); 1537 } 1538 else { 1539 $FileName = $FirstParameter; 1540 } 1541 1542 # Check file extension... 1543 $Status = FileUtil::CheckFileType($FileName, "fpf fp"); 1544 1545 return $Status; 1546 } 1547 1548 # Is it a FingerprintsFPFileIO object? 1549 sub _IsFingerprintsFPFileIO { 1550 my($Object) = @_; 1551 1552 return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0; 1553 } 1554