liveplots.xmlrpcserver
Covered: 171 lines
Missed: 72 lines
Skipped 46 lines
Percent: 70 %

      1

    __author__="fccoelho@gmail.com"

      2

    __date__ ="$26/02/2009 10:44:29$"

      3

    __docformat__ = "restructuredtext en"

      4

      5

    import Gnuplot

      6

    import numpy

      7

    from SimpleXMLRPCServer import SimpleXMLRPCServer

      8

    #from twisted.web import xmlrpc, server

      9

    #from twisted.internet import reactor

     10

    from multiprocessing import Process

     11

    from threading import Thread, Lock

     12

    from Queue import Queue

     13

    import time

     14

     15

    Gnuplot.GnuplotOpts.prefer_inline_data = 1

     16

    Gnuplot.GnuplotOpts.prefer_fifo_data = 0

     17

     18

    __ports_used = []

     19

     20

    Q = Queue()

     21

    def worker():

     22

        while True:

     23

            item = Q.get()

     24

            item[0](*item[1])

     25

            Q.task_done()

     26

     27

     28

    def enqueue(f):

     29

        """Decorator that places the call on a queue"""

     30

        def queued(self,*args,**kw):

     31

            Q.put((f,(self,)+args))

     32

        queued.__doc__ = f.__doc__

     33

        queued.__name__ = f.__name__

     34

        return queued

     35

     36

    class RTplot():

     37

        '''

     38

        Real time plotting class based on Gnuplot

     39

        '''

     40

        def __init__(self, persist=0,debug=0,**kwargs):

     41

            self.gp = Gnuplot.Gnuplot(persist = persist, debug=debug)

     42

            self.plots = []

     43

            self.Queue = Q

     44

            self.persist = persist

     45

            self.hold = 0 if 'hold' not in kwargs else kwargs['hold']

     46

            t= Thread(target=worker,args=())

     47

            t.setDaemon(True)

     48

            t.start()

     49

     50

        def set_hold(self,on):

     51

            '''

     52

            Sets hold state of the plot.

     53

            takes 0 or 1 as argument

     54

            '''

     55

            self.hold = on

     56

     57

        def clearFig(self):

     58

            '''

     59

            Clears the figure.

     60

            '''

     61

            self.plots = []

     62

            return 0

     63

            #self.gp.reset()

     64

        def close_plot(self):

     65

            self.flush_queue()

     66

            if self.persist:

     67

                self.gp.close()

     68

            return 0

     69

     70

        def flush_queue(self):

     71

            self.Queue.join()

     72

            return 0

     73

     74

        @enqueue

     75

        def scatter(self,x,y,labels=[],title='',style='points', jitter=True, multiplot=0):

     76

            """

     77

            Makes scatter plots from numpy arrays.

     78

            if x and are multidimensional(lists of lists), multiple scatter plots will be generated, pairing rows.

     79

     80

            :Parameters:

     81

                -`x`: list of numbers or list of lists

     82

                -`y`: list of numbers or list of lists

     83

                -`labels`: list of strings (variable names)

     84

                -`title`: Title of the plot

     85

            """

     86

            assert len(x)==len(y)

     87

            if multiplot:

     88

                sq = numpy.sqrt(len(x))

     89

                ad = 1 if sq%1 >0.5 else 0

     90

                r= numpy.floor(sq);c=numpy.ceil(sq)+ad

     91

                if len(x) == 3:

     92

                    r=3;c=1

     93

                self.gp('set multiplot layout %s,%s title "%s"'%(r, c, title))

     94

            else:

     95

                self.gp('set title "%s"'%title)

     96

            if jitter:

     97

                jt = numpy.random.normal(1, 1e-4,1)[0]

     98

            else:

     99

                jt = 1

    100

            x = numpy.array(x)

    101

            y = numpy.array(y)

    102

    103

            if x.shape != y.shape:

    104

                raise ValueError("x, %s and y, %s arrays must have the same shape."%(x.shape,y.shape))

    105

            if labels:

    106

                if len(x.shape)==1:

    107

                    if len(labels) !=2:

    108

                        raise ValueError("Labels list should contain exactly 2 elements, but has %s"%len(labels))

    109

                else:

    110

                    if len(labels) != x.shape[0]:

    111

                        raise ValueError("labels list must have exactly %s items, but has %s."%(x.shape[0],len(labels)))

    112

    113

    114

            self.gp('set title "%s"'%title)

    115

            if not labels:

    116

                labels = ['s%s'%i for i in range(x.shape[0])]

    117

            if len(x.shape) > 1 and len(x.shape) <= 2:

    118

                i = 0

    119

                for n in range(x.shape[0]):

    120

                    self.plots.append(Gnuplot.PlotItems.Data(x[n]*jt,y[n]*jt,title=labels[i],with_=style))

    121

                    i += 1

    122

                if multiplot:

    123

                    [self.gp.plot(pl) for pl in self.plots]

    124

                    self.gp('unset multiplot')

    125

                else:

    126

                    self.gp.plot(*tuple(self.plots))

    127

            elif len(x.shape) >2:

    128

                    pass

    129

            else:

    130

                #print data

    131

                self.plots.append(Gnuplot.PlotItems.Data(x*jt,y*jt,title=labels[0],with_=style))

    132

                if multiplot:

    133

                    [self.gp.plot(pl) for pl in self.plots]

    134

                    self.gp('unset multiplot')

    135

                else:

    136

                    self.gp.plot(*tuple(self.plots))

    137

            if not self.hold:

    138

                self.plots = []

    139

            return 0

    140

    141

        @enqueue

    142

        def lines(self, data, x=[], labels=[],title='',style='lines', multiplot=0):

    143

            '''

    144

            Create a single/multiple line plot from a numpy array or record array.

    145

    146

            :Parameters:

    147

                - `data`: must be a list of lists.

    148

                - `x`: x values for the series: list

    149

                - `labels`: is a list of strings to serve as legend labels

    150

                - `style`: plot styles from gnuplot: lines, boxes, points, linespoints, etc.

    151

                - `multiplot`: Whether to make multiple subplots

    152

            '''

    153

            #self.gp('set style %s 1'%style)

    154

            if multiplot:

    155

                sq = numpy.sqrt(len(data))

    156

                ad = 1 if sq%1 >0.5 else 0

    157

                r= numpy.floor(sq);c=numpy.ceil(sq)+ad

    158

                if len(data) == 3:

    159

                    r=3;c=1

    160

                self.gp('set multiplot layout %s,%s title "%s"'%(r, c, title))

    161

            else:

    162

                self.gp('set title "%s"'%title)

    163

    164

            assert isinstance (data, list)

    165

            data = numpy.array(data)

    166

    167

            if len(data.shape) > 1 and len(data.shape) <= 2:

    168

                i = 0

    169

                for row in data:

    170

                    if  x== []:

    171

                        x = numpy.arange(len(row))

    172

                    if labels:

    173

                        self.plots.append(Gnuplot.PlotItems.Data(x, row,title=labels[i], with_=style))

    174

                    else:

    175

                        self.plots.append(Gnuplot.PlotItems.Data(x, row, with_=style))

    176

                    i += 1

    177

                if multiplot:

    178

                    [self.gp.plot(pl) for pl in self.plots]

    179

                    self.gp('unset multiplot')

    180

                else:

    181

                    self.gp.plot(*tuple(self.plots))

    182

            elif len(data.shape) >2:

    183

                    pass

    184

            else:

    185

    #            print data

    186

                if x == [] :

    187

                    x = numpy.arange(len(data))

    188

                self.plots.append(Gnuplot.PlotItems.Data(x,data,title=labels[0],with_=style))

    189

                self.gp.plot(*tuple(self.plots))

    190

                if not multiplot:

    191

                    self.gp('unset multiplot')

    192

            if not self.hold:

    193

                self.plots = []

    194

            return 0

    195

    196

    197

        #~ def histogram(self,data,labels=[],title='',multiplot=0):

    198

            #~ self.Queue.put((self._histogram,(data,labels,title,multiplot)))

    199

        @enqueue

    200

        def histogram(self,data,labels=[],title='',multiplot=0,**kwargs):

    201

            '''

    202

            Create a single/multiple Histogram plot from a numpy array or record array.

    203

    204

            :Parameters:

    205

                - `data`: must be a list of lists.

    206

                - `labels`: is a list of strings to serve as legend labels

    207

                - `multiplot`: Whether to make multiple subplots

    208

            '''

    209

            if multiplot:

    210

                sq = numpy.sqrt(len(data))

    211

                ad = 1 if sq%1 >0.5 else 0

    212

                r= numpy.floor(sq);c=numpy.ceil(sq)+ad

    213

                if len(data) == 3:

    214

                    r=3;c=1

    215

                self.gp('set multiplot layout %s,%s title "%s"'%(r, c, title))

    216

            else:

    217

                self.gp('set title "%s"'%title)

    218

            self.gp('set style data boxes')

    219

    220

            assert isinstance (data, list)

    221

            data = numpy.array(data)

    222

            if not labels:

    223

                labels = ['Var_%s'%i for i in range(data.shape[0])]

    224

            if len(data.shape) == 2:

    225

                for n,row in enumerate(data):

    226

                    m,bins = numpy.histogram(row,normed=True,bins=50)

    227

                    d = zip(bins[:-1],m)

    228

                    self.plots.append(Gnuplot.PlotItems.Data(d,title=labels[n]))

    229

    230

                if multiplot:

    231

                    [self.gp.plot(pl) for pl in self.plots]

    232

                    self.gp('unset multiplot')

    233

                else:

    234

                    self.gp.plot(*tuple(self.plots))

    235

    236

    237

            elif len(data.shape) >2:

    238

                pass

    239

            elif len(data.shape) == 1:

    240

                m,bins = numpy.histogram(data,normed=True,bins=50)

    241

                d = zip(bins[:-1],m)

    242

                self.plots.append(Gnuplot.PlotItems.Data(d,title=labels[0]))

    243

                self.gp.plot(*tuple(self.plots))

    244

                if multiplot:

    245

                    self.gp('unset multiplot')

    246

    247

            if not self.hold:

    248

                self.plots = []

    249

            return 0

    250

    251

    252

    253

    def _start_server(server, persist,hold):

    254

        server.register_instance(RTplot(persist=persist, hold=hold))

    255

        server.register_introspection_functions()

    256

        server.serve_forever()

    257

    258

    259

    260

    def rpc_plot(port=0, persist=0, hold=0):

    261

        """

    262

        XML RPC plot server factory function

    263

        returns port if server successfully started or 0

    264

        """

    265

        if port == 0:

    266

            port = 10001

    267

        while 1:

    268

            if port in __ports_used:

    269

                port += 1

    270

                continue

    271

            try:

    272

                server = SimpleXMLRPCServer(("localhost", port),logRequests=False, allow_none=True)

    273

                server.register_introspection_functions()

    274

                p = Process(target=_start_server, args=(server, persist, hold))

    275

    276

                #p = Process(target=_start_twisted_server, args=(port, persist))

    277

                p.daemon = True

    278

                p.start()

    279

                break

    280

            except:

    281

                port += 1

    282

        port = port

    283

        __ports_used.append(port)

    284

        return port

    285

    286

    287

    if __name__ == "__main__":

    288

        pass

    289