def runProcess(processIndex, tasksQueue, resultsQueue, minX, minY, maxX, maxY, outputFolder, tempFolder, axisTiles):
    kill_received = False
    while not kill_received:
        inputFile = None
        try:
            # This call will patiently wait until new job is available
            inputFile = tasksQueue.get()
        except:
            # if there is an error we will quit
            kill_received = True
        if inputFile == None:
            # If we receive a None job, it means we can stop
            kill_received = True
        else:
            # Get number of points and BBOX of this file
            (fCount, fMinX, fMinY, _, fMaxX, fMaxY, _, _, _, _, _, _, _) = utils.getPCFileDetails(inputFile)
            print ('Processing', os.path.basename(inputFile), fCount, fMinX, fMinY, fMaxX, fMaxY)
            # For the four vertices of the BBOX we get in which tile they should go
            posMinXMinY = getTileIndex(fMinX, fMinY, minX, minY, maxX, maxY, axisTiles)
            posMinXMaxY = getTileIndex(fMinX, fMaxY, minX, minY, maxX, maxY, axisTiles)
            posMaxXMinY = getTileIndex(fMaxX, fMinY, minX, minY, maxX, maxY, axisTiles)
            posMaxXMaxY = getTileIndex(fMaxX, fMaxY, minX, minY, maxX, maxY, axisTiles)

            if (posMinXMinY == posMinXMaxY) and (posMinXMinY == posMaxXMinY) and (posMinXMinY == posMaxXMaxY):
                # If they are the same the whole file can be directly copied to the tile
                tileFolder = outputFolder + '/' + getTileName(*posMinXMinY)
                if not os.path.isdir(tileFolder):
                    utils.shellExecute('mkdir -p ' + tileFolder)
                utils.shellExecute('cp ' + inputFile + ' ' + tileFolder)
            else:
                # If not, we run PDAL gridder to split the file in pieces that can go to the tiles
                tGCount = runPDALSplitter(processIndex, inputFile, outputFolder, tempFolder, minX, minY, maxX, maxY, axisTiles)
                if tGCount != fCount:
                    print ('WARNING: split version of ', inputFile, ' does not have same number of points (', tGCount, 'expected', fCount, ')')
            resultsQueue.put((processIndex, inputFile, fCount))
Пример #2
0
def runPDALSplitter(processIndex, inputFile, outputFolder, tempFolder, minX,
                    minY, maxX, maxY, axisTiles):
    pTempFolder = tempFolder + '/' + str(processIndex)
    if not os.path.isdir(pTempFolder):
        utils.shellExecute('mkdir -p ' + pTempFolder)

    # Get the lenght required by the PDAL split filter in order to get "squared" tiles
    lengthPDAL = (maxX - minX) / float(axisTiles)

    utils.shellExecute('pdal split -i ' + inputFile + ' -o ' + pTempFolder +
                       '/' + os.path.basename(inputFile) + ' --origin_x ' +
                       str(minX) + ' --origin_y ' + str(minY) + ' --length ' +
                       str(lengthPDAL))
    tGCount = 0
    for gFile in os.listdir(pTempFolder):
        (gCount, gFileMinX, gFileMinY, _, gFileMaxX, gFileMaxY, _, _, _, _, _,
         _, _) = utils.getPCFileDetails(pTempFolder + '/' + gFile)
        # This tile should match with some tile. Let's use the central point to see which one
        pX = gFileMinX + ((gFileMaxX - gFileMinX) / 2.)
        pY = gFileMinY + ((gFileMaxY - gFileMinY) / 2.)
        tileFolder = outputFolder + '/' + getTileName(
            *getTileIndex(pX, pY, minX, minY, maxX, maxY, axisTiles))
        if not os.path.isdir(tileFolder):
            utils.shellExecute('mkdir -p ' + tileFolder)
        utils.shellExecute('mv ' + pTempFolder + '/' + gFile + ' ' +
                           tileFolder + '/' + gFile)
        tGCount += gCount
    return tGCount
