docs: def nearest_pipe(Do=None, Di=None, NPS=None, schedule='40'):
      r'''Searches for and finds the nearest standard pipe size to a given
      specification. Acceptable inputs are:
  
      - Nominal pipe size
      - Nominal pipe size and schedule
      - Outer diameter `Do`
      - Outer diameter `Do` and schedule
      - Inner diameter `Di`
      - Inner diameter `Di` and schedule
  
      Acceptable schedules are: '5', '10', '20', '30', '40', '60', '80', '100',
      '120', '140', '160', 'STD', 'XS', 'XXS', '5S', '10S', '40S', '80S'.
  
      Parameters
      ----------
      Do : float
          Pipe outer diameter, [m]
      Di : float
          Pipe inner diameter, [m]
      NPS : float
          Nominal pipe size, [-]
      schedule : str
          String representing schedule size
  
      Returns
      -------
      NPS : float
          Nominal pipe size, [-]
      Di : float
          Pipe inner diameter, [m]
      Do : float
          Pipe outer diameter, [m]
      t : float
          Pipe wall thickness, [m]
  
      Notes
      -----
      Internal units within this function are mm.
      The imperial schedules are not quite identical to these value, but
      all rounding differences happen in the sub-0.1 mm level.
  
      Examples
      --------
      >>> nearest_pipe(Di=0.021)
      (1, 0.02664, 0.0334, 0.0033799999999999998)
      >>> nearest_pipe(Do=.273, schedule='5S')
      (10, 0.26630000000000004, 0.2731, 0.0034)
  
      References
      ----------
      .. [1] American National Standards Institute, and American Society of
         Mechanical Engineers. B36.10M-2004: Welded and Seamless Wrought Steel
         Pipe. New York: American Society of Mechanical Engineers, 2004.
      .. [2] American National Standards Institute, and American Society of
         Mechanical Engineers. B36-19M-2004: Stainless Steel Pipe.
         New York, N.Y.: American Society of Mechanical Engineers, 2004.
      '''
      if Di: 
          Di *= 1E3
      if Do: 
          Do *= 1E3
      if NPS: 
          NPS = float(NPS)
  
      def Di_lookup(Di, NPSes, Dis, Dos, ts):
          for i in range(len(Dis)): # Go up ascending list; once larger than specified, return
              if Dis[-1] < Di:
                  return None
              if Dis[i] >= Di:
                  _nps, _di, _do, _t = NPSes[i], Dis[i], Dos[i], ts[i]
                  return (_nps, _di, _do, _t)
          raise Exception('Di lookup failed')
  
      def Do_lookup(Do, NPSes, Dis, Dos, ts):
          for i in range(len(Dos)): # Go up ascending list; once larger than specified, return
              if Dos[-1] < Do:
                  return None
              if Dos[i] >= Do:
                  _nps, _di, _do, _t = NPSes[i], Dis[i], Dos[i], ts[i]
                  return (_nps, _di, _do, _t)
          raise Exception('Do lookup failed')
  
      def NPS_lookup(NPS, NPSes, Dis, Dos, ts):
          for i in range(len(NPSes)): # Go up ascending list; once larger than specified, return
              if NPSes[i] == NPS:
                  _nps, _di, _do, _t = NPSes[i], Dis[i], Dos[i], ts[i]
                  return (_nps, _di, _do, _t)
          raise Exception('NPS not in list')
  
  
      # If accidentally given an numerical schedule, convert it to a string
      schedule_type = type(schedule)
      if schedule_type in (int, float):
          schedule = str(int(schedule))
      
      if schedule not in schedule_lookup:
          raise ValueError('Schedule not recognized')
      else:
          NPSes, Dis, Dos, ts = schedule_lookup[schedule]
      
      # Handle the three cases of different inputs
      if Di:
          nums = Di_lookup(Di, NPSes, Dis, Dos, ts)
      elif Do:
          nums = Do_lookup(Do, NPSes, Dis, Dos, ts)
      elif NPS:
          nums = NPS_lookup(NPS, NPSes, Dis, Dos, ts)
  
      if nums is None:
          raise ValueError('Pipe input is larger than max of selected schedule')
      _nps, _di, _do, _t = nums
      return _nps, _di/1E3, _do/1E3, _t/1E3