def run3phase(phasesToCalculate={'v': True, 't': True, 'd': True, 's': True}, calculationType='annual', epwFile=None, tmatrixFile=None): if phasesToCalculate['v']: # Step1: Create the view matrix. rfluxPara = RfluxmtxParameters() rfluxPara.irradianceCalc = True rfluxPara.ambientAccuracy = 0.1 rfluxPara.ambientBounces = 10 rfluxPara.ambientDivisions = 65536 rfluxPara.limitWeight = 1E-5 # step 1.1 Invert glazing surface with xform so that it faces inwards xfrPara = XformParameters() xfrPara.invertSurfaces = True xfr = Xform() xfr.xformParameters = xfrPara xfr.radFile = 'glazing.rad' xfr.outputFile = 'glazingI.rad' xfr.execute() rflux = Rfluxmtx() rflux.sender = '-' # This needs to be automated based on the normal of each window. # Klems full basis sampling and the window faces +Y recCtrlPar = rflux.ControlParameters(hemiType='kf', hemiUpDirection='+Z') rflux.receiverFile = rflux.addControlParameters('glazingI.rad', {'Exterior_Window': recCtrlPar}) rflux.rfluxmtxParameters = rfluxPara rflux.pointsFile = 'indoor_points.pts' rflux.outputMatrix = r'temp/vmatrix.vmx' rflux.radFiles = ['room.mat', 'room.rad'] rflux.execute() vMatrix = r'temp/vmatrix.vmx' # Step2: Assign T matrix from precalculated XML files. tMatrix = tmatrixFile or r'xmls/clear.xml' if phasesToCalculate['d']: # Step3: Create D matrix. rfluxPara = RfluxmtxParameters() rfluxPara.ambientAccuracy = 0.1 rfluxPara.ambientDivisions = 1024 rfluxPara.ambientBounces = 2 rfluxPara.limitWeight = 0.0000001 rflux2 = Rfluxmtx() rflux2.samplingRaysCount = 1000 rflux2.sender = 'glazingI_m.rad' skyFile = rflux2.defaultSkyGround(r'temp/rfluxSky.rad', skyType='r1') rflux2.receiverFile = skyFile rflux2.rfluxmtxParameters = rfluxPara rflux2.radFiles = [r"room.mat", r"room.rad"] rflux2.outputMatrix = r"temp/dmatrix.dmx" rflux2.execute() dMatrix = r"temp/dmatrix.dmx" # Step4a: Create the sky vector. # Step4a.1: Create a sky defintion # Step s: Creating the sky matrix if phasesToCalculate['s']: if calculationType == 'annual': weaFile = Epw2wea(epwFile=epwFile or 'test.epw', outputWeaFile=r'temp/test.wea') weaFile.execute() gendayParam = GendaymtxParameters() gendayParam.skyDensity = 1 genday = Gendaymtx(weaFile=r'temp/test.wea', outputName=r'temp/day.smx') genday.gendaymtxParameters = gendayParam genday.execute() skyVector = r'temp/day.smx' else: gensk = Gensky() gensk.monthDayHour = (11, 11, 11) gensk.outputFile = 'temp/sky.rad' # gensk.execute() genskv = Genskyvec() genskv.inputSkyFile = r'temp/sky.rad' genskv.outputFile = r'temp/sky.vec' genskv.skySubdivision = 1 genskv.execute() skyVector = r'temp/sky.vec' else: skyVector = r'temp/sky.vec' # Step5: Generate results dct = Dctimestep() dct.tmatrixFile = tMatrix dct.vmatrixSpec = vMatrix dct.dmatrixFile = dMatrix dct.skyVectorFile = skyVector dct.outputFileName = r'temp/results3p.tmp' dct.execute() mtx2Param = RmtxopParameters() mtx2Param.outputFormat = 'a' mtx2Param.combineValues = (47.4, 119.9, 11.6) mtx2Param.transposeMatrix = True mtx2 = Rmtxop(matrixFiles=[r'temp/results3p.tmp'], outputFile=r'temp/illuminance3p.ill') mtx2.rmtxopParameters = mtx2Param mtx2.execute() return 'temp/illuminance3p.ill'
def calcDirectIlluminance(epwFile, analemmaPath, sunListPath, sunMatrixPath, materialFile, geometryFiles, pointsFile, folderForCalculations, outputIllFilePath, HOYList=range(8760), overWriteExistingFiles=True): """ Calculate direct illuminance from the Sun. Args: epwFile: EPW file path. solarDiscPath: sunListPath: sunMatrixPath: materialFile: A single material file. geometryFiles: One or more geometry files. pointsFile: A points file in Daysim compatible format. folderForCalculations: A folder where all the intermediate files can be stored. outputIllFilePath: HOYList: overWriteExistingFiles: Returns: """ # a sad logging hack statusMsg = lambda msg: "\n%s:%s\n%s\n" % (time.ctime(), msg, "*~" * 25) # over-write warning. def overWriteWarning(filePath, overWriteExistingFiles=overWriteExistingFiles): if os.path.exists(filePath): if not overWriteExistingFiles: raise Exception( "The file %s already exists. Set the variable overWriteExistingFiles" "to True to overWrite this and other files." % filePath) else: msg = "The file %s already existed and was overwritten" % filePath warnings.warn(msg) statusMsg('Generating sunpath and sunmatrix') analemmaPath, sunListPath, sunMatrixPath = analemmacalculator( epwFile=epwFile, sunDiscRadPath=analemmaPath, sunListPath=sunListPath, solarRadiationMatrixPath=sunMatrixPath, HOYlist=HOYList) sceneData = [materialFile] # Append if single, extend if multiple if isinstance(geometryFiles, basestring): sceneData.append(geometryFiles) elif isinstance(geometryFiles, (tuple, list)): sceneData.extend(geometryFiles) octreeFile = os.path.join(folderForCalculations, 'solar.oct') # overWriteWarning(octreeFile) statusMsg('Creating octree') octree = Oconv() octree.sceneFiles = sceneData + [analemmaPath] octree.outputFile = octreeFile octree.execute() statusMsg('Creating sun coefficients') dcFile = os.path.join(folderForCalculations, 'sunCoeff.dc') overWriteWarning(dcFile) tmpIllFile = os.path.join(folderForCalculations, 'illum.tmp') overWriteWarning(tmpIllFile) rctPara = RcontribParameters() rctPara.ambientBounces = 0 rctPara.directJitter = 0 rctPara.directCertainty = 1 rctPara.directThreshold = 0 rctPara.modFile = sunListPath rctPara.irradianceCalc = True rctb = Rcontrib() rctb.octreeFile = octreeFile rctb.outputFile = dcFile rctb.pointsFile = pointsFile rctb.rcontribParameters = rctPara rctb.execute() statusMsg('Performing matrix multiplication between the coefficients' ' and the sun matrix.') dct = Dctimestep() dct.daylightCoeffSpec = dcFile dct.skyVectorFile = sunMatrixPath dct.outputFile = tmpIllFile dct.execute() statusMsg( 'Transposing the matrix as per time-series and calculating illuminance.' ) mtx2Param = RmtxopParameters() mtx2Param.outputFormat = 'a' mtx2Param.combineValues = (47.4, 119.9, 11.6) mtx2Param.transposeMatrix = True mtx2 = Rmtxop(matrixFiles=[tmpIllFile], outputFile=outputIllFilePath) mtx2.rmtxopParameters = mtx2Param mtx2.execute() return outputIllFilePath
def run3phaseMulti(pointsFile, outputIllName, windowConfig=(), epwFile=None, skyFile=None, geometryFile=None, materialFile=None, reuseVmtx=True, reuseSkyVector=True, reuseDmtx=True, skyDescr=1, klemsForVmtx='kf', vmtxParam=None, dmtxParam=None, TransposeAnnualResults=True, skyVectorParam=None): """ Notes: 1. It is assumed that the surfaces used for the vmtx are inward facing .i.e they need not be flipped. 2. It is also assumed that the surfaces used for vmtx already have a glow modifier assigned to them. Args: outputIllName: Name of the file to which the results should be written. windowConfig: A tuple containing the windowGroupGeometry, the direction of the surface Normal, the corresponding T matrix XML and an option to include or exclude the results from the windowgroup in the calculation. A typical option will be something like ('glazing.rad','+Z', 'blinds.xml',True), specifying that the radiance geometry 'glazing.rad', whose direction normal faces +Z will be used for the calculation of that particular V matrix. 'blinds.xml' indicates the XML file that will be used as T matrix for that window group and True indicates that this window group will be considered for the calculations. epwFile: epwFile corresponding to a particular location. If epwFile and skyFile are provided, the option for epwFile will be prioritized .i.e. the calculation will be annual. skyFile: An input from gensky or gendaylit for creating a point-in-time sky vector. geometryFile: Geometry for All the files in the calculation except the ones for the glazing. materialFile: Materials for all the geometry described in the geometryFile input. reuseVmtx: A boolean value for specifying if the Vmtx needs to be recalculated if it is already present. reuseDmtx: A boolean value for specifying if the Dmtx needs to be recalculated. reuseSkyVector: A boolean value for specifying if sky vector needs to be recalculated. pointsFile: The file containing the grid points that will be used for illumiance calcuations. skyDescr: An integer specifying the sky descretization value to be considered for generating the sky matrix. The values (number, skypataches)corresponding to different sky descretizations are : (1, 145),(2,577),(3,1297),(4,2305), (5,3601),(6,5185). Higher discretizations equal higher values. klemsForVmtx: The klems basis to be considered for sampling the vmtx. Default value is 'kf' vmtxParam: Calculation parameters corresponding to the V matrix. This should be an instance of the class RfluxParameters. If not specified, a default value will be assigned. dmtxParam: Calculation parameters corresponding to the D matrix. This should be an instance of the class RfluxParameters. If not specified, a default value will be assigned. TransposeAnnualResults: A boolean value, which if set to True, will transpose the results of an annual calculation as per the 8760 lines format. Returns: """ def createWinGroupReceivers(surfaceFile, surfaceNormal, klemsBasis): # remove the + or - sign if specified. surfaceNormal = surfaceNormal[-1] if len( surfaceNormal) > 1 else surfaceNormal hemiUp = "+Z" if surfaceNormal.lower() in "xy" else "+X" # check if there is a glow material assigned in the file. # retrieve the first polygon surface for assigning rfluxmtxParameters. surfaceStringNoComments = '' with open(surfaceFile) as surfaceData: for lines in surfaceData: if not lines.strip().startswith("#"): surfaceStringNoComments += lines surfaceStringNoComSplit = surfaceStringNoComments.split() assert surfaceStringNoComSplit[1] == 'glow',\ 'It appears that the glow material has not been applied to this surface.This' \ ' is essential for the Three Phase Method. ' firstPolyPosition = surfaceStringNoComSplit.index('polygon') surfaceName = surfaceStringNoComSplit[firstPolyPosition - 1] rflux = Rfluxmtx() receiverParam = rflux.ControlParameters(hemiType=klemsBasis, hemiUpDirection=hemiUp) receiverFile = rflux.addControlParameters(surfaceFile, {surfaceName: receiverParam}) return receiverFile def calcVmtx(surfaceFile, receiverFile, reuse, vmtxParam, pointsFile, materialFile, geometryFile): vmtxFile = os.path.join('temp', os.path.splitext(surfaceFile)[0] + '.vmtx') if os.path.exists(vmtxFile) and reuse: return vmtxFile if vmtxParam: assert isinstance(vmtxParam, RfluxmtxParameters),\ 'The input for vmtxParam must be an instance of RfluxmtxParamters. ' \ 'The current input is an instance of %s' % (type(vmtxParam)) else: vmtxParam = RfluxmtxParameters() vmtxParam.irradianceCalc = True vmtxParam.ambientAccuracy = 0.1 vmtxParam.ambientBounces = 10 vmtxParam.ambientDivisions = 65536 vmtxParam.limitWeight = 1E-5 rflux = Rfluxmtx() rflux.receiverFile = receiverFile rflux.rfluxmtxParameters = vmtxParam rflux.pointsFile = pointsFile rflux.sender = '-' rflux.outputMatrix = vmtxFile rflux.radFiles = [materialFile, geometryFile] print(rflux.toRadString()) rflux.execute() return vmtxFile def calcDmtx(surfaceFile, senderFile, reuse, skyDescr, dmtxParam, materialFile, geometryFile): dmtxFile = os.path.join('temp', os.path.splitext(surfaceFile)[0] + '.dmtx') if os.path.exists(dmtxFile) and reuse: return dmtxFile if dmtxParam: assert isinstance(dmtxParam, RfluxmtxParameters), \ 'The input for vmtxParam must be an instance of RfluxmtxParamters. ' \ 'The current input is an instance of %s' % (type(dmtxParam)) else: dmtxParam = RfluxmtxParameters() dmtxParam.ambientAccuracy = 0.1 dmtxParam.ambientBounces = 2 dmtxParam.ambientDivisions = 1024 dmtxParam.limitWeight = 1E-5 rflux2 = Rfluxmtx() rflux2.samplingRaysCount = 1000 rflux2.sender = senderFile skyFile = rflux2.defaultSkyGround(r'temp/rfluxSky.rad', skyType="r%s" % skyDescr) rflux2.receiverFile = skyFile rflux2.rfluxmtxParameters = dmtxParam rflux2.radFiles = [materialFile, geometryFile] rflux2.outputMatrix = dmtxFile rflux2.execute() return dmtxFile def calcSkyVector(skyDescr, epwFile=None, skyFile=None, reuse=True, skyVectorParam=None): assert epwFile or skyFile,\ 'Either an epwFile or a skyFile need to be provided for the skyVector to' \ 'be calculated.' if epwFile and os.path.exists(epwFile): epwName = os.path.split(epwFile)[1] skyMtxName = os.path.splitext(epwName)[0] + '%s.smx' % skyDescr weaName = os.path.splitext(epwFile)[0] + '.wea' if os.path.exists(skyMtxName) and reuse: return skyMtxName weaFile = Epw2wea(epwFile=epwFile, outputWeaFile=weaName) weaFile.execute() if skyVectorParam: assert isinstance(skyVectorParam, GendaymtxParameters),\ 'The input for skyVectorParam must be an instance of GendaymtxParameters.' gendayParam = skyVectorParam else: gendayParam = GendaymtxParameters() gendayParam.skyDensity = skyDescr genday = Gendaymtx(weaFile=weaName, outputName=skyMtxName) genday.gendaymtxParameters = skyVectorParam genday.execute() return skyMtxName elif skyFile and os.path.exists(skyFile): skyMtxName = os.path.splitext(skyFile)[0] + '%s.smx' % skyDescr if os.path.exists(skyMtxName) and reuse: return skyMtxName genskv = Genskyvec() genskv.inputSkyFile = skyFile genskv.skySubdivision = skyDescr genskv.outputFile = skyMtxName genskv.execute() return skyMtxName else: raise Exception( 'The input path for the skyFile or epwFile are not valid.') # generate receiver surfaces for all window groups..This is not an intensive process. receiverFiles = [ createWinGroupReceivers(win['windowSurface'], win['surfaceNormal'], klemsForVmtx) for win in windowConfig ] # create the skyVector. skyVector = calcSkyVector(skyDescr=skyDescr, epwFile=epwFile, skyFile=skyFile, reuse=reuseSkyVector, skyVectorParam=skyVectorParam) # create V and D matrices corresponding to each window Group. matrixFilesForResult = [] resultFiles = 0 for idx, recFile in enumerate(receiverFiles): vmtxFile = calcVmtx(windowConfig[idx]['windowSurface'], recFile, reuse=reuseVmtx, vmtxParam=vmtxParam, pointsFile=pointsFile, materialFile=materialFile, geometryFile=geometryFile) dmtxFile = calcDmtx(windowConfig[idx]['windowSurface'], senderFile=recFile, skyDescr=skyDescr, dmtxParam=dmtxParam, materialFile=materialFile, geometryFile=geometryFile, reuse=reuseDmtx) if windowConfig[idx]['includeInCalc']: windowName = os.path.splitext( windowConfig[idx]['windowSurface'])[0] + 'Res.tmp' dctResult = os.path.join('temp', windowName) dct = Dctimestep() dct.dmatrixFile = dmtxFile dct.vmatrixSpec = vmtxFile dct.skyVectorFile = skyVector dct.tmatrixFile = windowConfig[idx]['tMatrix'] dct.outputFileName = dctResult dct.execute() matrixFilesForResult.append(dctResult) resultFiles += 1 assert resultFiles, 'None of the Window Groups were chosen for calculating the results !' # add up values into a single tmp file rmtxAdd = Rmtxop() rmtxAdd.matrixFiles = matrixFilesForResult rmtxAdd.outputFile = os.path.splitext(outputIllName)[0] + '.tmp' rmtxAdd.execute() # convert r g b to illuminance rmtResParam = RmtxopParameters() rmtResParam.combineValues = (47.4, 119.9, 11.6) rmtResParam.outputFormat = 'a' rmtResParam.transposeMatrix = TransposeAnnualResults rmtxRes = Rmtxop() rmtxRes.matrixFiles = [rmtxAdd.outputFile] rmtxRes.outputFile = outputIllName rmtxRes.rmtxopParameters = rmtResParam rmtxRes.execute() return outputIllName
def improvedDCcalc(epwFile, materialFile, geometryFiles, pointsFile, folderForCalculations, outputIllFilePath, reinhartPatches=1, calcDict={ 'skyVectors': True, 'DirectDCCoeff': True, 'DCCoeff': True, 'DirectSun': True }): """ Args: epwFile: Epw file path. materialFile: Path for a single material file. geometryFiles: One or more geometry files. pointsFile: Path for poitns file folderForCalculations: Folder for storing intermediate files. outputIllFilePath: reinhartPatches: Default is 1. calcDict: This is useful for selectively running different parts of the simulation. Returns: """ #a sad logging hack statusMsg = lambda msg: "\n%s:%s\n%s\n" % (time.ctime(), msg, "*~" * 25) weaFilePath = os.path.join( folderForCalculations, os.path.splitext(os.path.split(epwFile)[1])[0] + '.wea') weaFile = Epw2wea(epwFile=epwFile, outputWeaFile=weaFilePath) weaFile.execute() #Calculate complete sky matrix. skyMatrix = os.path.join(folderForCalculations, 'skyMatrix.mtx') gendayParam = GendaymtxParameters() gendayParam.skyDensity = reinhartPatches genday = Gendaymtx(weaFile=weaFilePath, outputName=skyMatrix) genday.gendaymtxParameters = gendayParam if calcDict['skyVectors']: print(genday.toRadString()) genday.execute() #Calculate direct only matrix. skyMatrixDirect = os.path.join(folderForCalculations, 'skyMatrixDirect.mtx') gendayParam = GendaymtxParameters() gendayParam.skyDensity = reinhartPatches gendayParam.onlyDirect = True genday = Gendaymtx(weaFile=weaFilePath, outputName=skyMatrixDirect) genday.gendaymtxParameters = gendayParam if calcDict['skyVectors']: print(genday.toRadString()) genday.execute() skyDomeFile = os.path.join(folderForCalculations, 'rfluxSky.rad') dcCoeffMatrix = os.path.join(folderForCalculations, 'dc.mtx') dcCoeffMatrixDirect = os.path.join(folderForCalculations, 'dcDirect.mtx') sceneData = [materialFile] #Append if single, extend if multiple if isinstance(geometryFiles, basestring): sceneData.append(geometryFiles) elif isinstance(geometryFiles, (tuple, list)): sceneData.extend(geometryFiles) # Step2: Generate daylight coefficients for normal sky-matrix using rfluxmtx. rfluxPara = RfluxmtxParameters() rfluxPara.irradianceCalc = True rfluxPara.ambientAccuracy = 0.1 rfluxPara.ambientDivisions = 20000 rfluxPara.ambientBounces = 5 rfluxPara.limitWeight = 1E-7 rfluxPara.ambientResolution = 10000 rflux = Rfluxmtx() rflux.sender = '-' skyFile = rflux.defaultSkyGround(skyDomeFile, skyType='r%s' % reinhartPatches) rflux.receiverFile = skyDomeFile rflux.rfluxmtxParameters = rfluxPara rflux.radFiles = sceneData rflux.samplingRaysCount = 1 rflux.pointsFile = pointsFile rflux.outputMatrix = dcCoeffMatrix if calcDict['DCCoeff']: rflux.execute() tempIll = os.path.join(folderForCalculations, 'temp.ill') ill = os.path.join(folderForCalculations, 'Illuminance.ill') dct = Dctimestep() dct.daylightCoeffSpec = dcCoeffMatrix dct.skyVectorFile = skyMatrix dct.outputFile = tempIll if calcDict['DCCoeff']: dct.execute() mtx2Param = RmtxopParameters() mtx2Param.outputFormat = 'a' mtx2Param.combineValues = (47.4, 119.9, 11.6) mtx2Param.transposeMatrix = True mtx2 = Rmtxop(matrixFiles=[tempIll], outputFile=ill) mtx2.rmtxopParameters = mtx2Param if calcDict['DCCoeff']: mtx2.execute() # Step3: Generate direct daylight coefficients for normal sky-matrix using rfluxmtx. rfluxPara = RfluxmtxParameters() rfluxPara.irradianceCalc = True rfluxPara.ambientAccuracy = 0.01 rfluxPara.ambientDivisions = 20000 rfluxPara.ambientBounces = 1 rfluxPara.limitWeight = 1E-7 rfluxPara.ambientResolution = 10000 rflux = Rfluxmtx() rflux.sender = '-' skyFile = rflux.defaultSkyGround(skyDomeFile, skyType='r%s' % reinhartPatches) rflux.receiverFile = skyDomeFile rflux.rfluxmtxParameters = rfluxPara rflux.radFiles = sceneData rflux.samplingRaysCount = 1 rflux.pointsFile = pointsFile rflux.outputMatrix = dcCoeffMatrixDirect if calcDict['DirectDCCoeff']: rflux.execute() tempDirectIll = os.path.join(folderForCalculations, 'tempDirect.ill') illDirect = os.path.join(folderForCalculations, 'IlluminanceDirect.ill') dct = Dctimestep() dct.daylightCoeffSpec = dcCoeffMatrixDirect dct.skyVectorFile = skyMatrixDirect dct.outputFile = tempDirectIll if calcDict['DCCoeff']: dct.execute() mtx2Param = RmtxopParameters() mtx2Param.outputFormat = 'a' mtx2Param.combineValues = (47.4, 119.9, 11.6) mtx2Param.transposeMatrix = True mtx2 = Rmtxop(matrixFiles=[tempDirectIll], outputFile=illDirect) mtx2.rmtxopParameters = mtx2Param if calcDict['DirectDCCoeff']: mtx2.execute() solarDiscPath = os.path.join(folderForCalculations, 'solarDiscs.rad') sunListPath = os.path.join(folderForCalculations, 'sunList.txt') sunMatrixPath = os.path.join(folderForCalculations, 'sunMatrix.mtx') #Calculate direct only ill files. directSunIll = os.path.join(folderForCalculations, 'directSunIll.ill') if calcDict['DirectSun']: sunOnlyIll = calcDirectIlluminance( epwFile=epwFile, solarDiscPath=solarDiscPath, sunListPath=sunListPath, sunMatrixPath=sunMatrixPath, materialFile=materialFile, geometryFiles=geometryFiles, pointsFile=pointsFile, folderForCalculations=folderForCalculations, outputIllFilePath=directSunIll) #Instantiate matrices for subtraction and addition. finalMatrix = Rmtxop() #std. dc matrix. dcMatrix = RmtxopMatrix() dcMatrix.matrixFile = ill #direct dc matrix. -1 indicates that this one is being subtracted from dc matrix. dcDirectMatrix = RmtxopMatrix() dcDirectMatrix.matrixFile = illDirect dcDirectMatrix.scalarFactors = [-1] #Sun coefficient matrix. sunCoeffMatrix = RmtxopMatrix() sunCoeffMatrix.matrixFile = directSunIll #combine the matrices together. Sequence is extremely important finalMatrix.rmtxopMatrices = [dcMatrix, dcDirectMatrix, sunCoeffMatrix] finalMatrix.outputFile = outputIllFilePath #Done! finalMatrix.execute() return outputIllFilePath
from honeybee.radiance.parameters.genBsdf import GenbsdfParameters from honeybee.radiance.command.genBSDF import GenBSDF, RtraceParameters from honeybee.radiance.command.rmtxop import Rmtxop, RmtxopParameters import os y = GenbsdfParameters() y.num_processors = 10 y.geom_unit_incl = 'meter' z = GenBSDF() z.grid_based_parameters = RtraceParameters() z.grid_based_parameters.ambient_bounces = 1 z.gen_bsdf_parameters = y z.input_geometry = ['room/room.mat', 'room/glazing.rad'] z.output_file = 'room/test.xml' z.normal_orientation = '-Y' z.execute() rmt_para = RmtxopParameters() rmt_para.output_format = 'c' rmt = Rmtxop() rmt.rmtxop_parameters = rmt_para rmt.matrixF_files = ['room/test.xml'] rmt.output_file = 'room/testhdr.tmp' rmt.execute() os.system('pfilt -x 800 -y 800 %s > room/testhdr.hdr' % rmt.output_file) os.system('ra_bmp %s > room/testhdr.bmp' % 'room/testhdr.hdr') os.startfile(os.path.abspath('room/testhdr.bmp'))
def improvedDCcalc(epwFile, materialFile, geometryFiles, pointsFile, folderForCalculations, outputIllFilePath, glazingGeometry=None, reinhartPatches=1, ambBounces=5, ambDiv=5000, limitWt=0.0002, calcDict={ 'skyVectors': True, 'DirectDCCoeff': True, 'DCCoeff': True, 'DirectSun': True }, cleanUpTempFiles=True): """ Args: epwFile: Epw file path. materialFile: Path for a single material file. geometryFiles: One or more geometry files. pointsFile: Path for poitns file folderForCalculations: Folder for storing intermediate files. outputIllFilePath: reinhartPatches: Default is 1. calcDict: This is useful for selectively running different parts of the simulation. ambBounces: Ambient bounces. Defaults to 5 ambDiv: Ambient divisions. Defaults to 5000. limitWt: Limit weight. Defaults to 0.0002 cleanUpTempFiles: Delete all the temporary files that were created during the calculations. Returns: The path of the illuminance file generated through the calculations. """ # a sad logging hack statusMsg = lambda msg: "\n%s:%s\n%s\n" % (time.ctime(), msg, "*~" * 25) blackMaterial = "void plastic black 0 0 5 0 0 0 0 0" if limitWt > (1 / ambDiv): warnings.warn( "The value for limitWt(%s) should be set to a value equal to or " "less (%s) which is 1/ambDiv(%s)" % (limitWt, 1 / ambDiv, ambDiv)) # crate a tempfolder inside the folderForCalculations. tmpFolder = os.path.join(folderForCalculations, 'tmp') if not os.path.exists(tmpFolder): os.mkdir(tmpFolder) weaFilePath = os.path.join( tmpFolder, os.path.splitext(os.path.split(epwFile)[1])[0] + '.wea') weaFile = Epw2wea(epwFile=epwFile, outputWeaFile=weaFilePath) weaFile.execute() # Calculate complete sky matrix. skyMatrix = os.path.join(tmpFolder, 'skyMatrix.mtx') gendayParam = GendaymtxParameters() gendayParam.skyDensity = reinhartPatches genday = Gendaymtx(weaFile=weaFilePath, outputName=skyMatrix) genday.gendaymtxParameters = gendayParam if calcDict['skyVectors']: print(genday.toRadString()) genday.execute() # Calculate direct only matrix. skyMatrixDirect = os.path.join(tmpFolder, 'skyMatrixDirect.mtx') gendayParam = GendaymtxParameters() gendayParam.skyDensity = reinhartPatches gendayParam.onlyDirect = True genday = Gendaymtx(weaFile=weaFilePath, outputName=skyMatrixDirect) genday.gendaymtxParameters = gendayParam if calcDict['skyVectors']: print(genday.toRadString()) genday.execute() skyDomeFile = os.path.join(tmpFolder, 'rfluxSky.rad') dcCoeffMatrix = os.path.join(tmpFolder, 'dc.mtx') dcCoeffMatrixDirect = os.path.join(tmpFolder, 'dcDirect.mtx') blackMaterial = os.path.join(tmpFolder, 'black.mat') with open(blackMaterial, 'w') as blackMat: blackMat.write("void plastic black 0 0 5 0 0 0 0 0") sceneData = [materialFile] sceneDataBlack = [blackMaterial] geometryData = [] # Append if single, extend if multiple if isinstance(geometryFiles, basestring): geometryData.append(geometryFiles) elif isinstance(geometryFiles, (tuple, list)): geometryData.extend(geometryFiles) sceneData = sceneData + geometryData xfrPara = XformParameters() xfrPara.modReplace = 'black' # Note: Xform has this thing it only works well if the paths are absolute. blackGeometry = os.path.join(tmpFolder, 'blackGeometry.rad') xfr = Xform() xfr.xformParameters = xfrPara xfr.radFile = geometryData xfr.outputFile = blackGeometry xfr.execute() # Material file added in the end with the assumption that the material props for the # glazing are defined in the material file. As Radiance parses scene data in a # strictly linear fashion, even if the material for glazing is defined inside # the glazing geometry, it will still be fine. sceneDataBlack = sceneDataBlack + [blackGeometry] + [materialFile] if isinstance(glazingGeometry, basestring): sceneData.append(glazingGeometry) sceneDataBlack.append(glazingGeometry) elif isinstance(glazingGeometry, (tuple, list)): sceneData.extend(glazingGeometry) sceneDataBlack.extend(glazingGeometry) # Step2: Generate daylight coefficients for normal sky-matrix using rfluxmtx. rfluxPara = RfluxmtxParameters() rfluxPara.irradianceCalc = True rfluxPara.ambientDivisions = ambDiv rfluxPara.ambientBounces = ambBounces rfluxPara.limitWeight = limitWt rflux = Rfluxmtx() rflux.sender = '-' skyFile = rflux.defaultSkyGround(skyDomeFile, skyType='r%s' % reinhartPatches) rflux.receiverFile = skyDomeFile rflux.rfluxmtxParameters = rfluxPara rflux.radFiles = sceneData rflux.samplingRaysCount = 1 rflux.pointsFile = pointsFile rflux.outputMatrix = dcCoeffMatrix if calcDict['DCCoeff']: print(rflux.toRadString()) rflux.execute() tempIll = os.path.join(tmpFolder, 'temp.ill') ill = os.path.join(tmpFolder, 'Illuminance.ill') dct = Dctimestep() dct.daylightCoeffSpec = dcCoeffMatrix dct.skyVectorFile = skyMatrix dct.outputFile = tempIll if calcDict['DCCoeff']: print(dct.toRadString()) dct.execute() mtx2Param = RmtxopParameters() mtx2Param.outputFormat = 'a' mtx2Param.combineValues = (47.4, 119.9, 11.6) mtx2Param.transposeMatrix = True mtx2 = Rmtxop(matrixFiles=[tempIll], outputFile=ill) mtx2.rmtxopParameters = mtx2Param if calcDict['DCCoeff']: mtx2.execute() # Step3: Generate direct daylight coefficients for normal sky-matrix using rfluxmtx. rfluxPara = RfluxmtxParameters() rfluxPara.irradianceCalc = True rfluxPara.ambientDivisions = ambDiv rfluxPara.ambientBounces = 1 rfluxPara.limitWeight = limitWt rflux = Rfluxmtx() rflux.sender = '-' skyFile = rflux.defaultSkyGround(skyDomeFile, skyType='r%s' % reinhartPatches) rflux.receiverFile = skyDomeFile rflux.rfluxmtxParameters = rfluxPara rflux.radFiles = sceneDataBlack rflux.samplingRaysCount = 1 rflux.pointsFile = pointsFile rflux.outputMatrix = dcCoeffMatrixDirect if calcDict['DirectDCCoeff']: rflux.execute() tempDirectIll = os.path.join(tmpFolder, 'tempDirect.ill') illDirect = os.path.join(tmpFolder, 'IlluminanceDirect.ill') dct = Dctimestep() dct.daylightCoeffSpec = dcCoeffMatrixDirect dct.skyVectorFile = skyMatrixDirect dct.outputFile = tempDirectIll if calcDict['DCCoeff']: dct.execute() mtx2Param = RmtxopParameters() mtx2Param.outputFormat = 'a' mtx2Param.combineValues = (47.4, 119.9, 11.6) mtx2Param.transposeMatrix = True mtx2 = Rmtxop(matrixFiles=[tempDirectIll], outputFile=illDirect) mtx2.rmtxopParameters = mtx2Param if calcDict['DirectDCCoeff']: mtx2.execute() solarDiscPath = os.path.join(tmpFolder, 'solarDiscs.rad') sunListPath = os.path.join(tmpFolder, 'sunList.txt') sunMatrixPath = os.path.join(tmpFolder, 'sunMatrix.mtx') # Calculate direct only ill files. directSunIll = os.path.join(tmpFolder, 'directSunIll.ill') if calcDict['DirectSun']: calcDirectIlluminance(epwFile=epwFile, solarDiscPath=solarDiscPath, sunListPath=sunListPath, sunMatrixPath=sunMatrixPath, materialFile=blackMaterial, geometryFiles=sceneDataBlack, pointsFile=pointsFile, folderForCalculations=folderForCalculations, outputIllFilePath=directSunIll) # Instantiate matrices for subtraction and addition. finalMatrix = Rmtxop() # std. dc matrix. dcMatrix = RmtxopMatrix() dcMatrix.matrixFile = ill # direct dc matrix. -1 indicates that this one is being subtracted from dc matrix. dcDirectMatrix = RmtxopMatrix() dcDirectMatrix.matrixFile = illDirect dcDirectMatrix.scalarFactors = [-1] # Sun coefficient matrix. sunCoeffMatrix = RmtxopMatrix() sunCoeffMatrix.matrixFile = directSunIll # combine the matrices together. Sequence is extremely important finalMatrix.rmtxopMatrices = [dcMatrix, dcDirectMatrix, sunCoeffMatrix] finalMatrix.outputFile = outputIllFilePath # Done! finalMatrix.execute() return outputIllFilePath
def run2Phase(calculationType='annual'): if calculationType == 'annual': weaFile = Epw2wea(epwFile='test.epw', outputWeaFile=r'temp/test.wea') weaFile.execute() gendayParam = GendaymtxParameters() gendayParam.skyDensity = 4 genday = Gendaymtx(weaFile=r'temp/test.wea', outputName=r'temp/day.smx') genday.gendaymtxParameters = gendayParam # genday.execute() skyVector = r'temp/day.smx' else: gensk = Gensky() gensk.monthDayHour = (11, 11, 11) gensk.outputFile = 'temp/sky.rad' gensk.execute() genskv = Genskyvec() genskv.inputSkyFile = r'temp/sky.rad' genskv.outputFile = r'temp/sky.vec' genskv.skySubdivision = 4 genskv.execute() skyVector = r'temp/sky.vec' # # Step2: Generate daylight coefficients using rfluxmtx. rfluxPara = RfluxmtxParameters() rfluxPara.irradianceCalc = False rfluxPara.ambientAccuracy = 0.1 rfluxPara.ambientDivisions = 10 rfluxPara.ambientBounces = 1 rfluxPara.limitWeight = 0.1 rfluxPara.quality = 0 rflux = Rfluxmtx() rflux.sender = '-' skyFile = rflux.defaultSkyGround(r'temp/rfluxSky.rad',skyType='r4') rflux.receiverFile = skyFile rflux.rfluxmtxParameters = rfluxPara rflux.radFiles = [r"room.mat", r"room.rad"] rflux.pointsFile = r"indoor_points.pts" rflux.outputMatrix = r"temp/dayCoeff.dc" rflux.execute() mtx1 = Rmtxop(matrixFiles=(os.path.abspath(r'temp/dayCoeff.dc'), os.path.abspath(skyVector)), outputFile=r'temp/illuminance.tmp') mtx1.execute() mtx2Param = RmtxopParameters() mtx2Param.outputFormat = 'a' mtx2Param.combineValues = (47.4, 119.9, 11.6) # mtx2Param.transposeMatrix = True mtx2 = Rmtxop(matrixFiles=[r'temp/illuminance.tmp'], outputFile=r'temp/illuminance.ill') mtx2.rmtxopParameters = mtx2Param mtx2.execute() with open(r'temp/illuminance.ill') as illFile: for lines in illFile: try: print(map(float, lines.split())) except ValueError: pass
import os y = GenbsdfParameters() y.num_processors = 10 y.geom_unit_incl = 'meter' z = GenBSDF() z.grid_based_parameters = RtraceParameters() z.grid_based_parameters.ambient_bounces = 1 z.gen_bsdf_parameters = y z.input_geometry = ['room/room.mat', 'room/glazing.rad'] z.output_file = 'room/test.xml' z.normal_orientation = '-Y' z.execute() rmt_para = RmtxopParameters() rmt_para.output_format = 'c' rmt = Rmtxop() rmt.rmtxop_parameters = rmt_para rmt.matrixF_files = ['room/test.xml'] rmt.output_file = 'room/testhdr.tmp' rmt.execute() os.system('pfilt -x 800 -y 800 %s > room/testhdr.hdr' % rmt.output_file) os.system('ra_bmp %s > room/testhdr.bmp' % 'room/testhdr.hdr') os.startfile(os.path.abspath('room/testhdr.bmp'))
from honeybee.radiance.command.rmtxop import Rmtxop, RmtxopParameters y = GenbsdfParameters() y.numProcessors = 10 y.geomUnitIncl = 'meter' z = GenBSDF() z.gridBasedParameters = GridBasedParameters() z.gridBasedParameters.ambientBounces = 1 z.genBsdfParameters = y z.inputGeometry = ['room/room.mat', 'room/glazing.rad'] z.outputFile = 'room/test.xml' z.normalOrientation = '-Y' z.execute() rmtPara = RmtxopParameters() rmtPara.outputFormat = 'c' rmt = Rmtxop() rmt.rmtxopParameters = rmtPara rmt.matrixFiles = ['room/test.xml'] rmt.outputFile = 'room/testhdr.tmp' rmt.execute() import os os.system('pfilt -x 800 -y 800 %s > room/testhdr.hdr' % rmt.outputFile) os.system('ra_bmp %s > room/testhdr.bmp' % 'room/testhdr.hdr') os.startfile(os.path.abspath('room/testhdr.bmp'))
def directSunCalcs(epwFile, materialFile, geometryFiles, pointsFile, calcASE=True, calcASEptsSummary=True, illumForASE=1000, hoursForASE=250, hoyForValidation=13, repeatValidationOnly=False): """ Args: epwFile: path. materialFile: path. geometryFiles: path(s). pointsFile: path. calcASE: Boolean. If set to False, only raytrace and illuminance calcs will be performed. calcASEptsSummary: If set to True, will produce a summary of points and the number of hours for which they are above the value set for illumForASE. If set to False only the direct value of ASE (as specified by LM-83-12 will be calculated.) illumForASE: Illuminance for ASE. Has been set to a default of 1000 lux as per LM-83-12. hoursForASE: Hour-threshold for ASE. Has been set to a default of 250 hours as per LM-83-12. This option is only relevant if the the calcASEptsSummary option has been set to False. As otherwise, an entire list of hours will be produced regardless. hoyForValidation: A value between 0 to 8759 to check the annual results against an independent point-in-time ray-trace calc using rtrace. No validation will be performed if this value is set to None. repeatValidationOnly: Once the claculations have been run. Validation for more hours can be performed by setting this to True. Default is False. Returns: This function prints out. Does not return anything. """ #a sad logging hack statusMsg = lambda msg: "\n%s:%s\n%s\n" % (time.ctime(), msg, "*~" * 25) print(statusMsg('Starting calculations')) sceneData = [materialFile] #Append if single, extend if multiple if isinstance(geometryFiles, basestring): sceneData.append(geometryFiles) elif isinstance(geometryFiles, (tuple, list)): sceneData.extend(geometryFiles) monthDateTime = [DateTime.fromHoy(idx) for idx in xrange(8760)] epw = EPW(epwFile) latitude, longitude = epw.location.latitude, -epw.location.longitude meridian = -(15 * epw.location.timezone) #Create a directory for ASE test. dirName = 'tests/ASEtest' if not os.path.exists(dirName): os.mkdir(dirName) #Defining these upfront so that this data may be used for validation without rerunning #calcs every time sunList = os.path.join(dirName, 'sunlist') sunDiscRadFile = os.path.join(dirName, 'sunFile.rad') radiationMatrix = os.path.join(dirName, 'sunRadiation.mtx') annualResultsFile = os.path.join(dirName, 'illum.ill') if not repeatValidationOnly: # preCalcFiles = (sunList,sunDiscRadFile,radiationMatrix,annualResultsFile) # for files in preCalcFiles: # assert os.path.exists(files),'Precalculated data cannot be used as the file ' \ # '%s, which is required for calculations cannot be' \ # 'found.' #instantiating classes before looping makes sense as it will avoid the same calls over # and over. genParam = GendaylitParameters() genParam.meridian = meridian genParam.longitude = longitude genParam.latitude = latitude genDay = Gendaylit() sunValues = [] sunValuesHour = [] print(statusMsg('Calculating sun positions and radiation values')) # We need to throw out all the warning values arising from times when sun isn't present. # os.devnull serves that purpose. with open(os.devnull, 'w') as warningDump: for idx, timeStamp in enumerate(monthDateTime): month, day, hour = timeStamp.month, timeStamp.day, timeStamp.hour + 0.5 genParam.dirNormDifHorzIrrad = ( epw.directNormalRadiation[idx], epw.diffuseHorizontalRadiation[idx]) genDay.monthDayHour = (month, day, hour) genDay.gendaylitParameters = genParam gendayCmd = genDay.toRadString().split('|')[0] #run cmd, get results in the form of a list of lines. cmdRun = Popen(gendayCmd, stdout=PIPE, stderr=warningDump) data = cmdRun.stdout.read().split('\n') #clean the output by throwing out comments as well as brightness functions. sunCurrentValue = [] for lines in data: if not lines.strip().startswith("#"): if "brightfunc" in lines: break if lines.strip(): sunCurrentValue.extend(lines.strip().split()) #If a sun definition was captured in the last for-loop, store info. if sunCurrentValue and max(map(float, sunCurrentValue[6:9])): sunCurrentValue[2] = 'solar%s' % (len(sunValues) + 1) sunCurrentValue[9] = 'solar%s' % (len(sunValues) + 1) sunValues.append(sunCurrentValue) sunValuesHour.append(idx) numOfSuns = len(sunValues) print(statusMsg('Writing sun definitions to disc')) #create list of suns. with open(sunList, 'w') as sunList: sunList.write("\n".join( ["solar%s" % (idx + 1) for idx in xrange(numOfSuns)])) #create solar discs. with open(sunDiscRadFile, 'w') as solarDiscFile: solarDiscFile.write("\n".join([" ".join(sun) for sun in sunValues])) #Start creating header for the sun matrix. fileHeader = ['#?RADIANCE'] fileHeader += ['Sun matrix created by Honeybee'] fileHeader += ['LATLONG= %s %s' % (latitude, -longitude)] fileHeader += ['NROWS=%s' % numOfSuns] fileHeader += ['NCOLS=8760'] fileHeader += ['NCOMP=3'] fileHeader += ['FORMAT=ascii'] #Write the matrix to file. with open(radiationMatrix, 'w') as sunMtx: sunMtx.write("\n".join(fileHeader) + '\n' + '\n') for idx, sunValue in enumerate(sunValues): sunRadList = ["0 0 0"] * 8760 sunRadList[sunValuesHour[idx]] = " ".join(sunValue[6:9]) sunMtx.write("\n".join(sunRadList) + "\n" + "\n") #This last one is for the ground. sunRadList = ["0 0 0"] * 8760 sunMtx.write("\n".join(sunRadList)) print(statusMsg('Starting Raytrace calculations.')) octree = Oconv() octree.sceneFiles = sceneData + [r'tests/ASEtest/sunFile.rad'] octree.outputFile = r'tests/ASEtest/roomSun.oct' octree.execute() rctPara = RcontribParameters() rctPara.ambientBounces = 0 rctPara.directJitter = 0 rctPara.directCertainty = 1 rctPara.directThreshold = 0 rctPara.modFile = r'tests/ASEtest/sunlist' rctPara.irradianceCalc = True rctb = Rcontrib() rctb.octreeFile = r'tests/ASEtest/roomSun.oct' rctb.outputFile = r'tests/ASEtest/sunCoeff.dc' rctb.pointsFile = pointsFile rctb.rcontribParameters = rctPara rctb.execute() dct = Dctimestep() dct.daylightCoeffSpec = r'tests/ASEtest/sunCoeff.dc' dct.skyVectorFile = r'tests/ASEtest/sunRadiation.mtx' dct.outputFile = r'tests/ASEtest/illum.tmp' dct.execute() mtx2Param = RmtxopParameters() mtx2Param.outputFormat = 'a' mtx2Param.combineValues = (47.4, 119.9, 11.6) mtx2Param.transposeMatrix = True mtx2 = Rmtxop(matrixFiles=[r'tests/ASEtest/illum.tmp'], outputFile=annualResultsFile) mtx2.rmtxopParameters = mtx2Param mtx2.execute() print(statusMsg('Finished raytrace.')) # get points Data pointsList = [] with open(pointsFile) as pointsData: for lines in pointsData: if lines.strip(): pointsList.append(map(float, lines.strip().split()[:3])) hourlyIlluminanceValues = [] with open(annualResultsFile) as resData: for lines in resData: lines = lines.strip() if lines: try: tempIllData = map(float, lines.split()) hourlyIlluminanceValues.append(tempIllData) except ValueError: pass if calcASE: #As per IES-LM-83-12 ASE is the percent of sensors in the analysis area that are # found to be exposed to more than 1000lux of direct sunlight for more than 250hrs # per year. The present script allows user to define what the lux and hour value # should be. sensorIllumValues = zip(*hourlyIlluminanceValues) aseData = [] for idx, sensor in enumerate(sensorIllumValues): x, y, z = pointsList[idx] countAboveThreshold = len( [val for val in sensor if val > illumForASE]) aseData.append([x, y, z, countAboveThreshold]) sensorsWithHoursAboveLimit = [ hourCount for x, y, z, hourCount in aseData if hourCount > hoursForASE ] percentOfSensors = len(sensorsWithHoursAboveLimit) / len( pointsList) * 100 print( "ASE RESULT: Percent of sensors above %sLux for more than %s hours = %s%%" % (illumForASE, hoursForASE, percentOfSensors)) if calcASEptsSummary: print( "ASE RESULT: Location of sensors and # of hours above threshold of %sLux\n" % illumForASE) print("%12s %12s %12s %12s" % ('xCor', 'yCor', 'zCor', 'Hours')) for x, y, z, countAboveThreshold in aseData: print("%12.4f %12.4f %12.4f %12d" % (x, y, z, countAboveThreshold)) #Stage 2: Check values from ASE calc against if hoyForValidation in xrange(8760): print(statusMsg('Starting validation calcs.')) #Create a sky for a point in time calc. timeStamp = monthDateTime[hoyForValidation] month, day, hour = timeStamp.month, timeStamp.day, timeStamp.hour + 0.5 print( "VALIDATION RESULTS: Comparing illuminancevalues for (month,day,hour):(%s, %s, %s)\n" % (month, day, hour)) # msgString="\t\tComparing values for (month,day,hour):(%s, %s, %s)"%(month,day,hour) # print(msgString) # print("\t\t%s\n"%("~"*len(msgString))) genParam = GendaylitParameters() genParam.meridian = meridian genParam.longitude = longitude genParam.latitude = latitude genDay = Gendaylit() genParam.dirNormDifHorzIrrad = ( epw.directNormalRadiation[hoyForValidation], epw.diffuseHorizontalRadiation[hoyForValidation]) genDay.monthDayHour = (month, day, hour) genDay.gendaylitParameters = genParam genDay.outputFile = r'tests/ASEtest/genday.sky' genDay.execute() octGenday = Oconv() octGenday.sceneFiles = sceneData + [r'tests/ASEtest/genday.sky'] octGenday.outputFile = r'tests/ASEtest/roomSunGenday.oct' octGenday.execute() rtcPara = GridBasedParameters() rtcPara.irradianceCalc = True rtcPara.ambientBounces = 0 rtcPara.directJitter = 1 rtcPara.directCertainty = 1 rtcPara.directThreshold = 0 rtc = Rtrace() rtc.radianceParameters = rtcPara rtc.octreeFile = r'tests/ASEtest/roomSunGenday.oct' rtc.pointsFile = pointsFile rtc.outputFile = r'tests/ASEtest/rtraceTest.res' rtc.execute() #This is a quick hack to get values out of rtrace. I think the option to turn of header is # nested inside. rtraceIllValues = [] with open(r'tests/ASEtest/rtraceTest.res') as resFile: for lines in resFile: lines = lines.strip() if lines: try: r, g, b = map(float, lines.strip().split()) r, g, b = r * 47.4, g * 119.9, b * 11.6 rtraceIllValues.append(r + g + b) except ValueError: pass print("%12s %12s %12s %12s %12s %12s%%" % ('xCor', 'yCor', 'zCor', 'Annual-Ill', 'Rtrace-Ill', 'Diff')) for point, aseVal, rtraceVal in zip( pointsList, hourlyIlluminanceValues[hoyForValidation], rtraceIllValues): x, y, z = point if rtraceVal: diff = (rtraceVal - aseVal) / rtraceVal aseVal, rtraceVal, diff = map(lambda x: round(x, 4), (aseVal, rtraceVal, diff * 100)) else: aseVal, rtraceVal, diff = 0.0, 0.0, 0.0 aseVal, rtraceVal, diff = map(lambda x: round(x, 4), (aseVal, rtraceVal, diff * 100)) print("%12.4f %12.4f %12.4f %12.4f %12.4f %12.4f%%" % (x, y, z, aseVal, rtraceVal, diff)) print(statusMsg('Done!'))