Package pylal :: Module autotrackutils
[hide private]
[frames] | no frames]

Source Code for Module pylal.autotrackutils

   1  """ 
   2    * Copyright (C) 2004, 2005 Cristina V. Torres 
   3    * 
   4    *  This program is free software; you can redistribute it and/or modify 
   5    *  it under the terms of the GNU General Public License as published by 
   6    *  the Free Software Foundation; either version 2 of the License, or 
   7    *  (at your option) any later version. 
   8    * 
   9    *  This program is distributed in the hope that it will be useful, 
  10    *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  11    *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  12    *  GNU General Public License for more details. 
  13    * 
  14    *  You should have received a copy of the GNU General Public License 
  15    *  along with with program; see the file COPYING. If not, write to the 
  16    *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
  17    *  MA  02111-1307  USA 
  18  """ 
  19  __author__ = 'Cristina Torres <cristina.torres@ligo.org>' 
  20   
  21  import os 
  22  import numpy 
  23  import copy 
  24  import sys 
  25  try: 
  26    import sqlite3 as sqlite 
  27  except ImportError: 
  28    import sqlite 
  29  if os.getenv("DISPLAY") == None: 
  30    #Non-interactive 
  31    try: 
  32        import matplotlib 
  33        matplotlib.use("Agg") 
  34        import pylab 
  35    except Exception, errorInfo: #RuntimeError,ImportError: 
  36        disableGraphics=True 
  37        sys.stderr.write("Error trying to import NON-INTERACTIVE pylab!\n") 
  38        sys.stderr.write("Exception Instance :%s\n"%(str(type(errorInfo)))) 
  39        sys.stderr.write("Exception Args     :%s\n"%(str(errorInfo.args))) 
  40        sys.stderr.write("Pylab functionality unavailable!\n") 
  41  else: 
  42    #Interactive 
  43    try: 
  44        import pylab 
  45    except Exception, errorInfo: #RuntimeError,ImportError: 
  46        disableGraphics=True 
  47        sys.stderr.write("Error trying to import INTERACTIVE pylab!\n") 
  48        sys.stderr.write("Exception Instance :%s\n"%(str(type(errorInfo)))) 
  49        sys.stderr.write("Exception Args     :%s\n"%(str(errorInfo.args))) 
  50        sys.stderr.write("Pylab functionality unavailable!\n") 
  51   
  52  """ 
  53  This file is intended to provide the autotrack utilities required to 
  54  process the results of the tracksearch hybrid MDGC codes. 
  55  """ 
  56   
