Exemple #1
0
 def _safe_run(cmd_arg_list,
               descr="External command",
               require_empty_stderr=False,
               require_zero_exit=True):
     process = Popen(cmd_arg_list, stdout=PIPE, stderr=PIPE)
     stdoutstr, stderrstr = process.communicate()
     return_code = process.returncode
     if (require_zero_exit
             and return_code != 0) or (require_empty_stderr
                                       and len(stderrstr) > 0):
         raise RuntimeError(
             "{} run failed.  Command was:\n{}\nstdout was:\n{}\nstderr was:\n{}\nexit code was: {}"
             .format(descr, indent(" ".join(cmd_arg_list)),
                     indent(stdoutstr), indent(stderrstr), return_code))
     return stdoutstr, stderrstr
 def run(self):
     while True:
         if Queue.verbose:
             #TODO write this kind of stuff to something from the python standard library `logging` module
             print("Thread {} awaiting task...".format(self))
         next_task = self.parent_fifo.get()
         if Queue.verbose:
             print("Thread {} recieved task {}".format(self, next_task))
         if next_task is TerminateTask:
             self.parent_fifo.task_done()
             break
         else:
             index, c, lock = next_task
             try:
                 already_run = c.already_run()
                 if not already_run and not Queue.quiet:
                     # TODO acquire global output lock? (and release after output).  Or use the `logging` module
                     print("Running computation #{}:\n{}".format(index + 1, indent(c.task_description())))
                 elif Queue.verbose and already_run:
                     print("Computation #{} already run in {}, not re-running".format(index + 1, c.directory))
                 c.run(lock=lock)
                 if not already_run and not Queue.quiet:
                     print("Computation #{} completed.".format(index + 1))
             except Exception, e:
                 # TODO figure out how to handle exceptions here
                 print(e)
             self.parent_fifo.task_done()
             if Queue.verbose:
                 print("Thread {} finished task {}".format(self, next_task))
Exemple #3
0
 def run(self):
     while True:
         if Queue.verbose:
             #TODO write this kind of stuff to something from the python standard library `logging` module
             print("Thread {} awaiting task...".format(self))
         next_task = self.parent_fifo.get()
         if Queue.verbose:
             print("Thread {} recieved task {}".format(self, next_task))
         if next_task is TerminateTask:
             self.parent_fifo.task_done()
             break
         else:
             index, c, lock = next_task
             try:
                 already_run = c.already_run()
                 if not already_run and not Queue.quiet:
                     # TODO acquire global output lock? (and release after output).  Or use the `logging` module
                     print("Running computation #{}:\n{}".format(
                         index + 1, indent(c.task_description())))
                 elif Queue.verbose and already_run:
                     print(
                         "Computation #{} already run in {}, not re-running"
                         .format(index + 1, c.directory))
                 c.run(lock=lock)
                 if not already_run and not Queue.quiet:
                     print("Computation #{} completed.".format(index + 1))
             except Exception, e:
                 # TODO figure out how to handle exceptions here
                 print(e)
             self.parent_fifo.task_done()
             if Queue.verbose:
                 print("Thread {} finished task {}".format(self, next_task))
Exemple #4
0
def parse_geometry_string(string, filetype=None):
    possible_parsers = []
    for parser in known_parsers:
        if filetype is None:
            if parser.string_is_filetype(string):
                possible_parsers.append(parser)
        else:
            if parser._matches_filetype_name(filetype):
                possible_parsers.append(parser)
    if len(possible_parsers) == 0:
        if filetype is None:
            raise ValueError("Can't automatically determine file type of file with data:\n{}".format(
                string
            ))
        else:
            raise ValueError("No known parsers for filetype '{}'".format(
                filetype
            ))
    elif len(possible_parsers) > 1:
        raise ValueError("File type is ambiguous.  File could be interpreted as:"
                         " include:\n{}\nfor file with data:\n{}".format(
            indent("\n".join(p.format_description for p in possible_parsers)), string
        ))
    else:
        return possible_parsers[0].parse_string(string)
