Ejemplo n.º 1
0
    def renameResultFiles(self):
        """Rename result files to be named based on month_day_hour."""
        if not hasattr(self.skyMatrix, 'isSkyMatrix'):
            return self.resultsFile

        names = []
        for f, h in zip(self.results(), self.skyMatrix.hoys):
            hoy = DateTime.fromHoy(h)
            name = '%02d_%02d_%02d.hdr' % (hoy.month, hoy.day, int(hoy.hour))
            tf = f[:-8] + name
            if os.path.isfile(tf):
                try:
                    os.remove(tf)
                except:
                    print "Failed to remove %s." % tf

            try:
                os.rename(f, tf)
            except WindowsError:
                msg = 'Failed to rename (%s) to (%s)\n\t' \
                    'Access is denied. Do you have the file open?' % (f, tf)
                print msg
                names.append(f)
            else:
                names.append(tf)

        self.resultsFile = names
        return self.resultsFile
Ejemplo n.º 2
0
    def execute(self, workingDir, reuse=True):
        """Generate sun matrix.

        Args:
            workingDir: Folder to execute and write the output.
            reuse: Reuse the matrix if already existed in the folder.

        Returns:
            Full path to analemma, sunlist and sunmatrix.
        """
        fp = os.path.join(workingDir, self.analemmafile)
        lfp = os.path.join(workingDir, self.sunlistfile)
        mfp = os.path.join(workingDir, self.sunmtxfile)
        hrf = os.path.join(workingDir, self.name + '.hrs')

        if reuse:
            if self.hoursMatch(hrf):
                for f in (fp, lfp, mfp):
                    if not os.path.isfile(f):
                        break
                else:
                    print('Found the sun matrix!')
                    return fp, lfp, mfp

        with open(hrf, 'wb') as outf:
            outf.write(','.join(str(h) for h in self.hoys) + '\n')

        # written based on scripts/analemma provided by @sariths
        wea = self.wea
        monthDateTime = (DateTime.fromHoy(idx) for idx in self.hoys)
        latitude, longitude = wea.location.latitude, -wea.location.longitude
        meridian = -(15 * wea.location.timezone)

        gdlit = Gendaylit(rotation=self.north)
        gdlit.gendaylitParameters.meridian = meridian
        gdlit.gendaylitParameters.longitude = longitude
        gdlit.gendaylitParameters.latitude = latitude

        sunValues = []
        sunUpHours = []  # collect hours that sun is up

        # use gendaylit to calculate radiation values for each hour.
        print('Calculating sun positions and radiation values.')
        with open(os.devnull, 'w') as warningDump:
            for timeStamp in monthDateTime:
                month, day, hour = timeStamp.month, timeStamp.day, timeStamp.hour + 0.5
                dnr, dhr = wea.directNormalRadiation[timeStamp.intHOY], \
                    wea.diffuseHorizontalRadiation[timeStamp.intHOY]

                if dnr + dhr == 0:
                    # no need to run gendaylit as there is no radiation / sun
                    continue

                # update gendaylit params
                gdlit.gendaylitParameters.dirNormDifHorzIrrad = (dnr, dhr)
                gdlit.monthDayHour = (month, day, hour)
                cmdgd, ro = tuple(
                    c.strip()
                    for c in gdlit.toRadString().split('>')[0].split('|'))
                # run cmd, get results in the form of a list of lines.
                cmdRun = Popen(cmdgd, stdout=PIPE, stderr=warningDump)
                gd = Popen(ro, stdin=cmdRun.stdout, stdout=PIPE)
                data = gd.communicate()[0].split('\n')
                # clean the output by throwing out comments and brightness functions.
                sunCurrentValue = []
                for lines in data[:-6]:
                    if lines[0] == "#":
                        continue
                    ls = lines.strip()
                    if ls:
                        sunCurrentValue.extend(ls.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)
                    sunUpHours.append(timeStamp.intHOY)

        numOfSuns = len(sunUpHours)

        print('Writing sun positions and radiation values to {}'.format(fp))
        # create solar discs.
        with open(fp, 'w') as annfile:
            annfile.write("\n".join((" ".join(sun) for sun in sunValues)))
            annfile.write('\n')

        print('Writing list of suns to {}'.format(lfp))
        # create list of suns.
        with open(lfp, 'w') as sunlist:
            sunlist.write("\n".join(
                ("solar%s" % (idx + 1) for idx in xrange(numOfSuns))))
            sunlist.write('\n')

        # 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=%s' % len(self.hoys)]
        fileHeader += ['NCOMP=3']
        fileHeader += ['FORMAT=ascii']

        print('Writing sun matrix to {}'.format(mfp))
        # Write the matrix to file.
        with open(mfp, 'w') as sunMtx:
            sunMtx.write('\n'.join(fileHeader) + '\n' + '\n')
            for idx, sunValue in enumerate(sunValues):
                sunRadList = ['0 0 0'] * len(self.hoys)
                sunRadList[sunUpHours[idx]] = ' '.join(sunValue[6:9])
                sunMtx.write('\n'.join(sunRadList) + '\n\n')

            # This last one is for the ground.
            sunRadList = ['0 0 0'] * len(self.hoys)
            sunMtx.write('\n'.join(sunRadList))
            sunMtx.write('\n')

        return fp, lfp, mfp
