{"action":"created","comment":{"url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/comments/46102692","id":46102692,"diff_hunk":"@@ -542,7 +612,838 @@ def find_cloud_elements(mergImgs, timelist, mainStrDir, lat, lon, TRMMdirName=No\n \n     return CLOUD_ELEMENT_GRAPH\n #**********************************************************************************************************************\n+manager = Manager()\n+varsDict = manager.dict()\n+\n+\n+#Callable object that is passed to the Pool map (so that the find_cloud_elements function can be called many times in parallel) - Added by Gabriel Mel\n+class CeFinder(object):\n+    def __init__(self,timelist, mainStrDir, TRMMdirName=None):\n+        self.timelist = timelist\n+        self.mainStrDir = mainStrDir\n+        self.TRMMdirName = TRMMdirName\n+    def __call__(self,t):\n+        #cProfile.runctx('find_single_frame_cloud_elements(t,self.mergImgs,self.timelist,self.mainStrDir,\\\n+        #    self.lat,self.lon,self.TRMMdirName)',globals(),locals(),'poolProf')\n+        return find_single_frame_cloud_elements(t,varsDict['images'],self.timelist,self.mainStrDir,\\\n+            varsDict['lat'],varsDict['lon'],self.TRMMdirName)\n+        #return find_single_frame_cloud_elements(t,self.timelist,self.mainStrDir,\\\n+        #    varsDict['lat'],varsDict['lon'],self.TRMMdirName)\n+            \n+\n+#Batch parallel version for tests of overhead slowdown. May end up being useless\n+#Doesn't help much\n+def runBatch(frames, mergImgs, timelist, mainStrDir, lat, lon, TRMMdirName=None):\n+    return map(CeFinder(timelist, mainStrDir, TRMMdirName),frames)\n+\n+\n+#Serial version of find_cloud_elements which calls the find on single frames serially\n+#This version is a little easier to debug than the parallel version. I'm going to delete the old version (plain find_cloud_elements) soon\n+def serial_find_cloud_elements(mergImgs, timelist, mainStrDir, lat, lon, TRMMdirName=None):\n+    varsDict['images'] = mergImgs\n+    varsDict['lat'] = lat\n+    varsDict['lon'] = lon\n+    \n+    global MAIN_DIRECTORY\n+    MAIN_DIRECTORY = mainStrDir\n+    global LAT\n+    LAT = lat\n+    global LON\n+    LON = lon\n+    \n+    image_proc_start = time.time()\n+    results = map(CeFinder(timelist, mainStrDir, TRMMdirName), \\\n+        xrange(mergImgs.shape[0]))\n+    print(time.time() - image_proc_start)\n+    return serial_assemble_graph(results)\n+\n+\n+#Parellel version of find_cloud_elements which calls the find on single frames in parallel\n+def par_find_cloud_elements(mergImgs, timelist, mainStrDir, lat, lon, TRMMdirName=None):\n+    varsDict['images'] = mergImgs\n+    varsDict['lat'] = lat\n+    varsDict['lon'] = lon\n+    \n+    global MAIN_DIRECTORY\n+    MAIN_DIRECTORY = mainStrDir\n+    global LAT\n+    LAT = lat\n+    global LON\n+    LON = lon\n+    \n+    #batches = [xrange(mergImgs.shape[0]/3),xrange(mergImgs.shape[0]/3,2*mergImgs.shape[0]/3),xrange(2*mergImgs.shape[0]/3,mergImgs.shape[0])]\n+    #batches = [xrange(mergImgs.shape[0]/2),xrange(mergImgs.shape[0]/2,mergImgs.shape[0])]\n+    #results = map(lambda t:runBatch(t,mergImgs,timelist,mainStrDir,lat,lon,TRMMdirName),batches)\n+    \n+    #args = []\n+    #for t in xrange(mergImgs.shape[0]):\n+    #    args.append((t,mergImgs[t]))\n+    \n+    p = Pool(NUM_IMAGE_WORKERS)\n+    image_proc_start = time.time()\n+    results = p.map(CeFinder(timelist, mainStrDir, TRMMdirName), xrange(mergImgs.shape[0]))\n+    print(time.time() - image_proc_start)\n+    return serial_assemble_graph(results)\n+\n+#Once the images have been processed, the results are put together into the larger graph\n+def serial_assemble_graph(results):\n+    totals = 0\n+    edgeWeight = [1, 2, 3] #weights for the graph edges\n+    \n+    cloudElementsJSON = []  #list of the key, value objects associated with a CE in the graph\n+\n+    #openfile for storing ALL cloudElement information\n+    cloudElementsFile = open((MAIN_DIRECTORY + '/textFiles/cloudElements.txt'), 'wb')\n+    #openfile for storing cloudElement information meeting user criteria i.e. MCCs in this case\n+    cloudElementsUserFile = open((MAIN_DIRECTORY + '/textFiles/cloudElementsUserFile.txt'), 'w')\n+\n+    for ce in results[0][0]:\n+        CLOUD_ELEMENT_GRAPH.add_node(ce['uniqueID'],ce)\n+        #totals +=1\n+        cloudElementsFile.write(results[0][1])\n+        cloudElementsUserFile.write(results[0][2])    \n+    \n+    for t in xrange(1,len(results)):\n+        currFrameCEs = results[t][0]\n+        prevFrameCEs = results[t-1][0]\n+        ceNum = 0\n+        for ce in currFrameCEs:\n+            #totals +=1\n+            cloudElementsFile.write(results[t][1])\n+            cloudElementsUserFile.write(results[t][2])\n+            CLOUD_ELEMENT_GRAPH.add_node(ce['uniqueID'], ce)\n+            edges = []\n+            for cloudElementDict in prevFrameCEs:\n+                percentageOverlap, areaOverlap = cloud_element_overlap(ce['cloudElementLatLon'], \\\n+                    cloudElementDict['cloudElementLatLon'])\n+\n+                #change weights to int as the built in shortest path chokes on floating pts according to Networkx doc\n+                #according to Goyens et al, two CEs are considered related if there is atleast 95% overlap between \n+                #them for consecutive imgs a max of 2 hrs apart\n+                if percentageOverlap >= 0.95:\n+                    CLOUD_ELEMENT_GRAPH.add_edge(cloudElementDict['uniqueID'], ce['uniqueID'], weight=edgeWeight[0])\n+                    edges.append(cloudElementDict['uniqueID'])\n+\n+                elif percentageOverlap >= 0.90 and percentageOverlap < 0.95 :\n+                    CLOUD_ELEMENT_GRAPH.add_edge(cloudElementDict['uniqueID'], ce['uniqueID'], weight=edgeWeight[1])\n+                    edges.append(cloudElementDict['uniqueID'])\n+\n+                elif areaOverlap >= MIN_OVERLAP:\n+                    CLOUD_ELEMENT_GRAPH.add_edge(cloudElementDict['uniqueID'], ce['uniqueID'], weight=edgeWeight[2])\n+                    edges.append(cloudElementDict['uniqueID'])\n+            \n+            #Pull out JSON data\n+            JSONDict = results[t][3][ceNum]\n+            \n+            \n+            if edges:\n+                cloudElementsJSON.append({'cloudElement': cloudElementDict['uniqueID'], 'time': JSONDict['time'],\\\n+                    'area':JSONDict['area'], 'Tmax': JSONDict['tmax'], 'Tmin': JSONDict['tmin'],'center':JSONDict['center'],\\\n+                    'convective_fraction': JSONDict['cf'], 'lat_lon_box': JSONDict['lat_lon_box'], 'shape': JSONDict['shape'], 'edges':edges, 'eccentricity':JSONDict['cloudElementEpsilon']})\n+            \n+            \n+            \n+            ceNum += 1\n+\n+\n+    #Close info files\n+    cloudElementsFile.close()\n+    cloudElementsUserFile.close()\n+    \n+    #Write to JSON file\n+    filenameJSON = MAIN_DIRECTORY + '/textFiles/graphJSON.txt'\n+    with open(filenameJSON, 'w+') as f:\n+        json.dump(cloudElementsJSON,f)\n+\n+    #clean up graph - remove parent and childless nodes\n+    #print(\"Number of nodes before cleanup: \"+str(CLOUD_ELEMENT_GRAPH.number_of_nodes()) + \"\\n\")\n+    #print(\"TOTALS: \"+str(totals)+\"\\n\")\n+    outAndInDeg = CLOUD_ELEMENT_GRAPH.degree_iter()\n+    toRemove = [node[0] for node in outAndInDeg if node[1] < 1]\n+    CLOUD_ELEMENT_GRAPH.remove_nodes_from(toRemove)\n+    \n+    return CLOUD_ELEMENT_GRAPH\n+\n+#A version of find_cloud_elements which performs analysis on single frames only. The graph building\n+#has been taken out to allow parallelization. This function is called by many workers. \n+def find_single_frame_cloud_elements(t,mergImgs,timelist, mainStrDir, lat, lon, TRMMdirName=None):\n+#def find_single_frame_cloud_elements(tAndImg,timelist, mainStrDir, lat, lon, TRMMdirName=None):\n+    '''\n+    Purpose:: Determines the contiguous boxes for a given time of the satellite images i.e. each frame\n+        using scipy ndimage package\n+\n+    Inputs:: mergImgs: masked numpy array in (time,lat,lon),T_bb representing the satellite data. This is masked based \n+        on the maximum acceptable temperature, T_BB_MAX\n+        timelist: a list of python datatimes\n+        mainStrDir: a string representing the path to main directory where data will be written\n+        lat: a 2D array of the set of latitudes from the files opened\n+        lon: a 2D array of the set of longitudes from the files opened\n+        TRMMdirName (optional): string representing the path where to find the TRMM datafiles\n+\n+    Returns::\n+        CLOUD_ELEMENT_GRAPH: a Networkx directed graph where each node contains the information in cloudElementDict\n+        The nodes are determined according to the area of contiguous squares. The nodes are linked through weighted\n+        edges.\n+\n+        cloudElementDict = {'uniqueID': unique tag for this CE,\n+                            'cloudElementTime': time of the CE,\n+                            'cloudElementLatLon': (lat,lon,value) of MERG data of CE,\n+                            'cloudElementCenter':list of floating-point [lat,lon] representing the CE's center\n+                            'cloudElementArea':floating-point representing the area of the CE,\n+                            'cloudElementEccentricity': floating-point representing the shape of the CE,\n+                            'cloudElementTmax':integer representing the maximum Tb in CE,\n+                            'cloudElementTmin': integer representing the minimum Tb in CE,\n+                            'cloudElementPrecipTotal':floating-point representing the sum of all rainfall in CE if\n+                                                      TRMMdirName entered,\n+                            'cloudElementLatLonTRMM':(lat,lon,value) of TRMM data in CE if TRMMdirName entered,\n+                            'TRMMArea': floating-point representing the CE if TRMMdirName entered,\n+                            'CETRMMmax':floating-point representing the max rate in the CE if TRMMdirName entered,\n+                            'CETRMMmin':floating-point representing the min rate in the CE if TRMMdirName entered}\n+    Assumptions::\n+        Assumes we are dealing with MERG data which is 4kmx4km resolved, thus the smallest value\n+        required according to Vila et al. (2008) is 2400km^2\n+        therefore, 2400/16 = 150 contiguous squares\n+    '''\n+    \n+    single_frame_start = time.time()\n+\n+    #os.system('taskset -p 0x%x %d' % (t%8 + 1,os.getpid()))\n+    #os.system('taskset -p -c %i %d' % (t%8 + 1,os.getpid()))\n+    global MAIN_DIRECTORY\n+    MAIN_DIRECTORY = mainStrDir\n+    global LAT\n+    LAT = lat\n+    global LON\n+    LON = lon\n+    #global mergImgs\n+    global P_TIME\n+    \n+    cloudElementsJSON = []  #list of the key, value objects associated with a CE in the graph\n+    edges = []     #list of the nodes connected to a given CE\n+    latLonBox = [] #list of extreme points for the min fitting box around a CE [lon_min, lat_min, lon_max, lat_max]\n+    shape = 0      #max(num of non-zero boxes in lat, num of non-zero boxes in lon) for the CE\n+    cf = 0.0       #convective fraction \n+    tmin = 0.0     #IR Tmin for the CE\n+    tmax = 0.0     #IR Tmax for the CE\n+\n+    #frame = ma.empty((1, mergImgs.shape[1], mergImgs.shape[2]))\n+    ceCounter = 0\n+    frameceCounter = 0\n+    frameNum = 0\n+    cloudElementEpsilon = 0.0\n+    cloudElementDict = {}\n+    cloudElementCenter = []     #list with two elements [lat,lon] for the center of a CE\n+    prevFrameCEs = []           #list for CEs in previous frame\n+    currFrameCEs = []           #list for CEs in current frame\n+    cloudElementLat = []        #list for a particular CE's lat values\n+    cloudElementLon = []        #list for a particular CE's lon values\n+    cloudElementLatLons = []    #list for a particular CE's (lat,lon) values\n+    allCloudElementDicts = []\n+    allJSONDataDicts = []\n+\n+    TIR_min = 0.0\n+    TIR_max = 0.0\n+    temporalRes = 3 # TRMM data is 3 hourly\n+    precipTotal = 0.0\n+    ceTRMMList = []\n+    precip = []\n+\n+    nygrd = len(LAT[:, 0])\n+    nxgrd = len(LON[0, :])\n+\n+    #openfile for storing ALL cloudElement information\n+    #cloudElementsFile = open((MAIN_DIRECTORY + '/textFiles/cloudElements.txt'), 'wb')\n+    cloudElementsFileString = ''\n+    #openfile for storing cloudElement information meeting user criteria i.e. MCCs in this case\n+    #cloudElementsUserFile = open((MAIN_DIRECTORY + '/textFiles/cloudElementsUserFile.txt'), 'w')\n+    cloudElementsUserFileString = ''\n+    \n+    filenameJSON = MAIN_DIRECTORY + '/textFiles/graphJSON.txt'\n+\n+    #NB in the TRMM files the info is hours since the time thus 00Z file has in 01, 02 and 03 times\n+    \n+    #INSTEAD OF ITERATING OVER t, WE FREEZE IT AND CALL THE FUNCTION IN PARALLEL\n+    \n+    #for t in xrange(mergImgs.shape[0]):\n+    #-------------------------------------------------\n+    # #textfile name for saving the data for arcgis\n+    # thisFileName = MAIN_DIRECTORY+'/' + (str(timelist[t])).replace(' ', '_') + '.txt'\n+    # cloudElementsTextFile = open(thisFileName,'w')\n+    #-------------------------------------------------\n+\n+    #determine contiguous locations with temeperature below the warmest temp i.e. cloudElements in each frame\n+    frame, ceCounter = ndimage.measurements.label(mergImgs[t,:,:], structure=STRUCTURING_ELEMENT)\n+    #frame, ceCounter = ndimage.measurements.label(Img, structure=STRUCTURING_ELEMENT)\n+    frameceCounter = 0\n+    frameNum = t + 1\n+\n+    profTimes = np.zeros((10,))\n+\n+    #First do the regridding - don't duplicate this effort by doing it in a loop\n+    #if other dataset (TRMM) assumed to be a precipitation dataset was entered\n+    if TRMMdirName:\n+        #------------------TRMM stuff -------------------------------------------------\n+        fileDate = ((str(timelist[t])).replace(' ', '')[:-8]).replace('-', '')\n+        fileHr1 = (str(timelist[t])).replace(' ', '')[-8:-6]\n+\n+        if int(fileHr1) % temporalRes == 0:\n+            fileHr = fileHr1\n+        else:\n+            fileHr = (int(fileHr1) / temporalRes) * temporalRes\n+        if fileHr < 10:\n+            fileHr = '0'+str(fileHr)\n+        else:\n+            str(fileHr)\n+\n+        #open TRMM file for the resolution info and to create the appropriate sized grid\n+        TRMMfileName = TRMMdirName + '/3B42.' + fileDate + '.' + str(fileHr) + '.7A.nc'\n+\n+        TRMMData = Dataset(TRMMfileName, 'r', format='NETCDF4')\n+        precipRate = TRMMData.variables['pcp'][:, :, :]\n+        latsrawTRMMData = TRMMData.variables['latitude'][:]\n+        lonsrawTRMMData = TRMMData.variables['longitude'][:]\n+        lonsrawTRMMData[lonsrawTRMMData > 180] = lonsrawTRMMData[lonsrawTRMMData > 180] - 360.\n+        LONTRMM, LATTRMM = np.meshgrid(lonsrawTRMMData, latsrawTRMMData)\n+\n+        # nygrdTRMM = len(LATTRMM[:, 0])\n+        # nxgrdTRMM = len(LONTRMM[0, :])\n+        precipRateMasked = ma.masked_array(precipRate, mask=(precipRate < 0.0))\n+        #---------regrid the TRMM data to the MERG dataset ----------------------------------\n+        #regrid using the do_regrid stuff from the Apache OCW\n+        #regriddedTRMM = ma.zeros((0, nygrd, nxgrd))\n+        regriddedTRMM = utils.do_regrid(precipRateMasked[0, :, :], LATTRMM, LONTRMM, LAT, LON, order=1, \\\n+                                           mdi=-999999999)\n+        #regriddedTRMMCopy = np.copy(regriddedTRMM)\n+        #----------------------------------------------------------------------------------\n+\n+        # #get the lat/lon info from cloudElement\n+        #get the lat/lon info from the file\n+        #latCEStart = LAT[0][0]\n+        #latCEEnd = LAT[-1][0]\n+        #lonCEStart = LON[0][0]\n+        #lonCEEnd = LON[0][-1]\n+\n+        #get the lat/lon info for TRMM data (different resolution)\n+        # latStartT = utils.find_nearest(latsrawTRMMData, latCEStart)\n+        # latEndT = utils.find_nearest(latsrawTRMMData, latCEEnd)\n+        # lonStartT = utils.find_nearest(lonsrawTRMMData, lonCEStart)\n+        # lonEndT = utils.find_nearest(lonsrawTRMMData, lonCEEnd)\n+        # Unused since CEPrecipRate isn't used and these are just inputs\n+        # latStartIndex = np.where(latsrawTRMMData == latStartT)\n+        # latEndIndex = np.where(latsrawTRMMData == latEndT)\n+        # lonStartIndex = np.where(lonsrawTRMMData == lonStartT)\n+        # lonEndIndex = np.where(lonsrawTRMMData == lonEndT)\n+\n+        #get the relevant TRMM info\n+        # Unused Variable\n+        # CEprecipRate = precipRate[:, (latStartIndex[0][0]-1):latEndIndex[0][0], \\\n+        #        (lonStartIndex[0][0]-1):lonEndIndex[0][0]]\n+        TRMMData.close()\n+\n+\n+    #for each of the areas identified, check to determine if it a valid CE via an area and T requirement\n+    all_locs = ndimage.find_objects(frame)\n+    for count in xrange(ceCounter):\n+        #[0] is time dimension. Determine the actual values from the data\n+        #loc is a masked array\n+\n+        pin = time.time() #First pin drop\n+        try:\n+            #locOld = ndimage.find_objects(frame == (count + 1))[0]\n+            loc = all_locs[count]\n+            #assert(np.array_equal(loc,locOld))\n+        except Exception, e:\n+            print 'Error is ', e\n+            continue\n+        profTimes[0]+= time.time() - pin\n+        pin = time.time() #second pin drop\n+\n+        cloudElement = mergImgs[t,:,:][loc]\n+        #cloudElement = Img[loc]\n+        labels, _ = ndimage.label(cloudElement)\n+\n+        #determine the true lats and lons for this particular CE\n+        cloudElementLat = LAT[loc[0], 0]\n+        cloudElementLon = LON[0, loc[1]]\n+\n+        #determine number of boxes in this cloudelement\n+        numOfBoxes = np.count_nonzero(cloudElement)\n+        cloudElementArea = numOfBoxes * XRES * YRES\n+\n+        profTimes[1]+= time.time() - pin\n+        \n+\n+        #If the area is greater than the area required, or if the area is smaller than the suggested area,\n+        #check if it meets a convective fraction requirement consider as CE\n+\n+        if cloudElementArea >= AREA_MIN or (cloudElementArea < AREA_MIN and \\\n+                ((ndimage.minimum(cloudElement, labels=labels)) / \\\n+                    float((ndimage.maximum(cloudElement, labels=labels)))) < CONVECTIVE_FRACTION):\n+            pin = time.time() #third pin drop\n+            #get some time information and labeling info\n+            frameceCounter += 1\n+            ceUniqueID = 'F' + str(frameNum) + 'CE' + str(frameceCounter)\n+            #-------------------------------------------------\n+            #textfile name for accesing CE data using MATLAB code\n+            # thisFileName = MAIN_DIRECTORY+'/' + (str(timelist[t])).replace(' ', '_') + ceUniqueID +'.txt'\n+            # cloudElementsTextFile = open(thisFileName,'w')\n+            #-------------------------------------------------\n+            # ------ NETCDF File stuff for brightness temp stuff ------------------------------------\n+            thisFileName = MAIN_DIRECTORY + '/MERGnetcdfCEs/cloudElements' + \\\n+                            (str(timelist[t])).replace(' ', '_') + ceUniqueID + '.nc'\n+            currNetCDFCEData = Dataset(thisFileName, 'w', format='NETCDF4')\n+            currNetCDFCEData.description = 'Cloud Element '+ ceUniqueID + ' temperature data'\n+            currNetCDFCEData.calendar = 'standard'\n+            currNetCDFCEData.conventions = 'COARDS'\n+            # dimensions\n+            currNetCDFCEData.createDimension('time', None)\n+            currNetCDFCEData.createDimension('lat', len(LAT[:, 0]))\n+            currNetCDFCEData.createDimension('lon', len(LON[0, :]))\n+            # variables\n+            tempDims = ('time', 'lat', 'lon',)\n+            times = currNetCDFCEData.createVariable('time', 'f8', ('time',))\n+            times.units = 'hours since '+ str(timelist[t])[:-6]\n+            latitudes = currNetCDFCEData.createVariable('latitude', 'f8', ('lat',))\n+            longitudes = currNetCDFCEData.createVariable('longitude', 'f8', ('lon',))\n+            brightnesstemp = currNetCDFCEData.createVariable('brightnesstemp', 'i16', tempDims)\n+            brightnesstemp.units = 'Kelvin'\n+            # NETCDF data\n+            dates = [timelist[t] + timedelta(hours=0)]\n+            times[:] = date2num(dates, units=times.units)\n+            longitudes[:] = LON[0, :]\n+            longitudes.units = 'degrees_east'\n+            longitudes.long_name = 'Longitude'\n+\n+            latitudes[:] = LAT[:, 0]\n+            latitudes.units = 'degrees_north'\n+            latitudes.long_name = 'Latitude'\n+\n+            profTimes[2]+= time.time() - pin\n+            pin = time.time() #forth pin drop\n+\n+            profTimes[3]+= time.time() - pin\n+            pin = time.time() #fifth pin drop\n+\n+            #generate array of zeros for brightness temperature\n+            brightnesstemp1 = ma.zeros((1, len(latitudes), len(longitudes))).astype('int16')\n+            #-----------End most of NETCDF file stuff ------------------------------------\n+\n+            #if other dataset (TRMM) assumed to be a precipitation dataset was entered\n+            if TRMMdirName:\n+                pass\n+            #     #------------------TRMM stuff -------------------------------------------------\n+            #     fileDate = ((str(timelist[t])).replace(' ', '')[:-8]).replace('-', '')\n+            #     fileHr1 = (str(timelist[t])).replace(' ', '')[-8:-6]\n+            #\n+            #     if int(fileHr1) % temporalRes == 0:\n+            #         fileHr = fileHr1\n+            #     else:\n+            #         fileHr = (int(fileHr1) / temporalRes) * temporalRes\n+            #     if fileHr < 10:\n+            #         fileHr = '0'+str(fileHr)\n+            #     else:\n+            #         str(fileHr)\n+            #\n+            #     #open TRMM file for the resolution info and to create the appropriate sized grid\n+            #     TRMMfileName = TRMMdirName + '/3B42.' + fileDate + '.' + str(fileHr) + '.7A.nc'\n+            #\n+            #     TRMMData = Dataset(TRMMfileName, 'r', format='NETCDF4')\n+            #     precipRate = TRMMData.variables['pcp'][:, :, :]\n+            #     latsrawTRMMData = TRMMData.variables['latitude'][:]\n+            #     lonsrawTRMMData = TRMMData.variables['longitude'][:]\n+            #     lonsrawTRMMData[lonsrawTRMMData > 180] = lonsrawTRMMData[lonsrawTRMMData > 180] - 360.\n+            #     LONTRMMOld, LATTRMMOld = np.meshgrid(lonsrawTRMMData, latsrawTRMMData)\n+            #\n+            #\n+            #     # nygrdTRMM = len(LATTRMM[:, 0])\n+            #     # nxgrdTRMM = len(LONTRMM[0, :])\n+            #     precipRateMaskedOld = ma.masked_array(precipRate, mask=(precipRate < 0.0))\n+            #     #---------regrid the TRMM data to the MERG dataset ----------------------------------\n+            #     #regrid using the do_regrid stuff from the Apache OCW\n+            #     #regriddedTRMMOld = ma.zeros((0, nygrd, nxgrd))\n+            #     regriddedTRMMOld = utils.do_regrid(precipRateMaskedOld[0, :, :], LATTRMMOld, LONTRMMOld, LAT, LON, order=1,\\\n+            #                     mdi=-999999999)\n+            #     #----------------------------------------------------------------------------------\n+            #\n+            #     # #get the lat/lon info from cloudElement\n+            #     #get the lat/lon info from the file\n+            #     #latCEStart = LAT[0][0]\n+            #     #latCEEnd = LAT[-1][0]\n+            #     #lonCEStart = LON[0][0]\n+            #     #lonCEEnd = LON[0][-1]\n+            #\n+            #     #get the lat/lon info for TRMM data (different resolution)\n+            #     # latStartT = utils.find_nearest(latsrawTRMMData, latCEStart)\n+            #     # latEndT = utils.find_nearest(latsrawTRMMData, latCEEnd)\n+            #     # lonStartT = utils.find_nearest(lonsrawTRMMData, lonCEStart)\n+            #     # lonEndT = utils.find_nearest(lonsrawTRMMData, lonCEEnd)\n+            #     # Unused since CEPrecipRate isn't used and these are just inputs\n+            #     # latStartIndex = np.where(latsrawTRMMData == latStartT)\n+            #     # latEndIndex = np.where(latsrawTRMMData == latEndT)\n+            #     # lonStartIndex = np.where(lonsrawTRMMData == lonStartT)\n+            #     # lonEndIndex = np.where(lonsrawTRMMData == lonEndT)\n+            #\n+            #     #get the relevant TRMM info\n+            #     # Unused Variable\n+            #     # CEprecipRate = precipRate[:, (latStartIndex[0][0]-1):latEndIndex[0][0], \\\n+            #     #        (lonStartIndex[0][0]-1):lonEndIndex[0][0]]\n+            #     TRMMData.close()\n+\n+                #MINI UNIT TEST of change that pulls the above if statement out of the loop\n+                # try:\n+                #     assert(np.array_equal(regriddedTRMM,regriddedTRMMOld))\n+                # except:\n+                #     print(\"Not Equal\\n\")\n+\n+\n+                profTimes[4]+= time.time() - pin\n+                pin = time.time() #sixth pin drop\n+\n+                # ------ NETCDF File info for writing TRMM CE rainfall ------------------------------------\n+                thisFileName = MAIN_DIRECTORY+'/TRMMnetcdfCEs/TRMM' + (str(timelist[t])).replace(' ', '_') + ceUniqueID +'.nc'\n+                currNetCDFTRMMData = Dataset(thisFileName, 'w', format='NETCDF4')\n+                currNetCDFTRMMData.description = 'Cloud Element ' + ceUniqueID + ' precipitation data'\n+                currNetCDFTRMMData.calendar = 'standard'\n+                currNetCDFTRMMData.conventions = 'COARDS'\n+                # dimensions\n+                currNetCDFTRMMData.createDimension('time', None)\n+                currNetCDFTRMMData.createDimension('lat', len(LAT[:,0]))\n+                currNetCDFTRMMData.createDimension('lon', len(LON[0,:]))\n+\n+                # variables\n+                TRMMprecip = ('time', 'lat', 'lon',)\n+                times = currNetCDFTRMMData.createVariable('time', 'f8', ('time',))\n+                times.units = 'hours since '+ str(timelist[t])[:-6]\n+                latitude = currNetCDFTRMMData.createVariable('latitude', 'f8', ('lat',))\n+                longitude = currNetCDFTRMMData.createVariable('longitude', 'f8', ('lon',))\n+                rainFallacc = currNetCDFTRMMData.createVariable('precipitation_Accumulation', 'f8', TRMMprecip)\n+                rainFallacc.units = 'mm'\n+\n+                longitude[:] = LON[0,:]\n+                longitude.units = 'degrees_east'\n+                longitude.long_name = 'Longitude'\n+\n+                latitude[:] = LAT[:,0]\n+                latitude.units = 'degrees_north'\n+                latitude.long_name = 'Latitude'\n+\n+\n+\n+            finalCETRMMvalues = ma.zeros((brightnesstemp.shape))\n+            #-----------End most of NETCDF file stuff ------------------------------------\n+\n+            #populate cloudElementLatLons by unpacking the original values from loc to get the actual value for lat and lon\n+            #TODO: KDW - too dirty... play with itertools.izip or zip and the enumerate with this\n+            #           as cloudElement is masked\n+            #trialVar = ma.zeros((brightnesstemp1.shape))\n+            #cloudElementLatLonsOld = [];\n+            #brightnesstemp1Old = ma.zeros((1, len(latitudes), len(longitudes))).astype('int16')\n+            #finalCETRMMvaluesOld = ma.zeros((brightnesstemp.shape))\n+            #ceTRMMListOld = []\n+            #for index, value in np.ndenumerate(cloudElement):\n+                #if value != 0:\n+                    #pass\n+                    #latIndex, lonIndex = index\n+                    #latLonTuple = (cloudElementLat[latIndex], cloudElementLon[lonIndex], value)\n+\n+                    #generate the comma separated file for GIS\n+                    #cloudElementLatLonsOld.append(latLonTuple)\n+\n+                    #temp data for CE NETCDF file\n+                    #brightnesstemp1Old[0, int(np.where(LAT[:,0] == cloudElementLat[latIndex])[0]), \\\n+                    #        int(np.where(LON[0,:] == cloudElementLon[lonIndex])[0])] = value\n+                    #trialVar[0,int(loc[0].start)+latIndex,int(loc[1].start)+lonIndex] = value\n+\n+                    #if TRMMdirName:\n+                        #finalCETRMMvaluesOld[0, int(np.where(LAT[:,0] == cloudElementLat[latIndex])[0]), \\\n+                        #    int(np.where(LON[0,:] == cloudElementLon[lonIndex])[0])] = \\\n+                        #    regriddedTRMM[int(np.where(LAT[:,0] == cloudElementLat[latIndex])[0]), \\\n+                        #    int(np.where(LON[0,:] == cloudElementLon[lonIndex])[0])]\n+                        #ceTRMMListOld.append((cloudElementLat[latIndex], cloudElementLon[lonIndex], \\\n+                        #    finalCETRMMvalues[0,cloudElementLat[latIndex], cloudElementLon[lonIndex]]))\n+            \n+            #***GABE'S ADDITIONS***\n+            #This replaces the loop computation of cloudElementLatLons - doesn't match exactly, but when I looked in the\n+            #orignal variable it had two entries at the end which had values of 0, which is not supposed to happen\n+            cloudElementNonZeros = cloudElement.nonzero()\n+            passingSpots = np.transpose(cloudElementNonZeros)\n+            cloudElementLatLons = np.zeros((passingSpots.shape[0],3))\n+            cloudElementLatLons[:,0] = cloudElementLat[passingSpots[:,0]]\n+            cloudElementLatLons[:,1] = cloudElementLon[passingSpots[:,1]]\n+            cloudElementLatLons[:,2] = cloudElement[cloudElementNonZeros]\n+            cloudElementLatLons = cloudElementLatLons.tolist()\n+            #Mini unit test of this version as compared to the loop version, uncomment out code\n+            # that computes it the old way to use this test\n+            #i = 0\n+            #for tup in cloudElementLatLons:\n+            #    assert(tup==list(cloudElementLatLonsOld[i]))\n+            #    i+=1\n+\n+\n+\n+            #This replaces the loop computation of brightnesstemp1, commented lines are a test\n+            brightnesstemp1[0,loc[0],loc[1]] = cloudElement\n+            #Mini unit test comparing this to loop version. To use, uncomment the loop computation\n+            #assert(np.array_equal(brightnesstemp1,brightnesstemp1Old))\n+\n+            \n+            #This replaces the loop computation of finalCETRMMvalues and ceTRMM, tests commented\n+            if TRMMdirName:","path":"code/mccSearch.py","position":734,"original_position":734,"commit_id":"7e67f128d88dec9e1f426d9fd5804222276a8161","original_commit_id":"7e67f128d88dec9e1f426d9fd5804222276a8161","user":{"login":"kwhitehall","id":7198635,"avatar_url":"https://avatars.githubusercontent.com/u/7198635?v=3","gravatar_id":"","url":"https://api.github.com/users/kwhitehall","html_url":"https://github.com/kwhitehall","followers_url":"https://api.github.com/users/kwhitehall/followers","following_url":"https://api.github.com/users/kwhitehall/following{/other_user}","gists_url":"https://api.github.com/users/kwhitehall/gists{/gist_id}","starred_url":"https://api.github.com/users/kwhitehall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kwhitehall/subscriptions","organizations_url":"https://api.github.com/users/kwhitehall/orgs","repos_url":"https://api.github.com/users/kwhitehall/repos","events_url":"https://api.github.com/users/kwhitehall/events{/privacy}","received_events_url":"https://api.github.com/users/kwhitehall/received_events","type":"User","site_admin":false},"body":"These \"if TRMMdirName:\" statements should be as best as possible made into one. ","created_at":"2015-11-30T01:23:22Z","updated_at":"2015-11-30T01:23:22Z","html_url":"https://github.com/kwhitehall/grab-tag-graph/pull/65#discussion_r46102692","pull_request_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/65","_links":{"self":{"href":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/comments/46102692"},"html":{"href":"https://github.com/kwhitehall/grab-tag-graph/pull/65#discussion_r46102692"},"pull_request":{"href":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/65"}}},"pull_request":{"url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/65","id":48672923,"html_url":"https://github.com/kwhitehall/grab-tag-graph/pull/65","diff_url":"https://github.com/kwhitehall/grab-tag-graph/pull/65.diff","patch_url":"https://github.com/kwhitehall/grab-tag-graph/pull/65.patch","issue_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/issues/65","number":65,"state":"open","locked":false,"title":"Grab tag graph 47 - Not quite clean. In progress.","user":{"login":"meldefon","id":3287534,"avatar_url":"https://avatars.githubusercontent.com/u/3287534?v=3","gravatar_id":"","url":"https://api.github.com/users/meldefon","html_url":"https://github.com/meldefon","followers_url":"https://api.github.com/users/meldefon/followers","following_url":"https://api.github.com/users/meldefon/following{/other_user}","gists_url":"https://api.github.com/users/meldefon/gists{/gist_id}","starred_url":"https://api.github.com/users/meldefon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/meldefon/subscriptions","organizations_url":"https://api.github.com/users/meldefon/orgs","repos_url":"https://api.github.com/users/meldefon/repos","events_url":"https://api.github.com/users/meldefon/events{/privacy}","received_events_url":"https://api.github.com/users/meldefon/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-10-25T06:20:19Z","updated_at":"2015-11-30T01:23:22Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7dae9e9371ca6730bc7aa4f395567565ee854a79","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/65/commits","review_comments_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/65/comments","review_comment_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/issues/65/comments","statuses_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/statuses/7e67f128d88dec9e1f426d9fd5804222276a8161","head":{"label":"meldefon:grab-tag-graph-47","ref":"grab-tag-graph-47","sha":"7e67f128d88dec9e1f426d9fd5804222276a8161","user":{"login":"meldefon","id":3287534,"avatar_url":"https://avatars.githubusercontent.com/u/3287534?v=3","gravatar_id":"","url":"https://api.github.com/users/meldefon","html_url":"https://github.com/meldefon","followers_url":"https://api.github.com/users/meldefon/followers","following_url":"https://api.github.com/users/meldefon/following{/other_user}","gists_url":"https://api.github.com/users/meldefon/gists{/gist_id}","starred_url":"https://api.github.com/users/meldefon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/meldefon/subscriptions","organizations_url":"https://api.github.com/users/meldefon/orgs","repos_url":"https://api.github.com/users/meldefon/repos","events_url":"https://api.github.com/users/meldefon/events{/privacy}","received_events_url":"https://api.github.com/users/meldefon/received_events","type":"User","site_admin":false},"repo":{"id":42146605,"name":"grab-tag-graph","full_name":"meldefon/grab-tag-graph","owner":{"login":"meldefon","id":3287534,"avatar_url":"https://avatars.githubusercontent.com/u/3287534?v=3","gravatar_id":"","url":"https://api.github.com/users/meldefon","html_url":"https://github.com/meldefon","followers_url":"https://api.github.com/users/meldefon/followers","following_url":"https://api.github.com/users/meldefon/following{/other_user}","gists_url":"https://api.github.com/users/meldefon/gists{/gist_id}","starred_url":"https://api.github.com/users/meldefon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/meldefon/subscriptions","organizations_url":"https://api.github.com/users/meldefon/orgs","repos_url":"https://api.github.com/users/meldefon/repos","events_url":"https://api.github.com/users/meldefon/events{/privacy}","received_events_url":"https://api.github.com/users/meldefon/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/meldefon/grab-tag-graph","description":"Grab 'em, Tag 'em, Graph 'em (GTG) algorithm","fork":true,"url":"https://api.github.com/repos/meldefon/grab-tag-graph","forks_url":"https://api.github.com/repos/meldefon/grab-tag-graph/forks","keys_url":"https://api.github.com/repos/meldefon/grab-tag-graph/keys{/key_id}","collaborators_url":"https://api.github.com/repos/meldefon/grab-tag-graph/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/meldefon/grab-tag-graph/teams","hooks_url":"https://api.github.com/repos/meldefon/grab-tag-graph/hooks","issue_events_url":"https://api.github.com/repos/meldefon/grab-tag-graph/issues/events{/number}","events_url":"https://api.github.com/repos/meldefon/grab-tag-graph/events","assignees_url":"https://api.github.com/repos/meldefon/grab-tag-graph/assignees{/user}","branches_url":"https://api.github.com/repos/meldefon/grab-tag-graph/branches{/branch}","tags_url":"https://api.github.com/repos/meldefon/grab-tag-graph/tags","blobs_url":"https://api.github.com/repos/meldefon/grab-tag-graph/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/meldefon/grab-tag-graph/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/meldefon/grab-tag-graph/git/refs{/sha}","trees_url":"https://api.github.com/repos/meldefon/grab-tag-graph/git/trees{/sha}","statuses_url":"https://api.github.com/repos/meldefon/grab-tag-graph/statuses/{sha}","languages_url":"https://api.github.com/repos/meldefon/grab-tag-graph/languages","stargazers_url":"https://api.github.com/repos/meldefon/grab-tag-graph/stargazers","contributors_url":"https://api.github.com/repos/meldefon/grab-tag-graph/contributors","subscribers_url":"https://api.github.com/repos/meldefon/grab-tag-graph/subscribers","subscription_url":"https://api.github.com/repos/meldefon/grab-tag-graph/subscription","commits_url":"https://api.github.com/repos/meldefon/grab-tag-graph/commits{/sha}","git_commits_url":"https://api.github.com/repos/meldefon/grab-tag-graph/git/commits{/sha}","comments_url":"https://api.github.com/repos/meldefon/grab-tag-graph/comments{/number}","issue_comment_url":"https://api.github.com/repos/meldefon/grab-tag-graph/issues/comments{/number}","contents_url":"https://api.github.com/repos/meldefon/grab-tag-graph/contents/{+path}","compare_url":"https://api.github.com/repos/meldefon/grab-tag-graph/compare/{base}...{head}","merges_url":"https://api.github.com/repos/meldefon/grab-tag-graph/merges","archive_url":"https://api.github.com/repos/meldefon/grab-tag-graph/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/meldefon/grab-tag-graph/downloads","issues_url":"https://api.github.com/repos/meldefon/grab-tag-graph/issues{/number}","pulls_url":"https://api.github.com/repos/meldefon/grab-tag-graph/pulls{/number}","milestones_url":"https://api.github.com/repos/meldefon/grab-tag-graph/milestones{/number}","notifications_url":"https://api.github.com/repos/meldefon/grab-tag-graph/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/meldefon/grab-tag-graph/labels{/name}","releases_url":"https://api.github.com/repos/meldefon/grab-tag-graph/releases{/id}","created_at":"2015-09-09T00:33:04Z","updated_at":"2015-09-09T00:33:04Z","pushed_at":"2015-11-13T16:44:19Z","git_url":"git://github.com/meldefon/grab-tag-graph.git","ssh_url":"git@github.com:meldefon/grab-tag-graph.git","clone_url":"https://github.com/meldefon/grab-tag-graph.git","svn_url":"https://github.com/meldefon/grab-tag-graph","homepage":"","size":11959,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"kwhitehall:master","ref":"master","sha":"a5a87b7ebf021f3149c7971b85a1e893856aa6bf","user":{"login":"kwhitehall","id":7198635,"avatar_url":"https://avatars.githubusercontent.com/u/7198635?v=3","gravatar_id":"","url":"https://api.github.com/users/kwhitehall","html_url":"https://github.com/kwhitehall","followers_url":"https://api.github.com/users/kwhitehall/followers","following_url":"https://api.github.com/users/kwhitehall/following{/other_user}","gists_url":"https://api.github.com/users/kwhitehall/gists{/gist_id}","starred_url":"https://api.github.com/users/kwhitehall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kwhitehall/subscriptions","organizations_url":"https://api.github.com/users/kwhitehall/orgs","repos_url":"https://api.github.com/users/kwhitehall/repos","events_url":"https://api.github.com/users/kwhitehall/events{/privacy}","received_events_url":"https://api.github.com/users/kwhitehall/received_events","type":"User","site_admin":false},"repo":{"id":18535298,"name":"grab-tag-graph","full_name":"kwhitehall/grab-tag-graph","owner":{"login":"kwhitehall","id":7198635,"avatar_url":"https://avatars.githubusercontent.com/u/7198635?v=3","gravatar_id":"","url":"https://api.github.com/users/kwhitehall","html_url":"https://github.com/kwhitehall","followers_url":"https://api.github.com/users/kwhitehall/followers","following_url":"https://api.github.com/users/kwhitehall/following{/other_user}","gists_url":"https://api.github.com/users/kwhitehall/gists{/gist_id}","starred_url":"https://api.github.com/users/kwhitehall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kwhitehall/subscriptions","organizations_url":"https://api.github.com/users/kwhitehall/orgs","repos_url":"https://api.github.com/users/kwhitehall/repos","events_url":"https://api.github.com/users/kwhitehall/events{/privacy}","received_events_url":"https://api.github.com/users/kwhitehall/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/kwhitehall/grab-tag-graph","description":"Grab 'em, Tag 'em, Graph 'em (GTG) algorithm","fork":false,"url":"https://api.github.com/repos/kwhitehall/grab-tag-graph","forks_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/forks","keys_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/teams","hooks_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/hooks","issue_events_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/issues/events{/number}","events_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/events","assignees_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/assignees{/user}","branches_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/branches{/branch}","tags_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/tags","blobs_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/git/refs{/sha}","trees_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/statuses/{sha}","languages_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/languages","stargazers_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/stargazers","contributors_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/contributors","subscribers_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/subscribers","subscription_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/subscription","commits_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/commits{/sha}","git_commits_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/git/commits{/sha}","comments_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/comments{/number}","issue_comment_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/issues/comments{/number}","contents_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/contents/{+path}","compare_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/merges","archive_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/downloads","issues_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/issues{/number}","pulls_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls{/number}","milestones_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/milestones{/number}","notifications_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/labels{/name}","releases_url":"https://api.github.com/repos/kwhitehall/grab-tag-graph/releases{/id}","created_at":"2014-04-07T21:35:05Z","updated_at":"2015-05-04T14:42:35Z","pushed_at":"2015-11-27T20:30:20Z","git_url":"git://github.com/kwhitehall/grab-tag-graph.git","ssh_url":"git@github.com:kwhitehall/grab-tag-graph.git","clone_url":"https://github.com/kwhitehall/grab-tag-graph.git","svn_url":"https://github.com/kwhitehall/grab-tag-graph","homepage":"","size":22951,"stargazers_count":2,"watchers_count":2,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"open_issues_count":18,"forks":7,"open_issues":18,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/65"},"html":{"href":"https://github.com/kwhitehall/grab-tag-graph/pull/65"},"issue":{"href":"https://api.github.com/repos/kwhitehall/grab-tag-graph/issues/65"},"comments":{"href":"https://api.github.com/repos/kwhitehall/grab-tag-graph/issues/65/comments"},"review_comments":{"href":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/65/comments"},"review_comment":{"href":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kwhitehall/grab-tag-graph/pulls/65/commits"},"statuses":{"href":"https://api.github.com/repos/kwhitehall/grab-tag-graph/statuses/7e67f128d88dec9e1f426d9fd5804222276a8161"}}}}