Пример #3
0
def runProcess(processIndex, tasksQueue, resultsQueue, minX, minY, maxX, maxY,
               outputFolder, tempFolder, axisTiles):
    kill_received = False
    while not kill_received:
        inputFile = None
        try:
            # This call will patiently wait until new job is available
            inputFile = tasksQueue.get()
        except:
            # if there is an error we will quit
            kill_received = True
        if inputFile == None:
            # If we receive a None job, it means we can stop
            kill_received = True
        else:
            # Get number of points and BBOX of this file
            (fCount, fMinX, fMinY, _, fMaxX, fMaxY, _, _, _, _, _, _,
             _) = utils.getPCFileDetails(inputFile)
            print('Processing', os.path.basename(inputFile), fCount, fMinX,
                  fMinY, fMaxX, fMaxY)
            # For the four vertices of the BBOX we get in which tile they should go
            posMinXMinY = getTileIndex(fMinX, fMinY, minX, minY, maxX, maxY,
                                       axisTiles)
            posMinXMaxY = getTileIndex(fMinX, fMaxY, minX, minY, maxX, maxY,
                                       axisTiles)
            posMaxXMinY = getTileIndex(fMaxX, fMinY, minX, minY, maxX, maxY,
                                       axisTiles)
            posMaxXMaxY = getTileIndex(fMaxX, fMaxY, minX, minY, maxX, maxY,
                                       axisTiles)

            if (posMinXMinY
                    == posMinXMaxY) and (posMinXMinY
                                         == posMaxXMinY) and (posMinXMinY
                                                              == posMaxXMaxY):
                # If they are the same the whole file can be directly copied to the tile
                tileFolder = outputFolder + '/' + getTileName(*posMinXMinY)
                if not os.path.isdir(tileFolder):
                    utils.shellExecute('mkdir -p ' + tileFolder)
                utils.shellExecute('cp ' + inputFile + ' ' + tileFolder)
            else:
                # If not, we run PDAL gridder to split the file in pieces that can go to the tiles
                tGCount = runPDALSplitter(processIndex, inputFile,
                                          outputFolder, tempFolder, minX, minY,
                                          maxX, maxY, axisTiles)
                if tGCount != fCount:
                    print('WARNING: split version of ', inputFile,
                          ' does not have same number of points (', tGCount,
                          'expected', fCount, ')')
            resultsQueue.put((processIndex, inputFile, fCount))
Пример #4
0
def run(inputFolder, outputFolder, runMode, useLink, numberProcs):
    # Check input parameters
    if not os.path.isdir(inputFolder):
        raise Exception('Error: Input folder does not exist!')
    if os.path.isfile(outputFolder):
        raise Exception('Error: There is a file with the same name as the output folder. Please, delete it!')
    elif os.path.isdir(outputFolder) and os.listdir(outputFolder):
        raise Exception('Error: Output folder exists and it is not empty. Please, delete the data in the output folder!')
    if runMode not in ('s','i','si','is'):
        raise Exception('Error: running mode must be s, i, or si')


    # Make it absolute path
    inputFolder = os.path.abspath(inputFolder)

    utils.shellExecute('mkdir -p ' + outputFolder)

    # Create queues for the distributed processing
    tasksQueue = multiprocessing.Queue() # The queue of tasks (inputFiles)
    resultsQueue = multiprocessing.Queue() # The queue of results

    tilesNames = os.listdir(inputFolder)
    if 'tiles.js' in tilesNames:
        tilesNames.remove('tiles.js')
        utils.shellExecute('cp ' + inputFolder + '/tiles.js ' + outputFolder+ '/tiles.js')

    numTiles = len(tilesNames)

    # Add tasks/inputFiles
    for i in range(numTiles):
        tasksQueue.put(inputFolder + '/' + tilesNames[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, outputFolder, runMode, useLink)))
        processes[-1].start()

    # Get all the results (actually we do not need the returned values)
    for i in range(numTiles):
        resultsQueue.get()
        print ('Completed %d of %d (%.02f%%)' % (i+1, numTiles, 100. * float(i+1) / float(numTiles)))
    # wait for all users to finish their execution
    for i in range(numberProcs):
        processes[i].join()