Exemple #5
0
def parse_geometry_file(filename, filetype=None):
    # TODO check file extension
    possible_parsers = []
    for parser in known_parsers:
        if filetype is None:
            if parser.is_this_filetype(filename):
                possible_parsers.append(parser)
        else:
            if parser._matches_filetype_name(filetype):
                possible_parsers.append(parser)
    if len(possible_parsers) == 0:
        if filetype is None:
            raise ValueError("Can't automatically determine file type of file {}".format(
                filename
            ))
        else:
            raise ValueError("No known parsers for filetype '{}'".format(
                filetype
            ))
    elif len(possible_parsers) > 1:
        raise ValueError("File type of {} is ambiguous.  File could be interpreted as:"
                         " include:\n{}".format(
            filename,
            indent("\n".join(p.format_description for p in possible_parsers))
        ))
    else:
        return possible_parsers[0].parse_file(filename)
Exemple #6
0
 def _safe_run(cmd_arg_list, descr="External command",
         require_empty_stderr=False, require_zero_exit=True
 ):
     process = Popen(cmd_arg_list,
         stdout=PIPE,
         stderr=PIPE
     )
     stdoutstr, stderrstr = process.communicate()
     return_code = process.returncode
     if (require_zero_exit and return_code != 0) or (require_empty_stderr and len(stderrstr) > 0):
         raise RuntimeError("{} run failed.  Command was:\n{}\nstdout was:\n{}\nstderr was:\n{}\nexit code was: {}".format(
             descr,
             indent(" ".join(cmd_arg_list)),
             indent(stdoutstr),
             indent(stderrstr),
             return_code
         ))
     return stdoutstr, stderrstr
Exemple #7
0
 def __str__(self):
     ret_val = "CartesianRepresentation of molecule {}, in {}:\n".format(
         shortstr(self.molecule), self.units)
     for i, (x, y, z) in enumerate(grouper(3, self)):
         ret_val += indent(
             '{:>9} {:12.8f} {:12.8f} {:12.8f}\n'.format(
                 '[{}-{}]'.format(3 * i, 3 * i + 2), x.value, y.value,
                 z.value), 2)
     return ret_val
 def __str__(self):
     ret_val = "CartesianRepresentation of molecule {}, in {}:\n".format(shortstr(self.molecule), self.units)
     for i, (x, y, z) in enumerate(grouper(3, self)):
         ret_val += indent(
             "{:>9} {:12.8f} {:12.8f} {:12.8f}\n".format(
                 "[{}-{}]".format(3 * i, 3 * i + 2), x.value, y.value, z.value
             ),
             2,
         )
     return ret_val
 def __str__(self):
     namestrs = []
     valstrs = []
     it = np.nditer(self, flags=['multi_index'])
     for x in it:
         namestrs.append(", ".join(shortstr(self.representation[i]) for i in it.multi_index))
         valstrs.append("{: .8f}{}".format(float(x), (" " + str(self.units) if hasunits(self) else '')))
     width=max(len(s) for s in namestrs) + 4
     ret_val = self.__class__.__name__ + ":\n"
     for name, val in zip(namestrs, valstrs):
         ret_val += ("{:>"+str(width)+"}: {}\n").format(name, val)
     ret_val += "  for representation:\n{}".format(indent(str(self.representation)))
     return ret_val
Exemple #10
0
 def __str__(self):
     namestrs = []
     valstrs = []
     it = np.nditer(self, flags=['multi_index'])
     for x in it:
         namestrs.append(", ".join(
             shortstr(self.representation[i]) for i in it.multi_index))
         valstrs.append("{: .8f}{}".format(
             float(x), (" " + str(self.units) if hasunits(self) else '')))
     width = max(len(s) for s in namestrs) + 4
     ret_val = self.__class__.__name__ + ":\n"
     for name, val in zip(namestrs, valstrs):
         ret_val += ("{:>" + str(width) + "}: {}\n").format(name, val)
     ret_val += "  for representation:\n{}".format(
         indent(str(self.representation)))
     return ret_val
