docs: def get(self, cycle_list, dataitem=None, isotope=None, sparse=1):
          '''
          Get Data from HDF5 files.
  
          There are three ways to call this function
  
          1. get(dataitem)
  
              Fetches the datatiem for all cycles. If dataitem is a header
              attribute or list of attributes then the data is retured.
              If detaitem an individulal or list of column attributes,
              data columns or isotopes/elements the data is returned for
              all cycles.
  
          2. get(cycle_list, dataitem)
  
              Fetches the dataitem or list of dataitems for the cycle
              or list of cycles. The variable dataitems can contain column
              attributes, data columns, and isotopes/elemnts.
  
          3. get(cycle_list, dataitem, isotope)
  
              Fetches the dataitems like the seccond method except that
              one of the dataitems must be either "iso_massf" or "yps",
              and in the data returned "iso_massf" and "yps" are replaced
              with the data from the isotopes.  The isotopes must be in
              the form given by se.isotopes or se.elements.
  
          Parameters
          ----------
          cycle_list : list, integer or string
              If cycle_list is a list or string and all of the entries
              are header attributes then the attributes are returned.
  
              If cycle_list is a list or string of dataitems then the
              dataitems are fetched for all cycles.
  
              If cycle_list is a list, integer or string of cycle numbers
              then data is returned for those cycles.
          dataitem: list or string, optional
              If dataitem is not None then the data for each item is
              returned for the cycle or list of cycles. dataitem may be an
              individual or a mixed list of column attributes, column
              data or isotopes/elements. If dataitem is None then
              cycle_list must be a string.  The default is None.
          isotope: list or string, optional
              If one of the dataitems is "iso_massf" or "yps" then it is
              replaced with the data from the individual isotopes/elements
              listed in isotope.  The default is None.
          sparse : int
              Implements a sparsity factor on the fetched data i.e. only
              the i th cycle in cycle_list data is returned,
              where i = sparse.
  
          '''
  
  #    Check out the inputs
          t1=time.time()
          isotopes_of_interest = []
  
          nested_list = False
          # if one of cycle_list, dataitem or isotope is given as a string convert it to a list
          if isinstance(cycle_list, basestring):
              cycle_list = [cycle_list]
          else:
              try:
                  if len(cycle_list) == 1:
                      nested_list = True
              except TypeError:
                  pass #leave nested_list as false
          if isinstance(dataitem, basestring):
              dataitem = [dataitem]
          if isinstance(isotope, basestring):
              isotope = [isotope]
  
  
  
          if dataitem==None and isotope==None:
              option_ind = 1
              dataitem = cycle_list
  
              if not any([item in self.hattrs for item in dataitem]):
                  cycle_list = self.cycles
              else:
                  first_file = mrT.File(self.h5s[0].filename,'r')
                  dat = []
                  # get all dataitems from header attributes
                  for item in dataitem:
                      tmp = first_file.attrs.get(item, None)
                      try:
                          if len(tmp) == 1:
                              tmp = tmp[0]
                      except TypeError: #if a scaler is returned do nothing
                          pass
                      dat.append(tmp)
                  # if only one header attribute is required dont return as a list
                  if (len(dat) == 1) and (not nested_list):
                      dat = dat[0]
                  first_file.close()
                  return dat
              if any([item.split('-')[0] in self.isos for item in dataitem]):
                  return self.get(cycle_list,dataitem,sparse=sparse)
          elif isotope==None:
              option_ind = 2
              cycle_list = cycle_list
              dataitem = dataitem
              # if one dataitem is given as a string convert it to a list
              if isinstance(dataitem, basestring):
                  dataitem = [dataitem]
              new_dataitem = []
              new_isotopes = []
              for item in dataitem:
                  if item.split('-')[0] in self.isos:
                      new_isotopes.append(item)
                  else:
                      new_dataitem.append(item)
              if len(new_isotopes) != 0:
                  tmp = []
                  try:
                      tmp = self.get(cycle_list,new_dataitem + ['iso_massf'],new_isotopes,sparse=sparse)
                  except: # in some old se files there maybe still yps as the name for the abundance arrays
                      tmp =  self.get(cycle_list,new_dataitem + ['yps'],new_isotopes,sparse=sparse)
                  # modify the dat list so dat is structured like dataitems
                  dat = []
                  #make sure tmp containes the data as a list of cycles
                  if isinstance(cycle_list, basestring):
                      tmp = [tmp]
                  else:
                      try:
                          if len(cycle_list) == 1:
                              tmp = [tmp]
                      except TypeError:
                          tmp = [tmp]
                  for cyc in tmp:
                      temp_dataitem = []
                      for item in dataitem:
                          if item in new_dataitem:
                              temp_dataitem.append(cyc[new_dataitem.index(item)])
                          else:
                              if len(new_dataitem) == 0:
                                  temp_dataitem = cyc
                              else:
                                  if len(new_isotopes) == 1:
                                      temp_dataitem.append(cyc[-1])
                                  else:
                                      temp_dataitem.append(cyc[-1][new_isotopes.index(item)])
                      dat.append(temp_dataitem)
                  if (len(dat) == 1) and (not nested_list):
                      dat = dat[0]
                  return dat
          else:
  # there is an implicite rule here that if you want 2D arrays you have
  # to give 3 args, or, in other words you have to give a cycle or cycle
  # array; there is no good reason for that, except the programmers
  # laziness
              option_ind = 3
              cycle_list = cycle_list
              dataitem = dataitem
              isotopes_of_interest = isotope
  # we need to find out the shellnb to know if any yps array may just be
  # a one row array, as - for example- in the surf.h5 files
              # SJONES: I think here we only need to look at the first shellnb(!)
              #shellnb=self.get(cycle_list,'shellnb')
              try: #check if cycle_list is not a list
                  cycle_list[0]
              except (TypeError,IndexError):
                  cycle_list = [cycle_list]
              shellnb=self.get(cycle_list[0],'shellnb')
  
          if sparse <1:
              sparse=1
  
          #    Just in case the user inputs integers
          try:
              for x in range(len(cycle_list)):
                  cycle_list[x] = str(cycle_list[x])
          except TypeError:
              cycle_list = [str(cycle_list)]
  
          if option_ind != 1:
  
              try: #if it is a single cycle make sure its formatted correctly
                  if cycle_list.isdigit():
                      cycle_list = [cycle_list]
                      for cycle in cycle_list:
                          if len(cycle) != len(self.cycles[0]):
                                  #print "a"
                              diff = len(self.cycles[0])-len(cycle)
                              OO = ''
                              while diff >=1:
                                  OO+='0'
  
                              cycle = OO+cycle
  
              except AttributeError: ##if it is a list of cycles make sure its formatted correctly
                  if cycle_list[0].isdigit():
  
                      for x in range(len(cycle_list)):
                          if len(str(cycle_list[x])) != len(str(self.cycles[0])):
                              #print "b"
                              diff = len(str(self.cycles[0]))-len(str(cycle_list[x]))
  
                              OO = ''
                              while diff >=1:
                                  OO+='0'
                                  diff-=1
  
                              try:
                                  cycle_list[x] = OO+cycle_list[x]
                              except TypeError:
                                  cycle_list[0] = OO+cycle_list[0]
  
          dat = []
          cycle_list.sort()
  
          cyclelist=np.array(list(map(int, cycle_list)))
  
          # cycles_requested is a list of indices from cyclelist
          # The index of the larges and smallest indices should be stored
          # in sorted order. As new requests are made if the requests
          # border or over lap then only keep the index of the larges and
          # smallest indices.
          cycles_requested = []
  
          # Sometimes bad data or last restart.h5 files contain no cycles,
          # causing the code to crash. Do a simple try/except here:
          file_min=[]
          file_max=[]
          try:
              for h5 in self.h5s:
                  file_min.append(int(h5.cycle[0]))
                  file_max.append(int(h5.cycle[-1]))
          except IndexError:
              print('File '+h5.filename+' contains no data, please remove or rename it')
              print('Once the file has been removed or renamed, the preprocessor file must be re-written. Do this by either removing the file h5Preproc.txt from the data directory or by invoking the se instance with rewrite=True')
              print('At present, h5T cannot check for empty files since the overhead using the mounted VOSpace would be too great.')
              raise IOError('Cycle-less file encountered')
          file_min.sort()
          file_max.sort()
  
          for h5 in self.h5s:
              #initalize file metadata
              min_file = int(h5.cycle[0])
              max_file = int(h5.cycle[-1])
              min_list = int(cyclelist[0])
              max_list = int(cyclelist[-1])
              index_min = None #if None start at begining
              index_max = None #if None finish at end
  
              # SJONES Now we need to add the case that the set only contains one file:
              if len(file_min) == 1:
                  min_file = min_list - 1
                  max_file = max_list + 1
              else:
                  file_index = file_min.index(min_file)
                  if file_index == 0:
                      if min_list - 1 < min_file:
                          min_file = min_list - 1
                      max_file = (file_min[file_index + 1] + max_file)//2
                  elif file_index == len(file_min) - 1:
                      min_file = (file_max[file_index - 1] + min_file)//2 + 1
                      if max_list + 1 > max_file:
                          max_file = max_list + 1
                  else:
                      min_file = (file_max[file_index - 1] + min_file)//2 + 1
                      max_file = (file_min[file_index + 1] + max_file)//2
  
              # calculate the left and right limits of the intersection
              # of the lists h5.cycle and cyclelist
              if (max_list < min_file) or (max_file < min_list):
              # the lists do not intersect
                  continue
              elif (min_list <= min_file) and (max_file <= max_list):
                  # all of h5.cycle is within cyclelist
                  index_min = bisect.bisect_left(cyclelist, min_file)
                  index_max = bisect.bisect_right(cyclelist, max_file)
              elif (min_file <= min_list) and (max_list <= max_file):
                  # all of cyclelist is within h5.cycle
                  index_min = None
                  index_max = None
              else:
                  if min_list > min_file:
                  # cyclelist overlaps the right edge of h5.cycle
                      index_min = None
                      index_max = bisect.bisect_right(cyclelist, max_file)
                  else:
                      # cyclelist overlaps the left edge of h5.cylce
                      index_min = bisect.bisect_left(cyclelist, min_file)
                      index_max = None
  
              # maintin list of all requested cycles by keeping trak of
              # the maximum and minimum indices
              imin = index_min
              if index_min == None:
                  imin = 0
  
              imax = index_max
              if index_max == None:
                  imax = len(cyclelist)
  
              request_min = bisect.bisect_left(cycles_requested, imin)
              request_max = bisect.bisect_right(cycles_requested, imax)
  
              # if the new request overlabs older request remove them
              del cycles_requested[request_min:request_max]
              if ((request_max-request_min) % 2) ==1:
                  # new and old request overlaped on one edge only
                  if request_min % 2 == 0:
                      # add new starting index
                      cycles_requested.insert(request_min, imin)
                  else:
                      # add new ending index
                      cycles_requested.insert(request_min, imax)
              else:
                  # new and old requests overlaped on two edges
                  if request_min % 2 == 0:
                      # old request was contained with in new request
                      cycles_requested.insert(request_min, imin)
                      cycles_requested.insert(request_min + 1, imax)
                  else:
                      # new request wat contained within old request
                      pass
  
              if not self.h5sStarted[self.h5s.index(h5)]:
                  h5.start()
                  h5.join()
                  temp = h5.fetch_data_sam(dataitem,cycle_list[index_min:index_max],len(cycle_list),len(dat))
                  self.h5sStarted[self.h5s.index(h5)]=True
              else:
                  temp = h5.fetch_data_sam(dataitem,cycle_list[index_min:index_max],len(cycle_list),len(dat))
  
              temp_dat = []
              for temp_num, temp_cycle in enumerate(temp):
                  temp_dataforcycle = []
                  for dataitem_num, temp_dataitem in enumerate(temp_cycle):
                      # identify what cycle the temp data was collected from
                      temp_dataitem=self.red_dim(temp_dataitem)
  #                    if option_ind == 3 and isotopes_of_interest != []:
                      if (dataitem[dataitem_num] == 'iso_massf' or dataitem[dataitem_num] == 'yps') and isotopes_of_interest != []:
                      #    Figure out the index
                          index = []
                          iso_tmp = []
  
                          if 'iso' in dataitem[dataitem_num]: #if we are looking at an isotope
                              iso_tmp = self.isotopes
                          else:
                              iso_tmp = self.elements
  
                          for iso in isotopes_of_interest: #finds the location of the isotope
                              x = iso_tmp.index(iso)
                              index.append(x)
  
                          if index == []:
                              # if none of the isotopes of interest are found
                              # then the index defaults to [0], so that the loop
                              # will still try to acess the data in t.
                              index = [0]
                          islist=True
  
                          if len(cycle_list)==1:
                              islist=False
  
  #                        shellnb_index = 0
  #                        if index_min == None:
  #                            shellnb_index = temp_num
  #                        else:
  #                            shellnb_index = index_min + temp_num
                          temp_multicyc = []
                          for i in index:
  #                            if islist:
  #                                if shellnb[shellnb_index] == 1:    # again take care of 1-row 2D arrays
                                  if shellnb == 1:    # again take care of 1-row 2D arrays
                                      temp_multicyc.append(temp_dataitem[i])
                                  else:
                                      temp_multicyc.append(temp_dataitem[:,i])
  #                            else:
  #                                if shellnb == 1:    # again take care of 1-row 2D arrays
  #                                    temp_multicyc.append(temp_dataitem[i])
  #                                else:
  #                                    temp_multicyc.append(temp_dataitem[:,i])
                          if len(temp_multicyc) == 1: # agian take care of 1-row arrays
                              temp_multicyc = temp_multicyc[0]
                          temp_dataitem = temp_multicyc
                      temp_dataforcycle.append(temp_dataitem)
                  if len(temp_dataforcycle) == 1: # agian take care of 1-row arrays
                      temp_dataforcycle = temp_dataforcycle[0]
                  # Now add the information to the list we pass back
                  temp_dat.append(temp_dataforcycle)
              # calculate the proper insertion point for the data colected from
              # the file h5 in self.h5s
              insert_pnt = 0
              if index_min is not None: #alex: in py2: x < None == False
                  for i in range(len(cycles_requested)):
                      if i % 2 == 1:
                          if cycles_requested[i] < index_min:
                              insert_pnt += cycles_requested[i] - cycles_requested[i-1]
                          elif cycles_requested[i - 1] < index_min:
                              insert_pnt += index_min - cycles_requested[i - 1]
              # insert the cycle data from the current file into the apropiat place
              # in the output data.
              dat[insert_pnt:insert_pnt] = temp_dat
  
          #check if cycles were not requested from the file
  # SJONES comment
  #        missing_cycles = np.array([])
  #        if len(cycles_requested) != 2:
  #            if len(cycles_requested) == 0:
  #                missing_cycles = np.array([cycle_list])
  #            else:
  #                cycles_requested = [None] + cycles_requested + [None]
  #                for i in xrange(0, len(cycles_requested), 2):
  #                    min = cycles_requested[i]
  #                    max = cycles_requested[i + 1]
  #                    missing_cycles = np.append(missing_cycles, cycle_list[min:max])
  #            print "The requested cycles: " + str(missing_cycles) + " are not available in this data set"
  #        elif (cycles_requested[0] != 0) or (cycles_requested[1] != len(cyclelist)):
  #            min = cycles_requested[0]
  #            max = cycles_requested[1]
  #            missing_cycles = np.append(missing_cycles, cycle_list[0:min])
  #            missing_cycles = np.append(missing_cycles, cycle_list[max:])
  #            print "The requested cycles: " + str(missing_cycles) + " are not available in this data set"
  
          if len(dat) < 2 and option_ind != 3 and (not nested_list):
              try:
                  dat = dat[0]
              except IndexError:
                  None
              except TypeError:
                  None
          try:
              if len(dat) < 2 and isotopes_of_interest != []:
                  dat = dat[0]
          except TypeError:
              None
          except IndexError:
              None
          t2=time.time()
          return dat