Пример #5
0
def runProcess(processIndex, tasksQueue, resultsQueue, outputFolder, runMode, useLink):
    kill_received = False
    while not kill_received:
        tileAbsPath = None
        try:
            # This call will patiently wait until new job is available
            tileAbsPath = tasksQueue.get()
        except:
            # if there is an error we will quit
            kill_received = True
        if tileAbsPath == None:
            # If we receive a None job, it means we can stop
            kill_received = True
        else:
            tileOutputFolder = outputFolder + '/' + os.path.basename(tileAbsPath)
            tileFilesAbsPaths = utils.getFiles(tileAbsPath, recursive = True)
            for i,tileFileAbsPath in enumerate(tileFilesAbsPaths):
                if (len(tileFilesAbsPaths) == 1) and os.path.isfile(tileAbsPath):
                    outputAbsPath = tileOutputFolder
                else:
                    if i  == 0:
                        os.system('mkdir -p ' + tileOutputFolder)
                    outputAbsPath = outputFolder + '/' + os.path.basename(tileAbsPath) + '/' + os.path.basename(tileFileAbsPath)
                commands = []
                if 's' in runMode:
                    cmd = os.environ["LASSORT"]
                    commands.append(cmd + ' -i ' + tileFileAbsPath + ' -o ' + outputAbsPath)
                else:
                    if useLink:
                        commands.append('ln -s ' + tileFileAbsPath + ' ' + outputAbsPath)
                    else:
                        commands.append('cp ' + tileFileAbsPath + ' ' + outputAbsPath)
                if 'i' in runMode:
                    commands.append('lasindex -i ' + outputAbsPath)
                for command in commands:
                    utils.shellExecute(command, True)
            resultsQueue.put((processIndex, tileAbsPath))
Пример #6
0
def run(inputFolderA, inputFolderB, outputFolder, moveFiles):
    # Check input parameters
    if (not os.path.isdir(inputFolderA)) or (not os.path.isdir(inputFolderB)):
        raise Exception('Error: Some of the input folder does not exist!')
    if os.path.isfile(outputFolder):
        raise Exception('Error: There is a file with the same name as the output folder. Please, delete it!')
    elif os.path.isdir(outputFolder) and os.listdir(outputFolder):
        raise Exception('Error: Output folder exists and it is not empty. Please, delete the data in the output folder!')

    # Make the paths absolute path
    inputFolderA = os.path.abspath(inputFolderA)
    inputFolderB = os.path.abspath(inputFolderB)
    outputFolder = os.path.abspath(outputFolder)

    if moveFiles:
        cmcommand = 'mv '
    else:
        cmcommand = 'cp -r '

    dataA = inputFolderA + '/data'
    dataB = inputFolderB + '/data'
    dataO = outputFolder + '/data'

    # Check if the octtrees have actual data (i.e. one folder with the root node)
    hasNodeA = os.listdir(dataA) == ['r',]
    hasNodeB = os.listdir(dataB) == ['r',]

    if hasNodeA or hasNodeB:
        utils.shellExecute('mkdir -p ' + outputFolder)
        if hasNodeA and hasNodeB:
            # If both Octrees have data we need to merge them
            # Create output cloud.js from joining the two input ones
            cloudJSA = inputFolderA + '/cloud.js'
            cloudJSB = inputFolderB + '/cloud.js'
            if not (os.path.isfile(cloudJSA)) or not (os.path.isfile(cloudJSB)):
                raise Exception('Error: Some cloud.js is missing!')
            # We also get the hierarchyStepSize
            hierarchyStepSize = createCloudJS(cloudJSA, cloudJSB, outputFolder + '/cloud.js')
            listFileRootA =  os.listdir(dataA + '/r')
            if 'r.las' in listFileRootA:
                extension = 'las'
            elif 'r.laz' in listFileRootA:
                extension = 'laz'
            else:
                raise Exception('Error: ' + __file__ + ' only compatible with las/laz format')
            joinNode('r', dataA + '/r', dataB + '/r', dataO + '/r', hierarchyStepSize, extension, cmcommand)
        elif hasA:
            utils.shellExecute(cmcommand + inputFolderA + '/* ' + outputFolder)
        else:
            utils.shellExecute(cmcommand + inputFolderB + '/* ' + outputFolder)
    else:
        print ('Nothing to merge: both Octtrees are empty!')