Exemple #11
0
 def write_3d_pdf(self,
                  filename,
                  verbose=False,
                  extra_latex_before="",
                  extra_latex_after="",
                  latex_file_handler=None,
                  toolbar=False,
                  quiet=False,
                  **kwargs):
     self._ensure_tmp_xyz()
     #----------------------------------------#
     if not _have_meshlab:
         raise RuntimeError(
             "You need to have meshlab.app installed (currently it must be installed in /Applications/ to work...) to do make 3D pdfs.  Get it from Sourceforge"
         )
     #----------------------------------------#
     new_kw = JmolRenderer.default_keywords.copy()
     # 3d keywords are higher priority
     new_kw.update(JmolRenderer.default_3d_keywords)
     # user preferences always have veto power
     new_kw.update(kwargs)
     extra_lines = self._get_kwarg_script_lines(**new_kw)
     #----------------------------------------#
     if verbose: print("Generating idtf file with Jmol...")
     jscript = """
         load "{molfile}"
         {extra_lines}
         write "{tempdir}/output.idtf"
     """.format(molfile=self._geom_path,
                tempdir=self.tempdir,
                extra_lines=extra_lines)
     self._run_jmol_script(jscript)
     idtf_path = path_join(self.tempdir, "output.idtf")
     if not exists(idtf_path):
         raise RuntimeError("Jmol command failed to produce "
                            "file '{}'.  Script was:\n{}".format(
                                idtf_path, indent(jscript)))
     #----------------------------------------#
     # now convert to u3d format
     # TODO make this portable
     if verbose: print("Converting idtf file to u3d file...")
     idtf_cmd = _idtf_to_u3d_template.format(
         input=path_join(self.tempdir, "output.idtf"),
         output=path_join(self.tempdir, "output.u3d"))
     JmolRenderer._safe_run(shlex.split(idtf_cmd),
                            descr="IDTF to u3d conversion")
     #shlex.os.system(idtf_cmd)
     #----------------------------------------#
     # Now embed in a latex document and run PDFLatex
     if verbose:
         print("Constructing latex document...".format(
             pdflatex_path, self.tempdir))
     with open(path_join(self.tempdir, "output.idtf.tex")) as f:
         jmol_latex_data = f.read()
     stuff3d = jmol_latex_data.split("toolbar=false,")[1].split(
         "inline=true,")[0].strip()
     if latex_file_handler is None:
         f = open(path_join(self.tempdir, "output.tex"), "w+")
         run_pdflatex = True
     else:
         f = latex_file_handler
         run_pdflatex = False
     if run_pdflatex:
         f.write(pdf_3d_header)
     pdf3d_section = pdf_3d_entry_template\
         .replace("@@@LABEL@@@", "molecule")\
         .replace("@@@3DSTUFF@@@", stuff3d)\
         .replace("@@@FNAME@@@", path_join(self.tempdir, "output.u3d"))
     if toolbar:
         pdf3d_section = pdf3d_section.replace("toolbar=false",
                                               "toolbar=true")
     f.write(extra_latex_before)
     f.write(pdf3d_section)
     f.write(extra_latex_after)
     if run_pdflatex:
         f.write(pdf_3d_footer)
     #- - - - - - - - - - - - - - - - - - - - #
     if run_pdflatex:
         if verbose:
             print("Running '{} {} output' in directory {}...".format(
                 pdflatex_path, " ".join(pdflatex_args), self.tempdir))
         pdflatex_cmd_list = [pdflatex_path] + pdflatex_args + ["output"]
         with working_directory(self.tempdir):
             # Run 3 times to get references right
             JmolRenderer._safe_run(pdflatex_cmd_list,
                                    "pdflatex",
                                    require_empty_stderr=True,
                                    require_zero_exit=False)
             if verbose: print("  ...run 1 complete")
             JmolRenderer._safe_run(pdflatex_cmd_list,
                                    "output",
                                    require_empty_stderr=True,
                                    require_zero_exit=False)
             if verbose: print("  ...run 2 complete")
             JmolRenderer._safe_run(pdflatex_cmd_list,
                                    "output",
                                    require_empty_stderr=True,
                                    require_zero_exit=False)
             if verbose: print("  ...run 3 complete")
         #----------------------------------------#
         # Finally, copy back the temporary output to the requested file path
         #   but only if we wrote the file
         move(path_join(self.tempdir, "output.pdf"), filename)
