Python for light simulation

Hi all,
I have a question. I found this code for the ladybug tool which shows how to do light simulation given one room created on python. My problem is that I have a layout and 3 rooms as shown in the picture, so I want to modify this code so that I put the windows on the layout and I conduct the light simulation for the three rooms (1,2,3). However, the given code will not work because the windows are not located only in the rooms so I want to consider that each room has walls and a window and that the light is passed through the windows to the rooms. what changes to the codes are needed to tailor it to my problem? Note that this layout I have is also generated using python.
Can any one help me modify this code to account for this situation?

Thanks so much!

from honeybee.room import Room
from honeybee.radiance.material.glass import Glass
from honeybee.radiance.sky.certainIlluminance import CertainIlluminanceLevel
from honeybee.radiance.recipe.pointintime.gridbased import GridBased

# create a test room

room = Room(origin=(0, 0, 3.2), width=4.2, depth=6, height=3.2,
rotation_angle=45)

# add fenestration

# # add a window to the back wall

room.add_fenestration_surface(wall_name=‘back’, width=2, height=2, sill_height=0.7)

# add another window with custom material. This time to the right wall

glass_60 = Glass.by_single_trans_value(‘tvis_0.6’, 0.6)
room.add_fenestration_surface(‘right’, 4, 1.5, 1.2, radiance_material=glass_60)

# run a grid-based analysis for this room

# generate the sky

sky = CertainIlluminanceLevel(illuminance_value=2000)

# generate grid of test points

analysis_grid = room.generate_test_points(grid_size=0.5, height=0.75)

# put the recipe together

rp = GridBased(sky=sky, analysis_grids=(analysis_grid,), simulation_type=0,
hb_objects=(room,))

# write and run the analysis

batch_file = rp.write(target_folder=r’c:\ladybug’, project_name=‘room’)
rp.run(batch_file, debug=False)

# results - in this case it will be an analysis grid

result = rp.results()[0]

# print the values for each point

for value in result.combined_value_by_id():
print(‘illuminance value: %d lux’ % value[0])

Hi,@fhalawa1 Could you tell us why you persist to use Python for light simulation? I think it is much easier to do light simulation in Rhino/Grasshooper.

Could you point to where you found this code? Would be good to put it in the context of a specific version of honeybee.
Also, mind giving a slightly clearer drawing of the space you are wanting to simulate? (Not sure if I’m looking at plan view or side view or what the window dimensions are like)
Also, how much python do you know right now? Have you used it before?
Finally, how urgent is this? Is the room in question at risk of catastrophic underlighting? :stuck_out_tongue:

Hi @AntoineDao and @minggangyin
Well, I am not an architect but a researcher in healthcare design. I am developing a tool to generate a schematic design on python and conduct light simulation for a specific version, so eventually I am going to have many experiments and for each I want to conduct light simulation, so it is not handy to use the software. I found the code on the official honey bee website here:

For the layout, it is a schematic one (just to show an example of the output of my python code), and for now I will have assumptions that every room has a window placed on the top (I have to figure out this). I just want to know the python approach and the functions needed on how to run a simple illumination simulation for the picture I shown given several rooms inside a layout. The python code I provided uses light simulation for one room but it does not take into account simulating a layout. I do not want to be accurate in terms of material used, exact location of windows. All I need is to know what changes to the code I need to do to let light enters from two windows as shown in the picture above and then how lighting will be affecting the 3 rooms (let is assume that each room has a window on the top).

I am good in python as an engineer.
it is urgent from research point of view not from a lighting point of view :stuck_out_tongue:

Right I get you. And so what issue are you running against? Is the code running and not giving results?

Also, which platform are you using (Windows, MacOS or Linux)?

Finally do you know what kind of daylight simulation you want to run? Daylight Factor? Or something a bit more realistic like a yearly study or a point in time study? Are you wanting to render the inside of the rooms based on realistic daylight?