def runPDALSplitter(processIndex, inputFile, outputFolder, tempFolder, minX, minY, maxX, maxY, axisTiles):
    pTempFolder = tempFolder + '/' + str(processIndex)
    if not os.path.isdir(pTempFolder):
        utils.shellExecute('mkdir -p ' + pTempFolder)

    # Get the lenght required by the PDAL split filter in order to get "squared" tiles
    lengthPDAL = (maxX - minX) /  float(axisTiles)

    utils.shellExecute('pdal split -i ' + inputFile + ' -o ' + pTempFolder + '/' + os.path.basename(inputFile) + ' --origin_x=' + str(minX) + ' --origin_y=' + str(minY) + ' --length ' + str(lengthPDAL))
    tGCount = 0
    for gFile in os.listdir(pTempFolder):
        (gCount, gFileMinX, gFileMinY, _, gFileMaxX, gFileMaxY, _, _, _, _, _, _, _) = utils.getPCFileDetails(pTempFolder + '/' + gFile)
        # This tile should match with some tile. Let's use the central point to see which one
        pX = gFileMinX + ((gFileMaxX - gFileMinX) / 2.)
        pY = gFileMinY + ((gFileMaxY - gFileMinY) / 2.)
        tileFolder = outputFolder + '/' + getTileName(*getTileIndex(pX, pY, minX, minY, maxX, maxY, axisTiles))
        if not os.path.isdir(tileFolder):
            utils.shellExecute('mkdir -p ' + tileFolder)
        utils.shellExecute('mv ' + pTempFolder + '/' + gFile + ' ' + tileFolder + '/' + gFile)
        tGCount += gCount
    return tGCount
Пример #8
0
def main():
    args = argument_parser().parse_args()
    print ('Input folder: ', args.input)
    print ('Output folder: ', args.output)
    print ('Mode: ', args.mode)
    print ('Use Link: ', args.link)
    print ('Number of processes: ', args.proc)

    # Check the LAStools lassort.exe is installed
    if ('s' in args.mode):
        cmd = os.environ.get("LASSORT",None)
        if(not cmd or utils.shellExecute(cmd + ' -version').count('LAStools') == 0):
            raise Exception("LAStools lassort.exe is not found!. Please define LASSORT environment variable!")
    try:
        t0 = time.time()
        print ('Starting ' + os.path.basename(__file__) + '...')
        run(args.input, args.output, args.mode, args.link, args.proc)
        print ('Finished in %.2f seconds' % (time.time() - t0))
    except:
        print ('Execution failed!')
        print (traceback.format_exc())
