corems.mass_spectra.factory.GC_Class
1__author__ = "Yuri E. Corilo" 2__date__ = "Feb 13, 2020" 3 4 5from pathlib import Path 6import json 7 8from numpy import array 9 10 11from corems.mass_spectra.calc.GC_Calc import GC_Calculations 12from corems.mass_spectra.calc.GC_Deconvolution import MassDeconvolution 13from corems.mass_spectra.calc import SignalProcessing as sp 14 15from corems.chroma_peak.factory.chroma_peak_classes import GCPeak 16from corems.mass_spectra.output.export import LowResGCMSExport 17from corems.encapsulation.factory.parameters import GCMSParameters 18 19 20class GCMSBase(GC_Calculations, MassDeconvolution): 21 """Base class for GC-MS data processing. 22 23 Parameters 24 ---- 25 file_location : str, pathlib.Path, or s3path.S3Path 26 Path object containing the file location. 27 analyzer : str, optional 28 Name of the analyzer. Defaults to 'Unknown'. 29 instrument_label : str, optional 30 Label of the instrument. Defaults to 'Unknown'. 31 sample_name : str, optional 32 Name of the sample. If not provided, it is derived from the file location. 33 34 Attributes 35 ------------ 36 file_location : pathlib.Path 37 Path object containing the file location. 38 sample_name : str 39 Name of the sample. 40 analyzer : str 41 Name of the analyzer. 42 instrument_label : str 43 Label of the instrument. 44 gcpeaks : list 45 List of GCPeak objects. 46 ri_pairs_ref : None 47 Reference retention index pairs. 48 cal_file_path : None 49 Calibration file path. 50 _parameters : GCMSParameters 51 GC-MS parameters. 52 _retention_time_list : list 53 List of retention times. 54 _scans_number_list : list 55 List of scan numbers. 56 _tic_list : list 57 List of total ion chromatogram values. 58 _ms : dict 59 Dictionary containing all mass spectra. 60 _processed_tic : list 61 List of processed total ion chromatogram values. 62 63 Methods 64 ------- 65 * process_chromatogram(plot_res=False). Process the chromatogram. 66 * plot_gc_peaks(ax=None, color='red'). Plot the GC peaks. 67 """ 68 69 def __init__( 70 self, 71 file_location, 72 analyzer="Unknown", 73 instrument_label="Unknown", 74 sample_name=None, 75 ): 76 if isinstance(file_location, str): 77 # if obj is a string it defaults to create a Path obj, pass the S3Path if needed 78 file_location = Path(file_location) 79 80 if not file_location.exists(): 81 raise FileExistsError("File does not exist: " + str(file_location)) 82 83 self.file_location = file_location 84 85 if sample_name: 86 self.sample_name = sample_name 87 else: 88 self.sample_name = file_location.stem 89 90 self.analyzer = analyzer 91 self.instrument_label = instrument_label 92 self._init_settings() 93 94 self._retention_time_list = [] 95 self._scans_number_list = [] 96 self._tic_list = [] 97 98 # all scans 99 self._ms = {} 100 101 # after peak detection 102 self._processed_tic = [] 103 self.gcpeaks = [] 104 105 self.ri_pairs_ref = None 106 self.cal_file_path = None 107 108 def _init_settings(self): 109 """Initialize the settings for GC_Class. 110 111 This method initializes the settings for the GC_Class object using the GCMSParameters class. 112 """ 113 self._parameters = GCMSParameters() 114 115 def __len__(self): 116 """Return the number of GC peaks in the GC_Class object.""" 117 return len(self.gcpeaks) 118 119 def __getitem__(self, scan_number) -> GCPeak: 120 """Return the GCPeak with the given scan number.""" 121 return self.gcpeaks[scan_number] 122 123 # def __iter__(self): 124 125 # return iter(self.gcpeaks.values()) 126 127 def process_chromatogram(self, plot_res=False): 128 """Process the chromatogram. 129 130 This method processes the chromatogram. 131 132 Parameters 133 ---------- 134 plot_res : bool, optional 135 If True, plot the results. Defaults to False. 136 """ 137 138 # tic = self.tic - self.baseline_detector(self.tic) 139 140 self._processed_tic = self.smooth_tic(self.tic) 141 142 for index, tic in enumerate(self._processed_tic): 143 self._ms[index]._processed_tic = tic 144 145 # self.second_derivative_threshold(self._processed_tic) 146 147 if self.chromatogram_settings.use_deconvolution: 148 self.run_deconvolution(plot_res=False) 149 150 else: 151 peaks_index = self.centroid_detector( 152 self._processed_tic, self.retention_time 153 ) 154 155 for i in peaks_index: 156 apex_index = i[1] 157 158 gc_peak = GCPeak(self, self._ms[apex_index], i) 159 160 gc_peak.calc_area(self._processed_tic, 1) 161 162 self.gcpeaks.append(gc_peak) 163 164 # self.gcpeaks[self.scans_number[apex_index]] = gc_peak 165 166 def add_mass_spectrum(self, mass_spec): 167 """Add a mass spectrum to the GC-MS object. 168 169 This method adds a mass spectrum to the GC-MS object. 170 171 Parameters 172 ---------- 173 mass_spec : MassSpectrum 174 Mass spectrum to be added. 175 """ 176 177 self._ms[mass_spec.scan_number] = mass_spec 178 179 def set_tic_list_from_data(self): 180 """Set the total ion chromatogram list from the mass spectra data within the GC-MS data object.""" 181 182 self.tic = [self._ms.get(i).tic for i in self.scans_number] 183 184 # self.set_tic_list([self._ms.get(i).get_sumed_signal_to_noise() for i in self.get_scans_number()]) 185 186 def set_retention_time_from_data(self): 187 """Set the retention time list from the mass spectra data within the GC-MS data object.""" 188 189 retention_time_list = [] 190 191 for key_ms in sorted(self._ms.keys()): 192 retention_time_list.append(self._ms.get(key_ms).retention_time) 193 194 self.retention_time = retention_time_list 195 196 # self.set_retention_time_list(sorted(self._ms.keys())) 197 198 def set_scans_number_from_data(self): 199 """Set the scan number list from the mass spectra data within the GC-MS data object.""" 200 201 self.scans_number = sorted(self._ms.keys()) 202 203 @property 204 def parameters(self): 205 """GCMS Parameters""" 206 return self._parameters 207 208 @parameters.setter 209 def parameters(self, gcms_parameters_instance): 210 self._parameters = gcms_parameters_instance 211 212 # Note: maintaining `parameter` for backwards compatibility, 213 # but proper usage would reference `parameters` to conform 214 # to other classes. 215 @property 216 def parameter(self): 217 """GCMS Parameters""" 218 return self._parameters 219 220 @parameter.setter 221 def parameter(self, gcms_parameters_instance): 222 self._parameters = gcms_parameters_instance 223 224 @property 225 def molecular_search_settings(self): 226 """Molecular Search Settings""" 227 return self.parameters.molecular_search 228 229 @molecular_search_settings.setter 230 def molecular_search_settings(self, settings_class_instance): 231 self.parameters.molecular_search = settings_class_instance 232 233 @property 234 def chromatogram_settings(self): 235 """Chromatogram Settings""" 236 return self.parameters.gc_ms 237 238 @chromatogram_settings.setter 239 def chromatogram_settings(self, settings_class_instance): 240 self.parameters.gc_ms = settings_class_instance 241 242 @property 243 def scans_number(self): 244 """Scans Number""" 245 return self._scans_number_list 246 247 @property 248 def retention_time(self): 249 """Retention Time""" 250 return self._retention_time_list 251 252 @property 253 def processed_tic(self): 254 """Processed Total Ion Current""" 255 return self._processed_tic 256 257 @property 258 def tic(self): 259 """Total Ion Current""" 260 return self._tic_list 261 262 @property 263 def max_tic(self): 264 """Maximum Total Ion Current""" 265 return max([gc_peak.tic for gc_peak in self]) 266 267 @property 268 def min_tic(self): 269 """Minimum Total Ion Current""" 270 return min([gc_peak.tic for gc_peak in self]) 271 272 @property 273 def dynamic_range(self): 274 """Dynamic Range of the Total Ion Current""" 275 return self.max_tic / self.min_tic 276 277 @property 278 def matched_peaks(self): 279 """Matched Peaks""" 280 return [gc_peak for gc_peak in self if gc_peak] 281 282 @property 283 def sorted_gcpeaks(self): 284 """Sorted GC Peaks, by retention time""" 285 return sorted(self, key=lambda g: g.retention_time) 286 287 @property 288 def unique_metabolites(self): 289 """Unique Metabolites""" 290 metabolites = set() 291 for gc_peak in self: 292 if gc_peak: 293 for compound_obj in gc_peak: 294 metabolites.add(compound_obj.name) 295 296 return metabolites 297 298 @property 299 def metabolites_data(self): 300 """Metabolites Data""" 301 metabolites = {} 302 for gc_peak in self: 303 if gc_peak: 304 for compound_obj in gc_peak: 305 if compound_obj.name in metabolites.keys(): 306 current_score = metabolites[compound_obj.name][ 307 "highest_similarity_score" 308 ] 309 compound_score = compound_obj.spectral_similarity_score 310 metabolites[compound_obj.name]["highest_similarity_score"] = ( 311 compound_score 312 if compound_score > current_score 313 else current_score 314 ) 315 316 else: 317 if compound_obj.metadata: 318 metabolites[compound_obj.name] = { 319 "name": compound_obj.name, 320 "highest_similarity_score": compound_obj.spectral_similarity_score, 321 "casno": compound_obj.metadata.cas, 322 "kegg": compound_obj.metadata.kegg, 323 "inchi": compound_obj.metadata.inchi, 324 "inchi_key": compound_obj.metadata.inchikey, 325 "chebi": compound_obj.metadata.chebi, 326 "smiles": compound_obj.metadata.smiles, 327 } 328 else: 329 metabolites[compound_obj.name] = { 330 "name": compound_obj.name, 331 "highest_similarity_score": compound_obj.spectral_similarity_score, 332 "casno": "", 333 "kegg": "", 334 "inchi": "", 335 "inchikey": "", 336 "chebi": "", 337 "smiles": "", 338 } 339 340 return list(metabolites.values()) 341 342 @property 343 def no_matched_peaks(self): 344 """Peaks with no Matched Metabolites""" 345 return [peak for peak in self if not peak] 346 347 @retention_time.setter 348 def retention_time(self, alist): 349 # self._retention_time_list = linspace(0, 80, num=len(self._scans_number_list)) 350 self._retention_time_list = alist 351 352 @scans_number.setter 353 def scans_number(self, alist): 354 self._scans_number_list = alist 355 356 @tic.setter 357 def tic(self, alist): 358 self._tic_list = array(alist) 359 360 def plot_gc_peaks(self, ax=None, color="red"): # pragma: no cover 361 """Plot the GC peaks. 362 363 This method plots the GC peaks. 364 365 Parameters 366 ---------- 367 ax : matplotlib.axes.Axes, optional 368 Axes object to plot the GC peaks. Defaults to None. 369 color : str, optional 370 Color of the GC peaks. Defaults to 'red'. 371 """ 372 373 import matplotlib.pyplot as plt 374 375 fig = plt.gcf() 376 if ax is None: 377 ax = plt.gca() 378 379 max_rts = [gc_peak.mass_spectrum.retention_time for gc_peak in self] 380 max_tics = [gc_peak.mass_spectrum.tic for gc_peak in self] 381 382 # min_rts = [self._ms[gc_peak.start_index].retention_time for gc_peak in self] + [self._ms[gc_peak.final_index].retention_time for gc_peak in self] 383 # min_tics = [self._ms[gc_peak.start_index].tic for gc_peak in self] + [self._ms[gc_peak.final_index].tic for gc_peak in self] 384 # sc = ax.scatter(min_rts, min_tics, color='yellow', linewidth=0, marker='v') 385 386 sc = ax.scatter(max_rts, max_tics, color=color, marker="v") 387 388 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 389 390 annot = ax.annotate( 391 "", 392 xy=(0, 0), 393 xytext=(20, 20), 394 textcoords="offset points", 395 bbox=dict(boxstyle="round", fc="w"), 396 arrowprops=dict(arrowstyle="->"), 397 ) 398 annot.set_visible(False) 399 annot.get_bbox_patch().set_facecolor(("lightblue")) 400 annot.get_bbox_patch().set_alpha(0.8) 401 402 def update_annot(ind): 403 pos = sc.get_offsets()[ind["ind"][0]] 404 annot.xy = pos 405 406 text = "RT: {}\nRT Ref: {}\nRI: {}\nRI Ref: {}\nSimilarity Score: {}\nName: {}".format( 407 " ".join([str(round(self[n].retention_time, 2)) for n in ind["ind"]]), 408 " ".join( 409 [ 410 str( 411 round(self[n].highest_score_compound.retention_time, 2) 412 if self[n].highest_score_compound 413 else None 414 ) 415 for n in ind["ind"] 416 ] 417 ), 418 " ".join( 419 [ 420 str(round(self[n].ri, 2) if self[n].ri else None) 421 for n in ind["ind"] 422 ] 423 ), 424 " ".join( 425 [ 426 str( 427 round(self[n].highest_score_compound.ri, 2) 428 if self[n].highest_score_compound 429 else None 430 ) 431 for n in ind["ind"] 432 ] 433 ), 434 " ".join( 435 [ 436 str( 437 round(self[n].highest_score_compound.similarity_score, 4) 438 if self[n].highest_score_compound 439 else None 440 ) 441 for n in ind["ind"] 442 ] 443 ), 444 " ".join( 445 [ 446 str( 447 self[n].highest_score_compound.name 448 if self[n].highest_score_compound 449 else None 450 ) 451 for n in ind["ind"] 452 ] 453 ), 454 ) 455 annot.set_text(text) 456 457 def hover(event): 458 vis = annot.get_visible() 459 if event.inaxes == ax: 460 cont, ind = sc.contains(event) 461 if cont: 462 update_annot(ind) 463 annot.set_visible(True) 464 fig.canvas.draw_idle() 465 else: 466 if vis: 467 annot.set_visible(False) 468 fig.canvas.draw_idle() 469 470 fig.canvas.mpl_connect("motion_notify_event", hover) 471 472 return ax 473 474 def to_excel( 475 self, out_file_path, write_mode="ab", write_metadata=True, id_label="corems:" 476 ): 477 """Export the GC-MS data to an Excel file. 478 479 This method exports the GC-MS data to an Excel file. 480 481 Parameters 482 ---------- 483 out_file_path : str, pathlib.Path, or s3path.S3Path 484 Path object containing the file location. 485 write_mode : str, optional 486 Write mode. Defaults to 'ab'. 487 write_metadata : bool, optional 488 If True, write the metadata. Defaults to True. 489 id_label : str, optional 490 Label of the ID. Defaults to 'corems:'. 491 492 """ 493 494 if isinstance(out_file_path, str): 495 out_file_path = Path(out_file_path) 496 497 exportMS = LowResGCMSExport(out_file_path, self) 498 exportMS.to_excel( 499 id_label=id_label, write_mode=write_mode, write_metadata=write_metadata 500 ) 501 502 return out_file_path.with_suffix(".xlsx") 503 504 def to_csv( 505 self, 506 out_file_path, 507 separate_output=False, 508 write_metadata=True, 509 id_label="corems:", 510 ): 511 """Export the GC-MS data to a CSV file. 512 513 Parameters 514 ---------- 515 out_file_path : str, pathlib.Path, or s3path.S3Path 516 Path object containing the file location. 517 separate_output : bool, optional 518 If True, separate the output. Defaults to False. 519 write_metadata : bool, optional 520 If True, write the metadata. Defaults to True. 521 522 """ 523 524 if isinstance(out_file_path, str): 525 out_file_path = Path(out_file_path) 526 527 exportMS = LowResGCMSExport(out_file_path, self) 528 exportMS.to_csv( 529 id_label=id_label, 530 separate_output=separate_output, 531 write_metadata=write_metadata, 532 ) 533 534 return out_file_path.with_suffix(".csv") 535 536 def to_pandas(self, out_file_path, write_metadata=True, id_label="corems:"): 537 """Export the GC-MS data to a Pandas dataframe. 538 539 Parameters 540 ---------- 541 out_file_path : str, pathlib.Path, or s3path.S3Path 542 Path object containing the file location. 543 write_metadata : bool, optional 544 If True, write the metadata. Defaults to True. 545 id_label : str, optional 546 Label of the ID. Defaults to 'corems:'. 547 548 """ 549 550 if isinstance(out_file_path, str): 551 out_file_path = Path(out_file_path) 552 # pickle dataframe (pkl extension) 553 exportMS = LowResGCMSExport(out_file_path, self) 554 exportMS.to_pandas(id_label=id_label, write_metadata=write_metadata) 555 556 return out_file_path.with_suffix(".pkl") 557 558 def to_parquet(self, out_file_path, write_metadata=True, id_label="corems:"): 559 """Export the GC-MS data to a Parquet file. 560 561 Parameters 562 ---------- 563 out_file_path : str, pathlib.Path, or s3path.S3Path 564 Path object containing the file location. 565 write_metadata : bool, optional 566 If True, write the metadata. Defaults to True. 567 id_label : str, optional 568 Label of the ID. Defaults to 'corems:'. 569 570 Notes 571 ----- 572 Requires ``pyarrow`` (or ``fastparquet``) for pandas Parquet I/O. 573 """ 574 575 if isinstance(out_file_path, str): 576 out_file_path = Path(out_file_path) 577 578 exportMS = LowResGCMSExport(out_file_path, self) 579 exportMS.to_parquet(id_label=id_label, write_metadata=write_metadata) 580 581 return out_file_path.with_suffix(".parquet") 582 583 def to_dataframe(self, id_label="corems:"): 584 """Export the GC-MS data to a Pandas dataframe. 585 586 Parameters 587 ---------- 588 id_label : str, optional 589 Label of the ID. Defaults to 'corems:'. 590 591 """ 592 593 # returns pandas dataframe 594 exportMS = LowResGCMSExport(self.sample_name, self) 595 return exportMS.get_pandas_df(id_label=id_label) 596 597 def processing_stats(self): 598 """Return the processing statistics.""" 599 600 # returns json string 601 exportMS = LowResGCMSExport(self.sample_name, self) 602 return exportMS.get_data_stats(self) 603 604 def parameters_json(self, id_label="corems:", output_path=" "): 605 """Return the parameters in JSON format. 606 607 Parameters 608 ---------- 609 id_label : str, optional 610 Label of the ID. Defaults to 'corems:'. 611 output_path : str, optional 612 Path object containing the file location. Defaults to " ". 613 """ 614 615 # returns json string 616 exportMS = LowResGCMSExport(self.sample_name, self) 617 return exportMS.get_parameters_json(self, id_label, output_path) 618 619 def to_json(self, id_label="corems:"): 620 """Export the GC-MS data to a JSON file. 621 622 Parameters 623 ---------- 624 id_label : str, optional 625 Label of the ID. Defaults to 'corems:'. 626 627 """ 628 629 # returns pandas dataframe 630 exportMS = LowResGCMSExport(self.sample_name, self) 631 return exportMS.get_json(id_label=id_label) 632 633 def to_hdf(self, id_label="corems:"): 634 """Export the GC-MS data to a HDF file. 635 636 Parameters 637 ---------- 638 id_label : str, optional 639 Label of the ID. Defaults to 'corems:'. 640 641 """ 642 643 # returns pandas dataframe 644 exportMS = LowResGCMSExport(self.sample_name, self) 645 return exportMS.to_hdf(id_label=id_label) 646 647 def plot_chromatogram(self, ax=None, color="blue"): # pragma: no cover 648 """Plot the chromatogram. 649 650 Parameters 651 ---------- 652 ax : matplotlib.axes.Axes, optional 653 Axes object to plot the chromatogram. Defaults to None. 654 color : str, optional 655 Color of the chromatogram. Defaults to 'blue'. 656 657 """ 658 659 import matplotlib.pyplot as plt 660 661 if ax is None: 662 ax = plt.gca() 663 664 ax.plot(self.retention_time, self.tic, color=color) 665 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 666 667 return ax 668 669 def plot_smoothed_chromatogram(self, ax=None, color="green"): # pragma: no cover 670 """Plot the smoothed chromatogram. 671 672 Parameters 673 ---------- 674 ax : matplotlib.axes.Axes, optional 675 Axes object to plot the smoothed chromatogram. Defaults to None. 676 color : str, optional 677 Color of the smoothed chromatogram. Defaults to 'green'. 678 679 """ 680 681 import matplotlib.pyplot as plt 682 683 if ax is None: 684 ax = plt.gca() 685 686 ax.plot(self.retention_time, self.smooth_tic(self.tic), color=color) 687 688 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 689 690 return ax 691 692 def plot_detected_baseline(self, ax=None, color="blue"): # pragma: no cover 693 """Plot the detected baseline. 694 695 Parameters 696 ---------- 697 ax : matplotlib.axes.Axes, optional 698 Axes object to plot the detected baseline. Defaults to None. 699 color : str, optional 700 Color of the detected baseline. Defaults to 'blue'. 701 702 """ 703 704 import matplotlib.pyplot as plt 705 706 if ax is None: 707 ax = plt.gca() 708 709 max_height = self.chromatogram_settings.peak_height_max_percent 710 max_prominence = self.chromatogram_settings.peak_max_prominence_percent 711 712 baseline = sp.baseline_detector( 713 self.tic, self.retention_time, max_height, max_prominence 714 ) 715 ax.plot(self.retention_time, color=color) 716 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 717 718 return ax 719 720 def plot_baseline_subtraction(self, ax=None, color="black"): # pragma: no cover 721 """Plot the baseline subtraction. 722 723 Parameters 724 ---------- 725 ax : matplotlib.axes.Axes, optional 726 Axes object to plot the baseline subtraction. Defaults to None. 727 color : str, optional 728 Color of the baseline subtraction. Defaults to 'black'. 729 730 """ 731 732 import matplotlib.pyplot as plt 733 734 if ax is None: 735 ax = plt.gca() 736 737 max_height = self.chromatogram_settings.peak_height_max_percent 738 739 max_prominence = self.chromatogram_settings.peak_max_prominence_percent 740 741 x = self.tic + sp.baseline_detector( 742 self.tic, self.retention_time, max_height, max_prominence 743 ) 744 745 ax.plot(self.retention_time, x, color=color) 746 747 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 748 749 return ax 750 751 def peaks_rt_tic(self, json_string=False): 752 """Return the peaks, retention time, and total ion chromatogram. 753 754 Parameters 755 ---------- 756 json_string : bool, optional 757 If True, return the peaks, retention time, and total ion chromatogram in JSON format. Defaults to False. 758 759 """ 760 761 peaks_list = dict() 762 763 all_candidates_data = {} 764 765 all_peaks_data = {} 766 767 for gcms_peak in self.sorted_gcpeaks: 768 dict_data = { 769 "rt": gcms_peak.rt_list, 770 "tic": gcms_peak.tic_list, 771 "mz": gcms_peak.mass_spectrum.mz_exp.tolist(), 772 "abundance": gcms_peak.mass_spectrum.abundance.tolist(), 773 "candidate_names": gcms_peak.compound_names, 774 } 775 776 peaks_list[gcms_peak.retention_time] = dict_data 777 778 for compound in gcms_peak: 779 if compound.name not in all_candidates_data.keys(): 780 mz = array(compound.mz).tolist() 781 abundance = array(compound.abundance).tolist() 782 data = {"mz": mz, "abundance": abundance} 783 all_candidates_data[compound.name] = data 784 785 all_peaks_data["peak_data"] = peaks_list 786 all_peaks_data["ref_data"] = all_candidates_data 787 788 if json_string: 789 return json.dumps(all_peaks_data) 790 791 else: 792 return all_peaks_data 793 794 def plot_processed_chromatogram(self, ax=None, color="black"): 795 """Plot the processed chromatogram. 796 797 Parameters 798 ---------- 799 ax : matplotlib.axes.Axes, optional 800 Axes object to plot the processed chromatogram. Defaults to None. 801 color : str, optional 802 Color of the processed chromatogram. Defaults to 'black'. 803 804 """ 805 806 import matplotlib.pyplot as plt 807 808 if ax is None: 809 ax = plt.gca() 810 811 ax.plot(self.retention_time, self.processed_tic, color=color) 812 813 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 814 815 return ax
21class GCMSBase(GC_Calculations, MassDeconvolution): 22 """Base class for GC-MS data processing. 23 24 Parameters 25 ---- 26 file_location : str, pathlib.Path, or s3path.S3Path 27 Path object containing the file location. 28 analyzer : str, optional 29 Name of the analyzer. Defaults to 'Unknown'. 30 instrument_label : str, optional 31 Label of the instrument. Defaults to 'Unknown'. 32 sample_name : str, optional 33 Name of the sample. If not provided, it is derived from the file location. 34 35 Attributes 36 ------------ 37 file_location : pathlib.Path 38 Path object containing the file location. 39 sample_name : str 40 Name of the sample. 41 analyzer : str 42 Name of the analyzer. 43 instrument_label : str 44 Label of the instrument. 45 gcpeaks : list 46 List of GCPeak objects. 47 ri_pairs_ref : None 48 Reference retention index pairs. 49 cal_file_path : None 50 Calibration file path. 51 _parameters : GCMSParameters 52 GC-MS parameters. 53 _retention_time_list : list 54 List of retention times. 55 _scans_number_list : list 56 List of scan numbers. 57 _tic_list : list 58 List of total ion chromatogram values. 59 _ms : dict 60 Dictionary containing all mass spectra. 61 _processed_tic : list 62 List of processed total ion chromatogram values. 63 64 Methods 65 ------- 66 * process_chromatogram(plot_res=False). Process the chromatogram. 67 * plot_gc_peaks(ax=None, color='red'). Plot the GC peaks. 68 """ 69 70 def __init__( 71 self, 72 file_location, 73 analyzer="Unknown", 74 instrument_label="Unknown", 75 sample_name=None, 76 ): 77 if isinstance(file_location, str): 78 # if obj is a string it defaults to create a Path obj, pass the S3Path if needed 79 file_location = Path(file_location) 80 81 if not file_location.exists(): 82 raise FileExistsError("File does not exist: " + str(file_location)) 83 84 self.file_location = file_location 85 86 if sample_name: 87 self.sample_name = sample_name 88 else: 89 self.sample_name = file_location.stem 90 91 self.analyzer = analyzer 92 self.instrument_label = instrument_label 93 self._init_settings() 94 95 self._retention_time_list = [] 96 self._scans_number_list = [] 97 self._tic_list = [] 98 99 # all scans 100 self._ms = {} 101 102 # after peak detection 103 self._processed_tic = [] 104 self.gcpeaks = [] 105 106 self.ri_pairs_ref = None 107 self.cal_file_path = None 108 109 def _init_settings(self): 110 """Initialize the settings for GC_Class. 111 112 This method initializes the settings for the GC_Class object using the GCMSParameters class. 113 """ 114 self._parameters = GCMSParameters() 115 116 def __len__(self): 117 """Return the number of GC peaks in the GC_Class object.""" 118 return len(self.gcpeaks) 119 120 def __getitem__(self, scan_number) -> GCPeak: 121 """Return the GCPeak with the given scan number.""" 122 return self.gcpeaks[scan_number] 123 124 # def __iter__(self): 125 126 # return iter(self.gcpeaks.values()) 127 128 def process_chromatogram(self, plot_res=False): 129 """Process the chromatogram. 130 131 This method processes the chromatogram. 132 133 Parameters 134 ---------- 135 plot_res : bool, optional 136 If True, plot the results. Defaults to False. 137 """ 138 139 # tic = self.tic - self.baseline_detector(self.tic) 140 141 self._processed_tic = self.smooth_tic(self.tic) 142 143 for index, tic in enumerate(self._processed_tic): 144 self._ms[index]._processed_tic = tic 145 146 # self.second_derivative_threshold(self._processed_tic) 147 148 if self.chromatogram_settings.use_deconvolution: 149 self.run_deconvolution(plot_res=False) 150 151 else: 152 peaks_index = self.centroid_detector( 153 self._processed_tic, self.retention_time 154 ) 155 156 for i in peaks_index: 157 apex_index = i[1] 158 159 gc_peak = GCPeak(self, self._ms[apex_index], i) 160 161 gc_peak.calc_area(self._processed_tic, 1) 162 163 self.gcpeaks.append(gc_peak) 164 165 # self.gcpeaks[self.scans_number[apex_index]] = gc_peak 166 167 def add_mass_spectrum(self, mass_spec): 168 """Add a mass spectrum to the GC-MS object. 169 170 This method adds a mass spectrum to the GC-MS object. 171 172 Parameters 173 ---------- 174 mass_spec : MassSpectrum 175 Mass spectrum to be added. 176 """ 177 178 self._ms[mass_spec.scan_number] = mass_spec 179 180 def set_tic_list_from_data(self): 181 """Set the total ion chromatogram list from the mass spectra data within the GC-MS data object.""" 182 183 self.tic = [self._ms.get(i).tic for i in self.scans_number] 184 185 # self.set_tic_list([self._ms.get(i).get_sumed_signal_to_noise() for i in self.get_scans_number()]) 186 187 def set_retention_time_from_data(self): 188 """Set the retention time list from the mass spectra data within the GC-MS data object.""" 189 190 retention_time_list = [] 191 192 for key_ms in sorted(self._ms.keys()): 193 retention_time_list.append(self._ms.get(key_ms).retention_time) 194 195 self.retention_time = retention_time_list 196 197 # self.set_retention_time_list(sorted(self._ms.keys())) 198 199 def set_scans_number_from_data(self): 200 """Set the scan number list from the mass spectra data within the GC-MS data object.""" 201 202 self.scans_number = sorted(self._ms.keys()) 203 204 @property 205 def parameters(self): 206 """GCMS Parameters""" 207 return self._parameters 208 209 @parameters.setter 210 def parameters(self, gcms_parameters_instance): 211 self._parameters = gcms_parameters_instance 212 213 # Note: maintaining `parameter` for backwards compatibility, 214 # but proper usage would reference `parameters` to conform 215 # to other classes. 216 @property 217 def parameter(self): 218 """GCMS Parameters""" 219 return self._parameters 220 221 @parameter.setter 222 def parameter(self, gcms_parameters_instance): 223 self._parameters = gcms_parameters_instance 224 225 @property 226 def molecular_search_settings(self): 227 """Molecular Search Settings""" 228 return self.parameters.molecular_search 229 230 @molecular_search_settings.setter 231 def molecular_search_settings(self, settings_class_instance): 232 self.parameters.molecular_search = settings_class_instance 233 234 @property 235 def chromatogram_settings(self): 236 """Chromatogram Settings""" 237 return self.parameters.gc_ms 238 239 @chromatogram_settings.setter 240 def chromatogram_settings(self, settings_class_instance): 241 self.parameters.gc_ms = settings_class_instance 242 243 @property 244 def scans_number(self): 245 """Scans Number""" 246 return self._scans_number_list 247 248 @property 249 def retention_time(self): 250 """Retention Time""" 251 return self._retention_time_list 252 253 @property 254 def processed_tic(self): 255 """Processed Total Ion Current""" 256 return self._processed_tic 257 258 @property 259 def tic(self): 260 """Total Ion Current""" 261 return self._tic_list 262 263 @property 264 def max_tic(self): 265 """Maximum Total Ion Current""" 266 return max([gc_peak.tic for gc_peak in self]) 267 268 @property 269 def min_tic(self): 270 """Minimum Total Ion Current""" 271 return min([gc_peak.tic for gc_peak in self]) 272 273 @property 274 def dynamic_range(self): 275 """Dynamic Range of the Total Ion Current""" 276 return self.max_tic / self.min_tic 277 278 @property 279 def matched_peaks(self): 280 """Matched Peaks""" 281 return [gc_peak for gc_peak in self if gc_peak] 282 283 @property 284 def sorted_gcpeaks(self): 285 """Sorted GC Peaks, by retention time""" 286 return sorted(self, key=lambda g: g.retention_time) 287 288 @property 289 def unique_metabolites(self): 290 """Unique Metabolites""" 291 metabolites = set() 292 for gc_peak in self: 293 if gc_peak: 294 for compound_obj in gc_peak: 295 metabolites.add(compound_obj.name) 296 297 return metabolites 298 299 @property 300 def metabolites_data(self): 301 """Metabolites Data""" 302 metabolites = {} 303 for gc_peak in self: 304 if gc_peak: 305 for compound_obj in gc_peak: 306 if compound_obj.name in metabolites.keys(): 307 current_score = metabolites[compound_obj.name][ 308 "highest_similarity_score" 309 ] 310 compound_score = compound_obj.spectral_similarity_score 311 metabolites[compound_obj.name]["highest_similarity_score"] = ( 312 compound_score 313 if compound_score > current_score 314 else current_score 315 ) 316 317 else: 318 if compound_obj.metadata: 319 metabolites[compound_obj.name] = { 320 "name": compound_obj.name, 321 "highest_similarity_score": compound_obj.spectral_similarity_score, 322 "casno": compound_obj.metadata.cas, 323 "kegg": compound_obj.metadata.kegg, 324 "inchi": compound_obj.metadata.inchi, 325 "inchi_key": compound_obj.metadata.inchikey, 326 "chebi": compound_obj.metadata.chebi, 327 "smiles": compound_obj.metadata.smiles, 328 } 329 else: 330 metabolites[compound_obj.name] = { 331 "name": compound_obj.name, 332 "highest_similarity_score": compound_obj.spectral_similarity_score, 333 "casno": "", 334 "kegg": "", 335 "inchi": "", 336 "inchikey": "", 337 "chebi": "", 338 "smiles": "", 339 } 340 341 return list(metabolites.values()) 342 343 @property 344 def no_matched_peaks(self): 345 """Peaks with no Matched Metabolites""" 346 return [peak for peak in self if not peak] 347 348 @retention_time.setter 349 def retention_time(self, alist): 350 # self._retention_time_list = linspace(0, 80, num=len(self._scans_number_list)) 351 self._retention_time_list = alist 352 353 @scans_number.setter 354 def scans_number(self, alist): 355 self._scans_number_list = alist 356 357 @tic.setter 358 def tic(self, alist): 359 self._tic_list = array(alist) 360 361 def plot_gc_peaks(self, ax=None, color="red"): # pragma: no cover 362 """Plot the GC peaks. 363 364 This method plots the GC peaks. 365 366 Parameters 367 ---------- 368 ax : matplotlib.axes.Axes, optional 369 Axes object to plot the GC peaks. Defaults to None. 370 color : str, optional 371 Color of the GC peaks. Defaults to 'red'. 372 """ 373 374 import matplotlib.pyplot as plt 375 376 fig = plt.gcf() 377 if ax is None: 378 ax = plt.gca() 379 380 max_rts = [gc_peak.mass_spectrum.retention_time for gc_peak in self] 381 max_tics = [gc_peak.mass_spectrum.tic for gc_peak in self] 382 383 # min_rts = [self._ms[gc_peak.start_index].retention_time for gc_peak in self] + [self._ms[gc_peak.final_index].retention_time for gc_peak in self] 384 # min_tics = [self._ms[gc_peak.start_index].tic for gc_peak in self] + [self._ms[gc_peak.final_index].tic for gc_peak in self] 385 # sc = ax.scatter(min_rts, min_tics, color='yellow', linewidth=0, marker='v') 386 387 sc = ax.scatter(max_rts, max_tics, color=color, marker="v") 388 389 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 390 391 annot = ax.annotate( 392 "", 393 xy=(0, 0), 394 xytext=(20, 20), 395 textcoords="offset points", 396 bbox=dict(boxstyle="round", fc="w"), 397 arrowprops=dict(arrowstyle="->"), 398 ) 399 annot.set_visible(False) 400 annot.get_bbox_patch().set_facecolor(("lightblue")) 401 annot.get_bbox_patch().set_alpha(0.8) 402 403 def update_annot(ind): 404 pos = sc.get_offsets()[ind["ind"][0]] 405 annot.xy = pos 406 407 text = "RT: {}\nRT Ref: {}\nRI: {}\nRI Ref: {}\nSimilarity Score: {}\nName: {}".format( 408 " ".join([str(round(self[n].retention_time, 2)) for n in ind["ind"]]), 409 " ".join( 410 [ 411 str( 412 round(self[n].highest_score_compound.retention_time, 2) 413 if self[n].highest_score_compound 414 else None 415 ) 416 for n in ind["ind"] 417 ] 418 ), 419 " ".join( 420 [ 421 str(round(self[n].ri, 2) if self[n].ri else None) 422 for n in ind["ind"] 423 ] 424 ), 425 " ".join( 426 [ 427 str( 428 round(self[n].highest_score_compound.ri, 2) 429 if self[n].highest_score_compound 430 else None 431 ) 432 for n in ind["ind"] 433 ] 434 ), 435 " ".join( 436 [ 437 str( 438 round(self[n].highest_score_compound.similarity_score, 4) 439 if self[n].highest_score_compound 440 else None 441 ) 442 for n in ind["ind"] 443 ] 444 ), 445 " ".join( 446 [ 447 str( 448 self[n].highest_score_compound.name 449 if self[n].highest_score_compound 450 else None 451 ) 452 for n in ind["ind"] 453 ] 454 ), 455 ) 456 annot.set_text(text) 457 458 def hover(event): 459 vis = annot.get_visible() 460 if event.inaxes == ax: 461 cont, ind = sc.contains(event) 462 if cont: 463 update_annot(ind) 464 annot.set_visible(True) 465 fig.canvas.draw_idle() 466 else: 467 if vis: 468 annot.set_visible(False) 469 fig.canvas.draw_idle() 470 471 fig.canvas.mpl_connect("motion_notify_event", hover) 472 473 return ax 474 475 def to_excel( 476 self, out_file_path, write_mode="ab", write_metadata=True, id_label="corems:" 477 ): 478 """Export the GC-MS data to an Excel file. 479 480 This method exports the GC-MS data to an Excel file. 481 482 Parameters 483 ---------- 484 out_file_path : str, pathlib.Path, or s3path.S3Path 485 Path object containing the file location. 486 write_mode : str, optional 487 Write mode. Defaults to 'ab'. 488 write_metadata : bool, optional 489 If True, write the metadata. Defaults to True. 490 id_label : str, optional 491 Label of the ID. Defaults to 'corems:'. 492 493 """ 494 495 if isinstance(out_file_path, str): 496 out_file_path = Path(out_file_path) 497 498 exportMS = LowResGCMSExport(out_file_path, self) 499 exportMS.to_excel( 500 id_label=id_label, write_mode=write_mode, write_metadata=write_metadata 501 ) 502 503 return out_file_path.with_suffix(".xlsx") 504 505 def to_csv( 506 self, 507 out_file_path, 508 separate_output=False, 509 write_metadata=True, 510 id_label="corems:", 511 ): 512 """Export the GC-MS data to a CSV file. 513 514 Parameters 515 ---------- 516 out_file_path : str, pathlib.Path, or s3path.S3Path 517 Path object containing the file location. 518 separate_output : bool, optional 519 If True, separate the output. Defaults to False. 520 write_metadata : bool, optional 521 If True, write the metadata. Defaults to True. 522 523 """ 524 525 if isinstance(out_file_path, str): 526 out_file_path = Path(out_file_path) 527 528 exportMS = LowResGCMSExport(out_file_path, self) 529 exportMS.to_csv( 530 id_label=id_label, 531 separate_output=separate_output, 532 write_metadata=write_metadata, 533 ) 534 535 return out_file_path.with_suffix(".csv") 536 537 def to_pandas(self, out_file_path, write_metadata=True, id_label="corems:"): 538 """Export the GC-MS data to a Pandas dataframe. 539 540 Parameters 541 ---------- 542 out_file_path : str, pathlib.Path, or s3path.S3Path 543 Path object containing the file location. 544 write_metadata : bool, optional 545 If True, write the metadata. Defaults to True. 546 id_label : str, optional 547 Label of the ID. Defaults to 'corems:'. 548 549 """ 550 551 if isinstance(out_file_path, str): 552 out_file_path = Path(out_file_path) 553 # pickle dataframe (pkl extension) 554 exportMS = LowResGCMSExport(out_file_path, self) 555 exportMS.to_pandas(id_label=id_label, write_metadata=write_metadata) 556 557 return out_file_path.with_suffix(".pkl") 558 559 def to_parquet(self, out_file_path, write_metadata=True, id_label="corems:"): 560 """Export the GC-MS data to a Parquet file. 561 562 Parameters 563 ---------- 564 out_file_path : str, pathlib.Path, or s3path.S3Path 565 Path object containing the file location. 566 write_metadata : bool, optional 567 If True, write the metadata. Defaults to True. 568 id_label : str, optional 569 Label of the ID. Defaults to 'corems:'. 570 571 Notes 572 ----- 573 Requires ``pyarrow`` (or ``fastparquet``) for pandas Parquet I/O. 574 """ 575 576 if isinstance(out_file_path, str): 577 out_file_path = Path(out_file_path) 578 579 exportMS = LowResGCMSExport(out_file_path, self) 580 exportMS.to_parquet(id_label=id_label, write_metadata=write_metadata) 581 582 return out_file_path.with_suffix(".parquet") 583 584 def to_dataframe(self, id_label="corems:"): 585 """Export the GC-MS data to a Pandas dataframe. 586 587 Parameters 588 ---------- 589 id_label : str, optional 590 Label of the ID. Defaults to 'corems:'. 591 592 """ 593 594 # returns pandas dataframe 595 exportMS = LowResGCMSExport(self.sample_name, self) 596 return exportMS.get_pandas_df(id_label=id_label) 597 598 def processing_stats(self): 599 """Return the processing statistics.""" 600 601 # returns json string 602 exportMS = LowResGCMSExport(self.sample_name, self) 603 return exportMS.get_data_stats(self) 604 605 def parameters_json(self, id_label="corems:", output_path=" "): 606 """Return the parameters in JSON format. 607 608 Parameters 609 ---------- 610 id_label : str, optional 611 Label of the ID. Defaults to 'corems:'. 612 output_path : str, optional 613 Path object containing the file location. Defaults to " ". 614 """ 615 616 # returns json string 617 exportMS = LowResGCMSExport(self.sample_name, self) 618 return exportMS.get_parameters_json(self, id_label, output_path) 619 620 def to_json(self, id_label="corems:"): 621 """Export the GC-MS data to a JSON file. 622 623 Parameters 624 ---------- 625 id_label : str, optional 626 Label of the ID. Defaults to 'corems:'. 627 628 """ 629 630 # returns pandas dataframe 631 exportMS = LowResGCMSExport(self.sample_name, self) 632 return exportMS.get_json(id_label=id_label) 633 634 def to_hdf(self, id_label="corems:"): 635 """Export the GC-MS data to a HDF file. 636 637 Parameters 638 ---------- 639 id_label : str, optional 640 Label of the ID. Defaults to 'corems:'. 641 642 """ 643 644 # returns pandas dataframe 645 exportMS = LowResGCMSExport(self.sample_name, self) 646 return exportMS.to_hdf(id_label=id_label) 647 648 def plot_chromatogram(self, ax=None, color="blue"): # pragma: no cover 649 """Plot the chromatogram. 650 651 Parameters 652 ---------- 653 ax : matplotlib.axes.Axes, optional 654 Axes object to plot the chromatogram. Defaults to None. 655 color : str, optional 656 Color of the chromatogram. Defaults to 'blue'. 657 658 """ 659 660 import matplotlib.pyplot as plt 661 662 if ax is None: 663 ax = plt.gca() 664 665 ax.plot(self.retention_time, self.tic, color=color) 666 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 667 668 return ax 669 670 def plot_smoothed_chromatogram(self, ax=None, color="green"): # pragma: no cover 671 """Plot the smoothed chromatogram. 672 673 Parameters 674 ---------- 675 ax : matplotlib.axes.Axes, optional 676 Axes object to plot the smoothed chromatogram. Defaults to None. 677 color : str, optional 678 Color of the smoothed chromatogram. Defaults to 'green'. 679 680 """ 681 682 import matplotlib.pyplot as plt 683 684 if ax is None: 685 ax = plt.gca() 686 687 ax.plot(self.retention_time, self.smooth_tic(self.tic), color=color) 688 689 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 690 691 return ax 692 693 def plot_detected_baseline(self, ax=None, color="blue"): # pragma: no cover 694 """Plot the detected baseline. 695 696 Parameters 697 ---------- 698 ax : matplotlib.axes.Axes, optional 699 Axes object to plot the detected baseline. Defaults to None. 700 color : str, optional 701 Color of the detected baseline. Defaults to 'blue'. 702 703 """ 704 705 import matplotlib.pyplot as plt 706 707 if ax is None: 708 ax = plt.gca() 709 710 max_height = self.chromatogram_settings.peak_height_max_percent 711 max_prominence = self.chromatogram_settings.peak_max_prominence_percent 712 713 baseline = sp.baseline_detector( 714 self.tic, self.retention_time, max_height, max_prominence 715 ) 716 ax.plot(self.retention_time, color=color) 717 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 718 719 return ax 720 721 def plot_baseline_subtraction(self, ax=None, color="black"): # pragma: no cover 722 """Plot the baseline subtraction. 723 724 Parameters 725 ---------- 726 ax : matplotlib.axes.Axes, optional 727 Axes object to plot the baseline subtraction. Defaults to None. 728 color : str, optional 729 Color of the baseline subtraction. Defaults to 'black'. 730 731 """ 732 733 import matplotlib.pyplot as plt 734 735 if ax is None: 736 ax = plt.gca() 737 738 max_height = self.chromatogram_settings.peak_height_max_percent 739 740 max_prominence = self.chromatogram_settings.peak_max_prominence_percent 741 742 x = self.tic + sp.baseline_detector( 743 self.tic, self.retention_time, max_height, max_prominence 744 ) 745 746 ax.plot(self.retention_time, x, color=color) 747 748 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 749 750 return ax 751 752 def peaks_rt_tic(self, json_string=False): 753 """Return the peaks, retention time, and total ion chromatogram. 754 755 Parameters 756 ---------- 757 json_string : bool, optional 758 If True, return the peaks, retention time, and total ion chromatogram in JSON format. Defaults to False. 759 760 """ 761 762 peaks_list = dict() 763 764 all_candidates_data = {} 765 766 all_peaks_data = {} 767 768 for gcms_peak in self.sorted_gcpeaks: 769 dict_data = { 770 "rt": gcms_peak.rt_list, 771 "tic": gcms_peak.tic_list, 772 "mz": gcms_peak.mass_spectrum.mz_exp.tolist(), 773 "abundance": gcms_peak.mass_spectrum.abundance.tolist(), 774 "candidate_names": gcms_peak.compound_names, 775 } 776 777 peaks_list[gcms_peak.retention_time] = dict_data 778 779 for compound in gcms_peak: 780 if compound.name not in all_candidates_data.keys(): 781 mz = array(compound.mz).tolist() 782 abundance = array(compound.abundance).tolist() 783 data = {"mz": mz, "abundance": abundance} 784 all_candidates_data[compound.name] = data 785 786 all_peaks_data["peak_data"] = peaks_list 787 all_peaks_data["ref_data"] = all_candidates_data 788 789 if json_string: 790 return json.dumps(all_peaks_data) 791 792 else: 793 return all_peaks_data 794 795 def plot_processed_chromatogram(self, ax=None, color="black"): 796 """Plot the processed chromatogram. 797 798 Parameters 799 ---------- 800 ax : matplotlib.axes.Axes, optional 801 Axes object to plot the processed chromatogram. Defaults to None. 802 color : str, optional 803 Color of the processed chromatogram. Defaults to 'black'. 804 805 """ 806 807 import matplotlib.pyplot as plt 808 809 if ax is None: 810 ax = plt.gca() 811 812 ax.plot(self.retention_time, self.processed_tic, color=color) 813 814 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 815 816 return ax
Base class for GC-MS data processing.
Parameters
- file_location (str, pathlib.Path, or s3path.S3Path): Path object containing the file location.
- analyzer (str, optional): Name of the analyzer. Defaults to 'Unknown'.
- instrument_label (str, optional): Label of the instrument. Defaults to 'Unknown'.
- sample_name (str, optional): Name of the sample. If not provided, it is derived from the file location.
Attributes
- file_location (pathlib.Path): Path object containing the file location.
- sample_name (str): Name of the sample.
- analyzer (str): Name of the analyzer.
- instrument_label (str): Label of the instrument.
- gcpeaks (list): List of GCPeak objects.
- ri_pairs_ref (None): Reference retention index pairs.
- cal_file_path (None): Calibration file path.
- _parameters (GCMSParameters): GC-MS parameters.
- _retention_time_list (list): List of retention times.
- _scans_number_list (list): List of scan numbers.
- _tic_list (list): List of total ion chromatogram values.
- _ms (dict): Dictionary containing all mass spectra.
- _processed_tic (list): List of processed total ion chromatogram values.
Methods
- process_chromatogram(plot_res=False). Process the chromatogram.
- plot_gc_peaks(ax=None, color='red'). Plot the GC peaks.
70 def __init__( 71 self, 72 file_location, 73 analyzer="Unknown", 74 instrument_label="Unknown", 75 sample_name=None, 76 ): 77 if isinstance(file_location, str): 78 # if obj is a string it defaults to create a Path obj, pass the S3Path if needed 79 file_location = Path(file_location) 80 81 if not file_location.exists(): 82 raise FileExistsError("File does not exist: " + str(file_location)) 83 84 self.file_location = file_location 85 86 if sample_name: 87 self.sample_name = sample_name 88 else: 89 self.sample_name = file_location.stem 90 91 self.analyzer = analyzer 92 self.instrument_label = instrument_label 93 self._init_settings() 94 95 self._retention_time_list = [] 96 self._scans_number_list = [] 97 self._tic_list = [] 98 99 # all scans 100 self._ms = {} 101 102 # after peak detection 103 self._processed_tic = [] 104 self.gcpeaks = [] 105 106 self.ri_pairs_ref = None 107 self.cal_file_path = None
128 def process_chromatogram(self, plot_res=False): 129 """Process the chromatogram. 130 131 This method processes the chromatogram. 132 133 Parameters 134 ---------- 135 plot_res : bool, optional 136 If True, plot the results. Defaults to False. 137 """ 138 139 # tic = self.tic - self.baseline_detector(self.tic) 140 141 self._processed_tic = self.smooth_tic(self.tic) 142 143 for index, tic in enumerate(self._processed_tic): 144 self._ms[index]._processed_tic = tic 145 146 # self.second_derivative_threshold(self._processed_tic) 147 148 if self.chromatogram_settings.use_deconvolution: 149 self.run_deconvolution(plot_res=False) 150 151 else: 152 peaks_index = self.centroid_detector( 153 self._processed_tic, self.retention_time 154 ) 155 156 for i in peaks_index: 157 apex_index = i[1] 158 159 gc_peak = GCPeak(self, self._ms[apex_index], i) 160 161 gc_peak.calc_area(self._processed_tic, 1) 162 163 self.gcpeaks.append(gc_peak) 164 165 # self.gcpeaks[self.scans_number[apex_index]] = gc_peak
Process the chromatogram.
This method processes the chromatogram.
Parameters
- plot_res (bool, optional): If True, plot the results. Defaults to False.
167 def add_mass_spectrum(self, mass_spec): 168 """Add a mass spectrum to the GC-MS object. 169 170 This method adds a mass spectrum to the GC-MS object. 171 172 Parameters 173 ---------- 174 mass_spec : MassSpectrum 175 Mass spectrum to be added. 176 """ 177 178 self._ms[mass_spec.scan_number] = mass_spec
Add a mass spectrum to the GC-MS object.
This method adds a mass spectrum to the GC-MS object.
Parameters
- mass_spec (MassSpectrum): Mass spectrum to be added.
180 def set_tic_list_from_data(self): 181 """Set the total ion chromatogram list from the mass spectra data within the GC-MS data object.""" 182 183 self.tic = [self._ms.get(i).tic for i in self.scans_number] 184 185 # self.set_tic_list([self._ms.get(i).get_sumed_signal_to_noise() for i in self.get_scans_number()])
Set the total ion chromatogram list from the mass spectra data within the GC-MS data object.
187 def set_retention_time_from_data(self): 188 """Set the retention time list from the mass spectra data within the GC-MS data object.""" 189 190 retention_time_list = [] 191 192 for key_ms in sorted(self._ms.keys()): 193 retention_time_list.append(self._ms.get(key_ms).retention_time) 194 195 self.retention_time = retention_time_list 196 197 # self.set_retention_time_list(sorted(self._ms.keys()))
Set the retention time list from the mass spectra data within the GC-MS data object.
199 def set_scans_number_from_data(self): 200 """Set the scan number list from the mass spectra data within the GC-MS data object.""" 201 202 self.scans_number = sorted(self._ms.keys())
Set the scan number list from the mass spectra data within the GC-MS data object.
225 @property 226 def molecular_search_settings(self): 227 """Molecular Search Settings""" 228 return self.parameters.molecular_search
Molecular Search Settings
234 @property 235 def chromatogram_settings(self): 236 """Chromatogram Settings""" 237 return self.parameters.gc_ms
Chromatogram Settings
248 @property 249 def retention_time(self): 250 """Retention Time""" 251 return self._retention_time_list
Retention Time
253 @property 254 def processed_tic(self): 255 """Processed Total Ion Current""" 256 return self._processed_tic
Processed Total Ion Current
263 @property 264 def max_tic(self): 265 """Maximum Total Ion Current""" 266 return max([gc_peak.tic for gc_peak in self])
Maximum Total Ion Current
268 @property 269 def min_tic(self): 270 """Minimum Total Ion Current""" 271 return min([gc_peak.tic for gc_peak in self])
Minimum Total Ion Current
273 @property 274 def dynamic_range(self): 275 """Dynamic Range of the Total Ion Current""" 276 return self.max_tic / self.min_tic
Dynamic Range of the Total Ion Current
278 @property 279 def matched_peaks(self): 280 """Matched Peaks""" 281 return [gc_peak for gc_peak in self if gc_peak]
Matched Peaks
283 @property 284 def sorted_gcpeaks(self): 285 """Sorted GC Peaks, by retention time""" 286 return sorted(self, key=lambda g: g.retention_time)
Sorted GC Peaks, by retention time
288 @property 289 def unique_metabolites(self): 290 """Unique Metabolites""" 291 metabolites = set() 292 for gc_peak in self: 293 if gc_peak: 294 for compound_obj in gc_peak: 295 metabolites.add(compound_obj.name) 296 297 return metabolites
Unique Metabolites
299 @property 300 def metabolites_data(self): 301 """Metabolites Data""" 302 metabolites = {} 303 for gc_peak in self: 304 if gc_peak: 305 for compound_obj in gc_peak: 306 if compound_obj.name in metabolites.keys(): 307 current_score = metabolites[compound_obj.name][ 308 "highest_similarity_score" 309 ] 310 compound_score = compound_obj.spectral_similarity_score 311 metabolites[compound_obj.name]["highest_similarity_score"] = ( 312 compound_score 313 if compound_score > current_score 314 else current_score 315 ) 316 317 else: 318 if compound_obj.metadata: 319 metabolites[compound_obj.name] = { 320 "name": compound_obj.name, 321 "highest_similarity_score": compound_obj.spectral_similarity_score, 322 "casno": compound_obj.metadata.cas, 323 "kegg": compound_obj.metadata.kegg, 324 "inchi": compound_obj.metadata.inchi, 325 "inchi_key": compound_obj.metadata.inchikey, 326 "chebi": compound_obj.metadata.chebi, 327 "smiles": compound_obj.metadata.smiles, 328 } 329 else: 330 metabolites[compound_obj.name] = { 331 "name": compound_obj.name, 332 "highest_similarity_score": compound_obj.spectral_similarity_score, 333 "casno": "", 334 "kegg": "", 335 "inchi": "", 336 "inchikey": "", 337 "chebi": "", 338 "smiles": "", 339 } 340 341 return list(metabolites.values())
Metabolites Data
343 @property 344 def no_matched_peaks(self): 345 """Peaks with no Matched Metabolites""" 346 return [peak for peak in self if not peak]
Peaks with no Matched Metabolites
361 def plot_gc_peaks(self, ax=None, color="red"): # pragma: no cover 362 """Plot the GC peaks. 363 364 This method plots the GC peaks. 365 366 Parameters 367 ---------- 368 ax : matplotlib.axes.Axes, optional 369 Axes object to plot the GC peaks. Defaults to None. 370 color : str, optional 371 Color of the GC peaks. Defaults to 'red'. 372 """ 373 374 import matplotlib.pyplot as plt 375 376 fig = plt.gcf() 377 if ax is None: 378 ax = plt.gca() 379 380 max_rts = [gc_peak.mass_spectrum.retention_time for gc_peak in self] 381 max_tics = [gc_peak.mass_spectrum.tic for gc_peak in self] 382 383 # min_rts = [self._ms[gc_peak.start_index].retention_time for gc_peak in self] + [self._ms[gc_peak.final_index].retention_time for gc_peak in self] 384 # min_tics = [self._ms[gc_peak.start_index].tic for gc_peak in self] + [self._ms[gc_peak.final_index].tic for gc_peak in self] 385 # sc = ax.scatter(min_rts, min_tics, color='yellow', linewidth=0, marker='v') 386 387 sc = ax.scatter(max_rts, max_tics, color=color, marker="v") 388 389 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 390 391 annot = ax.annotate( 392 "", 393 xy=(0, 0), 394 xytext=(20, 20), 395 textcoords="offset points", 396 bbox=dict(boxstyle="round", fc="w"), 397 arrowprops=dict(arrowstyle="->"), 398 ) 399 annot.set_visible(False) 400 annot.get_bbox_patch().set_facecolor(("lightblue")) 401 annot.get_bbox_patch().set_alpha(0.8) 402 403 def update_annot(ind): 404 pos = sc.get_offsets()[ind["ind"][0]] 405 annot.xy = pos 406 407 text = "RT: {}\nRT Ref: {}\nRI: {}\nRI Ref: {}\nSimilarity Score: {}\nName: {}".format( 408 " ".join([str(round(self[n].retention_time, 2)) for n in ind["ind"]]), 409 " ".join( 410 [ 411 str( 412 round(self[n].highest_score_compound.retention_time, 2) 413 if self[n].highest_score_compound 414 else None 415 ) 416 for n in ind["ind"] 417 ] 418 ), 419 " ".join( 420 [ 421 str(round(self[n].ri, 2) if self[n].ri else None) 422 for n in ind["ind"] 423 ] 424 ), 425 " ".join( 426 [ 427 str( 428 round(self[n].highest_score_compound.ri, 2) 429 if self[n].highest_score_compound 430 else None 431 ) 432 for n in ind["ind"] 433 ] 434 ), 435 " ".join( 436 [ 437 str( 438 round(self[n].highest_score_compound.similarity_score, 4) 439 if self[n].highest_score_compound 440 else None 441 ) 442 for n in ind["ind"] 443 ] 444 ), 445 " ".join( 446 [ 447 str( 448 self[n].highest_score_compound.name 449 if self[n].highest_score_compound 450 else None 451 ) 452 for n in ind["ind"] 453 ] 454 ), 455 ) 456 annot.set_text(text) 457 458 def hover(event): 459 vis = annot.get_visible() 460 if event.inaxes == ax: 461 cont, ind = sc.contains(event) 462 if cont: 463 update_annot(ind) 464 annot.set_visible(True) 465 fig.canvas.draw_idle() 466 else: 467 if vis: 468 annot.set_visible(False) 469 fig.canvas.draw_idle() 470 471 fig.canvas.mpl_connect("motion_notify_event", hover) 472 473 return ax
Plot the GC peaks.
This method plots the GC peaks.
Parameters
- ax (matplotlib.axes.Axes, optional): Axes object to plot the GC peaks. Defaults to None.
- color (str, optional): Color of the GC peaks. Defaults to 'red'.
475 def to_excel( 476 self, out_file_path, write_mode="ab", write_metadata=True, id_label="corems:" 477 ): 478 """Export the GC-MS data to an Excel file. 479 480 This method exports the GC-MS data to an Excel file. 481 482 Parameters 483 ---------- 484 out_file_path : str, pathlib.Path, or s3path.S3Path 485 Path object containing the file location. 486 write_mode : str, optional 487 Write mode. Defaults to 'ab'. 488 write_metadata : bool, optional 489 If True, write the metadata. Defaults to True. 490 id_label : str, optional 491 Label of the ID. Defaults to 'corems:'. 492 493 """ 494 495 if isinstance(out_file_path, str): 496 out_file_path = Path(out_file_path) 497 498 exportMS = LowResGCMSExport(out_file_path, self) 499 exportMS.to_excel( 500 id_label=id_label, write_mode=write_mode, write_metadata=write_metadata 501 ) 502 503 return out_file_path.with_suffix(".xlsx")
Export the GC-MS data to an Excel file.
This method exports the GC-MS data to an Excel file.
Parameters
- out_file_path (str, pathlib.Path, or s3path.S3Path): Path object containing the file location.
- write_mode (str, optional): Write mode. Defaults to 'ab'.
- write_metadata (bool, optional): If True, write the metadata. Defaults to True.
- id_label (str, optional): Label of the ID. Defaults to 'corems:'.
505 def to_csv( 506 self, 507 out_file_path, 508 separate_output=False, 509 write_metadata=True, 510 id_label="corems:", 511 ): 512 """Export the GC-MS data to a CSV file. 513 514 Parameters 515 ---------- 516 out_file_path : str, pathlib.Path, or s3path.S3Path 517 Path object containing the file location. 518 separate_output : bool, optional 519 If True, separate the output. Defaults to False. 520 write_metadata : bool, optional 521 If True, write the metadata. Defaults to True. 522 523 """ 524 525 if isinstance(out_file_path, str): 526 out_file_path = Path(out_file_path) 527 528 exportMS = LowResGCMSExport(out_file_path, self) 529 exportMS.to_csv( 530 id_label=id_label, 531 separate_output=separate_output, 532 write_metadata=write_metadata, 533 ) 534 535 return out_file_path.with_suffix(".csv")
Export the GC-MS data to a CSV file.
Parameters
- out_file_path (str, pathlib.Path, or s3path.S3Path): Path object containing the file location.
- separate_output (bool, optional): If True, separate the output. Defaults to False.
- write_metadata (bool, optional): If True, write the metadata. Defaults to True.
537 def to_pandas(self, out_file_path, write_metadata=True, id_label="corems:"): 538 """Export the GC-MS data to a Pandas dataframe. 539 540 Parameters 541 ---------- 542 out_file_path : str, pathlib.Path, or s3path.S3Path 543 Path object containing the file location. 544 write_metadata : bool, optional 545 If True, write the metadata. Defaults to True. 546 id_label : str, optional 547 Label of the ID. Defaults to 'corems:'. 548 549 """ 550 551 if isinstance(out_file_path, str): 552 out_file_path = Path(out_file_path) 553 # pickle dataframe (pkl extension) 554 exportMS = LowResGCMSExport(out_file_path, self) 555 exportMS.to_pandas(id_label=id_label, write_metadata=write_metadata) 556 557 return out_file_path.with_suffix(".pkl")
Export the GC-MS data to a Pandas dataframe.
Parameters
- out_file_path (str, pathlib.Path, or s3path.S3Path): Path object containing the file location.
- write_metadata (bool, optional): If True, write the metadata. Defaults to True.
- id_label (str, optional): Label of the ID. Defaults to 'corems:'.
559 def to_parquet(self, out_file_path, write_metadata=True, id_label="corems:"): 560 """Export the GC-MS data to a Parquet file. 561 562 Parameters 563 ---------- 564 out_file_path : str, pathlib.Path, or s3path.S3Path 565 Path object containing the file location. 566 write_metadata : bool, optional 567 If True, write the metadata. Defaults to True. 568 id_label : str, optional 569 Label of the ID. Defaults to 'corems:'. 570 571 Notes 572 ----- 573 Requires ``pyarrow`` (or ``fastparquet``) for pandas Parquet I/O. 574 """ 575 576 if isinstance(out_file_path, str): 577 out_file_path = Path(out_file_path) 578 579 exportMS = LowResGCMSExport(out_file_path, self) 580 exportMS.to_parquet(id_label=id_label, write_metadata=write_metadata) 581 582 return out_file_path.with_suffix(".parquet")
Export the GC-MS data to a Parquet file.
Parameters
- out_file_path (str, pathlib.Path, or s3path.S3Path): Path object containing the file location.
- write_metadata (bool, optional): If True, write the metadata. Defaults to True.
- id_label (str, optional): Label of the ID. Defaults to 'corems:'.
Notes
Requires pyarrow (or fastparquet) for pandas Parquet I/O.
584 def to_dataframe(self, id_label="corems:"): 585 """Export the GC-MS data to a Pandas dataframe. 586 587 Parameters 588 ---------- 589 id_label : str, optional 590 Label of the ID. Defaults to 'corems:'. 591 592 """ 593 594 # returns pandas dataframe 595 exportMS = LowResGCMSExport(self.sample_name, self) 596 return exportMS.get_pandas_df(id_label=id_label)
Export the GC-MS data to a Pandas dataframe.
Parameters
- id_label (str, optional): Label of the ID. Defaults to 'corems:'.
598 def processing_stats(self): 599 """Return the processing statistics.""" 600 601 # returns json string 602 exportMS = LowResGCMSExport(self.sample_name, self) 603 return exportMS.get_data_stats(self)
Return the processing statistics.
605 def parameters_json(self, id_label="corems:", output_path=" "): 606 """Return the parameters in JSON format. 607 608 Parameters 609 ---------- 610 id_label : str, optional 611 Label of the ID. Defaults to 'corems:'. 612 output_path : str, optional 613 Path object containing the file location. Defaults to " ". 614 """ 615 616 # returns json string 617 exportMS = LowResGCMSExport(self.sample_name, self) 618 return exportMS.get_parameters_json(self, id_label, output_path)
Return the parameters in JSON format.
Parameters
- id_label (str, optional): Label of the ID. Defaults to 'corems:'.
- output_path (str, optional): Path object containing the file location. Defaults to " ".
620 def to_json(self, id_label="corems:"): 621 """Export the GC-MS data to a JSON file. 622 623 Parameters 624 ---------- 625 id_label : str, optional 626 Label of the ID. Defaults to 'corems:'. 627 628 """ 629 630 # returns pandas dataframe 631 exportMS = LowResGCMSExport(self.sample_name, self) 632 return exportMS.get_json(id_label=id_label)
Export the GC-MS data to a JSON file.
Parameters
- id_label (str, optional): Label of the ID. Defaults to 'corems:'.
634 def to_hdf(self, id_label="corems:"): 635 """Export the GC-MS data to a HDF file. 636 637 Parameters 638 ---------- 639 id_label : str, optional 640 Label of the ID. Defaults to 'corems:'. 641 642 """ 643 644 # returns pandas dataframe 645 exportMS = LowResGCMSExport(self.sample_name, self) 646 return exportMS.to_hdf(id_label=id_label)
Export the GC-MS data to a HDF file.
Parameters
- id_label (str, optional): Label of the ID. Defaults to 'corems:'.
648 def plot_chromatogram(self, ax=None, color="blue"): # pragma: no cover 649 """Plot the chromatogram. 650 651 Parameters 652 ---------- 653 ax : matplotlib.axes.Axes, optional 654 Axes object to plot the chromatogram. Defaults to None. 655 color : str, optional 656 Color of the chromatogram. Defaults to 'blue'. 657 658 """ 659 660 import matplotlib.pyplot as plt 661 662 if ax is None: 663 ax = plt.gca() 664 665 ax.plot(self.retention_time, self.tic, color=color) 666 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 667 668 return ax
Plot the chromatogram.
Parameters
- ax (matplotlib.axes.Axes, optional): Axes object to plot the chromatogram. Defaults to None.
- color (str, optional): Color of the chromatogram. Defaults to 'blue'.
670 def plot_smoothed_chromatogram(self, ax=None, color="green"): # pragma: no cover 671 """Plot the smoothed chromatogram. 672 673 Parameters 674 ---------- 675 ax : matplotlib.axes.Axes, optional 676 Axes object to plot the smoothed chromatogram. Defaults to None. 677 color : str, optional 678 Color of the smoothed chromatogram. Defaults to 'green'. 679 680 """ 681 682 import matplotlib.pyplot as plt 683 684 if ax is None: 685 ax = plt.gca() 686 687 ax.plot(self.retention_time, self.smooth_tic(self.tic), color=color) 688 689 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 690 691 return ax
Plot the smoothed chromatogram.
Parameters
- ax (matplotlib.axes.Axes, optional): Axes object to plot the smoothed chromatogram. Defaults to None.
- color (str, optional): Color of the smoothed chromatogram. Defaults to 'green'.
693 def plot_detected_baseline(self, ax=None, color="blue"): # pragma: no cover 694 """Plot the detected baseline. 695 696 Parameters 697 ---------- 698 ax : matplotlib.axes.Axes, optional 699 Axes object to plot the detected baseline. Defaults to None. 700 color : str, optional 701 Color of the detected baseline. Defaults to 'blue'. 702 703 """ 704 705 import matplotlib.pyplot as plt 706 707 if ax is None: 708 ax = plt.gca() 709 710 max_height = self.chromatogram_settings.peak_height_max_percent 711 max_prominence = self.chromatogram_settings.peak_max_prominence_percent 712 713 baseline = sp.baseline_detector( 714 self.tic, self.retention_time, max_height, max_prominence 715 ) 716 ax.plot(self.retention_time, color=color) 717 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 718 719 return ax
Plot the detected baseline.
Parameters
- ax (matplotlib.axes.Axes, optional): Axes object to plot the detected baseline. Defaults to None.
- color (str, optional): Color of the detected baseline. Defaults to 'blue'.
721 def plot_baseline_subtraction(self, ax=None, color="black"): # pragma: no cover 722 """Plot the baseline subtraction. 723 724 Parameters 725 ---------- 726 ax : matplotlib.axes.Axes, optional 727 Axes object to plot the baseline subtraction. Defaults to None. 728 color : str, optional 729 Color of the baseline subtraction. Defaults to 'black'. 730 731 """ 732 733 import matplotlib.pyplot as plt 734 735 if ax is None: 736 ax = plt.gca() 737 738 max_height = self.chromatogram_settings.peak_height_max_percent 739 740 max_prominence = self.chromatogram_settings.peak_max_prominence_percent 741 742 x = self.tic + sp.baseline_detector( 743 self.tic, self.retention_time, max_height, max_prominence 744 ) 745 746 ax.plot(self.retention_time, x, color=color) 747 748 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 749 750 return ax
Plot the baseline subtraction.
Parameters
- ax (matplotlib.axes.Axes, optional): Axes object to plot the baseline subtraction. Defaults to None.
- color (str, optional): Color of the baseline subtraction. Defaults to 'black'.
752 def peaks_rt_tic(self, json_string=False): 753 """Return the peaks, retention time, and total ion chromatogram. 754 755 Parameters 756 ---------- 757 json_string : bool, optional 758 If True, return the peaks, retention time, and total ion chromatogram in JSON format. Defaults to False. 759 760 """ 761 762 peaks_list = dict() 763 764 all_candidates_data = {} 765 766 all_peaks_data = {} 767 768 for gcms_peak in self.sorted_gcpeaks: 769 dict_data = { 770 "rt": gcms_peak.rt_list, 771 "tic": gcms_peak.tic_list, 772 "mz": gcms_peak.mass_spectrum.mz_exp.tolist(), 773 "abundance": gcms_peak.mass_spectrum.abundance.tolist(), 774 "candidate_names": gcms_peak.compound_names, 775 } 776 777 peaks_list[gcms_peak.retention_time] = dict_data 778 779 for compound in gcms_peak: 780 if compound.name not in all_candidates_data.keys(): 781 mz = array(compound.mz).tolist() 782 abundance = array(compound.abundance).tolist() 783 data = {"mz": mz, "abundance": abundance} 784 all_candidates_data[compound.name] = data 785 786 all_peaks_data["peak_data"] = peaks_list 787 all_peaks_data["ref_data"] = all_candidates_data 788 789 if json_string: 790 return json.dumps(all_peaks_data) 791 792 else: 793 return all_peaks_data
Return the peaks, retention time, and total ion chromatogram.
Parameters
- json_string (bool, optional): If True, return the peaks, retention time, and total ion chromatogram in JSON format. Defaults to False.
795 def plot_processed_chromatogram(self, ax=None, color="black"): 796 """Plot the processed chromatogram. 797 798 Parameters 799 ---------- 800 ax : matplotlib.axes.Axes, optional 801 Axes object to plot the processed chromatogram. Defaults to None. 802 color : str, optional 803 Color of the processed chromatogram. Defaults to 'black'. 804 805 """ 806 807 import matplotlib.pyplot as plt 808 809 if ax is None: 810 ax = plt.gca() 811 812 ax.plot(self.retention_time, self.processed_tic, color=color) 813 814 ax.set(xlabel="Retention Time (s)", ylabel="Total Ion Chromatogram") 815 816 return ax
Plot the processed chromatogram.
Parameters
- ax (matplotlib.axes.Axes, optional): Axes object to plot the processed chromatogram. Defaults to None.
- color (str, optional): Color of the processed chromatogram. Defaults to 'black'.