示例#1
0
def point(i):
    return Translated(i, 0, 0, Sphere(1))
示例#2
0
 def __call__(self, r):
     sphere =Sphere(r/10.)
     return Translated(self.pos_x,0,0,sphere)
示例#3
0
def irradiance_distribution(meteo,
                            geo_location,
                            irradiance_unit,
                            time_zone='Europe/Paris',
                            turtle_sectors='46',
                            turtle_format='uoc',
                            sun2scene=None,
                            rotation_angle=0.,
                            icosphere_level=None):
    """Calculates irradiance distribution over a semi-hemisphere surrounding the plant [umol m-2 s-1].

    Args:
        meteo (DataFrame): meteo data having the following columns:
            time (datetime): UTC time
            Tac (float): [°C] air temperature
            hs (float): (%) air relative humidity
            Rg or PPFD (float): respectively global [W m-2] or photosynthetic photon flux density [umol m-2 s-1]
            u (float): [m s-1] wind speed
            Ca (float): [ppm] CO2 concentration in the air
            Pa (float): [kPa] atmospheric pressure
        geo_location: tuple of (latitude [°], longitude [°], elevation [°])
        irradiance_unit (str): unit of the irradiance flux density,
            one of ('Rg_Watt/m2', 'RgPAR_Watt/m2', 'PPFD_umol/m2/s')
        time_zone (str): a 'pytz.timezone' (e.g. 'Europe/Paris')
        turtle_sectors (str): number of turtle sectors (see :func:`turtle` from `sky_tools` package)
        turtle_format (str): format irradiance distribution, could be 'soc', or 'uoc'
            (see :func:`turtle` from `sky_tools` package for details)
        sun2scene (pgl.scene): if provided, a sun object (sphere) is added to it
        rotation_angle (float): [°] counter clockwise azimuth between the default X-axis direction (South) and real
            direction of X-axis
        icosphere_level (int): the level of refinement of the dual icosphere
            (see :func:`alinea.astk.icosphere.turtle_dome` for details)

    Returns:
        [umol m-2 s-1] tuple of tuples, cumulative irradiance flux densities distributed across the semi-hemisphere
            surrounding the plant
        (float) [-] diffuse-to-total irradiance ratio

    Notes:
        meteo data can consist of only one line (single event) or multiple lines.
            In the latter case, this function returns accumulated irradiance throughtout the entire periode with sun
            positions corresponding to each time step.


    TODO: replace by the icosphere procedure

    """
    diffuse_ratio = []
    nrj_sum = 0
    for idate, date in enumerate(meteo.index):

        if irradiance_unit.split('_')[0] == 'PPFD':
            energy = meteo.loc[date, :].PPFD
        else:
            try:
                energy = meteo.loc[date, :].Rg
            except:
                raise TypeError(
                    "'irradiance_unit' must be one of the following 'Rg_Watt/m2', 'RgPAR_Watt/m2' or'PPFD_umol/m2/s'."
                )

        # First check: convert irradiance to W m-2 (Spitters method always gets energy flux as Rg Watt m-2)
        corr = e_conv_Wm2(irradiance_unit)
        energy = energy * corr

        # Second check: Convert to UTC datetime
        latitude, longitude, elevation = [geo_location[x] for x in range(3)]
        temperature = meteo.Tac.values[0]
        date_utc, lst = local2solar(date, latitude, longitude, time_zone,
                                    temperature)
        doy_utc = date_utc.timetuple().tm_yday
        hour_utc = date_utc.hour + date_utc.minute / 60.
        # R: Attention, ne renvoie pas exactement le même RdRsH que celui du noeud 'spitters_horaire' dans topvine.
        diffuse_ratio_hourly = RdRsH(energy, doy_utc, hour_utc, latitude)
        diffuse_ratio.append(diffuse_ratio_hourly * energy)
        nrj_sum += energy

        # Third and final check: it is always desirable to get energy as PPFD
        energy = energy * (0.48 * 4.6)

        irradiance_diff = diffuse_ratio_hourly * energy
        irradiance_dir = (1 - diffuse_ratio_hourly) * energy

        # diffuse irradiance
        if not icosphere_level:
            energy2, emission, direction, elevation, azimuth = turtle.turtle(
                sectors=turtle_sectors,
                format=turtle_format,
                energy=irradiance_diff)
        else:
            vert, fac = ico.turtle_dome(icosphere_level)
            direction = ico.sample_faces(vert, fac, iter=None,
                                         spheric=False).values()
            direction = [idirect[0] for idirect in direction]
            direction = map(lambda x: tuple(list(x[:2]) + [-x[2]]), direction)

        sky = list(
            zip(
                len(direction) * [irradiance_diff / len(direction)],
                direction))

        # direct irradiance
        sun = Gensun.Gensun()(Rsun=irradiance_dir,
                              DOY=doy_utc,
                              heureTU=hour_utc,
                              lat=latitude)
        sun = GetLightsSun.GetLightsSun(sun)
        sun_data = [(float(sun.split()[0]), (float(sun.split()[1]),
                                             float(sun.split()[2]),
                                             float(sun.split()[3])))]

        # diffuse irradiance (distributed over a dome) + direct irradiance (localized as point source(s))
        source = sky.__add__(sun_data)
        source = [list(isource) for isource in source]

        try:
            for j in range(len(source) - 1):
                source_cum[j][0] += source[j][0]
            source_cum.append(source[-1])
        except NameError:
            source_cum = []
            for isource in source:
                source_cum.append([isource[0], isource[1]])

        if date == meteo.index[-1]:
            source_cum = [tuple(isource) for isource in source_cum]

    # Rotate irradiance sources to cope with plant row orientation
    if rotation_angle != 0.:
        v_energy = [vec[0] for vec in source_cum]
        v_coord = [
            tuple(
                vector_rotation(vec[1], (0., 0., 1.), deg2rad(rotation_angle)))
            for vec in source_cum
        ]
        source_cum = zip(v_energy, v_coord)

    # Add Sun to an existing pgl.scene
    if sun2scene != None:
        xSun, ySun, zSun = -500. * array(
            [source_cum[-1][1][i] for i in range(3)])
        if zSun >= 0:
            ss = Translated(xSun, ySun, zSun, Sphere(20))
            sun = Shape(ss, Material('yellow', Color3(255, 255, 0)))
            sun2scene.add(sun)
        Viewer.display(sun2scene)

    # Diffuse_ratio mean
    if nrj_sum > 0:
        diffuse_ratio = sum(diffuse_ratio) / nrj_sum
    else:
        diffuse_ratio = 1

    # Filter black sources up to the penultimate (hsCaribu expect at least one source)
    source_cum = [v for v in source_cum if v[0] > 0]
    if len(source_cum) == 0:  # night
        source_cum = [(0, (0, 0, -1))]

    return source_cum, diffuse_ratio
示例#4
0
文件: view3d.py 项目: pradal/plantlab
def main():
    app = QtGui.QApplication(sys.argv)
    view = view3D()
    view.addToScene(Sphere())
    view.start()
    app.exec_()