Пример #9
0
def run(inputFolder, outputFolder, tempFolder, extent, numberTiles,
        numberProcs):
    # Check input parameters
    if not os.path.isdir(inputFolder) and not os.path.isfile(inputFolder):
        raise Exception('Error: Input folder does not exist!')
    if os.path.isfile(outputFolder):
        raise Exception(
            'Error: There is a file with the same name as the output folder. Please, delete it!'
        )
    elif os.path.isdir(outputFolder) and os.listdir(outputFolder):
        raise Exception(
            'Error: Output folder exists and it is not empty. Please, delete the data in the output folder!'
        )
    # Get the number of tiles per dimension (x and y)
    axisTiles = math.sqrt(numberTiles)
    if (not axisTiles.is_integer()) or (int(axisTiles) % 2):
        raise Exception(
            'Error: Number of tiles must be the square of number which is power of 2!'
        )
    axisTiles = int(axisTiles)

    # Create output and temporal folder
    utils.shellExecute('mkdir -p ' + outputFolder)
    utils.shellExecute('mkdir -p ' + tempFolder)

    (minX, minY, maxX, maxY) = extent.split(' ')
    minX = float(minX)
    minY = float(minY)
    maxX = float(maxX)
    maxY = float(maxY)

    if (maxX - minX) != (maxY - minY):
        raise Exception(
            'Error: Tiling requires that maxX-minX must be equal to maxY-minY!'
        )

    inputFiles = utils.getFiles(inputFolder, recursive=True)
    numInputFiles = len(inputFiles)
    print('%s contains %d files' % (inputFolder, numInputFiles))

    # Create queues for the distributed processing
    tasksQueue = multiprocessing.Queue()  # The queue of tasks (inputFiles)
    resultsQueue = multiprocessing.Queue()  # The queue of results

    # Add tasks/inputFiles
    for i in range(numInputFiles):
        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, minX,
                                          minY, maxX, maxY, outputFolder,
                                          tempFolder, axisTiles)))
        processes[-1].start()

    # Get all the results (actually we do not need the returned values)
    numPoints = 0
    for i in range(numInputFiles):
        (processIndex, inputFile, inputFileNumPoints) = resultsQueue.get()
        numPoints += inputFileNumPoints
        print(
            'Completed %d of %d (%.02f%%)' %
            (i + 1, numInputFiles, 100. * float(i + 1) / float(numInputFiles)))
    # wait for all users to finish their execution
    for i in range(numberProcs):
        processes[i].join()

    # Write the tile.js file with information about the tiles
    cFile = open(outputFolder + '/tiles.js', 'w')
    d = {}
    d["NumberPoints"] = numPoints
    d["numXTiles"] = axisTiles
    d["numYTiles"] = axisTiles
    d["boundingBox"] = {'lx': minX, 'ly': minY, 'ux': maxX, 'uy': maxY}
    cFile.write(json.dumps(d, indent=4, sort_keys=True))
    cFile.close()
Пример #10
0
def fixHeader(inputFile, outputFile):
    (_, minX, minY, minZ, maxX, maxY, maxZ, _, _, _, _, _, _) = utils.getPCFileDetails(inputFile)
    utils.shellExecute('lasinfo -i %s -nc -nv -nco -set_bounding_box %f %f %f %f %f %f' % (outputFile, minX, minY, minZ, maxX, maxY, maxZ))
Пример #11
0
def joinNode(node, nodeAbsPathA, nodeAbsPathB, nodeAbsPathO, hierarchyStepSize, extension, cmcommand):
    hrcFile = node + '.hrc'
    hrcA = None
    if os.path.isfile(nodeAbsPathA + '/' + hrcFile):
        # Check if there is data in this node in Octtree A (we check if the HRC file for this node exist)
        hrcA = utils.readHRC(nodeAbsPathA + '/' + hrcFile, hierarchyStepSize)
        if len(os.listdir(nodeAbsPathA)) == 2:
            hrcA[0][0] = utils.getPCFileDetails(nodeAbsPathA + '/' + node + extension)[0]
    hrcB = None
    if os.path.isfile(nodeAbsPathB + '/' + hrcFile):
        # Check if there is data in this node in Octtree B (we check if the HRC file for this node exist)
        hrcB = utils.readHRC(nodeAbsPathB + '/' + hrcFile, hierarchyStepSize)
        if len(os.listdir(nodeAbsPathB)) == 2:
            hrcB[0][0] = utils.getPCFileDetails(nodeAbsPathB + '/' + node + extension)[0]

    if hrcA != None and hrcB != None:
        utils.shellExecute('mkdir -p ' + nodeAbsPathO)
        # If both Octtrees A and B have data in this node we have to merge them
        hrcO = utils.initHRC(hierarchyStepSize)
        for level in range(hierarchyStepSize+2):
            numChildrenA = len(hrcA[level])
            numChildrenB = len(hrcB[level])
            numChildrenO = max((numChildrenA, numChildrenB))
            if level < (hierarchyStepSize+1):
                for i in range(numChildrenO):
                    hasNodeA = (i < numChildrenA) and (hrcA[level][i] > 0)
                    hasNodeB = (i < numChildrenB) and (hrcB[level][i] > 0)
                    (childNode, isFile) = utils.getNodeName(level, i, node, hierarchyStepSize, extension)
                    if hasNodeA and hasNodeB:
                        hrcO[level].append(hrcA[level][i] + hrcB[level][i])
                        #merge lAZ or folder (iteratively)
                        if isFile:
                            utils.shellExecute('lasmerge -i ' +  nodeAbsPathA + '/' + childNode + ' ' +  nodeAbsPathB + '/' + childNode + ' -o ' + nodeAbsPathO + '/' + childNode)
                            #We now need to set the header of the output file as the input files (lasmerge will have shrink it and we do not want that
                            fixHeader(nodeAbsPathA + '/' + childNode, nodeAbsPathO + '/' + childNode)
                        else:
                            joinNode(node + childNode, nodeAbsPathA + '/' + childNode, nodeAbsPathB + '/' + childNode, nodeAbsPathO + '/' + childNode, hierarchyStepSize, extension, cmcommand)
                    elif hasNodeA:
                        #mv / cp
                        hrcO[level].append(hrcA[level][i])
                        utils.shellExecute(cmcommand + nodeAbsPathA + '/' + childNode + ' ' + nodeAbsPathO + '/' + childNode)
                    elif hasNodeB:
                        #mv / cp
                        hrcO[level].append(hrcB[level][i])
                        utils.shellExecute(cmcommand + nodeAbsPathB + '/' + childNode + ' ' + nodeAbsPathO + '/' + childNode)
                    else:
                        hrcO[level].append(0)
            else:
                hrcO[level] = list(numpy.array(hrcA[level] + ([0]*(numChildrenO - numChildrenA))) + numpy.array(hrcB[level] + ([0]*(numChildrenO - numChildrenB))))
        # Write the HRC file
        utils.writeHRC(nodeAbsPathO + '/' + hrcFile, hierarchyStepSize, hrcO)
    elif hrcA != None:
        # Only Octtree A has data in this node. We can directly copy it to the output Octtree
        utils.shellExecute(cmcommand + nodeAbsPathA + ' ' + nodeAbsPathO)
    elif hrcB != None:
        # Only Octtree B has data in this node. We can directly copy it to the output Octtree
        utils.shellExecute(cmcommand + nodeAbsPathB + ' ' + nodeAbsPathO)
