Source code for pyqchem.tools

import matplotlib.pyplot as plt
from pyqchem.plots import plot_configuration
from pyqchem.structure import Structure
from urllib.request import urlopen
import requests as req
import numpy as np
import json
import warnings
from requests.exceptions import ConnectionError





[docs]def plot_rasci_state_configurations(states): """ Prints :param states: parsed data (excited states) dictionary entry from RASCI calculation :return: None """ for i, state in enumerate(states): plt.figure(figsize=(len(state['configurations']), 5)) plt.title('State {}'.format(i+1)) amplitude_list = [] for j, conf in enumerate(state['configurations']): plot_configuration(conf['alpha'], conf['beta'], index=j) amplitude_list.append(conf['amplitude']) plt.plot(range(1, len(amplitude_list)+1), np.square(amplitude_list)*len(state['configurations'][0]['alpha']), label='amplitudes') plt.xlabel('Configurations') plt.ylabel('Amplitude') plt.axis('off') plt.legend() plt.show()
[docs]def submit_notice(message, service='pushbullet', pb_token=None, sp_url=None, gc_key=None, gc_token=None, gc_thread=None, slack_token=None, slack_channel=None, ): """ Submit a notification using webhooks :param message: The message to send :param service: pushbullet, samepage, google_chat :param pb_token: pushbullet token :param sp_url: samepage url :param gc_key: google chat key :param gc_token: google chat token :param gc_thread: google chat thread :param slack_token: slack bot token (xoxb-xxx.xxx.xxx), :param slack_channel: slack channel :return: server response """ if service.lower() == 'pushbullet': if pb_token is None: warnings.warn('Message: you have to specify {}'.format(['pb_token'])) url = 'https://api.pushbullet.com/v2/pushes' bot_message = json.dumps({'body': message, 'type': 'note'}) message_headers = {'Content-Type': 'application/json; charset=UTF-8', 'Access-Token': pb_token} elif service.lower() == 'samepage': if sp_url is None: warnings.warn('You have to specify {}'.format(['sp_url'])) url = sp_url bot_message = json.dumps({'text': message}) message_headers = {'Content-Type': 'application/json'} elif service.lower() == 'google_chat': if gc_key is None or gc_token is None or gc_thread is None: warnings.warn('Message: you have to specify {}'.format(['gc_key', 'gc_token', 'gc_token'])) url = 'https://chat.googleapis.com/v1/spaces/<space>/messages?key={}\&token={}\&threadKey={}'.format(gc_key, gc_token, gc_thread) bot_message = {'text': message} message_headers = {'Content-Type': 'application/json'} elif service.lower() == 'slack': if slack_token is None or slack_channel is None: warnings.warn('Message: you have to specify {}'.format(['slack_token', 'slack_channel'])) url = 'https://slack.com/api/chat.postMessage' blocks = None bot_message = {'token': slack_token, 'channel': slack_channel, 'text': message, 'blocks': json.dumps(blocks) if blocks else None} message_headers = {} else: warnings.warn('Message: client not found!') return try: with req.post(url=url, headers=message_headers, data=bot_message) as r: response = r.json() return response except ConnectionError: warnings.warn('Connection error: Message was not delivered')
[docs]def rotate_coordinates(coordinates, angle, axis, atoms_list=None, center=(0, 0, 0)): """ Rotate the coordinates (or range of coordinates) with respect a given axis :param coordinates: coordinates to rotate :param angle: rotation angle in radians :param axis: rotation axis :param atoms_list: list of atoms to rotate (if None then rotate all) :return: rotated coordinates """ axis = np.array(axis) / np.linalg.norm(axis) # normalize axis coordinates = np.array(coordinates) - np.array(center) cos_term = 1 - np.cos(angle) rot_matrix = [[axis[0]**2*cos_term + np.cos(angle), axis[0]*axis[1]*cos_term - axis[2]*np.sin(angle), axis[0]*axis[2]*cos_term + axis[1]*np.sin(angle)], [axis[1]*axis[0]*cos_term + axis[2]*np.sin(angle), axis[1]**2*cos_term + np.cos(angle), axis[1]*axis[2]*cos_term - axis[0]*np.sin(angle)], [axis[2]*axis[0]*cos_term - axis[1]*np.sin(angle), axis[1]*axis[2]*cos_term + axis[0]*np.sin(angle), axis[2]**2*cos_term + np.cos(angle)]] if atoms_list is not None: coordinates[atoms_list] = np.dot(coordinates[atoms_list], rot_matrix) else: coordinates = np.dot(coordinates, rot_matrix) + np.array(center) return coordinates.tolist()
[docs]def get_geometry_from_pubchem(entry, type='name'): """ Get structure form PubChem database :param entry: entry data :param type: data type: 'name', 'cid' :return: Structure """ base = "https://pubchem.ncbi.nlm.nih.gov/rest/pug/" input_1 = 'compound/{}/'.format(type) output_format = "JSON" additional = "record_type=3d" apiurl = base + input_1 + output_format + '?' + additional postdata = '{}={}'.format(type, entry).encode() from urllib.error import HTTPError try: response = urlopen(apiurl, postdata) except HTTPError as e: string = e.read().decode("utf-8") json_data = json.loads(string) fault = json_data['Fault'] if 'Details' in fault: raise Exception(fault['Details'][0]) else: raise Exception(fault['Message']) string = response.read().decode("utf-8") json_data = json.loads(string) conformers = json_data['PC_Compounds'][0]['coords'][0]['conformers'][0] atoms = json_data['PC_Compounds'][0]['atoms'] positions = np.array([conformers['x'], conformers['y'], conformers['z']]).T atomic_numbers = atoms['element'] if 'charge' in atoms: charge = np.add.reduce([c_atom['value'] for c_atom in atoms['charge']]) else: charge = 0 return Structure(coordinates=positions, atomic_numbers=atomic_numbers, charge=charge, name=str(entry))
if __name__ == '__main__': mol = get_geometry_from_pubchem('acetone', type='name') print(mol)