Thanks, Antonie,
The code I sent works perfectly to simulate how sky light enters to one room right? So it gives me the lux values per grids (as explaiend in the code) But this is not how light simulation works for a layout Light will enter from the window and if the room is placed in the middle of the layout the room will get less light, right? If there is a room blocking light from passing by to the next room this should be accounted for. The code example is too basic: First python creates a rectangle, saves it as a room, and then places windows on an edge then creates grids and then the simulation is run. I use python spyder on windows and I got honeybee and all needed libraries installed. Here are the specific requirements I need~

  1. First how to pull weather data for a specific location (say new york) where I am?
  2. How can the simulation understand the orientation of the building? Maybe there is a funciton that says Getorientation(north, south) … I am not sure how does honeybee do this.
  3. How to adjust the model to understand that I have rooms inside a layout so that walls in these rooms would hinder light from passing by (In other word, how to conduct a simple simulation study for the layout showed)

Finally to answer your questions : I do not need to render, and daylight simulation is fine (if I can get number of hours on direct sun per year ) that would be perfect.

No. The code that is posted adds two windows to room walls. It’s not sklights. You can read it in the comments.

I’m not sure if I understand what you mean by a “layout” but there is no such a rule in general.

I already replied to this question under similar topic. See here:

Please do not open duplicated topics so we can help you easier.

In honeybee Y axis is north. In the example the room is rotated using rotation_angle argument.

room = Room(origin=(0, 0, 3.2), width=4.2, depth=6, height=3.2, rotation_angle=45)

You have to create each room separately and then add them all to the recipe instead having a single room. In that case you will get a single scene with 3 rooms.

EDIT: You will also need 3 analysis grids, one for each room if you are interested to get the values inside each of the 3 rooms.


room_1 = Room(origin=(x1, y1, z1), ...)
room_2 = Room(origin=(x2, y2, z2), ...)
room_3 = Room(origin=(x3, y3, z3), ...)

# ...


rp = GridBased(
    sky=sky,
    analysis_grids=(analysis_grid_1, analysis_grid_2, analysis_grid_3),
    simulation_type=0,
    hb_objects=(room_1, room_2, room_3)
)

See SolarAccess recipe. You should use that instead of the grid-based recipe and you will need sun vectors which you can generate using sun-path. Here is an example:

Mostapha, @mostapha
thanks a lot for your reply, it is really helpful!
I like the idea of defining 3 rooms separately. Then my question now is what if room 1 is placed not on the envelope (to the exterior) of the floorplan. What if it is placed inside, like the picture here? In this case, light will enter to the floorplan through the exterior window, and since the room has a window, a portion of light might pass through. How to account for this case in the code?

The short answer is yes.

Honeybee uses Radiance for daylight simulation and Radiance scene is created from faces and there is no concept of room. In other words the rooms are broken down into several faces with their modifier (aka materials). These geometries in addition to sky get compiled into an octree which will be passed to rtrace for ray-tracing.

Radiance is a backwards ray-tracer which means it goes backwards from the sensor points and tries to find light sources - in your case the Sky. So it doesn’t really know the structure of your scene. If a ray hits a glass geometry is passed through until it hits the next one. If that next surface is also glass it will pass through that too. If it is opaque then it will be reflected from that face and so on. This means that your scene will be totally fine for the study as long as you set the parameters correctly. For instance you will need enough ambient bounces (ab) to ensure the rays get a chance to leave the first room and see the other window. See here to learn more about radiance ambient parameters: https://www.radiance-online.org/community/workshops/2014-london/presentations/day1/Mardaljevic_AmbientCrash.pdf

1 Like

@mostapha, thanks for answering. I think my question was not so clear tho:
How to let the code understand that light will only enter the floor plan through the main windows in the exterior part of the floor plan (the envenlop) and what line of codes needed?

Previously you have suggested to use this concept when I have multiple rooms:

room_1 = Room(origin=(x1, y1, z1), …)
room_2 = Room(origin=(x2, y2, z2), …)
room_3 = Room(origin=(x3, y3, z3), …)

You suggested to add them to a recipe and then run the model, that is fine, but the main issue that is missing is that I need another line of code to define the floorplan boundaries and the main windows where light will enter from… Is there any line of code you suggest to use to define the exteriors of the floorplan and let the library know that the three rooms are located within those boundaries?
Thanks again for taking the time to answer my question

