code: def read_umls_concepts(
      meta_path: str,
      concept_details: Dict,
      source: Optional[str] = None,
      lang: str = "ENG",
      non_suppressed: bool = True,
  ):
      """
      Read the concepts file MRCONSO.RRF from a UMLS release and store it in
      concept_details dictionary. Each concept is represented with
      - concept_id
      - canonical_name
      - aliases
      - types
      - definition
      This function fills the first three. If a canonical name is not found, it is left empty.
  
      MRFILES.RRF file format: a pipe-separated values
      Useful columns: CUI, LAT, SUPPRESS, STR, ISPREF, TS, STT
  
      Args:
          meta_path: path to the META directory of an UMLS release
          concept_details: a dictionary to be filled with concept informations
          source: An optional source identifier, used as a filter to extract only a
                  specific source from UMLS.
          lang: An optional language identifier, used to filter terms by language
          non_suppressed: flag to indicate whether only non-suppressed concepts should be kept
      """
      concepts_filename = "MRCONSO.RRF"
      headers = read_umls_file_headers(meta_path, concepts_filename)
      with open(
          f"{meta_path}/{concepts_filename}", encoding="utf-8"
      ) as fin:
          for line in fin:
              splits = line.strip().split("|")
              assert len(headers) == len(splits), (headers, splits)
              concept = dict(zip(headers, splits))
              if (lang is not None and concept["LAT"] != lang) or (
                  non_suppressed and concept["SUPPRESS"] != "N"
              ):
                  continue  # Keep non-suppressed concepts in target language only
  
              if source is not None:
                  if concept["SAB"] != source:
                      continue
  
              concept_id = concept["CUI"]
              if concept_id not in concept_details:  # a new concept
                  # add it to the dictionary with an empty list of aliases and types
                  concept_details[concept_id] = {
                      "concept_id": concept_id,
                      "aliases": [],
                      "types": [],
                  }
  
              concept_name = concept["STR"]
              # this condition is copied from S2. It checks if the concept name is canonical or not
              is_canonical = (
                  concept["ISPREF"] == "Y"
                  and concept["TS"] == "P"
                  and concept["STT"] == "PF"
              )
  
              if (
                  not is_canonical
                  or "canonical_name" in concept_details[concept_id]
              ):
                  # not a canonical name or a canonical name already found
                  concept_details[concept_id]["aliases"].append(
                      concept_name
                  )  # add it as an alias
              else:
                  concept_details[concept_id][
                      "canonical_name"
                  ] = concept_name
  
imports: from typing import Optional, List, Dict
  from scispacy.linking_utils import Entity, UmlsKnowledgeBase
label_desc: Use image node_id 2 for calling a global function with example usage: read_umls_concepts(meta_path, concept_details, source, lang, non_suppressed) without return types