docs: def _setup_gc2_framework(self):
          """
          This method establishes the GC2 framework for a multi-segment
          (and indeed multi-typology) case based on the description in
          Spudich & Chiou (2015) - see section on Generalized Coordinate
          System for Multiple Rupture Traces
          """
          # Generate cartesian edge set
          edge_sets = self._get_cartesian_edge_set()
          self.gc2_config = {}
          # Determine furthest two points apart
          endpoint_set = numpy.vstack([cep for cep in self.cartesian_endpoints])
          dmat = squareform(pdist(endpoint_set))
          irow, icol = numpy.unravel_index(numpy.argmax(dmat), dmat.shape)
          # Join further points to form a vector (a_hat in Spudich & Chiou)
          # According to Spudich & Chiou, a_vec should be eastward trending
          if endpoint_set[irow, 0] > endpoint_set[icol, 0]:
              # Row point is to the east of column point
              beginning = endpoint_set[icol, :2]
              ending = endpoint_set[irow, :2]
          else:
              # Column point is to the east of row point
              beginning = endpoint_set[irow, :2]
              ending = endpoint_set[icol, :2]
  
          # Convert to unit vector
          a_vec = ending - beginning
          self.gc2_config["a_hat"] = a_vec / numpy.linalg.norm(a_vec)
          # Get e_j set
          self.gc2_config["ejs"] = []
          for c_edges in self.cartesian_edges:
              self.gc2_config["ejs"].append(
                  numpy.dot(c_edges[-1, :2] - c_edges[0, :2],
                            self.gc2_config["a_hat"]))
          # A "total E" is defined as the sum of the e_j values
          self.gc2_config["e_tot"] = sum(self.gc2_config["ejs"])
          sign_etot = numpy.sign(self.gc2_config["e_tot"])
          b_vec = numpy.zeros(2)
          self.gc2_config["sign"] = []
          for i, c_edges in enumerate(self.cartesian_edges):
              segment_sign = numpy.sign(self.gc2_config["ejs"][i]) * sign_etot
              self.gc2_config["sign"].append(segment_sign)
              if segment_sign < 0:
                  # Segment is discordant - reverse the points
                  c_edges = numpy.flipud(c_edges)
                  self.cartesian_edges[i] = c_edges
                  self.cartesian_endpoints[i] = numpy.flipud(
                      self.cartesian_endpoints[i])
              b_vec += (c_edges[-1, :2] - c_edges[0, :2])
  
          # Get unit vector
          self.gc2_config["b_hat"] = b_vec / numpy.linalg.norm(b_vec)
          if numpy.dot(a_vec, self.gc2_config["b_hat"]) >= 0.0:
              self.p0 = beginning
          else:
              self.p0 = ending
          # To later calculate Ry0 it is necessary to determine the maximum
          # GC2-U coordinate for the fault
          self._get_gc2_coordinates_for_rupture(edge_sets)