Exemple #12
0
 def write_3d_pdf(self, filename,
         verbose=False,
         extra_latex_before="",
         extra_latex_after="",
         latex_file_handler=None,
         toolbar=False,
         quiet=False,
         **kwargs
 ):
     self._ensure_tmp_xyz()
     #----------------------------------------#
     if not _have_meshlab:
         raise RuntimeError("You need to have meshlab.app installed (currently it must be installed in /Applications/ to work...) to do make 3D pdfs.  Get it from Sourceforge")
     #----------------------------------------#
     new_kw = JmolRenderer.default_keywords.copy()
     # 3d keywords are higher priority
     new_kw.update(JmolRenderer.default_3d_keywords)
     # user preferences always have veto power
     new_kw.update(kwargs)
     extra_lines = self._get_kwarg_script_lines(**new_kw)
     #----------------------------------------#
     if verbose: print("Generating idtf file with Jmol...")
     jscript = """
         load "{molfile}"
         {extra_lines}
         write "{tempdir}/output.idtf"
     """.format(
         molfile=self._geom_path,
         tempdir=self.tempdir,
         extra_lines=extra_lines
     )
     self._run_jmol_script(jscript)
     idtf_path = path_join(self.tempdir, "output.idtf")
     if not exists(idtf_path):
         raise RuntimeError("Jmol command failed to produce "
                            "file '{}'.  Script was:\n{}".format(
             idtf_path,
             indent(jscript)
         ))
     #----------------------------------------#
     # now convert to u3d format
     # TODO make this portable
     if verbose: print("Converting idtf file to u3d file...")
     idtf_cmd = _idtf_to_u3d_template.format(
         input=path_join(self.tempdir, "output.idtf"),
         output=path_join(self.tempdir, "output.u3d")
     )
     JmolRenderer._safe_run(shlex.split(idtf_cmd), descr="IDTF to u3d conversion")
     #shlex.os.system(idtf_cmd)
     #----------------------------------------#
     # Now embed in a latex document and run PDFLatex
     if verbose: print("Constructing latex document...".format(pdflatex_path, self.tempdir))
     with open(path_join(self.tempdir, "output.idtf.tex")) as f:
         jmol_latex_data = f.read()
     stuff3d = jmol_latex_data.split("toolbar=false,")[1].split("inline=true,")[0].strip()
     if latex_file_handler is None:
         f = open(path_join(self.tempdir, "output.tex"), "w+")
         run_pdflatex = True
     else:
         f = latex_file_handler
         run_pdflatex = False
     if run_pdflatex:
         f.write(pdf_3d_header)
     pdf3d_section = pdf_3d_entry_template\
         .replace("@@@LABEL@@@", "molecule")\
         .replace("@@@3DSTUFF@@@", stuff3d)\
         .replace("@@@FNAME@@@", path_join(self.tempdir, "output.u3d"))
     if toolbar:
         pdf3d_section = pdf3d_section.replace("toolbar=false", "toolbar=true")
     f.write(extra_latex_before)
     f.write(pdf3d_section)
     f.write(extra_latex_after)
     if run_pdflatex:
         f.write(pdf_3d_footer)
     #- - - - - - - - - - - - - - - - - - - - #
     if run_pdflatex:
         if verbose: print("Running '{} {} output' in directory {}...".format(pdflatex_path, " ".join(pdflatex_args), self.tempdir))
         pdflatex_cmd_list = [pdflatex_path] + pdflatex_args + ["output"]
         with working_directory(self.tempdir):
             # Run 3 times to get references right
             JmolRenderer._safe_run(pdflatex_cmd_list, "pdflatex",
                 require_empty_stderr=True, require_zero_exit=False)
             if verbose: print("  ...run 1 complete")
             JmolRenderer._safe_run(pdflatex_cmd_list, "output",
                 require_empty_stderr=True, require_zero_exit=False)
             if verbose: print("  ...run 2 complete")
             JmolRenderer._safe_run(pdflatex_cmd_list, "output",
                 require_empty_stderr=True, require_zero_exit=False)
             if verbose: print("  ...run 3 complete")
         #----------------------------------------#
         # Finally, copy back the temporary output to the requested file path
         #   but only if we wrote the file
         move(path_join(self.tempdir, "output.pdf"), filename)
