class UpdateTermReadme(): def __init__(self, owl_file): self.owl = OwlReader(owl_file) # Write out Readme def write_readme(self, readme_file, readme_txt): readme_file_open = open(readme_file, 'w') readme_file_open.write(readme_txt) readme_file_open.close() def create_term_row(self, term_name, definition, same_as, editor, note, color, range_value=None, domain=None, indiv_type=None): img_color = "" if color: img_color = '<img src="../../../doc/content/specs/img/'+color+'.png?raw=true"/> ' if same_as: same_as = "(same as: <a href="+same_as+">"+same_as+"</a>)" range_domain_type = "" if range_value is not None: range_domain_type = """ <td>"""+domain+"""</td> <td>"""+range_value+"""</td>""" if indiv_type is not None: range_domain_type += """ <td>"""+indiv_type+"""</td>""" # Github mardow-like links nidm_repo = "https://github.com/incf-nidash/nidm/" stato_repo = "https://github.com/ISA-tools/stato/" nidm_pr_issue = re.compile(nidm_repo+r'[a-zA-Z]*/(\d+)') note = nidm_pr_issue.sub(r'<a href="'+nidm_repo+r'pull/\1">'+r'#\1</a>', note) stato_pr_issue = re.compile(stato_repo+r'[a-zA-Z]*/(\d+)') note = stato_pr_issue.sub(r'<a href="'+stato_repo+r'pull/\1">'+r'ISA-tools/stato#\1</a>', note) if note: note = note+"<br/>" # Add a search link (to check current state of the repo) if "Under discussion" in note: search_text = "more" else: search_text = "find issues/PR" note = note+"<a href=\""+nidm_repo+"/issues?&q="+term_name.split(":")[1]+"\"> ["+search_text+"] </a>" term_row = """ <tr> <td>"""+img_color+"""</td> <td>"""+note+"""</td> <td><b>"""+term_name+""": </b>"""+definition+same_as+editor+"""</td>"""+range_domain_type+""" </tr>""" return term_row def create_curation_legend(self, order): curation_legend = "<b>Curation status</b>: \n" curation_colors_sorted = [(key, CURATION_COLORS.get(key)) for key in order] covered_colors = list() for curation_color in curation_colors_sorted: # curation_status = str(self.owl.qname(curation_color[0])) # curation_status_labels = self.owl.objects(curation_color[0], RDFS['label']) # curation_status = ", ".join(list(curation_status_labels)) color = curation_color[1] if not color in covered_colors: curation_legend = curation_legend+'<img src="../../../doc/content/specs/img/'+color+'.png?raw=true"/> '+\ CURATION_LEGEND[color]+";\n" covered_colors.append(color) return curation_legend # Get README text according to owl file information def update_readme(self, readme_file): class_terms = dict() prpty_terms = dict() indiv_terms = dict() definitions = dict() editors = dict() notes = dict() ranges = dict() domains = dict() sameas = dict() types = dict() for owl_term in self.owl.classes.union(self.owl.properties).union(self.owl.individuals): curation_status = self.owl.get_curation_status(owl_term) definition = self.owl.get_definition(owl_term) if definition == "": definition = "<undefined>" editor = self.owl.get_editor(owl_term) note = self.owl.get_editor_note(owl_term) range_value = self.owl.get_range(owl_term) domain = self.owl.get_domain(owl_term) same = self.owl.get_same_as(owl_term) indiv_type = self.owl.get_individual_type(owl_term) if curation_status: curation_key = curation_status term_key = self.owl.get_label(owl_term) if term_key.startswith("nidm") or term_key.startswith("spm") or\ term_key.startswith("fsl") or term_key.startswith("afni"): if owl_term in self.owl.classes: class_terms.setdefault(curation_key, list()).append(term_key) else: if owl_term in self.owl.properties: prpty_terms.setdefault(curation_key, list()).append(term_key) else: if owl_term in self.owl.individuals: indiv_terms.setdefault(curation_key, list()).append(term_key) definitions[term_key] = definition editors[term_key] = editor notes[term_key] = note ranges[term_key] = range_value domains[term_key] = domain sameas[term_key] = same types[term_key] = indiv_type # Include missing keys and do not display ready for release terms order=CURATION_ORDER+(list(set(class_terms.keys()).union(set(prpty_terms.keys())) - set(CURATION_ORDER+list([OBO_READY])))) class_terms_sorted = [(key, class_terms.get(key)) for key in order] prpty_terms_sorted = [(key, prpty_terms.get(key)) for key in order] indiv_terms_sorted = [(key, indiv_terms.get(key)) for key in order] class_table_txt = "<h2>Classes</h2>\n<table>\n<tr><th>Curation Status</th><th>Issue/PR</th><th>Term</th></tr>" for tuple_status_term in class_terms_sorted: curation_status = tuple_status_term[0] class_names = tuple_status_term[1] if class_names: for class_name in sorted(class_names): class_table_txt += self.create_term_row(class_name, \ definitions[class_name], \ sameas[class_name], \ editors[class_name], \ notes[class_name], \ CURATION_COLORS.setdefault(curation_status, "")) class_table_txt = class_table_txt+"\n</table>" prpty_table_txt = "<h2>Properties</h2>\n<table>\n<tr><th>Curation Status</th><th>Issue/PR</th><th>Term</th><th>Domain</th><th>Range</th></tr>" for tuple_status_term in prpty_terms_sorted: curation_status = tuple_status_term[0] term_names = tuple_status_term[1] if term_names: for term_name in sorted(term_names): prpty_table_txt += self.create_term_row(term_name, \ definitions[term_name], \ sameas[term_name], \ editors[term_name], \ notes[term_name], \ CURATION_COLORS.setdefault(curation_status, ""), \ ranges[term_name], \ domains[term_name]) prpty_table_txt = prpty_table_txt+"\n</table>" indiv_table_txt = "<h2>Individuals</h2>\n<table>\n<tr><th>Curation Status</th><th>Issue/PR</th><th>Term</th><th>Type</th></tr>" for tuple_status_term in indiv_terms_sorted: curation_status = tuple_status_term[0] term_names = tuple_status_term[1] if term_names: for term_name in sorted(term_names): indiv_table_txt += self.create_term_row(term_name, \ definitions[term_name], \ sameas[term_name], \ editors[term_name], \ notes[term_name], \ CURATION_COLORS.setdefault(curation_status, ""), \ None, None, types[term_name]) indiv_table_txt = indiv_table_txt+"\n</table>" curation_legend = self.create_curation_legend(order) title = "<h1>NIDM-Results Terms curation status</h1>" intro = """You will find below a listing of the NIDM-Results terms that \ need to be curated. If you would like **to help with the curation of a term, \ please follow those steps**: 1. Check if the terms is already under discussion in an issue. 2. If not, create a new issue including the current definition (available in\ the table below) and your proposed update. If possible, priority should be given to uncurated terms (in red). Thank you in advance for taking part in NIDM-Results term curation!\n\n""" self.write_readme(readme_file, title+intro+\ curation_legend+class_table_txt+prpty_table_txt+indiv_table_txt)
class OwlSpecification(object): def __init__(self, owl_file, import_files, spec_name, subcomponents=None, used_by=None, generated_by=None, derived_from=None, prefix=None, commentable=False, intro=None): self.owl = OwlReader(owl_file, import_files) self.owl.graph.bind('nidm', 'http://purl.org/nidash/nidm#') self.name = spec_name self.component = self.name.lower().replace("-", "_") self.section_open = 0 self.already_defined_classes = list() self.commentable = commentable self.attributes_done = set() self.text = "" self.create_specification(subcomponents, used_by, generated_by, derived_from, prefix, intro) def create_specification(self, subcomponents, used_by, generated_by, derived_from, prefix, intro=None): self.create_title(self.name + ": Types and relations", "definitions") if intro is not None: self.text += intro table_num = 3 for subcomponent_name, classes in subcomponents.items(): classes_by_types = self.owl.get_class_names_by_prov_type( classes, prefix=prefix, but=self.already_defined_classes) self.already_defined_classes += classes self.create_subcomponent_table(classes_by_types, table_num, subcomponent_name) table_num = table_num + 1 all_classes = classes_by_types[PROV['Agent']] + \ classes_by_types[PROV['Activity']] + \ classes_by_types[PROV['Entity']] + \ classes_by_types[None] for class_name in all_classes: self.create_class_section( class_name, self.owl.get_definition(class_name), self.owl.attributes.setdefault(class_name, None), used_by, generated_by, derived_from, children=not (self.owl.get_prov_class(class_name) == PROV['Entity'])) if subcomponent_name: self.text += """ </section>""" self.close_sections() def create_subcomponent_table(self, classes, table_num, subcomponent_name=None): if subcomponent_name: self.text += """ <section><h1>""" + subcomponent_name + """</h1>""" # Check if there is a header file to include here fname = os.path.join( INCLUDE_FOLDER, self.component + "_" + subcomponent_name.split(" ")[0].lower() + ".html") if os.path.isfile(fname): fid = open(fname, "r") self.text += fid.read() fid.close() else: subcomponent_name = "" # Did not find how to handle table numbering and ids with Respec as we # did for figures? table_id = "prov-mapping-" "" + subcomponent_name.lower() self.text += """ <div style="text-align: left;"> <table class="thinborder" \ style="margin-left: auto; margin-right: auto;"> <caption id=\"""" + table_id + """\">\ <a class="internalDFN" href=\"#""" + table_id + """\">\ Table """ + str(table_num) + """</a>:""" + self.name + """\ """ + subcomponent_name + """ Concepts</caption> \ <tbody> <tr> <th align="center"><b>""" + self.name + """ Concept</b>\ </th> <th align="center"><b>PROV type</b></th> <th align="center"><b>Identifier</b></th> </tr> """ self.text += """ <!-- HERE ------------- Beginning of PROV Entities ------------- --> """ for prov_class in list( [PROV['Agent'], PROV['Activity'], PROV['Entity']]): sorted_classes = classes[prov_class] for class_uri in sorted_classes: self.text += """ <tr> <td>""" + self.term_link(class_uri) + """ </td> """ # First iteration if class_uri is sorted_classes[0]: self.text += """ <td rowspan=\""""+str(len(sorted_classes)) + \ """\" style="text-align: center;"> """ + \ self.owl.get_label(prov_class) + \ """</td> """ self.text += """ <td>"""+self.owl.graph.qname(class_uri) + \ """</td> </tr> """ self.text += """ </tbody> </table> </div>""" def create_title(self, title, id=None): if id is None: self.text += """ <section> """ else: self.text += """ <section id=\"""" + id + """\"> """ self.text += """ <h1>""" + title + """</h1> """ self.section_open += 1 def _format_markdown(self, text): # Replace links specified in markdown by html text = markdown2.markdown(text).replace("<p>", "").replace("</p>", "") # Remove trailing new line text = text[0:-1] return text def format_definition(self, definition): # Capitalize first letter, format markdown and end with dot if definition: definition = definition[0].upper() + definition[1:] definition = self._format_markdown(definition) definition += "." return definition def linked_listing(self, uri_list, prefix="", suffix="", sort=True): linked_listing = prefix if sort: uri_list = self.owl.sorted_by_labels(uri_list) for i, uri in enumerate(uri_list): if i == 0: sep = "" elif i == len(uri_list): sep = " and " else: sep = ", " linked_listing += sep + self.term_link(uri) return linked_listing + suffix def term_link(self, term_uri, tag="a", text=None): href = "" if self.owl.is_external_namespace(term_uri): href = " href =\"" + str(term_uri) + "\"" if text is None: text = self.owl.get_label(term_uri) term_link = "<" + tag + " title=\"" + self.owl.get_name(term_uri) + \ "\"" + href + ">" + text+"</"+tag+">" # # This could be handled by Respec, here we overwrite the id and href # # fields in order to be able to have an id that is not generated from # # the title field. e.g. title = nidm_0000001 (nidm:Map) and # # id = nidm_0000001 # name_lw = self.owl.get_name(term_uri).lower() # if tag is "dfn": # link_info = " id=\"dfn-" + name_lw + "\"" # elif tag is "a": # link_info = " href=\"#dfn-" + name_lw + "\"" # term_link = "<" + tag + link_info + \ # " class=\"internalDFN\"" + \ # " title=\"" + self.owl.get_name(term_uri) + \ # " (" + self.owl.get_label(term_uri) + ")" + \ # "\"" + href + ">" + text + "</" + tag + ">" if tag is "dfn": issue_url = "https://github.com/incf-nidash/nidm/issues" # Add link to current definition term_link = self.term_link(term_uri, text=term_link) if self.commentable: term_link = term_link + \ " <a href=\""+issue_url+"?&q=is%3Aopen+'" + text + \ "'\"\"><sup>☆</sup></a>" + \ "<a href=\""+issue_url+"/new\";\"><sup>+</sup></a>" return term_link def create_class_section(self, class_uri, definition, attributes, used_by=None, generated_by=None, derived_from=None, children=False, is_range=False): class_label = self.owl.get_label(class_uri) class_name = self.owl.get_name(class_uri) definition = self.format_definition(definition) self.text += """ <!-- """ + class_label + """ (""" + class_name + """)""" + """ --> <section id="section-""" + class_label + """"> <h1 label=\"""" + class_name + """\">""" + class_label + """</h1> <div class="glossary-ref"> """ + self.term_link(class_uri, "dfn") + ": " + definition self.text += "<p> " + self.term_link(class_uri) + " is" nidm_class = self.owl.get_nidm_parent(class_uri) if nidm_class: self.text += " a " + self.term_link(nidm_class) else: prov_class = self.owl.get_prov_class(class_uri) if prov_class: self.text += " a " + self.owl.get_label(prov_class) found_used_by = False if used_by: if class_uri in used_by: self.text += self.linked_listing(used_by[class_uri], " used by ") found_used_by = True used_entities = list() for used_entity, used_activities in used_by.items(): for used_act in used_activities: if used_act == class_uri: used_entities.append(used_entity) if used_entities: self.text += self.linked_listing(used_entities, " that uses ", " entities") found_generated_by = False if generated_by: if class_uri in generated_by: if found_used_by: self.text += " and " self.text += self.linked_listing( list([generated_by[class_uri]]), " generated by ") found_generated_by = True if class_uri in generated_by.values(): generated_entities = list() for generated_entity, generated_act in generated_by.items(): if generated_act == class_uri: generated_entities.append(generated_entity) if generated_entities: self.text += self.linked_listing( generated_entities, ". This activity generates ", " entities") if derived_from: if class_uri in derived_from: if found_used_by or found_generated_by: self.text += " and " self.text += self.linked_listing( list([derived_from[class_uri]]), " derived from ") class_children = self.owl.get_direct_children(class_uri) if class_children: if found_used_by or found_generated_by: self.text += ". It " else: self.text += " and " self.text += " has the following child" if len(class_children) > 1: self.text += "ren" self.text += ": " + \ self.linked_listing(class_children) self.text += "." self.text += "</p>" range_classes = list() self.text += """ </div>""" if attributes and (attributes != set([CRYPTO['sha512']])): self.text += """ <p></p> <div class="attributes" id="attributes-"""+class_label + \ """"> A """ + \ self.term_link(class_uri)+""" has attributes: <ul> <li><span class="attribute" id=\"""" + \ class_label+""".label">rdfs:label</span>: \ (<em class="rfc2119" title="OPTIONAL">OPTIONAL</em>) """\ """Human readable description of the """ + \ self.term_link(class_uri)+""".</li>""" for att in sorted(attributes): # Do not display prov relations as attributes # (except prov:atLocation...) if not self.owl.is_prov(att) or (att == PROV['atLocation']): if att not in self.attributes_done: # First definition of this attribute att_tag = "dfn" else: att_tag = "a" self.attributes_done.add(att) # if att_label.startswith("nidm:"): att_def = self.owl.get_definition(att) self.text += """ <li>"""+self.term_link(att, att_tag) + \ '</span>: (<em class="rfc2119" title="OPTIONAL">' + \ 'OPTIONAL</em>) ' + self.format_definition(att_def) if att in self.owl.parent_ranges: child_ranges = list() for parent_range in self.owl.parent_ranges[att]: child_ranges += self.owl.get_direct_children( parent_range) if self.owl.get_label(parent_range).\ startswith('nidm'): range_classes.append(parent_range) child_ranges = sorted(child_ranges) # if nidm_namespace: child_range_txt = "" if child_ranges: # Get all child ranges child_range_txt = self.linked_listing( child_ranges, " such as ") self.text += self.linked_listing( self.owl.parent_ranges[att], " (range ", child_range_txt + ")") self.text += "." self.text += "</li>" self.text += """ </ul> </div>""" BASE_REPOSITORY = "https://raw.githubusercontent.com/" + \ "incf-nidash/nidm/master/" for title, example in self.owl.get_example(class_uri, BASE_REPOSITORY): self.text += """ </ul> </div> <pre class='example highlight' title=\""""+title+"""\">""" + \ cgi.escape(example) + """</pre>""" # For object property list also children (in sub-sections) if children: direct_children = self.owl.sorted_by_labels( self.owl.get_direct_children(class_uri)) for child in direct_children: if not child in self.already_defined_classes: self.create_class_section(child, self.owl.get_definition(child), self.owl.attributes.setdefault( child, None), children=True) self.already_defined_classes.append(child) # Display individuals individuals = self.owl.sorted_by_labels( self.owl.get_individuals(class_uri)) if individuals: self.text += \ " Examples of "+self.term_link(class_uri)+" includes " + \ "<ul>" for indiv in individuals: self.text += "<li>" + self.term_link(indiv, "dfn") + ": " + \ self.format_definition( self.owl.get_definition(indiv)) + \ "</li>" self.text += "</ul>" if is_range: self.text += """ </section>""" for range_name in self.owl.sorted_by_labels(range_classes): if not range_name in self.already_defined_classes: self.already_defined_classes.append(range_name) self.create_class_section(range_name, self.owl.get_definition(range_name), self.owl.attributes.setdefault( range_name, None), children=True, is_range=True) if not is_range: self.text += """ </section>""" def close_sections(self): for x in range(0, self.section_open): self.text += "\t" * x + "</section>\n" # Write out specification def write_specification(self, spec_file=None, component=None, version=None): if component and version: spec_file = os.path.join(DOC_FOLDER, component + "_" + version + ".html") spec_open = codecs.open(spec_file, 'w', "utf-8") spec_open.write(self.text) spec_open.close() def _header_footer(self, prev_file=None, follow_file=None, component=None, version=None): release_notes = None if component: prev_file = os.path.join(INCLUDE_FOLDER, component + "_" + version + "_head.html") if not os.path.isfile(prev_file): prev_file = os.path.join(INCLUDE_FOLDER, component + "_head.html") follow_file = os.path.join( INCLUDE_FOLDER, component + "_" + version + "_foot.html") if not os.path.isfile(follow_file): follow_file = os.path.join(INCLUDE_FOLDER, component + "_foot.html") if version: release_notes = os.path.join( os.path.dirname(self.owl.file), component + "_" + version + "_notes.html") if not os.path.isfile(release_notes): release_notes = None if prev_file is not None: prev_file_open = open(prev_file, 'r') self.text = prev_file_open.read().decode('utf-8') + self.text prev_file_open.close() if release_notes is not None: release_note_open = open(release_notes, 'r') self.text = self.text + release_note_open.read() release_note_open.close() if follow_file is not None: follow_file_open = open(follow_file, 'r') self.text = self.text + follow_file_open.read() follow_file_open.close()
class OwlSpecification(object): def __init__(self, owl_file, import_files, spec_name, subcomponents=None, used_by=None, generated_by=None, derived_from=None, prefix=None): self.owl = OwlReader(owl_file, import_files) self.owl.graph.bind('nidm', 'http://purl.org/nidash/nidm#') self.name = spec_name self.component = self.name.lower().replace("-", "_") self.section_open = 0 self.already_defined_classes = list() self.attributes_done = set() self.text = "" self.create_specification(subcomponents, used_by, generated_by, derived_from, prefix) def create_specification(self, subcomponents, used_by, generated_by, derived_from, prefix): self.create_title(self.name+": Types and relations") # If no subcomponents are defined display all classes if not subcomponents: subcomponents = dict([(None, self.owl.classes)]) table_num = 3 for subcomponent_name, classes in subcomponents.items(): classes_by_types = self.owl.get_class_names_by_prov_type( classes, prefix=prefix, but=self.already_defined_classes) self.already_defined_classes += classes self.create_subcomponent_table(classes_by_types, table_num, subcomponent_name) table_num = table_num + 1 all_classes = sorted(classes_by_types[PROV['Agent']]) + \ sorted(classes_by_types[PROV['Activity']]) + \ sorted(classes_by_types[PROV['Entity']]) + \ sorted(classes_by_types[None]) for class_name in all_classes: self.create_class_section( class_name, self.owl.get_definition(class_name), self.owl.attributes.setdefault(class_name, None), used_by, generated_by, derived_from) if subcomponent_name: self.text += """ </section>""" self.close_sections() def create_subcomponent_table(self, classes, table_num, subcomponent_name=None): if subcomponent_name: self.text += """ <section><h1>"""+subcomponent_name+"""</h1>""" # Check if there is a header file to include here fname = os.path.join( INCLUDE_FOLDER, self.component+"_" + subcomponent_name.split(" ")[0].lower()+".html") if os.path.isfile(fname): fid = open(fname, "r") self.text += fid.read() fid.close() else: subcomponent_name = "" # Did not find how to handle table numbering and ids with Respec as we # did for figures? table_id = "prov-mapping-"""+subcomponent_name.lower() self.text += """ <div style="text-align: left;"> <table class="thinborder" \ style="margin-left: auto; margin-right: auto;"> <caption id=\""""+table_id+"""\">\ <a class="internalDFN" href=\"#"""+table_id+"""\">\ Table """+str(table_num)+"""</a>: Mapping of """+self.name+""" """+subcomponent_name + \ """ Core Concepts to types and relations \ and PROV core concepts</caption> \ <tbody> <tr> <td><b>"""+self.name+""" Concepts</b></td> <td><b>Types or Relation (PROV concepts)</b></td> <td><b>Name</b></td> </tr> """ self.text += """ <!-- HERE ------------- Beginning of PROV Entities ------------- --> """ for prov_class in list([ PROV['Agent'], PROV['Activity'], PROV['Entity']]): sorted_classes = sorted(classes[prov_class]) for class_uri in sorted_classes: self.text += """ <tr> <td>"""+self.term_link(class_uri)+""" </td> """ # First iteration if class_uri is sorted_classes[0]: self.text += """ <td rowspan=\""""+str(len(sorted_classes)) + \ """\" style="text-align: center;">""" + \ self.name+""" Types<br/> \ (PROV """ + \ self.owl.get_label(prov_class).replace('prov:', '') + \ """)</td> """ self.text += """ <td>"""+self.term_link(class_uri)+"""</td> </tr> """ self.text += """ </tbody> </table> </div>""" def create_title(self, title): self.text += """ <section> <h1>"""+title+"""</h1> """ self.section_open += 1 def _format_markdown(self, text): # Replace links specified in markdown by html match = re.search(r'\[(?P<name>.*)\]\((?P<link>.*)\)', text) if match: text = text.replace( match.group(), '<a href="'+match.group('link')+'">' + match.group('name')+'</a>') return text def format_definition(self, definition): # Capitalize first letter of definition if definition: definition = definition[0].upper() + definition[1:] definition = self._format_markdown(definition) return definition def linked_listing(self, uri_list, prefix="", suffix=""): linked_listing = prefix for i, uri in enumerate(self.owl.sorted_by_labels(uri_list)): if i == 0: sep = "" elif i == len(uri_list): sep = " and " else: sep = ", " linked_listing += sep+self.term_link(uri) return linked_listing+suffix def term_link(self, term_uri, tag="a", text=None): href = "" if self.owl.is_external_namespace(term_uri): href = " href =\""+str(term_uri)+"\"" if text is None: text = self.owl.get_label(term_uri) term_link = "<" + tag + " title=\"" + self.owl.get_name(term_uri) + \ "\"" + href + ">" + text+"</"+tag+">" # # This could be handled by Respec, here we overwrite the id and href # # fields in order to be able to have an id that is not generated from # # the title field. e.g. title = nidm_0000001 (nidm:Map) and # # id = nidm_0000001 # name_lw = self.owl.get_name(term_uri).lower() # if tag is "dfn": # link_info = " id=\"dfn-" + name_lw + "\"" # elif tag is "a": # link_info = " href=\"#dfn-" + name_lw + "\"" # term_link = "<" + tag + link_info + \ # " class=\"internalDFN\"" + \ # " title=\"" + self.owl.get_name(term_uri) + \ # " (" + self.owl.get_label(term_uri) + ")" + \ # "\"" + href + ">" + text + "</" + tag + ">" if tag is "dfn": # Add link to current definition term_link = self.term_link(term_uri, text=term_link) return term_link def create_class_section(self, class_uri, definition, attributes, used_by=None, generated_by=None, derived_from=None, children=False): class_label = self.owl.get_label(class_uri) class_name = self.owl.get_name(class_uri) definition = self.format_definition(definition) self.text += """ <!-- """+class_label+""" ("""+class_name+""")"""+""" --> <section id="section-"""+class_label+""""> <h1 label=\""""+class_name+"""\">"""+class_label+"""</h1> <div class="glossary-ref"> """+self.term_link(class_uri, "dfn") + ": " + definition self.text += " "+self.term_link(class_uri)+" is" prov_class = self.owl.get_prov_class(class_uri) if prov_class: self.text += " a "+self.owl.get_label(prov_class) found_used_by = False if used_by: if class_uri in used_by: self.text += self.linked_listing(used_by[class_uri], " used by ") found_used_by = True used_entities = list() for used_entity, used_activities in used_by.items(): for used_act in used_activities: if used_act == class_uri: used_entities.append(used_entity) if used_entities: self.text += self.linked_listing(used_entities, " that uses ", " entities") found_generated_by = False if generated_by: if class_uri in generated_by: if found_used_by: self.text += " and " self.text += self.linked_listing( list([generated_by[class_uri]]), " generated by ") found_generated_by = True if class_uri in generated_by.values(): generated_entities = list() for generated_entity, generated_act in generated_by.items(): if generated_act == class_uri: generated_entities.append(generated_entity) if generated_entities: self.text += self.linked_listing( generated_entities, ". This activity generates ", " entities") if derived_from: if class_uri in derived_from: if found_used_by or found_generated_by: self.text += " and " self.text += self.linked_listing( list([derived_from[class_uri]]), " derived from ") self.text += "." range_classes = list() if attributes and (attributes != set([CRYPTO['sha512']])): self.text += """ </div> <p></p> <div class="attributes" id="attributes-"""+class_label + \ """"> A """ + \ self.term_link(class_uri)+""" has attributes: <ul> <li><span class="attribute" id=\"""" + \ class_label+""".label">rdfs:label</span>: \ (<em class="rfc2119" title="OPTIONAL">OPTIONAL</em>) """\ """Human readable description of the """ + \ self.term_link(class_uri)+""".</li>""" for att in sorted(attributes): # Do not display prov relations (used, wasGeneratedBy...) as # attributes if not self.owl.get_label(att).startswith("prov"): if att not in self.attributes_done: # First definition of this attribute att_tag = "dfn" else: att_tag = "a" self.attributes_done.add(att) # if att_label.startswith("nidm:"): att_def = self.owl.get_definition(att) self.text += """ <li>"""+self.term_link(att, att_tag) + \ '</span>: (<em class="rfc2119" title="OPTIONAL">' + \ 'OPTIONAL</em>) ' + self.format_definition(att_def) if att in self.owl.parent_ranges: child_ranges = list() for parent_range in self.owl.parent_ranges[att]: child_ranges += self.owl.get_direct_children( parent_range) child_ranges = sorted(child_ranges) # if nidm_namespace: child_range_txt = "" if child_ranges: # Get all child ranges child_range_txt = self.linked_listing( child_ranges, " such as ") self.text += self.linked_listing( self.owl.parent_ranges[att], " (range ", child_range_txt+")") self.text += "." for range_class in sorted(self.owl.ranges[att]): if self.owl.get_label(range_class).\ startswith('nidm'): range_classes.append(range_class) self.text += "</li>" BASE_REPOSITORY = "https://raw.githubusercontent.com/" + \ "incf-nidash/nidm/master/" examples = self.owl.get_example(class_uri, BASE_REPOSITORY) for example in sorted(examples): self.text += """ </ul> </div> <pre class='example highlight'>"""+cgi.escape(example) + \ """</pre>""" for range_name in range_classes: if not range_name in self.already_defined_classes: self.already_defined_classes.append(range_name) self.create_class_section( range_name, self.owl.get_definition(range_name), self.owl.attributes.setdefault(range_name, None), children=True) # For object property list also children (in sub-sections) if children: direct_children = self.owl.sorted_by_labels( self.owl.get_direct_children(class_uri)) for child in direct_children: if not child in self.already_defined_classes: self.create_class_section( child, self.owl.get_definition(child), self.owl.attributes.setdefault(child, None), children=True) self.already_defined_classes.append(child) # Display individuals individuals = self.owl.sorted_by_labels( self.owl.get_individuals(class_uri)) if individuals: self.text += \ " Examples of "+self.term_link(class_uri)+" includes " + \ "<ul>" for indiv in individuals: self.text += "<li>" + self.term_link(indiv, "dfn") + ": " + \ self.format_definition( self.owl.get_definition(indiv)) + \ "</li>" self.text += "</ul>" self.text += """ </section>""" def close_sections(self): for x in range(0, self.section_open): self.text += "\t"*x+"</section>\n" # Write out specification def write_specification(self, spec_file=None, component=None, version=None): if component and version: spec_file = os.path.join(DOC_FOLDER, component+"_"+version+".html") spec_open = codecs.open(spec_file, 'w', "utf-8") spec_open.write(self.text) spec_open.close() def _header_footer(self, prev_file=None, follow_file=None, component=None, version=None): release_notes = None if component: prev_file = os.path.join(INCLUDE_FOLDER, component+"_head.html") follow_file = os.path.join(INCLUDE_FOLDER, component+"_foot.html") if version: release_notes = os.path.join( os.path.dirname(self.owl.file), component+"_"+version+"_notes.html") if not os.path.isfile(release_notes): release_notes = None if prev_file is not None: prev_file_open = open(prev_file, 'r') self.text = prev_file_open.read().decode('utf-8')+self.text prev_file_open.close() if release_notes is not None: release_note_open = open(release_notes, 'r') self.text = self.text+release_note_open.read() release_note_open.close() if follow_file is not None: follow_file_open = open(follow_file, 'r') self.text = self.text+follow_file_open.read() follow_file_open.close()
class UpdateTermReadme(): def __init__(self, owl_file): self.owl = OwlReader(owl_file) # Write out Readme def write_readme(self, readme_file, readme_txt): readme_file_open = open(readme_file, 'w') readme_file_open.write(readme_txt) readme_file_open.close() def create_term_row(self, term_name, definition, same_as, editor, note, color, range_value=None, domain=None, indiv_type=None): img_color = "" if color: img_color = '<img src="../../../doc/content/specs/img/' + color + '.png?raw=true"/> ' if same_as: same_as = "(same as: <a href=" + same_as + ">" + same_as + "</a>)" range_domain_type = "" if range_value is not None: range_domain_type = """ <td>""" + domain + """</td> <td>""" + range_value + """</td>""" if indiv_type is not None: range_domain_type += """ <td>""" + indiv_type + """</td>""" # Github mardow-like links nidm_repo = "https://github.com/incf-nidash/nidm/" stato_repo = "https://github.com/ISA-tools/stato/" nidm_pr_issue = re.compile(nidm_repo + r'[a-zA-Z]*/(\d+)') note = nidm_pr_issue.sub( r'<a href="' + nidm_repo + r'pull/\1">' + r'#\1</a>', note) stato_pr_issue = re.compile(stato_repo + r'[a-zA-Z]*/(\d+)') note = stato_pr_issue.sub( r'<a href="' + stato_repo + r'pull/\1">' + r'ISA-tools/stato#\1</a>', note) if note: note = note + "<br/>" # Add a search link (to check current state of the repo) if "Under discussion" in note: search_text = "more" else: search_text = "find issues/PR" note = note + "<a href=\"" + nidm_repo + "/issues?&q=" + term_name.split( ":")[1] + "\"> [" + search_text + "] </a>" term_row = """ <tr> <td>""" + img_color + """</td> <td>""" + note + """</td> <td><b>""" + term_name + """: </b>""" + definition + same_as + editor + """</td>""" + range_domain_type + """ </tr>""" return term_row def create_curation_legend(self, order): curation_legend = "<b>Curation status</b>: \n" curation_colors_sorted = [(key, CURATION_COLORS.get(key)) for key in order] covered_colors = list() for curation_color in curation_colors_sorted: # curation_status = str(self.owl.qname(curation_color[0])) # curation_status_labels = self.owl.objects(curation_color[0], RDFS['label']) # curation_status = ", ".join(list(curation_status_labels)) color = curation_color[1] if not color in covered_colors: curation_legend = curation_legend+'<img src="../../../doc/content/specs/img/'+color+'.png?raw=true"/> '+\ CURATION_LEGEND[color]+";\n" covered_colors.append(color) return curation_legend # Get README text according to owl file information def update_readme(self, readme_file): class_terms = dict() prpty_terms = dict() indiv_terms = dict() definitions = dict() editors = dict() notes = dict() ranges = dict() domains = dict() sameas = dict() types = dict() for owl_term in self.owl.classes.union(self.owl.properties).union( self.owl.individuals): curation_status = self.owl.get_curation_status(owl_term) definition = self.owl.get_definition(owl_term) if definition == "": definition = "<undefined>" editor = self.owl.get_editor(owl_term) note = self.owl.get_editor_note(owl_term) range_value = self.owl.get_range(owl_term) domain = self.owl.get_domain(owl_term) same = self.owl.get_same_as(owl_term) indiv_type = self.owl.get_individual_type(owl_term) if curation_status: curation_key = curation_status term_key = self.owl.get_label(owl_term) if term_key.startswith("nidm") or term_key.startswith("spm") or\ term_key.startswith("fsl") or term_key.startswith("afni"): if owl_term in self.owl.classes: class_terms.setdefault(curation_key, list()).append(term_key) else: if owl_term in self.owl.properties: prpty_terms.setdefault(curation_key, list()).append(term_key) else: if owl_term in self.owl.individuals: indiv_terms.setdefault(curation_key, list()).append(term_key) definitions[term_key] = definition editors[term_key] = editor notes[term_key] = note ranges[term_key] = range_value domains[term_key] = domain sameas[term_key] = same types[term_key] = indiv_type # Include missing keys and do not display ready for release terms order = CURATION_ORDER + (list( set(class_terms.keys()).union(set(prpty_terms.keys())) - set(CURATION_ORDER + list([OBO_READY])))) class_terms_sorted = [(key, class_terms.get(key)) for key in order] prpty_terms_sorted = [(key, prpty_terms.get(key)) for key in order] indiv_terms_sorted = [(key, indiv_terms.get(key)) for key in order] class_table_txt = "<h2>Classes</h2>\n<table>\n<tr><th>Curation Status</th><th>Issue/PR</th><th>Term</th></tr>" for tuple_status_term in class_terms_sorted: curation_status = tuple_status_term[0] class_names = tuple_status_term[1] if class_names: for class_name in sorted(class_names): class_table_txt += self.create_term_row(class_name, \ definitions[class_name], \ sameas[class_name], \ editors[class_name], \ notes[class_name], \ CURATION_COLORS.setdefault(curation_status, "")) class_table_txt = class_table_txt + "\n</table>" prpty_table_txt = "<h2>Properties</h2>\n<table>\n<tr><th>Curation Status</th><th>Issue/PR</th><th>Term</th><th>Domain</th><th>Range</th></tr>" for tuple_status_term in prpty_terms_sorted: curation_status = tuple_status_term[0] term_names = tuple_status_term[1] if term_names: for term_name in sorted(term_names): prpty_table_txt += self.create_term_row(term_name, \ definitions[term_name], \ sameas[term_name], \ editors[term_name], \ notes[term_name], \ CURATION_COLORS.setdefault(curation_status, ""), \ ranges[term_name], \ domains[term_name]) prpty_table_txt = prpty_table_txt + "\n</table>" indiv_table_txt = "<h2>Individuals</h2>\n<table>\n<tr><th>Curation Status</th><th>Issue/PR</th><th>Term</th><th>Type</th></tr>" for tuple_status_term in indiv_terms_sorted: curation_status = tuple_status_term[0] term_names = tuple_status_term[1] if term_names: for term_name in sorted(term_names): indiv_table_txt += self.create_term_row(term_name, \ definitions[term_name], \ sameas[term_name], \ editors[term_name], \ notes[term_name], \ CURATION_COLORS.setdefault(curation_status, ""), \ None, None, types[term_name]) indiv_table_txt = indiv_table_txt + "\n</table>" curation_legend = self.create_curation_legend(order) title = "<h1>NIDM-Results Terms curation status</h1>" intro = """You will find below a listing of the NIDM-Results terms that \ need to be curated. If you would like **to help with the curation of a term, \ please follow those steps**: 1. Check if the terms is already under discussion in an issue. 2. If not, create a new issue including the current definition (available in\ the table below) and your proposed update. If possible, priority should be given to uncurated terms (in red). Thank you in advance for taking part in NIDM-Results term curation!\n\n""" self.write_readme(readme_file, title+intro+\ curation_legend+class_table_txt+prpty_table_txt+indiv_table_txt)