57 -def writeTGNListToFile(filename="default",tgnList=None):
58 """ 59 This writes the information in the tgnList to a simple text 60 file. Actually we write two files. filename.TGN and 61 filename.AUX. In the AUX file is information like time stamps, 62 and other misc information from the TGNs that are dumped to disk! 63 """ 64 if tgnList==None: 65 return 66 #Append extensions AUX and TGN 67 fp0=open(filename+".TGN",'wt') 68 fp1=open(filename+".AUX",'wt') 69 for tgn in tgnList: 70 a,b=tgn.reverseCreateFromString() 71 id=tgn.getID() 72 count=tgn.getMemberCount() 73 vol=tgn.getVolume() 74 fp0.write("%s\n%s\n"%(a,b)) 75 fp1.write("%s\t%s\t%s\n"%(id,count,vol)) 76 fp0.close() 77 fp1.close()
78 #End writeTGNListToFile() 79
80 -def generateTGNListFromFile(filename="",timestamp=str("0")):
81 """ 82 This method opens a text file containing multiple TGNs and creates 83 a list of TGN objects. It is assumed that this list of TGNs was 84 created at the same time for each TGN in the file. 85 """ 86 fp=open(filename,'rt') 87 rawData=fp.readlines() 88 fp.close() 89 linesPerTGN=2 90 if rawData.__len__().__mod__(linesPerTGN) != 0: 91 raise autotrackError("File appears inconsistent!") 92 eCount=rawData.__len__().__div__(linesPerTGN) 93 TGNList=list() 94 for index in range(0,eCount): 95 thisTGN=TGN() 96 thisTGN.createFromString(rawData[index*2],rawData[index*2+1]) 97 thisTGN.__setBirthDate__(timestamp) 98 thisTGN.__setGPS__(int(timestamp)) 99 TGNList.append(thisTGN) 100 return TGNList
101 #End 102
103 -def getQualityTable(backEndName="tracksearch"):
104 """ 105 Method is a complex case statement that selects out given a 106 back-end name the properties that the TGN should be capable of 107 tracking. Depends on the output formatting of tracksearchMDGCv2.m 108 file 109 """ 110 if backEndName.strip().lower() == "tracksearch": 111 #Fetch the property fields method out of the tracksearchutils module 112 from lalapps.tracksearchutils import candidateListProperties 113 tmpProperties=candidateListProperties() 114 #We assume that the below elements to be defined were 115 #processed in tracksearchMDGCv2 et all files and are in that 116 #order left to right columns. The column values specified here 117 #are those needed to access any particular data field from the 118 # 119 #Structure ["tag",TGNarrayIndex] 120 propertiesToKeep=[ 121 ["pp",0], 122 ["y",1], 123 ["b",2], 124 ["d",3], 125 ["a",4], 126 ["r",5], 127 ["rr",6], 128 ["w",7], 129 ["e",8], 130 ["ww",9], 131 ["ee",10] 132 ] 133 propertiesHandDefined=[ 134 ["ht","Time symmetry",11], 135 ["hf","Freq symmetry",12] 136 ] 137 #Create a 3 list with text labels and array locations! 138 finalPropertyList=[] 139 for myRow in propertiesToKeep: 140 for thatRow in tmpProperties: 141 if thatRow[0].lower().strip() == \ 142 myRow[0].lower().strip(): 143 finalPropertyList.append([myRow[0],thatRow[1],myRow[1]]) 144 for myRow in propertiesHandDefined: 145 finalPropertyList.append(myRow) 146 return finalPropertyList
147 #End getQualityTable() 148
149 -def coalescetuplelist(inputList=list()):
150 """ 151 Takes an input list of tuples representing start,stop and merges 152 them placing them in time order when returning the coalesced list of 153 tuples. 154 """ 155 outputList=list() 156 if type(inputList) != type(list()): 157 sys.stderr.write("Wrong variable type passed as argument in\ 158 autotrackutils.__coalescetuplelist__()\n") 159 return None 160 if inputList.__len__() < 1: 161 return inputList 162 inputList.sort() 163 while inputList: 164 segA=inputList.pop() 165 overlap=True 166 #Assume next segment overlaps segA 167 while overlap: 168 #Pop of next segment if available 169 if inputList.__len__() > 0: 170 segB=inputList.pop() 171 else: 172 #No overlap possible no segs left! 173 segB=(-1,-1) 174 overlap=False 175 #Three cases of intersection 176 #Overlap Left 177 if ( 178 (segB[0]<= segA[0] <= segB[1]) 179 and 180 (segA[1] >= segB[1]) 181 ): 182 segA=(segB[0],segA[1]) 183 #Overlap Right 184 elif ( 185 (segB[0]<= segA[1] <= segB[1]) 186 and 187 (segA[1] <= segB[0]) 188 ): 189 segA=(segA[0],segB[1]) 190 #Bridge over 191 elif ( 192 (segB[0]<=segA[0]) 193 and 194 (segB[1]>=segA[1]) 195 ): 196 segA=(segB[0],segB[1]) 197 else: 198 #Put segment back there was no overlap! 199 if not((-1,-1)==segB): 200 inputList.append(segB) 201 overlap=False 202 outputList.append(segA) 203 outputList.sort() 204 return outputList
205 #End def coalescetuplelist(input=list()): 206
207 -def activeThreadIntervals(tgnList=list(),tgnSize=int(300)):
208 """ 209 A simple coalesce feature useful to autotrack to return a list of 210 segments which define intervals that the thread was active. 211 """ 212 tupleList=list() 213 for tgn in tgnList: 214 start=float(tgn.getBirthDateText()) 215 stop=start+tgnSize 216 tupleList.append((start,stop)) 217 activeListofTuples=coalescetuplelist(tupleList) 218 return activeListofTuples
219 #End activeThreadIntervals(tgnList=list(),tgnSize=int(300)): 220
221 -class autotrackError(Exception):
222 """ 223 Generic class raise this flag if we do not have a better 224 flag name. 225 """
226 #End class 227
228 -class autotrackDefineMismatchError(Exception):
229 """ 230 Custom error exceptions for these class objects. 231 """
232 #End class autotrackDefineError 233
234 -class autotrackDefineIdMismatchError(Exception):
235 """ 236 Custom error handling of mismatched ID 237 """
238 #End class autotrackDefineIdMismatchError 239 240
241 -class plotTGN:
242 """ 243 This class is a wrapper for plotting TGNs. It can plot TGNs on a 244 2D plot of requested parameter options. 245 """
246 - def __init__(self,iTGN=None,thread=bool(False)):
247 """ 248 Ths method should be invoked blind with either a single TGN or 249 a list of TGNS. Invoking without a TGN is still possible. A 250 second argument lets the plotting code know if we are 251 comparing different TGNs or plotting a thread of TGNs. 252 """ 253 self.isThread=thread 254 if (iTGN != None and type(iTGN) != type([])): 255 raise autotrackError("plotTGN expects a list of TGN objects.") 256 self.tgnList=iTGN 257 #Default quantities to plot 258 self.defaultX="d" 259 self.defaultY="y" 260 #Default member scale for plots 1px == 100members 261 self.memberSteps=100;
262 #End __init__() 263
264 - def setXQuantity(self,newX="d"):
265 """ 266 Using the single character string see the output of 267 getQualityTable() select the quantity to show on the Xaxis. 268 """ 269 self.defaultX=newX
270 #End setXQuantity 271
272 - def setYQuantity(self,newY="y"):
273 """ 274 Using the single character string see the output of 275 getQualityTable() select the quantity to show on the Yaxis. 276 """ 277 self.defaultY=newY
278 #End setYQuantity 279
280 - def createFigure(self,filename=None):
281 """ 282 This function provides an interface to python plotting that 283 will plot a TGN or thread of TGNs given to the plotTGN class. 284 """ 285 if self.tgnList == None: 286 raise autotrackError("Figure creation requested, no TGNs defined.") 287 pylab.figure() 288 if not self.isThread: 289 self.__primativePlotTGNs__() 290 if self.isThread: 291 self.__primativePlotThread__() 292 if filename == None: 293 pylab.show() 294 else: 295 pylab.savefig(filename) 296 pylab.close()
297 #End createFigure() 298
299 - def createReportFigures(self,filename=None):
300 """ 301 This function creates a single plot with subplot of all know 302 properties plotted against each other to see if there are 303 any relationships between TGNs 304 """ 305 if self.tgnList == None: 306 raise autotrackError("Figure creation requested, no TGNs defined.") 307 figureCount=0 308 if filename != None: 309 [file,ext]=os.path.splitext(filename) 310 #Get property list 311 shortName=[element[0] for element in getQualityTable()] 312 plotCount=shortName.__len__()*shortName.__len__() 313 #Row image count 314 countRowImages=4 315 #Col image count 316 countColImages=int(shortName.__len__()).__div__(countRowImages) 317 if int(shortName.__len__()).__mod__(countRowImages) > 0: 318 countColImages=countColImages+1 319 for myXAxis in shortName: 320 myHandle=pylab.figure() 321 countImage=1 322 for myYAxis in shortName: 323 if myXAxis != myYAxis: 324 self.setXQuantity(myXAxis) 325 self.setYQuantity(myYAxis) 326 pylab.subplot(countRowImages,countColImages,countImage) 327 countImage=countImage+1 328 self.__primativePlotTGNs__(True) 329 if filename != None: 330 newFilename="%s_%s%s"%(file,str(figureCount).zfill(3),ext) 331 pylab.savefig(newFilename,dpi=160) 332 pylab.close() 333 figureCount=figureCount+1 334 if filename == None: 335 pylab.show()
336 #End createReportFigures() 337
338 - def __getIndexAndLabels__(self):
339 """ 340 Returns index and labels for X and Y axis 341 """ 342 for elem in getQualityTable(): 343 if elem[0].strip().lower() == self.defaultX: 344 xIndex=elem[2] 345 xLabel=elem[1] 346 if elem[0].strip().lower() == self.defaultY: 347 yIndex=elem[2] 348 yLabel=elem[1] 349 return [xIndex,xLabel,yIndex,yLabel]
350 #End __getIndexAndLabels__() 351
352 - def __primativePlotTGNs__(self,bare=bool(False)):
353 """ 354 Is a macro of plotting commands that takes a list of TGNs that 355 plots each of these individually as a collection of points. 356 Creates a figure plotting the thread of list of TGNs using the 357 centroid and an X,Y error bars. Take a optional boolean to 358 make the plot not include a title and legend 359 """ 360 #Determine the index that corresponds to X and Y quantities 361 xIndex=0 362 yIndex=0 363 xLabel="NULL" 364 yLabel="NULL" 365 (xIndex,xLabel,yIndex,yLabel)=self.__getIndexAndLabels__() 366 plotValues=list() 367 gpsTimesInList=list() 368 for thisTGN in self.tgnList: 369 label=str(thisTGN.getID()) 370 #Get the X,Y property 371 (xC,xE)=thisTGN.getCentroidErrorViaIndex(xIndex) 372 (yC,yE)=thisTGN.getCentroidErrorViaIndex(yIndex) 373 plotValues.append([xC,yC,xE,yE,label]) 374 gpsTimesInList.append(thisTGN.getGPS()) 375 for x,y,ex,ey,txtLabel in plotValues: 376 pylab.errorbar(x,y,xerr=ex,yerr=ey,label=txtLabel,marker='o') 377 pylab.xlabel(str(xLabel)) 378 pylab.ylabel(str(yLabel)) 379 if not bare: 380 pylab.title("TGNs: %i"%(min(gpsTimesInList))) 381 pylab.legend()
382 #End __primativePlotTGNs__ 383
384 - def __primativePlotThread__(self,bare=bool(False)):
385 """ 386 Is a macro of plotting commands that takes a list of TGNs that 387 plots each of these individually as a collection of points. 388 Creates a figure plotting the thread of list of TGNs using the 389 centroid and an X,Y error bars 390 """ 391 #Determine the index that corresponds to X and Y quantities 392 xIndex=0 393 yIndex=0 394 xLabel="NULL" 395 yLabel="NULL" 396 for elem in getQualityTable(): 397 if elem[0].strip().lower() == self.defaultX: 398 xIndex=elem[2] 399 xLabel=elem[1] 400 if elem[0].strip().lower() == self.defaultY: 401 yIndex=elem[2] 402 yLabel=elem[1] 403 plotValues=list() 404 gpsTimesInList=list() 405 for thisTGN in self.tgnList: 406 txtLabel=str(thisTGN.getGPS()) 407 #Get the X,Y property 408 (xC,xE)=thisTGN.getCentroidErrorViaIndex(xIndex) 409 (yC,yE)=thisTGN.getCentroidErrorViaIndex(yIndex) 410 plotValues.append([xC,yC,xE,yE,txtLabel]) 411 gpsTimesInList.append(thisTGN.getGPS()) 412 xVec=list() 413 yVec=list() 414 for x,y,ex,ey,txtLabel in plotValues: 415 xVec.append(x) 416 yVec.append(y) 417 pylab.plot(xVec,yVec,label="Time Line") 418 for x,y,ex,ey,txtLabel in plotValues: 419 pylab.errorbar(x,y,xerr=ex,yerr=ey,label=txtLabel,marker='o') 420 pylab.xlabel(str(xLabel)) 421 pylab.ylabel(str(yLabel)) 422 if not bare: 423 pylab.title("TGN Thread %i"%(min(gpsTimesInList))) 424 pylab.legend()
425 #End __primativePlotThread__ 426 427
428 -class TGN:
429 """ 430 This class provides the definition of a single defined autotrack 431 defined neighborhood. We use these neighborhoods to track 432 how the instrument behavior groups change, appear or disappear. 433 """
434 - def __init__(self):
435 """ This method initializes an empty neighborhood. 436 To populate the neightborhood invoke the proper method 437 depending on the source of the data, ie ascii mysql etc 438 """ 439 self.delim=" " 440 self.idNum=float(-1) 441 self.density=float(0) 442 self.memberCount=0 443 self.volume=0 444 self.colCount=0 445 self.birthdate=str("-1") 446 self.gpsStamp=int(-1) 447 self.discoverer=str() 448 self.lastSeen=float(0) 449 self.center=None 450 self.bound=None 451 #Convention below should match tracksearchUtils conventions 452 #Only keeping the lines that apply from method glitchDB 453 #variable named glitchDatabaseEntry method should be expanded 454 #to not be hardwired to backend defintions 455 self.qualities=getQualityTable("tracksearch")
456 #End __init__ method 457
458 - def __setID__(self,inputArg):
459 """ 460 Should set the ID numeric field 461 """ 462 if type(float(0)) != type(inputArg): 463 inputArg=float(inputArg) 464 self.idNum=inputArg
465 #End 466
467 - def getID(self):
468 """ 469 Fetches the numeric ID assigned to this TGN instance 470 """ 471 return self.idNum
472 #End 473
474 - def __setBirthDate__(self,bDate=str("")):
475 """ 476 Set a text string which is the GPS birthdate, 477 as closely as possible for this neighborhood. 478 """ 479 if type(str()) != type(bDate): 480 bDate=str(bDate) 481 self.birthdate=bDate
482 #End 483
484 - def __setGPS__(self,gps=int(0)):
485 """ 486 Set a text string which is the GPS birthdate, 487 as closely as possible for this neighborhood. 488 """ 489 if type(int()) != type(gps): 490 raise autotrackError("GPS time not a INT type.") 491 self.gpsStamp=gps
492 #End 493
494 - def getBirthDateText(self):
495 """ 496 This retrieves the text string birthdate stored in TGN 497 instance. 498 """ 499 return self.birthdate
500 #End 501
502 - def getGPS(self):
503 """ 504 This retrieves the integer GPS birthdate stored in TGN 505 instance. 506 """ 507 return self.gpsStamp
508 #End 509
510 - def createFromString(self,mString,bString,delim=" "):
511 """ 512 This input method assumes you've opened a text file container 513 and will input the data from text strings. The assumed 514 delimiter is a space but can be set in the method call. 515 """ 516 self.delim=delim 517 if self.delim == " ": 518 mData=str(mString).lower().split(None) 519 bData=str(bString).lower().split(None) 520 else: 521 mData=str(mString).lower().split(delim) 522 bData=str(bString).lower().split(delim) 523 mCol=mData.__len__() 524 sCol=bData.__len__() 525 if (mData.__len__()) != (bData.__len__()): 526 raise autotrackDefineMismatchError("Array lengths %i vs %i"%(mData.__len__(),bData.__len__())) 527 self.colCount=mCol 528 #Break off first few elements before creating arrays 529 mID=mData.pop(0) 530 mDensity=mData.pop(0) 531 mCount=mData.pop(0) 532 mVolume=mData.pop(0) 533 # 534 sID=bData.pop(0) 535 sDensity=bData.pop(0) 536 sCount=bData.pop(0) 537 sVolume=bData.pop(0) 538 # 539 if mID != sID: 540 raise autotrackDefineIdMismatchError("Group labels do not match!") 541 if mDensity != sDensity: 542 raise autotrackDefineIdMismatchError("Group density values do not match!") 543 if mCount != sCount: 544 raise autotrackDefineIdMismatchError("Group count values do not match!") 545 if mVolume!=sVolume: 546 raise autotrackDefineIdMismatchError("Group volume measures do not match! %f \t %f"%(float(mVolume),float(sVolume))) 547 self.__setID__(float(mID)) 548 self.__setDensity__(float(mDensity)) 549 self.__setMemberCount__(float(mCount)) 550 self.__setVolume__(float(mVolume)) 551 self.center=numpy.array([numpy.float64(j) for j in mData],'float64') 552 self.bound=numpy.array([numpy.float64(j) for j in bData],'float64')
553 #End createFromString 554
555 - def reverseCreateFromString(self):
556 """ 557 Returns a tuple of two strings, that can be dumped to disk and read 558 back into a TGN object with method createFromString() 559 """ 560 stringA,stringB=self.exportToString().split("\n") 561 return (stringA,stringB)
562 #End reverseCreateFromString() 563
564 - def __setMemberCount__(self,mCount=0):
565 """ 566 Sets the tally of members in the group. 567 """ 568 self.memberCount=mCount
569 #End 570
571 - def getMemberCount(self):
572 """ 573 get the registered members listed for this TGN 574 """ 575 return self.memberCount
576 #End 577
578 - def __setVolume__(self,volume=0):
579 """ 580 Sets the volume value of this grouping. 581 """ 582 self.volume=volume
583 #End 584
585 - def getVolume(self):
586 """ 587 Gets the registered volume for a given TGN. 588 """ 589 return self.volume
590 #End 591
592 - def exportToString(self):
593 """ 594 Create a text string that can be directly inserted into the 595 text field of the sqlite database table TGN. 596 """ 597 delimiter=self.delim 598 outputString="" 599 outputString=outputString+"%s%s"%(delimiter,self.getID()) 600 outputString=outputString+"%s%s"%(delimiter,self.getDensity()) 601 if self.colCount >= 17: 602 outputString=outputString+"%s%s"%(delimiter,self.getMemberCount()) 603 outputString=outputString+"%s%s"%(delimiter,self.getVolume()) 604 for elem in self.center: 605 outputString=outputString+"%s%s"%(delimiter,elem) 606 outputString=outputString+"\n" 607 outputString=outputString+"%s%s"%(delimiter,self.getID()) 608 outputString=outputString+"%s%s"%(delimiter,self.getDensity()) 609 if self.colCount >= 17: 610 outputString=outputString+"%s%s"%(delimiter,self.getMemberCount()) 611 outputString=outputString+"%s%s"%(delimiter,self.getVolume()) 612 for elem in self.bound: 613 outputString=outputString+"%s%s"%(delimiter,elem) 614 return outputString
615 #end exportToString() 616
617 - def getDensity(self):
618 """ 619 Returns the value of TGN density set. 620 """ 621 return self.density
622 #End 623
624 - def __setDensity__(self,inputArg):
625 """ 626 Sets the input density value to the TGN instance. 627 """ 628 if type(float(0)) != type(inputArg): 629 inputArg=float(inputArg) 630 self.density=inputArg
631 #End 632
633 - def isNULL(self):
634 """ 635 Check the defined properties, returns true if they are all 636 zeroed out which is NULL according the the matlab generator. 637 """ 638 isNull=bool(False) 639 cV=self.getCenterVector() 640 bV=self.getBoundVector() 641 if numpy.any(cV==0) and numpy.any(bV==0): 642 isNull=bool(True) 643 return isNull
644 #End isNull 645
646 - def getBoundVector(self):
647 """ 648 Gets the variance components of this TGN instance. 649 """ 650 return self.bound
651 #End getBoundVector 652
653 - def getCenterVector(self):
654 """ 655 Gets the center of the neighborhood 656 """ 657 return self.center
658 #End getCenterVector 659
660 - def getCentroidErrorViaIndex(self,index=0):
661 """ 662 Given an index select the that index from the Center vector 663 and the bound Vector. This will return a tuple (center,bound) 664 """ 665 centerVec=self.getCenterVector() 666 boundVec=self.getBoundVector() 667 vectorLength=centerVec.__len__() 668 if index >= vectorLength: 669 raise autotrackError("Invalid index requested exceeds\ 670 elements available. Elements: %i Index Sought: %i"%(vectorLength,index)) 671 center=centerVec[index] 672 bound=boundVec[index] 673 return (center,bound)
674 #End getCentroidErrorViaIndex 675
676 - def isSame(self,TGN):
677 """ 678 Checks to see if self instance is IDENTICAL to 679 TGN instance given as argument! 680 """ 681 samePoint=bool(False) 682 samePoint=self.checkOverlap(TGN,0) 683 if samePoint and self.idNum==TGN.idNum and self.density==TGN.density: 684 return bool(True) 685 return bool(False)
686
687 - def checkOverlap(self,TGN,boundSize=0.5,mutual=bool(True)):
688 """ 689 Check to see if SELF neighborhood overlaps with other input 690 TGN class. We define them as over lapping if they are 691 withing boundSize stddevs of the center of SELF compared 692 to the center of argument TGN. The last optional argument 693 dictates that given the bound vector of both TGNs they should be 694 able to 'walk' into each other not just A into B but that B must 695 also be able to step into the neighborhood of B. 696 """ 697 stepVectorSelf=boundSize*numpy.array(self.getBoundVector()).__abs__() 698 stepVectorTGN=boundSize*numpy.array(TGN.getBoundVector()).__abs__() 699 diffVector=numpy.array( 700 self.getCenterVector() 701 -TGN.getCenterVector()).__abs__() 702 if mutual: 703 if numpy.array(diffVector<=stepVectorSelf).all()\ 704 and\ 705 numpy.array(diffVector<=stepVectorTGN).all(): 706 return bool(True) 707 else: 708 return bool(False) 709 else: 710 if numpy.array(diffVector<=stepVectorSelf).all(): 711 return bool(True) 712 else: 713 return bool(False)
714 #End checkOverlap 715
716 - def getSeparation(self,TGN):
717 """ 718 Gets the resultant seperation vectors and normalizes this 719 value by the boundVector, then use this to compute a 720 normalized magnitude of the vector. 721 """ 722 diffVector=numpy.array( 723 self.getCenterVector() 724 -TGN.getCenterVector()).__abs__() 725 bv=self.getBoundVector() 726 sepVector=diffVector.__div__(bv) 727 mag=numpy.sqrt(numpy.inner(sepVector,sepVector)) 728 return mag
729 #End getSeperation 730
731 - def spatialAxisMinMax(self,TGN):
732 """ 733 Return the index returned by getCenterVector for self the spatial 734 axis with the smallest difference between self.getCenterVector and 735 TGN.getCenterVector 736 returns a tuple of two indices {minAxisIndex,maxAxisIndex} 737 """ 738 diffVector=numpy.array( 739 self.getCenterVector() 740 -TGN.getCenterVector()).__abs__() 741 smallIndex=diffVector.argmin() 742 largeIndex=diffVector.argmax() 743 return (smallIndex,largeIndex)
744 #End spatialAxisMinMax() 745
746 - def nearestTGNid(self,TGNList,boundSize=0.5):
747 """ 748 wrapper 749 """ 750 myN=self.nearestTGN(TGNList,boundSize) 751 myID=myN.getID() 752 return myID
753
754 - def nearestTGN(self,TGNList,boundSize=0.5):
755 """ 756 Takes a list of TGNs and compares it to self 757 to determine which is the closest one, this ideally 758 is the same group and we can associate the group IDs. If method 759 does not find TGN it returns a NONE value. 760 """ 761 if type(list())!=type(TGNList): 762 raise autotrackError("Type of input to method nearestTGNid is wrong!") 763 distanceKey=list() 764 for index in range(0,TGNList.__len__()): 765 #Ignore entries in the list that all NULL 766 if not TGNList[index].isNULL(): 767 if self.checkOverlap(TGNList[index],boundSize): 768 dist=self.getSeparation(TGNList[index]) 769 idVal=TGNList[index].getID() 770 distanceKey.append([dist,idVal]) 771 distanceKey.sort() 772 try: 773 findID=int(distanceKey[0][1]) 774 except IndexError: 775 findID=-1 776 if findID > -1: 777 for nhd in TGNList: 778 if nhd.getID() == findID: 779 foundTGN=nhd 780 else: 781 foundTGN=None 782 return foundTGN
783 #End nearestTGN 784 #End class TGN 785
786 -class tgnThread:
787 """ 788 This class is a simple list object with manipulation methods which 789 is called a thread that shows how the TNGs are related and it also 790 tracks knots (intersections/overlaps) of two different threads. 791 Thereby relating them. Three lists are tracked: 792 0) The thread serial number for quick ID 793 1) A thread name if given(default is thread serial number) 794 2) The list of TGN what are related and sorted by time 795 3) The list of knots (threads with overlaping TGNs) 796 """
797 - def __init__(self):
798 """ 799 HI 800 """
801 #End __init__() 802 803
804 -class autotrackSQL:
805 """ 806 This class provides sqlite table creation query deletion etc, 807 related funtions for working the the autotrack databases. This 808 """
809 - def __init__(self,dbName="autotrack_default.sqlite"):
810 """ 811 Initializes the variables associated with the autotrackSQL 812 database manipulations. Setup is {TableName,Bool,{Definition}} 813 """ 814 self.dbFile="" 815 self.dbSocket=None 816 #Add method to define table etc 817 self.tables=dict() 818 self.table['active_tgn']={'group_serial_number':'blob', 819 'group_birthdate' :'text', 820 'group_gps' :'integer', 821 'discoverer' :'text', 822 'group_IFO' :'text', 823 'group_label' :'text', 824 'group_density' :'text', 825 'group_member_count' :'text', 826 'group_last_seen' :'text', 827 'statistics' :'blob'} 828 829 self.table['scientist_entry']={'group_serial_number' :'blob', 830 'entry_date' :'text', 831 'scientist' :'blob', 832 'channels_of_interest' :'blob', 833 'URLs_of_interest' :'blob', 834 'description_text' :'text', 835 'solution_text' :'text', 836 'misc_information' :'text', 837 'usefulness_score' :'text', 838 'extra_field1' :'blob', 839 'extra_field2' :'blob', 840 'extra_field3' :'blob'} 841 842 self.table['plot_locations']={'group_serial_number' :'blob', 843 'line_plot' :'blob', 844 'aux_plots' :'blob'} 845 846 self.table['inactive_tgn']={'group_serial_number' :'blob', 847 'group_birthdate' :'text', 848 'group_gps' :'integer', 849 'discoverer' :'text', 850 'group_label' :'text', 851 'group_density' :'real', 852 'group_member_count' :'integer', 853 'group_last_seen' :'text', 854 'statistics' :'blob'} 855 856 self.table['active_threads']={'thread_serial_number' :'blob', 857 'thread_name' :'text', 858 'group_list' :'blob', 859 'knot_list' :'blob'} 860 861 self.table['inactive_threads']={'thread_serial_number' :'blob', 862 'thread_name' :'text', 863 'group_list' :'blob', 864 'knot_list' :'blob'} 865 866 #Look for the table if it does not exist create it 867 #otherwise load it into this object! 868 self.__selectDB__(dbName)
869 #End __init__() 870
871 - def __selectDB__(self,dbName='autotrack_default.sqlite'):
872 """ 873 Selects the specified if it exists is reads the contents 874 or if not is issues a warning and tells you the db 875 needs to be created. 876 """ 877 #Code up how to check for a db and either create the tables 878 #or read them 879 #End self.__selectDB__() 880 self.dbSocket=sqlite.connect(dbName) 881 self.dbFile=dbName 882 #Try seeing if there are tables that we want in there already 883 try: 884 self.dbSocket.execute("select * from %s"%(self.defineTables[0][0])) 885 except: 886 sys.stdout.write("It appears that we need to create the tables.\n") 887 self.createTables()
888 #End __selectDB__() 889
890 - def DEPRICATEDgetTableIndex(self,name=""):
891 """ 892 Given a string searches the tuple self.defineTables to 893 determine the index of that table to various function calls. 894 """ 895 answer=int(-1) 896 for index in range(self.defineTables.__len__()): 897 if self.defineTables[index][0].lower() == name.lower(): 898 answer=index 899 if not(type(int()) == type(answer)): 900 raise autotrackError("getTableIndex type invalid!\n %s"(answer)) 901 return answer
902 #End getTableIndex 903
904 - def __DEPRICATEDcreateSingleTable__(self,name):
905 """ 906 This method will generate a table from the list of tables 907 and definitions specified by self.autotrackTableDef or 908 self.auxTableDef 909 """ 910 tableIndex=self.DEPRICATEDgetTableIndex(name) 911 thisTable=self.defineTables[tableIndex] 912 tableName=thisTable[0] 913 required=thisTable[1] 914 colDefs=thisTable[2] 915 rowString="" 916 for col in colDefs: 917 rowString=rowString+"%s "%(col) 918 commandString="create table %s (%s)"%(tableName,rowString) 919 try: 920 self.dbSocket.execute(commandString) 921 except: 922 sys.stderr.write("Error trying to create table.\n") 923 self.dbSocket.commit() 924 return 925 self.dbSocket.commit()
926 #End __createSingleTable__() 927
928 - def __createSingleTable__(self,name=None,tabledef=None):
929 """ 930 This method will generate a table from the list of tables 931 and definitions specified by self.autotrackTableDef or 932 self.auxTableDef 933 """ 934 if (name == None or tabledef == None): 935 return 936 tableName=name 937 colDefs=tabledef 938 rowString="" 939 for col in colDefs: 940 rowString=rowString+"%s "%(col) 941 commandString="create table %s (%s)"%(tableName,rowString) 942 try: 943 self.dbSocket.execute(commandString) 944 except: 945 sys.stderr.write("Error trying to create table.\n") 946 self.dbSocket.commit() 947 return 948 self.dbSocket.commit()
949 #End __createSingleTable__() 950
951 - def getSocket(self):
952 """ 953 Returns an object which is a raw handle to the dqlite DB. 954 This is equivalent to being returned X from 955 X=sqlite.connect('dbfilename') 956 """ 957 return self.dbSocket
958 #End getSocket 959
960 - def createTables(self,overwrite=bool(False)):
961 """ 962 This function call will create the specified sqlite db unless 963 there exists one already. In that case we throw an error 964 unless we explicitly want to overwrite that table. 965 """ 966 for index in self.tables.keys(): 967 sys.stdout.write("Creating table %s\n"%(index)) 968 self.__createSingleTable__(index,self.tables[index]) 969 self.dbSocket.commit()
970 #End createTables() 971
972 - def getThreads(self,table='tgn',time=None):
973 """ 974 This method will fetch the groups defined at time NOW in table 975 TGN(default). It returns these groups as a list of TGN objects. 976 """ 977 #Search the group threads and grab a list of all threads. 978 #Take head of each thread and try for matching it against newly 979 #seen TNGs to increase the thread length. 980 # 981 print "HI"
982 #End getThreads() 983
984 - def getThreadHeads(self,table='tgn',time=None):
985 """ 986 This returns only the head of the thread to keep memory 987 requirements to a minimum. The thread object will only 988 be loaded if a manipulation to the thread or thread report 989 method is called. 990 """ 991 print "Getting all TGN heads from threads."
992 #End getThreadHeads() 993
994 - def getThreadByName(self,table='tgn',name=None):
995 """ 996 This function will return a thread object (list) for a 997 TGN thread that exists in the table specified. By default 998 we search the active threads in table TGN. 999 """ 1000 print "Getting single thread by name"
1001 #End 1002
1003 - def getThreadHeadByName(self,table='tgn',name=None):
1004 """ 1005 Returns a single TGN object the thread head for quoted 1006 thread. 1007 """ 1008 print "Getting TGN head from thread"
1009 #End getThreadHeadByName 1010 1011 #def loadThread(self,serialNumber=None) 1012 #def syncThread(self) 1013 #def deactivateThread(self) 1014 #def activateThread(self) 1015 #def deleteThread(self) 1016