Пример #12
0
def fixHeader(inputFile, outputFile):
    (_, minX, minY, minZ, maxX, maxY, maxZ, _, _, _, _, _,
     _) = utils.getPCFileDetails(inputFile)
    utils.shellExecute(
        'lasinfo -i %s -nc -nv -nco -set_bounding_box %f %f %f %f %f %f' %
        (outputFile, minX, minY, minZ, maxX, maxY, maxZ))
Пример #13
0
def joinNode(node, nodeAbsPathA, nodeAbsPathB, nodeAbsPathO, hierarchyStepSize,
             extension, cmcommand):
    hrcFile = node + '.hrc'
    hrcA = None
    if os.path.isfile(nodeAbsPathA + '/' + hrcFile):
        # Check if there is data in this node in Octtree A (we check if the HRC file for this node exist)
        hrcA = utils.readHRC(nodeAbsPathA + '/' + hrcFile, hierarchyStepSize)
        if len(os.listdir(nodeAbsPathA)) == 2:
            hrcA[0][0] = utils.getPCFileDetails(nodeAbsPathA + '/' + node +
                                                extension)[0]
    hrcB = None
    if os.path.isfile(nodeAbsPathB + '/' + hrcFile):
        # Check if there is data in this node in Octtree B (we check if the HRC file for this node exist)
        hrcB = utils.readHRC(nodeAbsPathB + '/' + hrcFile, hierarchyStepSize)
        if len(os.listdir(nodeAbsPathB)) == 2:
            hrcB[0][0] = utils.getPCFileDetails(nodeAbsPathB + '/' + node +
                                                extension)[0]

    if hrcA != None and hrcB != None:
        utils.shellExecute('mkdir -p ' + nodeAbsPathO)
        # If both Octtrees A and B have data in this node we have to merge them
        hrcO = utils.initHRC(hierarchyStepSize)
        for level in range(hierarchyStepSize + 2):
            numChildrenA = len(hrcA[level])
            numChildrenB = len(hrcB[level])
            numChildrenO = max((numChildrenA, numChildrenB))
            if level < (hierarchyStepSize + 1):
                for i in range(numChildrenO):
                    hasNodeA = (i < numChildrenA) and (hrcA[level][i] > 0)
                    hasNodeB = (i < numChildrenB) and (hrcB[level][i] > 0)
                    (childNode,
                     isFile) = utils.getNodeName(level, i, node,
                                                 hierarchyStepSize, extension)
                    if hasNodeA and hasNodeB:
                        hrcO[level].append(hrcA[level][i] + hrcB[level][i])
                        #merge lAZ or folder (iteratively)
                        if isFile:
                            utils.shellExecute('lasmerge -i ' + nodeAbsPathA +
                                               '/' + childNode + ' ' +
                                               nodeAbsPathB + '/' + childNode +
                                               ' -o ' + nodeAbsPathO + '/' +
                                               childNode)
                            #We now need to set the header of the output file as the input files (lasmerge will have shrink it and we do not want that
                            fixHeader(nodeAbsPathA + '/' + childNode,
                                      nodeAbsPathO + '/' + childNode)
                        else:
                            joinNode(node + childNode,
                                     nodeAbsPathA + '/' + childNode,
                                     nodeAbsPathB + '/' + childNode,
                                     nodeAbsPathO + '/' + childNode,
                                     hierarchyStepSize, extension, cmcommand)
                    elif hasNodeA:
                        #mv / cp
                        hrcO[level].append(hrcA[level][i])
                        utils.shellExecute(cmcommand + nodeAbsPathA + '/' +
                                           childNode + ' ' + nodeAbsPathO +
                                           '/' + childNode)
                    elif hasNodeB:
                        #mv / cp
                        hrcO[level].append(hrcB[level][i])
                        utils.shellExecute(cmcommand + nodeAbsPathB + '/' +
                                           childNode + ' ' + nodeAbsPathO +
                                           '/' + childNode)
                    else:
                        hrcO[level].append(0)
            else:
                hrcO[level] = list(
                    numpy.array(hrcA[level] +
                                ([0] * (numChildrenO - numChildrenA))) +
                    numpy.array(hrcB[level] + ([0] *
                                               (numChildrenO - numChildrenB))))
        # Write the HRC file
        utils.writeHRC(nodeAbsPathO + '/' + hrcFile, hierarchyStepSize, hrcO)
    elif hrcA != None:
        # Only Octtree A has data in this node. We can directly copy it to the output Octtree
        utils.shellExecute(cmcommand + nodeAbsPathA + ' ' + nodeAbsPathO)
    elif hrcB != None:
        # Only Octtree B has data in this node. We can directly copy it to the output Octtree
        utils.shellExecute(cmcommand + nodeAbsPathB + ' ' + nodeAbsPathO)
