docs: def _rank_classifications(
              self,
              crossmatchArray,
              colMaps):
          """*rank the classifications returned from the catalogue crossmatcher, annotate the results with a classification rank-number (most likely = 1) and a rank-score (weight of classification)*
  
          **Key Arguments:**
              - ``crossmatchArrayIndex`` -- the index of list of unranked crossmatch classifications
              - ``colMaps`` -- dictionary of dictionaries with the name of the database-view (e.g. `tcs_view_agn_milliquas_v4_5`) as the key and the column-name dictary map as value (`{view_name: {columnMap}}`).
  
          **Return:**
              - ``classifications`` -- the classifications assigned to the transients post-crossmatches
              - ``crossmatches`` -- the crossmatches annotated with rankings and rank-scores
  
          .. todo ::
  
              - update key arguments values and definitions with defaults
              - update return values and definitions
              - update usage examples and text
              - update docstring text
              - check sublime snippet exists
              - clip any useful text to docs mindmap
              - regenerate the docs and check redendering of this docstring
          """
          self.log.debug('starting the ``_rank_classifications`` method')
  
          crossmatches = crossmatchArray
  
          # GROUP CROSSMATCHES INTO DISTINCT SOURCES (DUPLICATE ENTRIES OF THE
          # SAME ASTROPHYSICAL SOURCE ACROSS MULTIPLE CATALOGUES)
          ra, dec = zip(*[(r["raDeg"], r["decDeg"]) for r in crossmatches])
  
          from HMpTy.htm import sets
          xmatcher = sets(
              log=self.log,
              ra=ra,
              dec=dec,
              radius=3 / (60. * 60.),  # in degrees
              sourceList=crossmatches
          )
          groupedMatches = xmatcher.match
  
          associatationTypeOrder = ["AGN", "CV", "NT", "SN", "VS", "BS"]
  
          # ADD DISTINCT-SOURCE KEY
          dupKey = 0
          distinctMatches = []
          for x in groupedMatches:
              dupKey += 1
              mergedMatch = copy.deepcopy(x[0])
              mergedMatch["merged_rank"] = int(dupKey)
  
              # ADD OTHER ESSENTIAL KEYS
              for e in ['z', 'photoZ', 'photoZErr']:
                  if e not in mergedMatch:
                      mergedMatch[e] = None
  
              bestDirectDistance = {
                  "direct_distance": mergedMatch["direct_distance"],
                  "direct_distance_modulus": mergedMatch["direct_distance_modulus"],
                  "direct_distance_scale": mergedMatch["direct_distance"],
                  "qual": colMaps[mergedMatch["catalogue_view_name"]]["object_type_accuracy"]
              }
              bestSpecz = {
                  "z": mergedMatch["z"],
                  "distance": mergedMatch["distance"],
                  "distance_modulus": mergedMatch["distance_modulus"],
                  "scale": mergedMatch["scale"],
                  "qual": colMaps[mergedMatch["catalogue_view_name"]]["object_type_accuracy"]
              }
              bestPhotoz = {
                  "photoZ": mergedMatch["photoZ"],
                  "photoZErr": mergedMatch["photoZErr"],
                  "distance": mergedMatch["distance"],
                  "distance_modulus": mergedMatch["distance_modulus"],
                  "scale": mergedMatch["scale"],
                  "qual": colMaps[mergedMatch["catalogue_view_name"]]["object_type_accuracy"]
              }
  
              for i, m in enumerate(x):
                  m["merged_rank"] = int(dupKey)
                  if i > 0:
                      # MERGE ALL BEST MAGNITUDE MEASUREMENTS
                      for f in self.filterPreference:
                          if f in m and m[f] and (f not in mergedMatch or (f + "Err" in mergedMatch and (f + "Err" not in m or (mergedMatch[f + "Err"] > m[f + "Err"])))):
                              mergedMatch[f] = m[f]
                              try:
                                  mergedMatch[f + "Err"] = m[f + "Err"]
                              except:
                                  pass
                      mergedMatch["original_search_radius_arcsec"] = "multiple"
                      mergedMatch["catalogue_object_subtype"] = "multiple"
                      mergedMatch["catalogue_view_name"] = "multiple"
  
                      # MERGE SEARCH NAMES
                      snippet = m["search_name"].split(" ")[0].upper()
  
                      if "/" not in mergedMatch["search_name"] and snippet not in mergedMatch["search_name"].upper():
                          mergedMatch["search_name"] = mergedMatch["search_name"].split(
                              " ")[0].upper() + "/" + m["search_name"].split(" ")[0].upper()
                      elif snippet not in mergedMatch["search_name"].upper():
                          mergedMatch[
                              "search_name"] += "/" + m["search_name"].split(" ")[0].upper()
                      elif "/" not in mergedMatch["search_name"]:
                          mergedMatch["search_name"] = mergedMatch["search_name"].split(
                              " ")[0].upper()
  
                      mergedMatch["catalogue_table_name"] = mergedMatch[
                          "search_name"]
  
                      # MERGE CATALOGUE SOURCE NAMES
                      mergedMatch["catalogue_object_id"] = str(
                          mergedMatch["catalogue_object_id"])
                      m["catalogue_object_id"] = str(m["catalogue_object_id"])
                      if m["catalogue_object_id"].replace(" ", "").lower() not in mergedMatch["catalogue_object_id"].replace(" ", "").lower():
                          mergedMatch["catalogue_object_id"] += "/" + \
                              m["catalogue_object_id"]
  
                      # DETERMINE BEST CLASSIFICATION
                      if mergedMatch["classificationReliability"] == 3 and m["classificationReliability"] < 3:
                          mergedMatch["association_type"] = m["association_type"]
                          mergedMatch["classificationReliability"] = m[
                              "classificationReliability"]
  
                      if m["classificationReliability"] != 3 and m["association_type"] in associatationTypeOrder and (mergedMatch["association_type"] not in associatationTypeOrder or associatationTypeOrder.index(m["association_type"]) < associatationTypeOrder.index(mergedMatch["association_type"])):
                          mergedMatch["association_type"] = m["association_type"]
                          mergedMatch["classificationReliability"] = m[
                              "classificationReliability"]
  
                      # FIND BEST DISTANCES
                      if "direct_distance" in m and m["direct_distance"] and colMaps[m["catalogue_view_name"]]["object_type_accuracy"] > bestDirectDistance["qual"]:
                          bestDirectDistance = {
                              "direct_distance": m["direct_distance"],
                              "direct_distance_modulus": m["direct_distance_modulus"],
                              "direct_distance_scale": m["direct_distance_scale"],
                              "catalogue_object_type": m["catalogue_object_type"],
                              "qual": colMaps[m["catalogue_view_name"]]["object_type_accuracy"]
                          }
                      # FIND BEST SPEC-Z
                      if "z" in m and m["z"] and colMaps[m["catalogue_view_name"]]["object_type_accuracy"] > bestSpecz["qual"]:
                          bestSpecz = {
                              "z": m["z"],
                              "distance": m["distance"],
                              "distance_modulus": m["distance_modulus"],
                              "scale": m["scale"],
                              "catalogue_object_type": m["catalogue_object_type"],
                              "qual": colMaps[m["catalogue_view_name"]]["object_type_accuracy"]
                          }
                      # FIND BEST PHOT-Z
                      if "photoZ" in m and m["photoZ"] and colMaps[m["catalogue_view_name"]]["object_type_accuracy"] > bestPhotoz["qual"]:
                          bestPhotoz = {
                              "photoZ": m["photoZ"],
                              "photoZErr": m["photoZErr"],
                              "distance": m["distance"],
                              "distance_modulus": m["distance_modulus"],
                              "scale": m["scale"],
                              "catalogue_object_type": m["catalogue_object_type"],
                              "qual": colMaps[m["catalogue_view_name"]]["object_type_accuracy"]
                          }
                      # CLOSEST ANGULAR SEP & COORDINATES
                      if m["separationArcsec"] < mergedMatch["separationArcsec"]:
                          mergedMatch["separationArcsec"] = m["separationArcsec"]
                          mergedMatch["raDeg"] = m["raDeg"]
                          mergedMatch["decDeg"] = m["decDeg"]
  
              # MERGE THE BEST RESULTS
              for l in [bestPhotoz, bestSpecz, bestDirectDistance]:
                  for k, v in l.iteritems():
                      if k != "qual":
                          mergedMatch[k] = v
  
              mergedMatch["catalogue_object_id"] = str(mergedMatch[
                  "catalogue_object_id"]).replace(" ", "")
  
              # RECALULATE PHYSICAL DISTANCE SEPARATION
              if mergedMatch["direct_distance_scale"]:
                  mergedMatch["physical_separation_kpc"] = mergedMatch[
                      "direct_distance_scale"] * mergedMatch["separationArcsec"]
              elif mergedMatch["scale"]:
                  mergedMatch["physical_separation_kpc"] = mergedMatch[
                      "scale"] * mergedMatch["separationArcsec"]
  
              if "/" in mergedMatch["search_name"]:
                  mergedMatch["search_name"] = "multiple"
  
              distinctMatches.append(mergedMatch)
  
          crossmatches = []
          for xm, gm in zip(distinctMatches, groupedMatches):
  
              # SPEC-Z GALAXIES
              if (xm["physical_separation_kpc"] is not None and xm["physical_separation_kpc"] != "null" and xm["physical_separation_kpc"] < 20. and xm["association_type"] == "SN" and (("z" in xm and xm["z"] is not None) or "photoZ" not in xm or xm["photoZ"] is None or xm["photoZ"] < 0.)):
                  rankScore = xm["classificationReliability"] * 1000 + 2. - \
                      xm["physical_separation_kpc"] / 10
              # PHOTO-Z GALAXIES
              elif (xm["physical_separation_kpc"] is not None and xm["physical_separation_kpc"] != "null" and xm["physical_separation_kpc"] < 20. and xm["association_type"] == "SN"):
                  rankScore = xm["classificationReliability"] * 1000 + 2.2 - \
                      xm["physical_separation_kpc"] / 10
              # NOT SPEC-Z, NON PHOTO-Z GALAXIES
              elif (xm["association_type"] == "SN"):
                  rankScore = xm["classificationReliability"] * 1000 + 5.
              # VS
              elif (xm["association_type"] == "VS"):
                  rankScore = xm["classificationReliability"] * \
                      1000 + xm["separationArcsec"] + 2.
              # BS
              elif (xm["association_type"] == "BS"):
                  rankScore = xm["classificationReliability"] * \
                      1000 + xm["separationArcsec"]
              else:
                  rankScore = xm["classificationReliability"] * \
                      1000 + xm["separationArcsec"] + 10.
              xm["rankScore"] = rankScore
              crossmatches.append(xm)
              if len(gm) > 1:
                  for g in gm:
                      g["rankScore"] = rankScore
  
          crossmatches = sorted(
              crossmatches, key=itemgetter('rankScore'), reverse=False)
          crossmatches = sorted(
              crossmatches, key=itemgetter('transient_object_id'))
  
          transient_object_id = None
          uniqueIndexCheck = []
          classifications = {}
          crossmatchesKeep = []
          rank = 0
          transClass = []
          for xm in crossmatches:
              rank += 1
              if rank == 1:
                  transClass.append(xm["association_type"])
                  classifications[xm["transient_object_id"]] = transClass
              xm["rank"] = rank
              crossmatchesKeep.append(xm)
          crossmatches = crossmatchesKeep
  
          crossmatchesKeep = []
          for xm in crossmatches:
              group = groupedMatches[xm["merged_rank"] - 1]
              xm["merged_rank"] = None
              crossmatchesKeep.append(xm)
  
              if len(group) > 1:
                  groupKeep = []
                  uniqueIndexCheck = []
                  for g in group:
                      g["merged_rank"] = xm["rank"]
                      g["rankScore"] = xm["rankScore"]
                      index = "%(catalogue_table_name)s%(catalogue_object_id)s" % g
                      # IF WE HAVE HIT A NEW SOURCE
                      if index not in uniqueIndexCheck:
                          uniqueIndexCheck.append(index)
                          crossmatchesKeep.append(g)
  
          crossmatches = crossmatchesKeep
  
          self.log.debug('completed the ``_rank_classifications`` method')
  
          return classifications, crossmatches