{"id":42912017,"url":"https://github.com/pvlib/solarfactors","last_synced_at":"2026-01-30T16:58:18.388Z","repository":{"id":152313318,"uuid":"606274886","full_name":"pvlib/solarfactors","owner":"pvlib","description":"A community-maintained implementation of the pvfactors bifacial irradiance model","archived":false,"fork":false,"pushed_at":"2026-01-15T22:33:51.000Z","size":3337,"stargazers_count":15,"open_issues_count":14,"forks_count":9,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-01-16T01:51:04.721Z","etag":null,"topics":["photovoltaic","pvlib","python","renewable-energy","renewables","solar-energy"],"latest_commit_sha":null,"homepage":"https://solarfactors.readthedocs.io/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pvlib.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-02-25T02:18:02.000Z","updated_at":"2026-01-15T22:32:35.000Z","dependencies_parsed_at":"2025-01-28T19:21:54.104Z","dependency_job_id":"d27a99df-6327-4b00-b701-896740b4bd3b","html_url":"https://github.com/pvlib/solarfactors","commit_stats":{"total_commits":108,"total_committers":7,"mean_commits":"15.428571428571429","dds":0.25,"last_synced_commit":"c8411bfd7199f029e75a7e15cd21219df873ff70"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/pvlib/solarfactors","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvlib%2Fsolarfactors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvlib%2Fsolarfactors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvlib%2Fsolarfactors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvlib%2Fsolarfactors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pvlib","download_url":"https://codeload.github.com/pvlib/solarfactors/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvlib%2Fsolarfactors/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28915942,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T16:37:38.804Z","status":"ssl_error","status_checked_at":"2026-01-30T16:37:37.878Z","response_time":66,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["photovoltaic","pvlib","python","renewable-energy","renewables","solar-energy"],"created_at":"2026-01-30T16:58:17.856Z","updated_at":"2026-01-30T16:58:18.368Z","avatar_url":"https://github.com/pvlib.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"pvlib/solarfactors: a fork of SunPower/pvfactors\n================================================\n\nThis repository is a fork of `SunPower/pvfactors \u003chttps://github.com/sunpower/pvfactors\u003e`_,\na 2-D view factor model for simulating front- and rear-side irradiance for\nbifacial PV systems.\n\nThis fork exists so that the pvfactors model can continue to be used with\n`pvlib python \u003chttps://github.com/pvlib/pvlib-python\u003e`_ even though the original\nrepository is no longer maintained.  The objective is to provide a working\ndependency for the existing pvfactors functionality currently in pvlib python.\n\nDocumentation for this fork can be found at `Read the Docs \u003chttps://solarfactors.readthedocs.io\u003e`_.\n\nThe project can be installed from PyPI using ``pip install solarfactors``.  Note\nthat the package is still used from python under the ``pvfactors`` name, i.e.\nwith ``from pvfactors.geometry import OrderedPVArray``.\n\n\npvfactors: irradiance modeling made simple\n==========================================\n\n|Logo|\n\n|GHActions|  |License|  |PyPI-Status|  |PyPI-Versions|\n\npvfactors is a tool used by PV professionals to calculate the\nirradiance incident on surfaces of a photovoltaic array. It relies on the use of\n2D geometries and view factors integrated mathematically into systems of\nequations to account for reflections between all of the surfaces.\n\npvfactors was originally ported from the SunPower developed 'vf_model' package, which was introduced at the IEEE PV Specialist Conference 44 2017 (see [#pvfactors_paper]_ and link_ to paper).\n\nThis fork, `pvlib/solarfactors \u003chttps://github.com/pvlib/solarfactors\u003e`_ is maintained by the pvlib project with contributions from the pvlib community.\n\n------------------------------------------\n\n.. contents:: Table of contents\n   :backlinks: top\n   :local:\n\n\nDocumentation\n-------------\n\nThe documentation of this fork can be found `here \u003chttps://solarfactors.readthedocs.io\u003e`_.\nIt includes a lot of tutorials_ that describe the different ways of using solarfactors.\n\n\nQuick Start\n-----------\n\nGiven some timeseries inputs:\n\n\n.. code:: python\n\n   # Import external libraries\n   from datetime import datetime\n   import pandas as pd\n\n   # Create input data\n   df_inputs = pd.DataFrame(\n       {'solar_zenith': [20., 50.],\n        'solar_azimuth': [110., 250.],\n        'surface_tilt': [10., 20.],\n        'surface_azimuth': [90., 270.],\n        'dni': [1000., 900.],\n        'dhi': [50., 100.],\n        'albedo': [0.2, 0.2]},\n       index=[datetime(2017, 8, 31, 11), datetime(2017, 8, 31, 15)])\n   df_inputs\n\n\n+---------------------+--------------+---------------+--------------+-----------------+--------+-------+--------+\n|                     | solar_zenith | solar_azimuth | surface_tilt | surface_azimuth | dni    | dhi   | albedo |\n+=====================+==============+===============+==============+=================+========+=======+========+\n| 2017-08-31 11:00:00 | 20.0         | 110.0         | 10.0         | 90.0            | 1000.0 | 50.0  | 0.2    |\n+---------------------+--------------+---------------+--------------+-----------------+--------+-------+--------+\n| 2017-08-31 15:00:00 | 50.0         | 250.0         | 20.0         | 270.0           | 900.0  | 100.0 | 0.2    |\n+---------------------+--------------+---------------+--------------+-----------------+--------+-------+--------+\n\n\nAnd some PV array parameters\n\n\n.. code:: python\n\n   pvarray_parameters = {\n       'n_pvrows': 3,            # number of pv rows\n       'pvrow_height': 1,        # height of pvrows (measured at center / torque tube)\n       'pvrow_width': 1,         # width of pvrows\n       'axis_azimuth': 0.,       # azimuth angle of rotation axis\n       'gcr': 0.4,               # ground coverage ratio\n   }\n\nThe user can quickly create a PV array with ``pvfactors``, and manipulate it with the engine\n\n\n.. code:: python\n\n   from pvfactors.geometry import OrderedPVArray\n   # Create PV array\n   pvarray = OrderedPVArray.init_from_dict(pvarray_parameters)\n\n\n\n.. code:: python\n\n   from pvfactors.engine import PVEngine\n   # Create engine\n   engine = PVEngine(pvarray)\n   # Fit engine to data\n   engine.fit(df_inputs.index, df_inputs.dni, df_inputs.dhi,\n              df_inputs.solar_zenith, df_inputs.solar_azimuth,\n              df_inputs.surface_tilt, df_inputs.surface_azimuth,\n              df_inputs.albedo)\n\nThe user can then plot the PV array geometry at any given time of the simulation:\n\n\n.. code:: python\n\n   # Plot pvarray shapely geometries\n   f, ax = plt.subplots(figsize=(10, 5))\n   pvarray.plot_at_idx(1, ax)\n   plt.show()\n\n.. image:: https://raw.githubusercontent.com/SunPower/pvfactors/master/docs/sphinx/_static/pvarray.png\n\n\nIt is then very easy to run simulations using the defined engine:\n\n\n.. code:: python\n\n    pvarray = engine.run_full_mode(fn_build_report=lambda pvarray: pvarray)\n\n\nAnd inspect the results thanks to the simple geometry API\n\n\n.. code:: python\n\n    print(\"Incident irradiance on front surface of middle pv row: {} W/m2\"\n          .format(pvarray.ts_pvrows[1].front.get_param_weighted('qinc')))\n    print(\"Reflected irradiance on back surface of left pv row: {} W/m2\"\n          .format(pvarray.ts_pvrows[0].back.get_param_weighted('reflection')))\n    print(\"Isotropic irradiance on back surface of right pv row: {} W/m2\"\n          .format(pvarray.ts_pvrows[2].back.get_param_weighted('isotropic')))\n\n\n.. parsed-literal::\n\n    Incident irradiance on front surface of middle pv row: [1034.968  886.377] W/m2\n    Reflected irradiance on back surface of left pv row: [112.139  86.404] W/m2\n    Isotropic irradiance on back surface of right pv row: [0.116 1.849] W/m2\n\n\nThe users can also create a \"report\" while running the simulations that will rely on the simple API shown above, and which will look like whatever the users want.\n\n.. code:: python\n\n    # Create a function that will build a report\n    def fn_report(pvarray): return {'total_incident_back': pvarray.ts_pvrows[1].back.get_param_weighted('qinc'),\n                                    'total_absorbed_back': pvarray.ts_pvrows[1].back.get_param_weighted('qabs')}\n\n    # Run full mode simulation\n    report = engine.run_full_mode(fn_build_report=fn_report)\n\n    # Print results (report is defined by report function passed by user)\n    df_report = pd.DataFrame(report, index=df_inputs.index)\n    df_report\n\n\n+---------------------+---------------------+---------------------+\n|                     | total_incident_back | total_absorbed_back |\n+=====================+=====================+=====================+\n| 2017-08-31 11:00:00 |          106.627832 |          103.428997 |\n+---------------------+---------------------+---------------------+\n| 2017-08-31 15:00:00 |          79.668878  |           77.278812 |\n+---------------------+---------------------+---------------------+\n\n\n\nInstallation\n------------\n\nsolarfactors is currently compatible and tested with Python 3.11 and Shapely 2.0.6, and is available in `PyPI \u003chttps://pypi.org/project/solarfactors/\u003e`_. The easiest way to install solarfactors is to use pip_ as follows:\n\n.. code:: sh\n\n    $ pip install solarfactors\n\nThe package wheel files are also available in the `release section`_ of the Github repository.\n\n\nRequirements\n------------\n\nRequirements are automatically installed when running ``pip install solarfactors``. Here is a list of important dependencies:\n\n* `numpy \u003chttps://pypi.python.org/pypi/numpy\u003e`_\n* `pvlib-python \u003chttps://pypi.python.org/pypi/pvlib\u003e`_\n* `shapely \u003chttps://pypi.python.org/pypi/Shapely\u003e`_ (version \u003e= 2.0)\n\n\nCiting pvfactors\n----------------\n\nIf you use solarfactors in a published work, cite the following paper:\n\n\n.. parsed-literal::\n\n   Anoma, M., Jacob, D., Bourne, B.C., Scholl, J.A., Riley, D.M. and Hansen, C.W., 2017. View Factor Model and Validation for Bifacial PV and Diffuse Shade on Single-Axis Trackers. In 44th IEEE Photovoltaic Specialist Conference.\n\n\nContributing\n------------\n\nContributions are needed in order to improve solarfactors.\n\nIf you wish to contribute, you can start by forking and cloning the repository, and then installing solarfactors using pip_ in the root folder of the package:\n\n.. code:: sh\n\n    $ pip install .\n\n\nTo install the package in editable mode, you can use:\n\n.. code:: sh\n\n    $ pip install -e .\n\n\nTesting\n+++++++\n\nInstall test dependencies using the ``test`` extra:\n\n.. code:: sh\n\n    $ pip install .[test]\n\nThen run the tests using:\n\n.. code:: sh\n\n    $ python -m pytest\n\nYou will need to close manually the plots that are generated during the tests, unless you define the ``CI`` environment variable, which will disable the tests that generate plots.\n\n\nReleasing\n+++++++++\n\nWhen releasing pvfactors, you will need to run a couple of build commands. First make sure to activate your virtual environment if any, then:\n\n- create a tag on the latest master branch commit using `git tag -a vX.X.X`, and write a tag message. You can then push that tag to Github so that it will appear there.\n- build the documentation by running `make build-docs`. When done running, you should be able to open `build/sphinx/html/index.html`, and confirm that the version displayed is the same as the one from the git tag. You can deploy by copying the content of of the `build/sphinx/html/` folder into the `gh-pages` branch of the repo (make sure to keep the `.nojekyll` file that's already present).\n- build the release files by running `make build-package`. When done running, you should be able to open `dist/` and see both a whl file and and tar file. Make sure that their names include the correct git tag you created. Please confirm that the whl file was built correctly by installing it locally and testing the newly released updates. You can deploy by 1) making a Github release from the tag you created and pushed, and including the files in `dist/` in the release. 2) The last step is to publish a release in PyPI, for which you can use twine and the command `twine upload dist/*`\n\n\n\n\nReferences\n----------\n\n.. [#pvfactors_paper] Anoma, M., Jacob, D., Bourne, B. C., Scholl, J. A., Riley, D. M., \u0026 Hansen, C. W. (2017). View Factor Model and Validation for Bifacial PV and Diffuse Shade on Single-Axis Trackers. In 44th IEEE Photovoltaic Specialist Conference.\n\n\n.. _link: https://pdfs.semanticscholar.org/ebb2/35e3c3796b158e1a3c45b40954e60d876ea9.pdf\n\n.. _tutorials: https://solarfactors.readthedocs.io/en/latest/tutorials/index.html\n\n.. _`full mode`: https://solarfactors.readthedocs.io/en/latest/theory/problem_formulation.html#full-simulations\n\n.. _`fast mode`: https://solarfactors.readthedocs.io/en/latest/theory/problem_formulation.html#fast-simulations\n\n.. _pip: https://pip.pypa.io/en/stable/\n\n.. _`release section`: https://github.com/pvlib/solarfactors/releases\n\n.. |Logo| image:: https://github.com/pvlib/solarfactors/blob/main/docs/sphinx/_static/logo_small.png?raw=true\n          :target: https://solarfactors.readthedocs.io/en/latest/index.html\n\n.. |GHActions| image:: https://github.com/pvlib/solarfactors/actions/workflows/test.yml/badge.svg?branch=main\n               :target: https://github.com/pvlib/solarfactors/actions/workflows/test.yml?query=branch%3Amain\n\n.. |License| image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg\n             :target: https://github.com/pvlib/solarfactors/blob/main/LICENSE\n\n.. |PyPI-Status| image:: https://img.shields.io/pypi/v/solarfactors.svg\n                 :target: https://pypi.org/project/solarfactors/\n\n.. |PyPI-Versions| image:: https://img.shields.io/pypi/pyversions/solarfactors.svg?logo=python\u0026logoColor=white\n                   :target: https://pypi.org/project/solarfactors/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpvlib%2Fsolarfactors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpvlib%2Fsolarfactors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpvlib%2Fsolarfactors/lists"}