From adc21f3276bbf87521f57a4fbef4c84eb326ce4e Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Tue, 3 May 2022 18:41:54 -0400 Subject: [PATCH 01/12] added peakfinding utility --- efxtools/realspace/__init__.py | 0 efxtools/realspace/find_peaks.py | 235 +++++++++++++++++++++++++++++++ setup.py | 1 + 3 files changed, 236 insertions(+) create mode 100644 efxtools/realspace/__init__.py create mode 100644 efxtools/realspace/find_peaks.py diff --git a/efxtools/realspace/__init__.py b/efxtools/realspace/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py new file mode 100644 index 0000000..8dbf381 --- /dev/null +++ b/efxtools/realspace/find_peaks.py @@ -0,0 +1,235 @@ +import warnings +import pandas as pd +import numpy as np +import gemmi + + +def peak_report( + structure, + grid, + sigma_cutoff, + min_volume = 0., + min_score = 0., + min_peak = 0., + distance_cutoff = 4., + use_long_names = False, + negate=False, + ): + """ + Build a report summarizing peaks in a map which are in the vicinity of atoms in the structure. + + For example, + + ```python + structure = gemmi.read_pdb(pdb_file_name) + mtz = gemmi.read_mtz_file(mtz_file_name) + grid = mtz.transform_f_phi_to_map( + "ANOM", "PHANOM", sample_rate=3.0 + ) + + report = peak_report( + structure, grid, + sigma_cutoff=10., + ) + ``` + will find peaks in an anomalous difference map above 10 sigma. + + For difference maps, it might make sense to use a pattern such as, + + ```python + report = peak_report(structure, grid, sigma_cutoff=3.5), + report = pd.concat(( + report, + peak_report(structure, grid, sigma_cutoff=3.5, negate=True), + )) + ``` + which will find positive and negative difference map peaks above + 3.5 sigma and concatenate them into the same report. + + + Parameters + ---------- + structure : gemmi.Structure + The structure which will be searched for atoms near the electron density peaks. + grid : gemmi.FloatGrid + This is an electron density map in the form of a gemmi.FloatGrid instance. + sigma_cutoff : float + The z-score cutoff at which pixels are thresholded for peak finding. + min_volume : float (optional) + The minimum volume of peaks which defaults to zero. + min_score : float (optional) + The minimum score of peaks which defaults to zero. See gemmi.find_blobs_by_flood_fill + min_peak : float (optional) + The minimum peak height of peaks which defaults to zero. See gemmi.find_blobs_by_flood_fill + distance_cutoff : float (optional) + This is the radius around atoms within which peaks will be kept. The default is 4 Angstroms. + Making this number large may impact performance. + use_log_names : bool (optional) + Optionally use more descriptive column names for the report. These may contain characters that + make them less pleasant to work with in pandas. The default is False. + negate : bool (optional) + Optionally find peaks in the negative electron density. This can be useful for difference maps. + The default is False. + + Returns + ------- + peak_report : pd.DataFrame + A dataframe summarizing the locations of found peaks and how they correspond to atoms in the structure. + """ + + if len(structure) > 1: + warnings.warn( + f"Multi-model PDBs are not supported. Using first model from file {pdb_file}.", + UserWarning + ) + + cell = structure.cell + model = structure[0] + + #Compute z-score cutoff + mean,sigma = np.mean(grid),np.std(grid) + cutoff = mean + sigma_cutoff * sigma + + #In gemmi peaks are blobs. So it goes. + #This returns a list of `gemmi.Blob` objects + blobs = gemmi.find_blobs_by_flood_fill( + grid, + cutoff=cutoff, + min_volume=min_volume, + min_score=min_score, + min_peak=min_peak, + negate=negate, + ) + + #This neighbor search object can find the atoms closest to query positions + ns = gemmi.NeighborSearch(model, structure.cell, distance_cutoff).populate() + + peaks = [] + for blob in blobs: + #This is a list of weird pointer objects. It is safest to convert them `gemmi.CRA` objects (see below) + marks = ns.find_atoms(blob.centroid) + if len(marks) == 0: + continue + + cra = dist = None + for mark in marks: + image_idx = mark.image_idx + _cra = mark.to_cra(model) + _dist = cell.find_nearest_pbc_image(blob.centroid, _cra.atom.pos, mark.image_idx).dist() + if cra is None: + dist = _dist + cra = _cra + elif _dist < dist: + dist = _dist + cra = _cra + + record = { + "chain" : cra.chain.name, + "seqid" : cra.residue.seqid.num, + "residue" : cra.residue.name, + "atom" : cra.atom.name, + "dist" : dist, + "peak" : blob.peak_value, + "peakz" : (blob.peak_value-mean)/sigma, + "score" : blob.score, + "scorez" : (blob.score-mean)/sigma, + "cenx" : blob.centroid.x, + "ceny" : blob.centroid.y, + "cenz" : blob.centroid.x, + "coordx" : cra.atom.pos.x, + "coordy" : cra.atom.pos.y, + "coordz" : cra.atom.pos.z, + } + if negate: + negative_keys = ['peak', 'peakz', 'score', 'scorez'] + for k in negative_keys: + record[k] = -record[k] + peaks.append(record) + + long_names = { + "chain" : "Chain", + "seqid" : "SeqID", + "residue" : "Residue", + "name" : "Atom Name", + "dist" : "Dist (Å)", + "peak" : "Peak Value", + "peakz" : "Peak Value (Z-score)", + "score" : "Peak Score", + "scorez" : "Peak Score (Z-score)", + "cenx" : "Centroid (x)", + "ceny" : "Centroid (y)", + "cenz" : "Centroid (z)", + "coordx" : "Coord (x)", + "coordy" : "Coord (y)", + "coordz" : "Coord (z)", + } + + out = pd.DataFrame.from_records(peaks) + + if use_long_names: + out.rename(columns = long_names) + return out + +def parse_args(): + from argparse import ArgumentParser + + program_description = """ + Search an electron density maps for + peaks in the vicinity of a structure. + """ + parser = ArgumentParser(description=program_description) + + # Required / Common options + parser.add_argument("-f", "--structure-factor-key", type=str, + required=True, help="column label of the structure factor you want to use.") + parser.add_argument("-p", "--phase-key", type=str, + required=True, help="column label of the phase you want to use.") + parser.add_argument("mtz_file") + parser.add_argument("pdb_file") + parser.add_argument("-o", "--csv-out", type=str, default=None, help="output the report to a csv file") + parser.add_argument("-z", "--sigma-cutoff", required=True, type=float, + help="the z-score cutoff for voxels to be included in the peak search.") + parser.add_argument("-d", "--difference-map", action='store_true', + help="search for negative peaks as well as positive.") + + # More esoteric options + parser.add_argument("--sample-rate", type=float, default=3., + help="change fft oversampling from the default (3).") + parser.add_argument("--min-volume", type=float, default=0., + help="the minimum volume of peaks in voxels with default zero.") + parser.add_argument("--min-score", type=float, default=0., + help="the minimum score of peaks with default zero.") + parser.add_argument("--min-peak", type=float, default=0., + help="the minimum peak value with default zero.") + parser.add_argument("--distance-cutoff", type=float, default=4., + help="the distance cutoff of nearest neighbor search with default of 4 angstroms.") + parser.add_argument("--use-long-names", action='store_true', + help="use more verbose column names in the peak report.") + parser = parser.parse_args() + return parser + +def main(): + parser = parse_args() + structure = gemmi.read_pdb(parser.pdb_file) + mtz = gemmi.read_mtz_file(parser.mtz_file) + grid = mtz.transform_f_phi_to_map( + parser.structure_factor_key, parser.phase_key, sample_rate=parser.sample_rate + ) + + out = peak_report( + structure, grid, + sigma_cutoff=parser.sigma_cutoff, + ) + if parser.difference_map: + out = pd.concat(( + out, + peak_report(structure, grid, sigma_cutoff=parser.sigma_cutoff, negate=True), + )) + + if parser.csv_out is not None: + out.to_csv(parser.csv_out) + + print(out.to_csv()) + +if __name__=="__main__": + main() diff --git a/setup.py b/setup.py index bfbed27..91325d7 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,7 @@ "efxtools.ccpred=efxtools.stats.ccpred:main", "efxtools.diffmap=efxtools.diffmaps.diffmap:main", "efxtools.precog2mtz=efxtools.io.precog2mtz:main", + "efxtools.findpeaks=efxtools.realspace.find_peaks:main", ] }, ) From 75d07f66299d97f4a176eba114b4795f0dca2990 Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Wed, 4 May 2022 09:55:43 -0400 Subject: [PATCH 02/12] fix typo --- efxtools/realspace/find_peaks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index 8dbf381..5bc61c9 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -174,7 +174,7 @@ def parse_args(): from argparse import ArgumentParser program_description = """ - Search an electron density maps for + Search an electron density map for peaks in the vicinity of a structure. """ parser = ArgumentParser(description=program_description) From 822189fdb08090ae2b2166f567f16f4c7e237811 Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Wed, 4 May 2022 10:32:05 -0400 Subject: [PATCH 03/12] added option for map weights --- efxtools/realspace/find_peaks.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index 5bc61c9..ff9c9c5 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -1,5 +1,6 @@ import warnings import pandas as pd +import reciprocalspaceship as rs import numpy as np import gemmi @@ -191,6 +192,8 @@ def parse_args(): help="the z-score cutoff for voxels to be included in the peak search.") parser.add_argument("-d", "--difference-map", action='store_true', help="search for negative peaks as well as positive.") + parser.add_argument("-w", "--weight-key", type=str, + required=False, default=None, help="column label of any weights you wish to apply to the map.") # More esoteric options parser.add_argument("--sample-rate", type=float, default=3., @@ -211,7 +214,16 @@ def parse_args(): def main(): parser = parse_args() structure = gemmi.read_pdb(parser.pdb_file) - mtz = gemmi.read_mtz_file(parser.mtz_file) + ds = rs.read_mtz(parser.mtz_file) + mtz = ds[[parser.phase_key]].copy() + + if parser.weight_key is not None: + mtz[parser.structure_factor_key] = ds[parser.structure_factor_key] * ds[parser.weight_key] + else: + mtz[parser.structure_factor_key] = ds[parser.structure_factor_key] + + mtz = mtz.to_gemmi() + grid = mtz.transform_f_phi_to_map( parser.structure_factor_key, parser.phase_key, sample_rate=parser.sample_rate ) From b6799b689f0802868e7d14965c6ee69700c6fb87 Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Thu, 5 May 2022 13:19:27 -0400 Subject: [PATCH 04/12] add separate entry point for diff maps peaks --- efxtools/realspace/find_peaks.py | 10 +++++++--- setup.py | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index ff9c9c5..6b860e1 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -190,8 +190,6 @@ def parse_args(): parser.add_argument("-o", "--csv-out", type=str, default=None, help="output the report to a csv file") parser.add_argument("-z", "--sigma-cutoff", required=True, type=float, help="the z-score cutoff for voxels to be included in the peak search.") - parser.add_argument("-d", "--difference-map", action='store_true', - help="search for negative peaks as well as positive.") parser.add_argument("-w", "--weight-key", type=str, required=False, default=None, help="column label of any weights you wish to apply to the map.") @@ -211,7 +209,13 @@ def parse_args(): parser = parser.parse_args() return parser -def main(): +def find_peaks(): + main(difference_map=False) + +def find_difference_peaks(): + main(difference_map=True) + +def main(difference_map=False): parser = parse_args() structure = gemmi.read_pdb(parser.pdb_file) ds = rs.read_mtz(parser.mtz_file) diff --git a/setup.py b/setup.py index 91325d7..0f0d4d9 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,8 @@ "efxtools.ccpred=efxtools.stats.ccpred:main", "efxtools.diffmap=efxtools.diffmaps.diffmap:main", "efxtools.precog2mtz=efxtools.io.precog2mtz:main", - "efxtools.findpeaks=efxtools.realspace.find_peaks:main", + "efxtools.find_peaks=efxtools.realspace.find_peaks:find_peaks", + "efxtools.find_difference_peaks=efxtools.realspace.find_peaks:find_difference_peaks", ] }, ) From 591265b046960706f68614659e023f958787f537 Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Thu, 5 May 2022 13:24:54 -0400 Subject: [PATCH 05/12] sort outpute by `peakz` --- efxtools/realspace/find_peaks.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index 6b860e1..8bd5e6f 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -15,6 +15,7 @@ def peak_report( distance_cutoff = 4., use_long_names = False, negate=False, + sort_by_key='peakz', ): """ Build a report summarizing peaks in a map which are in the vicinity of atoms in the structure. @@ -71,6 +72,8 @@ def peak_report( negate : bool (optional) Optionally find peaks in the negative electron density. This can be useful for difference maps. The default is False. + sort_by_key : str (optional) + Sort report by values in this column. the "peakz" column is used by default. Returns ------- @@ -166,6 +169,7 @@ def peak_report( } out = pd.DataFrame.from_records(peaks) + out = out.sort_values(sort_by_key) if use_long_names: out.rename(columns = long_names) From f2941e43198e18c78c63998878ee39b5b534e8c0 Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Thu, 5 May 2022 13:25:13 -0400 Subject: [PATCH 06/12] fix obsolete parser reference --- efxtools/realspace/find_peaks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index 8bd5e6f..5ca681f 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -240,7 +240,7 @@ def main(difference_map=False): structure, grid, sigma_cutoff=parser.sigma_cutoff, ) - if parser.difference_map: + if difference_map: out = pd.concat(( out, peak_report(structure, grid, sigma_cutoff=parser.sigma_cutoff, negate=True), From 2f16522b6dc33fbe2f5a776fc1b9d90e4a966052 Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Thu, 5 May 2022 13:28:58 -0400 Subject: [PATCH 07/12] fix sort for empty results --- efxtools/realspace/find_peaks.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index 5ca681f..a75543b 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -169,7 +169,10 @@ def peak_report( } out = pd.DataFrame.from_records(peaks) - out = out.sort_values(sort_by_key) + + #In case there are no peaks we need to test the length + if len(out) > 0: + out = out.sort_values(sort_by_key, ascending=False) if use_long_names: out.rename(columns = long_names) From 231628123873dc83fa7795626cffc585d8646052 Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Thu, 5 May 2022 13:29:50 -0400 Subject: [PATCH 08/12] add -d as alternate to --distance-cutoff --- efxtools/realspace/find_peaks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index a75543b..516d30f 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -209,7 +209,7 @@ def parse_args(): help="the minimum score of peaks with default zero.") parser.add_argument("--min-peak", type=float, default=0., help="the minimum peak value with default zero.") - parser.add_argument("--distance-cutoff", type=float, default=4., + parser.add_argument("-d", "--distance-cutoff", type=float, default=4., help="the distance cutoff of nearest neighbor search with default of 4 angstroms.") parser.add_argument("--use-long-names", action='store_true', help="use more verbose column names in the peak report.") From 8bc77b471cf526be169e62a914ddbe56d15131b8 Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Thu, 5 May 2022 13:32:56 -0400 Subject: [PATCH 09/12] move z-scores up in columns --- efxtools/realspace/find_peaks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index 516d30f..b42d362 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -133,10 +133,10 @@ def peak_report( "residue" : cra.residue.name, "atom" : cra.atom.name, "dist" : dist, - "peak" : blob.peak_value, "peakz" : (blob.peak_value-mean)/sigma, - "score" : blob.score, "scorez" : (blob.score-mean)/sigma, + "peak" : blob.peak_value, + "score" : blob.score, "cenx" : blob.centroid.x, "ceny" : blob.centroid.y, "cenz" : blob.centroid.x, From 322ac099d1c216abedd26c7188cf333def6a3e83 Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Thu, 5 May 2022 13:37:42 -0400 Subject: [PATCH 10/12] add default sigma cutoff 1.5/3.0 regular/diff maps --- efxtools/realspace/find_peaks.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index b42d362..3cf4bad 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -178,7 +178,7 @@ def peak_report( out.rename(columns = long_names) return out -def parse_args(): +def parse_args(default_sigma_cutoff=1.5): from argparse import ArgumentParser program_description = """ @@ -195,8 +195,8 @@ def parse_args(): parser.add_argument("mtz_file") parser.add_argument("pdb_file") parser.add_argument("-o", "--csv-out", type=str, default=None, help="output the report to a csv file") - parser.add_argument("-z", "--sigma-cutoff", required=True, type=float, - help="the z-score cutoff for voxels to be included in the peak search.") + parser.add_argument("-z", "--sigma-cutoff", required=False, default=default_sigma_cutoff, type=float, + help=f"the z-score cutoff for voxels to be included in the peak search. the default is {default_sigma_cutoff}") parser.add_argument("-w", "--weight-key", type=str, required=False, default=None, help="column label of any weights you wish to apply to the map.") @@ -217,13 +217,13 @@ def parse_args(): return parser def find_peaks(): - main(difference_map=False) + main(difference_map=False, default_sigma_cutoff=1.5) def find_difference_peaks(): - main(difference_map=True) + main(difference_map=True, default_sigma_cutoff=3.0) -def main(difference_map=False): - parser = parse_args() +def main(difference_map=False, default_sigma_cutoff=1.5): + parser = parse_args(default_sigma_cutoff) structure = gemmi.read_pdb(parser.pdb_file) ds = rs.read_mtz(parser.mtz_file) mtz = ds[[parser.phase_key]].copy() From 442a87e36802b2ebbcb5ab1f750f9065e5d23c7c Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Thu, 5 May 2022 14:00:00 -0400 Subject: [PATCH 11/12] fixes for broken parse args + sort by abs peakz --- efxtools/realspace/find_peaks.py | 69 +++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index 3cf4bad..14e49d6 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -5,6 +5,26 @@ import gemmi + +long_names = { + "chain" : "Chain", + "seqid" : "SeqID", + "residue" : "Residue", + "name" : "Atom Name", + "dist" : "Dist (Å)", + "peak" : "Peak Value", + "peakz" : "Peak Value (Z-score)", + "score" : "Peak Score", + "scorez" : "Peak Score (Z-score)", + "cenx" : "Centroid (x)", + "ceny" : "Centroid (y)", + "cenz" : "Centroid (z)", + "coordx" : "Coord (x)", + "coordy" : "Coord (y)", + "coordz" : "Coord (z)", +} + + def peak_report( structure, grid, @@ -150,24 +170,6 @@ def peak_report( record[k] = -record[k] peaks.append(record) - long_names = { - "chain" : "Chain", - "seqid" : "SeqID", - "residue" : "Residue", - "name" : "Atom Name", - "dist" : "Dist (Å)", - "peak" : "Peak Value", - "peakz" : "Peak Value (Z-score)", - "score" : "Peak Score", - "scorez" : "Peak Score (Z-score)", - "cenx" : "Centroid (x)", - "ceny" : "Centroid (y)", - "cenz" : "Centroid (z)", - "coordx" : "Coord (x)", - "coordy" : "Coord (y)", - "coordz" : "Coord (z)", - } - out = pd.DataFrame.from_records(peaks) #In case there are no peaks we need to test the length @@ -175,7 +177,7 @@ def peak_report( out = out.sort_values(sort_by_key, ascending=False) if use_long_names: - out.rename(columns = long_names) + out = out.rename(columns = long_names) return out def parse_args(default_sigma_cutoff=1.5): @@ -204,7 +206,7 @@ def parse_args(default_sigma_cutoff=1.5): parser.add_argument("--sample-rate", type=float, default=3., help="change fft oversampling from the default (3).") parser.add_argument("--min-volume", type=float, default=0., - help="the minimum volume of peaks in voxels with default zero.") + help="the minimum volume of peaks with default zero.") parser.add_argument("--min-score", type=float, default=0., help="the minimum score of peaks with default zero.") parser.add_argument("--min-peak", type=float, default=0., @@ -242,12 +244,31 @@ def main(difference_map=False, default_sigma_cutoff=1.5): out = peak_report( structure, grid, sigma_cutoff=parser.sigma_cutoff, + min_volume = parser.min_volume, + min_score = parser.min_score, + min_peak = parser.min_peak, + distance_cutoff = parser.distance_cutoff, + use_long_names = parser.use_long_names, + negate=False, ) if difference_map: - out = pd.concat(( - out, - peak_report(structure, grid, sigma_cutoff=parser.sigma_cutoff, negate=True), - )) + out_neg = peak_report( + structure, grid, + sigma_cutoff=parser.sigma_cutoff, + min_volume = parser.min_volume, + min_score = parser.min_score, + min_peak = parser.min_peak, + distance_cutoff = parser.distance_cutoff, + use_long_names = parser.use_long_names, + negate=True, + ) + out = pd.concat((out, out_neg)) + + #For difference maps re-sort the concatenated list + peak_key = 'peakz' if 'peakz' in out else long_names['peakz'] + out['_sort_key'] = out[peak_key].abs() + out = out.sort_values('_sort_key', ascending=False) + del(out['_sort_key']) if parser.csv_out is not None: out.to_csv(parser.csv_out) From 39a0a361c354c9ab0a5cec405d7ae48e29af51ac Mon Sep 17 00:00:00 2001 From: Kevin Dalton Date: Thu, 5 May 2022 15:23:14 -0400 Subject: [PATCH 12/12] remove legacy __main__ clause --- efxtools/realspace/find_peaks.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/efxtools/realspace/find_peaks.py b/efxtools/realspace/find_peaks.py index 14e49d6..dea5127 100644 --- a/efxtools/realspace/find_peaks.py +++ b/efxtools/realspace/find_peaks.py @@ -275,5 +275,3 @@ def main(difference_map=False, default_sigma_cutoff=1.5): print(out.to_csv()) -if __name__=="__main__": - main()