def run(self, input, output=None): if input is None: raise AquaChemistryError("Missing input.") self._parser = InputParser(input) self._parser.parse() driver_return = self._run_driver_from_parser(self._parser, False) if driver_return[0] == AquaChemistry._DRIVER_RUN_TO_HDF5: logger.info('No further process.') return {'printable': [driver_return[1]]} data = run_algorithm(driver_return[1], driver_return[2], True) if not isinstance(data, dict): raise AquaChemistryError( "Algorithm run result should be a dictionary") convert_json_to_dict(data) if logger.isEnabledFor(logging.DEBUG): logger.debug('Algorithm returned: {}'.format( pprint.pformat(data, indent=4))) lines, result = self._format_result(data) logger.info('Processing complete. Final result available') result['printable'] = lines if output is not None: with open(output, 'w') as f: for line in lines: print(line, file=f) return result
def _run_g16(cfg): # Run Gaussian 16. We capture stdout and if error log the last 10 lines that # should include the error description from Gaussian process = None try: process = Popen(GAUSSIAN_16, stdin=PIPE, stdout=PIPE, universal_newlines=True) stdout, stderr = process.communicate(cfg) process.wait() except: if process is not None: process.kill() raise AquaChemistryError('{} run has failed'.format(GAUSSIAN_16_DESC)) if process.returncode != 0: errmsg = "" if stdout is not None: lines = stdout.splitlines() start = 0 if len(lines) > 10: start = len(lines) - 10 for i in range(start, len(lines)): logger.error(lines[i]) errmsg += lines[i]+"\n" raise AquaChemistryError('{} process return code {}\n{}'.format(GAUSSIAN_16_DESC, process.returncode, errmsg)) else: if logger.isEnabledFor(logging.DEBUG): alltext = "" if stdout is not None: lines = stdout.splitlines() for line in lines: alltext += line + "\n" logger.debug("Gaussian output:\n{}".format(alltext))
def _check_molecule_format(val): """If it seems to be zmatrix rather than xyz format we convert before returning""" atoms = [x.strip() for x in val.split(';')] if atoms is None or len(atoms) < 1: raise AquaChemistryError('Molecule format error: ' + val) # Anx xyz format has 4 parts in each atom, if not then do zmatrix convert parts = [x.strip() for x in atoms[0].split(' ')] if len(parts) != 4: try: zmat = [] for atom in atoms: parts = [x.strip() for x in atom.split(' ')] z = [parts[0]] for i in range(1, len(parts), 2): z.append(int(parts[i])) z.append(float(parts[i + 1])) zmat.append(z) xyz = z2xyz(zmat) new_val = "" for i in range(len(xyz)): atm = xyz[i] if i > 0: new_val += "; " new_val += "{} {} {} {}".format(atm[0], atm[1], atm[2], atm[3]) return new_val except Exception as exc: raise AquaChemistryError('Failed to convert atom string: ' + val) from exc return val
def register_chemistry_operator(cls): """ Registers a chemistry operator class Args: cls (object): chemistry operator class. Returns: name: input name Raises: AquaChemistryError: if the class is already registered or could not be registered """ _discover_on_demand() # Verify that the pluggable is not already registered if cls in [input.cls for input in _REGISTERED_CHEMISTRY_OPERATORS.values()]: raise AquaChemistryError( 'Could not register class {} is already registered'.format(cls)) # Verify that it has a minimal valid configuration. try: chemistry_operator_name = cls.CONFIGURATION['name'] except (LookupError, TypeError): raise AquaChemistryError( 'Could not register chemistry operator: invalid configuration') if chemistry_operator_name in _REGISTERED_CHEMISTRY_OPERATORS: raise AquaChemistryError('Could not register class {}. Name {} {} is already registered'.format(cls, chemistry_operator_name, _REGISTERED_CHEMISTRY_OPERATORS[chemistry_operator_name].cls)) # Append the pluggable to the `registered_classes` dict. _REGISTERED_CHEMISTRY_OPERATORS[chemistry_operator_name] = RegisteredChemOp( chemistry_operator_name, cls, copy.deepcopy(cls.CONFIGURATION)) return chemistry_operator_name
def _run_psi4(input_file, output_file): # Run psi4. process = None try: process = subprocess.Popen([PSI4, input_file, output_file], stdout=subprocess.PIPE, universal_newlines=True) stdout, stderr = process.communicate() process.wait() except: if process is not None: process.kill() raise AquaChemistryError('{} run has failed'.format(PSI4)) if process.returncode != 0: errmsg = "" if stdout is not None: lines = stdout.splitlines() for i in range(len(lines)): logger.error(lines[i]) errmsg += lines[i] + "\n" raise AquaChemistryError('{} process return code {}\n{}'.format( PSI4, process.returncode, errmsg))
def _augment_config(self, fname, cfg): cfgaug = "" with io.StringIO() as outf: with io.StringIO(cfg) as inf: # Add our Route line at the end of any existing ones line = "" added = False while not added: line = inf.readline() if not line: break if line.startswith('#'): outf.write(line) while not added: line = inf.readline() if not line: raise AquaChemistryError('Unexpected end of Gaussian input') if len(line.strip()) == 0: outf.write('# Window=Full Int=NoRaff Symm=(NoInt,None) output=(matrix,i4labels,mo2el) tran=full\n') added = True outf.write(line) else: outf.write(line) # Now add our filename after the title and molecule but before any additional data. We located # the end of the # section by looking for a blank line after the first #. Allows comment lines # to be inter-mixed with Route lines if that's ever done. From here we need to see two sections # more, the title and molecule so we can add the filename. added = False section_count = 0 blank = True while not added: line = inf.readline() if not line: raise AquaChemistryError('Unexpected end of Gaussian input') if len(line.strip()) == 0: blank = True if section_count == 2: break else: if blank: section_count += 1 blank = False outf.write(line) outf.write(line) outf.write(fname) outf.write('\n\n') # Whatever is left in the original config we just append without further inspection while True: line = inf.readline() if not line: break outf.write(line) cfgaug = outf.getvalue() return cfgaug
def compute_integrals(config): # Get config from input parameters # Molecule is in this format: # atoms=H .0 .0 .0; H .0 .0 0.2 # units=Angstrom # charge=0 # multiplicity=1 # where we support symbol for atom as well as number if 'atoms' not in config: raise AquaChemistryError('Atoms is missing') val = config['atoms'] if val is None: raise AquaChemistryError('Atoms value is missing') charge = int(config.get('charge', '0')) multiplicity = int(config.get('multiplicity', '1')) units = __checkUnits(config.get('units', 'Angstrom')) mol = __parseMolecule(val, units, charge, multiplicity) basis = config.get('basis', 'sto3g') calc_type = config.get('calc_type', 'rhf').lower() try: ehf, enuke, norbs, mohij, mohijkl, orbs, orbs_energy = _calculate_integrals( mol, basis, calc_type) except Exception as exc: raise AquaChemistryError( 'Failed electronic structure computation') from exc # Create driver level molecule object and populate _q_ = QMolecule() # Energies and orbits _q_._hf_energy = ehf _q_._nuclear_repulsion_energy = enuke _q_._num_orbitals = norbs _q_._num_alpha = mol.nup() _q_._num_beta = mol.ndown() _q_._mo_coeff = orbs _q_._orbital_energies = orbs_energy # Molecule geometry _q_._molecular_charge = mol.charge _q_._multiplicity = mol.multiplicity _q_._num_atoms = len(mol) _q_._atom_symbol = [] _q_._atom_xyz = np.empty([len(mol), 3]) atoms = mol.atoms for _n in range(0, _q_._num_atoms): atuple = atoms[_n].atuple() _q_._atom_symbol.append(QMolecule.symbols[atuple[0]]) _q_._atom_xyz[_n][0] = atuple[1] _q_._atom_xyz[_n][1] = atuple[2] _q_._atom_xyz[_n][2] = atuple[3] # 1 and 2 electron integrals _q_._mo_onee_ints = mohij _q_._mo_eri_ints = mohijkl return _q_
def export_dictionary(self, file_name): if file_name is None: raise AquaChemistryError('Missing file path') file_name = file_name.strip() if len(file_name) == 0: raise AquaChemistryError('Missing file path') value = json.loads(json.dumps(self.to_dictionary())) value = pprint.pformat(value, indent=4) with open(file_name, 'w') as f: print(value, file=f)
def _check_molecule_format(val): """If it seems to be zmatrix rather than xyz format we convert before returning""" atoms = [x.strip() for x in val.split(';')] if atoms is None or len(atoms) < 1: raise AquaChemistryError('Molecule format error: ' + val) # Anx xyz format has 4 parts in each atom, if not then do zmatrix convert parts = [x.strip() for x in atoms[0].split(' ')] if len(parts) != 4: try: return gto.mole.from_zmatrix(val) except Exception as exc: raise AquaChemistryError('Failed to convert atom string: ' + val) from exc return val
def run(self, section): cfg = section['data'] if cfg is None or not isinstance(cfg,str): raise AquaChemistryError("Gaussian user supplied configuration invalid: '{}'".format(cfg)) while not cfg.endswith('\n\n'): cfg += '\n' logger.debug("User supplied configuration raw: '{}'".format(cfg.replace('\r', '\\r').replace('\n', '\\n'))) logger.debug('User supplied configuration\n{}'.format(cfg)) # To the Gaussian section of the input file passed here as section['data'] # add line '# Symm=NoInt output=(matrix,i4labels,mo2el) tran=full' # NB: Line above needs to be added in right context, i.e after any lines # beginning with % along with any others that start with # # append at end the name of the MatrixElement file to be written fd, fname = tempfile.mkstemp(suffix='.mat') os.close(fd) cfg = self._augment_config(fname, cfg) logger.debug('Augmented control information:\n{}'.format(cfg)) GaussianDriver._run_g16(cfg) q_mol = self._parse_matrix_file(fname) try: os.remove(fname) except: logger.warning("Failed to remove MatrixElement file " + fname) return q_mol
def run_algorithm_from_json(self, params, output=None, backend=None): """ Runs the Aqua Chemistry experiment from json dictionary Args: params (dictionary): Input data output (filename): Output data backend (BaseBackend): backend object Returns: result dictionary """ ret = run_algorithm(params, None, True, backend) if not isinstance(ret, dict): raise AquaChemistryError( "Algorithm run result should be a dictionary") convert_json_to_dict(ret) if logger.isEnabledFor(logging.DEBUG): logger.debug('Algorithm returned: {}'.format( pprint.pformat(ret, indent=4))) print('Output:') if isinstance(ret, dict): for k, v in ret.items(): print("'{}': {}".format(k, v)) else: print(ret) return ret
def _update_algorithm_problem(self): problem_name = self.get_section_property(JSONSchema.PROBLEM, JSONSchema.NAME) if problem_name is None: problem_name = self.get_property_default_value( JSONSchema.PROBLEM, JSONSchema.NAME) if problem_name is None: raise AquaChemistryError( "No algorithm 'problem' section found on input.") algo_name = self.get_section_property(JSONSchema.ALGORITHM, JSONSchema.NAME) if algo_name is not None and problem_name in InputParser.get_algorithm_problems( algo_name): return for algo_name in local_algorithms(): if problem_name in self.get_algorithm_problems(algo_name): # set to the first algorithm to solve the problem self.set_section_property(JSONSchema.ALGORITHM, JSONSchema.NAME, algo_name) return # no algorithm solve this problem, remove section self.delete_section(JSONSchema.ALGORITHM)
def set_default_properties_for_name(self, section_name): if self._parser is None: raise AquaChemistryError('Input not initialized.') name = self._parser.get_section_property(section_name, JSONSchema.NAME) self._parser.delete_section_properties(section_name) if name is not None: self._parser.set_section_property(section_name, JSONSchema.NAME, name) value = self._parser.get_section_default_properties(section_name) if isinstance(value, dict): for property_name, property_value in value.items(): if property_name != JSONSchema.NAME: self._parser.set_section_property(section_name, property_name, property_value) else: if value is None: types = self._parser.get_section_types(section_name) if 'null' not in types: if 'string' in types: value = '' elif 'object' in types: value = {} elif 'array' in types: value = [] self._parser.set_section_data(section_name, value)
def set_section(self, section_name): if self._parser is None: raise AquaChemistryError('Input not initialized.') self._parser.set_section(section_name) value = self._parser.get_section_default_properties(section_name) if isinstance(value, dict): for property_name, property_value in value.items(): self._parser.set_section_property(section_name, property_name, property_value) # do one more time in case schema was updated value = self._parser.get_section_default_properties(section_name) for property_name, property_value in value.items(): self._parser.set_section_property(section_name, property_name, property_value) else: if value is None: types = self._parser.get_section_types(section_name) if 'null' not in types: if 'string' in types: value = '' elif 'object' in types: value = {} elif 'array' in types: value = [] self._parser.set_section_data(section_name, value)
def _validate_operator_problem(self): operator_name = self.get_section_property(InputParser.OPERATOR, JSONSchema.NAME) if operator_name is None: return problem_name = self.get_section_property(JSONSchema.PROBLEM, JSONSchema.NAME) if problem_name is None: problem_name = self.get_property_default_value(JSONSchema.PROBLEM, JSONSchema.NAME) if problem_name is None: raise AquaChemistryError("No algorithm 'problem' section found on input.") problems = InputParser.get_operator_problems(operator_name) if problem_name not in problems: raise AquaChemistryError( "Problem: {} not in the list of problems: {} for operator: {}.".format(problem_name, problems, operator_name))
def _validate_algorithm_problem(self): algo_name = self.get_section_property(PluggableType.ALGORITHM.value, JSONSchema.NAME) if algo_name is None: return problem_name = self.get_section_property(JSONSchema.PROBLEM, JSONSchema.NAME) if problem_name is None: problem_name = self.get_property_default_value(JSONSchema.PROBLEM, JSONSchema.NAME) if problem_name is None: raise AquaChemistryError("No algorithm 'problem' section found on input.") problems = InputParser.get_algorithm_problems(algo_name) if problem_name not in problems: raise AquaChemistryError("Problem: {} not in the list of problems: {} for algorithm: {}.".format( problem_name, problems, algo_name))
def _update_operator_problem(self): problem_name = self.get_section_property(JSONSchema.PROBLEM, JSONSchema.NAME) if problem_name is None: problem_name = self.get_property_default_value( JSONSchema.PROBLEM, JSONSchema.NAME) if problem_name is None: raise AquaChemistryError( "No algorithm 'problem' section found on input.") operator_name = self.get_section_property(InputParser.OPERATOR, JSONSchema.NAME) if operator_name is not None and problem_name in InputParser.get_operator_problems( operator_name): return for operator_name in local_chemistry_operators(): if problem_name in self.get_operator_problems(operator_name): # set to the first input to solve the problem self.set_section_property(InputParser.OPERATOR, JSONSchema.NAME, operator_name) return # no input solve this problem, remove section self.delete_section(InputParser.OPERATOR)
def parse(self): """Parse the data.""" if self._inputdict is None: if self._filename is None: raise AquaChemistryError("Missing input file") section = None self._sections = OrderedDict() with open(self._filename, 'rt', encoding="utf8", errors='ignore') as f: for line in f: section = self._process_line(section, line) else: self._load_parser_from_dict() # check for old enable_substitutions name old_enable_substitutions = self.get_section_property( JSONSchema.PROBLEM, InputParser._OLD_ENABLE_SUBSTITUTIONS) if old_enable_substitutions is not None: self.delete_section_property(JSONSchema.PROBLEM, InputParser._OLD_ENABLE_SUBSTITUTIONS) self.set_section_property(JSONSchema.PROBLEM, InputParser.AUTO_SUBSTITUTIONS, old_enable_substitutions) self._json_schema.update_pluggable_input_schemas(self) self._update_driver_input_schemas() self._update_operator_input_schema() self._sections = self._order_sections(self._sections) self._original_sections = copy.deepcopy(self._sections)
def _process_line(self, section, line): stripLine = line.strip() if len(stripLine) == 0: if section is not None: section['data'].append(line) return section if stripLine.lower().startswith(InputParser._END_SECTION): if section is not None: self._sections[section[ JSONSchema.NAME]] = self._process_section(section) return None if stripLine.startswith(InputParser._START_SECTION): if section is not None: raise AquaChemistryError( 'New section "{0}" starting before the end of previuos section "{1}"' .format(line, section[JSONSchema.NAME])) return OrderedDict([(JSONSchema.NAME, stripLine[1:].lower()), ('data', [])]) if section is None: return section section['data'].append(line) return section
def process_substitutions(self, substitutions=None): if substitutions is not None and not isinstance(substitutions, dict): raise AquaChemistryError( 'Invalid substitution parameter: {}'.format(substitutions)) if not self.is_substitution_allowed(): return {} result = {} for key, value in self._substitutions.items(): key_items = key.split('.') if len(key_items) != 3: raise AquaChemistryError( 'Invalid substitution key: {}'.format(key)) name = self.get_property_default_value(key_items[0], JSONSchema.NAME) name = self.get_section_property(key_items[0], JSONSchema.NAME, name) if name != key_items[1]: continue value_set = False value_items = value.split('.') if len(value_items) == 3: name = self.get_section_property(value_items[0], JSONSchema.NAME) if name == value_items[1]: v = self.get_property_default_value( value_items[0], value_items[2]) v = self.get_section_property(value_items[0], value_items[2], v) if v is not None: self.set_section_property(key_items[0], key_items[2], v) result[key] = v value_set = True if value_set or substitutions is None: continue if value in substitutions: self.set_section_property(key_items[0], key_items[2], substitutions[value]) result[key] = substitutions[value] return result
def _update_operator_input_schema(self): # find operator default_name = self.get_property_default_value( InputParser.OPERATOR, JSONSchema.NAME) operator_name = self.get_section_property( InputParser.OPERATOR, JSONSchema.NAME, default_name) if operator_name is None: # find the first valid input for the problem problem_name = self.get_section_property( JSONSchema.PROBLEM, JSONSchema.NAME) if problem_name is None: problem_name = self.get_property_default_value( JSONSchema.PROBLEM, JSONSchema.NAME) if problem_name is None: raise AquaChemistryError( "No algorithm 'problem' section found on input.") for name in local_chemistry_operators(): if problem_name in self.get_operator_problems(name): # set to the first input to solve the problem operator_name = name break if operator_name is None: # just remove fromm schema if none solves the problem if InputParser.OPERATOR in self._json_schema.schema['properties']: del self._json_schema.schema['properties'][InputParser.OPERATOR] return if default_name is None: default_name = operator_name config = {} try: config = get_chemistry_operator_configuration(operator_name) except: pass input_schema = config['input_schema'] if 'input_schema' in config else { } properties = input_schema['properties'] if 'properties' in input_schema else { } properties[JSONSchema.NAME] = {'type': 'string'} required = input_schema['required'] if 'required' in input_schema else [ ] additionalProperties = input_schema['additionalProperties'] if 'additionalProperties' in input_schema else True if default_name is not None: properties[JSONSchema.NAME]['default'] = default_name required.append(JSONSchema.NAME) if InputParser.OPERATOR not in self._json_schema.schema['properties']: self._json_schema.schema['properties'][InputParser.OPERATOR] = { 'type': 'object'} self._json_schema.schema['properties'][InputParser.OPERATOR]['properties'] = properties self._json_schema.schema['properties'][InputParser.OPERATOR]['required'] = required self._json_schema.schema['properties'][InputParser.OPERATOR]['additionalProperties'] = additionalProperties
def delete_section_property(self, section_name, property_name): if self._parser is None: raise AquaChemistryError('Input not initialized.') self._parser.delete_section_property(section_name, property_name) if InputParser.is_pluggable_section( section_name) and property_name == JSONSchema.NAME: self._parser.delete_section_properties(section_name)
def __checkUnits(units): if units.lower() in ["angstrom", "ang", "a"]: units = 'Angstrom' elif units.lower() in ["bohr", "b"]: units = 'Bohr' else: raise AquaChemistryError('Molecule units format error: ' + units) return units
def __parseAtom(val): if val is None or len(val) < 1: raise AquaChemistryError('Molecule atom format error: ' + val) parts = re.split('\s+', val) if len(parts) != 4: raise AquaChemistryError('Molecule atom format error: ' + val) parts[0] = parts[0].lower().capitalize() if not parts[0].isdigit(): if parts[0] in QMolecule.symbols: parts[0] = QMolecule.symbols.index(parts[0]) else: raise AquaChemistryError('Molecule atom symbol error: ' + parts[0]) return int(float(parts[0])), float(parts[1]), float(parts[2]), float( parts[3])
def register_chemistry_operator(cls, configuration=None): """ Registers a chemistry operator class Args: cls (object): chemistry operator class. configuration (object, optional): Pluggable configuration Returns: name: input name Raises: AquaChemistryError: if the class is already registered or could not be registered """ _discover_on_demand() # Verify that the pluggable is not already registered if cls in [ input.cls for input in _REGISTERED_CHEMISTRY_OPERATORS.values() ]: raise AquaChemistryError( 'Could not register class {} is already registered'.format(cls)) try: chem_instance = cls(configuration=configuration) except Exception as err: raise AquaChemistryError( 'Could not register chemistry operator:{} could not be instantiated: {}' .format(cls, str(err))) # Verify that it has a minimal valid configuration. try: chemistry_operator_name = chem_instance.configuration['name'] except (LookupError, TypeError): raise AquaChemistryError( 'Could not register chemistry operator: invalid configuration') if chemistry_operator_name in _REGISTERED_CHEMISTRY_OPERATORS: raise AquaChemistryError( 'Could not register class {}. Name {} {} is already registered'. format( cls, chemistry_operator_name, _REGISTERED_CHEMISTRY_OPERATORS[chemistry_operator_name].cls)) # Append the pluggable to the `registered_classes` dict. _REGISTERED_CHEMISTRY_OPERATORS[ chemistry_operator_name] = RegisteredChemOp( chemistry_operator_name, cls, chem_instance.configuration) return chemistry_operator_name
def save_input(self, input_file): """Save the input of a run to a file. Params: input_file (string): file path """ if self._parser is None: raise AquaChemistryError("Missing input information.") self._parser.save_to_file(input_file)
def _calculate_integrals(molecule, basis='sto3g', calc_type='rhf'): """Function to calculate the one and two electron terms. Perform a Hartree-Fock calculation in the given basis. Args: molecule : A pyquante2 molecular object. basis : The basis set for the electronic structure computation calc_type: rhf, uhf, rohf Returns: ehf : Hartree-Fock energy enuke: Nuclear repulsion energy norbs : Number of orbitals mohij : One electron terms of the Hamiltonian. mohijkl : Two electron terms of the Hamiltonian. orbs: Molecular orbital coefficients orbs_energy: Orbital energies """ bfs = basisset(molecule, basis) integrals = onee_integrals(bfs, molecule) hij = integrals.T + integrals.V hijkl_compressed = twoe_integrals(bfs) # convert overlap integrals to molecular basis # calculate the Hartree-Fock solution of the molecule if calc_type == 'rhf': solver = rhf(molecule, bfs) elif calc_type == 'rohf': solver = rohf(molecule, bfs) elif calc_type == 'uhf': solver = uhf(molecule, bfs) else: raise AquaChemistryError('Invalid calc_type: {}'.format(calc_type)) logger.debug('Solver name {}'.format(solver.name)) ehf = solver.converge() if hasattr(solver, 'orbs'): orbs = solver.orbs else: orbs = solver.orbsa norbs = len(orbs) if hasattr(solver, 'orbe'): orbs_energy = solver.orbe else: orbs_energy = solver.orbea enuke = molecule.nuclear_repulsion() # Get ints in molecular orbital basis mohij = simx(hij, orbs) mohijkl_compressed = transformintegrals(hijkl_compressed, orbs) mohijkl = np.zeros((norbs, norbs, norbs, norbs)) for i in range(norbs): for j in range(norbs): for k in range(norbs): for l in range(norbs): mohijkl[i, j, k, l] = mohijkl_compressed[ijkl2intindex(i, j, k, l)] return ehf[0], enuke, norbs, mohij, mohijkl, orbs, orbs_energy
def __parseMolecule(val, units, charge, multiplicity): parts = [x.strip() for x in val.split(';')] if parts is None or len(parts) < 1: raise AquaChemistryError('Molecule format error: ' + val) geom = [] for n in range(len(parts)): part = parts[n] geom.append(__parseAtom(part)) if len(geom) < 1: raise AquaChemistryError('Molecule format error: ' + val) try: return molecule(geom, units=units, charge=charge, multiplicity=multiplicity) except Exception as exc: raise AquaChemistryError('Failed to create molecule') from exc
def set_section_property(self, section_name, property_name, value): section_name = JSONSchema.format_section_name(section_name).lower() property_name = JSONSchema.format_property_name(property_name) value = self._json_schema.check_property_value(section_name, property_name, value) types = self.get_property_types(section_name, property_name) parser_temp = copy.deepcopy(self) InputParser._set_section_property(parser_temp._sections, section_name, property_name, value, types) msg = self._json_schema.validate_property(parser_temp.to_JSON(), section_name, property_name) if msg is not None: raise AquaChemistryError("{}.{}: Value '{}': '{}'".format( section_name, property_name, value, msg)) InputParser._set_section_property(self._sections, section_name, property_name, value, types) if property_name == JSONSchema.NAME: if InputParser.OPERATOR == section_name: self._update_operator_input_schema() # remove properties that are not valid for this section default_properties = self.get_section_default_properties( section_name) if isinstance(default_properties, dict): properties = self.get_section_properties(section_name) for property_name in list(properties.keys()): if property_name != JSONSchema.NAME and property_name not in default_properties: self.delete_section_property( section_name, property_name) elif JSONSchema.PROBLEM == section_name: self._update_algorithm_problem() self._update_operator_problem() elif InputParser.is_pluggable_section(section_name): self._json_schema.update_pluggable_input_schemas(self) # remove properties that are not valid for this section default_properties = self.get_section_default_properties( section_name) if isinstance(default_properties, dict): properties = self.get_section_properties(section_name) for property_name in list(properties.keys()): if property_name != JSONSchema.NAME and property_name not in default_properties: self.delete_section_property( section_name, property_name) if section_name == JSONSchema.ALGORITHM: self._update_dependency_sections() elif value is not None: value = str(value).lower().strip() if len(value) > 0 and self.section_is_driver(value): self._update_driver_input_schemas() self._update_driver_sections() self._sections = self._order_sections(self._sections)
def _run_drive(self, input, save_json_algo_file): if input is None: raise AquaChemistryError("Missing input.") self._parser = InputParser(input) self._parser.parse() driver_return = self._run_driver_from_parser(self._parser, save_json_algo_file) driver_return[1]['input'] = driver_return[2].to_params() driver_return[1]['input']['name'] = driver_return[2].configuration[ 'name'] return driver_return[1]