예제 #1
0
    def setUp(self):
        """Set up the test case by initiating the class."""
        self.oconv = Oconv(output_name='tests/room/testrun/room.oct',
                           scene_files=('tests/room/room.mat',
                                        'tests/room/uniform.sky',
                                        'tests/room/room.rad'))

        self.output_file = None
예제 #2
0
class OconvTestCase(unittest.TestCase):
    """Test for (honeybee/radiance/command/oconv.py)."""

    # preparing to test
    def setUp(self):
        """Set up the test case by initiating the class."""
        self.oconv = Oconv(output_name='tests/room/testrun/room.oct',
                           scene_files=('tests/room/room.mat',
                                        'tests/room/uniform.sky',
                                        'tests/room/room.rad'))

        self.output_file = None

    # ending the test
    def tearDown(self):
        """Cleaning up after the test."""
        pass

    # test default values
    def test_default_values(self):
        """Test the command runs correctly."""
        self.output_file = self.oconv.execute()
        assert self.output_file == 'tests/room/testrun/room.oct'
        assert os.path.normpath(self.output_file.normpath) == \
            os.path.normpath('tests/room/testrun/room.oct')
class OconvTestCase(unittest.TestCase):
    """Test for (honeybee/radiance/command/oconv.py)."""

    # preparing to test
    def setUp(self):
        """Set up the test case by initiating the class."""
        self.oconv = Oconv(outputName='./tests/room/testrun/room.oct',
                           sceneFiles=('./tests/room/room.mat',
                                       './tests/room/uniform.sky',
                                       './tests/room/room.rad'))

        self.outputFile = None

    # ending the test
    def tearDown(self):
        """Cleaning up after the test."""
        if self.outputFile is not None:
            # remove the file which is just created
            os.remove(str(self.outputFile))

    # test default values
    def test_default_values(self):
        """Test the command runs correctly."""
        self.outputFile = self.oconv.execute()
        self.assertEqual(self.outputFile.normpath,
                         'tests/room/testrun/room.oct')
class OconvTestCase(unittest.TestCase):
    """Test for (honeybee/radiance/command/oconv.py)."""

    # preparing to test
    def setUp(self):
        """Set up the test case by initiating the class."""
        self.oconv = Oconv(
            output_name='./tests/room/testrun/room.oct',
            scene_files=('./tests/room/room.mat',
                         './tests/room/uniform.sky',
                         './tests/room/room.rad')
        )

        self.output_file = None

    # ending the test
    def tearDown(self):
        """Cleaning up after the test."""
        if self.output_file is not None:
            # remove the file which is just created
            os.remove(str(self.output_file))

    # test default values
    def test_default_values(self):
        """Test the command runs correctly."""
        self.output_file = self.oconv.execute()
        self.assertEqual(self.output_file.normpath, 'tests/room/testrun/room.oct')
    def setUp(self):
        """Set up the test case by initiating the class."""
        self.oconv = Oconv(
            output_name='./tests/room/testrun/room.oct',
            scene_files=('./tests/room/room.mat',
                         './tests/room/uniform.sky',
                         './tests/room/room.rad')
        )

        self.output_file = None
예제 #6
0
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
예제 #7
0
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!'))