diff --git a/bycon/__init__.py b/bycon/__init__.py index 3be05322b..0be5da91f 100644 --- a/bycon/__init__.py +++ b/bycon/__init__.py @@ -36,6 +36,7 @@ update_rootpars_from_local_or_HOST() rest_path_elements() set_beacon_defaults() + arguments_set_defaults() parse_arguments() set_entities() initialize_bycon_service() diff --git a/bycon/byconServiceLibs/bycon_plot.py b/bycon/byconServiceLibs/bycon_plot.py index 83d1fbd76..f088757f4 100644 --- a/bycon/byconServiceLibs/bycon_plot.py +++ b/bycon/byconServiceLibs/bycon_plot.py @@ -27,7 +27,6 @@ ################################################################################ class ByconPlotPars: - def __init__(self): self.plot_type = BYC_PARS.get("plot_type", "histoplot") self.plot_defaults = BYC.get("plot_defaults", {}) diff --git a/bycon/byconServiceLibs/datatable_utils.py b/bycon/byconServiceLibs/datatable_utils.py index 06889f1a5..7023632c2 100644 --- a/bycon/byconServiceLibs/datatable_utils.py +++ b/bycon/byconServiceLibs/datatable_utils.py @@ -83,8 +83,8 @@ def import_datatable_dict_line(parent, fieldnames, lineobj, primary_scope="biosa ################################################################################ def create_table_header(io_params): - """podmd - podmd""" + """ + """ header_labs = [ ] for par, par_defs in io_params.items(): pres = par_defs.get("prefix_split", {}) diff --git a/bycon/byconServiceLibs/export_file_generation.py b/bycon/byconServiceLibs/export_file_generation.py index 071676770..53bad8fc6 100644 --- a/bycon/byconServiceLibs/export_file_generation.py +++ b/bycon/byconServiceLibs/export_file_generation.py @@ -139,7 +139,7 @@ def export_pgxseg_download(datasets_results, ds_id): ################################################################################ def write_variants_bedfile(datasets_results, ds_id): - """podmd + """ ##### Accepts * a Bycon `h_o` handover object with its `target_values` representing `_id` @@ -157,7 +157,7 @@ def write_variants_bedfile(datasets_results, ds_id): +separate configuration entry and subroutine. * evaluate to use "bedDetails" format - podmd""" + """ if not (local_paths := BYC.get("local_paths")): return False tmp_path = path.join( *local_paths[ "server_tmp_dir_loc" ]) diff --git a/bycon/byconServiceLibs/ontology_utils.py b/bycon/byconServiceLibs/ontology_utils.py index 9a16f2959..574e47737 100644 --- a/bycon/byconServiceLibs/ontology_utils.py +++ b/bycon/byconServiceLibs/ontology_utils.py @@ -15,6 +15,14 @@ ) class OntologyMaps: + """ + The `OntologyMaps` class is used to create, retrieve and store ontology maps, + i.e. the corresponding terms for codes from different ontologies or controlled + vocabularies. In the context of the Progenetix Beacon as a data-rich `bycon` + deployment, a particlular use is the mapping of codes from different cancer + related diagnostic codes, specifically from ICD-O 3 histology/topography doublets + with NCIt cancer codes. + """ def __init__(self): self.query = {} self.term_groups = [] diff --git a/bycon/config/plot_defaults.yaml b/bycon/config/plot_defaults.yaml index 6283daea7..bf4acfc28 100644 --- a/bycon/config/plot_defaults.yaml +++ b/bycon/config/plot_defaults.yaml @@ -6,7 +6,7 @@ # `bycon` package. plot_type_defs: - + histoplot: description: >- The default option, used to plot histograms of the CNV frequencies per @@ -63,7 +63,6 @@ plot_type_defs: #------------------------------------------------------------------------------# plot_parameters: - # To limit the amount of pre-defined parameters accepted through the `bycon` # interface we are using a special syntax for plot parameters. Plot parameters # (see below for all pre-defined ones) are provided as a single string to `plotPars` diff --git a/bycon/config/services_entity_defaults.yaml b/bycon/config/services_entity_defaults.yaml index 33da140b2..014450e53 100644 --- a/bycon/config/services_entity_defaults.yaml +++ b/bycon/config/services_entity_defaults.yaml @@ -40,7 +40,7 @@ cytomapper: beacon_schema: entity_type: cytobandMapping schema: https://progenetix.org/services/schemas/CytobandMapping/ - path_id_value_bycon_parameter: cytoBands + path_id_value_bycon_parameter: cyto_bands endpoints: request_entity_path_id: endpoints @@ -78,6 +78,7 @@ geoLocation: ids: request_entity_path_id: ids + path_id_value_bycon_parameter: id intervalFrequencies: request_entity_path_id: intervalFrequencies @@ -155,8 +156,10 @@ sampleplots: schema: NA path_id_value_bycon_parameter: biosample_ids -schemas: - request_entity_path_id: schemas +byconschemas: + request_entity_path_aliases: + - schemas + request_entity_path_id: byconschemas path_id_value_bycon_parameter: id uploader: diff --git a/bycon/lib/cgi_parsing.py b/bycon/lib/cgi_parsing.py index 0b6f468b8..65abe77e5 100644 --- a/bycon/lib/cgi_parsing.py +++ b/bycon/lib/cgi_parsing.py @@ -8,14 +8,27 @@ ################################################################################ -def parse_arguments(): +class ByconParameters: + def __init__(self): + self.arg_defs = BYC.get("argument_definitions", {}) + self.byc_pars = {} + + +################################################################################ + +def arguments_set_defaults(): a_defs = BYC.get("argument_definitions", {}) for a, d in a_defs.items(): if "default" in d: BYC_PARS.update({a: d["default"]}) - if "local" in ENV: - if "local" in d: + if "local" in d and "local" in ENV: BYC_PARS.update({a: d["local"]}) + + +################################################################################ + +def parse_arguments(): + if "local" in ENV: args_update_form() else: r_m = environ.get('REQUEST_METHOD', '') diff --git a/bycon/lib/cytoband_parsing.py b/bycon/lib/cytoband_parsing.py index 0babcb332..51a0d5553 100644 --- a/bycon/lib/cytoband_parsing.py +++ b/bycon/lib/cytoband_parsing.py @@ -1,6 +1,7 @@ import csv, re from os import path +from bycon_helpers import prdbug from config import * from genome_utils import ChroNames @@ -8,8 +9,12 @@ ################################################################################ ################################################################################ - class Cytobands(): + """ + The `Cytobands()` class provides methods to access cytoband information from + a standard UCSC-style cytoband file (cytoBandIdeo.txt), to filter those for + cytoband or genomic ranges and to convert between cytoband and genomic coordinates. + """ def __init__(self): self.cytobands = [ ] @@ -33,16 +38,20 @@ def __init__(self): def get_all_cytobands(self): return self.cytobands + + # -------------------------------------------------------------------------# + def get_all_cytolimits(self): return self.cytolimits + + # -------------------------------------------------------------------------# + def get_genome_size(self): return self.genome_size # -------------------------------------------------------------------------# - # -------------------------------------------------------------------------# - def cytobands_response(self): self.__cytobands_from_request_pars() @@ -50,12 +59,11 @@ def cytobands_response(self): return self.cytoband_response - # -------------------------------------------------------------------------# # -------------------------------------------------------------------------# def bands_from_cytostring(self, cytoband=""): self.cytostring = cytoband - self.__cytobands_from_cytoband_string() + self.__bands_from_cytobands() return self.filtered_bands, self.chro, self.start, self.end @@ -63,17 +71,11 @@ def bands_from_cytostring(self, cytoband=""): # ----------------------------- private -----------------------------------# # -------------------------------------------------------------------------# - def __cytobands_from_cytoband_string(self): - self.filtered_bands, self.chro, self.start, self.end = bands_from_cytobands(self.cytostring) - - - # -------------------------------------------------------------------------# - - def __cytobands_from_request_pars(self): if (c_b := BYC_PARS.get("cyto_bands")): - self.filtered_bands, self.chro, self.start, self.end = bands_from_cytobands(c_b) - if (c_b := BYC_PARS.get("chro_bases")): + self.cytostring = c_b + self.__bands_from_cytobands() + if (c_b := BYC_PARS.get("chro_bases", [])): self.filtered_bands, self.chro, self.start, self.end = bands_from_chrobases(c_b) else: return @@ -83,6 +85,7 @@ def __cytobands_from_request_pars(self): def __cytobands_response_object(self): if len(self.filtered_bands) < 1: + BYC["ERRORS"].append("No matching cytobands!") return cb_label = cytobands_label(self.filtered_bands) @@ -165,116 +168,122 @@ def __parse_cytoband_file(self): }) self.genome_size += int(chrobands[-1]["end"]) - #--------------------------------------------------------------------------# + #--------------------------------------------------------------------------# + def __bands_from_cytobands(self): + argdefs = BYC.get("argument_definitions", {}) + cb_pat = re.compile( argdefs["cyto_bands"]["pattern"] ) + end_re = re.compile(r"^([pq]\d.*?)\.?\d$") + arm_re = re.compile(r"^([pq]).*?$") + p_re = re.compile(r"^p.*?$") + q_re = re.compile(r"^q.*?$") + chr_bands = self.cytostring -################################################################################ + if "p10" in chr_bands: + chr_bands = re.sub("p10", "pcen", chr_bands) + if "q10" in chr_bands: + chr_bands = re.sub("q10", "qcen", chr_bands) + + if not cb_pat.match(chr_bands): + return([], "", "", "") + + chro, cb_start, cb_end = cb_pat.match(chr_bands).group(1,2,3) + cytobands = list(filter(lambda d: d["chro"] == chro, self.cytobands.copy())) + + if len(cytobands) < 10: + BYC["ERRORS"].append(f"No matching cytobands for chromosome {chro}!") + return + + if cb_start is None and cb_end is None: + self.filtered_bands = cytobands + self.chro = chro + self.start = int( cytobands[0]["start"] ) + self.end = int( cytobands[-1]["end"]) + return + + p_bands = list(filter(lambda d: p_re.match(d["cytoband"]), cytobands)) + q_bands = list(filter(lambda d: q_re.match(d["cytoband"]), cytobands)) + + # if there was no end, the start band is queried again until its last match + if cb_end is None: + cb_end = cb_start + + if "qter" in cb_start: + cb_start = cytobands[-1]["cytoband"] + if "qter" in cb_end: + cb_end = cytobands[-1]["cytoband"] + if "pter" in cb_start: + cb_start = cytobands[0]["cytoband"] + if "pter" in cb_end: + cb_end = cytobands[0]["cytoband"] + if "pcen" in cb_start: + cb_start = p_bands[-1]["cytoband"] + if "pcen" in cb_end: + cb_end = p_bands[-1]["cytoband"] + if "qcen" in cb_start: + cb_start = q_bands[0]["cytoband"] + if "qcen" in cb_end: + cb_end = q_bands[0]["cytoband"] + + if "p" in cb_end: + if "q" in cb_start: + cb_start, cb_end = cb_end, cb_start + + # using a numeric comparison to sort bands for p higher to lower + cb_re = re.compile(r'^([pq])((\d)(?:\d(?:\.\d\d?\d?)?)?)$', re.IGNORECASE) + if cb_re.match(cb_start) and cb_re.match(cb_end): + fb1 = float( cb_re.match(cb_start).group(2) ) + fb2 = float( cb_re.match(cb_end).group(2) ) + arm1 = cb_re.match(cb_start).group(1) + arm2 = cb_re.match(cb_end).group(1) + mb1 = int( cb_re.match(cb_start).group(3) ) + mb2 = int( cb_re.match(cb_end).group(3) ) + if arm1 == arm2: + if "p" in arm1: + if not mb1 > mb2: + if fb2 > fb1: + cb_start, cb_end = cb_end, cb_start + elif "q" in arm1: + if not mb2 > mb1: + if fb2 < fb1: + cb_start, cb_end = cb_end, cb_start + + # print("\n", chro, cb_start, cb_end, chr_bands) + + # TODO: this is ugly - somehow had problems w/ recursion version :-/ + start_bands = match_bands(cb_start, cytobands) + if len(start_bands) < 1: + if end_re.match(cb_start): + band = end_re.match(cb_start).group(1) + start_bands = match_bands(band, cytobands) + if len(start_bands) < 1: + if arm_re.match(cb_start): + band = arm_re.match(cb_start).group(1) + start_bands = match_bands(band, cytobands) + + end_bands = match_bands(cb_end, cytobands) + if len(end_bands) < 1: + if end_re.match(cb_end): + band = end_re.match(cb_end).group(1) + end_bands = match_bands(band, cytobands) + if len(end_bands) < 1: + if arm_re.match(cb_end): + band = arm_re.match(cb_end).group(1) + end_bands = match_bands(band, cytobands) + + cb_from = start_bands[0]["i"] + cb_to = end_bands[-1]["i"] + 1 + + matched = self.cytobands[cb_from:cb_to] + + self.filtered_bands = matched + self.chro = chro + self.start = int( matched[0]["start"] ) + self.end = int( matched[-1]["end"]) + + #--------------------------------------------------------------------------# -def bands_from_cytobands(chr_bands): - argdefs = BYC.get("argument_definitions", {}) - cytoband_defs = BYC.get("cytobands", []) - cb_pat = re.compile( argdefs["cyto_bands"]["pattern"] ) - end_re = re.compile(r"^([pq]\d.*?)\.?\d$") - arm_re = re.compile(r"^([pq]).*?$") - p_re = re.compile(r"^p.*?$") - q_re = re.compile(r"^q.*?$") - - # chr_bands = "4pcenqcen" - - if "p10" in chr_bands: - chr_bands = re.sub("p10", "pcen", chr_bands) - if "q10" in chr_bands: - chr_bands = re.sub("q10", "qcen", chr_bands) - - if not cb_pat.match(chr_bands): - return([], "", "", "") - - chro, cb_start, cb_end = cb_pat.match(chr_bands).group(1,2,3) - cytobands = list(filter(lambda d: d[ "chro" ] == chro, cytoband_defs.copy())) - - if len(cytobands) < 10: - return([], "", "", "") - - if cb_start is None and cb_end is None: - return cytobands, chro, int( cytobands[0]["start"] ), int( cytobands[-1]["end"] ) - - p_bands = list(filter(lambda d: p_re.match(d[ "cytoband" ]), cytobands)) - q_bands = list(filter(lambda d: q_re.match(d[ "cytoband" ]), cytobands)) - - # if there was no end, the start band is queried again until its last match - if cb_end is None: - cb_end = cb_start - - if "qter" in cb_start: - cb_start = cytobands[-1]["cytoband"] - if "qter" in cb_end: - cb_end = cytobands[-1]["cytoband"] - if "pter" in cb_start: - cb_start = cytobands[0]["cytoband"] - if "pter" in cb_end: - cb_end = cytobands[0]["cytoband"] - if "pcen" in cb_start: - cb_start = p_bands[-1]["cytoband"] - if "pcen" in cb_end: - cb_end = p_bands[-1]["cytoband"] - if "qcen" in cb_start: - cb_start = q_bands[0]["cytoband"] - if "qcen" in cb_end: - cb_end = q_bands[0]["cytoband"] - - if "p" in cb_end: - if "q" in cb_start: - cb_start, cb_end = cb_end, cb_start - - # using a numeric comparison to sort bands for p higher to lower - cb_re = re.compile(r'^([pq])((\d)(?:\d(?:\.\d\d?\d?)?)?)$', re.IGNORECASE) - if cb_re.match(cb_start) and cb_re.match(cb_end): - fb1 = float( cb_re.match(cb_start).group(2) ) - fb2 = float( cb_re.match(cb_end).group(2) ) - arm1 = cb_re.match(cb_start).group(1) - arm2 = cb_re.match(cb_end).group(1) - mb1 = int( cb_re.match(cb_start).group(3) ) - mb2 = int( cb_re.match(cb_end).group(3) ) - if arm1 == arm2: - if "p" in arm1: - if not mb1 > mb2: - if fb2 > fb1: - cb_start, cb_end = cb_end, cb_start - elif "q" in arm1: - if not mb2 > mb1: - if fb2 < fb1: - cb_start, cb_end = cb_end, cb_start - - # print("\n", chro, cb_start, cb_end, chr_bands) - - # TODO: this is ugly - someho whad problems w/ recursion version :-/ - start_bands = match_bands(cb_start, cytobands) - if len(start_bands) < 1: - if end_re.match(cb_start): - band = end_re.match(cb_start).group(1) - start_bands = match_bands(band, cytobands) - if len(start_bands) < 1: - if arm_re.match(cb_start): - band = arm_re.match(cb_start).group(1) - start_bands = match_bands(band, cytobands) - - end_bands = match_bands(cb_end, cytobands) - if len(end_bands) < 1: - if end_re.match(cb_end): - band = end_re.match(cb_end).group(1) - end_bands = match_bands(band, cytobands) - if len(end_bands) < 1: - if arm_re.match(cb_end): - band = arm_re.match(cb_end).group(1) - end_bands = match_bands(band, cytobands) - - cb_from = start_bands[0]["i"] - cb_to = end_bands[-1]["i"] + 1 - - matched = cytoband_defs[cb_from:cb_to] - - return matched, chro, int( matched[0]["start"] ), int( matched[-1]["end"]) ################################################################################ @@ -321,31 +330,30 @@ def cytobands_label(cytobands): def cytobands_label_from_positions(chro, start, end): cytobands, chro, start, end = cytobands_list_from_positions(chro, start, end) cbl = cytobands_label(cytobands) - return cbl ################################################################################ def bands_from_chrobases(chro_bases): - cb_pat = re.compile( BYC["argument_definitions"]["chro_bases"]["items"]["pattern"] ) + cb_pat = re.compile( BYC["argument_definitions"]["chro_bases"]["pattern"] ) if not cb_pat.match(chro_bases): return [], "NA", 0, 0 chro, cb_start, cb_end = cb_pat.match(chro_bases).group(2,3,5) - return cytobands_list_from_positions(chro, cb_start, cb_end) ################################################################################ def cytobands_list_from_positions(chro, start=None, end=None): + cytobands = Cytobands().get_all_cytobands() if start: start = int(start) if not end: end = start + 1 end = int(end) - cytobands = list(filter(lambda d: d[ "chro" ] == chro, BYC.get("cytobands", []))) + cytobands = list(filter(lambda d: d[ "chro" ] == chro, cytobands)) if start == None: start = 0 if end == None: diff --git a/bycon/lib/handover_generation.py b/bycon/lib/handover_generation.py index 8a103fa69..fe118d567 100644 --- a/bycon/lib/handover_generation.py +++ b/bycon/lib/handover_generation.py @@ -11,8 +11,8 @@ ################################################################################ def dataset_response_add_handovers(ds_id, datasets_results): - """podmd - podmd""" + """ + """ b_h_o = [ ] if BYC_PARS.get("include_handovers", True) is not True: return b_h_o diff --git a/bycon/lib/query_generation.py b/bycon/lib/query_generation.py index 4143393cd..a1fb048ec 100644 --- a/bycon/lib/query_generation.py +++ b/bycon/lib/query_generation.py @@ -286,7 +286,7 @@ def __loop_multivars(self): ################################################################################ def __get_variant_request_type(self, v_pars): - """podmd + """ This method guesses the type of variant request, based on the complete fulfillment of the required parameters (all of `all_of`, one if `one_of`). In case of multiple types the one with most matched parameters is prefered. @@ -296,7 +296,7 @@ def __get_variant_request_type(self, v_pars): TODO: This is all a bit too complex; probbaly better to just do it as a stack of dedicated tests and including a "defined to fail" query which is only removed after a successfull type match. - podmd""" + """ variant_request_type = None @@ -607,9 +607,9 @@ def __create_variantBracketRequest_query(self, v_pars): #--------------------------------------------------------------------------# def __create_variantAlleleRequest_query(self, v_pars): - """podmd + """ - podmd""" + """ vp = v_pars v_p_defs = self.argument_definitions # TODO: Regexes for ref or alt with wildcard characters diff --git a/bycon/lib/read_specs.py b/bycon/lib/read_specs.py index eb6d5a66d..fca28d345 100644 --- a/bycon/lib/read_specs.py +++ b/bycon/lib/read_specs.py @@ -10,13 +10,13 @@ ################################################################################ def read_service_definition_files(): - """podmd + """ Reading the config from the same wrapper dir: module | |- lib - read_specs.py |- definitions - __name__.yaml - podmd""" + """ if not path.isdir(CONF_PATH): return b_d_fs = [ f.name for f in scandir(CONF_PATH) if f.is_file() ] diff --git a/bycon/lib/service_utils.py b/bycon/lib/service_utils.py index 60e154db3..2626ffee0 100644 --- a/bycon/lib/service_utils.py +++ b/bycon/lib/service_utils.py @@ -48,6 +48,7 @@ def set_entities(): BYC definitions. """ b_e_d = BYC.get("entity_defaults", {}) + a_defs = BYC.get("argument_definitions", {}) dealiased_path_ids = {} for e, e_d in b_e_d.items(): @@ -93,7 +94,9 @@ def set_entities(): }) if (rpidv := BYC.get("request_entity_path_id_value")): - BYC_PARS.update({p_p: rpidv}) + if p_p in a_defs.keys(): + v = RefactoredValues(a_defs[p_p]).refVal(rpidv) + BYC_PARS.update({p_p: v}) ################################################################################ diff --git a/bycon/schemas/bin/beaconYamler.py b/bycon/schemas/bin/beaconYamler.py index 53453671b..c263a7d45 100755 --- a/bycon/schemas/bin/beaconYamler.py +++ b/bycon/schemas/bin/beaconYamler.py @@ -13,10 +13,10 @@ with open(path.join( here_path, "config", this_script), 'r') as c_f: config = yaml.load(c_f, Loader=yaml.FullLoader) -"""podmd +""" The script converts files in directories between yaml <-> json It requires the specification of input and output directories and file formats. -podmd""" +""" ################################################################################ ################################################################################ diff --git a/byconServices/__init__.py b/byconServices/__init__.py new file mode 100644 index 000000000..614105ccc --- /dev/null +++ b/byconServices/__init__.py @@ -0,0 +1,28 @@ +# __init__.py +import sys +from os import path + +sys.path.append( path.dirname( path.abspath(__file__) ) ) + +from cnvstats import cnvstats +from collationplots import collationplots +from collations import collations +from cytomapper import cytomapper +from dbstats import dbstats +from endpoints import endpoints +from genespans import genespans +from geolocations import geolocations +from ids import ids +from intervalFrequencies import intervalFrequencies +from ontologymaps import ontologymaps +from pgxsegvariants import pgxsegvariants +from publications import publications +from samplemap import samplemap +from samplematrix import samplematrix +from sampleplots import sampleplots +from sampletable import sampletable +from byconschemas import byconschemas +from services import services +from uploader import uploader +from variantsbedfile import variantsbedfile +from vcfvariants import vcfvariants diff --git a/byconServices/byconschemas.py b/byconServices/byconschemas.py new file mode 100755 index 000000000..7c0080d34 --- /dev/null +++ b/byconServices/byconschemas.py @@ -0,0 +1,20 @@ +from bycon import prdbug, prjsonhead, prjsontrue, BYC, BYC_PARS, BeaconErrorResponse, read_schema_file + + +def byconschemas(): + """ + This helper service reads and serves local schema definition files. The name of + the schema (corresponding to the file name minus extension) is provided either + as an `id` query parameter or as the first part of the path after `schemas/`. + + * + """ + if (schema_name := BYC_PARS.get("id")): + schema_name = schema_name.split('.').pop(0) + if (s := read_schema_file(schema_name, "")): + prjsonhead() + prjsontrue(s) + exit() + + BYC["ERRORS"].append("No correct schema id provided!") + BeaconErrorResponse().respond_if_errors(422) diff --git a/byconServices/cnvstats.py b/byconServices/cnvstats.py index 257b78600..1592870e6 100755 --- a/byconServices/cnvstats.py +++ b/byconServices/cnvstats.py @@ -5,6 +5,9 @@ ) def cnvstats(): + """ + ==TBD== + """ BYC_PARS.update({ "output":"cnvstats", "include_handovers": False diff --git a/byconServices/collationplots.py b/byconServices/collationplots.py index d4a509b5d..89d48068f 100755 --- a/byconServices/collationplots.py +++ b/byconServices/collationplots.py @@ -1,20 +1,24 @@ from bycon import BeaconErrorResponse, BYC, BYC_PARS, prdbug from byconServiceLibs import ByconBundler, ByconPlot -"""podmd -* https://progenetix.org/services/collationplots/?datasetIds=progenetix&filters=NCIT:C7376,PMID:22824167,pgx:icdom-85003 -* https://progenetix.org/services/collationplots/?datasetIds=progenetix&filters=NCIT:C7376,PMID:22824167&plotType=histoplot -* https://progenetix.org/services/collationplots/?datasetIds=progenetix&id=pgxcohort-TCGAcancers -* http://progenetix.test/services/collationplots/?datasetIds=progenetix&filters=NCIT:C7376,PMID:22824167&plotType=histoheatplot -* http://progenetix.test/services/collationplots/?datasetIds=progenetix&collationTypes=NCIT&minNumber=500&plotType=histoheatplot&includeDescendantTerms=false -podmd""" - ################################################################################ def collationplots(): - if str(BYC_PARS.get("plot_type", "___none___")) not in ["histoplot", "histoheatplot", "histosparkplot"]: - BYC_PARS.update({"plot_type": "histoplot"}) + """ + The `collationplots` function is a service to provide plots for CNV data aggregated + for samples matching individual filter values such as diagnostic codes or experimental + series id values. The default response is an SVG histogram ("histoplot"). Please refer + to the plot parameters documentation and the `ByconPlot` class for other options. + + For a single plot one can provide the entity id as path id value. + + #### Examples (using the Progenetix resource as endpoint): + * https://progenetix.org/services/collationplots/pgx:cohort-TCGAcancers + * https://progenetix.org/services/collationplots/?filters=NCIT:C7376,PMID:22824167,pgx:icdom-85003 + * https://progenetix.org/services/collationplots/?filters=NCIT:C7376,PMID:22824167&plotType=histoheatplot + * https://progenetix.org/services/collationplots/?collationTypes=icdom&minNumber=1000&plotType=histoheatplot + """ pdb = ByconBundler().collationsPlotbundles() BeaconErrorResponse().respond_if_errors() ByconPlot(pdb).svgResponse() diff --git a/byconServices/collations.py b/byconServices/collations.py index 23791b762..2144dd3e7 100755 --- a/byconServices/collations.py +++ b/byconServices/collations.py @@ -2,4 +2,7 @@ from byconServiceLibs import ByconServiceResponse def collations(): + """ + ==TBD== + """ ByconServiceResponse().print_collations_response() diff --git a/byconServices/cytomapper.py b/byconServices/cytomapper.py index d0641c702..8acdde6a4 100755 --- a/byconServices/cytomapper.py +++ b/byconServices/cytomapper.py @@ -7,8 +7,17 @@ from byconServiceLibs import ByconServiceResponse def cytomapper(): - if not (cbr := Cytobands().cytobands_response()): - BYC["ERRORS"].append("No matching cytobands!") - BeaconErrorResponse().respond_if_errors() + """ + The `cytomapper` function provides a JSON response with cytoband information + such as matched cytobands and the genome coordinates of their extend. + #### Examples (using the Progenetix resource as endpoint): + + * https://progenetix.org/services/cytomapper/8q21q24 + * https://progenetix.org/services/cytomapper/13q + * https://progenetix.org/services/cytomapper?chroBases=12:10000000-45000000 + + """ + cbr = Cytobands().cytobands_response() + BeaconErrorResponse().respond_if_errors() print_json_response(ByconServiceResponse().populated_response([cbr])) diff --git a/byconServices/dbstats.py b/byconServices/dbstats.py index 406a43f1f..6f80d8bad 100755 --- a/byconServices/dbstats.py +++ b/byconServices/dbstats.py @@ -2,11 +2,12 @@ from bycon import BYC, DB_MONGOHOST, HOUSEKEEPING_DB, HOUSEKEEPING_INFO_COLL, print_json_response from byconServiceLibs import ByconServiceResponse -"""podmd -* -podmd""" - def dbstats(): + """ + ==TBD== + + * + """ stats_client = MongoClient(host=DB_MONGOHOST) stats_coll = stats_client[HOUSEKEEPING_DB][HOUSEKEEPING_INFO_COLL] results = [] diff --git a/byconServices/endpoints.py b/byconServices/endpoints.py index 2915f7920..312efa69a 100755 --- a/byconServices/endpoints.py +++ b/byconServices/endpoints.py @@ -9,12 +9,16 @@ rest_path_value ) -"""podmd -The service provides the schemas for the `BeaconMap` OpenAPI endpoints. -* -podmd""" def endpoints(): + """ + The service provides the schemas for the `BeaconMap` OpenAPI endpoints. + + #### Examples (using the Progenetix resource as endpoint): + + * + * + """ # TODO: This needs some error fallback, test for existing entities etc. schema_name = rest_path_value("endpoints") if schema_name: diff --git a/byconServices/genespans.py b/byconServices/genespans.py index 520d32002..7b63e63ef 100755 --- a/byconServices/genespans.py +++ b/byconServices/genespans.py @@ -15,12 +15,17 @@ services_conf_path = path.join( path.dirname( path.abspath(__file__) ), "config" ) -""" -* http://progenetix.test/services/genespans/MYC -* http://progenetix.test/services/genespans/?geneId=MYC -""" def genespans(): + """ + The `genespans` function provides a JSON response with the coordinates of + matching gene IDs. + + #### Examples (using the Progenetix resource as endpoint): + + * https://progenetix.test/services/genespans/MYC + * https://progenetix.test/services/genespans/?geneId=MYC + """ read_service_prefs("genespans", services_conf_path) # form id assumes start match (e.g. for autocompletes) diff --git a/byconServices/geolocations.py b/byconServices/geolocations.py index 7b0b99188..21557354c 100755 --- a/byconServices/geolocations.py +++ b/byconServices/geolocations.py @@ -4,13 +4,13 @@ from bycon import * from byconServiceLibs import ByconMap, ByconServiceResponse, open_text_streaming, ByconGeolocs -"""podmd +""" * * * * * -podmd""" +""" def main(): geolocations() diff --git a/byconServices/ids.py b/byconServices/ids.py index a9ae8674f..10f0cfdcf 100755 --- a/byconServices/ids.py +++ b/byconServices/ids.py @@ -1,47 +1,44 @@ -#!/usr/bin/env python3 import re from os import path -from bycon import * +from bycon import BYC, BYC_PARS, print_uri_rewrite_response, rest_path_value from byconServiceLibs import read_service_prefs -services_conf_path = path.join( path.dirname( path.abspath(__file__) ), "config" ) +################################################################################ -"""podmd -The `ids` service forwards compatible, prefixed ids (see `config/ids.yaml`) to specific -website endpoints. There is no check if the id exists; this is left to the web -page handling itself. +def ids(): + """ + The `ids` service forwards compatible, prefixed ids (see `config/ids.yaml`) to specific + website endpoints. There is no check if the id exists; this is left to the web + page handling itself. -Stacking with the "pgx:" prefix is allowed. -* -* -* -podmd""" + Stacking with the "pgx:" prefix is allowed. -def ids(): - set_debug_state(debug=0) - read_service_prefs( "ids", services_conf_path) + #### Examples (using the Progenetix resource as endpoint): + + * + * + * + """ + + conf_path = path.join( path.dirname( path.abspath(__file__) ), "config" ) + read_service_prefs( "ids", conf_path) id_in = rest_path_value("ids") - output = rest_path_value(id_in) s_c = BYC.get("service_config", {}) f_p_s = s_c.get("format_patterns", {}) - if id_in: + if len(id_in := BYC_PARS.get("id", [])) > 0: + lid = id_in[0] for f_p in f_p_s: - pat = re.compile( f_p["pattern"] ) - if pat.match(id_in): - lid = id_in + pat = re.compile(f_p["pattern"]) + if pat.match(lid): link = f_p["link"] - pim = f_p.get("prepend_if_missing", "") - if len(pim) > 0: + if len(pim := f_p.get("prepend_if_missing", "")) > 0: if pim in lid: pass else: lid = pim+lid print_uri_rewrite_response(link, lid) - print('Content-Type: text') - print('status:422') - print() - print("No correct id provided. Please refer to the documentation at http://info.progenetix.org/tags/services/") - exit() + BYC.update({"ERRORS": ["No correct id provided. Please refer to the documentation at http://info.progenetix.org/"]}) + BeaconErrorResponse().respond_if_errors() diff --git a/byconServices/intervalFrequencies.py b/byconServices/intervalFrequencies.py index 07bad8d7a..03a577203 100755 --- a/byconServices/intervalFrequencies.py +++ b/byconServices/intervalFrequencies.py @@ -1,11 +1,11 @@ from bycon import BYC_PARS, BeaconErrorResponse from byconServiceLibs import ByconBundler, GenomeBins, ByconServiceResponse, export_pgxseg_frequencies, export_pgxmatrix_frequencies -"""podmd +""" * https://progenetix.org/services/intervalFrequencies/?datasetIds=progenetix&filters=NCIT:C7376,PMID:22824167,pgx:icdom-85003 * https://progenetix.org/services/intervalFrequencies/?datasetIds=progenetix&id=pgxcohort-TCGAcancers * http://progenetix.test/services/intervalFrequencies/?datasetIds=progenetix&output=pgxmatrix&filters=NCIT:C7376,PMID:22824167 -podmd""" +""" def intervalFrequencies(): pdb = ByconBundler().collationsPlotbundles() diff --git a/byconServices/ontologymaps.py b/byconServices/ontologymaps.py index 98d4e0f08..0cfc3cba7 100755 --- a/byconServices/ontologymaps.py +++ b/byconServices/ontologymaps.py @@ -1,9 +1,9 @@ from bycon import BYC, BeaconErrorResponse, print_json_response from byconServiceLibs import ByconServiceResponse, OntologyMaps, read_service_prefs -"""podmd +""" * -podmd""" +""" def ontologymaps(): results = OntologyMaps().ontology_maps_results() diff --git a/byconServices/publications.py b/byconServices/publications.py index b5189415d..c78c3c13a 100755 --- a/byconServices/publications.py +++ b/byconServices/publications.py @@ -12,7 +12,9 @@ ################################################################################ def publications(): - initialize_bycon_service() + """ + ==TBD== + """ read_service_prefs("publications", services_conf_path) f_d_s = BYC.get("filter_definitions", {}) @@ -161,10 +163,10 @@ def _create_filters_query(): continue q_list.append( { dbk: { op: int(no) } } ) elif "start" in filter_precision or len(pre_code) == 1: - """podmd + """ If there was only prefix a regex match is enforced - basically here for the selection of PMID labeled publications. - podmd""" + """ q_list.append( { "id": re.compile(r'^'+f_val ) } ) elif "pgxuse" in f_val: if ":y" in f_val.lower(): diff --git a/byconServices/samplemap.py b/byconServices/samplemap.py index e53172109..a25de8166 100755 --- a/byconServices/samplemap.py +++ b/byconServices/samplemap.py @@ -2,6 +2,9 @@ from byconServiceLibs import ByconMap def samplemap(): + """ + ==TBD== + """ BYC_PARS.update({"marker_type": "marker"}) fd = ByconResultSets().get_flattened_data() BM = ByconMap() diff --git a/byconServices/samplematrix.py b/byconServices/samplematrix.py index 89a56e850..d12af946b 100755 --- a/byconServices/samplematrix.py +++ b/byconServices/samplematrix.py @@ -1,16 +1,15 @@ from bycon import ByconResultSets from byconServiceLibs import GenomeBins, export_callsets_matrix -""" -The service uses the standard bycon data retrieval pipeline with `analysis` -as entity type. Therefore, all standard Beacon query parameters work and also -the path is interpreted for an biosample `id` value if there is an entry at -`.../biosamples/{id}` -# TODO: right now only the first dataset will be exported ... -""" - def samplematrix(): + """ + The service uses the standard bycon data retrieval pipeline with `analysis` + as entity type. Therefore, all standard Beacon query parameters work and also + the path is interpreted for an biosample `id` value if there is an entry at + `.../biosamples/{id}` + """ GenomeBins() rss = ByconResultSets().datasetsResults() + # TODO: right now only the first dataset will be exported ... ds_id = list(rss.keys())[0] export_callsets_matrix(rss, ds_id) diff --git a/byconServices/sampleplots.py b/byconServices/sampleplots.py index a05f9b4c0..2df3f5803 100755 --- a/byconServices/sampleplots.py +++ b/byconServices/sampleplots.py @@ -9,27 +9,29 @@ ExportFile ) -""" -The plot service uses the standard bycon data retrieval pipeline with `biosample` -as entity type. Therefore, all standard Beacon query parameters work and also -the path is interpreted for an biosample `id` value if there is an entry at -`.../sampleplots/{id}` - -The plot type can be set with `plotType=samplesplot` (or `histoplot` but that is -the fallback). Plot options are available as usual. - -* http://progenetix.org/services/sampleplots/pgxbs-kftvjv8w -* http://progenetix.org/services/sampleplots/pgxbs-kftvjv8w?plotType=samplesplot&datasetIds=cellz -* http://progenetix.org/services/sampleplots?plotType=samplesplot&datasetIds=cellz&filters=cellosaurus:CVCL_0030 -* http://progenetix.org/services/sampleplots?filters=pgx:icdom-81703 -* http://progenetix.org/services/sampleplots/?testMode=true&plotType=samplesplot -* http://progenetix.org/services/sampleplots?filters=pgx:icdom-81703&plotType=histoplot&plotPars=plot_chro_height=0::plot_title_font_size=0::plot_area_height=18::plot_margins=0::plot_axislab_y_width=0::plot_grid_stroke=0::plot_footer_font_size=0::plot_width=400 -* http://progenetix.org/services/sampleplots?datasetIds=progenetix&plotMinLength=1000&plotMaxLength=3000000&geneId=CDKN2A&variantType=EFO:0020073&plotPars=plotChros=9::plotGeneSymbols=CDKN2A::plotWidth=300&plotType=histoplot -""" ################################################################################ def sampleplots(): + """ + The plot service uses the standard bycon data retrieval pipeline with `biosample` + as entity type. Therefore, all standard Beacon query parameters work and also + the path is interpreted for an biosample `id` value if there is an entry at + `.../sampleplots/{id}` + + The plot type can be set with `plotType=samplesplot` (or `histoplot` but that is + the fallback). Plot options are available as usual. + + #### Examples (using the Progenetix resource as endpoint): + + * http://progenetix.org/services/sampleplots/pgxbs-kftvjv8w + * http://progenetix.org/services/sampleplots/pgxbs-kftvjv8w?plotType=samplesplot&datasetIds=cellz + * http://progenetix.org/services/sampleplots?plotType=samplesplot&datasetIds=cellz&filters=cellosaurus:CVCL_0030 + * http://progenetix.org/services/sampleplots?filters=pgx:icdom-81703 + * http://progenetix.org/services/sampleplots/?testMode=true&plotType=samplesplot + * http://progenetix.org/services/sampleplots?filters=pgx:icdom-81703&plotType=histoplot&plotPars=plot_chro_height=0::plot_title_font_size=0::plot_area_height=18::plot_margins=0::plot_axislab_y_width=0::plot_grid_stroke=0::plot_footer_font_size=0::plot_width=400 + * http://progenetix.org/services/sampleplots?datasetIds=progenetix&plotMinLength=1000&plotMaxLength=3000000&geneId=CDKN2A&variantType=EFO:0020073&plotPars=plotChros=9::plotGeneSymbols=CDKN2A::plotWidth=300&plotType=histoplot + """ file_id = str(BYC_PARS.get("file_id", "___no-input-file___")) inputfile = Path( path.join( *BYC["local_paths"][ "server_tmp_dir_loc" ], file_id ) ) diff --git a/byconServices/sampletable.py b/byconServices/sampletable.py index ebf86768c..c4a4e67f1 100755 --- a/byconServices/sampletable.py +++ b/byconServices/sampletable.py @@ -1,22 +1,21 @@ from bycon import * from byconServiceLibs import export_datatable_download -""" -The service uses the standard bycon data retrieval pipeline with `biosample` -as entity type. Therefore, all standard Beacon query parameters work and also -the path is interpreted for an biosample `id` value if there is an entry at -`.../sampletable/{id}` -The table type can be changed with `tableType=individuals` (or `analyses`. - -* http://progenetix.org/services/sampletable/pgxbs-kftvjv8w -* http://progenetix.org/services/sampletable?datasetIds=cellz&filters=cellosaurus:CVCL_0030 -* http://progenetix.org/services/sampletable?filters=pgx:icdom-81703 +def sampletable(): + """ + The service uses the standard bycon data retrieval pipeline with `biosample` + as entity type. Therefore, all standard Beacon query parameters work and also + the path is interpreted for an biosample `id` value if there is an entry at + `.../sampletable/{id}` -""" + The table type can be changed with `tableType=individuals` (or `analyses`). -def sampletable(): - prdbug(f'{BYC.get("response_entity_id")}') + #### Examples + * http://progenetix.org/services/sampletable/pgxbs-kftvjv8w + * http://progenetix.org/services/sampletable?datasetIds=cellz&filters=cellosaurus:CVCL_0030 + * http://progenetix.org/services/sampletable?filters=pgx:icdom-81703 + """ fd = ByconResultSets().get_flattened_data() export_datatable_download(fd) diff --git a/byconServices/schemas.py b/byconServices/schemas.py deleted file mode 100755 index 5af5592df..000000000 --- a/byconServices/schemas.py +++ /dev/null @@ -1,20 +0,0 @@ -from bycon import prjsonhead, prjsontrue, BYC, BYC_PARS, BeaconErrorResponse, read_schema_file - -"""podmd -This helper service reads and serves local schema definition files. The name of -the schema (corresponding to the file name minus extension) is provided either -as an `id` query parameter or as the first part of the path after `schemas/`. - -* -podmd""" - -def schemas(): - if (ids := BYC_PARS.get("id"), []): - schema_name = ids[0].split('.').pop(0) - if (s := read_schema_file(schema_name, "")): - prjsonhead() - prjsontrue(s) - exit() - - BYC["ERRORS"].append("No correct schema id provided!") - BeaconErrorResponse().respond_if_errors(422) diff --git a/byconServices/services.py b/byconServices/services.py index 0d7537746..2bf5e0543 100755 --- a/byconServices/services.py +++ b/byconServices/services.py @@ -10,12 +10,6 @@ set_debug_state ) -""" -The `services` application deparses a request URI and calls the respective -script. The functionality is combined with the correct configuration of a -rewrite in the server configuration for creation of canonical URLs. -""" - ################################################################################ ################################################################################ ################################################################################ @@ -29,6 +23,11 @@ def main(): ################################################################################ def services(): + """ + The `services` application deparses a request URI and calls the respective + script. The functionality is combined with the correct configuration of a + rewrite in the server configuration for creation of canonical URLs. + """ set_debug_state(debug=0) rq_id = BYC.get("request_entity_id", "ids") diff --git a/byconServices/uploader.py b/byconServices/uploader.py index e2a9f69d9..2077583e5 100755 --- a/byconServices/uploader.py +++ b/byconServices/uploader.py @@ -10,6 +10,9 @@ ################################################################################ def uploader(): + """ + ==TBD== + """ read_service_prefs("uploader", services_conf_path) file_id = str(uuid4()) form_data = cgi.FieldStorage() diff --git a/byconServices/variantsbedfile.py b/byconServices/variantsbedfile.py index 2931afc63..e4feddc1b 100755 --- a/byconServices/variantsbedfile.py +++ b/byconServices/variantsbedfile.py @@ -1,11 +1,16 @@ from bycon import BYC, BYC_PARS, ByconResultSets, print_uri_rewrite_response from byconServiceLibs import write_variants_bedfile -""" -* http://progenetix.org/services/variantsbedfile/pgxbs-kftvjv8w -""" def variantsbedfile(): + """ + The `variantsbedfile` function provides a BED file with the matched genomic + variants from a Beacon query or a sample id. + + #### Examples + + * http://progenetix.org/services/variantsbedfile/pgxbs-kftvjv8w + """ BYC.update({"request_entity_id": "biosample"}) rss = ByconResultSets().datasetsResults() ds_id = list(rss.keys())[0] diff --git a/byconServices/vcfvariants.py b/byconServices/vcfvariants.py index 9200c50e2..dcc31ed5c 100755 --- a/byconServices/vcfvariants.py +++ b/byconServices/vcfvariants.py @@ -1,18 +1,19 @@ from bycon import BYC, ByconResultSets from byconServiceLibs import export_vcf_download -""" -The VCF service uses the standard bycon data retrieval pipeline with `biosample` -as entity type. Therefore, all standard Beacon query parameters work and also -the path is interpreted for an biosample `id` value if there is an entry at -`.../vcfvariants/{id}` - -* http://progenetix.org/services/vcfvariants/pgxbs-kftvjv8w -""" - ################################################################################ def vcfvariants(): + """ + The VCF service uses the standard bycon data retrieval pipeline with `biosample` + as entity type. Therefore, all standard Beacon query parameters work and also + the path is interpreted for an biosample `id` value if there is an entry at + `.../vcfvariants/{id}` + + #### Examples + + * http://progenetix.org/services/vcfvariants/pgxbs-kftvjv8w + """ # initialize_bycon_service() # TODO: Fix this, to be correctly read from services_entity_defaults BYC.update({"request_entity_id": "biosample"}) diff --git a/docs/generated/services.md b/docs/generated/services.md new file mode 100644 index 000000000..b58cb42ad --- /dev/null +++ b/docs/generated/services.md @@ -0,0 +1,202 @@ +## `byconschemas` + +podmd +This helper service reads and serves local schema definition files. The name of +the schema (corresponding to the file name minus extension) is provided either +as an `id` query parameter or as the first part of the path after `schemas/`. + +* +podmd + + +## `cnvstats` + +==TBD== + + +## `collationplots` + +The `collationplots` function is a service to provide plots for CNV data aggregated +for samples matching individual filter values such as diagnostic codes or experimental +series id values. The default response is an SVG histogram ("histoplot"). Please refer +to the plot parameters documentation and the `ByconPlot` class for other options. + +For a single plot one can provide the entity id as path id value. + +#### Examples (using the Progenetix resource as endpoint): + +* https://progenetix.org/services/collationplots/pgx:cohort-TCGAcancers +* https://progenetix.org/services/collationplots/?filters=NCIT:C7376,PMID:22824167,pgx:icdom-85003 +* https://progenetix.org/services/collationplots/?filters=NCIT:C7376,PMID:22824167&plotType=histoheatplot +* https://progenetix.org/services/collationplots/?collationTypes=icdom&minNumber=1000&plotType=histoheatplot + + +## `collations` + +==TBD== + + +## `cytomapper` + +The `cytomapper` function provides a JSON response with cytoband information +such as matched cytobands and the genome coordinates of their extend. + +#### Examples (using the Progenetix resource as endpoint): + +* https://progenetix.org/services/cytomapper/8q21q24 +* https://progenetix.org/services/cytomapper/13q +* https://progenetix.org/services/cytomapper?chroBases=12:10000000-45000000 + + +## `dbstats` + +==TBD== + +* + + +## `endpoints` + +The service provides the schemas for the `BeaconMap` OpenAPI endpoints. + +#### Examples (using the Progenetix resource as endpoint): + +* +* + + +## `genespans` + +The `genespans` function provides a JSON response with the coordinates of +matching gene IDs. + +#### Examples (using the Progenetix resource as endpoint): + +* https://progenetix.test/services/genespans/MYC +* https://progenetix.test/services/genespans/?geneId=MYC + + +## `geolocations` + +None + + +## `ids` + +The `ids` service forwards compatible, prefixed ids (see `config/ids.yaml`) to specific +website endpoints. There is no check if the id exists; this is left to the web +page handling itself. + +Stacking with the "pgx:" prefix is allowed. + +#### Examples (using the Progenetix resource as endpoint): + +* +* +* + + +## `intervalFrequencies` + +None + + +## `ontologymaps` + +None + + +## `pgxsegvariants` + +None + + +## `publications` + +==TBD== + + +## `samplemap` + +==TBD== + + +## `samplematrix` + +The service uses the standard bycon data retrieval pipeline with `analysis` +as entity type. Therefore, all standard Beacon query parameters work and also +the path is interpreted for an biosample `id` value if there is an entry at +`.../biosamples/{id}` + + +## `sampleplots` + +The plot service uses the standard bycon data retrieval pipeline with `biosample` +as entity type. Therefore, all standard Beacon query parameters work and also +the path is interpreted for an biosample `id` value if there is an entry at +`.../sampleplots/{id}` + +The plot type can be set with `plotType=samplesplot` (or `histoplot` but that is +the fallback). Plot options are available as usual. + +#### Examples (using the Progenetix resource as endpoint): + +* http://progenetix.org/services/sampleplots/pgxbs-kftvjv8w +* http://progenetix.org/services/sampleplots/pgxbs-kftvjv8w?plotType=samplesplot&datasetIds=cellz +* http://progenetix.org/services/sampleplots?plotType=samplesplot&datasetIds=cellz&filters=cellosaurus:CVCL_0030 +* http://progenetix.org/services/sampleplots?filters=pgx:icdom-81703 +* http://progenetix.org/services/sampleplots/?testMode=true&plotType=samplesplot +* http://progenetix.org/services/sampleplots?filters=pgx:icdom-81703&plotType=histoplot&plotPars=plot_chro_height=0::plot_title_font_size=0::plot_area_height=18::plot_margins=0::plot_axislab_y_width=0::plot_grid_stroke=0::plot_footer_font_size=0::plot_width=400 +* http://progenetix.org/services/sampleplots?datasetIds=progenetix&plotMinLength=1000&plotMaxLength=3000000&geneId=CDKN2A&variantType=EFO:0020073&plotPars=plotChros=9::plotGeneSymbols=CDKN2A::plotWidth=300&plotType=histoplot + + +## `sampletable` + +The service uses the standard bycon data retrieval pipeline with `biosample` +as entity type. Therefore, all standard Beacon query parameters work and also +the path is interpreted for an biosample `id` value if there is an entry at +`.../sampletable/{id}` + +The table type can be changed with `tableType=individuals` (or `analyses`). + +#### Examples + +* http://progenetix.org/services/sampletable/pgxbs-kftvjv8w +* http://progenetix.org/services/sampletable?datasetIds=cellz&filters=cellosaurus:CVCL_0030 +* http://progenetix.org/services/sampletable?filters=pgx:icdom-81703 + + +## `services` + +The `services` application deparses a request URI and calls the respective +script. The functionality is combined with the correct configuration of a +rewrite in the server configuration for creation of canonical URLs. + + +## `uploader` + +==TBD== + + +## `variantsbedfile` + +The `variantsbedfile` function provides a BED file with the matched genomic +variants from a Beacon query or a sample id. + +#### Examples + +* http://progenetix.org/services/variantsbedfile/pgxbs-kftvjv8w + + +## `vcfvariants` + +The VCF service uses the standard bycon data retrieval pipeline with `biosample` +as entity type. Therefore, all standard Beacon query parameters work and also +the path is interpreted for an biosample `id` value if there is an entry at +`.../vcfvariants/{id}` + +#### Examples + +* http://progenetix.org/services/vcfvariants/pgxbs-kftvjv8w + + diff --git a/docs/importers/index.md b/docs/importers/index.md index 75fc18f83..016c47155 100644 --- a/docs/importers/index.md +++ b/docs/importers/index.md @@ -4,4 +4,21 @@ Importing and updating of data for `bycon` databases is discussed in this section. The relevant apps can be found in the `importers` directory in the project's root. +## Importing Records in an Existing Database + +### Import Table Formats + +Importing new sample data alwaays requires the initial import of +_analysis_ data, _i.e._ at least an experimental identifier which then acts as +a reference for the genomic variants. + +The importers are designed to handle a tab-delimited data file +in which the first line contains column headers which have to correspond +to values in the `datatable_definitions.yaml` file. However, it is not necessary to +create separate files for all `analyses` & `biosamples` & `individuala` +entities; the importers will handle the data in a single file +which makes sense when having singular relation 1 individual => 1 biosample => 1 analysis (=> n variants). + + + ==TBD== \ No newline at end of file diff --git a/docs/installation.md b/docs/installation.md index ea043b174..32692d343 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -49,9 +49,6 @@ general installation and might contain deprecated code or dependencies through t * documentation, in Markdown, as source for documentation builded with `mkdocs` -### `lib` - -* Python libraries ### `rsrc` diff --git a/housekeepers/housekeeping.py b/housekeepers/housekeeping.py index 09c9cd3f9..6c16f7b18 100755 --- a/housekeepers/housekeeping.py +++ b/housekeepers/housekeeping.py @@ -29,9 +29,9 @@ def main(): # TODO: rewrap, use config etc. generated_docs_path = path.join( loc_path, pardir, "docs", "generated") - bycon_generated_docs_path = path.join( loc_path, pardir, pardir, "bycon", "docs", "generated") + # bycon_generated_docs_path = path.join( loc_path, pardir, pardir, "bycon", "docs", "generated") doc_generator(generated_docs_path) - doc_generator(bycon_generated_docs_path) + # doc_generator(bycon_generated_docs_path) ds_id = assertSingleDatasetOrExit() diff --git a/housekeepers/lib/doc_generator.py b/housekeepers/lib/doc_generator.py index 49868d2ea..6739e56ce 100644 --- a/housekeepers/lib/doc_generator.py +++ b/housekeepers/lib/doc_generator.py @@ -1,4 +1,8 @@ from config import * +from os import path, pardir + +loc_path = path.dirname( path.abspath(__file__) ) +pkg_path = path.join(loc_path, pardir, pardir) def doc_generator(generated_docs_path): if path.exists(generated_docs_path): diff --git a/markdowner.py b/markdowner.py new file mode 100755 index 000000000..15bb7a66b --- /dev/null +++ b/markdowner.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 + +import inspect, sys, re, yaml +from os import getlogin, makedirs, path, system +from pathlib import Path + +dir_path = path.dirname( path.abspath(__file__) ) + +import byconServices + +################################################################################ + +def main(): + generated_docs_path = path.join( dir_path, "docs", "generated") + + p = Path(path.join( dir_path, "byconServices" )) + s_p_s = [ f for f in p.rglob("*.py") if f.is_file() ] + + pp_f = path.join(generated_docs_path, f"services.md") + pp_fh = open(pp_f, "w") + md = [] + for f in sorted(s_p_s): + fn = f.name.split('.')[0] + if fn in [ "__init__"]: + continue + # print(f'from {fn} import {fn}') + + pp_fh.write(f'## `{fn}`\n\n') + + func = getattr(byconServices, fn) + pp_fh.write(f'{inspect.getdoc(func)}\n\n\n') + + pp_fh.close() + + +################################################################################ +################################################################################ +################################################################################ + +if __name__ == '__main__': + main() diff --git a/mkdocs.yaml b/mkdocs.yaml index cd19c40f4..4c44095f3 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -13,6 +13,7 @@ nav: - Maintenance: housekeepers - Recent Changes: changes - Upcoming & To Do: future + - Services: generated/services - Parameters: generated/argument_definitions - API Tests: tests - Progenetix Site: http://progenetix.org