Photography exposure
From Pynomo
Contents
Photography exposure
Photography exposure | |
![]() | |
author | Leif Roschier |
---|
Theory and background
References
Construction of the nomograph
Generated nomograph
Photography exposure | |
---|---|
![]() |
|
Generated portable document file (pdf): | File:Ex photo exposure.pdf |
Source code
""" ex_photo_exposure.py Photgraph exposure. Copyright (C) 2007-2008 Leif Roschier This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. """ from nomographer import * """ functions for solartime taken from solareqns.pdf from http://www.srrb.noaa.gov/highlights/sunrise/solareqns.PDF """ # fractional year def gamma(day): return 2*pi/365.0*(day-1+0.5) # equation of time def eq_time(day): gamma0=gamma(day) return 229.18*(0.000075+0.001868*cos(gamma0)-0.032077*sin(gamma0)\ -0.014615*cos(2*gamma0)-0.040849*sin(2*gamma0)) # mean correction, with constant correction we make less than 1.5 minutes error # in time axis temp_a=arange(0,2*pi,0.001) temp_b=eq_time(temp_a) correction=mean(temp_b) # this is about four minutes # declination def eq_declination(day): g0=gamma(day) return 0.006918-0.399912*cos(g0)+0.070257*sin(g0)-0.006758*cos(2*g0)\ +0.000907*sin(2*g0)-0.002697*cos(3*g0)+0.00148*sin(3*g0) def f1(dummy): return 0.0 def g1(fii): return cos(fii*pi/180.0) def f2(lat,day): dec=eq_declination(day) return (cos(lat*pi/180.0)*cos(dec))/(1.0+(cos(lat*pi/180.0)*cos(dec))) def g2(lat,day): dec=eq_declination(day) # in radians return (sin(lat*pi/180.0)*sin(dec))/(1.0+(cos(lat*pi/180.0)*cos(dec))) def f3(dummy): return 1 def g3(h): hr=(h*60.0+correction)/4.0-180.0 return -1.0*cos(hr*pi/180.0) days_in_month = (31,28,31,30,31,30,31,31,30,31,30,31) times1=[] for idx in range(0,12): times1.append(sum(days_in_month[0:idx])+1) #times=linspace(0,350,10) times=arange(0.0,360.0,10.0,dtype=double).tolist() time_titles=['January','February','March','April','May','June', 'July','August','September','October','November','December'] phi_params={ 'u_min':0.0, 'u_max':90.0, 'u_min_trafo':0.0, 'u_max_trafo':90.0, 'f':f1, 'g':g1, 'h':lambda u:1.0, 'title':r'Solar zenith angle $\phi$', 'title_x_shift':0.0, 'title_y_shift':0.25, 'scale_type':'linear', 'tick_levels':2, 'tick_text_levels':1, 'tick_side':'right', 'tag':'phi', 'grid':False, 'extra_params':[{'u_min':20.0, 'u_max':90.0, 'tick_levels':4, 'tick_text_levels':2, }] } time_params={ 'u_min':0.0, 'u_max':23.0, 'u_min_trafo':0.0, 'u_max_trafo':12.0, 'f':f3, 'g':g3, 'h':lambda u:1.0, 'title':r'Hour (h)', 'title_x_shift':0.0, 'title_y_shift':0.25, 'scale_type':'linear', 'tick_levels':2, 'tick_text_levels':1, 'tick_side':'right', 'tag':'none', 'grid':False, } lat_day_params={ 'ID':'none', # to identify the axis 'tag':'none', # for aligning block wrt others 'title':'Grid', 'title_x_shift':0.0, 'title_y_shift':0.25, 'title_distance_center':0.5, 'title_opposite_tick':True, 'u_min':20.0, # for alignment 'u_max':80.0, # for alignment 'f_grid':f2, 'g_grid':g2, 'h_grid':lambda u,v:1.0, 'u_start':30.0, 'u_stop':80.0, 'v_start':times1[0], # day 'v_stop':times1[-1], 'u_values':[30.0,40.0,50.0,60.0,70.0,80.0], 'u_texts':['30','40','50','Latitude = 60','70','80'], 'v_values':times1, 'v_texts':time_titles, 'grid':True, 'text_prefix_u':r'', 'text_prefix_v':r'', 'text_distance':0.5, 'v_texts_u_start':False, 'v_texts_u_stop':True, 'u_texts_v_start':False, 'u_texts_v_stop':True, } block_params={ 'block_type':'type_9', 'f1_params':phi_params, 'f2_params':lat_day_params, 'f3_params':time_params, 'transform_ini':True, } def limit_xx(x): x1=x if x1>1.0: x1=1.0 if x1<-1.0: x1=-1.0 return x1 def limit_x(x): x1=x if not x1>0.0: x1=0.0001 return x1 const_A=0.33766 const_B=-13.656 block_params_weather={ 'block_type':'type_5', 'u_func':lambda u:u, 'v_func':lambda x,v:const_A+const_B*log10(limit_x(x))+v, #'u_values':[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,15.0,20,25], 'u_values':[1.0,25.0], 'u_manual_axis_data':{1.0:'', 25.0:''}, 'v_values':[0.0,1.0,3.0,6.0,9.0,12.0], 'v_manual_axis_data': {0.0:['Clear sky, Cumulus clouds',{'x_corr':0.5, 'y_corr':0.0, 'draw_line':False}], 1.0:'Clear sky', 3.0:'Sun through clouds', 6.0:'Sky light gray', 9.0:'Sky dark gray', 12.0:'Thunder-clouds cover sky', }, 'v_text_distance':0.5, 'wd_tick_levels':0, 'wd_tick_text_levels':0, 'wd_tick_side':'right', 'wd_title':'', 'manual_x_scale':True, 'x_min':0.06, 'x_max':0.99, 'u_title':'', 'v_title':'', 'wd_title_opposite_tick':True, 'wd_title_distance_center':2.5, 'wd_align_func':lambda L:acos(limit_xx(10.0**((L-const_A)/const_B)))*180.0/pi, # phi as L 'wd_func':lambda L:10.0**((L-const_A)/const_B), # x as L 'wd_func_inv':lambda x:const_A+const_B*log10(x), # L as x 'wd_tag':'phi', 'mirror_y':True, 'mirror_x':False, 'width':10.0, 'height':10.0, 'u_scale_opposite':True, 'u_tag':'AA', 'horizontal_guides':True, } block_params_scene={ 'block_type':'type_5', 'u_func':lambda u:u, 'v_func':lambda x,v:x+v, 'u_values':[1.0,25.0], 'u_manual_axis_data':{1.0:'', 25.0:''}, 'u_tag':'AA', 'wd_tag':'EV', 'v_values':[-4.0,-1.0,2.0,5.0,7.0,9.0,11.0,13.0,15.0], 'v_manual_axis_data': {-6.0:'Person under trees', -4.0:'Inside forest', -1.0:'Person in shadow of wall', 2.0:'Person at open place; alley under trees', 5.0:'Buildings; street', 7.0:'Landscape and front matter', 9.0:'Open landscape', 11.0:'Snow landscape and front matter; beach', 13.0:'Snow field; open sea', 15.0:'Clouds', }, 'wd_tick_levels':0, 'wd_tick_text_levels':0, 'wd_tick_side':'right', 'wd_title':'', 'u_title':'', 'v_title':'', 'wd_title_opposite_tick':True, 'wd_title_distance_center':2.5, 'mirror_x':True, 'horizontal_guides':True, 'u_align_y_offset':-0.9, } camera_params_1={ 'u_min':-10.0, 'u_max':15.0, 'function':lambda u:u, 'title':r'', 'tick_levels':0, 'tick_text_levels':0, 'tag':'EV', } camera_params_2={ 'u_min':10.0, 'u_max':12800.0, 'function':lambda S:-(10*log10(S)+1.0), 'title':r'Film speed', 'manual_axis_data': {10.0:'ISO 10', 20.0:'ISO 20', #40.0:'ISO 40', 50.0:'ISO 50', 100.0:'ISO 100', 200.0:'ISO 200', 400.0:'ISO 400', 800.0:'ISO 800', 1600.0:'ISO 1600', 3200.0:'ISO 3200', 6400.0:'ISO 6400', 12800.0:'ISO 12800', }, 'scale_type':'manual line' } camera_params_3={ 'u_min':0.1, 'u_max':10000.0, 'function':lambda t:-10*log10((1.0/t)/(1.0/10.0))-30, 'manual_axis_data': {1/10.0:'10', 1/7.0:'7', 1/5.0:'5', 1/3.0:'3', 1/2.0:'2', 1.0:'1', 2.0:'1/2', 3.0:'1/3', 5.0:'1/5', 7.0:'1/7', 10.0:'1/10', 20.0:'1/20', 30.0:'1/30', 50.0:'1/50', 70.0:'1/70', 100.0:'1/100', 200.0:'1/200', 300.0:'1/300', 500.0:'1/500', 700.0:'1/700', 1000.0:'1/1000', 2000.0:'1/2000', 3000.0:'1/3000', 5000.0:'1/5000', 7000.0:'1/7000', 10000.0:'1/10000', }, 'scale_type':'manual line', 'title':r't (s)', 'text_format':r"1/%3.0f s" } # 6.7 8 9.5 11 13 16 19 22 camera_params_4={ 'u_min':1.0, 'u_max':22.0, 'function':lambda N:10*log10((N/3.2)**2)+30, 'manual_axis_data': {1.0:'f/1', 1.2:'f/1.2', 1.4:'f/1.4', 1.7:'f/1.7', 2.0:'f/2', 2.4:'f/2.4', 2.8:'f/2.8', 3.3:'f/3.3', 4.0:'f/4', 4.8:'f/4.8', 5.6:'f/5.6', 6.7:'f/6.7', 8.0:'f/8', 9.5:'f/9.5', 11.0:'f/11', 13.0:'f/13', 16.0:'f/16', 19.0:'f/19', 22.0:'f/22', }, 'scale_type':'manual line', 'title':r'Aperture', } block_params_camera={ 'block_type':'type_3', 'width':10.0, 'height':10.0, 'f_params':[camera_params_1,camera_params_2,camera_params_3, camera_params_4], 'mirror_x':True, } def old_EV(EV): return (-EV+13.654)/0.3322 EV_para={ 'tag':'EV', 'u_min':4.0, 'u_max':19.0, 'function':lambda u:old_EV(u), 'title':r'EV$_{100}$', 'tick_levels':1, 'tick_text_levels':1, 'align_func':old_EV, 'title_x_shift':0.5, 'tick_side':'right', } EV_block={ 'block_type':'type_8', 'f_params':EV_para } main_params={ 'filename':'ex_photo_exposure.pdf', 'paper_height':35.0, 'paper_width':35.0, 'block_params':[block_params,block_params_weather,block_params_scene,block_params_camera,EV_block], #'block_params':[block_params_weather,block_params_scene,block_params_camera,EV_block], 'transformations':[('rotate',0.01),('scale paper',)], 'title_x': 7, 'title_y': 34, 'title_box_width': 10, 'title_str':r'Photography exposure (Setala 1940) \copyright Leif Roschier 2008 ' } b=Nomographer(main_params)