docs: def _prepare_for_submission(self,tempfolder, inputdict):        
          """
          This is the routine to be called when you want to create
          the input files and related stuff with a plugin.
          
          :param tempfolder: a aiida.common.folders.Folder subclass where
                             the plugin should put all its files.
          :param inputdict: a dictionary with the input nodes, as they would
                  be returned by get_inputdata_dict (without the Code!)
          """
          try:
              code = inputdict.pop(self.get_linkname('code'))
          except KeyError:
              raise InputValidationError("No code specified for this "
                                         "calculation")
  
          try:
              parameters = inputdict.pop(self.get_linkname('parameters'))
          except KeyError:
              raise InputValidationError("No parameters specified for this "
                                         "calculation")
          if not isinstance(parameters, ParameterData):
              raise InputValidationError("parameters is not of type "
                                         "ParameterData")
          
          try:
              structure = inputdict.pop(self.get_linkname('structure'))
          except KeyError:
              raise InputValidationError("No structure specified for this "
                                         "calculation")
          if not isinstance(structure,StructureData):
              raise InputValidationError("structure node is not of type"
                                         "StructureData")
          
          try:
              settings = inputdict.pop(self.get_linkname('settings'),None)
          except KeyError:
              pass
          if settings is not None:
              if not isinstance(parameters, ParameterData):
                  raise InputValidationError("parameters is not of type "
                                             "ParameterData")
          
          try:
              kpoints = inputdict.pop(self.get_linkname('kpoints'),None)
          except KeyError:
              pass
          if kpoints is not None:
              if not isinstance(kpoints, KpointsData):
                  raise InputValidationError("kpoints is not of type KpointsData")
          
          ##############################
          # END OF INITIAL INPUT CHECK #
          ##############################
          
          # default atom getter: I will always retrieve the total energy at least
          default_atoms_getters = [ ["total_energy",""] ] 
          
          # ================================
          
          # save the structure in ase format
          atoms = structure.get_ase()
          atoms.write(tempfolder.get_abs_path(self._input_aseatoms))
          
          # ================== prepare the arguments of functions ================
          
          parameters_dict = parameters.get_dict()
          settings_dict = settings.get_dict() if settings is not None else {}
          
          # ==================== fix the args of the optimizer
          
          optimizer = parameters_dict.pop("optimizer",None)
          if optimizer is not None:
              # Validation
              if not isinstance(optimizer,dict):
                  raise InputValidationError("optimizer key must contain a dictionary")
              # get the name of the optimizer
              optimizer_name = optimizer.pop("name",None)
              if optimizer_name is None:
                  raise InputValidationError("Don't have access to the optimizer name")
              
              # prepare the arguments to be passed to the optimizer class
              optimizer_argsstr = "atoms, " + convert_the_args(optimizer.pop("args",[]))
              
              # prepare the arguments to be passed to optimizer.run()
              optimizer_runargsstr = convert_the_args(optimizer.pop("run_args",[]))
              
              # prepare the import string
              optimizer_import_string = get_optimizer_impstr(optimizer_name)
              
          # ================= determine the calculator name and its import ====
          
          calculator = parameters_dict.pop("calculator",{})
          calculator_import_string = get_calculator_impstr(calculator.pop("name",None))
          
          # =================== prepare the arguments for the calculator call
          
          read_calc_args = calculator.pop("args",[])
          #calc_args = calculator.pop("args",None)
          if read_calc_args is None:
              calc_argsstr = ""
          else:
              # transform a in "a" if a is a string (needed for formatting)
              calc_args = {}
              for k,v in read_calc_args.iteritems():
                  if isinstance(v, basestring):
                      the_v = '"{}"'.format(v)
                  else:
                      the_v = v
                  calc_args[k] = the_v
              
              def return_a_function(v):
                  try:
                      has_magic = "@function" in v.keys()
                  except AttributeError:
                      has_magic = False
                  
                  if has_magic:
                      
                      args_dict = {}
                      for k2,v2 in v['args'].iteritems():
                          if isinstance(v2,basestring):
                              the_v = '"{}"'.format(v2)
                          else:
                              the_v = v2
                          args_dict[k2] = the_v
                      
                      v2 = "{}({})".format(v['@function'],
                                           ", ".join(["{}={}".format(k_,v_) 
                                              for k_,v_ in args_dict.iteritems()]))
                      return v2
                  else:
                      return v
              
              tmp_list = [ "{}={}".format(k,return_a_function(v)) 
                           for k,v in calc_args.iteritems() ]
              
              calc_argsstr = ", ".join( tmp_list )
  
              # add kpoints if present
              if kpoints:
                  #TODO: here only the mesh is supported
                  # maybe kpoint lists are supported as well in ASE calculators
                  try:
                      mesh = kpoints.get_kpoints_mesh()[0]
                  except AttributeError:
                      raise InputValidationError("Coudn't find a mesh of kpoints"
                                                 " in the KpointsData")
                  calc_argsstr = ", ".join( [calc_argsstr] + ["kpts=({},{},{})".format( *mesh )] )
                          
          # =============== prepare the methods of atoms.get(), to save results
          
          atoms_getters = default_atoms_getters + convert_the_getters( parameters_dict.pop("atoms_getters",[]) )
          
          # =============== prepare the methods of calculator.get(), to save results
          
          calculator_getters = convert_the_getters( parameters_dict.pop("calculator_getters",[]) )
          
          # ===================== build the strings with the module imports
          
          all_imports = ["import ase", 'import ase.io', "import json",
                         "import numpy", calculator_import_string]
          
          if optimizer is not None:
              all_imports.append(optimizer_import_string)
  
          try:
              if "PW" in calc_args['mode'].values():
                  all_imports.append("from gpaw import PW")
          except KeyError:
              pass
          
          extra_imports = parameters_dict.pop("extra_imports",[])
          for i in extra_imports:
              if isinstance(i,basestring):
                  all_imports.append("import {}".format(i))
              elif isinstance(i,(list,tuple)):
                  if not all( [isinstance(j,basestring) for j in i] ):
                      raise ValueError("extra import must contain strings")
                  if len(i)==2:
                      all_imports.append("from {} import {}".format(*i))
                  elif len(i)==3:
                      all_imports.append("from {} import {} as {}".format(*i))
                  else:
                      raise ValueError("format for extra imports not recognized")
              else:
                  raise ValueError("format for extra imports not recognized")
          
          if self.get_withmpi():
              all_imports.append( "from ase.parallel import paropen" )
          
          all_imports_string = "\n".join(all_imports) + "\n"
          
          # =================== prepare the python script ========================
          
          input_txt = ""
          input_txt += get_file_header()
          input_txt += "# calculation pk: {}\n".format(self.pk)
          input_txt += "\n"
          input_txt += all_imports_string
          input_txt += "\n"
          
          pre_lines = parameters_dict.pop("pre_lines",None)
          if pre_lines is not None:
              if not isinstance(pre_lines,(list,tuple)):
                  raise ValueError("Prelines must be a list of strings")
              if not all( [isinstance(_,basestring) for _ in pre_lines] ):
                  raise ValueError("Prelines must be a list of strings")
              input_txt += "\n".join(pre_lines) + "\n\n"
          
          input_txt += "atoms = ase.io.read('{}')\n".format(self._input_aseatoms)
          input_txt += "\n"
          input_txt += "calculator = custom_calculator({})\n".format(calc_argsstr)
          input_txt += "atoms.set_calculator(calculator)\n"
          input_txt += "\n"
          
          if optimizer is not None:
              # here block the trajectory file name: trajectory = 'aiida.traj'
              input_txt += "optimizer = custom_optimizer({})\n".format(optimizer_argsstr)
              input_txt += "optimizer.run({})\n".format(optimizer_runargsstr)
              input_txt += "\n"
          
          # now dump / calculate the results
          input_txt += "results = {}\n"
          for getter,getter_args in atoms_getters:
              input_txt += "results['{}'] = atoms.get_{}({})\n".format(getter,
                                                                       getter,
                                                                       getter_args)
          input_txt += "\n"
          
          for getter,getter_args in calculator_getters:
              input_txt += "results['{}'] = calculator.get_{}({})\n".format(getter,
                                                                            getter,
                                                                            getter_args) 
          input_txt += "\n"
          
          # Convert to lists
          input_txt += "for k,v in results.iteritems():\n"
          input_txt += "    if isinstance(results[k],(numpy.matrix,numpy.ndarray)):\n"
          input_txt += "        results[k] = results[k].tolist()\n"
          
          input_txt += "\n"
          
          post_lines = parameters_dict.pop("post_lines",None)
          if post_lines is not None:
              if not isinstance(post_lines,(list,tuple)):
                  raise ValueError("Postlines must be a list of strings")
              if not all( [isinstance(_,basestring) for _ in post_lines] ):
                  raise ValueError("Postlines must be a list of strings")
              input_txt += "\n".join(post_lines) + "\n\n"
  
          # Dump results to file        
          right_open = "paropen" if self.get_withmpi() else "open"
          input_txt += "with {}('{}', 'w') as f:\n".format(right_open, self._OUTPUT_FILE_NAME)
          input_txt += "    json.dump(results,f)"
          input_txt += "\n"
          
          # Dump trajectory if present
          if optimizer is not None:
              input_txt += "atoms.write('{}')\n".format(self._output_aseatoms)
              input_txt += "\n"
          
          # write all the input script to a file
          input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)
          with open(input_filename,'w') as infile:
              infile.write(input_txt)
              
          # ============================ calcinfo ================================
          
          # TODO: look at the qmmm infoL: it might be necessary to put
          # some singlefiles in the directory.
          # right now it has to be taken care in the pre_lines
          
          local_copy_list = []
          remote_copy_list = [] 
          additional_retrieve_list = settings_dict.pop("ADDITIONAL_RETRIEVE_LIST",[])
          
          calcinfo = CalcInfo()
          
          calcinfo.uuid = self.uuid
          # Empty command line by default
          # calcinfo.cmdline_params = settings_dict.pop('CMDLINE', [])
          calcinfo.local_copy_list = local_copy_list
          calcinfo.remote_copy_list = remote_copy_list
          
          codeinfo = CodeInfo()
          codeinfo.cmdline_params = [self._INPUT_FILE_NAME]
          #calcinfo.stdin_name = self._INPUT_FILE_NAME
          codeinfo.stdout_name = self._TXT_OUTPUT_FILE_NAME
          codeinfo.code_uuid = code.uuid
          calcinfo.codes_info = [codeinfo]
          
          # Retrieve files
          calcinfo.retrieve_list = []
          calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)
          calcinfo.retrieve_list.append(self._output_aseatoms)
          calcinfo.retrieve_list += additional_retrieve_list
          
          # TODO: I should have two ways of running it: with gpaw-python in parallel
          # and executing python if in serial
          
          return calcinfo