Пример #14
0
def run(inputFolderA, inputFolderB, outputFolder, moveFiles):
    # Check input parameters
    if (not os.path.isdir(inputFolderA)) or (not os.path.isdir(inputFolderB)):
        raise Exception('Error: Some of the input folder does not exist!')
    if os.path.isfile(outputFolder):
        raise Exception(
            'Error: There is a file with the same name as the output folder. Please, delete it!'
        )
    elif os.path.isdir(outputFolder) and os.listdir(outputFolder):
        raise Exception(
            'Error: Output folder exists and it is not empty. Please, delete the data in the output folder!'
        )

    # Make the paths absolute path
    inputFolderA = os.path.abspath(inputFolderA)
    inputFolderB = os.path.abspath(inputFolderB)
    outputFolder = os.path.abspath(outputFolder)

    if moveFiles:
        cmcommand = 'mv '
    else:
        cmcommand = 'cp -r '

    dataA = inputFolderA + '/data'
    dataB = inputFolderB + '/data'
    dataO = outputFolder + '/data'

    # Check if the octtrees have actual data (i.e. one folder with the root node)
    hasNodeA = os.listdir(dataA) == [
        'r',
    ]
    hasNodeB = os.listdir(dataB) == [
        'r',
    ]

    if hasNodeA or hasNodeB:
        utils.shellExecute('mkdir -p ' + outputFolder)
        if hasNodeA and hasNodeB:
            # If both Octrees have data we need to merge them
            # Create output cloud.js from joining the two input ones
            cloudJSA = inputFolderA + '/cloud.js'
            cloudJSB = inputFolderB + '/cloud.js'
            if not (os.path.isfile(cloudJSA)) or not (
                    os.path.isfile(cloudJSB)):
                raise Exception('Error: Some cloud.js is missing!')
            # We also get the hierarchyStepSize
            hierarchyStepSize = createCloudJS(cloudJSA, cloudJSB,
                                              outputFolder + '/cloud.js')
            listFileRootA = os.listdir(dataA + '/r')
            if 'r.las' in listFileRootA:
                extension = 'las'
            elif 'r.laz' in listFileRootA:
                extension = 'laz'
            else:
                raise Exception('Error: ' + __file__ +
                                ' only compatible with las/laz format')
            joinNode('r', dataA + '/r', dataB + '/r', dataO + '/r',
                     hierarchyStepSize, extension, cmcommand)
        elif hasA:
            utils.shellExecute(cmcommand + inputFolderA + '/* ' + outputFolder)
        else:
            utils.shellExecute(cmcommand + inputFolderB + '/* ' + outputFolder)
    else:
        print('Nothing to merge: both Octtrees are empty!')
