https://github.com/catalystneuro/ndx-ophys-devices

This is an NWB extension for storing metadata of devices used in optical experimental setup (microscopy, fiber photometry, optogenetic stimulation etc.)

https://github.com/catalystneuro/ndx-ophys-devices

Science Score: 26.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Academic email domains
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (3.6%) to scientific vocabulary
Last synced: 6 months ago · JSON representation

Repository

This is an NWB extension for storing metadata of devices used in optical experimental setup (microscopy, fiber photometry, optogenetic stimulation etc.)

Basic Info
  • Host: GitHub
  • Owner: catalystneuro
  • License: bsd-3-clause
  • Language: Python
  • Default Branch: main
  • Size: 81.1 KB
Statistics
  • Stars: 1
  • Watchers: 1
  • Forks: 0
  • Open Issues: 0
  • Releases: 0
Created almost 2 years ago · Last pushed 8 months ago
Metadata Files
Readme Changelog License

README.md

ndx-ophys-devices Extension for NWB

This is an NWB extension for storing metadata of devices used in optical experimental setup (microscopy, fiber photometry, optogenetic stimulation etc.)

This extension consists of neurodata types in the following categories:

Container Classes: - ViralVector extends NWBContainer to hold metadata on viral vectors used for gene delivery. - ViralVectorInjection extends NWBContainer to hold metadata on viral vector injection procedures. - Indicator extends NWBContainer to hold metadata on the fluorescent indicator. - Effector extends NWBContainer to hold metadata on the effector/opsin. - LensPositioning extends NWBContainer to hold metadata on the positioning of a lens relative to the brain. - FiberInsertion extends NWBContainer to hold metadata on the insertion of a fiber into the brain.

Model Classes: - DeviceModel extends NWBContainer to hold metadata on device models. - OpticalFiberModel extends DeviceModel to hold metadata on the optical fiber model. - ExcitationSourceModel extends DeviceModel to hold metadata on the excitation source model. - PhotodetectorModel extends DeviceModel to hold metadata on the photodetector model. - DichroicMirrorModel extends DeviceModel to hold metadata on the dichroic mirror model. - OpticalFilterModel extends DeviceModel to hold metadata on a general optical filter model. - BandOpticalFilterModel extends OpticalFilterModel to hold metadata on any bandpass or bandstop optical filter models. - EdgeOpticalFilterModel extends OpticalFilterModel to hold metadata on any edge optical filter models. - OpticalLensModel extends DeviceModel to hold metadata on the optical lens model.

Device Instance Classes: - DeviceInstance extends Device to hold metadata on device instances. - OpticalFiber extends DeviceInstance to hold metadata on optical fiber instances. - ExcitationSource extends DeviceInstance to hold metadata on excitation source instances. - PulsedExcitationSource extends ExcitationSource to hold metadata on pulsed excitation source instances. - Photodetector extends DeviceInstance to hold metadata on photodetector instances. - DichroicMirror extends DeviceInstance to hold metadata on dichroic mirror instances. - OpticalFilter extends DeviceInstance to hold metadata on general optical filter instances. - BandOpticalFilter extends OpticalFilter to hold metadata on bandpass or bandstop optical filter instances. - EdgeOpticalFilter extends OpticalFilter to hold metadata on edge optical filter instances. - OpticalLens extends DeviceInstance to hold metadata on optical lens instances.

Note that the container classes cannot be directly added to the NWB file, but instead require extending LabMetaData to contain one or more of these container classes in a separate extension. For example, see ndx-optogenetics.

Installation

To install the latest stable release through PyPI, bash pip install ndx-ophys-devices

Usage

