def run(inputFolder, srid, dbName, dbPass, dbUser, dbHost, dbPort, numberProcs): # Make connection connectionString = utils.getConnectString(dbName, dbUser, dbPass, dbHost, dbPort) connection = psycopg2.connect(connectionString) cursor = connection.cursor() # Make it absolute path inputFolder = os.path.abspath(inputFolder) # Create table if it does not exist cursor.execute('CREATE TABLE ' + utils.DB_TABLE_RAW + ' (filepath text, numberpoints integer, minz double precision, maxz double precision, geom public.geometry(Geometry, %s))', [srid, ]) connection.commit() connection.close() # Create queues for the distributed processing tasksQueue = multiprocessing.Queue() # The queue of tasks (inputFiles) resultsQueue = multiprocessing.Queue() # The queue of results inputFiles = utils.getFiles(inputFolder, recursive=True) numFiles = len(inputFiles) # Add tasks/inputFiles for i in range(numFiles): tasksQueue.put(inputFiles[i]) for i in range(numberProcs): #we add as many None jobs as numberProcs to tell them to terminate (queue is FIFO) tasksQueue.put(None) processes = [] # We start numberProcs users processes for i in range(numberProcs): processes.append(multiprocessing.Process(target=runProcess, args=(i, tasksQueue, resultsQueue, connectionString, srid))) processes[-1].start() # Get all the results (actually we do not need the returned values) for i in range(numFiles): resultsQueue.get() print 'Completed %d of %d (%.02f%%)' % (i+1, numFiles, 100. * float(i+1) / float(numFiles)) # wait for all users to finish their execution for i in range(numberProcs): processes[i].join() # Create an index for the geometries connection = psycopg2.connect(connectionString) cursor = connection.cursor() cursor.execute('CREATE INDEX ' + utils.DB_TABLE_RAW + '_geom ON ' + utils.DB_TABLE_RAW + ' USING GIST ( geom )') connection.commit() connection.close()
def run(srid, userMail, level, bBox, dbName, dbPass, dbUser, dbHost, dbPort, baseURL, basePath): message = '' statusOk = True outputAbsPath = None timeStamp = datetime.datetime.now().strftime("%H_%M_%S_%f") try: # Get the extent of the bounding boxes anc check they are float values (minX,minY,maxX,maxY) = bBox.replace('"','').replace("'","").split(' ') for v in (minX,minY,maxX,maxY): float(v) # Make connection connectionString = utils.getConnectString(dbName, dbUser, dbPass, dbHost, dbPort) connection = psycopg2.connect(connectionString) cursor = connection.cursor() cursor.execute('SELECT max(level) FROM ' + utils.DB_TABLE_POTREE) maxLevelPotree = cursor.fetchone()[0] # print level,maxLevelPotree if level != '': if int(level) <= maxLevelPotree: dbTable = utils.DB_TABLE_POTREE else: dbTable = utils.DB_TABLE_RAW print 'Specified level (' + level + ') is not available in the potree data. Using raw data' else: dbTable = utils.DB_TABLE_RAW estimatedNumPoints = None if dbTable == utils.DB_TABLE_POTREE: cursor.execute("""SELECT floor(sum(numberpoints * (st_area(st_intersection(geom, qgeom)) / st_area(geom)))) FROM """ + utils.DB_TABLE_RAW + """, (SELECT ST_SetSRID(ST_MakeBox2D(ST_Point(""" + minX + """, """ + minY + """),ST_Point(""" + maxX + """, """ + maxY + """)), """ + str(srid) + """) as qgeom) AS B WHERE geom && qgeom AND st_area(geom) != 0""") estimatedNumPoints = cursor.fetchone()[0] connection.close() outputFileName = '%s_%s_%s_%s_%s.laz' % (timeStamp,minX,minY,maxX,maxY) outputAbsPath = basePath + '/' + outputFileName if os.path.isfile(outputAbsPath): raise Exception('The file already existed!') else: query = 'SELECT filepath FROM ' + dbTable + ' where ST_SetSRID(ST_MakeBox2D(ST_Point(' + minX + ', ' + minY + '),ST_Point(' + maxX + ', ' + maxY + ')), ' + str(srid) + ') && geom' if dbTable == utils.DB_TABLE_POTREE: query += ' AND level = ' + str(level) inputList = outputAbsPath + '.list' connectionStringCommandLine = utils.getConnectString(dbName, dbUser, dbPass, dbHost, dbPort, cline = True) precommand = 'psql ' + connectionStringCommandLine + ' -t -A -c "' + query + '" > ' + inputList print precommand os.system(precommand) command = 'lasmerge -lof ' + inputList + ' -inside ' + minX + ' ' + minY + ' ' + maxX + ' ' + maxY + ' -merged -o ' + outputAbsPath print command os.system(command) except: statusOk = False message = 'There was some error in the file generation: ' + traceback.format_exc() if outputAbsPath != None and os.path.isfile(outputAbsPath) and statusOk: (count, _, _, _, _, _, _, _, _, _, _, _, _) = utils.getPCFileDetails(outputAbsPath) size = utils.getFileSize(outputAbsPath) approxStr = '' if dbTable == utils.DB_TABLE_POTREE: approxStr = """ Note that due to the large extent of your selected area only the """ + '%.4f' % (float(count)/float(estimatedNumPoints)) + """ %% of the points are stored. """ content = """Subject: Data is ready Your selected data is ready. """ + str(count) + """ points were selected and stored in """ + outputAbsPath.replace(basePath, baseURL) + """ with a size of """ + str(size) + """ MB. """ + approxStr + """ Please download your data asap. This data will be deleted after 24 hours. To visualize LAZ data there are a few alternatives. For desktop-based simple visualization you can use LAStools lasview. For web-based visualization you can use http://plas.io/ """ else: content = """Subject: Data is NOT ready Your selection could not be stored. Sorry for the inconveniences.""" content += message mailFileAbsPath = timeStamp + '_error.mail' mailFile = open(mailFileAbsPath, 'w') mailFile.write(content) mailFile.close() os.system('sendmail ' + userMail + ' < ' + mailFileAbsPath)