Ejemplo n.º 3
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!'))
Ejemplo n.º 4
0
try:
    from honeybee.radiance.recipe.solaraccess.gridbased import SolarAccessGridBased
except ImportError as e:
    raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e))

if _analysisGrid:
    _modes = ('total', 'direct', 'diffuse')
    _mode_ = _mode_ or 0
    hoy_ = hoy_ or _analysisGrid.hoys[0]
    assert _mode_ < 3, '_mode_ can only be 0: total, 1: direct or 2: sky.'

    try:
        states = eval(blindStates_)
    except Exception as e:
        if blindStates_:
            raise TypeError('Failed to read blindStates_:\n{}'.format(e))
        states = None

    print('Loading {} values for {}.'.format(_modes[_mode_],
                                             DateTime.fromHoy(hoy_)))

    if _mode_ < 2:
        values = (v[_mode_]
                  for v in _analysisGrid.combinedValueById(hoy_, states))
    else:
        cValues = _analysisGrid.combinedValueById(hoy_, states)
        values = (v[0] - v[1] for v in cValues)

# assign outputs to OUT
OUT = (values, )
Ejemplo n.º 5
0
 def hoy(self, v):
     """Set datetime by hour of year."""
     self._datetime = DateTime.fromHoy(v)
Ejemplo n.º 6
0
    def execute(self, workingDir, reuse=True):
        """Generate sun matrix.

        Args:
            workingDir: Folder to execute and write the output.
            reuse: Reuse the matrix if already existed in the folder.

        Returns:
            Full path to analemma, sunlist and sunmatrix.
        """
        fp = os.path.join(workingDir, self.analemmafile)
        lfp = os.path.join(workingDir, self.sunlistfile)
        mfp = os.path.join(workingDir, self.sunmtxfile)
        hrf = os.path.join(workingDir, self.name + '.hrs')
        outputType = self.skyType

        if reuse:
            if self.hoursMatch(hrf):
                for f in (fp, lfp, mfp):
                    if not os.path.isfile(f):
                        break
                else:
                    return fp, lfp, mfp

        with open(hrf, 'wb') as outf:
            outf.write(','.join(str(h) for h in self.hoys) + '\n')

        wea = self.wea
        monthDateTime = (DateTime.fromHoy(idx) for idx in self.hoys)
        latitude, longitude = wea.location.latitude, -wea.location.longitude

        sp = Sunpath.fromLocation(wea.location, self.north)
        solarradiances = []
        sunValues = []
        sunUpHours = []  # collect hours that sun is up
        solarstring = \
            'void light solar{0} 0 0 3 {1} {1} {1} ' \
            'solar{0} source sun 0 0 4 {2:.6f} {3:.6f} {4:.6f} 0.533'

        # use gendaylit to calculate radiation values for each hour.
        print('Calculating sun positions and radiation values.')
        count = 0
        for timecount, timeStamp in enumerate(monthDateTime):
            month, day, hour = timeStamp.month, timeStamp.day, timeStamp.hour + 0.5
            dnr, dhr = int(wea.directNormalRadiation[timeStamp.intHOY]), \
                int(wea.diffuseHorizontalRadiation[timeStamp.intHOY])
            if dnr == 0:
                continue
            count += 1
            sun = sp.calculateSun(month, day, hour)
            if sun.altitude < 0:
                continue
            x, y, z = sun.sunVector
            solarradiance = \
                int(gendaylit(sun.altitude, month, day, hour, dnr, dhr, outputType))
            curSunDefinition = solarstring.format(count, solarradiance, -x, -y,
                                                  -z)
            solarradiances.append(solarradiance)
            sunValues.append(curSunDefinition)
            # keep the number of hour relative to hoys in this sun matrix
            sunUpHours.append(timecount)

        sunCount = len(sunUpHours)

        assert sunCount > 0, ValueError('There is 0 sun up hours!')

        print('# Number of sun up hours: %d' % sunCount)
        print('Writing sun positions and radiation values to {}'.format(fp))
        # create solar discs.
        with open(fp, 'w') as annfile:
            annfile.write("\n".join(sunValues))
            annfile.write('\n')

        print('Writing list of suns to {}'.format(lfp))
        # create list of suns.
        with open(lfp, 'w') as sunlist:
            sunlist.write("\n".join(
                ("solar%s" % (idx + 1) for idx in xrange(sunCount))))
            sunlist.write('\n')

        # Start creating header for the sun matrix.
        fileHeader = ['#?RADIANCE']
        fileHeader += ['Sun matrix created by Honeybee']
        fileHeader += ['LATLONG= %s %s' % (latitude, -longitude)]
        fileHeader += ['NROWS=%s' % sunCount]
        fileHeader += ['NCOLS=%s' % len(self.hoys)]
        fileHeader += ['NCOMP=3']
        fileHeader += ['FORMAT=ascii']

        print('Writing sun matrix to {}'.format(mfp))
        # Write the matrix to file.
        with open(mfp, 'w') as sunMtx:
            sunMtx.write('\n'.join(fileHeader) + '\n' + '\n')
            for idx, sunValue in enumerate(solarradiances):
                sunRadList = ['0 0 0'] * len(self.hoys)
                sunRadList[sunUpHours[idx]] = '{0} {0} {0}'.format(sunValue)
                sunMtx.write('\n'.join(sunRadList) + '\n\n')

            sunMtx.write('\n')

        return fp, lfp, mfp