```python import datetime import numpy as np from pynwb import NWBFile from ndxophysdevices import ( # Container classes ViralVector, ViralVectorInjection, Indicator, Effector, LensPositioning, FiberInsertion,

# Model classes
OpticalFiberModel,
ExcitationSourceModel,
PhotodetectorModel,
DichroicMirrorModel,
OpticalFilterModel,
BandOpticalFilterModel,
EdgeOpticalFilterModel,
OpticalLensModel,

# Device instance classes
OpticalFiber,
ExcitationSource,
PulsedExcitationSource,
Photodetector,
DichroicMirror,
OpticalFilter,
BandOpticalFilter,
EdgeOpticalFilter,
OpticalLens,

)

nwbfile = NWBFile( sessiondescription='sessiondescription', identifier='identifier', sessionstarttime=datetime.datetime.now(datetime.timezone.utc) )

Create container objects

viralvector = ViralVector( name="viralvector", description="AAV viral vector for optogenetic stimulation", constructname="AAV-EF1a-DIO-hChR2(H134R)-EYFP", manufacturer="Vector Manufacturer", titerinvgper_ml=1.0e12, )

viralvectorinjection = ViralVectorInjection( name="viralvectorinjection", description="Viral vector injection for optogenetic stimulation", location="Hippocampus", hemisphere="right", reference="Bregma at the cortical surface", apinmm=2.0, mlinmm=1.5, dvinmm=-3.0, pitchindeg=0.0, yawindeg=0.0, rollindeg=0.0, stereotacticrotationindeg=0.0, stereotactictiltindeg=0.0, volumeinuL=0.45, injectiondate="1970-01-01T00:00:00+00:00", viralvector=viral_vector, )

indicator = Indicator( name="indicator", description="Green indicator", label="GCamp6f", viralvectorinjection=viralvectorinjection, )

effector = Effector( name="effector", description="Excitatory opsin", label="hChR2", viralvectorinjection=viralvectorinjection, )

fiberinsertion = FiberInsertion( name="fiberinsertion", depthinmm=3.5, insertionpositionapinmm=2.0, insertionpositionmlinmm=1.5, insertionpositiondvinmm=3.0, positionreference="bregma", hemisphere="right", insertionanglepitchin_deg=10.0, )

lenspositioning = LensPositioning( name="lenspositioning", positioningtype="surface", depthinmm=0.0, targetpositionapinmm=1.5, targetpositionmlinmm=2.0, targetpositiondvinmm=0.0, workingdistanceinmm=2.0, positionreference="bregma", hemisphere="left", opticalaxisanglepitchindeg=0.0, )

Create model objects

opticalfibermodel = OpticalFiberModel( name="opticalfibermodel", manufacturer="Fiber Manufacturer", modelnumber="OF-123", description="Optical fiber model for optogenetics", numericalaperture=0.2, corediameterinum=400.0, activelengthinmm=2.0, ferrulename="cFCF - ∅2.5mm Ceramic Ferrule", ferrulemodel="SM-SC-CF-10-FM", ferrulediameterinmm=2.5, ) nwbfile.adddevice(opticalfibermodel)

opticallensmodel = OpticalLensModel( name="opticallensmodel", manufacturer="Lens Manufacturer", modelnumber="OL-123", description="Optical lens model for imaging", numericalaperture=0.39, magnification=40.0, ) nwbfile.adddevice(opticallens_model)

excitationsourcemodel = ExcitationSourceModel( name="excitationsourcemodel", manufacturer="Laser Manufacturer", modelnumber="ES-123", description="Excitation source model for green indicator", sourcetype="laser", excitationmode="one-photon", wavelengthrangeinnm=[400.0, 800.0], ) nwbfile.adddevice(excitationsource_model)

photodetectormodel = PhotodetectorModel( name="photodetectormodel", manufacturer="Detector Manufacturer", modelnumber="PD-123", description="Photodetector model for green emission", detectortype="PMT", wavelengthrangeinnm=[400.0, 800.0], gain=100.0, gainunit="A/W", ) nwbfile.adddevice(photodetectormodel)

dichroicmirrormodel = DichroicMirrorModel( name="dichroicmirrormodel", manufacturer="Mirror Manufacturer", modelnumber="DM-123", description="Dichroic mirror model for green indicator", cutonwavelengthinnm=470.0, cutoffwavelengthinnm=500.0, reflectionbandinnm=[460.0, 480.0], transmissionbandinnm=[490.0, 520.0], angleofincidenceindegrees=45.0, ) nwbfile.adddevice(dichroicmirrormodel)

bandopticalfiltermodel = BandOpticalFilterModel( name="bandopticalfiltermodel", manufacturer="Filter Manufacturer", modelnumber="BOF-123", description="Band optical filter model for green indicator", filtertype="Bandpass", centerwavelengthinnm=480.0, bandwidthinnm=30.0, # 480±15nm ) nwbfile.adddevice(bandopticalfilter_model)

edgeopticalfiltermodel = EdgeOpticalFilterModel( name="edgeopticalfiltermodel", manufacturer="Filter Manufacturer", modelnumber="EOF-123", description="Edge optical filter model for green indicator", filtertype="Longpass", cutwavelengthinnm=585.0, slopeinpercentcutwavelength=1.0, slopestartingtransmissioninpercent=10.0, slopeendingtransmissioninpercent=80.0, ) nwbfile.adddevice(edgeopticalfilter_model)

Create device instances

opticalfiber = OpticalFiber( name="opticalfiber", description="Optical fiber for optogenetics", serialnumber="OF-SN-123456", model=opticalfibermodel, fiberinsertion=fiber_insertion, )

opticallens = OpticalLens( name="opticallens", description="Optical lens for imaging", serialnumber="OL-SN-123456", model=opticallensmodel, lenspositioning=lens_positioning, )

excitationsource = ExcitationSource( name="excitationsource", description="Excitation source for green indicator", serialnumber="ES-SN-123456", model=excitationsourcemodel, powerinW=0.7, intensityinWperm2=0.005, exposuretimeins=2.51e-13, )

pulsedexcitationsource = PulsedExcitationSource( name="pulsedexcitationsource", description="Pulsed excitation source for red indicator", serialnumber="PES-SN-123456", model=excitationsourcemodel, peakpowerinW=0.7, peakpulseenergyinJ=0.7, intensityinWperm2=0.005, exposuretimeins=2.51e-13, pulserateinHz=2.0e6, )

photodetector = Photodetector( name="photodetector", description="Photodetector for green emission", serialnumber="PD-SN-123456", model=photodetectormodel, )

dichroicmirror = DichroicMirror( name="dichroicmirror", description="Dichroic mirror for green indicator", serialnumber="DM-SN-123456", model=dichroicmirror_model, )

bandopticalfilter = BandOpticalFilter( name="bandopticalfilter", description="Band optical filter for green indicator", serialnumber="BOF-SN-123456", model=bandopticalfiltermodel, )

edgeopticalfilter = EdgeOpticalFilter( name="edgeopticalfilter", description="Edge optical filter for green indicator", serialnumber="EOF-SN-123456", model=edgeopticalfiltermodel, )

Add objects to the NWBFile

nwbfile.adddevice(opticalfiber) nwbfile.adddevice(opticallens) nwbfile.adddevice(excitationsource) nwbfile.adddevice(pulsedexcitationsource) nwbfile.adddevice(photodetector) nwbfile.adddevice(dichroicmirror) nwbfile.adddevice(bandopticalfilter) nwbfile.adddevice(edgeopticalfilter)

```

