From b6300a86fe135fb94f1dbb58cbfda350c66357d2 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Sun, 8 Jan 2012 06:12:47 +0000 Subject: [PATCH] support bit vects <-> byte strings --- Code/DataStructs/BitOps.cpp | 51 ++++++++++++++++++++--- Code/DataStructs/BitOps.h | 22 ++++++++++ Code/DataStructs/Wrap/testBV.py | 10 +++++ Code/DataStructs/Wrap/wrap_BitOps.cpp | 8 +++- Code/DataStructs/Wrap/wrap_ExplicitBV.cpp | 2 +- Code/DataStructs/Wrap/wrap_SparseBV.cpp | 2 +- Code/DataStructs/Wrap/wrap_Utils.cpp | 9 ++++ Code/DataStructs/testDatastructs.cpp | 51 +++++++++++++++++++++++ 8 files changed, 147 insertions(+), 8 deletions(-) diff --git a/Code/DataStructs/BitOps.cpp b/Code/DataStructs/BitOps.cpp index 02c39f89b..2d511ac14 100644 --- a/Code/DataStructs/BitOps.cpp +++ b/Code/DataStructs/BitOps.cpp @@ -654,23 +654,48 @@ const char bin2Hex[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d', template std::string BitVectToFPSText(const T1& bv1){ - std::stringstream res; + std::string res(bv1.getNumBits()/4 + (bv1.getNumBits()%4?1:0),0); unsigned char c=0; + unsigned int byte=0; for(unsigned int i=0;i>4)%16]<>4)%16]; + res[byte++]=bin2Hex[c%16]; c=0; } } if(bv1.getNumBits()%8){ - res<>4)%16]<>4)%16]; + res[byte++]=bin2Hex[c%16]; } - return res.str(); + return res; } +template +std::string +BitVectToBinaryText(const T1& bv1){ + std::string res(bv1.getNumBits()/8 + (bv1.getNumBits()%8?1:0),0); + unsigned char c=0; + unsigned int byte=0; + for(unsigned int i=0;i void UpdateBitVectFromFPSText(T1& bv1,const std::string &fps){ @@ -693,6 +718,18 @@ UpdateBitVectFromFPSText(T1& bv1,const std::string &fps){ } } +template +void +UpdateBitVectFromBinaryText(T1& bv1,const std::string &fps){ + PRECONDITION(fps.length()*8<=bv1.getNumBits(),"bad FPS length"); + PRECONDITION(fps.length()%2==0,"bad FPS length"); + for(unsigned int i=0;i std::string BitVectToFPSText(const T1& bv1); +//! returns a binary string representation of a bit vector (an array of bytes) +/*! + \param bv1 the vector to use + + \return an std::string + + */ +template +std::string +BitVectToBinaryText(const T1& bv1); + //! updates a bit vector from Andrew Dalke's FPS format /*! \param bv1 the vector to use @@ -294,6 +305,17 @@ template void UpdateBitVectFromFPSText(T1& bv1,const std::string &fps); +//! updates a bit vector from a binary string representation of a bit vector (an array of bytes) +/*! + \param bv1 the vector to use + \param fps the binary string + + + */ +template +void +UpdateBitVectFromBinaryText(T1& bv1,const std::string &fps); + #endif diff --git a/Code/DataStructs/Wrap/testBV.py b/Code/DataStructs/Wrap/testBV.py index 1ef71d5a8..23e2c2423 100755 --- a/Code/DataStructs/Wrap/testBV.py +++ b/Code/DataStructs/Wrap/testBV.py @@ -153,6 +153,16 @@ class TestCase(unittest.TestCase): self.failUnlessEqual(DataStructs.BitVectToFPSText(bv),"03008280") bv2 = DataStructs.CreateFromFPSText("03008280") self.failUnlessEqual(bv,bv2) + def test8BinText(self): + bv = DataStructs.ExplicitBitVect(32) + bv.SetBit(0) + bv.SetBit(1) + bv.SetBit(17) + bv.SetBit(23) + bv.SetBit(31) + + bv2 = DataStructs.CreateFromBinaryText(DataStructs.BitVectToBinaryText(bv)) + self.failUnlessEqual(bv,bv2) if __name__ == '__main__': unittest.main() diff --git a/Code/DataStructs/Wrap/wrap_BitOps.cpp b/Code/DataStructs/Wrap/wrap_BitOps.cpp index 236f12bac..994276027 100644 --- a/Code/DataStructs/Wrap/wrap_BitOps.cpp +++ b/Code/DataStructs/Wrap/wrap_BitOps.cpp @@ -1,6 +1,6 @@ // $Id$ // -// Copyright (C) 2003-2008 greg Landrum and Rational Discovery LLC +// Copyright (C) 2003-2012 greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -352,6 +352,12 @@ struct BitOps_wrapper { (std::string (*)(const EBV&))BitVectToFPSText, "Returns an FPS string representing the bit vector." ); + python::def("BitVectToBinaryText", + (std::string (*)(const SBV&))BitVectToBinaryText); + python::def("BitVectToBinaryText", + (std::string (*)(const EBV&))BitVectToBinaryText, + "Returns a binary string (byte array) representing the bit vector." + ); } }; diff --git a/Code/DataStructs/Wrap/wrap_ExplicitBV.cpp b/Code/DataStructs/Wrap/wrap_ExplicitBV.cpp index 8a942c5c5..f9e14ebc4 100644 --- a/Code/DataStructs/Wrap/wrap_ExplicitBV.cpp +++ b/Code/DataStructs/Wrap/wrap_ExplicitBV.cpp @@ -73,7 +73,7 @@ struct EBV_wrapper { (IntVect (*)(const EBV&))GetOnBits, "Returns a tuple containing IDs of the on bits.\n") .def("ToBinary",&EBV::toString, - "Returns a binary string representation of the vector.\n") + "Returns an internal binary representation of the vector.\n") .def("FromBase64", (void (*)(EBV &,const std::string &))InitFromBase64, "Initializes the vector from a base64 encoded binary string.\n") diff --git a/Code/DataStructs/Wrap/wrap_SparseBV.cpp b/Code/DataStructs/Wrap/wrap_SparseBV.cpp index 6682dcd84..3efc58503 100644 --- a/Code/DataStructs/Wrap/wrap_SparseBV.cpp +++ b/Code/DataStructs/Wrap/wrap_SparseBV.cpp @@ -74,7 +74,7 @@ struct SBV_wrapper { (IntVect (*)(const SBV&))GetOnBits, "Returns a tuple containing IDs of the on bits.\n") .def("ToBinary",&SBV::toString, - "Returns a binary string representation of the vector.\n") + "Returns an internal binary representation of the vector.\n") .def("FromBase64", (void (*)(SBV &,const std::string &))InitFromBase64, "Initializes the vector from a base64 encoded binary string.\n") diff --git a/Code/DataStructs/Wrap/wrap_Utils.cpp b/Code/DataStructs/Wrap/wrap_Utils.cpp index 5279c4b6f..3e042a144 100644 --- a/Code/DataStructs/Wrap/wrap_Utils.cpp +++ b/Code/DataStructs/Wrap/wrap_Utils.cpp @@ -26,6 +26,12 @@ ExplicitBitVect *createFromFPSText(const std::string &fps){ return res; } +ExplicitBitVect *createFromBinaryText(const std::string &fps){ + ExplicitBitVect *res=new ExplicitBitVect(fps.length()*8); + UpdateBitVectFromBinaryText(*res,fps); + return res; +} + struct Utils_wrapper { static void wrap(){ @@ -38,6 +44,9 @@ struct Utils_wrapper { python::def("CreateFromFPSText",createFromFPSText, python::return_value_policy(), "Creates an ExplicitBitVect from an FPS string."); + python::def("CreateFromBinaryText",createFromBinaryText, + python::return_value_policy(), + "Creates an ExplicitBitVect from a binary string (byte array)."); python::def("InitFromDaylightString", (void (*)(SparseBitVect &,std::string))FromDaylightString); diff --git a/Code/DataStructs/testDatastructs.cpp b/Code/DataStructs/testDatastructs.cpp index 2d5f508ec..1c081c853 100644 --- a/Code/DataStructs/testDatastructs.cpp +++ b/Code/DataStructs/testDatastructs.cpp @@ -1039,6 +1039,54 @@ void test9BitVectFPS() { } } +void test10BitVectBinaryText() { + { + ExplicitBitVect bv(32); + std::string fps; + + fps = BitVectToBinaryText(bv); + TEST_ASSERT(fps.size()==4); + for(unsigned int i=0;i