@mostapha

Hi Mostapha, here is an example of my question:
I have the three rooms, and added a grid for each one, I also added them to the recipe… What is missing, the line of code that define the main windows where natural light will path through,… how to do that ? Can you send me the line of code needed? Thanks very much!
room_1 = Room(origin=(x1, y1, z1), …)
room_2 = Room(origin=(x2, y2, z2), …)
room_3 = Room(origin=(x3, y3, z3), …)
rp = GridBased(
sky=sky,
analysis_grids=(analysis_grid_1, analysis_grid_2, analysis_grid_3),
simulation_type=0,
hb_objects=(room_1, room_2, room_3)

Can’t you add that as room_4? You won’t need a separate grid for it but it can be added to the scene just like any other room.

@mostapha: Appreciate your help!

I pulled together all the points you mentioned and I wrote this code, but it is not working and I will show you what I wrote and what is the error, so if you bear with me step by step please…
First, here is the example that I want to simulate using Python.

Let us assume that the location is Duluth… so first I pulled up the duluth epw weather data from http://www.ladybug.tools/epwmap/. saved it to the same file of the code …

#Step 1:
Pull the weather data.

from ladybug.wea import Wea
from honeybee.radiance.sky.climatebased import ClimateBased

epw_file = 'USA_MN_Duluth.727450_TMY2.epw'
wea = Wea.from_epw_file(epw_file)
sky = ClimateBased(wea, month=6, day=21, hour=12.0, direct_radiation=0, diffuse_radiation=0, north=0,suffix=None)

#Question:what is the direct_radiation=0, diffuse_radiation=0 code did not work without them?**

#Step 2: Define the rooms and floorplan

from honeybee.room import Room
from honeybee.radiance.material.glass import Glass
from honeybee.radiance.sky.certainIlluminance import CertainIlluminanceLevel
from honeybee.radiance.recipe.pointintime.gridbased import GridBased

Floorplan_Boundries = Room(origin=(0, 0, 0), width=50, depth=50, height=3.2,
            rotation_angle=45)

room_1 = Room(origin=(1, 0, 0), width=4.2, depth=6, height=3.2,
            rotation_angle=45)


room_2 = Room(origin=(10, 1, 0), width=4.2, depth=6, height=3.2,
            rotation_angle=45)

room_3 = Room(origin=(10, 20, 0), width=4.2, depth=6, height=3.2,
            rotation_angle=45)

#Step 3:
Add windows and here I have a question: How to specify the exact location of the window, now it assumes that it is on the back wall or right wall, but what if I want to say it is on x=10, y =0? What if I have two windows and not one?

room_1.add_fenestration_surface(wall_name='back', width=2, height=2, sill_height=0.7)

room_2.add_fenestration_surface(wall_name='back', width=2, height=2, sill_height=0.7)

room_3.add_fenestration_surface(wall_name='back', width=2, height=2, sill_height=0.7)

Floorplan_Boundries.add_fenestration_surface(wall_name='back', width=2, height=2, sill_height=0.7)

#Step 4
Generate grids for ONLY for the 3 rooms…

#generate grid of test points for the actual rooms 
analysis_grid_1 = room_1.generate_test_points(grid_size=0.5, height=0.75)

analysis_grid_2 = room_2.generate_test_points(grid_size=0.5, height=0.75)

analysis_grid_3 = room_3.generate_test_points(grid_size=0.5, height=0.75)

#Put together the recipe for the floorplan and the 3 rooms
rp = GridBased(
    sky=sky,
    analysis_grids=(analysis_grid_1, analysis_grid_2, analysis_grid_3),
    simulation_type=0,
    hb_objects=(room_1, room_2, room_3, Floorplan_Boundries)
)

#run simulation 


batch_file = rp.write(target_folder=r'c:\ladybug', project_name='room')
rp.run(batch_file, debug=False)
#results - in this case it will be an analysis grid
result = rp.results()[0]

Well, tried to run this I get the following error: WEA [DULUTH] is not a Ladybug Location.
I do not get what is this error…

So can you assist me answer the questions provided above please? Also, would the code understand now that the natural lighting will enter from the main window defined in Floorplan and will pass through the back windows in rooms 1, 2 , 3 ? Based on what you explained, the library is smart enough to do that without additional code lines, right?

If you want you can create the sky from location and direct and diffuse values. In your case you should use from_wea classmethod. That’s where you made a mistake. Change:

sky = ClimateBased(wea, month=6, day=21, hour=12.0, direct_radiation=0, diffuse_radiation=0, north=0,suffix=None)

to

sky = ClimateBased.from_wea(wea, month=6, day=21, hour=12.0)

and it will take the direct and diffuse irradiance from the wea.

Yes. Radiance takes care of it. Just make sure to set the Radiance parameters correctly. For your case I would start from 3 or for ambient bounces. You should pass the parameters when you create a recipe. See the API documentation for more information.

@mostapha
It worked, thanks.
I still have questions regarding the function:
Floorplan_Boundries.add_fenestration_surface(wall_name=‘back’, width=2, height=2, sill_height=0.7)

  1. How to specific the x,y locations of windows? For example:

  1. Also: How to run the simulation for a period of time (between June- July, 8am-5pm)… any function to do that?

  2. Lastly, is the value Lux , calculated based on the average for the given time period?

Room.add_fenestration_surface only generates a centered window. You have to use other methods for wall itself to add two windows to the same wall. For more information see add_fenestration_surface_by_size method for HBSurface.

Whne you call Room.add_fenestration_surface it finds the face by name and then calls HBSurface.add_fenestration_surface_by_size which calculates the centered fenestration and passes it to add_fenestration_surface. You can create your fenestration surfaces from vertices and add them directly to wall surface using add_fenestration_surface.

To get the wall you can use their name. For instance you can get the back wall by using room.backWall.

GridBased recipe is for calculating the results for a single point-in-time. If you want more than a single hour you should use an annual simulation. See annual daylight recipe for grid-based studies. Note that it takes a sky matrix and not a sky anymore. You can generate the sky matrix using SkyMtx class. For some reason it is missing from the documentation but you can see the documentation on GitHub.

https://github.com/ladybug-tools/honeybee/blob/master/honeybee/radiance/sky/skymatrix.py#L8

The results will be for each hour of the study which is indicated in hoys input in SkyMtx. You can average them for each day or during all the hours if you would like to get the averaged values.

Thanks @mostapha,
I think it is still not clear how to add two windows to the wall with specific coordinates. I want to two windows located on say x=4 and y=5 for the first one, and x=10 and y=5 for the second one, and assume similar widths and heights… Can you please write to me the line of codes needed for this ?

@mostapha
Tried to use the annual simulation you suggested but I get this error:
from ._skyBase import RadianceSky
ValueError: Attempted relative import in non-package

I am going to double check with you if I am missing something:
1) Import package for Skymatrix using
from ._skyBase import RadianceSky
from …command.gendaymtx import Gendaymtx
from …parameters.gendaymtx import GendaymtxParameters
import os
from honeybee.radiance.recipe.daylightcoeff.gridbased.DaylightCoeffGridBased import GridBased

2) Remove sky = ClimateBased.from_wea(wea, month=6, day=21, hour=12.0)
and replace it with
sky_mtx= SkyMatrix(RadianceSky)

3) The recipe becomes:

rp = GridBased(
sky_mtx,
analysis_grids=(analysis_grid_1, analysis_grid_2, analysis_grid_3),
simulation_type=0,
hb_objects=(room_1, room_2, room_3, Floorplan_Boundries)
)

Am i missing something?

@fhalawa1,

I believe that error is occurring because you’re referencing the honeybee package relatively (based on directory structure), in an incorrect context. Basically, you’re making a python mistake, it doesn’t have anything to do with Honeybee.

Are you installing Honeybee through pip, or are you trying to run your script within the git cloned directory?

If the former, you should be able to call the honeybee package explicitly (using the actual name). If the latter, you need to use the module switch, and be in the correct place in the directory, when you call the script in the command line. An example of this can be seen here: https://github.com/ladybug-tools/uwg#example

S