Skip to content

Commit

Permalink
Add some additional classes including cjson and connect
Browse files Browse the repository at this point in the history
Signed-off-by: Geoff Hutchison <[email protected]>
  • Loading branch information
ghutchis committed Oct 29, 2023
1 parent 4af9309 commit 74f96b4
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 25 deletions.
2 changes: 2 additions & 0 deletions python/avogadro/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
from . import cjson

Check notice on line 1 in python/avogadro/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

python/avogadro/__init__.py#L1

'.cjson' imported but unused (F401)
from . import connect

Check notice on line 2 in python/avogadro/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

python/avogadro/__init__.py#L2

'.connect' imported but unused (F401)
from . import core
from . import io
70 changes: 45 additions & 25 deletions python/avogadro/cjson.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,41 @@
"""
/******************************************************************************
This source file is part of the Avogadro project.
This source code is released under the New BSD License, (the "License").
This source code is released under the 3-clause BSD License, (the "License").
******************************************************************************/
"""
import json
class Cjson:


class cjson:
"""
This Class is intended to read Cjson files
with python libraries and perform certain
methods on files and convert them back to Cjson
files as required
This class is intended to read and write cjson (chemical json) files
and help manipulate them (e.g., change coordinates, elements, etc.)
The cjson format is a JSON format for chemical information. It is
intended to be a common exchange and storage format for chemical
information that is both human and machine readable. It is intended
to be easily extended to support new features and data types.
More information and the schema can be found at:
https://github.com/OpenChemistry/chemicaljson
"""

def __init__(self):
pass

def __from_cjson(self, filePath):
'''Use to read CJson formats by converting them to python dictionaries'''
with open(filePath, 'r') as cjsonFile:
"""Use to read cjson formats by converting them to python dictionaries"""
with open(filePath, "r") as cjsonFile:
py_dict_data = json.load(cjsonFile)
return py_dict_data

def __to_cjson(self, cjson_dict_file):
'''It converts python dictionaries to CJson format'''
"""It converts python dictionaries to cjson format"""
cjsonData = json.dumps(cjson_dict_file, indent=4)
return (cjsonData)
def get_atoms_coords(self,filePath):
return cjsonData

def get_atoms_coords(self, filePath):
"""
It helps to get the co-ordinates of individual elements/atoms in the format
[
Expand All @@ -36,44 +48,52 @@ def get_atoms_coords(self,filePath):
data = self.__from_cjson(filePath)
coords = data["atoms"]["coords"]["3d"]
elements = data["atoms"]["elements"]["number"]
element_coords = [(*coords[i*3:(i+1)*3], elements[i]) for i in range(0, int(len(coords) / 3))]
cjson_dict = {"element-coordinates" :element_coords}
element_coords = [
(*coords[i * 3 : (i + 1) * 3], elements[i])
for i in range(0, int(len(coords) / 3))
]
cjson_dict = {"element-coordinates": element_coords}
return self.__to_cjson(cjson_dict)

def get_elements(self, filePath):
'''
"""
returns all the elements present in cjson file
'''
"""
data = self.__from_cjson(filePath)
elements = data["atoms"]["elements"]["number"]
return elements
def get_coordinates(self,filePath):
'''

def get_coordinates(self, filePath):
"""
returns the coordinate array
'''
"""
data = self.__from_cjson(filePath)
coords = data["atoms"]["coords"]["3d"]
return coords

def set_atoms_coordinates(self, filePath, coords_array):
'''
"""
it updates the coordinates array in cjson file
'''
"""
data = self.__from_cjson(filePath)
data["atoms"]["coords"]["3d"] = coords_array
return self.__to_cjson(data)

def set_elements(self, filePath, elements_array):
'''
"""
It sets all the elements present in the cjson file
where elements are set/recognized by their atomic numbers
'''
"""
data = self.__from_cjson(filePath)
data["atoms"]["elements"]["number"] = elements_array
return self.__to_cjson(data)

def set_coordinates(self, filePath, coords_array):
'''
"""
It helps to set all coordinates of the
cjson file where coordinates of all elements
can be changed by an input array of coords_array
'''
"""
data = self.__from_cjson(filePath)
data["atoms"]["coords"]["3d"] = coords_array
return self.__to_cjson(data)
return self.__to_cjson(data)
99 changes: 99 additions & 0 deletions python/avogadro/connect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"""
/******************************************************************************
This source file is part of the Avogadro project.
This source code is released under the 3-clause BSD License, (the "License").
******************************************************************************/
"""

import json
import os
import socket
import struct
import sys

Check notice on line 12 in python/avogadro/connect.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

python/avogadro/connect.py#L12

'sys' imported but unused (F401)

Check warning on line 12 in python/avogadro/connect.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

python/avogadro/connect.py#L12

Unused import sys
import tempfile


class connect:
"""
Send JSON-RPC requests to Avogadro through a named pipe.
This class is intended to be used by external scripts that are
run on the same machine as Avogadro.
The named pipe is created by Avogadro and is named "avogadro".
If it does not exist, Avogadro is not running.
"""

def __init__(self, name="avogadro"):
"""
Connect to the local named pipe
:param name: The name of the named pipe.
"""
# create socket and connect
try:
if os.name == "nt":
self.sock = open("//./pipe/" + name, "w+b", 0)
else:
self.sock.connect(tempfile.gettempdir() + "/" + name)
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)

except Exception as exception:
print("error while connecting: " + str(exception))
print("Is Avogadro running?")

def __json(self, method, params={}):

Check warning on line 45 in python/avogadro/connect.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

python/avogadro/connect.py#L45

Dangerous default value {} as argument
"""
Send a JSON-RPC request to the named pipe.
:param method: The JSON-RPC request method.
Send a message to the named pipe
:param file: file corresponding to method.
"""
if method == "receive_message":
size = 1024
if os.name == "nt":
packet = self.sock.read(size)
else:
packet = self.sock.recv(size)

try:
return json.loads(str(packet[4:]))
except Exception as exception:
print("error: " + str(exception))
return {}
else:
msg = {
"jsonrpc": "2.0",
"id": 0,
"method": method,
"params": params,
}
json_msg = json.dumps(msg)
size = len(json_msg)
header = struct.pack(">I", size)
packet = header + json_msg.encode("ascii")
if os.name == "nt":
self.sock.write(packet)
self.sock.seek(0)
else:
self.sock.send(packet)

def open_file(self, file):
"""Opens file"""
# param: file is filename input by the user in string
method = "openFile"
params = {"filename": file}
self.__json(method, params)
self.__json("receive_message")

def save_graphic(self, file):
"""Save Graphic"""
method = "saveGraphic"
params = {"filename": file}
self.__json(method, params)
self.__json("receive_message")

def close(self):
"""Close the socket to the named pipe"""
self.sock.close()

0 comments on commit 74f96b4

Please sign in to comment.