Entity relationship diagrams

Molecular Tools

mermaid %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#ffffff', 'primaryBorderColor': '#144E73', 'lineColor': '#D96F32'}}}%% classDiagram direction BT class ViralVector { <<NWBContainer>> -------------------------------------- attributes -------------------------------------- **construct_name** : text titer_in_vg_per_ml : numeric, optional manufacturer : text, optional description : text, optional } class ViralVectorInjection { <<NWBContainer>> -------------------------------------- attributes -------------------------------------- location : text, optional hemisphere : text, optional ap_in_mm : numeric, optional ml_in_mm : numeric, optional dv_in_mm : numeric, optional pitch_in_deg : numeric, optional yaw_in_deg : numeric, optional roll_in_deg : numeric, optional stereotactic_rotation_in_deg : numeric, optional stereotactic_tilt_in_deg : numeric, optional volume_in_uL : numeric, optional injection_date : text, optional **viral_vector** : ViralVector } class Indicator { <<NWBContainer>> -------------------------------------- attributes -------------------------------------- **label** : text description : text, optional manufacturer : text, optional injection_brain_region : text, optional injection_coordinates_in_mm : numeric, length 3, optional **viral_vector_injection** : ViralVectorInjection } class Effector { <<NWBContainer>> -------------------------------------- attributes -------------------------------------- **label** : text description : text, optional manufacturer : text, optional injection_brain_region : text, optional injection_coordinates_in_mm : numeric, length 3, optional **viral_vector_injection** : ViralVectorInjection } Indicator --> ViralVectorInjection : links Effector --> ViralVectorInjection : links ViralVectorInjection --> ViralVector : links

