Python3.8 pySerial sending int64 as signed bytes - byte

I'm trying to convert a class 'numpy.int64'named "int_array" into bytes.
In the past I used this structure
(-1024).to_bytes(8, byteorder='big', signed=True)
and worked fine.
Now, saving all the integers into a matrix, it doesn't allow me to do this:
int_array[1][i].to_bytes(8, byteorder='big', signed=True)
If there is a function for integer32 it would also work.
Does anybody know an equivalent command?
I will appreciate any help.

Apparently, in Python 3.8 I'm not allowed to do that.
The int.to_bytes method is available since Python 3.2:
New in version 3.2.
Alternatively you can use the struct module:
>>> import struct
>>> struct.pack(">q", -1024)
b'\xff\xff\xff\xff\xff\xff\xfc\x00'

Related

Chem.RDKFingerprint did not match C++ signature for some SMILES, but okay for others

I'm working on trying to use ligands that are referenced in UniProt with the same ligand in PDB entries. For many ligands (e.g. FAD), the three-letter code is the same in both UniProt and PDB entries, but for some there is a slight difference. For example, for haemoglobin 1a9w chain A, in the PDB file I find "HEM" but in the corresponding UniProt entry (P69905) I find "heme b". "heme b" (in the UniProt json) has chebi id CHEBI:60344.
I downloaded the full ChEBI sdf file from https://ftp.ebi.ac.uk/pub/databases/chebi/SDF/, and find there are three haems that are close to what I want. So far, so good.
If I use the following code to calculate Tanimoto coefficients using CHEBI:60344 as a reference, one of the haems is okay but the other raises a C++ exception that I haven't been able to catch in my Python code. The problem is that if my list of chebi ids is the other way round, the code always fails before I get a value for the Tanimoto coefficient.
My question is - is this a bug in my implementation of the RDKIT code, is it a bug in the RDKIT code, is it a bug in the ChEBI module of bioservices, is the SMILES string in the ChEBI sdf file written incorrectly, or is there another issue?
This is all using conda installed rdkit, bioservices, python3.9 etc on a (old) Mac Pro running High Sierra (can't upgrade to a newer OS).
Ran this code:
from rdkit import Chem, DataStructs
from bioservices import ChEBI
heme = ChEBI()
heme_chebi_id = "CHEBI:60344"
heme_smiles = heme.getCompleteEntity(heme_chebi_id).smiles
target = Chem.MolFromSmiles(heme_smiles)
fp2 = Chem.RDKFingerprint(target)
for chebi_id in ["CHEBI:17627", "CHEBI:26355"]:
ch = ChEBI()
smiley = ch.getCompleteEntity(chebi_id).smiles
print("reference:", heme_chebi_id)
print("target: ", chebi_id)
print("reference:", heme_smiles)
print("target: ", smiley)
ref = Chem.MolFromSmiles(smiley)
fp1 = Chem.RDKFingerprint(ref)
Tan = DataStructs.TanimotoSimilarity(fp1, fp2)
print(Tan)
print("-" * 64)
exit()
got this output:
reference: CHEBI:60344
target: CHEBI:17627
reference: CC1=C(CCC([O-])=O)C2=[N+]3C1=Cc1c(C)c(C=C)c4C=C5C(C)=C(C=C)C6=[N+]5[Fe--]3(n14)n1c(=C6)c(C)c(CCC([O-])=O)c1=C2
target: CC1=C(CCC(O)=O)C2=[N+]3C1=Cc1c(C)c(C=C)c4C=C5C(C)=C(C=C)C6=[N+]5[Fe--]3(n14)n1c(=C6)c(C)c(CCC(O)=O)c1=C2
Tanimoto coefficient: 1.0
reference: CHEBI:60344
target: CHEBI:26355
reference: CC1=C(CCC([O-])=O)C2=[N+]3C1=Cc1c(C)c(C=C)c4C=C5C(C)=C(C=C)C6=[N+]5[Fe--]3(n14)n1c(=C6)c(C)c(CCC([O-])=O)c1=C2
target: CC1=C(CCC(O)=O)C2=[N]3C1=Cc1c(C)c(C=C)c4C=C5C(C)=C(C=C)C6=[N]5[Fe]3(n14)n1c(=C6)c(C)c(CCC(O)=O)c1=C2
[12:36:26] Explicit valence for atom # 9 N, 4, is greater than permitted
Traceback (most recent call last):
File "/Volumes/Users/harry/icl/phyre2-ligand/./tanimoto_test.py", line 20, in <module>
fp1 = Chem.RDKFingerprint(ref)
Boost.Python.ArgumentError: Python argument types in
rdkit.Chem.rdmolops.RDKFingerprint(NoneType)
did not match C++ signature:
RDKFingerprint(RDKit::ROMol mol, unsigned int minPath=1, unsigned int maxPath=7, unsigned int fpSize=2048, unsigned int nBitsPerHash=2, bool useHs=True, double tgtDensity=0.0, unsigned int minSize=128, bool branchedPaths=True, bool useBondOrder=True, boost::python::api::object atomInvariants=0, boost::python::api::object fromAtoms=0, boost::python::api::object atomBits=None, boost::python::api::object bitInfo=None)
This error means that the input to the function Chem.RDKFingerprint is None. That means that ref is None. You can try printing the value of ref to verify.
In this case, this is None because RdKit is not able to parse the given SMILES to a proper mol object. It has even raised the following warning if you look at the error carefully:
Explicit valence for atom # 9 N, 4, is greater than permitted
This is because of the co-ordinate bond present in the molecule which RdKit doesn't support. RdKit will treat it as a single bond which will raise the valency of both the Nitrogen atoms to 4 and hence an invalid molecule. Here's the same molecule generated from other sources:
To deal with this error, you'll have to modify the SMILES manually to make it such that either there's a charge on those nitrogen atoms or [Fe] is a separate atom rather than connected with a bond. Something like this:
This isn't really an issue with the SMILES but more of a limitation with RDKit for its inability to support co-ordinate bonds. I have faced this issue many times and always had to modify the SMILES manually to get around it. One suggestion for you is that you can programmatically modify the SMILES because this kind of error will most likely occur for Metal-Ligand catalysts where a co-ordinate bond is almost always there. So you can search for atoms like [Fe] or [Pt] in the SMILES string and then modify them.
I've managed to get a couple of workarounds for this.
The problem arises because RDKit is (as of 30 Jan 2023) unable to process some IUPAC compliant SMILES (as noted in betelgeuse's answers).
One thing to do is to use the "Sanitize=False" option for rdkit.Chem.MolFromSmiles - this allows a non-None value to be returned for this SMILES, and subsequently, rdkit.Chem.RDKFingerprint returns a useful value.
However, using the results of the "Sanitize=False" option fails if I want to explore an alternative measure of similarity, e.g. FCFP4 instead of Tanimoto, using "rdkit.Chem.rdMolDescriptors.GetMorganFingerprint"; the way I got round this was to test for "None" from MolFromSmiles without using sanitize=False, retrieve an alternative SMILES from PubChem and use that. Having said that, if I didn't really want the SMILES from PDBeChem, I could have done that in the first place...

Set locale to cartopy ticker

I was wondering and searching on the docs: is there a way to set the locale, for example, to use commas instead of points as separators for decimals in cartopy ticklabels?
In matplotlib it can be done, but it doesn't apply to cartopy.mpl.ticker's LongitudeFormatter and LatitudeFormatter.
Maybe it's something for the developers to add in newer versions?
Nothing too special about the LongitudeFormatter and LatitudeFormatter, they are just specialised Formatters.
So, the gridlines object has properties 'xformatter' and 'yformatter', which have a 'set_useLocale' method.
This worked for me...
>>> ax = plt.gca()
>>> gl = ax.gridlines(draw_labels=True,
... xlocs=[-120.5, -50.8, 30.7, 134.2, 157.8])
>>> gl.xformatter.set_useLocale(True)
>>> plt.show()
BUT you do have to have the machine locale set to start with.
In order to get "," numeric seperators, I started with :
$ export LC_NUMERIC="it_IT.UTF-8"
$ python
I don't know much about it, but I think you can't change this dynamically through the Python interface, it needs to be in the calling environment
-- see Setting Python locale doesn't work

Unknown type name array

I have a metal 2 shader on macOS 10.12 that I am trying to pass an array of int into, but XCode is giving me a compile-time error Unknown type name 'array'. Here is the code I am using:
kernel void computeMandelbrot(texture2d<float, access::write> output [[texture(0)]], constant int &maxIterations [[buffer(1)]], const array<int, 10> &hist [[buffer(2)]], uint2 gid [[thread_position_in_grid]]) {
// Compute Mandelbrot
}
I have also tried using the keyword constant instead of const but then I also get an error of Parameter may not be qualified with an address space. I had read that arrays of textures were not supported in metal on macOS, but I was not sure if this appled to arrays of other types. Any help would be greatly appriciated, thank you!
A few things:
Metal 2 is not available in macOS 10.12. It is new with 10.13.
array is only usable with textures and samplers.
array is not available on macOS <=10.12. It's available on macOS 10.13+ with Metal 2.
You can declare your parameter as constant int *hist [[buffer(2)]]. It won't have an explicit length, but just limit what elements you reference.
Edit: I was wrong about array only being usable with textures and samplers. The spec suggests that to be the case by introducing it in a section titled "Arrays of Textures and Samplers" and only illustrating its use that way, but the template class itself seems generically useful.
However, until Metal 2, it's not available on macOS. In other words, it's only available on macOS 10.13+.

Using termios in Swift

Now that we've reached Swift 2.0, I've decided to convert my, as yet unfinished, OS X app to Swift. Making progress but I've run into some issues with using termios and could use some clarification and advice.
The termios struct is treated as a struct in Swift, no surprise there, but what is surprising is that the array of control characters in the struct is now a tuple. I was expecting it to just be an array. As you might imagine it took me a while to figure this out. Working in a Playground if I do:
var settings:termios = termios()
print(settings)
then I get the correct details printed for the struct.
In Obj-C to set the control characters you would use, say,
cfmakeraw(&settings);
settings.c_cc[VMIN] = 1;
where VMIN is a #define equal to 16 in termios.h. In Swift I have to do
cfmakeraw(&settings)
settings.c_cc.16 = 1
which works, but is a bit more opaque. I would prefer to use something along the lines of
settings.c_cc.vim = 1
instead, but can't seem to find any documentation describing the Swift "version" of termios. Does anyone know if the tuple has pre-assigned names for it's elements, or if not, is there a way to assign names after the fact? Should I just create my own tuple with named elements and then assign it to settings.c_cc?
Interestingly, despite the fact that pre-processor directives are not supposed to work in Swift, if I do
print(VMIN)
print(VTIME)
then the correct values are printed and no compiler errors are produced. I'd be interested in any clarification or comments on that. Is it a bug?
The remaining issues have to do with further configuration of the termios.
The definition of cfsetspeed is given as
func cfsetspeed(_: UnsafeMutablePointer<termios>, _: speed_t) -> Int32
and speed_t is typedef'ed as an unsigned long. In Obj-C we'd do
cfsetspeed(&settings, B38400);
but since B38400 is a #define in termios.h we can no longer do that. Has Apple set up replacement global constants for things like this in Swift, and if so, can anyone tell me where they are documented. The alternative seems to be to just plug in the raw values and lose readability, or to create my own versions of the constants previously defined in termios.h. I'm happy to go that route if there isn't a better choice.
Let's start with your second problem, which is easier to solve.
B38400 is available in Swift, it just has the wrong type.
So you have to convert it explicitly:
var settings = termios()
cfsetspeed(&settings, speed_t(B38400))
Your first problem has no "nice" solution that I know of.
Fixed sized arrays are imported to Swift as tuples, and – as far as I know – you cannot address a tuple element with a variable.
However,Swift preserves the memory layout of structures imported from C, as
confirmed by Apple engineer Joe Groff:. Therefore you can take the address of the tuple and “rebind” it to a pointer to the element type:
var settings = termios()
withUnsafeMutablePointer(to: &settings.c_cc) { (tuplePtr) -> Void in
tuplePtr.withMemoryRebound(to: cc_t.self, capacity: MemoryLayout.size(ofValue: settings.c_cc)) {
$0[Int(VMIN)] = 1
}
}
(Code updated for Swift 4+.)

How to force a raw value of 7 into a UIViewAnimationCurve enum?

The key UIKeyboardAnimationCurveUserInfoKey in the userInfo dictionary of a UIKeyboardWillShowNotification contains an Int with the value 7.
Now I need to pass this Int into UIView.setAnimationCurve(<here>). I tried to create the required UIViewAnimationCurve enum like this UIViewAnimationCurve(rawValue: 7). Because the raw value 7 is undocumented, the result is always nil.
It works fine this way in Objective-C. Any idea how to get this animation curve from the notification into a UIView animation using Swift?
Update:
As pointed out by Martin, this is no longer a problem since Xcode 6.3.
From the Xcode 6.3 Release Notes:
Imported NS_ENUM types with undocumented values, such as UIViewAnimationCurve, can now be converted from their raw integer values using the init(rawValue:) initializer without being reset to nil. Code that used unsafeBitCast as a workaround for this issue can be written to use the raw value initializer.
I think I figured it out, but I'm not sure if this is the way it's supposed to be done.
let animationCurve = unsafeBitCast(7, UIViewAnimationCurve.self)
UIView.setAnimationCurve(animationCurve)
Update: The solution contained in this question works as well.
var animationCurve = UIViewAnimationCurve.EaseInOut
NSNumber(integer: 7).getValue(&animationCurve)

Resources