code: def structure_from_ncdata(ncdata, site_properties=None, cls=Structure):
      
      ncdata, closeit = as_ncreader(ncdata)
  
      # TODO check whether atomic units are used
      lattice = ArrayWithUnit(ncdata.read_value("primitive_vectors"), "bohr").to("ang")
  
      red_coords = ncdata.read_value("reduced_atom_positions")
      natom = len(red_coords)
  
      znucl_type = ncdata.read_value("atomic_numbers")
  
      # type_atom[0:natom] --> index Between 1 and number of atom species
      type_atom = ncdata.read_value("atom_species")
  
      # Fortran to C index and float --> int conversion.
      species = natom * [None]
      for atom in range(natom):
          type_idx = type_atom[atom] - 1
          species[atom] = int(znucl_type[type_idx])
  
      d = {}
      if site_properties is not None:
          for prop in site_properties:
              d[property] = ncdata.read_value(prop)
  
      structure = cls(lattice, species, red_coords, site_properties=d)
  
      # Quick and dirty hack.
      # I need an abipy structure since I need to_abivars and other methods.
      try:
          from abipy.core.structure import Structure as AbipyStructure
          structure.__class__ = AbipyStructure
      except ImportError:
          pass
  
      if closeit:
          ncdata.close()
  
      return structure
docs: Reads and returns a pymatgen structure from a NetCDF file
      containing crystallographic data in the ETSF-IO format.
  
      Args:
          ncdata: filename or NetcdfReader instance.
          site_properties: Dictionary with site properties.
          cls: The Structure class to instanciate.