We supply lighting to office fit-outs across Lahore and Karachi, and the drawings that reach us often have the same gap. Someone has worked out how many LED panel lights the room needs, and then the false-ceiling contractor turns up and finds that half the positions land on a T-bar, or right where the AC diffuser has to go. The panels get shuffled on site, by eye, and the rows end up crooked.
The count is the easy part. Putting that count onto a 600 mm grid so the rows look straight and the light stays even is where the time goes. So this post builds a small Python script that works out the count with the lumen method, searches the row and column layouts that actually fit the tiles, and prints an ASCII ceiling plan you can drop into the WhatsApp group with the contractor.
Treat it as a planning aid. For anything a client signs off, run the manufacturer's photometric file through DIALux or similar.
Four inputs and one formula
The lumen method says the number of fittings is N = (E × A) / (Φ × UF × MF), rounded up. E is the target illuminance in lux, A is the floor area, Φ is the rated output of one panel in lumens, and UF and MF are the utilisation and maintenance factors.
For desk-based office work, most specs we see here use 500 lux, which is the figure EN 12464-1 gives for writing, typing and reading. Agree it with the client in writing anyway. For Φ, take the bottom of the datasheet range, not the top. Our 36 W backlit LED panel light is listed at 3,240 to 3,888 lumens, so the script uses 3,240.
UF and MF are where the judgement sits. We default to 0.6 and 0.8 as placeholders. A pale room with a white ceiling earns a better UF than one lined with dark wood, and the MF should reflect real cleaning habits. Offices on a main road in Faisalabad or Multan collect a film of dust on the diffusers within weeks of an andhi, and nobody climbs up to wipe them.
Why a 600 mm grid turns this into a search
In an ideal layout, panels sit at equal spacing with half a spacing between the outer rows and the walls. On paper that's trivial. On a T-bar ceiling, every LED panel light centre has to fall on the centre of a tile, and tiles come in fixed 600 mm steps.
Take a room that's 7.2 by 4.8 metres, which is 12 tiles by 8. Four columns along the 12-tile side means one panel every three tiles, and the centres land exactly on tile centres. Three rows across the 8-tile side can't do that. Eight doesn't split into three equal whole-tile gaps, so at least one row ends up off its ideal position.
So the script tries every rows-by-columns combination for the required count and a few above it. It drops anything where the spacing is too wide for the ceiling height, snaps the rest to the grid and ranks them by how far the panels had to move. For the spacing limit we use 1.5 times the height from desk to ceiling as a placeholder. The real spacing-to-height ratio comes from the panel's photometric data.
The layout script
Standard library only, so it runs on any Python 3.7 or later.
import math
from dataclasses import dataclass
TILE = 0.6 # metres, nominal 600 x 600 mm T-bar grid
@dataclass
class Room:
length: float # metres, along the long wall
width: float # metres
ceiling: float # false ceiling height
workplane: float = 0.75
@dataclass
class Panel:
name: str
lumens: float # low end of the datasheet range
def panels_needed(room, panel, lux, uf=0.6, mf=0.8):
"""Lumen method, rounded up to whole panels."""
area = room.length * room.width
return math.ceil(lux * area / (panel.lumens * uf * mf))
def snap_axis(n, span):
"""Spread n panels evenly along one axis, snap each to a tile centre.
Returns (tile indices, offset of each from its ideal spot in mm)."""
picks, offsets = [], []
for i in range(n):
ideal = (i + 0.5) * span / n
idx = int(ideal // TILE)
picks.append(idx)
offsets.append(round(abs((idx + 0.5) * TILE - ideal) * 1000))
return picks, offsets
def candidates(room, count, shr=1.5, extra=4):
"""Try every rows x cols grid holding count..count+extra panels."""
h = room.ceiling - room.workplane
out = []
for total in range(count, count + extra + 1):
for rows in range(1, total + 1):
if total % rows:
continue
cols = total // rows
sx, sy = room.length / cols, room.width / rows
if max(sx, sy) > shr * h:
continue # too far apart for this mounting height
_, ox = snap_axis(cols, room.length)
_, oy = snap_axis(rows, room.width)
avg = round(sum(ox + oy) / len(ox + oy))
out.append((total, avg, rows, cols, sx, sy))
return sorted(out)[:5]
def plan(room, rows, cols, blocked=()):
"""ASCII ceiling plan. P = panel, A = AC diffuser, . = plain tile."""
nx, ny = round(room.length / TILE), round(room.width / TILE)
xs, _ = snap_axis(cols, room.length)
ys, _ = snap_axis(rows, room.width)
spots = {(x, y) for x in xs for y in ys}
for (x, y) in list(spots):
if (x, y) in blocked: # nudge one tile along the row
spots.discard((x, y))
spots.add((x + 1, y) if (x + 1, y) not in blocked else (x - 1, y))
for y in range(ny):
row = ""
for x in range(nx):
row += "A" if (x, y) in blocked else "P" if (x, y) in spots else "."
print(" ".join(row))
if name == "main":
room = Room(length=7.2, width=4.8, ceiling=2.7)
panel = Panel("36 W backlit, 595 mm", lumens=3240)
target = 500
n = panels_needed(room, panel, target)
print(f"{room.length} x {room.width} m at {target} lux: {n} panels minimum\n")
print("total avg-offset rows x cols spacing (long / short)")
for total, err, rows, cols, sx, sy in candidates(room, n):
print(f"{total:>5} {err:>7} mm {rows:>4} x {cols:<4} {sx:.2f} m / {sy:.2f} m")
print()
plan(room, rows=3, cols=4, blocked={(4, 1), (7, 6)})
Where the LED panel lights land in a 7.2 by 4.8 metre office
With a 2.7 m false ceiling, a 500 lux target and the 3,240-lumen figure, the script prints this:
7.2 x 4.8 m at 500 lux: 12 panels minimum
total avg-offset rows x cols spacing (long / short)
12 71 mm 3 x 4 1.80 m / 1.60 m
12 300 mm 2 x 6 1.20 m / 2.40 m
12 300 mm 4 x 3 2.40 m / 1.20 m
14 186 mm 2 x 7 1.03 m / 2.40 m
15 160 mm 3 x 5 1.44 m / 1.60 m
. . . . . . . . . . . .
. P . . A P . P . . P .
. . . . . . . . . . . .
. . . . . . . . . . . .
. P . . P . . P . . P .
. . . . . . . . . . . .
. P . . P . . A P . P .
. . . . . . . . . . . .
Twelve panels is the minimum, and twelve gives an average of about 540 lux, so there's a little headroom. The ranking shows why the search matters. The 2 x 6 and 4 x 3 layouts hold the same twelve panels, but every one of them sits a full 300 mm from its ideal spot. On this grid that means the ideal position is on a T-bar. The 3 x 4 layout averages only 71 mm.
It still isn't perfect. Look at the plan: the rows sit on tiles 1, 4 and 6, so the gap between the first two rows is 1.8 m and between the last two it's 1.2 m. That's the 8-tile problem from earlier.
Most clients accept it once they see it on paper. What they don't accept is discovering it after the tiles are up.
Dodging AC diffusers
In a lot of offices here, a ducted split unit feeds square supply diffusers and return grilles into the same grid, and the HVAC contractor fixes those positions first. The blocked argument takes their tile coordinates. Where an LED panel light collides with one, the script slides it one tile along the row, which is the A sitting next to a P in the second and seventh rows of the plan.
It's a crude rule, and on a busy ceiling it can push a panel right up against its neighbour. Read the plan rather than trusting it. If two diffusers sit in the same row, it's usually cleaner to shift that whole row by one tile than to nudge single panels.
What the script doesn't model
Load-shedding is the big one. Most offices put part of the lighting on a UPS or inverter, and the lazy way is one circuit for the panels nearest the board. That leaves one bright corner and a dark office when the supply drops. Use the plan to put every other LED panel light in each row on the backed-up circuit instead, so the room dims evenly. In this example six panels on backup give roughly 270 lux, which is enough to keep working through an outage.
Daylight is the other. A west-facing window wall in a Lahore summer floods that side of the room until late afternoon, so the row nearest the glass is often worth its own switch.
Getting real numbers in
Swap in your own room, ceiling height and the lumen figure from the datasheet of whatever panel you're quoting. If you're still choosing, our LED panel lights with the lumen figure on every model are a reasonable place to start.
And if you'd like a second pair of eyes on a layout before it goes to the contractor, Hyundai LED's lighting engineers are happy to go over the numbers with you.
Top comments (0)