Exemple #13
0
 def __new__(cls, **kwargs):
     """
     """
     def get_kwarg(arg, cls, subclass=False):
         gotten = pop_kwarg(kwargs, arg)
         if not subclass:
             if gotten is not None and not isinstance(gotten, cls):
                 if not isinstance(cls, tuple):
                     raise TypeError("#{0} argument given to Computation() "\
                                     "must be an instance of the #{1} class.".format(arg, classname(cls)))
                 else:
                     raise TypeError("#{0} argument given to Computation() "\
                                     "must be one of (#{1}) .".format(arg, ', '.join(classname(cl) for cl in cls)))
         else:
             if gotten is not None and not issubclass(gotten, cls):
                 if not isinstance(cls, tuple):
                     raise TypeError("#{0} argument given to Computation() "\
                                     "must be an subclass of the #{1} class.".format(arg, classname(cls)))
                 else:
                     raise TypeError("#{0} argument given to Computation() "\
                                     "must be subclass of one of (#{1}) .".format(arg, ', '.join(classname(cl) for cl in cls)))
         return gotten
     #--------------------------------------------------------------------------------#
     # Handle molecule, make a ResultGetter
     molecule = get_kwarg('molecule', Molecule)
     res_getter = get_kwarg('result_getter', ComputationResultGetter)
     if res_getter is None:
         res_getter = ComputationResultGetter(**kwargs)
         molecule.result_getters.append(res_getter)
     #--------------------------------------------------------------------------------#
     # Now see what package we're using
     package = get_kwarg('package', (basestring, PackageInterface))
     comp_class = cls
     interface = None
     if isinstance(package, PackageInterface):
         interface = package
     elif isinstance(package, basestring):
         interface = PackageInterface.load_package(
                         package,
                         input_generator=get_kwarg('input_generator', InputGenerator, True),
                         runner=get_kwarg('runner', Runner, True),
                         output_parser=get_kwarg('output_parser', OutputParser, True),
                         details_class=get_kwarg('details_class', ComputationDetails, True),
                         computation_class=get_kwarg('computation_class', cls, True)
                     )
     if interface.computation_class is not None:
         comp_class = cls
     ret_val = object.__new__(comp_class)
     #--------------------------------------------------------------------------------#
     ret_val.molecule = molecule
     res_getter.add_computation(ret_val)
     ret_val.input_generator = interface.input_generator(ret_val)
     ret_val.output_parser = interface.output_parser(ret_val)
     #TODO accept option for directory to put input/output files in
     #TODO accept option for input/output filenames
     #TODO support for runners that don't follow the input/output pattern
     ret_val.runner = interface.runner(input_file='input.dat', output_file='output.dat')
     #--------------------------------------------------------------------------------#
     ret_val.details = get_kwarg('details', interface.details_class)
     ret_val.properties = pop_kwarg(kwargs, 'property')
     if isinstance(ret_val.properties, Iterable):
         ret_val.properties = list(ret_val.properties)
     else:
         ret_val.properties = [ret_val.properties]
     if not all(issubclass(prop, MolecularProperty) or isinstance(prop, MolecularProperty) for prop in ret_val.properties):
         raise TypeError("property argument given to Computation() must be a list of MolecularProperty subclasses or instances.".format(classname(cls)))
     fixed_properties = []
     for prop in ret_val.properties:
         if isinstance(prop, MolecularProperty):
             fixed_properties.append(prop)
             prop.details = ret_val.details
         elif issubclass(prop, MolecularProperty):
             fixed_properties.append(prop(molecule=ret_val.molecule, details=ret_val.details))
     ret_val.properties = fixed_properties
     #--------------------------------------------------------------------------------#
     # Get input_filename and output_filename, if specified.  Make sure that neither
     #   is a path.
     # first get input_filename
     input_filename = pop_kwarg(kwargs, 'input_filename')
     if input_filename:
         if os.path.split(input_filename)[0] != '':
             raise ValueError("File name '{0}' given for argument 'input_filename' of Computation constructor "
                              "must be a single file, not a path.  Use the 'directory' argument to specify "
                              "a directory.".format(input_filename))
         ret_val.runner.input_file = input_filename
     else:
         ret_val.runner.input_file = Runner.default_input_filename
     #----------------------------------------#
     # now get output_filename
     output_filename = pop_kwarg(kwargs, 'output_filename')
     if output_filename:
         if os.path.split(output_filename)[0] != '':
             raise ValueError("File name '{0}' given for argument 'output_filename' of Computation constructor "
                              "must be a single file, not a path.  Use the 'directory' argument to specify "
                              "a directory.".format(output_filename))
         ret_val.runner.output_file = output_filename
     else:
         ret_val.runner.output_file = Runner.default_output_filename
     #--------------------------------------------------------------------------------#
     # Find out the desired directory and make new ones if necessary and allowed.
     ret_val.directory = pop_kwarg(kwargs, 'directory')
     used_template = False
     if ret_val.directory is not None:
         ret_val.directory = full_path(ret_val.directory)
     elif cls.directory_template is not None:
         ret_val.directory = cls.directory_template
         used_template = True
     else:
         ret_val.directory = full_path(os.curdir)
     #----------------------------------------#
     # Do mako-template style replacement, if the user has mako
     try:
         from mako.template import Template
         from mako import exceptions
         # Start with some obvious standard things to add...
         variables = dict(
             mol = ret_val.molecule, molecule = ret_val.molecule,
             calc = ret_val, calculation = ret_val,
             rg = res_getter, result_getter = res_getter,
             details = ret_val.details
         )
         # Get all of the known details, as strings
         det_strs = dict()
         for k, v in ret_val.details._known_details.items():
             det_strs[str(k)] = str(v)
             det_strs[str(k).lower()] = str(v)
             det_strs[str(k).upper()] = str(v)
             if k in Computation.attribute_aliases:
                 for alias in Computation.attribute_aliases[k]:
                     alias = make_safe_identifier(alias)
                     det_strs[str(alias)] = str(v)
                     det_strs[str(alias).lower()] = str(v)
                     det_strs[str(alias).upper()] = str(v)
         variables.update(det_strs)
         # Get any additional keywords specified by the user (advanced feature)
         additional = kwargs.pop('directory_creation_vars', dict())
         variables.update(additional)
         # Now run mako on the template...
         try:
             ret_val.directory = Template(
                 text=ret_val.directory,
                 strict_undefined=True
             ).render(
                 **variables
             )
         except:
             raise ValueError(
                 "invalid MAKO template:\n{}\nMako came back with error:\n{}".format(
                     indent(ret_val.directory),
                     indent(exceptions.text_error_template().render())
                 )
             )
         # and make it into a "url safe string":
         ret_val.directory = urllib.quote_plus(
             ret_val.directory,
             safe='/' + cls.additional_safe_directory_characters
         )
     except ImportError:
         # Can't do mako parsing of path.  Oh well...
         # But if the user specified additional args, they probably thought they did have
         #   mako installed...
         additional = kwargs.pop('directory_creation_vars', None)
         if additional is not None:
             raise
         # and if they have a ${ in the directory name or a <% in the directory name,
         #   they probably also thought that they had mako.
         # (Note: this could be an issue in the unlikely scenario that the user is using
         #   e.g. zsh and specifying environment variables from within Python as ${ }.
         #   If someone is having that problem, they probably have enough intelligence
         #   also to figure out how to get around it.)
         if '${' in ret_val.directory or '<%' in ret_val.directory:
             raise
         # if they're using a class-level template, they also need to have mako installed
         if used_template:
             raise
     #----------------------------------------#
     ret_val.directory = full_path(ret_val.directory)
     #----------------------------------------#
     # Now create the directory if we're allowed to and need to
     create_dirs = kwargs.pop('create_directories', cls.always_create_missing)
     if create_dirs:
         if not os.path.isdir(ret_val.directory):
             if os.path.exists(ret_val.directory):
                 raise OSError(
                     "path '{}' exists and is not a directory".format(
                         ret_val.directory
                     )
                 )
             os.makedirs(ret_val.directory)
     else:
         if not os.path.isdir(ret_val.directory):
             raise OSError(
                 "'{0}' is not a valid directory, and will not be created.  Set the "
                 "'create_directories' argument of computation to True to do directory "
                 "creation automatically.".format(
                     ret_val.directory
                 ))
     #----------------------------------------#
     # now set the input_file and output_file values
     ret_val.runner.input_file = os.path.join(ret_val.directory, ret_val.runner.input_file)
     ret_val.runner.output_file = os.path.join(ret_val.directory, ret_val.runner.output_file)
     ret_val.runner.working_directory = ret_val.directory
     #--------------------------------------------------------------------------------#
     # Pass the remaining kwargs on to the initialization, which may have been customized for the particular package.
     ret_val.__init__(**kwargs)
     return ret_val