{"id":20662430,"url":"https://github.com/ovinc/exlo","last_synced_at":"2025-07-25T06:33:43.589Z","repository":{"id":41423129,"uuid":"424329918","full_name":"ovinc/exlo","owner":"ovinc","description":"Log usage of equipment for scientific experiments with json files","archived":false,"fork":false,"pushed_at":"2024-01-24T19:24:19.000Z","size":40,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-17T04:03:01.368Z","etag":null,"topics":["equipment","logging","projects","scientific","users"],"latest_commit_sha":null,"homepage":"","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/ovinc.png","metadata":{"files":{"readme":"README.md","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}},"created_at":"2021-11-03T18:01:45.000Z","updated_at":"2021-12-15T18:10:00.000Z","dependencies_parsed_at":"2025-01-17T12:26:59.178Z","dependency_job_id":"f341573f-545d-40f1-b4e2-7c168b6d229b","html_url":"https://github.com/ovinc/exlo","commit_stats":{"total_commits":16,"total_committers":1,"mean_commits":16.0,"dds":0.0,"last_synced_commit":"b5ea821fd0698e55b0554b7c34abbc44bbb0668e"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ovinc/exlo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ovinc%2Fexlo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ovinc%2Fexlo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ovinc%2Fexlo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ovinc%2Fexlo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ovinc","download_url":"https://codeload.github.com/ovinc/exlo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ovinc%2Fexlo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266966650,"owners_count":24013739,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-25T02:00:09.625Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["equipment","logging","projects","scientific","users"],"created_at":"2024-11-16T19:14:07.456Z","updated_at":"2025-07-25T06:33:43.522Z","avatar_url":"https://github.com/ovinc.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"About\n=====\n\nLog usage of equipment for scientific experiments with json files.\n\nInstall\n-------\n\nBefore install, the separate config/data package `exlo_data` must be installed, see https://github.com/ovinc/exlo_data\n\nAfter this, install the `exlo` package with:\n\n```bash\ngit clone https://github.com/ovinc/exlo\ncd exlo\npip install -e .\n```\n\nQuick start\n===========\n\n## Configuration\n\nThe companion `exlo_data` module contains several `json` files that need to be filled before being able to use the logger :\n\n- `config.json` (misc. configuration),\n- `users.json` (list of users and their information),\n- `components.json` (list of individual pieces of equipment that constitute the *setups* below),\n- `setups.json` (list of setups and related info),\n- `projects.json` (list of projects the equipment can be used for).\n\n## Logging use of equipment\n\nOnce the configuration step is done, one can instantiate and use the `Logger` class to create and manage logs for the equipment:\n\n```python\nfrom exlo import Logger\nlogger = Logger()\n\n# Add log; any field not provided will use default values from config.json\n# The user, setup \u0026 project must match one of those in the config files\n# The date parser uses dateutil.parser and accepts a variety of date formats\n# By default the day is present day, and timezone is the local timezone.\n# In case of ambiguity in day/month order, day first is assumed.\nlogger.add(user='Martin', setup='Optic1', project='Dupont-ERC-2020',\n           start='9am', end='15:00', note='First test of the new laser')\n\n# Save this new log to the log list in the json file\nlogger.save()\n\n# See all logs as a list (opening the json file might be easier to read)\nlogger.logs\n\n# Update any of the field in the last log; save() must be called again.\nlogger.update(setup='Optic2')\nlogger.update(42, end='16:30')  # update not the last log but another one (#42)\nlogger.save()\n\n# Remove logs\nlogger.remove()    # remove last log\nlogger.remove(33)  # remove specific log\nlogger.save()\n```\n\nEach log is an object from the `Log` dataclass, which stores all fields as strings (`str`) except the log number as an `int`. For convenience, one can also access time-related information as datetime/timedelta objects:\n```python\nlog = logger.logs[42]  # extract 42th log\n\n# datetime.dateime objects\nlog.start_datetime\nlog.end_datetime\n\n# timedelta object\nlog.duration\n```\n\n## Export logs to Excel\n\nThe `Logger` class has a `to_excel()` method that exports the info on users, projects, components, setups and logs into an Excel file.\n\nThe logs are separated for each component, and separate sheets in the Excel file represent the log data corresponding to every component. If a setup contains several components, this means that a log with this setup will be duplicated in all sheets of the corresponding components.\n\nTo do the export, just `cd` into the directory where you want the file to be generated and:\n```python\nfrom exlo import Logger\nlogger = Logger()\nlogger.to_excel()\n```\nThis will generate a file `Logs.xlsx` in the current directory.\n\nExport of logs can also be filtered by date:\n```python\nlogger.to_excel(min_date='Jan 1, 2023', max_date='Dec. 31, 2024')\n```\n(note that if a log spans before and after the min/max dates, it will be included, i.e. only the end time of the log is considered for the min date, and only the start time of the log is considered for the max date).\n\nIt is also possible to specify a path for saving and/or change the filename:\n```python\nlogger.to_excel(savepath='D:/Data/Logs', filename='Log_Data.xlsx')\n```\n\n**NOTE:** If `to_excel` generates an error *AttributeError: 'Worksheet' object has no attribute 'write'*, it may be that `xslxwriter` is not installed. This can be fixed with `pip install xlsxwriter`.\n\n\n## Python objects representing users, projects, components, setups\n\nThe users, projects, components and setup are also represented by classes (`User`, `Project`, `Component`, `Setup`, respectively), which define their attributes automatically from the `.json` files:\n\n```python\nfrom exlo import User, Project, Component, Setup\n\nuser = User('Martin')\nuser.status\n\u003e\u003e\u003e Postdoc\n\nsetup = Setup('Optic1')\nsetup.components\n\u003e\u003e\u003e [\"Laser\", \"Microscope\"]\n```\n\nThe `Setup` class also has a method to check that the listed components are indeed described in the `components.json` file.\n```python\nsetup.check_components()\n```\nwhich raises a `UnknownComponent` exception.\n\n## Batch change of names of users, projects, components, setups\n\nIt's possible to change the name (identifier) of a user, project, component or setup everywhere in the system at once by using the `change_name_to()` methods of the corresponding classes. For example,\n```python\nfrom exlo import User, Project, Component, Setup\n\nUser('Cam').change_name_to('Camille')\nProject('Dupont-ERC-2020').change_name_to('ERC')\nComponent('Microscope').change_name_to('Stereoscope')\nSetup('Optic1').change_name_to('Optic1-Old')\n```\nThis will change the identifier names anywhere they need to be changed in the JSON files, including *logs.json* (and for components, in the *setups.json* file).\n\nIt is probably wise to restart the python console and re-import **exlo** after calling `change_name_to()`, because some variables in memory don't automatically re-load data from the JSON files.\n\n\nTesting\n=======\n\nWith `pytest`:\n```bash\npytest\n```\n\nMisc. info\n==========\n\nModule requirements\n-------------------\n\n### Config/data module\n\nThe logger config and data are managed in a separate package `exlo_data` (see *Install* section above).\n\n\n### Modules outside of standard library\n\n(installed automatically by pip if necessary)\n\n- python-dateutil\n- tzlocal \u003c 3.0 (typically, 2.1; after this, problems arise due to dropped pytz support)\n- importlib-metadata\n\n\n\nPython requirements\n-------------------\n\nPython : \u003e= 3.7 (dataclasses)\n\nAuthor\n------\n\nOlivier Vincent\n\n(ovinc.py@gmail.com)\n\nLicense\n-------\n\n3-Clause BSD (see *LICENSE* file).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fovinc%2Fexlo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fovinc%2Fexlo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fovinc%2Fexlo/lists"}