Device Models and Instances

```mermaid %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#ffffff', "primaryBorderColor': '#144E73', 'lineColor': '#D96F32'}}}%% classDiagram direction TB

class DeviceModel{
    <<Device>>
    --------------------------------------
    attributes
    --------------------------------------
    manufacturer : text
    model_number : text, optional
}

class DeviceInstance{
    <<Device>>
    --------------------------------------
    attributes
    --------------------------------------
    serial_number : text, optional
    --------------------------------------
    links
    --------------------------------------
    model : DeviceModel, optional
}

class ExcitationSourceModel{
    <<DeviceModel>>
    --------------------------------------
    attributes
    --------------------------------------
    **source_type** : text
    **excitation_mode** : text
    wavelength_range_in_nm : numeric, optional
}

class ExcitationSource{
    <<DeviceInstance>>
    --------------------------------------
    attributes
    --------------------------------------
    power_in_W : numeric, optional
    intensity_in_W_per_m2 : numeric, optional
    exposure_time_in_s : numeric, optional
}

class PulsedExcitationSource{
    <<ExcitationSource>>
    --------------------------------------
    attributes
    --------------------------------------
    peak_power_in_W : numeric, optional
    peak_pulse_energy_in_J : numeric, optional
    pulse_rate_in_Hz : numeric, optional
}

class PhotodetectorModel{
    <<DeviceModel>>
    --------------------------------------
    attributes
    --------------------------------------
    **detector_type** : text
    wavelength_range_in_nm : numeric, optional
    gain : numeric, optional
    gain_unit : text, optional
}

class Photodetector{
    <<DeviceInstance>>
}

DeviceInstance o--> DeviceModel : links

DeviceModel <|-- ExcitationSourceModel : extends
DeviceInstance <|-- ExcitationSource : extends
ExcitationSource o--> ExcitationSourceModel : links
ExcitationSource <|-- PulsedExcitationSource : extends
PulsedExcitationSource o--> ExcitationSourceModel : links

DeviceModel <|-- PhotodetectorModel : extends
DeviceInstance <|-- Photodetector : extends
Photodetector o--> PhotodetectorModel : links

```

Optical Fiber and Optical Lens