def run(inputFolder, outputFolder, tempFolder, extent, numberTiles, numberProcs):
    # Check input parameters
    if not os.path.isdir(inputFolder) and not os.path.isfile(inputFolder):
        raise Exception('Error: Input folder does not exist!')
    if os.path.isfile(outputFolder):
        raise Exception('Error: There is a file with the same name as the output folder. Please, delete it!')
    elif os.path.isdir(outputFolder) and os.listdir(outputFolder):
        raise Exception('Error: Output folder exists and it is not empty. Please, delete the data in the output folder!')
    # Get the number of tiles per dimension (x and y)
    axisTiles = math.sqrt(numberTiles)
    if (not axisTiles.is_integer()) or (int(axisTiles) % 2):
        raise Exception('Error: Number of tiles must be the square of number which is power of 2!')
    axisTiles = int(axisTiles)

    # Create output and temporal folder
    utils.shellExecute('mkdir -p ' + outputFolder)
    utils.shellExecute('mkdir -p ' + tempFolder)

    (minX, minY, maxX, maxY) = extent.split(' ')
    minX = float(minX)
    minY = float(minY)
    maxX = float(maxX)
    maxY = float(maxY)

    if (maxX - minX) != (maxY - minY):
        raise Exception('Error: Tiling requires that maxX-minX must be equal to maxY-minY!')

    inputFiles = utils.getFiles(inputFolder, recursive=True)
    numInputFiles = len(inputFiles)
    print ('%s contains %d files' % (inputFolder, numInputFiles))

    # Create queues for the distributed processing
    tasksQueue = multiprocessing.Queue() # The queue of tasks (inputFiles)
    resultsQueue = multiprocessing.Queue() # The queue of results

    # Add tasks/inputFiles
    for i in range(numInputFiles):
        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, minX, minY, maxX, maxY, outputFolder, tempFolder, axisTiles)))
        processes[-1].start()

    # Get all the results (actually we do not need the returned values)
    numPoints = 0
    for i in range(numInputFiles):
        (processIndex, inputFile, inputFileNumPoints) = resultsQueue.get()
        numPoints += inputFileNumPoints
        print ('Completed %d of %d (%.02f%%)' % (i+1, numInputFiles, 100. * float(i+1) / float(numInputFiles)))
    # wait for all users to finish their execution
    for i in range(numberProcs):
        processes[i].join()

    # Write the tile.js file with information about the tiles
    cFile = open(outputFolder + '/tiles.js', 'w')
    d = {}
    d["NumberPoints"] = numPoints
    d["numXTiles"] = axisTiles
    d["numYTiles"] = axisTiles
    d["boundingBox"] = {'lx':minX,'ly':minY,'ux':maxX,'uy':maxY}
    cFile.write(json.dumps(d,indent=4,sort_keys=True))
    cFile.close()