diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/.nojekyll @@ -0,0 +1 @@ + diff --git a/README.md b/README.md new file mode 100644 index 00000000..ebfb3665 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# documentation diff --git a/docs/.buildinfo b/docs/.buildinfo new file mode 100644 index 00000000..7712a2e6 --- /dev/null +++ b/docs/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 113038d8757709e93cd94d7ecc074a06 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/.doctrees/cli/abnt.doctree b/docs/.doctrees/cli/abnt.doctree new file mode 100644 index 00000000..5cc4e9de Binary files /dev/null and b/docs/.doctrees/cli/abnt.doctree differ diff --git a/docs/.doctrees/cli/breeam.doctree b/docs/.doctrees/cli/breeam.doctree new file mode 100644 index 00000000..edcf5260 Binary files /dev/null and b/docs/.doctrees/cli/breeam.doctree differ diff --git a/docs/.doctrees/cli/datacollection.doctree b/docs/.doctrees/cli/datacollection.doctree new file mode 100644 index 00000000..b408206a Binary files /dev/null and b/docs/.doctrees/cli/datacollection.doctree differ diff --git a/docs/.doctrees/cli/grid.doctree b/docs/.doctrees/cli/grid.doctree new file mode 100644 index 00000000..a7ed0f12 Binary files /dev/null and b/docs/.doctrees/cli/grid.doctree differ diff --git a/docs/.doctrees/cli/index.doctree b/docs/.doctrees/cli/index.doctree new file mode 100644 index 00000000..c81aeae9 Binary files /dev/null and b/docs/.doctrees/cli/index.doctree differ diff --git a/docs/.doctrees/cli/leed.doctree b/docs/.doctrees/cli/leed.doctree new file mode 100644 index 00000000..728c57c0 Binary files /dev/null and b/docs/.doctrees/cli/leed.doctree differ diff --git a/docs/.doctrees/cli/main.doctree b/docs/.doctrees/cli/main.doctree new file mode 100644 index 00000000..227d979f Binary files /dev/null and b/docs/.doctrees/cli/main.doctree differ diff --git a/docs/.doctrees/cli/merge.doctree b/docs/.doctrees/cli/merge.doctree new file mode 100644 index 00000000..dfad4c4d Binary files /dev/null and b/docs/.doctrees/cli/merge.doctree differ diff --git a/docs/.doctrees/cli/mtxop.doctree b/docs/.doctrees/cli/mtxop.doctree new file mode 100644 index 00000000..a385e685 Binary files /dev/null and b/docs/.doctrees/cli/mtxop.doctree differ diff --git a/docs/.doctrees/cli/postprocess.doctree b/docs/.doctrees/cli/postprocess.doctree new file mode 100644 index 00000000..674fed91 Binary files /dev/null and b/docs/.doctrees/cli/postprocess.doctree differ diff --git a/docs/.doctrees/cli/schedule.doctree b/docs/.doctrees/cli/schedule.doctree new file mode 100644 index 00000000..9ec3e984 Binary files /dev/null and b/docs/.doctrees/cli/schedule.doctree differ diff --git a/docs/.doctrees/cli/translate.doctree b/docs/.doctrees/cli/translate.doctree new file mode 100644 index 00000000..553b5b1f Binary files /dev/null and b/docs/.doctrees/cli/translate.doctree differ diff --git a/docs/.doctrees/cli/two_phase.doctree b/docs/.doctrees/cli/two_phase.doctree new file mode 100644 index 00000000..0ba18bd7 Binary files /dev/null and b/docs/.doctrees/cli/two_phase.doctree differ diff --git a/docs/.doctrees/cli/viewfactor.doctree b/docs/.doctrees/cli/viewfactor.doctree new file mode 100644 index 00000000..5491b45e Binary files /dev/null and b/docs/.doctrees/cli/viewfactor.doctree differ diff --git a/docs/.doctrees/cli/well.doctree b/docs/.doctrees/cli/well.doctree new file mode 100644 index 00000000..c7a562b9 Binary files /dev/null and b/docs/.doctrees/cli/well.doctree differ diff --git a/docs/.doctrees/environment.pickle b/docs/.doctrees/environment.pickle new file mode 100644 index 00000000..a4a5c2ec Binary files /dev/null and b/docs/.doctrees/environment.pickle differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.annual.doctree b/docs/.doctrees/honeybee_radiance_postprocess.annual.doctree new file mode 100644 index 00000000..988315db Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.annual.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.annualdaylight.doctree b/docs/.doctrees/honeybee_radiance_postprocess.annualdaylight.doctree new file mode 100644 index 00000000..ae3ef653 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.annualdaylight.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.annualirradiance.doctree b/docs/.doctrees/honeybee_radiance_postprocess.annualirradiance.doctree new file mode 100644 index 00000000..0d7fbc12 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.annualirradiance.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.breeam.breeam.doctree b/docs/.doctrees/honeybee_radiance_postprocess.breeam.breeam.doctree new file mode 100644 index 00000000..425c62f7 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.breeam.breeam.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.breeam.doctree b/docs/.doctrees/honeybee_radiance_postprocess.breeam.doctree new file mode 100644 index 00000000..98ee2ade Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.breeam.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.abnt.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.abnt.doctree new file mode 100644 index 00000000..a9479533 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.abnt.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.breeam.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.breeam.doctree new file mode 100644 index 00000000..431064b1 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.breeam.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.datacollection.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.datacollection.doctree new file mode 100644 index 00000000..d8b95763 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.datacollection.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.doctree new file mode 100644 index 00000000..fbd7e75f Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.grid.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.grid.doctree new file mode 100644 index 00000000..5743b597 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.grid.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.leed.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.leed.doctree new file mode 100644 index 00000000..f342fc05 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.leed.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.merge.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.merge.doctree new file mode 100644 index 00000000..67c0bd2b Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.merge.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.mtxop.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.mtxop.doctree new file mode 100644 index 00000000..67f8e8eb Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.mtxop.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.postprocess.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.postprocess.doctree new file mode 100644 index 00000000..233f75b0 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.postprocess.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.schedule.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.schedule.doctree new file mode 100644 index 00000000..feabce09 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.schedule.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.translate.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.translate.doctree new file mode 100644 index 00000000..535d62c1 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.translate.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.two_phase.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.two_phase.doctree new file mode 100644 index 00000000..5ce0f5a0 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.two_phase.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.util.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.util.doctree new file mode 100644 index 00000000..1e37a1b0 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.util.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.viewfactor.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.viewfactor.doctree new file mode 100644 index 00000000..27055e4f Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.viewfactor.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.cli.well.doctree b/docs/.doctrees/honeybee_radiance_postprocess.cli.well.doctree new file mode 100644 index 00000000..a8461621 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.cli.well.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.data_type.doctree b/docs/.doctrees/honeybee_radiance_postprocess.data_type.doctree new file mode 100644 index 00000000..426109f5 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.data_type.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.doctree b/docs/.doctrees/honeybee_radiance_postprocess.doctree new file mode 100644 index 00000000..74df6bb5 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.dynamic.doctree b/docs/.doctrees/honeybee_radiance_postprocess.dynamic.doctree new file mode 100644 index 00000000..daeabc04 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.dynamic.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.electriclight.doctree b/docs/.doctrees/honeybee_radiance_postprocess.electriclight.doctree new file mode 100644 index 00000000..166452a9 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.electriclight.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.en17037.doctree b/docs/.doctrees/honeybee_radiance_postprocess.en17037.doctree new file mode 100644 index 00000000..6d323b52 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.en17037.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.helper.doctree b/docs/.doctrees/honeybee_radiance_postprocess.helper.doctree new file mode 100644 index 00000000..1d3c4b27 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.helper.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.ies.doctree b/docs/.doctrees/honeybee_radiance_postprocess.ies.doctree new file mode 100644 index 00000000..51900464 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.ies.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.ies.lm.doctree b/docs/.doctrees/honeybee_radiance_postprocess.ies.lm.doctree new file mode 100644 index 00000000..2f69a98f Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.ies.lm.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.ies.lm_schedule.doctree b/docs/.doctrees/honeybee_radiance_postprocess.ies.lm_schedule.doctree new file mode 100644 index 00000000..ec4c5828 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.ies.lm_schedule.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.leed.doctree b/docs/.doctrees/honeybee_radiance_postprocess.leed.doctree new file mode 100644 index 00000000..b6eaca0b Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.leed.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.leed.leed.doctree b/docs/.doctrees/honeybee_radiance_postprocess.leed.leed.doctree new file mode 100644 index 00000000..93b0b577 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.leed.leed.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.leed.leed_schedule.doctree b/docs/.doctrees/honeybee_radiance_postprocess.leed.leed_schedule.doctree new file mode 100644 index 00000000..56407e47 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.leed.leed_schedule.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.metrics.doctree b/docs/.doctrees/honeybee_radiance_postprocess.metrics.doctree new file mode 100644 index 00000000..595ef371 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.metrics.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.reader.doctree b/docs/.doctrees/honeybee_radiance_postprocess.reader.doctree new file mode 100644 index 00000000..6ca30eda Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.reader.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.results.annual_daylight.doctree b/docs/.doctrees/honeybee_radiance_postprocess.results.annual_daylight.doctree new file mode 100644 index 00000000..060f0765 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.results.annual_daylight.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.results.annual_irradiance.doctree b/docs/.doctrees/honeybee_radiance_postprocess.results.annual_irradiance.doctree new file mode 100644 index 00000000..f8769e39 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.results.annual_irradiance.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.results.doctree b/docs/.doctrees/honeybee_radiance_postprocess.results.doctree new file mode 100644 index 00000000..8633d871 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.results.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.results.results.doctree b/docs/.doctrees/honeybee_radiance_postprocess.results.results.doctree new file mode 100644 index 00000000..1f7ec490 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.results.results.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.type_hints.doctree b/docs/.doctrees/honeybee_radiance_postprocess.type_hints.doctree new file mode 100644 index 00000000..bd5f792e Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.type_hints.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.util.doctree b/docs/.doctrees/honeybee_radiance_postprocess.util.doctree new file mode 100644 index 00000000..27e902fa Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.util.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.vis_metadata.doctree b/docs/.doctrees/honeybee_radiance_postprocess.vis_metadata.doctree new file mode 100644 index 00000000..f6148237 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.vis_metadata.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.well.doctree b/docs/.doctrees/honeybee_radiance_postprocess.well.doctree new file mode 100644 index 00000000..1f289430 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.well.doctree differ diff --git a/docs/.doctrees/honeybee_radiance_postprocess.well.well.doctree b/docs/.doctrees/honeybee_radiance_postprocess.well.well.doctree new file mode 100644 index 00000000..6e8145d4 Binary files /dev/null and b/docs/.doctrees/honeybee_radiance_postprocess.well.well.doctree differ diff --git a/docs/.doctrees/index.doctree b/docs/.doctrees/index.doctree new file mode 100644 index 00000000..29c5a3d1 Binary files /dev/null and b/docs/.doctrees/index.doctree differ diff --git a/docs/.doctrees/modules.doctree b/docs/.doctrees/modules.doctree new file mode 100644 index 00000000..a9911473 Binary files /dev/null and b/docs/.doctrees/modules.doctree differ diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..ebfb3665 --- /dev/null +++ b/docs/README.md @@ -0,0 +1 @@ +# documentation diff --git a/docs/_modules/honeybee_radiance_postprocess/annual.html b/docs/_modules/honeybee_radiance_postprocess/annual.html new file mode 100644 index 00000000..e165518e --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/annual.html @@ -0,0 +1,771 @@ + + + + + + + honeybee_radiance_postprocess.annual — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.annual

+"""Shared functions for post-processing annual results."""
+from typing import Union
+import numpy as np
+
+from ladybug.analysisperiod import AnalysisPeriod
+from .util import filter_array
+
+
+
+[docs] +def occupancy_schedule_8_to_6( + timestep: int = 1, as_list: bool = False) -> Union[np.ndarray, list]: + """Create an occupancy schedule for LEED (8 am to 6 pm). + + Args: + timestep: An integer value noting the number of timesteps per hour. + Defaults to 1. + as_list: Boolean toggle to output the schedule as a Python list instead + of a NumPy array. Defaults to False. + + Returns: + A schedule as an array or list. + """ + full_analysis_period = AnalysisPeriod(timestep=timestep) + analysis_period = AnalysisPeriod(st_hour=8, end_hour=17, timestep=timestep) + schedule = np.zeros(8760 * timestep).astype(int) + hours = np.where(np.isin(full_analysis_period.hoys, analysis_period.hoys))[0] + schedule[hours] = 1 + if as_list: + schedule = schedule.tolist() + + return schedule
+ + + +
+[docs] +def schedule_to_hoys( + schedule: Union[list, np.ndarray], + sun_up_hours: Union[list, np.ndarray] = None, as_list: bool = False + ) -> Union[np.ndarray, list]: + """Convert a schedule to hoys. + + Args: + schedule: A list of 8760 values for the occupancy schedule. + sun_up_hours: An optional list of sun up hours as integers. If sun up + hours are provided the function will exclude all values from the + schedule that are not among the sun up hours. Defaults to None. + as_list: Boolean toggle to output the schedule as a Python list instead + of a NumPy array. Defaults to False. + + Returns: + An array or list of occupancy expressed as hoys. + """ + assert len(schedule) == 8760 + if not isinstance(schedule, np.ndarray): + schedule = np.array(schedule).astype(int) + + hours = np.arange(0, 8760, 1) + if sun_up_hours: + sun_up_hours = np.array(sun_up_hours).astype(int) + mask = np.ones(schedule.size, dtype=bool) + mask[sun_up_hours] = False + schedule[mask] = 0 + + occ_hoys = filter_array(hours, np.array(schedule)) + + if as_list: + occ_hoys = occ_hoys.tolist() + + return occ_hoys
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/annualdaylight.html b/docs/_modules/honeybee_radiance_postprocess/annualdaylight.html new file mode 100644 index 00000000..251897a3 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/annualdaylight.html @@ -0,0 +1,989 @@ + + + + + + + honeybee_radiance_postprocess.annualdaylight — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.annualdaylight

+"""Functions for post-processing annual daylight outputs.
+
+Note: These functions will most likely be moved to a separate package in the near future.
+"""
+import json
+import os
+import numpy as np
+
+from ladybug.color import Colorset
+from ladybug.datatype.fraction import Fraction
+from ladybug.legend import LegendParameters
+from honeybee_radiance.postprocess.annual import filter_schedule_by_hours, \
+    _process_input_folder
+
+from .metrics import da_array2d, cda_array2d, udi_array2d, \
+    udi_lower_array2d, udi_upper_array2d
+from .util import filter_array
+
+
+
+[docs] +def metrics_to_files(ill_file, occ_pattern, output_folder, threshold=300, + min_t=100, max_t=3000, grid_name=None, total_hours=None, + sun_down_occ_hours=0): + """Compute annual metrics for an ill file and write the results to a folder. + + This function generates 5 different files or daylight autonomy, continuous daylight + autonomy, lower than useful daylight illuminance, useful daylight illuminance and + higher than useful daylight illuminance. + + Args: + ill_file: Path to an ill file generated by Radiance. The ill file should be + tab separated and shot NOT have a header. The results for each sensor point + should be available in a row and and each column should be the illuminance + value for a sun_up_hour. The number of columns should match the number of + sun up hours. + occ_pattern: A list of 0 and 1 values for hours of occupancy. + output_folder: An output folder where the results will be written to. The folder + will be created if not exist. + threshold: Threshold illuminance level for daylight autonomy. Default: 300. + min_t: Minimum threshold for useful daylight illuminance. Default: 100. + max_t: Maximum threshold for useful daylight illuminance. Default: 3000. + grid_name: An optional name for grid name which will be used to name the output + files. If None the name of the input file will be used. + total_hours: An integer for the total number of occupied hours in the + occupancy schedule. If None, it will be assumed that all of the + occupied hours are sun-up hours and are already accounted for + in the the occ_pattern. + + Returns: + Tuple(file.da, file.cda, file.udi, file.udi, file.udi) + + """ + if not os.path.isdir(output_folder): + os.makedirs(output_folder) + + grid_name = grid_name or os.path.split(ill_file)[-1][-4:] + da = os.path.join(output_folder, 'da', '%s.da' % grid_name).replace('\\', '/') + cda = os.path.join(output_folder, 'cda', '%s.cda' % grid_name).replace('\\', '/') + udi = os.path.join(output_folder, 'udi', '%s.udi' % grid_name).replace('\\', '/') + udi_lower = \ + os.path.join(output_folder, 'udi_lower', '%s.udi' % grid_name).replace('\\', '/') + udi_upper = \ + os.path.join(output_folder, 'udi_upper', '%s.udi' % grid_name).replace('\\', '/') + + for file_path in [da, cda, udi, udi_upper, udi_lower]: + folder = os.path.dirname(file_path) + if not os.path.isdir(folder): + os.makedirs(folder) + + mask = np.array(occ_pattern) + results = np.load(ill_file) + results_occ = np.apply_along_axis(filter_array, 1, results, mask=mask) + + dar = da_array2d(results_occ, total_occ=total_hours, threshold=threshold) + np.savetxt(da, dar, fmt='%.2f') + + cdar = cda_array2d(results_occ, total_occ=total_hours, threshold=threshold) + np.savetxt(cda, cdar, fmt='%.2f') + + udir = udi_array2d(results_occ, total_occ=total_hours, min_t=min_t, max_t=max_t) + np.savetxt(udi, udir, fmt='%.2f') + + udi_lowerr = udi_lower_array2d(results_occ, total_occ=total_hours, min_t=min_t, + sun_down_occ_hours=sun_down_occ_hours) + np.savetxt(udi_lower, udi_lowerr, fmt='%.2f') + + udi_upperr = udi_upper_array2d(results_occ, total_occ=total_hours, max_t=max_t) + np.savetxt(udi_upper, udi_upperr, fmt='%.2f') + + return da, cda, udi_lower, udi, udi_upper
+ + + +# TODO - support a list of schedules/schedule folder to match the input grids +
+[docs] +def metrics_to_folder( + results_folder, schedule=None, threshold=300, min_t=100, max_t=3000, + grids_filter='*', sub_folder='metrics' + ): + """Compute annual metrics in a folder and write them in a subfolder. + + This folder is an output folder of annual daylight recipe. Folder should include + grids_info.json and sun-up-hours.txt - the script uses the list in grids_info.json + to find the result files for each sensor grid. + + Args: + results_folder: Results folder. + schedule: An annual schedule for 8760 hours of the year as a list of values. + threshold: Threshold illuminance level for daylight autonomy. Default: 300. + min_t: Minimum threshold for useful daylight illuminance. Default: 100. + max_t: Maximum threshold for useful daylight illuminance. Default: 3000. + grids_filter: A pattern to filter the grids. By default all the grids will be + processed. + sub_folder: An optional relative path for subfolder to copy results files. + Default: metrics + + Returns: + str -- Path to results folder. + + """ + grids, sun_up_hours = _process_input_folder(results_folder, grids_filter) + occ_pattern, total_occ, sun_down_occ_hours = \ + filter_schedule_by_hours(sun_up_hours=sun_up_hours, schedule=schedule) + + metrics_folder = os.path.join(results_folder, sub_folder) + if not os.path.isdir(metrics_folder): + os.makedirs(metrics_folder) + + for grid in grids: + ill_file = os.path.join(results_folder, '%s.npy' % grid['full_id']) + metrics_to_files( + ill_file, occ_pattern, metrics_folder, threshold, min_t, + max_t, grid['full_id'], total_occ, sun_down_occ_hours + ) + + # copy info.json to all results folders + for folder_name in ['da', 'cda', 'udi_lower', 'udi', 'udi_upper']: + grid_info = os.path.join(metrics_folder, folder_name, 'grids_info.json') + with open(grid_info, 'w') as outf: + json.dump(grids, outf) + + metric_info_dict = _annual_daylight_vis_metadata() + for metric, data in metric_info_dict.items(): + file_path = os.path.join(metrics_folder, metric, 'vis_metadata.json') + with open(file_path, 'w') as fp: + json.dump(data, fp, indent=4) + + return metrics_folder
+ + + +def _annual_daylight_vis_metadata(): + """Return visualization metadata for annual daylight.""" + udi_l_lpar = LegendParameters(min=0, max=100, colors=Colorset.nuanced()) + udi_u_lpar = LegendParameters(min=0, max=100, colors=Colorset.glare_study()) + udi_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort()) + cda_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort()) + da_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort()) + + metric_info_dict = { + 'udi_lower': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Useful Daylight Illuminance Lower').to_dict(), + 'unit': '%', + 'legend_parameters': udi_l_lpar.to_dict() + }, + 'udi_upper': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Useful Daylight Illuminance Upper').to_dict(), + 'unit': '%', + 'legend_parameters': udi_u_lpar.to_dict() + }, + 'udi': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Useful Daylight Illuminance').to_dict(), + 'unit': '%', + 'legend_parameters': udi_lpar.to_dict() + }, + 'cda': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Continuous Daylight Autonomy').to_dict(), + 'unit': '%', + 'legend_parameters': cda_lpar.to_dict() + }, + 'da': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Daylight Autonomy').to_dict(), + 'unit': '%', + 'legend_parameters': da_lpar.to_dict() + } + } + + return metric_info_dict + + +def _annual_daylight_config(): + """Return vtk-config for annual daylight. """ + cfg = { + "data": [ + { + "identifier": "Useful Daylight Illuminance Lower", + "object_type": "grid", + "unit": "Percentage", + "path": "udi_lower", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "nuanced", + }, + }, + { + "identifier": "Useful Daylight Illuminance Upper", + "object_type": "grid", + "unit": "Percentage", + "path": "udi_upper", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "glare_study", + "label_parameters": { + "color": [34, 247, 10], + "size": 0, + "bold": True, + }, + }, + }, + { + "identifier": "Useful Daylight Illuminance", + "object_type": "grid", + "unit": "Percentage", + "path": "udi", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "annual_comfort", + "label_parameters": { + "color": [34, 247, 10], + "size": 0, + "bold": True, + }, + }, + }, + { + "identifier": "Continuous Daylight Autonomy", + "object_type": "grid", + "unit": "Percentage", + "path": "cda", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "annual_comfort", + "label_parameters": { + "color": [34, 247, 10], + "size": 0, + "bold": True, + }, + }, + }, + { + "identifier": "Daylight Autonomy", + "object_type": "grid", + "unit": "Percentage", + "path": "da", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "annual_comfort", + "label_parameters": { + "color": [34, 247, 10], + "size": 0, + "bold": True, + }, + }, + }, + ] + } + + return cfg +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/breeam/breeam.html b/docs/_modules/honeybee_radiance_postprocess/breeam/breeam.html new file mode 100644 index 00000000..fbb622dc --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/breeam/breeam.html @@ -0,0 +1,1180 @@ + + + + + + + honeybee_radiance_postprocess.breeam.breeam — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.breeam.breeam

+"""Functions for BREEAM post-processing."""
+from typing import Union
+from pathlib import Path
+import json
+import numpy as np
+
+from honeybee.model import Model
+from honeybee_radiance.writer import _filter_by_pattern
+
+from ..results.annual_daylight import AnnualDaylight
+
+
+program_type_metrics = {
+    'BREEAM::Education_buildings::Preschools': [
+        {
+            'type': 'Education buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2000
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2000
+            }
+        }
+    ],
+    'BREEAM::Education_buildings::Higher_education': [
+        {
+            'type': 'Education buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2000
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2000
+            }
+        },
+        {
+            'type': 'Education buildings',
+            'credits': 1,
+            'area': 60,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2000
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2000
+            }
+        }
+    ],
+    'BREEAM::Healthcare_buildings::Staff_and_public_areas': [
+        {
+            'type': 'Healthcare buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2650
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2650
+            }
+        },
+        {
+            'type': 'Healthcare buildings',
+            'credits': 1,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2000
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2000
+            }
+        }
+    ],
+    'BREEAM::Healthcare_buildings::Patients_areas_and_consulting_rooms': [
+        {
+            'type': 'Healthcare buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2650
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2650
+            }
+        },
+        {
+            'type': 'Healthcare buildings',
+            'credits': 1,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2000
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2000
+            }
+        }
+    ],
+    'BREEAM::Multi_residential_buildings::Kitchen': [
+        {
+            'type': 'Multi-residential buildings',
+            'credits': 2,
+            'area': 100,
+            'average_daylight_illuminance': {
+                'illuminance': 100,
+                'hours': 3450
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 30,
+                'hours': 3450
+            }
+        }
+    ],
+    'BREEAM::Multi_residential_buildings::Living_rooms_dining_rooms_studies': [
+        {
+            'type': 'Multi-residential buildings',
+            'credits': 2,
+            'area': 100,
+            'average_daylight_illuminance': {
+                'illuminance': 100,
+                'hours': 3450
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 30,
+                'hours': 3450
+            }
+        }
+    ],
+    'BREEAM::Multi_residential_buildings::Non_residential_or_communal_spaces': [
+        {
+            'type': 'Multi-residential buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 200,
+                'hours': 2650
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 60,
+                'hours': 2650
+            }
+        }
+    ],
+    'BREEAM::Retail_buildings::Sales_areas': [
+        {
+            'type': 'Retail buildings',
+            'credits': 1,
+            'area': 35,
+            'average_daylight_illuminance': {
+                'illuminance': 200,
+                'hours': 2650
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 200,
+                'hours': 2650
+            }
+        }
+    ],
+    'BREEAM::Retail_buildings::Other_occupied_areas': [
+        {
+            'type': 'Retail buildings',
+            'credits': 1,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 200,
+                'hours': 2650
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 60,
+                'hours': 2650
+            }
+        }
+    ],
+    'BREEAM::Prison_buildings::Cells_and_custody_cells': [
+        {
+            'type': 'Prison buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 100,
+                'hours': 3150
+            },
+            'minimum_daylight_illuminance': None
+        }
+    ],
+    'BREEAM::Prison_buildings::Internal_association_or_atrium': [
+        {
+            'type': 'Prison buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2650
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 210,
+                'hours': 2650
+            }
+        }
+    ],
+    'BREEAM::Prison_buildings::Patient_care_spaces': [
+        {
+            'type': 'Prison buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2650
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 210,
+                'hours': 2650
+            }
+        }
+    ],
+    'BREEAM::Prison_buildings::Teaching_lecture_and_seminar_spaces': [
+        {
+            'type': 'Prison buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2000
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2000
+            }
+        }
+    ],
+    'BREEAM::Office_buildings::Occupied_spaces': [
+        {
+            'type': 'Office buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2000
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2000
+            }
+        }
+    ],
+    'BREEAM::Crèche_buildings::Occupied_spaces': [
+        {
+            'type': 'Crèche buildings',
+            'credits': 2,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2000
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2000
+            }
+        }
+    ],
+    'BREEAM::Other_buildings::Occupied_spaces': [
+        {
+            'type': 'Other buildings',
+            'credits': 1,
+            'area': 80,
+            'average_daylight_illuminance': {
+                'illuminance': 300,
+                'hours': 2000
+            },
+            'minimum_daylight_illuminance': {
+                'illuminance': 90,
+                'hours': 2000
+            }
+        }
+    ]
+}
+
+
+
+[docs] +def breeam_daylight_assessment_4b( + results: Union[str, AnnualDaylight], model: Union[str, Path, Model] = None, + grids_filter: str = '*', sub_folder: str = None): + """Calculate credits for BREEAM 4b. + + Args: + results: Path to results folder or a Results class object. + model: A model as a path or a HB Model object. If None, the function + will look for a model in the parent of the results folder. If a model + does not exist in this directory the function will raise an error. + Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + sub_folder: Relative path for a subfolder to write the output. If None, + the files will not be written. Defaults to None. + + Returns: + Tuple: + - credit_summary: Summary of each building type. + - program_summary: Summary of program type / space type. + """ + if not isinstance(results, AnnualDaylight): + results = AnnualDaylight(results) + + grids_info = results._filter_grids(grids_filter=grids_filter) + + # check to see if there is a HBJSON with sensor grid meshes for areas + grid_areas = {} + grid_program_types = {} + if model is None: + found_file = False + for base_file in Path(results.folder).parent.iterdir(): + if base_file.suffix in ('.hbjson', '.hbpkl'): + hb_model: Model = Model.from_file(base_file) + found_file = True + break + if not found_file: + raise FileNotFoundError( + 'Found no hbjson or hbpkl file in parent of results folder.') + else: + if isinstance(model, Model): + hb_model = model + else: + hb_model = Model.from_file(model) + + filt_grids = _filter_by_pattern( + hb_model.properties.radiance.sensor_grids, filter=grids_filter) + for s_grid in filt_grids: + if s_grid.mesh is not None: + grid_areas[s_grid.identifier] = np.array(s_grid.mesh.face_areas).sum() + else: + grid_areas[s_grid.identifier] = None + hb_room = hb_model.rooms_by_identifier([s_grid.room_identifier])[0] + try: + program_type_id = hb_room.properties.energy.program_type.identifier + except AttributeError as e: + raise ImportError('honeybee_energy library must be installed to use ' + 'breeam_daylight_assessment method. {}'.format(e)) + if program_type_id in program_type_metrics: + grid_program_types[s_grid.identifier] = program_type_id + + if not grid_areas: + grid_areas = {grid_info['full_id']: None for grid_info in grids_info} + + type_summary = {} + for grid_info in grids_info: + program_type = grid_program_types.get(grid_info['full_id'], None) + if program_type is None: + continue + if program_type not in type_summary: + type_summary[program_type] = {} + type_summary[program_type][grid_info['full_id']] = [] + + array = results._array_from_states(grid_info, zero_array=True) + # calculate average along axis 0 (average for each hour) + avg_ill = array.mean(axis=0) + + metrics_list = program_type_metrics[program_type] + for metrics in metrics_list: + metrics_summary = {} + metrics_summary['type'] = metrics['type'] + metrics_summary['area'] = grid_areas[grid_info['full_id']] + # calculate number of hours where avg. illuminance > target illuminance + target_ill = metrics['average_daylight_illuminance']['illuminance'] + hrs_abv = (avg_ill >= target_ill).sum() + # check if value is >= target hours + target_hrs = metrics['average_daylight_illuminance']['hours'] + avg_comply = hrs_abv >= target_hrs + + # calculate number of hours where illuminance > target illuminance + if program_type == 'BREEAM::Prison_buildings::Cells_and_custody_cells': + minimum_comply = True + else: + target_ill = metrics['minimum_daylight_illuminance']['illuminance'] + hrs_abv_target = (array >= target_ill).sum(axis=1) + # get the minimum, i.e., worst lit point + worst_lit_point = np.min(hrs_abv_target) + # check if values is >= target hours + target_hrs = metrics['minimum_daylight_illuminance']['hours'] + minimum_comply = worst_lit_point >= target_hrs + + metrics_summary['credits'] = metrics['credits'] + if avg_comply and minimum_comply: + metrics_summary['comply'] = True + else: + metrics_summary['comply'] = False + + type_summary[program_type][grid_info['full_id']].append(metrics_summary) + + program_summary = [] + for program_type, grid_summary in type_summary.items(): + program_type_summary = {} + program_type_summary['program_type'] = program_type + program_type_summary['credits'] = 0 # set 0 by default + program_type_summary['comply'] = False # set False by default + + metrics_summary = {} + for grid_id, metrics_list in grid_summary.items(): + for metric in metrics_list: + if metric['credits'] not in metrics_summary: + metrics_summary[metric['credits']] = {} + metrics_summary[metric['credits']]['type'] = metric['type'] + if 'total_area' not in metrics_summary[metric['credits']]: + metrics_summary[metric['credits']]['total_area'] = 0 + metrics_summary[metric['credits']]['total_area'] += metric['area'] + if 'area_comply' not in metrics_summary[metric['credits']]: + metrics_summary[metric['credits']]['area_comply'] = 0 + if metric['comply']: + metrics_summary[metric['credits']]['area_comply'] += metric['area'] + + for credit, metric_summary in metrics_summary.items(): + area_comply_pct = metric_summary['area_comply'] / metric_summary['total_area'] * 100 + metric_summary['area_comply_%'] = area_comply_pct + for metric in program_type_metrics[program_type]: + if credit == metric['credits']: + if area_comply_pct >= metric['area']: + metric_summary['comply'] = True + else: + metric_summary['comply'] = False + + for credit, metric_summary in metrics_summary.items(): + if metric_summary['comply'] and credit > program_type_summary['credits']: + program_type_summary['comply'] = True + program_type_summary['credits'] = credit + program_type_summary['total_area'] = metric_summary['total_area'] + program_type_summary['area_comply'] = metric_summary['area_comply'] + program_type_summary['area_comply_%'] = metric_summary['area_comply_%'] + program_type_summary['type'] = metric_summary['type'] + else: + program_type_summary['total_area'] = metric_summary['total_area'] + program_type_summary['area_comply'] = metric_summary['area_comply'] + program_type_summary['area_comply_%'] = metric_summary['area_comply_%'] + program_type_summary['type'] = metric_summary['type'] + + program_summary.append(program_type_summary) + + building_type_summary = {} + for _program_summary in program_summary: + if _program_summary['type'] not in building_type_summary: + building_type_summary[_program_summary['type']] = [] + building_type_summary[_program_summary['type']].append(_program_summary) + + credit_summary = [] + for building_type, summary in building_type_summary.items(): + _building_type_summary = {} + _building_type_summary['type'] = building_type + if all([v['comply'] for v in summary]): + _building_type_summary['comply'] = True + _building_type_summary['credits'] = min([v['credits'] for v in summary]) + else: + _building_type_summary['comply'] = False + _building_type_summary['credits'] = 0 + _building_type_summary['total_area'] = sum([v['total_area'] for v in summary]) + + credit_summary.append(_building_type_summary) + + if sub_folder: + folder = Path(sub_folder) + folder.mkdir(parents=True, exist_ok=True) + + credit_summary_file = folder.joinpath('summary.json') + credit_summary_file.write_text(json.dumps(credit_summary, indent=2)) + program_summary_file = folder.joinpath('program_summary.json') + program_summary_file.write_text(json.dumps(program_summary, indent=2)) + + return credit_summary, program_summary
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/cli/grid.html b/docs/_modules/honeybee_radiance_postprocess/cli/grid.html new file mode 100644 index 00000000..4757341a --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/cli/grid.html @@ -0,0 +1,995 @@ + + + + + + + honeybee_radiance_postprocess.cli.grid — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.cli.grid

+"""honeybee radiance postprocess grid commands."""
+import click
+import sys
+import logging
+import json
+import numpy as np
+from pathlib import Path
+
+from honeybee_radiance_postprocess.reader import binary_to_array
+from ..annualdaylight import _annual_daylight_vis_metadata
+
+_logger = logging.getLogger(__name__)
+
+
+@click.group(help='Commands for generating and modifying sensor grids.')
+def grid():
+    pass
+
+
+@grid.command('merge-folder')
+@click.argument(
+    'input-folder',
+    type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True))
+@click.argument(
+    'output-folder',
+    type=click.Path(file_okay=False, dir_okay=True, resolve_path=True))
+@click.argument('extension', type=str)
+@click.option(
+    '--dist-info', '-di',
+    help='An optional input for distribution information to put the grids back together '
+    '. Alternatively, the command will look for a _redist_info.json file inside the '
+    'folder.', type=click.Path(file_okay=True, dir_okay=False, resolve_path=True)
+)
+@click.option(
+    '--output-extension', '-oe',
+    help='Output file extension. This is only used if as_text is set to True. '
+    'Otherwise the output extension will be npy.', default='ill', type=click.STRING
+)
+@click.option(
+    '--as-text', '-at',
+    help='Set to True if the output files should be saved as text instead of '
+    'NumPy files.', default=False, type=click.BOOL
+)
+@click.option(
+    '--fmt',
+    help='Format for the output files when saved as text.', default='%.2f',
+    type=click.STRING
+)
+@click.option(
+    '--delimiter',
+    help='Delimiter for the output files when saved as text.',
+    type=click.Choice(['space', 'tab']), default='tab'
+)
+def merge_grid_folder(input_folder, output_folder, extension, dist_info,
+                      output_extension, as_text, fmt, delimiter):
+    """Restructure files in a distributed folder.
+
+    \b
+    Args:
+        input_folder: Path to input folder.
+        output_folder: Path to the new restructured folder
+        extension: Extension of the files to collect data from. It will be ``pts`` for
+            sensor files. Another common extension is ``ill`` for the results of daylight
+            studies.
+    """
+    try:
+        # handle optional case for Functions input
+        if dist_info and not Path(dist_info).is_file():
+            dist_info = None
+        restore_original_distribution(
+            input_folder, output_folder, extension, dist_info, output_extension,
+            as_text, fmt, delimiter)
+    except Exception:
+        _logger.exception('Failed to restructure data from folder.')
+        sys.exit(1)
+    else:
+        sys.exit(0)
+
+
+@grid.command('merge-folder-metrics')
+@click.argument(
+    'input-folder',
+    type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True))
+@click.argument(
+    'output-folder',
+    type=click.Path(file_okay=False, dir_okay=True, resolve_path=True))
+@click.option(
+    '--dist-info', '-di',
+    help='An optional input for distribution information to put the grids back together '
+    '. Alternatively, the command will look for a _redist_info.json file inside the '
+    'folder.', type=click.Path(file_okay=True, dir_okay=False, resolve_path=True)
+)
+@click.option(
+    '--grids-info', '-gi',
+    help='An optional input for grid information that will be copied to each '
+    'metric folder. This file is usually called grids_info.json.',
+    type=click.Path(file_okay=True, dir_okay=False, resolve_path=True)
+)
+def merge_metrics_folder(input_folder, output_folder, dist_info, grids_info):
+    """Restructure annual daylight metrics in a distributed folder.
+    
+    Since this command redistributes metrics it is expected that the input
+    folder has sub folder
+
+    \b
+    Args:
+        input_folder: Path to input folder.
+        output_folder: Path to the new restructured folder
+    """
+    try:
+        # handle optional case for Functions input
+        if dist_info and not Path(dist_info).is_file():
+            dist_info = None
+        if grids_info:
+            with open(grids_info) as gi:
+                grids_info = json.load(gi)
+        extension_mapper = {
+            'da': 'da',
+            'cda': 'cda',
+            'udi': 'udi',
+            'udi_lower': 'udi',
+            'udi_upper': 'udi'
+        }
+        metric_info_dict = _annual_daylight_vis_metadata()
+        input_folder = Path(input_folder)
+        output_folder = Path(output_folder)
+        for metric, extension in extension_mapper.items():
+            metric_folder = input_folder.joinpath(metric)
+            metric_out = output_folder.joinpath(metric)
+            restore_original_distribution_metrics(
+                metric_folder, output_folder, metric, extension, dist_info)
+
+            if grids_info:
+                info_file = metric_out.joinpath('grids_info.json')
+                info_file.write_text(json.dumps(grids_info))
+
+            vis_data = metric_info_dict[metric]
+            vis_metadata_file = metric_out.joinpath('vis_metadata.json')
+            vis_metadata_file.write_text(json.dumps(vis_data, indent=4))
+    except Exception:
+        _logger.exception('Failed to restructure data from folder.')
+        sys.exit(1)
+    else:
+        sys.exit(0)
+
+
+
+[docs] +def restore_original_distribution( + input_folder, output_folder, extension='npy', dist_info=None, + output_extension='ill', as_text=False, fmt='%.2f', input_delimiter=',', + delimiter='tab'): + """Restructure files to the original distribution based on the distribution info. + + It will assume that the files in the input folder are NumPy files. However, + if it fails to load the files as arrays it will try to load from binary + Radiance files to array. + + Args: + input_folder: Path to input folder. + output_folder: Path to the new restructured folder + extension: Extension of the files to collect data from. Default is ``npy`` for + NumPy files. Another common extension is ``ill`` for the results of daylight + studies. + dist_info: Path to dist_info.json file. If None, the function will try to load + ``_redist_info.json`` file from inside the input_folder. (Default: None). + output_extension: Output file extension. This is only used if as_text + is set to True. Otherwise the output extension will be ```npy``. + as_text: Set to True if the output files should be saved as text instead + of NumPy files. + fmt: Format for the output files when saved as text. + input_delimiter: Delimiter for the input files. This is used only if the + input files are text files. + delimiter: Delimiter for the output files when saved as text. + """ + if not dist_info: + _redist_info_file = Path(input_folder, '_redist_info.json') + else: + _redist_info_file = Path(dist_info) + + assert _redist_info_file.is_file(), 'Failed to find %s' % _redist_info_file + + with open(_redist_info_file) as inf: + data = json.load(inf) + + # create output folder + output_folder = Path(output_folder) + if not output_folder.is_dir(): + output_folder.mkdir(parents=True, exist_ok=True) + + src_file = Path() + for f in data: + output_file = Path(output_folder, f['identifier']) + # ensure the new folder is created. in case the identifier has a subfolder + parent_folder = output_file.parent + if not parent_folder.is_dir(): + parent_folder.mkdir() + + out_arrays = [] + for src_info in f['dist_info']: + st = src_info['st_ln'] + end = src_info['end_ln'] + new_file = Path(input_folder, '%s.%s' % (src_info['identifier'], extension)) + if not new_file.samefile(src_file): + src_file = new_file + try: + array = np.load(src_file) + except: + try: + array = binary_to_array(src_file) + except: + try: + array = np.loadtxt( + src_file, delimiter=input_delimiter) + except Exception: + raise RuntimeError( + f'Failed to load input file "{src_file}"') + slice_array = array[st:end+1,:] + + out_arrays.append(slice_array) + + out_array = np.concatenate(out_arrays) + # save numpy array, .npy extension is added automatically + if not as_text: + np.save(output_file, out_array) + else: + if output_extension.startswith('.'): + output_extension = output_extension[1:] + if delimiter == 'tab': + delimiter = '\t' + elif delimiter == 'space': + delimiter = ' ' + elif delimiter == 'comma': + delimiter = ',' + np.savetxt(output_file.with_suffix(f'.{output_extension}'), + out_array, fmt=fmt, delimiter=delimiter)
+ + + +
+[docs] +def restore_original_distribution_metrics( + input_folder, output_folder, metric, extension, dist_info=None): + """Restructure files to the original distribution based on the distribution info. + + It will assume that the files in the input folder are NumPy files. However, + if it fails to load the files as arrays it will try to load from binary + Radiance files to array. + + Args: + input_folder: Path to input folder. + output_folder: Path to the new restructured folder + metric: Name of the metric to redistribute. + extension: Extension of the files to collect data from. For annual + daylight metrics the extension can be 'da', 'cda', or 'udi'. + dist_info: Path to dist_info.json file. If None, the function will try to load + ``_redist_info.json`` file from inside the input_folder. (Default: None). + """ + if not dist_info: + _redist_info_file = Path(input_folder, '_redist_info.json') + else: + _redist_info_file = Path(dist_info) + + assert _redist_info_file.is_file(), 'Failed to find %s' % _redist_info_file + + with open(_redist_info_file) as inf: + data = json.load(inf) + + # create output folder + output_folder = Path(output_folder) + if not output_folder.is_dir(): + output_folder.mkdir() + + src_file = Path() + for f in data: + output_file = Path(output_folder, metric, '%s.%s' % (f['identifier'], extension)) + # ensure the new folder is created. in case the identifier has a subfolder + parent_folder = output_file.parent + if not parent_folder.is_dir(): + parent_folder.mkdir() + + out_arrays = [] + for src_info in f['dist_info']: + st = src_info['st_ln'] + end = src_info['end_ln'] + new_file = Path(input_folder, '%s.%s' % (src_info['identifier'], extension)) + if not new_file.samefile(src_file): + src_file = new_file + array = np.loadtxt(src_file) + slice_array = array[st:end+1] + out_arrays.append(slice_array) + + out_array = np.concatenate(out_arrays) + # save array as txt file + np.savetxt(output_file, out_array, fmt='%.2f')
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/cli/util.html b/docs/_modules/honeybee_radiance_postprocess/cli/util.html new file mode 100644 index 00000000..c531c6cd --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/cli/util.html @@ -0,0 +1,832 @@ + + + + + + + honeybee_radiance_postprocess.cli.util — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.cli.util

+from ladybug.analysisperiod import AnalysisPeriod
+from datetime import datetime
+import copy
+
+
+
+[docs] +def get_hoys(start_date, start_time, end_date, end_time, timestep, leap_year): + """Return list of hours from start date, star hour, end date and end hour. + + Date should be formatted as MMM-DD (e.g JUL-21) and hours must be formatted + as HH:MM (e.g 18:30). + """ + # convert datetimes + try: + start_date = datetime.strptime(start_date, '%b-%d') + except ValueError as e: + raise ValueError('Wrong input for start date:\n\t{}'.format(e)) + try: + start_time = datetime.strptime(start_time, '%H:%M') + except ValueError as e: + raise ValueError('Wrong input for start time:\n\t{}'.format(e)) + try: + end_date = datetime.strptime(end_date, '%b-%d') + except ValueError as e: + raise ValueError('Wrong input for end date:\n\t{}'.format(e)) + try: + end_time = datetime.strptime(end_time, '%H:%M') + except ValueError as e: + raise ValueError('Wrong input for end time:\n\t{}'.format(e)) + + org_end_time = copy.copy(end_time) + if end_time.minute != 0: + if end_time.hour != 23: + end_time = datetime( + end_time.year, end_time.month, end_time.day, end_time.hour + 1, 0 + ) + else: + end_time = datetime( + end_time.year, end_time.month, end_time.day + 1, 0, 0 + ) + ap = AnalysisPeriod( + start_date.month, start_date.day, start_time.hour, + end_date.month, end_date.day, end_time.hour, + timestep, leap_year + ) + + hoys = ap.hoys + + # filter start and end hours if needed + start_index = 0 + end_index = None + if start_time.minute != 0: + # remove the hours that are smaller than this hour + for start_index, h in enumerate(hoys): + if round(60 * h) % 60 >= start_time.minute: + break + + if org_end_time.minute != 0: + for end_index, h in enumerate(reversed(hoys)): + if (60 * h) % 60 <= org_end_time.minute: + break + + if start_index == 0 and end_index is None: + return hoys + elif end_index is None: + return hoys[start_index:] + else: + return hoys[start_index: -1 * (end_index + 1)]
+ + + +
+[docs] +def handle_operator(operator): + """Handle operator for rmtxopt command.""" + if operator == '+': + return '+' + elif operator == '-': + return '+ -s 1.0' + elif operator == '/': + return '/' + elif operator == '*': + return '"*"' + else: + raise ValueError('Invalid operator: %s' % operator)
+ + + +
+[docs] +def remove_header(input_file): + """Remove the header text from a Radiance matrix file.""" + inf = open(input_file) + first_line = next(inf) + if first_line[:10] == '#?RADIANCE': + for line in inf: + if line[:7] == 'FORMAT=': + # pass next empty line + next(inf) + first_line = next(inf) + break + continue + return first_line, inf
+ + + +
+[docs] +def get_compare_func(include_min, include_max, comply): + if include_max and include_min: + if comply: + compare = lambda value, minimum, maximum: minimum <= value <= maximum + else: + compare = lambda value, minimum, maximum: not (minimum <= value <= maximum) + elif not include_max and not include_min: + if comply: + compare = lambda value, minimum, maximum: minimum < value < maximum + else: + compare = lambda value, minimum, maximum: not (minimum < value < maximum) + elif include_max and not include_min: + if comply: + compare = lambda value, minimum, maximum: minimum < value <= maximum + else: + compare = lambda value, minimum, maximum: not (minimum < value <= maximum) + elif not include_max and include_min: + if comply: + compare = lambda value, minimum, maximum: minimum <= value < maximum + else: + compare = lambda value, minimum, maximum: not (minimum <= value < maximum) + + return compare
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/data_type.html b/docs/_modules/honeybee_radiance_postprocess/data_type.html new file mode 100644 index 00000000..41e0b654 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/data_type.html @@ -0,0 +1,808 @@ + + + + + + + honeybee_radiance_postprocess.data_type — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.data_type

+"""Functions for NumPy data type (dtype)."""
+from typing import Tuple
+import numpy as np
+
+
+
+[docs] +def smallest_integer_dtype(array: np.ndarray) -> np.signedinteger: + """Return the smallest possible integer dtype. + + Args: + array: NumPy array. + + Returns: + A NumPy integer dtype. + """ + if np.all(array >= np.iinfo(np.int8).min) and \ + np.all(array <= np.iinfo(np.int8).max): + return np.int8 + elif np.all(array >= np.iinfo(np.int16).min) and \ + np.all(array <= np.iinfo(np.int16).max): + return np.int16 + elif np.all(array >= np.iinfo(np.int32).min) and \ + np.all(array <= np.iinfo(np.int32).max): + return np.int32 + elif np.all(array >= np.iinfo(np.int64).min) and \ + np.all(array <= np.iinfo(np.int64).max): + return np.int64
+ + + +
+[docs] +def smallest_float_dtype(array: np.ndarray, rtol: float = 1e-5, + atol: float = 1e-5) -> np.floating: + """Return the smallest possible float dtype. + + The allclose function is used to check if a certain floating-point precision + can be used without losing accuracy. + + Args: + array: NumPy array. + rtol: The relative tolerance parameter for `np.allclose`. The default + is 1e-5. + atol: The absolute tolerance parameter for `np.allclose`. The default + is 1e-5. + + Returns: + A NumPy floating dtype. + """ + if np.all((array >= np.finfo(np.float16).min) & \ + (array <= np.finfo(np.float16).max)): + if np.allclose(array, array.astype(np.float16), rtol=rtol, atol=atol): + return np.float16 + if np.all((array >= np.finfo(np.float32).min) & \ + (array <= np.finfo(np.float32).max)): + if np.allclose(array, array.astype(np.float32), rtol=rtol, atol=atol): + return np.float32 + if np.all((array >= np.finfo(np.float64).min) & \ + (array <= np.finfo(np.float64).max)): + if np.allclose(array, array.astype(np.float64), rtol=rtol, atol=atol): + return np.float64
+ + + +
+[docs] +def smallest_dtype(array: np.ndarray, rtol: float = 1e-5, atol: float = 1e-5 + ) -> Tuple[np.signedinteger, np.floating]: + """Return the smallest possible dtype. + + Args: + array: NumPy array. + rtol: The relative tolerance parameter for `np.allclose`. The default + is 1e-5. This is also used if the dtype of the array is np.floating. + atol: The absolute tolerance parameter for `np.allclose`. The default + is 1e-5. This is also used if the dtype of the array is np.floating. + + Returns: + A NumPy dtype. + """ + if np.issubdtype(array.dtype, np.integer): + return smallest_integer_dtype(array) + elif np.issubdtype(array.dtype, np.floating): + return smallest_float_dtype(array, rtol=rtol, atol=atol) + else: + raise TypeError(f'Expected integer or floating dtype. Got {array.dtype}')
+ + + +
+[docs] +def set_smallest_dtype(array: np.ndarray, rtol: float = 1e-5, + atol: float = 1e-5) -> np.ndarray: + """Return a NumPy array with the smallest possible dtype. + + Args: + array: NumPy array. + rtol: The relative tolerance parameter for `np.allclose`. The default + is 1e-5. This is also used if the dtype of the array is np.floating. + atol: The absolute tolerance parameter for `np.allclose`. The default + is 1e-5. This is also used if the dtype of the array is np.floating. + + Returns: + A new NumPy array with a smaller dtype. + """ + dtype = smallest_dtype(array, rtol=rtol, atol=atol) + return array.astype(dtype)
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/dynamic.html b/docs/_modules/honeybee_radiance_postprocess/dynamic.html new file mode 100644 index 00000000..66c6dca8 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/dynamic.html @@ -0,0 +1,1014 @@ + + + + + + + honeybee_radiance_postprocess.dynamic — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.dynamic

+"""Post-processing classes for dynamic schedules."""
+import json
+import os
+import sys
+from itertools import islice, cycle
+
+from honeybee.config import folders
+
+
+
+[docs] +class ApertureGroupSchedule(object): + """ApertureGroupSchedule. + + This class contains the dynamic states schedule of a single ApertureGroup. + + Args: + identifier: Identifier of the ApertureGroup. + schedule: A list or tuple of integer values. + + Properties: + * identifier + * schedule + * is_static + """ + __slots__ = ('_identifier', '_schedule', '_is_static') + + def __init__(self, identifier, schedule, is_static=None): + """Initialize ApertureGroupSchedule.""" + self._identifier = identifier + self.schedule = schedule + self.is_static = is_static + +
+[docs] + @classmethod + def from_dict(cls, data): + """Initialize a ApertureGroupSchedule from a dictionary. + + Args: + data: A dictionary representation of an ApertureGroupSchedule + object. + """ + identifier = data['identifier'] + schedule = data['schedule'] + is_static = data['is_static'] if 'is_static' in data else None + return cls(identifier, schedule, is_static)
+ + + @property + def identifier(self): + """Return identifier.""" + return self._identifier + + @property + def schedule(self): + """Return ApertureGroup schedule.""" + return self._schedule + + @schedule.setter + def schedule(self, schedule): + assert isinstance(schedule, (list, tuple)), \ + ('Failed to add schedule. Received input of type: ' + '%s. Expected input of type: list or tuple.' % type(schedule)) + if isinstance(schedule, tuple): + schedule = list(schedule) + if len(schedule) < 8760: + schedule = list(islice(cycle(schedule), 8760)) + elif len(schedule) > 8760: + error_message = ( + 'The light path %s has %s values in ' + 'its states schedule. Maximum allowed number of values ' + 'is 8760.' % (self.identifier, len(schedule)) + ) + raise ValueError(error_message) + self._schedule = schedule + + @property + def is_static(self): + """Return True if schedule is static.""" + return self._is_static + + @is_static.setter + def is_static(self, value): + if value is not None: + assert isinstance(value, bool) + self._is_static = value + else: + if len(set(self.schedule)) == 1: + self._is_static = True + else: + self._is_static = False + +
+[docs] + def to_dict(self): + """Return ApertureGroupSchedule as a dictionary.""" + base = {} + base['identifier'] = self.identifier + base['schedule'] = self.schedule + base['is_static'] = self.is_static + return base
+ + +
+[docs] + def ToString(self): + """Overwrite .NET ToString.""" + return self.__repr__()
+ + + def __repr__(self): + return '{}: {}'.format(self.__class__.__name__, self.identifier)
+ + + +
+[docs] +class DynamicSchedule(object): + """DynamicSchedule. + + This class contains a single property (dynamic_schedule). This property is + a dictionary where keys are ApertureGroup identifiers and the value for + each key is the dynamic schedule for the ApertureGroup. + + Args: + dynamic_schedule: A dictionary of ApertureGroup identifier and + schedules. + + Properties: + * dynamic_schedule + """ + __slots__ = ('_dynamic_schedule',) + + def __init__(self, dynamic_schedule = None): + self.dynamic_schedule = dynamic_schedule + +
+[docs] + @classmethod + def from_group_schedules(cls, group_schedules): + """Initialize a DynamicSchedule from a list of ApertureGroupSchedules. + + The method will automatically sense if there are duplicated groups in + the list and ensure the group schedule only appears once. + + Args: + data: A dictionary representation of a DynamicSchedule objects. + """ + dyn_sch = cls() + dyn_sch_ids = set() + for _ap_group in group_schedules: + assert isinstance(_ap_group, ApertureGroupSchedule), \ + 'Expected Aperture Group Schedule. Got {}'.format(type(_ap_group)) + if _ap_group.identifier not in dyn_sch_ids: + dyn_sch_ids.add(_ap_group.identifier) + dyn_sch.add_aperture_group_schedule(_ap_group) + return dyn_sch
+ + +
+[docs] + @classmethod + def from_dict(cls, data): + """Initialize a DynamicSchedule from a dictionary. + + Args: + data: A dictionary representation of a DynamicSchedule objects. + """ + dynamic_schedule = {} + for identifier, group in data.items(): + dynamic_schedule[identifier] = ApertureGroupSchedule.from_dict(group) + return cls(dynamic_schedule)
+ + +
+[docs] + @classmethod + def from_json(cls, json_file): + """Initialize a DynamicSchedule from a JSON file. + + Args: + json_file: Path to JSON file. + """ + assert os.path.isfile(json_file), 'Failed to find %s' % json_file + if sys.version_info < (3, 0): + with open(json_file) as inf: + data = json.load(inf) + else: + with open(json_file, encoding='utf-8') as inf: + data = json.load(inf) + return cls.from_dict(data)
+ + + @property + def dynamic_schedule(self): + """Return dynamic schedule as a dictionary.""" + return self._dynamic_schedule + + @dynamic_schedule.setter + def dynamic_schedule(self, dynamic_schedule): + if not dynamic_schedule: + dynamic_schedule = {} + assert isinstance(dynamic_schedule, dict), \ + 'Expected dictionary. Got %s.' % type(dynamic_schedule) + self._dynamic_schedule = dynamic_schedule + +
+[docs] + def add_aperture_group_schedule(self, aperture_group_schedule): + """Add an ApertureGroupSchedule to the DynamicSchedule instance. + + Args: + aperture_group_schedule: An ApertureGroupSchedule object. + """ + assert isinstance(aperture_group_schedule, ApertureGroupSchedule), \ + ('Failed to add ApertureGroupSchedule. Received input of type: ' + '%s. Expected input of type: ApertureGroupSchedule.' \ + % type(aperture_group_schedule)) + identifier = aperture_group_schedule.identifier + self.dynamic_schedule[identifier] = aperture_group_schedule
+ + +
+[docs] + def filter_by_identifiers(self, identifiers): + """Filter the DynamicSchedule by identifiers. + + This method returns a filtered DynamicSchedule object. + + Args: + identifiers: A list of identifiers. + + Returns: + A filtered DynamicSchedule object. + """ + filter_dyn_sch = DynamicSchedule() + for identifier in identifiers: + if identifier in self.dynamic_schedule: + filter_dyn_sch.add_aperture_group_schedule( + self.dynamic_schedule[identifier] + ) + else: + filter_dyn_sch.add_aperture_group_schedule( + ApertureGroupSchedule(identifier, [0]) + ) + return filter_dyn_sch
+ + +
+[docs] + def to_dict(self, simplified=False): + """Return DynamicSchedule as a dictionary.""" + base = {} + for identifier, group in self.dynamic_schedule.items(): + if not simplified: + base[identifier] = group.to_dict() + else: + base[identifier] = group.to_dict()['schedule'] + return base
+ + +
+[docs] + def to_json(self, folder=None, file_name=None, indent=None, simplified=False): + """Write a DynamicSchedule to JSON. + + Args: + folder: A text string for the directory where the JSON file will be + written. If unspecified, the default simulation folder will be + used. This is usually at "C:\\Users\\USERNAME\\simulation." + file_name: _description_. Defaults to None. + indent: A positive integer to set the indentation used in the + resulting JSON file. (Default: None). + + Returns: + json_file: Path to JSON file. + """ + # create dictionary of the DynamicSchedule + dyn_sch_dict = self.to_dict(simplified=simplified) + + # set up name and folder for the JSON + file_name = file_name if file_name else 'dynamic_schedule' + if not file_name.endswith('.json'): + file_name += '.json' + folder = folder if folder is not None else folders.default_simulation_folder + json_file = os.path.join(folder, file_name) + + # write JSON + with open(json_file, 'w') as fp: + json.dump(dyn_sch_dict, fp, indent=indent) + return json_file
+ + +
+[docs] + def duplicate(self): + """Get a copy of this object.""" + return self.__copy__()
+ + +
+[docs] + def ToString(self): + """Overwrite .NET ToString.""" + return self.__repr__()
+ + + def __copy__(self): + new_dyn_sch = DynamicSchedule(self.dynamic_schedule) + return new_dyn_sch + + def __repr__(self): + return '{}'.format(self.__class__.__name__)
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/electriclight.html b/docs/_modules/honeybee_radiance_postprocess/electriclight.html new file mode 100644 index 00000000..2a4d623f --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/electriclight.html @@ -0,0 +1,720 @@ + + + + + + + honeybee_radiance_postprocess.electriclight — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.electriclight

+"""Functions for post-processing daylight outputs into electric lighting schedules."""
+from typing import List
+import numpy as np
+
+
+[docs] +def array_to_dimming_fraction( + array: np.ndarray, su_pattern: List[int], setpt: float, m_pow: float, + m_lgt: float, off_m: float) -> list: + """Compute hourly dimming fractions for a given result file.""" + fract_dim = (setpt - array) / (setpt - m_lgt) + par_dim = fract_dim + ((1 - fract_dim) * m_pow) + su_values = np.where(array > setpt, 0 if off_m else m_pow, + (np.where(array <= m_lgt, 1, par_dim))).sum(axis=0) + su_values = su_values / array.shape[0] + + dim_fract = np.ones(8760) + dim_fract[su_pattern] = su_values + + return dim_fract
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/en17037.html b/docs/_modules/honeybee_radiance_postprocess/en17037.html new file mode 100644 index 00000000..7979bf7b --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/en17037.html @@ -0,0 +1,1004 @@ + + + + + + + honeybee_radiance_postprocess.en17037 — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.en17037

+"""Functions for EN 17037 post-processing."""
+from typing import Union
+from pathlib import Path
+import json
+import numpy as np
+
+from ladybug.color import Colorset
+from ladybug.datatype.fraction import Fraction
+from ladybug.legend import LegendParameters
+
+from .results.annual_daylight import AnnualDaylight
+from .dynamic import DynamicSchedule
+from .metrics import da_array2d
+from .util import filter_array
+
+
+
+[docs] +def en17037_to_files( + array: np.ndarray, metrics_folder: Path, grid_info: dict) -> list: + """Compute annual EN 17037 metrics for a NumPy array and write the results + to a folder. + + This function generates 6 different files for daylight autonomy based on + the varying level of recommendation in EN 17037. + + Args: + array: A 2D NumPy array. + metrics_folder: An output folder where the results will be written to. + The folder will be created if it does not exist. + grid_info: A grid information dictionary. + + Returns: + tuple -- Tuple of lists of paths for da, sda, and compliance folders. + """ + recommendations = { + 'minimum_illuminance': { + 'minimum': 100, + 'medium': 300, + 'high': 500 + }, + 'target_illuminance': { + 'minimum': 300, + 'medium': 500, + 'high': 750 + } + } + compliance_value = { + 'minimum': 1, + 'medium': 2, + 'high': 3 + } + + grid_id = grid_info['full_id'] + grid_count = grid_info['count'] + + da_folders = [] + sda_folders = [] + compliance_folders = [] + da_folder = metrics_folder.joinpath('da') + sda_folder = metrics_folder.joinpath('sda') + compliance_folder = metrics_folder.joinpath('compliance_level') + + for target_type, thresholds in recommendations.items(): + compliance_level = None + for level, threshold in thresholds.items(): + # da + da_level_folder = \ + da_folder.joinpath('_'.join([target_type, str(threshold)])) + da_file = da_level_folder.joinpath(f'{grid_id}.da') + if not da_file.parent.is_dir(): + da_file.parent.mkdir(parents=True) + da = da_array2d(array, total_occ=4380, threshold=threshold) + np.savetxt(da_file, da, fmt='%.2f') + + # sda + sda_level_folder = \ + sda_folder.joinpath('_'.join([target_type, str(threshold)])) + sda_file = sda_level_folder.joinpath(f'{grid_id}.sda') + if not sda_file.parent.is_dir(): + sda_file.parent.mkdir(parents=True) + sda = (da >= 50).mean() * 100 + with open(sda_file, 'w') as sdaf: + sdaf.write(str(round(sda, 2))) + + space_target = 50 if target_type == 'target_illuminance' else 95 + if sda >= space_target: + compliance_level = np.full((grid_count), compliance_value[level], dtype=int) + + da_folders.append(da_file.parent) + sda_folders.append(sda_file.parent) + + if compliance_level is None: + compliance_level = np.zeros(grid_count, dtype=int) + compliance_level_folder = compliance_folder.joinpath(target_type) + compliance_level_file = compliance_level_folder.joinpath(f'{grid_id}.pf') + if not compliance_level_file.parent.is_dir(): + compliance_level_file.parent.mkdir(parents=True) + np.savetxt(compliance_level_file, compliance_level, fmt='%i') + compliance_folders.append(compliance_level_file.parent) + + return da_folders, sda_folders, compliance_folders
+ + + +
+[docs] +def en17037_to_folder( + results: Union[str, AnnualDaylight], schedule: list, + states: DynamicSchedule = None, grids_filter: str = '*', + sub_folder: str = 'en17037') -> Path: + """Compute annual EN 17037 metrics in a folder and write them in a subfolder. + + The results is an output folder of annual daylight recipe. + + Args: + results: Results folder. + schedule: An annual schedule for 8760 hours of the year as a list of + values. This should be a daylight hours schedule. + grids_filter: A pattern to filter the grids. By default all the grids + will be processed. + states: A dictionary of states. Defaults to None. + sub_folder: An optional relative path for subfolder to copy results + files. Default: en17037. + + Returns: + str -- Path to results folder. + """ + if not isinstance(results, AnnualDaylight): + results = AnnualDaylight(results, schedule=schedule) + else: + results.schedule = schedule + + total_occ = results.total_occ + occ_mask = results.occ_mask + + grids_info = results._filter_grids(grids_filter=grids_filter) + + sub_folder = Path(sub_folder) + + if total_occ != 4380: + raise ValueError( + f'There are {total_occ} occupied hours in the schedule. According ' + 'to EN 17037 the schedule must consist of the daylight hours ' + 'which is defined as the half of the year with the largest ' + 'quantity of daylight') + + for grid_info in grids_info: + array = results._array_from_states( + grid_info, states=states, res_type='total', zero_array=True) + if np.any(array): + array = np.apply_along_axis( + filter_array, 1, array, occ_mask) + da_folders, sda_folders, compliance_folders = en17037_to_files( + array, sub_folder, grid_info) + + # copy grids_info.json to all results folders + for folder in da_folders + sda_folders + compliance_folders: + grids_info_file = Path(folder, 'grids_info.json') + with open(grids_info_file, 'w') as outf: + json.dump(grids_info, outf, indent=2) + + metric_info_dict = _annual_daylight_en17037_vis_metadata() + da_folder = sub_folder.joinpath('da') + for metric, data in metric_info_dict.items(): + file_path = da_folder.joinpath(metric, 'vis_metadata.json') + with open(file_path, 'w') as fp: + json.dump(data, fp, indent=4) + + return sub_folder
+ + + +def _annual_daylight_en17037_vis_metadata(): + """Return visualization metadata for annual daylight.""" + da_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort()) + + metric_info_dict = { + 'minimum_illuminance_100': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Daylight Autonomy - minimum 100 lux').to_dict(), + 'unit': '%', + 'legend_parameters': da_lpar.to_dict() + }, + 'minimum_illuminance_300': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Daylight Autonomy - minimum 300 lux').to_dict(), + 'unit': '%', + 'legend_parameters': da_lpar.to_dict() + }, + 'minimum_illuminance_500': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Daylight Autonomy - minimum 500 lux').to_dict(), + 'unit': '%', + 'legend_parameters': da_lpar.to_dict() + }, + 'target_illuminance_300': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Daylight Autonomy - target 300 lux').to_dict(), + 'unit': '%', + 'legend_parameters': da_lpar.to_dict() + }, + 'target_illuminance_500': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Daylight Autonomy - target 500 lux').to_dict(), + 'unit': '%', + 'legend_parameters': da_lpar.to_dict() + }, + 'target_illuminance_750': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Daylight Autonomy - target 750 lux').to_dict(), + 'unit': '%', + 'legend_parameters': da_lpar.to_dict() + } + } + + return metric_info_dict + + +def _annual_daylight_en17037_config(): + """Return vtk-config for annual daylight EN 17037. """ + cfg = { + "data": [ + { + "identifier": "Daylight Autonomy - target 300 lux", + "object_type": "grid", + "unit": "Percentage", + "path": "target_illuminance/minimum/da", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "nuanced", + }, + }, + { + "identifier": "Daylight Autonomy - target 500 lux", + "object_type": "grid", + "unit": "Percentage", + "path": "target_illuminance/medium/da", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "nuanced", + }, + }, + { + "identifier": "Daylight Autonomy - target 750 lux", + "object_type": "grid", + "unit": "Percentage", + "path": "target_illuminance/high/da", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "nuanced", + }, + }, + { + "identifier": "Daylight Autonomy - minimum 100 lux", + "object_type": "grid", + "unit": "Percentage", + "path": "minimum_illuminance/minimum/da", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "nuanced", + }, + }, + { + "identifier": "Daylight Autonomy - minimum 300 lux", + "object_type": "grid", + "unit": "Percentage", + "path": "minimum_illuminance/medium/da", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "nuanced", + }, + }, + { + "identifier": "Daylight Autonomy - minimum 500 lux", + "object_type": "grid", + "unit": "Percentage", + "path": "minimum_illuminance/high/da", + "hide": False, + "legend_parameters": { + "hide_legend": False, + "min": 0, + "max": 100, + "color_set": "nuanced", + }, + }, + ] + } + + return cfg +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/helper.html b/docs/_modules/honeybee_radiance_postprocess/helper.html new file mode 100644 index 00000000..5829423f --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/helper.html @@ -0,0 +1,957 @@ + + + + + + + honeybee_radiance_postprocess.helper — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.helper

+"""Helper functions."""
+import json
+import numpy as np
+from pathlib import Path
+
+from honeybee.model import Model
+
+
+
+[docs] +def model_grid_areas(model, grids_info): + if isinstance(model, Model): + hb_model = model + else: + hb_model = Model.from_file(model) + + full_ids = [grid_info['full_id'] for grid_info in grids_info] + sensor_grids = hb_model.properties.radiance.sensor_grids + grid_areas = [] + for s_grid in sensor_grids: + if s_grid.identifier in full_ids: + if s_grid.mesh is not None: + grid_areas.append(s_grid.mesh.face_areas) + grid_areas = [np.array(grid) for grid in grid_areas] + if not grid_areas: + grid_areas = [None] * len(full_ids) + + return grid_areas
+ + + +
+[docs] +def grid_summary( + folder: Path, grid_areas: list = None, + grids_info: list = None, name: str = 'grid_summary', + grid_metrics: list = None, sub_folder: bool = True + ): + """Calculate a grid summary for a single metric. + + Args: + folder: A folder with results. + grid_areas: A list of area of each sensor. + grids_info: Grid information as a dictionary. + name: Optional filename of grid summary. + grid_metrics: Additional customized metrics to calculate. + sub_folder: If set to True it will look for results in all sub-folders + in the folder input. Else it look for results directly in the folder + input. + """ + if sub_folder: + sub_folders = [sf for sf in folder.iterdir() if sf.is_dir()] + else: + sub_folders = [folder] + + # set up the default data types + dtype_sensor_grid = ('Sensor Grid', 'O') + dtype_sensor_grid_id = ('Sensor Grid ID', 'O') + dtype_base = [ + ('Mean', np.float32), + ('Minimum', np.float32), + ('Maximum', np.float32), + ('Uniformity Ratio', np.float32) + ] + dtype = [] + + # set up default format (for first two columns: str) + fmt = ['%s', '%s'] + + if grids_info is None: + for sf in sub_folders: + gi_file = sf.joinpath('grids_info.json') + if gi_file.exists(): + with open(gi_file) as gi: + grids_info = json.load(gi) + break + if grids_info is None: + # if it did not find grids_info.json in any folder + raise FileNotFoundError( + f'The file grids_info.json was not found in any folder.') + + if grid_areas is None: + grid_areas = [None] * len(grids_info) + + + dtype.append(dtype_sensor_grid) + dtype.append(dtype_sensor_grid_id) + for sf in sub_folders: + _dtype = [] + _fmt = [] + for dt_b in dtype_base: + col_name = dt_b[0] + if sub_folder: + col_name = '-'.join([sf.stem.upper(), col_name]) + _dtype.append((col_name, np.float32)) + _fmt.append('%.2f') + dtype.extend(_dtype) + fmt.extend(_fmt) + + if grid_metrics is not None: + for grid_metric in grid_metrics: + if len(grid_metric) == 1: + if 'allOf' in grid_metric: + _mname = [] + for gr_m in grid_metric['allOf']: + _mname.append(_get_grid_metric_name(gr_m)) + mname = ' and '.join(_mname) + elif 'anyOf' in grid_metric: + _mname = [] + for gr_m in grid_metric['anyOf']: + _mname.append(_get_grid_metric_name(gr_m)) + mname = ' or '.join(_mname) + else: + mname = _get_grid_metric_name(grid_metric) + elif len(grid_metric) == 2: + _mname = [] + for k, v in grid_metric.items(): + _mname.append(_get_grid_metric_name({k: v})) + mname = ' and '.join(_mname) + col_name = mname + if sub_folder: + col_name = '-'.join([sf.stem.upper(), col_name]) + dtype.append((col_name, np.float32)) + fmt.append('%.2f') + + arrays = [] + for grid_info, grid_area in zip(grids_info, grid_areas): + full_id = grid_info['full_id'] + grid_name = grid_info['name'] + data = [grid_name, full_id] + for sf in sub_folders: + grid_files = list(sf.glob(f'{full_id}.*')) + assert len(grid_files) == 1 + + array = np.loadtxt(grid_files[0]) + _mean = array.mean() + _min = array.min() + _max = array.max() + _uniformity_ratio = _min / _mean * 100 + + data.extend([_mean, _min, _max, _uniformity_ratio]) + + if grid_metrics is not None: + # get grid metrics + grid_metrics_data = \ + _get_grid_metrics(array, grid_metrics, grid_info, grid_area) + data.extend(grid_metrics_data) + + arrays.append(tuple(data)) + + # create structured array + struct_array = np.array(arrays, dtype=dtype) + + header = [dt[0] for dt in dtype] + # write header to file + with open(folder.joinpath(f'{name}.csv'), 'w') as grid_summary_file: + grid_summary_file.write(','.join(header)) + # write structured array to grid_summary_file + with open(folder.joinpath(f'{name}.csv'), 'a') as grid_summary_file: + grid_summary_file.write('\n') + np.savetxt(grid_summary_file, struct_array, delimiter=',', fmt=fmt) + + return grid_summary_file
+ + + +def _calculate_percentage(gr_metric_bool, grid_info, grid_area=None): + """Calculate percentage of floor area where True. + + Args: + gr_metric_bool: A NumPy array of booleans. + grid_info: Grid information. + grid_area: A NumPy array of area for each sensor. (Default: None). + + Returns: + The percentage of floor area where gr_metric_bool is True. + """ + if grid_area is not None: + gr_metric_pct = \ + grid_area[gr_metric_bool].sum() / grid_area.sum() * 100 + else: + gr_metric_pct = \ + gr_metric_bool.sum() / grid_info['count'] * 100 + return gr_metric_pct + + +def _logical_operator(keyword): + lg = { + 'minimum': '>', + 'exclusiveMinimum': '>=', + 'maximum': '<', + 'exclusiveMaximum': '<=' + } + return lg[keyword] + + +def _get_grid_metric_name(grid_metric): + if 'minimum' in grid_metric: + return f'{_logical_operator("minimum")}{grid_metric["minimum"]}' + elif 'exclusiveMinimum' in grid_metric: + return f'{_logical_operator("exclusiveMinimum")}{grid_metric["exclusiveMinimum"]}' + elif 'maximum' in grid_metric: + return f'{_logical_operator("maximum")}{grid_metric["maximum"]}' + elif 'exclusiveMaximum' in grid_metric: + return f'{_logical_operator("exclusiveMaximum")}{grid_metric["exclusiveMaximum"]}' + + +def _numeric_type(array, gr_metric): + if 'minimum' in gr_metric: + gr_metric_bool = array > gr_metric['minimum'] + elif 'exclusiveMinimum' in gr_metric: + gr_metric_bool = array >= gr_metric['minimum'] + elif 'maximum' in gr_metric: + gr_metric_bool = array < gr_metric['maximum'] + elif 'exclusiveMaximum' in gr_metric: + gr_metric_bool = array <= gr_metric['exclusiveMaximum'] + return gr_metric_bool + + +def _grid_summary_all_any(array, gr_metric, grid_info, grid_area, keyword): + gr_metric_arrays = [] + for gr_m in gr_metric[keyword]: + assert len(gr_m) == 1 + gr_metric_arrays.append(_numeric_type(array, gr_m)) + if keyword == 'allOf': + gr_metric_bool = np.all(gr_metric_arrays, axis=0) + else: + gr_metric_bool = np.any(gr_metric_arrays, axis=0) + gr_metric_pct = \ + _calculate_percentage(gr_metric_bool, grid_info, grid_area) + return gr_metric_pct + + +def _get_grid_metrics(array, grid_metrics, grid_info, grid_area): + grid_metrics_data = [] + for gr_metric in grid_metrics: + if len(gr_metric) == 1: + if 'allOf' in gr_metric: + gr_metric_pct = \ + _grid_summary_all_any( + array, gr_metric, grid_info, grid_area, 'allOf') + elif 'anyOf' in gr_metric: + gr_metric_pct = \ + _grid_summary_all_any( + array, gr_metric, grid_info, grid_area, 'anyOf') + else: + gr_metric_bool = _numeric_type(array, gr_metric) + gr_metric_pct = \ + _calculate_percentage(gr_metric_bool, grid_info, grid_area) + elif len(gr_metric) == 2: + gr_metric_arrays = [] + for k, threshold in gr_metric.items(): + gr_metric_arrays.append(_numeric_type(array, {k: threshold})) + gr_metric_bool = np.all(gr_metric_arrays, axis=0) + gr_metric_pct = \ + _calculate_percentage(gr_metric_bool, grid_info, grid_area) + grid_metrics_data.append(gr_metric_pct) + return grid_metrics_data +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/ies/lm.html b/docs/_modules/honeybee_radiance_postprocess/ies/lm.html new file mode 100644 index 00000000..e3365ed8 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/ies/lm.html @@ -0,0 +1,918 @@ + + + + + + + honeybee_radiance_postprocess.ies.lm — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.ies.lm

+"""Functions for IES LM post-processing."""
+from typing import Tuple, Union
+from collections import defaultdict
+import itertools
+import numpy as np
+
+from honeybee_radiance.postprocess.annual import filter_schedule_by_hours
+
+from ..annual import schedule_to_hoys, occupancy_schedule_8_to_6
+from ..results.annual_daylight import AnnualDaylight
+from ..util import filter_array
+from ..dynamic import DynamicSchedule, ApertureGroupSchedule
+from .lm_schedule import shd_trans_schedule_descending, states_schedule_descending
+
+
+
+[docs] +def shade_transmittance_per_light_path( + light_paths: list, shade_transmittance: Union[float, dict], + shd_trans_dict: dict) -> dict: + """Filter shade_transmittance by light paths and add default multiplier. + + Args: + light_paths: A list of light paths. + shade_transmittance: A value to use as a multiplier in place of solar + shading. This input can be either a single value that will be used + for all aperture groups, or a dictionary where aperture groups are + keys, and the value for each key is the shade transmittance. Values + for shade transmittance must be 1 > value > 0. + shd_trans_dict: A dictionary used to store shade transmittance value + for each aperture group. + + Returns: + A dictionary with filtered light paths. + """ + shade_transmittances = {} + if isinstance(shade_transmittance, dict): + for light_path in light_paths: + # default multiplier + shade_transmittances[light_path] = [1] + # add custom shade transmittance + if light_path in shade_transmittance: + shade_transmittances[light_path].append( + shade_transmittance[light_path]) + shd_trans_dict[light_path] = shade_transmittance[light_path] + # add default shade transmittance (0.02) + elif light_path != '__static_apertures__': + shade_transmittances[light_path].append(0.02) + shd_trans_dict[light_path] = 0.02 + else: + shade_transmittances[light_path].append(1) + shd_trans_dict[light_path] = 1 + else: + shd_trans = float(shade_transmittance) + for light_path in light_paths: + # default multiplier + shade_transmittances[light_path] = [1] + # add custom shade transmittance + if light_path != '__static_apertures__': + shade_transmittances[light_path].append(shd_trans) + shd_trans_dict[light_path] = shd_trans + else: + shade_transmittances[light_path].append(1) + shd_trans_dict[light_path] = 1 + + return shade_transmittances, shd_trans_dict
+ + + +
+[docs] +def dynamic_schedule_direct_illuminance( + results: Union[str, AnnualDaylight], grids_filter: str = '*', + shade_transmittance: Union[float, dict] = 0.02, + use_states: bool = False + ) -> Tuple[dict, dict]: + """Calculate a schedule of each aperture group. + + This function calculates an annual shading schedule of each aperture + group. Hour by hour it will select the least shaded aperture group + configuration, so that no more than 2% of the sensors points receive + direct illuminance of 1000 lux or more. + + Args: + results: Path to results folder or a Results class object. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + shade_transmittance: A value to use as a multiplier in place of solar + shading. This input can be either a single value that will be used + for all aperture groups, or a dictionary where aperture groups are + keys, and the value for each key is the shade transmittance. Values + for shade transmittance must be 1 > value > 0. + Defaults to 0.02. + use_states: A boolean to note whether to use the simulated states. Set + to True to use the simulated states. The default is False which will + use the shade transmittance instead. + + Returns: + Tuple: A tuple with a dictionary of the annual schedule and a + dictionary of hours where no shading configuration comply with the + 2% rule. + """ + if not isinstance(results, AnnualDaylight): + results = AnnualDaylight(results) + + grids_info = results._filter_grids(grids_filter=grids_filter) + schedule = occupancy_schedule_8_to_6(as_list=True) + occ_pattern = \ + filter_schedule_by_hours(results.sun_up_hours, schedule=schedule)[0] + occ_mask = np.array(occ_pattern) + + states_schedule = defaultdict(list) + fail_to_comply = {} + shd_trans_dict = {} + + for grid_info in grids_info: + grid_states_schedule = defaultdict(list) + + grid_count = grid_info['count'] + light_paths = [] + for lp in grid_info['light_path']: + for _lp in lp: + if _lp == '__static_apertures__' and len(lp) > 1: + pass + else: + light_paths.append(_lp) + + shade_transmittances, shd_trans_dict = ( + shade_transmittance_per_light_path( + light_paths, shade_transmittance, shd_trans_dict + ) + ) + + if len(light_paths) > 6: + if use_states: + grid_states_schedule, fail_to_comply = states_schedule_descending( + results, grid_info, light_paths, occ_mask, + grid_states_schedule, fail_to_comply) + else: + grid_states_schedule, fail_to_comply = shd_trans_schedule_descending( + results, grid_info, light_paths, shade_transmittances, occ_mask, + grid_states_schedule, fail_to_comply) + else: + if use_states: + combinations = results._get_state_combinations(grid_info) + else: + shade_transmittances, shd_trans_dict = shade_transmittance_per_light_path( + light_paths, shade_transmittance, shd_trans_dict) + keys, values = zip(*shade_transmittances.items()) + combinations = [dict(zip(keys, v)) for v in itertools.product(*values)] + + array_list_combinations = [] + for combination in combinations: + combination_arrays = [] + for light_path, value in combination.items(): + if use_states: + combination_arrays.append( + results._get_array(grid_info, light_path, state=value, + res_type='direct') + ) + else: + array = results._get_array( + grid_info, light_path, res_type='direct') + if value == 1: + combination_arrays.append(array) + else: + combination_arrays.append(array * value) + combination_array = sum(combination_arrays) + + combination_percentage = \ + (combination_array >= 1000).sum(axis=0) / grid_count + array_list_combinations.append(combination_percentage) + array_combinations = np.array(array_list_combinations) + array_combinations[array_combinations > 0.02] = -np.inf + + grid_comply = np.where(np.all(array_combinations==-np.inf, axis=0))[0] + if grid_comply.size != 0: + grid_comply = np.array(results.sun_up_hours)[grid_comply] + fail_to_comply[grid_info['name']] = \ + [int(hoy) for hoy in grid_comply] + + array_combinations_filter = np.apply_along_axis( + filter_array, 1, array_combinations, occ_mask + ) + max_indices = array_combinations_filter.argmax(axis=0) + # select the combination for each hour + combinations = [combinations[idx] for idx in max_indices] + + # merge the combinations of dicts + for combination in combinations: + for light_path, value in combination.items(): + if light_path != '__static_apertures__': + grid_states_schedule[light_path].append(value) + + for key, value in grid_states_schedule.items(): + if key not in states_schedule: + states_schedule[key] = value + + occupancy_hoys = schedule_to_hoys(schedule, results.sun_up_hours) + + # map states to 8760 values + if use_states: + aperture_group_schedules = [] + for identifier, values in states_schedule.items(): + mapped_states = results.values_to_annual( + occupancy_hoys, values, results.timestep, dtype=np.int32) + aperture_group_schedules.append( + ApertureGroupSchedule(identifier, mapped_states.tolist()) + ) + states_schedule = \ + DynamicSchedule.from_group_schedules(aperture_group_schedules) + else: + for light_path, shd_trans in states_schedule.items(): + mapped_states = results.values_to_annual( + occupancy_hoys, shd_trans, results.timestep) + states_schedule[light_path] = mapped_states + + return states_schedule, fail_to_comply, shd_trans_dict
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/ies/lm_schedule.html b/docs/_modules/honeybee_radiance_postprocess/ies/lm_schedule.html new file mode 100644 index 00000000..2c25ab60 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/ies/lm_schedule.html @@ -0,0 +1,948 @@ + + + + + + + honeybee_radiance_postprocess.ies.lm_schedule — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.ies.lm_schedule

+"""Module for dynamic LM schedules."""
+from typing import Tuple
+import numpy as np
+
+from ..results.annual_daylight import AnnualDaylight
+from ..util import filter_array
+
+
+
+[docs] +def shd_trans_schedule_descending( + results: AnnualDaylight, grid_info, light_paths, shade_transmittances, occ_mask, + states_schedule, fail_to_comply + ) -> Tuple[dict, dict]: + grid_count = grid_info['count'] + full_direct = [] + full_thresh = [] + full_shd_trans_array = [] + for light_path in light_paths: + array = results._get_array(grid_info, light_path, res_type="direct") + array = np.apply_along_axis(filter_array, 1, array, occ_mask) + full_direct.append(array) + full_thresh.append((array >= 1000).sum(axis=0)) + full_shd_trans_array.append(shade_transmittances[light_path][1]) + + # Sum the array element-wise. + # This array is the sum of all direct illuminance without shade + # transmittance. + full_direct_sum = sum(full_direct) + + # Create base list of shading combinations (all set to 1). + # We will replace the 1s later. + combinations = [ + {light_path: 1 for light_path in light_paths} + for i in range(full_direct_sum.shape[1]) + ] + + # Find the percentage of floor area >= 1000 lux. + # This array is the percentage for each hour (axis=0). + direct_pct_above = (full_direct_sum >= 1000).sum(axis=0) / grid_count + + # Find the indices where the percentage of floor area is > 2%. + # This array is the problematic hours. + above_2_indices = np.where(direct_pct_above > 0.02)[0] + + # Use the indices to get the relevant hours. + direct_sum = np.take(full_direct_sum, above_2_indices, axis=1) + + # Use the indices to get the relevant hours. + direct = np.take(full_direct, above_2_indices, axis=2) + + # Use the indices to get the relevant hours. + thresh = np.take(full_thresh, above_2_indices, axis=1) + + # Sort and get indices. Negate the array to get descending order. + # Descending order puts the "highest offender" light path first. + sort_thresh = np.argsort(-thresh, axis=0).transpose() + + _combinations = [] + _combinations.insert( + 0, (np.arange(full_direct_sum.shape[1]), combinations) + ) + + if np.any(above_2_indices): + # There are hours where the percentage of floor area is > 2%. + for idx, lp in enumerate(light_paths): + # Take column. For each iteration it will take the next column + # in descending order, i.e., the "highest offender" is the first + # column. + sort_indices = np.take(sort_thresh, idx, axis=1) + + # Map light path identifiers to indices. + light_path_ids = np.take(light_paths, sort_indices) + + # Map shade transmittance to indices. + shd_trans_array = np.take(full_shd_trans_array, sort_indices) + + # Create combination for the subset. + _subset_combination = [ + {light_path: _shd_trans} for light_path, _shd_trans in + zip(light_path_ids, shd_trans_array) + ] + _combinations.insert(0, (above_2_indices, _subset_combination)) + + # Take the values from each array by indexing. + direct_array = \ + direct[sort_indices, :, range(len(sort_indices))].transpose() + + # Subtract the illuminance values. + direct_sum = direct_sum - (direct_array * (1 - shd_trans_array)) + + # Find the percentage of floor area >= 1000 lux. + direct_pct_above = (direct_sum >= 1000).sum(axis=0) / grid_count + + # Find the indices where the percentage of floor area is > 2%. + above_2_indices = np.where(direct_pct_above > 0.02)[0] + + # Break if there are no hours above 2%. + if not np.any(above_2_indices): + break + + # Update variables for the next iteration. + direct_sum = np.take(direct_sum, above_2_indices, axis=1) + direct = np.take(direct, above_2_indices, axis=2) + thresh = np.take(thresh, above_2_indices, axis=1) + sort_thresh = np.take(sort_thresh, above_2_indices, axis=0) + + if np.any(above_2_indices): + # There are hours not complying with the 2% rule. + previous_indices = [] + previous_combination = [] + grid_comply = [] + # Merge the combinations from the iterations of the subsets. + for i, subset in enumerate(_combinations): + if i == 0: + previous_indices = subset[0] + else: + _indices = subset[0] + grid_comply = [] + for _pr_idx in previous_indices: + grid_comply.append(_indices[_pr_idx]) + previous_indices = grid_comply + # Convert indices to sun up hours indices. + filter_indices = np.where(occ_mask.astype(bool))[0] + grid_comply = [filter_indices[_gc] for _gc in grid_comply] + grid_comply = np.array(results.sun_up_hours)[grid_comply] + fail_to_comply[grid_info['name']] = \ + [int(hoy) for hoy in grid_comply] + + previous_indices = None + previous_combination = None + # Merge the combinations from the iterations of the subsets. + for i, subset in enumerate(_combinations): + if i == 0: + previous_indices, previous_combination = subset + else: + _indices, _combination = subset + for _pr_idx, _pr_comb in \ + zip(previous_indices, previous_combination): + for light_path, _shd_trans in _pr_comb.items(): + _combination[_pr_idx][light_path] = _shd_trans + previous_indices = _indices + previous_combination = _combination + + combinations = _combination + + # Merge the combinations of dicts. + for combination in combinations: + for light_path, shd_trans in combination.items(): + if light_path != "__static_apertures__": + states_schedule[light_path].append(shd_trans) + + return states_schedule, fail_to_comply
+ + + +
+[docs] +def states_schedule_descending( + results: AnnualDaylight, grid_info, light_paths, occ_mask, + states_schedule, fail_to_comply + ) -> Tuple[dict, dict]: + grid_count = grid_info['count'] + full_direct = [] + full_thresh = [] + full_direct_blinds = [] + for light_path in light_paths: + array = results._get_array( + grid_info, light_path, state=0, res_type="direct") + array = np.apply_along_axis(filter_array, 1, array, occ_mask) + full_direct.append(array) + full_thresh.append((array >= 1000).sum(axis=0)) + + array = results._get_array( + grid_info, light_path, state=1, res_type="direct") + array = np.apply_along_axis(filter_array, 1, array, occ_mask) + full_direct_blinds.append(array) + + full_direct = np.array(full_direct) + full_direct_blinds = np.array(full_direct_blinds) + full_direct_sum = full_direct.sum(axis=0) + + new_array = full_direct.copy() + + percentage_sensors = (full_direct_sum >= 1000).sum(axis=0) / grid_count + if not np.any(percentage_sensors > 0.02): + combinations = [ + {light_path: 0 for light_path in light_paths} + for i in range(full_direct_sum.shape[1])] + else: + tracking_array = np.zeros( + (new_array.shape[0], new_array.shape[2]), dtype=int) + + percentage_sensors = (full_direct >= 1000).sum(axis=1) / grid_count + + ranking_indices = np.argsort(-percentage_sensors, axis=0) + + for rank in range(ranking_indices.shape[0]): + # Calculate the percentage of sensors with values >= 1000 for the current new_array + summed_array = np.sum(new_array, axis=0) + percentage_sensors_summed = np.sum( + summed_array >= 1000, axis=0) / grid_count + indices_above_2_percent = np.where( + percentage_sensors_summed > 0.02)[0] + + # Exit if there are no more hours exceeding the threshold + if len(indices_above_2_percent) == 0: + break + + # Array indices to use for replacement for these hours + replace_indices = indices_above_2_percent + array_indices = ranking_indices[rank, replace_indices] + + # Use advanced indexing to replace values in new_array for these hours + for hour_idx, array_idx in zip(replace_indices, array_indices): + new_array[array_idx, :, hour_idx] = full_direct_blinds[ + array_idx, :, hour_idx + ] + + # Update the tracking array + tracking_array[array_indices, replace_indices] = 1 + + combinations = [] + for hour in range(new_array.shape[2]): + hour_dict = { + light_paths[i]: tracking_array[i, hour] + for i in range(tracking_array.shape[0])} + combinations.append(hour_dict) + + final_summed_array = np.sum(new_array, axis=0) + final_percentage_sensors_summed = ( + final_summed_array >= 1000).sum( + axis=0) / grid_count + final_indices_above_2_percent = np.where( + final_percentage_sensors_summed > 0.02)[0] + if np.any(final_indices_above_2_percent): + sun_up_hours_indices = np.where(occ_mask == 1)[0][ + final_indices_above_2_percent] + grid_comply = np.array(results.sun_up_hours)[sun_up_hours_indices] + fail_to_comply[grid_info['name']] = [ + int(hoy) for hoy in grid_comply] + + for combination in combinations: + for light_path, value in combination.items(): + if light_path != '__static_apertures__': + states_schedule[light_path].append(value) + + return states_schedule, fail_to_comply
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/leed/leed.html b/docs/_modules/honeybee_radiance_postprocess/leed/leed.html new file mode 100644 index 00000000..8d37bb6f --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/leed/leed.html @@ -0,0 +1,1475 @@ + + + + + + + honeybee_radiance_postprocess.leed.leed — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.leed.leed

+"""Functions for LEED post-processing."""
+from typing import Tuple, Union
+from pathlib import Path
+from collections import defaultdict
+import json
+import itertools
+import numpy as np
+
+from ladybug.analysisperiod import AnalysisPeriod
+from ladybug.datatype.generic import GenericType
+from ladybug.color import Colorset
+from ladybug.datacollection import HourlyContinuousCollection
+from ladybug.datatype.fraction import Fraction
+from ladybug.datatype.time import Time
+from ladybug.legend import LegendParameters
+from ladybug.header import Header
+from honeybee.model import Model
+from honeybee.units import conversion_factor_to_meters
+from honeybee_radiance.writer import _filter_by_pattern
+from honeybee_radiance.postprocess.annual import filter_schedule_by_hours
+
+from ..metrics import da_array2d, ase_array2d
+from ..annual import schedule_to_hoys, occupancy_schedule_8_to_6
+from ..results.annual_daylight import AnnualDaylight
+from ..util import filter_array, recursive_dict_merge
+from ..dynamic import DynamicSchedule, ApertureGroupSchedule
+from .leed_schedule import shd_trans_schedule_descending, states_schedule_descending
+
+
+def _create_grid_summary(
+    grid_info, sda_grid, sda_blinds_up_grid, sda_blinds_down_grid, ase_grid,
+    pass_sda, pass_ase, total_floor, area_weighted=True):
+    """Create a LEED summary for a single grid.
+
+    Args:
+        grid_info: Grid information.
+        sda_grid: Spatial Daylight Autonomy.
+        ase_grid: Annual Sunlight Exposure.
+        pass_sda: The percentage of the sensor points or floor area that
+            passes sDA.
+        pass_ase: The percentage of the sensor points or floor area that
+            passes ASE.
+        total_floor: The number of sensor points or floor area.
+        area_weighted: Boolean to determine if the results are area
+            weighted. Defaults to True.
+
+    Returns:
+        Tuple:
+        -   summary_grid: Summary of each grid individually.
+    """
+    grid_id = grid_info['full_id']
+    grid_name = grid_info['name']
+    grid_summary = {
+        grid_id: {}
+    }
+    if ase_grid > 10:
+        ase_note = (
+            'The Annual Sunlight Exposure is greater than 10% for space: '
+            f'{grid_name}. Identify in writing how the space is designed to '
+            'address glare.'
+        )
+        grid_summary[grid_id]['ase_note'] = ase_note
+
+    if area_weighted:
+        _grid_summary = {
+            grid_id: {
+                'name': grid_name,
+                'full_id': grid_id,
+                'ase': round(ase_grid, 2),
+                'sda': round(sda_grid, 2),
+                'sda_blinds_up': round(sda_blinds_up_grid, 2),
+                'sda_blinds_down': round(sda_blinds_down_grid, 2),
+                'floor_area_passing_ase': round(pass_ase, 2),
+                'floor_area_passing_sda': round(pass_sda, 2),
+                'total_floor_area': round(total_floor, 2)
+            }
+        }
+    else:
+        _grid_summary = {
+            grid_id: {
+                'name': grid_name,
+                'full_id': grid_id,
+                'ase': round(ase_grid, 2),
+                'sda': round(sda_grid, 2),
+                'sda_blinds_up': round(sda_blinds_up_grid, 2),
+                'sda_blinds_down': round(sda_blinds_down_grid, 2),
+                'sensor_count_passing_ase': int(round(pass_ase, 2)),
+                'sensor_count_passing_sda': int(round(pass_sda, 2)),
+                'total_sensor_count': total_floor
+            }
+        }
+
+    recursive_dict_merge(grid_summary, _grid_summary)
+
+    return grid_summary
+
+
+def _leed_summary(
+    pass_ase_grids: list, pass_sda_grids: list, grids_info: list,
+    grid_areas: list, pass_sda_blinds_up_grids: list,
+    pass_sda_blinds_down_grids: list) -> Tuple[dict, dict]:
+    """Create combined summary and summary for each grid individually.
+
+    Args:
+        pass_ase_grids: A list where each sublist is a list of True/False that
+            tells if each sensor point passes ASE.
+        pass_sda_grids: A list where each sublist is a list of True/False that
+            tells if each sensor point passes sDA.
+        grids_info: A list of grid information.
+        grid_areas: A list where each sublist is the area of each sensor point.
+            The alternative is a list of None values for each grid information.
+
+    Returns:
+        Tuple:
+        -   summary: Summary of of all grids combined.
+        -   summary_grid: Summary of each grid individually.
+    """
+    summary = {}
+    summary_grid = {}
+
+    if all(grid_area is not None for grid_area in grid_areas):
+        # weighted by mesh face area
+        total_area = 0
+        total_area_pass_ase = 0
+        total_area_pass_sda = 0
+        for (pass_ase, pass_sda, grid_area, grid_info, pass_sda_blinds_up,
+             pass_sda_blinds_down) in \
+            zip(pass_ase_grids, pass_sda_grids, grid_areas, grids_info,
+                pass_sda_blinds_up_grids, pass_sda_blinds_down_grids):
+            total_grid_area = grid_area.sum()
+
+            area_pass_ase = grid_area[pass_ase].sum()
+            ase_grid = (total_grid_area - area_pass_ase) / total_grid_area * 100
+
+            area_pass_sda = grid_area[pass_sda].sum()
+            area_pass_sda_blind_up = grid_area[pass_sda_blinds_up].sum()
+            area_pass_sda_blinds_down = grid_area[pass_sda_blinds_down].sum()
+            sda_grid = area_pass_sda / total_grid_area * 100
+            sda_blinds_up_grid = area_pass_sda_blind_up / total_grid_area * 100
+            sda_blinds_down_grid = area_pass_sda_blinds_down / total_grid_area * 100
+
+            # grid summary
+            grid_summary = \
+                _create_grid_summary(
+                    grid_info, sda_grid, sda_blinds_up_grid, sda_blinds_down_grid,
+                    ase_grid, area_pass_sda, area_pass_ase, total_grid_area,
+                    area_weighted=True
+                )
+
+            recursive_dict_merge(summary_grid, grid_summary)
+
+            total_area += total_grid_area
+            total_area_pass_ase += area_pass_ase
+            total_area_pass_sda += area_pass_sda
+
+        summary['ase'] = round((total_area - total_area_pass_ase) / total_area * 100, 2)
+        summary['sda'] = round(total_area_pass_sda / total_area * 100, 2)
+        summary['floor_area_passing_ase'] = total_area_pass_ase
+        summary['floor_area_passing_sda'] = total_area_pass_sda
+        summary['total_floor_area'] = total_area
+    else:
+        # assume all sensor points cover the same area
+        total_sensor_count = 0
+        total_sensor_count_pass_ase = 0
+        total_sensor_count_pass_sda = 0
+        for (pass_ase, pass_sda, grid_info, pass_sda_blinds_up,
+             pass_sda_blinds_down) in \
+            zip(pass_ase_grids, pass_sda_grids, grids_info,
+                pass_sda_blinds_up_grids, pass_sda_blinds_down_grids):
+            grid_count = grid_info['count']
+            sensor_count_pass_ase = pass_ase.sum()
+            ase_grid = (grid_count - sensor_count_pass_ase) / grid_count * 100
+
+            sensor_count_pass_sda = pass_sda.sum()
+            sensor_count_pass_sda_blinds_up = pass_sda_blinds_up.sum()
+            sensor_count_pass_sda_blinds_down = pass_sda_blinds_down.sum()
+            sda_grid = sensor_count_pass_sda / grid_count * 100
+            sda_blinds_up_grid = sensor_count_pass_sda_blinds_up / grid_count * 100
+            sda_blinds_down_grid = sensor_count_pass_sda_blinds_down / grid_count * 100
+
+            # grid summary
+            grid_summary = \
+                _create_grid_summary(
+                    grid_info, sda_grid, sda_blinds_up_grid, sda_blinds_down_grid,
+                    ase_grid, sensor_count_pass_sda, sensor_count_pass_ase,
+                    grid_count, area_weighted=False
+                )
+
+            recursive_dict_merge(summary_grid, grid_summary)
+
+            total_sensor_count += grid_count
+            total_sensor_count_pass_ase += sensor_count_pass_ase
+            total_sensor_count_pass_sda += sensor_count_pass_sda
+
+        summary['ase'] = round((total_sensor_count - total_sensor_count_pass_ase) /
+            total_sensor_count * 100, 2
+        )
+        summary['sda'] = round(total_sensor_count_pass_sda / total_sensor_count * 100, 2)
+        summary['sensor_count_passing_ase'] = int(total_sensor_count_pass_ase)
+        summary['sensor_count_passing_sda'] = int(total_sensor_count_pass_sda)
+        summary['total_sensor_count'] = total_sensor_count
+
+    return summary, summary_grid
+
+
+def _ase_hourly_percentage(
+    results: AnnualDaylight, array: np.ndarray, grid_info: dict,
+    direct_threshold: float = 1000, grid_area: Union[None, np.ndarray] = None
+    ) -> np.ndarray:
+    """Calculate the percentage of floor area that receives greater than 1000
+    direct lux for each hour.
+
+    Args:
+        results: A Results object.
+        array: A NumPy array of the grid to process.
+        grid_info: Grid information of the grid to process..
+        direct_threshold: Direct threshold.
+        grid_area: Grid area as a NumPy array with a area value for each sensor
+            point, or a None value if there is no area associated with the
+            sensor point.
+
+    Returns:
+        A hourly data collection of the percentage of floor area that receives
+        greater than 1000 direct lux.
+    """
+    if grid_area is not None:
+        grid_area_2d = np.array([grid_area] * array.shape[1]).transpose()
+        area_above = \
+            np.where((array > direct_threshold), grid_area_2d, 0).sum(axis=0)
+        percentage_above = area_above / grid_area.sum() * 100
+    else:
+        percentage_above = \
+            (array > direct_threshold).sum(axis=0) / grid_info['count'] * 100
+
+    occupancy_hoys = schedule_to_hoys(results.schedule, results.sun_up_hours)
+    # map states to 8760 values
+    percentage_above = results.values_to_annual(
+        occupancy_hoys, percentage_above, results.timestep)
+    header = Header(Fraction('Percentage above 1000 direct lux'), '%',
+                    AnalysisPeriod(results.timestep),
+                    metadata={'SensorGrid': grid_info['name']})
+    data_collection = HourlyContinuousCollection(header, percentage_above.tolist())
+
+    return data_collection
+
+
+[docs] +def shade_transmittance_per_light_path( + light_paths: list, shade_transmittance: Union[float, dict], + shd_trans_dict: dict) -> dict: + """Filter shade_transmittance by light paths and add default multiplier. + + Args: + light_paths: A list of light paths. + shade_transmittance: A value to use as a multiplier in place of solar + shading. This input can be either a single value that will be used + for all aperture groups, or a dictionary where aperture groups are + keys, and the value for each key is the shade transmittance. Values + for shade transmittance must be 1 > value > 0. + shd_trans_dict: A dictionary used to store shade transmittance value + for each aperture group. + + Returns: + A dictionary with filtered light paths. + """ + shade_transmittances = {} + if isinstance(shade_transmittance, dict): + for light_path in light_paths: + # default multiplier + shade_transmittances[light_path] = [1] + # add custom shade transmittance + if light_path in shade_transmittance: + shade_transmittances[light_path].append( + shade_transmittance[light_path]) + shd_trans_dict[light_path] = shade_transmittance[light_path] + # add default shade transmittance (0.05) + elif light_path != '__static_apertures__': + shade_transmittances[light_path].append(0.05) + shd_trans_dict[light_path] = 0.05 + else: + shade_transmittances[light_path].append(1) + shd_trans_dict[light_path] = 1 + else: + shd_trans = float(shade_transmittance) + for light_path in light_paths: + # default multiplier + shade_transmittances[light_path] = [1] + # add custom shade transmittance + if light_path != '__static_apertures__': + shade_transmittances[light_path].append(shd_trans) + shd_trans_dict[light_path] = shd_trans + else: + shade_transmittances[light_path].append(1) + shd_trans_dict[light_path] = 1 + + return shade_transmittances, shd_trans_dict
+ + + +
+[docs] +def leed_states_schedule( + results: Union[str, AnnualDaylight], grids_filter: str = '*', + shade_transmittance: Union[float, dict] = 0.05, + use_states: bool = False + ) -> Tuple[dict, dict]: + """Calculate a schedule of each aperture group for LEED compliant sDA. + + This function calculates an annual shading schedule of each aperture + group. Hour by hour it will select the least shaded aperture group + configuration, so that no more than 2% of the sensors points receive + direct illuminance of 1000 lux or more. + + Args: + results: Path to results folder or a Results class object. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + shade_transmittance: A value to use as a multiplier in place of solar + shading. This input can be either a single value that will be used + for all aperture groups, or a dictionary where aperture groups are + keys, and the value for each key is the shade transmittance. Values + for shade transmittance must be 1 > value > 0. + Defaults to 0.05. + use_states: A boolean to note whether to use the simulated states. Set + to True to use the simulated states. The default is False which will + use the shade transmittance instead. + + Returns: + Tuple: A tuple with a dictionary of the annual schedule and a + dictionary of hours where no shading configuration comply with the + 2% rule. + """ + if not isinstance(results, AnnualDaylight): + results = AnnualDaylight(results) + + grids_info = results._filter_grids(grids_filter=grids_filter) + schedule = occupancy_schedule_8_to_6(as_list=True) + occ_pattern = \ + filter_schedule_by_hours(results.sun_up_hours, schedule=schedule)[0] + occ_mask = np.array(occ_pattern) + + states_schedule = defaultdict(list) + fail_to_comply = {} + shd_trans_dict = {} + + for grid_info in grids_info: + grid_states_schedule = defaultdict(list) + grid_count = grid_info['count'] + light_paths = [] + for lp in grid_info['light_path']: + for _lp in lp: + if _lp == '__static_apertures__' and len(lp) > 1: + pass + else: + light_paths.append(_lp) + + shade_transmittances, shd_trans_dict = ( + shade_transmittance_per_light_path( + light_paths, shade_transmittance, shd_trans_dict + ) + ) + + if len(light_paths) > 6: + if use_states: + grid_states_schedule, fail_to_comply = states_schedule_descending( + results, grid_info, light_paths, occ_mask, + grid_states_schedule, fail_to_comply) + else: + grid_states_schedule, fail_to_comply = shd_trans_schedule_descending( + results, grid_info, light_paths, shade_transmittances, occ_mask, + grid_states_schedule, fail_to_comply) + else: + if use_states: + combinations = results._get_state_combinations(grid_info) + else: + shade_transmittances, shd_trans_dict = shade_transmittance_per_light_path( + light_paths, shade_transmittance, shd_trans_dict) + keys, values = zip(*shade_transmittances.items()) + combinations = [dict(zip(keys, v)) for v in itertools.product(*values)] + + array_list_combinations = [] + for combination in combinations: + combination_arrays = [] + for light_path, value in combination.items(): + if use_states: + combination_arrays.append( + results._get_array(grid_info, light_path, state=value, + res_type='direct') + ) + else: + array = results._get_array( + grid_info, light_path, res_type='direct') + if value == 1: + combination_arrays.append(array) + else: + combination_arrays.append(array * value) + combination_array = sum(combination_arrays) + + combination_percentage = \ + (combination_array >= 1000).sum(axis=0) / grid_count + array_list_combinations.append(combination_percentage) + array_combinations = np.array(array_list_combinations) + array_combinations[array_combinations > 0.02] = -np.inf + + grid_comply = np.where(np.all(array_combinations==-np.inf, axis=0))[0] + if grid_comply.size != 0: + grid_comply = np.array(results.sun_up_hours)[grid_comply] + fail_to_comply[grid_info['name']] = \ + [int(hoy) for hoy in grid_comply] + + array_combinations_filter = np.apply_along_axis( + filter_array, 1, array_combinations, occ_mask + ) + max_indices = array_combinations_filter.argmax(axis=0) + # select the combination for each hour + combinations = [combinations[idx] for idx in max_indices] + # merge the combinations of dicts + for combination in combinations: + for light_path, value in combination.items(): + if light_path != '__static_apertures__': + grid_states_schedule[light_path].append(value) + + for key, value in grid_states_schedule.items(): + if key not in states_schedule: + states_schedule[key] = value + + occupancy_hoys = schedule_to_hoys(schedule, results.sun_up_hours) + + # map states to 8760 values + if use_states: + aperture_group_schedules = [] + for identifier, values in states_schedule.items(): + mapped_states = results.values_to_annual( + occupancy_hoys, values, results.timestep, dtype=np.int32) + aperture_group_schedules.append( + ApertureGroupSchedule(identifier, mapped_states.tolist()) + ) + states_schedule = \ + DynamicSchedule.from_group_schedules(aperture_group_schedules) + else: + for light_path, shd_trans in states_schedule.items(): + mapped_states = results.values_to_annual( + occupancy_hoys, shd_trans, results.timestep) + states_schedule[light_path] = mapped_states + + return states_schedule, fail_to_comply, shd_trans_dict
+ + + +
+[docs] +def leed_option_one( + results: Union[str, AnnualDaylight], grids_filter: str = '*', + shade_transmittance: Union[float, dict] = 0.05, + use_states: bool = False, states_schedule: dict = None, + threshold: float = 300, direct_threshold: float = 1000, + occ_hours: int = 250, target_time: float = 50, sub_folder: str = None): + """Calculate credits for LEED v4.1 Daylight Option 1. + + Args: + results: Path to results folder or a Results class object. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + shade_transmittance: A value to use as a multiplier in place of solar + shading. This input can be either a single value that will be used + for all aperture groups, or a dictionary where aperture groups are + keys, and the value for each key is the shade transmittance. Values + for shade transmittance must be 1 > value > 0. + Defaults to 0.05. + use_states: A boolean to note whether to use the simulated states. Set + to True to use the simulated states. The default is False which will + use the shade transmittance instead. + states_schedule: A custom dictionary of shading states. In case this is + left empty, the function will calculate a shading schedule by using + the shade_transmittance input. If a states schedule is provided it + will check that it is complying with the 2% rule. Defaults to None. + threshold: Threshold value for daylight autonomy. Default: 300. + direct_threshold: The threshold that determines if a sensor is overlit. + Defaults to 1000. + occ_hours: The number of occupied hours that cannot receive more than + the direct_threshold. Defaults to 250. + target_time: A minimum threshold of occupied time (eg. 50% of the + time), above which a given sensor passes and contributes to the + spatial daylight autonomy. Defaults to 50. + sub_folder: Relative path for a subfolder to write the output. If None, + the files will not be written. Defaults to None. + + Returns: + Tuple: + - summary: Summary of all grids combined. + - summary_grid: Summary of each grid individually. + - da_grids: List of daylight autonomy values for each grid. Each item + in the list is a NumPy array of DA values. + - hours_above: List of hours above 1000 direct illuminance (with + default states) for each grid. Each item in the list is a NumPy + array of hours above 1000 lux. + - states_schedule: A dictionary of annual shading schedules for each + aperture group. + - fail_to_comply: A dictionary with the hoys where the 2% rule failed. + - grids_info: Grid information. + """ + # use default leed occupancy schedule + schedule = occupancy_schedule_8_to_6(as_list=True) + + if not isinstance(results, AnnualDaylight): + results = AnnualDaylight(results, schedule=schedule) + else: + # set schedule to default leed schedule + results.schedule = schedule + + occ_mask = results.occ_mask + total_occ = results.total_occ + + grids_info = results._filter_grids(grids_filter=grids_filter) + + if not states_schedule: + states_schedule, fail_to_comply, shd_trans_dict = \ + leed_states_schedule(results, grids_filter=grids_filter, + shade_transmittance=shade_transmittance, use_states=use_states) + else: + raise NotImplementedError( + 'Custom input for argument states_schedule is not yet implemented.' + ) + + # check to see if there is a HBJSON with sensor grid meshes for areas + grid_areas, units_conversion = [], 1 + for base_file in Path(results.folder).parent.iterdir(): + if base_file.suffix in ('.hbjson', '.hbpkl'): + hb_model = Model.from_file(base_file) + units_conversion = conversion_factor_to_meters(hb_model.units) + filt_grids = _filter_by_pattern( + hb_model.properties.radiance.sensor_grids, filter=grids_filter) + for s_grid in filt_grids: + if s_grid.mesh is not None: + grid_areas.append(s_grid.mesh.face_areas) + grid_areas = [np.array(grid) for grid in grid_areas] + break + if not grid_areas: + grid_areas = [None] * len(grids_info) + + # annual sunlight exposure + ase_grids = [] + hours_above = [] + pass_ase_grids = [] + ase_hr_pct = [] + for (grid_info, grid_area) in zip(grids_info, grid_areas): + light_paths = [] + for lp in grid_info['light_path']: + for _lp in lp: + if _lp == '__static_apertures__' and len(lp) > 1: + pass + else: + light_paths.append(_lp) + arrays = [] + # combine direct array for all light paths + for light_path in light_paths: + array = results._get_array( + grid_info, light_path, res_type='direct') + array_filter = np.apply_along_axis( + filter_array, 1, array, occ_mask) + arrays.append(array_filter) + array = sum(arrays) + # calculate ase per grid + ase_grid, h_above = ase_array2d( + array, occ_hours=occ_hours, direct_threshold=direct_threshold) + + # calculate the number of sensor points above 1000 lux for each hour + ase_hr_pct.append( + _ase_hourly_percentage( + results, array, grid_info, direct_threshold=direct_threshold, + grid_area=grid_area + ) + ) + + ase_grids.append(ase_grid) + hours_above.append(h_above) + pass_ase = h_above < occ_hours + pass_ase_grids.append(pass_ase) + + # spatial daylight autonomy + da_grids = [] + pass_sda_grids = [] + pass_sda_blinds_up_grids = [] + pass_sda_blinds_down_grids = [] + for grid_info in grids_info: + light_paths = [] + for lp in grid_info['light_path']: + for _lp in lp: + if _lp == '__static_apertures__' and len(lp) > 1: + pass + else: + light_paths.append(_lp) + base_zero_array = np.apply_along_axis(filter_array, 1, np.zeros( + (grid_info['count'], len(results.sun_up_hours))), occ_mask) + arrays = [base_zero_array.copy()] + arrays_blinds_up = [base_zero_array.copy()] + arrays_blinds_down = [base_zero_array.copy()] + # combine total array for all light paths + if use_states: + array = results._array_from_states(grid_info, states=states_schedule, zero_array=True) + array = np.apply_along_axis(filter_array, 1, array, occ_mask) + + for light_path in light_paths: + # do an extra pass to calculate with blinds always up or down + if light_path != '__static_apertures__': + array_blinds_up = results._get_array( + grid_info, light_path, state=0, res_type='total') + array_filter = np.apply_along_axis( + filter_array, 1, array_blinds_up, occ_mask) + arrays_blinds_up.append(array_filter) + array_blinds_down = results._get_array( + grid_info, light_path, state=1, res_type='total') + array_filter = np.apply_along_axis( + filter_array, 1, array_blinds_down, occ_mask) + arrays_blinds_down.append(array_filter) + else: + static_array = results._get_array( + grid_info, light_path, state=0, res_type='total') + array_filter = np.apply_along_axis( + filter_array, 1, static_array, occ_mask) + arrays_blinds_up.append(array_filter) + arrays_blinds_down.append(array_filter) + else: + for light_path in light_paths: + array = results._get_array( + grid_info, light_path, res_type='total') + array_filter = np.apply_along_axis( + filter_array, 1, array, occ_mask) + if light_path != '__static_apertures__': + sun_up_hours = np.array(results.sun_up_hours).astype(int) + shd_trans_array = states_schedule[light_path][sun_up_hours] + shd_trans_array = shd_trans_array[occ_mask.astype(bool)] + arrays.append(array_filter * shd_trans_array) + arrays_blinds_up.append(array_filter) + arrays_blinds_down.append( + array_filter * shd_trans_dict[light_path]) + else: + arrays.append(array_filter) + arrays_blinds_up.append(array_filter) + arrays_blinds_down.append(array_filter) + array = sum(arrays) + + array_blinds_up = sum(arrays_blinds_up) + array_blinds_down = sum(arrays_blinds_down) + # calculate da per grid + da_grid = da_array2d(array, total_occ=total_occ, threshold=threshold) + da_grids.append(da_grid) + da_blinds_up_grid = da_array2d( + array_blinds_up, total_occ=total_occ, threshold=threshold) + da_blinds_down_grid = da_array2d( + array_blinds_down, total_occ=total_occ, threshold=threshold) + # calculate sda per grid + pass_sda_grids.append(da_grid >= target_time) + pass_sda_blinds_up_grids.append(da_blinds_up_grid >= target_time) + pass_sda_blinds_down_grids.append(da_blinds_down_grid >= target_time) + + # create summaries for all grids and each grid individually + summary, summary_grid = _leed_summary( + pass_ase_grids, pass_sda_grids, grids_info, grid_areas, + pass_sda_blinds_up_grids, pass_sda_blinds_down_grids) + + # credits + if not fail_to_comply: + if summary['sda'] >= 75: + summary['credits'] = 3 + elif summary['sda'] >= 55: + summary['credits'] = 2 + elif summary['sda'] >= 40: + summary['credits'] = 1 + else: + summary['credits'] = 0 + + if all(grid_summary['sda'] >= 55 for grid_summary in summary_grid.values()): + if summary['credits'] <= 2: + summary['credits'] += 1 + else: + summary['credits'] = 'Exemplary performance' + else: + summary['credits'] = 0 + fail_to_comply_rooms = ', '.join(list(fail_to_comply.keys())) + note = ( + '0 credits have been awarded. The following sensor grids have at ' + 'least one hour where 2% of the floor area receives direct ' + f'illuminance of 1000 lux or more: {fail_to_comply_rooms}.' + ) + summary['note'] = note + + # convert to datacollection + def to_datacollection(aperture_group: str, values: np.ndarray): + # convert values to 0 and 1 (0 = no shading, 1 = shading) + if use_states: + header = Header(data_type=GenericType(aperture_group, ''), unit='', + analysis_period=AnalysisPeriod()) + hourly_data = HourlyContinuousCollection(header=header, values=values) + else: + values[values == 1] = 0 + values[values == shd_trans_dict[aperture_group]] = 1 + header = Header(data_type=GenericType(aperture_group, ''), unit='', + analysis_period=AnalysisPeriod(), + metadata={'Shade Transmittance': shd_trans_dict[aperture_group]}) + hourly_data = HourlyContinuousCollection(header=header, values=values.tolist()) + return hourly_data.to_dict() + + if use_states: + states_schedule = {k:to_datacollection(k, v['schedule']) for k, v in states_schedule.to_dict().items()} + else: + states_schedule = {k:to_datacollection(k, v) for k, v in states_schedule.items()} + + if sub_folder: + folder = Path(sub_folder) + folder.mkdir(parents=True, exist_ok=True) + + summary_file = folder.joinpath('summary.json') + summary_file.write_text(json.dumps(summary, indent=2)) + summary_grid_file = folder.joinpath('summary_grid.json') + summary_grid_file.write_text(json.dumps(summary_grid, indent=2)) + states_schedule_file = folder.joinpath('states_schedule.json') + states_schedule_file.write_text(json.dumps(states_schedule)) + grids_info_file = folder.joinpath('grids_info.json') + grids_info_file.write_text(json.dumps(grids_info, indent=2)) + + for (da, h_above, ase_hr_p, grid_info) in \ + zip(da_grids, hours_above, ase_hr_pct, grids_info): + grid_id = grid_info['full_id'] + da_file = folder.joinpath('results', 'da', f'{grid_id}.da') + da_file.parent.mkdir(parents=True, exist_ok=True) + hours_above_file = folder.joinpath( + 'results', 'ase_hours_above', f'{grid_id}.res') + hours_above_file.parent.mkdir(parents=True, exist_ok=True) + ase_hr_p_file = folder.joinpath( + 'datacollections', 'ase_percentage_above', f'{grid_id}.json') + ase_hr_p_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(da_file, da, fmt='%.2f') + np.savetxt(hours_above_file, h_above, fmt='%.0f') + ase_hr_p_file.write_text(json.dumps(ase_hr_p.to_dict())) + + da_grids_info_file = folder.joinpath( + 'results', 'da', 'grids_info.json') + da_grids_info_file.write_text(json.dumps(grids_info, indent=2)) + ase_grids_info_file = folder.joinpath( + 'results', 'ase_hours_above', 'grids_info.json') + ase_grids_info_file.write_text(json.dumps(grids_info, indent=2)) + ase_hr_pct_info_file = folder.joinpath( + 'datacollections', 'ase_percentage_above', 'grids_info.json') + ase_hr_pct_info_file.write_text(json.dumps(grids_info, indent=2)) + + states_schedule_err_file = \ + folder.joinpath('states_schedule_err.json') + states_schedule_err_file.write_text(json.dumps(fail_to_comply)) + + return (summary, summary_grid, da_grids, hours_above, states_schedule, + fail_to_comply, grids_info)
+ + + +def _leed_daylight_option_one_vis_metadata(): + """Return visualization metadata for leed daylight option one.""" + da_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort()) + ase_hrs_lpar = LegendParameters(min=0, max=250, colors=Colorset.original()) + + metric_info_dict = { + 'da': { + 'type': 'VisualizationMetaData', + 'data_type': Fraction('Daylight Autonomy').to_dict(), + 'unit': '%', + 'legend_parameters': da_lpar.to_dict() + }, + 'ase_hours_above': { + 'type': 'VisualizationMetaData', + 'data_type': Time('Hours above direct threshold').to_dict(), + 'unit': 'hr', + 'legend_parameters': ase_hrs_lpar.to_dict() + } + } + + return metric_info_dict +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/leed/leed_schedule.html b/docs/_modules/honeybee_radiance_postprocess/leed/leed_schedule.html new file mode 100644 index 00000000..e68eb507 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/leed/leed_schedule.html @@ -0,0 +1,948 @@ + + + + + + + honeybee_radiance_postprocess.leed.leed_schedule — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.leed.leed_schedule

+"""Module for dynamic LEED schedules."""
+from typing import Tuple
+import numpy as np
+
+from ..results.annual_daylight import AnnualDaylight
+from ..util import filter_array
+
+
+
+[docs] +def shd_trans_schedule_descending( + results: AnnualDaylight, grid_info, light_paths, shade_transmittances, occ_mask, + states_schedule, fail_to_comply + ) -> Tuple[dict, dict]: + grid_count = grid_info['count'] + full_direct = [] + full_thresh = [] + full_shd_trans_array = [] + for light_path in light_paths: + array = results._get_array(grid_info, light_path, res_type="direct") + array = np.apply_along_axis(filter_array, 1, array, occ_mask) + full_direct.append(array) + full_thresh.append((array >= 1000).sum(axis=0)) + full_shd_trans_array.append(shade_transmittances[light_path][1]) + + # Sum the array element-wise. + # This array is the sum of all direct illuminance without shade + # transmittance. + full_direct_sum = sum(full_direct) + + # Create base list of shading combinations (all set to 1). + # We will replace the 1s later. + combinations = [ + {light_path: 1 for light_path in light_paths} + for i in range(full_direct_sum.shape[1]) + ] + + # Find the percentage of floor area >= 1000 lux. + # This array is the percentage for each hour (axis=0). + direct_pct_above = (full_direct_sum >= 1000).sum(axis=0) / grid_count + + # Find the indices where the percentage of floor area is > 2%. + # This array is the problematic hours. + above_2_indices = np.where(direct_pct_above > 0.02)[0] + + # Use the indices to get the relevant hours. + direct_sum = np.take(full_direct_sum, above_2_indices, axis=1) + + # Use the indices to get the relevant hours. + direct = np.take(full_direct, above_2_indices, axis=2) + + # Use the indices to get the relevant hours. + thresh = np.take(full_thresh, above_2_indices, axis=1) + + # Sort and get indices. Negate the array to get descending order. + # Descending order puts the "highest offender" light path first. + sort_thresh = np.argsort(-thresh, axis=0).transpose() + + _combinations = [] + _combinations.insert( + 0, (np.arange(full_direct_sum.shape[1]), combinations) + ) + + if np.any(above_2_indices): + # There are hours where the percentage of floor area is > 2%. + for idx, lp in enumerate(light_paths): + # Take column. For each iteration it will take the next column + # in descending order, i.e., the "highest offender" is the first + # column. + sort_indices = np.take(sort_thresh, idx, axis=1) + + # Map light path identifiers to indices. + light_path_ids = np.take(light_paths, sort_indices) + + # Map shade transmittance to indices. + shd_trans_array = np.take(full_shd_trans_array, sort_indices) + + # Create combination for the subset. + _subset_combination = [ + {light_path: _shd_trans} for light_path, _shd_trans in + zip(light_path_ids, shd_trans_array) + ] + _combinations.insert(0, (above_2_indices, _subset_combination)) + + # Take the values from each array by indexing. + direct_array = \ + direct[sort_indices, :, range(len(sort_indices))].transpose() + + # Subtract the illuminance values. + direct_sum = direct_sum - (direct_array * (1 - shd_trans_array)) + + # Find the percentage of floor area >= 1000 lux. + direct_pct_above = (direct_sum >= 1000).sum(axis=0) / grid_count + + # Find the indices where the percentage of floor area is > 2%. + above_2_indices = np.where(direct_pct_above > 0.02)[0] + + # Break if there are no hours above 2%. + if not np.any(above_2_indices): + break + + # Update variables for the next iteration. + direct_sum = np.take(direct_sum, above_2_indices, axis=1) + direct = np.take(direct, above_2_indices, axis=2) + thresh = np.take(thresh, above_2_indices, axis=1) + sort_thresh = np.take(sort_thresh, above_2_indices, axis=0) + + if np.any(above_2_indices): + # There are hours not complying with the 2% rule. + previous_indices = [] + previous_combination = [] + grid_comply = [] + # Merge the combinations from the iterations of the subsets. + for i, subset in enumerate(_combinations): + if i == 0: + previous_indices = subset[0] + else: + _indices = subset[0] + grid_comply = [] + for _pr_idx in previous_indices: + grid_comply.append(_indices[_pr_idx]) + previous_indices = grid_comply + # Convert indices to sun up hours indices. + filter_indices = np.where(occ_mask.astype(bool))[0] + grid_comply = [filter_indices[_gc] for _gc in grid_comply] + grid_comply = np.array(results.sun_up_hours)[grid_comply] + fail_to_comply[grid_info['name']] = \ + [int(hoy) for hoy in grid_comply] + + previous_indices = None + previous_combination = None + # Merge the combinations from the iterations of the subsets. + for i, subset in enumerate(_combinations): + if i == 0: + previous_indices, previous_combination = subset + else: + _indices, _combination = subset + for _pr_idx, _pr_comb in \ + zip(previous_indices, previous_combination): + for light_path, _shd_trans in _pr_comb.items(): + _combination[_pr_idx][light_path] = _shd_trans + previous_indices = _indices + previous_combination = _combination + + combinations = _combination + + # Merge the combinations of dicts. + for combination in combinations: + for light_path, shd_trans in combination.items(): + if light_path != "__static_apertures__": + states_schedule[light_path].append(shd_trans) + + return states_schedule, fail_to_comply
+ + + +
+[docs] +def states_schedule_descending( + results: AnnualDaylight, grid_info, light_paths, occ_mask, + states_schedule, fail_to_comply + ) -> Tuple[dict, dict]: + grid_count = grid_info['count'] + full_direct = [] + full_thresh = [] + full_direct_blinds = [] + for light_path in light_paths: + array = results._get_array( + grid_info, light_path, state=0, res_type="direct") + array = np.apply_along_axis(filter_array, 1, array, occ_mask) + full_direct.append(array) + full_thresh.append((array >= 1000).sum(axis=0)) + + array = results._get_array( + grid_info, light_path, state=1, res_type="direct") + array = np.apply_along_axis(filter_array, 1, array, occ_mask) + full_direct_blinds.append(array) + + full_direct = np.array(full_direct) + full_direct_blinds = np.array(full_direct_blinds) + full_direct_sum = full_direct.sum(axis=0) + + new_array = full_direct.copy() + + percentage_sensors = (full_direct_sum >= 1000).sum(axis=0) / grid_count + if not np.any(percentage_sensors > 0.02): + combinations = [ + {light_path: 0 for light_path in light_paths} + for i in range(full_direct_sum.shape[1])] + else: + tracking_array = np.zeros( + (new_array.shape[0], new_array.shape[2]), dtype=int) + + percentage_sensors = (full_direct >= 1000).sum(axis=1) / grid_count + + ranking_indices = np.argsort(-percentage_sensors, axis=0) + + for rank in range(ranking_indices.shape[0]): + # Calculate the percentage of sensors with values >= 1000 for the current new_array + summed_array = np.sum(new_array, axis=0) + percentage_sensors_summed = np.sum( + summed_array >= 1000, axis=0) / grid_count + indices_above_2_percent = np.where( + percentage_sensors_summed > 0.02)[0] + + # Exit if there are no more hours exceeding the threshold + if len(indices_above_2_percent) == 0: + break + + # Array indices to use for replacement for these hours + replace_indices = indices_above_2_percent + array_indices = ranking_indices[rank, replace_indices] + + # Use advanced indexing to replace values in new_array for these hours + for hour_idx, array_idx in zip(replace_indices, array_indices): + new_array[array_idx, :, hour_idx] = full_direct_blinds[ + array_idx, :, hour_idx + ] + + # Update the tracking array + tracking_array[array_indices, replace_indices] = 1 + + combinations = [] + for hour in range(new_array.shape[2]): + hour_dict = { + light_paths[i]: tracking_array[i, hour] + for i in range(tracking_array.shape[0])} + combinations.append(hour_dict) + + final_summed_array = np.sum(new_array, axis=0) + final_percentage_sensors_summed = ( + final_summed_array >= 1000).sum( + axis=0) / grid_count + final_indices_above_2_percent = np.where( + final_percentage_sensors_summed > 0.02)[0] + if np.any(final_indices_above_2_percent): + sun_up_hours_indices = np.where(occ_mask == 1)[0][ + final_indices_above_2_percent] + grid_comply = np.array(results.sun_up_hours)[sun_up_hours_indices] + fail_to_comply[grid_info['name']] = [ + int(hoy) for hoy in grid_comply] + + for combination in combinations: + for light_path, value in combination.items(): + if light_path != '__static_apertures__': + states_schedule[light_path].append(value) + + return states_schedule, fail_to_comply
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/metrics.html b/docs/_modules/honeybee_radiance_postprocess/metrics.html new file mode 100644 index 00000000..9e45f3d0 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/metrics.html @@ -0,0 +1,1164 @@ + + + + + + + honeybee_radiance_postprocess.metrics — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.metrics

+"""Functions to calculate various metrics for 1D and 2D NumPy arrays."""
+from typing import Tuple, Union
+import numpy as np
+
+from .util import check_array_dim
+
+
+
+[docs] +def da_array2d( + array: np.ndarray, total_occ: int = None, + threshold: float = 300) -> np.ndarray: + """Calculate daylight autonomy for a 2D NumPy array. + + Args: + array: A 2D NumPy array. + total_occ: Integer indicating the number of occupied hours. If not + given any input the number of occupied hours will be found by the + array shape, i.e., it is assumed that the array is filtered by + occupied hours. + threshold: Threshold value for daylight autonomy. Default: 300. + + Returns: + A 1-dimensional NumPy array with the daylight autonomy for each row in + the input array. + """ + check_array_dim(array, 2) + if total_occ is None: + # set total_occ to number of columns in array + total_occ = array.shape[1] + + da = np.apply_along_axis( + da_array1d, 1, array, total_occ=total_occ, threshold=threshold) + + return da
+ + + +
+[docs] +def da_array1d( + array: np.ndarray, total_occ: int = None, + threshold: float = 300) -> np.float64: + """Calculate daylight autonomy for a 1D NumPy array. + + Args: + array: A 1D NumPy array. + total_occ: Integer indicating the number of occupied hours. If not given any + input the number of occupied hours will be found by the array shape. + threshold: Threshold value for daylight autonomy. Default: 300. + + Returns: + A NumPy float of the daylight autonomy. + """ + check_array_dim(array, 1) + if total_occ is None: + # set total_occ to number of columns in array + total_occ = array.size + + return np.float64((array >= threshold).sum() / total_occ * 100)
+ + + +
+[docs] +def cda_array2d( + array: np.ndarray, total_occ: int = None, + threshold: float = 300) -> np.ndarray: + """Calculate continuos daylight autonomy for a 2D NumPy array. + + Args: + array: A 2D NumPy array. + total_occ: Integer indicating the number of occupied hours. If not given any + input the number of occupied hours will be found by the array shape. + threshold: Threshold value for continuos daylight autonomy. Default: 300. + + Returns: + A 1-dimensional NumPy array with the continuos daylight autonomy for + each row in the input array. + """ + check_array_dim(array, 2) + if total_occ is None: + # set total_occ to number of columns in array + total_occ = array.shape[1] + + cda = np.apply_along_axis( + cda_array1d, 1, array, total_occ=total_occ, threshold=threshold) + + return cda
+ + + +
+[docs] +def cda_array1d( + array: np.ndarray, total_occ: int = None, + threshold: float = 300) -> np.float64: + """Calculate continuos daylight autonomy for a 1D NumPy array. + + Args: + array: A 1D NumPy array. + total_occ: Integer indicating the number of occupied hours. If not given any + input the number of occupied hours will be found by the array shape. + threshold: Threshold value for continuos daylight autonomy. Default: 300. + + Returns: + A NumPy float of the continuos daylight autonomy. + """ + check_array_dim(array, 1) + if total_occ is None: + # set total_occ to number of columns in array + total_occ = array.size + + return np.float64( + np.where(array >= threshold, 1, array / threshold).sum() / total_occ * 100)
+ + + +
+[docs] +def udi_array2d( + array: np.ndarray, total_occ: int = None, min_t: float = 100, + max_t: float = 3000) -> np.ndarray: + """Calculate useful daylight illuminance for a 2D NumPy array. + + Args: + array: A 2D NumPy array. + total_occ: Integer indicating the number of occupied hours. If not given any + input the number of occupied hours will be found by the array shape. + min_t: Minimum threshold for useful daylight illuminance. Default: 100. + max_t: Maximum threshold for useful daylight illuminance. Default: 3000. + + Returns: + A 1-dimensional NumPy array with the useful daylight illuminance for + each row in the input array. + """ + check_array_dim(array, 2) + if total_occ is None: + # set total_occ to number of columns in array + total_occ = array.shape[1] + + udi = np.apply_along_axis( + udi_array1d, 1, array, total_occ=total_occ, min_t=min_t, max_t=max_t) + + return udi
+ + + +
+[docs] +def udi_array1d( + array: np.ndarray, total_occ: int = None, min_t: float = 100, + max_t: float = 3000) -> np.float64: + """Calculate useful daylight illuminance for a 1D NumPy array. + + Args: + array: A 1D NumPy array. + total_occ: Integer indicating the number of occupied hours. If not given any + input the number of occupied hours will be found by the array shape. + min_t: Minimum threshold for useful daylight illuminance. Default: 100. + max_t: Maximum threshold for useful daylight illuminance. Default: 3000. + + Returns: + A NumPy float of the useful daylight illuminance. + """ + check_array_dim(array, 1) + if total_occ is None: + # set total_occ to number of columns in array + total_occ = array.size + + return np.float64(((array >= min_t) & (array <= max_t)).sum() / total_occ * 100)
+ + + +
+[docs] +def udi_lower_array2d( + array: np.ndarray, total_occ: int = None, min_t: float = 100, + sun_down_occ_hours: int = 0) -> np.ndarray: + """Calculate lower than useful daylight illuminance for a 2D NumPy array. + + Args: + array: A 2D NumPy array. + total_occ: Integer indicating the number of occupied hours. If not given any + input the number of occupied hours will be found by the array shape. + min_t: Minimum threshold for useful daylight illuminance. Default: 100. + sun_down_occ_hours: Number of occupied hours where the sun is down. + + Returns: + A 1-dimensional NumPy array with the lower than useful daylight + illuminance for each row in the input array. + """ + check_array_dim(array, 2) + if total_occ is None: + # set total_occ to number of columns in array + total_occ = array.shape[1] + + udi = np.apply_along_axis( + udi_lower_array1d, 1, array, total_occ=total_occ, min_t=min_t, + sun_down_occ_hours=sun_down_occ_hours) + + return udi
+ + + +
+[docs] +def udi_lower_array1d( + array: np.ndarray, total_occ: int = None, min_t: float = 100, + sun_down_occ_hours: int = 0) -> np.float64: + """Calculate lower than useful daylight illuminance for a 1D NumPy array. + + Args: + array: A 1D NumPy array. + total_occ: Integer indicating the number of occupied hours. If not given any + input the number of occupied hours will be found by the array shape. + min_t: Minimum threshold for useful daylight illuminance. Default: 100. + sun_down_occ_hours: Number of occupied hours where the sun is down. + + Returns: + A NumPy float of the lower than useful daylight illuminance. + """ + check_array_dim(array, 1) + if total_occ is None: + # set total_occ to number of columns in array + total_occ = array.size + + if min_t == 0: + return np.float64(0) + + return np.float64(((array < min_t).sum() + sun_down_occ_hours) / total_occ * 100)
+ + + +
+[docs] +def udi_upper_array2d( + array: np.ndarray, total_occ: int = None, + max_t: float = 3000) -> np.ndarray: + """Calculate higher than useful daylight illuminance for a 2D NumPy array. + + Args: + array: A 2D NumPy array. + total_occ: Integer indicating the number of occupied hours. If not given any + input the number of occupied hours will be found by the array shape. + max_t: Maximum threshold for useful daylight illuminance. Default: 3000. + + Returns: + A 1-dimensional NumPy array with the higher than useful daylight + illuminance for each row in the input array. + """ + check_array_dim(array, 2) + if total_occ is None: + # set total_occ to number of columns in array + total_occ = array.shape[1] + + udi = np.apply_along_axis( + udi_upper_array1d, 1, array, total_occ=total_occ, max_t=max_t) + + return udi
+ + + +
+[docs] +def udi_upper_array1d( + array: np.ndarray, total_occ: int = None, + max_t: float = 3000) -> np.float64: + """Calculate higher than useful daylight illuminance for a 1D NumPy array. + + Args: + array: A 1D NumPy array. + total_occ: Integer indicating the number of occupied hours. If not given any + input the number of occupied hours will be found by the array shape. + max_t: Maximum threshold for higher than useful daylight illuminance. + Default: 3000. + + Returns: + A NumPy float of the higher than useful daylight illuminance. + """ + check_array_dim(array, 1) + if total_occ is None: + # set total_occ to number of columns in array + total_occ = array.size + + return np.float64((array > max_t).sum() / total_occ * 100)
+ + + +
+[docs] +def sda_array2d( + array: np.ndarray, target_time: float = 50, threshold: float = 300, + total_occ: int = None) -> np.ndarray: + """Calculate spatial daylight autonomy for a 2D NumPy array. + + Args: + array: A 2D NumPy array. + target_time: A minimum threshold of occupied time (eg. 50% of the + time), above which a given sensor passes and contributes to the + spatial daylight autonomy. Defaults to 50. + threshold: Threshold value for daylight autonomy. Default: 300. + total_occ: Integer indicating the number of occupied hours. If not + given any input the number of occupied hours will be found by the + array shape, i.e., it is assumed that the array is filtered by + occupied hours. + + Returns: + A NumPy float of the sDA as a percentage (decimal) + """ + da = da_array2d(array, total_occ=total_occ, threshold=threshold) + sda = (da >= target_time).mean() + + return sda
+ + + +
+[docs] +def ase_array2d( + array: np.ndarray, occ_hours: int = 250, + direct_threshold: float = 1000) -> Tuple[np.ndarray, np.ndarray]: + """Calculate annual sunlight exposure for a 2D NumPy array. + + Args: + array: A 2D NumPy array. + occ_hours: The number of occupied hours that cannot receive more than + the direct_threshold. Defaults to 250. + direct_threshold: The threshold that determines if a sensor is overlit. + Defaults to 1000. + + Returns: + A NumPy float of the ASE as a percentage (decimal). + """ + check_array_dim(array, 2) + h_above = (array > direct_threshold).sum(axis=1) + ase = (h_above > occ_hours).sum() / array.shape[0] * 100 + + return ase, h_above
+ + + +
+[docs] +def average_values_array2d( + array: np.ndarray, full_length: int = 8760) -> np.ndarray: + """Calculate average values for a 2D NumPy array. + + Args: + array: A 2D NumPy array. + full_length: Integer to use as divisor. + + Returns: + A 1-dimensional NumPy array with the average value for each row in the + input array. + """ + check_array_dim(array, 2) + + avg_values = array.sum(axis=1) / full_length + + return avg_values
+ + + +
+[docs] +def average_values_array1d( + array: np.ndarray, full_length: int = 8760) -> np.float64: + """Calculate average value for a 1D NumPy array. + + Args: + array: A 1D NumPy array. + full_length: Integer to use as divisor. + + Returns: + A NumPy float of the average value. + """ + check_array_dim(array, 1) + + return array.sum() / full_length
+ + + +
+[docs] +def cumulative_values_array2d( + array: np.ndarray, timestep: int = 1, t_step_multiplier: float = 1 + ) -> np.ndarray: + """Calculate cumulative values for a 2D NumPy array. + + Args: + array: A 2D NumPy array. + timestep: Integer for the timestep of the analysis. + t_step_multiplier: A value that will be multiplied with the timestep. + + Returns: + A 1-dimensional NumPy array with the cumulative value for each row in + the input array. + """ + check_array_dim(array, 2) + + cumulative_values = array.sum(axis=1) / (timestep * t_step_multiplier) + + return cumulative_values
+ + + +
+[docs] +def cumulative_values_array1d( + array: np.ndarray, timestep: int = 1, t_step_multiplier: float = 1 + ) -> np.float64: + """Calculate daylight autonomy for a 1D NumPy array. + + Args: + array: A 1D NumPy array. + timestep: Integer for the timestep of the analysis. + t_step_multiplier: A value that will be multiplied with the timestep. + + Returns: + A NumPy float of the cumulative value. + """ + check_array_dim(array, 1) + + return array.sum() / (timestep * t_step_multiplier)
+ + + +
+[docs] +def peak_values_array2d( + array: np.ndarray, coincident: bool = False + ) -> Tuple[np.ndarray, Union[int, None]]: + """Calculate peak values for a 2D NumPy array. + + Args: + array: A 2D NumPy array. + coincident: Boolean to indicate whether output values represent the + peak value for each sensor throughout the entire analysis (False) + or they represent the highest overall value across each sensor grid + at a particular timestep (True). + + Returns: + A 1-dimensional NumPy array with the peak value for each row in the + input array, and the index of the maximum value representing the + timestep in the array with the largest value. + """ + check_array_dim(array, 2) + + max_i = None + if coincident: + array_summed = array.sum(axis=0) + if np.any(array_summed): + max_i = np.argmax(array_summed) + peak_values = array[:, max_i] + else: + peak_values = np.zeros(array.shape[0]) + else: + if np.any(array): + peak_values = np.amax(array, axis=1) + else: + peak_values = np.zeros(array.shape[0]) + + return peak_values, max_i
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/reader.html b/docs/_modules/honeybee_radiance_postprocess/reader.html new file mode 100644 index 00000000..014674b4 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/reader.html @@ -0,0 +1,780 @@ + + + + + + + honeybee_radiance_postprocess.reader — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.reader

+"""Post-processing reader functions."""
+import numpy as np
+
+from .util import binary_mtx_dimension
+
+
+
+[docs] +def binary_to_array( + binary_file: str, nrows: int = None, ncols: int = None, + ncomp: int = None, fmt=None, line_count: int = 0) -> np.ndarray: + """Read a Radiance binary file as a NumPy array. + + Args: + binary_file: Path to binary Radiance file. + nrows: Number of rows in the Radiance file. + ncols: Number of columns in the Radiance file. + ncomp: Number of components of each element in the Radiance file. + fmt: Format of the Radiance file. Can be either "ascii", "float", or "double. + line_count: Number of lines to skip in the input file. Usually used to + skip the header. + + Returns: + A NumPy array. + """ + if (nrows or ncols or ncomp or fmt) is None: + # get nrows, ncols and header line count + nrows, ncols, ncomp, line_count, fmt = binary_mtx_dimension(binary_file) + with open(binary_file, 'rb') as reader: + # skip first n lines from reader + for i in range(line_count): + reader.readline() + + if fmt == 'ascii': + array = np.loadtxt(reader, dtype=np.float32) + elif fmt == 'float': + array = np.fromfile(reader, dtype=np.float32) + elif fmt == 'double': + array = np.fromfile(reader, dtype=np.float64) + + if ncomp != 1: + array = array.reshape(nrows, ncols, ncomp) + else: + array = array.reshape(nrows, ncols) + + return array
+ + + +
+[docs] +def ascii_to_array( + ascii_file: str, nrows: int = None, ncols: int = None, + ncomp: int = None, line_count: int = 0) -> np.ndarray: + """Read a Radiance ascii file as a NumPy array. + + Args: + ascii_file: Path to ascii Radiance file. + nrows: Number of rows in the Radiance file. + ncols: Number of columns in the Radiance file. + ncomp: Number of components of each element in the Radiance file. + line_count: Number of lines to skip in the input file. Usually used to + skip the header. + + Returns: + A NumPy array. + """ + with open(ascii_file, 'r') as reader: + if (nrows or ncols or ncomp) is None: + # get nrows, ncols and header line count + # we can reuse binary_mtx_dimension though the input file is ascii + nrows, ncols, ncomp, line_count, fmt = binary_mtx_dimension(ascii_file) + + array = np.loadtxt(reader, dtype=np.float32, skiprows=line_count) + if ncomp != 1: + array = array.reshape(nrows, ncols, ncomp) + else: + array = array.reshape(nrows, ncols) + + return array
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/results/annual_daylight.html b/docs/_modules/honeybee_radiance_postprocess/results/annual_daylight.html new file mode 100644 index 00000000..8a581634 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/results/annual_daylight.html @@ -0,0 +1,1498 @@ + + + + + + + honeybee_radiance_postprocess.results.annual_daylight — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.results.annual_daylight

+import json
+from pathlib import Path
+from typing import Tuple, List
+import numpy as np
+import itertools
+from collections import defaultdict
+
+from ladybug.analysisperiod import AnalysisPeriod
+from ladybug.datacollection import HourlyContinuousCollection
+from ladybug.datatype.illuminance import Illuminance
+from ladybug.datatype.fraction import Fraction
+from ladybug.header import Header
+
+from ..annual import occupancy_schedule_8_to_6
+from ..metrics import da_array2d, cda_array2d, udi_array2d, udi_lower_array2d, \
+    udi_upper_array2d, ase_array2d
+from ..util import filter_array
+from ..annualdaylight import _annual_daylight_vis_metadata
+from ..electriclight import array_to_dimming_fraction
+from .. import type_hints
+from ..dynamic import DynamicSchedule, ApertureGroupSchedule
+from .results import Results
+
+
+
+[docs] +class AnnualDaylight(Results): + """Annual Daylight Results class. + + Args: + folder: Path to results folder. + schedule: 8760 values as a list. Values must be either 0 or 1. Values of 1 + indicates occupied hours. If no schedule is provided a default schedule + will be used. (Default: None). + load_arrays: Set to True to load all NumPy arrays. If False the arrays will be + loaded only once they are needed. In both cases the loaded array(s) will be + stored in a dictionary under the arrays property. (Default: False). + + Properties: + * schedule + * occ_pattern + * total_occ + * sun_down_occ_hours + * occ_mask + * arrays + * valid_states + * datatype + """ + def __init__(self, folder, schedule: list = None, load_arrays: bool = False): + """Initialize Results.""" + Results.__init__(self, folder, datatype=Illuminance('Illuminance'), + schedule=schedule, unit='lux', load_arrays=load_arrays) + +
+[docs] + def daylight_autonomy( + self, threshold: float = 300, states: DynamicSchedule = None, + grids_filter: str = '*') -> type_hints.annual_metric: + """Calculate daylight autonomy. + + Args: + threshold: Threshold value for daylight autonomy. Defaults to 300. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the daylight autonomy and grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + + da = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type='total') + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=self.occ_mask) + results = da_array2d( + array_filter, total_occ=self.total_occ, threshold=threshold) + else: + results = np.zeros(grid_info['count']) + da.append(results) + + return da, grids_info
+ + +
+[docs] + def continuous_daylight_autonomy( + self, threshold: float = 300, states: DynamicSchedule = None, + grids_filter: str = '*') -> type_hints.annual_metric: + """Calculate continuous daylight autonomy. + + Args: + threshold: Threshold value for daylight autonomy. Defaults to 300. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the continuous daylight autonomy and grid + information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + + cda = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type='total') + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=self.occ_mask) + results = cda_array2d( + array_filter, total_occ=self.total_occ, threshold=threshold) + else: + results = np.zeros(grid_info['count']) + cda.append(results) + + return cda, grids_info
+ + +
+[docs] + def useful_daylight_illuminance( + self, min_t: float = 100, max_t: float = 3000, states: DynamicSchedule = None, + grids_filter: str = '*') -> type_hints.annual_metric: + """Calculate useful daylight illuminance. + + Args: + min_t: Minimum threshold for useful daylight illuminance. Defaults to 100. + max_t: Maximum threshold for useful daylight illuminance. Defaults to 3000. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the useful daylight illuminance and grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + + udi = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type='total') + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=self.occ_mask) + results = udi_array2d( + array_filter, total_occ=self.total_occ, min_t=min_t, max_t=max_t) + else: + results = np.zeros(grid_info['count']) + udi.append(results) + + return udi, grids_info
+ + +
+[docs] + def useful_daylight_illuminance_lower( + self, min_t: float = 100, states: DynamicSchedule = None, + grids_filter: str = '*') -> type_hints.annual_metric: + """Calculate lower than useful daylight illuminance. + + Args: + min_t: Minimum threshold for useful daylight illuminance. Defaults to 100. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the lower than useful daylight illuminance and + grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + sun_down_occ_hours = self.sun_down_occ_hours + + udi_lower = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type='total') + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=self.occ_mask) + results = udi_lower_array2d( + array_filter, total_occ=self.total_occ, + min_t=min_t, sun_down_occ_hours=sun_down_occ_hours) + else: + results = np.zeros(grid_info['count']) + udi_lower.append(results) + + return udi_lower, grids_info
+ + +
+[docs] + def useful_daylight_illuminance_upper( + self, max_t: float = 3000, states: DynamicSchedule = None, + grids_filter: str = '*') -> type_hints.annual_metric: + """Calculate higher than useful daylight illuminance. + + Args: + max_t: Maximum threshold for useful daylight illuminance. Defaults to 3000. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the higher than useful daylight illuminance and + grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + + udi_upper = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type='total') + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=self.occ_mask) + results = udi_upper_array2d( + array_filter, total_occ=self.total_occ, max_t=max_t) + else: + results = np.zeros(grid_info['count']) + udi_upper.append(results) + + return udi_upper, grids_info
+ + +
+[docs] + def annual_metrics( + self, threshold: float = 300, min_t: float = 100, + max_t: float = 3000, states: DynamicSchedule = None, + grids_filter: str = '*') -> type_hints.annual_daylight_metrics: + """Calculate multiple annual daylight metrics. + + This method will calculate the following metrics: + * Daylight autonomy + * Continuous daylight autonomy + * Useful daylight illuminance + * Lower than useful daylight illuminance + * Higher than useful daylight illuminance + + Args: + threshold: Threshold value for daylight autonomy. Defaults to 300. + min_t: Minimum threshold for useful daylight illuminance. Defaults to 100. + max_t: Maximum threshold for useful daylight illuminance. Defaults to 3000. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the five annual daylight metrics and grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + sun_down_occ_hours = self.sun_down_occ_hours + + da = [] + cda = [] + udi = [] + udi_lower = [] + udi_upper = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type='total') + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=self.occ_mask) + da_results = da_array2d( + array_filter, total_occ=self.total_occ, threshold=threshold) + cda_results = cda_array2d( + array_filter, total_occ=self.total_occ, threshold=threshold) + udi_results = udi_array2d( + array_filter, total_occ=self.total_occ, min_t=min_t, max_t=max_t) + udi_lower_results = udi_lower_array2d( + array_filter, total_occ=self.total_occ, min_t=min_t, + sun_down_occ_hours=sun_down_occ_hours) + udi_upper_results = udi_upper_array2d( + array_filter, total_occ=self.total_occ, max_t=max_t) + else: + da_results = cda_results = udi_results = udi_lower_results = \ + udi_upper_results = np.zeros(grid_info['count']) + da.append(da_results) + cda.append(cda_results) + udi.append(udi_results) + udi_lower.append(udi_lower_results) + udi_upper.append(udi_upper_results) + + return da, cda, udi, udi_lower, udi_upper, grids_info
+ + +
+[docs] + def annual_metrics_to_folder( + self, target_folder: str, threshold: float = 300, + min_t: float = 100, max_t: float = 3000, states: DynamicSchedule = None, + grids_filter: str = '*'): + """Calculate and write multiple annual daylight metrics to a folder. + + This method will calculate the following metrics: + * Daylight autonomy + * Continuous daylight autonomy + * Useful daylight illuminance + * Lower than useful daylight illuminance + * Higher than useful daylight illuminance + + Args: + target_folder: Folder path to write annual metrics in. Usually this + folder is called 'metrics'. + threshold: Threshold value for daylight autonomy. Defaults to 300. + min_t: Minimum threshold for useful daylight illuminance. Defaults to 100. + max_t: Maximum threshold for useful daylight illuminance. Defaults to 3000. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + da, cda, udi, udi_lower, udi_upper, grids_info = self.annual_metrics( + threshold=threshold, min_t=min_t, max_t=max_t, states=states, + grids_filter=grids_filter) + + pattern = { + 'da': da, 'cda': cda, 'udi_lower': udi_lower, 'udi': udi, + 'udi_upper': udi_upper + } + for metric, data in pattern.items(): + metric_folder = folder.joinpath(metric) + extension = metric.split('_')[0] + for count, grid_info in enumerate(grids_info): + d = data[count] + full_id = grid_info['full_id'] + output_file = metric_folder.joinpath(f'{full_id}.{extension}') + output_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(output_file, d, fmt='%.2f') + + for metric in pattern.keys(): + info_file = folder.joinpath(metric, 'grids_info.json') + info_file.write_text(json.dumps(grids_info)) + + metric_info_dict = _annual_daylight_vis_metadata() + for metric, data in metric_info_dict.items(): + vis_metadata_file = folder.joinpath(metric, 'vis_metadata.json') + vis_metadata_file.write_text(json.dumps(data, indent=4))
+ + +
+[docs] + def spatial_daylight_autonomy( + self, threshold: float = 300, target_time: float = 50, + states: DynamicSchedule = None, grids_filter: str = '*' + ) -> type_hints.spatial_daylight_autonomy: + """Calculate spatial daylight autonomy. + + Note: This component will only output a LEED compliant sDA if you've + run the simulation with blinds and blinds schedules as per the + IES-LM-83-12. Use the states option to calculate a LEED compliant sDA. + + Args: + threshold: Threshold value for daylight autonomy. Defaults to 300. + target_time: A minimum threshold of occupied time (eg. 50% of the + time), above which a given sensor passes and contributes to the + spatial daylight autonomy. Defaults to 50. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the spatial daylight autonomy and grid + information. + """ + da, grids_info = self.daylight_autonomy( + threshold=threshold, states=states, grids_filter=grids_filter) + + sda = [] + for array in da: + sda.append((array >= target_time).mean()) + + return sda, grids_info
+ + +
+[docs] + def annual_sunlight_exposure( + self, direct_threshold: float = 1000, occ_hours: int = 250, + states: DynamicSchedule = None, grids_filter: str = '*' + ) -> type_hints.annual_sunlight_exposure: + """Calculate annual sunlight exposure. + + Args: + direct_threshold: The threshold that determines if a sensor is + overlit. Defaults to 1000. + occ_hours: The number of occupied hours that cannot receive more + than the direct_threshold. Defaults to 250. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the annual sunlight exposure, the number of + hours that exceeds the direct threshold for each sensor, and + grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + + ase = [] + hours_above = [] + for grid_info in grids_info: + array = self._array_from_states( + grid_info, states=states, res_type='direct') + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=self.occ_mask) + results, h_above = ase_array2d( + array_filter, occ_hours=occ_hours, + direct_threshold=direct_threshold) + else: + results = np.float64(0) + h_above = np.zeros(grid_info['count']) + ase.append(results) + hours_above.append(h_above) + + return ase, hours_above, grids_info
+ + +
+[docs] + def annual_sunlight_exposure_to_folder( + self, target_folder: str, direct_threshold: float = 1000, + occ_hours: int = 250, states: DynamicSchedule = None, + grids_filter: str = '*'): + """Calculate and write annual sunlight exposure to a folder. + + Args: + direct_threshold: The threshold that determines if a sensor is + overlit. Defaults to 1000. + occ_hours: The number of occupied hours that cannot receive more + than the direct_threshold. Defaults to 250. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + ase, hours_above, grids_info = self.annual_sunlight_exposure( + direct_threshold=direct_threshold, occ_hours=occ_hours, + states=states, grids_filter=grids_filter + ) + + pattern = {'ase': ase, 'hours_above': hours_above} + for metric, data in pattern.items(): + metric_folder = folder.joinpath(metric) + if metric == 'hours_above': + extension = 'res' + else: + extension = 'ase' + for count, grid_info in enumerate(grids_info): + d = data[count] + full_id = grid_info['full_id'] + output_file = metric_folder.joinpath(f'{full_id}.{extension}') + output_file.parent.mkdir(parents=True, exist_ok=True) + if metric == 'hours_above': + np.savetxt(output_file, d, fmt='%i') + elif metric == 'ase': + output_file.write_text('%.2f' % d) + + for metric in pattern.keys(): + info_file = folder.joinpath(metric, 'grids_info.json') + info_file.write_text(json.dumps(grids_info))
+ + +
+[docs] + def daylight_control_schedules( + self, states: DynamicSchedule = None, grids_filter: str = '*', + base_schedule: list = None, ill_setpoint: float = 300, + min_power_in: float = 0.3, min_light_out: float = 0.2, + off_at_min: bool = False + ) -> Tuple[List[np.ndarray], List[dict]]: + """Generate electric lighting schedules from annual daylight results. + + Such controls will dim the lights according to whether the illuminance values + at the sensor locations are at a target illuminance setpoint. The results can be + used to account for daylight controls in energy simulations. + + This function will generate one schedule per sensor grid in the simulation. Each + grid should have sensors at the locations in space where daylight dimming sensors + are located. Grids with one, two, or more sensors can be used to model setups + where fractions of each room are controlled by different sensors. If the sensor + grids are distributed over the entire floor of the rooms, the resulting schedules + will be idealized, where light dimming has been optimized to supply the minimum + illuminance setpoint everywhere in the room. + + Args: + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + base_schedule: A list of 8760 fractional values for the lighting schedule + representing the usage of lights without any daylight controls. The + values of this schedule will be multiplied by the hourly dimming + fraction to yield the output lighting schedules. If None, a schedule + from 9AM to 5PM on weekdays will be used. (Default: None). + ill_setpoint: A number for the illuminance setpoint in lux beyond which + electric lights are dimmed if there is sufficient daylight. + Some common setpoints are listed below. (Default: 300 lux). + + * 50 lux - Corridors and hallways. + * 150 lux - Computer work spaces (screens provide illumination). + * 300 lux - Paper work spaces (reading from surfaces that need illumination). + * 500 lux - Retail spaces or museums illuminating merchandise/artifacts. + * 1000 lux - Operating rooms and workshops where light is needed for safety. + + min_power_in: A number between 0 and 1 for the the lowest power the lighting + system can dim down to, expressed as a fraction of maximum + input power. (Default: 0.3). + min_light_out: A number between 0 and 1 the lowest lighting output the lighting + system can dim down to, expressed as a fraction of maximum light + output. Note that setting this to 1 means lights aren't dimmed at + all until the illuminance setpoint is reached. This can be used to + approximate manual light-switching behavior when used in conjunction + with the off_at_min input below. (Default: 0.2). + off_at_min: Boolean to note whether lights should switch off completely when + they get to the minimum power input. (Default: False). + + Returns: + A tuple with two values. + + - schedules: A list of lists where each sub-list represents an electric + lighting dimming schedule for a sensor grid. + + - grids_info: A list of grid information. + """ + # process the base schedule input into a list of values + if base_schedule is None: + base_schedule = occupancy_schedule_8_to_6(timestep=self.timestep) + base_schedule = np.array(base_schedule) + + grids_info = self._filter_grids(grids_filter=grids_filter) + sun_up_hours = [int(h) for h in self.sun_up_hours] + + dim_fracts = [] + for grid_info in grids_info: + array = self._array_from_states( + grid_info, states=states, res_type='total') + if np.any(array): + fract_list = array_to_dimming_fraction( + array, sun_up_hours, ill_setpoint, min_power_in, + min_light_out, off_at_min + ) + else: + fract_list = np.ones(8760) + dim_fracts.append(fract_list) + + schedules = [] + for grid_info, dim_fract in zip(grids_info, dim_fracts): + sch_vals = base_schedule * dim_fract + schedules.append(sch_vals) + + return schedules, grids_info
+ + +
+[docs] + def daylight_control_schedules_to_folder( + self, target_folder: str, states: DynamicSchedule = None, + grids_filter: str = '*', base_schedule: list = None, + ill_setpoint: float = 300, min_power_in: float = 0.3, + min_light_out: float = 0.2, off_at_min: bool = False): + """Generate electric lighting schedules from annual daylight results and + write the schedules to a folder. + + Such controls will dim the lights according to whether the illuminance values + at the sensor locations are at a target illuminance setpoint. The results can be + used to account for daylight controls in energy simulations. + + This function will generate one schedule per sensor grid in the simulation. Each + grid should have sensors at the locations in space where daylight dimming sensors + are located. Grids with one, two, or more sensors can be used to model setups + where fractions of each room are controlled by different sensors. If the sensor + grids are distributed over the entire floor of the rooms, the resulting schedules + will be idealized, where light dimming has been optimized to supply the minimum + illuminance setpoint everywhere in the room. + + Args: + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + base_schedule: A list of 8760 fractional values for the lighting schedule + representing the usage of lights without any daylight controls. The + values of this schedule will be multiplied by the hourly dimming + fraction to yield the output lighting schedules. If None, a schedule + from 9AM to 5PM on weekdays will be used. (Default: None). + ill_setpoint: A number for the illuminance setpoint in lux beyond which + electric lights are dimmed if there is sufficient daylight. + Some common setpoints are listed below. (Default: 300 lux). + + * 50 lux - Corridors and hallways. + * 150 lux - Computer work spaces (screens provide illumination). + * 300 lux - Paper work spaces (reading from surfaces that need illumination). + * 500 lux - Retail spaces or museums illuminating merchandise/artifacts. + * 1000 lux - Operating rooms and workshops where light is needed for safety. + + min_power_in: A number between 0 and 1 for the the lowest power the lighting + system can dim down to, expressed as a fraction of maximum + input power. (Default: 0.3). + min_light_out: A number between 0 and 1 the lowest lighting output the lighting + system can dim down to, expressed as a fraction of maximum light + output. Note that setting this to 1 means lights aren't dimmed at + all until the illuminance setpoint is reached. This can be used to + approximate manual light-switching behavior when used in conjunction + with the off_at_min input below. (Default: 0.2). + off_at_min: Boolean to note whether lights should switch off completely when + they get to the minimum power input. (Default: False). + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + schedules, grids_info = self.daylight_control_schedules( + states=states, grids_filter=grids_filter, + base_schedule=base_schedule, ill_setpoint=ill_setpoint, + min_power_in=min_power_in, min_light_out=min_light_out, + off_at_min=off_at_min) + + schedule_folder = folder.joinpath('control_schedules') + + for count, grid_info in enumerate(grids_info): + d = schedules[count] + full_id = grid_info['full_id'] + output_file = schedule_folder.joinpath(f'{full_id}.txt') + output_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(output_file, d, fmt='%.2f') + + info_file = schedule_folder.joinpath('grids_info.json') + info_file.write_text(json.dumps(grids_info))
+ + +
+[docs] + def annual_uniformity_ratio( + self, threshold: float = 0.5, states: DynamicSchedule = None, + grids_filter: str = '*') -> type_hints.annual_uniformity_ratio: + """Calculate annual uniformity ratio. + + Args: + threshold: A threshold for the uniformity ratio. Defaults to 0.5. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the annual uniformity ratio, annual + data collections, and grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + analysis_period = AnalysisPeriod(timestep=self.timestep) + + data_collections = [] + annual_uniformity_ratio = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type='total') + if np.any(array): + su_min_array = array.min(axis=0) + su_mean_array = array.mean(axis=0) + su_uniformity_ratio = su_min_array / su_mean_array + + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=self.occ_mask) + min_array = array_filter.min(axis=0) + mean_array = array_filter.mean(axis=0) + uniformity_ratio = min_array / mean_array + annual_uniformity_ratio.append( + np.float64( + (uniformity_ratio >= threshold).sum() / self.total_occ * 100 + ) + ) + else: + su_uniformity_ratio = np.zeros(len(self.sun_up_hours)) + annual_uniformity_ratio.append(np.float64(0)) + + annual_array = \ + self.values_to_annual( + self.sun_up_hours, su_uniformity_ratio, self.timestep) + header = Header(Fraction(), '%', analysis_period) + header.metadata['sensor grid'] = grid_info['full_id'] + data_collections.append( + HourlyContinuousCollection(header, annual_array.tolist())) + + return annual_uniformity_ratio, data_collections, grids_info
+ + +
+[docs] + def annual_uniformity_ratio_to_folder( + self, target_folder: str, threshold: float = 0.5, + states: DynamicSchedule = None, grids_filter: str = '*' + ): + """Calculate annual uniformity ratio and write it to a folder. + + Args: + target_folder: Folder path to write annual uniformity ratio in. + threshold: A threshold for the uniformity ratio. Defaults to 0.5. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the daylight autonomy and grid information. + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + annual_uniformity_ratio, data_collections, grids_info = \ + self.annual_uniformity_ratio(threshold=threshold, states=states, + grids_filter=grids_filter) + + datacollection_folder = folder.joinpath('datacollections') + uniformity_ratio_folder = folder.joinpath('uniformity_ratio') + + for aur, data_collection, grid_info in \ + zip(annual_uniformity_ratio, data_collections, grids_info): + grid_id = grid_info['full_id'] + data_dict = data_collection.to_dict() + data_file = datacollection_folder.joinpath(f'{grid_id}.json') + data_file.parent.mkdir(parents=True, exist_ok=True) + data_file.write_text(json.dumps(data_dict)) + + aur_file = uniformity_ratio_folder.joinpath(f'{grid_id}.ur') + aur_file.parent.mkdir(parents=True, exist_ok=True) + aur_file.write_text(str(round(aur, 2))) + + info_file = uniformity_ratio_folder.joinpath('grids_info.json') + info_file.write_text(json.dumps(grids_info))
+ + +
+[docs] + def dynamic_schedule_from_sensor_maximum( + self, sensor_index: dict, grids_filter: str = '*', + maximum: float = 3000, res_type: str = 'total') -> DynamicSchedule: + """Calculate a DynamicSchedule from a sensor and a maximum allowed + illuminance. + + Args: + sensor_index: A dictionary with grids as keys and a list of sensor + indices as values. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + maximum: A float value of the maximum illuminance allowed for the + sensor. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + DynamicSchedule object. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + + aperture_group_schedules = [] + for grid_info in grids_info: + control_sensor = sensor_index.get(grid_info['full_id'], None) + if control_sensor is None: + continue + assert len(control_sensor) == 1, ('Expected one control sensor for ' + f'grid {grid_info["name"]}. Received {len(control_sensor)} ' + 'control sensors.') + control_sensor_index = control_sensor[0] + + combinations = self._get_state_combinations(grid_info) + + array_list_combinations = [] + for combination in combinations: + combination_arrays = [] + for light_path, state_index in combination.items(): + array = self._get_array( + grid_info, light_path, state=state_index, res_type=res_type) + sensor_array = array[control_sensor_index,:] + combination_arrays.append(sensor_array) + combination_array = sum(combination_arrays) + array_list_combinations.append(combination_array) + array_combinations = np.array(array_list_combinations) + array_combinations[array_combinations > maximum] = -np.inf + max_indices = array_combinations.argmax(axis=0) + combinations = [combinations[idx] for idx in max_indices] + + states_schedule = defaultdict(list) + for combination in combinations: + for light_path, state_index in combination.items(): + if light_path != '__static_apertures__': + states_schedule[light_path].append(state_index) + + # map states to 8760 values + for light_path, state_indices in states_schedule.items(): + mapped_states = self.values_to_annual( + self.sun_up_hours, state_indices, self.timestep) + mapped_states = mapped_states.astype(int) + aperture_group_schedules.append( + ApertureGroupSchedule(light_path, mapped_states.tolist())) + + dyn_sch = DynamicSchedule.from_group_schedules(aperture_group_schedules) + + return dyn_sch
+
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/results/annual_irradiance.html b/docs/_modules/honeybee_radiance_postprocess/results/annual_irradiance.html new file mode 100644 index 00000000..bad65a45 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/results/annual_irradiance.html @@ -0,0 +1,903 @@ + + + + + + + honeybee_radiance_postprocess.results.annual_irradiance — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.results.annual_irradiance

+import json
+from pathlib import Path
+import numpy as np
+
+from ladybug.datatype.energyflux import EnergyFlux
+
+from ..metrics import (average_values_array2d, cumulative_values_array2d,
+    peak_values_array2d)
+from ..util import filter_array, hoys_mask
+from ..annualirradiance import _annual_irradiance_vis_metadata
+from .. import type_hints
+from ..dynamic import DynamicSchedule
+from .results import Results
+
+
+
+[docs] +class AnnualIrradiance(Results): + """Annual Daylight Results class. + + Args: + folder: Path to results folder. + schedule: 8760 values as a list. Values must be either 0 or 1. Values of 1 + indicates occupied hours. If no schedule is provided a default schedule + will be used. (Default: None). + load_arrays: Set to True to load all NumPy arrays. If False the arrays will be + loaded only once they are needed. In both cases the loaded array(s) will be + stored in a dictionary under the arrays property. (Default: False). + + Properties: + * schedule + * occ_pattern + * total_occ + * sun_down_occ_hours + * occ_mask + * arrays + * valid_states + * datatype + """ + def __init__(self, folder, schedule: list = None, load_arrays: bool = False): + """Initialize Results.""" + Results.__init__(self, folder, datatype=EnergyFlux('Irradiance'), + schedule=schedule, unit='W/m2', load_arrays=load_arrays) + +
+[docs] + def cumulative_values( + self, hoys: list = [], states: DynamicSchedule = None, + t_step_multiplier: float = 1000, grids_filter: str = '*', + res_type: str = 'total') -> type_hints.cumulative_values: + """Get cumulative values for each sensor over a given period. + + The hoys input can be used to filter the data for a particular time + period. + + Args: + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + t_step_multiplier: A value that will be multiplied with the timestep. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + Tuple: A tuple with the cumulative value for each sensor and grid + information. + """ + cumulative_values, grids_info = \ + super(AnnualIrradiance, self).cumulative_values( + hoys=hoys, states=states, t_step_multiplier=t_step_multiplier, + grids_filter=grids_filter, res_type=res_type + ) + + return cumulative_values, grids_info
+ + +
+[docs] + def cumulative_values_to_folder( + self, target_folder: str, hoys: list = [], + states: DynamicSchedule = None, t_step_multiplier: float = 1000, + grids_filter: str = '*', res_type: str = 'total'): + """Get cumulative values for each sensor over a given period and write + the values to a folder. + + Args: + target_folder: Folder path to write annual metrics in. Usually this + folder is called 'metrics'. + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + t_step_multiplier: A value that will be multiplied with the timestep. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + """ + super(AnnualIrradiance, self).cumulative_values_to_folder( + target_folder, hoys=hoys, states=states, + t_step_multiplier=t_step_multiplier, grids_filter=grids_filter, + res_type=res_type + )
+ + +
+[docs] + def annual_metrics( + self, hoys: list = [], states: DynamicSchedule = None, + grids_filter: str = '*') -> type_hints.annual_irradiance_metrics: + """Calculate multiple annual irradiance metrics. + + This method will calculate the following metrics: + * Average Irradiance (W/m2) + * Peak Irradiance (W/m2) + * Cumulative Radiation (kWh/m2) + + Args: + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + Tuple: A tuple with the three annual irradiance metrics and grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + mask = hoys_mask(self.sun_up_hours, hoys) + full_length = len(self.study_hours) + + average = [] + peak = [] + cumulative = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type='total') + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=mask) + average_results = average_values_array2d( + array_filter, full_length=full_length) + peak_results, max_i = peak_values_array2d( + array_filter) + cumulative_results = cumulative_values_array2d( + array_filter, self.timestep, 1000) + else: + average_results = peak_results = cumulative_results = \ + np.zeros(grid_info['count']) + average.append(average_results) + peak.append(peak_results) + cumulative.append(cumulative_results) + + return average, peak, cumulative, grids_info
+ + +
+[docs] + def annual_metrics_to_folder( + self, target_folder: str, hoys: list = [], + states: DynamicSchedule = None, grids_filter: str = '*'): + """Calculate and write multiple annual irradiance metrics to a folder. + + This command generates 3 files for each input grid. + * average_irradiance/{grid-name}.res -- Average Irradiance (W/m2) + * peak_irradiance/{grid-name}.res -- Peak Irradiance (W/m2) + * cumulative_radiation/{grid-name}.res -- Cumulative Radiation (kWh/m2) + + Args: + target_folder: Folder path to write annual metrics in. Usually this + folder is called 'metrics'. + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + average, peak, cumulative, grids_info = self.annual_metrics( + hoys=hoys, states=states, grids_filter=grids_filter) + + pattern = { + 'average_irradiance': average, 'peak_irradiance': peak, + 'cumulative_radiation': cumulative, + } + for metric, data in pattern.items(): + metric_folder = folder.joinpath(metric) + for count, grid_info in enumerate(grids_info): + d = data[count] + full_id = grid_info['full_id'] + output_file = metric_folder.joinpath(f'{full_id}.res') + output_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(output_file, d, fmt='%.2f') + + for metric in pattern.keys(): + info_file = folder.joinpath(metric, 'grids_info.json') + info_file.write_text(json.dumps(grids_info)) + + metric_info_dict = _annual_irradiance_vis_metadata() + for metric, data in metric_info_dict.items(): + vis_metadata_file = folder.joinpath(metric, 'vis_metadata.json') + vis_metadata_file.write_text(json.dumps(data, indent=4))
+
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/results/results.html b/docs/_modules/honeybee_radiance_postprocess/results/results.html new file mode 100644 index 00000000..b66cefa5 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/results/results.html @@ -0,0 +1,2121 @@ + + + + + + + honeybee_radiance_postprocess.results.results — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.results.results

+"""Post-processing Results class."""
+import json
+from pathlib import Path
+from itertools import islice, cycle
+from typing import Tuple, Union, List
+import numpy as np
+import itertools
+
+from ladybug.analysisperiod import AnalysisPeriod
+from ladybug.datacollection import HourlyContinuousCollection
+from ladybug.datatype.generic import GenericType
+from ladybug.datatype.base import DataTypeBase
+from ladybug.dt import DateTime
+from ladybug.header import Header
+
+from ..annual import occupancy_schedule_8_to_6
+from ..metrics import (average_values_array2d, cumulative_values_array2d,
+    peak_values_array2d)
+from ..util import filter_array, hoys_mask, check_array_dim, \
+    _filter_grids_by_pattern
+from .. import type_hints
+from ..dynamic import DynamicSchedule, ApertureGroupSchedule
+
+
+class _ResultsFolder(object):
+    """Base class for ResultsFolder.
+
+    This class includes properties that are independent of the results.
+
+    Args:
+        folder: Path to results folder.
+
+    Properties:
+        * folder
+        * grids_info
+        * sun_up_hours
+        * sun_down_hours
+        * light_paths
+        * default_states
+        * grid_states
+        * timestep
+        * study_hours
+
+    """
+    __slots__ = ('_folder', '_grids_info', '_sun_up_hours', '_sun_down_hours',
+                 '_sun_up_hours_mask', '_sun_down_hours_mask', '_datetimes',
+                 '_light_paths', '_default_states', '_grid_states', '_timestep',
+                 '_study_hours')
+
+    def __init__(self, folder: Union[str, Path]):
+        """Initialize ResultsFolder."""
+        self._folder = Path(folder).absolute().as_posix()
+        self._timestep, self._study_hours = self._get_study_info()
+        self.grids_info = self._get_grids_info()
+        self.sun_up_hours = self._get_sun_up_hours()
+        self._sun_up_hours_mask = self._get_sun_up_hours_mask()
+        self._sun_down_hours_mask = self._get_sun_down_hours_mask()
+        self._datetimes = self._get_datetimes()
+        self._light_paths = self._get_light_paths()
+        self._default_states = self._get_default_states()
+        self._grid_states = self._get_grid_states()
+
+    @property
+    def folder(self):
+        """Return full path to results folder as a string."""
+        return self._folder
+
+    @property
+    def grids_info(self):
+        """Return grids information as list of dictionaries for each grid."""
+        return self._grids_info
+
+    @grids_info.setter
+    def grids_info(self, grids_info):
+        assert isinstance(grids_info, list), \
+            f'Grids information must be a list. Got object of type: {type(grids_info)}.'
+        for grid_info in grids_info:
+            assert isinstance(grid_info, dict), \
+                'Object in grids information must be a dictionary. ' \
+                f'Got object of type {type(grid_info)}.'
+            if 'light_path' in grid_info.keys():
+                _grid_info = []
+                for light_path in grid_info['light_path']:
+                    if Path(self.folder, light_path[0]).exists():
+                        _grid_info.append((light_path))
+                grid_info['light_path'] = _grid_info
+                if not grid_info['light_path']:
+                    # if light path is empty
+                    grid_info['light_path'] = [['__static_apertures__']]
+            else:
+                # if light path key is nonexistent
+                grid_info['light_path'] = [['__static_apertures__']]
+        self._grids_info = grids_info
+
+    @property
+    def sun_up_hours(self):
+        """Return sun up hours."""
+        return self._sun_up_hours
+
+    @sun_up_hours.setter
+    def sun_up_hours(self, sun_up_hours):
+        assert isinstance(sun_up_hours, list), \
+            f'Sun up hours must be a list. Got object of type: {type(sun_up_hours)}'
+        self._sun_up_hours = sun_up_hours
+        self.sun_down_hours = np.setdiff1d(self.study_hours, sun_up_hours).tolist()
+
+    @property
+    def sun_up_hours_mask(self):
+        """Return sun up hours masking array."""
+        return self._sun_up_hours_mask
+
+    @property
+    def sun_down_hours(self):
+        """Return sun down hours."""
+        return self._sun_down_hours
+
+    @sun_down_hours.setter
+    def sun_down_hours(self, sun_down_hours):
+        assert isinstance(sun_down_hours, list), \
+            f'Sun down hours must be a list. Got object of type: {type(sun_down_hours)}'
+        self._sun_down_hours = sun_down_hours
+
+    @property
+    def sun_down_hours_mask(self):
+        """Return sun down hours masking array."""
+        return self._sun_down_hours_mask
+
+    @property
+    def datetimes(self):
+        """Return DateTimes for sun up hours."""
+        return self._datetimes
+
+    @property
+    def light_paths(self):
+        """Return the identifiers of the light paths."""
+        return self._light_paths
+
+    @property
+    def default_states(self):
+        """Return default states as a dictionary."""
+        return self._default_states
+
+    @property
+    def grid_states(self):
+        """Return grid states as a dictionary."""
+        return self._grid_states
+
+    @property
+    def timestep(self):
+        """Return timestep as an integer."""
+        return self._timestep
+
+    @property
+    def study_hours(self):
+        """Return study hours as a list."""
+        return self._study_hours
+
+    def _get_light_paths(self) -> list:
+        """Find all light paths in grids_info."""
+        lp = []
+        for grid_info in self.grids_info:
+            try:
+                light_paths = grid_info['light_path']
+            except KeyError:
+                grid_info['light_path'] = [['__static_apertures__']]
+                light_paths = grid_info['light_path']
+            for light_path in light_paths:
+                for elem in light_path:
+                    if elem in lp:
+                        continue
+                    if elem == '__static_apertures__':
+                        lp.insert(0, elem)
+                    else:
+                        lp.append(elem)
+            if not light_paths and '__static_apertures__' not in lp:
+                lp.insert(0, '__static_apertures__')
+
+        return lp
+
+    def _get_default_states(self) -> dict:
+        """Set default state to 0 for all light paths."""
+        default_states = {}
+        for light_path in self.light_paths:
+            default_states[light_path] = [0]
+        return default_states
+
+    def _get_grid_states(self) -> dict:
+        """Read grid_states.json if available."""
+        info = Path(self.folder, 'grid_states.json')
+        if info.is_file():
+            with open(info) as data_f:
+                data = json.load(data_f)
+            return data
+        else:
+            # only static results
+            return {}
+
+    def _get_study_info(self) -> Tuple[int, list]:
+        """Read study info file."""
+        study_info_file = Path(self.folder).joinpath('study_info.json')
+        if study_info_file.exists():
+            with open(study_info_file) as file:
+                study_info = json.load(file)
+            if study_info['timestep'] == 1:
+                study_info['study_hours'] = \
+                    list(map(int, study_info['study_hours']))
+        else:
+            study_info = {}
+            study_info['timestep'] = 1
+            study_info['study_hours'] = AnalysisPeriod().hoys
+
+        return study_info['timestep'], study_info['study_hours']
+
+    def _get_datetimes(self) -> List[DateTime]:
+        """Get a list of DateTimes of the sun up hours."""
+        datetimes = [
+            DateTime.from_hoy(hoy) for hoy in list(map(float, self.sun_up_hours))
+            ]
+
+        return datetimes
+
+    def _get_grids_info(self) -> List[dict]:
+        """Get grids info from folder."""
+        info = Path(self.folder, 'grids_info.json')
+        with open(info) as data_f:
+            grids = json.load(data_f)
+
+        return grids
+
+    def _get_sun_up_hours(self) -> List[float]:
+        """Get sun up hours from folder."""
+        suh_fp = Path(self.folder, 'sun-up-hours.txt')
+        sun_up_hours = np.loadtxt(suh_fp, dtype=float).tolist()
+        if self.timestep == 1:
+            sun_up_hours = list(map(int, sun_up_hours))
+
+        return sun_up_hours
+
+    def _get_sun_up_hours_mask(self) -> List[int]:
+        """Get a sun up hours masking array of the study hours."""
+        sun_up_hours_mask = \
+            np.where(np.isin(self.study_hours, self.sun_up_hours))[0]
+
+        return sun_up_hours_mask
+
+    def _get_sun_down_hours_mask(self) -> List[int]:
+        """Get a sun down hours masking array of the study hours."""
+        sun_down_hours_mask = \
+            np.where(~np.isin(self.study_hours, self.sun_up_hours))[0]
+
+        return sun_down_hours_mask
+
+    def __repr__(self):
+        return f'{self.__class__.__name__}: {self.folder}'
+
+
+
+[docs] +class Results(_ResultsFolder): + """Results class. + + Args: + folder: Path to results folder. + schedule: 8760 values as a list. Values must be either 0 or 1. Values of 1 + indicates occupied hours. If no schedule is provided a default schedule + will be used. (Default: None). + load_arrays: Set to True to load all NumPy arrays. If False the arrays will be + loaded only once they are needed. In both cases the loaded array(s) will be + stored in a dictionary under the arrays property. (Default: False). + + Properties: + * schedule + * occ_pattern + * total_occ + * sun_down_occ_hours + * occ_mask + * arrays + * valid_states + * datatype + * unit + """ + __slots__ = ('_schedule', '_occ_pattern', '_total_occ', '_sun_down_occ_hours', + '_occ_mask', '_arrays', '_valid_states', '_datatype', '_unit') + + def __init__(self, folder, datatype: DataTypeBase = None, + schedule: list = None, unit: str = None, + load_arrays: bool = False): + """Initialize Results.""" + _ResultsFolder.__init__(self, folder) + self.schedule = schedule + self._arrays = self._load_arrays() if load_arrays else {} + self._valid_states = self._get_valid_states() + self.datatype = datatype + self.unit = unit + + @property + def schedule(self): + """Return schedule.""" + return self._schedule + + @schedule.setter + def schedule(self, schedule): + self._schedule = schedule if schedule else \ + occupancy_schedule_8_to_6(timestep=self.timestep, as_list=True) + self._update_occ() + + @property + def occ_pattern(self): + """Return a filtered version of the annual schedule that only includes the + sun-up-hours.""" + return self._occ_pattern + + @property + def total_occ(self): + """Return an integer for the total occupied hours of the schedule.""" + return self._total_occ + + @property + def sun_down_occ_hours(self): + """Return an integer for the number of occupied hours where the sun is down and + there's no possibility of being daylit or experiencing glare.""" + return self._sun_down_occ_hours + + @property + def occ_mask(self): + """Return an occupancy mask as a NumPy array that can be used to mask the + results.""" + return self._occ_mask + + @property + def arrays(self): + """Return a dictionary of all the NumPy arrays that have been loaded.""" + return self._arrays + + @arrays.setter + def arrays(self, value): + self._arrays = value + + @property + def valid_states(self): + """Return a dictionary with valid states. Each light path is represented by a + key-value pair where the light path identifier is the key and the value is a list + of valid states, e.g., [0, 1, 2, ...].""" + return self._valid_states + + @property + def datatype(self): + """Return a Ladybug DataType object.""" + return self._datatype + + @datatype.setter + def datatype(self, value): + if value is not None: + assert isinstance(value, DataTypeBase), \ + f'data_type must be a Ladybug DataType. Got {type(value)}' + else: + value = GenericType('Generic', '') + self._datatype = value + + @property + def unit(self): + """Return unit of hourly values.""" + return self._unit + + @unit.setter + def unit(self, value): + self._unit = value + +
+[docs] + def total( + self, hoys: list = [], states: DynamicSchedule = None, + grids_filter: str = '*', res_type: str = 'total' + ) -> type_hints.total: + """Get summed values for each sensor. + + Args: + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + Tuple: A tuple with total values and grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + mask = hoys_mask(self.sun_up_hours, hoys) + + total = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type=res_type) + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=mask + ) + array_total = array_filter.sum(axis=1) + else: + array_total = np.zeros(grid_info['count']) + total.append(array_total) + + return total, grids_info
+ + +
+[docs] + def point_in_time( + self, datetime: Union[float, DateTime], states: DynamicSchedule = None, + grids_filter: str = '*', res_type: str = 'total' + ) -> type_hints.point_in_time: + """Get point in time values. + + Args: + datetime: Hour of the year as a float or DateTime object. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + Tuple: A tuple with point in time values and grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + + if isinstance(datetime, float): + dt = DateTime.from_hoy(datetime) + elif isinstance(datetime, DateTime): + dt = datetime + else: + error_message = ( + f'Input datetime must be of type {int} or {DateTime}. ' + f'Received {type(DateTime)}.' + ) + raise ValueError(error_message) + + idx = self._index_from_datetime(dt) + + pit_values = [] + for grid_info in grids_info: + if idx: + array = self._array_from_states( + grid_info, states=states, res_type=res_type) + pit_values.append(array[:, idx]) + else: + # datetime not in sun up hours, add zeros + pit_values.append(np.zeros(grid_info['count'])) + + return pit_values, grids_info
+ + +
+[docs] + def point_in_time_to_folder( + self, target_folder: str, datetime: Union[float, DateTime], + states: DynamicSchedule = None, grids_filter: str = '*', + res_type: str = 'total' + ) -> type_hints.point_in_time: + """Get point in time values and write the values to a folder. + + Args: + target_folder: Folder path to write annual metrics in. Usually this + folder is called 'metrics'. + datetime: Hour of the year as a float or DateTime object. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + Tuple: A tuple with point in time values and grid information. + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + pit_values, grids_info = self.point_in_time( + datetime=datetime, states=states, + grids_filter=grids_filter, res_type=res_type) + + metric_folder = folder.joinpath('point_in_time') + + for count, grid_info in enumerate(grids_info): + d = pit_values[count] + full_id = grid_info['full_id'] + output_file = metric_folder.joinpath(f'{full_id}.pit') + output_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(output_file, d, fmt='%.2f') + + info_file = metric_folder.joinpath('grids_info.json') + info_file.write_text(json.dumps(grids_info)) + + return pit_values, grids_info
+ + +
+[docs] + def average_values( + self, hoys: list = [], states: DynamicSchedule = None, grids_filter: str = '*', + res_type: str = 'total') -> type_hints.average_values: + """Get average values for each sensor over a given period. + + The hoys input can be used to filter the data for a particular time + period. + + Args: + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + Tuple: A tuple with the average value for each sensor and grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + full_length = len(self.study_hours) if len(hoys) == 0 else len(hoys) + mask = hoys_mask(self.sun_up_hours, hoys) + + average_values = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type=res_type) + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=mask) + results = average_values_array2d( + array_filter, full_length) + else: + results = np.zeros(grid_info['count']) + average_values.append(results) + + return average_values, grids_info
+ + +
+[docs] + def average_values_to_folder( + self, target_folder: str, hoys: list = [], states: DynamicSchedule = None, + grids_filter: str = '*', res_type: str = 'total'): + """Get average values for each sensor over a given period and write the + values to a folder. + + Args: + target_folder: Folder path to write annual metrics in. Usually this + folder is called 'metrics'. + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + average_values, grids_info = self.average_values( + hoys=hoys, states=states, + grids_filter=grids_filter, res_type=res_type) + + metric_folder = folder.joinpath('average_values') + + for count, grid_info in enumerate(grids_info): + d = average_values[count] + full_id = grid_info['full_id'] + output_file = metric_folder.joinpath(f'{full_id}.average') + output_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(output_file, d, fmt='%.2f') + + info_file = metric_folder.joinpath('grids_info.json') + info_file.write_text(json.dumps(grids_info))
+ + +
+[docs] + def median_values( + self, hoys: list = [], states: dict = None, grids_filter: str = '*', + res_type: str = 'total') -> type_hints.median_values: + """Get median values for each sensor over a given period. + + The hoys input can be used to filter the data for a particular time + period. If hoys is left empty the median values will likely be 0 since + there are likely more sun down hours than sun up hours. + + Args: + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + Tuple: A tuple with the median value for each sensor and grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + mask = hoys_mask(self.sun_up_hours, hoys) + + median_values = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type=res_type) + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=mask) + if not hoys: + # concatenate zero array + zero_array = \ + np.zeros((grid_info['count'], len(self.sun_down_hours))) + array_filter = np.concatenate((array_filter, zero_array), axis=1) + else: + # find number of hoys that are sun down hours + sdh_hoys = \ + len(set(self.sun_down_hours).intersection(hoys)) + if sdh_hoys != 0: + # concatenate zero array + zero_array = np.zeros((grid_info['count'], sdh_hoys)) + array_filter = \ + np.concatenate((array_filter, zero_array), axis=1) + results = np.median(array_filter, axis=1) + else: + results = np.zeros(grid_info['count']) + median_values.append(results) + + return median_values, grids_info
+ + +
+[docs] + def median_values_to_folder( + self, target_folder: str, hoys: list = [], states: dict = None, + grids_filter: str = '*', res_type: str = 'total'): + """Get median values for each sensor over a given period and write the + values to a folder. + + Args: + target_folder: Folder path to write annual metrics in. Usually this + folder is called 'metrics'. + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + median_values, grids_info = self.median_values( + hoys=hoys, states=states, + grids_filter=grids_filter, res_type=res_type) + + metric_folder = folder.joinpath('median_values') + + for count, grid_info in enumerate(grids_info): + d = median_values[count] + full_id = grid_info['full_id'] + output_file = metric_folder.joinpath(f'{full_id}.median') + output_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(output_file, d, fmt='%.2f') + + info_file = metric_folder.joinpath('grids_info.json') + info_file.write_text(json.dumps(grids_info))
+ + +
+[docs] + def cumulative_values( + self, hoys: list = [], states: DynamicSchedule = None, + t_step_multiplier: float = 1, grids_filter: str = '*', + res_type: str = 'total') -> type_hints.cumulative_values: + """Get cumulative values for each sensor over a given period. + + The hoys input can be used to filter the data for a particular time + period. + + Args: + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + t_step_multiplier: A value that will be multiplied with the timestep. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + Tuple: A tuple with the cumulative value for each sensor and grid + information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + mask = hoys_mask(self.sun_up_hours, hoys) + + cumulative_values = [] + for grid_info in grids_info: + array = self._array_from_states(grid_info, states=states, res_type=res_type) + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=mask) + results = cumulative_values_array2d( + array_filter, self.timestep, t_step_multiplier) + else: + results = np.zeros(grid_info['count']) + cumulative_values.append(results) + + return cumulative_values, grids_info
+ + +
+[docs] + def cumulative_values_to_folder( + self, target_folder: str, hoys: list = [], + states: DynamicSchedule = None, t_step_multiplier: float = 1, + grids_filter: str = '*', res_type: str = 'total'): + """Get cumulative values for each sensor over a given period and write + the values to a folder. + + Args: + target_folder: Folder path to write annual metrics in. Usually this + folder is called 'metrics'. + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + t_step_multiplier: A value that will be multiplied with the timestep. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + res_type: Type of results to load. Defaults to 'total'. + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + cumulative_values, grids_info = self.cumulative_values( + hoys=hoys, states=states, t_step_multiplier=t_step_multiplier, + grids_filter=grids_filter, res_type=res_type + ) + + metric_folder = folder.joinpath('cumulative_values') + + for count, grid_info in enumerate(grids_info): + d = cumulative_values[count] + full_id = grid_info['full_id'] + output_file = metric_folder.joinpath(f'{full_id}.cumulative') + output_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(output_file, d, fmt='%.2f') + + info_file = metric_folder.joinpath('grids_info.json') + info_file.write_text(json.dumps(grids_info))
+ + +
+[docs] + def peak_values( + self, hoys: list = [], states: DynamicSchedule = None, grids_filter: str = '*', + coincident: bool = False, res_type: str = 'total' + ) -> type_hints.peak_values: + """Get peak values for each sensor over a given period. + + The hoys input can be used to filter the data for a particular time + period. + + Args: + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + coincident: Boolean to indicate whether output values represent the peak + value for each sensor throughout the entire analysis (False) or they + represent the highest overall value across each sensor grid at a + particular timestep (True). Defaults to False. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + Tuple: A tuple with the peak value for each sensor and grid information. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + mask = hoys_mask(self.sun_up_hours, hoys) + filt_suh = hoys if len(hoys) != 0 else self.sun_up_hours + + peak_values = [] + max_hoys = [] + for grid_info in grids_info: + max_i = None + array = self._array_from_states(grid_info, states=states, res_type=res_type) + if np.any(array): + array_filter = np.apply_along_axis( + filter_array, 1, array, mask=mask) + results, max_i = peak_values_array2d( + array_filter, coincident=coincident) + else: + results = np.zeros(grid_info['count']) + peak_values.append(results) + if max_i: + max_hoys.append(filt_suh[max_i]) + else: + max_hoys.append(None) + + return peak_values, max_hoys, grids_info
+ + +
+[docs] + def peak_values_to_folder( + self, target_folder: str, hoys: list = [], states: DynamicSchedule = None, + grids_filter: str = '*', coincident: bool = False, res_type='total'): + """Get peak values for each sensor over a given period and write the + values to a folder. + + Args: + target_folder: Folder path to write peak values in. Usually this + folder is called 'metrics'. + hoys: An optional numbers or list of numbers to select the hours of + the year (HOYs) for which results will be computed. Defaults to []. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + coincident: Boolean to indicate whether output values represent the peak + value for each sensor throughout the entire analysis (False) or they + represent the highest overall value across each sensor grid at a + particular timestep (True). Defaults to False. + res_type: Type of results to load. Defaults to 'total'. + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + peak_values, max_hoys, grids_info = self.peak_values( + hoys=hoys, states=states, grids_filter=grids_filter, + coincident=coincident, res_type=res_type) + + metric_folder = folder.joinpath('peak_values') + + for count, grid_info in enumerate(grids_info): + d = peak_values[count] + full_id = grid_info['full_id'] + output_file = metric_folder.joinpath(f'{full_id}.peak') + output_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(output_file, d, fmt='%.2f') + + max_hoys_file = metric_folder.joinpath('max_hoys.txt') + max_hoys_file.write_text('\n'.join(str(h) for h in max_hoys)) + + info_file = metric_folder.joinpath('grids_info.json') + info_file.write_text(json.dumps(grids_info))
+ + + def _array_to_annual_data( + self, grid_info, states: DynamicSchedule = None, + sensor_index: list = None, res_type: str = 'total' + ) -> Tuple[List[HourlyContinuousCollection], dict, list]: + """Get annual data for one or multiple sensors. + + Args: + grid_info: Grid information of the grid. + states: A dictionary of states. Defaults to None. + sensor_index: A list of sensor indices as integers. Defaults to None. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + Tuple: A tuple with Data Collections for each sensor, grid information, + and a list of the sensors. + """ + analysis_period = AnalysisPeriod(timestep=self.timestep) + + # if no sensor_index, create list with all sensors + if not sensor_index: + sensor_index = [range(grid_info['count'])] + + data_collections = [] + array = self._array_from_states(grid_info, states=states, res_type=res_type) + for idx in sensor_index: + if np.any(array): + values = array[idx, :] + else: + values = np.zeros(len(self.sun_up_hours)) + annual_array = Results.values_to_annual( + self.sun_up_hours, values, self.timestep, self.study_hours) + header = Header(self.datatype, self.unit, analysis_period) + header.metadata['sensor grid'] = grid_info['full_id'] + header.metadata['sensor index'] = idx + data_collections.append( + HourlyContinuousCollection(header, annual_array.tolist())) + + return data_collections, grid_info, sensor_index + +
+[docs] + def annual_data( + self, states: DynamicSchedule = None, grids_filter: str = '*', + sensor_index: dict = None, res_type: str = 'total' + ) -> type_hints.annual_data: + """Get annual data for one or multiple sensors. + + Args: + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + sensor_index: A dictionary with grids as keys and a list of sensor + indices as values. Defaults to None. + res_type: Type of results to load. Defaults to 'total'. + + Returns: + Tuple: A tuple with Data Collections for each sensor, grid information, + and a dictionary of the sensors. + """ + grids_info = self._filter_grids(grids_filter=grids_filter) + analysis_period = AnalysisPeriod(timestep=self.timestep) + + # if no sensor_index, create dict with all sensors + if not sensor_index: + sensor_index = {} + for grid_info in grids_info: + sensor_index[grid_info['full_id']] = \ + [i for i in range(grid_info['count'])] + + data_collections = [] + for grid_info in grids_info: + data_collections_grid = [] + grid_id = grid_info['full_id'] + array = self._array_from_states(grid_info, states=states, res_type=res_type) + indices = sensor_index[grid_id] + for idx in indices: + if np.any(array): + values = array[idx, :] + else: + values = np.zeros(len(self.sun_up_hours)) + annual_array = Results.values_to_annual( + self.sun_up_hours, values, self.timestep) + header = Header(self.datatype, self.unit, analysis_period) + header.metadata['sensor grid'] = grid_id + header.metadata['sensor index'] = idx + data_collections_grid.append( + HourlyContinuousCollection(header, annual_array.tolist())) + data_collections.append(data_collections_grid) + + return data_collections, grids_info, sensor_index
+ + +
+[docs] + def annual_data_to_folder( + self, target_folder: str, states: DynamicSchedule = None, grids_filter: str = '*', + sensor_index: dict = None, res_type: str = 'total'): + """Get annual data for one or multiple sensors and write the data to a + folder as Data Collections. + + Args: + target_folder: Folder path to write annual metrics in. Usually this + folder is called 'metrics'. + states: A dictionary of states. Defaults to None. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + sensor_index: A dictionary with grids as keys and a list of sensor + indices as values. Defaults to None. + res_type: Type of results to load. Defaults to 'total'. + """ + folder = Path(target_folder) + folder.mkdir(parents=True, exist_ok=True) + + data_collections, grids_info, sensor_index = self.annual_data( + states=states, grids_filter=grids_filter, sensor_index=sensor_index, + res_type=res_type) + + metric_folder = folder.joinpath('datacollections') + + for count, grid_info in enumerate(grids_info): + grid_collections = data_collections[count] + for data_collection in grid_collections: + grid_id = grid_info['full_id'] + sensor_id = data_collection.header.metadata['sensor index'] + data_dict = data_collection.to_dict() + data_file = metric_folder.joinpath(f'{grid_id}_{sensor_id}.json') + data_file.parent.mkdir(parents=True, exist_ok=True) + data_file.write_text(json.dumps(data_dict))
+ + +
+[docs] + @staticmethod + def values_to_annual( + hours: Union[List[float], np.ndarray], + values: Union[List[float], np.ndarray], + timestep: int, base_value: int = 0, + dtype: np.dtype = np.float32) -> np.ndarray: + """Map a 1D NumPy array based on a set of hours to an annual array. + + This method creates an array with a base value of length 8760 and + replaces the base value with the input 'values' at the indices of the + input 'hours'. + + Args: + hours: A list of hours. This can be a regular list or a 1D NumPy + array. + values: A list of values to map to an annual array. This can be a + regular list or a 1D NumPy array. + timestep: Time step of the simulation. + base_value: A value that will be applied for all the base array. + dtype: A NumPy dtype for the annual array. + + Returns: + A 1D NumPy array. + """ + values = np.array(values) + check_array_dim(values, 1) + hours = np.array(hours) + assert hours.shape == values.shape + full_ap = AnalysisPeriod(timestep=timestep) + indices = np.where(np.isin(full_ap.hoys, hours))[0] + annual_array = np.repeat(base_value, 8760 * timestep).astype(dtype) + annual_array[indices] = values + + return annual_array
+ + + def _index_from_datetime(self, datetime: DateTime) -> Union[int, None]: + """Returns the index of the input datetime in the list of datetimes + from the datetimes property. + + If the DateTime is not in the list, the function will return None. + + Args: + datetime: A DateTime object. + + Returns: + Index as an integer or None. + """ + assert isinstance(datetime, DateTime), \ + f'Expected DateTime object but received {type(datetime)}' + try: + index = self.datetimes.index(datetime) + except Exception: + # DateTime not in sun up hours + index = None + + return index + + def _get_array( + self, grid_info: dict, light_path: str, state: int = 0, + res_type: str = 'total', extension: str = '.npy') -> np.ndarray: + """Get an array for a given grid, light path, and state. + + The array will be fetched from the 'arrays' property if it has been + loaded already. + + Args: + grid_info: Grid information. + light_path: Identifier of the light path. + state: State as an integer. E.g., 0 for the default state. + Defaults to 0. + res_type: Type of results to load. Defaults to 'total'. + extension: File extension of the array to load. Defaults to '.npy'. + + Returns: + np.ndarray: A NumPy array of a given grid, light path, and state. + """ + grid_id = grid_info['full_id'] + + state_identifier = self._state_identifier(grid_id, light_path, state=state) + + try: + array = self.arrays[grid_id][light_path][state_identifier][res_type] + except Exception: + array = self._load_array( + grid_info, light_path, state=state, res_type=res_type, + extension=extension + ) + + return array + + def _load_array( + self, grid_info: dict, light_path: str, state: int = 0, + res_type: str = 'total', extension: str = '.npy') -> np.ndarray: + """Load a NumPy file to an array. + + This method will also update the arrays property value. + + Args: + grid_info: Grid information. + light_path: Identifier of the light path. + state: State as an integer. E.g., 0 for the default state. + Defaults to 0. + res_type: Which type of result to return a file for. E.g., 'total' for total + illuminance or 'direct' for direct illuminance. + extension: File extension of the array to load. Defaults to '.npy'. + + Returns: + np.ndarray: A NumPy array of a given grid, light path, and state + from a NumPy file. + """ + grid_id = grid_info['full_id'] + + def merge_dicts(array_dict, arrays): + for key, value in array_dict.items(): + if isinstance(value, dict): + node = arrays.setdefault(key, {}) + merge_dicts(value, node) + else: + arrays[key] = value + return arrays + + state_identifier = self._state_identifier(grid_id, light_path, state=state) + file = self._get_file(grid_id, light_path, state_identifier, res_type, + extension=extension) + array = np.load(file) + + array_dict = {grid_id: {light_path: {state_identifier: {res_type: array}}}} + arrays = merge_dicts(array_dict, self.arrays) + self.arrays = arrays + + return array + + def _state_identifier( + self, grid_id: str, light_path: str, state: int = 0) -> Union[str, None]: + """Get the state identifier from a light path and state integer. + + Args: + grid_id: Grid identifier. + light_path: Identifier of the light path. + state: State as an integer. E.g., 0 for the default state. + Defaults to 0. + + Returns: + State identifier. For static apertures the identifier is 'default', + and for other light paths it is the light path identifier preceded + by the state integer, e.g., '0_light_path'. If the state is -1 the + state identifier will be None. + """ + # TODO: Figure out if there is a better way to handle the states. + # I.e., state integer <--> state identifier. + valid_states = self.valid_states[light_path] + if state in valid_states: + if light_path == '__static_apertures__': + state_identifier = 'default' + else: + state_identifier = self.grid_states[grid_id][light_path][state] + return state_identifier + elif state == -1: + return None + else: + error_message = ( + f'State of {light_path} must be any of {valid_states} for on ' + f'or -1 for off. Received state {state}.' + ) + raise ValueError(error_message) + + def _get_file( + self, grid_id: str, light_path: str, state_identifier: str, + res_type: str = 'total', extension: str = '.npy') -> Path: + """Return the path of a results file. + + Args: + grid_id: Grid identifier. + light_path: Identifier of the light path. + state_identifier: State identifier. + res_type: Which type of result to return a file for. E.g., 'total' for total + illuminance or 'direct' for direct illuminance. + extension: File extension of the array to load. Defaults to '.npy'. + + Returns: + Path to a NumPy file. + """ + file = Path(self.folder, light_path, state_identifier, + res_type, grid_id + extension) + if not file.is_file(): + raise FileNotFoundError(f'File {file} not found in the results folder.') + + return file + + def _validate_dynamic_states(self, states: dict) -> dict: + """Validate dynamic states and return states dictionary. + + If all light paths in the dictionary have 8760 values, the states + dictionary is returned as is. If some light paths have less than 8760 + values, pattern of values will be repeated until it reaches a length of + 8760. + + Args: + states: A dictionary of states. + + Returns: + dict: A dictionary of states. + """ + if all(len(values) == 8760 for values in states.values()): + return states + for light_path, values in states.items(): + if len(values) < 8760: + states[light_path] = list(islice(cycle(values), 8760)) + elif len(values) > 8760: + error_message = ( + f'The light path {light_path} has {len(values)} values in ' + f'its states schedule. Maximum allowed number of values ' + f'is 8760.' + ) + raise ValueError(error_message) + + return states + + def _validate_states(self, states: dict) -> dict: + """Validate states and return states dictionary. + + If all light paths in the dictionary have integers only as values, the + states dictionary is returned as is. If some light paths have values + that are not integers, these values will be mapped as integers if + possible, e.g., if the values are strings ('0', '1', etc.) instead of + integers. + + Args: + states: A dictionary of states. + + Returns: + dict: A dictionary of states. + """ + if all(isinstance(v, int) for values in states.values() for v in values): + return states + for light_path, values in states.items(): + try: + states[light_path] = list(map(int, values)) + except ValueError as err: + error_message = ( + f'Failed to convert states schedule for light path ' + f'{light_path} to integers.' + ) + raise ValueError(error_message) from err + + return states + + def _filter_grid_states(self, grid_info, states: DynamicSchedule = None) -> DynamicSchedule: + """Filter a dictionary of states by grid. Only light paths relevant to + the given grid will be returned. + + Args: + grid_info: Grid information. + states: A dictionary of states. Light paths as keys and lists of + 8760 values for each key. The values should be integers + matching the states or -1 for off. Default to None. + + Returns: + dict: A filtered states dictionary. + """ + light_paths = [] + for lp in grid_info['light_path']: + for _lp in lp: + if _lp == '__static_apertures__' and len(lp) > 1: + pass + else: + light_paths.append(_lp) + if states: + states = states.filter_by_identifiers(light_paths) + else: + default_states = self.default_states + states = DynamicSchedule() + for light_path in light_paths: + ap_group_schedule = ApertureGroupSchedule( + light_path, default_states[light_path], is_static=True) + states.add_aperture_group_schedule(ap_group_schedule) + + return states + + def _array_from_states( + self, grid_info, states: DynamicSchedule = None, + res_type: str = 'total', zero_array: bool = False + ) -> np.ndarray: + """Create an array for a given grid by the states settings. + + Args: + grid_info: Grid information of the grid. + states: A dictionary of states. Light paths as keys and lists of 8760 values + for each key. The values should be integers matching the states or -1 for + off. + res_type: Which type of result to create an array for. E.g., 'total' + for total illuminance or 'direct' for direct illuminance. + zero_array: Boolean to note if a 2D zero array should be created if + the array of the grid is zero. This is the case if the + illuminance of the grid is zero. (Default: False). + + Returns: + A NumPy array based on the states settings. + """ + # get states that are relevant for the grid + states = self._filter_grid_states(grid_info, states=states) + + arrays = [] + for light_path, gr_schedule in states.dynamic_schedule.items(): + if gr_schedule.is_static: + state = gr_schedule.schedule[0] + # if state is -1 we continue since it is "turned off" + if state == -1: + continue + # load static array (state is static) + array = self._get_array( + grid_info, light_path, state=state, res_type=res_type) + arrays.append(array) + else: + # create default 0 array, we will add to this later + array = np.zeros((grid_info['count'], len(self.sun_up_hours))) + # slice states to match sun up hours + states_array = np.array(gr_schedule.schedule)[ + list(map(int, self.sun_up_hours))] + for state in np.unique(states_array): + if state == -1: + # if state is -1 we continue since it is "turned off" + continue + # load static array (state is static) + _array = self._get_array( + grid_info, light_path, state=state, res_type=res_type) + # get indices and add values to base array + states_indicies = states_array == state + array[:, states_indicies] += _array[:, states_indicies] + arrays.append(array) + array = sum(arrays) + + if not np.any(array): + if zero_array: + array = np.zeros((grid_info['count'], len(self.sun_up_hours))) + else: + array = np.array([]) + + return array + + def _update_occ(self): + """Set properties related to occupancy.""" + occ_mask = np.array(self.schedule, dtype=int)[self.sun_up_hours_mask] + sun_down_sch = \ + np.array(self.schedule, dtype=int)[self.sun_down_hours_mask].sum() + + self._occ_mask = occ_mask + self._total_occ = sum(self.schedule) + self._sun_down_occ_hours = sun_down_sch + + def _filter_grids(self, grids_filter: str = '*') -> list: + """Return grids information. + + Args: + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + + Returns: + list: List of grid information for filtered grids. + """ + if grids_filter != '*': + grids_info = \ + _filter_grids_by_pattern(self.grids_info, grids_filter) + else: + grids_info = self.grids_info + + return grids_info + + def _load_arrays(self) -> dict: + """Load all the NumPy arrays in the results folder.""" + arrays = {} + grids_info = self.grids_info + + for grid_info in grids_info: + grid_id = grid_info['full_id'] + light_paths = grid_info['light_path'] + arrays[grid_id] = {} + for light_path in light_paths: + light_path = light_path[0] + arrays[grid_id][light_path] = {} + light_path_folder = Path(self.folder, light_path) + for state_folder in Path(light_path_folder).iterdir(): + state = state_folder.name + arrays[grid_id][light_path][state] = {} + for res_type_folder in Path(state_folder).iterdir(): + res_type = res_type_folder.name + file = Path(res_type_folder, grid_id + '.npy') + array = np.load(file) + arrays[grid_id][light_path][state][res_type] = array + + return arrays + + def _get_valid_states(self) -> dict: + """Returns a dictionary with valid states for each light path. + + For each light path there will be a key (identifier of the light path) + and its value will be a list of valid states as integers. + + Example of output format: + { + '__static_apertures__': [0], + 'Room1_North': [0, 1], + 'Room1_South': [0, 1], + 'Room2_North1': [0, 1], + 'Room2_North2': [0, 1] + } + + Returns: + dict: Valid states integers for each light path. + """ + valid_states = {} + grid_states = self.grid_states + if '__static_apertures__' in self.light_paths: + valid_states['__static_apertures__'] = [0] + for light_paths in grid_states.values(): + for light_path, states in light_paths.items(): + if light_path not in valid_states: + valid_states[light_path] = list(range(len(states))) + + return valid_states + + def _light_paths_from_grid_info(self, grid_info: Union[dict, str]) -> list: + if isinstance(grid_info, str): + for _grid_info in self.grids_info: + if _grid_info['full_id'] == grid_info: + grid_info = _grid_info + break + else: + raise Exception(f'Grid info with full_id "{grid_info}" not found.') + light_paths = [] + for lp in grid_info['light_path']: + for _lp in lp: + if _lp == '__static_apertures__' and len(lp) > 1: + pass + else: + light_paths.append(_lp) + + return light_paths + + def _get_state_combinations(self, grid_info: Union[dict, str]) -> List[dict]: + light_paths = self._light_paths_from_grid_info(grid_info) + valid_states = self._get_valid_states() + filtered_states = {lp: valid_states[lp] for lp in light_paths} + keys, values = zip(*filtered_states.items()) + combinations = [dict(zip(keys, v)) for v in itertools.product(*values)] + + return combinations
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/util.html b/docs/_modules/honeybee_radiance_postprocess/util.html new file mode 100644 index 00000000..160b2c45 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/util.html @@ -0,0 +1,903 @@ + + + + + + + honeybee_radiance_postprocess.util — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.util

+"""Post-processing utility functions."""
+from typing import Tuple
+import numpy as np
+
+from honeybee_radiance.writer import _filter_by_pattern
+
+
+
+[docs] +def binary_mtx_dimension(filepath: str) -> Tuple[int, int, int, int, str]: + """Return binary Radiance matrix dimensions if exist. + + This function returns NROWS, NCOLS, NCOMP and number of header lines including the + white line after last header line. + + Args: + filepath: Full path to Radiance file. + + Returns: + nrows, ncols, ncomp, line_count, fmt + """ + try: + inf = open(filepath, 'rb', encoding='utf-8') + except Exception: + inf = open(filepath, 'rb') + try: + first_line = next(inf).rstrip().decode('utf-8') + if first_line[:10] != '#?RADIANCE': + error_message = ( + f'File with Radiance header must start with #?RADIANCE not ' + f'{first_line}.' + ) + raise ValueError(error_message) + + header_lines = [first_line] + nrows = ncols = ncomp = None + for line in inf: + line = line.rstrip().decode('utf-8') + header_lines.append(line) + if line[:6] == 'NROWS=': + nrows = int(line.split('=')[-1]) + if line[:6] == 'NCOLS=': + ncols = int(line.split('=')[-1]) + if line[:6] == 'NCOMP=': + ncomp = int(line.split('=')[-1]) + if line[:7] == 'FORMAT=': + fmt = line.split('=')[-1] + break + + if not nrows or not ncols: + error_message = ( + f'NROWS or NCOLS was not found in the Radiance header. NROWS ' + f'is {nrows} and NCOLS is {ncols}. The header must have both ' + f'elements.' + ) + raise ValueError(error_message) + return nrows, ncols, ncomp, len(header_lines) + 1, fmt + finally: + inf.close()
+ + + +
+[docs] +def check_array_dim(array: np.ndarray, dim: int): + """Check NumPy array dimension. + + Args: + array: A NumPy array. + dim: The dimension to check against. + """ + assert array.ndim == dim, \ + f'Expected {dim}-dimensional array. Dimension of array is {array.ndim}'
+ + + +
+[docs] +def filter_array(array: np.ndarray, mask: np.ndarray) -> np.ndarray: + """Filter a NumPy array by a masking array. The array will be passed as is + if the mask is None. + + Args: + array: A NumPy array to filter. + mask: A NumPy array of ones/zeros or True/False. + + Returns: + A filtered NumPy array. + """ + if mask is not None: + return array[mask.astype(bool)] + return array
+ + + +
+[docs] +def hoys_mask(sun_up_hours: list, hoys: list) -> np.ndarray: + """Create a NumPy masking array from a list of hoys. + + Args: + sun_up_hours: A list of sun up hours. + hoys: A list hoys to select. + + Returns: + A NumPy array of booleans. + """ + if len(hoys) != 0: + hoys_mask = np.where(np.isin(sun_up_hours, hoys), True, False) + return hoys_mask
+ + + +
+[docs] +def array_memory_size( + sensors: int, sun_up_hours: int, ncomp: int = None, + dtype: np.dtype = np.float32, gigabyte: bool = True) -> float: + """Calculate the memory size of an array before creating or loading an + array. + + Args: + sensors: Number of sensors in the array. + sun_up_hours: Number of sun up hours in the array. + ncomp: Optional number of components for each element in the array, + e.g., if the data is in RGB format then this value must be set + to 3. Defaults to None. + dtype: The data type of the array. Defaults to np.float32. + gigabyte: Boolean toggle to output the memory size in gigabytes. + Defaults to True. + + Returns: + float: The memory size of an array. + """ + # check if dtype is valid + dtypes = tuple(np.sctypes['float']) + if not isinstance(dtype, dtypes): + try: + dtype = dtype() + except TypeError as err: + error_message = ( + f'Unable to instantiate input dtype. Expected any of the ' + f'following: {dtypes}. Received: {type(dtype)}.' + ) + raise TypeError(error_message) from err + + # calculate memory size + size = sensors * sun_up_hours * dtype.itemsize + if ncomp: + size *= ncomp + if gigabyte: + size /= (1024 ** 3) + + return size
+ + + +
+[docs] +def recursive_dict_merge(dict_1: dict, dict_2: dict): + """Recursive merging of two dictionaries. + + Args: + dict_1: Original dictionary. + dict_2: Dictionary to merge with dict_1. + """ + for k in dict_2: + if (k in dict_1 and isinstance(dict_1[k], dict) and + isinstance(dict_2[k], dict)): + recursive_dict_merge(dict_1[k], dict_2[k]) + else: + dict_1[k] = dict_2[k]
+ + + +def _filter_grids_by_pattern(grids_info, filter_pattern): + """Filter grids_info by a pattern. + + Args: + grids_info: Grid information. + filter_pattern: Pattern to filter grids by. + + Returns: + A list of filtered grids. + """ + grids = _filter_by_pattern(grids_info, filter=filter_pattern) + + return grids + + +
+[docs] +def get_delimiter(delimiter_input): + if delimiter_input == 'tab' or delimiter_input == '\t': + return '\t' + elif delimiter_input == 'space' or delimiter_input == ' ': + return ' ' + elif delimiter_input == 'comma' or delimiter_input == ',': + return ',' + elif delimiter_input == 'semicolon' or delimiter_input == ';': + return ';' + else: + raise ValueError(f'Unsupported delimiter: {delimiter_input}')
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/honeybee_radiance_postprocess/well/well.html b/docs/_modules/honeybee_radiance_postprocess/well/well.html new file mode 100644 index 00000000..a81fc022 --- /dev/null +++ b/docs/_modules/honeybee_radiance_postprocess/well/well.html @@ -0,0 +1,1186 @@ + + + + + + + honeybee_radiance_postprocess.well.well — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +

Source code for honeybee_radiance_postprocess.well.well

+"""Functions for WELL post-processing."""
+from typing import Tuple, Union
+from pathlib import Path
+import json
+import numpy as np
+
+from ladybug.analysisperiod import AnalysisPeriod
+from ladybug.datatype.generic import GenericType
+from ladybug.datacollection import HourlyContinuousCollection
+from ladybug.header import Header
+from honeybee.model import Model
+from honeybee.units import conversion_factor_to_meters
+from honeybee_radiance.writer import _filter_by_pattern
+
+from ..metrics import da_array2d
+from ..annual import occupancy_schedule_8_to_6
+from ..results.annual_daylight import AnnualDaylight
+from ..util import filter_array, recursive_dict_merge
+from ..ies.lm import dynamic_schedule_direct_illuminance
+from ..en17037 import en17037_to_folder
+
+
+def _create_grid_summary(
+    grid_info, sda_grid, sda_blinds_up_grid, sda_blinds_down_grid, pass_sda,
+    total_floor, area_weighted=True):
+    """Create a WELL summary for a single grid.
+
+    Args:
+        grid_info: Grid information.
+        sda_grid: Spatial Daylight Autonomy.
+        pass_sda: The percentage of the sensor points or floor area that
+            passes sDA.
+        total_floor: The number of sensor points or floor area.
+        area_weighted: Boolean to determine if the results are area
+            weighted. Defaults to True.
+
+    Returns:
+        Tuple:
+        -   summary_grid: Summary of each grid individually.
+    """
+    grid_id = grid_info['full_id']
+    grid_name = grid_info['name']
+    grid_summary = {
+        grid_id: {}
+    }
+
+    if area_weighted:
+        _grid_summary = {
+            grid_id: {
+                'name': grid_name,
+                'full_id': grid_id,
+                'sda': round(sda_grid, 2),
+                'sda_blinds_up': round(sda_blinds_up_grid, 2),
+                'sda_blinds_down': round(sda_blinds_down_grid, 2),
+                'floor_area_passing_sda': round(pass_sda, 2),
+                'total_floor_area': round(total_floor, 2)
+            }
+        }
+    else:
+        _grid_summary = {
+            grid_id: {
+                'name': grid_name,
+                'full_id': grid_id,
+                'sda': round(sda_grid, 2),
+                'sda_blinds_up': round(sda_blinds_up_grid, 2),
+                'sda_blinds_down': round(sda_blinds_down_grid, 2),
+                'sensor_count_passing_sda': int(round(pass_sda, 2)),
+                'total_sensor_count': total_floor
+            }
+        }
+
+    recursive_dict_merge(grid_summary, _grid_summary)
+
+    return grid_summary
+
+
+def _well_summary(
+    pass_sda_grids: list, grids_info: list,
+    grid_areas: list, pass_sda_blinds_up_grids: list,
+    pass_sda_blinds_down_grids: list) -> Tuple[dict, dict]:
+    """Create combined summary and summary for each grid individually.
+
+    Args:
+        pass_sda_grids: A list where each sublist is a list of True/False that
+            tells if each sensor point passes sDA.
+        grids_info: A list of grid information.
+        grid_areas: A list where each sublist is the area of each sensor point.
+            The alternative is a list of None values for each grid information.
+
+    Returns:
+        Tuple:
+        -   summary: Summary of of all grids combined.
+        -   summary_grid: Summary of each grid individually.
+    """
+    summary = {}
+    summary_grid = {}
+
+    if all(grid_area is not None for grid_area in grid_areas):
+        # weighted by mesh face area
+        total_area = 0
+        total_area_pass_sda = 0
+        for (pass_sda, grid_area, grid_info, pass_sda_blinds_up,
+             pass_sda_blinds_down) in \
+            zip(pass_sda_grids, grid_areas, grids_info,
+                pass_sda_blinds_up_grids, pass_sda_blinds_down_grids):
+            total_grid_area = grid_area.sum()
+
+            area_pass_sda = grid_area[pass_sda].sum()
+            area_pass_sda_blind_up = grid_area[pass_sda_blinds_up].sum()
+            area_pass_sda_blinds_down = grid_area[pass_sda_blinds_down].sum()
+            sda_grid = area_pass_sda / total_grid_area * 100
+            sda_blinds_up_grid = area_pass_sda_blind_up / total_grid_area * 100
+            sda_blinds_down_grid = area_pass_sda_blinds_down / total_grid_area * 100
+
+            # grid summary
+            grid_summary = \
+                _create_grid_summary(
+                    grid_info, sda_grid, sda_blinds_up_grid, sda_blinds_down_grid,
+                    area_pass_sda, total_grid_area, area_weighted=True
+                )
+
+            recursive_dict_merge(summary_grid, grid_summary)
+
+            total_area += total_grid_area
+            total_area_pass_sda += area_pass_sda
+
+        summary['sda'] = round(total_area_pass_sda / total_area * 100, 2)
+        summary['floor_area_passing_sda'] = total_area_pass_sda
+        summary['total_floor_area'] = total_area
+    else:
+        # assume all sensor points cover the same area
+        total_sensor_count = 0
+        total_sensor_count_pass_sda = 0
+        for (pass_sda, grid_info, pass_sda_blinds_up, pass_sda_blinds_down) in \
+            zip(pass_sda_grids, grids_info, pass_sda_blinds_up_grids,
+                pass_sda_blinds_down_grids):
+            grid_count = grid_info['count']
+
+            sensor_count_pass_sda = pass_sda.sum()
+            sensor_count_pass_sda_blinds_up = pass_sda_blinds_up.sum()
+            sensor_count_pass_sda_blinds_down = pass_sda_blinds_down.sum()
+            sda_grid = sensor_count_pass_sda / grid_count * 100
+            sda_blinds_up_grid = sensor_count_pass_sda_blinds_up / grid_count * 100
+            sda_blinds_down_grid = sensor_count_pass_sda_blinds_down / grid_count * 100
+
+            # grid summary
+            grid_summary = \
+                _create_grid_summary(
+                    grid_info, sda_grid, sda_blinds_up_grid, sda_blinds_down_grid,
+                    sensor_count_pass_sda, grid_count, area_weighted=False
+                )
+
+            recursive_dict_merge(summary_grid, grid_summary)
+
+            total_sensor_count += grid_count
+            total_sensor_count_pass_sda += sensor_count_pass_sda
+
+        summary['sda'] = round(total_sensor_count_pass_sda / total_sensor_count * 100, 2)
+        summary['sensor_count_passing_sda'] = int(total_sensor_count_pass_sda)
+        summary['total_sensor_count'] = total_sensor_count
+
+    return summary, summary_grid
+
+
+
+[docs] +def well_annual_daylight( + results: Union[str, AnnualDaylight], daylight_hours: list, sub_folder, + grids_filter: str = '*', states_schedule: dict = None): + """Calculate credits for WELL L06. + + Args: + results: Path to results folder or a Results class object. + daylight_hours: Schedule of daylight hours used for EN 17037 + sub_folder: Relative path for a subfolder to write the output. + grids_filter: The name of a grid or a pattern to filter the grids. + Defaults to '*'. + states_schedule: A custom dictionary of shading states. In case this is + left empty, the function will calculate a shading schedule by using + the shade_transmittance input. If a states schedule is provided it + will check that it is complying with the 2% rule. Defaults to None. + + Returns: + Tuple: + - well_summary: Summary of WELL analysis. + - ies_lm_summary: Summary of IES LM analysis. + - ies_lm_summary_grid: Summary of IES LM analysis for each grid. + - da_grids: List of daylight autonomy values for each grid. Each item + in the list is a NumPy array of DA values. + - states_schedule: A dictionary of annual shading schedules for each + aperture group. + - fail_to_comply: A dictionary with the hoys where the 2% rule failed. + - grids_info: Grid information. + """ + schedule = occupancy_schedule_8_to_6(as_list=True) + + if not isinstance(results, AnnualDaylight): + results = AnnualDaylight(results, schedule=schedule) + else: + # set schedule to default leed schedule + results.schedule = schedule + + occ_mask = results.occ_mask + total_occ = results.total_occ + + grids_info = results._filter_grids(grids_filter=grids_filter) + + if not states_schedule: + states_schedule, fail_to_comply, shd_trans_dict = dynamic_schedule_direct_illuminance( + results, grids_filter=grids_filter, use_states=True) + else: + raise NotImplementedError( + 'Custom input for argument states_schedule is not yet implemented.' + ) + + # check to see if there is a HBJSON with sensor grid meshes for areas + grid_areas, units_conversion = [], 1 + for base_file in Path(results.folder).parent.iterdir(): + if base_file.suffix in ('.hbjson', '.hbpkl'): + hb_model = Model.from_file(base_file) + units_conversion = conversion_factor_to_meters(hb_model.units) + filt_grids = _filter_by_pattern( + hb_model.properties.radiance.sensor_grids, filter=grids_filter) + for s_grid in filt_grids: + if s_grid.mesh is not None: + grid_areas.append(s_grid.mesh.face_areas) + grid_areas = [np.array(grid) for grid in grid_areas] + break + if not grid_areas: + grid_areas = [None] * len(grids_info) + + # spatial daylight autonomy + l06_da_grids = [] + l06_pass_sda_grids = [] + l06_pass_sda_blinds_up_grids = [] + l06_pass_sda_blinds_down_grids = [] + l01_da_grids = [] + l01_pass_sda_grids = [] + l01_pass_sda_blinds_up_grids = [] + l01_pass_sda_blinds_down_grids = [] + for grid_info in grids_info: + light_paths = [] + for lp in grid_info['light_path']: + for _lp in lp: + if _lp == '__static_apertures__' and len(lp) > 1: + pass + else: + light_paths.append(_lp) + base_zero_array = np.apply_along_axis(filter_array, 1, np.zeros( + (grid_info['count'], len(results.sun_up_hours))), occ_mask) + arrays_blinds_up = [base_zero_array.copy()] + arrays_blinds_down = [base_zero_array.copy()] + # combine total array for all light paths + array = results._array_from_states(grid_info, states=states_schedule, zero_array=True) + array = np.apply_along_axis(filter_array, 1, array, occ_mask) + + for light_path in light_paths: + # do an extra pass to calculate with blinds always up or down + if light_path != '__static_apertures__': + array_blinds_up = results._get_array( + grid_info, light_path, state=0, res_type='total') + array_filter = np.apply_along_axis( + filter_array, 1, array_blinds_up, occ_mask) + arrays_blinds_up.append(array_filter) + array_blinds_down = results._get_array( + grid_info, light_path, state=1, res_type='total') + array_filter = np.apply_along_axis( + filter_array, 1, array_blinds_down, occ_mask) + arrays_blinds_down.append(array_filter) + else: + static_array = results._get_array( + grid_info, light_path, state=0, res_type='total') + array_filter = np.apply_along_axis( + filter_array, 1, static_array, occ_mask) + arrays_blinds_up.append(array_filter) + arrays_blinds_down.append(array_filter) + + array_blinds_up = sum(arrays_blinds_up) + array_blinds_down = sum(arrays_blinds_down) + # calculate da per grid + da_grid = da_array2d(array, total_occ=total_occ, threshold=300) + + l06_da_grids.append(da_grid) + da_blinds_up_grid = da_array2d( + array_blinds_up, total_occ=total_occ, threshold=300) + da_blinds_down_grid = da_array2d( + array_blinds_down, total_occ=total_occ, threshold=300) + # calculate sda per grid + l06_pass_sda_grids.append(da_grid >= 50) + l06_pass_sda_blinds_up_grids.append(da_blinds_up_grid >= 50) + l06_pass_sda_blinds_down_grids.append(da_blinds_down_grid >= 50) + + array_blinds_up = sum(arrays_blinds_up) + array_blinds_down = sum(arrays_blinds_down) + # calculate da per grid + da_grid = da_array2d(array, total_occ=total_occ, threshold=200) + + l01_da_grids.append(da_grid) + da_blinds_up_grid = da_array2d( + array_blinds_up, total_occ=total_occ, threshold=200) + da_blinds_down_grid = da_array2d( + array_blinds_down, total_occ=total_occ, threshold=200) + # calculate sda per grid + l01_pass_sda_grids.append(da_grid >= 40) + l01_pass_sda_blinds_up_grids.append(da_blinds_up_grid >= 40) + l01_pass_sda_blinds_down_grids.append(da_blinds_down_grid >= 40) + + # create summaries for all grids and each grid individually + l06_ies_lm_summary, l06_ies_lm_summary_grid = _well_summary( + l06_pass_sda_grids, grids_info, grid_areas, + l06_pass_sda_blinds_up_grids, l06_pass_sda_blinds_down_grids) + l01_ies_lm_summary, l01_ies_lm_summary_grid = _well_summary( + l01_pass_sda_grids, grids_info, grid_areas, + l01_pass_sda_blinds_up_grids, l01_pass_sda_blinds_down_grids) + + sub_folder = Path(sub_folder) + en17037_folder = en17037_to_folder( + results, schedule=daylight_hours, + sub_folder=sub_folder.joinpath('en17037')) + + l06_well_summary = [] + l01_well_summary = [] + l06_well_summary_ies_lm = {} + l06_well_summary_en17037 = {} + l01_well_summary_ies_lm = {} + l01_well_summary_en17037 = {} + l06_well_summary_ies_lm['method'] = 'IES LM-83-12' + l06_well_summary_en17037['method'] = 'EN 17037' + l01_well_summary_ies_lm['method'] = 'IES LM-83-12' + l01_well_summary_en17037['method'] = 'EN 17037' + + l06_combined_da_target = [] + l06_combined_da_minimum = [] + l01_combined_da_target = [] + for grid_info in grids_info: + l06_grid_da_target = np.loadtxt(en17037_folder.joinpath('da', 'target_illuminance_300', f'{grid_info["full_id"]}.da')) + l06_grid_da_minimum = np.loadtxt(en17037_folder.joinpath('da', 'minimum_illuminance_100', f'{grid_info["full_id"]}.da')) + l06_combined_da_target.append(l06_grid_da_target >= 50) + l06_combined_da_minimum.append(l06_grid_da_minimum >= 50) + + array = results._array_from_states( + grid_info, res_type='total', zero_array=True) + if np.any(array): + array = np.apply_along_axis( + filter_array, 1, array, occ_mask) + l01_grid_da_target = da_array2d(array, total_occ=4380, threshold=200) + l01_combined_da_target.append(l01_grid_da_target >= 50) + + l06_combined_sda_target_illuminance = np.concatenate(l06_combined_da_target).mean() * 100 + l06_combined_sda_minimum_illuminance = np.concatenate(l06_combined_da_minimum).mean() * 100 + + l01_combined_sda_target_illuminance = np.concatenate(l01_combined_da_target).mean() * 100 + + if l01_combined_sda_target_illuminance > 30: + l01_well_summary_en17037['comply'] = True + else: + l01_well_summary_en17037['comply'] = False + + if l06_combined_sda_target_illuminance > 50 and l06_combined_sda_minimum_illuminance > 95: + l06_well_summary_en17037['points'] = 2 + elif l06_combined_sda_target_illuminance > 50: + l06_well_summary_en17037['points'] = 1 + else: + l06_well_summary_en17037['points'] = 0 + + # credits + if not fail_to_comply: + if l06_ies_lm_summary['sda'] >= 75: + l06_ies_lm_summary['credits'] = 3 + l06_well_summary_ies_lm['points'] = 2 + elif l06_ies_lm_summary['sda'] >= 55: + l06_ies_lm_summary['credits'] = 2 + l06_well_summary_ies_lm['points'] = 1 + elif l06_ies_lm_summary['sda'] >= 40: + l06_ies_lm_summary['credits'] = 1 + l06_well_summary_ies_lm['points'] = 0 + else: + l06_ies_lm_summary['credits'] = 0 + l06_well_summary_ies_lm['points'] = 0 + + if all(grid_summary['sda'] >= 55 for grid_summary in l06_ies_lm_summary_grid.values()): + if l06_ies_lm_summary['credits'] <= 2: + l06_ies_lm_summary['credits'] += 1 + else: + l06_ies_lm_summary['credits'] = 'Exemplary performance' + + if l01_ies_lm_summary['sda'] >= 30: + l01_well_summary_ies_lm['comply'] = True + else: + l01_well_summary_ies_lm['comply'] = False + + l06_well_summary_ies_lm['sda'] = l06_ies_lm_summary['sda'] + l01_well_summary_ies_lm['sda'] = l01_ies_lm_summary['sda'] + else: + l06_ies_lm_summary['credits'] = 0 + fail_to_comply_rooms = ', '.join(list(fail_to_comply.keys())) + note = ( + '0 credits have been awarded. The following sensor grids have at ' + 'least one hour where 2% of the floor area receives direct ' + f'illuminance of 1000 lux or more: {fail_to_comply_rooms}.' + ) + l06_ies_lm_summary['note'] = note + l06_well_summary_ies_lm['points'] = 0 + + l01_ies_lm_summary['note'] = note + l01_well_summary_ies_lm['comply'] = False + + l06_well_summary_ies_lm['total_floor_area'] = sum(np.sum(arr) for arr in grid_areas) + l01_well_summary_ies_lm['total_floor_area'] = sum(np.sum(arr) for arr in grid_areas) + + # convert to datacollection + def to_datacollection(aperture_group: str, values: np.ndarray): + # convert values to 0 and 1 (0 = no shading, 1 = shading) + header = Header(data_type=GenericType(aperture_group, ''), unit='', + analysis_period=AnalysisPeriod()) + hourly_data = HourlyContinuousCollection(header=header, values=values) + return hourly_data.to_dict() + + states_schedule = {k:to_datacollection(k, v['schedule']) for k, v in states_schedule.to_dict().items()} + + ies_lm_folder = sub_folder.joinpath('ies_lm') + ies_lm_folder.mkdir(parents=True, exist_ok=True) + + l06_ies_lm_folder = ies_lm_folder.joinpath('l06_ies_lm_summary') + l01_ies_lm_folder = ies_lm_folder.joinpath('l01_ies_lm_summary') + + l06_ies_lm_folder.mkdir(parents=True, exist_ok=True) + l01_ies_lm_folder.mkdir(parents=True, exist_ok=True) + + ies_lm_summary_file = l06_ies_lm_folder.joinpath('ies_lm_summary.json') + ies_lm_summary_file.write_text(json.dumps(l06_ies_lm_summary, indent=2)) + ies_lm_summary_file = l01_ies_lm_folder.joinpath('ies_lm_summary.json') + ies_lm_summary_file.write_text(json.dumps(l01_ies_lm_summary, indent=2)) + + ies_lm_summary_grid_file = l06_ies_lm_folder.joinpath('ies_lm_summary_grid.json') + ies_lm_summary_grid_file.write_text(json.dumps(l06_ies_lm_summary_grid, indent=2)) + ies_lm_summary_grid_file = l01_ies_lm_folder.joinpath('ies_lm_summary_grid.json') + ies_lm_summary_grid_file.write_text(json.dumps(l01_ies_lm_summary_grid, indent=2)) + + states_schedule_file = l06_ies_lm_folder.joinpath('states_schedule.json') + states_schedule_file.write_text(json.dumps(states_schedule)) + states_schedule_file = l01_ies_lm_folder.joinpath('states_schedule.json') + states_schedule_file.write_text(json.dumps(states_schedule)) + + grids_info_file = l06_ies_lm_folder.joinpath('grids_info.json') + grids_info_file.write_text(json.dumps(grids_info, indent=2)) + grids_info_file = l01_ies_lm_folder.joinpath('grids_info.json') + grids_info_file.write_text(json.dumps(grids_info, indent=2)) + + for (da, grid_info) in \ + zip(l06_da_grids, grids_info): + grid_id = grid_info['full_id'] + da_file = l06_ies_lm_folder.joinpath('results', 'da', f'{grid_id}.da') + da_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(da_file, da, fmt='%.2f') + for (da, grid_info) in \ + zip(l01_da_grids, grids_info): + grid_id = grid_info['full_id'] + da_file = l01_ies_lm_folder.joinpath('results', 'da', f'{grid_id}.da') + da_file.parent.mkdir(parents=True, exist_ok=True) + np.savetxt(da_file, da, fmt='%.2f') + + da_grids_info_file = l06_ies_lm_folder.joinpath( + 'results', 'da', 'grids_info.json') + da_grids_info_file.write_text(json.dumps(grids_info, indent=2)) + da_grids_info_file = l01_ies_lm_folder.joinpath( + 'results', 'da', 'grids_info.json') + da_grids_info_file.write_text(json.dumps(grids_info, indent=2)) + + states_schedule_err_file = \ + l06_ies_lm_folder.joinpath('states_schedule_err.json') + states_schedule_err_file.write_text(json.dumps(fail_to_comply)) + states_schedule_err_file = \ + l01_ies_lm_folder.joinpath('states_schedule_err.json') + states_schedule_err_file.write_text(json.dumps(fail_to_comply)) + + l06_well_summary.append(l06_well_summary_ies_lm) + l06_well_summary.append(l06_well_summary_en17037) + well_summary_file = sub_folder.joinpath('l06_well_summary.json') + well_summary_file.write_text(json.dumps(l06_well_summary, indent=2)) + l01_well_summary.append(l01_well_summary_ies_lm) + l01_well_summary.append(l01_well_summary_en17037) + well_summary_file = sub_folder.joinpath('l01_well_summary.json') + well_summary_file.write_text(json.dumps(l01_well_summary, indent=2)) + + return (l06_well_summary, l01_well_summary, states_schedule, fail_to_comply, grids_info)
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/docs/_modules/index.html b/docs/_modules/index.html new file mode 100644 index 00000000..220e30bb --- /dev/null +++ b/docs/_modules/index.html @@ -0,0 +1,720 @@ + + + + + + + Overview: module code — honeybee-radiance-postprocess documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
+ + + \ No newline at end of file diff --git a/docs/_sources/cli/abnt.rst.txt b/docs/_sources/cli/abnt.rst.txt new file mode 100644 index 00000000..b059b52e --- /dev/null +++ b/docs/_sources/cli/abnt.rst.txt @@ -0,0 +1,6 @@ +abnt +==== + +.. click:: honeybee_radiance_postprocess.cli.abnt:abnt + :prog: honeybee-radiance-postprocess abnt + :show-nested: diff --git a/docs/_sources/cli/breeam.rst.txt b/docs/_sources/cli/breeam.rst.txt new file mode 100644 index 00000000..2c21fd3d --- /dev/null +++ b/docs/_sources/cli/breeam.rst.txt @@ -0,0 +1,6 @@ +breeam +====== + +.. click:: honeybee_radiance_postprocess.cli.breeam:breeam + :prog: honeybee-radiance-postprocess breeam + :show-nested: diff --git a/docs/_sources/cli/datacollection.rst.txt b/docs/_sources/cli/datacollection.rst.txt new file mode 100644 index 00000000..96d806bb --- /dev/null +++ b/docs/_sources/cli/datacollection.rst.txt @@ -0,0 +1,6 @@ +datacollection +============== + +.. click:: honeybee_radiance_postprocess.cli.datacollection:datacollection + :prog: honeybee-radiance-postprocess data-collection + :show-nested: diff --git a/docs/_sources/cli/grid.rst.txt b/docs/_sources/cli/grid.rst.txt new file mode 100644 index 00000000..14041523 --- /dev/null +++ b/docs/_sources/cli/grid.rst.txt @@ -0,0 +1,6 @@ +grid +==== + +.. click:: honeybee_radiance_postprocess.cli.grid:grid + :prog: honeybee-radiance-postprocess grid + :show-nested: diff --git a/docs/_sources/cli/index.rst.txt b/docs/_sources/cli/index.rst.txt new file mode 100644 index 00000000..112e4c6e --- /dev/null +++ b/docs/_sources/cli/index.rst.txt @@ -0,0 +1,23 @@ +CLI +=== + + +Commands +-------- +.. toctree:: + :maxdepth: 1 + + main + datacollection + mtxop + viewfactor + translate + grid + merge + leed + two_phase + well + breeam + postprocess + schedule + abnt diff --git a/docs/_sources/cli/leed.rst.txt b/docs/_sources/cli/leed.rst.txt new file mode 100644 index 00000000..f4c2e110 --- /dev/null +++ b/docs/_sources/cli/leed.rst.txt @@ -0,0 +1,6 @@ +leed +==== + +.. click:: honeybee_radiance_postprocess.cli.leed:leed + :prog: honeybee-radiance-postprocess leed + :show-nested: diff --git a/docs/_sources/cli/main.rst.txt b/docs/_sources/cli/main.rst.txt new file mode 100644 index 00000000..539de0d7 --- /dev/null +++ b/docs/_sources/cli/main.rst.txt @@ -0,0 +1,7 @@ +main +==== + +.. click:: honeybee_radiance_postprocess.cli.__init__:postprocess + :prog: honeybee-radiance-postprocess + :show-nested: + :commands: diff --git a/docs/_sources/cli/merge.rst.txt b/docs/_sources/cli/merge.rst.txt new file mode 100644 index 00000000..2d1e44bb --- /dev/null +++ b/docs/_sources/cli/merge.rst.txt @@ -0,0 +1,6 @@ +merge +===== + +.. click:: honeybee_radiance_postprocess.cli.merge:merge + :prog: honeybee-radiance-postprocess merge + :show-nested: diff --git a/docs/_sources/cli/mtxop.rst.txt b/docs/_sources/cli/mtxop.rst.txt new file mode 100644 index 00000000..a7e94b82 --- /dev/null +++ b/docs/_sources/cli/mtxop.rst.txt @@ -0,0 +1,6 @@ +mtxop +===== + +.. click:: honeybee_radiance_postprocess.cli.mtxop:mtxop + :prog: honeybee-radiance-postprocess mtxop + :show-nested: diff --git a/docs/_sources/cli/postprocess.rst.txt b/docs/_sources/cli/postprocess.rst.txt new file mode 100644 index 00000000..69cbfeb9 --- /dev/null +++ b/docs/_sources/cli/postprocess.rst.txt @@ -0,0 +1,6 @@ +postprocess +=========== + +.. click:: honeybee_radiance_postprocess.cli.postprocess:post_process + :prog: honeybee-radiance-postprocess post-process + :show-nested: diff --git a/docs/_sources/cli/schedule.rst.txt b/docs/_sources/cli/schedule.rst.txt new file mode 100644 index 00000000..51bcc163 --- /dev/null +++ b/docs/_sources/cli/schedule.rst.txt @@ -0,0 +1,6 @@ +schedule +======== + +.. click:: honeybee_radiance_postprocess.cli.schedule:schedule + :prog: honeybee-radiance-postprocess schedule + :show-nested: diff --git a/docs/_sources/cli/translate.rst.txt b/docs/_sources/cli/translate.rst.txt new file mode 100644 index 00000000..744adc85 --- /dev/null +++ b/docs/_sources/cli/translate.rst.txt @@ -0,0 +1,6 @@ +translate +========= + +.. click:: honeybee_radiance_postprocess.cli.translate:translate + :prog: honeybee-radiance-postprocess translate + :show-nested: diff --git a/docs/_sources/cli/two_phase.rst.txt b/docs/_sources/cli/two_phase.rst.txt new file mode 100644 index 00000000..8752f601 --- /dev/null +++ b/docs/_sources/cli/two_phase.rst.txt @@ -0,0 +1,6 @@ +two_phase +========= + +.. click:: honeybee_radiance_postprocess.cli.two_phase:two_phase + :prog: honeybee-radiance-postprocess two_phase + :show-nested: diff --git a/docs/_sources/cli/viewfactor.rst.txt b/docs/_sources/cli/viewfactor.rst.txt new file mode 100644 index 00000000..13077a88 --- /dev/null +++ b/docs/_sources/cli/viewfactor.rst.txt @@ -0,0 +1,6 @@ +viewfactor +========== + +.. click:: honeybee_radiance_postprocess.cli.viewfactor:view_factor + :prog: honeybee-radiance-postprocess view_factor + :show-nested: diff --git a/docs/_sources/cli/well.rst.txt b/docs/_sources/cli/well.rst.txt new file mode 100644 index 00000000..194b8474 --- /dev/null +++ b/docs/_sources/cli/well.rst.txt @@ -0,0 +1,6 @@ +well +==== + +.. click:: honeybee_radiance_postprocess.cli.well:well + :prog: honeybee-radiance-postprocess well + :show-nested: diff --git a/docs/_sources/honeybee_radiance_postprocess.annual.rst.txt b/docs/_sources/honeybee_radiance_postprocess.annual.rst.txt new file mode 100644 index 00000000..1470f683 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.annual.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.annual module +============================================= + +.. automodule:: honeybee_radiance_postprocess.annual + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.annualdaylight.rst.txt b/docs/_sources/honeybee_radiance_postprocess.annualdaylight.rst.txt new file mode 100644 index 00000000..f9465aa8 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.annualdaylight.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.annualdaylight module +===================================================== + +.. automodule:: honeybee_radiance_postprocess.annualdaylight + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.annualirradiance.rst.txt b/docs/_sources/honeybee_radiance_postprocess.annualirradiance.rst.txt new file mode 100644 index 00000000..b2867798 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.annualirradiance.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.annualirradiance module +======================================================= + +.. automodule:: honeybee_radiance_postprocess.annualirradiance + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.breeam.breeam.rst.txt b/docs/_sources/honeybee_radiance_postprocess.breeam.breeam.rst.txt new file mode 100644 index 00000000..a281c7a2 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.breeam.breeam.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.breeam.breeam module +==================================================== + +.. automodule:: honeybee_radiance_postprocess.breeam.breeam + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.breeam.rst.txt b/docs/_sources/honeybee_radiance_postprocess.breeam.rst.txt new file mode 100644 index 00000000..87d9afb9 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.breeam.rst.txt @@ -0,0 +1,18 @@ +honeybee\_radiance\_postprocess.breeam package +============================================== + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + honeybee_radiance_postprocess.breeam.breeam + +Module contents +--------------- + +.. automodule:: honeybee_radiance_postprocess.breeam + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.abnt.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.abnt.rst.txt new file mode 100644 index 00000000..6f0c8bb3 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.abnt.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.abnt module +=============================================== + +.. automodule:: honeybee_radiance_postprocess.cli.abnt + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.breeam.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.breeam.rst.txt new file mode 100644 index 00000000..2e2c2e60 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.breeam.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.breeam module +================================================= + +.. automodule:: honeybee_radiance_postprocess.cli.breeam + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.datacollection.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.datacollection.rst.txt new file mode 100644 index 00000000..5f1a6cc7 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.datacollection.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.datacollection module +========================================================= + +.. automodule:: honeybee_radiance_postprocess.cli.datacollection + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.grid.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.grid.rst.txt new file mode 100644 index 00000000..e9917eba --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.grid.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.grid module +=============================================== + +.. automodule:: honeybee_radiance_postprocess.cli.grid + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.leed.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.leed.rst.txt new file mode 100644 index 00000000..caff78ce --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.leed.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.leed module +=============================================== + +.. automodule:: honeybee_radiance_postprocess.cli.leed + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.merge.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.merge.rst.txt new file mode 100644 index 00000000..277e3cd8 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.merge.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.merge module +================================================ + +.. automodule:: honeybee_radiance_postprocess.cli.merge + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.mtxop.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.mtxop.rst.txt new file mode 100644 index 00000000..31dcf2c8 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.mtxop.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.mtxop module +================================================ + +.. automodule:: honeybee_radiance_postprocess.cli.mtxop + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.postprocess.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.postprocess.rst.txt new file mode 100644 index 00000000..8d3d9951 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.postprocess.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.postprocess module +====================================================== + +.. automodule:: honeybee_radiance_postprocess.cli.postprocess + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.rst.txt new file mode 100644 index 00000000..604097f6 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.rst.txt @@ -0,0 +1,31 @@ +honeybee\_radiance\_postprocess.cli package +=========================================== + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + honeybee_radiance_postprocess.cli.abnt + honeybee_radiance_postprocess.cli.breeam + honeybee_radiance_postprocess.cli.datacollection + honeybee_radiance_postprocess.cli.grid + honeybee_radiance_postprocess.cli.leed + honeybee_radiance_postprocess.cli.merge + honeybee_radiance_postprocess.cli.mtxop + honeybee_radiance_postprocess.cli.postprocess + honeybee_radiance_postprocess.cli.schedule + honeybee_radiance_postprocess.cli.translate + honeybee_radiance_postprocess.cli.two_phase + honeybee_radiance_postprocess.cli.util + honeybee_radiance_postprocess.cli.viewfactor + honeybee_radiance_postprocess.cli.well + +Module contents +--------------- + +.. automodule:: honeybee_radiance_postprocess.cli + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.schedule.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.schedule.rst.txt new file mode 100644 index 00000000..c36848bb --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.schedule.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.schedule module +=================================================== + +.. automodule:: honeybee_radiance_postprocess.cli.schedule + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.translate.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.translate.rst.txt new file mode 100644 index 00000000..88a9abbb --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.translate.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.translate module +==================================================== + +.. automodule:: honeybee_radiance_postprocess.cli.translate + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.two_phase.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.two_phase.rst.txt new file mode 100644 index 00000000..db290a1a --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.two_phase.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.two\_phase module +===================================================== + +.. automodule:: honeybee_radiance_postprocess.cli.two_phase + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.util.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.util.rst.txt new file mode 100644 index 00000000..b377af9b --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.util.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.util module +=============================================== + +.. automodule:: honeybee_radiance_postprocess.cli.util + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.viewfactor.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.viewfactor.rst.txt new file mode 100644 index 00000000..d18a70fc --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.viewfactor.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.viewfactor module +===================================================== + +.. automodule:: honeybee_radiance_postprocess.cli.viewfactor + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.cli.well.rst.txt b/docs/_sources/honeybee_radiance_postprocess.cli.well.rst.txt new file mode 100644 index 00000000..e00c095d --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.cli.well.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.cli.well module +=============================================== + +.. automodule:: honeybee_radiance_postprocess.cli.well + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.data_type.rst.txt b/docs/_sources/honeybee_radiance_postprocess.data_type.rst.txt new file mode 100644 index 00000000..74a158b3 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.data_type.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.data\_type module +================================================= + +.. automodule:: honeybee_radiance_postprocess.data_type + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.dynamic.rst.txt b/docs/_sources/honeybee_radiance_postprocess.dynamic.rst.txt new file mode 100644 index 00000000..fdd4345d --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.dynamic.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.dynamic module +============================================== + +.. automodule:: honeybee_radiance_postprocess.dynamic + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.electriclight.rst.txt b/docs/_sources/honeybee_radiance_postprocess.electriclight.rst.txt new file mode 100644 index 00000000..b29986b2 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.electriclight.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.electriclight module +==================================================== + +.. automodule:: honeybee_radiance_postprocess.electriclight + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.en17037.rst.txt b/docs/_sources/honeybee_radiance_postprocess.en17037.rst.txt new file mode 100644 index 00000000..cb046c11 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.en17037.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.en17037 module +============================================== + +.. automodule:: honeybee_radiance_postprocess.en17037 + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.helper.rst.txt b/docs/_sources/honeybee_radiance_postprocess.helper.rst.txt new file mode 100644 index 00000000..bff2aecc --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.helper.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.helper module +============================================= + +.. automodule:: honeybee_radiance_postprocess.helper + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.ies.lm.rst.txt b/docs/_sources/honeybee_radiance_postprocess.ies.lm.rst.txt new file mode 100644 index 00000000..941f92a3 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.ies.lm.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.ies.lm module +============================================= + +.. automodule:: honeybee_radiance_postprocess.ies.lm + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.ies.lm_schedule.rst.txt b/docs/_sources/honeybee_radiance_postprocess.ies.lm_schedule.rst.txt new file mode 100644 index 00000000..567a685a --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.ies.lm_schedule.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.ies.lm\_schedule module +======================================================= + +.. automodule:: honeybee_radiance_postprocess.ies.lm_schedule + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.ies.rst.txt b/docs/_sources/honeybee_radiance_postprocess.ies.rst.txt new file mode 100644 index 00000000..fac22806 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.ies.rst.txt @@ -0,0 +1,19 @@ +honeybee\_radiance\_postprocess.ies package +=========================================== + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + honeybee_radiance_postprocess.ies.lm + honeybee_radiance_postprocess.ies.lm_schedule + +Module contents +--------------- + +.. automodule:: honeybee_radiance_postprocess.ies + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.leed.leed.rst.txt b/docs/_sources/honeybee_radiance_postprocess.leed.leed.rst.txt new file mode 100644 index 00000000..30ff59e0 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.leed.leed.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.leed.leed module +================================================ + +.. automodule:: honeybee_radiance_postprocess.leed.leed + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.leed.leed_schedule.rst.txt b/docs/_sources/honeybee_radiance_postprocess.leed.leed_schedule.rst.txt new file mode 100644 index 00000000..575ccadc --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.leed.leed_schedule.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.leed.leed\_schedule module +========================================================== + +.. automodule:: honeybee_radiance_postprocess.leed.leed_schedule + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.leed.rst.txt b/docs/_sources/honeybee_radiance_postprocess.leed.rst.txt new file mode 100644 index 00000000..20b03627 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.leed.rst.txt @@ -0,0 +1,19 @@ +honeybee\_radiance\_postprocess.leed package +============================================ + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + honeybee_radiance_postprocess.leed.leed + honeybee_radiance_postprocess.leed.leed_schedule + +Module contents +--------------- + +.. automodule:: honeybee_radiance_postprocess.leed + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.metrics.rst.txt b/docs/_sources/honeybee_radiance_postprocess.metrics.rst.txt new file mode 100644 index 00000000..35d23c07 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.metrics.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.metrics module +============================================== + +.. automodule:: honeybee_radiance_postprocess.metrics + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.reader.rst.txt b/docs/_sources/honeybee_radiance_postprocess.reader.rst.txt new file mode 100644 index 00000000..51418cdd --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.reader.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.reader module +============================================= + +.. automodule:: honeybee_radiance_postprocess.reader + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.results.annual_daylight.rst.txt b/docs/_sources/honeybee_radiance_postprocess.results.annual_daylight.rst.txt new file mode 100644 index 00000000..afb1ef85 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.results.annual_daylight.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.results.annual\_daylight module +=============================================================== + +.. automodule:: honeybee_radiance_postprocess.results.annual_daylight + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.results.annual_irradiance.rst.txt b/docs/_sources/honeybee_radiance_postprocess.results.annual_irradiance.rst.txt new file mode 100644 index 00000000..cd611c9a --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.results.annual_irradiance.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.results.annual\_irradiance module +================================================================= + +.. automodule:: honeybee_radiance_postprocess.results.annual_irradiance + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.results.results.rst.txt b/docs/_sources/honeybee_radiance_postprocess.results.results.rst.txt new file mode 100644 index 00000000..ef6e19e2 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.results.results.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.results.results module +====================================================== + +.. automodule:: honeybee_radiance_postprocess.results.results + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.results.rst.txt b/docs/_sources/honeybee_radiance_postprocess.results.rst.txt new file mode 100644 index 00000000..591fd302 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.results.rst.txt @@ -0,0 +1,20 @@ +honeybee\_radiance\_postprocess.results package +=============================================== + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + honeybee_radiance_postprocess.results.annual_daylight + honeybee_radiance_postprocess.results.annual_irradiance + honeybee_radiance_postprocess.results.results + +Module contents +--------------- + +.. automodule:: honeybee_radiance_postprocess.results + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.rst.txt b/docs/_sources/honeybee_radiance_postprocess.rst.txt new file mode 100644 index 00000000..444c76bd --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.rst.txt @@ -0,0 +1,43 @@ +honeybee\_radiance\_postprocess package +======================================= + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + honeybee_radiance_postprocess.breeam + honeybee_radiance_postprocess.cli + honeybee_radiance_postprocess.ies + honeybee_radiance_postprocess.leed + honeybee_radiance_postprocess.results + honeybee_radiance_postprocess.well + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + honeybee_radiance_postprocess.annual + honeybee_radiance_postprocess.annualdaylight + honeybee_radiance_postprocess.annualirradiance + honeybee_radiance_postprocess.data_type + honeybee_radiance_postprocess.dynamic + honeybee_radiance_postprocess.electriclight + honeybee_radiance_postprocess.en17037 + honeybee_radiance_postprocess.helper + honeybee_radiance_postprocess.metrics + honeybee_radiance_postprocess.reader + honeybee_radiance_postprocess.type_hints + honeybee_radiance_postprocess.util + honeybee_radiance_postprocess.vis_metadata + +Module contents +--------------- + +.. automodule:: honeybee_radiance_postprocess + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.type_hints.rst.txt b/docs/_sources/honeybee_radiance_postprocess.type_hints.rst.txt new file mode 100644 index 00000000..2fa33c3f --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.type_hints.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.type\_hints module +================================================== + +.. automodule:: honeybee_radiance_postprocess.type_hints + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.util.rst.txt b/docs/_sources/honeybee_radiance_postprocess.util.rst.txt new file mode 100644 index 00000000..e825aa86 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.util.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.util module +=========================================== + +.. automodule:: honeybee_radiance_postprocess.util + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.vis_metadata.rst.txt b/docs/_sources/honeybee_radiance_postprocess.vis_metadata.rst.txt new file mode 100644 index 00000000..97e5d117 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.vis_metadata.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.vis\_metadata module +==================================================== + +.. automodule:: honeybee_radiance_postprocess.vis_metadata + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.well.rst.txt b/docs/_sources/honeybee_radiance_postprocess.well.rst.txt new file mode 100644 index 00000000..bd8ead5a --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.well.rst.txt @@ -0,0 +1,18 @@ +honeybee\_radiance\_postprocess.well package +============================================ + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + honeybee_radiance_postprocess.well.well + +Module contents +--------------- + +.. automodule:: honeybee_radiance_postprocess.well + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee_radiance_postprocess.well.well.rst.txt b/docs/_sources/honeybee_radiance_postprocess.well.well.rst.txt new file mode 100644 index 00000000..c9a14c82 --- /dev/null +++ b/docs/_sources/honeybee_radiance_postprocess.well.well.rst.txt @@ -0,0 +1,7 @@ +honeybee\_radiance\_postprocess.well.well module +================================================ + +.. automodule:: honeybee_radiance_postprocess.well.well + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/index.rst.txt b/docs/_sources/index.rst.txt new file mode 100644 index 00000000..7f4ac0a0 --- /dev/null +++ b/docs/_sources/index.rst.txt @@ -0,0 +1,27 @@ +Welcome to honeybee-radiance-postprocess's documentation! +=================================== + +CLI Docs +======== + +For command line interface documentation and API documentation see the pages below. + +.. toctree:: + :maxdepth: 2 + + cli//index + + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + +.. include:: modules.rst + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/_sources/modules.rst.txt b/docs/_sources/modules.rst.txt new file mode 100644 index 00000000..1e1cbf50 --- /dev/null +++ b/docs/_sources/modules.rst.txt @@ -0,0 +1,7 @@ +honeybee_radiance_postprocess +============================= + +.. toctree:: + :maxdepth: 4 + + honeybee_radiance_postprocess diff --git a/docs/_static/basic.css b/docs/_static/basic.css new file mode 100644 index 00000000..f316efcb --- /dev/null +++ b/docs/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.css b/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.css new file mode 100644 index 00000000..09e88ce3 --- /dev/null +++ b/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.css @@ -0,0 +1,1109 @@ +/*! + * Bootstrap Responsive v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +@-ms-viewport { + width: device-width; +} + +.hidden { + display: none; + visibility: hidden; +} + +.visible-phone { + display: none !important; +} + +.visible-tablet { + display: none !important; +} + +.hidden-desktop { + display: none !important; +} + +.visible-desktop { + display: inherit !important; +} + +@media (min-width: 768px) and (max-width: 979px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important ; + } + .visible-tablet { + display: inherit !important; + } + .hidden-tablet { + display: none !important; + } +} + +@media (max-width: 767px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important; + } + .visible-phone { + display: inherit !important; + } + .hidden-phone { + display: none !important; + } +} + +.visible-print { + display: none !important; +} + +@media print { + .visible-print { + display: inherit !important; + } + .hidden-print { + display: none !important; + } +} + +@media (min-width: 1200px) { + .row { + margin-left: -30px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 30px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 1170px; + } + .span12 { + width: 1170px; + } + .span11 { + width: 1070px; + } + .span10 { + width: 970px; + } + .span9 { + width: 870px; + } + .span8 { + width: 770px; + } + .span7 { + width: 670px; + } + .span6 { + width: 570px; + } + .span5 { + width: 470px; + } + .span4 { + width: 370px; + } + .span3 { + width: 270px; + } + .span2 { + width: 170px; + } + .span1 { + width: 70px; + } + .offset12 { + margin-left: 1230px; + } + .offset11 { + margin-left: 1130px; + } + .offset10 { + margin-left: 1030px; + } + .offset9 { + margin-left: 930px; + } + .offset8 { + margin-left: 830px; + } + .offset7 { + margin-left: 730px; + } + .offset6 { + margin-left: 630px; + } + .offset5 { + margin-left: 530px; + } + .offset4 { + margin-left: 430px; + } + .offset3 { + margin-left: 330px; + } + .offset2 { + margin-left: 230px; + } + .offset1 { + margin-left: 130px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.564102564102564%; + *margin-left: 2.5109110747408616%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.564102564102564%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + .row-fluid .span11 { + width: 91.45299145299145%; + *width: 91.39979996362975%; + } + .row-fluid .span10 { + width: 82.90598290598291%; + *width: 82.8527914166212%; + } + .row-fluid .span9 { + width: 74.35897435897436%; + *width: 74.30578286961266%; + } + .row-fluid .span8 { + width: 65.81196581196582%; + *width: 65.75877432260411%; + } + .row-fluid .span7 { + width: 57.26495726495726%; + *width: 57.21176577559556%; + } + .row-fluid .span6 { + width: 48.717948717948715%; + *width: 48.664757228587014%; + } + .row-fluid .span5 { + width: 40.17094017094017%; + *width: 40.11774868157847%; + } + .row-fluid .span4 { + width: 31.623931623931625%; + *width: 31.570740134569924%; + } + .row-fluid .span3 { + width: 23.076923076923077%; + *width: 23.023731587561375%; + } + .row-fluid .span2 { + width: 14.52991452991453%; + *width: 14.476723040552828%; + } + .row-fluid .span1 { + width: 5.982905982905983%; + *width: 5.929714493544281%; + } + .row-fluid .offset12 { + margin-left: 105.12820512820512%; + *margin-left: 105.02182214948171%; + } + .row-fluid .offset12:first-child { + margin-left: 102.56410256410257%; + *margin-left: 102.45771958537915%; + } + .row-fluid .offset11 { + margin-left: 96.58119658119658%; + *margin-left: 96.47481360247316%; + } + .row-fluid .offset11:first-child { + margin-left: 94.01709401709402%; + *margin-left: 93.91071103837061%; + } + .row-fluid .offset10 { + margin-left: 88.03418803418803%; + *margin-left: 87.92780505546462%; + } + .row-fluid .offset10:first-child { + margin-left: 85.47008547008548%; + *margin-left: 85.36370249136206%; + } + .row-fluid .offset9 { + margin-left: 79.48717948717949%; + *margin-left: 79.38079650845607%; + } + .row-fluid .offset9:first-child { + margin-left: 76.92307692307693%; + *margin-left: 76.81669394435352%; + } + .row-fluid .offset8 { + margin-left: 70.94017094017094%; + *margin-left: 70.83378796144753%; + } + .row-fluid .offset8:first-child { + margin-left: 68.37606837606839%; + *margin-left: 68.26968539734497%; + } + .row-fluid .offset7 { + margin-left: 62.393162393162385%; + *margin-left: 62.28677941443899%; + } + .row-fluid .offset7:first-child { + margin-left: 59.82905982905982%; + *margin-left: 59.72267685033642%; + } + .row-fluid .offset6 { + margin-left: 53.84615384615384%; + *margin-left: 53.739770867430444%; + } + .row-fluid .offset6:first-child { + margin-left: 51.28205128205128%; + *margin-left: 51.175668303327875%; + } + .row-fluid .offset5 { + margin-left: 45.299145299145295%; + *margin-left: 45.1927623204219%; + } + .row-fluid .offset5:first-child { + margin-left: 42.73504273504273%; + *margin-left: 42.62865975631933%; + } + .row-fluid .offset4 { + margin-left: 36.75213675213675%; + *margin-left: 36.645753773413354%; + } + .row-fluid .offset4:first-child { + margin-left: 34.18803418803419%; + *margin-left: 34.081651209310785%; + } + .row-fluid .offset3 { + margin-left: 28.205128205128204%; + *margin-left: 28.0987452264048%; + } + .row-fluid .offset3:first-child { + margin-left: 25.641025641025642%; + *margin-left: 25.53464266230224%; + } + .row-fluid .offset2 { + margin-left: 19.65811965811966%; + *margin-left: 19.551736679396257%; + } + .row-fluid .offset2:first-child { + margin-left: 17.094017094017094%; + *margin-left: 16.98763411529369%; + } + .row-fluid .offset1 { + margin-left: 11.11111111111111%; + *margin-left: 11.004728132387708%; + } + .row-fluid .offset1:first-child { + margin-left: 8.547008547008547%; + *margin-left: 8.440625568285142%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 30px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 1156px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 1056px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 956px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 856px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 756px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 656px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 556px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 456px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 356px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 256px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 156px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 56px; + } + .thumbnails { + margin-left: -30px; + } + .thumbnails > li { + margin-left: 30px; + } + .row-fluid .thumbnails { + margin-left: 0; + } +} + +@media (min-width: 768px) and (max-width: 979px) { + .row { + margin-left: -20px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 724px; + } + .span12 { + width: 724px; + } + .span11 { + width: 662px; + } + .span10 { + width: 600px; + } + .span9 { + width: 538px; + } + .span8 { + width: 476px; + } + .span7 { + width: 414px; + } + .span6 { + width: 352px; + } + .span5 { + width: 290px; + } + .span4 { + width: 228px; + } + .span3 { + width: 166px; + } + .span2 { + width: 104px; + } + .span1 { + width: 42px; + } + .offset12 { + margin-left: 764px; + } + .offset11 { + margin-left: 702px; + } + .offset10 { + margin-left: 640px; + } + .offset9 { + margin-left: 578px; + } + .offset8 { + margin-left: 516px; + } + .offset7 { + margin-left: 454px; + } + .offset6 { + margin-left: 392px; + } + .offset5 { + margin-left: 330px; + } + .offset4 { + margin-left: 268px; + } + .offset3 { + margin-left: 206px; + } + .offset2 { + margin-left: 144px; + } + .offset1 { + margin-left: 82px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.7624309392265194%; + *margin-left: 2.709239449864817%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.7624309392265194%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + .row-fluid .span11 { + width: 91.43646408839778%; + *width: 91.38327259903608%; + } + .row-fluid .span10 { + width: 82.87292817679558%; + *width: 82.81973668743387%; + } + .row-fluid .span9 { + width: 74.30939226519337%; + *width: 74.25620077583166%; + } + .row-fluid .span8 { + width: 65.74585635359117%; + *width: 65.69266486422946%; + } + .row-fluid .span7 { + width: 57.18232044198895%; + *width: 57.12912895262725%; + } + .row-fluid .span6 { + width: 48.61878453038674%; + *width: 48.56559304102504%; + } + .row-fluid .span5 { + width: 40.05524861878453%; + *width: 40.00205712942283%; + } + .row-fluid .span4 { + width: 31.491712707182323%; + *width: 31.43852121782062%; + } + .row-fluid .span3 { + width: 22.92817679558011%; + *width: 22.87498530621841%; + } + .row-fluid .span2 { + width: 14.3646408839779%; + *width: 14.311449394616199%; + } + .row-fluid .span1 { + width: 5.801104972375691%; + *width: 5.747913483013988%; + } + .row-fluid .offset12 { + margin-left: 105.52486187845304%; + *margin-left: 105.41847889972962%; + } + .row-fluid .offset12:first-child { + margin-left: 102.76243093922652%; + *margin-left: 102.6560479605031%; + } + .row-fluid .offset11 { + margin-left: 96.96132596685082%; + *margin-left: 96.8549429881274%; + } + .row-fluid .offset11:first-child { + margin-left: 94.1988950276243%; + *margin-left: 94.09251204890089%; + } + .row-fluid .offset10 { + margin-left: 88.39779005524862%; + *margin-left: 88.2914070765252%; + } + .row-fluid .offset10:first-child { + margin-left: 85.6353591160221%; + *margin-left: 85.52897613729868%; + } + .row-fluid .offset9 { + margin-left: 79.8342541436464%; + *margin-left: 79.72787116492299%; + } + .row-fluid .offset9:first-child { + margin-left: 77.07182320441989%; + *margin-left: 76.96544022569647%; + } + .row-fluid .offset8 { + margin-left: 71.2707182320442%; + *margin-left: 71.16433525332079%; + } + .row-fluid .offset8:first-child { + margin-left: 68.50828729281768%; + *margin-left: 68.40190431409427%; + } + .row-fluid .offset7 { + margin-left: 62.70718232044199%; + *margin-left: 62.600799341718584%; + } + .row-fluid .offset7:first-child { + margin-left: 59.94475138121547%; + *margin-left: 59.838368402492065%; + } + .row-fluid .offset6 { + margin-left: 54.14364640883978%; + *margin-left: 54.037263430116376%; + } + .row-fluid .offset6:first-child { + margin-left: 51.38121546961326%; + *margin-left: 51.27483249088986%; + } + .row-fluid .offset5 { + margin-left: 45.58011049723757%; + *margin-left: 45.47372751851417%; + } + .row-fluid .offset5:first-child { + margin-left: 42.81767955801105%; + *margin-left: 42.71129657928765%; + } + .row-fluid .offset4 { + margin-left: 37.01657458563536%; + *margin-left: 36.91019160691196%; + } + .row-fluid .offset4:first-child { + margin-left: 34.25414364640884%; + *margin-left: 34.14776066768544%; + } + .row-fluid .offset3 { + margin-left: 28.45303867403315%; + *margin-left: 28.346655695309746%; + } + .row-fluid .offset3:first-child { + margin-left: 25.69060773480663%; + *margin-left: 25.584224756083227%; + } + .row-fluid .offset2 { + margin-left: 19.88950276243094%; + *margin-left: 19.783119783707537%; + } + .row-fluid .offset2:first-child { + margin-left: 17.12707182320442%; + *margin-left: 17.02068884448102%; + } + .row-fluid .offset1 { + margin-left: 11.32596685082873%; + *margin-left: 11.219583872105325%; + } + .row-fluid .offset1:first-child { + margin-left: 8.56353591160221%; + *margin-left: 8.457152932878806%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 710px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 648px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 586px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 524px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 462px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 400px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 338px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 276px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 214px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 152px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 90px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 28px; + } +} + +@media (max-width: 767px) { + body { + padding-right: 20px; + padding-left: 20px; + } + .navbar-fixed-top, + .navbar-fixed-bottom, + .navbar-static-top { + margin-right: -20px; + margin-left: -20px; + } + .container-fluid { + padding: 0; + } + .dl-horizontal dt { + float: none; + width: auto; + clear: none; + text-align: left; + } + .dl-horizontal dd { + margin-left: 0; + } + .container { + width: auto; + } + .row-fluid { + width: 100%; + } + .row, + .thumbnails { + margin-left: 0; + } + .thumbnails > li { + float: none; + margin-left: 0; + } + [class*="span"], + .uneditable-input[class*="span"], + .row-fluid [class*="span"] { + display: block; + float: none; + width: 100%; + margin-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .span12, + .row-fluid .span12 { + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="offset"]:first-child { + margin-left: 0; + } + .input-large, + .input-xlarge, + .input-xxlarge, + input[class*="span"], + select[class*="span"], + textarea[class*="span"], + .uneditable-input { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .input-prepend input, + .input-append input, + .input-prepend input[class*="span"], + .input-append input[class*="span"] { + display: inline-block; + width: auto; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 0; + } + .modal { + position: fixed; + top: 20px; + right: 20px; + left: 20px; + width: auto; + margin: 0; + } + .modal.fade { + top: -100px; + } + .modal.fade.in { + top: 20px; + } +} + +@media (max-width: 480px) { + .nav-collapse { + -webkit-transform: translate3d(0, 0, 0); + } + .page-header h1 small { + display: block; + line-height: 20px; + } + input[type="checkbox"], + input[type="radio"] { + border: 1px solid #ccc; + } + .form-horizontal .control-label { + float: none; + width: auto; + padding-top: 0; + text-align: left; + } + .form-horizontal .controls { + margin-left: 0; + } + .form-horizontal .control-list { + padding-top: 0; + } + .form-horizontal .form-actions { + padding-right: 10px; + padding-left: 10px; + } + .media .pull-left, + .media .pull-right { + display: block; + float: none; + margin-bottom: 10px; + } + .media-object { + margin-right: 0; + margin-left: 0; + } + .modal { + top: 10px; + right: 10px; + left: 10px; + } + .modal-header .close { + padding: 10px; + margin: -10px; + } + .carousel-caption { + position: static; + } +} + +@media (max-width: 979px) { + body { + padding-top: 0; + } + .navbar-fixed-top, + .navbar-fixed-bottom { + position: static; + } + .navbar-fixed-top { + margin-bottom: 20px; + } + .navbar-fixed-bottom { + margin-top: 20px; + } + .navbar-fixed-top .navbar-inner, + .navbar-fixed-bottom .navbar-inner { + padding: 5px; + } + .navbar .container { + width: auto; + padding: 0; + } + .navbar .brand { + padding-right: 10px; + padding-left: 10px; + margin: 0 0 0 -5px; + } + .nav-collapse { + clear: both; + } + .nav-collapse .nav { + float: none; + margin: 0 0 10px; + } + .nav-collapse .nav > li { + float: none; + } + .nav-collapse .nav > li > a { + margin-bottom: 2px; + } + .nav-collapse .nav > .divider-vertical { + display: none; + } + .nav-collapse .nav .nav-header { + color: #777777; + text-shadow: none; + } + .nav-collapse .nav > li > a, + .nav-collapse .dropdown-menu a { + padding: 9px 15px; + font-weight: bold; + color: #777777; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + } + .nav-collapse .btn { + padding: 4px 10px 4px; + font-weight: normal; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + } + .nav-collapse .dropdown-menu li + li a { + margin-bottom: 2px; + } + .nav-collapse .nav > li > a:hover, + .nav-collapse .nav > li > a:focus, + .nav-collapse .dropdown-menu a:hover, + .nav-collapse .dropdown-menu a:focus { + background-color: #f2f2f2; + } + .navbar-inverse .nav-collapse .nav > li > a, + .navbar-inverse .nav-collapse .dropdown-menu a { + color: #999999; + } + .navbar-inverse .nav-collapse .nav > li > a:hover, + .navbar-inverse .nav-collapse .nav > li > a:focus, + .navbar-inverse .nav-collapse .dropdown-menu a:hover, + .navbar-inverse .nav-collapse .dropdown-menu a:focus { + background-color: #111111; + } + .nav-collapse.in .btn-group { + padding: 0; + margin-top: 5px; + } + .nav-collapse .dropdown-menu { + position: static; + top: auto; + left: auto; + display: none; + float: none; + max-width: none; + padding: 0; + margin: 0 15px; + background-color: transparent; + border: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + .nav-collapse .open > .dropdown-menu { + display: block; + } + .nav-collapse .dropdown-menu:before, + .nav-collapse .dropdown-menu:after { + display: none; + } + .nav-collapse .dropdown-menu .divider { + display: none; + } + .nav-collapse .nav > li > .dropdown-menu:before, + .nav-collapse .nav > li > .dropdown-menu:after { + display: none; + } + .nav-collapse .navbar-form, + .nav-collapse .navbar-search { + float: none; + padding: 10px 15px; + margin: 10px 0; + border-top: 1px solid #f2f2f2; + border-bottom: 1px solid #f2f2f2; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + } + .navbar-inverse .nav-collapse .navbar-form, + .navbar-inverse .nav-collapse .navbar-search { + border-top-color: #111111; + border-bottom-color: #111111; + } + .navbar .nav-collapse .nav.pull-right { + float: none; + margin-left: 0; + } + .nav-collapse, + .nav-collapse.collapse { + height: 0; + overflow: hidden; + } + .navbar .btn-navbar { + display: block; + } + .navbar-static .navbar-inner { + padding-right: 10px; + padding-left: 10px; + } +} + +@media (min-width: 980px) { + .nav-collapse.collapse { + height: auto !important; + overflow: visible !important; + } +} diff --git a/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.min.css b/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.min.css new file mode 100644 index 00000000..f4ede63f --- /dev/null +++ b/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap Responsive v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} diff --git a/docs/_static/bootstrap-2.3.2/css/bootstrap.css b/docs/_static/bootstrap-2.3.2/css/bootstrap.css new file mode 100644 index 00000000..b725064a --- /dev/null +++ b/docs/_static/bootstrap-2.3.2/css/bootstrap.css @@ -0,0 +1,6167 @@ +/*! + * Bootstrap v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +a:hover, +a:active { + outline: 0; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + width: auto\9; + height: auto; + max-width: 100%; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; +} + +#map_canvas img, +.google-maps img { + max-width: none; +} + +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle; +} + +button, +input { + *overflow: visible; + line-height: normal; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} + +label, +select, +button, +input[type="button"], +input[type="reset"], +input[type="submit"], +input[type="radio"], +input[type="checkbox"] { + cursor: pointer; +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} + +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + @page { + margin: 0.5cm; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } +} + +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + color: #333333; + background-color: #ffffff; +} + +a { + color: #0088cc; + text-decoration: none; +} + +a:hover, +a:focus { + color: #005580; + text-decoration: underline; +} + +.img-rounded { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.img-polaroid { + padding: 4px; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.img-circle { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px; +} + +.row { + margin-left: -20px; + *zoom: 1; +} + +.row:before, +.row:after { + display: table; + line-height: 0; + content: ""; +} + +.row:after { + clear: both; +} + +[class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; +} + +.container, +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.span12 { + width: 940px; +} + +.span11 { + width: 860px; +} + +.span10 { + width: 780px; +} + +.span9 { + width: 700px; +} + +.span8 { + width: 620px; +} + +.span7 { + width: 540px; +} + +.span6 { + width: 460px; +} + +.span5 { + width: 380px; +} + +.span4 { + width: 300px; +} + +.span3 { + width: 220px; +} + +.span2 { + width: 140px; +} + +.span1 { + width: 60px; +} + +.offset12 { + margin-left: 980px; +} + +.offset11 { + margin-left: 900px; +} + +.offset10 { + margin-left: 820px; +} + +.offset9 { + margin-left: 740px; +} + +.offset8 { + margin-left: 660px; +} + +.offset7 { + margin-left: 580px; +} + +.offset6 { + margin-left: 500px; +} + +.offset5 { + margin-left: 420px; +} + +.offset4 { + margin-left: 340px; +} + +.offset3 { + margin-left: 260px; +} + +.offset2 { + margin-left: 180px; +} + +.offset1 { + margin-left: 100px; +} + +.row-fluid { + width: 100%; + *zoom: 1; +} + +.row-fluid:before, +.row-fluid:after { + display: table; + line-height: 0; + content: ""; +} + +.row-fluid:after { + clear: both; +} + +.row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.127659574468085%; + *margin-left: 2.074468085106383%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.row-fluid [class*="span"]:first-child { + margin-left: 0; +} + +.row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.127659574468085%; +} + +.row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; +} + +.row-fluid .span11 { + width: 91.48936170212765%; + *width: 91.43617021276594%; +} + +.row-fluid .span10 { + width: 82.97872340425532%; + *width: 82.92553191489361%; +} + +.row-fluid .span9 { + width: 74.46808510638297%; + *width: 74.41489361702126%; +} + +.row-fluid .span8 { + width: 65.95744680851064%; + *width: 65.90425531914893%; +} + +.row-fluid .span7 { + width: 57.44680851063829%; + *width: 57.39361702127659%; +} + +.row-fluid .span6 { + width: 48.93617021276595%; + *width: 48.88297872340425%; +} + +.row-fluid .span5 { + width: 40.42553191489362%; + *width: 40.37234042553192%; +} + +.row-fluid .span4 { + width: 31.914893617021278%; + *width: 31.861702127659576%; +} + +.row-fluid .span3 { + width: 23.404255319148934%; + *width: 23.351063829787233%; +} + +.row-fluid .span2 { + width: 14.893617021276595%; + *width: 14.840425531914894%; +} + +.row-fluid .span1 { + width: 6.382978723404255%; + *width: 6.329787234042553%; +} + +.row-fluid .offset12 { + margin-left: 104.25531914893617%; + *margin-left: 104.14893617021275%; +} + +.row-fluid .offset12:first-child { + margin-left: 102.12765957446808%; + *margin-left: 102.02127659574467%; +} + +.row-fluid .offset11 { + margin-left: 95.74468085106382%; + *margin-left: 95.6382978723404%; +} + +.row-fluid .offset11:first-child { + margin-left: 93.61702127659574%; + *margin-left: 93.51063829787232%; +} + +.row-fluid .offset10 { + margin-left: 87.23404255319149%; + *margin-left: 87.12765957446807%; +} + +.row-fluid .offset10:first-child { + margin-left: 85.1063829787234%; + *margin-left: 84.99999999999999%; +} + +.row-fluid .offset9 { + margin-left: 78.72340425531914%; + *margin-left: 78.61702127659572%; +} + +.row-fluid .offset9:first-child { + margin-left: 76.59574468085106%; + *margin-left: 76.48936170212764%; +} + +.row-fluid .offset8 { + margin-left: 70.2127659574468%; + *margin-left: 70.10638297872339%; +} + +.row-fluid .offset8:first-child { + margin-left: 68.08510638297872%; + *margin-left: 67.9787234042553%; +} + +.row-fluid .offset7 { + margin-left: 61.70212765957446%; + *margin-left: 61.59574468085106%; +} + +.row-fluid .offset7:first-child { + margin-left: 59.574468085106375%; + *margin-left: 59.46808510638297%; +} + +.row-fluid .offset6 { + margin-left: 53.191489361702125%; + *margin-left: 53.085106382978715%; +} + +.row-fluid .offset6:first-child { + margin-left: 51.063829787234035%; + *margin-left: 50.95744680851063%; +} + +.row-fluid .offset5 { + margin-left: 44.68085106382979%; + *margin-left: 44.57446808510638%; +} + +.row-fluid .offset5:first-child { + margin-left: 42.5531914893617%; + *margin-left: 42.4468085106383%; +} + +.row-fluid .offset4 { + margin-left: 36.170212765957444%; + *margin-left: 36.06382978723405%; +} + +.row-fluid .offset4:first-child { + margin-left: 34.04255319148936%; + *margin-left: 33.93617021276596%; +} + +.row-fluid .offset3 { + margin-left: 27.659574468085104%; + *margin-left: 27.5531914893617%; +} + +.row-fluid .offset3:first-child { + margin-left: 25.53191489361702%; + *margin-left: 25.425531914893618%; +} + +.row-fluid .offset2 { + margin-left: 19.148936170212764%; + *margin-left: 19.04255319148936%; +} + +.row-fluid .offset2:first-child { + margin-left: 17.02127659574468%; + *margin-left: 16.914893617021278%; +} + +.row-fluid .offset1 { + margin-left: 10.638297872340425%; + *margin-left: 10.53191489361702%; +} + +.row-fluid .offset1:first-child { + margin-left: 8.51063829787234%; + *margin-left: 8.404255319148938%; +} + +[class*="span"].hide, +.row-fluid [class*="span"].hide { + display: none; +} + +[class*="span"].pull-right, +.row-fluid [class*="span"].pull-right { + float: right; +} + +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1; +} + +.container:before, +.container:after { + display: table; + line-height: 0; + content: ""; +} + +.container:after { + clear: both; +} + +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1; +} + +.container-fluid:before, +.container-fluid:after { + display: table; + line-height: 0; + content: ""; +} + +.container-fluid:after { + clear: both; +} + +p { + margin: 0 0 10px; +} + +.lead { + margin-bottom: 20px; + font-size: 21px; + font-weight: 200; + line-height: 30px; +} + +small { + font-size: 85%; +} + +strong { + font-weight: bold; +} + +em { + font-style: italic; +} + +cite { + font-style: normal; +} + +.muted { + color: #999999; +} + +a.muted:hover, +a.muted:focus { + color: #808080; +} + +.text-warning { + color: #c09853; +} + +a.text-warning:hover, +a.text-warning:focus { + color: #a47e3c; +} + +.text-error { + color: #b94a48; +} + +a.text-error:hover, +a.text-error:focus { + color: #953b39; +} + +.text-info { + color: #3a87ad; +} + +a.text-info:hover, +a.text-info:focus { + color: #2d6987; +} + +.text-success { + color: #468847; +} + +a.text-success:hover, +a.text-success:focus { + color: #356635; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-center { + text-align: center; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 10px 0; + font-family: inherit; + font-weight: bold; + line-height: 20px; + color: inherit; + text-rendering: optimizelegibility; +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + line-height: 1; + color: #999999; +} + +h1, +h2, +h3 { + line-height: 40px; +} + +h1 { + font-size: 38.5px; +} + +h2 { + font-size: 31.5px; +} + +h3 { + font-size: 24.5px; +} + +h4 { + font-size: 17.5px; +} + +h5 { + font-size: 14px; +} + +h6 { + font-size: 11.9px; +} + +h1 small { + font-size: 24.5px; +} + +h2 small { + font-size: 17.5px; +} + +h3 small { + font-size: 14px; +} + +h4 small { + font-size: 14px; +} + +.page-header { + padding-bottom: 9px; + margin: 20px 0 30px; + border-bottom: 1px solid #eeeeee; +} + +ul, +ol { + padding: 0; + margin: 0 0 10px 25px; +} + +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} + +li { + line-height: 20px; +} + +ul.unstyled, +ol.unstyled { + margin-left: 0; + list-style: none; +} + +ul.inline, +ol.inline { + margin-left: 0; + list-style: none; +} + +ul.inline > li, +ol.inline > li { + display: inline-block; + *display: inline; + padding-right: 5px; + padding-left: 5px; + *zoom: 1; +} + +dl { + margin-bottom: 20px; +} + +dt, +dd { + line-height: 20px; +} + +dt { + font-weight: bold; +} + +dd { + margin-left: 10px; +} + +.dl-horizontal { + *zoom: 1; +} + +.dl-horizontal:before, +.dl-horizontal:after { + display: table; + line-height: 0; + content: ""; +} + +.dl-horizontal:after { + clear: both; +} + +.dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; +} + +.dl-horizontal dd { + margin-left: 180px; +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px solid #eeeeee; + border-bottom: 1px solid #ffffff; +} + +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 0 0 0 15px; + margin: 0 0 20px; + border-left: 5px solid #eeeeee; +} + +blockquote p { + margin-bottom: 0; + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} + +blockquote small { + display: block; + line-height: 20px; + color: #999999; +} + +blockquote small:before { + content: '\2014 \00A0'; +} + +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} + +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} + +blockquote.pull-right small:before { + content: ''; +} + +blockquote.pull-right small:after { + content: '\00A0 \2014'; +} + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} + +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 20px; +} + +code, +pre { + padding: 0 3px 2px; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +code { + padding: 2px 4px; + color: #d14; + white-space: nowrap; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; +} + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 20px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +pre.prettyprint { + margin-bottom: 20px; +} + +pre code { + padding: 0; + color: inherit; + white-space: pre; + white-space: pre-wrap; + background-color: transparent; + border: 0; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +form { + margin: 0 0 20px; +} + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: 40px; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +legend small { + font-size: 15px; + color: #999999; +} + +label, +input, +button, +select, +textarea { + font-size: 14px; + font-weight: normal; + line-height: 20px; +} + +input, +button, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +label { + display: block; + margin-bottom: 5px; +} + +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + height: 20px; + padding: 4px 6px; + margin-bottom: 10px; + font-size: 14px; + line-height: 20px; + color: #555555; + vertical-align: middle; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +input, +textarea, +.uneditable-input { + width: 206px; +} + +textarea { + height: auto; +} + +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #ffffff; + border: 1px solid #cccccc; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="time"]:focus, +input[type="week"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="color"]:focus, +.uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + /* IE6-9 */ + + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); +} + +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + *margin-top: 0; + line-height: normal; +} + +input[type="file"], +input[type="image"], +input[type="submit"], +input[type="reset"], +input[type="button"], +input[type="radio"], +input[type="checkbox"] { + width: auto; +} + +select, +input[type="file"] { + height: 30px; + /* In IE7, the height of the select element cannot be changed by height, only font-size */ + + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + + line-height: 30px; +} + +select { + width: 220px; + background-color: #ffffff; + border: 1px solid #cccccc; +} + +select[multiple], +select[size] { + height: auto; +} + +select:focus, +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.uneditable-input, +.uneditable-textarea { + color: #999999; + cursor: not-allowed; + background-color: #fcfcfc; + border-color: #cccccc; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); +} + +.uneditable-input { + overflow: hidden; + white-space: nowrap; +} + +.uneditable-textarea { + width: auto; + height: auto; +} + +input:-moz-placeholder, +textarea:-moz-placeholder { + color: #999999; +} + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #999999; +} + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #999999; +} + +.radio, +.checkbox { + min-height: 20px; + padding-left: 20px; +} + +.radio input[type="radio"], +.checkbox input[type="checkbox"] { + float: left; + margin-left: -20px; +} + +.controls > .radio:first-child, +.controls > .checkbox:first-child { + padding-top: 5px; +} + +.radio.inline, +.checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle; +} + +.radio.inline + .radio.inline, +.checkbox.inline + .checkbox.inline { + margin-left: 10px; +} + +.input-mini { + width: 60px; +} + +.input-small { + width: 90px; +} + +.input-medium { + width: 150px; +} + +.input-large { + width: 210px; +} + +.input-xlarge { + width: 270px; +} + +.input-xxlarge { + width: 530px; +} + +input[class*="span"], +select[class*="span"], +textarea[class*="span"], +.uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0; +} + +.input-append input[class*="span"], +.input-append .uneditable-input[class*="span"], +.input-prepend input[class*="span"], +.input-prepend .uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"], +.row-fluid .input-prepend [class*="span"], +.row-fluid .input-append [class*="span"] { + display: inline-block; +} + +input, +textarea, +.uneditable-input { + margin-left: 0; +} + +.controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; +} + +input.span12, +textarea.span12, +.uneditable-input.span12 { + width: 926px; +} + +input.span11, +textarea.span11, +.uneditable-input.span11 { + width: 846px; +} + +input.span10, +textarea.span10, +.uneditable-input.span10 { + width: 766px; +} + +input.span9, +textarea.span9, +.uneditable-input.span9 { + width: 686px; +} + +input.span8, +textarea.span8, +.uneditable-input.span8 { + width: 606px; +} + +input.span7, +textarea.span7, +.uneditable-input.span7 { + width: 526px; +} + +input.span6, +textarea.span6, +.uneditable-input.span6 { + width: 446px; +} + +input.span5, +textarea.span5, +.uneditable-input.span5 { + width: 366px; +} + +input.span4, +textarea.span4, +.uneditable-input.span4 { + width: 286px; +} + +input.span3, +textarea.span3, +.uneditable-input.span3 { + width: 206px; +} + +input.span2, +textarea.span2, +.uneditable-input.span2 { + width: 126px; +} + +input.span1, +textarea.span1, +.uneditable-input.span1 { + width: 46px; +} + +.controls-row { + *zoom: 1; +} + +.controls-row:before, +.controls-row:after { + display: table; + line-height: 0; + content: ""; +} + +.controls-row:after { + clear: both; +} + +.controls-row [class*="span"], +.row-fluid .controls-row [class*="span"] { + float: left; +} + +.controls-row .checkbox[class*="span"], +.controls-row .radio[class*="span"] { + padding-top: 5px; +} + +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + cursor: not-allowed; + background-color: #eeeeee; +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent; +} + +.control-group.warning .control-label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #c09853; +} + +.control-group.warning .checkbox, +.control-group.warning .radio, +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + color: #c09853; +} + +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; +} + +.control-group.warning .input-prepend .add-on, +.control-group.warning .input-append .add-on { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853; +} + +.control-group.error .control-label, +.control-group.error .help-block, +.control-group.error .help-inline { + color: #b94a48; +} + +.control-group.error .checkbox, +.control-group.error .radio, +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + color: #b94a48; +} + +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.error input:focus, +.control-group.error select:focus, +.control-group.error textarea:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; +} + +.control-group.error .input-prepend .add-on, +.control-group.error .input-append .add-on { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48; +} + +.control-group.success .control-label, +.control-group.success .help-block, +.control-group.success .help-inline { + color: #468847; +} + +.control-group.success .checkbox, +.control-group.success .radio, +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + color: #468847; +} + +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.success input:focus, +.control-group.success select:focus, +.control-group.success textarea:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; +} + +.control-group.success .input-prepend .add-on, +.control-group.success .input-append .add-on { + color: #468847; + background-color: #dff0d8; + border-color: #468847; +} + +.control-group.info .control-label, +.control-group.info .help-block, +.control-group.info .help-inline { + color: #3a87ad; +} + +.control-group.info .checkbox, +.control-group.info .radio, +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + color: #3a87ad; +} + +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + border-color: #3a87ad; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.info input:focus, +.control-group.info select:focus, +.control-group.info textarea:focus { + border-color: #2d6987; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; +} + +.control-group.info .input-prepend .add-on, +.control-group.info .input-append .add-on { + color: #3a87ad; + background-color: #d9edf7; + border-color: #3a87ad; +} + +input:focus:invalid, +textarea:focus:invalid, +select:focus:invalid { + color: #b94a48; + border-color: #ee5f5b; +} + +input:focus:invalid:focus, +textarea:focus:invalid:focus, +select:focus:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} + +.form-actions { + padding: 19px 20px 20px; + margin-top: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1; +} + +.form-actions:before, +.form-actions:after { + display: table; + line-height: 0; + content: ""; +} + +.form-actions:after { + clear: both; +} + +.help-block, +.help-inline { + color: #595959; +} + +.help-block { + display: block; + margin-bottom: 10px; +} + +.help-inline { + display: inline-block; + *display: inline; + padding-left: 5px; + vertical-align: middle; + *zoom: 1; +} + +.input-append, +.input-prepend { + display: inline-block; + margin-bottom: 10px; + font-size: 0; + white-space: nowrap; + vertical-align: middle; +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input, +.input-append .dropdown-menu, +.input-prepend .dropdown-menu, +.input-append .popover, +.input-prepend .popover { + font-size: 14px; +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: top; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-append input:focus, +.input-prepend input:focus, +.input-append select:focus, +.input-prepend select:focus, +.input-append .uneditable-input:focus, +.input-prepend .uneditable-input:focus { + z-index: 2; +} + +.input-append .add-on, +.input-prepend .add-on { + display: inline-block; + width: auto; + height: 20px; + min-width: 16px; + padding: 4px 5px; + font-size: 14px; + font-weight: normal; + line-height: 20px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + background-color: #eeeeee; + border: 1px solid #ccc; +} + +.input-append .add-on, +.input-prepend .add-on, +.input-append .btn, +.input-prepend .btn, +.input-append .btn-group > .dropdown-toggle, +.input-prepend .btn-group > .dropdown-toggle { + vertical-align: top; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-append .active, +.input-prepend .active { + background-color: #a9dba9; + border-color: #46a546; +} + +.input-prepend .add-on, +.input-prepend .btn { + margin-right: -1px; +} + +.input-prepend .add-on:first-child, +.input-prepend .btn:first-child { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-append input, +.input-append select, +.input-append .uneditable-input { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-append input + .btn-group .btn:last-child, +.input-append select + .btn-group .btn:last-child, +.input-append .uneditable-input + .btn-group .btn:last-child { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-append .add-on, +.input-append .btn, +.input-append .btn-group { + margin-left: -1px; +} + +.input-append .add-on:last-child, +.input-append .btn:last-child, +.input-append .btn-group:last-child > .dropdown-toggle { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append input, +.input-prepend.input-append select, +.input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-prepend.input-append input + .btn-group .btn, +.input-prepend.input-append select + .btn-group .btn, +.input-prepend.input-append .uneditable-input + .btn-group .btn { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append .add-on:first-child, +.input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-prepend.input-append .add-on:last-child, +.input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append .btn-group:first-child { + margin-left: 0; +} + +input.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + /* IE7-8 doesn't have border-radius, so don't indent the padding */ + + margin-bottom: 0; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +/* Allow for input prepend/append in search forms */ + +.form-search .input-append .search-query, +.form-search .input-prepend .search-query { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.form-search .input-append .search-query { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search .input-append .btn { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .search-query { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .btn { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search input, +.form-inline input, +.form-horizontal input, +.form-search textarea, +.form-inline textarea, +.form-horizontal textarea, +.form-search select, +.form-inline select, +.form-horizontal select, +.form-search .help-inline, +.form-inline .help-inline, +.form-horizontal .help-inline, +.form-search .uneditable-input, +.form-inline .uneditable-input, +.form-horizontal .uneditable-input, +.form-search .input-prepend, +.form-inline .input-prepend, +.form-horizontal .input-prepend, +.form-search .input-append, +.form-inline .input-append, +.form-horizontal .input-append { + display: inline-block; + *display: inline; + margin-bottom: 0; + vertical-align: middle; + *zoom: 1; +} + +.form-search .hide, +.form-inline .hide, +.form-horizontal .hide { + display: none; +} + +.form-search label, +.form-inline label, +.form-search .btn-group, +.form-inline .btn-group { + display: inline-block; +} + +.form-search .input-append, +.form-inline .input-append, +.form-search .input-prepend, +.form-inline .input-prepend { + margin-bottom: 0; +} + +.form-search .radio, +.form-search .checkbox, +.form-inline .radio, +.form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle; +} + +.form-search .radio input[type="radio"], +.form-search .checkbox input[type="checkbox"], +.form-inline .radio input[type="radio"], +.form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0; +} + +.control-group { + margin-bottom: 10px; +} + +legend + .control-group { + margin-top: 20px; + -webkit-margin-top-collapse: separate; +} + +.form-horizontal .control-group { + margin-bottom: 20px; + *zoom: 1; +} + +.form-horizontal .control-group:before, +.form-horizontal .control-group:after { + display: table; + line-height: 0; + content: ""; +} + +.form-horizontal .control-group:after { + clear: both; +} + +.form-horizontal .control-label { + float: left; + width: 160px; + padding-top: 5px; + text-align: right; +} + +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 180px; + *margin-left: 0; +} + +.form-horizontal .controls:first-child { + *padding-left: 180px; +} + +.form-horizontal .help-block { + margin-bottom: 0; +} + +.form-horizontal input + .help-block, +.form-horizontal select + .help-block, +.form-horizontal textarea + .help-block, +.form-horizontal .uneditable-input + .help-block, +.form-horizontal .input-prepend + .help-block, +.form-horizontal .input-append + .help-block { + margin-top: 10px; +} + +.form-horizontal .form-actions { + padding-left: 180px; +} + +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0; +} + +.table { + width: 100%; + margin-bottom: 20px; +} + +.table th, +.table td { + padding: 8px; + line-height: 20px; + text-align: left; + vertical-align: top; + border-top: 1px solid #dddddd; +} + +.table th { + font-weight: bold; +} + +.table thead th { + vertical-align: bottom; +} + +.table caption + thead tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child th, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child th, +.table thead:first-child tr:first-child td { + border-top: 0; +} + +.table tbody + tbody { + border-top: 2px solid #dddddd; +} + +.table .table { + background-color: #ffffff; +} + +.table-condensed th, +.table-condensed td { + padding: 4px 5px; +} + +.table-bordered { + border: 1px solid #dddddd; + border-collapse: separate; + *border-collapse: collapse; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.table-bordered th, +.table-bordered td { + border-left: 1px solid #dddddd; +} + +.table-bordered caption + thead tr:first-child th, +.table-bordered caption + tbody tr:first-child th, +.table-bordered caption + tbody tr:first-child td, +.table-bordered colgroup + thead tr:first-child th, +.table-bordered colgroup + tbody tr:first-child th, +.table-bordered colgroup + tbody tr:first-child td, +.table-bordered thead:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child td { + border-top: 0; +} + +.table-bordered thead:first-child tr:first-child > th:first-child, +.table-bordered tbody:first-child tr:first-child > td:first-child, +.table-bordered tbody:first-child tr:first-child > th:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered thead:first-child tr:first-child > th:last-child, +.table-bordered tbody:first-child tr:first-child > td:last-child, +.table-bordered tbody:first-child tr:first-child > th:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-bordered thead:last-child tr:last-child > th:first-child, +.table-bordered tbody:last-child tr:last-child > td:first-child, +.table-bordered tbody:last-child tr:last-child > th:first-child, +.table-bordered tfoot:last-child tr:last-child > td:first-child, +.table-bordered tfoot:last-child tr:last-child > th:first-child { + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.table-bordered thead:last-child tr:last-child > th:last-child, +.table-bordered tbody:last-child tr:last-child > td:last-child, +.table-bordered tbody:last-child tr:last-child > th:last-child, +.table-bordered tfoot:last-child tr:last-child > td:last-child, +.table-bordered tfoot:last-child tr:last-child > th:last-child { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomleft: 0; +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + -moz-border-radius-bottomright: 0; +} + +.table-bordered caption + thead tr:first-child th:first-child, +.table-bordered caption + tbody tr:first-child td:first-child, +.table-bordered colgroup + thead tr:first-child th:first-child, +.table-bordered colgroup + tbody tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered caption + thead tr:first-child th:last-child, +.table-bordered caption + tbody tr:first-child td:last-child, +.table-bordered colgroup + thead tr:first-child th:last-child, +.table-bordered colgroup + tbody tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-striped tbody > tr:nth-child(odd) > td, +.table-striped tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} + +.table-hover tbody tr:hover > td, +.table-hover tbody tr:hover > th { + background-color: #f5f5f5; +} + +table td[class*="span"], +table th[class*="span"], +.row-fluid table td[class*="span"], +.row-fluid table th[class*="span"] { + display: table-cell; + float: none; + margin-left: 0; +} + +.table td.span1, +.table th.span1 { + float: none; + width: 44px; + margin-left: 0; +} + +.table td.span2, +.table th.span2 { + float: none; + width: 124px; + margin-left: 0; +} + +.table td.span3, +.table th.span3 { + float: none; + width: 204px; + margin-left: 0; +} + +.table td.span4, +.table th.span4 { + float: none; + width: 284px; + margin-left: 0; +} + +.table td.span5, +.table th.span5 { + float: none; + width: 364px; + margin-left: 0; +} + +.table td.span6, +.table th.span6 { + float: none; + width: 444px; + margin-left: 0; +} + +.table td.span7, +.table th.span7 { + float: none; + width: 524px; + margin-left: 0; +} + +.table td.span8, +.table th.span8 { + float: none; + width: 604px; + margin-left: 0; +} + +.table td.span9, +.table th.span9 { + float: none; + width: 684px; + margin-left: 0; +} + +.table td.span10, +.table th.span10 { + float: none; + width: 764px; + margin-left: 0; +} + +.table td.span11, +.table th.span11 { + float: none; + width: 844px; + margin-left: 0; +} + +.table td.span12, +.table th.span12 { + float: none; + width: 924px; + margin-left: 0; +} + +.table tbody tr.success > td { + background-color: #dff0d8; +} + +.table tbody tr.error > td { + background-color: #f2dede; +} + +.table tbody tr.warning > td { + background-color: #fcf8e3; +} + +.table tbody tr.info > td { + background-color: #d9edf7; +} + +.table-hover tbody tr.success:hover > td { + background-color: #d0e9c6; +} + +.table-hover tbody tr.error:hover > td { + background-color: #ebcccc; +} + +.table-hover tbody tr.warning:hover > td { + background-color: #faf2cc; +} + +.table-hover tbody tr.info:hover > td { + background-color: #c4e3f3; +} + +[class^="icon-"], +[class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + margin-top: 1px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; +} + +/* White icons with optional class, or on hover/focus/active states of certain elements */ + +.icon-white, +.nav-pills > .active > a > [class^="icon-"], +.nav-pills > .active > a > [class*=" icon-"], +.nav-list > .active > a > [class^="icon-"], +.nav-list > .active > a > [class*=" icon-"], +.navbar-inverse .nav > .active > a > [class^="icon-"], +.navbar-inverse .nav > .active > a > [class*=" icon-"], +.dropdown-menu > li > a:hover > [class^="icon-"], +.dropdown-menu > li > a:focus > [class^="icon-"], +.dropdown-menu > li > a:hover > [class*=" icon-"], +.dropdown-menu > li > a:focus > [class*=" icon-"], +.dropdown-menu > .active > a > [class^="icon-"], +.dropdown-menu > .active > a > [class*=" icon-"], +.dropdown-submenu:hover > a > [class^="icon-"], +.dropdown-submenu:focus > a > [class^="icon-"], +.dropdown-submenu:hover > a > [class*=" icon-"], +.dropdown-submenu:focus > a > [class*=" icon-"] { + background-image: url("../img/glyphicons-halflings-white.png"); +} + +.icon-glass { + background-position: 0 0; +} + +.icon-music { + background-position: -24px 0; +} + +.icon-search { + background-position: -48px 0; +} + +.icon-envelope { + background-position: -72px 0; +} + +.icon-heart { + background-position: -96px 0; +} + +.icon-star { + background-position: -120px 0; +} + +.icon-star-empty { + background-position: -144px 0; +} + +.icon-user { + background-position: -168px 0; +} + +.icon-film { + background-position: -192px 0; +} + +.icon-th-large { + background-position: -216px 0; +} + +.icon-th { + background-position: -240px 0; +} + +.icon-th-list { + background-position: -264px 0; +} + +.icon-ok { + background-position: -288px 0; +} + +.icon-remove { + background-position: -312px 0; +} + +.icon-zoom-in { + background-position: -336px 0; +} + +.icon-zoom-out { + background-position: -360px 0; +} + +.icon-off { + background-position: -384px 0; +} + +.icon-signal { + background-position: -408px 0; +} + +.icon-cog { + background-position: -432px 0; +} + +.icon-trash { + background-position: -456px 0; +} + +.icon-home { + background-position: 0 -24px; +} + +.icon-file { + background-position: -24px -24px; +} + +.icon-time { + background-position: -48px -24px; +} + +.icon-road { + background-position: -72px -24px; +} + +.icon-download-alt { + background-position: -96px -24px; +} + +.icon-download { + background-position: -120px -24px; +} + +.icon-upload { + background-position: -144px -24px; +} + +.icon-inbox { + background-position: -168px -24px; +} + +.icon-play-circle { + background-position: -192px -24px; +} + +.icon-repeat { + background-position: -216px -24px; +} + +.icon-refresh { + background-position: -240px -24px; +} + +.icon-list-alt { + background-position: -264px -24px; +} + +.icon-lock { + background-position: -287px -24px; +} + +.icon-flag { + background-position: -312px -24px; +} + +.icon-headphones { + background-position: -336px -24px; +} + +.icon-volume-off { + background-position: -360px -24px; +} + +.icon-volume-down { + background-position: -384px -24px; +} + +.icon-volume-up { + background-position: -408px -24px; +} + +.icon-qrcode { + background-position: -432px -24px; +} + +.icon-barcode { + background-position: -456px -24px; +} + +.icon-tag { + background-position: 0 -48px; +} + +.icon-tags { + background-position: -25px -48px; +} + +.icon-book { + background-position: -48px -48px; +} + +.icon-bookmark { + background-position: -72px -48px; +} + +.icon-print { + background-position: -96px -48px; +} + +.icon-camera { + background-position: -120px -48px; +} + +.icon-font { + background-position: -144px -48px; +} + +.icon-bold { + background-position: -167px -48px; +} + +.icon-italic { + background-position: -192px -48px; +} + +.icon-text-height { + background-position: -216px -48px; +} + +.icon-text-width { + background-position: -240px -48px; +} + +.icon-align-left { + background-position: -264px -48px; +} + +.icon-align-center { + background-position: -288px -48px; +} + +.icon-align-right { + background-position: -312px -48px; +} + +.icon-align-justify { + background-position: -336px -48px; +} + +.icon-list { + background-position: -360px -48px; +} + +.icon-indent-left { + background-position: -384px -48px; +} + +.icon-indent-right { + background-position: -408px -48px; +} + +.icon-facetime-video { + background-position: -432px -48px; +} + +.icon-picture { + background-position: -456px -48px; +} + +.icon-pencil { + background-position: 0 -72px; +} + +.icon-map-marker { + background-position: -24px -72px; +} + +.icon-adjust { + background-position: -48px -72px; +} + +.icon-tint { + background-position: -72px -72px; +} + +.icon-edit { + background-position: -96px -72px; +} + +.icon-share { + background-position: -120px -72px; +} + +.icon-check { + background-position: -144px -72px; +} + +.icon-move { + background-position: -168px -72px; +} + +.icon-step-backward { + background-position: -192px -72px; +} + +.icon-fast-backward { + background-position: -216px -72px; +} + +.icon-backward { + background-position: -240px -72px; +} + +.icon-play { + background-position: -264px -72px; +} + +.icon-pause { + background-position: -288px -72px; +} + +.icon-stop { + background-position: -312px -72px; +} + +.icon-forward { + background-position: -336px -72px; +} + +.icon-fast-forward { + background-position: -360px -72px; +} + +.icon-step-forward { + background-position: -384px -72px; +} + +.icon-eject { + background-position: -408px -72px; +} + +.icon-chevron-left { + background-position: -432px -72px; +} + +.icon-chevron-right { + background-position: -456px -72px; +} + +.icon-plus-sign { + background-position: 0 -96px; +} + +.icon-minus-sign { + background-position: -24px -96px; +} + +.icon-remove-sign { + background-position: -48px -96px; +} + +.icon-ok-sign { + background-position: -72px -96px; +} + +.icon-question-sign { + background-position: -96px -96px; +} + +.icon-info-sign { + background-position: -120px -96px; +} + +.icon-screenshot { + background-position: -144px -96px; +} + +.icon-remove-circle { + background-position: -168px -96px; +} + +.icon-ok-circle { + background-position: -192px -96px; +} + +.icon-ban-circle { + background-position: -216px -96px; +} + +.icon-arrow-left { + background-position: -240px -96px; +} + +.icon-arrow-right { + background-position: -264px -96px; +} + +.icon-arrow-up { + background-position: -289px -96px; +} + +.icon-arrow-down { + background-position: -312px -96px; +} + +.icon-share-alt { + background-position: -336px -96px; +} + +.icon-resize-full { + background-position: -360px -96px; +} + +.icon-resize-small { + background-position: -384px -96px; +} + +.icon-plus { + background-position: -408px -96px; +} + +.icon-minus { + background-position: -433px -96px; +} + +.icon-asterisk { + background-position: -456px -96px; +} + +.icon-exclamation-sign { + background-position: 0 -120px; +} + +.icon-gift { + background-position: -24px -120px; +} + +.icon-leaf { + background-position: -48px -120px; +} + +.icon-fire { + background-position: -72px -120px; +} + +.icon-eye-open { + background-position: -96px -120px; +} + +.icon-eye-close { + background-position: -120px -120px; +} + +.icon-warning-sign { + background-position: -144px -120px; +} + +.icon-plane { + background-position: -168px -120px; +} + +.icon-calendar { + background-position: -192px -120px; +} + +.icon-random { + width: 16px; + background-position: -216px -120px; +} + +.icon-comment { + background-position: -240px -120px; +} + +.icon-magnet { + background-position: -264px -120px; +} + +.icon-chevron-up { + background-position: -288px -120px; +} + +.icon-chevron-down { + background-position: -313px -119px; +} + +.icon-retweet { + background-position: -336px -120px; +} + +.icon-shopping-cart { + background-position: -360px -120px; +} + +.icon-folder-close { + width: 16px; + background-position: -384px -120px; +} + +.icon-folder-open { + width: 16px; + background-position: -408px -120px; +} + +.icon-resize-vertical { + background-position: -432px -119px; +} + +.icon-resize-horizontal { + background-position: -456px -118px; +} + +.icon-hdd { + background-position: 0 -144px; +} + +.icon-bullhorn { + background-position: -24px -144px; +} + +.icon-bell { + background-position: -48px -144px; +} + +.icon-certificate { + background-position: -72px -144px; +} + +.icon-thumbs-up { + background-position: -96px -144px; +} + +.icon-thumbs-down { + background-position: -120px -144px; +} + +.icon-hand-right { + background-position: -144px -144px; +} + +.icon-hand-left { + background-position: -168px -144px; +} + +.icon-hand-up { + background-position: -192px -144px; +} + +.icon-hand-down { + background-position: -216px -144px; +} + +.icon-circle-arrow-right { + background-position: -240px -144px; +} + +.icon-circle-arrow-left { + background-position: -264px -144px; +} + +.icon-circle-arrow-up { + background-position: -288px -144px; +} + +.icon-circle-arrow-down { + background-position: -312px -144px; +} + +.icon-globe { + background-position: -336px -144px; +} + +.icon-wrench { + background-position: -360px -144px; +} + +.icon-tasks { + background-position: -384px -144px; +} + +.icon-filter { + background-position: -408px -144px; +} + +.icon-briefcase { + background-position: -432px -144px; +} + +.icon-fullscreen { + background-position: -456px -144px; +} + +.dropup, +.dropdown { + position: relative; +} + +.dropdown-toggle { + *margin-bottom: -3px; +} + +.dropdown-toggle:active, +.open .dropdown-toggle { + outline: 0; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: ""; +} + +.dropdown .caret { + margin-top: 8px; + margin-left: 2px; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 20px; + color: #333333; + white-space: nowrap; +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-submenu:hover > a, +.dropdown-submenu:focus > a { + color: #ffffff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + outline: 0; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999999; +} + +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.open { + *z-index: 1000; +} + +.open > .dropdown-menu { + display: block; +} + +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000000; + content: ""; +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +.dropdown-submenu { + position: relative; +} + +.dropdown-submenu > .dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} + +.dropdown-submenu:hover > .dropdown-menu { + display: block; +} + +.dropup .dropdown-submenu > .dropdown-menu { + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -2px; + -webkit-border-radius: 5px 5px 5px 0; + -moz-border-radius: 5px 5px 5px 0; + border-radius: 5px 5px 5px 0; +} + +.dropdown-submenu > a:after { + display: block; + float: right; + width: 0; + height: 0; + margin-top: 5px; + margin-right: -10px; + border-color: transparent; + border-left-color: #cccccc; + border-style: solid; + border-width: 5px 0 5px 5px; + content: " "; +} + +.dropdown-submenu:hover > a:after { + border-left-color: #ffffff; +} + +.dropdown-submenu.pull-left { + float: none; +} + +.dropdown-submenu.pull-left > .dropdown-menu { + left: -100%; + margin-left: 10px; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.dropdown .dropdown-menu .nav-header { + padding-right: 20px; + padding-left: 20px; +} + +.typeahead { + z-index: 1051; + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} + +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + +.fade.in { + opacity: 1; +} + +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -moz-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +.collapse.in { + height: auto; +} + +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 20px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} + +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity=40); +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.btn { + display: inline-block; + *display: inline; + padding: 4px 12px; + margin-bottom: 0; + *margin-left: .3em; + font-size: 14px; + line-height: 20px; + color: #333333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background-color: #f5f5f5; + *background-color: #e6e6e6; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); + background-repeat: repeat-x; + border: 1px solid #cccccc; + *border: 0; + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn:hover, +.btn:focus, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + color: #333333; + background-color: #e6e6e6; + *background-color: #d9d9d9; +} + +.btn:active, +.btn.active { + background-color: #cccccc \9; +} + +.btn:first-child { + *margin-left: 0; +} + +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.btn.active, +.btn:active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn.disabled, +.btn[disabled] { + cursor: default; + background-image: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-large { + padding: 11px 19px; + font-size: 17.5px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.btn-large [class^="icon-"], +.btn-large [class*=" icon-"] { + margin-top: 4px; +} + +.btn-small { + padding: 2px 10px; + font-size: 11.9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.btn-small [class^="icon-"], +.btn-small [class*=" icon-"] { + margin-top: 0; +} + +.btn-mini [class^="icon-"], +.btn-mini [class*=" icon-"] { + margin-top: -1px; +} + +.btn-mini { + padding: 0 6px; + font-size: 10.5px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.btn-block + .btn-block { + margin-top: 5px; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.btn-primary.active, +.btn-warning.active, +.btn-danger.active, +.btn-success.active, +.btn-info.active, +.btn-inverse.active { + color: rgba(255, 255, 255, 0.75); +} + +.btn-primary { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #006dcc; + *background-color: #0044cc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-repeat: repeat-x; + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + color: #ffffff; + background-color: #0044cc; + *background-color: #003bb3; +} + +.btn-primary:active, +.btn-primary.active { + background-color: #003399 \9; +} + +.btn-warning { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #faa732; + *background-color: #f89406; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + border-color: #f89406 #f89406 #ad6704; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + color: #ffffff; + background-color: #f89406; + *background-color: #df8505; +} + +.btn-warning:active, +.btn-warning.active { + background-color: #c67605 \9; +} + +.btn-danger { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #da4f49; + *background-color: #bd362f; + background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); + background-repeat: repeat-x; + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + color: #ffffff; + background-color: #bd362f; + *background-color: #a9302a; +} + +.btn-danger:active, +.btn-danger.active { + background-color: #942a25 \9; +} + +.btn-success { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #5bb75b; + *background-color: #51a351; + background-image: -moz-linear-gradient(top, #62c462, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); + background-image: -webkit-linear-gradient(top, #62c462, #51a351); + background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(to bottom, #62c462, #51a351); + background-repeat: repeat-x; + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + color: #ffffff; + background-color: #51a351; + *background-color: #499249; +} + +.btn-success:active, +.btn-success.active { + background-color: #408140 \9; +} + +.btn-info { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #49afcd; + *background-color: #2f96b4; + background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); + background-repeat: repeat-x; + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + color: #ffffff; + background-color: #2f96b4; + *background-color: #2a85a0; +} + +.btn-info:active, +.btn-info.active { + background-color: #24748c \9; +} + +.btn-inverse { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #363636; + *background-color: #222222; + background-image: -moz-linear-gradient(top, #444444, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); + background-image: -webkit-linear-gradient(top, #444444, #222222); + background-image: -o-linear-gradient(top, #444444, #222222); + background-image: linear-gradient(to bottom, #444444, #222222); + background-repeat: repeat-x; + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-inverse:hover, +.btn-inverse:focus, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + color: #ffffff; + background-color: #222222; + *background-color: #151515; +} + +.btn-inverse:active, +.btn-inverse.active { + background-color: #080808 \9; +} + +button.btn, +input[type="submit"].btn { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn::-moz-focus-inner, +input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0; +} + +button.btn.btn-large, +input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px; +} + +button.btn.btn-small, +input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn.btn-mini, +input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px; +} + +.btn-link, +.btn-link:active, +.btn-link[disabled] { + background-color: transparent; + background-image: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-link { + color: #0088cc; + cursor: pointer; + border-color: transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-link:hover, +.btn-link:focus { + color: #005580; + text-decoration: underline; + background-color: transparent; +} + +.btn-link[disabled]:hover, +.btn-link[disabled]:focus { + color: #333333; + text-decoration: none; +} + +.btn-group { + position: relative; + display: inline-block; + *display: inline; + *margin-left: .3em; + font-size: 0; + white-space: nowrap; + vertical-align: middle; + *zoom: 1; +} + +.btn-group:first-child { + *margin-left: 0; +} + +.btn-group + .btn-group { + margin-left: 5px; +} + +.btn-toolbar { + margin-top: 10px; + margin-bottom: 10px; + font-size: 0; +} + +.btn-toolbar > .btn + .btn, +.btn-toolbar > .btn-group + .btn, +.btn-toolbar > .btn + .btn-group { + margin-left: 5px; +} + +.btn-group > .btn { + position: relative; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group > .btn + .btn { + margin-left: -1px; +} + +.btn-group > .btn, +.btn-group > .dropdown-menu, +.btn-group > .popover { + font-size: 14px; +} + +.btn-group > .btn-mini { + font-size: 10.5px; +} + +.btn-group > .btn-small { + font-size: 11.9px; +} + +.btn-group > .btn-large { + font-size: 17.5px; +} + +.btn-group > .btn:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.btn-group > .btn:last-child, +.btn-group > .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.btn-group > .btn.large:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.btn-group > .btn.large:last-child, +.btn-group > .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active { + z-index: 2; +} + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group > .btn + .dropdown-toggle { + *padding-top: 5px; + padding-right: 8px; + *padding-bottom: 5px; + padding-left: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group > .btn-mini + .dropdown-toggle { + *padding-top: 2px; + padding-right: 5px; + *padding-bottom: 2px; + padding-left: 5px; +} + +.btn-group > .btn-small + .dropdown-toggle { + *padding-top: 5px; + *padding-bottom: 4px; +} + +.btn-group > .btn-large + .dropdown-toggle { + *padding-top: 7px; + padding-right: 12px; + *padding-bottom: 7px; + padding-left: 12px; +} + +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6; +} + +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #0044cc; +} + +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #f89406; +} + +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f; +} + +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351; +} + +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4; +} + +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222222; +} + +.btn .caret { + margin-top: 8px; + margin-left: 0; +} + +.btn-large .caret { + margin-top: 6px; +} + +.btn-large .caret { + border-top-width: 5px; + border-right-width: 5px; + border-left-width: 5px; +} + +.btn-mini .caret, +.btn-small .caret { + margin-top: 8px; +} + +.dropup .btn-large .caret { + border-bottom-width: 5px; +} + +.btn-primary .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret, +.btn-success .caret, +.btn-inverse .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.btn-group-vertical { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; +} + +.btn-group-vertical > .btn { + display: block; + float: none; + max-width: 100%; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group-vertical > .btn + .btn { + margin-top: -1px; + margin-left: 0; +} + +.btn-group-vertical > .btn:first-child { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.btn-group-vertical > .btn:last-child { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.btn-group-vertical > .btn-large:first-child { + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} + +.btn-group-vertical > .btn-large:last-child { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 20px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.alert, +.alert h4 { + color: #c09853; +} + +.alert h4 { + margin: 0; +} + +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 20px; +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.alert-success h4 { + color: #468847; +} + +.alert-danger, +.alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.alert-danger h4, +.alert-error h4 { + color: #b94a48; +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.alert-info h4 { + color: #3a87ad; +} + +.alert-block { + padding-top: 14px; + padding-bottom: 14px; +} + +.alert-block > p, +.alert-block > ul { + margin-bottom: 0; +} + +.alert-block p + p { + margin-top: 5px; +} + +.nav { + margin-bottom: 20px; + margin-left: 0; + list-style: none; +} + +.nav > li > a { + display: block; +} + +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} + +.nav > li > a > img { + max-width: none; +} + +.nav > .pull-right { + float: right; +} + +.nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 20px; + color: #999999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase; +} + +.nav li + .nav-header { + margin-top: 9px; +} + +.nav-list { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 0; +} + +.nav-list > li > a, +.nav-list .nav-header { + margin-right: -15px; + margin-left: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} + +.nav-list > li > a { + padding: 3px 15px; +} + +.nav-list > .active > a, +.nav-list > .active > a:hover, +.nav-list > .active > a:focus { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #0088cc; +} + +.nav-list [class^="icon-"], +.nav-list [class*=" icon-"] { + margin-right: 2px; +} + +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.nav-tabs, +.nav-pills { + *zoom: 1; +} + +.nav-tabs:before, +.nav-pills:before, +.nav-tabs:after, +.nav-pills:after { + display: table; + line-height: 0; + content: ""; +} + +.nav-tabs:after, +.nav-pills:after { + clear: both; +} + +.nav-tabs > li, +.nav-pills > li { + float: left; +} + +.nav-tabs > li > a, +.nav-pills > li > a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px; +} + +.nav-tabs { + border-bottom: 1px solid #ddd; +} + +.nav-tabs > li { + margin-bottom: -1px; +} + +.nav-tabs > li > a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 20px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.nav-tabs > li > a:hover, +.nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #dddddd; +} + +.nav-tabs > .active > a, +.nav-tabs > .active > a:hover, +.nav-tabs > .active > a:focus { + color: #555555; + cursor: default; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} + +.nav-pills > li > a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.nav-pills > .active > a, +.nav-pills > .active > a:hover, +.nav-pills > .active > a:focus { + color: #ffffff; + background-color: #0088cc; +} + +.nav-stacked > li { + float: none; +} + +.nav-stacked > li > a { + margin-right: 0; +} + +.nav-tabs.nav-stacked { + border-bottom: 0; +} + +.nav-tabs.nav-stacked > li > a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.nav-tabs.nav-stacked > li:first-child > a { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; +} + +.nav-tabs.nav-stacked > li:last-child > a { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.nav-tabs.nav-stacked > li > a:hover, +.nav-tabs.nav-stacked > li > a:focus { + z-index: 2; + border-color: #ddd; +} + +.nav-pills.nav-stacked > li > a { + margin-bottom: 3px; +} + +.nav-pills.nav-stacked > li:last-child > a { + margin-bottom: 1px; +} + +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +.nav-pills .dropdown-menu { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.nav .dropdown-toggle .caret { + margin-top: 6px; + border-top-color: #0088cc; + border-bottom-color: #0088cc; +} + +.nav .dropdown-toggle:hover .caret, +.nav .dropdown-toggle:focus .caret { + border-top-color: #005580; + border-bottom-color: #005580; +} + +/* move down carets for tabs */ + +.nav-tabs .dropdown-toggle .caret { + margin-top: 8px; +} + +.nav .active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff; +} + +.nav-tabs .active .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.nav > .dropdown.active > a:hover, +.nav > .dropdown.active > a:focus { + cursor: pointer; +} + +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > li.dropdown.open.active > a:hover, +.nav > li.dropdown.open.active > a:focus { + color: #ffffff; + background-color: #999999; + border-color: #999999; +} + +.nav li.dropdown.open .caret, +.nav li.dropdown.open.active .caret, +.nav li.dropdown.open a:hover .caret, +.nav li.dropdown.open a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 1; + filter: alpha(opacity=100); +} + +.tabs-stacked .open > a:hover, +.tabs-stacked .open > a:focus { + border-color: #999999; +} + +.tabbable { + *zoom: 1; +} + +.tabbable:before, +.tabbable:after { + display: table; + line-height: 0; + content: ""; +} + +.tabbable:after { + clear: both; +} + +.tab-content { + overflow: auto; +} + +.tabs-below > .nav-tabs, +.tabs-right > .nav-tabs, +.tabs-left > .nav-tabs { + border-bottom: 0; +} + +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} + +.tab-content > .active, +.pill-content > .active { + display: block; +} + +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd; +} + +.tabs-below > .nav-tabs > li { + margin-top: -1px; + margin-bottom: 0; +} + +.tabs-below > .nav-tabs > li > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.tabs-below > .nav-tabs > li > a:hover, +.tabs-below > .nav-tabs > li > a:focus { + border-top-color: #ddd; + border-bottom-color: transparent; +} + +.tabs-below > .nav-tabs > .active > a, +.tabs-below > .nav-tabs > .active > a:hover, +.tabs-below > .nav-tabs > .active > a:focus { + border-color: transparent #ddd #ddd #ddd; +} + +.tabs-left > .nav-tabs > li, +.tabs-right > .nav-tabs > li { + float: none; +} + +.tabs-left > .nav-tabs > li > a, +.tabs-right > .nav-tabs > li > a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; +} + +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} + +.tabs-left > .nav-tabs > li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.tabs-left > .nav-tabs > li > a:hover, +.tabs-left > .nav-tabs > li > a:focus { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} + +.tabs-left > .nav-tabs .active > a, +.tabs-left > .nav-tabs .active > a:hover, +.tabs-left > .nav-tabs .active > a:focus { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #ffffff; +} + +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} + +.tabs-right > .nav-tabs > li > a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.tabs-right > .nav-tabs > li > a:hover, +.tabs-right > .nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} + +.tabs-right > .nav-tabs .active > a, +.tabs-right > .nav-tabs .active > a:hover, +.tabs-right > .nav-tabs .active > a:focus { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} + +.nav > .disabled > a { + color: #999999; +} + +.nav > .disabled > a:hover, +.nav > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; +} + +.navbar { + *position: relative; + *z-index: 2; + margin-bottom: 20px; + overflow: visible; +} + +.navbar-inner { + min-height: 40px; + padding-right: 20px; + padding-left: 20px; + background-color: #fafafa; + background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); + background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); + background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); + background-repeat: repeat-x; + border: 1px solid #d4d4d4; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); + *zoom: 1; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); +} + +.navbar-inner:before, +.navbar-inner:after { + display: table; + line-height: 0; + content: ""; +} + +.navbar-inner:after { + clear: both; +} + +.navbar .container { + width: auto; +} + +.nav-collapse.collapse { + height: auto; + overflow: visible; +} + +.navbar .brand { + display: block; + float: left; + padding: 10px 20px 10px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + color: #777777; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .brand:hover, +.navbar .brand:focus { + text-decoration: none; +} + +.navbar-text { + margin-bottom: 0; + line-height: 40px; + color: #777777; +} + +.navbar-link { + color: #777777; +} + +.navbar-link:hover, +.navbar-link:focus { + color: #333333; +} + +.navbar .divider-vertical { + height: 40px; + margin: 0 9px; + border-right: 1px solid #ffffff; + border-left: 1px solid #f2f2f2; +} + +.navbar .btn, +.navbar .btn-group { + margin-top: 5px; +} + +.navbar .btn-group .btn, +.navbar .input-prepend .btn, +.navbar .input-append .btn, +.navbar .input-prepend .btn-group, +.navbar .input-append .btn-group { + margin-top: 0; +} + +.navbar-form { + margin-bottom: 0; + *zoom: 1; +} + +.navbar-form:before, +.navbar-form:after { + display: table; + line-height: 0; + content: ""; +} + +.navbar-form:after { + clear: both; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .radio, +.navbar-form .checkbox { + margin-top: 5px; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .btn { + display: inline-block; + margin-bottom: 0; +} + +.navbar-form input[type="image"], +.navbar-form input[type="checkbox"], +.navbar-form input[type="radio"] { + margin-top: 3px; +} + +.navbar-form .input-append, +.navbar-form .input-prepend { + margin-top: 5px; + white-space: nowrap; +} + +.navbar-form .input-append input, +.navbar-form .input-prepend input { + margin-top: 0; +} + +.navbar-search { + position: relative; + float: left; + margin-top: 5px; + margin-bottom: 0; +} + +.navbar-search .search-query { + padding: 4px 14px; + margin-bottom: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.navbar-static-top { + position: static; + margin-bottom: 0; +} + +.navbar-static-top .navbar-inner { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + border-width: 0 0 1px; +} + +.navbar-fixed-bottom .navbar-inner { + border-width: 1px 0 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner { + padding-right: 0; + padding-left: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.navbar-fixed-top { + top: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); +} + +.navbar-fixed-bottom { + bottom: 0; +} + +.navbar-fixed-bottom .navbar-inner { + -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); +} + +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0; +} + +.navbar .nav.pull-right { + float: right; + margin-right: 0; +} + +.navbar .nav > li { + float: left; +} + +.navbar .nav > li > a { + float: none; + padding: 10px 15px 10px; + color: #777777; + text-decoration: none; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .nav .dropdown-toggle .caret { + margin-top: 8px; +} + +.navbar .nav > li > a:focus, +.navbar .nav > li > a:hover { + color: #333333; + text-decoration: none; + background-color: transparent; +} + +.navbar .nav > .active > a, +.navbar .nav > .active > a:hover, +.navbar .nav > .active > a:focus { + color: #555555; + text-decoration: none; + background-color: #e5e5e5; + -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); +} + +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-right: 5px; + margin-left: 5px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #ededed; + *background-color: #e5e5e5; + background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); + background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); + background-repeat: repeat-x; + border-color: #e5e5e5 #e5e5e5 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); +} + +.navbar .btn-navbar:hover, +.navbar .btn-navbar:focus, +.navbar .btn-navbar:active, +.navbar .btn-navbar.active, +.navbar .btn-navbar.disabled, +.navbar .btn-navbar[disabled] { + color: #ffffff; + background-color: #e5e5e5; + *background-color: #d9d9d9; +} + +.navbar .btn-navbar:active, +.navbar .btn-navbar.active { + background-color: #cccccc \9; +} + +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); +} + +.btn-navbar .icon-bar + .icon-bar { + margin-top: 3px; +} + +.navbar .nav > li > .dropdown-menu:before { + position: absolute; + top: -7px; + left: 9px; + display: inline-block; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-left: 7px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: ''; +} + +.navbar .nav > li > .dropdown-menu:after { + position: absolute; + top: -6px; + left: 10px; + display: inline-block; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + border-left: 6px solid transparent; + content: ''; +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:before { + top: auto; + bottom: -7px; + border-top: 7px solid #ccc; + border-bottom: 0; + border-top-color: rgba(0, 0, 0, 0.2); +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:after { + top: auto; + bottom: -6px; + border-top: 6px solid #ffffff; + border-bottom: 0; +} + +.navbar .nav li.dropdown > a:hover .caret, +.navbar .nav li.dropdown > a:focus .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle, +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.open.active > .dropdown-toggle { + color: #555555; + background-color: #e5e5e5; +} + +.navbar .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #777777; + border-bottom-color: #777777; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.navbar .pull-right > li > .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:before, +.navbar .nav > li > .dropdown-menu.pull-right:before { + right: 12px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:after, +.navbar .nav > li > .dropdown-menu.pull-right:after { + right: 13px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { + right: 100%; + left: auto; + margin-right: -1px; + margin-left: 0; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.navbar-inverse .navbar-inner { + background-color: #1b1b1b; + background-image: -moz-linear-gradient(top, #222222, #111111); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); + background-image: -webkit-linear-gradient(top, #222222, #111111); + background-image: -o-linear-gradient(top, #222222, #111111); + background-image: linear-gradient(to bottom, #222222, #111111); + background-repeat: repeat-x; + border-color: #252525; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); +} + +.navbar-inverse .brand, +.navbar-inverse .nav > li > a { + color: #999999; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-inverse .brand:hover, +.navbar-inverse .nav > li > a:hover, +.navbar-inverse .brand:focus, +.navbar-inverse .nav > li > a:focus { + color: #ffffff; +} + +.navbar-inverse .brand { + color: #999999; +} + +.navbar-inverse .navbar-text { + color: #999999; +} + +.navbar-inverse .nav > li > a:focus, +.navbar-inverse .nav > li > a:hover { + color: #ffffff; + background-color: transparent; +} + +.navbar-inverse .nav .active > a, +.navbar-inverse .nav .active > a:hover, +.navbar-inverse .nav .active > a:focus { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .navbar-link { + color: #999999; +} + +.navbar-inverse .navbar-link:hover, +.navbar-inverse .navbar-link:focus { + color: #ffffff; +} + +.navbar-inverse .divider-vertical { + border-right-color: #222222; + border-left-color: #111111; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .nav li.dropdown > a:hover .caret, +.navbar-inverse .nav li.dropdown > a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #999999; + border-bottom-color: #999999; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .navbar-search .search-query { + color: #ffffff; + background-color: #515151; + border-color: #111111; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; +} + +.navbar-inverse .navbar-search .search-query:-moz-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query:focus, +.navbar-inverse .navbar-search .search-query.focused { + padding: 5px 15px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + outline: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +} + +.navbar-inverse .btn-navbar { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e0e0e; + *background-color: #040404; + background-image: -moz-linear-gradient(top, #151515, #040404); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); + background-image: -webkit-linear-gradient(top, #151515, #040404); + background-image: -o-linear-gradient(top, #151515, #040404); + background-image: linear-gradient(to bottom, #151515, #040404); + background-repeat: repeat-x; + border-color: #040404 #040404 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.navbar-inverse .btn-navbar:hover, +.navbar-inverse .btn-navbar:focus, +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active, +.navbar-inverse .btn-navbar.disabled, +.navbar-inverse .btn-navbar[disabled] { + color: #ffffff; + background-color: #040404; + *background-color: #000000; +} + +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active { + background-color: #000000 \9; +} + +.breadcrumb { + padding: 8px 15px; + margin: 0 0 20px; + list-style: none; + background-color: #f5f5f5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.breadcrumb > li { + display: inline-block; + *display: inline; + text-shadow: 0 1px 0 #ffffff; + *zoom: 1; +} + +.breadcrumb > li > .divider { + padding: 0 5px; + color: #ccc; +} + +.breadcrumb > .active { + color: #999999; +} + +.pagination { + margin: 20px 0; +} + +.pagination ul { + display: inline-block; + *display: inline; + margin-bottom: 0; + margin-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + *zoom: 1; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.pagination ul > li { + display: inline; +} + +.pagination ul > li > a, +.pagination ul > li > span { + float: left; + padding: 4px 12px; + line-height: 20px; + text-decoration: none; + background-color: #ffffff; + border: 1px solid #dddddd; + border-left-width: 0; +} + +.pagination ul > li > a:hover, +.pagination ul > li > a:focus, +.pagination ul > .active > a, +.pagination ul > .active > span { + background-color: #f5f5f5; +} + +.pagination ul > .active > a, +.pagination ul > .active > span { + color: #999999; + cursor: default; +} + +.pagination ul > .disabled > span, +.pagination ul > .disabled > a, +.pagination ul > .disabled > a:hover, +.pagination ul > .disabled > a:focus { + color: #999999; + cursor: default; + background-color: transparent; +} + +.pagination ul > li:first-child > a, +.pagination ul > li:first-child > span { + border-left-width: 1px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.pagination ul > li:last-child > a, +.pagination ul > li:last-child > span { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.pagination-centered { + text-align: center; +} + +.pagination-right { + text-align: right; +} + +.pagination-large ul > li > a, +.pagination-large ul > li > span { + padding: 11px 19px; + font-size: 17.5px; +} + +.pagination-large ul > li:first-child > a, +.pagination-large ul > li:first-child > span { + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.pagination-large ul > li:last-child > a, +.pagination-large ul > li:last-child > span { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.pagination-mini ul > li:first-child > a, +.pagination-small ul > li:first-child > a, +.pagination-mini ul > li:first-child > span, +.pagination-small ul > li:first-child > span { + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-topleft: 3px; +} + +.pagination-mini ul > li:last-child > a, +.pagination-small ul > li:last-child > a, +.pagination-mini ul > li:last-child > span, +.pagination-small ul > li:last-child > span { + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-bottomright: 3px; +} + +.pagination-small ul > li > a, +.pagination-small ul > li > span { + padding: 2px 10px; + font-size: 11.9px; +} + +.pagination-mini ul > li > a, +.pagination-mini ul > li > span { + padding: 0 6px; + font-size: 10.5px; +} + +.pager { + margin: 20px 0; + text-align: center; + list-style: none; + *zoom: 1; +} + +.pager:before, +.pager:after { + display: table; + line-height: 0; + content: ""; +} + +.pager:after { + clear: both; +} + +.pager li { + display: inline; +} + +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #f5f5f5; +} + +.pager .next > a, +.pager .next > span { + float: right; +} + +.pager .previous > a, +.pager .previous > span { + float: left; +} + +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999999; + cursor: default; + background-color: #fff; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop, +.modal-backdrop.fade.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.modal { + position: fixed; + top: 10%; + left: 50%; + z-index: 1050; + width: 560px; + margin-left: -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +.modal.fade { + top: -25%; + -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; + -moz-transition: opacity 0.3s linear, top 0.3s ease-out; + -o-transition: opacity 0.3s linear, top 0.3s ease-out; + transition: opacity 0.3s linear, top 0.3s ease-out; +} + +.modal.fade.in { + top: 10%; +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} + +.modal-header .close { + margin-top: 2px; +} + +.modal-header h3 { + margin: 0; + line-height: 30px; +} + +.modal-body { + position: relative; + max-height: 400px; + padding: 15px; + overflow-y: auto; +} + +.modal-form { + margin-bottom: 0; +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + line-height: 0; + content: ""; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} + +.tooltip { + position: absolute; + z-index: 1030; + display: block; + font-size: 11px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible; +} + +.tooltip.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} + +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} + +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} + +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} + +.tooltip-inner { + max-width: 200px; + padding: 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-right-color: #000000; + border-width: 5px 5px 5px 0; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-left-color: #000000; + border-width: 5px 0 5px 5px; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.popover.top { + margin-top: -10px; +} + +.popover.right { + margin-left: 10px; +} + +.popover.bottom { + margin-top: 10px; +} + +.popover.left { + margin-left: -10px; +} + +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} + +.popover-title:empty { + display: none; +} + +.popover-content { + padding: 9px 14px; +} + +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.popover .arrow { + border-width: 11px; +} + +.popover .arrow:after { + border-width: 10px; + content: ""; +} + +.popover.top .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, 0.25); + border-bottom-width: 0; +} + +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + border-top-color: #ffffff; + border-bottom-width: 0; +} + +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, 0.25); + border-left-width: 0; +} + +.popover.right .arrow:after { + bottom: -10px; + left: 1px; + border-right-color: #ffffff; + border-left-width: 0; +} + +.popover.bottom .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, 0.25); + border-top-width: 0; +} + +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + border-bottom-color: #ffffff; + border-top-width: 0; +} + +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, 0.25); + border-right-width: 0; +} + +.popover.left .arrow:after { + right: 1px; + bottom: -10px; + border-left-color: #ffffff; + border-right-width: 0; +} + +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1; +} + +.thumbnails:before, +.thumbnails:after { + display: table; + line-height: 0; + content: ""; +} + +.thumbnails:after { + clear: both; +} + +.row-fluid .thumbnails { + margin-left: 0; +} + +.thumbnails > li { + float: left; + margin-bottom: 20px; + margin-left: 20px; +} + +.thumbnail { + display: block; + padding: 4px; + line-height: 20px; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +a.thumbnail:hover, +a.thumbnail:focus { + border-color: #0088cc; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} + +.thumbnail > img { + display: block; + max-width: 100%; + margin-right: auto; + margin-left: auto; +} + +.thumbnail .caption { + padding: 9px; + color: #555555; +} + +.media, +.media-body { + overflow: hidden; + *overflow: visible; + zoom: 1; +} + +.media, +.media .media { + margin-top: 15px; +} + +.media:first-child { + margin-top: 0; +} + +.media-object { + display: block; +} + +.media-heading { + margin: 0 0 5px; +} + +.media > .pull-left { + margin-right: 10px; +} + +.media > .pull-right { + margin-left: 10px; +} + +.media-list { + margin-left: 0; + list-style: none; +} + +.label, +.badge { + display: inline-block; + padding: 2px 4px; + font-size: 11.844px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + white-space: nowrap; + vertical-align: baseline; + background-color: #999999; +} + +.label { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.badge { + padding-right: 9px; + padding-left: 9px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px; +} + +.label:empty, +.badge:empty { + display: none; +} + +a.label:hover, +a.label:focus, +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.label-important, +.badge-important { + background-color: #b94a48; +} + +.label-important[href], +.badge-important[href] { + background-color: #953b39; +} + +.label-warning, +.badge-warning { + background-color: #f89406; +} + +.label-warning[href], +.badge-warning[href] { + background-color: #c67605; +} + +.label-success, +.badge-success { + background-color: #468847; +} + +.label-success[href], +.badge-success[href] { + background-color: #356635; +} + +.label-info, +.badge-info { + background-color: #3a87ad; +} + +.label-info[href], +.badge-info[href] { + background-color: #2d6987; +} + +.label-inverse, +.badge-inverse { + background-color: #333333; +} + +.label-inverse[href], +.badge-inverse[href] { + background-color: #1a1a1a; +} + +.btn .label, +.btn .badge { + position: relative; + top: -1px; +} + +.btn-mini .label, +.btn-mini .badge { + top: 0; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress .bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + color: #ffffff; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(to bottom, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width 0.6s ease; + -moz-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress .bar + .bar { + -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); +} + +.progress-striped .bar { + background-color: #149bdf; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px; +} + +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-danger .bar, +.progress .bar-danger { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); +} + +.progress-danger.progress-striped .bar, +.progress-striped .bar-danger { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-success .bar, +.progress .bar-success { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(to bottom, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); +} + +.progress-success.progress-striped .bar, +.progress-striped .bar-success { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-info .bar, +.progress .bar-info { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(to bottom, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); +} + +.progress-info.progress-striped .bar, +.progress-striped .bar-info { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-warning .bar, +.progress .bar-warning { + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); +} + +.progress-warning.progress-striped .bar, +.progress-striped .bar-warning { + background-color: #fbb450; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.accordion { + margin-bottom: 20px; +} + +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.accordion-heading { + border-bottom: 0; +} + +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px; +} + +.accordion-toggle { + cursor: pointer; +} + +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5; +} + +.carousel { + position: relative; + margin-bottom: 20px; + line-height: 1; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: 0.6s ease-in-out left; + -moz-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} + +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + line-height: 1; +} + +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} + +.carousel-inner > .active { + left: 0; +} + +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} + +.carousel-inner > .next { + left: 100%; +} + +.carousel-inner > .prev { + left: -100%; +} + +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} + +.carousel-inner > .active.left { + left: -100%; +} + +.carousel-inner > .active.right { + left: 100%; +} + +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #ffffff; + text-align: center; + background: #222222; + border: 3px solid #ffffff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: 0.5; + filter: alpha(opacity=50); +} + +.carousel-control.right { + right: 15px; + left: auto; +} + +.carousel-control:hover, +.carousel-control:focus { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} + +.carousel-indicators { + position: absolute; + top: 15px; + right: 15px; + z-index: 5; + margin: 0; + list-style: none; +} + +.carousel-indicators li { + display: block; + float: left; + width: 10px; + height: 10px; + margin-left: 5px; + text-indent: -999px; + background-color: #ccc; + background-color: rgba(255, 255, 255, 0.25); + border-radius: 5px; +} + +.carousel-indicators .active { + background-color: #fff; +} + +.carousel-caption { + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 15px; + background: #333333; + background: rgba(0, 0, 0, 0.75); +} + +.carousel-caption h4, +.carousel-caption p { + line-height: 20px; + color: #ffffff; +} + +.carousel-caption h4 { + margin: 0 0 5px; +} + +.carousel-caption p { + margin-bottom: 0; +} + +.hero-unit { + padding: 60px; + margin-bottom: 30px; + font-size: 18px; + font-weight: 200; + line-height: 30px; + color: inherit; + background-color: #eeeeee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; + color: inherit; +} + +.hero-unit li { + line-height: 30px; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.hide { + display: none; +} + +.show { + display: block; +} + +.invisible { + visibility: hidden; +} + +.affix { + position: fixed; +} diff --git a/docs/_static/bootstrap-2.3.2/css/bootstrap.min.css b/docs/_static/bootstrap-2.3.2/css/bootstrap.min.css new file mode 100644 index 00000000..b6428e69 --- /dev/null +++ b/docs/_static/bootstrap-2.3.2/css/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover,a:focus{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover,a.muted:focus{color:#808080}.text-warning{color:#c09853}a.text-warning:hover,a.text-warning:focus{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover,a.text-error:focus{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} diff --git a/docs/_static/bootstrap-2.3.2/img/glyphicons-halflings-white.png b/docs/_static/bootstrap-2.3.2/img/glyphicons-halflings-white.png new file mode 100644 index 00000000..3bf6484a Binary files /dev/null and b/docs/_static/bootstrap-2.3.2/img/glyphicons-halflings-white.png differ diff --git a/docs/_static/bootstrap-2.3.2/img/glyphicons-halflings.png b/docs/_static/bootstrap-2.3.2/img/glyphicons-halflings.png new file mode 100644 index 00000000..a9969993 Binary files /dev/null and b/docs/_static/bootstrap-2.3.2/img/glyphicons-halflings.png differ diff --git a/docs/_static/bootstrap-2.3.2/js/bootstrap.js b/docs/_static/bootstrap-2.3.2/js/bootstrap.js new file mode 100644 index 00000000..638bb187 --- /dev/null +++ b/docs/_static/bootstrap-2.3.2/js/bootstrap.js @@ -0,0 +1,2287 @@ +/* =================================================== + * bootstrap-transition.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#transitions + * =================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) + * ======================================================= */ + + $(function () { + + $.support.transition = (function () { + + var transitionEnd = (function () { + + var el = document.createElement('bootstrap') + , transEndEventNames = { + 'WebkitTransition' : 'webkitTransitionEnd' + , 'MozTransition' : 'transitionend' + , 'OTransition' : 'oTransitionEnd otransitionend' + , 'transition' : 'transitionend' + } + , name + + for (name in transEndEventNames){ + if (el.style[name] !== undefined) { + return transEndEventNames[name] + } + } + + }()) + + return transitionEnd && { + end: transitionEnd + } + + })() + + }) + +}(window.$jqTheme || window.jQuery); +/* ========================================================== + * bootstrap-alert.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#alerts + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* ALERT CLASS DEFINITION + * ====================== */ + + var dismiss = '[data-dismiss="alert"]' + , Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.prototype.close = function (e) { + var $this = $(this) + , selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = $(selector) + + e && e.preventDefault() + + $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) + + $parent.trigger(e = $.Event('close')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + $parent + .trigger('closed') + .remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent.on($.support.transition.end, removeElement) : + removeElement() + } + + + /* ALERT PLUGIN DEFINITION + * ======================= */ + + var old = $.fn.alert + + $.fn.alert = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('alert') + if (!data) $this.data('alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.alert.Constructor = Alert + + + /* ALERT NO CONFLICT + * ================= */ + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + /* ALERT DATA-API + * ============== */ + + $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) + +}(window.$jqTheme || window.jQuery); +/* ============================================================ + * bootstrap-button.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#buttons + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* BUTTON PUBLIC CLASS DEFINITION + * ============================== */ + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.button.defaults, options) + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + , $el = this.$element + , data = $el.data() + , val = $el.is('input') ? 'val' : 'html' + + state = state + 'Text' + data.resetText || $el.data('resetText', $el[val]()) + + $el[val](data[state] || this.options[state]) + + // push to event loop to allow forms to submit + setTimeout(function () { + state == 'loadingText' ? + $el.addClass(d).attr(d, d) : + $el.removeClass(d).removeAttr(d) + }, 0) + } + + Button.prototype.toggle = function () { + var $parent = this.$element.closest('[data-toggle="buttons-radio"]') + + $parent && $parent + .find('.active') + .removeClass('active') + + this.$element.toggleClass('active') + } + + + /* BUTTON PLUGIN DEFINITION + * ======================== */ + + var old = $.fn.button + + $.fn.button = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('button') + , options = typeof option == 'object' && option + if (!data) $this.data('button', (data = new Button(this, options))) + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + $.fn.button.defaults = { + loadingText: 'loading...' + } + + $.fn.button.Constructor = Button + + + /* BUTTON NO CONFLICT + * ================== */ + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + /* BUTTON DATA-API + * =============== */ + + $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + }) + +}(window.$jqTheme || window.jQuery); +/* ========================================================== + * bootstrap-carousel.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#carousel + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CAROUSEL CLASS DEFINITION + * ========================= */ + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.options.pause == 'hover' && this.$element + .on('mouseenter', $.proxy(this.pause, this)) + .on('mouseleave', $.proxy(this.cycle, this)) + } + + Carousel.prototype = { + + cycle: function (e) { + if (!e) this.paused = false + if (this.interval) clearInterval(this.interval); + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + return this + } + + , getActiveIndex: function () { + this.$active = this.$element.find('.item.active') + this.$items = this.$active.parent().children() + return this.$items.index(this.$active) + } + + , to: function (pos) { + var activeIndex = this.getActiveIndex() + , that = this + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) { + return this.$element.one('slid', function () { + that.to(pos) + }) + } + + if (activeIndex == pos) { + return this.pause().cycle() + } + + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + } + + , pause: function (e) { + if (!e) this.paused = true + if (this.$element.find('.next, .prev').length && $.support.transition.end) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + clearInterval(this.interval) + this.interval = null + return this + } + + , next: function () { + if (this.sliding) return + return this.slide('next') + } + + , prev: function () { + if (this.sliding) return + return this.slide('prev') + } + + , slide: function (type, next) { + var $active = this.$element.find('.item.active') + , $next = next || $active[type]() + , isCycling = this.interval + , direction = type == 'next' ? 'left' : 'right' + , fallback = type == 'next' ? 'first' : 'last' + , that = this + , e + + this.sliding = true + + isCycling && this.pause() + + $next = $next.length ? $next : this.$element.find('.item')[fallback]() + + e = $.Event('slide', { + relatedTarget: $next[0] + , direction: direction + }) + + if ($next.hasClass('active')) return + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } + + if ($.support.transition && this.$element.hasClass('slide')) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + this.$element.one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { that.$element.trigger('slid') }, 0) + }) + } else { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid') + } + + isCycling && this.cycle() + + return this + } + + } + + + /* CAROUSEL PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.carousel + + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('carousel') + , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) + , action = typeof option == 'string' ? option : options.slide + if (!data) $this.data('carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + $.fn.carousel.defaults = { + interval: 5000 + , pause: 'hover' + } + + $.fn.carousel.Constructor = Carousel + + + /* CAROUSEL NO CONFLICT + * ==================== */ + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + /* CAROUSEL DATA-API + * ================= */ + + $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var $this = $(this), href + , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + , options = $.extend({}, $target.data(), $this.data()) + , slideIndex + + $target.carousel(options) + + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('carousel').pause().to(slideIndex).cycle() + } + + e.preventDefault() + }) + +}(window.$jqTheme || window.jQuery); +/* ============================================================= + * bootstrap-collapse.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#collapse + * ============================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* COLLAPSE PUBLIC CLASS DEFINITION + * ================================ */ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.collapse.defaults, options) + + if (this.options.parent) { + this.$parent = $(this.options.parent) + } + + this.options.toggle && this.toggle() + } + + Collapse.prototype = { + + constructor: Collapse + + , dimension: function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + , show: function () { + var dimension + , scroll + , actives + , hasData + + if (this.transitioning || this.$element.hasClass('in')) return + + dimension = this.dimension() + scroll = $.camelCase(['scroll', dimension].join('-')) + actives = this.$parent && this.$parent.find('> .accordion-group > .in') + + if (actives && actives.length) { + hasData = actives.data('collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('collapse', null) + } + + this.$element[dimension](0) + this.transition('addClass', $.Event('show'), 'shown') + $.support.transition && this.$element[dimension](this.$element[0][scroll]) + } + + , hide: function () { + var dimension + if (this.transitioning || !this.$element.hasClass('in')) return + dimension = this.dimension() + this.reset(this.$element[dimension]()) + this.transition('removeClass', $.Event('hide'), 'hidden') + this.$element[dimension](0) + } + + , reset: function (size) { + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + [dimension](size || 'auto') + [0].offsetWidth + + this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') + + return this + } + + , transition: function (method, startEvent, completeEvent) { + var that = this + , complete = function () { + if (startEvent.type == 'show') that.reset() + that.transitioning = 0 + that.$element.trigger(completeEvent) + } + + this.$element.trigger(startEvent) + + if (startEvent.isDefaultPrevented()) return + + this.transitioning = 1 + + this.$element[method]('in') + + $.support.transition && this.$element.hasClass('collapse') ? + this.$element.one($.support.transition.end, complete) : + complete() + } + + , toggle: function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + } + + + /* COLLAPSE PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.collapse + + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('collapse') + , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.defaults = { + toggle: true + } + + $.fn.collapse.Constructor = Collapse + + + /* COLLAPSE NO CONFLICT + * ==================== */ + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + /* COLLAPSE DATA-API + * ================= */ + + $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + , target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + , option = $(target).data('collapse') ? 'toggle' : $this.data() + $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + $(target).collapse(option) + }) + +}(window.$jqTheme || window.jQuery); +/* ============================================================ + * bootstrap-dropdown.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#dropdowns + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* DROPDOWN CLASS DEFINITION + * ========================= */ + + var toggle = '[data-toggle=dropdown]' + , Dropdown = function (element) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } + + Dropdown.prototype = { + + constructor: Dropdown + + , toggle: function (e) { + var $this = $(this) + , $parent + , isActive + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement) { + // if mobile we we use a backdrop because click events don't delegate + $('