```mermaid %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#ffffff', "primaryBorderColor': '#144E73', 'lineColor': '#D96F32'}}}%% classDiagram direction TB

class DeviceModel{
    <<Device>>
    --------------------------------------
    attributes
    --------------------------------------
    manufacturer : text
    model_number : text, optional
}

class DeviceInstance{
    <<Device>>
    --------------------------------------
    attributes
    --------------------------------------
    serial_number : text, optional
    --------------------------------------
    links
    --------------------------------------
    model : DeviceModel, optional
}

class FiberInsertion{
    <<NWBContainer>>
    --------------------------------------
    attributes
    --------------------------------------
    insertion_position_ap_in_mm : numeric, optional
    insertion_position_ml_in_mm : numeric, optional
    insertion_position_dv_in_mm : numeric, optional
    depth_in_mm : numeric, optional
    position_reference : text, optional
    hemisphere : text, optional
    insertion_angle_yaw_in_deg : numeric, optional
    insertion_angle_pitch_in_deg : numeric, optional
    insertion_angle_roll_in_deg : numeric, optional
}

 class OpticalFiberModel{
    <<DeviceModel>>
    --------------------------------------
    attributes
    --------------------------------------
    **numerical_aperture** : numeric
    core_diameter_in_um : numeric, optional
    active_length_in_mm : numeric, optional
    ferrule_name : text, optional
    ferrule_model : text, optional
    ferrule_diameter_in_mm : numeric, optional 
}

class OpticalFiber{
    <<DeviceInstance>>
    --------------------------------------
    attributes
    --------------------------------------
    **fiber_insertion** : FiberInsertion
}

class LensPositioning{
    <<NWBContainer>>
    --------------------------------------
    attributes
    --------------------------------------
    **positioning_type** : text
    target_position_ap_in_mm : numeric, optional
    target_position_ml_in_mm : numeric, optional
    target_position_dv_in_mm : numeric, optional
    depth_in_mm : numeric
    working_distance_in_mm : numeric, optional
    position_reference : text, optional
    hemisphere : text, optional
    optical_axis_angle_yaw_in_deg : numeric, optional
    optical_axis_angle_pitch_in_deg : numeric, optional
    optical_axis_angle_roll_in_deg : numeric, optional
}

class OpticalLensModel{
    <<DeviceModel>>
    --------------------------------------
    attributes
    --------------------------------------
    **numerical_aperture** : numeric
    magnification : numeric, optional
}

class OpticalLens{
    <<DeviceInstance>>
    --------------------------------------
    attributes
    --------------------------------------
    **lens_positioning** : LensPositioning
}

DeviceModel <|-- OpticalFiberModel : extends
DeviceInstance <|-- OpticalFiber : extends
OpticalFiber *-- FiberInsertion : contains
OpticalFiber o--> OpticalFiberModel : links

DeviceModel <|-- OpticalLensModel : extends
DeviceInstance <|-- OpticalLens : extends
OpticalLens *-- LensPositioning : contains
OpticalLens o--> OpticalLensModel : links

```

Optical Filters and Dichroic Mirrors

```mermaid %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#ffffff', "primaryBorderColor': '#144E73', 'lineColor': '#D96F32'}}}%% classDiagram direction TB

class DeviceModel{
    <<Device>>
    --------------------------------------
    attributes
    --------------------------------------
    manufacturer : text, optional
    model_number : text, optional
}

class DeviceInstance{
    <<Device>>
    --------------------------------------
    attributes
    --------------------------------------
    serial_number : text, optional
    --------------------------------------
    links
    --------------------------------------
    model : DeviceModel, optional
}

class OpticalFilterModel{
    <<DeviceModel>>
    --------------------------------------
    attributes
    --------------------------------------
    **filter_type** : text
}

class OpticalFilter{
    <<DeviceInstance>>
}

class BandOpticalFilterModel{
    <<OpticalFilterModel>>
    --------------------------------------
    attributes
    --------------------------------------
    **center_wavelength_in_nm** : numeric
    **bandwidth_in_nm** : numeric
}

class BandOpticalFilter{
    <<OpticalFilter>>
}

class EdgeOpticalFilterModel{
    <<OpticalFilterModel>>
    --------------------------------------
    attributes
    --------------------------------------
    **cut_wavelength_in_nm** : numeric
    slope_in_percent_cut_wavelength : numeric, optional
    slope_starting_transmission_in_percent : numeric, optional
    slope_ending_transmission_in_percent : numeric, optional
}

class EdgeOpticalFilter{
    <<OpticalFilter>>
}

class DichroicMirrorModel{
    <<DeviceModel>>
    --------------------------------------
    attributes
    --------------------------------------
    cut_on_wavelength_in_nm : numeric, optional
    cut_off_wavelength_in_nm : numeric, optional
    reflection_band_in_nm : numeric, optional
    transmission_band_in_nm : numeric, optional
    angle_of_incidence_in_degrees : numeric, optional
}

class DichroicMirror{
    <<DeviceInstance>>
}


DeviceModel <|-- OpticalFilterModel : extends
DeviceInstance <|-- OpticalFilter : extends
OpticalFilter o--> OpticalFilterModel : links

OpticalFilterModel <|-- BandOpticalFilterModel : extends
OpticalFilter <|-- BandOpticalFilter : extends
BandOpticalFilter o--> BandOpticalFilterModel : links

OpticalFilterModel <|-- EdgeOpticalFilterModel : extends
OpticalFilter <|-- EdgeOpticalFilter : extends
EdgeOpticalFilter o--> EdgeOpticalFilterModel : links

DeviceModel <|-- DichroicMirrorModel : extends
DeviceInstance <|-- DichroicMirror : extends
DichroicMirror o--> DichroicMirrorModel : links

```

