Mercurial > repos > yufei-luo > s_mart
comparison SMART/Java/Python/misc/RPlotter.py @ 6:769e306b7933
Change the repository level.
| author | yufei-luo |
|---|---|
| date | Fri, 18 Jan 2013 04:54:14 -0500 |
| parents | |
| children | 94ab73e8a190 |
comparison
equal
deleted
inserted
replaced
| 5:ea3082881bf8 | 6:769e306b7933 |
|---|---|
| 1 # | |
| 2 # Copyright INRA-URGI 2009-2010 | |
| 3 # | |
| 4 # This software is governed by the CeCILL license under French law and | |
| 5 # abiding by the rules of distribution of free software. You can use, | |
| 6 # modify and/ or redistribute the software under the terms of the CeCILL | |
| 7 # license as circulated by CEA, CNRS and INRIA at the following URL | |
| 8 # "http://www.cecill.info". | |
| 9 # | |
| 10 # As a counterpart to the access to the source code and rights to copy, | |
| 11 # modify and redistribute granted by the license, users are provided only | |
| 12 # with a limited warranty and the software's author, the holder of the | |
| 13 # economic rights, and the successive licensors have only limited | |
| 14 # liability. | |
| 15 # | |
| 16 # In this respect, the user's attention is drawn to the risks associated | |
| 17 # with loading, using, modifying and/or developing or reproducing the | |
| 18 # software by the user in light of its specific status of free software, | |
| 19 # that may mean that it is complicated to manipulate, and that also | |
| 20 # therefore means that it is reserved for developers and experienced | |
| 21 # professionals having in-depth computer knowledge. Users are therefore | |
| 22 # encouraged to load and test the software's suitability as regards their | |
| 23 # requirements in conditions enabling the security of their systems and/or | |
| 24 # data to be ensured and, more generally, to use and operate it in the | |
| 25 # same conditions as regards security. | |
| 26 # | |
| 27 # The fact that you are presently reading this means that you have had | |
| 28 # knowledge of the CeCILL license and that you accept its terms. | |
| 29 # | |
| 30 | |
| 31 import os | |
| 32 import subprocess | |
| 33 import random | |
| 34 import math | |
| 35 | |
| 36 minPositiveValue = 10e-6 | |
| 37 | |
| 38 """ | |
| 39 Plot simple curves in R | |
| 40 """ | |
| 41 | |
| 42 class RPlotter(object): | |
| 43 """ | |
| 44 Plot some curves | |
| 45 @ivar nbColors: number of different colors | |
| 46 @type nbColors: int | |
| 47 @ivar fileName: name of the file | |
| 48 @type fileName: string | |
| 49 @ivar lines: lines to be plotted | |
| 50 @type lines: array of dict | |
| 51 @ivar names: name of the lines | |
| 52 @type names: array of strings | |
| 53 @ivar colors: color of the lines | |
| 54 @type colors: array of strings | |
| 55 @ivar types: type of the lines (plain or dashed) | |
| 56 @type types: array of strings | |
| 57 @ivar format: format of the picture | |
| 58 @type format: string | |
| 59 @ivar lineWidth: width of the line in a xy-plot | |
| 60 @type lineWidth: int | |
| 61 @ivar xMin: minimum value taken on the x-axis | |
| 62 @type xMin: int | |
| 63 @ivar xMax: maximum value taken on the x-axis | |
| 64 @type xMax: int | |
| 65 @ivar yMin: minimum value taken on the y-axis | |
| 66 @type yMin: int | |
| 67 @ivar yMax: maximum value taken on the y-axis | |
| 68 @type yMax: int | |
| 69 @ivar minimumX: minimum value allowed on the x-axis | |
| 70 @type minimumX: int | |
| 71 @ivar maximumX: maximum value allowed on the x-axis | |
| 72 @type maximumX: int | |
| 73 @ivar minimumY: minimum value allowed on the y-axis | |
| 74 @type minimumY: int | |
| 75 @ivar maximumY: maximum value allowed on the y-axis | |
| 76 @type maximumY: int | |
| 77 @ivar leftMargin: add some margin in the left part of the plot | |
| 78 @type leftMargin: float | |
| 79 @ivar rightMargin: add some margin in the right part of the plot | |
| 80 @type rightMargin: float | |
| 81 @ivar downMargin: add some margin at the top of the plot | |
| 82 @type downMargin: float | |
| 83 @ivar upMargin: add some margin at the bottom of the plot | |
| 84 @type upMargin: float | |
| 85 @ivar logX: use log scale on the x-axis | |
| 86 @type logX: boolean | |
| 87 @ivar logY: use log scale on the y-axis | |
| 88 @type logY: boolean | |
| 89 @ivar logZ: use log scale on the z-axis (the color) | |
| 90 @type logZ: boolean | |
| 91 @ival fill: if a value is not given, fill it with given value | |
| 92 @type fill: int | |
| 93 @ival bucket: cluster the data into buckets of given size | |
| 94 @type bucket: int | |
| 95 @ival seed: a random number | |
| 96 @type seed: int | |
| 97 @ival regression: plot a linear regression | |
| 98 @type regression: boolean | |
| 99 @ival legend: set the legend | |
| 100 @type legend: boolean | |
| 101 @ival legendBySide: set the legend outside of the plot | |
| 102 @type legendBySde: boolean | |
| 103 @ival xLabel: label for the x-axis | |
| 104 @type xLabel: string | |
| 105 @ival yLabel: label for the y-axis | |
| 106 @type yLabel: string | |
| 107 @ival title: title of the plot | |
| 108 @type title: string | |
| 109 @ival barplot: use a barplot representation instead | |
| 110 @type barplot: boolean | |
| 111 @ival points: use a point cloud instead | |
| 112 @type points: boolean | |
| 113 @ival heatPoints: use a colored point cloud instead | |
| 114 @type heatPoints: boolean | |
| 115 @ival axesLabels: change the names of the axes | |
| 116 @type axesLabels: vector of 2 int to string dict | |
| 117 @ival rotateAxesLabels: rotate the axes labels | |
| 118 @type rotateAxesLabels: dict of 2 boolean | |
| 119 @ival verbosity: verbosity of the class | |
| 120 @type verbosity: int | |
| 121 @ival keep: keep temporary files | |
| 122 @type keep: boolean | |
| 123 """ | |
| 124 | |
| 125 def __init__(self, fileName, verbosity = 0, keep = False): | |
| 126 """ | |
| 127 Constructor | |
| 128 @param fileName: name of the file to produce | |
| 129 @type fileName: string | |
| 130 @param verbosity: verbosity | |
| 131 @type verbosity: int | |
| 132 @param keep: keep temporary files | |
| 133 @type keep: boolean | |
| 134 """ | |
| 135 self.nbColors = 9 | |
| 136 self.fileName = fileName | |
| 137 self.verbosity = verbosity | |
| 138 self.keep = keep | |
| 139 self.format = "png" | |
| 140 self.fill = None | |
| 141 self.bucket = None | |
| 142 self.lines = [] | |
| 143 self.names = [] | |
| 144 self.colors = [] | |
| 145 self.types = [] | |
| 146 self.lineWidth = 1 | |
| 147 self.xMin = None | |
| 148 self.xMax = None | |
| 149 self.yMin = None | |
| 150 self.yMax = None | |
| 151 self.seed = random.randint(0, 10000) | |
| 152 self.minimumX = None | |
| 153 self.maximumX = None | |
| 154 self.minimumY = None | |
| 155 self.maximumY = None | |
| 156 self.leftMargin = 0 | |
| 157 self.rightMargin = 0 | |
| 158 self.topMargin = 0 | |
| 159 self.bottomMargin = 0 | |
| 160 self.logX = False | |
| 161 self.logY = False | |
| 162 self.logZ = False | |
| 163 self.regression = False | |
| 164 self.width = 1000 | |
| 165 self.height = 500 | |
| 166 self.legend = False | |
| 167 self.legendBySide = False | |
| 168 self.xLabel = "" | |
| 169 self.yLabel = "" | |
| 170 self.title = None | |
| 171 self.points = False | |
| 172 self.heatPoints = False | |
| 173 self.barplot = False | |
| 174 self.axesLabels = {1: None, 2: None} | |
| 175 self.rotateAxesLabels = {1: False, 2: False} | |
| 176 self.linesToAddBox = "" | |
| 177 | |
| 178 def __del__(self): | |
| 179 """ | |
| 180 Destructor | |
| 181 Remove tmp files | |
| 182 """ | |
| 183 if not self.keep: | |
| 184 scriptFileName = "tmpScript-%d.R" % (self.seed) | |
| 185 if os.path.exists(scriptFileName): | |
| 186 os.remove(scriptFileName) | |
| 187 outputFileName = "%sout" % (scriptFileName) | |
| 188 if os.path.exists(outputFileName): | |
| 189 os.remove(outputFileName) | |
| 190 nbLines = len(self.lines) + (1 if self.heatPoints else 0) | |
| 191 for i in range(nbLines): | |
| 192 if os.path.exists("tmpData-%d-%d.dat" % (self.seed, i)): | |
| 193 os.remove("tmpData-%d-%d.dat" % (self.seed, i)) | |
| 194 | |
| 195 | |
| 196 def setMinimumX(self, xMin): | |
| 197 """ | |
| 198 Set the minimum value on the x-axis | |
| 199 @param xMin:minimum value on the x-axis | |
| 200 @type xMin: int | |
| 201 """ | |
| 202 self.minimumX = xMin | |
| 203 | |
| 204 | |
| 205 def setMaximumX(self, xMax): | |
| 206 """ | |
| 207 Set the maximum value on the x-axis | |
| 208 @param xMax: maximum value on the x-axis | |
| 209 @type xMax: int | |
| 210 """ | |
| 211 self.maximumX = xMax | |
| 212 | |
| 213 | |
| 214 def setMinimumY(self, yMin): | |
| 215 """ | |
| 216 Set the minimum value on the y-axis | |
| 217 @param yMin: minimum value on the y-axis | |
| 218 @type yMin: int | |
| 219 """ | |
| 220 self.minimumY = yMin | |
| 221 | |
| 222 | |
| 223 def setMaximumY(self, yMax): | |
| 224 """ | |
| 225 Set the maximum value on the y-axis | |
| 226 @param yMax: maximum value on the y-axis | |
| 227 @type xmax: int | |
| 228 """ | |
| 229 self.maximumY = yMax | |
| 230 | |
| 231 | |
| 232 def setFill(self, fill): | |
| 233 """ | |
| 234 Fill empty data with given value | |
| 235 @param fill: the value to fill with | |
| 236 @type fill: int | |
| 237 """ | |
| 238 self.fill = fill | |
| 239 | |
| 240 | |
| 241 def setBuckets(self, bucket): | |
| 242 """ | |
| 243 Cluster the data into buckets of given size | |
| 244 @param bucket: the size of the buckets | |
| 245 @type bucket: int | |
| 246 """ | |
| 247 self.bucket = bucket | |
| 248 | |
| 249 | |
| 250 def setRegression(self, regression): | |
| 251 """ | |
| 252 Plot a linear regression line | |
| 253 @param regression: whether to plot the regression | |
| 254 @type regression: bool | |
| 255 """ | |
| 256 self.regression = regression | |
| 257 | |
| 258 | |
| 259 def setFormat(self, format): | |
| 260 """ | |
| 261 Set the format of the picture | |
| 262 @param format: the format | |
| 263 @type format: string | |
| 264 """ | |
| 265 if format not in ("png", "pdf", "jpeg", "bmp", "tiff"): | |
| 266 raise Exception("Format '%s' is not supported by RPlotter" % (format)) | |
| 267 self.format = format | |
| 268 | |
| 269 | |
| 270 def setWidth(self, width): | |
| 271 """ | |
| 272 Set the dimensions of the image produced | |
| 273 @param width: width of the image | |
| 274 @type width: int | |
| 275 """ | |
| 276 self.width = width | |
| 277 | |
| 278 | |
| 279 def setHeight(self, height): | |
| 280 """ | |
| 281 Set the dimensions of the image produced | |
| 282 @param height: heigth of the image | |
| 283 @type height: int | |
| 284 """ | |
| 285 self.height = height | |
| 286 | |
| 287 | |
| 288 def setImageSize(self, width, height): | |
| 289 """ | |
| 290 Set the dimensions of the image produced | |
| 291 @param width: width of the image | |
| 292 @type width: int | |
| 293 @param height: heigth of the image | |
| 294 @type height: int | |
| 295 """ | |
| 296 self.setWidth(width) | |
| 297 self.setHeight(height) | |
| 298 | |
| 299 | |
| 300 def setLegend(self, legend, bySide = False): | |
| 301 """ | |
| 302 Print a legend or not | |
| 303 @param legend: print a legend | |
| 304 @type legend: boolean | |
| 305 @param bySide: put the legend outside of the plot | |
| 306 @type bySide: boolean | |
| 307 """ | |
| 308 self.legend = legend | |
| 309 self.legendBySide = bySide | |
| 310 | |
| 311 | |
| 312 def setXLabel(self, label): | |
| 313 """ | |
| 314 Print a label for the x-axis | |
| 315 @param label: the label | |
| 316 @type label: string | |
| 317 """ | |
| 318 self.xLabel = label | |
| 319 if self.xLabel != None: | |
| 320 self.xLabel = self.xLabel.replace("_", " ") | |
| 321 | |
| 322 | |
| 323 def setYLabel(self, label): | |
| 324 """ | |
| 325 Print a label for the y-axis | |
| 326 @param label: the label | |
| 327 @type label: string | |
| 328 """ | |
| 329 self.yLabel = label | |
| 330 if self.yLabel != None: | |
| 331 self.yLabel = self.yLabel.replace("_", " ") | |
| 332 | |
| 333 | |
| 334 def addLeftMargin(self, margin): | |
| 335 """ | |
| 336 Increase the size of the space on the left part of the graph | |
| 337 @param margin: the space added | |
| 338 @type margin: float | |
| 339 """ | |
| 340 self.leftMargin = margin | |
| 341 | |
| 342 | |
| 343 def addRightMargin(self, margin): | |
| 344 """ | |
| 345 Increase the size of the space on the right part of the graph | |
| 346 @param margin: the space added | |
| 347 @type margin: float | |
| 348 """ | |
| 349 self.rightMargin = margin | |
| 350 | |
| 351 | |
| 352 def addTopMargin(self, margin): | |
| 353 """ | |
| 354 Increase the size of the space at the top of the graph | |
| 355 TopMargin is a percentage if 0 < TopMargin < 1. | |
| 356 TopMargin is a value if TopMargin >= 1. | |
| 357 @param margin: the space added | |
| 358 @type margin: float | |
| 359 """ | |
| 360 self.topMargin = margin | |
| 361 | |
| 362 | |
| 363 def addBottomMargin(self, margin): | |
| 364 """ | |
| 365 Increase the size of the space at the bottom of the graph | |
| 366 @param margin: the space added | |
| 367 @type margin: float | |
| 368 """ | |
| 369 self.bottomMargin = margin | |
| 370 | |
| 371 | |
| 372 def getNewYMaxWithTopMargin(self): | |
| 373 """ | |
| 374 Return new xMin coordinate with left margin | |
| 375 @param xMin: coordinate | |
| 376 @type xMin: float | |
| 377 """ | |
| 378 yMax = self.yMax | |
| 379 if 0 < self.topMargin and self.topMargin < 1: | |
| 380 topMargin = self.topMargin * self.yMax | |
| 381 yMax = self.yMax + topMargin | |
| 382 elif self.topMargin >= 1: | |
| 383 yMax = self.yMax + self.topMargin | |
| 384 return yMax | |
| 385 | |
| 386 | |
| 387 def setTitle(self, title): | |
| 388 """ | |
| 389 Print a title for graph | |
| 390 @param title: a title | |
| 391 @type title: string | |
| 392 """ | |
| 393 self.title = title | |
| 394 if self.title != None: | |
| 395 self.title = self.title.replace("_", " ") | |
| 396 | |
| 397 | |
| 398 def setAxisLabel(self, i, labels): | |
| 399 """ | |
| 400 Change x- or y-labels | |
| 401 @param i: x for x-label, y for y-label | |
| 402 @type i: string | |
| 403 @param labels: new labels | |
| 404 @type labels: int to string dict | |
| 405 """ | |
| 406 i = i.lower() | |
| 407 if i not in ("x", "y"): | |
| 408 raise Exception("Label name '" + i + "' should by 'x' or 'y' while changing axis labels.") | |
| 409 self.axesLabels[{"x": 1, "y": 2}[i]] = labels | |
| 410 | |
| 411 | |
| 412 def rotateAxisLabel(self, i, b = True): | |
| 413 """ | |
| 414 Rotate x- or y-labels | |
| 415 @param i: x for x-label, y for y-label | |
| 416 @type i: string | |
| 417 @param b: whether the labels should be rotated | |
| 418 @type b: boolean | |
| 419 """ | |
| 420 i = i.lower() | |
| 421 if i not in ("x", "y"): | |
| 422 raise Exception("Label name '" + i + "' should by 'x' or 'y' while rotating axis labels.") | |
| 423 self.rotateAxesLabels[{"x": 1, "y": 2}[i]] = b | |
| 424 | |
| 425 def setLineWidth(self, width): | |
| 426 """ | |
| 427 Set the line width in a xy-plot | |
| 428 @param width: the new line width | |
| 429 @type width: int | |
| 430 """ | |
| 431 self.lineWidth = width | |
| 432 | |
| 433 def setLog(self, log): | |
| 434 """ | |
| 435 Use log-scale for axes | |
| 436 @param log: use log scale | |
| 437 @type log: boolean | |
| 438 """ | |
| 439 self.logX = ("x" in log) | |
| 440 self.logY = ("y" in log) | |
| 441 self.logZ = ("z" in log) | |
| 442 | |
| 443 | |
| 444 def setBarplot(self, barplot): | |
| 445 """ | |
| 446 Use barplot representation instead | |
| 447 @param barplot: barplot representation | |
| 448 @type barplot: boolean | |
| 449 """ | |
| 450 self.barplot = barplot | |
| 451 | |
| 452 | |
| 453 def setPoints(self, points): | |
| 454 """ | |
| 455 Use points cloud representation instead | |
| 456 @param points: points cloud representation | |
| 457 @type points: boolean | |
| 458 """ | |
| 459 self.points = points | |
| 460 | |
| 461 | |
| 462 def setHeatPoints(self, heatPoints): | |
| 463 """ | |
| 464 Use points cloud representation with color representing another variable instead | |
| 465 @param points: colored points cloud representation | |
| 466 @type points: boolean | |
| 467 """ | |
| 468 self.heatPoints = heatPoints | |
| 469 | |
| 470 | |
| 471 def addBox(self, lXCoordList, minY, maxY): | |
| 472 for lXCoord in lXCoordList: | |
| 473 self.linesToAddBox += "rect(%s,%s,%s,%s,density=50, col='grey',border='transparent')\n" % (lXCoord[0], minY, lXCoord[1], maxY) | |
| 474 | |
| 475 def addLine(self, line, name = "", color = None): | |
| 476 """ | |
| 477 Add a line | |
| 478 @param line: a line to plot | |
| 479 @type line: dict | |
| 480 """ | |
| 481 # prepare data | |
| 482 plot = [] | |
| 483 if self.points or self.heatPoints: | |
| 484 values = line.values() | |
| 485 elif self.fill == None: | |
| 486 values = sorted(line.keys()) | |
| 487 else: | |
| 488 values = range(min(line.keys()), max(line.keys()) + 1) | |
| 489 | |
| 490 for element in values: | |
| 491 if self.points or self.heatPoints: | |
| 492 x = element[0] | |
| 493 y = element[1] | |
| 494 else: | |
| 495 x = element | |
| 496 if x not in line: | |
| 497 y = self.fill | |
| 498 else: | |
| 499 y = line[x] | |
| 500 | |
| 501 if self.minimumX != None and x < self.minimumX: | |
| 502 continue | |
| 503 if self.maximumX != None and x > self.maximumX: | |
| 504 continue | |
| 505 | |
| 506 if x == None: | |
| 507 raise Exception("Problem! x is None. Aborting...") | |
| 508 if y == None: | |
| 509 raise Exception("Problem! y is None. Aborting...") | |
| 510 if x == 0 and self.logX: | |
| 511 x = minPositiveValue | |
| 512 if y == 0 and self.logY: | |
| 513 y = minPositiveValue | |
| 514 if self.xMin == None: | |
| 515 if not self.logX or x != 0: | |
| 516 self.xMin = x | |
| 517 else: | |
| 518 if not self.logX or x != 0: | |
| 519 self.xMin = min(self.xMin, x) | |
| 520 if self.xMax == None: | |
| 521 self.xMax = x | |
| 522 else: | |
| 523 self.xMax = max(self.xMax, x) | |
| 524 if self.yMin == None: | |
| 525 if not self.logY or y != 0: | |
| 526 self.yMin = y | |
| 527 else: | |
| 528 if not self.logY or y != 0: | |
| 529 if y != "NA": | |
| 530 self.yMin = min(self.yMin, y) | |
| 531 if self.yMax == None: | |
| 532 self.yMax = y | |
| 533 else: | |
| 534 if y != "NA": | |
| 535 self.yMax = max(self.yMax, y) | |
| 536 | |
| 537 plot.append((x, y)) | |
| 538 | |
| 539 # cluster the data into buckets | |
| 540 if self.bucket != None: | |
| 541 buckets = dict([((int(value) / int(self.bucket)) * self.bucket, 0) for value in xrange(min(line.keys()), max(line.keys())+1)]) | |
| 542 for distance, nb in line.iteritems(): | |
| 543 buckets[(int(distance) / int(self.bucket)) * self.bucket] += nb | |
| 544 self.yMax = max(buckets.values()) | |
| 545 plot = [] | |
| 546 for x, y in buckets.iteritems(): | |
| 547 plot.append((x, y)) | |
| 548 | |
| 549 # write file | |
| 550 dataFileName = "tmpData-%d-%d.dat" % (self.seed, len(self.lines)) | |
| 551 dataHandle = open(dataFileName, "w") | |
| 552 if not self.heatPoints: | |
| 553 plot.sort() | |
| 554 for (x, y) in plot: | |
| 555 if y != "NA": | |
| 556 dataHandle.write("%f\t%f\n" % (x, y)) | |
| 557 else: | |
| 558 dataHandle.write("%f\t%s\n" % (x, y)) | |
| 559 dataHandle.close() | |
| 560 | |
| 561 self.lines.append(line) | |
| 562 self.names.append(name) | |
| 563 | |
| 564 if color == None: | |
| 565 colorNumber = len(self.colors) % (self.nbColors - 1) + 1 | |
| 566 type = "solid" | |
| 567 if len(self.colors) >= self.nbColors: | |
| 568 type = "dashed" | |
| 569 color = "colorPanel[%d]" % (colorNumber) | |
| 570 else: | |
| 571 color = "\"%s\"" % (color) | |
| 572 type = "solid" | |
| 573 self.colors.append(color) | |
| 574 self.types.append(type) | |
| 575 | |
| 576 | |
| 577 def addHeatLine(self, line, name = "", color = None): | |
| 578 """ | |
| 579 Add the heat line | |
| 580 @param line: the line which gives the color of the points | |
| 581 @type line: dict | |
| 582 """ | |
| 583 if not self.heatPoints: | |
| 584 raise Exception("Error! Trying to add a heat point whereas not mentioned to earlier! Aborting.") | |
| 585 | |
| 586 dataFileName = "tmpData-%d-%d.dat" % (self.seed, len(self.lines)) | |
| 587 dataHandle = open(dataFileName, "w") | |
| 588 | |
| 589 minimumHeat = min(line.values()) | |
| 590 maximumHeat = max(line.values()) | |
| 591 minLogValue = 0.00001 | |
| 592 log = self.logZ | |
| 593 | |
| 594 if log: | |
| 595 if minimumHeat == 0: | |
| 596 for element in line: | |
| 597 line[element] += minLogValue | |
| 598 minimumHeat += minLogValue | |
| 599 maximumHeat += minLogValue | |
| 600 minimumHeat = math.log10(minimumHeat) | |
| 601 maximumHeat = math.log10(maximumHeat) | |
| 602 | |
| 603 coeff = 255.0 / (maximumHeat - minimumHeat) | |
| 604 | |
| 605 for element in line: | |
| 606 value = line[element] | |
| 607 if log: | |
| 608 value = math.log10(max(minLogValue, value)) | |
| 609 dataHandle.write("\"#%02X%02X00\"\n" % (int((value - minimumHeat) * coeff), 255 - int((value - minimumHeat) * coeff))) | |
| 610 | |
| 611 dataHandle.close() | |
| 612 self.names.append(name) | |
| 613 if color == None: | |
| 614 colorNumber = len(self.colors) % (self.nbColors - 1) + 1 | |
| 615 type = "solid" | |
| 616 if len(self.colors) >= self.nbColors: | |
| 617 type = "dashed" | |
| 618 color = "colorPanel[%d]" % (colorNumber) | |
| 619 else: | |
| 620 color = "\"%s\"" % (color) | |
| 621 type = "solid" | |
| 622 self.colors.append(color) | |
| 623 self.types.append(type) | |
| 624 | |
| 625 | |
| 626 def getScript(self): | |
| 627 """ | |
| 628 Write (unfinished) R script | |
| 629 """ | |
| 630 script = "" | |
| 631 | |
| 632 xMin = self.xMin - self.leftMargin | |
| 633 if self.minimumX != None: | |
| 634 xMin = max(xMin, self.minimumX) | |
| 635 xMax = self.xMax + self.rightMargin | |
| 636 if self.maximumX != None: | |
| 637 xMax = min(xMax, self.maximumX) | |
| 638 yMin = self.yMin - self.bottomMargin | |
| 639 if self.minimumY != None: | |
| 640 yMin = self.minimumY | |
| 641 yMax = self.getNewYMaxWithTopMargin() | |
| 642 if self.maximumY != None: | |
| 643 yMax = self.maximumY | |
| 644 | |
| 645 log = "" | |
| 646 if self.logX: | |
| 647 log += "x" | |
| 648 if self.logY: | |
| 649 log += "y" | |
| 650 if log != "": | |
| 651 log = ", log=\"%s\"" % (log) | |
| 652 | |
| 653 title = "" | |
| 654 if self.title != None: | |
| 655 title = ", main = \"%s\"" % (self.title) | |
| 656 | |
| 657 if self.legend and self.legendBySide: | |
| 658 script += "layout(matrix(c(1,2), 1, 2), widths=c(5,1))\n" | |
| 659 | |
| 660 if self.rotateAxesLabels[2]: | |
| 661 script += "par(mar=c(5,12,4,2))\n" | |
| 662 else: | |
| 663 script += "par(mar=c(5,5,4,2))\n" | |
| 664 | |
| 665 addAxes = True | |
| 666 | |
| 667 if self.barplot: | |
| 668 script += "data = scan(\"tmpData-%d-0.dat\", list(x = -666, y = -666))\n" % (self.seed) | |
| 669 if len(self.lines) == 1: | |
| 670 script += "barplot(data$y, name = data$x, xlab=\"%s\", ylab=\"%s\", ylim = c(%f, %f), cex.axis = 2, cex.names = 2, cex.lab = 2%s%s)\n" % (self.xLabel, self.yLabel, yMin, yMax, title, log) | |
| 671 addAxes = False | |
| 672 else: | |
| 673 script += "data1 = scan(\"tmpData-%d-1.dat\", list(x = -666, y = -666))\n" % (self.seed) | |
| 674 script += "barplot(rbind(data$y, data1$y), name = data$x, xlab=\"%s\", ylab=\"%s\", cex.axis = 2, cex.names = 2, cex.lab = 2%s, beside = TRUE, space=c(-1,0), axes = FALSE%s)\n" % (self.xLabel, self.yLabel, title, log) | |
| 675 elif self.points: | |
| 676 script += "data = scan(\"tmpData-%d-0.dat\", list(x = -666, y = -666))\n" % (self.seed) | |
| 677 script += "plot(data$x, data$y, xlab=\"%s\", ylab=\"%s\", cex.axis = 2, cex.lab = 2, axes = FALSE%s%s)\n" % (self.xLabel, self.yLabel, title, log) | |
| 678 if self.regression: | |
| 679 x = "log10(data$x)" if self.logX else "data$x" | |
| 680 y = "log10(data$y)" if self.logY else "data$y" | |
| 681 script += "abline(lm(%s ~ %s))\n" % (y, x) | |
| 682 elif self.heatPoints: | |
| 683 if len(self.lines) != 1: | |
| 684 raise Exception("Error! Bad number of input data! Aborting...") | |
| 685 script += "data = scan(\"tmpData-%d-0.dat\", list(x = -666, y = -666))\n" % (self.seed) | |
| 686 script += "heatData = scan(\"tmpData-%d-1.dat\", list(x = \"\"))\n" % (self.seed) | |
| 687 script += "plot(data$x, data$y, col=heatData$x, xlab=\"%s\", ylab=\"%s\", cex.axis = 2, cex.lab = 2, axes = FALSE%s%s)\n" % (self.xLabel, self.yLabel, title, log) | |
| 688 if self.regression: | |
| 689 x = "log10(data$x)" if self.logX else "data$x" | |
| 690 y = "log10(data$y)" if self.logY else "data$y" | |
| 691 script += "abline(lm(%s ~ %s))\n" % (y, x) | |
| 692 else: | |
| 693 script += "plot(x = NA, y = NA, panel.first = grid(lwd = 1.0), xlab=\"%s\", ylab=\"%s\", xlim = c(%f, %f), ylim = c(%f, %f), cex.axis = 2, cex.lab = 2, axes = FALSE%s%s)\n" % (self.xLabel, self.yLabel, xMin, xMax, yMin, yMax, title, log) | |
| 694 for i in range(0, len(self.lines)): | |
| 695 script += "data = scan(\"tmpData-%d-%d.dat\", list(x = -666.666, y = -666.666))\n" % (self.seed, i) | |
| 696 script += "lines(x = data$x, y = data$y, col = %s, lty = \"%s\", lwd = %d)\n" % (self.colors[i], self.types[i], self.lineWidth) | |
| 697 | |
| 698 script += self.linesToAddBox | |
| 699 | |
| 700 if addAxes: | |
| 701 for i in self.axesLabels: | |
| 702 rotation = ", las = 2" if self.rotateAxesLabels[i] else "" | |
| 703 if self.axesLabels[i] == None: | |
| 704 script += "axis(%d, cex.axis = 2, cex.lab = 2%s)\n" % (i, rotation) | |
| 705 else: | |
| 706 oldKeys = ", ".join(["%d" % (key) for key in sorted(self.axesLabels[i].keys())]) | |
| 707 newKeys = ", ".join(["\"%s\"" % (self.axesLabels[i][key]) for key in sorted(self.axesLabels[i].keys())]) | |
| 708 script += "axis(%d, at=c(%s), lab=c(%s), cex.axis = 2, cex.lab = 2%s)\n" % (i, oldKeys, newKeys, rotation) | |
| 709 script += "box()\n" | |
| 710 | |
| 711 if self.legend: | |
| 712 if self.legendBySide: | |
| 713 script += "plot.new()\n" | |
| 714 script += "par(mar=c(0,0,0,0))\n" | |
| 715 script += "plot.window(c(0,1), c(0,1))\n" | |
| 716 script += "legends = c(%s)\n" % ", ".join(["\"%s\"" % name for name in self.names]) | |
| 717 script += "colors = c(%s)\n" % ", ".join(["%s" % color for color in self.colors]) | |
| 718 script += "lineTypes = c(%s)\n" % ", ".join(["\"%s\"" % type for type in self.types]) | |
| 719 if self.legendBySide: | |
| 720 script += "legend(0, 1, legend = legends, xjust = 0, yjust = 1, col = colors, lty = lineTypes, lwd = %d, cex = 1.5, ncol = 1, bg = \"white\")\n" % (self.lineWidth) | |
| 721 else: | |
| 722 script += "legend(\"topright\", legend = legends, xjust = 0, yjust = 1, col = colors, lty = lineTypes, lwd = %d, cex = 1.5, ncol = 1, bg = \"white\")\n" % (self.lineWidth) | |
| 723 | |
| 724 return script | |
| 725 | |
| 726 | |
| 727 | |
| 728 def plot(self): | |
| 729 """ | |
| 730 Plot the lines | |
| 731 """ | |
| 732 scriptFileName = "tmpScript-%d.R" % (self.seed) | |
| 733 scriptHandle = open(scriptFileName, "w") | |
| 734 scriptHandle.write("library(RColorBrewer)\n") | |
| 735 scriptHandle.write("colorPanel = brewer.pal(n=%d, name=\"Set1\")\n" % (self.nbColors)) | |
| 736 scriptHandle.write("%s(%s = \"%s\", width = %d, height = %d, bg = \"white\")\n" % (self.format, "filename" if self.format != "pdf" else "file", self.fileName, self.width, self.height)) | |
| 737 scriptHandle.write(self.getScript()) | |
| 738 scriptHandle.write("dev.off()\n") | |
| 739 scriptHandle.close() | |
| 740 rCommand = "R" | |
| 741 if "SMARTRPATH" in os.environ: | |
| 742 rCommand = os.environ["SMARTRPATH"] | |
| 743 command = "\"%s\" CMD BATCH %s" % (rCommand, scriptFileName) | |
| 744 status = subprocess.call(command, shell=True) | |
| 745 | |
| 746 if status != 0: | |
| 747 self.keep = True | |
| 748 raise Exception("Problem with the execution of script file %s, status is: %s" % (scriptFileName, status)) | |
| 749 | |
| 750 | |
| 751 def getCorrelationData(self): | |
| 752 if not self.regression: | |
| 753 return "" | |
| 754 scriptFileName = "tmpScript-%d.R" % (self.seed) | |
| 755 rScript = open(scriptFileName, "w") | |
| 756 rScript.write("data = scan(\"tmpData-%d-0.dat\", list(x = -0.000000, y = -0.000000))\n" % (self.seed)) | |
| 757 x = "log10(data$x)" if self.logX else "data$x" | |
| 758 y = "log10(data$y)" if self.logY else "data$y" | |
| 759 rScript.write("summary(lm(%s ~ %s))\n" % (y, x)) | |
| 760 rScript.close() | |
| 761 rCommand = "R" | |
| 762 if "SMARTRPATH" in os.environ: | |
| 763 rCommand = os.environ["SMARTRPATH"] | |
| 764 command = "\"%s\" CMD BATCH %s" % (rCommand, scriptFileName) | |
| 765 status = subprocess.call(command, shell=True) | |
| 766 if status != 0: | |
| 767 self.keep = True | |
| 768 raise Exception("Problem with the execution of script file %s computing the correlation, status is: %s" % (scriptFileName, status)) | |
| 769 outputRFile = open("%sout" % (scriptFileName)) | |
| 770 output = "" | |
| 771 start = False | |
| 772 end = False | |
| 773 for line in outputRFile: | |
| 774 if start and "> " in line: | |
| 775 end = True | |
| 776 if start and not end: | |
| 777 output += line | |
| 778 if "summary" in line: | |
| 779 start = True | |
| 780 return output | |
| 781 | |
| 782 | |
| 783 def getSpearmanRho(self): | |
| 784 """ | |
| 785 Get the Spearman rho correlation using R | |
| 786 """ | |
| 787 return None | |
| 788 if not self.points and not self.barplot and not self.heatPoints: | |
| 789 raise Exception("Cannot compute Spearman rho correlation whereas not in 'points' or 'bar' mode.") | |
| 790 | |
| 791 scriptFileName = "tmpScript-%d.R" % (self.seed) | |
| 792 rScript = open(scriptFileName, "w") | |
| 793 rScript.write("library(Hmisc)\n") | |
| 794 rScript.write("data = scan(\"tmpData-%d-0.dat\", list(x = -0.000000, y = -0.000000))\n" % (self.seed)) | |
| 795 rScript.write("spearman(data$x, data$y)\n") | |
| 796 rScript.close() | |
| 797 | |
| 798 rCommand = "R" | |
| 799 if "SMARTRPATH" in os.environ: | |
| 800 rCommand = os.environ["SMARTRPATH"] | |
| 801 command = "\"%s\" CMD BATCH %s" % (rCommand, scriptFileName) | |
| 802 status = subprocess.call(command, shell=True) | |
| 803 | |
| 804 if status != 0: | |
| 805 self.keep = True | |
| 806 raise Exception("Problem with the execution of script file %s, status is: %s" % (scriptFileName, status)) | |
| 807 | |
| 808 outputRFile = open("%sout" % (scriptFileName)) | |
| 809 nextLine = False | |
| 810 for line in outputRFile: | |
| 811 line = line.strip() | |
| 812 if nextLine: | |
| 813 if line == "NA": | |
| 814 return None | |
| 815 return float(line) | |
| 816 nextLine = False | |
| 817 if line == "rho": | |
| 818 nextLine = True | |
| 819 | |
| 820 return None |
