diff --git a/README.md b/README.md index a7f5ee3..c98ce6a 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,16 @@ also install the CUDA toolkit by downloading and installing the Toolkit from the Changelog for current and past releases: +### 1.3.1: +Bug fixes: +- \#47 -nprocs removed in keyplayer kp-info command line +- \#48 empty result with kp-finder +- \#49 -seed argument removed in pyntacle generator +- \#50 --plot-format option removed from 1.2 onward +- \#51 seed argument removed in group degree API +- \#52 bad handling of missing output file names +- \#53 bad handling of empty set due to graph intersection + ### 1.3: Major updates: - [algorithms] Implementation of the new Stochastic Gradient Descent (SGD) search algorithm diff --git a/cmds/convert.py b/cmds/convert.py index ff157d1..e1c16ef 100644 --- a/cmds/convert.py +++ b/cmds/convert.py @@ -1,11 +1,11 @@ -__author__ = u"Mauro Truglio, Tommaso Mazza" -__copyright__ = u"Copyright 2018, The Pyntacle Project" +__author__ = u"Tommaso Mazza" +__copyright__ = u"Copyright 2018-2020, The Pyntacle Project" __credits__ = [u"Ferenc Jordan"] -__version__ = u"1.1" +__version__ = u"1.3.1" __maintainer__ = u"Tommaso Mazza" __email__ = "bioinformatics@css-mendel.it" __status__ = u"Development" -__date__ = u"26/11/2018" +__date__ = u"26/11/2020" __license__ = u""" Copyright (C) 2016-2020 Tommaso Mazza Viale Regina Margherita 261, 00198 Rome, Italy @@ -55,7 +55,7 @@ def run(self): if self.args.input_file is None: sys.stderr.write( - u"Please specify an input file using the `-i/--input-file` option. Quitting\n") + u"Please specify an input file using the `-i/--input-file` option. Quit\n") sys.exit(1) if not os.path.exists(self.args.input_file): @@ -67,89 +67,82 @@ def run(self): else: separator = self.args.input_separator - - sys.stdout.write(run_start) - sys.stdout.write(u"Converting input file {0} to requested output file: {1}\n".format(os.path.basename(self.args.input_file), os.path.basename(self.args.output_file))) - - out_form = format_dictionary.get(self.args.output_format, "NA") - + if self.args.output_file is None: self.args.output_file = os.path.splitext(os.path.basename(self.args.input_file))[0] sys.stdout.write( u"Output file name will be the basename of the input file ({})\n".format(self.args.output_file)) - # print(self.args.output_file) + + sys.stdout.write(run_start) + sys.stdout.write(u"Converting input file {0} to requested output file: {1}\n".format( + os.path.basename(self.args.input_file), + os.path.basename(self.args.output_file))) + + out_format = format_dictionary.get(self.args.output_format, "NA") + if out_format == "NA": + sys.stderr.write( + u"The specified extension for the output file is not supported, see '--help' for more info. Quit\n") + sys.exit(1) if self.args.output_separator is None: - sys.stdout.write( - u"Using the field separator used in the input network file in the converted output file, if the desired output format requires field separator\n") + sys.stdout.write(u"Using the field separator of the input file in the converted output file\n") self.args.output_separator = separator if not os.path.isdir(self.args.directory): - sys.stdout.write(u"WARNING: output directory does not exist, will create one at {}\n".format( + sys.stdout.write(u"WARNING: the output directory does not exist. It will be created at {}\n".format( os.path.abspath(self.args.directory))) os.makedirs(os.path.abspath(self.args.directory), exist_ok=True) - if out_form == "NA": - sys.stderr.write(u"Output extension specified is not supported, see '--help' for more info. Quitting\n") - sys.exit(1) - - output_path = os.path.join(self.args.directory, ".".join([self.args.output_file, out_form])) - init_graph = GraphLoad(input_file=self.args.input_file, file_format=format_dictionary.get(self.args.format, "NA"), header=header, separator=self.args.input_separator) + output_path = os.path.join(self.args.directory, ".".join([self.args.output_file, out_format])) + init_graph = GraphLoad(input_file=self.args.input_file, file_format=format_dictionary.get( + self.args.format, "NA"), header=header, separator=self.args.input_separator) input_basename = os.path.basename(self.args.input_file) - # special cases: - #1: convert an edgelist to a sif file - if format_dictionary.get(self.args.format, "NA") == "egl" and out_form == "sif": - sys.stdout.write(u"Converting edge list to Simple Interaction Format (SIF)\nFull path to the output file:\n{}\n".format(output_path)) + # special cases: + # 1: convert an edgelist to a sif file + if format_dictionary.get(self.args.format, "NA") == "egl" and out_format == "sif": + sys.stdout.write(u"Converting edge-list to SIF\nFull path to the output file:\n{}\n".format(output_path)) PyntacleConverter.edgelistToSif(file=self.args.input_file, sep=separator, output_sep=self.args.output_separator, header=output_header, output_file=output_path) - - #2: convert a sif to an edgelist file - elif format_dictionary.get(self.args.format, "NA") == "sif" and out_form == "egl": - sys.stdout.write(u"Converting Simple Interaction Format (SIF) to edge list\nFull path to the output file:\n{}\n".format(output_path)) + # 2: convert a sif to an edgelist file + elif format_dictionary.get(self.args.format, "NA") == "sif" and out_format == "egl": + sys.stdout.write(u"Converting SIF to edge-list\nFull path to the output file:\n{}\n".format(output_path)) PyntacleConverter.sifToEdgelist(file=self.args.input_file, sep=separator, output_sep=self.args.output_separator, header=output_header, output_file=output_path) - else: - graph = init_graph.graph_load() in_form = init_graph.get_format() - if in_form == out_form: - sys.stderr.write(u"The output format specified is the same as the input format. Quitting\n") + if in_form == out_format: + sys.stderr.write(u"The specified format of the output file is the same as the input file. Quit\n") sys.exit(1) - if out_form == "adjm": - sys.stdout.write(u"Converting input graph file {0} to adjacency matrix at full path:\n{1}\n".format( + if out_format == "adjm": + sys.stdout.write(u"Converting the input file {0} to adjacency matrix. Path:\n{1}\n".format( input_basename, output_path)) PyntacleExporter.AdjacencyMatrix(graph, output_path, sep=self.args.output_separator, header=output_header) - - elif out_form == "egl": + elif out_format == "egl": sys.stdout.write( - u"Converting input graph file {0} to edge list at full path:\n{1}\n".format( + u"Converting the input file {0} to edge-list. Path:\n{1}\n".format( input_basename, output_path)) PyntacleExporter.EdgeList(graph, output_path, sep=self.args.output_separator, header=output_header) - - elif out_form == "sif": + elif out_format == "sif": sys.stdout.write( - u"Converting input graph file {0} to Simple Interaction Format (SIF) file at full path:\n{1}\n".format( + u"Converting the input file {0} to SIF. Path:\n{1}\n".format( input_basename, output_path)) PyntacleExporter.Sif(graph, output_path, sep=self.args.output_separator, header=output_header) - - elif out_form == "dot": + elif out_format == "dot": # Ignore ugly RuntimeWarnings while converting to dot simplefilter("ignore", RuntimeWarning) sys.stdout.write( - u"Converting input graph file {0} to DOT file using igraph utilities at full path:\n{1}\n(output separator will be ignored)\n".format( + u"Converting the input file {0} to DOT. Path:\n{1}\n(output separator will be ignored)\n".format( input_basename, output_path)) PyntacleExporter.Dot(graph, output_path) - - - elif out_form == "graph": + elif out_format == "graph": sys.stdout.write( - u"Converting input graph file {0} to a binary file (ending in .graph) at full path:\n{1}\n(output separator will be ignored)\n".format( + u"Converting the input file {0} to a binary file (with .graph extension). Path:\n{1}\n(output separator will be ignored)\n".format( input_basename, output_path)) PyntacleExporter.Binary(graph, output_path) diff --git a/cmds/keyplayer.py b/cmds/keyplayer.py index 14537f4..931cb5e 100644 --- a/cmds/keyplayer.py +++ b/cmds/keyplayer.py @@ -174,7 +174,7 @@ def run(self): kp_runner.run_reachability(self.args.k_size, KpposEnum.dR, cmode=implementation) sys.stdout.write("\n") - if self.args.type in (['m-reach', 'pos', 'all']): + if self.args.type in (['mreach', 'pos', 'all']): sys.stdout.write( u"KP-Pos: Finding optimal set of nodes of size {0} that maximizes the m-reach at distance {1}\n".format( self.args.k_size, self.args.m_reach)) @@ -218,7 +218,7 @@ def run(self): sys.stdout.write(sep_line) - if self.args.type in (['m-reach', 'pos', 'all']): + if self.args.type in (['mreach', 'pos', 'all']): sys.stdout.write( u"KP-Pos: Finding the best set(s) of nodes of size {0} that maximizes the m-reach at distance {1}\n".format( self.args.k_size, self.args.m_reach)) @@ -284,7 +284,7 @@ def run(self): **{k: v for k, v in optional_args.items() if v is not None}) sys.stdout.write("\n") - if self.args.type in (['m-reach', 'pos', 'all']): + if self.args.type in (['mreach', 'pos', 'all']): sys.stdout.write( u"KP-Pos: Finding optimal set of nodes of size {0} that maximizes the m-reach at distance {1}\n".format( self.args.k_size, self.args.m_reach)) @@ -368,7 +368,7 @@ def run(self): kp_runner.run_reachability(KpposEnum.dR, cmode=implementation) sys.stdout.write("\n") - if self.args.type in (['m-reach', 'pos', 'all']): + if self.args.type in (['mreach', 'pos', 'all']): kp_runner.run_reachability(KpposEnum.mreach, m=self.args.m_reach, cmode=implementation) sys.stdout.write("\n") diff --git a/cmds/set.py b/cmds/set.py index 505c521..c29208b 100644 --- a/cmds/set.py +++ b/cmds/set.py @@ -1,11 +1,11 @@ __author__ = u"Mauro Truglio, Tommaso Mazza" -__copyright__ = u"Copyright 2018, The Pyntacle Project" +__copyright__ = u"Copyright 2018-2020, The Pyntacle Project" __credits__ = [u"Ferenc Jordan"] -__version__ = u"1.1" +__version__ = u"1.3.1" __maintainer__ = u"Tommaso Mazza" __email__ = "bioinformatics@css-mendel.it" __status__ = u"Development" -__date__ = u"26/11/2018" +__date__ = u"26/11/2020" __license__ = u""" Copyright (C) 2016-2020 Tommaso Mazza Viale Regina Margherita 261, 00198 Rome, Italy @@ -56,11 +56,11 @@ def run(self): cursor.start() if not os.path.exists(self.args.input_file_1) or not os.path.exists(self.args.input_file_2): - sys.stderr.write(u"One of the two input files does not exist. Quitting\n") + sys.stderr.write(u"One of the two input files does not exist. Quit\n") sys.exit(1) if filecmp.cmp(self.args.input_file_1, self.args.input_file_2, shallow=False): - sys.stderr.write(u"The two input files are equal. Quitting\n") + sys.stderr.write(u"The two input files are equal. Quit\n") sys.exit(1) input_header = True @@ -112,7 +112,7 @@ def run(self): except MultipleSolutionsError: sys.stderr.write( - u"Graph {} has two largest components of the same size. Cannot choose one. either remove one of the components or run 'pyntacle set' without the '--largest-component' option. Quitting\n".format(graph1["name"])) + u"Graph {} has two largest components of the same size. Cannot choose one. either remove one of the components or run 'pyntacle set' without the '--largest-component' option. Quit\n".format(graph1["name"])) sys.exit(1) try: @@ -124,44 +124,15 @@ def run(self): except MultipleSolutionsError: sys.stderr.write( - u"Graph {} has two largest components of the same size. Cannot choose one. either remove one of the components or run 'pyntacle set' without the '--largest-component' option. Quitting\n".format( + u"Graph {} has two largest components of the same size. Cannot choose one: either remove one of the components or run 'pyntacle set' without the '--largest-component' option. Quit\n".format( graph2["name"])) sys.exit(1) - - # - OLD PLOTTER - LEGACY - - # # Check provided dimensions' format - # if self.args.plot_dim: # define custom format - # self.args.plot_dim = self.args.plot_dim.split(",") - # - # for i in range(0, len(self.args.plot_dim)): - # try: - # self.args.plot_dim[i] = int(self.args.plot_dim[i]) - # - # except ValueError: - # sys.stderr.write( - # u"Format specified must be a comma-separated list of values(e.g. 1920,1080). Quitting\n") - # sys.exit(1) - # - # if self.args.plot_dim[i] <= 0: - # sys.stderr.write( - # u"Format specified must be a comma-separated list of values(e.g. 1920,1080). Quitting\n") - # sys.exit(1) - # - # plot_size = tuple(self.args.plot_dim) - # - # else: - # # generate different formats according to graph size - # if graph1.vcount() <= 150 and graph2.vcount() <= 150: - # plot_size = (800, 800) - # - # else: - # plot_size = (1600, 1600) + if self.args.format == "sif" or not all(x is None for x in graph1.es()["sif_interaction"]) or not all( x is None for x in graph2.es()["sif_interaction"]): sys.stdout.write(u"WARNING: Interaction stored in SIF files will be removed\n") - # GraphSetOps(graph1=graph1, graph2=graph2,new_name = new_name sys.stdout.write(section_end) sys.stdout.write(run_start) @@ -171,10 +142,6 @@ def run(self): self.args.input_file_2)) output_graph = GraphSetOps.union(graph1, graph2, self.args.output_file) - if all(len(x) <= 2 for x in output_graph.vs()["parent"]): - sys.stdout.write( - u"There were no common nodes when performing Graph union. Will return two disjoint graphs\n") - elif self.args.which == "intersection": sys.stdout.write( u"Performing intersection between input graph {} and {}\n".format(self.args.input_file_1, @@ -184,33 +151,25 @@ def run(self): if output_graph.ecount() == 0: sys.stdout.write( - u"No intersection was possible for the two input graphs. No output will be generated\n") + u"The intersection is empty and a graph will not be generated\n") if not self.args.suppress_cursor: cursor.stop() sys.exit(0) - - elif self.args.which == "difference": + else: + # elif self.args.which == "difference": sys.stdout.write( "Performing difference between input graph {} and {}\n".format(self.args.input_file_1, self.args.input_file_2)) output_graph = GraphSetOps.difference(graph1, graph2, self.args.output_file) if output_graph.vcount() == graph1.vcount() and output_graph.ecount() == graph1.ecount(): - sys.stdout.write(u"Nothing of graph {} could be subtracted from graph {}\n".format( + sys.stdout.write(u"Graphs {} and {} are disjoint\n".format( os.path.basename(self.args.input_file_1), os.path.basename(self.args.input_file_2))) - if output_graph.vcount() == 0 and output_graph.ecount() == 0: - sys.stdout.write(u"Graph difference was complete, no nodes and edges could be retrieved. No output will be produced. Quitting\n") - sys.exit(0) - - if output_graph.vcount() <= 1 and output_graph.ecount() < 1: - sys.stdout.write(u"Graph difference returned only node {} and no edge. No output will be produced. Quitting\n".format("".join(output_graph.vs["name"]))) - sys.exit(0) - if output_graph.vcount() > 1 and output_graph.ecount() == 0: sys.stdout.write( - u"Graph difference returned {} nodes, namely: {} and no edge. No output will be produced. Quitting\n".format( - output_graph.vcount(), ",\n".join(output_graph.vs()["name"]))) + u"Graph difference returned {} isolates. A graph will not be produced. Quit\n".format( + output_graph.vcount())) sys.exit(0) sys.stdout.write(section_end) @@ -239,7 +198,7 @@ def run(self): sys.stdout.write(section_end) sys.stdout.write(report_start) if not os.path.isdir(self.args.directory): - sys.stdout.write(u"WARNING: Output directory does not exist, will create one at {}\n".format( + sys.stdout.write(u"WARNING: The output directory does not exist. It will be created at {}\n".format( os.path.abspath(self.args.directory))) os.makedirs(os.path.abspath(self.args.directory), exist_ok=True) @@ -247,48 +206,47 @@ def run(self): output_path = os.path.join(self.args.directory, ".".join([self.args.output_file, out_form])) sys.stdout.write(u"Basename of output graph: {}\n".format(self.args.output_file)) - sys.stdout.write(u"Path to generated graph is: {}\n".format(output_path)) + sys.stdout.write(u"Path of the generated graph: {}\n".format(output_path)) # producing output graph if self.args.no_output_header: - sys.stdout.write(u"Skipping header on output files\n") + sys.stdout.write(u"Skipping header in output file\n") output_header = False else: output_header = True if self.args.output_separator is None: - sys.stdout.write(u"Using '\\t' as default separator for output file\n") + sys.stdout.write(u"Using '\\t' as default separator for the output file\n") self.args.output_separator = "\t" if os.path.exists(output_path): - self.logging.warning(u"A file named {} already exist, will be overwritten".format(output_path)) + self.logging.warning(u"A file named {} already exist. It will be overwritten".format(output_path)) # output generated networks if out_form == "adjm": - sys.stdout.write(u"Writing resulting graph to an adjacency matrix\n") + sys.stdout.write(u"Writing the resulting graph to an adjacency matrix file\n") PyntacleExporter.AdjacencyMatrix(output_graph, output_path, sep=self.args.output_separator, header=output_header) elif out_form == "egl": - sys.stdout.write(u"Writing resulting graph to an edge list\n") + sys.stdout.write(u"Writing the resulting graph to an edge-list file\n") PyntacleExporter.EdgeList(output_graph, output_path, sep=self.args.output_separator, header=output_header) elif out_form == "sif": - sys.stdout.write(u"Writing resulting graph to Simple Interaction Format (SIF) file\n") + sys.stdout.write(u"Writing the resulting graph to a SIF file\n") PyntacleExporter.Sif(output_graph, output_path, sep=self.args.output_separator, header=output_header) elif out_form == "dot": - sys.stdout.write("Writing resulting graph to a DOT file\n") + sys.stdout.write("Writing the resulting graph to a DOT file\n") # Ignore ugly RuntimeWarnings while creating a dot simplefilter("ignore", RuntimeWarning) PyntacleExporter.Dot(output_graph, output_path) elif out_form == "graph": - sys.stdout.write("Writing resulting graph into a binary file (ending in .graph)\n") + sys.stdout.write("Writing the resulting graph to a binary file (with .graph extension)\n") PyntacleExporter.Binary(output_graph, output_path) - intersection_set = [] for v in output_graph.vs(): parent_g1 = "_".join(graph1["name"]) @@ -310,7 +268,7 @@ def run(self): setF_attr_dict = OrderedDict() if self.args.which == 'intersection': - setF_attr_dict['\nCommon Nodes'] = 'Node names'#(len(intersection_set), ','.join(intersection_set)) + setF_attr_dict['\nCommon nodes'] = 'Node names'#(len(intersection_set), ','.join(intersection_set)) setF_attr_dict[len(intersection_set)] = ','.join(intersection_set) reporter1.create_report(ReportEnum.Set, set1_attr_dict) reporter2.create_report(ReportEnum.Set, set2_attr_dict) @@ -323,10 +281,10 @@ def run(self): del(reporter2.report[0]) del(reporter_final.report[0]) for e in reporter_final.report: - if e[0] == 'Pyntacle Command:': + if e[0] == 'Pyntacle command:': e[1] = e[1] + ' ' + self.args.which - reporter_final.report[0] = ['\n--- Resulting Graph ---'] + reporter_final.report[0] = ['\n--- Resulting graph ---'] reporter1.report.extend(reporter2.report) reporter1.report.extend(reporter_final.report) reporter1.write_report(report_dir=self.args.directory, format=self.args.report_format) @@ -345,12 +303,12 @@ def run(self): suffix = "_".join(["_".join(graph1["name"]), "Set", "_".join(graph2["name"])]) - sys.stdout.write(u"Plotting {} among the two graph in {} directory with PyntacleInk\n".format(self.args.which, self.args.directory)) + sys.stdout.write(u"Plotting {} in {} with PyntacleInk\n".format(self.args.which, self.args.directory)) reporter_both_graphs.pyntacleink_report(report_dir=self.args.directory, report_dict=report_dict, suffix=suffix) elif total_nodes >= 5000: sys.stdout.write( - u"The total sum of the two graph nodes ({}). PyntacleInk can plot networks with N < 5000. This graph will not be plotted\n".format( + u"The sum of the nodes of the two graphs is {}. PyntacleInk can plot graphs with N < 5000. This graph will not be plotted\n".format( total_nodes)) else: sys.stdout.write(pyntacleink_skip_msg) diff --git a/graph_operations/set_operations.py b/graph_operations/set_operations.py index 458f90b..90ec2b4 100644 --- a/graph_operations/set_operations.py +++ b/graph_operations/set_operations.py @@ -1,11 +1,11 @@ __author__ = ["Mauro Truglio", "Tommaso Mazza"] -__copyright__ = u"Copyright 2018, The Pyntacle Project" +__copyright__ = u"Copyright 2018-2020, The Pyntacle Project" __credits__ = [u"Ferenc Jordan"] -__version__ = u"1.1" +__version__ = u"1.3.1" __maintainer__ = u"Tommaso Mazza" __email__ = "bioinformatics@css-mendel.it" __status__ = u"Development" -__date__ = u"26/11/2018" +__date__ = u"26/11/2020" __license__ = u""" Copyright (C) 2016-2020 Tommaso Mazza Viale Regina Margherita 261, 00198 Rome, Italy @@ -31,6 +31,7 @@ from tools.add_attributes import AddAttributes from tools.graph_utils import GraphUtils as GUtil + def make_sets(graph1: Graph, graph2: Graph, operation: GraphOperationEnum): r""" Internal method to deal with the set operations and the handling of the attributes. @@ -47,7 +48,7 @@ def make_sets(graph1: Graph, graph2: Graph, operation: GraphOperationEnum): union_v = {} for v in list(set1v | set2v): - # Looping through the Union set of vertices NAMES + # Looping through the Union set of vertex NAMES if v in intersect_v: union_v.setdefault(v, []).append(graph1.vs[graph1.vs.find(v).index]["parent"]) union_v.setdefault(v, []).append(graph2.vs[graph2.vs.find(v).index]["parent"]) @@ -87,7 +88,7 @@ def union(graph1: Graph, graph2: Graph, new_graph_name: str) -> Graph: :param igraph.Graph graph1: a :class:`igraph.Graph` object. The graph must satisfy a series of requirements, described in the `Minimum requirements specifications `_ section of the Pyntacle official page. :param igraph.Graph graph2: a :class:`igraph.Graph` object. The graph must satisfy a series of requirements, described in the `Minimum requirements specifications `_ section of the Pyntacle official page. - :param str new_graph_name: a string representing the new name that will be added to the graph ``name`` attribute + :param str new_graph_name: a string representing the new name that will be assigned to the graph ``name`` attribute :return igraph.Graph: the resulting :class:`igraph.Graph` object. This network will contain both the first and second noddes and edges. The origin of each node it is determined by the vertex ``parent`` attribute. """ union_v, union_e = make_sets(graph1, graph2, GraphOperationEnum.Union) @@ -98,7 +99,9 @@ def union(graph1: Graph, graph2: Graph, new_graph_name: str) -> Graph: AddAttributes.add_edge_names(graph=merged_g) merged_g.vs["parent"] = list(union_v.values()) - GUtil(graph=merged_g).graph_initializer(graph_name=new_graph_name) + + if merged_g.vcount() > 0: + GUtil(graph=merged_g).graph_initializer(graph_name=new_graph_name) return merged_g @@ -134,7 +137,9 @@ def intersection(graph1: Graph, graph2: Graph, new_graph_name: str) -> Graph: AddAttributes.add_edge_names(graph=intersection_g) intersection_g.vs["parent"] = list(intersect_v.values()) - GUtil(graph=intersection_g).graph_initializer(graph_name=new_graph_name) + + if intersection_g.vcount() > 0: + GUtil(graph=intersection_g).graph_initializer(graph_name=new_graph_name) return intersection_g @@ -165,5 +170,6 @@ def difference(graph1: Graph, graph2: Graph, new_graph_name: str) -> Graph: AddAttributes.add_edge_names(graph=exclusive_g1) exclusive_g1.vs["parent"] = list(exclusive1_v.values()) - GUtil(graph=exclusive_g1).graph_initializer(graph_name=new_graph_name) + if exclusive_g1.vcount() > 0: + GUtil(graph=exclusive_g1).graph_initializer(graph_name=new_graph_name) return exclusive_g1 diff --git a/io_stream/importer.py b/io_stream/importer.py index f6d9cd0..065a7e0 100644 --- a/io_stream/importer.py +++ b/io_stream/importer.py @@ -1,11 +1,11 @@ -__author__ = u"Mauro Truglio, Tommaso Mazza" -__copyright__ = u"Copyright 2018, The Pyntacle Project" +__author__ = u"Tommaso Mazza" +__copyright__ = u"Copyright 2018-2020, The Pyntacle Project" __credits__ = [u"Ferenc Jordan"] -__version__ = u"1.2" +__version__ = u"1.3" __maintainer__ = u"Tommaso Mazza" __email__ = "bioinformatics@css-mendel.it" __status__ = u"Development" -__date__ = u"11/06/2020" +__date__ = u"10/11/2020" __license__ = u""" Copyright (C) 2016-2020 Tommaso Mazza Viale Regina Margherita 261, 00198 Rome, Italy diff --git a/pyntacle.py b/pyntacle.py index 56c0f54..fc809b2 100755 --- a/pyntacle.py +++ b/pyntacle.py @@ -1,11 +1,11 @@ __author__ = u"Mauro Truglio, Tommaso Mazza" __copyright__ = u"Copyright 2018-2020, The Pyntacle Project" __credits__ = [u"Ferenc Jordan"] -__version__ = u"1.3" +__version__ = u"1.3.1" __maintainer__ = u"Tommaso Mazza" __email__ = "bioinformatics@css-mendel.it" __status__ = u"Development" -__date__ = u"09/07/2020" +__date__ = u"26/11/2020" __license__ = u""" Copyright (C) 2016-2020 Tommaso Mazza Viale Regina Margherita 261, 00198 Rome, Italy @@ -27,6 +27,7 @@ import argparse import sys import os + sys.path.append(os.path.dirname(os.path.abspath(__file__))) from config import * import unittest @@ -34,7 +35,6 @@ from exceptions.generic_error import Error from colorama import init - if sys.version_info <= (3, 6): sys.exit("Python < 3.6 is not supported. Please update your Python distribution") @@ -143,8 +143,7 @@ def keyplayer(self): "sub-commands:\n" + 100 * "-" + "\n" + " kp-finder\t Find the best kp-set of size k\n" " kp-info\t Compute individual key-player metrics for a selected set of nodes\n" + 100 * "-", - formatter_class=lambda prog: argparse.RawDescriptionHelpFormatter(prog, width=100, - max_help_position=100), + formatter_class=lambda prog: argparse.RawDescriptionHelpFormatter(prog, width=100, max_help_position=100), usage=Fore.RED + Style.BRIGHT + "pyntacle keyplayer" + Fore.GREEN + Style.BRIGHT + " {kp-finder, kp-info}" + Fore.LIGHTBLUE_EX + " --type {all | pos | neg | F | dF | dR | mreach}" + Fore.RED + " [arguments]\n" + Style.RESET_ALL) @@ -232,6 +231,10 @@ def keyplayer(self): info_case_parser.add_argument("-n", "--nodes", help="(REQUIRED) Comma-separated list of strings, corresponding to the node names in the input graph, or column index of the input network file if the 'no-header' flag is specified", required=True) + info_case_parser.add_argument("-O", "--nprocs", metavar="", default=1, type=procs_type, + help="(BRUTE-FORCE SEARCH ONLY) Specify the maximum number of processes that " + "will be used by the brute-force search algorithm. Default to 1") + # Subparser for kp-finder case finder_case_parser = subparsers.add_parser("kp-finder", usage="pyntacle keyplayer kp-finder [-h] [-m] [-f] [--input-separator] [-N] [-d] [-L] [-M] [-I] [-S] [-P float] [-T float] [-x int] [--save-binary] [--report-format] [--no-plot] --type [TYPE] --input-file [FILE] -k [K]", @@ -400,7 +403,6 @@ def groupcentrality(self): help="(STOCHASTIC GRADIENT DESCENT ONLY) Maximum allowed computation time " "(seconds). Default to infinity") - finder_case_parser.set_defaults(which="gr-finder") # if len(sys.argv) < 4 or (sys.argv[3] not in ("gr-finder", "gr-info")): @@ -967,7 +969,6 @@ def communities(self): sys.stderr.write(sigkill_message) def set(self): - parser = argparse.ArgumentParser( description="Perform set operations (union, intersection, difference) between two networks using " "logical graph operations\n\n"