Contributing

To help ensure a smooth Pull Request (PR) process, please always begin by raising an issue on the main repository so we can openly discuss any problems/additions before taking action.

The main branch of ndx-ophys-devices is protected; you cannot push to it directly. You must upload your changes by pushing a new branch, then submit your changes to the main branch via a Pull Request. This allows us to conduct automated testing of your contribution, and gives us a space for developers to discuss the contribution and request changes. If you decide to tackle an issue, please make yourself an assignee on the issue to communicate this to the team. Don’t worry - this does not commit you to solving this issue. It just lets others know who they should talk to about it.

From your local copy directory, use the following commands.

If you have not already, you will need to clone the repo: bash $ git clone https://github.com/catalystneuro/ndx-ophys-devices

First create a new branch to work on bash $ git checkout -b <new_branch>

Make your changes. Add new devices related to optical experiment setup or add more attributes on the existing ones. To speed up the process, you can write mock function (see _mock.py) that would be used to test the new neurodata type

We will automatically run tests to ensure that your contributions didn’t break anything and that they follow our style guide. You can speed up the testing cycle by running these tests locally on your own computer by calling pytest from the top-level directory. Push your feature branch to origin (i.e. GitHub)

bash $ git push origin <new_branch>

Once you have tested and finalized your changes, create a pull request (PR) targeting dev as the base branch: Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. TIP: Writing e.g. “fix #613” will automatically close issue #613 when this PR is merged. Before submitting, please ensure that the code follows the standard coding style of the respective repository. If you would like help with your contribution, or would like to communicate contributions that are not ready to merge, submit a PR where the title begins with “[WIP].”

Update the CHANGELOG.md regularly to document changes to the extension.

NOTE: Contributed branches will be removed by the development team after the merge is complete and should, hence, not be used after the pull request is complete.


This extension was created using ndx-template.

Owner

  • Name: CatalystNeuro
  • Login: catalystneuro
  • Kind: organization
  • Email: hello@catalystneuro.com

GitHub Events

Total
  • Issues event: 11
  • Watch event: 1
  • Delete event: 7
  • Issue comment event: 9
  • Push event: 39
  • Pull request review comment event: 4
  • Pull request review event: 5
  • Pull request event: 11
  • Fork event: 1
  • Create event: 9
Last Year
  • Issues event: 11
  • Watch event: 1
  • Delete event: 7
  • Issue comment event: 9
  • Push event: 39
  • Pull request review comment event: 4
  • Pull request review event: 5
  • Pull request event: 11
  • Fork event: 1
  • Create event: 9

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 7
  • Total pull requests: 8
  • Average time to close issues: 13 days
  • Average time to close pull requests: 6 days
  • Total issue authors: 2
  • Total pull request authors: 2
  • Average comments per issue: 0.29
  • Average comments per pull request: 0.25
  • Merged pull requests: 4
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 7
  • Pull requests: 8
  • Average time to close issues: 13 days
  • Average time to close pull requests: 6 days
  • Issue authors: 2
  • Pull request authors: 2
  • Average comments per issue: 0.29
  • Average comments per pull request: 0.25
  • Merged pull requests: 4
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • pauladkisson (5)
  • alessandratrapani (2)
Pull Request Authors
  • alessandratrapani (6)
  • pauladkisson (4)
Top Labels
Issue Labels
enhancement (1)
Pull Request Labels

Packages

  • Total packages: 1
  • Total downloads:
    • pypi 2,608 last-month
  • Total dependent packages: 0
  • Total dependent repositories: 0
  • Total versions: 3
  • Total maintainers: 2
pypi.org: ndx-ophys-devices

This is an NWB extension for storing metadata of devices used in optical experimental setup (microscopy, fiber photometry, optogenetic stimulation etc.)

  • Versions: 3
  • Dependent Packages: 0
  • Dependent Repositories: 0
  • Downloads: 2,608 Last month
Rankings
Dependent packages count: 9.9%
Average: 32.7%
Dependent repos count: 55.6%
Last synced: 7 months ago